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