ieee80211_node.c revision 179220
1331766Sken/*-
2331766Sken * Copyright (c) 2001 Atsushi Onoe
3331766Sken * Copyright (c) 2002-2008 Sam Leffler, Errno Consulting
4331766Sken * All rights reserved.
5331766Sken *
6331766Sken * Redistribution and use in source and binary forms, with or without
7331766Sken * modification, are permitted provided that the following conditions
8331766Sken * are met:
9331766Sken * 1. Redistributions of source code must retain the above copyright
10331766Sken *    notice, this list of conditions and the following disclaimer.
11331766Sken * 2. Redistributions in binary form must reproduce the above copyright
12331766Sken *    notice, this list of conditions and the following disclaimer in the
13331766Sken *    documentation and/or other materials provided with the distribution.
14331766Sken *
15331766Sken * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16331766Sken * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17331766Sken * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18331766Sken * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19331766Sken * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20331766Sken * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21331766Sken * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22331766Sken * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23331766Sken * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24331766Sken * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25331766Sken */
26331766Sken
27331766Sken#include <sys/cdefs.h>
28331766Sken__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_node.c 179220 2008-05-22 22:22:10Z sam $");
29331766Sken
30331766Sken#include "opt_wlan.h"
31331766Sken
32331766Sken#include <sys/param.h>
33331766Sken#include <sys/systm.h>
34331766Sken#include <sys/mbuf.h>
35331766Sken#include <sys/malloc.h>
36331766Sken#include <sys/kernel.h>
37331766Sken
38331766Sken#include <sys/socket.h>
39331766Sken
40331766Sken#include <net/if.h>
41331766Sken#include <net/if_media.h>
42331766Sken#include <net/ethernet.h>
43331766Sken
44331766Sken#include <net80211/ieee80211_var.h>
45331766Sken#include <net80211/ieee80211_input.h>
46331766Sken#include <net80211/ieee80211_wds.h>
47331766Sken
48331766Sken#include <net/bpf.h>
49331766Sken
50331766Sken/*
51331766Sken * Association id's are managed with a bit vector.
52331766Sken */
53331766Sken#define	IEEE80211_AID_SET(_vap, b) \
54331766Sken	((_vap)->iv_aid_bitmap[IEEE80211_AID(b) / 32] |= \
55331766Sken		(1 << (IEEE80211_AID(b) % 32)))
56331766Sken#define	IEEE80211_AID_CLR(_vap, b) \
57331766Sken	((_vap)->iv_aid_bitmap[IEEE80211_AID(b) / 32] &= \
58331766Sken		~(1 << (IEEE80211_AID(b) % 32)))
59331766Sken#define	IEEE80211_AID_ISSET(_vap, b) \
60331766Sken	((_vap)->iv_aid_bitmap[IEEE80211_AID(b) / 32] & (1 << (IEEE80211_AID(b) % 32)))
61331766Sken
62331766Sken#ifdef IEEE80211_DEBUG_REFCNT
63331766Sken#define REFCNT_LOC "%s (%s:%u) %p<%s> refcnt %d\n", __func__, func, line
64331766Sken#else
65331766Sken#define REFCNT_LOC "%s %p<%s> refcnt %d\n", __func__
66331766Sken#endif
67331766Sken
68331766Skenstatic int ieee80211_sta_join1(struct ieee80211_node *);
69331766Sken
70331766Skenstatic struct ieee80211_node *node_alloc(struct ieee80211_node_table *);
71331766Skenstatic void node_cleanup(struct ieee80211_node *);
72331766Skenstatic void node_free(struct ieee80211_node *);
73331766Skenstatic void node_age(struct ieee80211_node *);
74331766Skenstatic int8_t node_getrssi(const struct ieee80211_node *);
75331766Skenstatic void node_getsignal(const struct ieee80211_node *, int8_t *, int8_t *);
76331766Skenstatic void node_getmimoinfo(const struct ieee80211_node *,
77331766Sken	struct ieee80211_mimo_info *);
78331766Sken
79331766Skenstatic void _ieee80211_free_node(struct ieee80211_node *);
80331766Sken
81331766Skenstatic void ieee80211_node_table_init(struct ieee80211com *ic,
82331766Sken	struct ieee80211_node_table *nt, const char *name,
83331766Sken	int inact, int keymaxix);
84331766Skenstatic void ieee80211_node_table_reset(struct ieee80211_node_table *,
85331766Sken	struct ieee80211vap *);
86331766Skenstatic void ieee80211_node_reclaim(struct ieee80211_node *);
87331766Skenstatic void ieee80211_node_table_cleanup(struct ieee80211_node_table *nt);
88331766Skenstatic void ieee80211_erp_timeout(struct ieee80211com *);
89331766Sken
90331766SkenMALLOC_DEFINE(M_80211_NODE, "80211node", "802.11 node state");
91331766SkenMALLOC_DEFINE(M_80211_NODE_IE, "80211nodeie", "802.11 node ie");
92331766Sken
93331766Skenvoid
94331766Skenieee80211_node_attach(struct ieee80211com *ic)
95331766Sken{
96331766Sken	ieee80211_node_table_init(ic, &ic->ic_sta, "station",
97331766Sken		IEEE80211_INACT_INIT, ic->ic_max_keyix);
98331766Sken	callout_init(&ic->ic_inact, CALLOUT_MPSAFE);
99331766Sken	callout_reset(&ic->ic_inact, IEEE80211_INACT_WAIT*hz,
100331766Sken		ieee80211_node_timeout, ic);
101331766Sken
102331766Sken	ic->ic_node_alloc = node_alloc;
103331766Sken	ic->ic_node_free = node_free;
104331766Sken	ic->ic_node_cleanup = node_cleanup;
105331766Sken	ic->ic_node_age = node_age;
106331766Sken	ic->ic_node_drain = node_age;		/* NB: same as age */
107331766Sken	ic->ic_node_getrssi = node_getrssi;
108331766Sken	ic->ic_node_getsignal = node_getsignal;
109331766Sken	ic->ic_node_getmimoinfo = node_getmimoinfo;
110331766Sken
111331766Sken	/*
112331766Sken	 * Set flags to be propagated to all vap's;
113331766Sken	 * these define default behaviour/configuration.
114331766Sken	 */
115331766Sken	ic->ic_flags_ext |= IEEE80211_FEXT_INACT; /* inactivity processing */
116331766Sken}
117331766Sken
118331766Skenvoid
119331766Skenieee80211_node_detach(struct ieee80211com *ic)
120331766Sken{
121331766Sken
122331766Sken	callout_drain(&ic->ic_inact);
123331766Sken	ieee80211_node_table_cleanup(&ic->ic_sta);
124331766Sken}
125331766Sken
126331766Skenvoid
127331766Skenieee80211_node_vattach(struct ieee80211vap *vap)
128331766Sken{
129331766Sken	/* NB: driver can override */
130331766Sken	vap->iv_max_aid = IEEE80211_AID_DEF;
131331766Sken
132331766Sken	/* default station inactivity timer setings */
133331766Sken	vap->iv_inact_init = IEEE80211_INACT_INIT;
134331766Sken	vap->iv_inact_auth = IEEE80211_INACT_AUTH;
135331766Sken	vap->iv_inact_run = IEEE80211_INACT_RUN;
136331766Sken	vap->iv_inact_probe = IEEE80211_INACT_PROBE;
137331766Sken}
138331766Sken
139331766Skenvoid
140331766Skenieee80211_node_latevattach(struct ieee80211vap *vap)
141331766Sken{
142331766Sken	if (vap->iv_opmode == IEEE80211_M_HOSTAP) {
143331766Sken		/* XXX should we allow max aid to be zero? */
144331766Sken		if (vap->iv_max_aid < IEEE80211_AID_MIN) {
145331766Sken			vap->iv_max_aid = IEEE80211_AID_MIN;
146331766Sken			if_printf(vap->iv_ifp,
147331766Sken			    "WARNING: max aid too small, changed to %d\n",
148331766Sken			    vap->iv_max_aid);
149331766Sken		}
150331766Sken		MALLOC(vap->iv_aid_bitmap, uint32_t *,
151331766Sken			howmany(vap->iv_max_aid, 32) * sizeof(uint32_t),
152331766Sken			M_80211_NODE, M_NOWAIT | M_ZERO);
153331766Sken		if (vap->iv_aid_bitmap == NULL) {
154331766Sken			/* XXX no way to recover */
155331766Sken			printf("%s: no memory for AID bitmap, max aid %d!\n",
156331766Sken			    __func__, vap->iv_max_aid);
157331766Sken			vap->iv_max_aid = 0;
158331766Sken		}
159331766Sken	}
160331766Sken
161331766Sken	ieee80211_reset_bss(vap);
162331766Sken
163331766Sken	vap->iv_auth = ieee80211_authenticator_get(vap->iv_bss->ni_authmode);
164331766Sken}
165331766Sken
166331766Skenvoid
167331766Skenieee80211_node_vdetach(struct ieee80211vap *vap)
168331766Sken{
169331766Sken	struct ieee80211com *ic = vap->iv_ic;
170331766Sken
171331766Sken	ieee80211_node_table_reset(&ic->ic_sta, vap);
172331766Sken	if (vap->iv_bss != NULL) {
173331766Sken		ieee80211_free_node(vap->iv_bss);
174331766Sken		vap->iv_bss = NULL;
175331766Sken	}
176331766Sken	if (vap->iv_aid_bitmap != NULL) {
177331766Sken		FREE(vap->iv_aid_bitmap, M_80211_NODE);
178331766Sken		vap->iv_aid_bitmap = NULL;
179331766Sken	}
180331766Sken}
181331766Sken
182331766Sken/*
183331766Sken * Port authorize/unauthorize interfaces for use by an authenticator.
184331766Sken */
185331766Sken
186331766Skenvoid
187331766Skenieee80211_node_authorize(struct ieee80211_node *ni)
188331766Sken{
189331766Sken	ni->ni_flags |= IEEE80211_NODE_AUTH;
190331766Sken	ni->ni_inact_reload = ni->ni_vap->iv_inact_run;
191331766Sken	ni->ni_inact = ni->ni_inact_reload;
192331766Sken}
193331766Sken
194331766Skenvoid
195331766Skenieee80211_node_unauthorize(struct ieee80211_node *ni)
196331766Sken{
197331766Sken	ni->ni_flags &= ~IEEE80211_NODE_AUTH;
198331766Sken	ni->ni_inact_reload = ni->ni_vap->iv_inact_auth;
199331766Sken	if (ni->ni_inact > ni->ni_inact_reload)
200331766Sken		ni->ni_inact = ni->ni_inact_reload;
201331766Sken}
202331766Sken
203331766Sken/*
204331766Sken * Set/change the channel.  The rate set is also updated as
205331766Sken * to insure a consistent view by drivers.
206331766Sken * XXX should be private but hostap needs it to deal with CSA
207331766Sken */
208331766Skenvoid
209331766Skenieee80211_node_set_chan(struct ieee80211_node *ni,
210331766Sken	struct ieee80211_channel *chan)
211331766Sken{
212331766Sken	struct ieee80211com *ic = ni->ni_ic;
213331766Sken
214331766Sken	KASSERT(chan != IEEE80211_CHAN_ANYC, ("no channel"));
215331766Sken
216331766Sken	ni->ni_chan = chan;
217331766Sken	if (IEEE80211_IS_CHAN_HT(chan)) {
218331766Sken		/*
219331766Sken		 * XXX Gotta be careful here; the rate set returned by
220331766Sken		 * ieee80211_get_suprates is actually any HT rate
221331766Sken		 * set so blindly copying it will be bad.  We must
222331766Sken		 * install the legacy rate est in ni_rates and the
223331766Sken		 * HT rate set in ni_htrates.
224331766Sken		 */
225331766Sken		ni->ni_htrates = *ieee80211_get_suphtrates(ic, chan);
226331766Sken	}
227331766Sken	ni->ni_rates = *ieee80211_get_suprates(ic, chan);
228331766Sken}
229331766Sken
230331766Skenstatic __inline void
231331766Skencopy_bss(struct ieee80211_node *nbss, const struct ieee80211_node *obss)
232331766Sken{
233331766Sken	/* propagate useful state */
234331766Sken	nbss->ni_authmode = obss->ni_authmode;
235331766Sken	nbss->ni_txpower = obss->ni_txpower;
236331766Sken	nbss->ni_vlan = obss->ni_vlan;
237331766Sken	/* XXX statistics? */
238331766Sken	/* XXX legacy WDS bssid? */
239331766Sken}
240331766Sken
241331766Skenvoid
242331766Skenieee80211_create_ibss(struct ieee80211vap* vap, struct ieee80211_channel *chan)
243331766Sken{
244331766Sken	struct ieee80211com *ic = vap->iv_ic;
245331766Sken	struct ieee80211_node *ni;
246331766Sken
247331766Sken	IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
248331766Sken		"%s: creating ibss on channel %u\n", __func__,
249331766Sken		ieee80211_chan2ieee(ic, chan));
250331766Sken
251331766Sken	ni = ieee80211_alloc_node(&ic->ic_sta, vap, vap->iv_myaddr);
252331766Sken	if (ni == NULL) {
253331766Sken		/* XXX recovery? */
254331766Sken		return;
255331766Sken	}
256331766Sken	IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_myaddr);
257331766Sken	ni->ni_esslen = vap->iv_des_ssid[0].len;
258331766Sken	memcpy(ni->ni_essid, vap->iv_des_ssid[0].ssid, ni->ni_esslen);
259331766Sken	if (vap->iv_bss != NULL)
260331766Sken		copy_bss(ni, vap->iv_bss);
261331766Sken	ni->ni_intval = ic->ic_bintval;
262331766Sken	if (vap->iv_flags & IEEE80211_F_PRIVACY)
263331766Sken		ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY;
264331766Sken	if (ic->ic_phytype == IEEE80211_T_FH) {
265331766Sken		ni->ni_fhdwell = 200;	/* XXX */
266331766Sken		ni->ni_fhindex = 1;
267331766Sken	}
268331766Sken	if (vap->iv_opmode == IEEE80211_M_IBSS) {
269331766Sken		vap->iv_flags |= IEEE80211_F_SIBSS;
270331766Sken		ni->ni_capinfo |= IEEE80211_CAPINFO_IBSS;	/* XXX */
271331766Sken		if (vap->iv_flags & IEEE80211_F_DESBSSID)
272331766Sken			IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_des_bssid);
273331766Sken		else {
274331766Sken			get_random_bytes(ni->ni_bssid, IEEE80211_ADDR_LEN);
275331766Sken			/* clear group bit, add local bit */
276331766Sken			ni->ni_bssid[0] = (ni->ni_bssid[0] &~ 0x01) | 0x02;
277331766Sken		}
278331766Sken	} else if (vap->iv_opmode == IEEE80211_M_AHDEMO) {
279331766Sken		if (vap->iv_flags & IEEE80211_F_DESBSSID)
280331766Sken			IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_des_bssid);
281331766Sken		else
282331766Sken			memset(ni->ni_bssid, 0, IEEE80211_ADDR_LEN);
283331766Sken	}
284331766Sken	/*
285331766Sken	 * Fix the channel and related attributes.
286331766Sken	 */
287331766Sken	/* clear DFS CAC state on previous channel */
288331766Sken	if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
289331766Sken	    ic->ic_bsschan->ic_freq != chan->ic_freq &&
290331766Sken	    IEEE80211_IS_CHAN_CACDONE(ic->ic_bsschan))
291331766Sken		ieee80211_dfs_cac_clear(ic, ic->ic_bsschan);
292331766Sken	ic->ic_bsschan = chan;
293331766Sken	ieee80211_node_set_chan(ni, chan);
294331766Sken	ic->ic_curmode = ieee80211_chan2mode(chan);
295331766Sken	/*
296331766Sken	 * Do mode-specific setup.
297331766Sken	 */
298331766Sken	if (IEEE80211_IS_CHAN_FULL(chan)) {
299331766Sken		if (IEEE80211_IS_CHAN_ANYG(chan)) {
300331766Sken			/*
301331766Sken			 * Use a mixed 11b/11g basic rate set.
302331766Sken			 */
303331766Sken			ieee80211_setbasicrates(&ni->ni_rates,
304331766Sken			    IEEE80211_MODE_11G);
305331766Sken			if (vap->iv_flags & IEEE80211_F_PUREG) {
306331766Sken				/*
307331766Sken				 * Also mark OFDM rates basic so 11b
308331766Sken				 * stations do not join (WiFi compliance).
309331766Sken				 */
310331766Sken				ieee80211_addbasicrates(&ni->ni_rates,
311331766Sken				    IEEE80211_MODE_11A);
312331766Sken			}
313331766Sken		} else if (IEEE80211_IS_CHAN_B(chan)) {
314331766Sken			/*
315331766Sken			 * Force pure 11b rate set.
316331766Sken			 */
317331766Sken			ieee80211_setbasicrates(&ni->ni_rates,
318331766Sken				IEEE80211_MODE_11B);
319331766Sken		}
320331766Sken	}
321331766Sken
322331766Sken	(void) ieee80211_sta_join1(ieee80211_ref_node(ni));
323331766Sken}
324331766Sken
325331766Sken/*
326331766Sken * Reset bss state on transition to the INIT state.
327331766Sken * Clear any stations from the table (they have been
328331766Sken * deauth'd) and reset the bss node (clears key, rate
329331766Sken * etc. state).
330331766Sken */
331331766Skenvoid
332331766Skenieee80211_reset_bss(struct ieee80211vap *vap)
333331766Sken{
334331766Sken	struct ieee80211com *ic = vap->iv_ic;
335331766Sken	struct ieee80211_node *ni, *obss;
336331766Sken
337331766Sken	ieee80211_node_table_reset(&ic->ic_sta, vap);
338331766Sken	/* XXX multi-bss: wrong */
339331766Sken	ieee80211_reset_erp(ic);
340331766Sken
341331766Sken	ni = ieee80211_alloc_node(&ic->ic_sta, vap, vap->iv_myaddr);
342331766Sken	KASSERT(ni != NULL, ("unable to setup inital BSS node"));
343331766Sken	obss = vap->iv_bss;
344331766Sken	vap->iv_bss = ieee80211_ref_node(ni);
345331766Sken	if (obss != NULL) {
346331766Sken		copy_bss(ni, obss);
347331766Sken		ni->ni_intval = ic->ic_bintval;
348331766Sken		ieee80211_free_node(obss);
349331766Sken	} else
350331766Sken		IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_myaddr);
351331766Sken}
352331766Sken
353331766Skenstatic int
354331766Skenmatch_ssid(const struct ieee80211_node *ni,
355331766Sken	int nssid, const struct ieee80211_scan_ssid ssids[])
356331766Sken{
357331766Sken	int i;
358331766Sken
359331766Sken	for (i = 0; i < nssid; i++) {
360331766Sken		if (ni->ni_esslen == ssids[i].len &&
361331766Sken		     memcmp(ni->ni_essid, ssids[i].ssid, ni->ni_esslen) == 0)
362331766Sken			return 1;
363331766Sken	}
364331766Sken	return 0;
365331766Sken}
366331766Sken
367331766Sken/*
368331766Sken * Test a node for suitability/compatibility.
369331766Sken */
370331766Skenstatic int
371331766Skencheck_bss(struct ieee80211vap *vap, struct ieee80211_node *ni)
372331766Sken{
373331766Sken	struct ieee80211com *ic = ni->ni_ic;
374331766Sken        uint8_t rate;
375331766Sken
376331766Sken	if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, ni->ni_chan)))
377331766Sken		return 0;
378331766Sken	if (vap->iv_opmode == IEEE80211_M_IBSS) {
379331766Sken		if ((ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) == 0)
380331766Sken			return 0;
381331766Sken	} else {
382331766Sken		if ((ni->ni_capinfo & IEEE80211_CAPINFO_ESS) == 0)
383331766Sken			return 0;
384331766Sken	}
385331766Sken	if (vap->iv_flags & IEEE80211_F_PRIVACY) {
386331766Sken		if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0)
387331766Sken			return 0;
388331766Sken	} else {
389331766Sken		/* XXX does this mean privacy is supported or required? */
390331766Sken		if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY)
391331766Sken			return 0;
392331766Sken	}
393331766Sken	rate = ieee80211_fix_rate(ni, &ni->ni_rates,
394331766Sken	    IEEE80211_F_JOIN | IEEE80211_F_DONEGO | IEEE80211_F_DOFRATE);
395331766Sken	if (rate & IEEE80211_RATE_BASIC)
396331766Sken		return 0;
397331766Sken	if (vap->iv_des_nssid != 0 &&
398331766Sken	    !match_ssid(ni, vap->iv_des_nssid, vap->iv_des_ssid))
399331766Sken		return 0;
400331766Sken	if ((vap->iv_flags & IEEE80211_F_DESBSSID) &&
401331766Sken	    !IEEE80211_ADDR_EQ(vap->iv_des_bssid, ni->ni_bssid))
402331766Sken		return 0;
403331766Sken	return 1;
404331766Sken}
405331766Sken
406331766Sken#ifdef IEEE80211_DEBUG
407331766Sken/*
408331766Sken * Display node suitability/compatibility.
409331766Sken */
410331766Skenstatic void
411331766Skencheck_bss_debug(struct ieee80211vap *vap, struct ieee80211_node *ni)
412331766Sken{
413331766Sken	struct ieee80211com *ic = ni->ni_ic;
414331766Sken        uint8_t rate;
415331766Sken        int fail;
416331766Sken
417331766Sken	fail = 0;
418331766Sken	if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, ni->ni_chan)))
419331766Sken		fail |= 0x01;
420331766Sken	if (vap->iv_opmode == IEEE80211_M_IBSS) {
421331766Sken		if ((ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) == 0)
422331766Sken			fail |= 0x02;
423331766Sken	} else {
424331766Sken		if ((ni->ni_capinfo & IEEE80211_CAPINFO_ESS) == 0)
425331766Sken			fail |= 0x02;
426331766Sken	}
427331766Sken	if (vap->iv_flags & IEEE80211_F_PRIVACY) {
428331766Sken		if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0)
429331766Sken			fail |= 0x04;
430331766Sken	} else {
431331766Sken		/* XXX does this mean privacy is supported or required? */
432331766Sken		if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY)
433331766Sken			fail |= 0x04;
434331766Sken	}
435331766Sken	rate = ieee80211_fix_rate(ni, &ni->ni_rates,
436331766Sken	     IEEE80211_F_JOIN | IEEE80211_F_DONEGO | IEEE80211_F_DOFRATE);
437331766Sken	if (rate & IEEE80211_RATE_BASIC)
438331766Sken		fail |= 0x08;
439331766Sken	if (vap->iv_des_nssid != 0 &&
440331766Sken	    !match_ssid(ni, vap->iv_des_nssid, vap->iv_des_ssid))
441331766Sken		fail |= 0x10;
442331766Sken	if ((vap->iv_flags & IEEE80211_F_DESBSSID) &&
443331766Sken	    !IEEE80211_ADDR_EQ(vap->iv_des_bssid, ni->ni_bssid))
444331766Sken		fail |= 0x20;
445331766Sken
446331766Sken	printf(" %c %s", fail ? '-' : '+', ether_sprintf(ni->ni_macaddr));
447331766Sken	printf(" %s%c", ether_sprintf(ni->ni_bssid), fail & 0x20 ? '!' : ' ');
448331766Sken	printf(" %3d%c",
449331766Sken	    ieee80211_chan2ieee(ic, ni->ni_chan), fail & 0x01 ? '!' : ' ');
450331766Sken	printf(" %2dM%c", (rate & IEEE80211_RATE_VAL) / 2,
451331766Sken	    fail & 0x08 ? '!' : ' ');
452331766Sken	printf(" %4s%c",
453331766Sken	    (ni->ni_capinfo & IEEE80211_CAPINFO_ESS) ? "ess" :
454331766Sken	    (ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) ? "ibss" :
455331766Sken	    "????",
456331766Sken	    fail & 0x02 ? '!' : ' ');
457331766Sken	printf(" %3s%c ",
458331766Sken	    (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) ?  "wep" : "no",
459331766Sken	    fail & 0x04 ? '!' : ' ');
460331766Sken	ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
461331766Sken	printf("%s\n", fail & 0x10 ? "!" : "");
462331766Sken}
463331766Sken#endif /* IEEE80211_DEBUG */
464331766Sken
465331766Sken/*
466331766Sken * Handle 802.11 ad hoc network merge.  The
467331766Sken * convention, set by the Wireless Ethernet Compatibility Alliance
468331766Sken * (WECA), is that an 802.11 station will change its BSSID to match
469331766Sken * the "oldest" 802.11 ad hoc network, on the same channel, that
470331766Sken * has the station's desired SSID.  The "oldest" 802.11 network
471331766Sken * sends beacons with the greatest TSF timestamp.
472331766Sken *
473331766Sken * The caller is assumed to validate TSF's before attempting a merge.
474331766Sken *
475331766Sken * Return !0 if the BSSID changed, 0 otherwise.
476331766Sken */
477331766Skenint
478331766Skenieee80211_ibss_merge(struct ieee80211_node *ni)
479331766Sken{
480331766Sken	struct ieee80211vap *vap = ni->ni_vap;
481331766Sken#ifdef IEEE80211_DEBUG
482331766Sken	struct ieee80211com *ic = ni->ni_ic;
483331766Sken#endif
484331766Sken
485331766Sken	if (ni == vap->iv_bss ||
486331766Sken	    IEEE80211_ADDR_EQ(ni->ni_bssid, vap->iv_bss->ni_bssid)) {
487331766Sken		/* unchanged, nothing to do */
488331766Sken		return 0;
489331766Sken	}
490331766Sken	if (!check_bss(vap, ni)) {
491331766Sken		/* capabilities mismatch */
492331766Sken		IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC,
493331766Sken		    "%s: merge failed, capabilities mismatch\n", __func__);
494331766Sken#ifdef IEEE80211_DEBUG
495331766Sken		if (ieee80211_msg_assoc(vap))
496331766Sken			check_bss_debug(vap, ni);
497331766Sken#endif
498331766Sken		vap->iv_stats.is_ibss_capmismatch++;
499331766Sken		return 0;
500331766Sken	}
501331766Sken	IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC,
502331766Sken		"%s: new bssid %s: %s preamble, %s slot time%s\n", __func__,
503331766Sken		ether_sprintf(ni->ni_bssid),
504331766Sken		ic->ic_flags&IEEE80211_F_SHPREAMBLE ? "short" : "long",
505331766Sken		ic->ic_flags&IEEE80211_F_SHSLOT ? "short" : "long",
506331766Sken		ic->ic_flags&IEEE80211_F_USEPROT ? ", protection" : ""
507331766Sken	);
508331766Sken	return ieee80211_sta_join1(ieee80211_ref_node(ni));
509331766Sken}
510331766Sken
511331766Sken/*
512331766Sken * Calculate HT channel promotion flags for all vaps.
513331766Sken * This assumes ni_chan have been setup for each vap.
514331766Sken */
515331766Skenstatic int
516331766Skengethtadjustflags(struct ieee80211com *ic)
517331766Sken{
518331766Sken	struct ieee80211vap *vap;
519331766Sken	int flags;
520331766Sken
521331766Sken	flags = 0;
522331766Sken	/* XXX locking */
523331766Sken	TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
524331766Sken		if (vap->iv_state < IEEE80211_S_RUN)
525331766Sken			continue;
526331766Sken		switch (vap->iv_opmode) {
527331766Sken		case IEEE80211_M_WDS:
528331766Sken		case IEEE80211_M_STA:
529331766Sken		case IEEE80211_M_AHDEMO:
530331766Sken		case IEEE80211_M_HOSTAP:
531331766Sken		case IEEE80211_M_IBSS:
532331766Sken			flags |= ieee80211_htchanflags(vap->iv_bss->ni_chan);
533331766Sken			break;
534331766Sken		default:
535331766Sken			break;
536331766Sken		}
537331766Sken	}
538331766Sken	return flags;
539331766Sken}
540331766Sken
541331766Sken/*
542331766Sken * Check if the current channel needs to change based on whether
543331766Sken * any vap's are using HT20/HT40.  This is used sync the state of
544331766Sken * ic_curchan after a channel width change on a running vap.
545331766Sken */
546331766Skenvoid
547331766Skenieee80211_sync_curchan(struct ieee80211com *ic)
548331766Sken{
549331766Sken	struct ieee80211_channel *c;
550331766Sken
551331766Sken	c = ieee80211_ht_adjust_channel(ic, ic->ic_curchan, gethtadjustflags(ic));
552331766Sken	if (c != ic->ic_curchan) {
553331766Sken		ic->ic_curchan = c;
554331766Sken		ic->ic_curmode = ieee80211_chan2mode(ic->ic_curchan);
555331766Sken		ic->ic_set_channel(ic);
556331766Sken	}
557331766Sken}
558331766Sken
559331766Sken/*
560331766Sken * Change the current channel.  The request channel may be
561331766Sken * promoted if other vap's are operating with HT20/HT40.
562331766Sken */
563331766Skenvoid
564331766Skenieee80211_setcurchan(struct ieee80211com *ic, struct ieee80211_channel *c)
565331766Sken{
566331766Sken	if (ic->ic_htcaps & IEEE80211_HTC_HT) {
567331766Sken		int flags = gethtadjustflags(ic);
568331766Sken		/*
569331766Sken		 * Check for channel promotion required to support the
570331766Sken		 * set of running vap's.  This assumes we are called
571331766Sken		 * after ni_chan is setup for each vap.
572331766Sken		 */
573331766Sken		/* NB: this assumes IEEE80211_FEXT_USEHT40 > IEEE80211_FEXT_HT */
574331766Sken		if (flags > ieee80211_htchanflags(c))
575331766Sken			c = ieee80211_ht_adjust_channel(ic, c, flags);
576331766Sken	}
577331766Sken	ic->ic_bsschan = ic->ic_curchan = c;
578331766Sken	ic->ic_curmode = ieee80211_chan2mode(ic->ic_curchan);
579331766Sken	ic->ic_set_channel(ic);
580331766Sken}
581331766Sken
582331766Sken/*
583331766Sken * Join the specified IBSS/BSS network.  The node is assumed to
584331766Sken * be passed in with a held reference.
585331766Sken */
586331766Skenstatic int
587331766Skenieee80211_sta_join1(struct ieee80211_node *selbs)
588331766Sken{
589331766Sken	struct ieee80211vap *vap = selbs->ni_vap;
590331766Sken	struct ieee80211com *ic = selbs->ni_ic;
591331766Sken	struct ieee80211_node *obss;
592331766Sken	int canreassoc;
593331766Sken
594331766Sken	/*
595331766Sken	 * Committed to selbs, setup state.
596331766Sken	 */
597331766Sken	obss = vap->iv_bss;
598331766Sken	/*
599331766Sken	 * Check if old+new node have the same address in which
600331766Sken	 * case we can reassociate when operating in sta mode.
601331766Sken	 */
602331766Sken	canreassoc = (obss != NULL &&
603331766Sken		vap->iv_state == IEEE80211_S_RUN &&
604331766Sken		IEEE80211_ADDR_EQ(obss->ni_macaddr, selbs->ni_macaddr));
605331766Sken	vap->iv_bss = selbs;		/* NB: caller assumed to bump refcnt */
606331766Sken	if (obss != NULL) {
607331766Sken		copy_bss(selbs, obss);
608331766Sken		ieee80211_node_reclaim(obss);
609331766Sken		obss = NULL;		/* NB: guard against later use */
610331766Sken	}
611331766Sken
612331766Sken	/*
613331766Sken	 * Delete unusable rates; we've already checked
614331766Sken	 * that the negotiated rate set is acceptable.
615331766Sken	 */
616331766Sken	ieee80211_fix_rate(vap->iv_bss, &vap->iv_bss->ni_rates,
617331766Sken		IEEE80211_F_DODEL | IEEE80211_F_JOIN);
618331766Sken
619331766Sken	ieee80211_setcurchan(ic, selbs->ni_chan);
620331766Sken	/*
621331766Sken	 * Set the erp state (mostly the slot time) to deal with
622331766Sken	 * the auto-select case; this should be redundant if the
623331766Sken	 * mode is locked.
624331766Sken	 */
625331766Sken	ieee80211_reset_erp(ic);
626331766Sken	ieee80211_wme_initparams(vap);
627331766Sken
628331766Sken	if (vap->iv_opmode == IEEE80211_M_STA) {
629331766Sken		if (canreassoc) {
630331766Sken			/* Reassociate */
631331766Sken			ieee80211_new_state(vap, IEEE80211_S_ASSOC, 1);
632331766Sken		} else {
633331766Sken			/*
634331766Sken			 * Act as if we received a DEAUTH frame in case we
635331766Sken			 * are invoked from the RUN state.  This will cause
636331766Sken			 * us to try to re-authenticate if we are operating
637331766Sken			 * as a station.
638331766Sken			 */
639331766Sken			ieee80211_new_state(vap, IEEE80211_S_AUTH,
640331766Sken				IEEE80211_FC0_SUBTYPE_DEAUTH);
641331766Sken		}
642331766Sken	} else
643331766Sken		ieee80211_new_state(vap, IEEE80211_S_RUN, -1);
644331766Sken	return 1;
645331766Sken}
646331766Sken
647331766Skenint
648331766Skenieee80211_sta_join(struct ieee80211vap *vap,
649331766Sken	const struct ieee80211_scan_entry *se)
650331766Sken{
651331766Sken	struct ieee80211com *ic = vap->iv_ic;
652331766Sken	struct ieee80211_node *ni;
653331766Sken
654331766Sken	ni = ieee80211_alloc_node(&ic->ic_sta, vap, se->se_macaddr);
655331766Sken	if (ni == NULL) {
656331766Sken		/* XXX msg */
657331766Sken		return 0;
658331766Sken	}
659331766Sken	/*
660331766Sken	 * Expand scan state into node's format.
661331766Sken	 * XXX may not need all this stuff
662331766Sken	 */
663331766Sken	IEEE80211_ADDR_COPY(ni->ni_bssid, se->se_bssid);
664331766Sken	ni->ni_esslen = se->se_ssid[1];
665331766Sken	memcpy(ni->ni_essid, se->se_ssid+2, ni->ni_esslen);
666331766Sken	ni->ni_rstamp = se->se_rstamp;
667331766Sken	ni->ni_tstamp.tsf = se->se_tstamp.tsf;
668331766Sken	ni->ni_intval = se->se_intval;
669331766Sken	ni->ni_capinfo = se->se_capinfo;
670331766Sken	ni->ni_chan = se->se_chan;
671331766Sken	ni->ni_timoff = se->se_timoff;
672331766Sken	ni->ni_fhdwell = se->se_fhdwell;
673331766Sken	ni->ni_fhindex = se->se_fhindex;
674331766Sken	ni->ni_erp = se->se_erp;
675331766Sken	IEEE80211_RSSI_LPF(ni->ni_avgrssi, se->se_rssi);
676331766Sken	ni->ni_noise = se->se_noise;
677331766Sken
678331766Sken	if (ieee80211_ies_init(&ni->ni_ies, se->se_ies.data, se->se_ies.len)) {
679331766Sken		ieee80211_ies_expand(&ni->ni_ies);
680331766Sken		if (ni->ni_ies.ath_ie != NULL)
681331766Sken			ieee80211_parse_ath(ni, ni->ni_ies.ath_ie);
682331766Sken		if (ni->ni_ies.htcap_ie != NULL)
683331766Sken			ieee80211_parse_htcap(ni, ni->ni_ies.htcap_ie);
684331766Sken		if (ni->ni_ies.htinfo_ie != NULL)
685331766Sken			ieee80211_parse_htinfo(ni, ni->ni_ies.htinfo_ie);
686331766Sken	}
687331766Sken
688331766Sken	vap->iv_dtim_period = se->se_dtimperiod;
689331766Sken	vap->iv_dtim_count = 0;
690331766Sken
691331766Sken	/* NB: must be after ni_chan is setup */
692331766Sken	ieee80211_setup_rates(ni, se->se_rates, se->se_xrates,
693331766Sken		IEEE80211_F_DOSORT);
694331766Sken
695331766Sken	return ieee80211_sta_join1(ieee80211_ref_node(ni));
696331766Sken}
697331766Sken
698331766Sken/*
699331766Sken * Leave the specified IBSS/BSS network.  The node is assumed to
700331766Sken * be passed in with a held reference.
701331766Sken */
702331766Skenvoid
703331766Skenieee80211_sta_leave(struct ieee80211_node *ni)
704331766Sken{
705331766Sken	struct ieee80211com *ic = ni->ni_ic;
706331766Sken
707331766Sken	ic->ic_node_cleanup(ni);
708331766Sken	ieee80211_notify_node_leave(ni);
709331766Sken}
710331766Sken
711331766Sken/*
712331766Sken * Send a deauthenticate frame and drop the station.
713331766Sken */
714331766Skenvoid
715331766Skenieee80211_node_deauth(struct ieee80211_node *ni, int reason)
716331766Sken{
717331766Sken	/* NB: bump the refcnt to be sure temporay nodes are not reclaimed */
718331766Sken	ieee80211_ref_node(ni);
719331766Sken	if (ni->ni_associd != 0)
720331766Sken		IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_DEAUTH, reason);
721331766Sken	ieee80211_node_leave(ni);
722331766Sken	ieee80211_free_node(ni);
723331766Sken}
724331766Sken
725331766Skenstatic struct ieee80211_node *
726331766Skennode_alloc(struct ieee80211_node_table *nt)
727331766Sken{
728331766Sken	struct ieee80211_node *ni;
729331766Sken
730331766Sken	MALLOC(ni, struct ieee80211_node *, sizeof(struct ieee80211_node),
731331766Sken		M_80211_NODE, M_NOWAIT | M_ZERO);
732331766Sken	return ni;
733331766Sken}
734331766Sken
735331766Sken/*
736331766Sken * Initialize an ie blob with the specified data.  If previous
737331766Sken * data exists re-use the data block.  As a side effect we clear
738331766Sken * all references to specific ie's; the caller is required to
739331766Sken * recalculate them.
740331766Sken */
741331766Skenint
742331766Skenieee80211_ies_init(struct ieee80211_ies *ies, const uint8_t *data, int len)
743331766Sken{
744331766Sken	/* NB: assumes data+len are the last fields */
745331766Sken	memset(ies, 0, offsetof(struct ieee80211_ies, data));
746331766Sken	if (ies->data != NULL && ies->len != len) {
747331766Sken		/* data size changed */
748331766Sken		FREE(ies->data, M_80211_NODE_IE);
749331766Sken		ies->data = NULL;
750331766Sken	}
751331766Sken	if (ies->data == NULL) {
752331766Sken		MALLOC(ies->data, uint8_t *, len, M_80211_NODE_IE, M_NOWAIT);
753331766Sken		if (ies->data == NULL) {
754331766Sken			ies->len = 0;
755331766Sken			/* NB: pointers have already been zero'd above */
756331766Sken			return 0;
757331766Sken		}
758331766Sken	}
759331766Sken	memcpy(ies->data, data, len);
760331766Sken	ies->len = len;
761331766Sken	return 1;
762331766Sken}
763331766Sken
764331766Sken/*
765331766Sken * Reclaim storage for an ie blob.
766331766Sken */
767331766Skenvoid
768331766Skenieee80211_ies_cleanup(struct ieee80211_ies *ies)
769331766Sken{
770331766Sken	if (ies->data != NULL)
771331766Sken		FREE(ies->data, M_80211_NODE_IE);
772331766Sken}
773331766Sken
774331766Sken/*
775331766Sken * Expand an ie blob data contents and to fillin individual
776331766Sken * ie pointers.  The data blob is assumed to be well-formed;
777331766Sken * we don't do any validity checking of ie lengths.
778331766Sken */
779331766Skenvoid
780331766Skenieee80211_ies_expand(struct ieee80211_ies *ies)
781331766Sken{
782331766Sken	uint8_t *ie;
783331766Sken	int ielen;
784335291Sdim
785331766Sken	ie = ies->data;
786331766Sken	ielen = ies->len;
787331766Sken	while (ielen > 0) {
788331766Sken		switch (ie[0]) {
789331766Sken		case IEEE80211_ELEMID_VENDOR:
790331766Sken			if (iswpaoui(ie))
791331766Sken				ies->wpa_ie = ie;
792331766Sken			else if (iswmeoui(ie))
793331766Sken				ies->wme_ie = ie;
794331766Sken			else if (isatherosoui(ie))
795331766Sken				ies->ath_ie = ie;
796331766Sken			break;
797331766Sken		case IEEE80211_ELEMID_RSN:
798331766Sken			ies->rsn_ie = ie;
799331766Sken			break;
800331766Sken		case IEEE80211_ELEMID_HTCAP:
801331766Sken			ies->htcap_ie = ie;
802331766Sken			break;
803331766Sken		}
804331766Sken		ielen -= 2 + ie[1];
805331766Sken		ie += 2 + ie[1];
806331766Sken	}
807331766Sken}
808335291Sdim
809331766Sken/*
810331766Sken * Reclaim any resources in a node and reset any critical
811331766Sken * state.  Typically nodes are free'd immediately after,
812331766Sken * but in some cases the storage may be reused so we need
813331766Sken * to insure consistent state (should probably fix that).
814331766Sken */
815331766Skenstatic void
816331766Skennode_cleanup(struct ieee80211_node *ni)
817331766Sken{
818331766Sken#define	N(a)	(sizeof(a)/sizeof(a[0]))
819331766Sken	struct ieee80211vap *vap = ni->ni_vap;
820331766Sken	int i;
821331766Sken
822331766Sken	/* NB: preserve ni_table */
823331766Sken	if (ni->ni_flags & IEEE80211_NODE_PWR_MGT) {
824331766Sken		if (vap->iv_opmode != IEEE80211_M_STA)
825331766Sken			vap->iv_ps_sta--;
826331766Sken		ni->ni_flags &= ~IEEE80211_NODE_PWR_MGT;
827331766Sken		IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
828331766Sken		    "power save mode off, %u sta's in ps mode", vap->iv_ps_sta);
829331766Sken	}
830331766Sken	/*
831331766Sken	 * Cleanup any HT-related state.
832331766Sken	 */
833331766Sken	if (ni->ni_flags & IEEE80211_NODE_HT)
834331766Sken		ieee80211_ht_node_cleanup(ni);
835331766Sken	/*
836331766Sken	 * Clear AREF flag that marks the authorization refcnt bump
837331766Sken	 * has happened.  This is probably not needed as the node
838331766Sken	 * should always be removed from the table so not found but
839331766Sken	 * do it just in case.
840331766Sken	 */
841331766Sken	ni->ni_flags &= ~IEEE80211_NODE_AREF;
842331766Sken
843331766Sken	/*
844331766Sken	 * Drain power save queue and, if needed, clear TIM.
845331766Sken	 */
846331766Sken	if (ieee80211_node_saveq_drain(ni) != 0 && vap->iv_set_tim != NULL)
847331766Sken		vap->iv_set_tim(ni, 0);
848331766Sken
849331766Sken	ni->ni_associd = 0;
850331766Sken	if (ni->ni_challenge != NULL) {
851331766Sken		FREE(ni->ni_challenge, M_80211_NODE);
852331766Sken		ni->ni_challenge = NULL;
853331766Sken	}
854331766Sken	/*
855331766Sken	 * Preserve SSID, WPA, and WME ie's so the bss node is
856331766Sken	 * reusable during a re-auth/re-assoc state transition.
857331766Sken	 * If we remove these data they will not be recreated
858331766Sken	 * because they come from a probe-response or beacon frame
859331766Sken	 * which cannot be expected prior to the association-response.
860331766Sken	 * This should not be an issue when operating in other modes
861331766Sken	 * as stations leaving always go through a full state transition
862331766Sken	 * which will rebuild this state.
863331766Sken	 *
864331766Sken	 * XXX does this leave us open to inheriting old state?
865331766Sken	 */
866331766Sken	for (i = 0; i < N(ni->ni_rxfrag); i++)
867331766Sken		if (ni->ni_rxfrag[i] != NULL) {
868331766Sken			m_freem(ni->ni_rxfrag[i]);
869331766Sken			ni->ni_rxfrag[i] = NULL;
870331766Sken		}
871331766Sken	/*
872331766Sken	 * Must be careful here to remove any key map entry w/o a LOR.
873331766Sken	 */
874331766Sken	ieee80211_node_delucastkey(ni);
875331766Sken#undef N
876331766Sken}
877331766Sken
878331766Skenstatic void
879331766Skennode_free(struct ieee80211_node *ni)
880331766Sken{
881331766Sken	struct ieee80211com *ic = ni->ni_ic;
882331766Sken
883331766Sken	ic->ic_node_cleanup(ni);
884331766Sken	ieee80211_ies_cleanup(&ni->ni_ies);
885331766Sken	IEEE80211_NODE_SAVEQ_DESTROY(ni);
886331766Sken	IEEE80211_NODE_WDSQ_DESTROY(ni);
887331766Sken	FREE(ni, M_80211_NODE);
888331766Sken}
889331766Sken
890331766Skenstatic void
891331766Skennode_age(struct ieee80211_node *ni)
892331766Sken{
893331766Sken	struct ieee80211vap *vap = ni->ni_vap;
894331766Sken#if 0
895331766Sken	IEEE80211_NODE_LOCK_ASSERT(&ic->ic_sta);
896331766Sken#endif
897331766Sken	/*
898331766Sken	 * Age frames on the power save queue.
899331766Sken	 */
900331766Sken	if (ieee80211_node_saveq_age(ni) != 0 &&
901331766Sken	    IEEE80211_NODE_SAVEQ_QLEN(ni) == 0 &&
902331766Sken	    vap->iv_set_tim != NULL)
903331766Sken		vap->iv_set_tim(ni, 0);
904331766Sken	/*
905331766Sken	 * Age frames on the wds pending queue.
906331766Sken	 */
907331766Sken	if (IEEE80211_NODE_WDSQ_QLEN(ni) != 0)
908331766Sken		ieee80211_node_wdsq_age(ni);
909331766Sken	/*
910331766Sken	 * Age out HT resources (e.g. frames on the
911331766Sken	 * A-MPDU reorder queues).
912331766Sken	 */
913331766Sken	if (ni->ni_associd != 0 && (ni->ni_flags & IEEE80211_NODE_HT))
914331766Sken		ieee80211_ht_node_age(ni);
915331766Sken}
916331766Sken
917331766Skenstatic int8_t
918331766Skennode_getrssi(const struct ieee80211_node *ni)
919331766Sken{
920331766Sken	uint32_t avgrssi = ni->ni_avgrssi;
921331766Sken	int32_t rssi;
922331766Sken
923331766Sken	if (avgrssi == IEEE80211_RSSI_DUMMY_MARKER)
924331766Sken		return 0;
925331766Sken	rssi = IEEE80211_RSSI_GET(avgrssi);
926331766Sken	return rssi < 0 ? 0 : rssi > 127 ? 127 : rssi;
927331766Sken}
928331766Sken
929331766Skenstatic void
930331766Skennode_getsignal(const struct ieee80211_node *ni, int8_t *rssi, int8_t *noise)
931331766Sken{
932331766Sken	*rssi = node_getrssi(ni);
933331766Sken	*noise = ni->ni_noise;
934331766Sken}
935331766Sken
936331766Skenstatic void
937331766Skennode_getmimoinfo(const struct ieee80211_node *ni,
938331766Sken	struct ieee80211_mimo_info *info)
939331766Sken{
940331766Sken	/* XXX zero data? */
941331766Sken}
942331766Sken
943331766Skenstruct ieee80211_node *
944331766Skenieee80211_alloc_node(struct ieee80211_node_table *nt,
945331766Sken	struct ieee80211vap *vap, const uint8_t macaddr[IEEE80211_ADDR_LEN])
946331766Sken{
947331766Sken	struct ieee80211com *ic = nt->nt_ic;
948331766Sken	struct ieee80211_node *ni;
949331766Sken	int hash;
950331766Sken
951331766Sken	ni = ic->ic_node_alloc(nt);
952331766Sken	if (ni == NULL) {
953331766Sken		vap->iv_stats.is_rx_nodealloc++;
954331766Sken		return NULL;
955331766Sken	}
956331766Sken
957331766Sken	IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
958331766Sken		"%s %p<%s> in %s table\n", __func__, ni,
959331766Sken		ether_sprintf(macaddr), nt->nt_name);
960331766Sken
961331766Sken	IEEE80211_ADDR_COPY(ni->ni_macaddr, macaddr);
962331766Sken	hash = IEEE80211_NODE_HASH(macaddr);
963331766Sken	ieee80211_node_initref(ni);		/* mark referenced */
964331766Sken	ni->ni_chan = IEEE80211_CHAN_ANYC;
965331766Sken	ni->ni_authmode = IEEE80211_AUTH_OPEN;
966331766Sken	ni->ni_txpower = ic->ic_txpowlimit;	/* max power */
967331766Sken	ieee80211_crypto_resetkey(vap, &ni->ni_ucastkey, IEEE80211_KEYIX_NONE);
968331766Sken	ni->ni_avgrssi = IEEE80211_RSSI_DUMMY_MARKER;
969331766Sken	ni->ni_inact_reload = nt->nt_inact_init;
970331766Sken	ni->ni_inact = ni->ni_inact_reload;
971331766Sken	ni->ni_ath_defkeyix = 0x7fff;
972331766Sken	IEEE80211_NODE_SAVEQ_INIT(ni, "unknown");
973331766Sken	IEEE80211_NODE_WDSQ_INIT(ni, "unknown");
974331766Sken
975331766Sken	IEEE80211_NODE_LOCK(nt);
976331766Sken	TAILQ_INSERT_TAIL(&nt->nt_node, ni, ni_list);
977331766Sken	LIST_INSERT_HEAD(&nt->nt_hash[hash], ni, ni_hash);
978331766Sken	ni->ni_table = nt;
979331766Sken	ni->ni_vap = vap;
980331766Sken	ni->ni_ic = ic;
981331766Sken	IEEE80211_NODE_UNLOCK(nt);
982331766Sken
983331766Sken	return ni;
984331766Sken}
985331766Sken
986331766Sken/*
987331766Sken * Craft a temporary node suitable for sending a management frame
988331766Sken * to the specified station.  We craft only as much state as we
989331766Sken * need to do the work since the node will be immediately reclaimed
990331766Sken * once the send completes.
991331766Sken */
992331766Skenstruct ieee80211_node *
993331766Skenieee80211_tmp_node(struct ieee80211vap *vap,
994331766Sken	const uint8_t macaddr[IEEE80211_ADDR_LEN])
995331766Sken{
996331766Sken	struct ieee80211com *ic = vap->iv_ic;
997331766Sken	struct ieee80211_node *ni;
998331766Sken
999331766Sken	ni = ic->ic_node_alloc(&ic->ic_sta);
1000331766Sken	if (ni != NULL) {
1001331766Sken		IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
1002331766Sken			"%s %p<%s>\n", __func__, ni, ether_sprintf(macaddr));
1003331766Sken
1004331766Sken		ni->ni_table = NULL;		/* NB: pedantic */
1005331766Sken		ni->ni_ic = ic;			/* NB: needed to set channel */
1006331766Sken		ni->ni_vap = vap;
1007331766Sken
1008331766Sken		IEEE80211_ADDR_COPY(ni->ni_macaddr, macaddr);
1009331766Sken		IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_bss->ni_bssid);
1010331766Sken		ieee80211_node_initref(ni);		/* mark referenced */
1011331766Sken		/* NB: required by ieee80211_fix_rate */
1012331766Sken		ieee80211_node_set_chan(ni, vap->iv_bss->ni_chan);
1013331766Sken		ni->ni_txpower = vap->iv_bss->ni_txpower;
1014331766Sken		ieee80211_crypto_resetkey(vap, &ni->ni_ucastkey,
1015331766Sken			IEEE80211_KEYIX_NONE);
1016331766Sken		/* XXX optimize away */
1017331766Sken		IEEE80211_NODE_SAVEQ_INIT(ni, "unknown");
1018331766Sken		IEEE80211_NODE_WDSQ_INIT(ni, "unknown");
1019331766Sken	} else {
1020331766Sken		/* XXX msg */
1021331766Sken		vap->iv_stats.is_rx_nodealloc++;
1022331766Sken	}
1023331766Sken	return ni;
1024331766Sken}
1025331766Sken
1026331766Skenstruct ieee80211_node *
1027331766Skenieee80211_dup_bss(struct ieee80211vap *vap,
1028331766Sken	const uint8_t macaddr[IEEE80211_ADDR_LEN])
1029331766Sken{
1030331766Sken	struct ieee80211com *ic = vap->iv_ic;
1031331766Sken	struct ieee80211_node *ni;
1032331766Sken
1033331766Sken	ni = ieee80211_alloc_node(&ic->ic_sta, vap, macaddr);
1034331766Sken	if (ni != NULL) {
1035331766Sken		/*
1036331766Sken		 * Inherit from iv_bss.
1037331766Sken		 */
1038331766Sken		ni->ni_authmode = vap->iv_bss->ni_authmode;
1039331766Sken		ni->ni_txpower = vap->iv_bss->ni_txpower;
1040331766Sken		ni->ni_vlan = vap->iv_bss->ni_vlan;	/* XXX?? */
1041331766Sken		IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_bss->ni_bssid);
1042331766Sken		ieee80211_node_set_chan(ni, vap->iv_bss->ni_chan);
1043331766Sken	}
1044331766Sken	return ni;
1045331766Sken}
1046331766Sken
1047331766Sken/*
1048331766Sken * Create a bss node for a legacy WDS vap.  The far end does
1049331766Sken * not associate so we just create create a new node and
1050331766Sken * simulate an association.  The caller is responsible for
1051331766Sken * installing the node as the bss node and handling any further
1052331766Sken * setup work like authorizing the port.
1053331766Sken */
1054331766Skenstruct ieee80211_node *
1055331766Skenieee80211_node_create_wds(struct ieee80211vap *vap,
1056331766Sken	const uint8_t bssid[IEEE80211_ADDR_LEN], struct ieee80211_channel *chan)
1057331766Sken{
1058331766Sken	struct ieee80211com *ic = vap->iv_ic;
1059331766Sken	struct ieee80211_node *ni;
1060331766Sken
1061331766Sken	/* XXX check if node already in sta table? */
1062331766Sken	ni = ieee80211_alloc_node(&ic->ic_sta, vap, bssid);
1063331766Sken	if (ni != NULL) {
1064331766Sken		ni->ni_wdsvap = vap;
1065331766Sken		IEEE80211_ADDR_COPY(ni->ni_bssid, bssid);
1066331766Sken		/*
1067331766Sken		 * Inherit any manually configured settings.
1068331766Sken		 */
1069331766Sken		ni->ni_authmode = vap->iv_bss->ni_authmode;
1070331766Sken		ni->ni_txpower = vap->iv_bss->ni_txpower;
1071331766Sken		ni->ni_vlan = vap->iv_bss->ni_vlan;
1072331766Sken		ieee80211_node_set_chan(ni, chan);
1073331766Sken		/* NB: propagate ssid so available to WPA supplicant */
1074331766Sken		ni->ni_esslen = vap->iv_des_ssid[0].len;
1075331766Sken		memcpy(ni->ni_essid, vap->iv_des_ssid[0].ssid, ni->ni_esslen);
1076331766Sken		/* NB: no associd for peer */
1077331766Sken		/*
1078331766Sken		 * There are no management frames to use to
1079331766Sken		 * discover neighbor capabilities, so blindly
1080331766Sken		 * propagate the local configuration.
1081331766Sken		 */
1082331766Sken		if (vap->iv_flags & IEEE80211_F_WME)
1083331766Sken			ni->ni_flags |= IEEE80211_NODE_QOS;
1084331766Sken		if (vap->iv_flags & IEEE80211_F_FF)
1085331766Sken			ni->ni_flags |= IEEE80211_NODE_FF;
1086331766Sken		if ((ic->ic_htcaps & IEEE80211_HTC_HT) &&
1087331766Sken		    (vap->iv_flags_ext & IEEE80211_FEXT_HT)) {
1088331766Sken			/*
1089331766Sken			 * Device is HT-capable and HT is enabled for
1090331766Sken			 * the vap; setup HT operation.  On return
1091331766Sken			 * ni_chan will be adjusted to an HT channel.
1092331766Sken			 */
1093331766Sken			ieee80211_ht_wds_init(ni);
1094331766Sken		} else {
1095331766Sken			struct ieee80211_channel *c = ni->ni_chan;
1096331766Sken			/*
1097331766Sken			 * Force a legacy channel to be used.
1098331766Sken			 */
1099331766Sken			c = ieee80211_find_channel(ic,
1100331766Sken			    c->ic_freq, c->ic_flags &~ IEEE80211_CHAN_HT);
1101331766Sken			KASSERT(c != NULL, ("no legacy channel, %u/%x",
1102331766Sken			    ni->ni_chan->ic_freq, ni->ni_chan->ic_flags));
1103331766Sken			ni->ni_chan = c;
1104331766Sken		}
1105331766Sken	}
1106331766Sken	return ni;
1107331766Sken}
1108331766Sken
1109331766Skenstruct ieee80211_node *
1110331766Sken#ifdef IEEE80211_DEBUG_REFCNT
1111331766Skenieee80211_find_node_locked_debug(struct ieee80211_node_table *nt,
1112331766Sken	const uint8_t macaddr[IEEE80211_ADDR_LEN], const char *func, int line)
1113331766Sken#else
1114331766Skenieee80211_find_node_locked(struct ieee80211_node_table *nt,
1115331766Sken	const uint8_t macaddr[IEEE80211_ADDR_LEN])
1116331766Sken#endif
1117331766Sken{
1118331766Sken	struct ieee80211_node *ni;
1119331766Sken	int hash;
1120331766Sken
1121331766Sken	IEEE80211_NODE_LOCK_ASSERT(nt);
1122331766Sken
1123331766Sken	hash = IEEE80211_NODE_HASH(macaddr);
1124331766Sken	LIST_FOREACH(ni, &nt->nt_hash[hash], ni_hash) {
1125331766Sken		if (IEEE80211_ADDR_EQ(ni->ni_macaddr, macaddr)) {
1126331766Sken			ieee80211_ref_node(ni);	/* mark referenced */
1127331766Sken#ifdef IEEE80211_DEBUG_REFCNT
1128331766Sken			IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_NODE,
1129331766Sken			    "%s (%s:%u) %p<%s> refcnt %d\n", __func__,
1130331766Sken			    func, line,
1131331766Sken			    ni, ether_sprintf(ni->ni_macaddr),
1132331766Sken			    ieee80211_node_refcnt(ni));
1133331766Sken#endif
1134331766Sken			return ni;
1135331766Sken		}
1136331766Sken	}
1137331766Sken	return NULL;
1138331766Sken}
1139331766Sken
1140331766Skenstruct ieee80211_node *
1141331766Sken#ifdef IEEE80211_DEBUG_REFCNT
1142331766Skenieee80211_find_node_debug(struct ieee80211_node_table *nt,
1143331766Sken	const uint8_t macaddr[IEEE80211_ADDR_LEN], const char *func, int line)
1144331766Sken#else
1145331766Skenieee80211_find_node(struct ieee80211_node_table *nt,
1146331766Sken	const uint8_t macaddr[IEEE80211_ADDR_LEN])
1147331766Sken#endif
1148331766Sken{
1149331766Sken	struct ieee80211_node *ni;
1150331766Sken
1151331766Sken	IEEE80211_NODE_LOCK(nt);
1152331766Sken	ni = ieee80211_find_node_locked(nt, macaddr);
1153331766Sken	IEEE80211_NODE_UNLOCK(nt);
1154331766Sken	return ni;
1155331766Sken}
1156331766Sken
1157331766Skenstruct ieee80211_node *
1158331766Sken#ifdef IEEE80211_DEBUG_REFCNT
1159331766Skenieee80211_find_vap_node_locked_debug(struct ieee80211_node_table *nt,
1160331766Sken	const struct ieee80211vap *vap,
1161331766Sken	const uint8_t macaddr[IEEE80211_ADDR_LEN], const char *func, int line)
1162331766Sken#else
1163331766Skenieee80211_find_vap_node_locked(struct ieee80211_node_table *nt,
1164331766Sken	const struct ieee80211vap *vap,
1165331766Sken	const uint8_t macaddr[IEEE80211_ADDR_LEN])
1166331766Sken#endif
1167331766Sken{
1168331766Sken	struct ieee80211_node *ni;
1169331766Sken	int hash;
1170331766Sken
1171331766Sken	IEEE80211_NODE_LOCK_ASSERT(nt);
1172331766Sken
1173331766Sken	hash = IEEE80211_NODE_HASH(macaddr);
1174331766Sken	LIST_FOREACH(ni, &nt->nt_hash[hash], ni_hash) {
1175331766Sken		if (ni->ni_vap == vap &&
1176331766Sken		    IEEE80211_ADDR_EQ(ni->ni_macaddr, macaddr)) {
1177331766Sken			ieee80211_ref_node(ni);	/* mark referenced */
1178331766Sken#ifdef IEEE80211_DEBUG_REFCNT
1179331766Sken			IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_NODE,
1180331766Sken			    "%s (%s:%u) %p<%s> refcnt %d\n", __func__,
1181331766Sken			    func, line,
1182331766Sken			    ni, ether_sprintf(ni->ni_macaddr),
1183331766Sken			    ieee80211_node_refcnt(ni));
1184331766Sken#endif
1185331766Sken			return ni;
1186331766Sken		}
1187331766Sken	}
1188331766Sken	return NULL;
1189331766Sken}
1190331766Sken
1191331766Skenstruct ieee80211_node *
1192331766Sken#ifdef IEEE80211_DEBUG_REFCNT
1193331766Skenieee80211_find_vap_node_debug(struct ieee80211_node_table *nt,
1194331766Sken	const struct ieee80211vap *vap,
1195331766Sken	const uint8_t macaddr[IEEE80211_ADDR_LEN], const char *func, int line)
1196331766Sken#else
1197331766Skenieee80211_find_vap_node(struct ieee80211_node_table *nt,
1198331766Sken	const struct ieee80211vap *vap,
1199331766Sken	const uint8_t macaddr[IEEE80211_ADDR_LEN])
1200331766Sken#endif
1201331766Sken{
1202331766Sken	struct ieee80211_node *ni;
1203331766Sken
1204331766Sken	IEEE80211_NODE_LOCK(nt);
1205331766Sken	ni = ieee80211_find_vap_node_locked(nt, vap, macaddr);
1206331766Sken	IEEE80211_NODE_UNLOCK(nt);
1207331766Sken	return ni;
1208331766Sken}
1209331766Sken
1210331766Sken/*
1211331766Sken * Fake up a node; this handles node discovery in adhoc mode.
1212331766Sken * Note that for the driver's benefit we we treat this like
1213331766Sken * an association so the driver has an opportunity to setup
1214331766Sken * it's private state.
1215331766Sken */
1216331766Skenstruct ieee80211_node *
1217331766Skenieee80211_fakeup_adhoc_node(struct ieee80211vap *vap,
1218331766Sken	const uint8_t macaddr[IEEE80211_ADDR_LEN])
1219331766Sken{
1220331766Sken	struct ieee80211_node *ni;
1221331766Sken
1222331766Sken	IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
1223331766Sken	    "%s: mac<%s>\n", __func__, ether_sprintf(macaddr));
1224331766Sken	ni = ieee80211_dup_bss(vap, macaddr);
1225331766Sken	if (ni != NULL) {
1226331766Sken		struct ieee80211com *ic = vap->iv_ic;
1227331766Sken
1228331766Sken		/* XXX no rate negotiation; just dup */
1229331766Sken		ni->ni_rates = vap->iv_bss->ni_rates;
1230331766Sken		if (vap->iv_opmode == IEEE80211_M_AHDEMO) {
1231331766Sken			/*
1232331766Sken			 * In adhoc demo mode there are no management
1233331766Sken			 * frames to use to discover neighbor capabilities,
1234331766Sken			 * so blindly propagate the local configuration
1235331766Sken			 * so we can do interesting things (e.g. use
1236331766Sken			 * WME to disable ACK's).
1237331766Sken			 */
1238331766Sken			if (vap->iv_flags & IEEE80211_F_WME)
1239331766Sken				ni->ni_flags |= IEEE80211_NODE_QOS;
1240331766Sken			if (vap->iv_flags & IEEE80211_F_FF)
1241331766Sken				ni->ni_flags |= IEEE80211_NODE_FF;
1242331766Sken		}
1243331766Sken		if (ic->ic_newassoc != NULL)
1244331766Sken			ic->ic_newassoc(ni, 1);
1245331766Sken		/* XXX not right for 802.1x/WPA */
1246331766Sken		ieee80211_node_authorize(ni);
1247331766Sken	}
1248331766Sken	return ni;
1249331766Sken}
1250331766Sken
1251331766Skenvoid
1252331766Skenieee80211_init_neighbor(struct ieee80211_node *ni,
1253331766Sken	const struct ieee80211_frame *wh,
1254331766Sken	const struct ieee80211_scanparams *sp)
1255331766Sken{
1256331766Sken	ni->ni_esslen = sp->ssid[1];
1257331766Sken	memcpy(ni->ni_essid, sp->ssid + 2, sp->ssid[1]);
1258331766Sken	IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
1259331766Sken	memcpy(ni->ni_tstamp.data, sp->tstamp, sizeof(ni->ni_tstamp));
1260331766Sken	ni->ni_intval = sp->bintval;
1261331766Sken	ni->ni_capinfo = sp->capinfo;
1262331766Sken	ni->ni_chan = ni->ni_ic->ic_curchan;
1263331766Sken	ni->ni_fhdwell = sp->fhdwell;
1264331766Sken	ni->ni_fhindex = sp->fhindex;
1265331766Sken	ni->ni_erp = sp->erp;
1266331766Sken	ni->ni_timoff = sp->timoff;
1267331766Sken
1268331766Sken	if (ieee80211_ies_init(&ni->ni_ies, sp->ies, sp->ies_len)) {
1269331766Sken		ieee80211_ies_expand(&ni->ni_ies);
1270331766Sken		if (ni->ni_ies.ath_ie != NULL)
1271331766Sken			ieee80211_parse_ath(ni, ni->ni_ies.ath_ie);
1272331766Sken	}
1273331766Sken
1274331766Sken	/* NB: must be after ni_chan is setup */
1275331766Sken	ieee80211_setup_rates(ni, sp->rates, sp->xrates,
1276331766Sken		IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
1277331766Sken		IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
1278331766Sken}
1279331766Sken
1280331766Sken/*
1281331766Sken * Do node discovery in adhoc mode on receipt of a beacon
1282331766Sken * or probe response frame.  Note that for the driver's
1283331766Sken * benefit we we treat this like an association so the
1284331766Sken * driver has an opportunity to setup it's private state.
1285331766Sken */
1286331766Skenstruct ieee80211_node *
1287331766Skenieee80211_add_neighbor(struct ieee80211vap *vap,
1288331766Sken	const struct ieee80211_frame *wh,
1289331766Sken	const struct ieee80211_scanparams *sp)
1290331766Sken{
1291331766Sken	struct ieee80211_node *ni;
1292331766Sken
1293331766Sken	IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
1294331766Sken	    "%s: mac<%s>\n", __func__, ether_sprintf(wh->i_addr2));
1295331766Sken	ni = ieee80211_dup_bss(vap, wh->i_addr2);/* XXX alloc_node? */
1296331766Sken	if (ni != NULL) {
1297331766Sken		struct ieee80211com *ic = vap->iv_ic;
1298331766Sken
1299331766Sken		ieee80211_init_neighbor(ni, wh, sp);
1300331766Sken		if (ic->ic_newassoc != NULL)
1301331766Sken			ic->ic_newassoc(ni, 1);
1302331766Sken		/* XXX not right for 802.1x/WPA */
1303331766Sken		ieee80211_node_authorize(ni);
1304331766Sken	}
1305331766Sken	return ni;
1306331766Sken}
1307331766Sken
1308331766Sken#define	IS_CTL(wh) \
1309331766Sken	((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)
1310331766Sken#define	IS_PSPOLL(wh) \
1311331766Sken	((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == IEEE80211_FC0_SUBTYPE_PS_POLL)
1312331766Sken#define	IS_BAR(wh) \
1313331766Sken	((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == IEEE80211_FC0_SUBTYPE_BAR)
1314331766Sken#define	IS_PROBEREQ(wh) \
1315331766Sken	((wh->i_fc[0] & (IEEE80211_FC0_TYPE_MASK|IEEE80211_FC0_SUBTYPE_MASK)) \
1316331766Sken	    == (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_PROBE_REQ))
1317331766Sken#define	IS_BCAST_PROBEREQ(wh) \
1318331766Sken	(IS_PROBEREQ(wh) && IEEE80211_IS_MULTICAST( \
1319331766Sken	    ((const struct ieee80211_frame *)(wh))->i_addr3))
1320331766Sken
1321331766Skenstatic __inline struct ieee80211_node *
1322331766Sken_find_rxnode(struct ieee80211_node_table *nt,
1323331766Sken    const struct ieee80211_frame_min *wh)
1324331766Sken{
1325331766Sken	/* XXX 4-address frames? */
1326331766Sken	if (IS_CTL(wh) && !IS_PSPOLL(wh) && !IS_BAR(wh) /*&& !IS_RTS(ah)*/)
1327331766Sken		return ieee80211_find_node_locked(nt, wh->i_addr1);
1328331766Sken	if (IS_BCAST_PROBEREQ(wh))
1329331766Sken		return NULL;		/* spam bcast probe req to all vap's */
1330331766Sken	return ieee80211_find_node_locked(nt, wh->i_addr2);
1331331766Sken}
1332331766Sken
1333331766Sken/*
1334331766Sken * Locate the node for sender, track state, and then pass the
1335331766Sken * (referenced) node up to the 802.11 layer for its use.  Note
1336331766Sken * we can return NULL if the sender is not in the table.
1337331766Sken */
1338331766Skenstruct ieee80211_node *
1339331766Sken#ifdef IEEE80211_DEBUG_REFCNT
1340331766Skenieee80211_find_rxnode_debug(struct ieee80211com *ic,
1341331766Sken	const struct ieee80211_frame_min *wh, const char *func, int line)
1342331766Sken#else
1343331766Skenieee80211_find_rxnode(struct ieee80211com *ic,
1344331766Sken	const struct ieee80211_frame_min *wh)
1345331766Sken#endif
1346331766Sken{
1347331766Sken	struct ieee80211_node_table *nt;
1348331766Sken	struct ieee80211_node *ni;
1349331766Sken
1350331766Sken	nt = &ic->ic_sta;
1351331766Sken	IEEE80211_NODE_LOCK(nt);
1352331766Sken	ni = _find_rxnode(nt, wh);
1353331766Sken	IEEE80211_NODE_UNLOCK(nt);
1354331766Sken
1355331766Sken	return ni;
1356331766Sken}
1357331766Sken
1358331766Sken/*
1359331766Sken * Like ieee80211_find_rxnode but use the supplied h/w
1360331766Sken * key index as a hint to locate the node in the key
1361331766Sken * mapping table.  If an entry is present at the key
1362331766Sken * index we return it; otherwise do a normal lookup and
1363331766Sken * update the mapping table if the station has a unicast
1364331766Sken * key assigned to it.
1365331766Sken */
1366331766Skenstruct ieee80211_node *
1367331766Sken#ifdef IEEE80211_DEBUG_REFCNT
1368331766Skenieee80211_find_rxnode_withkey_debug(struct ieee80211com *ic,
1369331766Sken	const struct ieee80211_frame_min *wh, ieee80211_keyix keyix,
1370331766Sken	const char *func, int line)
1371331766Sken#else
1372331766Skenieee80211_find_rxnode_withkey(struct ieee80211com *ic,
1373331766Sken	const struct ieee80211_frame_min *wh, ieee80211_keyix keyix)
1374331766Sken#endif
1375331766Sken{
1376331766Sken	struct ieee80211_node_table *nt;
1377331766Sken	struct ieee80211_node *ni;
1378331766Sken
1379331766Sken	nt = &ic->ic_sta;
1380331766Sken	IEEE80211_NODE_LOCK(nt);
1381331766Sken	if (nt->nt_keyixmap != NULL && keyix < nt->nt_keyixmax)
1382331766Sken		ni = nt->nt_keyixmap[keyix];
1383331766Sken	else
1384331766Sken		ni = NULL;
1385331766Sken	if (ni == NULL) {
1386331766Sken		ni = _find_rxnode(nt, wh);
1387331766Sken		if (ni != NULL && nt->nt_keyixmap != NULL) {
1388331766Sken			/*
1389331766Sken			 * If the station has a unicast key cache slot
1390331766Sken			 * assigned update the key->node mapping table.
1391331766Sken			 */
1392331766Sken			keyix = ni->ni_ucastkey.wk_rxkeyix;
1393331766Sken			/* XXX can keyixmap[keyix] != NULL? */
1394331766Sken			if (keyix < nt->nt_keyixmax &&
1395331766Sken			    nt->nt_keyixmap[keyix] == NULL) {
1396331766Sken				IEEE80211_DPRINTF(ni->ni_vap,
1397331766Sken				    IEEE80211_MSG_NODE,
1398331766Sken				    "%s: add key map entry %p<%s> refcnt %d\n",
1399331766Sken				    __func__, ni, ether_sprintf(ni->ni_macaddr),
1400331766Sken				    ieee80211_node_refcnt(ni)+1);
1401331766Sken				nt->nt_keyixmap[keyix] = ieee80211_ref_node(ni);
1402331766Sken			}
1403331766Sken		}
1404331766Sken	} else {
1405331766Sken		if (IS_BCAST_PROBEREQ(wh))
1406331766Sken			ni = NULL;	/* spam bcast probe req to all vap's */
1407331766Sken		else
1408331766Sken			ieee80211_ref_node(ni);
1409331766Sken	}
1410331766Sken	IEEE80211_NODE_UNLOCK(nt);
1411331766Sken
1412331766Sken	return ni;
1413331766Sken}
1414331766Sken#undef IS_BCAST_PROBEREQ
1415331766Sken#undef IS_PROBEREQ
1416331766Sken#undef IS_BAR
1417331766Sken#undef IS_PSPOLL
1418331766Sken#undef IS_CTL
1419331766Sken
1420331766Sken/*
1421331766Sken * Return a reference to the appropriate node for sending
1422331766Sken * a data frame.  This handles node discovery in adhoc networks.
1423331766Sken */
1424331766Skenstruct ieee80211_node *
1425331766Sken#ifdef IEEE80211_DEBUG_REFCNT
1426331766Skenieee80211_find_txnode_debug(struct ieee80211vap *vap,
1427331766Sken	const uint8_t macaddr[IEEE80211_ADDR_LEN],
1428331766Sken	const char *func, int line)
1429331766Sken#else
1430331766Skenieee80211_find_txnode(struct ieee80211vap *vap,
1431331766Sken	const uint8_t macaddr[IEEE80211_ADDR_LEN])
1432331766Sken#endif
1433331766Sken{
1434331766Sken	struct ieee80211_node_table *nt = &vap->iv_ic->ic_sta;
1435331766Sken	struct ieee80211_node *ni;
1436331766Sken
1437331766Sken	/*
1438331766Sken	 * The destination address should be in the node table
1439331766Sken	 * unless this is a multicast/broadcast frame.  We can
1440331766Sken	 * also optimize station mode operation, all frames go
1441331766Sken	 * to the bss node.
1442331766Sken	 */
1443331766Sken	/* XXX can't hold lock across dup_bss 'cuz of recursive locking */
1444331766Sken	IEEE80211_NODE_LOCK(nt);
1445331766Sken	if (vap->iv_opmode == IEEE80211_M_STA ||
1446331766Sken	    vap->iv_opmode == IEEE80211_M_WDS ||
1447331766Sken	    IEEE80211_IS_MULTICAST(macaddr))
1448331766Sken		ni = ieee80211_ref_node(vap->iv_bss);
1449331766Sken	else {
1450331766Sken		ni = ieee80211_find_node_locked(nt, macaddr);
1451331766Sken		if (vap->iv_opmode == IEEE80211_M_HOSTAP &&
1452331766Sken		    (ni != NULL && ni->ni_associd == 0)) {
1453331766Sken			/*
1454331766Sken			 * Station is not associated; don't permit the
1455331766Sken			 * data frame to be sent by returning NULL.  This
1456331766Sken			 * is kinda a kludge but the least intrusive way
1457331766Sken			 * to add this check into all drivers.
1458331766Sken			 */
1459331766Sken			ieee80211_unref_node(&ni);	/* NB: null's ni */
1460331766Sken		}
1461331766Sken	}
1462331766Sken	IEEE80211_NODE_UNLOCK(nt);
1463331766Sken
1464331766Sken	if (ni == NULL) {
1465331766Sken		if (vap->iv_opmode == IEEE80211_M_IBSS ||
1466331766Sken		    vap->iv_opmode == IEEE80211_M_AHDEMO) {
1467331766Sken			/*
1468331766Sken			 * In adhoc mode cons up a node for the destination.
1469331766Sken			 * Note that we need an additional reference for the
1470331766Sken			 * caller to be consistent with
1471331766Sken			 * ieee80211_find_node_locked.
1472331766Sken			 */
1473331766Sken			ni = ieee80211_fakeup_adhoc_node(vap, macaddr);
1474331766Sken			if (ni != NULL)
1475331766Sken				(void) ieee80211_ref_node(ni);
1476331766Sken		} else {
1477331766Sken			IEEE80211_NOTE_MAC(vap, IEEE80211_MSG_OUTPUT, macaddr,
1478331766Sken			    "no node, discard frame (%s)", __func__);
1479331766Sken			vap->iv_stats.is_tx_nonode++;
1480331766Sken		}
1481331766Sken	}
1482331766Sken	return ni;
1483331766Sken}
1484331766Sken
1485331766Skenstatic void
1486331766Sken_ieee80211_free_node(struct ieee80211_node *ni)
1487331766Sken{
1488331766Sken	struct ieee80211vap *vap = ni->ni_vap;
1489331766Sken	struct ieee80211_node_table *nt = ni->ni_table;
1490331766Sken
1491331766Sken	IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
1492331766Sken		"%s %p<%s> in %s table\n", __func__, ni,
1493331766Sken		ether_sprintf(ni->ni_macaddr),
1494331766Sken		nt != NULL ? nt->nt_name : "<gone>");
1495331766Sken
1496331766Sken	if (vap->iv_aid_bitmap != NULL)
1497331766Sken		IEEE80211_AID_CLR(vap, ni->ni_associd);
1498331766Sken	if (nt != NULL) {
1499331766Sken		TAILQ_REMOVE(&nt->nt_node, ni, ni_list);
1500331766Sken		LIST_REMOVE(ni, ni_hash);
1501331766Sken	}
1502331766Sken	vap->iv_ic->ic_node_free(ni);
1503331766Sken}
1504331766Sken
1505331766Skenvoid
1506331766Sken#ifdef IEEE80211_DEBUG_REFCNT
1507331766Skenieee80211_free_node_debug(struct ieee80211_node *ni, const char *func, int line)
1508331766Sken#else
1509331766Skenieee80211_free_node(struct ieee80211_node *ni)
1510331766Sken#endif
1511331766Sken{
1512331766Sken	struct ieee80211_node_table *nt = ni->ni_table;
1513331766Sken
1514331766Sken#ifdef IEEE80211_DEBUG_REFCNT
1515331766Sken	IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_NODE,
1516331766Sken		"%s (%s:%u) %p<%s> refcnt %d\n", __func__, func, line, ni,
1517331766Sken		 ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)-1);
1518331766Sken#endif
1519331766Sken	if (nt != NULL) {
1520331766Sken		IEEE80211_NODE_LOCK(nt);
1521331766Sken		if (ieee80211_node_dectestref(ni)) {
1522331766Sken			/*
1523331766Sken			 * Last reference, reclaim state.
1524331766Sken			 */
1525331766Sken			_ieee80211_free_node(ni);
1526331766Sken		} else if (ieee80211_node_refcnt(ni) == 1 &&
1527331766Sken		    nt->nt_keyixmap != NULL) {
1528331766Sken			ieee80211_keyix keyix;
1529331766Sken			/*
1530331766Sken			 * Check for a last reference in the key mapping table.
1531331766Sken			 */
1532331766Sken			keyix = ni->ni_ucastkey.wk_rxkeyix;
1533331766Sken			if (keyix < nt->nt_keyixmax &&
1534331766Sken			    nt->nt_keyixmap[keyix] == ni) {
1535331766Sken				IEEE80211_DPRINTF(ni->ni_vap,
1536331766Sken				    IEEE80211_MSG_NODE,
1537331766Sken				    "%s: %p<%s> clear key map entry", __func__,
1538331766Sken				    ni, ether_sprintf(ni->ni_macaddr));
1539331766Sken				nt->nt_keyixmap[keyix] = NULL;
1540331766Sken				ieee80211_node_decref(ni); /* XXX needed? */
1541331766Sken				_ieee80211_free_node(ni);
1542331766Sken			}
1543331766Sken		}
1544331766Sken		IEEE80211_NODE_UNLOCK(nt);
1545331766Sken	} else {
1546331766Sken		if (ieee80211_node_dectestref(ni))
1547331766Sken			_ieee80211_free_node(ni);
1548331766Sken	}
1549331766Sken}
1550331766Sken
1551331766Sken/*
1552331766Sken * Reclaim a unicast key and clear any key cache state.
1553331766Sken */
1554331766Skenint
1555331766Skenieee80211_node_delucastkey(struct ieee80211_node *ni)
1556331766Sken{
1557331766Sken	struct ieee80211vap *vap = ni->ni_vap;
1558331766Sken	/* XXX is ni_table safe? */
1559331766Sken	struct ieee80211_node_table *nt = &ni->ni_ic->ic_sta;
1560331766Sken	struct ieee80211_node *nikey;
1561331766Sken	ieee80211_keyix keyix;
1562331766Sken	int isowned, status;
1563331766Sken
1564331766Sken	/*
1565331766Sken	 * NB: We must beware of LOR here; deleting the key
1566331766Sken	 * can cause the crypto layer to block traffic updates
1567331766Sken	 * which can generate a LOR against the node table lock;
1568331766Sken	 * grab it here and stash the key index for our use below.
1569331766Sken	 *
1570331766Sken	 * Must also beware of recursion on the node table lock.
1571331766Sken	 * When called from node_cleanup we may already have
1572331766Sken	 * the node table lock held.  Unfortunately there's no
1573331766Sken	 * way to separate out this path so we must do this
1574331766Sken	 * conditionally.
1575331766Sken	 */
1576331766Sken	isowned = IEEE80211_NODE_IS_LOCKED(nt);
1577331766Sken	if (!isowned)
1578331766Sken		IEEE80211_NODE_LOCK(nt);
1579331766Sken	keyix = ni->ni_ucastkey.wk_rxkeyix;
1580331766Sken	status = ieee80211_crypto_delkey(vap, &ni->ni_ucastkey);
1581331766Sken	if (nt->nt_keyixmap != NULL && keyix < nt->nt_keyixmax) {
1582331766Sken		nikey = nt->nt_keyixmap[keyix];
1583331766Sken		nt->nt_keyixmap[keyix] = NULL;;
1584331766Sken	} else
1585331766Sken		nikey = NULL;
1586331766Sken	if (!isowned)
1587331766Sken		IEEE80211_NODE_UNLOCK(nt);
1588331766Sken
1589331766Sken	if (nikey != NULL) {
1590331766Sken		KASSERT(nikey == ni,
1591331766Sken			("key map out of sync, ni %p nikey %p", ni, nikey));
1592331766Sken		IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE,
1593331766Sken			"%s: delete key map entry %p<%s> refcnt %d\n",
1594331766Sken			__func__, ni, ether_sprintf(ni->ni_macaddr),
1595331766Sken			ieee80211_node_refcnt(ni)-1);
1596331766Sken		ieee80211_free_node(ni);
1597331766Sken	}
1598331766Sken	return status;
1599331766Sken}
1600331766Sken
1601331766Sken/*
1602331766Sken * Reclaim a node.  If this is the last reference count then
1603331766Sken * do the normal free work.  Otherwise remove it from the node
1604331766Sken * table and mark it gone by clearing the back-reference.
1605331766Sken */
1606331766Skenstatic void
1607331766Skennode_reclaim(struct ieee80211_node_table *nt, struct ieee80211_node *ni)
1608331766Sken{
1609331766Sken	ieee80211_keyix keyix;
1610331766Sken
1611331766Sken	IEEE80211_NODE_LOCK_ASSERT(nt);
1612331766Sken
1613331766Sken	IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_NODE,
1614331766Sken		"%s: remove %p<%s> from %s table, refcnt %d\n",
1615331766Sken		__func__, ni, ether_sprintf(ni->ni_macaddr),
1616331766Sken		nt->nt_name, ieee80211_node_refcnt(ni)-1);
1617331766Sken	/*
1618331766Sken	 * Clear any entry in the unicast key mapping table.
1619331766Sken	 * We need to do it here so rx lookups don't find it
1620331766Sken	 * in the mapping table even if it's not in the hash
1621331766Sken	 * table.  We cannot depend on the mapping table entry
1622331766Sken	 * being cleared because the node may not be free'd.
1623331766Sken	 */
1624331766Sken	keyix = ni->ni_ucastkey.wk_rxkeyix;
1625331766Sken	if (nt->nt_keyixmap != NULL && keyix < nt->nt_keyixmax &&
1626331766Sken	    nt->nt_keyixmap[keyix] == ni) {
1627331766Sken		IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_NODE,
1628331766Sken			"%s: %p<%s> clear key map entry\n",
1629331766Sken			__func__, ni, ether_sprintf(ni->ni_macaddr));
1630331766Sken		nt->nt_keyixmap[keyix] = NULL;
1631331766Sken		ieee80211_node_decref(ni);	/* NB: don't need free */
1632331766Sken	}
1633331766Sken	if (!ieee80211_node_dectestref(ni)) {
1634331766Sken		/*
1635331766Sken		 * Other references are present, just remove the
1636331766Sken		 * node from the table so it cannot be found.  When
1637331766Sken		 * the references are dropped storage will be
1638331766Sken		 * reclaimed.
1639331766Sken		 */
1640331766Sken		TAILQ_REMOVE(&nt->nt_node, ni, ni_list);
1641331766Sken		LIST_REMOVE(ni, ni_hash);
1642331766Sken		ni->ni_table = NULL;		/* clear reference */
1643331766Sken	} else
1644331766Sken		_ieee80211_free_node(ni);
1645331766Sken}
1646331766Sken
1647331766Sken/*
1648331766Sken * Reclaim a (bss) node.  Decrement the refcnt and reclaim
1649331766Sken * the node if the only other reference to it is in the sta
1650331766Sken * table.  This is effectively ieee80211_free_node followed
1651331766Sken * by node_reclaim when the refcnt is 1 (after the free).
1652331766Sken */
1653331766Skenstatic void
1654331766Skenieee80211_node_reclaim(struct ieee80211_node *ni)
1655331766Sken{
1656331766Sken	struct ieee80211_node_table *nt = ni->ni_table;
1657331766Sken
1658331766Sken	KASSERT(nt != NULL, ("reclaim node not in table"));
1659331766Sken
1660331766Sken#ifdef IEEE80211_DEBUG_REFCNT
1661331766Sken	IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_NODE,
1662331766Sken		"%s %p<%s> refcnt %d\n", __func__, ni,
1663331766Sken		 ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)-1);
1664331766Sken#endif
1665331766Sken	IEEE80211_NODE_LOCK(nt);
1666331766Sken	if (ieee80211_node_dectestref(ni)) {
1667331766Sken		/*
1668331766Sken		 * Last reference, reclaim state.
1669331766Sken		 */
1670331766Sken		_ieee80211_free_node(ni);
1671331766Sken		nt = NULL;
1672331766Sken	} else if (ieee80211_node_refcnt(ni) == 1 &&
1673331766Sken	    nt->nt_keyixmap != NULL) {
1674331766Sken		ieee80211_keyix keyix;
1675331766Sken		/*
1676331766Sken		 * Check for a last reference in the key mapping table.
1677331766Sken		 */
1678331766Sken		keyix = ni->ni_ucastkey.wk_rxkeyix;
1679331766Sken		if (keyix < nt->nt_keyixmax &&
1680331766Sken		    nt->nt_keyixmap[keyix] == ni) {
1681331766Sken			IEEE80211_DPRINTF(ni->ni_vap,
1682331766Sken			    IEEE80211_MSG_NODE,
1683331766Sken			    "%s: %p<%s> clear key map entry", __func__,
1684331766Sken			    ni, ether_sprintf(ni->ni_macaddr));
1685331766Sken			nt->nt_keyixmap[keyix] = NULL;
1686331766Sken			ieee80211_node_decref(ni); /* XXX needed? */
1687331766Sken			_ieee80211_free_node(ni);
1688331766Sken			nt = NULL;
1689331766Sken		}
1690331766Sken	}
1691331766Sken	if (nt != NULL && ieee80211_node_refcnt(ni) == 1) {
1692331766Sken		/*
1693331766Sken		 * Last reference is in the sta table; complete
1694331766Sken		 * the reclaim.  This handles bss nodes being
1695331766Sken		 * recycled: the node has two references, one for
1696331766Sken		 * iv_bss and one for the table.  After dropping
1697331766Sken		 * the iv_bss ref above we need to reclaim the sta
1698331766Sken		 * table reference.
1699331766Sken		 */
1700331766Sken		ieee80211_node_decref(ni);	/* NB: be pendantic */
1701331766Sken		_ieee80211_free_node(ni);
1702331766Sken	}
1703331766Sken	IEEE80211_NODE_UNLOCK(nt);
1704331766Sken}
1705331766Sken
1706331766Sken/*
1707331766Sken * Node table support.
1708331766Sken */
1709331766Sken
1710331766Skenstatic void
1711331766Skenieee80211_node_table_init(struct ieee80211com *ic,
1712331766Sken	struct ieee80211_node_table *nt,
1713331766Sken	const char *name, int inact, int keyixmax)
1714331766Sken{
1715331766Sken	struct ifnet *ifp = ic->ic_ifp;
1716331766Sken
1717331766Sken	nt->nt_ic = ic;
1718331766Sken	IEEE80211_NODE_LOCK_INIT(nt, ifp->if_xname);
1719331766Sken	IEEE80211_NODE_ITERATE_LOCK_INIT(nt, ifp->if_xname);
1720331766Sken	TAILQ_INIT(&nt->nt_node);
1721331766Sken	nt->nt_name = name;
1722331766Sken	nt->nt_scangen = 1;
1723331766Sken	nt->nt_inact_init = inact;
1724331766Sken	nt->nt_keyixmax = keyixmax;
1725331766Sken	if (nt->nt_keyixmax > 0) {
1726331766Sken		MALLOC(nt->nt_keyixmap, struct ieee80211_node **,
1727331766Sken			keyixmax * sizeof(struct ieee80211_node *),
1728331766Sken			M_80211_NODE, M_NOWAIT | M_ZERO);
1729331766Sken		if (nt->nt_keyixmap == NULL)
1730331766Sken			if_printf(ic->ic_ifp,
1731331766Sken			    "Cannot allocate key index map with %u entries\n",
1732331766Sken			    keyixmax);
1733331766Sken	} else
1734331766Sken		nt->nt_keyixmap = NULL;
1735331766Sken}
1736331766Sken
1737331766Skenstatic void
1738331766Skenieee80211_node_table_reset(struct ieee80211_node_table *nt,
1739331766Sken	struct ieee80211vap *match)
1740331766Sken{
1741331766Sken	struct ieee80211_node *ni, *next;
1742331766Sken
1743331766Sken	IEEE80211_NODE_LOCK(nt);
1744331766Sken	TAILQ_FOREACH_SAFE(ni, &nt->nt_node, ni_list, next) {
1745331766Sken		if (match != NULL && ni->ni_vap != match)
1746331766Sken			continue;
1747331766Sken		/* XXX can this happen?  if so need's work */
1748331766Sken		if (ni->ni_associd != 0) {
1749331766Sken			struct ieee80211vap *vap = ni->ni_vap;
1750331766Sken
1751331766Sken			if (vap->iv_auth->ia_node_leave != NULL)
1752331766Sken				vap->iv_auth->ia_node_leave(ni);
1753331766Sken			if (vap->iv_aid_bitmap != NULL)
1754331766Sken				IEEE80211_AID_CLR(vap, ni->ni_associd);
1755331766Sken		}
1756331766Sken		ni->ni_wdsvap = NULL;		/* clear reference */
1757331766Sken		node_reclaim(nt, ni);
1758331766Sken	}
1759331766Sken	if (match != NULL && match->iv_opmode == IEEE80211_M_WDS) {
1760331766Sken		/*
1761331766Sken		 * Make a separate pass to clear references to this vap
1762331766Sken		 * held by DWDS entries.  They will not be matched above
1763331766Sken		 * because ni_vap will point to the ap vap but we still
1764331766Sken		 * need to clear ni_wdsvap when the WDS vap is destroyed
1765331766Sken		 * and/or reset.
1766331766Sken		 */
1767331766Sken		TAILQ_FOREACH_SAFE(ni, &nt->nt_node, ni_list, next)
1768331766Sken			if (ni->ni_wdsvap == match)
1769331766Sken				ni->ni_wdsvap = NULL;
1770331766Sken	}
1771331766Sken	IEEE80211_NODE_UNLOCK(nt);
1772331766Sken}
1773331766Sken
1774331766Skenstatic void
1775331766Skenieee80211_node_table_cleanup(struct ieee80211_node_table *nt)
1776331766Sken{
1777331766Sken	ieee80211_node_table_reset(nt, NULL);
1778331766Sken	if (nt->nt_keyixmap != NULL) {
1779331766Sken#ifdef DIAGNOSTIC
1780331766Sken		/* XXX verify all entries are NULL */
1781331766Sken		int i;
1782331766Sken		for (i = 0; i < nt->nt_keyixmax; i++)
1783331766Sken			if (nt->nt_keyixmap[i] != NULL)
1784331766Sken				printf("%s: %s[%u] still active\n", __func__,
1785331766Sken					nt->nt_name, i);
1786331766Sken#endif
1787331766Sken		FREE(nt->nt_keyixmap, M_80211_NODE);
1788331766Sken		nt->nt_keyixmap = NULL;
1789331766Sken	}
1790331766Sken	IEEE80211_NODE_ITERATE_LOCK_DESTROY(nt);
1791331766Sken	IEEE80211_NODE_LOCK_DESTROY(nt);
1792331766Sken}
1793331766Sken
1794331766Sken/*
1795331766Sken * Timeout inactive stations and do related housekeeping.
1796331766Sken * Note that we cannot hold the node lock while sending a
1797331766Sken * frame as this would lead to a LOR.  Instead we use a
1798331766Sken * generation number to mark nodes that we've scanned and
1799331766Sken * drop the lock and restart a scan if we have to time out
1800331766Sken * a node.  Since we are single-threaded by virtue of
1801331766Sken * controlling the inactivity timer we can be sure this will
1802331766Sken * process each node only once.
1803331766Sken */
1804331766Skenstatic void
1805331766Skenieee80211_timeout_stations(struct ieee80211com *ic)
1806331766Sken{
1807331766Sken	struct ieee80211_node_table *nt = &ic->ic_sta;
1808331766Sken	struct ieee80211vap *vap;
1809331766Sken	struct ieee80211_node *ni;
1810331766Sken	int gen = 0;
1811331766Sken
1812331766Sken	IEEE80211_NODE_ITERATE_LOCK(nt);
1813331766Sken	gen = ++nt->nt_scangen;
1814331766Skenrestart:
1815331766Sken	IEEE80211_NODE_LOCK(nt);
1816331766Sken	TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
1817331766Sken		if (ni->ni_scangen == gen)	/* previously handled */
1818331766Sken			continue;
1819331766Sken		ni->ni_scangen = gen;
1820331766Sken		/*
1821331766Sken		 * Ignore entries for which have yet to receive an
1822331766Sken		 * authentication frame.  These are transient and
1823331766Sken		 * will be reclaimed when the last reference to them
1824331766Sken		 * goes away (when frame xmits complete).
1825331766Sken		 */
1826331766Sken		vap = ni->ni_vap;
1827331766Sken		/*
1828331766Sken		 * Only process stations when in RUN state.  This
1829331766Sken		 * insures, for example, that we don't timeout an
1830331766Sken		 * inactive station during CAC.  Note that CSA state
1831331766Sken		 * is actually handled in ieee80211_node_timeout as
1832331766Sken		 * it applies to more than timeout processing.
1833331766Sken		 */
1834331766Sken		if (vap->iv_state != IEEE80211_S_RUN)
1835331766Sken			continue;
1836331766Sken		/* XXX can vap be NULL? */
1837331766Sken		if ((vap->iv_opmode == IEEE80211_M_HOSTAP ||
1838331766Sken		     vap->iv_opmode == IEEE80211_M_STA) &&
1839331766Sken		    (ni->ni_flags & IEEE80211_NODE_AREF) == 0)
1840331766Sken			continue;
1841331766Sken		/*
1842331766Sken		 * Free fragment if not needed anymore
1843331766Sken		 * (last fragment older than 1s).
1844331766Sken		 * XXX doesn't belong here, move to node_age
1845331766Sken		 */
1846331766Sken		if (ni->ni_rxfrag[0] != NULL &&
1847331766Sken		    ticks > ni->ni_rxfragstamp + hz) {
1848331766Sken			m_freem(ni->ni_rxfrag[0]);
1849331766Sken			ni->ni_rxfrag[0] = NULL;
1850331766Sken		}
1851331766Sken		if (ni->ni_inact > 0)
1852331766Sken			ni->ni_inact--;
1853331766Sken		/*
1854331766Sken		 * Special case ourself; we may be idle for extended periods
1855331766Sken		 * of time and regardless reclaiming our state is wrong.
1856331766Sken		 * XXX run ic_node_age
1857331766Sken		 */
1858331766Sken		if (ni == vap->iv_bss)
1859331766Sken			continue;
1860331766Sken		if (ni->ni_associd != 0 ||
1861331766Sken		    (vap->iv_opmode == IEEE80211_M_IBSS ||
1862331766Sken		     vap->iv_opmode == IEEE80211_M_AHDEMO)) {
1863331766Sken			/*
1864331766Sken			 * Age/drain resources held by the station.
1865331766Sken			 */
1866331766Sken			ic->ic_node_age(ni);
1867331766Sken			/*
1868331766Sken			 * Probe the station before time it out.  We
1869331766Sken			 * send a null data frame which may not be
1870331766Sken			 * universally supported by drivers (need it
1871331766Sken			 * for ps-poll support so it should be...).
1872331766Sken			 *
1873331766Sken			 * XXX don't probe the station unless we've
1874331766Sken			 *     received a frame from them (and have
1875331766Sken			 *     some idea of the rates they are capable
1876331766Sken			 *     of); this will get fixed more properly
1877331766Sken			 *     soon with better handling of the rate set.
1878331766Sken			 */
1879331766Sken			if ((vap->iv_flags_ext & IEEE80211_FEXT_INACT) &&
1880331766Sken			    (0 < ni->ni_inact &&
1881331766Sken			     ni->ni_inact <= vap->iv_inact_probe) &&
1882331766Sken			    ni->ni_rates.rs_nrates != 0) {
1883331766Sken				IEEE80211_NOTE(vap,
1884331766Sken				    IEEE80211_MSG_INACT | IEEE80211_MSG_NODE,
1885331766Sken				    ni, "%s",
1886331766Sken				    "probe station due to inactivity");
1887331766Sken				/*
1888331766Sken				 * Grab a reference before unlocking the table
1889331766Sken				 * so the node cannot be reclaimed before we
1890331766Sken				 * send the frame. ieee80211_send_nulldata
1891331766Sken				 * understands we've done this and reclaims the
1892331766Sken				 * ref for us as needed.
1893331766Sken				 */
1894331766Sken				ieee80211_ref_node(ni);
1895331766Sken				IEEE80211_NODE_UNLOCK(nt);
1896331766Sken				ieee80211_send_nulldata(ni);
1897331766Sken				/* XXX stat? */
1898331766Sken				goto restart;
1899331766Sken			}
1900331766Sken		}
1901331766Sken		if ((vap->iv_flags_ext & IEEE80211_FEXT_INACT) &&
1902331766Sken		    ni->ni_inact <= 0) {
1903331766Sken			IEEE80211_NOTE(vap,
1904331766Sken			    IEEE80211_MSG_INACT | IEEE80211_MSG_NODE, ni,
1905331766Sken			    "station timed out due to inactivity "
1906331766Sken			    "(refcnt %u)", ieee80211_node_refcnt(ni));
1907331766Sken			/*
1908331766Sken			 * Send a deauthenticate frame and drop the station.
1909331766Sken			 * This is somewhat complicated due to reference counts
1910331766Sken			 * and locking.  At this point a station will typically
1911331766Sken			 * have a reference count of 1.  ieee80211_node_leave
1912331766Sken			 * will do a "free" of the node which will drop the
1913331766Sken			 * reference count.  But in the meantime a reference
1914331766Sken			 * wil be held by the deauth frame.  The actual reclaim
1915331766Sken			 * of the node will happen either after the tx is
1916331766Sken			 * completed or by ieee80211_node_leave.
1917331766Sken			 *
1918331766Sken			 * Separately we must drop the node lock before sending
1919331766Sken			 * in case the driver takes a lock, as this can result
1920331766Sken			 * in a LOR between the node lock and the driver lock.
1921331766Sken			 */
1922331766Sken			ieee80211_ref_node(ni);
1923331766Sken			IEEE80211_NODE_UNLOCK(nt);
1924331766Sken			if (ni->ni_associd != 0) {
1925331766Sken				IEEE80211_SEND_MGMT(ni,
1926331766Sken				    IEEE80211_FC0_SUBTYPE_DEAUTH,
1927				    IEEE80211_REASON_AUTH_EXPIRE);
1928			}
1929			ieee80211_node_leave(ni);
1930			ieee80211_free_node(ni);
1931			vap->iv_stats.is_node_timeout++;
1932			goto restart;
1933		}
1934	}
1935	IEEE80211_NODE_UNLOCK(nt);
1936
1937	IEEE80211_NODE_ITERATE_UNLOCK(nt);
1938}
1939
1940/*
1941 * Aggressively reclaim resources.  This should be used
1942 * only in a critical situation to reclaim mbuf resources.
1943 */
1944void
1945ieee80211_drain(struct ieee80211com *ic)
1946{
1947	struct ieee80211_node_table *nt = &ic->ic_sta;
1948	struct ieee80211vap *vap;
1949	struct ieee80211_node *ni;
1950
1951	IEEE80211_NODE_LOCK(nt);
1952	TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
1953		/*
1954		 * Ignore entries for which have yet to receive an
1955		 * authentication frame.  These are transient and
1956		 * will be reclaimed when the last reference to them
1957		 * goes away (when frame xmits complete).
1958		 */
1959		vap = ni->ni_vap;
1960		/*
1961		 * Only process stations when in RUN state.  This
1962		 * insures, for example, that we don't timeout an
1963		 * inactive station during CAC.  Note that CSA state
1964		 * is actually handled in ieee80211_node_timeout as
1965		 * it applies to more than timeout processing.
1966		 */
1967		if (vap->iv_state != IEEE80211_S_RUN)
1968			continue;
1969		/* XXX can vap be NULL? */
1970		if ((vap->iv_opmode == IEEE80211_M_HOSTAP ||
1971		     vap->iv_opmode == IEEE80211_M_STA) &&
1972		    (ni->ni_flags & IEEE80211_NODE_AREF) == 0)
1973			continue;
1974		/*
1975		 * Free fragments.
1976		 * XXX doesn't belong here, move to node_drain
1977		 */
1978		if (ni->ni_rxfrag[0] != NULL) {
1979			m_freem(ni->ni_rxfrag[0]);
1980			ni->ni_rxfrag[0] = NULL;
1981		}
1982		/*
1983		 * Drain resources held by the station.
1984		 */
1985		ic->ic_node_drain(ni);
1986	}
1987	IEEE80211_NODE_UNLOCK(nt);
1988}
1989
1990/*
1991 * Per-ieee80211com inactivity timer callback.
1992 */
1993void
1994ieee80211_node_timeout(void *arg)
1995{
1996	struct ieee80211com *ic = arg;
1997
1998	/*
1999	 * Defer timeout processing if a channel switch is pending.
2000	 * We typically need to be mute so not doing things that
2001	 * might generate frames is good to handle in one place.
2002	 * Supressing the station timeout processing may extend the
2003	 * lifetime of inactive stations (by not decrementing their
2004	 * idle counters) but this should be ok unless the CSA is
2005	 * active for an unusually long time.
2006	 */
2007	if ((ic->ic_flags & IEEE80211_F_CSAPENDING) == 0) {
2008		ieee80211_scan_timeout(ic);
2009		ieee80211_timeout_stations(ic);
2010
2011		IEEE80211_LOCK(ic);
2012		ieee80211_erp_timeout(ic);
2013		ieee80211_ht_timeout(ic);
2014		IEEE80211_UNLOCK(ic);
2015	}
2016	callout_reset(&ic->ic_inact, IEEE80211_INACT_WAIT*hz,
2017		ieee80211_node_timeout, ic);
2018}
2019
2020void
2021ieee80211_iterate_nodes(struct ieee80211_node_table *nt,
2022	ieee80211_iter_func *f, void *arg)
2023{
2024	struct ieee80211_node *ni;
2025	u_int gen;
2026
2027	IEEE80211_NODE_ITERATE_LOCK(nt);
2028	gen = ++nt->nt_scangen;
2029restart:
2030	IEEE80211_NODE_LOCK(nt);
2031	TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
2032		if (ni->ni_scangen != gen) {
2033			ni->ni_scangen = gen;
2034			(void) ieee80211_ref_node(ni);
2035			IEEE80211_NODE_UNLOCK(nt);
2036			(*f)(arg, ni);
2037			ieee80211_free_node(ni);
2038			goto restart;
2039		}
2040	}
2041	IEEE80211_NODE_UNLOCK(nt);
2042
2043	IEEE80211_NODE_ITERATE_UNLOCK(nt);
2044}
2045
2046void
2047ieee80211_dump_node(struct ieee80211_node_table *nt, struct ieee80211_node *ni)
2048{
2049	printf("0x%p: mac %s refcnt %d\n", ni,
2050		ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni));
2051	printf("\tscangen %u authmode %u flags 0x%x\n",
2052		ni->ni_scangen, ni->ni_authmode, ni->ni_flags);
2053	printf("\tassocid 0x%x txpower %u vlan %u\n",
2054		ni->ni_associd, ni->ni_txpower, ni->ni_vlan);
2055	printf("\ttxseq %u rxseq %u fragno %u rxfragstamp %u\n",
2056		ni->ni_txseqs[IEEE80211_NONQOS_TID],
2057		ni->ni_rxseqs[IEEE80211_NONQOS_TID] >> IEEE80211_SEQ_SEQ_SHIFT,
2058		ni->ni_rxseqs[IEEE80211_NONQOS_TID] & IEEE80211_SEQ_FRAG_MASK,
2059		ni->ni_rxfragstamp);
2060	printf("\trstamp %u rssi %d noise %d intval %u capinfo 0x%x\n",
2061		ni->ni_rstamp, node_getrssi(ni), ni->ni_noise,
2062		ni->ni_intval, ni->ni_capinfo);
2063	printf("\tbssid %s essid \"%.*s\" channel %u:0x%x\n",
2064		ether_sprintf(ni->ni_bssid),
2065		ni->ni_esslen, ni->ni_essid,
2066		ni->ni_chan->ic_freq, ni->ni_chan->ic_flags);
2067	printf("\tinact %u txrate %u\n",
2068		ni->ni_inact, ni->ni_txrate);
2069	printf("\thtcap %x htparam %x htctlchan %u ht2ndchan %u\n",
2070		ni->ni_htcap, ni->ni_htparam,
2071		ni->ni_htctlchan, ni->ni_ht2ndchan);
2072	printf("\thtopmode %x htstbc %x chw %u\n",
2073		ni->ni_htopmode, ni->ni_htstbc, ni->ni_chw);
2074}
2075
2076void
2077ieee80211_dump_nodes(struct ieee80211_node_table *nt)
2078{
2079	ieee80211_iterate_nodes(nt,
2080		(ieee80211_iter_func *) ieee80211_dump_node, nt);
2081}
2082
2083void
2084ieee80211_notify_erp(struct ieee80211com *ic)
2085{
2086	struct ieee80211vap *vap;
2087
2088	IEEE80211_LOCK_ASSERT(ic);
2089
2090	TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next)
2091		if (vap->iv_opmode == IEEE80211_M_HOSTAP)
2092			ieee80211_beacon_notify(vap, IEEE80211_BEACON_ERP);
2093}
2094
2095/*
2096 * Handle a station joining an 11g network.
2097 */
2098static void
2099ieee80211_node_join_11g(struct ieee80211_node *ni)
2100{
2101	struct ieee80211com *ic = ni->ni_ic;
2102
2103	IEEE80211_LOCK_ASSERT(ic);
2104
2105	/*
2106	 * Station isn't capable of short slot time.  Bump
2107	 * the count of long slot time stations and disable
2108	 * use of short slot time.  Note that the actual switch
2109	 * over to long slot time use may not occur until the
2110	 * next beacon transmission (per sec. 7.3.1.4 of 11g).
2111	 */
2112	if ((ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME) == 0) {
2113		ic->ic_longslotsta++;
2114		IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ASSOC, ni,
2115		    "station needs long slot time, count %d",
2116		    ic->ic_longslotsta);
2117		/* XXX vap's w/ conflicting needs won't work */
2118		if (!IEEE80211_IS_CHAN_108G(ic->ic_bsschan)) {
2119			/*
2120			 * Don't force slot time when switched to turbo
2121			 * mode as non-ERP stations won't be present; this
2122			 * need only be done when on the normal G channel.
2123			 */
2124			ieee80211_set_shortslottime(ic, 0);
2125		}
2126	}
2127	/*
2128	 * If the new station is not an ERP station
2129	 * then bump the counter and enable protection
2130	 * if configured.
2131	 */
2132	if (!ieee80211_iserp_rateset(&ni->ni_rates)) {
2133		ic->ic_nonerpsta++;
2134		IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ASSOC, ni,
2135		    "station is !ERP, %d non-ERP stations associated",
2136		    ic->ic_nonerpsta);
2137		/*
2138		 * If station does not support short preamble
2139		 * then we must enable use of Barker preamble.
2140		 */
2141		if ((ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE) == 0) {
2142			IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ASSOC, ni,
2143			    "%s", "station needs long preamble");
2144			ic->ic_flags |= IEEE80211_F_USEBARKER;
2145			ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE;
2146		}
2147		/*
2148		 * If protection is configured and this is the first
2149		 * indication we should use protection, enable it.
2150		 */
2151		if (ic->ic_protmode != IEEE80211_PROT_NONE &&
2152		    ic->ic_nonerpsta == 1 &&
2153		    (ic->ic_flags_ext & IEEE80211_FEXT_NONERP_PR) == 0) {
2154			IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_ASSOC,
2155			    "%s: enable use of protection\n", __func__);
2156			ic->ic_flags |= IEEE80211_F_USEPROT;
2157			ieee80211_notify_erp(ic);
2158		}
2159	} else
2160		ni->ni_flags |= IEEE80211_NODE_ERP;
2161}
2162
2163void
2164ieee80211_node_join(struct ieee80211_node *ni, int resp)
2165{
2166	struct ieee80211com *ic = ni->ni_ic;
2167	struct ieee80211vap *vap = ni->ni_vap;
2168	int newassoc;
2169
2170	if (ni->ni_associd == 0) {
2171		uint16_t aid;
2172
2173		KASSERT(vap->iv_aid_bitmap != NULL, ("no aid bitmap"));
2174		/*
2175		 * It would be good to search the bitmap
2176		 * more efficiently, but this will do for now.
2177		 */
2178		for (aid = 1; aid < vap->iv_max_aid; aid++) {
2179			if (!IEEE80211_AID_ISSET(vap, aid))
2180				break;
2181		}
2182		if (aid >= vap->iv_max_aid) {
2183			IEEE80211_SEND_MGMT(ni, resp,
2184			    IEEE80211_REASON_ASSOC_TOOMANY);
2185			ieee80211_node_leave(ni);
2186			return;
2187		}
2188		ni->ni_associd = aid | 0xc000;
2189		ni->ni_jointime = time_uptime;
2190		IEEE80211_LOCK(ic);
2191		IEEE80211_AID_SET(vap, ni->ni_associd);
2192		vap->iv_sta_assoc++;
2193		ic->ic_sta_assoc++;
2194
2195		if (IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
2196			ieee80211_ht_node_join(ni);
2197		if (IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan) &&
2198		    IEEE80211_IS_CHAN_FULL(ic->ic_bsschan))
2199			ieee80211_node_join_11g(ni);
2200		IEEE80211_UNLOCK(ic);
2201
2202		newassoc = 1;
2203	} else
2204		newassoc = 0;
2205
2206	IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC | IEEE80211_MSG_DEBUG, ni,
2207	    "station associated at aid %d: %s preamble, %s slot time%s%s%s%s%s%s",
2208	    IEEE80211_NODE_AID(ni),
2209	    ic->ic_flags & IEEE80211_F_SHPREAMBLE ? "short" : "long",
2210	    ic->ic_flags & IEEE80211_F_SHSLOT ? "short" : "long",
2211	    ic->ic_flags & IEEE80211_F_USEPROT ? ", protection" : "",
2212	    ni->ni_flags & IEEE80211_NODE_QOS ? ", QoS" : "",
2213	    ni->ni_flags & IEEE80211_NODE_HT ?
2214		(ni->ni_chw == 20 ? ", HT20" : ", HT40") : "",
2215	    ni->ni_flags & IEEE80211_NODE_AMPDU ? " (+AMPDU)" : "",
2216	    IEEE80211_ATH_CAP(vap, ni, IEEE80211_NODE_FF) ?
2217		", fast-frames" : "",
2218	    IEEE80211_ATH_CAP(vap, ni, IEEE80211_NODE_TURBOP) ?
2219		", turbo" : ""
2220	);
2221
2222	/* give driver a chance to setup state like ni_txrate */
2223	if (ic->ic_newassoc != NULL)
2224		ic->ic_newassoc(ni, newassoc);
2225	IEEE80211_SEND_MGMT(ni, resp, IEEE80211_STATUS_SUCCESS);
2226	/* tell the authenticator about new station */
2227	if (vap->iv_auth->ia_node_join != NULL)
2228		vap->iv_auth->ia_node_join(ni);
2229	ieee80211_notify_node_join(ni,
2230	    resp == IEEE80211_FC0_SUBTYPE_ASSOC_RESP);
2231}
2232
2233static void
2234disable_protection(struct ieee80211com *ic)
2235{
2236	KASSERT(ic->ic_nonerpsta == 0 &&
2237	    (ic->ic_flags_ext & IEEE80211_FEXT_NONERP_PR) == 0,
2238	   ("%d non ERP stations, flags 0x%x", ic->ic_nonerpsta,
2239	   ic->ic_flags_ext));
2240
2241	ic->ic_flags &= ~IEEE80211_F_USEPROT;
2242	/* XXX verify mode? */
2243	if (ic->ic_caps & IEEE80211_C_SHPREAMBLE) {
2244		ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
2245		ic->ic_flags &= ~IEEE80211_F_USEBARKER;
2246	}
2247	ieee80211_notify_erp(ic);
2248}
2249
2250/*
2251 * Handle a station leaving an 11g network.
2252 */
2253static void
2254ieee80211_node_leave_11g(struct ieee80211_node *ni)
2255{
2256	struct ieee80211com *ic = ni->ni_ic;
2257
2258	IEEE80211_LOCK_ASSERT(ic);
2259
2260	KASSERT(IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan),
2261	     ("not in 11g, bss %u:0x%x", ic->ic_bsschan->ic_freq,
2262	      ic->ic_bsschan->ic_flags));
2263
2264	/*
2265	 * If a long slot station do the slot time bookkeeping.
2266	 */
2267	if ((ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME) == 0) {
2268		KASSERT(ic->ic_longslotsta > 0,
2269		    ("bogus long slot station count %d", ic->ic_longslotsta));
2270		ic->ic_longslotsta--;
2271		IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ASSOC, ni,
2272		    "long slot time station leaves, count now %d",
2273		    ic->ic_longslotsta);
2274		if (ic->ic_longslotsta == 0) {
2275			/*
2276			 * Re-enable use of short slot time if supported
2277			 * and not operating in IBSS mode (per spec).
2278			 */
2279			if ((ic->ic_caps & IEEE80211_C_SHSLOT) &&
2280			    ic->ic_opmode != IEEE80211_M_IBSS) {
2281				IEEE80211_DPRINTF(ni->ni_vap,
2282				    IEEE80211_MSG_ASSOC,
2283				    "%s: re-enable use of short slot time\n",
2284				    __func__);
2285				ieee80211_set_shortslottime(ic, 1);
2286			}
2287		}
2288	}
2289	/*
2290	 * If a non-ERP station do the protection-related bookkeeping.
2291	 */
2292	if ((ni->ni_flags & IEEE80211_NODE_ERP) == 0) {
2293		KASSERT(ic->ic_nonerpsta > 0,
2294		    ("bogus non-ERP station count %d", ic->ic_nonerpsta));
2295		ic->ic_nonerpsta--;
2296		IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_ASSOC, ni,
2297		    "non-ERP station leaves, count now %d%s", ic->ic_nonerpsta,
2298		    (ic->ic_flags_ext & IEEE80211_FEXT_NONERP_PR) ?
2299			" (non-ERP sta present)" : "");
2300		if (ic->ic_nonerpsta == 0 &&
2301		    (ic->ic_flags_ext & IEEE80211_FEXT_NONERP_PR) == 0) {
2302			IEEE80211_DPRINTF(ni->ni_vap, IEEE80211_MSG_ASSOC,
2303				"%s: disable use of protection\n", __func__);
2304			disable_protection(ic);
2305		}
2306	}
2307}
2308
2309/*
2310 * Time out presence of an overlapping bss with non-ERP
2311 * stations.  When operating in hostap mode we listen for
2312 * beacons from other stations and if we identify a non-ERP
2313 * station is present we enable protection.  To identify
2314 * when all non-ERP stations are gone we time out this
2315 * condition.
2316 */
2317static void
2318ieee80211_erp_timeout(struct ieee80211com *ic)
2319{
2320
2321	IEEE80211_LOCK_ASSERT(ic);
2322
2323	if ((ic->ic_flags_ext & IEEE80211_FEXT_NONERP_PR) &&
2324	    time_after(ticks, ic->ic_lastnonerp + IEEE80211_NONERP_PRESENT_AGE)) {
2325#if 0
2326		IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC, ni,
2327		    "%s", "age out non-ERP sta present on channel");
2328#endif
2329		ic->ic_flags_ext &= ~IEEE80211_FEXT_NONERP_PR;
2330		if (ic->ic_nonerpsta == 0)
2331			disable_protection(ic);
2332	}
2333}
2334
2335/*
2336 * Handle bookkeeping for station deauthentication/disassociation
2337 * when operating as an ap.
2338 */
2339void
2340ieee80211_node_leave(struct ieee80211_node *ni)
2341{
2342	struct ieee80211com *ic = ni->ni_ic;
2343	struct ieee80211vap *vap = ni->ni_vap;
2344	struct ieee80211_node_table *nt = ni->ni_table;
2345
2346	IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC | IEEE80211_MSG_DEBUG, ni,
2347	    "station with aid %d leaves", IEEE80211_NODE_AID(ni));
2348
2349	KASSERT(vap->iv_opmode != IEEE80211_M_STA,
2350		("unexpected operating mode %u", vap->iv_opmode));
2351	/*
2352	 * If node wasn't previously associated all
2353	 * we need to do is reclaim the reference.
2354	 */
2355	/* XXX ibss mode bypasses 11g and notification */
2356	if (ni->ni_associd == 0)
2357		goto done;
2358	/*
2359	 * Tell the authenticator the station is leaving.
2360	 * Note that we must do this before yanking the
2361	 * association id as the authenticator uses the
2362	 * associd to locate it's state block.
2363	 */
2364	if (vap->iv_auth->ia_node_leave != NULL)
2365		vap->iv_auth->ia_node_leave(ni);
2366
2367	IEEE80211_LOCK(ic);
2368	IEEE80211_AID_CLR(vap, ni->ni_associd);
2369	ni->ni_associd = 0;
2370	vap->iv_sta_assoc--;
2371	ic->ic_sta_assoc--;
2372
2373	if (IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
2374		ieee80211_ht_node_leave(ni);
2375	if (IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan) &&
2376	    IEEE80211_IS_CHAN_FULL(ic->ic_bsschan))
2377		ieee80211_node_leave_11g(ni);
2378	IEEE80211_UNLOCK(ic);
2379	/*
2380	 * Cleanup station state.  In particular clear various
2381	 * state that might otherwise be reused if the node
2382	 * is reused before the reference count goes to zero
2383	 * (and memory is reclaimed).
2384	 */
2385	ieee80211_sta_leave(ni);
2386done:
2387	/*
2388	 * Remove the node from any table it's recorded in and
2389	 * drop the caller's reference.  Removal from the table
2390	 * is important to insure the node is not reprocessed
2391	 * for inactivity.
2392	 */
2393	if (nt != NULL) {
2394		IEEE80211_NODE_LOCK(nt);
2395		node_reclaim(nt, ni);
2396		IEEE80211_NODE_UNLOCK(nt);
2397	} else
2398		ieee80211_free_node(ni);
2399}
2400
2401struct rssiinfo {
2402	struct ieee80211vap *vap;
2403	int	rssi_samples;
2404	uint32_t rssi_total;
2405};
2406
2407static void
2408get_hostap_rssi(void *arg, struct ieee80211_node *ni)
2409{
2410	struct rssiinfo *info = arg;
2411	struct ieee80211vap *vap = ni->ni_vap;
2412	int8_t rssi;
2413
2414	if (info->vap != vap)
2415		return;
2416	/* only associated stations */
2417	if (ni->ni_associd == 0)
2418		return;
2419	rssi = vap->iv_ic->ic_node_getrssi(ni);
2420	if (rssi != 0) {
2421		info->rssi_samples++;
2422		info->rssi_total += rssi;
2423	}
2424}
2425
2426static void
2427get_adhoc_rssi(void *arg, struct ieee80211_node *ni)
2428{
2429	struct rssiinfo *info = arg;
2430	struct ieee80211vap *vap = ni->ni_vap;
2431	int8_t rssi;
2432
2433	if (info->vap != vap)
2434		return;
2435	/* only neighbors */
2436	/* XXX check bssid */
2437	if ((ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) == 0)
2438		return;
2439	rssi = vap->iv_ic->ic_node_getrssi(ni);
2440	if (rssi != 0) {
2441		info->rssi_samples++;
2442		info->rssi_total += rssi;
2443	}
2444}
2445
2446int8_t
2447ieee80211_getrssi(struct ieee80211vap *vap)
2448{
2449#define	NZ(x)	((x) == 0 ? 1 : (x))
2450	struct ieee80211com *ic = vap->iv_ic;
2451	struct rssiinfo info;
2452
2453	info.rssi_total = 0;
2454	info.rssi_samples = 0;
2455	info.vap = vap;
2456	switch (vap->iv_opmode) {
2457	case IEEE80211_M_IBSS:		/* average of all ibss neighbors */
2458	case IEEE80211_M_AHDEMO:	/* average of all neighbors */
2459		ieee80211_iterate_nodes(&ic->ic_sta, get_adhoc_rssi, &info);
2460		break;
2461	case IEEE80211_M_HOSTAP:	/* average of all associated stations */
2462		ieee80211_iterate_nodes(&ic->ic_sta, get_hostap_rssi, &info);
2463		break;
2464	case IEEE80211_M_MONITOR:	/* XXX */
2465	case IEEE80211_M_STA:		/* use stats from associated ap */
2466	default:
2467		if (vap->iv_bss != NULL)
2468			info.rssi_total = ic->ic_node_getrssi(vap->iv_bss);
2469		info.rssi_samples = 1;
2470		break;
2471	}
2472	return info.rssi_total / NZ(info.rssi_samples);
2473#undef NZ
2474}
2475
2476void
2477ieee80211_getsignal(struct ieee80211vap *vap, int8_t *rssi, int8_t *noise)
2478{
2479
2480	if (vap->iv_bss == NULL)		/* NB: shouldn't happen */
2481		return;
2482	vap->iv_ic->ic_node_getsignal(vap->iv_bss, rssi, noise);
2483	/* for non-station mode return avg'd rssi accounting */
2484	if (vap->iv_opmode != IEEE80211_M_STA)
2485		*rssi = ieee80211_getrssi(vap);
2486}
2487