]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-network/test-dhcp6-client.c
sd-radv: Allocate space also for DNSSL iov option (#7144)
[thirdparty/systemd.git] / src / libsystemd-network / test-dhcp6-client.c
1 /***
2 This file is part of systemd.
3
4 Copyright (C) 2014 Intel Corporation. All rights reserved.
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <net/ethernet.h>
21 #include <stdbool.h>
22 #include <stdio.h>
23 #include <sys/socket.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26
27 #include "sd-dhcp6-client.h"
28 #include "sd-event.h"
29
30 #include "dhcp6-internal.h"
31 #include "dhcp6-lease-internal.h"
32 #include "dhcp6-protocol.h"
33 #include "fd-util.h"
34 #include "macro.h"
35 #include "socket-util.h"
36 #include "virt.h"
37
38 static struct ether_addr mac_addr = {
39 .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
40 };
41
42 static bool verbose = true;
43
44 static sd_event_source *hangcheck;
45 static int test_dhcp_fd[2];
46 static int test_index = 42;
47 static int test_client_message_num;
48 static be32_t test_iaid = 0;
49 static uint8_t test_duid[14] = { };
50
51 static int test_client_basic(sd_event *e) {
52 sd_dhcp6_client *client;
53
54 if (verbose)
55 printf("* %s\n", __FUNCTION__);
56
57 assert_se(sd_dhcp6_client_new(&client) >= 0);
58 assert_se(client);
59
60 assert_se(sd_dhcp6_client_attach_event(client, e, 0) >= 0);
61
62 assert_se(sd_dhcp6_client_set_ifindex(client, 15) == 0);
63 assert_se(sd_dhcp6_client_set_ifindex(client, -42) == -EINVAL);
64 assert_se(sd_dhcp6_client_set_ifindex(client, -1) == 0);
65 assert_se(sd_dhcp6_client_set_ifindex(client, 42) >= 0);
66
67 assert_se(sd_dhcp6_client_set_mac(client, (const uint8_t *) &mac_addr,
68 sizeof (mac_addr),
69 ARPHRD_ETHER) >= 0);
70
71 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_CLIENTID) == -EINVAL);
72 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DNS_SERVERS) == -EEXIST);
73 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_NTP_SERVER) == -EEXIST);
74 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_SNTP_SERVERS) == -EEXIST);
75 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DOMAIN_LIST) == -EEXIST);
76 assert_se(sd_dhcp6_client_set_request_option(client, 10) == -EINVAL);
77
78 assert_se(sd_dhcp6_client_set_callback(client, NULL, NULL) >= 0);
79
80 assert_se(sd_dhcp6_client_detach_event(client) >= 0);
81 assert_se(!sd_dhcp6_client_unref(client));
82
83 return 0;
84 }
85
86 static int test_option(sd_event *e) {
87 uint8_t packet[] = {
88 'F', 'O', 'O',
89 0x00, SD_DHCP6_OPTION_ORO, 0x00, 0x07,
90 'A', 'B', 'C', 'D', 'E', 'F', 'G',
91 0x00, SD_DHCP6_OPTION_VENDOR_CLASS, 0x00, 0x09,
92 '1', '2', '3', '4', '5', '6', '7', '8', '9',
93 'B', 'A', 'R',
94 };
95 uint8_t result[] = {
96 'F', 'O', 'O',
97 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
98 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
99 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100 'B', 'A', 'R',
101 };
102 uint16_t optcode;
103 size_t optlen;
104 uint8_t *optval, *buf, *out;
105 size_t zero = 0, pos = 3;
106 size_t buflen = sizeof(packet), outlen = sizeof(result);
107
108 if (verbose)
109 printf("* %s\n", __FUNCTION__);
110
111 assert_se(buflen == outlen);
112
113 assert_se(dhcp6_option_parse(&buf, &zero, &optcode, &optlen,
114 &optval) == -ENOMSG);
115
116 buflen -= 3;
117 buf = &packet[3];
118 outlen -= 3;
119 out = &result[3];
120
121 assert_se(dhcp6_option_parse(&buf, &buflen, &optcode, &optlen,
122 &optval) >= 0);
123 pos += 4 + optlen;
124 assert_se(buf == &packet[pos]);
125 assert_se(optcode == SD_DHCP6_OPTION_ORO);
126 assert_se(optlen == 7);
127 assert_se(buflen + pos == sizeof(packet));
128
129 assert_se(dhcp6_option_append(&out, &outlen, optcode, optlen,
130 optval) >= 0);
131 assert_se(out == &result[pos]);
132 assert_se(*out == 0x00);
133
134 assert_se(dhcp6_option_parse(&buf, &buflen, &optcode, &optlen,
135 &optval) >= 0);
136 pos += 4 + optlen;
137 assert_se(buf == &packet[pos]);
138 assert_se(optcode == SD_DHCP6_OPTION_VENDOR_CLASS);
139 assert_se(optlen == 9);
140 assert_se(buflen + pos == sizeof(packet));
141
142 assert_se(dhcp6_option_append(&out, &outlen, optcode, optlen,
143 optval) >= 0);
144 assert_se(out == &result[pos]);
145 assert_se(*out == 'B');
146
147 assert_se(memcmp(packet, result, sizeof(packet)) == 0);
148
149 return 0;
150 }
151
152 static uint8_t msg_advertise[198] = {
153 0x02, 0x0f, 0xb4, 0xe5, 0x00, 0x01, 0x00, 0x0e,
154 0x00, 0x01, 0x00, 0x01, 0x1a, 0x6b, 0xf3, 0x30,
155 0x3c, 0x97, 0x0e, 0xcf, 0xa3, 0x7d, 0x00, 0x03,
156 0x00, 0x5e, 0x0e, 0xcf, 0xa3, 0x7d, 0x00, 0x00,
157 0x00, 0x50, 0x00, 0x00, 0x00, 0x78, 0x00, 0x05,
158 0x00, 0x18, 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad,
159 0xbe, 0xef, 0x78, 0xee, 0x1c, 0xf3, 0x09, 0x3c,
160 0x55, 0xad, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00,
161 0x00, 0xb4, 0x00, 0x0d, 0x00, 0x32, 0x00, 0x00,
162 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x28,
163 0x65, 0x73, 0x29, 0x20, 0x72, 0x65, 0x6e, 0x65,
164 0x77, 0x65, 0x64, 0x2e, 0x20, 0x47, 0x72, 0x65,
165 0x65, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x66,
166 0x72, 0x6f, 0x6d, 0x20, 0x70, 0x6c, 0x61, 0x6e,
167 0x65, 0x74, 0x20, 0x45, 0x61, 0x72, 0x74, 0x68,
168 0x00, 0x17, 0x00, 0x10, 0x20, 0x01, 0x0d, 0xb8,
169 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00,
170 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x0b,
171 0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74,
172 0x72, 0x61, 0x00, 0x00, 0x1f, 0x00, 0x10, 0x20,
173 0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00,
174 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
175 0x02, 0x00, 0x0e, 0x00, 0x01, 0x00, 0x01, 0x19,
176 0x40, 0x5c, 0x53, 0x78, 0x2b, 0xcb, 0xb3, 0x6d,
177 0x53, 0x00, 0x07, 0x00, 0x01, 0x00
178 };
179
180 static uint8_t msg_reply[173] = {
181 0x07, 0xf7, 0x4e, 0x57, 0x00, 0x02, 0x00, 0x0e,
182 0x00, 0x01, 0x00, 0x01, 0x19, 0x40, 0x5c, 0x53,
183 0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53, 0x00, 0x01,
184 0x00, 0x0e, 0x00, 0x01, 0x00, 0x01, 0x1a, 0x6b,
185 0xf3, 0x30, 0x3c, 0x97, 0x0e, 0xcf, 0xa3, 0x7d,
186 0x00, 0x03, 0x00, 0x4a, 0x0e, 0xcf, 0xa3, 0x7d,
187 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x78,
188 0x00, 0x05, 0x00, 0x18, 0x20, 0x01, 0x0d, 0xb8,
189 0xde, 0xad, 0xbe, 0xef, 0x78, 0xee, 0x1c, 0xf3,
190 0x09, 0x3c, 0x55, 0xad, 0x00, 0x00, 0x00, 0x96,
191 0x00, 0x00, 0x00, 0xb4, 0x00, 0x0d, 0x00, 0x1e,
192 0x00, 0x00, 0x41, 0x6c, 0x6c, 0x20, 0x61, 0x64,
193 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x20,
194 0x77, 0x65, 0x72, 0x65, 0x20, 0x61, 0x73, 0x73,
195 0x69, 0x67, 0x6e, 0x65, 0x64, 0x2e, 0x00, 0x17,
196 0x00, 0x10, 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad,
197 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
198 0x00, 0x01, 0x00, 0x18, 0x00, 0x0b, 0x03, 0x6c,
199 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74, 0x72, 0x61,
200 0x00, 0x00, 0x1f, 0x00, 0x10, 0x20, 0x01, 0x0d,
201 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00,
202 0x00, 0x00, 0x00, 0x00, 0x01
203 };
204
205 static int test_advertise_option(sd_event *e) {
206 _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
207 DHCP6Message *advertise = (DHCP6Message *)msg_advertise;
208 uint8_t *optval, *opt = msg_advertise + sizeof(DHCP6Message);
209 uint16_t optcode;
210 size_t optlen, len = sizeof(msg_advertise) - sizeof(DHCP6Message);
211 be32_t val;
212 uint8_t preference = 255;
213 struct in6_addr addr;
214 uint32_t lt_pref, lt_valid;
215 int r;
216 bool opt_clientid = false;
217 struct in6_addr *addrs;
218 char **domains;
219
220 if (verbose)
221 printf("* %s\n", __FUNCTION__);
222
223 assert_se(dhcp6_lease_new(&lease) >= 0);
224
225 assert_se(advertise->type == DHCP6_ADVERTISE);
226 assert_se((be32toh(advertise->transaction_id) & 0x00ffffff) ==
227 0x0fb4e5);
228
229 while ((r = dhcp6_option_parse(&opt, &len, &optcode, &optlen,
230 &optval)) >= 0) {
231
232 switch(optcode) {
233 case SD_DHCP6_OPTION_CLIENTID:
234 assert_se(optlen == 14);
235
236 opt_clientid = true;
237 break;
238
239 case SD_DHCP6_OPTION_IA_NA:
240 assert_se(optlen == 94);
241 assert_se(!memcmp(optval, &msg_advertise[26], optlen));
242
243 val = htobe32(0x0ecfa37d);
244 assert_se(!memcmp(optval, &val, sizeof(val)));
245
246 val = htobe32(80);
247 assert_se(!memcmp(optval + 4, &val, sizeof(val)));
248
249 val = htobe32(120);
250 assert_se(!memcmp(optval + 8, &val, sizeof(val)));
251
252 assert_se(dhcp6_option_parse_ia(&optval, &optlen,
253 optcode,
254 &lease->ia) >= 0);
255
256 break;
257
258 case SD_DHCP6_OPTION_SERVERID:
259 assert_se(optlen == 14);
260 assert_se(!memcmp(optval, &msg_advertise[179], optlen));
261
262 assert_se(dhcp6_lease_set_serverid(lease, optval,
263 optlen) >= 0);
264 break;
265
266 case SD_DHCP6_OPTION_PREFERENCE:
267 assert_se(optlen == 1);
268 assert_se(!*optval);
269
270 assert_se(dhcp6_lease_set_preference(lease,
271 *optval) >= 0);
272 break;
273
274 case SD_DHCP6_OPTION_ELAPSED_TIME:
275 assert_se(optlen == 2);
276
277 break;
278
279 case SD_DHCP6_OPTION_DNS_SERVERS:
280 assert_se(optlen == 16);
281 assert_se(dhcp6_lease_set_dns(lease, optval,
282 optlen) >= 0);
283 break;
284
285 case SD_DHCP6_OPTION_DOMAIN_LIST:
286 assert_se(optlen == 11);
287 assert_se(dhcp6_lease_set_domains(lease, optval,
288 optlen) >= 0);
289 break;
290
291 case SD_DHCP6_OPTION_SNTP_SERVERS:
292 assert_se(optlen == 16);
293 assert_se(dhcp6_lease_set_sntp(lease, optval,
294 optlen) >= 0);
295 break;
296
297 default:
298 break;
299 }
300 }
301
302
303 assert_se(r == -ENOMSG);
304
305 assert_se(opt_clientid);
306
307 sd_dhcp6_lease_reset_address_iter(lease);
308 assert_se(sd_dhcp6_lease_get_address(lease, &addr, &lt_pref,
309 &lt_valid) >= 0);
310 assert_se(!memcmp(&addr, &msg_advertise[42], sizeof(addr)));
311 assert_se(lt_pref == 150);
312 assert_se(lt_valid == 180);
313 assert_se(sd_dhcp6_lease_get_address(lease, &addr, &lt_pref,
314 &lt_valid) == -ENOMSG);
315
316 sd_dhcp6_lease_reset_address_iter(lease);
317 assert_se(sd_dhcp6_lease_get_address(lease, &addr, &lt_pref,
318 &lt_valid) >= 0);
319 assert_se(!memcmp(&addr, &msg_advertise[42], sizeof(addr)));
320 assert_se(sd_dhcp6_lease_get_address(lease, &addr, &lt_pref,
321 &lt_valid) == -ENOMSG);
322 sd_dhcp6_lease_reset_address_iter(lease);
323 assert_se(sd_dhcp6_lease_get_address(lease, &addr, &lt_pref,
324 &lt_valid) >= 0);
325 assert_se(!memcmp(&addr, &msg_advertise[42], sizeof(addr)));
326 assert_se(sd_dhcp6_lease_get_address(lease, &addr, &lt_pref,
327 &lt_valid) == -ENOMSG);
328
329 assert_se(dhcp6_lease_get_serverid(lease, &opt, &len) >= 0);
330 assert_se(len == 14);
331 assert_se(!memcmp(opt, &msg_advertise[179], len));
332
333 assert_se(dhcp6_lease_get_preference(lease, &preference) >= 0);
334 assert_se(preference == 0);
335
336 r = sd_dhcp6_lease_get_dns(lease, &addrs);
337 assert_se(r == 1);
338 assert_se(!memcmp(addrs, &msg_advertise[124], r * 16));
339
340 r = sd_dhcp6_lease_get_domains(lease, &domains);
341 assert_se(r == 1);
342 assert_se(!strcmp("lab.intra", domains[0]));
343 assert_se(domains[1] == NULL);
344
345 r = sd_dhcp6_lease_get_ntp_addrs(lease, &addrs);
346 assert_se(r == 1);
347 assert_se(!memcmp(addrs, &msg_advertise[159], r * 16));
348
349 return 0;
350 }
351
352 static int test_hangcheck(sd_event_source *s, uint64_t usec, void *userdata) {
353 assert_not_reached("Test case should have completed in 2 seconds");
354
355 return 0;
356 }
357
358 static void test_client_solicit_cb(sd_dhcp6_client *client, int event,
359 void *userdata) {
360 sd_event *e = userdata;
361 sd_dhcp6_lease *lease;
362 struct in6_addr *addrs;
363 char **domains;
364
365 assert_se(e);
366 assert_se(event == SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE);
367
368 assert_se(sd_dhcp6_client_get_lease(client, &lease) >= 0);
369
370 assert_se(sd_dhcp6_lease_get_domains(lease, &domains) == 1);
371 assert_se(!strcmp("lab.intra", domains[0]));
372 assert_se(domains[1] == NULL);
373
374 assert_se(sd_dhcp6_lease_get_dns(lease, &addrs) == 1);
375 assert_se(!memcmp(addrs, &msg_advertise[124], 16));
376
377 assert_se(sd_dhcp6_lease_get_ntp_addrs(lease, &addrs) == 1);
378 assert_se(!memcmp(addrs, &msg_advertise[159], 16));
379
380 assert_se(sd_dhcp6_client_set_request_option(client, SD_DHCP6_OPTION_DNS_SERVERS) == -EBUSY);
381
382 if (verbose)
383 printf(" got DHCPv6 event %d\n", event);
384
385 sd_event_exit(e, 0);
386 }
387
388 static int test_client_send_reply(DHCP6Message *request) {
389 DHCP6Message reply;
390
391 reply.transaction_id = request->transaction_id;
392 reply.type = DHCP6_REPLY;
393
394 memcpy(msg_reply, &reply.transaction_id, 4);
395
396 memcpy(&msg_reply[26], test_duid, sizeof(test_duid));
397
398 memcpy(&msg_reply[44], &test_iaid, sizeof(test_iaid));
399
400 assert_se(write(test_dhcp_fd[1], msg_reply, sizeof(msg_reply))
401 == sizeof(msg_reply));
402
403 return 0;
404 }
405
406 static int test_client_verify_request(DHCP6Message *request, uint8_t *option,
407 size_t len) {
408 _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
409 uint8_t *optval;
410 uint16_t optcode;
411 size_t optlen;
412 bool found_clientid = false, found_iana = false, found_serverid = false,
413 found_elapsed_time = false;
414 int r;
415 struct in6_addr addr;
416 be32_t val;
417 uint32_t lt_pref, lt_valid;
418
419 assert_se(request->type == DHCP6_REQUEST);
420
421 assert_se(dhcp6_lease_new(&lease) >= 0);
422
423 while ((r = dhcp6_option_parse(&option, &len,
424 &optcode, &optlen, &optval)) >= 0) {
425 switch(optcode) {
426 case SD_DHCP6_OPTION_CLIENTID:
427 assert_se(!found_clientid);
428 found_clientid = true;
429
430 assert_se(!memcmp(optval, &test_duid,
431 sizeof(test_duid)));
432
433 break;
434
435 case SD_DHCP6_OPTION_IA_NA:
436 assert_se(!found_iana);
437 found_iana = true;
438
439
440 assert_se(optlen == 40);
441 assert_se(!memcmp(optval, &test_iaid, sizeof(test_iaid)));
442
443 val = htobe32(80);
444 assert_se(!memcmp(optval + 4, &val, sizeof(val)));
445
446 val = htobe32(120);
447 assert_se(!memcmp(optval + 8, &val, sizeof(val)));
448
449 assert_se(!dhcp6_option_parse_ia(&optval, &optlen,
450 optcode, &lease->ia));
451
452 break;
453
454 case SD_DHCP6_OPTION_SERVERID:
455 assert_se(!found_serverid);
456 found_serverid = true;
457
458 assert_se(optlen == 14);
459 assert_se(!memcmp(&msg_advertise[179], optval, optlen));
460
461 break;
462
463 case SD_DHCP6_OPTION_ELAPSED_TIME:
464 assert_se(!found_elapsed_time);
465 found_elapsed_time = true;
466
467 assert_se(optlen == 2);
468
469 break;
470 }
471 }
472
473 assert_se(r == -ENOMSG);
474 assert_se(found_clientid && found_iana && found_serverid &&
475 found_elapsed_time);
476
477 sd_dhcp6_lease_reset_address_iter(lease);
478 assert_se(sd_dhcp6_lease_get_address(lease, &addr, &lt_pref,
479 &lt_valid) >= 0);
480 assert_se(!memcmp(&addr, &msg_advertise[42], sizeof(addr)));
481 assert_se(lt_pref == 150);
482 assert_se(lt_valid == 180);
483
484 assert_se(sd_dhcp6_lease_get_address(lease, &addr, &lt_pref,
485 &lt_valid) == -ENOMSG);
486
487 return 0;
488 }
489
490 static int test_client_send_advertise(DHCP6Message *solicit) {
491 DHCP6Message advertise;
492
493 advertise.transaction_id = solicit->transaction_id;
494 advertise.type = DHCP6_ADVERTISE;
495
496 memcpy(msg_advertise, &advertise.transaction_id, 4);
497
498 memcpy(&msg_advertise[8], test_duid, sizeof(test_duid));
499
500 memcpy(&msg_advertise[26], &test_iaid, sizeof(test_iaid));
501
502 assert_se(write(test_dhcp_fd[1], msg_advertise, sizeof(msg_advertise))
503 == sizeof(msg_advertise));
504
505 return 0;
506 }
507
508 static int test_client_verify_solicit(DHCP6Message *solicit, uint8_t *option,
509 size_t len) {
510 uint8_t *optval;
511 uint16_t optcode;
512 size_t optlen;
513 bool found_clientid = false, found_iana = false,
514 found_elapsed_time = false;
515 int r;
516
517 assert_se(solicit->type == DHCP6_SOLICIT);
518
519 while ((r = dhcp6_option_parse(&option, &len,
520 &optcode, &optlen, &optval)) >= 0) {
521 switch(optcode) {
522 case SD_DHCP6_OPTION_CLIENTID:
523 assert_se(!found_clientid);
524 found_clientid = true;
525
526 assert_se(optlen == sizeof(test_duid));
527 memcpy(&test_duid, optval, sizeof(test_duid));
528
529 break;
530
531 case SD_DHCP6_OPTION_IA_NA:
532 assert_se(!found_iana);
533 found_iana = true;
534
535 assert_se(optlen == 12);
536
537 memcpy(&test_iaid, optval, sizeof(test_iaid));
538
539 break;
540
541 case SD_DHCP6_OPTION_ELAPSED_TIME:
542 assert_se(!found_elapsed_time);
543 found_elapsed_time = true;
544
545 assert_se(optlen == 2);
546
547 break;
548 }
549 }
550
551 assert_se(r == -ENOMSG);
552 assert_se(found_clientid && found_iana && found_elapsed_time);
553
554 return 0;
555 }
556
557 static void test_client_information_cb(sd_dhcp6_client *client, int event,
558 void *userdata) {
559 sd_event *e = userdata;
560 sd_dhcp6_lease *lease;
561 struct in6_addr *addrs;
562 struct in6_addr address = { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 } } };
563 char **domains;
564
565 assert_se(e);
566 assert_se(event == SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST);
567
568 assert_se(sd_dhcp6_client_get_lease(client, &lease) >= 0);
569
570 assert_se(sd_dhcp6_lease_get_domains(lease, &domains) == 1);
571 assert_se(!strcmp("lab.intra", domains[0]));
572 assert_se(domains[1] == NULL);
573
574 assert_se(sd_dhcp6_lease_get_dns(lease, &addrs) == 1);
575 assert_se(!memcmp(addrs, &msg_advertise[124], 16));
576
577 assert_se(sd_dhcp6_lease_get_ntp_addrs(lease, &addrs) == 1);
578 assert_se(!memcmp(addrs, &msg_advertise[159], 16));
579
580 if (verbose)
581 printf(" got DHCPv6 event %d\n", event);
582
583 assert_se(sd_dhcp6_client_set_information_request(client, false) == -EBUSY);
584 assert_se(sd_dhcp6_client_set_callback(client, NULL, e) >= 0);
585 assert_se(sd_dhcp6_client_stop(client) >= 0);
586 assert_se(sd_dhcp6_client_set_information_request(client, false) >= 0);
587
588 assert_se(sd_dhcp6_client_set_callback(client,
589 test_client_solicit_cb, e) >= 0);
590
591 assert_se(sd_dhcp6_client_set_local_address(client, &address) >= 0);
592
593 assert_se(sd_dhcp6_client_start(client) >= 0);
594 }
595
596 static int test_client_verify_information_request(DHCP6Message *information_request,
597 uint8_t *option, size_t len) {
598
599 _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
600 uint8_t *optval;
601 uint16_t optcode;
602 size_t optlen;
603 bool found_clientid = false, found_elapsed_time = false;
604 int r;
605 struct in6_addr addr;
606 uint32_t lt_pref, lt_valid;
607
608 assert_se(information_request->type == DHCP6_INFORMATION_REQUEST);
609
610 assert_se(dhcp6_lease_new(&lease) >= 0);
611
612 while ((r = dhcp6_option_parse(&option, &len,
613 &optcode, &optlen, &optval)) >= 0) {
614 switch(optcode) {
615 case SD_DHCP6_OPTION_CLIENTID:
616 assert_se(!found_clientid);
617 found_clientid = true;
618
619 assert_se(optlen == sizeof(test_duid));
620 memcpy(&test_duid, optval, sizeof(test_duid));
621
622 break;
623
624 case SD_DHCP6_OPTION_IA_NA:
625 assert_not_reached("IA TA option must not be present");
626
627 break;
628
629 case SD_DHCP6_OPTION_SERVERID:
630 assert_not_reached("Server ID option must not be present");
631
632 break;
633
634 case SD_DHCP6_OPTION_ELAPSED_TIME:
635 assert_se(!found_elapsed_time);
636 found_elapsed_time = true;
637
638 assert_se(optlen == 2);
639
640 break;
641 }
642 }
643
644 assert_se(r == -ENOMSG);
645 assert_se(found_clientid && found_elapsed_time);
646
647 sd_dhcp6_lease_reset_address_iter(lease);
648
649 assert_se(sd_dhcp6_lease_get_address(lease, &addr, &lt_pref,
650 &lt_valid) == -ENOMSG);
651
652 return 0;
653 }
654
655 int dhcp6_network_send_udp_socket(int s, struct in6_addr *server_address,
656 const void *packet, size_t len) {
657 struct in6_addr mcast =
658 IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT;
659 DHCP6Message *message;
660 uint8_t *option;
661
662 assert_se(s == test_dhcp_fd[0]);
663 assert_se(server_address);
664 assert_se(packet);
665 assert_se(len > sizeof(DHCP6Message) + 4);
666
667 assert_se(IN6_ARE_ADDR_EQUAL(server_address, &mcast));
668
669 message = (DHCP6Message *)packet;
670 option = (uint8_t *)(message + 1);
671 len -= sizeof(DHCP6Message);
672
673 assert_se(message->transaction_id & 0x00ffffff);
674
675 if (test_client_message_num == 0) {
676 test_client_verify_information_request(message, option, len);
677 test_client_send_reply(message);
678 test_client_message_num++;
679 } else if (test_client_message_num == 1) {
680 test_client_verify_solicit(message, option, len);
681 test_client_send_advertise(message);
682 test_client_message_num++;
683 } else if (test_client_message_num == 2) {
684 test_client_verify_request(message, option, len);
685 test_client_send_reply(message);
686 test_client_message_num++;
687 }
688
689 return len;
690 }
691
692 int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) {
693 assert_se(index == test_index);
694
695 if (socketpair(AF_UNIX, SOCK_STREAM, 0, test_dhcp_fd) < 0)
696 return -errno;
697
698 return test_dhcp_fd[0];
699 }
700
701 static int test_client_solicit(sd_event *e) {
702 sd_dhcp6_client *client;
703 usec_t time_now = now(clock_boottime_or_monotonic());
704 struct in6_addr address = { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 } } };
705 int val = true;
706
707 if (verbose)
708 printf("* %s\n", __FUNCTION__);
709
710 assert_se(sd_dhcp6_client_new(&client) >= 0);
711 assert_se(client);
712
713 assert_se(sd_dhcp6_client_attach_event(client, e, 0) >= 0);
714
715 assert_se(sd_dhcp6_client_set_ifindex(client, test_index) == 0);
716 assert_se(sd_dhcp6_client_set_mac(client, (const uint8_t *) &mac_addr,
717 sizeof (mac_addr),
718 ARPHRD_ETHER) >= 0);
719
720 assert_se(sd_dhcp6_client_get_information_request(client, &val) >= 0);
721 assert_se(val == false);
722 assert_se(sd_dhcp6_client_set_information_request(client, true) >= 0);
723 assert_se(sd_dhcp6_client_get_information_request(client, &val) >= 0);
724 assert_se(val == true);
725
726 assert_se(sd_dhcp6_client_set_callback(client,
727 test_client_information_cb, e) >= 0);
728
729 assert_se(sd_event_add_time(e, &hangcheck, clock_boottime_or_monotonic(),
730 time_now + 2 * USEC_PER_SEC, 0,
731 test_hangcheck, NULL) >= 0);
732
733 assert_se(sd_dhcp6_client_set_local_address(client, &address) >= 0);
734
735 assert_se(sd_dhcp6_client_start(client) >= 0);
736
737 sd_event_loop(e);
738
739 hangcheck = sd_event_source_unref(hangcheck);
740
741 assert_se(!sd_dhcp6_client_unref(client));
742
743 test_dhcp_fd[1] = safe_close(test_dhcp_fd[1]);
744
745 return 0;
746 }
747
748 int main(int argc, char *argv[]) {
749 _cleanup_(sd_event_unrefp) sd_event *e;
750
751 assert_se(sd_event_new(&e) >= 0);
752
753 log_set_max_level(LOG_DEBUG);
754 log_parse_environment();
755 log_open();
756
757 test_client_basic(e);
758 test_option(e);
759 test_advertise_option(e);
760 test_client_solicit(e);
761
762 return 0;
763 }