aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/util.c
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2012-01-09 02:38:23 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2012-01-09 02:38:23 -0500
commitda733563be5a9da26fe81d9f007262d00b846e22 (patch)
treedb28291df94a2043af2123911984c5c173da4e6f /net/wireless/util.c
parent6ccbcf2cb41131f8d56ef0723bf3f7c1f8486076 (diff)
parentdab78d7924598ea4031663dd10db814e2e324928 (diff)
Merge branch 'next' into for-linus
Diffstat (limited to 'net/wireless/util.c')
-rw-r--r--net/wireless/util.c195
1 files changed, 184 insertions, 11 deletions
diff --git a/net/wireless/util.c b/net/wireless/util.c
index be75a3a0424e..4dde429441d2 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -3,9 +3,11 @@
3 * 3 *
4 * Copyright 2007-2009 Johannes Berg <johannes@sipsolutions.net> 4 * Copyright 2007-2009 Johannes Berg <johannes@sipsolutions.net>
5 */ 5 */
6#include <linux/export.h>
6#include <linux/bitops.h> 7#include <linux/bitops.h>
7#include <linux/etherdevice.h> 8#include <linux/etherdevice.h>
8#include <linux/slab.h> 9#include <linux/slab.h>
10#include <linux/crc32.h>
9#include <net/cfg80211.h> 11#include <net/cfg80211.h>
10#include <net/ip.h> 12#include <net/ip.h>
11#include "core.h" 13#include "core.h"
@@ -150,12 +152,19 @@ void ieee80211_set_bitrate_flags(struct wiphy *wiphy)
150 set_mandatory_flags_band(wiphy->bands[band], band); 152 set_mandatory_flags_band(wiphy->bands[band], band);
151} 153}
152 154
155bool cfg80211_supported_cipher_suite(struct wiphy *wiphy, u32 cipher)
156{
157 int i;
158 for (i = 0; i < wiphy->n_cipher_suites; i++)
159 if (cipher == wiphy->cipher_suites[i])
160 return true;
161 return false;
162}
163
153int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, 164int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
154 struct key_params *params, int key_idx, 165 struct key_params *params, int key_idx,
155 bool pairwise, const u8 *mac_addr) 166 bool pairwise, const u8 *mac_addr)
156{ 167{
157 int i;
158
159 if (key_idx > 5) 168 if (key_idx > 5)
160 return -EINVAL; 169 return -EINVAL;
161 170
@@ -225,10 +234,7 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,
225 } 234 }
226 } 235 }
227 236
228 for (i = 0; i < rdev->wiphy.n_cipher_suites; i++) 237 if (!cfg80211_supported_cipher_suite(&rdev->wiphy, params->cipher))
229 if (params->cipher == rdev->wiphy.cipher_suites[i])
230 break;
231 if (i == rdev->wiphy.n_cipher_suites)
232 return -EINVAL; 238 return -EINVAL;
233 239
234 return 0; 240 return 0;
@@ -391,8 +397,9 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
391 } 397 }
392 break; 398 break;
393 case cpu_to_le16(0): 399 case cpu_to_le16(0):
394 if (iftype != NL80211_IFTYPE_ADHOC) 400 if (iftype != NL80211_IFTYPE_ADHOC &&
395 return -1; 401 iftype != NL80211_IFTYPE_STATION)
402 return -1;
396 break; 403 break;
397 } 404 }
398 405
@@ -512,10 +519,9 @@ int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
512 if (head_need) 519 if (head_need)
513 skb_orphan(skb); 520 skb_orphan(skb);
514 521
515 if (pskb_expand_head(skb, head_need, 0, GFP_ATOMIC)) { 522 if (pskb_expand_head(skb, head_need, 0, GFP_ATOMIC))
516 pr_err("failed to reallocate Tx buffer\n");
517 return -ENOMEM; 523 return -ENOMEM;
518 } 524
519 skb->truesize += head_need; 525 skb->truesize += head_need;
520 } 526 }
521 527
@@ -1044,3 +1050,170 @@ int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
1044 1050
1045 return 0; 1051 return 0;
1046} 1052}
1053
1054u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
1055 struct ieee802_11_elems *elems,
1056 u64 filter, u32 crc)
1057{
1058 size_t left = len;
1059 u8 *pos = start;
1060 bool calc_crc = filter != 0;
1061
1062 memset(elems, 0, sizeof(*elems));
1063 elems->ie_start = start;
1064 elems->total_len = len;
1065
1066 while (left >= 2) {
1067 u8 id, elen;
1068
1069 id = *pos++;
1070 elen = *pos++;
1071 left -= 2;
1072
1073 if (elen > left)
1074 break;
1075
1076 if (calc_crc && id < 64 && (filter & (1ULL << id)))
1077 crc = crc32_be(crc, pos - 2, elen + 2);
1078
1079 switch (id) {
1080 case WLAN_EID_SSID:
1081 elems->ssid = pos;
1082 elems->ssid_len = elen;
1083 break;
1084 case WLAN_EID_SUPP_RATES:
1085 elems->supp_rates = pos;
1086 elems->supp_rates_len = elen;
1087 break;
1088 case WLAN_EID_FH_PARAMS:
1089 elems->fh_params = pos;
1090 elems->fh_params_len = elen;
1091 break;
1092 case WLAN_EID_DS_PARAMS:
1093 elems->ds_params = pos;
1094 elems->ds_params_len = elen;
1095 break;
1096 case WLAN_EID_CF_PARAMS:
1097 elems->cf_params = pos;
1098 elems->cf_params_len = elen;
1099 break;
1100 case WLAN_EID_TIM:
1101 if (elen >= sizeof(struct ieee80211_tim_ie)) {
1102 elems->tim = (void *)pos;
1103 elems->tim_len = elen;
1104 }
1105 break;
1106 case WLAN_EID_IBSS_PARAMS:
1107 elems->ibss_params = pos;
1108 elems->ibss_params_len = elen;
1109 break;
1110 case WLAN_EID_CHALLENGE:
1111 elems->challenge = pos;
1112 elems->challenge_len = elen;
1113 break;
1114 case WLAN_EID_VENDOR_SPECIFIC:
1115 if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 &&
1116 pos[2] == 0xf2) {
1117 /* Microsoft OUI (00:50:F2) */
1118
1119 if (calc_crc)
1120 crc = crc32_be(crc, pos - 2, elen + 2);
1121
1122 if (pos[3] == 1) {
1123 /* OUI Type 1 - WPA IE */
1124 elems->wpa = pos;
1125 elems->wpa_len = elen;
1126 } else if (elen >= 5 && pos[3] == 2) {
1127 /* OUI Type 2 - WMM IE */
1128 if (pos[4] == 0) {
1129 elems->wmm_info = pos;
1130 elems->wmm_info_len = elen;
1131 } else if (pos[4] == 1) {
1132 elems->wmm_param = pos;
1133 elems->wmm_param_len = elen;
1134 }
1135 }
1136 }
1137 break;
1138 case WLAN_EID_RSN:
1139 elems->rsn = pos;
1140 elems->rsn_len = elen;
1141 break;
1142 case WLAN_EID_ERP_INFO:
1143 elems->erp_info = pos;
1144 elems->erp_info_len = elen;
1145 break;
1146 case WLAN_EID_EXT_SUPP_RATES:
1147 elems->ext_supp_rates = pos;
1148 elems->ext_supp_rates_len = elen;
1149 break;
1150 case WLAN_EID_HT_CAPABILITY:
1151 if (elen >= sizeof(struct ieee80211_ht_cap))
1152 elems->ht_cap_elem = (void *)pos;
1153 break;
1154 case WLAN_EID_HT_INFORMATION:
1155 if (elen >= sizeof(struct ieee80211_ht_info))
1156 elems->ht_info_elem = (void *)pos;
1157 break;
1158 case WLAN_EID_MESH_ID:
1159 elems->mesh_id = pos;
1160 elems->mesh_id_len = elen;
1161 break;
1162 case WLAN_EID_MESH_CONFIG:
1163 if (elen >= sizeof(struct ieee80211_meshconf_ie))
1164 elems->mesh_config = (void *)pos;
1165 break;
1166 case WLAN_EID_PEER_MGMT:
1167 elems->peering = pos;
1168 elems->peering_len = elen;
1169 break;
1170 case WLAN_EID_PREQ:
1171 elems->preq = pos;
1172 elems->preq_len = elen;
1173 break;
1174 case WLAN_EID_PREP:
1175 elems->prep = pos;
1176 elems->prep_len = elen;
1177 break;
1178 case WLAN_EID_PERR:
1179 elems->perr = pos;
1180 elems->perr_len = elen;
1181 break;
1182 case WLAN_EID_RANN:
1183 if (elen >= sizeof(struct ieee80211_rann_ie))
1184 elems->rann = (void *)pos;
1185 break;
1186 case WLAN_EID_CHANNEL_SWITCH:
1187 elems->ch_switch_elem = pos;
1188 elems->ch_switch_elem_len = elen;
1189 break;
1190 case WLAN_EID_QUIET:
1191 if (!elems->quiet_elem) {
1192 elems->quiet_elem = pos;
1193 elems->quiet_elem_len = elen;
1194 }
1195 elems->num_of_quiet_elem++;
1196 break;
1197 case WLAN_EID_COUNTRY:
1198 elems->country_elem = pos;
1199 elems->country_elem_len = elen;
1200 break;
1201 case WLAN_EID_PWR_CONSTRAINT:
1202 elems->pwr_constr_elem = pos;
1203 elems->pwr_constr_elem_len = elen;
1204 break;
1205 case WLAN_EID_TIMEOUT_INTERVAL:
1206 elems->timeout_int = pos;
1207 elems->timeout_int_len = elen;
1208 break;
1209 default:
1210 break;
1211 }
1212
1213 left -= elen;
1214 pos += elen;
1215 }
1216
1217 return crc;
1218}
1219EXPORT_SYMBOL(ieee802_11_parse_elems_crc);