aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/ieee80211.h11
-rw-r--r--net/mac80211/ieee80211_i.h6
-rw-r--r--net/mac80211/ieee80211_sta.c69
3 files changed, 67 insertions, 19 deletions
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index ecd61e8438a5..272f8c8c90da 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -227,6 +227,17 @@ struct ieee80211_cts {
227#define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10) 227#define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10)
228#define WLAN_CAPABILITY_DSSS_OFDM (1<<13) 228#define WLAN_CAPABILITY_DSSS_OFDM (1<<13)
229 229
230/* 802.11g ERP information element */
231#define WLAN_ERP_NON_ERP_PRESENT (1<<0)
232#define WLAN_ERP_USE_PROTECTION (1<<1)
233#define WLAN_ERP_BARKER_PREAMBLE (1<<2)
234
235/* WLAN_ERP_BARKER_PREAMBLE values */
236enum {
237 WLAN_ERP_PREAMBLE_SHORT = 0,
238 WLAN_ERP_PREAMBLE_LONG = 1,
239};
240
230/* Status codes */ 241/* Status codes */
231enum ieee80211_statuscode { 242enum ieee80211_statuscode {
232 WLAN_STATUS_SUCCESS = 0, 243 WLAN_STATUS_SUCCESS = 0,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index b222a9afd4e9..99ff7c5e9204 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -99,6 +99,12 @@ struct ieee80211_sta_bss {
99 int probe_resp; 99 int probe_resp;
100 unsigned long last_update; 100 unsigned long last_update;
101 101
102 /* during assocation, we save an ERP value from a probe response so
103 * that we can feed ERP info to the driver when handling the
104 * association completes. these fields probably won't be up-to-date
105 * otherwise, you probably don't want to use them. */
106 int has_erp_value;
107 u8 erp_value;
102}; 108};
103 109
104 110
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
index f3ca83743b48..df6c410de161 100644
--- a/net/mac80211/ieee80211_sta.c
+++ b/net/mac80211/ieee80211_sta.c
@@ -314,6 +314,27 @@ static void ieee80211_sta_wmm_params(struct net_device *dev,
314} 314}
315 315
316 316
317static void ieee80211_handle_erp_ie(struct net_device *dev, u8 erp_value)
318{
319 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
320 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
321 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
322 int use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0;
323
324 if (use_protection != !!ifsta->use_protection) {
325 if (net_ratelimit()) {
326 printk(KERN_DEBUG "%s: CTS protection %s (BSSID="
327 MAC_FMT ")\n",
328 dev->name,
329 use_protection ? "enabled" : "disabled",
330 MAC_ARG(ifsta->bssid));
331 }
332 ifsta->use_protection = use_protection ? 1 : 0;
333 local->cts_protect_erp_frames = use_protection;
334 }
335}
336
337
317static void ieee80211_sta_send_associnfo(struct net_device *dev, 338static void ieee80211_sta_send_associnfo(struct net_device *dev,
318 struct ieee80211_if_sta *ifsta) 339 struct ieee80211_if_sta *ifsta)
319{ 340{
@@ -377,9 +398,18 @@ static void ieee80211_set_associated(struct net_device *dev,
377 398
378 if (assoc) { 399 if (assoc) {
379 struct ieee80211_sub_if_data *sdata; 400 struct ieee80211_sub_if_data *sdata;
401 struct ieee80211_sta_bss *bss;
380 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 402 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
381 if (sdata->type != IEEE80211_IF_TYPE_STA) 403 if (sdata->type != IEEE80211_IF_TYPE_STA)
382 return; 404 return;
405
406 bss = ieee80211_rx_bss_get(dev, ifsta->bssid);
407 if (bss) {
408 if (bss->has_erp_value)
409 ieee80211_handle_erp_ie(dev, bss->erp_value);
410 ieee80211_rx_bss_put(dev, bss);
411 }
412
383 netif_carrier_on(dev); 413 netif_carrier_on(dev);
384 ifsta->prev_bssid_set = 1; 414 ifsta->prev_bssid_set = 1;
385 memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN); 415 memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN);
@@ -1177,6 +1207,18 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
1177 return; 1207 return;
1178 } 1208 }
1179 1209
1210 /* it probably doesn't, but if the frame includes an ERP value then
1211 * update our stored copy */
1212 if (elems.erp_info && elems.erp_info_len >= 1) {
1213 struct ieee80211_sta_bss *bss
1214 = ieee80211_rx_bss_get(dev, ifsta->bssid);
1215 if (bss) {
1216 bss->erp_value = elems.erp_info[0];
1217 bss->has_erp_value = 1;
1218 ieee80211_rx_bss_put(dev, bss);
1219 }
1220 }
1221
1180 printk(KERN_DEBUG "%s: associated\n", dev->name); 1222 printk(KERN_DEBUG "%s: associated\n", dev->name);
1181 ifsta->aid = aid; 1223 ifsta->aid = aid;
1182 ifsta->ap_capab = capab_info; 1224 ifsta->ap_capab = capab_info;
@@ -1499,6 +1541,12 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
1499 return; 1541 return;
1500 } 1542 }
1501 1543
1544 /* save the ERP value so that it is available at association time */
1545 if (elems.erp_info && elems.erp_info_len >= 1) {
1546 bss->erp_value = elems.erp_info[0];
1547 bss->has_erp_value = 1;
1548 }
1549
1502 bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); 1550 bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int);
1503 bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); 1551 bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info);
1504 if (elems.ssid && elems.ssid_len <= IEEE80211_MAX_SSID_LEN) { 1552 if (elems.ssid && elems.ssid_len <= IEEE80211_MAX_SSID_LEN) {
@@ -1614,10 +1662,8 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
1614 size_t len, 1662 size_t len,
1615 struct ieee80211_rx_status *rx_status) 1663 struct ieee80211_rx_status *rx_status)
1616{ 1664{
1617 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
1618 struct ieee80211_sub_if_data *sdata; 1665 struct ieee80211_sub_if_data *sdata;
1619 struct ieee80211_if_sta *ifsta; 1666 struct ieee80211_if_sta *ifsta;
1620 int use_protection;
1621 size_t baselen; 1667 size_t baselen;
1622 struct ieee802_11_elems elems; 1668 struct ieee802_11_elems elems;
1623 1669
@@ -1641,23 +1687,8 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
1641 &elems) == ParseFailed) 1687 &elems) == ParseFailed)
1642 return; 1688 return;
1643 1689
1644 use_protection = 0; 1690 if (elems.erp_info && elems.erp_info_len >= 1)
1645 if (elems.erp_info && elems.erp_info_len >= 1) { 1691 ieee80211_handle_erp_ie(dev, elems.erp_info[0]);
1646 use_protection =
1647 (elems.erp_info[0] & ERP_INFO_USE_PROTECTION) != 0;
1648 }
1649
1650 if (use_protection != !!ifsta->use_protection) {
1651 if (net_ratelimit()) {
1652 printk(KERN_DEBUG "%s: CTS protection %s (BSSID="
1653 MAC_FMT ")\n",
1654 dev->name,
1655 use_protection ? "enabled" : "disabled",
1656 MAC_ARG(ifsta->bssid));
1657 }
1658 ifsta->use_protection = use_protection ? 1 : 0;
1659 local->cts_protect_erp_frames = use_protection;
1660 }
1661 1692
1662 if (elems.wmm_param && ifsta->wmm_enabled) { 1693 if (elems.wmm_param && ifsta->wmm_enabled) {
1663 ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, 1694 ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,