Re: [PATCH v4 net-next 1/6] net/ipv6: Refactor gateway validation on route add

2018-03-14 Thread Ido Schimmel
On Tue, Mar 13, 2018 at 08:29:36AM -0700, David Ahern wrote:
> 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 

Reviewed-by: Ido Schimmel 


[PATCH v4 net-next 1/6] net/ipv6: Refactor gateway validation on route add

2018-03-13 Thread David Ahern
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 
---
 net/ipv6/route.c | 120 ++-
 1 file changed, 66 insertions(+), 54 deletions(-)

diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 81711e3e2604..23ced851fdb1 100644
--- a/net/ipv6/route.c
+++ b/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 @@ static int ip6_route_check_nh(struct net *net,
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 = >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 = >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, , , 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
-