return 0;
}
-int sd_dhcp_server_set_address(sd_dhcp_server *server, struct in_addr *address) {
+int sd_dhcp_server_set_address(sd_dhcp_server *server, struct in_addr *address, unsigned char prefixlen) {
assert_return(server, -EINVAL);
assert_return(address, -EINVAL);
assert_return(address->s_addr, -EINVAL);
+ assert_return(prefixlen <= 32, -ERANGE);
assert_return(server->address == htobe32(INADDR_ANY), -EBUSY);
+ assert_return(server->netmask == htobe32(INADDR_ANY), -EBUSY);
server->address = address->s_addr;
+ server->netmask = htobe32(0xfffffffflu << (32 - prefixlen));
return 0;
}
server->fd_raw = -1;
server->fd = -1;
server->address = htobe32(INADDR_ANY);
+ server->netmask = htobe32(INADDR_ANY);
server->index = ifindex;
server->leases_by_client_id = hashmap_new(client_id_hash_func, client_id_compare_func);
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);
if (r < 0)
return r;
+ r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
+ DHCP_OPTION_SUBNET_MASK, 4, &server->netmask);
+ if (r < 0)
+ return r;
+
+ r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
+ DHCP_OPTION_ROUTER, 4, &server->address);
+ if (r < 0)
+ return r;
+
r = dhcp_server_send_packet(server, req, packet, DHCP_OFFER, offset);
if (r < 0)
return r;
if (r < 0)
return r;
+ r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
+ DHCP_OPTION_SUBNET_MASK, 4, &server->netmask);
+ if (r < 0)
+ return r;
+
+ r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
+ DHCP_OPTION_ROUTER, 4, &server->address);
+ if (r < 0)
+ return r;
+
r = dhcp_server_send_packet(server, req, packet, DHCP_ACK, offset);
if (r < 0)
return r;
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;
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);
return 0;
}
+
+int sd_dhcp_server_forcerenew(sd_dhcp_server *server) {
+ unsigned i;
+ int r = 0;
+
+ 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;
+}