From: Yu Watanabe Date: Thu, 24 Feb 2022 17:32:58 +0000 (+0900) Subject: sd-dhcp-server: add support to send next server and filename option for PXE boot... X-Git-Tag: v251-rc1~226^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d5e5cd5c34211426778b042549267d03658b3b3e;p=thirdparty%2Fsystemd.git sd-dhcp-server: add support to send next server and filename option for PXE boot systems --- diff --git a/src/libsystemd-network/dhcp-server-internal.h b/src/libsystemd-network/dhcp-server-internal.h index 51510b9d22e..bb41ad2c3dc 100644 --- a/src/libsystemd-network/dhcp-server-internal.h +++ b/src/libsystemd-network/dhcp-server-internal.h @@ -65,6 +65,8 @@ struct sd_dhcp_server { char *timezone; DHCPServerData servers[_SD_DHCP_LEASE_SERVER_TYPE_MAX]; + struct in_addr next_server; + char *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 81dc4ff9504..1636b838e14 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -21,6 +21,7 @@ #include "siphash24.h" #include "string-util.h" #include "unaligned.h" +#include "utf8.h" #define DHCP_DEFAULT_LEASE_TIME_USEC USEC_PER_HOUR #define DHCP_MAX_LEASE_TIME_USEC (USEC_PER_HOUR*12) @@ -162,6 +163,7 @@ static sd_dhcp_server *dhcp_server_free(sd_dhcp_server *server) { sd_event_unref(server->event); + free(server->filename); free(server->timezone); for (sd_dhcp_lease_server_type_t i = 0; i < _SD_DHCP_LEASE_SERVER_TYPE_MAX; i++) @@ -270,6 +272,26 @@ 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) { + assert_return(server, -EINVAL); + + if (next_server) + server->next_server = *next_server; + else + server->next_server = (struct in_addr) {}; + + return 0; +} + +int sd_dhcp_server_set_filename(sd_dhcp_server *server, const char *filename) { + assert_return(server, -EINVAL); + + if (filename && !ascii_is_valid(filename)) + return -EINVAL; + + return free_and_strdup(&server->filename, filename); +} + int sd_dhcp_server_stop(sd_dhcp_server *server) { bool running; @@ -539,6 +561,7 @@ static int server_send_offer_or_ack( return r; packet->dhcp.yiaddr = address; + packet->dhcp.siaddr = server->next_server.s_addr; lease_time = htobe32(req->lifetime); r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0, @@ -562,6 +585,22 @@ 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. */ + r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0, + SD_DHCP_OPTION_PXELINUX_MAGIC, 4, + (const uint8_t[]) { 0xf1, 0x00, 0x74, 0x7e }); + if (r < 0) + return r; + + r = dhcp_option_append(&packet->dhcp, req->max_optlen, &offset, 0, + SD_DHCP_OPTION_CONFIGURATION_FILE, + strlen(server->filename), server->filename); + if (r < 0) + return r; + } + 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, diff --git a/src/systemd/sd-dhcp-client.h b/src/systemd/sd-dhcp-client.h index 4af4b45f2d4..78d68addf45 100644 --- a/src/systemd/sd-dhcp-client.h +++ b/src/systemd/sd-dhcp-client.h @@ -97,6 +97,10 @@ enum { SD_DHCP_OPTION_SIP_SERVER = 120, SD_DHCP_OPTION_CLASSLESS_STATIC_ROUTE = 121, SD_DHCP_OPTION_MUD_URL = 161, + SD_DHCP_OPTION_PXELINUX_MAGIC = 208, /* deprecated */ + SD_DHCP_OPTION_CONFIGURATION_FILE = 209, + SD_DHCP_OPTION_PATH_PREFIX = 210, + SD_DHCP_OPTION_REBOOT_TIME = 211, SD_DHCP_OPTION_6RD = 212, SD_DHCP_OPTION_PRIVATE_BASE = 224, /* Windows 10 option to send when Anonymize=true */ diff --git a/src/systemd/sd-dhcp-server.h b/src/systemd/sd-dhcp-server.h index 59ef27e1dcd..af7c3b68f3e 100644 --- a/src/systemd/sd-dhcp-server.h +++ b/src/systemd/sd-dhcp-server.h @@ -58,6 +58,8 @@ 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_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);