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"
21 #include "random-util.h"
25 static uint8_t mac_addr
[] = {'A', 'B', 'C', '1', '2', '3'};
26 static uint8_t bcast_addr
[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
28 typedef int (*test_callback_recv_t
)(size_t size
, DHCPMessage
*dhcp
);
30 static bool verbose
= true;
31 static int test_fd
[2];
32 static test_callback_recv_t callback_recv
;
35 static void test_request_basic(sd_event
*e
) {
38 sd_dhcp_client
*client
;
41 printf("* %s\n", __func__
);
43 /* Initialize client without Anonymize settings. */
44 r
= sd_dhcp_client_new(&client
, false);
49 r
= sd_dhcp_client_attach_event(client
, e
, 0);
52 assert_se(sd_dhcp_client_set_request_option(NULL
, 0) == -EINVAL
);
53 assert_se(sd_dhcp_client_set_request_address(NULL
, NULL
) == -EINVAL
);
54 assert_se(sd_dhcp_client_set_ifindex(NULL
, 0) == -EINVAL
);
56 assert_se(sd_dhcp_client_set_ifindex(client
, 15) == 0);
57 assert_se(sd_dhcp_client_set_ifindex(client
, -42) == -EINVAL
);
58 assert_se(sd_dhcp_client_set_ifindex(client
, -1) == -EINVAL
);
59 assert_se(sd_dhcp_client_set_ifindex(client
, 0) == -EINVAL
);
60 assert_se(sd_dhcp_client_set_ifindex(client
, 1) == 0);
62 assert_se(sd_dhcp_client_set_hostname(client
, "host") == 1);
63 assert_se(sd_dhcp_client_set_hostname(client
, "host.domain") == 1);
64 assert_se(sd_dhcp_client_set_hostname(client
, NULL
) == 1);
65 assert_se(sd_dhcp_client_set_hostname(client
, "~host") == -EINVAL
);
66 assert_se(sd_dhcp_client_set_hostname(client
, "~host.domain") == -EINVAL
);
68 assert_se(sd_dhcp_client_set_request_option(client
, SD_DHCP_OPTION_SUBNET_MASK
) == 0);
69 assert_se(sd_dhcp_client_set_request_option(client
, SD_DHCP_OPTION_ROUTER
) == 0);
70 /* This PRL option is not set when using Anonymize, but in this test
71 * Anonymize settings are not being used. */
72 assert_se(sd_dhcp_client_set_request_option(client
, SD_DHCP_OPTION_HOST_NAME
) == 0);
73 assert_se(sd_dhcp_client_set_request_option(client
, SD_DHCP_OPTION_DOMAIN_NAME
) == 0);
74 assert_se(sd_dhcp_client_set_request_option(client
, SD_DHCP_OPTION_DOMAIN_NAME_SERVER
) == 0);
76 assert_se(sd_dhcp_client_set_request_option(client
, SD_DHCP_OPTION_PAD
) == -EINVAL
);
77 assert_se(sd_dhcp_client_set_request_option(client
, SD_DHCP_OPTION_END
) == -EINVAL
);
78 assert_se(sd_dhcp_client_set_request_option(client
, SD_DHCP_OPTION_MESSAGE_TYPE
) == -EINVAL
);
79 assert_se(sd_dhcp_client_set_request_option(client
, SD_DHCP_OPTION_OVERLOAD
) == -EINVAL
);
80 assert_se(sd_dhcp_client_set_request_option(client
, SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
) == -EINVAL
);
82 /* RFC7844: option 33 (SD_DHCP_OPTION_STATIC_ROUTE) is set in the
83 * default PRL when using Anonymize, so it is changed to other option
84 * that is not set by default, to check that it was set successfully.
85 * Options not set by default (using or not anonymize) are option 17
86 * (SD_DHCP_OPTION_ROOT_PATH) and 42 (SD_DHCP_OPTION_NTP_SERVER) */
87 assert_se(sd_dhcp_client_set_request_option(client
, 17) == 1);
88 assert_se(sd_dhcp_client_set_request_option(client
, 17) == 0);
89 assert_se(sd_dhcp_client_set_request_option(client
, 42) == 1);
90 assert_se(sd_dhcp_client_set_request_option(client
, 17) == 0);
92 sd_dhcp_client_unref(client
);
95 static void test_request_anonymize(sd_event
*e
) {
98 sd_dhcp_client
*client
;
101 printf("* %s\n", __func__
);
103 /* Initialize client with Anonymize settings. */
104 r
= sd_dhcp_client_new(&client
, true);
109 r
= sd_dhcp_client_attach_event(client
, e
, 0);
112 assert_se(sd_dhcp_client_set_request_option(client
, SD_DHCP_OPTION_NETBIOS_NAMESERVER
) == 0);
113 /* This PRL option is not set when using Anonymize */
114 assert_se(sd_dhcp_client_set_request_option(client
, SD_DHCP_OPTION_HOST_NAME
) == 1);
115 assert_se(sd_dhcp_client_set_request_option(client
, SD_DHCP_OPTION_PARAMETER_REQUEST_LIST
) == -EINVAL
);
117 /* RFC7844: option 101 (SD_DHCP_OPTION_NEW_TZDB_TIMEZONE) is not set in the
118 * default PRL when using Anonymize, */
119 assert_se(sd_dhcp_client_set_request_option(client
, 101) == 1);
120 assert_se(sd_dhcp_client_set_request_option(client
, 101) == 0);
122 sd_dhcp_client_unref(client
);
125 static void test_checksum(void) {
127 0x45, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,
128 0x40, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
129 0xff, 0xff, 0xff, 0xff
133 printf("* %s\n", __func__
);
135 assert_se(dhcp_packet_checksum((uint8_t*)&buf
, 20) == be16toh(0x78ae));
138 static void test_dhcp_identifier_set_iaid(void) {
139 uint32_t iaid_legacy
;
142 assert_se(dhcp_identifier_set_iaid(42, mac_addr
, sizeof(mac_addr
), /* legacy = */ true,
143 /* use_mac = */ true, &iaid_legacy
) >= 0);
144 assert_se(dhcp_identifier_set_iaid(42, mac_addr
, sizeof(mac_addr
), /* legacy = */ false,
145 /* use_mac = */ true, &iaid
) >= 0);
147 /* we expect, that the MAC address was hashed. The legacy value is in native
149 assert_se(iaid_legacy
== 0x8dde4ba8u
);
150 assert_se(iaid
== htole32(0x8dde4ba8u
));
151 #if __BYTE_ORDER == __LITTLE_ENDIAN
152 assert_se(iaid
== iaid_legacy
);
154 assert_se(iaid
== bswap_32(iaid_legacy
));
158 static int check_options(uint8_t code
, uint8_t len
, const void *option
, void *userdata
) {
160 case SD_DHCP_OPTION_CLIENT_IDENTIFIER
:
166 assert_se(dhcp_identifier_set_duid_en(/* test_mode = */ true, &duid
, &duid_len
) >= 0);
167 assert_se(dhcp_identifier_set_iaid(42, mac_addr
, ETH_ALEN
, true, /* use_mac = */ true, &iaid
) >= 0);
169 assert_se(len
== sizeof(uint8_t) + sizeof(uint32_t) + duid_len
);
170 assert_se(len
== 19);
171 assert_se(((uint8_t*) option
)[0] == 0xff);
173 assert_se(memcmp((uint8_t*) option
+ 1, &iaid
, sizeof(iaid
)) == 0);
174 assert_se(memcmp((uint8_t*) option
+ 5, &duid
, duid_len
) == 0);
185 int dhcp_network_send_raw_socket(int s
, const union sockaddr_union
*link
, const void *packet
, size_t len
) {
187 _cleanup_free_ DHCPPacket
*discover
;
188 uint16_t ip_check
, udp_check
;
193 size
= sizeof(DHCPPacket
);
194 assert_se(len
> size
);
196 discover
= memdup(packet
, len
);
198 assert_se(discover
->ip
.ttl
== IPDEFTTL
);
199 assert_se(discover
->ip
.protocol
== IPPROTO_UDP
);
200 assert_se(discover
->ip
.saddr
== INADDR_ANY
);
201 assert_se(discover
->ip
.daddr
== INADDR_BROADCAST
);
202 assert_se(discover
->udp
.source
== be16toh(DHCP_PORT_CLIENT
));
203 assert_se(discover
->udp
.dest
== be16toh(DHCP_PORT_SERVER
));
205 ip_check
= discover
->ip
.check
;
207 discover
->ip
.ttl
= 0;
208 discover
->ip
.check
= discover
->udp
.len
;
210 udp_check
= ~dhcp_packet_checksum((uint8_t*)&discover
->ip
.ttl
, len
- 8);
211 assert_se(udp_check
== 0xffff);
213 discover
->ip
.ttl
= IPDEFTTL
;
214 discover
->ip
.check
= ip_check
;
216 ip_check
= ~dhcp_packet_checksum((uint8_t*)&discover
->ip
, sizeof(discover
->ip
));
217 assert_se(ip_check
== 0xffff);
219 assert_se(discover
->dhcp
.xid
);
220 assert_se(memcmp(discover
->dhcp
.chaddr
, &mac_addr
, ETH_ALEN
) == 0);
222 size
= len
- sizeof(struct iphdr
) - sizeof(struct udphdr
);
224 assert_se(callback_recv
);
225 callback_recv(size
, &discover
->dhcp
);
230 int dhcp_network_bind_raw_socket(
232 union sockaddr_union
*link
,
234 const uint8_t *addr
, size_t addr_len
,
235 const uint8_t *bcaddr
, size_t bcaddr_len
,
236 uint16_t arp_type
, uint16_t port
) {
238 if (socketpair(AF_UNIX
, SOCK_STREAM
| SOCK_CLOEXEC
| SOCK_NONBLOCK
, 0, test_fd
) < 0)
244 int dhcp_network_bind_udp_socket(int ifindex
, be32_t address
, uint16_t port
, int ip_service_type
) {
247 fd
= socket(AF_INET
, SOCK_DGRAM
| SOCK_CLOEXEC
| SOCK_NONBLOCK
, 0);
254 int dhcp_network_send_udp_socket(int s
, be32_t address
, uint16_t port
, const void *packet
, size_t len
) {
258 static int test_discover_message_verify(size_t size
, struct DHCPMessage
*dhcp
) {
261 res
= dhcp_option_parse(dhcp
, size
, check_options
, NULL
, NULL
);
262 assert_se(res
== DHCP_DISCOVER
);
265 printf(" recv DHCP Discover 0x%08x\n", be32toh(dhcp
->xid
));
270 static void test_discover_message(sd_event
*e
) {
271 sd_dhcp_client
*client
;
275 printf("* %s\n", __func__
);
277 r
= sd_dhcp_client_new(&client
, false);
281 r
= sd_dhcp_client_attach_event(client
, e
, 0);
284 assert_se(sd_dhcp_client_set_ifindex(client
, 42) >= 0);
285 assert_se(sd_dhcp_client_set_mac(client
, mac_addr
, bcast_addr
, ETH_ALEN
, ARPHRD_ETHER
) >= 0);
286 dhcp_client_set_test_mode(client
, true);
288 assert_se(sd_dhcp_client_set_request_option(client
, 248) >= 0);
290 callback_recv
= test_discover_message_verify
;
292 res
= sd_dhcp_client_start(client
);
294 assert_se(IN_SET(res
, 0, -EINPROGRESS
));
296 sd_event_run(e
, UINT64_MAX
);
298 sd_dhcp_client_stop(client
);
299 sd_dhcp_client_unref(client
);
301 test_fd
[1] = safe_close(test_fd
[1]);
303 callback_recv
= NULL
;
306 static uint8_t test_addr_acq_offer
[] = {
307 0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00,
308 0x80, 0x11, 0xb3, 0x84, 0xc0, 0xa8, 0x02, 0x01,
309 0xc0, 0xa8, 0x02, 0xbf, 0x00, 0x43, 0x00, 0x44,
310 0x01, 0x34, 0x00, 0x00, 0x02, 0x01, 0x06, 0x00,
311 0x6f, 0x95, 0x2f, 0x30, 0x00, 0x00, 0x00, 0x00,
312 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x02, 0xbf,
313 0xc0, 0xa8, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00,
314 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
315 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
316 0x00, 0x00, 0x00, 0x00, 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 0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x02, 0x36,
341 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x33, 0x04, 0x00,
342 0x00, 0x02, 0x58, 0x01, 0x04, 0xff, 0xff, 0xff,
343 0x00, 0x2a, 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x0f,
344 0x09, 0x6c, 0x61, 0x62, 0x2e, 0x69, 0x6e, 0x74,
345 0x72, 0x61, 0x03, 0x04, 0xc0, 0xa8, 0x02, 0x01,
346 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
347 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
350 static uint8_t test_addr_acq_ack
[] = {
351 0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00,
352 0x80, 0x11, 0xb3, 0x84, 0xc0, 0xa8, 0x02, 0x01,
353 0xc0, 0xa8, 0x02, 0xbf, 0x00, 0x43, 0x00, 0x44,
354 0x01, 0x34, 0x00, 0x00, 0x02, 0x01, 0x06, 0x00,
355 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
356 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x02, 0xbf,
357 0xc0, 0xa8, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00,
358 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
359 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
360 0x00, 0x00, 0x00, 0x00, 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 0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x05, 0x36,
385 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x33, 0x04, 0x00,
386 0x00, 0x02, 0x58, 0x01, 0x04, 0xff, 0xff, 0xff,
387 0x00, 0x2a, 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x0f,
388 0x09, 0x6c, 0x61, 0x62, 0x2e, 0x69, 0x6e, 0x74,
389 0x72, 0x61, 0x03, 0x04, 0xc0, 0xa8, 0x02, 0x01,
390 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
391 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
394 static int test_addr_acq_acquired(sd_dhcp_client
*client
, int event
,
396 sd_event
*e
= userdata
;
397 sd_dhcp_lease
*lease
;
399 const struct in_addr
*addrs
;
402 assert_se(IN_SET(event
, SD_DHCP_CLIENT_EVENT_IP_ACQUIRE
, SD_DHCP_CLIENT_EVENT_SELECTING
));
404 assert_se(sd_dhcp_client_get_lease(client
, &lease
) >= 0);
407 assert_se(sd_dhcp_lease_get_address(lease
, &addr
) >= 0);
408 assert_se(memcmp(&addr
.s_addr
, &test_addr_acq_ack
[44],
409 sizeof(addr
.s_addr
)) == 0);
411 assert_se(sd_dhcp_lease_get_netmask(lease
, &addr
) >= 0);
412 assert_se(memcmp(&addr
.s_addr
, &test_addr_acq_ack
[285],
413 sizeof(addr
.s_addr
)) == 0);
415 assert_se(sd_dhcp_lease_get_router(lease
, &addrs
) == 1);
416 assert_se(memcmp(&addrs
[0].s_addr
, &test_addr_acq_ack
[308],
417 sizeof(addrs
[0].s_addr
)) == 0);
420 printf(" DHCP address acquired\n");
427 static int test_addr_acq_recv_request(size_t size
, DHCPMessage
*request
) {
428 uint16_t udp_check
= 0;
429 uint8_t *msg_bytes
= (uint8_t *)request
;
432 res
= dhcp_option_parse(request
, size
, check_options
, NULL
, NULL
);
433 assert_se(res
== DHCP_REQUEST
);
434 assert_se(xid
== request
->xid
);
436 assert_se(msg_bytes
[size
- 1] == SD_DHCP_OPTION_END
);
439 printf(" recv DHCP Request 0x%08x\n", be32toh(xid
));
441 memcpy(&test_addr_acq_ack
[26], &udp_check
, sizeof(udp_check
));
442 memcpy(&test_addr_acq_ack
[32], &xid
, sizeof(xid
));
443 memcpy(&test_addr_acq_ack
[56], &mac_addr
, ETHER_ADDR_LEN
);
445 callback_recv
= NULL
;
447 res
= write(test_fd
[1], test_addr_acq_ack
,
448 sizeof(test_addr_acq_ack
));
449 assert_se(res
== sizeof(test_addr_acq_ack
));
452 printf(" send DHCP Ack\n");
457 static int test_addr_acq_recv_discover(size_t size
, DHCPMessage
*discover
) {
458 uint16_t udp_check
= 0;
459 uint8_t *msg_bytes
= (uint8_t *)discover
;
462 res
= dhcp_option_parse(discover
, size
, check_options
, NULL
, NULL
);
463 assert_se(res
== DHCP_DISCOVER
);
465 assert_se(msg_bytes
[size
- 1] == SD_DHCP_OPTION_END
);
470 printf(" recv DHCP Discover 0x%08x\n", be32toh(xid
));
472 memcpy(&test_addr_acq_offer
[26], &udp_check
, sizeof(udp_check
));
473 memcpy(&test_addr_acq_offer
[32], &xid
, sizeof(xid
));
474 memcpy(&test_addr_acq_offer
[56], &mac_addr
, ETHER_ADDR_LEN
);
476 callback_recv
= test_addr_acq_recv_request
;
478 res
= write(test_fd
[1], test_addr_acq_offer
,
479 sizeof(test_addr_acq_offer
));
480 assert_se(res
== sizeof(test_addr_acq_offer
));
483 printf(" sent DHCP Offer\n");
488 static void test_addr_acq(sd_event
*e
) {
489 sd_dhcp_client
*client
;
493 printf("* %s\n", __func__
);
495 r
= sd_dhcp_client_new(&client
, false);
499 r
= sd_dhcp_client_attach_event(client
, e
, 0);
502 assert_se(sd_dhcp_client_set_ifindex(client
, 42) >= 0);
503 assert_se(sd_dhcp_client_set_mac(client
, mac_addr
, bcast_addr
, ETH_ALEN
, ARPHRD_ETHER
) >= 0);
504 dhcp_client_set_test_mode(client
, true);
506 assert_se(sd_dhcp_client_set_callback(client
, test_addr_acq_acquired
, e
) >= 0);
508 callback_recv
= test_addr_acq_recv_discover
;
510 assert_se(sd_event_add_time_relative(e
, NULL
, clock_boottime_or_monotonic(),
512 NULL
, INT_TO_PTR(-ETIMEDOUT
)) >= 0);
514 res
= sd_dhcp_client_start(client
);
515 assert_se(IN_SET(res
, 0, -EINPROGRESS
));
517 assert_se(sd_event_loop(e
) >= 0);
519 assert_se(sd_dhcp_client_set_callback(client
, NULL
, NULL
) >= 0);
520 assert_se(sd_dhcp_client_stop(client
) >= 0);
521 sd_dhcp_client_unref(client
);
523 test_fd
[1] = safe_close(test_fd
[1]);
525 callback_recv
= NULL
;
529 int main(int argc
, char *argv
[]) {
530 _cleanup_(sd_event_unrefp
) sd_event
*e
;
532 test_setup_logging(LOG_DEBUG
);
534 assert_se(sd_event_new(&e
) >= 0);
536 test_request_basic(e
);
537 test_request_anonymize(e
);
539 test_dhcp_identifier_set_iaid();
541 test_discover_message(e
);
545 /* Make sure the async_close thread has finished.
546 * valgrind would report some of the phread_* structures
547 * as not cleaned up properly. */