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
=
63 IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT
;
64 static const struct in6_addr ia_na_address1
= { { { IA_NA_ADDRESS1_BYTES
} } };
65 static const struct in6_addr ia_na_address2
= { { { IA_NA_ADDRESS2_BYTES
} } };
66 static const struct in6_addr ia_pd_prefix1
= { { { IA_PD_PREFIX1_BYTES
} } };
67 static const struct in6_addr ia_pd_prefix2
= { { { IA_PD_PREFIX2_BYTES
} } };
68 static const struct in6_addr dns1
= { { { DNS1_BYTES
} } };
69 static const struct in6_addr dns2
= { { { DNS2_BYTES
} } };
70 static const struct in6_addr sntp1
= { { { SNTP1_BYTES
} } };
71 static const struct in6_addr sntp2
= { { { SNTP2_BYTES
} } };
72 static const struct in6_addr ntp1
= { { { NTP1_BYTES
} } };
73 static const struct in6_addr ntp2
= { { { NTP2_BYTES
} } };
74 static const uint8_t client_id
[] = { CLIENT_ID_BYTES
};
75 static const uint8_t server_id
[] = { SERVER_ID_BYTES
};
76 static uint8_t vendor_suboption_data
[] = { VENDOR_SUBOPTION_BYTES
};
77 static const struct ether_addr mac
= {
78 .ether_addr_octet
= { 'A', 'B', 'C', '1', '2', '3' },
80 static int test_fd
[2] = EBADF_PAIR
;
81 static sd_dhcp6_option vendor_suboption
= {
83 .enterprise_identifier
= 32,
85 .data
= vendor_suboption_data
,
88 static int test_ifindex
= 42;
89 static unsigned test_client_sent_message_count
= 0;
90 static sd_dhcp6_client
*client_ref
= NULL
;
93 _cleanup_(sd_dhcp6_client_unrefp
) sd_dhcp6_client
*client
= NULL
;
96 assert_se(sd_dhcp6_client_new(&client
) >= 0);
99 assert_se(sd_dhcp6_client_set_ifindex(client
, 15) == 0);
100 assert_se(sd_dhcp6_client_set_ifindex(client
, 42) >= 0);
102 assert_se(sd_dhcp6_client_set_mac(client
, mac
.ether_addr_octet
, sizeof(mac
), ARPHRD_ETHER
) >= 0);
104 assert_se(sd_dhcp6_client_set_fqdn(client
, "host") == 1);
105 assert_se(sd_dhcp6_client_set_fqdn(client
, "host.domain") == 1);
106 assert_se(sd_dhcp6_client_set_fqdn(client
, NULL
) == 1);
107 assert_se(sd_dhcp6_client_set_fqdn(client
, "~host") == -EINVAL
);
108 assert_se(sd_dhcp6_client_set_fqdn(client
, "~host.domain") == -EINVAL
);
110 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_CLIENTID
) == -EINVAL
);
111 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_DNS_SERVER
) >= 0);
112 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_NTP_SERVER
) >= 0);
113 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_SNTP_SERVER
) >= 0);
114 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_VENDOR_OPTS
) >= 0);
115 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_DOMAIN
) >= 0);
116 assert_se(sd_dhcp6_client_set_request_option(client
, 10) == -EINVAL
);
117 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_NIS_SERVER
) >= 0);
118 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_NISP_SERVER
) >= 0);
119 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_NIS_SERVER
) == -EEXIST
);
120 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_NISP_SERVER
) == -EEXIST
);
122 assert_se(sd_dhcp6_client_set_information_request(client
, 1) >= 0);
124 assert_se(sd_dhcp6_client_get_information_request(client
, &v
) >= 0);
126 assert_se(sd_dhcp6_client_set_information_request(client
, 0) >= 0);
128 assert_se(sd_dhcp6_client_get_information_request(client
, &v
) >= 0);
132 assert_se(sd_dhcp6_client_get_address_request(client
, &v
) >= 0);
135 assert_se(sd_dhcp6_client_set_address_request(client
, 1) >= 0);
136 assert_se(sd_dhcp6_client_get_address_request(client
, &v
) >= 0);
139 assert_se(sd_dhcp6_client_set_address_request(client
, 1) >= 0);
140 assert_se(sd_dhcp6_client_get_address_request(client
, &v
) >= 0);
143 assert_se(sd_dhcp6_client_set_address_request(client
, 1) >= 0);
144 assert_se(sd_dhcp6_client_set_prefix_delegation(client
, 1) >= 0);
146 assert_se(sd_dhcp6_client_get_address_request(client
, &v
) >= 0);
149 assert_se(sd_dhcp6_client_get_prefix_delegation(client
, &v
) >= 0);
152 assert_se(sd_dhcp6_client_set_callback(client
, NULL
, NULL
) >= 0);
154 assert_se(sd_dhcp6_client_detach_event(client
) >= 0);
158 _cleanup_free_
char *domain
= NULL
;
159 _cleanup_strv_free_
char **list
= NULL
;
162 data
= (uint8_t []) { 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0 };
163 assert_se(dhcp6_option_parse_domainname(data
, 13, &domain
) >= 0);
165 assert_se(streq(domain
, "example.com"));
166 domain
= mfree(domain
);
168 data
= (uint8_t []) { 4, 't', 'e', 's', 't' };
169 assert_se(dhcp6_option_parse_domainname(data
, 5, &domain
) >= 0);
171 assert_se(streq(domain
, "test"));
172 domain
= mfree(domain
);
174 data
= (uint8_t []) { 0 };
175 assert_se(dhcp6_option_parse_domainname(data
, 1, &domain
) < 0);
177 data
= (uint8_t []) { 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0,
178 6, 'f', 'o', 'o', 'b', 'a', 'r', 0 };
179 assert_se(dhcp6_option_parse_domainname_list(data
, 21, &list
) >= 0);
181 assert_se(streq(list
[0], "example.com"));
182 assert_se(streq(list
[1], "foobar"));
184 list
= strv_free(list
);
186 data
= (uint8_t []) { 1, 'a', 0, 20, 'b', 'c' };
187 assert_se(dhcp6_option_parse_domainname_list(data
, 6, &list
) < 0);
189 data
= (uint8_t []) { 0 , 0 };
190 assert_se(dhcp6_option_parse_domainname_list(data
, 2, &list
) < 0);
194 static const uint8_t packet
[] = {
195 'F', 'O', 'O', 'H', 'O', 'G', 'E',
196 0x00, SD_DHCP6_OPTION_ORO
, 0x00, 0x07,
197 'A', 'B', 'C', 'D', 'E', 'F', 'G',
198 0x00, SD_DHCP6_OPTION_VENDOR_CLASS
, 0x00, 0x09,
199 '1', '2', '3', '4', '5', '6', '7', '8', '9',
202 static const uint8_t result
[] = {
203 'F', 'O', 'O', 'H', 'O', 'G', 'E',
204 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
205 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
206 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
209 _cleanup_free_
uint8_t *buf
= NULL
;
210 size_t offset
, pos
, optlen
;
211 const uint8_t *optval
;
214 assert_se(sizeof(packet
) == sizeof(result
));
217 assert_se(dhcp6_option_parse(packet
, 0, &offset
, &optcode
, &optlen
, &optval
) == -EBADMSG
);
220 assert_se(dhcp6_option_parse(packet
, 0, &offset
, &optcode
, &optlen
, &optval
) == -EBADMSG
);
222 /* Tests for reading unaligned data. */
223 assert_se(buf
= new(uint8_t, sizeof(packet
)));
224 for (size_t i
= 0; i
<= 7; i
++) {
225 memcpy(buf
, packet
+ i
, sizeof(packet
) - i
);
227 assert_se(dhcp6_option_parse(buf
, sizeof(packet
), &offset
, &optcode
, &optlen
, &optval
) >= 0);
229 assert_se(optcode
== SD_DHCP6_OPTION_ORO
);
230 assert_se(optlen
== 7);
231 assert_se(optval
== buf
+ 11 - i
);
235 assert_se(dhcp6_option_parse(packet
, sizeof(packet
), &offset
, &optcode
, &optlen
, &optval
) >= 0);
237 assert_se(optcode
== SD_DHCP6_OPTION_ORO
);
238 assert_se(optlen
== 7);
239 assert_se(optval
== packet
+ 11);
242 assert_se(buf
= memdup(result
, sizeof(result
)));
244 assert_se(dhcp6_option_append(&buf
, &pos
, optcode
, optlen
, optval
) >= 0);
246 assert_se(dhcp6_option_parse(packet
, sizeof(packet
), &offset
, &optcode
, &optlen
, &optval
) >= 0);
248 assert_se(optcode
== SD_DHCP6_OPTION_VENDOR_CLASS
);
249 assert_se(optlen
== 9);
250 assert_se(optval
== packet
+ 22);
252 assert_se(dhcp6_option_append(&buf
, &pos
, optcode
, optlen
, optval
) >= 0);
254 assert_se(memcmp(packet
, buf
, sizeof(packet
)) == 0);
257 TEST(option_status
) {
258 uint8_t option1
[] = {
260 0x00, 0x03, 0x00, 0x12, 0x1a, 0x1d, 0x1a, 0x1d,
261 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02,
263 0x00, 0x0d, 0x00, 0x02, 0x00, 0x01,
265 static const uint8_t option2
[] = {
267 0x00, 0x03, 0x00, 0x2e, 0x1a, 0x1d, 0x1a, 0x1d,
268 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02,
270 0x00, 0x05, 0x00, 0x1e,
271 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
272 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
273 0x01, 0x02, 0x03, 0x04, 0x0a, 0x0b, 0x0c, 0x0d,
274 /* IA address status option */
275 0x00, 0x0d, 0x00, 0x02, 0x00, 0x01,
277 static const uint8_t option3
[] = {
279 0x00, 0x03, 0x00, 0x34, 0x1a, 0x1d, 0x1a, 0x1d,
280 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02,
282 0x00, 0x05, 0x00, 0x24,
283 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
284 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
285 0x01, 0x02, 0x03, 0x04, 0x0a, 0x0b, 0x0c, 0x0d,
286 /* IA address status option */
287 0x00, 0x0d, 0x00, 0x08, 0x00, 0x00, 'f', 'o',
290 static const uint8_t option4
[] = {
292 0x00, 0x19, 0x00, 0x2f, 0x1a, 0x1d, 0x1a, 0x1d,
293 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02,
295 0x00, 0x1a, 0x00, 0x1f,
296 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
297 0x80, 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe,
298 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
300 /* PD prefix status option */
301 0x00, 0x0d, 0x00, 0x02, 0x00, 0x00,
303 static const uint8_t option5
[] = {
305 0x00, 0x19, 0x00, 0x52, 0x1a, 0x1d, 0x1a, 0x1d,
306 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02,
307 /* IA PD Prefix #1 */
308 0x00, 0x1a, 0x00, 0x1f,
309 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
310 0x80, 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe,
311 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
313 /* PD prefix status option */
314 0x00, 0x0d, 0x00, 0x02, 0x00, 0x00,
315 /* IA PD Prefix #2 */
316 0x00, 0x1a, 0x00, 0x1f,
317 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
318 0x80, 0x20, 0x01, 0x0d, 0xb8, 0xc0, 0x0l
, 0xd0,
319 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
321 /* PD prefix status option */
322 0x00, 0x0d, 0x00, 0x02, 0x00, 0x00,
324 _cleanup_(dhcp6_ia_freep
) DHCP6IA
*ia
= NULL
;
329 memcpy(&iaid
, option1
+ 4, sizeof(iaid
));
331 option
= (DHCP6Option
*) option1
;
332 assert_se(sizeof(option1
) == sizeof(DHCP6Option
) + be16toh(option
->len
));
334 r
= dhcp6_option_parse_ia(NULL
, 0, be16toh(option
->code
), be16toh(option
->len
), option
->data
, &ia
);
335 assert_se(r
== -ENOANO
);
337 r
= dhcp6_option_parse_ia(NULL
, iaid
, be16toh(option
->code
), be16toh(option
->len
), option
->data
, &ia
);
338 assert_se(r
== -EINVAL
);
340 option
->len
= htobe16(17);
341 r
= dhcp6_option_parse_ia(NULL
, iaid
, be16toh(option
->code
), be16toh(option
->len
), option
->data
, &ia
);
342 assert_se(r
== -EBADMSG
);
344 option
->len
= htobe16(sizeof(DHCP6Option
));
345 r
= dhcp6_option_parse_ia(NULL
, iaid
, be16toh(option
->code
), be16toh(option
->len
), option
->data
, &ia
);
346 assert_se(r
== -EBADMSG
);
348 option
= (DHCP6Option
*) option2
;
349 assert_se(sizeof(option2
) == sizeof(DHCP6Option
) + be16toh(option
->len
));
350 r
= dhcp6_option_parse_ia(NULL
, iaid
, be16toh(option
->code
), be16toh(option
->len
), option
->data
, &ia
);
351 assert_se(r
== -ENODATA
);
353 option
= (DHCP6Option
*) option3
;
354 assert_se(sizeof(option3
) == sizeof(DHCP6Option
) + be16toh(option
->len
));
355 r
= dhcp6_option_parse_ia(NULL
, iaid
, be16toh(option
->code
), be16toh(option
->len
), option
->data
, &ia
);
358 assert_se(ia
->addresses
);
359 ia
= dhcp6_ia_free(ia
);
361 option
= (DHCP6Option
*) option4
;
362 assert_se(sizeof(option4
) == sizeof(DHCP6Option
) + be16toh(option
->len
));
363 r
= dhcp6_option_parse_ia(NULL
, iaid
, be16toh(option
->code
), be16toh(option
->len
), option
->data
, &ia
);
366 assert_se(ia
->addresses
);
367 assert_se(memcmp(&ia
->header
.id
, &option4
[4], 4) == 0);
368 assert_se(memcmp(&ia
->header
.lifetime_t1
, &option4
[8], 4) == 0);
369 assert_se(memcmp(&ia
->header
.lifetime_t2
, &option4
[12], 4) == 0);
370 ia
= dhcp6_ia_free(ia
);
372 option
= (DHCP6Option
*) option5
;
373 assert_se(sizeof(option5
) == sizeof(DHCP6Option
) + be16toh(option
->len
));
374 r
= dhcp6_option_parse_ia(NULL
, iaid
, be16toh(option
->code
), be16toh(option
->len
), option
->data
, &ia
);
377 assert_se(ia
->addresses
);
378 ia
= dhcp6_ia_free(ia
);
381 TEST(client_parse_message_issue_22099
) {
382 static const uint8_t msg
[] = {
388 0x00, SD_DHCP6_OPTION_RAPID_COMMIT
, 0x00, 0x00,
390 0x00, SD_DHCP6_OPTION_NTP_SERVER
, 0x00, 0x14,
391 /* NTP server (broken sub option and sub option length) */
392 0x01, 0x00, 0x10, 0x00,
393 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0x15, 0xc8, 0xff, 0xfe, 0xef, 0x1e, 0x4e,
395 0x00, SD_DHCP6_OPTION_CLIENTID
, 0x00, 0x0e,
396 0x00, 0x02, /* DUID-EN */
397 0x00, 0x00, 0xab, 0x11, /* pen */
398 0x5c, 0x6b, 0x90, 0xec, 0xda, 0x95, 0x15, 0x45, /* id */
400 0x00, SD_DHCP6_OPTION_SERVERID
, 0x00, 0x0a,
401 0x00, 0x03, /* DUID-LL */
402 0x00, 0x01, /* htype */
403 0xdc, 0x15, 0xc8, 0xef, 0x1e, 0x4e, /* haddr */
405 0x00, SD_DHCP6_OPTION_PREFERENCE
, 0x00, 0x01,
408 0x00, SD_DHCP6_OPTION_DNS_SERVER
, 0x00, 0x10,
409 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0x15, 0xc8, 0xff, 0xfe, 0xef, 0x1e, 0x4e,
411 0x00, SD_DHCP6_OPTION_V6_PCP_SERVER
, 0x00, 0x10,
412 0x2a, 0x02, 0x81, 0x0d, 0x98, 0x80, 0x37, 0x00, 0xde, 0x15, 0xc8, 0xff, 0xfe, 0xef, 0x1e, 0x4e,
414 0x00, SD_DHCP6_OPTION_IA_NA
, 0x00, 0x28,
415 0xcc, 0x59, 0x11, 0x7b, /* iaid */
416 0x00, 0x00, 0x07, 0x08, /* lifetime T1 */
417 0x00, 0x00, 0x0b, 0x40, /* lifetime T2 */
418 /* IA_NA (iaaddr suboption) */
419 0x00, SD_DHCP6_OPTION_IAADDR
, 0x00, 0x18,
420 0x2a, 0x02, 0x81, 0x0d, 0x98, 0x80, 0x37, 0x00, 0x6a, 0x05, 0xca, 0xff, 0xfe, 0xf1, 0x51, 0x53, /* address */
421 0x00, 0x00, 0x0e, 0x10, /* preferred lifetime */
422 0x00, 0x00, 0x1c, 0x20, /* valid lifetime */
424 0x00, SD_DHCP6_OPTION_IA_PD
, 0x00, 0x29,
425 0xcc, 0x59, 0x11, 0x7b, /* iaid */
426 0x00, 0x00, 0x07, 0x08, /* lifetime T1 */
427 0x00, 0x00, 0x0b, 0x40, /* lifetime T2 */
428 /* IA_PD (iaprefix suboption) */
429 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX
, 0x00, 0x19,
430 0x00, 0x00, 0x0e, 0x10, /* preferred lifetime */
431 0x00, 0x00, 0x1c, 0x20, /* valid lifetime */
432 0x3a, /* prefixlen */
433 0x2a, 0x02, 0x81, 0x0d, 0x98, 0x80, 0x37, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* prefix */
435 static const uint8_t duid
[] = {
436 0x00, 0x00, 0xab, 0x11, 0x5c, 0x6b, 0x90, 0xec, 0xda, 0x95, 0x15, 0x45,
438 _cleanup_(sd_dhcp6_client_unrefp
) sd_dhcp6_client
*client
= NULL
;
439 _cleanup_(sd_dhcp6_lease_unrefp
) sd_dhcp6_lease
*lease
= NULL
;
441 assert_se(sd_dhcp6_client_new(&client
) >= 0);
442 assert_se(sd_dhcp6_client_set_iaid(client
, 0xcc59117b) >= 0);
443 assert_se(sd_dhcp6_client_set_duid_raw(client
, 2, duid
, sizeof(duid
)) >= 0);
445 assert_se(dhcp6_lease_new_from_message(client
, (const DHCP6Message
*) msg
, sizeof(msg
), NULL
, NULL
, &lease
) >= 0);
448 TEST(client_parse_message_issue_24002
) {
449 static const uint8_t msg
[] = {
455 0x00, SD_DHCP6_OPTION_CLIENTID
, 0x00, 0x0e,
456 0x00, 0x02, /* DUID-EN */
457 0x00, 0x00, 0xab, 0x11, /* pen */
458 0x5c, 0x6b, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, /* id */
460 0x00, 0x02, 0x00, 0x1a,
461 0x00, 0x02, 0x00, 0x00, 0x05, 0x83, 0x30, 0x63, 0x3a, 0x38, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
462 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
464 0x00, 0x19, 0x00, 0x29,
465 0xaa, 0xbb, 0xcc, 0xdd, /* iaid */
466 0x00, 0x00, 0x03, 0x84, /* lifetime (T1) */
467 0x00, 0x00, 0x05, 0xa0, /* lifetime (T2) */
468 /* IA_PD (iaprefix suboption) */
469 0x00, 0x1a, 0x00, 0x19,
470 0x00, 0x00, 0x07, 0x08, /* preferred lifetime */
471 0x00, 0x00, 0x38, 0x40, /* valid lifetime */
472 0x38, /* prefixlen */
473 0x20, 0x03, 0x00, 0xff, 0xaa, 0xbb, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* prefix */
475 0x00, 0x0e, 0x00, 0x00,
476 /* Trailing invalid byte at the end. See issue #28183. */
479 static const uint8_t duid
[] = {
480 0x00, 0x00, 0xab, 0x11, 0x5c, 0x6b, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
482 _cleanup_(sd_dhcp6_client_unrefp
) sd_dhcp6_client
*client
= NULL
;
483 _cleanup_(sd_dhcp6_lease_unrefp
) sd_dhcp6_lease
*lease
= NULL
;
485 assert_se(sd_dhcp6_client_new(&client
) >= 0);
486 assert_se(sd_dhcp6_client_set_iaid(client
, 0xaabbccdd) >= 0);
487 assert_se(sd_dhcp6_client_set_duid_raw(client
, 2, duid
, sizeof(duid
)) >= 0);
489 assert_se(dhcp6_lease_new_from_message(client
, (const DHCP6Message
*) msg
, sizeof(msg
), NULL
, NULL
, &lease
) >= 0);
492 static const uint8_t msg_information_request
[] = {
494 DHCP6_MESSAGE_INFORMATION_REQUEST
,
499 0x00, SD_DHCP6_OPTION_ORO
, 0x00, 0x0c,
500 0x00, SD_DHCP6_OPTION_DNS_SERVER
,
501 0x00, SD_DHCP6_OPTION_DOMAIN
,
502 0x00, SD_DHCP6_OPTION_SNTP_SERVER
,
503 0x00, SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME
,
504 0x00, SD_DHCP6_OPTION_NTP_SERVER
,
505 0x00, SD_DHCP6_OPTION_INF_MAX_RT
,
507 0x00, SD_DHCP6_OPTION_CLIENTID
, 0x00, 0x0e,
511 0x00, SD_DHCP6_OPTION_ELAPSED_TIME
, 0x00, 0x02,
515 static const uint8_t msg_solicit
[] = {
517 DHCP6_MESSAGE_SOLICIT
,
521 0x00, SD_DHCP6_OPTION_RAPID_COMMIT
, 0x00, 0x00,
523 0x00, SD_DHCP6_OPTION_IA_NA
, 0x00, 0x0c,
525 0x00, 0x00, 0x00, 0x00, /* lifetime T1 */
526 0x00, 0x00, 0x00, 0x00, /* lifetime T2 */
528 0x00, SD_DHCP6_OPTION_IA_PD
, 0x00, 0x0c,
530 0x00, 0x00, 0x00, 0x00, /* lifetime T1 */
531 0x00, 0x00, 0x00, 0x00, /* lifetime T2 */
533 0x00, SD_DHCP6_OPTION_CLIENT_FQDN
, 0x00, 0x11,
535 0x04, 'h', 'o', 's', 't', 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
541 0x00, SD_DHCP6_OPTION_ORO
, 0x00, 0x0a,
542 0x00, SD_DHCP6_OPTION_DNS_SERVER
,
543 0x00, SD_DHCP6_OPTION_DOMAIN
,
544 0x00, SD_DHCP6_OPTION_SNTP_SERVER
,
545 0x00, SD_DHCP6_OPTION_NTP_SERVER
,
546 0x00, SD_DHCP6_OPTION_SOL_MAX_RT
,
548 0x00, SD_DHCP6_OPTION_CLIENTID
, 0x00, 0x0e,
552 0x00, SD_DHCP6_OPTION_ELAPSED_TIME
, 0x00, 0x02,
556 static const uint8_t msg_request
[] = {
558 DHCP6_MESSAGE_REQUEST
,
562 0x00, SD_DHCP6_OPTION_SERVERID
, 0x00, 0x0e,
565 0x00, SD_DHCP6_OPTION_IA_NA
, 0x00, 0x44,
567 0x00, 0x00, 0x00, 0x00, /* lifetime T1 */
568 0x00, 0x00, 0x00, 0x00, /* lifetime T2 */
569 /* IA_NA (IAADDR suboption) */
570 0x00, SD_DHCP6_OPTION_IAADDR
, 0x00, 0x18,
571 IA_NA_ADDRESS1_BYTES
,
572 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
573 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
574 /* IA_NA (IAADDR suboption) */
575 0x00, SD_DHCP6_OPTION_IAADDR
, 0x00, 0x18,
576 IA_NA_ADDRESS2_BYTES
,
577 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
578 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
580 0x00, SD_DHCP6_OPTION_IA_PD
, 0x00, 0x46,
582 0x00, 0x00, 0x00, 0x00, /* lifetime T1 */
583 0x00, 0x00, 0x00, 0x00, /* lifetime T2 */
584 /* IA_PD (IA_PD_PREFIX suboption) */
585 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX
, 0x00, 0x19,
586 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
587 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
588 0x40, /* prefixlen */
590 /* IA_PD (IA_PD_PREFIX suboption) */
591 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX
, 0x00, 0x19,
592 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
593 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
594 0x40, /* prefixlen */
597 0x00, SD_DHCP6_OPTION_CLIENT_FQDN
, 0x00, 0x11,
599 0x04, 'h', 'o', 's', 't', 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
605 0x00, SD_DHCP6_OPTION_ORO
, 0x00, 0x08,
606 0x00, SD_DHCP6_OPTION_DNS_SERVER
,
607 0x00, SD_DHCP6_OPTION_DOMAIN
,
608 0x00, SD_DHCP6_OPTION_SNTP_SERVER
,
609 0x00, SD_DHCP6_OPTION_NTP_SERVER
,
611 0x00, SD_DHCP6_OPTION_CLIENTID
, 0x00, 0x0e,
615 0x00, SD_DHCP6_OPTION_ELAPSED_TIME
, 0x00, 0x02,
619 /* RFC 3315 section 18.1.6. The DHCP6 Release message must include:
623 - all released IA with addresses included
624 - elapsed time (required for all messages).
625 All other options aren't required. */
626 static const uint8_t msg_release
[] = {
628 DHCP6_MESSAGE_RELEASE
,
632 0x00, SD_DHCP6_OPTION_SERVERID
, 0x00, 0x0e,
635 0x00, SD_DHCP6_OPTION_IA_NA
, 0x00, 0x44,
637 0x00, 0x00, 0x00, 0x00, /* lifetime T1 */
638 0x00, 0x00, 0x00, 0x00, /* lifetime T2 */
639 /* IA_NA (IAADDR suboption) */
640 0x00, SD_DHCP6_OPTION_IAADDR
, 0x00, 0x18,
641 IA_NA_ADDRESS1_BYTES
,
642 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
643 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
644 /* IA_NA (IAADDR suboption) */
645 0x00, SD_DHCP6_OPTION_IAADDR
, 0x00, 0x18,
646 IA_NA_ADDRESS2_BYTES
,
647 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
648 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
650 0x00, SD_DHCP6_OPTION_IA_PD
, 0x00, 0x46,
652 0x00, 0x00, 0x00, 0x00, /* lifetime T1 */
653 0x00, 0x00, 0x00, 0x00, /* lifetime T2 */
654 /* IA_PD (IA_PD_PREFIX suboption) */
655 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX
, 0x00, 0x19,
656 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
657 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
658 0x40, /* prefixlen */
660 /* IA_PD (IA_PD_PREFIX suboption) */
661 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX
, 0x00, 0x19,
662 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
663 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
664 0x40, /* prefixlen */
667 0x00, SD_DHCP6_OPTION_CLIENTID
, 0x00, 0x0e,
671 0x00, SD_DHCP6_OPTION_ELAPSED_TIME
, 0x00, 0x02,
675 static const uint8_t msg_reply
[] = {
681 0x00, SD_DHCP6_OPTION_CLIENTID
, 0x00, 0x0e,
684 0x00, SD_DHCP6_OPTION_SERVERID
, 0x00, 0x0e,
687 0x00, SD_DHCP6_OPTION_RAPID_COMMIT
, 0x00, 0x01,
690 0x00, SD_DHCP6_OPTION_IA_NA
, 0x00, 0x66,
692 0x00, 0x00, 0x00, 0x50, /* lifetime T1 */
693 0x00, 0x00, 0x00, 0x78, /* lifetime T2 */
694 /* IA_NA (IAADDR suboption) */
695 0x00, SD_DHCP6_OPTION_IAADDR
, 0x00, 0x18,
696 IA_NA_ADDRESS2_BYTES
,
697 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
698 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
699 /* IA_NA (IAADDR suboption) */
700 0x00, SD_DHCP6_OPTION_IAADDR
, 0x00, 0x18,
701 IA_NA_ADDRESS1_BYTES
,
702 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
703 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
704 /* IA_NA (status code suboption) */
705 0x00, SD_DHCP6_OPTION_STATUS_CODE
, 0x00, 0x1e,
706 0x00, 0x00, /* status code */
707 0x41, 0x6c, 0x6c, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x20, 0x77, 0x65,
708 0x72, 0x65, 0x20, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x2e, /* status message */
710 0x00, SD_DHCP6_OPTION_IA_PD
, 0x00, 0x46,
712 0x00, 0x00, 0x00, 0x50, /* lifetime T1 */
713 0x00, 0x00, 0x00, 0x78, /* lifetime T2 */
714 /* IA_PD (IA_PD_PREFIX suboption) */
715 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX
, 0x00, 0x19,
716 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
717 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
718 0x40, /* prefixlen */
720 /* IA_PD (IA_PD_PREFIX suboption) */
721 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX
, 0x00, 0x19,
722 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
723 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
724 0x40, /* prefixlen */
727 0x00, SD_DHCP6_OPTION_DNS_SERVER
, 0x00, 0x20,
731 0x00, SD_DHCP6_OPTION_SNTP_SERVER
, 0x00, 0x20,
735 0x00, SD_DHCP6_OPTION_NTP_SERVER
, 0x00, 0x37,
736 /* NTP server (address suboption) */
737 0x00, DHCP6_NTP_SUBOPTION_SRV_ADDR
, 0x00, 0x10,
739 /* NTP server (address suboption) */
740 0x00, DHCP6_NTP_SUBOPTION_SRV_ADDR
, 0x00, 0x10,
742 /* NTP server (fqdn suboption) */
743 0x00, DHCP6_NTP_SUBOPTION_SRV_FQDN
, 0x00, 0x0b,
744 0x03, 'n', 't', 'p', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
746 0x00, SD_DHCP6_OPTION_DOMAIN
, 0x00, 0x0b,
747 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
749 0x00, SD_DHCP6_OPTION_CLIENT_FQDN
, 0x00, 0x12,
750 0x01, 0x06, 'c', 'l', 'i', 'e', 'n', 't', 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a',
751 /* Vendor specific options */
752 0x00, SD_DHCP6_OPTION_VENDOR_OPTS
, 0x00, 0x09,
753 0x00, 0x00, 0x00, 0x20, 0x00, 0xf7, 0x00, 0x01, VENDOR_SUBOPTION_BYTES
,
756 static const uint8_t msg_advertise
[] = {
758 DHCP6_MESSAGE_ADVERTISE
,
762 0x00, SD_DHCP6_OPTION_CLIENTID
, 0x00, 0x0e,
765 0x00, SD_DHCP6_OPTION_SERVERID
, 0x00, 0x0e,
768 0x00, SD_DHCP6_OPTION_PREFERENCE
, 0x00, 0x01,
771 0x00, SD_DHCP6_OPTION_IA_NA
, 0x00, 0x7a,
773 0x00, 0x00, 0x00, 0x50, /* lifetime T1 */
774 0x00, 0x00, 0x00, 0x78, /* lifetime T2 */
775 /* IA_NA (IAADDR suboption) */
776 0x00, SD_DHCP6_OPTION_IAADDR
, 0x00, 0x18,
777 IA_NA_ADDRESS2_BYTES
, /* address */
778 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
779 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
780 /* IA_NA (IAADDR suboption) */
781 0x00, SD_DHCP6_OPTION_IAADDR
, 0x00, 0x18,
782 IA_NA_ADDRESS1_BYTES
, /* address */
783 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
784 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
785 /* IA_NA (status code suboption) */
786 0x00, SD_DHCP6_OPTION_STATUS_CODE
, 0x00, 0x32,
787 0x00, 0x00, /* status code */
788 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x28, 0x65, 0x73, 0x29, 0x20, 0x72, 0x65, 0x6e, 0x65,
789 0x77, 0x65, 0x64, 0x2e, 0x20, 0x47, 0x72, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x66,
790 0x72, 0x6f, 0x6d, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x74, 0x20, 0x45, 0x61, 0x72, 0x74, 0x68, /* status message */
792 0x00, SD_DHCP6_OPTION_IA_PD
, 0x00, 0x46,
794 0x00, 0x00, 0x00, 0x50, /* lifetime T1 */
795 0x00, 0x00, 0x00, 0x78, /* lifetime T2 */
796 /* IA_PD (IA_PD_PREFIX suboption) */
797 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX
, 0x00, 0x19,
798 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
799 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
800 0x40, /* prefixlen */
802 /* IA_PD (IA_PD_PREFIX suboption) */
803 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX
, 0x00, 0x19,
804 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
805 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
806 0x40, /* prefixlen */
809 0x00, SD_DHCP6_OPTION_DNS_SERVER
, 0x00, 0x20,
813 0x00, SD_DHCP6_OPTION_SNTP_SERVER
, 0x00, 0x20,
817 0x00, SD_DHCP6_OPTION_NTP_SERVER
, 0x00, 0x37,
818 /* NTP server (address suboption) */
819 0x00, DHCP6_NTP_SUBOPTION_SRV_ADDR
, 0x00, 0x10,
821 /* NTP server (address suboption) */
822 0x00, DHCP6_NTP_SUBOPTION_SRV_ADDR
, 0x00, 0x10,
824 /* NTP server (fqdn suboption) */
825 0x00, DHCP6_NTP_SUBOPTION_SRV_FQDN
, 0x00, 0x0b,
826 0x03, 'n', 't', 'p', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
828 0x00, SD_DHCP6_OPTION_DOMAIN
, 0x00, 0x0b,
829 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
831 0x00, SD_DHCP6_OPTION_CLIENT_FQDN
, 0x00, 0x12,
832 0x01, 0x06, 'c', 'l', 'i', 'e', 'n', 't', 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a',
833 /* Vendor specific options */
834 0x00, SD_DHCP6_OPTION_VENDOR_OPTS
, 0x00, 0x09,
835 0x00, 0x00, 0x00, 0x20, 0x00, 0xf7, 0x00, 0x01, VENDOR_SUBOPTION_BYTES
,
838 static void test_client_verify_information_request(const DHCP6Message
*msg
, size_t len
) {
839 log_debug("/* %s */", __func__
);
841 assert_se(len
== sizeof(msg_information_request
));
842 /* The elapsed time value is not deterministic. Skip it. */
843 assert_se(memcmp(msg
, msg_information_request
, len
- sizeof(be16_t
)) == 0);
846 static void test_client_verify_solicit(const DHCP6Message
*msg
, size_t len
) {
847 log_debug("/* %s */", __func__
);
849 assert_se(len
== sizeof(msg_solicit
));
850 /* The elapsed time value is not deterministic. Skip it. */
851 assert_se(memcmp(msg
, msg_solicit
, len
- sizeof(be16_t
)) == 0);
854 static void test_client_verify_release(const DHCP6Message
*msg
, size_t len
) {
855 log_debug("/* %s */", __func__
);
857 assert_se(len
== sizeof(msg_release
));
858 assert_se(msg
->type
== DHCP6_MESSAGE_RELEASE
);
859 /* The transaction ID and elapsed time value are not deterministic. Skip them. */
860 assert_se(memcmp(msg
->options
, msg_release
+ offsetof(DHCP6Message
, options
),
861 len
- offsetof(DHCP6Message
, options
) - sizeof(be16_t
)) == 0);
864 static void test_client_verify_request(const DHCP6Message
*msg
, size_t len
) {
865 log_debug("/* %s */", __func__
);
867 assert_se(len
== sizeof(msg_request
));
868 assert_se(msg
->type
== DHCP6_MESSAGE_REQUEST
);
869 /* The transaction ID and elapsed time value are not deterministic. Skip them. */
870 assert_se(memcmp(msg
->options
, msg_request
+ offsetof(DHCP6Message
, options
),
871 len
- offsetof(DHCP6Message
, options
) - sizeof(be16_t
)) == 0);
874 static void test_lease_common(sd_dhcp6_client
*client
) {
875 sd_dhcp6_lease
*lease
;
876 sd_dhcp6_option
**suboption
;
877 const struct in6_addr
*addrs
;
883 assert_se(sd_dhcp6_client_get_lease(client
, &lease
) >= 0);
885 assert_se(dhcp6_lease_get_clientid(lease
, &id
, &len
) >= 0);
886 assert_se(memcmp_nn(id
, len
, client_id
, sizeof(client_id
)) == 0);
888 assert_se(sd_dhcp6_lease_get_domains(lease
, &strv
) == 1);
889 assert_se(streq(strv
[0], "lab.intra"));
892 assert_se(sd_dhcp6_lease_get_fqdn(lease
, &str
) >= 0);
893 assert_se(streq(str
, "client.lab.intra"));
895 assert_se(sd_dhcp6_lease_get_dns(lease
, &addrs
) == 2);
896 assert_se(in6_addr_equal(&addrs
[0], &dns1
));
897 assert_se(in6_addr_equal(&addrs
[1], &dns2
));
899 assert_se(sd_dhcp6_lease_get_ntp_addrs(lease
, &addrs
) == 2);
900 assert_se(in6_addr_equal(&addrs
[0], &ntp1
));
901 assert_se(in6_addr_equal(&addrs
[1], &ntp2
));
903 assert_se(sd_dhcp6_lease_get_ntp_fqdn(lease
, &strv
) == 1);
904 assert_se(streq(strv
[0], "ntp.intra"));
907 assert_se(lease
->sntp_count
== 2);
908 assert_se(in6_addr_equal(&lease
->sntp
[0], &sntp1
));
909 assert_se(in6_addr_equal(&lease
->sntp
[1], &sntp2
));
911 assert_se(sd_dhcp6_lease_get_vendor_options(lease
, &suboption
) > 0);
912 assert_se((*suboption
)->enterprise_identifier
== vendor_suboption
.enterprise_identifier
);
913 assert_se((*suboption
)->option
== vendor_suboption
.option
);
914 assert_se(*(uint8_t*)(*suboption
)->data
== *(uint8_t*)vendor_suboption
.data
);
917 static void test_lease_managed(sd_dhcp6_client
*client
) {
918 sd_dhcp6_lease
*lease
;
919 struct in6_addr addr
;
920 usec_t lt_pref
, lt_valid
;
921 uint8_t *id
, prefixlen
;
924 assert_se(sd_dhcp6_client_get_lease(client
, &lease
) >= 0);
926 assert_se(dhcp6_lease_get_serverid(lease
, &id
, &len
) >= 0);
927 assert_se(memcmp_nn(id
, len
, server_id
, sizeof(server_id
)) == 0);
929 assert_se(sd_dhcp6_lease_has_address(lease
));
930 assert_se(sd_dhcp6_lease_has_pd_prefix(lease
));
932 for (unsigned i
= 0; i
< 2; i
++) {
933 assert_se(sd_dhcp6_lease_address_iterator_reset(lease
));
934 assert_se(sd_dhcp6_lease_get_address(lease
, &addr
) >= 0);
935 assert_se(sd_dhcp6_lease_get_address_lifetime(lease
, <_pref
, <_valid
) >= 0);
936 assert_se(in6_addr_equal(&addr
, &ia_na_address1
));
937 assert_se(lt_pref
== 150 * USEC_PER_SEC
);
938 assert_se(lt_valid
== 180 * USEC_PER_SEC
);
939 assert_se(sd_dhcp6_lease_address_iterator_next(lease
));
940 assert_se(sd_dhcp6_lease_get_address(lease
, &addr
) >= 0);
941 assert_se(sd_dhcp6_lease_get_address_lifetime(lease
, <_pref
, <_valid
) >= 0);
942 assert_se(in6_addr_equal(&addr
, &ia_na_address2
));
943 assert_se(lt_pref
== 150 * USEC_PER_SEC
);
944 assert_se(lt_valid
== 180 * USEC_PER_SEC
);
945 assert_se(!sd_dhcp6_lease_address_iterator_next(lease
));
947 assert_se(sd_dhcp6_lease_pd_iterator_reset(lease
));
948 assert_se(sd_dhcp6_lease_get_pd_prefix(lease
, &addr
, &prefixlen
) >= 0);
949 assert_se(sd_dhcp6_lease_get_pd_lifetime(lease
, <_pref
, <_valid
) >= 0);
950 assert_se(in6_addr_equal(&addr
, &ia_pd_prefix1
));
951 assert_se(prefixlen
== 64);
952 assert_se(lt_pref
== 150 * USEC_PER_SEC
);
953 assert_se(lt_valid
== 180 * USEC_PER_SEC
);
954 assert_se(sd_dhcp6_lease_pd_iterator_next(lease
));
955 assert_se(sd_dhcp6_lease_get_pd_prefix(lease
, &addr
, &prefixlen
) >= 0);
956 assert_se(sd_dhcp6_lease_get_pd_lifetime(lease
, <_pref
, <_valid
) >= 0);
957 assert_se(in6_addr_equal(&addr
, &ia_pd_prefix2
));
958 assert_se(prefixlen
== 64);
959 assert_se(lt_pref
== 150 * USEC_PER_SEC
);
960 assert_se(lt_valid
== 180 * USEC_PER_SEC
);
961 assert_se(!sd_dhcp6_lease_pd_iterator_next(lease
));
964 test_lease_common(client
);
967 static void test_client_callback(sd_dhcp6_client
*client
, int event
, void *userdata
) {
969 case SD_DHCP6_CLIENT_EVENT_STOP
:
970 log_debug("/* %s (event=stop) */", __func__
);
973 case SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST
:
974 log_debug("/* %s (event=information-request) */", __func__
);
976 assert_se(test_client_sent_message_count
== 1);
978 test_lease_common(client
);
980 assert_se(sd_dhcp6_client_set_information_request(client
, false) >= 0);
981 assert_se(sd_dhcp6_client_start(client
) >= 0);
982 assert_se(dhcp6_client_set_transaction_id(client
, ((const DHCP6Message
*) msg_advertise
)->transaction_id
) >= 0);
985 case SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE
:
986 log_debug("/* %s (event=ip-acquire) */", __func__
);
988 assert_se(IN_SET(test_client_sent_message_count
, 3, 5));
990 test_lease_managed(client
);
992 switch (test_client_sent_message_count
) {
994 assert_se(sd_dhcp6_client_stop(client
) >= 0);
995 assert_se(sd_dhcp6_client_start(client
) >= 0);
996 assert_se(dhcp6_client_set_transaction_id(client
, ((const DHCP6Message
*) msg_reply
)->transaction_id
) >= 0);
1000 assert_se(sd_event_exit(sd_dhcp6_client_get_event(client
), 0) >= 0);
1004 assert_not_reached();
1009 case DHCP6_CLIENT_EVENT_TEST_ADVERTISED
: {
1010 sd_dhcp6_lease
*lease
;
1013 log_debug("/* %s (event=test-advertised) */", __func__
);
1015 assert_se(test_client_sent_message_count
== 2);
1017 test_lease_managed(client
);
1019 assert_se(sd_dhcp6_client_get_lease(client
, &lease
) >= 0);
1020 assert_se(dhcp6_lease_get_preference(lease
, &preference
) >= 0);
1021 assert_se(preference
== 0xff);
1023 assert_se(dhcp6_client_set_transaction_id(client
, ((const DHCP6Message
*) msg_reply
)->transaction_id
) >= 0);
1027 assert_not_reached();
1031 int dhcp6_network_send_udp_socket(int s
, struct in6_addr
*a
, const void *packet
, size_t len
) {
1032 log_debug("/* %s(count=%u) */", __func__
, test_client_sent_message_count
);
1035 assert_se(in6_addr_equal(a
, &mcast_address
));
1037 assert_se(len
>= sizeof(DHCP6Message
));
1039 switch (test_client_sent_message_count
) {
1041 test_client_verify_information_request(packet
, len
);
1042 assert_se(write(test_fd
[1], msg_reply
, sizeof(msg_reply
)) == sizeof(msg_reply
));
1046 test_client_verify_solicit(packet
, len
);
1047 assert_se(write(test_fd
[1], msg_advertise
, sizeof(msg_advertise
)) == sizeof(msg_advertise
));
1051 test_client_callback(client_ref
, DHCP6_CLIENT_EVENT_TEST_ADVERTISED
, NULL
);
1052 test_client_verify_request(packet
, len
);
1053 assert_se(write(test_fd
[1], msg_reply
, sizeof(msg_reply
)) == sizeof(msg_reply
));
1057 test_client_verify_release(packet
, len
);
1058 /* when stopping, dhcp6 client doesn't wait for release server reply */
1059 assert_se(write(test_fd
[1], msg_reply
, sizeof(msg_reply
)) == sizeof(msg_reply
));
1063 test_client_verify_solicit(packet
, len
);
1064 assert_se(write(test_fd
[1], msg_reply
, sizeof(msg_reply
)) == sizeof(msg_reply
));
1068 assert_not_reached();
1071 test_client_sent_message_count
++;
1075 int dhcp6_network_bind_udp_socket(int ifindex
, struct in6_addr
*a
) {
1076 assert_se(ifindex
== test_ifindex
);
1078 assert_se(in6_addr_equal(a
, &local_address
));
1080 assert_se(socketpair(AF_UNIX
, SOCK_STREAM
| SOCK_CLOEXEC
| SOCK_NONBLOCK
, 0, test_fd
) >= 0);
1081 return TAKE_FD(test_fd
[0]);
1084 TEST(dhcp6_client
) {
1085 _cleanup_(sd_dhcp6_client_unrefp
) sd_dhcp6_client
*client
= NULL
;
1086 _cleanup_(sd_event_unrefp
) sd_event
*e
= NULL
;
1088 assert_se(sd_event_new(&e
) >= 0);
1089 assert_se(sd_event_add_time_relative(e
, NULL
, CLOCK_BOOTTIME
,
1090 2 * USEC_PER_SEC
, 0,
1091 NULL
, INT_TO_PTR(-ETIMEDOUT
)) >= 0);
1093 assert_se(sd_dhcp6_client_new(&client
) >= 0);
1094 assert_se(sd_dhcp6_client_attach_event(client
, e
, 0) >= 0);
1095 assert_se(sd_dhcp6_client_set_ifindex(client
, test_ifindex
) == 0);
1096 assert_se(sd_dhcp6_client_set_local_address(client
, &local_address
) >= 0);
1097 assert_se(sd_dhcp6_client_set_fqdn(client
, "host.lab.intra") >= 0);
1098 assert_se(sd_dhcp6_client_set_iaid(client
, unaligned_read_be32((uint8_t[]) { IA_ID_BYTES
})) >= 0);
1099 assert_se(sd_dhcp6_client_set_send_release(client
, true) >= 0);
1101 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_DNS_SERVER
) >= 0);
1102 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_DOMAIN
) >= 0);
1103 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_NTP_SERVER
) >= 0);
1104 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_SNTP_SERVER
) >= 0);
1106 assert_se(sd_dhcp6_client_set_information_request(client
, true) >= 0);
1107 assert_se(sd_dhcp6_client_set_callback(client
, test_client_callback
, NULL
) >= 0);
1109 assert_se(sd_dhcp6_client_start(client
) >= 0);
1111 assert_se(dhcp6_client_set_transaction_id(client
, ((const DHCP6Message
*) msg_reply
)->transaction_id
) >= 0);
1113 assert_se(client_ref
= sd_dhcp6_client_ref(client
));
1115 assert_se(sd_event_loop(e
) >= 0);
1117 assert_se(test_client_sent_message_count
== 5);
1119 assert_se(!sd_dhcp6_client_unref(client_ref
));
1120 test_fd
[1] = safe_close(test_fd
[1]);
1123 static int intro(void) {
1124 assert_se(setenv("SYSTEMD_NETWORK_TEST_MODE", "1", 1) >= 0);
1128 DEFINE_TEST_MAIN_WITH_INTRO(LOG_DEBUG
, intro
);