Merge branch 'vendor/TCPDUMP' and update build for the update.
[dragonfly.git] / sys / netproto / 802_11 / wlan / ieee80211_proto.c
1 /*
2  * Copyright (c) 2001 Atsushi Onoe
3  * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * Alternatively, this software may be distributed under the terms of the
18  * GNU General Public License ("GPL") version 2 as published by the Free
19  * Software Foundation.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * $FreeBSD: src/sys/net80211/ieee80211_proto.c,v 1.17.2.9 2006/03/13 03:10:31 sam Exp $
33  * $DragonFly: src/sys/netproto/802_11/wlan/ieee80211_proto.c,v 1.12 2007/04/26 12:59:14 sephe Exp $
34  */
35
36 /*
37  * IEEE 802.11 protocol support.
38  */
39
40 #include "opt_inet.h"
41
42 #include <sys/param.h>
43 #include <sys/kernel.h>
44 #include <sys/systm.h> 
45 #include <sys/serialize.h>
46  
47 #include <sys/socket.h>
48
49 #include <net/if.h>
50 #include <net/if_arp.h>
51 #include <net/if_media.h>
52 #include <net/ethernet.h>               /* XXX for ether_sprintf */
53
54 #include <netproto/802_11/ieee80211_var.h>
55
56 /* XXX tunables */
57 #define AGGRESSIVE_MODE_SWITCH_HYSTERESIS       3       /* pkts / 100ms */
58 #define HIGH_PRI_SWITCH_THRESH                  10      /* pkts / 100ms */
59
60 #define IEEE80211_RATE2MBS(r)   (((r) & IEEE80211_RATE_VAL) / 2)
61
62 const char *ieee80211_mgt_subtype_name[] = IEEE80211_MGT_SUBTYPE_NAMES;
63 const char *ieee80211_ctl_subtype_name[] = IEEE80211_CTL_SUBTYPE_NAMES;
64 const char *ieee80211_state_name[IEEE80211_S_MAX] = {
65         "INIT",         /* IEEE80211_S_INIT */
66         "SCAN",         /* IEEE80211_S_SCAN */
67         "AUTH",         /* IEEE80211_S_AUTH */
68         "ASSOC",        /* IEEE80211_S_ASSOC */
69         "RUN"           /* IEEE80211_S_RUN */
70 };
71 const char *ieee80211_wme_acnames[] = {
72         "WME_AC_BE",
73         "WME_AC_BK",
74         "WME_AC_VI",
75         "WME_AC_VO",
76         "WME_UPSD",
77 };
78
79 static int ieee80211_newstate(struct ieee80211com *, enum ieee80211_state, int);
80
81 void
82 ieee80211_proto_attach(struct ieee80211com *ic)
83 {
84         struct ifnet *ifp = ic->ic_ifp;
85
86         /* XXX room for crypto  */
87         ifp->if_hdrlen = sizeof(struct ieee80211_qosframe_addr4);
88
89         ic->ic_rtsthreshold = IEEE80211_RTS_DEFAULT;
90         ic->ic_fragthreshold = IEEE80211_FRAG_DEFAULT;
91         ic->ic_fixed_rate = IEEE80211_FIXED_RATE_NONE;
92         ic->ic_bmiss_max = IEEE80211_BMISS_MAX;
93         callout_init(&ic->ic_swbmiss);
94         ic->ic_mcast_rate = IEEE80211_MCAST_RATE_DEFAULT;
95         ic->ic_protmode = IEEE80211_PROT_CTSONLY;
96         ic->ic_roaming = IEEE80211_ROAMING_AUTO;
97
98         ic->ic_wme.wme_hipri_switch_hysteresis =
99                 AGGRESSIVE_MODE_SWITCH_HYSTERESIS;
100
101         /* protocol state change handler */
102         ic->ic_newstate = ieee80211_newstate;
103
104         /* initialize management frame handlers */
105         ic->ic_recv_mgmt = ieee80211_recv_mgmt;
106         ic->ic_send_mgmt = ieee80211_send_mgmt;
107 }
108
109 void
110 ieee80211_proto_detach(struct ieee80211com *ic)
111 {
112
113         /*
114          * This should not be needed as we detach when reseting
115          * the state but be conservative here since the
116          * authenticator may do things like spawn kernel threads.
117          */
118         if (ic->ic_auth->ia_detach)
119                 ic->ic_auth->ia_detach(ic);
120
121         ieee80211_drain_mgtq(&ic->ic_mgtq);
122
123         /*
124          * Detach any ACL'ator.
125          */
126         if (ic->ic_acl != NULL)
127                 ic->ic_acl->iac_detach(ic);
128 }
129
130 /*
131  * Simple-minded authenticator module support.
132  */
133
134 #define IEEE80211_AUTH_MAX      (IEEE80211_AUTH_WPA+1)
135 /* XXX well-known names */
136 static const char *auth_modnames[IEEE80211_AUTH_MAX] = {
137         "wlan_internal",        /* IEEE80211_AUTH_NONE */
138         "wlan_internal",        /* IEEE80211_AUTH_OPEN */
139         "wlan_internal",        /* IEEE80211_AUTH_SHARED */
140         "wlan_xauth",           /* IEEE80211_AUTH_8021X  */
141         "wlan_internal",        /* IEEE80211_AUTH_AUTO */
142         "wlan_xauth",           /* IEEE80211_AUTH_WPA */
143 };
144 static const struct ieee80211_authenticator *authenticators[IEEE80211_AUTH_MAX];
145
146 static const struct ieee80211_authenticator auth_internal = {
147         .ia_name                = "wlan_internal",
148         .ia_attach              = NULL,
149         .ia_detach              = NULL,
150         .ia_node_join           = NULL,
151         .ia_node_leave          = NULL,
152 };
153
154 /*
155  * Setup internal authenticators once; they are never unregistered.
156  */
157 static void
158 ieee80211_auth_setup(void)
159 {
160         ieee80211_authenticator_register(IEEE80211_AUTH_OPEN, &auth_internal);
161         ieee80211_authenticator_register(IEEE80211_AUTH_SHARED, &auth_internal);
162         ieee80211_authenticator_register(IEEE80211_AUTH_AUTO, &auth_internal);
163 }
164 SYSINIT(wlan_auth, SI_SUB_DRIVERS, SI_ORDER_FIRST, ieee80211_auth_setup, NULL);
165
166 const struct ieee80211_authenticator *
167 ieee80211_authenticator_get(int auth)
168 {
169         if (auth >= IEEE80211_AUTH_MAX)
170                 return NULL;
171         if (authenticators[auth] == NULL)
172                 ieee80211_load_module(auth_modnames[auth]);
173         return authenticators[auth];
174 }
175
176 void
177 ieee80211_authenticator_register(int type,
178         const struct ieee80211_authenticator *auth)
179 {
180         if (type >= IEEE80211_AUTH_MAX)
181                 return;
182         authenticators[type] = auth;
183 }
184
185 void
186 ieee80211_authenticator_unregister(int type)
187 {
188
189         if (type >= IEEE80211_AUTH_MAX)
190                 return;
191         authenticators[type] = NULL;
192 }
193
194 /*
195  * Very simple-minded ACL module support.
196  */
197 /* XXX just one for now */
198 static  const struct ieee80211_aclator *acl = NULL;
199
200 void
201 ieee80211_aclator_register(const struct ieee80211_aclator *iac)
202 {
203         kprintf("wlan: %s acl policy registered\n", iac->iac_name);
204         acl = iac;
205 }
206
207 void
208 ieee80211_aclator_unregister(const struct ieee80211_aclator *iac)
209 {
210         if (acl == iac)
211                 acl = NULL;
212         kprintf("wlan: %s acl policy unregistered\n", iac->iac_name);
213 }
214
215 const struct ieee80211_aclator *
216 ieee80211_aclator_get(const char *name)
217 {
218         if (acl == NULL)
219                 ieee80211_load_module("wlan_acl");
220         return acl != NULL && strcmp(acl->iac_name, name) == 0 ? acl : NULL;
221 }
222
223 void
224 ieee80211_print_essid(const uint8_t *essid, int len)
225 {
226         const uint8_t *p; 
227         int i;
228
229         if (len > IEEE80211_NWID_LEN)
230                 len = IEEE80211_NWID_LEN;
231         /* determine printable or not */
232         for (i = 0, p = essid; i < len; i++, p++) {
233                 if (*p < ' ' || *p > 0x7e)
234                         break;
235         }
236         if (i == len) {
237                 kprintf("\"");
238                 for (i = 0, p = essid; i < len; i++, p++)
239                         kprintf("%c", *p);
240                 kprintf("\"");
241         } else {
242                 kprintf("0x");
243                 for (i = 0, p = essid; i < len; i++, p++)
244                         kprintf("%02x", *p);
245         }
246 }
247
248 void
249 ieee80211_print_rateset(const struct ieee80211_rateset *rs)
250 {
251         int i;
252
253         for (i = 0; i < rs->rs_nrates; ++i) {
254                 kprintf("%d%s ", IEEE80211_RS_RATE(rs, i),
255                        (rs->rs_rates[i] & IEEE80211_RATE_BASIC) ?  "*" : "");
256         }
257 }
258
259 void
260 ieee80211_dump_pkt(const uint8_t *buf, int len, int rate, int rssi)
261 {
262         const struct ieee80211_frame *wh;
263         int i;
264
265         wh = (const struct ieee80211_frame *)buf;
266         switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
267         case IEEE80211_FC1_DIR_NODS:
268                 kprintf("NODS %6D", wh->i_addr2, ":");
269                 kprintf("->%6D", wh->i_addr1, ":");
270                 kprintf("(%6D)", wh->i_addr3, ":");
271                 break;
272         case IEEE80211_FC1_DIR_TODS:
273                 kprintf("TODS %6D", wh->i_addr2, ":");
274                 kprintf("->%6D", wh->i_addr3, ":");
275                 kprintf("(%6D)", wh->i_addr1, ":");
276                 break;
277         case IEEE80211_FC1_DIR_FROMDS:
278                 kprintf("FRDS %6D", wh->i_addr3, ":");
279                 kprintf("->%6D", wh->i_addr1, ":");
280                 kprintf("(%6D)", wh->i_addr2, ":");
281                 break;
282         case IEEE80211_FC1_DIR_DSTODS:
283                 kprintf("DSDS %6D", (const uint8_t *)&wh[1], ":");
284                 kprintf("->%6D", wh->i_addr3, ":");
285                 kprintf("(%6D", wh->i_addr2, ":");
286                 kprintf("->%6D)", wh->i_addr1, ":");
287                 break;
288         }
289         switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
290         case IEEE80211_FC0_TYPE_DATA:
291                 kprintf(" data");
292                 break;
293         case IEEE80211_FC0_TYPE_MGT:
294                 kprintf(" %s", ieee80211_mgt_subtype_name[
295                     (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK)
296                     >> IEEE80211_FC0_SUBTYPE_SHIFT]);
297                 break;
298         default:
299                 kprintf(" type#%d", wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK);
300                 break;
301         }
302         if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
303                 int i;
304                 kprintf(" WEP [IV");
305                 for (i = 0; i < IEEE80211_WEP_IVLEN; i++)
306                         kprintf(" %.02x", buf[sizeof(*wh)+i]);
307                 kprintf(" KID %u]", buf[sizeof(*wh)+i] >> 6);
308         }
309         if (rate >= 0)
310                 kprintf(" %dM", rate / 2);
311         if (rssi >= 0)
312                 kprintf(" +%d", rssi);
313         kprintf("\n");
314         if (len > 0) {
315                 for (i = 0; i < len; i++) {
316                         if ((i & 1) == 0)
317                                 kprintf(" ");
318                         kprintf("%02x", buf[i]);
319                 }
320                 kprintf("\n");
321         }
322 }
323
324 int
325 ieee80211_fix_rate(struct ieee80211_node *ni, int flags, int join)
326 {
327 #define RV(v)   ((v) & IEEE80211_RATE_VAL)
328         struct ieee80211com *ic = ni->ni_ic;
329         int i, j, ignore, error, nbasicrates;
330         int okrate, badrate, fixedrate;
331         const struct ieee80211_rateset *srs;
332         struct ieee80211_rateset *nrs;
333         uint8_t r;
334
335         /*
336          * If the fixed rate check was requested but no
337          * fixed has been defined then just remove it.
338          */
339         if ((flags & IEEE80211_F_DOFRATE) &&
340             ic->ic_fixed_rate == IEEE80211_FIXED_RATE_NONE)
341                 flags &= ~IEEE80211_F_DOFRATE;
342         error = 0;
343         okrate = badrate = fixedrate = 0;
344         nbasicrates = 0;
345         srs = &ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)];
346         nrs = &ni->ni_rates;
347         for (i = 0; i < nrs->rs_nrates; ) {
348                 ignore = 0;
349                 if (flags & IEEE80211_F_DOSORT) {
350                         /*
351                          * Sort rates.
352                          */
353                         for (j = i + 1; j < nrs->rs_nrates; j++) {
354                                 if (RV(nrs->rs_rates[i]) > RV(nrs->rs_rates[j])) {
355                                         r = nrs->rs_rates[i];
356                                         nrs->rs_rates[i] = nrs->rs_rates[j];
357                                         nrs->rs_rates[j] = r;
358                                 }
359                         }
360
361                         /*
362                          * Remove duplicated rate
363                          */
364                         if (i > 0 &&
365                             IEEE80211_RS_RATE(nrs, i) ==
366                             IEEE80211_RS_RATE(nrs, i - 1)) {
367                                 ignore = 1;
368                                 goto delit;
369                         }
370                 }
371                 r = nrs->rs_rates[i] & IEEE80211_RATE_VAL;
372                 badrate = r;
373                 if (flags & IEEE80211_F_DOFRATE) {
374                         /*
375                          * Check any fixed rate is included. 
376                          */
377                         if (r == RV(srs->rs_rates[ic->ic_fixed_rate]))
378                                 fixedrate = r;
379                 }
380                 if (flags & (IEEE80211_F_DONEGO | IEEE80211_F_DODEL)) {
381                         /*
382                          * Check against supported rates.
383                          */
384                         for (j = 0; j < srs->rs_nrates; j++) {
385                                 if (r == RV(srs->rs_rates[j])) {
386                                         /*
387                                          * Overwrite with the supported rate
388                                          * value so any basic rate bit is set.
389                                          */
390                                         if ((flags & IEEE80211_F_DONEGO) &&
391                                             !join) {
392                                                 nrs->rs_rates[i] =
393                                                     srs->rs_rates[j];
394
395                                                 if (nrs->rs_rates[i] &
396                                                     IEEE80211_RATE_BASIC)
397                                                         nbasicrates++;
398                                         }
399                                         break;
400                                 }
401                         }
402                         if (j == srs->rs_nrates) {
403                                 /*
404                                  * A rate in the node's rate set is not
405                                  * supported.  If this is a basic rate and
406                                  * we are operating as an STA then this is
407                                  * an error.
408                                  */
409                                 if ((flags & IEEE80211_F_DONEGO) && join &&
410                                     (nrs->rs_rates[i] & IEEE80211_RATE_BASIC))
411                                         error++;
412                                 ignore++;
413                         }
414                 }
415                 if (flags & IEEE80211_F_DODEL) {
416 delit:
417                         /*
418                          * Delete unacceptable rates.
419                          */
420                         if (ignore) {
421                                 nrs->rs_nrates--;
422                                 for (j = i; j < nrs->rs_nrates; j++)
423                                         nrs->rs_rates[j] = nrs->rs_rates[j + 1];
424                                 nrs->rs_rates[j] = 0;
425                                 continue;
426                         }
427                 }
428                 if (!ignore)
429                         okrate = nrs->rs_rates[i];
430                 i++;
431         }
432
433         /*
434          * Prevent STA from associating, if it does not support
435          * all of the rates in the basic rate set.
436          */
437         if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
438             (flags & IEEE80211_F_DONEGO) && !join &&
439             ic->ic_nbasicrates > nbasicrates)
440                 error++;
441
442         if (okrate == 0 || error != 0 ||
443             ((flags & IEEE80211_F_DOFRATE) && fixedrate == 0))
444                 return badrate | IEEE80211_RATE_BASIC;
445         else
446                 return RV(okrate);
447 #undef RV
448 }
449
450 /*
451  * Reset 11g-related state.
452  */
453 void
454 ieee80211_reset_erp(struct ieee80211com *ic)
455 {
456         ic->ic_flags &= ~IEEE80211_F_USEPROT;
457         ic->ic_nonerpsta = 0;
458         ic->ic_longslotsta = 0;
459         /*
460          * Short slot time is enabled only when operating in 11g
461          * and not in an IBSS.  We must also honor whether or not
462          * the driver is capable of doing it.
463          */
464         ieee80211_set_shortslottime(ic,
465                 ic->ic_curmode == IEEE80211_MODE_11A ||
466                 (ic->ic_curmode == IEEE80211_MODE_11G &&
467                 ic->ic_opmode == IEEE80211_M_HOSTAP &&
468                 (ic->ic_caps & IEEE80211_C_SHSLOT)));
469         /*
470          * Set short preamble and ERP barker-preamble flags.
471          */
472         ieee80211_set_shortpreamble(ic,
473                 ic->ic_curmode == IEEE80211_MODE_11A ||
474                 (ic->ic_caps & IEEE80211_C_SHPREAMBLE));
475 }
476
477 /*
478  * Set the short slot time state and notify the driver.
479  */
480 void
481 ieee80211_set_shortslottime(struct ieee80211com *ic, int onoff)
482 {
483         if (onoff)
484                 ic->ic_flags |= IEEE80211_F_SHSLOT;
485         else
486                 ic->ic_flags &= ~IEEE80211_F_SHSLOT;
487
488         /* Notify driver */
489         if (ic->ic_updateslot != NULL)
490                 ic->ic_updateslot(ic->ic_ifp);
491 }
492
493 /*
494  * Set the short preamble state and notify driver.
495  */
496 void
497 ieee80211_set_shortpreamble(struct ieee80211com *ic, int onoff)
498 {
499         if (onoff) {
500                 ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
501                 ic->ic_flags &= ~IEEE80211_F_USEBARKER;
502         } else {
503                 ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE;
504                 ic->ic_flags |= IEEE80211_F_USEBARKER;
505         }
506
507         /* Notify driver */
508         if (ic->ic_update_preamble != NULL)
509                 ic->ic_update_preamble(ic->ic_ifp);
510 }
511
512 /*
513  * Check if the specified rate set supports ERP.
514  * NB: the rate set is assumed to be sorted.
515  */
516 int
517 ieee80211_iserp_rateset(struct ieee80211com *ic,
518                         const struct ieee80211_rateset *rs)
519 {
520 #define N(a)    (sizeof(a) / sizeof(a[0]))
521         static const int rates[] = { 2, 4, 11, 22, 12, 24, 48 };
522         int i, j;
523
524         if (rs->rs_nrates < N(rates))
525                 return 0;
526         for (i = 0; i < N(rates); i++) {
527                 for (j = 0; j < rs->rs_nrates; j++) {
528                         int r = rs->rs_rates[j] & IEEE80211_RATE_VAL;
529                         if (rates[i] == r)
530                                 goto next;
531                         if (r > rates[i])
532                                 return 0;
533                 }
534                 return 0;
535         next:
536                 ;
537         }
538         return 1;
539 #undef N
540 }
541
542 /*
543  * Mark the basic rates for the 11g rate table based on the
544  * operating mode.  For real 11g we mark all the 11b rates
545  * and 6, 12, and 24 OFDM.  For 11b compatibility we mark only
546  * 11b rates.  There's also a pseudo 11a-mode used to mark only
547  * the basic OFDM rates.
548  */
549 void
550 ieee80211_set_basicrates(struct ieee80211_rateset *rs,
551                          enum ieee80211_phymode mode, int pureg)
552 {
553         static const struct ieee80211_rateset basic[] = {
554             [IEEE80211_MODE_AUTO]       = { 0 },
555             [IEEE80211_MODE_11A]        = { 3, { 12, 24, 48 } },
556             [IEEE80211_MODE_11B]        = { 2, { 2, 4 } },
557             [IEEE80211_MODE_11G]        = { 4, { 2, 4, 11, 22 } },
558             [IEEE80211_MODE_FH]         = { 0 },
559             [IEEE80211_MODE_TURBO_A]    = { 3, { 12, 24, 48 } },
560             [IEEE80211_MODE_TURBO_G]    = { 4, { 2, 4, 11, 22 } }
561         };
562         static const struct ieee80211_rateset basic_pureg =
563             { 7, { 2, 4, 11, 22, 12, 24, 48 } };
564         const struct ieee80211_rateset *basic_rs;
565         int i, j;
566
567         KASSERT(mode < IEEE80211_MODE_MAX, ("invalid phymode %u\n", mode));
568
569         if ((mode == IEEE80211_MODE_11G || mode == IEEE80211_MODE_TURBO_G) &&
570             pureg)
571                 basic_rs = &basic_pureg;
572         else
573                 basic_rs = &basic[mode];
574
575         for (i = 0; i < rs->rs_nrates; i++) {
576                 rs->rs_rates[i] &= IEEE80211_RATE_VAL;
577                 for (j = 0; j < basic_rs->rs_nrates; j++) {
578                         if (basic_rs->rs_rates[j] == rs->rs_rates[i]) {
579                                 rs->rs_rates[i] |= IEEE80211_RATE_BASIC;
580                                 break;
581                         }
582                 }
583         }
584 }
585
586 int
587 ieee80211_copy_basicrates(struct ieee80211_rateset *to,
588                           const struct ieee80211_rateset *from)
589 {
590         int i, nbasicrates = 0;
591
592         for (i = 0; i < to->rs_nrates; ++i) {
593                 int j;
594
595                 to->rs_rates[i] &= IEEE80211_RATE_VAL;
596                 for (j = 0; j < from->rs_nrates; ++j) {
597                         if ((from->rs_rates[j] & IEEE80211_RATE_BASIC) &&
598                             IEEE80211_RS_RATE(from, j) == to->rs_rates[i]) {
599                                 to->rs_rates[i] |= IEEE80211_RATE_BASIC;
600                                 ++nbasicrates;
601                                 break;
602                         }
603                 }
604         }
605         return nbasicrates;
606 }
607
608 /*
609  * WME protocol support.  The following parameters come from the spec.
610  */
611 typedef struct phyParamType {
612         uint8_t aifsn; 
613         uint8_t logcwmin;
614         uint8_t logcwmax; 
615         uint16_t txopLimit;
616         uint8_t acm;
617 } paramType;
618
619 static const struct phyParamType phyParamForAC_BE[IEEE80211_MODE_MAX] = {
620         { 3, 4, 6 },            /* IEEE80211_MODE_AUTO */
621         { 3, 4, 6 },            /* IEEE80211_MODE_11A */ 
622         { 3, 5, 7 },            /* IEEE80211_MODE_11B */ 
623         { 3, 4, 6 },            /* IEEE80211_MODE_11G */ 
624         { 3, 5, 7 },            /* IEEE80211_MODE_FH */ 
625         { 2, 3, 5 },            /* IEEE80211_MODE_TURBO_A */ 
626         { 2, 3, 5 },            /* IEEE80211_MODE_TURBO_G */ 
627 };
628 static const struct phyParamType phyParamForAC_BK[IEEE80211_MODE_MAX] = {
629         { 7, 4, 10 },           /* IEEE80211_MODE_AUTO */
630         { 7, 4, 10 },           /* IEEE80211_MODE_11A */ 
631         { 7, 5, 10 },           /* IEEE80211_MODE_11B */ 
632         { 7, 4, 10 },           /* IEEE80211_MODE_11G */ 
633         { 7, 5, 10 },           /* IEEE80211_MODE_FH */ 
634         { 7, 3, 10 },           /* IEEE80211_MODE_TURBO_A */ 
635         { 7, 3, 10 },           /* IEEE80211_MODE_TURBO_G */ 
636 };
637 static const struct phyParamType phyParamForAC_VI[IEEE80211_MODE_MAX] = {
638         { 1, 3, 4,  94 },       /* IEEE80211_MODE_AUTO */
639         { 1, 3, 4,  94 },       /* IEEE80211_MODE_11A */ 
640         { 1, 4, 5, 188 },       /* IEEE80211_MODE_11B */ 
641         { 1, 3, 4,  94 },       /* IEEE80211_MODE_11G */ 
642         { 1, 4, 5, 188 },       /* IEEE80211_MODE_FH */ 
643         { 1, 2, 3,  94 },       /* IEEE80211_MODE_TURBO_A */ 
644         { 1, 2, 3,  94 },       /* IEEE80211_MODE_TURBO_G */ 
645 };
646 static const struct phyParamType phyParamForAC_VO[IEEE80211_MODE_MAX] = {
647         { 1, 2, 3,  47 },       /* IEEE80211_MODE_AUTO */
648         { 1, 2, 3,  47 },       /* IEEE80211_MODE_11A */ 
649         { 1, 3, 4, 102 },       /* IEEE80211_MODE_11B */ 
650         { 1, 2, 3,  47 },       /* IEEE80211_MODE_11G */ 
651         { 1, 3, 4, 102 },       /* IEEE80211_MODE_FH */ 
652         { 1, 2, 2,  47 },       /* IEEE80211_MODE_TURBO_A */ 
653         { 1, 2, 2,  47 },       /* IEEE80211_MODE_TURBO_G */ 
654 };
655
656 static const struct phyParamType bssPhyParamForAC_BE[IEEE80211_MODE_MAX] = {
657         { 3, 4, 10 },           /* IEEE80211_MODE_AUTO */
658         { 3, 4, 10 },           /* IEEE80211_MODE_11A */ 
659         { 3, 5, 10 },           /* IEEE80211_MODE_11B */ 
660         { 3, 4, 10 },           /* IEEE80211_MODE_11G */ 
661         { 3, 5, 10 },           /* IEEE80211_MODE_FH */ 
662         { 2, 3, 10 },           /* IEEE80211_MODE_TURBO_A */ 
663         { 2, 3, 10 },           /* IEEE80211_MODE_TURBO_G */ 
664 };
665 static const struct phyParamType bssPhyParamForAC_VI[IEEE80211_MODE_MAX] = {
666         { 2, 3, 4,  94 },       /* IEEE80211_MODE_AUTO */
667         { 2, 3, 4,  94 },       /* IEEE80211_MODE_11A */ 
668         { 2, 4, 5, 188 },       /* IEEE80211_MODE_11B */ 
669         { 2, 3, 4,  94 },       /* IEEE80211_MODE_11G */ 
670         { 2, 4, 5, 188 },       /* IEEE80211_MODE_FH */ 
671         { 2, 2, 3,  94 },       /* IEEE80211_MODE_TURBO_A */ 
672         { 2, 2, 3,  94 },       /* IEEE80211_MODE_TURBO_G */ 
673 };
674 static const struct phyParamType bssPhyParamForAC_VO[IEEE80211_MODE_MAX] = {
675         { 2, 2, 3,  47 },       /* IEEE80211_MODE_AUTO */
676         { 2, 2, 3,  47 },       /* IEEE80211_MODE_11A */ 
677         { 2, 3, 4, 102 },       /* IEEE80211_MODE_11B */ 
678         { 2, 2, 3,  47 },       /* IEEE80211_MODE_11G */ 
679         { 2, 3, 4, 102 },       /* IEEE80211_MODE_FH */ 
680         { 1, 2, 2,  47 },       /* IEEE80211_MODE_TURBO_A */ 
681         { 1, 2, 2,  47 },       /* IEEE80211_MODE_TURBO_G */ 
682 };
683
684 void
685 ieee80211_wme_initparams(struct ieee80211com *ic)
686 {
687         struct ieee80211_wme_state *wme = &ic->ic_wme;
688         const paramType *pPhyParam, *pBssPhyParam;
689         struct wmeParams *wmep;
690         int i;
691
692         if ((ic->ic_caps & IEEE80211_C_WME) == 0)
693                 return;
694
695         for (i = 0; i < WME_NUM_AC; i++) {
696                 switch (i) {
697                 case WME_AC_BK:
698                         pPhyParam = &phyParamForAC_BK[ic->ic_curmode];
699                         pBssPhyParam = &phyParamForAC_BK[ic->ic_curmode];
700                         break;
701                 case WME_AC_VI:
702                         pPhyParam = &phyParamForAC_VI[ic->ic_curmode];
703                         pBssPhyParam = &bssPhyParamForAC_VI[ic->ic_curmode];
704                         break;
705                 case WME_AC_VO:
706                         pPhyParam = &phyParamForAC_VO[ic->ic_curmode];
707                         pBssPhyParam = &bssPhyParamForAC_VO[ic->ic_curmode];
708                         break;
709                 case WME_AC_BE:
710                 default:
711                         pPhyParam = &phyParamForAC_BE[ic->ic_curmode];
712                         pBssPhyParam = &bssPhyParamForAC_BE[ic->ic_curmode];
713                         break;
714                 }
715
716                 wmep = &wme->wme_wmeChanParams.cap_wmeParams[i];
717                 if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
718                         wmep->wmep_acm = pPhyParam->acm;
719                         wmep->wmep_aifsn = pPhyParam->aifsn;    
720                         wmep->wmep_logcwmin = pPhyParam->logcwmin;      
721                         wmep->wmep_logcwmax = pPhyParam->logcwmax;              
722                         wmep->wmep_txopLimit = pPhyParam->txopLimit;
723                 } else {
724                         wmep->wmep_acm = pBssPhyParam->acm;
725                         wmep->wmep_aifsn = pBssPhyParam->aifsn; 
726                         wmep->wmep_logcwmin = pBssPhyParam->logcwmin;   
727                         wmep->wmep_logcwmax = pBssPhyParam->logcwmax;           
728                         wmep->wmep_txopLimit = pBssPhyParam->txopLimit;
729
730                 }       
731                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
732                         "%s: %s chan [acm %u aifsn %u log2(cwmin) %u "
733                         "log2(cwmax) %u txpoLimit %u]\n", __func__
734                         , ieee80211_wme_acnames[i]
735                         , wmep->wmep_acm
736                         , wmep->wmep_aifsn
737                         , wmep->wmep_logcwmin
738                         , wmep->wmep_logcwmax
739                         , wmep->wmep_txopLimit
740                 );
741
742                 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[i];
743                 wmep->wmep_acm = pBssPhyParam->acm;
744                 wmep->wmep_aifsn = pBssPhyParam->aifsn; 
745                 wmep->wmep_logcwmin = pBssPhyParam->logcwmin;   
746                 wmep->wmep_logcwmax = pBssPhyParam->logcwmax;           
747                 wmep->wmep_txopLimit = pBssPhyParam->txopLimit;
748                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
749                         "%s: %s  bss [acm %u aifsn %u log2(cwmin) %u "
750                         "log2(cwmax) %u txpoLimit %u]\n", __func__
751                         , ieee80211_wme_acnames[i]
752                         , wmep->wmep_acm
753                         , wmep->wmep_aifsn
754                         , wmep->wmep_logcwmin
755                         , wmep->wmep_logcwmax
756                         , wmep->wmep_txopLimit
757                 );
758         }
759         /* NB: check ic_bss to avoid NULL deref on initial attach */
760         if (ic->ic_bss != NULL) {
761                 /*
762                  * Calculate agressive mode switching threshold based
763                  * on beacon interval.  This doesn't need locking since
764                  * we're only called before entering the RUN state at
765                  * which point we start sending beacon frames.
766                  */
767                 wme->wme_hipri_switch_thresh =
768                         (HIGH_PRI_SWITCH_THRESH * ic->ic_bss->ni_intval) / 100;
769                 ieee80211_wme_updateparams(ic);
770         }
771 }
772
773 /*
774  * Update WME parameters for ourself and the BSS.
775  */
776 void
777 ieee80211_wme_updateparams(struct ieee80211com *ic)
778 {
779         static const paramType phyParam[IEEE80211_MODE_MAX] = {
780                 { 2, 4, 10, 64 },       /* IEEE80211_MODE_AUTO */ 
781                 { 2, 4, 10, 64 },       /* IEEE80211_MODE_11A */ 
782                 { 2, 5, 10, 64 },       /* IEEE80211_MODE_11B */ 
783                 { 2, 4, 10, 64 },       /* IEEE80211_MODE_11G */ 
784                 { 2, 5, 10, 64 },       /* IEEE80211_MODE_FH */ 
785                 { 1, 3, 10, 64 },       /* IEEE80211_MODE_TURBO_A */ 
786                 { 1, 3, 10, 64 },       /* IEEE80211_MODE_TURBO_G */ 
787         };
788         struct ieee80211_wme_state *wme = &ic->ic_wme;
789         const struct wmeParams *wmep;
790         struct wmeParams *chanp, *bssp;
791         int i;
792
793         ASSERT_SERIALIZED(ic->ic_ifp->if_serializer);
794
795         if ((ic->ic_caps & IEEE80211_C_WME) == 0)
796                 return;
797
798         /* set up the channel access parameters for the physical device */
799         for (i = 0; i < WME_NUM_AC; i++) {
800                 chanp = &wme->wme_chanParams.cap_wmeParams[i];
801                 wmep = &wme->wme_wmeChanParams.cap_wmeParams[i];
802                 chanp->wmep_aifsn = wmep->wmep_aifsn;
803                 chanp->wmep_logcwmin = wmep->wmep_logcwmin;
804                 chanp->wmep_logcwmax = wmep->wmep_logcwmax;
805                 chanp->wmep_txopLimit = wmep->wmep_txopLimit;
806
807                 chanp = &wme->wme_bssChanParams.cap_wmeParams[i];
808                 wmep = &wme->wme_wmeBssChanParams.cap_wmeParams[i];
809                 chanp->wmep_aifsn = wmep->wmep_aifsn;
810                 chanp->wmep_logcwmin = wmep->wmep_logcwmin;
811                 chanp->wmep_logcwmax = wmep->wmep_logcwmax;
812                 chanp->wmep_txopLimit = wmep->wmep_txopLimit;
813         }
814
815         /*
816          * This implements agressive mode as found in certain
817          * vendors' AP's.  When there is significant high
818          * priority (VI/VO) traffic in the BSS throttle back BE
819          * traffic by using conservative parameters.  Otherwise
820          * BE uses agressive params to optimize performance of
821          * legacy/non-QoS traffic.
822          */
823         if ((ic->ic_opmode == IEEE80211_M_HOSTAP &&
824              (wme->wme_flags & WME_F_AGGRMODE) != 0) ||
825             (ic->ic_opmode == IEEE80211_M_STA &&
826              (ic->ic_bss->ni_flags & IEEE80211_NODE_QOS) == 0) ||
827             (ic->ic_flags & IEEE80211_F_WME) == 0) {
828                 chanp = &wme->wme_chanParams.cap_wmeParams[WME_AC_BE];
829                 bssp = &wme->wme_bssChanParams.cap_wmeParams[WME_AC_BE];
830
831                 chanp->wmep_aifsn = bssp->wmep_aifsn =
832                         phyParam[ic->ic_curmode].aifsn;
833                 chanp->wmep_logcwmin = bssp->wmep_logcwmin =
834                         phyParam[ic->ic_curmode].logcwmin;
835                 chanp->wmep_logcwmax = bssp->wmep_logcwmax =
836                         phyParam[ic->ic_curmode].logcwmax;
837                 chanp->wmep_txopLimit = bssp->wmep_txopLimit =
838                         (ic->ic_flags & IEEE80211_F_BURST) ?
839                                 phyParam[ic->ic_curmode].txopLimit : 0;         
840                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
841                         "%s: %s [acm %u aifsn %u log2(cwmin) %u "
842                         "log2(cwmax) %u txpoLimit %u]\n", __func__
843                         , ieee80211_wme_acnames[WME_AC_BE]
844                         , chanp->wmep_acm
845                         , chanp->wmep_aifsn
846                         , chanp->wmep_logcwmin
847                         , chanp->wmep_logcwmax
848                         , chanp->wmep_txopLimit
849                 );
850         }
851         
852         if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
853             ic->ic_sta_assoc < 2 && (wme->wme_flags & WME_F_AGGRMODE) != 0) {
854                 static const uint8_t logCwMin[IEEE80211_MODE_MAX] = {
855                         3,      /* IEEE80211_MODE_AUTO */
856                         3,      /* IEEE80211_MODE_11A */
857                         4,      /* IEEE80211_MODE_11B */
858                         3,      /* IEEE80211_MODE_11G */
859                         4,      /* IEEE80211_MODE_FH */
860                         3,      /* IEEE80211_MODE_TURBO_A */
861                         3,      /* IEEE80211_MODE_TURBO_G */
862                 };
863                 chanp = &wme->wme_chanParams.cap_wmeParams[WME_AC_BE];
864                 bssp = &wme->wme_bssChanParams.cap_wmeParams[WME_AC_BE];
865
866                 chanp->wmep_logcwmin = bssp->wmep_logcwmin = 
867                         logCwMin[ic->ic_curmode];
868                 IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
869                         "%s: %s log2(cwmin) %u\n", __func__
870                         , ieee80211_wme_acnames[WME_AC_BE]
871                         , chanp->wmep_logcwmin
872                 );
873         }       
874         if (ic->ic_opmode == IEEE80211_M_HOSTAP) {      /* XXX ibss? */
875                 /*
876                  * Arrange for a beacon update and bump the parameter
877                  * set number so associated stations load the new values.
878                  */
879                 wme->wme_bssChanParams.cap_info =
880                         (wme->wme_bssChanParams.cap_info+1) & WME_QOSINFO_COUNT;
881                 ic->ic_flags |= IEEE80211_F_WMEUPDATE;
882         }
883
884         wme->wme_update(ic);
885
886         IEEE80211_DPRINTF(ic, IEEE80211_MSG_WME,
887                 "%s: WME params updated, cap_info 0x%x\n", __func__,
888                 ic->ic_opmode == IEEE80211_M_STA ?
889                         wme->wme_wmeChanParams.cap_info :
890                         wme->wme_bssChanParams.cap_info);
891 }
892
893 void
894 ieee80211_beacon_miss(struct ieee80211com *ic)
895 {
896
897         if (ic->ic_flags & IEEE80211_F_SCAN) {
898                 /* XXX check ic_curchan != ic_bsschan? */
899                 return;
900         }
901         IEEE80211_DPRINTF(ic,
902                 IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG,
903                 "%s\n", "beacon miss");
904
905         /*
906          * Our handling is only meaningful for stations that are
907          * associated; any other conditions else will be handled
908          * through different means (e.g. the tx timeout on mgt frames).
909          */
910         if (ic->ic_opmode != IEEE80211_M_STA || ic->ic_state != IEEE80211_S_RUN)
911                 return;
912
913         if (++ic->ic_bmiss_count < ic->ic_bmiss_max) {
914                 /*
915                  * Send a directed probe req before falling back to a scan;
916                  * if we receive a response ic_bmiss_count will be reset.
917                  * Some cards mistakenly report beacon miss so this avoids
918                  * the expensive scan if the ap is still there.
919                  */
920                 ieee80211_send_probereq(ic->ic_bss, ic->ic_myaddr,
921                         ic->ic_bss->ni_bssid, ic->ic_bss->ni_bssid,
922                         ic->ic_bss->ni_essid, ic->ic_bss->ni_esslen,
923                         ic->ic_opt_ie, ic->ic_opt_ie_len);
924                 return;
925         }
926         ic->ic_bmiss_count = 0;
927         ieee80211_new_state(ic, IEEE80211_S_SCAN, 0);
928 }
929
930 /*
931  * Software beacon miss handling.  Check if any beacons
932  * were received in the last period.  If not post a
933  * beacon miss; otherwise reset the counter.
934  */
935 static void
936 ieee80211_swbmiss(void *arg)
937 {
938         struct ieee80211com *ic = arg;
939         struct ifnet *ifp = ic->ic_ifp;
940
941         ifnet_serialize_all(ifp);
942
943         if (ic->ic_swbmiss_count == 0) {
944                 ieee80211_beacon_miss(ic);
945                 if (ic->ic_bmiss_count == 0)    /* don't re-arm timer */
946                         goto back;
947         } else
948                 ic->ic_swbmiss_count = 0;
949         callout_reset(&ic->ic_swbmiss, ic->ic_swbmiss_period,
950                 ieee80211_swbmiss, ic);
951
952 back:
953         ifnet_deserialize_all(ifp);
954 }
955
956 static void
957 sta_disconnect(void *arg, struct ieee80211_node *ni)
958 {
959         struct ieee80211com *ic = arg;
960
961         if (ni->ni_associd != 0) {
962                 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DISASSOC,
963                         IEEE80211_REASON_ASSOC_LEAVE);
964                 ieee80211_node_leave(ic, ni);
965         } else if (ni->ni_flags & IEEE80211_NODE_AREF) {
966                 IEEE80211_SEND_MGMT(ic, ni, IEEE80211_FC0_SUBTYPE_DEAUTH,
967                         IEEE80211_REASON_ASSOC_LEAVE);
968                 ieee80211_node_leave(ic, ni);
969         }
970 }
971
972 void
973 ieee80211_reset_state(struct ieee80211com *ic,
974                       enum ieee80211_state cur_state)
975 {
976         struct ieee80211_node *ni;
977
978         IEEE80211_DPRINTF(ic, IEEE80211_MSG_STATE,
979                           "%s reset internal state machine (%s)\n",
980                           __func__, ieee80211_state_name[cur_state]);
981
982         ni = ic->ic_bss;
983         KASSERT(ni != NULL, ("empty ic_bss\n"));
984
985         switch (cur_state) {
986         case IEEE80211_S_INIT:
987                 break;
988         case IEEE80211_S_RUN:
989                 switch (ic->ic_opmode) {
990                 case IEEE80211_M_STA:
991                         /*
992                          * Avoid sending disassoc to self.  This could happen
993                          * when operational mode is switched directly from
994                          * HOSTAP/IBSS to STA.
995                          */
996                         if (!IEEE80211_ADDR_EQ(ic->ic_myaddr, ni->ni_macaddr)) {
997                                 IEEE80211_SEND_MGMT(ic, ni,
998                                     IEEE80211_FC0_SUBTYPE_DISASSOC,
999                                     IEEE80211_REASON_ASSOC_LEAVE);
1000                                 ieee80211_sta_leave(ic, ni);
1001                         }
1002                         break;
1003                 case IEEE80211_M_HOSTAP:
1004                         ieee80211_iterate_nodes(&ic->ic_sta,
1005                                 sta_disconnect, ic);
1006                         break;
1007                 default:
1008                         break;
1009                 }
1010                 break;
1011         case IEEE80211_S_ASSOC:
1012                 switch (ic->ic_opmode) {
1013                 case IEEE80211_M_STA:
1014                         /*
1015                          * Avoid sending deauth to self.
1016                          */
1017                         if (!IEEE80211_ADDR_EQ(ic->ic_myaddr, ni->ni_macaddr)) {
1018                                 IEEE80211_SEND_MGMT(ic, ni,
1019                                     IEEE80211_FC0_SUBTYPE_DEAUTH,
1020                                     IEEE80211_REASON_AUTH_LEAVE);
1021                         }
1022                         break;
1023                 default:
1024                         break;
1025                 }
1026                 break;
1027         case IEEE80211_S_SCAN:
1028                 ieee80211_cancel_scan(ic);
1029                 /* FALL THROUGH */
1030         case IEEE80211_S_AUTH:
1031                 break;
1032         }
1033
1034         ieee80211_drain_mgtq(&ic->ic_mgtq);
1035         ieee80211_reset_bss(ic);
1036 }
1037
1038 static int
1039 ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
1040 {
1041         struct ifnet *ifp = ic->ic_ifp;
1042         struct ieee80211_node *ni;
1043         enum ieee80211_state ostate;
1044
1045         ostate = ic->ic_state;
1046         IEEE80211_DPRINTF(ic, IEEE80211_MSG_STATE, "%s: %s -> %s\n", __func__,
1047                 ieee80211_state_name[ostate], ieee80211_state_name[nstate]);
1048         ic->ic_state = nstate;                  /* state transition */
1049         ni = ic->ic_bss;                        /* NB: no reference held */
1050         if (ic->ic_flags_ext & IEEE80211_FEXT_SWBMISS)
1051                 callout_stop(&ic->ic_swbmiss);
1052         switch (nstate) {
1053         case IEEE80211_S_INIT:
1054                 ieee80211_reset_state(ic, ostate);
1055                 ic->ic_mgt_timer = 0;
1056
1057                 if (ic->ic_auth->ia_detach != NULL)
1058                         ic->ic_auth->ia_detach(ic);
1059                 break;
1060  
1061         case IEEE80211_S_SCAN:
1062                 switch (ostate) {
1063                 case IEEE80211_S_INIT:
1064                         if ((ic->ic_opmode == IEEE80211_M_HOSTAP ||
1065                              ic->ic_opmode == IEEE80211_M_IBSS ||
1066                              ic->ic_opmode == IEEE80211_M_AHDEMO) &&
1067                             ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
1068                                 /*
1069                                  * AP operation and we already have a channel;
1070                                  * bypass the scan and startup immediately.
1071                                  */
1072                                 ieee80211_create_ibss(ic, ic->ic_des_chan);
1073                         } else {
1074                                 ieee80211_begin_scan(ic, arg);
1075                         }
1076                         break;
1077                 case IEEE80211_S_SCAN:
1078                         /*
1079                          * Scan next. If doing an active scan probe
1080                          * for the requested ap (if any).
1081                          */
1082                         if (ic->ic_flags & IEEE80211_F_ASCAN)
1083                                 ieee80211_probe_curchan(ic, 0);
1084                         break;
1085                 case IEEE80211_S_RUN:
1086                         /* beacon miss */
1087                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_STATE,
1088                                 "no recent beacons from %6D; rescanning\n",
1089                                 ic->ic_bss->ni_bssid, ":");
1090                         ieee80211_sta_leave(ic, ni);
1091                         ic->ic_flags &= ~IEEE80211_F_SIBSS;     /* XXX */
1092                         /* FALLTHRU */
1093                 case IEEE80211_S_AUTH:
1094                 case IEEE80211_S_ASSOC:
1095                         /* timeout restart scan */
1096                         ni = ieee80211_find_node(&ic->ic_scan,
1097                                 ic->ic_bss->ni_macaddr);
1098                         if (ni != NULL) {
1099                                 ni->ni_fails++;
1100                                 ieee80211_unref_node(&ni);
1101                         }
1102                         if (ic->ic_roaming == IEEE80211_ROAMING_AUTO)
1103                                 ieee80211_begin_scan(ic, arg);
1104                         break;
1105                 }
1106                 break;
1107         case IEEE80211_S_AUTH:
1108                 switch (ostate) {
1109                 case IEEE80211_S_INIT:
1110                 case IEEE80211_S_SCAN:
1111                         IEEE80211_SEND_MGMT(ic, ni,
1112                             IEEE80211_FC0_SUBTYPE_AUTH, 1);
1113                         break;
1114                 case IEEE80211_S_AUTH:
1115                 case IEEE80211_S_ASSOC:
1116                         switch (arg) {
1117                         case IEEE80211_FC0_SUBTYPE_AUTH:
1118                                 /* ??? */
1119                                 IEEE80211_SEND_MGMT(ic, ni,
1120                                     IEEE80211_FC0_SUBTYPE_AUTH, 2);
1121                                 break;
1122                         case IEEE80211_FC0_SUBTYPE_DEAUTH:
1123                                 /* ignore and retry scan on timeout */
1124                                 break;
1125                         }
1126                         break;
1127                 case IEEE80211_S_RUN:
1128                         switch (arg) {
1129                         case IEEE80211_FC0_SUBTYPE_AUTH:
1130                                 IEEE80211_SEND_MGMT(ic, ni,
1131                                     IEEE80211_FC0_SUBTYPE_AUTH, 2);
1132                                 ic->ic_state = ostate;  /* stay RUN */
1133                                 break;
1134                         case IEEE80211_FC0_SUBTYPE_DEAUTH:
1135                                 ieee80211_sta_leave(ic, ni);
1136                                 if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) {
1137                                         /* try to reauth */
1138                                         IEEE80211_SEND_MGMT(ic, ni,
1139                                             IEEE80211_FC0_SUBTYPE_AUTH, 1);
1140                                 }
1141                                 break;
1142                         }
1143                         break;
1144                 }
1145                 break;
1146         case IEEE80211_S_ASSOC:
1147                 switch (ostate) {
1148                 case IEEE80211_S_INIT:
1149                 case IEEE80211_S_SCAN:
1150                 case IEEE80211_S_ASSOC:
1151                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
1152                                 "%s: invalid transition\n", __func__);
1153                         break;
1154                 case IEEE80211_S_AUTH:
1155                         IEEE80211_SEND_MGMT(ic, ni,
1156                             IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0);
1157                         break;
1158                 case IEEE80211_S_RUN:
1159                         ieee80211_sta_leave(ic, ni);
1160                         if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) {
1161                                 IEEE80211_SEND_MGMT(ic, ni,
1162                                     IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 1);
1163                         }
1164                         break;
1165                 }
1166                 break;
1167         case IEEE80211_S_RUN:
1168                 if (ic->ic_flags & IEEE80211_F_WPA) {
1169                         /* XXX validate prerequisites */
1170                 }
1171                 switch (ostate) {
1172                 case IEEE80211_S_INIT:
1173                         if (ic->ic_opmode == IEEE80211_M_MONITOR)
1174                                 break;
1175                         /* fall thru... */
1176                 case IEEE80211_S_AUTH:
1177                         IEEE80211_DPRINTF(ic, IEEE80211_MSG_ANY,
1178                                 "%s: invalid transition\n", __func__);
1179                         /* fall thru... */
1180                 case IEEE80211_S_RUN:
1181                         break;
1182                 case IEEE80211_S_SCAN:          /* adhoc/hostap mode */
1183                 case IEEE80211_S_ASSOC:         /* infra mode */
1184                         KASSERT(ni->ni_txrate < ni->ni_rates.rs_nrates,
1185                                 ("%s: bogus xmit rate %u setup\n", __func__,
1186                                         ni->ni_txrate));
1187 #ifdef IEEE80211_DEBUG
1188                         if (ieee80211_msg_debug(ic)) {
1189                                 if (ic->ic_opmode == IEEE80211_M_STA)
1190                                         if_printf(ifp, "associated ");
1191                                 else
1192                                         if_printf(ifp, "synchronized ");
1193                                 kprintf("with %6D ssid ", ni->ni_bssid, ":");
1194                                 ieee80211_print_essid(ic->ic_bss->ni_essid,
1195                                     ni->ni_esslen);
1196                                 kprintf(" channel %d start %uMb\n",
1197                                         ieee80211_chan2ieee(ic, ic->ic_curchan),
1198                                         IEEE80211_RATE2MBS(ni->ni_rates.rs_rates[ni->ni_txrate]));
1199                         }
1200 #endif
1201                         ic->ic_mgt_timer = 0;
1202                         if (ic->ic_opmode == IEEE80211_M_STA)
1203                                 ieee80211_notify_node_join(ic, ni, 
1204                                         arg == IEEE80211_FC0_SUBTYPE_ASSOC_RESP);
1205                         ifp->if_start(ifp);     /* XXX not authorized yet */
1206                         break;
1207                 }
1208                 if (ostate != IEEE80211_S_RUN &&
1209                     ic->ic_opmode == IEEE80211_M_STA &&
1210                     (ic->ic_flags_ext & IEEE80211_FEXT_SWBMISS)) {
1211                         /*
1212                          * Start s/w beacon miss timer for devices w/o
1213                          * hardware support.  We fudge a bit here since
1214                          * we're doing this in software.
1215                          */
1216                         ic->ic_swbmiss_period = IEEE80211_TU_TO_TICKS(
1217                                 2 * ic->ic_bmissthreshold * ni->ni_intval);
1218                         ic->ic_swbmiss_count = 0;
1219                         callout_reset(&ic->ic_swbmiss, ic->ic_swbmiss_period,
1220                                 ieee80211_swbmiss, ic);
1221                 }
1222                 /*
1223                  * Start/stop the authenticator when operating as an
1224                  * AP.  We delay until here to allow configuration to
1225                  * happen out of order.
1226                  */
1227                 if (ic->ic_opmode == IEEE80211_M_HOSTAP && /* XXX IBSS/AHDEMO */
1228                     ic->ic_auth->ia_attach != NULL) {
1229                         /* XXX check failure */
1230                         ic->ic_auth->ia_attach(ic);
1231                 } else if (ic->ic_auth->ia_detach != NULL) {
1232                         ic->ic_auth->ia_detach(ic);
1233                 }
1234                 /*
1235                  * When 802.1x is not in use mark the port authorized
1236                  * at this point so traffic can flow.
1237                  */
1238                 if (ni->ni_authmode != IEEE80211_AUTH_8021X)
1239                         ieee80211_node_authorize(ni);
1240                 /*
1241                  * Enable inactivity processing.
1242                  * XXX
1243                  */
1244                 ic->ic_scan.nt_inact_timer = IEEE80211_INACT_WAIT;
1245                 ic->ic_sta.nt_inact_timer = IEEE80211_INACT_WAIT;
1246                 break;
1247         }
1248         return 0;
1249 }