@@ -243,6 +243,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = {
243
243
.seg6_require_hmac = 0 ,
244
244
#endif
245
245
.enhanced_dad = 1 ,
246
+ .addr_gen_mode = IN6_ADDR_GEN_MODE_EUI64 ,
246
247
};
247
248
248
249
static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
@@ -294,6 +295,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = {
294
295
.seg6_require_hmac = 0 ,
295
296
#endif
296
297
.enhanced_dad = 1 ,
298
+ .addr_gen_mode = IN6_ADDR_GEN_MODE_EUI64 ,
297
299
};
298
300
299
301
/* Check if a valid qdisc is available */
@@ -386,9 +388,9 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
386
388
memcpy (& ndev -> cnf , dev_net (dev )-> ipv6 .devconf_dflt , sizeof (ndev -> cnf ));
387
389
388
390
if (ndev -> cnf .stable_secret .initialized )
389
- ndev -> addr_gen_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY ;
391
+ ndev -> cnf . addr_gen_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY ;
390
392
else
391
- ndev -> addr_gen_mode = IN6_ADDR_GEN_MODE_EUI64 ;
393
+ ndev -> cnf . addr_gen_mode = ipv6_devconf_dflt . addr_gen_mode ;
392
394
393
395
ndev -> cnf .mtu6 = dev -> mtu ;
394
396
ndev -> nd_parms = neigh_parms_alloc (dev , & nd_tbl );
@@ -2387,8 +2389,8 @@ static void manage_tempaddrs(struct inet6_dev *idev,
2387
2389
2388
2390
static bool is_addr_mode_generate_stable (struct inet6_dev * idev )
2389
2391
{
2390
- return idev -> addr_gen_mode == IN6_ADDR_GEN_MODE_STABLE_PRIVACY ||
2391
- idev -> addr_gen_mode == IN6_ADDR_GEN_MODE_RANDOM ;
2392
+ return idev -> cnf . addr_gen_mode == IN6_ADDR_GEN_MODE_STABLE_PRIVACY ||
2393
+ idev -> cnf . addr_gen_mode == IN6_ADDR_GEN_MODE_RANDOM ;
2392
2394
}
2393
2395
2394
2396
int addrconf_prefix_rcv_add_addr (struct net * net , struct net_device * dev ,
@@ -3152,7 +3154,7 @@ static void addrconf_addr_gen(struct inet6_dev *idev, bool prefix_route)
3152
3154
3153
3155
ipv6_addr_set (& addr , htonl (0xFE800000 ), 0 , 0 , 0 );
3154
3156
3155
- switch (idev -> addr_gen_mode ) {
3157
+ switch (idev -> cnf . addr_gen_mode ) {
3156
3158
case IN6_ADDR_GEN_MODE_RANDOM :
3157
3159
ipv6_gen_mode_random_init (idev );
3158
3160
/* fallthrough */
@@ -3204,8 +3206,8 @@ static void addrconf_dev_config(struct net_device *dev)
3204
3206
3205
3207
/* this device type has no EUI support */
3206
3208
if (dev -> type == ARPHRD_NONE &&
3207
- idev -> addr_gen_mode == IN6_ADDR_GEN_MODE_EUI64 )
3208
- idev -> addr_gen_mode = IN6_ADDR_GEN_MODE_RANDOM ;
3209
+ idev -> cnf . addr_gen_mode == IN6_ADDR_GEN_MODE_EUI64 )
3210
+ idev -> cnf . addr_gen_mode = IN6_ADDR_GEN_MODE_RANDOM ;
3209
3211
3210
3212
addrconf_addr_gen (idev , false);
3211
3213
}
@@ -4982,6 +4984,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf,
4982
4984
array [DEVCONF_SEG6_REQUIRE_HMAC ] = cnf -> seg6_require_hmac ;
4983
4985
#endif
4984
4986
array [DEVCONF_ENHANCED_DAD ] = cnf -> enhanced_dad ;
4987
+ array [DEVCONF_ADDR_GEN_MODE ] = cnf -> addr_gen_mode ;
4985
4988
}
4986
4989
4987
4990
static inline size_t inet6_ifla6_size (void )
@@ -5093,7 +5096,7 @@ static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev,
5093
5096
if (!nla )
5094
5097
goto nla_put_failure ;
5095
5098
5096
- if (nla_put_u8 (skb , IFLA_INET6_ADDR_GEN_MODE , idev -> addr_gen_mode ))
5099
+ if (nla_put_u8 (skb , IFLA_INET6_ADDR_GEN_MODE , idev -> cnf . addr_gen_mode ))
5097
5100
goto nla_put_failure ;
5098
5101
5099
5102
read_lock_bh (& idev -> lock );
@@ -5211,6 +5214,26 @@ static int inet6_validate_link_af(const struct net_device *dev,
5211
5214
return nla_parse_nested (tb , IFLA_INET6_MAX , nla , inet6_af_policy );
5212
5215
}
5213
5216
5217
+ static int check_addr_gen_mode (int mode )
5218
+ {
5219
+ if (mode != IN6_ADDR_GEN_MODE_EUI64 &&
5220
+ mode != IN6_ADDR_GEN_MODE_NONE &&
5221
+ mode != IN6_ADDR_GEN_MODE_STABLE_PRIVACY &&
5222
+ mode != IN6_ADDR_GEN_MODE_RANDOM )
5223
+ return - EINVAL ;
5224
+ return 1 ;
5225
+ }
5226
+
5227
+ static int check_stable_privacy (struct inet6_dev * idev , struct net * net ,
5228
+ int mode )
5229
+ {
5230
+ if (mode == IN6_ADDR_GEN_MODE_STABLE_PRIVACY &&
5231
+ !idev -> cnf .stable_secret .initialized &&
5232
+ !net -> ipv6 .devconf_dflt -> stable_secret .initialized )
5233
+ return - EINVAL ;
5234
+ return 1 ;
5235
+ }
5236
+
5214
5237
static int inet6_set_link_af (struct net_device * dev , const struct nlattr * nla )
5215
5238
{
5216
5239
int err = - EINVAL ;
@@ -5232,18 +5255,11 @@ static int inet6_set_link_af(struct net_device *dev, const struct nlattr *nla)
5232
5255
if (tb [IFLA_INET6_ADDR_GEN_MODE ]) {
5233
5256
u8 mode = nla_get_u8 (tb [IFLA_INET6_ADDR_GEN_MODE ]);
5234
5257
5235
- if (mode != IN6_ADDR_GEN_MODE_EUI64 &&
5236
- mode != IN6_ADDR_GEN_MODE_NONE &&
5237
- mode != IN6_ADDR_GEN_MODE_STABLE_PRIVACY &&
5238
- mode != IN6_ADDR_GEN_MODE_RANDOM )
5239
- return - EINVAL ;
5240
-
5241
- if (mode == IN6_ADDR_GEN_MODE_STABLE_PRIVACY &&
5242
- !idev -> cnf .stable_secret .initialized &&
5243
- !dev_net (dev )-> ipv6 .devconf_dflt -> stable_secret .initialized )
5258
+ if (check_addr_gen_mode (mode ) < 0 ||
5259
+ check_stable_privacy (idev , dev_net (dev ), mode ) < 0 )
5244
5260
return - EINVAL ;
5245
5261
5246
- idev -> addr_gen_mode = mode ;
5262
+ idev -> cnf . addr_gen_mode = mode ;
5247
5263
err = 0 ;
5248
5264
}
5249
5265
@@ -5652,6 +5668,47 @@ int addrconf_sysctl_proxy_ndp(struct ctl_table *ctl, int write,
5652
5668
return ret ;
5653
5669
}
5654
5670
5671
+ static int addrconf_sysctl_addr_gen_mode (struct ctl_table * ctl , int write ,
5672
+ void __user * buffer , size_t * lenp ,
5673
+ loff_t * ppos )
5674
+ {
5675
+ int ret = 0 ;
5676
+ int new_val ;
5677
+ struct inet6_dev * idev = (struct inet6_dev * )ctl -> extra1 ;
5678
+ struct net * net = (struct net * )ctl -> extra2 ;
5679
+
5680
+ ret = proc_dointvec (ctl , write , buffer , lenp , ppos );
5681
+
5682
+ if (write ) {
5683
+ new_val = * ((int * )ctl -> data );
5684
+
5685
+ if (check_addr_gen_mode (new_val ) < 0 )
5686
+ return - EINVAL ;
5687
+
5688
+ /* request for default */
5689
+ if (& net -> ipv6 .devconf_dflt -> addr_gen_mode == ctl -> data ) {
5690
+ ipv6_devconf_dflt .addr_gen_mode = new_val ;
5691
+
5692
+ /* request for individual net device */
5693
+ } else {
5694
+ if (!idev )
5695
+ return ret ;
5696
+
5697
+ if (check_stable_privacy (idev , net , new_val ) < 0 )
5698
+ return - EINVAL ;
5699
+
5700
+ if (idev -> cnf .addr_gen_mode != new_val ) {
5701
+ idev -> cnf .addr_gen_mode = new_val ;
5702
+ rtnl_lock ();
5703
+ addrconf_dev_config (idev -> dev );
5704
+ rtnl_unlock ();
5705
+ }
5706
+ }
5707
+ }
5708
+
5709
+ return ret ;
5710
+ }
5711
+
5655
5712
static int addrconf_sysctl_stable_secret (struct ctl_table * ctl , int write ,
5656
5713
void __user * buffer , size_t * lenp ,
5657
5714
loff_t * ppos )
@@ -5702,14 +5759,14 @@ static int addrconf_sysctl_stable_secret(struct ctl_table *ctl, int write,
5702
5759
struct inet6_dev * idev = __in6_dev_get (dev );
5703
5760
5704
5761
if (idev ) {
5705
- idev -> addr_gen_mode =
5762
+ idev -> cnf . addr_gen_mode =
5706
5763
IN6_ADDR_GEN_MODE_STABLE_PRIVACY ;
5707
5764
}
5708
5765
}
5709
5766
} else {
5710
5767
struct inet6_dev * idev = ctl -> extra1 ;
5711
5768
5712
- idev -> addr_gen_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY ;
5769
+ idev -> cnf . addr_gen_mode = IN6_ADDR_GEN_MODE_STABLE_PRIVACY ;
5713
5770
}
5714
5771
5715
5772
out :
@@ -6096,6 +6153,13 @@ static const struct ctl_table addrconf_sysctl[] = {
6096
6153
.mode = 0644 ,
6097
6154
.proc_handler = proc_dointvec ,
6098
6155
},
6156
+ {
6157
+ .procname = "addr_gen_mode" ,
6158
+ .data = & ipv6_devconf .addr_gen_mode ,
6159
+ .maxlen = sizeof (int ),
6160
+ .mode = 0644 ,
6161
+ .proc_handler = addrconf_sysctl_addr_gen_mode ,
6162
+ },
6099
6163
{
6100
6164
/* sentinel */
6101
6165
}
0 commit comments