diff options
Diffstat (limited to 'drivers/staging/vt6655/hostap.c')
-rw-r--r-- | drivers/staging/vt6655/hostap.c | 907 |
1 files changed, 907 insertions, 0 deletions
diff --git a/drivers/staging/vt6655/hostap.c b/drivers/staging/vt6655/hostap.c new file mode 100644 index 000000000000..134de869cb80 --- /dev/null +++ b/drivers/staging/vt6655/hostap.c @@ -0,0 +1,907 @@ +/* + * 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: hostap.c + * + * Purpose: handle hostap deamon ioctl input/out functions + * + * Author: Lyndon Chen + * + * Date: Oct. 20, 2003 + * + * Functions: + * + * Revision History: + * + */ + + +#if !defined(__HOSTAP_H__) +#include "hostap.h" +#endif +#if !defined(__IOCMD_H__) +#include "iocmd.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif +#if !defined(__CARD_H__) +#include "card.h" +#endif +#if !defined(__BASEBAND_H__) +#include "baseband.h" +#endif +#if !defined(__WPACTL_H__) +#include "wpactl.h" +#endif +#if !defined(__KEY_H__) +#include "key.h" +#endif +#if !defined(__MAC_H__) +#include "mac.h" +#endif + + +#define VIAWGET_HOSTAPD_MAX_BUF_SIZE 1024 +#define HOSTAP_CRYPT_FLAG_SET_TX_KEY BIT0 +#define HOSTAP_CRYPT_FLAG_PERMANENT BIT1 +#define HOSTAP_CRYPT_ERR_UNKNOWN_ALG 2 +#define HOSTAP_CRYPT_ERR_UNKNOWN_ADDR 3 +#define HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED 4 +#define HOSTAP_CRYPT_ERR_KEY_SET_FAILED 5 +#define HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED 6 +#define HOSTAP_CRYPT_ERR_CARD_CONF_FAILED 7 + + +/*--------------------- Static Definitions -------------------------*/ + +/*--------------------- Static Classes ----------------------------*/ + +/*--------------------- Static Variables --------------------------*/ +//static int msglevel =MSG_LEVEL_DEBUG; +static int msglevel =MSG_LEVEL_INFO; + +/*--------------------- Static Functions --------------------------*/ + + + + +/*--------------------- Export Variables --------------------------*/ + + +/* + * Description: + * register net_device (AP) for hostap deamon + * + * Parameters: + * In: + * pDevice - + * rtnl_locked - + * Out: + * + * Return Value: + * + */ + +static int hostap_enable_hostapd(PSDevice pDevice, int rtnl_locked) +{ + struct net_device *dev = pDevice->dev; + int ret; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Enabling hostapd mode\n", dev->name); + +#ifdef PRIVATE_OBJ + pDevice->apdev = ref_init_apdev(dev); + + if (pDevice->apdev == NULL) + return -ENOMEM; + + if (rtnl_locked) + ret = register_netdevice(pDevice->apdev); + else + ret = register_netdev(pDevice->apdev); + if (ret) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: register_netdevice(AP) failed!\n", + dev->name); + return -1; + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Registered netdevice %s for AP management\n", + dev->name, pDevice->apdev->name); + +#else + pDevice->apdev = (struct net_device *)kmalloc(sizeof(struct net_device), GFP_KERNEL); + if (pDevice->apdev == NULL) + return -ENOMEM; + memset(pDevice->apdev, 0, sizeof(struct net_device)); + + pDevice->apdev->priv = pDevice; + memcpy(pDevice->apdev->dev_addr, dev->dev_addr, ETH_ALEN); + pDevice->apdev->hard_start_xmit = pDevice->tx_80211; + pDevice->apdev->type = ARPHRD_IEEE80211; + + pDevice->apdev->base_addr = dev->base_addr; + pDevice->apdev->irq = dev->irq; + pDevice->apdev->mem_start = dev->mem_start; + pDevice->apdev->mem_end = dev->mem_end; + sprintf(pDevice->apdev->name, "%sap", dev->name); + if (rtnl_locked) + ret = register_netdevice(pDevice->apdev); + else + ret = register_netdev(pDevice->apdev); + if (ret) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: register_netdevice(AP) failed!\n", + dev->name); + return -1; + } + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Registered netdevice %s for AP management\n", + dev->name, pDevice->apdev->name); + + KeyvInitTable(&pDevice->sKey, pDevice->PortOffset); +#endif + + return 0; +} + +/* + * Description: + * unregister net_device(AP) + * + * Parameters: + * In: + * pDevice - + * rtnl_locked - + * Out: + * + * Return Value: + * + */ + +static int hostap_disable_hostapd(PSDevice pDevice, int rtnl_locked) +{ + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: disabling hostapd mode\n", pDevice->dev->name); + + if (pDevice->apdev && pDevice->apdev->name && pDevice->apdev->name[0]) { + if (rtnl_locked) + unregister_netdevice(pDevice->apdev); + else + unregister_netdev(pDevice->apdev); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Netdevice %s unregistered\n", + pDevice->dev->name, pDevice->apdev->name); + } + kfree(pDevice->apdev); + pDevice->apdev = NULL; + pDevice->bEnable8021x = FALSE; + pDevice->bEnableHostWEP = FALSE; + pDevice->bEncryptionEnable = FALSE; + +//4.2007-0118-03,<Add> by EinsnLiu +//execute some clear work +pDevice->pMgmt->byCSSPK=KEY_CTL_NONE; +pDevice->pMgmt->byCSSGK=KEY_CTL_NONE; +KeyvInitTable(&pDevice->sKey,pDevice->PortOffset); + + return 0; +} + + +/* + * Description: + * Set enable/disable hostapd mode + * + * Parameters: + * In: + * pDevice - + * rtnl_locked - + * Out: + * + * Return Value: + * + */ + +int hostap_set_hostapd(PSDevice pDevice, int val, int rtnl_locked) +{ + if (val < 0 || val > 1) + return -EINVAL; + + if (pDevice->bEnableHostapd == val) + return 0; + + pDevice->bEnableHostapd = val; + + if (val) + return hostap_enable_hostapd(pDevice, rtnl_locked); + else + return hostap_disable_hostapd(pDevice, rtnl_locked); +} + + +/* + * Description: + * remove station function supported for hostap deamon + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ +static int hostap_remove_sta(PSDevice pDevice, + struct viawget_hostapd_param *param) +{ + UINT uNodeIndex; + + + if (BSSDBbIsSTAInNodeDB(pDevice->pMgmt, param->sta_addr, &uNodeIndex)) { + BSSvRemoveOneNode(pDevice, uNodeIndex); + } + else { + return -ENOENT; + } + return 0; +} + +/* + * Description: + * add a station from hostap deamon + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ +static int hostap_add_sta(PSDevice pDevice, + struct viawget_hostapd_param *param) +{ + PSMgmtObject pMgmt = pDevice->pMgmt; + UINT uNodeIndex; + + + if (!BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &uNodeIndex)) { + BSSvCreateOneNode((PSDevice)pDevice, &uNodeIndex); + } + memcpy(pMgmt->sNodeDBTable[uNodeIndex].abyMACAddr, param->sta_addr, WLAN_ADDR_LEN); + pMgmt->sNodeDBTable[uNodeIndex].eNodeState = NODE_ASSOC; + pMgmt->sNodeDBTable[uNodeIndex].wCapInfo = param->u.add_sta.capability; +// TODO listenInterval +// pMgmt->sNodeDBTable[uNodeIndex].wListenInterval = 1; + pMgmt->sNodeDBTable[uNodeIndex].bPSEnable = FALSE; + pMgmt->sNodeDBTable[uNodeIndex].bySuppRate = param->u.add_sta.tx_supp_rates; + + // set max tx rate + pMgmt->sNodeDBTable[uNodeIndex].wTxDataRate = + pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate; + // set max basic rate + pMgmt->sNodeDBTable[uNodeIndex].wMaxBasicRate = RATE_2M; + // Todo: check sta preamble, if ap can't support, set status code + pMgmt->sNodeDBTable[uNodeIndex].bShortPreamble = + WLAN_GET_CAP_INFO_SHORTPREAMBLE(pMgmt->sNodeDBTable[uNodeIndex].wCapInfo); + + pMgmt->sNodeDBTable[uNodeIndex].wAID = (WORD)param->u.add_sta.aid; +#ifdef PRIVATE_OBJ + pMgmt->sNodeDBTable[uNodeIndex].ulLastRxJiffer = get_jiffies(); +#else + pMgmt->sNodeDBTable[uNodeIndex].ulLastRxJiffer = jiffies; +#endif + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Add STA AID= %d \n", pMgmt->sNodeDBTable[uNodeIndex].wAID); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "MAC=%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X \n", + param->sta_addr[0], + param->sta_addr[1], + param->sta_addr[2], + param->sta_addr[3], + param->sta_addr[4], + param->sta_addr[5] + ) ; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Max Support rate = %d \n", + pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate); + + return 0; +} + +/* + * Description: + * get station info + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ + +static int hostap_get_info_sta(PSDevice pDevice, + struct viawget_hostapd_param *param) +{ + PSMgmtObject pMgmt = pDevice->pMgmt; + UINT uNodeIndex; + + if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &uNodeIndex)) { +#ifdef PRIVATE_OBJ + param->u.get_info_sta.inactive_sec = + (get_jiffies() - pMgmt->sNodeDBTable[uNodeIndex].ulLastRxJiffer) / HZ; +#else + param->u.get_info_sta.inactive_sec = + (jiffies - pMgmt->sNodeDBTable[uNodeIndex].ulLastRxJiffer) / HZ; +#endif + //param->u.get_info_sta.txexc = pMgmt->sNodeDBTable[uNodeIndex].uTxAttempts; + } + else { + return -ENOENT; + } + + return 0; +} + +/* + * Description: + * reset txexec + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * TURE, FALSE + * + * Return Value: + * + */ +/* +static int hostap_reset_txexc_sta(PSDevice pDevice, + struct viawget_hostapd_param *param) +{ + PSMgmtObject pMgmt = pDevice->pMgmt; + UINT uNodeIndex; + + if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &uNodeIndex)) { + pMgmt->sNodeDBTable[uNodeIndex].uTxAttempts = 0; + } + else { + return -ENOENT; + } + + return 0; +} +*/ + +/* + * Description: + * set station flag + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ +static int hostap_set_flags_sta(PSDevice pDevice, + struct viawget_hostapd_param *param) +{ + PSMgmtObject pMgmt = pDevice->pMgmt; + UINT uNodeIndex; + + if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &uNodeIndex)) { + pMgmt->sNodeDBTable[uNodeIndex].dwFlags |= param->u.set_flags_sta.flags_or; + pMgmt->sNodeDBTable[uNodeIndex].dwFlags &= param->u.set_flags_sta.flags_and; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " dwFlags = %x \n", + (UINT)pMgmt->sNodeDBTable[uNodeIndex].dwFlags); + } + else { + return -ENOENT; + } + + return 0; +} + + + +/* + * Description: + * set generic element (wpa ie) + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ +static int hostap_set_generic_element(PSDevice pDevice, + struct viawget_hostapd_param *param) +{ + PSMgmtObject pMgmt = pDevice->pMgmt; + + + + memcpy( pMgmt->abyWPAIE, + param->u.generic_elem.data, + param->u.generic_elem.len + ); + + pMgmt->wWPAIELen = param->u.generic_elem.len; + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pMgmt->wWPAIELen = %d\n", pMgmt->wWPAIELen); + + // disable wpa + if (pMgmt->wWPAIELen == 0) { + pMgmt->eAuthenMode = WMAC_AUTH_OPEN; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " No WPAIE, Disable WPA \n"); + } else { + // enable wpa + if ((pMgmt->abyWPAIE[0] == WLAN_EID_RSN_WPA) || + (pMgmt->abyWPAIE[0] == WLAN_EID_RSN)) { + pMgmt->eAuthenMode = WMAC_AUTH_WPANONE; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Set WPAIE enable WPA\n"); + } else + return -EINVAL; + } + + return 0; +} + +/* + * Description: + * flush station nodes table. + * + * Parameters: + * In: + * pDevice - + * Out: + * + * Return Value: + * + */ + +static void hostap_flush_sta(PSDevice pDevice) +{ + // reserved node index =0 for multicast node. + BSSvClearNodeDBTable(pDevice, 1); + pDevice->uAssocCount = 0; + + return; +} + +/* + * Description: + * set each stations encryption key + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ +static int hostap_set_encryption(PSDevice pDevice, + struct viawget_hostapd_param *param, + int param_len) +{ + PSMgmtObject pMgmt = pDevice->pMgmt; + DWORD dwKeyIndex = 0; + BYTE abyKey[MAX_KEY_LEN]; + BYTE abySeq[MAX_KEY_LEN]; + NDIS_802_11_KEY_RSC KeyRSC; + BYTE byKeyDecMode = KEY_CTL_WEP; + int ret = 0; + int iNodeIndex = -1; + int ii; + BOOL bKeyTableFull = FALSE; + WORD wKeyCtl = 0; + + + param->u.crypt.err = 0; +/* + if (param_len != + (int) ((char *) param->u.crypt.key - (char *) param) + + param->u.crypt.key_len) + return -EINVAL; +*/ + + if (param->u.crypt.alg > WPA_ALG_CCMP) + return -EINVAL; + + + if ((param->u.crypt.idx > 3) || (param->u.crypt.key_len > MAX_KEY_LEN)) { + param->u.crypt.err = HOSTAP_CRYPT_ERR_KEY_SET_FAILED; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " HOSTAP_CRYPT_ERR_KEY_SET_FAILED\n"); + return -EINVAL; + } + + if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && + param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && + param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { + if (param->u.crypt.idx >= MAX_GROUP_KEY) + return -EINVAL; + iNodeIndex = 0; + + } else { + if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &iNodeIndex) == FALSE) { + param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " HOSTAP_CRYPT_ERR_UNKNOWN_ADDR\n"); + return -EINVAL; + } + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " hostap_set_encryption: sta_index %d \n", iNodeIndex); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " hostap_set_encryption: alg %d \n", param->u.crypt.alg); + + if (param->u.crypt.alg == WPA_ALG_NONE) { + + if (pMgmt->sNodeDBTable[iNodeIndex].bOnFly == TRUE) { + if (KeybRemoveKey(&(pDevice->sKey), + param->sta_addr, + pMgmt->sNodeDBTable[iNodeIndex].dwKeyIndex, + pDevice->PortOffset) == FALSE) { + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "KeybRemoveKey fail \n"); + } + pMgmt->sNodeDBTable[iNodeIndex].bOnFly = FALSE; + } + pMgmt->sNodeDBTable[iNodeIndex].byKeyIndex = 0; + pMgmt->sNodeDBTable[iNodeIndex].dwKeyIndex = 0; + pMgmt->sNodeDBTable[iNodeIndex].uWepKeyLength = 0; + pMgmt->sNodeDBTable[iNodeIndex].KeyRSC = 0; + pMgmt->sNodeDBTable[iNodeIndex].dwTSC47_16 = 0; + pMgmt->sNodeDBTable[iNodeIndex].wTSC15_0 = 0; + pMgmt->sNodeDBTable[iNodeIndex].byCipherSuite = 0; + memset(&pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[0], + 0, + MAX_KEY_LEN + ); + + return ret; + } + + memcpy(abyKey, param->u.crypt.key, param->u.crypt.key_len); + // copy to node key tbl + pMgmt->sNodeDBTable[iNodeIndex].byKeyIndex = param->u.crypt.idx; + pMgmt->sNodeDBTable[iNodeIndex].uWepKeyLength = param->u.crypt.key_len; + memcpy(&pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[0], + param->u.crypt.key, + param->u.crypt.key_len + ); + + dwKeyIndex = (DWORD)(param->u.crypt.idx); + if (param->u.crypt.flags & HOSTAP_CRYPT_FLAG_SET_TX_KEY) { + pDevice->byKeyIndex = (BYTE)dwKeyIndex; + pDevice->bTransmitKey = TRUE; + dwKeyIndex |= (1 << 31); + } + + if (param->u.crypt.alg == WPA_ALG_WEP) { + + if ((pDevice->bEnable8021x == FALSE) || (iNodeIndex == 0)) { + KeybSetDefaultKey(&(pDevice->sKey), + dwKeyIndex & ~(BIT30 | USE_KEYRSC), + param->u.crypt.key_len, + NULL, + abyKey, + KEY_CTL_WEP, + pDevice->PortOffset, + pDevice->byLocalID); + + } else { + // 8021x enable, individual key + dwKeyIndex |= (1 << 30); // set pairwise key + if (KeybSetKey(&(pDevice->sKey), + ¶m->sta_addr[0], + dwKeyIndex & ~(USE_KEYRSC), + param->u.crypt.key_len, + (PQWORD) &(KeyRSC), + (PBYTE)abyKey, + KEY_CTL_WEP, + pDevice->PortOffset, + pDevice->byLocalID) == TRUE) { + + pMgmt->sNodeDBTable[iNodeIndex].bOnFly = TRUE; + + } else { + // Key Table Full + pMgmt->sNodeDBTable[iNodeIndex].bOnFly = FALSE; + bKeyTableFull = TRUE; + } + } + pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; + pDevice->bEncryptionEnable = TRUE; + pMgmt->byCSSPK = KEY_CTL_WEP; + pMgmt->byCSSGK = KEY_CTL_WEP; + pMgmt->sNodeDBTable[iNodeIndex].byCipherSuite = KEY_CTL_WEP; + pMgmt->sNodeDBTable[iNodeIndex].dwKeyIndex = dwKeyIndex; + return ret; + } + + if (param->u.crypt.seq) { + memcpy(&abySeq, param->u.crypt.seq, 8); + for (ii = 0 ; ii < 8 ; ii++) { + KeyRSC |= (abySeq[ii] << (ii * 8)); + } + dwKeyIndex |= 1 << 29; + pMgmt->sNodeDBTable[iNodeIndex].KeyRSC = KeyRSC; + } + + if (param->u.crypt.alg == WPA_ALG_TKIP) { + if (param->u.crypt.key_len != MAX_KEY_LEN) + return -EINVAL; + pDevice->eEncryptionStatus = Ndis802_11Encryption2Enabled; + byKeyDecMode = KEY_CTL_TKIP; + pMgmt->byCSSPK = KEY_CTL_TKIP; + pMgmt->byCSSGK = KEY_CTL_TKIP; + } + + if (param->u.crypt.alg == WPA_ALG_CCMP) { + if ((param->u.crypt.key_len != AES_KEY_LEN) || + (pDevice->byLocalID <= REV_ID_VT3253_A1)) + return -EINVAL; + pDevice->eEncryptionStatus = Ndis802_11Encryption3Enabled; + byKeyDecMode = KEY_CTL_CCMP; + pMgmt->byCSSPK = KEY_CTL_CCMP; + pMgmt->byCSSGK = KEY_CTL_CCMP; + } + + + if (iNodeIndex == 0) { + KeybSetDefaultKey(&(pDevice->sKey), + dwKeyIndex, + param->u.crypt.key_len, + (PQWORD) &(KeyRSC), + abyKey, + byKeyDecMode, + pDevice->PortOffset, + pDevice->byLocalID); + pMgmt->sNodeDBTable[iNodeIndex].bOnFly = TRUE; + + } else { + dwKeyIndex |= (1 << 30); // set pairwise key + if (KeybSetKey(&(pDevice->sKey), + ¶m->sta_addr[0], + dwKeyIndex, + param->u.crypt.key_len, + (PQWORD) &(KeyRSC), + (PBYTE)abyKey, + byKeyDecMode, + pDevice->PortOffset, + pDevice->byLocalID) == TRUE) { + + pMgmt->sNodeDBTable[iNodeIndex].bOnFly = TRUE; + + } else { + // Key Table Full + pMgmt->sNodeDBTable[iNodeIndex].bOnFly = FALSE; + bKeyTableFull = TRUE; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Key Table Full\n"); + } + + } + + if (bKeyTableFull == TRUE) { + wKeyCtl &= 0x7F00; // clear all key control filed + wKeyCtl |= (byKeyDecMode << 4); + wKeyCtl |= (byKeyDecMode); + wKeyCtl |= 0x0044; // use group key for all address + wKeyCtl |= 0x4000; // disable KeyTable[MAX_KEY_TABLE-1] on-fly to genernate rx int + MACvSetDefaultKeyCtl(pDevice->PortOffset, wKeyCtl, MAX_KEY_TABLE-1, pDevice->byLocalID); + } + + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Set key sta_index= %d \n", iNodeIndex); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " tx_index=%d len=%d \n", param->u.crypt.idx, + param->u.crypt.key_len ); + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO " key=%x-%x-%x-%x-%x-xxxxx \n", + pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[0], + pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[1], + pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[2], + pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[3], + pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[4] + ); + + // set wep key + pDevice->bEncryptionEnable = TRUE; + pMgmt->sNodeDBTable[iNodeIndex].byCipherSuite = byKeyDecMode; + pMgmt->sNodeDBTable[iNodeIndex].dwKeyIndex = dwKeyIndex; + pMgmt->sNodeDBTable[iNodeIndex].dwTSC47_16 = 0; + pMgmt->sNodeDBTable[iNodeIndex].wTSC15_0 = 0; + + return ret; +} + + + +/* + * Description: + * get each stations encryption key + * + * Parameters: + * In: + * pDevice - + * param - + * Out: + * + * Return Value: + * + */ +static int hostap_get_encryption(PSDevice pDevice, + struct viawget_hostapd_param *param, + int param_len) +{ + PSMgmtObject pMgmt = pDevice->pMgmt; + int ret = 0; + int ii; + int iNodeIndex =0; + + + param->u.crypt.err = 0; + + if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && + param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && + param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { + iNodeIndex = 0; + } else { + if (BSSDBbIsSTAInNodeDB(pMgmt, param->sta_addr, &iNodeIndex) == FALSE) { + param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR; + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "hostap_get_encryption: HOSTAP_CRYPT_ERR_UNKNOWN_ADDR\n"); + return -EINVAL; + } + } + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "hostap_get_encryption: %d\n", iNodeIndex); + memset(param->u.crypt.seq, 0, 8); + for (ii = 0 ; ii < 8 ; ii++) { + param->u.crypt.seq[ii] = (BYTE)pMgmt->sNodeDBTable[iNodeIndex].KeyRSC >> (ii * 8); + } + + return ret; +} + + +/* + * Description: + * hostap_ioctl main function supported for hostap deamon. + * + * Parameters: + * In: + * pDevice - + * iw_point - + * Out: + * + * Return Value: + * + */ + +int hostap_ioctl(PSDevice pDevice, struct iw_point *p) +{ + struct viawget_hostapd_param *param; + int ret = 0; + int ap_ioctl = 0; + + if (p->length < sizeof(struct viawget_hostapd_param) || + p->length > VIAWGET_HOSTAPD_MAX_BUF_SIZE || !p->pointer) + return -EINVAL; + + param = (struct viawget_hostapd_param *) kmalloc((int)p->length, (int)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_HOSTAPD_SET_ENCRYPTION: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SET_ENCRYPTION \n"); + spin_lock_irq(&pDevice->lock); + ret = hostap_set_encryption(pDevice, param, p->length); + spin_unlock_irq(&pDevice->lock); + break; + case VIAWGET_HOSTAPD_GET_ENCRYPTION: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_GET_ENCRYPTION \n"); + spin_lock_irq(&pDevice->lock); + ret = hostap_get_encryption(pDevice, param, p->length); + spin_unlock_irq(&pDevice->lock); + break; + case VIAWGET_HOSTAPD_SET_ASSOC_AP_ADDR: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SET_ASSOC_AP_ADDR \n"); + return -EOPNOTSUPP; + break; + case VIAWGET_HOSTAPD_FLUSH: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_FLUSH \n"); + spin_lock_irq(&pDevice->lock); + hostap_flush_sta(pDevice); + spin_unlock_irq(&pDevice->lock); + break; + case VIAWGET_HOSTAPD_ADD_STA: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_ADD_STA \n"); + spin_lock_irq(&pDevice->lock); + ret = hostap_add_sta(pDevice, param); + spin_unlock_irq(&pDevice->lock); + break; + case VIAWGET_HOSTAPD_REMOVE_STA: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_REMOVE_STA \n"); + spin_lock_irq(&pDevice->lock); + ret = hostap_remove_sta(pDevice, param); + spin_unlock_irq(&pDevice->lock); + break; + case VIAWGET_HOSTAPD_GET_INFO_STA: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_GET_INFO_STA \n"); + ret = hostap_get_info_sta(pDevice, param); + ap_ioctl = 1; + break; +/* + case VIAWGET_HOSTAPD_RESET_TXEXC_STA: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_RESET_TXEXC_STA \n"); + ret = hostap_reset_txexc_sta(pDevice, param); + break; +*/ + case VIAWGET_HOSTAPD_SET_FLAGS_STA: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SET_FLAGS_STA \n"); + ret = hostap_set_flags_sta(pDevice, param); + break; + + case VIAWGET_HOSTAPD_MLME: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_MLME \n"); + return -EOPNOTSUPP; + + case VIAWGET_HOSTAPD_SET_GENERIC_ELEMENT: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SET_GENERIC_ELEMENT \n"); + ret = hostap_set_generic_element(pDevice, param); + break; + + case VIAWGET_HOSTAPD_SCAN_REQ: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_SCAN_REQ \n"); + return -EOPNOTSUPP; + + case VIAWGET_HOSTAPD_STA_CLEAR_STATS: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "VIAWGET_HOSTAPD_STA_CLEAR_STATS \n"); + return -EOPNOTSUPP; + + default: + DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "hostap_ioctl: unknown cmd=%d\n", + (int)param->cmd); + return -EOPNOTSUPP; + break; + } + + + if ((ret == 0) && ap_ioctl) { + if (copy_to_user(p->pointer, param, p->length)) { + ret = -EFAULT; + goto out; + } + } + + out: + if (param != NULL) + kfree(param); + + return ret; +} + |