aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/ieee80211_sta.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/ieee80211_sta.c')
-rw-r--r--net/mac80211/ieee80211_sta.c98
1 files changed, 66 insertions, 32 deletions
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c
index 91b545c144c..ba2bf8f0a34 100644
--- a/net/mac80211/ieee80211_sta.c
+++ b/net/mac80211/ieee80211_sta.c
@@ -76,33 +76,36 @@ static int ieee80211_sta_config_auth(struct net_device *dev,
76 76
77/* Parsed Information Elements */ 77/* Parsed Information Elements */
78struct ieee802_11_elems { 78struct ieee802_11_elems {
79 /* pointers to IEs */
79 u8 *ssid; 80 u8 *ssid;
80 u8 ssid_len;
81 u8 *supp_rates; 81 u8 *supp_rates;
82 u8 supp_rates_len;
83 u8 *fh_params; 82 u8 *fh_params;
84 u8 fh_params_len;
85 u8 *ds_params; 83 u8 *ds_params;
86 u8 ds_params_len;
87 u8 *cf_params; 84 u8 *cf_params;
88 u8 cf_params_len;
89 u8 *tim; 85 u8 *tim;
90 u8 tim_len;
91 u8 *ibss_params; 86 u8 *ibss_params;
92 u8 ibss_params_len;
93 u8 *challenge; 87 u8 *challenge;
94 u8 challenge_len;
95 u8 *wpa; 88 u8 *wpa;
96 u8 wpa_len;
97 u8 *rsn; 89 u8 *rsn;
98 u8 rsn_len;
99 u8 *erp_info; 90 u8 *erp_info;
100 u8 erp_info_len;
101 u8 *ext_supp_rates; 91 u8 *ext_supp_rates;
102 u8 ext_supp_rates_len;
103 u8 *wmm_info; 92 u8 *wmm_info;
104 u8 wmm_info_len;
105 u8 *wmm_param; 93 u8 *wmm_param;
94
95 /* length of them, respectively */
96 u8 ssid_len;
97 u8 supp_rates_len;
98 u8 fh_params_len;
99 u8 ds_params_len;
100 u8 cf_params_len;
101 u8 tim_len;
102 u8 ibss_params_len;
103 u8 challenge_len;
104 u8 wpa_len;
105 u8 rsn_len;
106 u8 erp_info_len;
107 u8 ext_supp_rates_len;
108 u8 wmm_info_len;
106 u8 wmm_param_len; 109 u8 wmm_param_len;
107}; 110};
108 111
@@ -311,6 +314,25 @@ static void ieee80211_sta_wmm_params(struct net_device *dev,
311} 314}
312 315
313 316
317static void ieee80211_handle_erp_ie(struct net_device *dev, u8 erp_value)
318{
319 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
320 struct ieee80211_if_sta *ifsta = &sdata->u.sta;
321 int use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0;
322
323 if (use_protection != sdata->use_protection) {
324 if (net_ratelimit()) {
325 printk(KERN_DEBUG "%s: CTS protection %s (BSSID="
326 MAC_FMT ")\n",
327 dev->name,
328 use_protection ? "enabled" : "disabled",
329 MAC_ARG(ifsta->bssid));
330 }
331 sdata->use_protection = use_protection;
332 }
333}
334
335
314static void ieee80211_sta_send_associnfo(struct net_device *dev, 336static void ieee80211_sta_send_associnfo(struct net_device *dev,
315 struct ieee80211_if_sta *ifsta) 337 struct ieee80211_if_sta *ifsta)
316{ 338{
@@ -366,6 +388,7 @@ static void ieee80211_set_associated(struct net_device *dev,
366 struct ieee80211_if_sta *ifsta, int assoc) 388 struct ieee80211_if_sta *ifsta, int assoc)
367{ 389{
368 union iwreq_data wrqu; 390 union iwreq_data wrqu;
391 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
369 392
370 if (ifsta->associated == assoc) 393 if (ifsta->associated == assoc)
371 return; 394 return;
@@ -374,9 +397,18 @@ static void ieee80211_set_associated(struct net_device *dev,
374 397
375 if (assoc) { 398 if (assoc) {
376 struct ieee80211_sub_if_data *sdata; 399 struct ieee80211_sub_if_data *sdata;
400 struct ieee80211_sta_bss *bss;
377 sdata = IEEE80211_DEV_TO_SUB_IF(dev); 401 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
378 if (sdata->type != IEEE80211_IF_TYPE_STA) 402 if (sdata->type != IEEE80211_IF_TYPE_STA)
379 return; 403 return;
404
405 bss = ieee80211_rx_bss_get(dev, ifsta->bssid);
406 if (bss) {
407 if (bss->has_erp_value)
408 ieee80211_handle_erp_ie(dev, bss->erp_value);
409 ieee80211_rx_bss_put(dev, bss);
410 }
411
380 netif_carrier_on(dev); 412 netif_carrier_on(dev);
381 ifsta->prev_bssid_set = 1; 413 ifsta->prev_bssid_set = 1;
382 memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN); 414 memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN);
@@ -384,6 +416,7 @@ static void ieee80211_set_associated(struct net_device *dev,
384 ieee80211_sta_send_associnfo(dev, ifsta); 416 ieee80211_sta_send_associnfo(dev, ifsta);
385 } else { 417 } else {
386 netif_carrier_off(dev); 418 netif_carrier_off(dev);
419 sdata->use_protection = 0;
387 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); 420 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
388 } 421 }
389 wrqu.ap_addr.sa_family = ARPHRD_ETHER; 422 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
@@ -1174,6 +1207,18 @@ static void ieee80211_rx_mgmt_assoc_resp(struct net_device *dev,
1174 return; 1207 return;
1175 } 1208 }
1176 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
1177 printk(KERN_DEBUG "%s: associated\n", dev->name); 1222 printk(KERN_DEBUG "%s: associated\n", dev->name);
1178 ifsta->aid = aid; 1223 ifsta->aid = aid;
1179 ifsta->ap_capab = capab_info; 1224 ifsta->ap_capab = capab_info;
@@ -1496,6 +1541,12 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
1496 return; 1541 return;
1497 } 1542 }
1498 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
1499 bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int); 1550 bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int);
1500 bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info); 1551 bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info);
1501 if (elems.ssid && elems.ssid_len <= IEEE80211_MAX_SSID_LEN) { 1552 if (elems.ssid && elems.ssid_len <= IEEE80211_MAX_SSID_LEN) {
@@ -1611,10 +1662,8 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
1611 size_t len, 1662 size_t len,
1612 struct ieee80211_rx_status *rx_status) 1663 struct ieee80211_rx_status *rx_status)
1613{ 1664{
1614 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
1615 struct ieee80211_sub_if_data *sdata; 1665 struct ieee80211_sub_if_data *sdata;
1616 struct ieee80211_if_sta *ifsta; 1666 struct ieee80211_if_sta *ifsta;
1617 int use_protection;
1618 size_t baselen; 1667 size_t baselen;
1619 struct ieee802_11_elems elems; 1668 struct ieee802_11_elems elems;
1620 1669
@@ -1638,23 +1687,8 @@ static void ieee80211_rx_mgmt_beacon(struct net_device *dev,
1638 &elems) == ParseFailed) 1687 &elems) == ParseFailed)
1639 return; 1688 return;
1640 1689
1641 use_protection = 0; 1690 if (elems.erp_info && elems.erp_info_len >= 1)
1642 if (elems.erp_info && elems.erp_info_len >= 1) { 1691 ieee80211_handle_erp_ie(dev, elems.erp_info[0]);
1643 use_protection =
1644 (elems.erp_info[0] & ERP_INFO_USE_PROTECTION) != 0;
1645 }
1646
1647 if (use_protection != !!ifsta->use_protection) {
1648 if (net_ratelimit()) {
1649 printk(KERN_DEBUG "%s: CTS protection %s (BSSID="
1650 MAC_FMT ")\n",
1651 dev->name,
1652 use_protection ? "enabled" : "disabled",
1653 MAC_ARG(ifsta->bssid));
1654 }
1655 ifsta->use_protection = use_protection ? 1 : 0;
1656 local->cts_protect_erp_frames = use_protection;
1657 }
1658 1692
1659 if (elems.wmm_param && ifsta->wmm_enabled) { 1693 if (elems.wmm_param && ifsta->wmm_enabled) {
1660 ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param, 1694 ieee80211_sta_wmm_params(dev, ifsta, elems.wmm_param,