]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-network/test-dhcp-client.c
Merge pull request #29692 from H5117/fix_pkcs11_uri
[thirdparty/systemd.git] / src / libsystemd-network / test-dhcp-client.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
2 /***
3 Copyright © 2013 Intel Corporation. All rights reserved.
4 ***/
5
6 #include <errno.h>
7 #include <net/if.h>
8 #include <net/if_arp.h>
9 #include <stdio.h>
10 #include <sys/socket.h>
11 #include <unistd.h>
12 #if HAVE_VALGRIND_VALGRIND_H
13 # include <valgrind/valgrind.h>
14 #endif
15
16 #include "sd-dhcp-client.h"
17 #include "sd-event.h"
18
19 #include "alloc-util.h"
20 #include "dhcp-duid-internal.h"
21 #include "dhcp-network.h"
22 #include "dhcp-option.h"
23 #include "dhcp-packet.h"
24 #include "ether-addr-util.h"
25 #include "fd-util.h"
26 #include "random-util.h"
27 #include "tests.h"
28
29 static struct hw_addr_data hw_addr = {
30 .length = ETH_ALEN,
31 .ether = {{ 'A', 'B', 'C', '1', '2', '3' }},
32 }, bcast_addr = {
33 .length = ETH_ALEN,
34 .ether = {{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }},
35 };
36 typedef int (*test_callback_recv_t)(size_t size, DHCPMessage *dhcp);
37
38 static bool verbose = true;
39 static int test_fd[2];
40 static test_callback_recv_t callback_recv;
41 static be32_t xid;
42
43 static void test_request_basic(sd_event *e) {
44 int r;
45
46 sd_dhcp_client *client;
47
48 if (verbose)
49 printf("* %s\n", __func__);
50
51 /* Initialize client without Anonymize settings. */
52 r = sd_dhcp_client_new(&client, false);
53
54 assert_se(r >= 0);
55 assert_se(client);
56
57 r = sd_dhcp_client_attach_event(client, e, 0);
58 assert_se(r >= 0);
59
60 ASSERT_RETURN_EXPECTED_SE(sd_dhcp_client_set_request_option(NULL, 0) == -EINVAL);
61 ASSERT_RETURN_EXPECTED_SE(sd_dhcp_client_set_request_address(NULL, NULL) == -EINVAL);
62 ASSERT_RETURN_EXPECTED_SE(sd_dhcp_client_set_ifindex(NULL, 0) == -EINVAL);
63
64 assert_se(sd_dhcp_client_set_ifindex(client, 15) == 0);
65 ASSERT_RETURN_EXPECTED_SE(sd_dhcp_client_set_ifindex(client, -42) == -EINVAL);
66 ASSERT_RETURN_EXPECTED_SE(sd_dhcp_client_set_ifindex(client, -1) == -EINVAL);
67 ASSERT_RETURN_EXPECTED_SE(sd_dhcp_client_set_ifindex(client, 0) == -EINVAL);
68 assert_se(sd_dhcp_client_set_ifindex(client, 1) == 0);
69
70 assert_se(sd_dhcp_client_set_hostname(client, "host") == 1);
71 assert_se(sd_dhcp_client_set_hostname(client, "host.domain") == 1);
72 assert_se(sd_dhcp_client_set_hostname(client, NULL) == 1);
73 assert_se(sd_dhcp_client_set_hostname(client, "~host") == -EINVAL);
74 assert_se(sd_dhcp_client_set_hostname(client, "~host.domain") == -EINVAL);
75
76 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_SUBNET_MASK) == 0);
77 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_ROUTER) == 0);
78 /* This PRL option is not set when using Anonymize, but in this test
79 * Anonymize settings are not being used. */
80 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_HOST_NAME) == 0);
81 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_DOMAIN_NAME) == 0);
82 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_DOMAIN_NAME_SERVER) == 0);
83
84 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_PAD) == -EINVAL);
85 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_END) == -EINVAL);
86 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_MESSAGE_TYPE) == -EINVAL);
87 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_OVERLOAD) == -EINVAL);
88 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_PARAMETER_REQUEST_LIST) == -EINVAL);
89
90 /* RFC7844: option 33 (SD_DHCP_OPTION_STATIC_ROUTE) is set in the
91 * default PRL when using Anonymize, so it is changed to other option
92 * that is not set by default, to check that it was set successfully.
93 * Options not set by default (using or not anonymize) are option 17
94 * (SD_DHCP_OPTION_ROOT_PATH) and 42 (SD_DHCP_OPTION_NTP_SERVER) */
95 assert_se(sd_dhcp_client_set_request_option(client, 17) == 1);
96 assert_se(sd_dhcp_client_set_request_option(client, 17) == 0);
97 assert_se(sd_dhcp_client_set_request_option(client, 42) == 1);
98 assert_se(sd_dhcp_client_set_request_option(client, 17) == 0);
99
100 sd_dhcp_client_unref(client);
101 }
102
103 static void test_request_anonymize(sd_event *e) {
104 int r;
105
106 sd_dhcp_client *client;
107
108 if (verbose)
109 printf("* %s\n", __func__);
110
111 /* Initialize client with Anonymize settings. */
112 r = sd_dhcp_client_new(&client, true);
113
114 assert_se(r >= 0);
115 assert_se(client);
116
117 r = sd_dhcp_client_attach_event(client, e, 0);
118 assert_se(r >= 0);
119
120 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_NETBIOS_NAME_SERVER) == 0);
121 /* This PRL option is not set when using Anonymize */
122 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_HOST_NAME) == 1);
123 assert_se(sd_dhcp_client_set_request_option(client, SD_DHCP_OPTION_PARAMETER_REQUEST_LIST) == -EINVAL);
124
125 /* RFC7844: option 101 (SD_DHCP_OPTION_NEW_TZDB_TIMEZONE) is not set in the
126 * default PRL when using Anonymize, */
127 assert_se(sd_dhcp_client_set_request_option(client, 101) == 1);
128 assert_se(sd_dhcp_client_set_request_option(client, 101) == 0);
129
130 sd_dhcp_client_unref(client);
131 }
132
133 static void test_checksum(void) {
134 uint8_t buf[20] = {
135 0x45, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,
136 0x40, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
137 0xff, 0xff, 0xff, 0xff
138 };
139
140 if (verbose)
141 printf("* %s\n", __func__);
142
143 assert_se(dhcp_packet_checksum((uint8_t*)&buf, 20) == be16toh(0x78ae));
144 }
145
146 static void test_dhcp_identifier_set_iaid(void) {
147 uint32_t iaid_legacy;
148 be32_t iaid;
149
150 assert_se(dhcp_identifier_set_iaid(NULL, &hw_addr, /* legacy = */ true, &iaid_legacy) >= 0);
151 assert_se(dhcp_identifier_set_iaid(NULL, &hw_addr, /* legacy = */ false, &iaid) >= 0);
152
153 /* we expect, that the MAC address was hashed. The legacy value is in native
154 * endianness. */
155 assert_se(iaid_legacy == 0x8dde4ba8u);
156 assert_se(iaid == htole32(0x8dde4ba8u));
157 #if __BYTE_ORDER == __LITTLE_ENDIAN
158 assert_se(iaid == iaid_legacy);
159 #else
160 assert_se(iaid == bswap_32(iaid_legacy));
161 #endif
162 }
163
164 static int check_options(uint8_t code, uint8_t len, const void *option, void *userdata) {
165 switch (code) {
166 case SD_DHCP_OPTION_CLIENT_IDENTIFIER:
167 {
168 sd_dhcp_duid duid;
169 uint32_t iaid;
170
171 assert_se(sd_dhcp_duid_set_en(&duid) >= 0);
172 assert_se(dhcp_identifier_set_iaid(NULL, &hw_addr, /* legacy = */ true, &iaid) >= 0);
173
174 assert_se(len == sizeof(uint8_t) + sizeof(uint32_t) + duid.size);
175 assert_se(len == 19);
176 assert_se(((uint8_t*) option)[0] == 0xff);
177
178 assert_se(memcmp((uint8_t*) option + 1, &iaid, sizeof(iaid)) == 0);
179 assert_se(memcmp((uint8_t*) option + 5, &duid.duid, duid.size) == 0);
180 break;
181 }
182
183 default:
184 break;
185 }
186
187 return 0;
188 }
189
190 int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link, const void *packet, size_t len) {
191 size_t size;
192 _cleanup_free_ DHCPPacket *discover = NULL;
193 uint16_t ip_check, udp_check;
194
195 assert_se(s >= 0);
196 assert_se(packet);
197
198 size = sizeof(DHCPPacket);
199 assert_se(len > size);
200
201 discover = memdup(packet, len);
202
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));
209
210 ip_check = discover->ip.check;
211
212 discover->ip.ttl = 0;
213 discover->ip.check = discover->udp.len;
214
215 udp_check = ~dhcp_packet_checksum((uint8_t*)&discover->ip.ttl, len - 8);
216 assert_se(udp_check == 0xffff);
217
218 discover->ip.ttl = IPDEFTTL;
219 discover->ip.check = ip_check;
220
221 ip_check = ~dhcp_packet_checksum((uint8_t*)&discover->ip, sizeof(discover->ip));
222 assert_se(ip_check == 0xffff);
223
224 assert_se(discover->dhcp.xid);
225 assert_se(memcmp(discover->dhcp.chaddr, hw_addr.bytes, hw_addr.length) == 0);
226
227 size = len - sizeof(struct iphdr) - sizeof(struct udphdr);
228
229 assert_se(callback_recv);
230 callback_recv(size, &discover->dhcp);
231
232 return 575;
233 }
234
235 int dhcp_network_bind_raw_socket(
236 int ifindex,
237 union sockaddr_union *link,
238 uint32_t id,
239 const struct hw_addr_data *_hw_addr,
240 const struct hw_addr_data *_bcast_addr,
241 uint16_t arp_type,
242 uint16_t port,
243 bool so_priority_set,
244 int so_priority) {
245
246 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, test_fd) < 0)
247 return -errno;
248
249 return test_fd[0];
250 }
251
252 int dhcp_network_bind_udp_socket(int ifindex, be32_t address, uint16_t port, int ip_service_type) {
253 int fd;
254
255 fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
256 if (fd < 0)
257 return -errno;
258
259 return fd;
260 }
261
262 int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port, const void *packet, size_t len) {
263 return 0;
264 }
265
266 static int test_discover_message_verify(size_t size, struct DHCPMessage *dhcp) {
267 int res;
268
269 res = dhcp_option_parse(dhcp, size, check_options, NULL, NULL);
270 assert_se(res == DHCP_DISCOVER);
271
272 if (verbose)
273 printf(" recv DHCP Discover 0x%08x\n", be32toh(dhcp->xid));
274
275 return 0;
276 }
277
278 static void test_discover_message(sd_event *e) {
279 sd_dhcp_client *client;
280 int res, r;
281
282 if (verbose)
283 printf("* %s\n", __func__);
284
285 r = sd_dhcp_client_new(&client, false);
286 assert_se(r >= 0);
287 assert_se(client);
288
289 r = sd_dhcp_client_attach_event(client, e, 0);
290 assert_se(r >= 0);
291
292 assert_se(sd_dhcp_client_set_ifindex(client, 42) >= 0);
293 assert_se(sd_dhcp_client_set_mac(client, hw_addr.bytes, bcast_addr.bytes, hw_addr.length, ARPHRD_ETHER) >= 0);
294
295 assert_se(sd_dhcp_client_set_request_option(client, 248) >= 0);
296
297 callback_recv = test_discover_message_verify;
298
299 res = sd_dhcp_client_start(client);
300
301 assert_se(IN_SET(res, 0, -EINPROGRESS));
302
303 sd_event_run(e, UINT64_MAX);
304
305 sd_dhcp_client_stop(client);
306 sd_dhcp_client_unref(client);
307
308 test_fd[1] = safe_close(test_fd[1]);
309
310 callback_recv = NULL;
311 }
312
313 static 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
357 static 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,
393 0x00, 0x02, 0x58, 0x01, 0x04, 0xff, 0xff, 0xff,
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
401 static int test_addr_acq_acquired(sd_dhcp_client *client, int event,
402 void *userdata) {
403 sd_event *e = userdata;
404 sd_dhcp_lease *lease;
405 struct in_addr addr;
406 const struct in_addr *addrs;
407
408 assert_se(client);
409 assert_se(IN_SET(event, SD_DHCP_CLIENT_EVENT_IP_ACQUIRE, SD_DHCP_CLIENT_EVENT_SELECTING));
410
411 assert_se(sd_dhcp_client_get_lease(client, &lease) >= 0);
412 assert_se(lease);
413
414 assert_se(sd_dhcp_lease_get_address(lease, &addr) >= 0);
415 assert_se(memcmp(&addr.s_addr, &test_addr_acq_ack[44],
416 sizeof(addr.s_addr)) == 0);
417
418 assert_se(sd_dhcp_lease_get_netmask(lease, &addr) >= 0);
419 assert_se(memcmp(&addr.s_addr, &test_addr_acq_ack[285],
420 sizeof(addr.s_addr)) == 0);
421
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);
425
426 if (verbose)
427 printf(" DHCP address acquired\n");
428
429 sd_event_exit(e, 0);
430
431 return 0;
432 }
433
434 static int test_addr_acq_recv_request(size_t size, DHCPMessage *request) {
435 uint16_t udp_check = 0;
436 uint8_t *msg_bytes = (uint8_t *)request;
437 int res;
438
439 res = dhcp_option_parse(request, size, check_options, NULL, NULL);
440 assert_se(res == DHCP_REQUEST);
441 assert_se(xid == request->xid);
442
443 assert_se(msg_bytes[size - 1] == SD_DHCP_OPTION_END);
444
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));
450 memcpy(&test_addr_acq_ack[56], hw_addr.bytes, hw_addr.length);
451
452 callback_recv = NULL;
453
454 res = write(test_fd[1], test_addr_acq_ack,
455 sizeof(test_addr_acq_ack));
456 assert_se(res == sizeof(test_addr_acq_ack));
457
458 if (verbose)
459 printf(" send DHCP Ack\n");
460
461 return 0;
462 };
463
464 static int test_addr_acq_recv_discover(size_t size, DHCPMessage *discover) {
465 uint16_t udp_check = 0;
466 uint8_t *msg_bytes = (uint8_t *)discover;
467 int res;
468
469 res = dhcp_option_parse(discover, size, check_options, NULL, NULL);
470 assert_se(res == DHCP_DISCOVER);
471
472 assert_se(msg_bytes[size - 1] == SD_DHCP_OPTION_END);
473
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));
481 memcpy(&test_addr_acq_offer[56], hw_addr.bytes, hw_addr.length);
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));
487 assert_se(res == sizeof(test_addr_acq_offer));
488
489 if (verbose)
490 printf(" sent DHCP Offer\n");
491
492 return 0;
493 }
494
495 static void test_addr_acq(sd_event *e) {
496 sd_dhcp_client *client;
497 int res, r;
498
499 if (verbose)
500 printf("* %s\n", __func__);
501
502 r = sd_dhcp_client_new(&client, false);
503 assert_se(r >= 0);
504 assert_se(client);
505
506 r = sd_dhcp_client_attach_event(client, e, 0);
507 assert_se(r >= 0);
508
509 assert_se(sd_dhcp_client_set_ifindex(client, 42) >= 0);
510 assert_se(sd_dhcp_client_set_mac(client, hw_addr.bytes, bcast_addr.bytes, hw_addr.length, ARPHRD_ETHER) >= 0);
511
512 assert_se(sd_dhcp_client_set_callback(client, test_addr_acq_acquired, e) >= 0);
513
514 callback_recv = test_addr_acq_recv_discover;
515
516 assert_se(sd_event_add_time_relative(e, NULL, CLOCK_BOOTTIME,
517 2 * USEC_PER_SEC, 0,
518 NULL, INT_TO_PTR(-ETIMEDOUT)) >= 0);
519
520 res = sd_dhcp_client_start(client);
521 assert_se(IN_SET(res, 0, -EINPROGRESS));
522
523 assert_se(sd_event_loop(e) >= 0);
524
525 assert_se(sd_dhcp_client_set_callback(client, NULL, NULL) >= 0);
526 assert_se(sd_dhcp_client_stop(client) >= 0);
527 sd_dhcp_client_unref(client);
528
529 test_fd[1] = safe_close(test_fd[1]);
530
531 callback_recv = NULL;
532 xid = 0;
533 }
534
535 int main(int argc, char *argv[]) {
536 _cleanup_(sd_event_unrefp) sd_event *e;
537
538 assert_se(setenv("SYSTEMD_NETWORK_TEST_MODE", "1", 1) >= 0);
539
540 test_setup_logging(LOG_DEBUG);
541
542 assert_se(sd_event_new(&e) >= 0);
543
544 test_request_basic(e);
545 test_request_anonymize(e);
546 test_checksum();
547 test_dhcp_identifier_set_iaid();
548
549 test_discover_message(e);
550 test_addr_acq(e);
551
552 #if HAVE_VALGRIND_VALGRIND_H
553 /* Make sure the async_close thread has finished.
554 * valgrind would report some of the phread_* structures
555 * as not cleaned up properly. */
556 if (RUNNING_ON_VALGRIND)
557 sleep(1);
558 #endif
559
560 return 0;
561 }