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