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

📄 write.c

📁 Windows XP下的抓包程序实现
💻 C
📖 第 1 页 / 共 2 页
字号:
		// 
		// release ownership of the NdisAdapter binding
		//
		NPF_StopUsingBinding(Open);
		return 0;
	}

	// Reset the event used to synchronize packet allocation
	NdisResetEvent(&Open->WriteEvent);
	
	// Reset the pending packets counter
	Open->Multiple_Write_Counter = 0;

	// Start from the first packet
	winpcap_hdr = (struct sf_pkthdr*)UserBuff;
	
	// Retrieve the time references
	StartTicks = KeQueryPerformanceCounter(&TimeFreq);
	BufStartTime.tv_sec = winpcap_hdr->ts.tv_sec;
	BufStartTime.tv_usec = winpcap_hdr->ts.tv_usec;
	
	// Chech the consistency of the user buffer
	if( (PCHAR)winpcap_hdr + winpcap_hdr->caplen + sizeof(struct sf_pkthdr) > EndOfUserBuff )
	{
		IF_LOUD(DbgPrint("Buffered Write: bogus packet buffer\n");)

		// 
		// release ownership of the NdisAdapter binding
		//
		NPF_StopUsingBinding(Open);
		return -1;
	}
	
	// Save the current time stamp counter
	CurTicks = KeQueryPerformanceCounter(NULL);
	
	//
	// Main loop: send the buffer to the wire
	//
	while(TRUE)
	{

		if(winpcap_hdr->caplen ==0 || winpcap_hdr->caplen > Open->MaxFrameSize)
		{
			// Malformed header
			IF_LOUD(DbgPrint("NPF_BufferedWrite: malformed or bogus user buffer, aborting write.\n");)
			
			// 
			// release ownership of the NdisAdapter binding
			//
			NPF_StopUsingBinding(Open);
			return -1;
		}

		// Allocate an MDL to map the packet data
		TmpMdl = IoAllocateMdl((PCHAR)winpcap_hdr + sizeof(struct sf_pkthdr),
			winpcap_hdr->caplen,
			FALSE,
			FALSE,
			NULL);

		if (TmpMdl == NULL)
		{
			// Unable to map the memory: packet lost
			IF_LOUD(DbgPrint("NPF_BufferedWrite: unable to allocate the MDL.\n");)

			// 
			// release ownership of the NdisAdapter binding
			//
			NPF_StopUsingBinding(Open);
			return -1;
		}
		
		MmBuildMdlForNonPagedPool(TmpMdl);	// XXX can this line be removed?
		
		// Allocate a packet from our free list
		NdisAllocatePacket( &Status, &pPacket, Open->PacketPool);
		
		// If asked, set the flags for this packet.
		// Currently, the only situation in which we set the flags is to disable the reception of loopback
		// packets, i.e. of the packets sent by us.
		if(Open->SkipSentPackets)
		{
			NdisSetPacketFlags(
				pPacket,
				g_SendPacketFlags);
		}

		if (Status != NDIS_STATUS_SUCCESS) 
		{
			//  No more free packets
			IF_LOUD(DbgPrint("NPF_BufferedWrite: no more free packets, returning.\n");)

			NdisResetEvent(&Open->WriteEvent);

			NdisWaitEvent(&Open->WriteEvent, 1000);  

			// Try again to allocate a packet
			NdisAllocatePacket( &Status, &pPacket, Open->PacketPool);

			if(Open->SkipSentPackets)
			{
				NdisSetPacketFlags(
					pPacket,
					g_SendPacketFlags);
			}
			
			if (Status != NDIS_STATUS_SUCCESS) 
			{
				// Second failure, report an error
				IoFreeMdl(TmpMdl);
		
				// 
				// release ownership of the NdisAdapter binding
				//
				NPF_StopUsingBinding(Open);
				return -1;
			}

//			IoFreeMdl(TmpMdl);
//			return (PCHAR)winpcap_hdr - UserBuff;
		}

		
		// The packet has a buffer that needs to be freed after every single write
		RESERVED(pPacket)->FreeBufAfterWrite = TRUE;
		
        TmpMdl->Next = NULL;

		// Attach the MDL to the packet
		NdisChainBufferAtFront(pPacket, TmpMdl);
		
		// Increment the number of pending sends
		InterlockedIncrement(&Open->Multiple_Write_Counter);

		// Call the MAC
		NdisSend( &Status, Open->AdapterHandle,	pPacket);

		if (Status != NDIS_STATUS_PENDING) {
			// The send didn't pend so call the completion handler now
			NPF_SendComplete(
				Open,
				pPacket,
				Status
				);				
		}
		
		// Step to the next packet in the buffer
		(PCHAR)winpcap_hdr += winpcap_hdr->caplen + sizeof(struct sf_pkthdr);
		
		// Check if the end of the user buffer has been reached
		if( (PCHAR)winpcap_hdr >= EndOfUserBuff )
		{
			IF_LOUD(DbgPrint("NPF_BufferedWrite: End of buffer.\n");)

			// Wait the completion of pending sends
			NPF_WaitEndOfBufferedWrite(Open);

			// 
			// release ownership of the NdisAdapter binding
			//
			NPF_StopUsingBinding(Open);
	
			return (INT)((PCHAR)winpcap_hdr - UserBuff);
		}
	
		if( Sync ){
			
			// Release the application if it has been blocked for approximately more than 1 seconds
			if( winpcap_hdr->ts.tv_sec - BufStartTime.tv_sec > 1 )
			{
				IF_LOUD(DbgPrint("NPF_BufferedWrite: timestamp elapsed, returning.\n");)
		
				// Wait the completion of pending sends
				NPF_WaitEndOfBufferedWrite(Open);
					
				// 
				// release ownership of the NdisAdapter binding
				//
				NPF_StopUsingBinding(Open);
				return (INT)((PCHAR)winpcap_hdr - UserBuff);
			}
			
			// Calculate the time interval to wait before sending the next packet
			TargetTicks.QuadPart = StartTicks.QuadPart +
				(LONGLONG)((winpcap_hdr->ts.tv_sec - BufStartTime.tv_sec) * 1000000 +
				winpcap_hdr->ts.tv_usec - BufStartTime.tv_usec) *
				(TimeFreq.QuadPart) / 1000000;
			
			// Wait until the time interval has elapsed
			while( CurTicks.QuadPart <= TargetTicks.QuadPart )
				CurTicks = KeQueryPerformanceCounter(NULL);
		}
	
	}

	// 
	// release ownership of the NdisAdapter binding
	//
	NPF_StopUsingBinding(Open);

	return (INT)((PCHAR)winpcap_hdr - UserBuff);
}

//-------------------------------------------------------------------

VOID NPF_WaitEndOfBufferedWrite(POPEN_INSTANCE Open)
{
	UINT i;

	NdisResetEvent(&Open->WriteEvent);

	for(i=0; Open->Multiple_Write_Counter > 0 && i < TRANSMIT_PACKETS; i++)
	{
		NdisWaitEvent(&Open->WriteEvent, 100);  
		NdisResetEvent(&Open->WriteEvent);
	}

	return;
}

//-------------------------------------------------------------------

VOID
NPF_SendComplete(
				   IN NDIS_HANDLE   ProtocolBindingContext,
				   IN PNDIS_PACKET  pPacket,
				   IN NDIS_STATUS   Status
				   )
				   
{
	POPEN_INSTANCE      Open;
	PMDL TmpMdl;
	
	TRACE_ENTER();

	Open= (POPEN_INSTANCE)ProtocolBindingContext;

	if( RESERVED(pPacket)->FreeBufAfterWrite )
	{
		//
		// Packet sent by NPF_BufferedWrite()
		//

		
		// Free the MDL associated with the packet
		NdisUnchainBufferAtFront(pPacket, &TmpMdl);

		IoFreeMdl(TmpMdl);
		
		//  recyle the packet
		//	NdisReinitializePacket(pPacket);

		NdisFreePacket(pPacket);

		// Increment the number of pending sends
		InterlockedDecrement(&Open->Multiple_Write_Counter);

		NdisSetEvent(&Open->WriteEvent);
		
		TRACE_EXIT();
		return;
	}
	else
	{
		//
		// Packet sent by NPF_Write()
		//

		ULONG stillPendingPackets = InterlockedDecrement(&Open->TransmitPendingPackets);

		//
		//  Put the packet back on the free list
		//
		NdisFreePacket(pPacket);

		//
		// if the number of packets submitted to NdisSend and not acknoledged is less than half the
		// packets in the TX pool, wake up any transmitter waiting for available packets in the TX
		// packet pool
		//
		if (stillPendingPackets < TRANSMIT_PACKETS/2)
		{
			NdisSetEvent(&Open->WriteEvent);
		}
		else
		{
			//
			// otherwise, reset the event, so that we are sure that the NPF_Write will eventually block to
			// waitg for availability of packets in the TX packet pool
			//
			NdisResetEvent(&Open->WriteEvent);
		}

		if(stillPendingPackets == 0)
		{
			NdisSetEvent(&Open->NdisWriteCompleteEvent);
		}

		TRACE_EXIT();
		return;
	}
	
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -