aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
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/mac80211
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/mac80211')
-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_completed); 388EXPORT_SYMBOL(ieee80211_scan_completed);
370 389
371static int ieee80211_start_sw_scan(struct ieee80211_local *local) 390static int ieee80211_start_sw_scan(struct ieee80211_local *local,
391 struct ieee80211_sub_if_data *sdata)
372{ 392{
373 /* Software scan is not supported in multi-channel cases */ 393 /* Software scan is not supported in multi-channel cases */
374 if (local->use_chanctx) 394 if (local->use_chanctx)
@@ -387,7 +407,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
387 * nullfunc frames and probe requests will be dropped in 407 * nullfunc frames and probe requests will be dropped in
388 * ieee80211_tx_h_check_assoc(). 408 * ieee80211_tx_h_check_assoc().
389 */ 409 */
390 drv_sw_scan_start(local); 410 drv_sw_scan_start(local, sdata, local->scan_addr);
391 411
392 local->leave_oper_channel_time = jiffies; 412 local->leave_oper_channel_time = jiffies;
393 local->next_scan_state = SCAN_DECISION; 413 local->next_scan_state = SCAN_DECISION;
@@ -463,7 +483,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
463 483
464 for (i = 0; i < scan_req->n_ssids; i++) 484 for (i = 0; i < scan_req->n_ssids; i++)
465 ieee80211_send_probe_req( 485 ieee80211_send_probe_req(
466 sdata, NULL, 486 sdata, local->scan_addr, NULL,
467 scan_req->ssids[i].ssid, scan_req->ssids[i].ssid_len, 487 scan_req->ssids[i].ssid, scan_req->ssids[i].ssid_len,
468 scan_req->ie, scan_req->ie_len, 488 scan_req->ie, scan_req->ie_len,
469 scan_req->rates[band], false, 489 scan_req->rates[band], false,
@@ -543,6 +563,13 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
543 rcu_assign_pointer(local->scan_req, req); 563 rcu_assign_pointer(local->scan_req, req);
544 rcu_assign_pointer(local->scan_sdata, sdata); 564 rcu_assign_pointer(local->scan_sdata, sdata);
545 565
566 if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)
567 get_random_mask_addr(local->scan_addr,
568 req->mac_addr,
569 req->mac_addr_mask);
570 else
571 memcpy(local->scan_addr, sdata->vif.addr, ETH_ALEN);
572
546 if (local->ops->hw_scan) { 573 if (local->ops->hw_scan) {
547 __set_bit(SCAN_HW_SCANNING, &local->scanning); 574 __set_bit(SCAN_HW_SCANNING, &local->scanning);
548 } else if ((req->n_channels == 1) && 575 } else if ((req->n_channels == 1) &&
@@ -559,7 +586,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
559 586
560 /* Notify driver scan is starting, keep order of operations 587 /* Notify driver scan is starting, keep order of operations
561 * same as normal software scan, in case that matters. */ 588 * same as normal software scan, in case that matters. */
562 drv_sw_scan_start(local); 589 drv_sw_scan_start(local, sdata, local->scan_addr);
563 590
564 ieee80211_configure_filter(local); /* accept probe-responses */ 591 ieee80211_configure_filter(local); /* accept probe-responses */
565 592
@@ -589,8 +616,9 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
589 if (local->ops->hw_scan) { 616 if (local->ops->hw_scan) {
590 WARN_ON(!ieee80211_prep_hw_scan(local)); 617 WARN_ON(!ieee80211_prep_hw_scan(local));
591 rc = drv_hw_scan(local, sdata, local->hw_scan_req); 618 rc = drv_hw_scan(local, sdata, local->hw_scan_req);
592 } else 619 } else {
593 rc = ieee80211_start_sw_scan(local); 620 rc = ieee80211_start_sw_scan(local, sdata);
621 }
594 622
595 if (rc) { 623 if (rc) {
596 kfree(local->hw_scan_req); 624 kfree(local->hw_scan_req);
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 7f76e2f25744..eb91505eb43e 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -596,14 +596,33 @@ DEFINE_EVENT(local_sdata_evt, drv_sched_scan_stop,
596 TP_ARGS(local, sdata) 596 TP_ARGS(local, sdata)
597); 597);
598 598
599DEFINE_EVENT(local_only_evt, drv_sw_scan_start, 599TRACE_EVENT(drv_sw_scan_start,
600 TP_PROTO(struct ieee80211_local *local), 600 TP_PROTO(struct ieee80211_local *local,
601 TP_ARGS(local) 601 struct ieee80211_sub_if_data *sdata,
602 const u8 *mac_addr),
603
604 TP_ARGS(local, sdata, mac_addr),
605
606 TP_STRUCT__entry(
607 LOCAL_ENTRY
608 VIF_ENTRY
609 __array(char, mac_addr, ETH_ALEN)
610 ),
611
612 TP_fast_assign(
613 LOCAL_ASSIGN;
614 VIF_ASSIGN;
615 memcpy(__entry->mac_addr, mac_addr, ETH_ALEN);
616 ),
617
618 TP_printk(LOCAL_PR_FMT ", " VIF_PR_FMT ", addr:%pM",
619 LOCAL_PR_ARG, VIF_PR_ARG, __entry->mac_addr)
602); 620);
603 621
604DEFINE_EVENT(local_only_evt, drv_sw_scan_complete, 622DEFINE_EVENT(local_sdata_evt, drv_sw_scan_complete,
605 TP_PROTO(struct ieee80211_local *local), 623 TP_PROTO(struct ieee80211_local *local,
606 TP_ARGS(local) 624 struct ieee80211_sub_if_data *sdata),
625 TP_ARGS(local, sdata)
607); 626);
608 627
609TRACE_EVENT(drv_get_stats, 628TRACE_EVENT(drv_get_stats,
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 0cb41d1a1f20..66ddbbeccd20 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2961,19 +2961,16 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
2961EXPORT_SYMBOL(ieee80211_nullfunc_get); 2961EXPORT_SYMBOL(ieee80211_nullfunc_get);
2962 2962
2963struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw, 2963struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw,
2964 struct ieee80211_vif *vif, 2964 const u8 *src_addr,
2965 const u8 *ssid, size_t ssid_len, 2965 const u8 *ssid, size_t ssid_len,
2966 size_t tailroom) 2966 size_t tailroom)
2967{ 2967{
2968 struct ieee80211_sub_if_data *sdata; 2968 struct ieee80211_local *local = hw_to_local(hw);
2969 struct ieee80211_local *local;
2970 struct ieee80211_hdr_3addr *hdr; 2969 struct ieee80211_hdr_3addr *hdr;
2971 struct sk_buff *skb; 2970 struct sk_buff *skb;
2972 size_t ie_ssid_len; 2971 size_t ie_ssid_len;
2973 u8 *pos; 2972 u8 *pos;
2974 2973
2975 sdata = vif_to_sdata(vif);
2976 local = sdata->local;
2977 ie_ssid_len = 2 + ssid_len; 2974 ie_ssid_len = 2 + ssid_len;
2978 2975
2979 skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*hdr) + 2976 skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*hdr) +
@@ -2988,7 +2985,7 @@ struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw,
2988 hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 2985 hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
2989 IEEE80211_STYPE_PROBE_REQ); 2986 IEEE80211_STYPE_PROBE_REQ);
2990 eth_broadcast_addr(hdr->addr1); 2987 eth_broadcast_addr(hdr->addr1);
2991 memcpy(hdr->addr2, vif->addr, ETH_ALEN); 2988 memcpy(hdr->addr2, src_addr, ETH_ALEN);
2992 eth_broadcast_addr(hdr->addr3); 2989 eth_broadcast_addr(hdr->addr3);
2993 2990
2994 pos = skb_put(skb, ie_ssid_len); 2991 pos = skb_put(skb, ie_ssid_len);
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 0ad534abc008..bb9664cb8831 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1523,7 +1523,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
1523}; 1523};
1524 1524
1525struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, 1525struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
1526 u8 *dst, u32 ratemask, 1526 const u8 *src, const u8 *dst,
1527 u32 ratemask,
1527 struct ieee80211_channel *chan, 1528 struct ieee80211_channel *chan,
1528 const u8 *ssid, size_t ssid_len, 1529 const u8 *ssid, size_t ssid_len,
1529 const u8 *ie, size_t ie_len, 1530 const u8 *ie, size_t ie_len,
@@ -1548,8 +1549,8 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
1548 else 1549 else
1549 chandef.chan = chan; 1550 chandef.chan = chan;
1550 1551
1551 skb = ieee80211_probereq_get(&local->hw, &sdata->vif, 1552 skb = ieee80211_probereq_get(&local->hw, src, ssid, ssid_len,
1552 ssid, ssid_len, 100 + ie_len); 1553 100 + ie_len);
1553 if (!skb) 1554 if (!skb)
1554 return NULL; 1555 return NULL;
1555 1556
@@ -1571,7 +1572,8 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
1571 return skb; 1572 return skb;
1572} 1573}
1573 1574
1574void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, 1575void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata,
1576 const u8 *src, const u8 *dst,
1575 const u8 *ssid, size_t ssid_len, 1577 const u8 *ssid, size_t ssid_len,
1576 const u8 *ie, size_t ie_len, 1578 const u8 *ie, size_t ie_len,
1577 u32 ratemask, bool directed, u32 tx_flags, 1579 u32 ratemask, bool directed, u32 tx_flags,
@@ -1579,7 +1581,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
1579{ 1581{
1580 struct sk_buff *skb; 1582 struct sk_buff *skb;
1581 1583
1582 skb = ieee80211_build_probe_req(sdata, dst, ratemask, channel, 1584 skb = ieee80211_build_probe_req(sdata, src, dst, ratemask, channel,
1583 ssid, ssid_len, 1585 ssid, ssid_len,
1584 ie, ie_len, directed); 1586 ie, ie_len, directed);
1585 if (skb) { 1587 if (skb) {