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