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