Пример #1
0
static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy,
					   struct net_device *ndev,
					   u8 key_index, bool unicast,
					   bool multicast)
{
	struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
	struct ath6kl_key *key = NULL;
	int status = 0;
	u8 key_usage;
	enum crypto_type key_type = NONE_CRYPT;

	ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);

	if (!ath6kl_cfg80211_ready(ar))
		return -EIO;

	if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
		ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
			   "%s: key index %d out of bounds\n",
			   __func__, key_index);
		return -ENOENT;
	}

	if (!ar->keys[key_index].key_len) {
		ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: invalid key index %d\n",
			   __func__, key_index);
		return -EINVAL;
	}

	ar->def_txkey_index = key_index;
	key = &ar->keys[ar->def_txkey_index];
	key_usage = GROUP_USAGE;
	if (ar->prwise_crypto == WEP_CRYPT)
		key_usage |= TX_USAGE;
	if (unicast)
		key_type = ar->prwise_crypto;
	if (multicast)
		key_type = ar->grp_crypto;

	if (ar->next_mode == AP_NETWORK && !test_bit(CONNECTED, &ar->flag))
		return 0; /* Delay until AP mode has been started */

	status = ath6kl_wmi_addkey_cmd(ar->wmi, ar->def_txkey_index,
				       key_type, key_usage,
				       key->key_len, key->seq, key->key,
				       KEY_OP_INIT_VAL, NULL,
				       SYNC_BOTH_WMIFLAG);
	if (status)
		return -EIO;

	return 0;
}
Пример #2
0
void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel)
{
	struct ath6kl *ar = vif->ar;
	struct ath6kl_req_key *ik;
	int res;
	u8 key_rsc[ATH6KL_KEY_SEQ_LEN];

	ik = &ar->ap_mode_bkey;

	ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "AP mode started on %u MHz\n", channel);

	switch (vif->auth_mode) {
	case NONE_AUTH:
		if (vif->prwise_crypto == WEP_CRYPT)
			ath6kl_install_static_wep_keys(vif);
		if (!ik->valid || ik->key_type != WAPI_CRYPT)
			break;
		/* for WAPI, we need to set the delayed group key, continue: */
	case WPA_PSK_AUTH:
	case WPA2_PSK_AUTH:
	case (WPA_PSK_AUTH | WPA2_PSK_AUTH):
		if (!ik->valid)
			break;

		ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed addkey for "
			   "the initial group key for AP mode\n");
		memset(key_rsc, 0, sizeof(key_rsc));
		res = ath6kl_wmi_addkey_cmd(
			ar->wmi, vif->fw_vif_idx, ik->key_index, ik->key_type,
			GROUP_USAGE, ik->key_len, key_rsc, ATH6KL_KEY_SEQ_LEN,
			ik->key,
			KEY_OP_INIT_VAL, NULL, SYNC_BOTH_WMIFLAG);
		if (res) {
			ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed "
				   "addkey failed: %d\n", res);
		}
		break;
	}

	ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, NONE_BSS_FILTER, 0);
	set_bit(CONNECTED, &vif->flags);
	netif_carrier_on(vif->ndev);
}
Пример #3
0
static void ath6kl_install_static_wep_keys(struct ath6kl_vif *vif)
{
	u8 index;
	u8 keyusage;

	for (index = WMI_MIN_KEY_INDEX; index <= WMI_MAX_KEY_INDEX; index++) {
		if (vif->wep_key_list[index].key_len) {
			keyusage = GROUP_USAGE;
			if (index == vif->def_txkey_index)
				keyusage |= TX_USAGE;

			ath6kl_wmi_addkey_cmd(vif->ar->wmi, vif->fw_vif_idx,
					      index,
					      WEP_CRYPT,
					      keyusage,
					      vif->wep_key_list[index].key_len,
					      NULL, 0,
					      vif->wep_key_list[index].key,
					      KEY_OP_INIT_VAL, NULL,
					      NO_SYNC_WMIFLAG);
		}
	}
}
Пример #4
0
static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
				   u8 key_index, bool pairwise,
				   const u8 *mac_addr,
				   struct key_params *params)
{
	struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
	struct ath6kl_key *key = NULL;
	u8 key_usage;
	u8 key_type;
	int status = 0;

	if (!ath6kl_cfg80211_ready(ar))
		return -EIO;

	if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
		ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
			   "%s: key index %d out of bounds\n", __func__,
			   key_index);
		return -ENOENT;
	}

	key = &ar->keys[key_index];
	memset(key, 0, sizeof(struct ath6kl_key));

	if (pairwise)
		key_usage = PAIRWISE_USAGE;
	else
		key_usage = GROUP_USAGE;

	if (params) {
		if (params->key_len > WLAN_MAX_KEY_LEN ||
		    params->seq_len > sizeof(key->seq))
			return -EINVAL;

		key->key_len = params->key_len;
		memcpy(key->key, params->key, key->key_len);
		key->seq_len = params->seq_len;
		memcpy(key->seq, params->seq, key->seq_len);
		key->cipher = params->cipher;
	}

	switch (key->cipher) {
	case WLAN_CIPHER_SUITE_WEP40:
	case WLAN_CIPHER_SUITE_WEP104:
		key_type = WEP_CRYPT;
		break;

	case WLAN_CIPHER_SUITE_TKIP:
		key_type = TKIP_CRYPT;
		break;

	case WLAN_CIPHER_SUITE_CCMP:
		key_type = AES_CRYPT;
		break;

	default:
		return -ENOTSUPP;
	}

	if (((ar->auth_mode == WPA_PSK_AUTH)
	     || (ar->auth_mode == WPA2_PSK_AUTH))
	    && (key_usage & GROUP_USAGE))
		del_timer(&ar->disconnect_timer);

	ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
		   "%s: index %d, key_len %d, key_type 0x%x, key_usage 0x%x, seq_len %d\n",
		   __func__, key_index, key->key_len, key_type,
		   key_usage, key->seq_len);

	ar->def_txkey_index = key_index;

	if (ar->nw_type == AP_NETWORK && !pairwise &&
	    (key_type == TKIP_CRYPT || key_type == AES_CRYPT) && params) {
		ar->ap_mode_bkey.valid = true;
		ar->ap_mode_bkey.key_index = key_index;
		ar->ap_mode_bkey.key_type = key_type;
		ar->ap_mode_bkey.key_len = key->key_len;
		memcpy(ar->ap_mode_bkey.key, key->key, key->key_len);
		if (!test_bit(CONNECTED, &ar->flag)) {
			ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay initial group "
				   "key configuration until AP mode has been "
				   "started\n");
			/*
			 * The key will be set in ath6kl_connect_ap_mode() once
			 * the connected event is received from the target.
			 */
			return 0;
		}
	}

	if (ar->next_mode == AP_NETWORK && key_type == WEP_CRYPT &&
	    !test_bit(CONNECTED, &ar->flag)) {
		/*
		 * Store the key locally so that it can be re-configured after
		 * the AP mode has properly started
		 * (ath6kl_install_statioc_wep_keys).
		 */
		ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay WEP key configuration "
			   "until AP mode has been started\n");
		ar->wep_key_list[key_index].key_len = key->key_len;
		memcpy(ar->wep_key_list[key_index].key, key->key, key->key_len);
		return 0;
	}

	status = ath6kl_wmi_addkey_cmd(ar->wmi, ar->def_txkey_index,
				       key_type, key_usage, key->key_len,
				       key->seq, key->key, KEY_OP_INIT_VAL,
				       (u8 *) mac_addr, SYNC_BOTH_WMIFLAG);

	if (status)
		return -EIO;

	return 0;
}
Пример #5
0
static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
				   struct cfg80211_connect_params *sme)
{
	struct ath6kl *ar = ath6kl_priv(dev);
	int status;

	ar->sme_state = SME_CONNECTING;

	if (!ath6kl_cfg80211_ready(ar))
		return -EIO;

	if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) {
		ath6kl_err("destroy in progress\n");
		return -EBUSY;
	}

	if (test_bit(SKIP_SCAN, &ar->flag) &&
	    ((sme->channel && sme->channel->center_freq == 0) ||
	     (sme->bssid && is_zero_ether_addr(sme->bssid)))) {
		ath6kl_err("SkipScan: channel or bssid invalid\n");
		return -EINVAL;
	}

	if (down_interruptible(&ar->sem)) {
		ath6kl_err("busy, couldn't get access\n");
		return -ERESTARTSYS;
	}

	if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) {
		ath6kl_err("busy, destroy in progress\n");
		up(&ar->sem);
		return -EBUSY;
	}

	if (ar->tx_pending[ath6kl_wmi_get_control_ep(ar->wmi)]) {
		/*
		 * sleep until the command queue drains
		 */
		wait_event_interruptible_timeout(ar->event_wq,
			ar->tx_pending[ath6kl_wmi_get_control_ep(ar->wmi)] == 0,
			WMI_TIMEOUT);
		if (signal_pending(current)) {
			ath6kl_err("cmd queue drain timeout\n");
			up(&ar->sem);
			return -EINTR;
		}
	}

	if (test_bit(CONNECTED, &ar->flag) &&
	    ar->ssid_len == sme->ssid_len &&
	    !memcmp(ar->ssid, sme->ssid, ar->ssid_len)) {
		ar->reconnect_flag = true;
		status = ath6kl_wmi_reconnect_cmd(ar->wmi, ar->req_bssid,
						  ar->ch_hint);

		up(&ar->sem);
		if (status) {
			ath6kl_err("wmi_reconnect_cmd failed\n");
			return -EIO;
		}
		return 0;
	} else if (ar->ssid_len == sme->ssid_len &&
		   !memcmp(ar->ssid, sme->ssid, ar->ssid_len)) {
		ath6kl_disconnect(ar);
	}

	memset(ar->ssid, 0, sizeof(ar->ssid));
	ar->ssid_len = sme->ssid_len;
	memcpy(ar->ssid, sme->ssid, sme->ssid_len);

	if (sme->channel)
		ar->ch_hint = sme->channel->center_freq;

	memset(ar->req_bssid, 0, sizeof(ar->req_bssid));
	if (sme->bssid && !is_broadcast_ether_addr(sme->bssid))
		memcpy(ar->req_bssid, sme->bssid, sizeof(ar->req_bssid));

	ath6kl_set_wpa_version(ar, sme->crypto.wpa_versions);

	status = ath6kl_set_auth_type(ar, sme->auth_type);
	if (status) {
		up(&ar->sem);
		return status;
	}

	if (sme->crypto.n_ciphers_pairwise)
		ath6kl_set_cipher(ar, sme->crypto.ciphers_pairwise[0], true);
	else
		ath6kl_set_cipher(ar, 0, true);

	ath6kl_set_cipher(ar, sme->crypto.cipher_group, false);

	if (sme->crypto.n_akm_suites)
		ath6kl_set_key_mgmt(ar, sme->crypto.akm_suites[0]);

	if ((sme->key_len) &&
	    (ar->auth_mode == NONE_AUTH) && (ar->prwise_crypto == WEP_CRYPT)) {
		struct ath6kl_key *key = NULL;

		if (sme->key_idx < WMI_MIN_KEY_INDEX ||
		    sme->key_idx > WMI_MAX_KEY_INDEX) {
			ath6kl_err("key index %d out of bounds\n",
				   sme->key_idx);
			up(&ar->sem);
			return -ENOENT;
		}

		key = &ar->keys[sme->key_idx];
		key->key_len = sme->key_len;
		memcpy(key->key, sme->key, key->key_len);
		key->cipher = ar->prwise_crypto;
		ar->def_txkey_index = sme->key_idx;

		ath6kl_wmi_addkey_cmd(ar->wmi, sme->key_idx,
				      ar->prwise_crypto,
				      GROUP_USAGE | TX_USAGE,
				      key->key_len,
				      NULL,
				      key->key, KEY_OP_INIT_VAL, NULL,
				      NO_SYNC_WMIFLAG);
	}

	if (!ar->usr_bss_filter) {
		clear_bit(CLEAR_BSSFILTER_ON_BEACON, &ar->flag);
		if (ath6kl_wmi_bssfilter_cmd(ar->wmi, ALL_BSS_FILTER, 0) != 0) {
			ath6kl_err("couldn't set bss filtering\n");
			up(&ar->sem);
			return -EIO;
		}
	}

	ar->nw_type = ar->next_mode;

	ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
		   "%s: connect called with authmode %d dot11 auth %d"
		   " PW crypto %d PW crypto len %d GRP crypto %d"
		   " GRP crypto len %d channel hint %u\n",
		   __func__,
		   ar->auth_mode, ar->dot11_auth_mode, ar->prwise_crypto,
		   ar->prwise_crypto_len, ar->grp_crypto,
		   ar->grp_crypto_len, ar->ch_hint);

	ar->reconnect_flag = 0;
	status = ath6kl_wmi_connect_cmd(ar->wmi, ar->nw_type,
					ar->dot11_auth_mode, ar->auth_mode,
					ar->prwise_crypto,
					ar->prwise_crypto_len,
					ar->grp_crypto, ar->grp_crypto_len,
					ar->ssid_len, ar->ssid,
					ar->req_bssid, ar->ch_hint,
					ar->connect_ctrl_flags);

	up(&ar->sem);

	if (status == -EINVAL) {
		memset(ar->ssid, 0, sizeof(ar->ssid));
		ar->ssid_len = 0;
		ath6kl_err("invalid request\n");
		return -ENOENT;
	} else if (status) {
		ath6kl_err("ath6kl_wmi_connect_cmd failed\n");
		return -EIO;
	}

	if ((!(ar->connect_ctrl_flags & CONNECT_DO_WPA_OFFLOAD)) &&
	    ((ar->auth_mode == WPA_PSK_AUTH)
	     || (ar->auth_mode == WPA2_PSK_AUTH))) {
		mod_timer(&ar->disconnect_timer,
			  jiffies + msecs_to_jiffies(DISCON_TIMER_INTVAL));
	}

	ar->connect_ctrl_flags &= ~CONNECT_DO_WPA_OFFLOAD;
	set_bit(CONNECT_PEND, &ar->flag);

	return 0;
}