Home | History | Annotate | Line # | Download | only in net80211
ieee80211_node.c revision 1.60.4.1
      1      1.60    dyoung /*	$NetBSD: ieee80211_node.c,v 1.60.4.1 2008/02/22 16:50:25 skrll Exp $	*/
      2       1.1    dyoung /*-
      3       1.1    dyoung  * Copyright (c) 2001 Atsushi Onoe
      4  1.60.4.1     skrll  * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting
      5       1.1    dyoung  * All rights reserved.
      6       1.1    dyoung  *
      7       1.1    dyoung  * Redistribution and use in source and binary forms, with or without
      8       1.1    dyoung  * modification, are permitted provided that the following conditions
      9       1.1    dyoung  * are met:
     10       1.1    dyoung  * 1. Redistributions of source code must retain the above copyright
     11       1.1    dyoung  *    notice, this list of conditions and the following disclaimer.
     12       1.1    dyoung  * 2. Redistributions in binary form must reproduce the above copyright
     13       1.1    dyoung  *    notice, this list of conditions and the following disclaimer in the
     14       1.1    dyoung  *    documentation and/or other materials provided with the distribution.
     15       1.1    dyoung  *
     16       1.1    dyoung  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17       1.1    dyoung  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18       1.1    dyoung  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19       1.1    dyoung  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20       1.1    dyoung  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     21       1.1    dyoung  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     22       1.1    dyoung  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     23       1.1    dyoung  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24       1.1    dyoung  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     25       1.1    dyoung  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26       1.1    dyoung  */
     27       1.1    dyoung 
     28       1.1    dyoung #include <sys/cdefs.h>
     29       1.3    dyoung #ifdef __FreeBSD__
     30  1.60.4.1     skrll __FBSDID("$FreeBSD: src/sys/net80211/ieee80211_node.c,v 1.91 2007/11/23 06:23:12 sam Exp $");
     31      1.39    dyoung #endif
     32      1.39    dyoung #ifdef __NetBSD__
     33      1.60    dyoung __KERNEL_RCSID(0, "$NetBSD: ieee80211_node.c,v 1.60.4.1 2008/02/22 16:50:25 skrll Exp $");
     34       1.3    dyoung #endif
     35       1.1    dyoung 
     36       1.1    dyoung #include "opt_inet.h"
     37       1.1    dyoung 
     38       1.1    dyoung #include <sys/param.h>
     39      1.39    dyoung #include <sys/systm.h>
     40      1.39    dyoung #include <sys/mbuf.h>
     41       1.1    dyoung #include <sys/malloc.h>
     42       1.1    dyoung #include <sys/kernel.h>
     43      1.39    dyoung 
     44       1.1    dyoung #include <sys/socket.h>
     45       1.1    dyoung #include <sys/sockio.h>
     46       1.1    dyoung #include <sys/endian.h>
     47       1.1    dyoung #include <sys/errno.h>
     48       1.1    dyoung #include <sys/proc.h>
     49       1.1    dyoung #include <sys/sysctl.h>
     50       1.1    dyoung 
     51       1.1    dyoung #include <net/if.h>
     52       1.1    dyoung #include <net/if_media.h>
     53       1.1    dyoung #include <net/if_arp.h>
     54       1.4    dyoung #include <net/if_ether.h>
     55       1.1    dyoung #include <net/if_llc.h>
     56       1.1    dyoung 
     57      1.39    dyoung #include <net80211/ieee80211_netbsd.h>
     58       1.1    dyoung #include <net80211/ieee80211_var.h>
     59       1.1    dyoung 
     60       1.1    dyoung #include <net/bpf.h>
     61       1.1    dyoung 
     62       1.1    dyoung #ifdef INET
     63      1.39    dyoung #include <netinet/in.h>
     64       1.4    dyoung #include <net/if_ether.h>
     65       1.4    dyoung #endif
     66       1.1    dyoung 
     67      1.42    dyoung /*
     68      1.42    dyoung  * Association id's are managed with a bit vector.
     69      1.42    dyoung  */
     70      1.42    dyoung #define	IEEE80211_AID_SET(b, w) \
     71      1.42    dyoung 	((w)[IEEE80211_AID(b) / 32] |= (1 << (IEEE80211_AID(b) % 32)))
     72      1.42    dyoung #define	IEEE80211_AID_CLR(b, w) \
     73      1.42    dyoung 	((w)[IEEE80211_AID(b) / 32] &= ~(1 << (IEEE80211_AID(b) % 32)))
     74      1.42    dyoung #define	IEEE80211_AID_ISSET(b, w) \
     75      1.42    dyoung 	((w)[IEEE80211_AID(b) / 32] & (1 << (IEEE80211_AID(b) % 32)))
     76      1.42    dyoung 
     77  1.60.4.1     skrll #ifdef IEEE80211_DEBUG_REFCNT
     78  1.60.4.1     skrll #define REFCNT_LOC "%s (%s:%u) %p<%s> refcnt %d\n", __func__, func, line
     79  1.60.4.1     skrll #else
     80  1.60.4.1     skrll #define REFCNT_LOC "%s %p<%s> refcnt %d\n", __func__
     81  1.60.4.1     skrll #endif
     82  1.60.4.1     skrll 
     83  1.60.4.1     skrll static int ieee80211_sta_join1(struct ieee80211_node *);
     84  1.60.4.1     skrll 
     85      1.39    dyoung static struct ieee80211_node *node_alloc(struct ieee80211_node_table *);
     86      1.39    dyoung static void node_cleanup(struct ieee80211_node *);
     87      1.39    dyoung static void node_free(struct ieee80211_node *);
     88  1.60.4.1     skrll static int8_t node_getrssi(const struct ieee80211_node *);
     89  1.60.4.1     skrll static void node_getsignal(const struct ieee80211_node *, int8_t *, int8_t *);
     90      1.39    dyoung 
     91      1.39    dyoung static void ieee80211_setup_node(struct ieee80211_node_table *,
     92  1.60.4.1     skrll 		struct ieee80211_node *, const uint8_t *);
     93      1.39    dyoung static void _ieee80211_free_node(struct ieee80211_node *);
     94      1.39    dyoung 
     95      1.39    dyoung static void ieee80211_node_table_init(struct ieee80211com *ic,
     96      1.45     skrll 	struct ieee80211_node_table *nt, const char *name,
     97  1.60.4.1     skrll 	int inact, int keymaxix);
     98  1.60.4.1     skrll static void ieee80211_node_table_reset(struct ieee80211_node_table *);
     99      1.39    dyoung static void ieee80211_node_table_cleanup(struct ieee80211_node_table *nt);
    100  1.60.4.1     skrll static void ieee80211_erp_timeout(struct ieee80211com *);
    101       1.1    dyoung 
    102      1.11    dyoung MALLOC_DEFINE(M_80211_NODE, "80211node", "802.11 node state");
    103       1.9    dyoung 
    104       1.1    dyoung void
    105      1.23   mycroft ieee80211_node_attach(struct ieee80211com *ic)
    106       1.1    dyoung {
    107       1.1    dyoung 
    108      1.39    dyoung 	ic->ic_node_alloc = node_alloc;
    109      1.39    dyoung 	ic->ic_node_free = node_free;
    110      1.39    dyoung 	ic->ic_node_cleanup = node_cleanup;
    111      1.39    dyoung 	ic->ic_node_getrssi = node_getrssi;
    112  1.60.4.1     skrll 	ic->ic_node_getsignal = node_getsignal;
    113      1.39    dyoung 
    114      1.39    dyoung 	/* default station inactivity timer setings */
    115      1.39    dyoung 	ic->ic_inact_init = IEEE80211_INACT_INIT;
    116      1.39    dyoung 	ic->ic_inact_auth = IEEE80211_INACT_AUTH;
    117      1.39    dyoung 	ic->ic_inact_run = IEEE80211_INACT_RUN;
    118      1.39    dyoung 	ic->ic_inact_probe = IEEE80211_INACT_PROBE;
    119      1.22   mycroft 
    120  1.60.4.1     skrll 	callout_init(&ic->ic_inact, CALLOUT_MPSAFE);
    121  1.60.4.1     skrll 
    122      1.45     skrll 	/* NB: driver should override */
    123      1.45     skrll 	ic->ic_max_aid = IEEE80211_AID_DEF;
    124  1.60.4.1     skrll 
    125  1.60.4.1     skrll 	ic->ic_flags_ext |= IEEE80211_FEXT_INACT; /* inactivity processing */
    126      1.45     skrll }
    127      1.45     skrll 
    128      1.45     skrll void
    129      1.45     skrll ieee80211_node_lateattach(struct ieee80211com *ic)
    130      1.45     skrll {
    131      1.45     skrll 	struct ieee80211_rsnparms *rsn;
    132      1.45     skrll 
    133      1.45     skrll 	if (ic->ic_max_aid > IEEE80211_AID_MAX)
    134      1.22   mycroft 		ic->ic_max_aid = IEEE80211_AID_MAX;
    135      1.54  christos 	ic->ic_aid_bitmap = malloc(howmany(ic->ic_max_aid, 32) *
    136  1.60.4.1     skrll 	    sizeof(u_int32_t), M_80211_NODE, M_NOWAIT | M_ZERO);
    137      1.22   mycroft 	if (ic->ic_aid_bitmap == NULL) {
    138      1.22   mycroft 		/* XXX no way to recover */
    139      1.22   mycroft 		printf("%s: no memory for AID bitmap!\n", __func__);
    140      1.22   mycroft 		ic->ic_max_aid = 0;
    141      1.22   mycroft 	}
    142       1.1    dyoung 
    143      1.45     skrll 	ieee80211_node_table_init(ic, &ic->ic_sta, "station",
    144  1.60.4.1     skrll 		IEEE80211_INACT_INIT, ic->ic_crypto.cs_max_keyix);
    145       1.1    dyoung 
    146      1.45     skrll 	ieee80211_reset_bss(ic);
    147      1.39    dyoung 	/*
    148      1.39    dyoung 	 * Setup "global settings" in the bss node so that
    149      1.39    dyoung 	 * each new station automatically inherits them.
    150      1.39    dyoung 	 */
    151      1.45     skrll 	rsn = &ic->ic_bss->ni_rsn;
    152      1.39    dyoung 	/* WEP, TKIP, and AES-CCM are always supported */
    153      1.39    dyoung 	rsn->rsn_ucastcipherset |= 1<<IEEE80211_CIPHER_WEP;
    154      1.39    dyoung 	rsn->rsn_ucastcipherset |= 1<<IEEE80211_CIPHER_TKIP;
    155      1.39    dyoung 	rsn->rsn_ucastcipherset |= 1<<IEEE80211_CIPHER_AES_CCM;
    156      1.39    dyoung 	if (ic->ic_caps & IEEE80211_C_AES)
    157      1.39    dyoung 		rsn->rsn_ucastcipherset |= 1<<IEEE80211_CIPHER_AES_OCB;
    158      1.39    dyoung 	if (ic->ic_caps & IEEE80211_C_CKIP)
    159      1.39    dyoung 		rsn->rsn_ucastcipherset |= 1<<IEEE80211_CIPHER_CKIP;
    160      1.39    dyoung 	/*
    161      1.39    dyoung 	 * Default unicast cipher to WEP for 802.1x use.  If
    162      1.39    dyoung 	 * WPA is enabled the management code will set these
    163      1.39    dyoung 	 * values to reflect.
    164      1.39    dyoung 	 */
    165      1.39    dyoung 	rsn->rsn_ucastcipher = IEEE80211_CIPHER_WEP;
    166      1.39    dyoung 	rsn->rsn_ucastkeylen = 104 / NBBY;
    167      1.39    dyoung 	/*
    168      1.39    dyoung 	 * WPA says the multicast cipher is the lowest unicast
    169      1.39    dyoung 	 * cipher supported.  But we skip WEP which would
    170      1.39    dyoung 	 * otherwise be used based on this criteria.
    171      1.39    dyoung 	 */
    172      1.39    dyoung 	rsn->rsn_mcastcipher = IEEE80211_CIPHER_TKIP;
    173      1.39    dyoung 	rsn->rsn_mcastkeylen = 128 / NBBY;
    174      1.39    dyoung 
    175      1.39    dyoung 	/*
    176      1.39    dyoung 	 * We support both WPA-PSK and 802.1x; the one used
    177      1.39    dyoung 	 * is determined by the authentication mode and the
    178      1.39    dyoung 	 * setting of the PSK state.
    179      1.39    dyoung 	 */
    180      1.39    dyoung 	rsn->rsn_keymgmtset = WPA_ASE_8021X_UNSPEC | WPA_ASE_8021X_PSK;
    181      1.39    dyoung 	rsn->rsn_keymgmt = WPA_ASE_8021X_PSK;
    182      1.39    dyoung 
    183      1.45     skrll 	ic->ic_auth = ieee80211_authenticator_get(ic->ic_bss->ni_authmode);
    184       1.1    dyoung }
    185       1.1    dyoung 
    186       1.1    dyoung void
    187      1.23   mycroft ieee80211_node_detach(struct ieee80211com *ic)
    188       1.1    dyoung {
    189       1.1    dyoung 
    190      1.23   mycroft 	if (ic->ic_bss != NULL) {
    191      1.39    dyoung 		ieee80211_free_node(ic->ic_bss);
    192      1.23   mycroft 		ic->ic_bss = NULL;
    193      1.23   mycroft 	}
    194      1.39    dyoung 	ieee80211_node_table_cleanup(&ic->ic_sta);
    195      1.39    dyoung 	if (ic->ic_aid_bitmap != NULL) {
    196  1.60.4.1     skrll 		FREE(ic->ic_aid_bitmap, M_80211_NODE);
    197      1.39    dyoung 		ic->ic_aid_bitmap = NULL;
    198      1.39    dyoung 	}
    199      1.39    dyoung }
    200      1.39    dyoung 
    201      1.39    dyoung /*
    202      1.39    dyoung  * Port authorize/unauthorize interfaces for use by an authenticator.
    203      1.39    dyoung  */
    204      1.39    dyoung 
    205      1.39    dyoung void
    206      1.45     skrll ieee80211_node_authorize(struct ieee80211_node *ni)
    207      1.39    dyoung {
    208      1.45     skrll 	struct ieee80211com *ic = ni->ni_ic;
    209      1.45     skrll 
    210      1.39    dyoung 	ni->ni_flags |= IEEE80211_NODE_AUTH;
    211      1.39    dyoung 	ni->ni_inact_reload = ic->ic_inact_run;
    212  1.60.4.1     skrll 	ni->ni_inact = ni->ni_inact_reload;
    213      1.39    dyoung }
    214      1.39    dyoung 
    215      1.39    dyoung void
    216      1.45     skrll ieee80211_node_unauthorize(struct ieee80211_node *ni)
    217      1.39    dyoung {
    218  1.60.4.1     skrll 	struct ieee80211com *ic = ni->ni_ic;
    219  1.60.4.1     skrll 
    220      1.39    dyoung 	ni->ni_flags &= ~IEEE80211_NODE_AUTH;
    221  1.60.4.1     skrll 	ni->ni_inact_reload = ic->ic_inact_auth;
    222  1.60.4.1     skrll 	if (ni->ni_inact > ni->ni_inact_reload)
    223  1.60.4.1     skrll 		ni->ni_inact = ni->ni_inact_reload;
    224      1.39    dyoung }
    225      1.39    dyoung 
    226      1.39    dyoung /*
    227      1.39    dyoung  * Set/change the channel.  The rate set is also updated as
    228      1.39    dyoung  * to insure a consistent view by drivers.
    229      1.39    dyoung  */
    230      1.52    dyoung static void
    231  1.60.4.1     skrll ieee80211_node_set_chan(struct ieee80211com *ic, struct ieee80211_node *ni)
    232      1.39    dyoung {
    233  1.60.4.1     skrll 	struct ieee80211_channel *chan = ic->ic_bsschan;
    234  1.60.4.1     skrll 
    235  1.60.4.1     skrll #if 0
    236  1.60.4.1     skrll 	IASSERT(chan != IEEE80211_CHAN_ANYC, ("bss channel not setup"));
    237  1.60.4.1     skrll #else
    238      1.52    dyoung 	if (chan == IEEE80211_CHAN_ANYC)	/* XXX while scanning */
    239      1.52    dyoung 		chan = ic->ic_curchan;
    240  1.60.4.1     skrll #endif
    241      1.39    dyoung 	ni->ni_chan = chan;
    242  1.60.4.1     skrll 	if (IEEE80211_IS_CHAN_HT(chan)) {
    243  1.60.4.1     skrll 		/*
    244  1.60.4.1     skrll 		 * XXX Gotta be careful here; the rate set returned by
    245  1.60.4.1     skrll 		 * ieee80211_get_suprates is actually any HT rate
    246  1.60.4.1     skrll 		 * set so blindly copying it will be bad.  We must
    247  1.60.4.1     skrll 		 * install the legacy rate est in ni_rates and the
    248  1.60.4.1     skrll 		 * HT rate set in ni_htrates.
    249  1.60.4.1     skrll 		 */
    250  1.60.4.1     skrll 		ni->ni_htrates = *ieee80211_get_suphtrates(ic, chan);
    251      1.39    dyoung 	}
    252  1.60.4.1     skrll 	ni->ni_rates = *ieee80211_get_suprates(ic, chan);
    253       1.1    dyoung }
    254       1.1    dyoung 
    255       1.1    dyoung /*
    256  1.60.4.1     skrll  * AP scanning support.
    257       1.1    dyoung  */
    258      1.39    dyoung 
    259      1.57     tacha /*
    260      1.57     tacha  * Probe the curent channel, if allowed, while scanning.
    261      1.57     tacha  * If the channel is not marked passive-only then send
    262      1.57     tacha  * a probe request immediately.  Otherwise mark state and
    263      1.57     tacha  * listen for beacons on the channel; if we receive something
    264      1.57     tacha  * then we'll transmit a probe request.
    265      1.57     tacha  */
    266      1.57     tacha void
    267      1.57     tacha ieee80211_probe_curchan(struct ieee80211com *ic, int force)
    268      1.57     tacha {
    269      1.57     tacha 	struct ifnet *ifp = ic->ic_ifp;
    270      1.57     tacha 
    271      1.57     tacha 	if ((ic->ic_curchan->ic_flags & IEEE80211_CHAN_PASSIVE) == 0 || force) {
    272      1.57     tacha 		/*
    273      1.57     tacha 		 * XXX send both broadcast+directed probe request
    274      1.57     tacha 		 */
    275      1.57     tacha 		ieee80211_send_probereq(ic->ic_bss,
    276      1.57     tacha 			ic->ic_myaddr, ifp->if_broadcastaddr,
    277      1.57     tacha 			ifp->if_broadcastaddr,
    278  1.60.4.1     skrll 			ic->ic_des_ssid[0].ssid, ic->ic_des_ssid[0].len,
    279      1.57     tacha 			ic->ic_opt_ie, ic->ic_opt_ie_len);
    280      1.57     tacha 	} else
    281      1.57     tacha 		ic->ic_flags_ext |= IEEE80211_FEXT_PROBECHAN;
    282      1.57     tacha }
    283      1.57     tacha 
    284      1.39    dyoung static __inline void
    285      1.39    dyoung copy_bss(struct ieee80211_node *nbss, const struct ieee80211_node *obss)
    286      1.39    dyoung {
    287      1.39    dyoung 	/* propagate useful state */
    288      1.39    dyoung 	nbss->ni_authmode = obss->ni_authmode;
    289      1.39    dyoung 	nbss->ni_txpower = obss->ni_txpower;
    290      1.39    dyoung 	nbss->ni_vlan = obss->ni_vlan;
    291      1.39    dyoung 	nbss->ni_rsn = obss->ni_rsn;
    292      1.39    dyoung 	/* XXX statistics? */
    293       1.1    dyoung }
    294       1.1    dyoung 
    295       1.1    dyoung void
    296       1.1    dyoung ieee80211_create_ibss(struct ieee80211com* ic, struct ieee80211_channel *chan)
    297       1.1    dyoung {
    298      1.39    dyoung 	struct ieee80211_node_table *nt;
    299       1.1    dyoung 	struct ieee80211_node *ni;
    300       1.1    dyoung 
    301      1.39    dyoung 	IEEE80211_DPRINTF(ic, IEEE80211_MSG_SCAN,
    302      1.39    dyoung 		"%s: creating ibss\n", __func__);
    303      1.39    dyoung 
    304      1.39    dyoung 	/*
    305      1.39    dyoung 	 * Create the station/neighbor table.  Note that for adhoc
    306      1.39    dyoung 	 * mode we make the initial inactivity timer longer since
    307      1.39    dyoung 	 * we create nodes only through discovery and they typically
    308      1.39    dyoung 	 * are long-lived associations.
    309      1.39    dyoung 	 */
    310      1.39    dyoung 	nt = &ic->ic_sta;
    311      1.39    dyoung 	IEEE80211_NODE_LOCK(nt);
    312      1.39    dyoung 	if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
    313      1.39    dyoung 		nt->nt_name = "station";
    314      1.39    dyoung 		nt->nt_inact_init = ic->ic_inact_init;
    315      1.39    dyoung 	} else {
    316      1.39    dyoung 		nt->nt_name = "neighbor";
    317      1.39    dyoung 		nt->nt_inact_init = ic->ic_inact_run;
    318      1.39    dyoung 	}
    319      1.39    dyoung 	IEEE80211_NODE_UNLOCK(nt);
    320      1.39    dyoung 
    321      1.45     skrll 	ni = ieee80211_alloc_node(&ic->ic_sta, ic->ic_myaddr);
    322      1.39    dyoung 	if (ni == NULL) {
    323      1.39    dyoung 		/* XXX recovery? */
    324      1.39    dyoung 		return;
    325      1.16    dyoung 	}
    326      1.44    dyoung 	IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_myaddr);
    327  1.60.4.1     skrll 	ni->ni_esslen = ic->ic_des_ssid[0].len;
    328  1.60.4.1     skrll 	memcpy(ni->ni_essid, ic->ic_des_ssid[0].ssid, ni->ni_esslen);
    329  1.60.4.1     skrll 	if (ic->ic_bss != NULL)
    330  1.60.4.1     skrll 		copy_bss(ni, ic->ic_bss);
    331      1.45     skrll 	ni->ni_intval = ic->ic_bintval;
    332      1.21   mycroft 	if (ic->ic_flags & IEEE80211_F_PRIVACY)
    333       1.1    dyoung 		ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY;
    334       1.1    dyoung 	if (ic->ic_phytype == IEEE80211_T_FH) {
    335       1.1    dyoung 		ni->ni_fhdwell = 200;	/* XXX */
    336       1.1    dyoung 		ni->ni_fhindex = 1;
    337       1.1    dyoung 	}
    338      1.39    dyoung 	if (ic->ic_opmode == IEEE80211_M_IBSS) {
    339      1.39    dyoung 		ic->ic_flags |= IEEE80211_F_SIBSS;
    340      1.39    dyoung 		ni->ni_capinfo |= IEEE80211_CAPINFO_IBSS;	/* XXX */
    341      1.39    dyoung 		if (ic->ic_flags & IEEE80211_F_DESBSSID)
    342      1.39    dyoung 			IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_des_bssid);
    343  1.60.4.1     skrll 		else {
    344  1.60.4.1     skrll 			get_random_bytes(ni->ni_bssid, IEEE80211_ADDR_LEN);
    345  1.60.4.1     skrll 			/* clear group bit, add local bit */
    346  1.60.4.1     skrll 			ni->ni_bssid[0] = (ni->ni_bssid[0] &~ 0x01) | 0x02;
    347  1.60.4.1     skrll 		}
    348  1.60.4.1     skrll 	} else if (ic->ic_opmode == IEEE80211_M_AHDEMO) {
    349  1.60.4.1     skrll 		if (ic->ic_flags & IEEE80211_F_DESBSSID)
    350  1.60.4.1     skrll 			IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_des_bssid);
    351      1.39    dyoung 		else
    352  1.60.4.1     skrll 			memset(ni->ni_bssid, 0, IEEE80211_ADDR_LEN);
    353      1.39    dyoung 	}
    354      1.39    dyoung 	/*
    355      1.39    dyoung 	 * Fix the channel and related attributes.
    356      1.39    dyoung 	 */
    357  1.60.4.1     skrll 	ic->ic_bsschan = chan;
    358  1.60.4.1     skrll 	ieee80211_node_set_chan(ic, ni);
    359  1.60.4.1     skrll 	ic->ic_curmode = ieee80211_chan2mode(chan);
    360      1.39    dyoung 	/*
    361      1.39    dyoung 	 * Do mode-specific rate setup.
    362      1.39    dyoung 	 */
    363  1.60.4.1     skrll 	if (IEEE80211_IS_CHAN_FULL(chan)) {
    364  1.60.4.1     skrll 		if (IEEE80211_IS_CHAN_ANYG(chan)) {
    365  1.60.4.1     skrll 			/*
    366  1.60.4.1     skrll 			 * Use a mixed 11b/11g rate set.
    367  1.60.4.1     skrll 			 */
    368  1.60.4.1     skrll 			ieee80211_set11gbasicrates(&ni->ni_rates,
    369  1.60.4.1     skrll 				IEEE80211_MODE_11G);
    370  1.60.4.1     skrll 		} else if (IEEE80211_IS_CHAN_B(chan)) {
    371  1.60.4.1     skrll 			/*
    372  1.60.4.1     skrll 			 * Force pure 11b rate set.
    373  1.60.4.1     skrll 			 */
    374  1.60.4.1     skrll 			ieee80211_set11gbasicrates(&ni->ni_rates,
    375  1.60.4.1     skrll 				IEEE80211_MODE_11B);
    376  1.60.4.1     skrll 		}
    377      1.39    dyoung 	}
    378      1.39    dyoung 
    379  1.60.4.1     skrll 	(void) ieee80211_sta_join1(ieee80211_ref_node(ni));
    380       1.1    dyoung }
    381       1.1    dyoung 
    382  1.60.4.1     skrll /*
    383  1.60.4.1     skrll  * Reset bss state on transition to the INIT state.
    384  1.60.4.1     skrll  * Clear any stations from the table (they have been
    385  1.60.4.1     skrll  * deauth'd) and reset the bss node (clears key, rate
    386  1.60.4.1     skrll  * etc. state).
    387  1.60.4.1     skrll  */
    388      1.39    dyoung void
    389      1.39    dyoung ieee80211_reset_bss(struct ieee80211com *ic)
    390      1.39    dyoung {
    391      1.39    dyoung 	struct ieee80211_node *ni, *obss;
    392      1.39    dyoung 
    393  1.60.4.1     skrll 	callout_stop(&ic->ic_inact);
    394      1.39    dyoung 	ieee80211_node_table_reset(&ic->ic_sta);
    395  1.60.4.1     skrll 	ieee80211_reset_erp(ic);
    396      1.39    dyoung 
    397  1.60.4.1     skrll 	ni = ieee80211_alloc_node(&ic->ic_sta, ic->ic_myaddr);
    398      1.39    dyoung 	IASSERT(ni != NULL, ("unable to setup inital BSS node"));
    399      1.39    dyoung 	obss = ic->ic_bss;
    400      1.39    dyoung 	ic->ic_bss = ieee80211_ref_node(ni);
    401      1.39    dyoung 	if (obss != NULL) {
    402      1.39    dyoung 		copy_bss(ni, obss);
    403      1.45     skrll 		ni->ni_intval = ic->ic_bintval;
    404      1.39    dyoung 		ieee80211_free_node(obss);
    405      1.39    dyoung 	}
    406      1.39    dyoung }
    407      1.39    dyoung 
    408  1.60.4.1     skrll static int
    409  1.60.4.1     skrll match_ssid(const struct ieee80211_node *ni,
    410  1.60.4.1     skrll 	int nssid, const struct ieee80211_scan_ssid ssids[])
    411  1.60.4.1     skrll {
    412  1.60.4.1     skrll 	int i;
    413  1.60.4.1     skrll 
    414  1.60.4.1     skrll 	for (i = 0; i < nssid; i++) {
    415  1.60.4.1     skrll 		if (ni->ni_esslen == ssids[i].len &&
    416  1.60.4.1     skrll 		     memcmp(ni->ni_essid, ssids[i].ssid, ni->ni_esslen) == 0)
    417  1.60.4.1     skrll 			return 1;
    418  1.60.4.1     skrll 	}
    419  1.60.4.1     skrll 	return 0;
    420  1.60.4.1     skrll }
    421      1.45     skrll 
    422  1.60.4.1     skrll /*
    423  1.60.4.1     skrll  * Test a node for suitability/compatibility.
    424  1.60.4.1     skrll  */
    425      1.39    dyoung static int
    426  1.60.4.1     skrll check_bss(struct ieee80211com *ic, struct ieee80211_node *ni)
    427  1.60.4.1     skrll {
    428  1.60.4.1     skrll         uint8_t rate;
    429  1.60.4.1     skrll 
    430  1.60.4.1     skrll 	if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, ni->ni_chan)))
    431  1.60.4.1     skrll 		return 0;
    432  1.60.4.1     skrll 	if (ic->ic_opmode == IEEE80211_M_IBSS) {
    433  1.60.4.1     skrll 		if ((ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) == 0)
    434  1.60.4.1     skrll 			return 0;
    435  1.60.4.1     skrll 	} else {
    436  1.60.4.1     skrll 		if ((ni->ni_capinfo & IEEE80211_CAPINFO_ESS) == 0)
    437  1.60.4.1     skrll 			return 0;
    438  1.60.4.1     skrll 	}
    439  1.60.4.1     skrll 	if (ic->ic_flags & IEEE80211_F_PRIVACY) {
    440  1.60.4.1     skrll 		if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0)
    441  1.60.4.1     skrll 			return 0;
    442  1.60.4.1     skrll 	} else {
    443  1.60.4.1     skrll 		/* XXX does this mean privacy is supported or required? */
    444  1.60.4.1     skrll 		if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY)
    445  1.60.4.1     skrll 			return 0;
    446  1.60.4.1     skrll 	}
    447  1.60.4.1     skrll 	rate = ieee80211_fix_rate(ni, &ni->ni_rates,
    448  1.60.4.1     skrll 	    IEEE80211_F_JOIN | IEEE80211_F_DONEGO | IEEE80211_F_DOFRATE);
    449  1.60.4.1     skrll 	if (rate & IEEE80211_RATE_BASIC)
    450  1.60.4.1     skrll 		return 0;
    451  1.60.4.1     skrll 	if (ic->ic_des_nssid != 0 &&
    452  1.60.4.1     skrll 	    !match_ssid(ni, ic->ic_des_nssid, ic->ic_des_ssid))
    453  1.60.4.1     skrll 		return 0;
    454  1.60.4.1     skrll 	if ((ic->ic_flags & IEEE80211_F_DESBSSID) &&
    455  1.60.4.1     skrll 	    !IEEE80211_ADDR_EQ(ic->ic_des_bssid, ni->ni_bssid))
    456  1.60.4.1     skrll 		return 0;
    457  1.60.4.1     skrll 	return 1;
    458  1.60.4.1     skrll }
    459  1.60.4.1     skrll 
    460  1.60.4.1     skrll #ifdef IEEE80211_DEBUG
    461  1.60.4.1     skrll /*
    462  1.60.4.1     skrll  * Display node suitability/compatibility.
    463  1.60.4.1     skrll  */
    464  1.60.4.1     skrll static void
    465  1.60.4.1     skrll check_bss_debug(struct ieee80211com *ic, struct ieee80211_node *ni)
    466       1.5    dyoung {
    467  1.60.4.1     skrll         uint8_t rate;
    468       1.5    dyoung         int fail;
    469       1.5    dyoung 
    470       1.5    dyoung 	fail = 0;
    471       1.5    dyoung 	if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, ni->ni_chan)))
    472       1.5    dyoung 		fail |= 0x01;
    473       1.5    dyoung 	if (ic->ic_opmode == IEEE80211_M_IBSS) {
    474       1.5    dyoung 		if ((ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) == 0)
    475       1.5    dyoung 			fail |= 0x02;
    476       1.5    dyoung 	} else {
    477       1.5    dyoung 		if ((ni->ni_capinfo & IEEE80211_CAPINFO_ESS) == 0)
    478       1.5    dyoung 			fail |= 0x02;
    479       1.5    dyoung 	}
    480      1.21   mycroft 	if (ic->ic_flags & IEEE80211_F_PRIVACY) {
    481       1.5    dyoung 		if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0)
    482       1.5    dyoung 			fail |= 0x04;
    483       1.5    dyoung 	} else {
    484      1.11    dyoung 		/* XXX does this mean privacy is supported or required? */
    485       1.5    dyoung 		if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY)
    486       1.5    dyoung 			fail |= 0x04;
    487       1.5    dyoung 	}
    488  1.60.4.1     skrll 	rate = ieee80211_fix_rate(ni, &ni->ni_rates,
    489  1.60.4.1     skrll 	     IEEE80211_F_JOIN | IEEE80211_F_DONEGO | IEEE80211_F_DOFRATE);
    490       1.5    dyoung 	if (rate & IEEE80211_RATE_BASIC)
    491       1.5    dyoung 		fail |= 0x08;
    492  1.60.4.1     skrll 	if (ic->ic_des_nssid != 0 &&
    493  1.60.4.1     skrll 	    !match_ssid(ni, ic->ic_des_nssid, ic->ic_des_ssid))
    494       1.5    dyoung 		fail |= 0x10;
    495       1.5    dyoung 	if ((ic->ic_flags & IEEE80211_F_DESBSSID) &&
    496       1.5    dyoung 	    !IEEE80211_ADDR_EQ(ic->ic_des_bssid, ni->ni_bssid))
    497       1.5    dyoung 		fail |= 0x20;
    498       1.5    dyoung 
    499  1.60.4.1     skrll 	printf(" %c %s", fail ? '-' : '+', ether_sprintf(ni->ni_macaddr));
    500  1.60.4.1     skrll 	printf(" %s%c", ether_sprintf(ni->ni_bssid), fail & 0x20 ? '!' : ' ');
    501  1.60.4.1     skrll 	printf(" %3d%c",
    502  1.60.4.1     skrll 	    ieee80211_chan2ieee(ic, ni->ni_chan), fail & 0x01 ? '!' : ' ');
    503  1.60.4.1     skrll 	printf(" %+4d", ni->ni_rssi);
    504  1.60.4.1     skrll 	printf(" %2dM%c", (rate & IEEE80211_RATE_VAL) / 2,
    505  1.60.4.1     skrll 	    fail & 0x08 ? '!' : ' ');
    506  1.60.4.1     skrll 	printf(" %4s%c",
    507  1.60.4.1     skrll 	    (ni->ni_capinfo & IEEE80211_CAPINFO_ESS) ? "ess" :
    508  1.60.4.1     skrll 	    (ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) ? "ibss" :
    509  1.60.4.1     skrll 	    "????",
    510  1.60.4.1     skrll 	    fail & 0x02 ? '!' : ' ');
    511  1.60.4.1     skrll 	printf(" %3s%c ",
    512  1.60.4.1     skrll 	    (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) ?  "wep" : "no",
    513  1.60.4.1     skrll 	    fail & 0x04 ? '!' : ' ');
    514  1.60.4.1     skrll 	ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
    515  1.60.4.1     skrll 	printf("%s\n", fail & 0x10 ? "!" : "");
    516      1.39    dyoung }
    517  1.60.4.1     skrll #endif /* IEEE80211_DEBUG */
    518      1.39    dyoung 
    519      1.39    dyoung /*
    520      1.39    dyoung  * Handle 802.11 ad hoc network merge.  The
    521      1.39    dyoung  * convention, set by the Wireless Ethernet Compatibility Alliance
    522      1.39    dyoung  * (WECA), is that an 802.11 station will change its BSSID to match
    523      1.39    dyoung  * the "oldest" 802.11 ad hoc network, on the same channel, that
    524      1.39    dyoung  * has the station's desired SSID.  The "oldest" 802.11 network
    525      1.39    dyoung  * sends beacons with the greatest TSF timestamp.
    526      1.39    dyoung  *
    527      1.39    dyoung  * The caller is assumed to validate TSF's before attempting a merge.
    528      1.39    dyoung  *
    529      1.39    dyoung  * Return !0 if the BSSID changed, 0 otherwise.
    530      1.39    dyoung  */
    531      1.39    dyoung int
    532      1.45     skrll ieee80211_ibss_merge(struct ieee80211_node *ni)
    533      1.39    dyoung {
    534      1.45     skrll 	struct ieee80211com *ic = ni->ni_ic;
    535      1.39    dyoung 
    536      1.39    dyoung 	if (ni == ic->ic_bss ||
    537      1.39    dyoung 	    IEEE80211_ADDR_EQ(ni->ni_bssid, ic->ic_bss->ni_bssid)) {
    538      1.39    dyoung 		/* unchanged, nothing to do */
    539      1.39    dyoung 		return 0;
    540      1.39    dyoung 	}
    541  1.60.4.1     skrll 	if (!check_bss(ic, ni)) {
    542  1.60.4.1     skrll 		/* capabilities mismatch */
    543      1.39    dyoung 		IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
    544      1.39    dyoung 		    "%s: merge failed, capabilities mismatch\n", __func__);
    545  1.60.4.1     skrll #ifdef IEEE80211_DEBUG
    546  1.60.4.1     skrll 		if (ieee80211_msg_assoc(ic))
    547  1.60.4.1     skrll 			check_bss_debug(ic, ni);
    548  1.60.4.1     skrll #endif
    549      1.39    dyoung 		ic->ic_stats.is_ibss_capmismatch++;
    550      1.39    dyoung 		return 0;
    551      1.39    dyoung 	}
    552  1.60.4.1     skrll 	if (!ieee80211_sta_join1(ieee80211_ref_node(ni)))
    553      1.48    dyoung 		return 0;
    554      1.39    dyoung 	IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
    555      1.39    dyoung 		"%s: new bssid %s: %s preamble, %s slot time%s\n", __func__,
    556      1.39    dyoung 		ether_sprintf(ni->ni_bssid),
    557      1.39    dyoung 		ic->ic_flags&IEEE80211_F_SHPREAMBLE ? "short" : "long",
    558      1.39    dyoung 		ic->ic_flags&IEEE80211_F_SHSLOT ? "short" : "long",
    559      1.39    dyoung 		ic->ic_flags&IEEE80211_F_USEPROT ? ", protection" : ""
    560      1.39    dyoung 	);
    561      1.48    dyoung 	ic->ic_flags &= ~IEEE80211_F_SIBSS;
    562      1.48    dyoung 	return 1;
    563      1.39    dyoung }
    564      1.39    dyoung 
    565      1.39    dyoung /*
    566  1.60.4.1     skrll  * Change the bss channel.
    567  1.60.4.1     skrll  */
    568  1.60.4.1     skrll void
    569  1.60.4.1     skrll ieee80211_setbsschan(struct ieee80211com *ic, struct ieee80211_channel *c)
    570  1.60.4.1     skrll {
    571  1.60.4.1     skrll 	ic->ic_bsschan = c;
    572  1.60.4.1     skrll 	ic->ic_curchan = ic->ic_bsschan;
    573  1.60.4.1     skrll 	ic->ic_curmode = ieee80211_chan2mode(ic->ic_curchan);
    574  1.60.4.1     skrll 	ic->ic_set_channel(ic);
    575  1.60.4.1     skrll }
    576  1.60.4.1     skrll 
    577  1.60.4.1     skrll /*
    578      1.39    dyoung  * Join the specified IBSS/BSS network.  The node is assumed to
    579      1.39    dyoung  * be passed in with a held reference.
    580      1.39    dyoung  */
    581  1.60.4.1     skrll static int
    582  1.60.4.1     skrll ieee80211_sta_join1(struct ieee80211_node *selbs)
    583      1.39    dyoung {
    584  1.60.4.1     skrll 	struct ieee80211com *ic = selbs->ni_ic;
    585      1.39    dyoung 	struct ieee80211_node *obss;
    586  1.60.4.1     skrll 	int canreassoc;
    587      1.39    dyoung 
    588       1.1    dyoung 	if (ic->ic_opmode == IEEE80211_M_IBSS) {
    589      1.39    dyoung 		struct ieee80211_node_table *nt;
    590      1.39    dyoung 		/*
    591      1.39    dyoung 		 * Fillin the neighbor table; it will already
    592      1.39    dyoung 		 * exist if we are simply switching mastership.
    593      1.39    dyoung 		 * XXX ic_sta always setup so this is unnecessary?
    594      1.39    dyoung 		 */
    595      1.39    dyoung 		nt = &ic->ic_sta;
    596      1.39    dyoung 		IEEE80211_NODE_LOCK(nt);
    597      1.39    dyoung 		nt->nt_name = "neighbor";
    598      1.39    dyoung 		nt->nt_inact_init = ic->ic_inact_run;
    599      1.39    dyoung 		IEEE80211_NODE_UNLOCK(nt);
    600      1.39    dyoung 	}
    601      1.39    dyoung 
    602      1.39    dyoung 	/*
    603      1.39    dyoung 	 * Committed to selbs, setup state.
    604      1.39    dyoung 	 */
    605      1.39    dyoung 	obss = ic->ic_bss;
    606  1.60.4.1     skrll 	/*
    607  1.60.4.1     skrll 	 * Check if old+new node have the same address in which
    608  1.60.4.1     skrll 	 * case we can reassociate when operating in sta mode.
    609  1.60.4.1     skrll 	 */
    610  1.60.4.1     skrll 	canreassoc = (obss != NULL &&
    611  1.60.4.1     skrll 		ic->ic_state == IEEE80211_S_RUN &&
    612  1.60.4.1     skrll 		IEEE80211_ADDR_EQ(obss->ni_macaddr, selbs->ni_macaddr));
    613      1.39    dyoung 	ic->ic_bss = selbs;		/* NB: caller assumed to bump refcnt */
    614      1.52    dyoung 	if (obss != NULL) {
    615      1.52    dyoung 		copy_bss(selbs, obss);
    616      1.39    dyoung 		ieee80211_free_node(obss);
    617      1.52    dyoung 	}
    618  1.60.4.1     skrll 
    619  1.60.4.1     skrll 	/*
    620  1.60.4.1     skrll 	 * Delete unusable rates; we've already checked
    621  1.60.4.1     skrll 	 * that the negotiated rate set is acceptable.
    622  1.60.4.1     skrll 	 */
    623  1.60.4.1     skrll 	ieee80211_fix_rate(ic->ic_bss, &ic->ic_bss->ni_rates,
    624  1.60.4.1     skrll 		IEEE80211_F_DODEL | IEEE80211_F_JOIN);
    625  1.60.4.1     skrll 
    626  1.60.4.1     skrll 	ieee80211_setbsschan(ic, selbs->ni_chan);
    627      1.39    dyoung 	/*
    628      1.39    dyoung 	 * Set the erp state (mostly the slot time) to deal with
    629      1.39    dyoung 	 * the auto-select case; this should be redundant if the
    630      1.39    dyoung 	 * mode is locked.
    631      1.39    dyoung 	 */
    632      1.39    dyoung 	ieee80211_reset_erp(ic);
    633      1.39    dyoung 	ieee80211_wme_initparams(ic);
    634      1.39    dyoung 
    635  1.60.4.1     skrll 	if (ic->ic_opmode == IEEE80211_M_STA) {
    636  1.60.4.1     skrll 		if (canreassoc) {
    637  1.60.4.1     skrll 			/* Reassociate */
    638  1.60.4.1     skrll 			ieee80211_new_state(ic, IEEE80211_S_ASSOC, 1);
    639  1.60.4.1     skrll 		} else {
    640  1.60.4.1     skrll 			/*
    641  1.60.4.1     skrll 			 * Act as if we received a DEAUTH frame in case we
    642  1.60.4.1     skrll 			 * are invoked from the RUN state.  This will cause
    643  1.60.4.1     skrll 			 * us to try to re-authenticate if we are operating
    644  1.60.4.1     skrll 			 * as a station.
    645  1.60.4.1     skrll 			 */
    646  1.60.4.1     skrll 			ieee80211_new_state(ic, IEEE80211_S_AUTH,
    647  1.60.4.1     skrll 				IEEE80211_FC0_SUBTYPE_DEAUTH);
    648  1.60.4.1     skrll 		}
    649  1.60.4.1     skrll 	} else
    650       1.1    dyoung 		ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
    651      1.39    dyoung 	return 1;
    652      1.39    dyoung }
    653      1.39    dyoung 
    654  1.60.4.1     skrll int
    655  1.60.4.1     skrll ieee80211_sta_join(struct ieee80211com *ic,
    656  1.60.4.1     skrll 	const struct ieee80211_scan_entry *se)
    657  1.60.4.1     skrll {
    658  1.60.4.1     skrll 	struct ieee80211_node *ni;
    659  1.60.4.1     skrll 
    660  1.60.4.1     skrll 	ni = ieee80211_alloc_node(&ic->ic_sta, se->se_macaddr);
    661  1.60.4.1     skrll 	if (ni == NULL) {
    662  1.60.4.1     skrll 		/* XXX msg */
    663  1.60.4.1     skrll 		return 0;
    664  1.60.4.1     skrll 	}
    665  1.60.4.1     skrll 	/*
    666  1.60.4.1     skrll 	 * Expand scan state into node's format.
    667  1.60.4.1     skrll 	 * XXX may not need all this stuff
    668  1.60.4.1     skrll 	 */
    669  1.60.4.1     skrll 	IEEE80211_ADDR_COPY(ni->ni_bssid, se->se_bssid);
    670  1.60.4.1     skrll 	ni->ni_esslen = se->se_ssid[1];
    671  1.60.4.1     skrll 	memcpy(ni->ni_essid, se->se_ssid+2, ni->ni_esslen);
    672  1.60.4.1     skrll 	ni->ni_rstamp = se->se_rstamp;
    673  1.60.4.1     skrll 	ni->ni_tstamp.tsf = se->se_tstamp.tsf;
    674  1.60.4.1     skrll 	ni->ni_intval = se->se_intval;
    675  1.60.4.1     skrll 	ni->ni_capinfo = se->se_capinfo;
    676  1.60.4.1     skrll 	ni->ni_chan = se->se_chan;
    677  1.60.4.1     skrll 	ni->ni_timoff = se->se_timoff;
    678  1.60.4.1     skrll 	ni->ni_fhdwell = se->se_fhdwell;
    679  1.60.4.1     skrll 	ni->ni_fhindex = se->se_fhindex;
    680  1.60.4.1     skrll 	ni->ni_erp = se->se_erp;
    681  1.60.4.1     skrll 	ni->ni_rssi = se->se_rssi;
    682  1.60.4.1     skrll 	ni->ni_noise = se->se_noise;
    683  1.60.4.1     skrll 	if (se->se_htcap_ie != NULL) {
    684  1.60.4.1     skrll 		ieee80211_saveie(&ni->ni_htcap_ie, se->se_htcap_ie);
    685  1.60.4.1     skrll 		ieee80211_parse_htcap(ni, ni->ni_htcap_ie);
    686  1.60.4.1     skrll 	}
    687  1.60.4.1     skrll 	if (se->se_wpa_ie != NULL)
    688  1.60.4.1     skrll 		ieee80211_saveie(&ni->ni_wpa_ie, se->se_wpa_ie);
    689  1.60.4.1     skrll 	if (se->se_rsn_ie != NULL)
    690  1.60.4.1     skrll 		ieee80211_saveie(&ni->ni_rsn_ie, se->se_rsn_ie);
    691  1.60.4.1     skrll 	if (se->se_wme_ie != NULL)
    692  1.60.4.1     skrll 		ieee80211_saveie(&ni->ni_wme_ie, se->se_wme_ie);
    693  1.60.4.1     skrll 	if (se->se_ath_ie != NULL)
    694  1.60.4.1     skrll 		ieee80211_saveath(ni, se->se_ath_ie);
    695  1.60.4.1     skrll 
    696  1.60.4.1     skrll 	ic->ic_dtim_period = se->se_dtimperiod;
    697  1.60.4.1     skrll 	ic->ic_dtim_count = 0;
    698  1.60.4.1     skrll 
    699  1.60.4.1     skrll 	/* NB: must be after ni_chan is setup */
    700  1.60.4.1     skrll 	ieee80211_setup_rates(ni, se->se_rates, se->se_xrates,
    701  1.60.4.1     skrll 		IEEE80211_F_DOSORT);
    702  1.60.4.1     skrll 
    703  1.60.4.1     skrll 	return ieee80211_sta_join1(ieee80211_ref_node(ni));
    704  1.60.4.1     skrll }
    705  1.60.4.1     skrll 
    706      1.39    dyoung /*
    707      1.39    dyoung  * Leave the specified IBSS/BSS network.  The node is assumed to
    708      1.39    dyoung  * be passed in with a held reference.
    709      1.39    dyoung  */
    710      1.39    dyoung void
    711      1.39    dyoung ieee80211_sta_leave(struct ieee80211com *ic, struct ieee80211_node *ni)
    712      1.39    dyoung {
    713      1.39    dyoung 	ic->ic_node_cleanup(ni);
    714      1.39    dyoung 	ieee80211_notify_node_leave(ic, ni);
    715       1.1    dyoung }
    716       1.1    dyoung 
    717       1.5    dyoung int
    718      1.55    dyoung ieee80211_get_rate(const struct ieee80211_node * const ni)
    719       1.5    dyoung {
    720      1.49    dyoung #define	RATE(_ix)	(ni->ni_rates.rs_rates[(_ix)] & IEEE80211_RATE_VAL)
    721      1.49    dyoung 	int ix, rate;
    722      1.55    dyoung 	struct ieee80211com *ic = ni->ni_ic;
    723      1.49    dyoung 	const struct ieee80211_rateset *rs;
    724       1.5    dyoung 
    725      1.55    dyoung 	IASSERT(ni != NULL, ("ni != NULL"));
    726      1.55    dyoung 	IASSERT(ieee80211_node_refcnt(ni) > 0,
    727      1.55    dyoung 	    ("refcnt(ni) == %d", ieee80211_node_refcnt(ni)));
    728      1.55    dyoung 	IASSERT(ic != NULL, ("ic != NULL"));
    729      1.49    dyoung 	if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) {
    730      1.49    dyoung 		rs = &ic->ic_sup_rates[ic->ic_curmode];
    731      1.49    dyoung 		rate = rs->rs_rates[ic->ic_fixed_rate] & IEEE80211_RATE_VAL;
    732      1.49    dyoung 		for (ix = ni->ni_rates.rs_nrates - 1;
    733      1.49    dyoung 		     ix >= 0 && RATE(ix) != rate; ix--)
    734      1.49    dyoung 			;
    735      1.55    dyoung 		if (ix < 0) {
    736      1.55    dyoung 			IEEE80211_DPRINTF(ic, IEEE80211_MSG_DEBUG,
    737      1.55    dyoung 			    "%s: fixed rate %d (%d.%d Mb/s) not in rate set",
    738      1.55    dyoung 			    __func__, ic->ic_fixed_rate, (rate * 5) / 10,
    739      1.55    dyoung 			    (rate * 5) % 10);
    740      1.55    dyoung 			goto no_rate;
    741      1.55    dyoung 		}
    742      1.49    dyoung 	} else if (ic->ic_state == IEEE80211_S_RUN)
    743      1.49    dyoung 		rate = ni->ni_rates.rs_rates[ni->ni_txrate];
    744      1.55    dyoung 	else {
    745      1.55    dyoung no_rate:
    746      1.55    dyoung 		rs = &ni->ni_rates;
    747      1.55    dyoung 		/* Choose node's lowest basic rate, or else its lowest rate. */
    748      1.55    dyoung 		for (ix = 0; ix < rs->rs_nrates; ix++) {
    749      1.55    dyoung 			if (rs->rs_rates[ix] & IEEE80211_RATE_BASIC)
    750      1.55    dyoung 				return rs->rs_rates[ix] & IEEE80211_RATE_VAL;
    751      1.55    dyoung 		}
    752      1.55    dyoung 		return ni->ni_rates.rs_rates[0] & IEEE80211_RATE_VAL;
    753      1.55    dyoung 	}
    754       1.5    dyoung 	return rate & IEEE80211_RATE_VAL;
    755       1.5    dyoung }
    756       1.5    dyoung 
    757       1.1    dyoung static struct ieee80211_node *
    758      1.59  christos node_alloc(struct ieee80211_node_table *nt)
    759       1.1    dyoung {
    760      1.11    dyoung 	struct ieee80211_node *ni;
    761      1.39    dyoung 
    762  1.60.4.1     skrll 	ni = malloc(sizeof(struct ieee80211_node), M_80211_NODE,
    763  1.60.4.1     skrll 	    M_NOWAIT | M_ZERO);
    764      1.11    dyoung 	return ni;
    765       1.1    dyoung }
    766       1.1    dyoung 
    767      1.39    dyoung /*
    768      1.39    dyoung  * Reclaim any resources in a node and reset any critical
    769      1.39    dyoung  * state.  Typically nodes are free'd immediately after,
    770      1.39    dyoung  * but in some cases the storage may be reused so we need
    771      1.39    dyoung  * to insure consistent state (should probably fix that).
    772      1.39    dyoung  */
    773       1.1    dyoung static void
    774      1.39    dyoung node_cleanup(struct ieee80211_node *ni)
    775      1.22   mycroft {
    776      1.39    dyoung #define	N(a)	(sizeof(a)/sizeof(a[0]))
    777      1.39    dyoung 	struct ieee80211com *ic = ni->ni_ic;
    778  1.60.4.1     skrll 	int i;
    779      1.39    dyoung 
    780      1.39    dyoung 	/* NB: preserve ni_table */
    781      1.39    dyoung 	if (ni->ni_flags & IEEE80211_NODE_PWR_MGT) {
    782  1.60.4.1     skrll 		if (ic->ic_opmode != IEEE80211_M_STA)
    783  1.60.4.1     skrll 			ic->ic_ps_sta--;
    784      1.39    dyoung 		ni->ni_flags &= ~IEEE80211_NODE_PWR_MGT;
    785      1.39    dyoung 		IEEE80211_DPRINTF(ic, IEEE80211_MSG_POWER,
    786      1.39    dyoung 		    "[%s] power save mode off, %u sta's in ps mode\n",
    787      1.39    dyoung 		    ether_sprintf(ni->ni_macaddr), ic->ic_ps_sta);
    788      1.39    dyoung 	}
    789      1.42    dyoung 	/*
    790  1.60.4.1     skrll 	 * Cleanup any HT-related state.
    791  1.60.4.1     skrll 	 */
    792  1.60.4.1     skrll 	if (ni->ni_flags & IEEE80211_NODE_HT)
    793  1.60.4.1     skrll 		ieee80211_ht_node_cleanup(ni);
    794  1.60.4.1     skrll 	/*
    795      1.42    dyoung 	 * Clear AREF flag that marks the authorization refcnt bump
    796      1.42    dyoung 	 * has happened.  This is probably not needed as the node
    797      1.42    dyoung 	 * should always be removed from the table so not found but
    798      1.42    dyoung 	 * do it just in case.
    799      1.42    dyoung 	 */
    800      1.42    dyoung 	ni->ni_flags &= ~IEEE80211_NODE_AREF;
    801      1.39    dyoung 
    802      1.39    dyoung 	/*
    803      1.39    dyoung 	 * Drain power save queue and, if needed, clear TIM.
    804      1.39    dyoung 	 */
    805  1.60.4.1     skrll 	if (ieee80211_node_saveq_drain(ni) != 0 && ic->ic_set_tim != NULL)
    806      1.45     skrll 		ic->ic_set_tim(ni, 0);
    807      1.39    dyoung 
    808      1.39    dyoung 	ni->ni_associd = 0;
    809      1.39    dyoung 	if (ni->ni_challenge != NULL) {
    810  1.60.4.1     skrll 		FREE(ni->ni_challenge, M_80211_NODE);
    811      1.39    dyoung 		ni->ni_challenge = NULL;
    812      1.39    dyoung 	}
    813      1.39    dyoung 	/*
    814      1.39    dyoung 	 * Preserve SSID, WPA, and WME ie's so the bss node is
    815      1.39    dyoung 	 * reusable during a re-auth/re-assoc state transition.
    816      1.39    dyoung 	 * If we remove these data they will not be recreated
    817      1.39    dyoung 	 * because they come from a probe-response or beacon frame
    818      1.39    dyoung 	 * which cannot be expected prior to the association-response.
    819      1.39    dyoung 	 * This should not be an issue when operating in other modes
    820      1.39    dyoung 	 * as stations leaving always go through a full state transition
    821      1.39    dyoung 	 * which will rebuild this state.
    822      1.39    dyoung 	 *
    823      1.39    dyoung 	 * XXX does this leave us open to inheriting old state?
    824      1.39    dyoung 	 */
    825      1.39    dyoung 	for (i = 0; i < N(ni->ni_rxfrag); i++)
    826      1.39    dyoung 		if (ni->ni_rxfrag[i] != NULL) {
    827      1.39    dyoung 			m_freem(ni->ni_rxfrag[i]);
    828      1.39    dyoung 			ni->ni_rxfrag[i] = NULL;
    829      1.39    dyoung 		}
    830      1.45     skrll 	/*
    831      1.45     skrll 	 * Must be careful here to remove any key map entry w/o a LOR.
    832      1.45     skrll 	 */
    833      1.45     skrll 	ieee80211_node_delucastkey(ni);
    834      1.39    dyoung #undef N
    835      1.22   mycroft }
    836      1.22   mycroft 
    837      1.22   mycroft static void
    838      1.39    dyoung node_free(struct ieee80211_node *ni)
    839       1.1    dyoung {
    840      1.39    dyoung 	struct ieee80211com *ic = ni->ni_ic;
    841      1.39    dyoung 
    842      1.39    dyoung 	ic->ic_node_cleanup(ni);
    843      1.39    dyoung 	if (ni->ni_wpa_ie != NULL)
    844  1.60.4.1     skrll 		FREE(ni->ni_wpa_ie, M_80211_NODE);
    845  1.60.4.1     skrll 	if (ni->ni_rsn_ie != NULL)
    846  1.60.4.1     skrll 		FREE(ni->ni_rsn_ie, M_80211_NODE);
    847      1.39    dyoung 	if (ni->ni_wme_ie != NULL)
    848  1.60.4.1     skrll 		FREE(ni->ni_wme_ie, M_80211_NODE);
    849  1.60.4.1     skrll 	if (ni->ni_ath_ie != NULL)
    850  1.60.4.1     skrll 		FREE(ni->ni_ath_ie, M_80211_NODE);
    851      1.39    dyoung 	IEEE80211_NODE_SAVEQ_DESTROY(ni);
    852      1.11    dyoung 	FREE(ni, M_80211_NODE);
    853       1.1    dyoung }
    854       1.1    dyoung 
    855  1.60.4.1     skrll static int8_t
    856      1.39    dyoung node_getrssi(const struct ieee80211_node *ni)
    857       1.9    dyoung {
    858       1.9    dyoung 	return ni->ni_rssi;
    859       1.9    dyoung }
    860       1.9    dyoung 
    861       1.1    dyoung static void
    862  1.60.4.1     skrll node_getsignal(const struct ieee80211_node *ni, int8_t *rssi, int8_t *noise)
    863  1.60.4.1     skrll {
    864  1.60.4.1     skrll 	*rssi = ni->ni_rssi;
    865  1.60.4.1     skrll 	*noise = ni->ni_noise;
    866  1.60.4.1     skrll }
    867  1.60.4.1     skrll 
    868  1.60.4.1     skrll static void
    869      1.39    dyoung ieee80211_setup_node(struct ieee80211_node_table *nt,
    870  1.60.4.1     skrll 	struct ieee80211_node *ni, const uint8_t *macaddr)
    871       1.1    dyoung {
    872      1.39    dyoung 	struct ieee80211com *ic = nt->nt_ic;
    873       1.1    dyoung 	int hash;
    874       1.1    dyoung 
    875      1.23   mycroft 	IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
    876      1.39    dyoung 		"%s %p<%s> in %s table\n", __func__, ni,
    877      1.39    dyoung 		ether_sprintf(macaddr), nt->nt_name);
    878      1.39    dyoung 
    879       1.1    dyoung 	IEEE80211_ADDR_COPY(ni->ni_macaddr, macaddr);
    880       1.1    dyoung 	hash = IEEE80211_NODE_HASH(macaddr);
    881      1.39    dyoung 	ieee80211_node_initref(ni);		/* mark referenced */
    882      1.39    dyoung 	ni->ni_chan = IEEE80211_CHAN_ANYC;
    883      1.39    dyoung 	ni->ni_authmode = IEEE80211_AUTH_OPEN;
    884      1.39    dyoung 	ni->ni_txpower = ic->ic_txpowlimit;	/* max power */
    885      1.39    dyoung 	ieee80211_crypto_resetkey(ic, &ni->ni_ucastkey, IEEE80211_KEYIX_NONE);
    886      1.39    dyoung 	ni->ni_inact_reload = nt->nt_inact_init;
    887      1.39    dyoung 	ni->ni_inact = ni->ni_inact_reload;
    888  1.60.4.1     skrll 	ni->ni_ath_defkeyix = 0x7fff;
    889      1.39    dyoung 	IEEE80211_NODE_SAVEQ_INIT(ni, "unknown");
    890      1.39    dyoung 
    891      1.39    dyoung 	IEEE80211_NODE_LOCK(nt);
    892      1.39    dyoung 	TAILQ_INSERT_TAIL(&nt->nt_node, ni, ni_list);
    893      1.39    dyoung 	LIST_INSERT_HEAD(&nt->nt_hash[hash], ni, ni_hash);
    894      1.39    dyoung 	ni->ni_table = nt;
    895      1.39    dyoung 	ni->ni_ic = ic;
    896      1.39    dyoung 	IEEE80211_NODE_UNLOCK(nt);
    897       1.1    dyoung }
    898       1.1    dyoung 
    899       1.1    dyoung struct ieee80211_node *
    900  1.60.4.1     skrll ieee80211_alloc_node(struct ieee80211_node_table *nt, const uint8_t *macaddr)
    901       1.1    dyoung {
    902      1.39    dyoung 	struct ieee80211com *ic = nt->nt_ic;
    903      1.39    dyoung 	struct ieee80211_node *ni;
    904      1.39    dyoung 
    905      1.39    dyoung 	ni = ic->ic_node_alloc(nt);
    906      1.39    dyoung 	if (ni != NULL)
    907      1.39    dyoung 		ieee80211_setup_node(nt, ni, macaddr);
    908      1.39    dyoung 	else
    909      1.11    dyoung 		ic->ic_stats.is_rx_nodealloc++;
    910       1.1    dyoung 	return ni;
    911       1.1    dyoung }
    912       1.1    dyoung 
    913      1.45     skrll /*
    914      1.45     skrll  * Craft a temporary node suitable for sending a management frame
    915      1.45     skrll  * to the specified station.  We craft only as much state as we
    916      1.45     skrll  * need to do the work since the node will be immediately reclaimed
    917      1.45     skrll  * once the send completes.
    918      1.45     skrll  */
    919      1.45     skrll struct ieee80211_node *
    920  1.60.4.1     skrll ieee80211_tmp_node(struct ieee80211com *ic, const uint8_t *macaddr)
    921      1.45     skrll {
    922      1.45     skrll 	struct ieee80211_node *ni;
    923      1.45     skrll 
    924      1.45     skrll 	ni = ic->ic_node_alloc(&ic->ic_sta);
    925      1.45     skrll 	if (ni != NULL) {
    926      1.45     skrll 		IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
    927      1.45     skrll 			"%s %p<%s>\n", __func__, ni, ether_sprintf(macaddr));
    928      1.45     skrll 
    929      1.45     skrll 		IEEE80211_ADDR_COPY(ni->ni_macaddr, macaddr);
    930      1.45     skrll 		IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss->ni_bssid);
    931      1.45     skrll 		ieee80211_node_initref(ni);		/* mark referenced */
    932      1.45     skrll 		ni->ni_txpower = ic->ic_bss->ni_txpower;
    933      1.45     skrll 		/* NB: required by ieee80211_fix_rate */
    934  1.60.4.1     skrll 		ieee80211_node_set_chan(ic, ni);
    935      1.45     skrll 		ieee80211_crypto_resetkey(ic, &ni->ni_ucastkey,
    936      1.45     skrll 			IEEE80211_KEYIX_NONE);
    937      1.45     skrll 		/* XXX optimize away */
    938      1.45     skrll 		IEEE80211_NODE_SAVEQ_INIT(ni, "unknown");
    939      1.45     skrll 
    940      1.45     skrll 		ni->ni_table = NULL;		/* NB: pedantic */
    941      1.45     skrll 		ni->ni_ic = ic;
    942      1.45     skrll 	} else {
    943      1.45     skrll 		/* XXX msg */
    944      1.45     skrll 		ic->ic_stats.is_rx_nodealloc++;
    945      1.45     skrll 	}
    946      1.45     skrll 	return ni;
    947      1.45     skrll }
    948      1.45     skrll 
    949       1.1    dyoung struct ieee80211_node *
    950  1.60.4.1     skrll ieee80211_dup_bss(struct ieee80211_node_table *nt, const uint8_t *macaddr)
    951       1.1    dyoung {
    952      1.39    dyoung 	struct ieee80211com *ic = nt->nt_ic;
    953      1.39    dyoung 	struct ieee80211_node *ni;
    954      1.39    dyoung 
    955      1.39    dyoung 	ni = ic->ic_node_alloc(nt);
    956       1.1    dyoung 	if (ni != NULL) {
    957      1.39    dyoung 		ieee80211_setup_node(nt, ni, macaddr);
    958      1.11    dyoung 		/*
    959      1.11    dyoung 		 * Inherit from ic_bss.
    960      1.11    dyoung 		 */
    961      1.39    dyoung 		ni->ni_authmode = ic->ic_bss->ni_authmode;
    962      1.39    dyoung 		ni->ni_txpower = ic->ic_bss->ni_txpower;
    963      1.39    dyoung 		ni->ni_vlan = ic->ic_bss->ni_vlan;	/* XXX?? */
    964      1.11    dyoung 		IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss->ni_bssid);
    965  1.60.4.1     skrll 		ieee80211_node_set_chan(ic, ni);
    966      1.39    dyoung 		ni->ni_rsn = ic->ic_bss->ni_rsn;
    967      1.11    dyoung 	} else
    968      1.11    dyoung 		ic->ic_stats.is_rx_nodealloc++;
    969       1.1    dyoung 	return ni;
    970       1.1    dyoung }
    971       1.1    dyoung 
    972      1.11    dyoung static struct ieee80211_node *
    973      1.39    dyoung #ifdef IEEE80211_DEBUG_REFCNT
    974      1.39    dyoung _ieee80211_find_node_debug(struct ieee80211_node_table *nt,
    975  1.60.4.1     skrll 	const uint8_t *macaddr, const char *func, int line)
    976      1.39    dyoung #else
    977      1.39    dyoung _ieee80211_find_node(struct ieee80211_node_table *nt,
    978  1.60.4.1     skrll 	const uint8_t *macaddr)
    979      1.39    dyoung #endif
    980       1.1    dyoung {
    981       1.1    dyoung 	struct ieee80211_node *ni;
    982       1.1    dyoung 	int hash;
    983      1.11    dyoung 
    984      1.39    dyoung 	IEEE80211_NODE_LOCK_ASSERT(nt);
    985       1.1    dyoung 
    986       1.1    dyoung 	hash = IEEE80211_NODE_HASH(macaddr);
    987      1.39    dyoung 	LIST_FOREACH(ni, &nt->nt_hash[hash], ni_hash) {
    988       1.1    dyoung 		if (IEEE80211_ADDR_EQ(ni->ni_macaddr, macaddr)) {
    989      1.39    dyoung 			ieee80211_ref_node(ni);	/* mark referenced */
    990      1.39    dyoung #ifdef IEEE80211_DEBUG_REFCNT
    991      1.39    dyoung 			IEEE80211_DPRINTF(nt->nt_ic, IEEE80211_MSG_NODE,
    992      1.39    dyoung 			    "%s (%s:%u) %p<%s> refcnt %d\n", __func__,
    993      1.39    dyoung 			    func, line,
    994      1.39    dyoung 			    ni, ether_sprintf(ni->ni_macaddr),
    995      1.39    dyoung 			    ieee80211_node_refcnt(ni));
    996      1.39    dyoung #endif
    997      1.11    dyoung 			return ni;
    998       1.1    dyoung 		}
    999       1.1    dyoung 	}
   1000      1.11    dyoung 	return NULL;
   1001      1.11    dyoung }
   1002      1.39    dyoung #ifdef IEEE80211_DEBUG_REFCNT
   1003      1.39    dyoung #define	_ieee80211_find_node(nt, mac) \
   1004      1.39    dyoung 	_ieee80211_find_node_debug(nt, mac, func, line)
   1005      1.39    dyoung #endif
   1006      1.11    dyoung 
   1007      1.11    dyoung struct ieee80211_node *
   1008      1.39    dyoung #ifdef IEEE80211_DEBUG_REFCNT
   1009      1.39    dyoung ieee80211_find_node_debug(struct ieee80211_node_table *nt,
   1010  1.60.4.1     skrll 	const uint8_t *macaddr, const char *func, int line)
   1011      1.39    dyoung #else
   1012  1.60.4.1     skrll ieee80211_find_node(struct ieee80211_node_table *nt, const uint8_t *macaddr)
   1013      1.39    dyoung #endif
   1014      1.11    dyoung {
   1015      1.11    dyoung 	struct ieee80211_node *ni;
   1016      1.11    dyoung 
   1017      1.39    dyoung 	IEEE80211_NODE_LOCK(nt);
   1018      1.39    dyoung 	ni = _ieee80211_find_node(nt, macaddr);
   1019      1.39    dyoung 	IEEE80211_NODE_UNLOCK(nt);
   1020       1.7    dyoung 	return ni;
   1021       1.7    dyoung }
   1022       1.7    dyoung 
   1023      1.11    dyoung /*
   1024      1.39    dyoung  * Fake up a node; this handles node discovery in adhoc mode.
   1025      1.39    dyoung  * Note that for the driver's benefit we we treat this like
   1026      1.39    dyoung  * an association so the driver has an opportunity to setup
   1027      1.39    dyoung  * it's private state.
   1028      1.11    dyoung  */
   1029       1.7    dyoung struct ieee80211_node *
   1030      1.39    dyoung ieee80211_fakeup_adhoc_node(struct ieee80211_node_table *nt,
   1031  1.60.4.1     skrll 	const uint8_t macaddr[IEEE80211_ADDR_LEN])
   1032       1.7    dyoung {
   1033      1.39    dyoung 	struct ieee80211com *ic = nt->nt_ic;
   1034       1.7    dyoung 	struct ieee80211_node *ni;
   1035       1.7    dyoung 
   1036  1.60.4.1     skrll 	IEEE80211_DPRINTF(nt->nt_ic, IEEE80211_MSG_NODE,
   1037  1.60.4.1     skrll 	    "%s: mac<%s>\n", __func__, ether_sprintf(macaddr));
   1038      1.39    dyoung 	ni = ieee80211_dup_bss(nt, macaddr);
   1039      1.39    dyoung 	if (ni != NULL) {
   1040      1.35    dyoung 		/* XXX no rate negotiation; just dup */
   1041      1.35    dyoung 		ni->ni_rates = ic->ic_bss->ni_rates;
   1042      1.39    dyoung 		if (ic->ic_newassoc != NULL)
   1043      1.45     skrll 			ic->ic_newassoc(ni, 1);
   1044  1.60.4.1     skrll 		if (ic->ic_opmode == IEEE80211_M_AHDEMO) {
   1045  1.60.4.1     skrll 			/*
   1046  1.60.4.1     skrll 			 * In adhoc demo mode there are no management
   1047  1.60.4.1     skrll 			 * frames to use to discover neighbor capabilities,
   1048  1.60.4.1     skrll 			 * so blindly propagate the local configuration
   1049  1.60.4.1     skrll 			 * so we can do interesting things (e.g. use
   1050  1.60.4.1     skrll 			 * WME to disable ACK's).
   1051  1.60.4.1     skrll 			 */
   1052  1.60.4.1     skrll 			if (ic->ic_flags & IEEE80211_F_WME)
   1053  1.60.4.1     skrll 				ni->ni_flags |= IEEE80211_NODE_QOS;
   1054  1.60.4.1     skrll 			if (ic->ic_flags & IEEE80211_F_FF)
   1055  1.60.4.1     skrll 				ni->ni_flags |= IEEE80211_NODE_FF;
   1056  1.60.4.1     skrll 		}
   1057      1.45     skrll 		/* XXX not right for 802.1x/WPA */
   1058      1.45     skrll 		ieee80211_node_authorize(ni);
   1059      1.45     skrll 	}
   1060      1.45     skrll 	return ni;
   1061      1.45     skrll }
   1062      1.45     skrll 
   1063      1.45     skrll void
   1064  1.60.4.1     skrll ieee80211_init_neighbor(struct ieee80211_node *ni,
   1065      1.45     skrll 	const struct ieee80211_frame *wh,
   1066  1.60.4.1     skrll 	const struct ieee80211_scanparams *sp)
   1067      1.46    dyoung {
   1068      1.46    dyoung 	ni->ni_esslen = sp->ssid[1];
   1069      1.46    dyoung 	memcpy(ni->ni_essid, sp->ssid + 2, sp->ssid[1]);
   1070      1.46    dyoung 	IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3);
   1071      1.46    dyoung 	memcpy(ni->ni_tstamp.data, sp->tstamp, sizeof(ni->ni_tstamp));
   1072      1.46    dyoung 	ni->ni_intval = sp->bintval;
   1073      1.46    dyoung 	ni->ni_capinfo = sp->capinfo;
   1074  1.60.4.1     skrll 	ni->ni_chan = ni->ni_ic->ic_curchan;
   1075      1.46    dyoung 	ni->ni_fhdwell = sp->fhdwell;
   1076      1.46    dyoung 	ni->ni_fhindex = sp->fhindex;
   1077      1.46    dyoung 	ni->ni_erp = sp->erp;
   1078      1.46    dyoung 	ni->ni_timoff = sp->timoff;
   1079      1.46    dyoung 	if (sp->wme != NULL)
   1080      1.46    dyoung 		ieee80211_saveie(&ni->ni_wme_ie, sp->wme);
   1081      1.46    dyoung 	if (sp->wpa != NULL)
   1082      1.46    dyoung 		ieee80211_saveie(&ni->ni_wpa_ie, sp->wpa);
   1083  1.60.4.1     skrll 	if (sp->rsn != NULL)
   1084  1.60.4.1     skrll 		ieee80211_saveie(&ni->ni_rsn_ie, sp->rsn);
   1085  1.60.4.1     skrll 	if (sp->ath != NULL)
   1086  1.60.4.1     skrll 		ieee80211_saveath(ni, sp->ath);
   1087      1.46    dyoung 
   1088      1.46    dyoung 	/* NB: must be after ni_chan is setup */
   1089      1.46    dyoung 	ieee80211_setup_rates(ni, sp->rates, sp->xrates,
   1090  1.60.4.1     skrll 		IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE |
   1091  1.60.4.1     skrll 		IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
   1092      1.46    dyoung }
   1093      1.46    dyoung 
   1094      1.45     skrll /*
   1095      1.45     skrll  * Do node discovery in adhoc mode on receipt of a beacon
   1096      1.45     skrll  * or probe response frame.  Note that for the driver's
   1097      1.45     skrll  * benefit we we treat this like an association so the
   1098      1.45     skrll  * driver has an opportunity to setup it's private state.
   1099      1.45     skrll  */
   1100      1.45     skrll struct ieee80211_node *
   1101      1.45     skrll ieee80211_add_neighbor(struct ieee80211com *ic,
   1102      1.45     skrll 	const struct ieee80211_frame *wh,
   1103      1.45     skrll 	const struct ieee80211_scanparams *sp)
   1104      1.45     skrll {
   1105      1.45     skrll 	struct ieee80211_node *ni;
   1106      1.45     skrll 
   1107  1.60.4.1     skrll 	IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
   1108  1.60.4.1     skrll 	    "%s: mac<%s>\n", __func__, ether_sprintf(wh->i_addr2));
   1109      1.45     skrll 	ni = ieee80211_dup_bss(&ic->ic_sta, wh->i_addr2);/* XXX alloc_node? */
   1110      1.45     skrll 	if (ni != NULL) {
   1111  1.60.4.1     skrll 		ieee80211_init_neighbor(ni, wh, sp);
   1112  1.60.4.1     skrll 		if (ic->ic_newassoc != NULL)
   1113  1.60.4.1     skrll 			ic->ic_newassoc(ni, 1);
   1114      1.39    dyoung 		/* XXX not right for 802.1x/WPA */
   1115      1.45     skrll 		ieee80211_node_authorize(ni);
   1116       1.7    dyoung 	}
   1117      1.39    dyoung 	return ni;
   1118       1.7    dyoung }
   1119       1.7    dyoung 
   1120      1.45     skrll #define	IS_CTL(wh) \
   1121      1.45     skrll 	((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_CTL)
   1122      1.45     skrll #define	IS_PSPOLL(wh) \
   1123      1.45     skrll 	((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == IEEE80211_FC0_SUBTYPE_PS_POLL)
   1124  1.60.4.1     skrll #define	IS_BAR(wh) \
   1125  1.60.4.1     skrll 	((wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) == IEEE80211_FC0_SUBTYPE_BAR)
   1126  1.60.4.1     skrll 
   1127       1.7    dyoung /*
   1128      1.39    dyoung  * Locate the node for sender, track state, and then pass the
   1129      1.39    dyoung  * (referenced) node up to the 802.11 layer for its use.  We
   1130      1.39    dyoung  * are required to pass some node so we fall back to ic_bss
   1131      1.39    dyoung  * when this frame is from an unknown sender.  The 802.11 layer
   1132      1.39    dyoung  * knows this means the sender wasn't in the node table and
   1133      1.39    dyoung  * acts accordingly.
   1134       1.7    dyoung  */
   1135      1.39    dyoung struct ieee80211_node *
   1136      1.39    dyoung #ifdef IEEE80211_DEBUG_REFCNT
   1137      1.39    dyoung ieee80211_find_rxnode_debug(struct ieee80211com *ic,
   1138      1.39    dyoung 	const struct ieee80211_frame_min *wh, const char *func, int line)
   1139      1.39    dyoung #else
   1140      1.39    dyoung ieee80211_find_rxnode(struct ieee80211com *ic,
   1141      1.39    dyoung 	const struct ieee80211_frame_min *wh)
   1142      1.39    dyoung #endif
   1143       1.7    dyoung {
   1144      1.39    dyoung 	struct ieee80211_node_table *nt;
   1145      1.39    dyoung 	struct ieee80211_node *ni;
   1146       1.7    dyoung 
   1147      1.39    dyoung 	/* XXX check ic_bss first in station mode */
   1148      1.39    dyoung 	/* XXX 4-address frames? */
   1149  1.60.4.1     skrll 	nt = &ic->ic_sta;
   1150      1.39    dyoung 	IEEE80211_NODE_LOCK(nt);
   1151  1.60.4.1     skrll 	if (IS_CTL(wh) && !IS_PSPOLL(wh) && !IS_BAR(wh) /*&& !IS_RTS(ah)*/)
   1152      1.39    dyoung 		ni = _ieee80211_find_node(nt, wh->i_addr1);
   1153      1.39    dyoung 	else
   1154      1.39    dyoung 		ni = _ieee80211_find_node(nt, wh->i_addr2);
   1155      1.45     skrll 	if (ni == NULL)
   1156      1.45     skrll 		ni = ieee80211_ref_node(ic->ic_bss);
   1157      1.39    dyoung 	IEEE80211_NODE_UNLOCK(nt);
   1158       1.7    dyoung 
   1159      1.45     skrll 	return ni;
   1160      1.45     skrll }
   1161      1.45     skrll 
   1162      1.45     skrll /*
   1163      1.45     skrll  * Like ieee80211_find_rxnode but use the supplied h/w
   1164      1.45     skrll  * key index as a hint to locate the node in the key
   1165      1.45     skrll  * mapping table.  If an entry is present at the key
   1166      1.45     skrll  * index we return it; otherwise do a normal lookup and
   1167      1.45     skrll  * update the mapping table if the station has a unicast
   1168      1.45     skrll  * key assigned to it.
   1169      1.45     skrll  */
   1170      1.45     skrll struct ieee80211_node *
   1171      1.45     skrll #ifdef IEEE80211_DEBUG_REFCNT
   1172      1.45     skrll ieee80211_find_rxnode_withkey_debug(struct ieee80211com *ic,
   1173      1.45     skrll 	const struct ieee80211_frame_min *wh, ieee80211_keyix keyix,
   1174      1.45     skrll 	const char *func, int line)
   1175      1.45     skrll #else
   1176      1.45     skrll ieee80211_find_rxnode_withkey(struct ieee80211com *ic,
   1177      1.45     skrll 	const struct ieee80211_frame_min *wh, ieee80211_keyix keyix)
   1178      1.45     skrll #endif
   1179      1.45     skrll {
   1180      1.45     skrll 	struct ieee80211_node_table *nt;
   1181      1.45     skrll 	struct ieee80211_node *ni;
   1182      1.45     skrll 
   1183  1.60.4.1     skrll 	nt = &ic->ic_sta;
   1184      1.45     skrll 	IEEE80211_NODE_LOCK(nt);
   1185      1.45     skrll 	if (nt->nt_keyixmap != NULL && keyix < nt->nt_keyixmax)
   1186      1.45     skrll 		ni = nt->nt_keyixmap[keyix];
   1187      1.45     skrll 	else
   1188      1.45     skrll 		ni = NULL;
   1189      1.45     skrll 	if (ni == NULL) {
   1190  1.60.4.1     skrll 		if (IS_CTL(wh) && !IS_PSPOLL(wh) && !IS_BAR(wh) /*&& !IS_RTS(ah)*/)
   1191      1.45     skrll 			ni = _ieee80211_find_node(nt, wh->i_addr1);
   1192      1.45     skrll 		else
   1193      1.45     skrll 			ni = _ieee80211_find_node(nt, wh->i_addr2);
   1194      1.45     skrll 		if (ni == NULL)
   1195      1.45     skrll 			ni = ieee80211_ref_node(ic->ic_bss);
   1196      1.45     skrll 		if (nt->nt_keyixmap != NULL) {
   1197      1.45     skrll 			/*
   1198      1.45     skrll 			 * If the station has a unicast key cache slot
   1199      1.45     skrll 			 * assigned update the key->node mapping table.
   1200      1.45     skrll 			 */
   1201      1.45     skrll 			keyix = ni->ni_ucastkey.wk_rxkeyix;
   1202      1.45     skrll 			/* XXX can keyixmap[keyix] != NULL? */
   1203      1.45     skrll 			if (keyix < nt->nt_keyixmax &&
   1204      1.45     skrll 			    nt->nt_keyixmap[keyix] == NULL) {
   1205      1.45     skrll 				IEEE80211_DPRINTF(ni->ni_ic, IEEE80211_MSG_NODE,
   1206      1.45     skrll 				    "%s: add key map entry %p<%s> refcnt %d\n",
   1207      1.45     skrll 				    __func__, ni, ether_sprintf(ni->ni_macaddr),
   1208      1.45     skrll 				    ieee80211_node_refcnt(ni)+1);
   1209      1.45     skrll 				nt->nt_keyixmap[keyix] = ieee80211_ref_node(ni);
   1210      1.45     skrll 			}
   1211      1.45     skrll 		}
   1212  1.60.4.1     skrll 	} else
   1213      1.45     skrll 		ieee80211_ref_node(ni);
   1214      1.45     skrll 	IEEE80211_NODE_UNLOCK(nt);
   1215      1.45     skrll 
   1216      1.45     skrll 	return ni;
   1217      1.45     skrll }
   1218  1.60.4.1     skrll #undef IS_BAR
   1219      1.39    dyoung #undef IS_PSPOLL
   1220      1.39    dyoung #undef IS_CTL
   1221       1.7    dyoung 
   1222      1.39    dyoung /*
   1223      1.39    dyoung  * Return a reference to the appropriate node for sending
   1224      1.39    dyoung  * a data frame.  This handles node discovery in adhoc networks.
   1225      1.33    dyoung  */
   1226       1.7    dyoung struct ieee80211_node *
   1227      1.39    dyoung #ifdef IEEE80211_DEBUG_REFCNT
   1228  1.60.4.1     skrll ieee80211_find_txnode_debug(struct ieee80211com *ic, const uint8_t *macaddr,
   1229      1.39    dyoung 	const char *func, int line)
   1230      1.39    dyoung #else
   1231  1.60.4.1     skrll ieee80211_find_txnode(struct ieee80211com *ic, const uint8_t *macaddr)
   1232      1.39    dyoung #endif
   1233       1.7    dyoung {
   1234      1.39    dyoung 	struct ieee80211_node_table *nt = &ic->ic_sta;
   1235       1.7    dyoung 	struct ieee80211_node *ni;
   1236       1.7    dyoung 
   1237      1.39    dyoung 	/*
   1238      1.39    dyoung 	 * The destination address should be in the node table
   1239      1.45     skrll 	 * unless this is a multicast/broadcast frame.  We can
   1240      1.45     skrll 	 * also optimize station mode operation, all frames go
   1241      1.45     skrll 	 * to the bss node.
   1242      1.39    dyoung 	 */
   1243      1.39    dyoung 	/* XXX can't hold lock across dup_bss 'cuz of recursive locking */
   1244      1.39    dyoung 	IEEE80211_NODE_LOCK(nt);
   1245      1.45     skrll 	if (ic->ic_opmode == IEEE80211_M_STA || IEEE80211_IS_MULTICAST(macaddr))
   1246      1.45     skrll 		ni = ieee80211_ref_node(ic->ic_bss);
   1247  1.60.4.1     skrll 	else {
   1248      1.45     skrll 		ni = _ieee80211_find_node(nt, macaddr);
   1249  1.60.4.1     skrll 		if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
   1250  1.60.4.1     skrll 		    (ni != NULL && ni->ni_associd == 0)) {
   1251  1.60.4.1     skrll 			/*
   1252  1.60.4.1     skrll 			 * Station is not associated; don't permit the
   1253  1.60.4.1     skrll 			 * data frame to be sent by returning NULL.  This
   1254  1.60.4.1     skrll 			 * is kinda a kludge but the least intrusive way
   1255  1.60.4.1     skrll 			 * to add this check into all drivers.
   1256  1.60.4.1     skrll 			 */
   1257  1.60.4.1     skrll 			ieee80211_unref_node(&ni);	/* NB: null's ni */
   1258  1.60.4.1     skrll 		}
   1259  1.60.4.1     skrll 	}
   1260      1.39    dyoung 	IEEE80211_NODE_UNLOCK(nt);
   1261      1.15    dyoung 
   1262      1.39    dyoung 	if (ni == NULL) {
   1263      1.39    dyoung 		if (ic->ic_opmode == IEEE80211_M_IBSS ||
   1264      1.39    dyoung 		    ic->ic_opmode == IEEE80211_M_AHDEMO) {
   1265      1.39    dyoung 			/*
   1266      1.39    dyoung 			 * In adhoc mode cons up a node for the destination.
   1267      1.39    dyoung 			 * Note that we need an additional reference for the
   1268      1.39    dyoung 			 * caller to be consistent with _ieee80211_find_node.
   1269      1.39    dyoung 			 */
   1270      1.39    dyoung 			ni = ieee80211_fakeup_adhoc_node(nt, macaddr);
   1271      1.39    dyoung 			if (ni != NULL)
   1272      1.39    dyoung 				(void) ieee80211_ref_node(ni);
   1273      1.39    dyoung 		} else {
   1274      1.39    dyoung 			IEEE80211_DPRINTF(ic, IEEE80211_MSG_OUTPUT,
   1275      1.39    dyoung 				"[%s] no node, discard frame (%s)\n",
   1276      1.39    dyoung 				ether_sprintf(macaddr), __func__);
   1277      1.39    dyoung 			ic->ic_stats.is_tx_nonode++;
   1278      1.39    dyoung 		}
   1279      1.39    dyoung 	}
   1280      1.39    dyoung 	return ni;
   1281       1.1    dyoung }
   1282       1.1    dyoung 
   1283       1.1    dyoung /*
   1284      1.39    dyoung  * Like find but search based on the ssid too.
   1285      1.39    dyoung  */
   1286      1.39    dyoung struct ieee80211_node *
   1287      1.39    dyoung #ifdef IEEE80211_DEBUG_REFCNT
   1288      1.39    dyoung ieee80211_find_node_with_ssid_debug(struct ieee80211_node_table *nt,
   1289  1.60.4.1     skrll 	const uint8_t *macaddr, u_int ssidlen, const uint8_t *ssid,
   1290      1.39    dyoung 	const char *func, int line)
   1291      1.39    dyoung #else
   1292      1.39    dyoung ieee80211_find_node_with_ssid(struct ieee80211_node_table *nt,
   1293  1.60.4.1     skrll 	const uint8_t *macaddr, u_int ssidlen, const uint8_t *ssid)
   1294      1.39    dyoung #endif
   1295      1.39    dyoung {
   1296      1.42    dyoung #define	MATCH_SSID(ni, ssid, ssidlen) \
   1297      1.42    dyoung 	(ni->ni_esslen == ssidlen && memcmp(ni->ni_essid, ssid, ssidlen) == 0)
   1298  1.60.4.1     skrll 	static const uint8_t zeromac[IEEE80211_ADDR_LEN];
   1299      1.39    dyoung 	struct ieee80211_node *ni;
   1300      1.39    dyoung 	int hash;
   1301      1.39    dyoung 
   1302      1.39    dyoung 	IEEE80211_NODE_LOCK(nt);
   1303      1.42    dyoung 	/*
   1304      1.42    dyoung 	 * A mac address that is all zero means match only the ssid;
   1305      1.42    dyoung 	 * otherwise we must match both.
   1306      1.42    dyoung 	 */
   1307      1.42    dyoung 	if (IEEE80211_ADDR_EQ(macaddr, zeromac)) {
   1308      1.42    dyoung 		TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
   1309      1.42    dyoung 			if (MATCH_SSID(ni, ssid, ssidlen))
   1310      1.42    dyoung 				break;
   1311      1.42    dyoung 		}
   1312      1.42    dyoung 	} else {
   1313      1.42    dyoung 		hash = IEEE80211_NODE_HASH(macaddr);
   1314      1.42    dyoung 		LIST_FOREACH(ni, &nt->nt_hash[hash], ni_hash) {
   1315      1.42    dyoung 			if (IEEE80211_ADDR_EQ(ni->ni_macaddr, macaddr) &&
   1316      1.42    dyoung 			    MATCH_SSID(ni, ssid, ssidlen))
   1317      1.42    dyoung 				break;
   1318      1.42    dyoung 		}
   1319      1.42    dyoung 	}
   1320      1.42    dyoung 	if (ni != NULL) {
   1321      1.42    dyoung 		ieee80211_ref_node(ni);	/* mark referenced */
   1322  1.60.4.1     skrll 		IEEE80211_DPRINTF(nt->nt_ic, IEEE80211_MSG_NODE,
   1323  1.60.4.1     skrll 		     REFCNT_LOC, ni, ether_sprintf(ni->ni_macaddr),
   1324      1.42    dyoung 		     ieee80211_node_refcnt(ni));
   1325      1.39    dyoung 	}
   1326      1.39    dyoung 	IEEE80211_NODE_UNLOCK(nt);
   1327      1.39    dyoung 	return ni;
   1328      1.42    dyoung #undef MATCH_SSID
   1329      1.39    dyoung }
   1330      1.39    dyoung 
   1331       1.1    dyoung static void
   1332      1.39    dyoung _ieee80211_free_node(struct ieee80211_node *ni)
   1333       1.1    dyoung {
   1334      1.39    dyoung 	struct ieee80211com *ic = ni->ni_ic;
   1335      1.39    dyoung 	struct ieee80211_node_table *nt = ni->ni_table;
   1336       1.1    dyoung 
   1337      1.22   mycroft 	IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
   1338      1.39    dyoung 		"%s %p<%s> in %s table\n", __func__, ni,
   1339      1.39    dyoung 		ether_sprintf(ni->ni_macaddr),
   1340      1.39    dyoung 		nt != NULL ? nt->nt_name : "<gone>");
   1341      1.39    dyoung 
   1342       1.5    dyoung 	IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap);
   1343      1.39    dyoung 	if (nt != NULL) {
   1344      1.39    dyoung 		TAILQ_REMOVE(&nt->nt_node, ni, ni_list);
   1345      1.39    dyoung 		LIST_REMOVE(ni, ni_hash);
   1346      1.39    dyoung 	}
   1347      1.39    dyoung 	ic->ic_node_free(ni);
   1348       1.1    dyoung }
   1349       1.1    dyoung 
   1350       1.1    dyoung void
   1351      1.39    dyoung #ifdef IEEE80211_DEBUG_REFCNT
   1352      1.39    dyoung ieee80211_free_node_debug(struct ieee80211_node *ni, const char *func, int line)
   1353      1.39    dyoung #else
   1354      1.39    dyoung ieee80211_free_node(struct ieee80211_node *ni)
   1355      1.39    dyoung #endif
   1356      1.39    dyoung {
   1357      1.39    dyoung 	struct ieee80211_node_table *nt = ni->ni_table;
   1358      1.39    dyoung 
   1359      1.39    dyoung #ifdef IEEE80211_DEBUG_REFCNT
   1360      1.39    dyoung 	IEEE80211_DPRINTF(ni->ni_ic, IEEE80211_MSG_NODE,
   1361      1.39    dyoung 		"%s (%s:%u) %p<%s> refcnt %d\n", __func__, func, line, ni,
   1362      1.39    dyoung 		 ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni)-1);
   1363      1.39    dyoung #endif
   1364      1.45     skrll 	if (nt != NULL) {
   1365      1.45     skrll 		IEEE80211_NODE_LOCK(nt);
   1366      1.45     skrll 		if (ieee80211_node_dectestref(ni)) {
   1367      1.45     skrll 			/*
   1368      1.45     skrll 			 * Last reference, reclaim state.
   1369      1.45     skrll 			 */
   1370      1.39    dyoung 			_ieee80211_free_node(ni);
   1371      1.45     skrll 		} else if (ieee80211_node_refcnt(ni) == 1 &&
   1372      1.45     skrll 		    nt->nt_keyixmap != NULL) {
   1373      1.45     skrll 			ieee80211_keyix keyix;
   1374      1.45     skrll 			/*
   1375      1.45     skrll 			 * Check for a last reference in the key mapping table.
   1376      1.45     skrll 			 */
   1377      1.45     skrll 			keyix = ni->ni_ucastkey.wk_rxkeyix;
   1378      1.45     skrll 			if (keyix < nt->nt_keyixmax &&
   1379      1.45     skrll 			    nt->nt_keyixmap[keyix] == ni) {
   1380      1.45     skrll 				IEEE80211_DPRINTF(ni->ni_ic, IEEE80211_MSG_NODE,
   1381      1.45     skrll 				    "%s: %p<%s> clear key map entry", __func__,
   1382      1.45     skrll 				    ni, ether_sprintf(ni->ni_macaddr));
   1383      1.45     skrll 				nt->nt_keyixmap[keyix] = NULL;
   1384      1.45     skrll 				ieee80211_node_decref(ni); /* XXX needed? */
   1385      1.45     skrll 				_ieee80211_free_node(ni);
   1386      1.45     skrll 			}
   1387      1.45     skrll 		}
   1388      1.45     skrll 		IEEE80211_NODE_UNLOCK(nt);
   1389      1.45     skrll 	} else {
   1390      1.45     skrll 		if (ieee80211_node_dectestref(ni))
   1391      1.39    dyoung 			_ieee80211_free_node(ni);
   1392      1.39    dyoung 	}
   1393      1.39    dyoung }
   1394      1.39    dyoung 
   1395      1.39    dyoung /*
   1396      1.45     skrll  * Reclaim a unicast key and clear any key cache state.
   1397      1.45     skrll  */
   1398      1.45     skrll int
   1399      1.45     skrll ieee80211_node_delucastkey(struct ieee80211_node *ni)
   1400      1.45     skrll {
   1401      1.45     skrll 	struct ieee80211com *ic = ni->ni_ic;
   1402      1.45     skrll 	struct ieee80211_node_table *nt = &ic->ic_sta;
   1403      1.45     skrll 	struct ieee80211_node *nikey;
   1404      1.45     skrll 	ieee80211_keyix keyix;
   1405      1.45     skrll 	int isowned, status;
   1406      1.45     skrll 
   1407      1.45     skrll 	/*
   1408      1.45     skrll 	 * NB: We must beware of LOR here; deleting the key
   1409      1.45     skrll 	 * can cause the crypto layer to block traffic updates
   1410      1.45     skrll 	 * which can generate a LOR against the node table lock;
   1411      1.45     skrll 	 * grab it here and stash the key index for our use below.
   1412      1.45     skrll 	 *
   1413      1.45     skrll 	 * Must also beware of recursion on the node table lock.
   1414      1.45     skrll 	 * When called from node_cleanup we may already have
   1415      1.45     skrll 	 * the node table lock held.  Unfortunately there's no
   1416      1.45     skrll 	 * way to separate out this path so we must do this
   1417      1.45     skrll 	 * conditionally.
   1418      1.45     skrll 	 */
   1419      1.45     skrll 	isowned = IEEE80211_NODE_IS_LOCKED(nt);
   1420      1.45     skrll 	if (!isowned)
   1421      1.45     skrll 		IEEE80211_NODE_LOCK(nt);
   1422      1.45     skrll 	keyix = ni->ni_ucastkey.wk_rxkeyix;
   1423      1.45     skrll 	status = ieee80211_crypto_delkey(ic, &ni->ni_ucastkey);
   1424      1.45     skrll 	if (nt->nt_keyixmap != NULL && keyix < nt->nt_keyixmax) {
   1425      1.45     skrll 		nikey = nt->nt_keyixmap[keyix];
   1426      1.45     skrll 		nt->nt_keyixmap[keyix] = NULL;;
   1427      1.45     skrll 	} else
   1428      1.45     skrll 		nikey = NULL;
   1429      1.45     skrll 	if (!isowned)
   1430      1.45     skrll 		IEEE80211_NODE_UNLOCK(&ic->ic_sta);
   1431      1.45     skrll 
   1432      1.45     skrll 	if (nikey != NULL) {
   1433      1.45     skrll 		IASSERT(nikey == ni,
   1434      1.45     skrll 			("key map out of sync, ni %p nikey %p", ni, nikey));
   1435      1.45     skrll 		IEEE80211_DPRINTF(ni->ni_ic, IEEE80211_MSG_NODE,
   1436      1.45     skrll 			"%s: delete key map entry %p<%s> refcnt %d\n",
   1437      1.45     skrll 			__func__, ni, ether_sprintf(ni->ni_macaddr),
   1438      1.45     skrll 			ieee80211_node_refcnt(ni)-1);
   1439      1.45     skrll 		ieee80211_free_node(ni);
   1440      1.45     skrll 	}
   1441      1.45     skrll 	return status;
   1442      1.45     skrll }
   1443      1.45     skrll 
   1444      1.45     skrll /*
   1445      1.39    dyoung  * Reclaim a node.  If this is the last reference count then
   1446      1.39    dyoung  * do the normal free work.  Otherwise remove it from the node
   1447      1.39    dyoung  * table and mark it gone by clearing the back-reference.
   1448      1.39    dyoung  */
   1449      1.39    dyoung static void
   1450      1.39    dyoung node_reclaim(struct ieee80211_node_table *nt, struct ieee80211_node *ni)
   1451      1.39    dyoung {
   1452      1.45     skrll 	ieee80211_keyix keyix;
   1453      1.45     skrll 
   1454      1.45     skrll 	IEEE80211_NODE_LOCK_ASSERT(nt);
   1455      1.39    dyoung 
   1456      1.39    dyoung 	IEEE80211_DPRINTF(ni->ni_ic, IEEE80211_MSG_NODE,
   1457      1.39    dyoung 		"%s: remove %p<%s> from %s table, refcnt %d\n",
   1458      1.39    dyoung 		__func__, ni, ether_sprintf(ni->ni_macaddr),
   1459      1.39    dyoung 		nt->nt_name, ieee80211_node_refcnt(ni)-1);
   1460      1.45     skrll 	/*
   1461      1.45     skrll 	 * Clear any entry in the unicast key mapping table.
   1462      1.45     skrll 	 * We need to do it here so rx lookups don't find it
   1463      1.45     skrll 	 * in the mapping table even if it's not in the hash
   1464      1.45     skrll 	 * table.  We cannot depend on the mapping table entry
   1465      1.45     skrll 	 * being cleared because the node may not be free'd.
   1466      1.45     skrll 	 */
   1467      1.45     skrll 	keyix = ni->ni_ucastkey.wk_rxkeyix;
   1468      1.45     skrll 	if (nt->nt_keyixmap != NULL && keyix < nt->nt_keyixmax &&
   1469      1.45     skrll 	    nt->nt_keyixmap[keyix] == ni) {
   1470      1.45     skrll 		IEEE80211_DPRINTF(ni->ni_ic, IEEE80211_MSG_NODE,
   1471      1.45     skrll 			"%s: %p<%s> clear key map entry\n",
   1472      1.45     skrll 			__func__, ni, ether_sprintf(ni->ni_macaddr));
   1473      1.45     skrll 		nt->nt_keyixmap[keyix] = NULL;
   1474      1.45     skrll 		ieee80211_node_decref(ni);	/* NB: don't need free */
   1475      1.45     skrll 	}
   1476      1.39    dyoung 	if (!ieee80211_node_dectestref(ni)) {
   1477      1.39    dyoung 		/*
   1478      1.39    dyoung 		 * Other references are present, just remove the
   1479      1.39    dyoung 		 * node from the table so it cannot be found.  When
   1480      1.39    dyoung 		 * the references are dropped storage will be
   1481      1.39    dyoung 		 * reclaimed.
   1482      1.39    dyoung 		 */
   1483      1.39    dyoung 		TAILQ_REMOVE(&nt->nt_node, ni, ni_list);
   1484      1.39    dyoung 		LIST_REMOVE(ni, ni_hash);
   1485      1.39    dyoung 		ni->ni_table = NULL;		/* clear reference */
   1486      1.39    dyoung 	} else
   1487      1.39    dyoung 		_ieee80211_free_node(ni);
   1488      1.39    dyoung }
   1489      1.39    dyoung 
   1490      1.39    dyoung static void
   1491      1.39    dyoung ieee80211_free_allnodes_locked(struct ieee80211_node_table *nt)
   1492       1.1    dyoung {
   1493      1.39    dyoung 	struct ieee80211com *ic = nt->nt_ic;
   1494      1.39    dyoung 	struct ieee80211_node *ni;
   1495      1.39    dyoung 
   1496      1.23   mycroft 	IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
   1497      1.39    dyoung 		"%s: free all nodes in %s table\n", __func__, nt->nt_name);
   1498      1.39    dyoung 
   1499      1.39    dyoung 	while ((ni = TAILQ_FIRST(&nt->nt_node)) != NULL) {
   1500      1.39    dyoung 		if (ni->ni_associd != 0) {
   1501      1.39    dyoung 			if (ic->ic_auth->ia_node_leave != NULL)
   1502      1.39    dyoung 				ic->ic_auth->ia_node_leave(ic, ni);
   1503      1.39    dyoung 			IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap);
   1504      1.39    dyoung 		}
   1505      1.39    dyoung 		node_reclaim(nt, ni);
   1506       1.1    dyoung 	}
   1507       1.1    dyoung }
   1508       1.1    dyoung 
   1509       1.9    dyoung /*
   1510      1.39    dyoung  * Timeout inactive stations and do related housekeeping.
   1511      1.39    dyoung  * Note that we cannot hold the node lock while sending a
   1512      1.39    dyoung  * frame as this would lead to a LOR.  Instead we use a
   1513      1.39    dyoung  * generation number to mark nodes that we've scanned and
   1514      1.39    dyoung  * drop the lock and restart a scan if we have to time out
   1515      1.39    dyoung  * a node.  Since we are single-threaded by virtue of
   1516       1.9    dyoung  * controlling the inactivity timer we can be sure this will
   1517       1.9    dyoung  * process each node only once.
   1518       1.9    dyoung  */
   1519      1.39    dyoung static void
   1520      1.39    dyoung ieee80211_timeout_stations(struct ieee80211_node_table *nt)
   1521       1.1    dyoung {
   1522      1.39    dyoung 	struct ieee80211com *ic = nt->nt_ic;
   1523       1.9    dyoung 	struct ieee80211_node *ni;
   1524      1.39    dyoung 	u_int gen;
   1525      1.45     skrll 	int isadhoc;
   1526       1.1    dyoung 
   1527      1.45     skrll 	isadhoc = (ic->ic_opmode == IEEE80211_M_IBSS ||
   1528      1.45     skrll 		   ic->ic_opmode == IEEE80211_M_AHDEMO);
   1529      1.39    dyoung 	IEEE80211_SCAN_LOCK(nt);
   1530      1.56     seanb 	gen = ++nt->nt_scangen;
   1531      1.39    dyoung 	IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
   1532      1.39    dyoung 		"%s: %s scangen %u\n", __func__, nt->nt_name, gen);
   1533       1.9    dyoung restart:
   1534      1.39    dyoung 	IEEE80211_NODE_LOCK(nt);
   1535      1.39    dyoung 	TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
   1536       1.9    dyoung 		if (ni->ni_scangen == gen)	/* previously handled */
   1537       1.9    dyoung 			continue;
   1538       1.9    dyoung 		ni->ni_scangen = gen;
   1539      1.39    dyoung 		/*
   1540      1.42    dyoung 		 * Ignore entries for which have yet to receive an
   1541      1.42    dyoung 		 * authentication frame.  These are transient and
   1542      1.42    dyoung 		 * will be reclaimed when the last reference to them
   1543      1.42    dyoung 		 * goes away (when frame xmits complete).
   1544      1.42    dyoung 		 */
   1545  1.60.4.1     skrll 		if ((ic->ic_opmode == IEEE80211_M_HOSTAP ||
   1546  1.60.4.1     skrll 		     ic->ic_opmode == IEEE80211_M_STA) &&
   1547      1.45     skrll 		    (ni->ni_flags & IEEE80211_NODE_AREF) == 0)
   1548      1.42    dyoung 			continue;
   1549      1.42    dyoung 		/*
   1550      1.39    dyoung 		 * Free fragment if not needed anymore
   1551      1.39    dyoung 		 * (last fragment older than 1s).
   1552      1.39    dyoung 		 * XXX doesn't belong here
   1553      1.39    dyoung 		 */
   1554      1.39    dyoung 		if (ni->ni_rxfrag[0] != NULL &&
   1555      1.39    dyoung 		    ticks > ni->ni_rxfragstamp + hz) {
   1556      1.39    dyoung 			m_freem(ni->ni_rxfrag[0]);
   1557      1.39    dyoung 			ni->ni_rxfrag[0] = NULL;
   1558      1.39    dyoung 		}
   1559  1.60.4.1     skrll 		if (ni->ni_inact > 0)
   1560  1.60.4.1     skrll 			ni->ni_inact--;
   1561      1.39    dyoung 		/*
   1562      1.39    dyoung 		 * Special case ourself; we may be idle for extended periods
   1563      1.39    dyoung 		 * of time and regardless reclaiming our state is wrong.
   1564      1.39    dyoung 		 */
   1565      1.39    dyoung 		if (ni == ic->ic_bss)
   1566      1.33    dyoung 			continue;
   1567      1.45     skrll 		if (ni->ni_associd != 0 || isadhoc) {
   1568      1.39    dyoung 			/*
   1569  1.60.4.1     skrll 			 * Age frames on the power save queue.
   1570      1.39    dyoung 			 */
   1571  1.60.4.1     skrll 			if (ieee80211_node_saveq_age(ni) != 0 &&
   1572  1.60.4.1     skrll 			    IEEE80211_NODE_SAVEQ_QLEN(ni) == 0 &&
   1573  1.60.4.1     skrll 			    ic->ic_set_tim != NULL)
   1574  1.60.4.1     skrll 				ic->ic_set_tim(ni, 0);
   1575      1.39    dyoung 			/*
   1576      1.39    dyoung 			 * Probe the station before time it out.  We
   1577      1.39    dyoung 			 * send a null data frame which may not be
   1578      1.39    dyoung 			 * universally supported by drivers (need it
   1579      1.39    dyoung 			 * for ps-poll support so it should be...).
   1580  1.60.4.1     skrll 			 *
   1581  1.60.4.1     skrll 			 * XXX don't probe the station unless we've
   1582  1.60.4.1     skrll 			 *     received a frame from them (and have
   1583  1.60.4.1     skrll 			 *     some idea of the rates they are capable
   1584  1.60.4.1     skrll 			 *     of); this will get fixed more properly
   1585  1.60.4.1     skrll 			 *     soon with better handling of the rate set.
   1586      1.39    dyoung 			 */
   1587  1.60.4.1     skrll 			if ((ic->ic_flags_ext & IEEE80211_FEXT_INACT) &&
   1588  1.60.4.1     skrll 			    (0 < ni->ni_inact &&
   1589  1.60.4.1     skrll 			     ni->ni_inact <= ic->ic_inact_probe) &&
   1590  1.60.4.1     skrll 			    ni->ni_rates.rs_nrates != 0) {
   1591      1.45     skrll 				IEEE80211_NOTE(ic,
   1592      1.45     skrll 				    IEEE80211_MSG_INACT | IEEE80211_MSG_NODE,
   1593      1.45     skrll 				    ni, "%s",
   1594      1.45     skrll 				    "probe station due to inactivity");
   1595      1.45     skrll 				/*
   1596      1.45     skrll 				 * Grab a reference before unlocking the table
   1597      1.45     skrll 				 * so the node cannot be reclaimed before we
   1598      1.45     skrll 				 * send the frame. ieee80211_send_nulldata
   1599      1.45     skrll 				 * understands we've done this and reclaims the
   1600      1.45     skrll 				 * ref for us as needed.
   1601      1.45     skrll 				 */
   1602      1.45     skrll 				ieee80211_ref_node(ni);
   1603      1.39    dyoung 				IEEE80211_NODE_UNLOCK(nt);
   1604      1.45     skrll 				ieee80211_send_nulldata(ni);
   1605      1.39    dyoung 				/* XXX stat? */
   1606      1.39    dyoung 				goto restart;
   1607      1.39    dyoung 			}
   1608      1.39    dyoung 		}
   1609  1.60.4.1     skrll 		if ((ic->ic_flags_ext & IEEE80211_FEXT_INACT) &&
   1610  1.60.4.1     skrll 		    ni->ni_inact <= 0) {
   1611      1.45     skrll 			IEEE80211_NOTE(ic,
   1612      1.45     skrll 			    IEEE80211_MSG_INACT | IEEE80211_MSG_NODE, ni,
   1613      1.45     skrll 			    "station timed out due to inactivity "
   1614      1.45     skrll 			    "(refcnt %u)", ieee80211_node_refcnt(ni));
   1615      1.39    dyoung 			/*
   1616      1.39    dyoung 			 * Send a deauthenticate frame and drop the station.
   1617      1.39    dyoung 			 * This is somewhat complicated due to reference counts
   1618      1.39    dyoung 			 * and locking.  At this point a station will typically
   1619      1.39    dyoung 			 * have a reference count of 1.  ieee80211_node_leave
   1620      1.39    dyoung 			 * will do a "free" of the node which will drop the
   1621      1.39    dyoung 			 * reference count.  But in the meantime a reference
   1622      1.51       wiz 			 * will be held by the deauth frame.  The actual reclaim
   1623      1.39    dyoung 			 * of the node will happen either after the tx is
   1624      1.39    dyoung 			 * completed or by ieee80211_node_leave.
   1625      1.39    dyoung 			 *
   1626      1.39    dyoung 			 * Separately we must drop the node lock before sending
   1627  1.60.4.1     skrll 			 * in case the driver takes a lock, as this can result
   1628  1.60.4.1     skrll 			 * in a LOR between the node lock and the driver lock.
   1629      1.39    dyoung 			 */
   1630  1.60.4.1     skrll 			ieee80211_ref_node(ni);
   1631      1.39    dyoung 			IEEE80211_NODE_UNLOCK(nt);
   1632      1.39    dyoung 			if (ni->ni_associd != 0) {
   1633      1.39    dyoung 				IEEE80211_SEND_MGMT(ic, ni,
   1634      1.39    dyoung 				    IEEE80211_FC0_SUBTYPE_DEAUTH,
   1635      1.39    dyoung 				    IEEE80211_REASON_AUTH_EXPIRE);
   1636      1.39    dyoung 			}
   1637      1.33    dyoung 			ieee80211_node_leave(ic, ni);
   1638  1.60.4.1     skrll 			ieee80211_free_node(ni);
   1639      1.39    dyoung 			ic->ic_stats.is_node_timeout++;
   1640      1.39    dyoung 			goto restart;
   1641      1.39    dyoung 		}
   1642       1.1    dyoung 	}
   1643      1.39    dyoung 	IEEE80211_NODE_UNLOCK(nt);
   1644      1.39    dyoung 
   1645      1.39    dyoung 	IEEE80211_SCAN_UNLOCK(nt);
   1646  1.60.4.1     skrll }
   1647  1.60.4.1     skrll 
   1648  1.60.4.1     skrll void
   1649  1.60.4.1     skrll ieee80211_node_timeout(void *arg)
   1650  1.60.4.1     skrll {
   1651  1.60.4.1     skrll 	struct ieee80211com *ic = arg;
   1652  1.60.4.1     skrll 
   1653  1.60.4.1     skrll 	ieee80211_scan_timeout(ic);
   1654  1.60.4.1     skrll 	ieee80211_timeout_stations(&ic->ic_sta);
   1655      1.39    dyoung 
   1656  1.60.4.1     skrll 	IEEE80211_LOCK(ic);
   1657  1.60.4.1     skrll 	ieee80211_erp_timeout(ic);
   1658  1.60.4.1     skrll 	ieee80211_ht_timeout(ic);
   1659  1.60.4.1     skrll 	IEEE80211_UNLOCK(ic);
   1660  1.60.4.1     skrll 
   1661  1.60.4.1     skrll 	callout_reset(&ic->ic_inact, IEEE80211_INACT_WAIT*hz,
   1662  1.60.4.1     skrll 		ieee80211_node_timeout, ic);
   1663       1.1    dyoung }
   1664       1.1    dyoung 
   1665       1.1    dyoung void
   1666      1.39    dyoung ieee80211_iterate_nodes(struct ieee80211_node_table *nt, ieee80211_iter_func *f, void *arg)
   1667       1.1    dyoung {
   1668       1.1    dyoung 	struct ieee80211_node *ni;
   1669      1.39    dyoung 	u_int gen;
   1670      1.39    dyoung 
   1671      1.39    dyoung 	IEEE80211_SCAN_LOCK(nt);
   1672      1.56     seanb 	gen = ++nt->nt_scangen;
   1673      1.39    dyoung restart:
   1674      1.39    dyoung 	IEEE80211_NODE_LOCK(nt);
   1675      1.39    dyoung 	TAILQ_FOREACH(ni, &nt->nt_node, ni_list) {
   1676      1.39    dyoung 		if (ni->ni_scangen != gen) {
   1677      1.39    dyoung 			ni->ni_scangen = gen;
   1678      1.39    dyoung 			(void) ieee80211_ref_node(ni);
   1679      1.39    dyoung 			IEEE80211_NODE_UNLOCK(nt);
   1680      1.39    dyoung 			(*f)(arg, ni);
   1681      1.39    dyoung 			ieee80211_free_node(ni);
   1682      1.39    dyoung 			goto restart;
   1683      1.39    dyoung 		}
   1684      1.39    dyoung 	}
   1685      1.39    dyoung 	IEEE80211_NODE_UNLOCK(nt);
   1686      1.39    dyoung 
   1687      1.39    dyoung 	IEEE80211_SCAN_UNLOCK(nt);
   1688      1.39    dyoung }
   1689      1.39    dyoung 
   1690      1.39    dyoung void
   1691      1.59  christos ieee80211_dump_node(struct ieee80211_node_table *nt,
   1692      1.58  christos     struct ieee80211_node *ni)
   1693      1.39    dyoung {
   1694      1.39    dyoung 	printf("0x%p: mac %s refcnt %d\n", ni,
   1695      1.39    dyoung 		ether_sprintf(ni->ni_macaddr), ieee80211_node_refcnt(ni));
   1696      1.39    dyoung 	printf("\tscangen %u authmode %u flags 0x%x\n",
   1697      1.39    dyoung 		ni->ni_scangen, ni->ni_authmode, ni->ni_flags);
   1698      1.39    dyoung 	printf("\tassocid 0x%x txpower %u vlan %u\n",
   1699      1.39    dyoung 		ni->ni_associd, ni->ni_txpower, ni->ni_vlan);
   1700      1.39    dyoung 	printf("\ttxseq %u rxseq %u fragno %u rxfragstamp %u\n",
   1701  1.60.4.1     skrll 		ni->ni_txseqs[IEEE80211_NONQOS_TID],
   1702  1.60.4.1     skrll 		ni->ni_rxseqs[IEEE80211_NONQOS_TID] >> IEEE80211_SEQ_SEQ_SHIFT,
   1703  1.60.4.1     skrll 		ni->ni_rxseqs[IEEE80211_NONQOS_TID] & IEEE80211_SEQ_FRAG_MASK,
   1704      1.39    dyoung 		ni->ni_rxfragstamp);
   1705  1.60.4.1     skrll 	printf("\trstamp %u rssi %d noise %d intval %u capinfo 0x%x\n",
   1706  1.60.4.1     skrll 		ni->ni_rstamp, ni->ni_rssi, ni->ni_noise,
   1707  1.60.4.1     skrll 		ni->ni_intval, ni->ni_capinfo);
   1708      1.39    dyoung 	printf("\tbssid %s essid \"%.*s\" channel %u:0x%x\n",
   1709      1.39    dyoung 		ether_sprintf(ni->ni_bssid),
   1710      1.39    dyoung 		ni->ni_esslen, ni->ni_essid,
   1711      1.39    dyoung 		ni->ni_chan->ic_freq, ni->ni_chan->ic_flags);
   1712      1.39    dyoung 	printf("\tfails %u inact %u txrate %u\n",
   1713      1.39    dyoung 		ni->ni_fails, ni->ni_inact, ni->ni_txrate);
   1714  1.60.4.1     skrll 	printf("\thtcap %x htparam %x htctlchan %u ht2ndchan %u\n",
   1715  1.60.4.1     skrll 		ni->ni_htcap, ni->ni_htparam,
   1716  1.60.4.1     skrll 		ni->ni_htctlchan, ni->ni_ht2ndchan);
   1717  1.60.4.1     skrll 	printf("\thtopmode %x htstbc %x chw %u\n",
   1718  1.60.4.1     skrll 		ni->ni_htopmode, ni->ni_htstbc, ni->ni_chw);
   1719      1.39    dyoung }
   1720      1.39    dyoung 
   1721      1.39    dyoung void
   1722      1.39    dyoung ieee80211_dump_nodes(struct ieee80211_node_table *nt)
   1723      1.39    dyoung {
   1724      1.39    dyoung 	ieee80211_iterate_nodes(nt,
   1725      1.39    dyoung 		(ieee80211_iter_func *) ieee80211_dump_node, nt);
   1726      1.39    dyoung }
   1727      1.39    dyoung 
   1728  1.60.4.1     skrll void
   1729  1.60.4.1     skrll ieee80211_notify_erp(struct ieee80211com *ic)
   1730  1.60.4.1     skrll {
   1731  1.60.4.1     skrll 	if (ic->ic_opmode == IEEE80211_M_HOSTAP)
   1732  1.60.4.1     skrll 		ieee80211_beacon_notify(ic, IEEE80211_BEACON_ERP);
   1733  1.60.4.1     skrll }
   1734  1.60.4.1     skrll 
   1735      1.39    dyoung /*
   1736      1.39    dyoung  * Handle a station joining an 11g network.
   1737      1.39    dyoung  */
   1738      1.39    dyoung static void
   1739      1.39    dyoung ieee80211_node_join_11g(struct ieee80211com *ic, struct ieee80211_node *ni)
   1740      1.39    dyoung {
   1741       1.1    dyoung 
   1742  1.60.4.1     skrll 	IEEE80211_LOCK_ASSERT(ic);
   1743  1.60.4.1     skrll 
   1744      1.39    dyoung 	/*
   1745      1.39    dyoung 	 * Station isn't capable of short slot time.  Bump
   1746      1.39    dyoung 	 * the count of long slot time stations and disable
   1747      1.39    dyoung 	 * use of short slot time.  Note that the actual switch
   1748      1.39    dyoung 	 * over to long slot time use may not occur until the
   1749      1.39    dyoung 	 * next beacon transmission (per sec. 7.3.1.4 of 11g).
   1750      1.39    dyoung 	 */
   1751      1.39    dyoung 	if ((ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME) == 0) {
   1752      1.39    dyoung 		ic->ic_longslotsta++;
   1753  1.60.4.1     skrll 		IEEE80211_NOTE(ic, IEEE80211_MSG_ASSOC, ni,
   1754  1.60.4.1     skrll 		    "station needs long slot time, count %d",
   1755  1.60.4.1     skrll 		    ic->ic_longslotsta);
   1756      1.39    dyoung 		/* XXX vap's w/ conflicting needs won't work */
   1757  1.60.4.1     skrll 		if (!IEEE80211_IS_CHAN_108G(ic->ic_bsschan)) {
   1758  1.60.4.1     skrll 			/*
   1759  1.60.4.1     skrll 			 * Don't force slot time when switched to turbo
   1760  1.60.4.1     skrll 			 * mode as non-ERP stations won't be present; this
   1761  1.60.4.1     skrll 			 * need only be done when on the normal G channel.
   1762  1.60.4.1     skrll 			 */
   1763  1.60.4.1     skrll 			ieee80211_set_shortslottime(ic, 0);
   1764  1.60.4.1     skrll 		}
   1765      1.39    dyoung 	}
   1766      1.39    dyoung 	/*
   1767      1.39    dyoung 	 * If the new station is not an ERP station
   1768      1.39    dyoung 	 * then bump the counter and enable protection
   1769      1.39    dyoung 	 * if configured.
   1770      1.39    dyoung 	 */
   1771      1.39    dyoung 	if (!ieee80211_iserp_rateset(ic, &ni->ni_rates)) {
   1772      1.39    dyoung 		ic->ic_nonerpsta++;
   1773  1.60.4.1     skrll 		IEEE80211_NOTE(ic, IEEE80211_MSG_ASSOC, ni,
   1774  1.60.4.1     skrll 		    "station is !ERP, %d non-ERP stations associated",
   1775  1.60.4.1     skrll 		    ic->ic_nonerpsta);
   1776      1.39    dyoung 		/*
   1777      1.39    dyoung 		 * If station does not support short preamble
   1778      1.39    dyoung 		 * then we must enable use of Barker preamble.
   1779      1.39    dyoung 		 */
   1780      1.39    dyoung 		if ((ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE) == 0) {
   1781  1.60.4.1     skrll 			IEEE80211_NOTE(ic, IEEE80211_MSG_ASSOC, ni,
   1782  1.60.4.1     skrll 			    "%s", "station needs long preamble");
   1783      1.39    dyoung 			ic->ic_flags |= IEEE80211_F_USEBARKER;
   1784      1.39    dyoung 			ic->ic_flags &= ~IEEE80211_F_SHPREAMBLE;
   1785      1.39    dyoung 		}
   1786  1.60.4.1     skrll 		/*
   1787  1.60.4.1     skrll 		 * If protection is configured, enable it.
   1788  1.60.4.1     skrll 		 */
   1789  1.60.4.1     skrll 		if (ic->ic_protmode != IEEE80211_PROT_NONE &&
   1790  1.60.4.1     skrll 		    ic->ic_nonerpsta == 1 &&
   1791  1.60.4.1     skrll 		    (ic->ic_flags_ext & IEEE80211_FEXT_NONERP_PR) == 0) {
   1792  1.60.4.1     skrll 			IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
   1793  1.60.4.1     skrll 			    "%s: enable use of protection\n", __func__);
   1794  1.60.4.1     skrll 			ic->ic_flags |= IEEE80211_F_USEPROT;
   1795  1.60.4.1     skrll 			ieee80211_notify_erp(ic);
   1796  1.60.4.1     skrll 		}
   1797      1.39    dyoung 	} else
   1798      1.39    dyoung 		ni->ni_flags |= IEEE80211_NODE_ERP;
   1799       1.1    dyoung }
   1800      1.22   mycroft 
   1801      1.22   mycroft void
   1802      1.22   mycroft ieee80211_node_join(struct ieee80211com *ic, struct ieee80211_node *ni, int resp)
   1803      1.22   mycroft {
   1804      1.22   mycroft 	int newassoc;
   1805      1.22   mycroft 
   1806      1.22   mycroft 	if (ni->ni_associd == 0) {
   1807  1.60.4.1     skrll 		uint16_t aid;
   1808      1.22   mycroft 
   1809  1.60.4.1     skrll 		IEEE80211_LOCK(ic);
   1810      1.22   mycroft 		/*
   1811      1.39    dyoung 		 * It would be good to search the bitmap
   1812      1.22   mycroft 		 * more efficiently, but this will do for now.
   1813      1.22   mycroft 		 */
   1814      1.22   mycroft 		for (aid = 1; aid < ic->ic_max_aid; aid++) {
   1815      1.22   mycroft 			if (!IEEE80211_AID_ISSET(aid,
   1816      1.22   mycroft 			    ic->ic_aid_bitmap))
   1817      1.22   mycroft 				break;
   1818      1.22   mycroft 		}
   1819      1.22   mycroft 		if (aid >= ic->ic_max_aid) {
   1820  1.60.4.1     skrll 			IEEE80211_UNLOCK(ic);
   1821      1.22   mycroft 			IEEE80211_SEND_MGMT(ic, ni, resp,
   1822      1.22   mycroft 			    IEEE80211_REASON_ASSOC_TOOMANY);
   1823      1.22   mycroft 			ieee80211_node_leave(ic, ni);
   1824      1.22   mycroft 			return;
   1825      1.22   mycroft 		}
   1826      1.22   mycroft 		ni->ni_associd = aid | 0xc000;
   1827  1.60.4.1     skrll 		ni->ni_jointime = time_uptime;
   1828      1.22   mycroft 		IEEE80211_AID_SET(ni->ni_associd, ic->ic_aid_bitmap);
   1829      1.39    dyoung 		ic->ic_sta_assoc++;
   1830  1.60.4.1     skrll 
   1831  1.60.4.1     skrll 		if (IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
   1832  1.60.4.1     skrll 			ieee80211_ht_node_join(ni);
   1833  1.60.4.1     skrll 		if (IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan) &&
   1834  1.60.4.1     skrll 		    IEEE80211_IS_CHAN_FULL(ic->ic_bsschan))
   1835      1.39    dyoung 			ieee80211_node_join_11g(ic, ni);
   1836  1.60.4.1     skrll 		IEEE80211_UNLOCK(ic);
   1837  1.60.4.1     skrll 
   1838  1.60.4.1     skrll 		newassoc = 1;
   1839      1.22   mycroft 	} else
   1840      1.22   mycroft 		newassoc = 0;
   1841      1.22   mycroft 
   1842  1.60.4.1     skrll 	IEEE80211_NOTE(ic, IEEE80211_MSG_ASSOC | IEEE80211_MSG_DEBUG, ni,
   1843  1.60.4.1     skrll 	    "station associated at aid %d: %s preamble, %s slot time%s%s%s%s%s%s",
   1844      1.39    dyoung 	    IEEE80211_NODE_AID(ni),
   1845      1.39    dyoung 	    ic->ic_flags & IEEE80211_F_SHPREAMBLE ? "short" : "long",
   1846      1.39    dyoung 	    ic->ic_flags & IEEE80211_F_SHSLOT ? "short" : "long",
   1847      1.39    dyoung 	    ic->ic_flags & IEEE80211_F_USEPROT ? ", protection" : "",
   1848  1.60.4.1     skrll 	    ni->ni_flags & IEEE80211_NODE_QOS ? ", QoS" : "",
   1849  1.60.4.1     skrll 	    ni->ni_flags & IEEE80211_NODE_HT ?
   1850  1.60.4.1     skrll 		(ni->ni_chw == 20 ? ", HT20" : ", HT40") : "",
   1851  1.60.4.1     skrll 	    ni->ni_flags & IEEE80211_NODE_AMPDU ? " (+AMPDU)" : "",
   1852  1.60.4.1     skrll 	    IEEE80211_ATH_CAP(ic, ni, IEEE80211_NODE_FF) ?
   1853  1.60.4.1     skrll 		", fast-frames" : "",
   1854  1.60.4.1     skrll 	    IEEE80211_ATH_CAP(ic, ni, IEEE80211_NODE_TURBOP) ?
   1855  1.60.4.1     skrll 		", turbo" : ""
   1856      1.39    dyoung 	);
   1857      1.22   mycroft 
   1858      1.22   mycroft 	/* give driver a chance to setup state like ni_txrate */
   1859      1.39    dyoung 	if (ic->ic_newassoc != NULL)
   1860      1.45     skrll 		ic->ic_newassoc(ni, newassoc);
   1861      1.22   mycroft 	IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_SUCCESS);
   1862      1.39    dyoung 	/* tell the authenticator about new station */
   1863      1.39    dyoung 	if (ic->ic_auth->ia_node_join != NULL)
   1864      1.39    dyoung 		ic->ic_auth->ia_node_join(ic, ni);
   1865  1.60.4.1     skrll 	ieee80211_notify_node_join(ic, ni,
   1866  1.60.4.1     skrll 	    resp == IEEE80211_FC0_SUBTYPE_ASSOC_RESP);
   1867  1.60.4.1     skrll }
   1868  1.60.4.1     skrll 
   1869  1.60.4.1     skrll static void
   1870  1.60.4.1     skrll disable_protection(struct ieee80211com *ic)
   1871  1.60.4.1     skrll {
   1872  1.60.4.1     skrll 	IASSERT(ic->ic_nonerpsta == 0 &&
   1873  1.60.4.1     skrll 	    (ic->ic_flags_ext & IEEE80211_FEXT_NONERP_PR) == 0,
   1874  1.60.4.1     skrll 	   ("%d non ERP stations, flags 0x%x", ic->ic_nonerpsta,
   1875  1.60.4.1     skrll 	   ic->ic_flags_ext));
   1876  1.60.4.1     skrll 
   1877  1.60.4.1     skrll 	ic->ic_flags &= ~IEEE80211_F_USEPROT;
   1878  1.60.4.1     skrll 	/* XXX verify mode? */
   1879  1.60.4.1     skrll 	if (ic->ic_caps & IEEE80211_C_SHPREAMBLE) {
   1880  1.60.4.1     skrll 		ic->ic_flags |= IEEE80211_F_SHPREAMBLE;
   1881  1.60.4.1     skrll 		ic->ic_flags &= ~IEEE80211_F_USEBARKER;
   1882  1.60.4.1     skrll 	}
   1883  1.60.4.1     skrll 	ieee80211_notify_erp(ic);
   1884      1.39    dyoung }
   1885      1.39    dyoung 
   1886      1.39    dyoung /*
   1887      1.39    dyoung  * Handle a station leaving an 11g network.
   1888      1.39    dyoung  */
   1889      1.39    dyoung static void
   1890      1.39    dyoung ieee80211_node_leave_11g(struct ieee80211com *ic, struct ieee80211_node *ni)
   1891      1.39    dyoung {
   1892      1.39    dyoung 
   1893  1.60.4.1     skrll 	IEEE80211_LOCK_ASSERT(ic);
   1894  1.60.4.1     skrll 
   1895  1.60.4.1     skrll 	IASSERT(IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan),
   1896  1.60.4.1     skrll 	     ("not in 11g, bss %u:0x%x, curmode %u", ic->ic_bsschan->ic_freq,
   1897  1.60.4.1     skrll 	      ic->ic_bsschan->ic_flags, ic->ic_curmode));
   1898      1.39    dyoung 
   1899      1.39    dyoung 	/*
   1900      1.39    dyoung 	 * If a long slot station do the slot time bookkeeping.
   1901      1.39    dyoung 	 */
   1902      1.39    dyoung 	if ((ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME) == 0) {
   1903      1.39    dyoung 		IASSERT(ic->ic_longslotsta > 0,
   1904      1.39    dyoung 		    ("bogus long slot station count %d", ic->ic_longslotsta));
   1905      1.39    dyoung 		ic->ic_longslotsta--;
   1906  1.60.4.1     skrll 		IEEE80211_NOTE(ic, IEEE80211_MSG_ASSOC, ni,
   1907  1.60.4.1     skrll 		    "long slot time station leaves, count now %d",
   1908  1.60.4.1     skrll 		    ic->ic_longslotsta);
   1909      1.39    dyoung 		if (ic->ic_longslotsta == 0) {
   1910      1.39    dyoung 			/*
   1911      1.39    dyoung 			 * Re-enable use of short slot time if supported
   1912      1.39    dyoung 			 * and not operating in IBSS mode (per spec).
   1913      1.39    dyoung 			 */
   1914      1.39    dyoung 			if ((ic->ic_caps & IEEE80211_C_SHSLOT) &&
   1915      1.39    dyoung 			    ic->ic_opmode != IEEE80211_M_IBSS) {
   1916      1.39    dyoung 				IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
   1917      1.39    dyoung 				    "%s: re-enable use of short slot time\n",
   1918      1.39    dyoung 				    __func__);
   1919      1.39    dyoung 				ieee80211_set_shortslottime(ic, 1);
   1920      1.39    dyoung 			}
   1921      1.39    dyoung 		}
   1922      1.39    dyoung 	}
   1923      1.39    dyoung 	/*
   1924      1.39    dyoung 	 * If a non-ERP station do the protection-related bookkeeping.
   1925      1.39    dyoung 	 */
   1926      1.39    dyoung 	if ((ni->ni_flags & IEEE80211_NODE_ERP) == 0) {
   1927      1.39    dyoung 		IASSERT(ic->ic_nonerpsta > 0,
   1928      1.39    dyoung 		    ("bogus non-ERP station count %d", ic->ic_nonerpsta));
   1929      1.39    dyoung 		ic->ic_nonerpsta--;
   1930  1.60.4.1     skrll 		IEEE80211_NOTE(ic, IEEE80211_MSG_ASSOC, ni,
   1931  1.60.4.1     skrll 		    "non-ERP station leaves, count now %d%s", ic->ic_nonerpsta,
   1932  1.60.4.1     skrll 		    (ic->ic_flags_ext & IEEE80211_FEXT_NONERP_PR) ?
   1933  1.60.4.1     skrll 			" (non-ERP sta present)" : "");
   1934  1.60.4.1     skrll 		if (ic->ic_nonerpsta == 0 &&
   1935  1.60.4.1     skrll 		    (ic->ic_flags_ext & IEEE80211_FEXT_NONERP_PR) == 0) {
   1936      1.39    dyoung 			IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
   1937      1.39    dyoung 				"%s: disable use of protection\n", __func__);
   1938  1.60.4.1     skrll 			disable_protection(ic);
   1939      1.39    dyoung 		}
   1940      1.39    dyoung 	}
   1941      1.22   mycroft }
   1942      1.22   mycroft 
   1943      1.22   mycroft /*
   1944  1.60.4.1     skrll  * Time out presence of an overlapping bss with non-ERP
   1945  1.60.4.1     skrll  * stations.  When operating in hostap mode we listen for
   1946  1.60.4.1     skrll  * beacons from other stations and if we identify a non-ERP
   1947  1.60.4.1     skrll  * station is present we enable protection.  To identify
   1948  1.60.4.1     skrll  * when all non-ERP stations are gone we time out this
   1949  1.60.4.1     skrll  * condition.
   1950  1.60.4.1     skrll  */
   1951  1.60.4.1     skrll static void
   1952  1.60.4.1     skrll ieee80211_erp_timeout(struct ieee80211com *ic)
   1953  1.60.4.1     skrll {
   1954  1.60.4.1     skrll 
   1955  1.60.4.1     skrll 	IEEE80211_LOCK_ASSERT(ic);
   1956  1.60.4.1     skrll 
   1957  1.60.4.1     skrll 	if ((ic->ic_flags_ext & IEEE80211_FEXT_NONERP_PR) &&
   1958  1.60.4.1     skrll 	    time_after(ticks, ic->ic_lastnonerp + IEEE80211_NONERP_PRESENT_AGE)) {
   1959  1.60.4.1     skrll 		IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC,
   1960  1.60.4.1     skrll 		    "%s\n", "age out non-ERP sta present on channel");
   1961  1.60.4.1     skrll 		ic->ic_flags_ext &= ~IEEE80211_FEXT_NONERP_PR;
   1962  1.60.4.1     skrll 		if (ic->ic_nonerpsta == 0)
   1963  1.60.4.1     skrll 			disable_protection(ic);
   1964  1.60.4.1     skrll 	}
   1965  1.60.4.1     skrll }
   1966  1.60.4.1     skrll 
   1967  1.60.4.1     skrll /*
   1968      1.26    dyoung  * Handle bookkeeping for station deauthentication/disassociation
   1969      1.26    dyoung  * when operating as an ap.
   1970      1.22   mycroft  */
   1971      1.22   mycroft void
   1972      1.22   mycroft ieee80211_node_leave(struct ieee80211com *ic, struct ieee80211_node *ni)
   1973      1.22   mycroft {
   1974      1.39    dyoung 	struct ieee80211_node_table *nt = ni->ni_table;
   1975      1.39    dyoung 
   1976  1.60.4.1     skrll 	IEEE80211_NOTE(ic, IEEE80211_MSG_ASSOC | IEEE80211_MSG_DEBUG, ni,
   1977  1.60.4.1     skrll 	    "station with aid %d leaves", IEEE80211_NODE_AID(ni));
   1978  1.60.4.1     skrll 
   1979  1.60.4.1     skrll 	IASSERT(ic->ic_opmode != IEEE80211_M_STA,
   1980      1.39    dyoung 		("unexpected operating mode %u", ic->ic_opmode));
   1981      1.22   mycroft 	/*
   1982      1.22   mycroft 	 * If node wasn't previously associated all
   1983      1.22   mycroft 	 * we need to do is reclaim the reference.
   1984      1.22   mycroft 	 */
   1985      1.39    dyoung 	/* XXX ibss mode bypasses 11g and notification */
   1986      1.22   mycroft 	if (ni->ni_associd == 0)
   1987      1.39    dyoung 		goto done;
   1988      1.39    dyoung 	/*
   1989      1.39    dyoung 	 * Tell the authenticator the station is leaving.
   1990      1.39    dyoung 	 * Note that we must do this before yanking the
   1991      1.39    dyoung 	 * association id as the authenticator uses the
   1992      1.39    dyoung 	 * associd to locate it's state block.
   1993      1.39    dyoung 	 */
   1994      1.39    dyoung 	if (ic->ic_auth->ia_node_leave != NULL)
   1995      1.39    dyoung 		ic->ic_auth->ia_node_leave(ic, ni);
   1996  1.60.4.1     skrll 
   1997  1.60.4.1     skrll 	IEEE80211_LOCK(ic);
   1998      1.22   mycroft 	IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap);
   1999      1.22   mycroft 	ni->ni_associd = 0;
   2000      1.39    dyoung 	ic->ic_sta_assoc--;
   2001      1.39    dyoung 
   2002  1.60.4.1     skrll 	if (IEEE80211_IS_CHAN_HT(ic->ic_bsschan))
   2003  1.60.4.1     skrll 		ieee80211_ht_node_leave(ni);
   2004  1.60.4.1     skrll 	if (IEEE80211_IS_CHAN_ANYG(ic->ic_bsschan) &&
   2005  1.60.4.1     skrll 	    IEEE80211_IS_CHAN_FULL(ic->ic_bsschan))
   2006      1.39    dyoung 		ieee80211_node_leave_11g(ic, ni);
   2007  1.60.4.1     skrll 	IEEE80211_UNLOCK(ic);
   2008      1.39    dyoung 	/*
   2009      1.39    dyoung 	 * Cleanup station state.  In particular clear various
   2010      1.39    dyoung 	 * state that might otherwise be reused if the node
   2011      1.39    dyoung 	 * is reused before the reference count goes to zero
   2012      1.39    dyoung 	 * (and memory is reclaimed).
   2013      1.39    dyoung 	 */
   2014      1.39    dyoung 	ieee80211_sta_leave(ic, ni);
   2015      1.39    dyoung done:
   2016      1.39    dyoung 	/*
   2017      1.39    dyoung 	 * Remove the node from any table it's recorded in and
   2018      1.39    dyoung 	 * drop the caller's reference.  Removal from the table
   2019      1.39    dyoung 	 * is important to insure the node is not reprocessed
   2020      1.39    dyoung 	 * for inactivity.
   2021      1.39    dyoung 	 */
   2022      1.39    dyoung 	if (nt != NULL) {
   2023      1.39    dyoung 		IEEE80211_NODE_LOCK(nt);
   2024      1.39    dyoung 		node_reclaim(nt, ni);
   2025      1.39    dyoung 		IEEE80211_NODE_UNLOCK(nt);
   2026      1.39    dyoung 	} else
   2027      1.39    dyoung 		ieee80211_free_node(ni);
   2028      1.39    dyoung }
   2029      1.39    dyoung 
   2030  1.60.4.1     skrll int8_t
   2031      1.39    dyoung ieee80211_getrssi(struct ieee80211com *ic)
   2032      1.39    dyoung {
   2033      1.39    dyoung #define	NZ(x)	((x) == 0 ? 1 : (x))
   2034      1.39    dyoung 	struct ieee80211_node_table *nt = &ic->ic_sta;
   2035  1.60.4.1     skrll 	int rssi_samples;
   2036  1.60.4.1     skrll 	int32_t rssi_total;
   2037      1.39    dyoung 	struct ieee80211_node *ni;
   2038      1.39    dyoung 
   2039      1.39    dyoung 	rssi_total = 0;
   2040      1.39    dyoung 	rssi_samples = 0;
   2041      1.39    dyoung 	switch (ic->ic_opmode) {
   2042      1.39    dyoung 	case IEEE80211_M_IBSS:		/* average of all ibss neighbors */
   2043      1.39    dyoung 	case IEEE80211_M_AHDEMO:	/* average of all neighbors */
   2044      1.39    dyoung 	case IEEE80211_M_HOSTAP:	/* average of all associated stations */
   2045      1.40    dyoung #ifndef IEEE80211_NO_HOSTAP
   2046      1.39    dyoung 		/* XXX locking */
   2047      1.39    dyoung 		TAILQ_FOREACH(ni, &nt->nt_node, ni_list)
   2048  1.60.4.1     skrll 			if (ic->ic_opmode == IEEE80211_M_HOSTAP ||
   2049  1.60.4.1     skrll 			    (ni->ni_capinfo & IEEE80211_CAPINFO_IBSS)) {
   2050  1.60.4.1     skrll 				int8_t rssi = ic->ic_node_getrssi(ni);
   2051  1.60.4.1     skrll 				if (rssi != 0) {
   2052  1.60.4.1     skrll 					rssi_samples++;
   2053  1.60.4.1     skrll 					rssi_total += rssi;
   2054  1.60.4.1     skrll 				}
   2055      1.39    dyoung 			}
   2056      1.40    dyoung #endif /* !IEEE80211_NO_HOSTAP */
   2057      1.39    dyoung 		break;
   2058      1.39    dyoung 	case IEEE80211_M_MONITOR:	/* XXX */
   2059      1.39    dyoung 	case IEEE80211_M_STA:		/* use stats from associated ap */
   2060      1.39    dyoung 	default:
   2061      1.39    dyoung 		if (ic->ic_bss != NULL)
   2062      1.39    dyoung 			rssi_total = ic->ic_node_getrssi(ic->ic_bss);
   2063      1.39    dyoung 		rssi_samples = 1;
   2064      1.39    dyoung 		break;
   2065      1.39    dyoung 	}
   2066      1.39    dyoung 	return rssi_total / NZ(rssi_samples);
   2067      1.39    dyoung #undef NZ
   2068      1.39    dyoung }
   2069      1.39    dyoung 
   2070  1.60.4.1     skrll void
   2071  1.60.4.1     skrll ieee80211_getsignal(struct ieee80211com *ic, int8_t *rssi, int8_t *noise)
   2072      1.39    dyoung {
   2073      1.39    dyoung 
   2074  1.60.4.1     skrll 	if (ic->ic_bss == NULL)		/* NB: shouldn't happen */
   2075  1.60.4.1     skrll 		return;
   2076  1.60.4.1     skrll 	ic->ic_node_getsignal(ic->ic_bss, rssi, noise);
   2077  1.60.4.1     skrll 	/* for non-station mode return avg'd rssi accounting */
   2078  1.60.4.1     skrll 	if (ic->ic_opmode != IEEE80211_M_STA)
   2079  1.60.4.1     skrll 		*rssi = ieee80211_getrssi(ic);
   2080      1.39    dyoung }
   2081      1.39    dyoung 
   2082      1.39    dyoung /*
   2083      1.39    dyoung  * Node table support.
   2084      1.39    dyoung  */
   2085      1.39    dyoung 
   2086      1.39    dyoung static void
   2087      1.39    dyoung ieee80211_node_table_init(struct ieee80211com *ic,
   2088      1.39    dyoung 	struct ieee80211_node_table *nt,
   2089  1.60.4.1     skrll 	const char *name, int inact, int keyixmax)
   2090      1.39    dyoung {
   2091      1.39    dyoung 
   2092      1.39    dyoung 	IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
   2093      1.39    dyoung 		"%s %s table, inact %u\n", __func__, name, inact);
   2094      1.39    dyoung 
   2095      1.39    dyoung 	nt->nt_ic = ic;
   2096      1.39    dyoung 	/* XXX need unit */
   2097      1.39    dyoung 	IEEE80211_NODE_LOCK_INIT(nt, ic->ic_ifp->if_xname);
   2098      1.39    dyoung 	IEEE80211_SCAN_LOCK_INIT(nt, ic->ic_ifp->if_xname);
   2099      1.39    dyoung 	TAILQ_INIT(&nt->nt_node);
   2100      1.39    dyoung 	nt->nt_name = name;
   2101      1.39    dyoung 	nt->nt_scangen = 1;
   2102      1.39    dyoung 	nt->nt_inact_init = inact;
   2103      1.45     skrll 	nt->nt_keyixmax = keyixmax;
   2104      1.45     skrll 	if (nt->nt_keyixmax > 0) {
   2105      1.54  christos 		nt->nt_keyixmap = malloc(keyixmax *
   2106      1.54  christos 		    sizeof(struct ieee80211_node *), M_80211_NODE,
   2107      1.54  christos 		    M_NOWAIT | M_ZERO);
   2108      1.45     skrll 		if (nt->nt_keyixmap == NULL)
   2109      1.45     skrll 			if_printf(ic->ic_ifp,
   2110      1.45     skrll 			    "Cannot allocate key index map with %u entries\n",
   2111      1.45     skrll 			    keyixmax);
   2112      1.45     skrll 	} else
   2113      1.45     skrll 		nt->nt_keyixmap = NULL;
   2114      1.39    dyoung }
   2115      1.39    dyoung 
   2116  1.60.4.1     skrll static void
   2117      1.39    dyoung ieee80211_node_table_reset(struct ieee80211_node_table *nt)
   2118      1.39    dyoung {
   2119      1.39    dyoung 
   2120      1.39    dyoung 	IEEE80211_DPRINTF(nt->nt_ic, IEEE80211_MSG_NODE,
   2121      1.39    dyoung 		"%s %s table\n", __func__, nt->nt_name);
   2122      1.39    dyoung 
   2123      1.39    dyoung 	IEEE80211_NODE_LOCK(nt);
   2124      1.39    dyoung 	ieee80211_free_allnodes_locked(nt);
   2125      1.39    dyoung 	IEEE80211_NODE_UNLOCK(nt);
   2126      1.39    dyoung }
   2127      1.39    dyoung 
   2128      1.39    dyoung static void
   2129      1.39    dyoung ieee80211_node_table_cleanup(struct ieee80211_node_table *nt)
   2130      1.39    dyoung {
   2131      1.39    dyoung 
   2132      1.39    dyoung 	IEEE80211_DPRINTF(nt->nt_ic, IEEE80211_MSG_NODE,
   2133      1.39    dyoung 		"%s %s table\n", __func__, nt->nt_name);
   2134      1.39    dyoung 
   2135      1.45     skrll 	IEEE80211_NODE_LOCK(nt);
   2136      1.39    dyoung 	ieee80211_free_allnodes_locked(nt);
   2137      1.60    dyoung 	IEEE80211_NODE_UNLOCK(nt);
   2138      1.45     skrll 	if (nt->nt_keyixmap != NULL) {
   2139      1.45     skrll 		/* XXX verify all entries are NULL */
   2140      1.45     skrll 		int i;
   2141      1.45     skrll 		for (i = 0; i < nt->nt_keyixmax; i++)
   2142      1.45     skrll 			if (nt->nt_keyixmap[i] != NULL)
   2143      1.45     skrll 				printf("%s: %s[%u] still active\n", __func__,
   2144      1.45     skrll 					nt->nt_name, i);
   2145      1.45     skrll 		FREE(nt->nt_keyixmap, M_80211_NODE);
   2146      1.45     skrll 		nt->nt_keyixmap = NULL;
   2147      1.45     skrll 	}
   2148      1.39    dyoung 	IEEE80211_SCAN_LOCK_DESTROY(nt);
   2149      1.39    dyoung 	IEEE80211_NODE_LOCK_DESTROY(nt);
   2150      1.22   mycroft }
   2151