more ipv6 code. Now ipv6 ping succeeds
This commit is contained in:
parent
a53cf6534d
commit
7c006811f8
9 changed files with 541 additions and 141 deletions
|
@ -46,41 +46,10 @@ struct arphdr {
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
|
||||||
struct arp_entry {
|
|
||||||
int avail;
|
|
||||||
grub_net_network_level_address_t nl_address;
|
|
||||||
grub_net_link_level_address_t ll_address;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct arp_entry arp_table[10];
|
|
||||||
static grub_int8_t new_table_entry = -1;
|
|
||||||
|
|
||||||
static void
|
|
||||||
arp_init_table (void)
|
|
||||||
{
|
|
||||||
grub_memset (arp_table, 0, sizeof (arp_table));
|
|
||||||
new_table_entry = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct arp_entry *
|
|
||||||
arp_find_entry (const grub_net_network_level_address_t *proto)
|
|
||||||
{
|
|
||||||
unsigned i;
|
|
||||||
for (i = 0; i < ARRAY_SIZE (arp_table); i++)
|
|
||||||
{
|
|
||||||
if (arp_table[i].avail == 1 &&
|
|
||||||
grub_net_addr_cmp (&arp_table[i].nl_address, proto) == 0)
|
|
||||||
return &(arp_table[i]);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
grub_err_t
|
grub_err_t
|
||||||
grub_net_arp_resolve (struct grub_net_network_level_interface *inf,
|
grub_net_arp_send_request (struct grub_net_network_level_interface *inf,
|
||||||
const grub_net_network_level_address_t *proto_addr,
|
const grub_net_network_level_address_t *proto_addr)
|
||||||
grub_net_link_level_address_t *hw_addr)
|
|
||||||
{
|
{
|
||||||
struct arp_entry *entry;
|
|
||||||
struct grub_net_buff nb;
|
struct grub_net_buff nb;
|
||||||
struct arphdr *arp_header;
|
struct arphdr *arp_header;
|
||||||
grub_net_link_level_address_t target_hw_addr;
|
grub_net_link_level_address_t target_hw_addr;
|
||||||
|
@ -90,32 +59,11 @@ grub_net_arp_resolve (struct grub_net_network_level_interface *inf,
|
||||||
grub_size_t addrlen;
|
grub_size_t addrlen;
|
||||||
grub_uint16_t etherpro;
|
grub_uint16_t etherpro;
|
||||||
|
|
||||||
if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4
|
|
||||||
&& proto_addr->ipv4 == 0xffffffff)
|
|
||||||
{
|
|
||||||
hw_addr->type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
|
|
||||||
grub_memset (hw_addr->mac, -1, 6);
|
|
||||||
return GRUB_ERR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check cache table. */
|
|
||||||
entry = arp_find_entry (proto_addr);
|
|
||||||
if (entry)
|
|
||||||
{
|
|
||||||
*hw_addr = entry->ll_address;
|
|
||||||
return GRUB_ERR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4)
|
if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4)
|
||||||
{
|
{
|
||||||
addrlen = 4;
|
addrlen = 4;
|
||||||
etherpro = GRUB_NET_ETHERTYPE_IP;
|
etherpro = GRUB_NET_ETHERTYPE_IP;
|
||||||
}
|
}
|
||||||
else if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6)
|
|
||||||
{
|
|
||||||
addrlen = 16;
|
|
||||||
etherpro = GRUB_NET_ETHERTYPE_IP6;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "unsupported address family");
|
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "unsupported address family");
|
||||||
|
|
||||||
|
@ -141,45 +89,39 @@ grub_net_arp_resolve (struct grub_net_network_level_interface *inf,
|
||||||
|
|
||||||
aux += 6;
|
aux += 6;
|
||||||
/* Sender protocol address */
|
/* Sender protocol address */
|
||||||
if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4)
|
grub_memcpy (aux, &inf->address.ipv4, 4);
|
||||||
grub_memcpy (aux, &inf->address.ipv4, 4);
|
|
||||||
else
|
|
||||||
grub_memcpy (aux, &inf->address.ipv6, 16);
|
|
||||||
aux += addrlen;
|
aux += addrlen;
|
||||||
/* Target hardware address */
|
/* Target hardware address */
|
||||||
for (i = 0; i < 6; i++)
|
for (i = 0; i < 6; i++)
|
||||||
aux[i] = 0x00;
|
aux[i] = 0x00;
|
||||||
aux += 6;
|
aux += 6;
|
||||||
/* Target protocol address */
|
/* Target protocol address */
|
||||||
if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4)
|
grub_memcpy (aux, &proto_addr->ipv4, 4);
|
||||||
grub_memcpy (aux, &proto_addr->ipv4, 4);
|
|
||||||
else
|
|
||||||
grub_memcpy (aux, &proto_addr->ipv6, 16);
|
|
||||||
grub_memset (&target_hw_addr.mac, 0xff, 6);
|
grub_memset (&target_hw_addr.mac, 0xff, 6);
|
||||||
|
|
||||||
send_ethernet_packet (inf, &nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP);
|
send_ethernet_packet (inf, &nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP);
|
||||||
for (i = 0; i < GRUB_NET_TRIES; i++)
|
for (i = 0; i < GRUB_NET_TRIES; i++)
|
||||||
{
|
{
|
||||||
entry = arp_find_entry (proto_addr);
|
if (grub_net_link_layer_resolve_check (inf, proto_addr))
|
||||||
if (entry)
|
return GRUB_ERR_NONE;
|
||||||
{
|
|
||||||
grub_memcpy (hw_addr, &entry->ll_address, sizeof (*hw_addr));
|
|
||||||
return GRUB_ERR_NONE;
|
|
||||||
}
|
|
||||||
grub_net_poll_cards (GRUB_NET_INTERVAL);
|
grub_net_poll_cards (GRUB_NET_INTERVAL);
|
||||||
|
if (grub_net_link_layer_resolve_check (inf, proto_addr))
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
send_ethernet_packet (inf, &nb, target_hw_addr, GRUB_NET_ETHERTYPE_ARP);
|
||||||
}
|
}
|
||||||
|
|
||||||
return grub_error (GRUB_ERR_TIMEOUT, "timeout: could not resolve hardware address");
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_err_t
|
grub_err_t
|
||||||
grub_net_arp_receive (struct grub_net_buff *nb)
|
grub_net_arp_receive (struct grub_net_buff *nb,
|
||||||
|
struct grub_net_card *card)
|
||||||
{
|
{
|
||||||
struct arphdr *arp_header = (struct arphdr *) nb->data;
|
struct arphdr *arp_header = (struct arphdr *) nb->data;
|
||||||
struct arp_entry *entry;
|
|
||||||
grub_uint8_t *sender_hardware_address;
|
grub_uint8_t *sender_hardware_address;
|
||||||
grub_uint8_t *target_hardware_address;
|
grub_uint8_t *target_hardware_address;
|
||||||
grub_net_network_level_address_t sender_addr, target_addr;
|
grub_net_network_level_address_t sender_addr, target_addr;
|
||||||
|
grub_net_link_level_address_t sender_hw_addr;
|
||||||
struct grub_net_network_level_interface *inf;
|
struct grub_net_network_level_interface *inf;
|
||||||
grub_uint8_t *sender_protocol_address, *target_protocol_address;
|
grub_uint8_t *sender_protocol_address, *target_protocol_address;
|
||||||
|
|
||||||
|
@ -196,35 +138,13 @@ grub_net_arp_receive (struct grub_net_buff *nb)
|
||||||
grub_memcpy (&sender_addr.ipv4, sender_protocol_address, 4);
|
grub_memcpy (&sender_addr.ipv4, sender_protocol_address, 4);
|
||||||
grub_memcpy (&target_addr.ipv4, target_protocol_address, 4);
|
grub_memcpy (&target_addr.ipv4, target_protocol_address, 4);
|
||||||
}
|
}
|
||||||
else if (grub_be_to_cpu16 (arp_header->pro) == GRUB_NET_ETHERTYPE_IP6
|
|
||||||
&& arp_header->pln == 16)
|
|
||||||
{
|
|
||||||
sender_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
|
|
||||||
target_addr.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
|
|
||||||
grub_memcpy (&sender_addr.ipv6, sender_protocol_address, 16);
|
|
||||||
grub_memcpy (&target_addr.ipv6, target_protocol_address, 16);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
|
|
||||||
/* Check if the sender is in the cache table. */
|
sender_hw_addr.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
|
||||||
entry = arp_find_entry (&sender_addr);
|
grub_memcpy (sender_hw_addr.mac, &sender_hardware_address,
|
||||||
/* Update sender hardware address. */
|
sizeof (sender_hw_addr.mac));
|
||||||
if (entry)
|
grub_net_link_layer_add_address (card, &sender_addr, &sender_hw_addr, 1);
|
||||||
grub_memcpy (entry->ll_address.mac, sender_hardware_address, 6);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Add sender to cache table. */
|
|
||||||
if (new_table_entry == -1)
|
|
||||||
arp_init_table ();
|
|
||||||
entry = &(arp_table[new_table_entry]);
|
|
||||||
entry->avail = 1;
|
|
||||||
entry->nl_address = sender_addr;
|
|
||||||
grub_memcpy (entry->ll_address.mac, sender_hardware_address, 6);
|
|
||||||
new_table_entry++;
|
|
||||||
if (new_table_entry == ARRAY_SIZE (arp_table))
|
|
||||||
new_table_entry = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
|
FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
|
||||||
{
|
{
|
||||||
|
|
|
@ -80,8 +80,8 @@ send_ethernet_packet (struct grub_net_network_level_interface *inf,
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_err_t
|
grub_err_t
|
||||||
grub_net_recv_ethernet_packet (struct grub_net_buff * nb,
|
grub_net_recv_ethernet_packet (struct grub_net_buff *nb,
|
||||||
struct grub_net_card * card)
|
struct grub_net_card *card)
|
||||||
{
|
{
|
||||||
struct etherhdr *eth;
|
struct etherhdr *eth;
|
||||||
struct llchdr *llch;
|
struct llchdr *llch;
|
||||||
|
@ -118,7 +118,7 @@ grub_net_recv_ethernet_packet (struct grub_net_buff * nb,
|
||||||
{
|
{
|
||||||
/* ARP packet. */
|
/* ARP packet. */
|
||||||
case GRUB_NET_ETHERTYPE_ARP:
|
case GRUB_NET_ETHERTYPE_ARP:
|
||||||
grub_net_arp_receive (nb);
|
grub_net_arp_receive (nb, card);
|
||||||
grub_netbuff_free (nb);
|
grub_netbuff_free (nb);
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
/* IP packet. */
|
/* IP packet. */
|
||||||
|
|
|
@ -43,10 +43,15 @@ struct router_adv
|
||||||
grub_uint8_t options[0];
|
grub_uint8_t options[0];
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
struct prefix_option
|
struct option_header
|
||||||
{
|
{
|
||||||
grub_uint8_t type;
|
grub_uint8_t type;
|
||||||
grub_uint8_t len;
|
grub_uint8_t len;
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct prefix_option
|
||||||
|
{
|
||||||
|
struct option_header header;
|
||||||
grub_uint8_t prefixlen;
|
grub_uint8_t prefixlen;
|
||||||
grub_uint8_t flags;
|
grub_uint8_t flags;
|
||||||
grub_uint32_t valid_lifetime;
|
grub_uint32_t valid_lifetime;
|
||||||
|
@ -55,6 +60,18 @@ struct prefix_option
|
||||||
grub_uint64_t prefix[2];
|
grub_uint64_t prefix[2];
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct neighbour_solicit
|
||||||
|
{
|
||||||
|
grub_uint32_t reserved;
|
||||||
|
grub_uint64_t target[2];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
struct neighbour_advertise
|
||||||
|
{
|
||||||
|
grub_uint32_t flags;
|
||||||
|
grub_uint64_t target[2];
|
||||||
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
FLAG_SLAAC = 0x40
|
FLAG_SLAAC = 0x40
|
||||||
|
@ -64,7 +81,22 @@ enum
|
||||||
{
|
{
|
||||||
ICMP6_ECHO = 128,
|
ICMP6_ECHO = 128,
|
||||||
ICMP6_ECHO_REPLY = 129,
|
ICMP6_ECHO_REPLY = 129,
|
||||||
ICMP6_ROUTER_ADVERTISE = 134
|
ICMP6_ROUTER_ADVERTISE = 134,
|
||||||
|
ICMP6_NEIGHBOUR_SOLICIT = 135,
|
||||||
|
ICMP6_NEIGHBOUR_ADVERTISE = 136,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
OPTION_SOURCE_LINK_LAYER_ADDRESS = 1,
|
||||||
|
OPTION_TARGET_LINK_LAYER_ADDRESS = 2,
|
||||||
|
OPTION_PREFIX = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
FLAG_SOLICITED = (1 << 30),
|
||||||
|
FLAG_OVERRIDE = (1 << 29)
|
||||||
};
|
};
|
||||||
|
|
||||||
grub_err_t
|
grub_err_t
|
||||||
|
@ -72,7 +104,8 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb,
|
||||||
struct grub_net_card *card,
|
struct grub_net_card *card,
|
||||||
struct grub_net_network_level_interface *inf,
|
struct grub_net_network_level_interface *inf,
|
||||||
const grub_net_network_level_address_t *source,
|
const grub_net_network_level_address_t *source,
|
||||||
const grub_net_network_level_address_t *dest)
|
const grub_net_network_level_address_t *dest,
|
||||||
|
grub_uint8_t ttl)
|
||||||
{
|
{
|
||||||
struct icmp_header *icmph;
|
struct icmp_header *icmph;
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
|
@ -107,7 +140,10 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb,
|
||||||
|
|
||||||
err = grub_netbuff_pull (nb, sizeof (*icmph));
|
err = grub_netbuff_pull (nb, sizeof (*icmph));
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
{
|
||||||
|
grub_netbuff_free (nb);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
grub_dprintf ("net", "ICMPv6 message: %02x, %02x\n",
|
grub_dprintf ("net", "ICMPv6 message: %02x, %02x\n",
|
||||||
icmph->type, icmph->code);
|
icmph->type, icmph->code);
|
||||||
|
@ -154,24 +190,180 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb,
|
||||||
grub_netbuff_free (nb_reply);
|
grub_netbuff_free (nb_reply);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
case ICMP6_ROUTER_ADVERTISE:
|
case ICMP6_NEIGHBOUR_SOLICIT:
|
||||||
{
|
{
|
||||||
|
struct neighbour_solicit *nbh;
|
||||||
|
struct grub_net_buff *nb_reply;
|
||||||
|
struct option_header *ohdr;
|
||||||
|
struct neighbour_advertise *adv;
|
||||||
|
struct icmp_header *icmphr;
|
||||||
grub_uint8_t *ptr;
|
grub_uint8_t *ptr;
|
||||||
|
|
||||||
if (icmph->code)
|
if (icmph->code)
|
||||||
break;
|
break;
|
||||||
|
if (ttl != 0xff)
|
||||||
|
break;
|
||||||
|
nbh = (struct neighbour_solicit *) nb->data;
|
||||||
err = grub_netbuff_pull (nb, sizeof (struct router_adv));
|
err = grub_netbuff_pull (nb, sizeof (struct router_adv));
|
||||||
if (err)
|
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]);
|
grub_netbuff_free (nb);
|
||||||
if (ptr + 2 >= nb->tail || ptr[1] == 0)
|
return err;
|
||||||
|
}
|
||||||
|
for (ptr = (grub_uint8_t *) nb->data; ptr < nb->tail;
|
||||||
|
ptr += ohdr->len * 8)
|
||||||
|
{
|
||||||
|
ohdr = (struct option_header *) ptr;
|
||||||
|
if (ohdr->len == 0 || ptr + 8 * ohdr->len > nb->tail)
|
||||||
{
|
{
|
||||||
grub_netbuff_free (nb);
|
grub_netbuff_free (nb);
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
if (ptr[0] == 3 && ptr[1] == 4)
|
if (ohdr->type == OPTION_SOURCE_LINK_LAYER_ADDRESS
|
||||||
|
&& ohdr->len == 1)
|
||||||
|
{
|
||||||
|
grub_net_link_level_address_t ll_address;
|
||||||
|
ll_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
|
||||||
|
grub_memcpy (ll_address.mac, ohdr + 1, sizeof (ll_address.mac));
|
||||||
|
grub_net_link_layer_add_address (card, source, &ll_address, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FOR_NET_NETWORK_LEVEL_INTERFACES (inf)
|
||||||
|
{
|
||||||
|
if (inf->card == card
|
||||||
|
&& inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6
|
||||||
|
&& grub_memcmp (&inf->address.ipv6, &nbh->target, 16) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!inf)
|
||||||
|
break;
|
||||||
|
|
||||||
|
nb_reply = grub_netbuff_alloc (sizeof (struct neighbour_advertise)
|
||||||
|
+ sizeof (struct option_header)
|
||||||
|
+ 6
|
||||||
|
+ sizeof (struct icmp_header)
|
||||||
|
+ GRUB_NET_OUR_IPV6_HEADER_SIZE
|
||||||
|
+ GRUB_NET_MAX_LINK_HEADER_SIZE);
|
||||||
|
if (!nb_reply)
|
||||||
|
{
|
||||||
|
grub_netbuff_free (nb);
|
||||||
|
return grub_errno;
|
||||||
|
}
|
||||||
|
err = grub_netbuff_reserve (nb_reply,
|
||||||
|
sizeof (struct neighbour_advertise)
|
||||||
|
+ sizeof (struct option_header)
|
||||||
|
+ 6
|
||||||
|
+ sizeof (struct icmp_header)
|
||||||
|
+ GRUB_NET_OUR_IPV6_HEADER_SIZE
|
||||||
|
+ GRUB_NET_MAX_LINK_HEADER_SIZE);
|
||||||
|
if (err)
|
||||||
|
goto ndp_fail;
|
||||||
|
|
||||||
|
err = grub_netbuff_push (nb_reply, 6);
|
||||||
|
if (err)
|
||||||
|
goto ndp_fail;
|
||||||
|
grub_memcpy (nb_reply->data, inf->hwaddress.mac, 6);
|
||||||
|
err = grub_netbuff_push (nb_reply, sizeof (*ohdr));
|
||||||
|
if (err)
|
||||||
|
goto ndp_fail;
|
||||||
|
ohdr = (struct option_header *) nb_reply->data;
|
||||||
|
ohdr->type = OPTION_TARGET_LINK_LAYER_ADDRESS;
|
||||||
|
ohdr->len = 1;
|
||||||
|
err = grub_netbuff_push (nb_reply, sizeof (*adv));
|
||||||
|
if (err)
|
||||||
|
goto ndp_fail;
|
||||||
|
adv = (struct neighbour_advertise *) nb_reply->data;
|
||||||
|
adv->flags = grub_cpu_to_be32_compile_time (FLAG_SOLICITED
|
||||||
|
| FLAG_OVERRIDE);
|
||||||
|
grub_memcpy (&adv->target, &nbh->target, 16);
|
||||||
|
|
||||||
|
err = grub_netbuff_push (nb_reply, sizeof (*icmphr));
|
||||||
|
if (err)
|
||||||
|
goto ndp_fail;
|
||||||
|
icmphr = (struct icmp_header *) nb_reply->data;
|
||||||
|
icmphr->type = ICMP6_NEIGHBOUR_ADVERTISE;
|
||||||
|
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);
|
||||||
|
|
||||||
|
ndp_fail:
|
||||||
|
grub_netbuff_free (nb);
|
||||||
|
grub_netbuff_free (nb_reply);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
case ICMP6_NEIGHBOUR_ADVERTISE:
|
||||||
|
{
|
||||||
|
struct neighbour_advertise *nbh;
|
||||||
|
grub_uint8_t *ptr;
|
||||||
|
struct option_header *ohdr;
|
||||||
|
|
||||||
|
if (icmph->code)
|
||||||
|
break;
|
||||||
|
if (ttl != 0xff)
|
||||||
|
break;
|
||||||
|
nbh = (struct neighbour_advertise *) nb->data;
|
||||||
|
err = grub_netbuff_pull (nb, sizeof (*nbh));
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
grub_netbuff_free (nb);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ptr = (grub_uint8_t *) nb->data; ptr < nb->tail;
|
||||||
|
ptr += ohdr->len * 8)
|
||||||
|
{
|
||||||
|
ohdr = (struct option_header *) ptr;
|
||||||
|
if (ohdr->len == 0 || ptr + 8 * ohdr->len > nb->tail)
|
||||||
|
{
|
||||||
|
grub_netbuff_free (nb);
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
if (ohdr->type == OPTION_TARGET_LINK_LAYER_ADDRESS
|
||||||
|
&& ohdr->len == 1)
|
||||||
|
{
|
||||||
|
grub_net_link_level_address_t ll_address;
|
||||||
|
ll_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
|
||||||
|
grub_memcpy (ll_address.mac, ohdr + 1, sizeof (ll_address.mac));
|
||||||
|
grub_net_link_layer_add_address (card, source, &ll_address, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ICMP6_ROUTER_ADVERTISE:
|
||||||
|
{
|
||||||
|
grub_uint8_t *ptr;
|
||||||
|
struct option_header *ohdr;
|
||||||
|
if (icmph->code)
|
||||||
|
break;
|
||||||
|
err = grub_netbuff_pull (nb, sizeof (struct router_adv));
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
grub_netbuff_free (nb);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
for (ptr = (grub_uint8_t *) nb->data; ptr < nb->tail;
|
||||||
|
ptr += ohdr->len * 8)
|
||||||
|
{
|
||||||
|
ohdr = (struct option_header *) ptr;
|
||||||
|
if (ohdr->len == 0 || ptr + 8 * ohdr->len > nb->tail)
|
||||||
|
{
|
||||||
|
grub_netbuff_free (nb);
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
if (ohdr->type == OPTION_SOURCE_LINK_LAYER_ADDRESS
|
||||||
|
&& ohdr->len == 1)
|
||||||
|
{
|
||||||
|
grub_net_link_level_address_t ll_address;
|
||||||
|
ll_address.type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
|
||||||
|
grub_memcpy (ll_address.mac, ohdr + 1, sizeof (ll_address.mac));
|
||||||
|
grub_net_link_layer_add_address (card, source, &ll_address, 0);
|
||||||
|
}
|
||||||
|
if (ohdr->type == OPTION_PREFIX && ohdr->len == 4)
|
||||||
{
|
{
|
||||||
struct prefix_option *opt = (struct prefix_option *) ptr;
|
struct prefix_option *opt = (struct prefix_option *) ptr;
|
||||||
struct grub_net_slaac_mac_list *slaac;
|
struct grub_net_slaac_mac_list *slaac;
|
||||||
|
@ -181,7 +373,6 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb,
|
||||||
> grub_be_to_cpu32 (opt->valid_lifetime))
|
> grub_be_to_cpu32 (opt->valid_lifetime))
|
||||||
|| opt->prefixlen != 64)
|
|| opt->prefixlen != 64)
|
||||||
{
|
{
|
||||||
ptr += ptr[1] * 8;
|
|
||||||
grub_dprintf ("net", "discarded prefix: %d, %d, %d, %d\n",
|
grub_dprintf ("net", "discarded prefix: %d, %d, %d, %d\n",
|
||||||
!(opt->flags & FLAG_SLAAC),
|
!(opt->flags & FLAG_SLAAC),
|
||||||
(grub_be_to_cpu64 (opt->prefix[0]) >> 48) == 0xfe80,
|
(grub_be_to_cpu64 (opt->prefix[0]) >> 48) == 0xfe80,
|
||||||
|
@ -223,7 +414,6 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ptr += ptr[1] * 8;
|
|
||||||
}
|
}
|
||||||
if (ptr != nb->tail)
|
if (ptr != nb->tail)
|
||||||
break;
|
break;
|
||||||
|
@ -233,3 +423,91 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb,
|
||||||
grub_netbuff_free (nb);
|
grub_netbuff_free (nb);
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_net_icmp6_send_request (struct grub_net_network_level_interface *inf,
|
||||||
|
const grub_net_network_level_address_t *proto_addr)
|
||||||
|
{
|
||||||
|
struct grub_net_buff *nb;
|
||||||
|
grub_err_t err = GRUB_ERR_NONE;
|
||||||
|
int i;
|
||||||
|
struct option_header *ohdr;
|
||||||
|
struct neighbour_solicit *sol;
|
||||||
|
struct icmp_header *icmphr;
|
||||||
|
grub_net_network_level_address_t multicast;
|
||||||
|
|
||||||
|
multicast.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
|
||||||
|
multicast.ipv6[0] = grub_be_to_cpu64_compile_time (0xff02ULL << 48);
|
||||||
|
multicast.ipv6[1] = (grub_be_to_cpu64_compile_time (0x01ff000000ULL)
|
||||||
|
| (proto_addr->ipv6[1]
|
||||||
|
& grub_be_to_cpu64_compile_time (0xffffff)));
|
||||||
|
|
||||||
|
nb = grub_netbuff_alloc (sizeof (struct neighbour_solicit)
|
||||||
|
+ sizeof (struct option_header)
|
||||||
|
+ 6
|
||||||
|
+ sizeof (struct icmp_header)
|
||||||
|
+ GRUB_NET_OUR_IPV6_HEADER_SIZE
|
||||||
|
+ GRUB_NET_MAX_LINK_HEADER_SIZE);
|
||||||
|
if (!nb)
|
||||||
|
return grub_errno;
|
||||||
|
err = grub_netbuff_reserve (nb,
|
||||||
|
sizeof (struct neighbour_solicit)
|
||||||
|
+ sizeof (struct option_header)
|
||||||
|
+ 6
|
||||||
|
+ sizeof (struct icmp_header)
|
||||||
|
+ GRUB_NET_OUR_IPV6_HEADER_SIZE
|
||||||
|
+ GRUB_NET_MAX_LINK_HEADER_SIZE);
|
||||||
|
err = grub_netbuff_push (nb, 6);
|
||||||
|
if (err)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
grub_memcpy (nb->data, inf->hwaddress.mac, 6);
|
||||||
|
err = grub_netbuff_push (nb, sizeof (*ohdr));
|
||||||
|
if (err)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
ohdr = (struct option_header *) nb->data;
|
||||||
|
ohdr->type = OPTION_TARGET_LINK_LAYER_ADDRESS;
|
||||||
|
ohdr->len = 1;
|
||||||
|
err = grub_netbuff_push (nb, sizeof (*sol));
|
||||||
|
if (err)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
sol = (struct neighbour_solicit *) nb->data;
|
||||||
|
sol->reserved = 0;
|
||||||
|
grub_memcpy (&sol->target, &proto_addr->ipv6, 16);
|
||||||
|
|
||||||
|
err = grub_netbuff_push (nb, sizeof (*icmphr));
|
||||||
|
if (err)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
icmphr = (struct icmp_header *) nb->data;
|
||||||
|
icmphr->type = ICMP6_NEIGHBOUR_ADVERTISE;
|
||||||
|
icmphr->code = 0;
|
||||||
|
icmphr->checksum = 0;
|
||||||
|
icmphr->checksum = grub_net_ip_transport_checksum (nb,
|
||||||
|
GRUB_NET_IP_ICMPV6,
|
||||||
|
&inf->address,
|
||||||
|
&multicast);
|
||||||
|
err = grub_net_send_ip_packet (inf, &multicast, nb,
|
||||||
|
GRUB_NET_IP_ICMPV6);
|
||||||
|
if (err)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
for (i = 0; i < GRUB_NET_TRIES; i++)
|
||||||
|
{
|
||||||
|
if (grub_net_link_layer_resolve_check (inf, proto_addr))
|
||||||
|
break;
|
||||||
|
grub_net_poll_cards (GRUB_NET_INTERVAL);
|
||||||
|
if (grub_net_link_layer_resolve_check (inf, proto_addr))
|
||||||
|
break;
|
||||||
|
err = grub_net_send_ip_packet (inf, &multicast, nb,
|
||||||
|
GRUB_NET_IP_ICMPV6);
|
||||||
|
if (err)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fail:
|
||||||
|
grub_netbuff_free (nb);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
|
@ -87,6 +87,7 @@ struct reassemble
|
||||||
grub_uint8_t *asm_buffer;
|
grub_uint8_t *asm_buffer;
|
||||||
grub_size_t total_len;
|
grub_size_t total_len;
|
||||||
grub_size_t cur_ptr;
|
grub_size_t cur_ptr;
|
||||||
|
grub_uint8_t ttl;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct reassemble *reassembles;
|
struct reassemble *reassembles;
|
||||||
|
@ -192,7 +193,7 @@ grub_net_send_ip4_packet (struct grub_net_network_level_interface * inf,
|
||||||
COMPILE_TIME_ASSERT (GRUB_NET_OUR_IPV4_HEADER_SIZE == sizeof (*iph));
|
COMPILE_TIME_ASSERT (GRUB_NET_OUR_IPV4_HEADER_SIZE == sizeof (*iph));
|
||||||
|
|
||||||
/* Determine link layer target address via ARP. */
|
/* Determine link layer target address via ARP. */
|
||||||
err = grub_net_arp_resolve (inf, target, &ll_target_addr);
|
err = grub_net_link_layer_resolve (inf, target, &ll_target_addr);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -225,10 +226,12 @@ handle_dgram (struct grub_net_buff *nb,
|
||||||
const grub_net_link_level_address_t *hwaddress,
|
const grub_net_link_level_address_t *hwaddress,
|
||||||
grub_net_ip_protocol_t proto,
|
grub_net_ip_protocol_t proto,
|
||||||
const grub_net_network_level_address_t *source,
|
const grub_net_network_level_address_t *source,
|
||||||
const grub_net_network_level_address_t *dest)
|
const grub_net_network_level_address_t *dest,
|
||||||
|
grub_uint8_t ttl)
|
||||||
{
|
{
|
||||||
struct grub_net_network_level_interface *inf = NULL;
|
struct grub_net_network_level_interface *inf = NULL;
|
||||||
grub_err_t err;
|
grub_err_t err;
|
||||||
|
int multicast = 0;
|
||||||
|
|
||||||
/* DHCP needs special treatment since we don't know IP yet. */
|
/* DHCP needs special treatment since we don't know IP yet. */
|
||||||
{
|
{
|
||||||
|
@ -280,17 +283,39 @@ handle_dgram (struct grub_net_buff *nb,
|
||||||
&& grub_net_addr_cmp (&inf->address, dest) == 0
|
&& grub_net_addr_cmp (&inf->address, dest) == 0
|
||||||
&& grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0)
|
&& grub_net_hwaddr_cmp (&inf->hwaddress, hwaddress) == 0)
|
||||||
break;
|
break;
|
||||||
|
/* Solicited node multicast. */
|
||||||
|
if (inf->card == card
|
||||||
|
&& inf->address.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6
|
||||||
|
&& dest->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6
|
||||||
|
&& dest->ipv6[0] == grub_be_to_cpu64_compile_time (0xff02ULL << 48)
|
||||||
|
&& dest->ipv6[1] == (grub_be_to_cpu64_compile_time (0x01ff000000ULL)
|
||||||
|
| (inf->address.ipv6[1]
|
||||||
|
& grub_be_to_cpu64_compile_time (0xffffff)))
|
||||||
|
&& hwaddress->type == GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET
|
||||||
|
&& hwaddress->mac[0] == 0x33 && hwaddress->mac[1] == 0x33
|
||||||
|
&& hwaddress->mac[2] == 0xff
|
||||||
|
&& hwaddress->mac[3] == ((grub_be_to_cpu64 (inf->address.ipv6[1])
|
||||||
|
>> 16) & 0xff)
|
||||||
|
&& hwaddress->mac[4] == ((grub_be_to_cpu64 (inf->address.ipv6[1])
|
||||||
|
>> 8) & 0xff)
|
||||||
|
&& hwaddress->mac[5] == ((grub_be_to_cpu64 (inf->address.ipv6[1])
|
||||||
|
>> 0) & 0xff))
|
||||||
|
{
|
||||||
|
multicast = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!inf && !(dest->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6
|
if (!inf && !(dest->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6
|
||||||
&& dest->ipv6[0] == grub_be_to_cpu64 (0xff02ULL << 48)
|
&& dest->ipv6[0] == grub_be_to_cpu64_compile_time (0xff02ULL
|
||||||
&& dest->ipv6[1] == grub_be_to_cpu64 (1)))
|
<< 48)
|
||||||
|
&& dest->ipv6[1] == grub_be_to_cpu64_compile_time (1)))
|
||||||
{
|
{
|
||||||
grub_dprintf ("net", "undirected dgram discarded: %x, %lx, %lx\n",
|
|
||||||
dest->type, dest->ipv6[0], dest->ipv6[1]);
|
|
||||||
grub_netbuff_free (nb);
|
grub_netbuff_free (nb);
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
}
|
}
|
||||||
|
if (multicast)
|
||||||
|
inf = NULL;
|
||||||
|
|
||||||
switch (proto)
|
switch (proto)
|
||||||
{
|
{
|
||||||
|
@ -301,7 +326,7 @@ handle_dgram (struct grub_net_buff *nb,
|
||||||
case GRUB_NET_IP_ICMP:
|
case GRUB_NET_IP_ICMP:
|
||||||
return grub_net_recv_icmp_packet (nb, inf, source);
|
return grub_net_recv_icmp_packet (nb, inf, source);
|
||||||
case GRUB_NET_IP_ICMPV6:
|
case GRUB_NET_IP_ICMPV6:
|
||||||
return grub_net_recv_icmp6_packet (nb, card, inf, source, dest);
|
return grub_net_recv_icmp6_packet (nb, card, inf, source, dest, ttl);
|
||||||
default:
|
default:
|
||||||
grub_netbuff_free (nb);
|
grub_netbuff_free (nb);
|
||||||
break;
|
break;
|
||||||
|
@ -414,7 +439,7 @@ grub_net_recv_ip4_packets (struct grub_net_buff * nb,
|
||||||
dest.ipv4 = iph->dest;
|
dest.ipv4 = iph->dest;
|
||||||
|
|
||||||
return handle_dgram (nb, card, hwaddress, iph->protocol,
|
return handle_dgram (nb, card, hwaddress, iph->protocol,
|
||||||
&source, &dest);
|
&source, &dest, iph->ttl);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (prev = &reassembles, rsm = *prev; rsm; prev = &rsm->next, rsm = *prev)
|
for (prev = &reassembles, rsm = *prev; rsm; prev = &rsm->next, rsm = *prev)
|
||||||
|
@ -442,8 +467,10 @@ grub_net_recv_ip4_packets (struct grub_net_buff * nb,
|
||||||
rsm->asm_buffer = 0;
|
rsm->asm_buffer = 0;
|
||||||
rsm->total_len = 0;
|
rsm->total_len = 0;
|
||||||
rsm->cur_ptr = 0;
|
rsm->cur_ptr = 0;
|
||||||
|
rsm->ttl = 0xff;
|
||||||
}
|
}
|
||||||
|
if (rsm->ttl > iph->ttl)
|
||||||
|
rsm->ttl = iph->ttl;
|
||||||
rsm->last_time = grub_get_time_ms ();
|
rsm->last_time = grub_get_time_ms ();
|
||||||
free_old_fragments ();
|
free_old_fragments ();
|
||||||
|
|
||||||
|
@ -479,6 +506,7 @@ grub_net_recv_ip4_packets (struct grub_net_buff * nb,
|
||||||
grub_uint32_t dst;
|
grub_uint32_t dst;
|
||||||
grub_net_network_level_address_t source;
|
grub_net_network_level_address_t source;
|
||||||
grub_net_network_level_address_t dest;
|
grub_net_network_level_address_t dest;
|
||||||
|
grub_uint8_t ttl;
|
||||||
|
|
||||||
nb_top_p = grub_priority_queue_top (rsm->pq);
|
nb_top_p = grub_priority_queue_top (rsm->pq);
|
||||||
if (!nb_top_p)
|
if (!nb_top_p)
|
||||||
|
@ -521,6 +549,7 @@ grub_net_recv_ip4_packets (struct grub_net_buff * nb,
|
||||||
proto = rsm->proto;
|
proto = rsm->proto;
|
||||||
src = rsm->source;
|
src = rsm->source;
|
||||||
dst = rsm->dest;
|
dst = rsm->dest;
|
||||||
|
ttl = rsm->ttl;
|
||||||
|
|
||||||
rsm->asm_buffer = 0;
|
rsm->asm_buffer = 0;
|
||||||
res_len = rsm->total_len;
|
res_len = rsm->total_len;
|
||||||
|
@ -541,7 +570,8 @@ grub_net_recv_ip4_packets (struct grub_net_buff * nb,
|
||||||
dest.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
|
dest.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4;
|
||||||
dest.ipv4 = dst;
|
dest.ipv4 = dst;
|
||||||
|
|
||||||
return handle_dgram (ret, card, hwaddress, proto, &source, &dest);
|
return handle_dgram (ret, card, hwaddress, proto, &source, &dest,
|
||||||
|
ttl);
|
||||||
}
|
}
|
||||||
|
|
||||||
return GRUB_ERR_NONE;
|
return GRUB_ERR_NONE;
|
||||||
|
@ -560,7 +590,7 @@ grub_net_send_ip6_packet (struct grub_net_network_level_interface * inf,
|
||||||
COMPILE_TIME_ASSERT (GRUB_NET_OUR_IPV6_HEADER_SIZE == sizeof (*iph));
|
COMPILE_TIME_ASSERT (GRUB_NET_OUR_IPV6_HEADER_SIZE == sizeof (*iph));
|
||||||
|
|
||||||
/* Determine link layer target address via ARP. */
|
/* Determine link layer target address via ARP. */
|
||||||
err = grub_net_arp_resolve (inf, target, &ll_target_addr);
|
err = grub_net_link_layer_resolve (inf, target, &ll_target_addr);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -571,14 +601,14 @@ grub_net_send_ip6_packet (struct grub_net_network_level_interface * inf,
|
||||||
iph = (struct ip6hdr *) nb->data;
|
iph = (struct ip6hdr *) nb->data;
|
||||||
|
|
||||||
iph->version_class_flow = grub_cpu_to_be32 ((6 << 28));
|
iph->version_class_flow = grub_cpu_to_be32 ((6 << 28));
|
||||||
iph->len = grub_cpu_to_be16 (nb->tail - nb->data) - sizeof (*iph);
|
iph->len = grub_cpu_to_be16 (nb->tail - nb->data - sizeof (*iph));
|
||||||
iph->protocol = proto;
|
iph->protocol = proto;
|
||||||
iph->ttl = 0xff;
|
iph->ttl = 0xff;
|
||||||
grub_memcpy (&iph->src, inf->address.ipv6, sizeof (iph->src));
|
grub_memcpy (&iph->src, inf->address.ipv6, sizeof (iph->src));
|
||||||
grub_memcpy (&iph->dest, target->ipv6, sizeof (iph->dest));
|
grub_memcpy (&iph->dest, target->ipv6, sizeof (iph->dest));
|
||||||
|
|
||||||
return send_ethernet_packet (inf, nb, ll_target_addr,
|
return send_ethernet_packet (inf, nb, ll_target_addr,
|
||||||
GRUB_NET_ETHERTYPE_IP);
|
GRUB_NET_ETHERTYPE_IP6);
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_err_t
|
grub_err_t
|
||||||
|
@ -608,14 +638,6 @@ grub_net_recv_ip6_packets (struct grub_net_buff * nb,
|
||||||
grub_net_network_level_address_t source;
|
grub_net_network_level_address_t source;
|
||||||
grub_net_network_level_address_t dest;
|
grub_net_network_level_address_t dest;
|
||||||
|
|
||||||
if ((grub_be_to_cpu32 (iph->version_class_flow) >> 28) != 6)
|
|
||||||
{
|
|
||||||
grub_dprintf ("net", "Bad IP version: %d\n",
|
|
||||||
(grub_be_to_cpu32 (iph->version_class_flow) >> 28));
|
|
||||||
grub_netbuff_free (nb);
|
|
||||||
return GRUB_ERR_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nb->tail - nb->data < (grub_ssize_t) sizeof (*iph))
|
if (nb->tail - nb->data < (grub_ssize_t) sizeof (*iph))
|
||||||
{
|
{
|
||||||
grub_dprintf ("net", "IP packet too short: %" PRIdGRUB_SSIZE "\n",
|
grub_dprintf ("net", "IP packet too short: %" PRIdGRUB_SSIZE "\n",
|
||||||
|
@ -660,7 +682,7 @@ grub_net_recv_ip6_packets (struct grub_net_buff * nb,
|
||||||
grub_memcpy (dest.ipv6, &iph->dest, sizeof (dest.ipv6));
|
grub_memcpy (dest.ipv6, &iph->dest, sizeof (dest.ipv6));
|
||||||
|
|
||||||
return handle_dgram (nb, card, hwaddress, iph->protocol,
|
return handle_dgram (nb, card, hwaddress, iph->protocol,
|
||||||
&source, &dest);
|
&source, &dest, iph->ttl);
|
||||||
}
|
}
|
||||||
|
|
||||||
grub_err_t
|
grub_err_t
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <grub/command.h>
|
#include <grub/command.h>
|
||||||
#include <grub/env.h>
|
#include <grub/env.h>
|
||||||
#include <grub/net/ethernet.h>
|
#include <grub/net/ethernet.h>
|
||||||
|
#include <grub/net/arp.h>
|
||||||
#include <grub/net/ip.h>
|
#include <grub/net/ip.h>
|
||||||
#include <grub/loader.h>
|
#include <grub/loader.h>
|
||||||
#include <grub/bufio.h>
|
#include <grub/bufio.h>
|
||||||
|
@ -56,6 +57,144 @@ struct grub_net_card *grub_net_cards = NULL;
|
||||||
struct grub_net_network_level_protocol *grub_net_network_level_protocols = NULL;
|
struct grub_net_network_level_protocol *grub_net_network_level_protocols = NULL;
|
||||||
static struct grub_fs grub_net_fs;
|
static struct grub_fs grub_net_fs;
|
||||||
|
|
||||||
|
struct grub_net_link_layer_entry {
|
||||||
|
int avail;
|
||||||
|
grub_net_network_level_address_t nl_address;
|
||||||
|
grub_net_link_level_address_t ll_address;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define LINK_LAYER_CACHE_SIZE 256
|
||||||
|
|
||||||
|
static struct grub_net_link_layer_entry *
|
||||||
|
link_layer_find_entry (const grub_net_network_level_address_t *proto,
|
||||||
|
const struct grub_net_card *card)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
if (!card->link_layer_table)
|
||||||
|
return NULL;
|
||||||
|
for (i = 0; i < LINK_LAYER_CACHE_SIZE; i++)
|
||||||
|
{
|
||||||
|
if (card->link_layer_table[i].avail == 1
|
||||||
|
&& grub_net_addr_cmp (&card->link_layer_table[i].nl_address,
|
||||||
|
proto) == 0)
|
||||||
|
return &card->link_layer_table[i];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
grub_net_link_layer_add_address (struct grub_net_card *card,
|
||||||
|
const grub_net_network_level_address_t *nl,
|
||||||
|
const grub_net_link_level_address_t *ll,
|
||||||
|
int override)
|
||||||
|
{
|
||||||
|
struct grub_net_link_layer_entry *entry;
|
||||||
|
|
||||||
|
/* Check if the sender is in the cache table. */
|
||||||
|
entry = link_layer_find_entry (nl, card);
|
||||||
|
/* Update sender hardware address. */
|
||||||
|
if (entry && override)
|
||||||
|
grub_memcpy (&entry->ll_address, ll, sizeof (entry->ll_address));
|
||||||
|
if (entry)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Add sender to cache table. */
|
||||||
|
if (card->link_layer_table == NULL)
|
||||||
|
card->link_layer_table = grub_zalloc (LINK_LAYER_CACHE_SIZE
|
||||||
|
* sizeof (card->link_layer_table[0]));
|
||||||
|
entry = &(card->link_layer_table[card->new_ll_entry]);
|
||||||
|
entry->avail = 1;
|
||||||
|
grub_memcpy (&entry->ll_address, ll, sizeof (entry->ll_address));
|
||||||
|
grub_memcpy (&entry->nl_address, nl, sizeof (entry->nl_address));
|
||||||
|
card->new_ll_entry++;
|
||||||
|
if (card->new_ll_entry == LINK_LAYER_CACHE_SIZE)
|
||||||
|
card->new_ll_entry = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
grub_net_link_layer_resolve_check (struct grub_net_network_level_interface *inf,
|
||||||
|
const grub_net_network_level_address_t *proto_addr)
|
||||||
|
{
|
||||||
|
struct grub_net_link_layer_entry *entry;
|
||||||
|
|
||||||
|
if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4
|
||||||
|
&& proto_addr->ipv4 == 0xffffffff)
|
||||||
|
return 1;
|
||||||
|
entry = link_layer_find_entry (proto_addr, inf->card);
|
||||||
|
if (entry)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_net_link_layer_resolve (struct grub_net_network_level_interface *inf,
|
||||||
|
const grub_net_network_level_address_t *proto_addr,
|
||||||
|
grub_net_link_level_address_t *hw_addr)
|
||||||
|
{
|
||||||
|
struct grub_net_link_layer_entry *entry;
|
||||||
|
grub_err_t err;
|
||||||
|
|
||||||
|
if ((proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4
|
||||||
|
&& proto_addr->ipv4 == 0xffffffff)
|
||||||
|
|| proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV
|
||||||
|
|| (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6
|
||||||
|
&& proto_addr->ipv6[0] == grub_be_to_cpu64_compile_time (0xff02ULL
|
||||||
|
<< 48)
|
||||||
|
&& proto_addr->ipv6[1] == (grub_be_to_cpu64_compile_time (1))))
|
||||||
|
{
|
||||||
|
hw_addr->type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
|
||||||
|
grub_memset (hw_addr->mac, -1, 6);
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (proto_addr->type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6
|
||||||
|
&& ((grub_be_to_cpu64 (proto_addr->ipv6[0]) >> 56) == 0xff))
|
||||||
|
{
|
||||||
|
hw_addr->type = GRUB_NET_LINK_LEVEL_PROTOCOL_ETHERNET;
|
||||||
|
hw_addr->mac[0] = 0x33;
|
||||||
|
hw_addr->mac[1] = 0x33;
|
||||||
|
hw_addr->mac[2] = ((grub_be_to_cpu64 (proto_addr->ipv6[1]) >> 24) & 0xff);
|
||||||
|
hw_addr->mac[3] = ((grub_be_to_cpu64 (proto_addr->ipv6[1]) >> 16) & 0xff);
|
||||||
|
hw_addr->mac[4] = ((grub_be_to_cpu64 (proto_addr->ipv6[1]) >> 8) & 0xff);
|
||||||
|
hw_addr->mac[5] = ((grub_be_to_cpu64 (proto_addr->ipv6[1]) >> 0) & 0xff);
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Check cache table. */
|
||||||
|
entry = link_layer_find_entry (proto_addr, inf->card);
|
||||||
|
if (entry)
|
||||||
|
{
|
||||||
|
*hw_addr = entry->ll_address;
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
switch (proto_addr->type)
|
||||||
|
{
|
||||||
|
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
|
||||||
|
err = grub_net_arp_send_request (inf, proto_addr);
|
||||||
|
break;
|
||||||
|
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6:
|
||||||
|
err = grub_net_icmp6_send_request (inf, proto_addr);
|
||||||
|
break;
|
||||||
|
case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV:
|
||||||
|
return grub_error (GRUB_ERR_BUG, "shouldn't reach here");
|
||||||
|
default:
|
||||||
|
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
|
||||||
|
"unsupported address type %d", proto_addr->type);
|
||||||
|
}
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
entry = link_layer_find_entry (proto_addr, inf->card);
|
||||||
|
if (entry)
|
||||||
|
{
|
||||||
|
*hw_addr = entry->ll_address;
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
return grub_error (GRUB_ERR_TIMEOUT,
|
||||||
|
"timeout: could not resolve hardware address");
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
grub_net_card_unregister (struct grub_net_card *card)
|
grub_net_card_unregister (struct grub_net_card *card)
|
||||||
{
|
{
|
||||||
|
|
|
@ -105,6 +105,8 @@ struct grub_net_slaac_mac_list
|
||||||
char *name;
|
char *name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct grub_net_link_layer_entry;
|
||||||
|
|
||||||
struct grub_net_card
|
struct grub_net_card
|
||||||
{
|
{
|
||||||
struct grub_net_card *next;
|
struct grub_net_card *next;
|
||||||
|
@ -118,6 +120,8 @@ struct grub_net_card
|
||||||
grub_uint64_t last_poll;
|
grub_uint64_t last_poll;
|
||||||
grub_size_t mtu;
|
grub_size_t mtu;
|
||||||
struct grub_net_slaac_mac_list *slaac_list;
|
struct grub_net_slaac_mac_list *slaac_list;
|
||||||
|
grub_ssize_t new_ll_entry;
|
||||||
|
struct grub_net_link_layer_entry *link_layer_table;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
#ifdef GRUB_MACHINE_EFI
|
#ifdef GRUB_MACHINE_EFI
|
||||||
|
@ -455,6 +459,19 @@ grub_net_network_level_interface_unregister (struct grub_net_network_level_inter
|
||||||
void
|
void
|
||||||
grub_net_tcp_retransmit (void);
|
grub_net_tcp_retransmit (void);
|
||||||
|
|
||||||
|
void
|
||||||
|
grub_net_link_layer_add_address (struct grub_net_card *card,
|
||||||
|
const grub_net_network_level_address_t *nl,
|
||||||
|
const grub_net_link_level_address_t *ll,
|
||||||
|
int override);
|
||||||
|
int
|
||||||
|
grub_net_link_layer_resolve_check (struct grub_net_network_level_interface *inf,
|
||||||
|
const grub_net_network_level_address_t *proto_addr);
|
||||||
|
grub_err_t
|
||||||
|
grub_net_link_layer_resolve (struct grub_net_network_level_interface *inf,
|
||||||
|
const grub_net_network_level_address_t *proto_addr,
|
||||||
|
grub_net_link_level_address_t *hw_addr);
|
||||||
|
|
||||||
extern char *grub_net_default_server;
|
extern char *grub_net_default_server;
|
||||||
|
|
||||||
#define GRUB_NET_TRIES 40
|
#define GRUB_NET_TRIES 40
|
||||||
|
|
|
@ -21,10 +21,11 @@
|
||||||
#include <grub/misc.h>
|
#include <grub/misc.h>
|
||||||
#include <grub/net.h>
|
#include <grub/net.h>
|
||||||
|
|
||||||
extern grub_err_t grub_net_arp_receive(struct grub_net_buff *nb);
|
extern grub_err_t grub_net_arp_receive (struct grub_net_buff *nb,
|
||||||
|
struct grub_net_card *card);
|
||||||
|
|
||||||
extern grub_err_t grub_net_arp_resolve(struct grub_net_network_level_interface *inf,
|
grub_err_t
|
||||||
const grub_net_network_level_address_t *addr,
|
grub_net_arp_send_request (struct grub_net_network_level_interface *inf,
|
||||||
grub_net_link_level_address_t *hw_addr);
|
const grub_net_network_level_address_t *proto_addr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -64,7 +64,8 @@ grub_net_recv_icmp6_packet (struct grub_net_buff *nb,
|
||||||
struct grub_net_card *card,
|
struct grub_net_card *card,
|
||||||
struct grub_net_network_level_interface *inf,
|
struct grub_net_network_level_interface *inf,
|
||||||
const grub_net_network_level_address_t *source,
|
const grub_net_network_level_address_t *source,
|
||||||
const grub_net_network_level_address_t *dest);
|
const grub_net_network_level_address_t *dest,
|
||||||
|
grub_uint8_t ttl);
|
||||||
grub_err_t
|
grub_err_t
|
||||||
grub_net_recv_udp_packet (struct grub_net_buff *nb,
|
grub_net_recv_udp_packet (struct grub_net_buff *nb,
|
||||||
struct grub_net_network_level_interface *inf,
|
struct grub_net_network_level_interface *inf,
|
||||||
|
@ -83,5 +84,8 @@ grub_net_ip_transport_checksum (struct grub_net_buff *nb,
|
||||||
struct grub_net_network_level_interface *
|
struct grub_net_network_level_interface *
|
||||||
grub_net_ipv6_get_link_local (struct grub_net_card *card,
|
grub_net_ipv6_get_link_local (struct grub_net_card *card,
|
||||||
const grub_net_link_level_address_t *hwaddr);
|
const grub_net_link_level_address_t *hwaddr);
|
||||||
|
grub_err_t
|
||||||
|
grub_net_icmp6_send_request (struct grub_net_network_level_interface *inf,
|
||||||
|
const grub_net_network_level_address_t *proto_addr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -154,6 +154,18 @@ typedef grub_uint64_t grub_disk_addr_t;
|
||||||
|
|
||||||
#define grub_swap_bytes16_compile_time(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8))
|
#define grub_swap_bytes16_compile_time(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8))
|
||||||
#define grub_swap_bytes32_compile_time(x) ((((x) & 0xff) << 24) | (((x) & 0xff00) << 8) | (((x) & 0xff0000) >> 8) | (((x) & 0xff000000UL) >> 24))
|
#define grub_swap_bytes32_compile_time(x) ((((x) & 0xff) << 24) | (((x) & 0xff00) << 8) | (((x) & 0xff0000) >> 8) | (((x) & 0xff000000UL) >> 24))
|
||||||
|
#define grub_swap_bytes64_compile_time(x) \
|
||||||
|
({ \
|
||||||
|
grub_uint64_t _x = (x); \
|
||||||
|
(grub_uint64_t) ((_x << 56) \
|
||||||
|
| ((_x & (grub_uint64_t) 0xFF00ULL) << 40) \
|
||||||
|
| ((_x & (grub_uint64_t) 0xFF0000ULL) << 24) \
|
||||||
|
| ((_x & (grub_uint64_t) 0xFF000000ULL) << 8) \
|
||||||
|
| ((_x & (grub_uint64_t) 0xFF00000000ULL) >> 8) \
|
||||||
|
| ((_x & (grub_uint64_t) 0xFF0000000000ULL) >> 24) \
|
||||||
|
| ((_x & (grub_uint64_t) 0xFF000000000000ULL) >> 40) \
|
||||||
|
| (_x >> 56)); \
|
||||||
|
})
|
||||||
|
|
||||||
#if defined(__GNUC__) && (__GNUC__ > 3) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3)
|
#if defined(__GNUC__) && (__GNUC__ > 3) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3)
|
||||||
static inline grub_uint32_t grub_swap_bytes32(grub_uint32_t x)
|
static inline grub_uint32_t grub_swap_bytes32(grub_uint32_t x)
|
||||||
|
@ -202,6 +214,9 @@ static inline grub_uint64_t grub_swap_bytes64(grub_uint64_t x)
|
||||||
# define grub_be_to_cpu16(x) ((grub_uint16_t) (x))
|
# define grub_be_to_cpu16(x) ((grub_uint16_t) (x))
|
||||||
# define grub_be_to_cpu32(x) ((grub_uint32_t) (x))
|
# define grub_be_to_cpu32(x) ((grub_uint32_t) (x))
|
||||||
# define grub_be_to_cpu64(x) ((grub_uint64_t) (x))
|
# define grub_be_to_cpu64(x) ((grub_uint64_t) (x))
|
||||||
|
# define grub_cpu_to_be32_compile_time(x) ((grub_uint32_t) (x))
|
||||||
|
# define grub_cpu_to_be64_compile_time(x) ((grub_uint64_t) (x))
|
||||||
|
# define grub_be_to_cpu64_compile_time(x) ((grub_uint64_t) (x))
|
||||||
# define grub_cpu_to_le32_compile_time(x) grub_swap_bytes32_compile_time(x)
|
# define grub_cpu_to_le32_compile_time(x) grub_swap_bytes32_compile_time(x)
|
||||||
# define grub_cpu_to_le16_compile_time(x) grub_swap_bytes16_compile_time(x)
|
# define grub_cpu_to_le16_compile_time(x) grub_swap_bytes16_compile_time(x)
|
||||||
#else /* ! WORDS_BIGENDIAN */
|
#else /* ! WORDS_BIGENDIAN */
|
||||||
|
@ -217,8 +232,12 @@ static inline grub_uint64_t grub_swap_bytes64(grub_uint64_t x)
|
||||||
# define grub_be_to_cpu16(x) grub_swap_bytes16(x)
|
# define grub_be_to_cpu16(x) grub_swap_bytes16(x)
|
||||||
# define grub_be_to_cpu32(x) grub_swap_bytes32(x)
|
# define grub_be_to_cpu32(x) grub_swap_bytes32(x)
|
||||||
# define grub_be_to_cpu64(x) grub_swap_bytes64(x)
|
# define grub_be_to_cpu64(x) grub_swap_bytes64(x)
|
||||||
|
# define grub_cpu_to_be32_compile_time(x) grub_swap_bytes32_compile_time(x)
|
||||||
|
# define grub_cpu_to_be64_compile_time(x) grub_swap_bytes64_compile_time(x)
|
||||||
|
# define grub_be_to_cpu64_compile_time(x) grub_swap_bytes64_compile_time(x)
|
||||||
# define grub_cpu_to_le16_compile_time(x) ((grub_uint16_t) (x))
|
# define grub_cpu_to_le16_compile_time(x) ((grub_uint16_t) (x))
|
||||||
# define grub_cpu_to_le32_compile_time(x) ((grub_uint32_t) (x))
|
# define grub_cpu_to_le32_compile_time(x) ((grub_uint32_t) (x))
|
||||||
|
|
||||||
#endif /* ! WORDS_BIGENDIAN */
|
#endif /* ! WORDS_BIGENDIAN */
|
||||||
|
|
||||||
#endif /* ! GRUB_TYPES_HEADER */
|
#endif /* ! GRUB_TYPES_HEADER */
|
||||||
|
|
Loading…
Add table
Reference in a new issue