net/ipv6: Refactor gateway validation on route add
Move gateway validation code from ip6_route_info_create into ip6_validate_gw. Code move plus adjustments to handle the potential reset of dev and idev and to make checkpatch happy. Signed-off-by: David Ahern <dsahern@gmail.com> Reviewed-by: Ido Schimmel <idosch@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
1ad2ff028f
commit
9fbb704c33
120
net/ipv6/route.c
120
net/ipv6/route.c
@ -2550,7 +2550,7 @@ static struct rt6_info *ip6_nh_lookup_table(struct net *net,
|
||||
|
||||
static int ip6_route_check_nh_onlink(struct net *net,
|
||||
struct fib6_config *cfg,
|
||||
struct net_device *dev,
|
||||
const struct net_device *dev,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
u32 tbid = l3mdev_fib_table(dev) ? : RT_TABLE_MAIN;
|
||||
@ -2626,6 +2626,68 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ip6_validate_gw(struct net *net, struct fib6_config *cfg,
|
||||
struct net_device **_dev, struct inet6_dev **idev,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
const struct in6_addr *gw_addr = &cfg->fc_gateway;
|
||||
int gwa_type = ipv6_addr_type(gw_addr);
|
||||
const struct net_device *dev = *_dev;
|
||||
int err = -EINVAL;
|
||||
|
||||
/* if gw_addr is local we will fail to detect this in case
|
||||
* address is still TENTATIVE (DAD in progress). rt6_lookup()
|
||||
* will return already-added prefix route via interface that
|
||||
* prefix route was assigned to, which might be non-loopback.
|
||||
*/
|
||||
if (ipv6_chk_addr_and_flags(net, gw_addr,
|
||||
gwa_type & IPV6_ADDR_LINKLOCAL ?
|
||||
dev : NULL, 0, 0)) {
|
||||
NL_SET_ERR_MSG(extack, "Invalid gateway address");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (gwa_type != (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_UNICAST)) {
|
||||
/* IPv6 strictly inhibits using not link-local
|
||||
* addresses as nexthop address.
|
||||
* Otherwise, router will not able to send redirects.
|
||||
* It is very good, but in some (rare!) circumstances
|
||||
* (SIT, PtP, NBMA NOARP links) it is handy to allow
|
||||
* some exceptions. --ANK
|
||||
* We allow IPv4-mapped nexthops to support RFC4798-type
|
||||
* addressing
|
||||
*/
|
||||
if (!(gwa_type & (IPV6_ADDR_UNICAST | IPV6_ADDR_MAPPED))) {
|
||||
NL_SET_ERR_MSG(extack, "Invalid gateway address");
|
||||
goto out;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* reload in case device was changed */
|
||||
dev = *_dev;
|
||||
|
||||
err = -EINVAL;
|
||||
if (!dev) {
|
||||
NL_SET_ERR_MSG(extack, "Egress device not specified");
|
||||
goto out;
|
||||
} else if (dev->flags & IFF_LOOPBACK) {
|
||||
NL_SET_ERR_MSG(extack,
|
||||
"Egress device can not be loopback device for this route");
|
||||
goto out;
|
||||
}
|
||||
err = 0;
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
@ -2808,61 +2870,11 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg,
|
||||
}
|
||||
|
||||
if (cfg->fc_flags & RTF_GATEWAY) {
|
||||
const struct in6_addr *gw_addr;
|
||||
int gwa_type;
|
||||
|
||||
gw_addr = &cfg->fc_gateway;
|
||||
gwa_type = ipv6_addr_type(gw_addr);
|
||||
|
||||
/* if gw_addr is local we will fail to detect this in case
|
||||
* address is still TENTATIVE (DAD in progress). rt6_lookup()
|
||||
* will return already-added prefix route via interface that
|
||||
* prefix route was assigned to, which might be non-loopback.
|
||||
*/
|
||||
err = -EINVAL;
|
||||
if (ipv6_chk_addr_and_flags(net, gw_addr,
|
||||
gwa_type & IPV6_ADDR_LINKLOCAL ?
|
||||
dev : NULL, 0, 0)) {
|
||||
NL_SET_ERR_MSG(extack, "Invalid gateway address");
|
||||
err = ip6_validate_gw(net, cfg, &dev, &idev, extack);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
rt->rt6i_gateway = *gw_addr;
|
||||
|
||||
if (gwa_type != (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_UNICAST)) {
|
||||
/* IPv6 strictly inhibits using not link-local
|
||||
addresses as nexthop address.
|
||||
Otherwise, router will not able to send redirects.
|
||||
It is very good, but in some (rare!) circumstances
|
||||
(SIT, PtP, NBMA NOARP links) it is handy to allow
|
||||
some exceptions. --ANK
|
||||
We allow IPv4-mapped nexthops to support RFC4798-type
|
||||
addressing
|
||||
*/
|
||||
if (!(gwa_type & (IPV6_ADDR_UNICAST |
|
||||
IPV6_ADDR_MAPPED))) {
|
||||
NL_SET_ERR_MSG(extack,
|
||||
"Invalid gateway address");
|
||||
goto out;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
err = -EINVAL;
|
||||
if (!dev) {
|
||||
NL_SET_ERR_MSG(extack, "Egress device not specified");
|
||||
goto out;
|
||||
} else if (dev->flags & IFF_LOOPBACK) {
|
||||
NL_SET_ERR_MSG(extack,
|
||||
"Egress device can not be loopback device for this route");
|
||||
goto out;
|
||||
}
|
||||
rt->rt6i_gateway = cfg->fc_gateway;
|
||||
}
|
||||
|
||||
err = -ENODEV;
|
||||
|
Loading…
Reference in New Issue
Block a user