aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/ndisc.c
diff options
context:
space:
mode:
authorBrian Haley <brian.haley@hp.com>2007-10-08 03:12:05 -0400
committerDavid S. Miller <davem@davemloft.net>2007-10-08 03:12:05 -0400
commitbf0b48dfc368c07c42b5a3a5658c8ee81b4283ac (patch)
tree7174e3ce995d6deaefb76027bc1a6265ccd25d11 /net/ipv6/ndisc.c
parentbf1b803b01b00c3801e0aa373ba0305f8278e260 (diff)
[IPv6]: Fix ICMPv6 redirect handling with target multicast address
When the ICMPv6 Target address is multicast, Linux processes the redirect instead of dropping it. The problem is in this code in ndisc_redirect_rcv(): if (ipv6_addr_equal(dest, target)) { on_link = 1; } else if (!(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) { ND_PRINTK2(KERN_WARNING "ICMPv6 Redirect: target address is not link-local.\n"); return; } This second check will succeed if the Target address is, for example, FF02::1 because it has link-local scope. Instead, it should be checking if it's a unicast link-local address, as stated in RFC 2461/4861 Section 8.1: - The ICMP Target Address is either a link-local address (when redirected to a router) or the same as the ICMP Destination Address (when redirected to the on-link destination). I know this doesn't explicitly say unicast link-local address, but it's implied. This bug is preventing Linux kernels from achieving IPv6 Logo Phase II certification because of a recent error that was found in the TAHI test suite - Neighbor Disovery suite test 206 (v6LC.2.3.6_G) had the multicast address in the Destination field instead of Target field, so we were passing the test. This won't be the case anymore. The patch below fixes this problem, and also fixes ndisc_send_redirect() to not send an invalid redirect with a multicast address in the Target field. I re-ran the TAHI Neighbor Discovery section to make sure Linux passes all 245 tests now. Signed-off-by: Brian Haley <brian.haley@hp.com> Acked-by: David L Stevens <dlstevens@us.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/ndisc.c')
-rw-r--r--net/ipv6/ndisc.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 73a894a2152c..5b596659177c 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1268,9 +1268,10 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
1268 1268
1269 if (ipv6_addr_equal(dest, target)) { 1269 if (ipv6_addr_equal(dest, target)) {
1270 on_link = 1; 1270 on_link = 1;
1271 } else if (!(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) { 1271 } else if (ipv6_addr_type(target) !=
1272 (IPV6_ADDR_UNICAST|IPV6_ADDR_LINKLOCAL)) {
1272 ND_PRINTK2(KERN_WARNING 1273 ND_PRINTK2(KERN_WARNING
1273 "ICMPv6 Redirect: target address is not link-local.\n"); 1274 "ICMPv6 Redirect: target address is not link-local unicast.\n");
1274 return; 1275 return;
1275 } 1276 }
1276 1277
@@ -1344,9 +1345,9 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
1344 } 1345 }
1345 1346
1346 if (!ipv6_addr_equal(&ipv6_hdr(skb)->daddr, target) && 1347 if (!ipv6_addr_equal(&ipv6_hdr(skb)->daddr, target) &&
1347 !(ipv6_addr_type(target) & IPV6_ADDR_LINKLOCAL)) { 1348 ipv6_addr_type(target) != (IPV6_ADDR_UNICAST|IPV6_ADDR_LINKLOCAL)) {
1348 ND_PRINTK2(KERN_WARNING 1349 ND_PRINTK2(KERN_WARNING
1349 "ICMPv6 Redirect: target address is not link-local.\n"); 1350 "ICMPv6 Redirect: target address is not link-local unicast.\n");
1350 return; 1351 return;
1351 } 1352 }
1352 1353