diff options
author | David S. Miller <davem@davemloft.net> | 2012-07-13 08:03:45 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-07-20 16:31:20 -0400 |
commit | f8126f1d5136be1ca1a3536d43ad7a710b5620f8 (patch) | |
tree | 8a92815052257c4ca29461f5b9ddaaeac288a7ed /net/ipv4 | |
parent | f1ce3062c53809d862d8a04e7a0566c3cc4e0bda (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.c | 3 | ||||
-rw-r--r-- | net/ipv4/inet_connection_sock.c | 4 | ||||
-rw-r--r-- | net/ipv4/ip_gre.c | 2 | ||||
-rw-r--r-- | net/ipv4/ip_output.c | 2 | ||||
-rw-r--r-- | net/ipv4/ipip.c | 2 | ||||
-rw-r--r-- | net/ipv4/netfilter/ipt_MASQUERADE.c | 5 | ||||
-rw-r--r-- | net/ipv4/route.c | 17 |
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 | ||
373 | packet_routed: | 373 | packet_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 | ||