/* * 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: Oct. 20, 2003 * * 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 "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_DEBUG; 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); else 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->pMgmt; unsigned long dwKeyIndex = 0; unsigned char abyKey[MAX_KEY_LEN]; unsigned char abySeq[MAX_KEY_LEN]; QWORD KeyRSC; // NDIS_802_11_KEY_RSC KeyRSC; unsigned char byKeyDecMode = KEY_CTL_WEP; int ret = 0; int uu, ii; if (param->u.wpa_key.alg_name > WPA_ALG_CCMP || param->u.wpa_key.key_len >= MAX_KEY_LEN || param->u.wpa_key.seq_len >= MAX_KEY_LEN) 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; KeyvRemoveAllWEPKey(&(pDevice->sKey), pDevice->PortOffset); for (uu=0; uu<MAX_KEY_TABLE; uu++) { MACvDisableKeyEntry(pDevice->PortOffset, uu); } return ret; } //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 { spin_unlock_irq(&pDevice->lock); 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 = (unsigned long)(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 = (unsigned char)dwKeyIndex; pDevice->bTransmitKey = true; dwKeyIndex |= (1 << 31); } KeybSetDefaultKey(&(pDevice->sKey), dwKeyIndex & ~(BIT30 | USE_KEYRSC), param->u.wpa_key.key_len, NULL, abyKey, KEY_CTL_WEP, pDevice->PortOffset, pDevice->byLocalID); } pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; pDevice->bEncryptionEnable = true; return ret; } //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 { spin_unlock_irq(&pDevice->lock); 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)); //KeyRSC |= (abySeq[ii] << (ii * 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_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - TKIP Key must be 256 bits\n")); 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_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA - AES Key must be 128 bits\n")); return -EINVAL; } // spin_lock_irq(&pDevice->lock); if (is_broadcast_ether_addr(¶m->addr[0]) || (param->addr == NULL)) { // If is_broadcast_ether_addr, set the key as every key entry's group key. DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Groupe Key Assign.\n"); if ((KeybSetAllGroupKey(&(pDevice->sKey), dwKeyIndex, param->u.wpa_key.key_len, (PQWORD) &(KeyRSC), (unsigned char *)abyKey, byKeyDecMode, pDevice->PortOffset, pDevice->byLocalID) == true) && (KeybSetDefaultKey(&(pDevice->sKey), dwKeyIndex, param->u.wpa_key.key_len, (PQWORD) &(KeyRSC), (unsigned char *)abyKey, byKeyDecMode, pDevice->PortOffset, pDevice->byLocalID) == true) ) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "GROUP Key Assign.\n"); } else { //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA -KeybSetDefaultKey Fail.0\n")); // spin_unlock_irq(&pDevice->lock); 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"); //spin_unlock_irq(&pDevice->lock); 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")); //spin_unlock_irq(&pDevice->lock); return -EINVAL; } if (KeybSetKey(&(pDevice->sKey), ¶m->addr[0], dwKeyIndex, param->u.wpa_key.key_len, (PQWORD) &(KeyRSC), (unsigned char *)abyKey, byKeyDecMode, pDevice->PortOffset, pDevice->byLocalID) == true) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Set\n"); } else { // Key Table Full if (!compare_ether_addr(¶m->addr[0], pDevice->abyBSSID)) { //DBG_PRN_WLAN03(("return NDIS_STATUS_INVALID_DATA -Key Table Full.2\n")); //spin_unlock_irq(&pDevice->lock); return -EINVAL; } else { // Save Key and configure just before associate/reassociate to BSSID // we do not implement now //spin_unlock_irq(&pDevice->lock); return -EINVAL; } } } // BSSID not 0xffffffffffff if ((ret == 0) && ((param->u.wpa_key.set_tx) != 0)) { pDevice->byKeyIndex = (unsigned char)param->u.wpa_key.key_index; pDevice->bTransmitKey = true; } pDevice->bEncryptionEnable = true; //spin_unlock_irq(&pDevice->lock); /* DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " key=%x-%x-%x-%x-%x-xxxxx \n", pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][0], pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][1], pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][2], pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][3], pMgmt->sNodeDBTable[iNodeIndex].abyWepKey[byKeyIndex][4] ); */ 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->pMgmt; 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->pMgmt; 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; spin_lock_irq(&pDevice->lock); BSSvClearBSSList((void *)pDevice, pDevice->bLinkPass); bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, NULL); 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->pMgmt; 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->pMgmt; 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->pMgmt; PWLAN_IE_SSID pItemSSID; PKnownBSS pBSS; unsigned char *pBuf; int ret = 0; u16 count = 0; u16 ii, jj; #if 1 unsigned char *ptempBSS; ptempBSS = kmalloc(sizeof(KnownBSS), (int)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); // printk("bubble sort result:\n"); //for (ii = 0; ii < MAX_BSS_NUM; ii++) // printk("%d [%s]:RSSI=%d\n",ii,((PWLAN_IE_SSID)(pMgmt->sBSSList[ii].abySSID))->abySSID, // pMgmt->sBSSList[ii].uRSSI); #endif //******mike:bubble sort by stronger RSSI*****// 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), (int)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; //scan_buf->caps = pBSS->wCapInfo; //scan_buf->qual = //scan_buf->noise = //scan_buf->level = //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 *)((unsigned char *)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->pMgmt; PWLAN_IE_SSID pItemSSID; unsigned char abyNullAddr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; unsigned char 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); if (param->u.wpa_associate.wpa_ie_len) { if (!param->u.wpa_associate.wpa_ie) return -EINVAL; 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 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); // set bssid if (memcmp(param->u.wpa_associate.bssid, &abyNullAddr[0], 6) != 0) memcpy(pMgmt->abyDesireBSSID, param->u.wpa_associate.bssid, 6); else { bScheduleCommand((void *) pDevice, WLAN_CMD_BSSID_SCAN, pItemSSID->abySSID); } 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; } //DavidWang add for WPA_supplicant support open/share mode if (pMgmt->eAuthenMode == WMAC_AUTH_SHAREKEY) { pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; //pMgmt->eAuthenMode = WMAC_AUTH_SHAREKEY; pMgmt->bShareKeyAlgorithm = true; } else if (pMgmt->eAuthenMode == WMAC_AUTH_OPEN) { if(!bWepEnabled) pDevice->eEncryptionStatus = Ndis802_11EncryptionDisabled; else pDevice->eEncryptionStatus = Ndis802_11Encryption1Enabled; //pMgmt->eAuthenMode = WMAC_AUTH_OPEN; //pMgmt->bShareKeyAlgorithm = false; //20080717-06,<Modify> by chester//Fix Open mode, WEP encrytion } //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))) ) //DavidWang //20080717-06,<Modify> by chester//Not to initial WEP KeyvInitTable(&pDevice->sKey, pDevice->PortOffset); spin_lock_irq(&pDevice->lock); pDevice->bLinkPass = false; memset(pMgmt->abyCurrBSSID, 0, 6); pMgmt->eCurrState = WMAC_STATE_IDLE; netif_stop_queue(pDevice->dev); //20080701-02,<Add> by Mike Liu /*******search if ap_scan=2 ,which is associating request in hidden ssid mode ****/ { PKnownBSS pCurr = NULL; pCurr = BSSpSearchBSSList(pDevice, pMgmt->abyDesireBSSID, pMgmt->abyDesireSSID, pMgmt->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, (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_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); return -EOPNOTSUPP; break; } if ((ret == 0) && wpa_ioctl) { if (copy_to_user(p->pointer, param, p->length)) { ret = -EFAULT; goto out; } } out: kfree(param); return ret; }