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 static bool verbose = false;
42 static int test_fd[2];
44 static void test_request_basic(sd_event *e)
48 sd_dhcp_client *client;
51 printf("* %s\n", __FUNCTION__);
53 r = sd_dhcp_client_new(&client);
58 r = sd_dhcp_client_attach_event(client, e, 0);
61 assert(sd_dhcp_client_set_request_option(NULL, 0) == -EINVAL);
62 assert(sd_dhcp_client_set_request_address(NULL, NULL) == -EINVAL);
63 assert(sd_dhcp_client_set_index(NULL, 0) == -EINVAL);
65 assert(sd_dhcp_client_set_index(client, 15) == 0);
66 assert(sd_dhcp_client_set_index(client, -42) == -EINVAL);
67 assert(sd_dhcp_client_set_index(client, -1) == 0);
69 assert(sd_dhcp_client_set_request_option(client,
70 DHCP_OPTION_SUBNET_MASK) == -EEXIST);
71 assert(sd_dhcp_client_set_request_option(client,
72 DHCP_OPTION_ROUTER) == -EEXIST);
73 assert(sd_dhcp_client_set_request_option(client,
74 DHCP_OPTION_HOST_NAME) == -EEXIST);
75 assert(sd_dhcp_client_set_request_option(client,
76 DHCP_OPTION_DOMAIN_NAME) == -EEXIST);
77 assert(sd_dhcp_client_set_request_option(client,
78 DHCP_OPTION_DOMAIN_NAME_SERVER)
80 assert(sd_dhcp_client_set_request_option(client,
81 DHCP_OPTION_NTP_SERVER) == -EEXIST);
83 assert(sd_dhcp_client_set_request_option(client,
84 DHCP_OPTION_PAD) == -EINVAL);
85 assert(sd_dhcp_client_set_request_option(client,
86 DHCP_OPTION_END) == -EINVAL);
87 assert(sd_dhcp_client_set_request_option(client,
88 DHCP_OPTION_MESSAGE_TYPE) == -EINVAL);
89 assert(sd_dhcp_client_set_request_option(client,
90 DHCP_OPTION_OVERLOAD) == -EINVAL);
91 assert(sd_dhcp_client_set_request_option(client,
92 DHCP_OPTION_PARAMETER_REQUEST_LIST)
95 assert(sd_dhcp_client_set_request_option(client, 33) == 0);
96 assert(sd_dhcp_client_set_request_option(client, 33) == -EEXIST);
97 assert(sd_dhcp_client_set_request_option(client, 44) == 0);
98 assert(sd_dhcp_client_set_request_option(client, 33) == -EEXIST);
101 static uint16_t client_checksum(void *buf, int len)
111 for (i = 0; i < len / 2 ; i++)
120 sum = (sum & 0xffff) + (sum >> 16);
125 static void test_checksum(void)
128 0x45, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,
129 0x40, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
130 0xff, 0xff, 0xff, 0xff
134 printf("* %s\n", __FUNCTION__);
136 assert(client_checksum(&buf, 20) == be16toh(0x78ae));
139 static int check_options(uint8_t code, uint8_t len, const uint8_t *option,
145 int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
146 const void *packet, size_t len)
149 _cleanup_free_ DHCPPacket *discover;
150 uint16_t ip_check, udp_check;
156 size = sizeof(DHCPPacket) + 4;
159 discover = memdup(packet, len);
161 assert(memcmp(discover->dhcp.chaddr,
162 &mac_addr.ether_addr_octet, 6) == 0);
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 size = len - sizeof(struct iphdr) - sizeof(struct udphdr);
186 res = dhcp_option_parse(&discover->dhcp, size, check_options, NULL);
193 int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link)
195 if (socketpair(AF_UNIX, SOCK_STREAM, 0, test_fd) < 0)
201 int dhcp_network_bind_udp_socket(int index, be32_t address, uint16_t port)
206 int dhcp_network_send_udp_socket(int s, be32_t address, uint16_t port,
207 const void *packet, size_t len)
212 static void test_discover_message(sd_event *e)
214 sd_dhcp_client *client;
218 printf("* %s\n", __FUNCTION__);
220 r = sd_dhcp_client_new(&client);
224 r = sd_dhcp_client_attach_event(client, e, 0);
227 assert(sd_dhcp_client_set_index(client, 42) >= 0);
228 assert(sd_dhcp_client_set_mac(client, &mac_addr) >= 0);
230 assert(sd_dhcp_client_set_request_option(client, 248) >= 0);
232 res = sd_dhcp_client_start(client);
234 assert(res == 0 || res == -EINPROGRESS);
240 int main(int argc, char *argv[])
244 assert(sd_event_new(&e) >= 0);
246 test_request_basic(e);
249 test_discover_message(e);
250 sd_event_run(e, (uint64_t) -1);