test-dhcp-server: use sd_dhcp_message object to build test message
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
#include "dhcp-server-request.h"
|
||||
#include "fd-util.h"
|
||||
#include "iovec-util.h"
|
||||
#include "iovec-wrapper.h"
|
||||
#include "tests.h"
|
||||
|
||||
TEST(basic) {
|
||||
@@ -61,50 +62,32 @@ TEST(basic) {
|
||||
ASSERT_OK(sd_dhcp_server_start(server));
|
||||
}
|
||||
|
||||
static int process_one(sd_dhcp_server *server, sd_dhcp_message *message) {
|
||||
_cleanup_(iovw_done_free) struct iovec_wrapper iovw = {};
|
||||
ASSERT_OK(dhcp_message_build(message, &iovw));
|
||||
|
||||
_cleanup_(iovec_done) struct iovec iov = {};
|
||||
ASSERT_OK(iovw_concat(&iovw, &iov));
|
||||
return dhcp_server_process_message(server, &iov, /* mh= */ NULL);
|
||||
}
|
||||
|
||||
TEST(dhcp_server_process_message) {
|
||||
struct {
|
||||
DHCPMessageHeader header;
|
||||
struct {
|
||||
uint8_t code;
|
||||
uint8_t length;
|
||||
uint8_t type;
|
||||
} _packed_ option_type;
|
||||
struct {
|
||||
uint8_t code;
|
||||
uint8_t length;
|
||||
be32_t address;
|
||||
} _packed_ option_requested_ip;
|
||||
struct {
|
||||
uint8_t code;
|
||||
uint8_t length;
|
||||
be32_t address;
|
||||
} _packed_ option_server_id;
|
||||
struct {
|
||||
uint8_t code;
|
||||
uint8_t length;
|
||||
uint8_t id[7];
|
||||
} _packed_ option_client_id;
|
||||
struct {
|
||||
uint8_t code;
|
||||
uint8_t length;
|
||||
uint8_t hostname[6];
|
||||
} _packed_ option_hostname;
|
||||
uint8_t end;
|
||||
} _packed_ test = {
|
||||
.header.op = BOOTREQUEST,
|
||||
.header.htype = ARPHRD_ETHER,
|
||||
.header.hlen = ETHER_ADDR_LEN,
|
||||
.header.xid = htobe32(0x12345678),
|
||||
.header.chaddr = { 'A', 'B', 'C', 'D', 'E', 'F' },
|
||||
.header.magic = htobe32(DHCP_MAGIC_COOKIE),
|
||||
.option_type.code = SD_DHCP_OPTION_MESSAGE_TYPE,
|
||||
.option_type.length = 1,
|
||||
.option_type.type = DHCP_DISCOVER,
|
||||
.option_hostname.code = SD_DHCP_OPTION_HOST_NAME,
|
||||
.option_hostname.length = 6,
|
||||
.option_hostname.hostname = { 'T', 'E', 'S', 'T', 'H', 'N' },
|
||||
.end = SD_DHCP_OPTION_END,
|
||||
static const struct hw_addr_data hw_addr = {
|
||||
.length = ETH_ALEN,
|
||||
.ether = {{ 'A', 'B', 'C', 'D', 'E', 'F' }},
|
||||
};
|
||||
|
||||
_cleanup_(sd_dhcp_message_unrefp) sd_dhcp_message *m = NULL;
|
||||
ASSERT_OK(dhcp_message_new(&m));
|
||||
ASSERT_OK(dhcp_message_init_header(
|
||||
m,
|
||||
BOOTREQUEST,
|
||||
0x12345678,
|
||||
ARPHRD_ETHER,
|
||||
&hw_addr));
|
||||
|
||||
ASSERT_OK(dhcp_message_append_option_hostname(m, /* flags= */ 0, /* is_client= */ false, "TESTHN"));
|
||||
|
||||
struct in_addr address_lo = {
|
||||
.s_addr = htobe32(INADDR_LOOPBACK),
|
||||
};
|
||||
@@ -132,75 +115,74 @@ TEST(dhcp_server_process_message) {
|
||||
server->socket_fd = TAKE_FD(socket_fd[0]);
|
||||
ASSERT_OK(sd_dhcp_server_start(server));
|
||||
|
||||
ASSERT_OK_EQ(dhcp_server_process_message(server, &IOVEC_MAKE(&test, sizeof(test)), NULL), DHCP_OFFER);
|
||||
ASSERT_OK(dhcp_message_append_option_u8(m, SD_DHCP_OPTION_MESSAGE_TYPE, DHCP_DISCOVER));
|
||||
ASSERT_OK_EQ(process_one(server, m), DHCP_OFFER);
|
||||
|
||||
test.end = 0;
|
||||
/* TODO, shouldn't this fail? */
|
||||
ASSERT_OK_EQ(dhcp_server_process_message(server, &IOVEC_MAKE(&test, sizeof(test)), NULL), DHCP_OFFER);
|
||||
test.end = SD_DHCP_OPTION_END;
|
||||
ASSERT_OK_EQ(dhcp_server_process_message(server, &IOVEC_MAKE(&test, sizeof(test)), NULL), DHCP_OFFER);
|
||||
/* Missing Message Type option */
|
||||
dhcp_message_remove_option(m, SD_DHCP_OPTION_MESSAGE_TYPE);
|
||||
ASSERT_ERROR(process_one(server, m), ENODATA);
|
||||
ASSERT_OK(dhcp_message_append_option_u8(m, SD_DHCP_OPTION_MESSAGE_TYPE, DHCP_DISCOVER));
|
||||
|
||||
test.option_type.code = 0;
|
||||
test.option_type.length = 0;
|
||||
test.option_type.type = 0;
|
||||
ASSERT_ERROR(dhcp_server_process_message(server, &IOVEC_MAKE(&test, sizeof(test)), NULL), ENODATA);
|
||||
test.option_type.code = SD_DHCP_OPTION_MESSAGE_TYPE;
|
||||
test.option_type.length = 1;
|
||||
test.option_type.type = DHCP_DISCOVER;
|
||||
ASSERT_OK_EQ(dhcp_server_process_message(server, &IOVEC_MAKE(&test, sizeof(test)), NULL), DHCP_OFFER);
|
||||
/* Invalid op */
|
||||
m->header.op = 0;
|
||||
ASSERT_ERROR(process_one(server, m), EBADMSG);
|
||||
m->header.op = BOOTREQUEST;
|
||||
|
||||
test.header.op = 0;
|
||||
ASSERT_ERROR(dhcp_server_process_message(server, &IOVEC_MAKE(&test, sizeof(test)), NULL), EBADMSG);
|
||||
test.header.op = BOOTREQUEST;
|
||||
ASSERT_OK_EQ(dhcp_server_process_message(server, &IOVEC_MAKE(&test, sizeof(test)), NULL), DHCP_OFFER);
|
||||
/* Invalid htype */
|
||||
m->header.htype = 0;
|
||||
ASSERT_ERROR(process_one(server, m), EBADMSG);
|
||||
m->header.htype = ARPHRD_ETHER;
|
||||
|
||||
/* Neither client ID nor hardware type is set. There is no way to manage the bound lease for the request. */
|
||||
test.header.htype = 0;
|
||||
ASSERT_ERROR(dhcp_server_process_message(server, &IOVEC_MAKE(&test, sizeof(test)), NULL), EBADMSG);
|
||||
test.header.htype = ARPHRD_ETHER;
|
||||
ASSERT_OK_EQ(dhcp_server_process_message(server, &IOVEC_MAKE(&test, sizeof(test)), NULL), DHCP_OFFER);
|
||||
/* Invalid hlen */
|
||||
m->header.hlen = 0;
|
||||
ASSERT_ERROR(process_one(server, m), EBADMSG);
|
||||
m->header.hlen = ETHER_ADDR_LEN;
|
||||
|
||||
test.header.hlen = 0;
|
||||
ASSERT_ERROR(dhcp_server_process_message(server, &IOVEC_MAKE(&test, sizeof(test)), NULL), EBADMSG);
|
||||
test.header.hlen = ETHER_ADDR_LEN;
|
||||
ASSERT_OK_EQ(dhcp_server_process_message(server, &IOVEC_MAKE(&test, sizeof(test)), NULL), DHCP_OFFER);
|
||||
/* DHCPREQUEST (init-reboot) without Requested IP Address option */
|
||||
dhcp_message_remove_option(m, SD_DHCP_OPTION_MESSAGE_TYPE);
|
||||
ASSERT_OK(dhcp_message_append_option_u8(m, SD_DHCP_OPTION_MESSAGE_TYPE, DHCP_REQUEST));
|
||||
ASSERT_ERROR(process_one(server, m), ENODATA);
|
||||
|
||||
/* DHCPREQUEST (init-boot) without requested IP */
|
||||
test.option_type.type = DHCP_REQUEST;
|
||||
ASSERT_ERROR(dhcp_server_process_message(server, &IOVEC_MAKE(&test, sizeof(test)), NULL), ENODATA);
|
||||
/* DHCPREQUEST (init-reboot) with an invalid Requested IP Address option */
|
||||
ASSERT_OK(dhcp_message_append_option_be32(m, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS, htobe32(0x12345678)));
|
||||
ASSERT_OK_EQ(process_one(server, m), DHCP_NAK);
|
||||
|
||||
test.option_requested_ip.code = SD_DHCP_OPTION_REQUESTED_IP_ADDRESS;
|
||||
test.option_requested_ip.length = 4;
|
||||
test.option_requested_ip.address = htobe32(0x12345678);
|
||||
ASSERT_OK_EQ(dhcp_server_process_message(server, &IOVEC_MAKE(&test, sizeof(test)), NULL), DHCP_NAK);
|
||||
test.option_server_id.code = SD_DHCP_OPTION_SERVER_IDENTIFIER;
|
||||
test.option_server_id.length = 4;
|
||||
test.option_server_id.address = htobe32(INADDR_LOOPBACK);
|
||||
test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3);
|
||||
ASSERT_OK_EQ(dhcp_server_process_message(server, &IOVEC_MAKE(&test, sizeof(test)), NULL), DHCP_ACK);
|
||||
/* DHCPREQUEST (selecting) with Requested IP address */
|
||||
ASSERT_OK(dhcp_message_append_option_be32(m, SD_DHCP_OPTION_SERVER_IDENTIFIER, htobe32(INADDR_LOOPBACK)));
|
||||
dhcp_message_remove_option(m, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS);
|
||||
ASSERT_OK(dhcp_message_append_option_be32(m, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS, htobe32(INADDR_LOOPBACK + 3)));
|
||||
ASSERT_OK_EQ(process_one(server, m), DHCP_ACK);
|
||||
|
||||
test.option_server_id.address = htobe32(0x12345678);
|
||||
test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3);
|
||||
ASSERT_OK_ZERO(dhcp_server_process_message(server, &IOVEC_MAKE(&test, sizeof(test)), NULL));
|
||||
test.option_server_id.address = htobe32(INADDR_LOOPBACK);
|
||||
test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 4);
|
||||
ASSERT_OK_EQ(dhcp_server_process_message(server, &IOVEC_MAKE(&test, sizeof(test)), NULL), DHCP_ACK);
|
||||
test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 3);
|
||||
ASSERT_OK_EQ(dhcp_server_process_message(server, &IOVEC_MAKE(&test, sizeof(test)), NULL), DHCP_ACK);
|
||||
/* DHCPREQUEST (selecting) with unmatching server address (silently ignored). */
|
||||
dhcp_message_remove_option(m, SD_DHCP_OPTION_SERVER_IDENTIFIER);
|
||||
ASSERT_OK(dhcp_message_append_option_be32(m, SD_DHCP_OPTION_SERVER_IDENTIFIER, htobe32(0x12345678)));
|
||||
ASSERT_OK_ZERO(process_one(server, m));
|
||||
dhcp_message_remove_option(m, SD_DHCP_OPTION_SERVER_IDENTIFIER);
|
||||
ASSERT_OK(dhcp_message_append_option_be32(m, SD_DHCP_OPTION_SERVER_IDENTIFIER, htobe32(INADDR_LOOPBACK)));
|
||||
|
||||
test.option_client_id.code = SD_DHCP_OPTION_CLIENT_IDENTIFIER;
|
||||
test.option_client_id.length = 7;
|
||||
test.option_client_id.id[0] = 0x01;
|
||||
test.option_client_id.id[1] = 'A';
|
||||
test.option_client_id.id[2] = 'B';
|
||||
test.option_client_id.id[3] = 'C';
|
||||
test.option_client_id.id[4] = 'D';
|
||||
test.option_client_id.id[5] = 'E';
|
||||
test.option_client_id.id[6] = 'F';
|
||||
ASSERT_OK_EQ(dhcp_server_process_message(server, &IOVEC_MAKE(&test, sizeof(test)), NULL), DHCP_ACK);
|
||||
/* DHCPREQUEST (selecting) with another address */
|
||||
dhcp_message_remove_option(m, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS);
|
||||
ASSERT_OK(dhcp_message_append_option_be32(m, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS, htobe32(INADDR_LOOPBACK + 4)));
|
||||
ASSERT_OK_EQ(process_one(server, m), DHCP_ACK);
|
||||
|
||||
test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 30);
|
||||
ASSERT_OK_EQ(dhcp_server_process_message(server, &IOVEC_MAKE(&test, sizeof(test)), NULL), DHCP_ACK);
|
||||
/* Request the previous address again. */
|
||||
dhcp_message_remove_option(m, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS);
|
||||
ASSERT_OK(dhcp_message_append_option_be32(m, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS, htobe32(INADDR_LOOPBACK + 3)));
|
||||
ASSERT_OK_EQ(process_one(server, m), DHCP_ACK);
|
||||
|
||||
/* With client ID */
|
||||
struct sd_dhcp_client_id client_id = {
|
||||
.size = 7,
|
||||
.id.type = 1,
|
||||
.id.eth.haddr = { 'A', 'B', 'C', 'D', 'E', 'F' },
|
||||
};
|
||||
ASSERT_OK(dhcp_message_append_option_client_id(m, &client_id));
|
||||
ASSERT_OK_EQ(process_one(server, m), DHCP_ACK);
|
||||
|
||||
/* Request a different address with client ID */
|
||||
dhcp_message_remove_option(m, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS);
|
||||
ASSERT_OK(dhcp_message_append_option_be32(m, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS, htobe32(INADDR_LOOPBACK + 30)));
|
||||
ASSERT_OK_EQ(process_one(server, m), DHCP_ACK);
|
||||
|
||||
/* add the static lease for the client ID */
|
||||
ASSERT_OK(sd_dhcp_server_stop(server));
|
||||
@@ -213,26 +195,35 @@ TEST(dhcp_server_process_message) {
|
||||
ASSERT_OK(sd_dhcp_server_start(server));
|
||||
|
||||
/* discover */
|
||||
test.option_type.type = DHCP_DISCOVER;
|
||||
ASSERT_OK_EQ(dhcp_server_process_message(server, &IOVEC_MAKE(&test, sizeof(test)), NULL), DHCP_OFFER);
|
||||
dhcp_message_remove_option(m, SD_DHCP_OPTION_MESSAGE_TYPE);
|
||||
ASSERT_OK(dhcp_message_append_option_u8(m, SD_DHCP_OPTION_MESSAGE_TYPE, DHCP_DISCOVER));
|
||||
ASSERT_OK_EQ(process_one(server, m), DHCP_OFFER);
|
||||
|
||||
/* request neither bound nor static address */
|
||||
test.option_type.type = DHCP_REQUEST;
|
||||
test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 29);
|
||||
ASSERT_OK_EQ(dhcp_server_process_message(server, &IOVEC_MAKE(&test, sizeof(test)), NULL), DHCP_NAK);
|
||||
dhcp_message_remove_option(m, SD_DHCP_OPTION_MESSAGE_TYPE);
|
||||
ASSERT_OK(dhcp_message_append_option_u8(m, SD_DHCP_OPTION_MESSAGE_TYPE, DHCP_REQUEST));
|
||||
dhcp_message_remove_option(m, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS);
|
||||
ASSERT_OK(dhcp_message_append_option_be32(m, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS, htobe32(INADDR_LOOPBACK + 29)));
|
||||
ASSERT_OK_EQ(process_one(server, m), DHCP_NAK);
|
||||
|
||||
/* request the currently assigned address */
|
||||
test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 30);
|
||||
ASSERT_OK_EQ(dhcp_server_process_message(server, &IOVEC_MAKE(&test, sizeof(test)), NULL), DHCP_NAK);
|
||||
dhcp_message_remove_option(m, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS);
|
||||
ASSERT_OK(dhcp_message_append_option_be32(m, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS, htobe32(INADDR_LOOPBACK + 30)));
|
||||
ASSERT_OK_EQ(process_one(server, m), DHCP_NAK);
|
||||
|
||||
/* request the new static address */
|
||||
test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 31);
|
||||
ASSERT_OK_EQ(dhcp_server_process_message(server, &IOVEC_MAKE(&test, sizeof(test)), NULL), DHCP_ACK);
|
||||
dhcp_message_remove_option(m, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS);
|
||||
ASSERT_OK(dhcp_message_append_option_be32(m, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS, htobe32(INADDR_LOOPBACK + 31)));
|
||||
ASSERT_OK_EQ(process_one(server, m), DHCP_ACK);
|
||||
|
||||
/* release the bound static lease */
|
||||
test.header.ciaddr = htobe32(INADDR_LOOPBACK + 31);
|
||||
test.option_type.type = DHCP_RELEASE;
|
||||
ASSERT_OK_ZERO(dhcp_server_process_message(server, &IOVEC_MAKE(&test, sizeof(test)), NULL));
|
||||
m->header.ciaddr = htobe32(INADDR_LOOPBACK + 31);
|
||||
dhcp_message_remove_option(m, SD_DHCP_OPTION_MESSAGE_TYPE);
|
||||
ASSERT_OK(dhcp_message_append_option_u8(m, SD_DHCP_OPTION_MESSAGE_TYPE, DHCP_RELEASE));
|
||||
ASSERT_OK_ZERO(process_one(server, m));
|
||||
m->header.ciaddr = 0;
|
||||
dhcp_message_remove_option(m, SD_DHCP_OPTION_MESSAGE_TYPE);
|
||||
ASSERT_OK(dhcp_message_append_option_u8(m, SD_DHCP_OPTION_MESSAGE_TYPE, DHCP_REQUEST));
|
||||
|
||||
/* drop the static lease for the client ID */
|
||||
ASSERT_OK(sd_dhcp_server_stop(server));
|
||||
@@ -245,30 +236,35 @@ TEST(dhcp_server_process_message) {
|
||||
ASSERT_OK(sd_dhcp_server_start(server));
|
||||
|
||||
/* request a new non-static address */
|
||||
test.header.ciaddr = 0;
|
||||
test.option_type.type = DHCP_REQUEST;
|
||||
test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 29);
|
||||
ASSERT_OK_EQ(dhcp_server_process_message(server, &IOVEC_MAKE(&test, sizeof(test)), NULL), DHCP_ACK);
|
||||
dhcp_message_remove_option(m, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS);
|
||||
ASSERT_OK(dhcp_message_append_option_be32(m, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS, htobe32(INADDR_LOOPBACK + 29)));
|
||||
ASSERT_OK_EQ(process_one(server, m), DHCP_ACK);
|
||||
|
||||
/* request address reserved for static lease (unmatching client ID) */
|
||||
test.option_client_id.id[6] = 'H';
|
||||
test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 42);
|
||||
ASSERT_OK_EQ(dhcp_server_process_message(server, &IOVEC_MAKE(&test, sizeof(test)), NULL), DHCP_NAK);
|
||||
client_id.id.eth.haddr[5] = 'H';
|
||||
dhcp_message_remove_option(m, SD_DHCP_OPTION_CLIENT_IDENTIFIER);
|
||||
ASSERT_OK(dhcp_message_append_option_client_id(m, &client_id));
|
||||
dhcp_message_remove_option(m, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS);
|
||||
ASSERT_OK(dhcp_message_append_option_be32(m, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS, htobe32(INADDR_LOOPBACK + 42)));
|
||||
ASSERT_OK_EQ(process_one(server, m), DHCP_NAK);
|
||||
|
||||
/* request unmatching address */
|
||||
test.option_client_id.id[6] = 'G';
|
||||
test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 41);
|
||||
ASSERT_OK_EQ(dhcp_server_process_message(server, &IOVEC_MAKE(&test, sizeof(test)), NULL), DHCP_NAK);
|
||||
client_id.id.eth.haddr[5] = 'G';
|
||||
dhcp_message_remove_option(m, SD_DHCP_OPTION_CLIENT_IDENTIFIER);
|
||||
ASSERT_OK(dhcp_message_append_option_client_id(m, &client_id));
|
||||
dhcp_message_remove_option(m, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS);
|
||||
ASSERT_OK(dhcp_message_append_option_be32(m, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS, htobe32(INADDR_LOOPBACK + 41)));
|
||||
ASSERT_OK_EQ(process_one(server, m), DHCP_NAK);
|
||||
|
||||
/* request matching address */
|
||||
test.option_client_id.id[6] = 'G';
|
||||
test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 42);
|
||||
ASSERT_OK_EQ(dhcp_server_process_message(server, &IOVEC_MAKE(&test, sizeof(test)), NULL), DHCP_ACK);
|
||||
dhcp_message_remove_option(m, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS);
|
||||
ASSERT_OK(dhcp_message_append_option_be32(m, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS, htobe32(INADDR_LOOPBACK + 42)));
|
||||
ASSERT_OK_EQ(process_one(server, m), DHCP_ACK);
|
||||
|
||||
/* try again */
|
||||
test.option_client_id.id[6] = 'G';
|
||||
test.option_requested_ip.address = htobe32(INADDR_LOOPBACK + 42);
|
||||
ASSERT_OK_EQ(dhcp_server_process_message(server, &IOVEC_MAKE(&test, sizeof(test)), NULL), DHCP_ACK);
|
||||
dhcp_message_remove_option(m, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS);
|
||||
ASSERT_OK(dhcp_message_append_option_be32(m, SD_DHCP_OPTION_REQUESTED_IP_ADDRESS, htobe32(INADDR_LOOPBACK + 42)));
|
||||
ASSERT_OK_EQ(process_one(server, m), DHCP_ACK);
|
||||
}
|
||||
|
||||
TEST(sd_dhcp_server_set_static_lease) {
|
||||
|
||||
Reference in New Issue
Block a user