1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
3 Copyright © 2013 Intel Corporation. All rights reserved.
8 #include <net/if_arp.h>
10 #include <sys/socket.h>
13 #include "sd-dhcp-client.h"
16 #include "alloc-util.h"
17 #include "dhcp-identifier.h"
18 #include "dhcp-internal.h"
19 #include "dhcp-protocol.h"
20 #include "ether-addr-util.h"
22 #include "random-util.h"
26 static struct hw_addr_data hw_addr
= {
28 .ether
= {{ 'A', 'B', 'C', '1', '2', '3' }},
31 .ether
= {{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }},
33 typedef int (*test_callback_recv_t
)(size_t size
, DHCPMessage
*dhcp
);
35 static bool verbose
= true;
36 static int test_fd
[2];
37 static test_callback_recv_t callback_recv
;
40 static void test_request_basic(sd_event
*e
) {
43 sd_dhcp_client
*client
;
46 printf("* %s\n", __func__
);
48 /* Initialize client without Anonymize settings. */
49 r
= sd_dhcp_client_new(&client
, false);
54 r
= sd_dhcp_client_attach_event(client
, e
, 0);
57 assert_se(sd_dhcp_client_set_request_option(NULL
, 0) == -EINVAL
);
58 assert_se(sd_dhcp_client_set_request_address(NULL
, NULL
) == -EINVAL
);
59 assert_se(sd_dhcp_client_set_ifindex(NULL
, 0) == -EINVAL
);
61 assert_se(sd_dhcp_client_set_ifindex(client
, 15) == 0);
62 assert_se(sd_dhcp_client_set_ifindex(client
, -42) == -EINVAL
);
63 assert_se(sd_dhcp_client_set_ifindex(client
, -1) == -EINVAL
);
64 assert_se(sd_dhcp_client_set_ifindex(client
, 0) == -EINVAL
);
65 assert_se(sd_dhcp_client_set_ifindex(client
, 1) == 0);
67 assert_se(sd_dhcp_client_set_hostname(client
, "host") == 1);
68 assert_se(sd_dhcp_client_set_hostname(client
, "host.domain") == 1);
69 assert_se(sd_dhcp_client_set_hostname(client
, NULL
) == 1);
70 assert_se(sd_dhcp_client_set_hostname(client
, "~host") == -EINVAL
);
71 assert_se(sd_dhcp_client_set_hostname(client
, "~host.domain") == -EINVAL
);
73 assert_se(sd_dhcp_client_set_request_option(client
, SD_DHCP_OPTION_SUBNET_MASK
) == 0);
74 assert_se(sd_dhcp_client_set_request_option(client
, SD_DHCP_OPTION_ROUTER
) == 0);
75 /* This PRL option is not set when using Anonymize, but in this test
76 * Anonymize settings are not being used. */
77 assert_se(sd_dhcp_client_set_request_option(client
, SD_DHCP_OPTION_HOST_NAME
) == 0);
78 assert_se(sd_dhcp_client_set_request_option(client
, SD_DHCP_OPTION_DOMAIN_NAME
) == 0);
79 assert_se(sd_dhcp_client_set_request_option(client
, SD_DHCP_OPTION_DOMAIN_NAME_SERVER
) == 0);
81 assert_se(sd_dhcp_client_set_request_option(client
, SD_DHCP_OPTION_PAD
) == -EINVAL
);
82 assert_se(sd_dhcp_client_set_request_option(client
, SD_DHCP_OPTION_END
) == -EINVAL
);
83 assert_se(sd_dhcp_client_set_request_option(client
, SD_DHCP_OPTION_MESSAGE_TYPE
) == -EINVAL
);
84 assert_se(sd_dhcp_client_set_request_option(client
, SD_DHCP_OPTION_OVERLOAD
) == -EINVAL
);
85 assert_se(sd_dhcp_client_set_request_option(client
, SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
) == -EINVAL
);
87 /* RFC7844: option 33 (SD_DHCP_OPTION_STATIC_ROUTE) is set in the
88 * default PRL when using Anonymize, so it is changed to other option
89 * that is not set by default, to check that it was set successfully.
90 * Options not set by default (using or not anonymize) are option 17
91 * (SD_DHCP_OPTION_ROOT_PATH) and 42 (SD_DHCP_OPTION_NTP_SERVER) */
92 assert_se(sd_dhcp_client_set_request_option(client
, 17) == 1);
93 assert_se(sd_dhcp_client_set_request_option(client
, 17) == 0);
94 assert_se(sd_dhcp_client_set_request_option(client
, 42) == 1);
95 assert_se(sd_dhcp_client_set_request_option(client
, 17) == 0);
97 sd_dhcp_client_unref(client
);
100 static void test_request_anonymize(sd_event
*e
) {
103 sd_dhcp_client
*client
;
106 printf("* %s\n", __func__
);
108 /* Initialize client with Anonymize settings. */
109 r
= sd_dhcp_client_new(&client
, true);
114 r
= sd_dhcp_client_attach_event(client
, e
, 0);
117 assert_se(sd_dhcp_client_set_request_option(client
, SD_DHCP_OPTION_NETBIOS_NAME_SERVER
) == 0);
118 /* This PRL option is not set when using Anonymize */
119 assert_se(sd_dhcp_client_set_request_option(client
, SD_DHCP_OPTION_HOST_NAME
) == 1);
120 assert_se(sd_dhcp_client_set_request_option(client
, SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
) == -EINVAL
);
122 /* RFC7844: option 101 (SD_DHCP_OPTION_NEW_TZDB_TIMEZONE) is not set in the
123 * default PRL when using Anonymize, */
124 assert_se(sd_dhcp_client_set_request_option(client
, 101) == 1);
125 assert_se(sd_dhcp_client_set_request_option(client
, 101) == 0);
127 sd_dhcp_client_unref(client
);
130 static void test_checksum(void) {
132 0x45, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,
133 0x40, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
134 0xff, 0xff, 0xff, 0xff
138 printf("* %s\n", __func__
);
140 assert_se(dhcp_packet_checksum((uint8_t*)&buf
, 20) == be16toh(0x78ae));
143 static void test_dhcp_identifier_set_iaid(void) {
144 uint32_t iaid_legacy
;
147 assert_se(dhcp_identifier_set_iaid(NULL
, &hw_addr
, /* legacy = */ true, &iaid_legacy
) >= 0);
148 assert_se(dhcp_identifier_set_iaid(NULL
, &hw_addr
, /* legacy = */ false, &iaid
) >= 0);
150 /* we expect, that the MAC address was hashed. The legacy value is in native
152 assert_se(iaid_legacy
== 0x8dde4ba8u
);
153 assert_se(iaid
== htole32(0x8dde4ba8u
));
154 #if __BYTE_ORDER == __LITTLE_ENDIAN
155 assert_se(iaid
== iaid_legacy
);
157 assert_se(iaid
== bswap_32(iaid_legacy
));
161 static int check_options(uint8_t code
, uint8_t len
, const void *option
, void *userdata
) {
163 case SD_DHCP_OPTION_CLIENT_IDENTIFIER
:
169 assert_se(dhcp_identifier_set_duid_en(/* test_mode = */ true, &duid
, &duid_len
) >= 0);
170 assert_se(dhcp_identifier_set_iaid(NULL
, &hw_addr
, /* legacy = */ true, &iaid
) >= 0);
172 assert_se(len
== sizeof(uint8_t) + sizeof(uint32_t) + duid_len
);
173 assert_se(len
== 19);
174 assert_se(((uint8_t*) option
)[0] == 0xff);
176 assert_se(memcmp((uint8_t*) option
+ 1, &iaid
, sizeof(iaid
)) == 0);
177 assert_se(memcmp((uint8_t*) option
+ 5, &duid
, duid_len
) == 0);
188 int dhcp_network_send_raw_socket(int s
, const union sockaddr_union
*link
, const void *packet
, size_t len
) {
190 _cleanup_free_ DHCPPacket
*discover
;
191 uint16_t ip_check
, udp_check
;
196 size
= sizeof(DHCPPacket
);
197 assert_se(len
> size
);
199 discover
= memdup(packet
, len
);
201 assert_se(discover
->ip
.ttl
== IPDEFTTL
);
202 assert_se(discover
->ip
.protocol
== IPPROTO_UDP
);
203 assert_se(discover
->ip
.saddr
== INADDR_ANY
);
204 assert_se(discover
->ip
.daddr
== INADDR_BROADCAST
);
205 assert_se(discover
->udp
.source
== be16toh(DHCP_PORT_CLIENT
));
206 assert_se(discover
->udp
.dest
== be16toh(DHCP_PORT_SERVER
));
208 ip_check
= discover
->ip
.check
;
210 discover
->ip
.ttl
= 0;
211 discover
->ip
.check
= discover
->udp
.len
;
213 udp_check
= ~dhcp_packet_checksum((uint8_t*)&discover
->ip
.ttl
, len
- 8);
214 assert_se(udp_check
== 0xffff);
216 discover
->ip
.ttl
= IPDEFTTL
;
217 discover
->ip
.check
= ip_check
;
219 ip_check
= ~dhcp_packet_checksum((uint8_t*)&discover
->ip
, sizeof(discover
->ip
));
220 assert_se(ip_check
== 0xffff);
222 assert_se(discover
->dhcp
.xid
);
223 assert_se(memcmp(discover
->dhcp
.chaddr
, hw_addr
.bytes
, hw_addr
.length
) == 0);
225 size
= len
- sizeof(struct iphdr
) - sizeof(struct udphdr
);
227 assert_se(callback_recv
);
228 callback_recv(size
, &discover
->dhcp
);
233 int dhcp_network_bind_raw_socket(
235 union sockaddr_union
*link
,
237 const struct hw_addr_data
*_hw_addr
,
238 const struct hw_addr_data
*_bcast_addr
,
239 uint16_t arp_type
, uint16_t port
) {
241 if (socketpair(AF_UNIX
, SOCK_STREAM
| SOCK_CLOEXEC
| SOCK_NONBLOCK
, 0, test_fd
) < 0)
247 int dhcp_network_bind_udp_socket(int ifindex
, be32_t address
, uint16_t port
, int ip_service_type
) {
250 fd
= socket(AF_INET
, SOCK_DGRAM
| SOCK_CLOEXEC
| SOCK_NONBLOCK
, 0);
257 int dhcp_network_send_udp_socket(int s
, be32_t address
, uint16_t port
, const void *packet
, size_t len
) {
261 static int test_discover_message_verify(size_t size
, struct DHCPMessage
*dhcp
) {
264 res
= dhcp_option_parse(dhcp
, size
, check_options
, NULL
, NULL
);
265 assert_se(res
== DHCP_DISCOVER
);
268 printf(" recv DHCP Discover 0x%08x\n", be32toh(dhcp
->xid
));
273 static void test_discover_message(sd_event
*e
) {
274 sd_dhcp_client
*client
;
278 printf("* %s\n", __func__
);
280 r
= sd_dhcp_client_new(&client
, false);
284 r
= sd_dhcp_client_attach_event(client
, e
, 0);
287 assert_se(sd_dhcp_client_set_ifindex(client
, 42) >= 0);
288 assert_se(sd_dhcp_client_set_mac(client
, hw_addr
.bytes
, bcast_addr
.bytes
, hw_addr
.length
, ARPHRD_ETHER
) >= 0);
289 dhcp_client_set_test_mode(client
, true);
291 assert_se(sd_dhcp_client_set_request_option(client
, 248) >= 0);
293 callback_recv
= test_discover_message_verify
;
295 res
= sd_dhcp_client_start(client
);
297 assert_se(IN_SET(res
, 0, -EINPROGRESS
));
299 sd_event_run(e
, UINT64_MAX
);
301 sd_dhcp_client_stop(client
);
302 sd_dhcp_client_unref(client
);
304 test_fd
[1] = safe_close(test_fd
[1]);
306 callback_recv
= NULL
;
309 static uint8_t test_addr_acq_offer
[] = {
310 0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00,
311 0x80, 0x11, 0xb3, 0x84, 0xc0, 0xa8, 0x02, 0x01,
312 0xc0, 0xa8, 0x02, 0xbf, 0x00, 0x43, 0x00, 0x44,
313 0x01, 0x34, 0x00, 0x00, 0x02, 0x01, 0x06, 0x00,
314 0x6f, 0x95, 0x2f, 0x30, 0x00, 0x00, 0x00, 0x00,
315 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x02, 0xbf,
316 0xc0, 0xa8, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00,
317 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
318 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
319 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
320 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
321 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
322 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
323 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
324 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
325 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
326 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
327 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
328 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
329 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
330 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
331 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
332 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
333 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
334 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
335 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
336 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
337 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
338 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
339 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
340 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
341 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
342 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
343 0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x02, 0x36,
344 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x33, 0x04, 0x00,
345 0x00, 0x02, 0x58, 0x01, 0x04, 0xff, 0xff, 0xff,
346 0x00, 0x2a, 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x0f,
347 0x09, 0x6c, 0x61, 0x62, 0x2e, 0x69, 0x6e, 0x74,
348 0x72, 0x61, 0x03, 0x04, 0xc0, 0xa8, 0x02, 0x01,
349 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
350 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
353 static uint8_t test_addr_acq_ack
[] = {
354 0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00,
355 0x80, 0x11, 0xb3, 0x84, 0xc0, 0xa8, 0x02, 0x01,
356 0xc0, 0xa8, 0x02, 0xbf, 0x00, 0x43, 0x00, 0x44,
357 0x01, 0x34, 0x00, 0x00, 0x02, 0x01, 0x06, 0x00,
358 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
359 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x02, 0xbf,
360 0xc0, 0xa8, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00,
361 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
362 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
363 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
364 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
365 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
366 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
367 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
368 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
369 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
370 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
371 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
372 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
373 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
374 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
375 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
376 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
377 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
378 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
379 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
380 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
381 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
382 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
383 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
384 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
385 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
386 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
387 0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x05, 0x36,
388 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x33, 0x04, 0x00,
389 0x00, 0x02, 0x58, 0x01, 0x04, 0xff, 0xff, 0xff,
390 0x00, 0x2a, 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x0f,
391 0x09, 0x6c, 0x61, 0x62, 0x2e, 0x69, 0x6e, 0x74,
392 0x72, 0x61, 0x03, 0x04, 0xc0, 0xa8, 0x02, 0x01,
393 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
394 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
397 static int test_addr_acq_acquired(sd_dhcp_client
*client
, int event
,
399 sd_event
*e
= userdata
;
400 sd_dhcp_lease
*lease
;
402 const struct in_addr
*addrs
;
405 assert_se(IN_SET(event
, SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
, SD_DHCP_CLIENT_EVENT_SELECTING
));
407 assert_se(sd_dhcp_client_get_lease(client
, &lease
) >= 0);
410 assert_se(sd_dhcp_lease_get_address(lease
, &addr
) >= 0);
411 assert_se(memcmp(&addr
.s_addr
, &test_addr_acq_ack
[44],
412 sizeof(addr
.s_addr
)) == 0);
414 assert_se(sd_dhcp_lease_get_netmask(lease
, &addr
) >= 0);
415 assert_se(memcmp(&addr
.s_addr
, &test_addr_acq_ack
[285],
416 sizeof(addr
.s_addr
)) == 0);
418 assert_se(sd_dhcp_lease_get_router(lease
, &addrs
) == 1);
419 assert_se(memcmp(&addrs
[0].s_addr
, &test_addr_acq_ack
[308],
420 sizeof(addrs
[0].s_addr
)) == 0);
423 printf(" DHCP address acquired\n");
430 static int test_addr_acq_recv_request(size_t size
, DHCPMessage
*request
) {
431 uint16_t udp_check
= 0;
432 uint8_t *msg_bytes
= (uint8_t *)request
;
435 res
= dhcp_option_parse(request
, size
, check_options
, NULL
, NULL
);
436 assert_se(res
== DHCP_REQUEST
);
437 assert_se(xid
== request
->xid
);
439 assert_se(msg_bytes
[size
- 1] == SD_DHCP_OPTION_END
);
442 printf(" recv DHCP Request 0x%08x\n", be32toh(xid
));
444 memcpy(&test_addr_acq_ack
[26], &udp_check
, sizeof(udp_check
));
445 memcpy(&test_addr_acq_ack
[32], &xid
, sizeof(xid
));
446 memcpy(&test_addr_acq_ack
[56], hw_addr
.bytes
, hw_addr
.length
);
448 callback_recv
= NULL
;
450 res
= write(test_fd
[1], test_addr_acq_ack
,
451 sizeof(test_addr_acq_ack
));
452 assert_se(res
== sizeof(test_addr_acq_ack
));
455 printf(" send DHCP Ack\n");
460 static int test_addr_acq_recv_discover(size_t size
, DHCPMessage
*discover
) {
461 uint16_t udp_check
= 0;
462 uint8_t *msg_bytes
= (uint8_t *)discover
;
465 res
= dhcp_option_parse(discover
, size
, check_options
, NULL
, NULL
);
466 assert_se(res
== DHCP_DISCOVER
);
468 assert_se(msg_bytes
[size
- 1] == SD_DHCP_OPTION_END
);
473 printf(" recv DHCP Discover 0x%08x\n", be32toh(xid
));
475 memcpy(&test_addr_acq_offer
[26], &udp_check
, sizeof(udp_check
));
476 memcpy(&test_addr_acq_offer
[32], &xid
, sizeof(xid
));
477 memcpy(&test_addr_acq_offer
[56], hw_addr
.bytes
, hw_addr
.length
);
479 callback_recv
= test_addr_acq_recv_request
;
481 res
= write(test_fd
[1], test_addr_acq_offer
,
482 sizeof(test_addr_acq_offer
));
483 assert_se(res
== sizeof(test_addr_acq_offer
));
486 printf(" sent DHCP Offer\n");
491 static void test_addr_acq(sd_event
*e
) {
492 sd_dhcp_client
*client
;
496 printf("* %s\n", __func__
);
498 r
= sd_dhcp_client_new(&client
, false);
502 r
= sd_dhcp_client_attach_event(client
, e
, 0);
505 assert_se(sd_dhcp_client_set_ifindex(client
, 42) >= 0);
506 assert_se(sd_dhcp_client_set_mac(client
, hw_addr
.bytes
, bcast_addr
.bytes
, hw_addr
.length
, ARPHRD_ETHER
) >= 0);
507 dhcp_client_set_test_mode(client
, true);
509 assert_se(sd_dhcp_client_set_callback(client
, test_addr_acq_acquired
, e
) >= 0);
511 callback_recv
= test_addr_acq_recv_discover
;
513 assert_se(sd_event_add_time_relative(e
, NULL
, CLOCK_BOOTTIME
,
515 NULL
, INT_TO_PTR(-ETIMEDOUT
)) >= 0);
517 res
= sd_dhcp_client_start(client
);
518 assert_se(IN_SET(res
, 0, -EINPROGRESS
));
520 assert_se(sd_event_loop(e
) >= 0);
522 assert_se(sd_dhcp_client_set_callback(client
, NULL
, NULL
) >= 0);
523 assert_se(sd_dhcp_client_stop(client
) >= 0);
524 sd_dhcp_client_unref(client
);
526 test_fd
[1] = safe_close(test_fd
[1]);
528 callback_recv
= NULL
;
532 int main(int argc
, char *argv
[]) {
533 _cleanup_(sd_event_unrefp
) sd_event
*e
;
535 test_setup_logging(LOG_DEBUG
);
537 assert_se(sd_event_new(&e
) >= 0);
539 test_request_basic(e
);
540 test_request_anonymize(e
);
542 test_dhcp_identifier_set_iaid();
544 test_discover_message(e
);
548 /* Make sure the async_close thread has finished.
549 * valgrind would report some of the phread_* structures
550 * as not cleaned up properly. */