예제 #1
0
파일: hostap.c 프로젝트: AiWinters/linux
/*
 * Description:
 *      get each stations encryption key
 *
 * Parameters:
 *  In:
 *      pDevice   -
 *      param     -
 *  Out:
 *
 * Return Value:
 *
 */
static int hostap_get_encryption(struct vnt_private *pDevice,
				       struct viawget_hostapd_param *param,
				       int param_len)
{
	struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
	int ret = 0;
	int ii;
	s32 iNodeIndex = 0;


	param->u.crypt.err = 0;

	if (is_broadcast_ether_addr(param->sta_addr)) {
        iNodeIndex = 0;
	} else {
	    if (BSSbIsSTAInNodeDB(pDevice, param->sta_addr, &iNodeIndex) == false) {
	        param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR;
            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "hostap_get_encryption: HOSTAP_CRYPT_ERR_UNKNOWN_ADDR\n");
	        return -EINVAL;
	    }
	}
	DBG_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;
}
예제 #2
0
/*
 * 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->sMgmtObj);
	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 (BSSbIsSTAInNodeDB(pDevice, param->sta_addr, &iNodeIndex) == FALSE) {
	        param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR;
            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "hostap_get_encryption: HOSTAP_CRYPT_ERR_UNKNOWN_ADDR\n");
	        return -EINVAL;
	    }
	}
	DBG_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;
}
예제 #3
0
파일: hostap.c 프로젝트: AiWinters/linux
/*
 * Description:
 *      remove station function supported for hostap daemon
 *
 * Parameters:
 *  In:
 *      pDevice   -
 *      param     -
 *  Out:
 *
 * Return Value:
 *
 */
static int hostap_remove_sta(struct vnt_private *pDevice,
	struct viawget_hostapd_param *param)
{
	unsigned int uNodeIndex;


    if (BSSbIsSTAInNodeDB(pDevice, param->sta_addr, &uNodeIndex)) {
        BSSvRemoveOneNode(pDevice, uNodeIndex);
    }
    else {
        return -ENOENT;
    }
	return 0;
}
예제 #4
0
/*
 * 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 (BSSbIsSTAInNodeDB(pDevice, param->sta_addr, &uNodeIndex)) {
        BSSvRemoveOneNode(pDevice, uNodeIndex);
    }
    else {
        return -ENOENT;
    }
	return 0;
}
예제 #5
0
/*
 * Description:
 *      add a station from hostap daemon
 *
 * Parameters:
 *  In:
 *      pDevice   -
 *      param     -
 *  Out:
 *
 * Return Value:
 *
 */
static int hostap_add_sta(PSDevice pDevice,
				  struct viawget_hostapd_param *param)
{
    PSMgmtObject    pMgmt = &(pDevice->sMgmtObj);
	unsigned int uNodeIndex;


    if (!BSSbIsSTAInNodeDB(pDevice, 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;

    pMgmt->sNodeDBTable[uNodeIndex].ulLastRxJiffer = jiffies;

    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Add STA AID= %d \n", pMgmt->sNodeDBTable[uNodeIndex].wAID);
    DBG_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]
              ) ;
    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "Max Support rate = %d \n",
               pMgmt->sNodeDBTable[uNodeIndex].wMaxSuppRate);

	return 0;
}
예제 #6
0
파일: hostap.c 프로젝트: AiWinters/linux
/*
 * Description:
 *      set station flag
 *
 * Parameters:
 *  In:
 *      pDevice   -
 *      param     -
 *  Out:
 *
 * Return Value:
 *
 */
static int hostap_set_flags_sta(struct vnt_private *pDevice,
		struct viawget_hostapd_param *param)
{
	struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
	unsigned int uNodeIndex;

    if (BSSbIsSTAInNodeDB(pDevice, 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;
		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " dwFlags = %x\n",
			(unsigned int) pMgmt->sNodeDBTable[uNodeIndex].dwFlags);
	}
	else {
	    return -ENOENT;
	}

	return 0;
}
예제 #7
0
파일: hostap.c 프로젝트: AiWinters/linux
static int hostap_get_info_sta(struct vnt_private *pDevice,
	struct viawget_hostapd_param *param)
{
	struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
	unsigned int uNodeIndex;

    if (BSSbIsSTAInNodeDB(pDevice, param->sta_addr, &uNodeIndex)) {
	    param->u.get_info_sta.inactive_sec =
	        (jiffies - pMgmt->sNodeDBTable[uNodeIndex].ulLastRxJiffer) / HZ;

	    //param->u.get_info_sta.txexc = pMgmt->sNodeDBTable[uNodeIndex].uTxAttempts;
	}
	else {
	    return -ENOENT;
	}

	return 0;
}
예제 #8
0
static int hostap_get_info_sta(PSDevice pDevice,
				       struct viawget_hostapd_param *param)
{
    PSMgmtObject    pMgmt = &(pDevice->sMgmtObj);
	unsigned int uNodeIndex;

    if (BSSbIsSTAInNodeDB(pDevice, param->sta_addr, &uNodeIndex)) {
	    param->u.get_info_sta.inactive_sec =
	        (jiffies - pMgmt->sNodeDBTable[uNodeIndex].ulLastRxJiffer) / HZ;

	    //param->u.get_info_sta.txexc = pMgmt->sNodeDBTable[uNodeIndex].uTxAttempts;
	}
	else {
	    return -ENOENT;
	}

	return 0;
}
예제 #9
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->sMgmtObj);
	UINT uNodeIndex;

    if (BSSbIsSTAInNodeDB(pDevice, 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;
		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " dwFlags = %x \n",
		            (UINT)pMgmt->sNodeDBTable[uNodeIndex].dwFlags);
	}
	else {
	    return -ENOENT;
	}

	return 0;
}
예제 #10
0
파일: dpc.c 프로젝트: MaxChina/linux
int RXbBulkInProcessData(struct vnt_private *pDevice, struct vnt_rcb *pRCB,
	unsigned long BytesToIndicate)
{
	struct net_device_stats *pStats = &pDevice->stats;
	struct sk_buff *skb;
	struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
	struct vnt_rx_mgmt *pRxPacket = &pMgmt->sRxPacket;
	struct ieee80211_hdr *p802_11Header;
	u8 *pbyRsr, *pbyNewRsr, *pbyRSSI, *pbyFrame;
	u64 *pqwTSFTime;
	u32 bDeFragRx = false;
	u32 cbHeaderOffset, cbIVOffset;
	u32 FrameSize;
	u16 wEtherType = 0;
	s32 iSANodeIndex = -1;
	int ii;
	u8 *pbyRxSts, *pbyRxRate, *pbySQ, *pby3SQ;
	u32 cbHeaderSize;
	PSKeyItem pKey = NULL;
	u16 wRxTSC15_0 = 0;
	u32 dwRxTSC47_16 = 0;
	/* signed long ldBm = 0; */
	int bIsWEP = false; int bExtIV = false;
	u32 dwWbkStatus;
	struct vnt_rcb *pRCBIndicate = pRCB;
	u8 *pbyDAddress;
	u16 *pwPLCP_Length;
	u8 abyVaildRate[MAX_RATE]
		= {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108};
	u16 wPLCPwithPadding;
	struct ieee80211_hdr *pMACHeader;
	int bRxeapol_key = false;

    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"---------- RXbBulkInProcessData---\n");

    skb = pRCB->skb;

	/* [31:16]RcvByteCount ( not include 4-byte Status ) */
	dwWbkStatus = *((u32 *)(skb->data));
	FrameSize = dwWbkStatus >> 16;
	FrameSize += 4;

	if (BytesToIndicate != FrameSize) {
		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"------- WRONG Length 1\n");
		pStats->rx_frame_errors++;
		return false;
	}

    if ((BytesToIndicate > 2372) || (BytesToIndicate <= 40)) {
        // Frame Size error drop this packet.
	DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "---------- WRONG Length 2\n");
	pStats->rx_frame_errors++;
        return false;
    }

    pbyDAddress = (u8 *)(skb->data);
    pbyRxSts = pbyDAddress+4;
    pbyRxRate = pbyDAddress+5;

    //real Frame Size = USBFrameSize -4WbkStatus - 4RxStatus - 8TSF - 4RSR - 4SQ3 - ?Padding
    //if SQ3 the range is 24~27, if no SQ3 the range is 20~23
    //real Frame size in PLCPLength field.
    pwPLCP_Length = (u16 *) (pbyDAddress + 6);
    //Fix hardware bug => PLCP_Length error
    if ( ((BytesToIndicate - (*pwPLCP_Length)) > 27) ||
         ((BytesToIndicate - (*pwPLCP_Length)) < 24) ||
         (BytesToIndicate < (*pwPLCP_Length)) ) {

        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Wrong PLCP Length %x\n", (int) *pwPLCP_Length);
	pStats->rx_frame_errors++;
        return false;
    }
    for ( ii=RATE_1M;ii<MAX_RATE;ii++) {
        if ( *pbyRxRate == abyVaildRate[ii] ) {
            break;
        }
    }
    if ( ii==MAX_RATE ) {
        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Wrong RxRate %x\n",(int) *pbyRxRate);
        return false;
    }

    wPLCPwithPadding = ( (*pwPLCP_Length / 4) + ( (*pwPLCP_Length % 4) ? 1:0 ) ) *4;

	pqwTSFTime = (u64 *)(pbyDAddress + 8 + wPLCPwithPadding);
  if(pDevice->byBBType == BB_TYPE_11G)  {
      pby3SQ = pbyDAddress + 8 + wPLCPwithPadding + 12;
      pbySQ = pby3SQ;
    }
  else {
   pbySQ = pbyDAddress + 8 + wPLCPwithPadding + 8;
   pby3SQ = pbySQ;
  }
    pbyNewRsr = pbyDAddress + 8 + wPLCPwithPadding + 9;
    pbyRSSI = pbyDAddress + 8 + wPLCPwithPadding + 10;
    pbyRsr = pbyDAddress + 8 + wPLCPwithPadding + 11;

    FrameSize = *pwPLCP_Length;

    pbyFrame = pbyDAddress + 8;

    pMACHeader = (struct ieee80211_hdr *) pbyFrame;

//mike add: to judge if current AP is activated?
    if ((pMgmt->eCurrMode == WMAC_MODE_STANDBY) ||
        (pMgmt->eCurrMode == WMAC_MODE_ESS_STA)) {
       if (pMgmt->sNodeDBTable[0].bActive) {
	 if (ether_addr_equal(pMgmt->abyCurrBSSID, pMACHeader->addr2)) {
	    if (pMgmt->sNodeDBTable[0].uInActiveCount != 0)
                  pMgmt->sNodeDBTable[0].uInActiveCount = 0;
           }
       }
    }

    if (!is_multicast_ether_addr(pMACHeader->addr1)) {
        if (WCTLbIsDuplicate(&(pDevice->sDupRxCache), (struct ieee80211_hdr *) pbyFrame)) {
            return false;
        }

	if (!ether_addr_equal(pDevice->abyCurrentNetAddr, pMACHeader->addr1)) {
		return false;
        }
    }

    // Use for TKIP MIC
    s_vGetDASA(pbyFrame, &cbHeaderSize, &pDevice->sRxEthHeader);

    if (ether_addr_equal((u8 *)pDevice->sRxEthHeader.h_source,
			 pDevice->abyCurrentNetAddr))
        return false;

    if ((pMgmt->eCurrMode == WMAC_MODE_ESS_AP) || (pMgmt->eCurrMode == WMAC_MODE_IBSS_STA)) {
        if (IS_CTL_PSPOLL(pbyFrame) || !IS_TYPE_CONTROL(pbyFrame)) {
            p802_11Header = (struct ieee80211_hdr *) (pbyFrame);
            // get SA NodeIndex
            if (BSSbIsSTAInNodeDB(pDevice, (u8 *)(p802_11Header->addr2), &iSANodeIndex)) {
                pMgmt->sNodeDBTable[iSANodeIndex].ulLastRxJiffer = jiffies;
                pMgmt->sNodeDBTable[iSANodeIndex].uInActiveCount = 0;
            }
        }
    }

    if (IS_FC_WEP(pbyFrame)) {
        bool     bRxDecryOK = false;

        DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"rx WEP pkt\n");
        bIsWEP = true;

	bRxDecryOK = s_bHandleRxEncryption(pDevice, pbyFrame, FrameSize,
		pbyRsr, pbyNewRsr, &pKey, &bExtIV, &wRxTSC15_0, &dwRxTSC47_16);

        if (bRxDecryOK) {
            if ((*pbyNewRsr & NEWRSR_DECRYPTOK) == 0) {
                DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ICV Fail\n");
                if ( (pMgmt->eAuthenMode == WMAC_AUTH_WPA) ||
                    (pMgmt->eAuthenMode == WMAC_AUTH_WPAPSK) ||
                    (pMgmt->eAuthenMode == WMAC_AUTH_WPANONE) ||
                    (pMgmt->eAuthenMode == WMAC_AUTH_WPA2) ||
                    (pMgmt->eAuthenMode == WMAC_AUTH_WPA2PSK)) {
                }
                return false;
            }
        } else {
            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"WEP Func Fail\n");
            return false;
        }
        if ((pKey != NULL) && (pKey->byCipherSuite == KEY_CTL_CCMP))
            FrameSize -= 8;         // Message Integrity Code
        else
            FrameSize -= 4;         // 4 is ICV
    }

    //
    // RX OK
    //
    /* remove the FCS/CRC length */
    FrameSize -= ETH_FCS_LEN;

    if ( !(*pbyRsr & (RSR_ADDRBROAD | RSR_ADDRMULTI)) && // unicast address
        (IS_FRAGMENT_PKT((pbyFrame)))
        ) {
        // defragment
        bDeFragRx = WCTLbHandleFragment(pDevice, (struct ieee80211_hdr *) (pbyFrame), FrameSize, bIsWEP, bExtIV);
        if (bDeFragRx) {
            // defrag complete
            // TODO skb, pbyFrame
            skb = pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].skb;
            FrameSize = pDevice->sRxDFCB[pDevice->uCurrentDFCBIdx].cbFrameLength;
            pbyFrame = skb->data + 8;
        }
        else {
            return false;
        }
    }

    //
    // Management & Control frame Handle
    //
    if ((IS_TYPE_DATA((pbyFrame))) == false) {
        // Handle Control & Manage Frame

        if (IS_TYPE_MGMT((pbyFrame))) {
            u8 * pbyData1;
            u8 * pbyData2;

            pRxPacket = &(pRCB->sMngPacket);
            pRxPacket->p80211Header = (PUWLAN_80211HDR)(pbyFrame);
            pRxPacket->cbMPDULen = FrameSize;
            pRxPacket->uRSSI = *pbyRSSI;
            pRxPacket->bySQ = *pbySQ;
		pRxPacket->qwLocalTSF = cpu_to_le64(*pqwTSFTime);
            if (bIsWEP) {
                // strip IV
                pbyData1 = WLAN_HDR_A3_DATA_PTR(pbyFrame);
                pbyData2 = WLAN_HDR_A3_DATA_PTR(pbyFrame) + 4;
                for (ii = 0; ii < (FrameSize - 4); ii++) {
                    *pbyData1 = *pbyData2;
                     pbyData1++;
                     pbyData2++;
                }
            }

            pRxPacket->byRxRate = s_byGetRateIdx(*pbyRxRate);

            if ( *pbyRxSts == 0 ) {
                //Discard beacon packet which channel is 0
                if ( (WLAN_GET_FC_FSTYPE((pRxPacket->p80211Header->sA3.wFrameCtl)) == WLAN_FSTYPE_BEACON) ||
                     (WLAN_GET_FC_FSTYPE((pRxPacket->p80211Header->sA3.wFrameCtl)) == WLAN_FSTYPE_PROBERESP) ) {
			return false;
                }
            }
            pRxPacket->byRxChannel = (*pbyRxSts) >> 2;

            //
            // Insert the RCB in the Recv Mng list
            //
            EnqueueRCB(pDevice->FirstRecvMngList, pDevice->LastRecvMngList, pRCBIndicate);
            pDevice->NumRecvMngList++;
            if ( bDeFragRx == false) {
                pRCB->Ref++;
            }
            if (pDevice->bIsRxMngWorkItemQueued == false) {
                pDevice->bIsRxMngWorkItemQueued = true;
		schedule_work(&pDevice->rx_mng_work_item);
            }

        }
        else {
            // Control Frame
        };
예제 #11
0
파일: hostap.c 프로젝트: AiWinters/linux
/*
 * Description:
 *      set each stations encryption key
 *
 * Parameters:
 *  In:
 *      pDevice   -
 *      param     -
 *  Out:
 *
 * Return Value:
 *
 */
static int hostap_set_encryption(struct vnt_private *pDevice,
	struct viawget_hostapd_param *param, int param_len)
{
	struct vnt_manager *pMgmt = &pDevice->vnt_mgmt;
	u32 dwKeyIndex = 0;
	u8 abyKey[MAX_KEY_LEN];
	u8 abySeq[MAX_KEY_LEN];
	NDIS_802_11_KEY_RSC   KeyRSC;
	u8 byKeyDecMode = KEY_CTL_WEP;
	int ret = 0;
	s32 iNodeIndex = -1;
	int ii;
	int bKeyTableFull = false;
	u16 wKeyCtl = 0;


	param->u.crypt.err = 0;

	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;
		DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " HOSTAP_CRYPT_ERR_KEY_SET_FAILED\n");
		return -EINVAL;
	}

	if (is_broadcast_ether_addr(param->sta_addr)) {
		if (param->u.crypt.idx >= MAX_GROUP_KEY)
			return -EINVAL;
        iNodeIndex = 0;

	} else {
	    if (BSSbIsSTAInNodeDB(pDevice, param->sta_addr, &iNodeIndex) == false) {
	        param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR;
            DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " HOSTAP_CRYPT_ERR_UNKNOWN_ADDR\n");
	        return -EINVAL;
	    }
	}
    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " hostap_set_encryption: sta_index %d \n", iNodeIndex);
    DBG_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,
                               &(pDevice->sKey),
                               param->sta_addr,
                               pMgmt->sNodeDBTable[iNodeIndex].dwKeyIndex
                              ) == false) {
                DBG_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,
                                &(pDevice->sKey),
                                dwKeyIndex & ~(BIT30 | USE_KEYRSC),
                                param->u.crypt.key_len,
                                NULL,
                                abyKey,
                                KEY_CTL_WEP
                             );

        } else {
            // 8021x enable, individual key
            dwKeyIndex |= (1 << 30); // set pairwise key
		if (KeybSetKey(pDevice, &(pDevice->sKey),
			&param->sta_addr[0],
			dwKeyIndex & ~(USE_KEYRSC),
			param->u.crypt.key_len,
			&KeyRSC, (PBYTE)abyKey,
			KEY_CTL_WEP
                           ) == 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 |= (unsigned long)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,
                           &(pDevice->sKey),
                           dwKeyIndex,
                           param->u.crypt.key_len,
			&KeyRSC,
                           abyKey,
                           byKeyDecMode
                          );
       pMgmt->sNodeDBTable[iNodeIndex].bOnFly = true;

    } else {
        dwKeyIndex |= (1 << 30); // set pairwise key
        if (KeybSetKey(pDevice,
                       &(pDevice->sKey),
                       &param->sta_addr[0],
                       dwKeyIndex,
                       param->u.crypt.key_len,
			&KeyRSC,
                       (PBYTE)abyKey,
                        byKeyDecMode
                       ) == true) {

            pMgmt->sNodeDBTable[iNodeIndex].bOnFly = true;

        } else {
            // Key Table Full
            pMgmt->sNodeDBTable[iNodeIndex].bOnFly = false;
            bKeyTableFull = true;
            DBG_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
// Todo.. xxxxxx
        //MACvSetDefaultKeyCtl(pDevice->PortOffset, wKeyCtl, MAX_KEY_TABLE-1, pDevice->byLocalID);
    }

    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " Set key sta_index= %d \n", iNodeIndex);
    DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO " tx_index=%d len=%d \n", param->u.crypt.idx,
               param->u.crypt.key_len );
    DBG_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;
}