[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

(usagi-users 02693) transfer unnecessary IPv6 redirect packet



Hello,

I found that IPv6 source address check was insufficient
in the USAGI snap kernel-2.6-s20031208, when the IPv6
redirect packet was received.

------------------------------------------------------------------------
According to RFC2461:
  8.1.  Validation of Redirect Messages

  A host MUST silently discard any received Redirect message that does
  not satisfy all of the following validity checks:

......

 - The IP source address of the Redirect is the same as the current
    first-hop router for the specified ICMP Destination Address.
------------------------------------------------------------------------

I made a patch and fixed the problem. This patch referred
to the USAGI snap kernel-2.4-s20031208.

------------------------------------------------------------------------
--- net/ipv6/ndisc.c.bk 2003-12-09 11:18:59.000000000 +0900
+++ net/ipv6/ndisc.c    2003-12-09 11:19:34.000000000 +0900
@@ -1217,6 +1217,7 @@
        struct in6_addr *dest;
        struct in6_addr *target;        /* new first hop to destination */
        struct neighbour *neigh;
+       struct rt6_info *rt6;
        int on_link = 0;
        struct ndisc_options ndopts;
        int optlen;
@@ -1256,6 +1257,20 @@
                return;
        }


+       rt6 = rt6_lookup(dest, NULL, skb->dev->ifindex, 1);
+       if (!rt6) {
+                if (net_ratelimit())
+                        printk(KERN_WARNING "ICMP redirect: "
+                                         "no route found for redirect dst\n");
+                return;
+       } else if (ipv6_addr_cmp(&skb->nh.ipv6h->saddr, &rt6->rt6i_gateway) != 0) {
+                       if (net_ratelimit())
+                               printk(KERN_WARNING "ICMP redirect: "
+                                               "not equal to gw-for-src (must be same)\n");
+                       dst_release(&rt6->u.dst);
+                       return;
+       }
+
        in6_dev = in6_dev_get(skb->dev);
        if (!in6_dev)
                return;
------------------------------------------------------------------------

Regards,
Hiroaki Kago