⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 packet.cpp

📁 pppoe client
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		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 + -