diff options
author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2012-01-09 02:38:23 -0500 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2012-01-09 02:38:23 -0500 |
commit | da733563be5a9da26fe81d9f007262d00b846e22 (patch) | |
tree | db28291df94a2043af2123911984c5c173da4e6f /net/wireless/util.c | |
parent | 6ccbcf2cb41131f8d56ef0723bf3f7c1f8486076 (diff) | |
parent | dab78d7924598ea4031663dd10db814e2e324928 (diff) |
Merge branch 'next' into for-linus
Diffstat (limited to 'net/wireless/util.c')
-rw-r--r-- | net/wireless/util.c | 195 |
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 | ||
155 | bool 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 | |||
153 | int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, | 164 | int 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 | |||
1054 | u32 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 | } | ||
1219 | EXPORT_SYMBOL(ieee802_11_parse_elems_crc); | ||