mesh_plink.c revision c3896d2ca4dd97be290f000cb1079ed759d28574
1/* 2 * Copyright (c) 2008 open80211s Ltd. 3 * Author: Luis Carlos Cobo <luisca@cozybit.com> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 */ 9 10#include "ieee80211_i.h" 11#include "ieee80211_rate.h" 12#include "mesh.h" 13#include <linux/random.h> 14 15#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG 16#define mpl_dbg(fmt, args...) printk(KERN_DEBUG fmt, ##args) 17#else 18#define mpl_dbg(fmt, args...) do { (void)(0); } while (0) 19#endif 20 21#define IEEE80211_FC(type, stype) cpu_to_le16(type | stype) 22#define PLINK_GET_FRAME_SUBTYPE(p) (p) 23#define PLINK_GET_LLID(p) (p + 1) 24#define PLINK_GET_PLID(p) (p + 3) 25 26#define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \ 27 jiffies + HZ * t / 1000)) 28 29/* Peer link cancel reasons, all subject to ANA approval */ 30#define MESH_LINK_CANCELLED 2 31#define MESH_MAX_NEIGHBORS 3 32#define MESH_CAPABILITY_POLICY_VIOLATION 4 33#define MESH_CLOSE_RCVD 5 34#define MESH_MAX_RETRIES 6 35#define MESH_CONFIRM_TIMEOUT 7 36#define MESH_SECURITY_ROLE_NEGOTIATION_DIFFERS 8 37#define MESH_SECURITY_AUTHENTICATION_IMPOSSIBLE 9 38#define MESH_SECURITY_FAILED_VERIFICATION 10 39 40#define dot11MeshMaxRetries(s) (s->u.sta.mshcfg.dot11MeshMaxRetries) 41#define dot11MeshRetryTimeout(s) (s->u.sta.mshcfg.dot11MeshRetryTimeout) 42#define dot11MeshConfirmTimeout(s) (s->u.sta.mshcfg.dot11MeshConfirmTimeout) 43#define dot11MeshHoldingTimeout(s) (s->u.sta.mshcfg.dot11MeshHoldingTimeout) 44#define dot11MeshMaxPeerLinks(s) (s->u.sta.mshcfg.dot11MeshMaxPeerLinks) 45 46enum plink_frame_type { 47 PLINK_OPEN = 0, 48 PLINK_CONFIRM, 49 PLINK_CLOSE 50}; 51 52enum plink_event { 53 PLINK_UNDEFINED, 54 OPN_ACPT, 55 OPN_RJCT, 56 OPN_IGNR, 57 CNF_ACPT, 58 CNF_RJCT, 59 CNF_IGNR, 60 CLS_ACPT, 61 CLS_IGNR 62}; 63 64static inline 65void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) 66{ 67 atomic_inc(&sdata->u.sta.mshstats.estab_plinks); 68 mesh_accept_plinks_update(sdata->dev); 69} 70 71static inline 72void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata) 73{ 74 atomic_dec(&sdata->u.sta.mshstats.estab_plinks); 75 mesh_accept_plinks_update(sdata->dev); 76} 77 78/** 79 * mesh_plink_fsm_restart - restart a mesh peer link finite state machine 80 * 81 * @sta: mes peer link to restart 82 * 83 * Locking: this function must be called holding sta->plink_lock 84 */ 85static inline void mesh_plink_fsm_restart(struct sta_info *sta) 86{ 87 sta->plink_state = LISTEN; 88 sta->llid = sta->plid = sta->reason = sta->plink_retries = 0; 89} 90 91/** 92 * mesh_plink_add - allocate and add a new mesh peer link 93 * 94 * @hw_addr: hardware address (ETH_ALEN length) 95 * @rates: rates the mesh peer supports 96 * @dev: local mesh interface 97 * 98 * The initial state of the new plink is set to LISTEN 99 * 100 * Returns: non-NULL on success, ERR_PTR() on error. 101 */ 102struct sta_info *mesh_plink_add(u8 *hw_addr, u64 rates, struct net_device *dev) 103{ 104 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 105 struct sta_info *sta; 106 107 if (memcmp(hw_addr, dev->dev_addr, ETH_ALEN) == 0) 108 /* never add ourselves as neighbours */ 109 return ERR_PTR(-EINVAL); 110 111 if (is_multicast_ether_addr(hw_addr)) 112 return ERR_PTR(-EINVAL); 113 114 if (local->num_sta >= MESH_MAX_PLINKS) 115 return ERR_PTR(-ENOSPC); 116 117 sta = sta_info_add(local, dev, hw_addr, GFP_KERNEL); 118 if (IS_ERR(sta)) 119 return sta; 120 121 sta->plink_state = LISTEN; 122 spin_lock_init(&sta->plink_lock); 123 init_timer(&sta->plink_timer); 124 sta->flags |= WLAN_STA_AUTHORIZED; 125 sta->supp_rates[local->hw.conf.channel->band] = rates; 126 rate_control_rate_init(sta, local); 127 128 mesh_accept_plinks_update(dev); 129 130 return sta; 131} 132 133/** 134 * mesh_plink_deactivate - deactivate mesh peer link 135 * 136 * @sta: mesh peer link to deactivate 137 * 138 * All mesh paths with this peer as next hop will be flushed 139 * 140 * Locking: the caller must hold sta->plink_lock 141 */ 142void mesh_plink_deactivate(struct sta_info *sta) 143{ 144 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); 145 if (sta->plink_state == ESTAB) 146 mesh_plink_dec_estab_count(sdata); 147 sta->plink_state = BLOCKED; 148 mesh_path_flush_by_nexthop(sta); 149} 150 151static int mesh_plink_frame_tx(struct net_device *dev, 152 enum plink_frame_type action, u8 *da, __le16 llid, __le16 plid, 153 __le16 reason) { 154 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 155 struct sk_buff *skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); 156 struct ieee80211_mgmt *mgmt; 157 bool include_plid = false; 158 u8 *pos; 159 int ie_len; 160 161 if (!skb) 162 return -1; 163 skb_reserve(skb, local->hw.extra_tx_headroom); 164 /* 25 is the size of the common mgmt part (24) plus the size of the 165 * common action part (1) 166 */ 167 mgmt = (struct ieee80211_mgmt *) 168 skb_put(skb, 25 + sizeof(mgmt->u.action.u.plink_action)); 169 memset(mgmt, 0, 25 + sizeof(mgmt->u.action.u.plink_action)); 170 mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT, 171 IEEE80211_STYPE_ACTION); 172 memcpy(mgmt->da, da, ETH_ALEN); 173 memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); 174 /* BSSID is left zeroed, wildcard value */ 175 mgmt->u.action.category = PLINK_CATEGORY; 176 mgmt->u.action.u.plink_action.action_code = action; 177 178 if (action == PLINK_CLOSE) 179 mgmt->u.action.u.plink_action.aux = reason; 180 else { 181 mgmt->u.action.u.plink_action.aux = cpu_to_le16(0x0); 182 if (action == PLINK_CONFIRM) { 183 pos = skb_put(skb, 4); 184 /* two-byte status code followed by two-byte AID */ 185 memset(pos, 0, 4); 186 } 187 mesh_mgmt_ies_add(skb, dev); 188 } 189 190 /* Add Peer Link Management element */ 191 switch (action) { 192 case PLINK_OPEN: 193 ie_len = 3; 194 break; 195 case PLINK_CONFIRM: 196 ie_len = 5; 197 include_plid = true; 198 break; 199 case PLINK_CLOSE: 200 default: 201 if (!plid) 202 ie_len = 5; 203 else { 204 ie_len = 7; 205 include_plid = true; 206 } 207 break; 208 } 209 210 pos = skb_put(skb, 2 + ie_len); 211 *pos++ = WLAN_EID_PEER_LINK; 212 *pos++ = ie_len; 213 *pos++ = action; 214 memcpy(pos, &llid, 2); 215 if (include_plid) { 216 pos += 2; 217 memcpy(pos, &plid, 2); 218 } 219 if (action == PLINK_CLOSE) { 220 pos += 2; 221 memcpy(pos, &reason, 2); 222 } 223 224 ieee80211_sta_tx(dev, skb, 0); 225 return 0; 226} 227 228void mesh_neighbour_update(u8 *hw_addr, u64 rates, struct net_device *dev, 229 bool peer_accepting_plinks) 230{ 231 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 232 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 233 struct sta_info *sta; 234 235 sta = sta_info_get(local, hw_addr); 236 if (!sta) { 237 sta = mesh_plink_add(hw_addr, rates, dev); 238 if (IS_ERR(sta)) 239 return; 240 } 241 242 sta->last_rx = jiffies; 243 sta->supp_rates[local->hw.conf.channel->band] = rates; 244 if (peer_accepting_plinks && sta->plink_state == LISTEN && 245 sdata->u.sta.accepting_plinks && 246 sdata->u.sta.mshcfg.auto_open_plinks) 247 mesh_plink_open(sta); 248 249 sta_info_put(sta); 250} 251 252static void mesh_plink_timer(unsigned long data) 253{ 254 struct sta_info *sta; 255 __le16 llid, plid, reason; 256 struct net_device *dev = NULL; 257 struct ieee80211_sub_if_data *sdata; 258#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG 259 DECLARE_MAC_BUF(mac); 260#endif 261 262 sta = (struct sta_info *) data; 263 264 spin_lock_bh(&sta->plink_lock); 265 if (sta->ignore_plink_timer) { 266 sta->ignore_plink_timer = false; 267 spin_unlock_bh(&sta->plink_lock); 268 return; 269 } 270 mpl_dbg("Mesh plink timer for %s fired on state %d\n", 271 print_mac(mac, sta->addr), sta->plink_state); 272 reason = 0; 273 llid = sta->llid; 274 plid = sta->plid; 275 dev = sta->dev; 276 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 277 278 switch (sta->plink_state) { 279 case OPN_RCVD: 280 case OPN_SNT: 281 /* retry timer */ 282 if (sta->plink_retries < dot11MeshMaxRetries(sdata)) { 283 u32 rand; 284 mpl_dbg("Mesh plink for %s (retry, timeout): %d %d\n", 285 print_mac(mac, sta->addr), 286 sta->plink_retries, sta->plink_timeout); 287 get_random_bytes(&rand, sizeof(u32)); 288 sta->plink_timeout = sta->plink_timeout + 289 rand % sta->plink_timeout; 290 ++sta->plink_retries; 291 if (!mod_plink_timer(sta, sta->plink_timeout)) 292 __sta_info_get(sta); 293 spin_unlock_bh(&sta->plink_lock); 294 mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid, 295 0, 0); 296 break; 297 } 298 reason = cpu_to_le16(MESH_MAX_RETRIES); 299 /* fall through on else */ 300 case CNF_RCVD: 301 /* confirm timer */ 302 if (!reason) 303 reason = cpu_to_le16(MESH_CONFIRM_TIMEOUT); 304 sta->plink_state = HOLDING; 305 if (!mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata))) 306 __sta_info_get(sta); 307 spin_unlock_bh(&sta->plink_lock); 308 mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, plid, 309 reason); 310 break; 311 case HOLDING: 312 /* holding timer */ 313 if (del_timer(&sta->plink_timer)) 314 sta_info_put(sta); 315 mesh_plink_fsm_restart(sta); 316 spin_unlock_bh(&sta->plink_lock); 317 break; 318 default: 319 spin_unlock_bh(&sta->plink_lock); 320 break; 321 } 322 323 sta_info_put(sta); 324} 325 326static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout) 327{ 328 sta->plink_timer.expires = jiffies + (HZ * timeout / 1000); 329 sta->plink_timer.data = (unsigned long) sta; 330 sta->plink_timer.function = mesh_plink_timer; 331 sta->plink_timeout = timeout; 332 __sta_info_get(sta); 333 add_timer(&sta->plink_timer); 334} 335 336int mesh_plink_open(struct sta_info *sta) 337{ 338 __le16 llid; 339 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); 340#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG 341 DECLARE_MAC_BUF(mac); 342#endif 343 344 spin_lock_bh(&sta->plink_lock); 345 get_random_bytes(&llid, 2); 346 sta->llid = llid; 347 if (sta->plink_state != LISTEN) { 348 spin_unlock_bh(&sta->plink_lock); 349 sta_info_put(sta); 350 return -EBUSY; 351 } 352 sta->plink_state = OPN_SNT; 353 mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); 354 spin_unlock_bh(&sta->plink_lock); 355 mpl_dbg("Mesh plink: starting establishment with %s\n", 356 print_mac(mac, sta->addr)); 357 358 return mesh_plink_frame_tx(sta->dev, PLINK_OPEN, sta->addr, llid, 0, 0); 359} 360 361void mesh_plink_block(struct sta_info *sta) 362{ 363#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG 364 DECLARE_MAC_BUF(mac); 365#endif 366 367 spin_lock_bh(&sta->plink_lock); 368 mesh_plink_deactivate(sta); 369 sta->plink_state = BLOCKED; 370 spin_unlock_bh(&sta->plink_lock); 371} 372 373int mesh_plink_close(struct sta_info *sta) 374{ 375 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(sta->dev); 376 int llid, plid, reason; 377#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG 378 DECLARE_MAC_BUF(mac); 379#endif 380 381 mpl_dbg("Mesh plink: closing link with %s\n", 382 print_mac(mac, sta->addr)); 383 spin_lock_bh(&sta->plink_lock); 384 sta->reason = cpu_to_le16(MESH_LINK_CANCELLED); 385 reason = sta->reason; 386 387 if (sta->plink_state == LISTEN || sta->plink_state == BLOCKED) { 388 mesh_plink_fsm_restart(sta); 389 spin_unlock_bh(&sta->plink_lock); 390 sta_info_put(sta); 391 return 0; 392 } else if (sta->plink_state == ESTAB) { 393 mesh_plink_deactivate(sta); 394 /* The timer should not be running */ 395 if (!mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata))) 396 __sta_info_get(sta); 397 } else if (!mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata))) 398 sta->ignore_plink_timer = true; 399 400 sta->plink_state = HOLDING; 401 llid = sta->llid; 402 plid = sta->plid; 403 spin_unlock_bh(&sta->plink_lock); 404 mesh_plink_frame_tx(sta->dev, PLINK_CLOSE, sta->addr, llid, plid, 405 reason); 406 return 0; 407} 408 409void mesh_rx_plink_frame(struct net_device *dev, struct ieee80211_mgmt *mgmt, 410 size_t len, struct ieee80211_rx_status *rx_status) 411{ 412 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); 413 struct ieee802_11_elems elems; 414 struct sta_info *sta; 415 enum plink_event event; 416 enum plink_frame_type ftype; 417 size_t baselen; 418 u8 ie_len; 419 u8 *baseaddr; 420 __le16 plid, llid, reason; 421#ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG 422 DECLARE_MAC_BUF(mac); 423#endif 424 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 425 426 if (is_multicast_ether_addr(mgmt->da)) { 427 mpl_dbg("Mesh plink: ignore frame from multicast address"); 428 return; 429 } 430 431 baseaddr = mgmt->u.action.u.plink_action.variable; 432 baselen = (u8 *) mgmt->u.action.u.plink_action.variable - (u8 *) mgmt; 433 if (mgmt->u.action.u.plink_action.action_code == PLINK_CONFIRM) { 434 baseaddr += 4; 435 baselen -= 4; 436 } 437 ieee802_11_parse_elems(baseaddr, len - baselen, &elems); 438 if (!elems.peer_link) { 439 mpl_dbg("Mesh plink: missing necessary peer link ie\n"); 440 return; 441 } 442 443 ftype = *((u8 *)PLINK_GET_FRAME_SUBTYPE(elems.peer_link)); 444 ie_len = elems.peer_link_len; 445 if ((ftype == PLINK_OPEN && ie_len != 3) || 446 (ftype == PLINK_CONFIRM && ie_len != 5) || 447 (ftype == PLINK_CLOSE && ie_len != 5 && ie_len != 7)) { 448 mpl_dbg("Mesh plink: incorrect plink ie length\n"); 449 return; 450 } 451 452 if (ftype != PLINK_CLOSE && (!elems.mesh_id || !elems.mesh_config)) { 453 mpl_dbg("Mesh plink: missing necessary ie\n"); 454 return; 455 } 456 /* Note the lines below are correct, the llid in the frame is the plid 457 * from the point of view of this host. 458 */ 459 memcpy(&plid, PLINK_GET_LLID(elems.peer_link), 2); 460 if (ftype == PLINK_CONFIRM || (ftype == PLINK_CLOSE && ie_len == 7)) 461 memcpy(&llid, PLINK_GET_PLID(elems.peer_link), 2); 462 463 sta = sta_info_get(local, mgmt->sa); 464 if (!sta && ftype != PLINK_OPEN) { 465 mpl_dbg("Mesh plink: cls or cnf from unknown peer\n"); 466 return; 467 } 468 469 if (sta && sta->plink_state == BLOCKED) { 470 sta_info_put(sta); 471 return; 472 } 473 474 /* Now we will figure out the appropriate event... */ 475 event = PLINK_UNDEFINED; 476 if (ftype != PLINK_CLOSE && (!mesh_matches_local(&elems, dev))) { 477 switch (ftype) { 478 case PLINK_OPEN: 479 event = OPN_RJCT; 480 break; 481 case PLINK_CONFIRM: 482 event = CNF_RJCT; 483 break; 484 case PLINK_CLOSE: 485 /* avoid warning */ 486 break; 487 } 488 spin_lock_bh(&sta->plink_lock); 489 } else if (!sta) { 490 /* ftype == PLINK_OPEN */ 491 u64 rates; 492 if (!mesh_plink_free_count(sdata)) { 493 mpl_dbg("Mesh plink error: no more free plinks\n"); 494 return; 495 } 496 497 rates = ieee80211_sta_get_rates(local, &elems, rx_status->band); 498 sta = mesh_plink_add(mgmt->sa, rates, dev); 499 if (IS_ERR(sta)) { 500 mpl_dbg("Mesh plink error: plink table full\n"); 501 return; 502 } 503 event = OPN_ACPT; 504 spin_lock_bh(&sta->plink_lock); 505 } else { 506 spin_lock_bh(&sta->plink_lock); 507 switch (ftype) { 508 case PLINK_OPEN: 509 if (!mesh_plink_free_count(sdata) || 510 (sta->plid && sta->plid != plid)) 511 event = OPN_IGNR; 512 else 513 event = OPN_ACPT; 514 break; 515 case PLINK_CONFIRM: 516 if (!mesh_plink_free_count(sdata) || 517 (sta->llid != llid || sta->plid != plid)) 518 event = CNF_IGNR; 519 else 520 event = CNF_ACPT; 521 break; 522 case PLINK_CLOSE: 523 if (sta->plink_state == ESTAB) 524 /* Do not check for llid or plid. This does not 525 * follow the standard but since multiple plinks 526 * per sta are not supported, it is necessary in 527 * order to avoid a livelock when MP A sees an 528 * establish peer link to MP B but MP B does not 529 * see it. This can be caused by a timeout in 530 * B's peer link establishment or B beign 531 * restarted. 532 */ 533 event = CLS_ACPT; 534 else if (sta->plid != plid) 535 event = CLS_IGNR; 536 else if (ie_len == 7 && sta->llid != llid) 537 event = CLS_IGNR; 538 else 539 event = CLS_ACPT; 540 break; 541 default: 542 mpl_dbg("Mesh plink: unknown frame subtype\n"); 543 spin_unlock_bh(&sta->plink_lock); 544 sta_info_put(sta); 545 return; 546 } 547 } 548 549 mpl_dbg("Mesh plink (peer, state, llid, plid, event): %s %d %d %d %d\n", 550 print_mac(mac, mgmt->sa), sta->plink_state, 551 __le16_to_cpu(sta->llid), __le16_to_cpu(sta->plid), 552 event); 553 reason = 0; 554 switch (sta->plink_state) { 555 /* spin_unlock as soon as state is updated at each case */ 556 case LISTEN: 557 switch (event) { 558 case CLS_ACPT: 559 mesh_plink_fsm_restart(sta); 560 spin_unlock_bh(&sta->plink_lock); 561 break; 562 case OPN_ACPT: 563 sta->plink_state = OPN_RCVD; 564 sta->plid = plid; 565 get_random_bytes(&llid, 2); 566 sta->llid = llid; 567 mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); 568 spin_unlock_bh(&sta->plink_lock); 569 mesh_plink_frame_tx(dev, PLINK_OPEN, sta->addr, llid, 570 0, 0); 571 mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, 572 llid, plid, 0); 573 break; 574 default: 575 spin_unlock_bh(&sta->plink_lock); 576 break; 577 } 578 break; 579 580 case OPN_SNT: 581 switch (event) { 582 case OPN_RJCT: 583 case CNF_RJCT: 584 reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION); 585 case CLS_ACPT: 586 if (!reason) 587 reason = cpu_to_le16(MESH_CLOSE_RCVD); 588 sta->reason = reason; 589 sta->plink_state = HOLDING; 590 if (!mod_plink_timer(sta, 591 dot11MeshHoldingTimeout(sdata))) 592 sta->ignore_plink_timer = true; 593 594 llid = sta->llid; 595 spin_unlock_bh(&sta->plink_lock); 596 mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, 597 plid, reason); 598 break; 599 case OPN_ACPT: 600 /* retry timer is left untouched */ 601 sta->plink_state = OPN_RCVD; 602 sta->plid = plid; 603 llid = sta->llid; 604 spin_unlock_bh(&sta->plink_lock); 605 mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, 606 plid, 0); 607 break; 608 case CNF_ACPT: 609 sta->plink_state = CNF_RCVD; 610 if (!mod_plink_timer(sta, 611 dot11MeshConfirmTimeout(sdata))) 612 sta->ignore_plink_timer = true; 613 614 spin_unlock_bh(&sta->plink_lock); 615 break; 616 default: 617 spin_unlock_bh(&sta->plink_lock); 618 break; 619 } 620 break; 621 622 case OPN_RCVD: 623 switch (event) { 624 case OPN_RJCT: 625 case CNF_RJCT: 626 reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION); 627 case CLS_ACPT: 628 if (!reason) 629 reason = cpu_to_le16(MESH_CLOSE_RCVD); 630 sta->reason = reason; 631 sta->plink_state = HOLDING; 632 if (!mod_plink_timer(sta, 633 dot11MeshHoldingTimeout(sdata))) 634 sta->ignore_plink_timer = true; 635 636 llid = sta->llid; 637 spin_unlock_bh(&sta->plink_lock); 638 mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, 639 plid, reason); 640 break; 641 case OPN_ACPT: 642 llid = sta->llid; 643 spin_unlock_bh(&sta->plink_lock); 644 mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, 645 plid, 0); 646 break; 647 case CNF_ACPT: 648 if (del_timer(&sta->plink_timer)) 649 sta_info_put(sta); 650 sta->plink_state = ESTAB; 651 mesh_plink_inc_estab_count(sdata); 652 spin_unlock_bh(&sta->plink_lock); 653 mpl_dbg("Mesh plink with %s ESTABLISHED\n", 654 print_mac(mac, sta->addr)); 655 break; 656 default: 657 spin_unlock_bh(&sta->plink_lock); 658 break; 659 } 660 break; 661 662 case CNF_RCVD: 663 switch (event) { 664 case OPN_RJCT: 665 case CNF_RJCT: 666 reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION); 667 case CLS_ACPT: 668 if (!reason) 669 reason = cpu_to_le16(MESH_CLOSE_RCVD); 670 sta->reason = reason; 671 sta->plink_state = HOLDING; 672 if (!mod_plink_timer(sta, 673 dot11MeshHoldingTimeout(sdata))) 674 sta->ignore_plink_timer = true; 675 676 llid = sta->llid; 677 spin_unlock_bh(&sta->plink_lock); 678 mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, 679 plid, reason); 680 case OPN_ACPT: 681 if (del_timer(&sta->plink_timer)) 682 sta_info_put(sta); 683 sta->plink_state = ESTAB; 684 mesh_plink_inc_estab_count(sdata); 685 spin_unlock_bh(&sta->plink_lock); 686 mpl_dbg("Mesh plink with %s ESTABLISHED\n", 687 print_mac(mac, sta->addr)); 688 mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, 689 plid, 0); 690 break; 691 default: 692 spin_unlock_bh(&sta->plink_lock); 693 break; 694 } 695 break; 696 697 case ESTAB: 698 switch (event) { 699 case CLS_ACPT: 700 reason = cpu_to_le16(MESH_CLOSE_RCVD); 701 sta->reason = reason; 702 mesh_plink_deactivate(sta); 703 sta->plink_state = HOLDING; 704 llid = sta->llid; 705 if (!mod_plink_timer(sta, 706 dot11MeshHoldingTimeout(sdata))) 707 __sta_info_get(sta); 708 spin_unlock_bh(&sta->plink_lock); 709 mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, 710 plid, reason); 711 break; 712 case OPN_ACPT: 713 llid = sta->llid; 714 spin_unlock_bh(&sta->plink_lock); 715 mesh_plink_frame_tx(dev, PLINK_CONFIRM, sta->addr, llid, 716 plid, 0); 717 break; 718 default: 719 spin_unlock_bh(&sta->plink_lock); 720 break; 721 } 722 break; 723 case HOLDING: 724 switch (event) { 725 case CLS_ACPT: 726 if (del_timer(&sta->plink_timer)) { 727 sta->ignore_plink_timer = 1; 728 sta_info_put(sta); 729 } 730 mesh_plink_fsm_restart(sta); 731 spin_unlock_bh(&sta->plink_lock); 732 break; 733 case OPN_ACPT: 734 case CNF_ACPT: 735 case OPN_RJCT: 736 case CNF_RJCT: 737 llid = sta->llid; 738 reason = sta->reason; 739 spin_unlock_bh(&sta->plink_lock); 740 mesh_plink_frame_tx(dev, PLINK_CLOSE, sta->addr, llid, 741 plid, reason); 742 break; 743 default: 744 spin_unlock_bh(&sta->plink_lock); 745 } 746 break; 747 default: 748 /* should not get here, BLOCKED is dealt with at the beggining 749 * of the function 750 */ 751 spin_unlock_bh(&sta->plink_lock); 752 break; 753 } 754 sta_info_put(sta); 755} 756