Home | History | Annotate | Line # | Download | only in net80211
ieee80211_node.c revision 1.37.4.1
      1  1.37.4.1     yamt /*	$NetBSD: ieee80211_node.c,v 1.37.4.1 2005/03/19 08:36:35 yamt Exp $	*/
      2       1.1   dyoung /*-
      3       1.1   dyoung  * Copyright (c) 2001 Atsushi Onoe
      4      1.22  mycroft  * Copyright (c) 2002-2004 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  * 3. The name of the author may not be used to endorse or promote products
     16       1.1   dyoung  *    derived from this software without specific prior written permission.
     17       1.1   dyoung  *
     18       1.1   dyoung  * Alternatively, this software may be distributed under the terms of the
     19       1.1   dyoung  * GNU General Public License ("GPL") version 2 as published by the Free
     20       1.1   dyoung  * Software Foundation.
     21       1.1   dyoung  *
     22       1.1   dyoung  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     23       1.1   dyoung  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     24       1.1   dyoung  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     25       1.1   dyoung  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     26       1.1   dyoung  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     27       1.1   dyoung  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28       1.1   dyoung  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29       1.1   dyoung  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30       1.1   dyoung  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     31       1.1   dyoung  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32       1.1   dyoung  */
     33       1.1   dyoung 
     34       1.1   dyoung #include <sys/cdefs.h>
     35       1.3   dyoung #ifdef __FreeBSD__
     36      1.11   dyoung __FBSDID("$FreeBSD: src/sys/net80211/ieee80211_node.c,v 1.22 2004/04/05 04:15:55 sam Exp $");
     37       1.3   dyoung #else
     38  1.37.4.1     yamt __KERNEL_RCSID(0, "$NetBSD: ieee80211_node.c,v 1.37.4.1 2005/03/19 08:36:35 yamt Exp $");
     39       1.3   dyoung #endif
     40       1.1   dyoung 
     41       1.1   dyoung #include "opt_inet.h"
     42       1.1   dyoung 
     43       1.1   dyoung #include <sys/param.h>
     44  1.37.4.1     yamt #include <sys/systm.h>
     45  1.37.4.1     yamt #include <sys/mbuf.h>
     46       1.1   dyoung #include <sys/malloc.h>
     47       1.1   dyoung #include <sys/kernel.h>
     48       1.1   dyoung #include <sys/socket.h>
     49       1.1   dyoung #include <sys/sockio.h>
     50       1.1   dyoung #include <sys/endian.h>
     51       1.1   dyoung #include <sys/errno.h>
     52       1.4   dyoung #ifdef __FreeBSD__
     53       1.1   dyoung #include <sys/bus.h>
     54       1.4   dyoung #endif
     55       1.1   dyoung #include <sys/proc.h>
     56       1.1   dyoung #include <sys/sysctl.h>
     57       1.1   dyoung 
     58       1.2   dyoung #ifdef __FreeBSD__
     59       1.1   dyoung #include <machine/atomic.h>
     60       1.2   dyoung #endif
     61  1.37.4.1     yamt 
     62       1.1   dyoung #include <net/if.h>
     63       1.1   dyoung #include <net/if_dl.h>
     64       1.1   dyoung #include <net/if_media.h>
     65       1.1   dyoung #include <net/if_arp.h>
     66       1.2   dyoung #ifdef __FreeBSD__
     67       1.1   dyoung #include <net/ethernet.h>
     68       1.4   dyoung #else
     69       1.4   dyoung #include <net/if_ether.h>
     70       1.2   dyoung #endif
     71       1.1   dyoung #include <net/if_llc.h>
     72       1.1   dyoung 
     73       1.1   dyoung #include <net80211/ieee80211_var.h>
     74       1.4   dyoung #include <net80211/ieee80211_compat.h>
     75       1.1   dyoung 
     76       1.1   dyoung #include <net/bpf.h>
     77       1.1   dyoung 
     78       1.1   dyoung #ifdef INET
     79  1.37.4.1     yamt #include <netinet/in.h>
     80       1.4   dyoung #ifdef __FreeBSD__
     81       1.1   dyoung #include <netinet/if_ether.h>
     82       1.4   dyoung #else
     83       1.4   dyoung #include <net/if_ether.h>
     84       1.4   dyoung #endif
     85       1.1   dyoung #endif
     86       1.1   dyoung 
     87       1.1   dyoung static struct ieee80211_node *ieee80211_node_alloc(struct ieee80211com *);
     88       1.1   dyoung static void ieee80211_node_free(struct ieee80211com *, struct ieee80211_node *);
     89       1.1   dyoung static void ieee80211_node_copy(struct ieee80211com *,
     90       1.1   dyoung 		struct ieee80211_node *, const struct ieee80211_node *);
     91       1.9   dyoung static u_int8_t ieee80211_node_getrssi(struct ieee80211com *,
     92       1.9   dyoung 		struct ieee80211_node *);
     93       1.9   dyoung 
     94       1.1   dyoung static void ieee80211_setup_node(struct ieee80211com *ic,
     95       1.1   dyoung 		struct ieee80211_node *ni, u_int8_t *macaddr);
     96      1.33   dyoung static void ieee80211_free_node(struct ieee80211com *,
     97       1.1   dyoung 		struct ieee80211_node *);
     98       1.1   dyoung 
     99      1.11   dyoung MALLOC_DEFINE(M_80211_NODE, "80211node", "802.11 node state");
    100       1.9   dyoung 
    101       1.1   dyoung void
    102      1.23  mycroft ieee80211_node_attach(struct ieee80211com *ic)
    103       1.1   dyoung {
    104       1.1   dyoung 
    105       1.1   dyoung 	/* XXX need unit */
    106      1.23  mycroft 	IEEE80211_NODE_LOCK_INIT(ic, ic->ic_ifp->if_xname);
    107       1.1   dyoung 	TAILQ_INIT(&ic->ic_node);
    108       1.1   dyoung 	ic->ic_node_alloc = ieee80211_node_alloc;
    109       1.1   dyoung 	ic->ic_node_free = ieee80211_node_free;
    110       1.1   dyoung 	ic->ic_node_copy = ieee80211_node_copy;
    111       1.9   dyoung 	ic->ic_node_getrssi = ieee80211_node_getrssi;
    112       1.9   dyoung 	ic->ic_scangen = 1;
    113      1.33   dyoung 	ic->ic_max_nnodes = ieee80211_cache_size;
    114      1.22  mycroft 
    115      1.22  mycroft 	if (ic->ic_max_aid == 0)
    116      1.22  mycroft 		ic->ic_max_aid = IEEE80211_AID_DEF;
    117      1.22  mycroft 	else if (ic->ic_max_aid > IEEE80211_AID_MAX)
    118      1.22  mycroft 		ic->ic_max_aid = IEEE80211_AID_MAX;
    119      1.22  mycroft 	MALLOC(ic->ic_aid_bitmap, u_int32_t *,
    120      1.22  mycroft 		howmany(ic->ic_max_aid, 32) * sizeof(u_int32_t),
    121      1.22  mycroft 		M_DEVBUF, M_NOWAIT | M_ZERO);
    122      1.22  mycroft 	if (ic->ic_aid_bitmap == NULL) {
    123      1.22  mycroft 		/* XXX no way to recover */
    124      1.22  mycroft 		printf("%s: no memory for AID bitmap!\n", __func__);
    125      1.22  mycroft 		ic->ic_max_aid = 0;
    126      1.22  mycroft 	}
    127       1.1   dyoung }
    128       1.1   dyoung 
    129      1.33   dyoung static struct ieee80211_node *
    130      1.33   dyoung ieee80211_alloc_node_helper(struct ieee80211com *ic)
    131      1.33   dyoung {
    132      1.33   dyoung 	struct ieee80211_node *ni;
    133      1.33   dyoung 	if (ic->ic_nnodes >= ic->ic_max_nnodes)
    134      1.33   dyoung 		ieee80211_clean_nodes(ic);
    135      1.33   dyoung 	if (ic->ic_nnodes >= ic->ic_max_nnodes)
    136      1.33   dyoung 		return NULL;
    137      1.33   dyoung 	ni = (*ic->ic_node_alloc)(ic);
    138      1.33   dyoung 	if (ni != NULL)
    139      1.33   dyoung 		ic->ic_nnodes++;
    140      1.33   dyoung 	return ni;
    141      1.33   dyoung }
    142      1.33   dyoung 
    143       1.1   dyoung void
    144      1.23  mycroft ieee80211_node_lateattach(struct ieee80211com *ic)
    145       1.1   dyoung {
    146      1.11   dyoung 	struct ieee80211_node *ni;
    147       1.1   dyoung 
    148      1.33   dyoung 	ni = ieee80211_alloc_node_helper(ic);
    149      1.11   dyoung 	IASSERT(ni != NULL, ("unable to setup inital BSS node"));
    150      1.11   dyoung 	ni->ni_chan = IEEE80211_CHAN_ANYC;
    151      1.33   dyoung 	ic->ic_bss = ieee80211_ref_node(ni);
    152      1.11   dyoung 	ic->ic_txpower = IEEE80211_TXPOWER_MAX;
    153       1.1   dyoung }
    154       1.1   dyoung 
    155       1.1   dyoung void
    156      1.23  mycroft ieee80211_node_detach(struct ieee80211com *ic)
    157       1.1   dyoung {
    158       1.1   dyoung 
    159      1.23  mycroft 	if (ic->ic_bss != NULL) {
    160       1.1   dyoung 		(*ic->ic_node_free)(ic, ic->ic_bss);
    161      1.23  mycroft 		ic->ic_bss = NULL;
    162      1.23  mycroft 	}
    163       1.1   dyoung 	ieee80211_free_allnodes(ic);
    164       1.9   dyoung 	IEEE80211_NODE_LOCK_DESTROY(ic);
    165      1.22  mycroft         if (ic->ic_aid_bitmap != NULL)
    166      1.22  mycroft                 FREE(ic->ic_aid_bitmap, M_DEVBUF);
    167       1.1   dyoung }
    168       1.1   dyoung 
    169       1.1   dyoung /*
    170       1.1   dyoung  * AP scanning support.
    171       1.1   dyoung  */
    172       1.1   dyoung 
    173       1.1   dyoung /*
    174       1.1   dyoung  * Initialize the active channel set based on the set
    175       1.1   dyoung  * of available channels and the current PHY mode.
    176       1.1   dyoung  */
    177       1.1   dyoung static void
    178      1.23  mycroft ieee80211_reset_scan(struct ieee80211com *ic)
    179       1.1   dyoung {
    180       1.1   dyoung 
    181       1.1   dyoung 	memcpy(ic->ic_chan_scan, ic->ic_chan_active,
    182       1.1   dyoung 		sizeof(ic->ic_chan_active));
    183       1.1   dyoung 	/* NB: hack, setup so next_scan starts with the first channel */
    184       1.1   dyoung 	if (ic->ic_bss->ni_chan == IEEE80211_CHAN_ANYC)
    185       1.1   dyoung 		ic->ic_bss->ni_chan = &ic->ic_channels[IEEE80211_CHAN_MAX];
    186       1.1   dyoung }
    187       1.1   dyoung 
    188       1.1   dyoung /*
    189       1.1   dyoung  * Begin an active scan.
    190       1.1   dyoung  */
    191       1.1   dyoung void
    192      1.23  mycroft ieee80211_begin_scan(struct ieee80211com *ic)
    193       1.1   dyoung {
    194       1.1   dyoung 
    195       1.1   dyoung 	/*
    196       1.1   dyoung 	 * In all but hostap mode scanning starts off in
    197       1.1   dyoung 	 * an active mode before switching to passive.
    198       1.1   dyoung 	 */
    199       1.9   dyoung 	if (ic->ic_opmode != IEEE80211_M_HOSTAP) {
    200       1.1   dyoung 		ic->ic_flags |= IEEE80211_F_ASCAN;
    201       1.9   dyoung 		ic->ic_stats.is_scan_active++;
    202       1.9   dyoung 	} else
    203       1.9   dyoung 		ic->ic_stats.is_scan_passive++;
    204      1.20  mycroft 	IEEE80211_DPRINTF(ic, IEEE80211_MSG_SCAN, ("begin %s scan\n",
    205      1.20  mycroft 		(ic->ic_flags & IEEE80211_F_ASCAN) ?  "active" : "passive"));
    206       1.1   dyoung 	/*
    207       1.1   dyoung 	 * Clear scan state and flush any previously seen
    208       1.1   dyoung 	 * AP's.  Note that the latter assumes we don't act
    209       1.1   dyoung 	 * as both an AP and a station, otherwise we'll
    210       1.1   dyoung 	 * potentially flush state of stations associated
    211       1.1   dyoung 	 * with us.
    212       1.1   dyoung 	 */
    213      1.23  mycroft 	ieee80211_reset_scan(ic);
    214       1.1   dyoung 	ieee80211_free_allnodes(ic);
    215       1.1   dyoung 
    216       1.1   dyoung 	/* Scan the next channel. */
    217      1.23  mycroft 	ieee80211_next_scan(ic);
    218       1.1   dyoung }
    219       1.1   dyoung 
    220       1.1   dyoung /*
    221       1.1   dyoung  * Switch to the next channel marked for scanning.
    222       1.1   dyoung  */
    223       1.1   dyoung void
    224      1.23  mycroft ieee80211_next_scan(struct ieee80211com *ic)
    225       1.1   dyoung {
    226       1.1   dyoung 	struct ieee80211_channel *chan;
    227       1.1   dyoung 
    228       1.1   dyoung 	chan = ic->ic_bss->ni_chan;
    229       1.1   dyoung 	for (;;) {
    230       1.1   dyoung 		if (++chan > &ic->ic_channels[IEEE80211_CHAN_MAX])
    231       1.1   dyoung 			chan = &ic->ic_channels[0];
    232       1.1   dyoung 		if (isset(ic->ic_chan_scan, ieee80211_chan2ieee(ic, chan))) {
    233       1.1   dyoung 			/*
    234       1.1   dyoung 			 * Honor channels marked passive-only
    235       1.1   dyoung 			 * during an active scan.
    236       1.1   dyoung 			 */
    237       1.1   dyoung 			if ((ic->ic_flags & IEEE80211_F_ASCAN) == 0 ||
    238       1.1   dyoung 			    (chan->ic_flags & IEEE80211_CHAN_PASSIVE) == 0)
    239       1.1   dyoung 				break;
    240       1.1   dyoung 		}
    241       1.1   dyoung 		if (chan == ic->ic_bss->ni_chan) {
    242      1.23  mycroft 			ieee80211_end_scan(ic);
    243       1.1   dyoung 			return;
    244       1.1   dyoung 		}
    245       1.1   dyoung 	}
    246       1.1   dyoung 	clrbit(ic->ic_chan_scan, ieee80211_chan2ieee(ic, chan));
    247      1.18  mycroft 	IEEE80211_DPRINTF(ic, IEEE80211_MSG_SCAN,
    248      1.18  mycroft 		("%s: chan %d->%d\n", __func__,
    249      1.18  mycroft 		ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan),
    250      1.18  mycroft 		ieee80211_chan2ieee(ic, chan)));
    251       1.1   dyoung 	ic->ic_bss->ni_chan = chan;
    252       1.1   dyoung 	ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
    253       1.1   dyoung }
    254       1.1   dyoung 
    255       1.1   dyoung void
    256       1.1   dyoung ieee80211_create_ibss(struct ieee80211com* ic, struct ieee80211_channel *chan)
    257       1.1   dyoung {
    258       1.1   dyoung 	struct ieee80211_node *ni;
    259       1.1   dyoung 
    260       1.1   dyoung 	ni = ic->ic_bss;
    261       1.1   dyoung 	ic->ic_flags |= IEEE80211_F_SIBSS;
    262       1.1   dyoung 	ni->ni_chan = chan;
    263       1.1   dyoung 	ni->ni_rates = ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)];
    264       1.1   dyoung 	IEEE80211_ADDR_COPY(ni->ni_macaddr, ic->ic_myaddr);
    265       1.1   dyoung 	IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_myaddr);
    266      1.16   dyoung 	if (ic->ic_opmode == IEEE80211_M_IBSS) {
    267      1.16   dyoung 		if ((ic->ic_flags & IEEE80211_F_DESBSSID) != 0)
    268      1.16   dyoung 			IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_des_bssid);
    269      1.16   dyoung 		else
    270      1.16   dyoung 			ni->ni_bssid[0] |= 0x02;	/* local bit for IBSS */
    271      1.16   dyoung 	}
    272      1.37   dyoung 	if_printf(&ic->ic_if, "creating bss %s\n", ether_sprintf(ni->ni_bssid));
    273       1.1   dyoung 	ni->ni_esslen = ic->ic_des_esslen;
    274       1.1   dyoung 	memcpy(ni->ni_essid, ic->ic_des_essid, ni->ni_esslen);
    275       1.1   dyoung 	ni->ni_rssi = 0;
    276       1.1   dyoung 	ni->ni_rstamp = 0;
    277       1.1   dyoung 	memset(ni->ni_tstamp, 0, sizeof(ni->ni_tstamp));
    278       1.1   dyoung 	ni->ni_intval = ic->ic_lintval;
    279       1.1   dyoung 	ni->ni_capinfo = IEEE80211_CAPINFO_IBSS;
    280      1.21  mycroft 	if (ic->ic_flags & IEEE80211_F_PRIVACY)
    281       1.1   dyoung 		ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY;
    282       1.1   dyoung 	if (ic->ic_phytype == IEEE80211_T_FH) {
    283       1.1   dyoung 		ni->ni_fhdwell = 200;	/* XXX */
    284       1.1   dyoung 		ni->ni_fhindex = 1;
    285       1.1   dyoung 	}
    286       1.1   dyoung 	ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
    287       1.1   dyoung }
    288       1.1   dyoung 
    289       1.5   dyoung int
    290       1.5   dyoung ieee80211_match_bss(struct ieee80211com *ic, struct ieee80211_node *ni)
    291       1.5   dyoung {
    292       1.5   dyoung         u_int8_t rate;
    293       1.5   dyoung         int fail;
    294       1.5   dyoung 
    295       1.5   dyoung 	fail = 0;
    296       1.5   dyoung 	if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, ni->ni_chan)))
    297       1.5   dyoung 		fail |= 0x01;
    298       1.5   dyoung 	if (ic->ic_des_chan != IEEE80211_CHAN_ANYC &&
    299       1.5   dyoung 	    ni->ni_chan != ic->ic_des_chan)
    300       1.5   dyoung 		fail |= 0x01;
    301       1.5   dyoung 	if (ic->ic_opmode == IEEE80211_M_IBSS) {
    302       1.5   dyoung 		if ((ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) == 0)
    303       1.5   dyoung 			fail |= 0x02;
    304       1.5   dyoung 	} else {
    305       1.5   dyoung 		if ((ni->ni_capinfo & IEEE80211_CAPINFO_ESS) == 0)
    306       1.5   dyoung 			fail |= 0x02;
    307       1.5   dyoung 	}
    308      1.21  mycroft 	if (ic->ic_flags & IEEE80211_F_PRIVACY) {
    309       1.5   dyoung 		if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0)
    310       1.5   dyoung 			fail |= 0x04;
    311       1.5   dyoung 	} else {
    312      1.11   dyoung 		/* XXX does this mean privacy is supported or required? */
    313       1.5   dyoung 		if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY)
    314       1.5   dyoung 			fail |= 0x04;
    315       1.5   dyoung 	}
    316       1.5   dyoung 	rate = ieee80211_fix_rate(ic, ni, IEEE80211_F_DONEGO);
    317       1.5   dyoung 	if (rate & IEEE80211_RATE_BASIC)
    318       1.5   dyoung 		fail |= 0x08;
    319       1.5   dyoung 	if (ic->ic_des_esslen != 0 &&
    320       1.5   dyoung 	    (ni->ni_esslen != ic->ic_des_esslen ||
    321      1.11   dyoung 	     memcmp(ni->ni_essid, ic->ic_des_essid, ic->ic_des_esslen) != 0))
    322       1.5   dyoung 		fail |= 0x10;
    323       1.5   dyoung 	if ((ic->ic_flags & IEEE80211_F_DESBSSID) &&
    324       1.5   dyoung 	    !IEEE80211_ADDR_EQ(ic->ic_des_bssid, ni->ni_bssid))
    325       1.5   dyoung 		fail |= 0x20;
    326      1.11   dyoung #ifdef IEEE80211_DEBUG
    327      1.12   dyoung 	if (ic->ic_if.if_flags & IFF_DEBUG) {
    328       1.5   dyoung 		printf(" %c %s", fail ? '-' : '+',
    329       1.5   dyoung 		    ether_sprintf(ni->ni_macaddr));
    330       1.5   dyoung 		printf(" %s%c", ether_sprintf(ni->ni_bssid),
    331       1.5   dyoung 		    fail & 0x20 ? '!' : ' ');
    332       1.5   dyoung 		printf(" %3d%c", ieee80211_chan2ieee(ic, ni->ni_chan),
    333       1.5   dyoung 			fail & 0x01 ? '!' : ' ');
    334       1.5   dyoung 		printf(" %+4d", ni->ni_rssi);
    335       1.5   dyoung 		printf(" %2dM%c", (rate & IEEE80211_RATE_VAL) / 2,
    336       1.5   dyoung 		    fail & 0x08 ? '!' : ' ');
    337       1.5   dyoung 		printf(" %4s%c",
    338       1.5   dyoung 		    (ni->ni_capinfo & IEEE80211_CAPINFO_ESS) ? "ess" :
    339       1.5   dyoung 		    (ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) ? "ibss" :
    340       1.5   dyoung 		    "????",
    341       1.5   dyoung 		    fail & 0x02 ? '!' : ' ');
    342       1.5   dyoung 		printf(" %3s%c ",
    343       1.5   dyoung 		    (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) ?
    344       1.5   dyoung 		    "wep" : "no",
    345       1.5   dyoung 		    fail & 0x04 ? '!' : ' ');
    346       1.5   dyoung 		ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);
    347       1.5   dyoung 		printf("%s\n", fail & 0x10 ? "!" : "");
    348       1.5   dyoung 	}
    349      1.11   dyoung #endif
    350       1.5   dyoung 	return fail;
    351       1.5   dyoung }
    352       1.5   dyoung 
    353       1.1   dyoung /*
    354       1.1   dyoung  * Complete a scan of potential channels.
    355       1.1   dyoung  */
    356       1.1   dyoung void
    357      1.23  mycroft ieee80211_end_scan(struct ieee80211com *ic)
    358       1.1   dyoung {
    359       1.1   dyoung 	struct ieee80211_node *ni, *nextbs, *selbs;
    360       1.1   dyoung 	int i, fail;
    361       1.1   dyoung 
    362      1.23  mycroft 	IEEE80211_DPRINTF(ic, IEEE80211_MSG_SCAN, ("end %s scan\n",
    363      1.23  mycroft 		(ic->ic_flags & IEEE80211_F_ASCAN) ?  "active" : "passive"));
    364      1.23  mycroft 
    365       1.1   dyoung 	ic->ic_flags &= ~IEEE80211_F_ASCAN;
    366       1.1   dyoung 	ni = TAILQ_FIRST(&ic->ic_node);
    367       1.1   dyoung 
    368       1.1   dyoung 	if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
    369       1.1   dyoung 		/* XXX off stack? */
    370       1.1   dyoung 		u_char occupied[roundup(IEEE80211_CHAN_MAX, NBBY)];
    371       1.1   dyoung 		/*
    372       1.1   dyoung 		 * The passive scan to look for existing AP's completed,
    373       1.1   dyoung 		 * select a channel to camp on.  Identify the channels
    374       1.1   dyoung 		 * that already have one or more AP's and try to locate
    375       1.1   dyoung 		 * an unnoccupied one.  If that fails, pick a random
    376       1.1   dyoung 		 * channel from the active set.
    377       1.1   dyoung 		 */
    378       1.1   dyoung 		for (; ni != NULL; ni = nextbs) {
    379       1.1   dyoung 			nextbs = TAILQ_NEXT(ni, ni_list);
    380       1.1   dyoung 			setbit(occupied, ieee80211_chan2ieee(ic, ni->ni_chan));
    381       1.1   dyoung 		}
    382       1.1   dyoung 		for (i = 0; i < IEEE80211_CHAN_MAX; i++)
    383       1.1   dyoung 			if (isset(ic->ic_chan_active, i) && isclr(occupied, i))
    384       1.1   dyoung 				break;
    385       1.1   dyoung 		if (i == IEEE80211_CHAN_MAX) {
    386       1.1   dyoung 			fail = arc4random() & 3;	/* random 0-3 */
    387       1.1   dyoung 			for (i = 0; i < IEEE80211_CHAN_MAX; i++)
    388       1.1   dyoung 				if (isset(ic->ic_chan_active, i) && fail-- == 0)
    389       1.1   dyoung 					break;
    390       1.1   dyoung 		}
    391       1.1   dyoung 		ieee80211_create_ibss(ic, &ic->ic_channels[i]);
    392       1.1   dyoung 		return;
    393       1.1   dyoung 	}
    394       1.1   dyoung 	if (ni == NULL) {
    395      1.18  mycroft 		IEEE80211_DPRINTF(ic, IEEE80211_MSG_SCAN,
    396      1.18  mycroft 			("%s: no scan candidate\n", __func__));
    397       1.1   dyoung   notfound:
    398       1.1   dyoung 		if (ic->ic_opmode == IEEE80211_M_IBSS &&
    399       1.1   dyoung 		    (ic->ic_flags & IEEE80211_F_IBSSON) &&
    400       1.1   dyoung 		    ic->ic_des_esslen != 0) {
    401       1.1   dyoung 			ieee80211_create_ibss(ic, ic->ic_ibss_chan);
    402       1.1   dyoung 			return;
    403       1.1   dyoung 		}
    404       1.1   dyoung 		/*
    405       1.1   dyoung 		 * Reset the list of channels to scan and start again.
    406       1.1   dyoung 		 */
    407      1.23  mycroft 		ieee80211_reset_scan(ic);
    408      1.23  mycroft 		ieee80211_next_scan(ic);
    409       1.1   dyoung 		return;
    410       1.1   dyoung 	}
    411       1.1   dyoung 	selbs = NULL;
    412      1.20  mycroft 	IEEE80211_DPRINTF(ic, IEEE80211_MSG_SCAN,
    413      1.20  mycroft 		("\tmacaddr          bssid         chan  rssi rate flag  wep  essid\n"));
    414       1.1   dyoung 	for (; ni != NULL; ni = nextbs) {
    415       1.1   dyoung 		nextbs = TAILQ_NEXT(ni, ni_list);
    416       1.1   dyoung 		if (ni->ni_fails) {
    417       1.1   dyoung 			/*
    418       1.1   dyoung 			 * The configuration of the access points may change
    419       1.1   dyoung 			 * during my scan.  So delete the entry for the AP
    420       1.1   dyoung 			 * and retry to associate if there is another beacon.
    421       1.1   dyoung 			 */
    422       1.1   dyoung 			if (ni->ni_fails++ > 2)
    423       1.1   dyoung 				ieee80211_free_node(ic, ni);
    424       1.1   dyoung 			continue;
    425       1.1   dyoung 		}
    426       1.5   dyoung 		if (ieee80211_match_bss(ic, ni) == 0) {
    427       1.1   dyoung 			if (selbs == NULL)
    428       1.1   dyoung 				selbs = ni;
    429      1.33   dyoung 			else if (ni->ni_rssi > selbs->ni_rssi)
    430       1.1   dyoung 				selbs = ni;
    431       1.1   dyoung 		}
    432       1.1   dyoung 	}
    433       1.1   dyoung 	if (selbs == NULL)
    434       1.1   dyoung 		goto notfound;
    435       1.1   dyoung 	(*ic->ic_node_copy)(ic, ic->ic_bss, selbs);
    436      1.37   dyoung 	ieee80211_node_newstate(ic->ic_bss, IEEE80211_STA_BSS);
    437       1.1   dyoung 	if (ic->ic_opmode == IEEE80211_M_IBSS) {
    438       1.1   dyoung 		ieee80211_fix_rate(ic, ic->ic_bss, IEEE80211_F_DOFRATE |
    439       1.1   dyoung 		    IEEE80211_F_DONEGO | IEEE80211_F_DODEL);
    440      1.33   dyoung 		if (ic->ic_bss->ni_rates.rs_nrates == 0)
    441       1.1   dyoung 			goto notfound;
    442       1.1   dyoung 		ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
    443       1.1   dyoung 	} else {
    444       1.1   dyoung 		ieee80211_new_state(ic, IEEE80211_S_AUTH, -1);
    445       1.1   dyoung 	}
    446       1.1   dyoung }
    447       1.1   dyoung 
    448       1.5   dyoung int
    449       1.5   dyoung ieee80211_get_rate(struct ieee80211com *ic)
    450       1.5   dyoung {
    451       1.5   dyoung 	u_int8_t (*rates)[IEEE80211_RATE_MAXSIZE];
    452       1.5   dyoung 	int rate;
    453       1.5   dyoung 
    454       1.5   dyoung 	rates = &ic->ic_bss->ni_rates.rs_rates;
    455       1.5   dyoung 
    456       1.5   dyoung 	if (ic->ic_fixed_rate != -1)
    457       1.5   dyoung 		rate = (*rates)[ic->ic_fixed_rate];
    458       1.5   dyoung 	else if (ic->ic_state == IEEE80211_S_RUN)
    459       1.5   dyoung 		rate = (*rates)[ic->ic_bss->ni_txrate];
    460       1.5   dyoung 	else
    461       1.5   dyoung 		rate = 0;
    462       1.5   dyoung 
    463       1.5   dyoung 	return rate & IEEE80211_RATE_VAL;
    464       1.5   dyoung }
    465       1.5   dyoung 
    466       1.1   dyoung static struct ieee80211_node *
    467       1.1   dyoung ieee80211_node_alloc(struct ieee80211com *ic)
    468       1.1   dyoung {
    469      1.11   dyoung 	struct ieee80211_node *ni;
    470      1.11   dyoung 	MALLOC(ni, struct ieee80211_node *, sizeof(struct ieee80211_node),
    471      1.11   dyoung 		M_80211_NODE, M_NOWAIT | M_ZERO);
    472      1.11   dyoung 	return ni;
    473       1.1   dyoung }
    474       1.1   dyoung 
    475       1.1   dyoung static void
    476      1.22  mycroft node_cleanup(struct ieee80211com *ic, struct ieee80211_node *ni)
    477      1.22  mycroft {
    478      1.22  mycroft         if (ni->ni_challenge != NULL) {
    479      1.22  mycroft                 FREE(ni->ni_challenge, M_DEVBUF);
    480      1.22  mycroft                 ni->ni_challenge = NULL;
    481      1.22  mycroft         }
    482      1.22  mycroft }
    483      1.22  mycroft 
    484      1.22  mycroft static void
    485       1.1   dyoung ieee80211_node_free(struct ieee80211com *ic, struct ieee80211_node *ni)
    486       1.1   dyoung {
    487      1.22  mycroft 	node_cleanup(ic, ni);
    488      1.11   dyoung 	FREE(ni, M_80211_NODE);
    489       1.1   dyoung }
    490       1.1   dyoung 
    491       1.1   dyoung static void
    492       1.1   dyoung ieee80211_node_copy(struct ieee80211com *ic,
    493       1.1   dyoung 	struct ieee80211_node *dst, const struct ieee80211_node *src)
    494       1.1   dyoung {
    495      1.22  mycroft 	node_cleanup(ic, dst);
    496       1.1   dyoung 	*dst = *src;
    497       1.6   dyoung 	dst->ni_challenge = NULL;
    498       1.1   dyoung }
    499       1.1   dyoung 
    500       1.9   dyoung static u_int8_t
    501       1.9   dyoung ieee80211_node_getrssi(struct ieee80211com *ic, struct ieee80211_node *ni)
    502       1.9   dyoung {
    503       1.9   dyoung 	return ni->ni_rssi;
    504       1.9   dyoung }
    505       1.9   dyoung 
    506       1.1   dyoung static void
    507       1.1   dyoung ieee80211_setup_node(struct ieee80211com *ic,
    508       1.1   dyoung 	struct ieee80211_node *ni, u_int8_t *macaddr)
    509       1.1   dyoung {
    510       1.1   dyoung 	int hash;
    511       1.1   dyoung 
    512      1.23  mycroft 	IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
    513      1.23  mycroft 		("%s %s\n", __func__, ether_sprintf(macaddr)));
    514       1.1   dyoung 	IEEE80211_ADDR_COPY(ni->ni_macaddr, macaddr);
    515       1.1   dyoung 	hash = IEEE80211_NODE_HASH(macaddr);
    516      1.33   dyoung 	ieee80211_node_newstate(ni, IEEE80211_STA_CACHE);
    517      1.23  mycroft 
    518      1.23  mycroft 	IEEE80211_NODE_LOCK_BH(ic);
    519  1.37.4.1     yamt 	/*
    520       1.1   dyoung 	 * Note we don't enable the inactive timer when acting
    521       1.1   dyoung 	 * as a station.  Nodes created in this mode represent
    522       1.1   dyoung 	 * AP's identified while scanning.  If we time them out
    523       1.1   dyoung 	 * then several things happen: we can't return the data
    524       1.1   dyoung 	 * to users to show the list of AP's we encountered, and
    525       1.1   dyoung 	 * more importantly, we'll incorrectly deauthenticate
    526  1.37.4.1     yamt 	 * ourself because the inactivity timer will kick us off.
    527       1.1   dyoung 	 */
    528      1.31  mycroft 	if (ic->ic_opmode != IEEE80211_M_STA &&
    529      1.31  mycroft 	    TAILQ_EMPTY(&ic->ic_node))
    530       1.1   dyoung 		ic->ic_inact_timer = IEEE80211_INACT_WAIT;
    531      1.32  mycroft 	TAILQ_INSERT_TAIL(&ic->ic_node, ni, ni_list);
    532      1.32  mycroft 	LIST_INSERT_HEAD(&ic->ic_hash[hash], ni, ni_hash);
    533      1.23  mycroft 	IEEE80211_NODE_UNLOCK_BH(ic);
    534       1.1   dyoung }
    535       1.1   dyoung 
    536       1.1   dyoung struct ieee80211_node *
    537       1.1   dyoung ieee80211_alloc_node(struct ieee80211com *ic, u_int8_t *macaddr)
    538       1.1   dyoung {
    539      1.33   dyoung 	struct ieee80211_node *ni = ieee80211_alloc_node_helper(ic);
    540      1.33   dyoung 	if (ni != NULL) {
    541       1.1   dyoung 		ieee80211_setup_node(ic, ni, macaddr);
    542      1.33   dyoung 	} else
    543      1.11   dyoung 		ic->ic_stats.is_rx_nodealloc++;
    544       1.1   dyoung 	return ni;
    545       1.1   dyoung }
    546       1.1   dyoung 
    547       1.1   dyoung struct ieee80211_node *
    548       1.1   dyoung ieee80211_dup_bss(struct ieee80211com *ic, u_int8_t *macaddr)
    549       1.1   dyoung {
    550      1.33   dyoung 	struct ieee80211_node *ni = ieee80211_alloc_node_helper(ic);
    551       1.1   dyoung 	if (ni != NULL) {
    552       1.1   dyoung 		ieee80211_setup_node(ic, ni, macaddr);
    553      1.11   dyoung 		/*
    554      1.11   dyoung 		 * Inherit from ic_bss.
    555      1.11   dyoung 		 */
    556      1.11   dyoung 		IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss->ni_bssid);
    557      1.11   dyoung 		ni->ni_chan = ic->ic_bss->ni_chan;
    558      1.11   dyoung 	} else
    559      1.11   dyoung 		ic->ic_stats.is_rx_nodealloc++;
    560       1.1   dyoung 	return ni;
    561       1.1   dyoung }
    562       1.1   dyoung 
    563      1.11   dyoung static struct ieee80211_node *
    564      1.11   dyoung _ieee80211_find_node(struct ieee80211com *ic, u_int8_t *macaddr)
    565       1.1   dyoung {
    566       1.1   dyoung 	struct ieee80211_node *ni;
    567       1.1   dyoung 	int hash;
    568      1.11   dyoung 
    569      1.11   dyoung 	IEEE80211_NODE_LOCK_ASSERT(ic);
    570       1.1   dyoung 
    571       1.1   dyoung 	hash = IEEE80211_NODE_HASH(macaddr);
    572       1.1   dyoung 	LIST_FOREACH(ni, &ic->ic_hash[hash], ni_hash) {
    573       1.1   dyoung 		if (IEEE80211_ADDR_EQ(ni->ni_macaddr, macaddr)) {
    574      1.33   dyoung 			/* least-recently used is at tail */
    575      1.33   dyoung 			TAILQ_REMOVE(&ic->ic_node, ni, ni_list);
    576      1.33   dyoung 			TAILQ_INSERT_TAIL(&ic->ic_node, ni, ni_list);
    577      1.11   dyoung 			return ni;
    578       1.1   dyoung 		}
    579       1.1   dyoung 	}
    580      1.11   dyoung 	return NULL;
    581      1.11   dyoung }
    582      1.11   dyoung 
    583      1.11   dyoung struct ieee80211_node *
    584      1.11   dyoung ieee80211_find_node(struct ieee80211com *ic, u_int8_t *macaddr)
    585      1.11   dyoung {
    586      1.11   dyoung 	struct ieee80211_node *ni;
    587      1.11   dyoung 
    588      1.23  mycroft 	IEEE80211_NODE_LOCK(ic);
    589      1.11   dyoung 	ni = _ieee80211_find_node(ic, macaddr);
    590      1.23  mycroft 	IEEE80211_NODE_UNLOCK(ic);
    591       1.7   dyoung 	return ni;
    592       1.7   dyoung }
    593       1.7   dyoung 
    594      1.11   dyoung /*
    595      1.11   dyoung  * Return a reference to the appropriate node for sending
    596      1.11   dyoung  * a data frame.  This handles node discovery in adhoc networks.
    597      1.33   dyoung  *
    598      1.33   dyoung  * Drivers will call this, so increase the reference count before
    599      1.33   dyoung  * returning the node.
    600      1.11   dyoung  */
    601       1.7   dyoung struct ieee80211_node *
    602       1.7   dyoung ieee80211_find_txnode(struct ieee80211com *ic, u_int8_t *macaddr)
    603       1.7   dyoung {
    604       1.7   dyoung 	struct ieee80211_node *ni;
    605       1.7   dyoung 
    606       1.7   dyoung 	/*
    607       1.7   dyoung 	 * The destination address should be in the node table
    608      1.11   dyoung 	 * unless we are operating in station mode or this is a
    609      1.11   dyoung 	 * multicast/broadcast frame.
    610       1.7   dyoung 	 */
    611      1.11   dyoung 	if (ic->ic_opmode == IEEE80211_M_STA || IEEE80211_IS_MULTICAST(macaddr))
    612      1.33   dyoung 		return ieee80211_ref_node(ic->ic_bss);
    613       1.8   dyoung 
    614      1.11   dyoung 	/* XXX can't hold lock across dup_bss 'cuz of recursive locking */
    615      1.23  mycroft 	IEEE80211_NODE_LOCK(ic);
    616      1.11   dyoung 	ni = _ieee80211_find_node(ic, macaddr);
    617      1.23  mycroft 	IEEE80211_NODE_UNLOCK(ic);
    618      1.35   dyoung 	if (ni == NULL) {
    619      1.35   dyoung 		if (ic->ic_opmode != IEEE80211_M_IBSS &&
    620      1.35   dyoung 		    ic->ic_opmode != IEEE80211_M_AHDEMO)
    621      1.35   dyoung 			return NULL;
    622      1.11   dyoung 		/*
    623      1.11   dyoung 		 * Fake up a node; this handles node discovery in
    624      1.11   dyoung 		 * adhoc mode.  Note that for the driver's benefit
    625      1.11   dyoung 		 * we we treat this like an association so the driver
    626      1.11   dyoung 		 * has an opportunity to setup it's private state.
    627      1.11   dyoung 		 *
    628      1.11   dyoung 		 * XXX need better way to handle this; issue probe
    629      1.11   dyoung 		 *     request so we can deduce rate set, etc.
    630      1.11   dyoung 		 */
    631      1.35   dyoung 		if ((ni = ieee80211_dup_bss(ic, macaddr)) == NULL)
    632      1.35   dyoung 			return NULL;
    633      1.35   dyoung 		/* XXX no rate negotiation; just dup */
    634      1.35   dyoung 		ni->ni_rates = ic->ic_bss->ni_rates;
    635      1.35   dyoung 		if (ic->ic_newassoc)
    636      1.35   dyoung 			(*ic->ic_newassoc)(ic, ni, 1);
    637       1.7   dyoung 	}
    638      1.33   dyoung 	return ieee80211_ref_node(ni);
    639       1.7   dyoung }
    640       1.7   dyoung 
    641       1.7   dyoung /*
    642      1.29   dyoung  * It is usually desirable to process a Rx packet using its sender's
    643      1.29   dyoung  * node-record instead of the BSS record.
    644       1.7   dyoung  *
    645      1.17   dyoung  *  - AP mode: keep a node-record for every authenticated/associated
    646      1.17   dyoung  *    station *in the BSS*. For future use, we also track neighboring
    647      1.29   dyoung  *    APs, since they might belong to the same ESS.  APs in the same
    648      1.29   dyoung  *    ESS may bridge packets to each other, forming a Wireless
    649      1.29   dyoung  *    Distribution System (WDS).
    650       1.7   dyoung  *
    651      1.17   dyoung  * - IBSS mode: keep a node-record for every station *in the BSS*.
    652      1.29   dyoung  *   Also track neighboring stations by their beacons/probe responses.
    653       1.7   dyoung  *
    654      1.17   dyoung  * - monitor mode: keep a node-record for every sender, regardless
    655      1.17   dyoung  *   of BSS.
    656       1.7   dyoung  *
    657       1.7   dyoung  * - STA mode: the only available node-record is the BSS record,
    658       1.7   dyoung  *   ic->ic_bss.
    659       1.7   dyoung  *
    660       1.7   dyoung  * Of all the 802.11 Control packets, only the node-records for
    661       1.7   dyoung  * RTS packets node-record can be looked up.
    662       1.7   dyoung  *
    663       1.7   dyoung  * Return non-zero if the packet's node-record is kept, zero
    664       1.7   dyoung  * otherwise.
    665       1.7   dyoung  */
    666       1.7   dyoung static __inline int
    667       1.7   dyoung ieee80211_needs_rxnode(struct ieee80211com *ic, struct ieee80211_frame *wh,
    668       1.7   dyoung     u_int8_t **bssid)
    669       1.7   dyoung {
    670       1.7   dyoung 	struct ieee80211_node *bss = ic->ic_bss;
    671      1.19   dyoung 	int monitor, rc = 0;
    672       1.7   dyoung 
    673      1.19   dyoung 	monitor = (ic->ic_opmode == IEEE80211_M_MONITOR);
    674       1.7   dyoung 
    675       1.7   dyoung 	*bssid = NULL;
    676       1.7   dyoung 
    677       1.7   dyoung 	switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) {
    678       1.7   dyoung 	case IEEE80211_FC0_TYPE_CTL:
    679      1.19   dyoung 		if (!monitor)
    680      1.19   dyoung 			break;
    681       1.7   dyoung 		return (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) ==
    682       1.7   dyoung 		    IEEE80211_FC0_SUBTYPE_RTS;
    683       1.7   dyoung 	case IEEE80211_FC0_TYPE_MGT:
    684       1.7   dyoung 		*bssid = wh->i_addr3;
    685      1.29   dyoung 		switch (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) {
    686      1.29   dyoung 		case IEEE80211_FC0_SUBTYPE_BEACON:
    687      1.29   dyoung 		case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
    688      1.29   dyoung 			rc = 1;
    689      1.29   dyoung 			break;
    690      1.29   dyoung 		default:
    691      1.33   dyoung 			if (ic->ic_opmode == IEEE80211_M_STA)
    692      1.33   dyoung 				break;
    693      1.33   dyoung 			rc = IEEE80211_ADDR_EQ(*bssid, bss->ni_bssid) ||
    694      1.33   dyoung 			     IEEE80211_ADDR_EQ(*bssid, etherbroadcastaddr);
    695      1.29   dyoung 			break;
    696      1.29   dyoung 		}
    697       1.7   dyoung 		break;
    698       1.7   dyoung 	case IEEE80211_FC0_TYPE_DATA:
    699       1.7   dyoung 		switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) {
    700       1.7   dyoung 		case IEEE80211_FC1_DIR_NODS:
    701       1.7   dyoung 			*bssid = wh->i_addr3;
    702       1.7   dyoung 			if (ic->ic_opmode == IEEE80211_M_IBSS ||
    703       1.7   dyoung 			    ic->ic_opmode == IEEE80211_M_AHDEMO)
    704       1.7   dyoung 				rc = IEEE80211_ADDR_EQ(*bssid, bss->ni_bssid);
    705       1.7   dyoung 			break;
    706       1.7   dyoung 		case IEEE80211_FC1_DIR_TODS:
    707       1.7   dyoung 			*bssid = wh->i_addr1;
    708       1.7   dyoung 			if (ic->ic_opmode == IEEE80211_M_HOSTAP)
    709       1.7   dyoung 				rc = IEEE80211_ADDR_EQ(*bssid, bss->ni_bssid);
    710       1.7   dyoung 			break;
    711       1.7   dyoung 		case IEEE80211_FC1_DIR_FROMDS:
    712       1.7   dyoung 		case IEEE80211_FC1_DIR_DSTODS:
    713       1.7   dyoung 			*bssid = wh->i_addr2;
    714       1.7   dyoung 			rc = (ic->ic_opmode == IEEE80211_M_HOSTAP);
    715       1.7   dyoung 			break;
    716       1.7   dyoung 		}
    717       1.7   dyoung 		break;
    718       1.7   dyoung 	}
    719      1.19   dyoung 	return monitor || rc;
    720       1.7   dyoung }
    721       1.7   dyoung 
    722      1.33   dyoung /* Drivers call this, so increase the reference count before returning
    723      1.33   dyoung  * the node.
    724      1.33   dyoung  */
    725       1.7   dyoung struct ieee80211_node *
    726       1.7   dyoung ieee80211_find_rxnode(struct ieee80211com *ic, struct ieee80211_frame *wh)
    727       1.7   dyoung {
    728       1.7   dyoung 	struct ieee80211_node *ni;
    729       1.7   dyoung 	const static u_int8_t zero[IEEE80211_ADDR_LEN];
    730       1.7   dyoung 	u_int8_t *bssid;
    731       1.7   dyoung 
    732       1.7   dyoung 	if (!ieee80211_needs_rxnode(ic, wh, &bssid))
    733       1.7   dyoung 	        return ieee80211_ref_node(ic->ic_bss);
    734       1.7   dyoung 
    735      1.23  mycroft 	IEEE80211_NODE_LOCK(ic);
    736      1.11   dyoung 	ni = _ieee80211_find_node(ic, wh->i_addr2);
    737      1.23  mycroft 	IEEE80211_NODE_UNLOCK(ic);
    738       1.7   dyoung 
    739      1.15   dyoung 	if (ni != NULL)
    740      1.33   dyoung 		return ieee80211_ref_node(ni);
    741      1.15   dyoung 
    742      1.15   dyoung 	if (ic->ic_opmode == IEEE80211_M_HOSTAP)
    743      1.15   dyoung 		return ieee80211_ref_node(ic->ic_bss);
    744      1.15   dyoung 
    745      1.15   dyoung 	/* XXX see remarks in ieee80211_find_txnode */
    746      1.15   dyoung 	/* XXX no rate negotiation; just dup */
    747      1.15   dyoung 	if ((ni = ieee80211_dup_bss(ic, wh->i_addr2)) == NULL)
    748      1.15   dyoung 		return ieee80211_ref_node(ic->ic_bss);
    749      1.15   dyoung 
    750      1.15   dyoung 	IEEE80211_ADDR_COPY(ni->ni_bssid, (bssid != NULL) ? bssid : zero);
    751      1.15   dyoung 
    752      1.15   dyoung 	ni->ni_rates = ic->ic_bss->ni_rates;
    753      1.15   dyoung 	if (ic->ic_newassoc)
    754      1.15   dyoung 		(*ic->ic_newassoc)(ic, ni, 1);
    755      1.15   dyoung 
    756      1.18  mycroft 	IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
    757      1.18  mycroft 		("%s: faked-up node %p for %s\n", __func__, ni,
    758      1.18  mycroft 		ether_sprintf(wh->i_addr2)));
    759      1.15   dyoung 
    760      1.15   dyoung 	return ieee80211_ref_node(ni);
    761       1.1   dyoung }
    762       1.1   dyoung 
    763       1.1   dyoung /*
    764       1.1   dyoung  * Like find but search based on the channel too.
    765      1.36   dyoung  *
    766      1.36   dyoung  * Note that ieee80211_find_node_for_beacon does not increase the
    767      1.36   dyoung  * reference count before returning the node, because drivers are not
    768      1.36   dyoung  * expected to call it.
    769       1.1   dyoung  */
    770       1.1   dyoung struct ieee80211_node *
    771      1.30  mycroft ieee80211_find_node_for_beacon(struct ieee80211com *ic, u_int8_t *macaddr,
    772      1.30  mycroft 	struct ieee80211_channel *chan, char *ssid)
    773       1.1   dyoung {
    774      1.33   dyoung 	struct ieee80211_node *ni, *best;
    775       1.1   dyoung 	int hash;
    776      1.33   dyoung 	int best_score, score;
    777      1.33   dyoung 
    778      1.33   dyoung 	best = NULL;
    779      1.33   dyoung 	best_score = -1;
    780       1.1   dyoung 
    781       1.1   dyoung 	hash = IEEE80211_NODE_HASH(macaddr);
    782      1.23  mycroft 	IEEE80211_NODE_LOCK(ic);
    783       1.1   dyoung 	LIST_FOREACH(ni, &ic->ic_hash[hash], ni_hash) {
    784      1.33   dyoung 		if (!IEEE80211_ADDR_EQ(ni->ni_macaddr, macaddr))
    785      1.33   dyoung 			continue;
    786      1.33   dyoung 
    787      1.33   dyoung 		score = (ni->ni_chan == chan) ? 1 : 0;
    788      1.33   dyoung 
    789      1.33   dyoung 		if (ssid[1] == 0 || ni->ni_esslen == 0)
    790      1.33   dyoung 			score++;
    791      1.33   dyoung 		else if (ssid[1] != ni->ni_esslen ||
    792      1.33   dyoung 		     memcmp(ssid + 2, ni->ni_essid, ssid[1]) != 0)
    793      1.33   dyoung 			continue;
    794      1.33   dyoung 
    795      1.33   dyoung 		if (score > best_score) {
    796      1.36   dyoung 			best = ni;
    797      1.33   dyoung 			best_score = score;
    798       1.1   dyoung 		}
    799       1.1   dyoung 	}
    800      1.23  mycroft 	IEEE80211_NODE_UNLOCK(ic);
    801      1.33   dyoung 	return best;
    802       1.1   dyoung }
    803       1.1   dyoung 
    804       1.1   dyoung static void
    805      1.33   dyoung ieee80211_free_node(struct ieee80211com *ic, struct ieee80211_node *ni)
    806       1.1   dyoung {
    807      1.10   dyoung 	IASSERT(ni != ic->ic_bss, ("freeing bss node"));
    808       1.1   dyoung 
    809      1.22  mycroft 	IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
    810      1.22  mycroft 		("%s %s\n", __func__, ether_sprintf(ni->ni_macaddr)));
    811       1.5   dyoung 	IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap);
    812       1.1   dyoung 	TAILQ_REMOVE(&ic->ic_node, ni, ni_list);
    813       1.1   dyoung 	LIST_REMOVE(ni, ni_hash);
    814      1.33   dyoung 	ic->ic_nnodes--;
    815       1.5   dyoung 	if (!IF_IS_EMPTY(&ni->ni_savedq)) {
    816  1.37.4.1     yamt 		IF_PURGE(&ni->ni_savedq);
    817       1.5   dyoung 		if (ic->ic_set_tim)
    818      1.22  mycroft 			(*ic->ic_set_tim)(ic, ni->ni_associd, 0);
    819       1.5   dyoung 	}
    820       1.1   dyoung 	if (TAILQ_EMPTY(&ic->ic_node))
    821       1.1   dyoung 		ic->ic_inact_timer = 0;
    822       1.1   dyoung 	(*ic->ic_node_free)(ic, ni);
    823      1.33   dyoung 	/* TBD indicate to drivers that a new node can be allocated */
    824       1.1   dyoung }
    825       1.1   dyoung 
    826       1.1   dyoung void
    827      1.33   dyoung ieee80211_release_node(struct ieee80211com *ic, struct ieee80211_node *ni)
    828       1.1   dyoung {
    829      1.23  mycroft 	IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
    830      1.23  mycroft 		("%s %s refcnt %d\n", __func__,
    831      1.24   dyoung 		 ether_sprintf(ni->ni_macaddr), ni->ni_refcnt));
    832      1.33   dyoung 	if (ieee80211_node_decref(ni) == 0 &&
    833      1.33   dyoung 	    ni->ni_state == IEEE80211_STA_COLLECT) {
    834      1.23  mycroft 		IEEE80211_NODE_LOCK_BH(ic);
    835      1.33   dyoung 		ieee80211_free_node(ic, ni);
    836      1.23  mycroft 		IEEE80211_NODE_UNLOCK_BH(ic);
    837       1.1   dyoung 	}
    838       1.1   dyoung }
    839       1.1   dyoung 
    840       1.1   dyoung void
    841       1.1   dyoung ieee80211_free_allnodes(struct ieee80211com *ic)
    842       1.1   dyoung {
    843       1.1   dyoung 	struct ieee80211_node *ni;
    844       1.1   dyoung 
    845      1.22  mycroft 	IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE, ("free all nodes\n"));
    846      1.23  mycroft 	IEEE80211_NODE_LOCK_BH(ic);
    847       1.1   dyoung 	while ((ni = TAILQ_FIRST(&ic->ic_node)) != NULL)
    848  1.37.4.1     yamt 		ieee80211_free_node(ic, ni);
    849      1.23  mycroft 	IEEE80211_NODE_UNLOCK_BH(ic);
    850      1.22  mycroft 
    851      1.22  mycroft 	if (ic->ic_bss != NULL)
    852      1.22  mycroft 		node_cleanup(ic, ic->ic_bss);	/* for station mode */
    853       1.1   dyoung }
    854       1.1   dyoung 
    855       1.9   dyoung /*
    856       1.9   dyoung  * Timeout inactive nodes.  Note that we cannot hold the node
    857       1.9   dyoung  * lock while sending a frame as this would lead to a LOR.
    858       1.9   dyoung  * Instead we use a generation number to mark nodes that we've
    859       1.9   dyoung  * scanned and drop the lock and restart a scan if we have to
    860       1.9   dyoung  * time out a node.  Since we are single-threaded by virtue of
    861       1.9   dyoung  * controlling the inactivity timer we can be sure this will
    862       1.9   dyoung  * process each node only once.
    863       1.9   dyoung  */
    864       1.1   dyoung void
    865      1.33   dyoung ieee80211_clean_nodes(struct ieee80211com *ic)
    866       1.1   dyoung {
    867       1.9   dyoung 	struct ieee80211_node *ni;
    868       1.9   dyoung 	u_int gen = ic->ic_scangen++;		/* NB: ok 'cuz single-threaded*/
    869       1.1   dyoung 
    870       1.9   dyoung restart:
    871      1.23  mycroft 	IEEE80211_NODE_LOCK(ic);
    872       1.9   dyoung 	TAILQ_FOREACH(ni, &ic->ic_node, ni_list) {
    873      1.33   dyoung 		if (ic->ic_nnodes <= ic->ic_max_nnodes)
    874      1.33   dyoung 			break;
    875       1.9   dyoung 		if (ni->ni_scangen == gen)	/* previously handled */
    876       1.9   dyoung 			continue;
    877       1.9   dyoung 		ni->ni_scangen = gen;
    878      1.33   dyoung 		if (ni->ni_refcnt > 0)
    879      1.33   dyoung 			continue;
    880      1.33   dyoung 		IEEE80211_DPRINTF(ic, IEEE80211_MSG_NODE,
    881      1.33   dyoung 		    ("station %s purged from LRU cache\n",
    882      1.33   dyoung 		    ether_sprintf(ni->ni_macaddr)));
    883      1.33   dyoung 		/*
    884      1.33   dyoung 		 * Send a deauthenticate frame.
    885      1.33   dyoung 		 *
    886      1.33   dyoung 		 * Drop the node lock before sending the
    887  1.37.4.1     yamt 		 * deauthentication frame in case the driver takes
    888  1.37.4.1     yamt 		 * a lock, as this will result in a LOR between the
    889      1.33   dyoung 		 * node lock and the driver lock.
    890      1.33   dyoung 		 */
    891      1.33   dyoung 		IEEE80211_NODE_UNLOCK(ic);
    892      1.33   dyoung 		if (ic->ic_opmode == IEEE80211_M_HOSTAP) {
    893      1.33   dyoung 			IEEE80211_SEND_MGMT(ic, ni,
    894      1.33   dyoung 			    IEEE80211_FC0_SUBTYPE_DEAUTH,
    895      1.33   dyoung 			    IEEE80211_REASON_AUTH_EXPIRE);
    896      1.33   dyoung 			ieee80211_node_leave(ic, ni);
    897      1.33   dyoung 		} else
    898      1.33   dyoung 			ieee80211_free_node(ic, ni);
    899      1.33   dyoung 		ic->ic_stats.is_node_timeout++;
    900      1.33   dyoung 		goto restart;
    901       1.1   dyoung 	}
    902      1.23  mycroft 	IEEE80211_NODE_UNLOCK(ic);
    903       1.1   dyoung }
    904       1.1   dyoung 
    905       1.1   dyoung void
    906       1.1   dyoung ieee80211_iterate_nodes(struct ieee80211com *ic, ieee80211_iter_func *f, void *arg)
    907       1.1   dyoung {
    908       1.1   dyoung 	struct ieee80211_node *ni;
    909       1.1   dyoung 
    910      1.23  mycroft 	IEEE80211_NODE_LOCK(ic);
    911       1.1   dyoung 	TAILQ_FOREACH(ni, &ic->ic_node, ni_list)
    912       1.1   dyoung 		(*f)(arg, ni);
    913      1.23  mycroft 	IEEE80211_NODE_UNLOCK(ic);
    914       1.1   dyoung }
    915      1.22  mycroft 
    916      1.22  mycroft void
    917      1.22  mycroft ieee80211_node_join(struct ieee80211com *ic, struct ieee80211_node *ni, int resp)
    918      1.22  mycroft {
    919      1.22  mycroft 	int newassoc;
    920      1.22  mycroft 
    921      1.22  mycroft 	if (ni->ni_associd == 0) {
    922      1.22  mycroft 		u_int16_t aid;
    923      1.22  mycroft 
    924      1.22  mycroft 		/*
    925      1.22  mycroft 		 * It would be clever to search the bitmap
    926      1.22  mycroft 		 * more efficiently, but this will do for now.
    927      1.22  mycroft 		 */
    928      1.22  mycroft 		for (aid = 1; aid < ic->ic_max_aid; aid++) {
    929      1.22  mycroft 			if (!IEEE80211_AID_ISSET(aid,
    930      1.22  mycroft 			    ic->ic_aid_bitmap))
    931      1.22  mycroft 				break;
    932      1.22  mycroft 		}
    933      1.22  mycroft 		if (aid >= ic->ic_max_aid) {
    934      1.22  mycroft 			IEEE80211_SEND_MGMT(ic, ni, resp,
    935      1.22  mycroft 			    IEEE80211_REASON_ASSOC_TOOMANY);
    936      1.22  mycroft 			ieee80211_node_leave(ic, ni);
    937      1.22  mycroft 			return;
    938      1.22  mycroft 		}
    939      1.22  mycroft 		ni->ni_associd = aid | 0xc000;
    940      1.22  mycroft 		IEEE80211_AID_SET(ni->ni_associd, ic->ic_aid_bitmap);
    941      1.22  mycroft 		newassoc = 1;
    942      1.22  mycroft 		/* XXX for 11g must turn off short slot time if long
    943      1.22  mycroft 		   slot time sta associates */
    944      1.22  mycroft 	} else
    945      1.22  mycroft 		newassoc = 0;
    946      1.22  mycroft 
    947      1.22  mycroft 	IEEE80211_DPRINTF(ic, IEEE80211_MSG_ASSOC | IEEE80211_MSG_DEBUG,
    948      1.22  mycroft 		("station %s %s associated at aid %d\n",
    949      1.22  mycroft 		ether_sprintf(ni->ni_macaddr),
    950      1.22  mycroft 		(newassoc ? "newly" : "already"),
    951      1.22  mycroft 		ni->ni_associd & ~0xc000));
    952      1.22  mycroft 
    953      1.22  mycroft 	/* give driver a chance to setup state like ni_txrate */
    954      1.22  mycroft 	if (ic->ic_newassoc)
    955      1.22  mycroft 		(*ic->ic_newassoc)(ic, ni, newassoc);
    956      1.22  mycroft 	IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_SUCCESS);
    957      1.33   dyoung 	ieee80211_node_newstate(ni, IEEE80211_STA_ASSOC);
    958      1.22  mycroft }
    959      1.22  mycroft 
    960      1.22  mycroft /*
    961      1.26   dyoung  * Handle bookkeeping for station deauthentication/disassociation
    962      1.26   dyoung  * when operating as an ap.
    963      1.22  mycroft  */
    964      1.22  mycroft void
    965      1.22  mycroft ieee80211_node_leave(struct ieee80211com *ic, struct ieee80211_node *ni)
    966      1.22  mycroft {
    967      1.26   dyoung 
    968      1.26   dyoung 	IASSERT(ic->ic_opmode == IEEE80211_M_HOSTAP,
    969      1.26   dyoung 		("not in ap mode, mode %u", ic->ic_opmode));
    970      1.22  mycroft 	/*
    971      1.22  mycroft 	 * If node wasn't previously associated all
    972      1.22  mycroft 	 * we need to do is reclaim the reference.
    973      1.22  mycroft 	 */
    974      1.22  mycroft 	if (ni->ni_associd == 0)
    975      1.33   dyoung 		return;
    976      1.22  mycroft 	IEEE80211_AID_CLR(ni->ni_associd, ic->ic_aid_bitmap);
    977      1.22  mycroft 	ni->ni_associd = 0;
    978      1.33   dyoung 	ieee80211_node_newstate(ni, IEEE80211_STA_COLLECT);
    979      1.22  mycroft }
    980