2 * Copyright (c) 2001 Atsushi Onoe
3 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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>
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>
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
[] = {
79 static int ieee80211_newstate(struct ieee80211com
*, enum ieee80211_state
, int);
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
;
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",
150 .ia_node_join
= NULL
,
151 .ia_node_leave
= NULL
,
155 * Setup internal authenticators once; they are never unregistered.
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
)
171 if (authenticators
[auth
] == NULL
)
172 ieee80211_load_module(auth_modnames
[auth
]);
173 return authenticators
[auth
];
177 ieee80211_authenticator_register(int type
,
178 const struct ieee80211_authenticator
*auth
)
180 if (type
>= IEEE80211_AUTH_MAX
)
182 authenticators
[type
] = auth
;
186 ieee80211_authenticator_unregister(int type
)
189 if (type
>= IEEE80211_AUTH_MAX
)
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
;
201 ieee80211_aclator_register(const struct ieee80211_aclator
*iac
)
203 kprintf("wlan: %s acl policy registered\n", iac
->iac_name
);
208 ieee80211_aclator_unregister(const struct ieee80211_aclator
*iac
)
212 kprintf("wlan: %s acl policy unregistered\n", iac
->iac_name
);
215 const struct ieee80211_aclator
*
216 ieee80211_aclator_get(const char *name
)
219 ieee80211_load_module("wlan_acl");
220 return acl
!= NULL
&& strcmp(acl
->iac_name
, name
) == 0 ? acl
: NULL
;
224 ieee80211_print_essid(const uint8_t *essid
, int len
)
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)
238 for (i
= 0, p
= essid
; i
< len
; i
++, p
++)
243 for (i
= 0, p
= essid
; i
< len
; i
++, p
++)
249 ieee80211_print_rateset(const struct ieee80211_rateset
*rs
)
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
) ? "*" : "");
260 ieee80211_dump_pkt(const uint8_t *buf
, int len
, int rate
, int rssi
)
262 const struct ieee80211_frame
*wh
;
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
, ":");
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
, ":");
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
, ":");
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
, ":");
289 switch (wh
->i_fc
[0] & IEEE80211_FC0_TYPE_MASK
) {
290 case IEEE80211_FC0_TYPE_DATA
:
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
]);
299 kprintf(" type#%d", wh
->i_fc
[0] & IEEE80211_FC0_TYPE_MASK
);
302 if (wh
->i_fc
[1] & IEEE80211_FC1_WEP
) {
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);
310 kprintf(" %dM", rate
/ 2);
312 kprintf(" +%d", rssi
);
315 for (i
= 0; i
< len
; i
++) {
318 kprintf("%02x", buf
[i
]);
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
;
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
;
343 okrate
= badrate
= fixedrate
= 0;
345 srs
= &ic
->ic_sup_rates
[ieee80211_chan2mode(ic
, ni
->ni_chan
)];
347 for (i
= 0; i
< nrs
->rs_nrates
; ) {
349 if (flags
& IEEE80211_F_DOSORT
) {
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
365 IEEE80211_RS_RATE(nrs
, i
) ==
366 IEEE80211_RS_RATE(nrs
, i
- 1)) {
371 r
= nrs
->rs_rates
[i
] & IEEE80211_RATE_VAL
;
373 if (flags
& IEEE80211_F_DOFRATE
) {
375 * Check any fixed rate is included.
377 if (r
== RV(srs
->rs_rates
[ic
->ic_fixed_rate
]))
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
) &&
395 if (nrs
->rs_rates
[i
] &
396 IEEE80211_RATE_BASIC
)
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
409 if ((flags
& IEEE80211_F_DONEGO
) && join
&&
410 (nrs
->rs_rates
[i
] & IEEE80211_RATE_BASIC
))
415 if (flags
& IEEE80211_F_DODEL
) {
418 * Delete unacceptable rates.
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;
429 okrate
= nrs
->rs_rates
[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
)
442 if (okrate
== 0 || error
!= 0 ||
443 ((flags
& IEEE80211_F_DOFRATE
) && fixedrate
== 0))
444 return badrate
| IEEE80211_RATE_BASIC
;
451 * Reset 11g-related state.
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.
481 ieee80211_set_shortslottime(struct ieee80211com
*ic
, int onoff
)
484 ic
->ic_flags
|= IEEE80211_F_SHSLOT
;
486 ic
->ic_flags
&= ~IEEE80211_F_SHSLOT
;
489 if (ic
->ic_updateslot
!= NULL
)
490 ic
->ic_updateslot(ic
->ic_ifp
);
494 * Set the short preamble state and notify driver.
497 ieee80211_set_shortpreamble(struct ieee80211com
*ic
, int onoff
)
500 ic
->ic_flags
|= IEEE80211_F_SHPREAMBLE
;
501 ic
->ic_flags
&= ~IEEE80211_F_USEBARKER
;
503 ic
->ic_flags
&= ~IEEE80211_F_SHPREAMBLE
;
504 ic
->ic_flags
|= IEEE80211_F_USEBARKER
;
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 };
524 if (rs
->rs_nrates
< N(rates
))
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
;
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.
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
;
567 KASSERT(mode
< IEEE80211_MODE_MAX
, ("invalid phymode %u\n", mode
));
569 if ((mode
== IEEE80211_MODE_11G
|| mode
== IEEE80211_MODE_TURBO_G
) &&
571 basic_rs
= &basic_pureg
;
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
;
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
) {
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
;
609 * WME protocol support. The following parameters come from the spec.
611 typedef struct phyParamType
{
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 */
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
;
692 if ((ic
->ic_caps
& IEEE80211_C_WME
) == 0)
695 for (i
= 0; i
< WME_NUM_AC
; i
++) {
698 pPhyParam
= &phyParamForAC_BK
[ic
->ic_curmode
];
699 pBssPhyParam
= &phyParamForAC_BK
[ic
->ic_curmode
];
702 pPhyParam
= &phyParamForAC_VI
[ic
->ic_curmode
];
703 pBssPhyParam
= &bssPhyParamForAC_VI
[ic
->ic_curmode
];
706 pPhyParam
= &phyParamForAC_VO
[ic
->ic_curmode
];
707 pBssPhyParam
= &bssPhyParamForAC_VO
[ic
->ic_curmode
];
711 pPhyParam
= &phyParamForAC_BE
[ic
->ic_curmode
];
712 pBssPhyParam
= &bssPhyParamForAC_BE
[ic
->ic_curmode
];
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
;
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
]
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
]
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.
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
;
793 ASSERT_SERIALIZED(ic
->ic_ifp
->if_serializer
);
795 if ((ic
->ic_caps
& IEEE80211_C_WME
) == 0)
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
]
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
;
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
);
894 ieee80211_beacon_miss(struct ieee80211com
*ic
)
897 if (ic
->ic_flags
& IEEE80211_F_SCAN
) {
898 /* XXX check ic_curchan != ic_bsschan? */
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
)
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
);
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.
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 */
948 ic
->ic_swbmiss_count
= 0;
949 callout_reset(&ic
->ic_swbmiss
, ic
->ic_swbmiss_period
,
950 ieee80211_swbmiss
, ic
);
953 lwkt_serialize_exit(ifp
->if_serializer
);
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
);
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
]);
983 KASSERT(ni
!= NULL
, ("empty ic_bss\n"));
986 case IEEE80211_S_INIT
:
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
);
1003 case IEEE80211_M_HOSTAP
:
1004 ieee80211_iterate_nodes(&ic
->ic_sta
,
1005 sta_disconnect
, ic
);
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
);
1027 case IEEE80211_S_SCAN
:
1028 ieee80211_cancel_scan(ic
);
1030 case IEEE80211_S_AUTH
:
1034 ieee80211_drain_mgtq(&ic
->ic_mgtq
);
1035 ieee80211_reset_bss(ic
);
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
);
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
);
1061 case IEEE80211_S_SCAN
:
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
);
1074 ieee80211_begin_scan(ic
, arg
);
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);
1085 case IEEE80211_S_RUN
:
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 */
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
);
1100 ieee80211_unref_node(&ni
);
1102 if (ic
->ic_roaming
== IEEE80211_ROAMING_AUTO
)
1103 ieee80211_begin_scan(ic
, arg
);
1107 case IEEE80211_S_AUTH
:
1109 case IEEE80211_S_INIT
:
1110 case IEEE80211_S_SCAN
:
1111 IEEE80211_SEND_MGMT(ic
, ni
,
1112 IEEE80211_FC0_SUBTYPE_AUTH
, 1);
1114 case IEEE80211_S_AUTH
:
1115 case IEEE80211_S_ASSOC
:
1117 case IEEE80211_FC0_SUBTYPE_AUTH
:
1119 IEEE80211_SEND_MGMT(ic
, ni
,
1120 IEEE80211_FC0_SUBTYPE_AUTH
, 2);
1122 case IEEE80211_FC0_SUBTYPE_DEAUTH
:
1123 /* ignore and retry scan on timeout */
1127 case IEEE80211_S_RUN
:
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 */
1134 case IEEE80211_FC0_SUBTYPE_DEAUTH
:
1135 ieee80211_sta_leave(ic
, ni
);
1136 if (ic
->ic_roaming
== IEEE80211_ROAMING_AUTO
) {
1138 IEEE80211_SEND_MGMT(ic
, ni
,
1139 IEEE80211_FC0_SUBTYPE_AUTH
, 1);
1146 case IEEE80211_S_ASSOC
:
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__
);
1154 case IEEE80211_S_AUTH
:
1155 IEEE80211_SEND_MGMT(ic
, ni
,
1156 IEEE80211_FC0_SUBTYPE_ASSOC_REQ
, 0);
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);
1167 case IEEE80211_S_RUN
:
1168 if (ic
->ic_flags
& IEEE80211_F_WPA
) {
1169 /* XXX validate prerequisites */
1172 case IEEE80211_S_INIT
:
1173 if (ic
->ic_opmode
== IEEE80211_M_MONITOR
)
1176 case IEEE80211_S_AUTH
:
1177 IEEE80211_DPRINTF(ic
, IEEE80211_MSG_ANY
,
1178 "%s: invalid transition\n", __func__
);
1180 case IEEE80211_S_RUN
:
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__
,
1187 #ifdef IEEE80211_DEBUG
1188 if (ieee80211_msg_debug(ic
)) {
1189 if (ic
->ic_opmode
== IEEE80211_M_STA
)
1190 if_printf(ifp
, "associated ");
1192 if_printf(ifp
, "synchronized ");
1193 kprintf("with %6D ssid ", ni
->ni_bssid
, ":");
1194 ieee80211_print_essid(ic
->ic_bss
->ni_essid
,
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
]));
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 */
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.
1244 ic
->ic_scan
.nt_inact_timer
= IEEE80211_INACT_WAIT
;
1245 ic
->ic_sta
.nt_inact_timer
= IEEE80211_INACT_WAIT
;