]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-network/test-dhcp-server.c
Merge pull request #7388 from keszybz/doc-tweak
[thirdparty/systemd.git] / src / libsystemd-network / test-dhcp-server.c
CommitLineData
b44cd882
TG
1/***
2 This file is part of systemd.
3
4 Copyright (C) 2013 Intel Corporation. All rights reserved.
5 Copyright (C) 2014 Tom Gundersen
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
b44cd882
TG
21#include <errno.h>
22
07630cea 23#include "sd-dhcp-server.h"
b44cd882 24#include "sd-event.h"
b44cd882 25
b44cd882
TG
26#include "dhcp-server-internal.h"
27
99634696 28static void test_pool(struct in_addr *address, unsigned size, int ret) {
4afd3348 29 _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
99634696
TG
30
31 assert_se(sd_dhcp_server_new(&server, 1) >= 0);
32
33 assert_se(sd_dhcp_server_configure_pool(server, address, 8, 0, size) == ret);
34}
35
6f08fb7b 36static int test_basic(sd_event *event) {
4afd3348 37 _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
20af7091
TG
38 struct in_addr address_lo = {
39 .s_addr = htonl(INADDR_LOOPBACK),
40 };
41 struct in_addr address_any = {
42 .s_addr = htonl(INADDR_ANY),
43 };
6f08fb7b 44 int r;
b44cd882 45
3a864fe4
TG
46 /* attach to loopback interface */
47 assert_se(sd_dhcp_server_new(&server, 1) >= 0);
b44cd882
TG
48 assert_se(server);
49
50 assert_se(sd_dhcp_server_attach_event(server, event, 0) >= 0);
51 assert_se(sd_dhcp_server_attach_event(server, event, 0) == -EBUSY);
52 assert_se(sd_dhcp_server_get_event(server) == event);
53 assert_se(sd_dhcp_server_detach_event(server) >= 0);
54 assert_se(!sd_dhcp_server_get_event(server));
55 assert_se(sd_dhcp_server_attach_event(server, NULL, 0) >= 0);
56 assert_se(sd_dhcp_server_attach_event(server, NULL, 0) == -EBUSY);
57
58 assert_se(sd_dhcp_server_ref(server) == server);
59 assert_se(!sd_dhcp_server_unref(server));
ff734080 60
20af7091 61 assert_se(sd_dhcp_server_start(server) == -EUNATCH);
20af7091 62
99634696
TG
63 assert_se(sd_dhcp_server_configure_pool(server, &address_any, 28, 0, 0) == -EINVAL);
64 assert_se(sd_dhcp_server_configure_pool(server, &address_lo, 38, 0, 0) == -ERANGE);
65 assert_se(sd_dhcp_server_configure_pool(server, &address_lo, 8, 0, 0) >= 0);
45a9eac9 66 assert_se(sd_dhcp_server_configure_pool(server, &address_lo, 8, 0, 0) >= 0);
99634696
TG
67
68 test_pool(&address_any, 1, -EINVAL);
69 test_pool(&address_lo, 1, 0);
2dead812 70
6f08fb7b
TG
71 r = sd_dhcp_server_start(server);
72
73 if (r == -EPERM)
74 return EXIT_TEST_SKIP;
75 assert_se(r >= 0);
76
ff734080
TG
77 assert_se(sd_dhcp_server_start(server) == -EBUSY);
78 assert_se(sd_dhcp_server_stop(server) >= 0);
79 assert_se(sd_dhcp_server_stop(server) >= 0);
80 assert_se(sd_dhcp_server_start(server) >= 0);
6f08fb7b
TG
81
82 return 0;
b44cd882
TG
83}
84
be077570 85static void test_message_handler(void) {
4afd3348 86 _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL;
be077570
TG
87 struct {
88 DHCPMessage message;
89 struct {
90 uint8_t code;
91 uint8_t length;
92 uint8_t type;
93 } _packed_ option_type;
2dead812
TG
94 struct {
95 uint8_t code;
96 uint8_t length;
97 be32_t address;
98 } _packed_ option_requested_ip;
99 struct {
100 uint8_t code;
101 uint8_t length;
102 be32_t address;
103 } _packed_ option_server_id;
87322b3a
TG
104 struct {
105 uint8_t code;
106 uint8_t length;
107 uint8_t id[7];
108 } _packed_ option_client_id;
be077570
TG
109 uint8_t end;
110 } _packed_ test = {
111 .message.op = BOOTREQUEST,
112 .message.htype = ARPHRD_ETHER,
113 .message.hlen = ETHER_ADDR_LEN,
2dead812
TG
114 .message.xid = htobe32(0x12345678),
115 .message.chaddr = { 'A', 'B', 'C', 'D', 'E', 'F' },
22805d92 116 .option_type.code = SD_DHCP_OPTION_MESSAGE_TYPE,
be077570
TG
117 .option_type.length = 1,
118 .option_type.type = DHCP_DISCOVER,
22805d92 119 .end = SD_DHCP_OPTION_END,
be077570 120 };
20af7091
TG
121 struct in_addr address_lo = {
122 .s_addr = htonl(INADDR_LOOPBACK),
123 };
be077570
TG
124
125 assert_se(sd_dhcp_server_new(&server, 1) >= 0);
99634696 126 assert_se(sd_dhcp_server_configure_pool(server, &address_lo, 8, 0, 0) >= 0);
20af7091
TG
127 assert_se(sd_dhcp_server_attach_event(server, NULL, 0) >= 0);
128 assert_se(sd_dhcp_server_start(server) >= 0);
be077570 129
4dc35568 130 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
be077570
TG
131
132 test.end = 0;
133 /* TODO, shouldn't this fail? */
4dc35568 134 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
22805d92 135 test.end = SD_DHCP_OPTION_END;
4dc35568 136 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
be077570
TG
137
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);
22805d92 142 test.option_type.code = SD_DHCP_OPTION_MESSAGE_TYPE;
be077570
TG
143 test.option_type.length = 1;
144 test.option_type.type = DHCP_DISCOVER;
4dc35568 145 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
be077570
TG
146
147 test.message.op = 0;
148 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
149 test.message.op = BOOTREQUEST;
4dc35568 150 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
be077570
TG
151
152 test.message.htype = 0;
153 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
154 test.message.htype = ARPHRD_ETHER;
4dc35568 155 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
be077570
TG
156
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;
4dc35568 160 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
2dead812
TG
161
162 test.option_type.type = DHCP_REQUEST;
163 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
22805d92 164 test.option_requested_ip.code = SD_DHCP_OPTION_REQUESTED_IP_ADDRESS;
2dead812
TG
165 test.option_requested_ip.length = 4;
166 test.option_requested_ip.address = htobe32(0x12345678);
bd57b450 167 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_NAK);
22805d92 168 test.option_server_id.code = SD_DHCP_OPTION_SERVER_IDENTIFIER;
2dead812
TG
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);
87322b3a 173
2dead812
TG
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);
bd57b450 177 test.option_server_id.address = htobe32(INADDR_LOOPBACK);
87322b3a
TG
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);
182
22805d92 183 test.option_client_id.code = SD_DHCP_OPTION_CLIENT_IDENTIFIER;
87322b3a
TG
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);
193
bd57b450 194 test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 30);
2dead812 195 assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
be077570
TG
196}
197
b826ab58
TG
198static uint64_t client_id_hash_helper(DHCPClientId *id, uint8_t key[HASH_KEY_SIZE]) {
199 struct siphash state;
200
0cb3c286 201 siphash24_init(&state, key);
b826ab58 202 client_id_hash_func(id, &state);
0cb3c286 203
933f9cae 204 return htole64(siphash24_finalize(&state));
b826ab58
TG
205}
206
87322b3a
TG
207static void test_client_id_hash(void) {
208 DHCPClientId a = {
209 .length = 4,
210 }, b = {
211 .length = 4,
212 };
213 uint8_t hash_key[HASH_KEY_SIZE] = {
214 '0', '1', '2', '3', '4', '5', '6', '7',
215 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
216 };
217
218 a.data = (uint8_t*)strdup("abcd");
219 b.data = (uint8_t*)strdup("abcd");
220
221 assert_se(client_id_compare_func(&a, &b) == 0);
b826ab58 222 assert_se(client_id_hash_helper(&a, hash_key) == client_id_hash_helper(&b, hash_key));
87322b3a
TG
223 a.length = 3;
224 assert_se(client_id_compare_func(&a, &b) != 0);
225 a.length = 4;
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
229 b.length = 3;
230 assert_se(client_id_compare_func(&a, &b) != 0);
231 b.length = 4;
232 assert_se(client_id_compare_func(&a, &b) == 0);
b826ab58 233 assert_se(client_id_hash_helper(&a, hash_key) == client_id_hash_helper(&b, hash_key));
87322b3a
TG
234
235 free(b.data);
236 b.data = (uint8_t*)strdup("abce");
237 assert_se(client_id_compare_func(&a, &b) != 0);
238
239 free(a.data);
240 free(b.data);
241}
242
b44cd882 243int main(int argc, char *argv[]) {
4afd3348 244 _cleanup_(sd_event_unrefp) sd_event *e;
6f08fb7b 245 int r;
b44cd882
TG
246
247 log_set_max_level(LOG_DEBUG);
248 log_parse_environment();
249 log_open();
250
251 assert_se(sd_event_new(&e) >= 0);
252
6f08fb7b
TG
253 r = test_basic(e);
254 if (r != 0)
255 return r;
256
be077570 257 test_message_handler();
87322b3a 258 test_client_id_hash();
b44cd882
TG
259
260 return 0;
261}