Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ab617971 authored by Dan Williams's avatar Dan Williams Committed by David S. Miller
Browse files

[PATCH] libertas: clean up 802.11 IE post-scan handling



Remove struct IE_WPA and just use direct checking of the IE
bytes like ipw.  Remove WLAN_802_11_VARIABLE_IEs because
it's unused.

Kill ieeetypes_elementid enum and just use MFIE_* from
ieee80211.h.  Also use struct ieee80211_info_element for
scan buffer processing to simplify pointer usage.

Signed-off-by: default avatarDan Williams <dcbw@redhat.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 2950cd26
Loading
Loading
Loading
Loading
+0 −13
Original line number Diff line number Diff line
@@ -91,25 +91,12 @@ struct enc_key {
	u8 key[32];
};

struct IE_WPA {
	u8 elementid;
	u8 len;
	u8 oui[4];
	__le16 version;
};

/* wlan_offset_value */
struct wlan_offset_value {
	u32 offset;
	u32 value;
};

struct WLAN_802_11_VARIABLE_IEs {
	u8 elementid;
	u8 length;
	u8 data[1];
};

/* Define general data structure */
/* cmd_DS_GEN */
struct cmd_ds_gen {
+84 −115
Original line number Diff line number Diff line
@@ -74,8 +74,8 @@ static inline int match_bss_no_security(struct wlan_802_11_security * secinfo,
	if (   !secinfo->wep_enabled
	    && !secinfo->WPAenabled
	    && !secinfo->WPA2enabled
	    && match_bss->wpa_ie[0] != WPA_IE
	    && match_bss->rsn_ie[0] != WPA2_IE
	    && match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC
	    && match_bss->rsn_ie[0] != MFIE_TYPE_RSN
	    && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {
		return 1;
	}
@@ -99,7 +99,7 @@ static inline int match_bss_wpa(struct wlan_802_11_security * secinfo,
{
	if (  !secinfo->wep_enabled
	   && secinfo->WPAenabled
	   && (match_bss->wpa_ie[0] == WPA_IE)
	   && (match_bss->wpa_ie[0] == MFIE_TYPE_GENERIC)
	   /* privacy bit may NOT be set in some APs like LinkSys WRT54G
	      && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {
	    */
@@ -114,7 +114,7 @@ static inline int match_bss_wpa2(struct wlan_802_11_security * secinfo,
{
	if (  !secinfo->wep_enabled
	   && secinfo->WPA2enabled
	   && (match_bss->rsn_ie[0] == WPA2_IE)
	   && (match_bss->rsn_ie[0] == MFIE_TYPE_RSN)
	   /* privacy bit may NOT be set in some APs like LinkSys WRT54G
	      && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {
	    */
@@ -130,8 +130,8 @@ static inline int match_bss_dynamic_wep(struct wlan_802_11_security * secinfo,
	if (  !secinfo->wep_enabled
	   && !secinfo->WPAenabled
	   && !secinfo->WPA2enabled
	   && (match_bss->wpa_ie[0] != WPA_IE)
	   && (match_bss->rsn_ie[0] != WPA2_IE)
	   && (match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC)
	   && (match_bss->rsn_ie[0] != MFIE_TYPE_RSN)
	   && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {
		return 1;
	}
@@ -900,24 +900,18 @@ void wlan_ret_802_11_scan_get_tlv_ptrs(struct mrvlietypes_data * ptlv,
static int libertas_process_bss(struct bss_descriptor * bss,
				u8 ** pbeaconinfo, int *bytesleft)
{
	enum ieeetypes_elementid elemID;
	struct ieeetypes_fhparamset *pFH;
	struct ieeetypes_dsparamset *pDS;
	struct ieeetypes_cfparamset *pCF;
	struct ieeetypes_ibssparamset *pibss;
	u8 *pcurrentptr;
	u8 *pos, *end;
	u8 *pRate;
	u8 elemlen;
	u8 bytestocopy;
	u8 ratesize;
	u16 beaconsize;
	u8 founddatarateie;
	int bytesleftforcurrentbeacon;
	int ret;

	struct IE_WPA *pIe;
	const u8 oui01[4] = { 0x00, 0x50, 0xf2, 0x01 };

	struct ieeetypes_countryinfoset *pcountryinfo;

	lbs_deb_enter(LBS_DEB_ASSOC);
@@ -934,29 +928,24 @@ static int libertas_process_bss(struct bss_descriptor * bss,
	}

	if (beaconsize == 0 || beaconsize > *bytesleft) {

		*pbeaconinfo += *bytesleft;
		*bytesleft = 0;

		return -1;
	}

	/* Initialize the current working beacon pointer for this BSS iteration */
	pcurrentptr = *pbeaconinfo;
	pos = *pbeaconinfo;
	end = pos + beaconsize;

	/* Advance the return beacon pointer past the current beacon */
	*pbeaconinfo += beaconsize;
	*bytesleft -= beaconsize;

	bytesleftforcurrentbeacon = beaconsize;

	memcpy(bss->bssid, pcurrentptr, ETH_ALEN);
	memcpy(bss->bssid, pos, ETH_ALEN);
	lbs_deb_scan("process_bss: AP BSSID " MAC_FMT "\n", MAC_ARG(bss->bssid));
	pos += ETH_ALEN;

	pcurrentptr += ETH_ALEN;
	bytesleftforcurrentbeacon -= ETH_ALEN;

	if (bytesleftforcurrentbeacon < 12) {
	if ((end - pos) < 12) {
		lbs_deb_scan("process_bss: Not enough bytes left\n");
		return -1;
	}
@@ -967,26 +956,22 @@ static int libertas_process_bss(struct bss_descriptor * bss,
	 */

	/* RSSI is 1 byte long */
	bss->rssi = *pcurrentptr;
	lbs_deb_scan("process_bss: RSSI=%02X\n", *pcurrentptr);
	pcurrentptr += 1;
	bytesleftforcurrentbeacon -= 1;
	bss->rssi = *pos;
	lbs_deb_scan("process_bss: RSSI=%02X\n", *pos);
	pos++;

	/* time stamp is 8 bytes long */
	bss->timestamp = le64_to_cpup((void *)pcurrentptr);
	pcurrentptr += 8;
	bytesleftforcurrentbeacon -= 8;
	bss->timestamp = le64_to_cpup((void *) pos);
	pos += 8;

	/* beacon interval is 2 bytes long */
	bss->beaconperiod = le16_to_cpup((void *)pcurrentptr);
	pcurrentptr += 2;
	bytesleftforcurrentbeacon -= 2;
	bss->beaconperiod = le16_to_cpup((void *) pos);
	pos += 2;

	/* capability information is 2 bytes long */
	bss->capability = le16_to_cpup((void *)pcurrentptr);
	bss->capability = le16_to_cpup((void *) pos);
	lbs_deb_scan("process_bss: capabilities = 0x%4X\n", bss->capability);
	pcurrentptr += 2;
	bytesleftforcurrentbeacon -= 2;
	pos += 2;

	if (bss->capability & WLAN_CAPABILITY_PRIVACY)
		lbs_deb_scan("process_bss: AP WEP enabled\n");
@@ -996,47 +981,39 @@ static int libertas_process_bss(struct bss_descriptor * bss,
		bss->mode = IW_MODE_INFRA;

	/* rest of the current buffer are IE's */
	lbs_deb_scan("process_bss: IE length for this AP = %d\n",
	       bytesleftforcurrentbeacon);

	lbs_dbg_hex("process_bss: IE info", (u8 *) pcurrentptr,
		bytesleftforcurrentbeacon);
	lbs_deb_scan("process_bss: IE length for this AP = %zd\n", end - pos);
	lbs_dbg_hex("process_bss: IE info", pos, end - pos);

	/* process variable IE */
	while (bytesleftforcurrentbeacon >= 2) {
		elemID = (enum ieeetypes_elementid) (*((u8 *) pcurrentptr));
		elemlen = *((u8 *) pcurrentptr + 1);
	while (pos <= end - 2) {
		struct ieee80211_info_element * elem =
			(struct ieee80211_info_element *) pos;

		if (bytesleftforcurrentbeacon < elemlen) {
		if (pos + elem->len > end) {
			lbs_deb_scan("process_bss: error in processing IE, "
			       "bytes left < IE length\n");
			bytesleftforcurrentbeacon = 0;
			continue;
			break;
		}

		switch (elemID) {
		case SSID:
			bss->ssid_len = elemlen;
			memcpy(bss->ssid, (pcurrentptr + 2), elemlen);
		switch (elem->id) {
		case MFIE_TYPE_SSID:
			bss->ssid_len = elem->len;
			memcpy(bss->ssid, elem->data, elem->len);
			lbs_deb_scan("ssid '%s', ssid length %u\n",
			             escape_essid(bss->ssid, bss->ssid_len),
			             bss->ssid_len);
			break;

		case SUPPORTED_RATES:
			memcpy(bss->datarates, (pcurrentptr + 2), elemlen);
			memmove(bss->libertas_supported_rates, (pcurrentptr + 2),
				elemlen);
			ratesize = elemlen;
		case MFIE_TYPE_RATES:
			memcpy(bss->datarates, elem->data, elem->len);
			memmove(bss->libertas_supported_rates, elem->data,
				elem->len);
			ratesize = elem->len;
			founddatarateie = 1;
			break;

		case EXTRA_IE:
			lbs_deb_scan("process_bss: EXTRA_IE Found!\n");
			break;

		case FH_PARAM_SET:
			pFH = (struct ieeetypes_fhparamset *) pcurrentptr;
		case MFIE_TYPE_FH_SET:
			pFH = (struct ieeetypes_fhparamset *) pos;
			memmove(&bss->phyparamset.fhparamset, pFH,
				sizeof(struct ieeetypes_fhparamset));
#if 0 /* I think we can store these LE */
@@ -1045,21 +1022,21 @@ static int libertas_process_bss(struct bss_descriptor * bss,
#endif
			break;

		case DS_PARAM_SET:
			pDS = (struct ieeetypes_dsparamset *) pcurrentptr;
		case MFIE_TYPE_DS_SET:
			pDS = (struct ieeetypes_dsparamset *) pos;
			bss->channel = pDS->currentchan;
			memcpy(&bss->phyparamset.dsparamset, pDS,
			       sizeof(struct ieeetypes_dsparamset));
			break;

		case CF_PARAM_SET:
			pCF = (struct ieeetypes_cfparamset *) pcurrentptr;
		case MFIE_TYPE_CF_SET:
			pCF = (struct ieeetypes_cfparamset *) pos;
			memcpy(&bss->ssparamset.cfparamset, pCF,
			       sizeof(struct ieeetypes_cfparamset));
			break;

		case IBSS_PARAM_SET:
			pibss = (struct ieeetypes_ibssparamset *) pcurrentptr;
		case MFIE_TYPE_IBSS_SET:
			pibss = (struct ieeetypes_ibssparamset *) pos;
			bss->atimwindow = le32_to_cpu(pibss->atimwindow);
			memmove(&bss->ssparamset.ibssparamset, pibss,
				sizeof(struct ieeetypes_ibssparamset));
@@ -1069,9 +1046,8 @@ static int libertas_process_bss(struct bss_descriptor * bss,
#endif
			break;

			/* Handle Country Info IE */
		case COUNTRY_INFO:
			pcountryinfo = (struct ieeetypes_countryinfoset *) pcurrentptr;
		case MFIE_TYPE_COUNTRY:
			pcountryinfo = (struct ieeetypes_countryinfoset *) pos;
			if (pcountryinfo->len < sizeof(pcountryinfo->countrycode)
			    || pcountryinfo->len > 254) {
				lbs_deb_scan("process_bss: 11D- Err "
@@ -1089,62 +1065,55 @@ static int libertas_process_bss(struct bss_descriptor * bss,
				(u32) (pcountryinfo->len + 2));
			break;

		case EXTENDED_SUPPORTED_RATES:
			/*
			 * only process extended supported rate
			 * if data rate is already found.
			 * data rate IE should come before
		case MFIE_TYPE_RATES_EX:
			/* only process extended supported rate if data rate is
			 * already found. Data rate IE should come before
			 * extended supported rate IE
			 */
			if (founddatarateie) {
				if ((elemlen + ratesize) > WLAN_SUPPORTED_RATES) {
			if (!founddatarateie)
				break;

			if ((elem->len + ratesize) > WLAN_SUPPORTED_RATES) {
				bytestocopy =
				    (WLAN_SUPPORTED_RATES - ratesize);
			} else {
					bytestocopy = elemlen;
				bytestocopy = elem->len;
			}

			pRate = (u8 *) bss->datarates;
			pRate += ratesize;
				memmove(pRate, (pcurrentptr + 2), bytestocopy);
			memmove(pRate, elem->data, bytestocopy);
			pRate = (u8 *) bss->libertas_supported_rates;
			pRate += ratesize;
				memmove(pRate, (pcurrentptr + 2), bytestocopy);
			}
			break;

		case VENDOR_SPECIFIC_221:
#define IE_ID_LEN_FIELDS_BYTES 2
			pIe = (struct IE_WPA *)pcurrentptr;

			if (memcmp(pIe->oui, oui01, sizeof(oui01)))
			memmove(pRate, elem->data, bytestocopy);
			break;

			bss->wpa_ie_len = min(elemlen + IE_ID_LEN_FIELDS_BYTES,
				MAX_WPA_IE_LEN);
			memcpy(bss->wpa_ie, pcurrentptr, bss->wpa_ie_len);
			lbs_dbg_hex("process_bss: WPA IE", bss->wpa_ie, elemlen);
			break;
		case WPA2_IE:
			pIe = (struct IE_WPA *)pcurrentptr;
			bss->rsn_ie_len = min(elemlen + IE_ID_LEN_FIELDS_BYTES,
		case MFIE_TYPE_GENERIC:
			if (elem->len >= 4 &&
			    elem->data[0] == 0x00 &&
			    elem->data[1] == 0x50 &&
			    elem->data[2] == 0xf2 &&
			    elem->data[3] == 0x01) {
				bss->wpa_ie_len = min(elem->len + 2,
				                      MAX_WPA_IE_LEN);
			memcpy(bss->rsn_ie, pcurrentptr, bss->rsn_ie_len);
			lbs_dbg_hex("process_bss: RSN_IE", bss->rsn_ie, elemlen);
				memcpy(bss->wpa_ie, elem, bss->wpa_ie_len);
				lbs_dbg_hex("process_bss: WPA IE", bss->wpa_ie,
				            elem->len);
			}
			break;
		case TIM:

		case MFIE_TYPE_RSN:
			bss->rsn_ie_len = min(elem->len + 2, MAX_WPA_IE_LEN);
			memcpy(bss->rsn_ie, elem, bss->rsn_ie_len);
			lbs_dbg_hex("process_bss: RSN_IE", bss->rsn_ie, elem->len);
			break;

		case CHALLENGE_TEXT:
		default:
			break;
		}

		pcurrentptr += elemlen + 2;

		/* need to account for IE ID and IE len */
		bytesleftforcurrentbeacon -= (elemlen + 2);

	}			/* while (bytesleftforcurrentbeacon > 2) */
		pos += elem->len + 2;
	}

	/* Timestamp */
	bss->last_scanned = jiffies;
+0 −23
Original line number Diff line number Diff line
@@ -7,29 +7,6 @@
#include <linux/if_ether.h>
#include <asm/byteorder.h>

/** IEEE type definitions  */
enum ieeetypes_elementid {
	SSID = 0,
	SUPPORTED_RATES,
	FH_PARAM_SET,
	DS_PARAM_SET,
	CF_PARAM_SET,
	TIM,
	IBSS_PARAM_SET,
	COUNTRY_INFO = 7,

	CHALLENGE_TEXT = 16,

	EXTENDED_SUPPORTED_RATES = 50,

	VENDOR_SPECIFIC_221 = 221,

	WPA_IE = 221,
	WPA2_IE = 48,

	EXTRA_IE = 133,
} __attribute__ ((packed));

#define CAPINFO_MASK	(~(0x00da))

struct ieeetypes_cfparamset {