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
ada2f6d40c
commit
723c3174e4
2 changed files with 123 additions and 18 deletions
|
@ -35,14 +35,52 @@
|
||||||
#error "unknown bootp architecture"
|
#error "unknown bootp architecture"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static grub_uint8_t dhcp_option_header[] = {GRUB_NET_BOOTP_RFC1048_MAGIC_0,
|
|
||||||
GRUB_NET_BOOTP_RFC1048_MAGIC_1,
|
|
||||||
GRUB_NET_BOOTP_RFC1048_MAGIC_2,
|
|
||||||
GRUB_NET_BOOTP_RFC1048_MAGIC_3};
|
|
||||||
static grub_uint8_t grub_userclass[] = {0x4D, 0x06, 0x05, 'G', 'R', 'U', 'B', '2'};
|
static grub_uint8_t grub_userclass[] = {0x4D, 0x06, 0x05, 'G', 'R', 'U', 'B', '2'};
|
||||||
static grub_uint8_t grub_dhcpdiscover[] = {0x35, 0x01, 0x01};
|
static grub_uint8_t grub_dhcpdiscover[] = {0x35, 0x01, 0x01};
|
||||||
static grub_uint8_t grub_dhcptime[] = {0x33, 0x04, 0x00, 0x00, 0x0e, 0x10};
|
static grub_uint8_t grub_dhcptime[] = {0x33, 0x04, 0x00, 0x00, 0x0e, 0x10};
|
||||||
|
|
||||||
|
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,
|
||||||
|
@ -61,9 +99,6 @@ enum
|
||||||
GRUB_DHCP_MESSAGE_INFORM,
|
GRUB_DHCP_MESSAGE_INFORM,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Max timeout when waiting for BOOTP/DHCP reply */
|
|
||||||
#define GRUB_DHCP_MAX_PACKET_TIMEOUT 32
|
|
||||||
|
|
||||||
#define GRUB_BOOTP_MAX_OPTIONS_SIZE 64
|
#define GRUB_BOOTP_MAX_OPTIONS_SIZE 64
|
||||||
|
|
||||||
/* Max timeout when waiting for BOOTP/DHCP reply */
|
/* Max timeout when waiting for BOOTP/DHCP reply */
|
||||||
|
@ -405,35 +440,102 @@ send_dhcp_packet (struct grub_net_network_level_interface *iface)
|
||||||
grub_net_link_level_address_t ll_target;
|
grub_net_link_level_address_t ll_target;
|
||||||
grub_uint8_t *offset;
|
grub_uint8_t *offset;
|
||||||
|
|
||||||
nb = grub_netbuff_alloc (sizeof (*pack) + sizeof(dhcp_option_header)
|
static struct grub_dhcp_discover_options discover_options =
|
||||||
+ sizeof(grub_userclass)
|
{
|
||||||
|
{
|
||||||
|
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) + sizeof(grub_userclass)
|
||||||
+ sizeof(grub_dhcpdiscover)
|
+ sizeof(grub_dhcpdiscover)
|
||||||
+ sizeof(grub_dhcptime)
|
+ sizeof(grub_dhcptime)
|
||||||
+ GRUB_BOOTP_MAX_OPTIONS_SIZE + 128);
|
+ GRUB_BOOTP_MAX_OPTIONS_SIZE + 128);
|
||||||
if (!nb)
|
if (!nb)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
|
|
||||||
err = grub_netbuff_reserve (nb, sizeof (*pack) + sizeof(dhcp_option_header)
|
err = grub_netbuff_reserve (nb, sizeof (*pack) + sizeof(grub_userclass)
|
||||||
+ sizeof(grub_userclass)
|
|
||||||
+ sizeof(grub_dhcpdiscover)
|
+ sizeof(grub_dhcpdiscover)
|
||||||
+ sizeof(grub_dhcptime)
|
+ sizeof(grub_dhcptime)
|
||||||
+ GRUB_BOOTP_MAX_OPTIONS_SIZE + 128);
|
+ GRUB_BOOTP_MAX_OPTIONS_SIZE + 128);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
err = grub_netbuff_push (nb, sizeof(dhcp_option_header)
|
err = grub_netbuff_push (nb, sizeof(grub_userclass)
|
||||||
+ sizeof(grub_userclass)
|
|
||||||
+ sizeof(grub_dhcpdiscover)
|
+ sizeof(grub_dhcpdiscover)
|
||||||
+ sizeof(grub_dhcptime)
|
+ sizeof(grub_dhcptime)
|
||||||
+ GRUB_BOOTP_MAX_OPTIONS_SIZE);
|
+ GRUB_BOOTP_MAX_OPTIONS_SIZE);
|
||||||
if (err)
|
if (err)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
grub_memset (nb->data, 0, sizeof(dhcp_option_header)
|
grub_memset (nb->data, 0, sizeof(grub_userclass)
|
||||||
+ sizeof(grub_userclass)
|
|
||||||
+ sizeof(grub_dhcpdiscover)
|
+ sizeof(grub_dhcpdiscover)
|
||||||
+ sizeof(grub_dhcptime)
|
+ sizeof(grub_dhcptime)
|
||||||
+ GRUB_BOOTP_MAX_OPTIONS_SIZE);
|
+ 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)
|
||||||
|
@ -451,12 +553,13 @@ 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);
|
||||||
offset = (grub_uint8_t *)&pack->vendor;
|
offset = (grub_uint8_t *)&pack->vendor;
|
||||||
grub_memcpy (offset, dhcp_option_header, sizeof(dhcp_option_header));
|
|
||||||
offset += sizeof(dhcp_option_header);
|
|
||||||
grub_memcpy (offset, grub_dhcpdiscover, sizeof(grub_dhcpdiscover));
|
grub_memcpy (offset, grub_dhcpdiscover, sizeof(grub_dhcpdiscover));
|
||||||
offset += sizeof(grub_dhcpdiscover);
|
offset += sizeof(grub_dhcpdiscover);
|
||||||
grub_memcpy (offset, grub_userclass, sizeof(grub_userclass));
|
grub_memcpy (offset, grub_userclass, sizeof(grub_userclass));
|
||||||
|
|
|
@ -463,9 +463,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