]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-network/test-dhcp6-client.c
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
[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 "fd-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_(sd_dhcp6_lease_unrefp) 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_(sd_dhcp6_lease_unrefp) 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 struct in6_addr address = { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 } } };
565 char **domains;
566
567 assert_se(e);
568 assert_se(event == SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST);
569
570 assert_se(sd_dhcp6_client_get_lease(client, &lease) >= 0);
571
572 assert_se(sd_dhcp6_lease_get_domains(lease, &domains) == 1);
573 assert_se(!strcmp("lab.intra", domains[0]));
574 assert_se(domains[1] == NULL);
575
576 assert_se(sd_dhcp6_lease_get_dns(lease, &addrs) == 1);
577 assert_se(!memcmp(addrs, &msg_advertise[124], 16));
578
579 assert_se(sd_dhcp6_lease_get_ntp_addrs(lease, &addrs) == 1);
580 assert_se(!memcmp(addrs, &msg_advertise[159], 16));
581
582 if (verbose)
583 printf(" got DHCPv6 event %d\n", event);
584
585 assert_se(sd_dhcp6_client_set_information_request(client, false) == -EBUSY);
586 assert_se(sd_dhcp6_client_set_callback(client, NULL, e) >= 0);
587 assert_se(sd_dhcp6_client_stop(client) >= 0);
588 assert_se(sd_dhcp6_client_set_information_request(client, false) >= 0);
589
590 assert_se(sd_dhcp6_client_set_callback(client,
591 test_client_solicit_cb, e) >= 0);
592
593 assert_se(sd_dhcp6_client_set_local_address(client, &address) >= 0);
594
595 assert_se(sd_dhcp6_client_start(client) >= 0);
596 }
597
598 static int test_client_verify_information_request(DHCP6Message *information_request,
599 uint8_t *option, size_t len) {
600
601 _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL;
602 uint8_t *optval;
603 uint16_t optcode;
604 size_t optlen;
605 bool found_clientid = false, found_elapsed_time = false;
606 int r;
607 struct in6_addr addr;
608 uint32_t lt_pref, lt_valid;
609
610 assert_se(information_request->type == DHCP6_INFORMATION_REQUEST);
611
612 assert_se(dhcp6_lease_new(&lease) >= 0);
613
614 while ((r = dhcp6_option_parse(&option, &len,
615 &optcode, &optlen, &optval)) >= 0) {
616 switch(optcode) {
617 case DHCP6_OPTION_CLIENTID:
618 assert_se(!found_clientid);
619 found_clientid = true;
620
621 assert_se(optlen == sizeof(test_duid));
622 memcpy(&test_duid, optval, sizeof(test_duid));
623
624 break;
625
626 case DHCP6_OPTION_IA_NA:
627 assert_not_reached("IA TA option must not be present");
628
629 break;
630
631 case DHCP6_OPTION_SERVERID:
632 assert_not_reached("Server ID option must not be present");
633
634 break;
635
636 case DHCP6_OPTION_ELAPSED_TIME:
637 assert_se(!found_elapsed_time);
638 found_elapsed_time = true;
639
640 assert_se(optlen == 2);
641
642 break;
643 }
644 }
645
646 assert_se(r == -ENOMSG);
647 assert_se(found_clientid && found_elapsed_time);
648
649 sd_dhcp6_lease_reset_address_iter(lease);
650
651 assert_se(sd_dhcp6_lease_get_address(lease, &addr, &lt_pref,
652 &lt_valid) == -ENOMSG);
653
654 return 0;
655 }
656
657 int dhcp6_network_send_udp_socket(int s, struct in6_addr *server_address,
658 const void *packet, size_t len) {
659 struct in6_addr mcast =
660 IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT;
661 DHCP6Message *message;
662 uint8_t *option;
663
664 assert_se(s == test_dhcp_fd[0]);
665 assert_se(server_address);
666 assert_se(packet);
667 assert_se(len > sizeof(DHCP6Message) + 4);
668
669 assert_se(IN6_ARE_ADDR_EQUAL(server_address, &mcast));
670
671 message = (DHCP6Message *)packet;
672 option = (uint8_t *)(message + 1);
673 len -= sizeof(DHCP6Message);
674
675 assert_se(message->transaction_id & 0x00ffffff);
676
677 if (test_client_message_num == 0) {
678 test_client_verify_information_request(message, option, len);
679 test_client_send_reply(message);
680 test_client_message_num++;
681 } else if (test_client_message_num == 1) {
682 test_client_verify_solicit(message, option, len);
683 test_client_send_advertise(message);
684 test_client_message_num++;
685 } else if (test_client_message_num == 2) {
686 test_client_verify_request(message, option, len);
687 test_client_send_reply(message);
688 test_client_message_num++;
689 }
690
691 return len;
692 }
693
694 int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) {
695 assert_se(index == test_index);
696
697 if (socketpair(AF_UNIX, SOCK_STREAM, 0, test_dhcp_fd) < 0)
698 return -errno;
699
700 return test_dhcp_fd[0];
701 }
702
703 static int test_client_solicit(sd_event *e) {
704 sd_dhcp6_client *client;
705 usec_t time_now = now(clock_boottime_or_monotonic());
706 struct in6_addr address = { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 } } };
707 int val = true;
708
709 if (verbose)
710 printf("* %s\n", __FUNCTION__);
711
712 assert_se(sd_dhcp6_client_new(&client) >= 0);
713 assert_se(client);
714
715 assert_se(sd_dhcp6_client_attach_event(client, e, 0) >= 0);
716
717 assert_se(sd_dhcp6_client_set_index(client, test_index) == 0);
718 assert_se(sd_dhcp6_client_set_mac(client, (const uint8_t *) &mac_addr,
719 sizeof (mac_addr),
720 ARPHRD_ETHER) >= 0);
721
722 assert_se(sd_dhcp6_client_get_information_request(client, &val) >= 0);
723 assert_se(val == false);
724 assert_se(sd_dhcp6_client_set_information_request(client, true) >= 0);
725 assert_se(sd_dhcp6_client_get_information_request(client, &val) >= 0);
726 assert_se(val == true);
727
728 assert_se(sd_dhcp6_client_set_callback(client,
729 test_client_information_cb, e) >= 0);
730
731 assert_se(sd_event_add_time(e, &hangcheck, clock_boottime_or_monotonic(),
732 time_now + 2 * USEC_PER_SEC, 0,
733 test_hangcheck, NULL) >= 0);
734
735 assert_se(sd_dhcp6_client_set_local_address(client, &address) >= 0);
736
737 assert_se(sd_dhcp6_client_start(client) >= 0);
738
739 sd_event_loop(e);
740
741 hangcheck = sd_event_source_unref(hangcheck);
742
743 assert_se(!sd_dhcp6_client_unref(client));
744
745 test_dhcp_fd[1] = safe_close(test_dhcp_fd[1]);
746
747 return 0;
748 }
749
750 int main(int argc, char *argv[]) {
751 _cleanup_(sd_event_unrefp) sd_event *e;
752
753 assert_se(sd_event_new(&e) >= 0);
754
755 log_set_max_level(LOG_DEBUG);
756 log_parse_environment();
757 log_open();
758
759 test_client_basic(e);
760 test_option(e);
761 test_advertise_option(e);
762 test_client_solicit(e);
763
764 return 0;
765 }