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