691 lines
20 KiB
Diff
691 lines
20 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Peter Jones <pjones@redhat.com>
|
|
Date: Tue, 9 Jul 2019 11:47:37 +0200
|
|
Subject: [PATCH] efinet and bootp: add support for dhcpv6
|
|
|
|
Signed-off-by: Peter Jones <pjones@redhat.com>
|
|
---
|
|
grub-core/net/bootp.c | 173 +++++++++++++++++++++++++++++++++++++
|
|
grub-core/net/drivers/efi/efinet.c | 84 +++++++++++++-----
|
|
grub-core/net/net.c | 72 +++++++++++++++
|
|
grub-core/net/tftp.c | 3 +
|
|
include/grub/efi/api.h | 129 +++++++++++++++++++++++++--
|
|
include/grub/net.h | 60 +++++++++++++
|
|
6 files changed, 491 insertions(+), 30 deletions(-)
|
|
|
|
diff --git a/grub-core/net/bootp.c b/grub-core/net/bootp.c
|
|
index abe45ef7bf6..02d2c2614cb 100644
|
|
--- a/grub-core/net/bootp.c
|
|
+++ b/grub-core/net/bootp.c
|
|
@@ -905,6 +905,179 @@ grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)),
|
|
|
|
static grub_command_t cmd_getdhcp, cmd_bootp, cmd_dhcp;
|
|
|
|
+struct grub_net_network_level_interface *
|
|
+grub_net_configure_by_dhcpv6_ack (const char *name,
|
|
+ struct grub_net_card *card,
|
|
+ grub_net_interface_flags_t flags
|
|
+ __attribute__((__unused__)),
|
|
+ const grub_net_link_level_address_t *hwaddr,
|
|
+ const struct grub_net_dhcpv6_packet *packet,
|
|
+ int is_def, char **device, char **path)
|
|
+{
|
|
+ struct grub_net_network_level_interface *inter = NULL;
|
|
+ struct grub_net_network_level_address addr;
|
|
+ int mask = -1;
|
|
+
|
|
+ if (!device || !path)
|
|
+ return NULL;
|
|
+
|
|
+ *device = 0;
|
|
+ *path = 0;
|
|
+
|
|
+ grub_dprintf ("net", "mac address is %02x:%02x:%02x:%02x:%02x:%02x\n",
|
|
+ hwaddr->mac[0], hwaddr->mac[1], hwaddr->mac[2],
|
|
+ hwaddr->mac[3], hwaddr->mac[4], hwaddr->mac[5]);
|
|
+
|
|
+ if (is_def)
|
|
+ grub_net_default_server = 0;
|
|
+
|
|
+ if (is_def && !grub_net_default_server && packet)
|
|
+ {
|
|
+ const grub_uint8_t *options = packet->dhcp_options;
|
|
+ unsigned int option_max = 1024 - OFFSET_OF (dhcp_options, packet);
|
|
+ unsigned int i;
|
|
+
|
|
+ for (i = 0; i < option_max - sizeof (grub_net_dhcpv6_option_t); )
|
|
+ {
|
|
+ grub_uint16_t num, len;
|
|
+ grub_net_dhcpv6_option_t *opt =
|
|
+ (grub_net_dhcpv6_option_t *)(options + i);
|
|
+
|
|
+ num = grub_be_to_cpu16(opt->option_num);
|
|
+ len = grub_be_to_cpu16(opt->option_len);
|
|
+
|
|
+ grub_dprintf ("net", "got dhcpv6 option %d len %d\n", num, len);
|
|
+
|
|
+ if (len == 0)
|
|
+ break;
|
|
+
|
|
+ if (len + i > 1024)
|
|
+ break;
|
|
+
|
|
+ if (num == GRUB_NET_DHCP6_BOOTFILE_URL)
|
|
+ {
|
|
+ char *scheme, *userinfo, *host, *file;
|
|
+ char *tmp;
|
|
+ int hostlen;
|
|
+ int port;
|
|
+ int rc = extract_url_info ((const char *)opt->option_data,
|
|
+ (grub_size_t)len,
|
|
+ &scheme, &userinfo, &host, &port,
|
|
+ &file);
|
|
+ if (rc < 0)
|
|
+ continue;
|
|
+
|
|
+ /* right now this only handles tftp. */
|
|
+ if (grub_strcmp("tftp", scheme))
|
|
+ {
|
|
+ grub_free (scheme);
|
|
+ grub_free (userinfo);
|
|
+ grub_free (host);
|
|
+ grub_free (file);
|
|
+ continue;
|
|
+ }
|
|
+ grub_free (userinfo);
|
|
+
|
|
+ hostlen = grub_strlen (host);
|
|
+ if (hostlen > 2 && host[0] == '[' && host[hostlen-1] == ']')
|
|
+ {
|
|
+ tmp = host+1;
|
|
+ host[hostlen-1] = '\0';
|
|
+ }
|
|
+ else
|
|
+ tmp = host;
|
|
+
|
|
+ *device = grub_xasprintf ("%s,%s", scheme, tmp);
|
|
+ grub_free (scheme);
|
|
+ grub_free (host);
|
|
+
|
|
+ if (file && *file)
|
|
+ {
|
|
+ tmp = grub_strrchr (file, '/');
|
|
+ if (tmp)
|
|
+ *(tmp+1) = '\0';
|
|
+ else
|
|
+ file[0] = '\0';
|
|
+ }
|
|
+ else if (!file)
|
|
+ file = grub_strdup ("");
|
|
+
|
|
+ if (file[0] == '/')
|
|
+ {
|
|
+ *path = grub_strdup (file+1);
|
|
+ grub_free (file);
|
|
+ }
|
|
+ else
|
|
+ *path = file;
|
|
+ }
|
|
+ else if (num == GRUB_NET_DHCP6_IA_NA)
|
|
+ {
|
|
+ const grub_net_dhcpv6_option_t *ia_na_opt;
|
|
+ const grub_net_dhcpv6_opt_ia_na_t *ia_na =
|
|
+ (const grub_net_dhcpv6_opt_ia_na_t *)opt;
|
|
+ unsigned int left = len - OFFSET_OF (options, ia_na);
|
|
+ unsigned int j;
|
|
+
|
|
+ if ((grub_uint8_t *)ia_na + left >
|
|
+ (grub_uint8_t *)options + option_max)
|
|
+ left -= ((grub_uint8_t *)ia_na + left)
|
|
+ - ((grub_uint8_t *)options + option_max);
|
|
+
|
|
+ if (len < OFFSET_OF (option_data, opt)
|
|
+ + sizeof (grub_net_dhcpv6_option_t))
|
|
+ {
|
|
+ grub_dprintf ("net",
|
|
+ "found dhcpv6 ia_na option with no address\n");
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ for (j = 0; left > sizeof (grub_net_dhcpv6_option_t); )
|
|
+ {
|
|
+ ia_na_opt = (const grub_net_dhcpv6_option_t *)
|
|
+ (ia_na->options + j);
|
|
+ grub_uint16_t ia_na_opt_num, ia_na_opt_len;
|
|
+
|
|
+ ia_na_opt_num = grub_be_to_cpu16 (ia_na_opt->option_num);
|
|
+ ia_na_opt_len = grub_be_to_cpu16 (ia_na_opt->option_len);
|
|
+ if (ia_na_opt_len == 0)
|
|
+ break;
|
|
+ if (j + ia_na_opt_len > left)
|
|
+ break;
|
|
+ if (ia_na_opt_num == GRUB_NET_DHCP6_IA_ADDRESS)
|
|
+ {
|
|
+ const grub_net_dhcpv6_opt_ia_address_t *ia_addr;
|
|
+
|
|
+ ia_addr = (const grub_net_dhcpv6_opt_ia_address_t *)
|
|
+ ia_na_opt;
|
|
+ addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
|
|
+ grub_memcpy(addr.ipv6, ia_addr->ipv6_address,
|
|
+ sizeof (ia_addr->ipv6_address));
|
|
+ inter = grub_net_add_addr (name, card, &addr, hwaddr, 0);
|
|
+ }
|
|
+
|
|
+ j += ia_na_opt_len;
|
|
+ left -= ia_na_opt_len;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ i += len + 4;
|
|
+ }
|
|
+
|
|
+ grub_print_error ();
|
|
+ }
|
|
+
|
|
+ if (is_def)
|
|
+ {
|
|
+ grub_env_set ("net_default_interface", name);
|
|
+ grub_env_export ("net_default_interface");
|
|
+ }
|
|
+
|
|
+ if (inter)
|
|
+ grub_net_add_ipv6_local (inter, mask);
|
|
+ return inter;
|
|
+}
|
|
+
|
|
+
|
|
void
|
|
grub_bootp_init (void)
|
|
{
|
|
diff --git a/grub-core/net/drivers/efi/efinet.c b/grub-core/net/drivers/efi/efinet.c
|
|
index 3ea25cf9894..2af8742f904 100644
|
|
--- a/grub-core/net/drivers/efi/efinet.c
|
|
+++ b/grub-core/net/drivers/efi/efinet.c
|
|
@@ -18,11 +18,14 @@
|
|
|
|
#include <grub/net/netbuff.h>
|
|
#include <grub/dl.h>
|
|
+#include <grub/env.h>
|
|
#include <grub/net.h>
|
|
#include <grub/time.h>
|
|
#include <grub/efi/api.h>
|
|
#include <grub/efi/efi.h>
|
|
#include <grub/i18n.h>
|
|
+#include <grub/lib/hexdump.h>
|
|
+#include <grub/types.h>
|
|
|
|
GRUB_MOD_LICENSE ("GPLv3+");
|
|
|
|
@@ -346,7 +349,7 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
|
|
char **path)
|
|
{
|
|
struct grub_net_card *card;
|
|
- grub_efi_device_path_t *dp;
|
|
+ grub_efi_device_path_t *dp, *ldp = NULL;
|
|
struct grub_net_network_level_interface *inter;
|
|
grub_efi_device_path_t *vlan_dp;
|
|
grub_efi_uint16_t vlan_dp_len;
|
|
@@ -361,14 +364,19 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
|
|
grub_efi_device_path_t *cdp;
|
|
struct grub_efi_pxe *pxe;
|
|
struct grub_efi_pxe_mode *pxe_mode;
|
|
+
|
|
if (card->driver != &efidriver)
|
|
continue;
|
|
+
|
|
cdp = grub_efi_get_device_path (card->efi_handle);
|
|
if (! cdp)
|
|
continue;
|
|
+
|
|
+ ldp = grub_efi_find_last_device_path (dp);
|
|
+
|
|
if (grub_efi_compare_device_paths (dp, cdp) != 0)
|
|
{
|
|
- grub_efi_device_path_t *ldp, *dup_dp, *dup_ldp;
|
|
+ grub_efi_device_path_t *dup_dp, *dup_ldp;
|
|
int match;
|
|
|
|
/* EDK2 UEFI PXE driver creates pseudo devices with type IPv4/IPv6
|
|
@@ -377,7 +385,6 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
|
|
devices. We skip them when enumerating cards, so here we need to
|
|
find matching MAC device.
|
|
*/
|
|
- ldp = grub_efi_find_last_device_path (dp);
|
|
if (GRUB_EFI_DEVICE_PATH_TYPE (ldp) != GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE
|
|
|| (GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV4_DEVICE_PATH_SUBTYPE
|
|
&& GRUB_EFI_DEVICE_PATH_SUBTYPE (ldp) != GRUB_EFI_IPV6_DEVICE_PATH_SUBTYPE))
|
|
@@ -394,41 +401,70 @@ grub_efi_net_config_real (grub_efi_handle_t hnd, char **device,
|
|
if (!match)
|
|
continue;
|
|
}
|
|
+
|
|
pxe = grub_efi_open_protocol (hnd, &pxe_io_guid,
|
|
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
|
if (! pxe)
|
|
continue;
|
|
+
|
|
pxe_mode = pxe->mode;
|
|
+ if (pxe_mode->using_ipv6)
|
|
+ {
|
|
+ grub_net_link_level_address_t hwaddr;
|
|
+ struct grub_net_network_level_interface *intf;
|
|
+
|
|
+ grub_dprintf ("efinet", "using ipv6 and dhcpv6\n");
|
|
+ grub_dprintf ("efinet", "dhcp_ack_received: %s%s\n",
|
|
+ pxe_mode->dhcp_ack_received ? "yes" : "no",
|
|
+ pxe_mode->dhcp_ack_received ? "" : " cannot continue");
|
|
+ if (!pxe_mode->dhcp_ack_received)
|
|
+ continue;
|
|
|
|
- inter = grub_net_configure_by_dhcp_ack (card->name, card, 0,
|
|
- (struct grub_net_bootp_packet *)
|
|
- &pxe_mode->dhcp_ack,
|
|
- sizeof (pxe_mode->dhcp_ack),
|
|
- 1, device, path);
|
|
+ hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
|
|
+ grub_memcpy (hwaddr.mac,
|
|
+ card->efi_net->mode->current_address,
|
|
+ sizeof (hwaddr.mac));
|
|
|
|
- if (inter != NULL)
|
|
+ inter = grub_net_configure_by_dhcpv6_ack (card->name, card, 0, &hwaddr,
|
|
+ (const struct grub_net_dhcpv6_packet *)&pxe_mode->dhcp_ack.dhcpv6,
|
|
+ 1, device, path);
|
|
+ if (inter && device && path)
|
|
+ grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path);
|
|
+ }
|
|
+ else
|
|
{
|
|
- /*
|
|
- * Search the device path for any VLAN subtype and use it
|
|
- * to configure the interface.
|
|
- */
|
|
- vlan_dp = dp;
|
|
+ grub_dprintf ("efinet", "using ipv4 and dhcp\n");
|
|
+ inter = grub_net_configure_by_dhcp_ack (card->name, card, 0,
|
|
+ (struct grub_net_bootp_packet *)
|
|
+ &pxe_mode->dhcp_ack,
|
|
+ sizeof (pxe_mode->dhcp_ack),
|
|
+ 1, device, path);
|
|
|
|
- while (!GRUB_EFI_END_ENTIRE_DEVICE_PATH (vlan_dp))
|
|
+ grub_dprintf ("efinet", "device: `%s' path: `%s'\n", *device, *path);
|
|
+ if (inter != NULL)
|
|
{
|
|
- if (GRUB_EFI_DEVICE_PATH_TYPE (vlan_dp) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE &&
|
|
- GRUB_EFI_DEVICE_PATH_SUBTYPE (vlan_dp) == GRUB_EFI_VLAN_DEVICE_PATH_SUBTYPE)
|
|
+ /*
|
|
+ * Search the device path for any VLAN subtype and use it
|
|
+ * to configure the interface.
|
|
+ */
|
|
+ vlan_dp = dp;
|
|
+
|
|
+ while (!GRUB_EFI_END_ENTIRE_DEVICE_PATH (vlan_dp))
|
|
{
|
|
- vlan = (grub_efi_vlan_device_path_t *) vlan_dp;
|
|
- inter->vlantag = vlan->vlan_id;
|
|
- break;
|
|
+ if (GRUB_EFI_DEVICE_PATH_TYPE (vlan_dp) == GRUB_EFI_MESSAGING_DEVICE_PATH_TYPE &&
|
|
+ GRUB_EFI_DEVICE_PATH_SUBTYPE (vlan_dp) == GRUB_EFI_VLAN_DEVICE_PATH_SUBTYPE)
|
|
+ {
|
|
+ vlan = (grub_efi_vlan_device_path_t *) vlan_dp;
|
|
+ inter->vlantag = vlan->vlan_id;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ vlan_dp_len = GRUB_EFI_DEVICE_PATH_LENGTH (vlan_dp);
|
|
+ vlan_dp = (grub_efi_device_path_t *) ((grub_efi_uint8_t *) vlan_dp + vlan_dp_len);
|
|
}
|
|
-
|
|
- vlan_dp_len = GRUB_EFI_DEVICE_PATH_LENGTH (vlan_dp);
|
|
- vlan_dp = (grub_efi_device_path_t *) ((grub_efi_uint8_t *) vlan_dp + vlan_dp_len);
|
|
}
|
|
+ return;
|
|
}
|
|
- return;
|
|
}
|
|
}
|
|
|
|
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
|
|
index 54451cea2a7..20c55257647 100644
|
|
--- a/grub-core/net/net.c
|
|
+++ b/grub-core/net/net.c
|
|
@@ -984,6 +984,78 @@ grub_net_network_level_interface_register (struct grub_net_network_level_interfa
|
|
grub_net_network_level_interfaces = inter;
|
|
}
|
|
|
|
+int
|
|
+grub_ipv6_get_masksize (grub_uint16_t *be_mask)
|
|
+{
|
|
+ grub_uint8_t *mask;
|
|
+ grub_uint16_t mask16[8];
|
|
+ int x, y;
|
|
+ int ret = 128;
|
|
+
|
|
+ grub_memcpy (mask16, be_mask, sizeof (mask16));
|
|
+ for (x = 0; x < 8; x++)
|
|
+ mask16[x] = grub_be_to_cpu16 (mask16[x]);
|
|
+
|
|
+ mask = (grub_uint8_t *)mask16;
|
|
+
|
|
+ for (x = 15; x >= 0; x--)
|
|
+ {
|
|
+ grub_uint8_t octet = mask[x];
|
|
+ if (!octet)
|
|
+ {
|
|
+ ret -= 8;
|
|
+ continue;
|
|
+ }
|
|
+ for (y = 0; y < 8; y++)
|
|
+ {
|
|
+ if (octet & (1 << y))
|
|
+ break;
|
|
+ else
|
|
+ ret--;
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+grub_err_t
|
|
+grub_net_add_ipv6_local (struct grub_net_network_level_interface *inter,
|
|
+ int mask)
|
|
+{
|
|
+ struct grub_net_route *route;
|
|
+
|
|
+ if (inter->address.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6)
|
|
+ return 0;
|
|
+
|
|
+ if (mask == -1)
|
|
+ mask = grub_ipv6_get_masksize ((grub_uint16_t *)inter->address.ipv6);
|
|
+
|
|
+ if (mask == -1)
|
|
+ return 0;
|
|
+
|
|
+ route = grub_zalloc (sizeof (*route));
|
|
+ if (!route)
|
|
+ return grub_errno;
|
|
+
|
|
+ route->name = grub_xasprintf ("%s:local", inter->name);
|
|
+ if (!route->name)
|
|
+ {
|
|
+ grub_free (route);
|
|
+ return grub_errno;
|
|
+ }
|
|
+
|
|
+ route->target.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
|
|
+ grub_memcpy (route->target.ipv6.base, inter->address.ipv6,
|
|
+ sizeof (inter->address.ipv6));
|
|
+ route->target.ipv6.masksize = mask;
|
|
+ route->is_gateway = 0;
|
|
+ route->interface = inter;
|
|
+
|
|
+ grub_net_route_register (route);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
|
|
grub_err_t
|
|
grub_net_add_ipv4_local (struct grub_net_network_level_interface *inter,
|
|
diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
|
|
index 409b1d09bcd..f300a9d4007 100644
|
|
--- a/grub-core/net/tftp.c
|
|
+++ b/grub-core/net/tftp.c
|
|
@@ -359,6 +359,7 @@ tftp_open (struct grub_file *file, const char *filename)
|
|
file->not_easily_seekable = 1;
|
|
file->data = data;
|
|
|
|
+ grub_dprintf("tftp", "resolving address for %s\n", file->device->net->server);
|
|
err = grub_net_resolve_address (file->device->net->server, &addr);
|
|
if (err)
|
|
{
|
|
@@ -369,11 +370,13 @@ tftp_open (struct grub_file *file, const char *filename)
|
|
return err;
|
|
}
|
|
|
|
+ grub_dprintf("tftp", "opening connection\n");
|
|
data->sock = grub_net_udp_open (addr,
|
|
port ? port : TFTP_SERVER_PORT, tftp_receive,
|
|
file);
|
|
if (!data->sock)
|
|
{
|
|
+ grub_dprintf("tftp", "connection failed\n");
|
|
grub_free (data);
|
|
return grub_errno;
|
|
}
|
|
diff --git a/include/grub/efi/api.h b/include/grub/efi/api.h
|
|
index d44d00ad7d5..c6d702831f7 100644
|
|
--- a/include/grub/efi/api.h
|
|
+++ b/include/grub/efi/api.h
|
|
@@ -637,10 +637,16 @@ typedef void *grub_efi_handle_t;
|
|
typedef void *grub_efi_event_t;
|
|
typedef grub_efi_uint64_t grub_efi_lba_t;
|
|
typedef grub_efi_uintn_t grub_efi_tpl_t;
|
|
-typedef grub_uint8_t grub_efi_mac_address_t[32];
|
|
-typedef grub_uint8_t grub_efi_ipv4_address_t[4];
|
|
-typedef grub_uint16_t grub_efi_ipv6_address_t[8];
|
|
-typedef grub_uint8_t grub_efi_ip_address_t[8] __attribute__ ((aligned(4)));
|
|
+typedef grub_efi_uint8_t grub_efi_mac_address_t[32];
|
|
+typedef grub_efi_uint8_t grub_efi_ipv4_address_t[4];
|
|
+typedef grub_efi_uint8_t grub_efi_ipv6_address_t[16];
|
|
+typedef union
|
|
+{
|
|
+ grub_efi_uint32_t addr[4];
|
|
+ grub_efi_ipv4_address_t v4;
|
|
+ grub_efi_ipv6_address_t v6;
|
|
+} grub_efi_ip_address_t __attribute__ ((aligned(4)));
|
|
+
|
|
typedef grub_efi_uint64_t grub_efi_physical_address_t;
|
|
typedef grub_efi_uint64_t grub_efi_virtual_address_t;
|
|
|
|
@@ -1521,16 +1527,127 @@ struct grub_efi_simple_text_output_interface
|
|
};
|
|
typedef struct grub_efi_simple_text_output_interface grub_efi_simple_text_output_interface_t;
|
|
|
|
-typedef grub_uint8_t grub_efi_pxe_packet_t[1472];
|
|
+typedef struct grub_efi_pxe_dhcpv4_packet
|
|
+{
|
|
+ grub_efi_uint8_t bootp_opcode;
|
|
+ grub_efi_uint8_t bootp_hwtype;
|
|
+ grub_efi_uint8_t bootp_hwaddr_len;
|
|
+ grub_efi_uint8_t bootp_gate_hops;
|
|
+ grub_efi_uint32_t bootp_ident;
|
|
+ grub_efi_uint16_t bootp_seconds;
|
|
+ grub_efi_uint16_t bootp_flags;
|
|
+ grub_efi_uint8_t bootp_ci_addr[4];
|
|
+ grub_efi_uint8_t bootp_yi_addr[4];
|
|
+ grub_efi_uint8_t bootp_si_addr[4];
|
|
+ grub_efi_uint8_t bootp_gi_addr[4];
|
|
+ grub_efi_uint8_t bootp_hw_addr[16];
|
|
+ grub_efi_uint8_t bootp_srv_name[64];
|
|
+ grub_efi_uint8_t bootp_boot_file[128];
|
|
+ grub_efi_uint32_t dhcp_magik;
|
|
+ grub_efi_uint8_t dhcp_options[56];
|
|
+} grub_efi_pxe_dhcpv4_packet_t;
|
|
+
|
|
+struct grub_efi_pxe_dhcpv6_packet
|
|
+{
|
|
+ grub_efi_uint32_t message_type:8;
|
|
+ grub_efi_uint32_t transaction_id:24;
|
|
+ grub_efi_uint8_t dhcp_options[1024];
|
|
+} GRUB_PACKED;
|
|
+typedef struct grub_efi_pxe_dhcpv6_packet grub_efi_pxe_dhcpv6_packet_t;
|
|
+
|
|
+typedef union
|
|
+{
|
|
+ grub_efi_uint8_t raw[1472];
|
|
+ grub_efi_pxe_dhcpv4_packet_t dhcpv4;
|
|
+ grub_efi_pxe_dhcpv6_packet_t dhcpv6;
|
|
+} grub_efi_pxe_packet_t;
|
|
+
|
|
+#define GRUB_EFI_PXE_MAX_IPCNT 8
|
|
+#define GRUB_EFI_PXE_MAX_ARP_ENTRIES 8
|
|
+#define GRUB_EFI_PXE_MAX_ROUTE_ENTRIES 8
|
|
+
|
|
+typedef struct grub_efi_pxe_ip_filter
|
|
+{
|
|
+ grub_efi_uint8_t filters;
|
|
+ grub_efi_uint8_t ip_count;
|
|
+ grub_efi_uint8_t reserved;
|
|
+ grub_efi_ip_address_t ip_list[GRUB_EFI_PXE_MAX_IPCNT];
|
|
+} grub_efi_pxe_ip_filter_t;
|
|
+
|
|
+typedef struct grub_efi_pxe_arp_entry
|
|
+{
|
|
+ grub_efi_ip_address_t ip_addr;
|
|
+ grub_efi_mac_address_t mac_addr;
|
|
+} grub_efi_pxe_arp_entry_t;
|
|
+
|
|
+typedef struct grub_efi_pxe_route_entry
|
|
+{
|
|
+ grub_efi_ip_address_t ip_addr;
|
|
+ grub_efi_ip_address_t subnet_mask;
|
|
+ grub_efi_ip_address_t gateway_addr;
|
|
+} grub_efi_pxe_route_entry_t;
|
|
+
|
|
+typedef struct grub_efi_pxe_icmp_error
|
|
+{
|
|
+ grub_efi_uint8_t type;
|
|
+ grub_efi_uint8_t code;
|
|
+ grub_efi_uint16_t checksum;
|
|
+ union
|
|
+ {
|
|
+ grub_efi_uint32_t reserved;
|
|
+ grub_efi_uint32_t mtu;
|
|
+ grub_efi_uint32_t pointer;
|
|
+ struct
|
|
+ {
|
|
+ grub_efi_uint16_t identifier;
|
|
+ grub_efi_uint16_t sequence;
|
|
+ } echo;
|
|
+ } u;
|
|
+ grub_efi_uint8_t data[494];
|
|
+} grub_efi_pxe_icmp_error_t;
|
|
+
|
|
+typedef struct grub_efi_pxe_tftp_error
|
|
+{
|
|
+ grub_efi_uint8_t error_code;
|
|
+ grub_efi_char8_t error_string[127];
|
|
+} grub_efi_pxe_tftp_error_t;
|
|
|
|
typedef struct grub_efi_pxe_mode
|
|
{
|
|
- grub_uint8_t unused[52];
|
|
+ grub_efi_boolean_t started;
|
|
+ grub_efi_boolean_t ipv6_available;
|
|
+ grub_efi_boolean_t ipv6_supported;
|
|
+ grub_efi_boolean_t using_ipv6;
|
|
+ grub_efi_boolean_t bis_supported;
|
|
+ grub_efi_boolean_t bis_detected;
|
|
+ grub_efi_boolean_t auto_arp;
|
|
+ grub_efi_boolean_t send_guid;
|
|
+ grub_efi_boolean_t dhcp_discover_valid;
|
|
+ grub_efi_boolean_t dhcp_ack_received;
|
|
+ grub_efi_boolean_t proxy_offer_received;
|
|
+ grub_efi_boolean_t pxe_discover_valid;
|
|
+ grub_efi_boolean_t pxe_reply_received;
|
|
+ grub_efi_boolean_t pxe_bis_reply_received;
|
|
+ grub_efi_boolean_t icmp_error_received;
|
|
+ grub_efi_boolean_t tftp_error_received;
|
|
+ grub_efi_boolean_t make_callbacks;
|
|
+ grub_efi_uint8_t ttl;
|
|
+ grub_efi_uint8_t tos;
|
|
+ grub_efi_ip_address_t station_ip;
|
|
+ grub_efi_ip_address_t subnet_mask;
|
|
grub_efi_pxe_packet_t dhcp_discover;
|
|
grub_efi_pxe_packet_t dhcp_ack;
|
|
grub_efi_pxe_packet_t proxy_offer;
|
|
grub_efi_pxe_packet_t pxe_discover;
|
|
grub_efi_pxe_packet_t pxe_reply;
|
|
+ grub_efi_pxe_packet_t pxe_bis_reply;
|
|
+ grub_efi_pxe_ip_filter_t ip_filter;
|
|
+ grub_efi_uint32_t arp_cache_entries;
|
|
+ grub_efi_pxe_arp_entry_t arp_cache[GRUB_EFI_PXE_MAX_ARP_ENTRIES];
|
|
+ grub_efi_uint32_t route_table_entries;
|
|
+ grub_efi_pxe_route_entry_t route_table[GRUB_EFI_PXE_MAX_ROUTE_ENTRIES];
|
|
+ grub_efi_pxe_icmp_error_t icmp_error;
|
|
+ grub_efi_pxe_tftp_error_t tftp_error;
|
|
} grub_efi_pxe_mode_t;
|
|
|
|
typedef struct grub_efi_pxe
|
|
diff --git a/include/grub/net.h b/include/grub/net.h
|
|
index 844e501c128..bf8430a6364 100644
|
|
--- a/include/grub/net.h
|
|
+++ b/include/grub/net.h
|
|
@@ -450,6 +450,51 @@ struct grub_net_bootp_packet
|
|
grub_uint8_t vendor[0];
|
|
} GRUB_PACKED;
|
|
|
|
+enum
|
|
+ {
|
|
+ GRUB_NET_DHCP6_IA_NA = 3,
|
|
+ GRUB_NET_DHCP6_IA_ADDRESS = 5,
|
|
+ GRUB_NET_DHCP6_BOOTFILE_URL = 59,
|
|
+ };
|
|
+
|
|
+struct grub_net_dhcpv6_option
|
|
+{
|
|
+ grub_uint16_t option_num;
|
|
+ grub_uint16_t option_len;
|
|
+ grub_uint8_t option_data[];
|
|
+} GRUB_PACKED;
|
|
+typedef struct grub_net_dhcpv6_option grub_net_dhcpv6_option_t;
|
|
+
|
|
+struct grub_net_dhcpv6_opt_ia_na
|
|
+{
|
|
+ grub_uint16_t option_num;
|
|
+ grub_uint16_t option_len;
|
|
+ grub_uint32_t iaid;
|
|
+ grub_uint32_t t1;
|
|
+ grub_uint32_t t2;
|
|
+ grub_uint8_t options[];
|
|
+} GRUB_PACKED;
|
|
+typedef struct grub_net_dhcpv6_opt_ia_na grub_net_dhcpv6_opt_ia_na_t;
|
|
+
|
|
+struct grub_net_dhcpv6_opt_ia_address
|
|
+{
|
|
+ grub_uint16_t option_num;
|
|
+ grub_uint16_t option_len;
|
|
+ grub_uint64_t ipv6_address[2];
|
|
+ grub_uint32_t preferred_lifetime;
|
|
+ grub_uint32_t valid_lifetime;
|
|
+ grub_uint8_t options[];
|
|
+} GRUB_PACKED;
|
|
+typedef struct grub_net_dhcpv6_opt_ia_address grub_net_dhcpv6_opt_ia_address_t;
|
|
+
|
|
+struct grub_net_dhcpv6_packet
|
|
+{
|
|
+ grub_uint32_t message_type:8;
|
|
+ grub_uint32_t transaction_id:24;
|
|
+ grub_uint8_t dhcp_options[1024];
|
|
+} GRUB_PACKED;
|
|
+typedef struct grub_net_dhcpv6_packet grub_net_dhcpv6_packet_t;
|
|
+
|
|
#define GRUB_NET_BOOTP_RFC1048_MAGIC_0 0x63
|
|
#define GRUB_NET_BOOTP_RFC1048_MAGIC_1 0x82
|
|
#define GRUB_NET_BOOTP_RFC1048_MAGIC_2 0x53
|
|
@@ -485,6 +530,21 @@ grub_net_configure_by_dhcp_ack (const char *name,
|
|
grub_size_t size,
|
|
int is_def, char **device, char **path);
|
|
|
|
+struct grub_net_network_level_interface *
|
|
+grub_net_configure_by_dhcpv6_ack (const char *name,
|
|
+ struct grub_net_card *card,
|
|
+ grub_net_interface_flags_t flags,
|
|
+ const grub_net_link_level_address_t *hwaddr,
|
|
+ const struct grub_net_dhcpv6_packet *packet,
|
|
+ int is_def, char **device, char **path);
|
|
+
|
|
+int
|
|
+grub_ipv6_get_masksize(grub_uint16_t *mask);
|
|
+
|
|
+grub_err_t
|
|
+grub_net_add_ipv6_local (struct grub_net_network_level_interface *inf,
|
|
+ int mask);
|
|
+
|
|
grub_err_t
|
|
grub_net_add_ipv4_local (struct grub_net_network_level_interface *inf,
|
|
int mask);
|