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