mac80211: protect 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.
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>
This commit is contained in:
Arik Nemtsov 2014-06-11 17:18:27 +03:00 committed by Johannes Berg
parent 7adc3e4664
commit ee10f2c779
4 changed files with 44 additions and 1 deletions

View 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,

View 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)
{

View 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,

View 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),