?? ieee80211_node.c
字號(hào):
/*- * 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: ieee80211_node.c 1640 2006-06-13 08:50:37Z kelmo $ */#ifndef EXPORT_SYMTAB#define EXPORT_SYMTAB#endif/* * IEEE 802.11 node handling support. */#include <linux/config.h>#include <linux/version.h>#include <linux/module.h>#include <linux/skbuff.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/random.h>#include "if_media.h"#include <net80211/ieee80211_var.h>#include <net80211/if_athproto.h>/* * Association id's are managed with a bit vector. */#define IEEE80211_AID_SET(_vap, _b) \ ((_vap)->iv_aid_bitmap[IEEE80211_AID(_b) / 32] |= \ (1 << (IEEE80211_AID(_b) % 32)))#define IEEE80211_AID_CLR(_vap, _b) \ ((_vap)->iv_aid_bitmap[IEEE80211_AID(_b) / 32] &= \ ~(1 << (IEEE80211_AID(_b) % 32)))#define IEEE80211_AID_ISSET(_vap, _b) \ ((_vap)->iv_aid_bitmap[IEEE80211_AID(_b) / 32] & (1 << (IEEE80211_AID(_b) % 32)))static int ieee80211_sta_join1(struct ieee80211_node *);static struct ieee80211_node *node_alloc(struct ieee80211_node_table *, struct ieee80211vap *);static void node_cleanup(struct ieee80211_node *);static void node_free(struct ieee80211_node *);static u_int8_t node_getrssi(const struct ieee80211_node *);static void _ieee80211_free_node(struct ieee80211_node *);static void node_reclaim(struct ieee80211_node_table *, struct ieee80211_node*);static void ieee80211_node_timeout(unsigned long);static void ieee80211_node_table_init(struct ieee80211com *, struct ieee80211_node_table *, const char *, int);static void ieee80211_node_table_cleanup(struct ieee80211_node_table *);static void ieee80211_node_table_reset(struct ieee80211_node_table *, struct ieee80211vap *);static void ieee80211_node_wds_ageout(unsigned long);MALLOC_DEFINE(M_80211_NODE, "80211node", "802.11 node state");voidieee80211_node_attach(struct ieee80211com *ic){ ieee80211_node_table_init(ic, &ic->ic_sta, "station", IEEE80211_INACT_INIT); init_timer(&ic->ic_inact); ic->ic_inact.function = ieee80211_node_timeout; ic->ic_inact.data = (unsigned long) ic; ic->ic_inact.expires = jiffies + IEEE80211_INACT_WAIT * HZ; add_timer(&ic->ic_inact); ic->ic_node_alloc = node_alloc; ic->ic_node_free = node_free; ic->ic_node_cleanup = node_cleanup; ic->ic_node_getrssi = node_getrssi;}voidieee80211_node_detach(struct ieee80211com *ic){ del_timer(&ic->ic_inact); ieee80211_node_table_cleanup(&ic->ic_sta);}voidieee80211_node_vattach(struct ieee80211vap *vap){ /* default station inactivity timer setings */ vap->iv_inact_init = IEEE80211_INACT_INIT; vap->iv_inact_auth = IEEE80211_INACT_AUTH; vap->iv_inact_run = IEEE80211_INACT_RUN; vap->iv_inact_probe = IEEE80211_INACT_PROBE;}voidieee80211_node_latevattach(struct ieee80211vap *vap){ struct ieee80211com *ic = vap->iv_ic; struct ieee80211_rsnparms *rsn; /* * Allocate these only if needed. Beware that we * know adhoc mode doesn't support ATIM yet... */ if (vap->iv_opmode == IEEE80211_M_HOSTAP) { if (vap->iv_max_aid == 0) vap->iv_max_aid = IEEE80211_AID_DEF; else if (vap->iv_max_aid > IEEE80211_AID_MAX) vap->iv_max_aid = IEEE80211_AID_MAX; MALLOC(vap->iv_aid_bitmap, u_int32_t *, howmany(vap->iv_max_aid, 32) * sizeof(u_int32_t), M_DEVBUF, M_NOWAIT | M_ZERO); if (vap->iv_aid_bitmap == NULL) { /* XXX no way to recover */ printf("%s: no memory for AID bitmap!\n", __func__); vap->iv_max_aid = 0; } } ieee80211_reset_bss(vap); /* * Setup "global settings" in the bss node so that * each new station automatically inherits them. */ rsn = &vap->iv_bss->ni_rsn; /* WEP, TKIP, and AES-CCM are always supported */ rsn->rsn_ucastcipherset |= 1 << IEEE80211_CIPHER_WEP; rsn->rsn_ucastcipherset |= 1 << IEEE80211_CIPHER_TKIP; rsn->rsn_ucastcipherset |= 1 << IEEE80211_CIPHER_AES_CCM; if (ic->ic_caps & IEEE80211_C_AES) rsn->rsn_ucastcipherset |= 1 << IEEE80211_CIPHER_AES_OCB; if (ic->ic_caps & IEEE80211_C_CKIP) rsn->rsn_ucastcipherset |= 1 << IEEE80211_CIPHER_CKIP; /* * Default unicast cipher to WEP for 802.1x use. If * WPA is enabled the management code will set these * values to reflect. */ rsn->rsn_ucastcipher = IEEE80211_CIPHER_WEP; rsn->rsn_ucastkeylen = 104 / NBBY; /* * WPA says the multicast cipher is the lowest unicast * cipher supported. But we skip WEP which would * otherwise be used based on this criteria. */ rsn->rsn_mcastcipher = IEEE80211_CIPHER_TKIP; rsn->rsn_mcastkeylen = 128 / NBBY; /* * We support both WPA-PSK and 802.1x; the one used * is determined by the authentication mode and the * setting of the PSK state. */ rsn->rsn_keymgmtset = WPA_ASE_8021X_UNSPEC | WPA_ASE_8021X_PSK; rsn->rsn_keymgmt = WPA_ASE_8021X_PSK; vap->iv_auth = ieee80211_authenticator_get(vap->iv_bss->ni_authmode);}voidieee80211_node_vdetach(struct ieee80211vap *vap){ struct ieee80211com *ic = vap->iv_ic; ieee80211_node_table_reset(&ic->ic_sta, vap); if (vap->iv_bss != NULL) { ieee80211_free_node(vap->iv_bss); vap->iv_bss = NULL; } if (vap->iv_aid_bitmap != NULL) { FREE(vap->iv_aid_bitmap, M_DEVBUF); vap->iv_aid_bitmap = NULL; }}/* * Port authorize/unauthorize interfaces for use by an authenticator. */voidieee80211_node_authorize(struct ieee80211_node *ni){ ni->ni_flags |= IEEE80211_NODE_AUTH; ni->ni_inact_reload = ni->ni_vap->iv_inact_run;}EXPORT_SYMBOL(ieee80211_node_authorize);voidieee80211_node_unauthorize(struct ieee80211_node *ni){ ni->ni_flags &= ~IEEE80211_NODE_AUTH;}EXPORT_SYMBOL(ieee80211_node_unauthorize);/* * Set/change the channel. The rate set is also updated * to ensure a consistent view by drivers. */static __inline voidieee80211_node_set_chan(struct ieee80211com *ic, struct ieee80211_node *ni){ struct ieee80211_channel *chan = ic->ic_bsschan; KASSERT(chan != IEEE80211_CHAN_ANYC, ("bss channel not setup")); ni->ni_chan = chan;#ifdef ATH_SUPERG_XR if (ni->ni_vap->iv_flags & IEEE80211_F_XR) ni->ni_rates = ic->ic_sup_xr_rates; else#endif ni->ni_rates = ic->ic_sup_rates[ieee80211_chan2mode(chan)];}static __inline voidcopy_bss(struct ieee80211_node *nbss, const struct ieee80211_node *obss){ /* propagate useful state */ nbss->ni_authmode = obss->ni_authmode; nbss->ni_ath_flags = obss->ni_ath_flags; nbss->ni_txpower = obss->ni_txpower; nbss->ni_vlan = obss->ni_vlan; nbss->ni_rsn = obss->ni_rsn; /* XXX statistics? */}voidieee80211_create_ibss(struct ieee80211vap* vap, struct ieee80211_channel *chan){ struct ieee80211com *ic = vap->iv_ic; struct ieee80211_node *ni; IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s: creating ibss on channel %u\n", __func__, ieee80211_chan2ieee(ic, chan)); /* Check to see if we already have a node for this mac */ ni = ieee80211_find_node(&ic->ic_sta, vap->iv_myaddr); if (ni == NULL) { ni = ieee80211_alloc_node(&ic->ic_sta, vap, vap->iv_myaddr); if (ni == NULL) { /* XXX recovery? */ return; } } else ieee80211_free_node(ni); IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, "%s: %p<%s> refcnt %d\n", __func__, vap->iv_bss, ether_sprintf(vap->iv_bss->ni_macaddr), ieee80211_node_refcnt(ni)); IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_myaddr); ni->ni_esslen = vap->iv_des_ssid[0].len; memcpy(ni->ni_essid, vap->iv_des_ssid[0].ssid, ni->ni_esslen); if (vap->iv_bss != NULL) copy_bss(ni, vap->iv_bss); ni->ni_intval = ic->ic_lintval;#ifdef ATH_SUPERG_XR if (vap->iv_flags & IEEE80211_F_XR) { ni->ni_intval *= IEEE80211_XR_BEACON_FACTOR; }#endif if (vap->iv_flags & IEEE80211_F_PRIVACY) ni->ni_capinfo |= IEEE80211_CAPINFO_PRIVACY; if (ic->ic_phytype == IEEE80211_T_FH) { ni->ni_fhdwell = 200; /* XXX */ ni->ni_fhindex = 1; } if (vap->iv_opmode == IEEE80211_M_IBSS) { vap->iv_flags |= IEEE80211_F_SIBSS; ni->ni_capinfo |= IEEE80211_CAPINFO_IBSS; /* XXX */ if (vap->iv_flags & IEEE80211_F_DESBSSID) IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_des_bssid); else ni->ni_bssid[0] |= 0x02; /* local bit for IBSS */ } else if (vap->iv_opmode == IEEE80211_M_AHDEMO) { if (vap->iv_flags & IEEE80211_F_DESBSSID) IEEE80211_ADDR_COPY(ni->ni_bssid, vap->iv_des_bssid); else { ni->ni_bssid[0] = 0x00; ni->ni_bssid[1] = 0x00; ni->ni_bssid[2] = 0x00; ni->ni_bssid[3] = 0x00; ni->ni_bssid[4] = 0x00; ni->ni_bssid[5] = 0x00; } }#ifdef ATH_SUPERG_DYNTURBO if (vap->iv_opmode == IEEE80211_M_HOSTAP) { ni->ni_ath_flags = vap->iv_ath_cap; /* * no dynamic turbo and AR on a static turbo channel. * no dynamic turbo and AR on non-turbo channel. * no AR on 5GHZ channel . */ if (IEEE80211_IS_CHAN_STURBO(chan) || !ieee80211_find_channel(ic, chan->ic_freq, chan->ic_flags | IEEE80211_CHAN_TURBO)) ni->ni_ath_flags &= ~(IEEE80211_ATHC_TURBOP | IEEE80211_ATHC_AR); if (IEEE80211_IS_CHAN_5GHZ(chan)) ni->ni_ath_flags &= ~IEEE80211_ATHC_AR; }#endif /* * Fix the channel and related attributes. */ ic->ic_bsschan = chan; ieee80211_node_set_chan(ic, ni); ic->ic_curmode = ieee80211_chan2mode(chan); /* Update country ie information */ ieee80211_build_countryie(ic); if (IEEE80211_IS_CHAN_HALF(chan)) ni->ni_rates = ic->ic_sup_half_rates; else if (IEEE80211_IS_CHAN_QUARTER(chan)) ni->ni_rates = ic->ic_sup_quarter_rates; (void) ieee80211_sta_join1(ieee80211_ref_node(ni));}EXPORT_SYMBOL(ieee80211_create_ibss);/* * Reset bss state on transition to the INIT state. * Clear any stations from the table (they have been * deauth'd) and reset the bss node (clears key, rate, * etc. state). */voidieee80211_reset_bss(struct ieee80211vap *vap){ struct ieee80211com *ic = vap->iv_ic; struct ieee80211_node *ni, *obss; IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, "%s: old bss %p<%s> refcnt %d\n", __func__, vap->iv_bss, ether_sprintf(vap->iv_bss->ni_macaddr), ieee80211_node_refcnt(vap->iv_bss)); ieee80211_node_table_reset(&ic->ic_sta, vap); /* XXX multi-bss wrong */ ieee80211_reset_erp(ic, ic->ic_curmode); ni = ieee80211_alloc_node(&ic->ic_sta, vap, vap->iv_myaddr); KASSERT(ni != NULL, ("unable to setup inital BSS node")); obss = vap->iv_bss; vap->iv_bss = ieee80211_ref_node(ni); IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, "%s: new bss %p<%s> refcnt %d\n", __func__, vap->iv_bss, ether_sprintf(vap->iv_bss->ni_macaddr), ieee80211_node_refcnt(vap->iv_bss)); if (obss != NULL) { copy_bss(ni, obss); ni->ni_intval = ic->ic_lintval; ieee80211_free_node(obss); }}static intmatch_ssid(const struct ieee80211_node *ni, int nssid, const struct ieee80211_scan_ssid ssids[]){ int i; for (i = 0; i < nssid; i++) { if (ni->ni_esslen == ssids[i].len && memcmp(ni->ni_essid, ssids[i].ssid, ni->ni_esslen) == 0) return 1; } return 0;}/* * Test a node for suitability/compatibility. */static intcheck_bss(struct ieee80211vap *vap, struct ieee80211_node *ni){ struct ieee80211com *ic = ni->ni_ic; u_int8_t rate; if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, ni->ni_chan))) return 0; if (vap->iv_opmode == IEEE80211_M_IBSS) { if ((ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) == 0) return 0; } else { if ((ni->ni_capinfo & IEEE80211_CAPINFO_ESS) == 0) return 0; }
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -