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