Skip to content

Commit fc1e64e

Browse files
dsaherndavem330
authored andcommitted
net/ipv6: Add support for onlink flag
Similar to IPv4 allow routes to be added with the RTNH_F_ONLINK flag. The onlink option requires a gateway and a nexthop device. Any unicast gateway is allowed (including IPv4 mapped addresses and unresolved ones) as long as the gateway is not a local address and if it resolves it must match the given device. Signed-off-by: David Ahern <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent f4797b3 commit fc1e64e

File tree

1 file changed

+50
-1
lines changed

1 file changed

+50
-1
lines changed

net/ipv6/route.c

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2470,6 +2470,31 @@ static struct rt6_info *ip6_nh_lookup_table(struct net *net,
24702470
return rt;
24712471
}
24722472

2473+
static int ip6_route_check_nh_onlink(struct net *net,
2474+
struct fib6_config *cfg,
2475+
struct net_device *dev,
2476+
struct netlink_ext_ack *extack)
2477+
{
2478+
u32 tbid = l3mdev_fib_table(dev) ? : RT_TABLE_LOCAL;
2479+
const struct in6_addr *gw_addr = &cfg->fc_gateway;
2480+
u32 flags = RTF_LOCAL | RTF_ANYCAST | RTF_REJECT;
2481+
struct rt6_info *grt;
2482+
int err;
2483+
2484+
err = 0;
2485+
grt = ip6_nh_lookup_table(net, cfg, gw_addr, tbid, 0);
2486+
if (grt) {
2487+
if (grt->rt6i_flags & flags || dev != grt->dst.dev) {
2488+
NL_SET_ERR_MSG(extack, "Nexthop has invalid gateway");
2489+
err = -EINVAL;
2490+
}
2491+
2492+
ip6_rt_put(grt);
2493+
}
2494+
2495+
return err;
2496+
}
2497+
24732498
static int ip6_route_check_nh(struct net *net,
24742499
struct fib6_config *cfg,
24752500
struct net_device **_dev,
@@ -2572,6 +2597,21 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg,
25722597
if (cfg->fc_metric == 0)
25732598
cfg->fc_metric = IP6_RT_PRIO_USER;
25742599

2600+
if (cfg->fc_flags & RTNH_F_ONLINK) {
2601+
if (!dev) {
2602+
NL_SET_ERR_MSG(extack,
2603+
"Nexthop device required for onlink");
2604+
err = -ENODEV;
2605+
goto out;
2606+
}
2607+
2608+
if (!(dev->flags & IFF_UP)) {
2609+
NL_SET_ERR_MSG(extack, "Nexthop device is not up");
2610+
err = -ENETDOWN;
2611+
goto out;
2612+
}
2613+
}
2614+
25752615
err = -ENOBUFS;
25762616
if (cfg->fc_nlinfo.nlh &&
25772617
!(cfg->fc_nlinfo.nlh->nlmsg_flags & NLM_F_CREATE)) {
@@ -2732,7 +2772,12 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg,
27322772
goto out;
27332773
}
27342774

2735-
err = ip6_route_check_nh(net, cfg, &dev, &idev);
2775+
if (cfg->fc_flags & RTNH_F_ONLINK) {
2776+
err = ip6_route_check_nh_onlink(net, cfg, dev,
2777+
extack);
2778+
} else {
2779+
err = ip6_route_check_nh(net, cfg, &dev, &idev);
2780+
}
27362781
if (err)
27372782
goto out;
27382783
}
@@ -2774,6 +2819,7 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg,
27742819
if (!(rt->rt6i_flags & (RTF_LOCAL | RTF_ANYCAST)) &&
27752820
!netif_carrier_ok(dev))
27762821
rt->rt6i_nh_flags |= RTNH_F_LINKDOWN;
2822+
rt->rt6i_nh_flags |= (cfg->fc_flags & RTNH_F_ONLINK);
27772823
rt->dst.dev = dev;
27782824
rt->rt6i_idev = idev;
27792825
rt->rt6i_table = table;
@@ -3843,6 +3889,8 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
38433889
if (rtm->rtm_flags & RTM_F_CLONED)
38443890
cfg->fc_flags |= RTF_CACHE;
38453891

3892+
cfg->fc_flags |= (rtm->rtm_flags & RTNH_F_ONLINK);
3893+
38463894
cfg->fc_nlinfo.portid = NETLINK_CB(skb).portid;
38473895
cfg->fc_nlinfo.nlh = nlh;
38483896
cfg->fc_nlinfo.nl_net = sock_net(skb->sk);
@@ -4248,6 +4296,7 @@ static int rt6_nexthop_info(struct sk_buff *skb, struct rt6_info *rt,
42484296
goto nla_put_failure;
42494297
}
42504298

4299+
*flags |= (rt->rt6i_nh_flags & RTNH_F_ONLINK);
42514300
if (rt->rt6i_nh_flags & RTNH_F_OFFLOAD)
42524301
*flags |= RTNH_F_OFFLOAD;
42534302

0 commit comments

Comments
 (0)