From: Sepherosa Ziehau Date: Thu, 18 May 2006 14:40:49 +0000 (+0000) Subject: Remove old 802.11 sources code, they have been repo copied into X-Git-Tag: v2.0.1~4919 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/8c8970b2f3344f5910064d6c83800ff92a6cdb63 Remove old 802.11 sources code, they have been repo copied into sys/netproto/802_11/wlan/ --- diff --git a/sys/netproto/802_11/ieee80211.c b/sys/netproto/802_11/ieee80211.c deleted file mode 100644 index e9544e9d9c..0000000000 --- a/sys/netproto/802_11/ieee80211.c +++ /dev/null @@ -1,902 +0,0 @@ -/* - * Copyright (c) 2001 Atsushi Onoe - * Copyright (c) 2002, 2003 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. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * 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. - * - * $FreeBSD: src/sys/net80211/ieee80211.c,v 1.13 2004/05/30 17:57:45 phk Exp $ - * $DragonFly: src/sys/netproto/802_11/Attic/ieee80211.c,v 1.5 2006/01/14 13:36:39 swildner Exp $ - */ - -/* - * IEEE 802.11 generic handler - */ - -#include "opt_inet.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#ifdef INET -#include -#include -#endif - -#ifdef IEEE80211_DEBUG -int ieee80211_debug = 0; -SYSCTL_INT(_debug, OID_AUTO, ieee80211, CTLFLAG_RW, &ieee80211_debug, - 0, "IEEE 802.11 media debugging printfs"); -#endif - -static void ieee80211_set11gbasicrates(struct ieee80211_rateset *, - enum ieee80211_phymode); - -static const char *ieee80211_phymode_name[] = { - "auto", /* IEEE80211_MODE_AUTO */ - "11a", /* IEEE80211_MODE_11A */ - "11b", /* IEEE80211_MODE_11B */ - "11g", /* IEEE80211_MODE_11G */ - "FH", /* IEEE80211_MODE_FH */ - "turbo", /* IEEE80211_MODE_TURBO */ -}; - -void -ieee80211_ifattach(struct ifnet *ifp) -{ - struct ieee80211com *ic = (void *)ifp; - struct ieee80211_channel *c; - int i; - - ether_ifattach(ifp, ic->ic_myaddr, NULL); - bpfattach_dlt(ifp, DLT_IEEE802_11, - sizeof(struct ieee80211_frame_addr4), &ic->ic_rawbpf); - ieee80211_crypto_attach(ifp); - - /* - * Fill in 802.11 available channel set, mark - * all available channels as active, and pick - * a default channel if not already specified. - */ - memset(ic->ic_chan_avail, 0, sizeof(ic->ic_chan_avail)); - ic->ic_modecaps |= 1<ic_channels[i]; - if (c->ic_flags) { - /* - * Verify driver passed us valid data. - */ - if (i != ieee80211_chan2ieee(ic, c)) { - if_printf(ifp, "bad channel ignored; " - "freq %u flags %x number %u\n", - c->ic_freq, c->ic_flags, i); - c->ic_flags = 0; /* NB: remove */ - continue; - } - setbit(ic->ic_chan_avail, i); - /* - * Identify mode capabilities. - */ - if (IEEE80211_IS_CHAN_A(c)) - ic->ic_modecaps |= 1<ic_modecaps |= 1<ic_modecaps |= 1<ic_modecaps |= 1<ic_modecaps |= 1<ic_curmode */ - if ((ic->ic_modecaps & (1<ic_curmode)) == 0) - ic->ic_curmode = IEEE80211_MODE_AUTO; - ic->ic_des_chan = IEEE80211_CHAN_ANYC; /* any channel is ok */ - - ieee80211_setmode(ic, ic->ic_curmode); - - if (ic->ic_lintval == 0) - ic->ic_lintval = 100; /* default sleep */ - ic->ic_bmisstimeout = 7*ic->ic_lintval; /* default 7 beacons */ - - ieee80211_node_attach(ifp); - ieee80211_proto_attach(ifp); -} - -void -ieee80211_ifdetach(struct ifnet *ifp) -{ - struct ieee80211com *ic = (void *)ifp; - - ieee80211_proto_detach(ifp); - ieee80211_crypto_detach(ifp); - ieee80211_node_detach(ifp); - ifmedia_removeall(&ic->ic_media); - ether_ifdetach(ifp); -} - -/* - * Convert MHz frequency to IEEE channel number. - */ -u_int -ieee80211_mhz2ieee(u_int freq, u_int flags) -{ - if (flags & IEEE80211_CHAN_2GHZ) { /* 2GHz band */ - if (freq == 2484) - return 14; - if (freq < 2484) - return (freq - 2407) / 5; - else - return 15 + ((freq - 2512) / 20); - } else if (flags & IEEE80211_CHAN_5GHZ) { /* 5Ghz band */ - return (freq - 5000) / 5; - } else { /* either, guess */ - if (freq == 2484) - return 14; - if (freq < 2484) - return (freq - 2407) / 5; - if (freq < 5000) - return 15 + ((freq - 2512) / 20); - return (freq - 5000) / 5; - } -} - -/* - * Convert channel to IEEE channel number. - */ -u_int -ieee80211_chan2ieee(struct ieee80211com *ic, struct ieee80211_channel *c) -{ - if (ic->ic_channels <= c && c <= &ic->ic_channels[IEEE80211_CHAN_MAX]) - return c - ic->ic_channels; - else if (c == IEEE80211_CHAN_ANYC) - return IEEE80211_CHAN_ANY; - else if (c != NULL) { - if_printf(&ic->ic_if, "invalid channel freq %u flags %x\n", - c->ic_freq, c->ic_flags); - return 0; /* XXX */ - } else { - if_printf(&ic->ic_if, "invalid channel (NULL)\n"); - return 0; /* XXX */ - } -} - -/* - * Convert IEEE channel number to MHz frequency. - */ -u_int -ieee80211_ieee2mhz(u_int chan, u_int flags) -{ - if (flags & IEEE80211_CHAN_2GHZ) { /* 2GHz band */ - if (chan == 14) - return 2484; - if (chan < 14) - return 2407 + chan*5; - else - return 2512 + ((chan-15)*20); - } else if (flags & IEEE80211_CHAN_5GHZ) {/* 5Ghz band */ - return 5000 + (chan*5); - } else { /* either, guess */ - if (chan == 14) - return 2484; - if (chan < 14) /* 0-13 */ - return 2407 + chan*5; - if (chan < 27) /* 15-26 */ - return 2512 + ((chan-15)*20); - return 5000 + (chan*5); - } -} - -/* - * Setup the media data structures according to the channel and - * rate tables. This must be called by the driver after - * ieee80211_attach and before most anything else. - */ -void -ieee80211_media_init(struct ifnet *ifp, - ifm_change_cb_t media_change, ifm_stat_cb_t media_stat) -{ -#define ADD(_ic, _s, _o) \ - ifmedia_add(&(_ic)->ic_media, \ - IFM_MAKEWORD(IFM_IEEE80211, (_s), (_o), 0), 0, NULL) - struct ieee80211com *ic = (void *)ifp; - struct ifmediareq imr; - int i, j, mode, rate, maxrate, mword, mopt, r; - struct ieee80211_rateset *rs; - struct ieee80211_rateset allrates; - - /* - * Do late attach work that must wait for any subclass - * (i.e. driver) work such as overriding methods. - */ - ieee80211_node_lateattach(ifp); - - /* - * Fill in media characteristics. - */ - ifmedia_init(&ic->ic_media, 0, media_change, media_stat); - maxrate = 0; - memset(&allrates, 0, sizeof(allrates)); - for (mode = IEEE80211_MODE_AUTO; mode < IEEE80211_MODE_MAX; mode++) { - static const u_int mopts[] = { - IFM_AUTO, - IFM_IEEE80211_11A, - IFM_IEEE80211_11B, - IFM_IEEE80211_11G, - IFM_IEEE80211_FH, - IFM_IEEE80211_11A | IFM_IEEE80211_TURBO, - }; - if ((ic->ic_modecaps & (1<ic_caps & IEEE80211_C_IBSS) - ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_ADHOC); - if (ic->ic_caps & IEEE80211_C_HOSTAP) - ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_HOSTAP); - if (ic->ic_caps & IEEE80211_C_AHDEMO) - ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_ADHOC | IFM_FLAG0); - if (ic->ic_caps & IEEE80211_C_MONITOR) - ADD(ic, IFM_AUTO, mopt | IFM_IEEE80211_MONITOR); - if (mode == IEEE80211_MODE_AUTO) - continue; - if_printf(ifp, "%s rates: ", ieee80211_phymode_name[mode]); - rs = &ic->ic_sup_rates[mode]; - for (i = 0; i < rs->rs_nrates; i++) { - rate = rs->rs_rates[i]; - mword = ieee80211_rate2media(ic, rate, mode); - if (mword == 0) - continue; - printf("%s%d%sMbps", (i != 0 ? " " : ""), - (rate & IEEE80211_RATE_VAL) / 2, - ((rate & 0x1) != 0 ? ".5" : "")); - ADD(ic, mword, mopt); - if (ic->ic_caps & IEEE80211_C_IBSS) - ADD(ic, mword, mopt | IFM_IEEE80211_ADHOC); - if (ic->ic_caps & IEEE80211_C_HOSTAP) - ADD(ic, mword, mopt | IFM_IEEE80211_HOSTAP); - if (ic->ic_caps & IEEE80211_C_AHDEMO) - ADD(ic, mword, mopt | IFM_IEEE80211_ADHOC | IFM_FLAG0); - if (ic->ic_caps & IEEE80211_C_MONITOR) - ADD(ic, mword, mopt | IFM_IEEE80211_MONITOR); - /* - * Add rate to the collection of all rates. - */ - r = rate & IEEE80211_RATE_VAL; - for (j = 0; j < allrates.rs_nrates; j++) - if (allrates.rs_rates[j] == r) - break; - if (j == allrates.rs_nrates) { - /* unique, add to the set */ - allrates.rs_rates[j] = r; - allrates.rs_nrates++; - } - rate = (rate & IEEE80211_RATE_VAL) / 2; - if (rate > maxrate) - maxrate = rate; - } - printf("\n"); - } - for (i = 0; i < allrates.rs_nrates; i++) { - mword = ieee80211_rate2media(ic, allrates.rs_rates[i], - IEEE80211_MODE_AUTO); - if (mword == 0) - continue; - mword = IFM_SUBTYPE(mword); /* remove media options */ - ADD(ic, mword, 0); - if (ic->ic_caps & IEEE80211_C_IBSS) - ADD(ic, mword, IFM_IEEE80211_ADHOC); - if (ic->ic_caps & IEEE80211_C_HOSTAP) - ADD(ic, mword, IFM_IEEE80211_HOSTAP); - if (ic->ic_caps & IEEE80211_C_AHDEMO) - ADD(ic, mword, IFM_IEEE80211_ADHOC | IFM_FLAG0); - if (ic->ic_caps & IEEE80211_C_MONITOR) - ADD(ic, mword, IFM_IEEE80211_MONITOR); - } - ieee80211_media_status(ifp, &imr); - ifmedia_set(&ic->ic_media, imr.ifm_active); - - if (maxrate) - ifp->if_baudrate = IF_Mbps(maxrate); -#undef ADD -} - -static int -findrate(struct ieee80211com *ic, enum ieee80211_phymode mode, int rate) -{ -#define IEEERATE(_ic,_m,_i) \ - ((_ic)->ic_sup_rates[_m].rs_rates[_i] & IEEE80211_RATE_VAL) - int i, nrates = ic->ic_sup_rates[mode].rs_nrates; - for (i = 0; i < nrates; i++) - if (IEEERATE(ic, mode, i) == rate) - return i; - return -1; -#undef IEEERATE -} - -/* - * Handle a media change request. - */ -int -ieee80211_media_change(struct ifnet *ifp) -{ - struct ieee80211com *ic = (void *)ifp; - struct ifmedia_entry *ime; - enum ieee80211_opmode newopmode; - enum ieee80211_phymode newphymode; - int i, j, newrate, error = 0; - - ime = ic->ic_media.ifm_cur; - /* - * First, identify the phy mode. - */ - switch (IFM_MODE(ime->ifm_media)) { - case IFM_IEEE80211_11A: - newphymode = IEEE80211_MODE_11A; - break; - case IFM_IEEE80211_11B: - newphymode = IEEE80211_MODE_11B; - break; - case IFM_IEEE80211_11G: - newphymode = IEEE80211_MODE_11G; - break; - case IFM_IEEE80211_FH: - newphymode = IEEE80211_MODE_FH; - break; - case IFM_AUTO: - newphymode = IEEE80211_MODE_AUTO; - break; - default: - return EINVAL; - } - /* - * Turbo mode is an ``option''. Eventually it - * needs to be applied to 11g too. - */ - if (ime->ifm_media & IFM_IEEE80211_TURBO) { - if (newphymode != IEEE80211_MODE_11A) - return EINVAL; - newphymode = IEEE80211_MODE_TURBO; - } - /* - * Validate requested mode is available. - */ - if ((ic->ic_modecaps & (1<ifm_media) != IFM_AUTO) { - /* - * Convert media subtype to rate. - */ - newrate = ieee80211_media2rate(ime->ifm_media); - if (newrate == 0) - return EINVAL; - /* - * Check the rate table for the specified/current phy. - */ - if (newphymode == IEEE80211_MODE_AUTO) { - /* - * In autoselect mode search for the rate. - */ - for (j = IEEE80211_MODE_11A; - j < IEEE80211_MODE_MAX; j++) { - if ((ic->ic_modecaps & (1<ifm_media & (IFM_IEEE80211_ADHOC|IFM_FLAG0)) == - (IFM_IEEE80211_ADHOC|IFM_FLAG0)) - newopmode = IEEE80211_M_AHDEMO; - else if (ime->ifm_media & IFM_IEEE80211_HOSTAP) - newopmode = IEEE80211_M_HOSTAP; - else if (ime->ifm_media & IFM_IEEE80211_ADHOC) - newopmode = IEEE80211_M_IBSS; - else if (ime->ifm_media & IFM_IEEE80211_MONITOR) - newopmode = IEEE80211_M_MONITOR; - else - newopmode = IEEE80211_M_STA; - - /* - * Autoselect doesn't make sense when operating as an AP. - * If no phy mode has been selected, pick one and lock it - * down so rate tables can be used in forming beacon frames - * and the like. - */ - if (newopmode == IEEE80211_M_HOSTAP && - newphymode == IEEE80211_MODE_AUTO) { - for (j = IEEE80211_MODE_11A; j < IEEE80211_MODE_MAX; j++) - if (ic->ic_modecaps & (1<ic_curmode != newphymode) { /* change phy mode */ - error = ieee80211_setmode(ic, newphymode); - if (error != 0) - return error; - error = ENETRESET; - } - - /* - * Committed to changes, install the rate setting. - */ - if (ic->ic_fixed_rate != i) { - ic->ic_fixed_rate = i; /* set fixed tx rate */ - error = ENETRESET; - } - - /* - * Handle operating mode change. - */ - if (ic->ic_opmode != newopmode) { - ic->ic_opmode = newopmode; - switch (newopmode) { - case IEEE80211_M_AHDEMO: - case IEEE80211_M_HOSTAP: - case IEEE80211_M_STA: - case IEEE80211_M_MONITOR: - ic->ic_flags &= ~IEEE80211_F_IBSSON; - break; - case IEEE80211_M_IBSS: - ic->ic_flags |= IEEE80211_F_IBSSON; -#ifdef notdef - if (ic->ic_curmode == IEEE80211_MODE_11G) - ieee80211_set11gbasicrates( - &ic->ic_suprates[newphymode], - IEEE80211_MODE_11B); -#endif - break; - } - error = ENETRESET; - } -#ifdef notdef - if (error == 0) - ifp->if_baudrate = ifmedia_baudrate(ime->ifm_media); -#endif - return error; -} - -void -ieee80211_media_status(struct ifnet *ifp, struct ifmediareq *imr) -{ - struct ieee80211com *ic = (void *)ifp; - struct ieee80211_node *ni = NULL; - int old_status = imr->ifm_status; - - imr->ifm_status = IFM_AVALID; - imr->ifm_active = IFM_IEEE80211; -/* XXX - if (ic->ic_state == IEEE80211_S_RUN) { - imr->ifm_status |= IFM_ACTIVE; - ifp->if_link_state = LINK_STATE_UP; - } else - ifp->if_link_state = LINK_STATE_DOWN; -*/ - imr->ifm_active |= IFM_AUTO; - switch (ic->ic_opmode) { - case IEEE80211_M_STA: - ni = ic->ic_bss; - /* calculate rate subtype */ - imr->ifm_active |= ieee80211_rate2media(ic, - ni->ni_rates.rs_rates[ni->ni_txrate], ic->ic_curmode); - break; - case IEEE80211_M_IBSS: - imr->ifm_active |= IFM_IEEE80211_ADHOC; - break; - case IEEE80211_M_AHDEMO: - /* should not come here */ - break; - case IEEE80211_M_HOSTAP: - imr->ifm_active |= IFM_IEEE80211_HOSTAP; - break; - case IEEE80211_M_MONITOR: - imr->ifm_active |= IFM_IEEE80211_MONITOR; - break; - } - switch (ic->ic_curmode) { - case IEEE80211_MODE_11A: - imr->ifm_active |= IFM_IEEE80211_11A; - break; - case IEEE80211_MODE_11B: - imr->ifm_active |= IFM_IEEE80211_11B; - break; - case IEEE80211_MODE_11G: - imr->ifm_active |= IFM_IEEE80211_11G; - break; - case IEEE80211_MODE_FH: - imr->ifm_active |= IFM_IEEE80211_FH; - break; - case IEEE80211_MODE_TURBO: - imr->ifm_active |= IFM_IEEE80211_11A - | IFM_IEEE80211_TURBO; - break; - } - - /* Notify that the link state has changed. */ - if (imr->ifm_status != old_status) - rt_ifmsg(ifp); -} - -void -ieee80211_watchdog(struct ifnet *ifp) -{ - struct ieee80211com *ic = (void *)ifp; - - if (ic->ic_mgt_timer && --ic->ic_mgt_timer == 0) - ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); - if (ic->ic_inact_timer && --ic->ic_inact_timer == 0) - ieee80211_timeout_nodes(ic); - - if (ic->ic_mgt_timer != 0 || ic->ic_inact_timer != 0) - ifp->if_timer = 1; -} - -/* - * Mark the basic rates for the 11g rate table based on the - * operating mode. For real 11g we mark all the 11b rates - * and 6, 12, and 24 OFDM. For 11b compatibility we mark only - * 11b rates. There's also a pseudo 11a-mode used to mark only - * the basic OFDM rates. - */ -static void -ieee80211_set11gbasicrates(struct ieee80211_rateset *rs, enum ieee80211_phymode mode) -{ - static const struct ieee80211_rateset basic[] = { - { 3, { 12, 24, 48 } }, /* IEEE80211_MODE_11A */ - { 4, { 2, 4, 11, 22 } }, /* IEEE80211_MODE_11B */ - { 7, { 2, 4, 11, 22, 12, 24, 48 } },/* IEEE80211_MODE_11G */ - { 0 }, /* IEEE80211_MODE_FH */ - { 0 }, /* IEEE80211_MODE_TURBO */ - }; - int i, j; - - for (i = 0; i < rs->rs_nrates; i++) { - rs->rs_rates[i] &= IEEE80211_RATE_VAL; - for (j = 0; j < basic[mode].rs_nrates; j++) - if (basic[mode].rs_rates[j] == rs->rs_rates[i]) { - rs->rs_rates[i] |= IEEE80211_RATE_BASIC; - break; - } - } -} - -/* - * Set the current phy mode and recalculate the active channel - * set based on the available channels for this mode. Also - * select a new default/current channel if the current one is - * inappropriate for this mode. - */ -int -ieee80211_setmode(struct ieee80211com *ic, enum ieee80211_phymode mode) -{ -#define N(a) (sizeof(a) / sizeof(a[0])) - static const u_int chanflags[] = { - 0, /* IEEE80211_MODE_AUTO */ - IEEE80211_CHAN_A, /* IEEE80211_MODE_11A */ - IEEE80211_CHAN_B, /* IEEE80211_MODE_11B */ - IEEE80211_CHAN_PUREG, /* IEEE80211_MODE_11G */ - IEEE80211_CHAN_FHSS, /* IEEE80211_MODE_FH */ - IEEE80211_CHAN_T, /* IEEE80211_MODE_TURBO */ - }; - struct ieee80211_channel *c; - u_int modeflags; - int i; - - /* validate new mode */ - if ((ic->ic_modecaps & (1<ic_modecaps)); - return EINVAL; - } - - /* - * Verify at least one channel is present in the available - * channel list before committing to the new mode. - */ - KASSERT(mode < N(chanflags), ("Unexpected mode %u", mode)); - modeflags = chanflags[mode]; - for (i = 0; i <= IEEE80211_CHAN_MAX; i++) { - c = &ic->ic_channels[i]; - if (mode == IEEE80211_MODE_AUTO) { - /* ignore turbo channels for autoselect */ - if ((c->ic_flags &~ IEEE80211_CHAN_TURBO) != 0) - break; - } else { - if ((c->ic_flags & modeflags) == modeflags) - break; - } - } - if (i > IEEE80211_CHAN_MAX) { - IEEE80211_DPRINTF(("%s: no channels found for mode %u\n", - __func__, mode)); - return EINVAL; - } - - /* - * Calculate the active channel set. - */ - memset(ic->ic_chan_active, 0, sizeof(ic->ic_chan_active)); - for (i = 0; i <= IEEE80211_CHAN_MAX; i++) { - c = &ic->ic_channels[i]; - if (mode == IEEE80211_MODE_AUTO) { - /* take anything but pure turbo channels */ - if ((c->ic_flags &~ IEEE80211_CHAN_TURBO) != 0) - setbit(ic->ic_chan_active, i); - } else { - if ((c->ic_flags & modeflags) == modeflags) - setbit(ic->ic_chan_active, i); - } - } - /* - * If no current/default channel is setup or the current - * channel is wrong for the mode then pick the first - * available channel from the active list. This is likely - * not the right one. - */ - if (ic->ic_ibss_chan == NULL || - isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, ic->ic_ibss_chan))) { - for (i = 0; i <= IEEE80211_CHAN_MAX; i++) - if (isset(ic->ic_chan_active, i)) { - ic->ic_ibss_chan = &ic->ic_channels[i]; - break; - } - } - - /* - * Set/reset state flags that influence beacon contents, etc. - * - * XXX what if we have stations already associated??? - * XXX probably not right for autoselect? - */ - if (ic->ic_caps & IEEE80211_C_SHPREAMBLE) - ic->ic_flags |= IEEE80211_F_SHPREAMBLE; - if (mode == IEEE80211_MODE_11G) { - if (ic->ic_caps & IEEE80211_C_SHSLOT) - ic->ic_flags |= IEEE80211_F_SHSLOT; - ieee80211_set11gbasicrates(&ic->ic_sup_rates[mode], - IEEE80211_MODE_11G); - } else { - ic->ic_flags &= ~IEEE80211_F_SHSLOT; - } - - ic->ic_curmode = mode; - return 0; -#undef N -} - -/* - * Return the phy mode for with the specified channel so the - * caller can select a rate set. This is problematic and the - * work here assumes how things work elsewhere in this code. - */ -enum ieee80211_phymode -ieee80211_chan2mode(struct ieee80211com *ic, struct ieee80211_channel *chan) -{ - /* - * NB: this assumes the channel would not be supplied to us - * unless it was already compatible with the current mode. - */ - if (ic->ic_curmode != IEEE80211_MODE_AUTO) - return ic->ic_curmode; - /* - * In autoselect mode; deduce a mode based on the channel - * characteristics. We assume that turbo-only channels - * are not considered when the channel set is constructed. - */ - if (IEEE80211_IS_CHAN_5GHZ(chan)) - return IEEE80211_MODE_11A; - else if (IEEE80211_IS_CHAN_FHSS(chan)) - return IEEE80211_MODE_FH; - else if (chan->ic_flags & (IEEE80211_CHAN_OFDM|IEEE80211_CHAN_DYN)) - return IEEE80211_MODE_11G; - else - return IEEE80211_MODE_11B; -} - -/* - * convert IEEE80211 rate value to ifmedia subtype. - * ieee80211 rate is in unit of 0.5Mbps. - */ -int -ieee80211_rate2media(struct ieee80211com *ic, int rate, enum ieee80211_phymode mode) -{ -#define N(a) (sizeof(a) / sizeof(a[0])) - static const struct { - u_int m; /* rate + mode */ - u_int r; /* if_media rate */ - } rates[] = { - { 2 | IFM_IEEE80211_FH, IFM_IEEE80211_FH1 }, - { 4 | IFM_IEEE80211_FH, IFM_IEEE80211_FH2 }, - { 2 | IFM_IEEE80211_11B, IFM_IEEE80211_DS1 }, - { 4 | IFM_IEEE80211_11B, IFM_IEEE80211_DS2 }, - { 11 | IFM_IEEE80211_11B, IFM_IEEE80211_DS5 }, - { 22 | IFM_IEEE80211_11B, IFM_IEEE80211_DS11 }, - { 44 | IFM_IEEE80211_11B, IFM_IEEE80211_DS22 }, - { 12 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM6 }, - { 18 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM9 }, - { 24 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM12 }, - { 36 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM18 }, - { 48 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM24 }, - { 72 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM36 }, - { 96 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM48 }, - { 108 | IFM_IEEE80211_11A, IFM_IEEE80211_OFDM54 }, - { 2 | IFM_IEEE80211_11G, IFM_IEEE80211_DS1 }, - { 4 | IFM_IEEE80211_11G, IFM_IEEE80211_DS2 }, - { 11 | IFM_IEEE80211_11G, IFM_IEEE80211_DS5 }, - { 22 | IFM_IEEE80211_11G, IFM_IEEE80211_DS11 }, - { 12 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM6 }, - { 18 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM9 }, - { 24 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM12 }, - { 36 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM18 }, - { 48 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM24 }, - { 72 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM36 }, - { 96 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM48 }, - { 108 | IFM_IEEE80211_11G, IFM_IEEE80211_OFDM54 }, - /* NB: OFDM72 doesn't realy exist so we don't handle it */ - }; - u_int mask, i; - - mask = rate & IEEE80211_RATE_VAL; - switch (mode) { - case IEEE80211_MODE_11A: - case IEEE80211_MODE_TURBO: - mask |= IFM_IEEE80211_11A; - break; - case IEEE80211_MODE_11B: - mask |= IFM_IEEE80211_11B; - break; - case IEEE80211_MODE_FH: - mask |= IFM_IEEE80211_FH; - break; - case IEEE80211_MODE_AUTO: - /* NB: ic may be NULL for some drivers */ - if (ic && ic->ic_phytype == IEEE80211_T_FH) { - mask |= IFM_IEEE80211_FH; - break; - } - /* NB: hack, 11g matches both 11b+11a rates */ - /* fall thru... */ - case IEEE80211_MODE_11G: - mask |= IFM_IEEE80211_11G; - break; - } - for (i = 0; i < N(rates); i++) - if (rates[i].m == mask) - return rates[i].r; - return IFM_AUTO; -#undef N -} - -int -ieee80211_media2rate(int mword) -{ -#define N(a) (sizeof(a) / sizeof(a[0])) - static const int ieeerates[] = { - -1, /* IFM_AUTO */ - 0, /* IFM_MANUAL */ - 0, /* IFM_NONE */ - 2, /* IFM_IEEE80211_FH1 */ - 4, /* IFM_IEEE80211_FH2 */ - 2, /* IFM_IEEE80211_DS1 */ - 4, /* IFM_IEEE80211_DS2 */ - 11, /* IFM_IEEE80211_DS5 */ - 22, /* IFM_IEEE80211_DS11 */ - 44, /* IFM_IEEE80211_DS22 */ - 12, /* IFM_IEEE80211_OFDM6 */ - 18, /* IFM_IEEE80211_OFDM9 */ - 24, /* IFM_IEEE80211_OFDM12 */ - 36, /* IFM_IEEE80211_OFDM18 */ - 48, /* IFM_IEEE80211_OFDM24 */ - 72, /* IFM_IEEE80211_OFDM36 */ - 96, /* IFM_IEEE80211_OFDM48 */ - 108, /* IFM_IEEE80211_OFDM54 */ - 144, /* IFM_IEEE80211_OFDM72 */ - }; - return IFM_SUBTYPE(mword) < N(ieeerates) ? - ieeerates[IFM_SUBTYPE(mword)] : 0; -#undef N -} - -/* - * Module glue. - * - * NB: the module name is "wlan" for compatibility with NetBSD. - */ - -static int -ieee80211_modevent(module_t mod, int type, void *unused) -{ - switch (type) { - case MOD_LOAD: - if (bootverbose) - printf("wlan: <802.11 Link Layer>\n"); - return 0; - case MOD_UNLOAD: - case MOD_SHUTDOWN: - return 0; - } - return EINVAL; -} - -static moduledata_t ieee80211_mod = { - "wlan", - ieee80211_modevent, - 0 -}; -DECLARE_MODULE(wlan, ieee80211_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST); -MODULE_VERSION(wlan, 1); -MODULE_DEPEND(wlan, crypto, 1, 1, 1); diff --git a/sys/netproto/802_11/ieee80211_crypto.c b/sys/netproto/802_11/ieee80211_crypto.c deleted file mode 100644 index c6626eaa1b..0000000000 --- a/sys/netproto/802_11/ieee80211_crypto.c +++ /dev/null @@ -1,322 +0,0 @@ -/* - * Copyright (c) 2001 Atsushi Onoe - * Copyright (c) 2002, 2003 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. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * 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. - * - * $FreeBSD: src/sys/net80211/ieee80211_crypto.c,v 1.3 2003/10/17 23:15:30 sam Exp $ - * $DragonFly: src/sys/netproto/802_11/Attic/ieee80211_crypto.c,v 1.2 2005/06/08 23:29:29 hsu Exp $ - */ - -#include "opt_inet.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include - -#ifdef INET -#include -#include -#endif - -#include -#define arc4_ctxlen() sizeof (struct rc4_state) -#define arc4_setkey(_c,_k,_l) rc4_init(_c,_k,_l) -#define arc4_encrypt(_c,_d,_s,_l) rc4_crypt(_c,_s,_d,_l) - -static void ieee80211_crc_init(void); -static uint32_t ieee80211_crc_update(uint32_t crc, uint8_t *buf, int len); - -void -ieee80211_crypto_attach(struct ifnet *ifp) -{ - struct ieee80211com *ic = (void *)ifp; - - /* - * Setup crypto support. - */ - ieee80211_crc_init(); - ic->ic_iv = arc4random(); -} - -void -ieee80211_crypto_detach(struct ifnet *ifp) -{ - struct ieee80211com *ic = (void *)ifp; - - if (ic->ic_wep_ctx != NULL) { - free(ic->ic_wep_ctx, M_DEVBUF); - ic->ic_wep_ctx = NULL; - } -} - -struct mbuf * -ieee80211_wep_crypt(struct ifnet *ifp, struct mbuf *m0, int txflag) -{ - struct ieee80211com *ic = (void *)ifp; - struct mbuf *m, *n, *n0; - struct ieee80211_frame *wh; - int i, left, len, moff, noff, kid; - uint32_t iv, crc; - uint8_t *ivp; - void *ctx; - uint8_t keybuf[IEEE80211_WEP_IVLEN + IEEE80211_KEYBUF_SIZE]; - uint8_t crcbuf[IEEE80211_WEP_CRCLEN]; - - n0 = NULL; - if ((ctx = ic->ic_wep_ctx) == NULL) { - ctx = malloc(arc4_ctxlen(), M_DEVBUF, M_NOWAIT | M_ZERO); /* XXX */ - if (ctx == NULL) { - ic->ic_stats.is_crypto_nomem++; - goto fail; - } - ic->ic_wep_ctx = ctx; - } - m = m0; - left = m->m_pkthdr.len; - MGETHDR(n, MB_DONTWAIT, m->m_type); - n0 = n; - if (n == NULL) { - if (txflag) - ic->ic_stats.is_tx_nombuf++; - else - ic->ic_stats.is_rx_nombuf++; - goto fail; - } - M_MOVE_PKTHDR(n, m); - len = IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN + IEEE80211_WEP_CRCLEN; - if (txflag) { - n->m_pkthdr.len += len; - } else { - n->m_pkthdr.len -= len; - left -= len; - } - n->m_len = MHLEN; - if (n->m_pkthdr.len >= MINCLSIZE) { - MCLGET(n, MB_DONTWAIT); - if (n->m_flags & M_EXT) - n->m_len = n->m_ext.ext_size; - } - len = sizeof(struct ieee80211_frame); - memcpy(mtod(n, caddr_t), mtod(m, caddr_t), len); - wh = mtod(n, struct ieee80211_frame *); - left -= len; - moff = len; - noff = len; - if (txflag) { - kid = ic->ic_wep_txkey; - wh->i_fc[1] |= IEEE80211_FC1_WEP; - iv = ic->ic_iv; - /* - * Skip 'bad' IVs from Fluhrer/Mantin/Shamir: - * (B, 255, N) with 3 <= B < 8 - */ - if (iv >= 0x03ff00 && - (iv & 0xf8ff00) == 0x00ff00) - iv += 0x000100; - ic->ic_iv = iv + 1; - /* put iv in little endian to prepare 802.11i */ - ivp = mtod(n, uint8_t *) + noff; - for (i = 0; i < IEEE80211_WEP_IVLEN; i++) { - ivp[i] = iv & 0xff; - iv >>= 8; - } - ivp[IEEE80211_WEP_IVLEN] = kid << 6; /* pad and keyid */ - noff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN; - } else { - wh->i_fc[1] &= ~IEEE80211_FC1_WEP; - ivp = mtod(m, uint8_t *) + moff; - kid = ivp[IEEE80211_WEP_IVLEN] >> 6; - moff += IEEE80211_WEP_IVLEN + IEEE80211_WEP_KIDLEN; - } - memcpy(keybuf, ivp, IEEE80211_WEP_IVLEN); - memcpy(keybuf + IEEE80211_WEP_IVLEN, ic->ic_nw_keys[kid].wk_key, - ic->ic_nw_keys[kid].wk_len); - arc4_setkey(ctx, keybuf, - IEEE80211_WEP_IVLEN + ic->ic_nw_keys[kid].wk_len); - - /* encrypt with calculating CRC */ - crc = ~0; - while (left > 0) { - len = m->m_len - moff; - if (len == 0) { - m = m->m_next; - moff = 0; - continue; - } - if (len > n->m_len - noff) { - len = n->m_len - noff; - if (len == 0) { - MGET(n->m_next, MB_DONTWAIT, n->m_type); - if (n->m_next == NULL) { - if (txflag) - ic->ic_stats.is_tx_nombuf++; - else - ic->ic_stats.is_rx_nombuf++; - goto fail; - } - n = n->m_next; - n->m_len = MLEN; - if (left >= MINCLSIZE) { - MCLGET(n, MB_DONTWAIT); - if (n->m_flags & M_EXT) - n->m_len = n->m_ext.ext_size; - } - noff = 0; - continue; - } - } - if (len > left) - len = left; - arc4_encrypt(ctx, mtod(n, caddr_t) + noff, - mtod(m, caddr_t) + moff, len); - if (txflag) - crc = ieee80211_crc_update(crc, - mtod(m, uint8_t *) + moff, len); - else - crc = ieee80211_crc_update(crc, - mtod(n, uint8_t *) + noff, len); - left -= len; - moff += len; - noff += len; - } - crc = ~crc; - if (txflag) { - *(uint32_t *)crcbuf = htole32(crc); - if (n->m_len >= noff + sizeof(crcbuf)) - n->m_len = noff + sizeof(crcbuf); - else { - n->m_len = noff; - MGET(n->m_next, MB_DONTWAIT, n->m_type); - if (n->m_next == NULL) { - ic->ic_stats.is_tx_nombuf++; - goto fail; - } - n = n->m_next; - n->m_len = sizeof(crcbuf); - noff = 0; - } - arc4_encrypt(ctx, mtod(n, caddr_t) + noff, crcbuf, - sizeof(crcbuf)); - } else { - n->m_len = noff; - for (noff = 0; noff < sizeof(crcbuf); noff += len) { - len = sizeof(crcbuf) - noff; - if (len > m->m_len - moff) - len = m->m_len - moff; - if (len > 0) - arc4_encrypt(ctx, crcbuf + noff, - mtod(m, caddr_t) + moff, len); - m = m->m_next; - moff = 0; - } - if (crc != le32toh(*(uint32_t *)crcbuf)) { -#ifdef IEEE80211_DEBUG - if (ieee80211_debug) { - if_printf(ifp, "decrypt CRC error\n"); - if (ieee80211_debug > 1) - ieee80211_dump_pkt(n0->m_data, - n0->m_len, -1, -1); - } -#endif - ic->ic_stats.is_rx_decryptcrc++; - goto fail; - } - } - m_freem(m0); - return n0; - - fail: - m_freem(m0); - m_freem(n0); - return NULL; -} - -/* - * CRC 32 -- routine from RFC 2083 - */ - -/* Table of CRCs of all 8-bit messages */ -static uint32_t ieee80211_crc_table[256]; - -/* Make the table for a fast CRC. */ -static void -ieee80211_crc_init(void) -{ - uint32_t c; - int n, k; - - for (n = 0; n < 256; n++) { - c = (uint32_t)n; - for (k = 0; k < 8; k++) { - if (c & 1) - c = 0xedb88320UL ^ (c >> 1); - else - c = c >> 1; - } - ieee80211_crc_table[n] = c; - } -} - -/* - * Update a running CRC with the bytes buf[0..len-1]--the CRC - * should be initialized to all 1's, and the transmitted value - * is the 1's complement of the final running CRC - */ - -static uint32_t -ieee80211_crc_update(uint32_t crc, uint8_t *buf, int len) -{ - uint8_t *endbuf; - - for (endbuf = buf + len; buf < endbuf; buf++) - crc = ieee80211_crc_table[(crc ^ *buf) & 0xff] ^ (crc >> 8); - return crc; -} diff --git a/sys/netproto/802_11/ieee80211_input.c b/sys/netproto/802_11/ieee80211_input.c deleted file mode 100644 index 88d09f653d..0000000000 --- a/sys/netproto/802_11/ieee80211_input.c +++ /dev/null @@ -1,1186 +0,0 @@ -/* - * Copyright (c) 2001 Atsushi Onoe - * Copyright (c) 2002, 2003 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. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * 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. - * - * $FreeBSD: src/sys/net80211/ieee80211_input.c,v 1.21 2004/06/13 17:29:09 mlaier Exp $ - * $DragonFly: src/sys/netproto/802_11/Attic/ieee80211_input.c,v 1.3 2005/11/28 17:13:46 dillon Exp $ - */ - -#include "opt_inet.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include - -#ifdef INET -#include -#include -#endif - -/* - * Process a received frame. The node associated with the sender - * should be supplied. If nothing was found in the node table then - * the caller is assumed to supply a reference to ic_bss instead. - * The RSSI and a timestamp are also supplied. The RSSI data is used - * during AP scanning to select a AP to associate with; it can have - * any units so long as values have consistent units and higher values - * mean ``better signal''. The receive timestamp is currently not used - * by the 802.11 layer. - */ -void -ieee80211_input(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node *ni, - int rssi, uint32_t rstamp) -{ - struct ieee80211com *ic = (void *)ifp; - struct ieee80211_frame *wh; - struct ether_header *eh; - struct mbuf *m1; - int len; - uint8_t dir, type, subtype; - uint8_t *bssid; - uint16_t rxseq; - - KASSERT(ni != NULL, ("null node")); - -#ifdef M_HASFCS - /* trim CRC here so WEP can find its own CRC at the end of packet. */ - if (m->m_flags & M_HASFCS) { - m_adj(m, -IEEE80211_CRC_LEN); - m->m_flags &= ~M_HASFCS; - } -#endif - KASSERT(m->m_pkthdr.len >= sizeof(struct ieee80211_frame_min), - ("frame length too short: %u", m->m_pkthdr.len)); - - /* - * In monitor mode, send everything directly to bpf. - * XXX may want to include the CRC - */ - if (ic->ic_opmode == IEEE80211_M_MONITOR) - goto out; - - wh = mtod(m, struct ieee80211_frame *); - if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) != - IEEE80211_FC0_VERSION_0) { - if (ifp->if_flags & IFF_DEBUG) - if_printf(ifp, "receive packet with wrong version: %x\n", - wh->i_fc[0]); - ic->ic_stats.is_rx_badversion++; - goto err; - } - - dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK; - type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; - /* - * NB: We are not yet prepared to handle control frames, - * but permitting drivers to send them to us allows - * them to go through bpf tapping at the 802.11 layer. - */ - if (m->m_pkthdr.len < sizeof(struct ieee80211_frame)) { - /* XXX statistic */ - IEEE80211_DPRINTF2(("%s: frame too short, len %u\n", - __func__, m->m_pkthdr.len)); - ic->ic_stats.is_rx_tooshort++; - goto out; /* XXX */ - } - if (ic->ic_state != IEEE80211_S_SCAN) { - switch (ic->ic_opmode) { - case IEEE80211_M_STA: - if (!IEEE80211_ADDR_EQ(wh->i_addr2, ni->ni_bssid)) { - /* not interested in */ - IEEE80211_DPRINTF2(("%s: discard frame from " - "bss %6D\n", __func__, - wh->i_addr2, ":")); - ic->ic_stats.is_rx_wrongbss++; - goto out; - } - break; - case IEEE80211_M_IBSS: - case IEEE80211_M_AHDEMO: - case IEEE80211_M_HOSTAP: - if (dir == IEEE80211_FC1_DIR_NODS) - bssid = wh->i_addr3; - else - bssid = wh->i_addr1; - if (!IEEE80211_ADDR_EQ(bssid, ic->ic_bss->ni_bssid) && - !IEEE80211_ADDR_EQ(bssid, ifp->if_broadcastaddr)) { - /* not interested in */ - IEEE80211_DPRINTF2(("%s: discard frame from " - "bss %6D\n", __func__, - bssid, ":")); - ic->ic_stats.is_rx_wrongbss++; - goto out; - } - break; - case IEEE80211_M_MONITOR: - goto out; - default: - /* XXX catch bad values */ - break; - } - ni->ni_rssi = rssi; - ni->ni_rstamp = rstamp; - rxseq = ni->ni_rxseq; - ni->ni_rxseq = - le16toh(*(uint16_t *)wh->i_seq) >> IEEE80211_SEQ_SEQ_SHIFT; - /* TODO: fragment */ - if ((wh->i_fc[1] & IEEE80211_FC1_RETRY) && - rxseq == ni->ni_rxseq) { - /* duplicate, silently discarded */ - ic->ic_stats.is_rx_dup++; /* XXX per-station stat */ - goto out; - } - ni->ni_inact = 0; - } - - switch (type) { - case IEEE80211_FC0_TYPE_DATA: - switch (ic->ic_opmode) { - case IEEE80211_M_STA: - if (dir != IEEE80211_FC1_DIR_FROMDS) { - ic->ic_stats.is_rx_wrongdir++; - goto out; - } - if ((ifp->if_flags & IFF_SIMPLEX) && - IEEE80211_IS_MULTICAST(wh->i_addr1) && - IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_myaddr)) { - /* - * In IEEE802.11 network, multicast packet - * sent from me is broadcasted from AP. - * It should be silently discarded for - * SIMPLEX interface. - */ - ic->ic_stats.is_rx_mcastecho++; - goto out; - } - break; - case IEEE80211_M_IBSS: - case IEEE80211_M_AHDEMO: - if (dir != IEEE80211_FC1_DIR_NODS) { - ic->ic_stats.is_rx_wrongdir++; - goto out; - } - break; - case IEEE80211_M_HOSTAP: - if (dir != IEEE80211_FC1_DIR_TODS) { - ic->ic_stats.is_rx_wrongdir++; - goto out; - } - /* check if source STA is associated */ - if (ni == ic->ic_bss) { - IEEE80211_DPRINTF(("%s: data from unknown src " - "%6D\n", __func__, - wh->i_addr2, ":")); - /* NB: caller deals with reference */ - ni = ieee80211_dup_bss(ic, wh->i_addr2); - if (ni != NULL) { - IEEE80211_SEND_MGMT(ic, ni, - IEEE80211_FC0_SUBTYPE_DEAUTH, - IEEE80211_REASON_NOT_AUTHED); - ieee80211_free_node(ic, ni); - } - ic->ic_stats.is_rx_notassoc++; - goto err; - } - if (ni->ni_associd == 0) { - IEEE80211_DPRINTF(("ieee80211_input: " - "data from unassoc src %6D\n", - wh->i_addr2, ":")); - IEEE80211_SEND_MGMT(ic, ni, - IEEE80211_FC0_SUBTYPE_DISASSOC, - IEEE80211_REASON_NOT_ASSOCED); - ieee80211_unref_node(&ni); - ic->ic_stats.is_rx_notassoc++; - goto err; - } - break; - case IEEE80211_M_MONITOR: - break; - } - if (wh->i_fc[1] & IEEE80211_FC1_WEP) { - if (ic->ic_flags & IEEE80211_F_WEPON) { - m = ieee80211_wep_crypt(ifp, m, 0); - if (m == NULL) { - ic->ic_stats.is_rx_wepfail++; - goto err; - } - wh = mtod(m, struct ieee80211_frame *); - } else { - ic->ic_stats.is_rx_nowep++; - goto out; - } - } - /* copy to listener after decrypt */ - if (ic->ic_rawbpf != NULL) - bpf_mtap(ic->ic_rawbpf, m); - - m = ieee80211_decap(ifp, m); - if (m == NULL) { - ic->ic_stats.is_rx_decap++; - goto err; - } - ifp->if_ipackets++; - - /* perform as a bridge within the AP */ - m1 = NULL; - if (ic->ic_opmode == IEEE80211_M_HOSTAP) { - eh = mtod(m, struct ether_header *); - if (ETHER_IS_MULTICAST(eh->ether_dhost)) { - m1 = m_copypacket(m, MB_DONTWAIT); - if (m1 == NULL) - ifp->if_oerrors++; - else - m1->m_flags |= M_MCAST; - } else { - ni = ieee80211_find_node(ic, eh->ether_dhost); - if (ni != NULL) { - if (ni->ni_associd != 0) { - m1 = m; - m = NULL; - } - ieee80211_free_node(ic, ni); - } - } - if (m1 != NULL) { - len = m1->m_pkthdr.len; - IF_ENQUEUE(&ifp->if_snd, m1); - if (m != NULL) - ifp->if_omcasts++; - ifp->if_obytes += len; - } - } - if (m != NULL) - ifp->if_input(ifp, m); - return; - - case IEEE80211_FC0_TYPE_MGT: - if (dir != IEEE80211_FC1_DIR_NODS) { - ic->ic_stats.is_rx_wrongdir++; - goto err; - } - if (ic->ic_opmode == IEEE80211_M_AHDEMO) { - ic->ic_stats.is_rx_ahdemo_mgt++; - goto out; - } - subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; - - /* drop frames without interest */ - if (ic->ic_state == IEEE80211_S_SCAN) { - if (subtype != IEEE80211_FC0_SUBTYPE_BEACON && - subtype != IEEE80211_FC0_SUBTYPE_PROBE_RESP) { - ic->ic_stats.is_rx_mgtdiscard++; - goto out; - } - } else { - if (ic->ic_opmode != IEEE80211_M_IBSS && - subtype == IEEE80211_FC0_SUBTYPE_BEACON) { - ic->ic_stats.is_rx_mgtdiscard++; - goto out; - } - } - - if (ifp->if_flags & IFF_DEBUG) { - /* avoid to print too many frames */ - int doprint = 0; - - switch (subtype) { - case IEEE80211_FC0_SUBTYPE_BEACON: - if (ic->ic_state == IEEE80211_S_SCAN) - doprint = 1; - break; - case IEEE80211_FC0_SUBTYPE_PROBE_REQ: - if (ic->ic_opmode == IEEE80211_M_IBSS) - doprint = 1; - break; - default: - doprint = 1; - break; - } -#ifdef IEEE80211_DEBUG - doprint += ieee80211_debug; -#endif - if (doprint) - if_printf(ifp, "received %s from %6D rssi %d\n", - ieee80211_mgt_subtype_name[subtype - >> IEEE80211_FC0_SUBTYPE_SHIFT], - wh->i_addr2, ":", rssi); - } - if (ic->ic_rawbpf != NULL) - bpf_mtap(ic->ic_rawbpf, m); - (*ic->ic_recv_mgmt)(ic, m, ni, subtype, rssi, rstamp); - m_freem(m); - return; - - case IEEE80211_FC0_TYPE_CTL: - ic->ic_stats.is_rx_ctl++; - goto out; - default: - IEEE80211_DPRINTF(("%s: bad type %x\n", __func__, type)); - /* should not come here */ - break; - } - err: - ifp->if_ierrors++; - out: - if (m != NULL) { - if (ic->ic_rawbpf != NULL) - bpf_mtap(ic->ic_rawbpf, m); - m_freem(m); - } -} - -struct mbuf * -ieee80211_decap(struct ifnet *ifp, struct mbuf *m) -{ - struct ether_header *eh; - struct ieee80211_frame wh; - struct llc *llc; - - if (m->m_len < sizeof(wh) + sizeof(*llc)) { - m = m_pullup(m, sizeof(wh) + sizeof(*llc)); - if (m == NULL) - return NULL; - } - memcpy(&wh, mtod(m, caddr_t), sizeof(wh)); - llc = (struct llc *)(mtod(m, caddr_t) + sizeof(wh)); - if (llc->llc_dsap == LLC_SNAP_LSAP && llc->llc_ssap == LLC_SNAP_LSAP && - llc->llc_control == LLC_UI && llc->llc_snap.org_code[0] == 0 && - llc->llc_snap.org_code[1] == 0 && llc->llc_snap.org_code[2] == 0) { - m_adj(m, sizeof(wh) + sizeof(struct llc) - sizeof(*eh)); - llc = NULL; - } else { - m_adj(m, sizeof(wh) - sizeof(*eh)); - } - eh = mtod(m, struct ether_header *); - switch (wh.i_fc[1] & IEEE80211_FC1_DIR_MASK) { - case IEEE80211_FC1_DIR_NODS: - IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr1); - IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr2); - break; - case IEEE80211_FC1_DIR_TODS: - IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr3); - IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr2); - break; - case IEEE80211_FC1_DIR_FROMDS: - IEEE80211_ADDR_COPY(eh->ether_dhost, wh.i_addr1); - IEEE80211_ADDR_COPY(eh->ether_shost, wh.i_addr3); - break; - case IEEE80211_FC1_DIR_DSTODS: - /* not yet supported */ - IEEE80211_DPRINTF(("%s: DS to DS\n", __func__)); - m_freem(m); - return NULL; - } -#ifdef ALIGNED_POINTER - if (!ALIGNED_POINTER(mtod(m, caddr_t) + sizeof(*eh), uint32_t)) { - struct mbuf *n, *n0, **np; - caddr_t newdata; - int off, pktlen; - - n0 = NULL; - np = &n0; - off = 0; - pktlen = m->m_pkthdr.len; - while (pktlen > off) { - if (n0 == NULL) { - MGETHDR(n, MB_DONTWAIT, MT_DATA); - if (n == NULL) { - m_freem(m); - return NULL; - } - M_MOVE_PKTHDR(n, m); - n->m_len = MHLEN; - } else { - MGET(n, MB_DONTWAIT, MT_DATA); - if (n == NULL) { - m_freem(m); - m_freem(n0); - return NULL; - } - n->m_len = MLEN; - } - if (pktlen - off >= MINCLSIZE) { - MCLGET(n, MB_DONTWAIT); - if (n->m_flags & M_EXT) - n->m_len = n->m_ext.ext_size; - } - if (n0 == NULL) { - newdata = - (caddr_t)ALIGN(n->m_data + sizeof(*eh)) - - sizeof(*eh); - n->m_len -= newdata - n->m_data; - n->m_data = newdata; - } - if (n->m_len > pktlen - off) - n->m_len = pktlen - off; - m_copydata(m, off, n->m_len, mtod(n, caddr_t)); - off += n->m_len; - *np = n; - np = &n->m_next; - } - m_freem(m); - m = n0; - } -#endif /* ALIGNED_POINTER */ - if (llc != NULL) { - eh = mtod(m, struct ether_header *); - eh->ether_type = htons(m->m_pkthdr.len - sizeof(*eh)); - } - return m; -} - -/* - * Install received rate set information in the node's state block. - */ -static int -ieee80211_setup_rates(struct ieee80211com *ic, struct ieee80211_node *ni, - uint8_t *rates, uint8_t *xrates, int flags) -{ - struct ieee80211_rateset *rs = &ni->ni_rates; - - memset(rs, 0, sizeof(*rs)); - rs->rs_nrates = rates[1]; - memcpy(rs->rs_rates, rates + 2, rs->rs_nrates); - if (xrates != NULL) { - uint8_t nxrates; - /* - * Tack on 11g extended supported rate element. - */ - nxrates = xrates[1]; - if (rs->rs_nrates + nxrates > IEEE80211_RATE_MAXSIZE) { - nxrates = IEEE80211_RATE_MAXSIZE - rs->rs_nrates; - IEEE80211_DPRINTF(("%s: extended rate set too large;" - " only using %u of %u rates\n", - __func__, nxrates, xrates[1])); - ic->ic_stats.is_rx_rstoobig++; - } - memcpy(rs->rs_rates + rs->rs_nrates, xrates+2, nxrates); - rs->rs_nrates += nxrates; - } - return ieee80211_fix_rate(ic, ni, flags); -} - -/* Verify the existence and length of __elem or get out. */ -#define IEEE80211_VERIFY_ELEMENT(__elem, __maxlen) do { \ - if ((__elem) == NULL) { \ - IEEE80211_DPRINTF(("%s: no " #__elem "in %s frame\n", \ - __func__, ieee80211_mgt_subtype_name[subtype >> \ - IEEE80211_FC0_SUBTYPE_SHIFT])); \ - ic->ic_stats.is_rx_elem_missing++; \ - return; \ - } \ - if ((__elem)[1] > (__maxlen)) { \ - IEEE80211_DPRINTF(("%s: bad " #__elem " len %d in %s " \ - "frame from %6D\n", __func__, (__elem)[1], \ - ieee80211_mgt_subtype_name[subtype >> \ - IEEE80211_FC0_SUBTYPE_SHIFT], \ - wh->i_addr2, ":")); \ - ic->ic_stats.is_rx_elem_toobig++; \ - return; \ - } \ -} while (0) - -#define IEEE80211_VERIFY_LENGTH(_len, _minlen) do { \ - if ((_len) < (_minlen)) { \ - IEEE80211_DPRINTF(("%s: %s frame too short from %6D\n", \ - __func__, \ - ieee80211_mgt_subtype_name[subtype >> \ - IEEE80211_FC0_SUBTYPE_SHIFT], \ - wh->i_addr2, ":")); \ - ic->ic_stats.is_rx_elem_toosmall++; \ - return; \ - } \ -} while (0) - -void -ieee80211_recv_mgmt(struct ieee80211com *ic, struct mbuf *m0, - struct ieee80211_node *ni, - int subtype, int rssi, uint32_t rstamp) -{ - struct ifnet *ifp = &ic->ic_if; - struct ieee80211_frame *wh; - uint8_t *frm, *efrm; - uint8_t *ssid, *rates, *xrates; - int reassoc, resp, newassoc, allocbs; - - wh = mtod(m0, struct ieee80211_frame *); - frm = (uint8_t *)&wh[1]; - efrm = mtod(m0, uint8_t *) + m0->m_len; - switch (subtype) { - case IEEE80211_FC0_SUBTYPE_PROBE_RESP: - case IEEE80211_FC0_SUBTYPE_BEACON: { - uint8_t *tstamp, *bintval, *capinfo, *country; - uint8_t chan, bchan, fhindex, erp; - uint16_t fhdwell; - int isprobe; - - if (ic->ic_opmode != IEEE80211_M_IBSS && - ic->ic_state != IEEE80211_S_SCAN) { - /* XXX: may be useful for background scan */ - return; - } - isprobe = (subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP); - - /* - * beacon/probe response frame format - * [8] time stamp - * [2] beacon interval - * [2] capability information - * [tlv] ssid - * [tlv] supported rates - * [tlv] country information - * [tlv] parameter set (FH/DS) - * [tlv] erp information - * [tlv] extended supported rates - */ - IEEE80211_VERIFY_LENGTH(efrm - frm, 12); - tstamp = frm; frm += 8; - bintval = frm; frm += 2; - capinfo = frm; frm += 2; - ssid = rates = xrates = country = NULL; - bchan = ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan); - chan = bchan; - fhdwell = 0; - fhindex = 0; - erp = 0; - while (frm < efrm) { - switch (*frm) { - case IEEE80211_ELEMID_SSID: - ssid = frm; - break; - case IEEE80211_ELEMID_RATES: - rates = frm; - break; - case IEEE80211_ELEMID_COUNTRY: - country = frm; - break; - case IEEE80211_ELEMID_FHPARMS: - if (ic->ic_phytype == IEEE80211_T_FH) { - fhdwell = (frm[3] << 8) | frm[2]; - chan = IEEE80211_FH_CHAN(frm[4], frm[5]); - fhindex = frm[6]; - } - break; - case IEEE80211_ELEMID_DSPARMS: - /* - * XXX hack this since depending on phytype - * is problematic for multi-mode devices. - */ - if (ic->ic_phytype != IEEE80211_T_FH) - chan = frm[2]; - break; - case IEEE80211_ELEMID_TIM: - break; - case IEEE80211_ELEMID_IBSSPARMS: - break; - case IEEE80211_ELEMID_XRATES: - xrates = frm; - break; - case IEEE80211_ELEMID_ERP: - if (frm[1] != 1) { - IEEE80211_DPRINTF(("%s: invalid ERP " - "element; length %u, expecting " - "1\n", __func__, frm[1])); - ic->ic_stats.is_rx_elem_toobig++; - break; - } - erp = frm[2]; - break; - default: - IEEE80211_DPRINTF2(("%s: element id %u/len %u " - "ignored\n", __func__, *frm, frm[1])); - ic->ic_stats.is_rx_elem_unknown++; - break; - } - frm += frm[1] + 2; - } - IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE); - IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN); - if ( -#if IEEE80211_CHAN_MAX < 255 - chan > IEEE80211_CHAN_MAX || -#endif - isclr(ic->ic_chan_active, chan)) { - IEEE80211_DPRINTF(("%s: ignore %s with invalid channel " - "%u\n", __func__, - isprobe ? "probe response" : "beacon", - chan)); - ic->ic_stats.is_rx_badchan++; - return; - } - if (chan != bchan && ic->ic_phytype != IEEE80211_T_FH) { - /* - * Frame was received on a channel different from the - * one indicated in the DS params element id; - * silently discard it. - * - * NB: this can happen due to signal leakage. - * But we should take it for FH phy because - * the rssi value should be correct even for - * different hop pattern in FH. - */ - IEEE80211_DPRINTF(("%s: ignore %s on channel %u marked " - "for channel %u\n", __func__, - isprobe ? "probe response" : "beacon", - bchan, chan)); - ic->ic_stats.is_rx_chanmismatch++; - return; - } - - /* - * Use mac and channel for lookup so we collect all - * potential AP's when scanning. Otherwise we may - * see the same AP on multiple channels and will only - * record the last one. We could filter APs here based - * on rssi, etc. but leave that to the end of the scan - * so we can keep the selection criteria in one spot. - * This may result in a bloat of the scanned AP list but - * it shouldn't be too much. - */ - ni = ieee80211_lookup_node(ic, wh->i_addr2, - &ic->ic_channels[chan]); -#ifdef IEEE80211_DEBUG - if (ieee80211_debug && - (ni == NULL || ic->ic_state == IEEE80211_S_SCAN)) { - printf("%s: %s%s on chan %u (bss chan %u) ", - __func__, (ni == NULL ? "new " : ""), - isprobe ? "probe response" : "beacon", - chan, bchan); - ieee80211_print_essid(ssid + 2, ssid[1]); - printf(" from %6D\n", wh->i_addr2, ":"); - printf("%s: caps 0x%x bintval %u erp 0x%x\n", - __func__, le16toh(*(uint16_t *)capinfo), - le16toh(*(uint16_t *)bintval), erp); - if (country) - printf("%s: country info %*D\n", - __func__, country[1], country+2, " "); - } -#endif - if (ni == NULL) { - ni = ieee80211_alloc_node(ic, wh->i_addr2); - if (ni == NULL) - return; - ni->ni_esslen = ssid[1]; - memset(ni->ni_essid, 0, sizeof(ni->ni_essid)); - memcpy(ni->ni_essid, ssid + 2, ssid[1]); - allocbs = 1; - } else if (ssid[1] != 0 && isprobe) { - /* - * Update ESSID at probe response to adopt hidden AP by - * Lucent/Cisco, which announces null ESSID in beacon. - */ - ni->ni_esslen = ssid[1]; - memset(ni->ni_essid, 0, sizeof(ni->ni_essid)); - memcpy(ni->ni_essid, ssid + 2, ssid[1]); - allocbs = 0; - } else - allocbs = 0; - IEEE80211_ADDR_COPY(ni->ni_bssid, wh->i_addr3); - ni->ni_rssi = rssi; - ni->ni_rstamp = rstamp; - memcpy(ni->ni_tstamp, tstamp, sizeof(ni->ni_tstamp)); - ni->ni_intval = le16toh(*(uint16_t *)bintval); - ni->ni_capinfo = le16toh(*(uint16_t *)capinfo); - /* XXX validate channel # */ - ni->ni_chan = &ic->ic_channels[chan]; - ni->ni_fhdwell = fhdwell; - ni->ni_fhindex = fhindex; - ni->ni_erp = erp; - /* NB: must be after ni_chan is setup */ - ieee80211_setup_rates(ic, ni, rates, xrates, IEEE80211_F_DOSORT); - /* - * When scanning we record results (nodes) with a zero - * refcnt. Otherwise we want to hold the reference for - * ibss neighbors so the nodes don't get released prematurely. - * Anything else can be discarded (XXX and should be handled - * above so we don't do so much work). - */ - if (ic->ic_state == IEEE80211_S_SCAN) - ieee80211_unref_node(&ni); /* NB: do not free */ - else if (ic->ic_opmode == IEEE80211_M_IBSS && - allocbs && isprobe) { - /* - * Fake an association so the driver can setup it's - * private state. The rate set has been setup above; - * there is no handshake as in ap/station operation. - */ - if (ic->ic_newassoc) - (*ic->ic_newassoc)(ic, ni, 1); - /* NB: hold reference */ - } else { - /* XXX optimize to avoid work done above */ - ieee80211_free_node(ic, ni); - } - break; - } - - case IEEE80211_FC0_SUBTYPE_PROBE_REQ: { - uint8_t rate; - - if (ic->ic_opmode == IEEE80211_M_STA) - return; - if (ic->ic_state != IEEE80211_S_RUN) - return; - - /* - * prreq frame format - * [tlv] ssid - * [tlv] supported rates - * [tlv] extended supported rates - */ - ssid = rates = xrates = NULL; - while (frm < efrm) { - switch (*frm) { - case IEEE80211_ELEMID_SSID: - ssid = frm; - break; - case IEEE80211_ELEMID_RATES: - rates = frm; - break; - case IEEE80211_ELEMID_XRATES: - xrates = frm; - break; - } - frm += frm[1] + 2; - } - IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE); - IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN); - if (ssid[1] != 0 && - (ssid[1] != ic->ic_bss->ni_esslen || - memcmp(ssid + 2, ic->ic_bss->ni_essid, ic->ic_bss->ni_esslen) != 0)) { -#ifdef IEEE80211_DEBUG - if (ieee80211_debug) { - printf("%s: ssid unmatch ", __func__); - ieee80211_print_essid(ssid + 2, ssid[1]); - printf(" from %6D\n", wh->i_addr2, ":"); - } -#endif - ic->ic_stats.is_rx_ssidmismatch++; - return; - } - - if (ni == ic->ic_bss) { - ni = ieee80211_dup_bss(ic, wh->i_addr2); - if (ni == NULL) - return; - IEEE80211_DPRINTF(("%s: new req from %6D\n", - __func__, wh->i_addr2, ":")); - allocbs = 1; - } else - allocbs = 0; - ni->ni_rssi = rssi; - ni->ni_rstamp = rstamp; - rate = ieee80211_setup_rates(ic, ni, rates, xrates, - IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE - | IEEE80211_F_DONEGO | IEEE80211_F_DODEL); - if (rate & IEEE80211_RATE_BASIC) { - IEEE80211_DPRINTF(("%s: rate negotiation failed: %6D\n", - __func__, wh->i_addr2, ":")); - } else { - IEEE80211_SEND_MGMT(ic, ni, - IEEE80211_FC0_SUBTYPE_PROBE_RESP, 0); - } - if (allocbs) - ieee80211_free_node(ic, ni); - break; - } - - case IEEE80211_FC0_SUBTYPE_AUTH: { - uint16_t algo, seq, status; - /* - * auth frame format - * [2] algorithm - * [2] sequence - * [2] status - * [tlv*] challenge - */ - IEEE80211_VERIFY_LENGTH(efrm - frm, 6); - algo = le16toh(*(uint16_t *)frm); - seq = le16toh(*(uint16_t *)(frm + 2)); - status = le16toh(*(uint16_t *)(frm + 4)); - if (algo != IEEE80211_AUTH_ALG_OPEN) { - /* TODO: shared key auth */ - IEEE80211_DPRINTF(("%s: unsupported auth %d from %6D\n", - __func__, algo, wh->i_addr2, ":")); - ic->ic_stats.is_rx_auth_unsupported++; - return; - } - switch (ic->ic_opmode) { - case IEEE80211_M_IBSS: - if (ic->ic_state != IEEE80211_S_RUN || seq != 1) { - IEEE80211_DPRINTF(("%s: discard auth from %6D; " - "state %u, seq %u\n", __func__, - wh->i_addr2, ":", - ic->ic_state, seq)); - ic->ic_stats.is_rx_bad_auth++; - break; - } - ieee80211_new_state(ic, IEEE80211_S_AUTH, - wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK); - break; - - case IEEE80211_M_AHDEMO: - /* should not come here */ - break; - - case IEEE80211_M_HOSTAP: - if (ic->ic_state != IEEE80211_S_RUN || seq != 1) { - IEEE80211_DPRINTF(("%s: discard auth from %6D; " - "state %u, seq %u\n", __func__, - wh->i_addr2, ":", - ic->ic_state, seq)); - ic->ic_stats.is_rx_bad_auth++; - break; - } - if (ni == ic->ic_bss) { - ni = ieee80211_alloc_node(ic, wh->i_addr2); - if (ni == NULL) - return; - IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss->ni_bssid); - ni->ni_rssi = rssi; - ni->ni_rstamp = rstamp; - ni->ni_chan = ic->ic_bss->ni_chan; - allocbs = 1; - } else - allocbs = 0; - IEEE80211_SEND_MGMT(ic, ni, - IEEE80211_FC0_SUBTYPE_AUTH, 2); - if (ifp->if_flags & IFF_DEBUG) - if_printf(ifp, "station %6D %s authenticated\n", - ni->ni_macaddr, ":", - (allocbs ? "newly" : "already")); - break; - - case IEEE80211_M_STA: - if (ic->ic_state != IEEE80211_S_AUTH || seq != 2) { - IEEE80211_DPRINTF(("%s: discard auth from %6D; " - "state %u, seq %u\n", __func__, - wh->i_addr2, ":", - ic->ic_state, seq)); - ic->ic_stats.is_rx_bad_auth++; - break; - } - if (status != 0) { - if_printf(&ic->ic_if, - "authentication failed (reason %d) for %6D\n", - status, - wh->i_addr3, ":"); - if (ni != ic->ic_bss) - ni->ni_fails++; - ic->ic_stats.is_rx_auth_fail++; - return; - } - ieee80211_new_state(ic, IEEE80211_S_ASSOC, - wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK); - break; - case IEEE80211_M_MONITOR: - break; - } - break; - } - - case IEEE80211_FC0_SUBTYPE_ASSOC_REQ: - case IEEE80211_FC0_SUBTYPE_REASSOC_REQ: { - uint16_t capinfo, bintval; - - if (ic->ic_opmode != IEEE80211_M_HOSTAP || - (ic->ic_state != IEEE80211_S_RUN)) - return; - - if (subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) { - reassoc = 1; - resp = IEEE80211_FC0_SUBTYPE_REASSOC_RESP; - } else { - reassoc = 0; - resp = IEEE80211_FC0_SUBTYPE_ASSOC_RESP; - } - /* - * asreq frame format - * [2] capability information - * [2] listen interval - * [6*] current AP address (reassoc only) - * [tlv] ssid - * [tlv] supported rates - * [tlv] extended supported rates - */ - IEEE80211_VERIFY_LENGTH(efrm - frm, (reassoc ? 10 : 4)); - if (!IEEE80211_ADDR_EQ(wh->i_addr3, ic->ic_bss->ni_bssid)) { - IEEE80211_DPRINTF(("%s: ignore other bss from %6D\n", - __func__, wh->i_addr2, ":")); - ic->ic_stats.is_rx_assoc_bss++; - return; - } - capinfo = le16toh(*(uint16_t *)frm); frm += 2; - bintval = le16toh(*(uint16_t *)frm); frm += 2; - if (reassoc) - frm += 6; /* ignore current AP info */ - ssid = rates = xrates = NULL; - while (frm < efrm) { - switch (*frm) { - case IEEE80211_ELEMID_SSID: - ssid = frm; - break; - case IEEE80211_ELEMID_RATES: - rates = frm; - break; - case IEEE80211_ELEMID_XRATES: - xrates = frm; - break; - } - frm += frm[1] + 2; - } - IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE); - IEEE80211_VERIFY_ELEMENT(ssid, IEEE80211_NWID_LEN); - if (ssid[1] != ic->ic_bss->ni_esslen || - memcmp(ssid + 2, ic->ic_bss->ni_essid, ssid[1]) != 0) { -#ifdef IEEE80211_DEBUG - if (ieee80211_debug) { - printf("%s: ssid unmatch ", __func__); - ieee80211_print_essid(ssid + 2, ssid[1]); - printf(" from %6D\n", wh->i_addr2, ":"); - } -#endif - ic->ic_stats.is_rx_ssidmismatch++; - return; - } - if (ni == ic->ic_bss) { - IEEE80211_DPRINTF(("%s: not authenticated for %6D\n", - __func__, wh->i_addr2, ":")); - ni = ieee80211_dup_bss(ic, wh->i_addr2); - if (ni != NULL) { - IEEE80211_SEND_MGMT(ic, ni, - IEEE80211_FC0_SUBTYPE_DEAUTH, - IEEE80211_REASON_ASSOC_NOT_AUTHED); - ieee80211_free_node(ic, ni); - } - ic->ic_stats.is_rx_assoc_notauth++; - return; - } - /* XXX per-node cipher suite */ - /* XXX some stations use the privacy bit for handling APs - that suport both encrypted and unencrypted traffic */ - if ((capinfo & IEEE80211_CAPINFO_ESS) == 0 || - (capinfo & IEEE80211_CAPINFO_PRIVACY) != - ((ic->ic_flags & IEEE80211_F_WEPON) ? - IEEE80211_CAPINFO_PRIVACY : 0)) { - IEEE80211_DPRINTF(("%s: capability mismatch %x for %6D\n", - __func__, capinfo, wh->i_addr2, ":")); - ni->ni_associd = 0; - IEEE80211_SEND_MGMT(ic, ni, resp, - IEEE80211_STATUS_CAPINFO); - ic->ic_stats.is_rx_assoc_capmismatch++; - return; - } - ieee80211_setup_rates(ic, ni, rates, xrates, - IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE | - IEEE80211_F_DONEGO | IEEE80211_F_DODEL); - if (ni->ni_rates.rs_nrates == 0) { - IEEE80211_DPRINTF(("%s: rate unmatch for %6D\n", - __func__, wh->i_addr2, ":")); - ni->ni_associd = 0; - IEEE80211_SEND_MGMT(ic, ni, resp, - IEEE80211_STATUS_BASIC_RATE); - ic->ic_stats.is_rx_assoc_norate++; - return; - } - ni->ni_rssi = rssi; - ni->ni_rstamp = rstamp; - ni->ni_intval = bintval; - ni->ni_capinfo = capinfo; - ni->ni_chan = ic->ic_bss->ni_chan; - ni->ni_fhdwell = ic->ic_bss->ni_fhdwell; - ni->ni_fhindex = ic->ic_bss->ni_fhindex; - if (ni->ni_associd == 0) { - /* XXX handle rollover at 2007 */ - /* XXX guarantee uniqueness */ - ni->ni_associd = 0xc000 | ic->ic_bss->ni_associd++; - newassoc = 1; - } else - newassoc = 0; - /* XXX for 11g must turn off short slot time if long - slot time sta associates */ - IEEE80211_SEND_MGMT(ic, ni, resp, IEEE80211_STATUS_SUCCESS); - if (ifp->if_flags & IFF_DEBUG) - if_printf(ifp, "station %6D %s associated\n", - ni->ni_macaddr, ":", - (newassoc ? "newly" : "already")); - /* give driver a chance to setup state like ni_txrate */ - if (ic->ic_newassoc) - (*ic->ic_newassoc)(ic, ni, newassoc); - break; - } - - case IEEE80211_FC0_SUBTYPE_ASSOC_RESP: - case IEEE80211_FC0_SUBTYPE_REASSOC_RESP: { - uint16_t status; - - if (ic->ic_opmode != IEEE80211_M_STA || - ic->ic_state != IEEE80211_S_ASSOC) - return; - - /* - * asresp frame format - * [2] capability information - * [2] status - * [2] association ID - * [tlv] supported rates - * [tlv] extended supported rates - */ - IEEE80211_VERIFY_LENGTH(efrm - frm, 6); - ni = ic->ic_bss; - ni->ni_capinfo = le16toh(*(uint16_t *)frm); - frm += 2; - - status = le16toh(*(uint16_t *)frm); - frm += 2; - if (status != 0) { - if_printf(ifp, "association failed (reason %d) for %6D\n", - status, wh->i_addr3, ":"); - if (ni != ic->ic_bss) - ni->ni_fails++; - ic->ic_stats.is_rx_auth_fail++; - return; - } - ni->ni_associd = le16toh(*(uint16_t *)frm); - frm += 2; - - rates = xrates = NULL; - while (frm < efrm) { - switch (*frm) { - case IEEE80211_ELEMID_RATES: - rates = frm; - break; - case IEEE80211_ELEMID_XRATES: - xrates = frm; - break; - } - frm += frm[1] + 2; - } - - IEEE80211_VERIFY_ELEMENT(rates, IEEE80211_RATE_MAXSIZE); - ieee80211_setup_rates(ic, ni, rates, xrates, - IEEE80211_F_DOSORT | IEEE80211_F_DOFRATE | - IEEE80211_F_DONEGO | IEEE80211_F_DODEL); - if (ni->ni_rates.rs_nrates != 0) - ieee80211_new_state(ic, IEEE80211_S_RUN, - wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK); - break; - } - - case IEEE80211_FC0_SUBTYPE_DEAUTH: { - uint16_t reason; - /* - * deauth frame format - * [2] reason - */ - IEEE80211_VERIFY_LENGTH(efrm - frm, 2); - reason = le16toh(*(uint16_t *)frm); - ic->ic_stats.is_rx_deauth++; - switch (ic->ic_opmode) { - case IEEE80211_M_STA: - ieee80211_new_state(ic, IEEE80211_S_AUTH, - wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK); - break; - case IEEE80211_M_HOSTAP: - if (ni != ic->ic_bss) { - if (ifp->if_flags & IFF_DEBUG) - if_printf(ifp, "station %6D deauthenticated" - " by peer (reason %d)\n", - ni->ni_macaddr, ":", reason); - /* node will be free'd on return */ - ieee80211_unref_node(&ni); - } - break; - default: - break; - } - break; - } - - case IEEE80211_FC0_SUBTYPE_DISASSOC: { - uint16_t reason; - /* - * disassoc frame format - * [2] reason - */ - IEEE80211_VERIFY_LENGTH(efrm - frm, 2); - reason = le16toh(*(uint16_t *)frm); - ic->ic_stats.is_rx_disassoc++; - switch (ic->ic_opmode) { - case IEEE80211_M_STA: - ieee80211_new_state(ic, IEEE80211_S_ASSOC, - wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK); - break; - case IEEE80211_M_HOSTAP: - if (ni != ic->ic_bss) { - if (ifp->if_flags & IFF_DEBUG) - if_printf(ifp, "station %6D disassociated" - " by peer (reason %d)\n", - ni->ni_macaddr, ":", reason); - ni->ni_associd = 0; - /* XXX node reclaimed how? */ - } - break; - default: - break; - } - break; - } - default: - IEEE80211_DPRINTF(("%s: mgmt frame with subtype 0x%x not " - "handled\n", __func__, subtype)); - ic->ic_stats.is_rx_badsubtype++; - break; - } -} -#undef IEEE80211_VERIFY_LENGTH -#undef IEEE80211_VERIFY_ELEMENT diff --git a/sys/netproto/802_11/ieee80211_ioctl.c b/sys/netproto/802_11/ieee80211_ioctl.c deleted file mode 100644 index 529e0e6852..0000000000 --- a/sys/netproto/802_11/ieee80211_ioctl.c +++ /dev/null @@ -1,1128 +0,0 @@ -/* - * Copyright (c) 2001 Atsushi Onoe - * Copyright (c) 2002, 2003 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. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * 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. - * - * $FreeBSD: src/sys/net80211/ieee80211_ioctl.c,v 1.13 2004/03/30 22:57:57 sam Exp $ - * $DragonFly: src/sys/netproto/802_11/Attic/ieee80211_ioctl.c,v 1.1 2004/07/26 16:30:17 joerg Exp $ - */ - -/* - * IEEE 802.11 ioctl support (FreeBSD-specific) - */ - -#include "opt_inet.h" -#include "opt_ipx.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#ifdef INET -#include -#include -#endif - -#ifdef IPX -#include -#include -#endif - -#include -#include - -#include - -/* - * XXX - * Wireless LAN specific configuration interface, which is compatible - * with wicontrol(8). - */ - -int -ieee80211_cfgget(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr) -{ - struct ieee80211com *ic = (void *)ifp; - int i, j, error; - struct ifreq *ifr = (struct ifreq *)data; - struct wi_req wreq; - struct wi_ltv_keys *keys; - struct wi_apinfo *ap; - struct ieee80211_node *ni; - struct ieee80211_rateset *rs; - struct wi_sigcache wsc; - struct wi_scan_p2_hdr *p2; - struct wi_scan_res *res; - - error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); - if (error) - return error; - wreq.wi_len = 0; - switch (wreq.wi_type) { - case WI_RID_SERIALNO: - /* nothing appropriate */ - break; - case WI_RID_NODENAME: - strcpy((char *)&wreq.wi_val[1], hostname); - wreq.wi_val[0] = htole16(strlen(hostname)); - wreq.wi_len = (1 + strlen(hostname) + 1) / 2; - break; - case WI_RID_CURRENT_SSID: - if (ic->ic_state != IEEE80211_S_RUN) { - wreq.wi_val[0] = 0; - wreq.wi_len = 1; - break; - } - wreq.wi_val[0] = htole16(ic->ic_bss->ni_esslen); - memcpy(&wreq.wi_val[1], ic->ic_bss->ni_essid, - ic->ic_bss->ni_esslen); - wreq.wi_len = (1 + ic->ic_bss->ni_esslen + 1) / 2; - break; - case WI_RID_OWN_SSID: - case WI_RID_DESIRED_SSID: - wreq.wi_val[0] = htole16(ic->ic_des_esslen); - memcpy(&wreq.wi_val[1], ic->ic_des_essid, ic->ic_des_esslen); - wreq.wi_len = (1 + ic->ic_des_esslen + 1) / 2; - break; - case WI_RID_CURRENT_BSSID: - if (ic->ic_state == IEEE80211_S_RUN) - IEEE80211_ADDR_COPY(wreq.wi_val, ic->ic_bss->ni_bssid); - else - memset(wreq.wi_val, 0, IEEE80211_ADDR_LEN); - wreq.wi_len = IEEE80211_ADDR_LEN / 2; - break; - case WI_RID_CHANNEL_LIST: - memset(wreq.wi_val, 0, sizeof(wreq.wi_val)); - /* - * Since channel 0 is not available for DS, channel 1 - * is assigned to LSB on WaveLAN. - */ - if (ic->ic_phytype == IEEE80211_T_DS) - i = 1; - else - i = 0; - for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) - if (isset(ic->ic_chan_active, i)) { - setbit((uint8_t *)wreq.wi_val, j); - wreq.wi_len = j / 16 + 1; - } - break; - case WI_RID_OWN_CHNL: - wreq.wi_val[0] = htole16( - ieee80211_chan2ieee(ic, ic->ic_ibss_chan)); - wreq.wi_len = 1; - break; - case WI_RID_CURRENT_CHAN: - wreq.wi_val[0] = htole16( - ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan)); - wreq.wi_len = 1; - break; - case WI_RID_COMMS_QUALITY: - wreq.wi_val[0] = 0; /* quality */ - wreq.wi_val[1] = - htole16((*ic->ic_node_getrssi)(ic, ic->ic_bss)); - wreq.wi_val[2] = 0; /* noise */ - wreq.wi_len = 3; - break; - case WI_RID_PROMISC: - wreq.wi_val[0] = htole16((ifp->if_flags & IFF_PROMISC) ? 1 : 0); - wreq.wi_len = 1; - break; - case WI_RID_PORTTYPE: - wreq.wi_val[0] = htole16(ic->ic_opmode); - wreq.wi_len = 1; - break; - case WI_RID_MAC_NODE: - IEEE80211_ADDR_COPY(wreq.wi_val, ic->ic_myaddr); - wreq.wi_len = IEEE80211_ADDR_LEN / 2; - break; - case WI_RID_TX_RATE: - if (ic->ic_fixed_rate == -1) - wreq.wi_val[0] = 0; /* auto */ - else - wreq.wi_val[0] = htole16( - (ic->ic_sup_rates[ic->ic_curmode].rs_rates[ic->ic_fixed_rate] & - IEEE80211_RATE_VAL) / 2); - wreq.wi_len = 1; - break; - case WI_RID_CUR_TX_RATE: - wreq.wi_val[0] = htole16( - (ic->ic_bss->ni_rates.rs_rates[ic->ic_bss->ni_txrate] & - IEEE80211_RATE_VAL) / 2); - wreq.wi_len = 1; - break; - case WI_RID_RTS_THRESH: - wreq.wi_val[0] = htole16(ic->ic_rtsthreshold); - wreq.wi_len = 1; - break; - case WI_RID_CREATE_IBSS: - wreq.wi_val[0] = - htole16((ic->ic_flags & IEEE80211_F_IBSSON) ? 1 : 0); - wreq.wi_len = 1; - break; - case WI_RID_MICROWAVE_OVEN: - wreq.wi_val[0] = 0; /* no ... not supported */ - wreq.wi_len = 1; - break; - case WI_RID_ROAMING_MODE: - wreq.wi_val[0] = htole16(1); /* enabled ... not supported */ - wreq.wi_len = 1; - break; - case WI_RID_SYSTEM_SCALE: - wreq.wi_val[0] = htole16(1); /* low density ... not supp */ - wreq.wi_len = 1; - break; - case WI_RID_PM_ENABLED: - wreq.wi_val[0] = - htole16((ic->ic_flags & IEEE80211_F_PMGTON) ? 1 : 0); - wreq.wi_len = 1; - break; - case WI_RID_MAX_SLEEP: - wreq.wi_val[0] = htole16(ic->ic_lintval); - wreq.wi_len = 1; - break; - case WI_RID_CUR_BEACON_INT: - wreq.wi_val[0] = htole16(ic->ic_bss->ni_intval); - wreq.wi_len = 1; - break; - case WI_RID_WEP_AVAIL: - wreq.wi_val[0] = - htole16((ic->ic_caps & IEEE80211_C_WEP) ? 1 : 0); - wreq.wi_len = 1; - break; - case WI_RID_CNFAUTHMODE: - wreq.wi_val[0] = htole16(1); /* TODO: open system only */ - wreq.wi_len = 1; - break; - case WI_RID_ENCRYPTION: - wreq.wi_val[0] = - htole16((ic->ic_flags & IEEE80211_F_WEPON) ? 1 : 0); - wreq.wi_len = 1; - break; - case WI_RID_TX_CRYPT_KEY: - wreq.wi_val[0] = htole16(ic->ic_wep_txkey); - wreq.wi_len = 1; - break; - case WI_RID_DEFLT_CRYPT_KEYS: - keys = (struct wi_ltv_keys *)&wreq; - /* do not show keys to non-root user */ - error = suser_cred(cr, NULL_CRED_OKAY); - if (error) { - memset(keys, 0, sizeof(*keys)); - error = 0; - break; - } - for (i = 0; i < IEEE80211_WEP_NKID; i++) { - keys->wi_keys[i].wi_keylen = - htole16(ic->ic_nw_keys[i].wk_len); - memcpy(keys->wi_keys[i].wi_keydat, - ic->ic_nw_keys[i].wk_key, ic->ic_nw_keys[i].wk_len); - } - wreq.wi_len = sizeof(*keys) / 2; - break; - case WI_RID_MAX_DATALEN: - wreq.wi_val[0] = htole16(IEEE80211_MAX_LEN); /* TODO: frag */ - wreq.wi_len = 1; - break; - case WI_RID_IFACE_STATS: - /* XXX: should be implemented in lower drivers */ - break; - case WI_RID_READ_APS: - if (ic->ic_opmode != IEEE80211_M_HOSTAP) { - /* - * Don't return results until active scan completes. - */ - if (ic->ic_state == IEEE80211_S_SCAN && - (ic->ic_flags & IEEE80211_F_ASCAN)) { - error = EINPROGRESS; - break; - } - } - i = 0; - ap = (void *)((char *)wreq.wi_val + sizeof(i)); - TAILQ_FOREACH(ni, &ic->ic_node, ni_list) { - if ((caddr_t)(ap + 1) > (caddr_t)(&wreq + 1)) - break; - memset(ap, 0, sizeof(*ap)); - if (ic->ic_opmode == IEEE80211_M_HOSTAP) { - IEEE80211_ADDR_COPY(ap->bssid, ni->ni_macaddr); - ap->namelen = ic->ic_des_esslen; - if (ic->ic_des_esslen) - memcpy(ap->name, ic->ic_des_essid, - ic->ic_des_esslen); - } else { - IEEE80211_ADDR_COPY(ap->bssid, ni->ni_bssid); - ap->namelen = ni->ni_esslen; - if (ni->ni_esslen) - memcpy(ap->name, ni->ni_essid, - ni->ni_esslen); - } - ap->channel = ieee80211_chan2ieee(ic, ni->ni_chan); - ap->signal = (*ic->ic_node_getrssi)(ic, ni); - ap->capinfo = ni->ni_capinfo; - ap->interval = ni->ni_intval; - rs = &ni->ni_rates; - for (j = 0; j < rs->rs_nrates; j++) { - if (rs->rs_rates[j] & IEEE80211_RATE_BASIC) { - ap->rate = (rs->rs_rates[j] & - IEEE80211_RATE_VAL) * 5; /* XXX */ - } - } - i++; - ap++; - } - memcpy(wreq.wi_val, &i, sizeof(i)); - wreq.wi_len = (sizeof(int) + sizeof(*ap) * i) / 2; - break; - case WI_RID_PRISM2: - wreq.wi_val[0] = 1; /* XXX lie so SCAN_RES can give rates */ - wreq.wi_len = sizeof(uint16_t) / 2; - break; - case WI_RID_SCAN_RES: /* compatibility interface */ - if (ic->ic_opmode != IEEE80211_M_HOSTAP && - ic->ic_state == IEEE80211_S_SCAN && - (ic->ic_flags & IEEE80211_F_ASCAN)) { - error = EINPROGRESS; - break; - } - /* NB: we use the Prism2 format so we can return rate info */ - p2 = (struct wi_scan_p2_hdr *)wreq.wi_val; - res = (void *)&p2[1]; - i = 0; - TAILQ_FOREACH(ni, &ic->ic_node, ni_list) { - if ((caddr_t)(res + 1) > (caddr_t)(&wreq + 1)) - break; - res->wi_chan = ieee80211_chan2ieee(ic, ni->ni_chan); - res->wi_noise = 0; - res->wi_signal = (*ic->ic_node_getrssi)(ic, ni); - IEEE80211_ADDR_COPY(res->wi_bssid, ni->ni_bssid); - res->wi_interval = ni->ni_intval; - res->wi_capinfo = ni->ni_capinfo; - res->wi_ssid_len = ni->ni_esslen; - memcpy(res->wi_ssid, ni->ni_essid, IEEE80211_NWID_LEN); - /* NB: assumes wi_srates holds <= ni->ni_rates */ - memcpy(res->wi_srates, ni->ni_rates.rs_rates, - sizeof(res->wi_srates)); - if (ni->ni_rates.rs_nrates < 10) - res->wi_srates[ni->ni_rates.rs_nrates] = 0; - res->wi_rate = ni->ni_rates.rs_rates[ni->ni_txrate]; - res->wi_rsvd = 0; - res++, i++; - } - p2->wi_rsvd = 0; - p2->wi_reason = i; - wreq.wi_len = (sizeof(*p2) + sizeof(*res) * i) / 2; - break; - case WI_RID_READ_CACHE: - i = 0; - TAILQ_FOREACH(ni, &ic->ic_node, ni_list) { - if (i == (WI_MAX_DATALEN/sizeof(struct wi_sigcache))-1) - break; - IEEE80211_ADDR_COPY(wsc.macsrc, ni->ni_macaddr); - memset(&wsc.ipsrc, 0, sizeof(wsc.ipsrc)); - wsc.signal = (*ic->ic_node_getrssi)(ic, ni); - wsc.noise = 0; - wsc.quality = 0; - memcpy((caddr_t)wreq.wi_val + sizeof(wsc) * i, - &wsc, sizeof(wsc)); - i++; - } - wreq.wi_len = sizeof(wsc) * i / 2; - break; - case WI_RID_SCAN_APS: - error = EINVAL; - break; - default: - error = EINVAL; - break; - } - if (error == 0) { - wreq.wi_len++; - error = copyout(&wreq, ifr->ifr_data, sizeof(wreq)); - } - return error; -} - -static int -findrate(struct ieee80211com *ic, enum ieee80211_phymode mode, int rate) -{ -#define IEEERATE(_ic,_m,_i) \ - ((_ic)->ic_sup_rates[_m].rs_rates[_i] & IEEE80211_RATE_VAL) - int i, nrates = ic->ic_sup_rates[mode].rs_nrates; - for (i = 0; i < nrates; i++) - if (IEEERATE(ic, mode, i) == rate) - return i; - return -1; -#undef IEEERATE -} - -/* - * Prepare to do a user-initiated scan for AP's. If no - * current/default channel is setup or the current channel - * is invalid then pick the first available channel from - * the active list as the place to start the scan. - */ -static int -ieee80211_setupscan(struct ieee80211com *ic) -{ - u_char *chanlist = ic->ic_chan_active; - int i; - - if (ic->ic_ibss_chan == NULL || - isclr(chanlist, ieee80211_chan2ieee(ic, ic->ic_ibss_chan))) { - for (i = 0; i <= IEEE80211_CHAN_MAX; i++) - if (isset(chanlist, i)) { - ic->ic_ibss_chan = &ic->ic_channels[i]; - goto found; - } - return EINVAL; /* no active channels */ -found: - ; - } - if (ic->ic_bss->ni_chan == IEEE80211_CHAN_ANYC || - isclr(chanlist, ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan))) - ic->ic_bss->ni_chan = ic->ic_ibss_chan; - /* - * XXX don't permit a scan to be started unless we - * know the device is ready. For the moment this means - * the device is marked up as this is the required to - * initialize the hardware. It would be better to permit - * scanning prior to being up but that'll require some - * changes to the infrastructure. - */ - return (ic->ic_if.if_flags & IFF_UP) ? 0 : ENETRESET; -} - -int -ieee80211_cfgset(struct ifnet *ifp, u_long cmd, caddr_t data) -{ - struct ieee80211com *ic = (void *)ifp; - int i, j, len, error, rate; - struct ifreq *ifr = (struct ifreq *)data; - struct wi_ltv_keys *keys; - struct wi_req wreq; - u_char chanlist[roundup(IEEE80211_CHAN_MAX, NBBY)]; - - error = copyin(ifr->ifr_data, &wreq, sizeof(wreq)); - if (error) - return error; - len = wreq.wi_len ? (wreq.wi_len - 1) * 2 : 0; - switch (wreq.wi_type) { - case WI_RID_SERIALNO: - case WI_RID_NODENAME: - return EPERM; - case WI_RID_CURRENT_SSID: - return EPERM; - case WI_RID_OWN_SSID: - case WI_RID_DESIRED_SSID: - if (le16toh(wreq.wi_val[0]) * 2 > len || - le16toh(wreq.wi_val[0]) > IEEE80211_NWID_LEN) { - error = ENOSPC; - break; - } - memset(ic->ic_des_essid, 0, sizeof(ic->ic_des_essid)); - ic->ic_des_esslen = le16toh(wreq.wi_val[0]) * 2; - memcpy(ic->ic_des_essid, &wreq.wi_val[1], ic->ic_des_esslen); - error = ENETRESET; - break; - case WI_RID_CURRENT_BSSID: - return EPERM; - case WI_RID_OWN_CHNL: - if (len != 2) - return EINVAL; - i = le16toh(wreq.wi_val[0]); - if (i < 0 || - i > IEEE80211_CHAN_MAX || - isclr(ic->ic_chan_active, i)) - return EINVAL; - ic->ic_ibss_chan = &ic->ic_channels[i]; - if (ic->ic_flags & IEEE80211_F_SIBSS) - error = ENETRESET; - break; - case WI_RID_CURRENT_CHAN: - return EPERM; - case WI_RID_COMMS_QUALITY: - return EPERM; - case WI_RID_PROMISC: - if (len != 2) - return EINVAL; - if (ifp->if_flags & IFF_PROMISC) { - if (wreq.wi_val[0] == 0) { - ifp->if_flags &= ~IFF_PROMISC; - error = ENETRESET; - } - } else { - if (wreq.wi_val[0] != 0) { - ifp->if_flags |= IFF_PROMISC; - error = ENETRESET; - } - } - break; - case WI_RID_PORTTYPE: - if (len != 2) - return EINVAL; - switch (le16toh(wreq.wi_val[0])) { - case IEEE80211_M_STA: - break; - case IEEE80211_M_IBSS: - if (!(ic->ic_caps & IEEE80211_C_IBSS)) - return EINVAL; - break; - case IEEE80211_M_AHDEMO: - if (ic->ic_phytype != IEEE80211_T_DS || - !(ic->ic_caps & IEEE80211_C_AHDEMO)) - return EINVAL; - break; - case IEEE80211_M_HOSTAP: - if (!(ic->ic_caps & IEEE80211_C_HOSTAP)) - return EINVAL; - break; - default: - return EINVAL; - } - if (le16toh(wreq.wi_val[0]) != ic->ic_opmode) { - ic->ic_opmode = le16toh(wreq.wi_val[0]); - error = ENETRESET; - } - break; -#if 0 - case WI_RID_MAC_NODE: - if (len != IEEE80211_ADDR_LEN) - return EINVAL; - IEEE80211_ADDR_COPY(LLADDR(ifp->if_sadl), wreq.wi_val); - /* if_init will copy lladdr into ic_myaddr */ - error = ENETRESET; - break; -#endif - case WI_RID_TX_RATE: - if (len != 2) - return EINVAL; - if (wreq.wi_val[0] == 0) { - /* auto */ - ic->ic_fixed_rate = -1; - break; - } - rate = 2 * le16toh(wreq.wi_val[0]); - if (ic->ic_curmode == IEEE80211_MODE_AUTO) { - /* - * In autoselect mode search for the rate. We take - * the first instance which may not be right, but we - * are limited by the interface. Note that we also - * lock the mode to insure the rate is meaningful - * when it is used. - */ - for (j = IEEE80211_MODE_11A; - j < IEEE80211_MODE_MAX; j++) { - if ((ic->ic_modecaps & (1<ic_curmode = j; - goto setrate; - } - } - } else { - i = findrate(ic, ic->ic_curmode, rate); - if (i != -1) - goto setrate; - } - return EINVAL; - setrate: - ic->ic_fixed_rate = i; - error = ENETRESET; - break; - case WI_RID_CUR_TX_RATE: - return EPERM; - case WI_RID_RTS_THRESH: - if (len != 2) - return EINVAL; - if (le16toh(wreq.wi_val[0]) != IEEE80211_MAX_LEN) - return EINVAL; /* TODO: RTS */ - break; - case WI_RID_CREATE_IBSS: - if (len != 2) - return EINVAL; - if (wreq.wi_val[0] != 0) { - if ((ic->ic_caps & IEEE80211_C_IBSS) == 0) - return EINVAL; - if ((ic->ic_flags & IEEE80211_F_IBSSON) == 0) { - ic->ic_flags |= IEEE80211_F_IBSSON; - if (ic->ic_opmode == IEEE80211_M_IBSS && - ic->ic_state == IEEE80211_S_SCAN) - error = ENETRESET; - } - } else { - if (ic->ic_flags & IEEE80211_F_IBSSON) { - ic->ic_flags &= ~IEEE80211_F_IBSSON; - if (ic->ic_flags & IEEE80211_F_SIBSS) { - ic->ic_flags &= ~IEEE80211_F_SIBSS; - error = ENETRESET; - } - } - } - break; - case WI_RID_MICROWAVE_OVEN: - if (len != 2) - return EINVAL; - if (wreq.wi_val[0] != 0) - return EINVAL; /* not supported */ - break; - case WI_RID_ROAMING_MODE: - if (len != 2) - return EINVAL; - if (le16toh(wreq.wi_val[0]) != 1) - return EINVAL; /* not supported */ - break; - case WI_RID_SYSTEM_SCALE: - if (len != 2) - return EINVAL; - if (le16toh(wreq.wi_val[0]) != 1) - return EINVAL; /* not supported */ - break; - case WI_RID_PM_ENABLED: - if (len != 2) - return EINVAL; - if (wreq.wi_val[0] != 0) { - if ((ic->ic_caps & IEEE80211_C_PMGT) == 0) - return EINVAL; - if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) { - ic->ic_flags |= IEEE80211_F_PMGTON; - error = ENETRESET; - } - } else { - if (ic->ic_flags & IEEE80211_F_PMGTON) { - ic->ic_flags &= ~IEEE80211_F_PMGTON; - error = ENETRESET; - } - } - break; - case WI_RID_MAX_SLEEP: - if (len != 2) - return EINVAL; - ic->ic_lintval = le16toh(wreq.wi_val[0]); - if (ic->ic_flags & IEEE80211_F_PMGTON) - error = ENETRESET; - break; - case WI_RID_CUR_BEACON_INT: - return EPERM; - case WI_RID_WEP_AVAIL: - return EPERM; - case WI_RID_CNFAUTHMODE: - if (len != 2) - return EINVAL; - if (le16toh(wreq.wi_val[0]) != 1) - return EINVAL; /* TODO: shared key auth */ - break; - case WI_RID_ENCRYPTION: - if (len != 2) - return EINVAL; - if (wreq.wi_val[0] != 0) { - if ((ic->ic_caps & IEEE80211_C_WEP) == 0) - return EINVAL; - if ((ic->ic_flags & IEEE80211_F_WEPON) == 0) { - ic->ic_flags |= IEEE80211_F_WEPON; - error = ENETRESET; - } - } else { - if (ic->ic_flags & IEEE80211_F_WEPON) { - ic->ic_flags &= ~IEEE80211_F_WEPON; - error = ENETRESET; - } - } - break; - case WI_RID_TX_CRYPT_KEY: - if (len != 2) - return EINVAL; - i = le16toh(wreq.wi_val[0]); - if (i >= IEEE80211_WEP_NKID) - return EINVAL; - ic->ic_wep_txkey = i; - break; - case WI_RID_DEFLT_CRYPT_KEYS: - if (len != sizeof(struct wi_ltv_keys)) - return EINVAL; - keys = (struct wi_ltv_keys *)&wreq; - for (i = 0; i < IEEE80211_WEP_NKID; i++) { - len = le16toh(keys->wi_keys[i].wi_keylen); - if (len != 0 && len < IEEE80211_WEP_KEYLEN) - return EINVAL; - if (len > sizeof(ic->ic_nw_keys[i].wk_key)) - return EINVAL; - } - memset(ic->ic_nw_keys, 0, sizeof(ic->ic_nw_keys)); - for (i = 0; i < IEEE80211_WEP_NKID; i++) { - len = le16toh(keys->wi_keys[i].wi_keylen); - ic->ic_nw_keys[i].wk_len = len; - memcpy(ic->ic_nw_keys[i].wk_key, - keys->wi_keys[i].wi_keydat, len); - } - error = ENETRESET; - break; - case WI_RID_MAX_DATALEN: - if (len != 2) - return EINVAL; - len = le16toh(wreq.wi_val[0]); - if (len < 350 /* ? */ || len > IEEE80211_MAX_LEN) - return EINVAL; - if (len != IEEE80211_MAX_LEN) - return EINVAL; /* TODO: fragment */ - ic->ic_fragthreshold = len; - error = ENETRESET; - break; - case WI_RID_IFACE_STATS: - error = EPERM; - break; - case WI_RID_SCAN_REQ: /* XXX wicontrol */ - if (ic->ic_opmode == IEEE80211_M_HOSTAP) - break; - error = ieee80211_setupscan(ic); - if (error == 0) - error = ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); - break; - case WI_RID_SCAN_APS: - if (ic->ic_opmode == IEEE80211_M_HOSTAP) - break; - len--; /* XXX: tx rate? */ - /* FALLTHRU */ - case WI_RID_CHANNEL_LIST: - memset(chanlist, 0, sizeof(chanlist)); - /* - * Since channel 0 is not available for DS, channel 1 - * is assigned to LSB on WaveLAN. - */ - if (ic->ic_phytype == IEEE80211_T_DS) - i = 1; - else - i = 0; - for (j = 0; i <= IEEE80211_CHAN_MAX; i++, j++) { - if ((j / 8) >= len) - break; - if (isclr((uint8_t *)wreq.wi_val, j)) - continue; - if (isclr(ic->ic_chan_active, i)) { - if (wreq.wi_type != WI_RID_CHANNEL_LIST) - continue; - if (isclr(ic->ic_chan_avail, i)) - return EPERM; - } - setbit(chanlist, i); - } - memcpy(ic->ic_chan_active, chanlist, - sizeof(ic->ic_chan_active)); - error = ieee80211_setupscan(ic); - if (wreq.wi_type == WI_RID_CHANNEL_LIST) { - /* NB: ignore error from ieee80211_setupscan */ - error = ENETRESET; - } else if (error == 0) - error = ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); - break; - default: - error = EINVAL; - break; - } - return error; -} - -int -ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data, struct ucred *cr) -{ - struct ieee80211com *ic = (void *)ifp; - int error = 0; - u_int kid, len; - struct ieee80211req *ireq; - struct ifreq *ifr; - uint8_t tmpkey[IEEE80211_KEYBUF_SIZE]; - char tmpssid[IEEE80211_NWID_LEN]; - struct ieee80211_channel *chan; - struct ifaddr *ifa; /* XXX */ - - switch (cmd) { - case SIOCSIFMEDIA: - case SIOCGIFMEDIA: - error = ifmedia_ioctl(ifp, (struct ifreq *) data, - &ic->ic_media, cmd); - break; - case SIOCG80211: - ireq = (struct ieee80211req *) data; - switch (ireq->i_type) { - case IEEE80211_IOC_SSID: - switch (ic->ic_state) { - case IEEE80211_S_INIT: - case IEEE80211_S_SCAN: - ireq->i_len = ic->ic_des_esslen; - memcpy(tmpssid, ic->ic_des_essid, ireq->i_len); - break; - default: - ireq->i_len = ic->ic_bss->ni_esslen; - memcpy(tmpssid, ic->ic_bss->ni_essid, - ireq->i_len); - break; - } - error = copyout(tmpssid, ireq->i_data, ireq->i_len); - break; - case IEEE80211_IOC_NUMSSIDS: - ireq->i_val = 1; - break; - case IEEE80211_IOC_WEP: - if ((ic->ic_caps & IEEE80211_C_WEP) == 0) { - ireq->i_val = IEEE80211_WEP_NOSUP; - } else { - if (ic->ic_flags & IEEE80211_F_WEPON) { - ireq->i_val = - IEEE80211_WEP_MIXED; - } else { - ireq->i_val = - IEEE80211_WEP_OFF; - } - } - break; - case IEEE80211_IOC_WEPKEY: - if ((ic->ic_caps & IEEE80211_C_WEP) == 0) { - error = EINVAL; - break; - } - kid = (u_int) ireq->i_val; - if (kid >= IEEE80211_WEP_NKID) { - error = EINVAL; - break; - } - len = (u_int) ic->ic_nw_keys[kid].wk_len; - /* NB: only root can read WEP keys */ - if (suser_cred(cr, NULL_CRED_OKAY) == 0) { - bcopy(ic->ic_nw_keys[kid].wk_key, tmpkey, len); - } else { - bzero(tmpkey, len); - } - ireq->i_len = len; - error = copyout(tmpkey, ireq->i_data, len); - break; - case IEEE80211_IOC_NUMWEPKEYS: - if ((ic->ic_caps & IEEE80211_C_WEP) == 0) - error = EINVAL; - else - ireq->i_val = IEEE80211_WEP_NKID; - break; - case IEEE80211_IOC_WEPTXKEY: - if ((ic->ic_caps & IEEE80211_C_WEP) == 0) - error = EINVAL; - else - ireq->i_val = ic->ic_wep_txkey; - break; - case IEEE80211_IOC_AUTHMODE: - ireq->i_val = IEEE80211_AUTH_OPEN; - break; - case IEEE80211_IOC_CHANNEL: - switch (ic->ic_state) { - case IEEE80211_S_INIT: - case IEEE80211_S_SCAN: - if (ic->ic_opmode == IEEE80211_M_STA) - chan = ic->ic_des_chan; - else - chan = ic->ic_ibss_chan; - break; - default: - chan = ic->ic_bss->ni_chan; - break; - } - ireq->i_val = ieee80211_chan2ieee(ic, chan); - break; - case IEEE80211_IOC_POWERSAVE: - if (ic->ic_flags & IEEE80211_F_PMGTON) - ireq->i_val = IEEE80211_POWERSAVE_ON; - else - ireq->i_val = IEEE80211_POWERSAVE_OFF; - break; - case IEEE80211_IOC_POWERSAVESLEEP: - ireq->i_val = ic->ic_lintval; - break; - case IEEE80211_IOC_RTSTHRESHOLD: - ireq->i_val = ic->ic_rtsthreshold; - break; - case IEEE80211_IOC_PROTMODE: - ireq->i_val = ic->ic_protmode; - break; - case IEEE80211_IOC_TXPOWER: - if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) - error = EINVAL; - else - ireq->i_val = ic->ic_txpower; - break; - default: - error = EINVAL; - break; - } - break; - case SIOCS80211: - error = suser_cred(cr, NULL_CRED_OKAY); - if (error) - break; - ireq = (struct ieee80211req *) data; - switch (ireq->i_type) { - case IEEE80211_IOC_SSID: - if (ireq->i_val != 0 || - ireq->i_len > IEEE80211_NWID_LEN) { - error = EINVAL; - break; - } - error = copyin(ireq->i_data, tmpssid, ireq->i_len); - if (error) - break; - memset(ic->ic_des_essid, 0, IEEE80211_NWID_LEN); - ic->ic_des_esslen = ireq->i_len; - memcpy(ic->ic_des_essid, tmpssid, ireq->i_len); - error = ENETRESET; - break; - case IEEE80211_IOC_WEP: - /* - * These cards only support one mode so - * we just turn wep on if what ever is - * passed in is not OFF. - */ - if (ireq->i_val == IEEE80211_WEP_OFF) { - ic->ic_flags &= ~IEEE80211_F_WEPON; - } else { - ic->ic_flags |= IEEE80211_F_WEPON; - } - error = ENETRESET; - break; - case IEEE80211_IOC_WEPKEY: - if ((ic->ic_caps & IEEE80211_C_WEP) == 0) { - error = EINVAL; - break; - } - kid = (u_int) ireq->i_val; - if (kid >= IEEE80211_WEP_NKID) { - error = EINVAL; - break; - } - if (ireq->i_len > sizeof(tmpkey)) { - error = EINVAL; - break; - } - memset(tmpkey, 0, sizeof(tmpkey)); - error = copyin(ireq->i_data, tmpkey, ireq->i_len); - if (error) - break; - memcpy(ic->ic_nw_keys[kid].wk_key, tmpkey, - sizeof(tmpkey)); - ic->ic_nw_keys[kid].wk_len = ireq->i_len; - error = ENETRESET; - break; - case IEEE80211_IOC_WEPTXKEY: - kid = (u_int) ireq->i_val; - if (kid >= IEEE80211_WEP_NKID) { - error = EINVAL; - break; - } - ic->ic_wep_txkey = kid; - error = ENETRESET; - break; -#if 0 - case IEEE80211_IOC_AUTHMODE: - sc->wi_authmode = ireq->i_val; - break; -#endif - case IEEE80211_IOC_CHANNEL: - /* XXX 0xffff overflows 16-bit signed */ - if (ireq->i_val == 0 || - ireq->i_val == (int16_t) IEEE80211_CHAN_ANY) - ic->ic_des_chan = IEEE80211_CHAN_ANYC; - else if ((u_int) ireq->i_val > IEEE80211_CHAN_MAX || - isclr(ic->ic_chan_active, ireq->i_val)) { - error = EINVAL; - break; - } else - ic->ic_ibss_chan = ic->ic_des_chan = - &ic->ic_channels[ireq->i_val]; - switch (ic->ic_state) { - case IEEE80211_S_INIT: - case IEEE80211_S_SCAN: - error = ENETRESET; - break; - default: - if (ic->ic_opmode == IEEE80211_M_STA) { - if (ic->ic_des_chan != IEEE80211_CHAN_ANYC && - ic->ic_bss->ni_chan != ic->ic_des_chan) - error = ENETRESET; - } else { - if (ic->ic_bss->ni_chan != ic->ic_ibss_chan) - error = ENETRESET; - } - break; - } - break; - case IEEE80211_IOC_POWERSAVE: - switch (ireq->i_val) { - case IEEE80211_POWERSAVE_OFF: - if (ic->ic_flags & IEEE80211_F_PMGTON) { - ic->ic_flags &= ~IEEE80211_F_PMGTON; - error = ENETRESET; - } - break; - case IEEE80211_POWERSAVE_ON: - if ((ic->ic_caps & IEEE80211_C_PMGT) == 0) - error = EINVAL; - else if ((ic->ic_flags & IEEE80211_F_PMGTON) == 0) { - ic->ic_flags |= IEEE80211_F_PMGTON; - error = ENETRESET; - } - break; - default: - error = EINVAL; - break; - } - break; - case IEEE80211_IOC_POWERSAVESLEEP: - if (ireq->i_val < 0) { - error = EINVAL; - break; - } - ic->ic_lintval = ireq->i_val; - error = ENETRESET; - break; - case IEEE80211_IOC_RTSTHRESHOLD: - if (!(IEEE80211_RTS_MIN < ireq->i_val && - ireq->i_val < IEEE80211_RTS_MAX)) { - error = EINVAL; - break; - } - ic->ic_rtsthreshold = ireq->i_val; - error = ENETRESET; - break; - case IEEE80211_IOC_PROTMODE: - if (ireq->i_val > IEEE80211_PROT_RTSCTS) { - error = EINVAL; - break; - } - ic->ic_protmode = ireq->i_val; - /* NB: if not operating in 11g this can wait */ - if (ic->ic_curmode == IEEE80211_MODE_11G) - error = ENETRESET; - break; - case IEEE80211_IOC_TXPOWER: - if ((ic->ic_caps & IEEE80211_C_TXPMGT) == 0) { - error = EINVAL; - break; - } - if (!(IEEE80211_TXPOWER_MIN < ireq->i_val && - ireq->i_val < IEEE80211_TXPOWER_MAX)) { - error = EINVAL; - break; - } - ic->ic_txpower = ireq->i_val; - error = ENETRESET; - break; - default: - error = EINVAL; - break; - } - break; - case SIOCGIFGENERIC: - error = ieee80211_cfgget(ifp, cmd, data, cr); - break; - case SIOCSIFGENERIC: - error = suser_cred(cr, NULL_CRED_OKAY); - if (error) - break; - error = ieee80211_cfgset(ifp, cmd, data); - break; - case SIOCG80211STATS: - ifr = (struct ifreq *)data; - copyout(&ic->ic_stats, ifr->ifr_data, sizeof (ic->ic_stats)); - break; - case SIOCSIFMTU: - ifr = (struct ifreq *)data; - if (!(IEEE80211_MTU_MIN <= ifr->ifr_mtu && - ifr->ifr_mtu <= IEEE80211_MTU_MAX)) - error = EINVAL; - else - ifp->if_mtu = ifr->ifr_mtu; - break; - case SIOCSIFADDR: - /* - * XXX Handle this directly so we can supress if_init calls. - * XXX This should be done in ether_ioctl but for the moment - * XXX there are too many other parts of the system that - * XXX set IFF_UP and so supress if_init being called when - * XXX it should be. - */ - ifa = (struct ifaddr *) data; - switch (ifa->ifa_addr->sa_family) { -#ifdef INET - case AF_INET: - if ((ifp->if_flags & IFF_UP) == 0) { - ifp->if_flags |= IFF_UP; - ifp->if_init(ifp->if_softc); - } - arp_ifinit(ifp, ifa); - break; -#endif -#ifdef IPX - /* - * XXX - This code is probably wrong, - * but has been copied many times. - */ - case AF_IPX: { - struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr); - struct arpcom *ac = (struct arpcom *)ifp; - - if (ipx_nullhost(*ina)) - ina->x_host = *(union ipx_host *) ac->ac_enaddr; - else - bcopy((caddr_t) ina->x_host.c_host, - (caddr_t) ac->ac_enaddr, - sizeof(ac->ac_enaddr)); - /* fall thru... */ - } -#endif - default: - if ((ifp->if_flags & IFF_UP) == 0) { - ifp->if_flags |= IFF_UP; - ifp->if_init(ifp->if_softc); - } - break; - } - break; - default: - error = ether_ioctl(ifp, cmd, data); - break; - } - return error; -} diff --git a/sys/netproto/802_11/ieee80211_node.c b/sys/netproto/802_11/ieee80211_node.c deleted file mode 100644 index 68f98e3a6e..0000000000 --- a/sys/netproto/802_11/ieee80211_node.c +++ /dev/null @@ -1,702 +0,0 @@ -/* - * Copyright (c) 2001 Atsushi Onoe - * Copyright (c) 2002, 2003 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. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * 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. - * - * $FreeBSD: src/sys/net80211/ieee80211_node.c,v 1.22 2004/04/05 04:15:55 sam Exp $ - * $DragonFly: src/sys/netproto/802_11/Attic/ieee80211_node.c,v 1.1 2004/07/26 16:30:17 joerg Exp $ - */ - -#include "opt_inet.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include - -#ifdef INET -#include -#include -#endif - -static struct ieee80211_node *ieee80211_node_alloc(struct ieee80211com *); -static void ieee80211_node_free(struct ieee80211com *, struct ieee80211_node *); -static void ieee80211_node_copy(struct ieee80211com *, - struct ieee80211_node *, const struct ieee80211_node *); -static uint8_t ieee80211_node_getrssi(struct ieee80211com *, - struct ieee80211_node *); - -static void ieee80211_setup_node(struct ieee80211com *ic, - struct ieee80211_node *ni, uint8_t *macaddr); -static void _ieee80211_free_node(struct ieee80211com *, - struct ieee80211_node *); - -MALLOC_DEFINE(M_80211_NODE, "80211node", "802.11 node state"); - -void -ieee80211_node_attach(struct ifnet *ifp) -{ - struct ieee80211com *ic = (void *)ifp; - - lwkt_token_init(&ic->ic_nodetoken); - TAILQ_INIT(&ic->ic_node); - ic->ic_node_alloc = ieee80211_node_alloc; - ic->ic_node_free = ieee80211_node_free; - ic->ic_node_copy = ieee80211_node_copy; - ic->ic_node_getrssi = ieee80211_node_getrssi; - ic->ic_scangen = 1; -} - -void -ieee80211_node_lateattach(struct ifnet *ifp) -{ - struct ieee80211com *ic = (void *)ifp; - struct ieee80211_node *ni; - - ni = (*ic->ic_node_alloc)(ic); - KASSERT(ni != NULL, ("unable to setup inital BSS node")); - ni->ni_chan = IEEE80211_CHAN_ANYC; - ic->ic_bss = ni; - ic->ic_txpower = IEEE80211_TXPOWER_MAX; -} - -void -ieee80211_node_detach(struct ifnet *ifp) -{ - struct ieee80211com *ic = (void *)ifp; - - if (ic->ic_bss != NULL) - (*ic->ic_node_free)(ic, ic->ic_bss); - ieee80211_free_allnodes(ic); - lwkt_token_uninit(&ic->ic_nodetoken); -} - -/* - * AP scanning support. - */ - -/* - * Initialize the active channel set based on the set - * of available channels and the current PHY mode. - */ -static void -ieee80211_reset_scan(struct ifnet *ifp) -{ - struct ieee80211com *ic = (void *)ifp; - - memcpy(ic->ic_chan_scan, ic->ic_chan_active, - sizeof(ic->ic_chan_active)); - /* NB: hack, setup so next_scan starts with the first channel */ - if (ic->ic_bss->ni_chan == IEEE80211_CHAN_ANYC) - ic->ic_bss->ni_chan = &ic->ic_channels[IEEE80211_CHAN_MAX]; -} - -/* - * Begin an active scan. - */ -void -ieee80211_begin_scan(struct ifnet *ifp) -{ - struct ieee80211com *ic = (void *)ifp; - - /* - * In all but hostap mode scanning starts off in - * an active mode before switching to passive. - */ - if (ic->ic_opmode != IEEE80211_M_HOSTAP) { - ic->ic_flags |= IEEE80211_F_ASCAN; - ic->ic_stats.is_scan_active++; - } else - ic->ic_stats.is_scan_passive++; - if (ifp->if_flags & IFF_DEBUG) - if_printf(ifp, "begin %s scan\n", - (ic->ic_flags & IEEE80211_F_ASCAN) ? - "active" : "passive"); - /* - * Clear scan state and flush any previously seen - * AP's. Note that the latter assumes we don't act - * as both an AP and a station, otherwise we'll - * potentially flush state of stations associated - * with us. - */ - ieee80211_reset_scan(ifp); - ieee80211_free_allnodes(ic); - - /* Scan the next channel. */ - ieee80211_next_scan(ifp); -} - -/* - * Switch to the next channel marked for scanning. - */ -void -ieee80211_next_scan(struct ifnet *ifp) -{ - struct ieee80211com *ic = (void *)ifp; - struct ieee80211_channel *chan; - - chan = ic->ic_bss->ni_chan; - for (;;) { - if (++chan > &ic->ic_channels[IEEE80211_CHAN_MAX]) - chan = &ic->ic_channels[0]; - if (isset(ic->ic_chan_scan, ieee80211_chan2ieee(ic, chan))) { - /* - * Honor channels marked passive-only - * during an active scan. - */ - if ((ic->ic_flags & IEEE80211_F_ASCAN) == 0 || - (chan->ic_flags & IEEE80211_CHAN_PASSIVE) == 0) - break; - } - if (chan == ic->ic_bss->ni_chan) { - ieee80211_end_scan(ifp); - return; - } - } - clrbit(ic->ic_chan_scan, ieee80211_chan2ieee(ic, chan)); - IEEE80211_DPRINTF(("ieee80211_next_scan: chan %d->%d\n", - ieee80211_chan2ieee(ic, ic->ic_bss->ni_chan), - ieee80211_chan2ieee(ic, chan))); - ic->ic_bss->ni_chan = chan; - ieee80211_new_state(ic, IEEE80211_S_SCAN, -1); -} - -void -ieee80211_create_ibss(struct ieee80211com* ic, struct ieee80211_channel *chan) -{ - struct ieee80211_node *ni; - struct ifnet *ifp = &ic->ic_if; - - ni = ic->ic_bss; - if (ifp->if_flags & IFF_DEBUG) - if_printf(ifp, "creating ibss\n"); - ic->ic_flags |= IEEE80211_F_SIBSS; - ni->ni_chan = chan; - ni->ni_rates = ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)]; - IEEE80211_ADDR_COPY(ni->ni_macaddr, ic->ic_myaddr); - IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_myaddr); - if (ic->ic_opmode == IEEE80211_M_IBSS) - ni->ni_bssid[0] |= 0x02; /* local bit for IBSS */ - ni->ni_esslen = ic->ic_des_esslen; - memcpy(ni->ni_essid, ic->ic_des_essid, ni->ni_esslen); - ni->ni_rssi = 0; - ni->ni_rstamp = 0; - memset(ni->ni_tstamp, 0, sizeof(ni->ni_tstamp)); - ni->ni_intval = ic->ic_lintval; - ni->ni_capinfo = IEEE80211_CAPINFO_IBSS; - if (ic->ic_flags & IEEE80211_F_WEPON) - ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY; - if (ic->ic_phytype == IEEE80211_T_FH) { - ni->ni_fhdwell = 200; /* XXX */ - ni->ni_fhindex = 1; - } - ieee80211_new_state(ic, IEEE80211_S_RUN, -1); -} - -static int -ieee80211_match_bss(struct ifnet *ifp, struct ieee80211_node *ni) -{ - struct ieee80211com *ic = (void *)ifp; - uint8_t rate; - int fail; - - fail = 0; - if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, ni->ni_chan))) - fail |= 0x01; - if (ic->ic_des_chan != IEEE80211_CHAN_ANYC && - ni->ni_chan != ic->ic_des_chan) - fail |= 0x01; - if (ic->ic_opmode == IEEE80211_M_IBSS) { - if ((ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) == 0) - fail |= 0x02; - } else { - if ((ni->ni_capinfo & IEEE80211_CAPINFO_ESS) == 0) - fail |= 0x02; - } - if (ic->ic_flags & IEEE80211_F_WEPON) { - if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0) - fail |= 0x04; - } else { - /* XXX does this mean privacy is supported or required? */ - if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) - fail |= 0x04; - } - rate = ieee80211_fix_rate(ic, ni, IEEE80211_F_DONEGO); - if (rate & IEEE80211_RATE_BASIC) - fail |= 0x08; - if (ic->ic_des_esslen != 0 && - (ni->ni_esslen != ic->ic_des_esslen || - memcmp(ni->ni_essid, ic->ic_des_essid, ic->ic_des_esslen) != 0)) - fail |= 0x10; - if ((ic->ic_flags & IEEE80211_F_DESBSSID) && - !IEEE80211_ADDR_EQ(ic->ic_des_bssid, ni->ni_bssid)) - fail |= 0x20; -#ifdef IEEE80211_DEBUG - if (ifp->if_flags & IFF_DEBUG) { - printf(" %c %6D", fail ? '-' : '+', ni->ni_macaddr, ":"); - printf(" %6D%c", ni->ni_bssid, ":", fail & 0x20 ? '!' : ' '); - printf(" %3d%c", ieee80211_chan2ieee(ic, ni->ni_chan), - fail & 0x01 ? '!' : ' '); - printf(" %+4d", ni->ni_rssi); - printf(" %2dM%c", (rate & IEEE80211_RATE_VAL) / 2, - fail & 0x08 ? '!' : ' '); - printf(" %4s%c", - (ni->ni_capinfo & IEEE80211_CAPINFO_ESS) ? "ess" : - (ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) ? "ibss" : - "????", - fail & 0x02 ? '!' : ' '); - printf(" %3s%c ", - (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) ? - "wep" : "no", - fail & 0x04 ? '!' : ' '); - ieee80211_print_essid(ni->ni_essid, ni->ni_esslen); - printf("%s\n", fail & 0x10 ? "!" : ""); - } -#endif - return fail; -} - -/* - * Complete a scan of potential channels. - */ -void -ieee80211_end_scan(struct ifnet *ifp) -{ - struct ieee80211com *ic = (void *)ifp; - struct ieee80211_node *ni, *nextbs, *selbs; - int i, fail; - - ic->ic_flags &= ~IEEE80211_F_ASCAN; - ni = TAILQ_FIRST(&ic->ic_node); - - if (ic->ic_opmode == IEEE80211_M_HOSTAP) { - /* XXX off stack? */ - u_char occupied[roundup(IEEE80211_CHAN_MAX, NBBY)]; - /* - * The passive scan to look for existing AP's completed, - * select a channel to camp on. Identify the channels - * that already have one or more AP's and try to locate - * an unnoccupied one. If that fails, pick a random - * channel from the active set. - */ - for (; ni != NULL; ni = nextbs) { - ieee80211_ref_node(ni); - nextbs = TAILQ_NEXT(ni, ni_list); - setbit(occupied, ieee80211_chan2ieee(ic, ni->ni_chan)); - ieee80211_free_node(ic, ni); - } - for (i = 0; i < IEEE80211_CHAN_MAX; i++) - if (isset(ic->ic_chan_active, i) && isclr(occupied, i)) - break; - if (i == IEEE80211_CHAN_MAX) { - fail = arc4random() & 3; /* random 0-3 */ - for (i = 0; i < IEEE80211_CHAN_MAX; i++) - if (isset(ic->ic_chan_active, i) && fail-- == 0) - break; - } - ieee80211_create_ibss(ic, &ic->ic_channels[i]); - return; - } - if (ni == NULL) { - IEEE80211_DPRINTF(("%s: no scan candidate\n", __func__)); - notfound: - if (ic->ic_opmode == IEEE80211_M_IBSS && - (ic->ic_flags & IEEE80211_F_IBSSON) && - ic->ic_des_esslen != 0) { - ieee80211_create_ibss(ic, ic->ic_ibss_chan); - return; - } - /* - * Reset the list of channels to scan and start again. - */ - ieee80211_reset_scan(ifp); - ieee80211_next_scan(ifp); - return; - } - selbs = NULL; - if (ifp->if_flags & IFF_DEBUG) - if_printf(ifp, "\tmacaddr bssid chan rssi rate flag wep essid\n"); - for (; ni != NULL; ni = nextbs) { - ieee80211_ref_node(ni); - nextbs = TAILQ_NEXT(ni, ni_list); - if (ni->ni_fails) { - /* - * The configuration of the access points may change - * during my scan. So delete the entry for the AP - * and retry to associate if there is another beacon. - */ - if (ni->ni_fails++ > 2) - ieee80211_free_node(ic, ni); - continue; - } - if (ieee80211_match_bss(ifp, ni) == 0) { - if (selbs == NULL) - selbs = ni; - else if (ni->ni_rssi > selbs->ni_rssi) { - ieee80211_unref_node(&selbs); - selbs = ni; - } else - ieee80211_unref_node(&ni); - } else { - ieee80211_unref_node(&ni); - } - } - if (selbs == NULL) - goto notfound; - (*ic->ic_node_copy)(ic, ic->ic_bss, selbs); - if (ic->ic_opmode == IEEE80211_M_IBSS) { - ieee80211_fix_rate(ic, ic->ic_bss, IEEE80211_F_DOFRATE | - IEEE80211_F_DONEGO | IEEE80211_F_DODEL); - if (ic->ic_bss->ni_rates.rs_nrates == 0) { - selbs->ni_fails++; - ieee80211_unref_node(&selbs); - goto notfound; - } - ieee80211_unref_node(&selbs); - /* - * Discard scan set; the nodes have a refcnt of zero - * and have not asked the driver to setup private - * node state. Let them be repopulated on demand either - * through transmission (ieee80211_find_txnode) or receipt - * of a probe response (to be added). - */ - ieee80211_free_allnodes(ic); - ieee80211_new_state(ic, IEEE80211_S_RUN, -1); - } else { - ieee80211_unref_node(&selbs); - ieee80211_new_state(ic, IEEE80211_S_AUTH, -1); - } -} - -static struct ieee80211_node * -ieee80211_node_alloc(struct ieee80211com *ic) -{ - struct ieee80211_node *ni; - MALLOC(ni, struct ieee80211_node *, sizeof(struct ieee80211_node), - M_80211_NODE, M_NOWAIT | M_ZERO); - return ni; -} - -static void -ieee80211_node_free(struct ieee80211com *ic, struct ieee80211_node *ni) -{ - FREE(ni, M_80211_NODE); -} - -static void -ieee80211_node_copy(struct ieee80211com *ic, - struct ieee80211_node *dst, const struct ieee80211_node *src) -{ - *dst = *src; -} - -static uint8_t -ieee80211_node_getrssi(struct ieee80211com *ic, struct ieee80211_node *ni) -{ - return ni->ni_rssi; -} - -static void -ieee80211_setup_node(struct ieee80211com *ic, - struct ieee80211_node *ni, uint8_t *macaddr) -{ - lwkt_tokref ilock; - int hash; - - IEEE80211_ADDR_COPY(ni->ni_macaddr, macaddr); - hash = IEEE80211_NODE_HASH(macaddr); - ni->ni_refcnt = 1; /* mark referenced */ - lwkt_gettoken(&ilock, &ic->ic_nodetoken); - TAILQ_INSERT_TAIL(&ic->ic_node, ni, ni_list); - LIST_INSERT_HEAD(&ic->ic_hash[hash], ni, ni_hash); - /* - * Note we don't enable the inactive timer when acting - * as a station. Nodes created in this mode represent - * AP's identified while scanning. If we time them out - * then several things happen: we can't return the data - * to users to show the list of AP's we encountered, and - * more importantly, we'll incorrectly deauthenticate - * ourself because the inactivity timer will kick us off. - */ - if (ic->ic_opmode != IEEE80211_M_STA) - ic->ic_inact_timer = IEEE80211_INACT_WAIT; - lwkt_reltoken(&ilock); -} - -struct ieee80211_node * -ieee80211_alloc_node(struct ieee80211com *ic, uint8_t *macaddr) -{ - struct ieee80211_node *ni = (*ic->ic_node_alloc)(ic); - if (ni != NULL) - ieee80211_setup_node(ic, ni, macaddr); - else - ic->ic_stats.is_rx_nodealloc++; - return ni; -} - -struct ieee80211_node * -ieee80211_dup_bss(struct ieee80211com *ic, uint8_t *macaddr) -{ - struct ieee80211_node *ni = (*ic->ic_node_alloc)(ic); - if (ni != NULL) { - ieee80211_setup_node(ic, ni, macaddr); - /* - * Inherit from ic_bss. - */ - IEEE80211_ADDR_COPY(ni->ni_bssid, ic->ic_bss->ni_bssid); - ni->ni_chan = ic->ic_bss->ni_chan; - } else - ic->ic_stats.is_rx_nodealloc++; - return ni; -} - -static struct ieee80211_node * -_ieee80211_find_node(struct ieee80211com *ic, uint8_t *macaddr) -{ - struct ieee80211_node *ni; - int hash; - - hash = IEEE80211_NODE_HASH(macaddr); - LIST_FOREACH(ni, &ic->ic_hash[hash], ni_hash) { - if (IEEE80211_ADDR_EQ(ni->ni_macaddr, macaddr)) { - atomic_add_int(&ni->ni_refcnt, 1);/* mark referenced */ - return ni; - } - } - return NULL; -} - -struct ieee80211_node * -ieee80211_find_node(struct ieee80211com *ic, uint8_t *macaddr) -{ - struct ieee80211_node *ni; - struct lwkt_tokref ilock; - - lwkt_gettoken(&ilock, &ic->ic_nodetoken); - ni = _ieee80211_find_node(ic, macaddr); - lwkt_reltoken(&ilock); - return ni; -} - -/* - * Return a reference to the appropriate node for sending - * a data frame. This handles node discovery in adhoc networks. - */ -struct ieee80211_node * -ieee80211_find_txnode(struct ieee80211com *ic, uint8_t *macaddr) -{ - struct ieee80211_node *ni; - struct lwkt_tokref ilock; - - /* - * The destination address should be in the node table - * unless we are operating in station mode or this is a - * multicast/broadcast frame. - */ - if (ic->ic_opmode == IEEE80211_M_STA || IEEE80211_IS_MULTICAST(macaddr)) - return ic->ic_bss; - - /* XXX can't hold lock across dup_bss 'cuz of recursive locking */ - lwkt_gettoken(&ilock, &ic->ic_nodetoken); - ni = _ieee80211_find_node(ic, macaddr); - lwkt_reltoken(&ilock); - ni = _ieee80211_find_node(ic, macaddr); - if (ni == NULL && - (ic->ic_opmode == IEEE80211_M_IBSS || - ic->ic_opmode == IEEE80211_M_AHDEMO)) { - /* - * Fake up a node; this handles node discovery in - * adhoc mode. Note that for the driver's benefit - * we we treat this like an association so the driver - * has an opportunity to setup it's private state. - * - * XXX need better way to handle this; issue probe - * request so we can deduce rate set, etc. - */ - ni = ieee80211_dup_bss(ic, macaddr); - if (ni != NULL) { - /* XXX no rate negotiation; just dup */ - ni->ni_rates = ic->ic_bss->ni_rates; - if (ic->ic_newassoc) - (*ic->ic_newassoc)(ic, ni, 1); - } - } - return ni; -} - -/* - * Like find but search based on the channel too. - */ -struct ieee80211_node * -ieee80211_lookup_node(struct ieee80211com *ic, - uint8_t *macaddr, struct ieee80211_channel *chan) -{ - struct ieee80211_node *ni; - int hash; - lwkt_tokref ilock; - - hash = IEEE80211_NODE_HASH(macaddr); - lwkt_gettoken(&ilock, &ic->ic_nodetoken); - LIST_FOREACH(ni, &ic->ic_hash[hash], ni_hash) { - if (IEEE80211_ADDR_EQ(ni->ni_macaddr, macaddr) && - ni->ni_chan == chan) { - atomic_add_int(&ni->ni_refcnt, 1);/* mark referenced */ - break; - } - } - lwkt_reltoken(&ilock); - return ni; -} - -static void -_ieee80211_free_node(struct ieee80211com *ic, struct ieee80211_node *ni) -{ - KASSERT(ni != ic->ic_bss, ("freeing bss node")); - - TAILQ_REMOVE(&ic->ic_node, ni, ni_list); - LIST_REMOVE(ni, ni_hash); - if (TAILQ_EMPTY(&ic->ic_node)) - ic->ic_inact_timer = 0; - (*ic->ic_node_free)(ic, ni); -} - -void -ieee80211_free_node(struct ieee80211com *ic, struct ieee80211_node *ni) -{ - lwkt_tokref ilock; - - KASSERT(ni != ic->ic_bss, ("freeing ic_bss")); - - /* XXX DF atomic op */ - crit_enter(); - --ni->ni_refcnt; - if (ni->ni_refcnt == 0) { - crit_exit(); - lwkt_gettoken(&ilock, &ic->ic_nodetoken); - _ieee80211_free_node(ic, ni); - lwkt_reltoken(&ilock); - } else { - crit_exit(); - } -} - -void -ieee80211_free_allnodes(struct ieee80211com *ic) -{ - struct ieee80211_node *ni; - lwkt_tokref ilock; - - lwkt_gettoken(&ilock, &ic->ic_nodetoken); - while ((ni = TAILQ_FIRST(&ic->ic_node)) != NULL) - _ieee80211_free_node(ic, ni); - lwkt_reltoken(&ilock); -} - -/* - * Timeout inactive nodes. Note that we cannot hold the node - * lock while sending a frame as this would lead to a LOR. - * Instead we use a generation number to mark nodes that we've - * scanned and drop the lock and restart a scan if we have to - * time out a node. Since we are single-threaded by virtue of - * controlling the inactivity timer we can be sure this will - * process each node only once. - */ -void -ieee80211_timeout_nodes(struct ieee80211com *ic) -{ - struct ieee80211_node *ni; - lwkt_tokref ilock; - u_int gen = ic->ic_scangen++; /* NB: ok 'cuz single-threaded*/ - -restart: - lwkt_gettoken(&ilock, &ic->ic_nodetoken); - TAILQ_FOREACH(ni, &ic->ic_node, ni_list) { - if (ni->ni_scangen == gen) /* previously handled */ - continue; - ni->ni_scangen = gen; - if (++ni->ni_inact > IEEE80211_INACT_MAX) { - IEEE80211_DPRINTF(("station %6D timed out " - "due to inactivity (%u secs)\n", - ni->ni_macaddr, ":", ni->ni_inact)); - /* - * Send a deauthenticate frame. - * - * Drop the node lock before sending the - * deauthentication frame in case the driver takes - * a lock, as this will result in a LOR between the - * node lock and the driver lock. - */ - lwkt_reltoken(&ilock); - IEEE80211_SEND_MGMT(ic, ni, - IEEE80211_FC0_SUBTYPE_DEAUTH, - IEEE80211_REASON_AUTH_EXPIRE); - ieee80211_free_node(ic, ni); - ic->ic_stats.is_node_timeout++; - goto restart; - } - } - if (!TAILQ_EMPTY(&ic->ic_node)) - ic->ic_inact_timer = IEEE80211_INACT_WAIT; - lwkt_reltoken(&ilock); -} - -void -ieee80211_iterate_nodes(struct ieee80211com *ic, ieee80211_iter_func *f, void *arg) -{ - struct ieee80211_node *ni; - struct lwkt_tokref ilock; - - lwkt_gettoken(&ilock, &ic->ic_nodetoken); - TAILQ_FOREACH(ni, &ic->ic_node, ni_list) - (*f)(arg, ni); - lwkt_reltoken(&ilock); -} diff --git a/sys/netproto/802_11/ieee80211_output.c b/sys/netproto/802_11/ieee80211_output.c deleted file mode 100644 index fdba325666..0000000000 --- a/sys/netproto/802_11/ieee80211_output.c +++ /dev/null @@ -1,573 +0,0 @@ -/* - * Copyright (c) 2001 Atsushi Onoe - * Copyright (c) 2002, 2003 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. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * 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. - * - * $FreeBSD: src/sys/net80211/ieee80211_output.c,v 1.10 2004/04/02 23:25:39 sam Exp $ - * $DragonFly: src/sys/netproto/802_11/Attic/ieee80211_output.c,v 1.1 2004/07/26 16:30:17 joerg Exp $ - */ - -#include "opt_inet.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include - -#ifdef INET -#include -#include -#endif - -/* - * Send a management frame to the specified node. The node pointer - * must have a reference as the pointer will be passed to the driver - * and potentially held for a long time. If the frame is successfully - * dispatched to the driver, then it is responsible for freeing the - * reference (and potentially free'ing up any associated storage). - */ -static int -ieee80211_mgmt_output(struct ifnet *ifp, struct ieee80211_node *ni, - struct mbuf *m, int type) -{ - struct ieee80211com *ic = (void *)ifp; - struct ieee80211_frame *wh; - - KASSERT(ni != NULL, ("null node")); - ni->ni_inact = 0; - - /* - * Yech, hack alert! We want to pass the node down to the - * driver's start routine. If we don't do so then the start - * routine must immediately look it up again and that can - * cause a lock order reversal if, for example, this frame - * is being sent because the station is being timedout and - * the frame being sent is a DEAUTH message. We could stick - * this in an m_tag and tack that on to the mbuf. However - * that's rather expensive to do for every frame so instead - * we stuff it in the rcvif field since outbound frames do - * not (presently) use this. - */ - M_PREPEND(m, sizeof(struct ieee80211_frame), MB_DONTWAIT); - if (m == NULL) - return ENOMEM; - KASSERT(m->m_pkthdr.rcvif == NULL, ("rcvif not null")); - m->m_pkthdr.rcvif = (void *)ni; - - wh = mtod(m, struct ieee80211_frame *); - wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_MGT | type; - wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; - *(uint16_t *)wh->i_dur = 0; - *(uint16_t *)wh->i_seq = - htole16(ni->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT); - ni->ni_txseq++; - IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_macaddr); - IEEE80211_ADDR_COPY(wh->i_addr2, ic->ic_myaddr); - IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid); - - if (ifp->if_flags & IFF_DEBUG) { - /* avoid to print too many frames */ - if (ic->ic_opmode == IEEE80211_M_IBSS || -#ifdef IEEE80211_DEBUG - ieee80211_debug > 1 || -#endif - (type & IEEE80211_FC0_SUBTYPE_MASK) != - IEEE80211_FC0_SUBTYPE_PROBE_RESP) - if_printf(ifp, "sending %s to %6D on channel %u\n", - ieee80211_mgt_subtype_name[ - (type & IEEE80211_FC0_SUBTYPE_MASK) - >> IEEE80211_FC0_SUBTYPE_SHIFT], - ni->ni_macaddr, ":", - ieee80211_chan2ieee(ic, ni->ni_chan)); - } - - IF_ENQUEUE(&ic->ic_mgtq, m); - ifp->if_timer = 1; - (*ifp->if_start)(ifp); - return 0; -} - -/* - * Encapsulate an outbound data frame. The mbuf chain is updated and - * a reference to the destination node is returned. If an error is - * encountered NULL is returned and the node reference will also be NULL. - * - * NB: The caller is responsible for free'ing a returned node reference. - * The convention is ic_bss is not reference counted; the caller must - * maintain that. - */ -struct mbuf * -ieee80211_encap(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node **pni) -{ - struct ieee80211com *ic = (void *)ifp; - struct ether_header eh; - struct ieee80211_frame *wh; - struct ieee80211_node *ni = NULL; - struct llc *llc; - - if (m->m_len < sizeof(struct ether_header)) { - m = m_pullup(m, sizeof(struct ether_header)); - if (m == NULL) { - ic->ic_stats.is_tx_nombuf++; - goto bad; - } - } - memcpy(&eh, mtod(m, caddr_t), sizeof(struct ether_header)); - - ni = ieee80211_find_txnode(ic, eh.ether_dhost); - if (ni == NULL) { - IEEE80211_DPRINTF(("%s: no node for dst %6D, discard frame\n", - __func__, eh.ether_dhost, ":")); - ic->ic_stats.is_tx_nonode++; - goto bad; - } - ni->ni_inact = 0; - - m_adj(m, sizeof(struct ether_header) - sizeof(struct llc)); - llc = mtod(m, struct llc *); - llc->llc_dsap = llc->llc_ssap = LLC_SNAP_LSAP; - llc->llc_control = LLC_UI; - llc->llc_snap.org_code[0] = 0; - llc->llc_snap.org_code[1] = 0; - llc->llc_snap.org_code[2] = 0; - llc->llc_snap.ether_type = eh.ether_type; - M_PREPEND(m, sizeof(struct ieee80211_frame), MB_DONTWAIT); - if (m == NULL) { - ic->ic_stats.is_tx_nombuf++; - goto bad; - } - wh = mtod(m, struct ieee80211_frame *); - wh->i_fc[0] = IEEE80211_FC0_VERSION_0 | IEEE80211_FC0_TYPE_DATA; - *(uint16_t *)wh->i_dur = 0; - *(uint16_t *)wh->i_seq = - htole16(ni->ni_txseq << IEEE80211_SEQ_SEQ_SHIFT); - ni->ni_txseq++; - switch (ic->ic_opmode) { - case IEEE80211_M_STA: - wh->i_fc[1] = IEEE80211_FC1_DIR_TODS; - IEEE80211_ADDR_COPY(wh->i_addr1, ni->ni_bssid); - IEEE80211_ADDR_COPY(wh->i_addr2, eh.ether_shost); - IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_dhost); - break; - case IEEE80211_M_IBSS: - case IEEE80211_M_AHDEMO: - wh->i_fc[1] = IEEE80211_FC1_DIR_NODS; - IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost); - IEEE80211_ADDR_COPY(wh->i_addr2, eh.ether_shost); - IEEE80211_ADDR_COPY(wh->i_addr3, ni->ni_bssid); - break; - case IEEE80211_M_HOSTAP: - wh->i_fc[1] = IEEE80211_FC1_DIR_FROMDS; - IEEE80211_ADDR_COPY(wh->i_addr1, eh.ether_dhost); - IEEE80211_ADDR_COPY(wh->i_addr2, ni->ni_bssid); - IEEE80211_ADDR_COPY(wh->i_addr3, eh.ether_shost); - break; - case IEEE80211_M_MONITOR: - goto bad; - } - *pni = ni; - return m; -bad: - if (m != NULL) - m_freem(m); - if (ni && ni != ic->ic_bss) - ieee80211_free_node(ic, ni); - *pni = NULL; - return NULL; -} - -/* - * Add a supported rates element id to a frame. - */ -uint8_t * -ieee80211_add_rates(uint8_t *frm, const struct ieee80211_rateset *rs) -{ - int nrates; - - *frm++ = IEEE80211_ELEMID_RATES; - nrates = rs->rs_nrates; - if (nrates > IEEE80211_RATE_SIZE) - nrates = IEEE80211_RATE_SIZE; - *frm++ = nrates; - memcpy(frm, rs->rs_rates, nrates); - return frm + nrates; -} - -/* - * Add an extended supported rates element id to a frame. - */ -uint8_t * -ieee80211_add_xrates(uint8_t *frm, const struct ieee80211_rateset *rs) -{ - /* - * Add an extended supported rates element if operating in 11g mode. - */ - if (rs->rs_nrates > IEEE80211_RATE_SIZE) { - int nrates = rs->rs_nrates - IEEE80211_RATE_SIZE; - *frm++ = IEEE80211_ELEMID_XRATES; - *frm++ = nrates; - memcpy(frm, rs->rs_rates + IEEE80211_RATE_SIZE, nrates); - frm += nrates; - } - return frm; -} - -/* - * Add an ssid elemet to a frame. - */ -static uint8_t * -ieee80211_add_ssid(uint8_t *frm, const uint8_t *ssid, u_int len) -{ - *frm++ = IEEE80211_ELEMID_SSID; - *frm++ = len; - memcpy(frm, ssid, len); - return frm + len; -} - -static struct mbuf * -ieee80211_getmbuf(int flags, int type, u_int pktlen) -{ - struct mbuf *m; - - KASSERT(pktlen <= MCLBYTES, ("802.11 packet too large: %u", pktlen)); - if (pktlen <= MHLEN) - MGETHDR(m, flags, type); - else - m = m_getcl(flags, type, M_PKTHDR); - return m; -} - -/* - * Send a management frame. The node is for the destination (or ic_bss - * when in station mode). Nodes other than ic_bss have their reference - * count bumped to reflect our use for an indeterminant time. - */ -int -ieee80211_send_mgmt(struct ieee80211com *ic, struct ieee80211_node *ni, - int type, int arg) -{ -#define senderr(_x, _v) do { ic->ic_stats._v++; ret = _x; goto bad; } while (0) - struct ifnet *ifp = &ic->ic_if; - struct mbuf *m; - uint8_t *frm; - enum ieee80211_phymode mode; - uint16_t capinfo; - int ret, timer; - - KASSERT(ni != NULL, ("null node")); - - /* - * Hold a reference on the node so it doesn't go away until after - * the xmit is complete all the way in the driver. On error we - * will remove our reference. - */ - if (ni != ic->ic_bss) - ieee80211_ref_node(ni); - timer = 0; - switch (type) { - case IEEE80211_FC0_SUBTYPE_PROBE_REQ: - /* - * prreq frame format - * [tlv] ssid - * [tlv] supported rates - * [tlv] extended supported rates - */ - m = ieee80211_getmbuf(MB_DONTWAIT, MT_DATA, - 2 + ic->ic_des_esslen - + 2 + IEEE80211_RATE_SIZE - + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)); - if (m == NULL) - senderr(ENOMEM, is_tx_nombuf); - m->m_data += sizeof(struct ieee80211_frame); - frm = mtod(m, uint8_t *); - frm = ieee80211_add_ssid(frm, ic->ic_des_essid, ic->ic_des_esslen); - mode = ieee80211_chan2mode(ic, ni->ni_chan); - frm = ieee80211_add_rates(frm, &ic->ic_sup_rates[mode]); - frm = ieee80211_add_xrates(frm, &ic->ic_sup_rates[mode]); - m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *); - - timer = IEEE80211_TRANS_WAIT; - break; - - case IEEE80211_FC0_SUBTYPE_PROBE_RESP: - /* - * probe response frame format - * [8] time stamp - * [2] beacon interval - * [2] cabability information - * [tlv] ssid - * [tlv] supported rates - * [tlv] parameter set (FH/DS) - * [tlv] parameter set (IBSS) - * [tlv] extended supported rates - */ - m = ieee80211_getmbuf(MB_DONTWAIT, MT_DATA, - 8 + 2 + 2 + 2 - + 2 + ni->ni_esslen - + 2 + IEEE80211_RATE_SIZE - + (ic->ic_phytype == IEEE80211_T_FH ? 7 : 3) - + 6 - + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)); - if (m == NULL) - senderr(ENOMEM, is_tx_nombuf); - m->m_data += sizeof(struct ieee80211_frame); - frm = mtod(m, uint8_t *); - - memset(frm, 0, 8); /* timestamp should be filled later */ - frm += 8; - *(uint16_t *)frm = htole16(ic->ic_bss->ni_intval); - frm += 2; - if (ic->ic_opmode == IEEE80211_M_IBSS) - capinfo = IEEE80211_CAPINFO_IBSS; - else - capinfo = IEEE80211_CAPINFO_ESS; - if (ic->ic_flags & IEEE80211_F_WEPON) - capinfo |= IEEE80211_CAPINFO_PRIVACY; - if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && - IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) - capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE; - *(uint16_t *)frm = htole16(capinfo); - frm += 2; - - frm = ieee80211_add_ssid(frm, ic->ic_bss->ni_essid, - ic->ic_bss->ni_esslen); - frm = ieee80211_add_rates(frm, &ic->ic_bss->ni_rates); - - if (ic->ic_phytype == IEEE80211_T_FH) { - *frm++ = IEEE80211_ELEMID_FHPARMS; - *frm++ = 5; - *frm++ = ni->ni_fhdwell & 0x00ff; - *frm++ = (ni->ni_fhdwell >> 8) & 0x00ff; - *frm++ = IEEE80211_FH_CHANSET( - ieee80211_chan2ieee(ic, ni->ni_chan)); - *frm++ = IEEE80211_FH_CHANPAT( - ieee80211_chan2ieee(ic, ni->ni_chan)); - *frm++ = ni->ni_fhindex; - } else { - *frm++ = IEEE80211_ELEMID_DSPARMS; - *frm++ = 1; - *frm++ = ieee80211_chan2ieee(ic, ni->ni_chan); - } - - if (ic->ic_opmode == IEEE80211_M_IBSS) { - *frm++ = IEEE80211_ELEMID_IBSSPARMS; - *frm++ = 2; - *frm++ = 0; *frm++ = 0; /* TODO: ATIM window */ - } else { /* IEEE80211_M_HOSTAP */ - /* TODO: TIM */ - *frm++ = IEEE80211_ELEMID_TIM; - *frm++ = 4; /* length */ - *frm++ = 0; /* DTIM count */ - *frm++ = 1; /* DTIM period */ - *frm++ = 0; /* bitmap control */ - *frm++ = 0; /* Partial Virtual Bitmap (variable length) */ - } - frm = ieee80211_add_xrates(frm, &ic->ic_bss->ni_rates); - m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *); - break; - - case IEEE80211_FC0_SUBTYPE_AUTH: - MGETHDR(m, MB_DONTWAIT, MT_DATA); - if (m == NULL) - senderr(ENOMEM, is_tx_nombuf); - MH_ALIGN(m, 2 * 3); - m->m_pkthdr.len = m->m_len = 6; - frm = mtod(m, uint8_t *); - /* TODO: shared key auth */ - ((uint16_t *)frm)[0] = htole16(IEEE80211_AUTH_ALG_OPEN); - ((uint16_t *)frm)[1] = htole16(arg); /* sequence number */ - ((uint16_t *)frm)[2] = 0; /* status */ - if (ic->ic_opmode == IEEE80211_M_STA) - timer = IEEE80211_TRANS_WAIT; - break; - - case IEEE80211_FC0_SUBTYPE_DEAUTH: - if (ifp->if_flags & IFF_DEBUG) - if_printf(ifp, "station %6D deauthenticate (reason %d)\n", - ni->ni_macaddr, ":", arg); - MGETHDR(m, MB_DONTWAIT, MT_DATA); - if (m == NULL) - senderr(ENOMEM, is_tx_nombuf); - MH_ALIGN(m, 2); - m->m_pkthdr.len = m->m_len = 2; - *mtod(m, uint16_t *) = htole16(arg); /* reason */ - break; - - case IEEE80211_FC0_SUBTYPE_ASSOC_REQ: - case IEEE80211_FC0_SUBTYPE_REASSOC_REQ: - /* - * asreq frame format - * [2] capability information - * [2] listen interval - * [6*] current AP address (reassoc only) - * [tlv] ssid - * [tlv] supported rates - * [tlv] extended supported rates - */ - m = ieee80211_getmbuf(MB_DONTWAIT, MT_DATA, - sizeof(capinfo) - + sizeof(uint16_t) - + IEEE80211_ADDR_LEN - + 2 + ni->ni_esslen - + 2 + IEEE80211_RATE_SIZE - + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)); - if (m == NULL) - senderr(ENOMEM, is_tx_nombuf); - m->m_data += sizeof(struct ieee80211_frame); - frm = mtod(m, uint8_t *); - - capinfo = 0; - if (ic->ic_opmode == IEEE80211_M_IBSS) - capinfo |= IEEE80211_CAPINFO_IBSS; - else /* IEEE80211_M_STA */ - capinfo |= IEEE80211_CAPINFO_ESS; - if (ic->ic_flags & IEEE80211_F_WEPON) - capinfo |= IEEE80211_CAPINFO_PRIVACY; - /* - * NB: Some 11a AP's reject the request when - * short premable is set. - */ - if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && - IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) - capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE; - if (ic->ic_flags & IEEE80211_F_SHSLOT) - capinfo |= IEEE80211_CAPINFO_SHORT_SLOTTIME; - *(uint16_t *)frm = htole16(capinfo); - frm += 2; - - *(uint16_t *)frm = htole16(ic->ic_lintval); - frm += 2; - - if (type == IEEE80211_FC0_SUBTYPE_REASSOC_REQ) { - IEEE80211_ADDR_COPY(frm, ic->ic_bss->ni_bssid); - frm += IEEE80211_ADDR_LEN; - } - - frm = ieee80211_add_ssid(frm, ni->ni_essid, ni->ni_esslen); - frm = ieee80211_add_rates(frm, &ni->ni_rates); - frm = ieee80211_add_xrates(frm, &ni->ni_rates); - m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *); - - timer = IEEE80211_TRANS_WAIT; - break; - - case IEEE80211_FC0_SUBTYPE_ASSOC_RESP: - case IEEE80211_FC0_SUBTYPE_REASSOC_RESP: - /* - * asreq frame format - * [2] capability information - * [2] status - * [2] association ID - * [tlv] supported rates - * [tlv] extended supported rates - */ - m = ieee80211_getmbuf(MB_DONTWAIT, MT_DATA, - sizeof(capinfo) - + sizeof(uint16_t) - + sizeof(uint16_t) - + 2 + IEEE80211_RATE_SIZE - + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE)); - if (m == NULL) - senderr(ENOMEM, is_tx_nombuf); - m->m_data += sizeof(struct ieee80211_frame); - frm = mtod(m, uint8_t *); - - capinfo = IEEE80211_CAPINFO_ESS; - if (ic->ic_flags & IEEE80211_F_WEPON) - capinfo |= IEEE80211_CAPINFO_PRIVACY; - if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && - IEEE80211_IS_CHAN_2GHZ(ni->ni_chan)) - capinfo |= IEEE80211_CAPINFO_SHORT_PREAMBLE; - *(uint16_t *)frm = htole16(capinfo); - frm += 2; - - *(uint16_t *)frm = htole16(arg); /* status */ - frm += 2; - - if (arg == IEEE80211_STATUS_SUCCESS) - *(uint16_t *)frm = htole16(ni->ni_associd); - frm += 2; - - frm = ieee80211_add_rates(frm, &ni->ni_rates); - frm = ieee80211_add_xrates(frm, &ni->ni_rates); - m->m_pkthdr.len = m->m_len = frm - mtod(m, uint8_t *); - break; - - case IEEE80211_FC0_SUBTYPE_DISASSOC: - if (ifp->if_flags & IFF_DEBUG) - if_printf(ifp, "station %6D disassociate (reason %d)\n", - ni->ni_macaddr, ":", arg); - MGETHDR(m, MB_DONTWAIT, MT_DATA); - if (m == NULL) - senderr(ENOMEM, is_tx_nombuf); - MH_ALIGN(m, 2); - m->m_pkthdr.len = m->m_len = 2; - *mtod(m, uint16_t *) = htole16(arg); /* reason */ - break; - - default: - IEEE80211_DPRINTF(("%s: invalid mgmt frame type %u\n", - __func__, type)); - senderr(EINVAL, is_tx_unknownmgt); - /* NOTREACHED */ - } - - ret = ieee80211_mgmt_output(ifp, ni, m, type); - if (ret == 0) { - if (timer) - ic->ic_mgt_timer = timer; - } else { -bad: - if (ni != ic->ic_bss) /* remove ref we added */ - ieee80211_free_node(ic, ni); - } - return ret; -#undef senderr -} diff --git a/sys/netproto/802_11/ieee80211_proto.c b/sys/netproto/802_11/ieee80211_proto.c deleted file mode 100644 index b5fe72eefd..0000000000 --- a/sys/netproto/802_11/ieee80211_proto.c +++ /dev/null @@ -1,514 +0,0 @@ -/* - * Copyright (c) 2001 Atsushi Onoe - * Copyright (c) 2002, 2003 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. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * 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. - * - * $FreeBSD: src/sys/net80211/ieee80211_proto.c,v 1.8 2004/04/02 20:22:25 sam Exp $ - * $DragonFly: src/sys/netproto/802_11/Attic/ieee80211_proto.c,v 1.1 2004/07/26 16:30:17 joerg Exp $ - */ - -/* - * IEEE 802.11 protocol support. - */ - -#include "opt_inet.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -#include - -#include - -#ifdef INET -#include -#include -#endif - -#define IEEE80211_RATE2MBS(r) (((r) & IEEE80211_RATE_VAL) / 2) - -const char *ieee80211_mgt_subtype_name[] = { - "assoc_req", "assoc_resp", "reassoc_req", "reassoc_resp", - "probe_req", "probe_resp", "reserved#6", "reserved#7", - "beacon", "atim", "disassoc", "auth", - "deauth", "reserved#13", "reserved#14", "reserved#15" -}; -const char *ieee80211_state_name[IEEE80211_S_MAX] = { - "INIT", /* IEEE80211_S_INIT */ - "SCAN", /* IEEE80211_S_SCAN */ - "AUTH", /* IEEE80211_S_AUTH */ - "ASSOC", /* IEEE80211_S_ASSOC */ - "RUN" /* IEEE80211_S_RUN */ -}; - -static int ieee80211_newstate(struct ieee80211com *, enum ieee80211_state, int); - -void -ieee80211_proto_attach(struct ifnet *ifp) -{ - struct ieee80211com *ic = (void *)ifp; - - ifp->if_hdrlen = sizeof(struct ieee80211_frame); - -#ifdef notdef - ic->ic_rtsthreshold = IEEE80211_RTS_DEFAULT; -#else - ic->ic_rtsthreshold = IEEE80211_RTS_MAX; -#endif - ic->ic_fragthreshold = 2346; /* XXX not used yet */ - ic->ic_fixed_rate = -1; /* no fixed rate */ - ic->ic_protmode = IEEE80211_PROT_CTSONLY; - - /* protocol state change handler */ - ic->ic_newstate = ieee80211_newstate; - - /* initialize management frame handlers */ - ic->ic_recv_mgmt = ieee80211_recv_mgmt; - ic->ic_send_mgmt = ieee80211_send_mgmt; -} - -void -ieee80211_proto_detach(struct ifnet *ifp) -{ - struct ieee80211com *ic = (void *)ifp; - - IF_DRAIN(&ic->ic_mgtq); -} - -void -ieee80211_print_essid(uint8_t *essid, int len) -{ - int i; - uint8_t *p; - - if (len > IEEE80211_NWID_LEN) - len = IEEE80211_NWID_LEN; - /* determine printable or not */ - for (i = 0, p = essid; i < len; i++, p++) { - if (*p < ' ' || *p > 0x7e) - break; - } - if (i == len) { - printf("\""); - for (i = 0, p = essid; i < len; i++, p++) - printf("%c", *p); - printf("\""); - } else { - printf("0x"); - for (i = 0, p = essid; i < len; i++, p++) - printf("%02x", *p); - } -} - -void -ieee80211_dump_pkt(uint8_t *buf, int len, int rate, int rssi) -{ - struct ieee80211_frame *wh; - int i; - - wh = (struct ieee80211_frame *)buf; - switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) { - case IEEE80211_FC1_DIR_NODS: - printf("NODS %6D->%6D(%6D)", wh->i_addr2, ":", - wh->i_addr1, ":", wh->i_addr3, ":"); - break; - case IEEE80211_FC1_DIR_TODS: - printf("TODS %6D->%6D(%6D)", wh->i_addr2, ":", - wh->i_addr3, ":", wh->i_addr1, ":"); - break; - case IEEE80211_FC1_DIR_FROMDS: - printf("FRDS %6D->%6D(%6D)", wh->i_addr3, ":", - wh->i_addr1, ":", wh->i_addr2, ":"); - break; - case IEEE80211_FC1_DIR_DSTODS: - printf("DSDS %6D->%6D(%6D->%6D)", (uint8_t *)&wh[1], ":", - wh->i_addr3, ":", wh->i_addr2, ":", wh->i_addr1, ":"); - break; - } - switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) { - case IEEE80211_FC0_TYPE_DATA: - printf(" data"); - break; - case IEEE80211_FC0_TYPE_MGT: - printf(" %s", ieee80211_mgt_subtype_name[ - (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) - >> IEEE80211_FC0_SUBTYPE_SHIFT]); - break; - default: - printf(" type#%d", wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK); - break; - } - if (wh->i_fc[1] & IEEE80211_FC1_WEP) - printf(" WEP"); - if (rate >= 0) - printf(" %dM", rate / 2); - if (rssi >= 0) - printf(" +%d", rssi); - printf("\n"); - if (len > 0) { - for (i = 0; i < len; i++) { - if ((i & 1) == 0) - printf(" "); - printf("%02x", buf[i]); - } - printf("\n"); - } -} - -int -ieee80211_fix_rate(struct ieee80211com *ic, struct ieee80211_node *ni, int flags) -{ -#define RV(v) ((v) & IEEE80211_RATE_VAL) - int i, j, ignore, error; - int okrate, badrate; - struct ieee80211_rateset *srs, *nrs; - uint8_t r; - - error = 0; - okrate = badrate = 0; - srs = &ic->ic_sup_rates[ieee80211_chan2mode(ic, ni->ni_chan)]; - nrs = &ni->ni_rates; - for (i = 0; i < nrs->rs_nrates; ) { - ignore = 0; - if (flags & IEEE80211_F_DOSORT) { - /* - * Sort rates. - */ - for (j = i + 1; j < nrs->rs_nrates; j++) { - if (RV(nrs->rs_rates[i]) > RV(nrs->rs_rates[j])) { - r = nrs->rs_rates[i]; - nrs->rs_rates[i] = nrs->rs_rates[j]; - nrs->rs_rates[j] = r; - } - } - } - r = nrs->rs_rates[i] & IEEE80211_RATE_VAL; - badrate = r; - if (flags & IEEE80211_F_DOFRATE) { - /* - * Apply fixed rate constraint. Note that we do - * not apply the constraint to basic rates as - * otherwise we may not be able to associate if - * the rate set we submit to the AP is invalid - * (e.g. fix rate at 36Mb/s which is not a basic - * rate for 11a operation). - */ - if ((nrs->rs_rates[i] & IEEE80211_RATE_BASIC) == 0 && - ic->ic_fixed_rate >= 0 && - r != RV(srs->rs_rates[ic->ic_fixed_rate])) - ignore++; - } - if (flags & IEEE80211_F_DONEGO) { - /* - * Check against supported rates. - */ - for (j = 0; j < srs->rs_nrates; j++) { - if (r == RV(srs->rs_rates[j])) { - /* - * Overwrite with the supported rate - * value so any basic rate bit is set. - * This insures that response we send - * to stations have the necessary basic - * rate bit set. - */ - nrs->rs_rates[i] = srs->rs_rates[j]; - break; - } - } - if (j == srs->rs_nrates) { - /* - * A rate in the node's rate set is not - * supported. If this is a basic rate and we - * are operating as an AP then this is an error. - * Otherwise we just discard/ignore the rate. - * Note that this is important for 11b stations - * when they want to associate with an 11g AP. - */ - if (ic->ic_opmode == IEEE80211_M_HOSTAP && - (nrs->rs_rates[i] & IEEE80211_RATE_BASIC)) - error++; - ignore++; - } - } - if (flags & IEEE80211_F_DODEL) { - /* - * Delete unacceptable rates. - */ - if (ignore) { - nrs->rs_nrates--; - for (j = i; j < nrs->rs_nrates; j++) - nrs->rs_rates[j] = nrs->rs_rates[j + 1]; - nrs->rs_rates[j] = 0; - continue; - } - } - if (!ignore) - okrate = nrs->rs_rates[i]; - i++; - } - if (okrate == 0 || error != 0) - return badrate | IEEE80211_RATE_BASIC; - else - return RV(okrate); -#undef RV -} - -static int -ieee80211_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int mgt) -{ - struct ifnet *ifp = &ic->ic_if; - struct ieee80211_node *ni; - enum ieee80211_state ostate; - struct lwkt_tokref ilock; - - ostate = ic->ic_state; - IEEE80211_DPRINTF(("%s: %s -> %s\n", __func__, - ieee80211_state_name[ostate], ieee80211_state_name[nstate])); - ic->ic_state = nstate; /* state transition */ - ni = ic->ic_bss; /* NB: no reference held */ - switch (nstate) { - case IEEE80211_S_INIT: - switch (ostate) { - case IEEE80211_S_INIT: - break; - case IEEE80211_S_RUN: - switch (ic->ic_opmode) { - case IEEE80211_M_STA: - IEEE80211_SEND_MGMT(ic, ni, - IEEE80211_FC0_SUBTYPE_DISASSOC, - IEEE80211_REASON_ASSOC_LEAVE); - break; - case IEEE80211_M_HOSTAP: - lwkt_gettoken(&ilock, &ic->ic_nodetoken); - TAILQ_FOREACH(ni, &ic->ic_node, ni_list) { - if (ni->ni_associd == 0) - continue; - IEEE80211_SEND_MGMT(ic, ni, - IEEE80211_FC0_SUBTYPE_DISASSOC, - IEEE80211_REASON_ASSOC_LEAVE); - } - lwkt_reltoken(&ilock); - break; - default: - break; - } - /* FALLTHRU */ - case IEEE80211_S_ASSOC: - switch (ic->ic_opmode) { - case IEEE80211_M_STA: - IEEE80211_SEND_MGMT(ic, ni, - IEEE80211_FC0_SUBTYPE_DEAUTH, - IEEE80211_REASON_AUTH_LEAVE); - break; - case IEEE80211_M_HOSTAP: - lwkt_gettoken(&ilock, &ic->ic_nodetoken); - TAILQ_FOREACH(ni, &ic->ic_node, ni_list) { - IEEE80211_SEND_MGMT(ic, ni, - IEEE80211_FC0_SUBTYPE_DEAUTH, - IEEE80211_REASON_AUTH_LEAVE); - } - lwkt_reltoken(&ilock); - break; - default: - break; - } - /* FALLTHRU */ - case IEEE80211_S_AUTH: - case IEEE80211_S_SCAN: - ic->ic_mgt_timer = 0; - IF_DRAIN(&ic->ic_mgtq); - if (ic->ic_wep_ctx != NULL) { - free(ic->ic_wep_ctx, M_DEVBUF); - ic->ic_wep_ctx = NULL; - } - ieee80211_free_allnodes(ic); - break; - } - break; - case IEEE80211_S_SCAN: - ic->ic_flags &= ~IEEE80211_F_SIBSS; - /* initialize bss for probe request */ - IEEE80211_ADDR_COPY(ni->ni_macaddr, ifp->if_broadcastaddr); - IEEE80211_ADDR_COPY(ni->ni_bssid, ifp->if_broadcastaddr); - ni->ni_rates = ic->ic_sup_rates[ - ieee80211_chan2mode(ic, ni->ni_chan)]; - ni->ni_associd = 0; - ni->ni_rstamp = 0; - switch (ostate) { - case IEEE80211_S_INIT: - if (ic->ic_opmode == IEEE80211_M_HOSTAP && - ic->ic_des_chan != IEEE80211_CHAN_ANYC) { - /* - * AP operation and we already have a channel; - * bypass the scan and startup immediately. - */ - ieee80211_create_ibss(ic, ic->ic_des_chan); - } else { - ieee80211_begin_scan(ifp); - } - break; - case IEEE80211_S_SCAN: - /* scan next */ - if (ic->ic_flags & IEEE80211_F_ASCAN) { - IEEE80211_SEND_MGMT(ic, ni, - IEEE80211_FC0_SUBTYPE_PROBE_REQ, 0); - } - break; - case IEEE80211_S_RUN: - /* beacon miss */ - if (ifp->if_flags & IFF_DEBUG) { - /* XXX bssid clobbered above */ - if_printf(ifp, "no recent beacons from %6D;" - " rescanning\n", - ic->ic_bss->ni_bssid, ":"); - } - ieee80211_free_allnodes(ic); - /* FALLTHRU */ - case IEEE80211_S_AUTH: - case IEEE80211_S_ASSOC: - /* timeout restart scan */ - ni = ieee80211_find_node(ic, ic->ic_bss->ni_macaddr); - if (ni != NULL) { - ni->ni_fails++; - ieee80211_unref_node(&ni); - } - ieee80211_begin_scan(ifp); - break; - } - break; - case IEEE80211_S_AUTH: - switch (ostate) { - case IEEE80211_S_INIT: - IEEE80211_DPRINTF(("%s: invalid transition\n", - __func__)); - break; - case IEEE80211_S_SCAN: - IEEE80211_SEND_MGMT(ic, ni, - IEEE80211_FC0_SUBTYPE_AUTH, 1); - break; - case IEEE80211_S_AUTH: - case IEEE80211_S_ASSOC: - switch (mgt) { - case IEEE80211_FC0_SUBTYPE_AUTH: - /* ??? */ - IEEE80211_SEND_MGMT(ic, ni, - IEEE80211_FC0_SUBTYPE_AUTH, 2); - break; - case IEEE80211_FC0_SUBTYPE_DEAUTH: - /* ignore and retry scan on timeout */ - break; - } - break; - case IEEE80211_S_RUN: - switch (mgt) { - case IEEE80211_FC0_SUBTYPE_AUTH: - IEEE80211_SEND_MGMT(ic, ni, - IEEE80211_FC0_SUBTYPE_AUTH, 2); - ic->ic_state = ostate; /* stay RUN */ - break; - case IEEE80211_FC0_SUBTYPE_DEAUTH: - /* try to reauth */ - IEEE80211_SEND_MGMT(ic, ni, - IEEE80211_FC0_SUBTYPE_AUTH, 1); - break; - } - break; - } - break; - case IEEE80211_S_ASSOC: - switch (ostate) { - case IEEE80211_S_INIT: - case IEEE80211_S_SCAN: - case IEEE80211_S_ASSOC: - IEEE80211_DPRINTF(("%s: invalid transition\n", - __func__)); - break; - case IEEE80211_S_AUTH: - IEEE80211_SEND_MGMT(ic, ni, - IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0); - break; - case IEEE80211_S_RUN: - IEEE80211_SEND_MGMT(ic, ni, - IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 1); - break; - } - break; - case IEEE80211_S_RUN: - switch (ostate) { - case IEEE80211_S_INIT: - case IEEE80211_S_AUTH: - case IEEE80211_S_RUN: - IEEE80211_DPRINTF(("%s: invalid transition\n", - __func__)); - break; - case IEEE80211_S_SCAN: /* adhoc/hostap mode */ - case IEEE80211_S_ASSOC: /* infra mode */ - KASSERT(ni->ni_txrate < ni->ni_rates.rs_nrates, - ("%s: bogus xmit rate %u setup\n", __func__, - ni->ni_txrate)); - if (ifp->if_flags & IFF_DEBUG) { - if_printf(ifp, " "); - if (ic->ic_opmode == IEEE80211_M_STA) - printf("associated "); - else - printf("synchronized "); - printf("with %6D ssid ", ni->ni_bssid, ":"); - ieee80211_print_essid(ic->ic_bss->ni_essid, - ni->ni_esslen); - printf(" channel %d start %uMb\n", - ieee80211_chan2ieee(ic, ni->ni_chan), - IEEE80211_RATE2MBS(ni->ni_rates.rs_rates[ni->ni_txrate])); - } - ic->ic_mgt_timer = 0; - (*ifp->if_start)(ifp); - break; - } - break; - } - return 0; -}