Commit 6b77863b authored by Johannes Berg's avatar Johannes Berg

mac80211: fix current vs. operating channel in preq/beacon

When sending probe requests, e.g. during software scanning,
these will go out on the *current* channel, so their IEs
need to be built from the current channel. At other times,
e.g. for beacons or probe request templates, the IEs will
be used on the *operating* channel and using the current
channel instead might result in errors.

Add the appropriate parameters to respect the difference.
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 679ef4ea
...@@ -2655,6 +2655,7 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, ...@@ -2655,6 +2655,7 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
u16 status_code, struct sk_buff *skb) u16 status_code, struct sk_buff *skb)
{ {
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
struct ieee80211_tdls_data *tf; struct ieee80211_tdls_data *tf;
tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u)); tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
...@@ -2674,8 +2675,10 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, ...@@ -2674,8 +2675,10 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
tf->u.setup_req.capability = tf->u.setup_req.capability =
cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
ieee80211_add_srates_ie(sdata, skb, false); ieee80211_add_srates_ie(sdata, skb, false,
ieee80211_add_ext_srates_ie(sdata, skb, false); local->oper_channel->band);
ieee80211_add_ext_srates_ie(sdata, skb, false,
local->oper_channel->band);
ieee80211_tdls_add_ext_capab(skb); ieee80211_tdls_add_ext_capab(skb);
break; break;
case WLAN_TDLS_SETUP_RESPONSE: case WLAN_TDLS_SETUP_RESPONSE:
...@@ -2688,8 +2691,10 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, ...@@ -2688,8 +2691,10 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
tf->u.setup_resp.capability = tf->u.setup_resp.capability =
cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
ieee80211_add_srates_ie(sdata, skb, false); ieee80211_add_srates_ie(sdata, skb, false,
ieee80211_add_ext_srates_ie(sdata, skb, false); local->oper_channel->band);
ieee80211_add_ext_srates_ie(sdata, skb, false,
local->oper_channel->band);
ieee80211_tdls_add_ext_capab(skb); ieee80211_tdls_add_ext_capab(skb);
break; break;
case WLAN_TDLS_SETUP_CONFIRM: case WLAN_TDLS_SETUP_CONFIRM:
...@@ -2727,6 +2732,7 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, ...@@ -2727,6 +2732,7 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev,
u16 status_code, struct sk_buff *skb) u16 status_code, struct sk_buff *skb)
{ {
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
struct ieee80211_mgmt *mgmt; struct ieee80211_mgmt *mgmt;
mgmt = (void *)skb_put(skb, 24); mgmt = (void *)skb_put(skb, 24);
...@@ -2749,8 +2755,10 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, ...@@ -2749,8 +2755,10 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev,
mgmt->u.action.u.tdls_discover_resp.capability = mgmt->u.action.u.tdls_discover_resp.capability =
cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
ieee80211_add_srates_ie(sdata, skb, false); ieee80211_add_srates_ie(sdata, skb, false,
ieee80211_add_ext_srates_ie(sdata, skb, false); local->oper_channel->band);
ieee80211_add_ext_srates_ie(sdata, skb, false,
local->oper_channel->band);
ieee80211_tdls_add_ext_capab(skb); ieee80211_tdls_add_ext_capab(skb);
break; break;
default: default:
......
...@@ -1459,6 +1459,7 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, ...@@ -1459,6 +1459,7 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
u8 channel); u8 channel);
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, u8 *dst, u32 ratemask,
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);
...@@ -1489,9 +1490,11 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, ...@@ -1489,9 +1490,11 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
u32 cap); u32 cap);
int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb, bool need_basic); struct sk_buff *skb, bool need_basic,
enum ieee80211_band band);
int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb, bool need_basic); struct sk_buff *skb, bool need_basic,
enum ieee80211_band band);
/* channel management */ /* channel management */
enum ieee80211_chan_mode { enum ieee80211_chan_mode {
......
...@@ -258,8 +258,10 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, ...@@ -258,8 +258,10 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
pos = skb_put(skb, 2); pos = skb_put(skb, 2);
memcpy(pos + 2, &plid, 2); memcpy(pos + 2, &plid, 2);
} }
if (ieee80211_add_srates_ie(sdata, skb, true) || if (ieee80211_add_srates_ie(sdata, skb, true,
ieee80211_add_ext_srates_ie(sdata, skb, true) || local->oper_channel->band) ||
ieee80211_add_ext_srates_ie(sdata, skb, true,
local->oper_channel->band) ||
mesh_add_rsn_ie(skb, sdata) || mesh_add_rsn_ie(skb, sdata) ||
mesh_add_meshid_ie(skb, sdata) || mesh_add_meshid_ie(skb, sdata) ||
mesh_add_meshconf_ie(skb, sdata)) mesh_add_meshconf_ie(skb, sdata))
......
...@@ -1683,7 +1683,9 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, ...@@ -1683,7 +1683,9 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
ssid_len = ssid[1]; ssid_len = ssid[1];
skb = ieee80211_build_probe_req(sdata, cbss->bssid, skb = ieee80211_build_probe_req(sdata, cbss->bssid,
(u32) -1, ssid + 2, ssid_len, (u32) -1,
sdata->local->oper_channel,
ssid + 2, ssid_len,
NULL, 0, true); NULL, 0, true);
return skb; return skb;
......
...@@ -2303,7 +2303,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, ...@@ -2303,7 +2303,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
struct ieee80211_if_ap *ap = NULL; struct ieee80211_if_ap *ap = NULL;
struct beacon_data *beacon; struct beacon_data *beacon;
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
enum ieee80211_band band = local->hw.conf.channel->band; enum ieee80211_band band = local->oper_channel->band;
struct ieee80211_tx_rate_control txrc; struct ieee80211_tx_rate_control txrc;
sband = local->hw.wiphy->bands[band]; sband = local->hw.wiphy->bands[band];
...@@ -2429,9 +2429,9 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, ...@@ -2429,9 +2429,9 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
*pos++ = WLAN_EID_SSID; *pos++ = WLAN_EID_SSID;
*pos++ = 0x0; *pos++ = 0x0;
if (ieee80211_add_srates_ie(sdata, skb, true) || if (ieee80211_add_srates_ie(sdata, skb, true, band) ||
mesh_add_ds_params_ie(skb, sdata) || mesh_add_ds_params_ie(skb, sdata) ||
ieee80211_add_ext_srates_ie(sdata, skb, true) || ieee80211_add_ext_srates_ie(sdata, skb, true, band) ||
mesh_add_rsn_ie(skb, sdata) || mesh_add_rsn_ie(skb, sdata) ||
mesh_add_ht_cap_ie(skb, sdata) || mesh_add_ht_cap_ie(skb, sdata) ||
mesh_add_ht_oper_ie(skb, sdata) || mesh_add_ht_oper_ie(skb, sdata) ||
......
...@@ -1100,6 +1100,7 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, ...@@ -1100,6 +1100,7 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
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, u8 *dst, u32 ratemask,
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)
...@@ -1109,7 +1110,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, ...@@ -1109,7 +1110,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt; struct ieee80211_mgmt *mgmt;
size_t buf_len; size_t buf_len;
u8 *buf; u8 *buf;
u8 chan; u8 chan_no;
/* FIXME: come up with a proper value */ /* FIXME: come up with a proper value */
buf = kmalloc(200 + ie_len, GFP_KERNEL); buf = kmalloc(200 + ie_len, GFP_KERNEL);
...@@ -1122,14 +1123,12 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, ...@@ -1122,14 +1123,12 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
* badly-behaved APs don't respond when this parameter is included. * badly-behaved APs don't respond when this parameter is included.
*/ */
if (directed) if (directed)
chan = 0; chan_no = 0;
else else
chan = ieee80211_frequency_to_channel( chan_no = ieee80211_frequency_to_channel(chan->center_freq);
local->hw.conf.channel->center_freq);
buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len, buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len, chan->band,
local->hw.conf.channel->band, ratemask, chan_no);
ratemask, chan);
skb = ieee80211_probereq_get(&local->hw, &sdata->vif, skb = ieee80211_probereq_get(&local->hw, &sdata->vif,
ssid, ssid_len, ssid, ssid_len,
...@@ -1158,7 +1157,9 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, ...@@ -1158,7 +1157,9 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
{ {
struct sk_buff *skb; struct sk_buff *skb;
skb = ieee80211_build_probe_req(sdata, dst, ratemask, ssid, ssid_len, skb = ieee80211_build_probe_req(sdata, dst, ratemask,
sdata->local->hw.conf.channel,
ssid, ssid_len,
ie, ie_len, directed); ie, ie_len, directed);
if (skb) { if (skb) {
if (no_cck) if (no_cck)
...@@ -1810,7 +1811,8 @@ ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper) ...@@ -1810,7 +1811,8 @@ ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper)
} }
int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb, bool need_basic) struct sk_buff *skb, bool need_basic,
enum ieee80211_band band)
{ {
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
...@@ -1818,7 +1820,7 @@ int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, ...@@ -1818,7 +1820,7 @@ int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata,
u8 i, rates, *pos; u8 i, rates, *pos;
u32 basic_rates = sdata->vif.bss_conf.basic_rates; u32 basic_rates = sdata->vif.bss_conf.basic_rates;
sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; sband = local->hw.wiphy->bands[band];
rates = sband->n_bitrates; rates = sband->n_bitrates;
if (rates > 8) if (rates > 8)
rates = 8; rates = 8;
...@@ -1841,7 +1843,8 @@ int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, ...@@ -1841,7 +1843,8 @@ int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata,
} }
int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb, bool need_basic) struct sk_buff *skb, bool need_basic,
enum ieee80211_band band)
{ {
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
...@@ -1849,7 +1852,7 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, ...@@ -1849,7 +1852,7 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata,
u8 i, exrates, *pos; u8 i, exrates, *pos;
u32 basic_rates = sdata->vif.bss_conf.basic_rates; u32 basic_rates = sdata->vif.bss_conf.basic_rates;
sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; sband = local->hw.wiphy->bands[band];
exrates = sband->n_bitrates; exrates = sband->n_bitrates;
if (exrates > 8) if (exrates > 8)
exrates -= 8; exrates -= 8;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment