Loading net/ipv6/route.c +47 −43 Original line number Diff line number Diff line Loading @@ -1144,17 +1144,26 @@ static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_r void rt6_redirect(struct in6_addr *dest, struct in6_addr *saddr, struct neighbour *neigh, u8 *lladdr, int on_link) { struct rt6_info *rt, *nrt; /* Locate old route to this destination. */ rt = rt6_lookup(dest, NULL, neigh->dev->ifindex, 1); if (rt == NULL) return; struct rt6_info *rt, *nrt = NULL; int strict; struct fib6_node *fn; if (neigh->dev != rt->rt6i_dev) goto out; /* * Get the "current" route for this destination and * check if the redirect has come from approriate router. * * RFC 2461 specifies that redirects should only be * accepted if they come from the nexthop to the target. * Due to the way the routes are chosen, this notion * is a bit fuzzy and one might need to check all possible * routes. */ strict = ipv6_addr_type(dest) & (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL); read_lock_bh(&rt6_lock); fn = fib6_lookup(&ip6_routing_table, dest, NULL); restart: for (rt = fn->leaf; rt; rt = rt->u.next) { /* * Current route is on-link; redirect is always invalid. * Loading @@ -1163,40 +1172,35 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *saddr, * But then router serving it might decide, that we should * know truth 8)8) --ANK (980726). */ if (rt6_check_expired(rt)) continue; if (!(rt->rt6i_flags & RTF_GATEWAY)) goto out; /* * RFC 2461 specifies that redirects should only be * accepted if they come from the nexthop to the target. * Due to the way default routers are chosen, this notion * is a bit fuzzy and one might need to check all default * routers. */ if (!ipv6_addr_equal(saddr, &rt->rt6i_gateway)) { if (rt->rt6i_flags & RTF_DEFAULT) { struct rt6_info *rt1; read_lock(&rt6_lock); for (rt1 = ip6_routing_table.leaf; rt1; rt1 = rt1->u.next) { if (ipv6_addr_equal(saddr, &rt1->rt6i_gateway)) { dst_hold(&rt1->u.dst); dst_release(&rt->u.dst); read_unlock(&rt6_lock); rt = rt1; goto source_ok; continue; if (neigh->dev != rt->rt6i_dev) continue; if (!ipv6_addr_equal(saddr, &rt->rt6i_gateway)) continue; break; } if (rt) dst_hold(&rt->u.dst); else if (strict) { while ((fn = fn->parent) != NULL) { if (fn->fn_flags & RTN_ROOT) break; if (fn->fn_flags & RTN_RTINFO) goto restart; } read_unlock(&rt6_lock); } read_unlock_bh(&rt6_lock); if (!rt) { if (net_ratelimit()) printk(KERN_DEBUG "rt6_redirect: source isn't a valid nexthop " "for redirect target\n"); goto out; return; } source_ok: /* * We have finally decided to accept it. */ Loading Loading
net/ipv6/route.c +47 −43 Original line number Diff line number Diff line Loading @@ -1144,17 +1144,26 @@ static int ip6_route_del(struct in6_rtmsg *rtmsg, struct nlmsghdr *nlh, void *_r void rt6_redirect(struct in6_addr *dest, struct in6_addr *saddr, struct neighbour *neigh, u8 *lladdr, int on_link) { struct rt6_info *rt, *nrt; /* Locate old route to this destination. */ rt = rt6_lookup(dest, NULL, neigh->dev->ifindex, 1); if (rt == NULL) return; struct rt6_info *rt, *nrt = NULL; int strict; struct fib6_node *fn; if (neigh->dev != rt->rt6i_dev) goto out; /* * Get the "current" route for this destination and * check if the redirect has come from approriate router. * * RFC 2461 specifies that redirects should only be * accepted if they come from the nexthop to the target. * Due to the way the routes are chosen, this notion * is a bit fuzzy and one might need to check all possible * routes. */ strict = ipv6_addr_type(dest) & (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL); read_lock_bh(&rt6_lock); fn = fib6_lookup(&ip6_routing_table, dest, NULL); restart: for (rt = fn->leaf; rt; rt = rt->u.next) { /* * Current route is on-link; redirect is always invalid. * Loading @@ -1163,40 +1172,35 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *saddr, * But then router serving it might decide, that we should * know truth 8)8) --ANK (980726). */ if (rt6_check_expired(rt)) continue; if (!(rt->rt6i_flags & RTF_GATEWAY)) goto out; /* * RFC 2461 specifies that redirects should only be * accepted if they come from the nexthop to the target. * Due to the way default routers are chosen, this notion * is a bit fuzzy and one might need to check all default * routers. */ if (!ipv6_addr_equal(saddr, &rt->rt6i_gateway)) { if (rt->rt6i_flags & RTF_DEFAULT) { struct rt6_info *rt1; read_lock(&rt6_lock); for (rt1 = ip6_routing_table.leaf; rt1; rt1 = rt1->u.next) { if (ipv6_addr_equal(saddr, &rt1->rt6i_gateway)) { dst_hold(&rt1->u.dst); dst_release(&rt->u.dst); read_unlock(&rt6_lock); rt = rt1; goto source_ok; continue; if (neigh->dev != rt->rt6i_dev) continue; if (!ipv6_addr_equal(saddr, &rt->rt6i_gateway)) continue; break; } if (rt) dst_hold(&rt->u.dst); else if (strict) { while ((fn = fn->parent) != NULL) { if (fn->fn_flags & RTN_ROOT) break; if (fn->fn_flags & RTN_RTINFO) goto restart; } read_unlock(&rt6_lock); } read_unlock_bh(&rt6_lock); if (!rt) { if (net_ratelimit()) printk(KERN_DEBUG "rt6_redirect: source isn't a valid nexthop " "for redirect target\n"); goto out; return; } source_ok: /* * We have finally decided to accept it. */ Loading