aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2007-08-02 10:48:02 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:49:39 -0400
commitab6179711a5e46ed1db739bef7752d65ce836dce (patch)
treee1d026661ceb7736a516bcd4eb2eb50f917e9d5c
parent2950cd26308ced650cf7cc3199eae3eb27f9917f (diff)
[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>
-rw-r--r--drivers/net/wireless/libertas/hostcmd.h13
-rw-r--r--drivers/net/wireless/libertas/scan.c199
-rw-r--r--drivers/net/wireless/libertas/types.h23
3 files changed, 84 insertions, 151 deletions
diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h
index 01a97d0fa98a..05ea54df71bd 100644
--- a/drivers/net/wireless/libertas/hostcmd.h
+++ b/drivers/net/wireless/libertas/hostcmd.h
@@ -91,25 +91,12 @@ struct enc_key {
91 u8 key[32]; 91 u8 key[32];
92}; 92};
93 93
94struct IE_WPA {
95 u8 elementid;
96 u8 len;
97 u8 oui[4];
98 __le16 version;
99};
100
101/* wlan_offset_value */ 94/* wlan_offset_value */
102struct wlan_offset_value { 95struct wlan_offset_value {
103 u32 offset; 96 u32 offset;
104 u32 value; 97 u32 value;
105}; 98};
106 99
107struct WLAN_802_11_VARIABLE_IEs {
108 u8 elementid;
109 u8 length;
110 u8 data[1];
111};
112
113/* Define general data structure */ 100/* Define general data structure */
114/* cmd_DS_GEN */ 101/* cmd_DS_GEN */
115struct cmd_ds_gen { 102struct cmd_ds_gen {
diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c
index 8753f9344f3e..2d6bc7811b27 100644
--- a/drivers/net/wireless/libertas/scan.c
+++ b/drivers/net/wireless/libertas/scan.c
@@ -74,8 +74,8 @@ static inline int match_bss_no_security(struct wlan_802_11_security * secinfo,
74 if ( !secinfo->wep_enabled 74 if ( !secinfo->wep_enabled
75 && !secinfo->WPAenabled 75 && !secinfo->WPAenabled
76 && !secinfo->WPA2enabled 76 && !secinfo->WPA2enabled
77 && match_bss->wpa_ie[0] != WPA_IE 77 && match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC
78 && match_bss->rsn_ie[0] != WPA2_IE 78 && match_bss->rsn_ie[0] != MFIE_TYPE_RSN
79 && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY)) { 79 && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {
80 return 1; 80 return 1;
81 } 81 }
@@ -99,7 +99,7 @@ static inline int match_bss_wpa(struct wlan_802_11_security * secinfo,
99{ 99{
100 if ( !secinfo->wep_enabled 100 if ( !secinfo->wep_enabled
101 && secinfo->WPAenabled 101 && secinfo->WPAenabled
102 && (match_bss->wpa_ie[0] == WPA_IE) 102 && (match_bss->wpa_ie[0] == MFIE_TYPE_GENERIC)
103 /* privacy bit may NOT be set in some APs like LinkSys WRT54G 103 /* privacy bit may NOT be set in some APs like LinkSys WRT54G
104 && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) { 104 && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {
105 */ 105 */
@@ -114,7 +114,7 @@ static inline int match_bss_wpa2(struct wlan_802_11_security * secinfo,
114{ 114{
115 if ( !secinfo->wep_enabled 115 if ( !secinfo->wep_enabled
116 && secinfo->WPA2enabled 116 && secinfo->WPA2enabled
117 && (match_bss->rsn_ie[0] == WPA2_IE) 117 && (match_bss->rsn_ie[0] == MFIE_TYPE_RSN)
118 /* privacy bit may NOT be set in some APs like LinkSys WRT54G 118 /* privacy bit may NOT be set in some APs like LinkSys WRT54G
119 && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) { 119 && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {
120 */ 120 */
@@ -130,8 +130,8 @@ static inline int match_bss_dynamic_wep(struct wlan_802_11_security * secinfo,
130 if ( !secinfo->wep_enabled 130 if ( !secinfo->wep_enabled
131 && !secinfo->WPAenabled 131 && !secinfo->WPAenabled
132 && !secinfo->WPA2enabled 132 && !secinfo->WPA2enabled
133 && (match_bss->wpa_ie[0] != WPA_IE) 133 && (match_bss->wpa_ie[0] != MFIE_TYPE_GENERIC)
134 && (match_bss->rsn_ie[0] != WPA2_IE) 134 && (match_bss->rsn_ie[0] != MFIE_TYPE_RSN)
135 && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) { 135 && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) {
136 return 1; 136 return 1;
137 } 137 }
@@ -900,24 +900,18 @@ void wlan_ret_802_11_scan_get_tlv_ptrs(struct mrvlietypes_data * ptlv,
900static int libertas_process_bss(struct bss_descriptor * bss, 900static int libertas_process_bss(struct bss_descriptor * bss,
901 u8 ** pbeaconinfo, int *bytesleft) 901 u8 ** pbeaconinfo, int *bytesleft)
902{ 902{
903 enum ieeetypes_elementid elemID;
904 struct ieeetypes_fhparamset *pFH; 903 struct ieeetypes_fhparamset *pFH;
905 struct ieeetypes_dsparamset *pDS; 904 struct ieeetypes_dsparamset *pDS;
906 struct ieeetypes_cfparamset *pCF; 905 struct ieeetypes_cfparamset *pCF;
907 struct ieeetypes_ibssparamset *pibss; 906 struct ieeetypes_ibssparamset *pibss;
908 u8 *pcurrentptr; 907 u8 *pos, *end;
909 u8 *pRate; 908 u8 *pRate;
910 u8 elemlen;
911 u8 bytestocopy; 909 u8 bytestocopy;
912 u8 ratesize; 910 u8 ratesize;
913 u16 beaconsize; 911 u16 beaconsize;
914 u8 founddatarateie; 912 u8 founddatarateie;
915 int bytesleftforcurrentbeacon;
916 int ret; 913 int ret;
917 914
918 struct IE_WPA *pIe;
919 const u8 oui01[4] = { 0x00, 0x50, 0xf2, 0x01 };
920
921 struct ieeetypes_countryinfoset *pcountryinfo; 915 struct ieeetypes_countryinfoset *pcountryinfo;
922 916
923 lbs_deb_enter(LBS_DEB_ASSOC); 917 lbs_deb_enter(LBS_DEB_ASSOC);
@@ -934,29 +928,24 @@ static int libertas_process_bss(struct bss_descriptor * bss,
934 } 928 }
935 929
936 if (beaconsize == 0 || beaconsize > *bytesleft) { 930 if (beaconsize == 0 || beaconsize > *bytesleft) {
937
938 *pbeaconinfo += *bytesleft; 931 *pbeaconinfo += *bytesleft;
939 *bytesleft = 0; 932 *bytesleft = 0;
940
941 return -1; 933 return -1;
942 } 934 }
943 935
944 /* Initialize the current working beacon pointer for this BSS iteration */ 936 /* Initialize the current working beacon pointer for this BSS iteration */
945 pcurrentptr = *pbeaconinfo; 937 pos = *pbeaconinfo;
938 end = pos + beaconsize;
946 939
947 /* Advance the return beacon pointer past the current beacon */ 940 /* Advance the return beacon pointer past the current beacon */
948 *pbeaconinfo += beaconsize; 941 *pbeaconinfo += beaconsize;
949 *bytesleft -= beaconsize; 942 *bytesleft -= beaconsize;
950 943
951 bytesleftforcurrentbeacon = beaconsize; 944 memcpy(bss->bssid, pos, ETH_ALEN);
952
953 memcpy(bss->bssid, pcurrentptr, ETH_ALEN);
954 lbs_deb_scan("process_bss: AP BSSID " MAC_FMT "\n", MAC_ARG(bss->bssid)); 945 lbs_deb_scan("process_bss: AP BSSID " MAC_FMT "\n", MAC_ARG(bss->bssid));
946 pos += ETH_ALEN;
955 947
956 pcurrentptr += ETH_ALEN; 948 if ((end - pos) < 12) {
957 bytesleftforcurrentbeacon -= ETH_ALEN;
958
959 if (bytesleftforcurrentbeacon < 12) {
960 lbs_deb_scan("process_bss: Not enough bytes left\n"); 949 lbs_deb_scan("process_bss: Not enough bytes left\n");
961 return -1; 950 return -1;
962 } 951 }
@@ -967,26 +956,22 @@ static int libertas_process_bss(struct bss_descriptor * bss,
967 */ 956 */
968 957
969 /* RSSI is 1 byte long */ 958 /* RSSI is 1 byte long */
970 bss->rssi = *pcurrentptr; 959 bss->rssi = *pos;
971 lbs_deb_scan("process_bss: RSSI=%02X\n", *pcurrentptr); 960 lbs_deb_scan("process_bss: RSSI=%02X\n", *pos);
972 pcurrentptr += 1; 961 pos++;
973 bytesleftforcurrentbeacon -= 1;
974 962
975 /* time stamp is 8 bytes long */ 963 /* time stamp is 8 bytes long */
976 bss->timestamp = le64_to_cpup((void *)pcurrentptr); 964 bss->timestamp = le64_to_cpup((void *) pos);
977 pcurrentptr += 8; 965 pos += 8;
978 bytesleftforcurrentbeacon -= 8;
979 966
980 /* beacon interval is 2 bytes long */ 967 /* beacon interval is 2 bytes long */
981 bss->beaconperiod = le16_to_cpup((void *)pcurrentptr); 968 bss->beaconperiod = le16_to_cpup((void *) pos);
982 pcurrentptr += 2; 969 pos += 2;
983 bytesleftforcurrentbeacon -= 2;
984 970
985 /* capability information is 2 bytes long */ 971 /* capability information is 2 bytes long */
986 bss->capability = le16_to_cpup((void *)pcurrentptr); 972 bss->capability = le16_to_cpup((void *) pos);
987 lbs_deb_scan("process_bss: capabilities = 0x%4X\n", bss->capability); 973 lbs_deb_scan("process_bss: capabilities = 0x%4X\n", bss->capability);
988 pcurrentptr += 2; 974 pos += 2;
989 bytesleftforcurrentbeacon -= 2;
990 975
991 if (bss->capability & WLAN_CAPABILITY_PRIVACY) 976 if (bss->capability & WLAN_CAPABILITY_PRIVACY)
992 lbs_deb_scan("process_bss: AP WEP enabled\n"); 977 lbs_deb_scan("process_bss: AP WEP enabled\n");
@@ -996,47 +981,39 @@ static int libertas_process_bss(struct bss_descriptor * bss,
996 bss->mode = IW_MODE_INFRA; 981 bss->mode = IW_MODE_INFRA;
997 982
998 /* rest of the current buffer are IE's */ 983 /* rest of the current buffer are IE's */
999 lbs_deb_scan("process_bss: IE length for this AP = %d\n", 984 lbs_deb_scan("process_bss: IE length for this AP = %zd\n", end - pos);
1000 bytesleftforcurrentbeacon); 985 lbs_dbg_hex("process_bss: IE info", pos, end - pos);
1001
1002 lbs_dbg_hex("process_bss: IE info", (u8 *) pcurrentptr,
1003 bytesleftforcurrentbeacon);
1004 986
1005 /* process variable IE */ 987 /* process variable IE */
1006 while (bytesleftforcurrentbeacon >= 2) { 988 while (pos <= end - 2) {
1007 elemID = (enum ieeetypes_elementid) (*((u8 *) pcurrentptr)); 989 struct ieee80211_info_element * elem =
1008 elemlen = *((u8 *) pcurrentptr + 1); 990 (struct ieee80211_info_element *) pos;
1009 991
1010 if (bytesleftforcurrentbeacon < elemlen) { 992 if (pos + elem->len > end) {
1011 lbs_deb_scan("process_bss: error in processing IE, " 993 lbs_deb_scan("process_bss: error in processing IE, "
1012 "bytes left < IE length\n"); 994 "bytes left < IE length\n");
1013 bytesleftforcurrentbeacon = 0; 995 break;
1014 continue;
1015 } 996 }
1016 997
1017 switch (elemID) { 998 switch (elem->id) {
1018 case SSID: 999 case MFIE_TYPE_SSID:
1019 bss->ssid_len = elemlen; 1000 bss->ssid_len = elem->len;
1020 memcpy(bss->ssid, (pcurrentptr + 2), elemlen); 1001 memcpy(bss->ssid, elem->data, elem->len);
1021 lbs_deb_scan("ssid '%s', ssid length %u\n", 1002 lbs_deb_scan("ssid '%s', ssid length %u\n",
1022 escape_essid(bss->ssid, bss->ssid_len), 1003 escape_essid(bss->ssid, bss->ssid_len),
1023 bss->ssid_len); 1004 bss->ssid_len);
1024 break; 1005 break;
1025 1006
1026 case SUPPORTED_RATES: 1007 case MFIE_TYPE_RATES:
1027 memcpy(bss->datarates, (pcurrentptr + 2), elemlen); 1008 memcpy(bss->datarates, elem->data, elem->len);
1028 memmove(bss->libertas_supported_rates, (pcurrentptr + 2), 1009 memmove(bss->libertas_supported_rates, elem->data,
1029 elemlen); 1010 elem->len);
1030 ratesize = elemlen; 1011 ratesize = elem->len;
1031 founddatarateie = 1; 1012 founddatarateie = 1;
1032 break; 1013 break;
1033 1014
1034 case EXTRA_IE: 1015 case MFIE_TYPE_FH_SET:
1035 lbs_deb_scan("process_bss: EXTRA_IE Found!\n"); 1016 pFH = (struct ieeetypes_fhparamset *) pos;
1036 break;
1037
1038 case FH_PARAM_SET:
1039 pFH = (struct ieeetypes_fhparamset *) pcurrentptr;
1040 memmove(&bss->phyparamset.fhparamset, pFH, 1017 memmove(&bss->phyparamset.fhparamset, pFH,
1041 sizeof(struct ieeetypes_fhparamset)); 1018 sizeof(struct ieeetypes_fhparamset));
1042#if 0 /* I think we can store these LE */ 1019#if 0 /* I think we can store these LE */
@@ -1045,21 +1022,21 @@ static int libertas_process_bss(struct bss_descriptor * bss,
1045#endif 1022#endif
1046 break; 1023 break;
1047 1024
1048 case DS_PARAM_SET: 1025 case MFIE_TYPE_DS_SET:
1049 pDS = (struct ieeetypes_dsparamset *) pcurrentptr; 1026 pDS = (struct ieeetypes_dsparamset *) pos;
1050 bss->channel = pDS->currentchan; 1027 bss->channel = pDS->currentchan;
1051 memcpy(&bss->phyparamset.dsparamset, pDS, 1028 memcpy(&bss->phyparamset.dsparamset, pDS,
1052 sizeof(struct ieeetypes_dsparamset)); 1029 sizeof(struct ieeetypes_dsparamset));
1053 break; 1030 break;
1054 1031
1055 case CF_PARAM_SET: 1032 case MFIE_TYPE_CF_SET:
1056 pCF = (struct ieeetypes_cfparamset *) pcurrentptr; 1033 pCF = (struct ieeetypes_cfparamset *) pos;
1057 memcpy(&bss->ssparamset.cfparamset, pCF, 1034 memcpy(&bss->ssparamset.cfparamset, pCF,
1058 sizeof(struct ieeetypes_cfparamset)); 1035 sizeof(struct ieeetypes_cfparamset));
1059 break; 1036 break;
1060 1037
1061 case IBSS_PARAM_SET: 1038 case MFIE_TYPE_IBSS_SET:
1062 pibss = (struct ieeetypes_ibssparamset *) pcurrentptr; 1039 pibss = (struct ieeetypes_ibssparamset *) pos;
1063 bss->atimwindow = le32_to_cpu(pibss->atimwindow); 1040 bss->atimwindow = le32_to_cpu(pibss->atimwindow);
1064 memmove(&bss->ssparamset.ibssparamset, pibss, 1041 memmove(&bss->ssparamset.ibssparamset, pibss,
1065 sizeof(struct ieeetypes_ibssparamset)); 1042 sizeof(struct ieeetypes_ibssparamset));
@@ -1069,9 +1046,8 @@ static int libertas_process_bss(struct bss_descriptor * bss,
1069#endif 1046#endif
1070 break; 1047 break;
1071 1048
1072 /* Handle Country Info IE */ 1049 case MFIE_TYPE_COUNTRY:
1073 case COUNTRY_INFO: 1050 pcountryinfo = (struct ieeetypes_countryinfoset *) pos;
1074 pcountryinfo = (struct ieeetypes_countryinfoset *) pcurrentptr;
1075 if (pcountryinfo->len < sizeof(pcountryinfo->countrycode) 1051 if (pcountryinfo->len < sizeof(pcountryinfo->countrycode)
1076 || pcountryinfo->len > 254) { 1052 || pcountryinfo->len > 254) {
1077 lbs_deb_scan("process_bss: 11D- Err " 1053 lbs_deb_scan("process_bss: 11D- Err "
@@ -1089,62 +1065,55 @@ static int libertas_process_bss(struct bss_descriptor * bss,
1089 (u32) (pcountryinfo->len + 2)); 1065 (u32) (pcountryinfo->len + 2));
1090 break; 1066 break;
1091 1067
1092 case EXTENDED_SUPPORTED_RATES: 1068 case MFIE_TYPE_RATES_EX:
1093 /* 1069 /* only process extended supported rate if data rate is
1094 * only process extended supported rate 1070 * already found. Data rate IE should come before
1095 * if data rate is already found.
1096 * data rate IE should come before
1097 * extended supported rate IE 1071 * extended supported rate IE
1098 */ 1072 */
1099 if (founddatarateie) { 1073 if (!founddatarateie)
1100 if ((elemlen + ratesize) > WLAN_SUPPORTED_RATES) { 1074 break;
1101 bytestocopy =
1102 (WLAN_SUPPORTED_RATES - ratesize);
1103 } else {
1104 bytestocopy = elemlen;
1105 }
1106 1075
1107 pRate = (u8 *) bss->datarates; 1076 if ((elem->len + ratesize) > WLAN_SUPPORTED_RATES) {
1108 pRate += ratesize; 1077 bytestocopy =
1109 memmove(pRate, (pcurrentptr + 2), bytestocopy); 1078 (WLAN_SUPPORTED_RATES - ratesize);
1110 pRate = (u8 *) bss->libertas_supported_rates; 1079 } else {
1111 pRate += ratesize; 1080 bytestocopy = elem->len;
1112 memmove(pRate, (pcurrentptr + 2), bytestocopy);
1113 } 1081 }
1114 break;
1115
1116 case VENDOR_SPECIFIC_221:
1117#define IE_ID_LEN_FIELDS_BYTES 2
1118 pIe = (struct IE_WPA *)pcurrentptr;
1119 1082
1120 if (memcmp(pIe->oui, oui01, sizeof(oui01))) 1083 pRate = (u8 *) bss->datarates;
1121 break; 1084 pRate += ratesize;
1122 1085 memmove(pRate, elem->data, bytestocopy);
1123 bss->wpa_ie_len = min(elemlen + IE_ID_LEN_FIELDS_BYTES, 1086 pRate = (u8 *) bss->libertas_supported_rates;
1124 MAX_WPA_IE_LEN); 1087 pRate += ratesize;
1125 memcpy(bss->wpa_ie, pcurrentptr, bss->wpa_ie_len); 1088 memmove(pRate, elem->data, bytestocopy);
1126 lbs_dbg_hex("process_bss: WPA IE", bss->wpa_ie, elemlen);
1127 break; 1089 break;
1128 case WPA2_IE: 1090
1129 pIe = (struct IE_WPA *)pcurrentptr; 1091 case MFIE_TYPE_GENERIC:
1130 bss->rsn_ie_len = min(elemlen + IE_ID_LEN_FIELDS_BYTES, 1092 if (elem->len >= 4 &&
1131 MAX_WPA_IE_LEN); 1093 elem->data[0] == 0x00 &&
1132 memcpy(bss->rsn_ie, pcurrentptr, bss->rsn_ie_len); 1094 elem->data[1] == 0x50 &&
1133 lbs_dbg_hex("process_bss: RSN_IE", bss->rsn_ie, elemlen); 1095 elem->data[2] == 0xf2 &&
1096 elem->data[3] == 0x01) {
1097 bss->wpa_ie_len = min(elem->len + 2,
1098 MAX_WPA_IE_LEN);
1099 memcpy(bss->wpa_ie, elem, bss->wpa_ie_len);
1100 lbs_dbg_hex("process_bss: WPA IE", bss->wpa_ie,
1101 elem->len);
1102 }
1134 break; 1103 break;
1135 case TIM: 1104
1105 case MFIE_TYPE_RSN:
1106 bss->rsn_ie_len = min(elem->len + 2, MAX_WPA_IE_LEN);
1107 memcpy(bss->rsn_ie, elem, bss->rsn_ie_len);
1108 lbs_dbg_hex("process_bss: RSN_IE", bss->rsn_ie, elem->len);
1136 break; 1109 break;
1137 1110
1138 case CHALLENGE_TEXT: 1111 default:
1139 break; 1112 break;
1140 } 1113 }
1141 1114
1142 pcurrentptr += elemlen + 2; 1115 pos += elem->len + 2;
1143 1116 }
1144 /* need to account for IE ID and IE len */
1145 bytesleftforcurrentbeacon -= (elemlen + 2);
1146
1147 } /* while (bytesleftforcurrentbeacon > 2) */
1148 1117
1149 /* Timestamp */ 1118 /* Timestamp */
1150 bss->last_scanned = jiffies; 1119 bss->last_scanned = jiffies;
diff --git a/drivers/net/wireless/libertas/types.h b/drivers/net/wireless/libertas/types.h
index f4be1293cd16..2df352db1557 100644
--- a/drivers/net/wireless/libertas/types.h
+++ b/drivers/net/wireless/libertas/types.h
@@ -7,29 +7,6 @@
7#include <linux/if_ether.h> 7#include <linux/if_ether.h>
8#include <asm/byteorder.h> 8#include <asm/byteorder.h>
9 9
10/** IEEE type definitions */
11enum ieeetypes_elementid {
12 SSID = 0,
13 SUPPORTED_RATES,
14 FH_PARAM_SET,
15 DS_PARAM_SET,
16 CF_PARAM_SET,
17 TIM,
18 IBSS_PARAM_SET,
19 COUNTRY_INFO = 7,
20
21 CHALLENGE_TEXT = 16,
22
23 EXTENDED_SUPPORTED_RATES = 50,
24
25 VENDOR_SPECIFIC_221 = 221,
26
27 WPA_IE = 221,
28 WPA2_IE = 48,
29
30 EXTRA_IE = 133,
31} __attribute__ ((packed));
32
33#define CAPINFO_MASK (~(0x00da)) 10#define CAPINFO_MASK (~(0x00da))
34 11
35struct ieeetypes_cfparamset { 12struct ieeetypes_cfparamset {