aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2012-07-13 08:03:45 -0400
committerDavid S. Miller <davem@davemloft.net>2012-07-20 16:31:20 -0400
commitf8126f1d5136be1ca1a3536d43ad7a710b5620f8 (patch)
tree8a92815052257c4ca29461f5b9ddaaeac288a7ed /net/ipv4
parentf1ce3062c53809d862d8a04e7a0566c3cc4e0bda (diff)
ipv4: Adjust semantics of rt->rt_gateway.
In order to allow prefixed routes, we have to adjust how rt_gateway is set and interpreted. The new interpretation is: 1) rt_gateway == 0, destination is on-link, nexthop is iph->daddr 2) rt_gateway != 0, destination requires a nexthop gateway Abstract the fetching of the proper nexthop value using a new inline helper, rt_nexthop(), as suggested by Joe Perches. Signed-off-by: David S. Miller <davem@davemloft.net> Tested-by: Vijay Subramanian <subramanian.vijay@gmail.com>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/arp.c3
-rw-r--r--net/ipv4/inet_connection_sock.c4
-rw-r--r--net/ipv4/ip_gre.c2
-rw-r--r--net/ipv4/ip_output.c2
-rw-r--r--net/ipv4/ipip.c2
-rw-r--r--net/ipv4/netfilter/ipt_MASQUERADE.c5
-rw-r--r--net/ipv4/route.c17
7 files changed, 18 insertions, 17 deletions
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index c38293f38161..a0124eb7dbea 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -475,8 +475,7 @@ int arp_find(unsigned char *haddr, struct sk_buff *skb)
475 return 1; 475 return 1;
476 } 476 }
477 477
478 paddr = skb_rtable(skb)->rt_gateway; 478 paddr = rt_nexthop(skb_rtable(skb), ip_hdr(skb)->daddr);
479
480 if (arp_set_predefined(inet_addr_type(dev_net(dev), paddr), haddr, 479 if (arp_set_predefined(inet_addr_type(dev_net(dev), paddr), haddr,
481 paddr, dev)) 480 paddr, dev))
482 return 0; 481 return 0;
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index c7a4de05ca04..0a290d719bc7 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -389,7 +389,7 @@ struct dst_entry *inet_csk_route_req(struct sock *sk,
389 rt = ip_route_output_flow(net, fl4, sk); 389 rt = ip_route_output_flow(net, fl4, sk);
390 if (IS_ERR(rt)) 390 if (IS_ERR(rt))
391 goto no_route; 391 goto no_route;
392 if (opt && opt->opt.is_strictroute && fl4->daddr != rt->rt_gateway) 392 if (opt && opt->opt.is_strictroute && rt->rt_gateway)
393 goto route_err; 393 goto route_err;
394 return &rt->dst; 394 return &rt->dst;
395 395
@@ -422,7 +422,7 @@ struct dst_entry *inet_csk_route_child_sock(struct sock *sk,
422 rt = ip_route_output_flow(net, fl4, sk); 422 rt = ip_route_output_flow(net, fl4, sk);
423 if (IS_ERR(rt)) 423 if (IS_ERR(rt))
424 goto no_route; 424 goto no_route;
425 if (opt && opt->opt.is_strictroute && fl4->daddr != rt->rt_gateway) 425 if (opt && opt->opt.is_strictroute && rt->rt_gateway)
426 goto route_err; 426 goto route_err;
427 return &rt->dst; 427 return &rt->dst;
428 428
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 42c44b1403c9..b062a98574f2 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -766,7 +766,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
766 766
767 if (skb->protocol == htons(ETH_P_IP)) { 767 if (skb->protocol == htons(ETH_P_IP)) {
768 rt = skb_rtable(skb); 768 rt = skb_rtable(skb);
769 dst = rt->rt_gateway; 769 dst = rt_nexthop(rt, old_iph->daddr);
770 } 770 }
771#if IS_ENABLED(CONFIG_IPV6) 771#if IS_ENABLED(CONFIG_IPV6)
772 else if (skb->protocol == htons(ETH_P_IPV6)) { 772 else if (skb->protocol == htons(ETH_P_IPV6)) {
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index c528f841ca4b..4494015f7e32 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -371,7 +371,7 @@ int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl)
371 skb_dst_set_noref(skb, &rt->dst); 371 skb_dst_set_noref(skb, &rt->dst);
372 372
373packet_routed: 373packet_routed:
374 if (inet_opt && inet_opt->opt.is_strictroute && fl4->daddr != rt->rt_gateway) 374 if (inet_opt && inet_opt->opt.is_strictroute && rt->rt_gateway)
375 goto no_route; 375 goto no_route;
376 376
377 /* OK, we know where to send it, allocate and build IP header. */ 377 /* OK, we know where to send it, allocate and build IP header. */
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c
index 2c2c35bace76..99af1f0cc658 100644
--- a/net/ipv4/ipip.c
+++ b/net/ipv4/ipip.c
@@ -487,7 +487,7 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
487 dev->stats.tx_fifo_errors++; 487 dev->stats.tx_fifo_errors++;
488 goto tx_error; 488 goto tx_error;
489 } 489 }
490 dst = rt->rt_gateway; 490 dst = rt_nexthop(rt, old_iph->daddr);
491 } 491 }
492 492
493 rt = ip_route_output_ports(dev_net(dev), &fl4, NULL, 493 rt = ip_route_output_ports(dev_net(dev), &fl4, NULL,
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c
index 2f210c79dc87..cbb6a1a6f6f7 100644
--- a/net/ipv4/netfilter/ipt_MASQUERADE.c
+++ b/net/ipv4/netfilter/ipt_MASQUERADE.c
@@ -52,7 +52,7 @@ masquerade_tg(struct sk_buff *skb, const struct xt_action_param *par)
52 struct nf_nat_ipv4_range newrange; 52 struct nf_nat_ipv4_range newrange;
53 const struct nf_nat_ipv4_multi_range_compat *mr; 53 const struct nf_nat_ipv4_multi_range_compat *mr;
54 const struct rtable *rt; 54 const struct rtable *rt;
55 __be32 newsrc; 55 __be32 newsrc, nh;
56 56
57 NF_CT_ASSERT(par->hooknum == NF_INET_POST_ROUTING); 57 NF_CT_ASSERT(par->hooknum == NF_INET_POST_ROUTING);
58 58
@@ -70,7 +70,8 @@ masquerade_tg(struct sk_buff *skb, const struct xt_action_param *par)
70 70
71 mr = par->targinfo; 71 mr = par->targinfo;
72 rt = skb_rtable(skb); 72 rt = skb_rtable(skb);
73 newsrc = inet_select_addr(par->out, rt->rt_gateway, RT_SCOPE_UNIVERSE); 73 nh = rt_nexthop(rt, ip_hdr(skb)->daddr);
74 newsrc = inet_select_addr(par->out, nh, RT_SCOPE_UNIVERSE);
74 if (!newsrc) { 75 if (!newsrc) {
75 pr_info("%s ate my IP address\n", par->out->name); 76 pr_info("%s ate my IP address\n", par->out->name);
76 return NF_DROP; 77 return NF_DROP;
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 85d103fee88e..d1d579638092 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1085,8 +1085,9 @@ void ip_rt_get_source(u8 *addr, struct sk_buff *skb, struct rtable *rt)
1085 if (fib_lookup(dev_net(rt->dst.dev), &fl4, &res) == 0) 1085 if (fib_lookup(dev_net(rt->dst.dev), &fl4, &res) == 0)
1086 src = FIB_RES_PREFSRC(dev_net(rt->dst.dev), res); 1086 src = FIB_RES_PREFSRC(dev_net(rt->dst.dev), res);
1087 else 1087 else
1088 src = inet_select_addr(rt->dst.dev, rt->rt_gateway, 1088 src = inet_select_addr(rt->dst.dev,
1089 RT_SCOPE_UNIVERSE); 1089 rt_nexthop(rt, iph->daddr),
1090 RT_SCOPE_UNIVERSE);
1090 rcu_read_unlock(); 1091 rcu_read_unlock();
1091 } 1092 }
1092 memcpy(addr, &src, 4); 1093 memcpy(addr, &src, 4);
@@ -1132,7 +1133,7 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst)
1132 mtu = dst->dev->mtu; 1133 mtu = dst->dev->mtu;
1133 1134
1134 if (unlikely(dst_metric_locked(dst, RTAX_MTU))) { 1135 if (unlikely(dst_metric_locked(dst, RTAX_MTU))) {
1135 if (rt->rt_gateway != 0 && mtu > 576) 1136 if (rt->rt_gateway && mtu > 576)
1136 mtu = 576; 1137 mtu = 576;
1137 } 1138 }
1138 1139
@@ -1274,7 +1275,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
1274 rth->rt_iif = dev->ifindex; 1275 rth->rt_iif = dev->ifindex;
1275 rth->rt_oif = 0; 1276 rth->rt_oif = 0;
1276 rth->rt_pmtu = 0; 1277 rth->rt_pmtu = 0;
1277 rth->rt_gateway = daddr; 1278 rth->rt_gateway = 0;
1278 rth->fi = NULL; 1279 rth->fi = NULL;
1279 if (our) { 1280 if (our) {
1280 rth->dst.input= ip_local_deliver; 1281 rth->dst.input= ip_local_deliver;
@@ -1392,7 +1393,7 @@ static int __mkroute_input(struct sk_buff *skb,
1392 rth->rt_iif = in_dev->dev->ifindex; 1393 rth->rt_iif = in_dev->dev->ifindex;
1393 rth->rt_oif = 0; 1394 rth->rt_oif = 0;
1394 rth->rt_pmtu = 0; 1395 rth->rt_pmtu = 0;
1395 rth->rt_gateway = daddr; 1396 rth->rt_gateway = 0;
1396 rth->fi = NULL; 1397 rth->fi = NULL;
1397 1398
1398 rth->dst.input = ip_forward; 1399 rth->dst.input = ip_forward;
@@ -1557,7 +1558,7 @@ local_input:
1557 rth->rt_iif = dev->ifindex; 1558 rth->rt_iif = dev->ifindex;
1558 rth->rt_oif = 0; 1559 rth->rt_oif = 0;
1559 rth->rt_pmtu = 0; 1560 rth->rt_pmtu = 0;
1560 rth->rt_gateway = daddr; 1561 rth->rt_gateway = 0;
1561 rth->fi = NULL; 1562 rth->fi = NULL;
1562 if (res.type == RTN_UNREACHABLE) { 1563 if (res.type == RTN_UNREACHABLE) {
1563 rth->dst.input= ip_error; 1564 rth->dst.input= ip_error;
@@ -1707,7 +1708,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
1707 rth->rt_iif = orig_oif ? : dev_out->ifindex; 1708 rth->rt_iif = orig_oif ? : dev_out->ifindex;
1708 rth->rt_oif = orig_oif; 1709 rth->rt_oif = orig_oif;
1709 rth->rt_pmtu = 0; 1710 rth->rt_pmtu = 0;
1710 rth->rt_gateway = fl4->daddr; 1711 rth->rt_gateway = 0;
1711 rth->fi = NULL; 1712 rth->fi = NULL;
1712 1713
1713 RT_CACHE_STAT_INC(out_slow_tot); 1714 RT_CACHE_STAT_INC(out_slow_tot);
@@ -2070,7 +2071,7 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src,
2070 if (nla_put_be32(skb, RTA_PREFSRC, fl4->saddr)) 2071 if (nla_put_be32(skb, RTA_PREFSRC, fl4->saddr))
2071 goto nla_put_failure; 2072 goto nla_put_failure;
2072 } 2073 }
2073 if (fl4->daddr != rt->rt_gateway && 2074 if (rt->rt_gateway &&
2074 nla_put_be32(skb, RTA_GATEWAY, rt->rt_gateway)) 2075 nla_put_be32(skb, RTA_GATEWAY, rt->rt_gateway))
2075 goto nla_put_failure; 2076 goto nla_put_failure;
2076 2077