diff options
author | Dan Williams <dcbw@redhat.com> | 2007-08-02 10:48:02 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-10-10 19:49:39 -0400 |
commit | ab6179711a5e46ed1db739bef7752d65ce836dce (patch) | |
tree | e1d026661ceb7736a516bcd4eb2eb50f917e9d5c /drivers/net/wireless/libertas/scan.c | |
parent | 2950cd26308ced650cf7cc3199eae3eb27f9917f (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>
Diffstat (limited to 'drivers/net/wireless/libertas/scan.c')
-rw-r--r-- | drivers/net/wireless/libertas/scan.c | 199 |
1 files changed, 84 insertions, 115 deletions
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, | |||
900 | static int libertas_process_bss(struct bss_descriptor * bss, | 900 | static 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; |