xref: /titanic_51/usr/src/uts/common/io/net80211/net80211_input.c (revision 6cefaae1e90a413ba01560575bb3998e1a3df40e)
1 /*
2  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 /*
7  * Copyright (c) 2001 Atsushi Onoe
8  * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * Alternatively, this software may be distributed under the terms of the
23  * GNU General Public License ("GPL") version 2 as published by the Free
24  * Software Foundation.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
30  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  */
37 
38 /*
39  * Process received frame
40  */
41 
42 #include <sys/byteorder.h>
43 #include <sys/strsun.h>
44 #include "net80211_impl.h"
45 
46 static mblk_t *ieee80211_defrag(ieee80211com_t *, ieee80211_node_t *,
47     mblk_t *, int);
48 
49 /*
50  * Process a received frame.  The node associated with the sender
51  * should be supplied.  If nothing was found in the node table then
52  * the caller is assumed to supply a reference to ic_bss instead.
53  * The RSSI and a timestamp are also supplied.  The RSSI data is used
54  * during AP scanning to select a AP to associate with; it can have
55  * any units so long as values have consistent units and higher values
56  * mean ``better signal''.  The receive timestamp is currently not used
57  * by the 802.11 layer.
58  */
59 int
60 ieee80211_input(ieee80211com_t *ic, mblk_t *mp, struct ieee80211_node *in,
61     int32_t rssi, uint32_t rstamp)
62 {
63 	struct ieee80211_frame *wh;
64 	struct ieee80211_key *key;
65 	uint8_t *bssid;
66 	int hdrspace;
67 	int len;
68 	uint16_t rxseq;
69 	uint8_t dir;
70 	uint8_t type;
71 	uint8_t subtype;
72 	uint8_t tid;
73 
74 	ASSERT(in != NULL);
75 	type = (uint8_t)-1;		/* undefined */
76 	len = MBLKL(mp);
77 	if (len < sizeof (struct ieee80211_frame_min)) {
78 		ieee80211_dbg(IEEE80211_MSG_ANY, "ieee80211_input: "
79 		    "too short (1): len %u", len);
80 		goto out;
81 	}
82 	/*
83 	 * Bit of a cheat here, we use a pointer for a 3-address
84 	 * frame format but don't reference fields past outside
85 	 * ieee80211_frame_min w/o first validating the data is
86 	 * present.
87 	 */
88 	wh = (struct ieee80211_frame *)mp->b_rptr;
89 	if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) !=
90 	    IEEE80211_FC0_VERSION_0) {
91 		ieee80211_dbg(IEEE80211_MSG_ANY, "ieee80211_input: "
92 		    "discard pkt with wrong version %x", wh->i_fc[0]);
93 		goto out;
94 	}
95 
96 	dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK;
97 	type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
98 	subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
99 
100 	IEEE80211_LOCK(ic);
101 	if (!(ic->ic_flags & IEEE80211_F_SCAN)) {
102 		switch (ic->ic_opmode) {
103 		case IEEE80211_M_STA:
104 			bssid = wh->i_addr2;
105 			if (!IEEE80211_ADDR_EQ(bssid, in->in_bssid))
106 				goto out_exit_mutex;
107 			break;
108 		case IEEE80211_M_IBSS:
109 		case IEEE80211_M_AHDEMO:
110 			if (dir != IEEE80211_FC1_DIR_NODS) {
111 				bssid = wh->i_addr1;
112 			} else if (type == IEEE80211_FC0_TYPE_CTL) {
113 				bssid = wh->i_addr1;
114 			} else {
115 				if (len < sizeof (struct ieee80211_frame)) {
116 					ieee80211_dbg(IEEE80211_MSG_ANY,
117 					    "ieee80211_input: too short(2):"
118 					    "len %u\n", len);
119 					goto out_exit_mutex;
120 				}
121 				bssid = wh->i_addr3;
122 			}
123 			if (type != IEEE80211_FC0_TYPE_DATA)
124 				break;
125 			/*
126 			 * Data frame, validate the bssid.
127 			 */
128 			if (!IEEE80211_ADDR_EQ(bssid, ic->ic_bss->in_bssid) &&
129 			    !IEEE80211_ADDR_EQ(bssid, wifi_bcastaddr)) {
130 				/* not interested in */
131 				ieee80211_dbg(IEEE80211_MSG_INPUT,
132 				    "ieee80211_input: not to bss %s\n",
133 				    ieee80211_macaddr_sprintf(bssid));
134 				goto out_exit_mutex;
135 			}
136 			/*
137 			 * For adhoc mode we cons up a node when it doesn't
138 			 * exist. This should probably done after an ACL check.
139 			 */
140 			if (in == ic->ic_bss &&
141 			    ic->ic_opmode != IEEE80211_M_HOSTAP &&
142 			    !IEEE80211_ADDR_EQ(wh->i_addr2, in->in_macaddr)) {
143 				/*
144 				 * Fake up a node for this newly
145 				 * discovered member of the IBSS.
146 				 */
147 				in = ieee80211_fakeup_adhoc_node(&ic->ic_sta,
148 				    wh->i_addr2);
149 				if (in == NULL) {
150 					/* NB: stat kept for alloc failure */
151 					goto out_exit_mutex;
152 				}
153 			}
154 			break;
155 		default:
156 			goto out_exit_mutex;
157 		}
158 		in->in_rssi = (uint8_t)rssi;
159 		in->in_rstamp = rstamp;
160 		if (!(type & IEEE80211_FC0_TYPE_CTL)) {
161 			tid = 0;
162 			rxseq = (*(uint16_t *)wh->i_seq);
163 			if ((wh->i_fc[1] & IEEE80211_FC1_RETRY) &&
164 			    (rxseq - in->in_rxseqs[tid]) <= 0) {
165 				/* duplicate, discard */
166 				ieee80211_dbg(IEEE80211_MSG_INPUT,
167 				    "ieee80211_input: duplicate",
168 				    "seqno <%u,%u> fragno <%u,%u> tid %u",
169 				    rxseq >> IEEE80211_SEQ_SEQ_SHIFT,
170 				    in->in_rxseqs[tid] >>
171 				    IEEE80211_SEQ_SEQ_SHIFT,
172 				    rxseq & IEEE80211_SEQ_FRAG_MASK,
173 				    in->in_rxseqs[tid] &
174 				    IEEE80211_SEQ_FRAG_MASK,
175 				    tid);
176 				ic->ic_stats.is_rx_dups++;
177 				goto out_exit_mutex;
178 			}
179 			in->in_rxseqs[tid] = rxseq;
180 		}
181 		in->in_inact = 0;
182 	}
183 
184 	switch (type) {
185 	case IEEE80211_FC0_TYPE_DATA:
186 		hdrspace = ieee80211_hdrspace(wh);
187 		if (len < hdrspace) {
188 			ieee80211_dbg(IEEE80211_MSG_ANY, "ieee80211_input: "
189 			    "data too short: expecting %u", hdrspace);
190 			goto out_exit_mutex;
191 		}
192 		switch (ic->ic_opmode) {
193 		case IEEE80211_M_STA:
194 			if (dir != IEEE80211_FC1_DIR_FROMDS) {
195 				ieee80211_dbg(IEEE80211_MSG_INPUT,
196 				    "ieee80211_input: data ",
197 				    "unknown dir 0x%x", dir);
198 				goto out_exit_mutex;
199 			}
200 			if (IEEE80211_IS_MULTICAST(wh->i_addr1) &&
201 			    IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_macaddr)) {
202 				/*
203 				 * In IEEE802.11 network, multicast packet
204 				 * sent from me is broadcasted from AP.
205 				 * It should be silently discarded for
206 				 * SIMPLEX interface.
207 				 */
208 				ieee80211_dbg(IEEE80211_MSG_INPUT,
209 				    "ieee80211_input: multicast echo\n");
210 				goto out_exit_mutex;
211 			}
212 			break;
213 		case IEEE80211_M_IBSS:
214 		case IEEE80211_M_AHDEMO:
215 			if (dir != IEEE80211_FC1_DIR_NODS) {
216 				ieee80211_dbg(IEEE80211_MSG_INPUT,
217 				    "ieee80211_input: unknown dir 0x%x",
218 				    dir);
219 				goto out_exit_mutex;
220 			}
221 			break;
222 		default:
223 			ieee80211_err("ieee80211_input: "
224 			    "receive data, unknown opmode %u, skip\n",
225 			    ic->ic_opmode);
226 			goto out_exit_mutex;
227 		}
228 
229 		/*
230 		 * Handle privacy requirements.
231 		 */
232 		if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
233 			if ((ic->ic_flags & IEEE80211_F_PRIVACY) == 0) {
234 				/*
235 				 * Discard encrypted frames when privacy off.
236 				 */
237 				ieee80211_dbg(IEEE80211_MSG_INPUT,
238 				    "ieee80211_input: ""WEP PRIVACY off");
239 				ic->ic_stats.is_wep_errors++;
240 				goto out_exit_mutex;
241 			}
242 			key = ieee80211_crypto_decap(ic, mp, hdrspace);
243 			if (key == NULL) {
244 				/* NB: stats+msgs handled in crypto_decap */
245 				ic->ic_stats.is_wep_errors++;
246 				goto out_exit_mutex;
247 			}
248 			wh = (struct ieee80211_frame *)mp->b_rptr;
249 			wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
250 		} else {
251 			key = NULL;
252 		}
253 
254 		/*
255 		 * Next up, any fragmentation
256 		 */
257 		if (!IEEE80211_IS_MULTICAST(wh->i_addr1)) {
258 			mp = ieee80211_defrag(ic, in, mp, hdrspace);
259 			if (mp == NULL) {
260 				/* Fragment dropped or frame not complete yet */
261 				goto out_exit_mutex;
262 			}
263 		}
264 		wh = NULL;	/* no longer valid, catch any uses */
265 
266 		/*
267 		 * Next strip any MSDU crypto bits.
268 		 */
269 		if (key != NULL && !ieee80211_crypto_demic(ic, key, mp, 0)) {
270 			ieee80211_dbg(IEEE80211_MSG_INPUT, "ieee80211_input: "
271 			    "data demic error\n");
272 			goto out_exit_mutex;
273 		}
274 
275 		ic->ic_stats.is_rx_frags++;
276 		ic->ic_stats.is_rx_bytes += len;
277 		IEEE80211_UNLOCK(ic);
278 		mac_rx(ic->ic_mach, NULL, mp);
279 		return (IEEE80211_FC0_TYPE_DATA);
280 
281 	case IEEE80211_FC0_TYPE_MGT:
282 		if (dir != IEEE80211_FC1_DIR_NODS)
283 			goto out_exit_mutex;
284 		if (len < sizeof (struct ieee80211_frame))
285 			goto out_exit_mutex;
286 		if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
287 			if (subtype != IEEE80211_FC0_SUBTYPE_AUTH) {
288 				/*
289 				 * Only shared key auth frames with a challenge
290 				 * should be encrypted, discard all others.
291 				 */
292 				ieee80211_dbg(IEEE80211_MSG_INPUT,
293 				    "ieee80211_input: "
294 				    "%s WEP set but not permitted",
295 				    IEEE80211_SUBTYPE_NAME(subtype));
296 				ic->ic_stats.is_wep_errors++;
297 				goto out_exit_mutex;
298 			}
299 			if ((ic->ic_flags & IEEE80211_F_PRIVACY) == 0) {
300 				/*
301 				 * Discard encrypted frames when privacy off.
302 				 */
303 				ieee80211_dbg(IEEE80211_MSG_INPUT,
304 				    "ieee80211_input: "
305 				    "mgt WEP set but PRIVACY off");
306 				ic->ic_stats.is_wep_errors++;
307 				goto out_exit_mutex;
308 			}
309 			hdrspace = ieee80211_hdrspace(wh);
310 			key = ieee80211_crypto_decap(ic, mp, hdrspace);
311 			if (key == NULL) {
312 				/* NB: stats+msgs handled in crypto_decap */
313 				goto out_exit_mutex;
314 			}
315 			wh = (struct ieee80211_frame *)mp->b_rptr;
316 			wh->i_fc[1] &= ~IEEE80211_FC1_WEP;
317 		}
318 		IEEE80211_UNLOCK(ic);
319 		ic->ic_recv_mgmt(ic, mp, in, subtype, rssi, rstamp);
320 		goto out;
321 
322 	case IEEE80211_FC0_TYPE_CTL:
323 	default:
324 		ieee80211_dbg(IEEE80211_MSG_ANY, "ieee80211_input: "
325 		    "bad frame type 0x%x", type);
326 		/* should not come here */
327 		break;
328 	}
329 out_exit_mutex:
330 	IEEE80211_UNLOCK(ic);
331 out:
332 	if (mp != NULL)
333 		freemsg(mp);
334 
335 	return (type);
336 }
337 
338 /*
339  * This function reassemble fragments.
340  * More fragments bit in the frame control means the packet is fragmented.
341  * While the sequence control field consists of 4-bit fragment number
342  * field and a 12-bit sequence number field.
343  */
344 /* ARGSUSED */
345 static mblk_t *
346 ieee80211_defrag(ieee80211com_t *ic, struct ieee80211_node *in, mblk_t *mp,
347     int hdrspace)
348 {
349 	struct ieee80211_frame *wh = (struct ieee80211_frame *)mp->b_rptr;
350 	struct ieee80211_frame *lwh;
351 	mblk_t *mfrag;
352 	uint16_t rxseq;
353 	uint8_t fragno;
354 	uint8_t more_frag;
355 
356 	ASSERT(!IEEE80211_IS_MULTICAST(wh->i_addr1));
357 	more_frag = wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG;
358 	rxseq = LE_16(*(uint16_t *)wh->i_seq);
359 	fragno = rxseq & IEEE80211_SEQ_FRAG_MASK;
360 
361 	/* Quick way out, if there's nothing to defragment */
362 	if (!more_frag && fragno == 0 && in->in_rxfrag == NULL)
363 		return (mp);
364 
365 	/*
366 	 * Remove frag to insure it doesn't get reaped by timer.
367 	 */
368 	if (in->in_table == NULL) {
369 		/*
370 		 * Should never happen.  If the node is orphaned (not in
371 		 * the table) then input packets should not reach here.
372 		 * Otherwise, a concurrent request that yanks the table
373 		 * should be blocked by other interlocking and/or by first
374 		 * shutting the driver down.  Regardless, be defensive
375 		 * here and just bail
376 		 */
377 		freemsg(mp);
378 		return (NULL);
379 	}
380 	IEEE80211_NODE_LOCK(in->in_table);
381 	mfrag = in->in_rxfrag;
382 	in->in_rxfrag = NULL;
383 	IEEE80211_NODE_UNLOCK(in->in_table);
384 
385 	/*
386 	 * Validate new fragment is in order and
387 	 * related to the previous ones.
388 	 */
389 	if (mfrag != NULL) {
390 		uint16_t last_rxseq;
391 
392 		lwh = (struct ieee80211_frame *)mfrag->b_rptr;
393 		last_rxseq = LE_16(*(uint16_t *)lwh->i_seq);
394 		/*
395 		 * Sequence control field contains 12-bit sequence no
396 		 * and 4-bit fragment number. For fragemnts, the
397 		 * sequence no is not changed.
398 		 * NB: check seq # and frag together
399 		 */
400 		if (rxseq != last_rxseq + 1 ||
401 		    !IEEE80211_ADDR_EQ(wh->i_addr1, lwh->i_addr1) ||
402 		    !IEEE80211_ADDR_EQ(wh->i_addr2, lwh->i_addr2)) {
403 			/*
404 			 * Unrelated fragment or no space for it,
405 			 * clear current fragments.
406 			 */
407 			freemsg(mfrag);
408 			mfrag = NULL;
409 		}
410 	}
411 
412 	if (mfrag == NULL) {
413 		if (fragno != 0) {	/* !first fragment, discard */
414 			freemsg(mp);
415 			return (NULL);
416 		}
417 		mfrag = mp;
418 	} else {			/* concatenate */
419 		(void) adjmsg(mp, hdrspace);
420 		linkb(mfrag, mp);
421 		/* track last seqnum and fragno */
422 		lwh = (struct ieee80211_frame *)mfrag->b_rptr;
423 		*(uint16_t *)lwh->i_seq = *(uint16_t *)wh->i_seq;
424 	}
425 	if (more_frag != 0) {		/* more to come, save */
426 		in->in_rxfragstamp = ddi_get_lbolt();
427 		in->in_rxfrag = mfrag;
428 		mfrag = NULL;
429 	}
430 
431 	return (mfrag);
432 }
433 
434 /*
435  * Install received rate set information in the node's state block.
436  */
437 int
438 ieee80211_setup_rates(struct ieee80211_node *in, const uint8_t *rates,
439     const uint8_t *xrates, int flags)
440 {
441 	struct ieee80211_rateset *rs = &in->in_rates;
442 
443 	bzero(rs, sizeof (*rs));
444 	rs->ir_nrates = rates[1];
445 	/* skip 1 byte element ID and 1 byte length */
446 	bcopy(rates + 2, rs->ir_rates, rs->ir_nrates);
447 	if (xrates != NULL) {
448 		uint8_t nxrates;
449 
450 		/*
451 		 * Tack on 11g extended supported rate element.
452 		 */
453 		nxrates = xrates[1];
454 		if (rs->ir_nrates + nxrates > IEEE80211_RATE_MAXSIZE) {
455 			nxrates = IEEE80211_RATE_MAXSIZE - rs->ir_nrates;
456 			ieee80211_dbg(IEEE80211_MSG_XRATE,
457 			    "ieee80211_setup_rates: %s",
458 			    "[%s] extended rate set too large;"
459 			    " only using %u of %u rates\n",
460 			    ieee80211_macaddr_sprintf(in->in_macaddr),
461 			    nxrates, xrates[1]);
462 		}
463 		bcopy(xrates + 2, rs->ir_rates + rs->ir_nrates, nxrates);
464 		rs->ir_nrates += nxrates;
465 	}
466 	return (ieee80211_fix_rate(in, flags));
467 }
468 
469 /*
470  * Process open-system authentication response frame and start
471  * association if the authentication request is accepted.
472  */
473 static void
474 ieee80211_auth_open(ieee80211com_t *ic, struct ieee80211_frame *wh,
475     struct ieee80211_node *in, uint16_t seq, uint16_t status)
476 {
477 	IEEE80211_LOCK_ASSERT(ic);
478 	if (in->in_authmode == IEEE80211_AUTH_SHARED) {
479 		ieee80211_dbg(IEEE80211_MSG_AUTH,
480 		    "open auth: bad sta auth mode %u", in->in_authmode);
481 		return;
482 	}
483 	if (ic->ic_opmode == IEEE80211_M_STA) {
484 		if (ic->ic_state != IEEE80211_S_AUTH ||
485 		    seq != IEEE80211_AUTH_OPEN_RESPONSE) {
486 			return;
487 		}
488 		IEEE80211_UNLOCK(ic);
489 		if (status != 0) {
490 			ieee80211_dbg(IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH,
491 			    "open auth failed (reason %d)\n", status);
492 			if (in != ic->ic_bss)
493 				in->in_fails++;
494 			ieee80211_new_state(ic, IEEE80211_S_SCAN, 0);
495 		} else {
496 			/* i_fc[0] - frame control's type & subtype field */
497 			ieee80211_new_state(ic, IEEE80211_S_ASSOC,
498 			    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
499 		}
500 		IEEE80211_LOCK(ic);
501 	} else {
502 		ieee80211_dbg(IEEE80211_MSG_AUTH, "ieee80211_auth_open: "
503 		    "bad operating mode %u", ic->ic_opmode);
504 	}
505 }
506 
507 /*
508  * Allocate challenge text for use by shared-key authentication
509  * Return B_TRUE on success, B_FALST otherwise.
510  */
511 static boolean_t
512 ieee80211_alloc_challenge(struct ieee80211_node *in)
513 {
514 	if (in->in_challenge == NULL) {
515 		in->in_challenge = kmem_alloc(IEEE80211_CHALLENGE_LEN,
516 		    KM_NOSLEEP);
517 	}
518 	if (in->in_challenge == NULL) {
519 		ieee80211_dbg(IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH,
520 		    "[%s] shared key challenge alloc failed\n",
521 		    ieee80211_macaddr_sprintf(in->in_macaddr));
522 	}
523 	return (in->in_challenge != NULL);
524 }
525 
526 /*
527  * Process shared-key authentication response frames. If authentication
528  * succeeds, start association; otherwise, restart scan.
529  */
530 static void
531 ieee80211_auth_shared(ieee80211com_t *ic, struct ieee80211_frame *wh,
532     uint8_t *frm, uint8_t *efrm, struct ieee80211_node *in, uint16_t seq,
533     uint16_t status)
534 {
535 	uint8_t *challenge;
536 
537 	/*
538 	 * Pre-shared key authentication is evil; accept
539 	 * it only if explicitly configured (it is supported
540 	 * mainly for compatibility with clients like OS X).
541 	 */
542 	IEEE80211_LOCK_ASSERT(ic);
543 	if (in->in_authmode != IEEE80211_AUTH_AUTO &&
544 	    in->in_authmode != IEEE80211_AUTH_SHARED) {
545 		ieee80211_dbg(IEEE80211_MSG_AUTH, "ieee80211_auth_shared: "
546 		    "bad sta auth mode %u", in->in_authmode);
547 		goto bad;
548 	}
549 
550 	challenge = NULL;
551 	if (frm + 1 < efrm) {
552 		/*
553 		 * Challenge text information element
554 		 * frm[0] - element ID
555 		 * frm[1] - length
556 		 * frm[2]... - challenge text
557 		 */
558 		if ((frm[1] + 2) > (_PTRDIFF(efrm, frm))) {
559 			ieee80211_dbg(IEEE80211_MSG_AUTH,
560 			    "ieee80211_auth_shared: ie %d%d too long\n",
561 			    frm[0], (frm[1] + 2) - (_PTRDIFF(efrm, frm)));
562 			goto bad;
563 		}
564 		if (*frm == IEEE80211_ELEMID_CHALLENGE)
565 			challenge = frm;
566 		frm += frm[1] + 2;
567 	}
568 	switch (seq) {
569 	case IEEE80211_AUTH_SHARED_CHALLENGE:
570 	case IEEE80211_AUTH_SHARED_RESPONSE:
571 		if (challenge == NULL) {
572 			ieee80211_dbg(IEEE80211_MSG_AUTH,
573 			    "ieee80211_auth_shared: no challenge\n");
574 			goto bad;
575 		}
576 		if (challenge[1] != IEEE80211_CHALLENGE_LEN) {
577 			ieee80211_dbg(IEEE80211_MSG_AUTH,
578 			    "ieee80211_auth_shared: bad challenge len %d\n",
579 			    challenge[1]);
580 			goto bad;
581 		}
582 	default:
583 		break;
584 	}
585 	switch (ic->ic_opmode) {
586 	case IEEE80211_M_STA:
587 		if (ic->ic_state != IEEE80211_S_AUTH)
588 			return;
589 		switch (seq) {
590 		case IEEE80211_AUTH_SHARED_PASS:
591 			if (in->in_challenge != NULL) {
592 				kmem_free(in->in_challenge,
593 				    IEEE80211_CHALLENGE_LEN);
594 				in->in_challenge = NULL;
595 			}
596 			if (status != 0) {
597 				ieee80211_dbg(IEEE80211_MSG_DEBUG |
598 				    IEEE80211_MSG_AUTH,
599 				    "shared key auth failed (reason %d)\n",
600 				    status);
601 				if (in != ic->ic_bss)
602 					in->in_fails++;
603 				return;
604 			}
605 			IEEE80211_UNLOCK(ic);
606 			ieee80211_new_state(ic, IEEE80211_S_ASSOC,
607 			    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
608 			IEEE80211_LOCK(ic);
609 			break;
610 		case IEEE80211_AUTH_SHARED_CHALLENGE:
611 			if (!ieee80211_alloc_challenge(in))
612 				return;
613 			bcopy(&challenge[2], in->in_challenge, challenge[1]);
614 			IEEE80211_UNLOCK(ic);
615 			IEEE80211_SEND_MGMT(ic, in, IEEE80211_FC0_SUBTYPE_AUTH,
616 			    seq + 1);
617 			IEEE80211_LOCK(ic);
618 			break;
619 		default:
620 			ieee80211_dbg(IEEE80211_MSG_AUTH, "80211_auth_shared: "
621 			    "shared key auth: bad seq %d", seq);
622 			return;
623 		}
624 		break;
625 
626 	default:
627 		ieee80211_dbg(IEEE80211_MSG_AUTH,
628 		    "ieee80211_auth_shared: bad opmode %u\n",
629 		    ic->ic_opmode);
630 		break;
631 	}
632 	return;
633 bad:
634 	if (ic->ic_opmode == IEEE80211_M_STA) {
635 		/*
636 		 * Kick the state machine.  This short-circuits
637 		 * using the mgt frame timeout to trigger the
638 		 * state transition.
639 		 */
640 		if (ic->ic_state == IEEE80211_S_AUTH) {
641 			IEEE80211_UNLOCK(ic);
642 			ieee80211_new_state(ic, IEEE80211_S_SCAN, 0);
643 			IEEE80211_LOCK(ic);
644 		}
645 	}
646 }
647 
648 static int
649 iswpaoui(const uint8_t *frm)
650 {
651 	uint32_t c = *(uint32_t *)(frm + 2);
652 	return (frm[1] > 3 && c == ((WPA_OUI_TYPE << 24) | WPA_OUI));
653 }
654 
655 /*
656  * Process a beacon/probe response frame.
657  * When the device is in station mode, create a node and add it
658  * to the node database for a new ESS or update node info if it's
659  * already there.
660  */
661 static void
662 ieee80211_recv_beacon(ieee80211com_t *ic, mblk_t *mp, struct ieee80211_node *in,
663     int subtype, int rssi, uint32_t rstamp)
664 {
665 	ieee80211_impl_t *im = ic->ic_private;
666 	struct ieee80211_frame *wh;
667 	uint8_t *frm;
668 	uint8_t *efrm;	/* end of frame body */
669 	struct ieee80211_scanparams scan;
670 
671 	wh = (struct ieee80211_frame *)mp->b_rptr;
672 	frm = (uint8_t *)&wh[1];
673 	efrm = (uint8_t *)mp->b_wptr;
674 
675 	/*
676 	 * We process beacon/probe response frames:
677 	 *    o when scanning, or
678 	 *    o station mode when associated (to collect state
679 	 *	updates such as 802.11g slot time), or
680 	 *    o adhoc mode (to discover neighbors)
681 	 * Frames otherwise received are discarded.
682 	 */
683 	if (!((ic->ic_flags & IEEE80211_F_SCAN) ||
684 	    (ic->ic_opmode == IEEE80211_M_STA && in->in_associd != 0) ||
685 	    ic->ic_opmode == IEEE80211_M_IBSS)) {
686 		return;
687 	}
688 
689 	/*
690 	 * beacon/probe response frame format
691 	 *	[8] time stamp
692 	 *	[2] beacon interval
693 	 *	[2] capability information
694 	 *	[tlv] ssid
695 	 *	[tlv] supported rates
696 	 *	[tlv] country information
697 	 *	[tlv] parameter set (FH/DS)
698 	 *	[tlv] erp information
699 	 *	[tlv] extended supported rates
700 	 *	[tlv] WME
701 	 *	[tlv] WPA or RSN
702 	 */
703 	IEEE80211_VERIFY_LENGTH(_PTRDIFF(efrm, frm),
704 	    IEEE80211_BEACON_ELEM_MIN, return);
705 	bzero(&scan, sizeof (scan));
706 	scan.tstamp  = frm;
707 	frm += 8;
708 	scan.bintval = (*(uint16_t *)frm);
709 	frm += 2;
710 	scan.capinfo = (*(uint16_t *)frm);
711 	frm += 2;
712 	scan.bchan = ieee80211_chan2ieee(ic, ic->ic_curchan);
713 	scan.chan = scan.bchan;
714 
715 	while (frm < efrm) {
716 		/* Agere element in beacon */
717 		if ((*frm == IEEE80211_ELEMID_AGERE1) ||
718 		    (*frm == IEEE80211_ELEMID_AGERE2)) {
719 			frm = efrm;
720 			break;
721 		}
722 
723 		IEEE80211_VERIFY_LENGTH(_PTRDIFF(efrm, frm), frm[1], return);
724 		switch (*frm) {
725 		case IEEE80211_ELEMID_SSID:
726 			scan.ssid = frm;
727 			break;
728 		case IEEE80211_ELEMID_RATES:
729 			scan.rates = frm;
730 			break;
731 		case IEEE80211_ELEMID_COUNTRY:
732 			scan.country = frm;
733 			break;
734 		case IEEE80211_ELEMID_FHPARMS:
735 			if (ic->ic_phytype == IEEE80211_T_FH) {
736 				scan.fhdwell = LE_16(*(uint16_t *)(frm + 2));
737 				scan.chan = IEEE80211_FH_CHAN(frm[4], frm[5]);
738 				scan.fhindex = frm[6];
739 				scan.phytype = IEEE80211_T_FH;
740 			}
741 			break;
742 		case IEEE80211_ELEMID_DSPARMS:
743 			if (ic->ic_phytype != IEEE80211_T_FH) {
744 				scan.chan = frm[2];
745 				scan.phytype = IEEE80211_T_DS;
746 			}
747 			break;
748 		case IEEE80211_ELEMID_TIM:
749 			scan.tim = frm;
750 			scan.timoff = _PTRDIFF(frm, mp->b_rptr);
751 			break;
752 		case IEEE80211_ELEMID_IBSSPARMS:
753 			break;
754 		case IEEE80211_ELEMID_XRATES:
755 			scan.xrates = frm;
756 			break;
757 		case IEEE80211_ELEMID_ERP:
758 			if (frm[1] != 1) {
759 				ieee80211_dbg(IEEE80211_MSG_ELEMID,
760 				    "ieee80211_recv_mgmt: ignore %s, "
761 				    "invalid ERP element; "
762 				    "length %u, expecting 1\n",
763 				    IEEE80211_SUBTYPE_NAME(subtype),
764 				    frm[1]);
765 				break;
766 			}
767 			scan.erp = frm[2];
768 			scan.phytype = IEEE80211_T_OFDM;
769 			break;
770 		case IEEE80211_ELEMID_RSN:
771 			scan.wpa = frm;
772 			break;
773 		case IEEE80211_ELEMID_VENDOR:
774 			if (iswpaoui(frm))
775 				scan.wpa = frm;		/* IEEE802.11i D3.0 */
776 			break;
777 		default:
778 			ieee80211_dbg(IEEE80211_MSG_ELEMID,
779 			    "ieee80211_recv_mgmt: ignore %s,"
780 			    "unhandled id %u, len %u, totallen %u",
781 			    IEEE80211_SUBTYPE_NAME(subtype),
782 			    *frm, frm[1],
783 			    MBLKL(mp));
784 			break;
785 		}
786 		/* frm[1] - component length */
787 		frm += IEEE80211_ELEM_LEN(frm[1]);
788 	}
789 	IEEE80211_VERIFY_ELEMENT(scan.rates, IEEE80211_RATE_MAXSIZE, return);
790 	IEEE80211_VERIFY_ELEMENT(scan.ssid, IEEE80211_NWID_LEN, return);
791 	if (ieee80211_isclr(ic->ic_chan_active, scan.chan)) {
792 		ieee80211_dbg(IEEE80211_MSG_ELEMID | IEEE80211_MSG_INPUT,
793 		    "ieee80211_recv_mgmt: ignore %s ,"
794 		    "invalid channel %u\n",
795 		    IEEE80211_SUBTYPE_NAME(subtype), scan.chan);
796 		return;
797 	}
798 	if (scan.chan != scan.bchan &&
799 	    ic->ic_phytype != IEEE80211_T_FH) {
800 		/*
801 		 * Frame was received on a channel different from the
802 		 * one indicated in the DS params element id;
803 		 * silently discard it.
804 		 *
805 		 * NB:	this can happen due to signal leakage.
806 		 *	But we should take it for FH phy because
807 		 *	the rssi value should be correct even for
808 		 *	different hop pattern in FH.
809 		 */
810 		ieee80211_dbg(IEEE80211_MSG_ELEMID,
811 		    "ieee80211_recv_mgmt: ignore %s ,"
812 		    "phytype %u channel %u marked for %u\n",
813 		    IEEE80211_SUBTYPE_NAME(subtype),
814 		    ic->ic_phytype, scan.bchan, scan.chan);
815 		return;
816 	}
817 	if (!(IEEE80211_BINTVAL_MIN <= scan.bintval &&
818 	    scan.bintval <= IEEE80211_BINTVAL_MAX)) {
819 		ieee80211_dbg(IEEE80211_MSG_ELEMID | IEEE80211_MSG_INPUT,
820 		    "ieee80211_recv_mgmt: ignore %s ,"
821 		    "bogus beacon interval %u\n",
822 		    IEEE80211_SUBTYPE_NAME(subtype), scan.bintval);
823 		return;
824 	}
825 
826 	/*
827 	 * When operating in station mode, check for state updates.
828 	 * Be careful to ignore beacons received while doing a
829 	 * background scan.  We consider only 11g/WMM stuff right now.
830 	 */
831 	if (ic->ic_opmode == IEEE80211_M_STA &&
832 	    in->in_associd != 0 &&
833 	    (!(ic->ic_flags & IEEE80211_F_SCAN) ||
834 	    IEEE80211_ADDR_EQ(wh->i_addr2, in->in_bssid))) {
835 		/* record tsf of last beacon */
836 		bcopy(scan.tstamp, in->in_tstamp.data,
837 		    sizeof (in->in_tstamp));
838 		/* count beacon frame for s/w bmiss handling */
839 		im->im_swbmiss_count++;
840 		im->im_bmiss_count = 0;
841 
842 		if ((in->in_capinfo ^ scan.capinfo) &
843 		    IEEE80211_CAPINFO_SHORT_SLOTTIME) {
844 			ieee80211_dbg(IEEE80211_MSG_ASSOC,
845 			    "ieee80211_recv_mgmt: "
846 			    "[%s] cap change: before 0x%x, now 0x%x\n",
847 			    ieee80211_macaddr_sprintf(wh->i_addr2),
848 			    in->in_capinfo, scan.capinfo);
849 			/*
850 			 * NB:	we assume short preamble doesn't
851 			 *	change dynamically
852 			 */
853 			ieee80211_set_shortslottime(ic,
854 			    ic->ic_curmode == IEEE80211_MODE_11A ||
855 			    (scan.capinfo &
856 			    IEEE80211_CAPINFO_SHORT_SLOTTIME));
857 			in->in_capinfo = scan.capinfo;
858 		}
859 
860 		if (scan.tim != NULL) {
861 			struct ieee80211_tim_ie *ie;
862 
863 			ie = (struct ieee80211_tim_ie *)scan.tim;
864 			in->in_dtim_count = ie->tim_count;
865 			in->in_dtim_period = ie->tim_period;
866 		}
867 		if (ic->ic_flags & IEEE80211_F_SCAN) {
868 			ieee80211_add_scan(ic, &scan, wh, subtype, rssi,
869 			    rstamp);
870 		}
871 		return;
872 	}
873 	/*
874 	 * If scanning, just pass information to the scan module.
875 	 */
876 	if (ic->ic_flags & IEEE80211_F_SCAN) {
877 		ieee80211_add_scan(ic, &scan, wh, subtype, rssi, rstamp);
878 		return;
879 	}
880 
881 	if (scan.capinfo & IEEE80211_CAPINFO_IBSS) {
882 		if (!IEEE80211_ADDR_EQ(wh->i_addr2, in->in_macaddr)) {
883 			/*
884 			 * Create a new entry in the neighbor table.
885 			 */
886 			in = ieee80211_add_neighbor(ic, wh, &scan);
887 		} else if (in->in_capinfo == 0) {
888 			/*
889 			 * Update faked node created on transmit.
890 			 * Note this also updates the tsf.
891 			 */
892 			ieee80211_init_neighbor(in, wh, &scan);
893 		} else {
894 			/*
895 			 * Record tsf for potential resync.
896 			 */
897 			bcopy(scan.tstamp, in->in_tstamp.data,
898 			    sizeof (in->in_tstamp));
899 		}
900 		if (in != NULL) {
901 			in->in_rssi = (uint8_t)rssi;
902 			in->in_rstamp = rstamp;
903 		}
904 	}
905 }
906 
907 /*
908  * Perform input processing for 802.11 management frames.
909  * It's the default ic_recv_mgmt callback function for the interface
910  * softc, ic. Tipically ic_recv_mgmt is called within ieee80211_input()
911  */
912 void
913 ieee80211_recv_mgmt(ieee80211com_t *ic, mblk_t *mp, struct ieee80211_node *in,
914     int subtype, int rssi, uint32_t rstamp)
915 {
916 	struct ieee80211_frame *wh;
917 	uint8_t *frm;		/* pointer to start of the frame */
918 	uint8_t *efrm;		/* pointer to end of the frame */
919 	uint8_t *ssid;
920 	uint8_t *rates;
921 	uint8_t *xrates;	/* extended rates */
922 	boolean_t allocbs = B_FALSE;
923 	uint8_t rate;
924 	uint16_t algo;		/* authentication algorithm */
925 	uint16_t seq;		/* sequence no */
926 	uint16_t status;
927 	uint16_t capinfo;
928 	uint16_t associd;	/* association ID */
929 
930 	IEEE80211_LOCK(ic);
931 	wh = (struct ieee80211_frame *)mp->b_rptr;
932 	frm = (uint8_t *)&wh[1];
933 	efrm = (uint8_t *)mp->b_wptr;
934 	switch (subtype) {
935 	case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
936 	case IEEE80211_FC0_SUBTYPE_BEACON:
937 		ieee80211_recv_beacon(ic, mp, in, subtype, rssi, rstamp);
938 		break;
939 
940 	case IEEE80211_FC0_SUBTYPE_PROBE_REQ:
941 		if (ic->ic_opmode == IEEE80211_M_STA ||
942 		    ic->ic_state != IEEE80211_S_RUN ||
943 		    IEEE80211_IS_MULTICAST(wh->i_addr2)) {
944 			break;
945 		}
946 
947 		/*
948 		 * prreq frame format
949 		 *	[tlv] ssid
950 		 *	[tlv] supported rates
951 		 *	[tlv] extended supported rates
952 		 */
953 		ssid = rates = xrates = NULL;
954 		while (frm < efrm) {
955 			IEEE80211_VERIFY_LENGTH(_PTRDIFF(efrm, frm),
956 			    frm[1], goto out);
957 			switch (*frm) {
958 			case IEEE80211_ELEMID_SSID:
959 				ssid = frm;
960 				break;
961 			case IEEE80211_ELEMID_RATES:
962 				rates = frm;
963 				break;
964 			case IEEE80211_ELEMID_XRATES:
965 				xrates = frm;
966 				break;
967 			}
968 			frm += frm[1] + 2;
969 		}
970 		IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE, break);
971 		IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN, break);
972 		IEEE80211_VERIFY_SSID(ic->ic_bss, ssid, break);
973 		if ((ic->ic_flags & IEEE80211_F_HIDESSID) && ssid[1] == 0) {
974 			ieee80211_dbg(IEEE80211_MSG_INPUT,
975 			    "ieee80211_recv_mgmt: ignore %s, "
976 			    "no ssid with ssid suppression enabled",
977 			    IEEE80211_SUBTYPE_NAME(subtype));
978 			break;
979 		}
980 
981 		if (in == ic->ic_bss) {
982 			if (ic->ic_opmode != IEEE80211_M_IBSS) {
983 				in = ieee80211_tmp_node(ic, wh->i_addr2);
984 				allocbs = B_TRUE;
985 			} else if (!IEEE80211_ADDR_EQ(wh->i_addr2,
986 			    in->in_macaddr)) {
987 				/*
988 				 * Cannot tell if the sender is operating
989 				 * in ibss mode.  But we need a new node to
990 				 * send the response so blindly add them to the
991 				 * neighbor table.
992 				 */
993 				in = ieee80211_fakeup_adhoc_node(&ic->ic_sta,
994 				    wh->i_addr2);
995 			}
996 			if (in == NULL)
997 				break;
998 		}
999 		ieee80211_dbg(IEEE80211_MSG_ASSOC, "ieee80211_recv_mgmt: "
1000 		    "[%s] recv probe req\n",
1001 		    ieee80211_macaddr_sprintf(wh->i_addr2));
1002 		in->in_rssi = (uint8_t)rssi;
1003 		in->in_rstamp = rstamp;
1004 		/*
1005 		 * Adjust and check station's rate list with device's
1006 		 * supported rate.  Send back response if there is at
1007 		 * least one rate or the fixed rate(if being set) is
1008 		 * supported by both station and the device
1009 		 */
1010 		rate = ieee80211_setup_rates(in, rates, xrates,
1011 		    IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
1012 		    IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
1013 		if (rate & IEEE80211_RATE_BASIC) {
1014 			ieee80211_dbg(IEEE80211_MSG_XRATE, "ieee80211_recv_mgmt"
1015 			    "%s recv'd rate set invalid",
1016 			    IEEE80211_SUBTYPE_NAME(subtype));
1017 		} else {
1018 			IEEE80211_UNLOCK(ic);
1019 			IEEE80211_SEND_MGMT(ic, in,
1020 			    IEEE80211_FC0_SUBTYPE_PROBE_RESP, 0);
1021 			IEEE80211_LOCK(ic);
1022 		}
1023 		if (allocbs) {
1024 			/*
1025 			 * Temporary node created just to send a
1026 			 * response, reclaim immediately.
1027 			 */
1028 			ieee80211_free_node(in);
1029 		}
1030 		break;
1031 
1032 	case IEEE80211_FC0_SUBTYPE_AUTH:
1033 		/*
1034 		 * auth frame format
1035 		 *	[2] algorithm
1036 		 *	[2] sequence
1037 		 *	[2] status
1038 		 *	[tlv*] challenge
1039 		 */
1040 		IEEE80211_VERIFY_LENGTH(_PTRDIFF(efrm, frm),
1041 		    IEEE80211_AUTH_ELEM_MIN, break);
1042 		algo   = (*(uint16_t *)frm);
1043 		seq    = (*(uint16_t *)(frm + 2));
1044 		status = (*(uint16_t *)(frm + 4));
1045 		ieee80211_dbg(IEEE80211_MSG_AUTH, "ieee80211_recv_mgmt: "
1046 		    "[%s] recv auth frame with algorithm %d seq %d\n",
1047 		    ieee80211_macaddr_sprintf(wh->i_addr2), algo, seq);
1048 
1049 		if (ic->ic_flags & IEEE80211_F_COUNTERM) {
1050 			ieee80211_dbg(IEEE80211_MSG_AUTH | IEEE80211_MSG_CRYPTO,
1051 			    "ieee80211_recv_mgmt: ignore auth, %s\n",
1052 			    "TKIP countermeasures enabled");
1053 			break;
1054 		}
1055 		switch (algo) {
1056 		case IEEE80211_AUTH_ALG_SHARED:
1057 			ieee80211_auth_shared(ic, wh, frm + 6, efrm, in,
1058 			    seq, status);
1059 			break;
1060 		case IEEE80211_AUTH_ALG_OPEN:
1061 			ieee80211_auth_open(ic, wh, in, seq, status);
1062 			break;
1063 		default:
1064 			ieee80211_dbg(IEEE80211_MSG_ANY, "ieee80211_recv_mgmt: "
1065 			    "ignore auth, unsupported alg %d", algo);
1066 			break;
1067 		}
1068 		break;
1069 
1070 	case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
1071 	case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
1072 		if (ic->ic_opmode != IEEE80211_M_STA ||
1073 		    ic->ic_state != IEEE80211_S_ASSOC)
1074 			break;
1075 
1076 		/*
1077 		 * asresp frame format
1078 		 *	[2] capability information
1079 		 *	[2] status
1080 		 *	[2] association ID
1081 		 *	[tlv] supported rates
1082 		 *	[tlv] extended supported rates
1083 		 *	[tlv] WME
1084 		 */
1085 		IEEE80211_VERIFY_LENGTH(_PTRDIFF(efrm, frm),
1086 		    IEEE80211_ASSOC_RESP_ELEM_MIN, break);
1087 		in = ic->ic_bss;
1088 		capinfo = (*(uint16_t *)frm);
1089 		frm += 2;
1090 		status = (*(uint16_t *)frm);
1091 		frm += 2;
1092 		if (status != 0) {
1093 			ieee80211_dbg(IEEE80211_MSG_ASSOC,
1094 			    "assoc failed (reason %d)\n", status);
1095 			in = ieee80211_find_node(&ic->ic_scan, wh->i_addr2);
1096 			if (in != NULL) {
1097 				in->in_fails++;
1098 				ieee80211_free_node(in);
1099 			}
1100 			break;
1101 		}
1102 		associd = (*(uint16_t *)frm);
1103 		frm += 2;
1104 
1105 		rates = xrates = NULL;
1106 		while (frm < efrm) {
1107 			/*
1108 			 * Do not discard frames containing proprietary Agere
1109 			 * elements 128 and 129, as the reported element length
1110 			 * is often wrong. Skip rest of the frame, since we can
1111 			 * not rely on the given element length making it
1112 			 * impossible to know where the next element starts
1113 			 */
1114 			if ((*frm == IEEE80211_ELEMID_AGERE1) ||
1115 			    (*frm == IEEE80211_ELEMID_AGERE2)) {
1116 				frm = efrm;
1117 				break;
1118 			}
1119 
1120 			IEEE80211_VERIFY_LENGTH(_PTRDIFF(efrm, frm),
1121 			    frm[1], goto out);
1122 			switch (*frm) {
1123 			case IEEE80211_ELEMID_RATES:
1124 				rates = frm;
1125 				break;
1126 			case IEEE80211_ELEMID_XRATES:
1127 				xrates = frm;
1128 				break;
1129 			}
1130 			frm += frm[1] + 2;
1131 		}
1132 
1133 		IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE, break);
1134 		/*
1135 		 * Adjust and check AP's rate list with device's
1136 		 * supported rate. Re-start scan if no rate is or the
1137 		 * fixed rate(if being set) cannot be supported by
1138 		 * either AP or the device.
1139 		 */
1140 		rate = ieee80211_setup_rates(in, rates, xrates,
1141 		    IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
1142 		    IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
1143 		if (rate & IEEE80211_RATE_BASIC) {
1144 			ieee80211_dbg(IEEE80211_MSG_ASSOC,
1145 			    "assoc failed (rate set mismatch)\n");
1146 			if (in != ic->ic_bss)
1147 				in->in_fails++;
1148 			IEEE80211_UNLOCK(ic);
1149 			ieee80211_new_state(ic, IEEE80211_S_SCAN, 0);
1150 			return;
1151 		}
1152 
1153 		in->in_capinfo = capinfo;
1154 		in->in_associd = associd;
1155 		in->in_flags &= ~IEEE80211_NODE_QOS;
1156 		/*
1157 		 * Configure state now that we are associated.
1158 		 */
1159 		if (ic->ic_curmode == IEEE80211_MODE_11A ||
1160 		    (in->in_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) {
1161 			ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
1162 			ic->ic_flags &= ~IEEE80211_F_USEBARKER;
1163 		} else {
1164 			ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE;
1165 			ic->ic_flags |= IEEE80211_F_USEBARKER;
1166 		}
1167 		ieee80211_set_shortslottime(ic,
1168 		    ic->ic_curmode == IEEE80211_MODE_11A ||
1169 		    (in->in_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME));
1170 		/*
1171 		 * Honor ERP protection.
1172 		 *
1173 		 * NB:	in_erp should zero for non-11g operation.
1174 		 *	check ic_curmode anyway
1175 		 */
1176 		if (ic->ic_curmode == IEEE80211_MODE_11G &&
1177 		    (in->in_erp & IEEE80211_ERP_USE_PROTECTION))
1178 			ic->ic_flags |= IEEE80211_F_USEPROT;
1179 		else
1180 			ic->ic_flags &= ~IEEE80211_F_USEPROT;
1181 		ieee80211_dbg(IEEE80211_MSG_ASSOC,
1182 		    "assoc success: %s preamble, %s slot time%s%s\n",
1183 		    ic->ic_flags&IEEE80211_F_SHPREAMBLE ? "short" : "long",
1184 		    ic->ic_flags&IEEE80211_F_SHSLOT ? "short" : "long",
1185 		    ic->ic_flags&IEEE80211_F_USEPROT ? ", protection" : "",
1186 		    in->in_flags & IEEE80211_NODE_QOS ? ", QoS" : "");
1187 		IEEE80211_UNLOCK(ic);
1188 		ieee80211_new_state(ic, IEEE80211_S_RUN, subtype);
1189 		return;
1190 
1191 	case IEEE80211_FC0_SUBTYPE_DEAUTH:
1192 		if (ic->ic_state == IEEE80211_S_SCAN)
1193 			break;
1194 
1195 		/*
1196 		 * deauth frame format
1197 		 *	[2] reason
1198 		 */
1199 		IEEE80211_VERIFY_LENGTH(_PTRDIFF(efrm, frm), 2, break);
1200 		status = (*(uint16_t *)frm);
1201 
1202 		ieee80211_dbg(IEEE80211_MSG_AUTH,
1203 		    "recv deauthenticate (reason %d)\n", status);
1204 		switch (ic->ic_opmode) {
1205 		case IEEE80211_M_STA:
1206 			IEEE80211_UNLOCK(ic);
1207 			ieee80211_new_state(ic, IEEE80211_S_AUTH,
1208 			    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
1209 			return;
1210 		default:
1211 			break;
1212 		}
1213 		break;
1214 
1215 	case IEEE80211_FC0_SUBTYPE_DISASSOC:
1216 		if (ic->ic_state != IEEE80211_S_RUN &&
1217 		    ic->ic_state != IEEE80211_S_ASSOC &&
1218 		    ic->ic_state != IEEE80211_S_AUTH)
1219 			break;
1220 		/*
1221 		 * disassoc frame format
1222 		 *	[2] reason
1223 		 */
1224 		IEEE80211_VERIFY_LENGTH(_PTRDIFF(efrm, frm), 2, break);
1225 		status = (*(uint16_t *)frm);
1226 
1227 		ieee80211_dbg(IEEE80211_MSG_ASSOC,
1228 		    "recv disassociate (reason %d)\n", status);
1229 		switch (ic->ic_opmode) {
1230 		case IEEE80211_M_STA:
1231 			IEEE80211_UNLOCK(ic);
1232 			ieee80211_new_state(ic, IEEE80211_S_ASSOC,
1233 			    wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK);
1234 			return;
1235 		default:
1236 			break;
1237 		}
1238 		break;
1239 
1240 	default:
1241 		ieee80211_dbg(IEEE80211_MSG_ANY, "ieee80211_recv_mgmt: "
1242 		    "subtype 0x%x not handled\n", subtype);
1243 		break;
1244 	} /* switch subtype */
1245 out:
1246 	IEEE80211_UNLOCK(ic);
1247 }
1248