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

📄 ieee80211_input.c

📁 Linux下wifi实现
💻 C
📖 第 1 页 / 共 5 页
字号:
		if (status != 0) {			IEEE80211_NOTE(vap,				IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH, ni,				"open auth failed (reason %d)", status);			vap->iv_stats.is_rx_auth_fail++;			ieee80211_new_state(vap, IEEE80211_S_SCAN,				IEEE80211_SCAN_FAIL_STATUS);		} else			ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0);		break;	case IEEE80211_M_MONITOR:		break;	}}/* * Send a management frame error response to the specified * station.  If ni is associated with the station then use * it; otherwise allocate a temporary node suitable for * transmitting the frame and then free the reference so * it will go away as soon as the frame has been transmitted. */static voidieee80211_send_error(struct ieee80211_node *ni,	const u_int8_t *mac, int subtype, int arg){	struct ieee80211vap *vap = ni->ni_vap;	int istmp;	if (ni == vap->iv_bss) {		ni = ieee80211_tmp_node(vap, mac);		if (ni == NULL) {			/* XXX msg */			return;		}		istmp = 1;	} else		istmp = 0;	IEEE80211_SEND_MGMT(ni, subtype, arg);	if (istmp)		ieee80211_free_node(ni);}static intalloc_challenge(struct ieee80211_node *ni){	if (ni->ni_challenge == NULL)		MALLOC(ni->ni_challenge, u_int32_t*, IEEE80211_CHALLENGE_LEN,			M_DEVBUF, M_NOWAIT);	if (ni->ni_challenge == NULL) {		IEEE80211_NOTE(ni->ni_vap,			IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH, ni,			"%s", "shared key challenge alloc failed");		/* XXX statistic */	}	return (ni->ni_challenge != NULL);}/* XXX TODO: add statistics */static voidieee80211_auth_shared(struct ieee80211_node *ni, struct ieee80211_frame *wh,	u_int8_t *frm, u_int8_t *efrm, int rssi, u_int32_t rstamp,	u_int16_t seq, u_int16_t status){	struct ieee80211vap *vap = ni->ni_vap;	u_int8_t *challenge;	int allocbs, estatus;	/*	 * NB: this can happen as we allow pre-shared key	 * authentication to be enabled w/o wep being turned	 * on so that configuration of these can be done	 * in any order.  It may be better to enforce the	 * ordering in which case this check would just be	 * for sanity/consistency.	 */	estatus = 0;			/* NB: silence compiler */	if ((vap->iv_flags & IEEE80211_F_PRIVACY) == 0) {		IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_AUTH,			ni->ni_macaddr, "shared key auth",			"%s", " PRIVACY is disabled");		estatus = IEEE80211_STATUS_ALG;		goto bad;	}	/*	 * Pre-shared key authentication is evil; accept	 * it only if explicitly configured (it is supported	 * mainly for compatibility with clients like OS X).	 */	if (ni->ni_authmode != IEEE80211_AUTH_AUTO &&	    ni->ni_authmode != IEEE80211_AUTH_SHARED) {		IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_AUTH,			ni->ni_macaddr, "shared key auth",			"bad sta auth mode %u", ni->ni_authmode);		vap->iv_stats.is_rx_bad_auth++;	/* XXX maybe a unique error? */		estatus = IEEE80211_STATUS_ALG;		goto bad;	}	challenge = NULL;	if (frm + 1 < efrm) {		if ((frm[1] + 2) > (efrm - frm)) {			IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_AUTH,				ni->ni_macaddr, "shared key auth",				"ie %d/%d too long",				frm[0], (frm[1] + 2) - (efrm - frm));			vap->iv_stats.is_rx_bad_auth++;			estatus = IEEE80211_STATUS_CHALLENGE;			goto bad;		}		if (*frm == IEEE80211_ELEMID_CHALLENGE)			challenge = frm;		frm += frm[1] + 2;	}	switch (seq) {	case IEEE80211_AUTH_SHARED_CHALLENGE:	case IEEE80211_AUTH_SHARED_RESPONSE:		if (challenge == NULL) {			IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_AUTH,				ni->ni_macaddr, "shared key auth",				"%s", "no challenge");			vap->iv_stats.is_rx_bad_auth++;			estatus = IEEE80211_STATUS_CHALLENGE;			goto bad;		}		if (challenge[1] != IEEE80211_CHALLENGE_LEN) {			IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_AUTH,				ni->ni_macaddr, "shared key auth",				"bad challenge len %d", challenge[1]);			vap->iv_stats.is_rx_bad_auth++;			estatus = IEEE80211_STATUS_CHALLENGE;			goto bad;		}	default:		break;	}	switch (vap->iv_opmode) {	case IEEE80211_M_MONITOR:	case IEEE80211_M_AHDEMO:	case IEEE80211_M_IBSS:	case IEEE80211_M_WDS:		IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_AUTH,			ni->ni_macaddr, "shared key auth",			"bad operating mode %u", vap->iv_opmode);		return;	case IEEE80211_M_HOSTAP:		if (vap->iv_state != IEEE80211_S_RUN) {			IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_AUTH,				ni->ni_macaddr, "shared key auth",				"bad state %u", vap->iv_state);			estatus = IEEE80211_STATUS_ALG;	/* XXX */			goto bad;		}		switch (seq) {		case IEEE80211_AUTH_SHARED_REQUEST:			if (ni == vap->iv_bss) {				ni = ieee80211_dup_bss(vap, wh->i_addr2);				if (ni == NULL) {					/* NB: no way to return an error */					return;				}				IEEE80211_DPRINTF(vap, IEEE80211_MSG_NODE, 				"%s: %p<%s> refcnt %d\n", __func__, ni, ether_sprintf(ni->ni_macaddr), 				ieee80211_node_refcnt(ni));				allocbs = 1;			} else {				if ((ni->ni_flags & IEEE80211_NODE_AREF) == 0)					(void) ieee80211_ref_node(ni);				allocbs = 0;			}			/*			 * Mark the node as referenced to reflect that it's			 * reference count has been bumped to ensure it remains			 * after the transaction completes.			 */			ni->ni_flags |= IEEE80211_NODE_AREF;			ni->ni_rssi = rssi;			ni->ni_rstamp = rstamp;			ni->ni_last_rx = jiffies;			if (!alloc_challenge(ni)) {				/* NB: don't return error so they rexmit */				return;			}			get_random_bytes(ni->ni_challenge,				IEEE80211_CHALLENGE_LEN);			IEEE80211_NOTE(vap,				IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH, ni,				"shared key %sauth request", allocbs ? "" : "re");			break;		case IEEE80211_AUTH_SHARED_RESPONSE:			if (ni == vap->iv_bss) {				IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_AUTH,					ni->ni_macaddr, "shared key response",					"%s", "unknown station");				/* NB: don't send a response */				return;			}			if (ni->ni_challenge == NULL) {				IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_AUTH,					ni->ni_macaddr, "shared key response",					"%s", "no challenge recorded");				vap->iv_stats.is_rx_bad_auth++;				estatus = IEEE80211_STATUS_CHALLENGE;				goto bad;			}			if (memcmp(ni->ni_challenge, &challenge[2],			    challenge[1]) != 0) {				IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_AUTH,					ni->ni_macaddr, "shared key response",					"%s", "challenge mismatch");				vap->iv_stats.is_rx_auth_fail++;				estatus = IEEE80211_STATUS_CHALLENGE;				goto bad;			}			IEEE80211_NOTE(vap,				IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH, ni,				"station authenticated (%s)", "shared key");			ieee80211_node_authorize(ni);			break;		default:			IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_AUTH,				ni->ni_macaddr, "shared key auth",				"bad seq %d", seq);			vap->iv_stats.is_rx_bad_auth++;			estatus = IEEE80211_STATUS_SEQUENCE;			goto bad;		}		IEEE80211_SEND_MGMT(ni, IEEE80211_FC0_SUBTYPE_AUTH, seq + 1);		break;	case IEEE80211_M_STA:		if (vap->iv_state != IEEE80211_S_AUTH)			return;		switch (seq) {		case IEEE80211_AUTH_SHARED_PASS:			if (ni->ni_challenge != NULL) {				FREE(ni->ni_challenge, M_DEVBUF);				ni->ni_challenge = NULL;			}			if (status != 0) {				IEEE80211_NOTE_MAC(vap,					IEEE80211_MSG_DEBUG | IEEE80211_MSG_AUTH,					ieee80211_getbssid(vap, wh),					"shared key auth failed (reason %d)",					status);				vap->iv_stats.is_rx_auth_fail++;				/* XXX IEEE80211_SCAN_FAIL_STATUS */				goto bad;			}			ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0);			break;		case IEEE80211_AUTH_SHARED_CHALLENGE:			if (!alloc_challenge(ni))				goto bad;			/* XXX could optimize by passing recvd challenge */			memcpy(ni->ni_challenge, &challenge[2], challenge[1]);			IEEE80211_SEND_MGMT(ni,				IEEE80211_FC0_SUBTYPE_AUTH, seq + 1);			break;		default:			IEEE80211_DISCARD(vap, IEEE80211_MSG_AUTH,				wh, "shared key auth", "bad seq %d", seq);			vap->iv_stats.is_rx_bad_auth++;			goto bad;		}		break;	}	return;bad:	/*	 * Send an error response; but only when operating as an AP.	 */	if (vap->iv_opmode == IEEE80211_M_HOSTAP) {		/* XXX hack to workaround calling convention */		ieee80211_send_error(ni, wh->i_addr2, 			IEEE80211_FC0_SUBTYPE_AUTH,			(seq + 1) | (estatus<<16));	} else if (vap->iv_opmode == IEEE80211_M_STA) {		/*		 * Kick the state machine.  This short-circuits		 * using the mgt frame timeout to trigger the		 * state transition.		 */		if (vap->iv_state == IEEE80211_S_AUTH)			ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);	}}/* Verify the existence and length of __elem or get out. */#define IEEE80211_VERIFY_ELEMENT(__elem, __maxlen) do {			\	if ((__elem) == NULL) {						\		IEEE80211_DISCARD(vap, IEEE80211_MSG_ELEMID,		\			wh, ieee80211_mgt_subtype_name[subtype >>	\				IEEE80211_FC0_SUBTYPE_SHIFT],		\			"%s", "no " #__elem );				\		vap->iv_stats.is_rx_elem_missing++;			\		return;							\	}								\	if ((__elem)[1] > (__maxlen)) {					\		IEEE80211_DISCARD(vap, IEEE80211_MSG_ELEMID,		\			wh, ieee80211_mgt_subtype_name[subtype >>	\				IEEE80211_FC0_SUBTYPE_SHIFT],		\			"bad " #__elem " len %d", (__elem)[1]);		\		vap->iv_stats.is_rx_elem_toobig++;			\		return;							\	}								\} while (0)#define	IEEE80211_VERIFY_LENGTH(_len, _minlen) do {			\	if ((_len) < (_minlen)) {					\		IEEE80211_DISCARD(vap, IEEE80211_MSG_ELEMID,		\			wh, ieee80211_mgt_subtype_name[subtype >>	\				IEEE80211_FC0_SUBTYPE_SHIFT],		\			"%s", "ie too short");				\		vap->iv_stats.is_rx_elem_toosmall++;			\		return;							\	}								\} while (0)#ifdef IEEE80211_DEBUGstatic voidieee80211_ssid_mismatch(struct ieee80211vap *vap, const char *tag,	u_int8_t mac[IEEE80211_ADDR_LEN], u_int8_t *ssid){	printf("[%s] discard %s frame, ssid mismatch: ",		ether_sprintf(mac), tag);	ieee80211_print_essid(ssid + 2, ssid[1]);	printf("\n");}#define	IEEE80211_VERIFY_SSID(_ni, _ssid) do {				\	if ((_ssid)[1] != 0 &&						\	    ((_ssid)[1] != (_ni)->ni_esslen ||				\	    memcmp((_ssid) + 2, (_ni)->ni_essid, (_ssid)[1]) != 0)) {	\		if (ieee80211_msg_input(vap))				\			ieee80211_ssid_mismatch(vap, 			\			    	ieee80211_mgt_subtype_name[subtype >>	\					IEEE80211_FC0_SUBTYPE_SHIFT],	\				wh->i_addr2, _ssid);			\		vap->iv_stats.is_rx_ssidmismatch++;			\		return;							\	}								\} while (0)#else /* !IEEE80211_DEBUG */#define	IEEE80211_VERIFY_SSID(_ni, _ssid) do {				\	if ((_ssid)[1] != 0 &&						\	    ((_ssid)[1] != (_ni)->ni_esslen ||				\	    memcmp((_ssid) + 2, (_ni)->ni_essid, (_ssid)[1]) != 0)) {	\		vap->iv_stats.is_rx_ssidmismatch++;			\		return;							\	}								\} while (0)#endif /* !IEEE80211_DEBUG *//* unalligned little endian access */     #define LE_READ_2(p)					\	((u_int16_t)					\	 ((((const u_int8_t *)(p))[0]      ) |		\	  (((const u_int8_t *)(p))[1] <<  8)))#define LE_READ_4(p)					\	((u_int32_t)					\	 ((((const u_int8_t *)(p))[0]      ) |		\	  (((const u_int8_t *)(p))[1] <<  8) |		\	  (((const u_int8_t *)(p))[2] << 16) |		\	  (((const u_int8_t *)(p))[3] << 24)))static __inline intiswpaoui(const u_int8_t *frm){	return frm[1] > 3 && LE_READ_4(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI);}static __inline intiswmeoui(const u_int8_t *frm){	return frm[1] > 3 && LE_READ_4(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI);}static __inline intiswmeparam(const u_int8_t *frm){	return frm[1] > 5 && LE_READ_4(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI) &&		frm[6] == WME_PARAM_OUI_SUBTYPE;}static __inline intiswmeinfo(const u_int8_t *frm){	return frm[1] > 5 && LE_READ_4(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI) &&		frm[6] == WME_INFO_OUI_SUBTYPE;}static __inline intisatherosoui(const u_int8_t *frm){	return frm[1] > 3 && LE_READ_4(frm+2) == ((ATH_OUI_TYPE<<24)|ATH_OUI);}/* * Convert a WPA cipher selector OUI to an internal * cipher algorithm.  Where appropriate we also * record any key length. */static intwpa_cipher(u_int8_t *sel, u_int8_t *keylen){#define	WPA_SEL(x)	(((x) << 24) | WPA_OUI)	u_int32_t w = LE_READ_4(sel);	switch (w) {	case WPA_SEL(WPA_CSE_NULL):		return IEEE80211_CIPHER_NONE;	case WPA_SEL(WPA_CSE_WEP40):		if (keylen)			*keylen = 40 / NBBY;		return IEEE80211_CIPHER_WEP;	case WPA_SEL(WPA_CSE_WEP104):		if (keylen)			*keylen = 104 / NBBY;		return IEEE80211_CIPHER_WEP;	case WPA_SEL(WPA_CSE_TKIP):		return IEEE80211_CIPHER_TKIP;	case WPA_SEL(WPA_CSE_CCMP):		return IEEE80211_CIPHER_AES_CCM;	}	return 32;		/* NB: so 1<< is discarded */#undef WPA_SEL}/* * Convert a WPA key management/authentication algorithm * to an internal code. */static intwpa_keymgmt(u_int8_t *sel){#define	WPA_SEL(x)	(((x)<<24)|WPA_OUI)	u_int32_t w = LE_READ_4(sel);	switch (w) {	case WPA_SEL(WPA_ASE_8021X_UNSPEC):		return WPA_ASE_8021X_UNSPEC;	case WPA_SEL(WPA_ASE_8021X_PSK):		return WPA_ASE_8021X_PSK;

⌨️ 快捷键说明

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