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