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 int test_fd[2];
43 static void test_request_basic(sd_event *e)
45 sd_dhcp_client *client;
47 client = sd_dhcp_client_new(e);
51 assert(sd_dhcp_client_set_request_option(NULL, 0) == -EINVAL);
52 assert(sd_dhcp_client_set_request_address(NULL, NULL) == -EINVAL);
53 assert(sd_dhcp_client_set_index(NULL, 0) == -EINVAL);
55 assert(sd_dhcp_client_set_index(client, 15) == 0);
56 assert(sd_dhcp_client_set_index(client, -42) == -EINVAL);
57 assert(sd_dhcp_client_set_index(client, -1) == 0);
59 assert(sd_dhcp_client_set_request_option(client,
60 DHCP_OPTION_SUBNET_MASK) == -EEXIST);
61 assert(sd_dhcp_client_set_request_option(client,
62 DHCP_OPTION_ROUTER) == -EEXIST);
63 assert(sd_dhcp_client_set_request_option(client,
64 DHCP_OPTION_HOST_NAME) == -EEXIST);
65 assert(sd_dhcp_client_set_request_option(client,
66 DHCP_OPTION_DOMAIN_NAME) == -EEXIST);
67 assert(sd_dhcp_client_set_request_option(client,
68 DHCP_OPTION_DOMAIN_NAME_SERVER)
70 assert(sd_dhcp_client_set_request_option(client,
71 DHCP_OPTION_NTP_SERVER) == -EEXIST);
73 assert(sd_dhcp_client_set_request_option(client,
74 DHCP_OPTION_PAD) == -EINVAL);
75 assert(sd_dhcp_client_set_request_option(client,
76 DHCP_OPTION_END) == -EINVAL);
77 assert(sd_dhcp_client_set_request_option(client,
78 DHCP_OPTION_MESSAGE_TYPE) == -EINVAL);
79 assert(sd_dhcp_client_set_request_option(client,
80 DHCP_OPTION_OVERLOAD) == -EINVAL);
81 assert(sd_dhcp_client_set_request_option(client,
82 DHCP_OPTION_PARAMETER_REQUEST_LIST)
85 assert(sd_dhcp_client_set_request_option(client, 33) == 0);
86 assert(sd_dhcp_client_set_request_option(client, 33) == -EEXIST);
87 assert(sd_dhcp_client_set_request_option(client, 44) == 0);
90 static uint16_t client_checksum(void *buf, int len)
100 for (i = 0; i < len / 2 ; i++)
109 sum = (sum & 0xffff) + (sum >> 16);
114 static void test_checksum(void)
117 0x45, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,
118 0x40, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
119 0xff, 0xff, 0xff, 0xff
122 assert(client_checksum(&buf, 20) == be16toh(0x78ae));
125 static int check_options(uint8_t code, uint8_t len, const uint8_t *option,
131 int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
132 const void *packet, size_t len)
135 _cleanup_free_ DHCPPacket *discover;
136 uint16_t ip_check, udp_check;
142 size = sizeof(DHCPPacket) + 4;
145 discover = memdup(packet, len);
147 assert(memcmp(discover->dhcp.chaddr,
148 &mac_addr.ether_addr_octet, 6) == 0);
149 assert(discover->ip.ttl == IPDEFTTL);
150 assert(discover->ip.protocol == IPPROTO_UDP);
151 assert(discover->ip.saddr == INADDR_ANY);
152 assert(discover->ip.daddr == INADDR_BROADCAST);
153 assert(discover->udp.source == be16toh(DHCP_PORT_CLIENT));
154 assert(discover->udp.dest == be16toh(DHCP_PORT_SERVER));
156 ip_check = discover->ip.check;
158 discover->ip.ttl = 0;
159 discover->ip.check = discover->udp.len;
161 udp_check = ~client_checksum(&discover->ip.ttl, len - 8);
162 assert(udp_check == 0xffff);
164 discover->ip.ttl = IPDEFTTL;
165 discover->ip.check = ip_check;
167 ip_check = ~client_checksum(&discover->ip, sizeof(discover->ip));
168 assert(ip_check == 0xffff);
170 size = len - sizeof(struct iphdr) - sizeof(struct udphdr);
172 res = dhcp_option_parse(&discover->dhcp, size, check_options, NULL);
179 int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link)
181 if (socketpair(AF_UNIX, SOCK_STREAM, 0, test_fd) < 0)
187 int dhcp_network_bind_udp_socket(int index, be32_t client_address)
192 int dhcp_network_send_udp_socket(int s, be32_t server_address,
193 const void *packet, size_t len)
198 static void test_discover_message(sd_event *e)
200 sd_dhcp_client *client;
203 client = sd_dhcp_client_new(e);
206 assert(sd_dhcp_client_set_index(client, 42) >= 0);
207 assert(sd_dhcp_client_set_mac(client, &mac_addr) >= 0);
209 assert(sd_dhcp_client_set_request_option(client, 248) >= 0);
211 res = sd_dhcp_client_start(client);
213 assert(res == 0 || res == -EINPROGRESS);
219 int main(int argc, char *argv[])
223 assert(sd_event_new(&e) >= 0);
225 test_request_basic(e);
228 test_discover_message(e);
229 sd_event_run(e, (uint64_t) -1);