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