/**************************************************************************** * Ralink Tech Inc. * Taiwan, R.O.C. * * (c) Copyright 2002, Ralink Technology, Inc. * * All rights reserved. Ralink's source code is an unpublished work and the * use of a copyright notice does not imply otherwise. This source code * contains confidential trade secret material of Ralink Tech. Any attemp * or participation in deciphering, decoding, reverse engineering or in any * way altering the source code is stricitly prohibited, unless the prior * written consent of Ralink Technology, Inc. is obtained. ***************************************************************************/ /**************************************************************************** Abstract: All related IEEE802.11r Key Distribution Protocol (FT KDP) body. Overview: 1. A station associates to us, send out a broadcast ADD-Notify packet. ASSOC --> FT_KDP_EVENT_INFORM(FT_KDP_SIG_FT_ASSOCIATION) --> FT_KDP_EventInform(FT_KDP_SIG_FT_ASSOCIATION) --> Notify IAPP daemon, IAPP_RcvHandlerRawDrv(), IAPP_SIG_Process() --> Send ADD-Notify packet, IAPP_UDP_PacketSend(), IAPP_L2UpdateFrameSend() 2. When receiving a ADD-Notify packet, send a unicast SSB packet to request PMK-R1 key for the station with our R0KH. IAPP daemon, IAPP_RcvHandlerUdp() --> Notify driver, IAPP_MsgProcess() --> IOCTL, RTMPAPSetInformation() --> FT_KDP_StationInform() --> Notify IAPP daemon, FT_KDP_EventInform(FT_KDP_SIG_KEY_REQ_AUTO) --> Notify IAPP daemon, IAPP_RcvHandlerRawDrv(), IAPP_SIG_Process() --> Send SSB packet with R0KHID = 0, by using TCP or UDP based on peerIP 3. A station reassociates to us, send out a MOVE-Request packet. REASSOC --> FT_KDP_EVENT_INFORM(FT_KDP_SIG_FT_REASSOCIATION) --> FT_KDP_EventInform(FT_KDP_SIG_FT_REASSOCIATION) --> Notify IAPP daemon, IAPP_RcvHandlerRawDrv(), IAPP_SIG_Process() --> Send MOVE-Request packet by using TCP or UDP, IAPP_L2UpdateFrameSend() 4. When receiving a MOVE-Request packet, delete the STA MAC entry. IAPP daemon, IAPP_RcvHandlerUdp()/ IAPP_RcvHandlerTcp() --> Notify driver, IAPP_MsgProcess() --> IOCTL, RTMPAPSetInformation() --> RT_SET_DEL_MAC_ENTRY --> Send MOVE-Response packet by using TCP, FT_KDP_MoveFrameSend() 5. When receiving a MOVE-Response packet, nothing to do. 6. When receiving a SSB packet (i.e. key request), send a unicast SAB packet to response the key to the R1KH. IAPP daemon --> Notify driver, IAPP_MsgProcess() --> IOCTL, RTMPAPSetInformation() --> FT_KDP_IOCTL_KEY_REQ() --> Notify IAPP daemon, FT_KDP_EventInform(FT_KDP_SIG_KEY_RSP_AUTO) --> Send SAB packet with my R0KHID, FT_KDP_SecurityBlockSend() by using TCP 7. When receiving a SAB packet (i.e. key response), set the PMK-R1 key. IAPP daemon --> Notify driver, IAPP_MsgProcess() --> IOCTL, RTMPAPSetInformation() --> FT_KDP_KeyResponseToUs() 8. Send a information broadcast to the LAN periodically. ***************************************************************************/ #ifdef DOT11R_FT_SUPPORT #include "rt_config.h" #include "ft_cmm.h" #define TYPE_FUNC #define FT_KDP_DEBUG #define FT_KDP_FUNC_TEST /*#define FT_KDP_EMPTY */ /* empty codes to debug */ #define IAPP_SHOW_IP_HTONL(__IP) \ (htonl(__IP) >> 24) & 0xFF, \ (htonl(__IP) >> 16) & 0xFF, \ (htonl(__IP) >> 8) & 0xFF, \ (htonl(__IP) & 0xFF) #define IAPP_DAEMON_CMD_PARSE(__pInfo, __InfoLen, __PeerIP, __pData, __DataLen) \ NdisMoveMemory(&__PeerIP, __pInfo, FT_IP_ADDRESS_SIZE); \ __pData = (UCHAR *)(__pInfo + FT_IP_ADDRESS_SIZE); \ __DataLen = __InfoLen - FT_IP_ADDRESS_SIZE; /* private variable */ UINT32 FT_KDP_MemAllocNum, FT_KDP_MemFreeNum; /* extern variable */ #ifdef FT_KDP_FUNC_TEST extern UCHAR gFT_MAC_OldAP[]; #endif /* FT_KDP_FUNC_TEST */ /* private function prototype */ #ifdef FT_KDP_FUNC_R0KH_IP_RECORD BOOLEAN FT_KDP_R0KH_InfoAdd( IN PRTMP_ADAPTER pAd, IN UCHAR *pR0KHID, IN UCHAR *pMAC, IN UINT32 IP); VOID FT_KDP_R0KH_InfoDel( IN PRTMP_ADAPTER pAd, IN UCHAR *pR0KHID, IN UCHAR *pMAC, IN UINT32 IP); static BOOLEAN FT_KDP_R0KH_InfoGet( IN PRTMP_ADAPTER pAd, INOUT UCHAR *pR0KHID, INOUT UCHAR *pMAC, OUT UINT32 *pIP); #endif /* FT_KDP_FUNC_R0KH_IP_RECORD */ /* public function */ /* ======================================================================== Routine Description: Initialize FT KDP Module. Arguments: pAd - WLAN control block pointer Return Value: None Note: ======================================================================== */ VOID TYPE_FUNC FT_KDP_Init( IN PRTMP_ADAPTER pAd) { #ifndef FT_KDP_EMPTY if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 1) return; DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> Initialize FT KDP Module...\n")); /* allocate control block */ FT_MEM_ALLOC(pAd, &pAd->ApCfg.FtTab.pFT_KDP_Ctrl_BK, sizeof(FT_KDP_CTRL_BLOCK)); if (pAd->ApCfg.FtTab.pFT_KDP_Ctrl_BK == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> Allocate control block fail!\n")); return; } NdisAllocateSpinLock(pAd, &(pAd->ApCfg.FtTab.FT_KdpLock)); #ifndef FT_KDP_FUNC_SOCK_COMM /* init event list */ initList(&(FT_KDP_CB->EventList)); #endif /* FT_KDP_FUNC_SOCK_COMM */ #ifdef FT_KDP_FUNC_R0KH_IP_RECORD /* init R0KH information record */ FT_KDP_CB->R0KH_InfoHead = NULL; FT_KDP_CB->R0KH_InfoTail = NULL; FT_KDP_CB->R0KH_Size = 0; #endif /* FT_KDP_FUNC_R0KH_IP_RECORD */ #ifdef FT_KDP_FUNC_INFO_BROADCAST RTMPInitTimer(pAd, &FT_KDP_CB->TimerReport, GET_TIMER_FUNCTION(FT_KDP_InfoBroadcast), (PVOID)pAd, TRUE); RTMPSetTimer(&FT_KDP_CB->TimerReport, FT_KDP_INFO_BC_PERIOD_TIME); #endif /* FT_KDP_FUNC_INFO_BROADCAST */ #endif /* FT_KDP_EMPTY */ pAd->ApCfg.FtTab.FlgIsFtKdpInit = 1; } /* ======================================================================== Routine Description: Release FT KDP Module. Arguments: pAd - WLAN control block pointer Return Value: None Note: ======================================================================== */ VOID TYPE_FUNC FT_KDP_Release( IN PRTMP_ADAPTER pAd) { #ifndef FT_KDP_EMPTY #ifdef FT_KDP_FUNC_R0KH_IP_RECORD FT_KDP_R0KH_INFO *pInfoHead, *pInfo; #endif /* FT_KDP_FUNC_R0KH_IP_RECORD */ if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) return; DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> Release FT KDP Module...\n")); #ifndef FT_KDP_FUNC_SOCK_COMM /* free event list */ FT_KDP_EVT_LIST_EMPTY(pAd, &(FT_KDP_CB->EventList)); #endif /* FT_KDP_FUNC_SOCK_COMM */ #ifdef FT_KDP_FUNC_R0KH_IP_RECORD /* free all R0KH information */ pInfoHead = FT_KDP_CB->R0KH_InfoHead; while(pInfoHead != NULL) { pInfo = pInfoHead; pInfoHead = pInfoHead->pNext; FT_MEM_FREE(pAd, pInfo); } #endif /* FT_KDP_FUNC_R0KH_IP_RECORD */ if (pAd->ApCfg.FtTab.pFT_KDP_Ctrl_BK != NULL) { FT_MEM_FREE(pAd, pAd->ApCfg.FtTab.pFT_KDP_Ctrl_BK); pAd->ApCfg.FtTab.pFT_KDP_Ctrl_BK = NULL; } #ifdef FT_KDP_FUNC_INFO_BROADCAST { BOOLEAN Status; RTMPCancelTimer(&FT_KDP_CB->TimerReport, &Status); } #endif /* FT_KDP_FUNC_INFO_BROADCAST */ /* free spin lock */ NdisFreeSpinLock(&(pAd->ApCfg.FtTab.FT_KdpLock)); #endif /* FT_KDP_EMPTY */ pAd->ApCfg.FtTab.FlgIsFtKdpInit = 0; } /* ======================================================================== Routine Description: Inform us a event occurs. Arguments: pAd - WLAN control block pointer ApIdx - MBSS ID EventId - which event, such as FT_KDP_SIG_FT_ASSOCIATION *pEvent - event body EventLen - event body length PeerIP - peer IP address pCB - for special use (such as FT_KDP_SIG_ACTION) Return Value: None Note: EventId *pEvent -------------------------------------------------------------------- FT_KDP_SIG_FT_ASSOCIATION FT_KDP_EVT_ASSOC FT_KDP_SIG_FT_REASSOCIATION FT_KDP_EVT_REASSOC FT_KDP_SIG_KEY_TIMEOUT yet implement FT_KDP_SIG_KEY_REQ FT_KDP_EVT_KEY_ELM FT_KDP_SIG_ACTION WLAN Frame Body (Start from Category field) pCB == FT_KDP_EVT_ACTION ======================================================================== */ VOID TYPE_FUNC FT_KDP_EventInform( IN PRTMP_ADAPTER pAd, IN UINT32 ApIdx, IN UCHAR EventId, IN VOID *pEvent, IN UINT16 EventLen, IN UINT32 PeerIP, IN VOID *pCB) { #ifndef FT_KDP_EMPTY #ifndef FT_KDP_FUNC_SOCK_COMM POS_COOKIE pObj = (POS_COOKIE) pAd->OS_Cookie; UCHAR Size; #endif /* FT_KDP_FUNC_SOCK_COMM */ FT_KDP_SIGNAL *pFtKdp; FT_KDP_EVT_HEADER EvtHdr; if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) { DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); return; } #ifndef FT_KDP_FUNC_SOCK_COMM CHECK_PID_LEGALITY(pObj->IappPid) { /* valid, can do next step */ } else return; FT_KDP_EVT_LIST_SIZE_GET(pAd, &FT_KDP_CB->EventList, Size); if (Size > FT_KDP_EVENT_MAX) { DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Queued Events are too much!\n")); return; } #endif /* FT_KDP_FUNC_SOCK_COMM */ /* make up event content */ NdisZeroMemory(&EvtHdr, sizeof(FT_KDP_EVT_HEADER)); FT_MEM_ALLOC(pAd, &pFtKdp, sizeof(FT_KDP_SIGNAL)); if (pFtKdp == NULL) { DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Allocate signal content fail!\n")); return; } pFtKdp->Sig = EventId; /* handle different event */ switch(EventId) { case FT_KDP_SIG_FT_ASSOCIATION: { /* a station associates to us */ /* When a STA uses the 802.11 Association Request, rather than the Reassociation Request, the IAPP may not be able to notify the AP at which the STA was previously associated of the new association. */ FT_KDP_EVT_ASSOC *pEvtAssoc; pEvtAssoc = (FT_KDP_EVT_ASSOC *)pEvent; pFtKdp->Sequence = pEvtAssoc->SeqNum; NdisMoveMemory(pFtKdp->MacAddr, pEvtAssoc->MacAddr, MAC_ADDR_LEN); } break; case FT_KDP_SIG_FT_REASSOCIATION: { /* a station reassociates to us */ /* IEEE802.11f, 1.3 Inter-AP recommended practice overview In particular, the IAPP entity must be able to find and use a RADIUS server to look up the IP addresses of other APs in the ESS when given the Basic Service Set Identifier (BSSIDs) of those other APs (if a local capability to perform such a translation is not present), and to obtain security information to protect the content of certain IAPP packets. Here we dont use any Radius server so sometimes we can not send the MOVE-notify frame. */ /* The IAPP is not a routing protocol. The IAPP does not deal directly with the delivery of 802.11 data frames to the STA; instead the DS utilizes existing network functionality for data frame delivery. When a STA associates or reassociates, the STA must ascertain that its network layer address(es) is configured such that the normal routing functions of the network attaching to the BSS will correctly deliver the STA¡¦s traffic to the BSS to which it is associated. Two mechanisms for a STA to accomplish this are to renew a Dynamic Host Configuration Protocol (DHCP) lease for its IP address and to use Mobile IP to obtain a local IP address. */ FT_KDP_EVT_REASSOC *pEvtReAssoc; pEvtReAssoc = (FT_KDP_EVT_REASSOC *)pEvent; pFtKdp->Sequence = pEvtReAssoc->SeqNum; NdisMoveMemory(pFtKdp->MacAddr, pEvtReAssoc->MacAddr, MAC_ADDR_LEN); /* try to get the IP of old AP */ if (FT_KDP_R0KH_InfoGet(pAd, NULL, pEvtReAssoc->OldApMacAddr, &PeerIP) == FALSE) { #if 0 /* no IP so we can not send MOVE-REQ to the old AP */ FT_MEM_FREE(pAd, pFtKdp); DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Can not find the IP of old AP!\n")); return; #endif } } break; case FT_KDP_SIG_KEY_TIMEOUT: /* PMK-R1 Key timeout */ break; case FT_KDP_SIG_KEY_REQ: { FT_KDP_EVT_KEY_ELM *pEvtKeyReq; /* PMK-R1 Key Request */ if (PeerIP != 0) break; /* try to find the Peer IP address */ pEvtKeyReq = (FT_KDP_EVT_KEY_ELM *)pEvent; if (FT_KDP_R0KH_InfoGet(pAd, pEvtKeyReq->KeyInfo.R0KHID, NULL, &PeerIP) == FALSE) { #if 0 FT_MEM_FREE(pAd, pFtKdp); DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Can not find the IP of R0KH!\n")); return; #endif /* send a broadcast key request packet */ } } break; case FT_KDP_SIG_ACTION: { /* forward FT Action frame by using RRB protocol */ FT_KDP_EVT_ACTION *pActionCB = (FT_KDP_EVT_ACTION *)pCB; if (pCB == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> pCB == NULL!\n")); return; } pFtKdp->Sequence = pActionCB->RequestType; NdisMoveMemory(pFtKdp->MacAddr, pActionCB->MacDa, ETH_ALEN); NdisMoveMemory(pFtKdp->MacAddrSa, pActionCB->MacSa, ETH_ALEN); NdisMoveMemory(pFtKdp->CurrAPAddr, pActionCB->MacAp, ETH_ALEN); } break; case FT_KDP_SIG_KEY_REQ_AUTO: /* PMK-R1 Key Request */ break; case FT_KDP_SIG_KEY_RSP_AUTO: /* PMK-R1 Key Response */ break; case FT_KDP_SIG_INFO_BROADCAST: /* broadcast our AP information to neighbor APs */ break; case FT_KDP_SIG_AP_INFO_REQ: /* request neighbor AP information */ break; case FT_KDP_SIG_AP_INFO_RSP: /* response my information to a AP */ break; case FT_KSP_SIG_DEBUG_TRACE: /* change the debug level of IAPP daemon */ break; case FT_KDP_SIG_TERMINATE: /* terminate FT KDP daemon */ break; default: /* error event */ DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Signal is not supported %d!\n", EventId)); FT_MEM_FREE(pAd, pFtKdp); return; } /* init event content */ EvtHdr.PeerIpAddr = PeerIP; EvtHdr.EventLen = EventLen; NdisMoveMemory(pFtKdp->Content, &EvtHdr, sizeof(FT_KDP_EVT_HEADER)); if (pEvent != NULL) { NdisMoveMemory(pFtKdp->Content+sizeof(FT_KDP_EVT_HEADER), pEvent, EventLen); } DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Event ID = %d, EventLen = %d (%d, %d)\n", EventId, EventLen, FT_KDP_MemAllocNum, FT_KDP_MemFreeNum)); #ifndef FT_KDP_FUNC_SOCK_COMM /* insert to the event queue */ FT_KDP_EVT_LIST_INSERT_TAIL(pAd, &FT_KDP_CB->EventList, pFtKdp); /* inform FT KDP daemon to handle the event */ if ((EventId == FT_KDP_SIG_TERMINATE) || (EventId == FT_KSP_SIG_DEBUG_TRACE) || (EventId == FT_KDP_SIG_FT_ASSOCIATION) || (EventId == FT_KDP_SIG_FT_REASSOCIATION) || (EventId == FT_KDP_SIG_KEY_REQ) || (EventId == FT_KDP_SIG_KEY_TIMEOUT)) { /* Note: in VxWorks, we can not send any signal to same task which issues a ioctl path. */ DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Send signal to ft kdp daemon... (EventLen = %d)\n", EventLen)); SendSignalToDaemon(SIGUSR2, pObj->IappPid, pObj->IappPid_nr); } /* End of if */ #endif /* FT_KDP_FUNC_SOCK_COMM */ #ifdef FT_KDP_FUNC_SOCK_COMM /* inform FT KDP daemon to handle the event */ { FT_DRV_ETH_HEADER Hdr8023, *pHdr8023 = &Hdr8023; NDIS_PACKET *pPktComm; UINT32 FrameLen; #ifdef FT_OS_VXWORKS END_OBJ *pEndEth; #endif /* FT_OS_VXWORKS */ /* allocate a rx packet */ pPktComm = RtmpOSNetPktAlloc(pAd, sizeof(RT_SIGNAL_STRUC)+LENGTH_802_3); if (pPktComm != NULL) { /* make up 802.3 header */ NdisMoveMemory(pHdr8023->DA, pAd->ApCfg.MBSSID[ApIdx].Bssid, 6); /* can not send a packet with same SA & DA in 5VT board */ /* NdisMoveMemory(pHdr8023->SA, pAd->ApCfg.MBSSID[ApIdx].Bssid, 6); */ NdisZeroMemory(pHdr8023->SA, ETH_ALEN); pHdr8023->SA[5] = 0x01; pHdr8023->Len = IAPP_ETH_PRO; /* convert 802.11 to 802.3 packet */ #ifdef FT_OS_VXWORKS pEndEth = endFindByName("mirror", 0); if (pEndEth != NULL) { /* Sometimes if I use ra0 to send the command packet, daemon can not receive the command packet! So I use bridge to do the receive network interface. Support IEEE802.11r DS, must have bridge network interface. */ SET_OS_PKT_NETDEV(pPktComm, pEndEth->devObject.pDevice); } else #endif /* FT_OS_VXWORKS */ SET_OS_PKT_NETDEV(pPktComm, get_netdev_from_bssid(pAd, wdev_idx)); OS_PKT_RESERVE(RTPKT_TO_OSPKT(pPktComm), 2); /* 16 byte align the IP header */ NdisMoveMemory(OS_PKT_TAIL_BUF_EXTEND(RTPKT_TO_OSPKT(pPktComm), LENGTH_802_3), pHdr8023, LENGTH_802_3); FrameLen = RT_SIGNAL_STRUC_HDR_SIZE+sizeof(FT_KDP_EVT_HEADER)+EventLen; NdisMoveMemory(OS_PKT_TAIL_BUF_EXTEND(RTPKT_TO_OSPKT(pPktComm), FrameLen), pFtKdp, FrameLen); DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Send a command (MBSS%d, Frame Len%d) to IAPP daemon.\n", ApIdx, FrameLen)); /* pass this packet to upper layer */ announce_802_3_packet(pAd, pPktComm, OPMODE_AP); } else { DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Allocate signal to ft kdp daemon fail!\n")); } } #endif #ifdef FT_KDP_FUNC_SOCK_COMM FT_MEM_FREE(pAd, pFtKdp); #endif /* FT_KDP_FUNC_SOCK_COMM */ #endif /* FT_KDP_EMPTY */ } /* ======================================================================== Routine Description: Get a event. Arguments: pAd - WLAN control block pointer **pFtKdp - the queued event; if NULL, no event is queued. Return Value: None Note: Used in IOCTL from FT KDP daemon. ======================================================================== */ VOID TYPE_FUNC FT_KDP_EventGet( IN PRTMP_ADAPTER pAd, OUT FT_KDP_SIGNAL **pFtKdp) { #ifndef FT_KDP_EMPTY #ifndef FT_KDP_FUNC_SOCK_COMM UCHAR Size; if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) { DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); return; } /* init */ FT_KDP_EVT_LIST_SIZE_GET(pAd, &FT_KDP_CB->EventList, Size); /* check if any event is queued */ if (Size <= 0) { *pFtKdp = NULL; return; } /* return a event */ FT_KDP_EVT_LIST_REMOVE_HEAD(pAd, &FT_KDP_CB->EventList, (*pFtKdp)); #else *pFtKdp = NULL; #endif /* FT_KDP_FUNC_SOCK_COMM */ #endif /* FT_KDP_EMPTY */ } /* ======================================================================== Routine Description: Inform us a AP request the key. Arguments: pAd - WLAN control block pointer PeerIP - the IP of R1KH, must not be 0 *pNonce - the nonce for key request *pEvtKeyReq - information for key request Return Value: TRUE - request ok FALSE - can not find the IP of R0KH Note: If PeerIP == 0, search its IP from our information record. ======================================================================== */ BOOLEAN TYPE_FUNC FT_KDP_KeyRequestToUs( IN PRTMP_ADAPTER pAd, IN UINT32 PeerIP, IN UCHAR *pNonce, IN FT_KDP_EVT_KEY_ELM *pEvtKeyReq) { #ifndef FT_KDP_EMPTY UINT32 IDR0KH; UINT32 ApIdx; DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Key Req from Peer IP = %d.%d.%d.%d!\n", IAPP_SHOW_IP_HTONL(PeerIP))); if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) { DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); return FALSE; } if (PeerIP == 0) return FALSE; /* sanity check for R0KHID */ #ifdef FT_KDP_DEBUG DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Key Req: R0KH-ID = " "0x%02x:%02x:%02x:%02x:%02x:%02x!\n", pEvtKeyReq->KeyInfo.R0KHID[0], pEvtKeyReq->KeyInfo.R0KHID[1], pEvtKeyReq->KeyInfo.R0KHID[2], pEvtKeyReq->KeyInfo.R0KHID[3], pEvtKeyReq->KeyInfo.R0KHID[4], pEvtKeyReq->KeyInfo.R0KHID[5])); #endif /* FT_KDP_DEBUG */ ApIdx = BSS0; for(IDR0KH=0; IDR0KHKeyInfo.R0KHID[IDR0KH] != 0x00) { /* check if the R0KHID is same as us (MBSS); if not, return FALSE */ /* yet implement */ } } /* check if the request format is correct */ if ((pEvtKeyReq->ElmId == FT_KDP_ELM_ID_PRI) && (pEvtKeyReq->OUI[0] == FT_KDP_ELM_PRI_OUI_0) && (pEvtKeyReq->OUI[1] == FT_KDP_ELM_PRI_OUI_1) && (pEvtKeyReq->OUI[2] == FT_KDP_ELM_PRI_OUI_2)) { #ifdef FT_KDP_DEBUG DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Key Req: Station MAC = " "0x%02x:%02x:%02x:%02x:%02x:%02x!\n", pEvtKeyReq->MacAddr[0], pEvtKeyReq->MacAddr[1], pEvtKeyReq->MacAddr[2], pEvtKeyReq->MacAddr[3], pEvtKeyReq->MacAddr[4], pEvtKeyReq->MacAddr[5])); DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Key Req: R1KH-ID = " "0x%02x:%02x:%02x:%02x:%02x:%02x!\n", pEvtKeyReq->KeyInfo.R1KHID[0], pEvtKeyReq->KeyInfo.R1KHID[1], pEvtKeyReq->KeyInfo.R1KHID[2], pEvtKeyReq->KeyInfo.R1KHID[3], pEvtKeyReq->KeyInfo.R1KHID[4], pEvtKeyReq->KeyInfo.R1KHID[5])); #endif /* FT_KDP_DEBUG */ /* calculate the PMK-R1 Key for the station vs. the AP */ if (FT_QueryKeyInfoForKDP(pAd, ApIdx, pEvtKeyReq) == FALSE) { return FALSE; } /* response the requested PMK-R1 Key to the R1KH */ DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Key Rsp to Peer IP = %d.%d.%d.%d!\n", IAPP_SHOW_IP_HTONL(PeerIP))); FT_KDP_EventInform(pAd, ApIdx, FT_KDP_SIG_KEY_RSP_AUTO, (VOID *)pEvtKeyReq, sizeof(FT_KDP_EVT_KEY_ELM), PeerIP, NULL); return TRUE; } else { DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Key Req format incorrect!\n")); } #endif /* FT_KDP_EMPTY */ return FALSE; } /* ======================================================================== Routine Description: Inform us a AP response the key. Arguments: pAd - WLAN control block pointer *pInfo - key information InfoLen - information length Return Value: None Note: pInfo format is PeerIP (4B) + Nonce (8B) + FT_KDP_EVT_KEY_ELM structure ======================================================================== */ VOID TYPE_FUNC FT_KDP_KeyResponseToUs( IN PRTMP_ADAPTER pAd, IN UCHAR *pInfo, IN INT32 InfoLen) { #ifndef FT_KDP_EMPTY UINT32 PeerIP, DataLen; UCHAR *pData; FT_KDP_EVT_KEY_ELM *pEvtKeyRsp; UCHAR *pNonce; if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) { DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); return; } /* init */ IAPP_DAEMON_CMD_PARSE(pInfo, InfoLen, PeerIP, pData, DataLen); pNonce = pData; pEvtKeyRsp = (FT_KDP_EVT_KEY_ELM *)(pNonce + FT_NONCE_SIZE); #ifdef FT_KDP_DEBUG DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Key Rsp from Peer IP = %d.%d.%d.%d!\n", IAPP_SHOW_IP_HTONL(PeerIP))); #endif /* FT_KDP_DEBUG */ /* check if the response format is correct */ if ((pEvtKeyRsp->ElmId == FT_KDP_ELM_ID_PRI) && (pEvtKeyRsp->OUI[0] == FT_KDP_ELM_PRI_OUI_0) && (pEvtKeyRsp->OUI[1] == FT_KDP_ELM_PRI_OUI_1) && (pEvtKeyRsp->OUI[2] == FT_KDP_ELM_PRI_OUI_2)) { PFT_R1HK_ENTRY pR1hkEntry; BOOLEAN bUpdateR1kh = FALSE; #ifdef FT_KDP_DEBUG DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Key Rsp: Station MAC = " "0x%02x:%02x:%02x:%02x:%02x:%02x!\n", pEvtKeyRsp->MacAddr[0], pEvtKeyRsp->MacAddr[1], pEvtKeyRsp->MacAddr[2], pEvtKeyRsp->MacAddr[3], pEvtKeyRsp->MacAddr[4], pEvtKeyRsp->MacAddr[5])); DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Key Rsp: R1KH-ID = " "0x%02x:%02x:%02x:%02x:%02x:%02x!\n", pEvtKeyRsp->KeyInfo.R1KHID[0], pEvtKeyRsp->KeyInfo.R1KHID[1], pEvtKeyRsp->KeyInfo.R1KHID[2], pEvtKeyRsp->KeyInfo.R1KHID[3], pEvtKeyRsp->KeyInfo.R1KHID[4], pEvtKeyRsp->KeyInfo.R1KHID[5])); DBGPRINT(RT_DEBUG_TRACE, ("MacAddr")); hex_dump("PMKR1Name", pEvtKeyRsp->PMKR1Name, FT_KDP_WPA_NAME_MAX_SIZE); hex_dump("R0KH_MAC", pEvtKeyRsp->R0KH_MAC, ETH_ALEN); hex_dump("AKM Suite", pEvtKeyRsp->AkmSuite, 4); #endif /* FT_KDP_DEBUG */ /* Upon receiving a new PMK-R1 key for a STA, the target AP shall delete the prior PMK-R1 SA and PTKSAs derived from the prior PMK-R1 key */ pR1hkEntry = FT_R1khEntryTabLookup(pAd, pEvtKeyRsp->PMKR1Name); if (pR1hkEntry == NULL) { bUpdateR1kh = TRUE; } if (pR1hkEntry && RTMPEqualMemory(pR1hkEntry->PmkR1Key, pEvtKeyRsp->PMKR1, LEN_PMK) == FALSE) { FT_R1khEntryDelete(pAd, pR1hkEntry); bUpdateR1kh = TRUE; } if (bUpdateR1kh) { /* assign the PMK-R1 key to FT kernel */ FT_R1khEntryInsert(pAd, pEvtKeyRsp->KeyInfo.PMKR0Name, pEvtKeyRsp->PMKR1Name, pEvtKeyRsp->PMKR1, pEvtKeyRsp->PairwisChipher, pEvtKeyRsp->AkmSuite, pEvtKeyRsp->KeyLifeTime, pEvtKeyRsp->ReassocDeadline, (PUINT8)pEvtKeyRsp->KeyInfo.R0KHID, pEvtKeyRsp->KeyInfo.R0KHIDLen, pEvtKeyRsp->MacAddr); } #ifdef FT_KDP_FUNC_R0KH_IP_RECORD /* add the R0KH information */ FT_KDP_R0KH_InfoAdd(pAd, pEvtKeyRsp->KeyInfo.R0KHID, pEvtKeyRsp->R0KH_MAC, PeerIP); #endif /* FT_KDP_FUNC_R0KH_IP_RECORD */ } else { DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Key Rsp format incorrect!\n")); } #endif /* FT_KDP_EMPTY */ } /* ======================================================================== Routine Description: Inform us a FT station joins the BSS domain. Arguments: pAd - WLAN control block pointer *pInfo - station information InfoLen - information length Return Value: None Note: pInfo format is PeerIP (4B) + Station MAC (6B) ======================================================================== */ VOID TYPE_FUNC FT_KDP_StationInform( IN PRTMP_ADAPTER pAd, IN UCHAR *pInfo, IN INT32 InfoLen) { #ifndef FT_KDP_EMPTY UINT32 PeerIP, DataLen; UCHAR *pData; FT_KDP_EVT_KEY_ELM EvtKeyReq, *pEvtKeyReq; UCHAR StaMac[ETH_ALEN]; UINT32 IdBssNum; if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) { DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); return; } /* init */ IAPP_DAEMON_CMD_PARSE(pInfo, InfoLen, PeerIP, pData, DataLen); #ifndef FT_KDP_FUNC_TEST /* check if we are in security mode; if not, return */ for(IdBssNum=0; IdBssNumApCfg.BssidNum; IdBssNum++) { if (pAd->ApCfg.MBSSID[IdBssNum].WepStatus != Ndis802_11WEPDisabled) break; } if (IdBssNum == pAd->ApCfg.BssidNum) { DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> All BSS are open mode!\n")); return; /* all BSS are open mode */ } #endif NdisMoveMemory(StaMac, pData, ETH_ALEN); NdisZeroMemory(&EvtKeyReq, sizeof(FT_KDP_EVT_KEY_ELM)); pEvtKeyReq = &EvtKeyReq; #ifdef FT_KDP_DEBUG DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Station Inform from Peer IP = %d.%d.%d.%d!\n", IAPP_SHOW_IP_HTONL(PeerIP))); #endif /* make up request content */ pEvtKeyReq->ElmId = FT_KDP_ELM_ID_PRI; pEvtKeyReq->ElmLen = FT_KDP_ELM_PRI_LEN; pEvtKeyReq->OUI[0] = FT_KDP_ELM_PRI_OUI_0; pEvtKeyReq->OUI[1] = FT_KDP_ELM_PRI_OUI_1; pEvtKeyReq->OUI[2] = FT_KDP_ELM_PRI_OUI_2; NdisMoveMemory(pEvtKeyReq->MacAddr, StaMac, ETH_ALEN); NdisMoveMemory(pEvtKeyReq->KeyInfo.S1KHID, StaMac, FT_KDP_S1KHID_MAX_SIZE); /* request PMK-R1 Key (our R1KH vs. the station) from the R0KH */ #ifdef FT_KDP_DEBUG DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Send Key Req to Peer IP = %d.%d.%d.%d!\n", IAPP_SHOW_IP_HTONL(PeerIP))); #endif /* FT_KDP_DEBUG */ for(IdBssNum=0; IdBssNumApCfg.BssidNum; IdBssNum++) { #ifndef FT_KDP_FUNC_TEST if (pAd->ApCfg.MBSSID[IdBssNum].WepStatus != Ndis802_11WEPDisabled) #endif /* FT_KDP_FUNC_TEST */ { /* copy our MAC address to be the R1KHID */ /* different MAC for different BSS in MBSS mode */ NdisMoveMemory(pEvtKeyReq->KeyInfo.R1KHID, pAd->ApCfg.MBSSID[IdBssNum].Bssid, FT_KDP_R1KHID_MAX_SIZE); FT_KDP_EventInform(pAd, IdBssNum, FT_KDP_SIG_KEY_REQ_AUTO, (VOID *)pEvtKeyReq, sizeof(FT_KDP_EVT_KEY_ELM), PeerIP, NULL); } } #endif /* FT_KDP_EMPTY */ } /* ======================================================================== Routine Description: Set the encryption/decryption key from daemon or driver. Arguments: pAd - WLAN control block pointer *pKey - the key KeyLen - the key length Return Value: None Note: Key length can be 8B ~ 64B. We support key set from daemon or driver. Only one key for multiple BSS mode. ======================================================================== */ VOID TYPE_FUNC FT_KDP_CryptKeySet( IN PRTMP_ADAPTER pAd, IN UCHAR *pKey, IN INT32 KeyLen) { #ifndef FT_KDP_EMPTY UCHAR KeyMaterial[40]; if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) { DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); return; } /* key set */ if ((KeyLen >= 8) && (KeyLen <= 64)) { RtmpPasswordHash((RTMP_STRING *)pKey, (PUCHAR)FT_KDP_RALINK_PASSPHRASE, strlen(FT_KDP_RALINK_PASSPHRASE), KeyMaterial); } else { RtmpPasswordHash((RTMP_STRING *)FT_KDP_KEY_DEFAULT, (PUCHAR)FT_KDP_RALINK_PASSPHRASE, strlen(FT_KDP_RALINK_PASSPHRASE), KeyMaterial); } /* use the first 16B of KeyMaterial[] */ NdisMoveMemory(FT_KDP_CB->CryptKey, KeyMaterial, sizeof(KeyMaterial)); #endif /* FT_KDP_EMPTY */ } /* ======================================================================== Routine Description: Encrypt the data. Arguments: pAd - WLAN control block pointer *pData - data buffer *pDataLen - data buffer length Return Value: None Note: ======================================================================== */ VOID TYPE_FUNC FT_KDP_DataEncrypt( IN PRTMP_ADAPTER pAd, INOUT UCHAR *pData, IN UINT32 *pDataLen) { #ifndef FT_KDP_EMPTY UCHAR *pOutputBuf; UINT OutputLen = 0; if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) { DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); return; } /* init */ FT_MEM_ALLOC(pAd, &pOutputBuf, *pDataLen + FT_KDP_KEY_ENCRYPTION_EXTEND); if (pOutputBuf == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> Allocate encryption buffer fail!\n")); return; } NdisZeroMemory(pOutputBuf, *pDataLen + FT_KDP_KEY_ENCRYPTION_EXTEND); /* encrypt */ AES_Key_Wrap(pData, *pDataLen, FT_KDP_CB->CryptKey, 16, pOutputBuf, &OutputLen); *pDataLen = OutputLen; NdisMoveMemory(pData, pOutputBuf, *pDataLen); FT_MEM_FREE(pAd, pOutputBuf); #endif /* FT_KDP_EMPTY */ } /* ======================================================================== Routine Description: Decrypt the data. Arguments: pAd - WLAN control block pointer *pData - data buffer *pDataLen - data buffer length Return Value: None Note: ======================================================================== */ VOID TYPE_FUNC FT_KDP_DataDecrypt( IN PRTMP_ADAPTER pAd, IN UCHAR *pData, IN UINT32 *pDataLen) { #ifndef FT_KDP_EMPTY UCHAR *pOutputBuf; UINT OutputLen = 0; if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) { DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); return; } if ((*pDataLen) <= FT_KDP_KEY_ENCRYPTION_EXTEND) { DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd>Decryption length is too small!\n")); return; } /* init */ FT_MEM_ALLOC(pAd, &pOutputBuf, *pDataLen); if (pOutputBuf == NULL) { DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> Allocate decryption buffer fail!\n")); return; } /* decrypt */ AES_Key_Unwrap(pData, *pDataLen, FT_KDP_CB->CryptKey, 16, pOutputBuf, &OutputLen); *pDataLen = OutputLen; NdisMoveMemory(pData, pOutputBuf, *pDataLen); FT_MEM_FREE(pAd, pOutputBuf); #endif /* FT_KDP_EMPTY */ } /* private function */ #ifdef FT_KDP_FUNC_R0KH_IP_RECORD /* ======================================================================== Routine Description: Add a R0KH Information. Arguments: pAd - WLAN control block pointer *pR0KHID - R0KH ID *pMAC - R0KH MAC IP - R0KH IP Return Value: None Note: ======================================================================== */ BOOLEAN TYPE_FUNC FT_KDP_R0KH_InfoAdd( IN PRTMP_ADAPTER pAd, IN UCHAR *pR0KHID, IN UCHAR *pMAC, IN UINT32 IP) { #ifndef FT_KDP_EMPTY FT_KDP_R0KH_INFO *pInfo; BOOLEAN FlgIsSameRecordFound; if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) { DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); return FALSE; } /* sanity check for maximum size */ if (FT_KDP_CB->R0KH_Size >= FT_KDP_R0KH_INFO_MAX_SIZE) { /* delete oldest record first */ FT_KDP_R0KH_InfoDel(pAd, NULL, NULL, 0); } RTMP_SEM_LOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); /* sanity check if same information exists */ FlgIsSameRecordFound = FALSE; pInfo = FT_KDP_CB->R0KH_InfoHead; while(pInfo != NULL) { if ((NdisEqualMemory(pInfo->R0KHID, pR0KHID, sizeof(pInfo->R0KHID))) || (NdisEqualMemory(pInfo->MAC, pMAC, sizeof(pInfo->MAC))) || (pInfo->IP == IP)) { /* need to update the new information to the entry */ FlgIsSameRecordFound = TRUE; break; } pInfo = pInfo->pNext; } /* init or update */ if (FlgIsSameRecordFound == FALSE) { /* allocate a new record */ FT_MEM_ALLOC(pAd, &pInfo, sizeof(FT_KDP_R0KH_INFO)); if (pInfo == NULL) { RTMP_SEM_UNLOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> Allocate R0KH INFO fail!\n")); return FALSE; } pInfo->pNext = NULL; } /* update other R0KH device information */ NdisMoveMemory(pInfo->R0KHID, pR0KHID, sizeof(pInfo->R0KHID)); NdisMoveMemory(pInfo->MAC, pMAC, sizeof(pInfo->MAC)); pInfo->IP = IP; NdisGetSystemUpTime(&pInfo->TimeUpdate); /* append the new information to the information list */ if (FlgIsSameRecordFound == FALSE) { if (FT_KDP_CB->R0KH_InfoTail == NULL) { FT_KDP_CB->R0KH_InfoHead = pInfo; FT_KDP_CB->R0KH_InfoTail = pInfo; } else { (FT_KDP_CB->R0KH_InfoTail)->pNext = pInfo; FT_KDP_CB->R0KH_InfoTail = pInfo; } FT_KDP_CB->R0KH_Size ++; } RTMP_SEM_UNLOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); #endif /* FT_KDP_EMPTY */ return TRUE; } /* ======================================================================== Routine Description: Delete a R0KH Information. Arguments: pAd - WLAN control block pointer *pR0KHID - R0KH ID *pMAC - R0KH MAC IP - R0KH IP Return Value: None Note: If pR0KHID == NULL, pMAC == NULL, and IP = 0, means deleting the oldest. ======================================================================== */ VOID TYPE_FUNC FT_KDP_R0KH_InfoDel( IN PRTMP_ADAPTER pAd, IN UCHAR *pR0KHID, IN UCHAR *pMAC, IN UINT32 IP) { #ifndef FT_KDP_EMPTY FT_KDP_R0KH_INFO *pInfo; FT_KDP_R0KH_INFO *pInfoBackup, *pInfoDelPrev, *pInfoDel; ULONG TimeOldest; if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) { DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); return; } /* init */ pInfoDelPrev = NULL; pInfoDel = NULL; TimeOldest = 0xFFFFFFFF; RTMP_SEM_LOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); /* try to find the one expected to delete */ pInfo = FT_KDP_CB->R0KH_InfoHead; if (pInfo == NULL) { RTMP_SEM_UNLOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); return; } pInfoBackup = pInfo; while(pInfo != NULL) { if ((pR0KHID == NULL) && (pMAC == NULL) && (IP == 0)) { /* check if the info is the oldest one */ if (pInfo->TimeUpdate < TimeOldest) { TimeOldest = pInfo->TimeUpdate; pInfoDelPrev = pInfoBackup; pInfoDel = pInfo; } } else { /* check if the info is the one expected to delete */ if ((pR0KHID != NULL) && (NdisEqualMemory(pR0KHID, pInfo->R0KHID, sizeof(pInfo->R0KHID)))) { pInfoDelPrev = pInfoBackup; pInfoDel = pInfo; break; } if ((pMAC != NULL) && (NdisEqualMemory(pMAC, pInfo->MAC, sizeof(pInfo->MAC)))) { pInfoDelPrev = pInfoBackup; pInfoDel = pInfo; break; } if (IP == pInfo->IP) { pInfoDelPrev = pInfoBackup; pInfoDel = pInfo; break; } } /* check next one */ pInfoBackup = pInfo; pInfo = pInfo->pNext; } /* delete the information record */ if (pInfoDel != NULL) { FT_KDP_CB->R0KH_Size --; if (FT_KDP_CB->R0KH_Size == 0) { /* list is empty */ FT_KDP_CB->R0KH_InfoHead = NULL; FT_KDP_CB->R0KH_InfoTail = NULL; } else { if (pInfoDelPrev == pInfoDel) { /* must be the head one */ FT_KDP_CB->R0KH_InfoHead = pInfoDel->pNext; } else { /* must not be the head one */ pInfoDelPrev->pNext = pInfoDel->pNext; } } } else { /* sorry! can not find the one in the list */ } RTMP_SEM_UNLOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); /* free the one */ if (pInfoDel != NULL) FT_MEM_FREE(pAd, pInfoDel); #endif /* FT_KDP_EMPTY */ } /* ======================================================================== Routine Description: Get the IP of R0KH by R0KHID or MAC. Arguments: pAd - WLAN control block pointer *pR0KHID - R0KH ID *pMAC - R0KH MAC pIP - R0KH IP Return Value: TRUE - get ok FALSE - get fail Note: ======================================================================== */ static BOOLEAN TYPE_FUNC FT_KDP_R0KH_InfoGet( IN PRTMP_ADAPTER pAd, INOUT UCHAR *pR0KHID, INOUT UCHAR *pMAC, OUT UINT32 *pIP) { #ifndef FT_KDP_EMPTY FT_KDP_R0KH_INFO *pInfo; if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) { DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); return FALSE; } RTMP_SEM_LOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); pInfo = FT_KDP_CB->R0KH_InfoHead; while(pInfo != NULL) { /* check if the info is the one expected to get */ if ((pR0KHID != NULL) && (NdisEqualMemory(pR0KHID, pInfo->R0KHID, sizeof(pInfo->R0KHID)))) { *pIP = pInfo->IP; goto LabelOk; } if ((pMAC != NULL) && (NdisEqualMemory(pMAC, pInfo->MAC, sizeof(pInfo->MAC)))) { *pIP = pInfo->IP; goto LabelOk; } /* check next one */ pInfo = pInfo->pNext; } RTMP_SEM_UNLOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); return FALSE; LabelOk: RTMP_SEM_UNLOCK(&(pAd->ApCfg.FtTab.FT_KdpLock)); return TRUE; #else return FALSE; #endif /* FT_KDP_EMPTY */ } #endif /* FT_KDP_FUNC_R0KH_IP_RECORD */ /* ======================================================================== Routine Description: Broadcast our AP information. Arguments: SystemSpecific1 - no use FunctionContext - WLAN control block pointer SystemSpecific2 - no use SystemSpecific3 - no use Return Value: NONE Note: ======================================================================== */ VOID TYPE_FUNC FT_KDP_InfoBroadcast( IN PVOID SystemSpecific1, IN PVOID FunctionContext, IN PVOID SystemSpecific2, IN PVOID SystemSpecific3) { #ifndef FT_KDP_EMPTY #ifdef FT_KDP_FUNC_INFO_BROADCAST PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext; UINT32 IdBssNum; if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) { DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); return; } /* get my neighbor report element information */ /* yet implement */ for(IdBssNum=0; IdBssNumApCfg.BssidNum; IdBssNum++) { /* PeerIP = 0 means destination MAC = 0xFF FF FF FF FF FF */ FT_KDP_EventInform(pAd, IdBssNum, FT_KDP_SIG_INFO_BROADCAST, "test", 4, 0, NULL); } #endif /* FT_KDP_FUNC_INFO_BROADCAST */ #endif /* FT_KDP_EMPTY */ } #ifdef FT_KDP_FUNC_INFO_BROADCAST /* ======================================================================== Routine Description: Receive a neighbor report from another AP. Arguments: pAd - WLAN control block pointer *pInfo - report information InfoLen - information length Return Value: NONE Note: ======================================================================== */ VOID TYPE_FUNC FT_KDP_NeighborReportHandle( IN PRTMP_ADAPTER pAd, IN UCHAR *pInfo, IN INT32 InfoLen) { #ifndef FT_KDP_EMPTY UINT32 PeerIP, DataLen; UCHAR *pData; UINT32 IdBssNum; if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) { DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); return; } /* init */ IAPP_DAEMON_CMD_PARSE(pInfo, InfoLen, PeerIP, pData, DataLen); #ifdef FT_KDP_DEBUG DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Neighbor Report from Peer IP = %d.%d.%d.%d!\n", IAPP_SHOW_IP_HTONL(PeerIP))); #endif /* FT_KDP_DEBUG */ /* yet implememnt */ #endif /* FT_KDP_EMPTY */ } #endif /* FT_KDP_FUNC_INFO_BROADCAST */ /* ======================================================================== Routine Description: Receive a neighbor request from another AP. Arguments: pAd - WLAN control block pointer *pInfo - report information InfoLen - information length Return Value: NONE Note: ======================================================================== */ VOID TYPE_FUNC FT_KDP_NeighborRequestHandle( IN PRTMP_ADAPTER pAd, IN UCHAR *pInfo, IN INT32 InfoLen) { #ifndef FT_KDP_EMPTY UINT32 PeerIP, DataLen; UCHAR *pData; UINT32 IdBssNum; UINT16 SsidLen; RTMP_STRING *pSSID; if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) { DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); return; } /* init */ IAPP_DAEMON_CMD_PARSE(pInfo, InfoLen, PeerIP, pData, DataLen); SsidLen = DataLen; pSSID = (RTMP_STRING *)pData; pSSID[SsidLen] = 0x00; IdBssNum = BSS0; #ifdef FT_KDP_DEBUG DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Neighbor Request from Peer IP = %d.%d.%d.%d, SSID = %s\n", IAPP_SHOW_IP_HTONL(PeerIP), pSSID)); #endif /* FT_KDP_DEBUG */ /* check if the requested SSID is for us */ #if 0 /* yet implement */ for(IdBssNum=0; IdBssNumApCfg.BssidNum; IdBssNum++) { } /* End of for */ #endif /* 11k yet implememnt */ /* 11K_ApInfoGet(&ApInfo); */ /* reponse the neighbor request to the AP */ /* FT_KDP_EventInform(pAd, IdBssNum, FT_KDP_SIG_AP_INFO_RSP, */ /* &ApInfo, sizeof(ApInfo), PeerIP, NULL); */ #endif /* FT_KDP_EMPTY */ } /* ======================================================================== Routine Description: Receive a neighbor response from another AP. Arguments: pAd - WLAN control block pointer *pInfo - report information InfoLen - information length Return Value: NONE Note: ======================================================================== */ VOID TYPE_FUNC FT_KDP_NeighborResponseHandle( IN PRTMP_ADAPTER pAd, IN UCHAR *pInfo, IN INT32 InfoLen) { #ifndef FT_KDP_EMPTY UINT32 PeerIP, DataLen; UCHAR *pData; if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) { DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); return; } /* init */ IAPP_DAEMON_CMD_PARSE(pInfo, InfoLen, PeerIP, pData, DataLen); #ifdef FT_KDP_DEBUG DBGPRINT(RT_DEBUG_TRACE, ("ap_ftkd> Neighbor Response from Peer IP = %d.%d.%d.%d\n", IAPP_SHOW_IP_HTONL(PeerIP))); #endif /* FT_KDP_DEBUG */ /* 11k yet implememnt */ /* 11K_ResponseHandle(pData, DataLen); */ #endif /* FT_KDP_EMPTY */ } /* ======================================================================== Routine Description: Handle a RRB frame from DS. Arguments: pAd - WLAN control block pointer *pInfo - report information InfoLen - information length Return Value: NONE Note: ======================================================================== */ VOID TYPE_FUNC FT_RRB_ActionHandle( IN PRTMP_ADAPTER pAd, IN UCHAR *pInfo, IN INT32 InfoLen) { #ifndef FT_KDP_EMPTY if (pAd->ApCfg.FtTab.FlgIsFtKdpInit == 0) { DBGPRINT(RT_DEBUG_ERROR, ("ap_ftkd> %s: FT KDP is not init!\n", __FUNCTION__)); return; } /* handle it */ FT_RrbHandler(pAd, pInfo, InfoLen); #endif /* FT_KDP_EMPTY */ } #endif /* DOT11R_FT_SUPPORT */