xref: /titanic_41/usr/src/uts/common/io/net80211/net80211_node.c (revision e2cf88ac9d753a00c17aa235f6afdc76574fe3a6)
1 /*
2  * Copyright 2009 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-2008 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  * Node management routines
40  */
41 
42 #include "net80211_impl.h"
43 
44 static ieee80211_node_t *ieee80211_node_alloc(ieee80211com_t *);
45 static void ieee80211_node_cleanup(ieee80211_node_t *);
46 static void ieee80211_node_free(ieee80211_node_t *);
47 static uint8_t ieee80211_node_getrssi(const ieee80211_node_t *);
48 static void ieee80211_setup_node(ieee80211com_t *, ieee80211_node_table_t *,
49     ieee80211_node_t *, const uint8_t *);
50 static void ieee80211_node_reclaim(ieee80211_node_table_t *,
51     ieee80211_node_t *);
52 static void ieee80211_free_node_locked(ieee80211_node_t *);
53 static void ieee80211_free_allnodes(ieee80211_node_table_t *);
54 static void ieee80211_node_leave(ieee80211com_t *, ieee80211_node_t *);
55 static void ieee80211_timeout_scan_candidates(ieee80211_node_table_t *);
56 static void ieee80211_timeout_stations(ieee80211_node_table_t *);
57 static void ieee80211_node_table_init(ieee80211com_t *,
58     ieee80211_node_table_t *, const char *, int, int,
59     void (*timeout)(ieee80211_node_table_t *));
60 static void ieee80211_node_table_cleanup(ieee80211_node_table_t *);
61 
62 /*
63  * association failures before ignored
64  * The failure may be caused by the response frame is lost for
65  * environmental reason. So Try associate more than once before
66  * ignore the node
67  */
68 #define	IEEE80211_STA_FAILS_MAX	2
69 
70 /*
71  * Initialize node database management callbacks for the interface.
72  * This function is called by ieee80211_attach(). These callback
73  * functions may be overridden in special circumstances, as long as
74  * as this is done after calling ieee80211_attach() and prior to any
75  * other call which may allocate a node
76  */
77 void
ieee80211_node_attach(ieee80211com_t * ic)78 ieee80211_node_attach(ieee80211com_t *ic)
79 {
80 	struct ieee80211_impl *im = ic->ic_private;
81 
82 	ic->ic_node_alloc = ieee80211_node_alloc;
83 	ic->ic_node_free = ieee80211_node_free;
84 	ic->ic_node_cleanup = ieee80211_node_cleanup;
85 	ic->ic_node_getrssi = ieee80211_node_getrssi;
86 
87 	/* default station inactivity timer setings */
88 	im->im_inact_init = IEEE80211_INACT_INIT;
89 	im->im_inact_assoc = IEEE80211_INACT_ASSOC;
90 	im->im_inact_run = IEEE80211_INACT_RUN;
91 	im->im_inact_probe = IEEE80211_INACT_PROBE;
92 }
93 
94 /*
95  * Initialize node databases and the ic_bss node element.
96  */
97 void
ieee80211_node_lateattach(ieee80211com_t * ic)98 ieee80211_node_lateattach(ieee80211com_t *ic)
99 {
100 	/*
101 	 * Calculate ic_tim_bitmap size in bytes
102 	 * IEEE80211_AID_MAX defines maximum bits in ic_tim_bitmap
103 	 */
104 	ic->ic_tim_len = howmany(IEEE80211_AID_MAX, 8) * sizeof (uint8_t);
105 
106 	ieee80211_node_table_init(ic, &ic->ic_sta, "station",
107 	    IEEE80211_INACT_INIT, IEEE80211_WEP_NKID,
108 	    ieee80211_timeout_stations);
109 	ieee80211_node_table_init(ic, &ic->ic_scan, "scan",
110 	    IEEE80211_INACT_SCAN, 0, ieee80211_timeout_scan_candidates);
111 
112 	ieee80211_reset_bss(ic);
113 }
114 
115 /*
116  * Destroy all node databases and is usually called during device detach
117  */
118 void
ieee80211_node_detach(ieee80211com_t * ic)119 ieee80211_node_detach(ieee80211com_t *ic)
120 {
121 	/* Node Detach */
122 	if (ic->ic_bss != NULL) {
123 		ieee80211_free_node(ic->ic_bss);
124 		ic->ic_bss = NULL;
125 	}
126 	ieee80211_node_table_cleanup(&ic->ic_scan);
127 	ieee80211_node_table_cleanup(&ic->ic_sta);
128 }
129 
130 /*
131  * Increase a node's reference count
132  *
133  * Return pointer to the node
134  */
135 ieee80211_node_t *
ieee80211_ref_node(ieee80211_node_t * in)136 ieee80211_ref_node(ieee80211_node_t *in)
137 {
138 	ieee80211_node_incref(in);
139 	return (in);
140 }
141 
142 /*
143  * Dexrease a node's reference count
144  */
145 void
ieee80211_unref_node(ieee80211_node_t ** in)146 ieee80211_unref_node(ieee80211_node_t **in)
147 {
148 	ieee80211_node_decref(*in);
149 	*in = NULL;			/* guard against use */
150 }
151 
152 /*
153  * Mark ports authorized for data traffic. This function is usually
154  * used by 802.1x authenticator.
155  */
156 void
ieee80211_node_authorize(ieee80211_node_t * in)157 ieee80211_node_authorize(ieee80211_node_t *in)
158 {
159 	ieee80211_impl_t *im = in->in_ic->ic_private;
160 
161 	in->in_flags |= IEEE80211_NODE_AUTH;
162 	in->in_inact_reload = im->im_inact_run;
163 	in->in_inact = in->in_inact_reload;
164 }
165 
166 /*
167  * Mark ports unauthorized for data traffic. This function is usually
168  * used by 802.1x authenticator.
169  */
170 void
ieee80211_node_unauthorize(ieee80211_node_t * in)171 ieee80211_node_unauthorize(ieee80211_node_t *in)
172 {
173 	in->in_flags &= ~IEEE80211_NODE_AUTH;
174 }
175 
176 /*
177  * Set/change the channel.  The rate set is also updated as
178  * to insure a consistent view by drivers.
179  */
180 static void
ieee80211_node_setchan(ieee80211com_t * ic,ieee80211_node_t * in,struct ieee80211_channel * chan)181 ieee80211_node_setchan(ieee80211com_t *ic, ieee80211_node_t *in,
182     struct ieee80211_channel *chan)
183 {
184 	if (chan == IEEE80211_CHAN_ANYC)
185 		chan = ic->ic_curchan;
186 	in->in_chan = chan;
187 	if (IEEE80211_IS_CHAN_HT(chan)) {
188 		/*
189 		 * Gotta be careful here; the rate set returned by
190 		 * ieee80211_get_suprates is actually any HT rate
191 		 * set so blindly copying it will be bad.  We must
192 		 * install the legacy rate est in ni_rates and the
193 		 * HT rate set in ni_htrates.
194 		 */
195 		in->in_htrates = *ieee80211_get_suphtrates(ic, chan);
196 	}
197 	in->in_rates = *ieee80211_get_suprates(ic, chan);
198 	/* in->in_rates = ic->ic_sup_rates[ieee80211_chan2mode(ic, chan)]; */
199 }
200 
201 /*
202  * Initialize the channel set to scan based on the available channels
203  * and the current PHY mode.
204  */
205 static void
ieee80211_reset_scan(ieee80211com_t * ic)206 ieee80211_reset_scan(ieee80211com_t *ic)
207 {
208 	ieee80211_impl_t	*im = ic->ic_private;
209 
210 	if (ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
211 		(void) memset(im->im_chan_scan, 0, sizeof (im->im_chan_scan));
212 		ieee80211_setbit(im->im_chan_scan,
213 		    ieee80211_chan2ieee(ic, ic->ic_des_chan));
214 	} else {
215 		bcopy(ic->ic_chan_active, im->im_chan_scan,
216 		    sizeof (ic->ic_chan_active));
217 	}
218 	ieee80211_dbg(IEEE80211_MSG_SCAN, "ieee80211_reset_scan(): "
219 	    "start chan %u\n", ieee80211_chan2ieee(ic, ic->ic_curchan));
220 }
221 
222 /*
223  * Begin an active scan. Initialize the node cache. The scan
224  * begins on the next radio channel by calling ieee80211_next_scan().
225  * The actual scanning is not automated. The driver itself
226  * only handles setting the radio frequency and stepping through
227  * the channels.
228  */
229 void
ieee80211_begin_scan(ieee80211com_t * ic,boolean_t reset)230 ieee80211_begin_scan(ieee80211com_t *ic, boolean_t reset)
231 {
232 	IEEE80211_LOCK(ic);
233 
234 	if (ic->ic_opmode != IEEE80211_M_HOSTAP)
235 		ic->ic_flags |= IEEE80211_F_ASCAN;
236 	ieee80211_dbg(IEEE80211_MSG_SCAN,
237 	    "begin %s scan in %s mode on channel %u\n",
238 	    (ic->ic_flags & IEEE80211_F_ASCAN) ?  "active" : "passive",
239 	    ieee80211_phymode_name[ic->ic_curmode],
240 	    ieee80211_chan2ieee(ic, ic->ic_curchan));
241 
242 	/*
243 	 * Clear scan state and flush any previously seen AP's.
244 	 */
245 	ieee80211_reset_scan(ic);
246 	if (reset)
247 		ieee80211_free_allnodes(&ic->ic_scan);
248 
249 	ic->ic_flags |= IEEE80211_F_SCAN;
250 	IEEE80211_UNLOCK(ic);
251 
252 	/* Scan the next channel. */
253 	ieee80211_next_scan(ic);
254 }
255 
256 /*
257  * Switch to the next channel marked for scanning.
258  * A driver is expected to first call ieee80211_begin_scan(),
259  * to initialize the node cache, then set the radio channel
260  * on the device. And then after a certain time has elapsed,
261  * call ieee80211_next_scan() to move to the next channel.
262  * Typically, a timeout routine is used to automate this process.
263  */
264 void
ieee80211_next_scan(ieee80211com_t * ic)265 ieee80211_next_scan(ieee80211com_t *ic)
266 {
267 	ieee80211_impl_t *im = ic->ic_private;
268 	struct ieee80211_channel *chan;
269 
270 	IEEE80211_LOCK(ic);
271 	/*
272 	 * Insure any previous mgt frame timeouts don't fire.
273 	 * This assumes the driver does the right thing in
274 	 * flushing anything queued in the driver and below.
275 	 */
276 	im->im_mgt_timer = 0;
277 
278 	chan = ic->ic_curchan;
279 	do {
280 		if (++chan > &ic->ic_sup_channels[IEEE80211_CHAN_MAX])
281 			chan = &ic->ic_sup_channels[0];
282 		if (ieee80211_isset(im->im_chan_scan,
283 		    ieee80211_chan2ieee(ic, chan))) {
284 			ieee80211_clrbit(im->im_chan_scan,
285 			    ieee80211_chan2ieee(ic, chan));
286 			ieee80211_dbg(IEEE80211_MSG_SCAN,
287 			    "ieee80211_next_scan: chan %d->%d\n",
288 			    ieee80211_chan2ieee(ic, ic->ic_curchan),
289 			    ieee80211_chan2ieee(ic, chan));
290 			ic->ic_curchan = chan;
291 			/*
292 			 * drivers should do this as needed,
293 			 * for now maintain compatibility
294 			 */
295 			ic->ic_bss->in_rates =
296 			    ic->ic_sup_rates[ieee80211_chan2mode(ic, chan)];
297 			IEEE80211_UNLOCK(ic);
298 			ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
299 			return;
300 		}
301 	} while (chan != ic->ic_curchan);
302 	IEEE80211_UNLOCK(ic);
303 	ieee80211_end_scan(ic);
304 }
305 
306 /*
307  * Copy useful state from node obss into nbss.
308  */
309 static void
ieee80211_copy_bss(ieee80211_node_t * nbss,const ieee80211_node_t * obss)310 ieee80211_copy_bss(ieee80211_node_t *nbss, const ieee80211_node_t *obss)
311 {
312 	/* propagate useful state */
313 	nbss->in_authmode = obss->in_authmode;
314 	nbss->in_txpower = obss->in_txpower;
315 	nbss->in_vlan = obss->in_vlan;
316 }
317 
318 /*
319  * Setup the net80211 specific portion of an interface's softc, ic,
320  * for use in IBSS mode
321  */
322 void
ieee80211_create_ibss(ieee80211com_t * ic,struct ieee80211_channel * chan)323 ieee80211_create_ibss(ieee80211com_t *ic, struct ieee80211_channel *chan)
324 {
325 	ieee80211_impl_t *im = ic->ic_private;
326 	ieee80211_node_table_t *nt;
327 	ieee80211_node_t *in;
328 
329 	IEEE80211_LOCK_ASSERT(ic);
330 	ieee80211_dbg(IEEE80211_MSG_SCAN, "ieee80211_create_ibss: "
331 	    "creating ibss\n");
332 
333 	/*
334 	 * Create the station/neighbor table.  Note that for adhoc
335 	 * mode we make the initial inactivity timer longer since
336 	 * we create nodes only through discovery and they typically
337 	 * are long-lived associations.
338 	 */
339 	nt = &ic->ic_sta;
340 	IEEE80211_NODE_LOCK(nt);
341 	nt->nt_name = "neighbor";
342 	nt->nt_inact_init = im->im_inact_run;
343 	IEEE80211_NODE_UNLOCK(nt);
344 
345 	in = ieee80211_alloc_node(ic, &ic->ic_sta, ic->ic_macaddr);
346 	if (in == NULL) {
347 		ieee80211_err("ieee80211_create_ibss(): alloc node failed\n");
348 		return;
349 	}
350 	IEEE80211_ADDR_COPY(in->in_bssid, ic->ic_macaddr);
351 	in->in_esslen = ic->ic_des_esslen;
352 	(void) memcpy(in->in_essid, ic->ic_des_essid, in->in_esslen);
353 	ieee80211_copy_bss(in, ic->ic_bss);
354 	in->in_intval = ic->ic_bintval;
355 	if (ic->ic_flags & IEEE80211_F_PRIVACY)
356 		in->in_capinfo |= IEEE80211_CAPINFO_PRIVACY;
357 	if (ic->ic_phytype == IEEE80211_T_FH) {
358 		in->in_fhdwell = 200;
359 		in->in_fhindex = 1;
360 	}
361 	switch (ic->ic_opmode) {
362 	case IEEE80211_M_IBSS:
363 		ic->ic_flags |= IEEE80211_F_SIBSS;
364 		in->in_capinfo |= IEEE80211_CAPINFO_IBSS;
365 		if (ic->ic_flags & IEEE80211_F_DESBSSID)
366 			IEEE80211_ADDR_COPY(in->in_bssid, ic->ic_des_bssid);
367 		else
368 			in->in_bssid[0] |= 0x02;	/* local bit for IBSS */
369 		break;
370 	case IEEE80211_M_AHDEMO:
371 		if (ic->ic_flags & IEEE80211_F_DESBSSID)
372 			IEEE80211_ADDR_COPY(in->in_bssid, ic->ic_des_bssid);
373 		else
374 			(void) memset(in->in_bssid, 0, IEEE80211_ADDR_LEN);
375 		break;
376 	default:
377 		ieee80211_err("ieee80211_create_ibss(): "
378 		    "wrong opmode %u to creat IBSS, abort\n",
379 		    ic->ic_opmode);
380 		ieee80211_free_node(in);
381 		return;
382 	}
383 
384 	/*
385 	 * Fix the channel and related attributes.
386 	 */
387 	ieee80211_node_setchan(ic, in, chan);
388 	ic->ic_curchan = chan;
389 	ic->ic_curmode = ieee80211_chan2mode(ic, chan);
390 	/*
391 	 * Do mode-specific rate setup.
392 	 */
393 	ieee80211_setbasicrates(&in->in_rates, ic->ic_curmode);
394 	IEEE80211_UNLOCK(ic);
395 	ieee80211_sta_join(ic, ieee80211_ref_node(in));
396 	IEEE80211_LOCK(ic);
397 }
398 
399 void
ieee80211_reset_bss(ieee80211com_t * ic)400 ieee80211_reset_bss(ieee80211com_t *ic)
401 {
402 	ieee80211_node_t *in;
403 	ieee80211_node_t *obss;
404 
405 	ieee80211_node_table_reset(&ic->ic_sta);
406 	ieee80211_reset_erp(ic);
407 
408 	in = ieee80211_alloc_node(ic, &ic->ic_scan, ic->ic_macaddr);
409 	ASSERT(in != NULL);
410 	obss = ic->ic_bss;
411 	ic->ic_bss = ieee80211_ref_node(in);
412 	if (obss != NULL) {
413 		ieee80211_copy_bss(in, obss);
414 		in->in_intval = ic->ic_bintval;
415 		ieee80211_free_node(obss);
416 	}
417 }
418 
419 static int
ieee80211_match_bss(ieee80211com_t * ic,ieee80211_node_t * in)420 ieee80211_match_bss(ieee80211com_t *ic, ieee80211_node_t *in)
421 {
422 	uint8_t rate;
423 	int fail;
424 
425 	fail = 0;
426 	if (ieee80211_isclr(ic->ic_chan_active,
427 	    ieee80211_chan2ieee(ic, in->in_chan))) {
428 		fail |= IEEE80211_BADCHAN;
429 	}
430 	if (ic->ic_des_chan != IEEE80211_CHAN_ANYC &&
431 	    in->in_chan != ic->ic_des_chan) {
432 		fail |= IEEE80211_BADCHAN;
433 	}
434 	if (ic->ic_opmode == IEEE80211_M_IBSS) {
435 		if (!(in->in_capinfo & IEEE80211_CAPINFO_IBSS))
436 			fail |= IEEE80211_BADOPMODE;
437 	} else {
438 		if (!(in->in_capinfo & IEEE80211_CAPINFO_ESS))
439 			fail |= IEEE80211_BADOPMODE;
440 	}
441 	if (ic->ic_flags & IEEE80211_F_PRIVACY) {
442 		if (!(in->in_capinfo & IEEE80211_CAPINFO_PRIVACY))
443 			fail |= IEEE80211_BADPRIVACY;
444 	} else {
445 		if (in->in_capinfo & IEEE80211_CAPINFO_PRIVACY)
446 			fail |= IEEE80211_BADPRIVACY;
447 	}
448 	rate = ieee80211_fix_rate(in, &in->in_rates,
449 	    IEEE80211_F_DONEGO | IEEE80211_F_DOFRATE);
450 	if (rate & IEEE80211_RATE_BASIC)
451 		fail |= IEEE80211_BADRATE;
452 	if (ic->ic_des_esslen != 0 &&
453 	    (in->in_esslen != ic->ic_des_esslen ||
454 	    memcmp(in->in_essid, ic->ic_des_essid, ic->ic_des_esslen) != 0)) {
455 		fail |= IEEE80211_BADESSID;
456 	}
457 	if ((ic->ic_flags & IEEE80211_F_DESBSSID) &&
458 	    !IEEE80211_ADDR_EQ(ic->ic_des_bssid, in->in_bssid)) {
459 		fail |= IEEE80211_BADBSSID;
460 	}
461 	if (in->in_fails >= IEEE80211_STA_FAILS_MAX)
462 		fail |= IEEE80211_NODEFAIL;
463 
464 	return (fail);
465 }
466 
467 #define	IEEE80211_MAXRATE(_rs) \
468 	((_rs).ir_rates[(_rs).ir_nrates - 1] & IEEE80211_RATE_VAL)
469 
470 /*
471  * Compare the capabilities of node a with node b and decide which is
472  * more desirable (return b if b is considered better than a).  Note
473  * that we assume compatibility/usability has already been checked
474  * so we don't need to (e.g. validate whether privacy is supported).
475  * Used to select the best scan candidate for association in a BSS.
476  *
477  * Return desired node
478  */
479 static ieee80211_node_t *
ieee80211_node_compare(ieee80211com_t * ic,ieee80211_node_t * a,ieee80211_node_t * b)480 ieee80211_node_compare(ieee80211com_t *ic, ieee80211_node_t *a,
481     ieee80211_node_t *b)
482 {
483 	uint8_t maxa;
484 	uint8_t maxb;
485 	uint8_t rssia;
486 	uint8_t rssib;
487 
488 	/* privacy support preferred */
489 	if ((a->in_capinfo & IEEE80211_CAPINFO_PRIVACY) &&
490 	    !(b->in_capinfo & IEEE80211_CAPINFO_PRIVACY)) {
491 		return (a);
492 	}
493 	if (!(a->in_capinfo & IEEE80211_CAPINFO_PRIVACY) &&
494 	    (b->in_capinfo & IEEE80211_CAPINFO_PRIVACY)) {
495 		return (b);
496 	}
497 
498 	/* compare count of previous failures */
499 	if (b->in_fails != a->in_fails)
500 		return ((a->in_fails > b->in_fails) ? b : a);
501 
502 	rssia = ic->ic_node_getrssi(a);
503 	rssib = ic->ic_node_getrssi(b);
504 	if (ABS(rssib - rssia) < IEEE80211_RSSI_CMP_THRESHOLD) {
505 		/* best/max rate preferred if signal level close enough */
506 		maxa = IEEE80211_MAXRATE(a->in_rates);
507 		maxb = IEEE80211_MAXRATE(b->in_rates);
508 		if (maxa != maxb)
509 			return ((maxb > maxa) ? b : a);
510 		/* for now just prefer 5Ghz band to all other bands */
511 		if (IEEE80211_IS_CHAN_5GHZ(a->in_chan) &&
512 		    !IEEE80211_IS_CHAN_5GHZ(b->in_chan)) {
513 			return (a);
514 		}
515 		if (!IEEE80211_IS_CHAN_5GHZ(a->in_chan) &&
516 		    IEEE80211_IS_CHAN_5GHZ(b->in_chan)) {
517 			return (b);
518 		}
519 	}
520 	/* all things being equal, compare signal level */
521 	return ((rssib > rssia) ? b : a);
522 }
523 
524 /*
525  * Mark an ongoing scan stopped.
526  */
527 void
ieee80211_cancel_scan(ieee80211com_t * ic)528 ieee80211_cancel_scan(ieee80211com_t *ic)
529 {
530 	IEEE80211_LOCK(ic);
531 	ieee80211_dbg(IEEE80211_MSG_SCAN, "ieee80211_cancel_scan()"
532 	    "end %s scan\n",
533 	    (ic->ic_flags & IEEE80211_F_ASCAN) ?  "active" : "passive");
534 	ic->ic_flags &= ~(IEEE80211_F_SCAN | IEEE80211_F_ASCAN);
535 	cv_broadcast(&((ieee80211_impl_t *)ic->ic_private)->im_scan_cv);
536 	IEEE80211_UNLOCK(ic);
537 }
538 
539 /*
540  * Complete a scan of potential channels. It is called by
541  * ieee80211_next_scan() when the state machine has performed
542  * a full cycle of scaning on all available radio channels.
543  * ieee80211_end_scan() will inspect the node cache for suitable
544  * APs found during scaning, and associate with one, should
545  * the parameters of the node match those of the configuration
546  * requested from userland.
547  */
548 void
ieee80211_end_scan(ieee80211com_t * ic)549 ieee80211_end_scan(ieee80211com_t *ic)
550 {
551 	ieee80211_node_table_t *nt = &ic->ic_scan;
552 	ieee80211_node_t *in;
553 	ieee80211_node_t *selbs;
554 
555 	ieee80211_cancel_scan(ic);
556 	/* notify SCAN done */
557 	ieee80211_notify(ic, EVENT_SCAN_RESULTS);
558 	IEEE80211_LOCK(ic);
559 
560 	/*
561 	 * Automatic sequencing; look for a candidate and
562 	 * if found join the network.
563 	 */
564 	/* NB: unlocked read should be ok */
565 	in = list_head(&nt->nt_node);
566 	if (in == NULL && (ic->ic_flags & IEEE80211_F_WPA) == 0) {
567 		ieee80211_dbg(IEEE80211_MSG_SCAN, "ieee80211_end_scan: "
568 		    "no scan candidate\n");
569 	notfound:
570 		if (ic->ic_opmode == IEEE80211_M_IBSS &&
571 		    (ic->ic_flags & IEEE80211_F_IBSSON) &&
572 		    ic->ic_des_esslen != 0) {
573 			ieee80211_create_ibss(ic, ic->ic_ibss_chan);
574 			IEEE80211_UNLOCK(ic);
575 			return;
576 		}
577 
578 		/*
579 		 * Reset the list of channels to scan and start again.
580 		 */
581 		ieee80211_reset_scan(ic);
582 		ic->ic_flags |= IEEE80211_F_SCAN | IEEE80211_F_ASCAN;
583 		IEEE80211_UNLOCK(ic);
584 
585 		ieee80211_next_scan(ic);
586 		return;
587 	}
588 
589 	if (ic->ic_flags & IEEE80211_F_SCANONLY ||
590 	    ic->ic_flags & IEEE80211_F_WPA) {	/* scan only */
591 		ic->ic_flags &= ~IEEE80211_F_SCANONLY;
592 		IEEE80211_UNLOCK(ic);
593 		ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
594 		return;
595 	}
596 
597 	selbs = NULL;
598 	IEEE80211_NODE_LOCK(nt);
599 	while (in != NULL) {
600 		if (in->in_fails >= IEEE80211_STA_FAILS_MAX) {
601 			ieee80211_node_t *tmpin = in;
602 
603 			/*
604 			 * The configuration of the access points may change
605 			 * during my scan.  So delete the entry for the AP
606 			 * and retry to associate if there is another beacon.
607 			 */
608 			in = list_next(&nt->nt_node, tmpin);
609 			ieee80211_node_reclaim(nt, tmpin);
610 			continue;
611 		}
612 		/*
613 		 * It's possible at some special moments, the in_chan will
614 		 * be none. Need to skip the null node.
615 		 */
616 		if (in->in_chan == IEEE80211_CHAN_ANYC) {
617 			in = list_next(&nt->nt_node, in);
618 			continue;
619 		}
620 		if (ieee80211_match_bss(ic, in) == 0) {
621 			if (selbs == NULL)
622 				selbs = in;
623 			else
624 				selbs = ieee80211_node_compare(ic, selbs, in);
625 		}
626 		in = list_next(&nt->nt_node, in);
627 	}
628 	if (selbs != NULL)	/* grab ref while dropping lock */
629 		(void) ieee80211_ref_node(selbs);
630 	IEEE80211_NODE_UNLOCK(nt);
631 	if (selbs == NULL)
632 		goto notfound;
633 	IEEE80211_UNLOCK(ic);
634 	ieee80211_sta_join(ic, selbs);
635 }
636 
637 
638 /*
639  * Handle 802.11 ad hoc network merge.  The convention, set by the
640  * Wireless Ethernet Compatibility Alliance (WECA), is that an 802.11
641  * station will change its BSSID to match the "oldest" 802.11 ad hoc
642  * network, on the same channel, that has the station's desired SSID.
643  * The "oldest" 802.11 network sends beacons with the greatest TSF
644  * timestamp.
645  * The caller is assumed to validate TSF's before attempting a merge.
646  *
647  * Return B_TRUE if the BSSID changed, B_FALSE otherwise.
648  */
649 boolean_t
ieee80211_ibss_merge(ieee80211_node_t * in)650 ieee80211_ibss_merge(ieee80211_node_t *in)
651 {
652 	ieee80211com_t *ic = in->in_ic;
653 
654 	if (in == ic->ic_bss ||
655 	    IEEE80211_ADDR_EQ(in->in_bssid, ic->ic_bss->in_bssid)) {
656 		/* unchanged, nothing to do */
657 		return (B_FALSE);
658 	}
659 	if (ieee80211_match_bss(ic, in) != 0) {	/* capabilities mismatch */
660 		ieee80211_dbg(IEEE80211_MSG_ASSOC, "ieee80211_ibss_merge: "
661 		    " merge failed, capabilities mismatch\n");
662 		return (B_FALSE);
663 	}
664 	ieee80211_dbg(IEEE80211_MSG_ASSOC, "ieee80211_ibss_merge: "
665 	    "new bssid %s: %s preamble, %s slot time%s\n",
666 	    ieee80211_macaddr_sprintf(in->in_bssid),
667 	    (ic->ic_flags & IEEE80211_F_SHPREAMBLE) ? "short" : "long",
668 	    (ic->ic_flags & IEEE80211_F_SHSLOT) ? "short" : "long",
669 	    (ic->ic_flags&IEEE80211_F_USEPROT) ? ", protection" : "");
670 	ieee80211_sta_join(ic, ieee80211_ref_node(in));
671 	return (B_TRUE);
672 }
673 
674 /*
675  * Change the bss channel.
676  */
677 void
ieee80211_setcurchan(ieee80211com_t * ic,struct ieee80211_channel * c)678 ieee80211_setcurchan(ieee80211com_t *ic, struct ieee80211_channel *c)
679 {
680 	ic->ic_curchan = c;
681 	ic->ic_curmode = ieee80211_chan2mode(ic, ic->ic_curchan);
682 	if (ic->ic_set_channel != NULL)
683 		ic->ic_set_channel(ic);
684 }
685 
686 /*
687  * Join the specified IBSS/BSS network.  The node is assumed to
688  * be passed in with a held reference.
689  */
690 void
ieee80211_sta_join(ieee80211com_t * ic,ieee80211_node_t * selbs)691 ieee80211_sta_join(ieee80211com_t *ic, ieee80211_node_t *selbs)
692 {
693 	ieee80211_impl_t *im = ic->ic_private;
694 	ieee80211_node_t *obss;
695 
696 	IEEE80211_LOCK(ic);
697 	if (ic->ic_opmode == IEEE80211_M_IBSS) {
698 		ieee80211_node_table_t *nt;
699 
700 		/*
701 		 * Delete unusable rates; we've already checked
702 		 * that the negotiated rate set is acceptable.
703 		 */
704 		(void) ieee80211_fix_rate(selbs, &selbs->in_rates,
705 		    IEEE80211_F_DODEL);
706 		/*
707 		 * Fillin the neighbor table
708 		 */
709 		nt = &ic->ic_sta;
710 		IEEE80211_NODE_LOCK(nt);
711 		nt->nt_name = "neighbor";
712 		nt->nt_inact_init = im->im_inact_run;
713 		IEEE80211_NODE_UNLOCK(nt);
714 	}
715 
716 	/*
717 	 * Committed to selbs, setup state.
718 	 */
719 	obss = ic->ic_bss;
720 	ic->ic_bss = selbs;	/* caller assumed to bump refcnt */
721 	if (obss != NULL) {
722 		ieee80211_copy_bss(selbs, obss);
723 		ieee80211_free_node(obss);
724 	}
725 	ic->ic_curmode = ieee80211_chan2mode(ic, selbs->in_chan);
726 	ic->ic_curchan = selbs->in_chan;
727 	ic->ic_phytype = selbs->in_phytype;
728 	/*
729 	 * Set the erp state (mostly the slot time) to deal with
730 	 * the auto-select case; this should be redundant if the
731 	 * mode is locked.
732 	 */
733 	ieee80211_reset_erp(ic);
734 	ieee80211_wme_initparams(ic);
735 
736 	IEEE80211_UNLOCK(ic);
737 	if (ic->ic_opmode == IEEE80211_M_STA)
738 		ieee80211_new_state(ic, IEEE80211_S_AUTH, -1);
739 	else
740 		ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
741 }
742 
743 /*
744  * Leave the specified IBSS/BSS network.  The node is assumed to
745  * be passed in with a held reference.
746  */
747 void
ieee80211_sta_leave(ieee80211com_t * ic,ieee80211_node_t * in)748 ieee80211_sta_leave(ieee80211com_t *ic, ieee80211_node_t *in)
749 {
750 	IEEE80211_LOCK(ic);
751 	ic->ic_node_cleanup(in);
752 	ieee80211_notify_node_leave(ic, in);
753 	IEEE80211_UNLOCK(ic);
754 }
755 
756 /*
757  * Allocate a node. This is the default callback function for
758  * ic_node_alloc. This function may be overridden by the driver
759  * to allocate device specific node structure.
760  */
761 /* ARGSUSED */
762 static ieee80211_node_t *
ieee80211_node_alloc(ieee80211com_t * ic)763 ieee80211_node_alloc(ieee80211com_t *ic)
764 {
765 	return (kmem_zalloc(sizeof (ieee80211_node_t), KM_SLEEP));
766 }
767 
768 /*
769  * Cleanup a node, free any memory associated with the node.
770  * This is the default callback function for ic_node_cleanup
771  * and may be overridden by the driver.
772  */
773 static void
ieee80211_node_cleanup(ieee80211_node_t * in)774 ieee80211_node_cleanup(ieee80211_node_t *in)
775 {
776 	in->in_associd = 0;
777 	in->in_rssi = 0;
778 	in->in_rstamp = 0;
779 	if (in->in_challenge != NULL) {
780 		kmem_free(in->in_challenge, IEEE80211_CHALLENGE_LEN);
781 		in->in_challenge = NULL;
782 	}
783 	if (in->in_rxfrag != NULL) {
784 		freemsg(in->in_rxfrag);
785 		in->in_rxfrag = NULL;
786 	}
787 }
788 
789 /*
790  * Free a node. This is the default callback function for ic_node_free
791  * and may be overridden by the driver to free memory used by device
792  * specific node structure
793  */
794 static void
ieee80211_node_free(ieee80211_node_t * in)795 ieee80211_node_free(ieee80211_node_t *in)
796 {
797 	ieee80211com_t *ic = in->in_ic;
798 
799 	ic->ic_node_cleanup(in);
800 	if (in->in_wpa_ie != NULL)
801 		ieee80211_free(in->in_wpa_ie);
802 	if (in->in_wme_ie != NULL)
803 		ieee80211_free(in->in_wme_ie);
804 	if (in->in_htcap_ie != NULL)
805 		ieee80211_free(in->in_htcap_ie);
806 	kmem_free(in, sizeof (ieee80211_node_t));
807 }
808 
809 /*
810  * Get a node current RSSI value. This is the default callback function
811  * for ic_node_getrssi and may be overridden by the driver to provide
812  * device specific RSSI calculation algorithm.
813  */
814 static uint8_t
ieee80211_node_getrssi(const ieee80211_node_t * in)815 ieee80211_node_getrssi(const ieee80211_node_t *in)
816 {
817 	return (in->in_rssi);
818 }
819 
820 /* Free fragment if not needed anymore */
821 static void
node_cleanfrag(ieee80211_node_t * in)822 node_cleanfrag(ieee80211_node_t *in)
823 {
824 	clock_t ticks;
825 
826 	ticks = ddi_get_lbolt();
827 	if (in->in_rxfrag != NULL && ticks > (in->in_rxfragstamp + hz)) {
828 		freemsg(in->in_rxfrag);
829 		in->in_rxfrag = NULL;
830 	}
831 }
832 
833 /*
834  * Setup a node. Initialize the node with specified macaddr. Associate
835  * with the interface softc, ic, and add it to the specified node
836  * database.
837  */
838 static void
ieee80211_setup_node(ieee80211com_t * ic,ieee80211_node_table_t * nt,ieee80211_node_t * in,const uint8_t * macaddr)839 ieee80211_setup_node(ieee80211com_t *ic, ieee80211_node_table_t *nt,
840     ieee80211_node_t *in, const uint8_t *macaddr)
841 {
842 	int32_t hash;
843 
844 	ieee80211_dbg(IEEE80211_MSG_NODE, "ieee80211_setup_node(): "
845 	    "%p<%s> in %s table\n", in,
846 	    ieee80211_macaddr_sprintf(macaddr),
847 	    (nt != NULL) ? nt->nt_name : "NULL");
848 
849 	in->in_ic = ic;
850 	IEEE80211_ADDR_COPY(in->in_macaddr, macaddr);
851 	hash = ieee80211_node_hash(macaddr);
852 	ieee80211_node_initref(in);		/* mark referenced */
853 	in->in_authmode = IEEE80211_AUTH_OPEN;
854 	in->in_txpower = ic->ic_txpowlimit;	/* max power */
855 	in->in_chan = IEEE80211_CHAN_ANYC;
856 	in->in_inact_reload = IEEE80211_INACT_INIT;
857 	in->in_inact = in->in_inact_reload;
858 	ieee80211_crypto_resetkey(ic, &in->in_ucastkey, IEEE80211_KEYIX_NONE);
859 
860 	if (nt != NULL) {
861 		IEEE80211_NODE_LOCK(nt);
862 		list_insert_tail(&nt->nt_node, in);
863 		list_insert_tail(&nt->nt_hash[hash], in);
864 		in->in_table = nt;
865 		in->in_inact_reload = nt->nt_inact_init;
866 		IEEE80211_NODE_UNLOCK(nt);
867 	}
868 }
869 
870 /*
871  * Allocates and initialize a node with specified MAC address.
872  * Associate the node with the interface ic. If the allocation
873  * is successful, the node structure is initialized by
874  * ieee80211_setup_node(); otherwise, NULL is returned
875  */
876 ieee80211_node_t *
ieee80211_alloc_node(ieee80211com_t * ic,ieee80211_node_table_t * nt,const uint8_t * macaddr)877 ieee80211_alloc_node(ieee80211com_t *ic, ieee80211_node_table_t *nt,
878     const uint8_t *macaddr)
879 {
880 	ieee80211_node_t *in;
881 
882 	in = ic->ic_node_alloc(ic);
883 	if (in != NULL)
884 		ieee80211_setup_node(ic, nt, in, macaddr);
885 	return (in);
886 }
887 
888 /*
889  * Craft a temporary node suitable for sending a management frame
890  * to the specified station.  We craft only as much state as we
891  * need to do the work since the node will be immediately reclaimed
892  * once the send completes.
893  */
894 ieee80211_node_t *
ieee80211_tmp_node(ieee80211com_t * ic,const uint8_t * macaddr)895 ieee80211_tmp_node(ieee80211com_t *ic, const uint8_t *macaddr)
896 {
897 	ieee80211_node_t *in;
898 
899 	in = ic->ic_node_alloc(ic);
900 	if (in != NULL) {
901 		ieee80211_dbg(IEEE80211_MSG_NODE, "ieee80211_tmp_node: "
902 		    "%p<%s>\n", in, ieee80211_macaddr_sprintf(macaddr));
903 
904 		IEEE80211_ADDR_COPY(in->in_macaddr, macaddr);
905 		IEEE80211_ADDR_COPY(in->in_bssid, ic->ic_bss->in_bssid);
906 		ieee80211_node_initref(in);		/* mark referenced */
907 		in->in_txpower = ic->ic_bss->in_txpower;
908 		/* NB: required by ieee80211_fix_rate */
909 		ieee80211_node_setchan(ic, in, ic->ic_bss->in_chan);
910 		ieee80211_crypto_resetkey(ic, &in->in_ucastkey,
911 		    IEEE80211_KEYIX_NONE);
912 
913 		in->in_table = NULL;		/* NB: pedantic */
914 		in->in_ic = ic;
915 	}
916 
917 	return (in);
918 }
919 
920 /*
921  * ieee80211_dup_bss() is similar to ieee80211_alloc_node(),
922  * but is instead used to create a node database entry for
923  * the specified BSSID. If the allocation is successful, the
924  * node is initialized,  otherwise, NULL is returned.
925  */
926 ieee80211_node_t *
ieee80211_dup_bss(ieee80211_node_table_t * nt,const uint8_t * macaddr)927 ieee80211_dup_bss(ieee80211_node_table_t *nt, const uint8_t *macaddr)
928 {
929 	ieee80211com_t *ic = nt->nt_ic;
930 	ieee80211_node_t *in;
931 
932 	in = ieee80211_alloc_node(ic, nt, macaddr);
933 	if (in != NULL) {
934 		/*
935 		 * Inherit from ic_bss.
936 		 */
937 		ieee80211_copy_bss(in, ic->ic_bss);
938 		IEEE80211_ADDR_COPY(in->in_bssid, ic->ic_bss->in_bssid);
939 		ieee80211_node_setchan(ic, in, ic->ic_bss->in_chan);
940 	}
941 
942 	return (in);
943 }
944 
945 /*
946  * Iterate through the node table, searching for a node entry which
947  * matches macaddr. If the entry is found, its reference count is
948  * incremented, and a pointer to the node is returned; otherwise,
949  * NULL will be returned.
950  * The node table lock is acquired by the caller.
951  */
952 static ieee80211_node_t *
ieee80211_find_node_locked(ieee80211_node_table_t * nt,const uint8_t * macaddr)953 ieee80211_find_node_locked(ieee80211_node_table_t *nt, const uint8_t *macaddr)
954 {
955 	ieee80211_node_t *in;
956 	int hash;
957 
958 	ASSERT(IEEE80211_NODE_IS_LOCKED(nt));
959 
960 	hash = ieee80211_node_hash(macaddr);
961 	in = list_head(&nt->nt_hash[hash]);
962 	while (in != NULL) {
963 		if (IEEE80211_ADDR_EQ(in->in_macaddr, macaddr))
964 			return (ieee80211_ref_node(in)); /* mark referenced */
965 		in = list_next(&nt->nt_hash[hash], in);
966 	}
967 	return (NULL);
968 }
969 
970 /*
971  * Iterate through the node table, searching for a node entry
972  * which match specified mac address.
973  * Return NULL if no matching node found.
974  */
975 ieee80211_node_t *
ieee80211_find_node(ieee80211_node_table_t * nt,const uint8_t * macaddr)976 ieee80211_find_node(ieee80211_node_table_t *nt, const uint8_t *macaddr)
977 {
978 	ieee80211_node_t *in;
979 
980 	IEEE80211_NODE_LOCK(nt);
981 	in = ieee80211_find_node_locked(nt, macaddr);
982 	IEEE80211_NODE_UNLOCK(nt);
983 	return (in);
984 }
985 
986 /*
987  * Like find but search based on the ssid too.
988  */
989 ieee80211_node_t *
ieee80211_find_node_with_ssid(ieee80211_node_table_t * nt,const uint8_t * macaddr,uint32_t ssidlen,const uint8_t * ssid)990 ieee80211_find_node_with_ssid(ieee80211_node_table_t *nt,
991 	const uint8_t *macaddr, uint32_t ssidlen, const uint8_t *ssid)
992 {
993 	ieee80211_node_t *in;
994 	int hash;
995 
996 	IEEE80211_NODE_LOCK(nt);
997 
998 	hash = ieee80211_node_hash(macaddr);
999 	in = list_head(&nt->nt_hash[hash]);
1000 	while (in != NULL) {
1001 		if (IEEE80211_ADDR_EQ(in->in_macaddr, macaddr) &&
1002 		    in->in_esslen == ssidlen &&
1003 		    memcmp(in->in_essid, ssid, ssidlen) == 0)
1004 			break;
1005 		in = list_next(&nt->nt_hash[hash], in);
1006 	}
1007 	if (in != NULL) {
1008 		(void) ieee80211_ref_node(in); /* mark referenced */
1009 	}
1010 	IEEE80211_NODE_UNLOCK(nt);
1011 
1012 	return (in);
1013 }
1014 
1015 /*
1016  * Fake up a node; this handles node discovery in adhoc mode.
1017  * Note that for the driver's benefit we treat this like an
1018  * association so the driver has an opportunity to setup it's
1019  * private state.
1020  */
1021 ieee80211_node_t *
ieee80211_fakeup_adhoc_node(ieee80211_node_table_t * nt,const uint8_t * macaddr)1022 ieee80211_fakeup_adhoc_node(ieee80211_node_table_t *nt, const uint8_t *macaddr)
1023 {
1024 	ieee80211com_t *ic = nt->nt_ic;
1025 	ieee80211_node_t *in;
1026 
1027 	ieee80211_dbg(IEEE80211_MSG_NODE, "ieee80211_fakeup_adhoc_node: "
1028 	    "mac<%s>\n", ieee80211_macaddr_sprintf(macaddr));
1029 	in = ieee80211_dup_bss(nt, macaddr);
1030 	if (in != NULL) {
1031 		/* no rate negotiation; just dup */
1032 		in->in_rates = ic->ic_bss->in_rates;
1033 		if (ic->ic_node_newassoc != NULL)
1034 			ic->ic_node_newassoc(in, 1);
1035 		ieee80211_node_authorize(in);
1036 	}
1037 	return (in);
1038 }
1039 
1040 static void
ieee80211_saveie(uint8_t ** iep,const uint8_t * ie)1041 ieee80211_saveie(uint8_t **iep, const uint8_t *ie)
1042 {
1043 	uint_t ielen = ie[1]+2;
1044 	/*
1045 	 * Record information element for later use.
1046 	 */
1047 	if (*iep == NULL || (*iep)[1] != ie[1]) {
1048 		if (*iep != NULL)
1049 			ieee80211_free(*iep);
1050 		*iep = ieee80211_malloc(ielen);
1051 	}
1052 	if (*iep != NULL)
1053 		(void) memcpy(*iep, ie, ielen);
1054 }
1055 
1056 static void
saveie(uint8_t ** iep,const uint8_t * ie)1057 saveie(uint8_t **iep, const uint8_t *ie)
1058 {
1059 	if (ie == NULL) {
1060 		if (*iep != NULL)
1061 			ieee80211_free(*iep);
1062 		*iep = NULL;
1063 	}
1064 	else
1065 		ieee80211_saveie(iep, ie);
1066 }
1067 
1068 /*
1069  * Process a beacon or probe response frame.
1070  */
1071 void
ieee80211_add_scan(ieee80211com_t * ic,const struct ieee80211_scanparams * sp,const struct ieee80211_frame * wh,int subtype,int rssi,int rstamp)1072 ieee80211_add_scan(ieee80211com_t *ic, const struct ieee80211_scanparams *sp,
1073     const struct ieee80211_frame *wh, int subtype, int rssi, int rstamp)
1074 {
1075 	ieee80211_node_table_t *nt = &ic->ic_scan;
1076 	ieee80211_node_t *in;
1077 	boolean_t newnode = B_FALSE;
1078 
1079 	in = ieee80211_find_node(nt, wh->i_addr3);
1080 	if (in == NULL) {
1081 		/*
1082 		 * Create a new entry.
1083 		 */
1084 		in = ieee80211_alloc_node(ic, nt, wh->i_addr3);
1085 		if (in == NULL) {
1086 			ieee80211_dbg(IEEE80211_MSG_ANY, "ieee80211_add_scan: "
1087 			    "alloc node failed\n");
1088 			return;
1089 		}
1090 		/*
1091 		 * inherit from ic_bss.
1092 		 */
1093 		ieee80211_copy_bss(in, ic->ic_bss);
1094 		ieee80211_node_setchan(ic, in, ic->ic_curchan);
1095 		newnode = B_TRUE;
1096 	}
1097 
1098 	/* ap beaconing multiple ssid w/ same bssid */
1099 
1100 	/*
1101 	 * sp->ssid[0] - element ID
1102 	 * sp->ssid[1] - length
1103 	 * sp->ssid[2]... - ssid
1104 	 */
1105 	if (sp->ssid[1] != 0 &&
1106 	    subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP ||
1107 	    in->in_esslen == 0) {
1108 		in->in_esslen = sp->ssid[1];
1109 		bzero(in->in_essid, sizeof (in->in_essid));
1110 		bcopy(sp->ssid + 2, in->in_essid, sp->ssid[1]);
1111 	}
1112 	IEEE80211_ADDR_COPY(in->in_bssid, wh->i_addr3);
1113 	in->in_rssi = (uint8_t)rssi;
1114 	in->in_rstamp = rstamp;
1115 	bcopy(sp->tstamp, in->in_tstamp.data, sizeof (in->in_tstamp));
1116 	in->in_intval = sp->bintval;
1117 	in->in_capinfo = sp->capinfo;
1118 	in->in_chan = &ic->ic_sup_channels[sp->chan];
1119 	in->in_phytype = sp->phytype;
1120 	in->in_fhdwell = sp->fhdwell;
1121 	in->in_fhindex = sp->fhindex;
1122 	in->in_erp = sp->erp;
1123 	if (sp->tim != NULL) {
1124 		struct ieee80211_tim_ie *ie;
1125 
1126 		ie = (struct ieee80211_tim_ie *)sp->tim;
1127 		in->in_dtim_count = ie->tim_count;
1128 		in->in_dtim_period = ie->tim_period;
1129 	}
1130 	/*
1131 	 * Record the byte offset from the mac header to
1132 	 * the start of the TIM information element for
1133 	 * use by hardware and/or to speedup software
1134 	 * processing of beacon frames.
1135 	 */
1136 	in->in_tim_off = sp->timoff;
1137 	/*
1138 	 * Record optional information elements that might be
1139 	 * used by applications or drivers.
1140 	 */
1141 	saveie(&in->in_wme_ie, sp->wme);
1142 	saveie(&in->in_wpa_ie, sp->wpa);
1143 	saveie(&in->in_htcap_ie, sp->htcap);
1144 	/* parsed in ieee80211_sta_join() */
1145 	if (sp->htcap != NULL)
1146 		ieee80211_parse_htcap(in, in->in_htcap_ie);
1147 
1148 	/* NB: must be after in_chan is setup */
1149 	(void) ieee80211_setup_rates(in, sp->rates, sp->xrates,
1150 	    IEEE80211_F_DOSORT);
1151 
1152 	if (!newnode)
1153 		ieee80211_free_node(in);
1154 }
1155 
1156 /*
1157  * Initialize/update an ad-hoc node with contents from a received
1158  * beacon frame.
1159  */
1160 void
ieee80211_init_neighbor(ieee80211_node_t * in,const struct ieee80211_frame * wh,const struct ieee80211_scanparams * sp)1161 ieee80211_init_neighbor(ieee80211_node_t *in, const struct ieee80211_frame *wh,
1162     const struct ieee80211_scanparams *sp)
1163 {
1164 	in->in_esslen = sp->ssid[1];
1165 	(void) memcpy(in->in_essid, sp->ssid + 2, sp->ssid[1]);
1166 	IEEE80211_ADDR_COPY(in->in_bssid, wh->i_addr3);
1167 	(void) memcpy(in->in_tstamp.data, sp->tstamp, sizeof (in->in_tstamp));
1168 	in->in_intval = sp->bintval;
1169 	in->in_capinfo = sp->capinfo;
1170 	in->in_chan = in->in_ic->ic_curchan;
1171 	in->in_fhdwell = sp->fhdwell;
1172 	in->in_fhindex = sp->fhindex;
1173 	in->in_erp = sp->erp;
1174 	in->in_tim_off = sp->timoff;
1175 	if (sp->wme != NULL)
1176 		ieee80211_saveie(&in->in_wme_ie, sp->wme);
1177 
1178 	/* NB: must be after in_chan is setup */
1179 	(void) ieee80211_setup_rates(in, sp->rates, sp->xrates,
1180 	    IEEE80211_F_DOSORT);
1181 }
1182 
1183 /*
1184  * Do node discovery in adhoc mode on receipt of a beacon
1185  * or probe response frame.  Note that for the driver's
1186  * benefit we we treat this like an association so the
1187  * driver has an opportuinty to setup it's private state.
1188  */
1189 ieee80211_node_t *
ieee80211_add_neighbor(ieee80211com_t * ic,const struct ieee80211_frame * wh,const struct ieee80211_scanparams * sp)1190 ieee80211_add_neighbor(ieee80211com_t *ic, const struct ieee80211_frame *wh,
1191     const struct ieee80211_scanparams *sp)
1192 {
1193 	ieee80211_node_t *in;
1194 
1195 	in = ieee80211_dup_bss(&ic->ic_sta, wh->i_addr2);
1196 	if (in != NULL) {
1197 		ieee80211_init_neighbor(in, wh, sp);
1198 		if (ic->ic_node_newassoc != NULL)
1199 			ic->ic_node_newassoc(in, 1);
1200 	}
1201 	return (in);
1202 }
1203 
1204 #define	IEEE80211_IS_CTL(wh)	\
1205 	((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)
1206 
1207 #define	IEEE80211_IS_PSPOLL(wh)	\
1208 	((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==	\
1209 	    IEEE80211_FC0_SUBTYPE_PS_POLL)
1210 
1211 #define	IEEE80211_IS_BAR(wh)	\
1212 	((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==	\
1213 	    IEEE80211_FC0_SUBTYPE_BAR)
1214 
1215 /*
1216  * Locate the node for sender, track state, and then pass the
1217  * (referenced) node up to the 802.11 layer for its use.  We
1218  * are required to pass some node so we fall back to ic_bss
1219  * when this frame is from an unknown sender.  The 802.11 layer
1220  * knows this means the sender wasn't in the node table and
1221  * acts accordingly.
1222  */
1223 ieee80211_node_t *
ieee80211_find_rxnode(ieee80211com_t * ic,const struct ieee80211_frame * wh)1224 ieee80211_find_rxnode(ieee80211com_t *ic, const struct ieee80211_frame *wh)
1225 {
1226 	ieee80211_node_table_t *nt;
1227 	ieee80211_node_t *in;
1228 
1229 	/* may want scanned nodes in the neighbor table for adhoc */
1230 	if (ic->ic_opmode == IEEE80211_M_STA ||
1231 	    (ic->ic_flags & IEEE80211_F_SCAN)) {
1232 		nt = &ic->ic_scan;
1233 	} else {
1234 		nt = &ic->ic_sta;
1235 	}
1236 
1237 	IEEE80211_NODE_LOCK(nt);
1238 	if (IEEE80211_IS_CTL(wh) &&
1239 	    !IEEE80211_IS_PSPOLL(wh) && !IEEE80211_IS_BAR(wh))
1240 		in = ieee80211_find_node_locked(nt, wh->i_addr1);
1241 	else
1242 		in = ieee80211_find_node_locked(nt, wh->i_addr2);
1243 	IEEE80211_NODE_UNLOCK(nt);
1244 
1245 	if (in == NULL)
1246 		in = ieee80211_ref_node(ic->ic_bss);
1247 
1248 	return (in);
1249 }
1250 
1251 #undef IEEE80211_IS_BAR
1252 #undef IEEE80211_IS_PSPOLL
1253 #undef IEEE80211_IS_CTL
1254 
1255 /*
1256  * Return a reference to the appropriate node for sending
1257  * a data frame.  This handles node discovery in adhoc networks.
1258  */
1259 ieee80211_node_t *
ieee80211_find_txnode(ieee80211com_t * ic,const uint8_t * daddr)1260 ieee80211_find_txnode(ieee80211com_t *ic, const uint8_t *daddr)
1261 {
1262 	ieee80211_node_table_t *nt = &ic->ic_sta;
1263 	ieee80211_node_t *in;
1264 
1265 	/*
1266 	 * The destination address should be in the node table
1267 	 * unless this is a multicast/broadcast frame.  We can
1268 	 * also optimize station mode operation, all frames go
1269 	 * to the bss node.
1270 	 */
1271 	IEEE80211_NODE_LOCK(nt);
1272 	if (ic->ic_opmode == IEEE80211_M_STA || IEEE80211_IS_MULTICAST(daddr))
1273 		in = ieee80211_ref_node(ic->ic_bss);
1274 	else
1275 		in = ieee80211_find_node_locked(nt, daddr);
1276 	IEEE80211_NODE_UNLOCK(nt);
1277 
1278 	if (in == NULL) {
1279 		if (ic->ic_opmode == IEEE80211_M_IBSS) {
1280 			/*
1281 			 * In adhoc mode cons up a node for the destination.
1282 			 * Note that we need an additional reference for the
1283 			 * caller to be consistent with
1284 			 * ieee80211_find_node_locked
1285 			 * can't hold lock across ieee80211_dup_bss 'cuz of
1286 			 * recursive locking
1287 			 */
1288 			in = ieee80211_fakeup_adhoc_node(nt, daddr);
1289 			if (in != NULL)
1290 				(void) ieee80211_ref_node(in);
1291 		} else {
1292 			ieee80211_dbg(IEEE80211_MSG_OUTPUT,
1293 			    "ieee80211_find_txnode: "
1294 			    "[%s] no node, discard frame\n",
1295 			    ieee80211_macaddr_sprintf(daddr));
1296 		}
1297 	}
1298 	return (in);
1299 }
1300 
1301 /*
1302  * Remove a node from the node database entries and free memory
1303  * associated with the node. The node table lock is acquired by
1304  * the caller.
1305  */
1306 static void
ieee80211_free_node_locked(ieee80211_node_t * in)1307 ieee80211_free_node_locked(ieee80211_node_t *in)
1308 {
1309 	ieee80211com_t *ic = in->in_ic;
1310 	ieee80211_node_table_t *nt = in->in_table;
1311 	int32_t hash;
1312 
1313 	if (nt != NULL) {
1314 		hash = ieee80211_node_hash(in->in_macaddr);
1315 		list_remove(&nt->nt_hash[hash], in);
1316 		list_remove(&nt->nt_node, in);
1317 	}
1318 	ic->ic_node_free(in);
1319 }
1320 
1321 /*
1322  * Remove a node from the node database entries and free any
1323  * memory associated with the node.
1324  * This method can be overridden in ieee80211_attach()
1325  */
1326 void
ieee80211_free_node(ieee80211_node_t * in)1327 ieee80211_free_node(ieee80211_node_t *in)
1328 {
1329 	ieee80211_node_table_t *nt = in->in_table;
1330 
1331 	if (nt != NULL)
1332 		IEEE80211_NODE_LOCK(nt);
1333 	if (ieee80211_node_decref_nv(in) == 0)
1334 		ieee80211_free_node_locked(in);
1335 	if (nt != NULL)
1336 		IEEE80211_NODE_UNLOCK(nt);
1337 }
1338 
1339 /*
1340  * Reclaim a node.  If this is the last reference count then
1341  * do the normal free work.  Otherwise remove it from the node
1342  * table and mark it gone by clearing the back-reference.
1343  */
1344 static void
ieee80211_node_reclaim(ieee80211_node_table_t * nt,ieee80211_node_t * in)1345 ieee80211_node_reclaim(ieee80211_node_table_t *nt, ieee80211_node_t *in)
1346 {
1347 	int32_t hash;
1348 
1349 	IEEE80211_NODE_LOCK_ASSERT(nt);
1350 	ieee80211_dbg(IEEE80211_MSG_NODE, "node_reclaim: "
1351 	    " remove %p<%s> from %s table, refcnt %d\n",
1352 	    in, ieee80211_macaddr_sprintf(in->in_macaddr), nt->nt_name,
1353 	    ieee80211_node_refcnt(in));
1354 
1355 	if (ieee80211_node_decref_nv(in) != 0) {
1356 		/*
1357 		 * Clear any entry in the unicast key mapping table.
1358 		 * We need to do it here so rx lookups don't find it
1359 		 * in the mapping table even if it's not in the hash
1360 		 * table.  We cannot depend on the mapping table entry
1361 		 * being cleared because the node may not be free'd.
1362 		 */
1363 		hash = ieee80211_node_hash(in->in_macaddr);
1364 		list_remove(&nt->nt_hash[hash], in);
1365 		list_remove(&nt->nt_node, in);
1366 		in->in_table = NULL;
1367 	} else {
1368 		ieee80211_free_node_locked(in);
1369 	}
1370 }
1371 
1372 /*
1373  * Iterate through the node list and reclaim all node in the node table.
1374  * The node table lock is acquired by the caller
1375  */
1376 static void
ieee80211_free_allnodes_locked(ieee80211_node_table_t * nt)1377 ieee80211_free_allnodes_locked(ieee80211_node_table_t *nt)
1378 {
1379 	ieee80211_node_t *in;
1380 
1381 	ieee80211_dbg(IEEE80211_MSG_NODE, "ieee80211_free_allnodes_locked(): "
1382 	    "free all nodes in %s table\n", nt->nt_name);
1383 
1384 	in = list_head(&nt->nt_node);
1385 	while (in != NULL) {
1386 		ieee80211_node_reclaim(nt, in);
1387 		in = list_head(&nt->nt_node);
1388 	}
1389 	ieee80211_reset_erp(nt->nt_ic);
1390 }
1391 
1392 /*
1393  * Iterate through the node list, calling ieee80211_node_reclaim() for
1394  * all nodes associated with the interface.
1395  */
1396 static void
ieee80211_free_allnodes(ieee80211_node_table_t * nt)1397 ieee80211_free_allnodes(ieee80211_node_table_t *nt)
1398 {
1399 	IEEE80211_NODE_LOCK(nt);
1400 	ieee80211_free_allnodes_locked(nt);
1401 	IEEE80211_NODE_UNLOCK(nt);
1402 }
1403 
1404 /*
1405  * Timeout entries in the scan cache. This is the timeout callback
1406  * function of node table ic_scan which is called when the inactivity
1407  * timer expires.
1408  */
1409 static void
ieee80211_timeout_scan_candidates(ieee80211_node_table_t * nt)1410 ieee80211_timeout_scan_candidates(ieee80211_node_table_t *nt)
1411 {
1412 	ieee80211com_t *ic = nt->nt_ic;
1413 	ieee80211_node_t *in;
1414 
1415 	IEEE80211_NODE_LOCK(nt);
1416 	in = ic->ic_bss;
1417 	node_cleanfrag(in);	/* Free fragment if not needed */
1418 	nt->nt_inact_timer = IEEE80211_INACT_WAIT;
1419 	IEEE80211_NODE_UNLOCK(nt);
1420 }
1421 
1422 /*
1423  * Timeout inactive stations and do related housekeeping.
1424  * Note that we cannot hold the node lock while sending a
1425  * frame as this would lead to a LOR.  Instead we use a
1426  * generation number to mark nodes that we've scanned and
1427  * drop the lock and restart a scan if we have to time out
1428  * a node.  Since we are single-threaded by virtue of
1429  * controlling the inactivity timer we can be sure this will
1430  * process each node only once.
1431  */
1432 static void
ieee80211_timeout_stations(ieee80211_node_table_t * nt)1433 ieee80211_timeout_stations(ieee80211_node_table_t *nt)
1434 {
1435 	ieee80211com_t *ic = nt->nt_ic;
1436 	ieee80211_impl_t *im = ic->ic_private;
1437 	ieee80211_node_t *in = NULL;
1438 	uint32_t gen;
1439 	boolean_t isadhoc;
1440 
1441 	IEEE80211_LOCK_ASSERT(ic);
1442 	isadhoc = (ic->ic_opmode == IEEE80211_M_IBSS ||
1443 	    ic->ic_opmode == IEEE80211_M_AHDEMO);
1444 	IEEE80211_SCAN_LOCK(nt);
1445 	gen = ++nt->nt_scangen;
1446 restart:
1447 	IEEE80211_NODE_LOCK(nt);
1448 	for (in = list_head(&nt->nt_node); in != NULL;
1449 	    in = list_next(&nt->nt_node, in)) {
1450 		if (in->in_scangen == gen)	/* previously handled */
1451 			continue;
1452 		in->in_scangen = gen;
1453 		node_cleanfrag(in);	/* free fragment if not needed */
1454 
1455 		/*
1456 		 * Special case ourself; we may be idle for extended periods
1457 		 * of time and regardless reclaiming our state is wrong.
1458 		 */
1459 		if (in == ic->ic_bss)
1460 			continue;
1461 		in->in_inact--;
1462 		if (in->in_associd != 0 || isadhoc) {
1463 			/*
1464 			 * Probe the station before time it out.  We
1465 			 * send a null data frame which may not be
1466 			 * uinversally supported by drivers (need it
1467 			 * for ps-poll support so it should be...).
1468 			 */
1469 			if (0 < in->in_inact &&
1470 			    in->in_inact <= im->im_inact_probe) {
1471 				ieee80211_dbg(IEEE80211_MSG_NODE, "net80211: "
1472 				    "probe station due to inactivity\n");
1473 				IEEE80211_NODE_UNLOCK(nt);
1474 				IEEE80211_UNLOCK(ic);
1475 				(void) ieee80211_send_nulldata(in);
1476 				IEEE80211_LOCK(ic);
1477 				goto restart;
1478 			}
1479 		}
1480 		if (in->in_inact <= 0) {
1481 			ieee80211_dbg(IEEE80211_MSG_NODE, "net80211: "
1482 			    "station timed out due to inact (refcnt %u)\n",
1483 			    ieee80211_node_refcnt(in));
1484 			/*
1485 			 * Send a deauthenticate frame and drop the station.
1486 			 * This is somewhat complicated due to reference counts
1487 			 * and locking.  At this point a station will typically
1488 			 * have a reference count of 1.  ieee80211_node_leave
1489 			 * will do a "free" of the node which will drop the
1490 			 * reference count.  But in the meantime a reference
1491 			 * wil be held by the deauth frame.  The actual reclaim
1492 			 * of the node will happen either after the tx is
1493 			 * completed or by ieee80211_node_leave.
1494 			 *
1495 			 * Separately we must drop the node lock before sending
1496 			 * in case the driver takes a lock, as this will result
1497 			 * in  LOR between the node lock and the driver lock.
1498 			 */
1499 			IEEE80211_NODE_UNLOCK(nt);
1500 			if (in->in_associd != 0) {
1501 				IEEE80211_UNLOCK(ic);
1502 				IEEE80211_SEND_MGMT(ic, in,
1503 				    IEEE80211_FC0_SUBTYPE_DEAUTH,
1504 				    IEEE80211_REASON_AUTH_EXPIRE);
1505 				IEEE80211_LOCK(ic);
1506 			}
1507 			ieee80211_node_leave(ic, in);
1508 			goto restart;
1509 		}
1510 	}
1511 	IEEE80211_NODE_UNLOCK(nt);
1512 
1513 	IEEE80211_SCAN_UNLOCK(nt);
1514 
1515 	nt->nt_inact_timer = IEEE80211_INACT_WAIT;
1516 }
1517 
1518 /*
1519  * Call the user-defined call back function for all nodes in
1520  * the node cache. The callback is invoked with the user-supplied
1521  * value and a pointer to the current node.
1522  */
1523 void
ieee80211_iterate_nodes(ieee80211_node_table_t * nt,ieee80211_iter_func * f,void * arg)1524 ieee80211_iterate_nodes(ieee80211_node_table_t *nt, ieee80211_iter_func *f,
1525     void *arg)
1526 {
1527 	ieee80211_node_t *in;
1528 
1529 	IEEE80211_NODE_LOCK(nt);
1530 	in = list_head(&nt->nt_node);
1531 	while (in != NULL) {
1532 		if (in->in_chan == IEEE80211_CHAN_ANYC) {
1533 			in = list_next(&nt->nt_node, in);
1534 			continue;
1535 		}
1536 		(void) ieee80211_ref_node(in);
1537 		IEEE80211_NODE_UNLOCK(nt);
1538 		(*f)(arg, in);
1539 		ieee80211_free_node(in);
1540 		IEEE80211_NODE_LOCK(nt);
1541 		in = list_next(&nt->nt_node, in);
1542 	}
1543 	IEEE80211_NODE_UNLOCK(nt);
1544 }
1545 
1546 /*
1547  * Handle bookkeeping for station deauthentication/disassociation
1548  * when operating as an ap.
1549  */
1550 static void
ieee80211_node_leave(ieee80211com_t * ic,ieee80211_node_t * in)1551 ieee80211_node_leave(ieee80211com_t *ic, ieee80211_node_t *in)
1552 {
1553 	ieee80211_node_table_t *nt = in->in_table;
1554 
1555 	ASSERT(ic->ic_opmode == IEEE80211_M_IBSS);
1556 
1557 	/*
1558 	 * Remove the node from any table it's recorded in and
1559 	 * drop the caller's reference.  Removal from the table
1560 	 * is important to insure the node is not reprocessed
1561 	 * for inactivity.
1562 	 */
1563 	if (nt != NULL) {
1564 		IEEE80211_NODE_LOCK(nt);
1565 		ieee80211_node_reclaim(nt, in);
1566 		IEEE80211_NODE_UNLOCK(nt);
1567 	} else {
1568 		ieee80211_free_node(in);
1569 	}
1570 }
1571 
1572 /*
1573  * Initialize a node table with specified name, inactivity timer value
1574  * and callback inactivity timeout function. Associate the node table
1575  * with interface softc, ic.
1576  */
1577 static void
ieee80211_node_table_init(ieee80211com_t * ic,ieee80211_node_table_t * nt,const char * name,int inact,int keyixmax,void (* timeout)(ieee80211_node_table_t *))1578 ieee80211_node_table_init(ieee80211com_t *ic, ieee80211_node_table_t *nt,
1579     const char *name, int inact, int keyixmax,
1580     void (*timeout)(ieee80211_node_table_t *))
1581 {
1582 	int i;
1583 
1584 	ieee80211_dbg(IEEE80211_MSG_NODE, "ieee80211_node_table_init():"
1585 	    "%s table, inact %d\n", name, inact);
1586 
1587 	nt->nt_ic = ic;
1588 	nt->nt_name = name;
1589 	nt->nt_inact_timer = 0;
1590 	nt->nt_inact_init = inact;
1591 	nt->nt_timeout = timeout;
1592 	nt->nt_keyixmax = keyixmax;
1593 	nt->nt_scangen = 1;
1594 	mutex_init(&nt->nt_scanlock, NULL, MUTEX_DRIVER, NULL);
1595 	mutex_init(&nt->nt_nodelock, NULL, MUTEX_DRIVER, NULL);
1596 
1597 	list_create(&nt->nt_node, sizeof (ieee80211_node_t),
1598 	    offsetof(ieee80211_node_t, in_node));
1599 	for (i = 0; i < IEEE80211_NODE_HASHSIZE; i++) {
1600 		list_create(&nt->nt_hash[i], sizeof (ieee80211_node_t),
1601 		    offsetof(ieee80211_node_t, in_hash));
1602 	}
1603 }
1604 
1605 /*
1606  * Reset a node table. Clean its inactivity timer and call
1607  * ieee80211_free_allnodes_locked() to free all nodes in the
1608  * node table.
1609  */
1610 void
ieee80211_node_table_reset(ieee80211_node_table_t * nt)1611 ieee80211_node_table_reset(ieee80211_node_table_t *nt)
1612 {
1613 	ieee80211_dbg(IEEE80211_MSG_NODE, "ieee80211_node_table_reset(): "
1614 	    "%s table\n", nt->nt_name);
1615 
1616 	IEEE80211_NODE_LOCK(nt);
1617 	nt->nt_inact_timer = 0;
1618 	ieee80211_free_allnodes_locked(nt);
1619 	IEEE80211_NODE_UNLOCK(nt);
1620 }
1621 
1622 /*
1623  * Destroy a node table. Free all nodes in the node table.
1624  * This function is usually called by node detach function.
1625  */
1626 static void
ieee80211_node_table_cleanup(ieee80211_node_table_t * nt)1627 ieee80211_node_table_cleanup(ieee80211_node_table_t *nt)
1628 {
1629 	ieee80211_dbg(IEEE80211_MSG_NODE, "ieee80211_node_table_cleanup(): "
1630 	    "%s table\n", nt->nt_name);
1631 
1632 	IEEE80211_NODE_LOCK(nt);
1633 	ieee80211_free_allnodes_locked(nt);
1634 	IEEE80211_NODE_UNLOCK(nt);
1635 	mutex_destroy(&nt->nt_nodelock);
1636 	mutex_destroy(&nt->nt_scanlock);
1637 }
1638