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