1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright © 2013 Intel Corporation. All rights reserved.
8 #include "sd-dhcp-server.h"
11 #include "dhcp-server-internal.h"
14 static void test_pool(struct in_addr
*address
, unsigned size
, int ret
) {
15 _cleanup_(sd_dhcp_server_unrefp
) sd_dhcp_server
*server
= NULL
;
17 assert_se(sd_dhcp_server_new(&server
, 1) >= 0);
19 assert_se(sd_dhcp_server_configure_pool(server
, address
, 8, 0, size
) == ret
);
22 static int test_basic(sd_event
*event
) {
23 _cleanup_(sd_dhcp_server_unrefp
) sd_dhcp_server
*server
= NULL
;
24 struct in_addr address_lo
= {
25 .s_addr
= htonl(INADDR_LOOPBACK
),
27 struct in_addr address_any
= {
28 .s_addr
= htonl(INADDR_ANY
),
32 /* attach to loopback interface */
33 assert_se(sd_dhcp_server_new(&server
, 1) >= 0);
36 assert_se(sd_dhcp_server_attach_event(server
, event
, 0) >= 0);
37 assert_se(sd_dhcp_server_attach_event(server
, event
, 0) == -EBUSY
);
38 assert_se(sd_dhcp_server_get_event(server
) == event
);
39 assert_se(sd_dhcp_server_detach_event(server
) >= 0);
40 assert_se(!sd_dhcp_server_get_event(server
));
41 assert_se(sd_dhcp_server_attach_event(server
, NULL
, 0) >= 0);
42 assert_se(sd_dhcp_server_attach_event(server
, NULL
, 0) == -EBUSY
);
44 assert_se(sd_dhcp_server_ref(server
) == server
);
45 assert_se(!sd_dhcp_server_unref(server
));
47 assert_se(sd_dhcp_server_start(server
) == -EUNATCH
);
49 assert_se(sd_dhcp_server_configure_pool(server
, &address_any
, 28, 0, 0) == -EINVAL
);
50 assert_se(sd_dhcp_server_configure_pool(server
, &address_lo
, 38, 0, 0) == -ERANGE
);
51 assert_se(sd_dhcp_server_configure_pool(server
, &address_lo
, 8, 0, 0) >= 0);
52 assert_se(sd_dhcp_server_configure_pool(server
, &address_lo
, 8, 0, 0) >= 0);
54 test_pool(&address_any
, 1, -EINVAL
);
55 test_pool(&address_lo
, 1, 0);
57 r
= sd_dhcp_server_start(server
);
59 return log_info_errno(r
, "sd_dhcp_server_start failed: %m");
62 assert_se(sd_dhcp_server_start(server
) == -EBUSY
);
63 assert_se(sd_dhcp_server_stop(server
) >= 0);
64 assert_se(sd_dhcp_server_stop(server
) >= 0);
65 assert_se(sd_dhcp_server_start(server
) >= 0);
70 static void test_message_handler(void) {
71 _cleanup_(sd_dhcp_server_unrefp
) sd_dhcp_server
*server
= NULL
;
78 } _packed_ option_type
;
83 } _packed_ option_requested_ip
;
88 } _packed_ option_server_id
;
93 } _packed_ option_client_id
;
96 .message
.op
= BOOTREQUEST
,
97 .message
.htype
= ARPHRD_ETHER
,
98 .message
.hlen
= ETHER_ADDR_LEN
,
99 .message
.xid
= htobe32(0x12345678),
100 .message
.chaddr
= { 'A', 'B', 'C', 'D', 'E', 'F' },
101 .option_type
.code
= SD_DHCP_OPTION_MESSAGE_TYPE
,
102 .option_type
.length
= 1,
103 .option_type
.type
= DHCP_DISCOVER
,
104 .end
= SD_DHCP_OPTION_END
,
106 struct in_addr address_lo
= {
107 .s_addr
= htonl(INADDR_LOOPBACK
),
110 assert_se(sd_dhcp_server_new(&server
, 1) >= 0);
111 assert_se(sd_dhcp_server_configure_pool(server
, &address_lo
, 8, 0, 0) >= 0);
112 assert_se(sd_dhcp_server_attach_event(server
, NULL
, 0) >= 0);
113 assert_se(sd_dhcp_server_start(server
) >= 0);
115 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_OFFER
);
118 /* TODO, shouldn't this fail? */
119 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_OFFER
);
120 test
.end
= SD_DHCP_OPTION_END
;
121 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_OFFER
);
123 test
.option_type
.code
= 0;
124 test
.option_type
.length
= 0;
125 test
.option_type
.type
= 0;
126 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
127 test
.option_type
.code
= SD_DHCP_OPTION_MESSAGE_TYPE
;
128 test
.option_type
.length
= 1;
129 test
.option_type
.type
= DHCP_DISCOVER
;
130 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_OFFER
);
133 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
134 test
.message
.op
= BOOTREQUEST
;
135 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_OFFER
);
137 test
.message
.htype
= 0;
138 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
139 test
.message
.htype
= ARPHRD_ETHER
;
140 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_OFFER
);
142 test
.message
.hlen
= 0;
143 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
144 test
.message
.hlen
= ETHER_ADDR_LEN
;
145 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_OFFER
);
147 test
.option_type
.type
= DHCP_REQUEST
;
148 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
149 test
.option_requested_ip
.code
= SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
;
150 test
.option_requested_ip
.length
= 4;
151 test
.option_requested_ip
.address
= htobe32(0x12345678);
152 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_NAK
);
153 test
.option_server_id
.code
= SD_DHCP_OPTION_SERVER_IDENTIFIER
;
154 test
.option_server_id
.length
= 4;
155 test
.option_server_id
.address
= htobe32(INADDR_LOOPBACK
);
156 test
.option_requested_ip
.address
= htobe32(INADDR_LOOPBACK
+ 3);
157 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_ACK
);
159 test
.option_server_id
.address
= htobe32(0x12345678);
160 test
.option_requested_ip
.address
= htobe32(INADDR_LOOPBACK
+ 3);
161 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
162 test
.option_server_id
.address
= htobe32(INADDR_LOOPBACK
);
163 test
.option_requested_ip
.address
= htobe32(INADDR_LOOPBACK
+ 4);
164 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
165 test
.option_requested_ip
.address
= htobe32(INADDR_LOOPBACK
+ 3);
166 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_ACK
);
168 test
.option_client_id
.code
= SD_DHCP_OPTION_CLIENT_IDENTIFIER
;
169 test
.option_client_id
.length
= 7;
170 test
.option_client_id
.id
[0] = 0x01;
171 test
.option_client_id
.id
[1] = 'A';
172 test
.option_client_id
.id
[2] = 'B';
173 test
.option_client_id
.id
[3] = 'C';
174 test
.option_client_id
.id
[4] = 'D';
175 test
.option_client_id
.id
[5] = 'E';
176 test
.option_client_id
.id
[6] = 'F';
177 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_ACK
);
179 test
.option_requested_ip
.address
= htobe32(INADDR_LOOPBACK
+ 30);
180 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
183 static uint64_t client_id_hash_helper(DHCPClientId
*id
, uint8_t key
[HASH_KEY_SIZE
]) {
184 struct siphash state
;
186 siphash24_init(&state
, key
);
187 client_id_hash_func(id
, &state
);
189 return htole64(siphash24_finalize(&state
));
192 static void test_client_id_hash(void) {
198 uint8_t hash_key
[HASH_KEY_SIZE
] = {
199 '0', '1', '2', '3', '4', '5', '6', '7',
200 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
203 a
.data
= (uint8_t*)strdup("abcd");
204 b
.data
= (uint8_t*)strdup("abcd");
206 assert_se(client_id_compare_func(&a
, &b
) == 0);
207 assert_se(client_id_hash_helper(&a
, hash_key
) == client_id_hash_helper(&b
, hash_key
));
209 assert_se(client_id_compare_func(&a
, &b
) != 0);
211 assert_se(client_id_compare_func(&a
, &b
) == 0);
212 assert_se(client_id_hash_helper(&a
, hash_key
) == client_id_hash_helper(&b
, hash_key
));
215 assert_se(client_id_compare_func(&a
, &b
) != 0);
217 assert_se(client_id_compare_func(&a
, &b
) == 0);
218 assert_se(client_id_hash_helper(&a
, hash_key
) == client_id_hash_helper(&b
, hash_key
));
221 b
.data
= (uint8_t*)strdup("abce");
222 assert_se(client_id_compare_func(&a
, &b
) != 0);
228 int main(int argc
, char *argv
[]) {
229 _cleanup_(sd_event_unrefp
) sd_event
*e
;
232 test_setup_logging(LOG_DEBUG
);
234 assert_se(sd_event_new(&e
) >= 0);
238 return log_tests_skipped("cannot start dhcp server");
240 test_message_handler();
241 test_client_id_hash();