chiark / gitweb /
unit: move UnitDependency to unit-name
[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 = false;
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, &mac_addr) >= 0);
70
71         assert_se(sd_dhcp6_client_set_request_option(client, DHCP6_OPTION_CLIENTID) == -EINVAL);
72         assert_se(sd_dhcp6_client_set_request_option(client, DHCP6_OPTION_DNS_SERVERS) == -EEXIST);
73         assert_se(sd_dhcp6_client_set_request_option(client, DHCP6_OPTION_NTP_SERVER) == -EEXIST);
74         assert_se(sd_dhcp6_client_set_request_option(client, DHCP6_OPTION_SNTP_SERVERS) == 0);
75         assert_se(sd_dhcp6_client_set_request_option(client, DHCP6_OPTION_DOMAIN_LIST) == -EEXIST);
76         assert_se(sd_dhcp6_client_set_request_option(client, 10) == -EINVAL);
77
78         assert_se(sd_dhcp6_client_set_callback(client, NULL, NULL) >= 0);
79
80         assert_se(sd_dhcp6_client_detach_event(client) >= 0);
81         assert_se(!sd_dhcp6_client_unref(client));
82
83         return 0;
84 }
85
86 static int test_option(sd_event *e) {
87         uint8_t packet[] = {
88                 'F', 'O', 'O',
89                 0x00, DHCP6_OPTION_ORO, 0x00, 0x07,
90                 'A', 'B', 'C', 'D', 'E', 'F', 'G',
91                 0x00, DHCP6_OPTION_VENDOR_CLASS, 0x00, 0x09,
92                 '1', '2', '3', '4', '5', '6', '7', '8', '9',
93                 'B', 'A', 'R',
94         };
95         uint8_t result[] = {
96                 'F', 'O', 'O',
97                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
98                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
99                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100                 'B', 'A', 'R',
101         };
102         uint16_t optcode;
103         size_t optlen;
104         uint8_t *optval, *buf, *out;
105         size_t zero = 0, pos = 3;
106         size_t buflen = sizeof(packet), outlen = sizeof(result);
107
108         if (verbose)
109                 printf("* %s\n", __FUNCTION__);
110
111         assert_se(buflen == outlen);
112
113         assert_se(dhcp6_option_parse(&buf, &zero, &optcode, &optlen,
114                                      &optval) == -ENOMSG);
115
116         buflen -= 3;
117         buf = &packet[3];
118         outlen -= 3;
119         out = &result[3];
120
121         assert_se(dhcp6_option_parse(&buf, &buflen, &optcode, &optlen,
122                                      &optval) >= 0);
123         pos += 4 + optlen;
124         assert_se(buf == &packet[pos]);
125         assert_se(optcode == DHCP6_OPTION_ORO);
126         assert_se(optlen == 7);
127         assert_se(buflen + pos == sizeof(packet));
128
129         assert_se(dhcp6_option_append(&out, &outlen, optcode, optlen,
130                                       optval) >= 0);
131         assert_se(out == &result[pos]);
132         assert_se(*out == 0x00);
133
134         assert_se(dhcp6_option_parse(&buf, &buflen, &optcode, &optlen,
135                                      &optval) >= 0);
136         pos += 4 + optlen;
137         assert_se(buf == &packet[pos]);
138         assert_se(optcode == DHCP6_OPTION_VENDOR_CLASS);
139         assert_se(optlen == 9);
140         assert_se(buflen + pos == sizeof(packet));
141
142         assert_se(dhcp6_option_append(&out, &outlen, optcode, optlen,
143                                       optval) >= 0);
144         assert_se(out == &result[pos]);
145         assert_se(*out == 'B');
146
147         assert_se(memcmp(packet, result, sizeof(packet)) == 0);
148
149         return 0;
150 }
151
152 static uint8_t msg_advertise[198] = {
153         0x02, 0x0f, 0xb4, 0xe5, 0x00, 0x01, 0x00, 0x0e,
154         0x00, 0x01, 0x00, 0x01, 0x1a, 0x6b, 0xf3, 0x30,
155         0x3c, 0x97, 0x0e, 0xcf, 0xa3, 0x7d, 0x00, 0x03,
156         0x00, 0x5e, 0x0e, 0xcf, 0xa3, 0x7d, 0x00, 0x00,
157         0x00, 0x50, 0x00, 0x00, 0x00, 0x78, 0x00, 0x05,
158         0x00, 0x18, 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad,
159         0xbe, 0xef, 0x78, 0xee, 0x1c, 0xf3, 0x09, 0x3c,
160         0x55, 0xad, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00,
161         0x00, 0xb4, 0x00, 0x0d, 0x00, 0x32, 0x00, 0x00,
162         0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x28,
163         0x65, 0x73, 0x29, 0x20, 0x72, 0x65, 0x6e, 0x65,
164         0x77, 0x65, 0x64, 0x2e, 0x20, 0x47, 0x72, 0x65,
165         0x65, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x66,
166         0x72, 0x6f, 0x6d, 0x20, 0x70, 0x6c, 0x61, 0x6e,
167         0x65, 0x74, 0x20, 0x45, 0x61, 0x72, 0x74, 0x68,
168         0x00, 0x17, 0x00, 0x10, 0x20, 0x01, 0x0d, 0xb8,
169         0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00, 0x00,
170         0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x0b,
171         0x03, 0x6c, 0x61, 0x62, 0x05, 0x69, 0x6e, 0x74,
172         0x72, 0x61, 0x00, 0x00, 0x1f, 0x00, 0x10, 0x20,
173         0x01, 0x0d, 0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00,
174         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
175         0x02, 0x00, 0x0e, 0x00, 0x01, 0x00, 0x01, 0x19,
176         0x40, 0x5c, 0x53, 0x78, 0x2b, 0xcb, 0xb3, 0x6d,
177         0x53, 0x00, 0x07, 0x00, 0x01, 0x00
178 };
179
180 static uint8_t msg_reply[173] = {
181         0x07, 0xf7, 0x4e, 0x57, 0x00, 0x02, 0x00, 0x0e,
182         0x00, 0x01, 0x00, 0x01, 0x19, 0x40, 0x5c, 0x53,
183         0x78, 0x2b, 0xcb, 0xb3, 0x6d, 0x53, 0x00, 0x01,
184         0x00, 0x0e, 0x00, 0x01, 0x00, 0x01, 0x1a, 0x6b,
185         0xf3, 0x30, 0x3c, 0x97, 0x0e, 0xcf, 0xa3, 0x7d,
186         0x00, 0x03, 0x00, 0x4a, 0x0e, 0xcf, 0xa3, 0x7d,
187         0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x78,
188         0x00, 0x05, 0x00, 0x18, 0x20, 0x01, 0x0d, 0xb8,
189         0xde, 0xad, 0xbe, 0xef, 0x78, 0xee, 0x1c, 0xf3,
190         0x09, 0x3c, 0x55, 0xad, 0x00, 0x00, 0x00, 0x96,
191         0x00, 0x00, 0x00, 0xb4, 0x00, 0x0d, 0x00, 0x1e,
192         0x00, 0x00, 0x41, 0x6c, 0x6c, 0x20, 0x61, 0x64,
193         0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x20,
194         0x77, 0x65, 0x72, 0x65, 0x20, 0x61, 0x73, 0x73,
195         0x69, 0x67, 0x6e, 0x65, 0x64, 0x2e, 0x00, 0x17,
196         0x00, 0x10, 0x20, 0x01, 0x0d, 0xb8, 0xde, 0xad,
197         0xbe, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
198         0x00, 0x01, 0x00, 0x18, 0x00, 0x0b, 0x03, 0x6c,
199         0x61, 0x62, 0x05, 0x69, 0x6e, 0x74, 0x72, 0x61,
200         0x00, 0x00, 0x1f, 0x00, 0x10, 0x20, 0x01, 0x0d,
201         0xb8, 0xde, 0xad, 0xbe, 0xef, 0x00, 0x00, 0x00,
202         0x00, 0x00, 0x00, 0x00, 0x01
203 };
204
205 static int test_advertise_option(sd_event *e) {
206         _cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;
207         DHCP6Message *advertise = (DHCP6Message *)msg_advertise;
208         uint8_t *optval, *opt = msg_advertise + sizeof(DHCP6Message);
209         uint16_t optcode;
210         size_t optlen, len = sizeof(msg_advertise) - sizeof(DHCP6Message);
211         be32_t val;
212         uint8_t preference = 255;
213         struct in6_addr addr;
214         uint32_t lt_pref, lt_valid;
215         int r;
216         bool opt_clientid = false;
217
218         if (verbose)
219                 printf("* %s\n", __FUNCTION__);
220
221         assert_se(dhcp6_lease_new(&lease) >= 0);
222
223         assert_se(advertise->type == DHCP6_ADVERTISE);
224         assert_se((be32toh(advertise->transaction_id) & 0x00ffffff) ==
225                   0x0fb4e5);
226
227         while ((r = dhcp6_option_parse(&opt, &len, &optcode, &optlen,
228                                        &optval)) >= 0) {
229
230                 switch(optcode) {
231                 case DHCP6_OPTION_CLIENTID:
232                         assert_se(optlen == 14);
233
234                         opt_clientid = true;
235                         break;
236
237                 case DHCP6_OPTION_IA_NA:
238                         assert_se(optlen == 94);
239                         assert_se(!memcmp(optval, &msg_advertise[26], optlen));
240
241                         val = htobe32(0x0ecfa37d);
242                         assert_se(!memcmp(optval, &val, sizeof(val)));
243
244                         val = htobe32(80);
245                         assert_se(!memcmp(optval + 4, &val, sizeof(val)));
246
247                         val = htobe32(120);
248                         assert_se(!memcmp(optval + 8, &val, sizeof(val)));
249
250                         assert_se(dhcp6_option_parse_ia(&optval, &optlen,
251                                                         optcode,
252                                                         &lease->ia) >= 0);
253
254                         break;
255
256                 case DHCP6_OPTION_SERVERID:
257                         assert_se(optlen == 14);
258                         assert_se(!memcmp(optval, &msg_advertise[179], optlen));
259
260                         assert_se(dhcp6_lease_set_serverid(lease, optval,
261                                                            optlen) >= 0);
262                         break;
263
264                 case DHCP6_OPTION_PREFERENCE:
265                         assert_se(optlen == 1);
266                         assert_se(!*optval);
267
268                         assert_se(dhcp6_lease_set_preference(lease,
269                                                              *optval) >= 0);
270                         break;
271
272                 case DHCP6_OPTION_ELAPSED_TIME:
273                         assert_se(optlen == 2);
274
275                         break;
276
277                 default:
278                         break;
279                 }
280         }
281
282
283         assert_se(r == -ENOMSG);
284
285         assert_se(opt_clientid);
286
287         assert_se(sd_dhcp6_lease_get_first_address(lease, &addr, &lt_pref,
288                                                    &lt_valid) >= 0);
289         assert_se(!memcmp(&addr, &msg_advertise[42], sizeof(addr)));
290         assert_se(lt_pref == 150);
291         assert_se(lt_valid == 180);
292         assert_se(sd_dhcp6_lease_get_next_address(lease, &addr, &lt_pref,
293                                                   &lt_valid) == -ENOMSG);
294
295         assert_se(sd_dhcp6_lease_get_first_address(lease, &addr, &lt_pref,
296                                                    &lt_valid) >= 0);
297         assert_se(!memcmp(&addr, &msg_advertise[42], sizeof(addr)));
298         assert_se(sd_dhcp6_lease_get_next_address(lease, &addr, &lt_pref,
299                                                   &lt_valid) == -ENOMSG);
300         assert_se(sd_dhcp6_lease_get_next_address(lease, &addr, &lt_pref,
301                                                   &lt_valid) == -ENOMSG);
302         assert_se(sd_dhcp6_lease_get_first_address(lease, &addr, &lt_pref,
303                                                    &lt_valid) >= 0);
304         assert_se(!memcmp(&addr, &msg_advertise[42], sizeof(addr)));
305         assert_se(sd_dhcp6_lease_get_next_address(lease, &addr, &lt_pref,
306                                                   &lt_valid) == -ENOMSG);
307
308         assert_se(dhcp6_lease_get_serverid(lease, &opt, &len) >= 0);
309         assert_se(len == 14);
310         assert_se(!memcmp(opt, &msg_advertise[179], len));
311
312         assert_se(dhcp6_lease_get_preference(lease, &preference) >= 0);
313         assert_se(preference == 0);
314
315         return 0;
316 }
317
318 static int test_hangcheck(sd_event_source *s, uint64_t usec, void *userdata) {
319         assert_not_reached("Test case should have completed in 2 seconds");
320
321         return 0;
322 }
323
324 int detect_vm(const char **id) {
325         return 1;
326 }
327
328 int detect_container(const char **id) {
329         return 1;
330 }
331
332 int detect_virtualization(const char **id) {
333         return 1;
334 }
335
336 int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) {
337         assert_se(index == test_index);
338
339         if (socketpair(AF_UNIX, SOCK_STREAM, 0, test_dhcp_fd) < 0)
340                 return -errno;
341
342         return test_dhcp_fd[0];
343 }
344
345 static int test_client_send_reply(DHCP6Message *request) {
346         DHCP6Message reply;
347
348         reply.transaction_id = request->transaction_id;
349         reply.type = DHCP6_REPLY;
350
351         memcpy(msg_reply, &reply.transaction_id, 4);
352
353         memcpy(&msg_reply[26], test_duid, sizeof(test_duid));
354
355         memcpy(&msg_reply[44], &test_iaid, sizeof(test_iaid));
356
357         assert_se(write(test_dhcp_fd[1], msg_reply, sizeof(msg_reply))
358                   == sizeof(msg_reply));
359
360         return 0;
361 }
362
363 static int test_client_verify_request(DHCP6Message *request, uint8_t *option,
364                                       size_t len) {
365         _cleanup_dhcp6_lease_free_ sd_dhcp6_lease *lease = NULL;
366         uint8_t *optval;
367         uint16_t optcode;
368         size_t optlen;
369         bool found_clientid = false, found_iana = false, found_serverid = false,
370                 found_elapsed_time = false;
371         int r;
372         struct in6_addr addr;
373         be32_t val;
374         uint32_t lt_pref, lt_valid;
375
376         assert_se(request->type == DHCP6_REQUEST);
377
378         assert_se(dhcp6_lease_new(&lease) >= 0);
379
380         while ((r = dhcp6_option_parse(&option, &len,
381                                        &optcode, &optlen, &optval)) >= 0) {
382                 switch(optcode) {
383                 case DHCP6_OPTION_CLIENTID:
384                         assert_se(!found_clientid);
385                         found_clientid = true;
386
387                         assert_se(!memcmp(optval, &test_duid,
388                                           sizeof(test_duid)));
389
390                         break;
391
392                 case DHCP6_OPTION_IA_NA:
393                         assert_se(!found_iana);
394                         found_iana = true;
395
396
397                         assert_se(optlen == 40);
398                         assert_se(!memcmp(optval, &test_iaid, sizeof(test_iaid)));
399
400                         val = htobe32(80);
401                         assert_se(!memcmp(optval + 4, &val, sizeof(val)));
402
403                         val = htobe32(120);
404                         assert_se(!memcmp(optval + 8, &val, sizeof(val)));
405
406                         assert_se(!dhcp6_option_parse_ia(&optval, &optlen,
407                                                          optcode, &lease->ia));
408
409                         break;
410
411                 case DHCP6_OPTION_SERVERID:
412                         assert_se(!found_serverid);
413                         found_serverid = true;
414
415                         assert_se(optlen == 14);
416                         assert_se(!memcmp(&msg_advertise[179], optval, optlen));
417
418                         break;
419
420                 case DHCP6_OPTION_ELAPSED_TIME:
421                         assert_se(!found_elapsed_time);
422                         found_elapsed_time = true;
423
424                         assert_se(optlen == 2);
425
426                         break;
427                 }
428         }
429
430         assert_se(r == -ENOMSG);
431         assert_se(found_clientid && found_iana && found_serverid &&
432                   found_elapsed_time);
433
434         assert_se(sd_dhcp6_lease_get_first_address(lease, &addr, &lt_pref,
435                                                    &lt_valid) >= 0);
436         assert_se(!memcmp(&addr, &msg_advertise[42], sizeof(addr)));
437         assert_se(lt_pref == 150);
438         assert_se(lt_valid == 180);
439
440         assert_se(sd_dhcp6_lease_get_next_address(lease, &addr, &lt_pref,
441                                                   &lt_valid) == -ENOMSG);
442
443         return 0;
444 }
445
446 static int test_client_send_advertise(DHCP6Message *solicit)
447 {
448         DHCP6Message advertise;
449
450         advertise.transaction_id = solicit->transaction_id;
451         advertise.type = DHCP6_ADVERTISE;
452
453         memcpy(msg_advertise, &advertise.transaction_id, 4);
454
455         memcpy(&msg_advertise[8], test_duid, sizeof(test_duid));
456
457         memcpy(&msg_advertise[26], &test_iaid, sizeof(test_iaid));
458
459         assert_se(write(test_dhcp_fd[1], msg_advertise, sizeof(msg_advertise))
460                   == sizeof(msg_advertise));
461
462         return 0;
463 }
464
465 static int test_client_verify_solicit(DHCP6Message *solicit, uint8_t *option,
466                                       size_t len) {
467         uint8_t *optval;
468         uint16_t optcode;
469         size_t optlen;
470         bool found_clientid = false, found_iana = false,
471                 found_elapsed_time = false;
472         int r;
473
474         assert_se(solicit->type == DHCP6_SOLICIT);
475
476         while ((r = dhcp6_option_parse(&option, &len,
477                                        &optcode, &optlen, &optval)) >= 0) {
478                 switch(optcode) {
479                 case DHCP6_OPTION_CLIENTID:
480                         assert_se(!found_clientid);
481                         found_clientid = true;
482
483                         assert_se(optlen == sizeof(test_duid));
484                         memcpy(&test_duid, optval, sizeof(test_duid));
485
486                         break;
487
488                 case DHCP6_OPTION_IA_NA:
489                         assert_se(!found_iana);
490                         found_iana = true;
491
492                         assert_se(optlen == 12);
493
494                         memcpy(&test_iaid, optval, sizeof(test_iaid));
495
496                         break;
497
498                 case DHCP6_OPTION_ELAPSED_TIME:
499                         assert_se(!found_elapsed_time);
500                         found_elapsed_time = true;
501
502                         assert_se(optlen == 2);
503
504                         break;
505                 }
506         }
507
508         assert_se(r == -ENOMSG);
509         assert_se(found_clientid && found_iana && found_elapsed_time);
510
511         return 0;
512 }
513
514 int dhcp6_network_send_udp_socket(int s, struct in6_addr *server_address,
515                                   const void *packet, size_t len) {
516         struct in6_addr mcast =
517                 IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT;
518         DHCP6Message *message;
519         uint8_t *option;
520
521         assert_se(s == test_dhcp_fd[0]);
522         assert_se(server_address);
523         assert_se(packet);
524         assert_se(len > sizeof(DHCP6Message) + 4);
525
526         assert_se(IN6_ARE_ADDR_EQUAL(server_address, &mcast));
527
528         message = (DHCP6Message *)packet;
529         option = (uint8_t *)(message + 1);
530         len -= sizeof(DHCP6Message);
531
532         assert_se(message->transaction_id & 0x00ffffff);
533
534         if (test_client_message_num == 0) {
535                 test_client_verify_solicit(message, option, len);
536                 test_client_send_advertise(message);
537                 test_client_message_num++;
538         } else if (test_client_message_num == 1) {
539                 test_client_verify_request(message, option, len);
540                 test_client_send_reply(message);
541                 test_client_message_num++;
542         }
543
544         return len;
545 }
546
547 static void test_client_solicit_cb(sd_dhcp6_client *client, int event,
548                                    void *userdata) {
549         sd_event *e = userdata;
550
551         assert_se(e);
552         assert_se(event == DHCP6_EVENT_IP_ACQUIRE);
553
554         assert_se(sd_dhcp6_client_set_request_option(client, DHCP6_OPTION_DNS_SERVERS) == -EBUSY);
555
556         if (verbose)
557                 printf("  got DHCPv6 event %d\n", event);
558
559         sd_event_exit(e, 0);
560 }
561
562 static int test_client_solicit(sd_event *e) {
563         sd_dhcp6_client *client;
564         usec_t time_now = now(clock_boottime_or_monotonic());
565
566         if (verbose)
567                 printf("* %s\n", __FUNCTION__);
568
569         assert_se(sd_dhcp6_client_new(&client) >= 0);
570         assert_se(client);
571
572         assert_se(sd_dhcp6_client_attach_event(client, e, 0) >= 0);
573
574         assert_se(sd_dhcp6_client_set_index(client, test_index) == 0);
575         assert_se(sd_dhcp6_client_set_mac(client, &mac_addr) >= 0);
576
577         assert_se(sd_dhcp6_client_set_callback(client,
578                                                test_client_solicit_cb, e) >= 0);
579
580         assert_se(sd_event_add_time(e, &hangcheck, clock_boottime_or_monotonic(),
581                                     time_now + 2 * USEC_PER_SEC, 0,
582                                     test_hangcheck, NULL) >= 0);
583
584         assert_se(sd_dhcp6_client_start(client) >= 0);
585
586         sd_event_loop(e);
587
588         hangcheck = sd_event_source_unref(hangcheck);
589
590         assert_se(!sd_dhcp6_client_unref(client));
591
592         test_dhcp_fd[1] = safe_close(test_dhcp_fd[1]);
593
594         return 0;
595 }
596
597 int main(int argc, char *argv[]) {
598         _cleanup_event_unref_ sd_event *e;
599
600         assert_se(sd_event_new(&e) >= 0);
601
602         log_set_max_level(LOG_DEBUG);
603         log_parse_environment();
604         log_open();
605
606         test_client_basic(e);
607         test_option(e);
608         test_advertise_option(e);
609         test_client_solicit(e);
610
611         assert_se(!sd_event_unref(e));
612
613         return 0;
614 }