From 1157a45292fdf3d004b693982bbafb46285e0f6d Mon Sep 17 00:00:00 2001 From: Andrei Borzenkov Date: Thu, 7 Mar 2019 15:14:13 +0000 Subject: [PATCH] net/dhcp: Use DHCP options for name and bootfile The BOOTP RFC describes the boot file name and the server name as being part of the integral BOOTP data structure, with some limits on the size of them. DHCP extends this by allowing them to be separate DHCP options, which is more flexible. Teach the code dealing with those fields to check for those DHCP options first and use this information, if provided. We fall back to using the BOOTP information if those options are not used. Signed-off-by: Andre Przywara Reviewed-by: Daniel Kiper --- grub-core/net/bootp.c | 72 +++++++++++++++++++++++++++++++------------ include/grub/net.h | 2 ++ 2 files changed, 54 insertions(+), 20 deletions(-) diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c index 2908cda3d..79a5482a6 100644 --- a/grub-core/net/bootp.c +++ b/grub-core/net/bootp.c @@ -186,7 +186,9 @@ grub_net_configure_by_dhcp_ack (const char *name, int mask = -1; char server_ip[sizeof ("xxx.xxx.xxx.xxx")]; const grub_uint8_t *opt; - grub_uint8_t opt_len; + grub_uint8_t opt_len, overload = 0; + const char *boot_file = 0, *server_name = 0; + grub_size_t boot_file_len, server_name_len; addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4; addr.ipv4 = bp->your_ip; @@ -205,9 +207,36 @@ grub_net_configure_by_dhcp_ack (const char *name, if (!inter) return 0; - if (size > OFFSET_OF (boot_file, bp)) - grub_env_set_net_property (name, "boot_file", bp->boot_file, - sizeof (bp->boot_file)); + opt = find_dhcp_option (bp, size, GRUB_NET_DHCP_OVERLOAD, &opt_len); + if (opt && opt_len == 1) + overload = *opt; + + opt = find_dhcp_option (bp, size, GRUB_NET_DHCP_TFTP_SERVER_NAME, &opt_len); + if (opt && opt_len) + { + server_name = (const char *) opt; + server_name_len = opt_len; + } + else if (size > OFFSET_OF (server_name, bp) && !(overload & GRUB_DHCP_OPT_OVERLOAD_SNAME) && + bp->server_name[0]) + { + server_name = bp->server_name; + server_name_len = sizeof (bp->server_name); + } + + opt = find_dhcp_option (bp, size, GRUB_NET_DHCP_BOOTFILE_NAME, &opt_len); + if (opt && opt_len) + { + boot_file = (const char *) opt; + boot_file_len = opt_len; + } + else if (size > OFFSET_OF (boot_file, bp) && !(overload && GRUB_DHCP_OPT_OVERLOAD_FILE) && + bp->boot_file[0]) + { + boot_file = bp->boot_file; + boot_file_len = sizeof (bp->boot_file); + } + if (bp->server_ip) { grub_snprintf (server_ip, sizeof (server_ip), "%d.%d.%d.%d", @@ -238,35 +267,38 @@ grub_net_configure_by_dhcp_ack (const char *name, *device = grub_xasprintf ("tftp,%s", server_ip); grub_print_error (); } - if (size > OFFSET_OF (server_name, bp) - && bp->server_name[0]) + + if (server_name) { - grub_env_set_net_property (name, "dhcp_server_name", bp->server_name, - sizeof (bp->server_name)); + grub_env_set_net_property (name, "dhcp_server_name", server_name, server_name_len); if (is_def && !grub_net_default_server) { - grub_net_default_server = grub_strdup (bp->server_name); + grub_net_default_server = grub_strdup (server_name); grub_print_error (); } if (device && !*device) { - *device = grub_xasprintf ("tftp,%s", bp->server_name); + *device = grub_xasprintf ("tftp,%s", server_name); grub_print_error (); } } - if (size > OFFSET_OF (boot_file, bp) && path) + if (boot_file) { - *path = grub_strndup (bp->boot_file, sizeof (bp->boot_file)); - grub_print_error (); - if (*path) + grub_env_set_net_property (name, "boot_file", boot_file, boot_file_len); + if (path) { - char *slash; - slash = grub_strrchr (*path, '/'); - if (slash) - *slash = 0; - else - **path = 0; + *path = grub_strndup (boot_file, boot_file_len); + grub_print_error (); + if (*path) + { + char *slash; + slash = grub_strrchr (*path, '/'); + if (slash) + *slash = 0; + else + **path = 0; + } } } diff --git a/include/grub/net.h b/include/grub/net.h index 49bf39eb2..c77a77312 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -461,6 +461,8 @@ enum GRUB_NET_BOOTP_ROOT_PATH = 0x11, GRUB_NET_BOOTP_EXTENSIONS_PATH = 0x12, GRUB_NET_DHCP_OVERLOAD = 52, + GRUB_NET_DHCP_TFTP_SERVER_NAME = 66, + GRUB_NET_DHCP_BOOTFILE_NAME = 67, GRUB_NET_BOOTP_END = 0xff };