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