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++)
108 return ~((sum & 0xffff) + (sum >> 16));
111 static void test_checksum(void)
114 0x45, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,
115 0x40, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116 0xff, 0xff, 0xff, 0xff
123 uint16_t *val = (uint16_t *)check;
125 assert(client_checksum(&buf, 20) == *val);
128 static int check_options(uint8_t code, uint8_t len, const uint8_t *option,
134 int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
135 const void *packet, size_t len)
138 _cleanup_free_ DHCPPacket *discover;
139 uint16_t ip_check, udp_check;
145 size = sizeof(DHCPPacket) + 4;
148 discover = memdup(packet, len);
150 assert(memcmp(discover->dhcp.chaddr,
151 &mac_addr.ether_addr_octet, 6) == 0);
152 assert(discover->ip.ttl == IPDEFTTL);
153 assert(discover->ip.protocol == IPPROTO_UDP);
154 assert(discover->ip.saddr == INADDR_ANY);
155 assert(discover->ip.daddr == INADDR_BROADCAST);
156 assert(discover->udp.source == be16toh(DHCP_PORT_CLIENT));
157 assert(discover->udp.dest == be16toh(DHCP_PORT_SERVER));
159 ip_check = discover->ip.check;
161 discover->ip.ttl = 0;
162 discover->ip.check = discover->udp.len;
164 udp_check = ~client_checksum(&discover->ip.ttl, len - 8);
165 assert(udp_check == 0xffff);
167 discover->ip.ttl = IPDEFTTL;
168 discover->ip.check = ip_check;
170 ip_check = ~client_checksum(&discover->ip, sizeof(discover->ip));
171 assert(ip_check == 0xffff);
173 size = len - sizeof(struct iphdr) - sizeof(struct udphdr);
175 res = dhcp_option_parse(&discover->dhcp, size, check_options, NULL);
182 int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link)
184 if (socketpair(AF_UNIX, SOCK_STREAM, 0, test_fd) < 0)
190 static void test_discover_message(sd_event *e)
192 sd_dhcp_client *client;
195 client = sd_dhcp_client_new(e);
198 assert(sd_dhcp_client_set_index(client, 42) >= 0);
199 assert(sd_dhcp_client_set_mac(client, &mac_addr) >= 0);
201 assert(sd_dhcp_client_set_request_option(client, 248) >= 0);
203 res = sd_dhcp_client_start(client);
205 assert(res == 0 || res == -EINPROGRESS);
211 int main(int argc, char *argv[])
215 assert(sd_event_new(&e) >= 0);
217 test_request_basic(e);
220 test_discover_message(e);
221 sd_event_run(e, (uint64_t) -1);