mirror of https://gitee.com/openkylin/linux.git
cfg80211: fix channel configuration in IBSS join
When receiving an IBSS_JOINED event select the BSS object based on the {bssid, channel} couple rather than the bssid only. With the current approach if another cell having the same BSSID (but using a different channel) exists then cfg80211 picks up the wrong BSS object. The result is a mismatching channel configuration between cfg80211 and the driver, that can lead to any sort of problem. The issue can be triggered by having an IBSS sitting on given channel and then asking the driver to create a new cell using the same BSSID but with a different frequency. By passing the channel to cfg80211_get_bss() we can solve this ambiguity and retrieve/create the correct BSS object. All the users of cfg80211_ibss_joined() have been changed accordingly. Moreover WARN when cfg80211_ibss_joined() gets a NULL channel as argument and remove a bogus call of the same function in ath6kl (it does not make sense to call cfg80211_ibss_joined() with a zero BSSID on ibss-leave). Cc: Kalle Valo <kvalo@qca.qualcomm.com> Cc: Arend van Spriel <arend@broadcom.com> Cc: Bing Zhao <bzhao@marvell.com> Cc: Jussi Kivilinna <jussi.kivilinna@iki.fi> Cc: libertas-dev@lists.infradead.org Acked-by: Kalle Valo <kvalo@qca.qualcomm.com> Signed-off-by: Antonio Quartulli <antonio@open-mesh.com> [minor code cleanup in ath6kl] Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
67235cbca4
commit
fe94f3a4ff
|
@ -790,7 +790,7 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel,
|
|||
if (nw_type & ADHOC_NETWORK) {
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "ad-hoc %s selected\n",
|
||||
nw_type & ADHOC_CREATOR ? "creator" : "joiner");
|
||||
cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
|
||||
cfg80211_ibss_joined(vif->ndev, bssid, chan, GFP_KERNEL);
|
||||
cfg80211_put_bss(ar->wiphy, bss);
|
||||
return;
|
||||
}
|
||||
|
@ -861,13 +861,9 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
|
|||
}
|
||||
|
||||
if (vif->nw_type & ADHOC_NETWORK) {
|
||||
if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC) {
|
||||
if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC)
|
||||
ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
|
||||
"%s: ath6k not in ibss mode\n", __func__);
|
||||
return;
|
||||
}
|
||||
memset(bssid, 0, ETH_ALEN);
|
||||
cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -4658,6 +4658,7 @@ brcmf_notify_connect_status(struct brcmf_if *ifp,
|
|||
struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
|
||||
struct net_device *ndev = ifp->ndev;
|
||||
struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
|
||||
struct ieee80211_channel *chan;
|
||||
s32 err = 0;
|
||||
|
||||
if (ifp->vif->mode == WL_MODE_AP) {
|
||||
|
@ -4665,9 +4666,10 @@ brcmf_notify_connect_status(struct brcmf_if *ifp,
|
|||
} else if (brcmf_is_linkup(e)) {
|
||||
brcmf_dbg(CONN, "Linkup\n");
|
||||
if (brcmf_is_ibssmode(ifp->vif)) {
|
||||
chan = ieee80211_get_channel(cfg->wiphy, cfg->channel);
|
||||
memcpy(profile->bssid, e->addr, ETH_ALEN);
|
||||
wl_inform_ibss(cfg, ndev, e->addr);
|
||||
cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL);
|
||||
cfg80211_ibss_joined(ndev, e->addr, chan, GFP_KERNEL);
|
||||
clear_bit(BRCMF_VIF_STATUS_CONNECTING,
|
||||
&ifp->vif->sme_state);
|
||||
set_bit(BRCMF_VIF_STATUS_CONNECTED,
|
||||
|
|
|
@ -1766,7 +1766,8 @@ static void lbs_join_post(struct lbs_private *priv,
|
|||
memcpy(priv->wdev->ssid, params->ssid, params->ssid_len);
|
||||
priv->wdev->ssid_len = params->ssid_len;
|
||||
|
||||
cfg80211_ibss_joined(priv->dev, bssid, GFP_KERNEL);
|
||||
cfg80211_ibss_joined(priv->dev, bssid, params->chandef.chan,
|
||||
GFP_KERNEL);
|
||||
|
||||
/* TODO: consider doing this at MACREG_INT_CODE_LINK_SENSED time */
|
||||
priv->connect_status = LBS_CONNECTED;
|
||||
|
|
|
@ -1882,7 +1882,8 @@ mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
|
|||
params->privacy);
|
||||
done:
|
||||
if (!ret) {
|
||||
cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, GFP_KERNEL);
|
||||
cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid,
|
||||
params->chandef.chan, GFP_KERNEL);
|
||||
dev_dbg(priv->adapter->dev,
|
||||
"info: joined/created adhoc network with bssid"
|
||||
" %pM successfully\n", priv->cfg_bssid);
|
||||
|
|
|
@ -2835,7 +2835,9 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev)
|
|||
bssid, req_ie, req_ie_len,
|
||||
resp_ie, resp_ie_len, GFP_KERNEL);
|
||||
} else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC)
|
||||
cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL);
|
||||
cfg80211_ibss_joined(usbdev->net, bssid,
|
||||
get_current_channel(usbdev, NULL),
|
||||
GFP_KERNEL);
|
||||
|
||||
kfree(info);
|
||||
|
||||
|
|
|
@ -3895,6 +3895,7 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
|
|||
*
|
||||
* @dev: network device
|
||||
* @bssid: the BSSID of the IBSS joined
|
||||
* @channel: the channel of the IBSS joined
|
||||
* @gfp: allocation flags
|
||||
*
|
||||
* This function notifies cfg80211 that the device joined an IBSS or
|
||||
|
@ -3904,7 +3905,8 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
|
|||
* with the locally generated beacon -- this guarantees that there is
|
||||
* always a scan result for this IBSS. cfg80211 will handle the rest.
|
||||
*/
|
||||
void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp);
|
||||
void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
|
||||
struct ieee80211_channel *channel, gfp_t gfp);
|
||||
|
||||
/**
|
||||
* cfg80211_notify_new_candidate - notify cfg80211 of a new mesh peer candidate
|
||||
|
|
|
@ -382,7 +382,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
|
|||
presp->head_len, 0, GFP_KERNEL);
|
||||
cfg80211_put_bss(local->hw.wiphy, bss);
|
||||
netif_carrier_on(sdata->dev);
|
||||
cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL);
|
||||
cfg80211_ibss_joined(sdata->dev, ifibss->bssid, chan, GFP_KERNEL);
|
||||
}
|
||||
|
||||
static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
|
||||
|
|
|
@ -210,6 +210,7 @@ struct cfg80211_event {
|
|||
} dc;
|
||||
struct {
|
||||
u8 bssid[ETH_ALEN];
|
||||
struct ieee80211_channel *channel;
|
||||
} ij;
|
||||
};
|
||||
};
|
||||
|
@ -257,7 +258,8 @@ int __cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
|
|||
struct net_device *dev, bool nowext);
|
||||
int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
|
||||
struct net_device *dev, bool nowext);
|
||||
void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid);
|
||||
void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
|
||||
struct ieee80211_channel *channel);
|
||||
int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev);
|
||||
|
||||
|
|
|
@ -14,7 +14,8 @@
|
|||
#include "rdev-ops.h"
|
||||
|
||||
|
||||
void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
|
||||
void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
|
||||
struct ieee80211_channel *channel)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct cfg80211_bss *bss;
|
||||
|
@ -28,8 +29,7 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
|
|||
if (!wdev->ssid_len)
|
||||
return;
|
||||
|
||||
bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid,
|
||||
wdev->ssid, wdev->ssid_len,
|
||||
bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, NULL, 0,
|
||||
WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS);
|
||||
|
||||
if (WARN_ON(!bss))
|
||||
|
@ -54,21 +54,26 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
|
|||
#endif
|
||||
}
|
||||
|
||||
void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp)
|
||||
void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
|
||||
struct ieee80211_channel *channel, gfp_t gfp)
|
||||
{
|
||||
struct wireless_dev *wdev = dev->ieee80211_ptr;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
|
||||
struct cfg80211_event *ev;
|
||||
unsigned long flags;
|
||||
|
||||
trace_cfg80211_ibss_joined(dev, bssid);
|
||||
trace_cfg80211_ibss_joined(dev, bssid, channel);
|
||||
|
||||
if (WARN_ON(!channel))
|
||||
return;
|
||||
|
||||
ev = kzalloc(sizeof(*ev), gfp);
|
||||
if (!ev)
|
||||
return;
|
||||
|
||||
ev->type = EVENT_IBSS_JOINED;
|
||||
memcpy(ev->cr.bssid, bssid, ETH_ALEN);
|
||||
memcpy(ev->ij.bssid, bssid, ETH_ALEN);
|
||||
ev->ij.channel = channel;
|
||||
|
||||
spin_lock_irqsave(&wdev->event_lock, flags);
|
||||
list_add_tail(&ev->list, &wdev->event_list);
|
||||
|
|
|
@ -2278,11 +2278,6 @@ DECLARE_EVENT_CLASS(cfg80211_rx_evt,
|
|||
TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT, NETDEV_PR_ARG, MAC_PR_ARG(addr))
|
||||
);
|
||||
|
||||
DEFINE_EVENT(cfg80211_rx_evt, cfg80211_ibss_joined,
|
||||
TP_PROTO(struct net_device *netdev, const u8 *addr),
|
||||
TP_ARGS(netdev, addr)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_spurious_frame,
|
||||
TP_PROTO(struct net_device *netdev, const u8 *addr),
|
||||
TP_ARGS(netdev, addr)
|
||||
|
@ -2293,6 +2288,24 @@ DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_unexpected_4addr_frame,
|
|||
TP_ARGS(netdev, addr)
|
||||
);
|
||||
|
||||
TRACE_EVENT(cfg80211_ibss_joined,
|
||||
TP_PROTO(struct net_device *netdev, const u8 *bssid,
|
||||
struct ieee80211_channel *channel),
|
||||
TP_ARGS(netdev, bssid, channel),
|
||||
TP_STRUCT__entry(
|
||||
NETDEV_ENTRY
|
||||
MAC_ENTRY(bssid)
|
||||
CHAN_ENTRY
|
||||
),
|
||||
TP_fast_assign(
|
||||
NETDEV_ASSIGN;
|
||||
MAC_ASSIGN(bssid, bssid);
|
||||
CHAN_ASSIGN(channel);
|
||||
),
|
||||
TP_printk(NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", " CHAN_PR_FMT,
|
||||
NETDEV_PR_ARG, MAC_PR_ARG(bssid), CHAN_PR_ARG)
|
||||
);
|
||||
|
||||
TRACE_EVENT(cfg80211_probe_status,
|
||||
TP_PROTO(struct net_device *netdev, const u8 *addr, u64 cookie,
|
||||
bool acked),
|
||||
|
|
|
@ -820,7 +820,8 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev)
|
|||
ev->dc.reason, true);
|
||||
break;
|
||||
case EVENT_IBSS_JOINED:
|
||||
__cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid);
|
||||
__cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid,
|
||||
ev->ij.channel);
|
||||
break;
|
||||
}
|
||||
wdev_unlock(wdev);
|
||||
|
|
Loading…
Reference in New Issue