📄 ieee80211_proto.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 protocol support. */#ifndef AUTOCONF_INCLUDED#include <linux/config.h>#endif#include <linux/version.h>#include <linux/kmod.h>#include <linux/module.h>#include <linux/skbuff.h>#include <linux/netdevice.h>#include "if_media.h"#include <net80211/ieee80211_var.h>/* XXX tunables */#define AGGRESSIVE_MODE_SWITCH_HYSTERESIS 3 /* pkts / 100ms */#define HIGH_PRI_SWITCH_THRESH 10 /* pkts / 100ms */#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"};EXPORT_SYMBOL(ieee80211_mgt_subtype_name);const char *ieee80211_ctl_subtype_name[] = { "reserved#0", "reserved#1", "reserved#2", "reserved#3", "reserved#3", "reserved#5", "reserved#6", "reserved#7", "reserved#8", "reserved#9", "ps_poll", "rts", "cts", "ack", "cf_end", "cf_end_ack"};EXPORT_SYMBOL(ieee80211_ctl_subtype_name);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 */};EXPORT_SYMBOL(ieee80211_state_name);const char *ieee80211_wme_acnames[] = { "WME_AC_BE", "WME_AC_BK", "WME_AC_VI", "WME_AC_VO", "WME_UPSD",};EXPORT_SYMBOL(ieee80211_wme_acnames);static int ieee80211_newstate(struct ieee80211vap *, enum ieee80211_state, int);static void ieee80211_tx_timeout(unsigned long);#ifdef ATH_SUPERG_XRstatic void ieee80211_start_xrvap(unsigned long);#endifvoid ieee80211_auth_setup(void);voidieee80211_proto_attach(struct ieee80211com *ic){ ic->ic_protmode = IEEE80211_PROT_CTSONLY; ic->ic_rssi_ewma = 0; ic->ic_wme.wme_hipri_switch_hysteresis = AGGRESSIVE_MODE_SWITCH_HYSTERESIS; /* initialize management frame handlers */ ic->ic_recv_mgmt = ieee80211_recv_mgmt; ic->ic_send_mgmt = ieee80211_send_mgmt; ieee80211_auth_setup();}voidieee80211_proto_detach(struct ieee80211com *ic){}voidieee80211_proto_vattach(struct ieee80211vap *vap){#ifdef notdef vap->iv_rtsthreshold = IEEE80211_RTS_DEFAULT;#else vap->iv_rtsthreshold = IEEE80211_RTS_MAX;#endif vap->iv_fragthreshold = 2346; /* XXX not used yet */ vap->iv_fixed_rate = IEEE80211_FIXED_RATE_NONE; init_timer(&vap->iv_mgtsend); init_timer(&vap->iv_xrvapstart); init_timer(&vap->iv_swbmiss); init_timer(&vap->iv_csa_timer); vap->iv_mgtsend.function = ieee80211_tx_timeout; vap->iv_mgtsend.data = (unsigned long) vap; /* protocol state change handler */ vap->iv_newstate = ieee80211_newstate;}voidieee80211_proto_vdetach(struct ieee80211vap *vap){ /* * This should not be needed as we detach when reseting * the state but be conservative here since the * authenticator may do things like spawn kernel threads. */ if (vap->iv_auth->ia_detach) vap->iv_auth->ia_detach(vap); /* * Detach any ACL'ator. */ if (vap->iv_acl != NULL) vap->iv_acl->iac_detach(vap);}/* * Simple-minded authenticator module support. */#define IEEE80211_AUTH_MAX (IEEE80211_AUTH_WPA+1)/* XXX well-known names */static const char *auth_modnames[IEEE80211_AUTH_MAX] = { "wlan_internal", /* IEEE80211_AUTH_NONE */ "wlan_internal", /* IEEE80211_AUTH_OPEN */ "wlan_internal", /* IEEE80211_AUTH_SHARED */ "wlan_xauth", /* IEEE80211_AUTH_8021X */ "wlan_internal", /* IEEE80211_AUTH_AUTO */ "wlan_xauth", /* IEEE80211_AUTH_WPA */};static const struct ieee80211_authenticator *authenticators[IEEE80211_AUTH_MAX];static const struct ieee80211_authenticator auth_internal = { .ia_name = "wlan_internal", .ia_attach = NULL, .ia_detach = NULL, .ia_node_join = NULL, .ia_node_leave = NULL,};/* * Setup internal authenticators once; they are never unregistered. */voidieee80211_auth_setup(void){ ieee80211_authenticator_register(IEEE80211_AUTH_OPEN, &auth_internal); ieee80211_authenticator_register(IEEE80211_AUTH_SHARED, &auth_internal); ieee80211_authenticator_register(IEEE80211_AUTH_AUTO, &auth_internal);}const struct ieee80211_authenticator *ieee80211_authenticator_get(int auth){ if (auth >= IEEE80211_AUTH_MAX) return NULL; if (authenticators[auth] == NULL) ieee80211_load_module(auth_modnames[auth]); return authenticators[auth];}voidieee80211_authenticator_register(int type, const struct ieee80211_authenticator *auth){ if (type >= IEEE80211_AUTH_MAX) return; authenticators[type] = auth;}EXPORT_SYMBOL(ieee80211_authenticator_register);voidieee80211_authenticator_unregister(int type){ if (type >= IEEE80211_AUTH_MAX) return; authenticators[type] = NULL;}EXPORT_SYMBOL(ieee80211_authenticator_unregister);/* * Very simple-minded authenticator backend module support. *//* XXX just one for now */static const struct ieee80211_authenticator_backend *backend = NULL;voidieee80211_authenticator_backend_register( const struct ieee80211_authenticator_backend *be){ printk(KERN_INFO "wlan: %s backend registered\n", be->iab_name); backend = be;}EXPORT_SYMBOL(ieee80211_authenticator_backend_register);voidieee80211_authenticator_backend_unregister( const struct ieee80211_authenticator_backend * be){ if (backend == be) backend = NULL; printk(KERN_INFO "wlan: %s backend unregistered\n", be->iab_name);}EXPORT_SYMBOL(ieee80211_authenticator_backend_unregister);const struct ieee80211_authenticator_backend *ieee80211_authenticator_backend_get(const char *name){ return backend && strcmp(backend->iab_name, name) == 0 ? backend : NULL;}EXPORT_SYMBOL(ieee80211_authenticator_backend_get);/* * Very simple-minded ACL module support. *//* XXX just one for now */static const struct ieee80211_aclator *acl = NULL;voidieee80211_aclator_register(const struct ieee80211_aclator *iac){ printk(KERN_INFO "wlan: %s acl policy registered\n", iac->iac_name); acl = iac;}EXPORT_SYMBOL(ieee80211_aclator_register);voidieee80211_aclator_unregister(const struct ieee80211_aclator *iac){ if (acl == iac) acl = NULL; printk(KERN_INFO "wlan: %s acl policy unregistered\n", iac->iac_name);}EXPORT_SYMBOL(ieee80211_aclator_unregister);const struct ieee80211_aclator *ieee80211_aclator_get(const char *name){ if (acl == NULL) ieee80211_load_module("wlan_acl"); return acl && strcmp(acl->iac_name, name) == 0 ? acl : NULL;}EXPORT_SYMBOL(ieee80211_aclator_get);#ifdef IEEE80211_DEBUGvoidieee80211_print_essid(const u_int8_t *essid, int len){ int i; const u_int8_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) { printk("\""); for (i = 0, p = essid; i < len; i++, p++) printk("%c", *p); printk("\""); } else { printk("0x"); for (i = 0, p = essid; i < len; i++, p++) printk("%02x", *p); }}EXPORT_SYMBOL(ieee80211_print_essid);voidieee80211_dump_pkt(struct ieee80211com *ic, const u_int8_t *buf, int len, int rate, int rssi, int tx){ const struct ieee80211_frame *wh; int i; wh = (const struct ieee80211_frame *)buf; switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) { case IEEE80211_FC1_DIR_NODS: printk("NoDS " MAC_FMT, MAC_ADDR(wh->i_addr2)); printk("->" MAC_FMT, MAC_ADDR(wh->i_addr1)); printk("(" MAC_FMT ")", MAC_ADDR(wh->i_addr3)); break; case IEEE80211_FC1_DIR_TODS: printk("ToDS " MAC_FMT, MAC_ADDR(wh->i_addr2)); printk("->" MAC_FMT, MAC_ADDR(wh->i_addr3)); printk("(" MAC_FMT ")", MAC_ADDR(wh->i_addr1)); break; case IEEE80211_FC1_DIR_FROMDS: printk("FrDS " MAC_FMT, MAC_ADDR(wh->i_addr3)); printk("->" MAC_FMT, MAC_ADDR(wh->i_addr1)); printk("(" MAC_FMT ")", MAC_ADDR(wh->i_addr2)); break; case IEEE80211_FC1_DIR_DSTODS: printk("InDS " MAC_FMT, MAC_ADDR((u_int8_t *)&wh[1])); printk("->" MAC_FMT, MAC_ADDR(wh->i_addr3)); printk("(" MAC_FMT, MAC_ADDR(wh->i_addr2)); printk("->" MAC_FMT ")", MAC_ADDR(wh->i_addr1)); break; } switch (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) { case IEEE80211_FC0_TYPE_DATA: printk(" data"); break; case IEEE80211_FC0_TYPE_MGT: printk(" %s", ieee80211_mgt_subtype_name[ (wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK) >> IEEE80211_FC0_SUBTYPE_SHIFT]); break; default: printk(" type#%d", wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK); break; } if (IEEE80211_QOS_HAS_SEQ(wh)) { const struct ieee80211_qosframe *qwh = (const struct ieee80211_qosframe *)buf; printk(" QoS [TID %u%s]", qwh->i_qos[0] & IEEE80211_QOS_TID, qwh->i_qos[0] & IEEE80211_QOS_ACKPOLICY ? " ACM" : ""); } if (wh->i_fc[1] & IEEE80211_FC1_PROT) { int off; if (tx) off = ieee80211_anyhdrspace(ic, wh); else off = ieee80211_anyhdrsize(wh); printk(" Prot. [IV %.02x %.02x %.02x", buf[off + 0], buf[off + 1], buf[off + 2]); if (buf[off + IEEE80211_WEP_IVLEN] & IEEE80211_WEP_EXTIV) printk(" %.02x %.02x %.02x", buf[off + 4], buf[off + 5], buf[off + 6]); printk(" KID %u]", buf[off + IEEE80211_WEP_IVLEN] >> 6); } if (rate >= 0) printk(" %dM", rate / 2); if (rssi >= 0) printk(" +%d", rssi); printk("\n"); if (len > 0) { for (i = 0; i < len; i++) { if ((i % 8) == 0) printk(" "); if ((i % 16) == 0) printk("\n"); printk("%02x ", buf[i]); } printk("\n\n"); }}EXPORT_SYMBOL(ieee80211_dump_pkt);#endifintieee80211_fix_rate(struct ieee80211_node *ni, int flags){#define RV(v) ((v) & IEEE80211_RATE_VAL) struct ieee80211vap *vap = ni->ni_vap; struct ieee80211com *ic = ni->ni_ic; int i, j, ignore, error; int okrate, badrate, fixedrate; struct ieee80211_rateset *srs, *nrs; u_int8_t r; error = 0; okrate = badrate = fixedrate = 0; srs = &ic->ic_sup_rates[ieee80211_chan2mode(ni->ni_chan)]; nrs = &ni->ni_rates; fixedrate = IEEE80211_FIXED_RATE_NONE; 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; /* * remove 0 rates * they don't make sense and can lead to trouble later */ if (r == 0) { 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; } /* * Check for fixed rate. */ if (r == vap->iv_fixed_rate) fixedrate = r; 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 ensures 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 (vap->iv_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];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -