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