1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright (C) 2013 Intel Corporation. All rights reserved.
6 Copyright (C) 2014 Tom Gundersen
11 #include "sd-dhcp-server.h"
14 #include "dhcp-server-internal.h"
16 static void test_pool(struct in_addr
*address
, unsigned size
, int ret
) {
17 _cleanup_(sd_dhcp_server_unrefp
) sd_dhcp_server
*server
= NULL
;
19 assert_se(sd_dhcp_server_new(&server
, 1) >= 0);
21 assert_se(sd_dhcp_server_configure_pool(server
, address
, 8, 0, size
) == ret
);
24 static int test_basic(sd_event
*event
) {
25 _cleanup_(sd_dhcp_server_unrefp
) sd_dhcp_server
*server
= NULL
;
26 struct in_addr address_lo
= {
27 .s_addr
= htonl(INADDR_LOOPBACK
),
29 struct in_addr address_any
= {
30 .s_addr
= htonl(INADDR_ANY
),
34 /* attach to loopback interface */
35 assert_se(sd_dhcp_server_new(&server
, 1) >= 0);
38 assert_se(sd_dhcp_server_attach_event(server
, event
, 0) >= 0);
39 assert_se(sd_dhcp_server_attach_event(server
, event
, 0) == -EBUSY
);
40 assert_se(sd_dhcp_server_get_event(server
) == event
);
41 assert_se(sd_dhcp_server_detach_event(server
) >= 0);
42 assert_se(!sd_dhcp_server_get_event(server
));
43 assert_se(sd_dhcp_server_attach_event(server
, NULL
, 0) >= 0);
44 assert_se(sd_dhcp_server_attach_event(server
, NULL
, 0) == -EBUSY
);
46 assert_se(sd_dhcp_server_ref(server
) == server
);
47 assert_se(!sd_dhcp_server_unref(server
));
49 assert_se(sd_dhcp_server_start(server
) == -EUNATCH
);
51 assert_se(sd_dhcp_server_configure_pool(server
, &address_any
, 28, 0, 0) == -EINVAL
);
52 assert_se(sd_dhcp_server_configure_pool(server
, &address_lo
, 38, 0, 0) == -ERANGE
);
53 assert_se(sd_dhcp_server_configure_pool(server
, &address_lo
, 8, 0, 0) >= 0);
54 assert_se(sd_dhcp_server_configure_pool(server
, &address_lo
, 8, 0, 0) >= 0);
56 test_pool(&address_any
, 1, -EINVAL
);
57 test_pool(&address_lo
, 1, 0);
59 r
= sd_dhcp_server_start(server
);
62 return EXIT_TEST_SKIP
;
65 assert_se(sd_dhcp_server_start(server
) == -EBUSY
);
66 assert_se(sd_dhcp_server_stop(server
) >= 0);
67 assert_se(sd_dhcp_server_stop(server
) >= 0);
68 assert_se(sd_dhcp_server_start(server
) >= 0);
73 static void test_message_handler(void) {
74 _cleanup_(sd_dhcp_server_unrefp
) sd_dhcp_server
*server
= NULL
;
81 } _packed_ option_type
;
86 } _packed_ option_requested_ip
;
91 } _packed_ option_server_id
;
96 } _packed_ option_client_id
;
99 .message
.op
= BOOTREQUEST
,
100 .message
.htype
= ARPHRD_ETHER
,
101 .message
.hlen
= ETHER_ADDR_LEN
,
102 .message
.xid
= htobe32(0x12345678),
103 .message
.chaddr
= { 'A', 'B', 'C', 'D', 'E', 'F' },
104 .option_type
.code
= SD_DHCP_OPTION_MESSAGE_TYPE
,
105 .option_type
.length
= 1,
106 .option_type
.type
= DHCP_DISCOVER
,
107 .end
= SD_DHCP_OPTION_END
,
109 struct in_addr address_lo
= {
110 .s_addr
= htonl(INADDR_LOOPBACK
),
113 assert_se(sd_dhcp_server_new(&server
, 1) >= 0);
114 assert_se(sd_dhcp_server_configure_pool(server
, &address_lo
, 8, 0, 0) >= 0);
115 assert_se(sd_dhcp_server_attach_event(server
, NULL
, 0) >= 0);
116 assert_se(sd_dhcp_server_start(server
) >= 0);
118 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_OFFER
);
121 /* TODO, shouldn't this fail? */
122 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_OFFER
);
123 test
.end
= SD_DHCP_OPTION_END
;
124 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_OFFER
);
126 test
.option_type
.code
= 0;
127 test
.option_type
.length
= 0;
128 test
.option_type
.type
= 0;
129 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
130 test
.option_type
.code
= SD_DHCP_OPTION_MESSAGE_TYPE
;
131 test
.option_type
.length
= 1;
132 test
.option_type
.type
= DHCP_DISCOVER
;
133 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_OFFER
);
136 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
137 test
.message
.op
= BOOTREQUEST
;
138 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_OFFER
);
140 test
.message
.htype
= 0;
141 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
142 test
.message
.htype
= ARPHRD_ETHER
;
143 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_OFFER
);
145 test
.message
.hlen
= 0;
146 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
147 test
.message
.hlen
= ETHER_ADDR_LEN
;
148 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_OFFER
);
150 test
.option_type
.type
= DHCP_REQUEST
;
151 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
152 test
.option_requested_ip
.code
= SD_DHCP_OPTION_REQUESTED_IP_ADDRESS
;
153 test
.option_requested_ip
.length
= 4;
154 test
.option_requested_ip
.address
= htobe32(0x12345678);
155 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_NAK
);
156 test
.option_server_id
.code
= SD_DHCP_OPTION_SERVER_IDENTIFIER
;
157 test
.option_server_id
.length
= 4;
158 test
.option_server_id
.address
= htobe32(INADDR_LOOPBACK
);
159 test
.option_requested_ip
.address
= htobe32(INADDR_LOOPBACK
+ 3);
160 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_ACK
);
162 test
.option_server_id
.address
= htobe32(0x12345678);
163 test
.option_requested_ip
.address
= htobe32(INADDR_LOOPBACK
+ 3);
164 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
165 test
.option_server_id
.address
= htobe32(INADDR_LOOPBACK
);
166 test
.option_requested_ip
.address
= htobe32(INADDR_LOOPBACK
+ 4);
167 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
168 test
.option_requested_ip
.address
= htobe32(INADDR_LOOPBACK
+ 3);
169 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_ACK
);
171 test
.option_client_id
.code
= SD_DHCP_OPTION_CLIENT_IDENTIFIER
;
172 test
.option_client_id
.length
= 7;
173 test
.option_client_id
.id
[0] = 0x01;
174 test
.option_client_id
.id
[1] = 'A';
175 test
.option_client_id
.id
[2] = 'B';
176 test
.option_client_id
.id
[3] = 'C';
177 test
.option_client_id
.id
[4] = 'D';
178 test
.option_client_id
.id
[5] = 'E';
179 test
.option_client_id
.id
[6] = 'F';
180 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == DHCP_ACK
);
182 test
.option_requested_ip
.address
= htobe32(INADDR_LOOPBACK
+ 30);
183 assert_se(dhcp_server_handle_message(server
, (DHCPMessage
*)&test
, sizeof(test
)) == 0);
186 static uint64_t client_id_hash_helper(DHCPClientId
*id
, uint8_t key
[HASH_KEY_SIZE
]) {
187 struct siphash state
;
189 siphash24_init(&state
, key
);
190 client_id_hash_func(id
, &state
);
192 return htole64(siphash24_finalize(&state
));
195 static void test_client_id_hash(void) {
201 uint8_t hash_key
[HASH_KEY_SIZE
] = {
202 '0', '1', '2', '3', '4', '5', '6', '7',
203 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
206 a
.data
= (uint8_t*)strdup("abcd");
207 b
.data
= (uint8_t*)strdup("abcd");
209 assert_se(client_id_compare_func(&a
, &b
) == 0);
210 assert_se(client_id_hash_helper(&a
, hash_key
) == client_id_hash_helper(&b
, hash_key
));
212 assert_se(client_id_compare_func(&a
, &b
) != 0);
214 assert_se(client_id_compare_func(&a
, &b
) == 0);
215 assert_se(client_id_hash_helper(&a
, hash_key
) == client_id_hash_helper(&b
, hash_key
));
218 assert_se(client_id_compare_func(&a
, &b
) != 0);
220 assert_se(client_id_compare_func(&a
, &b
) == 0);
221 assert_se(client_id_hash_helper(&a
, hash_key
) == client_id_hash_helper(&b
, hash_key
));
224 b
.data
= (uint8_t*)strdup("abce");
225 assert_se(client_id_compare_func(&a
, &b
) != 0);
231 int main(int argc
, char *argv
[]) {
232 _cleanup_(sd_event_unrefp
) sd_event
*e
;
235 log_set_max_level(LOG_DEBUG
);
236 log_parse_environment();
239 assert_se(sd_event_new(&e
) >= 0);
245 test_message_handler();
246 test_client_id_hash();