1
0
mirror of https://github.com/systemd/systemd.git synced 2024-10-26 08:55:40 +03:00

network/dhcpv4: add ability to use BOOTP

BOOTP can be used to sign a static IP to clients. Instead of using the
four message exchange, and Option 53 (DHCP Message Type) there is only a
two message exchange.

Add the following network option to enable BOOTP:

[DHCPv4]
Bootp=yes

This will allow a two message request / reply sequence that doesn't
require DHCP message types.
This commit is contained in:
Colin Foster 2024-10-22 13:26:36 -05:00
parent 6d6048b4cb
commit fff2138a9a
8 changed files with 84 additions and 25 deletions

View File

@ -14,19 +14,13 @@
#define DHCP_CLIENT_MIN_OPTIONS_SIZE 312
int dhcp_message_init(
int bootp_message_init(
DHCPMessage *message,
uint8_t op,
uint32_t xid,
uint8_t type,
uint16_t arp_type,
uint8_t hlen,
const uint8_t *chaddr,
size_t optlen,
size_t *optoffset) {
size_t offset = 0;
int r;
const uint8_t *chaddr) {
assert(IN_SET(op, BOOTREQUEST, BOOTREPLY));
assert(chaddr || hlen == 0);
@ -51,6 +45,27 @@ int dhcp_message_init(
message->xid = htobe32(xid);
message->magic = htobe32(DHCP_MAGIC_COOKIE);
return 0;
}
int dhcp_message_init(
DHCPMessage *message,
uint8_t op,
uint32_t xid,
uint8_t type,
uint16_t arp_type,
uint8_t hlen,
const uint8_t *chaddr,
size_t optlen,
size_t *optoffset) {
size_t offset = 0;
int r;
r = bootp_message_init(message, op, xid, arp_type, hlen, chaddr);
if (r < 0)
return r;
r = dhcp_option_append(message, optlen, &offset, 0,
SD_DHCP_OPTION_MESSAGE_TYPE, 1, &type);
if (r < 0)

View File

@ -6,6 +6,14 @@
#include "dhcp-protocol.h"
int bootp_message_init(
DHCPMessage *message,
uint8_t op,
uint32_t xid,
uint16_t arp_type,
uint8_t hlen,
const uint8_t *chaddr);
int dhcp_message_init(
DHCPMessage *message,
uint8_t op,

View File

@ -105,6 +105,7 @@ struct sd_dhcp_client {
int socket_priority;
bool socket_priority_set;
bool ipv6_acquired;
bool bootp;
};
static const uint8_t default_req_opts[] = {
@ -656,6 +657,15 @@ int sd_dhcp_client_set_fallback_lease_lifetime(sd_dhcp_client *client, uint64_t
return 0;
}
int sd_dhcp_client_set_bootp(sd_dhcp_client *client, bool bootp) {
assert_return(client, -EINVAL);
assert_return(!sd_dhcp_client_is_running(client), -EBUSY);
client->bootp = bootp;
return 0;
}
static void client_set_state(sd_dhcp_client *client, DHCPState state) {
assert(client);
@ -793,9 +803,15 @@ static int client_message_init(
if (!packet)
return -ENOMEM;
if (client->bootp) {
r = bootp_message_init(&packet->dhcp, BOOTREQUEST, client->xid, client->arp_type,
client->hw_addr.length, client->hw_addr.bytes);
} else {
r = dhcp_message_init(&packet->dhcp, BOOTREQUEST, client->xid, type,
client->arp_type, client->hw_addr.length, client->hw_addr.bytes,
optlen, &optoffset);
}
if (r < 0)
return r;
@ -825,6 +841,7 @@ static int client_message_init(
if (client->request_broadcast || client->arp_type != ARPHRD_ETHER)
packet->dhcp.flags = htobe16(0x8000);
if (!client->bootp) {
/* Some DHCP servers will refuse to issue an DHCP lease if the Client
Identifier option is not set */
r = dhcp_option_append(&packet->dhcp, optlen, &optoffset, 0,
@ -833,6 +850,7 @@ static int client_message_init(
client->client_id.raw);
if (r < 0)
return r;
}
/* RFC2131 section 3.5:
in its initial DHCPDISCOVER or DHCPREQUEST message, a
@ -1509,13 +1527,15 @@ static int client_parse_message(
}
r = dhcp_option_parse(message, len, dhcp_lease_parse_options, lease, &error_message);
if (r < 0)
if (r == -ENOMSG && client->bootp)
log_dhcp_client(client, "No DHCP options found in bootp message, continuing.");
else if (r < 0)
return log_dhcp_client_errno(client, r, "Failed to parse DHCP options, ignoring: %m");
switch (client->state) {
case DHCP_STATE_SELECTING:
if (r == DHCP_ACK) {
if (!client->rapid_commit)
if (!client->rapid_commit && !client->bootp)
return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(ENOMSG),
"received unexpected ACK, ignoring.");
if (!lease->rapid_commit)
@ -1532,6 +1552,9 @@ static int client_parse_message(
if (lease->lifetime == 0 && client->fallback_lease_lifetime > 0)
lease->lifetime = client->fallback_lease_lifetime;
} else
if (client->bootp)
log_dhcp_client(client, "Ignoring return value %d for bootp message", r);
else
return log_dhcp_client_errno(client, SYNTHETIC_ERRNO(ENOMSG),
"received unexpected message, ignoring.");
@ -1561,6 +1584,9 @@ static int client_parse_message(
lease->next_server = message->siaddr;
lease->address = message->yiaddr;
if (client->bootp)
lease->lifetime = USEC_INFINITY;
if (lease->address == 0 ||
lease->server_address == 0 ||
lease->lifetime == 0)
@ -1601,7 +1627,7 @@ static int client_handle_offer_or_rapid_ack(sd_dhcp_client *client, DHCPMessage
dhcp_lease_unref_and_replace(client->lease, lease);
if (client->lease->rapid_commit) {
if (client->lease->rapid_commit || client->bootp) {
log_dhcp_client(client, "ACK");
return SD_DHCP_CLIENT_EVENT_IP_ACQUIRE;
}
@ -2007,7 +2033,7 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, s
if (r < 0)
return 0; /* invalid message, let's ignore it */
if (client->lease->rapid_commit)
if (client->lease->rapid_commit || client->bootp)
/* got a successful rapid commit */
return client_enter_bound(client, r);

View File

@ -1485,6 +1485,10 @@ static int dhcp4_configure(Link *link) {
if (r < 0)
return log_link_debug_errno(link, r, "DHCPv4 CLIENT: Failed to allocate DHCPv4 client: %m");
r = sd_dhcp_client_set_bootp(link->dhcp_client, link->network->dhcp_send_bootp);
if (r < 0)
return log_link_debug_errno(link, r, "DHCPv4 CLIENT: Failed to set BOOTP flag: %m");
r = sd_dhcp_client_attach_event(link->dhcp_client, link->manager->event, 0);
if (r < 0)
return log_link_debug_errno(link, r, "DHCPv4 CLIENT: Failed to attach event to DHCPv4 client: %m");

View File

@ -243,6 +243,7 @@ DHCPv4.QuickAck, config_parse_bool,
DHCPv4.RequestOptions, config_parse_dhcp_request_options, AF_INET, 0
DHCPv4.Anonymize, config_parse_bool, 0, offsetof(Network, dhcp_anonymize)
DHCPv4.SendHostname, config_parse_dhcp_send_hostname, AF_INET, 0
DHCPv4.Bootp, config_parse_bool, 0, offsetof(Network, dhcp_send_bootp)
DHCPv4.Hostname, config_parse_hostname, 0, offsetof(Network, dhcp_hostname)
DHCPv4.Label, config_parse_dhcp_label, 0, offsetof(Network, dhcp_label)
DHCPv4.RequestBroadcast, config_parse_tristate, 0, offsetof(Network, dhcp_broadcast)

View File

@ -405,6 +405,7 @@ int network_load_one(Manager *manager, OrderedHashmap **networks, const char *fi
.dhcp_broadcast = -1,
.dhcp_ipv6_only_mode = -1,
.dhcp_6rd_prefix_route_type = RTN_UNREACHABLE,
.dhcp_send_bootp = false,
.dhcp6_use_address = true,
.dhcp6_use_pd_prefix = true,

View File

@ -179,6 +179,7 @@ struct Network {
OrderedHashmap *dhcp_client_send_vendor_options;
char *dhcp_netlabel;
NFTSetContext dhcp_nft_set_context;
bool dhcp_send_bootp;
/* DHCPv6 Client support */
bool dhcp6_use_address;

View File

@ -147,6 +147,9 @@ int sd_dhcp_client_set_socket_priority(
int sd_dhcp_client_set_fallback_lease_lifetime(
sd_dhcp_client *client,
uint64_t fallback_lease_lifetime);
int sd_dhcp_client_set_bootp(
sd_dhcp_client *client,
bool bootp);
int sd_dhcp_client_add_option(sd_dhcp_client *client, sd_dhcp_option *v);
int sd_dhcp_client_add_vendor_option(sd_dhcp_client *client, sd_dhcp_option *v);