mirror of https://gitee.com/openkylin/linux.git
[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: Dan Williams <dcbw@redhat.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
2950cd2630
commit
ab6179711a
|
@ -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;
|
||||
}
|
||||
|
||||
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 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 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);
|
||||
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);
|
||||
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 {
|
||||
|
|
Loading…
Reference in New Issue