/** * @brief Set frequency/channel * * @param dev A pointer to net_device structure * @param info A pointer to iw_request_info structure * @param fwrq A pointer to iw_freq structure * @param extra A pointer to extra data buf * * @return 0 --success, otherwise fail */ static int woal_set_freq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *fwrq, char *extra) { moal_private *priv = (moal_private *) netdev_priv(dev); mlan_uap_bss_param sys_cfg, ap_cfg; int ret = 0, chan = 0, i = 0; ENTER(); if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_GET, &ap_cfg)) { PRINTM(MERROR, "Error getting AP confiruration\n"); ret = -EFAULT; goto done; } i = ap_cfg.chan_list.num_of_chan; /* Initialize the invalid values so that the correct values below are downloaded to firmware */ woal_set_sys_config_invalid_data(&sys_cfg); /* If setting by frequency, convert to a channel */ if (fwrq->e == 1) chan = freq_to_chan(fwrq->m / 100000); else chan = fwrq->m; if (chan > 0 && chan < MAX_CHANNEL) sys_cfg.channel = chan; else { ret = -EINVAL; goto done; } for (i = 0; i < ap_cfg.chan_list.num_of_chan; i++) if (ap_cfg.chan_list.chan[i] == chan) break; if (i == ap_cfg.chan_list.num_of_chan) { PRINTM(MERROR, "Channel %d is not supported\n", chan); ret = -EINVAL; goto done; } if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_SET, &sys_cfg)) { PRINTM(MERROR, "Error setting AP confiruration\n"); ret = -EFAULT; goto done; } done: LEAVE(); return ret; }
/** * @brief Get frequency and channel * * @param dev A pointer to net_device structure * @param info A pointer to iw_request_info structure * @param fwrq A pointer to iw_freq structure * @param extra A pointer to extra data buf * * @return 0 --success, otherwise fail */ static int woal_get_freq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *fwrq, char *extra) { moal_private *priv = (moal_private *) netdev_priv(dev); mlan_uap_bss_param ap_cfg; t_u8 band = 0; int ret = 0; ENTER(); if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_GET, MOAL_IOCTL_WAIT, &ap_cfg)) { PRINTM(MERROR, "Error getting AP confiruration\n"); LEAVE(); return -EFAULT; } band = ap_cfg.band_cfg & BAND_CONFIG_5GHZ; fwrq->i = (long)ap_cfg.channel; fwrq->m = (long)(channel_to_frequency(ap_cfg.channel, band)) * 100000; fwrq->e = 1; LEAVE(); return ret; }
/** * @brief Get current essid * * @param dev A pointer to net_device structure * @param info A pointer to iw_request_info structure * @param dwrq A pointer to iw_point structure * @param extra A pointer to extra data buf * * @return 0--success, otherwise fail */ static int woal_get_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { moal_private *priv = (moal_private *) netdev_priv(dev); mlan_uap_bss_param ap_cfg; ENTER(); if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_GET, MOAL_IOCTL_WAIT, &ap_cfg)) { PRINTM(MERROR, "Error getting AP confiruration\n"); LEAVE(); return -EFAULT; } if (priv->bss_started) { dwrq->length = MIN(dwrq->length, ap_cfg.ssid.ssid_len); memcpy(extra, ap_cfg.ssid.ssid, dwrq->length); } else dwrq->length = 0; dwrq->flags = 1; LEAVE(); return 0; }
/** * @brief Set AP configuration * * @param priv A pointer to moal_private structure * @param wrq A pointer to user data * * @return 0 --success, otherwise fail */ static int woal_uap_set_ap_cfg(moal_private * priv, struct iwreq *wrq) { int ret = 0; static t_s8 buf[MAX_BUF_LEN]; mlan_uap_bss_param sys_config; int restart = 0; ENTER(); #define MIN_AP_CFG_CMD_LEN 16 /* strlen("ASCII_CMD=AP_CFG") */ if ((wrq->u.data.length - 1) <= MIN_AP_CFG_CMD_LEN) { PRINTM(MERROR, "Invalid length of command\n"); ret = -EINVAL; goto done; } memset(buf, 0, MAX_BUF_LEN); memcpy(buf, wrq->u.data.pointer, wrq->u.data.length); /* Initialize the invalid values so that the correct values below are downloaded to firmware */ woal_set_sys_config_invalid_data(&sys_config); /* Setting the default values */ sys_config.channel = 6; sys_config.preamble_type = 0; if ((ret = woal_uap_ap_cfg_parse_data(&sys_config, buf))) goto done; /* If BSS already started stop it first and restart after changing the setting */ if (priv->bss_started == MTRUE) { if ((ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP))) goto done; restart = 1; } if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_SET, &sys_config)) { ret = -EFAULT; goto done; } /* Start the BSS after successful configuration */ if (restart) ret = woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_START); done: LEAVE(); return ret; }
/** * @brief Set essid * * @param dev A pointer to net_device structure * @param info A pointer to iw_request_info structure * @param dwrq A pointer to iw_point structure * @param extra A pointer to extra data buf * * @return 0--success, otherwise fail */ static int woal_set_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { moal_private *priv = (moal_private *) netdev_priv(dev); mlan_uap_bss_param sys_cfg; int ret = 0; ENTER(); /* Check the size of the string */ if (dwrq->length > IW_ESSID_MAX_SIZE + 1) { ret = -E2BIG; goto done; } /* Initialize the invalid values so that the correct values below are downloaded to firmware */ woal_set_sys_config_invalid_data(&sys_cfg); /* Set the SSID */ #if WIRELESS_EXT > 20 sys_cfg.ssid.ssid_len = dwrq->length; #else sys_cfg.ssid.ssid_len = dwrq->length - 1; #endif memcpy(sys_cfg.ssid.ssid, extra, MIN(sys_cfg.ssid.ssid_len, MLAN_MAX_SSID_LENGTH)); if (!sys_cfg.ssid.ssid_len || sys_cfg.ssid.ssid[0] < 0x20) { PRINTM(MERROR, "Invalid SSID - aborting set_essid\n"); ret = -EINVAL; goto done; } PRINTM(MINFO, "Requested new SSID = %s\n", (sys_cfg.ssid.ssid_len > 0) ? (char *)sys_cfg.ssid.ssid : "NULL"); /* Set AP configuration */ if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_SET, MOAL_IOCTL_WAIT, &sys_cfg)) { PRINTM(MERROR, "Error setting AP confiruration\n"); ret = -EFAULT; goto done; } done: LEAVE(); return ret; }
/** * @brief Get frequency and channel * * @param dev A pointer to net_device structure * @param info A pointer to iw_request_info structure * @param fwrq A pointer to iw_freq structure * @param extra A pointer to extra data buf * * @return 0 --success, otherwise fail */ static int woal_get_freq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *fwrq, char *extra) { moal_private *priv = (moal_private *) netdev_priv(dev); mlan_uap_bss_param ap_cfg; int ret = 0; ENTER(); if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_GET, &ap_cfg)) { PRINTM(MERROR, "Error getting AP confiruration\n"); LEAVE(); return -EFAULT; } fwrq->i = (long) ap_cfg.channel; fwrq->m = (long) (chan_to_freq[ap_cfg.channel - 1]) * 100000; fwrq->e = 1; LEAVE(); return ret; }
/** * @brief Get encryption key * * @param dev A pointer to net_device structure * @param info A pointer to iw_request_info structure * @param dwrq A pointer to iw_point structure * @param extra A pointer to extra data buf * * @return 0 --success, otherwise fail */ static int woal_get_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { moal_private *priv = (moal_private *) netdev_priv(dev); int index = (dwrq->flags & IW_ENCODE_INDEX); wep_key *pkey = NULL; mlan_uap_bss_param ap_cfg; int ret = 0; ENTER(); if (index < 0 || index > 4) { PRINTM(MERROR, "Key index #%d out of range\n", index); ret = -EINVAL; goto done; } if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_GET, MOAL_IOCTL_WAIT, &ap_cfg)) { PRINTM(MERROR, "Error getting AP confiruration\n"); ret = -EFAULT; goto done; } dwrq->flags = 0; /* * Check encryption mode */ switch (ap_cfg.auth_mode) { case MLAN_AUTH_MODE_OPEN: dwrq->flags = IW_ENCODE_OPEN; break; case MLAN_AUTH_MODE_SHARED: case MLAN_AUTH_MODE_NETWORKEAP: dwrq->flags = IW_ENCODE_RESTRICTED; break; default: dwrq->flags = IW_ENCODE_DISABLED | IW_ENCODE_OPEN; break; } switch (ap_cfg.protocol) { case PROTOCOL_NO_SECURITY: dwrq->flags |= IW_ENCODE_DISABLED; break; case PROTOCOL_STATIC_WEP: if (ap_cfg.wep_cfg.key0.is_default) pkey = &ap_cfg.wep_cfg.key0; else if (ap_cfg.wep_cfg.key1.is_default) pkey = &ap_cfg.wep_cfg.key1; else if (ap_cfg.wep_cfg.key2.is_default) pkey = &ap_cfg.wep_cfg.key2; else if (ap_cfg.wep_cfg.key3.is_default) pkey = &ap_cfg.wep_cfg.key3; if (pkey) { dwrq->flags |= (pkey->key_index + 1); dwrq->length = pkey->length; memcpy(extra, pkey->key, pkey->length); dwrq->flags &= ~IW_ENCODE_DISABLED; } else { ret = -EFAULT; } break; case PROTOCOL_WPA: case PROTOCOL_WPA2: case PROTOCOL_WPA2_MIXED: memcpy(extra, ap_cfg.wpa_cfg.passphrase, ap_cfg.wpa_cfg.length); dwrq->length = ap_cfg.wpa_cfg.length; dwrq->flags |= 1; dwrq->flags &= ~IW_ENCODE_DISABLED; break; default: dwrq->flags &= ~IW_ENCODE_DISABLED; break; } dwrq->flags |= IW_ENCODE_NOKEY; done: LEAVE(); return ret; }
/** * @brief Set encryption key * * @param dev A pointer to net_device structure * @param info A pointer to iw_request_info structure * @param dwrq A pointer to iw_point structure * @param extra A pointer to extra data buf * * @return 0 --success, otherwise fail */ static int woal_set_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { int ret = 0; moal_private *priv = (moal_private *) netdev_priv(dev); mlan_uap_bss_param *sys_cfg = NULL, *ap_cfg = NULL; wep_key *pkey = NULL; int key_index = 0; ENTER(); /* Check index */ key_index = (dwrq->flags & IW_ENCODE_INDEX) - 1; if (key_index > 3) { PRINTM(MERROR, "Key index #%d out of range\n", key_index); ret = -EINVAL; goto done; } ap_cfg = kmalloc(sizeof(mlan_uap_bss_param), GFP_KERNEL); if (ap_cfg == NULL) { ret = -ENOMEM; goto done; } sys_cfg = kmalloc(sizeof(mlan_uap_bss_param), GFP_KERNEL); if (sys_cfg == NULL) { ret = -ENOMEM; goto done; } if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_GET, MOAL_IOCTL_WAIT, ap_cfg)) { PRINTM(MERROR, "Error getting AP confiruration\n"); ret = -EFAULT; goto done; } /* Initialize the invalid values so that the correct values below are downloaded to firmware */ woal_set_sys_config_invalid_data(sys_cfg); sys_cfg->wep_cfg.key0.key_index = 0; sys_cfg->wep_cfg.key1.key_index = 1; sys_cfg->wep_cfg.key2.key_index = 2; sys_cfg->wep_cfg.key3.key_index = 3; if (key_index >= 0 && key_index <= 3) { if (key_index == 0) pkey = &sys_cfg->wep_cfg.key0; else if (key_index == 1) pkey = &sys_cfg->wep_cfg.key1; else if (key_index == 2) pkey = &sys_cfg->wep_cfg.key2; else if (key_index == 3) pkey = &sys_cfg->wep_cfg.key3; } if (!(dwrq->flags & IW_ENCODE_NOKEY) && dwrq->length) { if (dwrq->length > MAX_WEP_KEY_SIZE) { PRINTM(MERROR, "Key length (%d) out of range\n", dwrq->length); ret = -E2BIG; goto done; } if (key_index < 0) { /* Get current default key index */ if (ap_cfg->wep_cfg.key0.is_default) pkey = &sys_cfg->wep_cfg.key0; if (ap_cfg->wep_cfg.key1.is_default) pkey = &sys_cfg->wep_cfg.key1; if (ap_cfg->wep_cfg.key2.is_default) pkey = &sys_cfg->wep_cfg.key2; if (ap_cfg->wep_cfg.key3.is_default) pkey = &sys_cfg->wep_cfg.key3; } sys_cfg->protocol = PROTOCOL_STATIC_WEP; memcpy(pkey->key, extra, dwrq->length); /* Set the length */ if (dwrq->length > MIN_WEP_KEY_SIZE) pkey->length = MAX_WEP_KEY_SIZE; else pkey->length = MIN_WEP_KEY_SIZE; /* Set current key index as default */ pkey->is_default = MTRUE; } else { /* * No key provided so it is either enable key, * on or off */ if (dwrq->flags & IW_ENCODE_DISABLED) { PRINTM(MINFO, "*** iwconfig mlanX key off ***\n"); sys_cfg->protocol = PROTOCOL_NO_SECURITY; } else { /* * iwconfig mlanX key [n] * iwconfig mlanX key on * Do we want to just set the transmit key index ? */ if (key_index < 0) { PRINTM(MINFO, "*** iwconfig mlanX key on ***\n"); } else { /* Get current key configuration at key_index */ if (key_index == 0) memcpy(pkey, &ap_cfg->wep_cfg.key0, sizeof(wep_key)); if (key_index == 1) memcpy(pkey, &ap_cfg->wep_cfg.key1, sizeof(wep_key)); if (key_index == 2) memcpy(pkey, &ap_cfg->wep_cfg.key2, sizeof(wep_key)); if (key_index == 3) memcpy(pkey, &ap_cfg->wep_cfg.key3, sizeof(wep_key)); /* Set current key index as default */ pkey->is_default = MTRUE; } } } if (dwrq->flags & (IW_ENCODE_RESTRICTED | IW_ENCODE_OPEN)) { switch (dwrq->flags & 0xf000) { case IW_ENCODE_RESTRICTED: /* iwconfig mlanX restricted key [1] */ sys_cfg->auth_mode = MLAN_AUTH_MODE_SHARED; PRINTM(MINFO, "Auth mode restricted!\n"); break; case IW_ENCODE_OPEN: /* iwconfig mlanX key [2] open */ sys_cfg->auth_mode = MLAN_AUTH_MODE_OPEN; PRINTM(MINFO, "Auth mode open!\n"); break; case IW_ENCODE_RESTRICTED | IW_ENCODE_OPEN: default: /* iwconfig mlanX key [2] open restricted */ PRINTM(MINFO, "Auth mode auto!\n"); break; } } if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_SET, MOAL_IOCTL_WAIT, sys_cfg)) { PRINTM(MERROR, "Error setting AP confiruration\n"); ret = -EFAULT; goto done; } done: if (sys_cfg) kfree(sys_cfg); if (ap_cfg) kfree(ap_cfg); LEAVE(); return ret; }
/** * @brief Get Range Info * * @param dev A pointer to net_device structure * @param info A pointer to iw_request_info structure * @param dwrq A pointer to iw_point structure * @param extra A pointer to extra data buf * * @return 0 --success, otherwise fail */ static int woal_get_range(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { moal_private *priv = (moal_private *) netdev_priv(dev); mlan_uap_bss_param ap_cfg; struct iw_range *range = (struct iw_range *)extra; t_u8 band = 0; int i; ENTER(); if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_GET, MOAL_IOCTL_WAIT, &ap_cfg)) { PRINTM(MERROR, "Error getting AP confiruration\n"); LEAVE(); return -EFAULT; } dwrq->length = sizeof(struct iw_range); memset(range, 0, sizeof(struct iw_range)); range->min_nwid = 0; range->max_nwid = 0; range->num_bitrates = MAX_DATA_RATES; for (i = 0; i < MIN(MAX_DATA_RATES, IW_MAX_BITRATES) && ap_cfg.rates[i]; i++) { range->bitrate[i] = (ap_cfg.rates[i] & 0x7f) * 500000; } range->num_bitrates = i; PRINTM(MINFO, "IW_MAX_BITRATES=%d num_bitrates=%d\n", IW_MAX_BITRATES, range->num_bitrates); range->num_frequency = MIN(ap_cfg.num_of_chan, IW_MAX_FREQUENCIES); for (i = 0; i < range->num_frequency; i++) { range->freq[i].i = (long)ap_cfg.chan_list[i].chan_number; band = ap_cfg.chan_list[i].band_config_type & BAND_CONFIG_5GHZ; range->freq[i].m = (long)channel_to_frequency(ap_cfg.chan_list[i]. chan_number, band) * 100000; range->freq[i].e = 1; } PRINTM(MINFO, "IW_MAX_FREQUENCIES=%d num_frequency=%d\n", IW_MAX_FREQUENCIES, range->num_frequency); range->num_channels = range->num_frequency; woal_sort_channels(&range->freq[0], range->num_frequency); /* * Set an indication of the max TCP throughput in bit/s that we can * expect using this interface */ if (i > 2) range->throughput = 5000 * 1000; else range->throughput = 1500 * 1000; range->min_rts = MLAN_RTS_MIN_VALUE; range->max_rts = MLAN_RTS_MAX_VALUE; range->min_frag = MLAN_FRAG_MIN_VALUE; range->max_frag = MLAN_FRAG_MAX_VALUE; range->encoding_size[0] = 5; range->encoding_size[1] = 13; range->num_encoding_sizes = 2; range->max_encoding_tokens = 4; /** Minimum power period */ #define IW_POWER_PERIOD_MIN 1000000 /* 1 sec */ /** Maximum power period */ #define IW_POWER_PERIOD_MAX 120000000 /* 2 min */ /** Minimum power timeout value */ #define IW_POWER_TIMEOUT_MIN 1000 /* 1 ms */ /** Maximim power timeout value */ #define IW_POWER_TIMEOUT_MAX 1000000 /* 1 sec */ /* Power Management duration & timeout */ range->min_pmp = IW_POWER_PERIOD_MIN; range->max_pmp = IW_POWER_PERIOD_MAX; range->min_pmt = IW_POWER_TIMEOUT_MIN; range->max_pmt = IW_POWER_TIMEOUT_MAX; range->pmp_flags = IW_POWER_PERIOD; range->pmt_flags = IW_POWER_TIMEOUT; range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R; /* * Minimum version we recommend */ range->we_version_source = 15; /* * Version we are compiled with */ range->we_version_compiled = WIRELESS_EXT; range->retry_capa = IW_RETRY_LIMIT; range->retry_flags = IW_RETRY_LIMIT | IW_RETRY_MAX; range->min_retry = MLAN_TX_RETRY_MIN; range->max_retry = MLAN_TX_RETRY_MAX; #if (WIRELESS_EXT >= 18) if (ap_cfg.protocol & PROTOCOL_WPA) range->enc_capa |= IW_ENC_CAPA_WPA; if (ap_cfg.protocol & PROTOCOL_WPA2) range->enc_capa |= IW_ENC_CAPA_WPA2; if (ap_cfg.wpa_cfg.pairwise_cipher_wpa == CIPHER_TKIP || ap_cfg.wpa_cfg.pairwise_cipher_wpa2 == CIPHER_TKIP || ap_cfg.wpa_cfg.group_cipher == CIPHER_TKIP) range->enc_capa |= IW_ENC_CAPA_CIPHER_TKIP; if (ap_cfg.wpa_cfg.pairwise_cipher_wpa == CIPHER_AES_CCMP || ap_cfg.wpa_cfg.pairwise_cipher_wpa2 == CIPHER_AES_CCMP || ap_cfg.wpa_cfg.group_cipher == CIPHER_AES_CCMP) range->enc_capa |= IW_ENC_CAPA_CIPHER_CCMP; #endif LEAVE(); return 0; }
/** @brief Set authentication mode parameters * * @param dev A pointer to net_device structure * @param info A pointer to iw_request_info structure * @param vwrq A pointer to iw_param structure * @param extra A pointer to extra data buf * * @return 0 --success, otherwise fail */ static int woal_set_auth(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { int ret = 0; moal_private *priv = (moal_private *) netdev_priv(dev); mlan_uap_bss_param sys_cfg; ENTER(); /* Initialize the invalid values so that the correct values below are downloaded to firmware */ woal_set_sys_config_invalid_data(&sys_cfg); switch (vwrq->flags & IW_AUTH_INDEX) { case IW_AUTH_CIPHER_PAIRWISE: /* Rest are not supported now */ if (vwrq->value & IW_AUTH_CIPHER_NONE) ; else if (vwrq->value & IW_AUTH_CIPHER_WEP40) ; else if (vwrq->value & IW_AUTH_CIPHER_WEP104) ; else if (vwrq->value == IW_AUTH_CIPHER_TKIP) { sys_cfg.wpa_cfg.pairwise_cipher_wpa = CIPHER_TKIP; sys_cfg.wpa_cfg.pairwise_cipher_wpa2 = CIPHER_TKIP; priv->pairwise_cipher = CIPHER_TKIP; if (!priv->uap_key_mgmt) priv->uap_key_mgmt = KEY_MGMT_PSK; PRINTM(MINFO, "Set Auth Cipher TKIP\n"); } else if (vwrq->value == IW_AUTH_CIPHER_CCMP) { sys_cfg.wpa_cfg.pairwise_cipher_wpa = CIPHER_AES_CCMP; sys_cfg.wpa_cfg.pairwise_cipher_wpa2 = CIPHER_AES_CCMP; priv->pairwise_cipher = CIPHER_AES_CCMP; if (!priv->uap_key_mgmt) priv->uap_key_mgmt = KEY_MGMT_PSK; PRINTM(MINFO, "Set Auth Cipher CCMP\n"); } else if (vwrq->value == (IW_AUTH_CIPHER_TKIP | IW_AUTH_CIPHER_CCMP)) { sys_cfg.wpa_cfg.pairwise_cipher_wpa = (CIPHER_TKIP | CIPHER_AES_CCMP); sys_cfg.wpa_cfg.pairwise_cipher_wpa2 = (CIPHER_TKIP | CIPHER_AES_CCMP); priv->pairwise_cipher = (CIPHER_TKIP | CIPHER_AES_CCMP); if (!priv->uap_key_mgmt) priv->uap_key_mgmt = KEY_MGMT_PSK; PRINTM(MINFO, "Set Auth Cipher TKIP + CCMP\n"); } break; case IW_AUTH_CIPHER_GROUP: /* Rest are not supported now */ if (vwrq->value & IW_AUTH_CIPHER_NONE) ; else if (vwrq->value & IW_AUTH_CIPHER_WEP40) ; else if (vwrq->value & IW_AUTH_CIPHER_WEP104) ; else if (vwrq->value & IW_AUTH_CIPHER_TKIP) { sys_cfg.wpa_cfg.group_cipher = CIPHER_TKIP; priv->group_cipher = CIPHER_TKIP; if (!priv->uap_key_mgmt) priv->uap_key_mgmt = KEY_MGMT_PSK; PRINTM(MINFO, "Set Auth Cipher TKIP\n"); } else if (vwrq->value & IW_AUTH_CIPHER_CCMP) { sys_cfg.wpa_cfg.group_cipher = CIPHER_AES_CCMP; priv->group_cipher = CIPHER_AES_CCMP; if (!priv->uap_key_mgmt) priv->uap_key_mgmt = KEY_MGMT_PSK; PRINTM(MINFO, "Set Auth Cipher CCMP\n"); } break; case IW_AUTH_80211_AUTH_ALG: switch (vwrq->value) { case IW_AUTH_ALG_SHARED_KEY: PRINTM(MINFO, "Auth mode shared key!\n"); sys_cfg.auth_mode = MLAN_AUTH_MODE_SHARED; break; case IW_AUTH_ALG_LEAP: break; case IW_AUTH_ALG_OPEN_SYSTEM: PRINTM(MINFO, "Auth mode open!\n"); sys_cfg.auth_mode = MLAN_AUTH_MODE_OPEN; break; default: PRINTM(MINFO, "Auth mode auto!\n"); break; } break; case IW_AUTH_WPA_VERSION: switch (vwrq->value) { case IW_AUTH_WPA_VERSION_DISABLED: sys_cfg.protocol = PROTOCOL_NO_SECURITY; break; case IW_AUTH_WPA_VERSION_WPA: sys_cfg.protocol = PROTOCOL_WPA; break; case IW_AUTH_WPA_VERSION_WPA2: sys_cfg.protocol = PROTOCOL_WPA2; break; case IW_AUTH_WPA_VERSION_WPA | IW_AUTH_WPA_VERSION_WPA2: sys_cfg.protocol = PROTOCOL_WPA2_MIXED; break; default: break; } priv->uap_protocol = sys_cfg.protocol; break; case IW_AUTH_KEY_MGMT: switch (vwrq->value) { case IW_AUTH_KEY_MGMT_802_1X: sys_cfg.key_mgmt |= KEY_MGMT_EAP; priv->uap_key_mgmt |= KEY_MGMT_EAP; break; case IW_AUTH_KEY_MGMT_PSK: sys_cfg.key_mgmt |= KEY_MGMT_PSK; priv->uap_key_mgmt |= KEY_MGMT_PSK; break; default: break; } break; case IW_AUTH_WPA_ENABLED: case IW_AUTH_TKIP_COUNTERMEASURES: case IW_AUTH_DROP_UNENCRYPTED: case IW_AUTH_RX_UNENCRYPTED_EAPOL: case IW_AUTH_ROAMING_CONTROL: case IW_AUTH_PRIVACY_INVOKED: default: LEAVE(); return -EOPNOTSUPP; /* No AP configuration */ } if (!sys_cfg.key_mgmt) sys_cfg.key_mgmt = priv->uap_key_mgmt; if (sys_cfg.key_mgmt & KEY_MGMT_PSK) sys_cfg.key_mgmt_operation |= 0x01; if (sys_cfg.key_mgmt & KEY_MGMT_EAP) sys_cfg.key_mgmt_operation |= 0x03; if (!sys_cfg.protocol) sys_cfg.protocol = priv->uap_protocol; /* Set AP configuration */ if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_SET, MOAL_IOCTL_WAIT, &sys_cfg)) { PRINTM(MERROR, "Error setting AP confiruration\n"); ret = -EFAULT; goto done; } done: LEAVE(); return 0; }
/** * @brief Extended version of encoding configuration * * @param dev A pointer to net_device structure * @param info A pointer to iw_request_info structure * @param dwrq A pointer to iw_point structure * @param extra A pointer to extra data buf * * @return 0 --success, otherwise fail */ static int woal_set_encode_ext(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { struct iw_encode_ext *ext = (struct iw_encode_ext *) extra; moal_private *priv = (moal_private *) netdev_priv(dev); int key_index; t_u8 *pkey_material = NULL; mlan_ioctl_req *req = NULL; mlan_ds_sec_cfg *sec = NULL; mlan_uap_bss_param sys_cfg; wep_key *pwep_key = NULL; int ret = 0; ENTER(); key_index = (dwrq->flags & IW_ENCODE_INDEX) - 1; if (key_index < 0 || key_index > 3) { ret = -EINVAL; goto done; } if (ext->key_len > (dwrq->length - sizeof(struct iw_encode_ext))) { ret = -EINVAL; goto done; } /* Initialize the invalid values so that the correct values below are downloaded to firmware */ woal_set_sys_config_invalid_data(&sys_cfg); pkey_material = (t_u8 *) (ext + 1); /* Disable Key */ if ((dwrq->flags & IW_ENCODE_DISABLED) && !ext->key_len) { sys_cfg.protocol = PROTOCOL_NO_SECURITY; } else if (ext->alg == IW_ENCODE_ALG_WEP) { sys_cfg.protocol = PROTOCOL_STATIC_WEP; /* Set WEP key */ switch (key_index) { case 0: pwep_key = &sys_cfg.wep_cfg.key0; break; case 1: pwep_key = &sys_cfg.wep_cfg.key1; break; case 2: pwep_key = &sys_cfg.wep_cfg.key2; break; case 3: pwep_key = &sys_cfg.wep_cfg.key3; break; } pwep_key->key_index = key_index; pwep_key->is_default = MTRUE; pwep_key->length = ext->key_len; memcpy(pwep_key->key, pkey_material, ext->key_len); } else { sys_cfg.protocol = PROTOCOL_WPA2_MIXED; if (ext->alg == IW_ENCODE_ALG_TKIP) { sys_cfg.wpa_cfg.pairwise_cipher_wpa = CIPHER_TKIP; sys_cfg.wpa_cfg.pairwise_cipher_wpa2 = CIPHER_TKIP; sys_cfg.wpa_cfg.group_cipher = CIPHER_TKIP; } if (ext->alg == IW_ENCODE_ALG_CCMP) { sys_cfg.wpa_cfg.pairwise_cipher_wpa = CIPHER_AES_CCMP; sys_cfg.wpa_cfg.pairwise_cipher_wpa2 = CIPHER_AES_CCMP; sys_cfg.wpa_cfg.group_cipher = CIPHER_AES_CCMP; } /* Set WPA key */ req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg)); if (req == NULL) { ret = -ENOMEM; goto done; } sec = (mlan_ds_sec_cfg *) req->pbuf; sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_KEY; req->req_id = MLAN_IOCTL_SEC_CFG; req->action = MLAN_ACT_SET; sec->param.encrypt_key.key_len = ext->key_len; sec->param.encrypt_key.key_index = key_index; memcpy(sec->param.encrypt_key.key_material, pkey_material, ext->key_len); memcpy(sec->param.encrypt_key.mac_addr, ext->addr.sa_data, ETH_ALEN); if ((ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) && !key_index) { key_index = 1; sec->param.encrypt_key.key_index = key_index; PRINTM(MWARN, "Key index changed for GTK: %ld\n", sec->param.encrypt_key.key_index); } if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { ret = -EFAULT; } } if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_SET, &sys_cfg)) { PRINTM(MERROR, "Error setting AP confiruration\n"); ret = -EFAULT; goto done; } done: if (req) kfree(req); LEAVE(); return ret; }
/** * @brief Set IE * * Pass an opaque block of data, expected to be IEEE IEs, to the driver * for eventual passthrough to the firmware in an associate/join * (and potentially start) command. * * @param dev A pointer to net_device structure * @param info A pointer to iw_request_info structure * @param dwrq A pointer to iw_point structure * @param extra A pointer to extra data buf * * @return 0 --success, otherwise fail */ static int woal_set_gen_ie(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { int ret = 0; moal_private *priv = (moal_private *) netdev_priv(dev); mlan_ds_misc_cfg *misc = NULL; mlan_ioctl_req *req = NULL; mlan_uap_bss_param sys_cfg; IEEEtypes_Header_t *ie_hdr = NULL; IEEEtypes_Header_t *ie_hdr1 = NULL; ENTER(); req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_misc_cfg)); if (req == NULL) { ret = -ENOMEM; goto done; } req->req_id = MLAN_IOCTL_MISC_CFG; misc = (mlan_ds_misc_cfg *) req->pbuf; misc->sub_command = MLAN_OID_MISC_CUSTOM_IE; misc->param.cust_ie.type = 0x0169; /* TLV_TYPE_MGMT_IE */ req->action = MLAN_ACT_SET; if (dwrq->length > MAX_IE_SIZE) { ret = -EFAULT; goto done; } misc->param.cust_ie.len = dwrq->length + sizeof(custom_ie) - MAX_IE_SIZE; misc->param.cust_ie.ie_data_list[0].ie_index = 0; misc->param.cust_ie.ie_data_list[0].mgmt_subtype_mask = 0xffff; misc->param.cust_ie.ie_data_list[0].ie_length = dwrq->length; memcpy(misc->param.cust_ie.ie_data_list[0].ie_buffer, extra, dwrq->length); if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { ret = -EFAULT; goto done; } /* Initialize the invalid values so that the correct values below are downloaded to firmware */ woal_set_sys_config_invalid_data(&sys_cfg); ie_hdr = (IEEEtypes_Header_t *) extra; if (ie_hdr->element_id == WPA_IE) sys_cfg.protocol = PROTOCOL_WPA; else if (ie_hdr->element_id == RSN_IE) sys_cfg.protocol = PROTOCOL_WPA2; if (dwrq->length > (ie_hdr->len + sizeof(IEEEtypes_Header_t))) { ie_hdr1 = (IEEEtypes_Header_t *) ((t_u8 *) extra + ie_hdr->len + sizeof(IEEEtypes_Header_t)); if ((ie_hdr->element_id == WPA_IE && ie_hdr1->element_id == RSN_IE) || (ie_hdr->element_id == RSN_IE && ie_hdr1->element_id == WPA_IE)) { sys_cfg.protocol = PROTOCOL_WPA2_MIXED; } } if (sys_cfg.protocol) { if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_SET, &sys_cfg)) { PRINTM(MERROR, "Error setting AP confiruration\n"); ret = -EFAULT; goto done; } } done: if (req) kfree(req); LEAVE(); return ret; }
/** * @brief initialize AP or GO bss config * * @param priv A pointer to moal private structure * @param params A pointer to beacon_parameters structure * @return 0 -- success, otherwise fail */ static int woal_cfg80211_beacon_config(moal_private * priv, struct beacon_parameters *params) #endif { int ret = 0; mlan_uap_bss_param sys_config; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0) || defined(COMPAT_WIRELESS) int i = 0; #else const t_u8 *ssid_ie = NULL; struct ieee80211_mgmt *head = NULL; t_u16 capab_info = 0; #endif t_u8 Rates_BG[13] = { 0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c, 0 }; t_u8 Rates_A[9] = { 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c, 0 }; t_u8 chan2Offset = 0; #ifdef WIFI_DIRECT_SUPPORT t_u8 Rates_WFD[9] = { 0x8c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c, 0 }; #endif ENTER(); if (params == NULL) { ret = -EFAULT; goto done; } if (priv->bss_type != MLAN_BSS_TYPE_UAP #ifdef WIFI_DIRECT_SUPPORT && priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT #endif ) { ret = -EFAULT; goto done; } /* Initialize the uap bss values which are uploaded from firmware */ if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_GET, MOAL_IOCTL_WAIT, &sys_config)) { PRINTM(MERROR, "Error getting AP confiruration\n"); ret = -EFAULT; goto done; } /* Setting the default values */ sys_config.channel = 6; sys_config.preamble_type = 0; if (priv->bss_type == MLAN_BSS_TYPE_UAP) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) if (params->beacon_interval) sys_config.beacon_period = params->beacon_interval; #else if (params->interval) sys_config.beacon_period = params->interval; #endif if (params->dtim_period) sys_config.dtim_period = params->dtim_period; } if (priv->channel) { memset(sys_config.rates, 0, sizeof(sys_config.rates)); sys_config.channel = priv->channel; if (priv->channel <= MAX_BG_CHANNEL) { sys_config.band_cfg = BAND_CONFIG_2G; #ifdef WIFI_DIRECT_SUPPORT if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) memcpy(sys_config.rates, Rates_WFD, sizeof(Rates_WFD)); else #endif memcpy(sys_config.rates, Rates_BG, sizeof(Rates_BG)); } else { sys_config.band_cfg = BAND_CONFIG_5G; chan2Offset = woal_get_second_channel_offset(priv->channel); if (chan2Offset) { sys_config.band_cfg |= chan2Offset; sys_config.ht_cap_info = 0x117e; sys_config.ampdu_param = 3; } #ifdef WIFI_DIRECT_SUPPORT if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) memcpy(sys_config.rates, Rates_WFD, sizeof(Rates_WFD)); else #endif memcpy(sys_config.rates, Rates_A, sizeof(Rates_A)); } } #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0) || defined(COMPAT_WIRELESS) if (!params->ssid || !params->ssid_len) { ret = -EINVAL; goto done; } memcpy(sys_config.ssid.ssid, params->ssid, MIN(MLAN_MAX_SSID_LENGTH, params->ssid_len)); sys_config.ssid.ssid_len = MIN(MLAN_MAX_SSID_LENGTH, params->ssid_len); if (params->hidden_ssid) sys_config.bcast_ssid_ctl = 0; else sys_config.bcast_ssid_ctl = 1; if (params->auth_type == NL80211_AUTHTYPE_SHARED_KEY) sys_config.auth_mode = MLAN_AUTH_MODE_SHARED; else sys_config.auth_mode = MLAN_AUTH_MODE_OPEN; for (i = 0; i < params->crypto.n_akm_suites; i++) { switch (params->crypto.akm_suites[i]) { case WLAN_AKM_SUITE_8021X: sys_config.key_mgmt = KEY_MGMT_EAP; if ((params->crypto.wpa_versions & NL80211_WPA_VERSION_1) && (params->crypto.wpa_versions & NL80211_WPA_VERSION_2)) sys_config.protocol = PROTOCOL_WPA | PROTOCOL_WPA2; else if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2) sys_config.protocol = PROTOCOL_WPA2; else if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1) sys_config.protocol = PROTOCOL_WPA; break; case WLAN_AKM_SUITE_PSK: sys_config.key_mgmt = KEY_MGMT_PSK; if ((params->crypto.wpa_versions & NL80211_WPA_VERSION_1) && (params->crypto.wpa_versions & NL80211_WPA_VERSION_2)) sys_config.protocol = PROTOCOL_WPA | PROTOCOL_WPA2; else if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2) sys_config.protocol = PROTOCOL_WPA2; else if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1) sys_config.protocol = PROTOCOL_WPA; break; } } sys_config.wpa_cfg.pairwise_cipher_wpa = 0; sys_config.wpa_cfg.pairwise_cipher_wpa2 = 0; for (i = 0; i < params->crypto.n_ciphers_pairwise; i++) { switch (params->crypto.ciphers_pairwise[i]) { case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: break; case WLAN_CIPHER_SUITE_TKIP: if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1) sys_config.wpa_cfg.pairwise_cipher_wpa |= CIPHER_TKIP; if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2) sys_config.wpa_cfg.pairwise_cipher_wpa2 |= CIPHER_TKIP; break; case WLAN_CIPHER_SUITE_CCMP: if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1) sys_config.wpa_cfg.pairwise_cipher_wpa |= CIPHER_AES_CCMP; if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2) sys_config.wpa_cfg.pairwise_cipher_wpa2 |= CIPHER_AES_CCMP; break; } } switch (params->crypto.cipher_group) { case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: if ((priv->cipher == WLAN_CIPHER_SUITE_WEP40) || (priv->cipher == WLAN_CIPHER_SUITE_WEP104)) { sys_config.protocol = PROTOCOL_STATIC_WEP; sys_config.key_mgmt = KEY_MGMT_NONE; sys_config.wpa_cfg.length = 0; sys_config.wep_cfg.key0.key_index = priv->key_index; sys_config.wep_cfg.key0.is_default = 1; sys_config.wep_cfg.key0.length = priv->key_len; memcpy(sys_config.wep_cfg.key0.key, priv->key_material, priv->key_len); } break; case WLAN_CIPHER_SUITE_TKIP: sys_config.wpa_cfg.group_cipher = CIPHER_TKIP; break; case WLAN_CIPHER_SUITE_CCMP: sys_config.wpa_cfg.group_cipher = CIPHER_AES_CCMP; break; } #else /* Since in Android ICS 4.0.1's wpa_supplicant, there is no way to set ssid when GO (AP) starts up, so get it from beacon head parameter TODO: right now use hard code 24 -- ieee80211 header lenth, 12 -- fixed element length for beacon */ #define BEACON_IE_OFFSET 36 /* Find SSID in head SSID IE id: 0, right now use hard code */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) ssid_ie = woal_parse_ie_tlv(params->beacon.head + BEACON_IE_OFFSET, params->beacon.head_len - BEACON_IE_OFFSET, 0); #else ssid_ie = woal_parse_ie_tlv(params->head + BEACON_IE_OFFSET, params->head_len - BEACON_IE_OFFSET, 0); #endif if (!ssid_ie) { PRINTM(MERROR, "No ssid IE found.\n"); ret = -EFAULT; goto done; } if (*(ssid_ie + 1) > 32) { PRINTM(MERROR, "ssid len error: %d\n", *(ssid_ie + 1)); ret = -EFAULT; goto done; } memcpy(sys_config.ssid.ssid, ssid_ie + 2, *(ssid_ie + 1)); sys_config.ssid.ssid_len = *(ssid_ie + 1); #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) head = (struct ieee80211_mgmt *) params->beacon.head; #else head = (struct ieee80211_mgmt *) params->head; #endif capab_info = le16_to_cpu(head->u.beacon.capab_info); PRINTM(MIOCTL, "capab_info=0x%x\n", head->u.beacon.capab_info); sys_config.auth_mode = MLAN_AUTH_MODE_OPEN; /** For ICS, we don't support OPEN mode */ if ((priv->cipher == WLAN_CIPHER_SUITE_WEP40) || (priv->cipher == WLAN_CIPHER_SUITE_WEP104)) { sys_config.protocol = PROTOCOL_STATIC_WEP; sys_config.key_mgmt = KEY_MGMT_NONE; sys_config.wpa_cfg.length = 0; sys_config.wep_cfg.key0.key_index = priv->key_index; sys_config.wep_cfg.key0.is_default = 1; sys_config.wep_cfg.key0.length = priv->key_len; memcpy(sys_config.wep_cfg.key0.key, priv->key_material, priv->key_len); } else { /** Get cipher and key_mgmt from RSN/WPA IE */ if (capab_info & WLAN_CAPABILITY_PRIVACY) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0) if (MFALSE == woal_find_wpa_ies(params->beacon.tail, params->beacon.tail_len, &sys_config)) #else if (MFALSE == woal_find_wpa_ies(params->tail, params->tail_len, &sys_config)) #endif { /* hard code setting to wpa2-psk */ sys_config.protocol = PROTOCOL_WPA2; sys_config.key_mgmt = KEY_MGMT_PSK; sys_config.wpa_cfg.pairwise_cipher_wpa2 = CIPHER_AES_CCMP; sys_config.wpa_cfg.group_cipher = CIPHER_AES_CCMP; } } } #endif /* COMPAT_WIRELESS */ /* If the security mode is configured as WEP or WPA-PSK, it will disable 11n automatically, and if configured as open(off) or wpa2-psk, it will automatically enable 11n */ if ((sys_config.protocol == PROTOCOL_STATIC_WEP) || (sys_config.protocol == PROTOCOL_WPA)) woal_uap_set_11n_status(&sys_config, MLAN_ACT_DISABLE); else woal_uap_set_11n_status(&sys_config, MLAN_ACT_ENABLE); if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_SET, MOAL_IOCTL_WAIT, &sys_config)) { ret = -EFAULT; goto done; } done: LEAVE(); return ret; }
/** * @brief Initialize the uAP wiphy * * @param priv A pointer to moal_private structure * @param wait_option Wait option * * @return MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE */ mlan_status woal_cfg80211_uap_init_wiphy(moal_private * priv, t_u8 wait_option) { struct wiphy *wiphy; mlan_uap_bss_param ap_cfg; mlan_ioctl_req *req = NULL; mlan_ds_11n_cfg *cfg_11n = NULL; t_u32 hw_dev_cap; ENTER(); if (priv->wdev) wiphy = priv->wdev->wiphy; else { PRINTM(MERROR, "Invalid parameter when init wiphy.\n"); LEAVE(); return MLAN_STATUS_FAILURE; } if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_GET, wait_option, &ap_cfg)) { LEAVE(); return MLAN_STATUS_FAILURE; } /* Get 11n tx parameters from MLAN */ req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11n_cfg)); if (req == NULL) { LEAVE(); return MLAN_STATUS_FAILURE; } cfg_11n = (mlan_ds_11n_cfg *) req->pbuf; cfg_11n->sub_command = MLAN_OID_11N_HTCAP_CFG; req->req_id = MLAN_IOCTL_11N_CFG; req->action = MLAN_ACT_GET; cfg_11n->param.htcap_cfg.hw_cap_req = MTRUE; if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, wait_option)) { kfree(req); LEAVE(); return MLAN_STATUS_FAILURE; } hw_dev_cap = cfg_11n->param.htcap_cfg.htcap; /* Get supported MCS sets */ memset(req->pbuf, 0, sizeof(mlan_ds_11n_cfg)); cfg_11n->sub_command = MLAN_OID_11N_CFG_SUPPORTED_MCS_SET; req->req_id = MLAN_IOCTL_11N_CFG; req->action = MLAN_ACT_GET; if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, wait_option)) { kfree(req); LEAVE(); return MLAN_STATUS_FAILURE; } /* Initialize parameters for 2GHz and 5GHz bands */ woal_cfg80211_setup_ht_cap(&wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap, hw_dev_cap, cfg_11n->param.supported_mcs_set); /* For 2.4G band only card, this shouldn't be set */ if (wiphy->bands[IEEE80211_BAND_5GHZ]) woal_cfg80211_setup_ht_cap(&wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap, hw_dev_cap, cfg_11n->param.supported_mcs_set); if (req) kfree(req); /* Set retry limit count to wiphy */ wiphy->retry_long = (t_u8) ap_cfg.retry_limit; wiphy->retry_short = (t_u8) ap_cfg.retry_limit; wiphy->max_scan_ie_len = MAX_IE_SIZE; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) || defined(COMPAT_WIRELESS) wiphy->mgmt_stypes = ieee80211_uap_mgmt_stypes; #endif /* Set RTS threshold to wiphy */ wiphy->rts_threshold = (t_u32) ap_cfg.rts_threshold; /* Set fragment threshold to wiphy */ wiphy->frag_threshold = (t_u32) ap_cfg.frag_threshold; LEAVE(); return MLAN_STATUS_SUCCESS; }
/** * @brief Set IE * * Pass an opaque block of data, expected to be IEEE IEs, to the driver * for eventual passthrough to the firmware in an associate/join * (and potentially start) command. * * @param dev A pointer to net_device structure * @param info A pointer to iw_request_info structure * @param dwrq A pointer to iw_point structure * @param extra A pointer to extra data buf * * @return 0 --success, otherwise fail */ static int woal_set_gen_ie(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { moal_private *priv = (moal_private *) netdev_priv(dev); mlan_uap_bss_param sys_cfg; IEEEtypes_Header_t *tlv = NULL; int tlv_hdr_len = sizeof(IEEEtypes_Header_t), tlv_buf_left = 0; int ret = 0; ENTER(); /* Initialize the invalid values so that the correct values below are downloaded to firmware */ woal_set_sys_config_invalid_data(&sys_cfg); tlv_buf_left = dwrq->length; tlv = (IEEEtypes_Header_t *) extra; while (tlv_buf_left >= tlv_hdr_len) { if (tlv->element_id == WPA_IE) { sys_cfg.protocol |= PROTOCOL_WPA; if (priv->pairwise_cipher == CIPHER_TKIP) { sys_cfg.wpa_cfg.pairwise_cipher_wpa = CIPHER_TKIP; PRINTM(MINFO, "Set IE Cipher TKIP\n"); } if (priv->pairwise_cipher == CIPHER_AES_CCMP) { sys_cfg.wpa_cfg.pairwise_cipher_wpa = CIPHER_AES_CCMP; PRINTM(MINFO, "Set IE Cipher CCMP\n"); } if (priv->pairwise_cipher == (CIPHER_TKIP | CIPHER_AES_CCMP)) { sys_cfg.wpa_cfg.pairwise_cipher_wpa = CIPHER_TKIP | CIPHER_AES_CCMP; PRINTM(MINFO, "Set IE Cipher TKIP + CCMP\n"); } memcpy(priv->bcn_ie_buf + priv->bcn_ie_len, ((t_u8 *) tlv), sizeof(IEEEtypes_Header_t) + tlv->len); priv->bcn_ie_len += sizeof(IEEEtypes_Header_t) + tlv->len; } if (tlv->element_id == RSN_IE) { sys_cfg.protocol |= PROTOCOL_WPA2; if (priv->pairwise_cipher == CIPHER_TKIP) { sys_cfg.wpa_cfg.pairwise_cipher_wpa2 = CIPHER_TKIP; } if (priv->pairwise_cipher == CIPHER_AES_CCMP) { sys_cfg.wpa_cfg.pairwise_cipher_wpa2 = CIPHER_AES_CCMP; } if (priv->pairwise_cipher == (CIPHER_TKIP | CIPHER_AES_CCMP)) { sys_cfg.wpa_cfg.pairwise_cipher_wpa2 = (CIPHER_TKIP | CIPHER_AES_CCMP); } memcpy(priv->bcn_ie_buf + priv->bcn_ie_len, ((t_u8 *) tlv), sizeof(IEEEtypes_Header_t) + tlv->len); priv->bcn_ie_len += sizeof(IEEEtypes_Header_t) + tlv->len; } if (priv->group_cipher == CIPHER_TKIP) sys_cfg.wpa_cfg.group_cipher = CIPHER_TKIP; if (priv->group_cipher == CIPHER_AES_CCMP) sys_cfg.wpa_cfg.group_cipher = CIPHER_AES_CCMP; tlv_buf_left -= (tlv_hdr_len + tlv->len); tlv = (IEEEtypes_Header_t *) ((t_u8 *) tlv + tlv_hdr_len + tlv->len); } sys_cfg.key_mgmt = priv->uap_key_mgmt; if (sys_cfg.key_mgmt & KEY_MGMT_PSK) sys_cfg.key_mgmt_operation |= 0x01; if (sys_cfg.key_mgmt & KEY_MGMT_EAP) sys_cfg.key_mgmt_operation |= 0x03; if (sys_cfg.protocol) { if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_SET, MOAL_IOCTL_WAIT, &sys_cfg)) { PRINTM(MERROR, "Error setting AP configuration\n"); ret = -EFAULT; goto done; } priv->pairwise_cipher = 0; priv->group_cipher = 0; /* custom IE command to set priv->bcn_ie_buf */ if (MLAN_STATUS_SUCCESS != #define UAP_RSN_MASK (BIT(8) | BIT(5) | BIT(1) | BIT(3)) woal_set_get_custom_ie(priv, UAP_RSN_MASK, priv->bcn_ie_buf, priv->bcn_ie_len)) { PRINTM(MERROR, "Error setting wpa-rsn IE\n"); ret = -EFAULT; } } else if (dwrq->length == 0) { /* custom IE command to re-set priv->bcn_ie_buf */ if (MLAN_STATUS_SUCCESS != woal_set_get_custom_ie(priv, 0, priv->bcn_ie_buf, priv->bcn_ie_len)) { PRINTM(MERROR, "Error resetting wpa-rsn IE\n"); ret = -EFAULT; } priv->bcn_ie_len = 0; } done: LEAVE(); return ret; }
/** * @brief Get authentication mode parameters * * @param dev A pointer to net_device structure * @param info A pointer to iw_request_info structure * @param vwrq A pointer to iw_param structure * @param extra A pointer to extra data buf * * @return 0 --success, otherwise fail */ static int woal_get_auth(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra) { moal_private *priv = (moal_private *) netdev_priv(dev); mlan_uap_bss_param ap_cfg; ENTER(); if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_GET, MOAL_IOCTL_WAIT, &ap_cfg)) { PRINTM(MERROR, "Error getting AP confiruration\n"); LEAVE(); return -EFAULT; } switch (vwrq->flags & IW_AUTH_INDEX) { case IW_AUTH_CIPHER_PAIRWISE: if (ap_cfg.wpa_cfg.pairwise_cipher_wpa == CIPHER_TKIP || ap_cfg.wpa_cfg.pairwise_cipher_wpa2 == CIPHER_TKIP) vwrq->value = IW_AUTH_CIPHER_TKIP; else if (ap_cfg.wpa_cfg.pairwise_cipher_wpa == CIPHER_AES_CCMP || ap_cfg.wpa_cfg.pairwise_cipher_wpa2 == CIPHER_AES_CCMP) vwrq->value = IW_AUTH_CIPHER_CCMP; else vwrq->value = IW_AUTH_CIPHER_NONE; break; case IW_AUTH_CIPHER_GROUP: if (ap_cfg.wpa_cfg.group_cipher == CIPHER_TKIP) vwrq->value = IW_AUTH_CIPHER_TKIP; else if (ap_cfg.wpa_cfg.group_cipher == CIPHER_AES_CCMP) vwrq->value = IW_AUTH_CIPHER_CCMP; else vwrq->value = IW_AUTH_CIPHER_NONE; break; case IW_AUTH_80211_AUTH_ALG: if (ap_cfg.auth_mode == MLAN_AUTH_MODE_SHARED) vwrq->value = IW_AUTH_ALG_SHARED_KEY; else if (ap_cfg.auth_mode == MLAN_AUTH_MODE_NETWORKEAP) vwrq->value = IW_AUTH_ALG_LEAP; else vwrq->value = IW_AUTH_ALG_OPEN_SYSTEM; break; case IW_AUTH_WPA_ENABLED: if (ap_cfg.protocol == PROTOCOL_WPA || ap_cfg.protocol == PROTOCOL_WPA2 || ap_cfg.protocol == PROTOCOL_WPA2_MIXED) vwrq->value = 1; else vwrq->value = 0; break; case IW_AUTH_KEY_MGMT: if (ap_cfg.key_mgmt & KEY_MGMT_EAP) vwrq->value |= IW_AUTH_KEY_MGMT_802_1X; if (ap_cfg.key_mgmt & KEY_MGMT_PSK) vwrq->value |= IW_AUTH_KEY_MGMT_PSK; break; case IW_AUTH_WPA_VERSION: case IW_AUTH_TKIP_COUNTERMEASURES: case IW_AUTH_DROP_UNENCRYPTED: case IW_AUTH_RX_UNENCRYPTED_EAPOL: case IW_AUTH_ROAMING_CONTROL: case IW_AUTH_PRIVACY_INVOKED: default: LEAVE(); return -EOPNOTSUPP; } LEAVE(); return 0; }
/** * @brief Extended version of encoding configuration * * @param dev A pointer to net_device structure * @param info A pointer to iw_request_info structure * @param dwrq A pointer to iw_point structure * @param extra A pointer to extra data buf * * @return 0 --success, otherwise fail */ static int woal_set_encode_ext(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra) { struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; moal_private *priv = (moal_private *) netdev_priv(dev); int key_index; t_u8 *pkey_material = NULL; mlan_ioctl_req *req = NULL; mlan_ds_sec_cfg *sec = NULL; mlan_uap_bss_param sys_cfg; wep_key *pwep_key = NULL; int ret = 0; ENTER(); key_index = (dwrq->flags & IW_ENCODE_INDEX) - 1; if (key_index < 0 || key_index > 5) { ret = -EINVAL; goto done; } if (ext->key_len > (dwrq->length - sizeof(struct iw_encode_ext))) { ret = -EINVAL; goto done; } /* Initialize the invalid values so that the correct values below are downloaded to firmware */ woal_set_sys_config_invalid_data(&sys_cfg); pkey_material = (t_u8 *) (ext + 1); /* Disable Key */ if ((dwrq->flags & IW_ENCODE_DISABLED) && !ext->key_len) { sys_cfg.protocol = PROTOCOL_NO_SECURITY; } else if (ext->alg == IW_ENCODE_ALG_WEP) { sys_cfg.protocol = PROTOCOL_STATIC_WEP; /* Set WEP key */ switch (key_index) { case 0: pwep_key = &sys_cfg.wep_cfg.key0; break; case 1: pwep_key = &sys_cfg.wep_cfg.key1; break; case 2: pwep_key = &sys_cfg.wep_cfg.key2; break; case 3: pwep_key = &sys_cfg.wep_cfg.key3; break; } if (pwep_key) { pwep_key->key_index = key_index; pwep_key->is_default = MTRUE; pwep_key->length = ext->key_len; memcpy(pwep_key->key, pkey_material, ext->key_len); } } else { /* Set GTK/PTK key */ req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_sec_cfg)); if (req == NULL) { ret = -ENOMEM; goto done; } sec = (mlan_ds_sec_cfg *) req->pbuf; sec->sub_command = MLAN_OID_SEC_CFG_ENCRYPT_KEY; req->req_id = MLAN_IOCTL_SEC_CFG; req->action = MLAN_ACT_SET; sec->param.encrypt_key.key_len = ext->key_len; sec->param.encrypt_key.key_index = key_index; memcpy(sec->param.encrypt_key.key_material, pkey_material, ext->key_len); memcpy(sec->param.encrypt_key.mac_addr, ext->addr.sa_data, ETH_ALEN); sec->param.encrypt_key.key_flags = ext->ext_flags; if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { memcpy(sec->param.encrypt_key.pn, (t_u8 *) ext->rx_seq, SEQ_MAX_SIZE); DBG_HEXDUMP(MCMD_D, "Uap Rx PN", sec->param.encrypt_key.pn, SEQ_MAX_SIZE); } if (ext->ext_flags & IW_ENCODE_EXT_TX_SEQ_VALID) { memcpy(sec->param.encrypt_key.pn, (t_u8 *) ext->tx_seq, SEQ_MAX_SIZE); DBG_HEXDUMP(MCMD_D, "Uap Tx PN", sec->param.encrypt_key.pn, SEQ_MAX_SIZE); } PRINTM(MIOCTL, "set uap wpa key key_index=%d, key_len=%d key_flags=0x%x " MACSTR "\n", key_index, ext->key_len, sec->param.encrypt_key.key_flags, MAC2STR(sec->param.encrypt_key.mac_addr)); DBG_HEXDUMP(MCMD_D, "uap wpa key", pkey_material, ext->key_len); #define IW_ENCODE_ALG_AES_CMAC 5 if (ext->alg == IW_ENCODE_ALG_AES_CMAC) sec->param.encrypt_key.key_flags |= KEY_FLAG_AES_MCAST_IGTK; if (MLAN_STATUS_SUCCESS != woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT)) { ret = -EFAULT; } /* Cipher set will be done in set generic IE */ priv->pairwise_cipher = ext->alg; priv->group_cipher = ext->alg; goto done; /* No AP configuration */ } if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_SET, MOAL_IOCTL_WAIT, &sys_cfg)) { PRINTM(MERROR, "Error setting AP confiruration\n"); ret = -EFAULT; goto done; } done: if (req) kfree(req); LEAVE(); return ret; }
/** * @brief initialize AP or GO bss config * * @param priv A pointer to moal private structure * @param params A pointer to beacon_parameters structure * @return 0 -- success, otherwise fail */ static int woal_cfg80211_beacon_config(moal_private *priv, struct beacon_parameters *params) #endif { int ret = 0; mlan_uap_bss_param sys_config; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) || defined(COMPAT_WIRELESS) int i = 0; #else t_u8 wpa_ies; const t_u8 *ssid_ie = NULL; struct ieee80211_mgmt *head = NULL; t_u16 capab_info = 0; #endif t_u8 rates_bg[13] = { 0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c, 0x00 }; t_u8 rates_a[9] = { 0x8c, 0x12, 0x98, 0x24, 0xb0, 0x48, 0x60, 0x6c, 0x00 }; #ifdef WIFI_DIRECT_SUPPORT t_u8 rates_wfd[9] = { 0x8c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c, 0x00 }; #endif t_u8 chan2Offset = 0; t_u8 enable_11n = MTRUE; ENTER(); if (params == NULL) { ret = -EFAULT; goto done; } if (priv->bss_type != MLAN_BSS_TYPE_UAP #ifdef WIFI_DIRECT_SUPPORT && priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT #endif ) { ret = -EFAULT; goto done; } /* Initialize the uap bss values which are uploaded from firmware */ if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_GET, MOAL_IOCTL_WAIT, &sys_config)) { PRINTM(MERROR, "Error getting AP confiruration\n"); ret = -EFAULT; goto done; } /* Setting the default values */ sys_config.channel = 6; sys_config.preamble_type = 0; sys_config.mgmt_ie_passthru_mask = priv->mgmt_subtype_mask; memcpy(sys_config.mac_addr, priv->current_addr, ETH_ALEN); if (priv->bss_type == MLAN_BSS_TYPE_UAP) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) if (params->beacon_interval) sys_config.beacon_period = params->beacon_interval; #else if (params->interval) sys_config.beacon_period = params->interval; #endif if (params->dtim_period) sys_config.dtim_period = params->dtim_period; } if (priv->channel) { memset(sys_config.rates, 0, sizeof(sys_config.rates)); #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0) switch (params->chandef.width) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) case NL80211_CHAN_WIDTH_5: case NL80211_CHAN_WIDTH_10: #endif case NL80211_CHAN_WIDTH_20_NOHT: enable_11n = MFALSE; break; case NL80211_CHAN_WIDTH_20: break; case NL80211_CHAN_WIDTH_40: case NL80211_CHAN_WIDTH_80: case NL80211_CHAN_WIDTH_80P80: case NL80211_CHAN_WIDTH_160: if (params->chandef.center_freq1 < params->chandef.chan->center_freq) chan2Offset = SECOND_CHANNEL_BELOW; else chan2Offset = SECOND_CHANNEL_ABOVE; break; default: PRINTM(MWARN, "Unknown channel width: %d\n", params->chandef.width); break; } #else switch (params->channel_type) { case NL80211_CHAN_NO_HT: enable_11n = MFALSE; break; case NL80211_CHAN_HT20: break; case NL80211_CHAN_HT40PLUS: chan2Offset = SECOND_CHANNEL_ABOVE; break; case NL80211_CHAN_HT40MINUS: chan2Offset = SECOND_CHANNEL_BELOW; break; default: PRINTM(MWARN, "Unknown channel type: %d\n", params->channel_type); break; } #endif #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) */ sys_config.channel = priv->channel; if (priv->channel <= MAX_BG_CHANNEL) { sys_config.band_cfg = BAND_CONFIG_2G; #ifdef WIFI_DIRECT_SUPPORT if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) memcpy(sys_config.rates, rates_wfd, sizeof(rates_wfd)); else #endif memcpy(sys_config.rates, rates_bg, sizeof(rates_bg)); } else { sys_config.band_cfg = BAND_CONFIG_5G; #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0) chan2Offset = woal_get_second_channel_offset(priv->channel); #else #ifdef WIFI_DIRECT_SUPPORT /* Force enable 40MHZ on WFD interface */ if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) chan2Offset = woal_get_second_channel_offset(priv-> channel); #endif #endif #ifdef WIFI_DIRECT_SUPPORT if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT) memcpy(sys_config.rates, rates_wfd, sizeof(rates_wfd)); else #endif memcpy(sys_config.rates, rates_a, sizeof(rates_a)); } /* Disable GreenField by default */ sys_config.ht_cap_info = 0x10c; if (enable_11n) sys_config.ht_cap_info |= 0x20; if (chan2Offset) { sys_config.band_cfg |= chan2Offset; sys_config.ht_cap_info |= 0x1042; sys_config.ampdu_param = 3; } PRINTM(MCMND, "11n=%d, ht_cap=0x%x, channel=%d, band_cfg=0x%x\n", enable_11n, sys_config.ht_cap_info, priv->channel, sys_config.band_cfg); } #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) || defined(COMPAT_WIRELESS) if (!params->ssid || !params->ssid_len) { ret = -EINVAL; goto done; } memcpy(sys_config.ssid.ssid, params->ssid, MIN(MLAN_MAX_SSID_LENGTH, params->ssid_len)); sys_config.ssid.ssid_len = MIN(MLAN_MAX_SSID_LENGTH, params->ssid_len); if (params->hidden_ssid) sys_config.bcast_ssid_ctl = 0; else sys_config.bcast_ssid_ctl = 1; if (params->auth_type == NL80211_AUTHTYPE_SHARED_KEY) sys_config.auth_mode = MLAN_AUTH_MODE_SHARED; else sys_config.auth_mode = MLAN_AUTH_MODE_OPEN; if (params->crypto.n_akm_suites) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) woal_find_wpa_ies(params->beacon.tail, (int)params->beacon.tail_len, &sys_config); #else woal_find_wpa_ies(params->tail, params->tail_len, &sys_config); #endif } for (i = 0; i < params->crypto.n_akm_suites; i++) { switch (params->crypto.akm_suites[i]) { case WLAN_AKM_SUITE_8021X: sys_config.key_mgmt |= KEY_MGMT_EAP; if ((params->crypto. wpa_versions & NL80211_WPA_VERSION_1) && (params->crypto. wpa_versions & NL80211_WPA_VERSION_2)) sys_config.protocol = PROTOCOL_WPA | PROTOCOL_WPA2; else if (params->crypto. wpa_versions & NL80211_WPA_VERSION_2) sys_config.protocol = PROTOCOL_WPA2; else if (params->crypto. wpa_versions & NL80211_WPA_VERSION_1) sys_config.protocol = PROTOCOL_WPA; break; case WLAN_AKM_SUITE_PSK: sys_config.key_mgmt |= KEY_MGMT_PSK; if ((params->crypto. wpa_versions & NL80211_WPA_VERSION_1) && (params->crypto. wpa_versions & NL80211_WPA_VERSION_2)) sys_config.protocol = PROTOCOL_WPA | PROTOCOL_WPA2; else if (params->crypto. wpa_versions & NL80211_WPA_VERSION_2) sys_config.protocol = PROTOCOL_WPA2; else if (params->crypto. wpa_versions & NL80211_WPA_VERSION_1) sys_config.protocol = PROTOCOL_WPA; break; } } sys_config.wpa_cfg.pairwise_cipher_wpa = 0; sys_config.wpa_cfg.pairwise_cipher_wpa2 = 0; for (i = 0; i < params->crypto.n_ciphers_pairwise; i++) { switch (params->crypto.ciphers_pairwise[i]) { case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: break; case WLAN_CIPHER_SUITE_TKIP: if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1) sys_config.wpa_cfg.pairwise_cipher_wpa |= CIPHER_TKIP; if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2) sys_config.wpa_cfg.pairwise_cipher_wpa2 |= CIPHER_TKIP; break; case WLAN_CIPHER_SUITE_CCMP: if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1) sys_config.wpa_cfg.pairwise_cipher_wpa |= CIPHER_AES_CCMP; if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2) sys_config.wpa_cfg.pairwise_cipher_wpa2 |= CIPHER_AES_CCMP; break; } } switch (params->crypto.cipher_group) { case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: if ((priv->cipher == WLAN_CIPHER_SUITE_WEP40) || (priv->cipher == WLAN_CIPHER_SUITE_WEP104)) { sys_config.protocol = PROTOCOL_STATIC_WEP; sys_config.key_mgmt = KEY_MGMT_NONE; sys_config.wpa_cfg.length = 0; memcpy(&sys_config.wep_cfg.key0, &priv->uap_wep_key[0], sizeof(wep_key)); memcpy(&sys_config.wep_cfg.key1, &priv->uap_wep_key[1], sizeof(wep_key)); memcpy(&sys_config.wep_cfg.key2, &priv->uap_wep_key[2], sizeof(wep_key)); memcpy(&sys_config.wep_cfg.key3, &priv->uap_wep_key[3], sizeof(wep_key)); } break; case WLAN_CIPHER_SUITE_TKIP: sys_config.wpa_cfg.group_cipher = CIPHER_TKIP; break; case WLAN_CIPHER_SUITE_CCMP: sys_config.wpa_cfg.group_cipher = CIPHER_AES_CCMP; break; } #else /* Since in Android ICS 4.0.1's wpa_supplicant, there is no way to set ssid when GO (AP) starts up, so get it from beacon head parameter TODO: right now use hard code 24 -- ieee80211 header lenth, 12 -- fixed element length for beacon */ #define BEACON_IE_OFFSET 36 /* Find SSID in head SSID IE id: 0, right now use hard code */ ssid_ie = woal_parse_ie_tlv(params->head + BEACON_IE_OFFSET, params->head_len - BEACON_IE_OFFSET, 0); if (!ssid_ie) { PRINTM(MERROR, "No ssid IE found.\n"); ret = -EFAULT; goto done; } if (*(ssid_ie + 1) > 32) { PRINTM(MERROR, "ssid len error: %d\n", *(ssid_ie + 1)); ret = -EFAULT; goto done; } memcpy(sys_config.ssid.ssid, ssid_ie + 2, *(ssid_ie + 1)); sys_config.ssid.ssid_len = *(ssid_ie + 1); head = (struct ieee80211_mgmt *)params->head; capab_info = le16_to_cpu(head->u.beacon.capab_info); PRINTM(MIOCTL, "capab_info=0x%x\n", head->u.beacon.capab_info); sys_config.auth_mode = MLAN_AUTH_MODE_OPEN; /** For ICS, we don't support OPEN mode */ if ((priv->cipher == WLAN_CIPHER_SUITE_WEP40) || (priv->cipher == WLAN_CIPHER_SUITE_WEP104)) { sys_config.protocol = PROTOCOL_STATIC_WEP; sys_config.key_mgmt = KEY_MGMT_NONE; sys_config.wpa_cfg.length = 0; memcpy(&sys_config.wep_cfg.key0, &priv->uap_wep_key[0], sizeof(wep_key)); memcpy(&sys_config.wep_cfg.key1, &priv->uap_wep_key[1], sizeof(wep_key)); memcpy(&sys_config.wep_cfg.key2, &priv->uap_wep_key[2], sizeof(wep_key)); memcpy(&sys_config.wep_cfg.key3, &priv->uap_wep_key[3], sizeof(wep_key)); } else { /** Get cipher and key_mgmt from RSN/WPA IE */ if (capab_info & WLAN_CAPABILITY_PRIVACY) { wpa_ies = woal_find_wpa_ies(params->tail, params->tail_len, &sys_config); if (wpa_ies == MFALSE) { /* hard code setting to wpa2-psk */ sys_config.protocol = PROTOCOL_WPA2; sys_config.key_mgmt = KEY_MGMT_PSK; sys_config.wpa_cfg.pairwise_cipher_wpa2 = CIPHER_AES_CCMP; sys_config.wpa_cfg.group_cipher = CIPHER_AES_CCMP; } } } #endif /* COMPAT_WIRELESS */ /* If the security mode is configured as WEP or WPA-PSK, it will disable 11n automatically, and if configured as open(off) or wpa2-psk, it will automatically enable 11n */ if ((sys_config.protocol == PROTOCOL_STATIC_WEP) || (sys_config.protocol == PROTOCOL_WPA)) enable_11n = MFALSE; if (!enable_11n) { woal_uap_set_11n_status(&sys_config, MLAN_ACT_DISABLE); } else { woal_uap_set_11n_status(&sys_config, MLAN_ACT_ENABLE); woal_set_get_tx_bf_cap(priv, MLAN_ACT_GET, &sys_config.tx_bf_cap); } if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_SET, MOAL_IOCTL_WAIT, &sys_config)) { ret = -EFAULT; goto done; } done: LEAVE(); return ret; }