Skip to content

Commit 9fbb704

Browse files
dsaherndavem330
authored andcommitted
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>
1 parent 1ad2ff0 commit 9fbb704

File tree

1 file changed

+66
-54
lines changed

1 file changed

+66
-54
lines changed

net/ipv6/route.c

Lines changed: 66 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2550,7 +2550,7 @@ static struct rt6_info *ip6_nh_lookup_table(struct net *net,
25502550

25512551
static int ip6_route_check_nh_onlink(struct net *net,
25522552
struct fib6_config *cfg,
2553-
struct net_device *dev,
2553+
const struct net_device *dev,
25542554
struct netlink_ext_ack *extack)
25552555
{
25562556
u32 tbid = l3mdev_fib_table(dev) ? : RT_TABLE_MAIN;
@@ -2626,6 +2626,68 @@ static int ip6_route_check_nh(struct net *net,
26262626
return err;
26272627
}
26282628

2629+
static int ip6_validate_gw(struct net *net, struct fib6_config *cfg,
2630+
struct net_device **_dev, struct inet6_dev **idev,
2631+
struct netlink_ext_ack *extack)
2632+
{
2633+
const struct in6_addr *gw_addr = &cfg->fc_gateway;
2634+
int gwa_type = ipv6_addr_type(gw_addr);
2635+
const struct net_device *dev = *_dev;
2636+
int err = -EINVAL;
2637+
2638+
/* if gw_addr is local we will fail to detect this in case
2639+
* address is still TENTATIVE (DAD in progress). rt6_lookup()
2640+
* will return already-added prefix route via interface that
2641+
* prefix route was assigned to, which might be non-loopback.
2642+
*/
2643+
if (ipv6_chk_addr_and_flags(net, gw_addr,
2644+
gwa_type & IPV6_ADDR_LINKLOCAL ?
2645+
dev : NULL, 0, 0)) {
2646+
NL_SET_ERR_MSG(extack, "Invalid gateway address");
2647+
goto out;
2648+
}
2649+
2650+
if (gwa_type != (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_UNICAST)) {
2651+
/* IPv6 strictly inhibits using not link-local
2652+
* addresses as nexthop address.
2653+
* Otherwise, router will not able to send redirects.
2654+
* It is very good, but in some (rare!) circumstances
2655+
* (SIT, PtP, NBMA NOARP links) it is handy to allow
2656+
* some exceptions. --ANK
2657+
* We allow IPv4-mapped nexthops to support RFC4798-type
2658+
* addressing
2659+
*/
2660+
if (!(gwa_type & (IPV6_ADDR_UNICAST | IPV6_ADDR_MAPPED))) {
2661+
NL_SET_ERR_MSG(extack, "Invalid gateway address");
2662+
goto out;
2663+
}
2664+
2665+
if (cfg->fc_flags & RTNH_F_ONLINK)
2666+
err = ip6_route_check_nh_onlink(net, cfg, dev, extack);
2667+
else
2668+
err = ip6_route_check_nh(net, cfg, _dev, idev);
2669+
2670+
if (err)
2671+
goto out;
2672+
}
2673+
2674+
/* reload in case device was changed */
2675+
dev = *_dev;
2676+
2677+
err = -EINVAL;
2678+
if (!dev) {
2679+
NL_SET_ERR_MSG(extack, "Egress device not specified");
2680+
goto out;
2681+
} else if (dev->flags & IFF_LOOPBACK) {
2682+
NL_SET_ERR_MSG(extack,
2683+
"Egress device can not be loopback device for this route");
2684+
goto out;
2685+
}
2686+
err = 0;
2687+
out:
2688+
return err;
2689+
}
2690+
26292691
static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg,
26302692
struct netlink_ext_ack *extack)
26312693
{
@@ -2808,61 +2870,11 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg,
28082870
}
28092871

28102872
if (cfg->fc_flags & RTF_GATEWAY) {
2811-
const struct in6_addr *gw_addr;
2812-
int gwa_type;
2813-
2814-
gw_addr = &cfg->fc_gateway;
2815-
gwa_type = ipv6_addr_type(gw_addr);
2816-
2817-
/* if gw_addr is local we will fail to detect this in case
2818-
* address is still TENTATIVE (DAD in progress). rt6_lookup()
2819-
* will return already-added prefix route via interface that
2820-
* prefix route was assigned to, which might be non-loopback.
2821-
*/
2822-
err = -EINVAL;
2823-
if (ipv6_chk_addr_and_flags(net, gw_addr,
2824-
gwa_type & IPV6_ADDR_LINKLOCAL ?
2825-
dev : NULL, 0, 0)) {
2826-
NL_SET_ERR_MSG(extack, "Invalid gateway address");
2873+
err = ip6_validate_gw(net, cfg, &dev, &idev, extack);
2874+
if (err)
28272875
goto out;
2828-
}
2829-
rt->rt6i_gateway = *gw_addr;
2830-
2831-
if (gwa_type != (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_UNICAST)) {
2832-
/* IPv6 strictly inhibits using not link-local
2833-
addresses as nexthop address.
2834-
Otherwise, router will not able to send redirects.
2835-
It is very good, but in some (rare!) circumstances
2836-
(SIT, PtP, NBMA NOARP links) it is handy to allow
2837-
some exceptions. --ANK
2838-
We allow IPv4-mapped nexthops to support RFC4798-type
2839-
addressing
2840-
*/
2841-
if (!(gwa_type & (IPV6_ADDR_UNICAST |
2842-
IPV6_ADDR_MAPPED))) {
2843-
NL_SET_ERR_MSG(extack,
2844-
"Invalid gateway address");
2845-
goto out;
2846-
}
28472876

2848-
if (cfg->fc_flags & RTNH_F_ONLINK) {
2849-
err = ip6_route_check_nh_onlink(net, cfg, dev,
2850-
extack);
2851-
} else {
2852-
err = ip6_route_check_nh(net, cfg, &dev, &idev);
2853-
}
2854-
if (err)
2855-
goto out;
2856-
}
2857-
err = -EINVAL;
2858-
if (!dev) {
2859-
NL_SET_ERR_MSG(extack, "Egress device not specified");
2860-
goto out;
2861-
} else if (dev->flags & IFF_LOOPBACK) {
2862-
NL_SET_ERR_MSG(extack,
2863-
"Egress device can not be loopback device for this route");
2864-
goto out;
2865-
}
2877+
rt->rt6i_gateway = cfg->fc_gateway;
28662878
}
28672879

28682880
err = -ENODEV;

0 commit comments

Comments
 (0)