alistair23-linux/drivers/staging/vt6656/wpactl.c
Jesper Juhl e3b09e4bf6 staging, vt6656/wpactl.c: Fix mem leak in wpa_ioctl()
If we hit the default case in the switch statement in wpa_ioctl()
we'll leak the memory allocated to 'param' when the variable goes out
of scope without having been assigned to anything.

This patch fixes the leak by kfree()'ing the memory before we return
from the function.

Signed-off-by: Jesper Juhl <jj@chaosbits.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2012-02-09 09:20:06 -08:00

920 lines
23 KiB
C

/*
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
*
* File: wpactl.c
*
* Purpose: handle wpa supplicant ioctl input/out functions
*
* Author: Lyndon Chen
*
* Date: July 28, 2006
*
* Functions:
*
* Revision History:
*
*/
#include "wpactl.h"
#include "key.h"
#include "mac.h"
#include "device.h"
#include "wmgr.h"
#include "iocmd.h"
#include "iowpa.h"
#include "control.h"
#include "rndis.h"
#include "rf.h"
/*--------------------- Static Definitions -------------------------*/
#define VIAWGET_WPA_MAX_BUF_SIZE 1024
static const int frequency_list[] = {
2412, 2417, 2422, 2427, 2432, 2437, 2442,
2447, 2452, 2457, 2462, 2467, 2472, 2484
};
/*--------------------- Static Classes ----------------------------*/
/*--------------------- Static Variables --------------------------*/
static int msglevel = MSG_LEVEL_INFO;
/*--------------------- Static Functions --------------------------*/
/*--------------------- Export Variables --------------------------*/
static void wpadev_setup(struct net_device *dev)
{
dev->type = ARPHRD_IEEE80211;
dev->hard_header_len = ETH_HLEN;
dev->mtu = 2048;
dev->addr_len = ETH_ALEN;
dev->tx_queue_len = 1000;
memset(dev->broadcast, 0xFF, ETH_ALEN);
dev->flags = IFF_BROADCAST | IFF_MULTICAST;
}
/*
* Description:
* register netdev for wpa supplicant deamon
*
* Parameters:
* In:
* pDevice -
* enable -
* Out:
*
* Return Value:
*
*/
static int wpa_init_wpadev(PSDevice pDevice)
{
PSDevice wpadev_priv;
struct net_device *dev = pDevice->dev;
int ret = 0;
pDevice->wpadev = alloc_netdev(sizeof(PSDevice), "vntwpa", wpadev_setup);
if (pDevice->wpadev == NULL)
return -ENOMEM;
wpadev_priv = netdev_priv(pDevice->wpadev);
*wpadev_priv = *pDevice;
memcpy(pDevice->wpadev->dev_addr, dev->dev_addr, ETH_ALEN);
pDevice->wpadev->base_addr = dev->base_addr;
pDevice->wpadev->irq = dev->irq;
pDevice->wpadev->mem_start = dev->mem_start;
pDevice->wpadev->mem_end = dev->mem_end;
ret = register_netdev(pDevice->wpadev);
if (ret) {
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: register_netdev(WPA) failed!\n",
dev->name);
free_netdev(pDevice->wpadev);
return -1;
}
if (pDevice->skb == NULL) {
pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
if (pDevice->skb == NULL)
return -ENOMEM;
}
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Registered netdev %s for WPA management\n",
dev->name, pDevice->wpadev->name);
return 0;
}
/*
* Description:
* unregister net_device (wpadev)
*
* Parameters:
* In:
* pDevice -
* Out:
*
* Return Value:
*
*/
static int wpa_release_wpadev(PSDevice pDevice)
{
if (pDevice->skb) {
dev_kfree_skb(pDevice->skb);
pDevice->skb = NULL;
}
if (pDevice->wpadev) {
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Netdevice %s unregistered\n",
pDevice->dev->name, pDevice->wpadev->name);
unregister_netdev(pDevice->wpadev);
free_netdev(pDevice->wpadev);
pDevice->wpadev = NULL;
}
return 0;
}
/*
* Description:
* Set enable/disable dev for wpa supplicant deamon
*
* Parameters:
* In:
* pDevice -
* val -
* Out:
*
* Return Value:
*
*/
int wpa_set_wpadev(PSDevice pDevice, int val)
{
if (val)
return wpa_init_wpadev(pDevice);
return wpa_release_wpadev(pDevice);
}
/*
* Description:
* Set WPA algorithm & keys
*
* Parameters:
* In:
* pDevice -
* param -
* Out:
*
* Return Value:
*
*/
int wpa_set_keys(PSDevice pDevice, void *ctx, BOOL fcpfkernel)
{
struct viawget_wpa_param *param = ctx;
PSMgmtObject pMgmt = &pDevice->sMgmtObj;
DWORD dwKeyIndex = 0;
BYTE abyKey[MAX_KEY_LEN];
BYTE abySeq[MAX_KEY_LEN];
QWORD KeyRSC;
BYTE byKeyDecMode = KEY_CTL_WEP;
int ret = 0;
int uu;
int ii;
if (param->u.wpa_key.alg_name > WPA_ALG_CCMP)
return -EINVAL;
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "param->u.wpa_key.alg_name = %d \n",
param->u.wpa_key.alg_name);
if (param->u.wpa_key.alg_name == WPA_ALG_NONE) {
pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
pDevice->bEncryptionEnable = FALSE;
pDevice->byKeyIndex = 0;
pDevice->bTransmitKey = FALSE;
for (uu=0; uu<MAX_KEY_TABLE; uu++) {
MACvDisableKeyEntry(pDevice, uu);
}
return ret;
}
if (param->u.wpa_key.key && param->u.wpa_key.key_len > sizeof(abyKey))
return -EINVAL;
spin_unlock_irq(&pDevice->lock);
if (param->u.wpa_key.key && fcpfkernel) {
memcpy(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len);
} else {
if (param->u.wpa_key.key &&
copy_from_user(&abyKey[0], param->u.wpa_key.key,
param->u.wpa_key.key_len)) {
spin_lock_irq(&pDevice->lock);
return -EINVAL;
}
}
spin_lock_irq(&pDevice->lock);
dwKeyIndex = (DWORD)(param->u.wpa_key.key_index);
if (param->u.wpa_key.alg_name == WPA_ALG_WEP) {
if (dwKeyIndex > 3) {
return -EINVAL;
} else {
if (param->u.wpa_key.set_tx) {
pDevice->byKeyIndex = (BYTE)dwKeyIndex;
pDevice->bTransmitKey = TRUE;
dwKeyIndex |= (1 << 31);
}
KeybSetDefaultKey( pDevice,
&(pDevice->sKey),
dwKeyIndex & ~(BIT30 | USE_KEYRSC),
param->u.wpa_key.key_len,
NULL,
abyKey,
KEY_CTL_WEP
);
}
pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
pDevice->bEncryptionEnable = TRUE;
return ret;
}
if (param->u.wpa_key.seq && param->u.wpa_key.seq_len > sizeof(abySeq))
return -EINVAL;
spin_unlock_irq(&pDevice->lock);
if (param->u.wpa_key.seq && fcpfkernel) {
memcpy(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len);
} else {
if (param->u.wpa_key.seq &&
copy_from_user(&abySeq[0], param->u.wpa_key.seq,
param->u.wpa_key.seq_len)) {
spin_lock_irq(&pDevice->lock);
return -EINVAL;
}
}
spin_lock_irq(&pDevice->lock);
if (param->u.wpa_key.seq_len > 0) {
for (ii = 0 ; ii < param->u.wpa_key.seq_len ; ii++) {
if (ii < 4)
LODWORD(KeyRSC) |= (abySeq[ii] << (ii * 8));
else
HIDWORD(KeyRSC) |= (abySeq[ii] << ((ii-4) * 8));
}
dwKeyIndex |= 1 << 29;
}
if (param->u.wpa_key.key_index >= MAX_GROUP_KEY) {
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return dwKeyIndex > 3\n");
return -EINVAL;
}
if (param->u.wpa_key.alg_name == WPA_ALG_TKIP) {
pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;
}
if (param->u.wpa_key.alg_name == WPA_ALG_CCMP) {
pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;
}
if (param->u.wpa_key.set_tx)
dwKeyIndex |= (1 << 31);
if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled)
byKeyDecMode = KEY_CTL_CCMP;
else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled)
byKeyDecMode = KEY_CTL_TKIP;
else
byKeyDecMode = KEY_CTL_WEP;
// Fix HCT test that set 256 bits KEY and Ndis802_11Encryption3Enabled
if (pDevice->eEncryptionStatus == Ndis802_11Encryption3Enabled) {
if (param->u.wpa_key.key_len == MAX_KEY_LEN)
byKeyDecMode = KEY_CTL_TKIP;
else if (param->u.wpa_key.key_len == WLAN_WEP40_KEYLEN)
byKeyDecMode = KEY_CTL_WEP;
else if (param->u.wpa_key.key_len == WLAN_WEP104_KEYLEN)
byKeyDecMode = KEY_CTL_WEP;
} else if (pDevice->eEncryptionStatus == Ndis802_11Encryption2Enabled) {
if (param->u.wpa_key.key_len == WLAN_WEP40_KEYLEN)
byKeyDecMode = KEY_CTL_WEP;
else if (param->u.wpa_key.key_len == WLAN_WEP104_KEYLEN)
byKeyDecMode = KEY_CTL_WEP;
}
// Check TKIP key length
if ((byKeyDecMode == KEY_CTL_TKIP) &&
(param->u.wpa_key.key_len != MAX_KEY_LEN)) {
// TKIP Key must be 256 bits
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return- TKIP Key must be 256 bits!\n");
return -EINVAL;
}
// Check AES key length
if ((byKeyDecMode == KEY_CTL_CCMP) &&
(param->u.wpa_key.key_len != AES_KEY_LEN)) {
// AES Key must be 128 bits
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "return - AES Key must be 128 bits\n");
return -EINVAL;
}
if (is_broadcast_ether_addr(&param->addr[0]) || (param->addr == NULL)) {
/* if broadcast, set the key as every key entry's group key */
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Groupe Key Assign.\n");
if ((KeybSetAllGroupKey(pDevice, &(pDevice->sKey), dwKeyIndex,
param->u.wpa_key.key_len,
(PQWORD) &(KeyRSC),
(PBYTE)abyKey,
byKeyDecMode
) == TRUE) &&
(KeybSetDefaultKey(pDevice,
&(pDevice->sKey),
dwKeyIndex,
param->u.wpa_key.key_len,
(PQWORD) &(KeyRSC),
(PBYTE)abyKey,
byKeyDecMode
) == TRUE) ) {
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "GROUP Key Assign.\n");
} else {
return -EINVAL;
}
} else {
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Assign.\n");
// BSSID not 0xffffffffffff
// Pairwise Key can't be WEP
if (byKeyDecMode == KEY_CTL_WEP) {
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key can't be WEP\n");
return -EINVAL;
}
dwKeyIndex |= (1 << 30); // set pairwise key
if (pMgmt->eConfigMode == WMAC_CONFIG_IBSS_STA) {
//DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - WMAC_CONFIG_IBSS_STA\n"));
return -EINVAL;
}
if (KeybSetKey(pDevice, &(pDevice->sKey), &param->addr[0],
dwKeyIndex, param->u.wpa_key.key_len,
(PQWORD) &(KeyRSC), (PBYTE)abyKey, byKeyDecMode
) == TRUE) {
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Set\n");
} else {
// Key Table Full
if (!compare_ether_addr(&param->addr[0], pDevice->abyBSSID)) {
//DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA -Key Table Full.2\n"));
return -EINVAL;
} else {
// Save Key and configure just before associate/reassociate to BSSID
// we do not implement now
return -EINVAL;
}
}
} // BSSID not 0xffffffffffff
if ((ret == 0) && ((param->u.wpa_key.set_tx) != 0)) {
pDevice->byKeyIndex = (BYTE)param->u.wpa_key.key_index;
pDevice->bTransmitKey = TRUE;
}
pDevice->bEncryptionEnable = TRUE;
return ret;
}
/*
* Description:
* enable wpa auth & mode
*
* Parameters:
* In:
* pDevice -
* param -
* Out:
*
* Return Value:
*
*/
static int wpa_set_wpa(PSDevice pDevice, struct viawget_wpa_param *param)
{
PSMgmtObject pMgmt = &pDevice->sMgmtObj;
int ret = 0;
pMgmt->eAuthenMode = WMAC_AUTH_OPEN;
pMgmt->bShareKeyAlgorithm = FALSE;
return ret;
}
/*
* Description:
* set disassociate
*
* Parameters:
* In:
* pDevice -
* param -
* Out:
*
* Return Value:
*
*/
static int wpa_set_disassociate(PSDevice pDevice, struct viawget_wpa_param *param)
{
PSMgmtObject pMgmt = &pDevice->sMgmtObj;
int ret = 0;
spin_lock_irq(&pDevice->lock);
if (pDevice->bLinkPass) {
if (!memcmp(param->addr, pMgmt->abyCurrBSSID, 6))
bScheduleCommand((void *)pDevice, WLAN_CMD_DISASSOCIATE, NULL);
}
spin_unlock_irq(&pDevice->lock);
return ret;
}
/*
* Description:
* enable scan process
*
* Parameters:
* In:
* pDevice -
* param -
* Out:
*
* Return Value:
*
*/
static int wpa_set_scan(PSDevice pDevice, struct viawget_wpa_param *param)
{
int ret = 0;
/**set ap_scan=1&&scan_ssid=1 under hidden ssid mode**/
PSMgmtObject pMgmt = &pDevice->sMgmtObj;
PWLAN_IE_SSID pItemSSID;
printk("wpa_set_scan-->desired [ssid=%s,ssid_len=%d]\n",
param->u.scan_req.ssid,param->u.scan_req.ssid_len);
// Set the SSID
memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID;
pItemSSID->byElementID = WLAN_EID_SSID;
memcpy(pItemSSID->abySSID, param->u.scan_req.ssid, param->u.scan_req.ssid_len);
pItemSSID->len = param->u.scan_req.ssid_len;
spin_lock_irq(&pDevice->lock);
BSSvClearBSSList((void *) pDevice, pDevice->bLinkPass);
bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN,
pMgmt->abyDesireSSID);
spin_unlock_irq(&pDevice->lock);
return ret;
}
/*
* Description:
* get bssid
*
* Parameters:
* In:
* pDevice -
* param -
* Out:
*
* Return Value:
*
*/
static int wpa_get_bssid(PSDevice pDevice, struct viawget_wpa_param *param)
{
PSMgmtObject pMgmt = &pDevice->sMgmtObj;
int ret = 0;
memcpy(param->u.wpa_associate.bssid, pMgmt->abyCurrBSSID, 6);
return ret;
}
/*
* Description:
* get bssid
*
* Parameters:
* In:
* pDevice -
* param -
* Out:
*
* Return Value:
*
*/
static int wpa_get_ssid(PSDevice pDevice, struct viawget_wpa_param *param)
{
PSMgmtObject pMgmt = &pDevice->sMgmtObj;
PWLAN_IE_SSID pItemSSID;
int ret = 0;
pItemSSID = (PWLAN_IE_SSID)pMgmt->abyCurrSSID;
memcpy(param->u.wpa_associate.ssid, pItemSSID->abySSID, pItemSSID->len);
param->u.wpa_associate.ssid_len = pItemSSID->len;
return ret;
}
/*
* Description:
* get scan results
*
* Parameters:
* In:
* pDevice -
* param -
* Out:
*
* Return Value:
*
*/
static int wpa_get_scan(PSDevice pDevice, struct viawget_wpa_param *param)
{
struct viawget_scan_result *scan_buf;
PSMgmtObject pMgmt = &pDevice->sMgmtObj;
PWLAN_IE_SSID pItemSSID;
PKnownBSS pBSS;
PBYTE pBuf;
int ret = 0;
u16 count = 0;
u16 ii;
u16 jj;
long ldBm; //James //add
//******mike:bubble sort by stronger RSSI*****//
PBYTE ptempBSS;
ptempBSS = kmalloc(sizeof(KnownBSS), GFP_ATOMIC);
if (ptempBSS == NULL) {
printk("bubble sort kmalloc memory fail@@@\n");
ret = -ENOMEM;
return ret;
}
for (ii = 0; ii < MAX_BSS_NUM; ii++) {
for (jj = 0; jj < MAX_BSS_NUM - ii - 1; jj++) {
if ((pMgmt->sBSSList[jj].bActive != TRUE)
|| ((pMgmt->sBSSList[jj].uRSSI > pMgmt->sBSSList[jj + 1].uRSSI)
&& (pMgmt->sBSSList[jj + 1].bActive != FALSE))) {
memcpy(ptempBSS,&pMgmt->sBSSList[jj], sizeof(KnownBSS));
memcpy(&pMgmt->sBSSList[jj], &pMgmt->sBSSList[jj + 1],
sizeof(KnownBSS));
memcpy(&pMgmt->sBSSList[jj + 1], ptempBSS, sizeof(KnownBSS));
}
}
}
kfree(ptempBSS);
count = 0;
pBSS = &(pMgmt->sBSSList[0]);
for (ii = 0; ii < MAX_BSS_NUM; ii++) {
pBSS = &(pMgmt->sBSSList[ii]);
if (!pBSS->bActive)
continue;
count++;
}
pBuf = kcalloc(count, sizeof(struct viawget_scan_result), GFP_ATOMIC);
if (pBuf == NULL) {
ret = -ENOMEM;
return ret;
}
scan_buf = (struct viawget_scan_result *)pBuf;
pBSS = &(pMgmt->sBSSList[0]);
for (ii = 0, jj = 0; ii < MAX_BSS_NUM; ii++) {
pBSS = &(pMgmt->sBSSList[ii]);
if (pBSS->bActive) {
if (jj >= count)
break;
memcpy(scan_buf->bssid, pBSS->abyBSSID, WLAN_BSSID_LEN);
pItemSSID = (PWLAN_IE_SSID)pBSS->abySSID;
memcpy(scan_buf->ssid, pItemSSID->abySSID, pItemSSID->len);
scan_buf->ssid_len = pItemSSID->len;
scan_buf->freq = frequency_list[pBSS->uChannel-1];
scan_buf->caps = pBSS->wCapInfo; // DavidWang for sharemode
RFvRSSITodBm(pDevice, (BYTE)(pBSS->uRSSI), &ldBm);
if (-ldBm < 50)
scan_buf->qual = 100;
else if (-ldBm > 90)
scan_buf->qual = 0;
else
scan_buf->qual=(40-(-ldBm-50))*100/40;
//James
//scan_buf->caps = pBSS->wCapInfo;
//scan_buf->qual =
scan_buf->noise = 0;
scan_buf->level = ldBm;
//scan_buf->maxrate =
if (pBSS->wWPALen != 0) {
scan_buf->wpa_ie_len = pBSS->wWPALen;
memcpy(scan_buf->wpa_ie, pBSS->byWPAIE, pBSS->wWPALen);
}
if (pBSS->wRSNLen != 0) {
scan_buf->rsn_ie_len = pBSS->wRSNLen;
memcpy(scan_buf->rsn_ie, pBSS->byRSNIE, pBSS->wRSNLen);
}
scan_buf = (struct viawget_scan_result *)((PBYTE)scan_buf + sizeof(struct viawget_scan_result));
jj ++;
}
}
if (jj < count)
count = jj;
if (copy_to_user(param->u.scan_results.buf, pBuf, sizeof(struct viawget_scan_result) * count))
ret = -EFAULT;
param->u.scan_results.scan_count = count;
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " param->u.scan_results.scan_count = %d\n", count);
kfree(pBuf);
return ret;
}
/*
* Description:
* set associate with AP
*
* Parameters:
* In:
* pDevice -
* param -
* Out:
*
* Return Value:
*
*/
static int wpa_set_associate(PSDevice pDevice, struct viawget_wpa_param *param)
{
PSMgmtObject pMgmt = &pDevice->sMgmtObj;
PWLAN_IE_SSID pItemSSID;
BYTE abyNullAddr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
BYTE abyWPAIE[64];
int ret = 0;
BOOL bwepEnabled=FALSE;
// set key type & algorithm
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "pairwise_suite = %d\n", param->u.wpa_associate.pairwise_suite);
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "group_suite = %d\n", param->u.wpa_associate.group_suite);
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "key_mgmt_suite = %d\n", param->u.wpa_associate.key_mgmt_suite);
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "auth_alg = %d\n", param->u.wpa_associate.auth_alg);
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "mode = %d\n", param->u.wpa_associate.mode);
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ie_len = %d\n", param->u.wpa_associate.wpa_ie_len);
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Roaming dBm = %d\n", param->u.wpa_associate.roam_dbm); // Davidwang
if (param->u.wpa_associate.wpa_ie) {
if (param->u.wpa_associate.wpa_ie_len > sizeof(abyWPAIE))
return -EINVAL;
if (copy_from_user(&abyWPAIE[0], param->u.wpa_associate.wpa_ie,
param->u.wpa_associate.wpa_ie_len))
return -EFAULT;
}
if (param->u.wpa_associate.mode == 1)
pMgmt->eConfigMode = WMAC_CONFIG_IBSS_STA;
else
pMgmt->eConfigMode = WMAC_CONFIG_ESS_STA;
// set bssid
if (memcmp(param->u.wpa_associate.bssid, &abyNullAddr[0], 6) != 0)
memcpy(pMgmt->abyDesireBSSID, param->u.wpa_associate.bssid, 6);
// set ssid
memset(pMgmt->abyDesireSSID, 0, WLAN_IEHDR_LEN + WLAN_SSID_MAXLEN + 1);
pItemSSID = (PWLAN_IE_SSID)pMgmt->abyDesireSSID;
pItemSSID->byElementID = WLAN_EID_SSID;
pItemSSID->len = param->u.wpa_associate.ssid_len;
memcpy(pItemSSID->abySSID, param->u.wpa_associate.ssid, pItemSSID->len);
if (param->u.wpa_associate.wpa_ie_len == 0) {
if (param->u.wpa_associate.auth_alg & AUTH_ALG_SHARED_KEY)
pMgmt->eAuthenMode = WMAC_AUTH_SHAREKEY;
else
pMgmt->eAuthenMode = WMAC_AUTH_OPEN;
} else if (abyWPAIE[0] == RSN_INFO_ELEM) {
if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_PSK)
pMgmt->eAuthenMode = WMAC_AUTH_WPA2PSK;
else
pMgmt->eAuthenMode = WMAC_AUTH_WPA2;
} else {
if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_WPA_NONE)
pMgmt->eAuthenMode = WMAC_AUTH_WPANONE;
else if (param->u.wpa_associate.key_mgmt_suite == KEY_MGMT_PSK)
pMgmt->eAuthenMode = WMAC_AUTH_WPAPSK;
else
pMgmt->eAuthenMode = WMAC_AUTH_WPA;
}
switch (param->u.wpa_associate.pairwise_suite) {
case CIPHER_CCMP:
pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;
break;
case CIPHER_TKIP:
pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;
break;
case CIPHER_WEP40:
case CIPHER_WEP104:
pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
bwepEnabled = TRUE;
break;
case CIPHER_NONE:
if (param->u.wpa_associate.group_suite == CIPHER_CCMP)
pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled;
else
pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled;
break;
default:
pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
}
pMgmt->Roam_dbm = param->u.wpa_associate.roam_dbm;
if (pMgmt->eAuthenMode == WMAC_AUTH_SHAREKEY) { // @wep-sharekey
pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
pMgmt->bShareKeyAlgorithm = TRUE;
} else if (pMgmt->eAuthenMode == WMAC_AUTH_OPEN) {
if(bwepEnabled==TRUE) { //@open-wep
pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled;
} else {
// @only open
pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled;
}
}
// mike save old encryption status
pDevice->eOldEncryptionStatus = pDevice->eEncryptionStatus;
if (pDevice->eEncryptionStatus != Ndis802_11EncryptionDisabled)
pDevice->bEncryptionEnable = TRUE;
else
pDevice->bEncryptionEnable = FALSE;
if ((pMgmt->eAuthenMode == WMAC_AUTH_SHAREKEY) ||
((pMgmt->eAuthenMode == WMAC_AUTH_OPEN) && (bwepEnabled==TRUE))) {
// mike re-comment:open-wep && sharekey-wep needn't do initial key!!
} else {
KeyvInitTable(pDevice,&pDevice->sKey);
}
spin_lock_irq(&pDevice->lock);
pDevice->bLinkPass = FALSE;
ControlvMaskByte(pDevice, MESSAGE_REQUEST_MACREG, MAC_REG_PAPEDELAY, LEDSTS_STS, LEDSTS_SLOW);
memset(pMgmt->abyCurrBSSID, 0, 6);
pMgmt->eCurrState = WMAC_STATE_IDLE;
netif_stop_queue(pDevice->dev);
/******* search if ap_scan=2, which is associating request in hidden ssid mode ****/
{
PKnownBSS pCurr = NULL;
pCurr = BSSpSearchBSSList(pDevice,
pMgmt->abyDesireBSSID,
pMgmt->abyDesireSSID,
pDevice->eConfigPHYMode
);
if (pCurr == NULL){
printk("wpa_set_associate---->hidden mode site survey before associate.......\n");
bScheduleCommand((void *)pDevice,
WLAN_CMD_BSSID_SCAN,
pMgmt->abyDesireSSID);
}
}
/****************************************************************/
bScheduleCommand((void *)pDevice, WLAN_CMD_SSID, NULL);
spin_unlock_irq(&pDevice->lock);
return ret;
}
/*
* Description:
* wpa_ioctl main function supported for wpa supplicant
*
* Parameters:
* In:
* pDevice -
* iw_point -
* Out:
*
* Return Value:
*
*/
int wpa_ioctl(PSDevice pDevice, struct iw_point *p)
{
struct viawget_wpa_param *param;
int ret = 0;
int wpa_ioctl = 0;
if (p->length < sizeof(struct viawget_wpa_param) ||
p->length > VIAWGET_WPA_MAX_BUF_SIZE || !p->pointer)
return -EINVAL;
param = kmalloc((int)p->length, GFP_KERNEL);
if (param == NULL)
return -ENOMEM;
if (copy_from_user(param, p->pointer, p->length)) {
ret = -EFAULT;
goto out;
}
switch (param->cmd) {
case VIAWGET_SET_WPA:
ret = wpa_set_wpa(pDevice, param);
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_WPA \n");
break;
case VIAWGET_SET_KEY:
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_KEY \n");
spin_lock_irq(&pDevice->lock);
ret = wpa_set_keys(pDevice, param, FALSE);
spin_unlock_irq(&pDevice->lock);
break;
case VIAWGET_SET_SCAN:
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_SCAN \n");
ret = wpa_set_scan(pDevice, param);
break;
case VIAWGET_GET_SCAN:
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_SCAN\n");
ret = wpa_get_scan(pDevice, param);
wpa_ioctl = 1;
break;
case VIAWGET_GET_SSID:
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_SSID \n");
ret = wpa_get_ssid(pDevice, param);
wpa_ioctl = 1;
break;
case VIAWGET_GET_BSSID:
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_GET_BSSID \n");
ret = wpa_get_bssid(pDevice, param);
wpa_ioctl = 1;
break;
case VIAWGET_SET_ASSOCIATE:
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_ASSOCIATE \n");
ret = wpa_set_associate(pDevice, param);
break;
case VIAWGET_SET_DISASSOCIATE:
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DISASSOCIATE \n");
ret = wpa_set_disassociate(pDevice, param);
break;
case VIAWGET_SET_DROP_UNENCRYPT:
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DROP_UNENCRYPT \n");
break;
case VIAWGET_SET_DEAUTHENTICATE:
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_SET_DEAUTHENTICATE \n");
break;
default:
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "wpa_ioctl: unknown cmd=%d\n",
param->cmd);
kfree(param);
return -EOPNOTSUPP;
}
if ((ret == 0) && wpa_ioctl) {
if (copy_to_user(p->pointer, param, p->length)) {
ret = -EFAULT;
goto out;
}
}
out:
kfree(param);
return ret;
}