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

📄 write.c

📁 Windows XP下的抓包程序实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
 * Copyright (c) 2005 - 2006 CACE Technologies, Davis (California)
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the Politecnico di Torino, CACE Technologies 
 * nor the names of its contributors may be used to endorse or promote 
 * products derived from this software without specific prior written 
 * permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "stdarg.h"
#include "ntddk.h"
#include "ntiologc.h"
#include "ndis.h"

#include "debug.h"
#include "packet.h"

extern UINT g_SendPacketFlags;

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

NTSTATUS
NPF_Write(
	IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )

{
    POPEN_INSTANCE		Open;
    PIO_STACK_LOCATION	IrpSp;
    PNDIS_PACKET		pPacket;
    NDIS_STATUS		    Status;
	ULONG				NumSends;
	ULONG				numSentPackets;

	TRACE_ENTER();

	IrpSp = IoGetCurrentIrpStackLocation(Irp);

    Open=IrpSp->FileObject->FsContext;
	
	NumSends = Open->Nwrites;

	//
	// validate the send parameters set by the IOCTL
	//
	if (NumSends == 0)
	{
		Irp->IoStatus.Information = 0;
		Irp->IoStatus.Status = STATUS_SUCCESS;
		IoCompleteRequest(Irp, IO_NO_INCREMENT);
		
		TRACE_EXIT();
		return STATUS_SUCCESS;
	}

	//
	// Validate input parameters: 
	// 1. The packet size should be greater than 0,
	// 2. less-equal than max frame size for the link layer and
	// 3. the maximum frame size of the link layer should not be zero.
	//
	if(IrpSp->Parameters.Write.Length == 0 || 	// Check that the buffer provided by the user is not empty
		Open->MaxFrameSize == 0 ||	// Check that the MaxFrameSize is correctly initialized
		Irp->MdlAddress == NULL ||
		IrpSp->Parameters.Write.Length > Open->MaxFrameSize) // Check that the fame size is smaller that the MTU
	{
		TRACE_MESSAGE(PACKET_DEBUG_LOUD,"Frame size out of range, or maxFrameSize = 0. Send aborted");

		Irp->IoStatus.Information = 0;
		Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
		IoCompleteRequest(Irp, IO_NO_INCREMENT);
		
		TRACE_EXIT();
		return STATUS_UNSUCCESSFUL;
	}

	// 
	// Increment the ref counter of the binding handle, if possible
	//
	if(NPF_StartUsingBinding(Open) == FALSE)
	{ 
		TRACE_MESSAGE(PACKET_DEBUG_LOUD,"Adapter is probably unbinding, cannot send packets");

		Irp->IoStatus.Information = 0;
		Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
		IoCompleteRequest(Irp, IO_NO_INCREMENT);
		
		TRACE_EXIT();
		return STATUS_INVALID_DEVICE_REQUEST;
	} 

	NdisAcquireSpinLock(&Open->WriteLock);
	if(Open->WriteInProgress)
	{
		// Another write operation is currently in progress
		NdisReleaseSpinLock(&Open->WriteLock);

		NPF_StopUsingBinding(Open);

		TRACE_MESSAGE(PACKET_DEBUG_LOUD,"Another Send operation is in progress, aborting.");

		Irp->IoStatus.Information = 0;
		Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
		IoCompleteRequest(Irp, IO_NO_INCREMENT);
		
		TRACE_EXIT();

		return STATUS_UNSUCCESSFUL;
	}
	else
	{
		Open->WriteInProgress = TRUE;
		NdisResetEvent(&Open->NdisWriteCompleteEvent);
	}

	NdisReleaseSpinLock(&Open->WriteLock);

	TRACE_MESSAGE2(PACKET_DEBUG_LOUD,"Max frame size = %u, packet size = %u", Open->MaxFrameSize, IrpSp->Parameters.Write.Length);

	//
	// reset the number of packets pending the SendComplete
	//
	Open->TransmitPendingPackets = 0;

	NdisResetEvent(&Open->WriteEvent);

	numSentPackets = 0;
	
	while( numSentPackets < NumSends )
	{
		NdisAllocatePacket(
			&Status,
			&pPacket,
			Open->PacketPool
			);

		if (Status == NDIS_STATUS_SUCCESS) 
		{
			//
			// packet is available, prepare it and send it with NdisSend.
			//
			
			//
			// 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);
			}


			// The packet hasn't a buffer that needs not to be freed after every single write
			RESERVED(pPacket)->FreeBufAfterWrite = FALSE;

//			// Save the IRP associated with the packet
//			RESERVED(pPacket)->Irp=Irp;

			//  Attach the writes buffer to the packet
			NdisChainBufferAtFront(pPacket,Irp->MdlAddress);

			InterlockedIncrement(&Open->TransmitPendingPackets);
			
			NdisResetEvent(&Open->NdisWriteCompleteEvent);

			//
			//  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
					);
			}

			numSentPackets ++;
		}
		else
		{
			//
			// no packets are available in the Transmit pool, wait some time. The 
			// event gets signalled when at least half of the TX packet pool packets
			// are available
			//
			NdisWaitEvent(&Open->WriteEvent,1);  
		}
	}

	//
	// when we reach this point, all the packets have been enqueued to NdisSend,
	// we just need to wait for all the packets to be completed by the SendComplete
	// (if any of the NdisSend requests returned STATUS_PENDING)
	//
	NdisWaitEvent(&Open->NdisWriteCompleteEvent, 0);

	//
	// all the packets have been transmitted, release the use of the adapter binding
	//
	NPF_StopUsingBinding(Open);

	//
	// no more writes are in progress
	//
	NdisAcquireSpinLock(&Open->WriteLock);
	Open->WriteInProgress = FALSE;
	NdisReleaseSpinLock(&Open->WriteLock);

	//
	// Complete the Irp and return success
	//
	Irp->IoStatus.Status = STATUS_SUCCESS;
	Irp->IoStatus.Information = IrpSp->Parameters.Write.Length;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);
			
	TRACE_EXIT();
	
	return STATUS_SUCCESS;
}

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

INT
NPF_BufferedWrite(
	IN PIRP Irp, 
	IN PCHAR UserBuff, 
	IN ULONG UserBuffSize, 
	BOOLEAN Sync)
{
    POPEN_INSTANCE		Open;
    PIO_STACK_LOCATION	IrpSp;
    PNDIS_PACKET		pPacket;
	UINT				i;
    NDIS_STATUS		    Status;
	LARGE_INTEGER		StartTicks, CurTicks, TargetTicks;
	LARGE_INTEGER		TimeFreq;
	struct timeval		BufStartTime;
	struct sf_pkthdr	*winpcap_hdr;
	PMDL				TmpMdl;
	PCHAR				CurPos;
	PCHAR				EndOfUserBuff = UserBuff + UserBuffSize;

    IF_LOUD(DbgPrint("NPF: BufferedWrite, UserBuff=%p, Size=%u\n", UserBuff, UserBuffSize);)
		
	IrpSp = IoGetCurrentIrpStackLocation(Irp);
	
    Open=IrpSp->FileObject->FsContext;
	
	if( NPF_StartUsingBinding(Open) == FALSE)
	{ 
		// The Network adapter was removed. 
		return 0; 
	} 

	// Sanity check on the user buffer
	if(UserBuff == NULL)
	{
		// 
		// release ownership of the NdisAdapter binding
		//
		NPF_StopUsingBinding(Open);

		return 0;
	}

	// Check that the MaxFrameSize is correctly initialized
	if(Open->MaxFrameSize == 0)
	{
		IF_LOUD(DbgPrint("BufferedWrite: Open->MaxFrameSize not initialized, probably because of a problem in the OID query\n");)

⌨️ 快捷键说明

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