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