aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/route.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/route.c')
-rw-r--r--net/ipv6/route.c46
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
68enum rt6_nud_state { 68enum 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
85static int ip6_pkt_discard(struct sk_buff *skb); 86static int ip6_pkt_discard(struct sk_buff *skb);
86static int ip6_pkt_discard_out(struct sk_buff *skb); 87static int ip6_pkt_discard_out(struct sk_buff *skb);
88static int ip6_pkt_prohibit(struct sk_buff *skb);
89static int ip6_pkt_prohibit_out(struct sk_buff *skb);
87static void ip6_link_failure(struct sk_buff *skb); 90static void ip6_link_failure(struct sk_buff *skb);
88static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, 91static 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
237static int ip6_pkt_prohibit(struct sk_buff *skb);
238static int ip6_pkt_prohibit_out(struct sk_buff *skb);
239
240static const struct rt6_info ip6_prohibit_entry_template = { 240static 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
2149static int ip6_pkt_prohibit(struct sk_buff *skb) 2153static 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