aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/cfg.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-11-04 06:18:16 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-11-09 16:13:46 -0500
commit06500736c5d26bff93a4f358713689073e66d0f5 (patch)
tree809fb3df5a058e5cedf276e75c25d033405602b3 /net/mac80211/cfg.c
parent7f6cf311a594c1e7ca8120367dd1d4c685aabff1 (diff)
mac80211: support client probe
Support probing clients with null data frames in AP mode. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r--net/mac80211/cfg.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 1f1056172ef1..e072fea69a30 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2507,6 +2507,73 @@ static int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
2507 return 0; 2507 return 0;
2508} 2508}
2509 2509
2510static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
2511 const u8 *peer, u64 *cookie)
2512{
2513 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
2514 struct ieee80211_local *local = sdata->local;
2515 struct ieee80211_qos_hdr *nullfunc;
2516 struct sk_buff *skb;
2517 int size = sizeof(*nullfunc);
2518 __le16 fc;
2519 bool qos;
2520 struct ieee80211_tx_info *info;
2521 struct sta_info *sta;
2522
2523 rcu_read_lock();
2524 sta = sta_info_get(sdata, peer);
2525 if (sta)
2526 qos = test_sta_flag(sta, WLAN_STA_WME);
2527 rcu_read_unlock();
2528
2529 if (!sta)
2530 return -ENOLINK;
2531
2532 if (qos) {
2533 fc = cpu_to_le16(IEEE80211_FTYPE_DATA |
2534 IEEE80211_STYPE_QOS_NULLFUNC |
2535 IEEE80211_FCTL_FROMDS);
2536 } else {
2537 size -= 2;
2538 fc = cpu_to_le16(IEEE80211_FTYPE_DATA |
2539 IEEE80211_STYPE_NULLFUNC |
2540 IEEE80211_FCTL_FROMDS);
2541 }
2542
2543 skb = dev_alloc_skb(local->hw.extra_tx_headroom + size);
2544 if (!skb)
2545 return -ENOMEM;
2546
2547 skb->dev = dev;
2548
2549 skb_reserve(skb, local->hw.extra_tx_headroom);
2550
2551 nullfunc = (void *) skb_put(skb, size);
2552 nullfunc->frame_control = fc;
2553 nullfunc->duration_id = 0;
2554 memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN);
2555 memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN);
2556 memcpy(nullfunc->addr3, sdata->vif.addr, ETH_ALEN);
2557 nullfunc->seq_ctrl = 0;
2558
2559 info = IEEE80211_SKB_CB(skb);
2560
2561 info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS |
2562 IEEE80211_TX_INTFL_NL80211_FRAME_TX;
2563
2564 skb_set_queue_mapping(skb, IEEE80211_AC_VO);
2565 skb->priority = 7;
2566 if (qos)
2567 nullfunc->qos_ctrl = cpu_to_le16(7);
2568
2569 local_bh_disable();
2570 ieee80211_xmit(sdata, skb);
2571 local_bh_enable();
2572
2573 *cookie = (unsigned long) skb;
2574 return 0;
2575}
2576
2510struct cfg80211_ops mac80211_config_ops = { 2577struct cfg80211_ops mac80211_config_ops = {
2511 .add_virtual_intf = ieee80211_add_iface, 2578 .add_virtual_intf = ieee80211_add_iface,
2512 .del_virtual_intf = ieee80211_del_iface, 2579 .del_virtual_intf = ieee80211_del_iface,
@@ -2572,4 +2639,5 @@ struct cfg80211_ops mac80211_config_ops = {
2572 .set_rekey_data = ieee80211_set_rekey_data, 2639 .set_rekey_data = ieee80211_set_rekey_data,
2573 .tdls_oper = ieee80211_tdls_oper, 2640 .tdls_oper = ieee80211_tdls_oper,
2574 .tdls_mgmt = ieee80211_tdls_mgmt, 2641 .tdls_mgmt = ieee80211_tdls_mgmt,
2642 .probe_client = ieee80211_probe_client,
2575}; 2643};