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

📄 ieee80211_node.c

📁 Linux下wifi实现
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (vap->iv_flags & IEEE80211_F_PRIVACY) {		if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0)			return 0;	} else {		/* XXX does this mean privacy is supported or required? */		if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY)			return 0;	}	rate = ieee80211_fix_rate(ni, IEEE80211_F_DONEGO | IEEE80211_F_DOFRATE);	if (rate & IEEE80211_RATE_BASIC)		return 0;	if (vap->iv_des_nssid != 0 &&	    !match_ssid(ni, vap->iv_des_nssid, vap->iv_des_ssid))		return 0;	if ((vap->iv_flags & IEEE80211_F_DESBSSID) &&	    !IEEE80211_ADDR_EQ(vap->iv_des_bssid, ni->ni_bssid))		return 0;	return 1;}#ifdef IEEE80211_DEBUG/* * Display node suitability/compatibility. */static voidcheck_bss_debug(struct ieee80211vap *vap, struct ieee80211_node *ni){	struct ieee80211com *ic = ni->ni_ic;        u_int8_t rate;        int fail;	fail = 0;	if (isclr(ic->ic_chan_active, ieee80211_chan2ieee(ic, ni->ni_chan)))		fail |= 0x01;	if (vap->iv_opmode == IEEE80211_M_IBSS) {		if ((ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) == 0)			fail |= 0x02;	} else {		if ((ni->ni_capinfo & IEEE80211_CAPINFO_ESS) == 0)			fail |= 0x02;	}	if (vap->iv_flags & IEEE80211_F_PRIVACY) {		if ((ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) == 0)			fail |= 0x04;	} else {		/* XXX does this mean privacy is supported or required? */		if (ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY)			fail |= 0x04;	}	rate = ieee80211_fix_rate(ni, IEEE80211_F_DONEGO | IEEE80211_F_DOFRATE);	if (rate & IEEE80211_RATE_BASIC)		fail |= 0x08;	if (vap->iv_des_nssid != 0 &&	    !match_ssid(ni, vap->iv_des_nssid, vap->iv_des_ssid))		fail |= 0x10;	if ((vap->iv_flags & IEEE80211_F_DESBSSID) &&	    !IEEE80211_ADDR_EQ(vap->iv_des_bssid, ni->ni_bssid))		fail |= 0x20;	printf(" %c %s", fail ? '-' : '+', ether_sprintf(ni->ni_macaddr));	printf(" %s%c", ether_sprintf(ni->ni_bssid), fail & 0x20 ? '!' : ' ');	printf(" %3d%c",		ieee80211_chan2ieee(ic, ni->ni_chan), fail & 0x01 ? '!' : ' ');	printf(" %+4d", ni->ni_rssi);	printf(" %2dM%c", (rate & IEEE80211_RATE_VAL) / 2,		fail & 0x08 ? '!' : ' ');	printf(" %4s%c",		(ni->ni_capinfo & IEEE80211_CAPINFO_ESS) ? "ess" :			(ni->ni_capinfo & IEEE80211_CAPINFO_IBSS) ? "ibss" :				"????",	    	fail & 0x02 ? '!' : ' ');	printf(" %3s%c ",	    	(ni->ni_capinfo & IEEE80211_CAPINFO_PRIVACY) ?  "wep" : "no",	    	fail & 0x04 ? '!' : ' ');	ieee80211_print_essid(ni->ni_essid, ni->ni_esslen);	printf("%s\n", fail & 0x10 ? "!" : "");}#endif /* IEEE80211_DEBUG */ /* * Handle 802.11 ad hoc network merge.  The * convention, set by the Wireless Ethernet Compatibility Alliance * (WECA), is that an 802.11 station will change its BSSID to match * the "oldest" 802.11 ad hoc network, on the same channel, that * has the station's desired SSID.  The "oldest" 802.11 network * sends beacons with the greatest TSF timestamp. * * The caller is assumed to validate TSF's before attempting a merge. * * Return !0 if the BSSID changed, 0 otherwise. */intieee80211_ibss_merge(struct ieee80211_node *ni){	struct ieee80211vap *vap = ni->ni_vap;	struct ieee80211com *ic = ni->ni_ic;	if (ni == vap->iv_bss ||	    IEEE80211_ADDR_EQ(ni->ni_bssid, vap->iv_bss->ni_bssid)) {		/* unchanged, nothing to do */		return 0;	}	if (!check_bss(vap, ni)) {		/* capabilities mismatch */		IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC,		    "%s: merge failed, capabilities mismatch\n", __func__);#ifdef IEEE80211_DEBUG		if (ieee80211_msg_assoc(vap))			check_bss_debug(vap, ni);#endif		vap->iv_stats.is_ibss_capmismatch++;		return 0;	}	IEEE80211_DPRINTF(vap, IEEE80211_MSG_ASSOC,		"%s: new bssid %s: %s preamble, %s slot time%s\n", __func__,		ether_sprintf(ni->ni_bssid),		ic->ic_flags & IEEE80211_F_SHPREAMBLE ? "short" : "long",		ic->ic_flags & IEEE80211_F_SHSLOT ? "short" : "long",		ic->ic_flags & IEEE80211_F_USEPROT ? ", protection" : "");	return ieee80211_sta_join1(ieee80211_ref_node(ni));}EXPORT_SYMBOL(ieee80211_ibss_merge);static __inline intssid_equal(const struct ieee80211_node *a, const struct ieee80211_node *b){	return (a->ni_esslen == b->ni_esslen &&		memcmp(a->ni_essid, b->ni_bssid, a->ni_esslen) == 0);}/* * Join the specified IBSS/BSS network.  The node is assumed to * be passed in with a reference already held for use in assigning * to iv_bss. */static intieee80211_sta_join1(struct ieee80211_node *selbs){	struct ieee80211vap *vap = selbs->ni_vap;	struct ieee80211com *ic = selbs->ni_ic;	struct ieee80211_node *obss;	int canreassoc;	if (vap->iv_opmode == IEEE80211_M_IBSS) {		/*		 * Delete unusable rates; we've already checked		 * that the negotiated rate set is acceptable.		 */		ieee80211_fix_rate(selbs, IEEE80211_F_DODEL);	}	/*	 * Committed to selbs, setup state.	 */	obss = vap->iv_bss;	/*	 * Check if old+new node have the same ssid in which	 * case we can reassociate when operating in sta mode.	 */	canreassoc = (obss != NULL &&		vap->iv_state == IEEE80211_S_RUN && ssid_equal(obss, selbs));	vap->iv_bss = selbs;	if (obss != NULL)		ieee80211_free_node(obss);	ic->ic_bsschan = selbs->ni_chan;	ic->ic_curchan = ic->ic_bsschan;	ic->ic_curmode = ieee80211_chan2mode(ic->ic_curchan);	ic->ic_set_channel(ic);	/*	 * Set the erp state (mostly the slot time) to deal with	 * the auto-select case; this should be redundant if the	 * mode is locked.	 */ 	ieee80211_reset_erp(ic, ic->ic_curmode);	ieee80211_wme_initparams(vap);	if (vap->iv_opmode == IEEE80211_M_STA) {		/*		 * Act as if we received a DEAUTH frame in case we are		 * invoked from the RUN state.  This will cause us to try		 * to re-authenticate if we are operating as a station.		 */		if (canreassoc) {			vap->iv_nsparams.newstate = IEEE80211_S_ASSOC;			vap->iv_nsparams.arg = 0;			IEEE80211_SCHEDULE_TQUEUE(&vap->iv_stajoin1tq);		} else {			vap->iv_nsparams.newstate = IEEE80211_S_AUTH;			vap->iv_nsparams.arg = IEEE80211_FC0_SUBTYPE_DEAUTH;			IEEE80211_SCHEDULE_TQUEUE(&vap->iv_stajoin1tq);		}	} else {		vap->iv_nsparams.newstate = IEEE80211_S_RUN;		vap->iv_nsparams.arg = -1;		IEEE80211_SCHEDULE_TQUEUE(&vap->iv_stajoin1tq);	}	return 1;}voidieee80211_sta_join1_tasklet(IEEE80211_TQUEUE_ARG data){	struct ieee80211vap *vap= (struct ieee80211vap *) data;	int rc;	rc = ieee80211_new_state(vap, vap->iv_nsparams.newstate, vap->iv_nsparams.arg);	vap->iv_nsparams.result = rc;	vap->iv_nsdone = 1;}EXPORT_SYMBOL(ieee80211_sta_join1_tasklet);intieee80211_sta_join(struct ieee80211vap *vap,	const struct ieee80211_scan_entry *se){	struct ieee80211com *ic = vap->iv_ic;	struct ieee80211_node *ni;	ni = ieee80211_find_node(&ic->ic_sta, se->se_macaddr);	if (ni == NULL) {		ni = ieee80211_alloc_node(&ic->ic_sta, vap, se->se_macaddr);		if (ni == NULL) {			/* XXX msg */			return 0;		}	} else		ieee80211_free_node(ni);	/*	 * Expand scan state into node's format.	 * XXX may not need all this stuff	 */	ni->ni_authmode = vap->iv_bss->ni_authmode;		/* inherit authmode from iv_bss */	/* inherit the WPA setup as well (structure copy!) */	ni->ni_rsn = vap->iv_bss->ni_rsn; 	IEEE80211_ADDR_COPY(ni->ni_bssid, se->se_bssid);	ni->ni_esslen = se->se_ssid[1];	memcpy(ni->ni_essid, se->se_ssid + 2, ni->ni_esslen);	ni->ni_rstamp = se->se_rstamp;	ni->ni_tstamp.tsf = se->se_tstamp.tsf;	ni->ni_intval = se->se_intval;	ni->ni_capinfo = se->se_capinfo;	ni->ni_chan = se->se_chan;	ni->ni_timoff = se->se_timoff;	ni->ni_fhdwell = se->se_fhdwell;	ni->ni_fhindex = se->se_fhindex;	ni->ni_erp = se->se_erp;	ni->ni_rssi = se->se_rssi;	if (se->se_wpa_ie != NULL)		ieee80211_saveie(&ni->ni_wpa_ie, se->se_wpa_ie);	if (se->se_rsn_ie != NULL)		ieee80211_saveie(&ni->ni_rsn_ie, se->se_rsn_ie);	if (se->se_wme_ie != NULL)		ieee80211_saveie(&ni->ni_wme_ie, se->se_wme_ie);	if (se->se_ath_ie != NULL)		ieee80211_saveath(ni, se->se_ath_ie);	vap->iv_dtim_period = se->se_dtimperiod;	vap->iv_dtim_count = 0;	/* NB: must be after ni_chan is setup */	ieee80211_setup_rates(ni, se->se_rates, se->se_xrates,		IEEE80211_F_DOSORT | IEEE80211_F_DONEGO | IEEE80211_F_DODEL);	IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, 	"%s: %p<%s> refcnt %d\n", __func__, ni, ether_sprintf(ni->ni_macaddr), 	ieee80211_node_refcnt(ni)+1);	return ieee80211_sta_join1(ieee80211_ref_node(ni));}EXPORT_SYMBOL(ieee80211_sta_join);/* * Leave the specified IBSS/BSS network.  The node is assumed to * be passed in with a held reference. */voidieee80211_sta_leave(struct ieee80211_node *ni){	struct ieee80211vap *vap = ni->ni_vap;	struct ieee80211com *ic = vap->iv_ic;	/* WDS/Repeater: Stop software beacon timer for STA */	if (vap->iv_opmode == IEEE80211_M_STA &&	    vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS) {		del_timer(&vap->iv_swbmiss);	}	ic->ic_node_cleanup(ni);	ieee80211_notify_node_leave(ni);}/* * Node table support. */static voidieee80211_node_table_init(struct ieee80211com *ic,	struct ieee80211_node_table *nt,	const char *name, int inact){	nt->nt_ic = ic;	IEEE80211_NODE_LOCK_INIT(nt, ic->ic_dev->name);	IEEE80211_SCAN_LOCK_INIT(nt, ic->ic_dev->name);	TAILQ_INIT(&nt->nt_node);	nt->nt_name = name;	nt->nt_scangen = 1;	nt->nt_inact_init = inact;	init_timer(&nt->nt_wds_aging_timer);	nt->nt_wds_aging_timer.function = ieee80211_node_wds_ageout;	nt->nt_wds_aging_timer.data = (unsigned long) nt;	mod_timer(&nt->nt_wds_aging_timer, jiffies + HZ * WDS_AGING_TIMER_VAL);}static struct ieee80211_node *node_alloc(struct ieee80211_node_table *nt, struct ieee80211vap *vap){	struct ieee80211_node *ni;	MALLOC(ni, struct ieee80211_node *, sizeof(struct ieee80211_node),		M_80211_NODE, M_NOWAIT | M_ZERO);	return ni;}/* * Reclaim any resources in a node and reset any critical * state.  Typically nodes are free'd immediately after, * but in some cases the storage may be reused so we need * to ensure consistent state (should probably fix that). * * Context: hwIRQ, softIRQ and process context */static voidnode_cleanup(struct ieee80211_node *ni){#define	N(a)	(sizeof(a)/sizeof(a[0]))	struct ieee80211vap *vap = ni->ni_vap;	int i;	/* NB: preserve ni_table */	if (ni->ni_flags & IEEE80211_NODE_PWR_MGT) {		if (vap->iv_opmode != IEEE80211_M_STA)			vap->iv_ps_sta--;		ni->ni_flags &= ~IEEE80211_NODE_PWR_MGT;		IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,			"power save mode off, %u sta's in ps mode",			vap->iv_ps_sta);		if (ni->ni_flags & IEEE80211_NODE_UAPSD_TRIG) {			ni->ni_flags &= ~IEEE80211_NODE_UAPSD_TRIG;			IEEE80211_LOCK_IRQ(ni->ni_ic);			ni->ni_ic->ic_uapsdmaxtriggers--;			IEEE80211_UNLOCK_IRQ(ni->ni_ic);		}	}	/*	 * Clear AREF flag that marks the authorization refcnt bump	 * has happened.  This is probably not needed as the node	 * should always be removed from the table so not found but	 * do it just in case.	 */	ni->ni_flags &= ~IEEE80211_NODE_AREF;	/*	 * Drain power save queue and, if needed, clear TIM.	 */	if (ieee80211_node_saveq_drain(ni) != 0 && vap->iv_set_tim != NULL)		vap->iv_set_tim(ni, 0);	ni->ni_associd = 0;	if (ni->ni_challenge != NULL) {		FREE(ni->ni_challenge, M_DEVBUF);		ni->ni_challenge = NULL;	}	/*	 * Preserve SSID, WPA, and WME ie's so the bss node is	 * reusable during a re-auth/re-assoc state transition.	 * If we remove these data they will not be recreated	 * because they come from a probe-response or beacon frame	 * which cannot be expected prior to the association-response.	 * This should not be an issue when operating in other modes	 * as stations leaving always go through a full state transition	 * which will rebuild this state.	 *	 * XXX does this leave us open to inheriting old state?	 */	for (i = 0; i < N(ni->ni_rxfrag); i++)		if (ni->ni_rxfrag[i] != NULL) {			dev_kfree_skb_any(ni->ni_rxfrag[i]);			ni->ni_rxfrag[i] = NULL;		}	ieee80211_crypto_delkey(vap, &ni->ni_ucastkey, ni);	ni->ni_rxkeyoff = 0;#undef N}static voidnode_free(struct ieee80211_node *ni){	struct ieee80211com *ic = ni->ni_ic;	ic->ic_node_cleanup(ni);	if (ni->ni_wpa_ie != NULL)		FREE(ni->ni_wpa_ie, M_DEVBUF);	if (ni->ni_rsn_ie != NULL)		FREE(ni->ni_rsn_ie, M_DEVBUF);	if (ni->ni_wme_ie != NULL)		FREE(ni->ni_wme_ie, M_DEVBUF);	if (ni->ni_ath_ie != NULL)		FREE(ni->ni_ath_ie, M_DEVBUF);	IEEE80211_NODE_SAVEQ_DESTROY(ni);	FREE(ni, M_80211_NODE);}static u_int8_tnode_getrssi(const struct ieee80211_node *ni){

⌨️ 快捷键说明

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