Skip to content

Commit

Permalink
ipv6: fix the incorrect return value of throw route
Browse files Browse the repository at this point in the history
The error condition -EAGAIN, which is signaled by throw routes, tells
the rules framework to walk on searching for next matches. If the walk
ends and we stop walking the rules with the result of a throw route we
have to translate the error conditions to -ENETUNREACH.

Signed-off-by: Xin Long <[email protected]>
Signed-off-by: Hannes Frederic Sowa <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
lxin authored and davem330 committed Oct 23, 2015
1 parent f23d538 commit ab997ad
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 5 deletions.
19 changes: 15 additions & 4 deletions net/ipv6/fib6_rules.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ struct fib6_rule {
struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
int flags, pol_lookup_t lookup)
{
struct rt6_info *rt;
struct fib_lookup_arg arg = {
.lookup_ptr = lookup,
.flags = FIB_LOOKUP_NOREF,
Expand All @@ -40,11 +41,21 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
fib_rules_lookup(net->ipv6.fib6_rules_ops,
flowi6_to_flowi(fl6), flags, &arg);

if (arg.result)
return arg.result;
rt = arg.result;

dst_hold(&net->ipv6.ip6_null_entry->dst);
return &net->ipv6.ip6_null_entry->dst;
if (!rt) {
dst_hold(&net->ipv6.ip6_null_entry->dst);
return &net->ipv6.ip6_null_entry->dst;
}

if (rt->rt6i_flags & RTF_REJECT &&
rt->dst.error == -EAGAIN) {
ip6_rt_put(rt);
rt = net->ipv6.ip6_null_entry;
dst_hold(&rt->dst);
}

return &rt->dst;
}

static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
Expand Down
12 changes: 11 additions & 1 deletion net/ipv6/ip6_fib.c
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,17 @@ struct fib6_table *fib6_get_table(struct net *net, u32 id)
struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
int flags, pol_lookup_t lookup)
{
return (struct dst_entry *) lookup(net, net->ipv6.fib6_main_tbl, fl6, flags);
struct rt6_info *rt;

rt = lookup(net, net->ipv6.fib6_main_tbl, fl6, flags);
if (rt->rt6i_flags & RTF_REJECT &&
rt->dst.error == -EAGAIN) {
ip6_rt_put(rt);
rt = net->ipv6.ip6_null_entry;
dst_hold(&rt->dst);
}

return &rt->dst;
}

static void __net_init fib6_tables_init(struct net *net)
Expand Down

0 comments on commit ab997ad

Please sign in to comment.