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

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