chiark / gitweb /
bootchart: Ensure that systemd is the init called after using bootchart
[elogind.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 <stdbool.h>
23 #include <stdio.h>
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <unistd.h>
27 #include <net/ethernet.h>
28
29 #include "socket-util.h"
30 #include "macro.h"
31 #include "sd-event.h"
32 #include "event-util.h"
33 #include "virt.h"
34
35 #include "sd-dhcp6-client.h"
36 #include "dhcp6-protocol.h"
37 #include "dhcp6-internal.h"
38 #include "dhcp6-lease-internal.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) == 0);
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
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 DHCP6_OPTION_CLIENTID:
234                         assert_se(optlen == 14);
235
236                         opt_clientid = true;
237                         break;
238
239                 case 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 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 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 DHCP6_OPTION_ELAPSED_TIME:
275                         assert_se(optlen == 2);
276
277                         break;
278
279                 default:
280                         break;
281                 }
282         }
283
284
285         assert_se(r == -ENOMSG);
286
287         assert_se(opt_clientid);
288
289         sd_dhcp6_lease_reset_address_iter(lease);
290         assert_se(sd_dhcp6_lease_get_address(lease, &addr, &lt_pref,
291                                              &lt_valid) >= 0);
292         assert_se(!memcmp(&addr, &msg_advertise[42], sizeof(addr)));
293         assert_se(lt_pref == 150);
294         assert_se(lt_valid == 180);
295         assert_se(sd_dhcp6_lease_get_address(lease, &addr, &lt_pref,
296                                              &lt_valid) == -ENOMSG);
297
298         sd_dhcp6_lease_reset_address_iter(lease);
299         assert_se(sd_dhcp6_lease_get_address(lease, &addr, &lt_pref,
300                                              &lt_valid) >= 0);
301         assert_se(!memcmp(&addr, &msg_advertise[42], sizeof(addr)));
302         assert_se(sd_dhcp6_lease_get_address(lease, &addr, &lt_pref,
303                                              &lt_valid) == -ENOMSG);
304         sd_dhcp6_lease_reset_address_iter(lease);
305         assert_se(sd_dhcp6_lease_get_address(lease, &addr, &lt_pref,
306                                              &lt_valid) >= 0);
307         assert_se(!memcmp(&addr, &msg_advertise[42], sizeof(addr)));
308         assert_se(sd_dhcp6_lease_get_address(lease, &addr, &lt_pref,
309                                              &lt_valid) == -ENOMSG);
310
311         assert_se(dhcp6_lease_get_serverid(lease, &opt, &len) >= 0);
312         assert_se(len == 14);
313         assert_se(!memcmp(opt, &msg_advertise[179], len));
314
315         assert_se(dhcp6_lease_get_preference(lease, &preference) >= 0);
316         assert_se(preference == 0);
317
318         return 0;
319 }
320
321 static int test_hangcheck(sd_event_source *s, uint64_t usec, void *userdata) {
322         assert_not_reached("Test case should have completed in 2 seconds");
323
324         return 0;
325 }
326
327 int detect_vm(const char **id) {
328         return 1;
329 }
330
331 int detect_container(const char **id) {
332         return 1;
333 }
334
335 int detect_virtualization(const char **id) {
336         return 1;
337 }
338
339 static void test_client_solicit_cb(sd_dhcp6_client *client, int event,
340                                    void *userdata) {
341         sd_event *e = userdata;
342
343         assert_se(e);
344         assert_se(event == DHCP6_EVENT_IP_ACQUIRE);
345
346         assert_se(sd_dhcp6_client_set_request_option(client, DHCP6_OPTION_DNS_SERVERS) == -EBUSY);
347
348         if (verbose)
349                 printf("  got DHCPv6 event %d\n", event);
350
351         sd_event_exit(e, 0);
352 }
353
354 static int test_client_send_reply(DHCP6Message *request) {
355         DHCP6Message reply;
356
357         reply.transaction_id = request->transaction_id;
358         reply.type = DHCP6_REPLY;
359
360         memcpy(msg_reply, &reply.transaction_id, 4);
361
362         memcpy(&msg_reply[26], test_duid, sizeof(test_duid));
363
364         memcpy(&msg_reply[44], &test_iaid, sizeof(test_iaid));
365
366         assert_se(write(test_dhcp_fd[1], msg_reply, sizeof(msg_reply))
367                   == sizeof(msg_reply));
368
369         return 0;
370 }
371
372 static int test_client_verify_request(DHCP6Message *request, uint8_t *option,
373                                       size_t len) {
374         _cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;
375         uint8_t *optval;
376         uint16_t optcode;
377         size_t optlen;
378         bool found_clientid = false, found_iana = false, found_serverid = false,
379                 found_elapsed_time = false;
380         int r;
381         struct in6_addr addr;
382         be32_t val;
383         uint32_t lt_pref, lt_valid;
384
385         assert_se(request->type == DHCP6_REQUEST);
386
387         assert_se(dhcp6_lease_new(&lease) >= 0);
388
389         while ((r = dhcp6_option_parse(&option, &len,
390                                        &optcode, &optlen, &optval)) >= 0) {
391                 switch(optcode) {
392                 case DHCP6_OPTION_CLIENTID:
393                         assert_se(!found_clientid);
394                         found_clientid = true;
395
396                         assert_se(!memcmp(optval, &test_duid,
397                                           sizeof(test_duid)));
398
399                         break;
400
401                 case DHCP6_OPTION_IA_NA:
402                         assert_se(!found_iana);
403                         found_iana = true;
404
405
406                         assert_se(optlen == 40);
407                         assert_se(!memcmp(optval, &test_iaid, sizeof(test_iaid)));
408
409                         val = htobe32(80);
410                         assert_se(!memcmp(optval + 4, &val, sizeof(val)));
411
412                         val = htobe32(120);
413                         assert_se(!memcmp(optval + 8, &val, sizeof(val)));
414
415                         assert_se(!dhcp6_option_parse_ia(&optval, &optlen,
416                                                          optcode, &lease->ia));
417
418                         break;
419
420                 case DHCP6_OPTION_SERVERID:
421                         assert_se(!found_serverid);
422                         found_serverid = true;
423
424                         assert_se(optlen == 14);
425                         assert_se(!memcmp(&msg_advertise[179], optval, optlen));
426
427                         break;
428
429                 case DHCP6_OPTION_ELAPSED_TIME:
430                         assert_se(!found_elapsed_time);
431                         found_elapsed_time = true;
432
433                         assert_se(optlen == 2);
434
435                         break;
436                 }
437         }
438
439         assert_se(r == -ENOMSG);
440         assert_se(found_clientid && found_iana && found_serverid &&
441                   found_elapsed_time);
442
443         sd_dhcp6_lease_reset_address_iter(lease);
444         assert_se(sd_dhcp6_lease_get_address(lease, &addr, &lt_pref,
445                                              &lt_valid) >= 0);
446         assert_se(!memcmp(&addr, &msg_advertise[42], sizeof(addr)));
447         assert_se(lt_pref == 150);
448         assert_se(lt_valid == 180);
449
450         assert_se(sd_dhcp6_lease_get_address(lease, &addr, &lt_pref,
451                                              &lt_valid) == -ENOMSG);
452
453         return 0;
454 }
455
456 static int test_client_send_advertise(DHCP6Message *solicit)
457 {
458         DHCP6Message advertise;
459
460         advertise.transaction_id = solicit->transaction_id;
461         advertise.type = DHCP6_ADVERTISE;
462
463         memcpy(msg_advertise, &advertise.transaction_id, 4);
464
465         memcpy(&msg_advertise[8], test_duid, sizeof(test_duid));
466
467         memcpy(&msg_advertise[26], &test_iaid, sizeof(test_iaid));
468
469         assert_se(write(test_dhcp_fd[1], msg_advertise, sizeof(msg_advertise))
470                   == sizeof(msg_advertise));
471
472         return 0;
473 }
474
475 static int test_client_verify_solicit(DHCP6Message *solicit, uint8_t *option,
476                                       size_t len) {
477         uint8_t *optval;
478         uint16_t optcode;
479         size_t optlen;
480         bool found_clientid = false, found_iana = false,
481                 found_elapsed_time = false;
482         int r;
483
484         assert_se(solicit->type == DHCP6_SOLICIT);
485
486         while ((r = dhcp6_option_parse(&option, &len,
487                                        &optcode, &optlen, &optval)) >= 0) {
488                 switch(optcode) {
489                 case DHCP6_OPTION_CLIENTID:
490                         assert_se(!found_clientid);
491                         found_clientid = true;
492
493                         assert_se(optlen == sizeof(test_duid));
494                         memcpy(&test_duid, optval, sizeof(test_duid));
495
496                         break;
497
498                 case DHCP6_OPTION_IA_NA:
499                         assert_se(!found_iana);
500                         found_iana = true;
501
502                         assert_se(optlen == 12);
503
504                         memcpy(&test_iaid, optval, sizeof(test_iaid));
505
506                         break;
507
508                 case DHCP6_OPTION_ELAPSED_TIME:
509                         assert_se(!found_elapsed_time);
510                         found_elapsed_time = true;
511
512                         assert_se(optlen == 2);
513
514                         break;
515                 }
516         }
517
518         assert_se(r == -ENOMSG);
519         assert_se(found_clientid && found_iana && found_elapsed_time);
520
521         return 0;
522 }
523
524 static void test_client_information_cb(sd_dhcp6_client *client, int event,
525                                        void *userdata) {
526         sd_event *e = userdata;
527
528         assert_se(e);
529         assert_se(event == DHCP6_EVENT_INFORMATION_REQUEST);
530
531         if (verbose)
532                 printf("  got DHCPv6 event %d\n", event);
533
534         assert_se(sd_dhcp6_client_set_information_request(client, false) >= 0);
535         assert_se(sd_dhcp6_client_set_callback(client,
536                                                test_client_solicit_cb, e) >= 0);
537
538         assert_se(sd_dhcp6_client_start(client) >= 0);
539 }
540
541 static int test_client_verify_information_request(DHCP6Message *information_request,
542                                                   uint8_t *option, size_t len) {
543
544         _cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;
545         uint8_t *optval;
546         uint16_t optcode;
547         size_t optlen;
548         bool found_clientid = false, found_elapsed_time = false;
549         int r;
550         struct in6_addr addr;
551         uint32_t lt_pref, lt_valid;
552
553         assert_se(information_request->type == DHCP6_INFORMATION_REQUEST);
554
555         assert_se(dhcp6_lease_new(&lease) >= 0);
556
557         while ((r = dhcp6_option_parse(&option, &len,
558                                        &optcode, &optlen, &optval)) >= 0) {
559                 switch(optcode) {
560                 case DHCP6_OPTION_CLIENTID:
561                         assert_se(!found_clientid);
562                         found_clientid = true;
563
564                         assert_se(optlen == sizeof(test_duid));
565                         memcpy(&test_duid, optval, sizeof(test_duid));
566
567                         break;
568
569                 case DHCP6_OPTION_IA_NA:
570                         assert_not_reached("IA TA option must not be present");
571
572                         break;
573
574                 case DHCP6_OPTION_SERVERID:
575                         assert_not_reached("Server ID option must not be present");
576
577                         break;
578
579                 case DHCP6_OPTION_ELAPSED_TIME:
580                         assert_se(!found_elapsed_time);
581                         found_elapsed_time = true;
582
583                         assert_se(optlen == 2);
584
585                         break;
586                 }
587         }
588
589         assert_se(r == -ENOMSG);
590         assert_se(found_clientid && found_elapsed_time);
591
592         sd_dhcp6_lease_reset_address_iter(lease);
593
594         assert_se(sd_dhcp6_lease_get_address(lease, &addr, &lt_pref,
595                                              &lt_valid) == -ENOMSG);
596
597         return 0;
598 }
599
600 int dhcp6_network_send_udp_socket(int s, struct in6_addr *server_address,
601                                   const void *packet, size_t len) {
602         struct in6_addr mcast =
603                 IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT;
604         DHCP6Message *message;
605         uint8_t *option;
606
607         assert_se(s == test_dhcp_fd[0]);
608         assert_se(server_address);
609         assert_se(packet);
610         assert_se(len > sizeof(DHCP6Message) + 4);
611
612         assert_se(IN6_ARE_ADDR_EQUAL(server_address, &mcast));
613
614         message = (DHCP6Message *)packet;
615         option = (uint8_t *)(message + 1);
616         len -= sizeof(DHCP6Message);
617
618         assert_se(message->transaction_id & 0x00ffffff);
619
620         if (test_client_message_num == 0) {
621                 test_client_verify_information_request(message, option, len);
622                 test_client_send_reply(message);
623                 test_client_message_num++;
624         } else if (test_client_message_num == 1) {
625                 test_client_verify_solicit(message, option, len);
626                 test_client_send_advertise(message);
627                 test_client_message_num++;
628         } else if (test_client_message_num == 2) {
629                 test_client_verify_request(message, option, len);
630                 test_client_send_reply(message);
631                 test_client_message_num++;
632         }
633
634         return len;
635 }
636
637 int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) {
638         assert_se(index == test_index);
639
640         if (socketpair(AF_UNIX, SOCK_STREAM, 0, test_dhcp_fd) < 0)
641                 return -errno;
642
643         return test_dhcp_fd[0];
644 }
645
646 static int test_client_solicit(sd_event *e) {
647         sd_dhcp6_client *client;
648         usec_t time_now = now(clock_boottime_or_monotonic());
649         bool val = true;
650
651         if (verbose)
652                 printf("* %s\n", __FUNCTION__);
653
654         assert_se(sd_dhcp6_client_new(&client) >= 0);
655         assert_se(client);
656
657         assert_se(sd_dhcp6_client_attach_event(client, e, 0) >= 0);
658
659         assert_se(sd_dhcp6_client_set_index(client, test_index) == 0);
660         assert_se(sd_dhcp6_client_set_mac(client, (const uint8_t *) &mac_addr,
661                                           sizeof (mac_addr),
662                                           ARPHRD_ETHER) >= 0);
663
664         assert_se(sd_dhcp6_client_get_information_request(client, &val) >= 0);
665         assert_se(val == false);
666         assert_se(sd_dhcp6_client_set_information_request(client, true) >= 0);
667         assert_se(sd_dhcp6_client_get_information_request(client, &val) >= 0);
668         assert_se(val == true);
669
670         assert_se(sd_dhcp6_client_set_callback(client,
671                                                test_client_information_cb, e) >= 0);
672
673         assert_se(sd_event_add_time(e, &hangcheck, clock_boottime_or_monotonic(),
674                                     time_now + 2 * USEC_PER_SEC, 0,
675                                     test_hangcheck, NULL) >= 0);
676
677         assert_se(sd_dhcp6_client_start(client) >= 0);
678
679         sd_event_loop(e);
680
681         hangcheck = sd_event_source_unref(hangcheck);
682
683         assert_se(!sd_dhcp6_client_unref(client));
684
685         test_dhcp_fd[1] = safe_close(test_dhcp_fd[1]);
686
687         return 0;
688 }
689
690 int main(int argc, char *argv[]) {
691         _cleanup_event_unref_ sd_event *e;
692
693         assert_se(sd_event_new(&e) >= 0);
694
695         log_set_max_level(LOG_DEBUG);
696         log_parse_environment();
697         log_open();
698
699         test_client_basic(e);
700         test_option(e);
701         test_advertise_option(e);
702         test_client_solicit(e);
703
704         assert_se(!sd_event_unref(e));
705
706         return 0;
707 }