mac80211: protect TDLS discovery session
authorArik Nemtsov <arik@wizery.com>
Wed, 11 Jun 2014 14:18:27 +0000 (17:18 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 23 Jun 2014 12:28:19 +0000 (14:28 +0200)
After sending a TDLS discovery-request, we expect a reply to arrive on
the AP's channel. We must stay on the channel (no PSM, scan, etc.), since
a TDLS setup-response is a direct packet not buffered by the AP.
Add a new mac80211 driver callback to allow discovery session protection.

Signed-off-by: Arik Nemtsov <arikx.nemtsov@intel.com>
Reviewed-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/mac80211.h
net/mac80211/driver-ops.h
net/mac80211/tdls.c
net/mac80211/trace.h

index 8d876dc8b29935e4dd9020401f05b7113505a758..18c2bdbaf9882a5180961a61892860e59321385e 100644 (file)
@@ -2764,6 +2764,15 @@ enum ieee80211_roc_type {
  *     mac80211 will transmit the frame right away.
  *     The callback is optional and can (should!) sleep.
  *
+ * @mgd_protect_tdls_discover: Protect a TDLS discovery session. After sending
+ *     a TDLS discovery-request, we expect a reply to arrive on the AP's
+ *     channel. We must stay on the channel (no PSM, scan, etc.), since a TDLS
+ *     setup-response is a direct packet not buffered by the AP.
+ *     mac80211 will call this function just before the transmission of a TDLS
+ *     discovery-request. The recommended period of protection is at least
+ *     2 * (DTIM period).
+ *     The callback is optional and can sleep.
+ *
  * @add_chanctx: Notifies device driver about new channel context creation.
  * @remove_chanctx: Notifies device driver about channel context destruction.
  * @change_chanctx: Notifies device driver about channel context changes that
@@ -2981,6 +2990,9 @@ struct ieee80211_ops {
        void    (*mgd_prepare_tx)(struct ieee80211_hw *hw,
                                  struct ieee80211_vif *vif);
 
+       void    (*mgd_protect_tdls_discover)(struct ieee80211_hw *hw,
+                                            struct ieee80211_vif *vif);
+
        int (*add_chanctx)(struct ieee80211_hw *hw,
                           struct ieee80211_chanctx_conf *ctx);
        void (*remove_chanctx)(struct ieee80211_hw *hw,
index bd782dcffcc7b81478277bcb2b5545dfef545da8..2265bd7a44baed60084ad685b7ca7894c51c4fb1 100644 (file)
@@ -970,6 +970,22 @@ static inline void drv_mgd_prepare_tx(struct ieee80211_local *local,
        trace_drv_return_void(local);
 }
 
+static inline void
+drv_mgd_protect_tdls_discover(struct ieee80211_local *local,
+                             struct ieee80211_sub_if_data *sdata)
+{
+       might_sleep();
+
+       if (!check_sdata_in_driver(sdata))
+               return;
+       WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION);
+
+       trace_drv_mgd_protect_tdls_discover(local, sdata);
+       if (local->ops->mgd_protect_tdls_discover)
+               local->ops->mgd_protect_tdls_discover(&local->hw, &sdata->vif);
+       trace_drv_return_void(local);
+}
+
 static inline int drv_add_chanctx(struct ieee80211_local *local,
                                  struct ieee80211_chanctx *ctx)
 {
index b87e369561f420ac5adc1e23b7a7594c25543165..f7185338a0fad33508f17837041cbdb2c2d90d68 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/ieee80211.h>
 #include <net/cfg80211.h>
 #include "ieee80211_i.h"
+#include "driver-ops.h"
 
 /* give usermode some time for retries in setting up the TDLS session */
 #define TDLS_PEER_SETUP_TIMEOUT        (15 * HZ)
@@ -442,8 +443,15 @@ int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
                                                   peer_capability, initiator,
                                                   extra_ies, extra_ies_len);
                break;
-       case WLAN_TDLS_SETUP_CONFIRM:
        case WLAN_TDLS_DISCOVERY_REQUEST:
+               /*
+                * Protect the discovery so we can hear the TDLS discovery
+                * response frame. It is transmitted directly and not buffered
+                * by the AP.
+                */
+               drv_mgd_protect_tdls_discover(sdata->local, sdata);
+               /* fall-through */
+       case WLAN_TDLS_SETUP_CONFIRM:
        case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
                /* no special handling */
                ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer,
index cfe1a0688b5ce2846eb906b3f196c5cf51a4590b..02ac535d1274217653e2f9a48c6f6e60ed6d0927 100644 (file)
@@ -1330,6 +1330,13 @@ DEFINE_EVENT(local_sdata_evt, drv_mgd_prepare_tx,
        TP_ARGS(local, sdata)
 );
 
+DEFINE_EVENT(local_sdata_evt, drv_mgd_protect_tdls_discover,
+       TP_PROTO(struct ieee80211_local *local,
+                struct ieee80211_sub_if_data *sdata),
+
+       TP_ARGS(local, sdata)
+);
+
 DECLARE_EVENT_CLASS(local_chanctx,
        TP_PROTO(struct ieee80211_local *local,
                 struct ieee80211_chanctx *ctx),