some more ipv6 code
This commit is contained in:
parent
d5e60b1ba0
commit
a53cf6534d
12 changed files with 528 additions and 60 deletions
|
@ -1603,6 +1603,7 @@ module = {
|
|||
common = net/udp.c;
|
||||
common = net/tcp.c;
|
||||
common = net/icmp.c;
|
||||
common = net/icmp6.c;
|
||||
common = net/ethernet.c;
|
||||
common = net/arp.c;
|
||||
common = net/netbuff.c;
|
||||
|
|
|
@ -130,7 +130,7 @@ grub_net_configure_by_dhcp_ack (const char *name,
|
|||
: sizeof (hwaddr.mac));
|
||||
hwaddr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
|
||||
|
||||
inter = grub_net_add_addr (name, card, addr, hwaddr, flags);
|
||||
inter = grub_net_add_addr (name, card, &addr, &hwaddr, flags);
|
||||
if (bp->gateway_ip)
|
||||
{
|
||||
grub_net_network_level_netaddress_t target;
|
||||
|
@ -379,6 +379,7 @@ grub_cmd_dhcpopt (struct grub_command *cmd __attribute__ ((unused)),
|
|||
"unrecognised format specification %s", args[3]);
|
||||
}
|
||||
|
||||
/* FIXME: allow to specify mac address. */
|
||||
static grub_err_t
|
||||
grub_cmd_bootp (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
|
|
|
@ -81,7 +81,7 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf,
|
|||
|
||||
grub_err_t
|
||||
grub_net_recv_ethernet_packet (struct grub_net_buff * nb,
|
||||
const struct grub_net_card * card)
|
||||
struct grub_net_card * card)
|
||||
{
|
||||
struct etherhdr *eth;
|
||||
struct llchdr *llch;
|
||||
|
@ -123,11 +123,8 @@ grub_net_recv_ethernet_packet (struct grub_net_buff * nb,
|
|||
return GRUB_ERR_NONE;
|
||||
/* IP packet. */
|
||||
case GRUB_NET_ETHERTYPE_IP:
|
||||
grub_net_recv_ip4_packets (nb, card, &hwaddress);
|
||||
return GRUB_ERR_NONE;
|
||||
case GRUB_NET_ETHERTYPE_IP6:
|
||||
grub_net_recv_ip4_packets (nb, card, &hwaddress);
|
||||
return GRUB_ERR_NONE;
|
||||
return grub_net_recv_ip_packets (nb, card, &hwaddress);
|
||||
}
|
||||
grub_netbuff_free (nb);
|
||||
return GRUB_ERR_NONE;
|
||||
|
|
|
@ -25,13 +25,13 @@ struct icmp_header
|
|||
grub_uint8_t type;
|
||||
grub_uint8_t code;
|
||||
grub_uint16_t checksum;
|
||||
};
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct ping_header
|
||||
{
|
||||
grub_uint16_t id;
|
||||
grub_uint16_t seq;
|
||||
};
|
||||
} __attribute__ ((packed));
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -40,7 +40,7 @@ enum
|
|||
};
|
||||
|
||||
grub_err_t
|
||||
grub_net_recv_icmp_packet (struct grub_net_buff * nb,
|
||||
grub_net_recv_icmp_packet (struct grub_net_buff *nb,
|
||||
struct grub_net_network_level_interface *inf,
|
||||
const grub_net_network_level_address_t *src)
|
||||
{
|
||||
|
@ -48,15 +48,28 @@ grub_net_recv_icmp_packet (struct grub_net_buff * nb,
|
|||
grub_err_t err;
|
||||
grub_uint16_t checksum;
|
||||
|
||||
/* Ignore broadcast. */
|
||||
if (!inf)
|
||||
{
|
||||
grub_netbuff_free (nb);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
icmph = (struct icmp_header *) nb->data;
|
||||
|
||||
if (nb->tail - nb->data < (grub_ssize_t) sizeof (*icmph))
|
||||
return grub_error (GRUB_ERR_OUT_OF_RANGE, "ICMP packet too small");
|
||||
{
|
||||
grub_netbuff_free (nb);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
checksum = icmph->checksum;
|
||||
icmph->checksum = 0;
|
||||
if (checksum != grub_net_ip_chksum (nb->data, nb->tail - nb->data))
|
||||
return GRUB_ERR_NONE;
|
||||
{
|
||||
icmph->checksum = checksum;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
icmph->checksum = checksum;
|
||||
|
||||
err = grub_netbuff_pull (nb, sizeof (*icmph));
|
||||
|
|
235
grub-core/net/icmp6.c
Normal file
235
grub-core/net/icmp6.c
Normal file
|
@ -0,0 +1,235 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2010,2011 Free Software Foundation, Inc.
|
||||
*
|
||||
* GRUB is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GRUB is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <grub/net.h>
|
||||
#include <grub/net/ip.h>
|
||||
#include <grub/net/netbuff.h>
|
||||
|
||||
struct icmp_header
|
||||
{
|
||||
grub_uint8_t type;
|
||||
grub_uint8_t code;
|
||||
grub_uint16_t checksum;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct ping_header
|
||||
{
|
||||
grub_uint16_t id;
|
||||
grub_uint16_t seq;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct router_adv
|
||||
{
|
||||
grub_uint8_t ttl;
|
||||
grub_uint8_t flags;
|
||||
grub_uint16_t router_lifetime;
|
||||
grub_uint32_t reachable_time;
|
||||
grub_uint32_t retrans_timer;
|
||||
grub_uint8_t options[0];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct prefix_option
|
||||
{
|
||||
grub_uint8_t type;
|
||||
grub_uint8_t len;
|
||||
grub_uint8_t prefixlen;
|
||||
grub_uint8_t flags;
|
||||
grub_uint32_t valid_lifetime;
|
||||
grub_uint32_t prefered_lifetime;
|
||||
grub_uint32_t reserved;
|
||||
grub_uint64_t prefix[2];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
enum
|
||||
{
|
||||
FLAG_SLAAC = 0x40
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ICMP6_ECHO = 128,
|
||||
ICMP6_ECHO_REPLY = 129,
|
||||
ICMP6_ROUTER_ADVERTISE = 134
|
||||
};
|
||||
|
||||
grub_err_t
|
||||
grub_net_recv_icmp6_packet (struct grub_net_buff *nb,
|
||||
struct grub_net_card *card,
|
||||
struct grub_net_network_level_interface *inf,
|
||||
const grub_net_network_level_address_t *source,
|
||||
const grub_net_network_level_address_t *dest)
|
||||
{
|
||||
struct icmp_header *icmph;
|
||||
grub_err_t err;
|
||||
grub_uint16_t checksum;
|
||||
|
||||
icmph = (struct icmp_header *) nb->data;
|
||||
|
||||
if (nb->tail - nb->data < (grub_ssize_t) sizeof (*icmph))
|
||||
{
|
||||
grub_netbuff_free (nb);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
checksum = icmph->checksum;
|
||||
icmph->checksum = 0;
|
||||
if (checksum != grub_net_ip_transport_checksum (nb,
|
||||
GRUB_NET_IP_ICMPV6,
|
||||
source,
|
||||
dest))
|
||||
{
|
||||
grub_dprintf ("net", "invalid ICMPv6 checksum: %04x instead of %04x\n",
|
||||
checksum,
|
||||
grub_net_ip_transport_checksum (nb,
|
||||
GRUB_NET_IP_ICMPV6,
|
||||
source,
|
||||
dest));
|
||||
icmph->checksum = checksum;
|
||||
grub_netbuff_free (nb);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
icmph->checksum = checksum;
|
||||
|
||||
err = grub_netbuff_pull (nb, sizeof (*icmph));
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
grub_dprintf ("net", "ICMPv6 message: %02x, %02x\n",
|
||||
icmph->type, icmph->code);
|
||||
switch (icmph->type)
|
||||
{
|
||||
case ICMP6_ECHO:
|
||||
/* Don't accept multicast pings. */
|
||||
if (!inf)
|
||||
break;
|
||||
{
|
||||
struct grub_net_buff *nb_reply;
|
||||
struct icmp_header *icmphr;
|
||||
if (icmph->code)
|
||||
break;
|
||||
nb_reply = grub_netbuff_alloc (nb->tail - nb->data + 512);
|
||||
if (!nb_reply)
|
||||
{
|
||||
grub_netbuff_free (nb);
|
||||
return grub_errno;
|
||||
}
|
||||
err = grub_netbuff_reserve (nb_reply, nb->tail - nb->data + 512);
|
||||
if (err)
|
||||
goto ping_fail;
|
||||
err = grub_netbuff_push (nb_reply, nb->tail - nb->data);
|
||||
if (err)
|
||||
goto ping_fail;
|
||||
grub_memcpy (nb_reply->data, nb->data, nb->tail - nb->data);
|
||||
err = grub_netbuff_push (nb_reply, sizeof (*icmphr));
|
||||
if (err)
|
||||
goto ping_fail;
|
||||
icmphr = (struct icmp_header *) nb_reply->data;
|
||||
icmphr->type = ICMP6_ECHO_REPLY;
|
||||
icmphr->code = 0;
|
||||
icmphr->checksum = 0;
|
||||
icmphr->checksum = grub_net_ip_transport_checksum (nb_reply,
|
||||
GRUB_NET_IP_ICMPV6,
|
||||
&inf->address,
|
||||
source);
|
||||
err = grub_net_send_ip_packet (inf, source, nb_reply,
|
||||
GRUB_NET_IP_ICMPV6);
|
||||
|
||||
ping_fail:
|
||||
grub_netbuff_free (nb);
|
||||
grub_netbuff_free (nb_reply);
|
||||
return err;
|
||||
}
|
||||
case ICMP6_ROUTER_ADVERTISE:
|
||||
{
|
||||
grub_uint8_t *ptr;
|
||||
if (icmph->code)
|
||||
break;
|
||||
err = grub_netbuff_pull (nb, sizeof (struct router_adv));
|
||||
if (err)
|
||||
return err;
|
||||
for (ptr = (grub_uint8_t *) nb->data + sizeof (struct router_adv);
|
||||
ptr < nb->tail; )
|
||||
{
|
||||
grub_dprintf ("net", "option %02x, %02x\n", ptr[0], ptr[1]);
|
||||
if (ptr + 2 >= nb->tail || ptr[1] == 0)
|
||||
{
|
||||
grub_netbuff_free (nb);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
if (ptr[0] == 3 && ptr[1] == 4)
|
||||
{
|
||||
struct prefix_option *opt = (struct prefix_option *) ptr;
|
||||
struct grub_net_slaac_mac_list *slaac;
|
||||
if (!(opt->flags & FLAG_SLAAC)
|
||||
|| (grub_be_to_cpu64 (opt->prefix[0]) >> 48) == 0xfe80
|
||||
|| (grub_be_to_cpu32 (opt->prefered_lifetime)
|
||||
> grub_be_to_cpu32 (opt->valid_lifetime))
|
||||
|| opt->prefixlen != 64)
|
||||
{
|
||||
ptr += ptr[1] * 8;
|
||||
grub_dprintf ("net", "discarded prefix: %d, %d, %d, %d\n",
|
||||
!(opt->flags & FLAG_SLAAC),
|
||||
(grub_be_to_cpu64 (opt->prefix[0]) >> 48) == 0xfe80,
|
||||
(grub_be_to_cpu32 (opt->prefered_lifetime)
|
||||
> grub_be_to_cpu32 (opt->valid_lifetime)),
|
||||
opt->prefixlen != 64);
|
||||
continue;
|
||||
}
|
||||
for (slaac = card->slaac_list; slaac; slaac = slaac->next)
|
||||
{
|
||||
grub_net_network_level_address_t addr;
|
||||
if (slaac->address.type
|
||||
!= GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET)
|
||||
continue;
|
||||
addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
|
||||
addr.ipv6[0] = opt->prefix[0];
|
||||
addr.ipv6[1] = grub_net_ipv6_get_id (&slaac->address);
|
||||
FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
|
||||
{
|
||||
if (inf->card == card
|
||||
&& grub_net_addr_cmp (&inf->address, &addr) == 0)
|
||||
break;
|
||||
}
|
||||
/* Update lease time if needed here once we have
|
||||
lease times. */
|
||||
if (inf)
|
||||
continue;
|
||||
|
||||
grub_dprintf ("net", "creating slaac\n");
|
||||
|
||||
{
|
||||
char name[grub_strlen (slaac->name)
|
||||
+ sizeof (":XXXXXXXXXXXXXXXXXXXX")];
|
||||
grub_snprintf (name, sizeof (name), "%s:%d",
|
||||
slaac->name, slaac->slaac_counter++);
|
||||
grub_net_add_addr (name,
|
||||
card, &addr,
|
||||
&slaac->address, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
ptr += ptr[1] * 8;
|
||||
}
|
||||
if (ptr != nb->tail)
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
grub_netbuff_free (nb);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
|
@ -221,7 +221,7 @@ grub_net_send_ip4_packet (struct grub_net_network_level_interface * inf,
|
|||
|
||||
static grub_err_t
|
||||
handle_dgram (struct grub_net_buff *nb,
|
||||
const struct grub_net_card *card,
|
||||
struct grub_net_card *card,
|
||||
const grub_net_link_level_address_t *hwaddress,
|
||||
grub_net_ip_protocol_t proto,
|
||||
const grub_net_network_level_address_t *source,
|
||||
|
@ -282,8 +282,12 @@ handle_dgram (struct grub_net_buff *nb,
|
|||
break;
|
||||
}
|
||||
|
||||
if (!inf)
|
||||
if (!inf && !(dest->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6
|
||||
&& dest->ipv6[0] == grub_be_to_cpu64 (0xff02ULL << 48)
|
||||
&& dest->ipv6[1] == grub_be_to_cpu64 (1)))
|
||||
{
|
||||
grub_dprintf ("net", "undirected dgram discarded: %x, %lx, %lx\n",
|
||||
dest->type, dest->ipv6[0], dest->ipv6[1]);
|
||||
grub_netbuff_free (nb);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
@ -296,6 +300,8 @@ handle_dgram (struct grub_net_buff *nb,
|
|||
return grub_net_recv_tcp_packet (nb, inf, source);
|
||||
case GRUB_NET_IP_ICMP:
|
||||
return grub_net_recv_icmp_packet (nb, inf, source);
|
||||
case GRUB_NET_IP_ICMPV6:
|
||||
return grub_net_recv_icmp6_packet (nb, card, inf, source, dest);
|
||||
default:
|
||||
grub_netbuff_free (nb);
|
||||
break;
|
||||
|
@ -330,9 +336,9 @@ free_old_fragments (void)
|
|||
}
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
static grub_err_t
|
||||
grub_net_recv_ip4_packets (struct grub_net_buff * nb,
|
||||
const struct grub_net_card * card,
|
||||
struct grub_net_card * card,
|
||||
const grub_net_link_level_address_t * hwaddress)
|
||||
{
|
||||
struct iphdr *iph = (struct iphdr *) nb->data;
|
||||
|
@ -590,12 +596,11 @@ grub_net_send_ip_packet (struct grub_net_network_level_interface * inf,
|
|||
default:
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, "not an IP");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
static grub_err_t
|
||||
grub_net_recv_ip6_packets (struct grub_net_buff * nb,
|
||||
const struct grub_net_card * card,
|
||||
struct grub_net_card * card,
|
||||
const grub_net_link_level_address_t * hwaddress)
|
||||
{
|
||||
struct ip6hdr *iph = (struct ip6hdr *) nb->data;
|
||||
|
@ -652,8 +657,24 @@ grub_net_recv_ip6_packets (struct grub_net_buff * nb,
|
|||
source.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
|
||||
dest.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
|
||||
grub_memcpy (source.ipv6, &iph->src, sizeof (source.ipv6));
|
||||
grub_memcpy (dest.ipv6, &iph->src, sizeof (dest.ipv6));
|
||||
grub_memcpy (dest.ipv6, &iph->dest, sizeof (dest.ipv6));
|
||||
|
||||
return handle_dgram (nb, card, hwaddress, iph->protocol,
|
||||
&source, &dest);
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_net_recv_ip_packets (struct grub_net_buff * nb,
|
||||
struct grub_net_card * card,
|
||||
const grub_net_link_level_address_t * hwaddress)
|
||||
{
|
||||
struct iphdr *iph = (struct iphdr *) nb->data;
|
||||
|
||||
if ((iph->verhdrlen >> 4) == 4)
|
||||
return grub_net_recv_ip4_packets (nb, card, hwaddress);
|
||||
if ((iph->verhdrlen >> 4) == 6)
|
||||
return grub_net_recv_ip6_packets (nb, card, hwaddress);
|
||||
grub_dprintf ("net", "Bad IP version: %d\n", (iph->verhdrlen >> 4));
|
||||
grub_netbuff_free (nb);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <grub/command.h>
|
||||
#include <grub/env.h>
|
||||
#include <grub/net/ethernet.h>
|
||||
#include <grub/net/ip.h>
|
||||
#include <grub/loader.h>
|
||||
#include <grub/bufio.h>
|
||||
#include <grub/kernel.h>
|
||||
|
@ -72,6 +73,151 @@ grub_net_card_unregister (struct grub_net_card *card)
|
|||
GRUB_AS_LIST (card));
|
||||
}
|
||||
|
||||
static struct grub_net_slaac_mac_list *
|
||||
grub_net_ipv6_get_slaac (struct grub_net_card *card,
|
||||
const grub_net_link_level_address_t *hwaddr)
|
||||
{
|
||||
struct grub_net_slaac_mac_list *slaac;
|
||||
char *ptr;
|
||||
|
||||
for (slaac = card->slaac_list; slaac; slaac = slaac->next)
|
||||
if (grub_net_hwaddr_cmp (&slaac->address, hwaddr) == 0)
|
||||
return slaac;
|
||||
|
||||
slaac = grub_zalloc (sizeof (*slaac));
|
||||
if (!slaac)
|
||||
return NULL;
|
||||
|
||||
slaac->name = grub_malloc (grub_strlen (card->name)
|
||||
+ GRUB_NET_MAX_STR_HWADDR_LEN
|
||||
+ sizeof (":slaac"));
|
||||
ptr = grub_stpcpy (slaac->name, card->name);
|
||||
if (grub_net_hwaddr_cmp (&card->default_address, hwaddr) != 0)
|
||||
{
|
||||
ptr = grub_stpcpy (ptr, ":");
|
||||
grub_net_hwaddr_to_str (hwaddr, ptr);
|
||||
ptr += grub_strlen (ptr);
|
||||
}
|
||||
ptr = grub_stpcpy (ptr, ":slaac");
|
||||
|
||||
grub_memcpy (&slaac->address, hwaddr, sizeof (slaac->address));
|
||||
slaac->next = card->slaac_list;
|
||||
card->slaac_list = slaac;
|
||||
return slaac;
|
||||
}
|
||||
|
||||
struct grub_net_network_level_interface *
|
||||
grub_net_ipv6_get_link_local (struct grub_net_card *card,
|
||||
const grub_net_link_level_address_t *hwaddr)
|
||||
{
|
||||
struct grub_net_network_level_interface *inf;
|
||||
char name[grub_strlen (card->name)
|
||||
+ GRUB_NET_MAX_STR_HWADDR_LEN
|
||||
+ sizeof (":link")];
|
||||
char *ptr;
|
||||
grub_net_network_level_address_t addr;
|
||||
|
||||
addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
|
||||
addr.ipv6[0] = grub_cpu_to_be64 (0xfe80ULL << 48);
|
||||
addr.ipv6[1] = grub_net_ipv6_get_id (hwaddr);
|
||||
|
||||
FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
|
||||
{
|
||||
if (inf->card == card
|
||||
&& grub_net_hwaddr_cmp (&inf->hwaddress, hwaddr) == 0
|
||||
&& grub_net_addr_cmp (&inf->address, &addr) == 0)
|
||||
return inf;
|
||||
}
|
||||
|
||||
ptr = grub_stpcpy (name, card->name);
|
||||
if (grub_net_hwaddr_cmp (&card->default_address, hwaddr) != 0)
|
||||
{
|
||||
ptr = grub_stpcpy (ptr, ":");
|
||||
grub_net_hwaddr_to_str (hwaddr, ptr);
|
||||
ptr += grub_strlen (ptr);
|
||||
}
|
||||
ptr = grub_stpcpy (ptr, ":link");
|
||||
return grub_net_add_addr (name, card, &addr, hwaddr, 0);
|
||||
}
|
||||
|
||||
/* FIXME: allow to specify mac address. */
|
||||
static grub_err_t
|
||||
grub_cmd_ipv6_autoconf (struct grub_command *cmd __attribute__ ((unused)),
|
||||
int argc, char **args)
|
||||
{
|
||||
struct grub_net_card *card;
|
||||
struct grub_net_network_level_interface **ifaces;
|
||||
grub_size_t ncards = 0;
|
||||
unsigned j = 0;
|
||||
int interval;
|
||||
grub_err_t err;
|
||||
struct grub_net_slaac_mac_list **slaacs;
|
||||
|
||||
FOR_NET_CARDS (card)
|
||||
{
|
||||
if (argc > 0 && grub_strcmp (card->name, args[0]) != 0)
|
||||
continue;
|
||||
ncards++;
|
||||
}
|
||||
|
||||
ifaces = grub_zalloc (ncards * sizeof (ifaces[0]));
|
||||
slaacs = grub_zalloc (ncards * sizeof (slaacs[0]));
|
||||
if (!ifaces || !slaacs)
|
||||
{
|
||||
grub_free (ifaces);
|
||||
grub_free (slaacs);
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
FOR_NET_CARDS (card)
|
||||
{
|
||||
if (argc > 0 && grub_strcmp (card->name, args[0]) != 0)
|
||||
continue;
|
||||
ifaces[j] = grub_net_ipv6_get_link_local (card, &card->default_address);
|
||||
if (!ifaces[j])
|
||||
{
|
||||
grub_free (ifaces);
|
||||
grub_free (slaacs);
|
||||
return grub_errno;
|
||||
}
|
||||
slaacs[j] = grub_net_ipv6_get_slaac (card, &card->default_address);
|
||||
if (!slaacs[j])
|
||||
{
|
||||
grub_free (ifaces);
|
||||
grub_free (slaacs);
|
||||
return grub_errno;
|
||||
}
|
||||
j++;
|
||||
}
|
||||
|
||||
for (interval = 200; interval < 10000; interval *= 2)
|
||||
{
|
||||
/* FIXME: send router solicitation. */
|
||||
int done = 1;
|
||||
for (j = 0; j < ncards; j++)
|
||||
{
|
||||
if (slaacs[j]->slaac_counter)
|
||||
continue;
|
||||
done = 0;
|
||||
}
|
||||
if (done)
|
||||
break;
|
||||
grub_net_poll_cards (interval);
|
||||
}
|
||||
|
||||
err = GRUB_ERR_NONE;
|
||||
for (j = 0; j < ncards; j++)
|
||||
{
|
||||
if (slaacs[j]->slaac_counter)
|
||||
continue;
|
||||
err = grub_error (GRUB_ERR_FILE_NOT_FOUND, "couldn't configure %s",
|
||||
ifaces[j]->card->name);
|
||||
}
|
||||
|
||||
grub_free (ifaces);
|
||||
grub_free (slaacs);
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline void
|
||||
grub_net_route_register (struct grub_net_route *route)
|
||||
|
@ -265,20 +411,22 @@ grub_net_addr_to_str (const grub_net_network_level_address_t *target, char *buf)
|
|||
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6:
|
||||
{
|
||||
char *ptr = buf;
|
||||
grub_uint32_t n = grub_be_to_cpu32 (target->ipv6[0]);
|
||||
grub_uint64_t n = grub_be_to_cpu64 (target->ipv6[0]);
|
||||
int i;
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
grub_snprintf (ptr, 6, "%x:", (n >> (48 - 16 * i)) & 0xffff);
|
||||
grub_snprintf (ptr, 6, "%" PRIxGRUB_UINT64_T ":",
|
||||
(n >> (48 - 16 * i)) & 0xffff);
|
||||
ptr += grub_strlen (ptr);
|
||||
}
|
||||
n = grub_be_to_cpu32 (target->ipv6[1]);
|
||||
n = grub_be_to_cpu64 (target->ipv6[1]);
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
grub_snprintf (ptr, 6, "%x:", (n >> (48 - 16 * i)) & 0xffff);
|
||||
grub_snprintf (ptr, 6, "%" PRIxGRUB_UINT64_T ":",
|
||||
(n >> (48 - 16 * i)) & 0xffff);
|
||||
ptr += grub_strlen (ptr);
|
||||
}
|
||||
grub_snprintf (ptr, 5, "%x", n & 0xffff);
|
||||
grub_snprintf (ptr, 5, "%" PRIxGRUB_UINT64_T, n & 0xffff);
|
||||
return;
|
||||
}
|
||||
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
|
||||
|
@ -290,18 +438,13 @@ grub_net_addr_to_str (const grub_net_network_level_address_t *target, char *buf)
|
|||
}
|
||||
return;
|
||||
}
|
||||
grub_printf ("Unknown address type %d\n", target->type);
|
||||
grub_snprintf (buf, GRUB_NET_MAX_STR_ADDR_LEN,
|
||||
"Unknown address type %d", target->type);
|
||||
}
|
||||
|
||||
/*
|
||||
Currently suppoerted adresses:
|
||||
ethernet: XX:XX:XX:XX:XX:XX
|
||||
*/
|
||||
|
||||
#define MAX_STR_HWADDR_LEN (sizeof ("XX:XX:XX:XX:XX:XX"))
|
||||
|
||||
static void
|
||||
hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str)
|
||||
void
|
||||
grub_net_hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str)
|
||||
{
|
||||
str[0] = 0;
|
||||
switch (addr->type)
|
||||
|
@ -312,7 +455,7 @@ hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str)
|
|||
unsigned i;
|
||||
for (ptr = str, i = 0; i < ARRAY_SIZE (addr->mac); i++)
|
||||
{
|
||||
grub_snprintf (ptr, MAX_STR_HWADDR_LEN - (ptr - str),
|
||||
grub_snprintf (ptr, GRUB_NET_MAX_STR_HWADDR_LEN - (ptr - str),
|
||||
"%02x:", addr->mac[i] & 0xff);
|
||||
ptr += (sizeof ("XX:") - 1);
|
||||
}
|
||||
|
@ -380,9 +523,9 @@ static void
|
|||
grub_net_network_level_interface_register (struct grub_net_network_level_interface *inter)
|
||||
{
|
||||
{
|
||||
char buf[MAX_STR_HWADDR_LEN];
|
||||
char buf[GRUB_NET_MAX_STR_HWADDR_LEN];
|
||||
char name[grub_strlen (inter->name) + sizeof ("net__mac")];
|
||||
hwaddr_to_str (&inter->hwaddress, buf);
|
||||
grub_net_hwaddr_to_str (&inter->hwaddress, buf);
|
||||
grub_snprintf (name, sizeof (name), "net_%s_mac", inter->name);
|
||||
grub_env_set (name, buf);
|
||||
grub_register_variable_hook (name, 0, hwaddr_set_env);
|
||||
|
@ -408,8 +551,8 @@ grub_net_network_level_interface_register (struct grub_net_network_level_interfa
|
|||
struct grub_net_network_level_interface *
|
||||
grub_net_add_addr (const char *name,
|
||||
struct grub_net_card *card,
|
||||
grub_net_network_level_address_t addr,
|
||||
grub_net_link_level_address_t hwaddress,
|
||||
const grub_net_network_level_address_t *addr,
|
||||
const grub_net_link_level_address_t *hwaddress,
|
||||
grub_net_interface_flags_t flags)
|
||||
{
|
||||
struct grub_net_network_level_interface *inter;
|
||||
|
@ -419,8 +562,8 @@ grub_net_add_addr (const char *name,
|
|||
return NULL;
|
||||
|
||||
inter->name = grub_strdup (name);
|
||||
grub_memcpy (&(inter->address), &addr, sizeof (inter->address));
|
||||
grub_memcpy (&(inter->hwaddress), &hwaddress, sizeof (inter->hwaddress));
|
||||
grub_memcpy (&(inter->address), addr, sizeof (inter->address));
|
||||
grub_memcpy (&(inter->hwaddress), hwaddress, sizeof (inter->hwaddress));
|
||||
inter->flags = flags;
|
||||
inter->card = card;
|
||||
inter->dhcp_ack = NULL;
|
||||
|
@ -428,10 +571,10 @@ grub_net_add_addr (const char *name,
|
|||
|
||||
grub_net_network_level_interface_register (inter);
|
||||
|
||||
if (addr.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4)
|
||||
if (addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4)
|
||||
{
|
||||
int mask = -1;
|
||||
grub_uint32_t ip_cpu = grub_be_to_cpu32 (addr.ipv4);
|
||||
grub_uint32_t ip_cpu = grub_be_to_cpu32 (addr->ipv4);
|
||||
if (!(ip_cpu & 0x80000000))
|
||||
mask = 8;
|
||||
else if (!(ip_cpu & 0x40000000))
|
||||
|
@ -498,7 +641,7 @@ grub_cmd_addaddr (struct grub_command *cmd __attribute__ ((unused)),
|
|||
if (card->flags & GRUB_NET_CARD_HWADDRESS_IMMUTABLE)
|
||||
flags |= GRUB_NET_INTERFACE_HWADDRESS_IMMUTABLE;
|
||||
|
||||
grub_net_add_addr (args[0], card, addr, card->default_address,
|
||||
grub_net_add_addr (args[0], card, &addr, &card->default_address,
|
||||
flags);
|
||||
return grub_errno;
|
||||
}
|
||||
|
@ -685,8 +828,8 @@ grub_cmd_listcards (struct grub_command *cmd __attribute__ ((unused)),
|
|||
struct grub_net_card *card;
|
||||
FOR_NET_CARDS(card)
|
||||
{
|
||||
char buf[MAX_STR_HWADDR_LEN];
|
||||
hwaddr_to_str (&card->default_address, buf);
|
||||
char buf[GRUB_NET_MAX_STR_HWADDR_LEN];
|
||||
grub_net_hwaddr_to_str (&card->default_address, buf);
|
||||
grub_printf ("%s %s\n", card->name, buf);
|
||||
}
|
||||
return GRUB_ERR_NONE;
|
||||
|
@ -700,9 +843,9 @@ grub_cmd_listaddrs (struct grub_command *cmd __attribute__ ((unused)),
|
|||
struct grub_net_network_level_interface *inf;
|
||||
FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
|
||||
{
|
||||
char bufh[MAX_STR_HWADDR_LEN];
|
||||
char bufh[GRUB_NET_MAX_STR_HWADDR_LEN];
|
||||
char bufn[GRUB_NET_MAX_STR_ADDR_LEN];
|
||||
hwaddr_to_str (&inf->hwaddress, bufh);
|
||||
grub_net_hwaddr_to_str (&inf->hwaddress, bufh);
|
||||
grub_net_addr_to_str (&inf->address, bufn);
|
||||
grub_printf ("%s %s %s\n", inf->name, bufh, bufn);
|
||||
}
|
||||
|
@ -1060,13 +1203,18 @@ static void *fini_hnd;
|
|||
|
||||
static grub_command_t cmd_addaddr, cmd_deladdr, cmd_addroute, cmd_delroute;
|
||||
static grub_command_t cmd_lsroutes, cmd_lscards;
|
||||
static grub_command_t cmd_lsaddr;
|
||||
static grub_command_t cmd_lsaddr, cmd_slaac;
|
||||
|
||||
GRUB_MOD_INIT(net)
|
||||
{
|
||||
cmd_addaddr = grub_register_command ("net_add_addr", grub_cmd_addaddr,
|
||||
"SHORTNAME CARD ADDRESS [HWADDRESS]",
|
||||
N_("Add a network address."));
|
||||
cmd_slaac = grub_register_command ("net_ipv6_autoconf",
|
||||
grub_cmd_ipv6_autoconf,
|
||||
"[CARD [HWADDRESS]]",
|
||||
N_("Perform an IPV6 autoconfiguration"));
|
||||
|
||||
cmd_deladdr = grub_register_command ("net_del_addr", grub_cmd_deladdr,
|
||||
"SHORTNAME",
|
||||
N_("Delete a network address."));
|
||||
|
@ -1102,6 +1250,7 @@ GRUB_MOD_FINI(net)
|
|||
grub_unregister_command (cmd_lsroutes);
|
||||
grub_unregister_command (cmd_lscards);
|
||||
grub_unregister_command (cmd_lsaddr);
|
||||
grub_unregister_command (cmd_slaac);
|
||||
grub_fs_unregister (&grub_net_fs);
|
||||
grub_net_open = NULL;
|
||||
grub_net_fini_hw (0);
|
||||
|
|
|
@ -695,6 +695,13 @@ grub_net_recv_tcp_packet (struct grub_net_buff *nb,
|
|||
grub_net_tcp_socket_t sock;
|
||||
grub_err_t err;
|
||||
|
||||
/* Ignore broadcast. */
|
||||
if (!inf)
|
||||
{
|
||||
grub_netbuff_free (nb);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
tcph = (struct tcphdr *) nb->data;
|
||||
if ((grub_be_to_cpu16 (tcph->flags) >> 12) < 5)
|
||||
{
|
||||
|
|
|
@ -140,6 +140,13 @@ grub_net_recv_udp_packet (struct grub_net_buff *nb,
|
|||
grub_net_udp_socket_t sock;
|
||||
grub_err_t err;
|
||||
|
||||
/* Ignore broadcast. */
|
||||
if (!inf)
|
||||
{
|
||||
grub_netbuff_free (nb);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
udph = (struct udphdr *) nb->data;
|
||||
if (nb->tail - nb->data < (grub_ssize_t) sizeof (*udph))
|
||||
{
|
||||
|
|
|
@ -97,6 +97,14 @@ typedef struct grub_net_packets
|
|||
#include <grub/efi/api.h>
|
||||
#endif
|
||||
|
||||
struct grub_net_slaac_mac_list
|
||||
{
|
||||
struct grub_net_slaac_mac_list *next;
|
||||
grub_net_link_level_address_t address;
|
||||
int slaac_counter;
|
||||
char *name;
|
||||
};
|
||||
|
||||
struct grub_net_card
|
||||
{
|
||||
struct grub_net_card *next;
|
||||
|
@ -109,6 +117,7 @@ struct grub_net_card
|
|||
unsigned idle_poll_delay_ms;
|
||||
grub_uint64_t last_poll;
|
||||
grub_size_t mtu;
|
||||
struct grub_net_slaac_mac_list *slaac_list;
|
||||
union
|
||||
{
|
||||
#ifdef GRUB_MACHINE_EFI
|
||||
|
@ -282,8 +291,8 @@ grub_net_session_recv (struct grub_net_session *session, void *buf,
|
|||
struct grub_net_network_level_interface *
|
||||
grub_net_add_addr (const char *name,
|
||||
struct grub_net_card *card,
|
||||
grub_net_network_level_address_t addr,
|
||||
grub_net_link_level_address_t hwaddress,
|
||||
const grub_net_network_level_address_t *addr,
|
||||
const grub_net_link_level_address_t *hwaddress,
|
||||
grub_net_interface_flags_t flags);
|
||||
|
||||
extern struct grub_net_network_level_interface *grub_net_network_level_interfaces;
|
||||
|
@ -404,13 +413,22 @@ grub_net_addr_cmp (const grub_net_network_level_address_t *a,
|
|||
/*
|
||||
Currently supported adresses:
|
||||
IPv4: XXX.XXX.XXX.XXX
|
||||
IPv&: XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX
|
||||
IPv6: XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX
|
||||
*/
|
||||
#define GRUB_NET_MAX_STR_ADDR_LEN sizeof ("XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX")
|
||||
|
||||
/*
|
||||
Currently suppoerted adresses:
|
||||
ethernet: XX:XX:XX:XX:XX:XX
|
||||
*/
|
||||
|
||||
#define GRUB_NET_MAX_STR_HWADDR_LEN (sizeof ("XX:XX:XX:XX:XX:XX"))
|
||||
|
||||
void
|
||||
grub_net_addr_to_str (const grub_net_network_level_address_t *target,
|
||||
char *buf);
|
||||
void
|
||||
grub_net_hwaddr_to_str (const grub_net_link_level_address_t *addr, char *str);
|
||||
|
||||
extern struct grub_net_network_level_interface *grub_net_network_level_interfaces;
|
||||
#define FOR_NET_NETWORK_LEVEL_INTERFACES(var) for (var = grub_net_network_level_interfaces; var; var = var->next)
|
||||
|
|
|
@ -36,6 +36,6 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf,
|
|||
grub_net_ethertype_t ethertype);
|
||||
grub_err_t
|
||||
grub_net_recv_ethernet_packet (struct grub_net_buff *nb,
|
||||
const struct grub_net_card *card);
|
||||
struct grub_net_card *card);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -25,20 +25,29 @@ typedef enum grub_net_ip_protocol
|
|||
{
|
||||
GRUB_NET_IP_ICMP = 1,
|
||||
GRUB_NET_IP_TCP = 6,
|
||||
GRUB_NET_IP_UDP = 17
|
||||
GRUB_NET_IP_UDP = 17,
|
||||
GRUB_NET_IP_ICMPV6 = 58
|
||||
} grub_net_ip_protocol_t;
|
||||
#define GRUB_NET_IP_BROADCAST 0xFFFFFFFF
|
||||
|
||||
static inline grub_uint64_t
|
||||
grub_net_ipv6_get_id (const grub_net_link_level_address_t *addr)
|
||||
{
|
||||
return grub_cpu_to_be64 (((grub_uint64_t) (addr->mac[0] ^ 2) << 56)
|
||||
| ((grub_uint64_t) addr->mac[1] << 48)
|
||||
| ((grub_uint64_t) addr->mac[2] << 40)
|
||||
| 0xfffe000000ULL
|
||||
| ((grub_uint64_t) addr->mac[3] << 16)
|
||||
| ((grub_uint64_t) addr->mac[4] << 8)
|
||||
| ((grub_uint64_t) addr->mac[5]));
|
||||
}
|
||||
|
||||
grub_uint16_t grub_net_ip_chksum(void *ipv, grub_size_t len);
|
||||
|
||||
grub_err_t
|
||||
grub_net_recv_ip4_packets (struct grub_net_buff *nb,
|
||||
const struct grub_net_card *card,
|
||||
const grub_net_link_level_address_t *hwaddress);
|
||||
grub_err_t
|
||||
grub_net_recv_ip6_packets (struct grub_net_buff *nb,
|
||||
const struct grub_net_card *card,
|
||||
const grub_net_link_level_address_t *hwaddress);
|
||||
grub_net_recv_ip_packets (struct grub_net_buff *nb,
|
||||
struct grub_net_card *card,
|
||||
const grub_net_link_level_address_t *hwaddress);
|
||||
|
||||
grub_err_t
|
||||
grub_net_send_ip_packet (struct grub_net_network_level_interface *inf,
|
||||
|
@ -51,6 +60,12 @@ grub_net_recv_icmp_packet (struct grub_net_buff *nb,
|
|||
struct grub_net_network_level_interface *inf,
|
||||
const grub_net_network_level_address_t *src);
|
||||
grub_err_t
|
||||
grub_net_recv_icmp6_packet (struct grub_net_buff *nb,
|
||||
struct grub_net_card *card,
|
||||
struct grub_net_network_level_interface *inf,
|
||||
const grub_net_network_level_address_t *source,
|
||||
const grub_net_network_level_address_t *dest);
|
||||
grub_err_t
|
||||
grub_net_recv_udp_packet (struct grub_net_buff *nb,
|
||||
struct grub_net_network_level_interface *inf,
|
||||
const grub_net_network_level_address_t *src);
|
||||
|
@ -65,4 +80,8 @@ grub_net_ip_transport_checksum (struct grub_net_buff *nb,
|
|||
const grub_net_network_level_address_t *src,
|
||||
const grub_net_network_level_address_t *dst);
|
||||
|
||||
struct grub_net_network_level_interface *
|
||||
grub_net_ipv6_get_link_local (struct grub_net_card *card,
|
||||
const grub_net_link_level_address_t *hwaddr);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Reference in a new issue