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