aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r--net/mac80211/util.c297
1 files changed, 231 insertions, 66 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 3848140313f5..ca170b417da6 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -18,7 +18,6 @@
18#include <linux/skbuff.h> 18#include <linux/skbuff.h>
19#include <linux/etherdevice.h> 19#include <linux/etherdevice.h>
20#include <linux/if_arp.h> 20#include <linux/if_arp.h>
21#include <linux/wireless.h>
22#include <linux/bitmap.h> 21#include <linux/bitmap.h>
23#include <linux/crc32.h> 22#include <linux/crc32.h>
24#include <net/net_namespace.h> 23#include <net/net_namespace.h>
@@ -480,8 +479,8 @@ void ieee80211_iterate_active_interfaces(
480 case NL80211_IFTYPE_MESH_POINT: 479 case NL80211_IFTYPE_MESH_POINT:
481 break; 480 break;
482 } 481 }
483 if (netif_running(sdata->dev)) 482 if (ieee80211_sdata_running(sdata))
484 iterator(data, sdata->dev->dev_addr, 483 iterator(data, sdata->vif.addr,
485 &sdata->vif); 484 &sdata->vif);
486 } 485 }
487 486
@@ -514,8 +513,8 @@ void ieee80211_iterate_active_interfaces_atomic(
514 case NL80211_IFTYPE_MESH_POINT: 513 case NL80211_IFTYPE_MESH_POINT:
515 break; 514 break;
516 } 515 }
517 if (netif_running(sdata->dev)) 516 if (ieee80211_sdata_running(sdata))
518 iterator(data, sdata->dev->dev_addr, 517 iterator(data, sdata->vif.addr,
519 &sdata->vif); 518 &sdata->vif);
520 } 519 }
521 520
@@ -793,6 +792,8 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata)
793 break; 792 break;
794 } 793 }
795 794
795 qparam.uapsd = false;
796
796 drv_conf_tx(local, queue, &qparam); 797 drv_conf_tx(local, queue, &qparam);
797 } 798 }
798} 799}
@@ -860,7 +861,7 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
860 sizeof(*mgmt) + 6 + extra_len); 861 sizeof(*mgmt) + 6 + extra_len);
861 if (!skb) { 862 if (!skb) {
862 printk(KERN_DEBUG "%s: failed to allocate buffer for auth " 863 printk(KERN_DEBUG "%s: failed to allocate buffer for auth "
863 "frame\n", sdata->dev->name); 864 "frame\n", sdata->name);
864 return; 865 return;
865 } 866 }
866 skb_reserve(skb, local->hw.extra_tx_headroom); 867 skb_reserve(skb, local->hw.extra_tx_headroom);
@@ -870,7 +871,7 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
870 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 871 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
871 IEEE80211_STYPE_AUTH); 872 IEEE80211_STYPE_AUTH);
872 memcpy(mgmt->da, bssid, ETH_ALEN); 873 memcpy(mgmt->da, bssid, ETH_ALEN);
873 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); 874 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
874 memcpy(mgmt->bssid, bssid, ETH_ALEN); 875 memcpy(mgmt->bssid, bssid, ETH_ALEN);
875 mgmt->u.auth.auth_alg = cpu_to_le16(auth_alg); 876 mgmt->u.auth.auth_alg = cpu_to_le16(auth_alg);
876 mgmt->u.auth.auth_transaction = cpu_to_le16(transaction); 877 mgmt->u.auth.auth_transaction = cpu_to_le16(transaction);
@@ -893,43 +894,87 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
893 enum ieee80211_band band) 894 enum ieee80211_band band)
894{ 895{
895 struct ieee80211_supported_band *sband; 896 struct ieee80211_supported_band *sband;
896 u8 *pos, *supp_rates_len, *esupp_rates_len = NULL; 897 u8 *pos;
897 int i; 898 size_t offset = 0, noffset;
899 int supp_rates_len, i;
898 900
899 sband = local->hw.wiphy->bands[band]; 901 sband = local->hw.wiphy->bands[band];
900 902
901 pos = buffer; 903 pos = buffer;
902 904
905 supp_rates_len = min_t(int, sband->n_bitrates, 8);
906
903 *pos++ = WLAN_EID_SUPP_RATES; 907 *pos++ = WLAN_EID_SUPP_RATES;
904 supp_rates_len = pos; 908 *pos++ = supp_rates_len;
905 *pos++ = 0; 909
906 910 for (i = 0; i < supp_rates_len; i++) {
907 for (i = 0; i < sband->n_bitrates; i++) { 911 int rate = sband->bitrates[i].bitrate;
908 struct ieee80211_rate *rate = &sband->bitrates[i]; 912 *pos++ = (u8) (rate / 5);
909 913 }
910 if (esupp_rates_len) { 914
911 *esupp_rates_len += 1; 915 /* insert "request information" if in custom IEs */
912 } else if (*supp_rates_len == 8) { 916 if (ie && ie_len) {
913 *pos++ = WLAN_EID_EXT_SUPP_RATES; 917 static const u8 before_extrates[] = {
914 esupp_rates_len = pos; 918 WLAN_EID_SSID,
915 *pos++ = 1; 919 WLAN_EID_SUPP_RATES,
916 } else 920 WLAN_EID_REQUEST,
917 *supp_rates_len += 1; 921 };
922 noffset = ieee80211_ie_split(ie, ie_len,
923 before_extrates,
924 ARRAY_SIZE(before_extrates),
925 offset);
926 memcpy(pos, ie + offset, noffset - offset);
927 pos += noffset - offset;
928 offset = noffset;
929 }
930
931 if (sband->n_bitrates > i) {
932 *pos++ = WLAN_EID_EXT_SUPP_RATES;
933 *pos++ = sband->n_bitrates - i;
918 934
919 *pos++ = rate->bitrate / 5; 935 for (; i < sband->n_bitrates; i++) {
936 int rate = sband->bitrates[i].bitrate;
937 *pos++ = (u8) (rate / 5);
938 }
939 }
940
941 /* insert custom IEs that go before HT */
942 if (ie && ie_len) {
943 static const u8 before_ht[] = {
944 WLAN_EID_SSID,
945 WLAN_EID_SUPP_RATES,
946 WLAN_EID_REQUEST,
947 WLAN_EID_EXT_SUPP_RATES,
948 WLAN_EID_DS_PARAMS,
949 WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
950 };
951 noffset = ieee80211_ie_split(ie, ie_len,
952 before_ht, ARRAY_SIZE(before_ht),
953 offset);
954 memcpy(pos, ie + offset, noffset - offset);
955 pos += noffset - offset;
956 offset = noffset;
920 } 957 }
921 958
922 if (sband->ht_cap.ht_supported) { 959 if (sband->ht_cap.ht_supported) {
923 __le16 tmp = cpu_to_le16(sband->ht_cap.cap); 960 u16 cap = sband->ht_cap.cap;
961 __le16 tmp;
962
963 if (ieee80211_disable_40mhz_24ghz &&
964 sband->band == IEEE80211_BAND_2GHZ) {
965 cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
966 cap &= ~IEEE80211_HT_CAP_SGI_40;
967 }
924 968
925 *pos++ = WLAN_EID_HT_CAPABILITY; 969 *pos++ = WLAN_EID_HT_CAPABILITY;
926 *pos++ = sizeof(struct ieee80211_ht_cap); 970 *pos++ = sizeof(struct ieee80211_ht_cap);
927 memset(pos, 0, sizeof(struct ieee80211_ht_cap)); 971 memset(pos, 0, sizeof(struct ieee80211_ht_cap));
972 tmp = cpu_to_le16(cap);
928 memcpy(pos, &tmp, sizeof(u16)); 973 memcpy(pos, &tmp, sizeof(u16));
929 pos += sizeof(u16); 974 pos += sizeof(u16);
930 /* TODO: needs a define here for << 2 */
931 *pos++ = sband->ht_cap.ampdu_factor | 975 *pos++ = sband->ht_cap.ampdu_factor |
932 (sband->ht_cap.ampdu_density << 2); 976 (sband->ht_cap.ampdu_density <<
977 IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
933 memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); 978 memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
934 pos += sizeof(sband->ht_cap.mcs); 979 pos += sizeof(sband->ht_cap.mcs);
935 pos += 2 + 4 + 1; /* ext info, BF cap, antsel */ 980 pos += 2 + 4 + 1; /* ext info, BF cap, antsel */
@@ -940,9 +985,11 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
940 * that calculates local->scan_ies_len. 985 * that calculates local->scan_ies_len.
941 */ 986 */
942 987
943 if (ie) { 988 /* add any remaining custom IEs */
944 memcpy(pos, ie, ie_len); 989 if (ie && ie_len) {
945 pos += ie_len; 990 noffset = ie_len;
991 memcpy(pos, ie + offset, noffset - offset);
992 pos += noffset - offset;
946 } 993 }
947 994
948 return pos - buffer; 995 return pos - buffer;
@@ -955,40 +1002,33 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
955 struct ieee80211_local *local = sdata->local; 1002 struct ieee80211_local *local = sdata->local;
956 struct sk_buff *skb; 1003 struct sk_buff *skb;
957 struct ieee80211_mgmt *mgmt; 1004 struct ieee80211_mgmt *mgmt;
958 u8 *pos; 1005 size_t buf_len;
959 1006 u8 *buf;
960 skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200 + 1007
961 ie_len); 1008 /* FIXME: come up with a proper value */
962 if (!skb) { 1009 buf = kmalloc(200 + ie_len, GFP_KERNEL);
963 printk(KERN_DEBUG "%s: failed to allocate buffer for probe " 1010 if (!buf) {
964 "request\n", sdata->dev->name); 1011 printk(KERN_DEBUG "%s: failed to allocate temporary IE "
1012 "buffer\n", sdata->name);
965 return; 1013 return;
966 } 1014 }
967 skb_reserve(skb, local->hw.extra_tx_headroom);
968 1015
969 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); 1016 buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len,
970 memset(mgmt, 0, 24); 1017 local->hw.conf.channel->band);
971 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 1018
972 IEEE80211_STYPE_PROBE_REQ); 1019 skb = ieee80211_probereq_get(&local->hw, &sdata->vif,
973 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); 1020 ssid, ssid_len,
1021 buf, buf_len);
1022
974 if (dst) { 1023 if (dst) {
1024 mgmt = (struct ieee80211_mgmt *) skb->data;
975 memcpy(mgmt->da, dst, ETH_ALEN); 1025 memcpy(mgmt->da, dst, ETH_ALEN);
976 memcpy(mgmt->bssid, dst, ETH_ALEN); 1026 memcpy(mgmt->bssid, dst, ETH_ALEN);
977 } else {
978 memset(mgmt->da, 0xff, ETH_ALEN);
979 memset(mgmt->bssid, 0xff, ETH_ALEN);
980 } 1027 }
981 pos = skb_put(skb, 2 + ssid_len);
982 *pos++ = WLAN_EID_SSID;
983 *pos++ = ssid_len;
984 memcpy(pos, ssid, ssid_len);
985 pos += ssid_len;
986
987 skb_put(skb, ieee80211_build_preq_ies(local, pos, ie, ie_len,
988 local->hw.conf.channel->band));
989 1028
990 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; 1029 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
991 ieee80211_tx_skb(sdata, skb); 1030 ieee80211_tx_skb(sdata, skb);
1031 kfree(buf);
992} 1032}
993 1033
994u32 ieee80211_sta_get_rates(struct ieee80211_local *local, 1034u32 ieee80211_sta_get_rates(struct ieee80211_local *local,
@@ -1032,16 +1072,15 @@ void ieee80211_stop_device(struct ieee80211_local *local)
1032 ieee80211_led_radio(local, false); 1072 ieee80211_led_radio(local, false);
1033 1073
1034 cancel_work_sync(&local->reconfig_filter); 1074 cancel_work_sync(&local->reconfig_filter);
1035 drv_stop(local);
1036 1075
1037 flush_workqueue(local->workqueue); 1076 flush_workqueue(local->workqueue);
1077 drv_stop(local);
1038} 1078}
1039 1079
1040int ieee80211_reconfig(struct ieee80211_local *local) 1080int ieee80211_reconfig(struct ieee80211_local *local)
1041{ 1081{
1042 struct ieee80211_hw *hw = &local->hw; 1082 struct ieee80211_hw *hw = &local->hw;
1043 struct ieee80211_sub_if_data *sdata; 1083 struct ieee80211_sub_if_data *sdata;
1044 struct ieee80211_if_init_conf conf;
1045 struct sta_info *sta; 1084 struct sta_info *sta;
1046 unsigned long flags; 1085 unsigned long flags;
1047 int res; 1086 int res;
@@ -1061,7 +1100,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1061 if (res) { 1100 if (res) {
1062 WARN(local->suspended, "Harware became unavailable " 1101 WARN(local->suspended, "Harware became unavailable "
1063 "upon resume. This is could be a software issue" 1102 "upon resume. This is could be a software issue"
1064 "prior to suspend or a harware issue\n"); 1103 "prior to suspend or a hardware issue\n");
1065 return res; 1104 return res;
1066 } 1105 }
1067 1106
@@ -1072,12 +1111,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1072 list_for_each_entry(sdata, &local->interfaces, list) { 1111 list_for_each_entry(sdata, &local->interfaces, list) {
1073 if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && 1112 if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
1074 sdata->vif.type != NL80211_IFTYPE_MONITOR && 1113 sdata->vif.type != NL80211_IFTYPE_MONITOR &&
1075 netif_running(sdata->dev)) { 1114 ieee80211_sdata_running(sdata))
1076 conf.vif = &sdata->vif; 1115 res = drv_add_interface(local, &sdata->vif);
1077 conf.type = sdata->vif.type;
1078 conf.mac_addr = sdata->dev->dev_addr;
1079 res = drv_add_interface(local, &conf);
1080 }
1081 } 1116 }
1082 1117
1083 /* add STAs back */ 1118 /* add STAs back */
@@ -1090,7 +1125,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1090 struct ieee80211_sub_if_data, 1125 struct ieee80211_sub_if_data,
1091 u.ap); 1126 u.ap);
1092 1127
1093 drv_sta_notify(local, &sdata->vif, STA_NOTIFY_ADD, 1128 drv_sta_notify(local, sdata, STA_NOTIFY_ADD,
1094 &sta->sta); 1129 &sta->sta);
1095 } 1130 }
1096 spin_unlock_irqrestore(&local->sta_lock, flags); 1131 spin_unlock_irqrestore(&local->sta_lock, flags);
@@ -1119,7 +1154,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1119 /* Finally also reconfigure all the BSS information */ 1154 /* Finally also reconfigure all the BSS information */
1120 list_for_each_entry(sdata, &local->interfaces, list) { 1155 list_for_each_entry(sdata, &local->interfaces, list) {
1121 u32 changed = ~0; 1156 u32 changed = ~0;
1122 if (!netif_running(sdata->dev)) 1157 if (!ieee80211_sdata_running(sdata))
1123 continue; 1158 continue;
1124 switch (sdata->vif.type) { 1159 switch (sdata->vif.type) {
1125 case NL80211_IFTYPE_STATION: 1160 case NL80211_IFTYPE_STATION:
@@ -1147,7 +1182,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1147 1182
1148 /* add back keys */ 1183 /* add back keys */
1149 list_for_each_entry(sdata, &local->interfaces, list) 1184 list_for_each_entry(sdata, &local->interfaces, list)
1150 if (netif_running(sdata->dev)) 1185 if (ieee80211_sdata_running(sdata))
1151 ieee80211_enable_keys(sdata); 1186 ieee80211_enable_keys(sdata);
1152 1187
1153 ieee80211_wake_queues_by_reason(hw, 1188 ieee80211_wake_queues_by_reason(hw,
@@ -1194,3 +1229,133 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1194 return 0; 1229 return 0;
1195} 1230}
1196 1231
1232static int check_mgd_smps(struct ieee80211_if_managed *ifmgd,
1233 enum ieee80211_smps_mode *smps_mode)
1234{
1235 if (ifmgd->associated) {
1236 *smps_mode = ifmgd->ap_smps;
1237
1238 if (*smps_mode == IEEE80211_SMPS_AUTOMATIC) {
1239 if (ifmgd->powersave)
1240 *smps_mode = IEEE80211_SMPS_DYNAMIC;
1241 else
1242 *smps_mode = IEEE80211_SMPS_OFF;
1243 }
1244
1245 return 1;
1246 }
1247
1248 return 0;
1249}
1250
1251/* must hold iflist_mtx */
1252void ieee80211_recalc_smps(struct ieee80211_local *local,
1253 struct ieee80211_sub_if_data *forsdata)
1254{
1255 struct ieee80211_sub_if_data *sdata;
1256 enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_OFF;
1257 int count = 0;
1258
1259 if (forsdata)
1260 WARN_ON(!mutex_is_locked(&forsdata->u.mgd.mtx));
1261
1262 WARN_ON(!mutex_is_locked(&local->iflist_mtx));
1263
1264 /*
1265 * This function could be improved to handle multiple
1266 * interfaces better, but right now it makes any
1267 * non-station interfaces force SM PS to be turned
1268 * off. If there are multiple station interfaces it
1269 * could also use the best possible mode, e.g. if
1270 * one is in static and the other in dynamic then
1271 * dynamic is ok.
1272 */
1273
1274 list_for_each_entry(sdata, &local->interfaces, list) {
1275 if (!netif_running(sdata->dev))
1276 continue;
1277 if (sdata->vif.type != NL80211_IFTYPE_STATION)
1278 goto set;
1279 if (sdata != forsdata) {
1280 /*
1281 * This nested is ok -- we are holding the iflist_mtx
1282 * so can't get here twice or so. But it's required
1283 * since normally we acquire it first and then the
1284 * iflist_mtx.
1285 */
1286 mutex_lock_nested(&sdata->u.mgd.mtx, SINGLE_DEPTH_NESTING);
1287 count += check_mgd_smps(&sdata->u.mgd, &smps_mode);
1288 mutex_unlock(&sdata->u.mgd.mtx);
1289 } else
1290 count += check_mgd_smps(&sdata->u.mgd, &smps_mode);
1291
1292 if (count > 1) {
1293 smps_mode = IEEE80211_SMPS_OFF;
1294 break;
1295 }
1296 }
1297
1298 if (smps_mode == local->smps_mode)
1299 return;
1300
1301 set:
1302 local->smps_mode = smps_mode;
1303 /* changed flag is auto-detected for this */
1304 ieee80211_hw_config(local, 0);
1305}
1306
1307static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id)
1308{
1309 int i;
1310
1311 for (i = 0; i < n_ids; i++)
1312 if (ids[i] == id)
1313 return true;
1314 return false;
1315}
1316
1317/**
1318 * ieee80211_ie_split - split an IE buffer according to ordering
1319 *
1320 * @ies: the IE buffer
1321 * @ielen: the length of the IE buffer
1322 * @ids: an array with element IDs that are allowed before
1323 * the split
1324 * @n_ids: the size of the element ID array
1325 * @offset: offset where to start splitting in the buffer
1326 *
1327 * This function splits an IE buffer by updating the @offset
1328 * variable to point to the location where the buffer should be
1329 * split.
1330 *
1331 * It assumes that the given IE buffer is well-formed, this
1332 * has to be guaranteed by the caller!
1333 *
1334 * It also assumes that the IEs in the buffer are ordered
1335 * correctly, if not the result of using this function will not
1336 * be ordered correctly either, i.e. it does no reordering.
1337 *
1338 * The function returns the offset where the next part of the
1339 * buffer starts, which may be @ielen if the entire (remainder)
1340 * of the buffer should be used.
1341 */
1342size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
1343 const u8 *ids, int n_ids, size_t offset)
1344{
1345 size_t pos = offset;
1346
1347 while (pos < ielen && ieee80211_id_in_list(ids, n_ids, ies[pos]))
1348 pos += 2 + ies[pos + 1];
1349
1350 return pos;
1351}
1352
1353size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset)
1354{
1355 size_t pos = offset;
1356
1357 while (pos < ielen && ies[pos] != WLAN_EID_VENDOR_SPECIFIC)
1358 pos += 2 + ies[pos + 1];
1359
1360 return pos;
1361}