]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
b44cd882 | 2 | /*** |
810adae9 | 3 | Copyright © 2013 Intel Corporation. All rights reserved. |
b44cd882 TG |
4 | ***/ |
5 | ||
ddb82ec2 | 6 | #include <net/if_arp.h> |
b44cd882 | 7 | |
07630cea | 8 | #include "sd-dhcp-server.h" |
b44cd882 | 9 | #include "sd-event.h" |
b44cd882 | 10 | |
b44cd882 | 11 | #include "dhcp-server-internal.h" |
5cdf13c7 DDM |
12 | #include "hashmap.h" |
13 | #include "siphash24.h" | |
317bb217 | 14 | #include "tests.h" |
b44cd882 | 15 | |
99634696 | 16 | static void test_pool(struct in_addr *address, unsigned size, int ret) { |
4afd3348 | 17 | _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL; |
99634696 | 18 | |
73a1a6f4 | 19 | ASSERT_OK(sd_dhcp_server_new(&server, 1)); |
99634696 | 20 | |
73a1a6f4 DDM |
21 | if (ret >= 0) |
22 | ASSERT_RETURN_IS_CRITICAL(true, ASSERT_OK_EQ(sd_dhcp_server_configure_pool(server, address, 8, 0, size), ret)); | |
23 | else | |
24 | ASSERT_RETURN_IS_CRITICAL(false, ASSERT_ERROR(sd_dhcp_server_configure_pool(server, address, 8, 0, size), -ret)); | |
99634696 TG |
25 | } |
26 | ||
4e2319af | 27 | static int test_basic(bool bind_to_interface) { |
4afd3348 | 28 | _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL; |
4e2319af | 29 | _cleanup_(sd_event_unrefp) sd_event *event = NULL; |
20af7091 | 30 | struct in_addr address_lo = { |
d7a0f1f4 | 31 | .s_addr = htobe32(INADDR_LOOPBACK), |
20af7091 TG |
32 | }; |
33 | struct in_addr address_any = { | |
d7a0f1f4 | 34 | .s_addr = htobe32(INADDR_ANY), |
20af7091 | 35 | }; |
6f08fb7b | 36 | int r; |
b44cd882 | 37 | |
99e65b7d YW |
38 | log_debug("/* %s(bind_to_interface=%s) */", __func__, yes_no(bind_to_interface)); |
39 | ||
73a1a6f4 | 40 | ASSERT_OK(sd_event_new(&event)); |
4e2319af | 41 | |
3a864fe4 | 42 | /* attach to loopback interface */ |
73a1a6f4 DDM |
43 | ASSERT_OK(sd_dhcp_server_new(&server, 1)); |
44 | ASSERT_NOT_NULL(server); | |
21b6b87e | 45 | server->bind_to_interface = bind_to_interface; |
b44cd882 | 46 | |
73a1a6f4 DDM |
47 | ASSERT_OK(sd_dhcp_server_attach_event(server, event, 0)); |
48 | ASSERT_RETURN_EXPECTED(ASSERT_ERROR(sd_dhcp_server_attach_event(server, event, 0), EBUSY)); | |
49 | ASSERT_TRUE(sd_dhcp_server_get_event(server) == event); /* ASSERT_EQ() doesn't work here. */ | |
50 | ASSERT_OK(sd_dhcp_server_detach_event(server)); | |
51 | ASSERT_NULL(sd_dhcp_server_get_event(server)); | |
52 | ASSERT_OK(sd_dhcp_server_attach_event(server, NULL, 0)); | |
53 | ASSERT_RETURN_EXPECTED(ASSERT_ERROR(sd_dhcp_server_attach_event(server, NULL, 0), EBUSY)); | |
b44cd882 | 54 | |
73a1a6f4 DDM |
55 | ASSERT_TRUE(sd_dhcp_server_ref(server) == server); |
56 | ASSERT_NULL(sd_dhcp_server_unref(server)); | |
ff734080 | 57 | |
73a1a6f4 | 58 | ASSERT_RETURN_EXPECTED(ASSERT_ERROR(sd_dhcp_server_start(server), EUNATCH)); |
20af7091 | 59 | |
73a1a6f4 DDM |
60 | ASSERT_RETURN_EXPECTED(ASSERT_ERROR(sd_dhcp_server_configure_pool(server, &address_any, 28, 0, 0), EINVAL)); |
61 | ASSERT_RETURN_EXPECTED(ASSERT_ERROR(sd_dhcp_server_configure_pool(server, &address_lo, 38, 0, 0), ERANGE)); | |
62 | ASSERT_OK(sd_dhcp_server_configure_pool(server, &address_lo, 8, 0, 0)); | |
63 | ASSERT_OK(sd_dhcp_server_configure_pool(server, &address_lo, 8, 0, 0)); | |
99634696 TG |
64 | |
65 | test_pool(&address_any, 1, -EINVAL); | |
66 | test_pool(&address_lo, 1, 0); | |
2dead812 | 67 | |
6f08fb7b | 68 | r = sd_dhcp_server_start(server); |
19614a08 RK |
69 | /* skip test if running in an environment with no full networking support, CONFIG_PACKET not |
70 | * compiled in kernel, nor af_packet module available. */ | |
71 | if (r == -EPERM || r == -EAFNOSUPPORT) | |
7e0a8bf1 | 72 | return r; |
73a1a6f4 | 73 | ASSERT_OK(r); |
6f08fb7b | 74 | |
73a1a6f4 DDM |
75 | ASSERT_OK(sd_dhcp_server_start(server)); |
76 | ASSERT_OK(sd_dhcp_server_stop(server)); | |
77 | ASSERT_OK(sd_dhcp_server_stop(server)); | |
78 | ASSERT_OK(sd_dhcp_server_start(server)); | |
6f08fb7b TG |
79 | |
80 | return 0; | |
b44cd882 TG |
81 | } |
82 | ||
be077570 | 83 | static void test_message_handler(void) { |
4afd3348 | 84 | _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL; |
be077570 | 85 | struct { |
5b160db5 YW |
86 | struct { |
87 | DHCP_MESSAGE_HEADER_DEFINITION; | |
88 | } _packed_ message; | |
be077570 TG |
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; | |
930133d5 RH |
109 | struct { |
110 | uint8_t code; | |
111 | uint8_t length; | |
112 | uint8_t hostname[6]; | |
113 | } _packed_ option_hostname; | |
be077570 TG |
114 | uint8_t end; |
115 | } _packed_ test = { | |
116 | .message.op = BOOTREQUEST, | |
117 | .message.htype = ARPHRD_ETHER, | |
118 | .message.hlen = ETHER_ADDR_LEN, | |
2dead812 TG |
119 | .message.xid = htobe32(0x12345678), |
120 | .message.chaddr = { 'A', 'B', 'C', 'D', 'E', 'F' }, | |
22805d92 | 121 | .option_type.code = SD_DHCP_OPTION_MESSAGE_TYPE, |
be077570 TG |
122 | .option_type.length = 1, |
123 | .option_type.type = DHCP_DISCOVER, | |
930133d5 RH |
124 | .option_hostname.code = SD_DHCP_OPTION_HOST_NAME, |
125 | .option_hostname.length = 6, | |
126 | .option_hostname.hostname = { 'T', 'E', 'S', 'T', 'H', 'N' }, | |
22805d92 | 127 | .end = SD_DHCP_OPTION_END, |
be077570 | 128 | }; |
20af7091 | 129 | struct in_addr address_lo = { |
d7a0f1f4 | 130 | .s_addr = htobe32(INADDR_LOOPBACK), |
20af7091 | 131 | }; |
6796c5a9 YW |
132 | struct in_addr static_lease_address = { |
133 | .s_addr = htobe32(INADDR_LOOPBACK + 42), | |
134 | }; | |
135 | static uint8_t static_lease_client_id[7] = {0x01, 'A', 'B', 'C', 'D', 'E', 'G' }; | |
4cf7a676 | 136 | int r; |
be077570 | 137 | |
99e65b7d YW |
138 | log_debug("/* %s */", __func__); |
139 | ||
73a1a6f4 DDM |
140 | ASSERT_OK(sd_dhcp_server_new(&server, 1)); |
141 | ASSERT_OK(sd_dhcp_server_configure_pool(server, &address_lo, 8, 0, 0)); | |
142 | ASSERT_OK(sd_dhcp_server_set_static_lease(server, &static_lease_address, static_lease_client_id, | |
143 | ELEMENTSOF(static_lease_client_id))); | |
144 | ASSERT_OK(sd_dhcp_server_attach_event(server, NULL, 0)); | |
145 | ASSERT_OK(sd_dhcp_server_start(server)); | |
be077570 | 146 | |
4cf7a676 DDM |
147 | r = dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL); |
148 | if (r == -ENETDOWN) | |
149 | return (void) log_tests_skipped("Network is not available"); | |
73a1a6f4 | 150 | ASSERT_OK_EQ(r, DHCP_OFFER); |
be077570 TG |
151 | |
152 | test.end = 0; | |
153 | /* TODO, shouldn't this fail? */ | |
73a1a6f4 | 154 | ASSERT_OK_EQ(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL), DHCP_OFFER); |
22805d92 | 155 | test.end = SD_DHCP_OPTION_END; |
73a1a6f4 | 156 | ASSERT_OK_EQ(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL), DHCP_OFFER); |
be077570 TG |
157 | |
158 | test.option_type.code = 0; | |
159 | test.option_type.length = 0; | |
160 | test.option_type.type = 0; | |
73a1a6f4 | 161 | ASSERT_ERROR(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL), ENOMSG); |
22805d92 | 162 | test.option_type.code = SD_DHCP_OPTION_MESSAGE_TYPE; |
be077570 TG |
163 | test.option_type.length = 1; |
164 | test.option_type.type = DHCP_DISCOVER; | |
73a1a6f4 | 165 | ASSERT_OK_EQ(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL), DHCP_OFFER); |
be077570 TG |
166 | |
167 | test.message.op = 0; | |
73a1a6f4 | 168 | ASSERT_OK_ZERO(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL)); |
be077570 | 169 | test.message.op = BOOTREQUEST; |
73a1a6f4 | 170 | ASSERT_OK_EQ(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL), DHCP_OFFER); |
be077570 TG |
171 | |
172 | test.message.htype = 0; | |
73a1a6f4 | 173 | ASSERT_OK_EQ(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL), DHCP_OFFER); |
be077570 | 174 | test.message.htype = ARPHRD_ETHER; |
73a1a6f4 | 175 | ASSERT_OK_EQ(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL), DHCP_OFFER); |
be077570 TG |
176 | |
177 | test.message.hlen = 0; | |
73a1a6f4 | 178 | ASSERT_ERROR(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL), EBADMSG); |
be077570 | 179 | test.message.hlen = ETHER_ADDR_LEN; |
73a1a6f4 | 180 | ASSERT_OK_EQ(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL), DHCP_OFFER); |
2dead812 TG |
181 | |
182 | test.option_type.type = DHCP_REQUEST; | |
73a1a6f4 | 183 | ASSERT_OK_ZERO(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL)); |
22805d92 | 184 | test.option_requested_ip.code = SD_DHCP_OPTION_REQUESTED_IP_ADDRESS; |
2dead812 TG |
185 | test.option_requested_ip.length = 4; |
186 | test.option_requested_ip.address = htobe32(0x12345678); | |
73a1a6f4 | 187 | ASSERT_OK_EQ(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL), DHCP_NAK); |
22805d92 | 188 | test.option_server_id.code = SD_DHCP_OPTION_SERVER_IDENTIFIER; |
2dead812 TG |
189 | test.option_server_id.length = 4; |
190 | test.option_server_id.address = htobe32(INADDR_LOOPBACK); | |
191 | test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3); | |
73a1a6f4 | 192 | ASSERT_OK_EQ(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL), DHCP_ACK); |
87322b3a | 193 | |
2dead812 TG |
194 | test.option_server_id.address = htobe32(0x12345678); |
195 | test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3); | |
73a1a6f4 | 196 | ASSERT_OK_ZERO(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL)); |
bd57b450 | 197 | test.option_server_id.address = htobe32(INADDR_LOOPBACK); |
87322b3a | 198 | test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 4); |
73a1a6f4 | 199 | ASSERT_OK_EQ(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL), DHCP_ACK); |
87322b3a | 200 | test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3); |
73a1a6f4 | 201 | ASSERT_OK_EQ(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL), DHCP_ACK); |
87322b3a | 202 | |
22805d92 | 203 | test.option_client_id.code = SD_DHCP_OPTION_CLIENT_IDENTIFIER; |
87322b3a TG |
204 | test.option_client_id.length = 7; |
205 | test.option_client_id.id[0] = 0x01; | |
206 | test.option_client_id.id[1] = 'A'; | |
207 | test.option_client_id.id[2] = 'B'; | |
208 | test.option_client_id.id[3] = 'C'; | |
209 | test.option_client_id.id[4] = 'D'; | |
210 | test.option_client_id.id[5] = 'E'; | |
211 | test.option_client_id.id[6] = 'F'; | |
73a1a6f4 | 212 | ASSERT_OK_EQ(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL), DHCP_ACK); |
87322b3a | 213 | |
bd57b450 | 214 | test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 30); |
73a1a6f4 | 215 | ASSERT_OK_EQ(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL), DHCP_ACK); |
6796c5a9 YW |
216 | |
217 | /* request address reserved for static lease (unmatching client ID) */ | |
218 | test.option_client_id.id[6] = 'H'; | |
219 | test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 42); | |
73a1a6f4 | 220 | ASSERT_OK_ZERO(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL)); |
6796c5a9 YW |
221 | |
222 | /* request unmatching address */ | |
223 | test.option_client_id.id[6] = 'G'; | |
224 | test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 41); | |
73a1a6f4 | 225 | ASSERT_OK_ZERO(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL)); |
6796c5a9 YW |
226 | |
227 | /* request matching address */ | |
228 | test.option_client_id.id[6] = 'G'; | |
229 | test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 42); | |
73a1a6f4 | 230 | ASSERT_OK_EQ(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL), DHCP_ACK); |
6796c5a9 YW |
231 | |
232 | /* try again */ | |
233 | test.option_client_id.id[6] = 'G'; | |
234 | test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 42); | |
73a1a6f4 | 235 | ASSERT_OK_EQ(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test), NULL), DHCP_ACK); |
be077570 TG |
236 | } |
237 | ||
95c48613 | 238 | static uint64_t client_id_hash_helper(sd_dhcp_client_id *id, uint8_t key[HASH_KEY_SIZE]) { |
b826ab58 TG |
239 | struct siphash state; |
240 | ||
0cb3c286 | 241 | siphash24_init(&state, key); |
b826ab58 | 242 | client_id_hash_func(id, &state); |
0cb3c286 | 243 | |
933f9cae | 244 | return htole64(siphash24_finalize(&state)); |
b826ab58 TG |
245 | } |
246 | ||
87322b3a | 247 | static void test_client_id_hash(void) { |
95c48613 YW |
248 | sd_dhcp_client_id a = { |
249 | .size = 4, | |
87322b3a | 250 | }, b = { |
95c48613 | 251 | .size = 4, |
87322b3a TG |
252 | }; |
253 | uint8_t hash_key[HASH_KEY_SIZE] = { | |
254 | '0', '1', '2', '3', '4', '5', '6', '7', | |
255 | '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', | |
256 | }; | |
257 | ||
99e65b7d YW |
258 | log_debug("/* %s */", __func__); |
259 | ||
95c48613 YW |
260 | memcpy(a.raw, "abcd", 4); |
261 | memcpy(b.raw, "abcd", 4); | |
87322b3a | 262 | |
73a1a6f4 DDM |
263 | ASSERT_EQ(client_id_compare_func(&a, &b), 0); |
264 | ASSERT_EQ(client_id_hash_helper(&a, hash_key), client_id_hash_helper(&b, hash_key)); | |
95c48613 | 265 | a.size = 3; |
73a1a6f4 | 266 | ASSERT_NE(client_id_compare_func(&a, &b), 0); |
95c48613 | 267 | a.size = 4; |
73a1a6f4 DDM |
268 | ASSERT_EQ(client_id_compare_func(&a, &b), 0); |
269 | ASSERT_EQ(client_id_hash_helper(&a, hash_key), client_id_hash_helper(&b, hash_key)); | |
87322b3a | 270 | |
95c48613 | 271 | b.size = 3; |
73a1a6f4 | 272 | ASSERT_NE(client_id_compare_func(&a, &b), 0); |
95c48613 | 273 | b.size = 4; |
73a1a6f4 DDM |
274 | ASSERT_EQ(client_id_compare_func(&a, &b), 0); |
275 | ASSERT_EQ(client_id_hash_helper(&a, hash_key), client_id_hash_helper(&b, hash_key)); | |
87322b3a | 276 | |
95c48613 | 277 | memcpy(b.raw, "abce", 4); |
73a1a6f4 | 278 | ASSERT_NE(client_id_compare_func(&a, &b), 0); |
87322b3a TG |
279 | } |
280 | ||
7b5445e7 YW |
281 | static void test_static_lease(void) { |
282 | _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL; | |
283 | ||
284 | log_debug("/* %s */", __func__); | |
285 | ||
73a1a6f4 | 286 | ASSERT_OK(sd_dhcp_server_new(&server, 1)); |
7b5445e7 | 287 | |
73a1a6f4 DDM |
288 | ASSERT_OK(sd_dhcp_server_set_static_lease(server, &(struct in_addr) { .s_addr = 0x01020304 }, |
289 | (uint8_t*) &(uint32_t) { 0x01020304 }, sizeof(uint32_t))); | |
7b5445e7 | 290 | /* Duplicated entry. */ |
73a1a6f4 DDM |
291 | ASSERT_ERROR(sd_dhcp_server_set_static_lease(server, &(struct in_addr) { .s_addr = 0x01020304 }, |
292 | (uint8_t*) &(uint32_t) { 0x01020304 }, sizeof(uint32_t)), EEXIST); | |
7b5445e7 | 293 | /* Address is conflicted. */ |
73a1a6f4 DDM |
294 | ASSERT_ERROR(sd_dhcp_server_set_static_lease(server, &(struct in_addr) { .s_addr = 0x01020304 }, |
295 | (uint8_t*) &(uint32_t) { 0x01020305 }, sizeof(uint32_t)), EEXIST); | |
7b5445e7 | 296 | /* Client ID is conflicted. */ |
73a1a6f4 DDM |
297 | ASSERT_ERROR(sd_dhcp_server_set_static_lease(server, &(struct in_addr) { .s_addr = 0x01020305 }, |
298 | (uint8_t*) &(uint32_t) { 0x01020304 }, sizeof(uint32_t)), EEXIST); | |
7b5445e7 | 299 | |
73a1a6f4 DDM |
300 | ASSERT_OK(sd_dhcp_server_set_static_lease(server, &(struct in_addr) { .s_addr = 0x01020305 }, |
301 | (uint8_t*) &(uint32_t) { 0x01020305 }, sizeof(uint32_t))); | |
7b5445e7 | 302 | /* Remove the previous entry. */ |
73a1a6f4 DDM |
303 | ASSERT_OK(sd_dhcp_server_set_static_lease(server, &(struct in_addr) { .s_addr = 0x00000000 }, |
304 | (uint8_t*) &(uint32_t) { 0x01020305 }, sizeof(uint32_t))); | |
7b5445e7 | 305 | /* Then, set a different address. */ |
73a1a6f4 DDM |
306 | ASSERT_OK(sd_dhcp_server_set_static_lease(server, &(struct in_addr) { .s_addr = 0x01020306 }, |
307 | (uint8_t*) &(uint32_t) { 0x01020305 }, sizeof(uint32_t))); | |
7b5445e7 | 308 | /* Remove again. */ |
73a1a6f4 DDM |
309 | ASSERT_OK(sd_dhcp_server_set_static_lease(server, &(struct in_addr) { .s_addr = 0x00000000 }, |
310 | (uint8_t*) &(uint32_t) { 0x01020305 }, sizeof(uint32_t))); | |
7b5445e7 | 311 | /* Try to remove non-existent entry. */ |
73a1a6f4 DDM |
312 | ASSERT_OK(sd_dhcp_server_set_static_lease(server, &(struct in_addr) { .s_addr = 0x00000000 }, |
313 | (uint8_t*) &(uint32_t) { 0x01020305 }, sizeof(uint32_t))); | |
7b5445e7 | 314 | /* Try to remove non-existent entry. */ |
73a1a6f4 DDM |
315 | ASSERT_OK(sd_dhcp_server_set_static_lease(server, &(struct in_addr) { .s_addr = 0x00000000 }, |
316 | (uint8_t*) &(uint32_t) { 0x01020306 }, sizeof(uint32_t))); | |
7b5445e7 YW |
317 | } |
318 | ||
b44cd882 | 319 | int main(int argc, char *argv[]) { |
6f08fb7b | 320 | int r; |
b44cd882 | 321 | |
6d7c4033 | 322 | test_setup_logging(LOG_DEBUG); |
b44cd882 | 323 | |
4f3cb246 | 324 | test_client_id_hash(); |
7b5445e7 | 325 | test_static_lease(); |
4f3cb246 | 326 | |
4e2319af | 327 | r = test_basic(true); |
7e0a8bf1 YW |
328 | if (r < 0) |
329 | return log_tests_skipped_errno(r, "cannot start dhcp server(bound to interface)"); | |
21b6b87e | 330 | |
4e2319af | 331 | r = test_basic(false); |
7e0a8bf1 YW |
332 | if (r < 0) |
333 | return log_tests_skipped_errno(r, "cannot start dhcp server(non-bound to interface)"); | |
6f08fb7b | 334 | |
be077570 | 335 | test_message_handler(); |
b44cd882 TG |
336 | |
337 | return 0; | |
338 | } |