route.c (5e670d844b2a4e47d1b9b9aceb14dd3c12a6d4bf) route.c (6edb3c96a5f028e0cee5fe80ad09b866eb2f6179)
1/*
2 * Linux INET6 implementation
3 * FIB front-end.
4 *
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
7 *
8 * This program is free software; you can redistribute it and/or

--- 906 unchanged lines hidden (view full) ---

915 /* last case is netif_is_l3_master(dev) is true in which
916 * case we want dev returned to be dev
917 */
918 }
919
920 return dev;
921}
922
1/*
2 * Linux INET6 implementation
3 * FIB front-end.
4 *
5 * Authors:
6 * Pedro Roque <roque@di.fc.ul.pt>
7 *
8 * This program is free software; you can redistribute it and/or

--- 906 unchanged lines hidden (view full) ---

915 /* last case is netif_is_l3_master(dev) is true in which
916 * case we want dev returned to be dev
917 */
918 }
919
920 return dev;
921}
922
923static const int fib6_prop[RTN_MAX + 1] = {
924 [RTN_UNSPEC] = 0,
925 [RTN_UNICAST] = 0,
926 [RTN_LOCAL] = 0,
927 [RTN_BROADCAST] = 0,
928 [RTN_ANYCAST] = 0,
929 [RTN_MULTICAST] = 0,
930 [RTN_BLACKHOLE] = -EINVAL,
931 [RTN_UNREACHABLE] = -EHOSTUNREACH,
932 [RTN_PROHIBIT] = -EACCES,
933 [RTN_THROW] = -EAGAIN,
934 [RTN_NAT] = -EINVAL,
935 [RTN_XRESOLVE] = -EINVAL,
936};
937
938static int ip6_rt_type_to_error(u8 fib6_type)
939{
940 return fib6_prop[fib6_type];
941}
942
943static void ip6_rt_init_dst_reject(struct rt6_info *rt, struct rt6_info *ort)
944{
945 rt->dst.error = ip6_rt_type_to_error(ort->fib6_type);
946
947 switch (ort->fib6_type) {
948 case RTN_BLACKHOLE:
949 rt->dst.output = dst_discard_out;
950 rt->dst.input = dst_discard;
951 break;
952 case RTN_PROHIBIT:
953 rt->dst.output = ip6_pkt_prohibit_out;
954 rt->dst.input = ip6_pkt_prohibit;
955 break;
956 case RTN_THROW:
957 case RTN_UNREACHABLE:
958 default:
959 rt->dst.output = ip6_pkt_discard_out;
960 rt->dst.input = ip6_pkt_discard;
961 break;
962 }
963}
964
965static void ip6_rt_init_dst(struct rt6_info *rt, struct rt6_info *ort)
966{
967 if (ort->rt6i_flags & RTF_REJECT) {
968 ip6_rt_init_dst_reject(rt, ort);
969 return;
970 }
971
972 rt->dst.error = 0;
973 rt->dst.output = ip6_output;
974
975 if (ort->fib6_type == RTN_LOCAL) {
976 rt->dst.flags |= DST_HOST;
977 rt->dst.input = ip6_input;
978 } else if (ipv6_addr_type(&ort->rt6i_dst.addr) & IPV6_ADDR_MULTICAST) {
979 rt->dst.input = ip6_mc_input;
980 } else {
981 rt->dst.input = ip6_forward;
982 }
983
984 if (ort->fib6_nh.nh_lwtstate) {
985 rt->dst.lwtstate = lwtstate_get(ort->fib6_nh.nh_lwtstate);
986 lwtunnel_set_redirect(&rt->dst);
987 }
988
989 rt->dst.lastuse = jiffies;
990}
991
923static void rt6_set_from(struct rt6_info *rt, struct rt6_info *from)
924{
925 BUG_ON(from->from);
926
927 rt->rt6i_flags &= ~RTF_EXPIRES;
928 dst_hold(&from->dst);
929 rt->from = from;
930 dst_init_metrics(&rt->dst, dst_metrics_ptr(&from->dst), true);
931}
932
933static void ip6_rt_copy_init(struct rt6_info *rt, struct rt6_info *ort)
934{
992static void rt6_set_from(struct rt6_info *rt, struct rt6_info *from)
993{
994 BUG_ON(from->from);
995
996 rt->rt6i_flags &= ~RTF_EXPIRES;
997 dst_hold(&from->dst);
998 rt->from = from;
999 dst_init_metrics(&rt->dst, dst_metrics_ptr(&from->dst), true);
1000}
1001
1002static void ip6_rt_copy_init(struct rt6_info *rt, struct rt6_info *ort)
1003{
935 rt->dst.input = ort->dst.input;
936 rt->dst.output = ort->dst.output;
1004 ip6_rt_init_dst(rt, ort);
1005
937 rt->rt6i_dst = ort->rt6i_dst;
1006 rt->rt6i_dst = ort->rt6i_dst;
938 rt->dst.error = ort->dst.error;
939 rt->rt6i_idev = ort->rt6i_idev;
940 if (rt->rt6i_idev)
941 in6_dev_hold(rt->rt6i_idev);
1007 rt->rt6i_idev = ort->rt6i_idev;
1008 if (rt->rt6i_idev)
1009 in6_dev_hold(rt->rt6i_idev);
942 rt->dst.lastuse = jiffies;
943 rt->rt6i_gateway = ort->fib6_nh.nh_gw;
944 rt->rt6i_flags = ort->rt6i_flags;
945 rt6_set_from(rt, ort);
946 rt->rt6i_metric = ort->rt6i_metric;
947#ifdef CONFIG_IPV6_SUBTREES
948 rt->rt6i_src = ort->rt6i_src;
949#endif
950 rt->rt6i_prefsrc = ort->rt6i_prefsrc;

--- 1373 unchanged lines hidden (view full) ---

2324 rcu_read_lock();
2325 fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
2326restart:
2327 for_each_fib6_node_rt_rcu(fn) {
2328 if (rt->fib6_nh.nh_flags & RTNH_F_DEAD)
2329 continue;
2330 if (rt6_check_expired(rt))
2331 continue;
1010 rt->rt6i_gateway = ort->fib6_nh.nh_gw;
1011 rt->rt6i_flags = ort->rt6i_flags;
1012 rt6_set_from(rt, ort);
1013 rt->rt6i_metric = ort->rt6i_metric;
1014#ifdef CONFIG_IPV6_SUBTREES
1015 rt->rt6i_src = ort->rt6i_src;
1016#endif
1017 rt->rt6i_prefsrc = ort->rt6i_prefsrc;

--- 1373 unchanged lines hidden (view full) ---

2391 rcu_read_lock();
2392 fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
2393restart:
2394 for_each_fib6_node_rt_rcu(fn) {
2395 if (rt->fib6_nh.nh_flags & RTNH_F_DEAD)
2396 continue;
2397 if (rt6_check_expired(rt))
2398 continue;
2332 if (rt->dst.error)
2399 if (rt->rt6i_flags & RTF_REJECT)
2333 break;
2334 if (!(rt->rt6i_flags & RTF_GATEWAY))
2335 continue;
2336 if (fl6->flowi6_oif != rt->fib6_nh.nh_dev->ifindex)
2337 continue;
2338 /* rt_cache's gateway might be different from its 'parent'
2339 * in the case of an ip redirect.
2340 * So we keep searching in the exception table if the gateway

--- 11 unchanged lines hidden (view full) ---

2352 }
2353 continue;
2354 }
2355 break;
2356 }
2357
2358 if (!rt)
2359 rt = net->ipv6.ip6_null_entry;
2400 break;
2401 if (!(rt->rt6i_flags & RTF_GATEWAY))
2402 continue;
2403 if (fl6->flowi6_oif != rt->fib6_nh.nh_dev->ifindex)
2404 continue;
2405 /* rt_cache's gateway might be different from its 'parent'
2406 * in the case of an ip redirect.
2407 * So we keep searching in the exception table if the gateway

--- 11 unchanged lines hidden (view full) ---

2419 }
2420 continue;
2421 }
2422 break;
2423 }
2424
2425 if (!rt)
2426 rt = net->ipv6.ip6_null_entry;
2360 else if (rt->dst.error) {
2427 else if (rt->rt6i_flags & RTF_REJECT) {
2361 rt = net->ipv6.ip6_null_entry;
2362 goto out;
2363 }
2364
2365 if (rt == net->ipv6.ip6_null_entry) {
2366 fn = fib6_backtrack(fn, &fl6->saddr);
2367 if (fn)
2368 goto restart;

--- 526 unchanged lines hidden (view full) ---

2895 rt6_clean_expires(rt);
2896
2897 if (cfg->fc_protocol == RTPROT_UNSPEC)
2898 cfg->fc_protocol = RTPROT_BOOT;
2899 rt->rt6i_protocol = cfg->fc_protocol;
2900
2901 addr_type = ipv6_addr_type(&cfg->fc_dst);
2902
2428 rt = net->ipv6.ip6_null_entry;
2429 goto out;
2430 }
2431
2432 if (rt == net->ipv6.ip6_null_entry) {
2433 fn = fib6_backtrack(fn, &fl6->saddr);
2434 if (fn)
2435 goto restart;

--- 526 unchanged lines hidden (view full) ---

2962 rt6_clean_expires(rt);
2963
2964 if (cfg->fc_protocol == RTPROT_UNSPEC)
2965 cfg->fc_protocol = RTPROT_BOOT;
2966 rt->rt6i_protocol = cfg->fc_protocol;
2967
2968 addr_type = ipv6_addr_type(&cfg->fc_dst);
2969
2903 if (addr_type & IPV6_ADDR_MULTICAST)
2904 rt->dst.input = ip6_mc_input;
2905 else if (cfg->fc_flags & RTF_LOCAL)
2906 rt->dst.input = ip6_input;
2907 else
2908 rt->dst.input = ip6_forward;
2909
2910 rt->dst.output = ip6_output;
2911
2912 if (cfg->fc_encap) {
2913 struct lwtunnel_state *lwtstate;
2914
2915 err = lwtunnel_build_state(cfg->fc_encap_type,
2916 cfg->fc_encap, AF_INET6, cfg,
2917 &lwtstate, extack);
2918 if (err)
2919 goto out;
2920 rt->fib6_nh.nh_lwtstate = lwtstate_get(lwtstate);
2970 if (cfg->fc_encap) {
2971 struct lwtunnel_state *lwtstate;
2972
2973 err = lwtunnel_build_state(cfg->fc_encap_type,
2974 cfg->fc_encap, AF_INET6, cfg,
2975 &lwtstate, extack);
2976 if (err)
2977 goto out;
2978 rt->fib6_nh.nh_lwtstate = lwtstate_get(lwtstate);
2921 lwtunnel_set_redirect(&rt->dst);
2922 }
2923
2924 ipv6_addr_prefix(&rt->rt6i_dst.addr, &cfg->fc_dst, cfg->fc_dst_len);
2925 rt->rt6i_dst.plen = cfg->fc_dst_len;
2926 if (rt->rt6i_dst.plen == 128)
2927 rt->dst.flags |= DST_HOST;
2928
2929#ifdef CONFIG_IPV6_SUBTREES

--- 23 unchanged lines hidden (view full) ---

2953 dev_hold(dev);
2954 idev = in6_dev_get(dev);
2955 if (!idev) {
2956 err = -ENODEV;
2957 goto out;
2958 }
2959 }
2960 rt->rt6i_flags = RTF_REJECT|RTF_NONEXTHOP;
2979 }
2980
2981 ipv6_addr_prefix(&rt->rt6i_dst.addr, &cfg->fc_dst, cfg->fc_dst_len);
2982 rt->rt6i_dst.plen = cfg->fc_dst_len;
2983 if (rt->rt6i_dst.plen == 128)
2984 rt->dst.flags |= DST_HOST;
2985
2986#ifdef CONFIG_IPV6_SUBTREES

--- 23 unchanged lines hidden (view full) ---

3010 dev_hold(dev);
3011 idev = in6_dev_get(dev);
3012 if (!idev) {
3013 err = -ENODEV;
3014 goto out;
3015 }
3016 }
3017 rt->rt6i_flags = RTF_REJECT|RTF_NONEXTHOP;
2961 switch (cfg->fc_type) {
2962 case RTN_BLACKHOLE:
2963 rt->dst.error = -EINVAL;
2964 rt->dst.output = dst_discard_out;
2965 rt->dst.input = dst_discard;
2966 break;
2967 case RTN_PROHIBIT:
2968 rt->dst.error = -EACCES;
2969 rt->dst.output = ip6_pkt_prohibit_out;
2970 rt->dst.input = ip6_pkt_prohibit;
2971 break;
2972 case RTN_THROW:
2973 case RTN_UNREACHABLE:
2974 default:
2975 rt->dst.error = (cfg->fc_type == RTN_THROW) ? -EAGAIN
2976 : (cfg->fc_type == RTN_UNREACHABLE)
2977 ? -EHOSTUNREACH : -ENETUNREACH;
2978 rt->dst.output = ip6_pkt_discard_out;
2979 rt->dst.input = ip6_pkt_discard;
2980 break;
2981 }
2982 goto install_route;
2983 }
2984
2985 if (cfg->fc_flags & RTF_GATEWAY) {
2986 err = ip6_validate_gw(net, cfg, &dev, &idev, extack);
2987 if (err)
2988 goto out;
2989

--- 628 unchanged lines hidden (view full) ---

3618 struct net_device *dev = idev->dev;
3619 struct rt6_info *rt;
3620
3621 rt = ip6_dst_alloc(net, dev, DST_NOCOUNT);
3622 if (!rt)
3623 return ERR_PTR(-ENOMEM);
3624
3625 in6_dev_hold(idev);
3018 goto install_route;
3019 }
3020
3021 if (cfg->fc_flags & RTF_GATEWAY) {
3022 err = ip6_validate_gw(net, cfg, &dev, &idev, extack);
3023 if (err)
3024 goto out;
3025

--- 628 unchanged lines hidden (view full) ---

3654 struct net_device *dev = idev->dev;
3655 struct rt6_info *rt;
3656
3657 rt = ip6_dst_alloc(net, dev, DST_NOCOUNT);
3658 if (!rt)
3659 return ERR_PTR(-ENOMEM);
3660
3661 in6_dev_hold(idev);
3626
3627 rt->dst.flags |= DST_HOST;
3628 rt->dst.input = ip6_input;
3629 rt->dst.output = ip6_output;
3630 rt->rt6i_idev = idev;
3631
3662 rt->rt6i_idev = idev;
3663
3664 rt->dst.flags |= DST_HOST;
3632 rt->rt6i_protocol = RTPROT_KERNEL;
3633 rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP;
3634 if (anycast) {
3635 rt->fib6_type = RTN_ANYCAST;
3636 rt->rt6i_flags |= RTF_ANYCAST;
3637 } else {
3638 rt->fib6_type = RTN_LOCAL;
3639 rt->rt6i_flags |= RTF_LOCAL;

--- 1641 unchanged lines hidden ---
3665 rt->rt6i_protocol = RTPROT_KERNEL;
3666 rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP;
3667 if (anycast) {
3668 rt->fib6_type = RTN_ANYCAST;
3669 rt->rt6i_flags |= RTF_ANYCAST;
3670 } else {
3671 rt->fib6_type = RTN_LOCAL;
3672 rt->rt6i_flags |= RTF_LOCAL;

--- 1641 unchanged lines hidden ---