1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright (C) 2013 Intel Corporation. All rights reserved.
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
26 #include <sys/types.h>
27 #include <sys/socket.h>
31 #include "socket-util.h"
33 #include "dhcp-protocol.h"
34 #include "dhcp-internal.h"
35 #include "sd-dhcp-client.h"
37 static struct ether_addr mac_addr = {
38 .ether_addr_octet = {'A', 'B', 'C', '1', '2', '3'}
41 typedef int (*test_callback_recv_t)(size_t size, DHCPMessage *dhcp);
43 static bool verbose = false;
44 static int test_fd[2];
45 static test_callback_recv_t callback_recv;
48 static void test_request_basic(sd_event *e)
52 sd_dhcp_client *client;
55 printf("* %s\n", __FUNCTION__);
57 r = sd_dhcp_client_new(&client);
62 r = sd_dhcp_client_attach_event(client, e, 0);
65 assert_se(sd_dhcp_client_set_request_option(NULL, 0) == -EINVAL);
66 assert_se(sd_dhcp_client_set_request_address(NULL, NULL) == -EINVAL);
67 assert_se(sd_dhcp_client_set_index(NULL, 0) == -EINVAL);
69 assert_se(sd_dhcp_client_set_index(client, 15) == 0);
70 assert_se(sd_dhcp_client_set_index(client, -42) == -EINVAL);
71 assert_se(sd_dhcp_client_set_index(client, -1) == 0);
73 assert_se(sd_dhcp_client_set_request_option(client,
74 DHCP_OPTION_SUBNET_MASK) == -EEXIST);
75 assert_se(sd_dhcp_client_set_request_option(client,
76 DHCP_OPTION_ROUTER) == -EEXIST);
77 assert_se(sd_dhcp_client_set_request_option(client,
78 DHCP_OPTION_HOST_NAME) == -EEXIST);
79 assert_se(sd_dhcp_client_set_request_option(client,
80 DHCP_OPTION_DOMAIN_NAME) == -EEXIST);
81 assert_se(sd_dhcp_client_set_request_option(client,
82 DHCP_OPTION_DOMAIN_NAME_SERVER)
84 assert_se(sd_dhcp_client_set_request_option(client,
85 DHCP_OPTION_NTP_SERVER) == -EEXIST);
87 assert_se(sd_dhcp_client_set_request_option(client,
88 DHCP_OPTION_PAD) == -EINVAL);
89 assert_se(sd_dhcp_client_set_request_option(client,
90 DHCP_OPTION_END) == -EINVAL);
91 assert_se(sd_dhcp_client_set_request_option(client,
92 DHCP_OPTION_MESSAGE_TYPE) == -EINVAL);
93 assert_se(sd_dhcp_client_set_request_option(client,
94 DHCP_OPTION_OVERLOAD) == -EINVAL);
95 assert_se(sd_dhcp_client_set_request_option(client,
96 DHCP_OPTION_PARAMETER_REQUEST_LIST)
99 assert_se(sd_dhcp_client_set_request_option(client, 33) == 0);
100 assert_se(sd_dhcp_client_set_request_option(client, 33) == -EEXIST);
101 assert_se(sd_dhcp_client_set_request_option(client, 44) == 0);
102 assert_se(sd_dhcp_client_set_request_option(client, 33) == -EEXIST);
105 static void test_checksum(void)
108 0x45, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,
109 0x40, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
110 0xff, 0xff, 0xff, 0xff
114 printf("* %s\n", __FUNCTION__);
116 assert_se(dhcp_packet_checksum(&buf, 20) == be16toh(0x78ae));
119 static int check_options(uint8_t code, uint8_t len, const uint8_t *option,
125 int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
126 const void *packet, size_t len)
129 _cleanup_free_ DHCPPacket *discover;
130 uint16_t ip_check, udp_check;
135 size = sizeof(DHCPPacket) + 4;
136 assert_se(len > size);
138 discover = memdup(packet, len);
140 assert_se(discover->ip.ttl == IPDEFTTL);
141 assert_se(discover->ip.protocol == IPPROTO_UDP);
142 assert_se(discover->ip.saddr == INADDR_ANY);
143 assert_se(discover->ip.daddr == INADDR_BROADCAST);
144 assert_se(discover->udp.source == be16toh(DHCP_PORT_CLIENT));
145 assert_se(discover->udp.dest == be16toh(DHCP_PORT_SERVER));
147 ip_check = discover->ip.check;
149 discover->ip.ttl = 0;
150 discover->ip.check = discover->udp.len;
152 udp_check = ~dhcp_packet_checksum(&discover->ip.ttl, len - 8);
153 assert_se(udp_check == 0xffff);
155 discover->ip.ttl = IPDEFTTL;
156 discover->ip.check = ip_check;
158 ip_check = ~dhcp_packet_checksum(&discover->ip, sizeof(discover->ip));
159 assert_se(ip_check == 0xffff);
161 assert_se(discover->dhcp.xid);
162 assert_se(memcmp(discover->dhcp.chaddr,
163 &mac_addr.ether_addr_octet, 6) == 0);
165 size = len - sizeof(struct iphdr) - sizeof(struct udphdr);
167 assert_se(callback_recv);
168 callback_recv(size, &discover->dhcp);
173 int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link)
175 if (socketpair(AF_UNIX, SOCK_STREAM, 0, test_fd) < 0)
181 int dhcp_network_bind_udp_socket(int index, be32_t address, uint16_t port)
186 int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port,
187 const void *packet, size_t len)
192 static int test_discover_message_verify(size_t size, struct DHCPMessage *dhcp)
196 res = dhcp_option_parse(dhcp, size, check_options, NULL);
197 assert_se(res == DHCP_DISCOVER);
200 printf(" recv DHCP Discover 0x%08x\n", be32toh(dhcp->xid));
205 static void test_discover_message(sd_event *e)
207 sd_dhcp_client *client;
211 printf("* %s\n", __FUNCTION__);
213 r = sd_dhcp_client_new(&client);
217 r = sd_dhcp_client_attach_event(client, e, 0);
220 assert_se(sd_dhcp_client_set_index(client, 42) >= 0);
221 assert_se(sd_dhcp_client_set_mac(client, &mac_addr) >= 0);
223 assert_se(sd_dhcp_client_set_request_option(client, 248) >= 0);
225 callback_recv = test_discover_message_verify;
227 res = sd_dhcp_client_start(client);
229 assert_se(res == 0 || res == -EINPROGRESS);
231 sd_event_run(e, (uint64_t) -1);
233 sd_dhcp_client_stop(client);
234 sd_dhcp_client_free(client);
239 callback_recv = NULL;
242 static uint8_t test_addr_acq_offer[] = {
243 0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00,
244 0x80, 0x11, 0xb3, 0x84, 0xc0, 0xa8, 0x02, 0x01,
245 0xc0, 0xa8, 0x02, 0xbf, 0x00, 0x43, 0x00, 0x44,
246 0x01, 0x34, 0x00, 0x00, 0x02, 0x01, 0x06, 0x00,
247 0x6f, 0x95, 0x2f, 0x30, 0x00, 0x00, 0x00, 0x00,
248 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x02, 0xbf,
249 0xc0, 0xa8, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00,
250 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
251 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
252 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
253 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
254 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
255 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
256 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
257 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
258 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
259 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
260 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
261 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
262 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
263 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
264 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
265 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
266 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
267 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
268 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
269 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
270 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
271 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
272 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
273 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
274 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
275 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
276 0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x02, 0x36,
277 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x33, 0x04, 0x00,
278 0x00, 0x02, 0x58, 0x01, 0x04, 0xff, 0xff, 0xff,
279 0x00, 0x2a, 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x0f,
280 0x09, 0x6c, 0x61, 0x62, 0x2e, 0x69, 0x6e, 0x74,
281 0x72, 0x61, 0x03, 0x04, 0xc0, 0xa8, 0x02, 0x01,
282 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
283 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
286 static uint8_t test_addr_acq_ack[] = {
287 0x45, 0x10, 0x01, 0x48, 0x00, 0x00, 0x00, 0x00,
288 0x80, 0x11, 0xb3, 0x84, 0xc0, 0xa8, 0x02, 0x01,
289 0xc0, 0xa8, 0x02, 0xbf, 0x00, 0x43, 0x00, 0x44,
290 0x01, 0x34, 0x00, 0x00, 0x02, 0x01, 0x06, 0x00,
291 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
292 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x02, 0xbf,
293 0xc0, 0xa8, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00,
294 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
295 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
296 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
297 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
298 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
299 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
300 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
301 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
302 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
303 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
304 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
305 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
306 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
307 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
308 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
309 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
310 0x00, 0x00, 0x00, 0x00, 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 0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x05, 0x36,
321 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x33, 0x04, 0x00,
322 0x00, 0x02, 0x58, 0x01, 0x04, 0xff, 0xff, 0xff,
323 0x00, 0x2a, 0x04, 0xc0, 0xa8, 0x02, 0x01, 0x0f,
324 0x09, 0x6c, 0x61, 0x62, 0x2e, 0x69, 0x6e, 0x74,
325 0x72, 0x61, 0x03, 0x04, 0xc0, 0xa8, 0x02, 0x01,
326 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
327 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
330 static void test_addr_acq_acquired(sd_dhcp_client *client, int event,
333 sd_event *e = userdata;
334 sd_dhcp_lease *lease;
338 assert_se(event == DHCP_EVENT_IP_ACQUIRE);
340 assert_se(sd_dhcp_client_get_lease(client, &lease) >= 0);
343 assert_se(sd_dhcp_lease_get_address(lease, &addr) >= 0);
344 assert_se(memcmp(&addr.s_addr, &test_addr_acq_ack[44],
345 sizeof(addr.s_addr)) == 0);
347 assert_se(sd_dhcp_lease_get_netmask(lease, &addr) >= 0);
348 assert_se(memcmp(&addr.s_addr, &test_addr_acq_ack[285],
349 sizeof(addr.s_addr)) == 0);
351 assert_se(sd_dhcp_lease_get_router(lease, &addr) >= 0);
352 assert_se(memcmp(&addr.s_addr, &test_addr_acq_ack[308],
353 sizeof(addr.s_addr)) == 0);
356 printf(" DHCP address acquired\n");
361 static int test_addr_acq_recv_request(size_t size, DHCPMessage *request)
363 uint16_t udp_check = 0;
366 res = dhcp_option_parse(request, size, check_options, NULL);
367 assert_se(res == DHCP_REQUEST);
368 assert_se(xid == request->xid);
371 printf(" recv DHCP Request 0x%08x\n", be32toh(xid));
373 memcpy(&test_addr_acq_ack[26], &udp_check, sizeof(udp_check));
374 memcpy(&test_addr_acq_ack[32], &xid, sizeof(xid));
375 memcpy(&test_addr_acq_ack[56], &mac_addr.ether_addr_octet,
378 callback_recv = NULL;
380 res = write(test_fd[1], test_addr_acq_ack,
381 sizeof(test_addr_acq_ack));
382 assert_se(res == sizeof(test_addr_acq_ack));
385 printf(" send DHCP Ack\n");
390 static int test_addr_acq_recv_discover(size_t size, DHCPMessage *discover)
392 uint16_t udp_check = 0;
395 res = dhcp_option_parse(discover, size, check_options, NULL);
396 assert_se(res == DHCP_DISCOVER);
401 printf(" recv DHCP Discover 0x%08x\n", be32toh(xid));
403 memcpy(&test_addr_acq_offer[26], &udp_check, sizeof(udp_check));
404 memcpy(&test_addr_acq_offer[32], &xid, sizeof(xid));
405 memcpy(&test_addr_acq_offer[56], &mac_addr.ether_addr_octet,
408 callback_recv = test_addr_acq_recv_request;
410 res = write(test_fd[1], test_addr_acq_offer,
411 sizeof(test_addr_acq_offer));
412 assert_se(res == sizeof(test_addr_acq_offer));
415 printf(" send DHCP Offer\n");
420 static void test_addr_acq(sd_event *e)
422 sd_dhcp_client *client;
426 printf("* %s\n", __FUNCTION__);
428 r = sd_dhcp_client_new(&client);
432 r = sd_dhcp_client_attach_event(client, e, 0);
435 assert_se(sd_dhcp_client_set_index(client, 42) >= 0);
436 assert_se(sd_dhcp_client_set_mac(client, &mac_addr) >= 0);
438 assert_se(sd_dhcp_client_set_callback(client, test_addr_acq_acquired, e)
441 callback_recv = test_addr_acq_recv_discover;
443 res = sd_dhcp_client_start(client);
444 assert_se(res == 0 || res == -EINPROGRESS);
448 sd_dhcp_client_set_callback(client, NULL, NULL);
449 sd_dhcp_client_stop(client);
450 sd_dhcp_client_free(client);
455 callback_recv = NULL;
459 int main(int argc, char *argv[])
463 assert_se(sd_event_new(&e) >= 0);
465 test_request_basic(e);
468 test_discover_message(e);