Commit a344d677 authored by Johannes Berg's avatar Johannes Berg

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: default avatarJohannes Berg <johannes.berg@intel.com>
parent 6ea0a69c
...@@ -547,7 +547,9 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, ...@@ -547,7 +547,9 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
static void 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; struct ath5k_hw *ah = hw->priv;
if (!ah->assoc) if (!ah->assoc)
...@@ -556,7 +558,7 @@ ath5k_sw_scan_start(struct ieee80211_hw *hw) ...@@ -556,7 +558,7 @@ ath5k_sw_scan_start(struct ieee80211_hw *hw)
static void 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; struct ath5k_hw *ah = hw->priv;
ath5k_hw_set_ledstate(ah, ah->assoc ? ath5k_hw_set_ledstate(ah, ah->assoc ?
......
...@@ -963,7 +963,7 @@ static void ath_scan_send_probe(struct ath_softc *sc, ...@@ -963,7 +963,7 @@ static void ath_scan_send_probe(struct ath_softc *sc,
struct ieee80211_tx_info *info; struct ieee80211_tx_info *info;
int band = sc->offchannel.chan.chandef.chan->band; 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); ssid->ssid, ssid->ssid_len, req->ie_len);
if (!skb) if (!skb)
return; return;
......
...@@ -1691,7 +1691,9 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, ...@@ -1691,7 +1691,9 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw,
return ret; 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 ath9k_htc_priv *priv = hw->priv;
struct ath_common *common = ath9k_hw_common(priv->ah); struct ath_common *common = ath9k_hw_common(priv->ah);
...@@ -1705,7 +1707,8 @@ static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw) ...@@ -1705,7 +1707,8 @@ static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw)
mutex_unlock(&priv->mutex); 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 ath9k_htc_priv *priv = hw->priv;
struct ath_common *common = ath9k_hw_common(priv->ah); struct ath_common *common = ath9k_hw_common(priv->ah);
......
...@@ -2180,14 +2180,17 @@ static int ath9k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) ...@@ -2180,14 +2180,17 @@ static int ath9k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
return 0; 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_softc *sc = hw->priv;
struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_common *common = ath9k_hw_common(sc->sc_ah);
set_bit(ATH_OP_SCANNING, &common->op_flags); 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_softc *sc = hw->priv;
struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_common *common = ath9k_hw_common(sc->sc_ah);
......
...@@ -494,7 +494,9 @@ out: ...@@ -494,7 +494,9 @@ out:
return ret; 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; struct wcn36xx *wcn = hw->priv;
...@@ -502,7 +504,8 @@ static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw) ...@@ -502,7 +504,8 @@ static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw)
wcn36xx_smd_start_scan(wcn); 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; struct wcn36xx *wcn = hw->priv;
......
...@@ -5110,7 +5110,9 @@ static void b43_op_sta_notify(struct ieee80211_hw *hw, ...@@ -5110,7 +5110,9 @@ static void b43_op_sta_notify(struct ieee80211_hw *hw,
B43_WARN_ON(!vif || wl->vif != vif); 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_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev; struct b43_wldev *dev;
...@@ -5124,7 +5126,8 @@ static void b43_op_sw_scan_start_notifier(struct ieee80211_hw *hw) ...@@ -5124,7 +5126,8 @@ static void b43_op_sw_scan_start_notifier(struct ieee80211_hw *hw)
mutex_unlock(&wl->mutex); 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_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev; struct b43_wldev *dev;
......
...@@ -764,7 +764,9 @@ brcms_ops_configure_filter(struct ieee80211_hw *hw, ...@@ -764,7 +764,9 @@ brcms_ops_configure_filter(struct ieee80211_hw *hw,
return; 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; struct brcms_info *wl = hw->priv;
spin_lock_bh(&wl->lock); spin_lock_bh(&wl->lock);
...@@ -773,7 +775,8 @@ static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw) ...@@ -773,7 +775,8 @@ static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw)
return; 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; struct brcms_info *wl = hw->priv;
spin_lock_bh(&wl->lock); spin_lock_bh(&wl->lock);
......
...@@ -78,7 +78,7 @@ int cw1200_hw_scan(struct ieee80211_hw *hw, ...@@ -78,7 +78,7 @@ int cw1200_hw_scan(struct ieee80211_hw *hw,
if (req->n_ssids > WSM_SCAN_MAX_NUM_OF_SSIDS) if (req->n_ssids > WSM_SCAN_MAX_NUM_OF_SSIDS)
return -EINVAL; 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); req->ie_len);
if (!frame.skb) if (!frame.skb)
return -ENOMEM; return -ENOMEM;
......
...@@ -1802,7 +1802,7 @@ static void hw_scan_work(struct work_struct *work) ...@@ -1802,7 +1802,7 @@ static void hw_scan_work(struct work_struct *work)
struct sk_buff *probe; struct sk_buff *probe;
probe = ieee80211_probereq_get(hwsim->hw, probe = ieee80211_probereq_get(hwsim->hw,
hwsim->hw_scan_vif, hwsim->hw_scan_vif->addr,
req->ssids[i].ssid, req->ssids[i].ssid,
req->ssids[i].ssid_len, req->ssids[i].ssid_len,
req->ie_len); req->ie_len);
...@@ -1866,7 +1866,9 @@ static void mac80211_hwsim_cancel_hw_scan(struct ieee80211_hw *hw, ...@@ -1866,7 +1866,9 @@ static void mac80211_hwsim_cancel_hw_scan(struct ieee80211_hw *hw,
mutex_unlock(&hwsim->mutex); 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; struct mac80211_hwsim_data *hwsim = hw->priv;
...@@ -1884,7 +1886,8 @@ out: ...@@ -1884,7 +1886,8 @@ out:
mutex_unlock(&hwsim->mutex); 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; struct mac80211_hwsim_data *hwsim = hw->priv;
......
...@@ -5548,7 +5548,9 @@ mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ...@@ -5548,7 +5548,9 @@ mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
return rc; 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; struct mwl8k_priv *priv = hw->priv;
u8 tmp; u8 tmp;
...@@ -5565,7 +5567,8 @@ static void mwl8k_sw_scan_start(struct ieee80211_hw *hw) ...@@ -5565,7 +5567,8 @@ static void mwl8k_sw_scan_start(struct ieee80211_hw *hw)
priv->sw_scan_start = true; 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; struct mwl8k_priv *priv = hw->priv;
u8 tmp; u8 tmp;
......
...@@ -1437,8 +1437,11 @@ int rt2x00mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ...@@ -1437,8 +1437,11 @@ int rt2x00mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta); struct ieee80211_sta *sta);
int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta); struct ieee80211_sta *sta);
void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw); void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw,
void rt2x00mac_sw_scan_complete(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, int rt2x00mac_get_stats(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats); struct ieee80211_low_level_stats *stats);
void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
......
...@@ -568,7 +568,9 @@ int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ...@@ -568,7 +568,9 @@ int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
} }
EXPORT_SYMBOL_GPL(rt2x00mac_sta_remove); 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; struct rt2x00_dev *rt2x00dev = hw->priv;
set_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags); set_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);
...@@ -576,7 +578,8 @@ void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw) ...@@ -576,7 +578,8 @@ void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw)
} }
EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_start); 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; struct rt2x00_dev *rt2x00dev = hw->priv;
clear_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags); clear_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);
......
...@@ -1361,7 +1361,9 @@ static int rtl_op_ampdu_action(struct ieee80211_hw *hw, ...@@ -1361,7 +1361,9 @@ static int rtl_op_ampdu_action(struct ieee80211_hw *hw,
return 0; 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_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(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) ...@@ -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); 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_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
......
...@@ -1029,7 +1029,7 @@ static int wl1251_op_hw_scan(struct ieee80211_hw *hw, ...@@ -1029,7 +1029,7 @@ static int wl1251_op_hw_scan(struct ieee80211_hw *hw,
goto out_sleep; 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); req->ie_len);
if (!skb) { if (!skb) {
ret = -ENOMEM; ret = -ENOMEM;
......
...@@ -1145,7 +1145,7 @@ int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, ...@@ -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); 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); ie0_len + ie1_len);
if (!skb) { if (!skb) {
ret = -ENOMEM; ret = -ENOMEM;
......
...@@ -856,7 +856,9 @@ static int vnt_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, ...@@ -856,7 +856,9 @@ static int vnt_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
return 0; 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; struct vnt_private *priv = hw->priv;
...@@ -865,7 +867,8 @@ static void vnt_sw_scan_start(struct ieee80211_hw *hw) ...@@ -865,7 +867,8 @@ static void vnt_sw_scan_start(struct ieee80211_hw *hw)
vnt_update_pre_ed_threshold(priv, true); 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; struct vnt_private *priv = hw->priv;
......
...@@ -2622,7 +2622,9 @@ enum ieee80211_reconfig_type { ...@@ -2622,7 +2622,9 @@ enum ieee80211_reconfig_type {
* *
* @sw_scan_start: Notifier function that is called just before a software scan * @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. * 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 * @sw_scan_complete: Notifier function that is called just after a
* software scan finished. Can be NULL, if the driver doesn't need * software scan finished. Can be NULL, if the driver doesn't need
...@@ -3016,8 +3018,11 @@ struct ieee80211_ops { ...@@ -3016,8 +3018,11 @@ struct ieee80211_ops {
struct ieee80211_scan_ies *ies); struct ieee80211_scan_ies *ies);
int (*sched_scan_stop)(struct ieee80211_hw *hw, int (*sched_scan_stop)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif); struct ieee80211_vif *vif);
void (*sw_scan_start)(struct ieee80211_hw *hw); void (*sw_scan_start)(struct ieee80211_hw *hw,
void (*sw_scan_complete)(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, int (*get_stats)(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats); struct ieee80211_low_level_stats *stats);
void (*get_tkip_seq)(struct ieee80211_hw *hw, u8 hw_key_idx, 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, ...@@ -3820,7 +3825,7 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
/** /**
* ieee80211_probereq_get - retrieve a Probe Request template * ieee80211_probereq_get - retrieve a Probe Request template
* @hw: pointer obtained from ieee80211_alloc_hw(). * @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: SSID buffer
* @ssid_len: length of SSID * @ssid_len: length of SSID
* @tailroom: tailroom to reserve at end of SKB for IEs * @tailroom: tailroom to reserve at end of SKB for IEs
...@@ -3831,7 +3836,7 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw, ...@@ -3831,7 +3836,7 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
* Return: The Probe Request template. %NULL on error. * Return: The Probe Request template. %NULL on error.
*/ */
struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw, 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, const u8 *ssid, size_t ssid_len,
size_t tailroom); size_t tailroom);
......
...@@ -380,23 +380,26 @@ static inline int drv_sched_scan_stop(struct ieee80211_local *local, ...@@ -380,23 +380,26 @@ static inline int drv_sched_scan_stop(struct ieee80211_local *local,
return ret; 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(); might_sleep();
trace_drv_sw_scan_start(local); trace_drv_sw_scan_start(local, sdata, mac_addr);
if (local->ops->sw_scan_start) 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); 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(); might_sleep();
trace_drv_sw_scan_complete(local); trace_drv_sw_scan_complete(local, sdata);
if (local->ops->sw_scan_complete) 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); trace_drv_return_void(local);
} }
......
...@@ -1249,6 +1249,7 @@ struct ieee80211_local { ...@@ -1249,6 +1249,7 @@ struct ieee80211_local {
struct work_struct sched_scan_stopped_work; struct work_struct sched_scan_stopped_work;
struct ieee80211_sub_if_data __rcu *sched_scan_sdata; struct ieee80211_sub_if_data __rcu *sched_scan_sdata;
struct cfg80211_sched_scan_request __rcu *sched_scan_req; struct cfg80211_sched_scan_request __rcu *sched_scan_req;
u8 scan_addr[ETH_ALEN];
unsigned long leave_oper_channel_time; unsigned long leave_oper_channel_time;
enum mac80211_scan_state next_scan_state; enum mac80211_scan_state next_scan_state;
...@@ -1901,12 +1902,14 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, ...@@ -1901,12 +1902,14 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
u8 bands_used, u32 *rate_masks, u8 bands_used, u32 *rate_masks,
struct cfg80211_chan_def *chandef); struct cfg80211_chan_def *chandef);
struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, 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, struct ieee80211_channel *chan,
const u8 *ssid, size_t ssid_len, const u8 *ssid, size_t ssid_len,
const u8 *ie, size_t ie_len, const u8 *ie, size_t ie_len,
bool directed); 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 *ssid, size_t ssid_len,
const u8 *ie, size_t ie_len, const u8 *ie, size_t ie_len,
u32 ratemask, bool directed, u32 tx_flags, u32 ratemask, bool directed, u32 tx_flags,
......
...@@ -2225,7 +2225,8 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) ...@@ -2225,7 +2225,8 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
else else
ssid_len = ssid[1]; 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, 0, (u32) -1, true, 0,
ifmgd->associated->channel, false); ifmgd->associated->channel, false);
rcu_read_unlock(); rcu_read_unlock();
...@@ -2328,7 +2329,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, ...@@ -2328,7 +2329,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
else else
ssid_len = ssid[1]; 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, (u32) -1, cbss->channel,
ssid + 2, ssid_len, ssid + 2, ssid_len,
NULL, 0, true); NULL, 0, true);
...@@ -3649,7 +3650,8 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) ...@@ -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 * Direct probe is sent to broadcast address as some APs
* will not answer to direct packet in unassociated state. * 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, NULL, 0, (u32) -1, true, 0,
auth_data->bss->channel, false); auth_data->bss->channel, false);
rcu_read_unlock(); rcu_read_unlock();
......
...@@ -184,9 +184,21 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb) ...@@ -184,9 +184,21 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
return; return;
if (ieee80211_is_probe_resp(mgmt->frame_control)) { if (ieee80211_is_probe_resp(mgmt->frame_control)) {
/* ignore ProbeResp to foreign address */ struct cfg80211_scan_request *scan_req;
if ((!sdata1 || !ether_addr_equal(mgmt->da, sdata1->vif.addr)) && struct cfg80211_sched_scan_request *sched_scan_req;
(!sdata2 || !ether_addr_equal(mgmt->da, sdata2->vif.addr)))
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; return;
elements = mgmt->u.probe_resp.variable; elements = mgmt->u.probe_resp.variable;
...@@ -284,6 +296,9 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) ...@@ -284,6 +296,9 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
bands_used, req->rates, &chandef); bands_used, req->rates, &chandef);
local->hw_scan_req->req.ie_len = ielen; local->hw_scan_req->req.ie_len = ielen;
local->hw_scan_req->req.no_cck = req->no_cck; 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; return true;
} }
...@@ -294,6 +309,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) ...@@ -294,6 +309,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
bool hw_scan = local->ops->hw_scan; bool hw_scan = local->ops->hw_scan;
bool was_scanning = local->scanning; bool was_scanning = local->scanning;
struct cfg80211_scan_request *scan_req; struct cfg80211_scan_request *scan_req;
struct ieee80211_sub_if_data *scan_sdata;
lockdep_assert_held(&local->mtx); lockdep_assert_held(&local->mtx);
...@@ -332,6 +348,9 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) ...@@ -332,6 +348,9 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
if (scan_req != local->int_scan_req) if (scan_req != local->int_scan_req)
cfg80211_scan_done(scan_req, aborted); cfg80211_scan_done(scan_req, aborted);
RCU_INIT_POINTER(local->scan_req, NULL); 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); RCU_INIT_POINTER(local->scan_sdata, NULL);
local->scanning = 0; local->scanning = 0;
...@@ -342,7 +361,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) ...@@ -342,7 +361,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
if (!hw_scan) { if (!hw_scan) {
ieee80211_configure_filter(local); ieee80211_configure_filter(local);
drv_sw_scan_complete(local); drv_sw_scan_complete(local, scan_sdata);
ieee80211_offchannel_return(local); ieee80211_offchannel_return(local);
} }
...@@ -368,7 +387,8 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) ...@@ -368,7 +387,8 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
} }
EXPORT_SYMBOL(ieee80211_scan_completed); 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 */ /* Software scan is not supported in multi-channel cases */
if (local->use_chanctx) if (local->use_chanctx)
...@@ -387,7 +407,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) ...@@ -387,7 +407,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
* nullfunc frames and probe requests will be dropped in * nullfunc frames and probe requests will be dropped in