@@ -920,6 +920,75 @@ static struct net_device *ip6_rt_get_dev_rcu(struct rt6_info *rt)
920
920
return dev ;
921
921
}
922
922
923
+ static 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
+
938
+ static int ip6_rt_type_to_error (u8 fib6_type )
939
+ {
940
+ return fib6_prop [fib6_type ];
941
+ }
942
+
943
+ static 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
+
965
+ static 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
+
923
992
static void rt6_set_from (struct rt6_info * rt , struct rt6_info * from )
924
993
{
925
994
BUG_ON (from -> from );
@@ -932,14 +1001,12 @@ static void rt6_set_from(struct rt6_info *rt, struct rt6_info *from)
932
1001
933
1002
static void ip6_rt_copy_init (struct rt6_info * rt , struct rt6_info * ort )
934
1003
{
935
- rt -> dst . input = ort -> dst . input ;
936
- rt -> dst . output = ort -> dst . output ;
1004
+ ip6_rt_init_dst ( rt , ort ) ;
1005
+
937
1006
rt -> rt6i_dst = ort -> rt6i_dst ;
938
- rt -> dst .error = ort -> dst .error ;
939
1007
rt -> rt6i_idev = ort -> rt6i_idev ;
940
1008
if (rt -> rt6i_idev )
941
1009
in6_dev_hold (rt -> rt6i_idev );
942
- rt -> dst .lastuse = jiffies ;
943
1010
rt -> rt6i_gateway = ort -> fib6_nh .nh_gw ;
944
1011
rt -> rt6i_flags = ort -> rt6i_flags ;
945
1012
rt6_set_from (rt , ort );
@@ -2329,7 +2396,7 @@ static struct rt6_info *__ip6_route_redirect(struct net *net,
2329
2396
continue ;
2330
2397
if (rt6_check_expired (rt ))
2331
2398
continue ;
2332
- if (rt -> dst . error )
2399
+ if (rt -> rt6i_flags & RTF_REJECT )
2333
2400
break ;
2334
2401
if (!(rt -> rt6i_flags & RTF_GATEWAY ))
2335
2402
continue ;
@@ -2357,7 +2424,7 @@ static struct rt6_info *__ip6_route_redirect(struct net *net,
2357
2424
2358
2425
if (!rt )
2359
2426
rt = net -> ipv6 .ip6_null_entry ;
2360
- else if (rt -> dst . error ) {
2427
+ else if (rt -> rt6i_flags & RTF_REJECT ) {
2361
2428
rt = net -> ipv6 .ip6_null_entry ;
2362
2429
goto out ;
2363
2430
}
@@ -2900,15 +2967,6 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg,
2900
2967
2901
2968
addr_type = ipv6_addr_type (& cfg -> fc_dst );
2902
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
2970
if (cfg -> fc_encap ) {
2913
2971
struct lwtunnel_state * lwtstate ;
2914
2972
@@ -2918,7 +2976,6 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg,
2918
2976
if (err )
2919
2977
goto out ;
2920
2978
rt -> fib6_nh .nh_lwtstate = lwtstate_get (lwtstate );
2921
- lwtunnel_set_redirect (& rt -> dst );
2922
2979
}
2923
2980
2924
2981
ipv6_addr_prefix (& rt -> rt6i_dst .addr , & cfg -> fc_dst , cfg -> fc_dst_len );
@@ -2958,27 +3015,6 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg,
2958
3015
}
2959
3016
}
2960
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
3018
goto install_route ;
2983
3019
}
2984
3020
@@ -3623,12 +3659,9 @@ struct rt6_info *addrconf_dst_alloc(struct net *net,
3623
3659
return ERR_PTR (- ENOMEM );
3624
3660
3625
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
3662
rt -> rt6i_idev = idev ;
3631
3663
3664
+ rt -> dst .flags |= DST_HOST ;
3632
3665
rt -> rt6i_protocol = RTPROT_KERNEL ;
3633
3666
rt -> rt6i_flags = RTF_UP | RTF_NONEXTHOP ;
3634
3667
if (anycast ) {
0 commit comments