]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-network/test-dhcp-client.c
tree-wide: drop license boilerplate
[thirdparty/systemd.git] / src / libsystemd-network / test-dhcp-client.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright (C) 2013 Intel Corporation. All rights reserved.
6 ***/
7
8 #include <errno.h>
9 #include <stdio.h>
10 #include <sys/socket.h>
11 #include <unistd.h>
12
13 #include "sd-dhcp-client.h"
14 #include "sd-event.h"
15
16 #include "alloc-util.h"
17 #include "dhcp-identifier.h"
18 #include "dhcp-internal.h"
19 #include "dhcp-protocol.h"
20 #include "fd-util.h"
21 #include "util.h"
22
23 static uint8_t mac_addr[] = {'A', 'B', 'C', '1', '2', '3'};
24
25 typedef int (*test_callback_recv_t)(size_t size, DHCPMessage *dhcp);
26
27 static bool verbose = true;
28 static int test_fd[2];
29 static test_callback_recv_t callback_recv;
30 static be32_t xid;
31 static sd_event_source *test_hangcheck;
32
33 static int test_dhcp_hangcheck(sd_event_source *s, uint64_t usec, void *userdata) {
34 assert_not_reached("Test case should have completed in 2 seconds");
35
36 return 0;
37 }
38
39 static void test_request_basic(sd_event *e) {
40 int r;
41
42 sd_dhcp_client *client;
43
44 if (verbose)
45 printf("* %s\n", __FUNCTION__);
46
47 /* Initialize client without Anonymize settings. */
48 r = sd_dhcp_client_new(&client, false);
49
50 assert_se(r >= 0);
51 assert_se(client);
52
53 r = sd_dhcp_client_attach_event(client, e, 0);
54 assert_se(r >= 0);
55
56 assert_se(sd_dhcp_client_set_request_option(NULL, 0) == -EINVAL);
57 assert_se(sd_dhcp_client_set_request_address(NULL, NULL) == -EINVAL);
58 assert_se(sd_dhcp_client_set_ifindex(NULL, 0) == -EINVAL);
59
60 assert_se(sd_dhcp_client_set_ifindex(client, 15) == 0);
61 assert_se(sd_dhcp_client_set_ifindex(client, -42) == -EINVAL);
62 assert_se(sd_dhcp_client_set_ifindex(client, -1) == -EINVAL);
63 assert_se(sd_dhcp_client_set_ifindex(client, 0) == -EINVAL);
64 assert_se(sd_dhcp_client_set_ifindex(client, 1) == 0);
65
66 assert_se(sd_dhcp_client_set_hostname(client, "host") == 1);
67 assert_se(sd_dhcp_client_set_hostname(client, "host.domain") == 1);
68 assert_se(sd_dhcp_client_set_hostname(client, NULL) == 1);
69 assert_se(sd_dhcp_client_set_hostname(client, "~host") == -EINVAL);
70 assert_se(sd_dhcp_client_set_hostname(client, "~host.domain") == -EINVAL);
71
72 assert_se(sd_dhcp_client_set_request_option(client,
73 SD_DHCP_OPTION_SUBNET_MASK) == -EEXIST);
74 assert_se(sd_dhcp_client_set_request_option(client,
75 SD_DHCP_OPTION_ROUTER) == -EEXIST);
76 /* This PRL option is not set when using Anonymize, but in this test
77 * Anonymize settings are not being used. */
78 assert_se(sd_dhcp_client_set_request_option(client,
79 SD_DHCP_OPTION_HOST_NAME) == -EEXIST);
80 assert_se(sd_dhcp_client_set_request_option(client,
81 SD_DHCP_OPTION_DOMAIN_NAME) == -EEXIST);
82 assert_se(sd_dhcp_client_set_request_option(client,
83 SD_DHCP_OPTION_DOMAIN_NAME_SERVER) == -EEXIST);
84
85 assert_se(sd_dhcp_client_set_request_option(client,
86 SD_DHCP_OPTION_PAD) == -EINVAL);
87 assert_se(sd_dhcp_client_set_request_option(client,
88 SD_DHCP_OPTION_END) == -EINVAL);
89 assert_se(sd_dhcp_client_set_request_option(client,
90 SD_DHCP_OPTION_MESSAGE_TYPE) == -EINVAL);
91 assert_se(sd_dhcp_client_set_request_option(client,
92 SD_DHCP_OPTION_OVERLOAD) == -EINVAL);
93 assert_se(sd_dhcp_client_set_request_option(client,
94 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST)
95 == -EINVAL);
96
97 /* RFC7844: option 33 (SD_DHCP_OPTION_STATIC_ROUTE) is set in the
98 * default PRL when using Anonymize, so it is changed to other option
99 * that is not set by default, to check that it was set successfully.
100 * Options not set by default (using or not anonymize) are option 17
101 * (SD_DHCP_OPTION_ROOT_PATH) and 42 (SD_DHCP_OPTION_NTP_SERVER) */
102 assert_se(sd_dhcp_client_set_request_option(client, 17) == 0);
103 assert_se(sd_dhcp_client_set_request_option(client, 17) == -EEXIST);
104 assert_se(sd_dhcp_client_set_request_option(client, 42) == 0);
105 assert_se(sd_dhcp_client_set_request_option(client, 17) == -EEXIST);
106
107 sd_dhcp_client_unref(client);
108 }
109
110 static void test_request_anonymize(sd_event *e) {
111 int r;
112
113 sd_dhcp_client *client;
114
115 if (verbose)
116 printf("* %s\n", __FUNCTION__);
117
118 /* Initialize client with Anonymize settings. */
119 r = sd_dhcp_client_new(&client, true);
120
121 assert_se(r >= 0);
122 assert_se(client);
123
124 r = sd_dhcp_client_attach_event(client, e, 0);
125 assert_se(r >= 0);
126
127 assert_se(sd_dhcp_client_set_request_option(client,
128 SD_DHCP_OPTION_NETBIOS_NAMESERVER) == -EEXIST);
129 /* This PRL option is not set when using Anonymize */
130 assert_se(sd_dhcp_client_set_request_option(client,
131 SD_DHCP_OPTION_HOST_NAME) == 0);
132 assert_se(sd_dhcp_client_set_request_option(client,
133 SD_DHCP_OPTION_PARAMETER_REQUEST_LIST)
134 == -EINVAL);
135
136 /* RFC7844: option 101 (SD_DHCP_OPTION_NEW_TZDB_TIMEZONE) is not set in the
137 * default PRL when using Anonymize, */
138 assert_se(sd_dhcp_client_set_request_option(client, 101) == 0);
139 assert_se(sd_dhcp_client_set_request_option(client, 101) == -EEXIST);
140
141 sd_dhcp_client_unref(client);
142 }
143
144 static void test_checksum(void) {
145 uint8_t buf[20] = {
146 0x45, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,
147 0x40, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
148 0xff, 0xff, 0xff, 0xff
149 };
150
151 if (verbose)
152 printf("* %s\n", __FUNCTION__);
153
154 assert_se(dhcp_packet_checksum((uint8_t*)&buf, 20) == be16toh(0x78ae));
155 }
156
157 static int check_options(uint8_t code, uint8_t len, const void *option, void *userdata) {
158 switch(code) {
159 case SD_DHCP_OPTION_CLIENT_IDENTIFIER:
160 {
161 uint32_t iaid;
162 struct duid duid;
163 size_t duid_len;
164
165 assert_se(dhcp_identifier_set_duid_en(&duid, &duid_len) >= 0);
166 assert_se(dhcp_identifier_set_iaid(42, mac_addr, ETH_ALEN, &iaid) >= 0);
167
168 assert_se(len == sizeof(uint8_t) + sizeof(uint32_t) + duid_len);
169 assert_se(len == 19);
170 assert_se(((uint8_t*) option)[0] == 0xff);
171
172 assert_se(memcmp((uint8_t*) option + 1, &iaid, sizeof(iaid)) == 0);
173 assert_se(memcmp((uint8_t*) option + 5, &duid, duid_len) == 0);
174 break;
175 }
176
177 default:
178 break;
179 }
180
181 return 0;
182 }
183
184 int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link, const void *packet, size_t len) {
185 size_t size;
186 _cleanup_free_ DHCPPacket *discover;
187 uint16_t ip_check, udp_check;
188
189 assert_se(s >= 0);
190 assert_se(packet);
191
192 size = sizeof(DHCPPacket);
193 assert_se(len > size);
194
195 discover = memdup(packet, len);
196
197 assert_se(discover->ip.ttl == IPDEFTTL);
198 assert_se(discover->ip.protocol == IPPROTO_UDP);
199 assert_se(discover->ip.saddr == INADDR_ANY);
200 assert_se(discover->ip.daddr == INADDR_BROADCAST);
201 assert_se(discover->udp.source == be16toh(DHCP_PORT_CLIENT));
202 assert_se(discover->udp.dest == be16toh(DHCP_PORT_SERVER));
203
204 ip_check = discover->ip.check;
205
206 discover->ip.ttl = 0;
207 discover->ip.check = discover->udp.len;
208
209 udp_check = ~dhcp_packet_checksum((uint8_t*)&discover->ip.ttl, len - 8);
210 assert_se(udp_check == 0xffff);
211
212 discover->ip.ttl = IPDEFTTL;
213 discover->ip.check = ip_check;
214
215 ip_check = ~dhcp_packet_checksum((uint8_t*)&discover->ip, sizeof(discover->ip));
216 assert_se(ip_check == 0xffff);
217
218 assert_se(discover->dhcp.xid);
219 assert_se(memcmp(discover->dhcp.chaddr, &mac_addr, ETH_ALEN) == 0);
220
221 size = len - sizeof(struct iphdr) - sizeof(struct udphdr);
222
223 assert_se(callback_recv);
224 callback_recv(size, &discover->dhcp);
225
226 return 575;
227 }
228
229 int dhcp_network_bind_raw_socket(
230 int index,
231 union sockaddr_union *link,
232 uint32_t id,
233 const uint8_t *addr, size_t addr_len,
234 uint16_t arp_type, uint16_t port) {
235
236 if (socketpair(AF_UNIX, SOCK_STREAM, 0, test_fd) < 0)
237 return -errno;
238
239 return test_fd[0];
240 }
241
242 int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port) {
243 int fd;
244
245 fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, 0);
246 if (fd < 0)
247 return -errno;
248
249 return fd;
250 }
251
252 int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port, const void *packet, size_t len) {
253 return 0;
254 }
255
256 static int test_discover_message_verify(size_t size, struct DHCPMessage *dhcp) {
257 int res;
258
259 res = dhcp_option_parse(dhcp, size, check_options, NULL, NULL);
260 assert_se(res == DHCP_DISCOVER);
261
262 if (verbose)
263 printf(" recv DHCP Discover 0x%08x\n", be32toh(dhcp->xid));
264
265 return 0;
266 }
267
268 static void test_discover_message(sd_event *e) {
269 sd_dhcp_client *client;
270 int res, r;
271
272 if (verbose)
273 printf("* %s\n", __FUNCTION__);
274
275 r = sd_dhcp_client_new(&client, false);
276 assert_se(r >= 0);
277 assert_se(client);
278
279 r = sd_dhcp_client_attach_event(client, e, 0);
280 assert_se(r >= 0);
281
282 assert_se(sd_dhcp_client_set_ifindex(client, 42) >= 0);
283 assert_se(sd_dhcp_client_set_mac(client, mac_addr, ETH_ALEN, ARPHRD_ETHER) >= 0);
284
285 assert_se(sd_dhcp_client_set_request_option(client, 248) >= 0);
286
287 callback_recv = test_discover_message_verify;
288
289 res = sd_dhcp_client_start(client);
290
291 assert_se(IN_SET(res, 0, -EINPROGRESS));
292
293 sd_event_run(e, (uint64_t) -1);
294
295 sd_dhcp_client_stop(client);
296 sd_dhcp_client_unref(client);
297
298 test_fd[1] = safe_close(test_fd[1]);
299
300 callback_recv = NULL;
301 }
302
303 static uint8_t test_addr_acq_offer[] = {
304 0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00,
305 0x80, 0x11, 0xb3, 0x84, 0xc0, 0xa8, 0x02, 0x01,
306 0xc0, 0xa8, 0x02, 0xbf, 0x00, 0x43, 0x00, 0x44,
307 0x01, 0x34, 0x00, 0x00, 0x02, 0x01, 0x06, 0x00,
308 0x6f, 0x95, 0x2f, 0x30, 0x00, 0x00, 0x00, 0x00,
309 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x02, 0xbf,
310 0xc0, 0xa8, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00,
311 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
312 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
313 0x00, 0x00, 0x00, 0x00, 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 0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x02, 0x36,
338 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x33, 0x04, 0x00,
339 0x00, 0x02, 0x58, 0x01, 0x04, 0xff, 0xff, 0xff,
340 0x00, 0x2a, 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x0f,
341 0x09, 0x6c, 0x61, 0x62, 0x2e, 0x69, 0x6e, 0x74,
342 0x72, 0x61, 0x03, 0x04, 0xc0, 0xa8, 0x02, 0x01,
343 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
344 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
345 };
346
347 static uint8_t test_addr_acq_ack[] = {
348 0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00,
349 0x80, 0x11, 0xb3, 0x84, 0xc0, 0xa8, 0x02, 0x01,
350 0xc0, 0xa8, 0x02, 0xbf, 0x00, 0x43, 0x00, 0x44,
351 0x01, 0x34, 0x00, 0x00, 0x02, 0x01, 0x06, 0x00,
352 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
353 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x02, 0xbf,
354 0xc0, 0xa8, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00,
355 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
356 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
357 0x00, 0x00, 0x00, 0x00, 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 0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x05, 0x36,
382 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x33, 0x04, 0x00,
383 0x00, 0x02, 0x58, 0x01, 0x04, 0xff, 0xff, 0xff,
384 0x00, 0x2a, 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x0f,
385 0x09, 0x6c, 0x61, 0x62, 0x2e, 0x69, 0x6e, 0x74,
386 0x72, 0x61, 0x03, 0x04, 0xc0, 0xa8, 0x02, 0x01,
387 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
388 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
389 };
390
391 static void test_addr_acq_acquired(sd_dhcp_client *client, int event,
392 void *userdata) {
393 sd_event *e = userdata;
394 sd_dhcp_lease *lease;
395 struct in_addr addr;
396
397 assert_se(client);
398 assert_se(event == SD_DHCP_CLIENT_EVENT_IP_ACQUIRE);
399
400 assert_se(sd_dhcp_client_get_lease(client, &lease) >= 0);
401 assert_se(lease);
402
403 assert_se(sd_dhcp_lease_get_address(lease, &addr) >= 0);
404 assert_se(memcmp(&addr.s_addr, &test_addr_acq_ack[44],
405 sizeof(addr.s_addr)) == 0);
406
407 assert_se(sd_dhcp_lease_get_netmask(lease, &addr) >= 0);
408 assert_se(memcmp(&addr.s_addr, &test_addr_acq_ack[285],
409 sizeof(addr.s_addr)) == 0);
410
411 assert_se(sd_dhcp_lease_get_router(lease, &addr) >= 0);
412 assert_se(memcmp(&addr.s_addr, &test_addr_acq_ack[308],
413 sizeof(addr.s_addr)) == 0);
414
415 if (verbose)
416 printf(" DHCP address acquired\n");
417
418 sd_event_exit(e, 0);
419 }
420
421 static int test_addr_acq_recv_request(size_t size, DHCPMessage *request) {
422 uint16_t udp_check = 0;
423 uint8_t *msg_bytes = (uint8_t *)request;
424 int res;
425
426 res = dhcp_option_parse(request, size, check_options, NULL, NULL);
427 assert_se(res == DHCP_REQUEST);
428 assert_se(xid == request->xid);
429
430 assert_se(msg_bytes[size - 1] == SD_DHCP_OPTION_END);
431
432 if (verbose)
433 printf(" recv DHCP Request 0x%08x\n", be32toh(xid));
434
435 memcpy(&test_addr_acq_ack[26], &udp_check, sizeof(udp_check));
436 memcpy(&test_addr_acq_ack[32], &xid, sizeof(xid));
437 memcpy(&test_addr_acq_ack[56], &mac_addr, ETHER_ADDR_LEN);
438
439 callback_recv = NULL;
440
441 res = write(test_fd[1], test_addr_acq_ack,
442 sizeof(test_addr_acq_ack));
443 assert_se(res == sizeof(test_addr_acq_ack));
444
445 if (verbose)
446 printf(" send DHCP Ack\n");
447
448 return 0;
449 };
450
451 static int test_addr_acq_recv_discover(size_t size, DHCPMessage *discover) {
452 uint16_t udp_check = 0;
453 uint8_t *msg_bytes = (uint8_t *)discover;
454 int res;
455
456 res = dhcp_option_parse(discover, size, check_options, NULL, NULL);
457 assert_se(res == DHCP_DISCOVER);
458
459 assert_se(msg_bytes[size - 1] == SD_DHCP_OPTION_END);
460
461 xid = discover->xid;
462
463 if (verbose)
464 printf(" recv DHCP Discover 0x%08x\n", be32toh(xid));
465
466 memcpy(&test_addr_acq_offer[26], &udp_check, sizeof(udp_check));
467 memcpy(&test_addr_acq_offer[32], &xid, sizeof(xid));
468 memcpy(&test_addr_acq_offer[56], &mac_addr, ETHER_ADDR_LEN);
469
470 callback_recv = test_addr_acq_recv_request;
471
472 res = write(test_fd[1], test_addr_acq_offer,
473 sizeof(test_addr_acq_offer));
474 assert_se(res == sizeof(test_addr_acq_offer));
475
476 if (verbose)
477 printf(" sent DHCP Offer\n");
478
479 return 0;
480 }
481
482 static void test_addr_acq(sd_event *e) {
483 usec_t time_now = now(clock_boottime_or_monotonic());
484 sd_dhcp_client *client;
485 int res, r;
486
487 if (verbose)
488 printf("* %s\n", __FUNCTION__);
489
490 r = sd_dhcp_client_new(&client, false);
491 assert_se(r >= 0);
492 assert_se(client);
493
494 r = sd_dhcp_client_attach_event(client, e, 0);
495 assert_se(r >= 0);
496
497 assert_se(sd_dhcp_client_set_ifindex(client, 42) >= 0);
498 assert_se(sd_dhcp_client_set_mac(client, mac_addr, ETH_ALEN, ARPHRD_ETHER) >= 0);
499
500 assert_se(sd_dhcp_client_set_callback(client, test_addr_acq_acquired, e) >= 0);
501
502 callback_recv = test_addr_acq_recv_discover;
503
504 assert_se(sd_event_add_time(e, &test_hangcheck,
505 clock_boottime_or_monotonic(),
506 time_now + 2 * USEC_PER_SEC, 0,
507 test_dhcp_hangcheck, NULL) >= 0);
508
509 res = sd_dhcp_client_start(client);
510 assert_se(IN_SET(res, 0, -EINPROGRESS));
511
512 assert_se(sd_event_loop(e) >= 0);
513
514 test_hangcheck = sd_event_source_unref(test_hangcheck);
515
516 assert_se(sd_dhcp_client_set_callback(client, NULL, NULL) >= 0);
517 assert_se(sd_dhcp_client_stop(client) >= 0);
518 sd_dhcp_client_unref(client);
519
520 test_fd[1] = safe_close(test_fd[1]);
521
522 callback_recv = NULL;
523 xid = 0;
524 }
525
526 int main(int argc, char *argv[]) {
527 _cleanup_(sd_event_unrefp) sd_event *e;
528
529 log_set_max_level(LOG_DEBUG);
530 log_parse_environment();
531 log_open();
532
533 assert_se(sd_event_new(&e) >= 0);
534
535 test_request_basic(e);
536 test_request_anonymize(e);
537 test_checksum();
538
539 test_discover_message(e);
540 test_addr_acq(e);
541
542 #ifdef VALGRIND
543 /* Make sure the async_close thread has finished.
544 * valgrind would report some of the phread_* structures
545 * as not cleaned up properly. */
546 sleep(1);
547 #endif
548
549 return 0;
550 }