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

📄 ieee80211_scan_sta.c

📁 Linux下wifi实现
💻 C
📖 第 1 页 / 共 3 页
字号:
		 * Scan cache contents is too old; check about updating it.		 */		if (curRate < roamRate || curRssi < roamRssi) {			/*			 * Thresholds exceeded, force a scan now so we			 * have current state to make a decision with.			 */			ieee80211_bg_scan(vap);		} else if (time_after(jiffies,			ic->ic_lastdata + vap->iv_bgscanidle)) {			/*			 * We're not in need of a new ap, but idle;			 * kick off a bg scan to replenish the cache.			 */			ieee80211_bg_scan(vap);		}	} else {		/*		 * Scan cache contents are warm enough to use;		 * check if a new ap should be used and switch.		 * XXX deauth current ap		 */		if (curRate < roamRate || curRssi < roamRssi) {			se->base.se_rssi = curRssi;			selbs = select_bss(ss, vap);			if (selbs != NULL && selbs != se)				ieee80211_sta_join(vap, &selbs->base);		}	}}/* * Age entries in the scan cache. * XXX also do roaming since it's convenient */static voidsta_age(struct ieee80211_scan_state *ss){	struct ieee80211vap *vap = ss->ss_vap;	struct sta_table *st = ss->ss_priv;	struct sta_entry *se, *next;	spin_lock(&st->st_lock);	TAILQ_FOREACH_SAFE(se, &st->st_entry, se_list, next) {		if (se->se_notseen > STA_PURGE_SCANS) {			TAILQ_REMOVE(&st->st_entry, se, se_list);			LIST_REMOVE(se, se_hash);			FREE(se, M_80211_SCAN);		}	}	spin_unlock(&st->st_lock);	/*	 * If rate control is enabled check periodically to see if	 * we should roam from our current connection to one that	 * might be better.  This only applies when we're operating	 * in sta mode and automatic roaming is set.	 * XXX defer if busy	 * XXX repeater station	 */	KASSERT(vap->iv_opmode == IEEE80211_M_STA,		("wrong mode %u", vap->iv_opmode));	/* XXX turn this off until the ap release is cut */	if (0 && vap->iv_ic->ic_roaming == IEEE80211_ROAMING_AUTO &&	    vap->iv_state >= IEEE80211_S_RUN)		/* XXX vap is implicit */		sta_roam_check(ss, vap);}/* * Iterate over the entries in the scan cache, invoking * the callback function on each one. */static voidsta_iterate(struct ieee80211_scan_state *ss, 	ieee80211_scan_iter_func *f, void *arg){	struct sta_table *st = ss->ss_priv;	struct sta_entry *se;	u_int gen;	spin_lock(&st->st_scanlock);	gen = st->st_scangen++;restart:	spin_lock(&st->st_lock);	TAILQ_FOREACH(se, &st->st_entry, se_list) {		if (se->se_scangen != gen) {			se->se_scangen = gen;			/* update public state */			se->base.se_age = jiffies - se->se_lastupdate;			spin_unlock(&st->st_lock);			(*f)(arg, &se->base);			goto restart;		}	}	spin_unlock(&st->st_lock);	spin_unlock(&st->st_scanlock);}static voidsta_assoc_fail(struct ieee80211_scan_state *ss,	const u_int8_t macaddr[IEEE80211_ADDR_LEN], int reason){	struct sta_table *st = ss->ss_priv;	struct sta_entry *se;	se = sta_lookup(st, macaddr);	if (se != NULL) {		se->se_fails++;		se->se_lastfail = jiffies;		IEEE80211_NOTE_MAC(ss->ss_vap, IEEE80211_MSG_SCAN,			macaddr, "%s: reason %u fails %u",			__func__, reason, se->se_fails);	}}static voidsta_assoc_success(struct ieee80211_scan_state *ss,	const u_int8_t macaddr[IEEE80211_ADDR_LEN]){	struct sta_table *st = ss->ss_priv;	struct sta_entry *se;	se = sta_lookup(st, macaddr);	if (se != NULL) {#if 0		se->se_fails = 0;		IEEE80211_NOTE_MAC(ss->ss_vap, IEEE80211_MSG_SCAN,			macaddr, "%s: fails %u", __func__, se->se_fails);#endif		se->se_lastassoc = jiffies;	}}static const struct ieee80211_scanner sta_default = {	.scan_name		= "default",	.scan_attach		= sta_attach,	.scan_detach		= sta_detach,	.scan_start		= sta_start,	.scan_restart		= sta_restart,	.scan_cancel		= sta_cancel,	.scan_end		= sta_pick_bss,	.scan_flush		= sta_flush,	.scan_add		= sta_add,	.scan_age		= sta_age,	.scan_iterate		= sta_iterate,	.scan_assoc_fail	= sta_assoc_fail,	.scan_assoc_success	= sta_assoc_success,	.scan_default		= ieee80211_sta_join,};/* * Start an adhoc-mode scan by populating the channel list. */static intadhoc_start(struct ieee80211_scan_state *ss, struct ieee80211vap *vap){#define	N(a)	(sizeof(a)/sizeof(a[0]))	struct ieee80211com *ic = vap->iv_ic;	struct sta_table *st = ss->ss_priv;	const struct scanlist *scan;	enum ieee80211_phymode mode;		ss->ss_last = 0;	/*	 * Use the table of ordered channels to construct the list	 * of channels for scanning.  Any channels in the ordered	 * list not in the master list will be discarded.	 */	for (scan = staScanTable; scan->list != NULL; scan++) {		mode = scan->mode;		if (vap->iv_des_mode != IEEE80211_MODE_AUTO) {			/*			 * If a desired mode was specified, scan only 			 * channels that satisfy that constraint.			 */			if (vap->iv_des_mode != mode) {				/*				 * The scan table marks 2.4Ghz channels as b				 * so if the desired mode is 11g, then use				 * the 11b channel list but upgrade the mode.				 */				if (vap->iv_des_mode != IEEE80211_MODE_11G ||				    mode != IEEE80211_MODE_11B)					continue;				mode = IEEE80211_MODE_11G;	/* upgrade */			}		} else {			/*			 * This lets ieee80211_scan_add_channels			 * upgrade an 11b channel to 11g if available.			 */			if (mode == IEEE80211_MODE_11B)				mode = IEEE80211_MODE_AUTO;		}		/* XR does not operate on turbo channels */		if ((vap->iv_flags & IEEE80211_F_XR) &&		    (mode == IEEE80211_MODE_TURBO_A ||		     mode == IEEE80211_MODE_TURBO_G))			continue;		/*		 * Add the list of the channels; any that are not		 * in the master channel list will be discarded.		 */		add_channels(ic, ss, mode, scan->list, scan->count);	}	ss->ss_next = 0;	/* XXX tunables */	ss->ss_mindwell = msecs_to_jiffies(200);	/* 200ms */	ss->ss_maxdwell = msecs_to_jiffies(200);	/* 200ms */#ifdef IEEE80211_DEBUG	if (ieee80211_msg_scan(vap)) {		printf("%s: scan set ", vap->iv_dev->name);		ieee80211_scan_dump_channels(ss);		printf(" dwell min %ld max %ld\n",			ss->ss_mindwell, ss->ss_maxdwell);	}#endif /* IEEE80211_DEBUG */	st->st_newscan = 1;	return 0;#undef N}/* * Select a channel to start an adhoc network on. * The channel list was populated with appropriate * channels so select one that looks least occupied. * XXX need regulatory domain constraints */static struct ieee80211_channel *adhoc_pick_channel(struct ieee80211_scan_state *ss){	struct sta_table *st = ss->ss_priv;	struct sta_entry *se;	struct ieee80211_channel *c, *bestchan;	int i, bestrssi, maxrssi;	bestchan = NULL;	bestrssi = -1;	spin_lock(&st->st_lock);	for (i = 0; i < ss->ss_last; i++) {		c = ss->ss_chans[i];		maxrssi = 0;		TAILQ_FOREACH(se, &st->st_entry, se_list) {			if (se->base.se_chan != c)				continue;			if (se->base.se_rssi > maxrssi)				maxrssi = se->base.se_rssi;		}		if (bestchan == NULL || maxrssi < bestrssi)			bestchan = c;	}	spin_unlock(&st->st_lock);	return bestchan;}/* * Pick an ibss network to join or find a channel * to use to start an ibss network. */static intadhoc_pick_bss(struct ieee80211_scan_state *ss, struct ieee80211vap *vap,	int (*action)(struct ieee80211vap *, const struct ieee80211_scan_entry *),	u_int32_t flags){	struct sta_table *st = ss->ss_priv;	struct sta_entry *selbs;	struct ieee80211_channel *chan;	KASSERT(vap->iv_opmode == IEEE80211_M_IBSS ||		vap->iv_opmode == IEEE80211_M_AHDEMO,		("wrong opmode %u", vap->iv_opmode));	if (st->st_newscan) {		sta_update_notseen(st);		st->st_newscan = 0;	}	if (ss->ss_flags & IEEE80211_SCAN_NOPICK) {		/*		 * Manual/background scan, don't select+join the		 * bss, just return.  The scanning framework will		 * handle notification that this has completed.		 */		ss->ss_flags &= ~IEEE80211_SCAN_NOPICK;		return 1;	}	st->st_action = ss->ss_ops->scan_default;	if (action)		st->st_action = action;	/*	 * Automatic sequencing; look for a candidate and	 * if found join the network.	 */	/* NB: unlocked read should be ok */	if (TAILQ_FIRST(&st->st_entry) == NULL ||		(selbs = select_bss(ss, vap)) == NULL ) {		IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,			"%s: no scan candidate\n", __func__);		if (vap->iv_des_nssid) {			/*			 * No existing adhoc network to join and we have			 * an ssid; start one up.  If no channel was			 * specified, try to select a channel.			 */			if (vap->iv_des_chan == IEEE80211_CHAN_ANYC)				chan = adhoc_pick_channel(ss);			else				chan = vap->iv_des_chan;			if (chan != NULL) {				struct ieee80211_scan_entry se;				memset(&se, 0, sizeof(se));				se.se_chan = chan;				st->st_selbss = se;				/* defer action */				IEEE80211_SCHEDULE_TQUEUE(&st->st_actiontq);				return 1;			}		}		/*		 * If nothing suitable was found decrement		 * the failure counts so entries will be		 * reconsidered the next time around.  We		 * really want to do this only for sta's		 * where we've previously had some success.		 */		sta_dec_fails(st);		st->st_newscan = 1;		return 0;			/* restart scan */	}	/* 	 * Must defer action to avoid possible recursive call through 80211	 * state machine, which would result in recursive locking.	 */	st->st_selbss = selbs->base;	IEEE80211_SCHEDULE_TQUEUE(&st->st_actiontq);	return 1;				/* terminate scan */}/* * Age entries in the scan cache. */static voidadhoc_age(struct ieee80211_scan_state *ss){	struct sta_table *st = ss->ss_priv;	struct sta_entry *se, *next;	spin_lock(&st->st_lock);	TAILQ_FOREACH_SAFE(se, &st->st_entry, se_list, next) {		if (se->se_notseen > STA_PURGE_SCANS) {			TAILQ_REMOVE(&st->st_entry, se, se_list);			LIST_REMOVE(se, se_hash);			FREE(se, M_80211_SCAN);		}	}	spin_unlock(&st->st_lock);}/* * Default action to execute when a scan entry is found for adhoc * mode.  Return 1 on success, 0 on failure */static intadhoc_default_action(struct ieee80211vap *vap,	const struct ieee80211_scan_entry *se){	u_int8_t zeroMacAddr[IEEE80211_ADDR_LEN];	memset(&zeroMacAddr, 0, IEEE80211_ADDR_LEN);	if (IEEE80211_ADDR_EQ(se->se_bssid, &zeroMacAddr[0])) {		ieee80211_create_ibss(vap, se->se_chan);		return 1;	} else 		return ieee80211_sta_join(vap,se);}static const struct ieee80211_scanner adhoc_default = {	.scan_name		= "default",	.scan_attach		= sta_attach,	.scan_detach		= sta_detach,	.scan_start		= adhoc_start,	.scan_restart		= sta_restart,	.scan_cancel		= sta_cancel,	.scan_end		= adhoc_pick_bss,	.scan_flush		= sta_flush,	.scan_add		= sta_add,	.scan_age		= adhoc_age,	.scan_iterate		= sta_iterate,	.scan_assoc_fail	= sta_assoc_fail,	.scan_assoc_success	= sta_assoc_success,	.scan_default		= adhoc_default_action,};static voidaction_tasklet(IEEE80211_TQUEUE_ARG data){	struct ieee80211_scan_state *ss = (struct ieee80211_scan_state *)data;	struct sta_table *st = (struct sta_table *)ss->ss_priv;	struct ieee80211vap *vap = ss->ss_vap;	struct ieee80211_channel *chan;	if ((*ss->ss_ops->scan_default)(vap, &st->st_selbss))		return;	switch (vap->iv_opmode) {	case IEEE80211_M_STA:		sta_dec_fails(st);		st->st_newscan = 1;		break;	default:		/* ADHOC */        	if (vap->iv_des_nssid) {			/*			 * No existing adhoc network to join and we have			 * an ssid; start one up.  If no channel was			 * specified, try to select a channel.			 */			if (vap->iv_des_chan == IEEE80211_CHAN_ANYC)				chan = adhoc_pick_channel(ss);			else				chan = vap->iv_des_chan;			if (chan != NULL) {				struct ieee80211_scan_entry se;								memset(&se, 0, sizeof(se));				se.se_chan = chan;				if ((*ss->ss_ops->scan_default)(vap, &se))					return;			}		}		/*		 * If nothing suitable was found decrement	         * the failure counts so entries will be		 * reconsidered the next time around.  We		 * really want to do this only for sta's		 * where we've previously had some success.		 */		sta_dec_fails(st);		st->st_newscan = 1;			break;	}	/* 	 * restart scan 	 */	/* no ap, clear the flag for a new scan */	vap->iv_ic->ic_flags &= ~IEEE80211_F_SCAN;	if ((ss->ss_flags & IEEE80211_SCAN_USECACHE) == 0)		ieee80211_start_scan(vap, ss->ss_flags, ss->ss_duration, ss->ss_nssid, ss->ss_ssid);}/* * Module glue. */MODULE_AUTHOR("Errno Consulting, Sam Leffler");MODULE_DESCRIPTION("802.11 wireless support: default station scanner");#ifdef MODULE_LICENSEMODULE_LICENSE("Dual BSD/GPL");#endifstatic int __initinit_scanner_sta(void){	ieee80211_scanner_register(IEEE80211_M_STA, &sta_default);	ieee80211_scanner_register(IEEE80211_M_IBSS, &adhoc_default);	ieee80211_scanner_register(IEEE80211_M_AHDEMO, &adhoc_default);	return 0;}module_init(init_scanner_sta);static void __exitexit_scanner_sta(void){	ieee80211_scanner_unregister_all(&sta_default);	ieee80211_scanner_unregister_all(&adhoc_default);}module_exit(exit_scanner_sta);

⌨️ 快捷键说明

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