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