X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Flibsystemd-network%2Fsd-dhcp-server.c;h=2d3eaa35e396c245fe5b1e0369f73decc44dc178;hp=55a8fbe005bc78f6e3f56144a8e736332d9c9031;hb=c15fb62a731f1a457af94e60ac6a4d23f219a8f6;hpb=d6bd972d061af306ede2affd2c9340a1660f7996 diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index 55a8fbe00..2d3eaa35e 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -29,7 +29,7 @@ #include "dhcp-server-internal.h" #include "dhcp-internal.h" -#define DHCP_DEFAULT_LEASE_TIME 60 +#define DHCP_DEFAULT_LEASE_TIME 3600 /* one hour */ int sd_dhcp_server_set_lease_pool(sd_dhcp_server *server, struct in_addr *address, size_t size) { @@ -62,6 +62,12 @@ int sd_dhcp_server_set_address(sd_dhcp_server *server, struct in_addr *address) return 0; } +bool sd_dhcp_server_is_running(sd_dhcp_server *server) { + assert_return(server, -EINVAL); + + return !!server->receive_message; +} + sd_dhcp_server *sd_dhcp_server_ref(sd_dhcp_server *server) { if (server) assert_se(REFCNT_INC(server->n_ref) >= 2); @@ -356,7 +362,7 @@ int dhcp_server_send_packet(sd_dhcp_server *server, 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; + size_t optoffset = 0; int r; assert(server); @@ -450,6 +456,41 @@ 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); + 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; @@ -703,12 +744,14 @@ 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; - r = sd_event_now(server->event, CLOCK_MONOTONIC, &time_now); + r = sd_event_now(server->event, clock_boottime_or_monotonic(), &time_now); if (r < 0) - time_now = now(CLOCK_MONOTONIC); + time_now = now(clock_boottime_or_monotonic()); lease->expiration = req->lifetime * USEC_PER_SEC + time_now; r = server_send_ack(server, req, address); @@ -873,3 +916,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; +}