2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
7 * Copyright (c) 2001 Atsushi Onoe
8 * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
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.
39 * Node management routines
42 #include "net80211_impl.h"
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
*,
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
*);
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
68 #define IEEE80211_STA_FAILS_MAX 2
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
78 ieee80211_node_attach(ieee80211com_t
*ic
)
80 struct ieee80211_impl
*im
= ic
->ic_private
;
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
;
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
;
95 * Initialize node databases and the ic_bss node element.
98 ieee80211_node_lateattach(ieee80211com_t
*ic
)
101 * Calculate ic_tim_bitmap size in bytes
102 * IEEE80211_AID_MAX defines maximum bits in ic_tim_bitmap
104 ic
->ic_tim_len
= howmany(IEEE80211_AID_MAX
, 8) * sizeof (uint8_t);
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
);
112 ieee80211_reset_bss(ic
);
116 * Destroy all node databases and is usually called during device detach
119 ieee80211_node_detach(ieee80211com_t
*ic
)
122 if (ic
->ic_bss
!= NULL
) {
123 ieee80211_free_node(ic
->ic_bss
);
126 ieee80211_node_table_cleanup(&ic
->ic_scan
);
127 ieee80211_node_table_cleanup(&ic
->ic_sta
);
131 * Increase a node's reference count
133 * Return pointer to the node
136 ieee80211_ref_node(ieee80211_node_t
*in
)
138 ieee80211_node_incref(in
);
143 * Dexrease a node's reference count
146 ieee80211_unref_node(ieee80211_node_t
**in
)
148 ieee80211_node_decref(*in
);
149 *in
= NULL
; /* guard against use */
153 * Mark ports authorized for data traffic. This function is usually
154 * used by 802.1x authenticator.
157 ieee80211_node_authorize(ieee80211_node_t
*in
)
159 ieee80211_impl_t
*im
= in
->in_ic
->ic_private
;
161 in
->in_flags
|= IEEE80211_NODE_AUTH
;
162 in
->in_inact_reload
= im
->im_inact_run
;
163 in
->in_inact
= in
->in_inact_reload
;
167 * Mark ports unauthorized for data traffic. This function is usually
168 * used by 802.1x authenticator.
171 ieee80211_node_unauthorize(ieee80211_node_t
*in
)
173 in
->in_flags
&= ~IEEE80211_NODE_AUTH
;
177 * Set/change the channel. The rate set is also updated as
178 * to insure a consistent view by drivers.
181 ieee80211_node_setchan(ieee80211com_t
*ic
, ieee80211_node_t
*in
,
182 struct ieee80211_channel
*chan
)
184 if (chan
== IEEE80211_CHAN_ANYC
)
185 chan
= ic
->ic_curchan
;
187 if (IEEE80211_IS_CHAN_HT(chan
)) {
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.
195 in
->in_htrates
= *ieee80211_get_suphtrates(ic
, chan
);
197 in
->in_rates
= *ieee80211_get_suprates(ic
, chan
);
198 /* in->in_rates = ic->ic_sup_rates[ieee80211_chan2mode(ic, chan)]; */
202 * Initialize the channel set to scan based on the available channels
203 * and the current PHY mode.
206 ieee80211_reset_scan(ieee80211com_t
*ic
)
208 ieee80211_impl_t
*im
= ic
->ic_private
;
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
));
215 bcopy(ic
->ic_chan_active
, im
->im_chan_scan
,
216 sizeof (ic
->ic_chan_active
));
218 ieee80211_dbg(IEEE80211_MSG_SCAN
, "ieee80211_reset_scan(): "
219 "start chan %u\n", ieee80211_chan2ieee(ic
, ic
->ic_curchan
));
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
230 ieee80211_begin_scan(ieee80211com_t
*ic
, boolean_t reset
)
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
));
243 * Clear scan state and flush any previously seen AP's.
245 ieee80211_reset_scan(ic
);
247 ieee80211_free_allnodes(&ic
->ic_scan
);
249 ic
->ic_flags
|= IEEE80211_F_SCAN
;
250 IEEE80211_UNLOCK(ic
);
252 /* Scan the next channel. */
253 ieee80211_next_scan(ic
);
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.
265 ieee80211_next_scan(ieee80211com_t
*ic
)
267 ieee80211_impl_t
*im
= ic
->ic_private
;
268 struct ieee80211_channel
*chan
;
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.
276 im
->im_mgt_timer
= 0;
278 chan
= ic
->ic_curchan
;
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
;
292 * drivers should do this as needed,
293 * for now maintain compatibility
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);
301 } while (chan
!= ic
->ic_curchan
);
302 IEEE80211_UNLOCK(ic
);
303 ieee80211_end_scan(ic
);
307 * Copy useful state from node obss into nbss.
310 ieee80211_copy_bss(ieee80211_node_t
*nbss
, const ieee80211_node_t
*obss
)
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
;
319 * Setup the net80211 specific portion of an interface's softc, ic,
320 * for use in IBSS mode
323 ieee80211_create_ibss(ieee80211com_t
*ic
, struct ieee80211_channel
*chan
)
325 ieee80211_impl_t
*im
= ic
->ic_private
;
326 ieee80211_node_table_t
*nt
;
327 ieee80211_node_t
*in
;
329 IEEE80211_LOCK_ASSERT(ic
);
330 ieee80211_dbg(IEEE80211_MSG_SCAN
, "ieee80211_create_ibss: "
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.
340 IEEE80211_NODE_LOCK(nt
);
341 nt
->nt_name
= "neighbor";
342 nt
->nt_inact_init
= im
->im_inact_run
;
343 IEEE80211_NODE_UNLOCK(nt
);
345 in
= ieee80211_alloc_node(ic
, &ic
->ic_sta
, ic
->ic_macaddr
);
347 ieee80211_err("ieee80211_create_ibss(): alloc node failed\n");
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;
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
);
368 in
->in_bssid
[0] |= 0x02; /* local bit for IBSS */
370 case IEEE80211_M_AHDEMO
:
371 if (ic
->ic_flags
& IEEE80211_F_DESBSSID
)
372 IEEE80211_ADDR_COPY(in
->in_bssid
, ic
->ic_des_bssid
);
374 (void) memset(in
->in_bssid
, 0, IEEE80211_ADDR_LEN
);
377 ieee80211_err("ieee80211_create_ibss(): "
378 "wrong opmode %u to creat IBSS, abort\n",
380 ieee80211_free_node(in
);
385 * Fix the channel and related attributes.
387 ieee80211_node_setchan(ic
, in
, chan
);
388 ic
->ic_curchan
= chan
;
389 ic
->ic_curmode
= ieee80211_chan2mode(ic
, chan
);
391 * Do mode-specific rate setup.
393 ieee80211_setbasicrates(&in
->in_rates
, ic
->ic_curmode
);
394 IEEE80211_UNLOCK(ic
);
395 ieee80211_sta_join(ic
, ieee80211_ref_node(in
));
400 ieee80211_reset_bss(ieee80211com_t
*ic
)
402 ieee80211_node_t
*in
;
403 ieee80211_node_t
*obss
;
405 ieee80211_node_table_reset(&ic
->ic_sta
);
406 ieee80211_reset_erp(ic
);
408 in
= ieee80211_alloc_node(ic
, &ic
->ic_scan
, ic
->ic_macaddr
);
411 ic
->ic_bss
= ieee80211_ref_node(in
);
413 ieee80211_copy_bss(in
, obss
);
414 in
->in_intval
= ic
->ic_bintval
;
415 ieee80211_free_node(obss
);
420 ieee80211_match_bss(ieee80211com_t
*ic
, ieee80211_node_t
*in
)
426 if (ieee80211_isclr(ic
->ic_chan_active
,
427 ieee80211_chan2ieee(ic
, in
->in_chan
))) {
428 fail
|= IEEE80211_BADCHAN
;
430 if (ic
->ic_des_chan
!= IEEE80211_CHAN_ANYC
&&
431 in
->in_chan
!= ic
->ic_des_chan
) {
432 fail
|= IEEE80211_BADCHAN
;
434 if (ic
->ic_opmode
== IEEE80211_M_IBSS
) {
435 if (!(in
->in_capinfo
& IEEE80211_CAPINFO_IBSS
))
436 fail
|= IEEE80211_BADOPMODE
;
438 if (!(in
->in_capinfo
& IEEE80211_CAPINFO_ESS
))
439 fail
|= IEEE80211_BADOPMODE
;
441 if (ic
->ic_flags
& IEEE80211_F_PRIVACY
) {
442 if (!(in
->in_capinfo
& IEEE80211_CAPINFO_PRIVACY
))
443 fail
|= IEEE80211_BADPRIVACY
;
445 if (in
->in_capinfo
& IEEE80211_CAPINFO_PRIVACY
)
446 fail
|= IEEE80211_BADPRIVACY
;
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
;
457 if ((ic
->ic_flags
& IEEE80211_F_DESBSSID
) &&
458 !IEEE80211_ADDR_EQ(ic
->ic_des_bssid
, in
->in_bssid
)) {
459 fail
|= IEEE80211_BADBSSID
;
461 if (in
->in_fails
>= IEEE80211_STA_FAILS_MAX
)
462 fail
|= IEEE80211_NODEFAIL
;
467 #define IEEE80211_MAXRATE(_rs) \
468 ((_rs).ir_rates[(_rs).ir_nrates - 1] & IEEE80211_RATE_VAL)
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.
477 * Return desired node
479 static ieee80211_node_t
*
480 ieee80211_node_compare(ieee80211com_t
*ic
, ieee80211_node_t
*a
,
488 /* privacy support preferred */
489 if ((a
->in_capinfo
& IEEE80211_CAPINFO_PRIVACY
) &&
490 !(b
->in_capinfo
& IEEE80211_CAPINFO_PRIVACY
)) {
493 if (!(a
->in_capinfo
& IEEE80211_CAPINFO_PRIVACY
) &&
494 (b
->in_capinfo
& IEEE80211_CAPINFO_PRIVACY
)) {
498 /* compare count of previous failures */
499 if (b
->in_fails
!= a
->in_fails
)
500 return ((a
->in_fails
> b
->in_fails
) ? b
: a
);
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
);
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
)) {
515 if (!IEEE80211_IS_CHAN_5GHZ(a
->in_chan
) &&
516 IEEE80211_IS_CHAN_5GHZ(b
->in_chan
)) {
520 /* all things being equal, compare signal level */
521 return ((rssib
> rssia
) ? b
: a
);
525 * Mark an ongoing scan stopped.
528 ieee80211_cancel_scan(ieee80211com_t
*ic
)
531 ieee80211_dbg(IEEE80211_MSG_SCAN
, "ieee80211_cancel_scan()"
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
);
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.
549 ieee80211_end_scan(ieee80211com_t
*ic
)
551 ieee80211_node_table_t
*nt
= &ic
->ic_scan
;
552 ieee80211_node_t
*in
;
553 ieee80211_node_t
*selbs
;
555 ieee80211_cancel_scan(ic
);
556 /* notify SCAN done */
557 ieee80211_notify(ic
, EVENT_SCAN_RESULTS
);
561 * Automatic sequencing; look for a candidate and
562 * if found join the network.
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");
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
);
579 * Reset the list of channels to scan and start again.
581 ieee80211_reset_scan(ic
);
582 ic
->ic_flags
|= IEEE80211_F_SCAN
| IEEE80211_F_ASCAN
;
583 IEEE80211_UNLOCK(ic
);
585 ieee80211_next_scan(ic
);
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);
598 IEEE80211_NODE_LOCK(nt
);
600 if (in
->in_fails
>= IEEE80211_STA_FAILS_MAX
) {
601 ieee80211_node_t
*tmpin
= in
;
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.
608 in
= list_next(&nt
->nt_node
, tmpin
);
609 ieee80211_node_reclaim(nt
, tmpin
);
613 * It's possible at some special moments, the in_chan will
614 * be none. Need to skip the null node.
616 if (in
->in_chan
== IEEE80211_CHAN_ANYC
) {
617 in
= list_next(&nt
->nt_node
, in
);
620 if (ieee80211_match_bss(ic
, in
) == 0) {
624 selbs
= ieee80211_node_compare(ic
, selbs
, in
);
626 in
= list_next(&nt
->nt_node
, in
);
628 if (selbs
!= NULL
) /* grab ref while dropping lock */
629 (void) ieee80211_ref_node(selbs
);
630 IEEE80211_NODE_UNLOCK(nt
);
633 IEEE80211_UNLOCK(ic
);
634 ieee80211_sta_join(ic
, selbs
);
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
645 * The caller is assumed to validate TSF's before attempting a merge.
647 * Return B_TRUE if the BSSID changed, B_FALSE otherwise.
650 ieee80211_ibss_merge(ieee80211_node_t
*in
)
652 ieee80211com_t
*ic
= in
->in_ic
;
654 if (in
== ic
->ic_bss
||
655 IEEE80211_ADDR_EQ(in
->in_bssid
, ic
->ic_bss
->in_bssid
)) {
656 /* unchanged, nothing to do */
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");
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
));
675 * Change the bss channel.
678 ieee80211_setcurchan(ieee80211com_t
*ic
, struct ieee80211_channel
*c
)
681 ic
->ic_curmode
= ieee80211_chan2mode(ic
, ic
->ic_curchan
);
682 if (ic
->ic_set_channel
!= NULL
)
683 ic
->ic_set_channel(ic
);
687 * Join the specified IBSS/BSS network. The node is assumed to
688 * be passed in with a held reference.
691 ieee80211_sta_join(ieee80211com_t
*ic
, ieee80211_node_t
*selbs
)
693 ieee80211_impl_t
*im
= ic
->ic_private
;
694 ieee80211_node_t
*obss
;
697 if (ic
->ic_opmode
== IEEE80211_M_IBSS
) {
698 ieee80211_node_table_t
*nt
;
701 * Delete unusable rates; we've already checked
702 * that the negotiated rate set is acceptable.
704 (void) ieee80211_fix_rate(selbs
, &selbs
->in_rates
,
707 * Fillin the neighbor table
710 IEEE80211_NODE_LOCK(nt
);
711 nt
->nt_name
= "neighbor";
712 nt
->nt_inact_init
= im
->im_inact_run
;
713 IEEE80211_NODE_UNLOCK(nt
);
717 * Committed to selbs, setup state.
720 ic
->ic_bss
= selbs
; /* caller assumed to bump refcnt */
722 ieee80211_copy_bss(selbs
, obss
);
723 ieee80211_free_node(obss
);
725 ic
->ic_curmode
= ieee80211_chan2mode(ic
, selbs
->in_chan
);
726 ic
->ic_curchan
= selbs
->in_chan
;
727 ic
->ic_phytype
= selbs
->in_phytype
;
729 * Set the erp state (mostly the slot time) to deal with
730 * the auto-select case; this should be redundant if the
733 ieee80211_reset_erp(ic
);
734 ieee80211_wme_initparams(ic
);
736 IEEE80211_UNLOCK(ic
);
737 if (ic
->ic_opmode
== IEEE80211_M_STA
)
738 ieee80211_new_state(ic
, IEEE80211_S_AUTH
, -1);
740 ieee80211_new_state(ic
, IEEE80211_S_RUN
, -1);
744 * Leave the specified IBSS/BSS network. The node is assumed to
745 * be passed in with a held reference.
748 ieee80211_sta_leave(ieee80211com_t
*ic
, ieee80211_node_t
*in
)
751 ic
->ic_node_cleanup(in
);
752 ieee80211_notify_node_leave(ic
, in
);
753 IEEE80211_UNLOCK(ic
);
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.
762 static ieee80211_node_t
*
763 ieee80211_node_alloc(ieee80211com_t
*ic
)
765 return (kmem_zalloc(sizeof (ieee80211_node_t
), KM_SLEEP
));
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.
774 ieee80211_node_cleanup(ieee80211_node_t
*in
)
779 if (in
->in_challenge
!= NULL
) {
780 kmem_free(in
->in_challenge
, IEEE80211_CHALLENGE_LEN
);
781 in
->in_challenge
= NULL
;
783 if (in
->in_rxfrag
!= NULL
) {
784 freemsg(in
->in_rxfrag
);
785 in
->in_rxfrag
= NULL
;
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
795 ieee80211_node_free(ieee80211_node_t
*in
)
797 ieee80211com_t
*ic
= in
->in_ic
;
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
));
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.
815 ieee80211_node_getrssi(const ieee80211_node_t
*in
)
817 return (in
->in_rssi
);
820 /* Free fragment if not needed anymore */
822 node_cleanfrag(ieee80211_node_t
*in
)
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
;
834 * Setup a node. Initialize the node with specified macaddr. Associate
835 * with the interface softc, ic, and add it to the specified node
839 ieee80211_setup_node(ieee80211com_t
*ic
, ieee80211_node_table_t
*nt
,
840 ieee80211_node_t
*in
, const uint8_t *macaddr
)
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");
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
);
861 IEEE80211_NODE_LOCK(nt
);
862 list_insert_tail(&nt
->nt_node
, in
);
863 list_insert_tail(&nt
->nt_hash
[hash
], in
);
865 in
->in_inact_reload
= nt
->nt_inact_init
;
866 IEEE80211_NODE_UNLOCK(nt
);
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
877 ieee80211_alloc_node(ieee80211com_t
*ic
, ieee80211_node_table_t
*nt
,
878 const uint8_t *macaddr
)
880 ieee80211_node_t
*in
;
882 in
= ic
->ic_node_alloc(ic
);
884 ieee80211_setup_node(ic
, nt
, in
, macaddr
);
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.
895 ieee80211_tmp_node(ieee80211com_t
*ic
, const uint8_t *macaddr
)
897 ieee80211_node_t
*in
;
899 in
= ic
->ic_node_alloc(ic
);
901 ieee80211_dbg(IEEE80211_MSG_NODE
, "ieee80211_tmp_node: "
902 "%p<%s>\n", in
, ieee80211_macaddr_sprintf(macaddr
));
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
);
913 in
->in_table
= NULL
; /* NB: pedantic */
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.
927 ieee80211_dup_bss(ieee80211_node_table_t
*nt
, const uint8_t *macaddr
)
929 ieee80211com_t
*ic
= nt
->nt_ic
;
930 ieee80211_node_t
*in
;
932 in
= ieee80211_alloc_node(ic
, nt
, macaddr
);
935 * Inherit from ic_bss.
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
);
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.
952 static ieee80211_node_t
*
953 ieee80211_find_node_locked(ieee80211_node_table_t
*nt
, const uint8_t *macaddr
)
955 ieee80211_node_t
*in
;
958 ASSERT(IEEE80211_NODE_IS_LOCKED(nt
));
960 hash
= ieee80211_node_hash(macaddr
);
961 in
= list_head(&nt
->nt_hash
[hash
]);
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
);
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.
976 ieee80211_find_node(ieee80211_node_table_t
*nt
, const uint8_t *macaddr
)
978 ieee80211_node_t
*in
;
980 IEEE80211_NODE_LOCK(nt
);
981 in
= ieee80211_find_node_locked(nt
, macaddr
);
982 IEEE80211_NODE_UNLOCK(nt
);
987 * Like find but search based on the ssid too.
990 ieee80211_find_node_with_ssid(ieee80211_node_table_t
*nt
,
991 const uint8_t *macaddr
, uint32_t ssidlen
, const uint8_t *ssid
)
993 ieee80211_node_t
*in
;
996 IEEE80211_NODE_LOCK(nt
);
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)
1005 in
= list_next(&nt
->nt_hash
[hash
], in
);
1008 (void) ieee80211_ref_node(in
); /* mark referenced */
1010 IEEE80211_NODE_UNLOCK(nt
);
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
1022 ieee80211_fakeup_adhoc_node(ieee80211_node_table_t
*nt
, const uint8_t *macaddr
)
1024 ieee80211com_t
*ic
= nt
->nt_ic
;
1025 ieee80211_node_t
*in
;
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
);
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
);
1041 ieee80211_saveie(uint8_t **iep
, const uint8_t *ie
)
1043 uint_t ielen
= ie
[1]+2;
1045 * Record information element for later use.
1047 if (*iep
== NULL
|| (*iep
)[1] != ie
[1]) {
1049 ieee80211_free(*iep
);
1050 *iep
= ieee80211_malloc(ielen
);
1053 (void) memcpy(*iep
, ie
, ielen
);
1057 saveie(uint8_t **iep
, const uint8_t *ie
)
1061 ieee80211_free(*iep
);
1065 ieee80211_saveie(iep
, ie
);
1069 * Process a beacon or probe response frame.
1072 ieee80211_add_scan(ieee80211com_t
*ic
, const struct ieee80211_scanparams
*sp
,
1073 const struct ieee80211_frame
*wh
, int subtype
, int rssi
, int rstamp
)
1075 ieee80211_node_table_t
*nt
= &ic
->ic_scan
;
1076 ieee80211_node_t
*in
;
1077 boolean_t newnode
= B_FALSE
;
1079 in
= ieee80211_find_node(nt
, wh
->i_addr3
);
1082 * Create a new entry.
1084 in
= ieee80211_alloc_node(ic
, nt
, wh
->i_addr3
);
1086 ieee80211_dbg(IEEE80211_MSG_ANY
, "ieee80211_add_scan: "
1087 "alloc node failed\n");
1091 * inherit from ic_bss.
1093 ieee80211_copy_bss(in
, ic
->ic_bss
);
1094 ieee80211_node_setchan(ic
, in
, ic
->ic_curchan
);
1098 /* ap beaconing multiple ssid w/ same bssid */
1101 * sp->ssid[0] - element ID
1102 * sp->ssid[1] - length
1103 * sp->ssid[2]... - ssid
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]);
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
;
1126 ie
= (struct ieee80211_tim_ie
*)sp
->tim
;
1127 in
->in_dtim_count
= ie
->tim_count
;
1128 in
->in_dtim_period
= ie
->tim_period
;
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.
1136 in
->in_tim_off
= sp
->timoff
;
1138 * Record optional information elements that might be
1139 * used by applications or drivers.
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
);
1148 /* NB: must be after in_chan is setup */
1149 (void) ieee80211_setup_rates(in
, sp
->rates
, sp
->xrates
,
1150 IEEE80211_F_DOSORT
);
1153 ieee80211_free_node(in
);
1157 * Initialize/update an ad-hoc node with contents from a received
1161 ieee80211_init_neighbor(ieee80211_node_t
*in
, const struct ieee80211_frame
*wh
,
1162 const struct ieee80211_scanparams
*sp
)
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
);
1178 /* NB: must be after in_chan is setup */
1179 (void) ieee80211_setup_rates(in
, sp
->rates
, sp
->xrates
,
1180 IEEE80211_F_DOSORT
);
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.
1190 ieee80211_add_neighbor(ieee80211com_t
*ic
, const struct ieee80211_frame
*wh
,
1191 const struct ieee80211_scanparams
*sp
)
1193 ieee80211_node_t
*in
;
1195 in
= ieee80211_dup_bss(&ic
->ic_sta
, wh
->i_addr2
);
1197 ieee80211_init_neighbor(in
, wh
, sp
);
1198 if (ic
->ic_node_newassoc
!= NULL
)
1199 ic
->ic_node_newassoc(in
, 1);
1204 #define IEEE80211_IS_CTL(wh) \
1205 ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)
1207 #define IEEE80211_IS_PSPOLL(wh) \
1208 ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == \
1209 IEEE80211_FC0_SUBTYPE_PS_POLL)
1211 #define IEEE80211_IS_BAR(wh) \
1212 ((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == \
1213 IEEE80211_FC0_SUBTYPE_BAR)
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
1224 ieee80211_find_rxnode(ieee80211com_t
*ic
, const struct ieee80211_frame
*wh
)
1226 ieee80211_node_table_t
*nt
;
1227 ieee80211_node_t
*in
;
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
)) {
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
);
1242 in
= ieee80211_find_node_locked(nt
, wh
->i_addr2
);
1243 IEEE80211_NODE_UNLOCK(nt
);
1246 in
= ieee80211_ref_node(ic
->ic_bss
);
1251 #undef IEEE80211_IS_BAR
1252 #undef IEEE80211_IS_PSPOLL
1253 #undef IEEE80211_IS_CTL
1256 * Return a reference to the appropriate node for sending
1257 * a data frame. This handles node discovery in adhoc networks.
1260 ieee80211_find_txnode(ieee80211com_t
*ic
, const uint8_t *daddr
)
1262 ieee80211_node_table_t
*nt
= &ic
->ic_sta
;
1263 ieee80211_node_t
*in
;
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
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
);
1275 in
= ieee80211_find_node_locked(nt
, daddr
);
1276 IEEE80211_NODE_UNLOCK(nt
);
1279 if (ic
->ic_opmode
== IEEE80211_M_IBSS
) {
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
1288 in
= ieee80211_fakeup_adhoc_node(nt
, daddr
);
1290 (void) ieee80211_ref_node(in
);
1292 ieee80211_dbg(IEEE80211_MSG_OUTPUT
,
1293 "ieee80211_find_txnode: "
1294 "[%s] no node, discard frame\n",
1295 ieee80211_macaddr_sprintf(daddr
));
1302 * Remove a node from the node database entries and free memory
1303 * associated with the node. The node table lock is acquired by
1307 ieee80211_free_node_locked(ieee80211_node_t
*in
)
1309 ieee80211com_t
*ic
= in
->in_ic
;
1310 ieee80211_node_table_t
*nt
= in
->in_table
;
1314 hash
= ieee80211_node_hash(in
->in_macaddr
);
1315 list_remove(&nt
->nt_hash
[hash
], in
);
1316 list_remove(&nt
->nt_node
, in
);
1318 ic
->ic_node_free(in
);
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()
1327 ieee80211_free_node(ieee80211_node_t
*in
)
1329 ieee80211_node_table_t
*nt
= in
->in_table
;
1332 IEEE80211_NODE_LOCK(nt
);
1333 if (ieee80211_node_decref_nv(in
) == 0)
1334 ieee80211_free_node_locked(in
);
1336 IEEE80211_NODE_UNLOCK(nt
);
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.
1345 ieee80211_node_reclaim(ieee80211_node_table_t
*nt
, ieee80211_node_t
*in
)
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
));
1355 if (ieee80211_node_decref_nv(in
) != 0) {
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.
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
;
1368 ieee80211_free_node_locked(in
);
1373 * Iterate through the node list and reclaim all node in the node table.
1374 * The node table lock is acquired by the caller
1377 ieee80211_free_allnodes_locked(ieee80211_node_table_t
*nt
)
1379 ieee80211_node_t
*in
;
1381 ieee80211_dbg(IEEE80211_MSG_NODE
, "ieee80211_free_allnodes_locked(): "
1382 "free all nodes in %s table\n", nt
->nt_name
);
1384 in
= list_head(&nt
->nt_node
);
1385 while (in
!= NULL
) {
1386 ieee80211_node_reclaim(nt
, in
);
1387 in
= list_head(&nt
->nt_node
);
1389 ieee80211_reset_erp(nt
->nt_ic
);
1393 * Iterate through the node list, calling ieee80211_node_reclaim() for
1394 * all nodes associated with the interface.
1397 ieee80211_free_allnodes(ieee80211_node_table_t
*nt
)
1399 IEEE80211_NODE_LOCK(nt
);
1400 ieee80211_free_allnodes_locked(nt
);
1401 IEEE80211_NODE_UNLOCK(nt
);
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
1410 ieee80211_timeout_scan_candidates(ieee80211_node_table_t
*nt
)
1412 ieee80211com_t
*ic
= nt
->nt_ic
;
1413 ieee80211_node_t
*in
;
1415 IEEE80211_NODE_LOCK(nt
);
1417 node_cleanfrag(in
); /* Free fragment if not needed */
1418 nt
->nt_inact_timer
= IEEE80211_INACT_WAIT
;
1419 IEEE80211_NODE_UNLOCK(nt
);
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.
1433 ieee80211_timeout_stations(ieee80211_node_table_t
*nt
)
1435 ieee80211com_t
*ic
= nt
->nt_ic
;
1436 ieee80211_impl_t
*im
= ic
->ic_private
;
1437 ieee80211_node_t
*in
= NULL
;
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
;
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 */
1452 in
->in_scangen
= gen
;
1453 node_cleanfrag(in
); /* free fragment if not needed */
1456 * Special case ourself; we may be idle for extended periods
1457 * of time and regardless reclaiming our state is wrong.
1459 if (in
== ic
->ic_bss
)
1462 if (in
->in_associd
!= 0 || isadhoc
) {
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...).
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
);
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
));
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.
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.
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
);
1507 ieee80211_node_leave(ic
, in
);
1511 IEEE80211_NODE_UNLOCK(nt
);
1513 IEEE80211_SCAN_UNLOCK(nt
);
1515 nt
->nt_inact_timer
= IEEE80211_INACT_WAIT
;
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.
1524 ieee80211_iterate_nodes(ieee80211_node_table_t
*nt
, ieee80211_iter_func
*f
,
1527 ieee80211_node_t
*in
;
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
);
1536 (void) ieee80211_ref_node(in
);
1537 IEEE80211_NODE_UNLOCK(nt
);
1539 ieee80211_free_node(in
);
1540 IEEE80211_NODE_LOCK(nt
);
1541 in
= list_next(&nt
->nt_node
, in
);
1543 IEEE80211_NODE_UNLOCK(nt
);
1547 * Handle bookkeeping for station deauthentication/disassociation
1548 * when operating as an ap.
1551 ieee80211_node_leave(ieee80211com_t
*ic
, ieee80211_node_t
*in
)
1553 ieee80211_node_table_t
*nt
= in
->in_table
;
1555 ASSERT(ic
->ic_opmode
== IEEE80211_M_IBSS
);
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
1564 IEEE80211_NODE_LOCK(nt
);
1565 ieee80211_node_reclaim(nt
, in
);
1566 IEEE80211_NODE_UNLOCK(nt
);
1568 ieee80211_free_node(in
);
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.
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
*))
1584 ieee80211_dbg(IEEE80211_MSG_NODE
, "ieee80211_node_table_init():"
1585 "%s table, inact %d\n", name
, inact
);
1589 nt
->nt_inact_timer
= 0;
1590 nt
->nt_inact_init
= inact
;
1591 nt
->nt_timeout
= timeout
;
1592 nt
->nt_keyixmax
= keyixmax
;
1594 mutex_init(&nt
->nt_scanlock
, NULL
, MUTEX_DRIVER
, NULL
);
1595 mutex_init(&nt
->nt_nodelock
, NULL
, MUTEX_DRIVER
, NULL
);
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
));
1606 * Reset a node table. Clean its inactivity timer and call
1607 * ieee80211_free_allnodes_locked() to free all nodes in the
1611 ieee80211_node_table_reset(ieee80211_node_table_t
*nt
)
1613 ieee80211_dbg(IEEE80211_MSG_NODE
, "ieee80211_node_table_reset(): "
1614 "%s table\n", nt
->nt_name
);
1616 IEEE80211_NODE_LOCK(nt
);
1617 nt
->nt_inact_timer
= 0;
1618 ieee80211_free_allnodes_locked(nt
);
1619 IEEE80211_NODE_UNLOCK(nt
);
1623 * Destroy a node table. Free all nodes in the node table.
1624 * This function is usually called by node detach function.
1627 ieee80211_node_table_cleanup(ieee80211_node_table_t
*nt
)
1629 ieee80211_dbg(IEEE80211_MSG_NODE
, "ieee80211_node_table_cleanup(): "
1630 "%s table\n", nt
->nt_name
);
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
);