1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright (C) 2013 Intel Corporation. All rights reserved.
4 Copyright (C) 2014 Tom Gundersen
9 #include "sd-dhcp-server.h"
12 #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
);
60 return EXIT_TEST_SKIP
;
63 assert_se(sd_dhcp_server_start(server
) == -EBUSY
);
64 assert_se(sd_dhcp_server_stop(server
) >= 0);
65 assert_se(sd_dhcp_server_stop(server
) >= 0);
66 assert_se(sd_dhcp_server_start(server
) >= 0);
71 static void test_message_handler(void) {
72 _cleanup_(sd_dhcp_server_unrefp
) sd_dhcp_server
*server
= NULL
;
79 } _packed_ option_type
;
84 } _packed_ option_requested_ip
;
89 } _packed_ option_server_id
;
94 } _packed_ option_client_id
;
97 .message
.op
= BOOTREQUEST
,
98 .message
.htype
= ARPHRD_ETHER
,
99 .message
.hlen
= ETHER_ADDR_LEN
,
100 .message
.xid
= htobe32(0x12345678),
101 .message
.chaddr
= { 'A', 'B', 'C', 'D', 'E', 'F' },
102 .option_type
.code
= SD_DHCP_OPTION_MESSAGE_TYPE
,
103 .option_type
.length
= 1,
104 .option_type
.type
= DHCP_DISCOVER
,
105 .end
= SD_DHCP_OPTION_END
,
107 struct in_addr address_lo
= {
108 .s_addr
= htonl(INADDR_LOOPBACK
),
111 assert_se(sd_dhcp_server_new(&server
, 1) >= 0);
112 assert_se(sd_dhcp_server_configure_pool(server
, &address_lo
, 8, 0, 0) >= 0);
113 assert_se(sd_dhcp_server_attach_event(server
, NULL
, 0) >= 0);
114 assert_se(sd_dhcp_server_start(server
) >= 0);
116 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_OFFER
);
119 /* TODO, shouldn't this fail? */
120 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_OFFER
);
121 test
.end
= SD_DHCP_OPTION_END
;
122 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_OFFER
);
124 test
.option_type
.code
= 0;
125 test
.option_type
.length
= 0;
126 test
.option_type
.type
= 0;
127 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
128 test
.option_type
.code
= SD_DHCP_OPTION_MESSAGE_TYPE
;
129 test
.option_type
.length
= 1;
130 test
.option_type
.type
= DHCP_DISCOVER
;
131 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_OFFER
);
134 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
135 test
.message
.op
= BOOTREQUEST
;
136 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_OFFER
);
138 test
.message
.htype
= 0;
139 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
140 test
.message
.htype
= ARPHRD_ETHER
;
141 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_OFFER
);
143 test
.message
.hlen
= 0;
144 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
145 test
.message
.hlen
= ETHER_ADDR_LEN
;
146 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_OFFER
);
148 test
.option_type
.type
= DHCP_REQUEST
;
149 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
150 test
.option_requested_ip
.code
= SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
;
151 test
.option_requested_ip
.length
= 4;
152 test
.option_requested_ip
.address
= htobe32(0x12345678);
153 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_NAK
);
154 test
.option_server_id
.code
= SD_DHCP_OPTION_SERVER_IDENTIFIER
;
155 test
.option_server_id
.length
= 4;
156 test
.option_server_id
.address
= htobe32(INADDR_LOOPBACK
);
157 test
.option_requested_ip
.address
= htobe32(INADDR_LOOPBACK
+ 3);
158 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_ACK
);
160 test
.option_server_id
.address
= htobe32(0x12345678);
161 test
.option_requested_ip
.address
= htobe32(INADDR_LOOPBACK
+ 3);
162 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
163 test
.option_server_id
.address
= htobe32(INADDR_LOOPBACK
);
164 test
.option_requested_ip
.address
= htobe32(INADDR_LOOPBACK
+ 4);
165 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
166 test
.option_requested_ip
.address
= htobe32(INADDR_LOOPBACK
+ 3);
167 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_ACK
);
169 test
.option_client_id
.code
= SD_DHCP_OPTION_CLIENT_IDENTIFIER
;
170 test
.option_client_id
.length
= 7;
171 test
.option_client_id
.id
[0] = 0x01;
172 test
.option_client_id
.id
[1] = 'A';
173 test
.option_client_id
.id
[2] = 'B';
174 test
.option_client_id
.id
[3] = 'C';
175 test
.option_client_id
.id
[4] = 'D';
176 test
.option_client_id
.id
[5] = 'E';
177 test
.option_client_id
.id
[6] = 'F';
178 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_ACK
);
180 test
.option_requested_ip
.address
= htobe32(INADDR_LOOPBACK
+ 30);
181 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
184 static uint64_t client_id_hash_helper(DHCPClientId
*id
, uint8_t key
[HASH_KEY_SIZE
]) {
185 struct siphash state
;
187 siphash24_init(&state
, key
);
188 client_id_hash_func(id
, &state
);
190 return htole64(siphash24_finalize(&state
));
193 static void test_client_id_hash(void) {
199 uint8_t hash_key
[HASH_KEY_SIZE
] = {
200 '0', '1', '2', '3', '4', '5', '6', '7',
201 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
204 a
.data
= (uint8_t*)strdup("abcd");
205 b
.data
= (uint8_t*)strdup("abcd");
207 assert_se(client_id_compare_func(&a
, &b
) == 0);
208 assert_se(client_id_hash_helper(&a
, hash_key
) == client_id_hash_helper(&b
, hash_key
));
210 assert_se(client_id_compare_func(&a
, &b
) != 0);
212 assert_se(client_id_compare_func(&a
, &b
) == 0);
213 assert_se(client_id_hash_helper(&a
, hash_key
) == client_id_hash_helper(&b
, hash_key
));
216 assert_se(client_id_compare_func(&a
, &b
) != 0);
218 assert_se(client_id_compare_func(&a
, &b
) == 0);
219 assert_se(client_id_hash_helper(&a
, hash_key
) == client_id_hash_helper(&b
, hash_key
));
222 b
.data
= (uint8_t*)strdup("abce");
223 assert_se(client_id_compare_func(&a
, &b
) != 0);
229 int main(int argc
, char *argv
[]) {
230 _cleanup_(sd_event_unrefp
) sd_event
*e
;
233 log_set_max_level(LOG_DEBUG
);
234 log_parse_environment();
237 assert_se(sd_event_new(&e
) >= 0);
243 test_message_handler();
244 test_client_id_hash();