Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

cfg80211: Use consistent BSS matching between scan and sme

cfg80211 scan code adds separate BSS entries if the same BSS shows up
on multiple channels. However, sme implementation does not use the
frequency when fetching the BSS entry. Fix this by adding channel
information to cfg80211_roamed() and include it in cfg80211_get_bss()
calls.

Please note that drivers using cfg80211_roamed() need to be modified to
fully implement this fix. This commit includes only minimal changes to
avoid compilation issues; it maintains the old (broken) behavior for
most drivers. ath6kl was the only one that I could test, so I updated
it to provide the operating frequency in the roamed event.

Signed-off-by: Jouni Malinen <jouni.malinen@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

authored by

Jouni Malinen and committed by
John W. Linville
ed9d0102 79d2b157

+31 -15
+2 -2
drivers/net/wireless/iwmc3200wifi/rx.c
··· 565 565 if (!test_and_clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status) 566 566 && iwm->conf.mode == UMAC_MODE_BSS) { 567 567 cancel_delayed_work(&iwm->disconnect); 568 - cfg80211_roamed(iwm_to_ndev(iwm), 568 + cfg80211_roamed(iwm_to_ndev(iwm), NULL, 569 569 complete->bssid, 570 570 iwm->req_ie, iwm->req_ie_len, 571 571 iwm->resp_ie, iwm->resp_ie_len, ··· 586 586 WLAN_STATUS_SUCCESS, 587 587 GFP_KERNEL); 588 588 else 589 - cfg80211_roamed(iwm_to_ndev(iwm), 589 + cfg80211_roamed(iwm_to_ndev(iwm), NULL, 590 590 complete->bssid, 591 591 iwm->req_ie, iwm->req_ie_len, 592 592 iwm->resp_ie, iwm->resp_ie_len,
+2 -1
drivers/net/wireless/rndis_wlan.c
··· 2830 2830 req_ie_len, resp_ie, 2831 2831 resp_ie_len, 0, GFP_KERNEL); 2832 2832 else 2833 - cfg80211_roamed(usbdev->net, bssid, req_ie, req_ie_len, 2833 + cfg80211_roamed(usbdev->net, NULL, bssid, 2834 + req_ie, req_ie_len, 2834 2835 resp_ie, resp_ie_len, GFP_KERNEL); 2835 2836 } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC) 2836 2837 cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL);
+1 -1
drivers/staging/ath6kl/os/linux/cfg80211.c
··· 570 570 WLAN_STATUS_SUCCESS, GFP_KERNEL); 571 571 } else { 572 572 /* inform roam event to cfg80211 */ 573 - cfg80211_roamed(ar->arNetDev, bssid, 573 + cfg80211_roamed(ar->arNetDev, ibss_channel, bssid, 574 574 assocReqIe, assocReqLen, 575 575 assocRespIe, assocRespLen, 576 576 GFP_KERNEL);
+2 -2
drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
··· 2630 2630 wl_get_assoc_ies(wl); 2631 2631 memcpy(&wl->bssid, &e->addr, ETH_ALEN); 2632 2632 wl_update_bss_info(wl); 2633 - cfg80211_roamed(ndev, 2633 + cfg80211_roamed(ndev, NULL, 2634 2634 (u8 *)&wl->bssid, 2635 2635 conn_info->req_ie, conn_info->req_ie_len, 2636 2636 conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL); ··· 2663 2663 WL_DBG("Report connect result - connection %s\n", 2664 2664 completed ? "succeeded" : "failed"); 2665 2665 } else { 2666 - cfg80211_roamed(ndev, 2666 + cfg80211_roamed(ndev, NULL, 2667 2667 (u8 *)&wl->bssid, 2668 2668 conn_info->req_ie, conn_info->req_ie_len, 2669 2669 conn_info->resp_ie, conn_info->resp_ie_len,
+1 -1
drivers/staging/wlan-ng/cfg80211.c
··· 695 695 696 696 void prism2_roamed(wlandevice_t *wlandev) 697 697 { 698 - cfg80211_roamed(wlandev->netdev, wlandev->bssid, 698 + cfg80211_roamed(wlandev->netdev, NULL, wlandev->bssid, 699 699 NULL, 0, NULL, 0, GFP_KERNEL); 700 700 } 701 701
+4 -1
include/net/cfg80211.h
··· 2878 2878 * cfg80211_roamed - notify cfg80211 of roaming 2879 2879 * 2880 2880 * @dev: network device 2881 + * @channel: the channel of the new AP 2881 2882 * @bssid: the BSSID of the new AP 2882 2883 * @req_ie: association request IEs (maybe be %NULL) 2883 2884 * @req_ie_len: association request IEs length ··· 2889 2888 * It should be called by the underlying driver whenever it roamed 2890 2889 * from one AP to another while connected. 2891 2890 */ 2892 - void cfg80211_roamed(struct net_device *dev, const u8 *bssid, 2891 + void cfg80211_roamed(struct net_device *dev, 2892 + struct ieee80211_channel *channel, 2893 + const u8 *bssid, 2893 2894 const u8 *req_ie, size_t req_ie_len, 2894 2895 const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp); 2895 2896
+4 -1
net/wireless/core.h
··· 245 245 u16 status; 246 246 } cr; 247 247 struct { 248 + struct ieee80211_channel *channel; 248 249 u8 bssid[ETH_ALEN]; 249 250 const u8 *req_ie; 250 251 const u8 *resp_ie; ··· 393 392 int cfg80211_disconnect(struct cfg80211_registered_device *rdev, 394 393 struct net_device *dev, u16 reason, 395 394 bool wextev); 396 - void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid, 395 + void __cfg80211_roamed(struct wireless_dev *wdev, 396 + struct ieee80211_channel *channel, 397 + const u8 *bssid, 397 398 const u8 *req_ie, size_t req_ie_len, 398 399 const u8 *resp_ie, size_t resp_ie_len); 399 400 int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
+14 -5
net/wireless/sme.c
··· 250 250 if (wdev->conn->params.privacy) 251 251 capa |= WLAN_CAPABILITY_PRIVACY; 252 252 253 - bss = cfg80211_get_bss(wdev->wiphy, NULL, wdev->conn->params.bssid, 253 + bss = cfg80211_get_bss(wdev->wiphy, wdev->conn->params.channel, 254 + wdev->conn->params.bssid, 254 255 wdev->conn->params.ssid, 255 256 wdev->conn->params.ssid_len, 256 257 WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_PRIVACY, ··· 471 470 } 472 471 473 472 if (!bss) 474 - bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, 473 + bss = cfg80211_get_bss(wdev->wiphy, 474 + wdev->conn ? wdev->conn->params.channel : 475 + NULL, 476 + bssid, 475 477 wdev->ssid, wdev->ssid_len, 476 478 WLAN_CAPABILITY_ESS, 477 479 WLAN_CAPABILITY_ESS); ··· 542 538 } 543 539 EXPORT_SYMBOL(cfg80211_connect_result); 544 540 545 - void __cfg80211_roamed(struct wireless_dev *wdev, const u8 *bssid, 541 + void __cfg80211_roamed(struct wireless_dev *wdev, 542 + struct ieee80211_channel *channel, 543 + const u8 *bssid, 546 544 const u8 *req_ie, size_t req_ie_len, 547 545 const u8 *resp_ie, size_t resp_ie_len) 548 546 { ··· 571 565 cfg80211_put_bss(&wdev->current_bss->pub); 572 566 wdev->current_bss = NULL; 573 567 574 - bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, 568 + bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, 575 569 wdev->ssid, wdev->ssid_len, 576 570 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); 577 571 ··· 609 603 #endif 610 604 } 611 605 612 - void cfg80211_roamed(struct net_device *dev, const u8 *bssid, 606 + void cfg80211_roamed(struct net_device *dev, 607 + struct ieee80211_channel *channel, 608 + const u8 *bssid, 613 609 const u8 *req_ie, size_t req_ie_len, 614 610 const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp) 615 611 { ··· 627 619 return; 628 620 629 621 ev->type = EVENT_ROAMED; 622 + ev->rm.channel = channel; 630 623 memcpy(ev->rm.bssid, bssid, ETH_ALEN); 631 624 ev->rm.req_ie = ((u8 *)ev) + sizeof(*ev); 632 625 ev->rm.req_ie_len = req_ie_len;
+1 -1
net/wireless/util.c
··· 746 746 NULL); 747 747 break; 748 748 case EVENT_ROAMED: 749 - __cfg80211_roamed(wdev, ev->rm.bssid, 749 + __cfg80211_roamed(wdev, ev->rm.channel, ev->rm.bssid, 750 750 ev->rm.req_ie, ev->rm.req_ie_len, 751 751 ev->rm.resp_ie, ev->rm.resp_ie_len); 752 752 break;