diff --git a/man/systemd.network.xml b/man/systemd.network.xml
index 9d4a4b3e1f..ec270e5e96 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 bb41ad2c3d..607f9f0c2f 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 38c1f0be6a..b9ff27b9e1 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 795ad686af..515c9c44be 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 3ae8b8f460..ceaaa6a0f7 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 cdd2ef48d9..683b04b5ac 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 c764f69f52..807e0fadc6 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 af7c3b68f3..371834dd8d 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 c682ac4ac1..276f3c9307 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=