1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 Copyright © 2014 Intel Corporation. All rights reserved.
6 #include <net/ethernet.h>
7 #include <net/if_arp.h>
10 #include <sys/types.h>
13 #include "sd-dhcp6-client.h"
16 #include "dhcp-duid-internal.h"
17 #include "dhcp6-internal.h"
18 #include "dhcp6-lease-internal.h"
19 #include "dhcp6-protocol.h"
22 #include "memory-util.h"
23 #include "socket-util.h"
24 #include "string-util.h"
27 #include "time-util.h"
28 #include "unaligned.h"
30 #define DHCP6_CLIENT_EVENT_TEST_ADVERTISED 77
32 0x0e, 0xcf, 0xa3, 0x7d
33 #define IA_NA_ADDRESS1_BYTES \
34 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x78, 0xee, 0x1c, 0xf3, 0x09, 0x3c, 0x55, 0xad
35 #define IA_NA_ADDRESS2_BYTES \
36 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x78, 0xee, 0x1c, 0xf3, 0x09, 0x3c, 0x55, 0xae
37 #define IA_PD_PREFIX1_BYTES \
38 0x2a, 0x02, 0x81, 0x0d, 0x98, 0x80, 0x37, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
39 #define IA_PD_PREFIX2_BYTES \
40 0x2a, 0x02, 0x81, 0x0d, 0x98, 0x80, 0x37, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
42 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
44 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02
46 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03
48 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04
50 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05
52 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06
53 #define CLIENT_ID_BYTES \
54 0x00, 0x02, 0x00, 0x00, 0xab, 0x11, 0x61, 0x77, 0x40, 0xde, 0x13, 0x42, 0xc3, 0xa2
55 #define SERVER_ID_BYTES \
56 0x00, 0x01, 0x00, 0x01, 0x19, 0x40, 0x5c, 0x53, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53
57 #define VENDOR_SUBOPTION_BYTES \
60 static const struct in6_addr local_address
=
61 { { { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, } } };
62 static const struct in6_addr mcast_address
= IN6_ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS
;
63 static const struct in6_addr ia_na_address1
= { { { IA_NA_ADDRESS1_BYTES
} } };
64 static const struct in6_addr ia_na_address2
= { { { IA_NA_ADDRESS2_BYTES
} } };
65 static const struct in6_addr ia_pd_prefix1
= { { { IA_PD_PREFIX1_BYTES
} } };
66 static const struct in6_addr ia_pd_prefix2
= { { { IA_PD_PREFIX2_BYTES
} } };
67 static const struct in6_addr dns1
= { { { DNS1_BYTES
} } };
68 static const struct in6_addr dns2
= { { { DNS2_BYTES
} } };
69 static const struct in6_addr sntp1
= { { { SNTP1_BYTES
} } };
70 static const struct in6_addr sntp2
= { { { SNTP2_BYTES
} } };
71 static const struct in6_addr ntp1
= { { { NTP1_BYTES
} } };
72 static const struct in6_addr ntp2
= { { { NTP2_BYTES
} } };
73 static const uint8_t client_id
[] = { CLIENT_ID_BYTES
};
74 static const uint8_t server_id
[] = { SERVER_ID_BYTES
};
75 static uint8_t vendor_suboption_data
[] = { VENDOR_SUBOPTION_BYTES
};
76 static const struct ether_addr mac
= {
77 .ether_addr_octet
= { 'A', 'B', 'C', '1', '2', '3' },
79 static int test_fd
[2] = EBADF_PAIR
;
80 static sd_dhcp6_option vendor_suboption
= {
82 .enterprise_identifier
= 32,
84 .data
= vendor_suboption_data
,
87 static int test_ifindex
= 42;
88 static unsigned test_client_sent_message_count
= 0;
89 static sd_dhcp6_client
*client_ref
= NULL
;
92 _cleanup_(sd_dhcp6_client_unrefp
) sd_dhcp6_client
*client
= NULL
;
95 assert_se(sd_dhcp6_client_new(&client
) >= 0);
98 assert_se(sd_dhcp6_client_set_ifindex(client
, 15) == 0);
99 assert_se(sd_dhcp6_client_set_ifindex(client
, 42) >= 0);
101 assert_se(sd_dhcp6_client_set_mac(client
, mac
.ether_addr_octet
, sizeof(mac
), ARPHRD_ETHER
) >= 0);
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
);
109 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_CLIENTID
) == -EINVAL
);
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);
113 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_VENDOR_OPTS
) >= 0);
114 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_DOMAIN
) >= 0);
115 assert_se(sd_dhcp6_client_set_request_option(client
, 10) == -EINVAL
);
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);
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
);
121 assert_se(sd_dhcp6_client_set_information_request(client
, 1) >= 0);
123 assert_se(sd_dhcp6_client_get_information_request(client
, &v
) >= 0);
125 assert_se(sd_dhcp6_client_set_information_request(client
, 0) >= 0);
127 assert_se(sd_dhcp6_client_get_information_request(client
, &v
) >= 0);
131 assert_se(sd_dhcp6_client_get_address_request(client
, &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);
138 assert_se(sd_dhcp6_client_set_address_request(client
, 1) >= 0);
139 assert_se(sd_dhcp6_client_get_address_request(client
, &v
) >= 0);
142 assert_se(sd_dhcp6_client_set_address_request(client
, 1) >= 0);
143 assert_se(sd_dhcp6_client_set_prefix_delegation(client
, 1) >= 0);
145 assert_se(sd_dhcp6_client_get_address_request(client
, &v
) >= 0);
148 assert_se(sd_dhcp6_client_get_prefix_delegation(client
, &v
) >= 0);
151 assert_se(sd_dhcp6_client_set_callback(client
, NULL
, NULL
) >= 0);
153 assert_se(sd_dhcp6_client_detach_event(client
) >= 0);
157 _cleanup_free_
char *domain
= NULL
;
158 _cleanup_strv_free_
char **list
= NULL
;
161 data
= (uint8_t []) { 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0 };
162 assert_se(dhcp6_option_parse_domainname(data
, 13, &domain
) >= 0);
164 assert_se(streq(domain
, "example.com"));
165 domain
= mfree(domain
);
167 data
= (uint8_t []) { 4, 't', 'e', 's', 't' };
168 assert_se(dhcp6_option_parse_domainname(data
, 5, &domain
) >= 0);
170 assert_se(streq(domain
, "test"));
171 domain
= mfree(domain
);
173 data
= (uint8_t []) { 0 };
174 assert_se(dhcp6_option_parse_domainname(data
, 1, &domain
) < 0);
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 };
178 assert_se(dhcp6_option_parse_domainname_list(data
, 21, &list
) >= 0);
180 assert_se(streq(list
[0], "example.com"));
181 assert_se(streq(list
[1], "foobar"));
183 list
= strv_free(list
);
185 data
= (uint8_t []) { 1, 'a', 0, 20, 'b', 'c' };
186 assert_se(dhcp6_option_parse_domainname_list(data
, 6, &list
) < 0);
188 data
= (uint8_t []) { 0 , 0 };
189 assert_se(dhcp6_option_parse_domainname_list(data
, 2, &list
) < 0);
193 static const uint8_t packet
[] = {
194 'F', 'O', 'O', 'H', 'O', 'G', 'E',
195 0x00, SD_DHCP6_OPTION_ORO
, 0x00, 0x07,
196 'A', 'B', 'C', 'D', 'E', 'F', 'G',
197 0x00, SD_DHCP6_OPTION_VENDOR_CLASS
, 0x00, 0x09,
198 '1', '2', '3', '4', '5', '6', '7', '8', '9',
201 static const uint8_t result
[] = {
202 'F', 'O', 'O', 'H', 'O', 'G', 'E',
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,
208 _cleanup_free_
uint8_t *buf
= NULL
;
209 size_t offset
, pos
, optlen
;
210 const uint8_t *optval
;
213 assert_se(sizeof(packet
) == sizeof(result
));
216 assert_se(dhcp6_option_parse(packet
, 0, &offset
, &optcode
, &optlen
, &optval
) == -EBADMSG
);
219 assert_se(dhcp6_option_parse(packet
, 0, &offset
, &optcode
, &optlen
, &optval
) == -EBADMSG
);
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
);
226 assert_se(dhcp6_option_parse(buf
, sizeof(packet
), &offset
, &optcode
, &optlen
, &optval
) >= 0);
228 assert_se(optcode
== SD_DHCP6_OPTION_ORO
);
229 assert_se(optlen
== 7);
230 assert_se(optval
== buf
+ 11 - i
);
234 assert_se(dhcp6_option_parse(packet
, sizeof(packet
), &offset
, &optcode
, &optlen
, &optval
) >= 0);
236 assert_se(optcode
== SD_DHCP6_OPTION_ORO
);
237 assert_se(optlen
== 7);
238 assert_se(optval
== packet
+ 11);
241 assert_se(buf
= memdup(result
, sizeof(result
)));
243 assert_se(dhcp6_option_append(&buf
, &pos
, optcode
, optlen
, optval
) >= 0);
245 assert_se(dhcp6_option_parse(packet
, sizeof(packet
), &offset
, &optcode
, &optlen
, &optval
) >= 0);
247 assert_se(optcode
== SD_DHCP6_OPTION_VENDOR_CLASS
);
248 assert_se(optlen
== 9);
249 assert_se(optval
== packet
+ 22);
251 assert_se(dhcp6_option_append(&buf
, &pos
, optcode
, optlen
, optval
) >= 0);
253 assert_se(memcmp(packet
, buf
, sizeof(packet
)) == 0);
256 TEST(option_status
) {
257 uint8_t option1
[] = {
259 0x00, 0x03, 0x00, 0x12, 0x1a, 0x1d, 0x1a, 0x1d,
260 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02,
262 0x00, 0x0d, 0x00, 0x02, 0x00, 0x01,
264 static const uint8_t option2
[] = {
266 0x00, 0x03, 0x00, 0x2e, 0x1a, 0x1d, 0x1a, 0x1d,
267 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02,
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,
273 /* IA address status option */
274 0x00, 0x0d, 0x00, 0x02, 0x00, 0x01,
276 static const uint8_t option3
[] = {
278 0x00, 0x03, 0x00, 0x34, 0x1a, 0x1d, 0x1a, 0x1d,
279 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02,
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,
285 /* IA address status option */
286 0x00, 0x0d, 0x00, 0x08, 0x00, 0x00, 'f', 'o',
289 static const uint8_t option4
[] = {
291 0x00, 0x19, 0x00, 0x2f, 0x1a, 0x1d, 0x1a, 0x1d,
292 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02,
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,
299 /* PD prefix status option */
300 0x00, 0x0d, 0x00, 0x02, 0x00, 0x00,
302 static const uint8_t option5
[] = {
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,
312 /* PD prefix status option */
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,
320 /* PD prefix status option */
321 0x00, 0x0d, 0x00, 0x02, 0x00, 0x00,
323 _cleanup_(dhcp6_ia_freep
) DHCP6IA
*ia
= NULL
;
328 memcpy(&iaid
, option1
+ 4, sizeof(iaid
));
330 option
= (DHCP6Option
*) option1
;
331 assert_se(sizeof(option1
) == sizeof(DHCP6Option
) + be16toh(option
->len
));
333 r
= dhcp6_option_parse_ia(NULL
, 0, be16toh(option
->code
), be16toh(option
->len
), option
->data
, &ia
);
334 assert_se(r
== -ENOANO
);
336 r
= dhcp6_option_parse_ia(NULL
, iaid
, be16toh(option
->code
), be16toh(option
->len
), option
->data
, &ia
);
337 assert_se(r
== -EINVAL
);
339 option
->len
= htobe16(17);
340 r
= dhcp6_option_parse_ia(NULL
, iaid
, be16toh(option
->code
), be16toh(option
->len
), option
->data
, &ia
);
341 assert_se(r
== -EBADMSG
);
343 option
->len
= htobe16(sizeof(DHCP6Option
));
344 r
= dhcp6_option_parse_ia(NULL
, iaid
, be16toh(option
->code
), be16toh(option
->len
), option
->data
, &ia
);
345 assert_se(r
== -EBADMSG
);
347 option
= (DHCP6Option
*) option2
;
348 assert_se(sizeof(option2
) == sizeof(DHCP6Option
) + be16toh(option
->len
));
349 r
= dhcp6_option_parse_ia(NULL
, iaid
, be16toh(option
->code
), be16toh(option
->len
), option
->data
, &ia
);
350 assert_se(r
== -ENODATA
);
352 option
= (DHCP6Option
*) option3
;
353 assert_se(sizeof(option3
) == sizeof(DHCP6Option
) + be16toh(option
->len
));
354 r
= dhcp6_option_parse_ia(NULL
, iaid
, be16toh(option
->code
), be16toh(option
->len
), option
->data
, &ia
);
357 assert_se(ia
->addresses
);
358 ia
= dhcp6_ia_free(ia
);
360 option
= (DHCP6Option
*) option4
;
361 assert_se(sizeof(option4
) == sizeof(DHCP6Option
) + be16toh(option
->len
));
362 r
= dhcp6_option_parse_ia(NULL
, iaid
, be16toh(option
->code
), be16toh(option
->len
), option
->data
, &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
);
371 option
= (DHCP6Option
*) option5
;
372 assert_se(sizeof(option5
) == sizeof(DHCP6Option
) + be16toh(option
->len
));
373 r
= dhcp6_option_parse_ia(NULL
, iaid
, be16toh(option
->code
), be16toh(option
->len
), option
->data
, &ia
);
376 assert_se(ia
->addresses
);
377 ia
= dhcp6_ia_free(ia
);
380 TEST(client_parse_message_issue_22099
) {
381 static const uint8_t msg
[] = {
387 0x00, SD_DHCP6_OPTION_RAPID_COMMIT
, 0x00, 0x00,
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,
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 */
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 */
404 0x00, SD_DHCP6_OPTION_PREFERENCE
, 0x00, 0x01,
407 0x00, SD_DHCP6_OPTION_DNS_SERVER
, 0x00, 0x10,
408 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0x15, 0xc8, 0xff, 0xfe, 0xef, 0x1e, 0x4e,
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,
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 */
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 */
434 static const uint8_t duid
[] = {
435 0x00, 0x00, 0xab, 0x11, 0x5c, 0x6b, 0x90, 0xec, 0xda, 0x95, 0x15, 0x45,
437 _cleanup_(sd_dhcp6_client_unrefp
) sd_dhcp6_client
*client
= NULL
;
438 _cleanup_(sd_dhcp6_lease_unrefp
) sd_dhcp6_lease
*lease
= NULL
;
440 assert_se(sd_dhcp6_client_new(&client
) >= 0);
441 assert_se(sd_dhcp6_client_set_iaid(client
, 0xcc59117b) >= 0);
442 assert_se(sd_dhcp6_client_set_duid_raw(client
, 2, duid
, sizeof(duid
)) >= 0);
444 assert_se(dhcp6_lease_new_from_message(client
, (const DHCP6Message
*) msg
, sizeof(msg
), NULL
, NULL
, &lease
) >= 0);
447 TEST(client_parse_message_issue_24002
) {
448 static const uint8_t msg
[] = {
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 */
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,
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 */
474 0x00, 0x0e, 0x00, 0x00,
475 /* Trailing invalid byte at the end. See issue #28183. */
478 static const uint8_t duid
[] = {
479 0x00, 0x00, 0xab, 0x11, 0x5c, 0x6b, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
481 _cleanup_(sd_dhcp6_client_unrefp
) sd_dhcp6_client
*client
= NULL
;
482 _cleanup_(sd_dhcp6_lease_unrefp
) sd_dhcp6_lease
*lease
= NULL
;
484 assert_se(sd_dhcp6_client_new(&client
) >= 0);
485 assert_se(sd_dhcp6_client_set_iaid(client
, 0xaabbccdd) >= 0);
486 assert_se(sd_dhcp6_client_set_duid_raw(client
, 2, duid
, sizeof(duid
)) >= 0);
488 assert_se(dhcp6_lease_new_from_message(client
, (const DHCP6Message
*) msg
, sizeof(msg
), NULL
, NULL
, &lease
) >= 0);
491 static const uint8_t msg_information_request
[] = {
493 DHCP6_MESSAGE_INFORMATION_REQUEST
,
498 0x00, SD_DHCP6_OPTION_ORO
, 0x00, 0x0c,
499 0x00, SD_DHCP6_OPTION_DNS_SERVER
,
500 0x00, SD_DHCP6_OPTION_DOMAIN
,
501 0x00, SD_DHCP6_OPTION_SNTP_SERVER
,
502 0x00, SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME
,
503 0x00, SD_DHCP6_OPTION_NTP_SERVER
,
504 0x00, SD_DHCP6_OPTION_INF_MAX_RT
,
506 0x00, SD_DHCP6_OPTION_CLIENTID
, 0x00, 0x0e,
510 0x00, SD_DHCP6_OPTION_ELAPSED_TIME
, 0x00, 0x02,
514 static const uint8_t msg_solicit
[] = {
516 DHCP6_MESSAGE_SOLICIT
,
520 0x00, SD_DHCP6_OPTION_RAPID_COMMIT
, 0x00, 0x00,
522 0x00, SD_DHCP6_OPTION_IA_NA
, 0x00, 0x0c,
524 0x00, 0x00, 0x00, 0x00, /* lifetime T1 */
525 0x00, 0x00, 0x00, 0x00, /* lifetime T2 */
527 0x00, SD_DHCP6_OPTION_IA_PD
, 0x00, 0x0c,
529 0x00, 0x00, 0x00, 0x00, /* lifetime T1 */
530 0x00, 0x00, 0x00, 0x00, /* lifetime T2 */
532 0x00, SD_DHCP6_OPTION_CLIENT_FQDN
, 0x00, 0x11,
534 0x04, 'h', 'o', 's', 't', 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
540 0x00, SD_DHCP6_OPTION_ORO
, 0x00, 0x0a,
541 0x00, SD_DHCP6_OPTION_DNS_SERVER
,
542 0x00, SD_DHCP6_OPTION_DOMAIN
,
543 0x00, SD_DHCP6_OPTION_SNTP_SERVER
,
544 0x00, SD_DHCP6_OPTION_NTP_SERVER
,
545 0x00, SD_DHCP6_OPTION_SOL_MAX_RT
,
547 0x00, SD_DHCP6_OPTION_CLIENTID
, 0x00, 0x0e,
551 0x00, SD_DHCP6_OPTION_ELAPSED_TIME
, 0x00, 0x02,
555 static const uint8_t msg_request
[] = {
557 DHCP6_MESSAGE_REQUEST
,
561 0x00, SD_DHCP6_OPTION_SERVERID
, 0x00, 0x0e,
564 0x00, SD_DHCP6_OPTION_IA_NA
, 0x00, 0x44,
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 */
579 0x00, SD_DHCP6_OPTION_IA_PD
, 0x00, 0x46,
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 */
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 */
596 0x00, SD_DHCP6_OPTION_CLIENT_FQDN
, 0x00, 0x11,
598 0x04, 'h', 'o', 's', 't', 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
604 0x00, SD_DHCP6_OPTION_ORO
, 0x00, 0x08,
605 0x00, SD_DHCP6_OPTION_DNS_SERVER
,
606 0x00, SD_DHCP6_OPTION_DOMAIN
,
607 0x00, SD_DHCP6_OPTION_SNTP_SERVER
,
608 0x00, SD_DHCP6_OPTION_NTP_SERVER
,
610 0x00, SD_DHCP6_OPTION_CLIENTID
, 0x00, 0x0e,
614 0x00, SD_DHCP6_OPTION_ELAPSED_TIME
, 0x00, 0x02,
618 /* RFC 3315 section 18.1.6. The DHCP6 Release message must include:
622 - all released IA with addresses included
623 - elapsed time (required for all messages).
624 All other options aren't required. */
625 static const uint8_t msg_release
[] = {
627 DHCP6_MESSAGE_RELEASE
,
631 0x00, SD_DHCP6_OPTION_SERVERID
, 0x00, 0x0e,
634 0x00, SD_DHCP6_OPTION_IA_NA
, 0x00, 0x44,
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 */
649 0x00, SD_DHCP6_OPTION_IA_PD
, 0x00, 0x46,
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 */
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 */
666 0x00, SD_DHCP6_OPTION_CLIENTID
, 0x00, 0x0e,
670 0x00, SD_DHCP6_OPTION_ELAPSED_TIME
, 0x00, 0x02,
674 static const uint8_t msg_reply
[] = {
680 0x00, SD_DHCP6_OPTION_CLIENTID
, 0x00, 0x0e,
683 0x00, SD_DHCP6_OPTION_SERVERID
, 0x00, 0x0e,
686 0x00, SD_DHCP6_OPTION_RAPID_COMMIT
, 0x00, 0x01,
689 0x00, SD_DHCP6_OPTION_IA_NA
, 0x00, 0x66,
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 */
709 0x00, SD_DHCP6_OPTION_IA_PD
, 0x00, 0x46,
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 */
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 */
726 0x00, SD_DHCP6_OPTION_DNS_SERVER
, 0x00, 0x20,
730 0x00, SD_DHCP6_OPTION_SNTP_SERVER
, 0x00, 0x20,
734 0x00, SD_DHCP6_OPTION_NTP_SERVER
, 0x00, 0x37,
735 /* NTP server (address suboption) */
736 0x00, DHCP6_NTP_SUBOPTION_SRV_ADDR
, 0x00, 0x10,
738 /* NTP server (address suboption) */
739 0x00, DHCP6_NTP_SUBOPTION_SRV_ADDR
, 0x00, 0x10,
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,
745 0x00, SD_DHCP6_OPTION_DOMAIN
, 0x00, 0x0b,
746 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
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',
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
,
755 static const uint8_t msg_advertise
[] = {
757 DHCP6_MESSAGE_ADVERTISE
,
761 0x00, SD_DHCP6_OPTION_CLIENTID
, 0x00, 0x0e,
764 0x00, SD_DHCP6_OPTION_SERVERID
, 0x00, 0x0e,
767 0x00, SD_DHCP6_OPTION_PREFERENCE
, 0x00, 0x01,
770 0x00, SD_DHCP6_OPTION_IA_NA
, 0x00, 0x7a,
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 */
791 0x00, SD_DHCP6_OPTION_IA_PD
, 0x00, 0x46,
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 */
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 */
808 0x00, SD_DHCP6_OPTION_DNS_SERVER
, 0x00, 0x20,
812 0x00, SD_DHCP6_OPTION_SNTP_SERVER
, 0x00, 0x20,
816 0x00, SD_DHCP6_OPTION_NTP_SERVER
, 0x00, 0x37,
817 /* NTP server (address suboption) */
818 0x00, DHCP6_NTP_SUBOPTION_SRV_ADDR
, 0x00, 0x10,
820 /* NTP server (address suboption) */
821 0x00, DHCP6_NTP_SUBOPTION_SRV_ADDR
, 0x00, 0x10,
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,
827 0x00, SD_DHCP6_OPTION_DOMAIN
, 0x00, 0x0b,
828 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
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',
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
,
837 static void test_client_verify_information_request(const DHCP6Message
*msg
, size_t len
) {
838 log_debug("/* %s */", __func__
);
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);
845 static void test_client_verify_solicit(const DHCP6Message
*msg
, size_t len
) {
846 log_debug("/* %s */", __func__
);
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);
853 static void test_client_verify_release(const DHCP6Message
*msg
, size_t len
) {
854 log_debug("/* %s */", __func__
);
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);
863 static void test_client_verify_request(const DHCP6Message
*msg
, size_t len
) {
864 log_debug("/* %s */", __func__
);
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. */
869 assert_se(memcmp(msg
->options
, msg_request
+ offsetof(DHCP6Message
, options
),
870 len
- offsetof(DHCP6Message
, options
) - sizeof(be16_t
)) == 0);
873 static void test_lease_common(sd_dhcp6_client
*client
) {
874 sd_dhcp6_lease
*lease
;
875 sd_dhcp6_option
**suboption
;
876 const struct in6_addr
*addrs
;
882 assert_se(sd_dhcp6_client_get_lease(client
, &lease
) >= 0);
884 assert_se(dhcp6_lease_get_clientid(lease
, &id
, &len
) >= 0);
885 assert_se(memcmp_nn(id
, len
, client_id
, sizeof(client_id
)) == 0);
887 assert_se(sd_dhcp6_lease_get_domains(lease
, &strv
) == 1);
888 assert_se(streq(strv
[0], "lab.intra"));
891 assert_se(sd_dhcp6_lease_get_fqdn(lease
, &str
) >= 0);
892 assert_se(streq(str
, "client.lab.intra"));
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
));
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
));
902 assert_se(sd_dhcp6_lease_get_ntp_fqdn(lease
, &strv
) == 1);
903 assert_se(streq(strv
[0], "ntp.intra"));
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
));
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
);
916 static void test_lease_managed(sd_dhcp6_client
*client
) {
917 sd_dhcp6_lease
*lease
;
918 struct in6_addr addr
;
919 usec_t lt_pref
, lt_valid
;
920 uint8_t *id
, prefixlen
;
923 assert_se(sd_dhcp6_client_get_lease(client
, &lease
) >= 0);
925 assert_se(dhcp6_lease_get_serverid(lease
, &id
, &len
) >= 0);
926 assert_se(memcmp_nn(id
, len
, server_id
, sizeof(server_id
)) == 0);
928 assert_se(sd_dhcp6_lease_has_address(lease
));
929 assert_se(sd_dhcp6_lease_has_pd_prefix(lease
));
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
, <_pref
, <_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
, <_pref
, <_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
));
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
, <_pref
, <_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
, <_pref
, <_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
));
963 test_lease_common(client
);
966 static void test_client_callback(sd_dhcp6_client
*client
, int event
, void *userdata
) {
968 case SD_DHCP6_CLIENT_EVENT_STOP
:
969 log_debug("/* %s (event=stop) */", __func__
);
972 case SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST
:
973 log_debug("/* %s (event=information-request) */", __func__
);
975 assert_se(test_client_sent_message_count
== 1);
977 test_lease_common(client
);
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);
984 case SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE
:
985 log_debug("/* %s (event=ip-acquire) */", __func__
);
987 assert_se(IN_SET(test_client_sent_message_count
, 3, 5));
989 test_lease_managed(client
);
991 switch (test_client_sent_message_count
) {
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);
999 assert_se(sd_event_exit(sd_dhcp6_client_get_event(client
), 0) >= 0);
1003 assert_not_reached();
1008 case DHCP6_CLIENT_EVENT_TEST_ADVERTISED
: {
1009 sd_dhcp6_lease
*lease
;
1012 log_debug("/* %s (event=test-advertised) */", __func__
);
1014 assert_se(test_client_sent_message_count
== 2);
1016 test_lease_managed(client
);
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);
1022 assert_se(dhcp6_client_set_transaction_id(client
, ((const DHCP6Message
*) msg_reply
)->transaction_id
) >= 0);
1026 assert_not_reached();
1030 int dhcp6_network_send_udp_socket(int s
, const struct in6_addr
*a
, const void *packet
, size_t len
) {
1031 log_debug("/* %s(count=%u) */", __func__
, test_client_sent_message_count
);
1034 assert_se(in6_addr_equal(a
, &mcast_address
));
1036 assert_se(len
>= sizeof(DHCP6Message
));
1038 switch (test_client_sent_message_count
) {
1040 test_client_verify_information_request(packet
, len
);
1041 assert_se(write(test_fd
[1], msg_reply
, sizeof(msg_reply
)) == sizeof(msg_reply
));
1045 test_client_verify_solicit(packet
, len
);
1046 assert_se(write(test_fd
[1], msg_advertise
, sizeof(msg_advertise
)) == sizeof(msg_advertise
));
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
));
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
));
1062 test_client_verify_solicit(packet
, len
);
1063 assert_se(write(test_fd
[1], msg_reply
, sizeof(msg_reply
)) == sizeof(msg_reply
));
1067 assert_not_reached();
1070 test_client_sent_message_count
++;
1074 int dhcp6_network_bind_udp_socket(int ifindex
, const struct in6_addr
*a
) {
1075 assert_se(ifindex
== test_ifindex
);
1077 assert_se(in6_addr_equal(a
, &local_address
));
1079 assert_se(socketpair(AF_UNIX
, SOCK_STREAM
| SOCK_CLOEXEC
| SOCK_NONBLOCK
, 0, test_fd
) >= 0);
1080 return TAKE_FD(test_fd
[0]);
1083 TEST(dhcp6_client
) {
1084 _cleanup_(sd_dhcp6_client_unrefp
) sd_dhcp6_client
*client
= NULL
;
1085 _cleanup_(sd_event_unrefp
) sd_event
*e
= NULL
;
1087 assert_se(sd_event_new(&e
) >= 0);
1088 assert_se(sd_event_add_time_relative(e
, NULL
, CLOCK_BOOTTIME
,
1089 2 * USEC_PER_SEC
, 0,
1090 NULL
, INT_TO_PTR(-ETIMEDOUT
)) >= 0);
1092 assert_se(sd_dhcp6_client_new(&client
) >= 0);
1093 assert_se(sd_dhcp6_client_attach_event(client
, e
, 0) >= 0);
1094 assert_se(sd_dhcp6_client_set_ifindex(client
, test_ifindex
) == 0);
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);
1098 assert_se(sd_dhcp6_client_set_send_release(client
, true) >= 0);
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);
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);
1108 assert_se(sd_dhcp6_client_start(client
) >= 0);
1110 assert_se(dhcp6_client_set_transaction_id(client
, ((const DHCP6Message
*) msg_reply
)->transaction_id
) >= 0);
1112 assert_se(client_ref
= sd_dhcp6_client_ref(client
));
1114 assert_se(sd_event_loop(e
) >= 0);
1116 assert_se(test_client_sent_message_count
== 5);
1118 assert_se(!sd_dhcp6_client_unref(client_ref
));
1119 test_fd
[1] = safe_close(test_fd
[1]);
1122 static int intro(void) {
1123 assert_se(setenv("SYSTEMD_NETWORK_TEST_MODE", "1", 1) >= 0);
1127 DEFINE_TEST_MAIN_WITH_INTRO(LOG_DEBUG
, intro
);