aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/ieee80211.h10
-rw-r--r--net/mac80211/mlme.c78
2 files changed, 88 insertions, 0 deletions
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 8546f09e462c..cffd6d0094f9 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -739,11 +739,21 @@ struct ieee80211_ht_addt_info {
739#define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5) 739#define WLAN_CAPABILITY_SHORT_PREAMBLE (1<<5)
740#define WLAN_CAPABILITY_PBCC (1<<6) 740#define WLAN_CAPABILITY_PBCC (1<<6)
741#define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7) 741#define WLAN_CAPABILITY_CHANNEL_AGILITY (1<<7)
742
742/* 802.11h */ 743/* 802.11h */
743#define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8) 744#define WLAN_CAPABILITY_SPECTRUM_MGMT (1<<8)
744#define WLAN_CAPABILITY_QOS (1<<9) 745#define WLAN_CAPABILITY_QOS (1<<9)
745#define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10) 746#define WLAN_CAPABILITY_SHORT_SLOT_TIME (1<<10)
746#define WLAN_CAPABILITY_DSSS_OFDM (1<<13) 747#define WLAN_CAPABILITY_DSSS_OFDM (1<<13)
748/* measurement */
749#define IEEE80211_SPCT_MSR_RPRT_MODE_LATE (1<<0)
750#define IEEE80211_SPCT_MSR_RPRT_MODE_INCAPABLE (1<<1)
751#define IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED (1<<2)
752
753#define IEEE80211_SPCT_MSR_RPRT_TYPE_BASIC 0
754#define IEEE80211_SPCT_MSR_RPRT_TYPE_CCA 1
755#define IEEE80211_SPCT_MSR_RPRT_TYPE_RPI 2
756
747 757
748/* 802.11g ERP information element */ 758/* 802.11g ERP information element */
749#define WLAN_ERP_NON_ERP_PRESENT (1<<0) 759#define WLAN_ERP_NON_ERP_PRESENT (1<<0)
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 32453561fe32..6d9a4facf9dd 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1720,6 +1720,71 @@ void ieee80211_sta_tear_down_BA_sessions(struct net_device *dev, u8 *addr)
1720 } 1720 }
1721} 1721}
1722 1722
1723static void ieee80211_send_refuse_measurement_request(struct net_device *dev,
1724 struct ieee80211_msrment_ie *request_ie,
1725 const u8 *da, const u8 *bssid,
1726 u8 dialog_token)
1727{
1728 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
1729 struct sk_buff *skb;
1730 struct ieee80211_mgmt *msr_report;
1731
1732 skb = dev_alloc_skb(sizeof(*msr_report) + local->hw.extra_tx_headroom +
1733 sizeof(struct ieee80211_msrment_ie));
1734
1735 if (!skb) {
1736 printk(KERN_ERR "%s: failed to allocate buffer for "
1737 "measurement report frame\n", dev->name);
1738 return;
1739 }
1740
1741 skb_reserve(skb, local->hw.extra_tx_headroom);
1742 msr_report = (struct ieee80211_mgmt *)skb_put(skb, 24);
1743 memset(msr_report, 0, 24);
1744 memcpy(msr_report->da, da, ETH_ALEN);
1745 memcpy(msr_report->sa, dev->dev_addr, ETH_ALEN);
1746 memcpy(msr_report->bssid, bssid, ETH_ALEN);
1747 msr_report->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
1748 IEEE80211_STYPE_ACTION);
1749
1750 skb_put(skb, 1 + sizeof(msr_report->u.action.u.measurement));
1751 msr_report->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT;
1752 msr_report->u.action.u.measurement.action_code =
1753 WLAN_ACTION_SPCT_MSR_RPRT;
1754 msr_report->u.action.u.measurement.dialog_token = dialog_token;
1755
1756 msr_report->u.action.u.measurement.element_id = WLAN_EID_MEASURE_REPORT;
1757 msr_report->u.action.u.measurement.length =
1758 sizeof(struct ieee80211_msrment_ie);
1759
1760 memset(&msr_report->u.action.u.measurement.msr_elem, 0,
1761 sizeof(struct ieee80211_msrment_ie));
1762 msr_report->u.action.u.measurement.msr_elem.token = request_ie->token;
1763 msr_report->u.action.u.measurement.msr_elem.mode |=
1764 IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED;
1765 msr_report->u.action.u.measurement.msr_elem.type = request_ie->type;
1766
1767 ieee80211_sta_tx(dev, skb, 0);
1768}
1769
1770static void ieee80211_sta_process_measurement_req(struct net_device *dev,
1771 struct ieee80211_mgmt *mgmt,
1772 size_t len)
1773{
1774 /*
1775 * Ignoring measurement request is spec violation.
1776 * Mandatory measurements must be reported optional
1777 * measurements might be refused or reported incapable
1778 * For now just refuse
1779 * TODO: Answer basic measurement as unmeasured
1780 */
1781 ieee80211_send_refuse_measurement_request(dev,
1782 &mgmt->u.action.u.measurement.msr_elem,
1783 mgmt->sa, mgmt->bssid,
1784 mgmt->u.action.u.measurement.dialog_token);
1785}
1786
1787
1723static void ieee80211_rx_mgmt_auth(struct net_device *dev, 1788static void ieee80211_rx_mgmt_auth(struct net_device *dev,
1724 struct ieee80211_if_sta *ifsta, 1789 struct ieee80211_if_sta *ifsta,
1725 struct ieee80211_mgmt *mgmt, 1790 struct ieee80211_mgmt *mgmt,
@@ -3044,11 +3109,24 @@ static void ieee80211_rx_mgmt_action(struct net_device *dev,
3044 struct ieee80211_rx_status *rx_status) 3109 struct ieee80211_rx_status *rx_status)
3045{ 3110{
3046 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); 3111 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
3112 struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
3047 3113
3048 if (len < IEEE80211_MIN_ACTION_SIZE) 3114 if (len < IEEE80211_MIN_ACTION_SIZE)
3049 return; 3115 return;
3050 3116
3051 switch (mgmt->u.action.category) { 3117 switch (mgmt->u.action.category) {
3118 case WLAN_CATEGORY_SPECTRUM_MGMT:
3119 if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ)
3120 break;
3121 switch (mgmt->u.action.u.chan_switch.action_code) {
3122 case WLAN_ACTION_SPCT_MSR_REQ:
3123 if (len < (IEEE80211_MIN_ACTION_SIZE +
3124 sizeof(mgmt->u.action.u.measurement)))
3125 break;
3126 ieee80211_sta_process_measurement_req(dev, mgmt, len);
3127 break;
3128 }
3129 break;
3052 case WLAN_CATEGORY_BACK: 3130 case WLAN_CATEGORY_BACK:
3053 switch (mgmt->u.action.u.addba_req.action_code) { 3131 switch (mgmt->u.action.u.addba_req.action_code) {
3054 case WLAN_ACTION_ADDBA_REQ: 3132 case WLAN_ACTION_ADDBA_REQ: