Skip to content

Commit f8126f1

Browse files
committed
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 <[email protected]> Tested-by: Vijay Subramanian <[email protected]>
1 parent f1ce306 commit f8126f1

File tree

8 files changed

+25
-17
lines changed

8 files changed

+25
-17
lines changed

include/net/route.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,13 @@ static inline bool rt_is_output_route(const struct rtable *rt)
7070
return rt->rt_route_iif == 0;
7171
}
7272

73+
static inline __be32 rt_nexthop(const struct rtable *rt, __be32 daddr)
74+
{
75+
if (rt->rt_gateway)
76+
return rt->rt_gateway;
77+
return daddr;
78+
}
79+
7380
struct ip_rt_acct {
7481
__u32 o_bytes;
7582
__u32 o_packets;

net/ipv4/arp.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -475,8 +475,7 @@ int arp_find(unsigned char *haddr, struct sk_buff *skb)
475475
return 1;
476476
}
477477

478-
paddr = skb_rtable(skb)->rt_gateway;
479-
478+
paddr = rt_nexthop(skb_rtable(skb), ip_hdr(skb)->daddr);
480479
if (arp_set_predefined(inet_addr_type(dev_net(dev), paddr), haddr,
481480
paddr, dev))
482481
return 0;

net/ipv4/inet_connection_sock.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ struct dst_entry *inet_csk_route_req(struct sock *sk,
389389
rt = ip_route_output_flow(net, fl4, sk);
390390
if (IS_ERR(rt))
391391
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)
393393
goto route_err;
394394
return &rt->dst;
395395

@@ -422,7 +422,7 @@ struct dst_entry *inet_csk_route_child_sock(struct sock *sk,
422422
rt = ip_route_output_flow(net, fl4, sk);
423423
if (IS_ERR(rt))
424424
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)
426426
goto route_err;
427427
return &rt->dst;
428428

net/ipv4/ip_gre.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -766,7 +766,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
766766

767767
if (skb->protocol == htons(ETH_P_IP)) {
768768
rt = skb_rtable(skb);
769-
dst = rt->rt_gateway;
769+
dst = rt_nexthop(rt, old_iph->daddr);
770770
}
771771
#if IS_ENABLED(CONFIG_IPV6)
772772
else if (skb->protocol == htons(ETH_P_IPV6)) {

net/ipv4/ip_output.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl)
371371
skb_dst_set_noref(skb, &rt->dst);
372372

373373
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)
375375
goto no_route;
376376

377377
/* OK, we know where to send it, allocate and build IP header. */

net/ipv4/ipip.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,7 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
487487
dev->stats.tx_fifo_errors++;
488488
goto tx_error;
489489
}
490-
dst = rt->rt_gateway;
490+
dst = rt_nexthop(rt, old_iph->daddr);
491491
}
492492

493493
rt = ip_route_output_ports(dev_net(dev), &fl4, NULL,

net/ipv4/netfilter/ipt_MASQUERADE.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ masquerade_tg(struct sk_buff *skb, const struct xt_action_param *par)
5252
struct nf_nat_ipv4_range newrange;
5353
const struct nf_nat_ipv4_multi_range_compat *mr;
5454
const struct rtable *rt;
55-
__be32 newsrc;
55+
__be32 newsrc, nh;
5656

5757
NF_CT_ASSERT(par->hooknum == NF_INET_POST_ROUTING);
5858

@@ -70,7 +70,8 @@ masquerade_tg(struct sk_buff *skb, const struct xt_action_param *par)
7070

7171
mr = par->targinfo;
7272
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);
7475
if (!newsrc) {
7576
pr_info("%s ate my IP address\n", par->out->name);
7677
return NF_DROP;

net/ipv4/route.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,8 +1085,9 @@ void ip_rt_get_source(u8 *addr, struct sk_buff *skb, struct rtable *rt)
10851085
if (fib_lookup(dev_net(rt->dst.dev), &fl4, &res) == 0)
10861086
src = FIB_RES_PREFSRC(dev_net(rt->dst.dev), res);
10871087
else
1088-
src = inet_select_addr(rt->dst.dev, rt->rt_gateway,
1089-
RT_SCOPE_UNIVERSE);
1088+
src = inet_select_addr(rt->dst.dev,
1089+
rt_nexthop(rt, iph->daddr),
1090+
RT_SCOPE_UNIVERSE);
10901091
rcu_read_unlock();
10911092
}
10921093
memcpy(addr, &src, 4);
@@ -1132,7 +1133,7 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst)
11321133
mtu = dst->dev->mtu;
11331134

11341135
if (unlikely(dst_metric_locked(dst, RTAX_MTU))) {
1135-
if (rt->rt_gateway != 0 && mtu > 576)
1136+
if (rt->rt_gateway && mtu > 576)
11361137
mtu = 576;
11371138
}
11381139

@@ -1274,7 +1275,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
12741275
rth->rt_iif = dev->ifindex;
12751276
rth->rt_oif = 0;
12761277
rth->rt_pmtu = 0;
1277-
rth->rt_gateway = daddr;
1278+
rth->rt_gateway = 0;
12781279
rth->fi = NULL;
12791280
if (our) {
12801281
rth->dst.input= ip_local_deliver;
@@ -1392,7 +1393,7 @@ static int __mkroute_input(struct sk_buff *skb,
13921393
rth->rt_iif = in_dev->dev->ifindex;
13931394
rth->rt_oif = 0;
13941395
rth->rt_pmtu = 0;
1395-
rth->rt_gateway = daddr;
1396+
rth->rt_gateway = 0;
13961397
rth->fi = NULL;
13971398

13981399
rth->dst.input = ip_forward;
@@ -1557,7 +1558,7 @@ out: return err;
15571558
rth->rt_iif = dev->ifindex;
15581559
rth->rt_oif = 0;
15591560
rth->rt_pmtu = 0;
1560-
rth->rt_gateway = daddr;
1561+
rth->rt_gateway = 0;
15611562
rth->fi = NULL;
15621563
if (res.type == RTN_UNREACHABLE) {
15631564
rth->dst.input= ip_error;
@@ -1707,7 +1708,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
17071708
rth->rt_iif = orig_oif ? : dev_out->ifindex;
17081709
rth->rt_oif = orig_oif;
17091710
rth->rt_pmtu = 0;
1710-
rth->rt_gateway = fl4->daddr;
1711+
rth->rt_gateway = 0;
17111712
rth->fi = NULL;
17121713

17131714
RT_CACHE_STAT_INC(out_slow_tot);
@@ -2070,7 +2071,7 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src,
20702071
if (nla_put_be32(skb, RTA_PREFSRC, fl4->saddr))
20712072
goto nla_put_failure;
20722073
}
2073-
if (fl4->daddr != rt->rt_gateway &&
2074+
if (rt->rt_gateway &&
20742075
nla_put_be32(skb, RTA_GATEWAY, rt->rt_gateway))
20752076
goto nla_put_failure;
20762077

0 commit comments

Comments
 (0)