📄 wpactl.c
字号:
/*
* Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
* All rights reserved.
*
* This software is copyrighted by and is the sole property of
* VIA Networking Technologies, Inc. This software may only be used
* in accordance with the corresponding license agreement. Any unauthorized
* use, duplication, transmission, distribution, or disclosure of this
* software is expressly forbidden.
*
* This software is provided by VIA Networking Technologies, Inc. "as is"
* and any express or implied warranties, including, but not limited to, the
* implied warranties of merchantability and fitness for a particular purpose
* are disclaimed. In no event shall VIA Networking Technologies, Inc.
* be liable for any direct, indirect, incidental, special, exemplary, or
* consequential damages.
*
* File: wpactl.c
*
* Purpose: handle wpa supplicant ioctl input/out functions
*
* Author: Lyndon Chen
*
* Date: Oct. 20, 2003
*
* Functions:
*
* Revision History:
*
*/
#if !defined(__WPACTL_H__)
#include "wpactl.h"
#endif
#if !defined(__KEY_H__)
#include "key.h"
#endif
#if !defined(__MAC_H__)
#include "mac.h"
#endif
#if !defined(__DEVICE_H__)
#include "device.h"
#endif
#if !defined(__WMGR_H__)
#include "wmgr.h"
#endif
#if !defined(__IOCMD_H__)
#include "iocmd.h"
#endif
#if !defined(__IOWPA_H__)
#include "iowpa.h"
#endif
/*--------------------- 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 --------------------------*/
/*
* Description:
* register netdev for wpa supplicant deamon
*
* Parameters:
* In:
* pDevice -
* enable -
* Out:
*
* Return Value:
*
*/
static int wpa_init_wpadev(PSDevice pDevice)
{
struct net_device *dev = pDevice->dev;
int ret;
#ifdef PRIVATE_OBJ
pDevice->wpadev = ref_init_wpadev(dev);
if (pDevice->wpadev == NULL)
return -ENOMEM;
ret = register_netdevice(pDevice->wpadev);
if (ret) {
DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: register_netdevice(WPA) failed!\n",
dev->name);
return -1;
}
#else
if (pDevice->skb == NULL) {
pDevice->skb = dev_alloc_skb((int)pDevice->rx_buf_sz);
if (pDevice->skb == NULL)
return -ENOMEM;
}
pDevice->wpadev = alloc_etherdev(0);
//pDevice->wpadev = (struct net_device *)kmalloc(sizeof(struct net_device), GFP_KERNEL);
if (pDevice->wpadev == NULL)
return -ENOMEM;
//memset(pDevice->wpadev, 0, sizeof(struct net_device));
pDevice->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;
ether_setup(pDevice->wpadev);
sprintf(pDevice->wpadev->name, "%swpa", dev->name);
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
SET_NETDEV_DEV(pDevice->wpadev, dev->class_dev.dev);
pDevice->wpadev->destructor = free_netdev;
#endif
ret = register_netdevice(pDevice->wpadev);
if (ret) {
DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: register_netdevice(WPA) failed!\n",
dev->name);
return -1;
}
pDevice->wpadev->type = ARPHRD_IEEE80211;
#endif
DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Registered netdevice %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) {
if (unregister_netdevice(pDevice->wpadev) == 0) {
DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Netdevice %s unregistered\n",
pDevice->dev->name, pDevice->wpadev->name);
}
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,23))
kfree(pDevice->wpadev);
#endif
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 < 0 || val > 1)
return -EINVAL;
if (pDevice->bWPADevEnable == val)
return 0;
pDevice->bWPADevEnable = 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:
*
*/
static int wpa_set_keys(PSDevice pDevice, struct viawget_wpa_param *param)
{
PSMgmtObject pMgmt = pDevice->pMgmt;
DWORD dwKeyIndex = 0;
BYTE abyKey[MAX_KEY_LEN];
BYTE abySeq[MAX_KEY_LEN];
QWORD KeyRSC;
// NDIS_802_11_KEY_RSC KeyRSC;
BYTE byKeyDecMode = KEY_CTL_WEP;
int ret = 0;
int uu, ii;
if (param->u.wpa_key.alg_name > WPA_ALG_CCMP)
return -EINVAL;
DEVICE_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;
}
if (param->u.wpa_key.key &&
copy_from_user(&abyKey[0], param->u.wpa_key.key, param->u.wpa_key.key_len))
return -EINVAL;
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->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;
}
if (param->u.wpa_key.seq &&
copy_from_user(&abySeq[0], param->u.wpa_key.seq, param->u.wpa_key.seq_len))
return -EINVAL;
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) {
DEVICE_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"));
DEVICE_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_ADDRESS(¶m->addr[0]) || (param->addr == NULL)) {
// If IS_BROADCAST_ADDRESS, set the key as every key entry's group key.
DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Groupe Key Assign.\n");
if ((KeybSetAllGroupKey(&(pDevice->sKey),
dwKeyIndex,
param->u.wpa_key.key_len,
(PQWORD) &(KeyRSC),
(PBYTE)abyKey,
byKeyDecMode,
pDevice->PortOffset,
pDevice->byLocalID) == TRUE) &&
(KeybSetDefaultKey(&(pDevice->sKey),
dwKeyIndex,
param->u.wpa_key.key_len,
(PQWORD) &(KeyRSC),
(PBYTE)abyKey,
byKeyDecMode,
pDevice->PortOffset,
pDevice->byLocalID) == TRUE) ) {
DEVICE_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 {
DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Assign.\n");
// BSSID not 0xffffffffffff
// Pairwise Key can't be WEP
if (byKeyDecMode == KEY_CTL_WEP) {
DEVICE_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),
(PBYTE)abyKey,
byKeyDecMode,
pDevice->PortOffset,
pDevice->byLocalID) == TRUE) {
DEVICE_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Pairwise Key Set\n");
} else {
// Key Table Full
if (IS_ETH_ADDRESS_EQUAL(¶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 = (BYTE)param->u.wpa_key.key_index;
pDevice->bTransmitKey = TRUE;
}
pDevice->bEncryptionEnable = TRUE;
spin_unlock_irq(&pDevice->lock);
/*
DEVICE_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],
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -