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 void 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),
42 /* attach to loopback interface */
43 assert_se(sd_dhcp_server_new(&server, 1) >= 0);
46 assert_se(sd_dhcp_server_attach_event(server, event, 0) >= 0);
47 assert_se(sd_dhcp_server_attach_event(server, event, 0) == -EBUSY);
48 assert_se(sd_dhcp_server_get_event(server) == event);
49 assert_se(sd_dhcp_server_detach_event(server) >= 0);
50 assert_se(!sd_dhcp_server_get_event(server));
51 assert_se(sd_dhcp_server_attach_event(server, NULL, 0) >= 0);
52 assert_se(sd_dhcp_server_attach_event(server, NULL, 0) == -EBUSY);
54 assert_se(sd_dhcp_server_ref(server) == server);
55 assert_se(!sd_dhcp_server_unref(server));
57 assert_se(sd_dhcp_server_start(server) == -EUNATCH);
58 assert_se(sd_dhcp_server_set_address(server, &address_any) == -EINVAL);
59 assert_se(sd_dhcp_server_set_address(server, &address_lo) >= 0);
60 assert_se(sd_dhcp_server_set_address(server, &address_lo) == -EBUSY);
62 assert_se(sd_dhcp_server_set_lease_pool(server, &address_any, 1) == -EINVAL);
63 assert_se(sd_dhcp_server_set_lease_pool(server, &address_lo, 0) == -EINVAL);
64 assert_se(sd_dhcp_server_set_lease_pool(server, &address_lo, 1) >= 0);
65 assert_se(sd_dhcp_server_set_lease_pool(server, &address_lo, 1) == -EBUSY);
67 assert_se(sd_dhcp_server_start(server) >= 0);
68 assert_se(sd_dhcp_server_start(server) == -EBUSY);
69 assert_se(sd_dhcp_server_stop(server) >= 0);
70 assert_se(sd_dhcp_server_stop(server) >= 0);
71 assert_se(sd_dhcp_server_start(server) >= 0);
74 static void test_message_handler(void) {
75 _cleanup_dhcp_server_unref_ sd_dhcp_server *server = NULL;
82 } _packed_ option_type;
87 } _packed_ option_requested_ip;
92 } _packed_ option_server_id;
97 } _packed_ option_client_id;
100 .message.op = BOOTREQUEST,
101 .message.htype = ARPHRD_ETHER,
102 .message.hlen = ETHER_ADDR_LEN,
103 .message.xid = htobe32(0x12345678),
104 .message.chaddr = { 'A', 'B', 'C', 'D', 'E', 'F' },
105 .option_type.code = DHCP_OPTION_MESSAGE_TYPE,
106 .option_type.length = 1,
107 .option_type.type = DHCP_DISCOVER,
108 .end = DHCP_OPTION_END,
110 struct in_addr address_lo = {
111 .s_addr = htonl(INADDR_LOOPBACK),
114 assert_se(sd_dhcp_server_new(&server, 1) >= 0);
115 assert_se(sd_dhcp_server_set_address(server, &address_lo) >= 0);
116 assert_se(sd_dhcp_server_attach_event(server, NULL, 0) >= 0);
117 assert_se(sd_dhcp_server_start(server) >= 0);
119 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
120 assert_se(sd_dhcp_server_set_lease_pool(server, &address_lo, 10) >= 0);
121 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
124 /* TODO, shouldn't this fail? */
125 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
126 test.end = DHCP_OPTION_END;
127 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
129 test.option_type.code = 0;
130 test.option_type.length = 0;
131 test.option_type.type = 0;
132 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
133 test.option_type.code = DHCP_OPTION_MESSAGE_TYPE;
134 test.option_type.length = 1;
135 test.option_type.type = DHCP_DISCOVER;
136 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
139 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
140 test.message.op = BOOTREQUEST;
141 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
143 test.message.htype = 0;
144 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
145 test.message.htype = ARPHRD_ETHER;
146 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
148 test.message.hlen = 0;
149 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
150 test.message.hlen = ETHER_ADDR_LEN;
151 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
153 test.option_type.type = DHCP_REQUEST;
154 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
155 test.option_requested_ip.code = DHCP_OPTION_REQUESTED_IP_ADDRESS;
156 test.option_requested_ip.length = 4;
157 test.option_requested_ip.address = htobe32(0x12345678);
158 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_NAK);
159 test.option_server_id.code = DHCP_OPTION_SERVER_IDENTIFIER;
160 test.option_server_id.length = 4;
161 test.option_server_id.address = htobe32(INADDR_LOOPBACK);
162 test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3);
163 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_ACK);
165 test.option_server_id.address = htobe32(0x12345678);
166 test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3);
167 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
168 test.option_server_id.address = htobe32(INADDR_LOOPBACK);
169 test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 4);
170 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
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_client_id.code = DHCP_OPTION_CLIENT_IDENTIFIER;
175 test.option_client_id.length = 7;
176 test.option_client_id.id[0] = 0x01;
177 test.option_client_id.id[1] = 'A';
178 test.option_client_id.id[2] = 'B';
179 test.option_client_id.id[3] = 'C';
180 test.option_client_id.id[4] = 'D';
181 test.option_client_id.id[5] = 'E';
182 test.option_client_id.id[6] = 'F';
183 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_ACK);
185 test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 30);
186 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
189 static void test_client_id_hash(void) {
195 uint8_t hash_key[HASH_KEY_SIZE] = {
196 '0', '1', '2', '3', '4', '5', '6', '7',
197 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
200 a.data = (uint8_t*)strdup("abcd");
201 b.data = (uint8_t*)strdup("abcd");
203 assert_se(client_id_compare_func(&a, &b) == 0);
204 assert_se(client_id_hash_func(&a, hash_key) == client_id_hash_func(&b, hash_key));
206 assert_se(client_id_compare_func(&a, &b) != 0);
208 assert_se(client_id_compare_func(&a, &b) == 0);
209 assert_se(client_id_hash_func(&a, hash_key) == client_id_hash_func(&b, hash_key));
212 assert_se(client_id_compare_func(&a, &b) != 0);
214 assert_se(client_id_compare_func(&a, &b) == 0);
215 assert_se(client_id_hash_func(&a, hash_key) == client_id_hash_func(&b, hash_key));
218 b.data = (uint8_t*)strdup("abce");
219 assert_se(client_id_compare_func(&a, &b) != 0);
225 int main(int argc, char *argv[]) {
226 _cleanup_event_unref_ sd_event *e;
228 log_set_max_level(LOG_DEBUG);
229 log_parse_environment();
232 assert_se(sd_event_new(&e) >= 0);
235 test_message_handler();
236 test_client_id_hash();