]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-network/test-dhcp6-client.c
Merge pull request #30585 from YHNdnzj/isatty-handling
[thirdparty/systemd.git] / src / libsystemd-network / test-dhcp6-client.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
813e3a6f 2/***
810adae9 3 Copyright © 2014 Intel Corporation. All rights reserved.
813e3a6f
PF
4***/
5
07630cea 6#include <net/ethernet.h>
8f815e8b 7#include <net/if_arp.h>
813e3a6f
PF
8#include <stdbool.h>
9#include <stdio.h>
07630cea 10#include <sys/types.h>
2ea8857e 11#include <unistd.h>
813e3a6f 12
07630cea 13#include "sd-dhcp6-client.h"
813e3a6f 14#include "sd-event.h"
813e3a6f 15
8d71f2b3 16#include "dhcp-identifier.h"
f12ed3bf 17#include "dhcp6-internal.h"
859cca44 18#include "dhcp6-lease-internal.h"
07630cea 19#include "dhcp6-protocol.h"
3ffd4af2 20#include "fd-util.h"
07630cea 21#include "macro.h"
0a970718 22#include "memory-util.h"
07630cea 23#include "socket-util.h"
c43eea9f
BG
24#include "string-util.h"
25#include "strv.h"
6d7c4033 26#include "tests.h"
0a970718 27#include "time-util.h"
813e3a6f 28
1f280191
YW
29#define DHCP6_CLIENT_EVENT_TEST_ADVERTISED 77
30#define IA_ID_BYTES \
31 0x0e, 0xcf, 0xa3, 0x7d
32#define IA_NA_ADDRESS1_BYTES \
33 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x78, 0xee, 0x1c, 0xf3, 0x09, 0x3c, 0x55, 0xad
34#define IA_NA_ADDRESS2_BYTES \
35 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x78, 0xee, 0x1c, 0xf3, 0x09, 0x3c, 0x55, 0xae
36#define IA_PD_PREFIX1_BYTES \
37 0x2a, 0x02, 0x81, 0x0d, 0x98, 0x80, 0x37, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
38#define IA_PD_PREFIX2_BYTES \
39 0x2a, 0x02, 0x81, 0x0d, 0x98, 0x80, 0x37, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
40#define DNS1_BYTES \
41 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
42#define DNS2_BYTES \
43 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02
44#define SNTP1_BYTES \
45 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03
46#define SNTP2_BYTES \
47 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04
48#define NTP1_BYTES \
49 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05
50#define NTP2_BYTES \
51 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06
52#define CLIENT_ID_BYTES \
53 0x00, 0x02, 0x00, 0x00, 0xab, 0x11, 0x61, 0x77, 0x40, 0xde, 0x13, 0x42, 0xc3, 0xa2
54#define SERVER_ID_BYTES \
55 0x00, 0x01, 0x00, 0x01, 0x19, 0x40, 0x5c, 0x53, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53
6b44099b
NR
56#define VENDOR_SUBOPTION_BYTES \
57 0x01
1f280191
YW
58
59static const struct in6_addr local_address =
60 { { { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, } } };
61static const struct in6_addr mcast_address =
62 IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT;
63static const struct in6_addr ia_na_address1 = { { { IA_NA_ADDRESS1_BYTES } } };
64static const struct in6_addr ia_na_address2 = { { { IA_NA_ADDRESS2_BYTES } } };
65static const struct in6_addr ia_pd_prefix1 = { { { IA_PD_PREFIX1_BYTES } } };
66static const struct in6_addr ia_pd_prefix2 = { { { IA_PD_PREFIX2_BYTES } } };
67static const struct in6_addr dns1 = { { { DNS1_BYTES } } };
68static const struct in6_addr dns2 = { { { DNS2_BYTES } } };
69static const struct in6_addr sntp1 = { { { SNTP1_BYTES } } };
70static const struct in6_addr sntp2 = { { { SNTP2_BYTES } } };
71static const struct in6_addr ntp1 = { { { NTP1_BYTES } } };
72static const struct in6_addr ntp2 = { { { NTP2_BYTES } } };
73static const uint8_t client_id[] = { CLIENT_ID_BYTES };
74static const uint8_t server_id[] = { SERVER_ID_BYTES };
6b44099b 75static uint8_t vendor_suboption_data[] = { VENDOR_SUBOPTION_BYTES };
1f280191
YW
76static const struct ether_addr mac = {
77 .ether_addr_octet = { 'A', 'B', 'C', '1', '2', '3' },
813e3a6f 78};
71136404 79static int test_fd[2] = EBADF_PAIR;
6b44099b
NR
80static sd_dhcp6_option vendor_suboption = {
81 .n_ref = 1,
82 .enterprise_identifier = 32,
83 .option = 247,
84 .data = vendor_suboption_data,
85 .length = 1,
86};
1a6c9136 87static int test_ifindex = 42;
1f280191
YW
88static unsigned test_client_sent_message_count = 0;
89static sd_dhcp6_client *client_ref = NULL;
90
68da8adf 91TEST(client_basic) {
1f280191 92 _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
7776f2ae 93 int v;
813e3a6f 94
813e3a6f
PF
95 assert_se(sd_dhcp6_client_new(&client) >= 0);
96 assert_se(client);
97
2f8e7633 98 assert_se(sd_dhcp6_client_set_ifindex(client, 15) == 0);
2f8e7633 99 assert_se(sd_dhcp6_client_set_ifindex(client, 42) >= 0);
813e3a6f 100
1f280191 101 assert_se(sd_dhcp6_client_set_mac(client, mac.ether_addr_octet, sizeof(mac), ARPHRD_ETHER) >= 0);
813e3a6f 102
8006aa32
SA
103 assert_se(sd_dhcp6_client_set_fqdn(client, "host") == 1);
104 assert_se(sd_dhcp6_client_set_fqdn(client, "host.domain") == 1);
105 assert_se(sd_dhcp6_client_set_fqdn(client, NULL) == 1);
106 assert_se(sd_dhcp6_client_set_fqdn(client, "~host") == -EINVAL);
107 assert_se(sd_dhcp6_client_set_fqdn(client, "~host.domain") == -EINVAL);
108
fea8c180 109 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_CLIENTID) == -EINVAL);
612caa26
YW
110 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DNS_SERVER) >= 0);
111 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NTP_SERVER) >= 0);
112 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_SNTP_SERVER) >= 0);
6b44099b 113 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_VENDOR_OPTS) >= 0);
612caa26 114 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DOMAIN) >= 0);
fea8c180 115 assert_se(sd_dhcp6_client_set_request_option(client, 10) == -EINVAL);
612caa26
YW
116 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NIS_SERVER) >= 0);
117 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NISP_SERVER) >= 0);
f697ab35
YW
118 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NIS_SERVER) == -EEXIST);
119 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NISP_SERVER) == -EEXIST);
da6fe470 120
7776f2ae
PF
121 assert_se(sd_dhcp6_client_set_information_request(client, 1) >= 0);
122 v = 0;
123 assert_se(sd_dhcp6_client_get_information_request(client, &v) >= 0);
124 assert_se(v);
125 assert_se(sd_dhcp6_client_set_information_request(client, 0) >= 0);
126 v = 42;
127 assert_se(sd_dhcp6_client_get_information_request(client, &v) >= 0);
128 assert_se(v == 0);
129
130 v = 0;
131 assert_se(sd_dhcp6_client_get_address_request(client, &v) >= 0);
132 assert_se(v);
133 v = 0;
134 assert_se(sd_dhcp6_client_set_address_request(client, 1) >= 0);
135 assert_se(sd_dhcp6_client_get_address_request(client, &v) >= 0);
136 assert_se(v);
137 v = 42;
138 assert_se(sd_dhcp6_client_set_address_request(client, 1) >= 0);
139 assert_se(sd_dhcp6_client_get_address_request(client, &v) >= 0);
140 assert_se(v);
141
142 assert_se(sd_dhcp6_client_set_address_request(client, 1) >= 0);
143 assert_se(sd_dhcp6_client_set_prefix_delegation(client, 1) >= 0);
144 v = 0;
145 assert_se(sd_dhcp6_client_get_address_request(client, &v) >= 0);
146 assert_se(v);
147 v = 0;
148 assert_se(sd_dhcp6_client_get_prefix_delegation(client, &v) >= 0);
149 assert_se(v);
150
813e3a6f
PF
151 assert_se(sd_dhcp6_client_set_callback(client, NULL, NULL) >= 0);
152
153 assert_se(sd_dhcp6_client_detach_event(client) >= 0);
813e3a6f
PF
154}
155
68da8adf 156TEST(parse_domain) {
1f280191
YW
157 _cleanup_free_ char *domain = NULL;
158 _cleanup_strv_free_ char **list = NULL;
c43eea9f 159 uint8_t *data;
c43eea9f 160
c43eea9f 161 data = (uint8_t []) { 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0 };
1f280191 162 assert_se(dhcp6_option_parse_domainname(data, 13, &domain) >= 0);
c43eea9f
BG
163 assert_se(domain);
164 assert_se(streq(domain, "example.com"));
1f280191 165 domain = mfree(domain);
c43eea9f
BG
166
167 data = (uint8_t []) { 4, 't', 'e', 's', 't' };
1f280191 168 assert_se(dhcp6_option_parse_domainname(data, 5, &domain) >= 0);
c43eea9f
BG
169 assert_se(domain);
170 assert_se(streq(domain, "test"));
1f280191 171 domain = mfree(domain);
c43eea9f
BG
172
173 data = (uint8_t []) { 0 };
1f280191 174 assert_se(dhcp6_option_parse_domainname(data, 1, &domain) < 0);
c43eea9f
BG
175
176 data = (uint8_t []) { 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0,
177 6, 'f', 'o', 'o', 'b', 'a', 'r', 0 };
1f280191 178 assert_se(dhcp6_option_parse_domainname_list(data, 21, &list) >= 0);
c43eea9f
BG
179 assert_se(list);
180 assert_se(streq(list[0], "example.com"));
181 assert_se(streq(list[1], "foobar"));
1f280191
YW
182 assert_se(!list[2]);
183 list = strv_free(list);
c43eea9f
BG
184
185 data = (uint8_t []) { 1, 'a', 0, 20, 'b', 'c' };
1f280191 186 assert_se(dhcp6_option_parse_domainname_list(data, 6, &list) < 0);
c43eea9f
BG
187
188 data = (uint8_t []) { 0 , 0 };
1f280191 189 assert_se(dhcp6_option_parse_domainname_list(data, 2, &list) < 0);
c43eea9f
BG
190}
191
68da8adf 192TEST(option) {
9d2d346a 193 static const uint8_t packet[] = {
e6201049 194 'F', 'O', 'O', 'H', 'O', 'G', 'E',
2c1ab8ca 195 0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x07,
f12ed3bf 196 'A', 'B', 'C', 'D', 'E', 'F', 'G',
2c1ab8ca 197 0x00, SD_DHCP6_OPTION_VENDOR_CLASS, 0x00, 0x09,
f12ed3bf
PF
198 '1', '2', '3', '4', '5', '6', '7', '8', '9',
199 'B', 'A', 'R',
200 };
9d2d346a 201 static const uint8_t result[] = {
e6201049 202 'F', 'O', 'O', 'H', 'O', 'G', 'E',
f12ed3bf
PF
203 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
204 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
205 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
206 'B', 'A', 'R',
207 };
e6201049 208 _cleanup_free_ uint8_t *buf = NULL;
9d2d346a 209 size_t offset, pos, optlen;
b89a3758 210 const uint8_t *optval;
f12ed3bf 211 uint16_t optcode;
f12ed3bf 212
b89a3758 213 assert_se(sizeof(packet) == sizeof(result));
f12ed3bf 214
b89a3758
YW
215 offset = 0;
216 assert_se(dhcp6_option_parse(packet, 0, &offset, &optcode, &optlen, &optval) == -EBADMSG);
f12ed3bf 217
b89a3758
YW
218 offset = 3;
219 assert_se(dhcp6_option_parse(packet, 0, &offset, &optcode, &optlen, &optval) == -EBADMSG);
220
e6201049
YW
221 /* Tests for reading unaligned data. */
222 assert_se(buf = new(uint8_t, sizeof(packet)));
223 for (size_t i = 0; i <= 7; i++) {
224 memcpy(buf, packet + i, sizeof(packet) - i);
225 offset = 7 - i;
226 assert_se(dhcp6_option_parse(buf, sizeof(packet), &offset, &optcode, &optlen, &optval) >= 0);
227
228 assert_se(optcode == SD_DHCP6_OPTION_ORO);
229 assert_se(optlen == 7);
230 assert_se(optval == buf + 11 - i);
231 }
232
233 offset = 7;
b89a3758 234 assert_se(dhcp6_option_parse(packet, sizeof(packet), &offset, &optcode, &optlen, &optval) >= 0);
f12ed3bf 235
2c1ab8ca 236 assert_se(optcode == SD_DHCP6_OPTION_ORO);
f12ed3bf 237 assert_se(optlen == 7);
e6201049 238 assert_se(optval == packet + 11);
b89a3758 239
9d2d346a
YW
240 free(buf);
241 assert_se(buf = memdup(result, sizeof(result)));
e6201049 242 pos = 7;
9d2d346a 243 assert_se(dhcp6_option_append(&buf, &pos, optcode, optlen, optval) >= 0);
f12ed3bf 244
b89a3758
YW
245 assert_se(dhcp6_option_parse(packet, sizeof(packet), &offset, &optcode, &optlen, &optval) >= 0);
246
2c1ab8ca 247 assert_se(optcode == SD_DHCP6_OPTION_VENDOR_CLASS);
f12ed3bf 248 assert_se(optlen == 9);
e6201049 249 assert_se(optval == packet + 22);
b89a3758 250
9d2d346a 251 assert_se(dhcp6_option_append(&buf, &pos, optcode, optlen, optval) >= 0);
f12ed3bf 252
9d2d346a 253 assert_se(memcmp(packet, buf, sizeof(packet)) == 0);
f12ed3bf
PF
254}
255
68da8adf 256TEST(option_status) {
df296124
PF
257 uint8_t option1[] = {
258 /* IA NA */
259 0x00, 0x03, 0x00, 0x12, 0x1a, 0x1d, 0x1a, 0x1d,
260 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02,
261 /* status option */
262 0x00, 0x0d, 0x00, 0x02, 0x00, 0x01,
263 };
264 static const uint8_t option2[] = {
265 /* IA NA */
266 0x00, 0x03, 0x00, 0x2e, 0x1a, 0x1d, 0x1a, 0x1d,
267 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02,
268 /* IA Addr */
269 0x00, 0x05, 0x00, 0x1e,
270 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
271 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
272 0x01, 0x02, 0x03, 0x04, 0x0a, 0x0b, 0x0c, 0x0d,
4af39cb8 273 /* IA address status option */
df296124
PF
274 0x00, 0x0d, 0x00, 0x02, 0x00, 0x01,
275 };
276 static const uint8_t option3[] = {
277 /* IA NA */
278 0x00, 0x03, 0x00, 0x34, 0x1a, 0x1d, 0x1a, 0x1d,
279 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02,
280 /* IA Addr */
281 0x00, 0x05, 0x00, 0x24,
282 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
283 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
284 0x01, 0x02, 0x03, 0x04, 0x0a, 0x0b, 0x0c, 0x0d,
4af39cb8 285 /* IA address status option */
df296124
PF
286 0x00, 0x0d, 0x00, 0x08, 0x00, 0x00, 'f', 'o',
287 'o', 'b', 'a', 'r',
288 };
819c56f6
PF
289 static const uint8_t option4[] = {
290 /* IA PD */
291 0x00, 0x19, 0x00, 0x2f, 0x1a, 0x1d, 0x1a, 0x1d,
292 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02,
293 /* IA PD Prefix */
294 0x00, 0x1a, 0x00, 0x1f,
295 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
296 0x80, 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe,
297 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
298 0x00,
4af39cb8 299 /* PD prefix status option */
819c56f6
PF
300 0x00, 0x0d, 0x00, 0x02, 0x00, 0x00,
301 };
302 static const uint8_t option5[] = {
303 /* IA PD */
304 0x00, 0x19, 0x00, 0x52, 0x1a, 0x1d, 0x1a, 0x1d,
305 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02,
306 /* IA PD Prefix #1 */
307 0x00, 0x1a, 0x00, 0x1f,
308 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
309 0x80, 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe,
310 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
311 0x00,
4af39cb8 312 /* PD prefix status option */
819c56f6
PF
313 0x00, 0x0d, 0x00, 0x02, 0x00, 0x00,
314 /* IA PD Prefix #2 */
315 0x00, 0x1a, 0x00, 0x1f,
316 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
317 0x80, 0x20, 0x01, 0x0d, 0xb8, 0xc0, 0x0l, 0xd0,
318 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
319 0x00,
4af39cb8 320 /* PD prefix status option */
819c56f6
PF
321 0x00, 0x0d, 0x00, 0x02, 0x00, 0x00,
322 };
e5b0b87f 323 _cleanup_(dhcp6_ia_freep) DHCP6IA *ia = NULL;
df296124 324 DHCP6Option *option;
469fd57f 325 be32_t iaid;
e5b0b87f 326 int r;
df296124 327
469fd57f
YW
328 memcpy(&iaid, option1 + 4, sizeof(iaid));
329
4af39cb8 330 option = (DHCP6Option*) option1;
df296124
PF
331 assert_se(sizeof(option1) == sizeof(DHCP6Option) + be16toh(option->len));
332
8a895550 333 r = dhcp6_option_parse_ia(NULL, 0, be16toh(option->code), be16toh(option->len), option->data, &ia);
469fd57f
YW
334 assert_se(r == -ENOANO);
335
8a895550
YW
336 r = dhcp6_option_parse_ia(NULL, iaid, be16toh(option->code), be16toh(option->len), option->data, &ia);
337 assert_se(r == -EINVAL);
df296124
PF
338
339 option->len = htobe16(17);
8a895550
YW
340 r = dhcp6_option_parse_ia(NULL, iaid, be16toh(option->code), be16toh(option->len), option->data, &ia);
341 assert_se(r == -EBADMSG);
df296124
PF
342
343 option->len = htobe16(sizeof(DHCP6Option));
8a895550
YW
344 r = dhcp6_option_parse_ia(NULL, iaid, be16toh(option->code), be16toh(option->len), option->data, &ia);
345 assert_se(r == -EBADMSG);
df296124 346
4af39cb8 347 option = (DHCP6Option*) option2;
df296124 348 assert_se(sizeof(option2) == sizeof(DHCP6Option) + be16toh(option->len));
8a895550
YW
349 r = dhcp6_option_parse_ia(NULL, iaid, be16toh(option->code), be16toh(option->len), option->data, &ia);
350 assert_se(r == -ENODATA);
df296124 351
4af39cb8 352 option = (DHCP6Option*) option3;
df296124 353 assert_se(sizeof(option3) == sizeof(DHCP6Option) + be16toh(option->len));
8a895550
YW
354 r = dhcp6_option_parse_ia(NULL, iaid, be16toh(option->code), be16toh(option->len), option->data, &ia);
355 assert_se(r >= 0);
e5b0b87f
YW
356 assert_se(ia);
357 assert_se(ia->addresses);
358 ia = dhcp6_ia_free(ia);
df296124 359
4af39cb8 360 option = (DHCP6Option*) option4;
819c56f6 361 assert_se(sizeof(option4) == sizeof(DHCP6Option) + be16toh(option->len));
e5b0b87f 362 r = dhcp6_option_parse_ia(NULL, iaid, be16toh(option->code), be16toh(option->len), option->data, &ia);
8a895550 363 assert_se(r >= 0);
e5b0b87f
YW
364 assert_se(ia);
365 assert_se(ia->addresses);
366 assert_se(memcmp(&ia->header.id, &option4[4], 4) == 0);
367 assert_se(memcmp(&ia->header.lifetime_t1, &option4[8], 4) == 0);
368 assert_se(memcmp(&ia->header.lifetime_t2, &option4[12], 4) == 0);
369 ia = dhcp6_ia_free(ia);
819c56f6 370
4af39cb8 371 option = (DHCP6Option*) option5;
819c56f6 372 assert_se(sizeof(option5) == sizeof(DHCP6Option) + be16toh(option->len));
e5b0b87f 373 r = dhcp6_option_parse_ia(NULL, iaid, be16toh(option->code), be16toh(option->len), option->data, &ia);
8a895550 374 assert_se(r >= 0);
e5b0b87f
YW
375 assert_se(ia);
376 assert_se(ia->addresses);
377 ia = dhcp6_ia_free(ia);
df296124
PF
378}
379
68da8adf 380TEST(client_parse_message_issue_22099) {
95c514e9 381 static const uint8_t msg[] = {
1f280191
YW
382 /* Message type */
383 DHCP6_MESSAGE_REPLY,
384 /* Transaction ID */
385 0x7c, 0x4c, 0x16,
386 /* Rapid commit */
387 0x00, SD_DHCP6_OPTION_RAPID_COMMIT, 0x00, 0x00,
388 /* NTP servers */
389 0x00, SD_DHCP6_OPTION_NTP_SERVER, 0x00, 0x14,
390 /* NTP server (broken sub option and sub option length) */
391 0x01, 0x00, 0x10, 0x00,
392 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0x15, 0xc8, 0xff, 0xfe, 0xef, 0x1e, 0x4e,
393 /* Client ID */
394 0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
395 0x00, 0x02, /* DUID-EN */
396 0x00, 0x00, 0xab, 0x11, /* pen */
397 0x5c, 0x6b, 0x90, 0xec, 0xda, 0x95, 0x15, 0x45, /* id */
398 /* Server ID */
399 0x00, SD_DHCP6_OPTION_SERVERID, 0x00, 0x0a,
400 0x00, 0x03, /* DUID-LL */
401 0x00, 0x01, /* htype */
402 0xdc, 0x15, 0xc8, 0xef, 0x1e, 0x4e, /* haddr */
95c514e9 403 /* preference */
1f280191
YW
404 0x00, SD_DHCP6_OPTION_PREFERENCE, 0x00, 0x01,
405 0x00,
95c514e9 406 /* DNS servers */
f697ab35 407 0x00, SD_DHCP6_OPTION_DNS_SERVER, 0x00, 0x10,
1f280191 408 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0x15, 0xc8, 0xff, 0xfe, 0xef, 0x1e, 0x4e,
95c514e9 409 /* v6 pcp server */
1f280191
YW
410 0x00, SD_DHCP6_OPTION_V6_PCP_SERVER, 0x00, 0x10,
411 0x2a, 0x02, 0x81, 0x0d, 0x98, 0x80, 0x37, 0x00, 0xde, 0x15, 0xc8, 0xff, 0xfe, 0xef, 0x1e, 0x4e,
95c514e9 412 /* IA_NA */
1f280191
YW
413 0x00, SD_DHCP6_OPTION_IA_NA, 0x00, 0x28,
414 0xcc, 0x59, 0x11, 0x7b, /* iaid */
415 0x00, 0x00, 0x07, 0x08, /* lifetime T1 */
416 0x00, 0x00, 0x0b, 0x40, /* lifetime T2 */
417 /* IA_NA (iaaddr suboption) */
418 0x00, SD_DHCP6_OPTION_IAADDR, 0x00, 0x18,
419 0x2a, 0x02, 0x81, 0x0d, 0x98, 0x80, 0x37, 0x00, 0x6a, 0x05, 0xca, 0xff, 0xfe, 0xf1, 0x51, 0x53, /* address */
420 0x00, 0x00, 0x0e, 0x10, /* preferred lifetime */
421 0x00, 0x00, 0x1c, 0x20, /* valid lifetime */
95c514e9 422 /* IA_PD */
1f280191
YW
423 0x00, SD_DHCP6_OPTION_IA_PD, 0x00, 0x29,
424 0xcc, 0x59, 0x11, 0x7b, /* iaid */
425 0x00, 0x00, 0x07, 0x08, /* lifetime T1 */
426 0x00, 0x00, 0x0b, 0x40, /* lifetime T2 */
427 /* IA_PD (iaprefix suboption) */
428 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX, 0x00, 0x19,
429 0x00, 0x00, 0x0e, 0x10, /* preferred lifetime */
430 0x00, 0x00, 0x1c, 0x20, /* valid lifetime */
431 0x3a, /* prefixlen */
432 0x2a, 0x02, 0x81, 0x0d, 0x98, 0x80, 0x37, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* prefix */
95c514e9
YW
433 };
434 static const uint8_t duid[] = {
435 0x00, 0x00, 0xab, 0x11, 0x5c, 0x6b, 0x90, 0xec, 0xda, 0x95, 0x15, 0x45,
436 };
437 _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
438 _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
439
95c514e9
YW
440 assert_se(sd_dhcp6_client_new(&client) >= 0);
441 assert_se(sd_dhcp6_client_set_iaid(client, 0xcc59117b) >= 0);
53488ea3 442 assert_se(sd_dhcp6_client_set_duid_raw(client, 2, duid, sizeof(duid)) >= 0);
95c514e9 443
65ece4c8 444 assert_se(dhcp6_lease_new_from_message(client, (const DHCP6Message*) msg, sizeof(msg), NULL, NULL, &lease) >= 0);
95c514e9
YW
445}
446
68870a46
YW
447TEST(client_parse_message_issue_24002) {
448 static const uint8_t msg[] = {
449 /* Message Type */
450 0x07,
451 /* Transaction ID */
452 0x0e, 0xa5, 0x7c,
453 /* Client ID */
454 0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
455 0x00, 0x02, /* DUID-EN */
456 0x00, 0x00, 0xab, 0x11, /* pen */
457 0x5c, 0x6b, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, /* id */
458 /* Server ID */
459 0x00, 0x02, 0x00, 0x1a,
460 0x00, 0x02, 0x00, 0x00, 0x05, 0x83, 0x30, 0x63, 0x3a, 0x38, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
461 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
462 /* IA_PD */
463 0x00, 0x19, 0x00, 0x29,
464 0xaa, 0xbb, 0xcc, 0xdd, /* iaid */
465 0x00, 0x00, 0x03, 0x84, /* lifetime (T1) */
466 0x00, 0x00, 0x05, 0xa0, /* lifetime (T2) */
467 /* IA_PD (iaprefix suboption) */
468 0x00, 0x1a, 0x00, 0x19,
469 0x00, 0x00, 0x07, 0x08, /* preferred lifetime */
470 0x00, 0x00, 0x38, 0x40, /* valid lifetime */
471 0x38, /* prefixlen */
472 0x20, 0x03, 0x00, 0xff, 0xaa, 0xbb, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* prefix */
473 /* Rapid commit */
474 0x00, 0x0e, 0x00, 0x00,
894f4417
YW
475 /* Trailing invalid byte at the end. See issue #28183. */
476 00,
68870a46
YW
477 };
478 static const uint8_t duid[] = {
479 0x00, 0x00, 0xab, 0x11, 0x5c, 0x6b, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
480 };
481 _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
482 _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
483
484 assert_se(sd_dhcp6_client_new(&client) >= 0);
485 assert_se(sd_dhcp6_client_set_iaid(client, 0xaabbccdd) >= 0);
53488ea3 486 assert_se(sd_dhcp6_client_set_duid_raw(client, 2, duid, sizeof(duid)) >= 0);
68870a46
YW
487
488 assert_se(dhcp6_lease_new_from_message(client, (const DHCP6Message*) msg, sizeof(msg), NULL, NULL, &lease) >= 0);
489}
490
1f280191
YW
491static const uint8_t msg_information_request[] = {
492 /* Message type */
493 DHCP6_MESSAGE_INFORMATION_REQUEST,
494 /* Transaction ID */
495 0x0f, 0xb4, 0xe5,
496 /* MUD URL */
497 /* ORO */
822883b3 498 0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x0c,
f697ab35
YW
499 0x00, SD_DHCP6_OPTION_DNS_SERVER,
500 0x00, SD_DHCP6_OPTION_DOMAIN,
501 0x00, SD_DHCP6_OPTION_SNTP_SERVER,
822883b3 502 0x00, SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME,
0e0c4dae 503 0x00, SD_DHCP6_OPTION_NTP_SERVER,
822883b3 504 0x00, SD_DHCP6_OPTION_INF_MAX_RT,
1f280191
YW
505 /* Client ID */
506 0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
507 CLIENT_ID_BYTES,
508 /* Extra options */
509 /* Elapsed time */
510 0x00, SD_DHCP6_OPTION_ELAPSED_TIME, 0x00, 0x02,
511 0x00, 0x00,
859cca44
PF
512};
513
1f280191
YW
514static const uint8_t msg_solicit[] = {
515 /* Message type */
516 DHCP6_MESSAGE_SOLICIT,
517 /* Transaction ID */
518 0x0f, 0xb4, 0xe5,
519 /* Rapid commit */
520 0x00, SD_DHCP6_OPTION_RAPID_COMMIT, 0x00, 0x00,
521 /* IA_NA */
522 0x00, SD_DHCP6_OPTION_IA_NA, 0x00, 0x0c,
523 IA_ID_BYTES,
524 0x00, 0x00, 0x00, 0x00, /* lifetime T1 */
525 0x00, 0x00, 0x00, 0x00, /* lifetime T2 */
526 /* IA_PD */
527 0x00, SD_DHCP6_OPTION_IA_PD, 0x00, 0x0c,
528 IA_ID_BYTES,
529 0x00, 0x00, 0x00, 0x00, /* lifetime T1 */
530 0x00, 0x00, 0x00, 0x00, /* lifetime T2 */
531 /* Client FQDN */
532 0x00, SD_DHCP6_OPTION_CLIENT_FQDN, 0x00, 0x11,
533 DHCP6_FQDN_FLAG_S,
534 0x04, 'h', 'o', 's', 't', 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
535 /* User Class */
536 /* Vendor Class */
537 /* Vendor Options */
538 /* MUD URL */
539 /* ORO */
822883b3 540 0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x0a,
f697ab35
YW
541 0x00, SD_DHCP6_OPTION_DNS_SERVER,
542 0x00, SD_DHCP6_OPTION_DOMAIN,
543 0x00, SD_DHCP6_OPTION_SNTP_SERVER,
0e0c4dae 544 0x00, SD_DHCP6_OPTION_NTP_SERVER,
822883b3 545 0x00, SD_DHCP6_OPTION_SOL_MAX_RT,
1f280191
YW
546 /* Client ID */
547 0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
548 CLIENT_ID_BYTES,
549 /* Extra options */
550 /* Elapsed time */
551 0x00, SD_DHCP6_OPTION_ELAPSED_TIME, 0x00, 0x02,
552 0x00, 0x00,
947527f8
PF
553};
554
1f280191
YW
555static const uint8_t msg_request[] = {
556 /* Message type */
557 DHCP6_MESSAGE_REQUEST,
558 /* Transaction ID */
559 0x00, 0x00, 0x00,
560 /* Server ID */
561 0x00, SD_DHCP6_OPTION_SERVERID, 0x00, 0x0e,
562 SERVER_ID_BYTES,
563 /* IA_NA */
564 0x00, SD_DHCP6_OPTION_IA_NA, 0x00, 0x44,
565 IA_ID_BYTES,
566 0x00, 0x00, 0x00, 0x00, /* lifetime T1 */
567 0x00, 0x00, 0x00, 0x00, /* lifetime T2 */
568 /* IA_NA (IAADDR suboption) */
569 0x00, SD_DHCP6_OPTION_IAADDR, 0x00, 0x18,
570 IA_NA_ADDRESS1_BYTES,
571 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
572 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
573 /* IA_NA (IAADDR suboption) */
574 0x00, SD_DHCP6_OPTION_IAADDR, 0x00, 0x18,
575 IA_NA_ADDRESS2_BYTES,
576 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
577 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
578 /* IA_PD */
579 0x00, SD_DHCP6_OPTION_IA_PD, 0x00, 0x46,
580 IA_ID_BYTES,
581 0x00, 0x00, 0x00, 0x00, /* lifetime T1 */
582 0x00, 0x00, 0x00, 0x00, /* lifetime T2 */
583 /* IA_PD (IA_PD_PREFIX suboption) */
584 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX, 0x00, 0x19,
585 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
586 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
587 0x40, /* prefixlen */
588 IA_PD_PREFIX1_BYTES,
589 /* IA_PD (IA_PD_PREFIX suboption) */
590 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX, 0x00, 0x19,
591 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
592 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
593 0x40, /* prefixlen */
594 IA_PD_PREFIX2_BYTES,
595 /* Client FQDN */
596 0x00, SD_DHCP6_OPTION_CLIENT_FQDN, 0x00, 0x11,
597 DHCP6_FQDN_FLAG_S,
598 0x04, 'h', 'o', 's', 't', 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
599 /* User Class */
600 /* Vendor Class */
601 /* Vendor Options */
602 /* MUD URL */
603 /* ORO */
604 0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x08,
f697ab35
YW
605 0x00, SD_DHCP6_OPTION_DNS_SERVER,
606 0x00, SD_DHCP6_OPTION_DOMAIN,
607 0x00, SD_DHCP6_OPTION_SNTP_SERVER,
0e0c4dae 608 0x00, SD_DHCP6_OPTION_NTP_SERVER,
1f280191
YW
609 /* Client ID */
610 0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
611 CLIENT_ID_BYTES,
612 /* Extra options */
613 /* Elapsed time */
614 0x00, SD_DHCP6_OPTION_ELAPSED_TIME, 0x00, 0x02,
615 0x00, 0x00,
8006aa32
SA
616};
617
b895aa5f 618/* RFC 3315 section 18.1.6. The DHCP6 Release message must include:
619 - transaction id
620 - server identifier
621 - client identifier
622 - all released IA with addresses included
623 - elapsed time (required for all messages).
624 All other options aren't required. */
625static const uint8_t msg_release[] = {
626 /* Message type */
627 DHCP6_MESSAGE_RELEASE,
628 /* Transaction ID */
629 0x00, 0x00, 0x00,
630 /* Server ID */
631 0x00, SD_DHCP6_OPTION_SERVERID, 0x00, 0x0e,
632 SERVER_ID_BYTES,
633 /* IA_NA */
634 0x00, SD_DHCP6_OPTION_IA_NA, 0x00, 0x44,
635 IA_ID_BYTES,
636 0x00, 0x00, 0x00, 0x00, /* lifetime T1 */
637 0x00, 0x00, 0x00, 0x00, /* lifetime T2 */
638 /* IA_NA (IAADDR suboption) */
639 0x00, SD_DHCP6_OPTION_IAADDR, 0x00, 0x18,
640 IA_NA_ADDRESS1_BYTES,
641 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
642 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
643 /* IA_NA (IAADDR suboption) */
644 0x00, SD_DHCP6_OPTION_IAADDR, 0x00, 0x18,
645 IA_NA_ADDRESS2_BYTES,
646 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
647 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
648 /* IA_PD */
649 0x00, SD_DHCP6_OPTION_IA_PD, 0x00, 0x46,
650 IA_ID_BYTES,
651 0x00, 0x00, 0x00, 0x00, /* lifetime T1 */
652 0x00, 0x00, 0x00, 0x00, /* lifetime T2 */
653 /* IA_PD (IA_PD_PREFIX suboption) */
654 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX, 0x00, 0x19,
655 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
656 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
657 0x40, /* prefixlen */
658 IA_PD_PREFIX1_BYTES,
659 /* IA_PD (IA_PD_PREFIX suboption) */
660 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX, 0x00, 0x19,
661 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
662 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
663 0x40, /* prefixlen */
664 IA_PD_PREFIX2_BYTES,
665 /* Client ID */
666 0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
667 CLIENT_ID_BYTES,
668 /* Extra options */
669 /* Elapsed time */
670 0x00, SD_DHCP6_OPTION_ELAPSED_TIME, 0x00, 0x02,
671 0x00, 0x00,
672};
673
1f280191
YW
674static const uint8_t msg_reply[] = {
675 /* Message type */
676 DHCP6_MESSAGE_REPLY,
677 /* Transaction ID */
678 0x0f, 0xb4, 0xe5,
679 /* Client ID */
680 0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
681 CLIENT_ID_BYTES,
682 /* Server ID */
683 0x00, SD_DHCP6_OPTION_SERVERID, 0x00, 0x0e,
684 SERVER_ID_BYTES,
685 /* Rapid commit */
686 0x00, SD_DHCP6_OPTION_RAPID_COMMIT, 0x00, 0x01,
687 0x00,
688 /* IA_NA */
689 0x00, SD_DHCP6_OPTION_IA_NA, 0x00, 0x66,
690 IA_ID_BYTES,
691 0x00, 0x00, 0x00, 0x50, /* lifetime T1 */
692 0x00, 0x00, 0x00, 0x78, /* lifetime T2 */
693 /* IA_NA (IAADDR suboption) */
694 0x00, SD_DHCP6_OPTION_IAADDR, 0x00, 0x18,
695 IA_NA_ADDRESS2_BYTES,
696 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
697 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
698 /* IA_NA (IAADDR suboption) */
699 0x00, SD_DHCP6_OPTION_IAADDR, 0x00, 0x18,
700 IA_NA_ADDRESS1_BYTES,
701 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
702 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
703 /* IA_NA (status code suboption) */
704 0x00, SD_DHCP6_OPTION_STATUS_CODE, 0x00, 0x1e,
705 0x00, 0x00, /* status code */
706 0x41, 0x6c, 0x6c, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x20, 0x77, 0x65,
707 0x72, 0x65, 0x20, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x2e, /* status message */
708 /* IA_PD */
709 0x00, SD_DHCP6_OPTION_IA_PD, 0x00, 0x46,
710 IA_ID_BYTES,
711 0x00, 0x00, 0x00, 0x50, /* lifetime T1 */
712 0x00, 0x00, 0x00, 0x78, /* lifetime T2 */
713 /* IA_PD (IA_PD_PREFIX suboption) */
714 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX, 0x00, 0x19,
715 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
716 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
717 0x40, /* prefixlen */
718 IA_PD_PREFIX2_BYTES,
719 /* IA_PD (IA_PD_PREFIX suboption) */
720 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX, 0x00, 0x19,
721 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
722 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
723 0x40, /* prefixlen */
724 IA_PD_PREFIX1_BYTES,
725 /* DNS servers */
f697ab35 726 0x00, SD_DHCP6_OPTION_DNS_SERVER, 0x00, 0x20,
1f280191
YW
727 DNS1_BYTES,
728 DNS2_BYTES,
729 /* SNTP servers */
f697ab35 730 0x00, SD_DHCP6_OPTION_SNTP_SERVER, 0x00, 0x20,
1f280191
YW
731 SNTP1_BYTES,
732 SNTP2_BYTES,
733 /* NTP servers */
734 0x00, SD_DHCP6_OPTION_NTP_SERVER, 0x00, 0x37,
735 /* NTP server (address suboption) */
736 0x00, DHCP6_NTP_SUBOPTION_SRV_ADDR, 0x00, 0x10,
737 NTP1_BYTES,
738 /* NTP server (address suboption) */
739 0x00, DHCP6_NTP_SUBOPTION_SRV_ADDR, 0x00, 0x10,
740 NTP2_BYTES,
741 /* NTP server (fqdn suboption) */
742 0x00, DHCP6_NTP_SUBOPTION_SRV_FQDN, 0x00, 0x0b,
743 0x03, 'n', 't', 'p', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
744 /* Domain list */
f697ab35 745 0x00, SD_DHCP6_OPTION_DOMAIN, 0x00, 0x0b,
1f280191
YW
746 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
747 /* Client FQDN */
748 0x00, SD_DHCP6_OPTION_CLIENT_FQDN, 0x00, 0x12,
749 0x01, 0x06, 'c', 'l', 'i', 'e', 'n', 't', 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a',
6b44099b
NR
750 /* Vendor specific options */
751 0x00, SD_DHCP6_OPTION_VENDOR_OPTS, 0x00, 0x09,
752 0x00, 0x00, 0x00, 0x20, 0x00, 0xf7, 0x00, 0x01, VENDOR_SUBOPTION_BYTES,
1f280191 753};
859cca44 754
1f280191
YW
755static const uint8_t msg_advertise[] = {
756 /* Message type */
757 DHCP6_MESSAGE_ADVERTISE,
758 /* Transaction ID */
759 0x0f, 0xb4, 0xe5,
760 /* Client ID */
761 0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
762 CLIENT_ID_BYTES,
763 /* Server ID */
764 0x00, SD_DHCP6_OPTION_SERVERID, 0x00, 0x0e,
765 SERVER_ID_BYTES,
766 /* Preference */
767 0x00, SD_DHCP6_OPTION_PREFERENCE, 0x00, 0x01,
768 0xff,
769 /* IA_NA */
770 0x00, SD_DHCP6_OPTION_IA_NA, 0x00, 0x7a,
771 IA_ID_BYTES,
772 0x00, 0x00, 0x00, 0x50, /* lifetime T1 */
773 0x00, 0x00, 0x00, 0x78, /* lifetime T2 */
774 /* IA_NA (IAADDR suboption) */
775 0x00, SD_DHCP6_OPTION_IAADDR, 0x00, 0x18,
776 IA_NA_ADDRESS2_BYTES, /* address */
777 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
778 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
779 /* IA_NA (IAADDR suboption) */
780 0x00, SD_DHCP6_OPTION_IAADDR, 0x00, 0x18,
781 IA_NA_ADDRESS1_BYTES, /* address */
782 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
783 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
784 /* IA_NA (status code suboption) */
785 0x00, SD_DHCP6_OPTION_STATUS_CODE, 0x00, 0x32,
786 0x00, 0x00, /* status code */
787 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x28, 0x65, 0x73, 0x29, 0x20, 0x72, 0x65, 0x6e, 0x65,
788 0x77, 0x65, 0x64, 0x2e, 0x20, 0x47, 0x72, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x66,
789 0x72, 0x6f, 0x6d, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x74, 0x20, 0x45, 0x61, 0x72, 0x74, 0x68, /* status message */
790 /* IA_PD */
791 0x00, SD_DHCP6_OPTION_IA_PD, 0x00, 0x46,
792 IA_ID_BYTES,
793 0x00, 0x00, 0x00, 0x50, /* lifetime T1 */
794 0x00, 0x00, 0x00, 0x78, /* lifetime T2 */
795 /* IA_PD (IA_PD_PREFIX suboption) */
796 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX, 0x00, 0x19,
797 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
798 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
799 0x40, /* prefixlen */
800 IA_PD_PREFIX2_BYTES,
801 /* IA_PD (IA_PD_PREFIX suboption) */
802 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX, 0x00, 0x19,
803 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
804 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
805 0x40, /* prefixlen */
806 IA_PD_PREFIX1_BYTES,
807 /* DNS servers */
f697ab35 808 0x00, SD_DHCP6_OPTION_DNS_SERVER, 0x00, 0x20,
1f280191
YW
809 DNS1_BYTES,
810 DNS2_BYTES,
811 /* SNTP servers */
f697ab35 812 0x00, SD_DHCP6_OPTION_SNTP_SERVER, 0x00, 0x20,
1f280191
YW
813 SNTP1_BYTES,
814 SNTP2_BYTES,
815 /* NTP servers */
816 0x00, SD_DHCP6_OPTION_NTP_SERVER, 0x00, 0x37,
817 /* NTP server (address suboption) */
818 0x00, DHCP6_NTP_SUBOPTION_SRV_ADDR, 0x00, 0x10,
819 NTP1_BYTES,
820 /* NTP server (address suboption) */
821 0x00, DHCP6_NTP_SUBOPTION_SRV_ADDR, 0x00, 0x10,
822 NTP2_BYTES,
823 /* NTP server (fqdn suboption) */
824 0x00, DHCP6_NTP_SUBOPTION_SRV_FQDN, 0x00, 0x0b,
825 0x03, 'n', 't', 'p', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
826 /* Domain list */
f697ab35 827 0x00, SD_DHCP6_OPTION_DOMAIN, 0x00, 0x0b,
1f280191
YW
828 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
829 /* Client FQDN */
830 0x00, SD_DHCP6_OPTION_CLIENT_FQDN, 0x00, 0x12,
831 0x01, 0x06, 'c', 'l', 'i', 'e', 'n', 't', 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a',
6b44099b
NR
832 /* Vendor specific options */
833 0x00, SD_DHCP6_OPTION_VENDOR_OPTS, 0x00, 0x09,
834 0x00, 0x00, 0x00, 0x20, 0x00, 0xf7, 0x00, 0x01, VENDOR_SUBOPTION_BYTES,
1f280191 835};
859cca44 836
1f280191
YW
837static void test_client_verify_information_request(const DHCP6Message *msg, size_t len) {
838 log_debug("/* %s */", __func__);
469fd57f 839
1f280191
YW
840 assert_se(len == sizeof(msg_information_request));
841 /* The elapsed time value is not deterministic. Skip it. */
842 assert_se(memcmp(msg, msg_information_request, len - sizeof(be16_t)) == 0);
843}
859cca44 844
1f280191
YW
845static void test_client_verify_solicit(const DHCP6Message *msg, size_t len) {
846 log_debug("/* %s */", __func__);
859cca44 847
1f280191
YW
848 assert_se(len == sizeof(msg_solicit));
849 /* The elapsed time value is not deterministic. Skip it. */
850 assert_se(memcmp(msg, msg_solicit, len - sizeof(be16_t)) == 0);
851}
859cca44 852
b895aa5f 853static void test_client_verify_release(const DHCP6Message *msg, size_t len) {
854 log_debug("/* %s */", __func__);
855
856 assert_se(len == sizeof(msg_release));
857 assert_se(msg->type == DHCP6_MESSAGE_RELEASE);
858 /* The transaction ID and elapsed time value are not deterministic. Skip them. */
859 assert_se(memcmp(msg->options, msg_release + offsetof(DHCP6Message, options),
860 len - offsetof(DHCP6Message, options) - sizeof(be16_t)) == 0);
861}
862
1f280191
YW
863static void test_client_verify_request(const DHCP6Message *msg, size_t len) {
864 log_debug("/* %s */", __func__);
859cca44 865
1f280191
YW
866 assert_se(len == sizeof(msg_request));
867 assert_se(msg->type == DHCP6_MESSAGE_REQUEST);
868 /* The transaction ID and elapsed time value are not deterministic. Skip them. */
b895aa5f 869 assert_se(memcmp(msg->options, msg_request + offsetof(DHCP6Message, options),
870 len - offsetof(DHCP6Message, options) - sizeof(be16_t)) == 0);
1f280191 871}
859cca44 872
1f280191
YW
873static void test_lease_common(sd_dhcp6_client *client) {
874 sd_dhcp6_lease *lease;
6b44099b 875 sd_dhcp6_option **suboption;
1f280191
YW
876 const struct in6_addr *addrs;
877 const char *str;
878 char **strv;
879 uint8_t *id;
880 size_t len;
859cca44 881
1f280191 882 assert_se(sd_dhcp6_client_get_lease(client, &lease) >= 0);
859cca44 883
1f280191
YW
884 assert_se(dhcp6_lease_get_clientid(lease, &id, &len) >= 0);
885 assert_se(memcmp_nn(id, len, client_id, sizeof(client_id)) == 0);
859cca44 886
1f280191
YW
887 assert_se(sd_dhcp6_lease_get_domains(lease, &strv) == 1);
888 assert_se(streq(strv[0], "lab.intra"));
889 assert_se(!strv[1]);
859cca44 890
1f280191
YW
891 assert_se(sd_dhcp6_lease_get_fqdn(lease, &str) >= 0);
892 assert_se(streq(str, "client.lab.intra"));
d63be95a 893
1f280191
YW
894 assert_se(sd_dhcp6_lease_get_dns(lease, &addrs) == 2);
895 assert_se(in6_addr_equal(&addrs[0], &dns1));
896 assert_se(in6_addr_equal(&addrs[1], &dns2));
d63be95a 897
1f280191
YW
898 assert_se(sd_dhcp6_lease_get_ntp_addrs(lease, &addrs) == 2);
899 assert_se(in6_addr_equal(&addrs[0], &ntp1));
900 assert_se(in6_addr_equal(&addrs[1], &ntp2));
bc152ff8 901
1f280191
YW
902 assert_se(sd_dhcp6_lease_get_ntp_fqdn(lease, &strv) == 1);
903 assert_se(streq(strv[0], "ntp.intra"));
904 assert_se(!strv[1]);
bc152ff8 905
1f280191
YW
906 assert_se(lease->sntp_count == 2);
907 assert_se(in6_addr_equal(&lease->sntp[0], &sntp1));
908 assert_se(in6_addr_equal(&lease->sntp[1], &sntp2));
6b44099b
NR
909
910 assert_se(sd_dhcp6_lease_get_vendor_options(lease, &suboption) > 0);
911 assert_se((*suboption)->enterprise_identifier == vendor_suboption.enterprise_identifier);
912 assert_se((*suboption)->option == vendor_suboption.option);
913 assert_se(*(uint8_t*)(*suboption)->data == *(uint8_t*)vendor_suboption.data);
1f280191 914}
bc152ff8 915
1f280191
YW
916static void test_lease_managed(sd_dhcp6_client *client) {
917 sd_dhcp6_lease *lease;
918 struct in6_addr addr;
d8ec95c7 919 usec_t lt_pref, lt_valid;
1f280191
YW
920 uint8_t *id, prefixlen;
921 size_t len;
859cca44 922
1f280191 923 assert_se(sd_dhcp6_client_get_lease(client, &lease) >= 0);
859cca44 924
1f280191
YW
925 assert_se(dhcp6_lease_get_serverid(lease, &id, &len) >= 0);
926 assert_se(memcmp_nn(id, len, server_id, sizeof(server_id)) == 0);
859cca44 927
fb70992d
YW
928 assert_se(sd_dhcp6_lease_has_address(lease));
929 assert_se(sd_dhcp6_lease_has_pd_prefix(lease));
930
d8ec95c7
YW
931 for (unsigned i = 0; i < 2; i++) {
932 assert_se(sd_dhcp6_lease_address_iterator_reset(lease));
933 assert_se(sd_dhcp6_lease_get_address(lease, &addr) >= 0);
934 assert_se(sd_dhcp6_lease_get_address_lifetime(lease, &lt_pref, &lt_valid) >= 0);
935 assert_se(in6_addr_equal(&addr, &ia_na_address1));
936 assert_se(lt_pref == 150 * USEC_PER_SEC);
937 assert_se(lt_valid == 180 * USEC_PER_SEC);
938 assert_se(sd_dhcp6_lease_address_iterator_next(lease));
939 assert_se(sd_dhcp6_lease_get_address(lease, &addr) >= 0);
940 assert_se(sd_dhcp6_lease_get_address_lifetime(lease, &lt_pref, &lt_valid) >= 0);
941 assert_se(in6_addr_equal(&addr, &ia_na_address2));
942 assert_se(lt_pref == 150 * USEC_PER_SEC);
943 assert_se(lt_valid == 180 * USEC_PER_SEC);
944 assert_se(!sd_dhcp6_lease_address_iterator_next(lease));
945
946 assert_se(sd_dhcp6_lease_pd_iterator_reset(lease));
947 assert_se(sd_dhcp6_lease_get_pd_prefix(lease, &addr, &prefixlen) >= 0);
948 assert_se(sd_dhcp6_lease_get_pd_lifetime(lease, &lt_pref, &lt_valid) >= 0);
949 assert_se(in6_addr_equal(&addr, &ia_pd_prefix1));
950 assert_se(prefixlen == 64);
951 assert_se(lt_pref == 150 * USEC_PER_SEC);
952 assert_se(lt_valid == 180 * USEC_PER_SEC);
953 assert_se(sd_dhcp6_lease_pd_iterator_next(lease));
954 assert_se(sd_dhcp6_lease_get_pd_prefix(lease, &addr, &prefixlen) >= 0);
955 assert_se(sd_dhcp6_lease_get_pd_lifetime(lease, &lt_pref, &lt_valid) >= 0);
956 assert_se(in6_addr_equal(&addr, &ia_pd_prefix2));
957 assert_se(prefixlen == 64);
958 assert_se(lt_pref == 150 * USEC_PER_SEC);
959 assert_se(lt_valid == 180 * USEC_PER_SEC);
960 assert_se(!sd_dhcp6_lease_pd_iterator_next(lease));
961 }
5e256ea7 962
1f280191 963 test_lease_common(client);
5e256ea7
PF
964}
965
1f280191
YW
966static void test_client_callback(sd_dhcp6_client *client, int event, void *userdata) {
967 switch (event) {
968 case SD_DHCP6_CLIENT_EVENT_STOP:
969 log_debug("/* %s (event=stop) */", __func__);
970 return;
2ea8857e 971
1f280191
YW
972 case SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST:
973 log_debug("/* %s (event=information-request) */", __func__);
3bc424a3 974
1f280191 975 assert_se(test_client_sent_message_count == 1);
3bc424a3 976
1f280191 977 test_lease_common(client);
2ea8857e 978
1f280191
YW
979 assert_se(sd_dhcp6_client_set_information_request(client, false) >= 0);
980 assert_se(sd_dhcp6_client_start(client) >= 0);
981 assert_se(dhcp6_client_set_transaction_id(client, ((const DHCP6Message*) msg_advertise)->transaction_id) >= 0);
982 break;
2ea8857e 983
1f280191
YW
984 case SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE:
985 log_debug("/* %s (event=ip-acquire) */", __func__);
2ea8857e 986
b895aa5f 987 assert_se(IN_SET(test_client_sent_message_count, 3, 5));
2ea8857e 988
1f280191 989 test_lease_managed(client);
2ea8857e 990
119c00c1
YW
991 switch (test_client_sent_message_count) {
992 case 3:
993 assert_se(sd_dhcp6_client_stop(client) >= 0);
994 assert_se(sd_dhcp6_client_start(client) >= 0);
995 assert_se(dhcp6_client_set_transaction_id(client, ((const DHCP6Message*) msg_reply)->transaction_id) >= 0);
996 break;
997
b895aa5f 998 case 5:
119c00c1
YW
999 assert_se(sd_event_exit(sd_dhcp6_client_get_event(client), 0) >= 0);
1000 break;
1001
1002 default:
1003 assert_not_reached();
1004 }
1005
1f280191 1006 break;
5e256ea7 1007
1f280191
YW
1008 case DHCP6_CLIENT_EVENT_TEST_ADVERTISED: {
1009 sd_dhcp6_lease *lease;
1010 uint8_t preference;
d63be95a 1011
1f280191 1012 log_debug("/* %s (event=test-advertised) */", __func__);
d63be95a 1013
1f280191 1014 assert_se(test_client_sent_message_count == 2);
d63be95a 1015
1f280191 1016 test_lease_managed(client);
8006aa32 1017
1f280191
YW
1018 assert_se(sd_dhcp6_client_get_lease(client, &lease) >= 0);
1019 assert_se(dhcp6_lease_get_preference(lease, &preference) >= 0);
1020 assert_se(preference == 0xff);
8006aa32 1021
1f280191
YW
1022 assert_se(dhcp6_client_set_transaction_id(client, ((const DHCP6Message*) msg_reply)->transaction_id) >= 0);
1023 break;
2ea8857e 1024 }
1f280191
YW
1025 default:
1026 assert_not_reached();
c4e8cedd 1027 }
c4e8cedd
PF
1028}
1029
1f280191
YW
1030int dhcp6_network_send_udp_socket(int s, struct in6_addr *a, const void *packet, size_t len) {
1031 log_debug("/* %s(count=%u) */", __func__, test_client_sent_message_count);
2ea8857e 1032
1f280191
YW
1033 assert_se(a);
1034 assert_se(in6_addr_equal(a, &mcast_address));
2ea8857e 1035 assert_se(packet);
1f280191
YW
1036 assert_se(len >= sizeof(DHCP6Message));
1037
1038 switch (test_client_sent_message_count) {
1039 case 0:
1040 test_client_verify_information_request(packet, len);
1041 assert_se(write(test_fd[1], msg_reply, sizeof(msg_reply)) == sizeof(msg_reply));
1042 break;
1043
1044 case 1:
1045 test_client_verify_solicit(packet, len);
1046 assert_se(write(test_fd[1], msg_advertise, sizeof(msg_advertise)) == sizeof(msg_advertise));
1047 break;
1048
1049 case 2:
1050 test_client_callback(client_ref, DHCP6_CLIENT_EVENT_TEST_ADVERTISED, NULL);
1051 test_client_verify_request(packet, len);
1052 assert_se(write(test_fd[1], msg_reply, sizeof(msg_reply)) == sizeof(msg_reply));
1053 break;
1054
119c00c1 1055 case 3:
b895aa5f 1056 test_client_verify_release(packet, len);
1057 /* when stopping, dhcp6 client doesn't wait for release server reply */
1058 assert_se(write(test_fd[1], msg_reply, sizeof(msg_reply)) == sizeof(msg_reply));
1059 break;
1060
1061 case 4:
119c00c1
YW
1062 test_client_verify_solicit(packet, len);
1063 assert_se(write(test_fd[1], msg_reply, sizeof(msg_reply)) == sizeof(msg_reply));
1064 break;
1065
1f280191
YW
1066 default:
1067 assert_not_reached();
5e256ea7 1068 }
2ea8857e 1069
1f280191 1070 test_client_sent_message_count++;
2ea8857e
PF
1071 return len;
1072}
1073
1f280191 1074int dhcp6_network_bind_udp_socket(int ifindex, struct in6_addr *a) {
1a6c9136 1075 assert_se(ifindex == test_ifindex);
1f280191
YW
1076 assert_se(a);
1077 assert_se(in6_addr_equal(a, &local_address));
da6fe470 1078
1f280191
YW
1079 assert_se(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) >= 0);
1080 return TAKE_FD(test_fd[0]);
2ea8857e
PF
1081}
1082
68da8adf 1083TEST(dhcp6_client) {
1f280191
YW
1084 _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
1085 _cleanup_(sd_event_unrefp) sd_event *e = NULL;
2ea8857e 1086
1f280191 1087 assert_se(sd_event_new(&e) >= 0);
ba4e0427 1088 assert_se(sd_event_add_time_relative(e, NULL, CLOCK_BOOTTIME,
1f280191 1089 2 * USEC_PER_SEC, 0,
2e37084f 1090 NULL, INT_TO_PTR(-ETIMEDOUT)) >= 0);
2ea8857e 1091
1f280191 1092 assert_se(sd_dhcp6_client_new(&client) >= 0);
2ea8857e 1093 assert_se(sd_dhcp6_client_attach_event(client, e, 0) >= 0);
1a6c9136 1094 assert_se(sd_dhcp6_client_set_ifindex(client, test_ifindex) == 0);
1f280191
YW
1095 assert_se(sd_dhcp6_client_set_local_address(client, &local_address) >= 0);
1096 assert_se(sd_dhcp6_client_set_fqdn(client, "host.lab.intra") >= 0);
1097 assert_se(sd_dhcp6_client_set_iaid(client, unaligned_read_be32((uint8_t[]) { IA_ID_BYTES })) >= 0);
b895aa5f 1098 assert_se(sd_dhcp6_client_set_send_release(client, true) >= 0);
2ea8857e 1099
612caa26
YW
1100 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DNS_SERVER) >= 0);
1101 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DOMAIN) >= 0);
1102 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NTP_SERVER) >= 0);
1103 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_SNTP_SERVER) >= 0);
1104
1f280191
YW
1105 assert_se(sd_dhcp6_client_set_information_request(client, true) >= 0);
1106 assert_se(sd_dhcp6_client_set_callback(client, test_client_callback, NULL) >= 0);
c601ebf7 1107
2ea8857e
PF
1108 assert_se(sd_dhcp6_client_start(client) >= 0);
1109
1f280191
YW
1110 assert_se(dhcp6_client_set_transaction_id(client, ((const DHCP6Message*) msg_reply)->transaction_id) >= 0);
1111
1112 assert_se(client_ref = sd_dhcp6_client_ref(client));
2ea8857e 1113
1f280191 1114 assert_se(sd_event_loop(e) >= 0);
2ea8857e 1115
b895aa5f 1116 assert_se(test_client_sent_message_count == 5);
2ea8857e 1117
8306912b 1118 assert_se(!sd_dhcp6_client_unref(client_ref));
1f280191 1119 test_fd[1] = safe_close(test_fd[1]);
2ea8857e
PF
1120}
1121
8b50b319
YW
1122static int intro(void) {
1123 assert_se(setenv("SYSTEMD_NETWORK_TEST_MODE", "1", 1) >= 0);
1124 return 0;
1125}
1126
1127DEFINE_TEST_MAIN_WITH_INTRO(LOG_DEBUG, intro);