1
0
mirror of https://github.com/systemd/systemd.git synced 2025-01-03 05:18:09 +03:00

test-dhcp-client: add test for bootp clients

Verify that BOOTP replies are successfully handled by the sd-dhcp-client
when configured for BOOTP.
This commit is contained in:
Colin Foster 2024-10-28 19:50:06 -05:00 committed by Avram Dorfman
parent 83cd170172
commit a40038c28a

View File

@ -35,6 +35,14 @@ static struct hw_addr_data hw_addr = {
};
typedef int (*test_callback_recv_t)(size_t size, DHCPMessage *dhcp);
struct bootp_addr_data {
uint8_t *offer_buf;
int offer_len;
int netmask_offset;
int ip_offset;
};
struct bootp_addr_data *bootp_test_context;
static bool verbose = true;
static int test_fd[2];
static test_callback_recv_t callback_recv;
@ -532,6 +540,204 @@ static void test_addr_acq(sd_event *e) {
xid = 0;
}
static uint8_t test_addr_bootp_reply[] = {
0x45, 0x00, 0x01, 0x48, 0x00, 0x00, 0x40, 0x00,
0xff, 0x11, 0x70, 0xa3, 0x0a, 0x00, 0x00, 0x02,
0xff, 0xff, 0xff, 0xff, 0x00, 0x43, 0x00, 0x44,
0x01, 0x2c, 0x2b, 0x91, 0x02, 0x01, 0x06, 0x00,
0x69, 0xd3, 0x79, 0x11, 0x17, 0x00, 0x80, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0a, 0x46, 0x00, 0x02,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x50, 0x2d, 0xf4, 0x1f, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x63, 0x82, 0x53, 0x63, 0x01, 0x04, 0xff, 0x00,
0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
static uint8_t test_addr_bootp_reply_bootpd[] = {
0x45, 0x00, 0x01, 0x48, 0xbe, 0xad, 0x40, 0x00,
0x40, 0x11, 0x73, 0x43, 0xc0, 0xa8, 0x43, 0x31,
0xc0, 0xa8, 0x43, 0x32, 0x00, 0x43, 0x00, 0x44,
0x01, 0x34, 0x08, 0xfa, 0x02, 0x01, 0x06, 0x00,
0x82, 0x57, 0xda, 0xf1, 0x00, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x43, 0x32,
0xc0, 0xa8, 0x43, 0x31, 0x00, 0x00, 0x00, 0x00,
0xc2, 0x3e, 0xa5, 0x53, 0x57, 0x72, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x64, 0x65, 0x62, 0x69, 0x61, 0x6e, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x63, 0x82, 0x53, 0x63, 0x01, 0x04, 0xff, 0xff,
0xff, 0xf0, 0x03, 0x04, 0xc0, 0xa8, 0x43, 0x31,
0x06, 0x04, 0x0a, 0x00, 0x01, 0x01, 0x0c, 0x15,
0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2d, 0x64,
0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x2d, 0x74,
0x72, 0x69, 0x78, 0x69, 0x65, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static struct bootp_addr_data bootp_addr_data[] = {
{
.offer_buf = test_addr_bootp_reply,
.offer_len = sizeof(test_addr_bootp_reply),
.netmask_offset = 270,
.ip_offset = 44,
},
{
.offer_buf = test_addr_bootp_reply_bootpd,
.offer_len = sizeof(test_addr_bootp_reply_bootpd),
.netmask_offset = 270,
.ip_offset = 44,
},
};
static int test_bootp_acquired(sd_dhcp_client *client, int event,
void *userdata) {
sd_event *e = userdata;
sd_dhcp_lease *lease;
struct in_addr addr;
assert_se(client);
assert_se(IN_SET(event, SD_DHCP_CLIENT_EVENT_IP_ACQUIRE, SD_DHCP_CLIENT_EVENT_SELECTING));
assert_se(sd_dhcp_client_get_lease(client, &lease) >= 0);
assert_se(lease);
assert_se(sd_dhcp_lease_get_address(lease, &addr) >= 0);
assert_se(memcmp(&addr.s_addr, &bootp_test_context->offer_buf[bootp_test_context->ip_offset],
sizeof(addr.s_addr)) == 0);
assert_se(sd_dhcp_lease_get_netmask(lease, &addr) >= 0);
assert_se(memcmp(&addr.s_addr, &bootp_test_context->offer_buf[bootp_test_context->netmask_offset],
sizeof(addr.s_addr)) == 0);
if (verbose)
log_info(" BOOTP address acquired");
sd_event_exit(e, 0);
return 0;
}
static int test_bootp_recv_request(size_t size, DHCPMessage *request) {
uint16_t udp_check = 0;
int res;
xid = request->xid;
if (verbose)
log_info(" recv BOOTP Request 0x%08x", be32toh(xid));
callback_recv = NULL;
memcpy(&bootp_test_context->offer_buf[26], &udp_check, sizeof(udp_check));
memcpy(&bootp_test_context->offer_buf[32], &xid, sizeof(xid));
memcpy(&bootp_test_context->offer_buf[56], hw_addr.bytes, hw_addr.length);
res = write(test_fd[1], bootp_test_context->offer_buf,
bootp_test_context->offer_len);
assert_se(res == bootp_test_context->offer_len);
if (verbose)
log_info(" sent BOOTP Reply");
return 0;
};
static void test_acquire_bootp(sd_event *e) {
sd_dhcp_client *client;
int res, r;
if (verbose)
log_info("* %s", __func__);
r = sd_dhcp_client_new(&client, false);
assert_se(r >= 0);
assert_se(client);
r = sd_dhcp_client_attach_event(client, e, 0);
assert_se(r >= 0);
r = sd_dhcp_client_set_bootp(client, true);
assert_se(r >= 0);
assert_se(sd_dhcp_client_set_ifindex(client, 42) >= 0);
assert_se(sd_dhcp_client_set_mac(client, hw_addr.bytes, bcast_addr.bytes, hw_addr.length, ARPHRD_ETHER) >= 0);
assert_se(sd_dhcp_client_set_callback(client, test_bootp_acquired, e) >= 0);
callback_recv = test_bootp_recv_request;
assert_se(sd_event_add_time_relative(e, NULL, CLOCK_BOOTTIME,
30 * USEC_PER_SEC, 0,
NULL, INT_TO_PTR(-ETIMEDOUT)) >= 0);
res = sd_dhcp_client_start(client);
assert_se(IN_SET(res, 0, -EINPROGRESS));
assert_se(sd_event_loop(e) >= 0);
assert_se(sd_dhcp_client_set_callback(client, NULL, NULL) >= 0);
assert_se(sd_dhcp_client_stop(client) >= 0);
sd_dhcp_client_unref(client);
test_fd[1] = safe_close(test_fd[1]);
callback_recv = NULL;
xid = 0;
}
int main(int argc, char *argv[]) {
_cleanup_(sd_event_unrefp) sd_event *e;
@ -549,6 +755,13 @@ int main(int argc, char *argv[]) {
test_discover_message(e);
test_addr_acq(e);
for (size_t i = 0; i < sizeof(bootp_addr_data) / sizeof(bootp_addr_data[0]); i++) {
sd_event_unref(e);
assert_se(sd_event_new(&e) >= 0);
bootp_test_context = &bootp_addr_data[i];
test_acquire_bootp(e);
}
#if HAVE_VALGRIND_VALGRIND_H
/* Make sure the async_close thread has finished.
* valgrind would report some of the phread_* structures