aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/cfg.c
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2011-10-11 15:35:42 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-10-11 15:35:42 -0400
commit094daf7db7c47861009899ce23f9177d761e20b0 (patch)
treea107065393720b80664157a035b206576e834793 /net/mac80211/cfg.c
parent3ed6f6958c0ac21958285d8648f14d34da4bbcb3 (diff)
parent5f68a2b0a890d086e40fc7b55f4a0c32c28bc0d2 (diff)
Merge branch 'master' of git://git.infradead.org/users/linville/wireless-next into for-davem
Conflicts: Documentation/feature-removal-schedule.txt
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r--net/mac80211/cfg.c380
1 files changed, 363 insertions, 17 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 9b1a95e1f56a..55ee5a31756f 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -12,6 +12,7 @@
12#include <linux/slab.h> 12#include <linux/slab.h>
13#include <net/net_namespace.h> 13#include <net/net_namespace.h>
14#include <linux/rcupdate.h> 14#include <linux/rcupdate.h>
15#include <linux/if_ether.h>
15#include <net/cfg80211.h> 16#include <net/cfg80211.h>
16#include "ieee80211_i.h" 17#include "ieee80211_i.h"
17#include "driver-ops.h" 18#include "driver-ops.h"
@@ -667,7 +668,6 @@ static void sta_apply_parameters(struct ieee80211_local *local,
667 struct sta_info *sta, 668 struct sta_info *sta,
668 struct station_parameters *params) 669 struct station_parameters *params)
669{ 670{
670 unsigned long flags;
671 u32 rates; 671 u32 rates;
672 int i, j; 672 int i, j;
673 struct ieee80211_supported_band *sband; 673 struct ieee80211_supported_band *sband;
@@ -676,46 +676,58 @@ static void sta_apply_parameters(struct ieee80211_local *local,
676 676
677 sband = local->hw.wiphy->bands[local->oper_channel->band]; 677 sband = local->hw.wiphy->bands[local->oper_channel->band];
678 678
679 spin_lock_irqsave(&sta->flaglock, flags);
680 mask = params->sta_flags_mask; 679 mask = params->sta_flags_mask;
681 set = params->sta_flags_set; 680 set = params->sta_flags_set;
682 681
683 if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { 682 if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
684 sta->flags &= ~WLAN_STA_AUTHORIZED;
685 if (set & BIT(NL80211_STA_FLAG_AUTHORIZED)) 683 if (set & BIT(NL80211_STA_FLAG_AUTHORIZED))
686 sta->flags |= WLAN_STA_AUTHORIZED; 684 set_sta_flag(sta, WLAN_STA_AUTHORIZED);
685 else
686 clear_sta_flag(sta, WLAN_STA_AUTHORIZED);
687 } 687 }
688 688
689 if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) { 689 if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) {
690 sta->flags &= ~WLAN_STA_SHORT_PREAMBLE;
691 if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) 690 if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE))
692 sta->flags |= WLAN_STA_SHORT_PREAMBLE; 691 set_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE);
692 else
693 clear_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE);
693 } 694 }
694 695
695 if (mask & BIT(NL80211_STA_FLAG_WME)) { 696 if (mask & BIT(NL80211_STA_FLAG_WME)) {
696 sta->flags &= ~WLAN_STA_WME;
697 sta->sta.wme = false;
698 if (set & BIT(NL80211_STA_FLAG_WME)) { 697 if (set & BIT(NL80211_STA_FLAG_WME)) {
699 sta->flags |= WLAN_STA_WME; 698 set_sta_flag(sta, WLAN_STA_WME);
700 sta->sta.wme = true; 699 sta->sta.wme = true;
700 } else {
701 clear_sta_flag(sta, WLAN_STA_WME);
702 sta->sta.wme = false;
701 } 703 }
702 } 704 }
703 705
704 if (mask & BIT(NL80211_STA_FLAG_MFP)) { 706 if (mask & BIT(NL80211_STA_FLAG_MFP)) {
705 sta->flags &= ~WLAN_STA_MFP;
706 if (set & BIT(NL80211_STA_FLAG_MFP)) 707 if (set & BIT(NL80211_STA_FLAG_MFP))
707 sta->flags |= WLAN_STA_MFP; 708 set_sta_flag(sta, WLAN_STA_MFP);
709 else
710 clear_sta_flag(sta, WLAN_STA_MFP);
708 } 711 }
709 712
710 if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) { 713 if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED)) {
711 sta->flags &= ~WLAN_STA_AUTH;
712 if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) 714 if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED))
713 sta->flags |= WLAN_STA_AUTH; 715 set_sta_flag(sta, WLAN_STA_AUTH);
716 else
717 clear_sta_flag(sta, WLAN_STA_AUTH);
714 } 718 }
715 spin_unlock_irqrestore(&sta->flaglock, flags);
716 719
717 sta->sta.uapsd_queues = params->uapsd_queues; 720 if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
718 sta->sta.max_sp = params->max_sp; 721 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER))
722 set_sta_flag(sta, WLAN_STA_TDLS_PEER);
723 else
724 clear_sta_flag(sta, WLAN_STA_TDLS_PEER);
725 }
726
727 if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD) {
728 sta->sta.uapsd_queues = params->uapsd_queues;
729 sta->sta.max_sp = params->max_sp;
730 }
719 731
720 /* 732 /*
721 * cfg80211 validates this (1-2007) and allows setting the AID 733 * cfg80211 validates this (1-2007) and allows setting the AID
@@ -806,10 +818,17 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
806 if (!sta) 818 if (!sta)
807 return -ENOMEM; 819 return -ENOMEM;
808 820
809 sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC; 821 set_sta_flag(sta, WLAN_STA_AUTH);
822 set_sta_flag(sta, WLAN_STA_ASSOC);
810 823
811 sta_apply_parameters(local, sta, params); 824 sta_apply_parameters(local, sta, params);
812 825
826 /* Only TDLS-supporting stations can add TDLS peers */
827 if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) &&
828 !((wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) &&
829 sdata->vif.type == NL80211_IFTYPE_STATION))
830 return -ENOTSUPP;
831
813 rate_control_rate_init(sta); 832 rate_control_rate_init(sta);
814 833
815 layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN || 834 layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
@@ -862,6 +881,14 @@ static int ieee80211_change_station(struct wiphy *wiphy,
862 return -ENOENT; 881 return -ENOENT;
863 } 882 }
864 883
884 /* The TDLS bit cannot be toggled after the STA was added */
885 if ((params->sta_flags_mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) &&
886 !!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) !=
887 !!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) {
888 rcu_read_unlock();
889 return -EINVAL;
890 }
891
865 if (params->vlan && params->vlan != sta->sdata->dev) { 892 if (params->vlan && params->vlan != sta->sdata->dev) {
866 vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan); 893 vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
867 894
@@ -2126,6 +2153,323 @@ static int ieee80211_set_rekey_data(struct wiphy *wiphy,
2126 return 0; 2153 return 0;
2127} 2154}
2128 2155
2156static void ieee80211_tdls_add_ext_capab(struct sk_buff *skb)
2157{
2158 u8 *pos = (void *)skb_put(skb, 7);
2159
2160 *pos++ = WLAN_EID_EXT_CAPABILITY;
2161 *pos++ = 5; /* len */
2162 *pos++ = 0x0;
2163 *pos++ = 0x0;
2164 *pos++ = 0x0;
2165 *pos++ = 0x0;
2166 *pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED;
2167}
2168
2169static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata)
2170{
2171 struct ieee80211_local *local = sdata->local;
2172 u16 capab;
2173
2174 capab = 0;
2175 if (local->oper_channel->band != IEEE80211_BAND_2GHZ)
2176 return capab;
2177
2178 if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
2179 capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
2180 if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE))
2181 capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
2182
2183 return capab;
2184}
2185
2186static void ieee80211_tdls_add_link_ie(struct sk_buff *skb, u8 *src_addr,
2187 u8 *peer, u8 *bssid)
2188{
2189 struct ieee80211_tdls_lnkie *lnkid;
2190
2191 lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie));
2192
2193 lnkid->ie_type = WLAN_EID_LINK_ID;
2194 lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2;
2195
2196 memcpy(lnkid->bssid, bssid, ETH_ALEN);
2197 memcpy(lnkid->init_sta, src_addr, ETH_ALEN);
2198 memcpy(lnkid->resp_sta, peer, ETH_ALEN);
2199}
2200
2201static int
2202ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
2203 u8 *peer, u8 action_code, u8 dialog_token,
2204 u16 status_code, struct sk_buff *skb)
2205{
2206 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
2207 struct ieee80211_tdls_data *tf;
2208
2209 tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
2210
2211 memcpy(tf->da, peer, ETH_ALEN);
2212 memcpy(tf->sa, sdata->vif.addr, ETH_ALEN);
2213 tf->ether_type = cpu_to_be16(ETH_P_TDLS);
2214 tf->payload_type = WLAN_TDLS_SNAP_RFTYPE;
2215
2216 switch (action_code) {
2217 case WLAN_TDLS_SETUP_REQUEST:
2218 tf->category = WLAN_CATEGORY_TDLS;
2219 tf->action_code = WLAN_TDLS_SETUP_REQUEST;
2220
2221 skb_put(skb, sizeof(tf->u.setup_req));
2222 tf->u.setup_req.dialog_token = dialog_token;
2223 tf->u.setup_req.capability =
2224 cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
2225
2226 ieee80211_add_srates_ie(&sdata->vif, skb);
2227 ieee80211_add_ext_srates_ie(&sdata->vif, skb);
2228 ieee80211_tdls_add_ext_capab(skb);
2229 break;
2230 case WLAN_TDLS_SETUP_RESPONSE:
2231 tf->category = WLAN_CATEGORY_TDLS;
2232 tf->action_code = WLAN_TDLS_SETUP_RESPONSE;
2233
2234 skb_put(skb, sizeof(tf->u.setup_resp));
2235 tf->u.setup_resp.status_code = cpu_to_le16(status_code);
2236 tf->u.setup_resp.dialog_token = dialog_token;
2237 tf->u.setup_resp.capability =
2238 cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
2239
2240 ieee80211_add_srates_ie(&sdata->vif, skb);
2241 ieee80211_add_ext_srates_ie(&sdata->vif, skb);
2242 ieee80211_tdls_add_ext_capab(skb);
2243 break;
2244 case WLAN_TDLS_SETUP_CONFIRM:
2245 tf->category = WLAN_CATEGORY_TDLS;
2246 tf->action_code = WLAN_TDLS_SETUP_CONFIRM;
2247
2248 skb_put(skb, sizeof(tf->u.setup_cfm));
2249 tf->u.setup_cfm.status_code = cpu_to_le16(status_code);
2250 tf->u.setup_cfm.dialog_token = dialog_token;
2251 break;
2252 case WLAN_TDLS_TEARDOWN:
2253 tf->category = WLAN_CATEGORY_TDLS;
2254 tf->action_code = WLAN_TDLS_TEARDOWN;
2255
2256 skb_put(skb, sizeof(tf->u.teardown));
2257 tf->u.teardown.reason_code = cpu_to_le16(status_code);
2258 break;
2259 case WLAN_TDLS_DISCOVERY_REQUEST:
2260 tf->category = WLAN_CATEGORY_TDLS;
2261 tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST;
2262
2263 skb_put(skb, sizeof(tf->u.discover_req));
2264 tf->u.discover_req.dialog_token = dialog_token;
2265 break;
2266 default:
2267 return -EINVAL;
2268 }
2269
2270 return 0;
2271}
2272
2273static int
2274ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev,
2275 u8 *peer, u8 action_code, u8 dialog_token,
2276 u16 status_code, struct sk_buff *skb)
2277{
2278 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
2279 struct ieee80211_mgmt *mgmt;
2280
2281 mgmt = (void *)skb_put(skb, 24);
2282 memset(mgmt, 0, 24);
2283 memcpy(mgmt->da, peer, ETH_ALEN);
2284 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
2285 memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
2286
2287 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
2288 IEEE80211_STYPE_ACTION);
2289
2290 switch (action_code) {
2291 case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
2292 skb_put(skb, 1 + sizeof(mgmt->u.action.u.tdls_discover_resp));
2293 mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
2294 mgmt->u.action.u.tdls_discover_resp.action_code =
2295 WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
2296 mgmt->u.action.u.tdls_discover_resp.dialog_token =
2297 dialog_token;
2298 mgmt->u.action.u.tdls_discover_resp.capability =
2299 cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
2300
2301 ieee80211_add_srates_ie(&sdata->vif, skb);
2302 ieee80211_add_ext_srates_ie(&sdata->vif, skb);
2303 ieee80211_tdls_add_ext_capab(skb);
2304 break;
2305 default:
2306 return -EINVAL;
2307 }
2308
2309 return 0;
2310}
2311
2312static int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
2313 u8 *peer, u8 action_code, u8 dialog_token,
2314 u16 status_code, const u8 *extra_ies,
2315 size_t extra_ies_len)
2316{
2317 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
2318 struct ieee80211_local *local = sdata->local;
2319 struct ieee80211_tx_info *info;
2320 struct sk_buff *skb = NULL;
2321 bool send_direct;
2322 int ret;
2323
2324 if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
2325 return -ENOTSUPP;
2326
2327 /* make sure we are in managed mode, and associated */
2328 if (sdata->vif.type != NL80211_IFTYPE_STATION ||
2329 !sdata->u.mgd.associated)
2330 return -EINVAL;
2331
2332#ifdef CONFIG_MAC80211_VERBOSE_TDLS_DEBUG
2333 printk(KERN_DEBUG "TDLS mgmt action %d peer %pM\n", action_code, peer);
2334#endif
2335
2336 skb = dev_alloc_skb(local->hw.extra_tx_headroom +
2337 max(sizeof(struct ieee80211_mgmt),
2338 sizeof(struct ieee80211_tdls_data)) +
2339 50 + /* supported rates */
2340 7 + /* ext capab */
2341 extra_ies_len +
2342 sizeof(struct ieee80211_tdls_lnkie));
2343 if (!skb)
2344 return -ENOMEM;
2345
2346 info = IEEE80211_SKB_CB(skb);
2347 skb_reserve(skb, local->hw.extra_tx_headroom);
2348
2349 switch (action_code) {
2350 case WLAN_TDLS_SETUP_REQUEST:
2351 case WLAN_TDLS_SETUP_RESPONSE:
2352 case WLAN_TDLS_SETUP_CONFIRM:
2353 case WLAN_TDLS_TEARDOWN:
2354 case WLAN_TDLS_DISCOVERY_REQUEST:
2355 ret = ieee80211_prep_tdls_encap_data(wiphy, dev, peer,
2356 action_code, dialog_token,
2357 status_code, skb);
2358 send_direct = false;
2359 break;
2360 case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
2361 ret = ieee80211_prep_tdls_direct(wiphy, dev, peer, action_code,
2362 dialog_token, status_code,
2363 skb);
2364 send_direct = true;
2365 break;
2366 default:
2367 ret = -ENOTSUPP;
2368 break;
2369 }
2370
2371 if (ret < 0)
2372 goto fail;
2373
2374 if (extra_ies_len)
2375 memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len);
2376
2377 /* the TDLS link IE is always added last */
2378 switch (action_code) {
2379 case WLAN_TDLS_SETUP_REQUEST:
2380 case WLAN_TDLS_SETUP_CONFIRM:
2381 case WLAN_TDLS_TEARDOWN:
2382 case WLAN_TDLS_DISCOVERY_REQUEST:
2383 /* we are the initiator */
2384 ieee80211_tdls_add_link_ie(skb, sdata->vif.addr, peer,
2385 sdata->u.mgd.bssid);
2386 break;
2387 case WLAN_TDLS_SETUP_RESPONSE:
2388 case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
2389 /* we are the responder */
2390 ieee80211_tdls_add_link_ie(skb, peer, sdata->vif.addr,
2391 sdata->u.mgd.bssid);
2392 break;
2393 default:
2394 ret = -ENOTSUPP;
2395 goto fail;
2396 }
2397
2398 if (send_direct) {
2399 ieee80211_tx_skb(sdata, skb);
2400 return 0;
2401 }
2402
2403 /*
2404 * According to 802.11z: Setup req/resp are sent in AC_BK, otherwise
2405 * we should default to AC_VI.
2406 */
2407 switch (action_code) {
2408 case WLAN_TDLS_SETUP_REQUEST:
2409 case WLAN_TDLS_SETUP_RESPONSE:
2410 skb_set_queue_mapping(skb, IEEE80211_AC_BK);
2411 skb->priority = 2;
2412 break;
2413 default:
2414 skb_set_queue_mapping(skb, IEEE80211_AC_VI);
2415 skb->priority = 5;
2416 break;
2417 }
2418
2419 /* disable bottom halves when entering the Tx path */
2420 local_bh_disable();
2421 ret = ieee80211_subif_start_xmit(skb, dev);
2422 local_bh_enable();
2423
2424 return ret;
2425
2426fail:
2427 dev_kfree_skb(skb);
2428 return ret;
2429}
2430
2431static int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
2432 u8 *peer, enum nl80211_tdls_operation oper)
2433{
2434 struct sta_info *sta;
2435 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
2436
2437 if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
2438 return -ENOTSUPP;
2439
2440 if (sdata->vif.type != NL80211_IFTYPE_STATION)
2441 return -EINVAL;
2442
2443#ifdef CONFIG_MAC80211_VERBOSE_TDLS_DEBUG
2444 printk(KERN_DEBUG "TDLS oper %d peer %pM\n", oper, peer);
2445#endif
2446
2447 switch (oper) {
2448 case NL80211_TDLS_ENABLE_LINK:
2449 rcu_read_lock();
2450 sta = sta_info_get(sdata, peer);
2451 if (!sta) {
2452 rcu_read_unlock();
2453 return -ENOLINK;
2454 }
2455
2456 set_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH);
2457 rcu_read_unlock();
2458 break;
2459 case NL80211_TDLS_DISABLE_LINK:
2460 return sta_info_destroy_addr(sdata, peer);
2461 case NL80211_TDLS_TEARDOWN:
2462 case NL80211_TDLS_SETUP:
2463 case NL80211_TDLS_DISCOVERY_REQ:
2464 /* We don't support in-driver setup/teardown/discovery */
2465 return -ENOTSUPP;
2466 default:
2467 return -ENOTSUPP;
2468 }
2469
2470 return 0;
2471}
2472
2129struct cfg80211_ops mac80211_config_ops = { 2473struct cfg80211_ops mac80211_config_ops = {
2130 .add_virtual_intf = ieee80211_add_iface, 2474 .add_virtual_intf = ieee80211_add_iface,
2131 .del_virtual_intf = ieee80211_del_iface, 2475 .del_virtual_intf = ieee80211_del_iface,
@@ -2189,4 +2533,6 @@ struct cfg80211_ops mac80211_config_ops = {
2189 .set_ringparam = ieee80211_set_ringparam, 2533 .set_ringparam = ieee80211_set_ringparam,
2190 .get_ringparam = ieee80211_get_ringparam, 2534 .get_ringparam = ieee80211_get_ringparam,
2191 .set_rekey_data = ieee80211_set_rekey_data, 2535 .set_rekey_data = ieee80211_set_rekey_data,
2536 .tdls_oper = ieee80211_tdls_oper,
2537 .tdls_mgmt = ieee80211_tdls_mgmt,
2192}; 2538};