/* * Handle routines to communicate with AUTH daemon (802.1x authenticator) * * $Id: 8192cd_security.c,v 1.10.2.9 2011/01/10 08:19:42 jimmylin Exp $ * * Copyright (c) 2009 Realtek Semiconductor Corp. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #define _8192CD_SECURITY_C_ #ifdef __KERNEL__ #include #include #elif defined(__ECOS) #include #include #include #include #endif #include "./8192cd_cfg.h" #if !defined(__KERNEL__) && !defined(__ECOS) #include "./sys-support.h" #endif #include "./8192cd.h" #include "./8192cd_security.h" #include "./8192cd_headers.h" #include "./8192cd_debug.h" #if defined(CONFIG_RTL_WAPI_SUPPORT) #include "wapi_wai.h" #endif #ifdef INCLUDE_WPS #include "./wps/wsc.h" #endif #ifdef RTK_NL80211 #include "8192cd_cfg80211.h" #endif #define E_MSG_DOT11_2LARGE "ItemSize Too Large" #define E_MSG_DOT11_QFULL "Event Queue Full" #define E_MSG_DOT11_QEMPTY "Event Queue Empty" void DOT11_InitQueue(DOT11_QUEUE * q) { q->Head = 0; q->Tail = 0; q->NumItem = 0; q->MaxItem = MAXQUEUESIZE; } #ifndef WITHOUT_ENQUEUE /*-------------------------------------------------------------------------------- Return Value Success : return 0; Fail : return E_DOT11_QFULL if queue is full return E_DOT1ZX_2LARGE if the item size is large than allocated --------------------------------------------------------------------------------*/ int DOT11_EnQueue(unsigned long task_priv, DOT11_QUEUE *q, unsigned char *item, int itemsize) { #ifdef __KERNEL__ struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; #endif #ifndef SMP_SYNC unsigned long flags; #endif if (itemsize > MAXDATALEN) return E_DOT11_2LARGE; SAVE_INT_AND_CLI(flags); if (DOT11_IsFullQueue(q)) { RESTORE_INT(flags); return E_DOT11_QFULL; } q->ItemArray[q->Tail].ItemSize = itemsize; memset(q->ItemArray[q->Tail].Item, 0, sizeof(q->ItemArray[q->Tail].Item)); memcpy(q->ItemArray[q->Tail].Item, item, itemsize); q->NumItem++; if((q->Tail+1) == MAXQUEUESIZE) q->Tail = 0; else q->Tail++; RESTORE_INT(flags); return 0; } int DOT11_DeQueue(unsigned long task_priv, DOT11_QUEUE *q, unsigned char *item, int *itemsize) { #ifdef __KERNEL__ struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv; #endif #ifndef SMP_SYNC unsigned long flags; #endif SAVE_INT_AND_CLI(flags); if (DOT11_IsEmptyQueue(q)) { RESTORE_INT(flags); return E_DOT11_QEMPTY; } memcpy(item, q->ItemArray[q->Head].Item, q->ItemArray[q->Head].ItemSize); *itemsize = q->ItemArray[q->Head].ItemSize; q->NumItem--; if((q->Head+1) == MAXQUEUESIZE) q->Head = 0; else q->Head++; RESTORE_INT(flags); return 0; } #endif // !WITHOUT_ENQUEUE #if 0 void DOT11_PrintQueue(DOT11_QUEUE *q) { int i, j, index; printk("\n/-------------------------------------------------\n[DOT11_PrintQueue]: MaxItem = %d, NumItem = %d, Head = %d, Tail = %d\n", q->MaxItem, q->NumItem, q->Head, q->Tail); for(i=0; iNumItem; i++) { index = (i + q->Head) % q->MaxItem; printk("Queue[%d].ItemSize = %d ", index, q->ItemArray[index].ItemSize); for(j=0; jItemArray[index].ItemSize; j++) printk(" %x", q->ItemArray[index].Item[j]); printk("\n"); } printk("------------------------------------------------/\n"); } char *DOT11_ErrMsgQueue(int err) { switch(err) { case E_DOT11_2LARGE: return E_MSG_DOT11_2LARGE; case E_DOT11_QFULL: return E_MSG_DOT11_QFULL; case E_DOT11_QEMPTY: return E_MSG_DOT11_QEMPTY; default: return "E_MSG_DOT11_QNOERR"; } } void DOT11_Dump(char *fun, UINT8 *buf, int size, char *comment) { int i; printk("$$ %s $$: %s", fun, comment); if (buf != NULL) { printk("\nMessage is %d bytes %x hex", size, size); for (i = 0; i < size; i++) { if (i % 16 == 0) printk("\n\t"); printk("%2x ", *(buf+i)); } } printk("\n"); } #endif /*------------------------------------------------------------ Set RSNIE is to set Information Element of AP Return Value Success : 0 ------------------------------------------------------------*/ static int DOT11_Process_Set_RSNIE(struct net_device *dev, struct iw_point *data) { struct Dot11RsnIE *pdot11RsnIE; struct wifi_mib *pmib; struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); #ifdef HS2_SUPPORT unsigned char rsnie_hdr_OSEN[4]={0x50, 0x6F, 0x9A, 0x12}; #endif DOT11_SET_RSNIE *Set_RSNIE = (DOT11_SET_RSNIE *)data->pointer; DEBUG_INFO("going to set rsnie\n"); pmib = priv->pmib; pdot11RsnIE = &pmib->dot11RsnIE; if(Set_RSNIE->Flag == DOT11_Ioctl_Set) { pdot11RsnIE->rsnielen = Set_RSNIE->RSNIELen; memcpy((void *)pdot11RsnIE->rsnie, Set_RSNIE->RSNIE, pdot11RsnIE->rsnielen); priv->pmib->dot118021xAuthEntry.dot118021xAlgrthm = 1; DEBUG_INFO("DOT11_Process_Set_RSNIE rsnielen=%d\n", pdot11RsnIE->rsnielen); // see whether if driver is open. If not, do not enable tx/rx, david if (!netif_running(priv->dev)) { #ifdef __OSK__ if (IS_VXD_INTERFACE(priv) && pdot11RsnIE->rsnielen > 0) priv->pmib->dot11OperationEntry.keep_rsnie = 1; #endif return 0; } // Alway enable tx/rx in rtl8190_init_hw_PCI() //RTL_W8(_CR_, BIT(2) | BIT(3)); #if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) if (!priv->pmib->dot1180211AuthEntry.dot11EnablePSK) #endif { if (OPMODE & WIFI_AP_STATE) { #ifdef MBSSID if (IS_ROOT_INTERFACE(priv)) #endif { if (priv->auto_channel) { priv->ss_ssidlen = 0; DEBUG_INFO("start_clnt_ss, trigger by %s, ss_ssidlen=0\n", (char *)__FUNCTION__); start_clnt_ss(priv); } } } //for openwrt 8021x donot trigger site survey when rsnie init in init sw #if defined(CLIENT_MODE) && !defined(RTK_NL80211) && !defined(WIFI_WPAS_CLI) if (OPMODE & (WIFI_STATION_STATE | WIFI_ADHOC_STATE)) start_clnt_lookup(priv, RESCAN); #endif } } else if(Set_RSNIE->Flag == DOT11_Ioctl_Query) { } return 0; } #if 0 char *DOT11_Parse_RSNIE_Err(int err) { switch(err) { case ERROR_BUFFER_TOO_SMALL: return RSN_STRERROR_BUFFER_TOO_SMALL; case ERROR_INVALID_PARA: return RSN_STRERROR_INVALID_PARAMETER; case ERROR_INVALID_RSNIE: return RSN_STRERROR_INVALID_RSNIE; case ERROR_INVALID_MULTICASTCIPHER: return RSN_STRERROR_INVALID_MULTICASTCIPHER; case ERROR_INVALID_UNICASTCIPHER: return RSN_STRERROR_INVALID_UNICASTCIPHER; case ERROR_INVALID_AUTHKEYMANAGE: return RSN_STRERROR_INVALID_AUTHKEYMANAGE; case ERROR_UNSUPPORTED_RSNEVERSION: return RSN_STRERROR_UNSUPPORTED_RSNEVERSION; case ERROR_INVALID_CAPABILITIES: return RSN_STRERROR_INVALID_CAPABILITIES; default: return "Uknown Failure"; } } #endif /*------------------------------------------------- Send association response to STA Return Value Success : 0 ---------------------------------------------------*/ static int DOT11_Process_Association_Rsp(struct net_device *dev, struct iw_point *data, int frame_type) { #ifndef SMP_SYNC unsigned long flags; #endif struct stat_info *pstat; unsigned char *hwaddr; struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); DOT11_ASSOCIATIIN_RSP *Assoc_Rsp = (DOT11_ASSOCIATIIN_RSP *)data->pointer; pstat = get_stainfo(priv, (UINT8 *)Assoc_Rsp->MACAddr); if (pstat == NULL) return (-1); hwaddr = (unsigned char *)Assoc_Rsp->MACAddr; DEBUG_INFO("802.1x issue assoc_rsp sta:%02X%02X%02X%02X%02X%02X status:%d\n", hwaddr[0],hwaddr[1],hwaddr[2],hwaddr[3],hwaddr[4],hwaddr[5], Assoc_Rsp->Status); issue_asocrsp(priv, Assoc_Rsp->Status, pstat, frame_type); if (Assoc_Rsp->Status != 0) { SAVE_INT_AND_CLI(flags); if (asoc_list_del(priv, pstat)) { if (pstat->expire_to > 0) { cnt_assoc_num(priv, pstat, DECREASE, (char *)__FUNCTION__); check_sta_characteristic(priv, pstat, DECREASE); LOG_MSG("A STA is rejected by 802.1x daemon - %02X:%02X:%02X:%02X:%02X:%02X\n", pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5]); } } free_stainfo(priv, pstat); RESTORE_INT(flags); } else update_fwtbl_asoclst(priv, pstat); return 0; } /*------------------------------------------------- Send Disassociation request to STA Return Value Success : 0 ---------------------------------------------------*/ #ifdef CONFIG_PCI_HCI static inline #endif int __DOT11_Process_Disconnect_Req(struct net_device *dev, struct iw_point *data) { #ifndef SMP_SYNC unsigned long flags; #endif struct stat_info *pstat; unsigned char *hwaddr; struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); DOT11_DISCONNECT_REQ *Disconnect_Req = (DOT11_DISCONNECT_REQ *)data->pointer; pstat = get_stainfo(priv, (UINT8 *)Disconnect_Req->MACAddr); if (pstat == NULL) return (-1); hwaddr = (unsigned char *)Disconnect_Req->MACAddr; #ifdef WIFI_SIMPLE_CONFIG if (wsc_disconn_list_check(priv, hwaddr)) { DEBUG_INFO("Ignore issue disassoc sta:%02X%02X%02X%02X%02X%02X due to STA had reconnected\n", hwaddr[0],hwaddr[1],hwaddr[2],hwaddr[3],hwaddr[4],hwaddr[5]); return 0; } #endif DEBUG_INFO("802.1x issue disassoc sta:%02X%02X%02X%02X%02X%02X reason:%d\n", hwaddr[0],hwaddr[1],hwaddr[2],hwaddr[3],hwaddr[4],hwaddr[5], Disconnect_Req->Reason); #ifdef CLIENT_MODE if(OPMODE & WIFI_STATION_STATE){ if((OPMODE&( WIFI_AUTH_SUCCESS | WIFI_ASOC_STATE)) ==( WIFI_AUTH_SUCCESS | WIFI_ASOC_STATE)) { issue_deauth(priv, BSSID, _RSON_DEAUTH_STA_LEAVING_); OPMODE_VAL(OPMODE & ~(WIFI_AUTH_SUCCESS | WIFI_ASOC_STATE)); #ifndef WIFI_WPAS_CLI #ifdef SMART_REPEATER_MODE if(GET_MIB(priv)->ap_profile.enable_profile && GET_MIB(priv)->ap_profile.profile_num > 0) { if((priv->site_survey->count_target > 0) && ((priv->join_index+1) > priv->site_survey->count_target)){ start_clnt_lookup(priv, RESCAN); }else{ start_clnt_lookup(priv, DONTRESCAN); } } else #endif { start_clnt_lookup(priv, RESCAN); } #endif // !WIFI_WPAS_CLI //SME_DEBUG("!!issue disconnect at wlan!!\n"); }else{ return (-1); } }else #endif { issue_deauth(priv, pstat->hwaddr, Disconnect_Req->Reason); } SAVE_INT_AND_CLI(flags); if (asoc_list_del(priv, pstat)) { if (pstat->expire_to > 0) { cnt_assoc_num(priv, pstat, DECREASE, (char *)__FUNCTION__); check_sta_characteristic(priv, pstat, DECREASE); LOG_MSG("A STA is rejected by 802.1x daemon - %02X:%02X:%02X:%02X:%02X:%02X\n", pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5]); } } free_stainfo(priv, pstat); RESTORE_INT(flags); return 0; } int DOT11_Process_Disconnect_Req(struct net_device *dev, struct iw_point *data) { #if defined(CONFIG_PCI_HCI) return __DOT11_Process_Disconnect_Req(dev, data); #elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) notify_disconnect_sta(dev, (DOT11_DISCONNECT_REQ *)data->pointer); return 0; #endif } /*--------------------------------------------------------------------- Delete Group Key for AP and Pairwise Key for specific STA Return Value Success : 0 -----------------------------------------------------------------------*/ int DOT11_Process_Delete_Key(struct net_device *dev, struct iw_point *data) { struct stat_info *pstat = NULL; struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); DOT11_DELETE_KEY *Delete_Key = (DOT11_DELETE_KEY *)data->pointer; struct wifi_mib *pmib = priv->pmib; unsigned char MULTICAST_ADD[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; if (Delete_Key->KeyType == DOT11_KeyType_Group) { pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TTKeyLen = 0; pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TMicKeyLen = 0; DEBUG_INFO("Delete Group Key\n"); if (CamDeleteOneEntry(priv, MULTICAST_ADD, 1, 0)) priv->pshare->CamEntryOccupied--; #if defined(CONFIG_RTL_HW_WAPI_SUPPORT) if (CamDeleteOneEntry(priv, MULTICAST_ADD, 1, 0)) priv->pshare->CamEntryOccupied--; #endif } else if (Delete_Key->KeyType == DOT11_KeyType_Pairwise) { pstat = get_stainfo(priv, (UINT8 *)Delete_Key->MACAddr); if (pstat == NULL) return (-1); pstat->dot11KeyMapping.dot11EncryptKey.dot11TTKeyLen = 0; pstat->dot11KeyMapping.dot11EncryptKey.dot11TMicKeyLen = 0; DEBUG_INFO("Delete Unicast Key\n"); if (pstat->dot11KeyMapping.keyInCam == TRUE) { if (CamDeleteOneEntry(priv, (unsigned char *)Delete_Key->MACAddr, 0, 0)) { priv->pshare->CamEntryOccupied--; if (pstat) pstat->dot11KeyMapping.keyInCam = FALSE; } #if defined(CONFIG_RTL_HW_WAPI_SUPPORT) if (CamDeleteOneEntry(priv, (unsigned char *)Delete_Key->MACAddr, 0, 0)) { priv->pshare->CamEntryOccupied--; if (pstat) pstat->dot11KeyMapping.keyInCam = FALSE; } #endif } } return 0; } static __inline__ void set_ttkeylen(struct Dot11EncryptKey *pEncryptKey, UINT8 len) { pEncryptKey->dot11TTKeyLen = len; } static __inline__ void set_tmickeylen(struct Dot11EncryptKey *pEncryptKey, UINT8 len) { pEncryptKey->dot11TMicKeyLen = len; } static __inline__ void set_tkip_key(struct Dot11EncryptKey *pEncryptKey, UINT8 *src) { memcpy(pEncryptKey->dot11TTKey.skey, src, pEncryptKey->dot11TTKeyLen); memcpy(pEncryptKey->dot11TMicKey1.skey, src + 16, pEncryptKey->dot11TMicKeyLen); memcpy(pEncryptKey->dot11TMicKey2.skey, src + 24, pEncryptKey->dot11TMicKeyLen); } static __inline__ void set_aes_key(struct Dot11EncryptKey *pEncryptKey, UINT8 *src) { memcpy(pEncryptKey->dot11TTKey.skey, src, pEncryptKey->dot11TTKeyLen); memcpy(pEncryptKey->dot11TMicKey1.skey, src, pEncryptKey->dot11TMicKeyLen); } static __inline__ void set_wep40_key(struct Dot11EncryptKey *pEncryptKey, UINT8 *src) { memcpy(pEncryptKey->dot11TTKey.skey, src, pEncryptKey->dot11TTKeyLen); } static __inline__ void set_wep104_key(struct Dot11EncryptKey *pEncryptKey, UINT8 *src) { memcpy(pEncryptKey->dot11TTKey.skey, src, pEncryptKey->dot11TTKeyLen); } static __inline__ void clean_pn(unsigned char *pn) { memset(pn, 0, 6); } /*--------------------------------------------------------------------- Set Group Key for AP and Pairwise Key for specific STA Return Value Success : 0 -----------------------------------------------------------------------*/ int DOT11_Process_Set_Key(struct net_device *dev, struct iw_point *data, DOT11_SET_KEY *pSetKey, unsigned char *pKey) { struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); struct wifi_mib *pmib = priv->pmib; struct Dot11EncryptKey *pEncryptKey = NULL; struct stat_info *pstat = NULL; DOT11_SET_KEY Set_Key; unsigned char key_combo[32]; unsigned char MULTICAST_ADD[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; int retVal; if (data) { #if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) memcpy((void *)&Set_Key, (void *)data->pointer, sizeof(DOT11_SET_KEY)); memcpy((void *)key_combo, ((DOT11_SET_KEY *)data->pointer)->KeyMaterial, 32); #else if (copy_from_user((void *)&Set_Key, (void *)data->pointer, sizeof(DOT11_SET_KEY))) { DEBUG_ERR("copy_from_user error!\n"); return -1; } if (copy_from_user((void *)key_combo, ((DOT11_SET_KEY *)data->pointer)->KeyMaterial, 32)) { DEBUG_ERR("copy_from_user error!\n"); return -1; } #endif } else { Set_Key = *pSetKey; memcpy(key_combo, pKey, 32); } #ifdef WDS #ifdef LAZY_WDS if ((priv->pmib->dot11WdsInfo.wdsEnabled == WDS_LAZY_ENABLE || (priv->pmib->dot11WdsInfo.wdsEnabled && priv->pmib->dot11WdsInfo.wdsNum)) && #else if (priv->pmib->dot11WdsInfo.wdsEnabled && priv->pmib->dot11WdsInfo.wdsNum && #endif ((priv->pmib->dot11WdsInfo.wdsPrivacy == _TKIP_PRIVACY_) || (priv->pmib->dot11WdsInfo.wdsPrivacy == _CCMP_PRIVACY_)) && (Set_Key.KeyType == DOT11_KeyType_Group) && !memcmp(Set_Key.MACAddr, NULL_MAC_ADDR, 6)) { int i; for (i=0; i<32; i++) sprintf((char *)&priv->pmib->dot11WdsInfo.wdsPskPassPhrase[i*2], "%02x", key_combo[i]); priv->pmib->dot11WdsInfo.wdsPskPassPhrase[i*2] = '\0'; for (i=0; ipmib->dot11WdsInfo.wdsEnabled == WDS_LAZY_ENABLE) { if (!memcmp(priv->pmib->dot11WdsInfo.entry[i].macAddr, NULL_MAC_ADDR, 6)) continue; } else #endif { if (i+1 > pmib->dot11WdsInfo.wdsNum) break; } memcpy(Set_Key.MACAddr, priv->pmib->dot11WdsInfo.entry[i].macAddr, 6); Set_Key.KeyType = DOT11_KeyType_Pairwise; Set_Key.EncType = priv->pmib->dot11WdsInfo.wdsPrivacy; Set_Key.KeyIndex = 0; DOT11_Process_Set_Key(priv->dev, NULL, &Set_Key, key_combo); } return 0; } #endif if(Set_Key.KeyType == DOT11_KeyType_Group) { int set_gkey_to_cam = 0; #ifdef CONFIG_RTL_88E_SUPPORT if (GET_CHIP_VER(priv) == VERSION_8188E) set_gkey_to_cam = 1; #endif #ifdef UNIVERSAL_REPEATER if (IS_VXD_INTERFACE(priv)) set_gkey_to_cam = 0; else { if (IS_ROOT_INTERFACE(priv)) { if (IS_DRV_OPEN(GET_VXD_PRIV(priv))) set_gkey_to_cam = 0; } } #endif #ifdef MBSSID if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { // No matter root or vap, don't set key to cam if vap is enabled. set_gkey_to_cam = 0; } #endif pmib->dot11GroupKeysTable.dot11Privacy = Set_Key.EncType; pEncryptKey = &pmib->dot11GroupKeysTable.dot11EncryptKey; pmib->dot11GroupKeysTable.keyid = (UINT)Set_Key.KeyIndex; switch(Set_Key.EncType) { case DOT11_ENC_TKIP: set_ttkeylen(pEncryptKey, 16); set_tmickeylen(pEncryptKey, 8); set_tkip_key(pEncryptKey, key_combo); DEBUG_INFO("going to set TKIP group key! id %X\n", (UINT)Set_Key.KeyIndex); if (!SWCRYPTO) { if (set_gkey_to_cam) { retVal = CamDeleteOneEntry(priv, MULTICAST_ADD, Set_Key.KeyIndex, 0); if (retVal) { priv->pshare->CamEntryOccupied--; pmib->dot11GroupKeysTable.keyInCam = FALSE; } retVal = CamAddOneEntry(priv, MULTICAST_ADD, Set_Key.KeyIndex, DOT11_ENC_TKIP<<2, 0, key_combo); if (retVal) { priv->pshare->CamEntryOccupied++; pmib->dot11GroupKeysTable.keyInCam = TRUE; } } } break; case DOT11_ENC_WEP40: set_ttkeylen(pEncryptKey, 5); set_tmickeylen(pEncryptKey, 0); set_wep40_key(pEncryptKey, key_combo); DEBUG_INFO("going to set WEP40 group key!\n"); if (!SWCRYPTO) { if (set_gkey_to_cam) { retVal = CamDeleteOneEntry(priv, MULTICAST_ADD, Set_Key.KeyIndex, 0); if (retVal) { priv->pshare->CamEntryOccupied--; pmib->dot11GroupKeysTable.keyInCam = FALSE; } retVal = CamAddOneEntry(priv, MULTICAST_ADD, Set_Key.KeyIndex, DOT11_ENC_WEP40<<2, 0, key_combo); if (retVal) { priv->pshare->CamEntryOccupied++; pmib->dot11GroupKeysTable.keyInCam = TRUE; } } } break; case DOT11_ENC_WEP104: set_ttkeylen(pEncryptKey, 13); set_tmickeylen(pEncryptKey, 0); set_wep104_key(pEncryptKey, key_combo); DEBUG_INFO("going to set WEP104 group key!\n"); if (!SWCRYPTO) { if (set_gkey_to_cam) { retVal = CamDeleteOneEntry(priv, MULTICAST_ADD, Set_Key.KeyIndex, 0); if (retVal) { priv->pshare->CamEntryOccupied--; pmib->dot11GroupKeysTable.keyInCam = FALSE; } retVal = CamAddOneEntry(priv, MULTICAST_ADD, Set_Key.KeyIndex, DOT11_ENC_WEP104<<2, 0, key_combo); if (retVal) { priv->pshare->CamEntryOccupied++; pmib->dot11GroupKeysTable.keyInCam = TRUE; } } } break; case DOT11_ENC_CCMP: set_ttkeylen(pEncryptKey, 16); set_tmickeylen(pEncryptKey, 16); set_aes_key(pEncryptKey, key_combo); DEBUG_INFO("going to set CCMP-AES group key!\n"); if (!SWCRYPTO) { if (set_gkey_to_cam) { retVal = CamDeleteOneEntry(priv, MULTICAST_ADD, Set_Key.KeyIndex, 0); if (retVal) { priv->pshare->CamEntryOccupied--; pmib->dot11GroupKeysTable.keyInCam = FALSE; } retVal = CamAddOneEntry(priv, MULTICAST_ADD, Set_Key.KeyIndex, DOT11_ENC_CCMP<<2, 0, key_combo); if (retVal) { priv->pshare->CamEntryOccupied++; pmib->dot11GroupKeysTable.keyInCam = TRUE; } } } break; case DOT11_ENC_NONE: default: DEBUG_ERR("No group encryption key is set!\n"); set_ttkeylen(pEncryptKey, 0); set_tmickeylen(pEncryptKey, 0); break; } } #ifdef CONFIG_IEEE80211W else if(Set_Key.KeyType == DOT11_KeyType_IGTK) { int set_gkey_to_cam = 0; #ifdef CONFIG_RTL_88E_SUPPORT if (GET_CHIP_VER(priv) == VERSION_8188E) set_gkey_to_cam = 1; #endif //CONFIG_RTL_88E_SUPPORT #ifdef MBSSID if (GET_ROOT(priv)->pmib->miscEntry.vap_enable) { // No matter root or vap, don't set key to cam if vap is enabled. set_gkey_to_cam = 0; } #endif pmib->dot11IGTKTable.dot11Privacy = Set_Key.EncType; pEncryptKey = &pmib->dot11IGTKTable.dot11EncryptKey; pmib->dot11IGTKTable.keyid = (UINT)Set_Key.KeyIndex; set_ttkeylen(pEncryptKey, 16); set_tmickeylen(pEncryptKey, 16); set_aes_key(pEncryptKey, key_combo); } #endif // CONFIG_IEEE80211W else if(Set_Key.KeyType == DOT11_KeyType_Pairwise) { #ifdef WDS // always to store WDS key for tx-hangup re-init #if 0 // if driver is not opened, save the WDS key into mib. The key value will // be updated into CAM when driver opened. david if ( !IS_DRV_OPEN(priv)) { // not open or not in open // if interface is not open and STA is a WDS entry, save the key // to mib and restore it to STA table when driver is open, david struct net_device *pNet = getWdsDevByAddr(priv, Set_Key.MACAddr); if (pNet) { int widx = getWdsIdxByDev(priv, pNet); if (widx >= 0) { if (Set_Key.EncType == _WEP_40_PRIVACY_ || Set_Key.EncType == _WEP_104_PRIVACY_) memcpy(pmib->dot11WdsInfo.wdsWepKey, key_combo, 32); else { memcpy(pmib->dot11WdsInfo.wdsMapingKey[widx], key_combo, 32); pmib->dot11WdsInfo.wdsMappingKeyLen[widx] = 32; } pmib->dot11WdsInfo.wdsKeyId = Set_Key.KeyIndex; pmib->dot11WdsInfo.wdsPrivacy = Set_Key.EncType; return 0; } } return -1; } #endif int widx = -1; struct net_device *pNet = getWdsDevByAddr(priv, Set_Key.MACAddr); if (pNet) { widx = getWdsIdxByDev(priv, pNet); if (widx >= 0) { if (Set_Key.EncType == _WEP_40_PRIVACY_ || Set_Key.EncType == _WEP_104_PRIVACY_) memcpy(pmib->dot11WdsInfo.wdsWepKey, key_combo, 32); else { memcpy(pmib->dot11WdsInfo.wdsMapingKey[widx], key_combo, 32); pmib->dot11WdsInfo.wdsMappingKeyLen[widx] = 32; } pmib->dot11WdsInfo.wdsKeyId = Set_Key.KeyIndex; pmib->dot11WdsInfo.wdsPrivacy = Set_Key.EncType; } } if ( !IS_DRV_OPEN(priv)) { if (widx > 0 && pmib->dot11WdsInfo.wdsMappingKeyLen[widx] > 0) pmib->dot11WdsInfo.wdsMappingKeyLen[widx] |= 0x80000000; return 0; } //----------------------------------- david+2006-06-30 #endif // WDS #ifdef MULTI_MAC_CLONE if ((OPMODE & WIFI_STATION_STATE) && priv->pmib->ethBrExtInfo.macclone_enable) { ACTIVE_ID = mclone_find_address(priv, Set_Key.MACAddr, NULL, MAC_CLONE_NOCARE_FIND); if (ACTIVE_ID < 0) { DEBUG_ERR("Invalid mac address!\n"); return 0; } pstat = get_stainfo(priv, priv->pmib->dot11Bss.bssid); } else #endif pstat = get_stainfo(priv, Set_Key.MACAddr); if (pstat == NULL) { DEBUG_ERR("Set key failed, invalid mac address: %02x%02x%02x%02x%02x%02x\n", Set_Key.MACAddr[0], Set_Key.MACAddr[1], Set_Key.MACAddr[2], Set_Key.MACAddr[3], Set_Key.MACAddr[4], Set_Key.MACAddr[5]); return (-1); } pstat->dot11KeyMapping.dot11Privacy = Set_Key.EncType; pEncryptKey = &pstat->dot11KeyMapping.dot11EncryptKey; pstat->keyid = Set_Key.KeyIndex; #if defined(__DRAYTEK_OS__) && defined(WDS) if (pstat->state & WIFI_WDS) priv->pmib->dot11WdsInfo.wdsPrivacy = Set_Key.EncType; #endif switch(Set_Key.EncType) { case DOT11_ENC_TKIP: set_ttkeylen(pEncryptKey, 16); set_tmickeylen(pEncryptKey, 8); set_tkip_key(pEncryptKey, key_combo); DEBUG_INFO("going to set TKIP Unicast key for sta %02X%02X%02X%02X%02X%02X, id=%d\n", Set_Key.MACAddr[0], Set_Key.MACAddr[1], Set_Key.MACAddr[2], Set_Key.MACAddr[3], Set_Key.MACAddr[4], Set_Key.MACAddr[5], pstat->keyid); if (!SWCRYPTO) { retVal = CamDeleteOneEntry(priv, Set_Key.MACAddr, Set_Key.KeyIndex, 0); if (retVal) { priv->pshare->CamEntryOccupied--; if (pstat) pstat->dot11KeyMapping.keyInCam = FALSE; } retVal = CamAddOneEntry(priv, Set_Key.MACAddr, Set_Key.KeyIndex, DOT11_ENC_TKIP<<2, 0, key_combo); if (retVal) { priv->pshare->CamEntryOccupied++; if (pstat) pstat->dot11KeyMapping.keyInCam = TRUE; } else { if (pstat->aggre_mthd != AGGRE_MTHD_NONE) pstat->aggre_mthd = AGGRE_MTHD_NONE; } } break; case DOT11_ENC_WEP40: set_ttkeylen(pEncryptKey, 5); set_tmickeylen(pEncryptKey, 0); set_wep40_key(pEncryptKey, key_combo); DEBUG_INFO("going to set WEP40 unicast key for sta %02X%02X%02X%02X%02X%02X, id=%d\n", Set_Key.MACAddr[0], Set_Key.MACAddr[1], Set_Key.MACAddr[2], Set_Key.MACAddr[3], Set_Key.MACAddr[4], Set_Key.MACAddr[5], pstat->keyid); if (!SWCRYPTO) { retVal = CamDeleteOneEntry(priv, Set_Key.MACAddr, Set_Key.KeyIndex, 0); if (retVal) { priv->pshare->CamEntryOccupied--; if (pstat) pstat->dot11KeyMapping.keyInCam = FALSE; } retVal = CamAddOneEntry(priv, Set_Key.MACAddr, Set_Key.KeyIndex, DOT11_ENC_WEP40<<2, 0, key_combo); if (retVal) { priv->pshare->CamEntryOccupied++; if (pstat) pstat->dot11KeyMapping.keyInCam = TRUE; } else { if (pstat->aggre_mthd != AGGRE_MTHD_NONE) pstat->aggre_mthd = AGGRE_MTHD_NONE; } } break; case DOT11_ENC_WEP104: set_ttkeylen(pEncryptKey, 13); set_tmickeylen(pEncryptKey, 0); set_wep104_key(pEncryptKey, key_combo); DEBUG_INFO("going to set WEP104 unicast key for sta %02X%02X%02X%02X%02X%02X, id=%d\n", Set_Key.MACAddr[0], Set_Key.MACAddr[1], Set_Key.MACAddr[2], Set_Key.MACAddr[3], Set_Key.MACAddr[4], Set_Key.MACAddr[5], pstat->keyid); if (!SWCRYPTO) { retVal = CamDeleteOneEntry(priv, Set_Key.MACAddr, Set_Key.KeyIndex, 0); if (retVal) { priv->pshare->CamEntryOccupied--; if (pstat) pstat->dot11KeyMapping.keyInCam = FALSE; } retVal = CamAddOneEntry(priv, Set_Key.MACAddr, Set_Key.KeyIndex, DOT11_ENC_WEP104<<2, 0, key_combo); if (retVal) { priv->pshare->CamEntryOccupied++; if (pstat) pstat->dot11KeyMapping.keyInCam = TRUE; } else { if (pstat->aggre_mthd != AGGRE_MTHD_NONE) pstat->aggre_mthd = AGGRE_MTHD_NONE; } } break; case DOT11_ENC_CCMP: set_ttkeylen(pEncryptKey, 16); set_tmickeylen(pEncryptKey, 16); set_aes_key(pEncryptKey, key_combo); DEBUG_INFO("going to set CCMP-AES unicast key for sta %02X%02X%02X%02X%02X%02X, id=%d\n", Set_Key.MACAddr[0], Set_Key.MACAddr[1], Set_Key.MACAddr[2], Set_Key.MACAddr[3], Set_Key.MACAddr[4], Set_Key.MACAddr[5], pstat->keyid); if (!SWCRYPTO) { retVal = CamDeleteOneEntry(priv, Set_Key.MACAddr, Set_Key.KeyIndex, 0); if (retVal) { priv->pshare->CamEntryOccupied--; if (pstat) pstat->dot11KeyMapping.keyInCam = FALSE; } retVal = CamAddOneEntry(priv, Set_Key.MACAddr, Set_Key.KeyIndex, DOT11_ENC_CCMP<<2, 0, key_combo); if (retVal) { priv->pshare->CamEntryOccupied++; if (pstat) pstat->dot11KeyMapping.keyInCam = TRUE; assign_aggre_mthod(priv, pstat); } else { if (pstat->aggre_mthd != AGGRE_MTHD_NONE) pstat->aggre_mthd = AGGRE_MTHD_NONE; } } break; case DOT11_ENC_NONE: default: DEBUG_ERR("No pairewise encryption key is set!\n"); set_ttkeylen(pEncryptKey, 0); set_tmickeylen(pEncryptKey, 0); break; } } return 0; } /*--------------------------------------------------------------------- Set Port Enable of Disable for STA Return Value Success : 0 -----------------------------------------------------------------------*/ static int DOT11_Process_Set_Port(struct net_device *dev, struct iw_point *data) { struct stat_info *pstat; struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); struct wifi_mib *pmib = priv->pmib; DOT11_SET_PORT *Set_Port = (DOT11_SET_PORT *)data->pointer; DEBUG_INFO("Set_Port sta %02X%02X%02X%02X%02X%02X Status %X\n", Set_Port->MACAddr[0],Set_Port->MACAddr[1],Set_Port->MACAddr[2], Set_Port->MACAddr[3],Set_Port->MACAddr[4],Set_Port->MACAddr[5], Set_Port->PortStatus); // if driver is not opened, return immediately, david if (!netif_running(priv->dev)) return (-1); pstat = get_stainfo(priv, Set_Port->MACAddr); if ((pstat == NULL) || (!(pstat->state & WIFI_ASOC_STATE))) return (-1); if (Set_Port->PortStatus) { pstat->ieee8021x_ctrlport = Set_Port->PortStatus; #ifdef INDICATE_LINK_CHANGE indicate_sta_link_change(priv, pstat, INCREASE, __FUNCTION__); #endif } else pstat->ieee8021x_ctrlport = pmib->dot118021xAuthEntry.dot118021xDefaultPort; #ifdef P2P_SUPPORT if((OPMODE&WIFI_P2P_SUPPORT)&&( P2PMODE ==P2P_CLIENT)){ /*to indicate web server that data path is connected done(can start issue udhcpc daemon)*/ P2P_STATE = P2P_S_CLIENT_CONNECTED_DHCPC; priv->p2pPtr->clientmode_try_connect = 0; P2P_DEBUG("Set_Port Sta[%02X%02X%02X%02X%02X%02X],Status=%X\n\n\n", Set_Port->MACAddr[0],Set_Port->MACAddr[1],Set_Port->MACAddr[2], Set_Port->MACAddr[3],Set_Port->MACAddr[4],Set_Port->MACAddr[5], Set_Port->PortStatus); } #endif return 0; } static int DOT11_Process_QueryRSC(struct net_device *dev, struct iw_point *data) { DOT11_GKEY_TSC *pGkey_TSC = (DOT11_GKEY_TSC *)data->pointer; struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); struct wifi_mib *pmib = priv->pmib; pGkey_TSC->EventId = DOT11_EVENT_GKEY_TSC; pGkey_TSC->IsMoreEvent = FALSE; // Fix bug of getting RSC for auth (should consider endian issue) //memcpy((void *)pGkey_TSC->KeyTSC, // (void *)&(pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48.val48), 6); pGkey_TSC->KeyTSC[0] = pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC0; pGkey_TSC->KeyTSC[1] = pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC1; pGkey_TSC->KeyTSC[2] = pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC2; pGkey_TSC->KeyTSC[3] = pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC3; pGkey_TSC->KeyTSC[4] = pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC4; pGkey_TSC->KeyTSC[5] = pmib->dot11GroupKeysTable.dot11EncryptKey.dot11TXPN48._byte_.TSC5; pGkey_TSC->KeyTSC[6] = 0x00; pGkey_TSC->KeyTSC[7] = 0x00; return 0; } static int DOT11_Porcess_EAPOL_MICReport(struct net_device *dev, struct iw_point *data) { #ifdef _DEBUG_RTL8192CD_ struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); #endif struct stat_info *pstat = NULL; #ifdef _SINUX_ DOT11_MIC_FAILURE *MIC_Failure = (DOT11_MIC_FAILURE *)data->pointer; printk("MIC fail report from 802.1x daemon\n"); printk("mac: %02x%02x%02x%02x%02x%02x\n", MIC_Failure->MACAddr[0], MIC_Failure->MACAddr[1], MIC_Failure->MACAddr[2], MIC_Failure->MACAddr[3], MIC_Failure->MACAddr[4], MIC_Failure->MACAddr[5]); mic_error_report(1); #else //DOT11_MIC_FAILURE *MIC_Failure = (DOT11_MIC_FAILURE *)data->pointer; DEBUG_INFO("MIC fail report from 802.1x daemon\n"); //DEBUG_INFO("mac: %02x%02x%02x%02x%02x%02x\n", MIC_Failure->MACAddr[0], MIC_Failure->MACAddr[1], //MIC_Failure->MACAddr[2], MIC_Failure->MACAddr[3], MIC_Failure->MACAddr[4], MIC_Failure->MACAddr[5]); #endif #ifdef RTL_WPA2 PRINT_INFO("%s: DOT11_Indicate_MIC_Failure \n", (char *)__FUNCTION__); #endif DOT11_Indicate_MIC_Failure(dev, pstat); return 0; } #ifdef CONFIG_PCI_HCI static inline #endif int __DOT11_Indicate_MIC_Failure(struct net_device *dev, struct stat_info *pstat) { struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); struct stat_info *pstat_del; DOT11_MIC_FAILURE Mic_Failure; DOT11_DISASSOCIATION_IND Disassociation_Ind; int i; if (priv->pshare->skip_mic_chk || ((priv->ext_stats.tx_avarage + priv->ext_stats.rx_avarage) > (1024*1024/8))) return 0; // Indicate to upper layer if (pstat != NULL) // if pstat==NULL, it is called by upper layer { DEBUG_INFO("MIC error indicate to 1x in driver\n"); //DEBUG_INFO("mac: %02x%02x%02x%02x%02x%02x\n", pstat->hwaddr[0], pstat->hwaddr[1], //pstat->hwaddr[2], pstat->hwaddr[3], pstat->hwaddr[4], pstat->hwaddr[5]); #ifdef __DRAYTEK_OS__ cb_tkip_micFailure(dev, pstat->hwaddr); return 0; #endif #if !defined(WITHOUT_ENQUEUE) && (!defined(RTK_NL80211) || defined(NON_NL80211_AP)) Mic_Failure.EventId = DOT11_EVENT_MIC_FAILURE; Mic_Failure.IsMoreEvent = 0; memcpy(&Mic_Failure.MACAddr, pstat->hwaddr, MACADDRLEN); DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (UINT8 *)&Mic_Failure, sizeof(DOT11_MIC_FAILURE)); #endif #ifdef INCLUDE_WPA_PSK psk_indicate_evt(priv, DOT11_EVENT_MIC_FAILURE, pstat->hwaddr, NULL, 0); #endif #ifdef WIFI_HAPD event_indicate_hapd(priv, pstat->hwaddr, HAPD_MIC_FAILURE, NULL); #ifdef HAPD_DRV_PSK_WPS event_indicate(priv, pstat->hwaddr, 5); #endif #else event_indicate(priv, pstat->hwaddr, 5); #endif #if 0//def WIFI_WPAS //_Eric ?? event_indicate_wpas(priv, pstat->hwaddr, WPAS_MIC_FAILURE, NULL); #endif } if (priv->MIC_timer_on) { // Second time to detect MIC error in a time period // Stop Timer (fill a timer before than now) if (timer_pending(&priv->MIC_check_timer)) del_timer_sync(&priv->MIC_check_timer); priv->MIC_timer_on = FALSE; // Start Timer to reject assocaiton request from STA, and reject all the packet mod_timer(&priv->assoc_reject_timer, jiffies + REJECT_ASSOC_PERIOD); priv->assoc_reject_on = TRUE; for(i=0; ipshare->aidarray[i] && (priv->pshare->aidarray[i]->used == TRUE) #ifdef WDS && !(priv->pshare->aidarray[i]->station.state & WIFI_WDS) #endif ) { #if defined(UNIVERSAL_REPEATER) || defined(MBSSID) if (priv != priv->pshare->aidarray[i]->priv) continue; #endif pstat_del = &(priv->pshare->aidarray[i]->station); if (!list_empty(&pstat_del->asoc_list)) { #ifdef _SINUX_ printk("Second time to detect MIC error in a time period so disassociate the all client\n"); mic_error_report(2); #endif #ifndef WITHOUT_ENQUEUE memcpy((void *)Disassociation_Ind.MACAddr, (void *)pstat_del->hwaddr, MACADDRLEN); Disassociation_Ind.EventId = DOT11_EVENT_DISASSOCIATION_IND; Disassociation_Ind.IsMoreEvent = 0; Disassociation_Ind.Reason = _STATS_OTHER_; Disassociation_Ind.tx_packets = pstat_del->tx_pkts; Disassociation_Ind.rx_packets = pstat_del->rx_pkts; Disassociation_Ind.tx_bytes = pstat_del->tx_bytes; Disassociation_Ind.rx_bytes = pstat_del->rx_bytes; DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (UINT8 *)&Disassociation_Ind, sizeof(DOT11_DISASSOCIATION_IND)); #endif #if defined(INCLUDE_WPA_PSK) psk_indicate_evt(priv, DOT11_EVENT_DISASSOCIATION_IND, pstat_del->hwaddr, NULL, 0); #elif defined(WIFI_HAPD) || defined(RTK_NL80211) nl80211_psk_indicate_evt(priv, DOT11_EVENT_DISASSOCIATION_IND, pstat_del->hwaddr, NULL, 0); #endif #if defined(RTK_NL80211) && !defined(NON_NL80211_AP) event_indicate_cfg80211(priv, pstat_del->hwaddr, CFG80211_DEL_STA, NULL); #elif defined(WIFI_HAPD) event_indicate_hapd(priv, pstat_del->hwaddr, HAPD_EXIRED, NULL); #ifdef HAPD_DRV_PSK_WPS event_indicate(priv, pstat_del->hwaddr, 2); #endif #else event_indicate(priv, pstat_del->hwaddr, 2); #endif issue_disassoc(priv, pstat_del->hwaddr, _RSON_MIC_FAILURE_); } free_stainfo(priv, pstat_del); } } priv->assoc_num = 0; if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) { priv->pmib->dot11ErpInfo.nonErpStaNum = 0; check_protection_shortslot(priv); priv->pmib->dot11ErpInfo.longPreambleStaNum = 0; } if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) priv->ht_legacy_sta_num = 0; // ToDo: Should we delete group key? #ifdef _SINUX_ printk("-------------------------------------------------------\n"); printk("Second time of MIC failure in a time period \n"); printk("-------------------------------------------------------\n"); #else DEBUG_INFO("-------------------------------------------------------\n"); DEBUG_INFO("Second time of MIC failure in a time period \n"); DEBUG_INFO("-------------------------------------------------------\n"); #endif } else { // First time to detect MIC error, start the timer mod_timer(&priv->MIC_check_timer, jiffies + MIC_TIMER_PERIOD); priv->MIC_timer_on = TRUE; DEBUG_INFO("-------------------------------------------------------\n"); DEBUG_INFO("First time of MIC failure in a time period, start timer\n"); DEBUG_INFO("-------------------------------------------------------\n"); } return 0; } int DOT11_Indicate_MIC_Failure(struct net_device *dev, struct stat_info *pstat) { #if defined(CONFIG_PCI_HCI) return __DOT11_Indicate_MIC_Failure(dev, pstat); #elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) notify_indicate_MIC_failure(dev, pstat); return 0; #endif } void DOT11_Process_MIC_Timerup(unsigned long data) { struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)data; if (!(priv->drv_state & DRV_STATE_OPEN)) return; DEBUG_INFO("MIC Timer is up. Cancel Timer\n"); priv->MIC_timer_on = FALSE; } void DOT11_Process_Reject_Assoc_Timerup(unsigned long data) { struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)data; if (!(priv->drv_state & DRV_STATE_OPEN)) return; DEBUG_INFO("Reject Association Request Timer is up. Cancel Timer\n"); memset(priv->assoc_reject_mac,0,MACADDRLEN); #ifdef CLIENT_MODE if (OPMODE & WIFI_STATION_STATE) start_clnt_lookup(priv, 0); #endif priv->assoc_reject_on = FALSE; } #ifdef CONFIG_PCI_HCI static inline #endif void __DOT11_Indicate_MIC_Failure_Clnt(struct rtl8192cd_priv *priv, unsigned char *sa) { DOT11_MIC_FAILURE Mic_Failure; struct stat_info *pstat_del; DOT11_DISASSOCIATION_IND Disassociation_Ind; // int i; #ifndef WITHOUT_ENQUEUE Mic_Failure.EventId = DOT11_EVENT_MIC_FAILURE; Mic_Failure.IsMoreEvent = 0; memcpy(&Mic_Failure.MACAddr, sa, MACADDRLEN); DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (UINT8 *)&Mic_Failure, sizeof(DOT11_MIC_FAILURE)); #endif #if defined(INCLUDE_WPA_PSK) && !defined(NON_NL80211_AP) && !defined(WIFI_WPAS_CLI) if (OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) psk_indicate_evt(priv, DOT11_EVENT_MIC_FAILURE, BSSID, NULL, 0); #endif #if defined(RTK_NL80211) && !defined(NON_NL80211_WPAS) event_indicate_cfg80211(priv, sa, CFG80211_MIC_FAILURE, NULL); #elif defined(WIFI_WPAS) event_indicate_wpas(priv, sa, WPAS_MIC_FAILURE, NULL); #else event_indicate(priv, sa, 5); #endif if (priv->MIC_timer_on) { // Second time to detect MIC error in a time period // Stop Timer (fill a timer before than now) if (timer_pending(&priv->MIC_check_timer)) del_timer_sync(&priv->MIC_check_timer); priv->MIC_timer_on = FALSE; // Start Timer to reject assocaiton request from STA, and reject all the packet mod_timer(&priv->assoc_reject_timer, jiffies + REJECT_ASSOC_PERIOD); priv->assoc_reject_on = TRUE; memcpy(priv->assoc_reject_mac, BSSID, MACADDRLEN); pstat_del = get_stainfo(priv, BSSID); memcpy((void *)Disassociation_Ind.MACAddr, (void *)pstat_del->hwaddr, MACADDRLEN); DEBUG_INFO("%s() disassoc %02X:%02X:%02X:%02X:%02X:%02X\n",__func__,pstat_del->hwaddr[0],pstat_del->hwaddr[1],pstat_del->hwaddr[2],pstat_del->hwaddr[3],pstat_del->hwaddr[4],pstat_del->hwaddr[5]); Disassociation_Ind.EventId = DOT11_EVENT_DISASSOCIATION_IND; Disassociation_Ind.IsMoreEvent = 0; Disassociation_Ind.Reason = _STATS_OTHER_; Disassociation_Ind.tx_packets = pstat_del->tx_pkts; Disassociation_Ind.rx_packets = pstat_del->rx_pkts; Disassociation_Ind.tx_bytes = pstat_del->tx_bytes; Disassociation_Ind.rx_bytes = pstat_del->rx_bytes; DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (UINT8 *)&Disassociation_Ind, sizeof(DOT11_DISASSOCIATION_IND)); /* * To make sure the MIC Failure Report is sent before disassoc */ delay_ms(20); issue_disassoc(priv, pstat_del->hwaddr, _RSON_MIC_FAILURE_); free_stainfo(priv, pstat_del); priv->assoc_num = 0; if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) { priv->pmib->dot11ErpInfo.nonErpStaNum = 0; check_protection_shortslot(priv); priv->pmib->dot11ErpInfo.longPreambleStaNum = 0; } if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) priv->ht_legacy_sta_num = 0; DEBUG_INFO("-------------------------------------------------------\n"); DEBUG_INFO("Second time of MIC failure in a time period \n"); DEBUG_INFO("-------------------------------------------------------\n"); } else { // First time to detect MIC error, start the timer mod_timer(&priv->MIC_check_timer, jiffies + MIC_TIMER_PERIOD); priv->MIC_timer_on = TRUE; DEBUG_INFO("-------------------------------------------------------\n"); DEBUG_INFO("First time of MIC failure in a time period, start timer\n"); DEBUG_INFO("-------------------------------------------------------\n"); } } void DOT11_Indicate_MIC_Failure_Clnt(struct rtl8192cd_priv *priv, unsigned char *sa) { #if defined(WIFI_WPAS_CLI) event_indicate_wpas(priv, sa, WPAS_MIC_FAILURE, NULL); #elif defined(CONFIG_PCI_HCI) __DOT11_Indicate_MIC_Failure_Clnt(priv, sa); #elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) notify_indicate_MIC_failure_clnt(priv, sa); #endif } #ifdef RADIUS_ACCOUNTING void DOT11_Process_Acc_SetExpiredTime(struct net_device *dev, struct iw_point *data) { struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); //WLAN_CTX *wCtx = (WLAN_CTX *) ( priv->pwlanCtx ); DOT11_SET_EXPIREDTIME *Set_ExpireTime = (DOT11_SET_EXPIREDTIME *)data->pointer; struct stat_info *pstat=NULL; if( Set_ExpireTime != NULL ){ Set_ExpireTime->EventId = DOT11_EVENT_ACC_SET_EXPIREDTIME; Set_ExpireTime->IsMoreEvent = 0; if( (pstat = get_stainfo(priv, Set_ExpireTime->MACAddr)) ){ pstat->def_expired_time = Set_ExpireTime->ExpireTime; DEBUG_INFO("%s: Set %02x:%02x:%02x:%02x:%02x:%02x def_expired_time = %ld!\n", (char *)__FUNCTION__, pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5], Set_ExpireTime->ExpireTime); } else{ DEBUG_ERR("%s: ERRO, CAN NOT GET STA INFO!\n", (char *)__FUNCTION__); } } else{ DEBUG_ERR("%s: NULL POINTER!\n", (char *)__FUNCTION__); } } void DOT11_Process_Acc_QueryStats(struct net_device *dev, struct iw_point *data) { struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); //WLAN_CTX *wCtx = (WLAN_CTX *) ( priv->pwlanCtx ); struct stat_info *pstat=NULL; DOT11_QUERY_STATS *pStats = (DOT11_QUERY_STATS *)data->pointer; if( pStats != NULL ){ pStats->EventId = DOT11_EVENT_ACC_QUERY_STATS; pStats->IsMoreEvent = 0; if( (pstat = get_stainfo(priv, pStats->MACAddr)) ){ pStats->tx_packets = pstat->tx_pkts; pStats->rx_packets = pstat->rx_pkts; pStats->tx_bytes = pstat->tx_bytes; pStats->rx_bytes = pstat->rx_bytes; pStats->IsSuccess = TRUE; DEBUG_INFO("%s: Get %02x:%02x:%02x:%02x:%02x:%02x stats!\n", (char *)__FUNCTION__, pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5]); } else{ pStats->IsSuccess = FALSE; DEBUG_ERR("%s: ERROR, CAN NOT GET STA INFO!\n", (char *)__FUNCTION__); } } else{ DEBUG_ERR("%s: NULL POINTER!\n", (char *)__FUNCTION__); } } //------------------------- //DOT11_QUERY_STATS stats[RTL_AP_MAX_STA_NUM+1]; //data->pointer = (unsigned char *)stats; void DOT11_Process_Acc_QueryStats_All(struct net_device *dev, struct iw_point *data) { struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); struct list_head *phead=NULL, *plist=NULL; struct stat_info *pstat=NULL; //WLAN_CTX *wCtx = (WLAN_CTX *) ( priv->pwlanCtx ); DOT11_QUERY_STATS *pStats = (DOT11_QUERY_STATS *)data->pointer; //int i; int cnt = 0; #ifdef SMP_SYNC unsigned long flags=0; #endif if( pStats != NULL ){ phead = &priv->asoc_list; SMP_LOCK_ASOC_LIST(flags); plist = phead->next; while (plist != phead) { pstat = list_entry(plist, struct stat_info, asoc_list); plist = plist->next; pStats[cnt].EventId = DOT11_EVENT_ACC_QUERY_STATS_ALL; pStats[cnt].IsMoreEvent = 0; memcpy( pStats[cnt].MACAddr, pstat->hwaddr, MACADDRLEN ); pStats[cnt].tx_packets = pstat->tx_pkts; pStats[cnt].rx_packets = pstat->rx_pkts; pStats[cnt].tx_bytes = pstat->tx_bytes; pStats[cnt].rx_bytes = pstat->rx_bytes; cnt++; } SMP_UNLOCK_ASOC_LIST(flags); } else{ printk("%s: NULL POINTER!\n", (char *)__FUNCTION__); } } #endif static int DOT11_Process_STA_Query_Bssid(struct net_device *dev, struct iw_point *data) { DOT11_STA_QUERY_BSSID *pQuery = (DOT11_STA_QUERY_BSSID *)data->pointer; struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); pQuery->EventId = DOT11_EVENT_STA_QUERY_BSSID; pQuery->IsMoreEvent = FALSE; if ((OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) == (WIFI_STATION_STATE | WIFI_ASOC_STATE)) { pQuery->IsValid = TRUE; memcpy(pQuery->Bssid, BSSID, 6); } else pQuery->IsValid = FALSE; return 0; } static int DOT11_Process_STA_Query_Ssid(struct net_device *dev, struct iw_point *data) { DOT11_STA_QUERY_SSID *pQuery = (DOT11_STA_QUERY_SSID *)data->pointer; struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); pQuery->EventId = DOT11_EVENT_STA_QUERY_SSID; pQuery->IsMoreEvent = FALSE; if ((OPMODE & (WIFI_STATION_STATE | WIFI_ASOC_STATE)) == (WIFI_STATION_STATE | WIFI_ASOC_STATE)) { pQuery->IsValid = TRUE; memcpy(pQuery->ssid, SSID, 32); pQuery->ssid_len = SSID_LEN; } else pQuery->IsValid = FALSE; return 0; } #ifdef WIFI_SIMPLE_CONFIG static int DOT11_WSC_set_ie(struct net_device *dev, struct iw_point *data) { struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); DOT11_SET_RSNIE *Set_RSNIE = (DOT11_SET_RSNIE *)data->pointer; if (Set_RSNIE->Flag == SET_IE_FLAG_BEACON) { DEBUG_INFO("WSC: set beacon IE\n"); priv->pmib->wscEntry.beacon_ielen = Set_RSNIE->RSNIELen; memcpy((void *)priv->pmib->wscEntry.beacon_ie, Set_RSNIE->RSNIE, Set_RSNIE->RSNIELen); #ifdef SDIO_AP_OFFLOAD { #define TAG_SELECTED_REGISTRAR 0x1041 int attr_len; if (search_wsc_tag(Set_RSNIE->RSNIE+6, TAG_SELECTED_REGISTRAR, Set_RSNIE->RSNIELen-6, &attr_len)) // found ap_offload_deactivate(priv, OFFLOAD_PROHIBIT_WPS); else ap_offload_activate(priv, OFFLOAD_PROHIBIT_WPS); } #endif // SDIO_AP_OFFLOAD } else if (Set_RSNIE->Flag == SET_IE_FLAG_PROBE_RSP) { DEBUG_INFO("WSC: set probe response IE\n"); priv->pmib->wscEntry.probe_rsp_ielen = Set_RSNIE->RSNIELen; memcpy((void *)priv->pmib->wscEntry.probe_rsp_ie, Set_RSNIE->RSNIE, Set_RSNIE->RSNIELen); } else if (Set_RSNIE->Flag == SET_IE_FLAG_PROBE_REQ) { DEBUG_INFO("WSC: set probe request IE\n"); priv->pmib->wscEntry.probe_req_ielen = Set_RSNIE->RSNIELen; memcpy((void *)priv->pmib->wscEntry.probe_req_ie, Set_RSNIE->RSNIE, Set_RSNIE->RSNIELen); } else if (Set_RSNIE->Flag == SET_IE_FLAG_ASSOC_REQ || Set_RSNIE->Flag == SET_IE_FLAG_ASSOC_RSP) { DEBUG_INFO("WSC: set assoc IE\n"); priv->pmib->wscEntry.assoc_ielen = Set_RSNIE->RSNIELen; memcpy((void *)priv->pmib->wscEntry.assoc_ie, Set_RSNIE->RSNIE, Set_RSNIE->RSNIELen); } #if 0 else if (Set_RSNIE->Flag == 3) { printk("WSC: set RSN IE\n"); priv->pmib->dot11RsnIE.rsnielen = Set_RSNIE->RSNIELen; memcpy((void *)priv->pmib->dot11RsnIE.rsnie, Set_RSNIE->RSNIE, Set_RSNIE->RSNIELen); } #endif else { DEBUG_ERR("Invalid flag of set IE [%d]!\n", Set_RSNIE->Flag); } #ifdef PCIE_POWER_SAVING if ((Set_RSNIE->Flag == SET_IE_FLAG_BEACON) || (Set_RSNIE->Flag == SET_IE_FLAG_PROBE_RSP)) PCIeWakeUp(priv, (POWER_DOWN_T0)); #endif return 0; } #ifdef INCLUDE_WPS #ifndef CONFIG_MSC static int dispatch_wscsoap(struct rtl8192cd_priv *priv ,pDOT11_WSC_SOAP soap) { struct WSC_packet *packet=NULL; printk("\nWlan Driver receive SOAP request:%s\n",soap->action); packet = &soap->packet; if( strcmp(soap->action,"WFAGetDeviceInfo") ){ packet->EventType = WSC_NOT_PROXY; packet->EventID = WSC_GETDEVINFO; } else if ( strcmp(soap->action,"SendMsgToSM_Dir_In") ){ packet->EventID = WSC_SETSELECTEDREGISTRA; } else if ( strcmp(soap->action,"SendMsgToSM_Dir_InOut") ){ packet->EventID = WSC_M2M4M6M8; } else if ( strcmp(soap->action,"WFAPutWLANResponse") ) { packet->EventID = WSC_PUTWLANRESPONSE; } #ifdef SUPPORT_UPNP if (PWSCUpnpCallbackEventHandler(packet) != WSC_UPNP_SUCCESS) { DEBUG_ERR("WSCCallBack Fail!\n"); goto error_handle; } #endif return 0; error_handle: return -1; } #endif #endif #endif // WIFI_SIMPLE_CONFIG #ifdef USER_ADDIE static int DOT11_USER_set_ie(struct net_device *dev, struct iw_point *data) { struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); DOT11_SET_USERIE *Set_USERIE = (DOT11_SET_USERIE *)data->pointer; unsigned int i; if (Set_USERIE->Flag == SET_IE_FLAG_INSERT) { DEBUG_INFO("USER: add beacon IE\n"); for (i=0; iuser_ie_list[i].used) break; } if (i == MAX_USER_IE) return -1; priv->user_ie_list[i].used = 1; priv->user_ie_list[i].ie_len = Set_USERIE->USERIELen; memcpy((void *)priv->user_ie_list[i].ie, Set_USERIE->USERIE, Set_USERIE->USERIELen); } else if (Set_USERIE->Flag == SET_IE_FLAG_DELETE) { DEBUG_INFO("USER: remove beacon IE\n"); for (i=0; iuser_ie_list[i].used && !memcmp(priv->user_ie_list[i].ie, Set_USERIE->USERIE, Set_USERIE->USERIELen)) { priv->user_ie_list[i].used = 0; break; } } if (i == MAX_USER_IE) return -1; } else { DEBUG_ERR("Invalid flag of set IE [%d]!\n", Set_USERIE->Flag); } return 0; } #endif #ifdef CONFIG_IEEE80211W static int DOT11_PMF_set_ie(struct net_device *dev, struct iw_point *data) { struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); struct stat_info *pstat; DOT11_SET_11W_Flags flags; if (!memcpy((void *)(&flags),(void *)(data->pointer), data->length)) { PMFDEBUG("memcpy fail!, data=%x, length=%d\n", data->pointer, data->length); return -1; } pstat= get_stainfo(priv,flags.macAddr); if (!pstat) { //PMFDEBUG("psta is NULL\n"); } else { pstat->isPMF = flags.isPMF; PMFDEBUG("set sta[%02x%02x%02x:%02x%02x%02x]'s PMF=[%d]\n",pstat->hwaddr[0],pstat->hwaddr[1],pstat->hwaddr[2],pstat->hwaddr[3],pstat->hwaddr[4],pstat->hwaddr[5], flags.isPMF); } return 0; } #endif #ifdef HS2_SUPPORT /* Hotspot 2.0 Release 1*/ static int DOT11_HS2_set_ie(struct net_device *dev, struct iw_point *data) { struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); DOT11_SET_RSNIE *Set_RSNIE = (DOT11_SET_RSNIE *)data->pointer; HS2_DEBUG_INFO("HS2 set ie, flag=%d\n",Set_RSNIE->Flag); if (Set_RSNIE->Flag == SET_IE_FLAG_INTERWORKING) { //DEBUG_INFO HS2_DEBUG_TRACE(1, "HS2: set interworking IE,%x,%x\n",Set_RSNIE->RSNIE[0], Set_RSNIE->RSNIE[1]); priv->pmib->hs2Entry.interworking_ielen = Set_RSNIE->RSNIELen; memcpy((void *)priv->pmib->hs2Entry.interworking_ie, Set_RSNIE->RSNIE, Set_RSNIE->RSNIELen); } else if (Set_RSNIE->Flag == SET_IE_FLAG_ADVT_PROTO) { HS2_DEBUG_TRACE(1, "HS2: set advt proto IE\n"); priv->pmib->hs2Entry.advt_proto_ielen = Set_RSNIE->RSNIELen; memcpy((void *)priv->pmib->hs2Entry.advt_proto_ie, Set_RSNIE->RSNIE, Set_RSNIE->RSNIELen); } else if (Set_RSNIE->Flag == SET_IE_FLAG_ROAMING) { HS2_DEBUG_TRACE(1, "HS2: set roaming IE\n"); priv->pmib->hs2Entry.roam_ielen = Set_RSNIE->RSNIELen; memcpy((void *)priv->pmib->hs2Entry.roam_ie, Set_RSNIE->RSNIE, Set_RSNIE->RSNIELen); } else if (Set_RSNIE->Flag == SET_IE_FLAG_HS2) { HS2_DEBUG_TRACE(1, "HS2: set HS2 IE\n"); priv->pmib->hs2Entry.hs2_ielen = Set_RSNIE->RSNIELen; memcpy((void *)priv->pmib->hs2Entry.hs2_ie, Set_RSNIE->RSNIE, Set_RSNIE->RSNIELen); if (priv->pmib->hs2Entry.hs2_ie[4] & 0x01) { HS2_DEBUG_TRACE(1, "dgaf enable\n"); priv->dgaf_disable = 1; } else { HS2_DEBUG_TRACE(1, "dgaf disable\n"); priv->dgaf_disable = 0; } //channel utilization init_timer(&priv->cu_cntdwn_timer); priv->cu_cntdwn_timer.data = (unsigned long) priv; priv->cu_cntdwn_timer.function = rtl8192cd_cu_cntdwn_timer; priv->cu_cntdwn = priv->cu_initialcnt = (priv->pmib->hs2Entry.channel_utili_beaconIntval * priv->pmib->dot11StationConfigEntry.dot11BeaconPeriod)/CU_Intval; start_bbp_ch_load(priv, 50000); priv->cu_cntdwn_timer.expires = jiffies + CU_TO; mod_timer(&priv->cu_cntdwn_timer, jiffies + CU_TO); } else if (Set_RSNIE->Flag == SET_IE_FLAG_TIMEADVT) { HS2_DEBUG_TRACE(1, "HS2: set timeadvt IE\n"); priv->pmib->hs2Entry.timeadvt_ielen = Set_RSNIE->RSNIELen; memcpy((void *)priv->pmib->hs2Entry.timeadvt_ie, Set_RSNIE->RSNIE, Set_RSNIE->RSNIELen); } else if (Set_RSNIE->Flag == SET_IE_FLAG_TIMEZONE) { HS2_DEBUG_TRACE(1, "HS2: set time zone IE\n"); priv->pmib->hs2Entry.timezone_ielen = Set_RSNIE->RSNIELen; memcpy((void *)priv->pmib->hs2Entry.timezone_ie, Set_RSNIE->RSNIE, Set_RSNIE->RSNIELen); } else if (Set_RSNIE->Flag == SET_IE_FLAG_PROXYARP) { priv->proxy_arp = *Set_RSNIE->RSNIE; HS2_DEBUG_INFO("\n\n\n\nproxy arp in driver=%d\n\n\n\n\n", priv->proxy_arp); } else if (Set_RSNIE->Flag == SET_IE_FLAG_ICMPv4ECHO) { priv->pmib->hs2Entry.ICMPv4ECHO = *Set_RSNIE->RSNIE; HS2_DEBUG_INFO("\n\n\n\nICMPv4ECHO in driver=%d\n\n\n\n\n", priv->pmib->hs2Entry.ICMPv4ECHO); } else if (Set_RSNIE->Flag == SET_IE_FLAG_MMPDULIMIT) { memcpy((void *)(&priv->pmib->hs2Entry.mmpdu_limit), Set_RSNIE->RSNIE, Set_RSNIE->RSNIELen); HS2_DEBUG_INFO("mmpdu_limit:%d\n",priv->pmib->hs2Entry.mmpdu_limit); } else { HS2_DEBUG_ERR("HS2: unknown ioctl flag\n"); } } #endif /*----------------------------------------------------------------------------- Most of the time, we don't have to worry about the racing condition of "event_queue" in wlan drivers, since all the queue/dequeue are handled in non-isr context. However, my guess is, someone always want to port these driver to fit different OS platform. At that time, please always keep in mind all the possilbe racing condition... That could be big disasters... ------------------------------------------------------------------------------*/ #if defined(CONFIG_RTL_KERNEL_MIPS16_WLAN) && defined(CONFIG_RTL8196C) __NOMIPS16 #endif int rtl8192cd_ioctl_priv_daemonreq(struct net_device *dev, struct iw_point *data) { int ret; #ifndef WITHOUT_ENQUEUE static UINT8 QueueData[MAXDATALEN]; int QueueDataLen; #elif defined(CONFIG_RTL_WAPI_SUPPORT) static UINT8 QueueData[MAXDATALEN]; int QueueDataLen; #endif UINT8 val8; DOT11_REQUEST req; struct rtl8192cd_priv *priv = GET_DEV_PRIV(dev); #if defined(INCLUDE_WPA_PSK) || defined(WIFI_HAPD) || defined(RTK_NL80211) memcpy((void *)&req, (void *)(data->pointer), sizeof(DOT11_REQUEST)); #else if (copy_from_user((void *)&req, (void *)(data->pointer), sizeof(DOT11_REQUEST))) { DEBUG_ERR("copy_from_user error!\n"); return -1; } #endif #ifdef INCLUDE_WPS DOT11_GETSET_MIB *getset_mib_t; #endif switch(req.EventId) { case DOT11_EVENT_NO_EVENT: break; #ifndef WITHOUT_ENQUEUE case DOT11_EVENT_REQUEST: if((ret = DOT11_DeQueue((unsigned long)priv, priv->pevent_queue, QueueData, &QueueDataLen)) != 0) { val8 = DOT11_EVENT_NO_EVENT; if (copy_to_user((void *)((unsigned long)(data->pointer)), &val8, 1)) { DEBUG_ERR("copy_to_user fail!\n"); return -1; } val8 = 0; if (copy_to_user((void *)((unsigned long)(data->pointer) + 1), &val8, 1)) { DEBUG_ERR("copy_to_user fail!\n"); return -1; } data->length = sizeof(DOT11_NO_EVENT); } else { QueueData[1] = (priv->pevent_queue->NumItem != 0)? 1 : 0; if (copy_to_user((void *)data->pointer, (void *)QueueData, QueueDataLen)) { DEBUG_ERR("copy_to_user fail!\n"); return -1; } data->length = QueueDataLen; } break; #ifdef INCLUDE_WPS case DOT11_EVENT_REQUEST_F_INCLUDE_WPS: if((ret = DOT11_DeQueue((unsigned long)priv, priv->pevent_queue, QueueData, &QueueDataLen)) != 0) { val8 = DOT11_EVENT_NO_EVENT; memcpy((void *)((unsigned long)(data->pointer)), &val8, 1); val8 = 0; memcpy((void *)((unsigned long)(data->pointer) + 1), &val8, 1); data->length = sizeof(DOT11_NO_EVENT); } else { QueueData[1] = (priv->pevent_queue->NumItem != 0)? 1 : 0; memcpy((void *)data->pointer, (void *)QueueData, QueueDataLen); data->length = QueueDataLen; //DEBUG_INFO("%d de-queue ; pMsg=%s\n", __LINE__ , (char *)data->pointer); } break; #endif #endif case DOT11_EVENT_ASSOCIATION_RSP: if(!DOT11_Process_Association_Rsp(dev, data, WIFI_ASSOCRSP)) {} break; case DOT11_EVENT_DISCONNECT_REQ: if(!DOT11_Process_Disconnect_Req(dev, data)) {} break; case DOT11_EVENT_SET_802DOT11: break; case DOT11_EVENT_SET_KEY: #if defined(CONFIG_PCI_HCI) if(!DOT11_Process_Set_Key(dev, data, NULL, NULL)) {} #elif defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) notify_set_key(dev, (DOT11_SET_KEY *)data->pointer, NULL); #endif break; case DOT11_EVENT_SET_PORT: if(!DOT11_Process_Set_Port(dev, data)) {} break; case DOT11_EVENT_DELETE_KEY: if(!DOT11_Process_Delete_Key(dev, data)) {} break; case DOT11_EVENT_SET_RSNIE: if(priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm != _NO_PRIVACY_ && priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm != _WEP_40_PRIVACY_ && priv->pmib->dot1180211AuthEntry.dot11PrivacyAlgrthm != _WEP_104_PRIVACY_) if(!DOT11_Process_Set_RSNIE(dev, data)) {} break; case DOT11_EVENT_GKEY_TSC: if(!DOT11_Process_QueryRSC(dev, data)) {} break; case DOT11_EVENT_MIC_FAILURE: if(!DOT11_Porcess_EAPOL_MICReport(dev, data)) {} break; case DOT11_EVENT_ASSOCIATION_INFO: #if 0 if(!DOT11_Process_Association_Info(dev, data)) {} #endif DEBUG_INFO("trying to process assoc info\n"); break; case DOT11_EVENT_INIT_QUEUE: DOT11_InitQueue(priv->pevent_queue); break; case DOT11_EVENT_ACC_SET_EXPIREDTIME: #ifdef RADIUS_ACCOUNTING DOT11_Process_Acc_SetExpiredTime(dev, data); #endif DEBUG_INFO("trying to Set ACC Expiredtime\n"); break; case DOT11_EVENT_ACC_QUERY_STATS: #ifdef RADIUS_ACCOUNTING DOT11_Process_Acc_QueryStats(dev, data); #endif DEBUG_INFO("trying to Set ACC Expiredtime\n"); break; case DOT11_EVENT_REASSOCIATION_RSP: if(!DOT11_Process_Association_Rsp(dev, data, WIFI_REASSOCRSP)) {} break; case DOT11_EVENT_STA_QUERY_BSSID: if(!DOT11_Process_STA_Query_Bssid(dev, data)) {}; break; case DOT11_EVENT_STA_QUERY_SSID: if(!DOT11_Process_STA_Query_Ssid(dev, data)) {}; break; #ifdef WIFI_SIMPLE_CONFIG case DOT11_EVENT_WSC_SET_IE: if(!DOT11_WSC_set_ie(dev, data)) {}; break; #ifdef INCLUDE_WPS #ifndef CONFIG_MSC // procress ioctl request from upnp case DOT11_EVENT_WSC_SOAP:{ CTX_Tp tmp = &(priv->pshare->WSC_CONT_S); DOT11_WSC_SOAP *soap_evt; //chris 0328 DOT11_EAP_PACKET *upnp_pkt; //chris 0328 struct soap_t *soap_pkt; //chris 0328 soap_evt = (DOT11_WSC_SOAP *) kmalloc(sizeof(DOT11_WSC_SOAP), GFP_ATOMIC); upnp_pkt = (DOT11_EAP_PACKET *) kmalloc(sizeof(DOT11_EAP_PACKET), GFP_ATOMIC); soap_pkt = (struct soap_t *) kmalloc(sizeof(struct soap_t), GFP_ATOMIC); memset(soap_evt, 0, sizeof(DOT11_WSC_SOAP)); memset(upnp_pkt, 0, sizeof(DOT11_EAP_PACKET)); memset(soap_pkt, 0, sizeof(struct soap_t)); if (copy_from_user((void *)soap_evt, (void *)(data->pointer), sizeof(DOT11_WSC_SOAP))) { //DEBUG_ERR("copy_from_user error!\n"); printk("copy_from_user error!\n"); kfree(soap_evt); kfree(upnp_pkt); kfree(soap_pkt); return -1; } memcpy(soap_pkt->EventMac, soap_evt->packet.EventMac, MACLEN); memcpy(soap_pkt->IP, soap_evt->packet.IP, IP_ADDRLEN); memcpy(soap_pkt->packet, soap_evt->packet.buffer, soap_evt->packet.size); soap_pkt->length = soap_evt->packet.size; if( soap_evt->packet.EventID == WSC_GETDEVINFO ){ upnp_pkt->EventId = DOT11_EVENT_WSC_GETDEVINFO; tmp->wps_profile.soap_mathods.upnpGetDeviceInfoHandler(soap_pkt); printk("%s %d ; call upnpGetDeviceInfoHandler\n",__FUNCTION__,__LINE__); }else if ( soap_evt->packet.EventID == WSC_M2M4M6M8 ) { upnp_pkt->EventId = DOT11_EVENT_WSC_M2M4M6M8; tmp->wps_profile.soap_mathods.upnpPutMessageHandler(soap_pkt); }else if ( soap_evt->packet.EventID == WSC_SETSELECTEDREGISTRA ) { upnp_pkt->EventId = DOT11_EVENT_WSC_PUTMESSAGE; tmp->wps_profile.soap_mathods.upnpSelectedRegistrarHandler(soap_pkt); }else if ( soap_evt->packet.EventID == WSC_PUTWLANRESPONSE ) { upnp_pkt->EventId = DOT11_EVENT_WSC_PUTWLANRESPONSE; tmp->wps_profile.soap_mathods.upnpWlanResponseHandler(soap_pkt); } upnp_pkt->IsMoreEvent = FALSE; /* if( packet.tx_size < MAX_MSG_SIZE ){ upnp_packet.packet_len = packet.tx_size; memcpy(upnp_packet.packet, packet.tx_buffer, packet.tx_size); } else { upnp_packet.packet_len = 0; }*/ if( soap_pkt->length > 0 && soap_pkt->length < MAX_MSG_SIZE ){ upnp_pkt->packet_len = soap_pkt->length; memcpy(upnp_pkt->packet, soap_pkt->packet, soap_pkt->length); } else { upnp_pkt->packet_len = 0; } printk("Rx ; En-Queue UPnP Packet %s %d \n",__FUNCTION__ , __LINE__); wsc_debug_out(">>>>>>>>>>>>>upnp_packet", upnp_pkt, sizeof(DOT11_EAP_PACKET)); DOT11_EnQueue((unsigned long)priv, priv->pevent_queue, (unsigned char*)upnp_pkt, sizeof(DOT11_EAP_PACKET)); event_indicate(priv, NULL, -1); kfree(soap_evt); kfree(upnp_pkt); kfree(soap_pkt); } break; case DOT11_EVENT_WSC_PIN:{ CTX_Tp tmp = &(priv->pshare->WSC_CONT_S); DOT11_WSC_METHOD wps_pin; if (copy_from_user((void *)&wps_pin, (void *)(data->pointer), sizeof(DOT11_WSC_PIN_IND))) { //DEBUG_ERR("copy_from_user error!\n"); printk("copy_from_user error!\n"); return -1; } tmp->start = 3; memcpy(tmp->peer_pin_code, wps_pin.code, PIN_LEN); //evHandler_pin_input(wps_pin.code); printk("PIN method invoked (from wscd)\n"); } break; case DOT11_EVENT_WSC_PBC:{ CTX_Tp tmp = &(priv->pshare->WSC_CONT_S); tmp->start = 2; //evHandler_pb_press(); printk("PBC method invoked from wscd\n"); } break; case DOT11_EVENT_WSC_PUTCONF:{ DOT11_WSC_GETCONF wps_getconf; CTX_Tp tmp = &(priv->pshare->WSC_CONT_S); memset(&wps_getconf,0,sizeof(DOT11_WSC_GETCONF)); WSC_CONFp wps_config = &(wps_getconf.config); if (copy_from_user((void *)&wps_getconf, (void *)(data->pointer), sizeof(WSC_CONF))) { DEBUG_ERR("copy_from_user error!\n"); return -1; } /* for verify ,wscd-deamon will report config-info at WSC_CONF call to kernel-mode-wps , receive_config_setting(); in sercomm case , will not via here,sercomm will direct call wps_start() */ printk("[wlan ioctl]:receive \"DOT11_EVENT_WSC_PUTCONF\" from wscd \n"); //receive_config_setting(priv , wps_config); read_config_file(tmp, DEFAULT_CONFIG_FILENAME); } break; case DOT11_EVENT_WSC_PROXY_ON: { printk("[%s] switch proxy on\n",__FUNCTION__); priv->pshare->WSC_CONT_S.TotalSubscriptions = 1; } break; case DOT11_EVENT_WSC_PROXY_OFF: { printk("[%s] switch proxy off\n",__FUNCTION__); priv->pshare->WSC_CONT_S.TotalSubscriptions = 0; } break; #endif #endif #ifdef INCLUDE_WPS case DOT11_EVENT_WSC_SET_MIB: getset_mib_t = (DOT11_GETSET_MIB *)data->pointer; set_mib(dev->priv, getset_mib_t->cmd); break; case DOT11_EVENT_WSC_GET_MIB: getset_mib_t = (DOT11_GETSET_MIB*)data->pointer; get_mib(dev->priv, getset_mib_t->cmd); break; #endif #endif //WIFI_SIMPLE_CONFIG #ifdef CONFIG_RTL_WAPI_SUPPORT case DOT11_EVENT_WAPI_INIT_QUEUE: DOT11_InitQueue(priv->wapiEvent_queue); break; case DOT11_EVENT_WAPI_READ_QUEUE: if((ret = DOT11_DeQueue((unsigned long)priv, priv->wapiEvent_queue, QueueData, &QueueDataLen)) != 0) { val8 = DOT11_EVENT_NO_EVENT; if (copy_to_user((void *)((unsigned long)(data->pointer)), &val8, 1)) { DEBUG_ERR("copy_to_user fail!\n"); return -1; } val8 = 0; if (copy_to_user((void *)((unsigned long)(data->pointer) + 1), &val8, 1)) { DEBUG_ERR("copy_to_user fail!\n"); return -1; } data->length = sizeof(DOT11_NO_EVENT); } else { QueueData[1] = (priv->wapiEvent_queue->NumItem != 0)? 1 : 0; if (copy_to_user((void *)data->pointer, (void *)QueueData, QueueDataLen)) { DEBUG_ERR("copy_to_user fail!\n"); return -1; } data->length = QueueDataLen; } break; case DOT11_EVENT_WAPI_WRITE_QUEUE: { unsigned char *kernelbuf; kernelbuf = (unsigned char *)kmalloc(data->length,GFP_ATOMIC); if(NULL == kernelbuf) { DEBUG_ERR("Memory alloc fail!\n"); return -1; } if (copy_from_user((void *)kernelbuf, (void *)(data->pointer), data->length)) { DEBUG_ERR("copy_from_user error!\n"); kfree(kernelbuf); return -1; } DOT11_Process_WAPI_Info(priv,kernelbuf,data->length); kfree(kernelbuf); } break; #endif #ifdef HS2_SUPPORT /* Hotsport 2.0 Release 1 */ case DOT11_EVENT_HS2_SET_IE: if(!DOT11_HS2_set_ie(dev, data)) {}; break; case DOT11_EVENT_HS2_GET_TSF: { unsigned long long tsf; unsigned long tsf_sec; tsf = RTL_R32(TSFTR+4); tsf = (tsf<<32) + RTL_R32(TSFTR); tsf_sec = (unsigned long)tsf/1000000; if (copy_to_user((void *)(data->pointer), &tsf_sec, sizeof(unsigned long))) { HS2_DEBUG_ERR("copy_to_user fail!\n"); return -1; } data->length = sizeof(unsigned long); } break; case DOT11_EVENT_HS2_GAS_RSP: issue_GASrsp(priv, data->pointer); break; case DOT11_EVENT_HS2_TSM_REQ: issue_BSS_TSM_req(priv, data->pointer); break; case DOT11_EVENT_HS2_GET_RSN: { struct wifi_mib *pmib; pmib = GET_MIB(priv); if (pmib->dot11RsnIE.rsnielen) { if (copy_to_user((void *)(data->pointer), pmib->dot11RsnIE.rsnie, pmib->dot11RsnIE.rsnielen)) { HS2_DEBUG_ERR("copy_to_user fail!\n"); return -1; } data->length = pmib->dot11RsnIE.rsnielen; } } break; case DOT11_EVENT_HS2_GET_MMPDULIMIT: { struct wifi_mib *pmib; pmib = GET_MIB(priv); if (copy_to_user((void *)(data->pointer), (void *)(&pmib->hs2Entry.mmpdu_limit), sizeof(unsigned int))) { HS2_DEBUG_ERR("copy_to_user fail!\n"); return -1; } data->length = sizeof(unsigned int); } break; #endif // HS2_SUPPORT #ifdef CONFIG_IEEE80211W /*HS2 R2 logo test*/ case DOT11_EVENT_INIT_PMF: { int i; DOT11_INIT_11W_Flags flags; if (copy_from_user((void *)(&flags),(void *)(data->pointer), data->length)) { PMFDEBUG("copy_from_user fail!\n"); return -1; } PMFDEBUG("init pmf:11W[%d],SHA256[%d]\n",flags.dot11IEEE80211W, flags.dot11EnableSHA256); priv->pmib->dot1180211AuthEntry.dot11IEEE80211W = flags.dot11IEEE80211W; priv->pmib->dot1180211AuthEntry.dot11EnableSHA256 = flags.dot11EnableSHA256; if(priv->pmib->dot1180211AuthEntry.dot11IEEE80211W == 0 && priv->pmib->dot1180211AuthEntry.dot11EnableSHA256) { priv->pmib->dot1180211AuthEntry.dot11EnableSHA256 = 0; panic_printk("disable SHA256 when PMF is disable\n"); } } case DOT11_EVENT_SET_PMF: if(!DOT11_PMF_set_ie(dev, data)) {} break; case DOT11_EVENT_GET_IGTK_PN: { struct wifi_mib *pmib; int i; unsigned char *tt; pmib = GET_MIB(priv); #ifdef PMF_DEBUGMSG PMFDEBUG("get IGTK_PN:"); tt = (unsigned char *) & pmib->dot11IGTKTable.dot11EncryptKey.dot11TXPN48; for (i=0;idot11IGTKTable.dot11EncryptKey.dot11TXPN48._byte_.TSC0 ,pmib->dot11IGTKTable.dot11EncryptKey.dot11TXPN48._byte_.TSC1 ,pmib->dot11IGTKTable.dot11EncryptKey.dot11TXPN48._byte_.TSC2 ,pmib->dot11IGTKTable.dot11EncryptKey.dot11TXPN48._byte_.TSC3 ,pmib->dot11IGTKTable.dot11EncryptKey.dot11TXPN48._byte_.TSC4 ,pmib->dot11IGTKTable.dot11EncryptKey.dot11TXPN48._byte_.TSC5); #endif #endif if (copy_to_user((void *)(data->pointer), (void *) (&pmib->dot11IGTKTable.dot11EncryptKey.dot11TXPN48.val48), sizeof(pmib->dot11IGTKTable.dot11EncryptKey.dot11TXPN48.val48))) { DEBUG_ERR("copy_to_user fail!\n"); return -1; } data->length = sizeof(pmib->dot11IGTKTable.dot11EncryptKey.dot11TXPN48.val48); } break; case DOT11_EVENT_SA_QUERY_RSP: { DOT11_SA_QUERY_RSP resp; if (copy_from_user((void *)(&resp),(void *)(data->pointer), data->length)) { DEBUG_ERR("copy_from_user fail!\n"); return -1; } issue_SA_Query_Rsp(dev, resp.MACAddr, resp.trans_id); } break; #endif // CONFIG_IEEE80211W #ifdef USER_ADDIE case DOT11_EVENT_USER_SETIE: { if(DOT11_USER_set_ie(dev, data) < 0) { DEBUG_ERR("DOT11_USER_set_ie failed\n"); return -1; }; } break; #endif default: DEBUG_ERR("unknown user daemon command\n"); break; } // switch(req->EventId) return 0; }