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

📄 ieee80211_proto.c

📁 Linux下wifi实现
💻 C
📖 第 1 页 / 共 4 页
字号:
	switch (nstate) {	case IEEE80211_S_INIT:		switch (ostate) {		case IEEE80211_S_INIT:			break;		case IEEE80211_S_RUN:			switch (vap->iv_opmode) {			case IEEE80211_M_STA:				IEEE80211_SEND_MGMT(ni,					IEEE80211_FC0_SUBTYPE_DISASSOC,					IEEE80211_REASON_ASSOC_LEAVE);				ieee80211_sta_leave(ni);				break;			case IEEE80211_M_HOSTAP:				ieee80211_iterate_nodes(&ic->ic_sta,					sta_disassoc, vap);				break;			default:				break;			}			goto reset;		case IEEE80211_S_ASSOC:			switch (vap->iv_opmode) {			case IEEE80211_M_STA:				IEEE80211_SEND_MGMT(ni,					IEEE80211_FC0_SUBTYPE_DEAUTH,					IEEE80211_REASON_AUTH_LEAVE);				break;			case IEEE80211_M_HOSTAP:				ieee80211_iterate_nodes(&ic->ic_sta,					sta_deauth, vap);				break;			default:				break;			}			goto reset;		case IEEE80211_S_SCAN:			ieee80211_cancel_scan(vap);			goto reset;		case IEEE80211_S_AUTH:		reset:			ieee80211_reset_bss(vap);			break;		}		if (vap->iv_auth->ia_detach != NULL)			vap->iv_auth->ia_detach(vap);		break;	case IEEE80211_S_SCAN:		switch (ostate) {		case IEEE80211_S_INIT:		createibss:			if ((vap->iv_opmode == IEEE80211_M_HOSTAP ||			     vap->iv_opmode == IEEE80211_M_IBSS ||			     vap->iv_opmode == IEEE80211_M_AHDEMO) &&			    vap->iv_des_chan != IEEE80211_CHAN_ANYC) {				/*				 * AP operation and we already have a channel;				 * bypass the scan and startup immediately.				 */				ieee80211_create_ibss(vap, vap->iv_des_chan);			} else {				ieee80211_check_scan(vap,					IEEE80211_SCAN_ACTIVE | 					IEEE80211_SCAN_FLUSH,					IEEE80211_SCAN_FOREVER,					vap->iv_des_nssid, vap->iv_des_ssid,					NULL);			}			break;		case IEEE80211_S_SCAN:		case IEEE80211_S_AUTH:		case IEEE80211_S_ASSOC:			/*			 * These can happen either because of a timeout			 * on an assoc/auth response or because of a			 * change in state that requires a reset.  For			 * the former we're called with a non-zero arg			 * that is the cause for the failure; pass this			 * to the scan code so it can update state.			 * Otherwise trigger a new scan unless we're in			 * manual roaming mode in which case an application			 * must issue an explicit scan request.			 */			if (arg != 0)				ieee80211_scan_assoc_fail(ic,					vap->iv_bss->ni_macaddr, arg);			if (ic->ic_roaming == IEEE80211_ROAMING_AUTO)				ieee80211_check_scan(vap,					IEEE80211_SCAN_ACTIVE,					IEEE80211_SCAN_FOREVER,					vap->iv_des_nssid, vap->iv_des_ssid,					NULL);			break;		case IEEE80211_S_RUN:		/* beacon miss */			if (vap->iv_opmode == IEEE80211_M_STA) {				ieee80211_sta_leave(ni);				vap->iv_flags &= ~IEEE80211_F_SIBSS;	/* XXX */				if (ic->ic_roaming == IEEE80211_ROAMING_AUTO)					ieee80211_check_scan(vap,						IEEE80211_SCAN_ACTIVE,						IEEE80211_SCAN_FOREVER,						vap->iv_des_nssid,						vap->iv_des_ssid,						NULL);			} else {				ieee80211_iterate_nodes(&ic->ic_sta,					sta_disassoc, vap);				goto createibss;			}			break;		}		break;	case IEEE80211_S_AUTH:		KASSERT(vap->iv_opmode == IEEE80211_M_STA,			("switch to %s state when operating in mode %u",			 ieee80211_state_name[nstate], vap->iv_opmode));		switch (ostate) {		case IEEE80211_S_INIT:		case IEEE80211_S_SCAN:			IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_AUTH, 1);			break;		case IEEE80211_S_AUTH:		case IEEE80211_S_ASSOC:			switch (arg) {			case IEEE80211_FC0_SUBTYPE_AUTH:				/* ??? */				IEEE80211_SEND_MGMT(ni,					IEEE80211_FC0_SUBTYPE_AUTH, 2);				break;			case IEEE80211_FC0_SUBTYPE_DEAUTH:				IEEE80211_SEND_MGMT(ni,					IEEE80211_FC0_SUBTYPE_AUTH, 1);				break;			}			break;		case IEEE80211_S_RUN:			switch (arg) {			case IEEE80211_FC0_SUBTYPE_AUTH:				IEEE80211_SEND_MGMT(ni,					IEEE80211_FC0_SUBTYPE_AUTH, 2);				vap->iv_state = ostate;	/* stay RUN */				break;			case IEEE80211_FC0_SUBTYPE_DEAUTH:				ieee80211_sta_leave(ni);				if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) {					/* try to reauth */					IEEE80211_SEND_MGMT(ni,						IEEE80211_FC0_SUBTYPE_AUTH, 1);				}				break;			}			break;		}		break;	case IEEE80211_S_ASSOC:		KASSERT(vap->iv_opmode == IEEE80211_M_STA,			("switch to %s state when operating in mode %u",			 ieee80211_state_name[nstate], vap->iv_opmode));		switch (ostate) {		case IEEE80211_S_INIT:		case IEEE80211_S_SCAN:			IEEE80211_DPRINTF(vap, IEEE80211_MSG_ANY,				"%s: invalid transition\n", __func__);			break;		case IEEE80211_S_AUTH:		case IEEE80211_S_ASSOC:			IEEE80211_SEND_MGMT(ni,				IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0);			break;		case IEEE80211_S_RUN:			ieee80211_sta_leave(ni);			if (ic->ic_roaming == IEEE80211_ROAMING_AUTO) {				/* NB: caller specifies ASSOC/REASSOC by arg */				IEEE80211_SEND_MGMT(ni, arg ?					IEEE80211_FC0_SUBTYPE_REASSOC_REQ :					IEEE80211_FC0_SUBTYPE_ASSOC_REQ, 0);			}			break;		}		break;	case IEEE80211_S_RUN:		if (vap->iv_flags & IEEE80211_F_WPA) {			/* XXX validate prerequisites */		}		switch (ostate) {		case IEEE80211_S_INIT:			if (vap->iv_opmode == IEEE80211_M_MONITOR ||			    vap->iv_opmode == IEEE80211_M_WDS ||			    vap->iv_opmode == IEEE80211_M_HOSTAP) {				/*				 * Already have a channel; bypass the				 * scan and startup immediately.				 */				ieee80211_create_ibss(vap, ic->ic_curchan);				/*				 * In wds mode allocate and initialize peer node				 */								if (vap->iv_opmode == IEEE80211_M_WDS) {					struct ieee80211_node *wds_ni;					wds_ni = ieee80211_alloc_node(&ic->ic_sta, vap, vap->wds_mac);					if (wds_ni != NULL) {						if (ieee80211_add_wds_addr(&ic->ic_sta, wds_ni, vap->wds_mac, 1) == 0) {							ieee80211_node_authorize(wds_ni);							wds_ni->ni_chan = vap->iv_bss->ni_chan;							wds_ni->ni_capinfo = ni->ni_capinfo;							wds_ni->ni_associd = 1;							wds_ni->ni_ath_flags = vap->iv_ath_cap;						}					}				}				break;			}			/* fall thru... */		case IEEE80211_S_AUTH:			IEEE80211_DPRINTF(vap, IEEE80211_MSG_ANY,				"%s: invalid transition\n", __func__);			break;		case IEEE80211_S_RUN:			break;		case IEEE80211_S_SCAN:		/* adhoc/hostap mode */		case IEEE80211_S_ASSOC:		/* infra mode */			KASSERT(ni->ni_txrate < ni->ni_rates.rs_nrates,				("%s: bogus xmit rate %u setup\n", __func__,				ni->ni_txrate));#ifdef IEEE80211_DEBUG			if (ieee80211_msg_debug(vap)) {				ieee80211_note(vap, "%s with %s ssid ",					(vap->iv_opmode == IEEE80211_M_STA ?					"associated" : "synchronized "),					ether_sprintf(ni->ni_bssid));				ieee80211_print_essid(vap->iv_bss->ni_essid,					ni->ni_esslen);				printf(" channel %d start %uMb\n",					ieee80211_chan2ieee(ic, ic->ic_curchan),					IEEE80211_RATE2MBS(ni->ni_rates.rs_rates[ni->ni_txrate]));			}#endif			if (vap->iv_opmode == IEEE80211_M_STA) {				ieee80211_scan_assoc_success(ic,					ni->ni_macaddr);				ieee80211_notify_node_join(ni, 					(arg == IEEE80211_FC0_SUBTYPE_ASSOC_RESP) | \					(arg == IEEE80211_FC0_SUBTYPE_REASSOC_RESP));			}			break;		}		/* WDS/Repeater: Start software beacon timer for STA */		if (ostate != IEEE80211_S_RUN &&		    (vap->iv_opmode == IEEE80211_M_STA &&		     vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS)) {			vap->iv_swbmiss.function = ieee80211_sta_swbmiss;			vap->iv_swbmiss.data = (unsigned long) vap;			vap->iv_swbmiss_period = IEEE80211_TU_TO_JIFFIES(				IEEE80211_SWBMISS_THRESHOLD * ni->ni_intval);						mod_timer(&vap->iv_swbmiss, jiffies + vap->iv_swbmiss_period);		}				/*		 * Start/stop the authenticator when operating as an		 * AP.  We delay until here to allow configuration to		 * happen out of order.		 */		/* XXX WDS? */		if (vap->iv_opmode == IEEE80211_M_HOSTAP && /* XXX IBSS/AHDEMO */		    vap->iv_auth->ia_attach != NULL) {			/* XXX check failure */			vap->iv_auth->ia_attach(vap);		} else if (vap->iv_auth->ia_detach != NULL)			vap->iv_auth->ia_detach(vap);		/*		 * When 802.1x is not in use mark the port authorized		 * at this point so traffic can flow.		 */		if (ni->ni_authmode != IEEE80211_AUTH_8021X)			ieee80211_node_authorize(ni);#ifdef ATH_SUPERG_XR		/*		 * fire a timer to bring up XR vap if configured.		 */		if (ostate != IEEE80211_S_RUN &&		    vap->iv_xrvap &&		    !(vap->iv_flags & IEEE80211_F_XR)) {			vap->iv_xrvapstart.function = ieee80211_start_xrvap;			vap->iv_xrvapstart.data = (unsigned long) vap->iv_xrvap;			mod_timer(&vap->iv_xrvapstart,jiffies+HZ); /* start xr vap on next second */			/* 			 * do not let the normal vap automatically bring up XR vap.			 * let the timer handler start the XR vap. if you let the			 * normal vap automatically start the XR vap  normal vap will not			 * have the bssid initialized and the XR vap will use the			 * invalid bssid in XRIE of its beacon.			 */			if (vap->iv_xrvap->iv_flags_ext & IEEE80211_FEXT_SCAN_PENDING) 				vap->iv_xrvap->iv_flags_ext &= ~IEEE80211_FEXT_SCAN_PENDING;		}		/*		 * when an XR vap transitions to RUN state,		 * normal vap needs to update the XR IE		 * with the xr vaps MAC address.		 */		if (vap->iv_flags & IEEE80211_F_XR)			vap->iv_xrvap->iv_flags |= IEEE80211_F_XRUPDATE; #endif		break;	}		return 0;}static intieee80211_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg){	struct ieee80211com *ic = vap->iv_ic;	enum ieee80211_state ostate;	struct ieee80211vap *tmpvap;	ostate = vap->iv_state;	switch (nstate) {	case IEEE80211_S_SCAN:		if (ostate == IEEE80211_S_INIT) {			int nrunning, nscanning;			nrunning = nscanning = 0;			TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) {				if (vap != tmpvap) {					if (tmpvap->iv_state == IEEE80211_S_RUN)						nrunning++;					else if (tmpvap->iv_state == IEEE80211_S_SCAN ||					    tmpvap->iv_state == IEEE80211_S_AUTH || /* STA in WDS/Repeater */					    tmpvap->iv_state == IEEE80211_S_ASSOC)						nscanning++;				}			}			KASSERT(!(nscanning && nrunning), ("SCAN and RUN can't happen at the same time\n"));			if (!nscanning && !nrunning) {				/* when no one is running or scanning, start a new scan */				__ieee80211_newstate(vap, nstate, arg);			} else if (!nscanning && nrunning) {				/* when no one is scanning but someone is running, bypass				 * scan and go to run state immediately */				__ieee80211_newstate(vap, IEEE80211_S_RUN, arg);			} else if (nscanning && !nrunning) {				/* when someone is scanning and no one is running, set				 * the scan pending flag. Don't go through state machine */				IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE,					"%s: %s -> %s with SCAN_PENDING\n",					__func__,					ieee80211_state_name[ostate],					ieee80211_state_name[nstate]);				vap->iv_flags_ext |= IEEE80211_FEXT_SCAN_PENDING;			}		} else {			/* the VAP is forced to scan, we need to change all other vap's state			 * to INIT and pend for the scan completion */			TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) {				if (vap != tmpvap && tmpvap->iv_state != IEEE80211_S_INIT) {					tmpvap->iv_newstate(tmpvap, IEEE80211_S_INIT, 0);					tmpvap->iv_flags_ext |= IEEE80211_FEXT_SCAN_PENDING;				}			}			/* start the new scan */			__ieee80211_newstate(vap, nstate, arg);		}		break;			case IEEE80211_S_RUN:		if (ostate == IEEE80211_S_SCAN ||		/* AP coming out of scan */		    vap->iv_opmode == IEEE80211_M_STA) {	/* STA in WDS/Repeater needs to bring up other VAPs  */			__ieee80211_newstate(vap, nstate, arg);			/* bring up all other vaps pending on the scan*/			TAILQ_FOREACH(tmpvap, &ic->ic_vaps, iv_next) {				if (vap != tmpvap) {					if (tmpvap->iv_flags_ext & IEEE80211_FEXT_SCAN_PENDING) {						tmpvap->iv_flags_ext &= ~IEEE80211_FEXT_SCAN_PENDING;						tmpvap->iv_newstate(tmpvap, IEEE80211_S_RUN, 0);					}				}			}		} else			__ieee80211_newstate(vap, nstate, arg);		break;	case IEEE80211_S_INIT:		if (ostate == IEEE80211_S_INIT && vap->iv_flags_ext & IEEE80211_FEXT_SCAN_PENDING)			vap->iv_flags_ext &= ~IEEE80211_FEXT_SCAN_PENDING;		/* fall through */	default:		__ieee80211_newstate(vap, nstate, arg);	}	return 0;}#ifdef ATH_SUPERG_XR/* * start the XR vap . * called from a timer when normal vap enters RUN state . */static voidieee80211_start_xrvap(unsigned long data){	struct ieee80211vap *vap = (struct ieee80211vap *)data;	/* make sure that the normal vap is still in RUN state */	if (vap->iv_xrvap->iv_state == IEEE80211_S_RUN)		ieee80211_init(vap->iv_dev, 0);}#endif

⌨️ 快捷键说明

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