1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2025-01-08 21:17:47 +03:00

dhcp-server: also append specified additional options and vendor specific option on DHCP_OFFER

Fixes #15780.
This commit is contained in:
Yu Watanabe 2021-03-04 17:51:25 +09:00
parent 329998b365
commit 986c0edfcb

View File

@ -425,66 +425,23 @@ static int server_message_init(sd_dhcp_server *server, DHCPPacket **ret,
return 0;
}
static int server_send_offer(sd_dhcp_server *server, DHCPRequest *req,
be32_t address) {
_cleanup_free_ DHCPPacket *packet = NULL;
size_t offset;
be32_t lease_time;
int r;
r = server_message_init(server, &packet, DHCP_OFFER, &offset, req);
if (r < 0)
return r;
packet->dhcp.yiaddr = address;
lease_time = htobe32(req->lifetime);
r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
SD_DHCP_OPTION_IP_ADDRESS_LEASE_TIME, 4,
&lease_time);
if (r < 0)
return r;
r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
SD_DHCP_OPTION_SUBNET_MASK, 4, &server->netmask);
if (r < 0)
return r;
if (server->emit_router) {
r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0,
SD_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;
return 0;
}
static int server_send_ack(
static int server_send_offer_or_ack(
sd_dhcp_server *server,
DHCPRequest *req,
be32_t address) {
static const uint8_t option_map[_SD_DHCP_LEASE_SERVER_TYPE_MAX] = {
[SD_DHCP_LEASE_DNS] = SD_DHCP_OPTION_DOMAIN_NAME_SERVER,
[SD_DHCP_LEASE_NTP] = SD_DHCP_OPTION_NTP_SERVER,
[SD_DHCP_LEASE_SIP] = SD_DHCP_OPTION_SIP_SERVER,
[SD_DHCP_LEASE_POP3] = SD_DHCP_OPTION_POP3_SERVER,
[SD_DHCP_LEASE_SMTP] = SD_DHCP_OPTION_SMTP_SERVER,
[SD_DHCP_LEASE_LPR] = SD_DHCP_OPTION_LPR_SERVER,
};
be32_t address,
uint8_t type) {
_cleanup_free_ DHCPPacket *packet = NULL;
be32_t lease_time;
sd_dhcp_option *j;
be32_t lease_time;
size_t offset;
int r;
r = server_message_init(server, &packet, DHCP_ACK, &offset, req);
assert(server);
assert(req);
assert(IN_SET(type, DHCP_OFFER, DHCP_ACK));
r = server_message_init(server, &packet, type, &offset, req);
if (r < 0)
return r;
@ -509,27 +466,38 @@ static int server_send_ack(
return r;
}
for (sd_dhcp_lease_server_type_t k = 0; k < _SD_DHCP_LEASE_SERVER_TYPE_MAX; k++) {
if (type == DHCP_ACK) {
static const uint8_t option_map[_SD_DHCP_LEASE_SERVER_TYPE_MAX] = {
[SD_DHCP_LEASE_DNS] = SD_DHCP_OPTION_DOMAIN_NAME_SERVER,
[SD_DHCP_LEASE_NTP] = SD_DHCP_OPTION_NTP_SERVER,
[SD_DHCP_LEASE_SIP] = SD_DHCP_OPTION_SIP_SERVER,
[SD_DHCP_LEASE_POP3] = SD_DHCP_OPTION_POP3_SERVER,
[SD_DHCP_LEASE_SMTP] = SD_DHCP_OPTION_SMTP_SERVER,
[SD_DHCP_LEASE_LPR] = SD_DHCP_OPTION_LPR_SERVER,
};
if (server->servers[k].size <= 0)
continue;
for (sd_dhcp_lease_server_type_t k = 0; k < _SD_DHCP_LEASE_SERVER_TYPE_MAX; k++) {
if (server->servers[k].size <= 0)
continue;
r = dhcp_option_append(
&packet->dhcp, req->max_optlen, &offset, 0,
option_map[k],
sizeof(struct in_addr) * server->servers[k].size, server->servers[k].addr);
if (r < 0)
return r;
}
r = dhcp_option_append(
&packet->dhcp, req->max_optlen, &offset, 0,
option_map[k],
sizeof(struct in_addr) * server->servers[k].size,
server->servers[k].addr);
if (r < 0)
return r;
}
if (server->timezone) {
r = dhcp_option_append(
&packet->dhcp, req->max_optlen, &offset, 0,
SD_DHCP_OPTION_NEW_TZDB_TIMEZONE,
strlen(server->timezone), server->timezone);
if (r < 0)
return r;
if (server->timezone) {
r = dhcp_option_append(
&packet->dhcp, req->max_optlen, &offset, 0,
SD_DHCP_OPTION_NEW_TZDB_TIMEZONE,
strlen(server->timezone), server->timezone);
if (r < 0)
return r;
}
}
ORDERED_SET_FOREACH(j, server->extra_options) {
@ -548,7 +516,7 @@ static int server_send_ack(
return r;
}
r = dhcp_server_send_packet(server, req, packet, DHCP_ACK, offset);
r = dhcp_server_send_packet(server, req, packet, type, offset);
if (r < 0)
return r;
@ -783,7 +751,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
/* no free addresses left */
return 0;
r = server_send_offer(server, req, address);
r = server_send_offer_or_ack(server, req, address, DHCP_OFFER);
if (r < 0)
/* this only fails on critical errors */
return log_dhcp_server_errno(server, r, "Could not send offer: %m");
@ -886,7 +854,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
lease->expiration = req->lifetime * USEC_PER_SEC + time_now;
r = server_send_ack(server, req, address);
r = server_send_offer_or_ack(server, req, address, DHCP_ACK);
if (r < 0) {
/* this only fails on critical errors */
log_dhcp_server_errno(server, r, "Could not send ack: %m");