break;
case SD_DHCP_OPTION_SERVER_IDENTIFIER:
if (len == 4)
- memcpy(&req->server_id, option, sizeof(be32_t));
+ memcpy(&req->server_address, option, sizeof(be32_t));
break;
case SD_DHCP_OPTION_CLIENT_IDENTIFIER:
r = dhcp_option_parse(message, length, parse_request, req, &error_message);
if (r < 0)
return r;
- int type = r;
+ req->type = r;
r = ensure_sane_request(server, req, message);
if (r < 0)
*ret = TAKE_PTR(req);
*ret_error_message = TAKE_PTR(error_message);
- return type;
+ return 0;
}
-static int dhcp_server_ack(sd_dhcp_server *server, DHCPRequest *req, be32_t address) {
- usec_t expiration;
+static int dhcp_server_ack(sd_dhcp_server *server, DHCPRequest *req) {
int r;
assert(server);
assert(req);
- assert(address != 0);
-
- r = dhcp_request_get_lifetime_timestamp(req, CLOCK_BOOTTIME, &expiration);
- if (r < 0)
- return r;
+ assert(req->address != INADDR_ANY);
- r = dhcp_server_set_lease(server, address, req, expiration);
+ r = dhcp_server_set_lease(server, req);
if (r < 0)
return log_dhcp_server_errno(server, r, "Failed to create new lease: %m");
- r = server_send_offer_or_ack(server, req, address, DHCP_ACK);
+ r = server_send_offer_or_ack(server, req, DHCP_ACK);
if (r < 0)
return log_dhcp_server_errno(server, r, "Could not send ACK: %m");
/* no pool allocated */
return 0;
- be32_t address = INADDR_ANY;
-
/* for now pick a random free address from the pool */
if (static_lease) {
sd_dhcp_server_lease *l = hashmap_get(server->bound_leases_by_address, UINT32_TO_PTR(static_lease->address));
return 0;
/* Found a matching static lease. */
- address = static_lease->address;
+ req->static_lease = static_lease;
+ req->address = static_lease->address;
} else if (existing_lease && dhcp_server_address_is_in_pool(server, existing_lease->address))
/* If we previously assigned an address to the host, then reuse it. */
- address = existing_lease->address;
+ req->address = existing_lease->address;
else {
struct siphash state;
for (unsigned i = 0; i < server->pool_size; i++) {
be32_t a = server->subnet | htobe32(server->pool_offset + (hash + i) % server->pool_size);
if (dhcp_server_address_available(server, a)) {
- address = a;
+ req->address = a;
break;
}
}
}
- if (address == INADDR_ANY)
+ if (req->address == INADDR_ANY)
/* no free addresses left */
return 0;
if (server->rapid_commit && req->rapid_commit)
- return dhcp_server_ack(server, req, address);
+ return dhcp_server_ack(server, req);
- r = server_send_offer_or_ack(server, req, address, DHCP_OFFER);
+ r = server_send_offer_or_ack(server, req, DHCP_OFFER);
if (r < 0)
/* this only fails on critical errors */
return log_dhcp_server_errno(server, r, "Could not send offer: %m");
/* see RFC 2131, section 4.3.2 */
- if (req->server_id != 0) {
+ if (req->server_address != INADDR_ANY) {
log_dhcp_server(server, "REQUEST (selecting) (0x%x)",
be32toh(req->message->xid));
/* SELECTING */
- if (req->server_id != server->address)
+ if (req->server_address != server->address)
/* client did not pick us */
return 0;
/* The requested address is already assigned to another host. Refusing. */
return server_send_nak_or_ignore(server, init_reboot, req);
+ req->static_lease = static_lease;
+ req->address = address;
+
/* Found a static lease for the client ID. */
- return dhcp_server_ack(server, req, address);
+ return dhcp_server_ack(server, req);
}
- if (dhcp_server_address_is_in_pool(server, address))
+ if (dhcp_server_address_is_in_pool(server, address)) {
/* The requested address is in the pool. */
- return dhcp_server_ack(server, req, address);
+ req->address = address;
+
+ return dhcp_server_ack(server, req);
+ }
/* Refuse otherwise. */
return server_send_nak_or_ignore(server, init_reboot, req);
r = dhcp_server_parse_message(server, message, length, &req, &error_message);
if (r < 0)
return r;
- int type = r;
dhcp_request_set_timestamp(req, timestamp);
if (r < 0)
return r;
- switch (type) {
+ switch (req->type) {
case DHCP_DISCOVER:
return dhcp_server_process_discover(server, req);
case DHCP_REQUEST:
size_t *offset,
DHCPRequest *req) {
- sd_dhcp_server_lease *static_lease;
int r;
assert(server);
assert(offset);
assert(req);
- static_lease = dhcp_server_get_static_lease(server, req);
- if (!static_lease || !static_lease->hostname)
+ if (!req->static_lease || !req->static_lease->hostname)
return 0;
- if (dns_name_is_single_label(static_lease->hostname))
+ if (dns_name_is_single_label(req->static_lease->hostname))
/* Option 12 */
return dhcp_option_append(
&packet->dhcp,
offset,
/* overload= */ 0,
SD_DHCP_OPTION_HOST_NAME,
- strlen(static_lease->hostname),
- static_lease->hostname);
+ strlen(req->static_lease->hostname),
+ req->static_lease->hostname);
/* Option 81 */
buffer[1] = 255;
buffer[2] = 255;
- r = dns_name_to_wire_format(static_lease->hostname, buffer + 3, sizeof(buffer) - 3, false);
+ r = dns_name_to_wire_format(req->static_lease->hostname, buffer + 3, sizeof(buffer) - 3, false);
if (r < 0)
return log_dhcp_server_errno(server, r, "Failed to encode FQDN for static lease: %m");
if (r > DHCP_MAX_FQDN_LENGTH)
int server_send_offer_or_ack(
sd_dhcp_server *server,
DHCPRequest *req,
- be32_t address,
uint8_t type) {
static const uint8_t option_map[_SD_DHCP_LEASE_SERVER_TYPE_MAX] = {
if (r < 0)
return r;
- packet->dhcp.yiaddr = address;
+ packet->dhcp.yiaddr = req->address;
packet->dhcp.siaddr = server->boot_server_address.s_addr;
lease_time = usec_to_be32_sec(req->lifetime);
return 0;
}
-int dhcp_server_set_lease(sd_dhcp_server *server, be32_t address, DHCPRequest *req, usec_t expiration) {
+int dhcp_server_set_lease(sd_dhcp_server *server, DHCPRequest *req) {
_cleanup_(sd_dhcp_server_lease_unrefp) sd_dhcp_server_lease *lease = NULL;
int r;
assert(server);
- assert(address != 0);
assert(req);
- assert(expiration != 0);
+ assert(req->address != INADDR_ANY);
+
+ usec_t expiration;
+ r = dhcp_request_get_lifetime_timestamp(req, CLOCK_BOOTTIME, &expiration);
+ if (r < 0)
+ return r;
/* If a lease for the host already exists, update it. */
lease = hashmap_get(server->bound_leases_by_client_id, &req->client_id);
if (lease) {
- if (lease->address != address) {
+ if (lease->address != req->address) {
hashmap_remove_value(server->bound_leases_by_address, UINT32_TO_PTR(lease->address), lease);
- lease->address = address;
+ lease->address = req->address;
r = hashmap_ensure_put(&server->bound_leases_by_address, NULL, UINT32_TO_PTR(lease->address), lease);
if (r < 0)
*lease = (sd_dhcp_server_lease) {
.n_ref = 1,
- .address = address,
+ .address = req->address,
.client_id = req->client_id,
.htype = req->message->htype,
.gateway = req->message->giaddr,