diff options
author | Assaf Krauss <assaf.krauss@intel.com> | 2008-06-16 09:09:49 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2008-06-26 16:49:14 -0400 |
commit | b662348662f9661f9259c7186c1bdb65620045f1 (patch) | |
tree | 3010967b8be537cf0743ed2f0f872140f5f8011a /net/mac80211 | |
parent | f2df38596a81b6c24f4586b0b4befeaebf3e02db (diff) |
mac80211: 11h - Handling measurement request
This patch handles the 11h measurement request information element.
This is minimal requested implementation - refuse measurement.
Signed-off-by: Assaf Krauss <assaf.krauss@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/mlme.c | 78 |
1 files changed, 78 insertions, 0 deletions
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: |