diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/fib_frontend.c | 3 | ||||
-rw-r--r-- | net/ipv4/route.c | 30 |
2 files changed, 18 insertions, 15 deletions
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 68c93d1bb03a..825c608826de 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -322,7 +322,8 @@ int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst, | |||
322 | { | 322 | { |
323 | int r = secpath_exists(skb) ? 0 : IN_DEV_RPFILTER(idev); | 323 | int r = secpath_exists(skb) ? 0 : IN_DEV_RPFILTER(idev); |
324 | 324 | ||
325 | if (!r && !fib_num_tclassid_users(dev_net(dev))) { | 325 | if (!r && !fib_num_tclassid_users(dev_net(dev)) && |
326 | (dev->ifindex != oif || !IN_DEV_TX_REDIRECTS(idev))) { | ||
326 | *itag = 0; | 327 | *itag = 0; |
327 | return 0; | 328 | return 0; |
328 | } | 329 | } |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 132e0dfee53a..b90da1bc2704 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -802,7 +802,8 @@ void ip_rt_send_redirect(struct sk_buff *skb) | |||
802 | net = dev_net(rt->dst.dev); | 802 | net = dev_net(rt->dst.dev); |
803 | peer = inet_getpeer_v4(net->ipv4.peers, ip_hdr(skb)->saddr, 1); | 803 | peer = inet_getpeer_v4(net->ipv4.peers, ip_hdr(skb)->saddr, 1); |
804 | if (!peer) { | 804 | if (!peer) { |
805 | icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, rt->rt_gateway); | 805 | icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, |
806 | rt_nexthop(rt, ip_hdr(skb)->daddr)); | ||
806 | return; | 807 | return; |
807 | } | 808 | } |
808 | 809 | ||
@@ -827,7 +828,9 @@ void ip_rt_send_redirect(struct sk_buff *skb) | |||
827 | time_after(jiffies, | 828 | time_after(jiffies, |
828 | (peer->rate_last + | 829 | (peer->rate_last + |
829 | (ip_rt_redirect_load << peer->rate_tokens)))) { | 830 | (ip_rt_redirect_load << peer->rate_tokens)))) { |
830 | icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, rt->rt_gateway); | 831 | __be32 gw = rt_nexthop(rt, ip_hdr(skb)->daddr); |
832 | |||
833 | icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, gw); | ||
831 | peer->rate_last = jiffies; | 834 | peer->rate_last = jiffies; |
832 | ++peer->rate_tokens; | 835 | ++peer->rate_tokens; |
833 | #ifdef CONFIG_IP_ROUTE_VERBOSE | 836 | #ifdef CONFIG_IP_ROUTE_VERBOSE |
@@ -835,7 +838,7 @@ void ip_rt_send_redirect(struct sk_buff *skb) | |||
835 | peer->rate_tokens == ip_rt_redirect_number) | 838 | peer->rate_tokens == ip_rt_redirect_number) |
836 | net_warn_ratelimited("host %pI4/if%d ignores redirects for %pI4 to %pI4\n", | 839 | net_warn_ratelimited("host %pI4/if%d ignores redirects for %pI4 to %pI4\n", |
837 | &ip_hdr(skb)->saddr, inet_iif(skb), | 840 | &ip_hdr(skb)->saddr, inet_iif(skb), |
838 | &ip_hdr(skb)->daddr, &rt->rt_gateway); | 841 | &ip_hdr(skb)->daddr, &gw); |
839 | #endif | 842 | #endif |
840 | } | 843 | } |
841 | out_put_peer: | 844 | out_put_peer: |
@@ -1442,10 +1445,13 @@ static int __mkroute_input(struct sk_buff *skb, | |||
1442 | goto cleanup; | 1445 | goto cleanup; |
1443 | } | 1446 | } |
1444 | 1447 | ||
1445 | if (out_dev == in_dev && err && | 1448 | do_cache = res->fi && !itag; |
1449 | if (out_dev == in_dev && err && IN_DEV_TX_REDIRECTS(out_dev) && | ||
1446 | (IN_DEV_SHARED_MEDIA(out_dev) || | 1450 | (IN_DEV_SHARED_MEDIA(out_dev) || |
1447 | inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res)))) | 1451 | inet_addr_onlink(out_dev, saddr, FIB_RES_GW(*res)))) { |
1448 | flags |= RTCF_DOREDIRECT; | 1452 | flags |= RTCF_DOREDIRECT; |
1453 | do_cache = false; | ||
1454 | } | ||
1449 | 1455 | ||
1450 | if (skb->protocol != htons(ETH_P_IP)) { | 1456 | if (skb->protocol != htons(ETH_P_IP)) { |
1451 | /* Not IP (i.e. ARP). Do not create route, if it is | 1457 | /* Not IP (i.e. ARP). Do not create route, if it is |
@@ -1462,15 +1468,11 @@ static int __mkroute_input(struct sk_buff *skb, | |||
1462 | } | 1468 | } |
1463 | } | 1469 | } |
1464 | 1470 | ||
1465 | do_cache = false; | 1471 | if (do_cache) { |
1466 | if (res->fi) { | 1472 | rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input); |
1467 | if (!itag) { | 1473 | if (rt_cache_valid(rth)) { |
1468 | rth = rcu_dereference(FIB_RES_NH(*res).nh_rth_input); | 1474 | skb_dst_set_noref(skb, &rth->dst); |
1469 | if (rt_cache_valid(rth)) { | 1475 | goto out; |
1470 | skb_dst_set_noref(skb, &rth->dst); | ||
1471 | goto out; | ||
1472 | } | ||
1473 | do_cache = true; | ||
1474 | } | 1476 | } |
1475 | } | 1477 | } |
1476 | 1478 | ||