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

📄 ieee80211_input.c

📁 Linux下wifi实现
💻 C
📖 第 1 页 / 共 5 页
字号:
	case WPA_SEL(WPA_ASE_NONE):		return WPA_ASE_NONE;	}	return 0;		/* NB: so is discarded */#undef WPA_SEL}/* * Parse a WPA information element to collect parameters * and validate the parameters against what has been * configured for the system. */static intieee80211_parse_wpa(struct ieee80211vap *vap, u_int8_t *frm,	struct ieee80211_rsnparms *rsn_parm, const struct ieee80211_frame *wh){	u_int8_t len = frm[1];	u_int32_t w;	int n;	/*	 * Check the length once for fixed parts: OUI, type,	 * version, mcast cipher, and 2 selector counts.	 * Other, variable-length data, must be checked separately.	 */	if (!(vap->iv_flags & IEEE80211_F_WPA1)) {		IEEE80211_DISCARD_IE(vap,			IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,			wh, "WPA", "vap not WPA, flags 0x%x", vap->iv_flags);		return IEEE80211_REASON_IE_INVALID;	}		if (len < 14) {		IEEE80211_DISCARD_IE(vap,			IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,			wh, "WPA", "too short, len %u", len);		return IEEE80211_REASON_IE_INVALID;	}	frm += 6, len -= 4;		/* NB: len is payload only */	/* NB: iswapoui already validated the OUI and type */	w = LE_READ_2(frm);	if (w != WPA_VERSION) {		IEEE80211_DISCARD_IE(vap,			IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,			wh, "WPA", "bad version %u", w);		return IEEE80211_REASON_IE_INVALID;	}	frm += 2;	len -= 2;	/* multicast/group cipher */	w = wpa_cipher(frm, &rsn_parm->rsn_mcastkeylen);	if (w != rsn_parm->rsn_mcastcipher) {		IEEE80211_DISCARD_IE(vap,			IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,			wh, "WPA", "mcast cipher mismatch; got %u, expected %u",			w, rsn_parm->rsn_mcastcipher);		return IEEE80211_REASON_IE_INVALID;	}	frm += 4;	len -= 4;	/* unicast ciphers */	n = LE_READ_2(frm);	frm += 2;	len -= 2;	if (len < n*4+2) {		IEEE80211_DISCARD_IE(vap,			IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,			wh, "WPA", "ucast cipher data too short; len %u, n %u",			len, n);		return IEEE80211_REASON_IE_INVALID;	}	w = 0;	for (; n > 0; n--) {		w |= 1 << wpa_cipher(frm, &rsn_parm->rsn_ucastkeylen);		frm += 4;		len -= 4;	}	w &= rsn_parm->rsn_ucastcipherset;	if (w == 0) {		IEEE80211_DISCARD_IE(vap,			IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,			wh, "WPA", "%s", "ucast cipher set empty");		return IEEE80211_REASON_IE_INVALID;	}	if (w & (1 << IEEE80211_CIPHER_TKIP))		rsn_parm->rsn_ucastcipher = IEEE80211_CIPHER_TKIP;	else		rsn_parm->rsn_ucastcipher = IEEE80211_CIPHER_AES_CCM;	/* key management algorithms */	n = LE_READ_2(frm);	frm += 2;	len -= 2;	if (len < n * 4) {		IEEE80211_DISCARD_IE(vap,			IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,			wh, "WPA", "key mgmt alg data too short; len %u, n %u",			len, n);		return IEEE80211_REASON_IE_INVALID;	}	w = 0;	for (; n > 0; n--) {		w |= wpa_keymgmt(frm);		frm += 4;		len -= 4;	}	w &= rsn_parm->rsn_keymgmtset;	if (w == 0) {		IEEE80211_DISCARD_IE(vap,			IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,			wh, "WPA", "%s", "no acceptable key mgmt alg");		return IEEE80211_REASON_IE_INVALID;	}	if (w & WPA_ASE_8021X_UNSPEC)		rsn_parm->rsn_keymgmt = WPA_ASE_8021X_UNSPEC;	else		rsn_parm->rsn_keymgmt = WPA_ASE_8021X_PSK;	if (len > 2)		/* optional capabilities */		rsn_parm->rsn_caps = LE_READ_2(frm);	return 0;}/* * Convert an RSN cipher selector OUI to an internal * cipher algorithm.  Where appropriate we also * record any key length. */static intrsn_cipher(u_int8_t *sel, u_int8_t *keylen){#define	RSN_SEL(x)	(((x) << 24) | RSN_OUI)	u_int32_t w = LE_READ_4(sel);	switch (w) {	case RSN_SEL(RSN_CSE_NULL):		return IEEE80211_CIPHER_NONE;	case RSN_SEL(RSN_CSE_WEP40):		if (keylen)			*keylen = 40 / NBBY;		return IEEE80211_CIPHER_WEP;	case RSN_SEL(RSN_CSE_WEP104):		if (keylen)			*keylen = 104 / NBBY;		return IEEE80211_CIPHER_WEP;	case RSN_SEL(RSN_CSE_TKIP):		return IEEE80211_CIPHER_TKIP;	case RSN_SEL(RSN_CSE_CCMP):		return IEEE80211_CIPHER_AES_CCM;	case RSN_SEL(RSN_CSE_WRAP):		return IEEE80211_CIPHER_AES_OCB;	}	return 32;		/* NB: so 1<< is discarded */#undef RSN_SEL}/* * Convert an RSN key management/authentication algorithm * to an internal code. */static intrsn_keymgmt(u_int8_t *sel){#define	RSN_SEL(x)	(((x) << 24) | RSN_OUI)	u_int32_t w = LE_READ_4(sel);	switch (w) {	case RSN_SEL(RSN_ASE_8021X_UNSPEC):		return RSN_ASE_8021X_UNSPEC;	case RSN_SEL(RSN_ASE_8021X_PSK):		return RSN_ASE_8021X_PSK;	case RSN_SEL(RSN_ASE_NONE):		return RSN_ASE_NONE;	}	return 0;		/* NB: so is discarded */#undef RSN_SEL}/* * Parse a WPA/RSN information element to collect parameters * and validate the parameters against what has been * configured for the system. */static intieee80211_parse_rsn(struct ieee80211vap *vap, u_int8_t *frm,	struct ieee80211_rsnparms *rsn_parm, const struct ieee80211_frame *wh){	u_int8_t len = frm[1];	u_int32_t w;	int n;	/*	 * Check the length once for fixed parts: 	 * version, mcast cipher, and 2 selector counts.	 * Other, variable-length data, must be checked separately.	 */	if (!(vap->iv_flags & IEEE80211_F_WPA2)) {		IEEE80211_DISCARD_IE(vap,			IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,			wh, "RSN", "vap not RSN, flags 0x%x", vap->iv_flags);		return IEEE80211_REASON_IE_INVALID;	}		if (len < 10) {		IEEE80211_DISCARD_IE(vap,			IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,			wh, "RSN", "too short, len %u", len);		return IEEE80211_REASON_IE_INVALID;	}	frm += 2;	w = LE_READ_2(frm);	if (w != RSN_VERSION) {		IEEE80211_DISCARD_IE(vap,			IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,			wh, "RSN", "bad version %u", w);		return IEEE80211_REASON_IE_INVALID;	}	frm += 2;	len -= 2;	/* multicast/group cipher */	w = rsn_cipher(frm, &rsn_parm->rsn_mcastkeylen);	if (w != rsn_parm->rsn_mcastcipher) {		IEEE80211_DISCARD_IE(vap,			IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,			wh, "RSN", "mcast cipher mismatch; got %u, expected %u",			w, rsn_parm->rsn_mcastcipher);		return IEEE80211_REASON_IE_INVALID;	}	frm += 4;	len -= 4;	/* unicast ciphers */	n = LE_READ_2(frm);	frm += 2;	len -= 2;	if (len < n * 4 + 2) {		IEEE80211_DISCARD_IE(vap,			IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,			wh, "RSN", "ucast cipher data too short; len %u, n %u",			len, n);		return IEEE80211_REASON_IE_INVALID;	}	w = 0;	for (; n > 0; n--) {		w |= 1 << rsn_cipher(frm, &rsn_parm->rsn_ucastkeylen);		frm += 4;		len -= 4;	}	w &= rsn_parm->rsn_ucastcipherset;	if (w == 0) {		IEEE80211_DISCARD_IE(vap,			IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,			wh, "RSN", "%s", "ucast cipher set empty");		return IEEE80211_REASON_IE_INVALID;	}	if (w & (1<<IEEE80211_CIPHER_TKIP))		rsn_parm->rsn_ucastcipher = IEEE80211_CIPHER_TKIP;	else		rsn_parm->rsn_ucastcipher = IEEE80211_CIPHER_AES_CCM;	/* key management algorithms */	n = LE_READ_2(frm);	frm += 2;	len -= 2;	if (len < n * 4) {		IEEE80211_DISCARD_IE(vap, 			IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,			wh, "RSN", "key mgmt alg data too short; len %u, n %u",			len, n);		return IEEE80211_REASON_IE_INVALID;	}	w = 0;	for (; n > 0; n--) {		w |= rsn_keymgmt(frm);		frm += 4;		len -= 4;	}	w &= rsn_parm->rsn_keymgmtset;	if (w == 0) {		IEEE80211_DISCARD_IE(vap,			IEEE80211_MSG_ELEMID | IEEE80211_MSG_WPA,			wh, "RSN", "%s", "no acceptable key mgmt alg");		return IEEE80211_REASON_IE_INVALID;	}	if (w & RSN_ASE_8021X_UNSPEC)		rsn_parm->rsn_keymgmt = RSN_ASE_8021X_UNSPEC;	else		rsn_parm->rsn_keymgmt = RSN_ASE_8021X_PSK;	/* optional RSN capabilities */	if (len > 2)		rsn_parm->rsn_caps = LE_READ_2(frm);	/* XXXPMKID */	return 0;}voidieee80211_saveie(u_int8_t **iep, const u_int8_t *ie){	u_int ielen = ie[1] + 2;	/*	 * Record information element for later use.	 */	if (*iep == NULL || (*iep)[1] != ie[1]) {		if (*iep != NULL)			FREE(*iep, M_DEVBUF);		MALLOC(*iep, void*, ielen, M_DEVBUF, M_NOWAIT);	}	if (*iep != NULL)		memcpy(*iep, ie, ielen);}EXPORT_SYMBOL(ieee80211_saveie);static intieee80211_parse_wmeie(u_int8_t *frm, const struct ieee80211_frame *wh, 					  struct ieee80211_node *ni){	u_int len = frm[1];	if (len != 7) {		IEEE80211_DISCARD_IE(ni->ni_vap,			IEEE80211_MSG_ELEMID | IEEE80211_MSG_WME,			wh, "WME IE", "too short, len %u", len);		return -1;	}	ni->ni_uapsd = frm[WME_CAPINFO_IE_OFFSET];	if (ni->ni_uapsd) {		ni->ni_flags |= IEEE80211_NODE_UAPSD;		switch (WME_UAPSD_MAXSP(ni->ni_uapsd)) {		case 1: 			ni->ni_uapsd_maxsp = 2; break;		case 2: 			ni->ni_uapsd_maxsp = 4; break;		case 3: 			ni->ni_uapsd_maxsp = 6; break;		default:  			ni->ni_uapsd_maxsp = WME_UAPSD_NODE_MAXQDEPTH;		}	}	IEEE80211_NOTE(ni->ni_vap, IEEE80211_MSG_POWER, ni,		"UAPSD bit settings from STA: %02x", ni->ni_uapsd);	return 1;}static intieee80211_parse_wmeparams(struct ieee80211vap *vap, u_int8_t *frm,	const struct ieee80211_frame *wh, u_int8_t *qosinfo){#define	MS(_v, _f)	(((_v) & _f) >> _f##_S)	struct ieee80211_wme_state *wme = &vap->iv_ic->ic_wme;	u_int len = frm[1], qosinfo_count;	int i;	*qosinfo = 0;	if (len < sizeof(struct ieee80211_wme_param)-2) {		IEEE80211_DISCARD_IE(vap,			IEEE80211_MSG_ELEMID | IEEE80211_MSG_WME,			wh, "WME", "too short, len %u", len);		return -1;	}	*qosinfo = frm[__offsetof(struct ieee80211_wme_param, param_qosInfo)];	qosinfo_count = *qosinfo & WME_QOSINFO_COUNT;	/* XXX do proper check for wraparound */	if (qosinfo_count == wme->wme_wmeChanParams.cap_info_count)		return 0;	frm += __offsetof(struct ieee80211_wme_param, params_acParams);	for (i = 0; i < WME_NUM_AC; i++) {		struct wmeParams *wmep =			&wme->wme_wmeChanParams.cap_wmeParams[i];		/* NB: ACI not used */		wmep->wmep_acm = MS(frm[0], WME_PARAM_ACM);		wmep->wmep_aifsn = MS(frm[0], WME_PARAM_AIFSN);		wmep->wmep_logcwmin = MS(frm[1], WME_PARAM_LOGCWMIN);		wmep->wmep_logcwmax = MS(frm[1], WME_PARAM_LOGCWMAX);		wmep->wmep_txopLimit = LE_READ_2(frm + 2);		frm += 4;	}	wme->wme_wmeChanParams.cap_info_count = qosinfo_count;	return 1;#undef MS}static voidieee80211_parse_athParams(struct ieee80211_node *ni, u_int8_t *ie){	struct ieee80211vap *vap = ni->ni_vap;	struct ieee80211com *ic = ni->ni_ic;	struct ieee80211_ie_athAdvCap *athIe =		(struct ieee80211_ie_athAdvCap *) ie;	ni->ni_ath_flags = athIe->athAdvCap_capability;	if (ni->ni_ath_flags & IEEE80211_ATHC_COMP)		ni->ni_ath_defkeyindex = LE_READ_2(&athIe->athAdvCap_defKeyIndex);#if 0	/* NB: too noisy */	IEEE80211_NOTE(vap, IEEE80211_MSG_SUPG, ni,		"recv ath params: caps 0x%x flags 0x%x defkeyix %u",		athIe->athAdvCap_capability, ni->ni_ath_flags,		ni->ni_ath_defkeyindex);#endif#ifdef ATH_SUPERG_DYNTURBO	if (IEEE80211_ATH_CAP(vap, ni, IEEE80211_ATHC_TURBOP)) {		u_int16_t curflags, newflags;		/*		 * Check for turbo mode switch.  Calculate flags		 * for the new mode and effect the switch.		 */		newflags = curflags = ic->ic_bsschan->ic_flags;		/* NB: ATHC_BOOST is not in ic_ath_cap, so get it from the ie */		if (athIe->athAdvCap_capability & IEEE80211_ATHC_BOOST) 			newflags |= IEEE80211_CHAN_TURBO;		else			newflags &= ~IEEE80211_CHAN_TURBO;		if (newflags != curflags)			ieee80211_dturbo_switch(ic, newflags);	}#endif /* ATH_SUPERG_DYNTURBO */}voidieee80211_saveath(struct ieee80211_node *ni, u_int8_t *ie){	const struct ieee80211_ie_athAdvCap *athIe =		(const struct ieee80211_ie_athAdvCap *) ie;	ni->ni_ath_flags = athIe->athAdvCap_capability;	if (ni->ni_ath_flags & IEEE80211_ATHC_COMP)		ni->ni_ath_defkeyindex = LE_READ_2(&athIe->athAdvCap_defKeyIndex);	ieee80211_saveie(&ni->ni_ath_ie, ie);}struct ieee80211_channel *ieee80211_doth_findchan(struct ieee80211vap *vap, u_int8_t chan){	

⌨️ 快捷键说明

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