From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.71) id 1Xqdrk-0006i1-L9 for mharc-grub-devel@gnu.org; Tue, 18 Nov 2014 03:10:24 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:56717) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Xqdra-0006gu-14 for grub-devel@gnu.org; Tue, 18 Nov 2014 03:10:23 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XqdrQ-0006ne-V7 for grub-devel@gnu.org; Tue, 18 Nov 2014 03:10:13 -0500 Received: from mail-oi0-x22d.google.com ([2607:f8b0:4003:c06::22d]:56817) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XqdrQ-0006mG-PH for grub-devel@gnu.org; Tue, 18 Nov 2014 03:10:04 -0500 Received: by mail-oi0-f45.google.com with SMTP id a141so8091942oig.4 for ; Tue, 18 Nov 2014 00:10:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:subject:date:message-id; bh=910UeehVPtNWl+MhwEFQtLHZ2Hwm6DaJtxgCPCebqv4=; b=NTbvWi1rI0Y5L0xrNQ5Ppdap2tevaBuJRCC1BqeNRmVpnQk9rPSPHmpsGn3h5L4DPW MF+Ci1SXcX8+UkVWq1YQig1Xy0IlTBUshJdZKp6k1kg5MN/2NoWS+ZKoQ7oZ9pgcD/wc OPftDOzmLqMGvaFmT+vyzAwLiYn3IvURYlyVOTKMmTIjVBKPqocyKUx1+5JxqWZLbEY+ FF4mWe7pc5jPncOynOEs2ttP4mUxgUrfSWY7f2DDqIL0gNZ+zvQ9mQ5sbNJ07y8F8tlC vNWzl+9u57vhNwPxmeyLcY9MGmxrWE06vZX3av2f7rgo7OgNYpaEEABhSG4nPI+pFYpj pVpA== X-Received: by 10.182.87.37 with SMTP id u5mr12206819obz.38.1416298204379; Tue, 18 Nov 2014 00:10:04 -0800 (PST) Received: from localhost.localdomain ([130.57.30.250]) by mx.google.com with ESMTPSA id e18sm12434093oih.3.2014.11.18.00.10.02 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 18 Nov 2014 00:10:03 -0800 (PST) Sender: =?UTF-8?B?5by15paH6I+v?= From: Michael Chang To: grub-devel@gnu.org Subject: [PATCH] send router solicitation for ipv6 address autoconf v2 Date: Tue, 18 Nov 2014 16:03:08 +0800 Message-Id: <1416297788-10783-1-git-send-email-mchang@suse.com> X-Mailer: git-send-email 1.7.3.4 X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2607:f8b0:4003:c06::22d X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list Reply-To: The development of GNU GRUB List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 18 Nov 2014 08:10:23 -0000 Many routers have long router advertisment interval configured by default. The Neighbor Discovery protocol (RFC4861) has defined default MaxRtrAdvInterval value as 600 seconds and MinRtrAdvInterval as 0.33*MaxRtrAdvInterval. This makes net_ipv6_autoconf fails more often than not as currently it passively listens the RA message to perfom address autoconfiguration. This patch tries to send router solicitation to overcome the problem of long RA interval. v2: use cpu_to_be macro for network byte order conversion add missing error handling --- grub-core/net/icmp6.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++ grub-core/net/net.c | 4 ++- include/grub/net/ip.h | 2 + 3 files changed, 88 insertions(+), 1 deletions(-) diff --git a/grub-core/net/icmp6.c b/grub-core/net/icmp6.c index 796d549..267aeb8 100644 --- a/grub-core/net/icmp6.c +++ b/grub-core/net/icmp6.c @@ -72,6 +72,11 @@ struct neighbour_advertise grub_uint64_t target[2]; } GRUB_PACKED; +struct router_solicit +{ + grub_uint32_t reserved; +} GRUB_PACKED; + enum { FLAG_SLAAC = 0x40 @@ -81,6 +86,7 @@ enum { ICMP6_ECHO = 128, ICMP6_ECHO_REPLY = 129, + ICMP6_ROUTER_SOLICIT = 133, ICMP6_ROUTER_ADVERTISE = 134, ICMP6_NEIGHBOUR_SOLICIT = 135, ICMP6_NEIGHBOUR_ADVERTISE = 136, @@ -533,3 +539,80 @@ grub_net_icmp6_send_request (struct grub_net_network_level_interface *inf, grub_netbuff_free (nb); return err; } + +grub_err_t +grub_net_icmp6_send_router_solicit (struct grub_net_network_level_interface *inf) +{ + struct grub_net_buff *nb; + grub_err_t err = GRUB_ERR_NONE; + grub_net_network_level_address_t multicast; + grub_net_link_level_address_t ll_multicast; + struct option_header *ohdr; + struct router_solicit *sol; + struct icmp_header *icmphr; + + multicast.type = GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6; + multicast.ipv6[0] = grub_cpu_to_be64 (0xff02ULL << 48); + multicast.ipv6[1] = grub_cpu_to_be64 (0x02ULL); + + err = grub_net_link_layer_resolve (inf, &multicast, &ll_multicast); + if (err) + return err; + + nb = grub_netbuff_alloc (sizeof (struct router_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 router_solicit) + + sizeof (struct option_header) + + 6 + + sizeof (struct icmp_header) + + GRUB_NET_OUR_IPV6_HEADER_SIZE + + GRUB_NET_MAX_LINK_HEADER_SIZE); + if (err) + goto fail; + + 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_SOURCE_LINK_LAYER_ADDRESS; + ohdr->len = 1; + + err = grub_netbuff_push (nb, sizeof (*sol)); + if (err) + goto fail; + + sol = (struct router_solicit *) nb->data; + sol->reserved = 0; + + err = grub_netbuff_push (nb, sizeof (*icmphr)); + if (err) + goto fail; + + icmphr = (struct icmp_header *) nb->data; + icmphr->type = ICMP6_ROUTER_SOLICIT; + 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, &ll_multicast, nb, + GRUB_NET_IP_ICMPV6); + fail: + grub_netbuff_free (nb); + return err; +} diff --git a/grub-core/net/net.c b/grub-core/net/net.c index 82af3a0..21a4e94 100644 --- a/grub-core/net/net.c +++ b/grub-core/net/net.c @@ -380,12 +380,14 @@ grub_cmd_ipv6_autoconf (struct grub_command *cmd __attribute__ ((unused)), 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; + err = grub_net_icmp6_send_router_solicit (ifaces[j]); + if (err) + err = GRUB_ERR_NONE; done = 0; } if (done) diff --git a/include/grub/net/ip.h b/include/grub/net/ip.h index 7a8e614..dcceaa5 100644 --- a/include/grub/net/ip.h +++ b/include/grub/net/ip.h @@ -92,4 +92,6 @@ grub_err_t grub_net_icmp6_send_request (struct grub_net_network_level_interface *inf, const grub_net_network_level_address_t *proto_addr); +grub_err_t +grub_net_icmp6_send_router_solicit (struct grub_net_network_level_interface *inf); #endif -- 1.7.3.4