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);
88 assert(sd_dhcp_client_set_request_option(client, 33) == -EEXIST);
91 static uint16_t client_checksum(void *buf, int len)
101 for (i = 0; i < len / 2 ; i++)
110 sum = (sum & 0xffff) + (sum >> 16);
115 static void test_checksum(void)
118 0x45, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,
119 0x40, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
120 0xff, 0xff, 0xff, 0xff
123 assert(client_checksum(&buf, 20) == be16toh(0x78ae));
126 static int check_options(uint8_t code, uint8_t len, const uint8_t *option,
132 int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
133 const void *packet, size_t len)
136 _cleanup_free_ DHCPPacket *discover;
137 uint16_t ip_check, udp_check;
143 size = sizeof(DHCPPacket) + 4;
146 discover = memdup(packet, len);
148 assert(memcmp(discover->dhcp.chaddr,
149 &mac_addr.ether_addr_octet, 6) == 0);
150 assert(discover->ip.ttl == IPDEFTTL);
151 assert(discover->ip.protocol == IPPROTO_UDP);
152 assert(discover->ip.saddr == INADDR_ANY);
153 assert(discover->ip.daddr == INADDR_BROADCAST);
154 assert(discover->udp.source == be16toh(DHCP_PORT_CLIENT));
155 assert(discover->udp.dest == be16toh(DHCP_PORT_SERVER));
157 ip_check = discover->ip.check;
159 discover->ip.ttl = 0;
160 discover->ip.check = discover->udp.len;
162 udp_check = ~client_checksum(&discover->ip.ttl, len - 8);
163 assert(udp_check == 0xffff);
165 discover->ip.ttl = IPDEFTTL;
166 discover->ip.check = ip_check;
168 ip_check = ~client_checksum(&discover->ip, sizeof(discover->ip));
169 assert(ip_check == 0xffff);
171 size = len - sizeof(struct iphdr) - sizeof(struct udphdr);
173 res = dhcp_option_parse(&discover->dhcp, size, check_options, NULL);
180 int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link)
182 if (socketpair(AF_UNIX, SOCK_STREAM, 0, test_fd) < 0)
188 int dhcp_network_bind_udp_socket(int index, be32_t client_address)
193 int dhcp_network_send_udp_socket(int s, be32_t server_address,
194 const void *packet, size_t len)
199 static void test_discover_message(sd_event *e)
201 sd_dhcp_client *client;
204 client = sd_dhcp_client_new(e);
207 assert(sd_dhcp_client_set_index(client, 42) >= 0);
208 assert(sd_dhcp_client_set_mac(client, &mac_addr) >= 0);
210 assert(sd_dhcp_client_set_request_option(client, 248) >= 0);
212 res = sd_dhcp_client_start(client);
214 assert(res == 0 || res == -EINPROGRESS);
220 int main(int argc, char *argv[])
224 assert(sd_event_new(&e) >= 0);
226 test_request_basic(e);
229 test_discover_message(e);
230 sd_event_run(e, (uint64_t) -1);