]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-network/test-dhcp6-client.c
Merge pull request #30513 from rpigott/resolved-ede
[thirdparty/systemd.git] / src / libsystemd-network / test-dhcp6-client.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 /***
3 Copyright © 2014 Intel Corporation. All rights reserved.
4 ***/
5
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>
12
13 #include "sd-dhcp6-client.h"
14 #include "sd-event.h"
15
16 #include "dhcp-duid-internal.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"
28 #include "unaligned.h"
29
30 #define DHCP6_CLIENT_EVENT_TEST_ADVERTISED 77
31 #define IA_ID_BYTES \
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
41 #define DNS1_BYTES \
42 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
43 #define DNS2_BYTES \
44 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02
45 #define SNTP1_BYTES \
46 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03
47 #define SNTP2_BYTES \
48 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04
49 #define NTP1_BYTES \
50 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05
51 #define NTP2_BYTES \
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 \
58 0x01
59
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' },
79 };
80 static int test_fd[2] = EBADF_PAIR;
81 static sd_dhcp6_option vendor_suboption = {
82 .n_ref = 1,
83 .enterprise_identifier = 32,
84 .option = 247,
85 .data = vendor_suboption_data,
86 .length = 1,
87 };
88 static int test_ifindex = 42;
89 static unsigned test_client_sent_message_count = 0;
90 static sd_dhcp6_client *client_ref = NULL;
91
92 TEST(client_basic) {
93 _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
94 int v;
95
96 assert_se(sd_dhcp6_client_new(&client) >= 0);
97 assert_se(client);
98
99 assert_se(sd_dhcp6_client_set_ifindex(client, 15) == 0);
100 assert_se(sd_dhcp6_client_set_ifindex(client, 42) >= 0);
101
102 assert_se(sd_dhcp6_client_set_mac(client, mac.ether_addr_octet, sizeof(mac), ARPHRD_ETHER) >= 0);
103
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);
109
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);
121
122 assert_se(sd_dhcp6_client_set_information_request(client, 1) >= 0);
123 v = 0;
124 assert_se(sd_dhcp6_client_get_information_request(client, &v) >= 0);
125 assert_se(v);
126 assert_se(sd_dhcp6_client_set_information_request(client, 0) >= 0);
127 v = 42;
128 assert_se(sd_dhcp6_client_get_information_request(client, &v) >= 0);
129 assert_se(v == 0);
130
131 v = 0;
132 assert_se(sd_dhcp6_client_get_address_request(client, &v) >= 0);
133 assert_se(v);
134 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);
137 assert_se(v);
138 v = 42;
139 assert_se(sd_dhcp6_client_set_address_request(client, 1) >= 0);
140 assert_se(sd_dhcp6_client_get_address_request(client, &v) >= 0);
141 assert_se(v);
142
143 assert_se(sd_dhcp6_client_set_address_request(client, 1) >= 0);
144 assert_se(sd_dhcp6_client_set_prefix_delegation(client, 1) >= 0);
145 v = 0;
146 assert_se(sd_dhcp6_client_get_address_request(client, &v) >= 0);
147 assert_se(v);
148 v = 0;
149 assert_se(sd_dhcp6_client_get_prefix_delegation(client, &v) >= 0);
150 assert_se(v);
151
152 assert_se(sd_dhcp6_client_set_callback(client, NULL, NULL) >= 0);
153
154 assert_se(sd_dhcp6_client_detach_event(client) >= 0);
155 }
156
157 TEST(parse_domain) {
158 _cleanup_free_ char *domain = NULL;
159 _cleanup_strv_free_ char **list = NULL;
160 uint8_t *data;
161
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);
164 assert_se(domain);
165 assert_se(streq(domain, "example.com"));
166 domain = mfree(domain);
167
168 data = (uint8_t []) { 4, 't', 'e', 's', 't' };
169 assert_se(dhcp6_option_parse_domainname(data, 5, &domain) >= 0);
170 assert_se(domain);
171 assert_se(streq(domain, "test"));
172 domain = mfree(domain);
173
174 data = (uint8_t []) { 0 };
175 assert_se(dhcp6_option_parse_domainname(data, 1, &domain) < 0);
176
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);
180 assert_se(list);
181 assert_se(streq(list[0], "example.com"));
182 assert_se(streq(list[1], "foobar"));
183 assert_se(!list[2]);
184 list = strv_free(list);
185
186 data = (uint8_t []) { 1, 'a', 0, 20, 'b', 'c' };
187 assert_se(dhcp6_option_parse_domainname_list(data, 6, &list) < 0);
188
189 data = (uint8_t []) { 0 , 0 };
190 assert_se(dhcp6_option_parse_domainname_list(data, 2, &list) < 0);
191 }
192
193 TEST(option) {
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',
200 'B', 'A', 'R',
201 };
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,
207 'B', 'A', 'R',
208 };
209 _cleanup_free_ uint8_t *buf = NULL;
210 size_t offset, pos, optlen;
211 const uint8_t *optval;
212 uint16_t optcode;
213
214 assert_se(sizeof(packet) == sizeof(result));
215
216 offset = 0;
217 assert_se(dhcp6_option_parse(packet, 0, &offset, &optcode, &optlen, &optval) == -EBADMSG);
218
219 offset = 3;
220 assert_se(dhcp6_option_parse(packet, 0, &offset, &optcode, &optlen, &optval) == -EBADMSG);
221
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);
226 offset = 7 - i;
227 assert_se(dhcp6_option_parse(buf, sizeof(packet), &offset, &optcode, &optlen, &optval) >= 0);
228
229 assert_se(optcode == SD_DHCP6_OPTION_ORO);
230 assert_se(optlen == 7);
231 assert_se(optval == buf + 11 - i);
232 }
233
234 offset = 7;
235 assert_se(dhcp6_option_parse(packet, sizeof(packet), &offset, &optcode, &optlen, &optval) >= 0);
236
237 assert_se(optcode == SD_DHCP6_OPTION_ORO);
238 assert_se(optlen == 7);
239 assert_se(optval == packet + 11);
240
241 free(buf);
242 assert_se(buf = memdup(result, sizeof(result)));
243 pos = 7;
244 assert_se(dhcp6_option_append(&buf, &pos, optcode, optlen, optval) >= 0);
245
246 assert_se(dhcp6_option_parse(packet, sizeof(packet), &offset, &optcode, &optlen, &optval) >= 0);
247
248 assert_se(optcode == SD_DHCP6_OPTION_VENDOR_CLASS);
249 assert_se(optlen == 9);
250 assert_se(optval == packet + 22);
251
252 assert_se(dhcp6_option_append(&buf, &pos, optcode, optlen, optval) >= 0);
253
254 assert_se(memcmp(packet, buf, sizeof(packet)) == 0);
255 }
256
257 TEST(option_status) {
258 uint8_t option1[] = {
259 /* IA NA */
260 0x00, 0x03, 0x00, 0x12, 0x1a, 0x1d, 0x1a, 0x1d,
261 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02,
262 /* status option */
263 0x00, 0x0d, 0x00, 0x02, 0x00, 0x01,
264 };
265 static const uint8_t option2[] = {
266 /* IA NA */
267 0x00, 0x03, 0x00, 0x2e, 0x1a, 0x1d, 0x1a, 0x1d,
268 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02,
269 /* IA Addr */
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,
276 };
277 static const uint8_t option3[] = {
278 /* IA NA */
279 0x00, 0x03, 0x00, 0x34, 0x1a, 0x1d, 0x1a, 0x1d,
280 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02,
281 /* IA Addr */
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',
288 'o', 'b', 'a', 'r',
289 };
290 static const uint8_t option4[] = {
291 /* IA PD */
292 0x00, 0x19, 0x00, 0x2f, 0x1a, 0x1d, 0x1a, 0x1d,
293 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02,
294 /* IA PD Prefix */
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,
299 0x00,
300 /* PD prefix status option */
301 0x00, 0x0d, 0x00, 0x02, 0x00, 0x00,
302 };
303 static const uint8_t option5[] = {
304 /* IA PD */
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,
312 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,
320 0x00,
321 /* PD prefix status option */
322 0x00, 0x0d, 0x00, 0x02, 0x00, 0x00,
323 };
324 _cleanup_(dhcp6_ia_freep) DHCP6IA *ia = NULL;
325 DHCP6Option *option;
326 be32_t iaid;
327 int r;
328
329 memcpy(&iaid, option1 + 4, sizeof(iaid));
330
331 option = (DHCP6Option*) option1;
332 assert_se(sizeof(option1) == sizeof(DHCP6Option) + be16toh(option->len));
333
334 r = dhcp6_option_parse_ia(NULL, 0, be16toh(option->code), be16toh(option->len), option->data, &ia);
335 assert_se(r == -ENOANO);
336
337 r = dhcp6_option_parse_ia(NULL, iaid, be16toh(option->code), be16toh(option->len), option->data, &ia);
338 assert_se(r == -EINVAL);
339
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);
343
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);
347
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);
352
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);
356 assert_se(r >= 0);
357 assert_se(ia);
358 assert_se(ia->addresses);
359 ia = dhcp6_ia_free(ia);
360
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);
364 assert_se(r >= 0);
365 assert_se(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);
371
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);
375 assert_se(r >= 0);
376 assert_se(ia);
377 assert_se(ia->addresses);
378 ia = dhcp6_ia_free(ia);
379 }
380
381 TEST(client_parse_message_issue_22099) {
382 static const uint8_t msg[] = {
383 /* Message type */
384 DHCP6_MESSAGE_REPLY,
385 /* Transaction ID */
386 0x7c, 0x4c, 0x16,
387 /* Rapid commit */
388 0x00, SD_DHCP6_OPTION_RAPID_COMMIT, 0x00, 0x00,
389 /* NTP servers */
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,
394 /* Client ID */
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 */
399 /* Server 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 */
404 /* preference */
405 0x00, SD_DHCP6_OPTION_PREFERENCE, 0x00, 0x01,
406 0x00,
407 /* DNS servers */
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,
410 /* v6 pcp server */
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,
413 /* IA_NA */
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 */
423 /* IA_PD */
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 */
434 };
435 static const uint8_t duid[] = {
436 0x00, 0x00, 0xab, 0x11, 0x5c, 0x6b, 0x90, 0xec, 0xda, 0x95, 0x15, 0x45,
437 };
438 _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
439 _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
440
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);
444
445 assert_se(dhcp6_lease_new_from_message(client, (const DHCP6Message*) msg, sizeof(msg), NULL, NULL, &lease) >= 0);
446 }
447
448 TEST(client_parse_message_issue_24002) {
449 static const uint8_t msg[] = {
450 /* Message Type */
451 0x07,
452 /* Transaction ID */
453 0x0e, 0xa5, 0x7c,
454 /* Client ID */
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 */
459 /* Server 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,
463 /* IA_PD */
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 */
474 /* Rapid commit */
475 0x00, 0x0e, 0x00, 0x00,
476 /* Trailing invalid byte at the end. See issue #28183. */
477 00,
478 };
479 static const uint8_t duid[] = {
480 0x00, 0x00, 0xab, 0x11, 0x5c, 0x6b, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff,
481 };
482 _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
483 _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
484
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);
488
489 assert_se(dhcp6_lease_new_from_message(client, (const DHCP6Message*) msg, sizeof(msg), NULL, NULL, &lease) >= 0);
490 }
491
492 static const uint8_t msg_information_request[] = {
493 /* Message type */
494 DHCP6_MESSAGE_INFORMATION_REQUEST,
495 /* Transaction ID */
496 0x0f, 0xb4, 0xe5,
497 /* MUD URL */
498 /* ORO */
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,
506 /* Client ID */
507 0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
508 CLIENT_ID_BYTES,
509 /* Extra options */
510 /* Elapsed time */
511 0x00, SD_DHCP6_OPTION_ELAPSED_TIME, 0x00, 0x02,
512 0x00, 0x00,
513 };
514
515 static const uint8_t msg_solicit[] = {
516 /* Message type */
517 DHCP6_MESSAGE_SOLICIT,
518 /* Transaction ID */
519 0x0f, 0xb4, 0xe5,
520 /* Rapid commit */
521 0x00, SD_DHCP6_OPTION_RAPID_COMMIT, 0x00, 0x00,
522 /* IA_NA */
523 0x00, SD_DHCP6_OPTION_IA_NA, 0x00, 0x0c,
524 IA_ID_BYTES,
525 0x00, 0x00, 0x00, 0x00, /* lifetime T1 */
526 0x00, 0x00, 0x00, 0x00, /* lifetime T2 */
527 /* IA_PD */
528 0x00, SD_DHCP6_OPTION_IA_PD, 0x00, 0x0c,
529 IA_ID_BYTES,
530 0x00, 0x00, 0x00, 0x00, /* lifetime T1 */
531 0x00, 0x00, 0x00, 0x00, /* lifetime T2 */
532 /* Client FQDN */
533 0x00, SD_DHCP6_OPTION_CLIENT_FQDN, 0x00, 0x11,
534 DHCP6_FQDN_FLAG_S,
535 0x04, 'h', 'o', 's', 't', 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
536 /* User Class */
537 /* Vendor Class */
538 /* Vendor Options */
539 /* MUD URL */
540 /* ORO */
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,
547 /* Client ID */
548 0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
549 CLIENT_ID_BYTES,
550 /* Extra options */
551 /* Elapsed time */
552 0x00, SD_DHCP6_OPTION_ELAPSED_TIME, 0x00, 0x02,
553 0x00, 0x00,
554 };
555
556 static const uint8_t msg_request[] = {
557 /* Message type */
558 DHCP6_MESSAGE_REQUEST,
559 /* Transaction ID */
560 0x00, 0x00, 0x00,
561 /* Server ID */
562 0x00, SD_DHCP6_OPTION_SERVERID, 0x00, 0x0e,
563 SERVER_ID_BYTES,
564 /* IA_NA */
565 0x00, SD_DHCP6_OPTION_IA_NA, 0x00, 0x44,
566 IA_ID_BYTES,
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 */
579 /* IA_PD */
580 0x00, SD_DHCP6_OPTION_IA_PD, 0x00, 0x46,
581 IA_ID_BYTES,
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 */
589 IA_PD_PREFIX1_BYTES,
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 */
595 IA_PD_PREFIX2_BYTES,
596 /* Client FQDN */
597 0x00, SD_DHCP6_OPTION_CLIENT_FQDN, 0x00, 0x11,
598 DHCP6_FQDN_FLAG_S,
599 0x04, 'h', 'o', 's', 't', 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
600 /* User Class */
601 /* Vendor Class */
602 /* Vendor Options */
603 /* MUD URL */
604 /* ORO */
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,
610 /* Client ID */
611 0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
612 CLIENT_ID_BYTES,
613 /* Extra options */
614 /* Elapsed time */
615 0x00, SD_DHCP6_OPTION_ELAPSED_TIME, 0x00, 0x02,
616 0x00, 0x00,
617 };
618
619 /* RFC 3315 section 18.1.6. The DHCP6 Release message must include:
620 - transaction id
621 - server identifier
622 - client identifier
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[] = {
627 /* Message type */
628 DHCP6_MESSAGE_RELEASE,
629 /* Transaction ID */
630 0x00, 0x00, 0x00,
631 /* Server ID */
632 0x00, SD_DHCP6_OPTION_SERVERID, 0x00, 0x0e,
633 SERVER_ID_BYTES,
634 /* IA_NA */
635 0x00, SD_DHCP6_OPTION_IA_NA, 0x00, 0x44,
636 IA_ID_BYTES,
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 */
649 /* IA_PD */
650 0x00, SD_DHCP6_OPTION_IA_PD, 0x00, 0x46,
651 IA_ID_BYTES,
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 */
659 IA_PD_PREFIX1_BYTES,
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 */
665 IA_PD_PREFIX2_BYTES,
666 /* Client ID */
667 0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
668 CLIENT_ID_BYTES,
669 /* Extra options */
670 /* Elapsed time */
671 0x00, SD_DHCP6_OPTION_ELAPSED_TIME, 0x00, 0x02,
672 0x00, 0x00,
673 };
674
675 static const uint8_t msg_reply[] = {
676 /* Message type */
677 DHCP6_MESSAGE_REPLY,
678 /* Transaction ID */
679 0x0f, 0xb4, 0xe5,
680 /* Client ID */
681 0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
682 CLIENT_ID_BYTES,
683 /* Server ID */
684 0x00, SD_DHCP6_OPTION_SERVERID, 0x00, 0x0e,
685 SERVER_ID_BYTES,
686 /* Rapid commit */
687 0x00, SD_DHCP6_OPTION_RAPID_COMMIT, 0x00, 0x01,
688 0x00,
689 /* IA_NA */
690 0x00, SD_DHCP6_OPTION_IA_NA, 0x00, 0x66,
691 IA_ID_BYTES,
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 */
709 /* IA_PD */
710 0x00, SD_DHCP6_OPTION_IA_PD, 0x00, 0x46,
711 IA_ID_BYTES,
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 */
719 IA_PD_PREFIX2_BYTES,
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 */
725 IA_PD_PREFIX1_BYTES,
726 /* DNS servers */
727 0x00, SD_DHCP6_OPTION_DNS_SERVER, 0x00, 0x20,
728 DNS1_BYTES,
729 DNS2_BYTES,
730 /* SNTP servers */
731 0x00, SD_DHCP6_OPTION_SNTP_SERVER, 0x00, 0x20,
732 SNTP1_BYTES,
733 SNTP2_BYTES,
734 /* NTP servers */
735 0x00, SD_DHCP6_OPTION_NTP_SERVER, 0x00, 0x37,
736 /* NTP server (address suboption) */
737 0x00, DHCP6_NTP_SUBOPTION_SRV_ADDR, 0x00, 0x10,
738 NTP1_BYTES,
739 /* NTP server (address suboption) */
740 0x00, DHCP6_NTP_SUBOPTION_SRV_ADDR, 0x00, 0x10,
741 NTP2_BYTES,
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,
745 /* Domain list */
746 0x00, SD_DHCP6_OPTION_DOMAIN, 0x00, 0x0b,
747 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
748 /* Client FQDN */
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,
754 };
755
756 static const uint8_t msg_advertise[] = {
757 /* Message type */
758 DHCP6_MESSAGE_ADVERTISE,
759 /* Transaction ID */
760 0x0f, 0xb4, 0xe5,
761 /* Client ID */
762 0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e,
763 CLIENT_ID_BYTES,
764 /* Server ID */
765 0x00, SD_DHCP6_OPTION_SERVERID, 0x00, 0x0e,
766 SERVER_ID_BYTES,
767 /* Preference */
768 0x00, SD_DHCP6_OPTION_PREFERENCE, 0x00, 0x01,
769 0xff,
770 /* IA_NA */
771 0x00, SD_DHCP6_OPTION_IA_NA, 0x00, 0x7a,
772 IA_ID_BYTES,
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 */
791 /* IA_PD */
792 0x00, SD_DHCP6_OPTION_IA_PD, 0x00, 0x46,
793 IA_ID_BYTES,
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 */
801 IA_PD_PREFIX2_BYTES,
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 */
807 IA_PD_PREFIX1_BYTES,
808 /* DNS servers */
809 0x00, SD_DHCP6_OPTION_DNS_SERVER, 0x00, 0x20,
810 DNS1_BYTES,
811 DNS2_BYTES,
812 /* SNTP servers */
813 0x00, SD_DHCP6_OPTION_SNTP_SERVER, 0x00, 0x20,
814 SNTP1_BYTES,
815 SNTP2_BYTES,
816 /* NTP servers */
817 0x00, SD_DHCP6_OPTION_NTP_SERVER, 0x00, 0x37,
818 /* NTP server (address suboption) */
819 0x00, DHCP6_NTP_SUBOPTION_SRV_ADDR, 0x00, 0x10,
820 NTP1_BYTES,
821 /* NTP server (address suboption) */
822 0x00, DHCP6_NTP_SUBOPTION_SRV_ADDR, 0x00, 0x10,
823 NTP2_BYTES,
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,
827 /* Domain list */
828 0x00, SD_DHCP6_OPTION_DOMAIN, 0x00, 0x0b,
829 0x03, 'l', 'a', 'b', 0x05, 'i', 'n', 't', 'r', 'a', 0x00,
830 /* Client FQDN */
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,
836 };
837
838 static void test_client_verify_information_request(const DHCP6Message *msg, size_t len) {
839 log_debug("/* %s */", __func__);
840
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);
844 }
845
846 static void test_client_verify_solicit(const DHCP6Message *msg, size_t len) {
847 log_debug("/* %s */", __func__);
848
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);
852 }
853
854 static void test_client_verify_release(const DHCP6Message *msg, size_t len) {
855 log_debug("/* %s */", __func__);
856
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);
862 }
863
864 static void test_client_verify_request(const DHCP6Message *msg, size_t len) {
865 log_debug("/* %s */", __func__);
866
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);
872 }
873
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;
878 const char *str;
879 char **strv;
880 uint8_t *id;
881 size_t len;
882
883 assert_se(sd_dhcp6_client_get_lease(client, &lease) >= 0);
884
885 assert_se(dhcp6_lease_get_clientid(lease, &id, &len) >= 0);
886 assert_se(memcmp_nn(id, len, client_id, sizeof(client_id)) == 0);
887
888 assert_se(sd_dhcp6_lease_get_domains(lease, &strv) == 1);
889 assert_se(streq(strv[0], "lab.intra"));
890 assert_se(!strv[1]);
891
892 assert_se(sd_dhcp6_lease_get_fqdn(lease, &str) >= 0);
893 assert_se(streq(str, "client.lab.intra"));
894
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));
898
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));
902
903 assert_se(sd_dhcp6_lease_get_ntp_fqdn(lease, &strv) == 1);
904 assert_se(streq(strv[0], "ntp.intra"));
905 assert_se(!strv[1]);
906
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));
910
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);
915 }
916
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;
922 size_t len;
923
924 assert_se(sd_dhcp6_client_get_lease(client, &lease) >= 0);
925
926 assert_se(dhcp6_lease_get_serverid(lease, &id, &len) >= 0);
927 assert_se(memcmp_nn(id, len, server_id, sizeof(server_id)) == 0);
928
929 assert_se(sd_dhcp6_lease_has_address(lease));
930 assert_se(sd_dhcp6_lease_has_pd_prefix(lease));
931
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, &lt_pref, &lt_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, &lt_pref, &lt_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));
946
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, &lt_pref, &lt_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, &lt_pref, &lt_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));
962 }
963
964 test_lease_common(client);
965 }
966
967 static void test_client_callback(sd_dhcp6_client *client, int event, void *userdata) {
968 switch (event) {
969 case SD_DHCP6_CLIENT_EVENT_STOP:
970 log_debug("/* %s (event=stop) */", __func__);
971 return;
972
973 case SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST:
974 log_debug("/* %s (event=information-request) */", __func__);
975
976 assert_se(test_client_sent_message_count == 1);
977
978 test_lease_common(client);
979
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);
983 break;
984
985 case SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE:
986 log_debug("/* %s (event=ip-acquire) */", __func__);
987
988 assert_se(IN_SET(test_client_sent_message_count, 3, 5));
989
990 test_lease_managed(client);
991
992 switch (test_client_sent_message_count) {
993 case 3:
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);
997 break;
998
999 case 5:
1000 assert_se(sd_event_exit(sd_dhcp6_client_get_event(client), 0) >= 0);
1001 break;
1002
1003 default:
1004 assert_not_reached();
1005 }
1006
1007 break;
1008
1009 case DHCP6_CLIENT_EVENT_TEST_ADVERTISED: {
1010 sd_dhcp6_lease *lease;
1011 uint8_t preference;
1012
1013 log_debug("/* %s (event=test-advertised) */", __func__);
1014
1015 assert_se(test_client_sent_message_count == 2);
1016
1017 test_lease_managed(client);
1018
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);
1022
1023 assert_se(dhcp6_client_set_transaction_id(client, ((const DHCP6Message*) msg_reply)->transaction_id) >= 0);
1024 break;
1025 }
1026 default:
1027 assert_not_reached();
1028 }
1029 }
1030
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);
1033
1034 assert_se(a);
1035 assert_se(in6_addr_equal(a, &mcast_address));
1036 assert_se(packet);
1037 assert_se(len >= sizeof(DHCP6Message));
1038
1039 switch (test_client_sent_message_count) {
1040 case 0:
1041 test_client_verify_information_request(packet, len);
1042 assert_se(write(test_fd[1], msg_reply, sizeof(msg_reply)) == sizeof(msg_reply));
1043 break;
1044
1045 case 1:
1046 test_client_verify_solicit(packet, len);
1047 assert_se(write(test_fd[1], msg_advertise, sizeof(msg_advertise)) == sizeof(msg_advertise));
1048 break;
1049
1050 case 2:
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));
1054 break;
1055
1056 case 3:
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));
1060 break;
1061
1062 case 4:
1063 test_client_verify_solicit(packet, len);
1064 assert_se(write(test_fd[1], msg_reply, sizeof(msg_reply)) == sizeof(msg_reply));
1065 break;
1066
1067 default:
1068 assert_not_reached();
1069 }
1070
1071 test_client_sent_message_count++;
1072 return len;
1073 }
1074
1075 int dhcp6_network_bind_udp_socket(int ifindex, struct in6_addr *a) {
1076 assert_se(ifindex == test_ifindex);
1077 assert_se(a);
1078 assert_se(in6_addr_equal(a, &local_address));
1079
1080 assert_se(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) >= 0);
1081 return TAKE_FD(test_fd[0]);
1082 }
1083
1084 TEST(dhcp6_client) {
1085 _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL;
1086 _cleanup_(sd_event_unrefp) sd_event *e = NULL;
1087
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);
1092
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);
1100
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);
1105
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);
1108
1109 assert_se(sd_dhcp6_client_start(client) >= 0);
1110
1111 assert_se(dhcp6_client_set_transaction_id(client, ((const DHCP6Message*) msg_reply)->transaction_id) >= 0);
1112
1113 assert_se(client_ref = sd_dhcp6_client_ref(client));
1114
1115 assert_se(sd_event_loop(e) >= 0);
1116
1117 assert_se(test_client_sent_message_count == 5);
1118
1119 assert_se(!sd_dhcp6_client_unref(client_ref));
1120 test_fd[1] = safe_close(test_fd[1]);
1121 }
1122
1123 static int intro(void) {
1124 assert_se(setenv("SYSTEMD_NETWORK_TEST_MODE", "1", 1) >= 0);
1125 return 0;
1126 }
1127
1128 DEFINE_TEST_MAIN_WITH_INTRO(LOG_DEBUG, intro);