int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, struct net_device *dev, struct ieee80211_channel *chan, const u8 *bssid, const u8 *ssid, int ssid_len, struct cfg80211_assoc_request *req) { struct wireless_dev *wdev = dev->ieee80211_ptr; int err; ASSERT_WDEV_LOCK(wdev); if (wdev->current_bss && (!req->prev_bssid || !ether_addr_equal(wdev->current_bss->pub.bssid, req->prev_bssid))) return -EALREADY; cfg80211_oper_and_ht_capa(&req->ht_capa_mask, rdev->wiphy.ht_capa_mod_mask); cfg80211_oper_and_vht_capa(&req->vht_capa_mask, rdev->wiphy.vht_capa_mod_mask); req->bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); if (!req->bss) return -ENOENT; err = rdev_assoc(rdev, dev, req); if (!err) cfg80211_hold_bss(bss_from_pub(req->bss)); else cfg80211_put_bss(&rdev->wiphy, req->bss); return err; }
struct ieee80211_bss * ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, u8 *ssid, u8 ssid_len) { return (void *)cfg80211_get_bss(local->hw.wiphy, ieee80211_get_channel(local->hw.wiphy, freq), bssid, ssid, ssid_len, 0, 0); }
int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, struct net_device *dev, struct ieee80211_channel *chan, const u8 *bssid, const u8 *ssid, int ssid_len, struct cfg80211_assoc_request *req) { struct wireless_dev *wdev = dev->ieee80211_ptr; int err; bool was_connected = false; ASSERT_WDEV_LOCK(wdev); if (wdev->current_bss && req->prev_bssid && ether_addr_equal(wdev->current_bss->pub.bssid, req->prev_bssid)) { /* * Trying to reassociate: Allow this to proceed and let the old * association to be dropped when the new one is completed. */ if (wdev->sme_state == CFG80211_SME_CONNECTED) { was_connected = true; wdev->sme_state = CFG80211_SME_CONNECTING; } } else if (wdev->current_bss) return -EALREADY; cfg80211_oper_and_ht_capa(&req->ht_capa_mask, rdev->wiphy.ht_capa_mod_mask); cfg80211_oper_and_vht_capa(&req->vht_capa_mask, rdev->wiphy.vht_capa_mod_mask); req->bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); if (!req->bss) { if (was_connected) wdev->sme_state = CFG80211_SME_CONNECTED; return -ENOENT; } err = cfg80211_can_use_chan(rdev, wdev, chan, CHAN_MODE_SHARED); if (err) goto out; err = rdev_assoc(rdev, dev, req); out: if (err) { if (was_connected) wdev->sme_state = CFG80211_SME_CONNECTED; cfg80211_put_bss(&rdev->wiphy, req->bss); } return err; }
struct ieee80211_bss * ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, u8 *ssid, u8 ssid_len) { struct cfg80211_bss *cbss; cbss = cfg80211_get_bss(local->hw.wiphy, ieee80211_get_channel(local->hw.wiphy, freq), bssid, ssid, ssid_len, 0, 0); if (!cbss) return NULL; return (void *)cbss->priv; }
/* some MLME handling for userspace SME */ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, struct net_device *dev, struct ieee80211_channel *chan, enum nl80211_auth_type auth_type, const u8 *bssid, const u8 *ssid, int ssid_len, const u8 *ie, int ie_len, const u8 *key, int key_len, int key_idx, const u8 *sae_data, int sae_data_len) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_auth_request req; int err; ASSERT_WDEV_LOCK(wdev); if (auth_type == NL80211_AUTHTYPE_SHARED_KEY) if (!key || !key_len || key_idx < 0 || key_idx > 4) return -EINVAL; if (wdev->current_bss && ether_addr_equal(bssid, wdev->current_bss->pub.bssid)) return -EALREADY; memset(&req, 0, sizeof(req)); req.ie = ie; req.ie_len = ie_len; req.sae_data = sae_data; req.sae_data_len = sae_data_len; req.auth_type = auth_type; req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); req.key = key; req.key_len = key_len; req.key_idx = key_idx; if (!req.bss) return -ENOENT; err = cfg80211_can_use_chan(rdev, wdev, req.bss->channel, CHAN_MODE_SHARED); if (err) goto out; err = rdev_auth(rdev, dev, &req); out: cfg80211_put_bss(&rdev->wiphy, req.bss); return err; }
static void CFG80211_UpdateBssTableRssi( IN VOID *pAdCB) { PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pAdCB; CFG80211_CB *pCfg80211_CB = (CFG80211_CB *)pAd->pCfg80211_CB; struct wiphy *pWiphy = pCfg80211_CB->pCfg80211_Wdev->wiphy; struct ieee80211_channel *chan; struct cfg80211_bss *bss; BSS_ENTRY *pBssEntry; UINT index; UINT32 CenFreq; for (index = 0; index < pAd->ScanTab.BssNr; index++) { pBssEntry = &pAd->ScanTab.BssEntry[index]; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39)) if (pAd->ScanTab.BssEntry[index].Channel > 14) CenFreq = ieee80211_channel_to_frequency(pAd->ScanTab.BssEntry[index].Channel , IEEE80211_BAND_5GHZ); else CenFreq = ieee80211_channel_to_frequency(pAd->ScanTab.BssEntry[index].Channel , IEEE80211_BAND_2GHZ); #else CenFreq = ieee80211_channel_to_frequency(pAd->ScanTab.BssEntry[index].Channel); #endif chan = ieee80211_get_channel(pWiphy, CenFreq); bss = cfg80211_get_bss(pWiphy, chan, pBssEntry->Bssid, pBssEntry->Ssid, pBssEntry->SsidLen, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); if (bss == NULL) { /* ScanTable Entry not exist in kernel buffer */ } else { /* HIT */ CFG80211_CalBssAvgRssi(pBssEntry); bss->signal = pBssEntry->AvgRssi * 100; //UNIT: MdBm #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0)) cfg80211_put_bss(pWiphy, bss); #else cfg80211_put_bss(bss); #endif /* LINUX_VERSION_CODE: 3.9.0 */ } } }
static int ath6kl_add_bss_if_needed(struct ath6kl *ar, const u8 *bssid, struct ieee80211_channel *chan, const u8 *beacon_ie, size_t beacon_ie_len) { struct cfg80211_bss *bss; u8 *ie; bss = cfg80211_get_bss(ar->wdev->wiphy, chan, bssid, ar->ssid, ar->ssid_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); if (bss == NULL) { /* * Since cfg80211 may not yet know about the BSS, * generate a partial entry until the first BSS info * event becomes available. * * Prepend SSID element since it is not included in the Beacon * IEs from the target. */ ie = kmalloc(2 + ar->ssid_len + beacon_ie_len, GFP_KERNEL); if (ie == NULL) return -ENOMEM; ie[0] = WLAN_EID_SSID; ie[1] = ar->ssid_len; memcpy(ie + 2, ar->ssid, ar->ssid_len); memcpy(ie + 2 + ar->ssid_len, beacon_ie, beacon_ie_len); bss = cfg80211_inform_bss(ar->wdev->wiphy, chan, bssid, 0, WLAN_CAPABILITY_ESS, 100, ie, 2 + ar->ssid_len + beacon_ie_len, 0, GFP_KERNEL); if (bss) ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "added dummy bss for " "%pM prior to indicating connect/roamed " "event\n", bssid); kfree(ie); } else ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "cfg80211 already has a bss " "entry\n"); if (bss == NULL) return -ENOMEM; cfg80211_put_bss(bss); return 0; }
/* some MLME handling for userspace SME */ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, struct net_device *dev, struct ieee80211_channel *chan, enum nl80211_auth_type auth_type, const u8 *bssid, const u8 *ssid, int ssid_len, const u8 *ie, int ie_len, const u8 *key, int key_len, int key_idx, const u8 *auth_data, int auth_data_len) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_auth_request req = { .ie = ie, .ie_len = ie_len, .auth_data = auth_data, .auth_data_len = auth_data_len, .auth_type = auth_type, .key = key, .key_len = key_len, .key_idx = key_idx, }; int err; ASSERT_WDEV_LOCK(wdev); if (auth_type == NL80211_AUTHTYPE_SHARED_KEY) if (!key || !key_len || key_idx < 0 || key_idx > 3) return -EINVAL; if (wdev->current_bss && ether_addr_equal(bssid, wdev->current_bss->pub.bssid)) return -EALREADY; req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY); if (!req.bss) return -ENOENT; err = rdev_auth(rdev, dev, &req); cfg80211_put_bss(&rdev->wiphy, req.bss); return err; }
/* some MLME handling for userspace SME */ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, struct net_device *dev, struct ieee80211_channel *chan, enum nl80211_auth_type auth_type, const u8 *bssid, const u8 *ssid, int ssid_len, const u8 *ie, int ie_len, const u8 *key, int key_len, int key_idx) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_auth_request req; int err; ASSERT_WDEV_LOCK(wdev); if (auth_type == NL80211_AUTHTYPE_SHARED_KEY) if (!key || !key_len || key_idx < 0 || key_idx > 4) return -EINVAL; if (wdev->current_bss && memcmp(bssid, wdev->current_bss->pub.bssid, ETH_ALEN) == 0) return -EALREADY; memset(&req, 0, sizeof(req)); req.ie = ie; req.ie_len = ie_len; req.auth_type = auth_type; req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); req.key = key; req.key_len = key_len; req.key_idx = key_idx; if (!req.bss) return -ENOENT; err = rdev->ops->auth(&rdev->wiphy, dev, &req); cfg80211_put_bss(req.bss); return err; }
void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_bss *bss; #ifdef CONFIG_CFG80211_WEXT union iwreq_data wrqu; #endif if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) return; if (!wdev->ssid_len) return; bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, wdev->ssid, wdev->ssid_len, WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS); if (WARN_ON(!bss)) return; if (wdev->current_bss) { cfg80211_unhold_bss(wdev->current_bss); cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub); } cfg80211_hold_bss(bss_from_pub(bss)); wdev->current_bss = bss_from_pub(bss); wdev->sme_state = CFG80211_SME_CONNECTED; cfg80211_upload_connect_keys(wdev); nl80211_send_ibss_bssid(wiphy_to_dev(wdev->wiphy), dev, bssid, GFP_KERNEL); #ifdef CONFIG_CFG80211_WEXT memset(&wrqu, 0, sizeof(wrqu)); memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN); wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); #endif }
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; #ifdef CONFIG_CFG80211_WEXT union iwreq_data wrqu; #endif if (WARN_ON(wdev->iftype != NL80211_IFTYPE_ADHOC)) return; if (!wdev->ssid_len) return; bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, NULL, 0, IEEE80211_BSS_TYPE_IBSS, IEEE80211_PRIVACY_ANY); if (WARN_ON(!bss)) return; if (wdev->current_bss) { cfg80211_unhold_bss(wdev->current_bss); cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub); } cfg80211_hold_bss(bss_from_pub(bss)); wdev->current_bss = bss_from_pub(bss); if (!(wdev->wiphy->flags & WIPHY_FLAG_HAS_STATIC_WEP)) cfg80211_upload_connect_keys(wdev); nl80211_send_ibss_bssid(wiphy_to_rdev(wdev->wiphy), dev, bssid, GFP_KERNEL); #ifdef CONFIG_CFG80211_WEXT memset(&wrqu, 0, sizeof(wrqu)); memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN); wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); #endif }
static void CFG80211_UpdateBssTableRssi( IN struct rtmp_adapter *pAd) { struct mt7612u_cfg80211_cb *pCfg80211_CB = (struct mt7612u_cfg80211_cb *)pAd->pCfg80211_CB; struct wiphy *pWiphy = pCfg80211_CB->pCfg80211_Wdev->wiphy; struct ieee80211_channel *chan; struct cfg80211_bss *bss; BSS_ENTRY *pBssEntry; UINT index; uint32_t CenFreq; for (index = 0; index < pAd->ScanTab.BssNr; index++) { pBssEntry = &pAd->ScanTab.BssEntry[index]; if (pAd->ScanTab.BssEntry[index].Channel > 14) CenFreq = ieee80211_channel_to_frequency(pAd->ScanTab.BssEntry[index].Channel , NL80211_BAND_5GHZ); else CenFreq = ieee80211_channel_to_frequency(pAd->ScanTab.BssEntry[index].Channel , NL80211_BAND_2GHZ); chan = ieee80211_get_channel(pWiphy, CenFreq); bss = cfg80211_get_bss(pWiphy, chan, pBssEntry->Bssid, pBssEntry->Ssid, pBssEntry->SsidLen, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); if (bss == NULL) { /* ScanTable Entry not exist in kernel buffer */ } else { /* HIT */ CFG80211_CalBssAvgRssi(pBssEntry); bss->signal = pBssEntry->AvgRssi * 100; //UNIT: MdBm cfg80211_put_bss(pWiphy, bss); } } }
int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, struct net_device *dev, struct ieee80211_channel *chan, const u8 *bssid, const u8 *prev_bssid, const u8 *ssid, int ssid_len, const u8 *ie, int ie_len, bool use_mfp, struct cfg80211_crypto_settings *crypt) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_assoc_request req; struct cfg80211_internal_bss *bss; int i, err, slot = -1; bool was_connected = false; ASSERT_WDEV_LOCK(wdev); memset(&req, 0, sizeof(req)); if (wdev->current_bss && prev_bssid && memcmp(wdev->current_bss->pub.bssid, prev_bssid, ETH_ALEN) == 0) { /* * Trying to reassociate: Allow this to proceed and let the old * association to be dropped when the new one is completed. */ if (wdev->sme_state == CFG80211_SME_CONNECTED) { was_connected = true; wdev->sme_state = CFG80211_SME_CONNECTING; } } else if (wdev->current_bss) return -EALREADY; req.ie = ie; req.ie_len = ie_len; memcpy(&req.crypto, crypt, sizeof(req.crypto)); req.use_mfp = use_mfp; req.prev_bssid = prev_bssid; req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); if (!req.bss) { if (was_connected) wdev->sme_state = CFG80211_SME_CONNECTED; return -ENOENT; } bss = bss_from_pub(req.bss); for (i = 0; i < MAX_AUTH_BSSES; i++) { if (bss == wdev->auth_bsses[i]) { slot = i; break; } } if (slot < 0) { err = -ENOTCONN; goto out; } err = rdev->ops->assoc(&rdev->wiphy, dev, &req); out: if (err && was_connected) wdev->sme_state = CFG80211_SME_CONNECTED; /* still a reference in wdev->auth_bsses[slot] */ cfg80211_put_bss(req.bss); return err; }
int __cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev, struct net_device *dev, struct ieee80211_channel *chan, const u8 *bssid, const u8 *prev_bssid, const u8 *ssid, int ssid_len, const u8 *ie, int ie_len, bool use_mfp, struct cfg80211_crypto_settings *crypt, u32 assoc_flags, struct ieee80211_ht_cap *ht_capa, struct ieee80211_ht_cap *ht_capa_mask) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_assoc_request req; int err; bool was_connected = false; ASSERT_WDEV_LOCK(wdev); memset(&req, 0, sizeof(req)); if (wdev->current_bss && prev_bssid && ether_addr_equal(wdev->current_bss->pub.bssid, prev_bssid)) { /* * Trying to reassociate: Allow this to proceed and let the old * association to be dropped when the new one is completed. */ if (wdev->sme_state == CFG80211_SME_CONNECTED) { was_connected = true; wdev->sme_state = CFG80211_SME_CONNECTING; } } else if (wdev->current_bss) return -EALREADY; req.ie = ie; req.ie_len = ie_len; memcpy(&req.crypto, crypt, sizeof(req.crypto)); req.use_mfp = use_mfp; req.prev_bssid = prev_bssid; req.flags = assoc_flags; if (ht_capa) memcpy(&req.ht_capa, ht_capa, sizeof(req.ht_capa)); if (ht_capa_mask) memcpy(&req.ht_capa_mask, ht_capa_mask, sizeof(req.ht_capa_mask)); cfg80211_oper_and_ht_capa(&req.ht_capa_mask, rdev->wiphy.ht_capa_mod_mask); req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); if (!req.bss) { if (was_connected) wdev->sme_state = CFG80211_SME_CONNECTED; return -ENOENT; } err = rdev->ops->assoc(&rdev->wiphy, dev, &req); if (err) { if (was_connected) wdev->sme_state = CFG80211_SME_CONNECTED; cfg80211_put_bss(req.bss); } return err; }
int mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, u16 channel) { int ret; struct mwifiex_bss_info bss_info; struct mwifiex_ssid_bssid ssid_bssid; u16 curr_chan = 0; struct cfg80211_bss *bss = NULL; struct ieee80211_channel *chan; enum ieee80211_band band; memset(&bss_info, 0, sizeof(bss_info)); if (mwifiex_get_bss_info(priv, &bss_info)) return -1; ret = mwifiex_bss_ioctl_ibss_channel(priv, HostCmd_ACT_GEN_GET, &curr_chan); if (curr_chan == channel) { ret = 0; goto done; } dev_dbg(priv->adapter->dev, "cmd: updating channel from %d to %d\n", curr_chan, channel); if (!bss_info.media_connected) { ret = 0; goto done; } memset(&ssid_bssid, 0, ETH_ALEN); ret = mwifiex_deauthenticate(priv, ssid_bssid.bssid); ret = mwifiex_bss_ioctl_ibss_channel(priv, HostCmd_ACT_GEN_SET, &channel); if (mwifiex_request_scan(priv, &bss_info.ssid)) { ret = -1; goto done; } band = mwifiex_band_to_radio_type(priv->curr_bss_params.band); chan = __ieee80211_get_channel(priv->wdev->wiphy, ieee80211_channel_to_frequency(channel, band)); bss = cfg80211_get_bss(priv->wdev->wiphy, chan, bss_info.bssid, bss_info.ssid.ssid, bss_info.ssid.ssid_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); if (!bss) wiphy_warn(priv->wdev->wiphy, "assoc: bss %pM not in scan results\n", bss_info.bssid); ret = mwifiex_bss_start(priv, bss, &bss_info.ssid); done: return ret; }
/* some MLME handling for userspace SME */ int __cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, struct net_device *dev, struct ieee80211_channel *chan, enum nl80211_auth_type auth_type, const u8 *bssid, const u8 *ssid, int ssid_len, const u8 *ie, int ie_len, const u8 *key, int key_len, int key_idx, bool local_state_change) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_auth_request req; struct cfg80211_internal_bss *bss; int i, err, slot = -1, nfree = 0; ASSERT_WDEV_LOCK(wdev); if (auth_type == NL80211_AUTHTYPE_SHARED_KEY) if (!key || !key_len || key_idx < 0 || key_idx > 4) return -EINVAL; if (wdev->current_bss && memcmp(bssid, wdev->current_bss->pub.bssid, ETH_ALEN) == 0) return -EALREADY; for (i = 0; i < MAX_AUTH_BSSES; i++) { if (wdev->authtry_bsses[i] && memcmp(bssid, wdev->authtry_bsses[i]->pub.bssid, ETH_ALEN) == 0) return -EALREADY; if (wdev->auth_bsses[i] && memcmp(bssid, wdev->auth_bsses[i]->pub.bssid, ETH_ALEN) == 0) return -EALREADY; } memset(&req, 0, sizeof(req)); req.local_state_change = local_state_change; req.ie = ie; req.ie_len = ie_len; req.auth_type = auth_type; req.bss = cfg80211_get_bss(&rdev->wiphy, chan, bssid, ssid, ssid_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); req.key = key; req.key_len = key_len; req.key_idx = key_idx; if (!req.bss) return -ENOENT; bss = bss_from_pub(req.bss); for (i = 0; i < MAX_AUTH_BSSES; i++) { if (!wdev->auth_bsses[i] && !wdev->authtry_bsses[i]) { slot = i; nfree++; } } /* we need one free slot for disassoc and one for this auth */ if (nfree < 2) { err = -ENOSPC; goto out; } if (local_state_change) wdev->auth_bsses[slot] = bss; else wdev->authtry_bsses[slot] = bss; cfg80211_hold_bss(bss); err = rdev->ops->auth(&rdev->wiphy, dev, &req); if (err) { if (local_state_change) wdev->auth_bsses[slot] = NULL; else wdev->authtry_bsses[slot] = NULL; cfg80211_unhold_bss(bss); } out: if (err) cfg80211_put_bss(req.bss); return err; }
/* * This function connects with a BSS. * * This function handles both Infra and Ad-Hoc modes. It also performs * validity checking on the provided parameters, disconnects from the * current BSS (if any), sets up the association/scan parameters, * including security settings, and performs specific SSID scan before * trying to connect. * * For Infra mode, the function returns failure if the specified SSID * is not found in scan table. However, for Ad-Hoc mode, it can create * the IBSS if it does not exist. On successful completion in either case, * the function notifies the CFG802.11 subsystem of the new BSS connection. */ static int mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, u8 *bssid, int mode, struct ieee80211_channel *channel, struct cfg80211_connect_params *sme, bool privacy) { struct cfg80211_ssid req_ssid; int ret, auth_type = 0; struct cfg80211_bss *bss = NULL; u8 is_scanning_required = 0; memset(&req_ssid, 0, sizeof(struct cfg80211_ssid)); req_ssid.ssid_len = ssid_len; if (ssid_len > IEEE80211_MAX_SSID_LEN) { dev_err(priv->adapter->dev, "invalid SSID - aborting\n"); return -EINVAL; } memcpy(req_ssid.ssid, ssid, ssid_len); if (!req_ssid.ssid_len || req_ssid.ssid[0] < 0x20) { dev_err(priv->adapter->dev, "invalid SSID - aborting\n"); return -EINVAL; } /* disconnect before try to associate */ mwifiex_deauthenticate(priv, NULL); if (channel) ret = mwifiex_set_rf_channel(priv, channel, priv->adapter->channel_type); /* As this is new association, clear locally stored * keys and security related flags */ priv->sec_info.wpa_enabled = false; priv->sec_info.wpa2_enabled = false; priv->wep_key_curr_index = 0; priv->sec_info.encryption_mode = 0; priv->sec_info.is_authtype_auto = 0; ret = mwifiex_set_encode(priv, NULL, 0, 0, NULL, 1); if (mode == NL80211_IFTYPE_ADHOC) { /* "privacy" is set only for ad-hoc mode */ if (privacy) { /* * Keep WLAN_CIPHER_SUITE_WEP104 for now so that * the firmware can find a matching network from the * scan. The cfg80211 does not give us the encryption * mode at this stage so just setting it to WEP here. */ priv->sec_info.encryption_mode = WLAN_CIPHER_SUITE_WEP104; priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM; } goto done; } /* Now handle infra mode. "sme" is valid for infra mode only */ if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) { auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM; priv->sec_info.is_authtype_auto = 1; } else { auth_type = sme->auth_type; } if (sme->crypto.n_ciphers_pairwise) { priv->sec_info.encryption_mode = sme->crypto.ciphers_pairwise[0]; priv->sec_info.authentication_mode = auth_type; } if (sme->crypto.cipher_group) { priv->sec_info.encryption_mode = sme->crypto.cipher_group; priv->sec_info.authentication_mode = auth_type; } if (sme->ie) ret = mwifiex_set_gen_ie(priv, sme->ie, sme->ie_len); if (sme->key) { if (mwifiex_is_alg_wep(priv->sec_info.encryption_mode)) { dev_dbg(priv->adapter->dev, "info: setting wep encryption" " with key len %d\n", sme->key_len); priv->wep_key_curr_index = sme->key_idx; ret = mwifiex_set_encode(priv, sme->key, sme->key_len, sme->key_idx, NULL, 0); } } done: /* * Scan entries are valid for some time (15 sec). So we can save one * active scan time if we just try cfg80211_get_bss first. If it fails * then request scan and cfg80211_get_bss() again for final output. */ while (1) { if (is_scanning_required) { /* Do specific SSID scanning */ if (mwifiex_request_scan(priv, &req_ssid)) { dev_err(priv->adapter->dev, "scan error\n"); return -EFAULT; } } /* Find the BSS we want using available scan results */ if (mode == NL80211_IFTYPE_ADHOC) bss = cfg80211_get_bss(priv->wdev->wiphy, channel, bssid, ssid, ssid_len, WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS); else bss = cfg80211_get_bss(priv->wdev->wiphy, channel, bssid, ssid, ssid_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); if (!bss) { if (is_scanning_required) { dev_warn(priv->adapter->dev, "assoc: requested bss not found in scan results\n"); break; } is_scanning_required = 1; } else { dev_dbg(priv->adapter->dev, "info: trying to associate to '%s' bssid %pM\n", (char *) req_ssid.ssid, bss->bssid); memcpy(&priv->cfg_bssid, bss->bssid, ETH_ALEN); break; } } if (mwifiex_bss_start(priv, bss, &req_ssid)) return -EFAULT; if (mode == NL80211_IFTYPE_ADHOC) { /* Inform the BSS information to kernel, otherwise * kernel will give a panic after successful assoc */ if (mwifiex_cfg80211_inform_ibss_bss(priv)) return -EFAULT; } return ret; }
static int qtnf_event_handle_bss_join(struct qtnf_vif *vif, const struct qlink_event_bss_join *join_info, u16 len) { struct wiphy *wiphy = priv_to_wiphy(vif->mac); enum ieee80211_statuscode status = le16_to_cpu(join_info->status); struct cfg80211_chan_def chandef; struct cfg80211_bss *bss = NULL; u8 *ie = NULL; size_t payload_len; u16 tlv_type; u16 tlv_value_len; size_t tlv_full_len; const struct qlink_tlv_hdr *tlv; const u8 *rsp_ies = NULL; size_t rsp_ies_len = 0; if (unlikely(len < sizeof(*join_info))) { pr_err("VIF%u.%u: payload is too short (%u < %zu)\n", vif->mac->macid, vif->vifid, len, sizeof(struct qlink_event_bss_join)); return -EINVAL; } if (vif->wdev.iftype != NL80211_IFTYPE_STATION) { pr_err("VIF%u.%u: BSS_JOIN event when not in STA mode\n", vif->mac->macid, vif->vifid); return -EPROTO; } pr_debug("VIF%u.%u: BSSID:%pM status:%u\n", vif->mac->macid, vif->vifid, join_info->bssid, status); if (status != WLAN_STATUS_SUCCESS) goto done; qlink_chandef_q2cfg(wiphy, &join_info->chan, &chandef); if (!cfg80211_chandef_valid(&chandef)) { pr_warn("MAC%u.%u: bad channel freq=%u cf1=%u cf2=%u bw=%u\n", vif->mac->macid, vif->vifid, chandef.chan->center_freq, chandef.center_freq1, chandef.center_freq2, chandef.width); status = WLAN_STATUS_UNSPECIFIED_FAILURE; goto done; } bss = cfg80211_get_bss(wiphy, chandef.chan, join_info->bssid, NULL, 0, IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY); if (!bss) { pr_warn("VIF%u.%u: add missing BSS:%pM chan:%u\n", vif->mac->macid, vif->vifid, join_info->bssid, chandef.chan->hw_value); if (!vif->wdev.ssid_len) { pr_warn("VIF%u.%u: SSID unknown for BSS:%pM\n", vif->mac->macid, vif->vifid, join_info->bssid); status = WLAN_STATUS_UNSPECIFIED_FAILURE; goto done; } ie = kzalloc(2 + vif->wdev.ssid_len, GFP_KERNEL); if (!ie) { pr_warn("VIF%u.%u: IE alloc failed for BSS:%pM\n", vif->mac->macid, vif->vifid, join_info->bssid); status = WLAN_STATUS_UNSPECIFIED_FAILURE; goto done; } ie[0] = WLAN_EID_SSID; ie[1] = vif->wdev.ssid_len; memcpy(ie + 2, vif->wdev.ssid, vif->wdev.ssid_len); bss = cfg80211_inform_bss(wiphy, chandef.chan, CFG80211_BSS_FTYPE_UNKNOWN, join_info->bssid, 0, WLAN_CAPABILITY_ESS, 100, ie, 2 + vif->wdev.ssid_len, 0, GFP_KERNEL); if (!bss) { pr_warn("VIF%u.%u: can't connect to unknown BSS: %pM\n", vif->mac->macid, vif->vifid, join_info->bssid); status = WLAN_STATUS_UNSPECIFIED_FAILURE; goto done; } } payload_len = len - sizeof(*join_info); tlv = (struct qlink_tlv_hdr *)join_info->ies; while (payload_len >= sizeof(struct qlink_tlv_hdr)) { tlv_type = le16_to_cpu(tlv->type); tlv_value_len = le16_to_cpu(tlv->len); tlv_full_len = tlv_value_len + sizeof(struct qlink_tlv_hdr); if (payload_len < tlv_full_len) { pr_warn("invalid %u TLV\n", tlv_type); status = WLAN_STATUS_UNSPECIFIED_FAILURE; goto done; } if (tlv_type == QTN_TLV_ID_IE_SET) { const struct qlink_tlv_ie_set *ie_set; unsigned int ie_len; if (payload_len < sizeof(*ie_set)) { pr_warn("invalid IE_SET TLV\n"); status = WLAN_STATUS_UNSPECIFIED_FAILURE; goto done; } ie_set = (const struct qlink_tlv_ie_set *)tlv; ie_len = tlv_value_len - (sizeof(*ie_set) - sizeof(ie_set->hdr)); switch (ie_set->type) { case QLINK_IE_SET_ASSOC_RESP: if (ie_len) { rsp_ies = ie_set->ie_data; rsp_ies_len = ie_len; } break; default: pr_warn("unexpected IE type: %u\n", ie_set->type); break; } } payload_len -= tlv_full_len; tlv = (struct qlink_tlv_hdr *)(tlv->val + tlv_value_len); } if (payload_len) pr_warn("VIF%u.%u: unexpected remaining payload: %zu\n", vif->mac->macid, vif->vifid, payload_len); done: cfg80211_connect_result(vif->netdev, join_info->bssid, NULL, 0, rsp_ies, rsp_ies_len, status, GFP_KERNEL); if (bss) { if (!ether_addr_equal(vif->bssid, join_info->bssid)) ether_addr_copy(vif->bssid, join_info->bssid); cfg80211_put_bss(wiphy, bss); } if (status == WLAN_STATUS_SUCCESS) netif_carrier_on(vif->netdev); kfree(ie); return 0; }
static int wil_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_connect_params *sme) { struct wil6210_priv *wil = wiphy_to_wil(wiphy); struct cfg80211_bss *bss; struct wmi_connect_cmd conn; const u8 *ssid_eid; const u8 *rsn_eid; int ch; int rc = 0; if (test_bit(wil_status_fwconnecting, &wil->status) || test_bit(wil_status_fwconnected, &wil->status)) return -EALREADY; bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid, sme->ssid, sme->ssid_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); if (!bss) { wil_err(wil, "Unable to find BSS\n"); return -ENOENT; } ssid_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SSID); if (!ssid_eid) { wil_err(wil, "No SSID\n"); rc = -ENOENT; goto out; } rsn_eid = sme->ie ? cfg80211_find_ie(WLAN_EID_RSN, sme->ie, sme->ie_len) : NULL; if (rsn_eid) { if (sme->ie_len > WMI_MAX_IE_LEN) { rc = -ERANGE; wil_err(wil, "IE too large (%td bytes)\n", sme->ie_len); goto out; } /* * For secure assoc, send: * (1) WMI_DELETE_CIPHER_KEY_CMD * (2) WMI_SET_APPIE_CMD */ rc = wmi_del_cipher_key(wil, 0, bss->bssid); if (rc) { wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD failed\n"); goto out; } /* WMI_SET_APPIE_CMD */ rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_REQ, sme->ie_len, sme->ie); if (rc) { wil_err(wil, "WMI_SET_APPIE_CMD failed\n"); goto out; } } /* WMI_CONNECT_CMD */ memset(&conn, 0, sizeof(conn)); switch (bss->capability & WLAN_CAPABILITY_DMG_TYPE_MASK) { case WLAN_CAPABILITY_DMG_TYPE_AP: conn.network_type = WMI_NETTYPE_INFRA; break; case WLAN_CAPABILITY_DMG_TYPE_PBSS: conn.network_type = WMI_NETTYPE_P2P; break; default: wil_err(wil, "Unsupported BSS type, capability= 0x%04x\n", bss->capability); goto out; } if (rsn_eid) { conn.dot11_auth_mode = WMI_AUTH11_SHARED; conn.auth_mode = WMI_AUTH_WPA2_PSK; conn.pairwise_crypto_type = WMI_CRYPT_AES_GCMP; conn.pairwise_crypto_len = 16; } else { conn.dot11_auth_mode = WMI_AUTH11_OPEN; conn.auth_mode = WMI_AUTH_NONE; } conn.ssid_len = min_t(u8, ssid_eid[1], 32); memcpy(conn.ssid, ssid_eid+2, conn.ssid_len); ch = bss->channel->hw_value; if (ch == 0) { wil_err(wil, "BSS at unknown frequency %dMhz\n", bss->channel->center_freq); rc = -EOPNOTSUPP; goto out; } conn.channel = ch - 1; memcpy(conn.bssid, bss->bssid, ETH_ALEN); memcpy(conn.dst_mac, bss->bssid, ETH_ALEN); set_bit(wil_status_fwconnecting, &wil->status); rc = wmi_send(wil, WMI_CONNECT_CMDID, &conn, sizeof(conn)); if (rc == 0) { /* Connect can take lots of time */ mod_timer(&wil->connect_timer, jiffies + msecs_to_jiffies(2000)); } else { clear_bit(wil_status_fwconnecting, &wil->status); } out: cfg80211_put_bss(wiphy, bss); return rc; }
static int r92su_connect(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_connect_params *sme) { struct r92su *r92su = wiphy_priv(wiphy); struct cfg80211_bss *bss = NULL; struct r92su_bss_priv *bss_priv = NULL; int err = -ENODEV; u8 ie_buf[256]; u8 *ie = ie_buf; u32 ie_len_left = sizeof(ie_buf); err = r92su_internal_scan(r92su, sme->ssid, sme->ssid_len); if (err) return err; mutex_lock(&r92su->lock); if (!r92su_is_open(r92su)) goto out; bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid, sme->ssid, sme->ssid_len, IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY); if (!bss) { err = -ENOENT; goto out; } bss_priv = r92su_get_bss_priv(bss); err = r92su_connect_set_auth(r92su, bss, sme->auth_type, &sme->crypto); if (err) goto out; err = r92su_connect_set_shared_key(r92su, bss, sme); if (err) goto out; WARN(!r92su_add_ies(r92su, &ie, &ie_len_left, sme->ie, sme->ie_len), "no space left for cfg80211's ies"); if (!(sme->flags & ASSOC_REQ_DISABLE_HT)) { WARN(!r92su_ht_update(r92su, &ie, &ie_len_left), "no space left for ht caps ie"); } WARN(!r92su_wmm_update(r92su, &ie, &ie_len_left), "no space left for wmm ie"); err = r92su_internal_connect(r92su, bss, true, ie_buf, ie - ie_buf); out: if (err) { if (bss_priv) kfree(bss_priv->assoc_ie); r92su->want_connect_bss = NULL; if (bss) cfg80211_put_bss(wiphy, bss); } mutex_unlock(&r92su->lock); return err; }
static int r92su_join_ibss(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_ibss_params *params) { struct r92su *r92su = wiphy_priv(wiphy); struct cfg80211_bss *bss = NULL; struct r92su_bss_priv *bss_priv = NULL; int err = -EAGAIN; u8 ie_buf[256]; u8 *ie = ie_buf; u32 ie_len_left = sizeof(ie_buf); bool join; err = r92su_internal_scan(r92su, params->ssid, params->ssid_len); if (err) return err; mutex_lock(&r92su->lock); if (!r92su_is_open(r92su)) goto out; bss = cfg80211_get_bss(wiphy, NULL, params->bssid, params->ssid, params->ssid_len, IEEE80211_BSS_TYPE_IBSS, IEEE80211_PRIVACY_ANY); if (!bss) { u8 bssid[ETH_ALEN]; u16 capability; capability = WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_SHORT_PREAMBLE; if (params->privacy) capability |= WLAN_CAPABILITY_PRIVACY; if (!params->bssid) { /* generate random, not broadcast, locally administered * bssid. */ get_random_bytes(&bssid, sizeof(bssid)); bssid[0] &= ~0x01; bssid[0] |= 0x02; } else { memcpy(bssid, params->bssid, ETH_ALEN); } err = r92su_ibss_build_ie(r92su, &ie, &ie_len_left, params); if (err) goto out; bss = cfg80211_inform_bss(r92su->wdev.wiphy, params->chandef.chan, CFG80211_BSS_FTYPE_UNKNOWN, bssid, 0, capability, params->beacon_interval, ie_buf, ie - ie_buf, 0, GFP_KERNEL); if (!bss) goto out; bss_priv = r92su_get_bss_priv(bss); err = r92su_bss_build_fw_bss(r92su, bss, ie_buf, ie - ie_buf); if (err) goto out; join = false; } else { bss_priv = r92su_get_bss_priv(bss); WARN(!r92su_add_ies(r92su, &ie, &ie_len_left, params->ie, params->ie_len), "no space left for cfg80211's ies"); join = true; } err = r92su_internal_connect(r92su, bss, join, ie_buf, ie - ie_buf); out: if (err) { if (bss_priv) kfree(bss_priv->assoc_ie); r92su->want_connect_bss = NULL; if (bss) cfg80211_put_bss(wiphy, bss); } mutex_unlock(&r92su->lock); return err; }