📄 packet.cpp
字号:
NdisFreeBufferPool(g_hBufferPool);
}
}
// ref a packet
VOID ReferencePacket(PPPPOE_PACKET pPacket)
{
NdisInterlockedIncrement(&pPacket->m_lRefCount);
}
// def a packet
VOID DereferencePacket(PPPPOE_PACKET pPacket)
{
LONG lRef = NdisInterlockedDecrement(&pPacket->m_lRefCount);
if(!lRef)
{
// buffer chained
if(pPacket->m_ulFlags & PPPOE_PACKET_BUFFER_CHAINED)
{
NdisUnchainBufferAtFront(pPacket->m_pNdisPacket,&pPacket->m_pNdisBuffer);
}
// allocated from our pool
if(pPacket->m_ulFlags & PPPOE_PACKET_BUFFER_FROM_POOL)
{
NdisAdjustBufferLength(pPacket->m_pNdisBuffer,g_bufferPool.m_ulBufferSize);
FreeBufferToPool(&g_bufferPool,pPacket->m_pFrame);
}
// allocated from ndis pool
if(pPacket->m_ulFlags & PPPOE_PACKET_BUFFER_FROM_NDIS)
{
NdisFreeBuffer(pPacket->m_pNdisBuffer);
}
// call wan send complete
if(pPacket->m_ulFlags & PPPOE_PACKET_NEED_CALL_SEND_COMPLETE)
{
PPROTOCOL_RESERVED pResv = reinterpret_cast<PPROTOCOL_RESERVED>(pPacket->m_pNdisPacket->ProtocolReserved);
NdisMWanSendComplete(pResv->m_pAdapter->m_hMiniportAdapter,pResv->m_pWanPacket,pPacket->m_status);
NdisInterlockedDecrement(&pResv->m_pAdapter->m_lSendPackets);
}
// free to pool
if(pPacket->m_ulFlags & PPPOE_PACKET_FROM_POOL)
{
FreePacketToPool(&g_packetPool,pPacket);
}
// return the packet
if(pPacket->m_ulFlags & PPPOE_PACKET_NEED_RETURN_PACKET)
{
NdisReturnPackets(&pPacket->m_pNdisPacket,1);
NdisInterlockedDecrement(&pPacket->m_pBindContext->m_lPacketNeedReturn);
}
FreePPPOEPacketStorage(pPacket);
}
}
// clone packet
PPPPOE_PACKET ClonePacket(PPPPOE_PACKET pPacket)
{
PPPPOE_PACKET pRet = GetSimplePPPOEPacket();
if(pRet)
{
NdisMoveMemory(pRet->m_pFrame,pPacket->m_pFrame,PPPOE_HEADER_LEN);
NdisMoveMemory(pRet->m_pDataBuffer,pPacket->m_pDataBuffer,PPPOE_MAX_DATA_SIZE);
NdisAdjustBufferLength(pRet->m_pNdisBuffer,ntohs(pPacket->m_pFrame->m_pppFrame.m_usLen) + PPPOE_HEADER_LEN);
}
return pRet;
}
// build pppoe packet from wan packet
PPPPOE_PACKET BuildPPPOEPacketFromWanSendPacket(PADAPTER pAdapter,USHORT usSessionId,PUCHAR pPeerMac,PUCHAR pSelfMac,
PNDIS_WAN_PACKET pWanPacket)
{
PPPPOE_PACKET pRet = NULL;
NDIS_STATUS status;
// check buffer
if( pWanPacket->CurrentLength > PPPOE_MAX_DATA_SIZE ||
pWanPacket->CurrentBuffer - pWanPacket->StartBuffer < PPPOE_MIN_ETH_FRAME_SIZE)
return pRet;
__try
{
// alloc the packet
pRet = AllocPPPOEPacketStorage();
// allocate buffer desc
NdisAllocateBuffer(&status,&pRet->m_pNdisBuffer,g_hBufferPool,pWanPacket->CurrentBuffer - PPPOE_HEADER_LEN,
pWanPacket->CurrentLength + PPPOE_HEADER_LEN);
if(status != NDIS_STATUS_SUCCESS)
ExRaiseStatus(status);
pRet->m_ulFlags |= PPPOE_PACKET_BUFFER_FROM_NDIS;
// get wan buffer safe
UINT ulBufferLen;
NdisQueryBufferSafe(pRet->m_pNdisBuffer,&pRet->m_pRealBuffer,&ulBufferLen,NormalPagePriority);
// get a packet desc
pRet->m_pNdisPacket = GetNdisPacketFromPool(&g_packetPool,&pRet->m_pPacketItem);
if(pRet->m_pNdisPacket)
pRet->m_ulFlags |= PPPOE_PACKET_FROM_POOL;
// chain in the packet
NdisChainBufferAtFront(pRet->m_pNdisPacket,pRet->m_pNdisBuffer);
pRet->m_ulFlags |= PPPOE_PACKET_BUFFER_CHAINED;
// set data buffer pointer
pRet->m_pucDataBuffer = pRet->m_pucFrame + PPPOE_HEADER_LEN;
// copy dst and src mac addr
NdisMoveMemory(pRet->m_pFrame->m_dstMac,pPeerMac,sizeof(pRet->m_pFrame->m_dstMac));
NdisMoveMemory(pRet->m_pFrame->m_srcMac,pSelfMac,sizeof(pRet->m_pFrame->m_dstMac));
// set ethernet type
pRet->m_pFrame->m_usProtocolType = PPPOE_SESSION;
// set session id
pRet->m_pFrame->m_pppFrame.m_usSession = htons(usSessionId);
// set other
pRet->m_pFrame->m_pppFrame.m_ucCode = PPPOE_CODE_PAY_LOAD;
pRet->m_pFrame->m_pppFrame.m_ucType = PPPOE_TYPE;
pRet->m_pFrame->m_pppFrame.m_ucVer = PPPOE_VER;
pRet->m_pFrame->m_pppFrame.m_usLen = (USHORT)htons(pWanPacket->CurrentLength);
// save pointer
PPROTOCOL_RESERVED pResv = reinterpret_cast<PPROTOCOL_RESERVED>(pRet->m_pNdisPacket->ProtocolReserved);
pResv->m_pAdapter = pAdapter;
pResv->m_pPPPOEPacket = pRet;
pResv->m_pWanPacket = pWanPacket;
// prepare it
PreparePacketForSend(pRet);
NdisInterlockedIncrement(&pAdapter->m_lSendPackets);
pRet->m_ulFlags |= PPPOE_PACKET_NEED_CALL_SEND_COMPLETE;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
if(pRet)
{
if(pRet->m_pNdisBuffer)
NdisFreeBuffer(pRet->m_pNdisBuffer);
if(pRet->m_pNdisPacket)
DereferencePacket(pRet);
pRet = NULL;
}
}
return pRet;
}
// create pppop packet reuse buffer
PPPPOE_PACKET CreatePPPOEPacketFromReceived(PBIND_CONTEXT pBind,PNDIS_PACKET pNdisPacket,PNDIS_BUFFER pBuffer,PPPPOE_FRAME pFrame)
{
PPPPOE_PACKET pRet = AllocPPPOEPacketStorage();
pRet->m_ulFlags |= PPPOE_PACKET_NEED_RETURN_PACKET;
pRet->m_pNdisBuffer = pBuffer;
pRet->m_pNdisPacket = pNdisPacket;
pRet->m_pFrame = pFrame;
pRet->m_pucDataBuffer = pRet->m_pucFrame + PPPOE_HEADER_LEN;
pRet->m_pBindContext = pBind;
return pRet;
}
// get pppoe packet from a ndis received packet
PPPPOE_PACKET NdisPacket2PPPOEPacket(PBIND_CONTEXT pBind,PNDIS_PACKET pNdisPacket,PBOOLEAN pNeedCallReturn)
{
*pNeedCallReturn = FALSE;
PPPPOE_PACKET pPPPOEPacket = NULL;
PNDIS_BUFFER pFirstBuffer = NULL;
UINT nBufferCount = 0;
UINT nTotalLen = 0;
// query packet
NdisQueryPacket(pNdisPacket,NULL,&nBufferCount,&pFirstBuffer,&nTotalLen);
if(nTotalLen > PPPOE_MAX_ETH_FRAME_SIZE)
return NULL;
NDIS_STATUS status = NDIS_GET_PACKET_STATUS(pNdisPacket);
if(status != NDIS_STATUS_RESOURCES && nBufferCount == 1)
{
PPPPOE_FRAME pFrame;
UINT uLen;
// query buffer
NdisQueryBufferSafe(pFirstBuffer,(PVOID*)&pFrame,&uLen,NormalPagePriority);
// check return value
if(pFrame && uLen > PPPOE_MIN_ETH_FRAME_SIZE)
{
// check pppoe frame
if(FastCheckIsPPPOEFrame(pFrame,PPPOE_MIN_ETH_FRAME_SIZE))
{
// check frame size
if((UINT)ntohs(pFrame->m_pppFrame.m_usLen) <= uLen)
{
// reuse the buffers
pPPPOEPacket = CreatePPPOEPacketFromReceived(pBind,pNdisPacket,pFirstBuffer,pFrame);
}
}
}
if(pPPPOEPacket)
{
*pNeedCallReturn = TRUE;
NdisInterlockedIncrement(&pBind->m_lPacketNeedReturn);
}
}
else
{
// create new packet
pPPPOEPacket = GetSimplePPPOEPacket();
UINT uCurrentOffset = 0;
PUCHAR pFrame;
UINT uLen;
for(;pFirstBuffer;)
{
// query buffer
NdisQueryBufferSafe(pFirstBuffer,(PVOID *)&pFrame,&uLen,NormalPagePriority);
NdisMoveMemory(pPPPOEPacket->m_pucFrame + uCurrentOffset,pFrame,uLen);
uCurrentOffset += uLen;
NdisGetNextBuffer(pFirstBuffer,&pFirstBuffer);
if(uCurrentOffset < PPPOE_MIN_ETH_FRAME_SIZE)
continue;
if(!FastCheckIsPPPOEFrame(pPPPOEPacket->m_pFrame,PPPOE_MIN_ETH_FRAME_SIZE))
{
uCurrentOffset = 0;
break;
}
}
// check the packet
if(uCurrentOffset < PPPOE_MIN_ETH_FRAME_SIZE || uCurrentOffset < nTotalLen)
DereferencePacket(pPPPOEPacket);
}
return pPPPOEPacket;
}
// prepare packet for send
VOID PreparePacketForSend(PPPPOE_PACKET pPacket)
{
/*
* Serive AC Host ACCookie Relay
* 101 102 103 104 110
* PAY_LOAD
* PADT
* PADI: M O
* PADO: M O O O O
* PADR: M O O O
* PADS: M O O
*/
switch(pPacket->m_pFrame->m_pppFrame.m_ucCode)
{
// pay load
case PPPOE_CODE_PAY_LOAD:
// PADT
case PPPOE_CODE_PADT:
break;
// PADO
case PPPOE_CODE_PADO:
// 0x102 AC name
PPPOEPacketInsertTag(PPPOE_TAG_AC,pPacket,pPacket->m_pACName,pPacket->m_usACName,&pPacket->m_pACName);
// fall through
// PADR
case PPPOE_CODE_PADR:
// 0x104 AC cookie
if(pPacket->m_pFrame->m_pppFrame.m_ucCode != PPPOE_CODE_PADR || pPacket->m_usACCookie)
PPPOEPacketInsertTag(PPPOE_TAG_AC_COOKIE,pPacket,pPacket->m_pACCookie,pPacket->m_usACCookie,&pPacket->m_pACCookie);
// fall through
// PADS
case PPPOE_CODE_PADS:
// 0x110 relay session id
if(pPacket->m_usRelaySessionId)
PPPOEPacketInsertTag(PPPOE_TAG_RELAY_SESSION_ID,pPacket,pPacket->m_pRelaySessionId,pPacket->m_usRelaySessionId,
&pPacket->m_pRelaySessionId);
// fall through
// PADI
case PPPOE_CODE_PADI:
// 0x101 service name
PPPOEPacketInsertTag(PPPOE_TAG_SERVICE,pPacket,pPacket->m_pServiceName,pPacket->m_usServiceName,&pPacket->m_pServiceName);
// 0x103 host unique
if(pPacket->m_usHostUnique)
PPPOEPacketInsertTag(PPPOE_TAG_HOST_UNIQUE,pPacket,pPacket->m_pHostUnique,pPacket->m_usHostUnique,
&pPacket->m_pHostUnique);
break;
}
// set buffer len
NdisAdjustBufferLength(pPacket->m_pNdisBuffer,ntohs(pPacket->m_pFrame->m_pppFrame.m_usLen) + PPPOE_HEADER_LEN);
}
// initialize packet member value
BOOLEAN InitializePPPOEPacketForRecved(PPPPOE_PACKET pPacket)
{
/*
* Serive AC Host ACCookie Relay
* 101 102 103 104 110
* PAY_LOAD
* PADT
* PADI: M O O
* PADO: M M O O O
* PADR: M O O O
* PADS: M O
*/
// check pppoe format
if(!CheckIsPPPOEPacket(pPacket))
return FALSE;
// check len
UCHAR ucCode = pPacket->m_pFrame->m_pppFrame.m_ucCode;
if(ucCode)
{
PUCHAR pEnd = pPacket->m_pucDataBuffer + ntohs(pPacket->m_pFrame->m_pppFrame.m_usLen);
PUCHAR pCurrent = pPacket->m_pucDataBuffer;
while(pCurrent < pEnd)
{
PPPP_TAG pTag = reinterpret_cast<PPPP_TAG>(pCurrent);
pCurrent += ntohs(pTag->m_usLen) + sizeof(PPP_TAG);
}
if(pCurrent != pEnd)
return FALSE;
}
// check erroe tag
switch(pPacket->m_pFrame->m_pppFrame.m_ucCode)
{
case PPPOE_CODE_PAY_LOAD:
case PPPOE_CODE_PADT:
break;
// PADO
case PPPOE_CODE_PADO:
{
// get service name
RetrieveTag(PPPOE_TAG_SERVICE,pPacket,&pPacket->m_pServiceName,&pPacket->m_usServiceName,TRUE);
if(pPacket->m_pServiceName)
{
// get ac name
RetrieveTag(PPPOE_TAG_AC,pPacket,&pPacket->m_pACName,&pPacket->m_usACName,TRUE);
if(pPacket->m_pACName)
{
// ac cookie
RetrieveTag(PPPOE_TAG_AC_COOKIE,pPacket,&pPacket->m_pACCookie,&pPacket->m_usACCookie,TRUE);
// host unique
RetrieveTag(PPPOE_TAG_HOST_UNIQUE,pPacket,&pPacket->m_pHostUnique,&pPacket->m_usHostUnique,TRUE);
// relay session id
RetrieveTag(PPPOE_TAG_RELAY_SESSION_ID,pPacket,&pPacket->m_pRelaySessionId,&pPacket->m_usRelaySessionId,TRUE);
}
}
}
break;
// PADI
case PPPOE_CODE_PADI:
{
// get service name
RetrieveTag(PPPOE_TAG_SERVICE,pPacket,&pPacket->m_pServiceName,&pPacket->m_usServiceName,TRUE);
if(pPacket->m_pServiceName)
{
// host unique
RetrieveTag(PPPOE_TAG_HOST_UNIQUE,pPacket,&pPacket->m_pHostUnique,&pPacket->m_usHostUnique,TRUE);
// relay session id
RetrieveTag(PPPOE_TAG_RELAY_SESSION_ID,pPacket,&pPacket->m_pRelaySessionId,&pPacket->m_usRelaySessionId,TRUE);
}
}
break;
// PADR
case PPPOE_CODE_PADR:
{
// get service name
RetrieveTag(PPPOE_TAG_SERVICE,pPacket,&pPacket->m_pServiceName,&pPacket->m_usServiceName,TRUE);
if(pPacket->m_pServiceName)
{
// ac cookie
RetrieveTag(PPPOE_TAG_AC_COOKIE,pPacket,&pPacket->m_pACCookie,&pPacket->m_usACCookie,TRUE);
// host unique
RetrieveTag(PPPOE_TAG_HOST_UNIQUE,pPacket,&pPacket->m_pHostUnique,&pPacket->m_usHostUnique,TRUE);
// relay session id
RetrieveTag(PPPOE_TAG_RELAY_SESSION_ID,pPacket,&pPacket->m_pRelaySessionId,&pPacket->m_usRelaySessionId,TRUE);
}
}
break;
// PADS
case PPPOE_CODE_PADS:
{
// get service name
RetrieveTag(PPPOE_TAG_SERVICE,pPacket,&pPacket->m_pServiceName,&pPacket->m_usServiceName,TRUE);
if(pPacket->m_pServiceName)
{
// host unique
RetrieveTag(PPPOE_TAG_HOST_UNIQUE,pPacket,&pPacket->m_pHostUnique,&pPacket->m_usHostUnique,TRUE);
}
}
break;
}
// get error tag
RetrieveErrorTag(pPacket);
return TRUE;
}
// init a PADI
PPPPOE_PACKET InitializePADIToSend(PUCHAR pServiceName,USHORT usServiceName,PUCHAR pHostUnique,USHORT usHostUnique)
{
static UCHAR _s_macBroadcast[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
PPPPOE_PACKET pRet = NULL;
__try
{
pRet = GetSimplePPPOEPacket();
NdisMoveMemory(pRet->m_pFrame->m_dstMac,_s_macBroadcast,6);
pRet->m_pFrame->m_usProtocolType = PPPOE_DISCOVERY;
pRet->m_pFrame->m_pppFrame.m_ucVer = PPPOE_VER;
pRet->m_pFrame->m_pppFrame.m_ucType = PPPOE_TYPE;
pRet->m_pFrame->m_pppFrame.m_usSession = 0;
pRet->m_pFrame->m_pppFrame.m_ucCode = PPPOE_CODE_PADI;
pRet->m_pFrame->m_pppFrame.m_usLen = 0;
pRet->m_pServiceName = pServiceName;
pRet->m_usServiceName = usServiceName;
pRet->m_pHostUnique = pHostUnique;
pRet->m_usHostUnique = usHostUnique;
PreparePacketForSend(pRet);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
if(pRet)
DereferencePacket(pRet);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -