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