00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <linux/gfp.h>
00010 #include <linux/kernel.h>
00011 #include <linux/random.h>
00012 #include "ieee80211_i.h"
00013 #include "rate.h"
00014 #include "mesh.h"
00015
00016 #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
00017 #define mpl_dbg(fmt, args...) printk(KERN_DEBUG fmt, ##args)
00018 #else
00019 #define mpl_dbg(fmt, args...) do { (void)(0); } while (0)
00020 #endif
00021
00022 #define PLINK_GET_LLID(p) (p + 2)
00023 #define PLINK_GET_PLID(p) (p + 4)
00024
00025 #define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \
00026 jiffies + HZ * t / 1000))
00027
00028 #define dot11MeshMaxRetries(s) (s->u.mesh.mshcfg.dot11MeshMaxRetries)
00029 #define dot11MeshRetryTimeout(s) (s->u.mesh.mshcfg.dot11MeshRetryTimeout)
00030 #define dot11MeshConfirmTimeout(s) (s->u.mesh.mshcfg.dot11MeshConfirmTimeout)
00031 #define dot11MeshHoldingTimeout(s) (s->u.mesh.mshcfg.dot11MeshHoldingTimeout)
00032 #define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks)
00033
00034
00035 #define rssi_threshold_check(sta, sdata) \
00036 (sdata->u.mesh.mshcfg.rssi_threshold == 0 ||\
00037 (sta && (s8) -ewma_read(&sta->avg_signal) > \
00038 sdata->u.mesh.mshcfg.rssi_threshold))
00039
00040 enum plink_event {
00041 PLINK_UNDEFINED,
00042 OPN_ACPT,
00043 OPN_RJCT,
00044 OPN_IGNR,
00045 CNF_ACPT,
00046 CNF_RJCT,
00047 CNF_IGNR,
00048 CLS_ACPT,
00049 CLS_IGNR
00050 };
00051
00052 static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
00053 enum ieee80211_self_protected_actioncode action,
00054 u8 *da, __le16 llid, __le16 plid, __le16 reason);
00055
00056 static inline
00057 void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata)
00058 {
00059 atomic_inc(&sdata->u.mesh.mshstats.estab_plinks);
00060 mesh_accept_plinks_update(sdata);
00061 }
00062
00063 static inline
00064 void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata)
00065 {
00066 atomic_dec(&sdata->u.mesh.mshstats.estab_plinks);
00067 mesh_accept_plinks_update(sdata);
00068 }
00069
00077 static inline void mesh_plink_fsm_restart(struct sta_info *sta)
00078 {
00079 sta->plink_state = NL80211_PLINK_LISTEN;
00080 sta->llid = sta->plid = sta->reason = 0;
00081 sta->plink_retries = 0;
00082 }
00083
00084
00085
00086
00087 static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
00088 u8 *hw_addr)
00089 {
00090 struct sta_info *sta;
00091
00092 if (sdata->local->num_sta >= MESH_MAX_PLINKS)
00093 return NULL;
00094
00095 sta = sta_info_alloc(sdata, hw_addr, GFP_KERNEL);
00096 if (!sta)
00097 return NULL;
00098
00099 sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
00100 sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
00101 sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED);
00102
00103 set_sta_flag(sta, WLAN_STA_WME);
00104
00105 return sta;
00106 }
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118 static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata)
00119 {
00120 struct ieee80211_local *local = sdata->local;
00121 struct sta_info *sta;
00122 u32 changed = 0;
00123 u16 ht_opmode;
00124 bool non_ht_sta = false, ht20_sta = false;
00125
00126 if (local->_oper_channel_type == NL80211_CHAN_NO_HT)
00127 return 0;
00128
00129 rcu_read_lock();
00130 list_for_each_entry_rcu(sta, &local->sta_list, list) {
00131 if (sdata != sta->sdata ||
00132 sta->plink_state != NL80211_PLINK_ESTAB)
00133 continue;
00134
00135 switch (sta->ch_type) {
00136 case NL80211_CHAN_NO_HT:
00137 mpl_dbg("mesh_plink %pM: nonHT sta (%pM) is present",
00138 sdata->vif.addr, sta->sta.addr);
00139 non_ht_sta = true;
00140 goto out;
00141 case NL80211_CHAN_HT20:
00142 mpl_dbg("mesh_plink %pM: HT20 sta (%pM) is present",
00143 sdata->vif.addr, sta->sta.addr);
00144 ht20_sta = true;
00145 default:
00146 break;
00147 }
00148 }
00149 out:
00150 rcu_read_unlock();
00151
00152 if (non_ht_sta)
00153 ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED;
00154 else if (ht20_sta && local->_oper_channel_type > NL80211_CHAN_HT20)
00155 ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_20MHZ;
00156 else
00157 ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
00158
00159 if (sdata->vif.bss_conf.ht_operation_mode != ht_opmode) {
00160 sdata->vif.bss_conf.ht_operation_mode = ht_opmode;
00161 sdata->u.mesh.mshcfg.ht_opmode = ht_opmode;
00162 changed = BSS_CHANGED_HT;
00163 mpl_dbg("mesh_plink %pM: protection mode changed to %d",
00164 sdata->vif.addr, ht_opmode);
00165 }
00166
00167 return changed;
00168 }
00169
00179 static bool __mesh_plink_deactivate(struct sta_info *sta)
00180 {
00181 struct ieee80211_sub_if_data *sdata = sta->sdata;
00182 bool deactivated = false;
00183
00184 if (sta->plink_state == NL80211_PLINK_ESTAB) {
00185 mesh_plink_dec_estab_count(sdata);
00186 deactivated = true;
00187 }
00188 sta->plink_state = NL80211_PLINK_BLOCKED;
00189 mesh_path_flush_by_nexthop(sta);
00190
00191 return deactivated;
00192 }
00193
00201 void mesh_plink_deactivate(struct sta_info *sta)
00202 {
00203 struct ieee80211_sub_if_data *sdata = sta->sdata;
00204 bool deactivated;
00205
00206 spin_lock_bh(&sta->lock);
00207 deactivated = __mesh_plink_deactivate(sta);
00208 sta->reason = cpu_to_le16(WLAN_REASON_MESH_PEER_CANCELED);
00209 mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
00210 sta->sta.addr, sta->llid, sta->plid,
00211 sta->reason);
00212 spin_unlock_bh(&sta->lock);
00213
00214 if (deactivated)
00215 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
00216 }
00217
00218 static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
00219 enum ieee80211_self_protected_actioncode action,
00220 u8 *da, __le16 llid, __le16 plid, __le16 reason) {
00221 struct ieee80211_local *local = sdata->local;
00222 struct sk_buff *skb;
00223 struct ieee80211_mgmt *mgmt;
00224 bool include_plid = false;
00225 u16 peering_proto = 0;
00226 u8 *pos, ie_len = 4;
00227 int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.self_prot) +
00228 sizeof(mgmt->u.action.u.self_prot);
00229
00230 skb = dev_alloc_skb(local->tx_headroom +
00231 hdr_len +
00232 2 +
00233 2 +
00234 2 + 8 +
00235 2 + (IEEE80211_MAX_SUPP_RATES - 8) +
00236 2 + sdata->u.mesh.mesh_id_len +
00237 2 + sizeof(struct ieee80211_meshconf_ie) +
00238 2 + sizeof(struct ieee80211_ht_cap) +
00239 2 + sizeof(struct ieee80211_ht_operation) +
00240 2 + 8 +
00241 sdata->u.mesh.ie_len);
00242 if (!skb)
00243 return -1;
00244 skb_reserve(skb, local->tx_headroom);
00245 mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
00246 memset(mgmt, 0, hdr_len);
00247 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
00248 IEEE80211_STYPE_ACTION);
00249 memcpy(mgmt->da, da, ETH_ALEN);
00250 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
00251 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
00252 mgmt->u.action.category = WLAN_CATEGORY_SELF_PROTECTED;
00253 mgmt->u.action.u.self_prot.action_code = action;
00254
00255 if (action != WLAN_SP_MESH_PEERING_CLOSE) {
00256
00257 pos = skb_put(skb, 2);
00258 memset(pos, 0, 2);
00259 if (action == WLAN_SP_MESH_PEERING_CONFIRM) {
00260
00261 pos = skb_put(skb, 2);
00262 memcpy(pos + 2, &plid, 2);
00263 }
00264 if (ieee80211_add_srates_ie(&sdata->vif, skb, true) ||
00265 ieee80211_add_ext_srates_ie(&sdata->vif, skb, true) ||
00266 mesh_add_rsn_ie(skb, sdata) ||
00267 mesh_add_meshid_ie(skb, sdata) ||
00268 mesh_add_meshconf_ie(skb, sdata))
00269 return -1;
00270 } else {
00271 if (mesh_add_meshid_ie(skb, sdata))
00272 return -1;
00273 }
00274
00275
00276 switch (action) {
00277 case WLAN_SP_MESH_PEERING_OPEN:
00278 break;
00279 case WLAN_SP_MESH_PEERING_CONFIRM:
00280 ie_len += 2;
00281 include_plid = true;
00282 break;
00283 case WLAN_SP_MESH_PEERING_CLOSE:
00284 if (plid) {
00285 ie_len += 2;
00286 include_plid = true;
00287 }
00288 ie_len += 2;
00289 break;
00290 default:
00291 return -EINVAL;
00292 }
00293
00294 if (WARN_ON(skb_tailroom(skb) < 2 + ie_len))
00295 return -ENOMEM;
00296
00297 pos = skb_put(skb, 2 + ie_len);
00298 *pos++ = WLAN_EID_PEER_MGMT;
00299 *pos++ = ie_len;
00300 memcpy(pos, &peering_proto, 2);
00301 pos += 2;
00302 memcpy(pos, &llid, 2);
00303 pos += 2;
00304 if (include_plid) {
00305 memcpy(pos, &plid, 2);
00306 pos += 2;
00307 }
00308 if (action == WLAN_SP_MESH_PEERING_CLOSE) {
00309 memcpy(pos, &reason, 2);
00310 pos += 2;
00311 }
00312
00313 if (action != WLAN_SP_MESH_PEERING_CLOSE) {
00314 if (mesh_add_ht_cap_ie(skb, sdata) ||
00315 mesh_add_ht_oper_ie(skb, sdata))
00316 return -1;
00317 }
00318
00319 if (mesh_add_vendor_ies(skb, sdata))
00320 return -1;
00321
00322 ieee80211_tx_skb(sdata, skb);
00323 return 0;
00324 }
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata,
00335 u8 *addr,
00336 struct ieee802_11_elems *elems)
00337 {
00338 struct ieee80211_local *local = sdata->local;
00339 enum ieee80211_band band = local->oper_channel->band;
00340 struct ieee80211_supported_band *sband;
00341 u32 rates, basic_rates = 0;
00342 struct sta_info *sta;
00343 bool insert = false;
00344
00345 sband = local->hw.wiphy->bands[band];
00346 rates = ieee80211_sta_get_rates(local, elems, band, &basic_rates);
00347
00348 sta = sta_info_get(sdata, addr);
00349 if (!sta) {
00350
00351 if (sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED) {
00352 cfg80211_notify_new_peer_candidate(sdata->dev, addr,
00353 elems->ie_start,
00354 elems->total_len,
00355 GFP_ATOMIC);
00356 return NULL;
00357 }
00358
00359 sta = mesh_plink_alloc(sdata, addr);
00360 if (!sta)
00361 return NULL;
00362 insert = true;
00363 }
00364
00365 spin_lock_bh(&sta->lock);
00366 sta->last_rx = jiffies;
00367 sta->sta.supp_rates[band] = rates;
00368 if (elems->ht_cap_elem &&
00369 sdata->local->_oper_channel_type != NL80211_CHAN_NO_HT)
00370 ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
00371 elems->ht_cap_elem,
00372 &sta->sta.ht_cap);
00373 else
00374 memset(&sta->sta.ht_cap, 0, sizeof(sta->sta.ht_cap));
00375
00376 if (elems->ht_operation) {
00377 if (!(elems->ht_operation->ht_param &
00378 IEEE80211_HT_PARAM_CHAN_WIDTH_ANY))
00379 sta->sta.ht_cap.cap &=
00380 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
00381 sta->ch_type =
00382 ieee80211_ht_oper_to_channel_type(elems->ht_operation);
00383 }
00384
00385 rate_control_rate_init(sta);
00386 spin_unlock_bh(&sta->lock);
00387
00388 if (insert && sta_info_insert(sta))
00389 return NULL;
00390
00391 return sta;
00392 }
00393
00394 void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata,
00395 u8 *hw_addr,
00396 struct ieee802_11_elems *elems)
00397 {
00398 struct sta_info *sta;
00399
00400 rcu_read_lock();
00401 sta = mesh_peer_init(sdata, hw_addr, elems);
00402 if (!sta)
00403 goto out;
00404
00405 if (mesh_peer_accepts_plinks(elems) &&
00406 sta->plink_state == NL80211_PLINK_LISTEN &&
00407 sdata->u.mesh.accepting_plinks &&
00408 sdata->u.mesh.mshcfg.auto_open_plinks &&
00409 rssi_threshold_check(sta, sdata))
00410 mesh_plink_open(sta);
00411
00412 out:
00413 rcu_read_unlock();
00414 }
00415
00416 static void mesh_plink_timer(unsigned long data)
00417 {
00418 struct sta_info *sta;
00419 __le16 llid, plid, reason;
00420 struct ieee80211_sub_if_data *sdata;
00421
00422
00423
00424
00425
00426
00427 sta = (struct sta_info *) data;
00428
00429 if (sta->sdata->local->quiescing) {
00430 sta->plink_timer_was_running = true;
00431 return;
00432 }
00433
00434 spin_lock_bh(&sta->lock);
00435 if (sta->ignore_plink_timer) {
00436 sta->ignore_plink_timer = false;
00437 spin_unlock_bh(&sta->lock);
00438 return;
00439 }
00440 mpl_dbg("Mesh plink timer for %pM fired on state %d\n",
00441 sta->sta.addr, sta->plink_state);
00442 reason = 0;
00443 llid = sta->llid;
00444 plid = sta->plid;
00445 sdata = sta->sdata;
00446
00447 switch (sta->plink_state) {
00448 case NL80211_PLINK_OPN_RCVD:
00449 case NL80211_PLINK_OPN_SNT:
00450
00451 if (sta->plink_retries < dot11MeshMaxRetries(sdata)) {
00452 u32 rand;
00453 mpl_dbg("Mesh plink for %pM (retry, timeout): %d %d\n",
00454 sta->sta.addr, sta->plink_retries,
00455 sta->plink_timeout);
00456 get_random_bytes(&rand, sizeof(u32));
00457 sta->plink_timeout = sta->plink_timeout +
00458 rand % sta->plink_timeout;
00459 ++sta->plink_retries;
00460 mod_plink_timer(sta, sta->plink_timeout);
00461 spin_unlock_bh(&sta->lock);
00462 mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN,
00463 sta->sta.addr, llid, 0, 0);
00464 break;
00465 }
00466 reason = cpu_to_le16(WLAN_REASON_MESH_MAX_RETRIES);
00467
00468 case NL80211_PLINK_CNF_RCVD:
00469
00470 if (!reason)
00471 reason = cpu_to_le16(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
00472 sta->plink_state = NL80211_PLINK_HOLDING;
00473 mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
00474 spin_unlock_bh(&sta->lock);
00475 mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
00476 sta->sta.addr, llid, plid, reason);
00477 break;
00478 case NL80211_PLINK_HOLDING:
00479
00480 del_timer(&sta->plink_timer);
00481 mesh_plink_fsm_restart(sta);
00482 spin_unlock_bh(&sta->lock);
00483 break;
00484 default:
00485 spin_unlock_bh(&sta->lock);
00486 break;
00487 }
00488 }
00489
00490 #ifdef CONFIG_PM
00491 void mesh_plink_quiesce(struct sta_info *sta)
00492 {
00493 if (del_timer_sync(&sta->plink_timer))
00494 sta->plink_timer_was_running = true;
00495 }
00496
00497 void mesh_plink_restart(struct sta_info *sta)
00498 {
00499 if (sta->plink_timer_was_running) {
00500 add_timer(&sta->plink_timer);
00501 sta->plink_timer_was_running = false;
00502 }
00503 }
00504 #endif
00505
00506 static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout)
00507 {
00508 sta->plink_timer.expires = jiffies + (HZ * timeout / 1000);
00509 sta->plink_timer.data = (unsigned long) sta;
00510 sta->plink_timer.function = mesh_plink_timer;
00511 sta->plink_timeout = timeout;
00512 add_timer(&sta->plink_timer);
00513 }
00514
00515 int mesh_plink_open(struct sta_info *sta)
00516 {
00517 __le16 llid;
00518 struct ieee80211_sub_if_data *sdata = sta->sdata;
00519
00520 if (!test_sta_flag(sta, WLAN_STA_AUTH))
00521 return -EPERM;
00522
00523 spin_lock_bh(&sta->lock);
00524 get_random_bytes(&llid, 2);
00525 sta->llid = llid;
00526 if (sta->plink_state != NL80211_PLINK_LISTEN) {
00527 spin_unlock_bh(&sta->lock);
00528 return -EBUSY;
00529 }
00530 sta->plink_state = NL80211_PLINK_OPN_SNT;
00531 mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata));
00532 spin_unlock_bh(&sta->lock);
00533 mpl_dbg("Mesh plink: starting establishment with %pM\n",
00534 sta->sta.addr);
00535
00536 return mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN,
00537 sta->sta.addr, llid, 0, 0);
00538 }
00539
00540 void mesh_plink_block(struct sta_info *sta)
00541 {
00542 struct ieee80211_sub_if_data *sdata = sta->sdata;
00543 bool deactivated;
00544
00545 spin_lock_bh(&sta->lock);
00546 deactivated = __mesh_plink_deactivate(sta);
00547 sta->plink_state = NL80211_PLINK_BLOCKED;
00548 spin_unlock_bh(&sta->lock);
00549
00550 if (deactivated)
00551 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
00552 }
00553
00554
00555 void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt,
00556 size_t len, struct ieee80211_rx_status *rx_status)
00557 {
00558 struct ieee802_11_elems elems;
00559 struct sta_info *sta;
00560 enum plink_event event;
00561 enum ieee80211_self_protected_actioncode ftype;
00562 size_t baselen;
00563 bool matches_local = true;
00564 u8 ie_len;
00565 u8 *baseaddr;
00566 u32 changed = 0;
00567 __le16 plid, llid, reason;
00568 #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
00569 static const char *mplstates[] = {
00570 [NL80211_PLINK_LISTEN] = "LISTEN",
00571 [NL80211_PLINK_OPN_SNT] = "OPN-SNT",
00572 [NL80211_PLINK_OPN_RCVD] = "OPN-RCVD",
00573 [NL80211_PLINK_CNF_RCVD] = "CNF_RCVD",
00574 [NL80211_PLINK_ESTAB] = "ESTAB",
00575 [NL80211_PLINK_HOLDING] = "HOLDING",
00576 [NL80211_PLINK_BLOCKED] = "BLOCKED"
00577 };
00578 #endif
00579
00580
00581 if (len < IEEE80211_MIN_ACTION_SIZE + 3)
00582 return;
00583
00584 if (is_multicast_ether_addr(mgmt->da)) {
00585 mpl_dbg("Mesh plink: ignore frame from multicast address");
00586 return;
00587 }
00588
00589 baseaddr = mgmt->u.action.u.self_prot.variable;
00590 baselen = (u8 *) mgmt->u.action.u.self_prot.variable - (u8 *) mgmt;
00591 if (mgmt->u.action.u.self_prot.action_code ==
00592 WLAN_SP_MESH_PEERING_CONFIRM) {
00593 baseaddr += 4;
00594 baselen += 4;
00595 }
00596 ieee802_11_parse_elems(baseaddr, len - baselen, &elems);
00597 if (!elems.peering) {
00598 mpl_dbg("Mesh plink: missing necessary peer link ie\n");
00599 return;
00600 }
00601 if (elems.rsn_len &&
00602 sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) {
00603 mpl_dbg("Mesh plink: can't establish link with secure peer\n");
00604 return;
00605 }
00606
00607 ftype = mgmt->u.action.u.self_prot.action_code;
00608 ie_len = elems.peering_len;
00609 if ((ftype == WLAN_SP_MESH_PEERING_OPEN && ie_len != 4) ||
00610 (ftype == WLAN_SP_MESH_PEERING_CONFIRM && ie_len != 6) ||
00611 (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len != 6
00612 && ie_len != 8)) {
00613 mpl_dbg("Mesh plink: incorrect plink ie length %d %d\n",
00614 ftype, ie_len);
00615 return;
00616 }
00617
00618 if (ftype != WLAN_SP_MESH_PEERING_CLOSE &&
00619 (!elems.mesh_id || !elems.mesh_config)) {
00620 mpl_dbg("Mesh plink: missing necessary ie\n");
00621 return;
00622 }
00623
00624
00625
00626 memcpy(&plid, PLINK_GET_LLID(elems.peering), 2);
00627 if (ftype == WLAN_SP_MESH_PEERING_CONFIRM ||
00628 (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len == 8))
00629 memcpy(&llid, PLINK_GET_PLID(elems.peering), 2);
00630
00631 rcu_read_lock();
00632
00633 sta = sta_info_get(sdata, mgmt->sa);
00634 if (!sta && ftype != WLAN_SP_MESH_PEERING_OPEN) {
00635 mpl_dbg("Mesh plink: cls or cnf from unknown peer\n");
00636 rcu_read_unlock();
00637 return;
00638 }
00639
00640 if (ftype == WLAN_SP_MESH_PEERING_OPEN &&
00641 !rssi_threshold_check(sta, sdata)) {
00642 mpl_dbg("Mesh plink: %pM does not meet rssi threshold\n",
00643 mgmt->sa);
00644 rcu_read_unlock();
00645 return;
00646 }
00647
00648 if (sta && !test_sta_flag(sta, WLAN_STA_AUTH)) {
00649 mpl_dbg("Mesh plink: Action frame from non-authed peer\n");
00650 rcu_read_unlock();
00651 return;
00652 }
00653
00654 if (sta && sta->plink_state == NL80211_PLINK_BLOCKED) {
00655 rcu_read_unlock();
00656 return;
00657 }
00658
00659
00660 event = PLINK_UNDEFINED;
00661 if (ftype != WLAN_SP_MESH_PEERING_CLOSE &&
00662 !mesh_matches_local(sdata, &elems)) {
00663 matches_local = false;
00664 switch (ftype) {
00665 case WLAN_SP_MESH_PEERING_OPEN:
00666 event = OPN_RJCT;
00667 break;
00668 case WLAN_SP_MESH_PEERING_CONFIRM:
00669 event = CNF_RJCT;
00670 break;
00671 default:
00672 break;
00673 }
00674 }
00675
00676 if (!sta && !matches_local) {
00677 rcu_read_unlock();
00678 reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
00679 llid = 0;
00680 mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
00681 mgmt->sa, llid, plid, reason);
00682 return;
00683 } else if (!sta) {
00684
00685 if (!mesh_plink_free_count(sdata)) {
00686 mpl_dbg("Mesh plink error: no more free plinks\n");
00687 rcu_read_unlock();
00688 return;
00689 }
00690 event = OPN_ACPT;
00691 } else if (matches_local) {
00692 switch (ftype) {
00693 case WLAN_SP_MESH_PEERING_OPEN:
00694 if (!mesh_plink_free_count(sdata) ||
00695 (sta->plid && sta->plid != plid))
00696 event = OPN_IGNR;
00697 else
00698 event = OPN_ACPT;
00699 break;
00700 case WLAN_SP_MESH_PEERING_CONFIRM:
00701 if (!mesh_plink_free_count(sdata) ||
00702 (sta->llid != llid || sta->plid != plid))
00703 event = CNF_IGNR;
00704 else
00705 event = CNF_ACPT;
00706 break;
00707 case WLAN_SP_MESH_PEERING_CLOSE:
00708 if (sta->plink_state == NL80211_PLINK_ESTAB)
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718 event = CLS_ACPT;
00719 else if (sta->plid != plid)
00720 event = CLS_IGNR;
00721 else if (ie_len == 7 && sta->llid != llid)
00722 event = CLS_IGNR;
00723 else
00724 event = CLS_ACPT;
00725 break;
00726 default:
00727 mpl_dbg("Mesh plink: unknown frame subtype\n");
00728 rcu_read_unlock();
00729 return;
00730 }
00731 }
00732
00733 if (event == OPN_ACPT) {
00734
00735 sta = mesh_peer_init(sdata, mgmt->sa, &elems);
00736 if (!sta) {
00737 mpl_dbg("Mesh plink: failed to init peer!\n");
00738 rcu_read_unlock();
00739 return;
00740 }
00741 }
00742
00743 mpl_dbg("Mesh plink (peer, state, llid, plid, event): %pM %s %d %d %d\n",
00744 mgmt->sa, mplstates[sta->plink_state],
00745 le16_to_cpu(sta->llid), le16_to_cpu(sta->plid),
00746 event);
00747 reason = 0;
00748 spin_lock_bh(&sta->lock);
00749 switch (sta->plink_state) {
00750
00751 case NL80211_PLINK_LISTEN:
00752 switch (event) {
00753 case CLS_ACPT:
00754 mesh_plink_fsm_restart(sta);
00755 spin_unlock_bh(&sta->lock);
00756 break;
00757 case OPN_ACPT:
00758 sta->plink_state = NL80211_PLINK_OPN_RCVD;
00759 sta->plid = plid;
00760 get_random_bytes(&llid, 2);
00761 sta->llid = llid;
00762 mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata));
00763 spin_unlock_bh(&sta->lock);
00764 mesh_plink_frame_tx(sdata,
00765 WLAN_SP_MESH_PEERING_OPEN,
00766 sta->sta.addr, llid, 0, 0);
00767 mesh_plink_frame_tx(sdata,
00768 WLAN_SP_MESH_PEERING_CONFIRM,
00769 sta->sta.addr, llid, plid, 0);
00770 break;
00771 default:
00772 spin_unlock_bh(&sta->lock);
00773 break;
00774 }
00775 break;
00776
00777 case NL80211_PLINK_OPN_SNT:
00778 switch (event) {
00779 case OPN_RJCT:
00780 case CNF_RJCT:
00781 reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
00782 case CLS_ACPT:
00783 if (!reason)
00784 reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
00785 sta->reason = reason;
00786 sta->plink_state = NL80211_PLINK_HOLDING;
00787 if (!mod_plink_timer(sta,
00788 dot11MeshHoldingTimeout(sdata)))
00789 sta->ignore_plink_timer = true;
00790
00791 llid = sta->llid;
00792 spin_unlock_bh(&sta->lock);
00793 mesh_plink_frame_tx(sdata,
00794 WLAN_SP_MESH_PEERING_CLOSE,
00795 sta->sta.addr, llid, plid, reason);
00796 break;
00797 case OPN_ACPT:
00798
00799 sta->plink_state = NL80211_PLINK_OPN_RCVD;
00800 sta->plid = plid;
00801 llid = sta->llid;
00802 spin_unlock_bh(&sta->lock);
00803 mesh_plink_frame_tx(sdata,
00804 WLAN_SP_MESH_PEERING_CONFIRM,
00805 sta->sta.addr, llid, plid, 0);
00806 break;
00807 case CNF_ACPT:
00808 sta->plink_state = NL80211_PLINK_CNF_RCVD;
00809 if (!mod_plink_timer(sta,
00810 dot11MeshConfirmTimeout(sdata)))
00811 sta->ignore_plink_timer = true;
00812
00813 spin_unlock_bh(&sta->lock);
00814 break;
00815 default:
00816 spin_unlock_bh(&sta->lock);
00817 break;
00818 }
00819 break;
00820
00821 case NL80211_PLINK_OPN_RCVD:
00822 switch (event) {
00823 case OPN_RJCT:
00824 case CNF_RJCT:
00825 reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
00826 case CLS_ACPT:
00827 if (!reason)
00828 reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
00829 sta->reason = reason;
00830 sta->plink_state = NL80211_PLINK_HOLDING;
00831 if (!mod_plink_timer(sta,
00832 dot11MeshHoldingTimeout(sdata)))
00833 sta->ignore_plink_timer = true;
00834
00835 llid = sta->llid;
00836 spin_unlock_bh(&sta->lock);
00837 mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
00838 sta->sta.addr, llid, plid, reason);
00839 break;
00840 case OPN_ACPT:
00841 llid = sta->llid;
00842 spin_unlock_bh(&sta->lock);
00843 mesh_plink_frame_tx(sdata,
00844 WLAN_SP_MESH_PEERING_CONFIRM,
00845 sta->sta.addr, llid, plid, 0);
00846 break;
00847 case CNF_ACPT:
00848 del_timer(&sta->plink_timer);
00849 sta->plink_state = NL80211_PLINK_ESTAB;
00850 spin_unlock_bh(&sta->lock);
00851 mesh_plink_inc_estab_count(sdata);
00852 changed |= mesh_set_ht_prot_mode(sdata);
00853 changed |= BSS_CHANGED_BEACON;
00854 mpl_dbg("Mesh plink with %pM ESTABLISHED\n",
00855 sta->sta.addr);
00856 break;
00857 default:
00858 spin_unlock_bh(&sta->lock);
00859 break;
00860 }
00861 break;
00862
00863 case NL80211_PLINK_CNF_RCVD:
00864 switch (event) {
00865 case OPN_RJCT:
00866 case CNF_RJCT:
00867 reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
00868 case CLS_ACPT:
00869 if (!reason)
00870 reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
00871 sta->reason = reason;
00872 sta->plink_state = NL80211_PLINK_HOLDING;
00873 if (!mod_plink_timer(sta,
00874 dot11MeshHoldingTimeout(sdata)))
00875 sta->ignore_plink_timer = true;
00876
00877 llid = sta->llid;
00878 spin_unlock_bh(&sta->lock);
00879 mesh_plink_frame_tx(sdata,
00880 WLAN_SP_MESH_PEERING_CLOSE,
00881 sta->sta.addr, llid, plid, reason);
00882 break;
00883 case OPN_ACPT:
00884 del_timer(&sta->plink_timer);
00885 sta->plink_state = NL80211_PLINK_ESTAB;
00886 spin_unlock_bh(&sta->lock);
00887 mesh_plink_inc_estab_count(sdata);
00888 changed |= mesh_set_ht_prot_mode(sdata);
00889 changed |= BSS_CHANGED_BEACON;
00890 mpl_dbg("Mesh plink with %pM ESTABLISHED\n",
00891 sta->sta.addr);
00892 mesh_plink_frame_tx(sdata,
00893 WLAN_SP_MESH_PEERING_CONFIRM,
00894 sta->sta.addr, llid, plid, 0);
00895 break;
00896 default:
00897 spin_unlock_bh(&sta->lock);
00898 break;
00899 }
00900 break;
00901
00902 case NL80211_PLINK_ESTAB:
00903 switch (event) {
00904 case CLS_ACPT:
00905 reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
00906 sta->reason = reason;
00907 __mesh_plink_deactivate(sta);
00908 sta->plink_state = NL80211_PLINK_HOLDING;
00909 llid = sta->llid;
00910 mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
00911 spin_unlock_bh(&sta->lock);
00912 changed |= mesh_set_ht_prot_mode(sdata);
00913 changed |= BSS_CHANGED_BEACON;
00914 mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
00915 sta->sta.addr, llid, plid, reason);
00916 break;
00917 case OPN_ACPT:
00918 llid = sta->llid;
00919 spin_unlock_bh(&sta->lock);
00920 mesh_plink_frame_tx(sdata,
00921 WLAN_SP_MESH_PEERING_CONFIRM,
00922 sta->sta.addr, llid, plid, 0);
00923 break;
00924 default:
00925 spin_unlock_bh(&sta->lock);
00926 break;
00927 }
00928 break;
00929 case NL80211_PLINK_HOLDING:
00930 switch (event) {
00931 case CLS_ACPT:
00932 if (del_timer(&sta->plink_timer))
00933 sta->ignore_plink_timer = 1;
00934 mesh_plink_fsm_restart(sta);
00935 spin_unlock_bh(&sta->lock);
00936 break;
00937 case OPN_ACPT:
00938 case CNF_ACPT:
00939 case OPN_RJCT:
00940 case CNF_RJCT:
00941 llid = sta->llid;
00942 reason = sta->reason;
00943 spin_unlock_bh(&sta->lock);
00944 mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
00945 sta->sta.addr, llid, plid, reason);
00946 break;
00947 default:
00948 spin_unlock_bh(&sta->lock);
00949 }
00950 break;
00951 default:
00952
00953
00954
00955 spin_unlock_bh(&sta->lock);
00956 break;
00957 }
00958
00959 rcu_read_unlock();
00960
00961 if (changed)
00962 ieee80211_bss_info_change_notify(sdata, changed);
00963 }