Beispiel #1
0
int cfg80211_mgd_wext_giwessid(struct net_device *dev,
			       struct iw_request_info *info,
			       struct iw_point *data, char *ssid)
{
	struct wireless_dev *wdev = dev->ieee80211_ptr;

	/* call only for station! */
	if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
		return -EINVAL;

	data->flags = 0;

	wdev_lock(wdev);
	if (wdev->current_bss) {
		const u8 *ie = ieee80211_bss_get_ie(&wdev->current_bss->pub,
						    WLAN_EID_SSID);
		if (ie) {
			data->flags = 1;
			data->length = ie[1];
			memcpy(ssid, ie + 2, data->length);
		}
	} else if (wdev->wext.connect.ssid && wdev->wext.connect.ssid_len) {
		data->flags = 1;
		data->length = wdev->wext.connect.ssid_len;
		memcpy(ssid, wdev->wext.connect.ssid, data->length);
	}
	wdev_unlock(wdev);

	return 0;
}
Beispiel #2
0
static int mwifiex_process_country_ie(struct mwifiex_private *priv,
				      struct cfg80211_bss *bss)
{
	const u8 *country_ie;
	u8 country_ie_len;
	struct mwifiex_802_11d_domain_reg *domain_info =
					&priv->adapter->domain_reg;

	rcu_read_lock();
	country_ie = ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY);
	if (!country_ie) {
		rcu_read_unlock();
		return 0;
	}

	country_ie_len = country_ie[1];
	if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) {
		rcu_read_unlock();
		return 0;
	}

	if (!strncmp(priv->adapter->country_code, &country_ie[2], 2)) {
		rcu_read_unlock();
		wiphy_dbg(priv->wdev->wiphy,
			  "11D: skip setting domain info in FW\n");
		return 0;
	}
	memcpy(priv->adapter->country_code, &country_ie[2], 2);

	domain_info->country_code[0] = country_ie[2];
	domain_info->country_code[1] = country_ie[3];
	domain_info->country_code[2] = ' ';

	country_ie_len -= IEEE80211_COUNTRY_STRING_LEN;

	domain_info->no_of_triplet =
		country_ie_len / sizeof(struct ieee80211_country_ie_triplet);

	memcpy((u8 *)domain_info->triplet,
	       &country_ie[2] + IEEE80211_COUNTRY_STRING_LEN, country_ie_len);

	rcu_read_unlock();

	if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11D_DOMAIN_INFO,
			     HostCmd_ACT_GEN_SET, 0, NULL, false)) {
		wiphy_err(priv->adapter->wiphy,
			  "11D: setting domain info in FW\n");
		return -1;
	}

	mwifiex_dnld_txpwr_table(priv);

	return 0;
}
Beispiel #3
0
static int mwifiex_process_country_ie(struct mwifiex_private *priv,
				      struct cfg80211_bss *bss)
{
	u8 *country_ie, country_ie_len;
	struct mwifiex_802_11d_domain_reg *domain_info =
					&priv->adapter->domain_reg;

	country_ie = (u8 *)ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY);

	if (!country_ie)
		return 0;

	country_ie_len = country_ie[1];
	if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN)
		return 0;

	domain_info->country_code[0] = country_ie[2];
	domain_info->country_code[1] = country_ie[3];
	domain_info->country_code[2] = ' ';

	country_ie_len -= IEEE80211_COUNTRY_STRING_LEN;

	domain_info->no_of_triplet =
		country_ie_len / sizeof(struct ieee80211_country_ie_triplet);

	memcpy((u8 *)domain_info->triplet,
	       &country_ie[2] + IEEE80211_COUNTRY_STRING_LEN, country_ie_len);

	if (mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11D_DOMAIN_INFO,
				   HostCmd_ACT_GEN_SET, 0, NULL)) {
		wiphy_err(priv->adapter->wiphy,
			  "11D: setting domain info in FW\n");
		return -1;
	}

	return 0;
}
Beispiel #4
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;
}