diff options
Diffstat (limited to 'net/mac80211/ieee80211_sta.c')
-rw-r--r-- | net/mac80211/ieee80211_sta.c | 98 |
1 files changed, 66 insertions, 32 deletions
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index 91b545c144c1..ba2bf8f0a347 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 */ |
78 | struct ieee802_11_elems { | 78 | struct 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 | ||
317 | static 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 | |||
314 | static void ieee80211_sta_send_associnfo(struct net_device *dev, | 336 | static 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, |