aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorYogesh Ashok Powar <yogeshp@marvell.com>2011-08-09 21:02:26 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-08-12 13:45:03 -0400
commit0879fa44b54101c9955123582018cb511047a2b6 (patch)
tree0a9c1f5fc10a3b320d0db793598822a43b2dc719 /net/wireless
parentf3d4505de539f754b78d5c30e5d2cb41a0ed0117 (diff)
cfg80211/mac80211: move information element parsing logic to cfg80211
Moving the parsing logic for retrieving the information elements stored in management frames, e.g. beacons or probe responses, and making it available to other cfg80211 drivers. Signed-off-by: Yogesh Ashok Powar <yogeshp@marvell.com> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com> Signed-off-by: Bing Zhao <bzhao@marvell.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/util.c168
1 files changed, 168 insertions, 0 deletions
diff --git a/net/wireless/util.c b/net/wireless/util.c
index be75a3a0424e..844ddb0aa653 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -6,6 +6,7 @@
6#include <linux/bitops.h> 6#include <linux/bitops.h>
7#include <linux/etherdevice.h> 7#include <linux/etherdevice.h>
8#include <linux/slab.h> 8#include <linux/slab.h>
9#include <linux/crc32.h>
9#include <net/cfg80211.h> 10#include <net/cfg80211.h>
10#include <net/ip.h> 11#include <net/ip.h>
11#include "core.h" 12#include "core.h"
@@ -1044,3 +1045,170 @@ int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
1044 1045
1045 return 0; 1046 return 0;
1046} 1047}
1048
1049u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
1050 struct ieee802_11_elems *elems,
1051 u64 filter, u32 crc)
1052{
1053 size_t left = len;
1054 u8 *pos = start;
1055 bool calc_crc = filter != 0;
1056
1057 memset(elems, 0, sizeof(*elems));
1058 elems->ie_start = start;
1059 elems->total_len = len;
1060
1061 while (left >= 2) {
1062 u8 id, elen;
1063
1064 id = *pos++;
1065 elen = *pos++;
1066 left -= 2;
1067
1068 if (elen > left)
1069 break;
1070
1071 if (calc_crc && id < 64 && (filter & (1ULL << id)))
1072 crc = crc32_be(crc, pos - 2, elen + 2);
1073
1074 switch (id) {
1075 case WLAN_EID_SSID:
1076 elems->ssid = pos;
1077 elems->ssid_len = elen;
1078 break;
1079 case WLAN_EID_SUPP_RATES:
1080 elems->supp_rates = pos;
1081 elems->supp_rates_len = elen;
1082 break;
1083 case WLAN_EID_FH_PARAMS:
1084 elems->fh_params = pos;
1085 elems->fh_params_len = elen;
1086 break;
1087 case WLAN_EID_DS_PARAMS:
1088 elems->ds_params = pos;
1089 elems->ds_params_len = elen;
1090 break;
1091 case WLAN_EID_CF_PARAMS:
1092 elems->cf_params = pos;
1093 elems->cf_params_len = elen;
1094 break;
1095 case WLAN_EID_TIM:
1096 if (elen >= sizeof(struct ieee80211_tim_ie)) {
1097 elems->tim = (void *)pos;
1098 elems->tim_len = elen;
1099 }
1100 break;
1101 case WLAN_EID_IBSS_PARAMS:
1102 elems->ibss_params = pos;
1103 elems->ibss_params_len = elen;
1104 break;
1105 case WLAN_EID_CHALLENGE:
1106 elems->challenge = pos;
1107 elems->challenge_len = elen;
1108 break;
1109 case WLAN_EID_VENDOR_SPECIFIC:
1110 if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 &&
1111 pos[2] == 0xf2) {
1112 /* Microsoft OUI (00:50:F2) */
1113
1114 if (calc_crc)
1115 crc = crc32_be(crc, pos - 2, elen + 2);
1116
1117 if (pos[3] == 1) {
1118 /* OUI Type 1 - WPA IE */
1119 elems->wpa = pos;
1120 elems->wpa_len = elen;
1121 } else if (elen >= 5 && pos[3] == 2) {
1122 /* OUI Type 2 - WMM IE */
1123 if (pos[4] == 0) {
1124 elems->wmm_info = pos;
1125 elems->wmm_info_len = elen;
1126 } else if (pos[4] == 1) {
1127 elems->wmm_param = pos;
1128 elems->wmm_param_len = elen;
1129 }
1130 }
1131 }
1132 break;
1133 case WLAN_EID_RSN:
1134 elems->rsn = pos;
1135 elems->rsn_len = elen;
1136 break;
1137 case WLAN_EID_ERP_INFO:
1138 elems->erp_info = pos;
1139 elems->erp_info_len = elen;
1140 break;
1141 case WLAN_EID_EXT_SUPP_RATES:
1142 elems->ext_supp_rates = pos;
1143 elems->ext_supp_rates_len = elen;
1144 break;
1145 case WLAN_EID_HT_CAPABILITY:
1146 if (elen >= sizeof(struct ieee80211_ht_cap))
1147 elems->ht_cap_elem = (void *)pos;
1148 break;
1149 case WLAN_EID_HT_INFORMATION:
1150 if (elen >= sizeof(struct ieee80211_ht_info))
1151 elems->ht_info_elem = (void *)pos;
1152 break;
1153 case WLAN_EID_MESH_ID:
1154 elems->mesh_id = pos;
1155 elems->mesh_id_len = elen;
1156 break;
1157 case WLAN_EID_MESH_CONFIG:
1158 if (elen >= sizeof(struct ieee80211_meshconf_ie))
1159 elems->mesh_config = (void *)pos;
1160 break;
1161 case WLAN_EID_PEER_LINK:
1162 elems->peer_link = pos;
1163 elems->peer_link_len = elen;
1164 break;
1165 case WLAN_EID_PREQ:
1166 elems->preq = pos;
1167 elems->preq_len = elen;
1168 break;
1169 case WLAN_EID_PREP:
1170 elems->prep = pos;
1171 elems->prep_len = elen;
1172 break;
1173 case WLAN_EID_PERR:
1174 elems->perr = pos;
1175 elems->perr_len = elen;
1176 break;
1177 case WLAN_EID_RANN:
1178 if (elen >= sizeof(struct ieee80211_rann_ie))
1179 elems->rann = (void *)pos;
1180 break;
1181 case WLAN_EID_CHANNEL_SWITCH:
1182 elems->ch_switch_elem = pos;
1183 elems->ch_switch_elem_len = elen;
1184 break;
1185 case WLAN_EID_QUIET:
1186 if (!elems->quiet_elem) {
1187 elems->quiet_elem = pos;
1188 elems->quiet_elem_len = elen;
1189 }
1190 elems->num_of_quiet_elem++;
1191 break;
1192 case WLAN_EID_COUNTRY:
1193 elems->country_elem = pos;
1194 elems->country_elem_len = elen;
1195 break;
1196 case WLAN_EID_PWR_CONSTRAINT:
1197 elems->pwr_constr_elem = pos;
1198 elems->pwr_constr_elem_len = elen;
1199 break;
1200 case WLAN_EID_TIMEOUT_INTERVAL:
1201 elems->timeout_int = pos;
1202 elems->timeout_int_len = elen;
1203 break;
1204 default:
1205 break;
1206 }
1207
1208 left -= elen;
1209 pos += elen;
1210 }
1211
1212 return crc;
1213}
1214EXPORT_SYMBOL(ieee802_11_parse_elems_crc);