[systemd-devel] [PATCH 10/17] sd-dhcp-server: add basic DISCOVER/OFFER support
Tom Gundersen
teg at jklm.no
Tue May 27 08:55:57 PDT 2014
On Tue, May 27, 2014 at 5:41 PM, Zbigniew Jędrzejewski-Szmek
<zbyszek at in.waw.pl> wrote:
> 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 :)
Ha, indeed. I started out with 10 seconds, but watching wireshark was
not possible at that speed :)
>> + 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.
Hm, yes, you are right. We should just make sure that
server_send_offer can only fail with critical errors and then return r
here (same goes for the other server_send_*() methods later in the
patches.
>> + 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