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.
7 Copyright (C) 2014 Tom Gundersen
9 systemd is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published by
11 the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
14 systemd is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Lesser General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include <netinet/if_ether.h>
28 #include "event-util.h"
30 #include "sd-dhcp-server.h"
31 #include "dhcp-server-internal.h"
33 static int test_basic(sd_event *event) {
34 _cleanup_dhcp_server_unref_ sd_dhcp_server *server = NULL;
35 struct in_addr address_lo = {
36 .s_addr = htonl(INADDR_LOOPBACK),
38 struct in_addr address_any = {
39 .s_addr = htonl(INADDR_ANY),
43 /* attach to loopback interface */
44 assert_se(sd_dhcp_server_new(&server, 1) >= 0);
47 assert_se(sd_dhcp_server_attach_event(server, event, 0) >= 0);
48 assert_se(sd_dhcp_server_attach_event(server, event, 0) == -EBUSY);
49 assert_se(sd_dhcp_server_get_event(server) == event);
50 assert_se(sd_dhcp_server_detach_event(server) >= 0);
51 assert_se(!sd_dhcp_server_get_event(server));
52 assert_se(sd_dhcp_server_attach_event(server, NULL, 0) >= 0);
53 assert_se(sd_dhcp_server_attach_event(server, NULL, 0) == -EBUSY);
55 assert_se(sd_dhcp_server_ref(server) == server);
56 assert_se(!sd_dhcp_server_unref(server));
58 assert_se(sd_dhcp_server_start(server) == -EUNATCH);
59 assert_se(sd_dhcp_server_set_address(server, &address_any, 28) == -EINVAL);
60 assert_se(sd_dhcp_server_set_address(server, &address_any, 38) == -ERANGE);
61 assert_se(sd_dhcp_server_set_address(server, &address_lo, 8) >= 0);
62 assert_se(sd_dhcp_server_set_address(server, &address_lo, 8) == -EBUSY);
64 assert_se(sd_dhcp_server_set_lease_pool(server, &address_any, 1) == -EINVAL);
65 assert_se(sd_dhcp_server_set_lease_pool(server, &address_lo, 0) == -EINVAL);
66 assert_se(sd_dhcp_server_set_lease_pool(server, &address_lo, 1) >= 0);
67 assert_se(sd_dhcp_server_set_lease_pool(server, &address_lo, 1) == -EBUSY);
69 r = sd_dhcp_server_start(server);
72 return EXIT_TEST_SKIP;
75 assert_se(sd_dhcp_server_start(server) == -EBUSY);
76 assert_se(sd_dhcp_server_stop(server) >= 0);
77 assert_se(sd_dhcp_server_stop(server) >= 0);
78 assert_se(sd_dhcp_server_start(server) >= 0);
83 static void test_message_handler(void) {
84 _cleanup_dhcp_server_unref_ sd_dhcp_server *server = NULL;
91 } _packed_ option_type;
96 } _packed_ option_requested_ip;
101 } _packed_ option_server_id;
106 } _packed_ option_client_id;
109 .message.op = BOOTREQUEST,
110 .message.htype = ARPHRD_ETHER,
111 .message.hlen = ETHER_ADDR_LEN,
112 .message.xid = htobe32(0x12345678),
113 .message.chaddr = { 'A', 'B', 'C', 'D', 'E', 'F' },
114 .option_type.code = DHCP_OPTION_MESSAGE_TYPE,
115 .option_type.length = 1,
116 .option_type.type = DHCP_DISCOVER,
117 .end = DHCP_OPTION_END,
119 struct in_addr address_lo = {
120 .s_addr = htonl(INADDR_LOOPBACK),
123 assert_se(sd_dhcp_server_new(&server, 1) >= 0);
124 assert_se(sd_dhcp_server_set_address(server, &address_lo, 8) >= 0);
125 assert_se(sd_dhcp_server_attach_event(server, NULL, 0) >= 0);
126 assert_se(sd_dhcp_server_start(server) >= 0);
128 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
129 assert_se(sd_dhcp_server_set_lease_pool(server, &address_lo, 10) >= 0);
130 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
133 /* TODO, shouldn't this fail? */
134 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
135 test.end = DHCP_OPTION_END;
136 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
138 test.option_type.code = 0;
139 test.option_type.length = 0;
140 test.option_type.type = 0;
141 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
142 test.option_type.code = DHCP_OPTION_MESSAGE_TYPE;
143 test.option_type.length = 1;
144 test.option_type.type = DHCP_DISCOVER;
145 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
148 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
149 test.message.op = BOOTREQUEST;
150 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
152 test.message.htype = 0;
153 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
154 test.message.htype = ARPHRD_ETHER;
155 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
157 test.message.hlen = 0;
158 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
159 test.message.hlen = ETHER_ADDR_LEN;
160 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
162 test.option_type.type = DHCP_REQUEST;
163 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
164 test.option_requested_ip.code = DHCP_OPTION_REQUESTED_IP_ADDRESS;
165 test.option_requested_ip.length = 4;
166 test.option_requested_ip.address = htobe32(0x12345678);
167 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_NAK);
168 test.option_server_id.code = DHCP_OPTION_SERVER_IDENTIFIER;
169 test.option_server_id.length = 4;
170 test.option_server_id.address = htobe32(INADDR_LOOPBACK);
171 test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3);
172 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_ACK);
174 test.option_server_id.address = htobe32(0x12345678);
175 test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3);
176 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
177 test.option_server_id.address = htobe32(INADDR_LOOPBACK);
178 test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 4);
179 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
180 test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3);
181 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_ACK);
183 test.option_client_id.code = DHCP_OPTION_CLIENT_IDENTIFIER;
184 test.option_client_id.length = 7;
185 test.option_client_id.id[0] = 0x01;
186 test.option_client_id.id[1] = 'A';
187 test.option_client_id.id[2] = 'B';
188 test.option_client_id.id[3] = 'C';
189 test.option_client_id.id[4] = 'D';
190 test.option_client_id.id[5] = 'E';
191 test.option_client_id.id[6] = 'F';
192 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_ACK);
194 test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 30);
195 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
198 static void test_client_id_hash(void) {
204 uint8_t hash_key[HASH_KEY_SIZE] = {
205 '0', '1', '2', '3', '4', '5', '6', '7',
206 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
209 a.data = (uint8_t*)strdup("abcd");
210 b.data = (uint8_t*)strdup("abcd");
212 assert_se(client_id_compare_func(&a, &b) == 0);
213 assert_se(client_id_hash_func(&a, hash_key) == client_id_hash_func(&b, hash_key));
215 assert_se(client_id_compare_func(&a, &b) != 0);
217 assert_se(client_id_compare_func(&a, &b) == 0);
218 assert_se(client_id_hash_func(&a, hash_key) == client_id_hash_func(&b, hash_key));
221 assert_se(client_id_compare_func(&a, &b) != 0);
223 assert_se(client_id_compare_func(&a, &b) == 0);
224 assert_se(client_id_hash_func(&a, hash_key) == client_id_hash_func(&b, hash_key));
227 b.data = (uint8_t*)strdup("abce");
228 assert_se(client_id_compare_func(&a, &b) != 0);
234 int main(int argc, char *argv[]) {
235 _cleanup_event_unref_ sd_event *e;
238 log_set_max_level(LOG_DEBUG);
239 log_parse_environment();
242 assert_se(sd_event_new(&e) >= 0);
248 test_message_handler();
249 test_client_id_hash();