1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright (C) 2014 Intel Corporation. All rights reserved.
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.
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.
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/>.
22 #include <net/ethernet.h>
25 #include <sys/socket.h>
26 #include <sys/types.h>
29 #include "sd-dhcp6-client.h"
32 #include "dhcp6-internal.h"
33 #include "dhcp6-lease-internal.h"
34 #include "dhcp6-protocol.h"
35 #include "event-util.h"
37 #include "socket-util.h"
40 static struct ether_addr mac_addr
= {
41 .ether_addr_octet
= {'A', 'B', 'C', '1', '2', '3'}
44 static bool verbose
= true;
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] = { };
53 static int test_client_basic(sd_event
*e
) {
54 sd_dhcp6_client
*client
;
57 printf("* %s\n", __FUNCTION__
);
59 assert_se(sd_dhcp6_client_new(&client
) >= 0);
62 assert_se(sd_dhcp6_client_attach_event(client
, e
, 0) >= 0);
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);
69 assert_se(sd_dhcp6_client_set_mac(client
, (const uint8_t *) &mac_addr
,
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
);
80 assert_se(sd_dhcp6_client_set_callback(client
, NULL
, NULL
) >= 0);
82 assert_se(sd_dhcp6_client_detach_event(client
) >= 0);
83 assert_se(!sd_dhcp6_client_unref(client
));
88 static int test_option(sd_event
*e
) {
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',
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,
106 uint8_t *optval
, *buf
, *out
;
107 size_t zero
= 0, pos
= 3;
108 size_t buflen
= sizeof(packet
), outlen
= sizeof(result
);
111 printf("* %s\n", __FUNCTION__
);
113 assert_se(buflen
== outlen
);
115 assert_se(dhcp6_option_parse(&buf
, &zero
, &optcode
, &optlen
,
116 &optval
) == -ENOMSG
);
123 assert_se(dhcp6_option_parse(&buf
, &buflen
, &optcode
, &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
));
131 assert_se(dhcp6_option_append(&out
, &outlen
, optcode
, optlen
,
133 assert_se(out
== &result
[pos
]);
134 assert_se(*out
== 0x00);
136 assert_se(dhcp6_option_parse(&buf
, &buflen
, &optcode
, &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
));
144 assert_se(dhcp6_option_append(&out
, &outlen
, optcode
, optlen
,
146 assert_se(out
== &result
[pos
]);
147 assert_se(*out
== 'B');
149 assert_se(memcmp(packet
, result
, sizeof(packet
)) == 0);
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
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
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
);
212 size_t optlen
, len
= sizeof(msg_advertise
) - sizeof(DHCP6Message
);
214 uint8_t preference
= 255;
215 struct in6_addr addr
;
216 uint32_t lt_pref
, lt_valid
;
218 bool opt_clientid
= false;
219 struct in6_addr
*addrs
;
223 printf("* %s\n", __FUNCTION__
);
225 assert_se(dhcp6_lease_new(&lease
) >= 0);
227 assert_se(advertise
->type
== DHCP6_ADVERTISE
);
228 assert_se((be32toh(advertise
->transaction_id
) & 0x00ffffff) ==
231 while ((r
= dhcp6_option_parse(&opt
, &len
, &optcode
, &optlen
,
235 case DHCP6_OPTION_CLIENTID
:
236 assert_se(optlen
== 14);
241 case DHCP6_OPTION_IA_NA
:
242 assert_se(optlen
== 94);
243 assert_se(!memcmp(optval
, &msg_advertise
[26], optlen
));
245 val
= htobe32(0x0ecfa37d);
246 assert_se(!memcmp(optval
, &val
, sizeof(val
)));
249 assert_se(!memcmp(optval
+ 4, &val
, sizeof(val
)));
252 assert_se(!memcmp(optval
+ 8, &val
, sizeof(val
)));
254 assert_se(dhcp6_option_parse_ia(&optval
, &optlen
,
260 case DHCP6_OPTION_SERVERID
:
261 assert_se(optlen
== 14);
262 assert_se(!memcmp(optval
, &msg_advertise
[179], optlen
));
264 assert_se(dhcp6_lease_set_serverid(lease
, optval
,
268 case DHCP6_OPTION_PREFERENCE
:
269 assert_se(optlen
== 1);
272 assert_se(dhcp6_lease_set_preference(lease
,
276 case DHCP6_OPTION_ELAPSED_TIME
:
277 assert_se(optlen
== 2);
281 case DHCP6_OPTION_DNS_SERVERS
:
282 assert_se(optlen
== 16);
283 assert_se(dhcp6_lease_set_dns(lease
, optval
,
287 case DHCP6_OPTION_DOMAIN_LIST
:
288 assert_se(optlen
== 11);
289 assert_se(dhcp6_lease_set_domains(lease
, optval
,
293 case DHCP6_OPTION_SNTP_SERVERS
:
294 assert_se(optlen
== 16);
295 assert_se(dhcp6_lease_set_sntp(lease
, optval
,
305 assert_se(r
== -ENOMSG
);
307 assert_se(opt_clientid
);
309 sd_dhcp6_lease_reset_address_iter(lease
);
310 assert_se(sd_dhcp6_lease_get_address(lease
, &addr
, <_pref
,
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
, <_pref
,
316 <_valid
) == -ENOMSG
);
318 sd_dhcp6_lease_reset_address_iter(lease
);
319 assert_se(sd_dhcp6_lease_get_address(lease
, &addr
, <_pref
,
321 assert_se(!memcmp(&addr
, &msg_advertise
[42], sizeof(addr
)));
322 assert_se(sd_dhcp6_lease_get_address(lease
, &addr
, <_pref
,
323 <_valid
) == -ENOMSG
);
324 sd_dhcp6_lease_reset_address_iter(lease
);
325 assert_se(sd_dhcp6_lease_get_address(lease
, &addr
, <_pref
,
327 assert_se(!memcmp(&addr
, &msg_advertise
[42], sizeof(addr
)));
328 assert_se(sd_dhcp6_lease_get_address(lease
, &addr
, <_pref
,
329 <_valid
) == -ENOMSG
);
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
));
335 assert_se(dhcp6_lease_get_preference(lease
, &preference
) >= 0);
336 assert_se(preference
== 0);
338 r
= sd_dhcp6_lease_get_dns(lease
, &addrs
);
340 assert_se(!memcmp(addrs
, &msg_advertise
[124], r
* 16));
342 r
= sd_dhcp6_lease_get_domains(lease
, &domains
);
344 assert_se(!strcmp("lab.intra", domains
[0]));
345 assert_se(domains
[1] == NULL
);
347 r
= sd_dhcp6_lease_get_ntp_addrs(lease
, &addrs
);
349 assert_se(!memcmp(addrs
, &msg_advertise
[159], r
* 16));
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");
360 static void test_client_solicit_cb(sd_dhcp6_client
*client
, int event
,
362 sd_event
*e
= userdata
;
363 sd_dhcp6_lease
*lease
;
364 struct in6_addr
*addrs
;
368 assert_se(event
== SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE
);
370 assert_se(sd_dhcp6_client_get_lease(client
, &lease
) >= 0);
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
);
376 assert_se(sd_dhcp6_lease_get_dns(lease
, &addrs
) == 1);
377 assert_se(!memcmp(addrs
, &msg_advertise
[124], 16));
379 assert_se(sd_dhcp6_lease_get_ntp_addrs(lease
, &addrs
) == 1);
380 assert_se(!memcmp(addrs
, &msg_advertise
[159], 16));
382 assert_se(sd_dhcp6_client_set_request_option(client
, DHCP6_OPTION_DNS_SERVERS
) == -EBUSY
);
385 printf(" got DHCPv6 event %d\n", event
);
390 static int test_client_send_reply(DHCP6Message
*request
) {
393 reply
.transaction_id
= request
->transaction_id
;
394 reply
.type
= DHCP6_REPLY
;
396 memcpy(msg_reply
, &reply
.transaction_id
, 4);
398 memcpy(&msg_reply
[26], test_duid
, sizeof(test_duid
));
400 memcpy(&msg_reply
[44], &test_iaid
, sizeof(test_iaid
));
402 assert_se(write(test_dhcp_fd
[1], msg_reply
, sizeof(msg_reply
))
403 == sizeof(msg_reply
));
408 static int test_client_verify_request(DHCP6Message
*request
, uint8_t *option
,
410 _cleanup_dhcp6_lease_free_ sd_dhcp6_lease
*lease
= NULL
;
414 bool found_clientid
= false, found_iana
= false, found_serverid
= false,
415 found_elapsed_time
= false;
417 struct in6_addr addr
;
419 uint32_t lt_pref
, lt_valid
;
421 assert_se(request
->type
== DHCP6_REQUEST
);
423 assert_se(dhcp6_lease_new(&lease
) >= 0);
425 while ((r
= dhcp6_option_parse(&option
, &len
,
426 &optcode
, &optlen
, &optval
)) >= 0) {
428 case DHCP6_OPTION_CLIENTID
:
429 assert_se(!found_clientid
);
430 found_clientid
= true;
432 assert_se(!memcmp(optval
, &test_duid
,
437 case DHCP6_OPTION_IA_NA
:
438 assert_se(!found_iana
);
442 assert_se(optlen
== 40);
443 assert_se(!memcmp(optval
, &test_iaid
, sizeof(test_iaid
)));
446 assert_se(!memcmp(optval
+ 4, &val
, sizeof(val
)));
449 assert_se(!memcmp(optval
+ 8, &val
, sizeof(val
)));
451 assert_se(!dhcp6_option_parse_ia(&optval
, &optlen
,
452 optcode
, &lease
->ia
));
456 case DHCP6_OPTION_SERVERID
:
457 assert_se(!found_serverid
);
458 found_serverid
= true;
460 assert_se(optlen
== 14);
461 assert_se(!memcmp(&msg_advertise
[179], optval
, optlen
));
465 case DHCP6_OPTION_ELAPSED_TIME
:
466 assert_se(!found_elapsed_time
);
467 found_elapsed_time
= true;
469 assert_se(optlen
== 2);
475 assert_se(r
== -ENOMSG
);
476 assert_se(found_clientid
&& found_iana
&& found_serverid
&&
479 sd_dhcp6_lease_reset_address_iter(lease
);
480 assert_se(sd_dhcp6_lease_get_address(lease
, &addr
, <_pref
,
482 assert_se(!memcmp(&addr
, &msg_advertise
[42], sizeof(addr
)));
483 assert_se(lt_pref
== 150);
484 assert_se(lt_valid
== 180);
486 assert_se(sd_dhcp6_lease_get_address(lease
, &addr
, <_pref
,
487 <_valid
) == -ENOMSG
);
492 static int test_client_send_advertise(DHCP6Message
*solicit
) {
493 DHCP6Message advertise
;
495 advertise
.transaction_id
= solicit
->transaction_id
;
496 advertise
.type
= DHCP6_ADVERTISE
;
498 memcpy(msg_advertise
, &advertise
.transaction_id
, 4);
500 memcpy(&msg_advertise
[8], test_duid
, sizeof(test_duid
));
502 memcpy(&msg_advertise
[26], &test_iaid
, sizeof(test_iaid
));
504 assert_se(write(test_dhcp_fd
[1], msg_advertise
, sizeof(msg_advertise
))
505 == sizeof(msg_advertise
));
510 static int test_client_verify_solicit(DHCP6Message
*solicit
, uint8_t *option
,
515 bool found_clientid
= false, found_iana
= false,
516 found_elapsed_time
= false;
519 assert_se(solicit
->type
== DHCP6_SOLICIT
);
521 while ((r
= dhcp6_option_parse(&option
, &len
,
522 &optcode
, &optlen
, &optval
)) >= 0) {
524 case DHCP6_OPTION_CLIENTID
:
525 assert_se(!found_clientid
);
526 found_clientid
= true;
528 assert_se(optlen
== sizeof(test_duid
));
529 memcpy(&test_duid
, optval
, sizeof(test_duid
));
533 case DHCP6_OPTION_IA_NA
:
534 assert_se(!found_iana
);
537 assert_se(optlen
== 12);
539 memcpy(&test_iaid
, optval
, sizeof(test_iaid
));
543 case DHCP6_OPTION_ELAPSED_TIME
:
544 assert_se(!found_elapsed_time
);
545 found_elapsed_time
= true;
547 assert_se(optlen
== 2);
553 assert_se(r
== -ENOMSG
);
554 assert_se(found_clientid
&& found_iana
&& found_elapsed_time
);
559 static void test_client_information_cb(sd_dhcp6_client
*client
, int event
,
561 sd_event
*e
= userdata
;
562 sd_dhcp6_lease
*lease
;
563 struct in6_addr
*addrs
;
567 assert_se(event
== SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST
);
569 assert_se(sd_dhcp6_client_get_lease(client
, &lease
) >= 0);
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
);
575 assert_se(sd_dhcp6_lease_get_dns(lease
, &addrs
) == 1);
576 assert_se(!memcmp(addrs
, &msg_advertise
[124], 16));
578 assert_se(sd_dhcp6_lease_get_ntp_addrs(lease
, &addrs
) == 1);
579 assert_se(!memcmp(addrs
, &msg_advertise
[159], 16));
582 printf(" got DHCPv6 event %d\n", event
);
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);
589 assert_se(sd_dhcp6_client_set_callback(client
,
590 test_client_solicit_cb
, e
) >= 0);
592 assert_se(sd_dhcp6_client_start(client
) >= 0);
595 static int test_client_verify_information_request(DHCP6Message
*information_request
,
596 uint8_t *option
, size_t len
) {
598 _cleanup_dhcp6_lease_free_ sd_dhcp6_lease
*lease
= NULL
;
602 bool found_clientid
= false, found_elapsed_time
= false;
604 struct in6_addr addr
;
605 uint32_t lt_pref
, lt_valid
;
607 assert_se(information_request
->type
== DHCP6_INFORMATION_REQUEST
);
609 assert_se(dhcp6_lease_new(&lease
) >= 0);
611 while ((r
= dhcp6_option_parse(&option
, &len
,
612 &optcode
, &optlen
, &optval
)) >= 0) {
614 case DHCP6_OPTION_CLIENTID
:
615 assert_se(!found_clientid
);
616 found_clientid
= true;
618 assert_se(optlen
== sizeof(test_duid
));
619 memcpy(&test_duid
, optval
, sizeof(test_duid
));
623 case DHCP6_OPTION_IA_NA
:
624 assert_not_reached("IA TA option must not be present");
628 case DHCP6_OPTION_SERVERID
:
629 assert_not_reached("Server ID option must not be present");
633 case DHCP6_OPTION_ELAPSED_TIME
:
634 assert_se(!found_elapsed_time
);
635 found_elapsed_time
= true;
637 assert_se(optlen
== 2);
643 assert_se(r
== -ENOMSG
);
644 assert_se(found_clientid
&& found_elapsed_time
);
646 sd_dhcp6_lease_reset_address_iter(lease
);
648 assert_se(sd_dhcp6_lease_get_address(lease
, &addr
, <_pref
,
649 <_valid
) == -ENOMSG
);
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
;
661 assert_se(s
== test_dhcp_fd
[0]);
662 assert_se(server_address
);
664 assert_se(len
> sizeof(DHCP6Message
) + 4);
666 assert_se(IN6_ARE_ADDR_EQUAL(server_address
, &mcast
));
668 message
= (DHCP6Message
*)packet
;
669 option
= (uint8_t *)(message
+ 1);
670 len
-= sizeof(DHCP6Message
);
672 assert_se(message
->transaction_id
& 0x00ffffff);
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
++;
691 int dhcp6_network_bind_udp_socket(int index
, struct in6_addr
*local_address
) {
692 assert_se(index
== test_index
);
694 if (socketpair(AF_UNIX
, SOCK_STREAM
, 0, test_dhcp_fd
) < 0)
697 return test_dhcp_fd
[0];
700 static int test_client_solicit(sd_event
*e
) {
701 sd_dhcp6_client
*client
;
702 usec_t time_now
= now(clock_boottime_or_monotonic());
706 printf("* %s\n", __FUNCTION__
);
708 assert_se(sd_dhcp6_client_new(&client
) >= 0);
711 assert_se(sd_dhcp6_client_attach_event(client
, e
, 0) >= 0);
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
,
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);
724 assert_se(sd_dhcp6_client_set_callback(client
,
725 test_client_information_cb
, e
) >= 0);
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);
731 assert_se(sd_dhcp6_client_start(client
) >= 0);
735 hangcheck
= sd_event_source_unref(hangcheck
);
737 assert_se(!sd_dhcp6_client_unref(client
));
739 test_dhcp_fd
[1] = safe_close(test_dhcp_fd
[1]);
744 int main(int argc
, char *argv
[]) {
745 _cleanup_event_unref_ sd_event
*e
;
747 assert_se(sd_event_new(&e
) >= 0);
749 log_set_max_level(LOG_DEBUG
);
750 log_parse_environment();
753 test_client_basic(e
);
755 test_advertise_option(e
);
756 test_client_solicit(e
);