]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-network/test-dhcp-server.c
dhcp: export routes as opaque objects
[thirdparty/systemd.git] / src / libsystemd-network / test-dhcp-server.c
CommitLineData
b44cd882
TG
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright (C) 2013 Intel Corporation. All rights reserved.
7 Copyright (C) 2014 Tom Gundersen
8
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.
13
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.
18
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/>.
21***/
22
b44cd882
TG
23#include <errno.h>
24
07630cea 25#include "sd-dhcp-server.h"
b44cd882 26#include "sd-event.h"
b44cd882 27
b44cd882
TG
28#include "dhcp-server-internal.h"
29
99634696 30static void test_pool(struct in_addr *address, unsigned size, int ret) {
4afd3348 31 _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
99634696
TG
32
33 assert_se(sd_dhcp_server_new(&server, 1) >= 0);
34
35 assert_se(sd_dhcp_server_configure_pool(server, address, 8, 0, size) == ret);
36}
37
6f08fb7b 38static int test_basic(sd_event *event) {
4afd3348 39 _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
20af7091
TG
40 struct in_addr address_lo = {
41 .s_addr = htonl(INADDR_LOOPBACK),
42 };
43 struct in_addr address_any = {
44 .s_addr = htonl(INADDR_ANY),
45 };
6f08fb7b 46 int r;
b44cd882 47
3a864fe4
TG
48 /* attach to loopback interface */
49 assert_se(sd_dhcp_server_new(&server, 1) >= 0);
b44cd882
TG
50 assert_se(server);
51
52 assert_se(sd_dhcp_server_attach_event(server, event, 0) >= 0);
53 assert_se(sd_dhcp_server_attach_event(server, event, 0) == -EBUSY);
54 assert_se(sd_dhcp_server_get_event(server) == event);
55 assert_se(sd_dhcp_server_detach_event(server) >= 0);
56 assert_se(!sd_dhcp_server_get_event(server));
57 assert_se(sd_dhcp_server_attach_event(server, NULL, 0) >= 0);
58 assert_se(sd_dhcp_server_attach_event(server, NULL, 0) == -EBUSY);
59
60 assert_se(sd_dhcp_server_ref(server) == server);
61 assert_se(!sd_dhcp_server_unref(server));
ff734080 62
20af7091 63 assert_se(sd_dhcp_server_start(server) == -EUNATCH);
20af7091 64
99634696
TG
65 assert_se(sd_dhcp_server_configure_pool(server, &address_any, 28, 0, 0) == -EINVAL);
66 assert_se(sd_dhcp_server_configure_pool(server, &address_lo, 38, 0, 0) == -ERANGE);
67 assert_se(sd_dhcp_server_configure_pool(server, &address_lo, 8, 0, 0) >= 0);
68 assert_se(sd_dhcp_server_configure_pool(server, &address_lo, 8, 0, 0) == -EBUSY);
69
70 test_pool(&address_any, 1, -EINVAL);
71 test_pool(&address_lo, 1, 0);
2dead812 72
6f08fb7b
TG
73 r = sd_dhcp_server_start(server);
74
75 if (r == -EPERM)
76 return EXIT_TEST_SKIP;
77 assert_se(r >= 0);
78
ff734080
TG
79 assert_se(sd_dhcp_server_start(server) == -EBUSY);
80 assert_se(sd_dhcp_server_stop(server) >= 0);
81 assert_se(sd_dhcp_server_stop(server) >= 0);
82 assert_se(sd_dhcp_server_start(server) >= 0);
6f08fb7b
TG
83
84 return 0;
b44cd882
TG
85}
86
be077570 87static void test_message_handler(void) {
4afd3348 88 _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
be077570
TG
89 struct {
90 DHCPMessage message;
91 struct {
92 uint8_t code;
93 uint8_t length;
94 uint8_t type;
95 } _packed_ option_type;
2dead812
TG
96 struct {
97 uint8_t code;
98 uint8_t length;
99 be32_t address;
100 } _packed_ option_requested_ip;
101 struct {
102 uint8_t code;
103 uint8_t length;
104 be32_t address;
105 } _packed_ option_server_id;
87322b3a
TG
106 struct {
107 uint8_t code;
108 uint8_t length;
109 uint8_t id[7];
110 } _packed_ option_client_id;
be077570
TG
111 uint8_t end;
112 } _packed_ test = {
113 .message.op = BOOTREQUEST,
114 .message.htype = ARPHRD_ETHER,
115 .message.hlen = ETHER_ADDR_LEN,
2dead812
TG
116 .message.xid = htobe32(0x12345678),
117 .message.chaddr = { 'A', 'B', 'C', 'D', 'E', 'F' },
be077570
TG
118 .option_type.code = DHCP_OPTION_MESSAGE_TYPE,
119 .option_type.length = 1,
120 .option_type.type = DHCP_DISCOVER,
121 .end = DHCP_OPTION_END,
122 };
20af7091
TG
123 struct in_addr address_lo = {
124 .s_addr = htonl(INADDR_LOOPBACK),
125 };
be077570
TG
126
127 assert_se(sd_dhcp_server_new(&server, 1) >= 0);
99634696 128 assert_se(sd_dhcp_server_configure_pool(server, &address_lo, 8, 0, 0) >= 0);
20af7091
TG
129 assert_se(sd_dhcp_server_attach_event(server, NULL, 0) >= 0);
130 assert_se(sd_dhcp_server_start(server) >= 0);
be077570 131
4dc35568 132 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
be077570
TG
133
134 test.end = 0;
135 /* TODO, shouldn't this fail? */
4dc35568 136 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
be077570 137 test.end = DHCP_OPTION_END;
4dc35568 138 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
be077570
TG
139
140 test.option_type.code = 0;
141 test.option_type.length = 0;
142 test.option_type.type = 0;
143 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
144 test.option_type.code = DHCP_OPTION_MESSAGE_TYPE;
145 test.option_type.length = 1;
146 test.option_type.type = DHCP_DISCOVER;
4dc35568 147 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
be077570
TG
148
149 test.message.op = 0;
150 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
151 test.message.op = BOOTREQUEST;
4dc35568 152 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
be077570
TG
153
154 test.message.htype = 0;
155 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
156 test.message.htype = ARPHRD_ETHER;
4dc35568 157 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
be077570
TG
158
159 test.message.hlen = 0;
160 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
161 test.message.hlen = ETHER_ADDR_LEN;
4dc35568 162 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
2dead812
TG
163
164 test.option_type.type = DHCP_REQUEST;
165 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
166 test.option_requested_ip.code = DHCP_OPTION_REQUESTED_IP_ADDRESS;
167 test.option_requested_ip.length = 4;
168 test.option_requested_ip.address = htobe32(0x12345678);
bd57b450 169 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_NAK);
2dead812
TG
170 test.option_server_id.code = DHCP_OPTION_SERVER_IDENTIFIER;
171 test.option_server_id.length = 4;
172 test.option_server_id.address = htobe32(INADDR_LOOPBACK);
173 test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3);
174 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_ACK);
87322b3a 175
2dead812
TG
176 test.option_server_id.address = htobe32(0x12345678);
177 test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3);
178 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
bd57b450 179 test.option_server_id.address = htobe32(INADDR_LOOPBACK);
87322b3a
TG
180 test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 4);
181 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
182 test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3);
183 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_ACK);
184
185 test.option_client_id.code = DHCP_OPTION_CLIENT_IDENTIFIER;
186 test.option_client_id.length = 7;
187 test.option_client_id.id[0] = 0x01;
188 test.option_client_id.id[1] = 'A';
189 test.option_client_id.id[2] = 'B';
190 test.option_client_id.id[3] = 'C';
191 test.option_client_id.id[4] = 'D';
192 test.option_client_id.id[5] = 'E';
193 test.option_client_id.id[6] = 'F';
194 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_ACK);
195
bd57b450 196 test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 30);
2dead812 197 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
be077570
TG
198}
199
b826ab58
TG
200static uint64_t client_id_hash_helper(DHCPClientId *id, uint8_t key[HASH_KEY_SIZE]) {
201 struct siphash state;
202
0cb3c286 203 siphash24_init(&state, key);
b826ab58 204 client_id_hash_func(id, &state);
0cb3c286 205
933f9cae 206 return htole64(siphash24_finalize(&state));
b826ab58
TG
207}
208
87322b3a
TG
209static void test_client_id_hash(void) {
210 DHCPClientId a = {
211 .length = 4,
212 }, b = {
213 .length = 4,
214 };
215 uint8_t hash_key[HASH_KEY_SIZE] = {
216 '0', '1', '2', '3', '4', '5', '6', '7',
217 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
218 };
219
220 a.data = (uint8_t*)strdup("abcd");
221 b.data = (uint8_t*)strdup("abcd");
222
223 assert_se(client_id_compare_func(&a, &b) == 0);
b826ab58 224 assert_se(client_id_hash_helper(&a, hash_key) == client_id_hash_helper(&b, hash_key));
87322b3a
TG
225 a.length = 3;
226 assert_se(client_id_compare_func(&a, &b) != 0);
227 a.length = 4;
228 assert_se(client_id_compare_func(&a, &b) == 0);
b826ab58 229 assert_se(client_id_hash_helper(&a, hash_key) == client_id_hash_helper(&b, hash_key));
87322b3a
TG
230
231 b.length = 3;
232 assert_se(client_id_compare_func(&a, &b) != 0);
233 b.length = 4;
234 assert_se(client_id_compare_func(&a, &b) == 0);
b826ab58 235 assert_se(client_id_hash_helper(&a, hash_key) == client_id_hash_helper(&b, hash_key));
87322b3a
TG
236
237 free(b.data);
238 b.data = (uint8_t*)strdup("abce");
239 assert_se(client_id_compare_func(&a, &b) != 0);
240
241 free(a.data);
242 free(b.data);
243}
244
b44cd882 245int main(int argc, char *argv[]) {
4afd3348 246 _cleanup_(sd_event_unrefp) sd_event *e;
6f08fb7b 247 int r;
b44cd882
TG
248
249 log_set_max_level(LOG_DEBUG);
250 log_parse_environment();
251 log_open();
252
253 assert_se(sd_event_new(&e) >= 0);
254
6f08fb7b
TG
255 r = test_basic(e);
256 if (r != 0)
257 return r;
258
be077570 259 test_message_handler();
87322b3a 260 test_client_id_hash();
b44cd882
TG
261
262 return 0;
263}