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

[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
......@@ -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 {
......
......@@ -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) {
bytestocopy =
(WLAN_SUPPORTED_RATES - ratesize);
} else {
bytestocopy = elemlen;
}
if (!founddatarateie)
break;
pRate = (u8 *) bss->datarates;
pRate += ratesize;
memmove(pRate, (pcurrentptr + 2), bytestocopy);
pRate = (u8 *) bss->libertas_supported_rates;
pRate += ratesize;
memmove(pRate, (pcurrentptr + 2), bytestocopy);
if ((elem->len + ratesize) > WLAN_SUPPORTED_RATES) {
bytestocopy =
(WLAN_SUPPORTED_RATES - ratesize);
} else {
bytestocopy = elem->len;
}
break;
case VENDOR_SPECIFIC_221:
#define IE_ID_LEN_FIELDS_BYTES 2
pIe = (struct IE_WPA *)pcurrentptr;
if (memcmp(pIe->oui, oui01, sizeof(oui01)))
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);
pRate = (u8 *) bss->datarates;
pRate += ratesize;
memmove(pRate, elem->data, bytestocopy);
pRate = (u8 *) bss->libertas_supported_rates;
pRate += ratesize;
memmove(pRate, elem->data, bytestocopy);
break;
case WPA2_IE:
pIe = (struct IE_WPA *)pcurrentptr;
bss->rsn_ie_len = min(elemlen + IE_ID_LEN_FIELDS_BYTES,
MAX_WPA_IE_LEN);
memcpy(bss->rsn_ie, pcurrentptr, bss->rsn_ie_len);
lbs_dbg_hex("process_bss: RSN_IE", bss->rsn_ie, elemlen);
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->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;
......
......@@ -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 {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment