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;
47 static void test_request_basic(sd_event *e)
51 sd_dhcp_client *client;
54 printf("* %s\n", __FUNCTION__);
56 r = sd_dhcp_client_new(&client);
61 r = sd_dhcp_client_attach_event(client, e, 0);
64 assert(sd_dhcp_client_set_request_option(NULL, 0) == -EINVAL);
65 assert(sd_dhcp_client_set_request_address(NULL, NULL) == -EINVAL);
66 assert(sd_dhcp_client_set_index(NULL, 0) == -EINVAL);
68 assert(sd_dhcp_client_set_index(client, 15) == 0);
69 assert(sd_dhcp_client_set_index(client, -42) == -EINVAL);
70 assert(sd_dhcp_client_set_index(client, -1) == 0);
72 assert(sd_dhcp_client_set_request_option(client,
73 DHCP_OPTION_SUBNET_MASK) == -EEXIST);
74 assert(sd_dhcp_client_set_request_option(client,
75 DHCP_OPTION_ROUTER) == -EEXIST);
76 assert(sd_dhcp_client_set_request_option(client,
77 DHCP_OPTION_HOST_NAME) == -EEXIST);
78 assert(sd_dhcp_client_set_request_option(client,
79 DHCP_OPTION_DOMAIN_NAME) == -EEXIST);
80 assert(sd_dhcp_client_set_request_option(client,
81 DHCP_OPTION_DOMAIN_NAME_SERVER)
83 assert(sd_dhcp_client_set_request_option(client,
84 DHCP_OPTION_NTP_SERVER) == -EEXIST);
86 assert(sd_dhcp_client_set_request_option(client,
87 DHCP_OPTION_PAD) == -EINVAL);
88 assert(sd_dhcp_client_set_request_option(client,
89 DHCP_OPTION_END) == -EINVAL);
90 assert(sd_dhcp_client_set_request_option(client,
91 DHCP_OPTION_MESSAGE_TYPE) == -EINVAL);
92 assert(sd_dhcp_client_set_request_option(client,
93 DHCP_OPTION_OVERLOAD) == -EINVAL);
94 assert(sd_dhcp_client_set_request_option(client,
95 DHCP_OPTION_PARAMETER_REQUEST_LIST)
98 assert(sd_dhcp_client_set_request_option(client, 33) == 0);
99 assert(sd_dhcp_client_set_request_option(client, 33) == -EEXIST);
100 assert(sd_dhcp_client_set_request_option(client, 44) == 0);
101 assert(sd_dhcp_client_set_request_option(client, 33) == -EEXIST);
104 static uint16_t client_checksum(void *buf, int len)
114 for (i = 0; i < len / 2 ; i++)
123 sum = (sum & 0xffff) + (sum >> 16);
128 static void test_checksum(void)
131 0x45, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,
132 0x40, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
133 0xff, 0xff, 0xff, 0xff
137 printf("* %s\n", __FUNCTION__);
139 assert(client_checksum(&buf, 20) == be16toh(0x78ae));
142 static int check_options(uint8_t code, uint8_t len, const uint8_t *option,
148 int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
149 const void *packet, size_t len)
152 _cleanup_free_ DHCPPacket *discover;
153 uint16_t ip_check, udp_check;
158 size = sizeof(DHCPPacket) + 4;
161 discover = memdup(packet, len);
163 assert(discover->ip.ttl == IPDEFTTL);
164 assert(discover->ip.protocol == IPPROTO_UDP);
165 assert(discover->ip.saddr == INADDR_ANY);
166 assert(discover->ip.daddr == INADDR_BROADCAST);
167 assert(discover->udp.source == be16toh(DHCP_PORT_CLIENT));
168 assert(discover->udp.dest == be16toh(DHCP_PORT_SERVER));
170 ip_check = discover->ip.check;
172 discover->ip.ttl = 0;
173 discover->ip.check = discover->udp.len;
175 udp_check = ~client_checksum(&discover->ip.ttl, len - 8);
176 assert(udp_check == 0xffff);
178 discover->ip.ttl = IPDEFTTL;
179 discover->ip.check = ip_check;
181 ip_check = ~client_checksum(&discover->ip, sizeof(discover->ip));
182 assert(ip_check == 0xffff);
184 assert(discover->dhcp.xid);
185 assert(memcmp(discover->dhcp.chaddr,
186 &mac_addr.ether_addr_octet, 6) == 0);
188 size = len - sizeof(struct iphdr) - sizeof(struct udphdr);
190 assert(callback_recv);
191 callback_recv(size, &discover->dhcp);
196 int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link)
198 if (socketpair(AF_UNIX, SOCK_STREAM, 0, test_fd) < 0)
204 int dhcp_network_bind_udp_socket(int index, be32_t address, uint16_t port)
209 int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port,
210 const void *packet, size_t len)
215 static int test_discover_message_verify(size_t size, struct DHCPMessage *dhcp)
219 res = dhcp_option_parse(dhcp, size, check_options, NULL);
220 assert(res == DHCP_DISCOVER);
223 printf(" recv DHCP Discover 0x%08x\n", be32toh(dhcp->xid));
228 static void test_discover_message(sd_event *e)
230 sd_dhcp_client *client;
234 printf("* %s\n", __FUNCTION__);
236 r = sd_dhcp_client_new(&client);
240 r = sd_dhcp_client_attach_event(client, e, 0);
243 assert(sd_dhcp_client_set_index(client, 42) >= 0);
244 assert(sd_dhcp_client_set_mac(client, &mac_addr) >= 0);
246 assert(sd_dhcp_client_set_request_option(client, 248) >= 0);
248 callback_recv = test_discover_message_verify;
250 res = sd_dhcp_client_start(client);
252 assert(res == 0 || res == -EINPROGRESS);
254 sd_event_run(e, (uint64_t) -1);
256 sd_dhcp_client_stop(client);
257 sd_dhcp_client_free(client);
262 callback_recv = NULL;
265 int main(int argc, char *argv[])
269 assert(sd_event_new(&e) >= 0);
271 test_request_basic(e);
274 test_discover_message(e);