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"
13 static void test_pool(struct in_addr
*address
, unsigned size
, int ret
) {
14 _cleanup_(sd_dhcp_server_unrefp
) sd_dhcp_server
*server
= NULL
;
16 assert_se(sd_dhcp_server_new(&server
, 1) >= 0);
18 assert_se(sd_dhcp_server_configure_pool(server
, address
, 8, 0, size
) == ret
);
21 static int test_basic(sd_event
*event
) {
22 _cleanup_(sd_dhcp_server_unrefp
) sd_dhcp_server
*server
= NULL
;
23 struct in_addr address_lo
= {
24 .s_addr
= htonl(INADDR_LOOPBACK
),
26 struct in_addr address_any
= {
27 .s_addr
= htonl(INADDR_ANY
),
31 /* attach to loopback interface */
32 assert_se(sd_dhcp_server_new(&server
, 1) >= 0);
35 assert_se(sd_dhcp_server_attach_event(server
, event
, 0) >= 0);
36 assert_se(sd_dhcp_server_attach_event(server
, event
, 0) == -EBUSY
);
37 assert_se(sd_dhcp_server_get_event(server
) == event
);
38 assert_se(sd_dhcp_server_detach_event(server
) >= 0);
39 assert_se(!sd_dhcp_server_get_event(server
));
40 assert_se(sd_dhcp_server_attach_event(server
, NULL
, 0) >= 0);
41 assert_se(sd_dhcp_server_attach_event(server
, NULL
, 0) == -EBUSY
);
43 assert_se(sd_dhcp_server_ref(server
) == server
);
44 assert_se(!sd_dhcp_server_unref(server
));
46 assert_se(sd_dhcp_server_start(server
) == -EUNATCH
);
48 assert_se(sd_dhcp_server_configure_pool(server
, &address_any
, 28, 0, 0) == -EINVAL
);
49 assert_se(sd_dhcp_server_configure_pool(server
, &address_lo
, 38, 0, 0) == -ERANGE
);
50 assert_se(sd_dhcp_server_configure_pool(server
, &address_lo
, 8, 0, 0) >= 0);
51 assert_se(sd_dhcp_server_configure_pool(server
, &address_lo
, 8, 0, 0) >= 0);
53 test_pool(&address_any
, 1, -EINVAL
);
54 test_pool(&address_lo
, 1, 0);
56 r
= sd_dhcp_server_start(server
);
58 return log_info_errno(r
, "sd_dhcp_server_start failed: %m");
61 assert_se(sd_dhcp_server_start(server
) == -EBUSY
);
62 assert_se(sd_dhcp_server_stop(server
) >= 0);
63 assert_se(sd_dhcp_server_stop(server
) >= 0);
64 assert_se(sd_dhcp_server_start(server
) >= 0);
69 static void test_message_handler(void) {
70 _cleanup_(sd_dhcp_server_unrefp
) sd_dhcp_server
*server
= NULL
;
77 } _packed_ option_type
;
82 } _packed_ option_requested_ip
;
87 } _packed_ option_server_id
;
92 } _packed_ option_client_id
;
95 .message
.op
= BOOTREQUEST
,
96 .message
.htype
= ARPHRD_ETHER
,
97 .message
.hlen
= ETHER_ADDR_LEN
,
98 .message
.xid
= htobe32(0x12345678),
99 .message
.chaddr
= { 'A', 'B', 'C', 'D', 'E', 'F' },
100 .option_type
.code
= SD_DHCP_OPTION_MESSAGE_TYPE
,
101 .option_type
.length
= 1,
102 .option_type
.type
= DHCP_DISCOVER
,
103 .end
= SD_DHCP_OPTION_END
,
105 struct in_addr address_lo
= {
106 .s_addr
= htonl(INADDR_LOOPBACK
),
109 assert_se(sd_dhcp_server_new(&server
, 1) >= 0);
110 assert_se(sd_dhcp_server_configure_pool(server
, &address_lo
, 8, 0, 0) >= 0);
111 assert_se(sd_dhcp_server_attach_event(server
, NULL
, 0) >= 0);
112 assert_se(sd_dhcp_server_start(server
) >= 0);
114 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_OFFER
);
117 /* TODO, shouldn't this fail? */
118 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_OFFER
);
119 test
.end
= SD_DHCP_OPTION_END
;
120 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_OFFER
);
122 test
.option_type
.code
= 0;
123 test
.option_type
.length
= 0;
124 test
.option_type
.type
= 0;
125 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
126 test
.option_type
.code
= SD_DHCP_OPTION_MESSAGE_TYPE
;
127 test
.option_type
.length
= 1;
128 test
.option_type
.type
= DHCP_DISCOVER
;
129 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_OFFER
);
132 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
133 test
.message
.op
= BOOTREQUEST
;
134 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_OFFER
);
136 test
.message
.htype
= 0;
137 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
138 test
.message
.htype
= ARPHRD_ETHER
;
139 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_OFFER
);
141 test
.message
.hlen
= 0;
142 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
143 test
.message
.hlen
= ETHER_ADDR_LEN
;
144 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_OFFER
);
146 test
.option_type
.type
= DHCP_REQUEST
;
147 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
148 test
.option_requested_ip
.code
= SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
;
149 test
.option_requested_ip
.length
= 4;
150 test
.option_requested_ip
.address
= htobe32(0x12345678);
151 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_NAK
);
152 test
.option_server_id
.code
= SD_DHCP_OPTION_SERVER_IDENTIFIER
;
153 test
.option_server_id
.length
= 4;
154 test
.option_server_id
.address
= htobe32(INADDR_LOOPBACK
);
155 test
.option_requested_ip
.address
= htobe32(INADDR_LOOPBACK
+ 3);
156 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_ACK
);
158 test
.option_server_id
.address
= htobe32(0x12345678);
159 test
.option_requested_ip
.address
= htobe32(INADDR_LOOPBACK
+ 3);
160 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
161 test
.option_server_id
.address
= htobe32(INADDR_LOOPBACK
);
162 test
.option_requested_ip
.address
= htobe32(INADDR_LOOPBACK
+ 4);
163 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
164 test
.option_requested_ip
.address
= htobe32(INADDR_LOOPBACK
+ 3);
165 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_ACK
);
167 test
.option_client_id
.code
= SD_DHCP_OPTION_CLIENT_IDENTIFIER
;
168 test
.option_client_id
.length
= 7;
169 test
.option_client_id
.id
[0] = 0x01;
170 test
.option_client_id
.id
[1] = 'A';
171 test
.option_client_id
.id
[2] = 'B';
172 test
.option_client_id
.id
[3] = 'C';
173 test
.option_client_id
.id
[4] = 'D';
174 test
.option_client_id
.id
[5] = 'E';
175 test
.option_client_id
.id
[6] = 'F';
176 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_ACK
);
178 test
.option_requested_ip
.address
= htobe32(INADDR_LOOPBACK
+ 30);
179 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
182 static uint64_t client_id_hash_helper(DHCPClientId
*id
, uint8_t key
[HASH_KEY_SIZE
]) {
183 struct siphash state
;
185 siphash24_init(&state
, key
);
186 client_id_hash_func(id
, &state
);
188 return htole64(siphash24_finalize(&state
));
191 static void test_client_id_hash(void) {
197 uint8_t hash_key
[HASH_KEY_SIZE
] = {
198 '0', '1', '2', '3', '4', '5', '6', '7',
199 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
202 a
.data
= (uint8_t*)strdup("abcd");
203 b
.data
= (uint8_t*)strdup("abcd");
205 assert_se(client_id_compare_func(&a
, &b
) == 0);
206 assert_se(client_id_hash_helper(&a
, hash_key
) == client_id_hash_helper(&b
, hash_key
));
208 assert_se(client_id_compare_func(&a
, &b
) != 0);
210 assert_se(client_id_compare_func(&a
, &b
) == 0);
211 assert_se(client_id_hash_helper(&a
, hash_key
) == client_id_hash_helper(&b
, hash_key
));
214 assert_se(client_id_compare_func(&a
, &b
) != 0);
216 assert_se(client_id_compare_func(&a
, &b
) == 0);
217 assert_se(client_id_hash_helper(&a
, hash_key
) == client_id_hash_helper(&b
, hash_key
));
220 b
.data
= (uint8_t*)strdup("abce");
221 assert_se(client_id_compare_func(&a
, &b
) != 0);
227 int main(int argc
, char *argv
[]) {
228 _cleanup_(sd_event_unrefp
) sd_event
*e
;
231 log_set_max_level(LOG_DEBUG
);
232 log_parse_environment();
235 assert_se(sd_event_new(&e
) >= 0);
239 log_notice("%s: skipping tests.", program_invocation_short_name
);
240 return EXIT_TEST_SKIP
;
243 test_message_handler();
244 test_client_id_hash();