diff options
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r-- | net/ipv6/route.c | 46 |
1 files changed, 23 insertions, 23 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 7faa9d5e1503..89b2735cecf5 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -66,8 +66,9 @@ | |||
66 | #endif | 66 | #endif |
67 | 67 | ||
68 | enum rt6_nud_state { | 68 | enum rt6_nud_state { |
69 | RT6_NUD_FAIL_HARD = -2, | 69 | RT6_NUD_FAIL_HARD = -3, |
70 | RT6_NUD_FAIL_SOFT = -1, | 70 | RT6_NUD_FAIL_PROBE = -2, |
71 | RT6_NUD_FAIL_DO_RR = -1, | ||
71 | RT6_NUD_SUCCEED = 1 | 72 | RT6_NUD_SUCCEED = 1 |
72 | }; | 73 | }; |
73 | 74 | ||
@@ -84,6 +85,8 @@ static int ip6_dst_gc(struct dst_ops *ops); | |||
84 | 85 | ||
85 | static int ip6_pkt_discard(struct sk_buff *skb); | 86 | static int ip6_pkt_discard(struct sk_buff *skb); |
86 | static int ip6_pkt_discard_out(struct sk_buff *skb); | 87 | static int ip6_pkt_discard_out(struct sk_buff *skb); |
88 | static int ip6_pkt_prohibit(struct sk_buff *skb); | ||
89 | static int ip6_pkt_prohibit_out(struct sk_buff *skb); | ||
87 | static void ip6_link_failure(struct sk_buff *skb); | 90 | static void ip6_link_failure(struct sk_buff *skb); |
88 | static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, | 91 | static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, |
89 | struct sk_buff *skb, u32 mtu); | 92 | struct sk_buff *skb, u32 mtu); |
@@ -234,9 +237,6 @@ static const struct rt6_info ip6_null_entry_template = { | |||
234 | 237 | ||
235 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 238 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
236 | 239 | ||
237 | static int ip6_pkt_prohibit(struct sk_buff *skb); | ||
238 | static int ip6_pkt_prohibit_out(struct sk_buff *skb); | ||
239 | |||
240 | static const struct rt6_info ip6_prohibit_entry_template = { | 240 | static const struct rt6_info ip6_prohibit_entry_template = { |
241 | .dst = { | 241 | .dst = { |
242 | .__refcnt = ATOMIC_INIT(1), | 242 | .__refcnt = ATOMIC_INIT(1), |
@@ -522,7 +522,7 @@ static void rt6_probe(struct rt6_info *rt) | |||
522 | work = kmalloc(sizeof(*work), GFP_ATOMIC); | 522 | work = kmalloc(sizeof(*work), GFP_ATOMIC); |
523 | 523 | ||
524 | if (neigh && work) | 524 | if (neigh && work) |
525 | neigh->updated = jiffies; | 525 | __neigh_set_probe_once(neigh); |
526 | 526 | ||
527 | if (neigh) | 527 | if (neigh) |
528 | write_unlock(&neigh->lock); | 528 | write_unlock(&neigh->lock); |
@@ -578,11 +578,13 @@ static inline enum rt6_nud_state rt6_check_neigh(struct rt6_info *rt) | |||
578 | #ifdef CONFIG_IPV6_ROUTER_PREF | 578 | #ifdef CONFIG_IPV6_ROUTER_PREF |
579 | else if (!(neigh->nud_state & NUD_FAILED)) | 579 | else if (!(neigh->nud_state & NUD_FAILED)) |
580 | ret = RT6_NUD_SUCCEED; | 580 | ret = RT6_NUD_SUCCEED; |
581 | else | ||
582 | ret = RT6_NUD_FAIL_PROBE; | ||
581 | #endif | 583 | #endif |
582 | read_unlock(&neigh->lock); | 584 | read_unlock(&neigh->lock); |
583 | } else { | 585 | } else { |
584 | ret = IS_ENABLED(CONFIG_IPV6_ROUTER_PREF) ? | 586 | ret = IS_ENABLED(CONFIG_IPV6_ROUTER_PREF) ? |
585 | RT6_NUD_SUCCEED : RT6_NUD_FAIL_SOFT; | 587 | RT6_NUD_SUCCEED : RT6_NUD_FAIL_DO_RR; |
586 | } | 588 | } |
587 | rcu_read_unlock_bh(); | 589 | rcu_read_unlock_bh(); |
588 | 590 | ||
@@ -619,16 +621,17 @@ static struct rt6_info *find_match(struct rt6_info *rt, int oif, int strict, | |||
619 | goto out; | 621 | goto out; |
620 | 622 | ||
621 | m = rt6_score_route(rt, oif, strict); | 623 | m = rt6_score_route(rt, oif, strict); |
622 | if (m == RT6_NUD_FAIL_SOFT) { | 624 | if (m == RT6_NUD_FAIL_DO_RR) { |
623 | match_do_rr = true; | 625 | match_do_rr = true; |
624 | m = 0; /* lowest valid score */ | 626 | m = 0; /* lowest valid score */ |
625 | } else if (m < 0) { | 627 | } else if (m == RT6_NUD_FAIL_HARD) { |
626 | goto out; | 628 | goto out; |
627 | } | 629 | } |
628 | 630 | ||
629 | if (strict & RT6_LOOKUP_F_REACHABLE) | 631 | if (strict & RT6_LOOKUP_F_REACHABLE) |
630 | rt6_probe(rt); | 632 | rt6_probe(rt); |
631 | 633 | ||
634 | /* note that m can be RT6_NUD_FAIL_PROBE at this point */ | ||
632 | if (m > *mpri) { | 635 | if (m > *mpri) { |
633 | *do_rr = match_do_rr; | 636 | *do_rr = match_do_rr; |
634 | *mpri = m; | 637 | *mpri = m; |
@@ -1565,21 +1568,24 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1565 | goto out; | 1568 | goto out; |
1566 | } | 1569 | } |
1567 | } | 1570 | } |
1568 | rt->dst.output = ip6_pkt_discard_out; | ||
1569 | rt->dst.input = ip6_pkt_discard; | ||
1570 | rt->rt6i_flags = RTF_REJECT|RTF_NONEXTHOP; | 1571 | rt->rt6i_flags = RTF_REJECT|RTF_NONEXTHOP; |
1571 | switch (cfg->fc_type) { | 1572 | switch (cfg->fc_type) { |
1572 | case RTN_BLACKHOLE: | 1573 | case RTN_BLACKHOLE: |
1573 | rt->dst.error = -EINVAL; | 1574 | rt->dst.error = -EINVAL; |
1575 | rt->dst.output = dst_discard; | ||
1576 | rt->dst.input = dst_discard; | ||
1574 | break; | 1577 | break; |
1575 | case RTN_PROHIBIT: | 1578 | case RTN_PROHIBIT: |
1576 | rt->dst.error = -EACCES; | 1579 | rt->dst.error = -EACCES; |
1580 | rt->dst.output = ip6_pkt_prohibit_out; | ||
1581 | rt->dst.input = ip6_pkt_prohibit; | ||
1577 | break; | 1582 | break; |
1578 | case RTN_THROW: | 1583 | case RTN_THROW: |
1579 | rt->dst.error = -EAGAIN; | ||
1580 | break; | ||
1581 | default: | 1584 | default: |
1582 | rt->dst.error = -ENETUNREACH; | 1585 | rt->dst.error = (cfg->fc_type == RTN_THROW) ? -EAGAIN |
1586 | : -ENETUNREACH; | ||
1587 | rt->dst.output = ip6_pkt_discard_out; | ||
1588 | rt->dst.input = ip6_pkt_discard; | ||
1583 | break; | 1589 | break; |
1584 | } | 1590 | } |
1585 | goto install_route; | 1591 | goto install_route; |
@@ -2144,8 +2150,6 @@ static int ip6_pkt_discard_out(struct sk_buff *skb) | |||
2144 | return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_OUTNOROUTES); | 2150 | return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_OUTNOROUTES); |
2145 | } | 2151 | } |
2146 | 2152 | ||
2147 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | ||
2148 | |||
2149 | static int ip6_pkt_prohibit(struct sk_buff *skb) | 2153 | static int ip6_pkt_prohibit(struct sk_buff *skb) |
2150 | { | 2154 | { |
2151 | return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_INNOROUTES); | 2155 | return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_INNOROUTES); |
@@ -2157,8 +2161,6 @@ static int ip6_pkt_prohibit_out(struct sk_buff *skb) | |||
2157 | return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES); | 2161 | return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES); |
2158 | } | 2162 | } |
2159 | 2163 | ||
2160 | #endif | ||
2161 | |||
2162 | /* | 2164 | /* |
2163 | * Allocate a dst for local (unicast / anycast) address. | 2165 | * Allocate a dst for local (unicast / anycast) address. |
2164 | */ | 2166 | */ |
@@ -2168,12 +2170,10 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
2168 | bool anycast) | 2170 | bool anycast) |
2169 | { | 2171 | { |
2170 | struct net *net = dev_net(idev->dev); | 2172 | struct net *net = dev_net(idev->dev); |
2171 | struct rt6_info *rt = ip6_dst_alloc(net, net->loopback_dev, 0, NULL); | 2173 | struct rt6_info *rt = ip6_dst_alloc(net, net->loopback_dev, |
2172 | 2174 | DST_NOCOUNT, NULL); | |
2173 | if (!rt) { | 2175 | if (!rt) |
2174 | net_warn_ratelimited("Maximum number of routes reached, consider increasing route/max_size\n"); | ||
2175 | return ERR_PTR(-ENOMEM); | 2176 | return ERR_PTR(-ENOMEM); |
2176 | } | ||
2177 | 2177 | ||
2178 | in6_dev_hold(idev); | 2178 | in6_dev_hold(idev); |
2179 | 2179 | ||