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