diff options
-rw-r--r-- | include/linux/ieee80211.h | 10 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 78 |
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 | ||
1723 | static 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 | |||
1770 | static 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 | |||
1723 | static void ieee80211_rx_mgmt_auth(struct net_device *dev, | 1788 | static 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: |