ieee80211_node.c revision 173273
169626Sru/*-
2104862Sru * Copyright (c) 2001 Atsushi Onoe
369626Sru * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting
4151497Sru * All rights reserved.
5104862Sru *
669626Sru * Redistribution and use in source and binary forms, with or without
769626Sru * modification, are permitted provided that the following conditions
8151497Sru * are met:
969626Sru * 1. Redistributions of source code must retain the above copyright
10104862Sru *    notice, this list of conditions and the following disclaimer.
1169626Sru * 2. Redistributions in binary form must reproduce the above copyright
1269626Sru *    notice, this list of conditions and the following disclaimer in the
1369626Sru *    documentation and/or other materials provided with the distribution.
1469626Sru *
15104862Sru * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1669626Sru * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1769626Sru * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1869626Sru * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1969626Sru * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2069626Sru * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2169626Sru * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2269626Sru * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2369626Sru * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2469626Sru * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2569626Sru */
26151497Sru
27151497Sru#include <sys/cdefs.h>
28151497Sru__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_node.c 173273 2007-11-02 05:22:25Z sam $");
29104862Sru
30104862Sru#include <sys/param.h>
3169626Sru#include <sys/systm.h>
3275584Sru#include <sys/mbuf.h>
3369626Sru#include <sys/malloc.h>
3469626Sru#include <sys/kernel.h>
3569626Sru
3669626Sru#include <sys/socket.h>
3769626Sru
38104862Sru#include <net/if.h>
39104862Sru#include <net/if_media.h>
40104862Sru#include <net/ethernet.h>
41104862Sru
42104862Sru#include <net80211/ieee80211_var.h>
43104862Sru
44104862Sru#include <net/bpf.h>
45104862Sru
46104862Sru/*
47104862Sru * Association id's are managed with a bit vector.
48104862Sru */
49104862Sru#define	IEEE80211_AID_SET(b, w) \
50104862Sru	((w)[IEEE80211_AID(b) / 32] |= (1 << (IEEE80211_AID(b) % 32)))
51104862Sru#define	IEEE80211_AID_CLR(b, w) \
52104862Sru	((w)[IEEE80211_AID(b) / 32] &= ~(1 << (IEEE80211_AID(b) % 32)))
53104862Sru#define	IEEE80211_AID_ISSET(b, w) \
54104862Sru	((w)[IEEE80211_AID(b) / 32] & (1 << (IEEE80211_AID(b) % 32)))
55104862Sru
56104862Sru#ifdef IEEE80211_DEBUG_REFCNT
57104862Sru#define REFCNT_LOC "%s (%s:%u) %p<%s> refcnt %d\n", __func__, func, line
58104862Sru#else
59104862Sru#define REFCNT_LOC "%s %p<%s> refcnt %d\n", __func__
60104862Sru#endif
61104862Sru
62104862Srustatic int ieee80211_sta_join1(struct ieee80211_node *);
63104862Sru
64104862Srustatic struct ieee80211_node *node_alloc(struct ieee80211_node_table *);
65104862Srustatic void node_cleanup(struct ieee80211_node *);
66104862Srustatic void node_free(struct ieee80211_node *);
6769626Srustatic int8_t node_getrssi(const struct ieee80211_node *);
6869626Srustatic void node_getsignal(const struct ieee80211_node *, int8_t *, int8_t *);
69104862Sru
70104862Srustatic void ieee80211_setup_node(struct ieee80211_node_table *,
71104862Sru		struct ieee80211_node *, const uint8_t *);
72104862Srustatic void _ieee80211_free_node(struct ieee80211_node *);
73104862Sru
74104862Srustatic void ieee80211_node_table_init(struct ieee80211com *ic,
7569626Sru	struct ieee80211_node_table *nt, const char *name,
7669626Sru	int inact, int keymaxix);
77104862Srustatic void ieee80211_node_table_reset(struct ieee80211_node_table *);
78104862Srustatic void ieee80211_node_table_cleanup(struct ieee80211_node_table *nt);
79104862Srustatic void ieee80211_erp_timeout(struct ieee80211com *);
80104862Sru
81104862SruMALLOC_DEFINE(M_80211_NODE, "80211node", "802.11 node state");
82104862Sru
83104862Sruvoid
84104862Sruieee80211_node_attach(struct ieee80211com *ic)
85104862Sru{
8669626Sru
87104862Sru	ic->ic_node_alloc = node_alloc;
88104862Sru	ic->ic_node_free = node_free;
8969626Sru	ic->ic_node_cleanup = node_cleanup;
9069626Sru	ic->ic_node_getrssi = node_getrssi;
91104862Sru	ic->ic_node_getsignal = node_getsignal;
92104862Sru
9369626Sru	/* default station inactivity timer setings */
94104862Sru	ic->ic_inact_init = IEEE80211_INACT_INIT;
95104862Sru	ic->ic_inact_auth = IEEE80211_INACT_AUTH;
9669626Sru	ic->ic_inact_run = IEEE80211_INACT_RUN;
9769626Sru	ic->ic_inact_probe = IEEE80211_INACT_PROBE;
98104862Sru
99104862Sru	callout_init(&ic->ic_inact, CALLOUT_MPSAFE);
100104862Sru
101104862Sru	/* NB: driver should override */
102104862Sru	ic->ic_max_aid = IEEE80211_AID_DEF;
103104862Sru
104104862Sru	ic->ic_flags_ext |= IEEE80211_FEXT_INACT; /* inactivity processing */
105104862Sru}
106104862Sru
107104862Sruvoid
108104862Sruieee80211_node_lateattach(struct ieee80211com *ic)
109104862Sru{
11069626Sru	struct ieee80211_rsnparms *rsn;
11169626Sru
112104862Sru	if (ic->ic_max_aid > IEEE80211_AID_MAX)
113104862Sru		ic->ic_max_aid = IEEE80211_AID_MAX;
114104862Sru	MALLOC(ic->ic_aid_bitmap, uint32_t *,
115104862Sru		howmany(ic->ic_max_aid, 32) * sizeof(uint32_t),
116104862Sru		M_80211_NODE, M_NOWAIT | M_ZERO);
117104862Sru	if (ic->ic_aid_bitmap == NULL) {
118104862Sru		/* XXX no way to recover */
119104862Sru		printf("%s: no memory for AID bitmap!\n", __func__);
120104862Sru		ic->ic_max_aid = 0;
121104862Sru	}
122104862Sru
123104862Sru	ieee80211_node_table_init(ic, &ic->ic_sta, "station",
124104862Sru		IEEE80211_INACT_INIT, ic->ic_crypto.cs_max_keyix);
125104862Sru
12669626Sru	ieee80211_reset_bss(ic);
12769626Sru	/*
128104862Sru	 * Setup "global settings" in the bss node so that
129104862Sru	 * each new station automatically inherits them.
130104862Sru	 */
131104862Sru	rsn = &ic->ic_bss->ni_rsn;
13275584Sru	/* WEP, TKIP, and AES-CCM are always supported */
13375584Sru	rsn->rsn_ucastcipherset |= 1<<IEEE80211_CIPHER_WEP;
134104862Sru	rsn->rsn_ucastcipherset |= 1<<IEEE80211_CIPHER_TKIP;
135104862Sru	rsn->rsn_ucastcipherset |= 1<<IEEE80211_CIPHER_AES_CCM;
136104862Sru	if (ic->ic_caps & IEEE80211_C_AES)
137104862Sru		rsn->rsn_ucastcipherset |= 1<<IEEE80211_CIPHER_AES_OCB;
138104862Sru	if (ic->ic_caps & IEEE80211_C_CKIP)
139104862Sru		rsn->rsn_ucastcipherset |= 1<<IEEE80211_CIPHER_CKIP;
140104862Sru	/*
141104862Sru	 * Default unicast cipher to WEP for 802.1x use.  If
142104862Sru	 * WPA is enabled the management code will set these
143104862Sru	 * values to reflect.
144104862Sru	 */
145104862Sru	rsn->rsn_ucastcipher = IEEE80211_CIPHER_WEP;
146104862Sru	rsn->rsn_ucastkeylen = 104 / NBBY;
14769626Sru	/*
14869626Sru	 * WPA says the multicast cipher is the lowest unicast
14969626Sru	 * cipher supported.  But we skip WEP which would
150104862Sru	 * otherwise be used based on this criteria.
15169626Sru	 */
15269626Sru	rsn->rsn_mcastcipher = IEEE80211_CIPHER_TKIP;
153104862Sru	rsn->rsn_mcastkeylen = 128 / NBBY;
154104862Sru
155104862Sru	/*
15669626Sru	 * We support both WPA-PSK and 802.1x; the one used
15769626Sru	 * is determined by the authentication mode and the
15869626Sru	 * setting of the PSK state.
159104862Sru	 */
16069626Sru	rsn->rsn_keymgmtset = WPA_ASE_8021X_UNSPEC | WPA_ASE_8021X_PSK;
16169626Sru	rsn->rsn_keymgmt = WPA_ASE_8021X_PSK;
16269626Sru
16369626Sru	ic->ic_auth = ieee80211_authenticator_get(ic->ic_bss->ni_authmode);
16469626Sru}
165104862Sru
16669626Sruvoid
16769626Sruieee80211_node_detach(struct ieee80211com *ic)
168104862Sru{
169104862Sru
170104862Sru	if (ic->ic_bss != NULL) {
171104862Sru		ieee80211_free_node(ic->ic_bss);
172104862Sru		ic->ic_bss = NULL;
173104862Sru	}
174104862Sru	ieee80211_node_table_cleanup(&ic->ic_sta);
175104862Sru	if (ic->ic_aid_bitmap != NULL) {
176104862Sru		FREE(ic->ic_aid_bitmap, M_80211_NODE);
177104862Sru		ic->ic_aid_bitmap = NULL;
17869626Sru	}
179104862Sru}
180104862Sru
181104862Sru/*
182104862Sru * Port authorize/unauthorize interfaces for use by an authenticator.
183104862Sru */
184104862Sru
185104862Sruvoid
18669626Sruieee80211_node_authorize(struct ieee80211_node *ni)
187104862Sru{
188104862Sru	struct ieee80211com *ic = ni->ni_ic;
189104862Sru
190104862Sru	ni->ni_flags |= IEEE80211_NODE_AUTH;
19169626Sru	ni->ni_inact_reload = ic->ic_inact_run;
192104862Sru	ni->ni_inact = ni->ni_inact_reload;
193104862Sru}
194104862Sru
195104862Sruvoid
196104862Sruieee80211_node_unauthorize(struct ieee80211_node *ni)
197104862Sru{
198104862Sru	struct ieee80211com *ic = ni->ni_ic;
199104862Sru
200104862Sru	ni->ni_flags &= ~IEEE80211_NODE_AUTH;
201104862Sru	ni->ni_inact_reload = ic->ic_inact_auth;
202104862Sru	if (ni->ni_inact > ni->ni_inact_reload)
203104862Sru		ni->ni_inact = ni->ni_inact_reload;
204104862Sru}
205104862Sru
206104862Sru/*
207104862Sru * Set/change the channel.  The rate set is also updated as
208104862Sru * to insure a consistent view by drivers.
209104862Sru */
210104862Srustatic void
211104862Sruieee80211_node_set_chan(struct ieee80211com *ic, struct ieee80211_node *ni)
212104862Sru{
213104862Sru	struct ieee80211_channel *chan = ic->ic_bsschan;
214104862Sru
215104862Sru#if 0
216104862Sru	KASSERT(chan != IEEE80211_CHAN_ANYC, ("bss channel not setup"));
217104862Sru#else
218104862Sru	if (chan == IEEE80211_CHAN_ANYC)	/* XXX while scanning */
219104862Sru		chan = ic->ic_curchan;
22069626Sru#endif
221104862Sru	ni->ni_chan = chan;
222104862Sru	if (IEEE80211_IS_CHAN_HT(chan)) {
223104862Sru		/*
224104862Sru		 * XXX Gotta be careful here; the rate set returned by
225104862Sru		 * ieee80211_get_suprates is actually any HT rate
226104862Sru		 * set so blindly copying it will be bad.  We must
227104862Sru		 * install the legacy rate est in ni_rates and the
228104862Sru		 * HT rate set in ni_htrates.
229104862Sru		 */
230104862Sru		ni->ni_htrates = *ieee80211_get_suphtrates(ic, chan);
231104862Sru	}
232104862Sru	ni->ni_rates = *ieee80211_get_suprates(ic, chan);
233104862Sru}
234104862Sru
235104862Sru/*
236104862Sru * Probe the curent channel, if allowed, while scanning.
237104862Sru * If the channel is not marked passive-only then send
238104862Sru * a probe request immediately.  Otherwise mark state and
239104862Sru * listen for beacons on the channel; if we receive something
240104862Sru * then we'll transmit a probe request.
241104862Sru */
24269626Sruvoid
243104862Sruieee80211_probe_curchan(struct ieee80211com *ic, int force)
24469626Sru{
245104862Sru	struct ifnet *ifp = ic->ic_ifp;
246104862Sru
24769626Sru	if ((ic->ic_curchan->ic_flags & IEEE80211_CHAN_PASSIVE) == 0 || force) {
248104862Sru		/*
249104862Sru		 * XXX send both broadcast+directed probe request
250104862Sru		 */
251104862Sru		ieee80211_send_probereq(ic->ic_bss,
252104862Sru			ic->ic_myaddr, ifp->if_broadcastaddr,
253104862Sru			ifp->if_broadcastaddr,
254104862Sru			ic->ic_des_ssid[0].ssid, ic->ic_des_ssid[0].len,
255104862Sru			ic->ic_opt_ie, ic->ic_opt_ie_len);
256104862Sru	} else
257104862Sru		ic->ic_flags_ext |= IEEE80211_FEXT_PROBECHAN;
258104862Sru}
259104862Sru
260104862Srustatic __inline void
261104862Srucopy_bss(struct ieee80211_node *nbss, const struct ieee80211_node *obss)
26269626Sru{
263104862Sru	/* propagate useful state */
264104862Sru	nbss->ni_authmode = obss->ni_authmode;
265104862Sru	nbss->ni_txpower = obss->ni_txpower;
266104862Sru	nbss->ni_vlan = obss->ni_vlan;
267104862Sru	nbss->ni_rsn = obss->ni_rsn;
268104862Sru	/* XXX statistics? */
269104862Sru}
270104862Sru
271104862Sruvoid
272104862Sruieee80211_create_ibss(struct ieee80211com* ic, struct ieee80211_channel *chan)
273104862Sru{
274104862Sru	struct ieee80211_node_table *nt;
275114402Sru	struct ieee80211_node *ni;
276104862Sru
277104862Sru	IEEE80211_DPRINTF(ic, IEEE80211_MSG_SCAN,
278104862Sru		"%s: creating ibss\n", __func__);
279104862Sru
280104862Sru	/*
281104862Sru	 * Create the station/neighbor table.  Note that for adhoc
282104862Sru	 * mode we make the initial inactivity timer longer since
283104862Sru	 * we create nodes only through discovery and they typically
284104862Sru	 * are long-lived associations.
285104862Sru	 */
286104862Sru	nt = &ic->ic_sta;
287104862Sru	IEEE80211_NODE_LOCK(nt);
288104862Sru	if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
289104862Sru		nt->nt_name = "station";
290104862Sru		nt->nt_inact_init = ic->ic_inact_init;
291104862Sru	} else {
292104862Sru		nt->nt_name = "neighbor";
293104862Sru		nt->nt_inact_init = ic->ic_inact_run;
294104862Sru	}
295104862Sru	IEEE80211_NODE_UNLOCK(nt);
296104862Sru
297104862Sru	ni = ieee80211_alloc_node(&ic->ic_sta, ic->ic_myaddr);
298104862Sru	if (ni == NULL) {
299104862Sru		/* XXX recovery? */
300104862Sru		return;
301104862Sru	}
302104862Sru	IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_myaddr);
303104862Sru	ni->ni_esslen = ic->ic_des_ssid[0].len;
304104862Sru	memcpy(ni->ni_essid, ic->ic_des_ssid[0].ssid, ni->ni_esslen);
305104862Sru	if (ic->ic_bss != NULL)
306104862Sru		copy_bss(ni, ic->ic_bss);
307104862Sru	ni->ni_intval = ic->ic_bintval;
308104862Sru	if (ic->ic_flags & IEEE80211_F_PRIVACY)
309104862Sru		ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY;
310104862Sru	if (ic->ic_phytype == IEEE80211_T_FH) {
311104862Sru		ni->ni_fhdwell = 200;	/* XXX */
312104862Sru		ni->ni_fhindex = 1;
313104862Sru	}
314104862Sru	if (ic->ic_opmode == IEEE80211_M_IBSS) {
315104862Sru		ic->ic_flags |= IEEE80211_F_SIBSS;
316104862Sru		ni->ni_capinfo |= IEEE80211_CAPINFO_IBSS;	/* XXX */
31769626Sru		if (ic->ic_flags & IEEE80211_F_DESBSSID)
318104862Sru			IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_des_bssid);
31969626Sru		else {
320104862Sru			get_random_bytes(ni->ni_bssid, IEEE80211_ADDR_LEN);
321104862Sru			/* clear group bit, add local bit */
322104862Sru			ni->ni_bssid[0] = (ni->ni_bssid[0] &~ 0x01) | 0x02;
323104862Sru		}
324104862Sru	} else if (ic->ic_opmode == IEEE80211_M_AHDEMO) {
325104862Sru		if (ic->ic_flags & IEEE80211_F_DESBSSID)
326104862Sru			IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_des_bssid);
327104862Sru		else
328104862Sru			memset(ni->ni_bssid, 0, IEEE80211_ADDR_LEN);
329104862Sru	}
330104862Sru	/*
331104862Sru	 * Fix the channel and related attributes.
332104862Sru	 */
333104862Sru	ic->ic_bsschan = chan;
334104862Sru	ieee80211_node_set_chan(ic, ni);
335104862Sru	ic->ic_curmode = ieee80211_chan2mode(chan);
336104862Sru	/*
337104862Sru	 * Do mode-specific rate setup.
338104862Sru	 */
339104862Sru	if (IEEE80211_IS_CHAN_FULL(chan)) {
340104862Sru		if (IEEE80211_IS_CHAN_ANYG(chan)) {
341104862Sru			/*
342104862Sru			 * Use a mixed 11b/11g rate set.
343104862Sru			 */
344104862Sru			ieee80211_set11gbasicrates(&ni->ni_rates,
345104862Sru				IEEE80211_MODE_11G);
346104862Sru		} else if (IEEE80211_IS_CHAN_B(chan)) {
347104862Sru			/*
348104862Sru			 * Force pure 11b rate set.
349104862Sru			 */
350104862Sru			ieee80211_set11gbasicrates(&ni->ni_rates,
351104862Sru				IEEE80211_MODE_11B);
352104862Sru		}
353104862Sru	}
354104862Sru
355104862Sru	(void) ieee80211_sta_join1(ieee80211_ref_node(ni));
356104862Sru}
357104862Sru
358104862Sru/*
359104862Sru * Reset bss state on transition to the INIT state.
360104862Sru * Clear any stations from the table (they have been
361104862Sru * deauth'd) and reset the bss node (clears key, rate
362104862Sru * etc. state).
363104862Sru */
364104862Sruvoid
365104862Sruieee80211_reset_bss(struct ieee80211com *ic)
366104862Sru{
367104862Sru	struct ieee80211_node *ni, *obss;
368104862Sru
369104862Sru	callout_drain(&ic->ic_inact);
370104862Sru	ieee80211_node_table_reset(&ic->ic_sta);
371104862Sru	ieee80211_reset_erp(ic);
372104862Sru
37369626Sru	ni = ieee80211_alloc_node(&ic->ic_sta, ic->ic_myaddr);
374104862Sru	KASSERT(ni != NULL, ("unable to setup inital BSS node"));
375104862Sru	obss = ic->ic_bss;
376104862Sru	ic->ic_bss = ieee80211_ref_node(ni);
377104862Sru	if (obss != NULL) {
378104862Sru		copy_bss(ni, obss);
379104862Sru		ni->ni_intval = ic->ic_bintval;
380104862Sru		ieee80211_free_node(obss);
381104862Sru	}
382104862Sru}
383104862Sru
384104862Srustatic int
385104862Srumatch_ssid(const struct ieee80211_node *ni,
386104862Sru	int nssid, const struct ieee80211_scan_ssid ssids[])
387104862Sru{
388104862Sru	int i;
389104862Sru
390104862Sru	for (i = 0; i < nssid; i++) {
391104862Sru		if (ni->ni_esslen == ssids[i].len &&
392104862Sru		     memcmp(ni->ni_essid, ssids[i].ssid, ni->ni_esslen) == 0)
393104862Sru			return 1;
394104862Sru	}
395104862Sru	return 0;
396104862Sru}
397104862Sru
398104862Sru/*
399104862Sru * Test a node for suitability/compatibility.
400104862Sru */
401104862Srustatic int
402104862Srucheck_bss(struct ieee80211com *ic, struct ieee80211_node *ni)
403104862Sru{
404104862Sru        uint8_t rate;
405104862Sru
406104862Sru	if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, ni->ni_chan)))
407104862Sru		return 0;
408104862Sru	if (ic->ic_opmode == IEEE80211_M_IBSS) {
409104862Sru		if ((ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) == 0)
410104862Sru			return 0;
411104862Sru	} else {
412104862Sru		if ((ni->ni_capinfo & IEEE80211_CAPINFO_ESS) == 0)
413104862Sru			return 0;
414104862Sru	}
415104862Sru	if (ic->ic_flags & IEEE80211_F_PRIVACY) {
416104862Sru		if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0)
417104862Sru			return 0;
418104862Sru	} else {
419104862Sru		/* XXX does this mean privacy is supported or required? */
420104862Sru		if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY)
421104862Sru			return 0;
422104862Sru	}
423104862Sru	rate = ieee80211_fix_rate(ni, &ni->ni_rates,
424104862Sru	    IEEE80211_F_JOIN | IEEE80211_F_DONEGO | IEEE80211_F_DOFRATE);
425104862Sru	if (rate & IEEE80211_RATE_BASIC)
42669626Sru		return 0;
427104862Sru	if (ic->ic_des_nssid != 0 &&
428104862Sru	    !match_ssid(ni, ic->ic_des_nssid, ic->ic_des_ssid))
429104862Sru		return 0;
430104862Sru	if ((ic->ic_flags & IEEE80211_F_DESBSSID) &&
431104862Sru	    !IEEE80211_ADDR_EQ(ic->ic_des_bssid, ni->ni_bssid))
432104862Sru		return 0;
433104862Sru	return 1;
434104862Sru}
435104862Sru
436104862Sru#ifdef IEEE80211_DEBUG
437104862Sru/*
438104862Sru * Display node suitability/compatibility.
439104862Sru */
440104862Srustatic void
441104862Srucheck_bss_debug(struct ieee80211com *ic, struct ieee80211_node *ni)
442104862Sru{
443104862Sru        uint8_t rate;
444104862Sru        int fail;
445104862Sru
446104862Sru	fail = 0;
447104862Sru	if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, ni->ni_chan)))
448104862Sru		fail |= 0x01;
449104862Sru	if (ic->ic_opmode == IEEE80211_M_IBSS) {
450104862Sru		if ((ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) == 0)
451104862Sru			fail |= 0x02;
452104862Sru	} else {
453104862Sru		if ((ni->ni_capinfo & IEEE80211_CAPINFO_ESS) == 0)
454104862Sru			fail |= 0x02;
455104862Sru	}
456104862Sru	if (ic->ic_flags & IEEE80211_F_PRIVACY) {
457104862Sru		if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0)
458104862Sru			fail |= 0x04;
459104862Sru	} else {
460104862Sru		/* XXX does this mean privacy is supported or required? */
461104862Sru		if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY)
462104862Sru			fail |= 0x04;
463104862Sru	}
464104862Sru	rate = ieee80211_fix_rate(ni, &ni->ni_rates,
465104862Sru	     IEEE80211_F_JOIN | IEEE80211_F_DONEGO | IEEE80211_F_DOFRATE);
466104862Sru	if (rate & IEEE80211_RATE_BASIC)
467104862Sru		fail |= 0x08;
468104862Sru	if (ic->ic_des_nssid != 0 &&
469104862Sru	    !match_ssid(ni, ic->ic_des_nssid, ic->ic_des_ssid))
470104862Sru		fail |= 0x10;
471104862Sru	if ((ic->ic_flags & IEEE80211_F_DESBSSID) &&
472104862Sru	    !IEEE80211_ADDR_EQ(ic->ic_des_bssid, ni->ni_bssid))
473104862Sru		fail |= 0x20;
474104862Sru
475104862Sru	printf(" %c %s", fail ? '-' : '+', ether_sprintf(ni->ni_macaddr));
476151497Sru	printf(" %s%c", ether_sprintf(ni->ni_bssid), fail & 0x20 ? '!' : ' ');
477104862Sru	printf(" %3d%c",
478104862Sru	    ieee80211_chan2ieee(ic, ni->ni_chan), fail & 0x01 ? '!' : ' ');
479104862Sru	printf(" %+4d", ni->ni_rssi);
480104862Sru	printf(" %2dM%c", (rate & IEEE80211_RATE_VAL) / 2,
481104862Sru	    fail & 0x08 ? '!' : ' ');
482104862Sru	printf(" %4s%c",
483104862Sru	    (ni->ni_capinfo & IEEE80211_CAPINFO_ESS) ? "ess" :
484104862Sru	    (ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) ? "ibss" :
485104862Sru	    "????",
486104862Sru	    fail & 0x02 ? '!' : ' ');
487104862Sru	printf(" %3s%c ",
488104862Sru	    (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) ?  "wep" : "no",
489104862Sru	    fail & 0x04 ? '!' : ' ');
490104862Sru	ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
491104862Sru	printf("%s\n", fail & 0x10 ? "!" : "");
492104862Sru}
493104862Sru#endif /* IEEE80211_DEBUG */
494104862Sru
495104862Sru/*
496104862Sru * Handle 802.11 ad hoc network merge.  The
497104862Sru * convention, set by the Wireless Ethernet Compatibility Alliance
49869626Sru * (WECA), is that an 802.11 station will change its BSSID to match
499104862Sru * the "oldest" 802.11 ad hoc network, on the same channel, that
500104862Sru * has the station's desired SSID.  The "oldest" 802.11 network
501104862Sru * sends beacons with the greatest TSF timestamp.
502104862Sru *
503104862Sru * The caller is assumed to validate TSF's before attempting a merge.
504104862Sru *
505104862Sru * Return !0 if the BSSID changed, 0 otherwise.
506104862Sru */
507104862Sruint
508104862Sruieee80211_ibss_merge(struct ieee80211_node *ni)
509104862Sru{
510104862Sru	struct ieee80211com *ic = ni->ni_ic;
511104862Sru
512104862Sru	if (ni == ic->ic_bss ||
513104862Sru	    IEEE80211_ADDR_EQ(ni->ni_bssid, ic->ic_bss->ni_bssid)) {
514104862Sru		/* unchanged, nothing to do */
515104862Sru		return 0;
51669626Sru	}
517104862Sru	if (!check_bss(ic, ni)) {
51869626Sru		/* capabilities mismatch */
519104862Sru		IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
520104862Sru		    "%s: merge failed, capabilities mismatch\n", __func__);
521104862Sru#ifdef IEEE80211_DEBUG
522104862Sru		if (ieee80211_msg_assoc(ic))
523104862Sru			check_bss_debug(ic, ni);
524104862Sru#endif
525104862Sru		ic->ic_stats.is_ibss_capmismatch++;
526151497Sru		return 0;
527104862Sru	}
528104862Sru	IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
529104862Sru		"%s: new bssid %s: %s preamble, %s slot time%s\n", __func__,
530104862Sru		ether_sprintf(ni->ni_bssid),
531104862Sru		ic->ic_flags&IEEE80211_F_SHPREAMBLE ? "short" : "long",
532104862Sru		ic->ic_flags&IEEE80211_F_SHSLOT ? "short" : "long",
533104862Sru		ic->ic_flags&IEEE80211_F_USEPROT ? ", protection" : ""
534104862Sru	);
535104862Sru	return ieee80211_sta_join1(ieee80211_ref_node(ni));
536104862Sru}
537104862Sru
538104862Sru/*
539104862Sru * Change the bss channel.
540104862Sru */
541104862Sruvoid
542104862Sruieee80211_setbsschan(struct ieee80211com *ic, struct ieee80211_channel *c)
543104862Sru{
544104862Sru	ic->ic_bsschan = c;
545104862Sru	ic->ic_curchan = ic->ic_bsschan;
546104862Sru	ic->ic_curmode = ieee80211_chan2mode(ic->ic_curchan);
547104862Sru	ic->ic_set_channel(ic);
548104862Sru}
549104862Sru
550104862Sru/*
551104862Sru * Join the specified IBSS/BSS network.  The node is assumed to
552104862Sru * be passed in with a held reference.
553104862Sru */
554104862Srustatic int
555104862Sruieee80211_sta_join1(struct ieee80211_node *selbs)
556104862Sru{
557104862Sru	struct ieee80211com *ic = selbs->ni_ic;
558104862Sru	struct ieee80211_node *obss;
559104862Sru	int canreassoc;
560104862Sru
561104862Sru	if (ic->ic_opmode == IEEE80211_M_IBSS) {
562104862Sru		struct ieee80211_node_table *nt;
563104862Sru		/*
564104862Sru		 * Fillin the neighbor table; it will already
565104862Sru		 * exist if we are simply switching mastership.
566104862Sru		 * XXX ic_sta always setup so this is unnecessary?
567104862Sru		 */
568104862Sru		nt = &ic->ic_sta;
569104862Sru		IEEE80211_NODE_LOCK(nt);
570104862Sru		nt->nt_name = "neighbor";
571104862Sru		nt->nt_inact_init = ic->ic_inact_run;
572104862Sru		IEEE80211_NODE_UNLOCK(nt);
573104862Sru	}
574104862Sru
575104862Sru	/*
576104862Sru	 * Committed to selbs, setup state.
577104862Sru	 */
578104862Sru	obss = ic->ic_bss;
579104862Sru	/*
580104862Sru	 * Check if old+new node have the same address in which
581104862Sru	 * case we can reassociate when operating in sta mode.
582104862Sru	 */
583104862Sru	canreassoc = (obss != NULL &&
584104862Sru		ic->ic_state == IEEE80211_S_RUN &&
585104862Sru		IEEE80211_ADDR_EQ(obss->ni_macaddr, selbs->ni_macaddr));
586104862Sru	ic->ic_bss = selbs;		/* NB: caller assumed to bump refcnt */
587104862Sru	if (obss != NULL) {
588104862Sru		copy_bss(selbs, obss);
589104862Sru		ieee80211_free_node(obss);
590104862Sru	}
591104862Sru
592104862Sru	/*
593104862Sru	 * Delete unusable rates; we've already checked
594104862Sru	 * that the negotiated rate set is acceptable.
595104862Sru	 */
596104862Sru	ieee80211_fix_rate(ic->ic_bss, &ic->ic_bss->ni_rates,
597104862Sru		IEEE80211_F_DODEL | IEEE80211_F_JOIN);
598104862Sru
599104862Sru	ieee80211_setbsschan(ic, selbs->ni_chan);
600104862Sru	/*
601104862Sru	 * Set the erp state (mostly the slot time) to deal with
602104862Sru	 * the auto-select case; this should be redundant if the
603104862Sru	 * mode is locked.
604104862Sru	 */
605104862Sru	ieee80211_reset_erp(ic);
606104862Sru	ieee80211_wme_initparams(ic);
607104862Sru
608104862Sru	if (ic->ic_opmode == IEEE80211_M_STA) {
609104862Sru		if (canreassoc) {
610104862Sru			/* Reassociate */
611104862Sru			ieee80211_new_state(ic, IEEE80211_S_ASSOC, 1);
612104862Sru		} else {
613104862Sru			/*
614104862Sru			 * Act as if we received a DEAUTH frame in case we
615104862Sru			 * are invoked from the RUN state.  This will cause
616104862Sru			 * us to try to re-authenticate if we are operating
617104862Sru			 * as a station.
618104862Sru			 */
619104862Sru			ieee80211_new_state(ic, IEEE80211_S_AUTH,
620104862Sru				IEEE80211_FC0_SUBTYPE_DEAUTH);
621104862Sru		}
622104862Sru	} else
623104862Sru		ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
624104862Sru	return 1;
625104862Sru}
626104862Sru
627104862Sruint
628104862Sruieee80211_sta_join(struct ieee80211com *ic,
629104862Sru	const struct ieee80211_scan_entry *se)
630104862Sru{
631104862Sru	struct ieee80211_node *ni;
632104862Sru
63369626Sru	ni = ieee80211_alloc_node(&ic->ic_sta, se->se_macaddr);
63469626Sru	if (ni == NULL) {
635104862Sru		/* XXX msg */
636104862Sru		return 0;
637104862Sru	}
638104862Sru	/*
639104862Sru	 * Expand scan state into node's format.
640104862Sru	 * XXX may not need all this stuff
641104862Sru	 */
642104862Sru	IEEE80211_ADDR_COPY(ni->ni_bssid, se->se_bssid);
643104862Sru	ni->ni_esslen = se->se_ssid[1];
644104862Sru	memcpy(ni->ni_essid, se->se_ssid+2, ni->ni_esslen);
645104862Sru	ni->ni_rstamp = se->se_rstamp;
646104862Sru	ni->ni_tstamp.tsf = se->se_tstamp.tsf;
647104862Sru	ni->ni_intval = se->se_intval;
648104862Sru	ni->ni_capinfo = se->se_capinfo;
649104862Sru	ni->ni_chan = se->se_chan;
65069626Sru	ni->ni_timoff = se->se_timoff;
65169626Sru	ni->ni_fhdwell = se->se_fhdwell;
65269626Sru	ni->ni_fhindex = se->se_fhindex;
653104862Sru	ni->ni_erp = se->se_erp;
654104862Sru	ni->ni_rssi = se->se_rssi;
655104862Sru	ni->ni_noise = se->se_noise;
656104862Sru	if (se->se_htcap_ie != NULL)
657104862Sru		ieee80211_saveie(&ni->ni_htcap_ie, se->se_htcap_ie);
658104862Sru	if (se->se_wpa_ie != NULL)
659104862Sru		ieee80211_saveie(&ni->ni_wpa_ie, se->se_wpa_ie);
660104862Sru	if (se->se_rsn_ie != NULL)
661104862Sru		ieee80211_saveie(&ni->ni_rsn_ie, se->se_rsn_ie);
662104862Sru	if (se->se_wme_ie != NULL)
663104862Sru		ieee80211_saveie(&ni->ni_wme_ie, se->se_wme_ie);
664104862Sru	if (se->se_ath_ie != NULL)
665104862Sru		ieee80211_saveath(ni, se->se_ath_ie);
666104862Sru
667104862Sru	ic->ic_dtim_period = se->se_dtimperiod;
668104862Sru	ic->ic_dtim_count = 0;
669104862Sru
670104862Sru	/* NB: must be after ni_chan is setup */
671104862Sru	ieee80211_setup_rates(ni, se->se_rates, se->se_xrates,
672104862Sru		IEEE80211_F_DOSORT);
673104862Sru
674104862Sru	return ieee80211_sta_join1(ieee80211_ref_node(ni));
675104862Sru}
67669626Sru
677104862Sru/*
67869626Sru * Leave the specified IBSS/BSS network.  The node is assumed to
679104862Sru * be passed in with a held reference.
680104862Sru */
681104862Sruvoid
682104862Sruieee80211_sta_leave(struct ieee80211com *ic, struct ieee80211_node *ni)
683104862Sru{
684104862Sru	ic->ic_node_cleanup(ni);
685104862Sru	ieee80211_notify_node_leave(ic, ni);
686104862Sru}
687104862Sru
688104862Srustatic struct ieee80211_node *
689104862Srunode_alloc(struct ieee80211_node_table *nt)
690104862Sru{
691104862Sru	struct ieee80211_node *ni;
692104862Sru
693104862Sru	MALLOC(ni, struct ieee80211_node *, sizeof(struct ieee80211_node),
694104862Sru		M_80211_NODE, M_NOWAIT | M_ZERO);
695104862Sru	return ni;
696104862Sru}
697104862Sru
698104862Sru/*
699104862Sru * Reclaim any resources in a node and reset any critical
700104862Sru * state.  Typically nodes are free'd immediately after,
701104862Sru * but in some cases the storage may be reused so we need
702104862Sru * to insure consistent state (should probably fix that).
703104862Sru */
704104862Srustatic void
705104862Srunode_cleanup(struct ieee80211_node *ni)
706104862Sru{
707104862Sru#define	N(a)	(sizeof(a)/sizeof(a[0]))
708104862Sru	struct ieee80211com *ic = ni->ni_ic;
709104862Sru	int i;
710104862Sru
711104862Sru	/* NB: preserve ni_table */
712104862Sru	if (ni->ni_flags & IEEE80211_NODE_PWR_MGT) {
713104862Sru		if (ic->ic_opmode != IEEE80211_M_STA)
714104862Sru			ic->ic_ps_sta--;
715104862Sru		ni->ni_flags &= ~IEEE80211_NODE_PWR_MGT;
716104862Sru		IEEE80211_DPRINTF(ic, IEEE80211_MSG_POWER,
717104862Sru		    "[%s] power save mode off, %u sta's in ps mode\n",
718104862Sru		    ether_sprintf(ni->ni_macaddr), ic->ic_ps_sta);
719104862Sru	}
720104862Sru	/*
721104862Sru	 * Cleanup any HT-related state.
722104862Sru	 */
723104862Sru	if (ni->ni_flags & IEEE80211_NODE_HT)
724104862Sru		ieee80211_ht_node_cleanup(ni);
725104862Sru	/*
726104862Sru	 * Clear AREF flag that marks the authorization refcnt bump
727104862Sru	 * has happened.  This is probably not needed as the node
728104862Sru	 * should always be removed from the table so not found but
729104862Sru	 * do it just in case.
730104862Sru	 */
731104862Sru	ni->ni_flags &= ~IEEE80211_NODE_AREF;
732104862Sru
733104862Sru	/*
734104862Sru	 * Drain power save queue and, if needed, clear TIM.
735104862Sru	 */
736104862Sru	if (ieee80211_node_saveq_drain(ni) != 0 && ic->ic_set_tim != NULL)
737104862Sru		ic->ic_set_tim(ni, 0);
738104862Sru
739104862Sru	ni->ni_associd = 0;
740104862Sru	if (ni->ni_challenge != NULL) {
741104862Sru		FREE(ni->ni_challenge, M_80211_NODE);
742104862Sru		ni->ni_challenge = NULL;
743104862Sru	}
744104862Sru	/*
745104862Sru	 * Preserve SSID, WPA, and WME ie's so the bss node is
746104862Sru	 * reusable during a re-auth/re-assoc state transition.
747104862Sru	 * If we remove these data they will not be recreated
748104862Sru	 * because they come from a probe-response or beacon frame
749104862Sru	 * which cannot be expected prior to the association-response.
750104862Sru	 * This should not be an issue when operating in other modes
751104862Sru	 * as stations leaving always go through a full state transition
752104862Sru	 * which will rebuild this state.
753104862Sru	 *
754104862Sru	 * XXX does this leave us open to inheriting old state?
755104862Sru	 */
756104862Sru	for (i = 0; i < N(ni->ni_rxfrag); i++)
757104862Sru		if (ni->ni_rxfrag[i] != NULL) {
758104862Sru			m_freem(ni->ni_rxfrag[i]);
759104862Sru			ni->ni_rxfrag[i] = NULL;
760104862Sru		}
761104862Sru	/*
762104862Sru	 * Must be careful here to remove any key map entry w/o a LOR.
763104862Sru	 */
764104862Sru	ieee80211_node_delucastkey(ni);
765104862Sru#undef N
766104862Sru}
767104862Sru
768104862Srustatic void
769104862Srunode_free(struct ieee80211_node *ni)
770104862Sru{
771104862Sru	struct ieee80211com *ic = ni->ni_ic;
772104862Sru
773104862Sru	ic->ic_node_cleanup(ni);
774104862Sru	if (ni->ni_wpa_ie != NULL)
775104862Sru		FREE(ni->ni_wpa_ie, M_80211_NODE);
776104862Sru	if (ni->ni_rsn_ie != NULL)
777104862Sru		FREE(ni->ni_rsn_ie, M_80211_NODE);
778104862Sru	if (ni->ni_wme_ie != NULL)
779104862Sru		FREE(ni->ni_wme_ie, M_80211_NODE);
780104862Sru	if (ni->ni_ath_ie != NULL)
781104862Sru		FREE(ni->ni_ath_ie, M_80211_NODE);
782104862Sru	IEEE80211_NODE_SAVEQ_DESTROY(ni);
783104862Sru	FREE(ni, M_80211_NODE);
784104862Sru}
785104862Sru
786104862Srustatic int8_t
787104862Srunode_getrssi(const struct ieee80211_node *ni)
788104862Sru{
789104862Sru	return ni->ni_rssi;
790104862Sru}
791104862Sru
792104862Srustatic void
793104862Srunode_getsignal(const struct ieee80211_node *ni, int8_t *rssi, int8_t *noise)
794104862Sru{
795104862Sru	*rssi = ni->ni_rssi;
79669626Sru	*noise = ni->ni_noise;
79769626Sru}
798104862Sru
79969626Srustatic void
800104862Sruieee80211_setup_node(struct ieee80211_node_table *nt,
80169626Sru	struct ieee80211_node *ni, const uint8_t *macaddr)
80275584Sru{
803104862Sru	struct ieee80211com *ic = nt->nt_ic;
80475584Sru	int hash;
805104862Sru
806104862Sru	IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
807104862Sru		"%s %p<%s> in %s table\n", __func__, ni,
80869626Sru		ether_sprintf(macaddr), nt->nt_name);
809104862Sru
810104862Sru	IEEE80211_ADDR_COPY(ni->ni_macaddr, macaddr);
811104862Sru	hash = IEEE80211_NODE_HASH(macaddr);
81275584Sru	ieee80211_node_initref(ni);		/* mark referenced */
813104862Sru	ni->ni_chan = IEEE80211_CHAN_ANYC;
814104862Sru	ni->ni_authmode = IEEE80211_AUTH_OPEN;
815104862Sru	ni->ni_txpower = ic->ic_txpowlimit;	/* max power */
816104862Sru	ieee80211_crypto_resetkey(ic, &ni->ni_ucastkey, IEEE80211_KEYIX_NONE);
817104862Sru	ni->ni_inact_reload = nt->nt_inact_init;
818104862Sru	ni->ni_inact = ni->ni_inact_reload;
819104862Sru	ni->ni_ath_defkeyix = 0x7fff;
820104862Sru	IEEE80211_NODE_SAVEQ_INIT(ni, "unknown");
821104862Sru
822104862Sru	IEEE80211_NODE_LOCK(nt);
823104862Sru	TAILQ_INSERT_TAIL(&nt->nt_node, ni, ni_list);
824104862Sru	LIST_INSERT_HEAD(&nt->nt_hash[hash], ni, ni_hash);
82569626Sru	ni->ni_table = nt;
826104862Sru	ni->ni_ic = ic;
827104862Sru	IEEE80211_NODE_UNLOCK(nt);
82869626Sru}
829104862Sru
830104862Srustruct ieee80211_node *
831104862Sruieee80211_alloc_node(struct ieee80211_node_table *nt, const uint8_t *macaddr)
832104862Sru{
833104862Sru	struct ieee80211com *ic = nt->nt_ic;
834104862Sru	struct ieee80211_node *ni;
835104862Sru
836104862Sru	ni = ic->ic_node_alloc(nt);
837104862Sru	if (ni != NULL)
83869626Sru		ieee80211_setup_node(nt, ni, macaddr);
83969626Sru	else
840104862Sru		ic->ic_stats.is_rx_nodealloc++;
841104862Sru	return ni;
842104862Sru}
843104862Sru
84469626Sru/*
845104862Sru * Craft a temporary node suitable for sending a management frame
846104862Sru * to the specified station.  We craft only as much state as we
847104862Sru * need to do the work since the node will be immediately reclaimed
848104862Sru * once the send completes.
849104862Sru */
850104862Srustruct ieee80211_node *
851104862Sruieee80211_tmp_node(struct ieee80211com *ic, const uint8_t *macaddr)
852104862Sru{
853104862Sru	struct ieee80211_node *ni;
854104862Sru
855104862Sru	ni = ic->ic_node_alloc(&ic->ic_sta);
856104862Sru	if (ni != NULL) {
857104862Sru		IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
858104862Sru			"%s %p<%s>\n", __func__, ni, ether_sprintf(macaddr));
859104862Sru
860104862Sru		IEEE80211_ADDR_COPY(ni->ni_macaddr, macaddr);
861104862Sru		IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss->ni_bssid);
862104862Sru		ieee80211_node_initref(ni);		/* mark referenced */
863104862Sru		ni->ni_txpower = ic->ic_bss->ni_txpower;
864104862Sru		/* NB: required by ieee80211_fix_rate */
865104862Sru		ieee80211_node_set_chan(ic, ni);
866104862Sru		ieee80211_crypto_resetkey(ic, &ni->ni_ucastkey,
867104862Sru			IEEE80211_KEYIX_NONE);
868104862Sru		/* XXX optimize away */
869104862Sru		IEEE80211_NODE_SAVEQ_INIT(ni, "unknown");
870104862Sru
871104862Sru		ni->ni_table = NULL;		/* NB: pedantic */
872104862Sru		ni->ni_ic = ic;
873104862Sru	} else {
874104862Sru		/* XXX msg */
875104862Sru		ic->ic_stats.is_rx_nodealloc++;
876104862Sru	}
877104862Sru	return ni;
878104862Sru}
879104862Sru
880104862Srustruct ieee80211_node *
881104862Sruieee80211_dup_bss(struct ieee80211_node_table *nt, const uint8_t *macaddr)
882104862Sru{
883104862Sru	struct ieee80211com *ic = nt->nt_ic;
884104862Sru	struct ieee80211_node *ni;
885104862Sru
886104862Sru	ni = ic->ic_node_alloc(nt);
887104862Sru	if (ni != NULL) {
888104862Sru		ieee80211_setup_node(nt, ni, macaddr);
889104862Sru		/*
890104862Sru		 * Inherit from ic_bss.
891104862Sru		 */
892104862Sru		ni->ni_authmode = ic->ic_bss->ni_authmode;
893104862Sru		ni->ni_txpower = ic->ic_bss->ni_txpower;
894104862Sru		ni->ni_vlan = ic->ic_bss->ni_vlan;	/* XXX?? */
895104862Sru		IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss->ni_bssid);
896104862Sru		ieee80211_node_set_chan(ic, ni);
897104862Sru		ni->ni_rsn = ic->ic_bss->ni_rsn;
898104862Sru	} else
899104862Sru		ic->ic_stats.is_rx_nodealloc++;
900104862Sru	return ni;
901104862Sru}
902104862Sru
903104862Srustatic struct ieee80211_node *
904104862Sru#ifdef IEEE80211_DEBUG_REFCNT
905104862Sru_ieee80211_find_node_debug(struct ieee80211_node_table *nt,
906104862Sru	const uint8_t *macaddr, const char *func, int line)
907104862Sru#else
908104862Sru_ieee80211_find_node(struct ieee80211_node_table *nt,
909104862Sru	const uint8_t *macaddr)
91069626Sru#endif
91169626Sru{
912104862Sru	struct ieee80211_node *ni;
913104862Sru	int hash;
91469626Sru
91569626Sru	IEEE80211_NODE_LOCK_ASSERT(nt);
916104862Sru
917104862Sru	hash = IEEE80211_NODE_HASH(macaddr);
918104862Sru	LIST_FOREACH(ni, &nt->nt_hash[hash], ni_hash) {
919104862Sru		if (IEEE80211_ADDR_EQ(ni->ni_macaddr, macaddr)) {
92069626Sru			ieee80211_ref_node(ni);	/* mark referenced */
92169626Sru#ifdef IEEE80211_DEBUG_REFCNT
92269626Sru			IEEE80211_DPRINTF(nt->nt_ic, IEEE80211_MSG_NODE,
92369626Sru			    "%s (%s:%u) %p<%s> refcnt %d\n", __func__,
92469626Sru			    func, line,
92569626Sru			    ni, ether_sprintf(ni->ni_macaddr),
92669626Sru			    ieee80211_node_refcnt(ni));
92769626Sru#endif
92869626Sru			return ni;
92969626Sru		}
93069626Sru	}
93169626Sru	return NULL;
93269626Sru}
93369626Sru#ifdef IEEE80211_DEBUG_REFCNT
93469626Sru#define	_ieee80211_find_node(nt, mac) \
93569626Sru	_ieee80211_find_node_debug(nt, mac, func, line)
936104862Sru#endif
937104862Sru
93869626Srustruct ieee80211_node *
939104862Sru#ifdef IEEE80211_DEBUG_REFCNT
940104862Sruieee80211_find_node_debug(struct ieee80211_node_table *nt,
941104862Sru	const uint8_t *macaddr, const char *func, int line)
942104862Sru#else
943104862Sruieee80211_find_node(struct ieee80211_node_table *nt, const uint8_t *macaddr)
944104862Sru#endif
945104862Sru{
946104862Sru	struct ieee80211_node *ni;
947104862Sru
94869626Sru	IEEE80211_NODE_LOCK(nt);
94969626Sru	ni = _ieee80211_find_node(nt, macaddr);
95069626Sru	IEEE80211_NODE_UNLOCK(nt);
951104862Sru	return ni;
952104862Sru}
953104862Sru
954104862Sru/*
955104862Sru * Fake up a node; this handles node discovery in adhoc mode.
956104862Sru * Note that for the driver's benefit we we treat this like
957104862Sru * an association so the driver has an opportunity to setup
958104862Sru * it's private state.
959104862Sru */
960104862Srustruct ieee80211_node *
96169626Sruieee80211_fakeup_adhoc_node(struct ieee80211_node_table *nt,
96269626Sru	const uint8_t macaddr[IEEE80211_ADDR_LEN])
96369626Sru{
964104862Sru	struct ieee80211com *ic = nt->nt_ic;
965104862Sru	struct ieee80211_node *ni;
96669626Sru
967104862Sru	IEEE80211_DPRINTF(nt->nt_ic, IEEE80211_MSG_NODE,
96869626Sru	    "%s: mac<%s>\n", __func__, ether_sprintf(macaddr));
969104862Sru	ni = ieee80211_dup_bss(nt, macaddr);
970104862Sru	if (ni != NULL) {
971104862Sru		/* XXX no rate negotiation; just dup */
972104862Sru		ni->ni_rates = ic->ic_bss->ni_rates;
973104862Sru		if (ic->ic_newassoc != NULL)
974104862Sru			ic->ic_newassoc(ni, 1);
975104862Sru		if (ic->ic_opmode == IEEE80211_M_AHDEMO) {
976104862Sru			/*
977104862Sru			 * In adhoc demo mode there are no management
978104862Sru			 * frames to use to discover neighbor capabilities,
979104862Sru			 * so blindly propagate the local configuration
980104862Sru			 * so we can do interesting things (e.g. use
981104862Sru			 * WME to disable ACK's).
982104862Sru			 */
983104862Sru			if (ic->ic_flags & IEEE80211_F_WME)
984104862Sru				ni->ni_flags |= IEEE80211_NODE_QOS;
985104862Sru			if (ic->ic_flags & IEEE80211_F_FF)
986104862Sru				ni->ni_flags |= IEEE80211_NODE_FF;
987104862Sru		}
988104862Sru		/* XXX not right for 802.1x/WPA */
989104862Sru		ieee80211_node_authorize(ni);
990104862Sru	}
991104862Sru	return ni;
992104862Sru}
993104862Sru
994104862Sruvoid
995104862Sruieee80211_init_neighbor(struct ieee80211_node *ni,
996104862Sru	const struct ieee80211_frame *wh,
997104862Sru	const struct ieee80211_scanparams *sp)
998104862Sru{
999104862Sru	ni->ni_esslen = sp->ssid[1];
1000104862Sru	memcpy(ni->ni_essid, sp->ssid + 2, sp->ssid[1]);
1001104862Sru	IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
1002104862Sru	memcpy(ni->ni_tstamp.data, sp->tstamp, sizeof(ni->ni_tstamp));
1003104862Sru	ni->ni_intval = sp->bintval;
1004104862Sru	ni->ni_capinfo = sp->capinfo;
1005104862Sru	ni->ni_chan = ni->ni_ic->ic_curchan;
1006104862Sru	ni->ni_fhdwell = sp->fhdwell;
1007104862Sru	ni->ni_fhindex = sp->fhindex;
1008104862Sru	ni->ni_erp = sp->erp;
1009104862Sru	ni->ni_timoff = sp->timoff;
1010104862Sru	if (sp->wme != NULL)
1011104862Sru		ieee80211_saveie(&ni->ni_wme_ie, sp->wme);
1012104862Sru	if (sp->wpa != NULL)
1013104862Sru		ieee80211_saveie(&ni->ni_wpa_ie, sp->wpa);
1014104862Sru	if (sp->rsn != NULL)
1015104862Sru		ieee80211_saveie(&ni->ni_rsn_ie, sp->rsn);
1016104862Sru	if (sp->ath != NULL)
1017104862Sru		ieee80211_saveath(ni, sp->ath);
1018104862Sru
1019104862Sru	/* NB: must be after ni_chan is setup */
1020104862Sru	ieee80211_setup_rates(ni, sp->rates, sp->xrates,
1021104862Sru		IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
1022104862Sru		IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
1023104862Sru}
1024104862Sru
1025104862Sru/*
1026104862Sru * Do node discovery in adhoc mode on receipt of a beacon
1027104862Sru * or probe response frame.  Note that for the driver's
1028104862Sru * benefit we we treat this like an association so the
1029104862Sru * driver has an opportunity to setup it's private state.
1030104862Sru */
1031104862Srustruct ieee80211_node *
1032104862Sruieee80211_add_neighbor(struct ieee80211com *ic,
1033104862Sru	const struct ieee80211_frame *wh,
1034104862Sru	const struct ieee80211_scanparams *sp)
1035104862Sru{
1036104862Sru	struct ieee80211_node *ni;
1037104862Sru
1038104862Sru	IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
1039104862Sru	    "%s: mac<%s>\n", __func__, ether_sprintf(wh->i_addr2));
1040104862Sru	ni = ieee80211_dup_bss(&ic->ic_sta, wh->i_addr2);/* XXX alloc_node? */
1041104862Sru	if (ni != NULL) {
1042104862Sru		ieee80211_init_neighbor(ni, wh, sp);
1043104862Sru		if (ic->ic_newassoc != NULL)
1044104862Sru			ic->ic_newassoc(ni, 1);
1045104862Sru		/* XXX not right for 802.1x/WPA */
1046104862Sru		ieee80211_node_authorize(ni);
1047104862Sru	}
1048104862Sru	return ni;
1049104862Sru}
1050104862Sru
1051104862Sru#define	IS_CTL(wh) \
1052104862Sru	((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)
1053104862Sru#define	IS_PSPOLL(wh) \
1054104862Sru	((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == IEEE80211_FC0_SUBTYPE_PS_POLL)
1055104862Sru#define	IS_BAR(wh) \
1056104862Sru	((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == IEEE80211_FC0_SUBTYPE_BAR)
1057104862Sru
1058104862Sru/*
1059104862Sru * Locate the node for sender, track state, and then pass the
1060104862Sru * (referenced) node up to the 802.11 layer for its use.  We
1061104862Sru * are required to pass some node so we fall back to ic_bss
1062104862Sru * when this frame is from an unknown sender.  The 802.11 layer
1063104862Sru * knows this means the sender wasn't in the node table and
1064104862Sru * acts accordingly.
1065104862Sru */
1066104862Srustruct ieee80211_node *
1067104862Sru#ifdef IEEE80211_DEBUG_REFCNT
1068104862Sruieee80211_find_rxnode_debug(struct ieee80211com *ic,
1069104862Sru	const struct ieee80211_frame_min *wh, const char *func, int line)
1070104862Sru#else
1071104862Sruieee80211_find_rxnode(struct ieee80211com *ic,
1072104862Sru	const struct ieee80211_frame_min *wh)
1073104862Sru#endif
1074104862Sru{
1075104862Sru	struct ieee80211_node_table *nt;
1076104862Sru	struct ieee80211_node *ni;
1077104862Sru
1078104862Sru	/* XXX check ic_bss first in station mode */
1079104862Sru	/* XXX 4-address frames? */
1080104862Sru	nt = &ic->ic_sta;
108169626Sru	IEEE80211_NODE_LOCK(nt);
1082104862Sru	if (IS_CTL(wh) && !IS_PSPOLL(wh) && !IS_BAR(wh) /*&& !IS_RTS(ah)*/)
108369626Sru		ni = _ieee80211_find_node(nt, wh->i_addr1);
1084104862Sru	else
1085104862Sru		ni = _ieee80211_find_node(nt, wh->i_addr2);
1086104862Sru	if (ni == NULL)
1087104862Sru		ni = ieee80211_ref_node(ic->ic_bss);
1088104862Sru	IEEE80211_NODE_UNLOCK(nt);
1089104862Sru
1090104862Sru	return ni;
1091104862Sru}
1092104862Sru
1093104862Sru/*
1094104862Sru * Like ieee80211_find_rxnode but use the supplied h/w
1095104862Sru * key index as a hint to locate the node in the key
1096104862Sru * mapping table.  If an entry is present at the key
1097104862Sru * index we return it; otherwise do a normal lookup and
1098104862Sru * update the mapping table if the station has a unicast
1099104862Sru * key assigned to it.
1100104862Sru */
1101104862Srustruct ieee80211_node *
1102104862Sru#ifdef IEEE80211_DEBUG_REFCNT
1103104862Sruieee80211_find_rxnode_withkey_debug(struct ieee80211com *ic,
1104104862Sru	const struct ieee80211_frame_min *wh, ieee80211_keyix keyix,
1105104862Sru	const char *func, int line)
110669626Sru#else
1107104862Sruieee80211_find_rxnode_withkey(struct ieee80211com *ic,
1108104862Sru	const struct ieee80211_frame_min *wh, ieee80211_keyix keyix)
1109104862Sru#endif
1110104862Sru{
111169626Sru	struct ieee80211_node_table *nt;
1112104862Sru	struct ieee80211_node *ni;
1113104862Sru
1114104862Sru	nt = &ic->ic_sta;
1115104862Sru	IEEE80211_NODE_LOCK(nt);
1116104862Sru	if (nt->nt_keyixmap != NULL && keyix < nt->nt_keyixmax)
1117104862Sru		ni = nt->nt_keyixmap[keyix];
1118104862Sru	else
1119104862Sru		ni = NULL;
112069626Sru	if (ni == NULL) {
1121104862Sru		if (IS_CTL(wh) && !IS_PSPOLL(wh) && !IS_BAR(wh) /*&& !IS_RTS(ah)*/)
1122104862Sru			ni = _ieee80211_find_node(nt, wh->i_addr1);
1123104862Sru		else
1124104862Sru			ni = _ieee80211_find_node(nt, wh->i_addr2);
1125104862Sru		if (ni == NULL)
1126104862Sru			ni = ieee80211_ref_node(ic->ic_bss);
1127104862Sru		if (nt->nt_keyixmap != NULL) {
1128104862Sru			/*
1129104862Sru			 * If the station has a unicast key cache slot
1130104862Sru			 * assigned update the key->node mapping table.
1131104862Sru			 */
1132104862Sru			keyix = ni->ni_ucastkey.wk_rxkeyix;
1133104862Sru			/* XXX can keyixmap[keyix] != NULL? */
1134104862Sru			if (keyix < nt->nt_keyixmax &&
1135104862Sru			    nt->nt_keyixmap[keyix] == NULL) {
1136104862Sru				IEEE80211_DPRINTF(ni->ni_ic, IEEE80211_MSG_NODE,
1137104862Sru				    "%s: add key map entry %p<%s> refcnt %d\n",
1138104862Sru				    __func__, ni, ether_sprintf(ni->ni_macaddr),
1139104862Sru				    ieee80211_node_refcnt(ni)+1);
1140104862Sru				nt->nt_keyixmap[keyix] = ieee80211_ref_node(ni);
1141104862Sru			}
1142104862Sru		}
1143104862Sru	} else
1144104862Sru		ieee80211_ref_node(ni);
1145104862Sru	IEEE80211_NODE_UNLOCK(nt);
1146104862Sru
1147104862Sru	return ni;
1148104862Sru}
1149104862Sru#undef IS_BAR
1150104862Sru#undef IS_PSPOLL
1151104862Sru#undef IS_CTL
1152104862Sru
1153104862Sru/*
1154104862Sru * Return a reference to the appropriate node for sending
1155104862Sru * a data frame.  This handles node discovery in adhoc networks.
1156104862Sru */
1157104862Srustruct ieee80211_node *
1158104862Sru#ifdef IEEE80211_DEBUG_REFCNT
1159104862Sruieee80211_find_txnode_debug(struct ieee80211com *ic, const uint8_t *macaddr,
1160104862Sru	const char *func, int line)
1161104862Sru#else
1162104862Sruieee80211_find_txnode(struct ieee80211com *ic, const uint8_t *macaddr)
1163104862Sru#endif
1164104862Sru{
1165104862Sru	struct ieee80211_node_table *nt = &ic->ic_sta;
1166104862Sru	struct ieee80211_node *ni;
116769626Sru
1168104862Sru	/*
116969626Sru	 * The destination address should be in the node table
1170104862Sru	 * unless this is a multicast/broadcast frame.  We can
1171104862Sru	 * also optimize station mode operation, all frames go
1172151497Sru	 * to the bss node.
1173104862Sru	 */
1174104862Sru	/* XXX can't hold lock across dup_bss 'cuz of recursive locking */
1175104862Sru	IEEE80211_NODE_LOCK(nt);
1176104862Sru	if (ic->ic_opmode == IEEE80211_M_STA || IEEE80211_IS_MULTICAST(macaddr))
117769626Sru		ni = ieee80211_ref_node(ic->ic_bss);
1178104862Sru	else {
1179104862Sru		ni = _ieee80211_find_node(nt, macaddr);
1180104862Sru		if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
1181104862Sru		    (ni != NULL && ni->ni_associd == 0)) {
1182104862Sru			/*
1183104862Sru			 * Station is not associated; don't permit the
1184104862Sru			 * data frame to be sent by returning NULL.  This
1185104862Sru			 * is kinda a kludge but the least intrusive way
118669626Sru			 * to add this check into all drivers.
1187104862Sru			 */
1188104862Sru			ieee80211_unref_node(&ni);	/* NB: null's ni */
1189104862Sru		}
1190104862Sru	}
1191104862Sru	IEEE80211_NODE_UNLOCK(nt);
1192104862Sru
1193104862Sru	if (ni == NULL) {
1194104862Sru		if (ic->ic_opmode == IEEE80211_M_IBSS ||
1195104862Sru		    ic->ic_opmode == IEEE80211_M_AHDEMO) {
1196104862Sru			/*
119769626Sru			 * In adhoc mode cons up a node for the destination.
1198104862Sru			 * Note that we need an additional reference for the
1199104862Sru			 * caller to be consistent with _ieee80211_find_node.
1200104862Sru			 */
1201104862Sru			ni = ieee80211_fakeup_adhoc_node(nt, macaddr);
1202104862Sru			if (ni != NULL)
1203104862Sru				(void) ieee80211_ref_node(ni);
1204104862Sru		} else {
120569626Sru			IEEE80211_DPRINTF(ic, IEEE80211_MSG_OUTPUT,
1206104862Sru				"[%s] no node, discard frame (%s)\n",
1207104862Sru				ether_sprintf(macaddr), __func__);
1208104862Sru			ic->ic_stats.is_tx_nonode++;
1209104862Sru		}
1210104862Sru	}
1211104862Sru	return ni;
1212104862Sru}
1213104862Sru
1214104862Sru/*
1215104862Sru * Like find but search based on the ssid too.
1216104862Sru */
1217104862Srustruct ieee80211_node *
1218104862Sru#ifdef IEEE80211_DEBUG_REFCNT
1219104862Sruieee80211_find_node_with_ssid_debug(struct ieee80211_node_table *nt,
1220104862Sru	const uint8_t *macaddr, u_int ssidlen, const uint8_t *ssid,
1221104862Sru	const char *func, int line)
1222104862Sru#else
122369626Sruieee80211_find_node_with_ssid(struct ieee80211_node_table *nt,
1224104862Sru	const uint8_t *macaddr, u_int ssidlen, const uint8_t *ssid)
122569626Sru#endif
1226104862Sru{
1227104862Sru#define	MATCH_SSID(ni, ssid, ssidlen) \
1228104862Sru	(ni->ni_esslen == ssidlen && memcmp(ni->ni_essid, ssid, ssidlen) == 0)
1229104862Sru	static const uint8_t zeromac[IEEE80211_ADDR_LEN];
1230104862Sru	struct ieee80211_node *ni;
1231104862Sru	int hash;
1232104862Sru
1233104862Sru	IEEE80211_NODE_LOCK(nt);
1234104862Sru	/*
1235104862Sru	 * A mac address that is all zero means match only the ssid;
1236104862Sru	 * otherwise we must match both.
1237104862Sru	 */
1238104862Sru	if (IEEE80211_ADDR_EQ(macaddr, zeromac)) {
1239104862Sru		TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
1240104862Sru			if (MATCH_SSID(ni, ssid, ssidlen))
1241104862Sru				break;
1242104862Sru		}
1243104862Sru	} else {
1244104862Sru		hash = IEEE80211_NODE_HASH(macaddr);
1245104862Sru		LIST_FOREACH(ni, &nt->nt_hash[hash], ni_hash) {
124669626Sru			if (IEEE80211_ADDR_EQ(ni->ni_macaddr, macaddr) &&
1247104862Sru			    MATCH_SSID(ni, ssid, ssidlen))
124869626Sru				break;
1249104862Sru		}
1250151497Sru	}
1251104862Sru	if (ni != NULL) {
1252104862Sru		ieee80211_ref_node(ni);	/* mark referenced */
1253104862Sru		IEEE80211_DPRINTF(nt->nt_ic, IEEE80211_MSG_NODE,
1254104862Sru		     REFCNT_LOC, ni, ether_sprintf(ni->ni_macaddr),
1255104862Sru		     ieee80211_node_refcnt(ni));
1256104862Sru	}
1257104862Sru	IEEE80211_NODE_UNLOCK(nt);
1258104862Sru	return ni;
1259104862Sru#undef MATCH_SSID
1260104862Sru}
1261104862Sru
1262104862Srustatic void
1263104862Sru_ieee80211_free_node(struct ieee80211_node *ni)
1264104862Sru{
1265104862Sru	struct ieee80211com *ic = ni->ni_ic;
1266104862Sru	struct ieee80211_node_table *nt = ni->ni_table;
1267104862Sru
1268104862Sru	IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
1269104862Sru		"%s %p<%s> in %s table\n", __func__, ni,
1270151497Sru		ether_sprintf(ni->ni_macaddr),
1271104862Sru		nt != NULL ? nt->nt_name : "<gone>");
127269626Sru
1273104862Sru	IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap);
127469626Sru	if (nt != NULL) {
127579543Sru		TAILQ_REMOVE(&nt->nt_node, ni, ni_list);
127679543Sru		LIST_REMOVE(ni, ni_hash);
127779543Sru	}
127879543Sru	ic->ic_node_free(ni);
1279}
1280
1281void
1282#ifdef IEEE80211_DEBUG_REFCNT
1283ieee80211_free_node_debug(struct ieee80211_node *ni, const char *func, int line)
1284#else
1285ieee80211_free_node(struct ieee80211_node *ni)
1286#endif
1287{
1288	struct ieee80211_node_table *nt = ni->ni_table;
1289
1290#ifdef IEEE80211_DEBUG_REFCNT
1291	IEEE80211_DPRINTF(ni->ni_ic, IEEE80211_MSG_NODE,
1292		"%s (%s:%u) %p<%s> refcnt %d\n", __func__, func, line, ni,
1293		 ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)-1);
1294#endif
1295	if (nt != NULL) {
1296		IEEE80211_NODE_LOCK(nt);
1297		if (ieee80211_node_dectestref(ni)) {
1298			/*
1299			 * Last reference, reclaim state.
1300			 */
1301			_ieee80211_free_node(ni);
1302		} else if (ieee80211_node_refcnt(ni) == 1 &&
1303		    nt->nt_keyixmap != NULL) {
1304			ieee80211_keyix keyix;
1305			/*
1306			 * Check for a last reference in the key mapping table.
1307			 */
1308			keyix = ni->ni_ucastkey.wk_rxkeyix;
1309			if (keyix < nt->nt_keyixmax &&
1310			    nt->nt_keyixmap[keyix] == ni) {
1311				IEEE80211_DPRINTF(ni->ni_ic, IEEE80211_MSG_NODE,
1312				    "%s: %p<%s> clear key map entry", __func__,
1313				    ni, ether_sprintf(ni->ni_macaddr));
1314				nt->nt_keyixmap[keyix] = NULL;
1315				ieee80211_node_decref(ni); /* XXX needed? */
1316				_ieee80211_free_node(ni);
1317			}
1318		}
1319		IEEE80211_NODE_UNLOCK(nt);
1320	} else {
1321		if (ieee80211_node_dectestref(ni))
1322			_ieee80211_free_node(ni);
1323	}
1324}
1325
1326/*
1327 * Reclaim a unicast key and clear any key cache state.
1328 */
1329int
1330ieee80211_node_delucastkey(struct ieee80211_node *ni)
1331{
1332	struct ieee80211com *ic = ni->ni_ic;
1333	struct ieee80211_node_table *nt = &ic->ic_sta;
1334	struct ieee80211_node *nikey;
1335	ieee80211_keyix keyix;
1336	int isowned, status;
1337
1338	/*
1339	 * NB: We must beware of LOR here; deleting the key
1340	 * can cause the crypto layer to block traffic updates
1341	 * which can generate a LOR against the node table lock;
1342	 * grab it here and stash the key index for our use below.
1343	 *
1344	 * Must also beware of recursion on the node table lock.
1345	 * When called from node_cleanup we may already have
1346	 * the node table lock held.  Unfortunately there's no
1347	 * way to separate out this path so we must do this
1348	 * conditionally.
1349	 */
1350	isowned = IEEE80211_NODE_IS_LOCKED(nt);
1351	if (!isowned)
1352		IEEE80211_NODE_LOCK(nt);
1353	keyix = ni->ni_ucastkey.wk_rxkeyix;
1354	status = ieee80211_crypto_delkey(ic, &ni->ni_ucastkey);
1355	if (nt->nt_keyixmap != NULL && keyix < nt->nt_keyixmax) {
1356		nikey = nt->nt_keyixmap[keyix];
1357		nt->nt_keyixmap[keyix] = NULL;;
1358	} else
1359		nikey = NULL;
1360	if (!isowned)
1361		IEEE80211_NODE_UNLOCK(&ic->ic_sta);
1362
1363	if (nikey != NULL) {
1364		KASSERT(nikey == ni,
1365			("key map out of sync, ni %p nikey %p", ni, nikey));
1366		IEEE80211_DPRINTF(ni->ni_ic, IEEE80211_MSG_NODE,
1367			"%s: delete key map entry %p<%s> refcnt %d\n",
1368			__func__, ni, ether_sprintf(ni->ni_macaddr),
1369			ieee80211_node_refcnt(ni)-1);
1370		ieee80211_free_node(ni);
1371	}
1372	return status;
1373}
1374
1375/*
1376 * Reclaim a node.  If this is the last reference count then
1377 * do the normal free work.  Otherwise remove it from the node
1378 * table and mark it gone by clearing the back-reference.
1379 */
1380static void
1381node_reclaim(struct ieee80211_node_table *nt, struct ieee80211_node *ni)
1382{
1383	ieee80211_keyix keyix;
1384
1385	IEEE80211_NODE_LOCK_ASSERT(nt);
1386
1387	IEEE80211_DPRINTF(ni->ni_ic, IEEE80211_MSG_NODE,
1388		"%s: remove %p<%s> from %s table, refcnt %d\n",
1389		__func__, ni, ether_sprintf(ni->ni_macaddr),
1390		nt->nt_name, ieee80211_node_refcnt(ni)-1);
1391	/*
1392	 * Clear any entry in the unicast key mapping table.
1393	 * We need to do it here so rx lookups don't find it
1394	 * in the mapping table even if it's not in the hash
1395	 * table.  We cannot depend on the mapping table entry
1396	 * being cleared because the node may not be free'd.
1397	 */
1398	keyix = ni->ni_ucastkey.wk_rxkeyix;
1399	if (nt->nt_keyixmap != NULL && keyix < nt->nt_keyixmax &&
1400	    nt->nt_keyixmap[keyix] == ni) {
1401		IEEE80211_DPRINTF(ni->ni_ic, IEEE80211_MSG_NODE,
1402			"%s: %p<%s> clear key map entry\n",
1403			__func__, ni, ether_sprintf(ni->ni_macaddr));
1404		nt->nt_keyixmap[keyix] = NULL;
1405		ieee80211_node_decref(ni);	/* NB: don't need free */
1406	}
1407	if (!ieee80211_node_dectestref(ni)) {
1408		/*
1409		 * Other references are present, just remove the
1410		 * node from the table so it cannot be found.  When
1411		 * the references are dropped storage will be
1412		 * reclaimed.
1413		 */
1414		TAILQ_REMOVE(&nt->nt_node, ni, ni_list);
1415		LIST_REMOVE(ni, ni_hash);
1416		ni->ni_table = NULL;		/* clear reference */
1417	} else
1418		_ieee80211_free_node(ni);
1419}
1420
1421static void
1422ieee80211_free_allnodes_locked(struct ieee80211_node_table *nt)
1423{
1424	struct ieee80211com *ic = nt->nt_ic;
1425	struct ieee80211_node *ni;
1426
1427	IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
1428		"%s: free all nodes in %s table\n", __func__, nt->nt_name);
1429
1430	while ((ni = TAILQ_FIRST(&nt->nt_node)) != NULL) {
1431		if (ni->ni_associd != 0) {
1432			if (ic->ic_auth->ia_node_leave != NULL)
1433				ic->ic_auth->ia_node_leave(ic, ni);
1434			IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap);
1435		}
1436		node_reclaim(nt, ni);
1437	}
1438}
1439
1440/*
1441 * Timeout inactive stations and do related housekeeping.
1442 * Note that we cannot hold the node lock while sending a
1443 * frame as this would lead to a LOR.  Instead we use a
1444 * generation number to mark nodes that we've scanned and
1445 * drop the lock and restart a scan if we have to time out
1446 * a node.  Since we are single-threaded by virtue of
1447 * controlling the inactivity timer we can be sure this will
1448 * process each node only once.
1449 */
1450static void
1451ieee80211_timeout_stations(struct ieee80211_node_table *nt)
1452{
1453	struct ieee80211com *ic = nt->nt_ic;
1454	struct ieee80211_node *ni;
1455	u_int gen;
1456	int isadhoc;
1457
1458	isadhoc = (ic->ic_opmode == IEEE80211_M_IBSS ||
1459		   ic->ic_opmode == IEEE80211_M_AHDEMO);
1460	IEEE80211_SCAN_LOCK(nt);
1461	gen = ++nt->nt_scangen;
1462restart:
1463	IEEE80211_NODE_LOCK(nt);
1464	TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
1465		if (ni->ni_scangen == gen)	/* previously handled */
1466			continue;
1467		ni->ni_scangen = gen;
1468		/*
1469		 * Ignore entries for which have yet to receive an
1470		 * authentication frame.  These are transient and
1471		 * will be reclaimed when the last reference to them
1472		 * goes away (when frame xmits complete).
1473		 */
1474		if ((ic->ic_opmode == IEEE80211_M_HOSTAP ||
1475		     ic->ic_opmode == IEEE80211_M_STA) &&
1476		    (ni->ni_flags & IEEE80211_NODE_AREF) == 0)
1477			continue;
1478		/*
1479		 * Free fragment if not needed anymore
1480		 * (last fragment older than 1s).
1481		 * XXX doesn't belong here
1482		 */
1483		if (ni->ni_rxfrag[0] != NULL &&
1484		    ticks > ni->ni_rxfragstamp + hz) {
1485			m_freem(ni->ni_rxfrag[0]);
1486			ni->ni_rxfrag[0] = NULL;
1487		}
1488		if (ni->ni_inact > 0)
1489			ni->ni_inact--;
1490		/*
1491		 * Special case ourself; we may be idle for extended periods
1492		 * of time and regardless reclaiming our state is wrong.
1493		 */
1494		if (ni == ic->ic_bss)
1495			continue;
1496		if (ni->ni_associd != 0 || isadhoc) {
1497			/*
1498			 * Age frames on the power save queue.
1499			 */
1500			if (ieee80211_node_saveq_age(ni) != 0 &&
1501			    IEEE80211_NODE_SAVEQ_QLEN(ni) == 0 &&
1502			    ic->ic_set_tim != NULL)
1503				ic->ic_set_tim(ni, 0);
1504			/*
1505			 * Probe the station before time it out.  We
1506			 * send a null data frame which may not be
1507			 * universally supported by drivers (need it
1508			 * for ps-poll support so it should be...).
1509			 *
1510			 * XXX don't probe the station unless we've
1511			 *     received a frame from them (and have
1512			 *     some idea of the rates they are capable
1513			 *     of); this will get fixed more properly
1514			 *     soon with better handling of the rate set.
1515			 */
1516			if ((ic->ic_flags_ext & IEEE80211_FEXT_INACT) &&
1517			    (0 < ni->ni_inact &&
1518			     ni->ni_inact <= ic->ic_inact_probe) &&
1519			    ni->ni_rates.rs_nrates != 0) {
1520				IEEE80211_NOTE(ic,
1521				    IEEE80211_MSG_INACT | IEEE80211_MSG_NODE,
1522				    ni, "%s",
1523				    "probe station due to inactivity");
1524				/*
1525				 * Grab a reference before unlocking the table
1526				 * so the node cannot be reclaimed before we
1527				 * send the frame. ieee80211_send_nulldata
1528				 * understands we've done this and reclaims the
1529				 * ref for us as needed.
1530				 */
1531				ieee80211_ref_node(ni);
1532				IEEE80211_NODE_UNLOCK(nt);
1533				ieee80211_send_nulldata(ni);
1534				/* XXX stat? */
1535				goto restart;
1536			}
1537		}
1538		if ((ic->ic_flags_ext & IEEE80211_FEXT_INACT) &&
1539		    ni->ni_inact <= 0) {
1540			IEEE80211_NOTE(ic,
1541			    IEEE80211_MSG_INACT | IEEE80211_MSG_NODE, ni,
1542			    "station timed out due to inactivity "
1543			    "(refcnt %u)", ieee80211_node_refcnt(ni));
1544			/*
1545			 * Send a deauthenticate frame and drop the station.
1546			 * This is somewhat complicated due to reference counts
1547			 * and locking.  At this point a station will typically
1548			 * have a reference count of 1.  ieee80211_node_leave
1549			 * will do a "free" of the node which will drop the
1550			 * reference count.  But in the meantime a reference
1551			 * wil be held by the deauth frame.  The actual reclaim
1552			 * of the node will happen either after the tx is
1553			 * completed or by ieee80211_node_leave.
1554			 *
1555			 * Separately we must drop the node lock before sending
1556			 * in case the driver takes a lock, as this can result
1557			 * in a LOR between the node lock and the driver lock.
1558			 */
1559			ieee80211_ref_node(ni);
1560			IEEE80211_NODE_UNLOCK(nt);
1561			if (ni->ni_associd != 0) {
1562				IEEE80211_SEND_MGMT(ic, ni,
1563				    IEEE80211_FC0_SUBTYPE_DEAUTH,
1564				    IEEE80211_REASON_AUTH_EXPIRE);
1565			}
1566			ieee80211_node_leave(ic, ni);
1567			ieee80211_free_node(ni);
1568			ic->ic_stats.is_node_timeout++;
1569			goto restart;
1570		}
1571	}
1572	IEEE80211_NODE_UNLOCK(nt);
1573
1574	IEEE80211_SCAN_UNLOCK(nt);
1575}
1576
1577void
1578ieee80211_node_timeout(void *arg)
1579{
1580	struct ieee80211com *ic = arg;
1581
1582	ieee80211_scan_timeout(ic);
1583	ieee80211_timeout_stations(&ic->ic_sta);
1584
1585	IEEE80211_LOCK(ic);
1586	ieee80211_erp_timeout(ic);
1587	ieee80211_ht_timeout(ic);
1588	IEEE80211_UNLOCK(ic);
1589
1590	callout_reset(&ic->ic_inact, IEEE80211_INACT_WAIT*hz,
1591		ieee80211_node_timeout, ic);
1592}
1593
1594void
1595ieee80211_iterate_nodes(struct ieee80211_node_table *nt, ieee80211_iter_func *f, void *arg)
1596{
1597	struct ieee80211_node *ni;
1598	u_int gen;
1599
1600	IEEE80211_SCAN_LOCK(nt);
1601	gen = ++nt->nt_scangen;
1602restart:
1603	IEEE80211_NODE_LOCK(nt);
1604	TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
1605		if (ni->ni_scangen != gen) {
1606			ni->ni_scangen = gen;
1607			(void) ieee80211_ref_node(ni);
1608			IEEE80211_NODE_UNLOCK(nt);
1609			(*f)(arg, ni);
1610			ieee80211_free_node(ni);
1611			goto restart;
1612		}
1613	}
1614	IEEE80211_NODE_UNLOCK(nt);
1615
1616	IEEE80211_SCAN_UNLOCK(nt);
1617}
1618
1619void
1620ieee80211_dump_node(struct ieee80211_node_table *nt, struct ieee80211_node *ni)
1621{
1622	printf("0x%p: mac %s refcnt %d\n", ni,
1623		ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni));
1624	printf("\tscangen %u authmode %u flags 0x%x\n",
1625		ni->ni_scangen, ni->ni_authmode, ni->ni_flags);
1626	printf("\tassocid 0x%x txpower %u vlan %u\n",
1627		ni->ni_associd, ni->ni_txpower, ni->ni_vlan);
1628	printf("\ttxseq %u rxseq %u fragno %u rxfragstamp %u\n",
1629		ni->ni_txseqs[IEEE80211_NONQOS_TID],
1630		ni->ni_rxseqs[IEEE80211_NONQOS_TID] >> IEEE80211_SEQ_SEQ_SHIFT,
1631		ni->ni_rxseqs[IEEE80211_NONQOS_TID] & IEEE80211_SEQ_FRAG_MASK,
1632		ni->ni_rxfragstamp);
1633	printf("\trstamp %u rssi %d noise %d intval %u capinfo 0x%x\n",
1634		ni->ni_rstamp, ni->ni_rssi, ni->ni_noise,
1635		ni->ni_intval, ni->ni_capinfo);
1636	printf("\tbssid %s essid \"%.*s\" channel %u:0x%x\n",
1637		ether_sprintf(ni->ni_bssid),
1638		ni->ni_esslen, ni->ni_essid,
1639		ni->ni_chan->ic_freq, ni->ni_chan->ic_flags);
1640	printf("\tfails %u inact %u txrate %u\n",
1641		ni->ni_fails, ni->ni_inact, ni->ni_txrate);
1642	printf("\thtcap %x htparam %x htctlchan %u ht2ndchan %u\n",
1643		ni->ni_htcap, ni->ni_htparam,
1644		ni->ni_htctlchan, ni->ni_ht2ndchan);
1645	printf("\thtopmode %x htstbc %x chw %u\n",
1646		ni->ni_htopmode, ni->ni_htstbc, ni->ni_chw);
1647}
1648
1649void
1650ieee80211_dump_nodes(struct ieee80211_node_table *nt)
1651{
1652	ieee80211_iterate_nodes(nt,
1653		(ieee80211_iter_func *) ieee80211_dump_node, nt);
1654}
1655
1656void
1657ieee80211_notify_erp(struct ieee80211com *ic)
1658{
1659	if (ic->ic_opmode == IEEE80211_M_HOSTAP)
1660		ieee80211_beacon_notify(ic, IEEE80211_BEACON_ERP);
1661}
1662
1663/*
1664 * Handle a station joining an 11g network.
1665 */
1666static void
1667ieee80211_node_join_11g(struct ieee80211com *ic, struct ieee80211_node *ni)
1668{
1669
1670	IEEE80211_LOCK_ASSERT(ic);
1671
1672	/*
1673	 * Station isn't capable of short slot time.  Bump
1674	 * the count of long slot time stations and disable
1675	 * use of short slot time.  Note that the actual switch
1676	 * over to long slot time use may not occur until the
1677	 * next beacon transmission (per sec. 7.3.1.4 of 11g).
1678	 */
1679	if ((ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME) == 0) {
1680		ic->ic_longslotsta++;
1681		IEEE80211_NOTE(ic, IEEE80211_MSG_ASSOC, ni,
1682		    "station needs long slot time, count %d",
1683		    ic->ic_longslotsta);
1684		/* XXX vap's w/ conflicting needs won't work */
1685		if (!IEEE80211_IS_CHAN_108G(ic->ic_bsschan)) {
1686			/*
1687			 * Don't force slot time when switched to turbo
1688			 * mode as non-ERP stations won't be present; this
1689			 * need only be done when on the normal G channel.
1690			 */
1691			ieee80211_set_shortslottime(ic, 0);
1692		}
1693	}
1694	/*
1695	 * If the new station is not an ERP station
1696	 * then bump the counter and enable protection
1697	 * if configured.
1698	 */
1699	if (!ieee80211_iserp_rateset(ic, &ni->ni_rates)) {
1700		ic->ic_nonerpsta++;
1701		IEEE80211_NOTE(ic, IEEE80211_MSG_ASSOC, ni,
1702		    "station is !ERP, %d non-ERP stations associated",
1703		    ic->ic_nonerpsta);
1704		/*
1705		 * If station does not support short preamble
1706		 * then we must enable use of Barker preamble.
1707		 */
1708		if ((ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE) == 0) {
1709			IEEE80211_NOTE(ic, IEEE80211_MSG_ASSOC, ni,
1710			    "%s", "station needs long preamble");
1711			ic->ic_flags |= IEEE80211_F_USEBARKER;
1712			ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE;
1713		}
1714		/*
1715		 * If protection is configured, enable it.
1716		 */
1717		if (ic->ic_protmode != IEEE80211_PROT_NONE &&
1718		    ic->ic_nonerpsta == 1 &&
1719		    (ic->ic_flags_ext & IEEE80211_FEXT_NONERP_PR) == 0) {
1720			IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
1721			    "%s: enable use of protection\n", __func__);
1722			ic->ic_flags |= IEEE80211_F_USEPROT;
1723			ieee80211_notify_erp(ic);
1724		}
1725	} else
1726		ni->ni_flags |= IEEE80211_NODE_ERP;
1727}
1728
1729void
1730ieee80211_node_join(struct ieee80211com *ic, struct ieee80211_node *ni, int resp)
1731{
1732	int newassoc;
1733
1734	if (ni->ni_associd == 0) {
1735		uint16_t aid;
1736
1737		IEEE80211_LOCK(ic);
1738		/*
1739		 * It would be good to search the bitmap
1740		 * more efficiently, but this will do for now.
1741		 */
1742		for (aid = 1; aid < ic->ic_max_aid; aid++) {
1743			if (!IEEE80211_AID_ISSET(aid,
1744			    ic->ic_aid_bitmap))
1745				break;
1746		}
1747		if (aid >= ic->ic_max_aid) {
1748			IEEE80211_UNLOCK(ic);
1749			IEEE80211_SEND_MGMT(ic, ni, resp,
1750			    IEEE80211_REASON_ASSOC_TOOMANY);
1751			ieee80211_node_leave(ic, ni);
1752			return;
1753		}
1754		ni->ni_associd = aid | 0xc000;
1755		ni->ni_jointime = time_uptime;
1756		IEEE80211_AID_SET(ni->ni_associd, ic->ic_aid_bitmap);
1757		ic->ic_sta_assoc++;
1758
1759		if (IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
1760			ieee80211_ht_node_join(ni);
1761		if (IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan) &&
1762		    IEEE80211_IS_CHAN_FULL(ic->ic_bsschan))
1763			ieee80211_node_join_11g(ic, ni);
1764		IEEE80211_UNLOCK(ic);
1765
1766		newassoc = 1;
1767	} else
1768		newassoc = 0;
1769
1770	IEEE80211_NOTE(ic, IEEE80211_MSG_ASSOC | IEEE80211_MSG_DEBUG, ni,
1771	    "station %sassociated at aid %d: %s preamble, %s slot time%s%s%s%s%s%s",
1772	    newassoc ? "" : "re",
1773	    IEEE80211_NODE_AID(ni),
1774	    ic->ic_flags & IEEE80211_F_SHPREAMBLE ? "short" : "long",
1775	    ic->ic_flags & IEEE80211_F_SHSLOT ? "short" : "long",
1776	    ic->ic_flags & IEEE80211_F_USEPROT ? ", protection" : "",
1777	    ni->ni_flags & IEEE80211_NODE_QOS ? ", QoS" : "",
1778	    ni->ni_flags & IEEE80211_NODE_HT ?
1779		(ni->ni_chw == 20 ? ", HT20" : ", HT40") : "",
1780	    ni->ni_flags & IEEE80211_NODE_AMPDU ? " (+AMPDU)" : "",
1781	    IEEE80211_ATH_CAP(ic, ni, IEEE80211_NODE_FF) ?
1782		", fast-frames" : "",
1783	    IEEE80211_ATH_CAP(ic, ni, IEEE80211_NODE_TURBOP) ?
1784		", turbo" : ""
1785	);
1786
1787	/* give driver a chance to setup state like ni_txrate */
1788	if (ic->ic_newassoc != NULL)
1789		ic->ic_newassoc(ni, newassoc);
1790	IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_SUCCESS);
1791	/* tell the authenticator about new station */
1792	if (ic->ic_auth->ia_node_join != NULL)
1793		ic->ic_auth->ia_node_join(ic, ni);
1794	ieee80211_notify_node_join(ic, ni, newassoc);
1795}
1796
1797static void
1798disable_protection(struct ieee80211com *ic)
1799{
1800	KASSERT(ic->ic_nonerpsta == 0 &&
1801	    (ic->ic_flags_ext & IEEE80211_FEXT_NONERP_PR) == 0,
1802	   ("%d non ERP stations, flags 0x%x", ic->ic_nonerpsta,
1803	   ic->ic_flags_ext));
1804
1805	ic->ic_flags &= ~IEEE80211_F_USEPROT;
1806	/* XXX verify mode? */
1807	if (ic->ic_caps & IEEE80211_C_SHPREAMBLE) {
1808		ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
1809		ic->ic_flags &= ~IEEE80211_F_USEBARKER;
1810	}
1811	ieee80211_notify_erp(ic);
1812}
1813
1814/*
1815 * Handle a station leaving an 11g network.
1816 */
1817static void
1818ieee80211_node_leave_11g(struct ieee80211com *ic, struct ieee80211_node *ni)
1819{
1820
1821	IEEE80211_LOCK_ASSERT(ic);
1822
1823	KASSERT(IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan),
1824	     ("not in 11g, bss %u:0x%x, curmode %u", ic->ic_bsschan->ic_freq,
1825	      ic->ic_bsschan->ic_flags, ic->ic_curmode));
1826
1827	/*
1828	 * If a long slot station do the slot time bookkeeping.
1829	 */
1830	if ((ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME) == 0) {
1831		KASSERT(ic->ic_longslotsta > 0,
1832		    ("bogus long slot station count %d", ic->ic_longslotsta));
1833		ic->ic_longslotsta--;
1834		IEEE80211_NOTE(ic, IEEE80211_MSG_ASSOC, ni,
1835		    "long slot time station leaves, count now %d",
1836		    ic->ic_longslotsta);
1837		if (ic->ic_longslotsta == 0) {
1838			/*
1839			 * Re-enable use of short slot time if supported
1840			 * and not operating in IBSS mode (per spec).
1841			 */
1842			if ((ic->ic_caps & IEEE80211_C_SHSLOT) &&
1843			    ic->ic_opmode != IEEE80211_M_IBSS) {
1844				IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
1845				    "%s: re-enable use of short slot time\n",
1846				    __func__);
1847				ieee80211_set_shortslottime(ic, 1);
1848			}
1849		}
1850	}
1851	/*
1852	 * If a non-ERP station do the protection-related bookkeeping.
1853	 */
1854	if ((ni->ni_flags & IEEE80211_NODE_ERP) == 0) {
1855		KASSERT(ic->ic_nonerpsta > 0,
1856		    ("bogus non-ERP station count %d", ic->ic_nonerpsta));
1857		ic->ic_nonerpsta--;
1858		IEEE80211_NOTE(ic, IEEE80211_MSG_ASSOC, ni,
1859		    "non-ERP station leaves, count now %d%s", ic->ic_nonerpsta,
1860		    (ic->ic_flags_ext & IEEE80211_FEXT_NONERP_PR) ?
1861			" (non-ERP sta present)" : "");
1862		if (ic->ic_nonerpsta == 0 &&
1863		    (ic->ic_flags_ext & IEEE80211_FEXT_NONERP_PR) == 0) {
1864			IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
1865				"%s: disable use of protection\n", __func__);
1866			disable_protection(ic);
1867		}
1868	}
1869}
1870
1871/*
1872 * Time out presence of an overlapping bss with non-ERP
1873 * stations.  When operating in hostap mode we listen for
1874 * beacons from other stations and if we identify a non-ERP
1875 * station is present we enable protection.  To identify
1876 * when all non-ERP stations are gone we time out this
1877 * condition.
1878 */
1879static void
1880ieee80211_erp_timeout(struct ieee80211com *ic)
1881{
1882
1883	IEEE80211_LOCK_ASSERT(ic);
1884
1885	if ((ic->ic_flags_ext & IEEE80211_FEXT_NONERP_PR) &&
1886	    time_after(ticks, ic->ic_lastnonerp + IEEE80211_NONERP_PRESENT_AGE)) {
1887		IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
1888		    "%s\n", "age out non-ERP sta present on channel");
1889		ic->ic_flags_ext &= ~IEEE80211_FEXT_NONERP_PR;
1890		if (ic->ic_nonerpsta == 0)
1891			disable_protection(ic);
1892	}
1893}
1894
1895/*
1896 * Handle bookkeeping for station deauthentication/disassociation
1897 * when operating as an ap.
1898 */
1899void
1900ieee80211_node_leave(struct ieee80211com *ic, struct ieee80211_node *ni)
1901{
1902	struct ieee80211_node_table *nt = ni->ni_table;
1903
1904	IEEE80211_NOTE(ic, IEEE80211_MSG_ASSOC | IEEE80211_MSG_DEBUG, ni,
1905	    "station with aid %d leaves", IEEE80211_NODE_AID(ni));
1906
1907	KASSERT(ic->ic_opmode != IEEE80211_M_STA,
1908		("unexpected operating mode %u", ic->ic_opmode));
1909	/*
1910	 * If node wasn't previously associated all
1911	 * we need to do is reclaim the reference.
1912	 */
1913	/* XXX ibss mode bypasses 11g and notification */
1914	if (ni->ni_associd == 0)
1915		goto done;
1916	/*
1917	 * Tell the authenticator the station is leaving.
1918	 * Note that we must do this before yanking the
1919	 * association id as the authenticator uses the
1920	 * associd to locate it's state block.
1921	 */
1922	if (ic->ic_auth->ia_node_leave != NULL)
1923		ic->ic_auth->ia_node_leave(ic, ni);
1924
1925	IEEE80211_LOCK(ic);
1926	IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap);
1927	ni->ni_associd = 0;
1928	ic->ic_sta_assoc--;
1929
1930	if (IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
1931		ieee80211_ht_node_leave(ni);
1932	if (IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan) &&
1933	    IEEE80211_IS_CHAN_FULL(ic->ic_bsschan))
1934		ieee80211_node_leave_11g(ic, ni);
1935	IEEE80211_UNLOCK(ic);
1936	/*
1937	 * Cleanup station state.  In particular clear various
1938	 * state that might otherwise be reused if the node
1939	 * is reused before the reference count goes to zero
1940	 * (and memory is reclaimed).
1941	 */
1942	ieee80211_sta_leave(ic, ni);
1943done:
1944	/*
1945	 * Remove the node from any table it's recorded in and
1946	 * drop the caller's reference.  Removal from the table
1947	 * is important to insure the node is not reprocessed
1948	 * for inactivity.
1949	 */
1950	if (nt != NULL) {
1951		IEEE80211_NODE_LOCK(nt);
1952		node_reclaim(nt, ni);
1953		IEEE80211_NODE_UNLOCK(nt);
1954	} else
1955		ieee80211_free_node(ni);
1956}
1957
1958int8_t
1959ieee80211_getrssi(struct ieee80211com *ic)
1960{
1961#define	NZ(x)	((x) == 0 ? 1 : (x))
1962	struct ieee80211_node_table *nt = &ic->ic_sta;
1963	int rssi_samples;
1964	int32_t rssi_total;
1965	struct ieee80211_node *ni;
1966
1967	rssi_total = 0;
1968	rssi_samples = 0;
1969	switch (ic->ic_opmode) {
1970	case IEEE80211_M_IBSS:		/* average of all ibss neighbors */
1971	case IEEE80211_M_AHDEMO:	/* average of all neighbors */
1972	case IEEE80211_M_HOSTAP:	/* average of all associated stations */
1973		/* XXX locking */
1974		TAILQ_FOREACH(ni, &nt->nt_node, ni_list)
1975			if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
1976			    (ni->ni_capinfo & IEEE80211_CAPINFO_IBSS)) {
1977				int8_t rssi = ic->ic_node_getrssi(ni);
1978				if (rssi != 0) {
1979					rssi_samples++;
1980					rssi_total += rssi;
1981				}
1982			}
1983		break;
1984	case IEEE80211_M_MONITOR:	/* XXX */
1985	case IEEE80211_M_STA:		/* use stats from associated ap */
1986	default:
1987		if (ic->ic_bss != NULL)
1988			rssi_total = ic->ic_node_getrssi(ic->ic_bss);
1989		rssi_samples = 1;
1990		break;
1991	}
1992	return rssi_total / NZ(rssi_samples);
1993#undef NZ
1994}
1995
1996void
1997ieee80211_getsignal(struct ieee80211com *ic, int8_t *rssi, int8_t *noise)
1998{
1999
2000	if (ic->ic_bss == NULL)		/* NB: shouldn't happen */
2001		return;
2002	ic->ic_node_getsignal(ic->ic_bss, rssi, noise);
2003	/* for non-station mode return avg'd rssi accounting */
2004	if (ic->ic_opmode != IEEE80211_M_STA)
2005		*rssi = ieee80211_getrssi(ic);
2006}
2007
2008/*
2009 * Node table support.
2010 */
2011
2012static void
2013ieee80211_node_table_init(struct ieee80211com *ic,
2014	struct ieee80211_node_table *nt,
2015	const char *name, int inact, int keyixmax)
2016{
2017
2018	IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
2019		"%s %s table, inact %u\n", __func__, name, inact);
2020
2021	nt->nt_ic = ic;
2022	/* XXX need unit */
2023	IEEE80211_NODE_LOCK_INIT(nt, ic->ic_ifp->if_xname);
2024	IEEE80211_SCAN_LOCK_INIT(nt, ic->ic_ifp->if_xname);
2025	TAILQ_INIT(&nt->nt_node);
2026	nt->nt_name = name;
2027	nt->nt_scangen = 1;
2028	nt->nt_inact_init = inact;
2029	nt->nt_keyixmax = keyixmax;
2030	if (nt->nt_keyixmax > 0) {
2031		MALLOC(nt->nt_keyixmap, struct ieee80211_node **,
2032			keyixmax * sizeof(struct ieee80211_node *),
2033			M_80211_NODE, M_NOWAIT | M_ZERO);
2034		if (nt->nt_keyixmap == NULL)
2035			if_printf(ic->ic_ifp,
2036			    "Cannot allocate key index map with %u entries\n",
2037			    keyixmax);
2038	} else
2039		nt->nt_keyixmap = NULL;
2040}
2041
2042static void
2043ieee80211_node_table_reset(struct ieee80211_node_table *nt)
2044{
2045
2046	IEEE80211_DPRINTF(nt->nt_ic, IEEE80211_MSG_NODE,
2047		"%s %s table\n", __func__, nt->nt_name);
2048
2049	IEEE80211_NODE_LOCK(nt);
2050	ieee80211_free_allnodes_locked(nt);
2051	IEEE80211_NODE_UNLOCK(nt);
2052}
2053
2054static void
2055ieee80211_node_table_cleanup(struct ieee80211_node_table *nt)
2056{
2057
2058	IEEE80211_DPRINTF(nt->nt_ic, IEEE80211_MSG_NODE,
2059		"%s %s table\n", __func__, nt->nt_name);
2060
2061	IEEE80211_NODE_LOCK(nt);
2062	ieee80211_free_allnodes_locked(nt);
2063	if (nt->nt_keyixmap != NULL) {
2064		/* XXX verify all entries are NULL */
2065		int i;
2066		for (i = 0; i < nt->nt_keyixmax; i++)
2067			if (nt->nt_keyixmap[i] != NULL)
2068				printf("%s: %s[%u] still active\n", __func__,
2069					nt->nt_name, i);
2070		FREE(nt->nt_keyixmap, M_80211_NODE);
2071		nt->nt_keyixmap = NULL;
2072	}
2073	IEEE80211_SCAN_LOCK_DESTROY(nt);
2074	IEEE80211_NODE_LOCK_DESTROY(nt);
2075}
2076