@@ -276,6 +276,15 @@ static const u32 ip6_template_metrics[RTAX_MAX] = {
276276 [RTAX_HOPLIMIT - 1 ] = 0 ,
277277};
278278
279+ static const struct rt6_info fib6_null_entry_template = {
280+ .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP ),
281+ .rt6i_protocol = RTPROT_KERNEL ,
282+ .rt6i_metric = ~(u32 )0 ,
283+ .rt6i_ref = ATOMIC_INIT (1 ),
284+ .fib6_type = RTN_UNREACHABLE ,
285+ .fib6_metrics = (struct dst_metrics * )& dst_default_metrics ,
286+ };
287+
279288static const struct rt6_info ip6_null_entry_template = {
280289 .dst = {
281290 .__refcnt = ATOMIC_INIT (1 ),
@@ -522,10 +531,10 @@ static inline struct rt6_info *rt6_device_match(struct net *net,
522531 return local ;
523532
524533 if (flags & RT6_LOOKUP_F_IFACE )
525- return net -> ipv6 .ip6_null_entry ;
534+ return net -> ipv6 .fib6_null_entry ;
526535 }
527536
528- return rt -> fib6_nh .nh_flags & RTNH_F_DEAD ? net -> ipv6 .ip6_null_entry : rt ;
537+ return rt -> fib6_nh .nh_flags & RTNH_F_DEAD ? net -> ipv6 .fib6_null_entry : rt ;
529538}
530539
531540#ifdef CONFIG_IPV6_ROUTER_PREF
@@ -758,8 +767,8 @@ static struct rt6_info *rt6_select(struct net *net, struct fib6_node *fn,
758767 bool do_rr = false;
759768 int key_plen ;
760769
761- if (!leaf || leaf == net -> ipv6 .ip6_null_entry )
762- return net -> ipv6 .ip6_null_entry ;
770+ if (!leaf || leaf == net -> ipv6 .fib6_null_entry )
771+ return net -> ipv6 .fib6_null_entry ;
763772
764773 rt0 = rcu_dereference (fn -> rr_ptr );
765774 if (!rt0 )
@@ -776,7 +785,7 @@ static struct rt6_info *rt6_select(struct net *net, struct fib6_node *fn,
776785 key_plen = rt0 -> rt6i_src .plen ;
777786#endif
778787 if (fn -> fn_bit != key_plen )
779- return net -> ipv6 .ip6_null_entry ;
788+ return net -> ipv6 .fib6_null_entry ;
780789
781790 match = find_rr_leaf (fn , leaf , rt0 , rt0 -> rt6i_metric , oif , strict ,
782791 & do_rr );
@@ -797,7 +806,7 @@ static struct rt6_info *rt6_select(struct net *net, struct fib6_node *fn,
797806 }
798807 }
799808
800- return match ? match : net -> ipv6 .ip6_null_entry ;
809+ return match ? match : net -> ipv6 .fib6_null_entry ;
801810}
802811
803812static bool rt6_is_gw_or_nonexthop (const struct rt6_info * rt )
@@ -1063,15 +1072,15 @@ static struct rt6_info *ip6_pol_route_lookup(struct net *net,
10631072restart :
10641073 rt = rcu_dereference (fn -> leaf );
10651074 if (!rt ) {
1066- rt = net -> ipv6 .ip6_null_entry ;
1075+ rt = net -> ipv6 .fib6_null_entry ;
10671076 } else {
10681077 rt = rt6_device_match (net , rt , & fl6 -> saddr ,
10691078 fl6 -> flowi6_oif , flags );
10701079 if (rt -> rt6i_nsiblings && fl6 -> flowi6_oif == 0 )
10711080 rt = rt6_multipath_select (net , rt , fl6 , fl6 -> flowi6_oif ,
10721081 skb , flags );
10731082 }
1074- if (rt == net -> ipv6 .ip6_null_entry ) {
1083+ if (rt == net -> ipv6 .fib6_null_entry ) {
10751084 fn = fib6_backtrack (fn , & fl6 -> saddr );
10761085 if (fn )
10771086 goto restart ;
@@ -1820,7 +1829,7 @@ struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
18201829 rt = rt6_select (net , fn , oif , strict );
18211830 if (rt -> rt6i_nsiblings )
18221831 rt = rt6_multipath_select (net , rt , fl6 , oif , skb , strict );
1823- if (rt == net -> ipv6 .ip6_null_entry ) {
1832+ if (rt == net -> ipv6 .fib6_null_entry ) {
18241833 fn = fib6_backtrack (fn , & fl6 -> saddr );
18251834 if (fn )
18261835 goto redo_rt6_select ;
@@ -1837,7 +1846,8 @@ struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
18371846 if (rt_cache )
18381847 rt = rt_cache ;
18391848
1840- if (rt == net -> ipv6 .ip6_null_entry ) {
1849+ if (rt == net -> ipv6 .fib6_null_entry ) {
1850+ rt = net -> ipv6 .ip6_null_entry ;
18411851 rcu_read_unlock ();
18421852 dst_hold (& rt -> dst );
18431853 trace_fib6_table_lookup (net , rt , table , fl6 );
@@ -2412,13 +2422,13 @@ static struct rt6_info *__ip6_route_redirect(struct net *net,
24122422 }
24132423
24142424 if (!rt )
2415- rt = net -> ipv6 .ip6_null_entry ;
2425+ rt = net -> ipv6 .fib6_null_entry ;
24162426 else if (rt -> rt6i_flags & RTF_REJECT ) {
24172427 rt = net -> ipv6 .ip6_null_entry ;
24182428 goto out ;
24192429 }
24202430
2421- if (rt == net -> ipv6 .ip6_null_entry ) {
2431+ if (rt == net -> ipv6 .fib6_null_entry ) {
24222432 fn = fib6_backtrack (fn , & fl6 -> saddr );
24232433 if (fn )
24242434 goto restart ;
@@ -3051,7 +3061,7 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info)
30513061 struct fib6_table * table ;
30523062 int err ;
30533063
3054- if (rt == net -> ipv6 .ip6_null_entry ) {
3064+ if (rt == net -> ipv6 .fib6_null_entry ) {
30553065 err = - ENOENT ;
30563066 goto out ;
30573067 }
@@ -3081,7 +3091,7 @@ static int __ip6_del_rt_siblings(struct rt6_info *rt, struct fib6_config *cfg)
30813091 struct fib6_table * table ;
30823092 int err = - ENOENT ;
30833093
3084- if (rt == net -> ipv6 .ip6_null_entry )
3094+ if (rt == net -> ipv6 .fib6_null_entry )
30853095 goto out_put ;
30863096 table = rt -> rt6i_table ;
30873097 spin_lock_bh (& table -> tb6_lock );
@@ -3634,7 +3644,7 @@ static int fib6_remove_prefsrc(struct rt6_info *rt, void *arg)
36343644 struct in6_addr * addr = ((struct arg_dev_net_ip * )arg )-> addr ;
36353645
36363646 if (((void * )rt -> fib6_nh .nh_dev == dev || !dev ) &&
3637- rt != net -> ipv6 .ip6_null_entry &&
3647+ rt != net -> ipv6 .fib6_null_entry &&
36383648 ipv6_addr_equal (addr , & rt -> rt6i_prefsrc .addr )) {
36393649 spin_lock_bh (& rt6_exception_lock );
36403650 /* remove prefsrc entry */
@@ -3789,7 +3799,7 @@ static int fib6_ifup(struct rt6_info *rt, void *p_arg)
37893799 const struct arg_netdev_event * arg = p_arg ;
37903800 struct net * net = dev_net (arg -> dev );
37913801
3792- if (rt != net -> ipv6 .ip6_null_entry && rt -> fib6_nh .nh_dev == arg -> dev ) {
3802+ if (rt != net -> ipv6 .fib6_null_entry && rt -> fib6_nh .nh_dev == arg -> dev ) {
37933803 rt -> fib6_nh .nh_flags &= ~arg -> nh_flags ;
37943804 fib6_update_sernum_upto_root (net , rt );
37953805 rt6_multipath_rebalance (rt );
@@ -3873,7 +3883,7 @@ static int fib6_ifdown(struct rt6_info *rt, void *p_arg)
38733883 const struct net_device * dev = arg -> dev ;
38743884 struct net * net = dev_net (dev );
38753885
3876- if (rt == net -> ipv6 .ip6_null_entry )
3886+ if (rt == net -> ipv6 .fib6_null_entry )
38773887 return 0 ;
38783888
38793889 switch (arg -> event ) {
@@ -4624,7 +4634,7 @@ int rt6_dump_route(struct rt6_info *rt, void *p_arg)
46244634 struct rt6_rtnl_dump_arg * arg = (struct rt6_rtnl_dump_arg * ) p_arg ;
46254635 struct net * net = arg -> net ;
46264636
4627- if (rt == net -> ipv6 .ip6_null_entry )
4637+ if (rt == net -> ipv6 .fib6_null_entry )
46284638 return 0 ;
46294639
46304640 if (nlmsg_len (arg -> cb -> nlh ) >= sizeof (struct rtmsg )) {
@@ -4813,6 +4823,8 @@ static int ip6_route_dev_notify(struct notifier_block *this,
48134823 return NOTIFY_OK ;
48144824
48154825 if (event == NETDEV_REGISTER ) {
4826+ net -> ipv6 .fib6_null_entry -> fib6_nh .nh_dev = dev ;
4827+ net -> ipv6 .fib6_null_entry -> rt6i_idev = in6_dev_get (dev );
48164828 net -> ipv6 .ip6_null_entry -> dst .dev = dev ;
48174829 net -> ipv6 .ip6_null_entry -> rt6i_idev = in6_dev_get (dev );
48184830#ifdef CONFIG_IPV6_MULTIPLE_TABLES
@@ -4826,6 +4838,7 @@ static int ip6_route_dev_notify(struct notifier_block *this,
48264838 /* NETDEV_UNREGISTER could be fired for multiple times by
48274839 * netdev_wait_allrefs(). Make sure we only call this once.
48284840 */
4841+ in6_dev_put_clear (& net -> ipv6 .fib6_null_entry -> rt6i_idev );
48294842 in6_dev_put_clear (& net -> ipv6 .ip6_null_entry -> rt6i_idev );
48304843#ifdef CONFIG_IPV6_MULTIPLE_TABLES
48314844 in6_dev_put_clear (& net -> ipv6 .ip6_prohibit_entry -> rt6i_idev );
@@ -5009,11 +5022,17 @@ static int __net_init ip6_route_net_init(struct net *net)
50095022 if (dst_entries_init (& net -> ipv6 .ip6_dst_ops ) < 0 )
50105023 goto out_ip6_dst_ops ;
50115024
5025+ net -> ipv6 .fib6_null_entry = kmemdup (& fib6_null_entry_template ,
5026+ sizeof (* net -> ipv6 .fib6_null_entry ),
5027+ GFP_KERNEL );
5028+ if (!net -> ipv6 .fib6_null_entry )
5029+ goto out_ip6_dst_entries ;
5030+
50125031 net -> ipv6 .ip6_null_entry = kmemdup (& ip6_null_entry_template ,
50135032 sizeof (* net -> ipv6 .ip6_null_entry ),
50145033 GFP_KERNEL );
50155034 if (!net -> ipv6 .ip6_null_entry )
5016- goto out_ip6_dst_entries ;
5035+ goto out_fib6_null_entry ;
50175036 net -> ipv6 .ip6_null_entry -> dst .ops = & net -> ipv6 .ip6_dst_ops ;
50185037 dst_init_metrics (& net -> ipv6 .ip6_null_entry -> dst ,
50195038 ip6_template_metrics , true);
@@ -5060,6 +5079,8 @@ static int __net_init ip6_route_net_init(struct net *net)
50605079out_ip6_null_entry :
50615080 kfree (net -> ipv6 .ip6_null_entry );
50625081#endif
5082+ out_fib6_null_entry :
5083+ kfree (net -> ipv6 .fib6_null_entry );
50635084out_ip6_dst_entries :
50645085 dst_entries_destroy (& net -> ipv6 .ip6_dst_ops );
50655086out_ip6_dst_ops :
@@ -5068,6 +5089,7 @@ static int __net_init ip6_route_net_init(struct net *net)
50685089
50695090static void __net_exit ip6_route_net_exit (struct net * net )
50705091{
5092+ kfree (net -> ipv6 .fib6_null_entry );
50715093 kfree (net -> ipv6 .ip6_null_entry );
50725094#ifdef CONFIG_IPV6_MULTIPLE_TABLES
50735095 kfree (net -> ipv6 .ip6_prohibit_entry );
@@ -5138,6 +5160,8 @@ void __init ip6_route_init_special_entries(void)
51385160 /* Registering of the loopback is done before this portion of code,
51395161 * the loopback reference in rt6_info will not be taken, do it
51405162 * manually for init_net */
5163+ init_net .ipv6 .fib6_null_entry -> fib6_nh .nh_dev = init_net .loopback_dev ;
5164+ init_net .ipv6 .fib6_null_entry -> rt6i_idev = in6_dev_get (init_net .loopback_dev );
51415165 init_net .ipv6 .ip6_null_entry -> dst .dev = init_net .loopback_dev ;
51425166 init_net .ipv6 .ip6_null_entry -> rt6i_idev = in6_dev_get (init_net .loopback_dev );
51435167 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
0 commit comments