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