From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.71) id 1gtc9h-0002ik-Sx for mharc-grub-devel@gnu.org; Tue, 12 Feb 2019 12:47:37 -0500 Received: from eggs.gnu.org ([209.51.188.92]:53870) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gtc9e-0002fw-UU for grub-devel@gnu.org; Tue, 12 Feb 2019 12:47:35 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gtc9Z-000344-Rc for grub-devel@gnu.org; Tue, 12 Feb 2019 12:47:34 -0500 Received: from usa-sjc-mx-foss1.foss.arm.com ([217.140.101.70]:37688 helo=foss.arm.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gtc9U-0002v0-RS for grub-devel@gnu.org; Tue, 12 Feb 2019 12:47:26 -0500 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id C36C31596; Tue, 12 Feb 2019 09:47:20 -0800 (PST) Received: from donnerap.arm.com (donnerap.cambridge.arm.com [10.1.197.44]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 6D2783F675; Tue, 12 Feb 2019 09:47:19 -0800 (PST) From: Andre Przywara To: Daniel Kiper Cc: Vladimir Serbinenko , Andrei Borzenkov , Daniel Kiper , Mark Rutland , grub-devel@gnu.org Subject: [PATCH v2 8/9] net: dhcp: actually send out DHCPv4 DISCOVER and REQUEST messages Date: Tue, 12 Feb 2019 17:46:59 +0000 Message-Id: <20190212174700.184741-9-andre.przywara@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190212174700.184741-1-andre.przywara@arm.com> References: <20190212174700.184741-1-andre.przywara@arm.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 217.140.101.70 X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 12 Feb 2019 17:47:36 -0000 From: Andrei Borzenkov Even though we were parsing some DHCP options sent by the server, so far we are only using the BOOTP 2-way handshake, even when talking to a DHCP server. Change this by actually sending out DHCP DISCOVER packets instead of the generic (mostly empty) BOOTP BOOTREQUEST packets. A pure BOOTP server would ignore the extra DHCP options in the DISCOVER packet and would just reply with a BOOTREPLY packet, which we also handle in the code. Signed-off-by: Andre Przywara --- grub-core/net/bootp.c | 120 +++++++++++++++++++++++++++++++++++++++++- include/grub/net.h | 2 + 2 files changed, 121 insertions(+), 1 deletion(-) diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c index f02e73003..4b20b1799 100644 --- a/grub-core/net/bootp.c +++ b/grub-core/net/bootp.c @@ -25,6 +25,48 @@ #include #include +struct grub_dhcp_discover_options +{ + grub_uint8_t magic[4]; + struct + { + grub_uint8_t code; + grub_uint8_t len; + grub_uint8_t data; + } GRUB_PACKED message_type; + grub_uint8_t end; +} GRUB_PACKED; + +struct grub_dhcp_request_options +{ + grub_uint8_t magic[4]; + struct + { + grub_uint8_t code; + grub_uint8_t len; + grub_uint8_t data; + } GRUB_PACKED message_type; + struct + { + grub_uint8_t type; + grub_uint8_t len; + grub_uint32_t data; + } GRUB_PACKED server_identifier; + struct + { + grub_uint8_t type; + grub_uint8_t len; + grub_uint32_t data; + } GRUB_PACKED requested_ip; + struct + { + grub_uint8_t type; + grub_uint8_t len; + grub_uint8_t data[7]; + } GRUB_PACKED parameter_request; + grub_uint8_t end; +} GRUB_PACKED; + enum { GRUB_DHCP_OPT_OVERLOAD_FILE = 1, @@ -43,6 +85,8 @@ enum GRUB_DHCP_MESSAGE_INFORM, }; +#define GRUB_BOOTP_MAX_OPTIONS_SIZE 64 + /* Max timeout when waiting for BOOTP/DHCP reply */ #define GRUB_DHCP_MAX_PACKET_TIMEOUT 32 @@ -387,6 +431,64 @@ send_dhcp_packet (struct grub_net_network_level_interface *iface) grub_net_network_level_address_t target; grub_net_link_level_address_t ll_target; + static struct grub_dhcp_discover_options discover_options = + { + { + GRUB_NET_BOOTP_RFC1048_MAGIC_0, + GRUB_NET_BOOTP_RFC1048_MAGIC_1, + GRUB_NET_BOOTP_RFC1048_MAGIC_2, + GRUB_NET_BOOTP_RFC1048_MAGIC_3, + }, + { + GRUB_NET_DHCP_MESSAGE_TYPE, + sizeof (discover_options.message_type.data), + GRUB_DHCP_MESSAGE_DISCOVER, + }, + GRUB_NET_BOOTP_END, + }; + + static struct grub_dhcp_request_options request_options = + { + { + GRUB_NET_BOOTP_RFC1048_MAGIC_0, + GRUB_NET_BOOTP_RFC1048_MAGIC_1, + GRUB_NET_BOOTP_RFC1048_MAGIC_2, + GRUB_NET_BOOTP_RFC1048_MAGIC_3, + }, + { + GRUB_NET_DHCP_MESSAGE_TYPE, + sizeof (request_options.message_type.data), + GRUB_DHCP_MESSAGE_REQUEST, + }, + { + GRUB_NET_DHCP_SERVER_IDENTIFIER, + sizeof (request_options.server_identifier.data), + 0, + }, + { + GRUB_NET_DHCP_REQUESTED_IP_ADDRESS, + sizeof (request_options.requested_ip.data), + 0, + }, + { + GRUB_NET_DHCP_PARAMETER_REQUEST_LIST, + sizeof (request_options.parameter_request.data), + { + GRUB_NET_BOOTP_NETMASK, + GRUB_NET_BOOTP_ROUTER, + GRUB_NET_BOOTP_DNS, + GRUB_NET_BOOTP_DOMAIN, + GRUB_NET_BOOTP_HOSTNAME, + GRUB_NET_BOOTP_ROOT_PATH, + GRUB_NET_BOOTP_EXTENSIONS_PATH, + }, + }, + GRUB_NET_BOOTP_END, + }; + + COMPILE_TIME_ASSERT (sizeof (discover_options) <= GRUB_BOOTP_MAX_OPTIONS_SIZE); + COMPILE_TIME_ASSERT (sizeof (request_options) <= GRUB_BOOTP_MAX_OPTIONS_SIZE); + nb = grub_netbuff_alloc (sizeof (*pack) + GRUB_BOOTP_MAX_OPTIONS_SIZE + 128); if (!nb) return grub_errno; @@ -400,6 +502,19 @@ send_dhcp_packet (struct grub_net_network_level_interface *iface) goto out; grub_memset (nb->data, 0, GRUB_BOOTP_MAX_OPTIONS_SIZE); + if (!iface->srv_id) + { + grub_memcpy (nb->data, &discover_options, sizeof (discover_options)); + } + else + { + struct grub_dhcp_request_options *ro = (struct grub_dhcp_request_options *) nb->data; + + grub_memcpy (nb->data, &request_options, sizeof (request_options)); + /* my_ip and srv_id are stored in network order so do not need conversion. */ + grub_set_unaligned32 (&ro->server_identifier.data, iface->srv_id); + grub_set_unaligned32 (&ro->requested_ip.data, iface->my_ip); + } err = grub_netbuff_push (nb, sizeof (*pack)); if (err) @@ -417,7 +532,10 @@ send_dhcp_packet (struct grub_net_network_level_interface *iface) t = 0; } pack->seconds = grub_cpu_to_be16 (t); - pack->ident = grub_cpu_to_be32 (t); + if (!iface->srv_id) + iface->xid = pack->ident = grub_cpu_to_be32 (t); + else + pack->ident = iface->xid; grub_memcpy (&pack->mac_addr, &iface->hwaddress.mac, 6); diff --git a/include/grub/net.h b/include/grub/net.h index 68a9f1311..4a9069a14 100644 --- a/include/grub/net.h +++ b/include/grub/net.h @@ -462,9 +462,11 @@ enum GRUB_NET_BOOTP_DOMAIN = 0x0f, GRUB_NET_BOOTP_ROOT_PATH = 0x11, GRUB_NET_BOOTP_EXTENSIONS_PATH = 0x12, + GRUB_NET_DHCP_REQUESTED_IP_ADDRESS = 50, GRUB_NET_DHCP_OVERLOAD = 52, GRUB_NET_DHCP_MESSAGE_TYPE = 53, GRUB_NET_DHCP_SERVER_IDENTIFIER = 54, + GRUB_NET_DHCP_PARAMETER_REQUEST_LIST = 55, GRUB_NET_DHCP_TFTP_SERVER_NAME = 66, GRUB_NET_DHCP_BOOTFILE_NAME = 67, GRUB_NET_BOOTP_END = 0xff -- 2.17.1