aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mesh_plink.c
diff options
context:
space:
mode:
authorThomas Pedersen <thomas@cozybit.com>2013-11-05 14:17:05 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-11-25 14:50:29 -0500
commit204d130426206071b08c0aa74002fbdb67960eed (patch)
treec1f4a7788bba2b3afe9c5df2254995231daefc9c /net/mac80211/mesh_plink.c
parentc99a89edb1066e4c1f79b3ca4e91a676d1b25ce1 (diff)
mac80211: clean up mesh local link ID generation
802.11-2012 13.3.1 implicitly limits the mesh local link ID range to that of AID, since for mesh PS the local link ID must be indicated in the TIM IE, which only holds IEEE80211_MAX_AID bits. Also the code was allowing a local link ID of 0, but this is not correct since that TIM bit is used for indicating buffered mcast frames. Generate a random, unique, link ID from 1 - 2007, and drop a modulo conversion for the local link ID, but keep it for the peer link ID in case he chose something > MAX_AID. Signed-off-by: Thomas Pedersen <thomas@cozybit.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/mesh_plink.c')
-rw-r--r--net/mac80211/mesh_plink.c40
1 files changed, 35 insertions, 5 deletions
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index ee2a97f31732..fadc3e189131 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -615,9 +615,40 @@ static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout)
615 add_timer(&sta->plink_timer); 615 add_timer(&sta->plink_timer);
616} 616}
617 617
618static bool llid_in_use(struct ieee80211_sub_if_data *sdata,
619 __le16 llid)
620{
621 struct ieee80211_local *local = sdata->local;
622 bool in_use = false;
623 struct sta_info *sta;
624
625 rcu_read_lock();
626 list_for_each_entry_rcu(sta, &local->sta_list, list) {
627 if (!memcmp(&sta->llid, &llid, sizeof(llid))) {
628 in_use = true;
629 break;
630 }
631 }
632 rcu_read_unlock();
633
634 return in_use;
635}
636
637static __le16 mesh_get_new_llid(struct ieee80211_sub_if_data *sdata)
638{
639 u16 llid;
640
641 do {
642 get_random_bytes(&llid, sizeof(llid));
643 /* for mesh PS we still only have the AID range for TIM bits */
644 llid = (llid % IEEE80211_MAX_AID) + 1;
645 } while (llid_in_use(sdata, cpu_to_le16(llid)));
646
647 return cpu_to_le16(llid);
648}
649
618u32 mesh_plink_open(struct sta_info *sta) 650u32 mesh_plink_open(struct sta_info *sta)
619{ 651{
620 __le16 llid;
621 struct ieee80211_sub_if_data *sdata = sta->sdata; 652 struct ieee80211_sub_if_data *sdata = sta->sdata;
622 u32 changed; 653 u32 changed;
623 654
@@ -625,8 +656,7 @@ u32 mesh_plink_open(struct sta_info *sta)
625 return 0; 656 return 0;
626 657
627 spin_lock_bh(&sta->lock); 658 spin_lock_bh(&sta->lock);
628 get_random_bytes(&llid, 2); 659 sta->llid = mesh_get_new_llid(sdata);
629 sta->llid = llid;
630 if (sta->plink_state != NL80211_PLINK_LISTEN && 660 if (sta->plink_state != NL80211_PLINK_LISTEN &&
631 sta->plink_state != NL80211_PLINK_BLOCKED) { 661 sta->plink_state != NL80211_PLINK_BLOCKED) {
632 spin_unlock_bh(&sta->lock); 662 spin_unlock_bh(&sta->lock);
@@ -643,7 +673,7 @@ u32 mesh_plink_open(struct sta_info *sta)
643 changed = ieee80211_mps_local_status_update(sdata); 673 changed = ieee80211_mps_local_status_update(sdata);
644 674
645 mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN, 675 mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN,
646 sta->sta.addr, llid, 0, 0); 676 sta->sta.addr, sta->llid, 0, 0);
647 return changed; 677 return changed;
648} 678}
649 679
@@ -719,7 +749,7 @@ static u32 mesh_plink_fsm(struct ieee80211_sub_if_data *sdata,
719 break; 749 break;
720 case OPN_ACPT: 750 case OPN_ACPT:
721 sta->plink_state = NL80211_PLINK_OPN_RCVD; 751 sta->plink_state = NL80211_PLINK_OPN_RCVD;
722 get_random_bytes(&sta->llid, 2); 752 sta->llid = mesh_get_new_llid(sdata);
723 mesh_plink_timer_set(sta, 753 mesh_plink_timer_set(sta,
724 mshcfg->dot11MeshRetryTimeout); 754 mshcfg->dot11MeshRetryTimeout);
725 755