@@ -493,6 +493,7 @@ static LIST_HEAD(hwsim_radios);
493
493
static struct workqueue_struct * hwsim_wq ;
494
494
static struct rhashtable hwsim_radios_rht ;
495
495
static int hwsim_radio_idx ;
496
+ static int hwsim_radios_generation = 1 ;
496
497
497
498
static struct platform_driver mac80211_hwsim_driver = {
498
499
.driver = {
@@ -637,6 +638,7 @@ static const struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = {
637
638
[HWSIM_ATTR_RADIO_NAME ] = { .type = NLA_STRING },
638
639
[HWSIM_ATTR_NO_VIF ] = { .type = NLA_FLAG },
639
640
[HWSIM_ATTR_FREQ ] = { .type = NLA_U32 },
641
+ [HWSIM_ATTR_PERM_ADDR ] = { .type = NLA_UNSPEC , .len = ETH_ALEN },
640
642
};
641
643
642
644
static void mac80211_hwsim_tx_frame (struct ieee80211_hw * hw ,
@@ -2408,6 +2410,7 @@ struct hwsim_new_radio_params {
2408
2410
bool destroy_on_close ;
2409
2411
const char * hwname ;
2410
2412
bool no_vif ;
2413
+ const u8 * perm_addr ;
2411
2414
};
2412
2415
2413
2416
static void hwsim_mcast_config_msg (struct sk_buff * mcast_skb ,
@@ -2572,15 +2575,25 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
2572
2575
skb_queue_head_init (& data -> pending );
2573
2576
2574
2577
SET_IEEE80211_DEV (hw , data -> dev );
2575
- eth_zero_addr (addr );
2576
- addr [0 ] = 0x02 ;
2577
- addr [3 ] = idx >> 8 ;
2578
- addr [4 ] = idx ;
2579
- memcpy (data -> addresses [0 ].addr , addr , ETH_ALEN );
2580
- memcpy (data -> addresses [1 ].addr , addr , ETH_ALEN );
2581
- data -> addresses [1 ].addr [0 ] |= 0x40 ;
2582
- hw -> wiphy -> n_addresses = 2 ;
2583
- hw -> wiphy -> addresses = data -> addresses ;
2578
+ if (!param -> perm_addr ) {
2579
+ eth_zero_addr (addr );
2580
+ addr [0 ] = 0x02 ;
2581
+ addr [3 ] = idx >> 8 ;
2582
+ addr [4 ] = idx ;
2583
+ memcpy (data -> addresses [0 ].addr , addr , ETH_ALEN );
2584
+ /* Why need here second address ? */
2585
+ data -> addresses [1 ].addr [0 ] |= 0x40 ;
2586
+ memcpy (data -> addresses [1 ].addr , addr , ETH_ALEN );
2587
+ hw -> wiphy -> n_addresses = 2 ;
2588
+ hw -> wiphy -> addresses = data -> addresses ;
2589
+ /* possible address clash is checked at hash table insertion */
2590
+ } else {
2591
+ memcpy (data -> addresses [0 ].addr , param -> perm_addr , ETH_ALEN );
2592
+ /* compatibility with automatically generated mac addr */
2593
+ memcpy (data -> addresses [1 ].addr , param -> perm_addr , ETH_ALEN );
2594
+ hw -> wiphy -> n_addresses = 2 ;
2595
+ hw -> wiphy -> addresses = data -> addresses ;
2596
+ }
2584
2597
2585
2598
data -> channels = param -> channels ;
2586
2599
data -> use_chanctx = param -> use_chanctx ;
@@ -2785,13 +2798,17 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
2785
2798
err = rhashtable_insert_fast (& hwsim_radios_rht , & data -> rht ,
2786
2799
hwsim_rht_params );
2787
2800
if (err < 0 ) {
2788
- pr_debug ("mac80211_hwsim: radio index %d already present\n" ,
2789
- idx );
2801
+ if (info ) {
2802
+ GENL_SET_ERR_MSG (info , "perm addr already present" );
2803
+ NL_SET_BAD_ATTR (info -> extack ,
2804
+ info -> attrs [HWSIM_ATTR_PERM_ADDR ]);
2805
+ }
2790
2806
spin_unlock_bh (& hwsim_radio_lock );
2791
2807
goto failed_final_insert ;
2792
2808
}
2793
2809
2794
2810
list_add_tail (& data -> list , & hwsim_radios );
2811
+ hwsim_radios_generation ++ ;
2795
2812
spin_unlock_bh (& hwsim_radio_lock );
2796
2813
2797
2814
if (idx > 0 )
@@ -3210,6 +3227,19 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info)
3210
3227
param .regd = hwsim_world_regdom_custom [idx ];
3211
3228
}
3212
3229
3230
+ if (info -> attrs [HWSIM_ATTR_PERM_ADDR ]) {
3231
+ if (!is_valid_ether_addr (
3232
+ nla_data (info -> attrs [HWSIM_ATTR_PERM_ADDR ]))) {
3233
+ GENL_SET_ERR_MSG (info ,"MAC is no valid source addr" );
3234
+ NL_SET_BAD_ATTR (info -> extack ,
3235
+ info -> attrs [HWSIM_ATTR_PERM_ADDR ]);
3236
+ return - EINVAL ;
3237
+ }
3238
+
3239
+
3240
+ param .perm_addr = nla_data (info -> attrs [HWSIM_ATTR_PERM_ADDR ]);
3241
+ }
3242
+
3213
3243
ret = mac80211_hwsim_new_radio (info , & param );
3214
3244
kfree (hwname );
3215
3245
return ret ;
@@ -3249,6 +3279,7 @@ static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info)
3249
3279
list_del (& data -> list );
3250
3280
rhashtable_remove_fast (& hwsim_radios_rht , & data -> rht ,
3251
3281
hwsim_rht_params );
3282
+ hwsim_radios_generation ++ ;
3252
3283
spin_unlock_bh (& hwsim_radio_lock );
3253
3284
mac80211_hwsim_del_radio (data , wiphy_name (data -> hw -> wiphy ),
3254
3285
info );
@@ -3305,17 +3336,19 @@ static int hwsim_get_radio_nl(struct sk_buff *msg, struct genl_info *info)
3305
3336
static int hwsim_dump_radio_nl (struct sk_buff * skb ,
3306
3337
struct netlink_callback * cb )
3307
3338
{
3308
- int idx = cb -> args [0 ];
3339
+ int last_idx = cb -> args [0 ];
3309
3340
struct mac80211_hwsim_data * data = NULL ;
3310
- int res ;
3341
+ int res = 0 ;
3342
+ void * hdr ;
3311
3343
3312
3344
spin_lock_bh (& hwsim_radio_lock );
3345
+ cb -> seq = hwsim_radios_generation ;
3313
3346
3314
- if (idx == hwsim_radio_idx )
3347
+ if (last_idx >= hwsim_radio_idx - 1 )
3315
3348
goto done ;
3316
3349
3317
3350
list_for_each_entry (data , & hwsim_radios , list ) {
3318
- if (data -> idx < idx )
3351
+ if (data -> idx <= last_idx )
3319
3352
continue ;
3320
3353
3321
3354
if (!net_eq (wiphy_net (data -> hw -> wiphy ), sock_net (skb -> sk )))
@@ -3328,14 +3361,25 @@ static int hwsim_dump_radio_nl(struct sk_buff *skb,
3328
3361
if (res < 0 )
3329
3362
break ;
3330
3363
3331
- idx = data -> idx + 1 ;
3364
+ last_idx = data -> idx ;
3332
3365
}
3333
3366
3334
- cb -> args [0 ] = idx ;
3367
+ cb -> args [0 ] = last_idx ;
3368
+
3369
+ /* list changed, but no new element sent, set interrupted flag */
3370
+ if (skb -> len == 0 && cb -> prev_seq && cb -> seq != cb -> prev_seq ) {
3371
+ hdr = genlmsg_put (skb , NETLINK_CB (cb -> skb ).portid ,
3372
+ cb -> nlh -> nlmsg_seq , & hwsim_genl_family ,
3373
+ NLM_F_MULTI , HWSIM_CMD_GET_RADIO );
3374
+ if (!hdr )
3375
+ res = - EMSGSIZE ;
3376
+ genl_dump_check_consistent (cb , hdr );
3377
+ genlmsg_end (skb , hdr );
3378
+ }
3335
3379
3336
3380
done :
3337
3381
spin_unlock_bh (& hwsim_radio_lock );
3338
- return skb -> len ;
3382
+ return res ?: skb -> len ;
3339
3383
}
3340
3384
3341
3385
/* Generic Netlink operations array */
@@ -3393,6 +3437,7 @@ static void destroy_radio(struct work_struct *work)
3393
3437
struct mac80211_hwsim_data * data =
3394
3438
container_of (work , struct mac80211_hwsim_data , destroy_work );
3395
3439
3440
+ hwsim_radios_generation ++ ;
3396
3441
mac80211_hwsim_del_radio (data , wiphy_name (data -> hw -> wiphy ), NULL );
3397
3442
}
3398
3443
0 commit comments