1 /* $NetBSD: ieee80211_proto.c,v 1.28 2006/11/16 01:33:41 christos Exp $ */
3 * Copyright (c) 2001 Atsushi Onoe
4 * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
18 * Alternatively, this software may be distributed under the terms of the
19 * GNU General Public License ("GPL") version 2 as published by the Free
20 * Software Foundation.
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD: src/sys/net80211/ieee80211_proto.c,v 1.23 2005/08/10 16:22:29 sam Exp $");
39 __KERNEL_RCSID(0, "$NetBSD: ieee80211_proto.c,v 1.28 2006/11/16 01:33:41 christos Exp $");
43 * IEEE 802.11 protocol support.
48 #include <sys/param.h>
49 #include <sys/kernel.h>
50 #include <sys/systm.h>
52 #include <sys/socket.h>
53 #include <sys/sockio.h>
54 #include <sys/endian.h>
55 #include <sys/errno.h>
57 #include <sys/sysctl.h>
60 #include <net/if_media.h>
61 #include <net/if_arp.h>
62 #include <net/if_ether.h>
63 #include <net/if_llc.h>
65 #include <net80211/ieee80211_netbsd.h>
66 #include <net80211/ieee80211_var.h>
71 #include <netinet/in.h>
72 #include <net/if_ether.h>
75 #include <net/route.h>
77 #define AGGRESSIVE_MODE_SWITCH_HYSTERESIS 3 /* pkts / 100ms */
78 #define HIGH_PRI_SWITCH_THRESH 10 /* pkts / 100ms */
80 #define IEEE80211_RATE2MBS(r) (((r) & IEEE80211_RATE_VAL) / 2)
82 const char *ieee80211_mgt_subtype_name
[] = {
83 "assoc_req", "assoc_resp", "reassoc_req", "reassoc_resp",
84 "probe_req", "probe_resp", "reserved#6", "reserved#7",
85 "beacon", "atim", "disassoc", "auth",
86 "deauth", "reserved#13", "reserved#14", "reserved#15"
88 const char *ieee80211_ctl_subtype_name
[] = {
89 "reserved#0", "reserved#1", "reserved#2", "reserved#3",
90 "reserved#3", "reserved#5", "reserved#6", "reserved#7",
91 "reserved#8", "reserved#9", "ps_poll", "rts",
92 "cts", "ack", "cf_end", "cf_end_ack"
94 const char *ieee80211_state_name
[IEEE80211_S_MAX
] = {
95 "INIT", /* IEEE80211_S_INIT */
96 "SCAN", /* IEEE80211_S_SCAN */
97 "AUTH", /* IEEE80211_S_AUTH */
98 "ASSOC", /* IEEE80211_S_ASSOC */
99 "RUN" /* IEEE80211_S_RUN */
101 const char *ieee80211_wme_acnames
[] = {
109 static int ieee80211_newstate(struct ieee80211com
*, enum ieee80211_state
, int);
112 ieee80211_proto_attach(struct ieee80211com
*ic
)
114 struct ifnet
*ifp
= ic
->ic_ifp
;
116 /* XXX room for crypto */
117 ifp
->if_hdrlen
= sizeof(struct ieee80211_qosframe_addr4
);
119 ic
->ic_rtsthreshold
= IEEE80211_RTS_DEFAULT
;
120 ic
->ic_fragthreshold
= IEEE80211_FRAG_DEFAULT
;
121 ic
->ic_fixed_rate
= IEEE80211_FIXED_RATE_NONE
;
122 ic
->ic_bmiss_max
= IEEE80211_BMISS_MAX
;
123 ic
->ic_mcast_rate
= IEEE80211_MCAST_RATE_DEFAULT
;
124 ic
->ic_protmode
= IEEE80211_PROT_CTSONLY
;
125 ic
->ic_roaming
= IEEE80211_ROAMING_AUTO
;
127 ic
->ic_wme
.wme_hipri_switch_hysteresis
=
128 AGGRESSIVE_MODE_SWITCH_HYSTERESIS
;
130 /* protocol state change handler */
131 ic
->ic_newstate
= ieee80211_newstate
;
133 /* initialize management frame handlers */
134 ic
->ic_recv_mgmt
= ieee80211_recv_mgmt
;
135 ic
->ic_send_mgmt
= ieee80211_send_mgmt
;
139 ieee80211_proto_detach(struct ieee80211com
*ic
)
143 * This should not be needed as we detach when reseting
144 * the state but be conservative here since the
145 * authenticator may do things like spawn kernel threads.
147 if (ic
->ic_auth
->ia_detach
)
148 ic
->ic_auth
->ia_detach(ic
);
150 ieee80211_drain_ifq(&ic
->ic_mgtq
);
153 * Detach any ACL'ator.
155 if (ic
->ic_acl
!= NULL
)
156 ic
->ic_acl
->iac_detach(ic
);
160 * Simple-minded authenticator module support.
163 #define IEEE80211_AUTH_MAX (IEEE80211_AUTH_WPA+1)
164 /* XXX well-known names */
165 static const char *auth_modnames
[IEEE80211_AUTH_MAX
] = {
166 "wlan_internal", /* IEEE80211_AUTH_NONE */
167 "wlan_internal", /* IEEE80211_AUTH_OPEN */
168 "wlan_internal", /* IEEE80211_AUTH_SHARED */
169 "wlan_xauth", /* IEEE80211_AUTH_8021X */
170 "wlan_internal", /* IEEE80211_AUTH_AUTO */
171 "wlan_xauth", /* IEEE80211_AUTH_WPA */
173 static const struct ieee80211_authenticator
*authenticators
[IEEE80211_AUTH_MAX
];
175 static const struct ieee80211_authenticator auth_internal
= {
176 .ia_name
= "wlan_internal",
179 .ia_node_join
= NULL
,
180 .ia_node_leave
= NULL
,
184 * Setup internal authenticators once; they are never unregistered.
187 ieee80211_auth_setup(void)
189 ieee80211_authenticator_register(IEEE80211_AUTH_OPEN
, &auth_internal
);
190 ieee80211_authenticator_register(IEEE80211_AUTH_SHARED
, &auth_internal
);
191 ieee80211_authenticator_register(IEEE80211_AUTH_AUTO
, &auth_internal
);
194 const struct ieee80211_authenticator
*
195 ieee80211_authenticator_get(int auth
)
197 static int initialized
= 0;
199 ieee80211_auth_setup();
202 if (auth
>= IEEE80211_AUTH_MAX
)
204 if (authenticators
[auth
] == NULL
)
205 ieee80211_load_module(auth_modnames
[auth
]);
206 return authenticators
[auth
];
210 ieee80211_authenticator_register(int type
,
211 const struct ieee80211_authenticator
*auth
)
213 if (type
>= IEEE80211_AUTH_MAX
)
215 authenticators
[type
] = auth
;
219 ieee80211_authenticator_unregister(int type
)
222 if (type
>= IEEE80211_AUTH_MAX
)
224 authenticators
[type
] = NULL
;
228 * Very simple-minded ACL module support.
230 /* XXX just one for now */
231 static const struct ieee80211_aclator
*acl
= NULL
;
234 ieee80211_aclator_register(const struct ieee80211_aclator
*iac
)
236 printf("wlan: %s acl policy registered\n", iac
->iac_name
);
241 ieee80211_aclator_unregister(const struct ieee80211_aclator
*iac
)
245 printf("wlan: %s acl policy unregistered\n", iac
->iac_name
);
248 const struct ieee80211_aclator
*
249 ieee80211_aclator_get(const char *name
)
252 ieee80211_load_module("wlan_acl");
253 return acl
!= NULL
&& strcmp(acl
->iac_name
, name
) == 0 ? acl
: NULL
;
257 ieee80211_print_essid(const u_int8_t
*essid
, int len
)
262 if (len
> IEEE80211_NWID_LEN
)
263 len
= IEEE80211_NWID_LEN
;
264 /* determine printable or not */
265 for (i
= 0, p
= essid
; i
< len
; i
++, p
++) {
266 if (*p
< ' ' || *p
> 0x7e)
271 for (i
= 0, p
= essid
; i
< len
; i
++, p
++)
276 for (i
= 0, p
= essid
; i
< len
; i
++, p
++)
282 ieee80211_dump_pkt(const u_int8_t
*buf
, int len
, int rate
, int rssi
)
284 const struct ieee80211_frame
*wh
;
287 wh
= (const struct ieee80211_frame
*)buf
;
288 switch (wh
->i_fc
[1] & IEEE80211_FC1_DIR_MASK
) {
289 case IEEE80211_FC1_DIR_NODS
:
290 printf("NODS %s", ether_sprintf(wh
->i_addr2
));
291 printf("->%s", ether_sprintf(wh
->i_addr1
));
292 printf("(%s)", ether_sprintf(wh
->i_addr3
));
294 case IEEE80211_FC1_DIR_TODS
:
295 printf("TODS %s", ether_sprintf(wh
->i_addr2
));
296 printf("->%s", ether_sprintf(wh
->i_addr3
));
297 printf("(%s)", ether_sprintf(wh
->i_addr1
));
299 case IEEE80211_FC1_DIR_FROMDS
:
300 printf("FRDS %s", ether_sprintf(wh
->i_addr3
));
301 printf("->%s", ether_sprintf(wh
->i_addr1
));
302 printf("(%s)", ether_sprintf(wh
->i_addr2
));
304 case IEEE80211_FC1_DIR_DSTODS
:
305 printf("DSDS %s", ether_sprintf((const u_int8_t
*)&wh
[1]));
306 printf("->%s", ether_sprintf(wh
->i_addr3
));
307 printf("(%s", ether_sprintf(wh
->i_addr2
));
308 printf("->%s)", ether_sprintf(wh
->i_addr1
));
311 switch (wh
->i_fc
[0] & IEEE80211_FC0_TYPE_MASK
) {
312 case IEEE80211_FC0_TYPE_DATA
:
315 case IEEE80211_FC0_TYPE_MGT
:
316 printf(" %s", ieee80211_mgt_subtype_name
[
317 (wh
->i_fc
[0] & IEEE80211_FC0_SUBTYPE_MASK
)
318 >> IEEE80211_FC0_SUBTYPE_SHIFT
]);
321 printf(" type#%d", wh
->i_fc
[0] & IEEE80211_FC0_TYPE_MASK
);
324 if (wh
->i_fc
[1] & IEEE80211_FC1_WEP
) {
326 for (i
= 0; i
< IEEE80211_WEP_IVLEN
; i
++)
327 printf(" %.02x", buf
[sizeof(*wh
)+i
]);
328 printf(" KID %u]", buf
[sizeof(*wh
)+i
] >> 6);
331 printf(" %dM", rate
/ 2);
333 printf(" +%d", rssi
);
336 for (i
= 0; i
< len
; i
++) {
339 printf("%02x", buf
[i
]);
346 ieee80211_fix_rate(struct ieee80211_node
*ni
, int flags
)
348 #define RV(v) ((v) & IEEE80211_RATE_VAL)
349 struct ieee80211com
*ic
= ni
->ni_ic
;
350 int i
, j
, ignore
, error
;
351 int okrate
, badrate
, fixedrate
;
352 struct ieee80211_rateset
*srs
, *nrs
;
356 * If the fixed rate check was requested but no
357 * fixed has been defined then just remove it.
359 if ((flags
& IEEE80211_F_DOFRATE
) &&
360 ic
->ic_fixed_rate
== IEEE80211_FIXED_RATE_NONE
)
361 flags
&= ~IEEE80211_F_DOFRATE
;
363 okrate
= badrate
= fixedrate
= 0;
364 srs
= &ic
->ic_sup_rates
[ieee80211_chan2mode(ic
, ni
->ni_chan
)];
366 for (i
= 0; i
< nrs
->rs_nrates
; ) {
368 if (flags
& IEEE80211_F_DOSORT
) {
372 for (j
= i
+ 1; j
< nrs
->rs_nrates
; j
++) {
373 if (RV(nrs
->rs_rates
[i
]) > RV(nrs
->rs_rates
[j
])) {
374 r
= nrs
->rs_rates
[i
];
375 nrs
->rs_rates
[i
] = nrs
->rs_rates
[j
];
376 nrs
->rs_rates
[j
] = r
;
380 r
= nrs
->rs_rates
[i
] & IEEE80211_RATE_VAL
;
382 if (flags
& IEEE80211_F_DOFRATE
) {
384 * Check any fixed rate is included.
386 if (r
== RV(srs
->rs_rates
[ic
->ic_fixed_rate
]))
389 if (flags
& IEEE80211_F_DONEGO
) {
391 * Check against supported rates.
393 for (j
= 0; j
< srs
->rs_nrates
; j
++) {
394 if (r
== RV(srs
->rs_rates
[j
])) {
396 * Overwrite with the supported rate
397 * value so any basic rate bit is set.
398 * This insures that response we send
399 * to stations have the necessary basic
402 nrs
->rs_rates
[i
] = srs
->rs_rates
[j
];
406 if (j
== srs
->rs_nrates
) {
408 * A rate in the node's rate set is not
409 * supported. If this is a basic rate and we
410 * are operating as an AP then this is an error.
411 * Otherwise we just discard/ignore the rate.
412 * Note that this is important for 11b stations
413 * when they want to associate with an 11g AP.
415 #ifndef IEEE80211_NO_HOSTAP
416 if (ic
->ic_opmode
== IEEE80211_M_HOSTAP
&&
417 (nrs
->rs_rates
[i
] & IEEE80211_RATE_BASIC
))
419 #endif /* !IEEE80211_NO_HOSTAP */
423 if (flags
& IEEE80211_F_DODEL
) {
425 * Delete unacceptable rates.
429 for (j
= i
; j
< nrs
->rs_nrates
; j
++)
430 nrs
->rs_rates
[j
] = nrs
->rs_rates
[j
+ 1];
431 nrs
->rs_rates
[j
] = 0;
436 okrate
= nrs
->rs_rates
[i
];
441 if (okrate
== 0 || error
!= 0 ||
442 ((flags
& IEEE80211_F_DOFRATE
) && fixedrate
== 0))
443 return badrate
| IEEE80211_RATE_BASIC
;
450 * Reset 11g-related state.
453 ieee80211_reset_erp(struct ieee80211com
*ic
)
455 ic
->ic_flags
&= ~IEEE80211_F_USEPROT
;
456 ic
->ic_nonerpsta
= 0;
457 ic
->ic_longslotsta
= 0;
459 * Short slot time is enabled only when operating in 11g
460 * and not in an IBSS. We must also honor whether or not
461 * the driver is capable of doing it.
463 ieee80211_set_shortslottime(ic
,
464 ic
->ic_curmode
== IEEE80211_MODE_11A
||
465 (ic
->ic_curmode
== IEEE80211_MODE_11G
&&
466 ic
->ic_opmode
== IEEE80211_M_HOSTAP
&&
467 (ic
->ic_caps
& IEEE80211_C_SHSLOT
)));
469 * Set short preamble and ERP barker-preamble flags.
471 if (ic
->ic_curmode
== IEEE80211_MODE_11A
||
472 (ic
->ic_caps
& IEEE80211_C_SHPREAMBLE
)) {
473 ic
->ic_flags
|= IEEE80211_F_SHPREAMBLE
;
474 ic
->ic_flags
&= ~IEEE80211_F_USEBARKER
;
476 ic
->ic_flags
&= ~IEEE80211_F_SHPREAMBLE
;
477 ic
->ic_flags
|= IEEE80211_F_USEBARKER
;
482 * Set the short slot time state and notify the driver.
485 ieee80211_set_shortslottime(struct ieee80211com
*ic
, int onoff
)
488 ic
->ic_flags
|= IEEE80211_F_SHSLOT
;
490 ic
->ic_flags
&= ~IEEE80211_F_SHSLOT
;
492 if (ic
->ic_updateslot
!= NULL
)
493 ic
->ic_updateslot(ic
->ic_ifp
);
497 * Check if the specified rate set supports ERP.
498 * NB: the rate set is assumed to be sorted.
501 ieee80211_iserp_rateset(struct ieee80211com
*ic
,
502 struct ieee80211_rateset
*rs
)
504 #define N(a) (sizeof(a) / sizeof(a[0]))
505 static const int rates
[] = { 2, 4, 11, 22, 12, 24, 48 };
508 if (rs
->rs_nrates
< N(rates
))
510 for (i
= 0; i
< N(rates
); i
++) {
511 for (j
= 0; j
< rs
->rs_nrates
; j
++) {
512 int r
= rs
->rs_rates
[j
] & IEEE80211_RATE_VAL
;
527 * Mark the basic rates for the 11g rate table based on the
528 * operating mode. For real 11g we mark all the 11b rates
529 * and 6, 12, and 24 OFDM. For 11b compatibility we mark only
530 * 11b rates. There's also a pseudo 11a-mode used to mark only
531 * the basic OFDM rates.
534 ieee80211_set11gbasicrates(struct ieee80211_rateset
*rs
, enum ieee80211_phymode mode
)
536 static const struct ieee80211_rateset basic
[] = {
537 { .rs_nrates
= 0 }, /* IEEE80211_MODE_AUTO */
538 { 3, { 12, 24, 48 } }, /* IEEE80211_MODE_11A */
539 { 2, { 2, 4 } }, /* IEEE80211_MODE_11B */
540 { 4, { 2, 4, 11, 22 } }, /* IEEE80211_MODE_11G (mixed b/g) */
541 { .rs_nrates
= 0 }, /* IEEE80211_MODE_FH */
542 /* IEEE80211_MODE_PUREG (not yet) */
543 { 7, { 2, 4, 11, 22, 12, 24, 48 } },
547 for (i
= 0; i
< rs
->rs_nrates
; i
++) {
548 rs
->rs_rates
[i
] &= IEEE80211_RATE_VAL
;
549 for (j
= 0; j
< basic
[mode
].rs_nrates
; j
++)
550 if (basic
[mode
].rs_rates
[j
] == rs
->rs_rates
[i
]) {
551 rs
->rs_rates
[i
] |= IEEE80211_RATE_BASIC
;
558 * WME protocol support. The following parameters come from the spec.
560 typedef struct phyParamType
{
568 static const struct phyParamType phyParamForAC_BE
[IEEE80211_MODE_MAX
] = {
569 { 3, 4, 6, 0, 0, }, /* IEEE80211_MODE_AUTO */
570 { 3, 4, 6, 0, 0, }, /* IEEE80211_MODE_11A */
571 { 3, 5, 7, 0, 0, }, /* IEEE80211_MODE_11B */
572 { 3, 4, 6, 0, 0, }, /* IEEE80211_MODE_11G */
573 { 3, 5, 7, 0, 0, }, /* IEEE80211_MODE_FH */
574 { 2, 3, 5, 0, 0, }, /* IEEE80211_MODE_TURBO_A */
575 { 2, 3, 5, 0, 0, }, /* IEEE80211_MODE_TURBO_G */
577 static const struct phyParamType phyParamForAC_BK
[IEEE80211_MODE_MAX
] = {
578 { 7, 4, 10, 0, 0, }, /* IEEE80211_MODE_AUTO */
579 { 7, 4, 10, 0, 0, }, /* IEEE80211_MODE_11A */
580 { 7, 5, 10, 0, 0, }, /* IEEE80211_MODE_11B */
581 { 7, 4, 10, 0, 0, }, /* IEEE80211_MODE_11G */
582 { 7, 5, 10, 0, 0, }, /* IEEE80211_MODE_FH */
583 { 7, 3, 10, 0, 0, }, /* IEEE80211_MODE_TURBO_A */
584 { 7, 3, 10, 0, 0, }, /* IEEE80211_MODE_TURBO_G */
586 static const struct phyParamType phyParamForAC_VI
[IEEE80211_MODE_MAX
] = {
587 { 1, 3, 4, 94, 0, }, /* IEEE80211_MODE_AUTO */
588 { 1, 3, 4, 94, 0, }, /* IEEE80211_MODE_11A */
589 { 1, 4, 5, 188, 0, }, /* IEEE80211_MODE_11B */
590 { 1, 3, 4, 94, 0, }, /* IEEE80211_MODE_11G */
591 { 1, 4, 5, 188, 0, }, /* IEEE80211_MODE_FH */
592 { 1, 2, 3, 94, 0, }, /* IEEE80211_MODE_TURBO_A */
593 { 1, 2, 3, 94, 0, }, /* IEEE80211_MODE_TURBO_G */
595 static const struct phyParamType phyParamForAC_VO
[IEEE80211_MODE_MAX
] = {
596 { 1, 2, 3, 47, 0, }, /* IEEE80211_MODE_AUTO */
597 { 1, 2, 3, 47, 0, }, /* IEEE80211_MODE_11A */
598 { 1, 3, 4, 102, 0, }, /* IEEE80211_MODE_11B */
599 { 1, 2, 3, 47, 0, }, /* IEEE80211_MODE_11G */
600 { 1, 3, 4, 102, 0, }, /* IEEE80211_MODE_FH */
601 { 1, 2, 2, 47, 0, }, /* IEEE80211_MODE_TURBO_A */
602 { 1, 2, 2, 47, 0, }, /* IEEE80211_MODE_TURBO_G */
605 static const struct phyParamType bssPhyParamForAC_BE
[IEEE80211_MODE_MAX
] = {
606 { 3, 4, 10, 0, 0, }, /* IEEE80211_MODE_AUTO */
607 { 3, 4, 10, 0, 0, }, /* IEEE80211_MODE_11A */
608 { 3, 5, 10, 0, 0, }, /* IEEE80211_MODE_11B */
609 { 3, 4, 10, 0, 0, }, /* IEEE80211_MODE_11G */
610 { 3, 5, 10, 0, 0, }, /* IEEE80211_MODE_FH */
611 { 2, 3, 10, 0, 0, }, /* IEEE80211_MODE_TURBO_A */
612 { 2, 3, 10, 0, 0, }, /* IEEE80211_MODE_TURBO_G */
614 static const struct phyParamType bssPhyParamForAC_VI
[IEEE80211_MODE_MAX
] = {
615 { 2, 3, 4, 94, 0, }, /* IEEE80211_MODE_AUTO */
616 { 2, 3, 4, 94, 0, }, /* IEEE80211_MODE_11A */
617 { 2, 4, 5, 188, 0, }, /* IEEE80211_MODE_11B */
618 { 2, 3, 4, 94, 0, }, /* IEEE80211_MODE_11G */
619 { 2, 4, 5, 188, 0, }, /* IEEE80211_MODE_FH */
620 { 2, 2, 3, 94, 0, }, /* IEEE80211_MODE_TURBO_A */
621 { 2, 2, 3, 94, 0, }, /* IEEE80211_MODE_TURBO_G */
623 static const struct phyParamType bssPhyParamForAC_VO
[IEEE80211_MODE_MAX
] = {
624 { 2, 2, 3, 47, 0, }, /* IEEE80211_MODE_AUTO */
625 { 2, 2, 3, 47, 0, }, /* IEEE80211_MODE_11A */
626 { 2, 3, 4, 102, 0, }, /* IEEE80211_MODE_11B */
627 { 2, 2, 3, 47, 0, }, /* IEEE80211_MODE_11G */
628 { 2, 3, 4, 102, 0, }, /* IEEE80211_MODE_FH */
629 { 1, 2, 2, 47, 0, }, /* IEEE80211_MODE_TURBO_A */
630 { 1, 2, 2, 47, 0, }, /* IEEE80211_MODE_TURBO_G */
634 ieee80211_wme_initparams(struct ieee80211com
*ic
)
636 struct ieee80211_wme_state
*wme
= &ic
->ic_wme
;
637 const paramType
*pPhyParam
, *pBssPhyParam
;
638 struct wmeParams
*wmep
;
641 if ((ic
->ic_caps
& IEEE80211_C_WME
) == 0)
644 for (i
= 0; i
< WME_NUM_AC
; i
++) {
647 pPhyParam
= &phyParamForAC_BK
[ic
->ic_curmode
];
648 pBssPhyParam
= &phyParamForAC_BK
[ic
->ic_curmode
];
651 pPhyParam
= &phyParamForAC_VI
[ic
->ic_curmode
];
652 pBssPhyParam
= &bssPhyParamForAC_VI
[ic
->ic_curmode
];
655 pPhyParam
= &phyParamForAC_VO
[ic
->ic_curmode
];
656 pBssPhyParam
= &bssPhyParamForAC_VO
[ic
->ic_curmode
];
660 pPhyParam
= &phyParamForAC_BE
[ic
->ic_curmode
];
661 pBssPhyParam
= &bssPhyParamForAC_BE
[ic
->ic_curmode
];
665 wmep
= &wme
->wme_wmeChanParams
.cap_wmeParams
[i
];
666 if (ic
->ic_opmode
== IEEE80211_M_HOSTAP
) {
667 wmep
->wmep_acm
= pPhyParam
->acm
;
668 wmep
->wmep_aifsn
= pPhyParam
->aifsn
;
669 wmep
->wmep_logcwmin
= pPhyParam
->logcwmin
;
670 wmep
->wmep_logcwmax
= pPhyParam
->logcwmax
;
671 wmep
->wmep_txopLimit
= pPhyParam
->txopLimit
;
673 wmep
->wmep_acm
= pBssPhyParam
->acm
;
674 wmep
->wmep_aifsn
= pBssPhyParam
->aifsn
;
675 wmep
->wmep_logcwmin
= pBssPhyParam
->logcwmin
;
676 wmep
->wmep_logcwmax
= pBssPhyParam
->logcwmax
;
677 wmep
->wmep_txopLimit
= pBssPhyParam
->txopLimit
;
680 IEEE80211_DPRINTF(ic
, IEEE80211_MSG_WME
,
681 "%s: %s chan [acm %u aifsn %u log2(cwmin) %u "
682 "log2(cwmax) %u txpoLimit %u]\n", __func__
683 , ieee80211_wme_acnames
[i
]
686 , wmep
->wmep_logcwmin
687 , wmep
->wmep_logcwmax
688 , wmep
->wmep_txopLimit
691 wmep
= &wme
->wme_wmeBssChanParams
.cap_wmeParams
[i
];
692 wmep
->wmep_acm
= pBssPhyParam
->acm
;
693 wmep
->wmep_aifsn
= pBssPhyParam
->aifsn
;
694 wmep
->wmep_logcwmin
= pBssPhyParam
->logcwmin
;
695 wmep
->wmep_logcwmax
= pBssPhyParam
->logcwmax
;
696 wmep
->wmep_txopLimit
= pBssPhyParam
->txopLimit
;
697 IEEE80211_DPRINTF(ic
, IEEE80211_MSG_WME
,
698 "%s: %s bss [acm %u aifsn %u log2(cwmin) %u "
699 "log2(cwmax) %u txpoLimit %u]\n", __func__
700 , ieee80211_wme_acnames
[i
]
703 , wmep
->wmep_logcwmin
704 , wmep
->wmep_logcwmax
705 , wmep
->wmep_txopLimit
708 /* NB: check ic_bss to avoid NULL deref on initial attach */
709 if (ic
->ic_bss
!= NULL
) {
711 * Calculate agressive mode switching threshold based
712 * on beacon interval. This doesn't need locking since
713 * we're only called before entering the RUN state at
714 * which point we start sending beacon frames.
716 wme
->wme_hipri_switch_thresh
=
717 (HIGH_PRI_SWITCH_THRESH
* ic
->ic_bss
->ni_intval
) / 100;
718 ieee80211_wme_updateparams(ic
);
723 * Update WME parameters for ourself and the BSS.
726 ieee80211_wme_updateparams_locked(struct ieee80211com
*ic
)
728 static const paramType phyParam
[IEEE80211_MODE_MAX
] = {
729 { 2, 4, 10, 64, 0, }, /* IEEE80211_MODE_AUTO */
730 { 2, 4, 10, 64, 0, }, /* IEEE80211_MODE_11A */
731 { 2, 5, 10, 64, 0, }, /* IEEE80211_MODE_11B */
732 { 2, 4, 10, 64, 0, }, /* IEEE80211_MODE_11G */
733 { 2, 5, 10, 64, 0, }, /* IEEE80211_MODE_FH */
734 { 1, 3, 10, 64, 0, }, /* IEEE80211_MODE_TURBO_A */
735 { 1, 3, 10, 64, 0, }, /* IEEE80211_MODE_TURBO_G */
737 struct ieee80211_wme_state
*wme
= &ic
->ic_wme
;
738 const struct wmeParams
*wmep
;
739 struct wmeParams
*chanp
, *bssp
;
742 /* set up the channel access parameters for the physical device */
743 for (i
= 0; i
< WME_NUM_AC
; i
++) {
744 chanp
= &wme
->wme_chanParams
.cap_wmeParams
[i
];
745 wmep
= &wme
->wme_wmeChanParams
.cap_wmeParams
[i
];
746 chanp
->wmep_aifsn
= wmep
->wmep_aifsn
;
747 chanp
->wmep_logcwmin
= wmep
->wmep_logcwmin
;
748 chanp
->wmep_logcwmax
= wmep
->wmep_logcwmax
;
749 chanp
->wmep_txopLimit
= wmep
->wmep_txopLimit
;
751 chanp
= &wme
->wme_bssChanParams
.cap_wmeParams
[i
];
752 wmep
= &wme
->wme_wmeBssChanParams
.cap_wmeParams
[i
];
753 chanp
->wmep_aifsn
= wmep
->wmep_aifsn
;
754 chanp
->wmep_logcwmin
= wmep
->wmep_logcwmin
;
755 chanp
->wmep_logcwmax
= wmep
->wmep_logcwmax
;
756 chanp
->wmep_txopLimit
= wmep
->wmep_txopLimit
;
760 * This implements agressive mode as found in certain
761 * vendors' AP's. When there is significant high
762 * priority (VI/VO) traffic in the BSS throttle back BE
763 * traffic by using conservative parameters. Otherwise
764 * BE uses agressive params to optimize performance of
765 * legacy/non-QoS traffic.
767 if ((ic
->ic_opmode
== IEEE80211_M_HOSTAP
&&
768 (wme
->wme_flags
& WME_F_AGGRMODE
) == 0) ||
769 (ic
->ic_opmode
!= IEEE80211_M_HOSTAP
&&
770 (ic
->ic_bss
->ni_flags
& IEEE80211_NODE_QOS
) == 0) ||
771 (ic
->ic_flags
& IEEE80211_F_WME
) == 0) {
772 chanp
= &wme
->wme_chanParams
.cap_wmeParams
[WME_AC_BE
];
773 bssp
= &wme
->wme_bssChanParams
.cap_wmeParams
[WME_AC_BE
];
775 chanp
->wmep_aifsn
= bssp
->wmep_aifsn
=
776 phyParam
[ic
->ic_curmode
].aifsn
;
777 chanp
->wmep_logcwmin
= bssp
->wmep_logcwmin
=
778 phyParam
[ic
->ic_curmode
].logcwmin
;
779 chanp
->wmep_logcwmax
= bssp
->wmep_logcwmax
=
780 phyParam
[ic
->ic_curmode
].logcwmax
;
781 chanp
->wmep_txopLimit
= bssp
->wmep_txopLimit
=
782 (ic
->ic_caps
& IEEE80211_C_BURST
) ?
783 phyParam
[ic
->ic_curmode
].txopLimit
: 0;
784 IEEE80211_DPRINTF(ic
, IEEE80211_MSG_WME
,
785 "%s: %s [acm %u aifsn %u log2(cwmin) %u "
786 "log2(cwmax) %u txpoLimit %u]\n", __func__
787 , ieee80211_wme_acnames
[WME_AC_BE
]
790 , chanp
->wmep_logcwmin
791 , chanp
->wmep_logcwmax
792 , chanp
->wmep_txopLimit
796 #ifndef IEEE80211_NO_HOSTAP
797 if (ic
->ic_opmode
== IEEE80211_M_HOSTAP
&&
798 ic
->ic_sta_assoc
< 2 && (wme
->wme_flags
& WME_F_AGGRMODE
) == 0) {
799 static const u_int8_t logCwMin
[IEEE80211_MODE_MAX
] = {
800 3, /* IEEE80211_MODE_AUTO */
801 3, /* IEEE80211_MODE_11A */
802 4, /* IEEE80211_MODE_11B */
803 3, /* IEEE80211_MODE_11G */
804 4, /* IEEE80211_MODE_FH */
805 3, /* IEEE80211_MODE_TURBO_A */
806 3, /* IEEE80211_MODE_TURBO_G */
808 chanp
= &wme
->wme_chanParams
.cap_wmeParams
[WME_AC_BE
];
809 bssp
= &wme
->wme_bssChanParams
.cap_wmeParams
[WME_AC_BE
];
811 chanp
->wmep_logcwmin
= bssp
->wmep_logcwmin
=
812 logCwMin
[ic
->ic_curmode
];
813 IEEE80211_DPRINTF(ic
, IEEE80211_MSG_WME
,
814 "%s: %s log2(cwmin) %u\n", __func__
815 , ieee80211_wme_acnames
[WME_AC_BE
]
816 , chanp
->wmep_logcwmin
819 if (ic
->ic_opmode
== IEEE80211_M_HOSTAP
) { /* XXX ibss? */
821 * Arrange for a beacon update and bump the parameter
822 * set number so associated stations load the new values.
824 wme
->wme_bssChanParams
.cap_info
=
825 (wme
->wme_bssChanParams
.cap_info
+1) & WME_QOSINFO_COUNT
;
826 ic
->ic_flags
|= IEEE80211_F_WMEUPDATE
;
828 #endif /* !IEEE80211_NO_HOSTAP */
832 IEEE80211_DPRINTF(ic
, IEEE80211_MSG_WME
,
833 "%s: WME params updated, cap_info 0x%x\n", __func__
,
834 ic
->ic_opmode
== IEEE80211_M_STA
?
835 wme
->wme_wmeChanParams
.cap_info
:
836 wme
->wme_bssChanParams
.cap_info
);
840 ieee80211_wme_updateparams(struct ieee80211com
*ic
)
843 if (ic
->ic_caps
& IEEE80211_C_WME
) {
844 IEEE80211_BEACON_LOCK(ic
);
845 ieee80211_wme_updateparams_locked(ic
);
846 IEEE80211_BEACON_UNLOCK(ic
);
850 #ifndef IEEE80211_NO_HOSTAP
852 sta_disassoc(void *arg
, struct ieee80211_node
*ni
)
854 struct ieee80211com
*ic
= arg
;
856 if (ni
->ni_associd
!= 0) {
857 IEEE80211_SEND_MGMT(ic
, ni
, IEEE80211_FC0_SUBTYPE_DISASSOC
,
858 IEEE80211_REASON_ASSOC_LEAVE
);
859 ieee80211_node_leave(ic
, ni
);
862 #endif /* !IEEE80211_NO_HOSTAP */
865 ieee80211_beacon_miss(struct ieee80211com
*ic
)
868 if (ic
->ic_flags
& IEEE80211_F_SCAN
) {
869 /* XXX check ic_curchan != ic_bsschan? */
872 IEEE80211_DPRINTF(ic
,
873 IEEE80211_MSG_STATE
| IEEE80211_MSG_DEBUG
,
874 "%s\n", "beacon miss");
877 * Our handling is only meaningful for stations that are
878 * associated; any other conditions else will be handled
879 * through different means (e.g. the tx timeout on mgt frames).
881 if (ic
->ic_opmode
!= IEEE80211_M_STA
|| ic
->ic_state
!= IEEE80211_S_RUN
)
884 if (++ic
->ic_bmiss_count
< ic
->ic_bmiss_max
) {
886 * Send a directed probe req before falling back to a scan;
887 * if we receive a response ic_bmiss_count will be reset.
888 * Some cards mistakenly report beacon miss so this avoids
889 * the expensive scan if the ap is still there.
891 ieee80211_send_probereq(ic
->ic_bss
, ic
->ic_myaddr
,
892 ic
->ic_bss
->ni_bssid
, ic
->ic_bss
->ni_bssid
,
893 ic
->ic_bss
->ni_essid
, ic
->ic_bss
->ni_esslen
,
894 ic
->ic_opt_ie
, ic
->ic_opt_ie_len
);
897 ic
->ic_bmiss_count
= 0;
898 ieee80211_new_state(ic
, IEEE80211_S_SCAN
, 0);
901 #ifndef IEEE80211_NO_HOSTAP
903 sta_deauth(void *arg
, struct ieee80211_node
*ni
)
905 struct ieee80211com
*ic
= arg
;
907 IEEE80211_SEND_MGMT(ic
, ni
, IEEE80211_FC0_SUBTYPE_DEAUTH
,
908 IEEE80211_REASON_ASSOC_LEAVE
);
910 #endif /* !IEEE80211_NO_HOSTAP */
913 ieee80211_newstate(struct ieee80211com
*ic
, enum ieee80211_state nstate
, int arg
)
915 struct ifnet
*ifp
= ic
->ic_ifp
;
916 struct ieee80211_node
*ni
;
917 enum ieee80211_state ostate
;
919 ostate
= ic
->ic_state
;
920 IEEE80211_DPRINTF(ic
, IEEE80211_MSG_STATE
, "%s: %s -> %s\n", __func__
,
921 ieee80211_state_name
[ostate
], ieee80211_state_name
[nstate
]);
922 ic
->ic_state
= nstate
; /* state transition */
923 ni
= ic
->ic_bss
; /* NB: no reference held */
925 case IEEE80211_S_INIT
:
927 case IEEE80211_S_INIT
:
929 case IEEE80211_S_RUN
:
930 switch (ic
->ic_opmode
) {
931 case IEEE80211_M_STA
:
932 IEEE80211_SEND_MGMT(ic
, ni
,
933 IEEE80211_FC0_SUBTYPE_DISASSOC
,
934 IEEE80211_REASON_ASSOC_LEAVE
);
935 ieee80211_sta_leave(ic
, ni
);
937 case IEEE80211_M_HOSTAP
:
938 #ifndef IEEE80211_NO_HOSTAP
939 ieee80211_iterate_nodes(&ic
->ic_sta
,
941 #endif /* !IEEE80211_NO_HOSTAP */
947 case IEEE80211_S_ASSOC
:
948 switch (ic
->ic_opmode
) {
949 case IEEE80211_M_STA
:
950 IEEE80211_SEND_MGMT(ic
, ni
,
951 IEEE80211_FC0_SUBTYPE_DEAUTH
,
952 IEEE80211_REASON_AUTH_LEAVE
);
954 case IEEE80211_M_HOSTAP
:
955 #ifndef IEEE80211_NO_HOSTAP
956 ieee80211_iterate_nodes(&ic
->ic_sta
,
958 #endif /* !IEEE80211_NO_HOSTAP */
964 case IEEE80211_S_SCAN
:
965 ieee80211_cancel_scan(ic
);
967 case IEEE80211_S_AUTH
:
969 ic
->ic_mgt_timer
= 0;
970 ieee80211_drain_ifq(&ic
->ic_mgtq
);
971 ieee80211_reset_bss(ic
);
974 if (ic
->ic_auth
->ia_detach
!= NULL
)
975 ic
->ic_auth
->ia_detach(ic
);
977 case IEEE80211_S_SCAN
:
979 case IEEE80211_S_INIT
:
980 if ((ic
->ic_opmode
== IEEE80211_M_HOSTAP
||
981 ic
->ic_opmode
== IEEE80211_M_IBSS
||
982 ic
->ic_opmode
== IEEE80211_M_AHDEMO
) &&
983 ic
->ic_des_chan
!= IEEE80211_CHAN_ANYC
) {
985 * AP operation and we already have a channel;
986 * bypass the scan and startup immediately.
988 ieee80211_create_ibss(ic
, ic
->ic_des_chan
);
990 ieee80211_begin_scan(ic
, arg
);
993 case IEEE80211_S_SCAN
:
995 * Scan next. If doing an active scan probe
996 * for the requested ap (if any).
998 if (ic
->ic_flags
& IEEE80211_F_ASCAN
)
999 ieee80211_probe_curchan(ic
, 0);
1001 case IEEE80211_S_RUN
:
1003 IEEE80211_DPRINTF(ic
, IEEE80211_MSG_STATE
,
1004 "no recent beacons from %s; rescanning\n",
1005 ether_sprintf(ic
->ic_bss
->ni_bssid
));
1006 ieee80211_sta_leave(ic
, ni
);
1007 ic
->ic_flags
&= ~IEEE80211_F_SIBSS
; /* XXX */
1009 case IEEE80211_S_AUTH
:
1010 case IEEE80211_S_ASSOC
:
1011 /* timeout restart scan */
1012 ni
= ieee80211_find_node(&ic
->ic_scan
,
1013 ic
->ic_bss
->ni_macaddr
);
1016 ieee80211_unref_node(&ni
);
1018 if (ic
->ic_roaming
== IEEE80211_ROAMING_AUTO
)
1019 ieee80211_begin_scan(ic
, arg
);
1023 case IEEE80211_S_AUTH
:
1025 case IEEE80211_S_INIT
:
1026 case IEEE80211_S_SCAN
:
1027 IEEE80211_SEND_MGMT(ic
, ni
,
1028 IEEE80211_FC0_SUBTYPE_AUTH
, 1);
1030 case IEEE80211_S_AUTH
:
1031 case IEEE80211_S_ASSOC
:
1033 case IEEE80211_FC0_SUBTYPE_AUTH
:
1035 IEEE80211_SEND_MGMT(ic
, ni
,
1036 IEEE80211_FC0_SUBTYPE_AUTH
, 2);
1038 case IEEE80211_FC0_SUBTYPE_DEAUTH
:
1039 /* ignore and retry scan on timeout */
1043 case IEEE80211_S_RUN
:
1045 case IEEE80211_FC0_SUBTYPE_AUTH
:
1046 IEEE80211_SEND_MGMT(ic
, ni
,
1047 IEEE80211_FC0_SUBTYPE_AUTH
, 2);
1048 ic
->ic_state
= ostate
; /* stay RUN */
1050 case IEEE80211_FC0_SUBTYPE_DEAUTH
:
1051 ieee80211_sta_leave(ic
, ni
);
1052 if (ic
->ic_roaming
== IEEE80211_ROAMING_AUTO
) {
1054 IEEE80211_SEND_MGMT(ic
, ni
,
1055 IEEE80211_FC0_SUBTYPE_AUTH
, 1);
1062 case IEEE80211_S_ASSOC
:
1064 case IEEE80211_S_INIT
:
1065 case IEEE80211_S_SCAN
:
1066 case IEEE80211_S_ASSOC
:
1067 IEEE80211_DPRINTF(ic
, IEEE80211_MSG_ANY
,
1068 "%s: invalid transition\n", __func__
);
1070 case IEEE80211_S_AUTH
:
1071 IEEE80211_SEND_MGMT(ic
, ni
,
1072 IEEE80211_FC0_SUBTYPE_ASSOC_REQ
, 0);
1074 case IEEE80211_S_RUN
:
1075 ieee80211_sta_leave(ic
, ni
);
1076 if (ic
->ic_roaming
== IEEE80211_ROAMING_AUTO
) {
1077 IEEE80211_SEND_MGMT(ic
, ni
,
1078 IEEE80211_FC0_SUBTYPE_ASSOC_REQ
, 1);
1083 case IEEE80211_S_RUN
:
1084 if (ic
->ic_flags
& IEEE80211_F_WPA
) {
1085 /* XXX validate prerequisites */
1088 case IEEE80211_S_INIT
:
1089 if (ic
->ic_opmode
== IEEE80211_M_MONITOR
)
1092 case IEEE80211_S_AUTH
:
1093 IEEE80211_DPRINTF(ic
, IEEE80211_MSG_ANY
,
1094 "%s: invalid transition\n", __func__
);
1096 case IEEE80211_S_RUN
:
1098 case IEEE80211_S_SCAN
: /* adhoc/hostap mode */
1099 case IEEE80211_S_ASSOC
: /* infra mode */
1100 IASSERT(ni
->ni_txrate
< ni
->ni_rates
.rs_nrates
,
1101 ("%s: bogus xmit rate %u setup\n", __func__
,
1103 #ifdef IEEE80211_DEBUG
1104 if (ieee80211_msg_debug(ic
)) {
1105 if (ic
->ic_opmode
== IEEE80211_M_STA
)
1106 if_printf(ifp
, "associated ");
1108 if_printf(ifp
, "synchronized ");
1109 printf("with %s ssid ",
1110 ether_sprintf(ni
->ni_bssid
));
1111 ieee80211_print_essid(ic
->ic_bss
->ni_essid
,
1113 printf(" channel %d start %uMb\n",
1114 ieee80211_chan2ieee(ic
, ic
->ic_curchan
),
1115 IEEE80211_RATE2MBS(ni
->ni_rates
.rs_rates
[ni
->ni_txrate
]));
1118 ic
->ic_mgt_timer
= 0;
1119 if (ic
->ic_opmode
== IEEE80211_M_STA
)
1120 ieee80211_notify_node_join(ic
, ni
,
1121 arg
== IEEE80211_FC0_SUBTYPE_ASSOC_RESP
);
1122 (*ifp
->if_start
)(ifp
); /* XXX not authorized yet */
1126 * Start/stop the authenticator when operating as an
1127 * AP. We delay until here to allow configuration to
1128 * happen out of order.
1130 if (ic
->ic_opmode
== IEEE80211_M_HOSTAP
&& /* XXX IBSS/AHDEMO */
1131 ic
->ic_auth
->ia_attach
!= NULL
) {
1132 /* XXX check failure */
1133 ic
->ic_auth
->ia_attach(ic
);
1134 } else if (ic
->ic_auth
->ia_detach
!= NULL
) {
1135 ic
->ic_auth
->ia_detach(ic
);
1138 * When 802.1x is not in use mark the port authorized
1139 * at this point so traffic can flow.
1141 if (ni
->ni_authmode
!= IEEE80211_AUTH_8021X
)
1142 ieee80211_node_authorize(ni
);
1144 * Enable inactivity processing.
1147 ic
->ic_scan
.nt_inact_timer
= IEEE80211_INACT_WAIT
;
1148 ic
->ic_sta
.nt_inact_timer
= IEEE80211_INACT_WAIT
;