/** * @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 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 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 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 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 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; }