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