From 6278e42878018d66ee557e5a34f782fc9584eb68 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 7 Mar 2022 19:57:09 +0900 Subject: [PATCH] network: dhcp: rename NextServer= and Filename= settings And make the settings configures DHCP option 66 and 67. Follow-ups for #22615. Fixes #22661. --- man/systemd.network.xml | 27 +++++++++-- src/libsystemd-network/dhcp-server-internal.h | 5 +- src/libsystemd-network/sd-dhcp-server.c | 48 +++++++++++++------ src/network/networkd-dhcp-server.c | 14 ++++-- src/network/networkd-network-gperf.gperf | 5 +- src/network/networkd-network.c | 3 +- src/network/networkd-network.h | 5 +- src/systemd/sd-dhcp-server.h | 5 +- .../fuzz-network-parser/directives.network | 5 +- 9 files changed, 82 insertions(+), 35 deletions(-) diff --git a/man/systemd.network.xml b/man/systemd.network.xml index 9d4a4b3e1fc..ec270e5e962 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -2626,19 +2626,38 @@ Token=prefixstable:2002:da8:1:: - NextServer= + BootServerAddress= - Takes an IPv4 address. Configures the next server used by e.g. PXE boot systems. + Takes an IPv4 address of the boot server used by e.g. PXE boot systems. When specified, + the address is set to the siaddr field of the DHCP message header. See + RFC 2131 for more details. Defaults to unset. - Filename= + BootServerName= - Takes a path or url to a file loaded by e.g. a PXE boot loader. Defaults to unset. + Takes a name of the boot server used by e.g. PXE boot systems. When specified, the + server name is set to the DHCP option 66. See + RFC 2132 for more details. + Defaults to unset. + Note that typically one of + BootServerName=/BootServerAddress= is sufficient to be + set, but both can be set too, if desired. + + + + + BootFilename= + + + Takes a path or URL to a file loaded by e.g. a PXE boot loader. The specified path is + set to the DHCP option 67. See + RFC 2132 for more details. + Defaults to unset. diff --git a/src/libsystemd-network/dhcp-server-internal.h b/src/libsystemd-network/dhcp-server-internal.h index bb41ad2c3dc..607f9f0c2fa 100644 --- a/src/libsystemd-network/dhcp-server-internal.h +++ b/src/libsystemd-network/dhcp-server-internal.h @@ -65,8 +65,9 @@ struct sd_dhcp_server { char *timezone; DHCPServerData servers[_SD_DHCP_LEASE_SERVER_TYPE_MAX]; - struct in_addr next_server; - char *filename; + struct in_addr boot_server_address; + char *boot_server_name; + char *boot_filename; OrderedSet *extra_options; OrderedSet *vendor_options; diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index 38c1f0be6a3..b9ff27b9e1e 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -12,6 +12,7 @@ #include "alloc-util.h" #include "dhcp-internal.h" #include "dhcp-server-internal.h" +#include "dns-domain.h" #include "fd-util.h" #include "in-addr-util.h" #include "io-util.h" @@ -163,7 +164,8 @@ static sd_dhcp_server *dhcp_server_free(sd_dhcp_server *server) { sd_event_unref(server->event); - free(server->filename); + free(server->boot_server_name); + free(server->boot_filename); free(server->timezone); for (sd_dhcp_lease_server_type_t i = 0; i < _SD_DHCP_LEASE_SERVER_TYPE_MAX; i++) @@ -272,24 +274,40 @@ sd_event *sd_dhcp_server_get_event(sd_dhcp_server *server) { return server->event; } -int sd_dhcp_server_set_next_server(sd_dhcp_server *server, const struct in_addr *next_server) { +int sd_dhcp_server_set_boot_server_address(sd_dhcp_server *server, const struct in_addr *address) { assert_return(server, -EINVAL); - if (next_server) - server->next_server = *next_server; + if (address) + server->boot_server_address = *address; else - server->next_server = (struct in_addr) {}; + server->boot_server_address = (struct in_addr) {}; return 0; } -int sd_dhcp_server_set_filename(sd_dhcp_server *server, const char *filename) { +int sd_dhcp_server_set_boot_server_name(sd_dhcp_server *server, const char *name) { + int r; + + assert_return(server, -EINVAL); + + if (name) { + r = dns_name_is_valid(name); + if (r < 0) + return r; + if (r == 0) + return -EINVAL; + } + + return free_and_strdup(&server->boot_server_name, name); +} + +int sd_dhcp_server_set_boot_filename(sd_dhcp_server *server, const char *filename) { assert_return(server, -EINVAL); if (filename && (!string_is_safe(filename) || !ascii_is_valid(filename))) return -EINVAL; - return free_and_strdup(&server->filename, filename); + return free_and_strdup(&server->boot_filename, filename); } int sd_dhcp_server_stop(sd_dhcp_server *server) { @@ -561,7 +579,7 @@ static int server_send_offer_or_ack( return r; packet->dhcp.yiaddr = address; - packet->dhcp.siaddr = server->next_server.s_addr; + packet->dhcp.siaddr = server->boot_server_address.s_addr; lease_time = htobe32(req->lifetime); r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0, @@ -585,18 +603,18 @@ static int server_send_offer_or_ack( return r; } - if (server->filename) { - /* The pxelinux magic option is marked as deprecated, but let's append it for older - * implementations. */ + if (server->boot_server_name) { r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0, - SD_DHCP_OPTION_PXELINUX_MAGIC, 4, - (const uint8_t[]) { 0xf1, 0x00, 0x74, 0x7e }); + SD_DHCP_OPTION_BOOT_SERVER_NAME, + strlen(server->boot_server_name), server->boot_server_name); if (r < 0) return r; + } + if (server->boot_filename) { r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0, - SD_DHCP_OPTION_CONFIGURATION_FILE, - strlen(server->filename), server->filename); + SD_DHCP_OPTION_BOOT_FILENAME, + strlen(server->boot_filename), server->boot_filename); if (r < 0) return r; } diff --git a/src/network/networkd-dhcp-server.c b/src/network/networkd-dhcp-server.c index 795ad686af9..515c9c44bee 100644 --- a/src/network/networkd-dhcp-server.c +++ b/src/network/networkd-dhcp-server.c @@ -416,13 +416,17 @@ static int dhcp4_server_configure(Link *link) { return log_link_error_errno(link, r, "Failed to set default lease time for DHCPv4 server instance: %m"); } - r = sd_dhcp_server_set_next_server(link->dhcp_server, &link->network->dhcp_server_next_server); + r = sd_dhcp_server_set_boot_server_address(link->dhcp_server, &link->network->dhcp_server_boot_server_address); if (r < 0) - return log_link_warning_errno(link, r, "Failed to set next server for DHCPv4 server instance: %m"); + return log_link_warning_errno(link, r, "Failed to set boot server address for DHCPv4 server instance: %m"); - r = sd_dhcp_server_set_filename(link->dhcp_server, link->network->dhcp_server_filename); + r = sd_dhcp_server_set_boot_server_name(link->dhcp_server, link->network->dhcp_server_boot_server_name); if (r < 0) - return log_link_warning_errno(link, r, "Failed to set filename for DHCPv4 server instance: %m"); + return log_link_warning_errno(link, r, "Failed to set boot server name for DHCPv4 server instance: %m"); + + r = sd_dhcp_server_set_boot_filename(link->dhcp_server, link->network->dhcp_server_boot_filename); + if (r < 0) + return log_link_warning_errno(link, r, "Failed to set boot filename for DHCPv4 server instance: %m"); for (sd_dhcp_lease_server_type_t type = 0; type < _SD_DHCP_LEASE_SERVER_TYPE_MAX; type ++) { @@ -712,7 +716,7 @@ int config_parse_dhcp_server_address( void *data, void *userdata) { - Network *network = userdata; + Network *network = ASSERT_PTR(userdata); union in_addr_union a; unsigned char prefixlen; int r; diff --git a/src/network/networkd-network-gperf.gperf b/src/network/networkd-network-gperf.gperf index 3ae8b8f4600..ceaaa6a0f7c 100644 --- a/src/network/networkd-network-gperf.gperf +++ b/src/network/networkd-network-gperf.gperf @@ -305,8 +305,9 @@ DHCPServer.PoolSize, config_parse_uint32, DHCPServer.SendVendorOption, config_parse_dhcp_send_option, 0, offsetof(Network, dhcp_server_send_vendor_options) DHCPServer.SendOption, config_parse_dhcp_send_option, 0, offsetof(Network, dhcp_server_send_options) DHCPServer.BindToInterface, config_parse_bool, 0, offsetof(Network, dhcp_server_bind_to_interface) -DHCPServer.NextServer, config_parse_in_addr_non_null, AF_INET, offsetof(Network, dhcp_server_next_server) -DHCPServer.Filename, config_parse_string, CONFIG_PARSE_STRING_SAFE_AND_ASCII, offsetof(Network, dhcp_server_filename) +DHCPServer.BootServerAddress, config_parse_in_addr_non_null, AF_INET, offsetof(Network, dhcp_server_boot_server_address) +DHCPServer.BootServerName, config_parse_dns_name, 0, offsetof(Network, dhcp_server_boot_server_name) +DHCPServer.BootFilename, config_parse_string, CONFIG_PARSE_STRING_SAFE_AND_ASCII, offsetof(Network, dhcp_server_boot_filename) DHCPServerStaticLease.Address, config_parse_dhcp_static_lease_address, 0, 0 DHCPServerStaticLease.MACAddress, config_parse_dhcp_static_lease_hwaddr, 0, 0 Bridge.Cost, config_parse_uint32, 0, offsetof(Network, cost) diff --git a/src/network/networkd-network.c b/src/network/networkd-network.c index cdd2ef48d98..683b04b5acd 100644 --- a/src/network/networkd-network.c +++ b/src/network/networkd-network.c @@ -702,7 +702,8 @@ static Network *network_free(Network *network) { free(network->dhcp_server_relay_agent_circuit_id); free(network->dhcp_server_relay_agent_remote_id); - free(network->dhcp_server_filename); + free(network->dhcp_server_boot_server_name); + free(network->dhcp_server_boot_filename); free(network->description); free(network->dhcp_vendor_class_identifier); diff --git a/src/network/networkd-network.h b/src/network/networkd-network.h index c764f69f529..807e0fadc66 100644 --- a/src/network/networkd-network.h +++ b/src/network/networkd-network.h @@ -200,8 +200,9 @@ struct Network { uint32_t dhcp_server_pool_size; OrderedHashmap *dhcp_server_send_options; OrderedHashmap *dhcp_server_send_vendor_options; - struct in_addr dhcp_server_next_server; - char *dhcp_server_filename; + struct in_addr dhcp_server_boot_server_address; + char *dhcp_server_boot_server_name; + char *dhcp_server_boot_filename; /* link local addressing support */ AddressFamily link_local; diff --git a/src/systemd/sd-dhcp-server.h b/src/systemd/sd-dhcp-server.h index af7c3b68f3e..371834dd8da 100644 --- a/src/systemd/sd-dhcp-server.h +++ b/src/systemd/sd-dhcp-server.h @@ -58,8 +58,9 @@ int sd_dhcp_server_stop(sd_dhcp_server *server); int sd_dhcp_server_configure_pool(sd_dhcp_server *server, const struct in_addr *address, unsigned char prefixlen, uint32_t offset, uint32_t size); -int sd_dhcp_server_set_next_server(sd_dhcp_server *server, const struct in_addr *next_server); -int sd_dhcp_server_set_filename(sd_dhcp_server *server, const char *filename); +int sd_dhcp_server_set_boot_server_address(sd_dhcp_server *server, const struct in_addr *address); +int sd_dhcp_server_set_boot_server_name(sd_dhcp_server *server, const char *name); +int sd_dhcp_server_set_boot_filename(sd_dhcp_server *server, const char *filename); int sd_dhcp_server_set_bind_to_interface(sd_dhcp_server *server, int enabled); int sd_dhcp_server_set_timezone(sd_dhcp_server *server, const char *timezone); int sd_dhcp_server_set_router(sd_dhcp_server *server, const struct in_addr *address); diff --git a/test/fuzz/fuzz-network-parser/directives.network b/test/fuzz/fuzz-network-parser/directives.network index c682ac4ac1a..276f3c93076 100644 --- a/test/fuzz/fuzz-network-parser/directives.network +++ b/test/fuzz/fuzz-network-parser/directives.network @@ -409,8 +409,9 @@ RelayAgentCircuitId= RelayAgentRemoteId= ServerAddress= UplinkInterface= -NextServer= -Filename= +BootServerAddress= +BootServerName= +BootFilename= [DHCPServerStaticLease] MACAddress= Address= -- 2.39.2