/* * CFG802.11 operation handler to delete a network key. */ static int mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, bool pairwise, const u8 *mac_addr) { struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); if (mwifiex_set_encode(priv, NULL, 0, key_index, 1)) { wiphy_err(wiphy, "deleting the crypto keys\n"); return -EFAULT; } wiphy_dbg(wiphy, "info: crypto keys deleted\n"); return 0; }
/* * CFG802.11 operation handler to add a network key. */ static int mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, bool pairwise, const u8 *mac_addr, struct key_params *params) { struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); if (mwifiex_set_encode(priv, params->key, params->key_len, key_index, 0)) { wiphy_err(wiphy, "crypto keys added\n"); return -EFAULT; } return 0; }
/* * CFG802.11 operation handler to add a network key. */ static int mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, bool pairwise, const u8 *mac_addr, struct key_params *params) { struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev); const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; const u8 *peer_mac = pairwise ? mac_addr : bc_mac; if (mwifiex_set_encode(priv, params->key, params->key_len, key_index, peer_mac, 0)) { wiphy_err(wiphy, "crypto keys added\n"); return -EFAULT; } return 0; }
/* * CFG802.11 operation handler to set the default network key. */ static int mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index, bool unicast, bool multicast) { struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev); /* Return if WEP key not configured */ if (!priv->sec_info.wep_enabled) return 0; if (mwifiex_set_encode(priv, NULL, 0, key_index, NULL, 0)) { wiphy_err(wiphy, "set default Tx key index\n"); return -EFAULT; } return 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; }
/* * 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, * otherwise the kernel will panic. */ 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 mwifiex_802_11_ssid req_ssid; struct mwifiex_ssid_bssid ssid_bssid; int ret, auth_type = 0; memset(&req_ssid, 0, sizeof(struct mwifiex_802_11_ssid)); memset(&ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid)); 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, mwifiex_channels_to_cfg80211_channel_type (priv->adapter->chan_offset)); ret = mwifiex_set_encode(priv, NULL, 0, 0, 1); /* Disable keys */ 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 || sme->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM; else if (sme->auth_type == NL80211_AUTHTYPE_SHARED_KEY) auth_type = NL80211_AUTHTYPE_SHARED_KEY; 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); ret = mwifiex_set_encode(priv, sme->key, sme->key_len, sme->key_idx, 0); } } done: /* Do specific SSID scanning */ if (mwifiex_request_scan(priv, &req_ssid)) { dev_err(priv->adapter->dev, "scan error\n"); return -EFAULT; } memcpy(&ssid_bssid.ssid, &req_ssid, sizeof(struct mwifiex_802_11_ssid)); if (mode != NL80211_IFTYPE_ADHOC) { if (mwifiex_find_best_bss(priv, &ssid_bssid)) return -EFAULT; /* Inform the BSS information to kernel, otherwise * kernel will give a panic after successful assoc */ if (mwifiex_inform_bss_from_scan_result(priv, &req_ssid)) return -EFAULT; } dev_dbg(priv->adapter->dev, "info: trying to associate to %s and bssid %pM\n", (char *) req_ssid.ssid, ssid_bssid.bssid); memcpy(&priv->cfg_bssid, ssid_bssid.bssid, 6); /* Connect to BSS by ESSID */ memset(&ssid_bssid.bssid, 0, ETH_ALEN); if (!netif_queue_stopped(priv->netdev)) netif_stop_queue(priv->netdev); if (mwifiex_bss_start(priv, &ssid_bssid)) 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; }