Exemple #1
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;

	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;
}
Exemple #2
0
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);
}
Exemple #3
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;
}
Exemple #4
0
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;
}
Exemple #5
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 *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;
}
Exemple #6
0
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 */
		}
	}	
}
Exemple #7
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;
}
Exemple #8
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;
}
Exemple #9
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)
{
	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
}
Exemple #11
0
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
}
Exemple #12
0
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);
		}
	}
}
Exemple #13
0
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;
}
Exemple #14
0
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;
}
Exemple #16
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,
			 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;
}
Exemple #17
0
/*
 * 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;
}
Exemple #18
0
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;
}
Exemple #19
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;
}
Exemple #20
0
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;
}
Exemple #21
0
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;
}