]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - net/ipv6/route.c
proc: clean the ip_misc_proc_init and ip_proc_init_net error paths
[net-next-2.6.git] / net / ipv6 / route.c
index 7ff687020fa9ee780042ddeeb080e3ebb20f8199..5d6c166dfbb6e087e0f634d69d305d1f1912fdda 100644 (file)
@@ -5,8 +5,6 @@
  *     Authors:
  *     Pedro Roque             <roque@di.fc.ul.pt>
  *
- *     $Id: route.c,v 1.56 2001/10/31 21:55:55 davem Exp $
- *
  *     This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
  *      as published by the Free Software Foundation; either version
@@ -230,7 +228,7 @@ static __inline__ int rt6_check_expired(const struct rt6_info *rt)
 static inline int rt6_need_strict(struct in6_addr *daddr)
 {
        return (ipv6_addr_type(daddr) &
-               (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL));
+               (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK));
 }
 
 /*
@@ -239,15 +237,20 @@ static inline int rt6_need_strict(struct in6_addr *daddr)
 
 static inline struct rt6_info *rt6_device_match(struct net *net,
                                                    struct rt6_info *rt,
+                                                   struct in6_addr *saddr,
                                                    int oif,
                                                    int flags)
 {
        struct rt6_info *local = NULL;
        struct rt6_info *sprt;
 
-       if (oif) {
-               for (sprt = rt; sprt; sprt = sprt->u.dst.rt6_next) {
-                       struct net_device *dev = sprt->rt6i_dev;
+       if (!oif && ipv6_addr_any(saddr))
+               goto out;
+
+       for (sprt = rt; sprt; sprt = sprt->u.dst.rt6_next) {
+               struct net_device *dev = sprt->rt6i_dev;
+
+               if (oif) {
                        if (dev->ifindex == oif)
                                return sprt;
                        if (dev->flags & IFF_LOOPBACK) {
@@ -261,14 +264,21 @@ static inline struct rt6_info *rt6_device_match(struct net *net,
                                }
                                local = sprt;
                        }
+               } else {
+                       if (ipv6_chk_addr(net, saddr, dev,
+                                         flags & RT6_LOOKUP_F_IFACE))
+                               return sprt;
                }
+       }
 
+       if (oif) {
                if (local)
                        return local;
 
                if (flags & RT6_LOOKUP_F_IFACE)
                        return net->ipv6.ip6_null_entry;
        }
+out:
        return rt;
 }
 
@@ -541,7 +551,7 @@ static struct rt6_info *ip6_pol_route_lookup(struct net *net,
        fn = fib6_lookup(&table->tb6_root, &fl->fl6_dst, &fl->fl6_src);
 restart:
        rt = fn->leaf;
-       rt = rt6_device_match(net, rt, fl->oif, flags);
+       rt = rt6_device_match(net, rt, &fl->fl6_src, fl->oif, flags);
        BACKTRACK(net, &fl->fl6_src);
 out:
        dst_use(&rt->u.dst, jiffies);