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