amd64 port: mainly on the pmap headers, identify_cpu and initcpu
[dragonfly/port-amd64.git] / sys / netproto / 802_11 / wlan / ieee80211_proto.c
blob561fe0e3409a26219e37cb6e2ccc1c8c71ebfa23
1 /*
2 * Copyright (c) 2001 Atsushi Onoe
3 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
4 * All rights reserved.
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.
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.
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.
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 $
37 * IEEE 802.11 protocol support.
40 #include "opt_inet.h"
42 #include <sys/param.h>
43 #include <sys/kernel.h>
44 #include <sys/systm.h>
45 #include <sys/serialize.h>
47 #include <sys/socket.h>
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 */
54 #include <netproto/802_11/ieee80211_var.h>
56 /* XXX tunables */
57 #define AGGRESSIVE_MODE_SWITCH_HYSTERESIS 3 /* pkts / 100ms */
58 #define HIGH_PRI_SWITCH_THRESH 10 /* pkts / 100ms */
60 #define IEEE80211_RATE2MBS(r) (((r) & IEEE80211_RATE_VAL) / 2)
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 */
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",
79 static int ieee80211_newstate(struct ieee80211com *, enum ieee80211_state, int);
81 void
82 ieee80211_proto_attach(struct ieee80211com *ic)
84 struct ifnet *ifp = ic->ic_ifp;
86 /* XXX room for crypto */
87 ifp->if_hdrlen = sizeof(struct ieee80211_qosframe_addr4);
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;
98 ic->ic_wme.wme_hipri_switch_hysteresis =
99 AGGRESSIVE_MODE_SWITCH_HYSTERESIS;
101 /* protocol state change handler */
102 ic->ic_newstate = ieee80211_newstate;
104 /* initialize management frame handlers */
105 ic->ic_recv_mgmt = ieee80211_recv_mgmt;
106 ic->ic_send_mgmt = ieee80211_send_mgmt;
109 void
110 ieee80211_proto_detach(struct ieee80211com *ic)
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.
118 if (ic->ic_auth->ia_detach)
119 ic->ic_auth->ia_detach(ic);
121 ieee80211_drain_mgtq(&ic->ic_mgtq);
124 * Detach any ACL'ator.
126 if (ic->ic_acl != NULL)
127 ic->ic_acl->iac_detach(ic);
131 * Simple-minded authenticator module support.
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 */
144 static const struct ieee80211_authenticator *authenticators[IEEE80211_AUTH_MAX];
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,
155 * Setup internal authenticators once; they are never unregistered.
157 static void
158 ieee80211_auth_setup(void)
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);
164 SYSINIT(wlan_auth, SI_SUB_DRIVERS, SI_ORDER_FIRST, ieee80211_auth_setup, NULL);
166 const struct ieee80211_authenticator *
167 ieee80211_authenticator_get(int auth)
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];
176 void
177 ieee80211_authenticator_register(int type,
178 const struct ieee80211_authenticator *auth)
180 if (type >= IEEE80211_AUTH_MAX)
181 return;
182 authenticators[type] = auth;
185 void
186 ieee80211_authenticator_unregister(int type)
189 if (type >= IEEE80211_AUTH_MAX)
190 return;
191 authenticators[type] = NULL;
195 * Very simple-minded ACL module support.
197 /* XXX just one for now */
198 static const struct ieee80211_aclator *acl = NULL;
200 void
201 ieee80211_aclator_register(const struct ieee80211_aclator *iac)
203 kprintf("wlan: %s acl policy registered\n", iac->iac_name);
204 acl = iac;
207 void
208 ieee80211_aclator_unregister(const struct ieee80211_aclator *iac)
210 if (acl == iac)
211 acl = NULL;
212 kprintf("wlan: %s acl policy unregistered\n", iac->iac_name);
215 const struct ieee80211_aclator *
216 ieee80211_aclator_get(const char *name)
218 if (acl == NULL)
219 ieee80211_load_module("wlan_acl");
220 return acl != NULL && strcmp(acl->iac_name, name) == 0 ? acl : NULL;
223 void
224 ieee80211_print_essid(const uint8_t *essid, int len)
226 const uint8_t *p;
227 int i;
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;
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);
248 void
249 ieee80211_print_rateset(const struct ieee80211_rateset *rs)
251 int i;
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) ? "*" : "");
259 void
260 ieee80211_dump_pkt(const uint8_t *buf, int len, int rate, int rssi)
262 const struct ieee80211_frame *wh;
263 int i;
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;
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;
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);
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]);
320 kprintf("\n");
325 ieee80211_fix_rate(struct ieee80211_node *ni, int flags, int join)
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;
336 * If the fixed rate check was requested but no
337 * fixed has been defined then just remove it.
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) {
351 * Sort rates.
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;
362 * Remove duplicated rate
364 if (i > 0 &&
365 IEEE80211_RS_RATE(nrs, i) ==
366 IEEE80211_RS_RATE(nrs, i - 1)) {
367 ignore = 1;
368 goto delit;
371 r = nrs->rs_rates[i] & IEEE80211_RATE_VAL;
372 badrate = r;
373 if (flags & IEEE80211_F_DOFRATE) {
375 * Check any fixed rate is included.
377 if (r == RV(srs->rs_rates[ic->ic_fixed_rate]))
378 fixedrate = r;
380 if (flags & (IEEE80211_F_DONEGO | IEEE80211_F_DODEL)) {
382 * Check against supported rates.
384 for (j = 0; j < srs->rs_nrates; j++) {
385 if (r == RV(srs->rs_rates[j])) {
387 * Overwrite with the supported rate
388 * value so any basic rate bit is set.
390 if ((flags & IEEE80211_F_DONEGO) &&
391 !join) {
392 nrs->rs_rates[i] =
393 srs->rs_rates[j];
395 if (nrs->rs_rates[i] &
396 IEEE80211_RATE_BASIC)
397 nbasicrates++;
399 break;
402 if (j == srs->rs_nrates) {
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.
409 if ((flags & IEEE80211_F_DONEGO) && join &&
410 (nrs->rs_rates[i] & IEEE80211_RATE_BASIC))
411 error++;
412 ignore++;
415 if (flags & IEEE80211_F_DODEL) {
416 delit:
418 * Delete unacceptable rates.
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;
428 if (!ignore)
429 okrate = nrs->rs_rates[i];
430 i++;
434 * Prevent STA from associating, if it does not support
435 * all of the rates in the basic rate set.
437 if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
438 (flags & IEEE80211_F_DONEGO) && !join &&
439 ic->ic_nbasicrates > nbasicrates)
440 error++;
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
451 * Reset 11g-related state.
453 void
454 ieee80211_reset_erp(struct ieee80211com *ic)
456 ic->ic_flags &= ~IEEE80211_F_USEPROT;
457 ic->ic_nonerpsta = 0;
458 ic->ic_longslotsta = 0;
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.
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)));
470 * Set short preamble and ERP barker-preamble flags.
472 ieee80211_set_shortpreamble(ic,
473 ic->ic_curmode == IEEE80211_MODE_11A ||
474 (ic->ic_caps & IEEE80211_C_SHPREAMBLE));
478 * Set the short slot time state and notify the driver.
480 void
481 ieee80211_set_shortslottime(struct ieee80211com *ic, int onoff)
483 if (onoff)
484 ic->ic_flags |= IEEE80211_F_SHSLOT;
485 else
486 ic->ic_flags &= ~IEEE80211_F_SHSLOT;
488 /* Notify driver */
489 if (ic->ic_updateslot != NULL)
490 ic->ic_updateslot(ic->ic_ifp);
494 * Set the short preamble state and notify driver.
496 void
497 ieee80211_set_shortpreamble(struct ieee80211com *ic, int onoff)
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;
507 /* Notify driver */
508 if (ic->ic_update_preamble != NULL)
509 ic->ic_update_preamble(ic->ic_ifp);
513 * Check if the specified rate set supports ERP.
514 * NB: the rate set is assumed to be sorted.
517 ieee80211_iserp_rateset(struct ieee80211com *ic,
518 const struct ieee80211_rateset *rs)
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;
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;
534 return 0;
535 next:
538 return 1;
539 #undef N
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.
549 void
550 ieee80211_set_basicrates(struct ieee80211_rateset *rs,
551 enum ieee80211_phymode mode, int pureg)
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 } }
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;
567 KASSERT(mode < IEEE80211_MODE_MAX, ("invalid phymode %u\n", mode));
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];
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;
587 ieee80211_copy_basicrates(struct ieee80211_rateset *to,
588 const struct ieee80211_rateset *from)
590 int i, nbasicrates = 0;
592 for (i = 0; i < to->rs_nrates; ++i) {
593 int j;
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;
605 return nbasicrates;
609 * WME protocol support. The following parameters come from the spec.
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;
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 */
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 */
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 */
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 */
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 */
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 */
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 */
684 void
685 ieee80211_wme_initparams(struct ieee80211com *ic)
687 struct ieee80211_wme_state *wme = &ic->ic_wme;
688 const paramType *pPhyParam, *pBssPhyParam;
689 struct wmeParams *wmep;
690 int i;
692 if ((ic->ic_caps & IEEE80211_C_WME) == 0)
693 return;
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;
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;
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
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
759 /* NB: check ic_bss to avoid NULL deref on initial attach */
760 if (ic->ic_bss != NULL) {
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.
767 wme->wme_hipri_switch_thresh =
768 (HIGH_PRI_SWITCH_THRESH * ic->ic_bss->ni_intval) / 100;
769 ieee80211_wme_updateparams(ic);
774 * Update WME parameters for ourself and the BSS.
776 void
777 ieee80211_wme_updateparams(struct ieee80211com *ic)
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 */
788 struct ieee80211_wme_state *wme = &ic->ic_wme;
789 const struct wmeParams *wmep;
790 struct wmeParams *chanp, *bssp;
791 int i;
793 ASSERT_SERIALIZED(ic->ic_ifp->if_serializer);
795 if ((ic->ic_caps & IEEE80211_C_WME) == 0)
796 return;
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;
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;
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.
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];
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
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 */
863 chanp = &wme->wme_chanParams.cap_wmeParams[WME_AC_BE];
864 bssp = &wme->wme_bssChanParams.cap_wmeParams[WME_AC_BE];
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
874 if (ic->ic_opmode == IEEE80211_M_HOSTAP) { /* XXX ibss? */
876 * Arrange for a beacon update and bump the parameter
877 * set number so associated stations load the new values.
879 wme->wme_bssChanParams.cap_info =
880 (wme->wme_bssChanParams.cap_info+1) & WME_QOSINFO_COUNT;
881 ic->ic_flags |= IEEE80211_F_WMEUPDATE;
884 wme->wme_update(ic);
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);
893 void
894 ieee80211_beacon_miss(struct ieee80211com *ic)
897 if (ic->ic_flags & IEEE80211_F_SCAN) {
898 /* XXX check ic_curchan != ic_bsschan? */
899 return;
901 IEEE80211_DPRINTF(ic,
902 IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG,
903 "%s\n", "beacon miss");
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).
910 if (ic->ic_opmode != IEEE80211_M_STA || ic->ic_state != IEEE80211_S_RUN)
911 return;
913 if (++ic->ic_bmiss_count < ic->ic_bmiss_max) {
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.
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;
926 ic->ic_bmiss_count = 0;
927 ieee80211_new_state(ic, IEEE80211_S_SCAN, 0);
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.
935 static void
936 ieee80211_swbmiss(void *arg)
938 struct ieee80211com *ic = arg;
939 struct ifnet *ifp = ic->ic_ifp;
941 lwkt_serialize_enter(ifp->if_serializer);
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);
952 back:
953 lwkt_serialize_exit(ifp->if_serializer);
956 static void
957 sta_disconnect(void *arg, struct ieee80211_node *ni)
959 struct ieee80211com *ic = arg;
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);
972 void
973 ieee80211_reset_state(struct ieee80211com *ic,
974 enum ieee80211_state cur_state)
976 struct ieee80211_node *ni;
978 IEEE80211_DPRINTF(ic, IEEE80211_MSG_STATE,
979 "%s reset internal state machine (%s)\n",
980 __func__, ieee80211_state_name[cur_state]);
982 ni = ic->ic_bss;
983 KASSERT(ni != NULL, ("empty ic_bss\n"));
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:
992 * Avoid sending disassoc to self. This could happen
993 * when operational mode is switched directly from
994 * HOSTAP/IBSS to STA.
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);
1002 break;
1003 case IEEE80211_M_HOSTAP:
1004 ieee80211_iterate_nodes(&ic->ic_sta,
1005 sta_disconnect, ic);
1006 break;
1007 default:
1008 break;
1010 break;
1011 case IEEE80211_S_ASSOC:
1012 switch (ic->ic_opmode) {
1013 case IEEE80211_M_STA:
1015 * Avoid sending deauth to self.
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);
1022 break;
1023 default:
1024 break;
1026 break;
1027 case IEEE80211_S_SCAN:
1028 ieee80211_cancel_scan(ic);
1029 /* FALL THROUGH */
1030 case IEEE80211_S_AUTH:
1031 break;
1034 ieee80211_drain_mgtq(&ic->ic_mgtq);
1035 ieee80211_reset_bss(ic);
1038 static int
1039 ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
1041 struct ifnet *ifp = ic->ic_ifp;
1042 struct ieee80211_node *ni;
1043 enum ieee80211_state ostate;
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;
1057 if (ic->ic_auth->ia_detach != NULL)
1058 ic->ic_auth->ia_detach(ic);
1059 break;
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) {
1069 * AP operation and we already have a channel;
1070 * bypass the scan and startup immediately.
1072 ieee80211_create_ibss(ic, ic->ic_des_chan);
1073 } else {
1074 ieee80211_begin_scan(ic, arg);
1076 break;
1077 case IEEE80211_S_SCAN:
1079 * Scan next. If doing an active scan probe
1080 * for the requested ap (if any).
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);
1102 if (ic->ic_roaming == IEEE80211_ROAMING_AUTO)
1103 ieee80211_begin_scan(ic, arg);
1104 break;
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;
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);
1141 break;
1143 break;
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);
1164 break;
1166 break;
1167 case IEEE80211_S_RUN:
1168 if (ic->ic_flags & IEEE80211_F_WPA) {
1169 /* XXX validate prerequisites */
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]));
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;
1208 if (ostate != IEEE80211_S_RUN &&
1209 ic->ic_opmode == IEEE80211_M_STA &&
1210 (ic->ic_flags_ext & IEEE80211_FEXT_SWBMISS)) {
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.
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);
1223 * Start/stop the authenticator when operating as an
1224 * AP. We delay until here to allow configuration to
1225 * happen out of order.
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);
1235 * When 802.1x is not in use mark the port authorized
1236 * at this point so traffic can flow.
1238 if (ni->ni_authmode != IEEE80211_AUTH_8021X)
1239 ieee80211_node_authorize(ni);
1241 * Enable inactivity processing.
1242 * XXX
1244 ic->ic_scan.nt_inact_timer = IEEE80211_INACT_WAIT;
1245 ic->ic_sta.nt_inact_timer = IEEE80211_INACT_WAIT;
1246 break;
1248 return 0;