mac80211: mesh peer link implementation
[safe/jmp/linux-2.6] / net / mac80211 / mesh_plink.c
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
46 enum plink_frame_type {
47         PLINK_OPEN = 0,
48         PLINK_CONFIRM,
49         PLINK_CLOSE
50 };
51
52 enum 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
64 static inline
65 void 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
71 static inline
72 void 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  */
85 static 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  */
102 struct 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  */
142 void 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
151 static 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
228 void 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
252 static 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
326 static 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
336 int 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
361 void 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
373 int 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
409 void 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 }