aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2014-06-12 16:24:31 -0400
committerJohannes Berg <johannes.berg@intel.com>2014-11-19 12:46:09 -0500
commita344d6778a98e4c19ac871f369e399e6356edcb3 (patch)
tree57680bfd10fc013c7a996fbea7212be900f089db /net
parent6ea0a69ca21bbddab5b3979c2190013b0263e749 (diff)
mac80211: allow drivers to support NL80211_SCAN_FLAG_RANDOM_ADDR
Allow drivers to support NL80211_SCAN_FLAG_RANDOM_ADDR with software based scanning and generate a random MAC address for them for every scan request with the flag. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/driver-ops.h15
-rw-r--r--net/mac80211/ieee80211_i.h7
-rw-r--r--net/mac80211/mlme.c8
-rw-r--r--net/mac80211/scan.c48
-rw-r--r--net/mac80211/trace.h31
-rw-r--r--net/mac80211/tx.c9
-rw-r--r--net/mac80211/util.c12
7 files changed, 92 insertions, 38 deletions
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index ba0d2cb5df12..5f5fc3f3ee7c 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -380,23 +380,26 @@ static inline int drv_sched_scan_stop(struct ieee80211_local *local,
380 return ret; 380 return ret;
381} 381}
382 382
383static inline void drv_sw_scan_start(struct ieee80211_local *local) 383static inline void drv_sw_scan_start(struct ieee80211_local *local,
384 struct ieee80211_sub_if_data *sdata,
385 const u8 *mac_addr)
384{ 386{
385 might_sleep(); 387 might_sleep();
386 388
387 trace_drv_sw_scan_start(local); 389 trace_drv_sw_scan_start(local, sdata, mac_addr);
388 if (local->ops->sw_scan_start) 390 if (local->ops->sw_scan_start)
389 local->ops->sw_scan_start(&local->hw); 391 local->ops->sw_scan_start(&local->hw, &sdata->vif, mac_addr);
390 trace_drv_return_void(local); 392 trace_drv_return_void(local);
391} 393}
392 394
393static inline void drv_sw_scan_complete(struct ieee80211_local *local) 395static inline void drv_sw_scan_complete(struct ieee80211_local *local,
396 struct ieee80211_sub_if_data *sdata)
394{ 397{
395 might_sleep(); 398 might_sleep();
396 399
397 trace_drv_sw_scan_complete(local); 400 trace_drv_sw_scan_complete(local, sdata);
398 if (local->ops->sw_scan_complete) 401 if (local->ops->sw_scan_complete)
399 local->ops->sw_scan_complete(&local->hw); 402 local->ops->sw_scan_complete(&local->hw, &sdata->vif);
400 trace_drv_return_void(local); 403 trace_drv_return_void(local);
401} 404}
402 405
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index dd27180060b9..cf95d033bcbf 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1249,6 +1249,7 @@ struct ieee80211_local {
1249 struct work_struct sched_scan_stopped_work; 1249 struct work_struct sched_scan_stopped_work;
1250 struct ieee80211_sub_if_data __rcu *sched_scan_sdata; 1250 struct ieee80211_sub_if_data __rcu *sched_scan_sdata;
1251 struct cfg80211_sched_scan_request __rcu *sched_scan_req; 1251 struct cfg80211_sched_scan_request __rcu *sched_scan_req;
1252 u8 scan_addr[ETH_ALEN];
1252 1253
1253 unsigned long leave_oper_channel_time; 1254 unsigned long leave_oper_channel_time;
1254 enum mac80211_scan_state next_scan_state; 1255 enum mac80211_scan_state next_scan_state;
@@ -1901,12 +1902,14 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
1901 u8 bands_used, u32 *rate_masks, 1902 u8 bands_used, u32 *rate_masks,
1902 struct cfg80211_chan_def *chandef); 1903 struct cfg80211_chan_def *chandef);
1903struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, 1904struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
1904 u8 *dst, u32 ratemask, 1905 const u8 *src, const u8 *dst,
1906 u32 ratemask,
1905 struct ieee80211_channel *chan, 1907 struct ieee80211_channel *chan,
1906 const u8 *ssid, size_t ssid_len, 1908 const u8 *ssid, size_t ssid_len,
1907 const u8 *ie, size_t ie_len, 1909 const u8 *ie, size_t ie_len,
1908 bool directed); 1910 bool directed);
1909void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, 1911void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata,
1912 const u8 *src, const u8 *dst,
1910 const u8 *ssid, size_t ssid_len, 1913 const u8 *ssid, size_t ssid_len,
1911 const u8 *ie, size_t ie_len, 1914 const u8 *ie, size_t ie_len,
1912 u32 ratemask, bool directed, u32 tx_flags, 1915 u32 ratemask, bool directed, u32 tx_flags,
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 45490a202d9c..d29589a09065 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2225,7 +2225,8 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
2225 else 2225 else
2226 ssid_len = ssid[1]; 2226 ssid_len = ssid[1];
2227 2227
2228 ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL, 2228 ieee80211_send_probe_req(sdata, sdata->vif.addr, NULL,
2229 ssid + 2, ssid_len, NULL,
2229 0, (u32) -1, true, 0, 2230 0, (u32) -1, true, 0,
2230 ifmgd->associated->channel, false); 2231 ifmgd->associated->channel, false);
2231 rcu_read_unlock(); 2232 rcu_read_unlock();
@@ -2328,7 +2329,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
2328 else 2329 else
2329 ssid_len = ssid[1]; 2330 ssid_len = ssid[1];
2330 2331
2331 skb = ieee80211_build_probe_req(sdata, cbss->bssid, 2332 skb = ieee80211_build_probe_req(sdata, sdata->vif.addr, cbss->bssid,
2332 (u32) -1, cbss->channel, 2333 (u32) -1, cbss->channel,
2333 ssid + 2, ssid_len, 2334 ssid + 2, ssid_len,
2334 NULL, 0, true); 2335 NULL, 0, true);
@@ -3649,7 +3650,8 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
3649 * Direct probe is sent to broadcast address as some APs 3650 * Direct probe is sent to broadcast address as some APs
3650 * will not answer to direct packet in unassociated state. 3651 * will not answer to direct packet in unassociated state.
3651 */ 3652 */
3652 ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1], 3653 ieee80211_send_probe_req(sdata, sdata->vif.addr, NULL,
3654 ssidie + 2, ssidie[1],
3653 NULL, 0, (u32) -1, true, 0, 3655 NULL, 0, (u32) -1, true, 0,
3654 auth_data->bss->channel, false); 3656 auth_data->bss->channel, false);
3655 rcu_read_unlock(); 3657 rcu_read_unlock();
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index e75e64b8042c..ae842678b629 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -184,9 +184,21 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
184 return; 184 return;
185 185
186 if (ieee80211_is_probe_resp(mgmt->frame_control)) { 186 if (ieee80211_is_probe_resp(mgmt->frame_control)) {
187 /* ignore ProbeResp to foreign address */ 187 struct cfg80211_scan_request *scan_req;
188 if ((!sdata1 || !ether_addr_equal(mgmt->da, sdata1->vif.addr)) && 188 struct cfg80211_sched_scan_request *sched_scan_req;
189 (!sdata2 || !ether_addr_equal(mgmt->da, sdata2->vif.addr))) 189
190 scan_req = rcu_dereference(local->scan_req);
191 sched_scan_req = rcu_dereference(local->sched_scan_req);
192
193 /* ignore ProbeResp to foreign address unless scanning
194 * with randomised address
195 */
196 if (!(sdata1 &&
197 (ether_addr_equal(mgmt->da, sdata1->vif.addr) ||
198 scan_req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)) &&
199 !(sdata2 &&
200 (ether_addr_equal(mgmt->da, sdata2->vif.addr) ||
201 sched_scan_req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)))
190 return; 202 return;
191 203
192 elements = mgmt->u.probe_resp.variable; 204 elements = mgmt->u.probe_resp.variable;
@@ -284,6 +296,9 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
284 bands_used, req->rates, &chandef); 296 bands_used, req->rates, &chandef);
285 local->hw_scan_req->req.ie_len = ielen; 297 local->hw_scan_req->req.ie_len = ielen;
286 local->hw_scan_req->req.no_cck = req->no_cck; 298 local->hw_scan_req->req.no_cck = req->no_cck;
299 ether_addr_copy(local->hw_scan_req->req.mac_addr, req->mac_addr);
300 ether_addr_copy(local->hw_scan_req->req.mac_addr_mask,
301 req->mac_addr_mask);
287 302
288 return true; 303 return true;
289} 304}
@@ -294,6 +309,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
294 bool hw_scan = local->ops->hw_scan; 309 bool hw_scan = local->ops->hw_scan;
295 bool was_scanning = local->scanning; 310 bool was_scanning = local->scanning;
296 struct cfg80211_scan_request *scan_req; 311 struct cfg80211_scan_request *scan_req;
312 struct ieee80211_sub_if_data *scan_sdata;
297 313
298 lockdep_assert_held(&local->mtx); 314 lockdep_assert_held(&local->mtx);
299 315
@@ -332,6 +348,9 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
332 if (scan_req != local->int_scan_req) 348 if (scan_req != local->int_scan_req)
333 cfg80211_scan_done(scan_req, aborted); 349 cfg80211_scan_done(scan_req, aborted);
334 RCU_INIT_POINTER(local->scan_req, NULL); 350 RCU_INIT_POINTER(local->scan_req, NULL);
351
352 scan_sdata = rcu_dereference_protected(local->scan_sdata,
353 lockdep_is_held(&local->mtx));
335 RCU_INIT_POINTER(local->scan_sdata, NULL); 354 RCU_INIT_POINTER(local->scan_sdata, NULL);
336 355
337 local->scanning = 0; 356 local->scanning = 0;
@@ -342,7 +361,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
342 361
343 if (!hw_scan) { 362 if (!hw_scan) {
344 ieee80211_configure_filter(local); 363 ieee80211_configure_filter(local);
345 drv_sw_scan_complete(local); 364 drv_sw_scan_complete(local, scan_sdata);
346 ieee80211_offchannel_return(local); 365 ieee80211_offchannel_return(local);
347 } 366 }
348 367
@@ -368,7 +387,8 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
368} 387}
369EXPORT_SYMBOL(ieee80211_scan_complete