[IPV6] ROUTE: Fix looking up a route on subtree.
authorYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Thu, 24 Aug 2006 00:21:12 +0000 (17:21 -0700)
committerDavid S. Miller <davem@sunset.davemloft.net>
Fri, 22 Sep 2006 21:55:48 +0000 (14:55 -0700)
Even on RTN_ROOT node, we need to process its subtree first.
Fix NULL pointer dereference in fib6_locate().

Based on MIPL2 kernel patch.

Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: Ville Nuorvala <vnuorval@tcs.hut.fi>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv6/ip6_fib.c

index 35b91ff95db2c9e7e570628da82359715dd56a0d..5408b64f3b5fa8c799ddea68080f713cee0fd6a3 100644 (file)
@@ -850,33 +850,26 @@ static struct fib6_node * fib6_lookup_1(struct fib6_node *root,
                break;
        }
 
-       while ((fn->fn_flags & RTN_ROOT) == 0) {
-#ifdef CONFIG_IPV6_SUBTREES
-               if (fn->subtree) {
-                       struct fib6_node *st;
-                       struct lookup_args *narg;
-
-                       narg = args + 1;
-
-                       if (narg->addr) {
-                               st = fib6_lookup_1(fn->subtree, narg);
-
-                               if (st && !(st->fn_flags & RTN_ROOT))
-                                       return st;
-                       }
-               }
-#endif
-
-               if (fn->fn_flags & RTN_RTINFO) {
+       while(fn) {
+               if (SUBTREE(fn) || fn->fn_flags & RTN_RTINFO) {
                        struct rt6key *key;
 
                        key = (struct rt6key *) ((u8 *) fn->leaf +
                                                 args->offset);
 
-                       if (ipv6_prefix_equal(&key->addr, args->addr, key->plen))
-                               return fn;
+                       if (ipv6_prefix_equal(&key->addr, args->addr, key->plen)) {
+#ifdef CONFIG_IPV6_SUBTREES
+                               if (fn->subtree)
+                                       fn = fib6_lookup_1(fn->subtree, args + 1);
+#endif
+                               if (!fn || fn->fn_flags & RTN_RTINFO)
+                                       return fn;
+                       }
                }
 
+               if (fn->fn_flags & RTN_ROOT)
+                       break;
+
                fn = fn->parent;
        }
 
@@ -953,10 +946,8 @@ struct fib6_node * fib6_locate(struct fib6_node *root,
 #ifdef CONFIG_IPV6_SUBTREES
        if (src_len) {
                BUG_TRAP(saddr!=NULL);
-               if (fn == NULL)
-                       fn = fn->subtree;
-               if (fn)
-                       fn = fib6_locate_1(fn, saddr, src_len,
+               if (fn && fn->subtree)
+                       fn = fib6_locate_1(fn->subtree, saddr, src_len,
                                           offsetof(struct rt6_info, rt6i_src));
        }
 #endif