139192c0bSJohannes Berg /* 239192c0bSJohannes Berg * spectrum management 339192c0bSJohannes Berg * 439192c0bSJohannes Berg * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi> 539192c0bSJohannes Berg * Copyright 2002-2005, Instant802 Networks, Inc. 639192c0bSJohannes Berg * Copyright 2005-2006, Devicescape Software, Inc. 739192c0bSJohannes Berg * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 839192c0bSJohannes Berg * Copyright 2007, Michael Wu <flamingice@sourmilk.net> 939192c0bSJohannes Berg * Copyright 2007-2008, Intel Corporation 1039192c0bSJohannes Berg * Copyright 2008, Johannes Berg <johannes@sipsolutions.net> 1139192c0bSJohannes Berg * 1239192c0bSJohannes Berg * This program is free software; you can redistribute it and/or modify 1339192c0bSJohannes Berg * it under the terms of the GNU General Public License version 2 as 1439192c0bSJohannes Berg * published by the Free Software Foundation. 1539192c0bSJohannes Berg */ 1639192c0bSJohannes Berg 1739192c0bSJohannes Berg #include <linux/ieee80211.h> 18d3236553SJohannes Berg #include <net/cfg80211.h> 1939192c0bSJohannes Berg #include <net/mac80211.h> 2039192c0bSJohannes Berg #include "ieee80211_i.h" 2139192c0bSJohannes Berg #include "sta_info.h" 2239192c0bSJohannes Berg #include "wme.h" 2339192c0bSJohannes Berg 2439192c0bSJohannes Berg static void ieee80211_send_refuse_measurement_request(struct ieee80211_sub_if_data *sdata, 2539192c0bSJohannes Berg struct ieee80211_msrment_ie *request_ie, 2639192c0bSJohannes Berg const u8 *da, const u8 *bssid, 2739192c0bSJohannes Berg u8 dialog_token) 2839192c0bSJohannes Berg { 2939192c0bSJohannes Berg struct ieee80211_local *local = sdata->local; 3039192c0bSJohannes Berg struct sk_buff *skb; 3139192c0bSJohannes Berg struct ieee80211_mgmt *msr_report; 3239192c0bSJohannes Berg 3339192c0bSJohannes Berg skb = dev_alloc_skb(sizeof(*msr_report) + local->hw.extra_tx_headroom + 3439192c0bSJohannes Berg sizeof(struct ieee80211_msrment_ie)); 35d15b8459SJoe Perches if (!skb) 3639192c0bSJohannes Berg return; 3739192c0bSJohannes Berg 3839192c0bSJohannes Berg skb_reserve(skb, local->hw.extra_tx_headroom); 3939192c0bSJohannes Berg msr_report = (struct ieee80211_mgmt *)skb_put(skb, 24); 4039192c0bSJohannes Berg memset(msr_report, 0, 24); 4139192c0bSJohannes Berg memcpy(msr_report->da, da, ETH_ALEN); 4247846c9bSJohannes Berg memcpy(msr_report->sa, sdata->vif.addr, ETH_ALEN); 4339192c0bSJohannes Berg memcpy(msr_report->bssid, bssid, ETH_ALEN); 4439192c0bSJohannes Berg msr_report->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 4539192c0bSJohannes Berg IEEE80211_STYPE_ACTION); 4639192c0bSJohannes Berg 4739192c0bSJohannes Berg skb_put(skb, 1 + sizeof(msr_report->u.action.u.measurement)); 4839192c0bSJohannes Berg msr_report->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT; 4939192c0bSJohannes Berg msr_report->u.action.u.measurement.action_code = 5039192c0bSJohannes Berg WLAN_ACTION_SPCT_MSR_RPRT; 5139192c0bSJohannes Berg msr_report->u.action.u.measurement.dialog_token = dialog_token; 5239192c0bSJohannes Berg 5339192c0bSJohannes Berg msr_report->u.action.u.measurement.element_id = WLAN_EID_MEASURE_REPORT; 5439192c0bSJohannes Berg msr_report->u.action.u.measurement.length = 5539192c0bSJohannes Berg sizeof(struct ieee80211_msrment_ie); 5639192c0bSJohannes Berg 5739192c0bSJohannes Berg memset(&msr_report->u.action.u.measurement.msr_elem, 0, 5839192c0bSJohannes Berg sizeof(struct ieee80211_msrment_ie)); 5939192c0bSJohannes Berg msr_report->u.action.u.measurement.msr_elem.token = request_ie->token; 6039192c0bSJohannes Berg msr_report->u.action.u.measurement.msr_elem.mode |= 6139192c0bSJohannes Berg IEEE80211_SPCT_MSR_RPRT_MODE_REFUSED; 6239192c0bSJohannes Berg msr_report->u.action.u.measurement.msr_elem.type = request_ie->type; 6339192c0bSJohannes Berg 6462ae67beSJohannes Berg ieee80211_tx_skb(sdata, skb); 6539192c0bSJohannes Berg } 6639192c0bSJohannes Berg 6739192c0bSJohannes Berg void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata, 6839192c0bSJohannes Berg struct ieee80211_mgmt *mgmt, 6939192c0bSJohannes Berg size_t len) 7039192c0bSJohannes Berg { 7139192c0bSJohannes Berg /* 7239192c0bSJohannes Berg * Ignoring measurement request is spec violation. 7339192c0bSJohannes Berg * Mandatory measurements must be reported optional 7439192c0bSJohannes Berg * measurements might be refused or reported incapable 7539192c0bSJohannes Berg * For now just refuse 7639192c0bSJohannes Berg * TODO: Answer basic measurement as unmeasured 7739192c0bSJohannes Berg */ 7839192c0bSJohannes Berg ieee80211_send_refuse_measurement_request(sdata, 7939192c0bSJohannes Berg &mgmt->u.action.u.measurement.msr_elem, 8039192c0bSJohannes Berg mgmt->sa, mgmt->bssid, 8139192c0bSJohannes Berg mgmt->u.action.u.measurement.dialog_token); 8239192c0bSJohannes Berg } 83