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