]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-network/test-dhcp-client.c
libsystemd-network: introduce $SYSTEMD_NETWORK_TEST_MODE environment variable
[thirdparty/systemd.git] / src / libsystemd-network / test-dhcp-client.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
be391925 2/***
810adae9 3 Copyright © 2013 Intel Corporation. All rights reserved.
be391925
PF
4***/
5
be391925 6#include <errno.h>
ddb82ec2
LP
7#include <net/if.h>
8#include <net/if_arp.h>
39b7f596 9#include <stdio.h>
8c00042c
PF
10#include <sys/socket.h>
11#include <unistd.h>
50b35193
ZJS
12#if HAVE_VALGRIND_VALGRIND_H
13# include <valgrind/valgrind.h>
14#endif
be391925 15
07630cea 16#include "sd-dhcp-client.h"
6e00a806 17#include "sd-event.h"
290c7324 18
b5efdb8a 19#include "alloc-util.h"
5bac5235 20#include "dhcp-identifier.h"
290c7324 21#include "dhcp-internal.h"
07630cea 22#include "dhcp-protocol.h"
3b75435d 23#include "ether-addr-util.h"
3ffd4af2 24#include "fd-util.h"
43fc0955 25#include "random-util.h"
6d7c4033 26#include "tests.h"
be391925 27
3b75435d
YW
28static struct hw_addr_data hw_addr = {
29 .length = ETH_ALEN,
30 .ether = {{ 'A', 'B', 'C', '1', '2', '3' }},
31}, bcast_addr = {
32 .length = ETH_ALEN,
33 .ether = {{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }},
34};
6c8a0f07
PF
35typedef int (*test_callback_recv_t)(size_t size, DHCPMessage *dhcp);
36
5bac5235 37static bool verbose = true;
8c00042c 38static int test_fd[2];
6c8a0f07 39static test_callback_recv_t callback_recv;
234ed3eb 40static be32_t xid;
8c00042c 41
52efd56a 42static void test_request_basic(sd_event *e) {
b25ef18b
TG
43 int r;
44
be391925
PF
45 sd_dhcp_client *client;
46
ede286f9 47 if (verbose)
7fbae5b7 48 printf("* %s\n", __func__);
ede286f9 49
db3d2358 50 /* Initialize client without Anonymize settings. */
51 r = sd_dhcp_client_new(&client, false);
be391925 52
12e0f830
TG
53 assert_se(r >= 0);
54 assert_se(client);
be391925 55
b25ef18b 56 r = sd_dhcp_client_attach_event(client, e, 0);
12e0f830 57 assert_se(r >= 0);
b25ef18b 58
12e0f830
TG
59 assert_se(sd_dhcp_client_set_request_option(NULL, 0) == -EINVAL);
60 assert_se(sd_dhcp_client_set_request_address(NULL, NULL) == -EINVAL);
2f8e7633 61 assert_se(sd_dhcp_client_set_ifindex(NULL, 0) == -EINVAL);
be391925 62
2f8e7633
LP
63 assert_se(sd_dhcp_client_set_ifindex(client, 15) == 0);
64 assert_se(sd_dhcp_client_set_ifindex(client, -42) == -EINVAL);
65 assert_se(sd_dhcp_client_set_ifindex(client, -1) == -EINVAL);
66 assert_se(sd_dhcp_client_set_ifindex(client, 0) == -EINVAL);
67 assert_se(sd_dhcp_client_set_ifindex(client, 1) == 0);
be391925 68
9740eae6
SA
69 assert_se(sd_dhcp_client_set_hostname(client, "host") == 1);
70 assert_se(sd_dhcp_client_set_hostname(client, "host.domain") == 1);
71 assert_se(sd_dhcp_client_set_hostname(client, NULL) == 1);
72 assert_se(sd_dhcp_client_set_hostname(client, "~host") == -EINVAL);
73 assert_se(sd_dhcp_client_set_hostname(client, "~host.domain") == -EINVAL);
74
4081756a
YW
75 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_SUBNET_MASK) == 0);
76 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_ROUTER) == 0);
db3d2358 77 /* This PRL option is not set when using Anonymize, but in this test
78 * Anonymize settings are not being used. */
4081756a
YW
79 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_HOST_NAME) == 0);
80 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_DOMAIN_NAME) == 0);
81 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_DOMAIN_NAME_SERVER) == 0);
82
83 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_PAD) == -EINVAL);
84 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_END) == -EINVAL);
85 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_MESSAGE_TYPE) == -EINVAL);
86 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_OVERLOAD) == -EINVAL);
87 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_PARAMETER_REQUEST_LIST) == -EINVAL);
be391925 88
db3d2358 89 /* RFC7844: option 33 (SD_DHCP_OPTION_STATIC_ROUTE) is set in the
90 * default PRL when using Anonymize, so it is changed to other option
da172fa9
FK
91 * that is not set by default, to check that it was set successfully.
92 * Options not set by default (using or not anonymize) are option 17
db3d2358 93 * (SD_DHCP_OPTION_ROOT_PATH) and 42 (SD_DHCP_OPTION_NTP_SERVER) */
4081756a
YW
94 assert_se(sd_dhcp_client_set_request_option(client, 17) == 1);
95 assert_se(sd_dhcp_client_set_request_option(client, 17) == 0);
96 assert_se(sd_dhcp_client_set_request_option(client, 42) == 1);
db3d2358 97 assert_se(sd_dhcp_client_set_request_option(client, 17) == 0);
6e00a806
ZJS
98
99 sd_dhcp_client_unref(client);
be391925
PF
100}
101
dbb35f1f 102static void test_request_anonymize(sd_event *e) {
103 int r;
104
105 sd_dhcp_client *client;
106
107 if (verbose)
7fbae5b7 108 printf("* %s\n", __func__);
dbb35f1f 109
110 /* Initialize client with Anonymize settings. */
111 r = sd_dhcp_client_new(&client, true);
112
113 assert_se(r >= 0);
114 assert_se(client);
115
116 r = sd_dhcp_client_attach_event(client, e, 0);
117 assert_se(r >= 0);
118
3cb62efe 119 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_NETBIOS_NAME_SERVER) == 0);
dbb35f1f 120 /* This PRL option is not set when using Anonymize */
4081756a
YW
121 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_HOST_NAME) == 1);
122 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_PARAMETER_REQUEST_LIST) == -EINVAL);
dbb35f1f 123
124 /* RFC7844: option 101 (SD_DHCP_OPTION_NEW_TZDB_TIMEZONE) is not set in the
125 * default PRL when using Anonymize, */
4081756a 126 assert_se(sd_dhcp_client_set_request_option(client, 101) == 1);
dbb35f1f 127 assert_se(sd_dhcp_client_set_request_option(client, 101) == 0);
dbb35f1f 128
129 sd_dhcp_client_unref(client);
130}
131
52efd56a 132static void test_checksum(void) {
39b7f596
PF
133 uint8_t buf[20] = {
134 0x45, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,
135 0x40, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
136 0xff, 0xff, 0xff, 0xff
137 };
138
ede286f9 139 if (verbose)
7fbae5b7 140 printf("* %s\n", __func__);
ede286f9 141
0bbc2c1f 142 assert_se(dhcp_packet_checksum((uint8_t*)&buf, 20) == be16toh(0x78ae));
39b7f596
PF
143}
144
43fc0955 145static void test_dhcp_identifier_set_iaid(void) {
6d13616b
TH
146 uint32_t iaid_legacy;
147 be32_t iaid;
43fc0955 148
14805b14
YW
149 assert_se(dhcp_identifier_set_iaid(NULL, &hw_addr, /* legacy = */ true, &iaid_legacy) >= 0);
150 assert_se(dhcp_identifier_set_iaid(NULL, &hw_addr, /* legacy = */ false, &iaid) >= 0);
43fc0955 151
6d13616b 152 /* we expect, that the MAC address was hashed. The legacy value is in native
43fc0955 153 * endianness. */
6d13616b
TH
154 assert_se(iaid_legacy == 0x8dde4ba8u);
155 assert_se(iaid == htole32(0x8dde4ba8u));
156#if __BYTE_ORDER == __LITTLE_ENDIAN
157 assert_se(iaid == iaid_legacy);
158#else
fe92eb79 159 assert_se(iaid == bswap_32(iaid_legacy));
6d13616b 160#endif
43fc0955
TH
161}
162
52efd56a 163static int check_options(uint8_t code, uint8_t len, const void *option, void *userdata) {
79893116 164 switch (code) {
22805d92 165 case SD_DHCP_OPTION_CLIENT_IDENTIFIER:
5bac5235
TG
166 {
167 uint32_t iaid;
168 struct duid duid;
169 size_t duid_len;
170
8b50b319 171 assert_se(dhcp_identifier_set_duid_en(&duid, &duid_len) >= 0);
14805b14 172 assert_se(dhcp_identifier_set_iaid(NULL, &hw_addr, /* legacy = */ true, &iaid) >= 0);
5bac5235
TG
173
174 assert_se(len == sizeof(uint8_t) + sizeof(uint32_t) + duid_len);
175 assert_se(len == 19);
e4735228 176 assert_se(((uint8_t*) option)[0] == 0xff);
5bac5235 177
e4735228
LP
178 assert_se(memcmp((uint8_t*) option + 1, &iaid, sizeof(iaid)) == 0);
179 assert_se(memcmp((uint8_t*) option + 5, &duid, duid_len) == 0);
d790d3f1 180 break;
5bac5235 181 }
d790d3f1
PF
182
183 default:
184 break;
185 }
186
290c7324
PF
187 return 0;
188}
189
52efd56a 190int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link, const void *packet, size_t len) {
290c7324 191 size_t size;
3d41b6b8 192 _cleanup_free_ DHCPPacket *discover = NULL;
290c7324 193 uint16_t ip_check, udp_check;
290c7324 194
12e0f830
TG
195 assert_se(s >= 0);
196 assert_se(packet);
290c7324 197
d47e1de4 198 size = sizeof(DHCPPacket);
12e0f830 199 assert_se(len > size);
290c7324
PF
200
201 discover = memdup(packet, len);
202
12e0f830
TG
203 assert_se(discover->ip.ttl == IPDEFTTL);
204 assert_se(discover->ip.protocol == IPPROTO_UDP);
205 assert_se(discover->ip.saddr == INADDR_ANY);
206 assert_se(discover->ip.daddr == INADDR_BROADCAST);
207 assert_se(discover->udp.source == be16toh(DHCP_PORT_CLIENT));
208 assert_se(discover->udp.dest == be16toh(DHCP_PORT_SERVER));
290c7324
PF
209
210 ip_check = discover->ip.check;
211
212 discover->ip.ttl = 0;
213 discover->ip.check = discover->udp.len;
214
0bbc2c1f 215 udp_check = ~dhcp_packet_checksum((uint8_t*)&discover->ip.ttl, len - 8);
12e0f830 216 assert_se(udp_check == 0xffff);
290c7324
PF
217
218 discover->ip.ttl = IPDEFTTL;
219 discover->ip.check = ip_check;
220
0bbc2c1f 221 ip_check = ~dhcp_packet_checksum((uint8_t*)&discover->ip, sizeof(discover->ip));
12e0f830 222 assert_se(ip_check == 0xffff);
290c7324 223
12e0f830 224 assert_se(discover->dhcp.xid);
3b75435d 225 assert_se(memcmp(discover->dhcp.chaddr, hw_addr.bytes, hw_addr.length) == 0);
6c8a0f07 226
290c7324
PF
227 size = len - sizeof(struct iphdr) - sizeof(struct udphdr);
228
12e0f830 229 assert_se(callback_recv);
6c8a0f07 230 callback_recv(size, &discover->dhcp);
290c7324
PF
231
232 return 575;
233}
234
52efd56a 235int dhcp_network_bind_raw_socket(
1a6c9136 236 int ifindex,
52efd56a
LP
237 union sockaddr_union *link,
238 uint32_t id,
073a1daa
YW
239 const struct hw_addr_data *_hw_addr,
240 const struct hw_addr_data *_bcast_addr,
ea577968 241 uint16_t arp_type,
242 uint16_t port,
243 bool so_priority_set,
244 int so_priority) {
52efd56a 245
3e29b889 246 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) < 0)
8c00042c
PF
247 return -errno;
248
249 return test_fd[0];
250}
251
afe42aef 252int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port, int ip_service_type) {
fe0885f8
ZJS
253 int fd;
254
3e29b889 255 fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
fe0885f8
ZJS
256 if (fd < 0)
257 return -errno;
258
259 return fd;
234fc2df
PF
260}
261
52efd56a 262int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port, const void *packet, size_t len) {
234fc2df
PF
263 return 0;
264}
265
52efd56a 266static int test_discover_message_verify(size_t size, struct DHCPMessage *dhcp) {
6c8a0f07
PF
267 int res;
268
f693e9b3 269 res = dhcp_option_parse(dhcp, size, check_options, NULL, NULL);
12e0f830 270 assert_se(res == DHCP_DISCOVER);
6c8a0f07
PF
271
272 if (verbose)
273 printf(" recv DHCP Discover 0x%08x\n", be32toh(dhcp->xid));
274
275 return 0;
276}
277
52efd56a 278static void test_discover_message(sd_event *e) {
290c7324 279 sd_dhcp_client *client;
b25ef18b 280 int res, r;
290c7324 281
ede286f9 282 if (verbose)
7fbae5b7 283 printf("* %s\n", __func__);
ede286f9 284
db3d2358 285 r = sd_dhcp_client_new(&client, false);
12e0f830
TG
286 assert_se(r >= 0);
287 assert_se(client);
290c7324 288
b25ef18b 289 r = sd_dhcp_client_attach_event(client, e, 0);
12e0f830 290 assert_se(r >= 0);
b25ef18b 291
2f8e7633 292 assert_se(sd_dhcp_client_set_ifindex(client, 42) >= 0);
3b75435d 293 assert_se(sd_dhcp_client_set_mac(client, hw_addr.bytes, bcast_addr.bytes, hw_addr.length, ARPHRD_ETHER) >= 0);
290c7324 294
12e0f830 295 assert_se(sd_dhcp_client_set_request_option(client, 248) >= 0);
290c7324 296
6c8a0f07
PF
297 callback_recv = test_discover_message_verify;
298
290c7324
PF
299 res = sd_dhcp_client_start(client);
300
4c701096 301 assert_se(IN_SET(res, 0, -EINPROGRESS));
8c00042c 302
f5fbe71d 303 sd_event_run(e, UINT64_MAX);
6c8a0f07
PF
304
305 sd_dhcp_client_stop(client);
e5b04c8d 306 sd_dhcp_client_unref(client);
6c8a0f07 307
2afa65c3 308 test_fd[1] = safe_close(test_fd[1]);
6c8a0f07
PF
309
310 callback_recv = NULL;
290c7324
PF
311}
312
234ed3eb
PF
313static uint8_t test_addr_acq_offer[] = {
314 0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00,
315 0x80, 0x11, 0xb3, 0x84, 0xc0, 0xa8, 0x02, 0x01,
316 0xc0, 0xa8, 0x02, 0xbf, 0x00, 0x43, 0x00, 0x44,
317 0x01, 0x34, 0x00, 0x00, 0x02, 0x01, 0x06, 0x00,
318 0x6f, 0x95, 0x2f, 0x30, 0x00, 0x00, 0x00, 0x00,
319 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x02, 0xbf,
320 0xc0, 0xa8, 0x02, 0x01, 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 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
346 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
347 0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x02, 0x36,
348 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x33, 0x04, 0x00,
349 0x00, 0x02, 0x58, 0x01, 0x04, 0xff, 0xff, 0xff,
350 0x00, 0x2a, 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x0f,
351 0x09, 0x6c, 0x61, 0x62, 0x2e, 0x69, 0x6e, 0x74,
352 0x72, 0x61, 0x03, 0x04, 0xc0, 0xa8, 0x02, 0x01,
353 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
354 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
355};
356
357static uint8_t test_addr_acq_ack[] = {
358 0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00,
359 0x80, 0x11, 0xb3, 0x84, 0xc0, 0xa8, 0x02, 0x01,
360 0xc0, 0xa8, 0x02, 0xbf, 0x00, 0x43, 0x00, 0x44,
361 0x01, 0x34, 0x00, 0x00, 0x02, 0x01, 0x06, 0x00,
362 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
363 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x02, 0xbf,
364 0xc0, 0xa8, 0x02, 0x01, 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 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 0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x05, 0x36,
392 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x33, 0x04, 0x00,
d47e1de4 393 0x00, 0x02, 0x58, 0x01, 0x04, 0xff, 0xff, 0xff,
234ed3eb
PF
394 0x00, 0x2a, 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x0f,
395 0x09, 0x6c, 0x61, 0x62, 0x2e, 0x69, 0x6e, 0x74,
396 0x72, 0x61, 0x03, 0x04, 0xc0, 0xa8, 0x02, 0x01,
397 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
398 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
399};
400
727b5734 401static int test_addr_acq_acquired(sd_dhcp_client *client, int event,
c4acff12 402 void *userdata) {
234ed3eb
PF
403 sd_event *e = userdata;
404 sd_dhcp_lease *lease;
405 struct in_addr addr;
f8862395 406 const struct in_addr *addrs;
234ed3eb 407
12e0f830 408 assert_se(client);
727b5734 409 assert_se(IN_SET(event, SD_DHCP_CLIENT_EVENT_IP_ACQUIRE, SD_DHCP_CLIENT_EVENT_SELECTING));
234ed3eb 410
12e0f830
TG
411 assert_se(sd_dhcp_client_get_lease(client, &lease) >= 0);
412 assert_se(lease);
234ed3eb 413
12e0f830
TG
414 assert_se(sd_dhcp_lease_get_address(lease, &addr) >= 0);
415 assert_se(memcmp(&addr.s_addr, &test_addr_acq_ack[44],
234ed3eb
PF
416 sizeof(addr.s_addr)) == 0);
417
12e0f830
TG
418 assert_se(sd_dhcp_lease_get_netmask(lease, &addr) >= 0);
419 assert_se(memcmp(&addr.s_addr, &test_addr_acq_ack[285],
234ed3eb
PF
420 sizeof(addr.s_addr)) == 0);
421
f8862395
TH
422 assert_se(sd_dhcp_lease_get_router(lease, &addrs) == 1);
423 assert_se(memcmp(&addrs[0].s_addr, &test_addr_acq_ack[308],
424 sizeof(addrs[0].s_addr)) == 0);
234ed3eb
PF
425
426 if (verbose)
427 printf(" DHCP address acquired\n");
428
429 sd_event_exit(e, 0);
727b5734
SS
430
431 return 0;
234ed3eb
PF
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));
3b75435d 450 memcpy(&test_addr_acq_ack[56], hw_addr.bytes, hw_addr.length);
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));
3b75435d 481 memcpy(&test_addr_acq_offer[56], hw_addr.bytes, hw_addr.length);
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) {
234ed3eb
PF
496 sd_dhcp_client *client;
497 int res, r;
498
499 if (verbose)
7fbae5b7 500 printf("* %s\n", __func__);
234ed3eb 501
db3d2358 502 r = sd_dhcp_client_new(&client, false);
12e0f830
TG
503 assert_se(r >= 0);
504 assert_se(client);
234ed3eb
PF
505
506 r = sd_dhcp_client_attach_event(client, e, 0);
12e0f830 507 assert_se(r >= 0);
234ed3eb 508
2f8e7633 509 assert_se(sd_dhcp_client_set_ifindex(client, 42) >= 0);
3b75435d 510 assert_se(sd_dhcp_client_set_mac(client, hw_addr.bytes, bcast_addr.bytes, hw_addr.length, ARPHRD_ETHER) >= 0);
234ed3eb 511
afa3509a 512 assert_se(sd_dhcp_client_set_callback(client, test_addr_acq_acquired, e) >= 0);
234ed3eb
PF
513
514 callback_recv = test_addr_acq_recv_discover;
515
ba4e0427 516 assert_se(sd_event_add_time_relative(e, NULL, CLOCK_BOOTTIME,
2e37084f
YW
517 2 * USEC_PER_SEC, 0,
518 NULL, INT_TO_PTR(-ETIMEDOUT)) >= 0);
8fc8e3ab 519
234ed3eb 520 res = sd_dhcp_client_start(client);
4c701096 521 assert_se(IN_SET(res, 0, -EINPROGRESS));
234ed3eb 522
3b981f74 523 assert_se(sd_event_loop(e) >= 0);
234ed3eb 524
fc292b5f
TG
525 assert_se(sd_dhcp_client_set_callback(client, NULL, NULL) >= 0);
526 assert_se(sd_dhcp_client_stop(client) >= 0);
e5b04c8d 527 sd_dhcp_client_unref(client);
234ed3eb 528
2afa65c3 529 test_fd[1] = safe_close(test_fd[1]);
234ed3eb
PF
530
531 callback_recv = NULL;
532 xid = 0;
533}
534
c4acff12 535int main(int argc, char *argv[]) {
4afd3348 536 _cleanup_(sd_event_unrefp) sd_event *e;
6e00a806 537
8b50b319
YW
538 assert_se(setenv("SYSTEMD_NETWORK_TEST_MODE", "1", 1) >= 0);
539
6d7c4033 540 test_setup_logging(LOG_DEBUG);
d3d8ac2f 541
12e0f830 542 assert_se(sd_event_new(&e) >= 0);
d3d8ac2f
PF
543
544 test_request_basic(e);
dbb35f1f 545 test_request_anonymize(e);
39b7f596 546 test_checksum();
43fc0955 547 test_dhcp_identifier_set_iaid();
be391925 548
d3d8ac2f 549 test_discover_message(e);
234ed3eb 550 test_addr_acq(e);
290c7324 551
50b35193 552#if HAVE_VALGRIND_VALGRIND_H
374c22b3
ZJS
553 /* Make sure the async_close thread has finished.
554 * valgrind would report some of the phread_* structures
555 * as not cleaned up properly. */
50b35193
ZJS
556 if (RUNNING_ON_VALGRIND)
557 sleep(1);
374c22b3
ZJS
558#endif
559
be391925
PF
560 return 0;
561}