mac80211: allow drivers to support NL80211_SCAN_FLAG_RANDOM_ADDR
authorJohannes Berg <johannes.berg@intel.com>
Thu, 12 Jun 2014 20:24:31 +0000 (22:24 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 19 Nov 2014 17:46:09 +0000 (18:46 +0100)
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>
24 files changed:
drivers/net/wireless/ath/ath5k/mac80211-ops.c
drivers/net/wireless/ath/ath9k/channel.c
drivers/net/wireless/ath/ath9k/htc_drv_main.c
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/wcn36xx/main.c
drivers/net/wireless/b43/main.c
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
drivers/net/wireless/cw1200/scan.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/mwl8k.c
drivers/net/wireless/rt2x00/rt2x00.h
drivers/net/wireless/rt2x00/rt2x00mac.c
drivers/net/wireless/rtlwifi/core.c
drivers/net/wireless/ti/wl1251/main.c
drivers/net/wireless/ti/wlcore/cmd.c
drivers/staging/vt6656/main_usb.c
include/net/mac80211.h
net/mac80211/driver-ops.h
net/mac80211/ieee80211_i.h
net/mac80211/mlme.c
net/mac80211/scan.c
net/mac80211/trace.h
net/mac80211/tx.c
net/mac80211/util.c

index ab2709a..19eab2a 100644 (file)
@@ -547,7 +547,9 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 
 
 static void
-ath5k_sw_scan_start(struct ieee80211_hw *hw)
+ath5k_sw_scan_start(struct ieee80211_hw *hw,
+                   struct ieee80211_vif *vif,
+                   const u8 *mac_addr)
 {
        struct ath5k_hw *ah = hw->priv;
        if (!ah->assoc)
@@ -556,7 +558,7 @@ ath5k_sw_scan_start(struct ieee80211_hw *hw)
 
 
 static void
-ath5k_sw_scan_complete(struct ieee80211_hw *hw)
+ath5k_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 {
        struct ath5k_hw *ah = hw->priv;
        ath5k_hw_set_ledstate(ah, ah->assoc ?
index 794d520..2066650 100644 (file)
@@ -963,7 +963,7 @@ static void ath_scan_send_probe(struct ath_softc *sc,
        struct ieee80211_tx_info *info;
        int band = sc->offchannel.chan.chandef.chan->band;
 
-       skb = ieee80211_probereq_get(sc->hw, vif,
+       skb = ieee80211_probereq_get(sc->hw, vif->addr,
                        ssid->ssid, ssid->ssid_len, req->ie_len);
        if (!skb)
                return;
index c7d12ef..92d5a6c 100644 (file)
@@ -1691,7 +1691,9 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw,
        return ret;
 }
 
-static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw)
+static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw,
+                                   struct ieee80211_vif *vif,
+                                   const u8 *mac_addr)
 {
        struct ath9k_htc_priv *priv = hw->priv;
        struct ath_common *common = ath9k_hw_common(priv->ah);
@@ -1705,7 +1707,8 @@ static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw)
        mutex_unlock(&priv->mutex);
 }
 
-static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw)
+static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw,
+                                      struct ieee80211_vif *vif)
 {
        struct ath9k_htc_priv *priv = hw->priv;
        struct ath_common *common = ath9k_hw_common(priv->ah);
index 5f16630..027ad71 100644 (file)
@@ -2180,14 +2180,17 @@ static int ath9k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
        return 0;
 }
 
-static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
+static void ath9k_sw_scan_start(struct ieee80211_hw *hw,
+                               struct ieee80211_vif *vif,
+                               const u8 *mac_addr)
 {
        struct ath_softc *sc = hw->priv;
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        set_bit(ATH_OP_SCANNING, &common->op_flags);
 }
 
-static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
+static void ath9k_sw_scan_complete(struct ieee80211_hw *hw,
+                                  struct ieee80211_vif *vif)
 {
        struct ath_softc *sc = hw->priv;
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
index b71d2b3..267c35d 100644 (file)
@@ -494,7 +494,9 @@ out:
        return ret;
 }
 
-static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw)
+static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw,
+                                 struct ieee80211_vif *vif,
+                                 const u8 *mac_addr)
 {
        struct wcn36xx *wcn = hw->priv;
 
@@ -502,7 +504,8 @@ static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw)
        wcn36xx_smd_start_scan(wcn);
 }
 
-static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw)
+static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw,
+                                    struct ieee80211_vif *vif)
 {
        struct wcn36xx *wcn = hw->priv;
 
index 5d4173e..47731cb 100644 (file)
@@ -5110,7 +5110,9 @@ static void b43_op_sta_notify(struct ieee80211_hw *hw,
        B43_WARN_ON(!vif || wl->vif != vif);
 }
 
-static void b43_op_sw_scan_start_notifier(struct ieee80211_hw *hw)
+static void b43_op_sw_scan_start_notifier(struct ieee80211_hw *hw,
+                                         struct ieee80211_vif *vif,
+                                         const u8 *mac_addr)
 {
        struct b43_wl *wl = hw_to_b43_wl(hw);
        struct b43_wldev *dev;
@@ -5124,7 +5126,8 @@ static void b43_op_sw_scan_start_notifier(struct ieee80211_hw *hw)
        mutex_unlock(&wl->mutex);
 }
 
-static void b43_op_sw_scan_complete_notifier(struct ieee80211_hw *hw)
+static void b43_op_sw_scan_complete_notifier(struct ieee80211_hw *hw,
+                                            struct ieee80211_vif *vif)
 {
        struct b43_wl *wl = hw_to_b43_wl(hw);
        struct b43_wldev *dev;
index 43c71bf..f95b524 100644 (file)
@@ -764,7 +764,9 @@ brcms_ops_configure_filter(struct ieee80211_hw *hw,
        return;
 }
 
-static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw)
+static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw,
+                                   struct ieee80211_vif *vif,
+                                   const u8 *mac_addr)
 {
        struct brcms_info *wl = hw->priv;
        spin_lock_bh(&wl->lock);
@@ -773,7 +775,8 @@ static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw)
        return;
 }
 
-static void brcms_ops_sw_scan_complete(struct ieee80211_hw *hw)
+static void brcms_ops_sw_scan_complete(struct ieee80211_hw *hw,
+                                      struct ieee80211_vif *vif)
 {
        struct brcms_info *wl = hw->priv;
        spin_lock_bh(&wl->lock);
index b2fb6c6..f2e276f 100644 (file)
@@ -78,7 +78,7 @@ int cw1200_hw_scan(struct ieee80211_hw *hw,
        if (req->n_ssids > WSM_SCAN_MAX_NUM_OF_SSIDS)
                return -EINVAL;
 
-       frame.skb = ieee80211_probereq_get(hw, priv->vif, NULL, 0,
+       frame.skb = ieee80211_probereq_get(hw, priv->vif->addr, NULL, 0,
                req->ie_len);
        if (!frame.skb)
                return -ENOMEM;
index 58f11bb..6daaad5 100644 (file)
@@ -1802,7 +1802,7 @@ static void hw_scan_work(struct work_struct *work)
                        struct sk_buff *probe;
 
                        probe = ieee80211_probereq_get(hwsim->hw,
-                                                      hwsim->hw_scan_vif,
+                                                      hwsim->hw_scan_vif->addr,
                                                       req->ssids[i].ssid,
                                                       req->ssids[i].ssid_len,
                                                       req->ie_len);
@@ -1866,7 +1866,9 @@ static void mac80211_hwsim_cancel_hw_scan(struct ieee80211_hw *hw,
        mutex_unlock(&hwsim->mutex);
 }
 
-static void mac80211_hwsim_sw_scan(struct ieee80211_hw *hw)
+static void mac80211_hwsim_sw_scan(struct ieee80211_hw *hw,
+                                  struct ieee80211_vif *vif,
+                                  const u8 *mac_addr)
 {
        struct mac80211_hwsim_data *hwsim = hw->priv;
 
@@ -1884,7 +1886,8 @@ out:
        mutex_unlock(&hwsim->mutex);
 }
 
-static void mac80211_hwsim_sw_scan_complete(struct ieee80211_hw *hw)
+static void mac80211_hwsim_sw_scan_complete(struct ieee80211_hw *hw,
+                                           struct ieee80211_vif *vif)
 {
        struct mac80211_hwsim_data *hwsim = hw->priv;
 
index ef11044..b8d1e04 100644 (file)
@@ -5548,7 +5548,9 @@ mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
        return rc;
 }
 
-static void mwl8k_sw_scan_start(struct ieee80211_hw *hw)
+static void mwl8k_sw_scan_start(struct ieee80211_hw *hw,
+                               struct ieee80211_vif *vif,
+                               const u8 *mac_addr)
 {
        struct mwl8k_priv *priv = hw->priv;
        u8 tmp;
@@ -5565,7 +5567,8 @@ static void mwl8k_sw_scan_start(struct ieee80211_hw *hw)
        priv->sw_scan_start = true;
 }
 
-static void mwl8k_sw_scan_complete(struct ieee80211_hw *hw)
+static void mwl8k_sw_scan_complete(struct ieee80211_hw *hw,
+                                  struct ieee80211_vif *vif)
 {
        struct mwl8k_priv *priv = hw->priv;
        u8 tmp;
index d13f25c..1ff81af 100644 (file)
@@ -1437,8 +1437,11 @@ int rt2x00mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                      struct ieee80211_sta *sta);
 int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                         struct ieee80211_sta *sta);
-void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw);
-void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw);
+void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw,
+                            struct ieee80211_vif *vif,
+                            const u8 *mac_addr);
+void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw,
+                               struct ieee80211_vif *vif);
 int rt2x00mac_get_stats(struct ieee80211_hw *hw,
                        struct ieee80211_low_level_stats *stats);
 void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
index ad6e5a8..cb40245 100644 (file)
@@ -568,7 +568,9 @@ int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_sta_remove);
 
-void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw)
+void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw,
+                            struct ieee80211_vif *vif,
+                            const u8 *mac_addr)
 {
        struct rt2x00_dev *rt2x00dev = hw->priv;
        set_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);
@@ -576,7 +578,8 @@ void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw)
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_start);
 
-void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw)
+void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw,
+                               struct ieee80211_vif *vif)
 {
        struct rt2x00_dev *rt2x00dev = hw->priv;
        clear_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);
index f6179bc..884d905 100644 (file)
@@ -1361,7 +1361,9 @@ static int rtl_op_ampdu_action(struct ieee80211_hw *hw,
        return 0;
 }
 
-static void rtl_op_sw_scan_start(struct ieee80211_hw *hw)
+static void rtl_op_sw_scan_start(struct ieee80211_hw *hw,
+                                struct ieee80211_vif *vif,
+                                const u8 *mac_addr)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
@@ -1396,7 +1398,8 @@ static void rtl_op_sw_scan_start(struct ieee80211_hw *hw)
        rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_BACKUP_BAND0);
 }
 
-static void rtl_op_sw_scan_complete(struct ieee80211_hw *hw)
+static void rtl_op_sw_scan_complete(struct ieee80211_hw *hw,
+                                   struct ieee80211_vif *vif)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
        struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
index 3823485..0b30a7b 100644 (file)
@@ -1029,7 +1029,7 @@ static int wl1251_op_hw_scan(struct ieee80211_hw *hw,
                        goto out_sleep;
        }
 
-       skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len,
+       skb = ieee80211_probereq_get(wl->hw, wl->vif->addr, ssid, ssid_len,
                                     req->ie_len);
        if (!skb) {
                ret = -ENOMEM;
index dd2e448..b826619 100644 (file)
@@ -1145,7 +1145,7 @@ int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif,
 
        wl1271_debug(DEBUG_SCAN, "build probe request band %d", band);
 
-       skb = ieee80211_probereq_get(wl->hw, vif, ssid, ssid_len,
+       skb = ieee80211_probereq_get(wl->hw, vif->addr, ssid, ssid_len,
                                     ie0_len + ie1_len);
        if (!skb) {
                ret = -ENOMEM;
index 2fbff90..dbc311c 100644 (file)
@@ -856,7 +856,9 @@ static int vnt_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
        return 0;
 }
 
-static void vnt_sw_scan_start(struct ieee80211_hw *hw)
+static void vnt_sw_scan_start(struct ieee80211_hw *hw,
+                             struct ieee80211_vif *vif,
+                             const u8 *addr)
 {
        struct vnt_private *priv = hw->priv;
 
@@ -865,7 +867,8 @@ static void vnt_sw_scan_start(struct ieee80211_hw *hw)
        vnt_update_pre_ed_threshold(priv, true);
 }
 
-static void vnt_sw_scan_complete(struct ieee80211_hw *hw)
+static void vnt_sw_scan_complete(struct ieee80211_hw *hw,
+                                struct ieee80211_vif *vif)
 {
        struct vnt_private *priv = hw->priv;
 
index 59166a1..7b889e3 100644 (file)
@@ -2622,7 +2622,9 @@ enum ieee80211_reconfig_type {
  *
  * @sw_scan_start: Notifier function that is called just before a software scan
  *     is started. Can be NULL, if the driver doesn't need this notification.
- *     The callback can sleep.
+ *     The mac_addr parameter allows supporting NL80211_SCAN_FLAG_RANDOM_ADDR,
+ *     the driver may set the NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR flag if it
+ *     can use this parameter. The callback can sleep.
  *
  * @sw_scan_complete: Notifier function that is called just after a
  *     software scan finished. Can be NULL, if the driver doesn't need
@@ -3016,8 +3018,11 @@ struct ieee80211_ops {
                                struct ieee80211_scan_ies *ies);
        int (*sched_scan_stop)(struct ieee80211_hw *hw,
                               struct ieee80211_vif *vif);
-       void (*sw_scan_start)(struct ieee80211_hw *hw);
-       void (*sw_scan_complete)(struct ieee80211_hw *hw);
+       void (*sw_scan_start)(struct ieee80211_hw *hw,
+                             struct ieee80211_vif *vif,
+                             const u8 *mac_addr);
+       void (*sw_scan_complete)(struct ieee80211_hw *hw,
+                                struct ieee80211_vif *vif);
        int (*get_stats)(struct ieee80211_hw *hw,
                         struct ieee80211_low_level_stats *stats);
        void (*get_tkip_seq)(struct ieee80211_hw *hw, u8 hw_key_idx,
@@ -3820,7 +3825,7 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
 /**
  * ieee80211_probereq_get - retrieve a Probe Request template
  * @hw: pointer obtained from ieee80211_alloc_hw().
- * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @src_addr: source MAC address
  * @ssid: SSID buffer
  * @ssid_len: length of SSID
  * @tailroom: tailroom to reserve at end of SKB for IEs
@@ -3831,7 +3836,7 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
  * Return: The Probe Request template. %NULL on error.
  */
 struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw,
-                                      struct ieee80211_vif *vif,
+                                      const u8 *src_addr,
                                       const u8 *ssid, size_t ssid_len,
                                       size_t tailroom);
 
index ba0d2cb..5f5fc3f 100644 (file)
@@ -380,23 +380,26 @@ static inline int drv_sched_scan_stop(struct ieee80211_local *local,
        return ret;
 }
 
-static inline void drv_sw_scan_start(struct ieee80211_local *local)
+static inline void drv_sw_scan_start(struct ieee80211_local *local,
+                                    struct ieee80211_sub_if_data *sdata,
+                                    const u8 *mac_addr)
 {
        might_sleep();
 
-       trace_drv_sw_scan_start(local);
+       trace_drv_sw_scan_start(local, sdata, mac_addr);
        if (local->ops->sw_scan_start)
-               local->ops->sw_scan_start(&local->hw);
+               local->ops->sw_scan_start(&local->hw, &sdata->vif, mac_addr);
        trace_drv_return_void(local);
 }
 
-static inline void drv_sw_scan_complete(struct ieee80211_local *local)
+static inline void drv_sw_scan_complete(struct ieee80211_local *local,
+                                       struct ieee80211_sub_if_data *sdata)
 {
        might_sleep();
 
-       trace_drv_sw_scan_complete(local);
+       trace_drv_sw_scan_complete(local, sdata);
        if (local->ops->sw_scan_complete)
-               local->ops->sw_scan_complete(&local->hw);
+               local->ops->sw_scan_complete(&local->hw, &sdata->vif);
        trace_drv_return_void(local);
 }
 
index dd27180..cf95d03 100644 (file)
@@ -1249,6 +1249,7 @@ struct ieee80211_local {
        struct work_struct sched_scan_stopped_work;
        struct ieee80211_sub_if_data __rcu *sched_scan_sdata;
        struct cfg80211_sched_scan_request __rcu *sched_scan_req;
+       u8 scan_addr[ETH_ALEN];
 
        unsigned long leave_oper_channel_time;
        enum mac80211_scan_state next_scan_state;
@@ -1901,12 +1902,14 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
                             u8 bands_used, u32 *rate_masks,
                             struct cfg80211_chan_def *chandef);
 struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
-                                         u8 *dst, u32 ratemask,
+                                         const u8 *src, const u8 *dst,
+                                         u32 ratemask,
                                          struct ieee80211_channel *chan,
                                          const u8 *ssid, size_t ssid_len,
                                          const u8 *ie, size_t ie_len,
                                          bool directed);
-void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
+void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata,
+                             const u8 *src, const u8 *dst,
                              const u8 *ssid, size_t ssid_len,
                              const u8 *ie, size_t ie_len,
                              u32 ratemask, bool directed, u32 tx_flags,
index 45490a2..d29589a 100644 (file)
@@ -2225,7 +2225,8 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
                else
                        ssid_len = ssid[1];
 
-               ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL,
+               ieee80211_send_probe_req(sdata, sdata->vif.addr, NULL,
+                                        ssid + 2, ssid_len, NULL,
                                         0, (u32) -1, true, 0,
                                         ifmgd->associated->channel, false);
                rcu_read_unlock();
@@ -2328,7 +2329,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
        else
                ssid_len = ssid[1];
 
-       skb = ieee80211_build_probe_req(sdata, cbss->bssid,
+       skb = ieee80211_build_probe_req(sdata, sdata->vif.addr, cbss->bssid,
                                        (u32) -1, cbss->channel,
                                        ssid + 2, ssid_len,
                                        NULL, 0, true);
@@ -3649,7 +3650,8 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
                 * Direct probe is sent to broadcast address as some APs
                 * will not answer to direct packet in unassociated state.
                 */
-               ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1],
+               ieee80211_send_probe_req(sdata, sdata->vif.addr, NULL,
+                                        ssidie + 2, ssidie[1],
                                         NULL, 0, (u32) -1, true, 0,
                                         auth_data->bss->channel, false);
                rcu_read_unlock();
index e75e64b..ae84267 100644 (file)
@@ -184,9 +184,21 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
                return;
 
        if (ieee80211_is_probe_resp(mgmt->frame_control)) {
-               /* ignore ProbeResp to foreign address */
-               if ((!sdata1 || !ether_addr_equal(mgmt->da, sdata1->vif.addr)) &&
-                   (!sdata2 || !ether_addr_equal(mgmt->da, sdata2->vif.addr)))
+               struct cfg80211_scan_request *scan_req;
+               struct cfg80211_sched_scan_request *sched_scan_req;
+
+               scan_req = rcu_dereference(local->scan_req);
+               sched_scan_req = rcu_dereference(local->sched_scan_req);
+
+               /* ignore ProbeResp to foreign address unless scanning
+                * with randomised address
+                */
+               if (!(sdata1 &&
+                     (ether_addr_equal(mgmt->da, sdata1->vif.addr) ||
+                      scan_req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)) &&
+                   !(sdata2 &&
+                     (ether_addr_equal(mgmt->da, sdata2->vif.addr) ||
+                      sched_scan_req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)))
                        return;
 
                elements = mgmt->u.probe_resp.variable;
@@ -284,6 +296,9 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
                                         bands_used, req->rates, &chandef);
        local->hw_scan_req->req.ie_len = ielen;
        local->hw_scan_req->req.no_cck = req->no_cck;
+       ether_addr_copy(local->hw_scan_req->req.mac_addr, req->mac_addr);
+       ether_addr_copy(local->hw_scan_req->req.mac_addr_mask,
+                       req->mac_addr_mask);
 
        return true;
 }
@@ -294,6 +309,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
        bool hw_scan = local->ops->hw_scan;
        bool was_scanning = local->scanning;
        struct cfg80211_scan_request *scan_req;
+       struct ieee80211_sub_if_data *scan_sdata;
 
        lockdep_assert_held(&local->mtx);
 
@@ -332,6 +348,9 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
        if (scan_req != local->int_scan_req)
                cfg80211_scan_done(scan_req, aborted);
        RCU_INIT_POINTER(local->scan_req, NULL);
+
+       scan_sdata = rcu_dereference_protected(local->scan_sdata,
+                                              lockdep_is_held(&local->mtx));
        RCU_INIT_POINTER(local->scan_sdata, NULL);
 
        local->scanning = 0;
@@ -342,7 +361,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
 
        if (!hw_scan) {
                ieee80211_configure_filter(local);
-               drv_sw_scan_complete(local);
+               drv_sw_scan_complete(local, scan_sdata);
                ieee80211_offchannel_return(local);
        }
 
@@ -368,7 +387,8 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
 }
 EXPORT_SYMBOL(ieee80211_scan_completed);
 
-static int ieee80211_start_sw_scan(struct ieee80211_local *local)
+static int ieee80211_start_sw_scan(struct ieee80211_local *local,
+                                  struct ieee80211_sub_if_data *sdata)
 {
        /* Software scan is not supported in multi-channel cases */
        if (local->use_chanctx)
@@ -387,7 +407,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
         * nullfunc frames and probe requests will be dropped in
         * ieee80211_tx_h_check_assoc().
         */
-       drv_sw_scan_start(local);
+       drv_sw_scan_start(local, sdata, local->scan_addr);
 
        local->leave_oper_channel_time = jiffies;
        local->next_scan_state = SCAN_DECISION;
@@ -463,7 +483,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
 
        for (i = 0; i < scan_req->n_ssids; i++)
                ieee80211_send_probe_req(
-                       sdata, NULL,
+                       sdata, local->scan_addr, NULL,
                        scan_req->ssids[i].ssid, scan_req->ssids[i].ssid_len,
                        scan_req->ie, scan_req->ie_len,
                        scan_req->rates[band], false,
@@ -543,6 +563,13 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
        rcu_assign_pointer(local->scan_req, req);
        rcu_assign_pointer(local->scan_sdata, sdata);
 
+       if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)
+               get_random_mask_addr(local->scan_addr,
+                                    req->mac_addr,
+                                    req->mac_addr_mask);
+       else
+               memcpy(local->scan_addr, sdata->vif.addr, ETH_ALEN);
+
        if (local->ops->hw_scan) {
                __set_bit(SCAN_HW_SCANNING, &local->scanning);
        } else if ((req->n_channels == 1) &&
@@ -559,7 +586,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
 
                /* Notify driver scan is starting, keep order of operations
                 * same as normal software scan, in case that matters. */
-               drv_sw_scan_start(local);
+               drv_sw_scan_start(local, sdata, local->scan_addr);
 
                ieee80211_configure_filter(local); /* accept probe-responses */
 
@@ -589,8 +616,9 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
        if (local->ops->hw_scan) {
                WARN_ON(!ieee80211_prep_hw_scan(local));
                rc = drv_hw_scan(local, sdata, local->hw_scan_req);
-       } else
-               rc = ieee80211_start_sw_scan(local);
+       } else {
+               rc = ieee80211_start_sw_scan(local, sdata);
+       }
 
        if (rc) {
                kfree(local->hw_scan_req);
index 7f76e2f..eb91505 100644 (file)
@@ -596,14 +596,33 @@ DEFINE_EVENT(local_sdata_evt, drv_sched_scan_stop,
        TP_ARGS(local, sdata)
 );
 
-DEFINE_EVENT(local_only_evt, drv_sw_scan_start,
-       TP_PROTO(struct ieee80211_local *local),
-       TP_ARGS(local)
+TRACE_EVENT(drv_sw_scan_start,
+       TP_PROTO(struct ieee80211_local *local,
+                struct ieee80211_sub_if_data *sdata,
+                const u8 *mac_addr),
+
+       TP_ARGS(local, sdata, mac_addr),
+
+       TP_STRUCT__entry(
+               LOCAL_ENTRY
+               VIF_ENTRY
+               __array(char, mac_addr, ETH_ALEN)
+       ),
+
+       TP_fast_assign(
+               LOCAL_ASSIGN;
+               VIF_ASSIGN;
+               memcpy(__entry->mac_addr, mac_addr, ETH_ALEN);
+       ),
+
+       TP_printk(LOCAL_PR_FMT ", " VIF_PR_FMT ", addr:%pM",
+                 LOCAL_PR_ARG, VIF_PR_ARG, __entry->mac_addr)
 );
 
-DEFINE_EVENT(local_only_evt, drv_sw_scan_complete,
-       TP_PROTO(struct ieee80211_local *local),
-       TP_ARGS(local)
+DEFINE_EVENT(local_sdata_evt, drv_sw_scan_complete,
+       TP_PROTO(struct ieee80211_local *local,
+                struct ieee80211_sub_if_data *sdata),
+       TP_ARGS(local, sdata)
 );
 
 TRACE_EVENT(drv_get_stats,
index 0cb41d1..66ddbbe 100644 (file)
@@ -2961,19 +2961,16 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
 EXPORT_SYMBOL(ieee80211_nullfunc_get);
 
 struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw,
-                                      struct ieee80211_vif *vif,
+                                      const u8 *src_addr,
                                       const u8 *ssid, size_t ssid_len,
                                       size_t tailroom)
 {
-       struct ieee80211_sub_if_data *sdata;
-       struct ieee80211_local *local;
+       struct ieee80211_local *local = hw_to_local(hw);
        struct ieee80211_hdr_3addr *hdr;
        struct sk_buff *skb;
        size_t ie_ssid_len;
        u8 *pos;
 
-       sdata = vif_to_sdata(vif);
-       local = sdata->local;
        ie_ssid_len = 2 + ssid_len;
 
        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,
        hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
                                         IEEE80211_STYPE_PROBE_REQ);
        eth_broadcast_addr(hdr->addr1);
-       memcpy(hdr->addr2, vif->addr, ETH_ALEN);
+       memcpy(hdr->addr2, src_addr, ETH_ALEN);
        eth_broadcast_addr(hdr->addr3);
 
        pos = skb_put(skb, ie_ssid_len);
index 0ad534a..bb9664c 100644 (file)
@@ -1523,7 +1523,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
 };
 
 struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
-                                         u8 *dst, u32 ratemask,
+                                         const u8 *src, const u8 *dst,
+                                         u32 ratemask,
                                          struct ieee80211_channel *chan,
                                          const u8 *ssid, size_t ssid_len,
                                          const u8 *ie, size_t ie_len,
@@ -1548,8 +1549,8 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
        else
                chandef.chan = chan;
 
-       skb = ieee80211_probereq_get(&local->hw, &sdata->vif,
-                                    ssid, ssid_len, 100 + ie_len);
+       skb = ieee80211_probereq_get(&local->hw, src, ssid, ssid_len,
+                                    100 + ie_len);
        if (!skb)
                return NULL;
 
@@ -1571,7 +1572,8 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
        return skb;
 }
 
-void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
+void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata,
+                             const u8 *src, const u8 *dst,
                              const u8 *ssid, size_t ssid_len,
                              const u8 *ie, size_t ie_len,
                              u32 ratemask, bool directed, u32 tx_flags,
@@ -1579,7 +1581,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
 {
        struct sk_buff *skb;
 
-       skb = ieee80211_build_probe_req(sdata, dst, ratemask, channel,
+       skb = ieee80211_build_probe_req(sdata, src, dst, ratemask, channel,
                                        ssid, ssid_len,
                                        ie, ie_len, directed);
        if (skb) {