📄 ieee80211.c.svn-base
字号:
/*- * Copyright (c) 2001 Atsushi Onoe * Copyright (c) 2002-2005 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. * * $Id$ */#ifndef EXPORT_SYMTAB#define EXPORT_SYMTAB#endif/* * IEEE 802.11 generic handler */#ifndef AUTOCONF_INCLUDED#include <linux/config.h>#endif#include <linux/version.h>#include <linux/module.h>#include <linux/skbuff.h>#include <linux/netdevice.h>#include <linux/rtnetlink.h> /* XXX for rtnl_lock */#include "if_media.h"#include <net80211/ieee80211_var.h>#include <net80211/if_athproto.h>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 */ "turboA", /* IEEE80211_MODE_TURBO_A */ "turboG", /* IEEE80211_MODE_TURBO_G */ "staticTurboA", /* IEEE80211_MODE_TURBO_G */};EXPORT_SYMBOL(ieee80211_phymode_name);const char *ieee80211_opmode_name[] = { "ibss", /* IEEE80211_M_IBSS = 0 - IBSS (adhoc) station */ "station", /* IEEE80211_M_STA = 1 - infrastructure station */ "wds", /* IEEE80211_M_WDS = 2 - WDS link */ "ahdemo", /* IEEE80211_M_AHDEMO = 3 - Old lucent compatible adhoc demo */ "opmode4", /* invalid = 4 - invalid */ "opmode5", /* invalid = 5 - invalid */ "hostap", /* IEEE80211_M_HOSTAP = 6 - Software Access Point */ "opmode7", /* invalid = 7 - invalid */ "monitor" /* IEEE80211_M_MONITOR = 8 - Monitor mode */ };EXPORT_SYMBOL(ieee80211_opmode_name);static void ieee80211com_media_status(struct net_device *, struct ifmediareq *);static int ieee80211com_media_change(struct net_device *);static struct net_device_stats *ieee80211_getstats(struct net_device *);static int ieee80211_change_mtu(struct net_device *, int);static void ieee80211_set_multicast_list(struct net_device *);static void ieee80211_expire_dfs_excl_timer(unsigned long);MALLOC_DEFINE(M_80211_VAP, "80211vap", "802.11 vap state");/* * Country Code Table for code-to-string conversion. */struct country_code_to_string { u_int16_t iso_code; const char *iso_name;};/* * XXX: Ugly, since these must match defines in other modules. */#define CTRY_DEBUG 0x1ff /* debug */#define CTRY_DEFAULT 0 /* default */static const struct country_code_to_string country_strings[] = { {CTRY_DEBUG, "DB"}, {CTRY_DEFAULT, "NA"}, {CTRY_ALBANIA, "AL"}, {CTRY_ALGERIA, "DZ"}, {CTRY_ARGENTINA, "AR"}, {CTRY_ARMENIA, "AM"}, {CTRY_AUSTRALIA, "AU"}, {CTRY_AUSTRIA, "AT"}, {CTRY_AZERBAIJAN, "AZ"}, {CTRY_BAHRAIN, "BH"}, {CTRY_BELARUS, "BY"}, {CTRY_BELGIUM, "BE"}, {CTRY_BELIZE, "BZ"}, {CTRY_BOLIVIA, "BO"}, {CTRY_BRAZIL, "BR"}, {CTRY_BRUNEI_DARUSSALAM, "BN"}, {CTRY_BULGARIA, "BG"}, {CTRY_CANADA, "CA"}, {CTRY_CHILE, "CL"}, {CTRY_CHINA, "CN"}, {CTRY_COLOMBIA, "CO"}, {CTRY_COSTA_RICA, "CR"}, {CTRY_CROATIA, "HR"}, {CTRY_CYPRUS, "CY"}, {CTRY_CZECH, "CZ"}, {CTRY_DENMARK, "DK"}, {CTRY_DOMINICAN_REPUBLIC, "DO"}, {CTRY_ECUADOR, "EC"}, {CTRY_EGYPT, "EG"}, {CTRY_EL_SALVADOR, "SV"}, {CTRY_ESTONIA, "EE"}, {CTRY_FINLAND, "FI"}, {CTRY_FRANCE, "FR"}, {CTRY_FRANCE2, "F2"}, {CTRY_GEORGIA, "GE"}, {CTRY_GERMANY, "DE"}, {CTRY_GREECE, "GR"}, {CTRY_GUATEMALA, "GT"}, {CTRY_HONDURAS, "HN"}, {CTRY_HONG_KONG, "HK"}, {CTRY_HUNGARY, "HU"}, {CTRY_ICELAND, "IS"}, {CTRY_INDIA, "IN"}, {CTRY_INDONESIA, "ID"}, {CTRY_IRAN, "IR"}, {CTRY_IRELAND, "IE"}, {CTRY_ISRAEL, "IL"}, {CTRY_ITALY, "IT"}, {CTRY_JAPAN, "JP"}, {CTRY_JAPAN1, "J1"}, {CTRY_JAPAN2, "J2"}, {CTRY_JAPAN3, "J3"}, {CTRY_JAPAN4, "J4"}, {CTRY_JAPAN5, "J5"}, {CTRY_JAPAN7, "JP"}, {CTRY_JAPAN6, "JP"}, {CTRY_JAPAN8, "JP"}, {CTRY_JAPAN9, "JP"}, {CTRY_JAPAN10, "JP"}, {CTRY_JAPAN11, "JP"}, {CTRY_JAPAN12, "JP"}, {CTRY_JAPAN13, "JP"}, {CTRY_JAPAN14, "JP"}, {CTRY_JAPAN15, "JP"}, {CTRY_JAPAN16, "JP"}, {CTRY_JAPAN17, "JP"}, {CTRY_JAPAN18, "JP"}, {CTRY_JAPAN19, "JP"}, {CTRY_JAPAN20, "JP"}, {CTRY_JAPAN21, "JP"}, {CTRY_JAPAN22, "JP"}, {CTRY_JAPAN23, "JP"}, {CTRY_JAPAN24, "JP"}, {CTRY_JAPAN25, "JP"}, {CTRY_JAPAN26, "JP"}, {CTRY_JAPAN27, "JP"}, {CTRY_JAPAN28, "JP"}, {CTRY_JAPAN29, "JP"}, {CTRY_JAPAN30, "JP"}, {CTRY_JAPAN31, "JP"}, {CTRY_JAPAN32, "JP"}, {CTRY_JAPAN33, "JP"}, {CTRY_JAPAN34, "JP"}, {CTRY_JAPAN35, "JP"}, {CTRY_JAPAN36, "JP"}, {CTRY_JAPAN37, "JP"}, {CTRY_JAPAN38, "JP"}, {CTRY_JAPAN39, "JP"}, {CTRY_JAPAN40, "JP"}, {CTRY_JAPAN41, "JP"}, {CTRY_JAPAN42, "JP"}, {CTRY_JAPAN43, "JP"}, {CTRY_JAPAN44, "JP"}, {CTRY_JAPAN45, "JP"}, {CTRY_JAPAN46, "JP"}, {CTRY_JAPAN47, "JP"}, {CTRY_JAPAN48, "JP"}, {CTRY_JORDAN, "JO"}, {CTRY_KAZAKHSTAN, "KZ"}, {CTRY_KOREA_NORTH, "KP"}, {CTRY_KOREA_ROC, "KR"}, {CTRY_KOREA_ROC2, "K2"}, {CTRY_KUWAIT, "KW"}, {CTRY_LATVIA, "LV"}, {CTRY_LEBANON, "LB"}, {CTRY_LIECHTENSTEIN, "LI"}, {CTRY_LITHUANIA, "LT"}, {CTRY_LUXEMBOURG, "LU"}, {CTRY_MACAU, "MO"}, {CTRY_MACEDONIA, "MK"}, {CTRY_MALAYSIA, "MY"}, {CTRY_MEXICO, "MX"}, {CTRY_MONACO, "MC"}, {CTRY_MOROCCO, "MA"}, {CTRY_NETHERLANDS, "NL"}, {CTRY_NEW_ZEALAND, "NZ"}, {CTRY_NORWAY, "NO"}, {CTRY_OMAN, "OM"}, {CTRY_PAKISTAN, "PK"}, {CTRY_PANAMA, "PA"}, {CTRY_PERU, "PE"}, {CTRY_PHILIPPINES, "PH"}, {CTRY_POLAND, "PL"}, {CTRY_PORTUGAL, "PT"}, {CTRY_PUERTO_RICO, "PR"}, {CTRY_QATAR, "QA"}, {CTRY_ROMANIA, "RO"}, {CTRY_RUSSIA, "RU"}, {CTRY_SAUDI_ARABIA, "SA"}, {CTRY_SINGAPORE, "SG"}, {CTRY_SLOVAKIA, "SK"}, {CTRY_SLOVENIA, "SI"}, {CTRY_SOUTH_AFRICA, "ZA"}, {CTRY_SPAIN, "ES"}, {CTRY_SWEDEN, "SE"}, {CTRY_SWITZERLAND, "CH"}, {CTRY_SYRIA, "SY"}, {CTRY_TAIWAN, "TW"}, {CTRY_THAILAND, "TH"}, {CTRY_TRINIDAD_Y_TOBAGO, "TT"}, {CTRY_TUNISIA, "TN"}, {CTRY_TURKEY, "TR"}, {CTRY_UKRAINE, "UA"}, {CTRY_UAE, "AE"}, {CTRY_UNITED_KINGDOM, "GB"}, {CTRY_UNITED_STATES, "US"}, {CTRY_UNITED_STATES_FCC49, "US"}, {CTRY_URUGUAY, "UY"}, {CTRY_UZBEKISTAN, "UZ"}, {CTRY_VENEZUELA, "VE"}, {CTRY_VIET_NAM, "VN"}, {CTRY_YEMEN, "YE"}, {CTRY_ZIMBABWE, "ZW"}};intieee80211_ifattach(struct ieee80211com *ic){ struct net_device *dev = ic->ic_dev; struct ieee80211_channel *c; struct ifmediareq imr; int i; _MOD_INC_USE(THIS_MODULE, return -ENODEV); /* * Pick an initial operating mode until we have a vap * created to lock it down correctly. This is only * drivers have something defined for configuring the * hardware at startup. */ ic->ic_opmode = IEEE80211_M_STA; /* everyone supports this */ /* * Fill in 802.11 available channel set, mark * all available channels as active, and pick * a default channel if not already specified. */ KASSERT(0 < ic->ic_nchans && ic->ic_nchans < IEEE80211_CHAN_MAX, ("invalid number of channels specified: %u", ic->ic_nchans)); memset(ic->ic_chan_avail, 0, sizeof(ic->ic_chan_avail)); ic->ic_modecaps |= 1 << IEEE80211_MODE_AUTO; for (i = 0; i < ic->ic_nchans; i++) { c = &ic->ic_channels[i]; KASSERT(c->ic_flags != 0, ("channel with no flags")); KASSERT(c->ic_ieee < IEEE80211_CHAN_MAX, ("channel with bogus ieee number %u", c->ic_ieee)); setbit(ic->ic_chan_avail, c->ic_ieee); /* Identify mode capabilities. */ if (IEEE80211_IS_CHAN_A(c)) ic->ic_modecaps |= 1 << IEEE80211_MODE_11A; if (IEEE80211_IS_CHAN_B(c)) ic->ic_modecaps |= 1 << IEEE80211_MODE_11B; if (IEEE80211_IS_CHAN_PUREG(c)) ic->ic_modecaps |= 1 << IEEE80211_MODE_11G; if (IEEE80211_IS_CHAN_FHSS(c)) ic->ic_modecaps |= 1 << IEEE80211_MODE_FH; if (IEEE80211_IS_CHAN_108A(c)) ic->ic_modecaps |= 1 << IEEE80211_MODE_TURBO_A; if (IEEE80211_IS_CHAN_108G(c)) ic->ic_modecaps |= 1 << IEEE80211_MODE_TURBO_G; } /* Initialize candidate channels to all available */ memcpy(ic->ic_chan_active, ic->ic_chan_avail, sizeof(ic->ic_chan_avail)); /* update Supported Channels information element */ ieee80211_build_sc_ie(ic); /* Validate ic->ic_curmode */ if ((ic->ic_modecaps & (1 << ic->ic_curmode)) == 0) ic->ic_curmode = IEEE80211_MODE_AUTO; /* * When 11g is supported, force the rate set to * include basic rates suitable for a mixed b/g bss. */ if (ic->ic_modecaps & (1 << IEEE80211_MODE_11G)) ieee80211_set11gbasicrates( &ic->ic_sup_rates[IEEE80211_MODE_11G], IEEE80211_MODE_11G); /* Setup initial channel settings */ ic->ic_bsschan = IEEE80211_CHAN_ANYC; /* Arbitrarily pick the first channel */ ic->ic_curchan = &ic->ic_channels[0]; /* Enable marking of dfs by default */ ic->ic_flags_ext |= IEEE80211_FEXT_MARKDFS; /* Enable WME by default, if we're capable. */ if (ic->ic_caps & IEEE80211_C_WME) ic->ic_flags |= IEEE80211_F_WME; (void) ieee80211_setmode(ic, ic->ic_curmode); /* Store default beacon interval, as nec. */ if (ic->ic_lintval == 0) ic->ic_lintval = IEEE80211_BINTVAL_DEFAULT; /* We store the beacon miss threshold in integral number of beacons, * to keep the calculations on the critical path simple. */ if (ic->ic_bmissthreshold == 0) { ic->ic_bmissthreshold = howmany(roundup( IEEE80211_MS_TO_TU(IEEE80211_BMISSTHRESH_DEFAULT_MS), ic->ic_lintval), ic->ic_lintval); } IEEE80211_LOCK_INIT(ic, "ieee80211com"); IEEE80211_VAPS_LOCK_INIT(ic, "ieee80211com_vaps"); TAILQ_INIT(&ic->ic_vaps); ic->ic_txpowlimit = IEEE80211_TXPOWER_MAX; ic->ic_txpowlimit = IEEE80211_TXPOWER_MIN; ic->ic_newtxpowlimit = IEEE80211_TXPOWER_MAX; init_timer(&ic->ic_dfs_excl_timer); ic->ic_dfs_excl_timer.function = ieee80211_expire_dfs_excl_timer; ic->ic_dfs_excl_timer.data = (unsigned long) ic; ieee80211_crypto_attach(ic); ieee80211_node_attach(ic); ieee80211_power_attach(ic); ieee80211_proto_attach(ic); ieee80211_scan_attach(ic); ieee80211_media_setup(ic, &ic->ic_media, ic->ic_caps, ieee80211com_media_change, ieee80211com_media_status); ieee80211com_media_status(dev, &imr); ifmedia_set(&ic->ic_media, imr.ifm_active); return 0;}EXPORT_SYMBOL(ieee80211_ifattach);voidieee80211_ifdetach(struct ieee80211com *ic){ struct ieee80211vap *vap; rtnl_lock(); while ((vap = TAILQ_FIRST(&ic->ic_vaps)) != NULL) ic->ic_vap_delete(vap); rtnl_unlock(); del_timer(&ic->ic_dfs_excl_timer); ieee80211_scan_detach(ic); ieee80211_proto_detach(ic); ieee80211_crypto_detach(ic); ieee80211_power_detach(ic); ieee80211_node_detach(ic); ifmedia_removeall(&ic->ic_media); IEEE80211_VAPS_LOCK_DESTROY(ic); IEEE80211_LOCK_DESTROY(ic); _MOD_DEC_USE(THIS_MODULE);}EXPORT_SYMBOL(ieee80211_ifdetach);intieee80211_vap_setup(struct ieee80211com *ic, struct net_device *dev, const char *name, int opmode, int flags){#define IEEE80211_C_OPMODE \ (IEEE80211_C_IBSS | IEEE80211_C_HOSTAP | IEEE80211_C_AHDEMO | \ IEEE80211_C_MONITOR) struct ieee80211vap *vap = netdev_priv(dev); struct net_device *parent = ic->ic_dev; int err; if (name != NULL) { /* XXX */ if (strchr(name, '%')) { if ((err = dev_alloc_name(dev, name)) < 0) { printk(KERN_ERR "can't alloc name %s\n", name); return err; } } else strncpy(dev->name, name, sizeof(dev->name)); } dev->get_stats = ieee80211_getstats; dev->open = ieee80211_open; dev->stop = ieee80211_stop; dev->hard_start_xmit = ieee80211_hardstart; dev->set_multicast_list = ieee80211_set_multicast_list;#if 0 dev->set_mac_address = ieee80211_set_mac_address;#endif dev->change_mtu = ieee80211_change_mtu; dev->tx_queue_len = 0; /* NB: bypass queuing */ dev->hard_header_len = parent->hard_header_len; /* * The caller is assumed to allocate the device with * alloc_etherdev or similar so we arrange for the * space to be reclaimed accordingly. */#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) /* In 2.4 things are done differently... */ dev->features |= NETIF_F_DYNALLOC;#else dev->destructor = free_netdev;#endif vap->iv_ic = ic; vap->iv_dev = dev; /* back pointer */ vap->iv_xrvap = NULL; vap->iv_flags = ic->ic_flags; /* propagate common flags */ vap->iv_flags_ext = ic->ic_flags_ext; vap->iv_ath_cap = ic->ic_ath_cap; vap->iv_mcast_rate = 1000; /* Default multicast traffic to lowest rate of 1Mbps */#ifdef ATH_SUPERG_XR /* * Setup XR VAP specific flags. * link the XR VAP to its normal val. */ if (flags & IEEE80211_VAP_XR) { vap->iv_flags |= IEEE80211_F_XR; /* propagate common flags and add XR flag */ vap->iv_mcast_rate = 256; /* Default multicast rate to lowest possible 256 kbps */ }#endif vap->iv_caps = ic->ic_caps &~ IEEE80211_C_OPMODE; switch (opmode) { case IEEE80211_M_STA: /* WDS/Repeater */ if (flags & IEEE80211_USE_SW_BEACON_TIMERS) vap->iv_flags_ext |= IEEE80211_FEXT_SWBMISS; break; case IEEE80211_M_IBSS: vap->iv_caps |= IEEE80211_C_IBSS; vap->iv_ath_cap &= ~IEEE80211_ATHC_XR; break; case IEEE80211_M_AHDEMO: vap->iv_caps |= IEEE80211_C_AHDEMO; vap->iv_ath_cap &= ~IEEE80211_ATHC_XR; break; case IEEE80211_M_HOSTAP: vap->iv_caps |= IEEE80211_C_HOSTAP;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -