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)
47 sd_dhcp_client *client;
49 r = sd_dhcp_client_new(&client);
54 r = sd_dhcp_client_attach_event(client, e, 0);
57 assert(sd_dhcp_client_set_request_option(NULL, 0) == -EINVAL);
58 assert(sd_dhcp_client_set_request_address(NULL, NULL) == -EINVAL);
59 assert(sd_dhcp_client_set_index(NULL, 0) == -EINVAL);
61 assert(sd_dhcp_client_set_index(client, 15) == 0);
62 assert(sd_dhcp_client_set_index(client, -42) == -EINVAL);
63 assert(sd_dhcp_client_set_index(client, -1) == 0);
65 assert(sd_dhcp_client_set_request_option(client,
66 DHCP_OPTION_SUBNET_MASK) == -EEXIST);
67 assert(sd_dhcp_client_set_request_option(client,
68 DHCP_OPTION_ROUTER) == -EEXIST);
69 assert(sd_dhcp_client_set_request_option(client,
70 DHCP_OPTION_HOST_NAME) == -EEXIST);
71 assert(sd_dhcp_client_set_request_option(client,
72 DHCP_OPTION_DOMAIN_NAME) == -EEXIST);
73 assert(sd_dhcp_client_set_request_option(client,
74 DHCP_OPTION_DOMAIN_NAME_SERVER)
76 assert(sd_dhcp_client_set_request_option(client,
77 DHCP_OPTION_NTP_SERVER) == -EEXIST);
79 assert(sd_dhcp_client_set_request_option(client,
80 DHCP_OPTION_PAD) == -EINVAL);
81 assert(sd_dhcp_client_set_request_option(client,
82 DHCP_OPTION_END) == -EINVAL);
83 assert(sd_dhcp_client_set_request_option(client,
84 DHCP_OPTION_MESSAGE_TYPE) == -EINVAL);
85 assert(sd_dhcp_client_set_request_option(client,
86 DHCP_OPTION_OVERLOAD) == -EINVAL);
87 assert(sd_dhcp_client_set_request_option(client,
88 DHCP_OPTION_PARAMETER_REQUEST_LIST)
91 assert(sd_dhcp_client_set_request_option(client, 33) == 0);
92 assert(sd_dhcp_client_set_request_option(client, 33) == -EEXIST);
93 assert(sd_dhcp_client_set_request_option(client, 44) == 0);
94 assert(sd_dhcp_client_set_request_option(client, 33) == -EEXIST);
97 static uint16_t client_checksum(void *buf, int len)
107 for (i = 0; i < len / 2 ; i++)
116 sum = (sum & 0xffff) + (sum >> 16);
121 static void test_checksum(void)
124 0x45, 0x00, 0x02, 0x40, 0x00, 0x00, 0x00, 0x00,
125 0x40, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
126 0xff, 0xff, 0xff, 0xff
129 assert(client_checksum(&buf, 20) == be16toh(0x78ae));
132 static int check_options(uint8_t code, uint8_t len, const uint8_t *option,
138 int dhcp_network_send_raw_socket(int s, const union sockaddr_union *link,
139 const void *packet, size_t len)
142 _cleanup_free_ DHCPPacket *discover;
143 uint16_t ip_check, udp_check;
149 size = sizeof(DHCPPacket) + 4;
152 discover = memdup(packet, len);
154 assert(memcmp(discover->dhcp.chaddr,
155 &mac_addr.ether_addr_octet, 6) == 0);
156 assert(discover->ip.ttl == IPDEFTTL);
157 assert(discover->ip.protocol == IPPROTO_UDP);
158 assert(discover->ip.saddr == INADDR_ANY);
159 assert(discover->ip.daddr == INADDR_BROADCAST);
160 assert(discover->udp.source == be16toh(DHCP_PORT_CLIENT));
161 assert(discover->udp.dest == be16toh(DHCP_PORT_SERVER));
163 ip_check = discover->ip.check;
165 discover->ip.ttl = 0;
166 discover->ip.check = discover->udp.len;
168 udp_check = ~client_checksum(&discover->ip.ttl, len - 8);
169 assert(udp_check == 0xffff);
171 discover->ip.ttl = IPDEFTTL;
172 discover->ip.check = ip_check;
174 ip_check = ~client_checksum(&discover->ip, sizeof(discover->ip));
175 assert(ip_check == 0xffff);
177 size = len - sizeof(struct iphdr) - sizeof(struct udphdr);
179 res = dhcp_option_parse(&discover->dhcp, size, check_options, NULL);
186 int dhcp_network_bind_raw_socket(int index, union sockaddr_union *link)
188 if (socketpair(AF_UNIX, SOCK_STREAM, 0, test_fd) < 0)
194 int dhcp_network_bind_udp_socket(int index, be32_t client_address)
199 int dhcp_network_send_udp_socket(int s, be32_t server_address,
200 const void *packet, size_t len)
205 static void test_discover_message(sd_event *e)
207 sd_dhcp_client *client;
210 r = sd_dhcp_client_new(&client);
214 r = sd_dhcp_client_attach_event(client, e, 0);
217 assert(sd_dhcp_client_set_index(client, 42) >= 0);
218 assert(sd_dhcp_client_set_mac(client, &mac_addr) >= 0);
220 assert(sd_dhcp_client_set_request_option(client, 248) >= 0);
222 res = sd_dhcp_client_start(client);
224 assert(res == 0 || res == -EINPROGRESS);
230 int main(int argc, char *argv[])
234 assert(sd_event_new(&e) >= 0);
236 test_request_basic(e);
239 test_discover_message(e);
240 sd_event_run(e, (uint64_t) -1);