diff options
author | Simon Wunderlich <simon.wunderlich@s2003.tu-chemnitz.de> | 2013-08-28 15:41:31 +0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-09-26 15:27:14 +0400 |
commit | cd7760e62c2ac8581f050b2d36501d1a60beaf83 (patch) | |
tree | 1f4e9fb22e3b952c68c2e055a5381f5f9c5a2f94 /net/mac80211/rx.c | |
parent | 871a4180b8b62dbed54cd203c33bdab7fce24e6f (diff) | |
download | linux-cd7760e62c2ac8581f050b2d36501d1a60beaf83.tar.xz |
mac80211: add support for CSA in IBSS mode
This function adds the channel switch announcement implementation for the
IBSS code. It is triggered by userspace (mac80211/cfg) or by external
channel switch announcement, which have to be adopted. Both CSAs in
beacons and action frames are supported. As for AP mode, the channel
switch is applied after some time. However in IBSS mode, the channel
switch IEs are generated in the kernel.
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Signed-off-by: Mathias Kretschmer <mathias.kretschmer@fokus.fraunhofer.de>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r-- | net/mac80211/rx.c | 36 |
1 files changed, 26 insertions, 10 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 54395d7583ba..8e908e17e248 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2402,7 +2402,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) return RX_DROP_UNUSABLE; if (!rx->sta && mgmt->u.action.category != WLAN_CATEGORY_PUBLIC && - mgmt->u.action.category != WLAN_CATEGORY_SELF_PROTECTED) + mgmt->u.action.category != WLAN_CATEGORY_SELF_PROTECTED && + mgmt->u.action.category != WLAN_CATEGORY_SPECTRUM_MGMT) return RX_DROP_UNUSABLE; if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) @@ -2566,31 +2567,46 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) goto queue; case WLAN_CATEGORY_SPECTRUM_MGMT: - if (status->band != IEEE80211_BAND_5GHZ) - break; - - if (sdata->vif.type != NL80211_IFTYPE_STATION) - break; - /* verify action_code is present */ if (len < IEEE80211_MIN_ACTION_SIZE + 1) break; switch (mgmt->u.action.u.measurement.action_code) { case WLAN_ACTION_SPCT_MSR_REQ: + if (status->band != IEEE80211_BAND_5GHZ) + break; + if (len < (IEEE80211_MIN_ACTION_SIZE + sizeof(mgmt->u.action.u.measurement))) break; + + if (sdata->vif.type != NL80211_IFTYPE_STATION) + break; + ieee80211_process_measurement_req(sdata, mgmt, len); goto handled; - case WLAN_ACTION_SPCT_CHL_SWITCH: - if (sdata->vif.type != NL80211_IFTYPE_STATION) + case WLAN_ACTION_SPCT_CHL_SWITCH: { + u8 *bssid; + if (len < (IEEE80211_MIN_ACTION_SIZE + + sizeof(mgmt->u.action.u.chan_switch))) break; - if (!ether_addr_equal(mgmt->bssid, sdata->u.mgd.bssid)) + if (sdata->vif.type != NL80211_IFTYPE_STATION && + sdata->vif.type != NL80211_IFTYPE_ADHOC) + break; + + if (sdata->vif.type == NL80211_IFTYPE_STATION) + bssid = sdata->u.mgd.bssid; + else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) + bssid = sdata->u.ibss.bssid; + else + break; + + if (!ether_addr_equal(mgmt->bssid, bssid)) break; goto queue; + } } break; case WLAN_CATEGORY_SA_QUERY: |