summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libsystemd-network/dhcp-server-internal.h2
-rw-r--r--src/libsystemd-network/sd-dhcp-server.c60
-rw-r--r--src/systemd/sd-dhcp-server.h2
3 files changed, 64 insertions, 0 deletions
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