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 enum plink_event {
00035 PLINK_UNDEFINED,
00036 OPN_ACPT,
00037 OPN_RJCT,
00038 OPN_IGNR,
00039 CNF_ACPT,
00040 CNF_RJCT,
00041 CNF_IGNR,
00042 CLS_ACPT,
00043 CLS_IGNR
00044 };
00045
00046 static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
00047 enum ieee80211_self_protected_actioncode action,
00048 u8 *da, __le16 llid, __le16 plid, __le16 reason);
00049
00050 static inline
00051 void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata)
00052 {
00053 atomic_inc(&sdata->u.mesh.mshstats.estab_plinks);
00054 mesh_accept_plinks_update(sdata);
00055 }
00056
00057 static inline
00058 void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata)
00059 {
00060 atomic_dec(&sdata->u.mesh.mshstats.estab_plinks);
00061 mesh_accept_plinks_update(sdata);
00062 }
00063
00071 static inline void mesh_plink_fsm_restart(struct sta_info *sta)
00072 {
00073 sta->plink_state = NL80211_PLINK_LISTEN;
00074 sta->llid = sta->plid = sta->reason = 0;
00075 sta->plink_retries = 0;
00076 }
00077
00078
00079
00080
00081
00082 static struct sta_info *mesh_plink_alloc(struct ieee80211_sub_if_data *sdata,
00083 u8 *hw_addr, u32 rates)
00084 {
00085 struct ieee80211_local *local = sdata->local;
00086 struct sta_info *sta;
00087
00088 if (local->num_sta >= MESH_MAX_PLINKS)
00089 return NULL;
00090
00091 sta = sta_info_alloc(sdata, hw_addr, GFP_KERNEL);
00092 if (!sta)
00093 return NULL;
00094
00095 set_sta_flag(sta, WLAN_STA_AUTH);
00096 set_sta_flag(sta, WLAN_STA_AUTHORIZED);
00097 set_sta_flag(sta, WLAN_STA_WME);
00098 sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
00099 rate_control_rate_init(sta);
00100
00101 return sta;
00102 }
00103
00113 static bool __mesh_plink_deactivate(struct sta_info *sta)
00114 {
00115 struct ieee80211_sub_if_data *sdata = sta->sdata;
00116 bool deactivated = false;
00117
00118 if (sta->plink_state == NL80211_PLINK_ESTAB) {
00119 mesh_plink_dec_estab_count(sdata);
00120 deactivated = true;
00121 }
00122 sta->plink_state = NL80211_PLINK_BLOCKED;
00123 mesh_path_flush_by_nexthop(sta);
00124
00125 return deactivated;
00126 }
00127
00135 void mesh_plink_deactivate(struct sta_info *sta)
00136 {
00137 struct ieee80211_sub_if_data *sdata = sta->sdata;
00138 bool deactivated;
00139
00140 spin_lock_bh(&sta->lock);
00141 deactivated = __mesh_plink_deactivate(sta);
00142 sta->reason = cpu_to_le16(WLAN_REASON_MESH_PEER_CANCELED);
00143 mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
00144 sta->sta.addr, sta->llid, sta->plid,
00145 sta->reason);
00146 spin_unlock_bh(&sta->lock);
00147
00148 if (deactivated)
00149 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
00150 }
00151
00152 static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
00153 enum ieee80211_self_protected_actioncode action,
00154 u8 *da, __le16 llid, __le16 plid, __le16 reason) {
00155 struct ieee80211_local *local = sdata->local;
00156 struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 +
00157 sdata->u.mesh.ie_len);
00158 struct ieee80211_mgmt *mgmt;
00159 bool include_plid = false;
00160 int ie_len = 4;
00161 u16 peering_proto = 0;
00162 u8 *pos;
00163
00164 if (!skb)
00165 return -1;
00166 skb_reserve(skb, local->hw.extra_tx_headroom);
00167
00168
00169
00170 mgmt = (struct ieee80211_mgmt *)
00171 skb_put(skb, 25 + sizeof(mgmt->u.action.u.self_prot));
00172 memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.self_prot));
00173 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
00174 IEEE80211_STYPE_ACTION);
00175 memcpy(mgmt->da, da, ETH_ALEN);
00176 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
00177 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
00178 mgmt->u.action.category = WLAN_CATEGORY_SELF_PROTECTED;
00179 mgmt->u.action.u.self_prot.action_code = action;
00180
00181 if (action != WLAN_SP_MESH_PEERING_CLOSE) {
00182
00183 pos = skb_put(skb, 2);
00184 memset(pos, 0, 2);
00185 if (action == WLAN_SP_MESH_PEERING_CONFIRM) {
00186
00187 pos = skb_put(skb, 2);
00188 memcpy(pos + 2, &plid, 2);
00189 }
00190 if (ieee80211_add_srates_ie(&sdata->vif, skb) ||
00191 ieee80211_add_ext_srates_ie(&sdata->vif, skb) ||
00192 mesh_add_rsn_ie(skb, sdata) ||
00193 mesh_add_meshid_ie(skb, sdata) ||
00194 mesh_add_meshconf_ie(skb, sdata))
00195 return -1;
00196 } else {
00197 if (mesh_add_meshid_ie(skb, sdata))
00198 return -1;
00199 }
00200
00201
00202 switch (action) {
00203 case WLAN_SP_MESH_PEERING_OPEN:
00204 break;
00205 case WLAN_SP_MESH_PEERING_CONFIRM:
00206 ie_len += 2;
00207 include_plid = true;
00208 break;
00209 case WLAN_SP_MESH_PEERING_CLOSE:
00210 if (plid) {
00211 ie_len += 2;
00212 include_plid = true;
00213 }
00214 ie_len += 2;
00215 break;
00216 default:
00217 return -EINVAL;
00218 }
00219
00220 if (WARN_ON(skb_tailroom(skb) < 2 + ie_len))
00221 return -ENOMEM;
00222
00223 pos = skb_put(skb, 2 + ie_len);
00224 *pos++ = WLAN_EID_PEER_MGMT;
00225 *pos++ = ie_len;
00226 memcpy(pos, &peering_proto, 2);
00227 pos += 2;
00228 memcpy(pos, &llid, 2);
00229 pos += 2;
00230 if (include_plid) {
00231 memcpy(pos, &plid, 2);
00232 pos += 2;
00233 }
00234 if (action == WLAN_SP_MESH_PEERING_CLOSE) {
00235 memcpy(pos, &reason, 2);
00236 pos += 2;
00237 }
00238 if (mesh_add_vendor_ies(skb, sdata))
00239 return -1;
00240
00241 ieee80211_tx_skb(sdata, skb);
00242 return 0;
00243 }
00244
00245 void mesh_neighbour_update(u8 *hw_addr, u32 rates,
00246 struct ieee80211_sub_if_data *sdata,
00247 struct ieee802_11_elems *elems)
00248 {
00249 struct ieee80211_local *local = sdata->local;
00250 struct sta_info *sta;
00251
00252 rcu_read_lock();
00253
00254 sta = sta_info_get(sdata, hw_addr);
00255 if (!sta) {
00256 rcu_read_unlock();
00257
00258
00259 if (sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED)
00260 cfg80211_notify_new_peer_candidate(sdata->dev, hw_addr,
00261 elems->ie_start, elems->total_len,
00262 GFP_KERNEL);
00263 else
00264 sta = mesh_plink_alloc(sdata, hw_addr, rates);
00265 if (!sta)
00266 return;
00267 if (sta_info_insert_rcu(sta)) {
00268 rcu_read_unlock();
00269 return;
00270 }
00271 }
00272
00273 sta->last_rx = jiffies;
00274 sta->sta.supp_rates[local->hw.conf.channel->band] = rates;
00275 if (mesh_peer_accepts_plinks(elems) &&
00276 sta->plink_state == NL80211_PLINK_LISTEN &&
00277 sdata->u.mesh.accepting_plinks &&
00278 sdata->u.mesh.mshcfg.auto_open_plinks)
00279 mesh_plink_open(sta);
00280
00281 rcu_read_unlock();
00282 }
00283
00284 static void mesh_plink_timer(unsigned long data)
00285 {
00286 struct sta_info *sta;
00287 __le16 llid, plid, reason;
00288 struct ieee80211_sub_if_data *sdata;
00289
00290
00291
00292
00293
00294
00295 sta = (struct sta_info *) data;
00296
00297 if (sta->sdata->local->quiescing) {
00298 sta->plink_timer_was_running = true;
00299 return;
00300 }
00301
00302 spin_lock_bh(&sta->lock);
00303 if (sta->ignore_plink_timer) {
00304 sta->ignore_plink_timer = false;
00305 spin_unlock_bh(&sta->lock);
00306 return;
00307 }
00308 mpl_dbg("Mesh plink timer for %pM fired on state %d\n",
00309 sta->sta.addr, sta->plink_state);
00310 reason = 0;
00311 llid = sta->llid;
00312 plid = sta->plid;
00313 sdata = sta->sdata;
00314
00315 switch (sta->plink_state) {
00316 case NL80211_PLINK_OPN_RCVD:
00317 case NL80211_PLINK_OPN_SNT:
00318
00319 if (sta->plink_retries < dot11MeshMaxRetries(sdata)) {
00320 u32 rand;
00321 mpl_dbg("Mesh plink for %pM (retry, timeout): %d %d\n",
00322 sta->sta.addr, sta->plink_retries,
00323 sta->plink_timeout);
00324 get_random_bytes(&rand, sizeof(u32));
00325 sta->plink_timeout = sta->plink_timeout +
00326 rand % sta->plink_timeout;
00327 ++sta->plink_retries;
00328 mod_plink_timer(sta, sta->plink_timeout);
00329 spin_unlock_bh(&sta->lock);
00330 mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN,
00331 sta->sta.addr, llid, 0, 0);
00332 break;
00333 }
00334 reason = cpu_to_le16(WLAN_REASON_MESH_MAX_RETRIES);
00335
00336 case NL80211_PLINK_CNF_RCVD:
00337
00338 if (!reason)
00339 reason = cpu_to_le16(WLAN_REASON_MESH_CONFIRM_TIMEOUT);
00340 sta->plink_state = NL80211_PLINK_HOLDING;
00341 mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
00342 spin_unlock_bh(&sta->lock);
00343 mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
00344 sta->sta.addr, llid, plid, reason);
00345 break;
00346 case NL80211_PLINK_HOLDING:
00347
00348 del_timer(&sta->plink_timer);
00349 mesh_plink_fsm_restart(sta);
00350 spin_unlock_bh(&sta->lock);
00351 break;
00352 default:
00353 spin_unlock_bh(&sta->lock);
00354 break;
00355 }
00356 }
00357
00358 #ifdef CONFIG_PM
00359 void mesh_plink_quiesce(struct sta_info *sta)
00360 {
00361 if (del_timer_sync(&sta->plink_timer))
00362 sta->plink_timer_was_running = true;
00363 }
00364
00365 void mesh_plink_restart(struct sta_info *sta)
00366 {
00367 if (sta->plink_timer_was_running) {
00368 add_timer(&sta->plink_timer);
00369 sta->plink_timer_was_running = false;
00370 }
00371 }
00372 #endif
00373
00374 static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout)
00375 {
00376 sta->plink_timer.expires = jiffies + (HZ * timeout / 1000);
00377 sta->plink_timer.data = (unsigned long) sta;
00378 sta->plink_timer.function = mesh_plink_timer;
00379 sta->plink_timeout = timeout;
00380 add_timer(&sta->plink_timer);
00381 }
00382
00383 int mesh_plink_open(struct sta_info *sta)
00384 {
00385 __le16 llid;
00386 struct ieee80211_sub_if_data *sdata = sta->sdata;
00387
00388 if (!test_sta_flag(sta, WLAN_STA_AUTH))
00389 return -EPERM;
00390
00391 spin_lock_bh(&sta->lock);
00392 get_random_bytes(&llid, 2);
00393 sta->llid = llid;
00394 if (sta->plink_state != NL80211_PLINK_LISTEN) {
00395 spin_unlock_bh(&sta->lock);
00396 return -EBUSY;
00397 }
00398 sta->plink_state = NL80211_PLINK_OPN_SNT;
00399 mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata));
00400 spin_unlock_bh(&sta->lock);
00401 mpl_dbg("Mesh plink: starting establishment with %pM\n",
00402 sta->sta.addr);
00403
00404 return mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_OPEN,
00405 sta->sta.addr, llid, 0, 0);
00406 }
00407
00408 void mesh_plink_block(struct sta_info *sta)
00409 {
00410 struct ieee80211_sub_if_data *sdata = sta->sdata;
00411 bool deactivated;
00412
00413 spin_lock_bh(&sta->lock);
00414 deactivated = __mesh_plink_deactivate(sta);
00415 sta->plink_state = NL80211_PLINK_BLOCKED;
00416 spin_unlock_bh(&sta->lock);
00417
00418 if (deactivated)
00419 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
00420 }
00421
00422
00423 void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt,
00424 size_t len, struct ieee80211_rx_status *rx_status)
00425 {
00426 struct ieee80211_local *local = sdata->local;
00427 struct ieee802_11_elems elems;
00428 struct sta_info *sta;
00429 enum plink_event event;
00430 enum ieee80211_self_protected_actioncode ftype;
00431 size_t baselen;
00432 bool deactivated, matches_local = true;
00433 u8 ie_len;
00434 u8 *baseaddr;
00435 __le16 plid, llid, reason;
00436 #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG
00437 static const char *mplstates[] = {
00438 [NL80211_PLINK_LISTEN] = "LISTEN",
00439 [NL80211_PLINK_OPN_SNT] = "OPN-SNT",
00440 [NL80211_PLINK_OPN_RCVD] = "OPN-RCVD",
00441 [NL80211_PLINK_CNF_RCVD] = "CNF_RCVD",
00442 [NL80211_PLINK_ESTAB] = "ESTAB",
00443 [NL80211_PLINK_HOLDING] = "HOLDING",
00444 [NL80211_PLINK_BLOCKED] = "BLOCKED"
00445 };
00446 #endif
00447
00448
00449 if (len < IEEE80211_MIN_ACTION_SIZE + 3)
00450 return;
00451
00452 if (is_multicast_ether_addr(mgmt->da)) {
00453 mpl_dbg("Mesh plink: ignore frame from multicast address");
00454 return;
00455 }
00456
00457 baseaddr = mgmt->u.action.u.self_prot.variable;
00458 baselen = (u8 *) mgmt->u.action.u.self_prot.variable - (u8 *) mgmt;
00459 if (mgmt->u.action.u.self_prot.action_code ==
00460 WLAN_SP_MESH_PEERING_CONFIRM) {
00461 baseaddr += 4;
00462 baselen += 4;
00463 }
00464 ieee802_11_parse_elems(baseaddr, len - baselen, &elems);
00465 if (!elems.peering) {
00466 mpl_dbg("Mesh plink: missing necessary peer link ie\n");
00467 return;
00468 }
00469 if (elems.rsn_len &&
00470 sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) {
00471 mpl_dbg("Mesh plink: can't establish link with secure peer\n");
00472 return;
00473 }
00474
00475 ftype = mgmt->u.action.u.self_prot.action_code;
00476 ie_len = elems.peering_len;
00477 if ((ftype == WLAN_SP_MESH_PEERING_OPEN && ie_len != 4) ||
00478 (ftype == WLAN_SP_MESH_PEERING_CONFIRM && ie_len != 6) ||
00479 (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len != 6
00480 && ie_len != 8)) {
00481 mpl_dbg("Mesh plink: incorrect plink ie length %d %d\n",
00482 ftype, ie_len);
00483 return;
00484 }
00485
00486 if (ftype != WLAN_SP_MESH_PEERING_CLOSE &&
00487 (!elems.mesh_id || !elems.mesh_config)) {
00488 mpl_dbg("Mesh plink: missing necessary ie\n");
00489 return;
00490 }
00491
00492
00493
00494 memcpy(&plid, PLINK_GET_LLID(elems.peering), 2);
00495 if (ftype == WLAN_SP_MESH_PEERING_CONFIRM ||
00496 (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len == 8))
00497 memcpy(&llid, PLINK_GET_PLID(elems.peering), 2);
00498
00499 rcu_read_lock();
00500
00501 sta = sta_info_get(sdata, mgmt->sa);
00502 if (!sta && ftype != WLAN_SP_MESH_PEERING_OPEN) {
00503 mpl_dbg("Mesh plink: cls or cnf from unknown peer\n");
00504 rcu_read_unlock();
00505 return;
00506 }
00507
00508 if (sta && !test_sta_flag(sta, WLAN_STA_AUTH)) {
00509 mpl_dbg("Mesh plink: Action frame from non-authed peer\n");
00510 rcu_read_unlock();
00511 return;
00512 }
00513
00514 if (sta && sta->plink_state == NL80211_PLINK_BLOCKED) {
00515 rcu_read_unlock();
00516 return;
00517 }
00518
00519
00520 event = PLINK_UNDEFINED;
00521 if (ftype != WLAN_SP_MESH_PEERING_CLOSE &&
00522 (!mesh_matches_local(&elems, sdata))) {
00523 matches_local = false;
00524 switch (ftype) {
00525 case WLAN_SP_MESH_PEERING_OPEN:
00526 event = OPN_RJCT;
00527 break;
00528 case WLAN_SP_MESH_PEERING_CONFIRM:
00529 event = CNF_RJCT;
00530 break;
00531 default:
00532 break;
00533 }
00534 }
00535
00536 if (!sta && !matches_local) {
00537 rcu_read_unlock();
00538 reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
00539 llid = 0;
00540 mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
00541 mgmt->sa, llid, plid, reason);
00542 return;
00543 } else if (!sta) {
00544
00545 u32 rates;
00546
00547 rcu_read_unlock();
00548
00549 if (!mesh_plink_free_count(sdata)) {
00550 mpl_dbg("Mesh plink error: no more free plinks\n");
00551 return;
00552 }
00553
00554 rates = ieee80211_sta_get_rates(local, &elems, rx_status->band);
00555 sta = mesh_plink_alloc(sdata, mgmt->sa, rates);
00556 if (!sta) {
00557 mpl_dbg("Mesh plink error: plink table full\n");
00558 return;
00559 }
00560 if (sta_info_insert_rcu(sta)) {
00561 rcu_read_unlock();
00562 return;
00563 }
00564 event = OPN_ACPT;
00565 spin_lock_bh(&sta->lock);
00566 } else if (matches_local) {
00567 spin_lock_bh(&sta->lock);
00568 switch (ftype) {
00569 case WLAN_SP_MESH_PEERING_OPEN:
00570 if (!mesh_plink_free_count(sdata) ||
00571 (sta->plid && sta->plid != plid))
00572 event = OPN_IGNR;
00573 else
00574 event = OPN_ACPT;
00575 break;
00576 case WLAN_SP_MESH_PEERING_CONFIRM:
00577 if (!mesh_plink_free_count(sdata) ||
00578 (sta->llid != llid || sta->plid != plid))
00579 event = CNF_IGNR;
00580 else
00581 event = CNF_ACPT;
00582 break;
00583 case WLAN_SP_MESH_PEERING_CLOSE:
00584 if (sta->plink_state == NL80211_PLINK_ESTAB)
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594 event = CLS_ACPT;
00595 else if (sta->plid != plid)
00596 event = CLS_IGNR;
00597 else if (ie_len == 7 && sta->llid != llid)
00598 event = CLS_IGNR;
00599 else
00600 event = CLS_ACPT;
00601 break;
00602 default:
00603 mpl_dbg("Mesh plink: unknown frame subtype\n");
00604 spin_unlock_bh(&sta->lock);
00605 rcu_read_unlock();
00606 return;
00607 }
00608 } else {
00609 spin_lock_bh(&sta->lock);
00610 }
00611
00612 mpl_dbg("Mesh plink (peer, state, llid, plid, event): %pM %s %d %d %d\n",
00613 mgmt->sa, mplstates[sta->plink_state],
00614 le16_to_cpu(sta->llid), le16_to_cpu(sta->plid),
00615 event);
00616 reason = 0;
00617 switch (sta->plink_state) {
00618
00619 case NL80211_PLINK_LISTEN:
00620 switch (event) {
00621 case CLS_ACPT:
00622 mesh_plink_fsm_restart(sta);
00623 spin_unlock_bh(&sta->lock);
00624 break;
00625 case OPN_ACPT:
00626 sta->plink_state = NL80211_PLINK_OPN_RCVD;
00627 sta->plid = plid;
00628 get_random_bytes(&llid, 2);
00629 sta->llid = llid;
00630 mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata));
00631 spin_unlock_bh(&sta->lock);
00632 mesh_plink_frame_tx(sdata,
00633 WLAN_SP_MESH_PEERING_OPEN,
00634 sta->sta.addr, llid, 0, 0);
00635 mesh_plink_frame_tx(sdata,
00636 WLAN_SP_MESH_PEERING_CONFIRM,
00637 sta->sta.addr, llid, plid, 0);
00638 break;
00639 default:
00640 spin_unlock_bh(&sta->lock);
00641 break;
00642 }
00643 break;
00644
00645 case NL80211_PLINK_OPN_SNT:
00646 switch (event) {
00647 case OPN_RJCT:
00648 case CNF_RJCT:
00649 reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
00650 case CLS_ACPT:
00651 if (!reason)
00652 reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
00653 sta->reason = reason;
00654 sta->plink_state = NL80211_PLINK_HOLDING;
00655 if (!mod_plink_timer(sta,
00656 dot11MeshHoldingTimeout(sdata)))
00657 sta->ignore_plink_timer = true;
00658
00659 llid = sta->llid;
00660 spin_unlock_bh(&sta->lock);
00661 mesh_plink_frame_tx(sdata,
00662 WLAN_SP_MESH_PEERING_CLOSE,
00663 sta->sta.addr, llid, plid, reason);
00664 break;
00665 case OPN_ACPT:
00666
00667 sta->plink_state = NL80211_PLINK_OPN_RCVD;
00668 sta->plid = plid;
00669 llid = sta->llid;
00670 spin_unlock_bh(&sta->lock);
00671 mesh_plink_frame_tx(sdata,
00672 WLAN_SP_MESH_PEERING_CONFIRM,
00673 sta->sta.addr, llid, plid, 0);
00674 break;
00675 case CNF_ACPT:
00676 sta->plink_state = NL80211_PLINK_CNF_RCVD;
00677 if (!mod_plink_timer(sta,
00678 dot11MeshConfirmTimeout(sdata)))
00679 sta->ignore_plink_timer = true;
00680
00681 spin_unlock_bh(&sta->lock);
00682 break;
00683 default:
00684 spin_unlock_bh(&sta->lock);
00685 break;
00686 }
00687 break;
00688
00689 case NL80211_PLINK_OPN_RCVD:
00690 switch (event) {
00691 case OPN_RJCT:
00692 case CNF_RJCT:
00693 reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
00694 case CLS_ACPT:
00695 if (!reason)
00696 reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
00697 sta->reason = reason;
00698 sta->plink_state = NL80211_PLINK_HOLDING;
00699 if (!mod_plink_timer(sta,
00700 dot11MeshHoldingTimeout(sdata)))
00701 sta->ignore_plink_timer = true;
00702
00703 llid = sta->llid;
00704 spin_unlock_bh(&sta->lock);
00705 mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
00706 sta->sta.addr, llid, plid, reason);
00707 break;
00708 case OPN_ACPT:
00709 llid = sta->llid;
00710 spin_unlock_bh(&sta->lock);
00711 mesh_plink_frame_tx(sdata,
00712 WLAN_SP_MESH_PEERING_CONFIRM,
00713 sta->sta.addr, llid, plid, 0);
00714 break;
00715 case CNF_ACPT:
00716 del_timer(&sta->plink_timer);
00717 sta->plink_state = NL80211_PLINK_ESTAB;
00718 spin_unlock_bh(&sta->lock);
00719 mesh_plink_inc_estab_count(sdata);
00720 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
00721 mpl_dbg("Mesh plink with %pM ESTABLISHED\n",
00722 sta->sta.addr);
00723 break;
00724 default:
00725 spin_unlock_bh(&sta->lock);
00726 break;
00727 }
00728 break;
00729
00730 case NL80211_PLINK_CNF_RCVD:
00731 switch (event) {
00732 case OPN_RJCT:
00733 case CNF_RJCT:
00734 reason = cpu_to_le16(WLAN_REASON_MESH_CONFIG);
00735 case CLS_ACPT:
00736 if (!reason)
00737 reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
00738 sta->reason = reason;
00739 sta->plink_state = NL80211_PLINK_HOLDING;
00740 if (!mod_plink_timer(sta,
00741 dot11MeshHoldingTimeout(sdata)))
00742 sta->ignore_plink_timer = true;
00743
00744 llid = sta->llid;
00745 spin_unlock_bh(&sta->lock);
00746 mesh_plink_frame_tx(sdata,
00747 WLAN_SP_MESH_PEERING_CLOSE,
00748 sta->sta.addr, llid, plid, reason);
00749 break;
00750 case OPN_ACPT:
00751 del_timer(&sta->plink_timer);
00752 sta->plink_state = NL80211_PLINK_ESTAB;
00753 spin_unlock_bh(&sta->lock);
00754 mesh_plink_inc_estab_count(sdata);
00755 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
00756 mpl_dbg("Mesh plink with %pM ESTABLISHED\n",
00757 sta->sta.addr);
00758 mesh_plink_frame_tx(sdata,
00759 WLAN_SP_MESH_PEERING_CONFIRM,
00760 sta->sta.addr, llid, plid, 0);
00761 break;
00762 default:
00763 spin_unlock_bh(&sta->lock);
00764 break;
00765 }
00766 break;
00767
00768 case NL80211_PLINK_ESTAB:
00769 switch (event) {
00770 case CLS_ACPT:
00771 reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE);
00772 sta->reason = reason;
00773 deactivated = __mesh_plink_deactivate(sta);
00774 sta->plink_state = NL80211_PLINK_HOLDING;
00775 llid = sta->llid;
00776 mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata));
00777 spin_unlock_bh(&sta->lock);
00778 if (deactivated)
00779 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
00780 mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
00781 sta->sta.addr, llid, plid, reason);
00782 break;
00783 case OPN_ACPT:
00784 llid = sta->llid;
00785 spin_unlock_bh(&sta->lock);
00786 mesh_plink_frame_tx(sdata,
00787 WLAN_SP_MESH_PEERING_CONFIRM,
00788 sta->sta.addr, llid, plid, 0);
00789 break;
00790 default:
00791 spin_unlock_bh(&sta->lock);
00792 break;
00793 }
00794 break;
00795 case NL80211_PLINK_HOLDING:
00796 switch (event) {
00797 case CLS_ACPT:
00798 if (del_timer(&sta->plink_timer))
00799 sta->ignore_plink_timer = 1;
00800 mesh_plink_fsm_restart(sta);
00801 spin_unlock_bh(&sta->lock);
00802 break;
00803 case OPN_ACPT:
00804 case CNF_ACPT:
00805 case OPN_RJCT:
00806 case CNF_RJCT:
00807 llid = sta->llid;
00808 reason = sta->reason;
00809 spin_unlock_bh(&sta->lock);
00810 mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE,
00811 sta->sta.addr, llid, plid, reason);
00812 break;
00813 default:
00814 spin_unlock_bh(&sta->lock);
00815 }
00816 break;
00817 default:
00818
00819
00820
00821 spin_unlock_bh(&sta->lock);
00822 break;
00823 }
00824
00825 rcu_read_unlock();
00826 }