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 { ...@@ -91,25 +91,12 @@ struct enc_key {
u8 key[32]; u8 key[32];
}; };
struct IE_WPA {
u8 elementid;
u8 len;
u8 oui[4];
__le16 version;
};
/* wlan_offset_value */ /* wlan_offset_value */
struct wlan_offset_value { struct wlan_offset_value {
u32 offset; u32 offset;
u32 value; u32 value;
}; };
struct WLAN_802_11_VARIABLE_IEs {
u8 elementid;
u8 length;
u8 data[1];
};
/* Define general data structure */ /* Define general data structure */
/* cmd_DS_GEN */ /* cmd_DS_GEN */
struct cmd_ds_gen { struct cmd_ds_gen {
......
...@@ -74,8 +74,8 @@ static inline int match_bss_no_security(struct wlan_802_11_security * secinfo, ...@@ -74,8 +74,8 @@ static inline int match_bss_no_security(struct wlan_802_11_security * secinfo,
if ( !secinfo->wep_enabled if ( !secinfo->wep_enabled
&& !secinfo->WPAenabled && !secinfo->WPAenabled
&& !secinfo->WPA2enabled && !secinfo->WPA2enabled
&& match_bss->wpa_ie[0] != WPA_IE && match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC
&& match_bss->rsn_ie[0] != WPA2_IE && match_bss->rsn_ie[0] != MFIE_TYPE_RSN
&& !(match_bss->capability & WLAN_CAPABILITY_PRIVACY)) { && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {
return 1; return 1;
} }
...@@ -99,7 +99,7 @@ static inline int match_bss_wpa(struct wlan_802_11_security * secinfo, ...@@ -99,7 +99,7 @@ static inline int match_bss_wpa(struct wlan_802_11_security * secinfo,
{ {
if ( !secinfo->wep_enabled if ( !secinfo->wep_enabled
&& secinfo->WPAenabled && 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 /* privacy bit may NOT be set in some APs like LinkSys WRT54G
&& (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) { && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {
*/ */
...@@ -114,7 +114,7 @@ static inline int match_bss_wpa2(struct wlan_802_11_security * secinfo, ...@@ -114,7 +114,7 @@ static inline int match_bss_wpa2(struct wlan_802_11_security * secinfo,
{ {
if ( !secinfo->wep_enabled if ( !secinfo->wep_enabled
&& secinfo->WPA2enabled && 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 /* privacy bit may NOT be set in some APs like LinkSys WRT54G
&& (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) { && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {
*/ */
...@@ -130,8 +130,8 @@ static inline int match_bss_dynamic_wep(struct wlan_802_11_security * secinfo, ...@@ -130,8 +130,8 @@ static inline int match_bss_dynamic_wep(struct wlan_802_11_security * secinfo,
if ( !secinfo->wep_enabled if ( !secinfo->wep_enabled
&& !secinfo->WPAenabled && !secinfo->WPAenabled
&& !secinfo->WPA2enabled && !secinfo->WPA2enabled
&& (match_bss->wpa_ie[0] != WPA_IE) && (match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC)
&& (match_bss->rsn_ie[0] != WPA2_IE) && (match_bss->rsn_ie[0] != MFIE_TYPE_RSN)
&& (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) { && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {
return 1; return 1;
} }
...@@ -900,24 +900,18 @@ void wlan_ret_802_11_scan_get_tlv_ptrs(struct mrvlietypes_data * ptlv, ...@@ -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, static int libertas_process_bss(struct bss_descriptor * bss,
u8 ** pbeaconinfo, int *bytesleft) u8 ** pbeaconinfo, int *bytesleft)
{ {
enum ieeetypes_elementid elemID;
struct ieeetypes_fhparamset *pFH; struct ieeetypes_fhparamset *pFH;
struct ieeetypes_dsparamset *pDS; struct ieeetypes_dsparamset *pDS;
struct ieeetypes_cfparamset *pCF; struct ieeetypes_cfparamset *pCF;
struct ieeetypes_ibssparamset *pibss; struct ieeetypes_ibssparamset *pibss;
u8 *pcurrentptr; u8 *pos, *end;
u8 *pRate; u8 *pRate;
u8 elemlen;
u8 bytestocopy; u8 bytestocopy;
u8 ratesize; u8 ratesize;
u16 beaconsize; u16 beaconsize;
u8 founddatarateie; u8 founddatarateie;
int bytesleftforcurrentbeacon;
int ret; int ret;
struct IE_WPA *pIe;
const u8 oui01[4] = { 0x00, 0x50, 0xf2, 0x01 };
struct ieeetypes_countryinfoset *pcountryinfo; struct ieeetypes_countryinfoset *pcountryinfo;
lbs_deb_enter(LBS_DEB_ASSOC); lbs_deb_enter(LBS_DEB_ASSOC);
...@@ -934,29 +928,24 @@ static int libertas_process_bss(struct bss_descriptor * bss, ...@@ -934,29 +928,24 @@ static int libertas_process_bss(struct bss_descriptor * bss,
} }
if (beaconsize == 0 || beaconsize > *bytesleft) { if (beaconsize == 0 || beaconsize > *bytesleft) {
*pbeaconinfo += *bytesleft; *pbeaconinfo += *bytesleft;
*bytesleft = 0; *bytesleft = 0;
return -1; return -1;
} }
/* Initialize the current working beacon pointer for this BSS iteration */ /* 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 */ /* Advance the return beacon pointer past the current beacon */
*pbeaconinfo += beaconsize; *pbeaconinfo += beaconsize;
*bytesleft -= beaconsize; *bytesleft -= beaconsize;
bytesleftforcurrentbeacon = beaconsize; memcpy(bss->bssid, pos, ETH_ALEN);
memcpy(bss->bssid, pcurrentptr, ETH_ALEN);
lbs_deb_scan("process_bss: AP BSSID " MAC_FMT "\n", MAC_ARG(bss->bssid)); lbs_deb_scan("process_bss: AP BSSID " MAC_FMT "\n", MAC_ARG(bss->bssid));
pos += ETH_ALEN;
pcurrentptr += ETH_ALEN; if ((end - pos) < 12) {
bytesleftforcurrentbeacon -= ETH_ALEN;
if (bytesleftforcurrentbeacon < 12) {
lbs_deb_scan("process_bss: Not enough bytes left\n"); lbs_deb_scan("process_bss: Not enough bytes left\n");
return -1; return -1;
} }
...@@ -967,26 +956,22 @@ static int libertas_process_bss(struct bss_descriptor * bss, ...@@ -967,26 +956,22 @@ static int libertas_process_bss(struct bss_descriptor * bss,
*/ */
/* RSSI is 1 byte long */ /* RSSI is 1 byte long */
bss->rssi = *pcurrentptr; bss->rssi = *pos;
lbs_deb_scan("process_bss: RSSI=%02X\n", *pcurrentptr); lbs_deb_scan("process_bss: RSSI=%02X\n", *pos);
pcurrentptr += 1; pos++;
bytesleftforcurrentbeacon -= 1;
/* time stamp is 8 bytes long */ /* time stamp is 8 bytes long */
bss->timestamp = le64_to_cpup((void *)pcurrentptr); bss->timestamp = le64_to_cpup((void *) pos);
pcurrentptr += 8; pos += 8;
bytesleftforcurrentbeacon -= 8;
/* beacon interval is 2 bytes long */ /* beacon interval is 2 bytes long */
bss->beaconperiod = le16_to_cpup((void *)pcurrentptr); bss->beaconperiod = le16_to_cpup((void *) pos);
pcurrentptr += 2; pos += 2;
bytesleftforcurrentbeacon -= 2;
/* capability information is 2 bytes long */ /* 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); lbs_deb_scan("process_bss: capabilities = 0x%4X\n", bss->capability);
pcurrentptr += 2; pos += 2;
bytesleftforcurrentbeacon -= 2;
if (bss->capability & WLAN_CAPABILITY_PRIVACY) if (bss->capability & WLAN_CAPABILITY_PRIVACY)
lbs_deb_scan("process_bss: AP WEP enabled\n"); lbs_deb_scan("process_bss: AP WEP enabled\n");
...@@ -996,47 +981,39 @@ static int libertas_process_bss(struct bss_descriptor * bss, ...@@ -996,47 +981,39 @@ static int libertas_process_bss(struct bss_descriptor * bss,
bss->mode = IW_MODE_INFRA; bss->mode = IW_MODE_INFRA;
/* rest of the current buffer are IE's */ /* rest of the current buffer are IE's */
lbs_deb_scan("process_bss: IE length for this AP = %d\n", lbs_deb_scan("process_bss: IE length for this AP = %zd\n", end - pos);
bytesleftforcurrentbeacon); lbs_dbg_hex("process_bss: IE info", pos, end - pos);
lbs_dbg_hex("process_bss: IE info", (u8 *) pcurrentptr,
bytesleftforcurrentbeacon);
/* process variable IE */ /* process variable IE */
while (bytesleftforcurrentbeacon >= 2) { while (pos <= end - 2) {
elemID = (enum ieeetypes_elementid) (*((u8 *) pcurrentptr)); struct ieee80211_info_element * elem =
elemlen = *((u8 *) pcurrentptr + 1); (struct ieee80211_info_element *) pos;
if (bytesleftforcurrentbeacon < elemlen) { if (pos + elem->len > end) {
lbs_deb_scan("process_bss: error in processing IE, " lbs_deb_scan("process_bss: error in processing IE, "
"bytes left < IE length\n"); "bytes left < IE length\n");
bytesleftforcurrentbeacon = 0; break;
continue;
} }
switch (elemID) { switch (elem->id) {
case SSID: case MFIE_TYPE_SSID:
bss->ssid_len = elemlen; bss->ssid_len = elem->len;
memcpy(bss->ssid, (pcurrentptr + 2), elemlen); memcpy(bss->ssid, elem->data, elem->len);
lbs_deb_scan("ssid '%s', ssid length %u\n", lbs_deb_scan("ssid '%s', ssid length %u\n",
escape_essid(bss->ssid, bss->ssid_len), escape_essid(bss->ssid, bss->ssid_len),
bss->ssid_len); bss->ssid_len);
break; break;
case SUPPORTED_RATES: case MFIE_TYPE_RATES:
memcpy(bss->datarates, (pcurrentptr + 2), elemlen); memcpy(bss->datarates, elem->data, elem->len);
memmove(bss->libertas_supported_rates, (pcurrentptr + 2), memmove(bss->libertas_supported_rates, elem->data,
elemlen); elem->len);
ratesize = elemlen; ratesize = elem->len;
founddatarateie = 1; founddatarateie = 1;
break; break;
case EXTRA_IE: case MFIE_TYPE_FH_SET:
lbs_deb_scan("process_bss: EXTRA_IE Found!\n"); pFH = (struct ieeetypes_fhparamset *) pos;
break;
case FH_PARAM_SET:
pFH = (struct ieeetypes_fhparamset *) pcurrentptr;
memmove(&bss->phyparamset.fhparamset, pFH, memmove(&bss->phyparamset.fhparamset, pFH,
sizeof(struct ieeetypes_fhparamset)); sizeof(struct ieeetypes_fhparamset));
#if 0 /* I think we can store these LE */ #if 0 /* I think we can store these LE */
...@@ -1045,21 +1022,21 @@ static int libertas_process_bss(struct bss_descriptor * bss, ...@@ -1045,21 +1022,21 @@ static int libertas_process_bss(struct bss_descriptor * bss,
#endif #endif
break; break;
case DS_PARAM_SET: case MFIE_TYPE_DS_SET:
pDS = (struct ieeetypes_dsparamset *) pcurrentptr; pDS = (struct ieeetypes_dsparamset *) pos;
bss->channel = pDS->currentchan; bss->channel = pDS->currentchan;
memcpy(&bss->phyparamset.dsparamset, pDS, memcpy(&bss->phyparamset.dsparamset, pDS,
sizeof(struct ieeetypes_dsparamset)); sizeof(struct ieeetypes_dsparamset));
break; break;
case CF_PARAM_SET: case MFIE_TYPE_CF_SET:
pCF = (struct ieeetypes_cfparamset *) pcurrentptr; pCF = (struct ieeetypes_cfparamset *) pos;
memcpy(&bss->ssparamset.cfparamset, pCF, memcpy(&bss->ssparamset.cfparamset, pCF,
sizeof(struct ieeetypes_cfparamset)); sizeof(struct ieeetypes_cfparamset));
break; break;
case IBSS_PARAM_SET: case MFIE_TYPE_IBSS_SET:
pibss = (struct ieeetypes_ibssparamset *) pcurrentptr; pibss = (struct ieeetypes_ibssparamset *) pos;
bss->atimwindow = le32_to_cpu(pibss->atimwindow); bss->atimwindow = le32_to_cpu(pibss->atimwindow);
memmove(&bss->ssparamset.ibssparamset, pibss, memmove(&bss->ssparamset.ibssparamset, pibss,
sizeof(struct ieeetypes_ibssparamset)); sizeof(struct ieeetypes_ibssparamset));
...@@ -1069,9 +1046,8 @@ static int libertas_process_bss(struct bss_descriptor * bss, ...@@ -1069,9 +1046,8 @@ static int libertas_process_bss(struct bss_descriptor * bss,
#endif #endif
break; break;
/* Handle Country Info IE */ case MFIE_TYPE_COUNTRY:
case COUNTRY_INFO: pcountryinfo = (struct ieeetypes_countryinfoset *) pos;
pcountryinfo = (struct ieeetypes_countryinfoset *) pcurrentptr;
if (pcountryinfo->len < sizeof(pcountryinfo->countrycode) if (pcountryinfo->len < sizeof(pcountryinfo->countrycode)
|| pcountryinfo->len > 254) { || pcountryinfo->len > 254) {
lbs_deb_scan("process_bss: 11D- Err " lbs_deb_scan("process_bss: 11D- Err "
...@@ -1089,62 +1065,55 @@ static int libertas_process_bss(struct bss_descriptor * bss, ...@@ -1089,62 +1065,55 @@ static int libertas_process_bss(struct bss_descriptor * bss,
(u32) (pcountryinfo->len + 2)); (u32) (pcountryinfo->len + 2));
break; break;
case EXTENDED_SUPPORTED_RATES: case MFIE_TYPE_RATES_EX:
/* /* only process extended supported rate if data rate is
* only process extended supported rate * already found. Data rate IE should come before
* if data rate is already found.
* data rate IE should come before
* extended supported rate IE * extended supported rate IE
*/ */
if (founddatarateie) { if (!founddatarateie)
if ((elemlen + ratesize) > WLAN_SUPPORTED_RATES) { break;
bytestocopy =
(WLAN_SUPPORTED_RATES - ratesize);
} else {
bytestocopy = elemlen;
}
pRate = (u8 *) bss->datarates; if ((elem->len + ratesize) > WLAN_SUPPORTED_RATES) {
pRate += ratesize; bytestocopy =
memmove(pRate, (pcurrentptr + 2), bytestocopy); (WLAN_SUPPORTED_RATES - ratesize);
pRate = (u8 *) bss->libertas_supported_rates; } else {
pRate += ratesize; bytestocopy = elem->len;
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))) pRate = (u8 *) bss->datarates;
break; pRate += ratesize;
memmove(pRate, elem->data, bytestocopy);
bss->wpa_ie_len = min(elemlen + IE_ID_LEN_FIELDS_BYTES, pRate = (u8 *) bss->libertas_supported_rates;
MAX_WPA_IE_LEN); pRate += ratesize;
memcpy(bss->wpa_ie, pcurrentptr, bss->wpa_ie_len); memmove(pRate, elem->data, bytestocopy);
lbs_dbg_hex("process_bss: WPA IE", bss->wpa_ie, elemlen);
break; break;
case WPA2_IE:
pIe = (struct IE_WPA *)pcurrentptr; case MFIE_TYPE_GENERIC:
bss->rsn_ie_len = min(elemlen + IE_ID_LEN_FIELDS_BYTES, if (elem->len >= 4 &&
MAX_WPA_IE_LEN); elem->data[0] == 0x00 &&
memcpy(bss->rsn_ie, pcurrentptr, bss->rsn_ie_len); elem->data[1] == 0x50 &&
lbs_dbg_hex("process_bss: RSN_IE", bss->rsn_ie, elemlen); 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; 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; break;
case CHALLENGE_TEXT: default:
break; break;
} }
pcurrentptr += elemlen + 2; pos += elem->len + 2;
}
/* need to account for IE ID and IE len */
bytesleftforcurrentbeacon -= (elemlen + 2);
} /* while (bytesleftforcurrentbeacon > 2) */
/* Timestamp */ /* Timestamp */
bss->last_scanned = jiffies; bss->last_scanned = jiffies;
......
...@@ -7,29 +7,6 @@ ...@@ -7,29 +7,6 @@
#include <linux/if_ether.h> #include <linux/if_ether.h>
#include <asm/byteorder.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)) #define CAPINFO_MASK (~(0x00da))
struct ieeetypes_cfparamset { 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