net/dhcp: Actually send out DHCPv4 DISCOVER and REQUEST messages
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 <andre.przywara@arm.com> Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
This commit is contained in:
parent
5a365fed87
commit
5a4f9d5c04
2 changed files with 121 additions and 1 deletions
|
@ -25,6 +25,48 @@
|
||||||
#include <grub/net/udp.h>
|
#include <grub/net/udp.h>
|
||||||
#include <grub/datetime.h>
|
#include <grub/datetime.h>
|
||||||
|
|
||||||
|
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
|
enum
|
||||||
{
|
{
|
||||||
GRUB_DHCP_OPT_OVERLOAD_FILE = 1,
|
GRUB_DHCP_OPT_OVERLOAD_FILE = 1,
|
||||||
|
@ -43,6 +85,8 @@ enum
|
||||||
GRUB_DHCP_MESSAGE_INFORM,
|
GRUB_DHCP_MESSAGE_INFORM,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define GRUB_BOOTP_MAX_OPTIONS_SIZE 64
|
||||||
|
|
||||||
/* Max timeout when waiting for BOOTP/DHCP reply */
|
/* Max timeout when waiting for BOOTP/DHCP reply */
|
||||||
#define GRUB_DHCP_MAX_PACKET_TIMEOUT 32
|
#define GRUB_DHCP_MAX_PACKET_TIMEOUT 32
|
||||||
|
|
||||||
|
@ -386,6 +430,64 @@ send_dhcp_packet (struct grub_net_network_level_interface *iface)
|
||||||
grub_net_network_level_address_t target;
|
grub_net_network_level_address_t target;
|
||||||
grub_net_link_level_address_t ll_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);
|
nb = grub_netbuff_alloc (sizeof (*pack) + GRUB_BOOTP_MAX_OPTIONS_SIZE + 128);
|
||||||
if (!nb)
|
if (!nb)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
@ -399,6 +501,19 @@ send_dhcp_packet (struct grub_net_network_level_interface *iface)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
grub_memset (nb->data, 0, GRUB_BOOTP_MAX_OPTIONS_SIZE);
|
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));
|
err = grub_netbuff_push (nb, sizeof (*pack));
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -416,7 +531,10 @@ send_dhcp_packet (struct grub_net_network_level_interface *iface)
|
||||||
t = 0;
|
t = 0;
|
||||||
}
|
}
|
||||||
pack->seconds = grub_cpu_to_be16 (t);
|
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);
|
grub_memcpy (&pack->mac_addr, &iface->hwaddress.mac, 6);
|
||||||
|
|
||||||
|
|
|
@ -462,9 +462,11 @@ enum
|
||||||
GRUB_NET_BOOTP_DOMAIN = 0x0f,
|
GRUB_NET_BOOTP_DOMAIN = 0x0f,
|
||||||
GRUB_NET_BOOTP_ROOT_PATH = 0x11,
|
GRUB_NET_BOOTP_ROOT_PATH = 0x11,
|
||||||
GRUB_NET_BOOTP_EXTENSIONS_PATH = 0x12,
|
GRUB_NET_BOOTP_EXTENSIONS_PATH = 0x12,
|
||||||
|
GRUB_NET_DHCP_REQUESTED_IP_ADDRESS = 50,
|
||||||
GRUB_NET_DHCP_OVERLOAD = 52,
|
GRUB_NET_DHCP_OVERLOAD = 52,
|
||||||
GRUB_NET_DHCP_MESSAGE_TYPE = 53,
|
GRUB_NET_DHCP_MESSAGE_TYPE = 53,
|
||||||
GRUB_NET_DHCP_SERVER_IDENTIFIER = 54,
|
GRUB_NET_DHCP_SERVER_IDENTIFIER = 54,
|
||||||
|
GRUB_NET_DHCP_PARAMETER_REQUEST_LIST = 55,
|
||||||
GRUB_NET_DHCP_TFTP_SERVER_NAME = 66,
|
GRUB_NET_DHCP_TFTP_SERVER_NAME = 66,
|
||||||
GRUB_NET_DHCP_BOOTFILE_NAME = 67,
|
GRUB_NET_DHCP_BOOTFILE_NAME = 67,
|
||||||
GRUB_NET_BOOTP_END = 0xff
|
GRUB_NET_BOOTP_END = 0xff
|
||||||
|
|
Loading…
Reference in a new issue