diff options
author | David Ahern <dsahern@gmail.com> | 2018-01-25 19:55:07 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-01-26 10:16:42 -0500 |
commit | 1edce99fa8d6119d89b3b6e92b6cfa56889b4f3d (patch) | |
tree | 30b5af7a5b811f56fde3642c4711539cf48be364 | |
parent | 9515a2e082f91457db0ecff4b65371d0fb5d9aad (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.c | 85 |
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 | ||
2472 | static 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 | |||
2516 | out: | ||
2517 | return err; | ||
2518 | } | ||
2519 | |||
2472 | static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg, | 2520 | static 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 | } |