Blame SOURCES/0172-send-router-solicitation-for-ipv6-address-autoconf-v.patch

f731ee
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
f731ee
From: Michael Chang <mchang@suse.com>
f731ee
Date: Tue, 18 Nov 2014 16:03:08 +0800
f731ee
Subject: [PATCH] send router solicitation for ipv6 address autoconf v2
f731ee
f731ee
Many routers have long router advertisment interval configured by
f731ee
default. The Neighbor Discovery protocol (RFC4861) has defined default
f731ee
MaxRtrAdvInterval value as 600 seconds and
f731ee
MinRtrAdvInterval as 0.33*MaxRtrAdvInterval. This makes
f731ee
net_ipv6_autoconf fails more often than not as currently it passively
f731ee
listens the RA message to perfom address autoconfiguration.
f731ee
f731ee
This patch tries to send router solicitation to overcome the problem of
f731ee
long RA interval.
f731ee
f731ee
v2:
f731ee
use cpu_to_be macro for network byte order conversion
f731ee
add missing error handling
f731ee
---
f731ee
 grub-core/net/icmp6.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++
f731ee
 grub-core/net/net.c   |  4 ++-
f731ee
 include/grub/net/ip.h |  2 ++
f731ee
 3 files changed, 88 insertions(+), 1 deletion(-)
f731ee
f731ee
diff --git a/grub-core/net/icmp6.c b/grub-core/net/icmp6.c
f731ee
index bbc902014fe..0843a15afda 100644
f731ee
--- a/grub-core/net/icmp6.c
f731ee
+++ b/grub-core/net/icmp6.c
f731ee
@@ -72,6 +72,11 @@ struct neighbour_advertise
f731ee
   grub_uint64_t target[2];
f731ee
 } GRUB_PACKED;
f731ee
 
f731ee
+struct router_solicit
f731ee
+{
f731ee
+  grub_uint32_t reserved;
f731ee
+} GRUB_PACKED;
f731ee
+
f731ee
 enum
f731ee
   {
f731ee
     FLAG_SLAAC = 0x40
f731ee
@@ -81,6 +86,7 @@ enum
f731ee
   {
f731ee
     ICMP6_ECHO = 128,
f731ee
     ICMP6_ECHO_REPLY = 129,
f731ee
+    ICMP6_ROUTER_SOLICIT = 133,
f731ee
     ICMP6_ROUTER_ADVERTISE = 134,
f731ee
     ICMP6_NEIGHBOUR_SOLICIT = 135,
f731ee
     ICMP6_NEIGHBOUR_ADVERTISE = 136,
f731ee
@@ -533,3 +539,80 @@ grub_net_icmp6_send_request (struct grub_net_network_level_interface *inf,
f731ee
   grub_netbuff_free (nb);
f731ee
   return err;
f731ee
 }
f731ee
+
f731ee
+grub_err_t
f731ee
+grub_net_icmp6_send_router_solicit (struct grub_net_network_level_interface *inf)
f731ee
+{
f731ee
+  struct grub_net_buff *nb;
f731ee
+  grub_err_t err = GRUB_ERR_NONE;
f731ee
+  grub_net_network_level_address_t multicast;
f731ee
+  grub_net_link_level_address_t ll_multicast;
f731ee
+  struct option_header *ohdr;
f731ee
+  struct router_solicit *sol;
f731ee
+  struct icmp_header *icmphr;
f731ee
+
f731ee
+  multicast.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6;
f731ee
+  multicast.ipv6[0] = grub_cpu_to_be64 (0xff02ULL << 48);
f731ee
+  multicast.ipv6[1] = grub_cpu_to_be64 (0x02ULL);
f731ee
+
f731ee
+  err = grub_net_link_layer_resolve (inf, &multicast, &ll_multicast);
f731ee
+  if (err)
f731ee
+    return err;
f731ee
+
f731ee
+  nb = grub_netbuff_alloc (sizeof (struct router_solicit)
f731ee
+			   + sizeof (struct option_header)
f731ee
+			   + 6
f731ee
+			   + sizeof (struct icmp_header)
f731ee
+			   + GRUB_NET_OUR_IPV6_HEADER_SIZE
f731ee
+			   + GRUB_NET_MAX_LINK_HEADER_SIZE);
f731ee
+  if (!nb)
f731ee
+    return grub_errno;
f731ee
+  err = grub_netbuff_reserve (nb,
f731ee
+			      sizeof (struct router_solicit)
f731ee
+			      + sizeof (struct option_header)
f731ee
+			      + 6
f731ee
+			      + sizeof (struct icmp_header)
f731ee
+			      + GRUB_NET_OUR_IPV6_HEADER_SIZE
f731ee
+			      + GRUB_NET_MAX_LINK_HEADER_SIZE);
f731ee
+  if (err)
f731ee
+    goto fail;
f731ee
+
f731ee
+  err = grub_netbuff_push (nb, 6);
f731ee
+  if (err)
f731ee
+    goto fail;
f731ee
+
f731ee
+  grub_memcpy (nb->data, inf->hwaddress.mac, 6);
f731ee
+
f731ee
+  err = grub_netbuff_push (nb, sizeof (*ohdr));
f731ee
+  if (err)
f731ee
+    goto fail;
f731ee
+
f731ee
+  ohdr = (struct option_header *) nb->data;
f731ee
+  ohdr->type = OPTION_SOURCE_LINK_LAYER_ADDRESS;
f731ee
+  ohdr->len = 1;
f731ee
+
f731ee
+  err = grub_netbuff_push (nb, sizeof (*sol));
f731ee
+  if (err)
f731ee
+    goto fail;
f731ee
+
f731ee
+  sol = (struct router_solicit *) nb->data;
f731ee
+  sol->reserved = 0;
f731ee
+
f731ee
+  err = grub_netbuff_push (nb, sizeof (*icmphr));
f731ee
+  if (err)
f731ee
+    goto fail;
f731ee
+
f731ee
+  icmphr = (struct icmp_header *) nb->data;
f731ee
+  icmphr->type = ICMP6_ROUTER_SOLICIT;
f731ee
+  icmphr->code = 0;
f731ee
+  icmphr->checksum = 0;
f731ee
+  icmphr->checksum = grub_net_ip_transport_checksum (nb,
f731ee
+						     GRUB_NET_IP_ICMPV6,
f731ee
+						     &inf->address,
f731ee
+						     &multicast);
f731ee
+  err = grub_net_send_ip_packet (inf, &multicast, &ll_multicast, nb,
f731ee
+				 GRUB_NET_IP_ICMPV6);
f731ee
+ fail:
f731ee
+  grub_netbuff_free (nb);
f731ee
+  return err;
f731ee
+}
f731ee
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
f731ee
index 10bfed31b2b..b10addbe27b 100644
f731ee
--- a/grub-core/net/net.c
f731ee
+++ b/grub-core/net/net.c
f731ee
@@ -380,12 +380,14 @@ grub_cmd_ipv6_autoconf (struct grub_command *cmd __attribute__ ((unused)),
f731ee
 
f731ee
   for (interval = 200; interval < 10000; interval *= 2)
f731ee
     {
f731ee
-      /* FIXME: send router solicitation.  */
f731ee
       int done = 1;
f731ee
       for (j = 0; j < ncards; j++)
f731ee
 	{
f731ee
 	  if (slaacs[j]->slaac_counter)
f731ee
 	    continue;
f731ee
+	  err = grub_net_icmp6_send_router_solicit (ifaces[j]);
f731ee
+	  if (err)
f731ee
+	    err = GRUB_ERR_NONE;
f731ee
 	  done = 0;
f731ee
 	}
f731ee
       if (done)
f731ee
diff --git a/include/grub/net/ip.h b/include/grub/net/ip.h
f731ee
index 7a8e614794d..dcceaa56894 100644
f731ee
--- a/include/grub/net/ip.h
f731ee
+++ b/include/grub/net/ip.h
f731ee
@@ -92,4 +92,6 @@ grub_err_t
f731ee
 grub_net_icmp6_send_request (struct grub_net_network_level_interface *inf,
f731ee
 			     const grub_net_network_level_address_t *proto_addr);
f731ee
 
f731ee
+grub_err_t
f731ee
+grub_net_icmp6_send_router_solicit (struct grub_net_network_level_interface *inf);
f731ee
 #endif