aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntonio Quartulli <antonio@open-mesh.com>2014-01-29 11:53:43 -0500
committerJohannes Berg <johannes.berg@intel.com>2014-02-04 15:58:16 -0500
commitfe94f3a4ffaa20c7470038c69ffc8e545ef5f90a (patch)
treea8056f9f9e74e30679bb4fc852dfe19bd680f51e
parent67235cbca44f082e9c4c2ed370f9afe5fc478d49 (diff)
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>
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c8
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c4
-rw-r--r--drivers/net/wireless/libertas/cfg.c3
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.c3
-rw-r--r--drivers/net/wireless/rndis_wlan.c4
-rw-r--r--include/net/cfg80211.h4
-rw-r--r--net/mac80211/ibss.c2
-rw-r--r--net/wireless/core.h4
-rw-r--r--net/wireless/ibss.c17
-rw-r--r--net/wireless/trace.h23
-rw-r--r--net/wireless/util.c3
11 files changed, 50 insertions, 25 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index eba32f56850a..c2c6f4604958 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -790,7 +790,7 @@ void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel,
790 if (nw_type & ADHOC_NETWORK) { 790 if (nw_type & ADHOC_NETWORK) {
791 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "ad-hoc %s selected\n", 791 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "ad-hoc %s selected\n",
792 nw_type & ADHOC_CREATOR ? "creator" : "joiner"); 792 nw_type & ADHOC_CREATOR ? "creator" : "joiner");
793 cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL); 793 cfg80211_ibss_joined(vif->ndev, bssid, chan, GFP_KERNEL);
794 cfg80211_put_bss(ar->wiphy, bss); 794 cfg80211_put_bss(ar->wiphy, bss);
795 return; 795 return;
796 } 796 }
@@ -861,13 +861,9 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason,
861 } 861 }
862 862
863 if (vif->nw_type & ADHOC_NETWORK) { 863 if (vif->nw_type & ADHOC_NETWORK) {
864 if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC) { 864 if (vif->wdev.iftype != NL80211_IFTYPE_ADHOC)
865 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, 865 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
866 "%s: ath6k not in ibss mode\n", __func__); 866 "%s: ath6k not in ibss mode\n", __func__);
867 return;
868 }
869 memset(bssid, 0, ETH_ALEN);
870 cfg80211_ibss_joined(vif->ndev, bssid, GFP_KERNEL);
871 return; 867 return;
872 } 868 }
873 869
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index 3d25c18340c5..1a80bf19cb89 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -4658,6 +4658,7 @@ brcmf_notify_connect_status(struct brcmf_if *ifp,
4658 struct brcmf_cfg80211_info *cfg = ifp->drvr->config; 4658 struct brcmf_cfg80211_info *cfg = ifp->drvr->config;
4659 struct net_device *ndev = ifp->ndev; 4659 struct net_device *ndev = ifp->ndev;
4660 struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; 4660 struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
4661 struct ieee80211_channel *chan;
4661 s32 err = 0; 4662 s32 err = 0;
4662 4663
4663 if (ifp->vif->mode == WL_MODE_AP) { 4664 if (ifp->vif->mode == WL_MODE_AP) {
@@ -4665,9 +4666,10 @@ brcmf_notify_connect_status(struct brcmf_if *ifp,
4665 } else if (brcmf_is_linkup(e)) { 4666 } else if (brcmf_is_linkup(e)) {
4666 brcmf_dbg(CONN, "Linkup\n"); 4667 brcmf_dbg(CONN, "Linkup\n");
4667 if (brcmf_is_ibssmode(ifp->vif)) { 4668 if (brcmf_is_ibssmode(ifp->vif)) {
4669 chan = ieee80211_get_channel(cfg->wiphy, cfg->channel);
4668 memcpy(profile->bssid, e->addr, ETH_ALEN); 4670 memcpy(profile->bssid, e->addr, ETH_ALEN);
4669 wl_inform_ibss(cfg, ndev, e->addr); 4671 wl_inform_ibss(cfg, ndev, e->addr);
4670 cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL); 4672 cfg80211_ibss_joined(ndev, e->addr, chan, GFP_KERNEL);
4671 clear_bit(BRCMF_VIF_STATUS_CONNECTING, 4673 clear_bit(BRCMF_VIF_STATUS_CONNECTING,
4672 &ifp->vif->sme_state); 4674 &ifp->vif->sme_state);
4673 set_bit(BRCMF_VIF_STATUS_CONNECTED, 4675 set_bit(BRCMF_VIF_STATUS_CONNECTED,
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index 32f75007a825..2d72a6b4b93e 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -1766,7 +1766,8 @@ static void lbs_join_post(struct lbs_private *priv,
1766 memcpy(priv->wdev->ssid, params->ssid, params->ssid_len); 1766 memcpy(priv->wdev->ssid, params->ssid, params->ssid_len);
1767 priv->wdev->ssid_len = params->ssid_len; 1767 priv->wdev->ssid_len = params->ssid_len;
1768 1768
1769 cfg80211_ibss_joined(priv->dev, bssid, GFP_KERNEL); 1769 cfg80211_ibss_joined(priv->dev, bssid, params->chandef.chan,
1770 GFP_KERNEL);
1770 1771
1771 /* TODO: consider doing this at MACREG_INT_CODE_LINK_SENSED time */ 1772 /* TODO: consider doing this at MACREG_INT_CODE_LINK_SENSED time */
1772 priv->connect_status = LBS_CONNECTED; 1773 priv->connect_status = LBS_CONNECTED;
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index f4cf9c9d40ec..0948ebe8942e 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -1882,7 +1882,8 @@ mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
1882 params->privacy); 1882 params->privacy);
1883done: 1883done:
1884 if (!ret) { 1884 if (!ret) {
1885 cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, GFP_KERNEL); 1885 cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid,
1886 params->chandef.chan, GFP_KERNEL);
1886 dev_dbg(priv->adapter->dev, 1887 dev_dbg(priv->adapter->dev,
1887 "info: joined/created adhoc network with bssid" 1888 "info: joined/created adhoc network with bssid"
1888 " %pM successfully\n", priv->cfg_bssid); 1889 " %pM successfully\n", priv->cfg_bssid);
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 5028557aa18a..2e89a865a67d 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -2835,7 +2835,9 @@ static void rndis_wlan_do_link_up_work(struct usbnet *usbdev)
2835 bssid, req_ie, req_ie_len, 2835 bssid, req_ie, req_ie_len,
2836 resp_ie, resp_ie_len, GFP_KERNEL); 2836 resp_ie, resp_ie_len, GFP_KERNEL);
2837 } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC) 2837 } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC)
2838 cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL); 2838 cfg80211_ibss_joined(usbdev->net, bssid,
2839 get_current_channel(usbdev, NULL),
2840 GFP_KERNEL);
2839 2841
2840 kfree(info); 2842 kfree(info);
2841 2843
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 009290e36d15..c68201d78b90 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3895,6 +3895,7 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
3895 * 3895 *
3896 * @dev: network device 3896 * @dev: network device
3897 * @bssid: the BSSID of the IBSS joined 3897 * @bssid: the BSSID of the IBSS joined
3898 * @channel: the channel of the IBSS joined
3898 * @gfp: allocation flags 3899 * @gfp: allocation flags
3899 * 3900 *
3900 * This function notifies cfg80211 that the device joined an IBSS or 3901 * 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,
3904 * with the locally generated beacon -- this guarantees that there is 3905 * with the locally generated beacon -- this guarantees that there is
3905 * always a scan result for this IBSS. cfg80211 will handle the rest. 3906 * always a scan result for this IBSS. cfg80211 will handle the rest.
3906 */ 3907 */
3907void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp); 3908void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
3909 struct ieee80211_channel *channel, gfp_t gfp);
3908 3910
3909/** 3911/**
3910 * cfg80211_notify_new_candidate - notify cfg80211 of a new mesh peer candidate 3912 * cfg80211_notify_new_candidate - notify cfg80211 of a new mesh peer candidate
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 8e444476307a..9c84b75f3de8 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -382,7 +382,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
382 presp->head_len, 0, GFP_KERNEL); 382 presp->head_len, 0, GFP_KERNEL);
383 cfg80211_put_bss(local->hw.wiphy, bss); 383 cfg80211_put_bss(local->hw.wiphy, bss);
384 netif_carrier_on(sdata->dev); 384 netif_carrier_on(sdata->dev);
385 cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL); 385 cfg80211_ibss_joined(sdata->dev, ifibss->bssid, chan, GFP_KERNEL);
386} 386}
387 387
388static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, 388static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 37ec16d7bb1a..8a820f9c4a76 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -210,6 +210,7 @@ struct cfg80211_event {
210 } dc; 210 } dc;
211 struct { 211 struct {
212 u8 bssid[ETH_ALEN]; 212 u8 bssid[ETH_ALEN];
213 struct ieee80211_channel *channel;
213 } ij; 214 } ij;
214 }; 215 };
215}; 216};
@@ -257,7 +258,8 @@ int __cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
257 struct net_device *dev, bool nowext); 258 struct net_device *dev, bool nowext);
258int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, 259int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev,
259 struct net_device *dev, bool nowext); 260 struct net_device *dev, bool nowext);
260void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid); 261void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
262 struct ieee80211_channel *channel);
261int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, 263int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
262 struct wireless_dev *wdev); 264 struct wireless_dev *wdev);
263 265
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index f911c5f9f903..e37e39c29dfb 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -14,7 +14,8 @@
14#include "rdev-ops.h" 14#include "rdev-ops.h"
15 15
16 16
17void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid) 17void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
18 struct ieee80211_channel *channel)
18{ 19{
19 struct wireless_dev *wdev = dev->ieee80211_ptr; 20 struct wireless_dev *wdev = dev->ieee80211_ptr;
20 struct cfg80211_bss *bss; 21 struct cfg80211_bss *bss;
@@ -28,8 +29,7 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
28 if (!wdev->ssid_len) 29 if (!wdev->ssid_len)
29 return; 30 return;
30 31
31 bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, 32 bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, NULL, 0,
32 wdev->ssid, wdev->ssid_len,
33 WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS); 33 WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS);
34 34
35 if (WARN_ON(!bss)) 35 if (WARN_ON(!bss))
@@ -54,21 +54,26 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid)
54#endif 54#endif
55} 55}
56 56
57void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp) 57void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid,
58 struct ieee80211_channel *channel, gfp_t gfp)
58{ 59{
59 struct wireless_dev *wdev = dev->ieee80211_ptr; 60 struct wireless_dev *wdev = dev->ieee80211_ptr;
60 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); 61 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
61 struct cfg80211_event *ev; 62 struct cfg80211_event *ev;
62 unsigned long flags; 63 unsigned long flags;
63 64
64 trace_cfg80211_ibss_joined(dev, bssid); 65 trace_cfg80211_ibss_joined(dev, bssid, channel);
66
67 if (WARN_ON(!channel))
68 return;
65 69
66 ev = kzalloc(sizeof(*ev), gfp); 70 ev = kzalloc(sizeof(*ev), gfp);
67 if (!ev) 71 if (!ev)
68 return; 72 return;
69 73
70 ev->type = EVENT_IBSS_JOINED; 74 ev->type = EVENT_IBSS_JOINED;
71 memcpy(ev->cr.bssid, bssid, ETH_ALEN); 75 memcpy(ev->ij.bssid, bssid, ETH_ALEN);
76 ev->ij.channel = channel;
72 77
73 spin_lock_irqsave(&wdev->event_lock, flags); 78 spin_lock_irqsave(&wdev->event_lock, flags);
74 list_add_tail(&ev->list, &wdev->event_list); 79 list_add_tail(&ev->list, &wdev->event_list);
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index fbcc23edee54..5eaeed59db07 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -2278,11 +2278,6 @@ DECLARE_EVENT_CLASS(cfg80211_rx_evt,
2278 TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT, NETDEV_PR_ARG, MAC_PR_ARG(addr)) 2278 TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT, NETDEV_PR_ARG, MAC_PR_ARG(addr))
2279); 2279);
2280 2280
2281DEFINE_EVENT(cfg80211_rx_evt, cfg80211_ibss_joined,
2282 TP_PROTO(struct net_device *netdev, const u8 *addr),
2283 TP_ARGS(netdev, addr)
2284);
2285
2286DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_spurious_frame, 2281DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_spurious_frame,
2287 TP_PROTO(struct net_device *netdev, const u8 *addr), 2282 TP_PROTO(struct net_device *netdev, const u8 *addr),
2288 TP_ARGS(netdev, addr) 2283 TP_ARGS(netdev, addr)
@@ -2293,6 +2288,24 @@ DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_unexpected_4addr_frame,
2293 TP_ARGS(netdev, addr) 2288 TP_ARGS(netdev, addr)
2294); 2289);
2295 2290
2291TRACE_EVENT(cfg80211_ibss_joined,
2292 TP_PROTO(struct net_device *netdev, const u8 *bssid,
2293 struct ieee80211_channel *channel),
2294 TP_ARGS(netdev, bssid, channel),
2295 TP_STRUCT__entry(
2296 NETDEV_ENTRY
2297 MAC_ENTRY(bssid)
2298 CHAN_ENTRY
2299 ),
2300 TP_fast_assign(
2301 NETDEV_ASSIGN;
2302 MAC_ASSIGN(bssid, bssid);
2303 CHAN_ASSIGN(channel);
2304 ),
2305 TP_printk(NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", " CHAN_PR_FMT,
2306 NETDEV_PR_ARG, MAC_PR_ARG(bssid), CHAN_PR_ARG)
2307);
2308
2296TRACE_EVENT(cfg80211_probe_status, 2309TRACE_EVENT(cfg80211_probe_status,
2297 TP_PROTO(struct net_device *netdev, const u8 *addr, u64 cookie, 2310 TP_PROTO(struct net_device *netdev, const u8 *addr, u64 cookie,
2298 bool acked), 2311 bool acked),
diff --git a/net/wireless/util.c b/net/wireless/util.c
index d39c37104ae2..7526a4d8aa16 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -820,7 +820,8 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev)
820 ev->dc.reason, true); 820 ev->dc.reason, true);
821 break; 821 break;
822 case EVENT_IBSS_JOINED: 822 case EVENT_IBSS_JOINED:
823 __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid); 823 __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid,
824 ev->ij.channel);
824 break; 825 break;
825 } 826 }
826 wdev_unlock(wdev); 827 wdev_unlock(wdev);