aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/fib_frontend.c3
-rw-r--r--net/ipv4/route.c30
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 }
841out_put_peer: 844out_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