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