aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Ahern <dsahern@gmail.com>2018-01-25 19:55:07 -0500
committerDavid S. Miller <davem@davemloft.net>2018-01-26 10:16:42 -0500
commit1edce99fa8d6119d89b3b6e92b6cfa56889b4f3d (patch)
tree30b5af7a5b811f56fde3642c4711539cf48be364
parent9515a2e082f91457db0ecff4b65371d0fb5d9aad (diff)
net/ipv6: Move gateway validation into helper
Move existing code to validate nexthop into a helper. Follow on patch adds support for nexthops marked with onlink, and this helper keeps the complexity of ip6_route_info_create in check. Signed-off-by: David Ahern <dsahern@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ipv6/route.c85
1 files changed, 49 insertions, 36 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index aa4411c81e7e..bfd1a06a0700 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2469,6 +2469,54 @@ static struct rt6_info *ip6_nh_lookup_table(struct net *net,
2469 return rt; 2469 return rt;
2470} 2470}
2471 2471
2472static int ip6_route_check_nh(struct net *net,
2473 struct fib6_config *cfg,
2474 struct net_device **_dev,
2475 struct inet6_dev **idev)
2476{
2477 const struct in6_addr *gw_addr = &cfg->fc_gateway;
2478 struct net_device *dev = _dev ? *_dev : NULL;
2479 struct rt6_info *grt = NULL;
2480 int err = -EHOSTUNREACH;
2481
2482 if (cfg->fc_table) {
2483 grt = ip6_nh_lookup_table(net, cfg, gw_addr);
2484 if (grt) {
2485 if (grt->rt6i_flags & RTF_GATEWAY ||
2486 (dev && dev != grt->dst.dev)) {
2487 ip6_rt_put(grt);
2488 grt = NULL;
2489 }
2490 }
2491 }
2492
2493 if (!grt)
2494 grt = rt6_lookup(net, gw_addr, NULL, cfg->fc_ifindex, 1);
2495
2496 if (!grt)
2497 goto out;
2498
2499 if (dev) {
2500 if (dev != grt->dst.dev) {
2501 ip6_rt_put(grt);
2502 goto out;
2503 }
2504 } else {
2505 *_dev = dev = grt->dst.dev;
2506 *idev = grt->rt6i_idev;
2507 dev_hold(dev);
2508 in6_dev_hold(grt->rt6i_idev);
2509 }
2510
2511 if (!(grt->rt6i_flags & RTF_GATEWAY))
2512 err = 0;
2513
2514 ip6_rt_put(grt);
2515
2516out:
2517 return err;
2518}
2519
2472static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg, 2520static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg,
2473 struct netlink_ext_ack *extack) 2521 struct netlink_ext_ack *extack)
2474{ 2522{
@@ -2664,8 +2712,6 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg,
2664 rt->rt6i_gateway = *gw_addr; 2712 rt->rt6i_gateway = *gw_addr;
2665 2713
2666 if (gwa_type != (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_UNICAST)) { 2714 if (gwa_type != (IPV6_ADDR_LINKLOCAL|IPV6_ADDR_UNICAST)) {
2667 struct rt6_info *grt = NULL;
2668
2669 /* IPv6 strictly inhibits using not link-local 2715 /* IPv6 strictly inhibits using not link-local
2670 addresses as nexthop address. 2716 addresses as nexthop address.
2671 Otherwise, router will not able to send redirects. 2717 Otherwise, router will not able to send redirects.
@@ -2682,40 +2728,7 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg,
2682 goto out; 2728 goto out;
2683 } 2729 }
2684 2730
2685 if (cfg->fc_table) { 2731 err = ip6_route_check_nh(net, cfg, &dev, &idev);
2686 grt = ip6_nh_lookup_table(net, cfg, gw_addr);
2687
2688 if (grt) {
2689 if (grt->rt6i_flags & RTF_GATEWAY ||
2690 (dev && dev != grt->dst.dev)) {
2691 ip6_rt_put(grt);
2692 grt = NULL;
2693 }
2694 }
2695 }
2696
2697 if (!grt)
2698 grt = rt6_lookup(net, gw_addr, NULL,
2699 cfg->fc_ifindex, 1);
2700
2701 err = -EHOSTUNREACH;
2702 if (!grt)
2703 goto out;
2704 if (dev) {
2705 if (dev != grt->dst.dev) {
2706 ip6_rt_put(grt);
2707 goto out;
2708 }
2709 } else {
2710 dev = grt->dst.dev;
2711 idev = grt->rt6i_idev;
2712 dev_hold(dev);
2713 in6_dev_hold(grt->rt6i_idev);
2714 }
2715 if (!(grt->rt6i_flags & RTF_GATEWAY))
2716 err = 0;
2717 ip6_rt_put(grt);
2718
2719 if (err) 2732 if (err)
2720 goto out; 2733 goto out;
2721 } 2734 }