[systemd-devel] [PATCH 10/17] sd-dhcp-server: add basic DISCOVER/OFFER support
Zbigniew Jędrzejewski-Szmek
zbyszek at in.waw.pl
Tue May 27 08:41:34 PDT 2014
On Mon, May 26, 2014 at 09:39:39PM +0200, Tom Gundersen wrote:
> ---
> src/libsystemd-network/sd-dhcp-server.c | 81 ++++++++++++++++++++++++++++++-
> src/libsystemd-network/test-dhcp-server.c | 14 +++---
> 2 files changed, 86 insertions(+), 9 deletions(-)
>
> diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c
> index cea7390..be6938b 100644
> --- a/src/libsystemd-network/sd-dhcp-server.c
> +++ b/src/libsystemd-network/sd-dhcp-server.c
> @@ -27,6 +27,8 @@
> #include "dhcp-server-internal.h"
> #include "dhcp-internal.h"
>
> +#define DHCP_DEFAULT_LEASE_TIME 60
> +
> int sd_dhcp_server_set_address(sd_dhcp_server *server, struct in_addr *address) {
> assert_return(server, -EINVAL);
> assert_return(address, -EINVAL);
> @@ -277,6 +279,64 @@ int dhcp_server_send_packet(sd_dhcp_server *server,
> sizeof(DHCPPacket) + optoffset);
> }
>
> +static int server_message_init(sd_dhcp_server *server, DHCPPacket **ret,
> + uint8_t type, size_t *_optoffset, DHCPRequest *req) {
> + _cleanup_free_ DHCPPacket *packet = NULL;
> + size_t optoffset;
> + int r;
> +
> + assert(server);
> + assert(ret);
> + assert(_optoffset);
> + assert(type == DHCP_OFFER);
> +
> + packet = malloc0(sizeof(DHCPPacket) + req->max_optlen);
> + if (!packet)
> + return -ENOMEM;
> +
> + r = dhcp_message_init(&packet->dhcp, BOOTREPLY, be32toh(req->message->xid),
> + type, req->max_optlen, &optoffset);
> + if (r < 0)
> + return r;
> +
> + packet->dhcp.flags = req->message->flags;
> + packet->dhcp.giaddr = req->message->giaddr;
> + memcpy(&packet->dhcp.chaddr, &req->message->chaddr, ETH_ALEN);
> +
> + *_optoffset = optoffset;
> + *ret = packet;
> + packet = NULL;
> +
> + return 0;
> +}
> +
> +static int server_send_offer(sd_dhcp_server *server, DHCPRequest *req) {
> + _cleanup_free_ DHCPPacket *packet = NULL;
> + size_t offset;
> + be32_t lease_time;
> + int r;
> +
> + r = server_message_init(server, &packet, DHCP_OFFER, &offset, req);
> + if (r < 0)
> + return r;
> +
> + /* for now offer a random IP */
> + packet->dhcp.yiaddr = random_u32();
> +
> + /* for ten seconds */
The comment appears to be out of date already, it's 60 :)
> + lease_time = htobe32(DHCP_DEFAULT_LEASE_TIME);
> + r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
> + DHCP_OPTION_IP_ADDRESS_LEASE_TIME, 4, &lease_time);
> + if (r < 0)
> + return r;
> +
> + r = dhcp_server_send_packet(server, req, packet, DHCP_OFFER, offset);
> + if (r < 0)
> + return r;
> +
> + return 0;
> +}
> +
> static int parse_request(uint8_t code, uint8_t len, const uint8_t *option,
> void *user_data) {
> DHCPRequest *req = user_data;
> @@ -377,9 +437,26 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
> /* this only fails on critical errors */
> return r;
>
> - log_dhcp_server(server, "received message of type %d", type);
> + switch(type) {
> + case DHCP_DISCOVER:
> + log_dhcp_server(server, "DISCOVER (0x%x)",
> + be32toh(req->message->xid));
> +
> + r = server_send_offer(server, req);
> + if (r < 0) {
> + log_dhcp_server(server, "could not send offer: %s",
> + strerror(-r));
The error is logged at debug level, but otherwise ignored. Is this enough? It seems that if
server_send_offer() fails, things are significantly off.
> + return 0;
> + } else {
> + log_dhcp_server(server, "OFFER (0x%x)",
> + be32toh(req->message->xid));
> + return DHCP_OFFER;
> + }
> +
> + break;
> + }
>
> - return 1;
> + return 0;
> }
>
> static int server_receive_message(sd_event_source *s, int fd,
> diff --git a/src/libsystemd-network/test-dhcp-server.c b/src/libsystemd-network/test-dhcp-server.c
> index 0cbb4df..ed3aaf9 100644
> --- a/src/libsystemd-network/test-dhcp-server.c
> +++ b/src/libsystemd-network/test-dhcp-server.c
> @@ -94,13 +94,13 @@ static void test_message_handler(void) {
> assert_se(sd_dhcp_server_attach_event(server, NULL, 0) >= 0);
> assert_se(sd_dhcp_server_start(server) >= 0);
>
> - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 1);
> + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
>
> test.end = 0;
> /* TODO, shouldn't this fail? */
> - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 1);
> + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
> test.end = DHCP_OPTION_END;
> - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 1);
> + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
>
> test.option_type.code = 0;
> test.option_type.length = 0;
> @@ -109,22 +109,22 @@ static void test_message_handler(void) {
> test.option_type.code = DHCP_OPTION_MESSAGE_TYPE;
> test.option_type.length = 1;
> test.option_type.type = DHCP_DISCOVER;
> - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 1);
> + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
>
> test.message.op = 0;
> assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
> test.message.op = BOOTREQUEST;
> - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 1);
> + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
>
> test.message.htype = 0;
> assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
> test.message.htype = ARPHRD_ETHER;
> - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 1);
> + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
>
> test.message.hlen = 0;
> assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 0);
> test.message.hlen = ETHER_ADDR_LEN;
> - assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == 1);
> + assert_se(dhcp_server_handle_message(server, (DHCPMessage*)&test, sizeof(test)) == DHCP_OFFER);
> }
Zbyszek
More information about the systemd-devel
mailing list