aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/net/mac80211/mesh_plink.c
diff options
context:
space:
mode:
authorThomas Pedersen <thomas@cozybit.com>2013-11-05 11:17:05 -0800
committerJohannes Berg <johannes.berg@intel.com>2013-11-25 20:50:29 +0100
commit204d130426206071b08c0aa74002fbdb67960eed (patch)
treec1f4a7788bba2b3afe9c5df2254995231daefc9c /net/mac80211/mesh_plink.c
parentmac80211: factor out plink event gathering (diff)
downloadwireguard-linux-204d130426206071b08c0aa74002fbdb67960eed.tar.xz
wireguard-linux-204d130426206071b08c0aa74002fbdb67960eed.zip
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)
add_timer(&sta->plink_timer);
}
+static bool llid_in_use(struct ieee80211_sub_if_data *sdata,
+ __le16 llid)
+{
+ struct ieee80211_local *local = sdata->local;
+ bool in_use = false;
+ struct sta_info *sta;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(sta, &local->sta_list, list) {
+ if (!memcmp(&sta->llid, &llid, sizeof(llid))) {
+ in_use = true;
+ break;
+ }
+ }
+ rcu_read_unlock();
+
+ return in_use;
+}
+
+static __le16 mesh_get_new_llid(struct ieee80211_sub_if_data *sdata)
+{
+ u16 llid;
+
+ do {
+ get_random_bytes(&llid, sizeof(llid));
+ /* for mesh PS we still only have the AID range for TIM bits */
+ llid = (llid % IEEE80211_MAX_AID) + 1;
+ } while (llid_in_use(sdata, cpu_to_le16(llid)));
+
+ return cpu_to_le16(llid);
+}
+
u32 mesh_plink_open(struct sta_info *sta)
{
- __le16 llid;
struct ieee80211_sub_if_data *sdata = sta->sdata;
u32 changed;
@@ -625,8 +656,7 @@ u32 mesh_plink_open(struct sta_info *sta)
return 0;
spin_lock_bh(&sta->lock);
- get_random_bytes(&llid, 2);
- sta->llid = llid;
+ sta->llid = mesh_get_new_llid(sdata);
if (sta->plink_state != NL80211_PLINK_LISTEN &&
sta->plink_state != NL80211_PLINK_BLOCKED) {
spin_unlock_bh(&sta->lock);
@@ -643,7 +673,7 @@ u32 mesh_plink_open(struct sta_info *sta)
changed = ieee80211_mps_local_status_update(sdata);
mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN,
- sta->sta.addr, llid, 0, 0);
+ sta->sta.addr, sta->llid, 0, 0);
return changed;
}
@@ -719,7 +749,7 @@ static u32 mesh_plink_fsm(struct ieee80211_sub_if_data *sdata,
break;
case OPN_ACPT:
sta->plink_state = NL80211_PLINK_OPN_RCVD;
- get_random_bytes(&sta->llid, 2);
+ sta->llid = mesh_get_new_llid(sdata);
mesh_plink_timer_set(sta,
mshcfg->dot11MeshRetryTimeout);