diff options
| author | Johannes Berg <johannes.berg@intel.com> | 2014-06-12 16:24:31 -0400 |
|---|---|---|
| committer | Johannes Berg <johannes.berg@intel.com> | 2014-11-19 12:46:09 -0500 |
| commit | a344d6778a98e4c19ac871f369e399e6356edcb3 (patch) | |
| tree | 57680bfd10fc013c7a996fbea7212be900f089db /net | |
| parent | 6ea0a69ca21bbddab5b3979c2190013b0263e749 (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.h | 15 | ||||
| -rw-r--r-- | net/mac80211/ieee80211_i.h | 7 | ||||
| -rw-r--r-- | net/mac80211/mlme.c | 8 | ||||
| -rw-r--r-- | net/mac80211/scan.c | 48 | ||||
| -rw-r--r-- | net/mac80211/trace.h | 31 | ||||
| -rw-r--r-- | net/mac80211/tx.c | 9 | ||||
| -rw-r--r-- | net/mac80211/util.c | 12 |
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 | ||
| 383 | static inline void drv_sw_scan_start(struct ieee80211_local *local) | 383 | static 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 | ||
| 393 | static inline void drv_sw_scan_complete(struct ieee80211_local *local) | 395 | static 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); |
| 1903 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | 1904 | struct 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); |
| 1909 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | 1911 | void 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 | } |
| 369 | EXPORT_SYMBOL(ieee80211_scan_complete | ||
