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>
12 #include "sd-dhcp6-client.h"
13 #include "sd-dhcp6-protocol.h"
16 #include "dhcp6-internal.h"
17 #include "dhcp6-lease-internal.h"
18 #include "dhcp6-protocol.h"
20 #include "in-addr-util.h"
21 #include "memory-util.h"
24 #include "time-util.h"
25 #include "unaligned.h"
27 #define DHCP6_CLIENT_EVENT_TEST_ADVERTISED 77
29 0x0e, 0xcf, 0xa3, 0x7d
30 #define IA_NA_ADDRESS1_BYTES \
31 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x78, 0xee, 0x1c, 0xf3, 0x09, 0x3c, 0x55, 0xad
32 #define IA_NA_ADDRESS2_BYTES \
33 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x78, 0xee, 0x1c, 0xf3, 0x09, 0x3c, 0x55, 0xae
34 #define IA_PD_PREFIX1_BYTES \
35 0x2a, 0x02, 0x81, 0x0d, 0x98, 0x80, 0x37, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
36 #define IA_PD_PREFIX2_BYTES \
37 0x2a, 0x02, 0x81, 0x0d, 0x98, 0x80, 0x37, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
39 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
41 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02
43 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03
45 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04
47 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05
49 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06
50 #define CLIENT_ID_BYTES \
51 0x00, 0x02, 0x00, 0x00, 0xab, 0x11, 0x61, 0x77, 0x40, 0xde, 0x13, 0x42, 0xc3, 0xa2
52 #define SERVER_ID_BYTES \
53 0x00, 0x01, 0x00, 0x01, 0x19, 0x40, 0x5c, 0x53, 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53
54 #define VENDOR_SUBOPTION_BYTES \
57 static const struct in6_addr local_address
=
58 { { { 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, } } };
59 static const struct in6_addr mcast_address
= IN6_ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS
;
60 static const struct in6_addr ia_na_address1
= { { { IA_NA_ADDRESS1_BYTES
} } };
61 static const struct in6_addr ia_na_address2
= { { { IA_NA_ADDRESS2_BYTES
} } };
62 static const struct in6_addr ia_pd_prefix1
= { { { IA_PD_PREFIX1_BYTES
} } };
63 static const struct in6_addr ia_pd_prefix2
= { { { IA_PD_PREFIX2_BYTES
} } };
64 static const struct in6_addr dns1
= { { { DNS1_BYTES
} } };
65 static const struct in6_addr dns2
= { { { DNS2_BYTES
} } };
66 static const struct in6_addr sntp1
= { { { SNTP1_BYTES
} } };
67 static const struct in6_addr sntp2
= { { { SNTP2_BYTES
} } };
68 static const struct in6_addr ntp1
= { { { NTP1_BYTES
} } };
69 static const struct in6_addr ntp2
= { { { NTP2_BYTES
} } };
70 static const uint8_t client_id
[] = { CLIENT_ID_BYTES
};
71 static const uint8_t server_id
[] = { SERVER_ID_BYTES
};
72 static uint8_t vendor_suboption_data
[] = { VENDOR_SUBOPTION_BYTES
};
73 static const struct ether_addr mac
= {
74 .ether_addr_octet
= { 'A', 'B', 'C', '1', '2', '3' },
76 static int test_fd
[2] = EBADF_PAIR
;
77 static sd_dhcp6_option vendor_suboption
= {
79 .enterprise_identifier
= 32,
81 .data
= vendor_suboption_data
,
84 static int test_ifindex
= 42;
85 static unsigned test_client_sent_message_count
= 0;
86 static sd_dhcp6_client
*client_ref
= NULL
;
89 _cleanup_(sd_dhcp6_client_unrefp
) sd_dhcp6_client
*client
= NULL
;
92 assert_se(sd_dhcp6_client_new(&client
) >= 0);
95 assert_se(sd_dhcp6_client_set_ifindex(client
, 15) == 0);
96 assert_se(sd_dhcp6_client_set_ifindex(client
, 42) >= 0);
98 assert_se(sd_dhcp6_client_set_mac(client
, mac
.ether_addr_octet
, sizeof(mac
), ARPHRD_ETHER
) >= 0);
100 assert_se(sd_dhcp6_client_set_fqdn(client
, "host") == 1);
101 assert_se(sd_dhcp6_client_set_fqdn(client
, "host.domain") == 1);
102 assert_se(sd_dhcp6_client_set_fqdn(client
, NULL
) == 1);
103 assert_se(sd_dhcp6_client_set_fqdn(client
, "~host") == -EINVAL
);
104 assert_se(sd_dhcp6_client_set_fqdn(client
, "~host.domain") == -EINVAL
);
106 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_CLIENTID
) == -EINVAL
);
107 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_DNS_SERVER
) >= 0);
108 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_NTP_SERVER
) >= 0);
109 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_SNTP_SERVER
) >= 0);
110 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_VENDOR_OPTS
) >= 0);
111 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_DOMAIN
) >= 0);
112 assert_se(sd_dhcp6_client_set_request_option(client
, 10) == -EINVAL
);
113 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_NIS_SERVER
) >= 0);
114 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_NISP_SERVER
) >= 0);
115 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_NIS_SERVER
) == -EEXIST
);
116 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_NISP_SERVER
) == -EEXIST
);
118 assert_se(sd_dhcp6_client_set_information_request(client
, 1) >= 0);
120 assert_se(sd_dhcp6_client_get_information_request(client
, &v
) >= 0);
122 assert_se(sd_dhcp6_client_set_information_request(client
, 0) >= 0);
124 assert_se(sd_dhcp6_client_get_information_request(client
, &v
) >= 0);
128 assert_se(sd_dhcp6_client_get_address_request(client
, &v
) >= 0);
131 assert_se(sd_dhcp6_client_set_address_request(client
, 1) >= 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_set_prefix_delegation(client
, 1) >= 0);
142 assert_se(sd_dhcp6_client_get_address_request(client
, &v
) >= 0);
145 assert_se(sd_dhcp6_client_get_prefix_delegation(client
, &v
) >= 0);
148 assert_se(sd_dhcp6_client_set_callback(client
, NULL
, NULL
) >= 0);
150 assert_se(sd_dhcp6_client_detach_event(client
) >= 0);
154 _cleanup_free_
char *domain
= NULL
;
155 _cleanup_strv_free_
char **list
= NULL
;
158 data
= (uint8_t []) { 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0 };
159 assert_se(dhcp6_option_parse_domainname(data
, 13, &domain
) >= 0);
161 assert_se(streq(domain
, "example.com"));
162 domain
= mfree(domain
);
164 data
= (uint8_t []) { 4, 't', 'e', 's', 't' };
165 ASSERT_OK(dhcp6_option_parse_domainname(data
, 5, &domain
));
166 ASSERT_STREQ(domain
, "test");
167 domain
= mfree(domain
);
169 data
= (uint8_t []) { 0 };
170 assert_se(dhcp6_option_parse_domainname(data
, 1, &domain
) < 0);
172 data
= (uint8_t []) { 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 3, 'c', 'o', 'm', 0,
173 6, 'f', 'o', 'o', 'b', 'a', 'r', 0 };
174 assert_se(dhcp6_option_parse_domainname_list(data
, 21, &list
) >= 0);
176 assert_se(streq(list
[0], "example.com"));
177 assert_se(streq(list
[1], "foobar"));
179 list
= strv_free(list
);
181 data
= (uint8_t []) { 1, 'a', 0, 20, 'b', 'c' };
182 assert_se(dhcp6_option_parse_domainname_list(data
, 6, &list
) < 0);
184 data
= (uint8_t []) { 0 , 0 };
185 assert_se(dhcp6_option_parse_domainname_list(data
, 2, &list
) < 0);
189 static const uint8_t packet
[] = {
190 'F', 'O', 'O', 'H', 'O', 'G', 'E',
191 0x00, SD_DHCP6_OPTION_ORO
, 0x00, 0x07,
192 'A', 'B', 'C', 'D', 'E', 'F', 'G',
193 0x00, SD_DHCP6_OPTION_VENDOR_CLASS
, 0x00, 0x09,
194 '1', '2', '3', '4', '5', '6', '7', '8', '9',
197 static const uint8_t result
[] = {
198 'F', 'O', 'O', 'H', 'O', 'G', 'E',
199 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
201 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
204 _cleanup_free_
uint8_t *buf
= NULL
;
205 size_t offset
, pos
, optlen
;
206 const uint8_t *optval
;
209 assert_se(sizeof(packet
) == sizeof(result
));
212 assert_se(dhcp6_option_parse(packet
, 0, &offset
, &optcode
, &optlen
, &optval
) == -EBADMSG
);
215 assert_se(dhcp6_option_parse(packet
, 0, &offset
, &optcode
, &optlen
, &optval
) == -EBADMSG
);
217 /* Tests for reading unaligned data. */
218 assert_se(buf
= new(uint8_t, sizeof(packet
)));
219 for (size_t i
= 0; i
<= 7; i
++) {
220 memcpy(buf
, packet
+ i
, sizeof(packet
) - i
);
222 assert_se(dhcp6_option_parse(buf
, sizeof(packet
), &offset
, &optcode
, &optlen
, &optval
) >= 0);
224 assert_se(optcode
== SD_DHCP6_OPTION_ORO
);
225 assert_se(optlen
== 7);
226 assert_se(optval
== buf
+ 11 - i
);
230 assert_se(dhcp6_option_parse(packet
, sizeof(packet
), &offset
, &optcode
, &optlen
, &optval
) >= 0);
232 assert_se(optcode
== SD_DHCP6_OPTION_ORO
);
233 assert_se(optlen
== 7);
234 assert_se(optval
== packet
+ 11);
237 assert_se(buf
= memdup(result
, sizeof(result
)));
239 assert_se(dhcp6_option_append(&buf
, &pos
, optcode
, optlen
, optval
) >= 0);
241 assert_se(dhcp6_option_parse(packet
, sizeof(packet
), &offset
, &optcode
, &optlen
, &optval
) >= 0);
243 assert_se(optcode
== SD_DHCP6_OPTION_VENDOR_CLASS
);
244 assert_se(optlen
== 9);
245 assert_se(optval
== packet
+ 22);
247 assert_se(dhcp6_option_append(&buf
, &pos
, optcode
, optlen
, optval
) >= 0);
249 assert_se(memcmp(packet
, buf
, sizeof(packet
)) == 0);
252 TEST(option_status
) {
253 uint8_t option1
[] = {
255 0x00, 0x03, 0x00, 0x12, 0x1a, 0x1d, 0x1a, 0x1d,
256 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02,
258 0x00, 0x0d, 0x00, 0x02, 0x00, 0x01,
260 static const uint8_t option2
[] = {
262 0x00, 0x03, 0x00, 0x2e, 0x1a, 0x1d, 0x1a, 0x1d,
263 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02,
265 0x00, 0x05, 0x00, 0x1e,
266 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
267 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
268 0x01, 0x02, 0x03, 0x04, 0x0a, 0x0b, 0x0c, 0x0d,
269 /* IA address status option */
270 0x00, 0x0d, 0x00, 0x02, 0x00, 0x01,
272 static const uint8_t option3
[] = {
274 0x00, 0x03, 0x00, 0x34, 0x1a, 0x1d, 0x1a, 0x1d,
275 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02,
277 0x00, 0x05, 0x00, 0x24,
278 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
279 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
280 0x01, 0x02, 0x03, 0x04, 0x0a, 0x0b, 0x0c, 0x0d,
281 /* IA address status option */
282 0x00, 0x0d, 0x00, 0x08, 0x00, 0x00, 'f', 'o',
285 static const uint8_t option4
[] = {
287 0x00, 0x19, 0x00, 0x2f, 0x1a, 0x1d, 0x1a, 0x1d,
288 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02,
290 0x00, 0x1a, 0x00, 0x1f,
291 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
292 0x80, 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe,
293 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
295 /* PD prefix status option */
296 0x00, 0x0d, 0x00, 0x02, 0x00, 0x00,
298 static const uint8_t option5
[] = {
300 0x00, 0x19, 0x00, 0x52, 0x1a, 0x1d, 0x1a, 0x1d,
301 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02,
302 /* IA PD Prefix #1 */
303 0x00, 0x1a, 0x00, 0x1f,
304 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
305 0x80, 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe,
306 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
308 /* PD prefix status option */
309 0x00, 0x0d, 0x00, 0x02, 0x00, 0x00,
310 /* IA PD Prefix #2 */
311 0x00, 0x1a, 0x00, 0x1f,
312 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
313 0x80, 0x20, 0x01, 0x0d, 0xb8, 0xc0, 0x0l
, 0xd0,
314 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
316 /* PD prefix status option */
317 0x00, 0x0d, 0x00, 0x02, 0x00, 0x00,
319 _cleanup_(dhcp6_ia_freep
) DHCP6IA
*ia
= NULL
;
324 memcpy(&iaid
, option1
+ 4, sizeof(iaid
));
326 option
= (DHCP6Option
*) option1
;
327 assert_se(sizeof(option1
) == sizeof(DHCP6Option
) + be16toh(option
->len
));
329 r
= dhcp6_option_parse_ia(NULL
, 0, be16toh(option
->code
), be16toh(option
->len
), option
->data
, &ia
);
330 assert_se(r
== -ENOANO
);
332 r
= dhcp6_option_parse_ia(NULL
, iaid
, be16toh(option
->code
), be16toh(option
->len
), option
->data
, &ia
);
333 assert_se(r
== -EINVAL
);
335 option
->len
= htobe16(17);
336 r
= dhcp6_option_parse_ia(NULL
, iaid
, be16toh(option
->code
), be16toh(option
->len
), option
->data
, &ia
);
337 assert_se(r
== -EBADMSG
);
339 option
->len
= htobe16(sizeof(DHCP6Option
));
340 r
= dhcp6_option_parse_ia(NULL
, iaid
, be16toh(option
->code
), be16toh(option
->len
), option
->data
, &ia
);
341 assert_se(r
== -EBADMSG
);
343 option
= (DHCP6Option
*) option2
;
344 assert_se(sizeof(option2
) == sizeof(DHCP6Option
) + be16toh(option
->len
));
345 r
= dhcp6_option_parse_ia(NULL
, iaid
, be16toh(option
->code
), be16toh(option
->len
), option
->data
, &ia
);
346 assert_se(r
== -ENODATA
);
348 option
= (DHCP6Option
*) option3
;
349 assert_se(sizeof(option3
) == sizeof(DHCP6Option
) + be16toh(option
->len
));
350 r
= dhcp6_option_parse_ia(NULL
, iaid
, be16toh(option
->code
), be16toh(option
->len
), option
->data
, &ia
);
353 assert_se(ia
->addresses
);
354 ia
= dhcp6_ia_free(ia
);
356 option
= (DHCP6Option
*) option4
;
357 assert_se(sizeof(option4
) == sizeof(DHCP6Option
) + be16toh(option
->len
));
358 r
= dhcp6_option_parse_ia(NULL
, iaid
, be16toh(option
->code
), be16toh(option
->len
), option
->data
, &ia
);
361 assert_se(ia
->addresses
);
362 assert_se(memcmp(&ia
->header
.id
, &option4
[4], 4) == 0);
363 assert_se(memcmp(&ia
->header
.lifetime_t1
, &option4
[8], 4) == 0);
364 assert_se(memcmp(&ia
->header
.lifetime_t2
, &option4
[12], 4) == 0);
365 ia
= dhcp6_ia_free(ia
);
367 option
= (DHCP6Option
*) option5
;
368 assert_se(sizeof(option5
) == sizeof(DHCP6Option
) + be16toh(option
->len
));
369 r
= dhcp6_option_parse_ia(NULL
, iaid
, be16toh(option
->code
), be16toh(option
->len
), option
->data
, &ia
);
372 assert_se(ia
->addresses
);
373 ia
= dhcp6_ia_free(ia
);
376 TEST(client_parse_message_issue_22099
) {
377 static const uint8_t msg
[] = {
383 0x00, SD_DHCP6_OPTION_RAPID_COMMIT
, 0x00, 0x00,
385 0x00, SD_DHCP6_OPTION_NTP_SERVER
, 0x00, 0x14,
386 /* NTP server (broken sub option and sub option length) */
387 0x01, 0x00, 0x10, 0x00,
388 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0x15, 0xc8, 0xff, 0xfe, 0xef, 0x1e, 0x4e,
390 0x00, SD_DHCP6_OPTION_CLIENTID
, 0x00, 0x0e,
391 0x00, 0x02, /* DUID-EN */
392 0x00, 0x00, 0xab, 0x11, /* pen */
393 0x5c, 0x6b, 0x90, 0xec, 0xda, 0x95, 0x15, 0x45, /* id */
395 0x00, SD_DHCP6_OPTION_SERVERID
, 0x00, 0x0a,
396 0x00, 0x03, /* DUID-LL */
397 0x00, 0x01, /* htype */
398 0xdc, 0x15, 0xc8, 0xef, 0x1e, 0x4e, /* haddr */
400 0x00, SD_DHCP6_OPTION_PREFERENCE
, 0x00, 0x01,
403 0x00, SD_DHCP6_OPTION_DNS_SERVER
, 0x00, 0x10,
404 0xfd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0x15, 0xc8, 0xff, 0xfe, 0xef, 0x1e, 0x4e,
406 0x00, SD_DHCP6_OPTION_V6_PCP_SERVER
, 0x00, 0x10,
407 0x2a, 0x02, 0x81, 0x0d, 0x98, 0x80, 0x37, 0x00, 0xde, 0x15, 0xc8, 0xff, 0xfe, 0xef, 0x1e, 0x4e,
409 0x00, SD_DHCP6_OPTION_IA_NA
, 0x00, 0x28,
410 0xcc, 0x59, 0x11, 0x7b, /* iaid */
411 0x00, 0x00, 0x07, 0x08, /* lifetime T1 */
412 0x00, 0x00, 0x0b, 0x40, /* lifetime T2 */
413 /* IA_NA (iaaddr suboption) */
414 0x00, SD_DHCP6_OPTION_IAADDR
, 0x00, 0x18,
415 0x2a, 0x02, 0x81, 0x0d, 0x98, 0x80, 0x37, 0x00, 0x6a, 0x05, 0xca, 0xff, 0xfe, 0xf1, 0x51, 0x53, /* address */
416 0x00, 0x00, 0x0e, 0x10, /* preferred lifetime */
417 0x00, 0x00, 0x1c, 0x20, /* valid lifetime */
419 0x00, SD_DHCP6_OPTION_IA_PD
, 0x00, 0x29,
420 0xcc, 0x59, 0x11, 0x7b, /* iaid */
421 0x00, 0x00, 0x07, 0x08, /* lifetime T1 */
422 0x00, 0x00, 0x0b, 0x40, /* lifetime T2 */
423 /* IA_PD (iaprefix suboption) */
424 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX
, 0x00, 0x19,
425 0x00, 0x00, 0x0e, 0x10, /* preferred lifetime */
426 0x00, 0x00, 0x1c, 0x20, /* valid lifetime */
427 0x3a, /* prefixlen */
428 0x2a, 0x02, 0x81, 0x0d, 0x98, 0x80, 0x37, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* prefix */
430 static const uint8_t duid
[] = {
431 0x00, 0x00, 0xab, 0x11, 0x5c, 0x6b, 0x90, 0xec, 0xda, 0x95, 0x15, 0x45,
433 _cleanup_(sd_dhcp6_client_unrefp
) sd_dhcp6_client
*client
= NULL
;
434 _cleanup_(sd_dhcp6_lease_unrefp
) sd_dhcp6_lease
*lease
= NULL
;
436 assert_se(sd_dhcp6_client_new(&client
) >= 0);
437 assert_se(sd_dhcp6_client_set_iaid(client
, 0xcc59117b) >= 0);
438 assert_se(sd_dhcp6_client_set_duid_raw(client
, 2, duid
, sizeof(duid
)) >= 0);
440 assert_se(dhcp6_lease_new_from_message(client
, (const DHCP6Message
*) msg
, sizeof(msg
), NULL
, NULL
, &lease
) >= 0);
443 TEST(client_parse_message_issue_24002
) {
444 static const uint8_t msg
[] = {
450 0x00, SD_DHCP6_OPTION_CLIENTID
, 0x00, 0x0e,
451 0x00, 0x02, /* DUID-EN */
452 0x00, 0x00, 0xab, 0x11, /* pen */
453 0x5c, 0x6b, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, /* id */
455 0x00, 0x02, 0x00, 0x1a,
456 0x00, 0x02, 0x00, 0x00, 0x05, 0x83, 0x30, 0x63, 0x3a, 0x38, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55,
457 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
459 0x00, 0x19, 0x00, 0x29,
460 0xaa, 0xbb, 0xcc, 0xdd, /* iaid */
461 0x00, 0x00, 0x03, 0x84, /* lifetime (T1) */
462 0x00, 0x00, 0x05, 0xa0, /* lifetime (T2) */
463 /* IA_PD (iaprefix suboption) */
464 0x00, 0x1a, 0x00, 0x19,
465 0x00, 0x00, 0x07, 0x08, /* preferred lifetime */
466 0x00, 0x00, 0x38, 0x40, /* valid lifetime */
467 0x38, /* prefixlen */
468 0x20, 0x03, 0x00, 0xff, 0xaa, 0xbb, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* prefix */
470 0x00, 0x0e, 0x00, 0x00,
471 /* Trailing invalid byte at the end. See issue #28183. */
474 static const uint8_t duid
[] = {
475 0x00, 0x00, 0xab, 0x11, 0x5c, 0x6b, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
477 _cleanup_(sd_dhcp6_client_unrefp
) sd_dhcp6_client
*client
= NULL
;
478 _cleanup_(sd_dhcp6_lease_unrefp
) sd_dhcp6_lease
*lease
= NULL
;
480 assert_se(sd_dhcp6_client_new(&client
) >= 0);
481 assert_se(sd_dhcp6_client_set_iaid(client
, 0xaabbccdd) >= 0);
482 assert_se(sd_dhcp6_client_set_duid_raw(client
, 2, duid
, sizeof(duid
)) >= 0);
484 assert_se(dhcp6_lease_new_from_message(client
, (const DHCP6Message
*) msg
, sizeof(msg
), NULL
, NULL
, &lease
) >= 0);
487 static const uint8_t msg_information_request
[] = {
489 DHCP6_MESSAGE_INFORMATION_REQUEST
,
494 0x00, SD_DHCP6_OPTION_ORO
, 0x00, 0x0c,
495 0x00, SD_DHCP6_OPTION_DNS_SERVER
,
496 0x00, SD_DHCP6_OPTION_DOMAIN
,
497 0x00, SD_DHCP6_OPTION_SNTP_SERVER
,
498 0x00, SD_DHCP6_OPTION_INFORMATION_REFRESH_TIME
,
499 0x00, SD_DHCP6_OPTION_NTP_SERVER
,
500 0x00, SD_DHCP6_OPTION_INF_MAX_RT
,
502 0x00, SD_DHCP6_OPTION_CLIENTID
, 0x00, 0x0e,
506 0x00, SD_DHCP6_OPTION_ELAPSED_TIME
, 0x00, 0x02,
510 static const uint8_t msg_solicit
[] = {
512 DHCP6_MESSAGE_SOLICIT
,
516 0x00, SD_DHCP6_OPTION_RAPID_COMMIT
, 0x00, 0x00,
518 0x00, SD_DHCP6_OPTION_IA_NA
, 0x00, 0x0c,
520 0x00, 0x00, 0x00, 0x00, /* lifetime T1 */
521 0x00, 0x00, 0x00, 0x00, /* lifetime T2 */
523 0x00, SD_DHCP6_OPTION_IA_PD
, 0x00, 0x0c,
525 0x00, 0x00, 0x00, 0x00, /* lifetime T1 */
526 0x00, 0x00, 0x00, 0x00, /* lifetime T2 */
528 0x00, SD_DHCP6_OPTION_CLIENT_FQDN
, 0x00, 0x11,
530 0x04, 'h', 'o', 's', 't', 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
536 0x00, SD_DHCP6_OPTION_ORO
, 0x00, 0x0a,
537 0x00, SD_DHCP6_OPTION_DNS_SERVER
,
538 0x00, SD_DHCP6_OPTION_DOMAIN
,
539 0x00, SD_DHCP6_OPTION_SNTP_SERVER
,
540 0x00, SD_DHCP6_OPTION_NTP_SERVER
,
541 0x00, SD_DHCP6_OPTION_SOL_MAX_RT
,
543 0x00, SD_DHCP6_OPTION_CLIENTID
, 0x00, 0x0e,
547 0x00, SD_DHCP6_OPTION_ELAPSED_TIME
, 0x00, 0x02,
551 static const uint8_t msg_request
[] = {
553 DHCP6_MESSAGE_REQUEST
,
557 0x00, SD_DHCP6_OPTION_SERVERID
, 0x00, 0x0e,
560 0x00, SD_DHCP6_OPTION_IA_NA
, 0x00, 0x44,
562 0x00, 0x00, 0x00, 0x00, /* lifetime T1 */
563 0x00, 0x00, 0x00, 0x00, /* lifetime T2 */
564 /* IA_NA (IAADDR suboption) */
565 0x00, SD_DHCP6_OPTION_IAADDR
, 0x00, 0x18,
566 IA_NA_ADDRESS1_BYTES
,
567 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
568 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
569 /* IA_NA (IAADDR suboption) */
570 0x00, SD_DHCP6_OPTION_IAADDR
, 0x00, 0x18,
571 IA_NA_ADDRESS2_BYTES
,
572 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
573 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
575 0x00, SD_DHCP6_OPTION_IA_PD
, 0x00, 0x46,
577 0x00, 0x00, 0x00, 0x00, /* lifetime T1 */
578 0x00, 0x00, 0x00, 0x00, /* lifetime T2 */
579 /* IA_PD (IA_PD_PREFIX suboption) */
580 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX
, 0x00, 0x19,
581 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
582 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
583 0x40, /* prefixlen */
585 /* IA_PD (IA_PD_PREFIX suboption) */
586 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX
, 0x00, 0x19,
587 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
588 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
589 0x40, /* prefixlen */
592 0x00, SD_DHCP6_OPTION_CLIENT_FQDN
, 0x00, 0x11,
594 0x04, 'h', 'o', 's', 't', 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
600 0x00, SD_DHCP6_OPTION_ORO
, 0x00, 0x08,
601 0x00, SD_DHCP6_OPTION_DNS_SERVER
,
602 0x00, SD_DHCP6_OPTION_DOMAIN
,
603 0x00, SD_DHCP6_OPTION_SNTP_SERVER
,
604 0x00, SD_DHCP6_OPTION_NTP_SERVER
,
606 0x00, SD_DHCP6_OPTION_CLIENTID
, 0x00, 0x0e,
610 0x00, SD_DHCP6_OPTION_ELAPSED_TIME
, 0x00, 0x02,
614 /* RFC 3315 section 18.1.6. The DHCP6 Release message must include:
618 - all released IA with addresses included
619 - elapsed time (required for all messages).
620 All other options aren't required. */
621 static const uint8_t msg_release
[] = {
623 DHCP6_MESSAGE_RELEASE
,
627 0x00, SD_DHCP6_OPTION_SERVERID
, 0x00, 0x0e,
630 0x00, SD_DHCP6_OPTION_IA_NA
, 0x00, 0x44,
632 0x00, 0x00, 0x00, 0x00, /* lifetime T1 */
633 0x00, 0x00, 0x00, 0x00, /* lifetime T2 */
634 /* IA_NA (IAADDR suboption) */
635 0x00, SD_DHCP6_OPTION_IAADDR
, 0x00, 0x18,
636 IA_NA_ADDRESS1_BYTES
,
637 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
638 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
639 /* IA_NA (IAADDR suboption) */
640 0x00, SD_DHCP6_OPTION_IAADDR
, 0x00, 0x18,
641 IA_NA_ADDRESS2_BYTES
,
642 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
643 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
645 0x00, SD_DHCP6_OPTION_IA_PD
, 0x00, 0x46,
647 0x00, 0x00, 0x00, 0x00, /* lifetime T1 */
648 0x00, 0x00, 0x00, 0x00, /* lifetime T2 */
649 /* IA_PD (IA_PD_PREFIX suboption) */
650 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX
, 0x00, 0x19,
651 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
652 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
653 0x40, /* prefixlen */
655 /* IA_PD (IA_PD_PREFIX suboption) */
656 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX
, 0x00, 0x19,
657 0x00, 0x00, 0x00, 0x00, /* preferred lifetime */
658 0x00, 0x00, 0x00, 0x00, /* valid lifetime */
659 0x40, /* prefixlen */
662 0x00, SD_DHCP6_OPTION_CLIENTID
, 0x00, 0x0e,
666 0x00, SD_DHCP6_OPTION_ELAPSED_TIME
, 0x00, 0x02,
670 static const uint8_t msg_reply
[] = {
676 0x00, SD_DHCP6_OPTION_CLIENTID
, 0x00, 0x0e,
679 0x00, SD_DHCP6_OPTION_SERVERID
, 0x00, 0x0e,
682 0x00, SD_DHCP6_OPTION_RAPID_COMMIT
, 0x00, 0x01,
685 0x00, SD_DHCP6_OPTION_IA_NA
, 0x00, 0x66,
687 0x00, 0x00, 0x00, 0x50, /* lifetime T1 */
688 0x00, 0x00, 0x00, 0x78, /* lifetime T2 */
689 /* IA_NA (IAADDR suboption) */
690 0x00, SD_DHCP6_OPTION_IAADDR
, 0x00, 0x18,
691 IA_NA_ADDRESS2_BYTES
,
692 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
693 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
694 /* IA_NA (IAADDR suboption) */
695 0x00, SD_DHCP6_OPTION_IAADDR
, 0x00, 0x18,
696 IA_NA_ADDRESS1_BYTES
,
697 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
698 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
699 /* IA_NA (status code suboption) */
700 0x00, SD_DHCP6_OPTION_STATUS_CODE
, 0x00, 0x1e,
701 0x00, 0x00, /* status code */
702 0x41, 0x6c, 0x6c, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x20, 0x77, 0x65,
703 0x72, 0x65, 0x20, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x2e, /* status message */
705 0x00, SD_DHCP6_OPTION_IA_PD
, 0x00, 0x46,
707 0x00, 0x00, 0x00, 0x50, /* lifetime T1 */
708 0x00, 0x00, 0x00, 0x78, /* lifetime T2 */
709 /* IA_PD (IA_PD_PREFIX suboption) */
710 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX
, 0x00, 0x19,
711 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
712 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
713 0x40, /* prefixlen */
715 /* IA_PD (IA_PD_PREFIX suboption) */
716 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX
, 0x00, 0x19,
717 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
718 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
719 0x40, /* prefixlen */
722 0x00, SD_DHCP6_OPTION_DNS_SERVER
, 0x00, 0x20,
726 0x00, SD_DHCP6_OPTION_SNTP_SERVER
, 0x00, 0x20,
730 0x00, SD_DHCP6_OPTION_NTP_SERVER
, 0x00, 0x37,
731 /* NTP server (address suboption) */
732 0x00, DHCP6_NTP_SUBOPTION_SRV_ADDR
, 0x00, 0x10,
734 /* NTP server (address suboption) */
735 0x00, DHCP6_NTP_SUBOPTION_SRV_ADDR
, 0x00, 0x10,
737 /* NTP server (fqdn suboption) */
738 0x00, DHCP6_NTP_SUBOPTION_SRV_FQDN
, 0x00, 0x0b,
739 0x03, 'n', 't', 'p', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
741 0x00, SD_DHCP6_OPTION_DOMAIN
, 0x00, 0x0b,
742 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
744 0x00, SD_DHCP6_OPTION_CLIENT_FQDN
, 0x00, 0x13,
745 0x01, 0x06, 'c', 'l', 'i', 'e', 'n', 't', 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
746 /* Vendor specific options */
747 0x00, SD_DHCP6_OPTION_VENDOR_OPTS
, 0x00, 0x09,
748 0x00, 0x00, 0x00, 0x20, 0x00, 0xf7, 0x00, 0x01, VENDOR_SUBOPTION_BYTES
,
751 static const uint8_t msg_advertise
[] = {
753 DHCP6_MESSAGE_ADVERTISE
,
757 0x00, SD_DHCP6_OPTION_CLIENTID
, 0x00, 0x0e,
760 0x00, SD_DHCP6_OPTION_SERVERID
, 0x00, 0x0e,
763 0x00, SD_DHCP6_OPTION_PREFERENCE
, 0x00, 0x01,
766 0x00, SD_DHCP6_OPTION_IA_NA
, 0x00, 0x7a,
768 0x00, 0x00, 0x00, 0x50, /* lifetime T1 */
769 0x00, 0x00, 0x00, 0x78, /* lifetime T2 */
770 /* IA_NA (IAADDR suboption) */
771 0x00, SD_DHCP6_OPTION_IAADDR
, 0x00, 0x18,
772 IA_NA_ADDRESS2_BYTES
, /* address */
773 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
774 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
775 /* IA_NA (IAADDR suboption) */
776 0x00, SD_DHCP6_OPTION_IAADDR
, 0x00, 0x18,
777 IA_NA_ADDRESS1_BYTES
, /* address */
778 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
779 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
780 /* IA_NA (status code suboption) */
781 0x00, SD_DHCP6_OPTION_STATUS_CODE
, 0x00, 0x32,
782 0x00, 0x00, /* status code */
783 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x28, 0x65, 0x73, 0x29, 0x20, 0x72, 0x65, 0x6e, 0x65,
784 0x77, 0x65, 0x64, 0x2e, 0x20, 0x47, 0x72, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x66,
785 0x72, 0x6f, 0x6d, 0x20, 0x70, 0x6c, 0x61, 0x6e, 0x65, 0x74, 0x20, 0x45, 0x61, 0x72, 0x74, 0x68, /* status message */
787 0x00, SD_DHCP6_OPTION_IA_PD
, 0x00, 0x46,
789 0x00, 0x00, 0x00, 0x50, /* lifetime T1 */
790 0x00, 0x00, 0x00, 0x78, /* lifetime T2 */
791 /* IA_PD (IA_PD_PREFIX suboption) */
792 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX
, 0x00, 0x19,
793 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
794 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
795 0x40, /* prefixlen */
797 /* IA_PD (IA_PD_PREFIX suboption) */
798 0x00, SD_DHCP6_OPTION_IA_PD_PREFIX
, 0x00, 0x19,
799 0x00, 0x00, 0x00, 0x96, /* preferred lifetime */
800 0x00, 0x00, 0x00, 0xb4, /* valid lifetime */
801 0x40, /* prefixlen */
804 0x00, SD_DHCP6_OPTION_DNS_SERVER
, 0x00, 0x20,
808 0x00, SD_DHCP6_OPTION_SNTP_SERVER
, 0x00, 0x20,
812 0x00, SD_DHCP6_OPTION_NTP_SERVER
, 0x00, 0x37,
813 /* NTP server (address suboption) */
814 0x00, DHCP6_NTP_SUBOPTION_SRV_ADDR
, 0x00, 0x10,
816 /* NTP server (address suboption) */
817 0x00, DHCP6_NTP_SUBOPTION_SRV_ADDR
, 0x00, 0x10,
819 /* NTP server (fqdn suboption) */
820 0x00, DHCP6_NTP_SUBOPTION_SRV_FQDN
, 0x00, 0x0b,
821 0x03, 'n', 't', 'p', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
823 0x00, SD_DHCP6_OPTION_DOMAIN
, 0x00, 0x0b,
824 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
826 0x00, SD_DHCP6_OPTION_CLIENT_FQDN
, 0x00, 0x13,
827 0x01, 0x06, 'c', 'l', 'i', 'e', 'n', 't', 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
828 /* Vendor specific options */
829 0x00, SD_DHCP6_OPTION_VENDOR_OPTS
, 0x00, 0x09,
830 0x00, 0x00, 0x00, 0x20, 0x00, 0xf7, 0x00, 0x01, VENDOR_SUBOPTION_BYTES
,
833 static void test_client_verify_information_request(const DHCP6Message
*msg
, size_t len
) {
834 log_debug("/* %s */", __func__
);
836 assert_se(len
== sizeof(msg_information_request
));
837 /* The elapsed time value is not deterministic. Skip it. */
838 assert_se(memcmp(msg
, msg_information_request
, len
- sizeof(be16_t
)) == 0);
841 static void test_client_verify_solicit(const DHCP6Message
*msg
, size_t len
) {
842 log_debug("/* %s */", __func__
);
844 assert_se(len
== sizeof(msg_solicit
));
845 /* The elapsed time value is not deterministic. Skip it. */
846 assert_se(memcmp(msg
, msg_solicit
, len
- sizeof(be16_t
)) == 0);
849 static void test_client_verify_release(const DHCP6Message
*msg
, size_t len
) {
850 log_debug("/* %s */", __func__
);
852 assert_se(len
== sizeof(msg_release
));
853 assert_se(msg
->type
== DHCP6_MESSAGE_RELEASE
);
854 /* The transaction ID and elapsed time value are not deterministic. Skip them. */
855 assert_se(memcmp(msg
->options
, msg_release
+ offsetof(DHCP6Message
, options
),
856 len
- offsetof(DHCP6Message
, options
) - sizeof(be16_t
)) == 0);
859 static void test_client_verify_request(const DHCP6Message
*msg
, size_t len
) {
860 log_debug("/* %s */", __func__
);
862 assert_se(len
== sizeof(msg_request
));
863 assert_se(msg
->type
== DHCP6_MESSAGE_REQUEST
);
864 /* The transaction ID and elapsed time value are not deterministic. Skip them. */
865 assert_se(memcmp(msg
->options
, msg_request
+ offsetof(DHCP6Message
, options
),
866 len
- offsetof(DHCP6Message
, options
) - sizeof(be16_t
)) == 0);
869 static void test_lease_common(sd_dhcp6_client
*client
) {
870 sd_dhcp6_lease
*lease
;
871 sd_dhcp6_option
**suboption
;
872 const struct in6_addr
*addrs
;
878 assert_se(sd_dhcp6_client_get_lease(client
, &lease
) >= 0);
880 assert_se(dhcp6_lease_get_clientid(lease
, &id
, &len
) >= 0);
881 assert_se(memcmp_nn(id
, len
, client_id
, sizeof(client_id
)) == 0);
883 assert_se(sd_dhcp6_lease_get_domains(lease
, &strv
) == 1);
884 assert_se(streq(strv
[0], "lab.intra"));
887 assert_se(sd_dhcp6_lease_get_fqdn(lease
, &str
) >= 0);
888 assert_se(streq(str
, "client.lab.intra"));
890 assert_se(sd_dhcp6_lease_get_dns(lease
, &addrs
) == 2);
891 assert_se(in6_addr_equal(&addrs
[0], &dns1
));
892 assert_se(in6_addr_equal(&addrs
[1], &dns2
));
894 assert_se(sd_dhcp6_lease_get_ntp_addrs(lease
, &addrs
) == 2);
895 assert_se(in6_addr_equal(&addrs
[0], &ntp1
));
896 assert_se(in6_addr_equal(&addrs
[1], &ntp2
));
898 assert_se(sd_dhcp6_lease_get_ntp_fqdn(lease
, &strv
) == 1);
899 assert_se(streq(strv
[0], "ntp.intra"));
902 assert_se(lease
->sntp_count
== 2);
903 assert_se(in6_addr_equal(&lease
->sntp
[0], &sntp1
));
904 assert_se(in6_addr_equal(&lease
->sntp
[1], &sntp2
));
906 assert_se(sd_dhcp6_lease_get_vendor_options(lease
, &suboption
) > 0);
907 assert_se((*suboption
)->enterprise_identifier
== vendor_suboption
.enterprise_identifier
);
908 assert_se((*suboption
)->option
== vendor_suboption
.option
);
909 assert_se(*(uint8_t*)(*suboption
)->data
== *(uint8_t*)vendor_suboption
.data
);
912 static void test_lease_managed(sd_dhcp6_client
*client
) {
913 sd_dhcp6_lease
*lease
;
914 struct in6_addr addr
;
915 usec_t lt_pref
, lt_valid
;
916 uint8_t *id
, prefixlen
;
919 assert_se(sd_dhcp6_client_get_lease(client
, &lease
) >= 0);
921 assert_se(dhcp6_lease_get_serverid(lease
, &id
, &len
) >= 0);
922 assert_se(memcmp_nn(id
, len
, server_id
, sizeof(server_id
)) == 0);
924 assert_se(sd_dhcp6_lease_has_address(lease
));
925 assert_se(sd_dhcp6_lease_has_pd_prefix(lease
));
927 for (unsigned i
= 0; i
< 2; i
++) {
928 assert_se(sd_dhcp6_lease_address_iterator_reset(lease
));
929 assert_se(sd_dhcp6_lease_get_address(lease
, &addr
) >= 0);
930 assert_se(sd_dhcp6_lease_get_address_lifetime(lease
, <_pref
, <_valid
) >= 0);
931 assert_se(in6_addr_equal(&addr
, &ia_na_address1
));
932 assert_se(lt_pref
== 150 * USEC_PER_SEC
);
933 assert_se(lt_valid
== 180 * USEC_PER_SEC
);
934 assert_se(sd_dhcp6_lease_address_iterator_next(lease
));
935 assert_se(sd_dhcp6_lease_get_address(lease
, &addr
) >= 0);
936 assert_se(sd_dhcp6_lease_get_address_lifetime(lease
, <_pref
, <_valid
) >= 0);
937 assert_se(in6_addr_equal(&addr
, &ia_na_address2
));
938 assert_se(lt_pref
== 150 * USEC_PER_SEC
);
939 assert_se(lt_valid
== 180 * USEC_PER_SEC
);
940 assert_se(!sd_dhcp6_lease_address_iterator_next(lease
));
942 assert_se(sd_dhcp6_lease_pd_iterator_reset(lease
));
943 assert_se(sd_dhcp6_lease_get_pd_prefix(lease
, &addr
, &prefixlen
) >= 0);
944 assert_se(sd_dhcp6_lease_get_pd_lifetime(lease
, <_pref
, <_valid
) >= 0);
945 assert_se(in6_addr_equal(&addr
, &ia_pd_prefix1
));
946 assert_se(prefixlen
== 64);
947 assert_se(lt_pref
== 150 * USEC_PER_SEC
);
948 assert_se(lt_valid
== 180 * USEC_PER_SEC
);
949 assert_se(sd_dhcp6_lease_pd_iterator_next(lease
));
950 assert_se(sd_dhcp6_lease_get_pd_prefix(lease
, &addr
, &prefixlen
) >= 0);
951 assert_se(sd_dhcp6_lease_get_pd_lifetime(lease
, <_pref
, <_valid
) >= 0);
952 assert_se(in6_addr_equal(&addr
, &ia_pd_prefix2
));
953 assert_se(prefixlen
== 64);
954 assert_se(lt_pref
== 150 * USEC_PER_SEC
);
955 assert_se(lt_valid
== 180 * USEC_PER_SEC
);
956 assert_se(!sd_dhcp6_lease_pd_iterator_next(lease
));
959 test_lease_common(client
);
962 static void test_client_callback(sd_dhcp6_client
*client
, int event
, void *userdata
) {
964 case SD_DHCP6_CLIENT_EVENT_STOP
:
965 log_debug("/* %s (event=stop) */", __func__
);
968 case SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST
:
969 log_debug("/* %s (event=information-request) */", __func__
);
971 assert_se(test_client_sent_message_count
== 1);
973 test_lease_common(client
);
975 assert_se(sd_dhcp6_client_set_information_request(client
, false) >= 0);
976 assert_se(sd_dhcp6_client_start(client
) >= 0);
977 assert_se(dhcp6_client_set_transaction_id(client
, ((const DHCP6Message
*) msg_advertise
)->transaction_id
) >= 0);
980 case SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE
:
981 log_debug("/* %s (event=ip-acquire) */", __func__
);
983 assert_se(IN_SET(test_client_sent_message_count
, 3, 5));
985 test_lease_managed(client
);
987 switch (test_client_sent_message_count
) {
989 assert_se(sd_dhcp6_client_stop(client
) >= 0);
990 assert_se(sd_dhcp6_client_start(client
) >= 0);
991 assert_se(dhcp6_client_set_transaction_id(client
, ((const DHCP6Message
*) msg_reply
)->transaction_id
) >= 0);
995 assert_se(sd_event_exit(sd_dhcp6_client_get_event(client
), 0) >= 0);
999 assert_not_reached();
1004 case DHCP6_CLIENT_EVENT_TEST_ADVERTISED
: {
1005 sd_dhcp6_lease
*lease
;
1008 log_debug("/* %s (event=test-advertised) */", __func__
);
1010 assert_se(test_client_sent_message_count
== 2);
1012 test_lease_managed(client
);
1014 assert_se(sd_dhcp6_client_get_lease(client
, &lease
) >= 0);
1015 assert_se(dhcp6_lease_get_preference(lease
, &preference
) >= 0);
1016 assert_se(preference
== 0xff);
1018 assert_se(dhcp6_client_set_transaction_id(client
, ((const DHCP6Message
*) msg_reply
)->transaction_id
) >= 0);
1022 assert_not_reached();
1026 int dhcp6_network_send_udp_socket(int s
, const struct in6_addr
*a
, const void *packet
, size_t len
) {
1027 log_debug("/* %s(count=%u) */", __func__
, test_client_sent_message_count
);
1030 assert_se(in6_addr_equal(a
, &mcast_address
));
1032 assert_se(len
>= sizeof(DHCP6Message
));
1034 switch (test_client_sent_message_count
) {
1036 test_client_verify_information_request(packet
, len
);
1037 assert_se(write(test_fd
[1], msg_reply
, sizeof(msg_reply
)) == sizeof(msg_reply
));
1041 test_client_verify_solicit(packet
, len
);
1042 assert_se(write(test_fd
[1], msg_advertise
, sizeof(msg_advertise
)) == sizeof(msg_advertise
));
1046 test_client_callback(client_ref
, DHCP6_CLIENT_EVENT_TEST_ADVERTISED
, NULL
);
1047 test_client_verify_request(packet
, len
);
1048 assert_se(write(test_fd
[1], msg_reply
, sizeof(msg_reply
)) == sizeof(msg_reply
));
1052 test_client_verify_release(packet
, len
);
1053 /* when stopping, dhcp6 client doesn't wait for release server reply */
1054 assert_se(write(test_fd
[1], msg_reply
, sizeof(msg_reply
)) == sizeof(msg_reply
));
1058 test_client_verify_solicit(packet
, len
);
1059 assert_se(write(test_fd
[1], msg_reply
, sizeof(msg_reply
)) == sizeof(msg_reply
));
1063 assert_not_reached();
1066 test_client_sent_message_count
++;
1070 int dhcp6_network_bind_udp_socket(int ifindex
, const struct in6_addr
*a
) {
1071 assert_se(ifindex
== test_ifindex
);
1073 assert_se(in6_addr_equal(a
, &local_address
));
1075 assert_se(socketpair(AF_UNIX
, SOCK_STREAM
| SOCK_CLOEXEC
| SOCK_NONBLOCK
, 0, test_fd
) >= 0);
1076 return TAKE_FD(test_fd
[0]);
1079 TEST(dhcp6_client
) {
1080 _cleanup_(sd_dhcp6_client_unrefp
) sd_dhcp6_client
*client
= NULL
;
1081 _cleanup_(sd_event_unrefp
) sd_event
*e
= NULL
;
1083 assert_se(sd_event_new(&e
) >= 0);
1084 assert_se(sd_event_add_time_relative(e
, NULL
, CLOCK_BOOTTIME
,
1085 30 * USEC_PER_SEC
, 0,
1086 NULL
, INT_TO_PTR(-ETIMEDOUT
)) >= 0);
1088 assert_se(sd_dhcp6_client_new(&client
) >= 0);
1089 assert_se(sd_dhcp6_client_attach_event(client
, e
, 0) >= 0);
1090 assert_se(sd_dhcp6_client_set_ifindex(client
, test_ifindex
) == 0);
1091 assert_se(sd_dhcp6_client_set_local_address(client
, &local_address
) >= 0);
1092 assert_se(sd_dhcp6_client_set_fqdn(client
, "host.lab.intra") >= 0);
1093 assert_se(sd_dhcp6_client_set_iaid(client
, unaligned_read_be32((uint8_t[]) { IA_ID_BYTES
})) >= 0);
1094 assert_se(sd_dhcp6_client_set_send_release(client
, true) >= 0);
1096 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_DNS_SERVER
) >= 0);
1097 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_DOMAIN
) >= 0);
1098 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_NTP_SERVER
) >= 0);
1099 assert_se(sd_dhcp6_client_set_request_option(client
, SD_DHCP6_OPTION_SNTP_SERVER
) >= 0);
1101 assert_se(sd_dhcp6_client_set_information_request(client
, true) >= 0);
1102 assert_se(sd_dhcp6_client_set_callback(client
, test_client_callback
, NULL
) >= 0);
1104 assert_se(sd_dhcp6_client_start(client
) >= 0);
1106 assert_se(dhcp6_client_set_transaction_id(client
, ((const DHCP6Message
*) msg_reply
)->transaction_id
) >= 0);
1108 assert_se(client_ref
= sd_dhcp6_client_ref(client
));
1110 assert_se(sd_event_loop(e
) >= 0);
1112 assert_se(test_client_sent_message_count
== 5);
1114 assert_se(!sd_dhcp6_client_unref(client_ref
));
1115 test_fd
[1] = safe_close(test_fd
[1]);
1118 static int intro(void) {
1119 assert_se(setenv("SYSTEMD_NETWORK_TEST_MODE", "1", 1) >= 0);
1123 DEFINE_TEST_MAIN_WITH_INTRO(LOG_DEBUG
, intro
);