⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ieee80211_node.c

📁 Linux下wifi实现
💻 C
📖 第 1 页 / 共 5 页
字号:
/*- * 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;	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -