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"
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_(sd_dhcp6_lease_unrefp
) 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_(sd_dhcp6_lease_unrefp
) 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
;
564 struct in6_addr address
= { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 } } };
568 assert_se(event
== SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST
);
570 assert_se(sd_dhcp6_client_get_lease(client
, &lease
) >= 0);
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
);
576 assert_se(sd_dhcp6_lease_get_dns(lease
, &addrs
) == 1);
577 assert_se(!memcmp(addrs
, &msg_advertise
[124], 16));
579 assert_se(sd_dhcp6_lease_get_ntp_addrs(lease
, &addrs
) == 1);
580 assert_se(!memcmp(addrs
, &msg_advertise
[159], 16));
583 printf(" got DHCPv6 event %d\n", event
);
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);
590 assert_se(sd_dhcp6_client_set_callback(client
,
591 test_client_solicit_cb
, e
) >= 0);
593 assert_se(sd_dhcp6_client_set_local_address(client
, &address
) >= 0);
595 assert_se(sd_dhcp6_client_start(client
) >= 0);
598 static int test_client_verify_information_request(DHCP6Message
*information_request
,
599 uint8_t *option
, size_t len
) {
601 _cleanup_(sd_dhcp6_lease_unrefp
) sd_dhcp6_lease
*lease
= NULL
;
605 bool found_clientid
= false, found_elapsed_time
= false;
607 struct in6_addr addr
;
608 uint32_t lt_pref
, lt_valid
;
610 assert_se(information_request
->type
== DHCP6_INFORMATION_REQUEST
);
612 assert_se(dhcp6_lease_new(&lease
) >= 0);
614 while ((r
= dhcp6_option_parse(&option
, &len
,
615 &optcode
, &optlen
, &optval
)) >= 0) {
617 case DHCP6_OPTION_CLIENTID
:
618 assert_se(!found_clientid
);
619 found_clientid
= true;
621 assert_se(optlen
== sizeof(test_duid
));
622 memcpy(&test_duid
, optval
, sizeof(test_duid
));
626 case DHCP6_OPTION_IA_NA
:
627 assert_not_reached("IA TA option must not be present");
631 case DHCP6_OPTION_SERVERID
:
632 assert_not_reached("Server ID option must not be present");
636 case DHCP6_OPTION_ELAPSED_TIME
:
637 assert_se(!found_elapsed_time
);
638 found_elapsed_time
= true;
640 assert_se(optlen
== 2);
646 assert_se(r
== -ENOMSG
);
647 assert_se(found_clientid
&& found_elapsed_time
);
649 sd_dhcp6_lease_reset_address_iter(lease
);
651 assert_se(sd_dhcp6_lease_get_address(lease
, &addr
, <_pref
,
652 <_valid
) == -ENOMSG
);
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
;
664 assert_se(s
== test_dhcp_fd
[0]);
665 assert_se(server_address
);
667 assert_se(len
> sizeof(DHCP6Message
) + 4);
669 assert_se(IN6_ARE_ADDR_EQUAL(server_address
, &mcast
));
671 message
= (DHCP6Message
*)packet
;
672 option
= (uint8_t *)(message
+ 1);
673 len
-= sizeof(DHCP6Message
);
675 assert_se(message
->transaction_id
& 0x00ffffff);
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
++;
694 int dhcp6_network_bind_udp_socket(int index
, struct in6_addr
*local_address
) {
695 assert_se(index
== test_index
);
697 if (socketpair(AF_UNIX
, SOCK_STREAM
, 0, test_dhcp_fd
) < 0)
700 return test_dhcp_fd
[0];
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 } } };
710 printf("* %s\n", __FUNCTION__
);
712 assert_se(sd_dhcp6_client_new(&client
) >= 0);
715 assert_se(sd_dhcp6_client_attach_event(client
, e
, 0) >= 0);
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
,
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);
728 assert_se(sd_dhcp6_client_set_callback(client
,
729 test_client_information_cb
, e
) >= 0);
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);
735 assert_se(sd_dhcp6_client_set_local_address(client
, &address
) >= 0);
737 assert_se(sd_dhcp6_client_start(client
) >= 0);
741 hangcheck
= sd_event_source_unref(hangcheck
);
743 assert_se(!sd_dhcp6_client_unref(client
));
745 test_dhcp_fd
[1] = safe_close(test_dhcp_fd
[1]);
750 int main(int argc
, char *argv
[]) {
751 _cleanup_(sd_event_unrefp
) sd_event
*e
;
753 assert_se(sd_event_new(&e
) >= 0);
755 log_set_max_level(LOG_DEBUG
);
756 log_parse_environment();
759 test_client_basic(e
);
761 test_advertise_option(e
);
762 test_client_solicit(e
);