mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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 <dsahern@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									f4797b33db
								
							
						
					
					
						commit
						fc1e64e109
					
				
					 1 changed files with 50 additions and 1 deletions
				
			
		| 
						 | 
				
			
			@ -2470,6 +2470,31 @@ static struct rt6_info *ip6_nh_lookup_table(struct net *net,
 | 
			
		|||
	return rt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int ip6_route_check_nh_onlink(struct net *net,
 | 
			
		||||
				     struct fib6_config *cfg,
 | 
			
		||||
				     struct net_device *dev,
 | 
			
		||||
				     struct netlink_ext_ack *extack)
 | 
			
		||||
{
 | 
			
		||||
	u32 tbid = l3mdev_fib_table(dev) ? : RT_TABLE_LOCAL;
 | 
			
		||||
	const struct in6_addr *gw_addr = &cfg->fc_gateway;
 | 
			
		||||
	u32 flags = RTF_LOCAL | RTF_ANYCAST | RTF_REJECT;
 | 
			
		||||
	struct rt6_info *grt;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
	err = 0;
 | 
			
		||||
	grt = ip6_nh_lookup_table(net, cfg, gw_addr, tbid, 0);
 | 
			
		||||
	if (grt) {
 | 
			
		||||
		if (grt->rt6i_flags & flags || dev != grt->dst.dev) {
 | 
			
		||||
			NL_SET_ERR_MSG(extack, "Nexthop has invalid gateway");
 | 
			
		||||
			err = -EINVAL;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ip6_rt_put(grt);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return err;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int ip6_route_check_nh(struct net *net,
 | 
			
		||||
			      struct fib6_config *cfg,
 | 
			
		||||
			      struct net_device **_dev,
 | 
			
		||||
| 
						 | 
				
			
			@ -2572,6 +2597,21 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg,
 | 
			
		|||
	if (cfg->fc_metric == 0)
 | 
			
		||||
		cfg->fc_metric = IP6_RT_PRIO_USER;
 | 
			
		||||
 | 
			
		||||
	if (cfg->fc_flags & RTNH_F_ONLINK) {
 | 
			
		||||
		if (!dev) {
 | 
			
		||||
			NL_SET_ERR_MSG(extack,
 | 
			
		||||
				       "Nexthop device required for onlink");
 | 
			
		||||
			err = -ENODEV;
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!(dev->flags & IFF_UP)) {
 | 
			
		||||
			NL_SET_ERR_MSG(extack, "Nexthop device is not up");
 | 
			
		||||
			err = -ENETDOWN;
 | 
			
		||||
			goto out;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = -ENOBUFS;
 | 
			
		||||
	if (cfg->fc_nlinfo.nlh &&
 | 
			
		||||
	    !(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,
 | 
			
		|||
				goto out;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			err = ip6_route_check_nh(net, cfg, &dev, &idev);
 | 
			
		||||
			if (cfg->fc_flags & RTNH_F_ONLINK) {
 | 
			
		||||
				err = ip6_route_check_nh_onlink(net, cfg, dev,
 | 
			
		||||
								extack);
 | 
			
		||||
			} else {
 | 
			
		||||
				err = ip6_route_check_nh(net, cfg, &dev, &idev);
 | 
			
		||||
			}
 | 
			
		||||
			if (err)
 | 
			
		||||
				goto out;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -2774,6 +2819,7 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg,
 | 
			
		|||
	if (!(rt->rt6i_flags & (RTF_LOCAL | RTF_ANYCAST)) &&
 | 
			
		||||
	    !netif_carrier_ok(dev))
 | 
			
		||||
		rt->rt6i_nh_flags |= RTNH_F_LINKDOWN;
 | 
			
		||||
	rt->rt6i_nh_flags |= (cfg->fc_flags & RTNH_F_ONLINK);
 | 
			
		||||
	rt->dst.dev = dev;
 | 
			
		||||
	rt->rt6i_idev = idev;
 | 
			
		||||
	rt->rt6i_table = table;
 | 
			
		||||
| 
						 | 
				
			
			@ -3843,6 +3889,8 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
 | 
			
		|||
	if (rtm->rtm_flags & RTM_F_CLONED)
 | 
			
		||||
		cfg->fc_flags |= RTF_CACHE;
 | 
			
		||||
 | 
			
		||||
	cfg->fc_flags |= (rtm->rtm_flags & RTNH_F_ONLINK);
 | 
			
		||||
 | 
			
		||||
	cfg->fc_nlinfo.portid = NETLINK_CB(skb).portid;
 | 
			
		||||
	cfg->fc_nlinfo.nlh = nlh;
 | 
			
		||||
	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,
 | 
			
		|||
			goto nla_put_failure;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*flags |= (rt->rt6i_nh_flags & RTNH_F_ONLINK);
 | 
			
		||||
	if (rt->rt6i_nh_flags & RTNH_F_OFFLOAD)
 | 
			
		||||
		*flags |= RTNH_F_OFFLOAD;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue