some more ipv6 code

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2011-10-12 10:20:55 +02:00
parent d5e60b1ba0
commit a53cf6534d
12 changed files with 528 additions and 60 deletions

View File

@ -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;

View File

@ -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)

View File

@ -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;

View File

@ -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
View 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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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)
{

View File

@ -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))
{

View File

@ -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)

View File

@ -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

View File

@ -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