diff options
| author | Daiqian Hu <[email protected]> | 2016-11-21 08:54:24 +0800 |
|---|---|---|
| committer | Daiqian Hu <[email protected]> | 2016-11-21 08:54:24 +0800 |
| commit | a95eaad088f61aa55da9d73015cf1ed86e64a67e (patch) | |
| tree | 15b498a08a4aee4b7f8b1627d39c965b3aa3ba98 /network/wlan/WDI/COMMON/ParserGen.c | |
| parent | 1aa0338ec5418345ea0c383e92b4fa19f7c98425 (diff) | |
Re-submit for WDI sample driver to GitHub
Submit WDI sample driver to GitHub for RS1.
Diffstat (limited to 'network/wlan/WDI/COMMON/ParserGen.c')
| -rw-r--r-- | network/wlan/WDI/COMMON/ParserGen.c | 2292 |
1 files changed, 2292 insertions, 0 deletions
diff --git a/network/wlan/WDI/COMMON/ParserGen.c b/network/wlan/WDI/COMMON/ParserGen.c new file mode 100644 index 00000000..df264db2 --- /dev/null +++ b/network/wlan/WDI/COMMON/ParserGen.c @@ -0,0 +1,2292 @@ +/*++ +Copyright (c) Realtek Semiconductor Corp. All rights reserved. + +Module Name: + ParserGen.c + +Abstract: + Parse MSDU to match the specified type, fetch fixed offset. + +Major Change History: + When Who What + ---------- --------------- ------------------------------- + 2007-06-11 shienchang Create. + 2008-03-11 Bruce Modify from 818xB. + +--*/ + +#include "Mp_Precomp.h" + +#if WPP_SOFTWARE_TRACE +#include "ParserGen.tmh" +#endif + +// Global protocols and the corresponding actions. +static GP_RULE GPGlobalRule[] = +{ + { PROTO_ETHERNET, PROTO_IP, 12, 2, GPParserHandlerEthernet }, + { PROTO_WLAN_80211, PROTO_WLAN_LLC, 0, 2, GPParserHandlerWlan }, + { PROTO_WLAN_LLC, PROTO_IP, 6, 2, GPParserHandlerWlanLlc }, + { PROTO_IP, PROTO_TCP, 9, 1, GPParserHandlerIP }, + { PROTO_IP, PROTO_UDP, 9, 1, GPParserHandlerIP }, + {0}, +}; + +// The SIP protocol definitions and the corresponding actions. +static GP_RULE GPVoWlanSipRule[] = +{ + { PROTO_UDP, PROTO_SIP_INVITE, UNKNOWN_SIG, UNKNOWN_SIG, GPParserCustomHandleUDP2SIP }, + { PROTO_UDP, PROTO_SIP_STATUS, UNKNOWN_SIG, UNKNOWN_SIG, GPParserCustomHandleUDP2SIP }, + { PROTO_UDP, PROTO_SIP_BYE, UNKNOWN_SIG, UNKNOWN_SIG, GPParserCustomHandleUDP2SIP }, + { PROTO_SIP_INVITE, PROTO_SIP_SDP, UNKNOWN_SIG, UNKNOWN_SIG, GPParserCustomHandleSIP2SDP }, + { PROTO_SIP_STATUS, PROTO_SIP_SDP, UNKNOWN_SIG, UNKNOWN_SIG, GPParserCustomHandleSIP2SDP }, + { PROTO_SIP_STATUS, PROTO_UNKNOWN, UNKNOWN_SIG, UNKNOWN_SIG, GPParserCustomHandleSIPSTATUS }, + { PROTO_SIP_SDP, PROTO_UNKNOWN, UNKNOWN_SIG, UNKNOWN_SIG, GPParserCustomHandleSDP }, + { PROTO_SIP_BYE, PROTO_UNKNOWN, UNKNOWN_SIG, UNKNOWN_SIG, GPParserCustomHandleSIPBYE }, + { PROTO_UDP, PROTO_RTP, UNKNOWN_SIG, UNKNOWN_SIG, GPParserCustomHandleUDP2RTP }, + { PROTO_RTP, PROTO_RTP_G711, UNKNOWN_SIG, UNKNOWN_SIG, GPParserCustomHandleRTP2G711 }, + { PROTO_RTP_G711, PROTO_UNKNOWN, UNKNOWN_SIG, UNKNOWN_SIG, GPParserCustomHandleG711 }, + {0}, +}; +//============================================================================= +// Prototype of protected function. +//============================================================================= +TR_ACTION +ParseBuffer( + IN PADAPTER Adapter, + IN PGPPARSE_TOKEN pToken + ); + +VOID +RuleMatchingProcess( + IN PADAPTER Adapter, + IN PGPPARSE_TOKEN pToken, + IN PGENERIC_PARSER pParser + ); + +BOOLEAN +MatchingByRule( + IN PADAPTER Adapter, + IN PGP_RULE pRule, + IN PGPPARSE_TOKEN pToken, + IN PGENERIC_PARSER pParser + ); + +BOOLEAN +GetSignatureAndAdvanceToNextProtocol( + IN PGPPARSE_TOKEN pToken, + IN u4Byte DataOffset, + IN u4Byte HeaderLength, + IN PVOID pDataBuffer, + IN u4Byte DataBufLength + ); + +BOOLEAN +GetNextLine( + IN PGPPARSE_TOKEN pToken, + IN BOOLEAN bNoAdvance, + OUT pu1Byte pOutBuffer, + IN u4Byte OutBufferLen + ); + +BOOLEAN +UngetLine( + IN PGPPARSE_TOKEN pToken + ); + +BOOLEAN +AdvanceAndGetDataByOffset( + IN PGPPARSE_TOKEN pToken, + IN u4Byte DataOffset, + IN BOOLEAN bNoAdvance, + OUT PVOID pDataBuffer, + IN u4Byte DataBufLength + ); + +//============================================================================= +// End of Prototype of protected function. +//============================================================================= + +//============================================================================= +// Private utility function. +//============================================================================= + +#if DBG +// +// Description: +// Debug routine of protocol. +// 2007.07.10, by shien chang. +// +VOID +DbgProtocol( + IN u4Byte protocol + ) +{ + switch (protocol) + { + case PROTO_UNKNOWN: + RT_TRACE(COMP_CCX, DBG_TRACE, ("\n")); + break; + case PROTO_ETHERNET: + RT_TRACE(COMP_CCX, DBG_TRACE, ("ethernet -> ")); + break; + case PROTO_WLAN_80211: + RT_TRACE(COMP_CCX, DBG_TRACE, ("wlan -> ")); + break; + case PROTO_WLAN_LLC: + RT_TRACE(COMP_CCX, DBG_TRACE, ("llc -> ")); + break; + case PROTO_IP: + RT_TRACE(COMP_CCX, DBG_TRACE, ("ip -> ")); + break; + case PROTO_TCP: + RT_TRACE(COMP_CCX, DBG_TRACE, ("tcp -> ")); + break; + case PROTO_UDP: + RT_TRACE(COMP_CCX, DBG_TRACE, ("udp -> ")); + break; + case PROTO_RTP: + RT_TRACE(COMP_CCX, DBG_TRACE, ("rtp -> ")); + break; + case PROTO_SIP_INVITE: + RT_TRACE(COMP_CCX, DBG_TRACE, ("sip invite -> ")); + break; + case PROTO_SIP_STATUS: + RT_TRACE(COMP_CCX, DBG_TRACE, ("sip status -> ")); + break; + case PROTO_SIP_BYE: + RT_TRACE(COMP_CCX, DBG_TRACE, ("sip bye -> ")); + break; + case PROTO_SIP_NOTIFY: + RT_TRACE(COMP_CCX, DBG_TRACE, ("sip notify -> ")); + break; + case PROTO_SIP_SDP: + RT_TRACE(COMP_CCX, DBG_TRACE, ("sip sdp -> ")); + break; + case PROTO_RTP_G711: + RT_TRACE(COMP_CCX, DBG_TRACE, ("rtp g711 -> ")); + break; + default: + RT_TRACE(COMP_CCX, DBG_TRACE, ("protocol: %d -> ", protocol)); + break; + } +} +#endif + + +// +// Description: +// Request every parser to parse the tx or rx packet. +// 2007.07.10, by shien chang. +// +TR_ACTION +ParseBuffer( + IN PADAPTER Adapter, + IN PGPPARSE_TOKEN pToken + ) +{ + PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo); + u4Byte i; + PGENERIC_PARSER pParser; + TR_ACTION trAction = TR_ACTION_CONTINUE; + + for (i=0; i < MAX_PARSER_NUM; i++) + { + pParser = *(((PGENERIC_PARSER*)pMgntInfo->pGenericParser) + i); + if ( pParser ) + { + // + // Drive the parser go through the registered rules. + // + if ( pParser->Gate && pParser->Gate(Adapter, pParser) ) + { + RuleMatchingProcess(Adapter, pToken, pParser); + if (pParser->Action != NULL) + trAction = pParser->Action(Adapter, pToken, pParser); + if (trAction != TR_ACTION_CONTINUE) + break; + } + } + } + + return trAction; +} + +// +// Description: +// This routine drive parser according to parsing rules. +// 2007.07.10, by shien chang. +// +VOID +RuleMatchingProcess( + IN PADAPTER Adapter, + IN PGPPARSE_TOKEN pToken, + IN PGENERIC_PARSER pParser + ) +{ + PGP_RULE pRule = NULL; + BOOLEAN bMatched = FALSE; + PGP_RULE pRuleSet[2]; + u4Byte i=0; + + pRuleSet[0] = pParser->pParseRules; + pRuleSet[1] = GPGlobalRule; + + while ( i < sizeof(pRuleSet) / sizeof(PGP_RULE) ) + { + // + // Go through parser's rules & global rules. + // + bMatched = FALSE; + + for (pRule = pRuleSet[i]; + (pRule != NULL) && (pRule->CurrProtocol != 0); + pRule ++) + { + if (pRule->CurrProtocol == pToken->currProtocol) + { + bMatched = MatchingByRule(Adapter, + pRule, + pToken, + pParser); + if (bMatched) + break; + } + } + + if (bMatched) + { + if (pRule->NextProtocol != PROTO_UNKNOWN) + { + i = 0; + } + else + { + break; + } + } + else + i ++; + } + + if (!bMatched) + { + DbgProtocol(pToken->currProtocol); + if (pToken->ProtocolCount < MAX_PROTOCOL_NUM) + pToken->ProtocolSuite[pToken->ProtocolCount++] = pToken->currProtocol; + } + DbgProtocol(PROTO_UNKNOWN); +} + +// +// Description: +// Try to match a rule. +// 2007.7.13, by shien chang. +// +BOOLEAN +MatchingByRule( + IN PADAPTER Adapter, + IN PGP_RULE pRule, + IN PGPPARSE_TOKEN pToken, + IN PGENERIC_PARSER pParser + ) +{ + u1Byte SigBuffer[MAX_SIG_LENGTH]; + BOOLEAN bApply = FALSE; + BOOLEAN bMatched = FALSE; + BOOLEAN bAdv=FALSE; + u4Byte currIndex, currOffset; + u4Byte hdrLen=0; + + if ( pRule->SigLength <= MAX_SIG_LENGTH) + { + currIndex = pToken->currBufferIndex; + currOffset = pToken->currBufferOffset; + hdrLen = PROTO_UNKNOWN_HDRLEN; + + // + // Check signature. + // case 1: if signature is unknown, invoke the customer routine + // and advance to next protocol if success. + // case 2: if signature is known, get the signature first and then + // invoke the costomer routine. + // + if ( pRule->SigLength == UNKNOWN_SIG ) + { + bApply = pRule->ParseHandler( + Adapter, + pParser->ParserContext, + pToken->currProtocol, + pRule->NextProtocol, + NULL, + 0, + pToken, + &hdrLen); + + if (hdrLen == PROTO_UNKNOWN_HDRLEN) + { + pToken->currBufferIndex = currIndex; + pToken->currBufferOffset = currOffset; + bAdv = TRUE; + } + else if (bApply) + { + bAdv = GetSignatureAndAdvanceToNextProtocol( + pToken, + pRule->SigStart, + hdrLen, + NULL, + 0); + } + + if (bApply && bAdv) + { + DbgProtocol(pToken->currProtocol); + if (pToken->ProtocolCount < MAX_PROTOCOL_NUM) + pToken->ProtocolSuite[pToken->ProtocolCount++] = pToken->currProtocol; + + if (pRule->NextProtocol != PROTO_UNKNOWN) + pToken->currProtocol = pRule->NextProtocol; + bMatched = TRUE; + } + + } + else + { + if (AdvanceAndGetDataByOffset( + pToken, + pRule->SigStart, + TRUE, + SigBuffer, + pRule->SigLength)) + { + bApply = pRule->ParseHandler( + Adapter, + pParser->ParserContext, + pToken->currProtocol, + pRule->NextProtocol, + SigBuffer, + pRule->SigLength, + pToken, + &hdrLen); + + if (hdrLen == PROTO_UNKNOWN_HDRLEN) + { + pToken->currBufferIndex = currIndex; + pToken->currBufferOffset = currOffset; + bAdv = TRUE; + } + else if (bApply) + { + bAdv = GetSignatureAndAdvanceToNextProtocol( + pToken, + pRule->SigStart, + hdrLen, + NULL, + 0); + } + + if (bApply && bAdv) + { + DbgProtocol(pToken->currProtocol); + if (pToken->ProtocolCount < MAX_PROTOCOL_NUM) + pToken->ProtocolSuite[pToken->ProtocolCount++] = pToken->currProtocol; + + if (pRule->NextProtocol != PROTO_UNKNOWN) + pToken->currProtocol = pRule->NextProtocol; + bMatched = TRUE; + } + } + + } + } + else + { + RT_TRACE(COMP_CCX, DBG_WARNING, ("Signature length is too long (limit = %d)\n", MAX_SIG_LENGTH)); + } + + return bMatched; +} + +// +// Description: +// Get signature at DataOffset and advance to the begining of +// next protocol. +// +// Arguments: +// pToken - the parsing token which maintain by parser. +// DataOffset - start offset of signature. +// HeaderLength -length of current protocol. +// pDataBuffer - buffer to store the read signature. +// DataBufLength - lenght of signature to be read. +// +// Return: +// TRUE if read success. +// FALSE if read failed. +// +// Note: +// If pDataBuffer is NULL or DataBufLength is zero, this routine will +// just advance to DataOffset and doesn't read any data. +// +// 2007.07.10, by shien chang. +// +BOOLEAN +GetSignatureAndAdvanceToNextProtocol( + IN PGPPARSE_TOKEN pToken, + IN u4Byte DataOffset, + IN u4Byte HeaderLength, + IN PVOID pDataBuffer, + IN u4Byte DataBufLength + ) +{ + + if (pDataBuffer!=NULL && DataBufLength!=0) + { + if (AdvanceAndGetDataByOffset(pToken, + DataOffset, + FALSE, + pDataBuffer, + DataBufLength)) + { + if (AdvanceAndGetDataByOffset(pToken, + HeaderLength-DataOffset, + FALSE, + NULL, + 0)) + { + return TRUE; + } + } + } + else + { + if (AdvanceAndGetDataByOffset(pToken, + HeaderLength, + FALSE, + NULL, + 0)) + { + return TRUE; + } + } + + return FALSE; +} + +// +// Description: +// Get next line of protocol such as SIP, SDP ... which are +// end with every line a "0x0d 0x0a" seprator. This routine will +// advance to begining of next line after current line has read +// according to bNoAdvance flag. +// +// Arguments: +// pToken - the parsing token which maintain by parser. +// bNoAdvance - TRUE: advance to next line. +// FALSE: don't advance to next line. +// pOutBuffer - buffer to store the read data. +// OutBufferLen - length of pOutBuffer. +// +// Return: +// TRUE if read success. +// FALSE if read failed. +// +// Assumption: +// pOutBuffer can't be NULL. +// OutBufferLen can't be zero. +// +// 2007.07.10, by shien chang. +// +BOOLEAN +GetNextLine( + IN PGPPARSE_TOKEN pToken, + IN BOOLEAN bNoAdvance, + OUT pu1Byte pOutBuffer, + IN u4Byte OutBufferLen + ) +{ + u4Byte BytesRead = 0; + u4Byte i, j; + u4Byte start; + + PlatformZeroMemory(pOutBuffer, OutBufferLen); + + for(i = pToken->currBufferIndex; i < pToken->BufferCount; i ++) + { + if (i == pToken->currBufferIndex) + start = pToken->currBufferOffset; + else + start = 0; + + for (j = start; j < pToken->BufferList[i].Length; j ++) + { + pOutBuffer[BytesRead ++] = pToken->BufferList[i].VirtualAddress[j]; + + if (pOutBuffer[BytesRead-2]==0x0d && + pOutBuffer[BytesRead-1]==0x0a) + { + if (!bNoAdvance) + { + if (j == pToken->BufferList[i].Length-1) + { + if (i + 1 < pToken->BufferCount) + { + pToken->currBufferIndex = i + 1; + pToken->currBufferOffset = 0; + } + else + { + pToken->currBufferIndex = i; + pToken->currBufferOffset = j; + } + } + else + { + pToken->currBufferIndex = i; + pToken->currBufferOffset = j + 1; + } + } + return TRUE; + } + if (BytesRead==OutBufferLen) + return FALSE; + } + } + + return FALSE; +} + +// +// Description: +// Retreat the point back to previous line. This is +// a reverse operation of GetNextLine. +// +// Argument: +// pToken - the parsing token which maintain by parser. +// +// Return: +// TRUE if retreat success. +// FALSE if retreat failed. +// +// 2007.07.10, by shien chang. +// +BOOLEAN +UngetLine( + IN PGPPARSE_TOKEN pToken + ) +{ + u4Byte i, j, len; + u1Byte found = 0, sta = 0; + u4Byte m=0,n=0; + + for (i = pToken->currBufferIndex + 1; i > 0; i --) + { + if (i==pToken->currBufferIndex+1) + len = pToken->currBufferOffset; + else + len = pToken->BufferList[i-1].Length; + + for (j = len; j > 0; j --) + { + if (pToken->BufferList[i-1].VirtualAddress[j-1] == 0x0a) + { + sta++; + continue; + } + if (pToken->BufferList[i-1].VirtualAddress[j-1] == 0x0d) + { + if (sta == 1) + { + found++; + if (found == 2) + { + pToken->currBufferIndex = m; + pToken->currBufferOffset = n; + return TRUE; + } + } + else + sta = 0; + } + + sta = 0; + m = i-1; + n = j-1; + } + + } + + return FALSE; +} + +// +// Description: +// Advance to the offset specific by DataOffset and get following +// bytes into buffer. +// +// Arguments: +// pToken - the parsing token which maintain by parser. +// DataOffset - the offset parser will advance before get data. +// bNoAdvance - TRUE: only get data at DataOffset, not advance to. +// FALSE: advance to DataOffset, and get data. +// pDataBuffer -buffer to store the read data. +// DataBufferLength - lenght of pDataBuffer and bytes to read. +// +// Return: +// TRUE if read success. +// FALSE if read failed. +// +// Note: +// If pDataBuffer is NULL or DataBufLength is zero, this routine will +// just advance to DataOffset and doesn't read any data. +// +// 2007.07.10, by shien chang. +// +BOOLEAN +AdvanceAndGetDataByOffset( + IN PGPPARSE_TOKEN pToken, + IN u4Byte DataOffset, + IN BOOLEAN bNoAdvance, + OUT PVOID pDataBuffer, + IN u4Byte DataBufLength + ) +{ + BOOLEAN bResult = TRUE; + u4Byte BytesRead = 0; + u4Byte i; + u4Byte offset = 0; + pu1Byte pBuffer = (pu1Byte)pDataBuffer; + u4Byte len; + u4Byte tmpIndex=0, tmpOffset=0; + BOOLEAN bOnlyAdvance = (pDataBuffer==NULL || DataBufLength==0) ? TRUE : FALSE; + BOOLEAN bOnlyAdvanceComplete = FALSE; + + for(i = pToken->currBufferIndex;i < pToken->BufferCount; i ++) + { + if(pToken->BufferList[i].Length==0) + continue; + + if (i == pToken->currBufferIndex) + { + len = pToken->BufferList[i].Length - pToken->currBufferOffset; + } + else + { + len = pToken->BufferList[i].Length; + } + + for (; (BytesRead!=DataBufLength) || bOnlyAdvance; BytesRead ++) + { + if ( (len + offset) > (DataOffset + BytesRead) ) + { + u4Byte ByteIndexToCopy = + (i == pToken->currBufferIndex) ? + (DataOffset+BytesRead + pToken->currBufferOffset ) - offset : + (DataOffset+BytesRead) - offset; + + + if (!bOnlyAdvance) + pBuffer[BytesRead] = pToken->BufferList[i].VirtualAddress[ByteIndexToCopy]; + + if (BytesRead == 0) + { + tmpIndex = i; + tmpOffset = ByteIndexToCopy; + + if (bOnlyAdvance) + { + bOnlyAdvanceComplete = TRUE; + break; + } + } + } + else + break; + } + + if (bOnlyAdvance) + { + if (bOnlyAdvanceComplete) + break; + } + else + { + if (BytesRead == DataBufLength) + break; + } + offset += len; + } + + if (!bOnlyAdvance && BytesRead != DataBufLength) + { + RT_TRACE(COMP_CCX, DBG_LOUD, ("AdvanceAndGetDataByOffset(): some data can not be retrived\n")); + bResult = FALSE; + } + + if (bResult && !bNoAdvance) + { + pToken->currBufferIndex = tmpIndex; + pToken->currBufferOffset = tmpOffset; + } + + return bResult; +} + + +//============================================================================= +// End of Private utility function. +//============================================================================= + + + + +//============================================================================= +// Public parser interface. +//============================================================================= + +// +// Description: +// Use high performance parser. +// 2007.07.12, by shien chang. +// +VOID +GPUseHPParser( + IN PGENERIC_PARSER pParser + ) +{ + PGP_HP_ENTRY pEntry, pTmpEntry; + PGP_HP_NODE pNode; + PGP_RULE pRuleSet[2]; + PGP_RULE pRule; + u4Byte i, j; + u4Byte entryIndex = 0; + u4Byte nodeIndex = 0; + u4Byte currNode=0, nextNode=0; + PRT_LIST_ENTRY pListEntry; + + if (pParser->pParsingTree == NULL) + { + pParser->bUseHP = FALSE; + return; + } + + pRuleSet[0] = GPGlobalRule; + pRuleSet[1] = pParser->pParseRules; + + for (i = 0; i < 2; i ++) + { + for (pRule = pRuleSet[i]; + (pRule != NULL) && (pRule->CurrProtocol != 0); + pRule ++) + { + for (j = 0; j < nodeIndex; j ++) + { + pNode = GP_HP_GET_NODE_BY_INDEX(pParser->pParsingTree, j); + if (pNode->ProtocolId == pRule->CurrProtocol) + { + currNode = j; + break; + } + } + if (j == nodeIndex) + { + currNode = nodeIndex; + pNode = GP_HP_GET_NODE_BY_INDEX(pParser->pParsingTree, currNode); + pNode->ProtocolId = pRule->CurrProtocol; + pNode->bUsed = TRUE; + RTInitializeListHead(&(pNode->Link)); + nodeIndex ++; + if (nodeIndex == MAX_HP_PROTOCOL_PER_PARSER) + { + pParser->bUseHP = FALSE; + return; + } + } + + for (j = 0; j < nodeIndex; j ++) + { + pNode = GP_HP_GET_NODE_BY_INDEX(pParser->pParsingTree, j); + if (pNode->ProtocolId == pRule->NextProtocol) + { + nextNode = j; + break; + } + } + if (j == nodeIndex) + { + nextNode = nodeIndex; + pNode = GP_HP_GET_NODE_BY_INDEX(pParser->pParsingTree, nextNode); + pNode->ProtocolId = pRule->NextProtocol; + pNode->bUsed = TRUE; + RTInitializeListHead(&(pNode->Link)); + nodeIndex++; + if (nodeIndex == MAX_HP_PROTOCOL_PER_PARSER) + { + pParser->bUseHP = FALSE; + return; + } + } + + pEntry = GP_HP_GET_ENTRY_BY_INDEX(pParser->pParsingTree, entryIndex); + pNode = GP_HP_GET_NODE_BY_INDEX(pParser->pParsingTree, currNode); + + // Check overwrite. + for (pListEntry = (&pNode->Link)->Flink; + pListEntry != &pNode->Link; + pListEntry = pListEntry->Flink) + { + pTmpEntry = (PGP_HP_ENTRY)pListEntry; + if ( (pTmpEntry->pRule->CurrProtocol == pRule->CurrProtocol) && + (pTmpEntry->pRule->NextProtocol == pRule->NextProtocol) ) + { + RTRemoveEntryList(pListEntry); + break; + } + } + + pEntry->pRule = pRule; + pEntry->index = (u1Byte)nextNode; + RTInsertTailList(&(pNode->Link), &(pEntry->Link)); + entryIndex++; + if (entryIndex == MAX_HP_RULES_PER_PARSER) + { + pParser->bUseHP = FALSE; + return; + } + + } + } + + pParser->bUseHP = TRUE; +} + +// +// Description: +// This routine parse ethernet header. +// 2007.07.10, by shien chang. +// +BOOLEAN +GPParserHandlerEthernet( + IN PADAPTER Adapter, + IN PVOID pParserContext, + IN PROTO_ID CurrProtocol, + IN PROTO_ID NextProtocol, + OUT pu1Byte pSigBuffer, + IN u4Byte SigBufferLen, + IN PGPPARSE_TOKEN pToken, + OUT pu4Byte AdvBytes + ) +{ + u2Byte typeLength; + BOOLEAN bResult = FALSE; + + *AdvBytes = PROTO_UNKNOWN_HDRLEN; + if (pSigBuffer == NULL) return FALSE; + + typeLength = N2H2BYTE( *((UNALIGNED pu2Byte)pSigBuffer) ); + + switch (NextProtocol) + { + case PROTO_IP: + if (typeLength == 0x0800) + { + *AdvBytes = PROTO_ETHERNET_HDRLEN; + bResult = TRUE; + } + break; + + default: + break; + } + + return bResult; +} + +// +// Description: +// This routine parse 802.11 wlan header. +// 2007.07.10, by shien chang. +// +BOOLEAN +GPParserHandlerWlan( + IN PADAPTER Adapter, + IN PVOID pParserContext, + IN PROTO_ID CurrProtocol, + IN PROTO_ID NextProtocol, + OUT pu1Byte pSigBuffer, + IN u4Byte SigBufferLen, + IN PGPPARSE_TOKEN pToken, + OUT pu4Byte AdvBytes + ) +{ + PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo); + u4Byte QosCtrlLen = 0; + + *AdvBytes = PROTO_UNKNOWN_HDRLEN; + if (pSigBuffer == NULL) + return FALSE; + + if ( IsDataFrame(pSigBuffer) ) + { + if( IsQoSDataFrame( pToken->BufferList[0].VirtualAddress ) ) + { + QosCtrlLen = sQoSCtlLng; + } + + *AdvBytes = sMacHdrLng+QosCtrlLen+pMgntInfo->SecurityInfo.EncryptionHeadOverhead; + return TRUE; + } + + return FALSE; +} + +// +// Description: +// This routine parse 802.11 wlan LLC header. +// 2007.07.10, by shien chang. +// +BOOLEAN +GPParserHandlerWlanLlc( + IN PADAPTER Adapter, + IN PVOID pParserContext, + IN PROTO_ID CurrProtocol, + IN PROTO_ID NextProtocol, + OUT pu1Byte pSigBuffer, + IN u4Byte SigBufferLen, + IN PGPPARSE_TOKEN pToken, + OUT pu4Byte AdvBytes + ) +{ + u2Byte typeLength; + BOOLEAN bResult = FALSE; + + *AdvBytes = PROTO_UNKNOWN_HDRLEN; + if (pSigBuffer == NULL) + return FALSE; + typeLength = N2H2BYTE( *((UNALIGNED pu2Byte)pSigBuffer) ); + + switch (NextProtocol) + { + case PROTO_IP: + if (typeLength == 0x0800) + { + *AdvBytes = PROTO_WLAN_LLC_HDRLEN; + bResult = TRUE; + } + break; + + default: + break; + } + + return bResult; +} + +// +// Description: +// This routine parse ip header. +// 2007.07.10, by shien chang. +// +BOOLEAN +GPParserHandlerIP( + IN PADAPTER Adapter, + IN PVOID pParserContext, + IN PROTO_ID CurrProtocol, + IN PROTO_ID NextProtocol, + OUT pu1Byte pSigBuffer, + IN u4Byte SigBufferLen, + IN PGPPARSE_TOKEN pToken, + OUT pu4Byte AdvBytes + ) +{ + u1Byte type = *pSigBuffer; + BOOLEAN bResult = FALSE; + + *AdvBytes = PROTO_UNKNOWN_HDRLEN; + if (pSigBuffer == NULL) + return FALSE; + + switch (NextProtocol) + { + case PROTO_TCP: + if (type == 0x06) + { + *AdvBytes = PROTO_IP_HDRLEN; + bResult = TRUE; + } + break; + + case PROTO_UDP: + if (type == 0x11) + { + *AdvBytes = PROTO_IP_HDRLEN; + bResult = TRUE; + } + break; + + default: + break; + } + + return bResult; +} + +// +// Description: +// Allocate a parser and associate the parser with a gate +// routine which checks parsing criteria and a action routine +// which decides how to handle the parsed packet. +// 2007.07.10, by shien chang. +// +BOOLEAN +GPAllocateParser( + IN PADAPTER Adapter, + IN u1Byte Pid, + IN const char* strParserName, + IN ifAllocateParser AllocateRoutine, + IN GPParserGate ParserGateRoutine, + IN GPParserAction ParserActionRoutine, + IN BOOLEAN bUseHP + ) +{ + PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo); + RT_STATUS Status; + u4Byte i; + BOOLEAN bFound = FALSE; + PGENERIC_PARSER pParser; + + // + // Allocate global data structure first. + // + if (pMgntInfo->pGenericParser == NULL) + { + Status = PlatformAllocateMemory( + Adapter, + &(pMgntInfo->pGenericParser), + sizeof(PGENERIC_PARSER) * MAX_PARSER_NUM); + if (Status != RT_STATUS_SUCCESS) + { + RT_TRACE(COMP_CCX, DBG_SERIOUS, ("GPAllocateParser(): Failed to allocate parsers\n")); + return FALSE; + } + + PlatformZeroMemory(pMgntInfo->pGenericParser, + sizeof(PGENERIC_PARSER) * MAX_PARSER_NUM); + } + + // + // Try to allocate parser. + // + for (i = 0; i < MAX_PARSER_NUM; i ++) + { + if ( *(((PGENERIC_PARSER*)pMgntInfo->pGenericParser) + i) == NULL) + { + // + // Allocate parser + // + Status = PlatformAllocateMemory( + Adapter, + (PVOID*)&pParser, + sizeof(GENERIC_PARSER)); + if (Status != RT_STATUS_SUCCESS) + { + RT_TRACE(COMP_CCX, DBG_SERIOUS, ("GPAllocateParser(): Failed to allocate parser\n")); + return FALSE; + } + + PlatformZeroMemory(pParser, sizeof(GENERIC_PARSER)); + + pParser->PID = Pid; + PlatformZeroMemory(pParser->ParserName, MAX_PARSER_NAME); + if (strParserName) + { + ASCII_STR_COPY(pParser->ParserName, strParserName, MAX_PARSER_NAME); + } + pParser->Gate = ParserGateRoutine; + pParser->Action = ParserActionRoutine; + pParser->bUseHP = bUseHP; + + if (bUseHP) + { + // + // Allocate HP rule structure. + // + Status = PlatformAllocateMemory( + Adapter, + (PVOID*)&pParser->pParsingTree, + MAX_HP_PROTOCOL_PER_PARSER * sizeof(GP_HP_NODE) + + MAX_HP_RULES_PER_PARSER * sizeof(GP_HP_ENTRY)); + if (Status != RT_STATUS_SUCCESS) + { + pParser->pParsingTree = NULL; + } + + PlatformZeroMemory(pParser->pParsingTree, + MAX_HP_PROTOCOL_PER_PARSER * sizeof(GP_HP_NODE) + + MAX_HP_RULES_PER_PARSER * sizeof(GP_HP_ENTRY)); + } + else + { + pParser->pParsingTree = NULL; + } + + // + // Allocate specific data. + // + if (AllocateRoutine) + { + if (! AllocateRoutine(Adapter, pParser)) + { + GPFreeParser(Adapter, Pid, NULL); + return FALSE; + } + } + + *(((PGENERIC_PARSER*)pMgntInfo->pGenericParser) + i) = pParser; + + bFound = TRUE; + break; + } + } + + return bFound; +} + +// +// Description: +// Deallocate parser allocated at GPAllocateParser. +// 2007.07.10, by shien chang. +// +VOID +GPFreeParser( + IN PADAPTER Adapter, + IN u1Byte Pid, + IN ifFreeParser FreeRoutine + ) +{ + PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo); + BOOLEAN bClear = TRUE; + u4Byte i; + PGENERIC_PARSER pParser; + + if (pMgntInfo->pGenericParser == NULL) + return; + + // + // Try to free parser. + // + for (i = 0; i < MAX_PARSER_NUM; i++) + { + pParser = *(((PGENERIC_PARSER*)pMgntInfo->pGenericParser) + i); + if (pParser) + { + if (pParser->PID == Pid) + { + if (FreeRoutine) + FreeRoutine(Adapter, pParser); + + if (pParser->pParsingTree) + { + PlatformFreeMemory( + pParser->pParsingTree, + MAX_HP_PROTOCOL_PER_PARSER * sizeof(GP_HP_NODE) + + MAX_HP_RULES_PER_PARSER * sizeof(GP_HP_ENTRY)); + } + + PlatformFreeMemory(pParser, sizeof(GENERIC_PARSER)); + + *(((PGENERIC_PARSER*)pMgntInfo->pGenericParser)+i) = NULL; + break; + } + } + } + + // + // Free all pointer if no parser. + // + for (i=0; i < MAX_PARSER_NUM; i++) + { + pParser = *(((PGENERIC_PARSER*)pMgntInfo->pGenericParser) + i); + if (pParser) + { + bClear = FALSE; + break; + } + } + + if (bClear) + { + PlatformFreeMemory(pMgntInfo->pGenericParser, + sizeof(PGENERIC_PARSER) * MAX_PARSER_NUM); + } +} + + + +// +// Description: +// Parse Tx packet which started as InitProtocol. +// 2007.07.10, by shien chang. +// +TR_ACTION +GPParseTCB( + IN PADAPTER Adapter, + IN PRT_TCB pTcb, + IN PROTO_ID InitProtocol + ) +{ + GPPARSE_TOKEN token; + PGPPARSE_TOKEN pToken = &token; + + PlatformZeroMemory(pToken, sizeof(GPPARSE_TOKEN)); + + PlatformMoveMemory(pToken->BufferList, + pTcb->BufferList, + sizeof(SHARED_MEMORY) * MAX_PER_PACKET_BUFFER_LIST_LENGTH); + pToken->BufferCount = pTcb->BufferCount; + pToken->currBufferIndex = 0; + pToken->currBufferOffset = 0; + pToken->currProtocol = InitProtocol; + pToken->pDataObj = pTcb; + pToken->gpFlag = GPFLAG_TX; + + return ParseBuffer(Adapter, pToken); + +} + +// +// Description: +// Parse Rx packet which started as InitProtocol. +// 2007.07.10, by shien chang. +// +TR_ACTION +GPParseRFD( + IN PADAPTER Adapter, + IN PRT_RFD pRfd, + IN PROTO_ID InitProtocol + ) +{ + GPPARSE_TOKEN token; + PGPPARSE_TOKEN pToken = &token; + + PlatformZeroMemory(pToken, sizeof(GPPARSE_TOKEN)); + + pToken->BufferList[0].VirtualAddress = pRfd->Buffer.VirtualAddress + pRfd->FragOffset; + pToken->BufferList[0].Length = pRfd->FragLength; + pToken->BufferCount = 1; + pToken->currBufferIndex = 0; + pToken->currBufferOffset = 0; + pToken->currProtocol = InitProtocol; + pToken->pDataObj = pRfd; + pToken->gpFlag = GPFLAG_RX; + + return ParseBuffer(Adapter, pToken); + +} + + +//============================================================================= +// End of Public parser interface. +//============================================================================= + +//============================================================================= +// Custom parser routines. +//============================================================================= + +// +// Description: +// Gate routine of VOWLAN parser. +// If return TRUE, parser rules will be driven. +// If return FALSE, parser will skip it's work. +// 2007.07.10, by shien chang. +// +BOOLEAN +GPParserGateVoWlanSIP( + IN PADAPTER Adapter, + IN PVOID pParser + ) +{ + PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo); + PSTA_QOS pStaQos = pMgntInfo->pStaQos; + + // + // Check if WMM is enabled, CCX is version 4 + // + if (pMgntInfo->mAssoc) + { + if ( (pMgntInfo->pStaQos->CurrentQosMode & QOS_WMM) || + (pMgntInfo->pStaQos->CurrentQosMode & QOS_WMMSA) ) + { + u1Byte CurrCcxVerNumber = 0; + + CCX_QueryVersionNum(Adapter, &CurrCcxVerNumber); + + if ( CurrCcxVerNumber >= 4 ) + { + pu1Byte param = GET_WMM_PARAM_ELE_AC_PARAM(pStaQos->WMMParamEle); + u1Byte acmVO = GET_WMM_AC_PARAM_ACM(param + AC3_VO * 4); + + if (acmVO) + return TRUE; + } + } + } + + return FALSE; +} + +// +// Description: +// Allocation routine of VOWLAN parser. +// 2007.07.10, by shien chang. +// +BOOLEAN +GPAllocateParserVoWlanSIP( + IN PADAPTER Adapter, + IN PGENERIC_PARSER pParser + ) +{ + PGP_VOWLAN_CONTEXT pContext; + RT_STATUS Status; + + Status = PlatformAllocateMemory(Adapter, + (PVOID*)&pContext, + sizeof(GP_VOWLAN_CONTEXT)); + if (Status != RT_STATUS_SUCCESS) + { + RT_TRACE(COMP_CCX, DBG_SERIOUS, ("GPAllocateParserVoWlanSIP(): Failed to allocate memory\n")); + return FALSE; + } + + PlatformZeroMemory(pContext, sizeof(GP_VOWLAN_CONTEXT)); + + GP_REGISTER_RULES(pParser, GPVoWlanSipRule); + GP_BIND_CONTEXT(pParser, pContext); + + if (pParser->pParsingTree && pParser->bUseHP) + GPUseHPParser(pParser); + + return TRUE; +} + +// +// Description: +// Deallocation routine of VOWLAN parser. +// 2007.07.10, by shien chang. +// +BOOLEAN +GPFreeParserVoWlanSIP( + IN PADAPTER Adapter, + IN PGENERIC_PARSER pParser + ) +{ + PGP_VOWLAN_CONTEXT pContext; + + pContext = (PGP_VOWLAN_CONTEXT)GP_GET_CONTEXT(pParser); + if (pContext) + { + PlatformFreeMemory(pContext, sizeof(GP_VOWLAN_CONTEXT)); + } + + GP_UNBIND_CONTEXT(pParser); + GP_UNREGISTER_RULES(pParser); + + return TRUE; +} + +// +// Description: +// Action routine of VOWLAN parser. +// 2007.07.10, by shien chang. +// +TR_ACTION +GPParserActionVoWlanSIP( + IN PADAPTER Adapter, + IN PGPPARSE_TOKEN pToken, + IN PVOID pParser + ) +{ + TR_ACTION trAction = TR_ACTION_CONTINUE; + //PGENERIC_PARSER pGPParser = (PGENERIC_PARSER)pParser; + //PGP_VOWLAN_CONTEXT pContext = (PGP_VOWLAN_CONTEXT)pGPParser->ParserContext; + + return trAction; +} + + +// +// Description: +// Custom routine to parse UDP to SIP. +// 2007.07.10, by shien chang. +// +BOOLEAN +GPParserCustomHandleUDP2SIP( + IN PADAPTER Adapter, + IN PVOID pParserContext, + IN PROTO_ID CurrProtocol, + IN PROTO_ID NextProtocol, + OUT pu1Byte pSigBuffer, + IN u4Byte SigBufferLen, + IN PGPPARSE_TOKEN pToken, + OUT pu4Byte AdvBytes + ) +{ + PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo); + PSTA_QOS pStaQos = pMgntInfo->pStaQos; + u1Byte line[256]; + const char* InviteSig = "INVITE sip:"; + const char* StatusSig = "SIP/2.0"; + const char* ByeSig = "BYE sip:"; + const char* NotifySig = "NOTIFY sip:"; + const char* AckSig = "ACK sip:"; + BOOLEAN bReturn = FALSE; + RT_SPINLOCK_TYPE SpinLockType; + BOOLEAN bQosData = FALSE; + BOOLEAN bRejectData = FALSE; + + RT_ASSERT( ((pToken->gpFlag == GPFLAG_TX)||(pToken->gpFlag == GPFLAG_RX)), + ("GPParserCustomHandleUDP2SIP(): Parser flag must either be GPFLAG_TX or GPFLAG_RX\n")); + + if (pToken->gpFlag == GPFLAG_TX) + SpinLockType = RT_TX_SPINLOCK; + else if (pToken->gpFlag == GPFLAG_RX) + SpinLockType = RT_RX_SPINLOCK; + else + return bReturn; + + *AdvBytes = PROTO_UNKNOWN_HDRLEN; + + if (!GetNextLine(pToken, TRUE, line, sizeof(line)) ) + return FALSE; + + switch (NextProtocol) + { + case PROTO_SIP_INVITE: + if (PlatformCompareMemory( + &(line[PROTO_UDP_HDRLEN]), (PVOID)InviteSig, 11) == 0) + { + RT_TRACE(COMP_CCX , DBG_LOUD, ("GPParserCustomHandleUDP2SIP(): PROTO_SIP_INVITE, pToken->gpFlag = %02X\n", pToken->gpFlag)); + CCX_GPParserCustomHandleUDP2SIP(Adapter, SpinLockType, &bQosData, &bReturn, &bRejectData); + } + break; + + case PROTO_SIP_STATUS: + if (PlatformCompareMemory( + &line[PROTO_UDP_HDRLEN], + (PVOID)StatusSig, + 7) == 0) + { + if (CCX_CAC_IsVoiceTsExist(Adapter)) + { + bQosData = TRUE; + bReturn = TRUE; + } + else if(pToken->gpFlag == GPFLAG_TX) + { // Reject the status packet responding to the in-call. + bRejectData = TRUE; + } + } + break; + + case PROTO_SIP_BYE: + if (PlatformCompareMemory( + &line[PROTO_UDP_HDRLEN], + (PVOID)ByeSig, + 8) == 0) + { + PlatformReleaseSpinLock(Adapter, SpinLockType); + RT_TRACE(COMP_CCX, DBG_LOUD, ("GPParserCustomHandleUDP2SIP(): PROTO_SIP_BYE, pToken->gpFlag = %02X\n", pToken->gpFlag)); + CCX_CAC_DelTs(Adapter); + PlatformAcquireSpinLock(Adapter, SpinLockType); + bReturn = TRUE; + } + break; + + case PROTO_SIP_NOTIFY: + if (PlatformCompareMemory( + &line[PROTO_UDP_HDRLEN], + (PVOID)NotifySig, + 11) == 0) + { + //if (CCX_CAC_IsSignalTsExist(Adapter)) + if (CCX_CAC_IsVoiceTsExist(Adapter)) + bQosData = TRUE; + bReturn = TRUE; + } + break; + + case PROTO_SIP_ACK: + if (PlatformCompareMemory( + &line[PROTO_UDP_HDRLEN], + (PVOID)AckSig, + 8) == 0) + { + //if (CCX_CAC_IsSignalTsExist(Adapter)) + if (CCX_CAC_IsVoiceTsExist(Adapter)) + bQosData = TRUE; + bReturn = TRUE; + } + break; + + default: + break; + } + + if (bQosData) + { + *AdvBytes = PROTO_UDP_HDRLEN; + if (pToken->gpFlag == GPFLAG_TX) + { + PQOS_TSTREAM pTs = NULL; + PRT_TCB pTcb = (PRT_TCB)pToken->pDataObj; + pu1Byte pHeader = pTcb->BufferList[0].VirtualAddress; + if (pTcb) + { + pTcb->DataRate = RT_CCX_CAC_MIN_PHY_RATE(Adapter); + pTcb->TSID = 0; + pTcb->priority = 6; + SET_80211_HDR_QOS_EN(pHeader, 1); + + if (!ACTING_AS_AP(Adapter)) + { + pTs = &(pStaQos->StaTsArray[pTcb->TSID]); + if (pTs && pTs->bUsed) + { + pTcb->DataRate = QosGetNPR(Adapter, pTs); + } + } + } + } + } + else if (bRejectData) + { + PRT_TCB pTcb = (PRT_TCB)pToken->pDataObj; + if (pTcb) pTcb->TSID = SESSION_REJECT_TSID; + } + + return bReturn; +} + +// +// Description: +// Custom routine to parse SIP to SDP. +// 2007.07.10, by shien chang. +// +BOOLEAN +GPParserCustomHandleSIP2SDP( + IN PADAPTER Adapter, + IN PVOID pParserContext, + IN PROTO_ID CurrProtocol, + IN PROTO_ID NextProtocol, + OUT pu1Byte pSigBuffer, + IN u4Byte SigBufferLen, + IN PGPPARSE_TOKEN pToken, + OUT pu4Byte AdvBytes + ) +{ + u1Byte line[256]; + const char* AudioSig = "m=audio"; + + *AdvBytes = PROTO_UNKNOWN_HDRLEN; + + while (GetNextLine(pToken, FALSE, line, sizeof(line)) ) + { + if (PlatformCompareMemory(line, (PVOID)AudioSig, 7) == 0) + { + return TRUE; + } + } + + return FALSE; +} + +// +// Description: +// Custom routine to handle SIP STATUS message. +// 2007.07.10, by shien chang. +// +BOOLEAN +GPParserCustomHandleSIPSTATUS( + IN PADAPTER Adapter, + IN PVOID pParserContext, + IN PROTO_ID CurrProtocol, + IN PROTO_ID NextProtocol, + OUT pu1Byte pSigBuffer, + IN u4Byte SigBufferLen, + IN PGPPARSE_TOKEN pToken, + OUT pu4Byte AdvBytes + ) +{ + u1Byte line[256]; + u1Byte callId[MAX_SESSION_ID]; + u4Byte callIdLen; + RT_SPINLOCK_TYPE SpinLockType; + + RT_ASSERT( ((pToken->gpFlag == GPFLAG_TX)||(pToken->gpFlag == GPFLAG_RX)), + ("GPParserCustomHandleUDP2SIP(): Parser flag must either be GPFLAG_TX or GPFLAG_RX\n")); + + if (pToken->gpFlag == GPFLAG_TX) + SpinLockType = RT_TX_SPINLOCK; + else if (pToken->gpFlag == GPFLAG_RX) + SpinLockType = RT_RX_SPINLOCK; + else + return FALSE; + + *AdvBytes = PROTO_UNKNOWN_HDRLEN; + + if (GetNextLine(pToken, TRUE, line, sizeof(line)) ) + { + // + // SIP reponse status code: + // 1XX Provisional 100 Trying + // 2XX Successful 200 OK + // 3XX Redirection 302 Moved Temporarily + // 4XX Client Error 404 Not Found + // 5XX Server Error 504 Server Time-out + // 6XX Global Failure 603 Decline + // By Bruce, 2008-03-17. + // + if ( (line[8] == '4') || (line[8] == '5' || (line[8] == '6') )) + { + if (GetCallId(pToken, FALSE, callId, &callIdLen)) + { + RemoveSession((PGP_VOWLAN_CONTEXT)pParserContext, callId, callIdLen); + } + + PlatformReleaseSpinLock(Adapter, SpinLockType); + RT_TRACE(COMP_CCX, DBG_LOUD, ("GPParserCustomHandleSIPSTATUS(): Remove Session(reason = %02X), pToken->gpFlag = %02X\n", line[8], pToken->gpFlag)); + CCX_CAC_DelTs(Adapter); + PlatformAcquireSpinLock(Adapter, SpinLockType); + + if (pToken->gpFlag == GPFLAG_TX) + { + PRT_TCB pTcb = (PRT_TCB)pToken->pDataObj; + pu1Byte pHeader = pTcb->BufferList[0].VirtualAddress; + if (pTcb) + { + pTcb->TSID = DEFAULT_TSID; + pTcb->priority = 0; + SET_80211_HDR_QOS_EN(pHeader, 0); + } + } + } + } + + return TRUE; +} + +// +// Description: +// Get call id which is contained in SIP message. +// 2007.07.10, by shien chang. +// +BOOLEAN +GetCallId( + IN PGPPARSE_TOKEN pToken, + IN BOOLEAN bNoAdvance, + OUT pu1Byte callId, + OUT pu4Byte callIdLen + ) +{ + u1Byte buf[256]; + u4Byte i; + const char* CallSig = "Call-ID:"; + + while (GetNextLine(pToken, bNoAdvance, buf, sizeof(buf))) + { + if (PlatformCompareMemory(buf, (PVOID)CallSig, 8) == 0) + { + for (i=9; i<sizeof(buf); i++) + { + if (buf[i] == 0x2e) + { + PlatformMoveMemory(callId, &(buf[9]), i-9); + *callIdLen = i-9; + return TRUE; + } + } + } + } + + return FALSE; +} + +// +// Description: +// Session Management - remove a session. +// 2007.07.10, by shien chang. +// +VOID +RemoveSession( + IN PGP_VOWLAN_CONTEXT pContext, + IN pu1Byte sessionId, + IN u4Byte sessionIdLen + ) +{ + u4Byte i; + + if (sessionIdLen > MAX_SESSION_ID) + return; + + for (i = 0; i < MAX_SESSION; i ++) + { + if ( (pContext->Session[i].bUsed == TRUE) && + (pContext->Session[i].sessionIdLen == sessionIdLen) && + (PlatformCompareMemory( + pContext->Session[i].sessionId, + sessionId, + sessionIdLen) == 0) ) + { + RT_PRINT_STR(COMP_CCX, DBG_LOUD, "RemoveSession():\n", pContext->Session[i].sessionId, pContext->Session[i].sessionIdLen); + pContext->Session[i].bUsed = FALSE; + break; + } + } + +} + +// +// Description: +// Custom routine to handle SDP. +// 2007.07.10, by shien chang. +// +BOOLEAN +GPParserCustomHandleSDP( + IN PADAPTER Adapter, + IN PVOID pParserContext, + IN PROTO_ID CurrProtocol, + IN PROTO_ID NextProtocol, + OUT pu1Byte pSigBuffer, + IN u4Byte SigBufferLen, + IN PGPPARSE_TOKEN pToken, + OUT pu4Byte AdvBytes + ) +{ + u1Byte line[256]; + u2Byte port = 0; + u2Byte type = 65535; + u1Byte charTable[] = { '0','1','2','3','4','5','6','7','8','9' }; + u4Byte i,j; + u1Byte callId[MAX_SESSION_ID]; + u4Byte callIdLen; + BOOLEAN bReturn = FALSE; + u4Byte hdrLen=0; + const char* RtpSig = "RTP/AVP"; + + *AdvBytes = PROTO_UNKNOWN_HDRLEN; + + if (GetCallId(pToken, FALSE, callId, &callIdLen)) + { + if (!AddSession((PGP_VOWLAN_CONTEXT)pParserContext, callId, callIdLen)) + { + RT_TRACE(COMP_CCX, DBG_LOUD, ("GPParserCustomHandleUDP2SIP(): Failed to add a call\n")); + return FALSE; + } + } + else + return FALSE; + + if (GPParserCustomHandleSIP2SDP(Adapter, + pParserContext, + CurrProtocol, + NextProtocol, + pSigBuffer, + SigBufferLen, + pToken, + &hdrLen)) + { + if (!UngetLine(pToken)) + return FALSE; + } + else + return FALSE; + + if (!GetNextLine(pToken, TRUE, line, sizeof(line)) ) + return FALSE; + + // get port num + for (i = 8; i < sizeof(line); i ++) + { + for (j = 0; j < sizeof(charTable); j ++) + { + if (line[i] == charTable[j]) + break; + } + + if (j==sizeof(charTable)) + break; + + port = (port*10)+(u2Byte)j; + } + + if (port) + { + i ++; + if ((i + 7 < 256) && PlatformCompareMemory( + &(line[i]), + (PVOID)RtpSig, + 7) == 0) + { + i += 7; + while (line[i] != 0x0d) + { + i ++; + type = 65535; + + for (; i < sizeof(line); i ++) + { + for (j = 0; j < sizeof(charTable); j ++) + { + if (line[i] == charTable[j]) + break; + } + + if (j==sizeof(charTable)) + break; + + if (type==65535) + type=0; + type = (type*10) + (u2Byte)j; + } + + if (type == 0 || type == 8) + { + if (pToken->gpFlag == GPFLAG_TX) + { // Update Port Num + UpdateSessionInfo((PGP_VOWLAN_CONTEXT)pParserContext, callId, callIdLen, port, 0); + bReturn = TRUE; + } + else if (pToken->gpFlag == GPFLAG_RX) + { + // Update Port Num + UpdateSessionInfo((PGP_VOWLAN_CONTEXT)pParserContext, callId, callIdLen, 0, port); + bReturn = TRUE; + } + else + { + RT_TRACE(COMP_CCX, DBG_LOUD, ("GPParserCustomHandleSDP(): Invalid flag\n")); + } + + break; + } + } + } + } + + return bReturn; +} + +// +// Description: +// Session Management - add a new session. +// 2007.07.10, by shien chang. +// +BOOLEAN +AddSession( + IN PGP_VOWLAN_CONTEXT pContext, + IN pu1Byte sessionId, + IN u4Byte sessionIdLen + ) +{ + u4Byte i; + + if (sessionIdLen > MAX_SESSION_ID) + { + RT_TRACE(COMP_CCX, DBG_WARNING, ("AddSession(): Failed, sessionIDLen(%d) > Max(%d)\n", sessionIdLen, MAX_SESSION_ID)); + return FALSE; + } + + RT_PRINT_STR(COMP_CCX, DBG_LOUD, "AddSession():\n", sessionId, sessionIdLen); + + // + // Check if an call can be added. + // + for (i = 0; i < MAX_SESSION; i ++) + { + if (pContext->Session[i].bUsed) + { + if ( (sessionIdLen == pContext->Session[i].sessionIdLen) && + (PlatformCompareMemory(sessionId, + pContext->Session[i].sessionId, + sessionIdLen) == 0) ) + { + RT_TRACE(COMP_CCX, DBG_LOUD, ("AddSession(): This session has been existed!\n")); + return TRUE; + } + } + + if (!pContext->Session[i].bUsed) break; + } + + if (i != MAX_SESSION) + { + PlatformZeroMemory(pContext->Session[i].sessionId, MAX_SESSION_ID); + PlatformMoveMemory(pContext->Session[i].sessionId, sessionId, sessionIdLen); + pContext->Session[i].sessionIdLen = sessionIdLen; + pContext->Session[i].bUsed = TRUE; + return TRUE; + } + + RT_TRACE(COMP_CCX, DBG_WARNING, ("AddSession(): Add Session Failed SessionNum = %d > Max(%d) \n", i, MAX_SESSION)); + + return FALSE; +} + +// +// Description: +// Session Management - update a session information. +// 2007.07.10, by shien chang. +// +BOOLEAN +UpdateSessionInfo( + IN PGP_VOWLAN_CONTEXT pContext, + IN pu1Byte sessionId, + IN u4Byte sessionIdLen, + IN u2Byte srcPort, + IN u2Byte dstPort + ) +{ + u4Byte i; + + if (sessionIdLen > MAX_SESSION_ID) + return FALSE; + + for (i = 0; i < MAX_SESSION; i ++) + { + if ( (pContext->Session[i].bUsed == TRUE) && + (pContext->Session[i].sessionIdLen == sessionIdLen) && + (PlatformCompareMemory( + pContext->Session[i].sessionId, + sessionId, + sessionIdLen) == 0) ) + { + if (srcPort) + pContext->Session[i].srcPort = srcPort; + if (dstPort) + pContext->Session[i].dstPort = dstPort; + return TRUE; + } + } + + return FALSE; +} + +// +// Description: +// Session Management - match a session by port. +// 2007.07.10, by shien chang. +// +BOOLEAN +MatchSession( + IN PGP_VOWLAN_CONTEXT pContext, + IN u2Byte Port, + IN u1Byte Flag + ) +{ + u4Byte i; + + if ( (Flag != GPFLAG_TX) && (Flag != GPFLAG_RX) ) + return FALSE; + if (Port == 0) + return FALSE; + + for (i = 0; i < MAX_SESSION; i ++) + { + if (pContext->Session[i].bUsed) + { + if ( (Flag == GPFLAG_TX) && (pContext->Session[i].srcPort == Port) ) + return TRUE; + if ( (Flag == GPFLAG_RX) && (pContext->Session[i].dstPort == Port) ) + return TRUE; + } + } + + return FALSE; +} + + +// +// Description: +// Custom routine to handle SIP BYE message. +// 2007.07.10, by shien chang. +// +BOOLEAN +GPParserCustomHandleSIPBYE( + IN PADAPTER Adapter, + IN PVOID pParserContext, + IN PROTO_ID CurrProtocol, + IN PROTO_ID NextProtocol, + OUT pu1Byte pSigBuffer, + IN u4Byte SigBufferLen, + IN PGPPARSE_TOKEN pToken, + OUT pu4Byte AdvBytes + ) +{ + u1Byte callId[MAX_SESSION_ID]; + u4Byte callIdLen; + + *AdvBytes = PROTO_UNKNOWN_HDRLEN; + + if (GetCallId(pToken, FALSE, callId, &callIdLen)) + { + RemoveSession((PGP_VOWLAN_CONTEXT)pParserContext, callId, callIdLen); + } + + return TRUE; +} + +// +// Description: +// Custom routine to parse UDP to RTP. +// 2007.07.10, by shien chang. +// +BOOLEAN +GPParserCustomHandleUDP2RTP( + IN PADAPTER Adapter, + IN PVOID pParserContext, + IN PROTO_ID CurrProtocol, + IN PROTO_ID NextProtocol, + OUT pu1Byte pSigBuffer, + IN u4Byte SigBufferLen, + IN PGPPARSE_TOKEN pToken, + OUT pu4Byte AdvBytes + ) +{ + u2Byte PortBuf=0; + u2Byte Port; + u4Byte offset; + BOOLEAN bReturn = FALSE; + + *AdvBytes = PROTO_UNKNOWN_HDRLEN; + + if ( (pToken->gpFlag == GPFLAG_TX) || (pToken->gpFlag == GPFLAG_RX) ) + { + offset = 0; + } + else + { + return FALSE; + } + + if (AdvanceAndGetDataByOffset(pToken, + offset, + TRUE, + (pu1Byte)&PortBuf, + sizeof(PortBuf)) ) + { + Port = N2H2BYTE(PortBuf); + if ( MatchSession((PGP_VOWLAN_CONTEXT)pParserContext, Port, pToken->gpFlag) ) + { + *AdvBytes = PROTO_UDP_HDRLEN; + bReturn = TRUE; + } + } + + return bReturn; +} + +// +// Description: +// Custom routine to parse RTP to G.711. +// 2007.07.10, by shien chang. +// +BOOLEAN +GPParserCustomHandleRTP2G711( + IN PADAPTER Adapter, + IN PVOID pParserContext, + IN PROTO_ID CurrProtocol, + IN PROTO_ID NextProtocol, + OUT pu1Byte pSigBuffer, + IN u4Byte SigBufferLen, + IN PGPPARSE_TOKEN pToken, + OUT pu4Byte AdvBytes + ) +{ + u1Byte type; + + *AdvBytes = PROTO_UNKNOWN_HDRLEN; + + if (AdvanceAndGetDataByOffset(pToken, + 1, + TRUE, + &type, + sizeof(type)) ) + { + // + // RTP payload types: + // 0x0: PCMU(mu-law G.711) Audio Clock rate = 8000 + // 0x08: PCMA(A-law G.711) Audio Clock rate = 8000 + // By Bruce, 2008-03-18. + // + if (type==0x00 || type==0x08) + return TRUE; + } + + return FALSE; +} + +// +// Description: +// Custom routine to handle G.711 packet. +// 2007.07.10, by shien chang. +// +BOOLEAN +GPParserCustomHandleG711( + IN PADAPTER Adapter, + IN PVOID pParserContext, + IN PROTO_ID CurrProtocol, + IN PROTO_ID NextProtocol, + OUT pu1Byte pSigBuffer, + IN u4Byte SigBufferLen, + IN PGPPARSE_TOKEN pToken, + OUT pu4Byte AdvBytes + ) +{ + PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo); + PSTA_QOS pStaQos = pMgntInfo->pStaQos; + PQOS_TSTREAM pTs = NULL; + + *AdvBytes = PROTO_UNKNOWN_HDRLEN; + if (pToken->gpFlag == GPFLAG_TX) + { + PRT_TCB pTcb = (PRT_TCB)pToken->pDataObj; + pu1Byte pHeader = pTcb->BufferList[0].VirtualAddress; + if (pTcb) + { + pTcb->DataRate = RT_CCX_CAC_MIN_PHY_RATE(Adapter); + pTcb->TSID = 0; + pTcb->priority = 6; + SET_80211_HDR_QOS_EN(pHeader, 1); + + if (!ACTING_AS_AP(Adapter)) + { + pTs = &(pStaQos->StaTsArray[pTcb->TSID]); + if (pTs && pTs->bUsed) + { + pTcb->DataRate = QosGetNPR(Adapter, pTs); + } + } + } + } + return TRUE; +} + +// +// Must call After TranslateHandleRxDot11FrameHeader +// Note : No Qos , IV , HTC 802.11 frame !! +// And Data frame !! +// + +BOOLEAN +GPGetParseRFDInfo( + IN PADAPTER Adapter, + IN PRT_RFD pRfd, + IN PRX_FILTER_INFO pRxfiterInfo + ) +{ + /* + typedef struct _RX_FILTER_INFO{ + // MAC + pu1Byte pDA; + pu1Byte pSA; + u1Byte PacketType; // RX_PACKET_TYPE + pu1Byte pEtherType; // 2 bytes : IPv4 , IPv6 , ARP ... + // IP + u1Byte ARPOption; // Request or Response + pu1Byte ARPSPA; // ARP Sender IP + pu1Byte ARPTPA; // ARP Target IP + u1Byte Protocol; // UDP : 0x11 , TCP : 0x06 + //UDP + pu1Byte pDestinationPort; // 2 bytes + }RX_FILTER_INFO,*PRX_FILTER_INFO; + */ + OCTET_STRING frame; + //PRX_FILTER_INFO pRxfiterInfo = &(pRfd->D0FilterCoalPktInfo); + pu1Byte pCurrentbuf; + u1Byte ArpType[2] = {0x08 ,0x06}; + u1Byte IPv4Type[2] = {0x08 ,0x00}; + u1Byte IPv6Type[2] = {0x86 ,0xdd}; + + FillOctetString(frame, pRfd->Buffer.VirtualAddress+PLATFORM_GET_FRAGOFFSET(pRfd), pRfd->PacketLength); + + PlatformZeroMemory(pRxfiterInfo, sizeof(RX_FILTER_INFO)); + + // Just for Data packet !! + if(!IsDataFrame(frame.Octet)) + { + pRxfiterInfo->PacketType = RXPacketTypeUndefined; + return FALSE; + } + + // MAC !! + pRxfiterInfo->pDA = Frame_pDaddr(frame); + pRxfiterInfo->pSA = Frame_pSaddr(frame); + + if( MacAddr_isBcst(pRxfiterInfo->pDA)) + { + pRxfiterInfo->PacketType = RXPacketTypeBroadcast; + } + else if( MacAddr_isMulticast(pRxfiterInfo->pDA) ) + { + pRxfiterInfo->PacketType = RXPacketTypeMulticast; + } + else + { + pRxfiterInfo->PacketType = RXPacketTypeUnicast; + return TRUE; + } + /* + if( Frame_ValidAddr4(frame) ) + { + offset += 6; May no Address4 frame !! + } + */ + + //RT_PRINT_DATA(COMP_TEST, DBG_LOUD, "===> GPGetParseRFDInfo:\n", frame.Octet, frame.Length); + pRxfiterInfo->pEtherType = frame.Octet + sMacHdrLng + LLC_HEADER_SIZE; + + pCurrentbuf = frame.Octet + sMacHdrLng + LLC_HEADER_SIZE + TYPE_LENGTH_FIELD_SIZE; + + // IP !! + if( PlatformCompareMemory(pRxfiterInfo->pEtherType , ArpType, 2) == 0) + { + // ARP + pRxfiterInfo->ARPOption = pCurrentbuf + 6; + pRxfiterInfo->ARPSPA = pCurrentbuf + 6 + 2 + 6; // 6 Option offset , 2 Option Len , 6 SPA Mac Len + pRxfiterInfo->ARPTPA = pCurrentbuf + 6 + 2 + 6 + 4 + 6 ; // // 6 Option offset , 2 Option Len , 6 SPA Mac Len , 4 SPA len , 6 TPA Mac Len + } + else if(PlatformCompareMemory(pRxfiterInfo->pEtherType , IPv4Type, 2) == 0) + { + pRxfiterInfo->Protocol = pCurrentbuf[9]; + // UDP !! + if(pRxfiterInfo->Protocol == 0x11) + { + u1Byte IPv4len = (pCurrentbuf[0]&0x0f) * 4; + pRxfiterInfo->pDestinationPort = pCurrentbuf + IPv4len + 2; // (pCurrentbuf[0]>>4) IPv4 Heard len 2 Source Port + //RT_PRINT_DATA(COMP_TEST, DBG_LOUD, "IPV4 pRxfiterInfo->pDestinationPort :\n", pRxfiterInfo->pDestinationPort, 2); + } + //RT_TRACE(COMP_TEST, DBG_LOUD , ("===> pRfd nTotalSubframe (%d) \n" , pRfd->nTotalSubframe) ); + } + else if(PlatformCompareMemory(pRxfiterInfo->pEtherType , IPv6Type, 2) == 0) + { + + pRxfiterInfo->Protocol = pCurrentbuf[6]; + // UDP !! + if(pRxfiterInfo->Protocol == 0x11) + { + pRxfiterInfo->pDestinationPort = pCurrentbuf + 40 + 2; // 40 IPv6 Len , 2 Source Port + //RT_PRINT_DATA(COMP_TEST, DBG_LOUD, "IPV6 pRxfiterInfo->pDestinationPort :\n", pRxfiterInfo->pDestinationPort, 2); + } + //RT_TRACE(COMP_TEST, DBG_LOUD , ("===> pRfd nTotalSubframe (%d) \n" , pRfd->nTotalSubframe) ); + } + + + return TRUE; + +} + + +//============================================================================= +// End of Custom parser routines. +//============================================================================= + |
