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

📄 openclos.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 "stdio.h"
#include "ntddk.h"
#include "ntiologc.h"
#include "ndis.h"

#include "debug.h"
#include "packet.h"
#include "..\..\Common\WpcapNames.h"


static NDIS_MEDIUM MediumArray[] = {
	NdisMedium802_3,
//	NdisMediumWan,
	NdisMediumFddi,
	NdisMediumArcnet878_2,
	NdisMediumAtm,
	NdisMedium802_5
};

#define NUM_NDIS_MEDIA  (sizeof MediumArray / sizeof MediumArray[0])

//Itoa. Replaces the buggy RtlIntegerToUnicodeString
void PacketItoa(UINT n,PUCHAR buf){
int i;

	for(i=0;i<20;i+=2){
		buf[18-i]=(n%10)+48;
		buf[19-i]=0;
		n/=10;
	}

}

/// Global start time. Used as an absolute reference for timestamp conversion.
struct time_conv G_Start_Time = {
	0,	
	{0, 0},	
};

ULONG g_NumOpenedInstances = 0;

BOOLEAN NPF_StartUsingBinding(
    IN POPEN_INSTANCE pOpen)
{
	ASSERT(pOpen != NULL);
	ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
	
	NdisAcquireSpinLock(&pOpen->AdapterHandleLock);

	if (pOpen->AdapterBindingStatus != ADAPTER_BOUND)
	{
		NdisReleaseSpinLock(&pOpen->AdapterHandleLock);
		return FALSE;
	}
	
	pOpen->AdapterHandleUsageCounter++;

	NdisReleaseSpinLock(&pOpen->AdapterHandleLock);
	
	return TRUE;
}

VOID NPF_StopUsingBinding(
    IN POPEN_INSTANCE pOpen)
{
	ASSERT(pOpen != NULL);
//
//  There is no risk in calling this function from abobe passive level 
//  (i.e. DISPATCH, in this driver) as we acquire a spinlock and decrement a 
//  counter.
//
//	ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

	NdisAcquireSpinLock(&pOpen->AdapterHandleLock);

	ASSERT(pOpen->AdapterHandleUsageCounter > 0);
	ASSERT(pOpen->AdapterBindingStatus == ADAPTER_BOUND);

	pOpen->AdapterHandleUsageCounter--;

	NdisReleaseSpinLock(&pOpen->AdapterHandleLock);
}

VOID
NPF_CloseBinding(
    IN POPEN_INSTANCE pOpen)
{
	NDIS_EVENT Event;
	NDIS_STATUS Status;

	ASSERT(pOpen != NULL);
	ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

	NdisInitializeEvent(&Event);
	NdisResetEvent(&Event);

	NdisAcquireSpinLock(&pOpen->AdapterHandleLock);

	while(pOpen->AdapterHandleUsageCounter > 0)
	{
		NdisReleaseSpinLock(&pOpen->AdapterHandleLock);
		NdisWaitEvent(&Event,1);
		NdisAcquireSpinLock(&pOpen->AdapterHandleLock);
	}

	//
	// now the UsageCounter is 0
	//

	while(pOpen->AdapterBindingStatus == ADAPTER_UNBINDING)
	{
		NdisReleaseSpinLock(&pOpen->AdapterHandleLock);
		NdisWaitEvent(&Event,1);
		NdisAcquireSpinLock(&pOpen->AdapterHandleLock);
	}

	//
	// now the binding status is either bound or unbound
	//

	if (pOpen->AdapterBindingStatus == ADAPTER_UNBOUND)
	{
		NdisReleaseSpinLock(&pOpen->AdapterHandleLock);
		return;
	}

	ASSERT(pOpen->AdapterBindingStatus == ADAPTER_BOUND);

	pOpen->AdapterBindingStatus = ADAPTER_UNBINDING;

	NdisReleaseSpinLock(&pOpen->AdapterHandleLock);

	//
	// do the release procedure
	//
	NdisResetEvent(&pOpen->NdisOpenCloseCompleteEvent);

	// Close the adapter
	NdisCloseAdapter(
		&Status,
		pOpen->AdapterHandle
		);

	if (Status == NDIS_STATUS_PENDING)
	{
		TRACE_MESSAGE(PACKET_DEBUG_LOUD, "Pending NdisCloseAdapter");
		NdisWaitEvent(&pOpen->NdisOpenCloseCompleteEvent, 0);
	}
	else
	{
		TRACE_MESSAGE(PACKET_DEBUG_LOUD, "Not Pending NdisCloseAdapter");
	}

	NdisAcquireSpinLock(&pOpen->AdapterHandleLock);
	pOpen->AdapterBindingStatus = ADAPTER_UNBOUND;
	NdisReleaseSpinLock(&pOpen->AdapterHandleLock);
}

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

NTSTATUS NPF_Open(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{

	PDEVICE_EXTENSION	DeviceExtension;
	POPEN_INSTANCE		Open;
	PIO_STACK_LOCATION  IrpSp;
	NDIS_STATUS			Status;
	NDIS_STATUS			ErrorStatus;
	UINT				i;
	PUCHAR				tpointer;
	PLIST_ENTRY			PacketListEntry;
	NTSTATUS			returnStatus;

//  
//	Old registry based WinPcap names
//
//	WCHAR				EventPrefix[MAX_WINPCAP_KEY_CHARS];
//	UINT				RegStrLen;

	TRACE_ENTER();

	DeviceExtension = DeviceObject->DeviceExtension;

	IrpSp = IoGetCurrentIrpStackLocation(Irp);

	//  allocate some memory for the open structure
	Open=ExAllocatePoolWithTag(NonPagedPool, sizeof(OPEN_INSTANCE), '0OWA');

	if (Open==NULL) {
		// no memory
		Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
		IoCompleteRequest(Irp, IO_NO_INCREMENT);
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	RtlZeroMemory(
		Open,
		sizeof(OPEN_INSTANCE)
		);

//  
//	Old registry based WinPcap names
//
//	//
//	// Get the Event names base from the registry
//	//
//	RegStrLen = sizeof(EventPrefix)/sizeof(EventPrefix[0]);
//
//	NPF_QueryWinpcapRegistryString(NPF_EVENTS_NAMES_REG_KEY_WC,
//		EventPrefix,
//		RegStrLen,
//		NPF_EVENTS_NAMES_WIDECHAR);
//
		
	Open->DeviceExtension=DeviceExtension;

	//  Allocate a packet pool for our xmit and receive packets
	NdisAllocatePacketPool(
		&Status,
		&Open->PacketPool,
		TRANSMIT_PACKETS,
		sizeof(PACKET_RESERVED));

	if (Status != NDIS_STATUS_SUCCESS) {

		TRACE_MESSAGE(PACKET_DEBUG_LOUD, "Failed to allocate packet pool");

		ExFreePool(Open);
		Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
		IoCompleteRequest(Irp, IO_NO_INCREMENT);
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	NdisInitializeEvent(&Open->WriteEvent);
	NdisInitializeEvent(&Open->NdisRequestEvent);
	NdisInitializeEvent(&Open->NdisWriteCompleteEvent);
	NdisInitializeEvent(&Open->DumpEvent);
	NdisAllocateSpinLock(&Open->MachineLock);
	NdisAllocateSpinLock(&Open->WriteLock);
	Open->WriteInProgress = FALSE;

	for (i = 0; i < NCpu; i++)
	{
		NdisAllocateSpinLock(&Open->CpuData[i].BufferLock);
	}

	NdisInitializeEvent(&Open->NdisOpenCloseCompleteEvent);

	//  list to hold irp's want to reset the adapter
	InitializeListHead(&Open->ResetIrpList);

	//  Initialize the request list
	KeInitializeSpinLock(&Open->RequestSpinLock);
	InitializeListHead(&Open->RequestList);

	// Initializes the extended memory of the NPF machine
	Open->mem_ex.buffer = ExAllocatePoolWithTag(NonPagedPool, DEFAULT_MEM_EX_SIZE, '2OWA');
	if((Open->mem_ex.buffer) == NULL)
	{
		//
		// no memory
		//
		ExFreePool(Open);
		Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
		IoCompleteRequest(Irp, IO_NO_INCREMENT);
		return STATUS_INSUFFICIENT_RESOURCES;
	}

	Open->mem_ex.size = DEFAULT_MEM_EX_SIZE;
	RtlZeroMemory(Open->mem_ex.buffer, DEFAULT_MEM_EX_SIZE);

	//
	// Initialize the open instance
	//
	Open->bpfprogram = NULL;	//reset the filter
	Open->mode = MODE_CAPT;
	Open->Nbytes.QuadPart = 0;
	Open->Npackets.QuadPart = 0;
	Open->Nwrites = 1;
	Open->Multiple_Write_Counter = 0;
	Open->MinToCopy = 0;
	Open->TimeOut.QuadPart = (LONGLONG)1;
	Open->DumpFileName.Buffer = NULL;
	Open->DumpFileHandle = NULL;
	Open->tme.active = TME_NONE_ACTIVE;
	Open->DumpLimitReached = FALSE;
	Open->MaxFrameSize = 0;
	Open->WriterSN=0;
	Open->ReaderSN=0;
	Open->Size=0;
	Open->SkipSentPackets = FALSE;
	Open->ReadEvent = NULL;

	//
	//allocate the spinlock for the statistic counters
	//
	NdisAllocateSpinLock(&Open->CountersLock);

	//
	//  link up the request stored in our open block
	//
	for (i = 0 ; i < MAX_REQUESTS ; i++ ) 
	{
		NdisInitializeEvent(&Open->Requests[i].InternalRequestCompletedEvent);

		ExInterlockedInsertTailList(
			&Open->RequestList,
			&Open->Requests[i].ListElement,
			&Open->RequestSpinLock);
	}

	NdisResetEvent(&Open->NdisOpenCloseCompleteEvent);

	// 
	// set the proper binding flags before trying to open the MAC
	//
	Open->AdapterBindingStatus = ADAPTER_BOUND;
	Open->AdapterHandleUsageCounter = 0;
	NdisAllocateSpinLock(&Open->AdapterHandleLock);

	//
	//  Try to open the MAC
	//
	TRACE_MESSAGE2(PACKET_DEBUG_LOUD,"Opening the device %ws, BindingContext=%p",DeviceExtension->AdapterName.Buffer, Open);

	returnStatus = STATUS_SUCCESS;

	NdisOpenAdapter(
		&Status,
		&ErrorStatus,
		&Open->AdapterHandle,
		&Open->Medium,
		MediumArray,
		NUM_NDIS_MEDIA,
		DeviceExtension->NdisProtocolHandle,
		Open,
		&DeviceExtension->AdapterName,
		0,
		NULL);

	TRACE_MESSAGE1(PACKET_DEBUG_LOUD,"Opened the device, Status=%x",Status);

	if (Status == NDIS_STATUS_PENDING)
	{
		NdisWaitEvent(&Open->NdisOpenCloseCompleteEvent, 0);

		if (!NT_SUCCESS(Open->OpenCloseStatus))
		{
			returnStatus = Open->OpenCloseStatus;
		}
		else
		{
			returnStatus = STATUS_SUCCESS;
		}
	}
	else
	{
		//
		// request not pending, we know the result, and OpenComplete has not been called.
		//
		if (Status == NDIS_STATUS_SUCCESS)
		{
			returnStatus = STATUS_SUCCESS;
		}
		else
		{
			//
			// this is not completely correct, as we are converting an NDIS_STATUS to a NTSTATUS
			//
			returnStatus = Status;

		}
	}

	if (returnStatus == STATUS_SUCCESS)
	{
		ULONG localNumOpenedInstances;	
		//
		// complete the open
		//
		localNumOpenedInstances = InterlockedIncrement(&g_NumOpenedInstances);

		TRACE_MESSAGE1(PACKET_DEBUG_LOUD, "Opened Instances: %u", localNumOpenedInstances);

		// Get the absolute value of the system boot time.
		// This is used for timestamp conversion.
		TIME_SYNCHRONIZE(&G_Start_Time);

		returnStatus = NPF_GetDeviceMTU(Open, Irp, &Open->MaxFrameSize);

		if (!NT_SUCCESS(returnStatus))
		{
			//
			// Close the binding
			//
			NPF_CloseBinding(Open);
		}
	}

	if (!NT_SUCCESS(returnStatus))
	{
		NPF_CloseOpenInstance(Open);
	}
	else
	{
		//  Save or open here
		IrpSp->FileObject->FsContext=Open;
	}

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

	TRACE_EXIT();
	return returnStatus;
}

⌨️ 快捷键说明

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