diff options
-rw-r--r-- | net/mac80211/mesh_plink.c | 41 |
1 files changed, 35 insertions, 6 deletions
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 3323413acb77..e12be2e4e8df 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -422,20 +422,54 @@ out: | |||
422 | spin_unlock_bh(&sta->mesh->plink_lock); | 422 | spin_unlock_bh(&sta->mesh->plink_lock); |
423 | } | 423 | } |
424 | 424 | ||
425 | static int mesh_allocate_aid(struct ieee80211_sub_if_data *sdata) | ||
426 | { | ||
427 | struct sta_info *sta; | ||
428 | unsigned long *aid_map; | ||
429 | int aid; | ||
430 | |||
431 | aid_map = kcalloc(BITS_TO_LONGS(IEEE80211_MAX_AID + 1), | ||
432 | sizeof(*aid_map), GFP_KERNEL); | ||
433 | if (!aid_map) | ||
434 | return -ENOMEM; | ||
435 | |||
436 | /* reserve aid 0 for mcast indication */ | ||
437 | __set_bit(0, aid_map); | ||
438 | |||
439 | rcu_read_lock(); | ||
440 | list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) | ||
441 | __set_bit(sta->sta.aid, aid_map); | ||
442 | rcu_read_unlock(); | ||
443 | |||
444 | aid = find_first_zero_bit(aid_map, IEEE80211_MAX_AID + 1); | ||
445 | kfree(aid_map); | ||
446 | |||
447 | if (aid > IEEE80211_MAX_AID) | ||
448 | return -ENOBUFS; | ||
449 | |||
450 | return aid; | ||
451 | } | ||
452 | |||
425 | static struct sta_info * | 453 | static struct sta_info * |
426 | __mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *hw_addr) | 454 | __mesh_sta_info_alloc(struct ieee80211_sub_if_data *sdata, u8 *hw_addr) |
427 | { | 455 | { |
428 | struct sta_info *sta; | 456 | struct sta_info *sta; |
457 | int aid; | ||
429 | 458 | ||
430 | if (sdata->local->num_sta >= MESH_MAX_PLINKS) | 459 | if (sdata->local->num_sta >= MESH_MAX_PLINKS) |
431 | return NULL; | 460 | return NULL; |
432 | 461 | ||
462 | aid = mesh_allocate_aid(sdata); | ||
463 | if (aid < 0) | ||
464 | return NULL; | ||
465 | |||
433 | sta = sta_info_alloc(sdata, hw_addr, GFP_KERNEL); | 466 | sta = sta_info_alloc(sdata, hw_addr, GFP_KERNEL); |
434 | if (!sta) | 467 | if (!sta) |
435 | return NULL; | 468 | return NULL; |
436 | 469 | ||
437 | sta->mesh->plink_state = NL80211_PLINK_LISTEN; | 470 | sta->mesh->plink_state = NL80211_PLINK_LISTEN; |
438 | sta->sta.wme = true; | 471 | sta->sta.wme = true; |
472 | sta->sta.aid = aid; | ||
439 | 473 | ||
440 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); | 474 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); |
441 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); | 475 | sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC); |
@@ -659,8 +693,6 @@ static u16 mesh_get_new_llid(struct ieee80211_sub_if_data *sdata) | |||
659 | 693 | ||
660 | do { | 694 | do { |
661 | get_random_bytes(&llid, sizeof(llid)); | 695 | get_random_bytes(&llid, sizeof(llid)); |
662 | /* for mesh PS we still only have the AID range for TIM bits */ | ||
663 | llid = (llid % IEEE80211_MAX_AID) + 1; | ||
664 | } while (llid_in_use(sdata, llid)); | 696 | } while (llid_in_use(sdata, llid)); |
665 | 697 | ||
666 | return llid; | 698 | return llid; |
@@ -1069,7 +1101,6 @@ mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata, | |||
1069 | goto unlock_rcu; | 1101 | goto unlock_rcu; |
1070 | } | 1102 | } |
1071 | sta->mesh->plid = plid; | 1103 | sta->mesh->plid = plid; |
1072 | sta->sta.aid = plid; | ||
1073 | } else if (!sta && event == OPN_RJCT) { | 1104 | } else if (!sta && event == OPN_RJCT) { |
1074 | mesh_plink_frame_tx(sdata, NULL, WLAN_SP_MESH_PEERING_CLOSE, | 1105 | mesh_plink_frame_tx(sdata, NULL, WLAN_SP_MESH_PEERING_CLOSE, |
1075 | mgmt->sa, 0, plid, | 1106 | mgmt->sa, 0, plid, |
@@ -1082,10 +1113,8 @@ mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata, | |||
1082 | 1113 | ||
1083 | if (event == CNF_ACPT) { | 1114 | if (event == CNF_ACPT) { |
1084 | /* 802.11-2012 13.3.7.2 - update plid on CNF if not set */ | 1115 | /* 802.11-2012 13.3.7.2 - update plid on CNF if not set */ |
1085 | if (!sta->mesh->plid) { | 1116 | if (!sta->mesh->plid) |
1086 | sta->mesh->plid = plid; | 1117 | sta->mesh->plid = plid; |
1087 | sta->sta.aid = sta->mesh->plid; | ||
1088 | } | ||
1089 | 1118 | ||
1090 | sta->mesh->aid = get_unaligned_le16(PLINK_CNF_AID(mgmt)); | 1119 | sta->mesh->aid = get_unaligned_le16(PLINK_CNF_AID(mgmt)); |
1091 | } | 1120 | } |