]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-network/test-dhcp-client.c
dhcp: make dhcp_network_bind_raw_socket() take struct hw_addr_data
[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>
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"
3b75435d 20#include "ether-addr-util.h"
3ffd4af2 21#include "fd-util.h"
43fc0955 22#include "random-util.h"
6d7c4033 23#include "tests.h"
cf0fbc49 24#include "util.h"
be391925 25
3b75435d
YW
26static struct hw_addr_data hw_addr = {
27 .length = ETH_ALEN,
28 .ether = {{ 'A', 'B', 'C', '1', '2', '3' }},
29}, bcast_addr = {
30 .length = ETH_ALEN,
31 .ether = {{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }},
32};
6c8a0f07
PF
33typedef int (*test_callback_recv_t)(size_t size, DHCPMessage *dhcp);
34
5bac5235 35static bool verbose = true;
8c00042c 36static int test_fd[2];
6c8a0f07 37static test_callback_recv_t callback_recv;
234ed3eb 38static be32_t xid;
8c00042c 39
52efd56a 40static void test_request_basic(sd_event *e) {
b25ef18b
TG
41 int r;
42
be391925
PF
43 sd_dhcp_client *client;
44
ede286f9 45 if (verbose)
7fbae5b7 46 printf("* %s\n", __func__);
ede286f9 47
db3d2358 48 /* Initialize client without Anonymize settings. */
49 r = sd_dhcp_client_new(&client, false);
be391925 50
12e0f830
TG
51 assert_se(r >= 0);
52 assert_se(client);
be391925 53
b25ef18b 54 r = sd_dhcp_client_attach_event(client, e, 0);
12e0f830 55 assert_se(r >= 0);
b25ef18b 56
12e0f830
TG
57 assert_se(sd_dhcp_client_set_request_option(NULL, 0) == -EINVAL);
58 assert_se(sd_dhcp_client_set_request_address(NULL, NULL) == -EINVAL);
2f8e7633 59 assert_se(sd_dhcp_client_set_ifindex(NULL, 0) == -EINVAL);
be391925 60
2f8e7633
LP
61 assert_se(sd_dhcp_client_set_ifindex(client, 15) == 0);
62 assert_se(sd_dhcp_client_set_ifindex(client, -42) == -EINVAL);
63 assert_se(sd_dhcp_client_set_ifindex(client, -1) == -EINVAL);
64 assert_se(sd_dhcp_client_set_ifindex(client, 0) == -EINVAL);
65 assert_se(sd_dhcp_client_set_ifindex(client, 1) == 0);
be391925 66
9740eae6
SA
67 assert_se(sd_dhcp_client_set_hostname(client, "host") == 1);
68 assert_se(sd_dhcp_client_set_hostname(client, "host.domain") == 1);
69 assert_se(sd_dhcp_client_set_hostname(client, NULL) == 1);
70 assert_se(sd_dhcp_client_set_hostname(client, "~host") == -EINVAL);
71 assert_se(sd_dhcp_client_set_hostname(client, "~host.domain") == -EINVAL);
72
4081756a
YW
73 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_SUBNET_MASK) == 0);
74 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_ROUTER) == 0);
db3d2358 75 /* This PRL option is not set when using Anonymize, but in this test
76 * Anonymize settings are not being used. */
4081756a
YW
77 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_HOST_NAME) == 0);
78 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_DOMAIN_NAME) == 0);
79 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_DOMAIN_NAME_SERVER) == 0);
80
81 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_PAD) == -EINVAL);
82 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_END) == -EINVAL);
83 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_MESSAGE_TYPE) == -EINVAL);
84 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_OVERLOAD) == -EINVAL);
85 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_PARAMETER_REQUEST_LIST) == -EINVAL);
be391925 86
db3d2358 87 /* RFC7844: option 33 (SD_DHCP_OPTION_STATIC_ROUTE) is set in the
88 * default PRL when using Anonymize, so it is changed to other option
da172fa9
FK
89 * that is not set by default, to check that it was set successfully.
90 * Options not set by default (using or not anonymize) are option 17
db3d2358 91 * (SD_DHCP_OPTION_ROOT_PATH) and 42 (SD_DHCP_OPTION_NTP_SERVER) */
4081756a
YW
92 assert_se(sd_dhcp_client_set_request_option(client, 17) == 1);
93 assert_se(sd_dhcp_client_set_request_option(client, 17) == 0);
94 assert_se(sd_dhcp_client_set_request_option(client, 42) == 1);
db3d2358 95 assert_se(sd_dhcp_client_set_request_option(client, 17) == 0);
6e00a806
ZJS
96
97 sd_dhcp_client_unref(client);
be391925
PF
98}
99
dbb35f1f 100static void test_request_anonymize(sd_event *e) {
101 int r;
102
103 sd_dhcp_client *client;
104
105 if (verbose)
7fbae5b7 106 printf("* %s\n", __func__);
dbb35f1f 107
108 /* Initialize client with Anonymize settings. */
109 r = sd_dhcp_client_new(&client, true);
110
111 assert_se(r >= 0);
112 assert_se(client);
113
114 r = sd_dhcp_client_attach_event(client, e, 0);
115 assert_se(r >= 0);
116
3cb62efe 117 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_NETBIOS_NAME_SERVER) == 0);
dbb35f1f 118 /* This PRL option is not set when using Anonymize */
4081756a
YW
119 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_HOST_NAME) == 1);
120 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_PARAMETER_REQUEST_LIST) == -EINVAL);
dbb35f1f 121
122 /* RFC7844: option 101 (SD_DHCP_OPTION_NEW_TZDB_TIMEZONE) is not set in the
123 * default PRL when using Anonymize, */
4081756a 124 assert_se(sd_dhcp_client_set_request_option(client, 101) == 1);
dbb35f1f 125 assert_se(sd_dhcp_client_set_request_option(client, 101) == 0);
dbb35f1f 126
127 sd_dhcp_client_unref(client);
128}
129
52efd56a 130static void test_checksum(void) {
39b7f596
PF
131 uint8_t buf[20] = {
132 0x45, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,
133 0x40, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
134 0xff, 0xff, 0xff, 0xff
135 };
136
ede286f9 137 if (verbose)
7fbae5b7 138 printf("* %s\n", __func__);
ede286f9 139
0bbc2c1f 140 assert_se(dhcp_packet_checksum((uint8_t*)&buf, 20) == be16toh(0x78ae));
39b7f596
PF
141}
142
43fc0955 143static void test_dhcp_identifier_set_iaid(void) {
6d13616b
TH
144 uint32_t iaid_legacy;
145 be32_t iaid;
43fc0955 146
3b75435d 147 assert_se(dhcp_identifier_set_iaid(42, &hw_addr, /* legacy = */ true,
8d71f2b3 148 /* use_mac = */ true, &iaid_legacy) >= 0);
3b75435d 149 assert_se(dhcp_identifier_set_iaid(42, &hw_addr, /* legacy = */ false,
8d71f2b3 150 /* use_mac = */ true, &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
ac680f76 171 assert_se(dhcp_identifier_set_duid_en(/* test_mode = */ true, &duid, &duid_len) >= 0);
3b75435d 172 assert_se(dhcp_identifier_set_iaid(42, &hw_addr, /* legacy = */ true, /* use_mac = */ 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;
f937d3d6 192 _cleanup_free_ DHCPPacket *discover;
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,
9faed222 241 uint16_t arp_type, uint16_t port) {
52efd56a 242
3e29b889 243 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) < 0)
8c00042c
PF
244 return -errno;
245
246 return test_fd[0];
247}
248
afe42aef 249int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port, int ip_service_type) {
fe0885f8
ZJS
250 int fd;
251
3e29b889 252 fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
fe0885f8
ZJS
253 if (fd < 0)
254 return -errno;
255
256 return fd;
234fc2df
PF
257}
258
52efd56a 259int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port, const void *packet, size_t len) {
234fc2df
PF
260 return 0;
261}
262
52efd56a 263static int test_discover_message_verify(size_t size, struct DHCPMessage *dhcp) {
6c8a0f07
PF
264 int res;
265
f693e9b3 266 res = dhcp_option_parse(dhcp, size, check_options, NULL, NULL);
12e0f830 267 assert_se(res == DHCP_DISCOVER);
6c8a0f07
PF
268
269 if (verbose)
270 printf(" recv DHCP Discover 0x%08x\n", be32toh(dhcp->xid));
271
272 return 0;
273}
274
52efd56a 275static void test_discover_message(sd_event *e) {
290c7324 276 sd_dhcp_client *client;
b25ef18b 277 int res, r;
290c7324 278
ede286f9 279 if (verbose)
7fbae5b7 280 printf("* %s\n", __func__);
ede286f9 281
db3d2358 282 r = sd_dhcp_client_new(&client, false);
12e0f830
TG
283 assert_se(r >= 0);
284 assert_se(client);
290c7324 285
b25ef18b 286 r = sd_dhcp_client_attach_event(client, e, 0);
12e0f830 287 assert_se(r >= 0);
b25ef18b 288
2f8e7633 289 assert_se(sd_dhcp_client_set_ifindex(client, 42) >= 0);
3b75435d 290 assert_se(sd_dhcp_client_set_mac(client, hw_addr.bytes, bcast_addr.bytes, hw_addr.length, ARPHRD_ETHER) >= 0);
8d71f2b3 291 dhcp_client_set_test_mode(client, true);
290c7324 292
12e0f830 293 assert_se(sd_dhcp_client_set_request_option(client, 248) >= 0);
290c7324 294
6c8a0f07
PF
295 callback_recv = test_discover_message_verify;
296
290c7324
PF
297 res = sd_dhcp_client_start(client);
298
4c701096 299 assert_se(IN_SET(res, 0, -EINPROGRESS));
8c00042c 300
f5fbe71d 301 sd_event_run(e, UINT64_MAX);
6c8a0f07
PF
302
303 sd_dhcp_client_stop(client);
e5b04c8d 304 sd_dhcp_client_unref(client);
6c8a0f07 305
2afa65c3 306 test_fd[1] = safe_close(test_fd[1]);
6c8a0f07
PF
307
308 callback_recv = NULL;
290c7324
PF
309}
310
234ed3eb
PF
311static uint8_t test_addr_acq_offer[] = {
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 0x6f, 0x95, 0x2f, 0x30, 0x00, 0x00, 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, 0x02, 0x36,
346 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x33, 0x04, 0x00,
347 0x00, 0x02, 0x58, 0x01, 0x04, 0xff, 0xff, 0xff,
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 uint8_t test_addr_acq_ack[] = {
356 0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00,
357 0x80, 0x11, 0xb3, 0x84, 0xc0, 0xa8, 0x02, 0x01,
358 0xc0, 0xa8, 0x02, 0xbf, 0x00, 0x43, 0x00, 0x44,
359 0x01, 0x34, 0x00, 0x00, 0x02, 0x01, 0x06, 0x00,
360 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
361 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x02, 0xbf,
362 0xc0, 0xa8, 0x02, 0x01, 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 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 0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x05, 0x36,
390 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x33, 0x04, 0x00,
d47e1de4 391 0x00, 0x02, 0x58, 0x01, 0x04, 0xff, 0xff, 0xff,
234ed3eb
PF
392 0x00, 0x2a, 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x0f,
393 0x09, 0x6c, 0x61, 0x62, 0x2e, 0x69, 0x6e, 0x74,
394 0x72, 0x61, 0x03, 0x04, 0xc0, 0xa8, 0x02, 0x01,
395 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
396 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
397};
398
727b5734 399static int test_addr_acq_acquired(sd_dhcp_client *client, int event,
c4acff12 400 void *userdata) {
234ed3eb
PF
401 sd_event *e = userdata;
402 sd_dhcp_lease *lease;
403 struct in_addr addr;
f8862395 404 const struct in_addr *addrs;
234ed3eb 405
12e0f830 406 assert_se(client);
727b5734 407 assert_se(IN_SET(event, SD_DHCP_CLIENT_EVENT_IP_ACQUIRE, SD_DHCP_CLIENT_EVENT_SELECTING));
234ed3eb 408
12e0f830
TG
409 assert_se(sd_dhcp_client_get_lease(client, &lease) >= 0);
410 assert_se(lease);
234ed3eb 411
12e0f830
TG
412 assert_se(sd_dhcp_lease_get_address(lease, &addr) >= 0);
413 assert_se(memcmp(&addr.s_addr, &test_addr_acq_ack[44],
234ed3eb
PF
414 sizeof(addr.s_addr)) == 0);
415
12e0f830
TG
416 assert_se(sd_dhcp_lease_get_netmask(lease, &addr) >= 0);
417 assert_se(memcmp(&addr.s_addr, &test_addr_acq_ack[285],
234ed3eb
PF
418 sizeof(addr.s_addr)) == 0);
419
f8862395
TH
420 assert_se(sd_dhcp_lease_get_router(lease, &addrs) == 1);
421 assert_se(memcmp(&addrs[0].s_addr, &test_addr_acq_ack[308],
422 sizeof(addrs[0].s_addr)) == 0);
234ed3eb
PF
423
424 if (verbose)
425 printf(" DHCP address acquired\n");
426
427 sd_event_exit(e, 0);
727b5734
SS
428
429 return 0;
234ed3eb
PF
430}
431
c4acff12 432static int test_addr_acq_recv_request(size_t size, DHCPMessage *request) {
234ed3eb 433 uint16_t udp_check = 0;
d790d3f1 434 uint8_t *msg_bytes = (uint8_t *)request;
234ed3eb
PF
435 int res;
436
f693e9b3 437 res = dhcp_option_parse(request, size, check_options, NULL, NULL);
12e0f830
TG
438 assert_se(res == DHCP_REQUEST);
439 assert_se(xid == request->xid);
234ed3eb 440
22805d92 441 assert_se(msg_bytes[size - 1] == SD_DHCP_OPTION_END);
d790d3f1 442
234ed3eb
PF
443 if (verbose)
444 printf(" recv DHCP Request 0x%08x\n", be32toh(xid));
445
446 memcpy(&test_addr_acq_ack[26], &udp_check, sizeof(udp_check));
447 memcpy(&test_addr_acq_ack[32], &xid, sizeof(xid));
3b75435d 448 memcpy(&test_addr_acq_ack[56], hw_addr.bytes, hw_addr.length);
234ed3eb
PF
449
450 callback_recv = NULL;
451
452 res = write(test_fd[1], test_addr_acq_ack,
453 sizeof(test_addr_acq_ack));
12e0f830 454 assert_se(res == sizeof(test_addr_acq_ack));
234ed3eb
PF
455
456 if (verbose)
457 printf(" send DHCP Ack\n");
458
459 return 0;
460};
461
c4acff12 462static int test_addr_acq_recv_discover(size_t size, DHCPMessage *discover) {
234ed3eb 463 uint16_t udp_check = 0;
d790d3f1 464 uint8_t *msg_bytes = (uint8_t *)discover;
234ed3eb
PF
465 int res;
466
f693e9b3 467 res = dhcp_option_parse(discover, size, check_options, NULL, NULL);
12e0f830 468 assert_se(res == DHCP_DISCOVER);
234ed3eb 469
22805d92 470 assert_se(msg_bytes[size - 1] == SD_DHCP_OPTION_END);
d790d3f1 471
234ed3eb
PF
472 xid = discover->xid;
473
474 if (verbose)
475 printf(" recv DHCP Discover 0x%08x\n", be32toh(xid));
476
477 memcpy(&test_addr_acq_offer[26], &udp_check, sizeof(udp_check));
478 memcpy(&test_addr_acq_offer[32], &xid, sizeof(xid));
3b75435d 479 memcpy(&test_addr_acq_offer[56], hw_addr.bytes, hw_addr.length);
234ed3eb
PF
480
481 callback_recv = test_addr_acq_recv_request;
482
483 res = write(test_fd[1], test_addr_acq_offer,
484 sizeof(test_addr_acq_offer));
12e0f830 485 assert_se(res == sizeof(test_addr_acq_offer));
234ed3eb
PF
486
487 if (verbose)
c4acff12 488 printf(" sent DHCP Offer\n");
234ed3eb
PF
489
490 return 0;
491}
492
c4acff12 493static void test_addr_acq(sd_event *e) {
234ed3eb
PF
494 sd_dhcp_client *client;
495 int res, r;
496
497 if (verbose)
7fbae5b7 498 printf("* %s\n", __func__);
234ed3eb 499
db3d2358 500 r = sd_dhcp_client_new(&client, false);
12e0f830
TG
501 assert_se(r >= 0);
502 assert_se(client);
234ed3eb
PF
503
504 r = sd_dhcp_client_attach_event(client, e, 0);
12e0f830 505 assert_se(r >= 0);
234ed3eb 506
2f8e7633 507 assert_se(sd_dhcp_client_set_ifindex(client, 42) >= 0);
3b75435d 508 assert_se(sd_dhcp_client_set_mac(client, hw_addr.bytes, bcast_addr.bytes, hw_addr.length, ARPHRD_ETHER) >= 0);
8d71f2b3 509 dhcp_client_set_test_mode(client, true);
234ed3eb 510
afa3509a 511 assert_se(sd_dhcp_client_set_callback(client, test_addr_acq_acquired, e) >= 0);
234ed3eb
PF
512
513 callback_recv = test_addr_acq_recv_discover;
514
ba4e0427 515 assert_se(sd_event_add_time_relative(e, NULL, CLOCK_BOOTTIME,
2e37084f
YW
516 2 * USEC_PER_SEC, 0,
517 NULL, INT_TO_PTR(-ETIMEDOUT)) >= 0);
8fc8e3ab 518
234ed3eb 519 res = sd_dhcp_client_start(client);
4c701096 520 assert_se(IN_SET(res, 0, -EINPROGRESS));
234ed3eb 521
fc292b5f 522 assert_se(sd_event_loop(e) >= 0);
234ed3eb 523
fc292b5f
TG
524 assert_se(sd_dhcp_client_set_callback(client, NULL, NULL) >= 0);
525 assert_se(sd_dhcp_client_stop(client) >= 0);
e5b04c8d 526 sd_dhcp_client_unref(client);
234ed3eb 527
2afa65c3 528 test_fd[1] = safe_close(test_fd[1]);
234ed3eb
PF
529
530 callback_recv = NULL;
531 xid = 0;
532}
533
c4acff12 534int main(int argc, char *argv[]) {
4afd3348 535 _cleanup_(sd_event_unrefp) sd_event *e;
6e00a806 536
6d7c4033 537 test_setup_logging(LOG_DEBUG);
d3d8ac2f 538
12e0f830 539 assert_se(sd_event_new(&e) >= 0);
d3d8ac2f
PF
540
541 test_request_basic(e);
dbb35f1f 542 test_request_anonymize(e);
39b7f596 543 test_checksum();
43fc0955 544 test_dhcp_identifier_set_iaid();
be391925 545
d3d8ac2f 546 test_discover_message(e);
234ed3eb 547 test_addr_acq(e);
290c7324 548
d18cb393 549#if VALGRIND
374c22b3
ZJS
550 /* Make sure the async_close thread has finished.
551 * valgrind would report some of the phread_* structures
552 * as not cleaned up properly. */
553 sleep(1);
554#endif
555
be391925
PF
556 return 0;
557}