diff options
author | Antonio Quartulli <antonio@open-mesh.com> | 2014-01-29 17:53:43 +0100 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2014-02-04 21:58:16 +0100 |
commit | fe94f3a4ffaa20c7470038c69ffc8e545ef5f90a (patch) | |
tree | a8056f9f9e74e30679bb4fc852dfe19bd680f51e /net/wireless | |
parent | 67235cbca44f082e9c4c2ed370f9afe5fc478d49 (diff) | |
download | op-kernel-dev-fe94f3a4ffaa20c7470038c69ffc8e545ef5f90a.zip op-kernel-dev-fe94f3a4ffaa20c7470038c69ffc8e545ef5f90a.tar.gz |
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>
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/core.h | 4 | ||||
-rw-r--r-- | net/wireless/ibss.c | 17 | ||||
-rw-r--r-- | net/wireless/trace.h | 23 | ||||
-rw-r--r-- | net/wireless/util.c | 3 |
4 files changed, 34 insertions, 13 deletions
diff --git a/net/wireless/core.h b/net/wireless/core.h index 37ec16d..8a820f9 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -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); diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index f911c5f9f..e37e39c 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c @@ -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); diff --git a/net/wireless/trace.h b/net/wireless/trace.h index fbcc23e..5eaeed5 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h @@ -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), diff --git a/net/wireless/util.c b/net/wireless/util.c index d39c371..7526a4d 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -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); |