From 527503444ef24ae03c73cf85128c7acbb1146f3c Mon Sep 17 00:00:00 2001 From: Tom Gundersen Date: Sat, 26 Jul 2014 19:12:24 +0200 Subject: sd-dhcp-server: add forcerenew support --- src/libsystemd-network/dhcp-server-internal.h | 2 + src/libsystemd-network/sd-dhcp-server.c | 60 +++++++++++++++++++++++++++ src/systemd/sd-dhcp-server.h | 2 + 3 files changed, 64 insertions(+) diff --git a/src/libsystemd-network/dhcp-server-internal.h b/src/libsystemd-network/dhcp-server-internal.h index 7fe7253fdb..cdaa471b62 100644 --- a/src/libsystemd-network/dhcp-server-internal.h +++ b/src/libsystemd-network/dhcp-server-internal.h @@ -39,6 +39,8 @@ typedef struct DHCPLease { DHCPClientId client_id; be32_t address; + be32_t gateway; + uint8_t chaddr[16]; usec_t expiration; } DHCPLease; diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index bcf7d1fa2c..99b833ac6b 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -456,6 +456,39 @@ static int server_send_nak(sd_dhcp_server *server, DHCPRequest *req) { return 0; } +static int server_send_forcerenew(sd_dhcp_server *server, be32_t address, be32_t gateway, + uint8_t chaddr[]) { + _cleanup_free_ DHCPPacket *packet = NULL; + size_t optoffset = 0; + int r; + + assert(server); + assert(address != INADDR_ANY); + assert(chaddr); + + packet = malloc0(sizeof(DHCPPacket) + DHCP_MIN_OPTIONS_SIZE); + if (!packet) + return -ENOMEM; + + r = dhcp_message_init(&packet->dhcp, BOOTREPLY, 0, + DHCP_FORCERENEW, DHCP_MIN_OPTIONS_SIZE, + &optoffset); + if (r < 0) + return r; + + r = dhcp_option_append(&packet->dhcp, DHCP_MIN_OPTIONS_SIZE, + &optoffset, 0, DHCP_OPTION_END, 0, NULL); + if (r < 0) + return r; + + memcpy(&packet->dhcp.chaddr, chaddr, ETH_ALEN); + + r = dhcp_server_send_udp(server, address, &packet->dhcp, + sizeof(DHCPMessage) + optoffset); + + return 0; +} + static int parse_request(uint8_t code, uint8_t len, const uint8_t *option, void *user_data) { DHCPRequest *req = user_data; @@ -709,6 +742,8 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, return -ENOMEM; } lease->client_id.length = req->client_id.length; + memcpy(&lease->chaddr, &req->message->chaddr, ETH_ALEN); + lease->gateway = req->message->giaddr; } else lease = existing_lease; @@ -879,3 +914,28 @@ int sd_dhcp_server_start(sd_dhcp_server *server) { return 0; } + +int sd_dhcp_server_forcerenew(sd_dhcp_server *server) { + unsigned i; + int r; + + assert_return(server, -EINVAL); + assert(server->bound_leases); + + for (i = 0; i < server->pool_size; i++) { + DHCPLease *lease = server->bound_leases[i]; + + if (!lease) + continue; + + r = server_send_forcerenew(server, lease->address, + lease->gateway, + lease->chaddr); + if (r < 0) + return r; + else + log_dhcp_server(server, "FORCERENEW"); + } + + return r; +} diff --git a/src/systemd/sd-dhcp-server.h b/src/systemd/sd-dhcp-server.h index 01595d39d1..a4f7c85d6d 100644 --- a/src/systemd/sd-dhcp-server.h +++ b/src/systemd/sd-dhcp-server.h @@ -46,4 +46,6 @@ int sd_dhcp_server_stop(sd_dhcp_server *server); int sd_dhcp_server_set_address(sd_dhcp_server *server, struct in_addr *address); int sd_dhcp_server_set_lease_pool(sd_dhcp_server *server, struct in_addr *start, size_t size); + +int sd_dhcp_server_forcerenew(sd_dhcp_server *server); #endif -- cgit v1.2.3-54-g00ecf