diff options
author | Johannes Berg <johannes.berg@intel.com> | 2018-05-28 09:47:41 -0400 |
---|---|---|
committer | Johannes Berg <johannes@sipsolutions.net> | 2018-06-15 07:34:40 -0400 |
commit | b9771d41aee7aa3207b985422a1cc19e8342bc50 (patch) | |
tree | 13413533108492a4bb95aa282abf426fab1d707e /net/mac80211/scan.c | |
parent | 2e076f199097d670ce5e5492cea57f552b93bba9 (diff) |
mac80211: support scan features for improved scan privacy
Support the new random SN and minimal probe request contents
scan flags for the case of software scan - for hardware scan
the drivers need to opt in, but may need to do only that,
depending on their implementation.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Diffstat (limited to 'net/mac80211/scan.c')
-rw-r--r-- | net/mac80211/scan.c | 35 |
1 files changed, 30 insertions, 5 deletions
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 03f66f31c5b4..ae77d1c12856 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <net/sch_generic.h> | 20 | #include <net/sch_generic.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/export.h> | 22 | #include <linux/export.h> |
23 | #include <linux/random.h> | ||
23 | #include <net/mac80211.h> | 24 | #include <net/mac80211.h> |
24 | 25 | ||
25 | #include "ieee80211_i.h" | 26 | #include "ieee80211_i.h" |
@@ -293,6 +294,7 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) | |||
293 | struct cfg80211_chan_def chandef; | 294 | struct cfg80211_chan_def chandef; |
294 | u8 bands_used = 0; | 295 | u8 bands_used = 0; |
295 | int i, ielen, n_chans; | 296 | int i, ielen, n_chans; |
297 | u32 flags = 0; | ||
296 | 298 | ||
297 | req = rcu_dereference_protected(local->scan_req, | 299 | req = rcu_dereference_protected(local->scan_req, |
298 | lockdep_is_held(&local->mtx)); | 300 | lockdep_is_held(&local->mtx)); |
@@ -331,12 +333,16 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) | |||
331 | local->hw_scan_req->req.n_channels = n_chans; | 333 | local->hw_scan_req->req.n_channels = n_chans; |
332 | ieee80211_prepare_scan_chandef(&chandef, req->scan_width); | 334 | ieee80211_prepare_scan_chandef(&chandef, req->scan_width); |
333 | 335 | ||
336 | if (req->flags & NL80211_SCAN_FLAG_MIN_PREQ_CONTENT) | ||
337 | flags |= IEEE80211_PROBE_FLAG_MIN_CONTENT; | ||
338 | |||
334 | ielen = ieee80211_build_preq_ies(local, | 339 | ielen = ieee80211_build_preq_ies(local, |
335 | (u8 *)local->hw_scan_req->req.ie, | 340 | (u8 *)local->hw_scan_req->req.ie, |
336 | local->hw_scan_ies_bufsize, | 341 | local->hw_scan_ies_bufsize, |
337 | &local->hw_scan_req->ies, | 342 | &local->hw_scan_req->ies, |
338 | req->ie, req->ie_len, | 343 | req->ie, req->ie_len, |
339 | bands_used, req->rates, &chandef, 0); | 344 | bands_used, req->rates, &chandef, |
345 | flags); | ||
340 | local->hw_scan_req->req.ie_len = ielen; | 346 | local->hw_scan_req->req.ie_len = ielen; |
341 | local->hw_scan_req->req.no_cck = req->no_cck; | 347 | local->hw_scan_req->req.no_cck = req->no_cck; |
342 | ether_addr_copy(local->hw_scan_req->req.mac_addr, req->mac_addr); | 348 | ether_addr_copy(local->hw_scan_req->req.mac_addr, req->mac_addr); |
@@ -536,13 +542,24 @@ static void ieee80211_send_scan_probe_req(struct ieee80211_sub_if_data *sdata, | |||
536 | struct ieee80211_channel *channel) | 542 | struct ieee80211_channel *channel) |
537 | { | 543 | { |
538 | struct sk_buff *skb; | 544 | struct sk_buff *skb; |
545 | u32 txdata_flags = 0; | ||
539 | 546 | ||
540 | skb = ieee80211_build_probe_req(sdata, src, dst, ratemask, channel, | 547 | skb = ieee80211_build_probe_req(sdata, src, dst, ratemask, channel, |
541 | ssid, ssid_len, | 548 | ssid, ssid_len, |
542 | ie, ie_len, flags); | 549 | ie, ie_len, flags); |
550 | |||
543 | if (skb) { | 551 | if (skb) { |
552 | if (flags & IEEE80211_PROBE_FLAG_RANDOM_SN) { | ||
553 | struct ieee80211_hdr *hdr = (void *)skb->data; | ||
554 | u16 sn = get_random_u32(); | ||
555 | |||
556 | txdata_flags |= IEEE80211_TX_NO_SEQNO; | ||
557 | hdr->seq_ctrl = | ||
558 | cpu_to_le16(IEEE80211_SN_TO_SEQ(sn)); | ||
559 | } | ||
544 | IEEE80211_SKB_CB(skb)->flags |= tx_flags; | 560 | IEEE80211_SKB_CB(skb)->flags |= tx_flags; |
545 | ieee80211_tx_skb_tid_band(sdata, skb, 7, channel->band); | 561 | ieee80211_tx_skb_tid_band(sdata, skb, 7, channel->band, |
562 | txdata_flags); | ||
546 | } | 563 | } |
547 | } | 564 | } |
548 | 565 | ||
@@ -553,7 +570,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, | |||
553 | struct ieee80211_sub_if_data *sdata; | 570 | struct ieee80211_sub_if_data *sdata; |
554 | struct cfg80211_scan_request *scan_req; | 571 | struct cfg80211_scan_request *scan_req; |
555 | enum nl80211_band band = local->hw.conf.chandef.chan->band; | 572 | enum nl80211_band band = local->hw.conf.chandef.chan->band; |
556 | u32 tx_flags; | 573 | u32 flags = 0, tx_flags; |
557 | 574 | ||
558 | scan_req = rcu_dereference_protected(local->scan_req, | 575 | scan_req = rcu_dereference_protected(local->scan_req, |
559 | lockdep_is_held(&local->mtx)); | 576 | lockdep_is_held(&local->mtx)); |
@@ -561,6 +578,10 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, | |||
561 | tx_flags = IEEE80211_TX_INTFL_OFFCHAN_TX_OK; | 578 | tx_flags = IEEE80211_TX_INTFL_OFFCHAN_TX_OK; |
562 | if (scan_req->no_cck) | 579 | if (scan_req->no_cck) |
563 | tx_flags |= IEEE80211_TX_CTL_NO_CCK_RATE; | 580 | tx_flags |= IEEE80211_TX_CTL_NO_CCK_RATE; |
581 | if (scan_req->flags & NL80211_SCAN_FLAG_MIN_PREQ_CONTENT) | ||
582 | flags |= IEEE80211_PROBE_FLAG_MIN_CONTENT; | ||
583 | if (scan_req->flags & NL80211_SCAN_FLAG_RANDOM_SN) | ||
584 | flags |= IEEE80211_PROBE_FLAG_RANDOM_SN; | ||
564 | 585 | ||
565 | sdata = rcu_dereference_protected(local->scan_sdata, | 586 | sdata = rcu_dereference_protected(local->scan_sdata, |
566 | lockdep_is_held(&local->mtx)); | 587 | lockdep_is_held(&local->mtx)); |
@@ -570,7 +591,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, | |||
570 | sdata, local->scan_addr, scan_req->bssid, | 591 | sdata, local->scan_addr, scan_req->bssid, |
571 | scan_req->ssids[i].ssid, scan_req->ssids[i].ssid_len, | 592 | scan_req->ssids[i].ssid, scan_req->ssids[i].ssid_len, |
572 | scan_req->ie, scan_req->ie_len, | 593 | scan_req->ie, scan_req->ie_len, |
573 | scan_req->rates[band], 0, | 594 | scan_req->rates[band], flags, |
574 | tx_flags, local->hw.conf.chandef.chan); | 595 | tx_flags, local->hw.conf.chandef.chan); |
575 | 596 | ||
576 | /* | 597 | /* |
@@ -1159,6 +1180,7 @@ int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
1159 | u32 rate_masks[NUM_NL80211_BANDS] = {}; | 1180 | u32 rate_masks[NUM_NL80211_BANDS] = {}; |
1160 | u8 bands_used = 0; | 1181 | u8 bands_used = 0; |
1161 | u8 *ie; | 1182 | u8 *ie; |
1183 | u32 flags = 0; | ||
1162 | 1184 | ||
1163 | iebufsz = local->scan_ies_len + req->ie_len; | 1185 | iebufsz = local->scan_ies_len + req->ie_len; |
1164 | 1186 | ||
@@ -1175,6 +1197,9 @@ int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
1175 | } | 1197 | } |
1176 | } | 1198 | } |
1177 | 1199 | ||
1200 | if (req->flags & NL80211_SCAN_FLAG_MIN_PREQ_CONTENT) | ||
1201 | flags |= IEEE80211_PROBE_FLAG_MIN_CONTENT; | ||
1202 | |||
1178 | ie = kzalloc(num_bands * iebufsz, GFP_KERNEL); | 1203 | ie = kzalloc(num_bands * iebufsz, GFP_KERNEL); |
1179 | if (!ie) { | 1204 | if (!ie) { |
1180 | ret = -ENOMEM; | 1205 | ret = -ENOMEM; |
@@ -1186,7 +1211,7 @@ int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
1186 | ieee80211_build_preq_ies(local, ie, num_bands * iebufsz, | 1211 | ieee80211_build_preq_ies(local, ie, num_bands * iebufsz, |
1187 | &sched_scan_ies, req->ie, | 1212 | &sched_scan_ies, req->ie, |
1188 | req->ie_len, bands_used, rate_masks, &chandef, | 1213 | req->ie_len, bands_used, rate_masks, &chandef, |
1189 | 0); | 1214 | flags); |
1190 | 1215 | ||
1191 | ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies); | 1216 | ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies); |
1192 | if (ret == 0) { | 1217 | if (ret == 0) { |