@@ -3729,15 +3729,13 @@ void fib6_nh_release_dsts(struct fib6_nh *fib6_nh)
3729
3729
}
3730
3730
3731
3731
static struct fib6_info * ip6_route_info_create (struct fib6_config * cfg ,
3732
- gfp_t gfp_flags ,
3733
- struct netlink_ext_ack * extack )
3732
+ gfp_t gfp_flags ,
3733
+ struct netlink_ext_ack * extack )
3734
3734
{
3735
3735
struct net * net = cfg -> fc_nlinfo .nl_net ;
3736
- struct fib6_info * rt = NULL ;
3737
3736
struct fib6_table * table ;
3738
- struct fib6_nh * fib6_nh ;
3739
- int err = - ENOBUFS ;
3740
- int addr_type ;
3737
+ struct fib6_info * rt ;
3738
+ int err ;
3741
3739
3742
3740
if (cfg -> fc_nlinfo .nlh &&
3743
3741
!(cfg -> fc_nlinfo .nlh -> nlmsg_flags & NLM_F_CREATE )) {
@@ -3749,35 +3747,35 @@ static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg,
3749
3747
} else {
3750
3748
table = fib6_new_table (net , cfg -> fc_table );
3751
3749
}
3750
+ if (!table ) {
3751
+ err = - ENOBUFS ;
3752
+ goto err ;
3753
+ }
3752
3754
3753
- if (!table )
3754
- goto out ;
3755
-
3756
- err = - ENOMEM ;
3757
3755
rt = fib6_info_alloc (gfp_flags , !cfg -> fc_nh_id );
3758
- if (!rt )
3759
- goto out ;
3756
+ if (!rt ) {
3757
+ err = - ENOMEM ;
3758
+ goto err ;
3759
+ }
3760
3760
3761
3761
rt -> fib6_metrics = ip_fib_metrics_init (cfg -> fc_mx , cfg -> fc_mx_len ,
3762
3762
extack );
3763
3763
if (IS_ERR (rt -> fib6_metrics )) {
3764
3764
err = PTR_ERR (rt -> fib6_metrics );
3765
- /* Do not leave garbage there. */
3766
- rt -> fib6_metrics = (struct dst_metrics * )& dst_default_metrics ;
3767
- goto out_free ;
3765
+ goto free ;
3768
3766
}
3769
3767
3770
3768
if (cfg -> fc_flags & RTF_ADDRCONF )
3771
3769
rt -> dst_nocount = true;
3772
3770
3773
3771
if (cfg -> fc_flags & RTF_EXPIRES )
3774
3772
fib6_set_expires (rt , jiffies +
3775
- clock_t_to_jiffies (cfg -> fc_expires ));
3773
+ clock_t_to_jiffies (cfg -> fc_expires ));
3776
3774
3777
3775
if (cfg -> fc_protocol == RTPROT_UNSPEC )
3778
3776
cfg -> fc_protocol = RTPROT_BOOT ;
3779
- rt -> fib6_protocol = cfg -> fc_protocol ;
3780
3777
3778
+ rt -> fib6_protocol = cfg -> fc_protocol ;
3781
3779
rt -> fib6_table = table ;
3782
3780
rt -> fib6_metric = cfg -> fc_metric ;
3783
3781
rt -> fib6_type = cfg -> fc_type ? : RTN_UNICAST ;
@@ -3790,6 +3788,20 @@ static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg,
3790
3788
ipv6_addr_prefix (& rt -> fib6_src .addr , & cfg -> fc_src , cfg -> fc_src_len );
3791
3789
rt -> fib6_src .plen = cfg -> fc_src_len ;
3792
3790
#endif
3791
+ return rt ;
3792
+ free :
3793
+ kfree (rt );
3794
+ err :
3795
+ return ERR_PTR (err );
3796
+ }
3797
+
3798
+ static int ip6_route_info_create_nh (struct fib6_info * rt ,
3799
+ struct fib6_config * cfg ,
3800
+ struct netlink_ext_ack * extack )
3801
+ {
3802
+ struct net * net = cfg -> fc_nlinfo .nl_net ;
3803
+ struct fib6_nh * fib6_nh ;
3804
+ int err ;
3793
3805
3794
3806
if (cfg -> fc_nh_id ) {
3795
3807
struct nexthop * nh ;
@@ -3814,9 +3826,11 @@ static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg,
3814
3826
rt -> nh = nh ;
3815
3827
fib6_nh = nexthop_fib6_nh (rt -> nh );
3816
3828
} else {
3817
- err = fib6_nh_init (net , rt -> fib6_nh , cfg , gfp_flags , extack );
3829
+ int addr_type ;
3830
+
3831
+ err = fib6_nh_init (net , rt -> fib6_nh , cfg , GFP_ATOMIC , extack );
3818
3832
if (err )
3819
- goto out ;
3833
+ goto out_release ;
3820
3834
3821
3835
fib6_nh = rt -> fib6_nh ;
3822
3836
@@ -3835,21 +3849,20 @@ static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg,
3835
3849
if (!ipv6_chk_addr (net , & cfg -> fc_prefsrc , dev , 0 )) {
3836
3850
NL_SET_ERR_MSG (extack , "Invalid source address" );
3837
3851
err = - EINVAL ;
3838
- goto out ;
3852
+ goto out_release ;
3839
3853
}
3840
3854
rt -> fib6_prefsrc .addr = cfg -> fc_prefsrc ;
3841
3855
rt -> fib6_prefsrc .plen = 128 ;
3842
- } else
3843
- rt -> fib6_prefsrc .plen = 0 ;
3856
+ }
3844
3857
3845
- return rt ;
3846
- out :
3858
+ return 0 ;
3859
+ out_release :
3847
3860
fib6_info_release (rt );
3848
- return ERR_PTR ( err ) ;
3861
+ return err ;
3849
3862
out_free :
3850
3863
ip_fib_metrics_put (rt -> fib6_metrics );
3851
3864
kfree (rt );
3852
- return ERR_PTR ( err ) ;
3865
+ return err ;
3853
3866
}
3854
3867
3855
3868
int ip6_route_add (struct fib6_config * cfg , gfp_t gfp_flags ,
@@ -3862,6 +3875,10 @@ int ip6_route_add(struct fib6_config *cfg, gfp_t gfp_flags,
3862
3875
if (IS_ERR (rt ))
3863
3876
return PTR_ERR (rt );
3864
3877
3878
+ err = ip6_route_info_create_nh (rt , cfg , extack );
3879
+ if (err )
3880
+ return err ;
3881
+
3865
3882
err = __ip6_ins_rt (rt , & cfg -> fc_nlinfo , extack );
3866
3883
fib6_info_release (rt );
3867
3884
@@ -4585,6 +4602,7 @@ struct fib6_info *addrconf_f6i_alloc(struct net *net,
4585
4602
.fc_ignore_dev_down = true,
4586
4603
};
4587
4604
struct fib6_info * f6i ;
4605
+ int err ;
4588
4606
4589
4607
if (anycast ) {
4590
4608
cfg .fc_type = RTN_ANYCAST ;
@@ -4595,14 +4613,19 @@ struct fib6_info *addrconf_f6i_alloc(struct net *net,
4595
4613
}
4596
4614
4597
4615
f6i = ip6_route_info_create (& cfg , gfp_flags , extack );
4598
- if (! IS_ERR (f6i )) {
4599
- f6i -> dst_nocount = true ;
4616
+ if (IS_ERR (f6i ))
4617
+ return f6i ;
4600
4618
4601
- if (!anycast &&
4602
- (READ_ONCE (net -> ipv6 .devconf_all -> disable_policy ) ||
4603
- READ_ONCE (idev -> cnf .disable_policy )))
4604
- f6i -> dst_nopolicy = true;
4605
- }
4619
+ err = ip6_route_info_create_nh (f6i , & cfg , extack );
4620
+ if (err )
4621
+ return ERR_PTR (err );
4622
+
4623
+ f6i -> dst_nocount = true;
4624
+
4625
+ if (!anycast &&
4626
+ (READ_ONCE (net -> ipv6 .devconf_all -> disable_policy ) ||
4627
+ READ_ONCE (idev -> cnf .disable_policy )))
4628
+ f6i -> dst_nopolicy = true;
4606
4629
4607
4630
return f6i ;
4608
4631
}
@@ -5400,6 +5423,12 @@ static int ip6_route_multipath_add(struct fib6_config *cfg,
5400
5423
goto cleanup ;
5401
5424
}
5402
5425
5426
+ err = ip6_route_info_create_nh (rt , & r_cfg , extack );
5427
+ if (err ) {
5428
+ rt = NULL ;
5429
+ goto cleanup ;
5430
+ }
5431
+
5403
5432
rt -> fib6_nh -> fib_nh_weight = rtnh -> rtnh_hops + 1 ;
5404
5433
5405
5434
err = ip6_route_info_append (info -> nl_net , & rt6_nh_list ,
0 commit comments