diff options
Diffstat (limited to 'net/mac80211/mesh_plink.c')
-rw-r--r-- | net/mac80211/mesh_plink.c | 35 |
1 files changed, 28 insertions, 7 deletions
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 44b53931ba5e..84e5b056af02 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -105,7 +105,7 @@ static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata, | |||
105 | if (!sta) | 105 | if (!sta) |
106 | return NULL; | 106 | return NULL; |
107 | 107 | ||
108 | sta->flags = WLAN_STA_AUTHORIZED; | 108 | sta->flags = WLAN_STA_AUTHORIZED | WLAN_STA_AUTH; |
109 | sta->sta.supp_rates[local->hw.conf.channel->band] = rates; | 109 | sta->sta.supp_rates[local->hw.conf.channel->band] = rates; |
110 | rate_control_rate_init(sta); | 110 | rate_control_rate_init(sta); |
111 | 111 | ||
@@ -161,7 +161,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
161 | __le16 reason) { | 161 | __le16 reason) { |
162 | struct ieee80211_local *local = sdata->local; | 162 | struct ieee80211_local *local = sdata->local; |
163 | struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 + | 163 | struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 + |
164 | sdata->u.mesh.vendor_ie_len); | 164 | sdata->u.mesh.ie_len); |
165 | struct ieee80211_mgmt *mgmt; | 165 | struct ieee80211_mgmt *mgmt; |
166 | bool include_plid = false; | 166 | bool include_plid = false; |
167 | static const u8 meshpeeringproto[] = { 0x00, 0x0F, 0xAC, 0x2A }; | 167 | static const u8 meshpeeringproto[] = { 0x00, 0x0F, 0xAC, 0x2A }; |
@@ -237,8 +237,9 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
237 | return 0; | 237 | return 0; |
238 | } | 238 | } |
239 | 239 | ||
240 | void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data *sdata, | 240 | void mesh_neighbour_update(u8 *hw_addr, u32 rates, |
241 | bool peer_accepting_plinks) | 241 | struct ieee80211_sub_if_data *sdata, |
242 | struct ieee802_11_elems *elems) | ||
242 | { | 243 | { |
243 | struct ieee80211_local *local = sdata->local; | 244 | struct ieee80211_local *local = sdata->local; |
244 | struct sta_info *sta; | 245 | struct sta_info *sta; |
@@ -248,8 +249,14 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data | |||
248 | sta = sta_info_get(sdata, hw_addr); | 249 | sta = sta_info_get(sdata, hw_addr); |
249 | if (!sta) { | 250 | if (!sta) { |
250 | rcu_read_unlock(); | 251 | rcu_read_unlock(); |
251 | 252 | /* Userspace handles peer allocation when security is enabled | |
252 | sta = mesh_plink_alloc(sdata, hw_addr, rates); | 253 | * */ |
254 | if (sdata->u.mesh.is_secure) | ||
255 | cfg80211_notify_new_peer_candidate(sdata->dev, hw_addr, | ||
256 | elems->ie_start, elems->total_len, | ||
257 | GFP_KERNEL); | ||
258 | else | ||
259 | sta = mesh_plink_alloc(sdata, hw_addr, rates); | ||
253 | if (!sta) | 260 | if (!sta) |
254 | return; | 261 | return; |
255 | if (sta_info_insert_rcu(sta)) { | 262 | if (sta_info_insert_rcu(sta)) { |
@@ -260,7 +267,8 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, struct ieee80211_sub_if_data | |||
260 | 267 | ||
261 | sta->last_rx = jiffies; | 268 | sta->last_rx = jiffies; |
262 | sta->sta.supp_rates[local->hw.conf.channel->band] = rates; | 269 | sta->sta.supp_rates[local->hw.conf.channel->band] = rates; |
263 | if (peer_accepting_plinks && sta->plink_state == PLINK_LISTEN && | 270 | if (mesh_peer_accepts_plinks(elems) && |
271 | sta->plink_state == PLINK_LISTEN && | ||
264 | sdata->u.mesh.accepting_plinks && | 272 | sdata->u.mesh.accepting_plinks && |
265 | sdata->u.mesh.mshcfg.auto_open_plinks) | 273 | sdata->u.mesh.mshcfg.auto_open_plinks) |
266 | mesh_plink_open(sta); | 274 | mesh_plink_open(sta); |
@@ -372,6 +380,9 @@ int mesh_plink_open(struct sta_info *sta) | |||
372 | __le16 llid; | 380 | __le16 llid; |
373 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 381 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
374 | 382 | ||
383 | if (!test_sta_flags(sta, WLAN_STA_AUTH)) | ||
384 | return -EPERM; | ||
385 | |||
375 | spin_lock_bh(&sta->lock); | 386 | spin_lock_bh(&sta->lock); |
376 | get_random_bytes(&llid, 2); | 387 | get_random_bytes(&llid, 2); |
377 | sta->llid = llid; | 388 | sta->llid = llid; |
@@ -449,6 +460,10 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
449 | mpl_dbg("Mesh plink: missing necessary peer link ie\n"); | 460 | mpl_dbg("Mesh plink: missing necessary peer link ie\n"); |
450 | return; | 461 | return; |
451 | } | 462 | } |
463 | if (elems.rsn_len && !sdata->u.mesh.is_secure) { | ||
464 | mpl_dbg("Mesh plink: can't establish link with secure peer\n"); | ||
465 | return; | ||
466 | } | ||
452 | 467 | ||
453 | ftype = mgmt->u.action.u.plink_action.action_code; | 468 | ftype = mgmt->u.action.u.plink_action.action_code; |
454 | ie_len = elems.peer_link_len; | 469 | ie_len = elems.peer_link_len; |
@@ -480,6 +495,12 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
480 | return; | 495 | return; |
481 | } | 496 | } |
482 | 497 | ||
498 | if (sta && !test_sta_flags(sta, WLAN_STA_AUTH)) { | ||
499 | mpl_dbg("Mesh plink: Action frame from non-authed peer\n"); | ||
500 | rcu_read_unlock(); | ||
501 | return; | ||
502 | } | ||
503 | |||
483 | if (sta && sta->plink_state == PLINK_BLOCKED) { | 504 | if (sta && sta->plink_state == PLINK_BLOCKED) { |
484 | rcu_read_unlock(); | 505 | rcu_read_unlock(); |
485 | return; | 506 | return; |