diff options
Diffstat (limited to 'sys/net80211/ieee80211_scan_ap.c')
-rw-r--r-- | sys/net80211/ieee80211_scan_ap.c | 408 |
1 files changed, 0 insertions, 408 deletions
diff --git a/sys/net80211/ieee80211_scan_ap.c b/sys/net80211/ieee80211_scan_ap.c deleted file mode 100644 index 300f440..0000000 --- a/sys/net80211/ieee80211_scan_ap.c +++ /dev/null @@ -1,408 +0,0 @@ -/*- - * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -/* - * IEEE 802.11 ap scanning support. - */ -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/kernel.h> -#include <sys/module.h> - -#include <sys/socket.h> - -#include <net/if.h> -#include <net/if_media.h> -#include <net/ethernet.h> - -#include <net80211/ieee80211_var.h> - -#include <net/bpf.h> - -struct ap_state { - int as_maxrssi[IEEE80211_CHAN_MAX]; -}; - -static int ap_flush(struct ieee80211_scan_state *); - -/* number of references from net80211 layer */ -static int nrefs = 0; - -/* - * Attach prior to any scanning work. - */ -static int -ap_attach(struct ieee80211_scan_state *ss) -{ - struct ap_state *as; - - MALLOC(as, struct ap_state *, sizeof(struct ap_state), - M_80211_SCAN, M_NOWAIT); - ss->ss_priv = as; - ap_flush(ss); - nrefs++; /* NB: we assume caller locking */ - return 1; -} - -/* - * Cleanup any private state. - */ -static int -ap_detach(struct ieee80211_scan_state *ss) -{ - struct ap_state *as = ss->ss_priv; - - if (as != NULL) { - KASSERT(nrefs > 0, ("imbalanced attach/detach")); - nrefs--; /* NB: we assume caller locking */ - FREE(as, M_80211_SCAN); - } - return 1; -} - -/* - * Flush all per-scan state. - */ -static int -ap_flush(struct ieee80211_scan_state *ss) -{ - struct ap_state *as = ss->ss_priv; - - memset(as->as_maxrssi, 0, sizeof(as->as_maxrssi)); - ss->ss_last = 0; /* insure no channel will be picked */ - return 0; -} - -static int -find11gchannel(struct ieee80211com *ic, int i, int freq) -{ - const struct ieee80211_channel *c; - int j; - - /* - * The normal ordering in the channel list is b channel - * immediately followed by g so optimize the search for - * this. We'll still do a full search just in case. - */ - for (j = i+1; j < ic->ic_nchans; j++) { - c = &ic->ic_channels[j]; - if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c)) - return 1; - } - for (j = 0; j < i; j++) { - c = &ic->ic_channels[j]; - if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c)) - return 1; - } - return 0; -} - -/* - * Start an ap scan by populating the channel list. - */ -static int -ap_start(struct ieee80211_scan_state *ss, struct ieee80211com *ic) -{ - struct ieee80211_channel *c; - int i; - - ss->ss_last = 0; - if (ic->ic_des_mode == IEEE80211_MODE_AUTO) { - for (i = 0; i < ic->ic_nchans; i++) { - c = &ic->ic_channels[i]; - if (IEEE80211_IS_CHAN_TURBO(c)) { -#ifdef IEEE80211_F_XR - /* XR is not supported on turbo channels */ - if (ic->ic_flags & IEEE80211_F_XR) - continue; -#endif - /* dynamic channels are scanned in base mode */ - if (!IEEE80211_IS_CHAN_ST(c)) - continue; - } else if (IEEE80211_IS_CHAN_HT(c)) { - /* HT channels are scanned in legacy */ - continue; - } else { - /* - * Use any 11g channel instead of 11b one. - */ - if (IEEE80211_IS_CHAN_B(c) && - find11gchannel(ic, i, c->ic_freq)) - continue; - } - if (ss->ss_last >= IEEE80211_SCAN_MAX) - break; - ss->ss_chans[ss->ss_last++] = c; - } - } else { - static const u_int chanflags[IEEE80211_MODE_MAX] = { - 0, /* IEEE80211_MODE_AUTO */ - IEEE80211_CHAN_A, /* IEEE80211_MODE_11A */ - IEEE80211_CHAN_B, /* IEEE80211_MODE_11B */ - IEEE80211_CHAN_G, /* IEEE80211_MODE_11G */ - IEEE80211_CHAN_FHSS, /* IEEE80211_MODE_FH */ - IEEE80211_CHAN_108A, /* IEEE80211_MODE_TURBO_A */ - IEEE80211_CHAN_108G, /* IEEE80211_MODE_TURBO_G */ - IEEE80211_CHAN_ST, /* IEEE80211_MODE_STURBO_A */ - IEEE80211_CHAN_A, /* IEEE80211_MODE_11NA */ - IEEE80211_CHAN_G, /* IEEE80211_MODE_11NG */ - }; - u_int modeflags; - - modeflags = chanflags[ic->ic_des_mode]; - if ((ic->ic_flags & IEEE80211_F_TURBOP) && - modeflags != IEEE80211_CHAN_ST) { - if (ic->ic_des_mode == IEEE80211_MODE_11G) - modeflags = IEEE80211_CHAN_108G; - else - modeflags = IEEE80211_CHAN_108A; - } - for (i = 0; i < ic->ic_nchans; i++) { - c = &ic->ic_channels[i]; - if ((c->ic_flags & modeflags) != modeflags) - continue; -#ifdef IEEE80211_F_XR - /* XR is not supported on turbo channels */ - if (IEEE80211_IS_CHAN_TURBO(c) && - (ic->ic_flags & IEEE80211_F_XR)) - continue; -#endif - if (ss->ss_last >= IEEE80211_SCAN_MAX) - break; - /* - * Do not select static turbo channels if - * the mode is not static turbo. - */ - if (IEEE80211_IS_CHAN_STURBO(c) && - ic->ic_des_mode != IEEE80211_MODE_STURBO_A) - continue; - ss->ss_chans[ss->ss_last++] = c; - } - } - ss->ss_next = 0; - /* XXX tunables */ - ss->ss_mindwell = msecs_to_ticks(200); /* 200ms */ - ss->ss_maxdwell = msecs_to_ticks(300); /* 300ms */ - -#ifdef IEEE80211_DEBUG - if (ieee80211_msg_scan(ic)) { - if_printf(ic->ic_ifp, "scan set "); - ieee80211_scan_dump_channels(ss); - printf(" dwell min %ld max %ld\n", - ss->ss_mindwell, ss->ss_maxdwell); - } -#endif /* IEEE80211_DEBUG */ - - return 0; -} - -/* - * Restart a bg scan. - */ -static int -ap_restart(struct ieee80211_scan_state *ss, struct ieee80211com *ic) -{ - return 0; -} - -/* - * Cancel an ongoing scan. - */ -static int -ap_cancel(struct ieee80211_scan_state *ss, struct ieee80211com *ic) -{ - return 0; -} - -/* - * Record max rssi on channel. - */ -static int -ap_add(struct ieee80211_scan_state *ss, - const struct ieee80211_scanparams *sp, - const struct ieee80211_frame *wh, - int subtype, int rssi, int noise, int rstamp) -{ - struct ap_state *as = ss->ss_priv; - struct ieee80211com *ic = ss->ss_ic; - int chan; - - chan = ieee80211_chan2ieee(ic, ic->ic_curchan); - /* XXX better quantification of channel use? */ - /* XXX count bss's? */ - if (rssi > as->as_maxrssi[chan]) - as->as_maxrssi[chan] = rssi; - /* XXX interference, turbo requirements */ - return 1; -} - -/* - * Pick a quiet channel to use for ap operation. - */ -static int -ap_end(struct ieee80211_scan_state *ss, struct ieee80211com *ic) -{ - struct ap_state *as = ss->ss_priv; - int i, chan, bestchan, bestchanix; - - KASSERT(ic->ic_opmode == IEEE80211_M_HOSTAP, - ("wrong opmode %u", ic->ic_opmode)); - /* XXX select channel more intelligently, e.g. channel spread, power */ - bestchan = -1; - bestchanix = 0; /* NB: silence compiler */ - /* NB: use scan list order to preserve channel preference */ - for (i = 0; i < ss->ss_last; i++) { - /* - * If the channel is unoccupied the max rssi - * should be zero; just take it. Otherwise - * track the channel with the lowest rssi and - * use that when all channels appear occupied. - */ - /* XXX channel have interference? */ - chan = ieee80211_chan2ieee(ic, ss->ss_chans[i]); - - IEEE80211_DPRINTF(ic, IEEE80211_MSG_SCAN, - "%s: channel %u rssi %d bestchan %d bestchan rssi %d\n", - __func__, chan, as->as_maxrssi[chan], - bestchan, bestchan != -1 ? as->as_maxrssi[bestchan] : 0); - - if (as->as_maxrssi[chan] == 0) { - bestchan = chan; - bestchanix = i; - /* XXX use other considerations */ - break; - } - if (bestchan == -1 || - as->as_maxrssi[chan] < as->as_maxrssi[bestchan]) - bestchan = chan; - } - if (bestchan == -1) { - /* no suitable channel, should not happen */ - IEEE80211_DPRINTF(ic, IEEE80211_MSG_SCAN, - "%s: no suitable channel! (should not happen)\n", __func__); - /* XXX print something? */ - return 0; /* restart scan */ - } else { - struct ieee80211_channel *c; - - /* XXX notify all vap's? */ - /* - * If this is a dynamic turbo frequency, - * start with normal mode first. - */ - c = ss->ss_chans[bestchanix]; - if (IEEE80211_IS_CHAN_TURBO(c) && - !IEEE80211_IS_CHAN_STURBO(c)) { - c = ieee80211_find_channel(ic, c->ic_freq, - c->ic_flags & ~IEEE80211_CHAN_TURBO); - if (c == NULL) { - /* should never happen ?? */ - return 0; - } - } - ieee80211_create_ibss(ic, - ieee80211_ht_adjust_channel(ic, c, ic->ic_flags_ext)); - return 1; - } -} - -static void -ap_age(struct ieee80211_scan_state *ss) -{ - /* XXX is there anything meaningful to do? */ -} - -static void -ap_iterate(struct ieee80211_scan_state *ss, - ieee80211_scan_iter_func *f, void *arg) -{ - /* NB: nothing meaningful we can do */ -} - -static void -ap_assoc_success(struct ieee80211_scan_state *ss, - const uint8_t macaddr[IEEE80211_ADDR_LEN]) -{ - /* should not be called */ -} - -static void -ap_assoc_fail(struct ieee80211_scan_state *ss, - const uint8_t macaddr[IEEE80211_ADDR_LEN], int reason) -{ - /* should not be called */ -} - -static const struct ieee80211_scanner ap_default = { - .scan_name = "default", - .scan_attach = ap_attach, - .scan_detach = ap_detach, - .scan_start = ap_start, - .scan_restart = ap_restart, - .scan_cancel = ap_cancel, - .scan_end = ap_end, - .scan_flush = ap_flush, - .scan_add = ap_add, - .scan_age = ap_age, - .scan_iterate = ap_iterate, - .scan_assoc_success = ap_assoc_success, - .scan_assoc_fail = ap_assoc_fail, -}; - -/* - * Module glue. - */ -static int -wlan_modevent(module_t mod, int type, void *unused) -{ - switch (type) { - case MOD_LOAD: - ieee80211_scanner_register(IEEE80211_M_HOSTAP, &ap_default); - return 0; - case MOD_UNLOAD: - case MOD_QUIESCE: - if (nrefs) { - printf("wlan_scan_ap: still in use (%u dynamic refs)\n", - nrefs); - return EBUSY; - } - if (type == MOD_UNLOAD) - ieee80211_scanner_unregister_all(&ap_default); - return 0; - } - return EINVAL; -} - -static moduledata_t wlan_mod = { - "wlan_scan_ap", - wlan_modevent, - 0 -}; -DECLARE_MODULE(wlan_scan_ap, wlan_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST); -MODULE_VERSION(wlan_scan_ap, 1); -MODULE_DEPEND(wlan_scan_ap, wlan, 1, 1, 1); |