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 --- |