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