diff --git a/drivers/3rdparty/CMakeLists.txt b/drivers/3rdparty/CMakeLists.txt
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/drivers/3rdparty/npf/DEBUG.H b/drivers/3rdparty/npf/DEBUG.H
new file mode 100644
index 0000000000000..8f1cf1bd83a21
--- /dev/null
+++ b/drivers/3rdparty/npf/DEBUG.H
@@ -0,0 +1,108 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef __DEBUG_INCLUDE
+#define __DEBUG_INCLUDE
+
+
+#if DBG
+
+#define IF_PACKETDEBUG(f) if (PacketDebugFlag & (f))
+extern ULONG PacketDebugFlag;
+
+#define PACKET_DEBUG_LOUD 0x00000001 // debugging info
+#define PACKET_DEBUG_VERY_LOUD 0x00000002 // excessive debugging info
+
+#define PACKET_DEBUG_INIT 0x00000100 // init debugging info
+
+//
+// unfortunately, NT4 does not have the __FUNCTION__ macro, so we define it as null
+//
+#ifndef __FUNCTION__
+#define __FUNCTION__
+#endif
+
+//
+// Macro for deciding whether to dump lots of debugging information.
+//
+
+#define IF_LOUD(A) IF_PACKETDEBUG( PACKET_DEBUG_LOUD ) { A }
+#define IF_VERY_LOUD(A) IF_PACKETDEBUG( PACKET_DEBUG_VERY_LOUD ) { A }
+#define IF_INIT_LOUD(A) IF_PACKETDEBUG( PACKET_DEBUG_INIT ) { A }
+
+#define TRACE_ENTER() DbgPrint("--> " __FUNCTION__)
+#define TRACE_EXIT() DbgPrint("<-- " __FUNCTION__)
+#define TRACE_MESSAGE(__level__, __message__) do{ if (PacketDebugFlag & (__level__)) DbgPrint(" " __FUNCTION__ ": " __message__);} while(FALSE)
+
+#define TRACE_MESSAGE1(__level__, __message__, __p1__) do \
+ { \
+ if (PacketDebugFlag & (__level__)) \
+ DbgPrint(" " __FUNCTION__ ": " __message__, __p1__); \
+ } while(FALSE)
+
+#define TRACE_MESSAGE2(__level__, __message__, __p1__, __p2__) do \
+ { \
+ if (PacketDebugFlag & (__level__)) \
+ DbgPrint(" " __FUNCTION__ ": " __message__, __p1__, __p2__); \
+ } while(FALSE)
+
+#define TRACE_MESSAGE3(__level__, __message__, __p1__, __p2__, __p3__) do \
+ { \
+ if (PacketDebugFlag & (__level__)) \
+ DbgPrint(" " __FUNCTION__ ": " __message__, __p1__, __p2__, __p3__); \
+ } while(FALSE)
+
+#define TRACE_MESSAGE4(__level__, __message__, __p1__, __p2__, __p3__, __p4__) do \
+ { \
+ if (PacketDebugFlag & (__level__)) \
+ DbgPrint(" " __FUNCTION__ ": " __message__, __p1__, __p2__, __p3__, __p4__ ); \
+ } while(FALSE)
+
+
+#else //DBG
+
+#define IF_LOUD(A)
+#define IF_VERY_LOUD(A)
+#define IF_INIT_LOUD(A)
+
+#define TRACE_ENTER()
+#define TRACE_EXIT()
+#define TRACE_MESSAGE(__level__, __message__)
+#define TRACE_MESSAGE1(__level__, __message__, __p1__)
+#define TRACE_MESSAGE2(__level__, __message__, __p1__, __p2__)
+#define TRACE_MESSAGE3(__level__, __message__, __p1__, __p2__, __p3__)
+#define TRACE_MESSAGE4(__level__, __message__, __p1__, __p2__, __p3__, __p4__)
+
+#endif
+
+#endif /*#define __DEBUG_INCLUDE*/
diff --git a/drivers/3rdparty/npf/Driver.vcproj b/drivers/3rdparty/npf/Driver.vcproj
new file mode 100644
index 0000000000000..a9aa1dafa71a7
--- /dev/null
+++ b/drivers/3rdparty/npf/Driver.vcproj
@@ -0,0 +1,266 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/drivers/3rdparty/npf/MAKEFILE b/drivers/3rdparty/npf/MAKEFILE
new file mode 100644
index 0000000000000..58189757d61c2
--- /dev/null
+++ b/drivers/3rdparty/npf/MAKEFILE
@@ -0,0 +1,7 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the driver components of the Windows NT DDK
+#
+
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/drivers/3rdparty/npf/NPF.RC b/drivers/3rdparty/npf/NPF.RC
new file mode 100644
index 0000000000000..aea560336dcb7
--- /dev/null
+++ b/drivers/3rdparty/npf/NPF.RC
@@ -0,0 +1,48 @@
+#include "windows.h"
+#include "..\..\version.h"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION WINPCAP_MAJOR,WINPCAP_MINOR,WINPCAP_REV,WINPCAP_BUILD
+ PRODUCTVERSION WINPCAP_MAJOR,WINPCAP_MINOR,WINPCAP_REV,WINPCAP_BUILD
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x3L
+ FILESUBTYPE 0x7L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "000004b0"
+ BEGIN
+ VALUE "CompanyName", WINPCAP_COMPANY_NAME
+#ifdef __NPF_NT4__
+ VALUE "FileDescription", "npf.sys (NT4) Kernel Driver"
+#elif defined(_AMD64_)
+ VALUE "FileDescription", "npf.sys (NT5/6 AMD64) Kernel Driver"
+#else
+ VALUE "FileDescription", "npf.sys (NT5/6 x86) Kernel Driver"
+#endif
+ VALUE "FileVersion", WINPCAP_VER_STRING
+ VALUE "InternalName", "NPF + TME"
+ VALUE "LegalCopyright", WINPCAP_COPYRIGHT_STRING
+ VALUE "LegalTrademarks", ""
+ VALUE "OriginalFilename", "npf.sys"
+ VALUE "ProductName", WINPCAP_PRODUCT_NAME
+ VALUE "ProductVersion", WINPCAP_VER_STRING
+ VALUE "Build Description", WINPCAP_BUILD_DESCRIPTION
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+END
+
diff --git a/drivers/3rdparty/npf/Openclos.c b/drivers/3rdparty/npf/Openclos.c
new file mode 100644
index 0000000000000..77d0528695b1d
--- /dev/null
+++ b/drivers/3rdparty/npf/Openclos.c
@@ -0,0 +1,988 @@
+/*
+ * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2010 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
+#include
+
+#include "debug.h"
+#include "packet.h"
+#include "..\..\Common\WpcapNames.h"
+
+
+static
+VOID
+NPF_ReleaseOpenInstanceResources(POPEN_INSTANCE pOpen);
+
+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 < g_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);
+
+#ifdef HAVE_BUGGY_TME_SUPPORT
+ // 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);
+#endif //HAVE_BUGGY_TME_SUPPORT
+
+
+ //
+ // 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;
+#ifdef HAVE_BUGGY_TME_SUPPORT
+ Open->tme.active = TME_NONE_ACTIVE;
+#endif // HAVE_BUGGY_TME_SUPPORT
+ Open->DumpLimitReached = FALSE;
+ Open->MaxFrameSize = 0;
+ Open->WriterSN=0;
+ Open->ReaderSN=0;
+ Open->Size=0;
+ Open->SkipSentPackets = FALSE;
+ Open->ReadEvent = NULL;
+
+ //
+ // we need to keep a counter of the pending IRPs
+ // so that when the IRP_MJ_CLEANUP dispatcher gets called,
+ // we can wait for those IRPs to be completed
+ //
+ Open->NumPendingIrps = 0;
+ Open->ClosePending = FALSE;
+ NdisAllocateSpinLock(&Open->OpenInUseLock);
+
+ //
+ //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,
+ g_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_ReleaseOpenInstanceResources(Open);
+ //
+ // Free the open instance itself
+ //
+ ExFreePool(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;
+}
+
+BOOLEAN
+NPF_StartUsingOpenInstance(
+ IN POPEN_INSTANCE pOpen
+ )
+{
+ BOOLEAN returnStatus;
+
+ NdisAcquireSpinLock(&pOpen->OpenInUseLock);
+ if (pOpen->ClosePending)
+ {
+ returnStatus = FALSE;
+ }
+ else
+ {
+ returnStatus = TRUE;
+ pOpen->NumPendingIrps ++;
+ }
+ NdisReleaseSpinLock(&pOpen->OpenInUseLock);
+
+ return returnStatus;
+}
+
+VOID
+NPF_StopUsingOpenInstance(
+ IN POPEN_INSTANCE pOpen
+ )
+{
+ NdisAcquireSpinLock(&pOpen->OpenInUseLock);
+ ASSERT(pOpen->NumPendingIrps > 0);
+ pOpen->NumPendingIrps --;
+ NdisReleaseSpinLock(&pOpen->OpenInUseLock);
+}
+
+VOID
+NPF_CloseOpenInstance(
+ IN POPEN_INSTANCE pOpen
+ )
+{
+ ULONG i = 0;
+ NDIS_EVENT Event;
+
+ ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
+
+ NdisInitializeEvent(&Event);
+ NdisResetEvent(&Event);
+
+ NdisAcquireSpinLock(&pOpen->OpenInUseLock);
+
+ pOpen->ClosePending = TRUE;
+
+ while(pOpen->NumPendingIrps > 0)
+ {
+ NdisReleaseSpinLock(&pOpen->OpenInUseLock);
+ NdisWaitEvent(&Event,1);
+ NdisAcquireSpinLock(&pOpen->OpenInUseLock);
+ }
+
+ NdisReleaseSpinLock(&pOpen->OpenInUseLock);
+}
+
+
+VOID
+NPF_ReleaseOpenInstanceResources(POPEN_INSTANCE pOpen)
+{
+ PKEVENT pEvent;
+ UINT i;
+
+ TRACE_ENTER();
+
+ ASSERT(pOpen != NULL);
+ ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
+
+ TRACE_MESSAGE1(PACKET_DEBUG_LOUD, "Open= %p", pOpen);
+
+ NdisFreePacketPool(pOpen->PacketPool);
+
+#ifdef HAVE_BUGGY_TME_SUPPORT
+ //
+ // free mem_ex
+ //
+ pOpen->mem_ex.size = 0;
+ if(pOpen->mem_ex.buffer != NULL)
+ ExFreePool(pOpen->mem_ex.buffer);
+#endif //HAVE_BUGGY_TME_SUPPORT
+
+ //
+ // Free the filter if it's present
+ //
+ if(pOpen->bpfprogram != NULL)
+ ExFreePool(pOpen->bpfprogram);
+
+//
+// Jitted filters are supported on x86 (32bit) only
+//
+#ifdef _X86_
+ // Free the jitted filter if it's present
+ if(pOpen->Filter != NULL)
+ BPF_Destroy_JIT_Filter(pOpen->Filter);
+#endif //_X86_
+
+ //
+ // Dereference the read event.
+ //
+
+ if (pOpen->ReadEvent != NULL)
+ ObDereferenceObject(pOpen->ReadEvent);
+
+ //
+ // free the buffer
+ // NOTE: the buffer is fragmented among the various CPUs, but the base pointer of the
+ // allocated chunk of memory is stored in the first slot (pOpen->CpuData[0])
+ //
+ if (pOpen->Size > 0)
+ ExFreePool(pOpen->CpuData[0].Buffer);
+
+ //
+ // free the per CPU spinlocks
+ //
+ for (i = 0; i < g_NCpu; i++)
+ {
+ NdisFreeSpinLock(&Open->CpuData[i].BufferLock);
+ }
+
+ //
+ // Free the string with the name of the dump file
+ //
+ if(pOpen->DumpFileName.Buffer!=NULL)
+ ExFreePool(pOpen->DumpFileName.Buffer);
+
+ TRACE_EXIT();
+}
+
+
+//-------------------------------------------------------------------
+
+VOID NPF_OpenAdapterComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status,
+ IN NDIS_STATUS OpenErrorStatus)
+{
+
+ POPEN_INSTANCE Open;
+ PLIST_ENTRY RequestListEntry;
+ PINTERNAL_REQUEST MaxSizeReq;
+ NDIS_STATUS ReqStatus;
+
+ TRACE_ENTER();
+
+ Open = (POPEN_INSTANCE)ProtocolBindingContext;
+
+ ASSERT(Open != NULL);
+
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ //
+ // this is not completely correct, as we are converting an NDIS_STATUS to a NTSTATUS
+ //
+ Open->OpenCloseStatus = Status;
+ }
+ else
+ {
+ Open->OpenCloseStatus = STATUS_SUCCESS;
+ }
+
+ //
+ // wake up the caller of NdisOpen, that is NPF_Open
+ //
+ NdisSetEvent(&Open->NdisOpenCloseCompleteEvent);
+
+ TRACE_EXIT();
+}
+
+NTSTATUS
+NPF_GetDeviceMTU(
+ IN POPEN_INSTANCE pOpen,
+ IN PIRP pIrp,
+ OUT PUINT pMtu)
+{
+ PLIST_ENTRY RequestListEntry;
+ PINTERNAL_REQUEST MaxSizeReq;
+ NDIS_STATUS ReqStatus;
+
+ TRACE_ENTER();
+
+ ASSERT(pOpen != NULL);
+ ASSERT(pIrp != NULL);
+ ASSERT(pMtu != NULL);
+
+ // Extract a request from the list of free ones
+ RequestListEntry = ExInterlockedRemoveHeadList(&pOpen->RequestList, &pOpen->RequestSpinLock);
+
+ if (RequestListEntry == NULL)
+ {
+ //
+ // THIS IS WRONG
+ //
+
+ //
+ // Assume Ethernet
+ //
+ *pMtu = 1514;
+ TRACE_EXIT();
+ return STATUS_SUCCESS;
+ }
+
+ MaxSizeReq = CONTAINING_RECORD(RequestListEntry, INTERNAL_REQUEST, ListElement);
+
+ MaxSizeReq->Request.RequestType = NdisRequestQueryInformation;
+ MaxSizeReq->Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_MAXIMUM_TOTAL_SIZE;
+
+ MaxSizeReq->Request.DATA.QUERY_INFORMATION.InformationBuffer = pMtu;
+ MaxSizeReq->Request.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(*pMtu);
+
+ NdisResetEvent(&MaxSizeReq->InternalRequestCompletedEvent);
+
+ // submit the request
+ NdisRequest(
+ &ReqStatus,
+ pOpen->AdapterHandle,
+ &MaxSizeReq->Request);
+
+ if (ReqStatus == NDIS_STATUS_PENDING)
+ {
+ NdisWaitEvent(&MaxSizeReq->InternalRequestCompletedEvent, 0);
+ ReqStatus = MaxSizeReq->RequestStatus;
+ }
+
+ //
+ // Put the request in the list of the free ones
+ //
+ ExInterlockedInsertTailList(&pOpen->RequestList, &MaxSizeReq->ListElement, &pOpen->RequestSpinLock);
+
+ if (ReqStatus == NDIS_STATUS_SUCCESS)
+ {
+ TRACE_EXIT();
+ return STATUS_SUCCESS;
+ }
+ else
+ {
+ //
+ // THIS IS WRONG
+ //
+
+ //
+ // Assume Ethernet
+ //
+ *pMtu = 1514;
+
+ TRACE_EXIT();
+ return STATUS_SUCCESS;
+
+ // return ReqStatus;
+ }
+}
+
+
+//-------------------------------------------------------------------
+NTSTATUS
+NPF_Close(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
+{
+ POPEN_INSTANCE pOpen;
+ PIO_STACK_LOCATION IrpSp;
+ TRACE_ENTER();
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+ pOpen = IrpSp->FileObject->FsContext;
+
+ ASSERT(pOpen != NULL);
+ //
+ // Free the open instance itself
+ //
+ ExFreePool(pOpen);
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ TRACE_EXIT();
+ return STATUS_SUCCESS;
+}
+
+//-------------------------------------------------------------------
+NTSTATUS
+NPF_Cleanup(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
+{
+
+ POPEN_INSTANCE Open;
+ NDIS_STATUS Status;
+ PIO_STACK_LOCATION IrpSp;
+ LARGE_INTEGER ThreadDelay;
+ ULONG localNumOpenInstances;
+
+ TRACE_ENTER();
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+ Open = IrpSp->FileObject->FsContext;
+
+ TRACE_MESSAGE1(PACKET_DEBUG_LOUD, "Open = %p\n", Open);
+
+ ASSERT(Open != NULL);
+
+ NPF_CloseOpenInstance(Open);
+
+ if (Open->ReadEvent != NULL)
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+
+ NPF_CloseBinding(Open);
+
+ // NOTE:
+ // code commented out because the kernel dump feature is disabled
+ //
+ //if (AdapterAlreadyClosing == FALSE)
+ //{
+
+ //
+ // Unfreeze the consumer
+ //
+ // if(Open->mode & MODE_DUMP)
+ // NdisSetEvent(&Open->DumpEvent);
+ // else
+ // KeSetEvent(Open->ReadEvent,0,FALSE);
+
+ // //
+ // // If this instance is in dump mode, complete the dump and close the file
+ // //
+ // if((Open->mode & MODE_DUMP) && Open->DumpFileHandle != NULL)
+ // {
+ // NTSTATUS wres;
+
+ // ThreadDelay.QuadPart = -50000000;
+
+ // //
+ // // Wait the completion of the thread
+ // //
+ // wres = KeWaitForSingleObject(Open->DumpThreadObject,
+ // UserRequest,
+ // KernelMode,
+ // TRUE,
+ // &ThreadDelay);
+
+ // ObDereferenceObject(Open->DumpThreadObject);
+
+ // //
+ // // Flush and close the dump file
+ // //
+ // NPF_CloseDumpFile(Open);
+ // }
+ //}
+
+
+ //
+ // release all the resources
+ //
+ NPF_ReleaseOpenInstanceResources(Open);
+
+// IrpSp->FileObject->FsContext = NULL;
+
+ //
+ // Decrease the counter of open instances
+ //
+ localNumOpenInstances = InterlockedDecrement(&g_NumOpenedInstances);
+ TRACE_MESSAGE1(PACKET_DEBUG_LOUD, "Opened Instances: %u", localNumOpenInstances);
+
+ if(localNumOpenInstances == 0)
+ {
+ //
+ // Force a synchronization at the next NPF_Open().
+ // This hopefully avoids the synchronization issues caused by hibernation or standby.
+ //
+ TIME_DESYNCHRONIZE(&G_Start_Time);
+ }
+
+
+ //
+ // and complete the IRP with status success
+ //
+ Irp->IoStatus.Information = 0;
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ TRACE_EXIT();
+
+ return(STATUS_SUCCESS);
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_CloseAdapterComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status)
+{
+ POPEN_INSTANCE Open;
+ PIRP Irp;
+
+ TRACE_ENTER();
+
+ Open = (POPEN_INSTANCE)ProtocolBindingContext;
+
+ ASSERT(Open != NULL);
+
+ TRACE_MESSAGE1(PACKET_DEBUG_LOUD, "Open= %p", Open);
+
+ NdisSetEvent(&Open->NdisOpenCloseCompleteEvent);
+
+ TRACE_EXIT();
+ return;
+
+}
+//-------------------------------------------------------------------
+
+#ifdef NDIS50
+NDIS_STATUS
+NPF_PowerChange(IN NDIS_HANDLE ProtocolBindingContext, IN PNET_PNP_EVENT pNetPnPEvent)
+{
+ TRACE_ENTER();
+
+ TIME_DESYNCHRONIZE(&G_Start_Time);
+ TIME_SYNCHRONIZE(&G_Start_Time);
+
+ TRACE_EXIT();
+ return STATUS_SUCCESS;
+}
+#endif
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_BindAdapter(
+ OUT PNDIS_STATUS Status,
+ IN NDIS_HANDLE BindContext,
+ IN PNDIS_STRING DeviceName,
+ IN PVOID SystemSpecific1,
+ IN PVOID SystemSpecific2
+ )
+{
+ TRACE_ENTER();
+ TRACE_EXIT();
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_UnbindAdapter(
+ OUT PNDIS_STATUS Status,
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_HANDLE UnbindContext
+ )
+{
+ POPEN_INSTANCE Open =(POPEN_INSTANCE)ProtocolBindingContext;
+
+ TRACE_ENTER();
+
+ ASSERT(Open != NULL);
+
+ //
+ // The following code has been disabled bcause the kernel dump feature has been disabled.
+ //
+ ////
+ //// Awake a possible pending read on this instance
+ //// TODO should be ok.
+ ////
+ // if(Open->mode & MODE_DUMP)
+ // NdisSetEvent(&Open->DumpEvent);
+ // else
+ if (Open->ReadEvent != NULL)
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+
+ //
+ // The following code has been disabled bcause the kernel dump feature has been disabled.
+ //
+ ////
+ //// If this instance is in dump mode, complete the dump and close the file
+ //// TODO needs to be checked again.
+ ////
+ // if((Open->mode & MODE_DUMP) && Open->DumpFileHandle != NULL)
+ // NPF_CloseDumpFile(Open);
+
+ *Status = NDIS_STATUS_SUCCESS;
+
+ NPF_CloseBinding(Open);
+
+ TRACE_EXIT();
+ return;
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_ResetComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status)
+
+{
+ POPEN_INSTANCE Open;
+ PIRP Irp;
+
+ PLIST_ENTRY ResetListEntry;
+
+ TRACE_ENTER();
+
+ Open = (POPEN_INSTANCE)ProtocolBindingContext;
+
+ //
+ // remove the reset IRP from the list
+ //
+ ResetListEntry=ExInterlockedRemoveHeadList(
+ &Open->ResetIrpList,
+ &Open->RequestSpinLock
+ );
+
+ Irp=CONTAINING_RECORD(ResetListEntry,IRP,Tail.Overlay.ListEntry);
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ TRACE_EXIT();
+
+ return;
+
+}
diff --git a/drivers/3rdparty/npf/Packet.c b/drivers/3rdparty/npf/Packet.c
new file mode 100644
index 0000000000000..cc1ca20e0958e
--- /dev/null
+++ b/drivers/3rdparty/npf/Packet.c
@@ -0,0 +1,2115 @@
+/*
+ * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2010 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
+#include
+
+#include "debug.h"
+#include "packet.h"
+#include "win_bpf.h"
+#include "ioctls.h"
+
+#ifdef HAVE_BUGGY_TME_SUPPORT
+#include "win_bpf_filter_init.h"
+#endif //HAVE_BUGGY_TME_SUPPORT
+
+#include "..\..\Common\WpcapNames.h"
+
+
+#if DBG
+// Declare the global debug flag for this driver.
+ULONG PacketDebugFlag = PACKET_DEBUG_LOUD;
+
+#endif
+
+PDEVICE_EXTENSION GlobalDeviceExtension;
+
+//
+// Global strings
+//
+WCHAR g_NPF_PrefixBuffer[MAX_WINPCAP_KEY_CHARS] = NPF_DEVICE_NAMES_PREFIX_WIDECHAR;
+//
+// Old registry based WinPcap names
+//
+//WCHAR g_NPF_PrefixBuffer[MAX_WINPCAP_KEY_CHARS];
+NDIS_STRING g_NPF_Prefix;
+NDIS_STRING devicePrefix = NDIS_STRING_CONST("\\Device\\");
+NDIS_STRING symbolicLinkPrefix = NDIS_STRING_CONST("\\DosDevices\\");
+NDIS_STRING tcpLinkageKeyName = NDIS_STRING_CONST("\\Registry\\Machine\\System"
+ L"\\CurrentControlSet\\Services\\Tcpip\\Linkage");
+NDIS_STRING AdapterListKey = NDIS_STRING_CONST("\\Registry\\Machine\\System"
+ L"\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}");
+NDIS_STRING bindValueName = NDIS_STRING_CONST("Bind");
+NDIS_STRING g_WinpcapGlobalKey = NDIS_STRING_CONST("\\Registry\\Machine\\" WINPCAP_INSTANCE_KEY_WIDECHAR);
+//NDIS_STRING g_WinpcapGlobalKey = NDIS_STRING_CONST("\\Registry\\Machine\\" WINPCAP_GLOBAL_KEY_WIDECHAR);
+
+/// Global variable that points to the names of the bound adapters
+WCHAR* bindP = NULL;
+
+NDIS_HANDLE g_NdisProtocolHandle = NULL;
+
+ULONG g_NCpu;
+
+ULONG TimestampMode;
+UINT g_SendPacketFlags = 0;
+
+static VOID NPF_ResetBufferContents(POPEN_INSTANCE Open);
+
+//
+// Packet Driver's entry routine.
+//
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ )
+{
+ NDIS_PROTOCOL_CHARACTERISTICS ProtocolChar;
+ UNICODE_STRING MacDriverName;
+ UNICODE_STRING UnicodeDeviceName;
+ PDEVICE_OBJECT DeviceObject = NULL;
+ PDEVICE_EXTENSION DeviceExtension = NULL;
+ NTSTATUS Status = STATUS_SUCCESS;
+ NTSTATUS ErrorCode = STATUS_SUCCESS;
+ NDIS_STRING ProtoName = NDIS_STRING_CONST("PacketDriver");
+ ULONG DevicesCreated=0;
+ PWSTR BindString;
+ PWSTR ExportString;
+ PWSTR BindStringSave;
+ PWSTR ExportStringSave;
+ WCHAR* bindT;
+ PKEY_VALUE_PARTIAL_INFORMATION tcpBindingsP;
+ UNICODE_STRING macName;
+//
+// Old registry based WinPcap names
+//
+// UINT RegStrLen;
+ ULONG OsMajorVersion, OsMinorVersion;
+
+ TRACE_ENTER();
+
+#ifndef __NPF_NT4__
+
+ TRACE_MESSAGE(PACKET_DEBUG_INIT, "DriverEntry -- NT4");
+
+ //
+ // Get OS version and store it in a global variable.
+ // For the moment we use the deprecated PsGetVersion() because the suggested
+ // RtlGetVersion() doesn't seem to exist in Windows 2000, and we don't want
+ // to have two separated drivers just for this call.
+ // Morever, the NT4 version of the driver just excludes this, since those flags
+ // are not available.
+ //
+ // Note: both RtlGetVersion() and PsGetVersion() are documented to always return success.
+ //
+ // OsVersion.dwOSVersionInfoSize = sizeof(OsVersion);
+ // RtlGetVersion(&OsVersion);
+ PsGetVersion(&OsMajorVersion, &OsMinorVersion, NULL, NULL);
+ TRACE_MESSAGE2(PACKET_DEBUG_INIT, "OS Version: %d.%d\n", OsMajorVersion, OsMinorVersion);
+
+ //
+ // Define the correct flag to skip the loopback packets, according to the OS
+ //
+ if((OsMajorVersion == 5) && (OsMinorVersion == 0))
+ {
+ // Windows 2000 wants both NDIS_FLAGS_DONT_LOOPBACK and NDIS_FLAGS_SKIP_LOOPBACK
+ g_SendPacketFlags = NDIS_FLAGS_DONT_LOOPBACK | NDIS_FLAGS_SKIP_LOOPBACK_W2K;
+ }
+ else
+ {
+ // Windows XP, 2003 and follwing want only NDIS_FLAGS_DONT_LOOPBACK
+ g_SendPacketFlags = NDIS_FLAGS_DONT_LOOPBACK;
+ }
+#endif //__NPF_NT4__
+
+ //
+ // Set timestamp gathering method getting it from the registry
+ //
+ ReadTimeStampModeFromRegistry(RegistryPath);
+
+ TRACE_MESSAGE1(PACKET_DEBUG_INIT,"%ws",RegistryPath->Buffer);
+
+//
+// Old registry based WinPcap names
+//
+// //
+// // Get the device names prefix from the registry
+// //
+// RegStrLen = sizeof(g_NPF_PrefixBuffer) / sizeof(g_NPF_PrefixBuffer[0]);
+//
+// NPF_QueryWinpcapRegistryString(NPF_DEVICES_PREFIX_REG_KEY_WC,
+// g_NPF_PrefixBuffer,
+// RegStrLen,
+// NPF_DEVICE_NAMES_PREFIX_WIDECHAR);
+//
+ NdisInitUnicodeString(&g_NPF_Prefix, g_NPF_PrefixBuffer);
+
+
+ //
+ // Get number of CPUs and save it
+ //
+ g_NCpu = NdisSystemProcessorCount();
+
+ RtlZeroMemory(&ProtocolChar,sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
+
+ //
+ // Register as a protocol with NDIS
+ //
+#ifdef NDIS50
+ ProtocolChar.MajorNdisVersion = 5;
+#else
+ ProtocolChar.MajorNdisVersion = 3;
+#endif
+ ProtocolChar.MinorNdisVersion = 0;
+ ProtocolChar.Reserved = 0;
+ ProtocolChar.OpenAdapterCompleteHandler = NPF_OpenAdapterComplete;
+ ProtocolChar.CloseAdapterCompleteHandler = NPF_CloseAdapterComplete;
+ ProtocolChar.SendCompleteHandler = NPF_SendComplete;
+ ProtocolChar.TransferDataCompleteHandler = NPF_TransferDataComplete;
+ ProtocolChar.ResetCompleteHandler = NPF_ResetComplete;
+ ProtocolChar.RequestCompleteHandler = NPF_RequestComplete;
+ ProtocolChar.ReceiveHandler = NPF_tap;
+ ProtocolChar.ReceiveCompleteHandler = NPF_ReceiveComplete;
+ ProtocolChar.StatusHandler = NPF_Status;
+ ProtocolChar.StatusCompleteHandler = NPF_StatusComplete;
+#ifdef NDIS50
+ ProtocolChar.BindAdapterHandler = NPF_BindAdapter;
+ ProtocolChar.UnbindAdapterHandler = NPF_UnbindAdapter;
+ ProtocolChar.PnPEventHandler = NPF_PowerChange;
+ ProtocolChar.ReceivePacketHandler = NULL;
+#endif
+ ProtocolChar.Name = ProtoName;
+
+ NdisRegisterProtocol(
+ &Status,
+ &g_NdisProtocolHandle,
+ &ProtocolChar,
+ sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ TRACE_MESSAGE(PACKET_DEBUG_INIT,"Failed to register protocol with NDIS");
+
+ TRACE_EXIT();
+ return Status;
+
+ }
+
+ //
+ // Standard device driver entry points stuff.
+ //
+ DriverObject->MajorFunction[IRP_MJ_CREATE] = NPF_Open;
+ DriverObject->MajorFunction[IRP_MJ_CLOSE] = NPF_Close;
+ DriverObject->MajorFunction[IRP_MJ_CLEANUP]= NPF_Cleanup;
+ DriverObject->MajorFunction[IRP_MJ_READ] = NPF_Read;
+ DriverObject->MajorFunction[IRP_MJ_WRITE] = NPF_Write;
+ DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = NPF_IoControl;
+ DriverObject->DriverUnload = NPF_Unload;
+
+ bindP = getAdaptersList();
+
+ if (bindP == NULL)
+ {
+ TRACE_MESSAGE(PACKET_DEBUG_INIT, "Adapters not found in the registry, try to copy the bindings of TCP-IP.");
+
+ tcpBindingsP = getTcpBindings();
+
+ if (tcpBindingsP == NULL)
+ {
+ TRACE_MESSAGE(PACKET_DEBUG_INIT, "TCP-IP not found, quitting.");
+ goto RegistryError;
+ }
+
+ bindP = (WCHAR*)tcpBindingsP;
+ bindT = (WCHAR*)(tcpBindingsP->Data);
+
+ }
+ else
+ {
+ bindT = bindP;
+ }
+
+ for (; *bindT != UNICODE_NULL; bindT += (macName.Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR))
+ {
+ RtlInitUnicodeString(&macName, bindT);
+ NPF_CreateDevice(DriverObject, &macName);
+ }
+
+ TRACE_EXIT();
+ return STATUS_SUCCESS;
+
+RegistryError:
+
+ NdisDeregisterProtocol(
+ &Status,
+ g_NdisProtocolHandle
+ );
+
+ Status=STATUS_UNSUCCESSFUL;
+
+ TRACE_EXIT();
+ return(Status);
+}
+
+//-------------------------------------------------------------------
+
+PWCHAR getAdaptersList(void)
+{
+ PKEY_VALUE_PARTIAL_INFORMATION result = NULL;
+ OBJECT_ATTRIBUTES objAttrs;
+ NTSTATUS status;
+ HANDLE keyHandle;
+ UINT BufPos=0;
+ UINT BufLen=4096;
+
+
+ PWCHAR DeviceNames = (PWCHAR) ExAllocatePoolWithTag(PagedPool, BufLen, '0PWA');
+
+ if (DeviceNames == NULL) {
+ IF_LOUD(DbgPrint("Unable the allocate the buffer for the list of the network adapters\n");)
+ return NULL;
+ }
+
+ InitializeObjectAttributes(&objAttrs, &AdapterListKey,
+ OBJ_CASE_INSENSITIVE, NULL, NULL);
+ status = ZwOpenKey(&keyHandle, KEY_READ, &objAttrs);
+ if (!NT_SUCCESS(status)) {
+ IF_LOUD(DbgPrint("\n\nStatus of %x opening %ws\n", status, tcpLinkageKeyName.Buffer);)
+ }
+ else { //OK
+
+ ULONG resultLength;
+ KEY_VALUE_PARTIAL_INFORMATION valueInfo;
+ CHAR AdapInfo[1024];
+ UINT i=0;
+
+ IF_LOUD(DbgPrint("getAdaptersList: scanning the list of the adapters in the registry, DeviceNames=%p\n",DeviceNames);)
+
+ // Scan the list of the devices
+ while((status=ZwEnumerateKey(keyHandle,i,KeyBasicInformation,AdapInfo,sizeof(AdapInfo),&resultLength))==STATUS_SUCCESS)
+ {
+ WCHAR ExportKeyName [512];
+ PWCHAR ExportKeyPrefix = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\";
+ UINT ExportKeyPrefixSize = sizeof(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}");
+ PWCHAR LinkageKeyPrefix = L"\\Linkage";
+ UINT LinkageKeyPrefixSize = sizeof(L"\\Linkage");
+ NDIS_STRING FinalExportKey = NDIS_STRING_CONST("Export");
+ PKEY_BASIC_INFORMATION tInfo= (PKEY_BASIC_INFORMATION)AdapInfo;
+ UNICODE_STRING AdapterKeyName;
+ HANDLE ExportKeyHandle;
+
+ RtlCopyMemory(ExportKeyName,
+ ExportKeyPrefix,
+ ExportKeyPrefixSize);
+
+ RtlCopyMemory((PCHAR)ExportKeyName+ExportKeyPrefixSize,
+ tInfo->Name,
+ tInfo->NameLength+2);
+
+ RtlCopyMemory((PCHAR)ExportKeyName+ExportKeyPrefixSize+tInfo->NameLength,
+ LinkageKeyPrefix,
+ LinkageKeyPrefixSize);
+
+ IF_LOUD(DbgPrint("Key name=%ws\n", ExportKeyName);)
+
+ RtlInitUnicodeString(&AdapterKeyName, ExportKeyName);
+
+ InitializeObjectAttributes(&objAttrs, &AdapterKeyName,
+ OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+ status=ZwOpenKey(&ExportKeyHandle,KEY_READ,&objAttrs);
+
+ if (!NT_SUCCESS(status)) {
+ IF_LOUD(DbgPrint("OpenKey Failed, %d!\n",status);)
+ i++;
+ continue;
+ }
+
+ status = ZwQueryValueKey(ExportKeyHandle, &FinalExportKey,
+ KeyValuePartialInformation, &valueInfo,
+ sizeof(valueInfo), &resultLength);
+
+ if (!NT_SUCCESS(status) && (status != STATUS_BUFFER_OVERFLOW)) {
+ IF_LOUD(DbgPrint("\n\nStatus of %x querying key value for size\n", status);)
+ }
+ else { // We know how big it needs to be.
+ ULONG valueInfoLength = valueInfo.DataLength + FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
+ PKEY_VALUE_PARTIAL_INFORMATION valueInfoP = (PKEY_VALUE_PARTIAL_INFORMATION) ExAllocatePoolWithTag(PagedPool, valueInfoLength, '1PWA');
+ if (valueInfoP != NULL) {
+ status = ZwQueryValueKey(ExportKeyHandle, &FinalExportKey,
+ KeyValuePartialInformation,
+ valueInfoP,
+ valueInfoLength, &resultLength);
+ if (!NT_SUCCESS(status)) {
+ IF_LOUD(DbgPrint("Status of %x querying key value\n", status);)
+ }
+ else{
+ IF_LOUD(DbgPrint("Device %d = %ws\n", i, valueInfoP->Data);)
+ if( BufPos + valueInfoP->DataLength > BufLen ) {
+ // double the buffer size
+ PWCHAR DeviceNames2 = (PWCHAR) ExAllocatePoolWithTag(PagedPool, BufLen
+ << 1, '0PWA');
+ if( DeviceNames2 ) {
+ RtlCopyMemory((PCHAR)DeviceNames2, (PCHAR)DeviceNames, BufLen);
+ BufLen <<= 1;
+ ExFreePool(DeviceNames);
+ DeviceNames = DeviceNames2;
+ }
+ }
+ if( BufPos + valueInfoP->DataLength < BufLen ) {
+ RtlCopyMemory((PCHAR)DeviceNames+BufPos,
+ valueInfoP->Data,
+ valueInfoP->DataLength);
+ BufPos+=valueInfoP->DataLength-2;
+ }
+ }
+
+ ExFreePool(valueInfoP);
+ }
+ else {
+ IF_LOUD(DbgPrint("Error Allocating the buffer for the device name\n");)
+ }
+
+ }
+
+ // terminate the buffer
+ DeviceNames[BufPos/2]=0;
+ DeviceNames[BufPos/2+1]=0;
+
+ ZwClose (ExportKeyHandle);
+ i++;
+
+ }
+
+ ZwClose (keyHandle);
+
+ }
+ if(BufPos==0){
+ ExFreePool(DeviceNames);
+ return NULL;
+ }
+ return DeviceNames;
+}
+
+//-------------------------------------------------------------------
+
+PKEY_VALUE_PARTIAL_INFORMATION getTcpBindings(void)
+{
+ PKEY_VALUE_PARTIAL_INFORMATION result = NULL;
+ OBJECT_ATTRIBUTES objAttrs;
+ NTSTATUS status;
+ HANDLE keyHandle;
+
+ InitializeObjectAttributes(&objAttrs, &tcpLinkageKeyName,
+ OBJ_CASE_INSENSITIVE, NULL, NULL);
+ status = ZwOpenKey(&keyHandle, KEY_READ, &objAttrs);
+ if (!NT_SUCCESS(status))
+ {
+ IF_LOUD(DbgPrint("\n\nStatus of %x opening %ws\n", status, tcpLinkageKeyName.Buffer);)
+ }
+ else
+ {
+ ULONG resultLength;
+ KEY_VALUE_PARTIAL_INFORMATION valueInfo;
+
+ IF_LOUD(DbgPrint("\n\nOpened %ws\n", tcpLinkageKeyName.Buffer);)
+
+ status = ZwQueryValueKey(keyHandle, &bindValueName,
+ KeyValuePartialInformation, &valueInfo,
+ sizeof(valueInfo), &resultLength);
+ if (!NT_SUCCESS(status) && (status != STATUS_BUFFER_OVERFLOW))
+ {
+ IF_LOUD(DbgPrint("\n\nStatus of %x querying key value for size\n", status);)
+ }
+ else
+ { // We know how big it needs to be.
+ ULONG valueInfoLength = valueInfo.DataLength + FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
+ PKEY_VALUE_PARTIAL_INFORMATION valueInfoP =
+ (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(PagedPool, valueInfoLength, '2PWA');
+
+ if (valueInfoP != NULL)
+ {
+ status = ZwQueryValueKey(keyHandle, &bindValueName,
+ KeyValuePartialInformation,
+ valueInfoP,
+ valueInfoLength, &resultLength);
+
+ if (!NT_SUCCESS(status))
+ {
+ IF_LOUD(DbgPrint("\n\nStatus of %x querying key value\n", status);)
+ ExFreePool(valueInfoP);
+ }
+ else
+ {
+ if (valueInfoLength != resultLength)
+ {
+ IF_LOUD(DbgPrint("\n\nQuerying key value result len = %u "
+ "but previous len = %u\n",
+ resultLength, valueInfoLength);)
+ ExFreePool(valueInfoP);
+ }
+ else
+ {
+ if (valueInfoP->Type != REG_MULTI_SZ)
+ {
+ IF_LOUD(DbgPrint("\n\nTcpip bind value not REG_MULTI_SZ but %u\n",
+ valueInfoP->Type);)
+ ExFreePool(valueInfoP);
+ }
+ else
+ { // It's OK
+#if DBG
+ ULONG i;
+ WCHAR* dataP = (WCHAR*)(&valueInfoP->Data[0]);
+ IF_LOUD(DbgPrint("\n\nBind value:\n");)
+ for (i = 0; *dataP != UNICODE_NULL; i++) {
+ UNICODE_STRING macName;
+ RtlInitUnicodeString(&macName, dataP);
+ IF_LOUD(DbgPrint("\n\nMac %u = %ws\n", i, macName.Buffer);)
+ dataP +=
+ (macName.Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR);
+ }
+#endif // DBG
+ result = valueInfoP;
+ }
+ }
+ }
+ }
+ }
+ ZwClose(keyHandle);
+ }
+ return result;
+}
+
+//-------------------------------------------------------------------
+
+BOOLEAN NPF_CreateDevice(IN OUT PDRIVER_OBJECT adriverObjectP,
+ IN PUNICODE_STRING amacNameP)
+{
+ NTSTATUS status;
+ PDEVICE_OBJECT devObjP;
+ UNICODE_STRING deviceName;
+ UNICODE_STRING deviceSymLink;
+
+ IF_LOUD(DbgPrint("\n\ncreateDevice for MAC %ws\n", amacNameP->Buffer););
+ if (RtlCompareMemory(amacNameP->Buffer, devicePrefix.Buffer,
+ devicePrefix.Length) < devicePrefix.Length)
+ {
+ return FALSE;
+ }
+
+ deviceName.Length = 0;
+ deviceName.MaximumLength = (USHORT)(amacNameP->Length + g_NPF_Prefix.Length + sizeof(UNICODE_NULL));
+ deviceName.Buffer = ExAllocatePoolWithTag(PagedPool, deviceName.MaximumLength, '3PWA');
+
+ if (deviceName.Buffer == NULL)
+ return FALSE;
+
+ deviceSymLink.Length = 0;
+ deviceSymLink.MaximumLength =(USHORT)(amacNameP->Length-devicePrefix.Length
+ + symbolicLinkPrefix.Length
+ + g_NPF_Prefix.Length
+ + sizeof(UNICODE_NULL));
+
+ deviceSymLink.Buffer = ExAllocatePoolWithTag(NonPagedPool, deviceSymLink.MaximumLength, '3PWA');
+
+ if (deviceSymLink.Buffer == NULL)
+ {
+ ExFreePool(deviceName.Buffer);
+ return FALSE;
+ }
+
+ RtlAppendUnicodeStringToString(&deviceName, &devicePrefix);
+ RtlAppendUnicodeStringToString(&deviceName, &g_NPF_Prefix);
+ RtlAppendUnicodeToString(&deviceName, amacNameP->Buffer +
+ devicePrefix.Length / sizeof(WCHAR));
+
+ RtlAppendUnicodeStringToString(&deviceSymLink, &symbolicLinkPrefix);
+ RtlAppendUnicodeStringToString(&deviceSymLink, &g_NPF_Prefix);
+ RtlAppendUnicodeToString(&deviceSymLink, amacNameP->Buffer +
+ devicePrefix.Length / sizeof(WCHAR));
+
+ IF_LOUD(DbgPrint("Creating device name: %ws\n", deviceName.Buffer);)
+
+ status = IoCreateDevice(adriverObjectP,
+ sizeof(DEVICE_EXTENSION),
+ &deviceName,
+ FILE_DEVICE_TRANSPORT,
+#ifdef __NPF_NT4__
+ 0,
+#else //__NPF_NT4__
+ FILE_DEVICE_SECURE_OPEN,
+#endif //__NPF_NT4__
+ FALSE,
+ &devObjP);
+
+ if (NT_SUCCESS(status))
+ {
+ PDEVICE_EXTENSION devExtP = (PDEVICE_EXTENSION)devObjP->DeviceExtension;
+
+ IF_LOUD(DbgPrint("Device created successfully\n"););
+
+ devObjP->Flags |= DO_DIRECT_IO;
+ RtlInitUnicodeString(&devExtP->AdapterName,amacNameP->Buffer);
+
+ IF_LOUD(DbgPrint("Trying to create SymLink %ws\n",deviceSymLink.Buffer););
+
+ if (IoCreateSymbolicLink(&deviceSymLink,&deviceName) != STATUS_SUCCESS)
+ {
+ IF_LOUD(DbgPrint("\n\nError creating SymLink %ws\nn", deviceSymLink.Buffer););
+
+ ExFreePool(deviceName.Buffer);
+ ExFreePool(deviceSymLink.Buffer);
+
+ devExtP->ExportString = NULL;
+
+ return FALSE;
+ }
+
+ IF_LOUD(DbgPrint("SymLink %ws successfully created.\n\n", deviceSymLink.Buffer););
+
+ devExtP->ExportString = deviceSymLink.Buffer;
+
+ ExFreePool(deviceName.Buffer);
+
+ return TRUE;
+ }
+
+ else
+ {
+ IF_LOUD(DbgPrint("\n\nIoCreateDevice status = %x\n", status););
+
+ ExFreePool(deviceName.Buffer);
+ ExFreePool(deviceSymLink.Buffer);
+
+ return FALSE;
+ }
+}
+//-------------------------------------------------------------------
+
+VOID NPF_Unload(IN PDRIVER_OBJECT DriverObject)
+{
+ PDEVICE_OBJECT DeviceObject;
+ PDEVICE_OBJECT OldDeviceObject;
+ PDEVICE_EXTENSION DeviceExtension;
+ NDIS_STATUS Status;
+ NDIS_STRING SymLink;
+
+ TRACE_ENTER();
+
+ DeviceObject = DriverObject->DeviceObject;
+
+ while (DeviceObject != NULL) {
+ OldDeviceObject = DeviceObject;
+
+ DeviceObject = DeviceObject->NextDevice;
+
+ DeviceExtension = OldDeviceObject->DeviceExtension;
+
+ TRACE_MESSAGE4(PACKET_DEBUG_LOUD,"Deleting Adapter %ws, Protocol Handle=%p, Device Obj=%p (%p)",
+ DeviceExtension->AdapterName.Buffer,
+ g_NdisProtocolHandle,
+ DeviceObject,
+ OldDeviceObject);
+
+ if (DeviceExtension->ExportString)
+ {
+ RtlInitUnicodeString(&SymLink , DeviceExtension->ExportString);
+
+ TRACE_MESSAGE1(PACKET_DEBUG_LOUD, "Deleting SymLink at %p", SymLink.Buffer);
+
+ IoDeleteSymbolicLink(&SymLink);
+ ExFreePool(DeviceExtension->ExportString);
+ }
+
+ IoDeleteDevice(OldDeviceObject);
+ }
+
+ NdisDeregisterProtocol(
+ &Status,
+ g_NdisProtocolHandle
+ );
+
+ // Free the adapters names
+ ExFreePool( bindP );
+
+ TRACE_EXIT();
+
+ // Free the device names string that was allocated in the DriverEntry
+// NdisFreeString(g_NPF_Prefix);
+}
+
+#define SET_FAILURE_BUFFER_SMALL() do{\
+ Information = 0; \
+ Status = STATUS_BUFFER_TOO_SMALL; \
+} while(FALSE)
+
+#define SET_RESULT_SUCCESS(__a__) do{\
+ Information = __a__; \
+ Status = STATUS_SUCCESS; \
+} while(FALSE)
+
+#define SET_FAILURE_INVALID_REQUEST() do{\
+ Information = 0; \
+ Status = STATUS_INVALID_DEVICE_REQUEST; \
+} while(FALSE)
+
+#define SET_FAILURE_UNSUCCESSFUL() do{\
+ Information = 0; \
+ Status = STATUS_UNSUCCESSFUL; \
+} while(FALSE)
+
+#define SET_FAILURE_NOMEM() do{\
+ Information = 0; \
+ Status = STATUS_INSUFFICIENT_RESOURCES; \
+} while(FALSE)
+
+//-------------------------------------------------------------------
+
+NTSTATUS NPF_IoControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
+{
+ POPEN_INSTANCE Open;
+ PIO_STACK_LOCATION IrpSp;
+ PLIST_ENTRY RequestListEntry;
+ PINTERNAL_REQUEST pRequest;
+ ULONG FunctionCode;
+ NDIS_STATUS Status;
+ ULONG Information = 0;
+ PLIST_ENTRY PacketListEntry;
+ UINT i;
+ PUCHAR tpointer;
+ ULONG dim,timeout;
+ struct bpf_insn* NewBpfProgram;
+ PPACKET_OID_DATA OidData;
+ int *StatsBuf;
+ PNDIS_PACKET pPacket;
+ ULONG mode;
+ PWSTR DumpNameBuff;
+ PUCHAR TmpBPFProgram;
+ INT WriteRes;
+ BOOLEAN SyncWrite = FALSE;
+ struct bpf_insn *initprogram;
+ ULONG insns;
+ ULONG cnt;
+ BOOLEAN IsExtendedFilter=FALSE;
+ ULONG StringLength;
+ ULONG NeededBytes;
+ BOOLEAN Flag;
+ PUINT pStats;
+ ULONG StatsLength;
+
+ HANDLE hUserEvent;
+ PKEVENT pKernelEvent;
+#ifdef _AMD64_
+ VOID*POINTER_32 hUserEvent32Bit;
+#endif //_AMD64_
+ PMDL mdl;
+
+ TRACE_ENTER();
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+ FunctionCode=IrpSp->Parameters.DeviceIoControl.IoControlCode;
+ Open=IrpSp->FileObject->FsContext;
+
+ if (NPF_StartUsingOpenInstance(Open) == FALSE)
+ {
+ //
+ // an IRP_MJ_CLEANUP was received, just fail the request
+ //
+ Irp->IoStatus.Information = 0;
+ Irp->IoStatus.Status = STATUS_CANCELLED;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ TRACE_EXIT();
+ return STATUS_CANCELLED;
+ }
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+
+ TRACE_MESSAGE3(PACKET_DEBUG_LOUD,
+ "Function code is %08lx Input size=%08lx Output size %08lx",
+ FunctionCode,
+ IrpSp->Parameters.DeviceIoControl.InputBufferLength,
+ IrpSp->Parameters.DeviceIoControl.OutputBufferLength);
+
+ switch (FunctionCode){
+
+ case BIOCGSTATS: //function to get the capture stats
+
+ TRACE_MESSAGE(PACKET_DEBUG_LOUD, "BIOCGSTATS");
+
+ StatsLength = 4*sizeof(UINT);
+ if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength < StatsLength)
+ {
+ SET_FAILURE_BUFFER_SMALL();
+ break;
+ }
+
+ if (Irp->UserBuffer == NULL)
+ {
+ SET_FAILURE_UNSUCCESSFUL();
+ break;
+ }
+
+ //
+ // temp fix to a GIANT bug from LD. The CTL code has been defined as METHOD_NEITHER, so it
+ // might well be a dangling pointer. We need to probe and lock the address.
+ //
+
+ mdl = NULL;
+ pStats = NULL;
+
+ __try
+ {
+ mdl = IoAllocateMdl(
+ Irp->UserBuffer,
+ StatsLength,
+ FALSE,
+ TRUE,
+ NULL);
+
+ if (mdl == NULL)
+ {
+ SET_FAILURE_UNSUCCESSFUL();
+ break;
+ }
+
+ MmProbeAndLockPages(
+ mdl,
+ UserMode,
+ IoWriteAccess);
+
+ pStats = (PUINT)(Irp->UserBuffer);
+ }
+ __except(GetExceptionCode() == STATUS_ACCESS_VIOLATION)
+ {
+ pStats = NULL;
+ }
+
+ if (pStats == NULL)
+ {
+ if (mdl != NULL)
+ {
+ IoFreeMdl(mdl);
+ }
+
+ SET_FAILURE_UNSUCCESSFUL();
+ break;
+ }
+
+ pStats[3] = 0;
+ pStats[0] = 0;
+ pStats[1] = 0;
+ pStats[2] = 0; // Not yet supported
+
+ for(i = 0 ; i < g_NCpu ; i++)
+ {
+
+ pStats[3] += Open->CpuData[i].Accepted;
+ pStats[0] += Open->CpuData[i].Received;
+ pStats[1] += Open->CpuData[i].Dropped;
+ pStats[2] += 0; // Not yet supported
+ }
+
+ MmUnlockPages(mdl);
+ IoFreeMdl(mdl);
+
+ SET_RESULT_SUCCESS(StatsLength);
+
+ break;
+
+ case BIOCGEVNAME: //function to get the name of the event associated with the current instance
+
+ TRACE_MESSAGE(PACKET_DEBUG_LOUD, "BIOCGEVNAME");
+
+ //
+ // Since 20060405, the event handling has been changed:
+ // we no longer use named events, instead the user level app creates an event,
+ // and passes it back to the kernel, that references it (ObReferenceObjectByHandle), and
+ // signals it.
+ // For the time being, we still leave this ioctl code here, and we simply fail.
+ //
+ SET_FAILURE_INVALID_REQUEST();
+ break;
+
+ case BIOCSENDPACKETSSYNC:
+
+ SyncWrite = TRUE;
+
+ case BIOCSENDPACKETSNOSYNC:
+
+ TRACE_MESSAGE(PACKET_DEBUG_LOUD, "BIOCSENDPACKETSNOSYNC");
+
+ NdisAcquireSpinLock(&Open->WriteLock);
+ if(Open->WriteInProgress)
+ {
+ NdisReleaseSpinLock(&Open->WriteLock);
+ //
+ // Another write operation is currently in progress
+ //
+ SET_FAILURE_UNSUCCESSFUL();
+ break;
+ }
+ else
+ {
+ Open->WriteInProgress = TRUE;
+ }
+ NdisReleaseSpinLock(&Open->WriteLock);
+
+ WriteRes = NPF_BufferedWrite(Irp,
+ (PUCHAR)Irp->AssociatedIrp.SystemBuffer,
+ IrpSp->Parameters.DeviceIoControl.InputBufferLength,
+ SyncWrite);
+
+ NdisAcquireSpinLock(&Open->WriteLock);
+ Open->WriteInProgress = FALSE;
+ NdisReleaseSpinLock(&Open->WriteLock);
+
+ if( WriteRes != -1)
+ {
+ SET_RESULT_SUCCESS(WriteRes);
+ }
+ else
+ {
+ SET_FAILURE_UNSUCCESSFUL();
+ }
+ break;
+
+ case BIOCSETF:
+
+ TRACE_MESSAGE(PACKET_DEBUG_LOUD, "BIOCSETF");
+
+ //
+ // Get the pointer to the new program
+ //
+ NewBpfProgram = (struct bpf_insn*)Irp->AssociatedIrp.SystemBuffer;
+
+ if(NewBpfProgram == NULL)
+ {
+ SET_FAILURE_BUFFER_SMALL();
+ break;
+ }
+
+ //
+ // Lock the machine. After this call we are at DISPATCH level
+ //
+ NdisAcquireSpinLock(&Open->MachineLock);
+
+ do
+ {
+
+ // Free the previous buffer if it was present
+ if(Open->bpfprogram != NULL)
+ {
+ TmpBPFProgram = Open->bpfprogram;
+ Open->bpfprogram = NULL;
+ ExFreePool(TmpBPFProgram);
+ }
+
+//
+// Jitted filters are supported on x86 (32bit) only
+//
+#ifdef _X86_
+ if (Open->Filter != NULL)
+ {
+ BPF_Destroy_JIT_Filter(Open->Filter);
+ Open->Filter = NULL;
+ }
+#endif // _X86_
+
+ insns = (IrpSp->Parameters.DeviceIoControl.InputBufferLength)/sizeof(struct bpf_insn);
+
+ //count the number of operative instructions
+ for (cnt = 0 ; (cnt < insns) &&(NewBpfProgram[cnt].code != BPF_SEPARATION); cnt++);
+
+ TRACE_MESSAGE1(PACKET_DEBUG_LOUD, "Operative instructions=%u", cnt);
+
+#ifdef HAVE_BUGGY_TME_SUPPORT
+ if ( (cnt != insns) && (insns != cnt+1) && (NewBpfProgram[cnt].code == BPF_SEPARATION))
+ {
+ TRACE_MESSAGE1(PACKET_DEBUG_LOUD,"Initialization instructions = %u",insns-cnt-1);
+
+ IsExtendedFilter = TRUE;
+
+ initprogram = &NewBpfProgram[cnt+1];
+
+ if(bpf_filter_init(initprogram,&(Open->mem_ex),&(Open->tme), &G_Start_Time)!=INIT_OK)
+ {
+
+ TRACE_MESSAGE(PACKET_DEBUG_LOUD, "Error initializing NPF machine (bpf_filter_init)");
+
+ SET_FAILURE_INVALID_REQUEST();
+ break;
+ }
+ }
+#else // HAVE_BUGGY_TME_SUPPORT
+ if ( cnt != insns)
+ {
+ TRACE_MESSAGE(PACKET_DEBUG_LOUD, "Error installing the BPF filter. The filter contains TME extensions,"
+ " not supported on 64bit platforms.");
+
+ SET_FAILURE_INVALID_REQUEST();
+ break;
+ }
+#endif // HAVE_BUGGY_TME_SUPPORT
+
+ //the NPF processor has been initialized, we have to validate the operative instructions
+ insns = cnt;
+
+ //NOTE: the validation code checks for TME instructions, and fails if a TME instruction is
+ //encountered on 64 bit machines
+#ifdef HAVE_BUGGY_TME_SUPPORT
+ if(bpf_validate(NewBpfProgram, cnt, Open->mem_ex.size) == 0)
+#else //HAVE_BUGGY_TME_SUPPORT
+ if(bpf_validate(NewBpfProgram, cnt) == 0)
+#endif //HAVE_BUGGY_TME_SUPPORT
+ {
+ TRACE_MESSAGE(PACKET_DEBUG_LOUD, "Error validating program");
+ //FIXME: the machine has been initialized(?), but the operative code is wrong.
+ //we have to reset the machine!
+ //something like: reallocate the mem_ex, and reset the tme_core
+ SET_FAILURE_INVALID_REQUEST();
+ break;
+ }
+
+ // Allocate the memory to contain the new filter program
+ // We could need the original BPF binary if we are forced to use bpf_filter_with_2_buffers()
+ TmpBPFProgram = (PUCHAR)ExAllocatePoolWithTag(NonPagedPool, cnt*sizeof(struct bpf_insn), '4PWA');
+ if (TmpBPFProgram == NULL)
+ {
+ TRACE_MESSAGE(PACKET_DEBUG_LOUD, "Error - No memory for filter");
+ // no memory
+
+ SET_FAILURE_NOMEM();
+ break;
+ }
+
+ //
+ // At the moment the JIT compiler works on x86 (32 bit) only
+ //
+#ifdef _X86_
+ // Create the new JIT filter function
+ if(!IsExtendedFilter)
+ {
+ if((Open->Filter = BPF_jitter(NewBpfProgram, cnt)) == NULL)
+ {
+ TRACE_MESSAGE(PACKET_DEBUG_LOUD, "Error jittering filter");
+
+ ExFreePool(TmpBPFProgram);
+
+ SET_FAILURE_UNSUCCESSFUL();
+ break;
+ }
+ }
+#endif //_X86_
+
+ //copy the program in the new buffer
+ RtlCopyMemory(TmpBPFProgram,NewBpfProgram,cnt*sizeof(struct bpf_insn));
+ Open->bpfprogram = TmpBPFProgram;
+
+ SET_RESULT_SUCCESS(0);
+ }
+ while(FALSE);
+
+ //
+ // release the machine lock and then reset the buffer
+ //
+ NdisReleaseSpinLock(&Open->MachineLock);
+
+ NPF_ResetBufferContents(Open);
+
+ break;
+
+ case BIOCSMODE: //set the capture mode
+
+ TRACE_MESSAGE(PACKET_DEBUG_LOUD, "BIOCSMODE");
+
+ if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
+ {
+ SET_FAILURE_BUFFER_SMALL();
+ break;
+ }
+
+ mode=*((PULONG)Irp->AssociatedIrp.SystemBuffer);
+
+///////kernel dump does not work at the moment//////////////////////////////////////////
+ if (mode & MODE_DUMP)
+ {
+ SET_FAILURE_INVALID_REQUEST();
+ break;
+ }
+///////kernel dump does not work at the moment//////////////////////////////////////////
+
+ if(mode == MODE_CAPT)
+ {
+ Open->mode = MODE_CAPT;
+
+ SET_RESULT_SUCCESS(0);
+ break;
+ }
+ else if (mode == MODE_MON)
+ {
+ //
+ // The MONITOR_MODE (aka TME extensions) is not supported on
+ // 64 bit architectures
+ //
+
+#ifdef HAVE_BUGGY_TME_SUPPORT
+ Open->mode = MODE_MON;
+ SET_RESULT_SUCCESS(0);
+#else // HAVE_BUGGY_TME_SUPPORT
+ SET_FAILURE_INVALID_REQUEST();
+#endif // HAVE_BUGGY_TME_SUPPORT
+
+ break;
+ }
+ else{
+ if(mode & MODE_STAT){
+ Open->mode = MODE_STAT;
+ NdisAcquireSpinLock(&Open->CountersLock);
+ Open->Nbytes.QuadPart = 0;
+ Open->Npackets.QuadPart = 0;
+ NdisReleaseSpinLock(&Open->CountersLock);
+
+ if(Open->TimeOut.QuadPart==0)Open->TimeOut.QuadPart = -10000000;
+
+ }
+
+ if(mode & MODE_DUMP){
+
+ Open->mode |= MODE_DUMP;
+// Open->MinToCopy=(Open->BufSize<2000000)?Open->BufSize/2:1000000;
+
+ }
+
+ SET_RESULT_SUCCESS(0);
+ break;
+ }
+
+ SET_FAILURE_INVALID_REQUEST();
+
+ break;
+
+ case BIOCSETDUMPFILENAME:
+
+ TRACE_MESSAGE(PACKET_DEBUG_LOUD, "BIOCSETDUMPFILENAME");
+
+///////kernel dump does not work at the moment//////////////////////////////////////////
+ SET_FAILURE_INVALID_REQUEST();
+ break;
+///////kernel dump does not work at the moment//////////////////////////////////////////
+
+ //if(Open->mode & MODE_DUMP)
+ //{
+ //
+ // // Close current dump file
+ // if(Open->DumpFileHandle != NULL)
+ // {
+ // NPF_CloseDumpFile(Open);
+ // Open->DumpFileHandle = NULL;
+ // }
+ //
+ // if(IrpSp->Parameters.DeviceIoControl.InputBufferLength == 0){
+ // EXIT_FAILURE(0);
+ // }
+ //
+ // // Allocate the buffer that will contain the string
+ // DumpNameBuff=ExAllocatePoolWithTag(NonPagedPool, IrpSp->Parameters.DeviceIoControl.InputBufferLength, '5PWA');
+ // if(DumpNameBuff==NULL || Open->DumpFileName.Buffer!=NULL){
+ // IF_LOUD(DbgPrint("NPF: unable to allocate the dump filename: not enough memory or name already set\n");)
+ // EXIT_FAILURE(0);
+ // }
+ //
+ // // Copy the buffer
+ // RtlCopyBytes((PVOID)DumpNameBuff,
+ // Irp->AssociatedIrp.SystemBuffer,
+ // IrpSp->Parameters.DeviceIoControl.InputBufferLength);
+ //
+ // // Force a \0 at the end of the filename to avoid that malformed strings cause RtlInitUnicodeString to crash the system
+ // ((PSHORT)DumpNameBuff)[IrpSp->Parameters.DeviceIoControl.InputBufferLength/2-1]=0;
+ //
+ // // Create the unicode string
+ // RtlInitUnicodeString(&Open->DumpFileName, DumpNameBuff);
+ //
+ // IF_LOUD(DbgPrint("NPF: dump file name set to %ws, len=%d\n",
+ // Open->DumpFileName.Buffer,
+ // IrpSp->Parameters.DeviceIoControl.InputBufferLength);)
+ //
+ // // Try to create the file
+ // if ( NT_SUCCESS( NPF_OpenDumpFile(Open,&Open->DumpFileName,FALSE)) &&
+ // NT_SUCCESS( NPF_StartDump(Open)))
+ // {
+ // EXIT_SUCCESS(0);
+ // }
+ //}
+ //
+ //EXIT_FAILURE(0);
+ //
+ //break;
+
+ case BIOCSETDUMPLIMITS:
+
+ TRACE_MESSAGE(PACKET_DEBUG_LOUD, "BIOCSETDUMPLIMITS");
+
+///////kernel dump does not work at the moment//////////////////////////////////////////
+ SET_FAILURE_INVALID_REQUEST();
+ break;
+///////kernel dump does not work at the moment//////////////////////////////////////////
+
+ //if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < 2*sizeof(ULONG))
+ //{
+ // EXIT_FAILURE(0);
+ //}
+ //
+ //Open->MaxDumpBytes = *(PULONG)Irp->AssociatedIrp.SystemBuffer;
+ //Open->MaxDumpPacks = *((PULONG)Irp->AssociatedIrp.SystemBuffer + 1);
+ //
+ //IF_LOUD(DbgPrint("NPF: Set dump limits to %u bytes, %u packs\n", Open->MaxDumpBytes, Open->MaxDumpPacks);)
+ //
+ //EXIT_SUCCESS(0);
+ //
+ //break;
+
+ case BIOCISDUMPENDED:
+
+ TRACE_MESSAGE(PACKET_DEBUG_LOUD, "BIOCISDUMPENDED");
+
+///////kernel dump does not work at the moment//////////////////////////////////////////
+ SET_FAILURE_INVALID_REQUEST();
+ break;
+///////kernel dump does not work at the moment//////////////////////////////////////////
+
+ //if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(UINT))
+ //{
+ // EXIT_FAILURE(0);
+ //}
+
+ //*((UINT*)Irp->UserBuffer) = (Open->DumpLimitReached)?1:0;
+
+ //EXIT_SUCCESS(4);
+
+ //break;
+
+ case BIOCISETLOBBEH:
+
+ if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(INT))
+ {
+ SET_FAILURE_BUFFER_SMALL();
+ break;
+ }
+
+#ifdef __NPF_NT4__
+
+ // NT4 doesn't support loopback inhibition / activation
+ SET_FAILURE_INVALID_REQUEST();
+ break;
+
+#else //not __NPF_NT4__
+ //
+ // win2000/xp/2003/vista
+ //
+ if(*(PINT)Irp->AssociatedIrp.SystemBuffer == NPF_DISABLE_LOOPBACK)
+ {
+ Open->SkipSentPackets = TRUE;
+
+ //
+ // Reset the capture buffers, since they could contain loopbacked packets
+ //
+
+ NPF_ResetBufferContents(Open);
+
+ SET_RESULT_SUCCESS(0);
+ break;
+
+ }
+ else
+ if(*(PINT)Irp->AssociatedIrp.SystemBuffer == NPF_ENABLE_LOOPBACK)
+ {
+ Open->SkipSentPackets = FALSE;
+
+ SET_RESULT_SUCCESS(0);
+ break;
+ }
+ else
+ {
+ // Unknown operation
+ SET_FAILURE_INVALID_REQUEST();
+ break;
+ }
+
+#endif // !__NPF_NT4__
+ break;
+
+ case BIOCSETEVENTHANDLE:
+
+ TRACE_MESSAGE(PACKET_DEBUG_LOUD, "BIOCSETEVENTHANDLE");
+
+#ifdef _AMD64_
+ if (IoIs32bitProcess(Irp))
+ {
+ //
+ // validate the input
+ //
+ if (IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof (hUserEvent32Bit))
+ {
+ SET_FAILURE_INVALID_REQUEST();
+ break;
+ }
+
+ hUserEvent32Bit = *(VOID*POINTER_32*)Irp->AssociatedIrp.SystemBuffer;
+ hUserEvent = hUserEvent32Bit;
+ }
+ else
+#endif //_AMD64_
+ {
+ //
+ // validate the input
+ //
+ if (IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof (hUserEvent))
+ {
+ SET_FAILURE_INVALID_REQUEST();
+ break;
+ }
+
+ hUserEvent = *(PHANDLE)Irp->AssociatedIrp.SystemBuffer;
+ }
+
+ //
+ // NT4 doesn't seem to have EVENT_MODIFY_STATE, so on NT4 we request a wider set
+ // of privileges for the event handle
+ //
+#ifdef __NPF_NT4__
+ Status = ObReferenceObjectByHandle(hUserEvent,
+ OBJECT_TYPE_ALL_ACCESS, *ExEventObjectType, Irp->RequestorMode,
+ (PVOID*) &pKernelEvent, NULL);
+#else //__NPF_NT4__
+ Status = ObReferenceObjectByHandle(hUserEvent,
+ EVENT_MODIFY_STATE, *ExEventObjectType, Irp->RequestorMode,
+ (PVOID*) &pKernelEvent, NULL);
+#endif //__NPF_NT4__
+
+ if (!NT_SUCCESS(Status))
+ {
+ // Status = ??? already set
+ Information = 0;
+ break;
+ }
+
+
+ //
+ // NT4 does not have InterlockedCompareExchangePointer
+ // InterlockedCompareExchange on NT4 has the same prototype of InterlockedCompareExchange
+ // on NT5x, so we use this one.
+ //
+#ifdef __NPF_NT4__
+ if (InterlockedCompareExchange(&Open->ReadEvent, pKernelEvent, NULL) != NULL)
+#else
+ if (InterlockedCompareExchangePointer(&Open->ReadEvent, pKernelEvent, NULL) != NULL)
+#endif
+ {
+ //
+ // dereference the new pointer
+ //
+
+ ObDereferenceObject(pKernelEvent);
+ SET_FAILURE_INVALID_REQUEST();
+ break;
+ }
+
+ KeResetEvent(Open->ReadEvent);
+
+ SET_RESULT_SUCCESS(0);
+ break;
+
+ case BIOCSETBUFFERSIZE:
+
+ TRACE_MESSAGE(PACKET_DEBUG_LOUD, "BIOCSETBUFFERSIZE");
+
+
+ if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
+ {
+ SET_FAILURE_BUFFER_SMALL();
+ break;
+ }
+
+ // Get the number of bytes to allocate
+ dim = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
+
+ if (dim / g_NCpu < sizeof(struct PacketHeader))
+ {
+ dim = 0;
+ }
+ else
+ {
+ tpointer = ExAllocatePoolWithTag(NonPagedPool, dim, '6PWA');
+ if (tpointer == NULL)
+ {
+ // no memory
+ SET_FAILURE_NOMEM();
+ break;
+ }
+ }
+
+ //
+ // acquire the locks for all the buffers
+ //
+ for (i = 0; i < g_NCpu ; i++)
+ {
+#pragma prefast(suppress:8103, "There's no Spinlock leak here, as it's released some lines below.")
+ NdisAcquireSpinLock(&Open->CpuData[i].BufferLock);
+ }
+
+ //
+ // free the old buffer, if any
+ //
+ if (Open->CpuData[0].Buffer != NULL)
+ {
+ ExFreePool(Open->CpuData[0].Buffer);
+ }
+
+ for (i = 0 ; i < g_NCpu ; i++)
+ {
+ if (dim > 0)
+ Open->CpuData[i].Buffer=(PUCHAR)tpointer + (dim/g_NCpu)*i;
+ else
+ Open->CpuData[i].Buffer = NULL;
+ Open->CpuData[i].Free = dim/g_NCpu;
+ Open->CpuData[i].P = 0;
+ Open->CpuData[i].C = 0;
+ Open->CpuData[i].Accepted = 0;
+ Open->CpuData[i].Dropped = 0;
+ Open->CpuData[i].Received = 0;
+ }
+
+ Open->ReaderSN=0;
+ Open->WriterSN=0;
+
+ Open->Size = dim/g_NCpu;
+
+ //
+ // acquire the locks for all the buffers
+ //
+ i = g_NCpu;
+
+ do
+ {
+ i--;
+
+#pragma prefast(suppress:8107, "There's no Spinlock leak here, as it's acquired some lines above.")
+ NdisReleaseSpinLock(&Open->CpuData[i].BufferLock);
+ }while(i != 0);
+
+ SET_RESULT_SUCCESS(0);
+ break;
+
+ case BIOCSRTIMEOUT: //set the timeout on the read calls
+
+ TRACE_MESSAGE(PACKET_DEBUG_LOUD, "BIOCSRTIMEOUT");
+
+ if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
+ {
+ SET_FAILURE_BUFFER_SMALL();
+ break;
+ }
+
+ timeout = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
+ if(timeout == (ULONG)-1)
+ Open->TimeOut.QuadPart=(LONGLONG)IMMEDIATE;
+ else
+ {
+ Open->TimeOut.QuadPart = (LONGLONG)timeout;
+ Open->TimeOut.QuadPart *= 10000;
+ Open->TimeOut.QuadPart = -Open->TimeOut.QuadPart;
+ }
+
+ TRACE_MESSAGE1(PACKET_DEBUG_LOUD, "Read timeout set to %I64d",Open->TimeOut.QuadPart);
+
+ SET_RESULT_SUCCESS(0);
+ break;
+
+ case BIOCSWRITEREP: //set the writes repetition number
+
+ TRACE_MESSAGE(PACKET_DEBUG_LOUD, "BIOCSWRITEREP");
+
+ if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
+ {
+ SET_FAILURE_BUFFER_SMALL();
+ break;
+ }
+
+ Open->Nwrites = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
+
+ SET_RESULT_SUCCESS(0);
+ break;
+
+ case BIOCSMINTOCOPY: //set the minimum buffer's size to copy to the application
+
+ TRACE_MESSAGE(PACKET_DEBUG_LOUD, "BIOCSMINTOCOPY");
+
+ if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
+ {
+ SET_FAILURE_BUFFER_SMALL();
+ break;
+ }
+
+ Open->MinToCopy = (*((PULONG)Irp->AssociatedIrp.SystemBuffer))/g_NCpu; //An hack to make the NCPU-buffers behave like a larger one
+
+ SET_RESULT_SUCCESS(0);
+ break;
+
+// case IOCTL_PROTOCOL_RESET:
+//
+// TRACE_MESSAGE(PACKET_DEBUG_LOUD, "IOCTL_PROTOCOL_RESET");
+//
+// IoMarkIrpPending(Irp);
+// Irp->IoStatus.Status = STATUS_SUCCESS;
+//
+// ExInterlockedInsertTailList(&Open->ResetIrpList,&Irp->Tail.Overlay.ListEntry,&Open->RequestSpinLock);
+// NdisReset(&Status,Open->AdapterHandle);
+// if (Status != NDIS_STATUS_PENDING)
+// {
+// IF_LOUD(DbgPrint("NPF: IoControl - ResetComplete being called\n");)
+// NPF_ResetComplete(Open,Status);
+// }
+//
+// break;
+
+ case BIOCSETOID:
+ case BIOCQUERYOID:
+
+ TRACE_MESSAGE(PACKET_DEBUG_LOUD, "BIOCSETOID - BIOCQUERYOID");
+
+ //
+ // gain ownership of the Ndis Handle
+ //
+ if (NPF_StartUsingBinding(Open) == FALSE)
+ {
+ //
+ // MAC unbindind or unbound
+ //
+ SET_FAILURE_INVALID_REQUEST();
+ break;
+ }
+
+
+ // Extract a request from the list of free ones
+ RequestListEntry=ExInterlockedRemoveHeadList(&Open->RequestList,&Open->RequestSpinLock);
+ if (RequestListEntry == NULL)
+ {
+ //
+ // Release ownership of the Ndis Handle
+ //
+ NPF_StopUsingBinding(Open);
+
+ SET_FAILURE_NOMEM();
+ break;
+ }
+
+ pRequest=CONTAINING_RECORD(RequestListEntry,INTERNAL_REQUEST,ListElement);
+
+ //
+ // See if it is an Ndis request
+ //
+ OidData=Irp->AssociatedIrp.SystemBuffer;
+
+ if ((IrpSp->Parameters.DeviceIoControl.InputBufferLength == IrpSp->Parameters.DeviceIoControl.OutputBufferLength)
+ &&
+ (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA))
+ &&
+ (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA)-1+OidData->Length)) {
+
+ TRACE_MESSAGE2(PACKET_DEBUG_LOUD, "BIOCSETOID|BIOCQUERYOID Request: Oid=%08lx, Length=%08lx",OidData->Oid,OidData->Length);
+
+ //
+ // The buffer is valid
+ //
+ if (FunctionCode == BIOCSETOID){
+
+ pRequest->Request.RequestType=NdisRequestSetInformation;
+ pRequest->Request.DATA.SET_INFORMATION.Oid=OidData->Oid;
+
+ pRequest->Request.DATA.SET_INFORMATION.InformationBuffer=OidData->Data;
+ pRequest->Request.DATA.SET_INFORMATION.InformationBufferLength=OidData->Length;
+
+
+ }
+ else{
+
+ pRequest->Request.RequestType=NdisRequestQueryInformation;
+ pRequest->Request.DATA.QUERY_INFORMATION.Oid=OidData->Oid;
+
+ pRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer=OidData->Data;
+ pRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength=OidData->Length;
+
+ }
+
+ NdisResetEvent(&pRequest->InternalRequestCompletedEvent);
+
+ //
+ // submit the request
+ //
+ NdisRequest(
+ &Status,
+ Open->AdapterHandle,
+ &pRequest->Request
+ );
+
+ } else {
+ //
+ // Release ownership of the Ndis Handle
+ //
+ NPF_StopUsingBinding(Open);
+
+ //
+ // buffer too small
+ //
+ SET_FAILURE_BUFFER_SMALL();
+ break;
+ }
+
+ if (Status == NDIS_STATUS_PENDING)
+ {
+ NdisWaitEvent(&pRequest->InternalRequestCompletedEvent, 0);
+ Status = pRequest->RequestStatus;
+ }
+
+ //
+ // Release ownership of the Ndis Handle
+ //
+ NPF_StopUsingBinding(Open);
+
+ //
+ // Complete the request
+ //
+ if (FunctionCode == BIOCSETOID)
+ {
+ OidData->Length = pRequest->Request.DATA.SET_INFORMATION.BytesRead;
+ TRACE_MESSAGE1(PACKET_DEBUG_LOUD, "BIOCSETOID completed, BytesRead = %u",OidData->Length);
+ }
+ else
+ {
+ if (FunctionCode == BIOCQUERYOID)
+ {
+ OidData->Length = pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten;
+
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ //
+ // check for the stupid bug of the Nortel driver ipsecw2k.sys v. 4.10.0.0 that doesn't set the BytesWritten correctly
+ // The driver is the one shipped with Nortel client Contivity VPN Client V04_65.18, and the MD5 for the buggy (unsigned) driver
+ // is 3c2ff8886976214959db7d7ffaefe724 *ipsecw2k.sys (there are multiple copies of this binary with the same exact version info!)
+ //
+ // The (certified) driver shipped with Nortel client Contivity VPN Client V04_65.320 doesn't seem affected by the bug.
+ //
+ if (pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten > pRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength)
+ {
+ TRACE_MESSAGE2(PACKET_DEBUG_LOUD, "Bogus return from NdisRequest (query): Bytes Written (%u) > InfoBufferLength (%u)!!",
+ pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten,
+ pRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength);
+
+ Status = NDIS_STATUS_INVALID_DATA;
+ }
+ }
+
+ TRACE_MESSAGE1(PACKET_DEBUG_LOUD, "BIOCQUERYOID completed, BytesWritten = %u",OidData->Length);
+ }
+ }
+
+
+ ExInterlockedInsertTailList(
+ &Open->RequestList,
+ &pRequest->ListElement,
+ &Open->RequestSpinLock);
+
+ if (Status == NDIS_STATUS_SUCCESS)
+ {
+ SET_RESULT_SUCCESS(sizeof(PACKET_OID_DATA) - 1 + OidData->Length);
+ }
+ else
+ {
+ SET_FAILURE_INVALID_REQUEST();
+ }
+
+ break;
+
+
+ default:
+
+ TRACE_MESSAGE(PACKET_DEBUG_LOUD, "Unknown IOCTL code");
+ SET_FAILURE_INVALID_REQUEST();
+ break;
+ }
+
+
+ //
+ // release the Open structure
+ //
+ NPF_StopUsingOpenInstance(Open);
+
+ //
+ // complete the IRP
+ //
+ Irp->IoStatus.Information = Information;
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+
+ TRACE_EXIT();
+
+ return Status;
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_RequestComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN PNDIS_REQUEST NdisRequest,
+ IN NDIS_STATUS Status
+ )
+
+{
+ PINTERNAL_REQUEST pRequest;
+
+ TRACE_ENTER();
+
+ pRequest = CONTAINING_RECORD(NdisRequest,INTERNAL_REQUEST,Request);
+
+ //
+ // Set the request result
+ //
+ pRequest->RequestStatus = Status;
+
+ //
+ // and awake the caller
+ //
+ NdisSetEvent(&pRequest->InternalRequestCompletedEvent);
+
+ TRACE_EXIT();
+ return;
+
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_Status(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status,
+ IN PVOID StatusBuffer,
+ IN UINT StatusBufferSize
+ )
+
+{
+
+ IF_LOUD(DbgPrint("NPF: Status Indication\n");)
+
+ return;
+
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_StatusComplete(
+ IN NDIS_HANDLE ProtocolBindingContext
+ )
+
+{
+
+ IF_LOUD(DbgPrint("NPF: StatusIndicationComplete\n");)
+
+ return;
+
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS
+NPF_ReadRegistry(
+ IN PWSTR *MacDriverName,
+ IN PWSTR *PacketDriverName,
+ IN PUNICODE_STRING RegistryPath
+ )
+
+{
+ NTSTATUS Status;
+
+ RTL_QUERY_REGISTRY_TABLE ParamTable[4];
+
+ PWSTR Bind = L"Bind";
+ PWSTR Export = L"Export";
+ PWSTR Parameters = L"Parameters";
+ PWSTR Linkage = L"Linkage";
+
+ PWCHAR Path;
+
+
+
+ Path=ExAllocatePoolWithTag(PagedPool, RegistryPath->Length+sizeof(WCHAR), '7PWA');
+
+ if (Path == NULL) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlZeroMemory(
+ Path,
+ RegistryPath->Length+sizeof(WCHAR)
+ );
+
+ RtlCopyMemory(
+ Path,
+ RegistryPath->Buffer,
+ RegistryPath->Length
+ );
+
+ IF_LOUD(DbgPrint("NPF: Reg path is %ws\n",RegistryPath->Buffer);)
+
+ RtlZeroMemory(
+ ParamTable,
+ sizeof(ParamTable)
+ );
+
+
+
+ //
+ // change to the linkage key
+ //
+
+ ParamTable[0].QueryRoutine = NULL;
+ ParamTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
+ ParamTable[0].Name = Linkage;
+
+
+ //
+ // Get the name of the mac driver we should bind to
+ //
+
+ ParamTable[1].QueryRoutine = NPF_QueryRegistryRoutine;
+ ParamTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED |
+ RTL_QUERY_REGISTRY_NOEXPAND;
+
+ ParamTable[1].Name = Bind;
+ ParamTable[1].EntryContext = (PVOID)MacDriverName;
+ ParamTable[1].DefaultType = REG_MULTI_SZ;
+
+ //
+ // Get the name that we should use for the driver object
+ //
+
+ ParamTable[2].QueryRoutine = NPF_QueryRegistryRoutine;
+ ParamTable[2].Flags = RTL_QUERY_REGISTRY_REQUIRED |
+ RTL_QUERY_REGISTRY_NOEXPAND;
+
+ ParamTable[2].Name = Export;
+ ParamTable[2].EntryContext = (PVOID)PacketDriverName;
+ ParamTable[2].DefaultType = REG_MULTI_SZ;
+
+
+ Status=RtlQueryRegistryValues(
+ RTL_REGISTRY_ABSOLUTE,
+ Path,
+ ParamTable,
+ NULL,
+ NULL
+ );
+
+
+ ExFreePool(Path);
+
+ return Status;
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS
+NPF_QueryRegistryRoutine(
+ IN PWSTR ValueName,
+ IN ULONG ValueType,
+ IN PVOID ValueData,
+ IN ULONG ValueLength,
+ IN PVOID Context,
+ IN PVOID EntryContext
+ )
+
+{
+
+ PUCHAR Buffer;
+
+ IF_LOUD(DbgPrint("Perf: QueryRegistryRoutine\n");)
+
+ if (ValueType != REG_MULTI_SZ) {
+
+ return STATUS_OBJECT_NAME_NOT_FOUND;
+
+ }
+
+ Buffer=ExAllocatePoolWithTag(NonPagedPool, ValueLength, '8PWA');
+
+ if (Buffer==NULL) {
+
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ }
+
+ RtlCopyMemory(
+ Buffer,
+ ValueData,
+ ValueLength
+ );
+
+ *((PUCHAR *)EntryContext)=Buffer;
+
+ return STATUS_SUCCESS;
+
+}
+
+VOID NPF_ResetBufferContents(POPEN_INSTANCE Open)
+{
+ UINT i;
+
+ //
+ // lock all the buffers
+ //
+ for (i = 0 ; i < g_NCpu ; i++)
+ {
+//#pragma prefast(suppress:8103, "There's no Spinlock leak here, as it's released some lines below.")
+ NdisAcquireSpinLock(&Open->CpuData[i].BufferLock);
+ }
+
+ Open->ReaderSN = 0;
+ Open->WriterSN = 0;
+
+ //
+ // reset their pointers
+ //
+ for (i = 0 ; i < g_NCpu ; i++)
+ {
+ Open->CpuData[i].C=0;
+ Open->CpuData[i].P=0;
+ Open->CpuData[i].Free = Open->Size;
+ Open->CpuData[i].Accepted = 0;
+ Open->CpuData[i].Dropped = 0;
+ Open->CpuData[i].Received = 0;
+ }
+
+ //
+ // release the locks in reverse order
+ //
+ i = g_NCpu;
+
+ do
+ {
+ i--;
+#pragma prefast(suppress:8107, "There's no Spinlock leak here, as it's allocated some lines above.")
+ NdisReleaseSpinLock(&Open->CpuData[i].BufferLock);
+
+ }
+ while (i != 0);
+}
+
+#if 0
+//
+// Old registry based WinPcap names
+//
+
+//-------------------------------------------------------------------
+
+//NOTE: ValueLen is the length of Value in characters
+
+VOID NPF_QueryWinpcapRegistryString(PWSTR SubKeyName,
+ WCHAR *Value,
+ UINT ValueLen,
+ WCHAR *DefaultValue)
+{
+ UINT CharsToCopy;
+
+#ifdef WPCAP_OEM
+ OBJECT_ATTRIBUTES objAttrs;
+ NTSTATUS status;
+ HANDLE keyHandle;
+ UNICODE_STRING SubKeyToQueryU;
+ CHAR kvpiBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(WCHAR) * MAX_WINPCAP_KEY_CHARS];
+ ULONG QvkResultLength;
+ PKEY_VALUE_PARTIAL_INFORMATION pKeyValuePartialInformation = (PKEY_VALUE_PARTIAL_INFORMATION)kvpiBuffer;
+ PWCHAR pResultingKeyValue;
+
+ //
+ // Create subkey string
+ //
+ RtlInitUnicodeString(&SubKeyToQueryU, SubKeyName);
+
+ //
+ // Init Attributes
+ //
+ InitializeObjectAttributes(&objAttrs,
+ &g_WinpcapGlobalKey,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+
+ //
+ // Open the key
+ //
+ status = ZwOpenKey(&keyHandle,
+ KEY_QUERY_VALUE,
+ &objAttrs);
+
+ if(!NT_SUCCESS(status))
+ {
+ IF_LOUD(DbgPrint("NPF_QueryWinpcapRegistryKey: ZwOpenKey error %x\n", status);)
+
+ //copy the default value and return
+ CharsToCopy = wcslen(DefaultValue) + 1;
+ if (CharsToCopy > ValueLen)
+ {
+ RtlCopyMemory(Value, DefaultValue, ValueLen * 2);
+ Value[ValueLen - 1] = 0;
+ }
+ else
+ {
+ RtlCopyMemory(Value, DefaultValue, CharsToCopy * 2);
+ }
+ return;
+ }
+
+ //
+ // Query the requested value
+ //
+ status = ZwQueryValueKey(keyHandle,
+ &SubKeyToQueryU,
+ KeyValuePartialInformation,
+ pKeyValuePartialInformation,
+ sizeof(kvpiBuffer),
+ &QvkResultLength);
+
+ if(!NT_SUCCESS(status))
+ {
+ IF_LOUD(DbgPrint("NPF_QueryWinpcapRegistryKey: Status of %x querying key value %ws\n",
+ status,
+ SubKeyToQueryU.Buffer);)
+
+ ZwClose(keyHandle);
+
+ //copy the default value and return
+ CharsToCopy = wcslen(DefaultValue) + 1;
+ if (CharsToCopy > ValueLen)
+ {
+ RtlCopyMemory(Value, DefaultValue, ValueLen * 2);
+ Value[ValueLen - 1] = 0;
+ }
+ else
+ {
+ RtlCopyMemory(Value, DefaultValue, CharsToCopy * 2);
+ }
+ return;
+ }
+
+ //
+ // Check that the resulting value is of the correct type
+ //
+ if (pKeyValuePartialInformation->Type != REG_SZ)
+ {
+ IF_LOUD(DbgPrint("NPF_QueryWinpcapRegistryKey: the reg key has the wrong type (%u)\n", pKeyValuePartialInformation->Type);)
+
+ ZwClose(keyHandle);
+
+ //copy the default value and return
+ CharsToCopy = wcslen(DefaultValue) + 1;
+ if (CharsToCopy > ValueLen)
+ {
+ RtlCopyMemory(Value, DefaultValue, ValueLen * 2);
+ Value[ValueLen - 1] = 0;
+ }
+ else
+ {
+ RtlCopyMemory(Value, DefaultValue, CharsToCopy * 2);
+ }
+ return;
+ }
+
+ pResultingKeyValue = (PWCHAR)pKeyValuePartialInformation->Data;
+
+ //
+ // Check we have enough space for the result. We include 1 to account for the UNICODE NULL terminator
+ //
+ if(wcslen(pResultingKeyValue) + 1 > ValueLen)
+ {
+ IF_LOUD(DbgPrint("NPF_QueryWinpcapRegistryKey: storage buffer too small\n");)
+
+ ZwClose(keyHandle);
+
+ //copy the default value and return
+ CharsToCopy = wcslen(DefaultValue) + 1;
+ if (CharsToCopy > ValueLen)
+ {
+ RtlCopyMemory(Value, DefaultValue, ValueLen * 2);
+ Value[ValueLen - 1] = 0;
+ }
+ else
+ {
+ RtlCopyMemory(Value, DefaultValue, CharsToCopy * 2);
+ }
+ return;
+ }
+
+ //
+ // Copy the value to the user-provided values
+ //
+ wcscpy(Value, pResultingKeyValue);
+
+ //
+ // Free the key
+ //
+ ZwClose(keyHandle);
+
+ return;
+
+#else // WPCAP_OEM
+
+ //copy the default value and return
+ CharsToCopy = wcslen(DefaultValue) + 1;
+ if (CharsToCopy > ValueLen)
+ {
+ RtlCopyMemory(Value, DefaultValue, ValueLen * 2);
+ Value[ValueLen - 1] = 0;
+ }
+ else
+ {
+ RtlCopyMemory(Value, DefaultValue, CharsToCopy * 2);
+ }
+ return;
+
+#endif // WPCAP_OEM
+}
+
+#endif
\ No newline at end of file
diff --git a/drivers/3rdparty/npf/Packet.h b/drivers/3rdparty/npf/Packet.h
new file mode 100644
index 0000000000000..9367a832015db
--- /dev/null
+++ b/drivers/3rdparty/npf/Packet.h
@@ -0,0 +1,941 @@
+/*
+ * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2010 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.
+ *
+ */
+
+/** @addtogroup NPF
+ * @{
+ */
+
+/** @defgroup NPF_include NPF structures and definitions
+ * @{
+ */
+
+#ifndef __PACKET_INCLUDE______
+#define __PACKET_INCLUDE______
+
+#if !defined(NDIS30) && !defined(NDIS50)
+#error NDIS30 or NDIS50 should be defined
+#endif
+
+#ifdef _X86_
+#define NTKERNEL ///< Forces the compilation of the jitter with kernel calls
+#include "jitter.h"
+#endif
+
+#ifdef HAVE_BUGGY_TME_SUPPORT
+#ifndef _X86_
+#error TME support is available only on x86 architectures
+#endif // _X86_
+#endif //HAVE_BUGGY_TME_SUPPORT
+
+
+//
+// Needed to disable a warning due to the #pragma prefast directives,
+// that are ignored by the normal DDK compiler
+//
+#ifndef _PREFAST_
+#pragma warning(disable:4068)
+#endif
+
+#include "win_bpf.h"
+
+#define MAX_REQUESTS 32 ///< Maximum number of simultaneous IOCTL requests.
+
+#define Packet_ALIGNMENT sizeof(int) ///< Alignment macro. Defines the alignment size.
+#define Packet_WORDALIGN(x) (((x)+(Packet_ALIGNMENT-1))&~(Packet_ALIGNMENT-1)) ///< Alignment macro. Rounds up to the next
+ ///< even multiple of Packet_ALIGNMENT.
+
+#define KERNEL_EVENT_NAMESPACE L"\\BaseNamedObjects\\"
+
+
+// Working modes
+#define MODE_CAPT 0x0 ///< Capture working mode
+#define MODE_STAT 0x1 ///< Statistical working mode
+#define MODE_MON 0x2 ///< Kernel monitoring mode
+#define MODE_DUMP 0x10 ///< Kernel dump working mode
+
+
+#define IMMEDIATE 1 ///< Immediate timeout. Forces a read call to return immediately.
+
+#define NDIS_FLAGS_SKIP_LOOPBACK_W2K 0x400 ///< This is an undocumented flag for NdisSetPacketFlags() that allows to disable loopback reception.
+
+// The following definitions are used to provide compatibility
+// of the dump files with the ones of libpcap
+#define TCPDUMP_MAGIC 0xa1b2c3d4 ///< Libpcap magic number. Used by programs like tcpdump to recognize a driver's generated dump file.
+#define PCAP_VERSION_MAJOR 2 ///< Major libpcap version of the dump file. Used by programs like tcpdump to recognize a driver's generated dump file.
+#define PCAP_VERSION_MINOR 4 ///< Minor libpcap version of the dump file. Used by programs like tcpdump to recognize a driver's generated dump file.
+
+// Loopback behaviour definitions
+#define NPF_DISABLE_LOOPBACK 1 ///< Tells the driver to drop the packets sent by itself. This is usefult when building applications like bridges.
+#define NPF_ENABLE_LOOPBACK 2 ///< Tells the driver to capture the packets sent by itself.
+
+/*!
+ \brief Header of a libpcap dump file.
+
+ Used when a driver instance is set in dump mode to create a libpcap-compatible file.
+*/
+struct packet_file_header
+{
+ UINT magic; ///< Libpcap magic number
+ USHORT version_major; ///< Libpcap major version
+ USHORT version_minor; ///< Libpcap minor version
+ UINT thiszone; ///< Gmt to local correction
+ UINT sigfigs; ///< Accuracy of timestamps
+ UINT snaplen; ///< Length of the max saved portion of each packet
+ UINT linktype; ///< Data link type (DLT_*). See win_bpf.h for details.
+};
+
+/*!
+ \brief Header associated to a packet in the driver's buffer when the driver is in dump mode.
+ Similar to the bpf_hdr structure, but simpler.
+*/
+struct sf_pkthdr {
+ struct timeval ts; ///< time stamp
+ UINT caplen; ///< Length of captured portion. The captured portion can be different from
+ ///< the original packet, because it is possible (with a proper filter) to
+ ///< instruct the driver to capture only a portion of the packets.
+ UINT len; ///< Length of the original packet (off wire).
+};
+
+//
+// NT4 DDK doesn't have C_ASSERT
+//
+#ifndef C_ASSERT
+#define C_ASSERT(a)
+#endif
+
+/*!
+ \brief Structure containing an OID request.
+
+ It is used by the PacketRequest() function to send an OID to the interface card driver.
+ It can be used, for example, to retrieve the status of the error counters on the adapter, its MAC address,
+ the list of the multicast groups defined on it, and so on.
+*/
+typedef struct _PACKET_OID_DATA {
+ ULONG Oid; ///< OID code. See the Microsoft DDK documentation or the file ntddndis.h
+ ///< for a complete list of valid codes.
+ ULONG Length; ///< Length of the data field
+ UCHAR Data[1]; ///< variable-lenght field that contains the information passed to or received
+ ///< from the adapter.
+}
+ PACKET_OID_DATA, *PPACKET_OID_DATA;
+
+C_ASSERT(sizeof(PACKET_OID_DATA) == 12);
+
+/*!
+ \brief Stores an OID request.
+
+ This structure is used by the driver to perform OID query or set operations on the underlying NIC driver.
+ The OID operations be performed usually only by network drivers, but NPF exports this mechanism to user-level
+ applications through an IOCTL interface. The driver uses this structure to wrap a NDIS_REQUEST structure.
+ This allows to handle correctly the callback structure of NdisRequest(), handling multiple requests and
+ maintaining information about the IRPs to complete.
+*/
+typedef struct _INTERNAL_REQUEST {
+ LIST_ENTRY ListElement; ///< Used to handle lists of requests.
+// PIRP Irp; ///< Irp that performed the request
+// BOOLEAN Internal; ///< True if the request is for internal use of npf.sys. False if the request is performed by the user through an IOCTL.
+ NDIS_EVENT InternalRequestCompletedEvent;
+ NDIS_REQUEST Request; ///< The structure with the actual request, that will be passed to NdisRequest().
+ NDIS_STATUS RequestStatus;
+
+} INTERNAL_REQUEST, *PINTERNAL_REQUEST;
+
+/*!
+ \brief Contains a NDIS packet.
+
+ The driver uses this structure to wrap a NDIS_PACKET structure.
+ This allows to handle correctly the callback structure of NdisTransferData(), handling multiple requests and
+ maintaining information about the IRPs to complete.
+*/
+typedef struct _PACKET_RESERVED {
+ LIST_ENTRY ListElement; ///< Used to handle lists of packets.
+ PIRP Irp; ///< Irp that performed the request
+ PMDL pMdl; ///< MDL mapping the buffer of the packet.
+ BOOLEAN FreeBufAfterWrite; ///< True if the memory buffer associated with the packet must be freed
+ ///< after a call to NdisSend().
+ ULONG Cpu; ///< The CPU on which the packet was pulled out of the linked list of free packets
+} PACKET_RESERVED, *PPACKET_RESERVED;
+
+#define RESERVED(_p) ((PPACKET_RESERVED)((_p)->ProtocolReserved)) ///< Macro to obtain a NDIS_PACKET from a PACKET_RESERVED
+
+/*!
+ \brief Port device extension.
+
+ Structure containing some data relative to every adapter on which NPF is bound.
+*/
+typedef struct _DEVICE_EXTENSION {
+ NDIS_STRING AdapterName; ///< Name of the adapter.
+ PWSTR ExportString; ///< Name of the exported device, i.e. name that the applications will use
+ ///< to open this adapter through WinPcap.
+} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
+
+/*!
+ \brief Kernel buffer of each CPU.
+
+ Structure containing the kernel buffer (and other CPU related fields) used to capture packets.
+*/
+typedef struct __CPU_Private_Data
+{
+ ULONG P; ///< Zero-based index of the producer in the buffer. It indicates the first free byte to be written.
+ ULONG C; ///< Zero-based index of the consumer in the buffer. It indicates the first free byte to be read.
+ ULONG Free; ///< Number of the free bytes in the buffer
+ PUCHAR Buffer; ///< Pointer to the kernel buffer used to capture packets.
+ ULONG Accepted; ///< Number of packet that current capture instance acepted, from its opening. A packet
+ ///< is accepted if it passes the filter and fits in the buffer. Accepted packets are the
+ ///< ones that reach the application.
+ ///< This number is related to the particular CPU this structure is referring to.
+ ULONG Received; ///< Number of packets received by current instance from its opening, i.e. number of
+ ///< packet received by the network adapter since the beginning of the
+ ///< capture/monitoring/dump session.
+ ///< This number is related to the particular CPU this structure is referring to.
+ ULONG Dropped; ///< Number of packet that current instance had to drop, from its opening. A packet
+ ///< is dropped if there is no more space to store it in the circular buffer that the
+ ///< driver associates to current instance.
+ ///< This number is related to the particular CPU this structure is referring to.
+ NDIS_SPIN_LOCK BufferLock; ///< It protects the buffer associated with this CPU.
+ PMDL TransferMdl1; ///< MDL used to map the portion of the buffer that will contain an incoming packet.
+ PMDL TransferMdl2; ///< Second MDL used to map the portion of the buffer that will contain an incoming packet.
+ ULONG NewP; ///< Used by NdisTransferData() (when we call NdisTransferData, p index must be updated only in the TransferDataComplete.
+}
+ CpuPrivateData;
+
+
+/*!
+ \brief Contains the state of a running instance of the NPF driver.
+
+ This is the most important structure of NPF: it is used by almost all the functions of the driver. An
+ _OPEN_INSTANCE structure is associated with every user-level session, allowing concurrent access
+ to the driver.
+*/
+typedef struct _OPEN_INSTANCE
+{
+ PDEVICE_EXTENSION DeviceExtension; ///< Pointer to the _DEVICE_EXTENSION structure of the device on which
+ ///< the instance is bound.
+ NDIS_HANDLE AdapterHandle; ///< NDIS idetifier of the adapter used by this instance.
+ UINT Medium; ///< Type of physical medium the underlying NDIS driver uses. See the
+ ///< documentation of NdisOpenAdapter in the MS DDK for details.
+ NDIS_HANDLE PacketPool; ///< Pool of NDIS_PACKET structures used to transfer the packets from and to the NIC driver.
+ KSPIN_LOCK RequestSpinLock; ///< SpinLock used to synchronize the OID requests.
+ LIST_ENTRY RequestList; ///< List of pending OID requests.
+ LIST_ENTRY ResetIrpList; ///< List of pending adapter reset requests.
+ INTERNAL_REQUEST Requests[MAX_REQUESTS]; ///< Array of structures that wrap every single OID request.
+ PMDL BufferMdl; ///< Pointer to a Memory descriptor list (MDL) that maps the circular buffer's memory.
+ PKEVENT ReadEvent; ///< Pointer to the event on which the read calls on this instance must wait.
+ PUCHAR bpfprogram; ///< Pointer to the filtering pseudo-code associated with current instance of the driver.
+ ///< This code is used only in particular situations (for example when the packet received
+ ///< from the NIC driver is stored in two non-consecutive buffers. In normal situations
+ ///< the filtering routine created by the JIT compiler and pointed by the next field
+ ///< is used. See \ref NPF for details on the filtering process.
+#ifdef _X86_
+ JIT_BPF_Filter *Filter; ///< Pointer to the native filtering function created by the jitter.
+ ///< See BPF_jitter() for details.
+#endif //_X86_
+ UINT MinToCopy; ///< Minimum amount of data in the circular buffer that unlocks a read. Set with the
+ ///< BIOCSMINTOCOPY IOCTL.
+ LARGE_INTEGER TimeOut; ///< Timeout after which a read is released, also if the amount of data in the buffer is
+ ///< less than MinToCopy. Set with the BIOCSRTIMEOUT IOCTL.
+
+ int mode; ///< Working mode of the driver. See PacketSetMode() for details.
+ LARGE_INTEGER Nbytes; ///< Amount of bytes accepted by the filter when this instance is in statistical mode.
+ LARGE_INTEGER Npackets; ///< Number of packets accepted by the filter when this instance is in statistical mode.
+ NDIS_SPIN_LOCK CountersLock; ///< SpinLock that protects the statistical mode counters.
+ UINT Nwrites; ///< Number of times a single write must be physically repeated. See \ref NPF for an
+ ///< explanation
+ ULONG Multiple_Write_Counter; ///< Counts the number of times a single write has already physically repeated.
+ NDIS_EVENT WriteEvent; ///< Event used to synchronize the multiple write process.
+ BOOLEAN WriteInProgress; ///< True if a write is currently in progress. NPF currently allows a single wite on
+ ///< the same open instance.
+ NDIS_SPIN_LOCK WriteLock; ///< SpinLock that protects the WriteInProgress variable.
+ NDIS_EVENT NdisRequestEvent; ///< Event used to synchronize I/O requests with the callback structure of NDIS.
+ BOOLEAN SkipSentPackets; ///< True if this instance should not capture back the packets that it transmits.
+ NDIS_STATUS IOStatus; ///< Maintains the status of and OID request call, that will be passed to the application.
+ HANDLE DumpFileHandle; ///< Handle of the file used in dump mode.
+ PFILE_OBJECT DumpFileObject; ///< Pointer to the object of the file used in dump mode.
+ PKTHREAD DumpThreadObject; ///< Pointer to the object of the thread used in dump mode.
+ HANDLE DumpThreadHandle; ///< Handle of the thread created by dump mode to asynchronously move the buffer to disk.
+ NDIS_EVENT DumpEvent; ///< Event used to synchronize the dump thread with the tap when the instance is in dump mode.
+ LARGE_INTEGER DumpOffset; ///< Current offset in the dump file.
+ UNICODE_STRING DumpFileName; ///< String containing the name of the dump file.
+ UINT MaxDumpBytes; ///< Maximum dimension in bytes of the dump file. If the dump file reaches this size it
+ ///< will be closed. A value of 0 means unlimited size.
+ UINT MaxDumpPacks; ///< Maximum number of packets that will be saved in the dump file. If this number of
+ ///< packets is reached the dump will be closed. A value of 0 means unlimited number of
+ ///< packets.
+ BOOLEAN DumpLimitReached; ///< TRUE if the maximum dimension of the dump file (MaxDumpBytes or MaxDumpPacks) is
+ ///< reached.
+#ifdef HAVE_BUGGY_TME_SUPPORT
+ MEM_TYPE mem_ex; ///< Memory used by the TME virtual co-processor
+ TME_CORE tme; ///< Data structure containing the virtualization of the TME co-processor
+#endif //HAVE_BUGGY_TME_SUPPORT
+
+ NDIS_SPIN_LOCK MachineLock; ///< SpinLock that protects the BPF filter and the TME engine, if in use.
+ UINT MaxFrameSize; ///< Maximum frame size that the underlying MAC acceptes. Used to perform a check on the
+ ///< size of the frames sent with NPF_Write() or NPF_BufferedWrite().
+ //
+ // KAFFINITY is used as a bit mask for the affinity in the system. So on every supported OS is big enough for all the CPUs on the system (32 bits on x86, 64 on x64?).
+ // We use its size to compute the max number of CPUs.
+ //
+ CpuPrivateData CpuData[sizeof(KAFFINITY) * 8]; ///< Pool of kernel buffer structures, one for each CPU.
+ ULONG ReaderSN; ///< Sequence number of the next packet to be read from the pool of kernel buffers.
+ ULONG WriterSN; ///< Sequence number of the next packet to be written in the pool of kernel buffers.
+ ///< These two sequence numbers are unique for each capture instance.
+ ULONG Size; ///< Size of each kernel buffer contained in the CpuData field.
+ ULONG AdapterHandleUsageCounter;
+ NDIS_SPIN_LOCK AdapterHandleLock;
+ ULONG AdapterBindingStatus; ///< Specifies if NPF is still bound to the adapter used by this instance, it's unbinding or it's not bound.
+
+ NDIS_EVENT NdisOpenCloseCompleteEvent;
+ NDIS_EVENT NdisWriteCompleteEvent; ///< Event that is signalled when all the packets have been successfully sent by NdisSend (and corresponfing sendComplete has been called)
+ NTSTATUS OpenCloseStatus;
+ ULONG TransmitPendingPackets; ///< Specifies the number of packets that are pending to be transmitted, i.e. have been submitted to NdisSendXXX but the SendComplete has not been called yet.
+ ULONG NumPendingIrps;
+ BOOLEAN ClosePending;
+ NDIS_SPIN_LOCK OpenInUseLock;
+}
+OPEN_INSTANCE, *POPEN_INSTANCE;
+
+enum ADAPTER_BINDING_STATUS
+{
+ ADAPTER_UNBOUND,
+ ADAPTER_BOUND,
+ ADAPTER_UNBINDING,
+};
+
+/*!
+ \brief Structure prepended to each packet in the kernel buffer pool.
+
+ Each packet in one of the kernel buffers is prepended by this header. It encapsulates the bpf_header,
+ which will be passed to user level programs, as well as the sequence number of the packet, set by the producer (the tap function),
+ and used by the consumer (the read function) to "reorder" the packets contained in the various kernel buffers.
+*/
+struct PacketHeader
+{
+ ULONG SN; ///< Sequence number of the packet.
+ struct bpf_hdr header; ///< bpf header, created by the tap, and copied unmodified to user level programs.
+};
+
+extern ULONG g_NCpu;
+extern NDIS_HANDLE g_NdisProtocolHandle;
+extern struct time_conv G_Start_Time; // from openclos.c
+extern UINT g_SendPacketFlags;
+
+#define TRANSMIT_PACKETS 256 ///< Maximum number of packets in the transmit packet pool. This value is an upper bound to the number
+ ///< of packets that can be transmitted at the same time or with a single call to NdisSendPackets.
+
+
+/// Macro used in the I/O routines to return the control to user-mode with a success status.
+#define EXIT_SUCCESS(quantity) Irp->IoStatus.Information=quantity;\
+ Irp->IoStatus.Status = STATUS_SUCCESS;\
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);\
+ return STATUS_SUCCESS;\
+
+/// Macro used in the I/O routines to return the control to user-mode with a failure status.
+#define EXIT_FAILURE(quantity) Irp->IoStatus.Information=quantity;\
+ Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;\
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);\
+ return STATUS_UNSUCCESSFUL;\
+
+/**
+ * @}
+ */
+
+
+/***************************/
+/* Prototypes */
+/***************************/
+
+/** @defgroup NPF_code NPF functions
+ * @{
+ */
+
+
+/*!
+ \brief The initialization routine of the driver.
+ \param DriverObject The driver object of NPF created by the system.
+ \param RegistryPath The registry path containing the keys related to the driver.
+ \return A string containing a list of network adapters.
+
+ DriverEntry is a mandatory function in a device driver. Like the main() of a user level program, it is called
+ by the system when the driver is loaded in memory and started. Its purpose is to initialize the driver,
+ performing all the allocations and the setup. In particular, DriverEntry registers all the driver's I/O
+ callbacks, creates the devices, defines NPF as a protocol inside NDIS.
+*/
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ );
+
+/*!
+ \brief Returns the list of the MACs available on the system.
+ \return A string containing a list of network adapters.
+
+ The list of adapters is retrieved from the
+ SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318} registry key.
+ NPF tries to create its bindings from this list. In this way it is possible to be loaded
+ and unloaded dynamically without passing from the control panel.
+*/
+PWCHAR getAdaptersList(VOID);
+
+/*!
+ \brief Returns the MACs that bind to TCP/IP.
+ \return Pointer to the registry key containing the list of adapters on which TCP/IP is bound.
+
+ If getAdaptersList() fails, NPF tries to obtain the TCP/IP bindings through this function.
+*/
+PKEY_VALUE_PARTIAL_INFORMATION getTcpBindings(VOID);
+
+/*!
+ \brief Creates a device for a given MAC.
+ \param adriverObjectP The driver object that will be associated with the device, i.e. the one of NPF.
+ \param amacNameP The name of the network interface that the device will point.
+ \return If the function succeeds, the return value is nonzero.
+
+ NPF creates a device for every valid network adapter. The new device points to the NPF driver, but contains
+ information about the original device. In this way, when the user opens the new device, NPF will be able to
+ determine the correct adapter to use.
+*/
+BOOLEAN NPF_CreateDevice(
+ IN OUT PDRIVER_OBJECT adriverObjectP,
+ IN PUNICODE_STRING amacNameP
+ );
+/*!
+ \brief Opens a new instance of the driver.
+ \param DeviceObject Pointer to the device object utilized by the user.
+ \param Irp Pointer to the IRP containing the user request.
+ \return The status of the operation. See ntstatus.h in the DDK.
+
+ This function is called by the OS when a new instance of the driver is opened, i.e. when a user application
+ performs a CreateFile on a device created by NPF. NPF_Open allocates and initializes variables, objects
+ and buffers needed by the new instance, fills the OPEN_INSTANCE structure associated with it and opens the
+ adapter with a call to NdisOpenAdapter.
+*/
+NTSTATUS
+NPF_Open(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ );
+
+/*!
+ \brief Ends the opening of an adapter.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+ \param Status Status of the opening operation performed by NDIS.
+ \param OpenErrorStatus not used by NPF.
+
+ Callback function associated with the NdisOpenAdapter() NDIS function. It is invoked by NDIS when the NIC
+ driver has finished an open operation that was previously started by NPF_Open().
+*/
+VOID
+NPF_OpenAdapterComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status,
+ IN NDIS_STATUS OpenErrorStatus
+ );
+
+/*!
+ \brief Closes an instance of the driver.
+ \param DeviceObject Pointer to the device object utilized by the user.
+ \param Irp Pointer to the IRP containing the user request.
+ \return The status of the operation. See ntstatus.h in the DDK.
+
+ This function is called when a running instance of the driver is closed by the user with a CloseHandle().
+ It stops the capture/monitoring/dump process, deallocates the memory and the objects associated with the
+ instance and closing the files. The network adapter is then closed with a call to NdisCloseAdapter.
+*/
+NTSTATUS
+NPF_Cleanup(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ );
+
+NTSTATUS
+NPF_Close(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ );
+
+
+
+/*!
+ \brief Ends the closing of an adapter.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+ \param Status Status of the close operation performed by NDIS.
+
+ Callback function associated with the NdisCloseAdapter() NDIS function. It is invoked by NDIS when the NIC
+ driver has finished a close operation that was previously started by NPF_Close().
+*/
+VOID
+NPF_CloseAdapterComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status
+ );
+
+/*!
+ \brief Callback invoked by NDIS when a packet arrives from the network.
+ \param ProtocolBindingContext Context of the function. Points to a OPEN_INSTANCE structure that identifies
+ the NPF instance to which the packets are destined.
+ \param MacReceiveContext Handle that identifies the underlying NIC driver that generated the request.
+ This value must be used when the packet is transferred from the NIC driver with NdisTransferData().
+ \param HeaderBuffer Pointer to the buffer in the NIC driver memory that contains the header of the packet.
+ \param HeaderBufferSize Size in bytes of the header.
+ \param LookAheadBuffer Pointer to the buffer in the NIC driver's memory that contains the incoming packet's
+ data available to NPF. This value does not necessarily coincide with the actual size of the packet,
+ since only a portion can be available at this time. The remaining portion can be obtained with the
+ NdisTransferData() NDIS function.
+ \param LookaheadBufferSize Size in bytes of the lookahead buffer.
+ \param PacketSize Total size of the incoming packet, excluded the header.
+ \return The status of the operation. See ntstatus.h in the DDK.
+
+ NPF_tap() is called by the underlying NIC for every incoming packet. It is the most important and one of
+ the most complex functions of NPF: it executes the filter, runs the statistical engine (if the instance is in
+ statistical mode), gathers the timestamp, moves the packet in the buffer. NPF_tap() is the only function,
+ along with the filtering ones, that is executed for every incoming packet, therefore it is carefully
+ optimized.
+*/
+NDIS_STATUS
+NPF_tap(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_HANDLE MacReceiveContext,
+ IN PVOID HeaderBuffer,
+ IN UINT HeaderBufferSize,
+ IN PVOID LookAheadBuffer,
+ IN UINT LookaheadBufferSize,
+ IN UINT PacketSize
+ );
+
+/*!
+ \brief Ends the transfer of a packet.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+ \param Packet Pointer to the NDIS_PACKET structure that received the packet data.
+ \param Status Status of the transfer operation.
+ \param BytesTransferred Amount of bytes transferred.
+
+ Callback function associated with the NdisTransferData() NDIS function. It is invoked by NDIS when the NIC
+ driver has finished the transfer of a packet from the NIC driver memory to the NPF circular buffer.
+*/
+VOID
+NPF_TransferDataComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN PNDIS_PACKET Packet,
+ IN NDIS_STATUS Status,
+ IN UINT BytesTransferred
+ );
+
+/*!
+ \brief Callback function that signals the end of a packet reception.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+
+ does nothing in NPF
+*/
+VOID
+NPF_ReceiveComplete(IN NDIS_HANDLE ProtocolBindingContext);
+
+/*!
+ \brief Handles the IOCTL calls.
+ \param DeviceObject Pointer to the device object utilized by the user.
+ \param Irp Pointer to the IRP containing the user request.
+ \return The status of the operation. See ntstatus.h in the DDK.
+
+ Once the packet capture driver is opened it can be configured from user-level applications with IOCTL commands
+ using the DeviceIoControl() system call. NPF_IoControl receives and serves all the IOCTL calls directed to NPF.
+ The following commands are recognized:
+ - #BIOCSETBUFFERSIZE
+ - #BIOCSETF
+ - #BIOCGSTATS
+ - #BIOCSRTIMEOUT
+ - #BIOCSMODE
+ - #BIOCSWRITEREP
+ - #BIOCSMINTOCOPY
+ - #BIOCSETOID
+ - #BIOCQUERYOID
+ - #BIOCSETDUMPFILENAME
+ - #BIOCGEVNAME
+ - #BIOCSENDPACKETSSYNC
+ - #BIOCSENDPACKETSNOSYNC
+*/
+NTSTATUS
+NPF_IoControl(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ );
+
+VOID
+
+/*!
+ \brief Ends an OID request.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+ \param pRequest Pointer to the completed OID request.
+ \param Status Status of the operation.
+
+ Callback function associated with the NdisRequest() NDIS function. It is invoked by NDIS when the NIC
+ driver has finished an OID request operation that was previously started by NPF_IoControl().
+*/
+NPF_RequestComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN PNDIS_REQUEST pRequest,
+ IN NDIS_STATUS Status
+ );
+
+/*!
+ \brief Writes a raw packet to the network.
+ \param DeviceObject Pointer to the device object on which the user wrote the packet.
+ \param Irp Pointer to the IRP containing the user request.
+ \return The status of the operation. See ntstatus.h in the DDK.
+
+ This function is called by the OS in consequence of user WriteFile() call, with the data of the packet that must
+ be sent on the net. The data is contained in the buffer associated with Irp, NPF_Write takes it and
+ delivers it to the NIC driver via the NdisSend() function. The Nwrites field of the OPEN_INSTANCE structure
+ associated with Irp indicates the number of copies of the packet that will be sent: more than one copy of the
+ packet can be sent for performance reasons.
+*/
+NTSTATUS
+NPF_Write(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ );
+
+
+/*!
+ \brief Writes a buffer of raw packets to the network.
+ \param Irp Pointer to the IRP containing the user request.
+ \param UserBuff Pointer to the buffer containing the packets to send.
+ \param UserBuffSize Size of the buffer with the packets.
+ \param sync If set to TRUE, the packets are transmitted respecting their timestamps.
+ \return The amount of bytes actually sent. If the return value is smaller than the Size parameter, an
+ error occurred during the send. The error can be caused by an adapter problem or by an
+ inconsistent/bogus user buffer.
+
+ This function is called by the OS in consequence of a BIOCSENDPACKETSNOSYNC or a BIOCSENDPACKETSSYNC IOCTL.
+ The buffer received as input parameter contains an arbitrary number of packets, each of which preceded by a
+ sf_pkthdr structure. NPF_BufferedWrite() scans the buffer and sends every packet via the NdisSend() function.
+ When Sync is set to TRUE, the packets are synchronized with the KeQueryPerformanceCounter() function.
+ This requires a remarkable amount of CPU, but allows to respect the timestamps associated with packets with a precision
+ of some microseconds (depending on the precision of the performance counter of the machine).
+ If Sync is false, the timestamps are ignored and the packets are sent as fat as possible.
+*/
+
+INT NPF_BufferedWrite(IN PIRP Irp,
+ IN PCHAR UserBuff,
+ IN ULONG UserBuffSize,
+ BOOLEAN sync);
+
+/*!
+ \brief Waits the completion of all the sends performed by NPF_BufferedWrite.
+
+ \param Open Pointer to open context structure
+
+ Used by NPF_BufferedWrite to wait the completion of all the sends before returning the control to the user.
+*/
+VOID NPF_WaitEndOfBufferedWrite(POPEN_INSTANCE Open);
+
+/*!
+ \brief Ends a send operation.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+ \param pPacket Pointer to the NDIS PACKET structure used by NPF_Write() to send the packet.
+ \param Status Status of the operation.
+
+ Callback function associated with the NdisSend() NDIS function. It is invoked by NDIS when the NIC
+ driver has finished an OID request operation that was previously started by NPF_Write().
+*/
+VOID
+NPF_SendComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN PNDIS_PACKET pPacket,
+ IN NDIS_STATUS Status
+ );
+
+/*!
+ \brief Ends a reset of the adapter.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+ \param Status Status of the operation.
+
+ Callback function associated with the NdisReset() NDIS function. It is invoked by NDIS when the NIC
+ driver has finished an OID request operation that was previously started by NPF_IoControl(), in an IOCTL_PROTOCOL_RESET
+ command.
+*/
+VOID
+NPF_ResetComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status
+ );
+
+/*!
+ \brief Callback for NDIS StatusHandler. Not used by NPF
+*/
+VOID
+NPF_Status(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status,
+ IN PVOID StatusBuffer,
+ IN UINT StatusBufferSize
+ );
+
+
+/*!
+ \brief Callback for NDIS StatusCompleteHandler. Not used by NPF
+*/
+VOID
+NPF_StatusComplete(IN NDIS_HANDLE ProtocolBindingContext);
+
+/*!
+ \brief Function called by the OS when NPF is unloaded.
+ \param DriverObject The driver object of NPF created by the system.
+
+ This is the last function executed when the driver is unloaded from the system. It frees global resources,
+ delete the devices and deregisters the protocol. The driver can be unloaded by the user stopping the NPF
+ service (from control panel or with a console 'net stop npf').
+*/
+VOID
+NPF_Unload(IN PDRIVER_OBJECT DriverObject);
+
+
+/*!
+ \brief Function that serves the user's reads.
+ \param DeviceObject Pointer to the device used by the user.
+ \param Irp Pointer to the IRP containing the user request.
+ \return The status of the operation. See ntstatus.h in the DDK.
+
+ This function is called by the OS in consequence of user ReadFile() call. It moves the data present in the
+ kernel buffer to the user buffer associated with Irp.
+ First of all, NPF_Read checks the amount of data in kernel buffer associated with current NPF instance.
+ - If the instance is in capture mode and the buffer contains more than OPEN_INSTANCE::MinToCopy bytes,
+ NPF_Read moves the data in the user buffer and returns immediatly. In this way, the read performed by the
+ user is not blocking.
+ - If the buffer contains less than MinToCopy bytes, the application's request isn't
+ satisfied immediately, but it's blocked until at least MinToCopy bytes arrive from the net
+ or the timeout on this read expires. The timeout is kept in the OPEN_INSTANCE::TimeOut field.
+ - If the instance is in statistical mode or in dump mode, the application's request is blocked until the
+ timeout kept in OPEN_INSTANCE::TimeOut expires.
+*/
+NTSTATUS
+NPF_Read(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ );
+
+/*!
+ \brief Reads the registry keys associated woth NPF if the driver is manually installed via the control panel.
+
+ Normally not used in recent versions of NPF.
+*/
+NTSTATUS
+NPF_ReadRegistry(
+ IN PWSTR *MacDriverName,
+ IN PWSTR *PacketDriverName,
+ IN PUNICODE_STRING RegistryPath
+ );
+
+/*!
+ \brief Function used by NPF_ReadRegistry() to quesry the registry keys associated woth NPF if the driver
+ is manually installed via the control panel.
+
+ Normally not used in recent versions of NPF.
+*/
+NTSTATUS
+NPF_QueryRegistryRoutine(
+ IN PWSTR ValueName,
+ IN ULONG ValueType,
+ IN PVOID ValueData,
+ IN ULONG ValueLength,
+ IN PVOID Context,
+ IN PVOID EntryContext
+ );
+
+/*!
+ \brief Callback for NDIS BindAdapterHandler. Not used by NPF.
+
+ Function called by NDIS when a new adapter is installed on the machine With Plug and Play.
+*/
+VOID NPF_BindAdapter(
+ OUT PNDIS_STATUS Status,
+ IN NDIS_HANDLE BindContext,
+ IN PNDIS_STRING DeviceName,
+ IN PVOID SystemSpecific1,
+ IN PVOID SystemSpecific2
+ );
+
+/*!
+ \brief Callback for NDIS UnbindAdapterHandler.
+ \param Status out variable filled by NPF_UnbindAdapter with the status of the unbind operation.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with current instance.
+ \param UnbindContext Specifies a handle, supplied by NDIS, that NPF can use to complete the opration.
+
+ Function called by NDIS when a new adapter is removed from the machine without shutting it down.
+ NPF_UnbindAdapter closes the adapter calling NdisCloseAdapter() and frees the memory and the structures
+ associated with it. It also releases the waiting user-level app and closes the dump thread if the instance
+ is in dump mode.
+*/
+VOID
+NPF_UnbindAdapter(
+ OUT PNDIS_STATUS Status,
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_HANDLE UnbindContext
+ );
+
+
+/*!
+ \brief Creates the file that will receive the packets when the driver is in dump mode.
+ \param Open The NPF instance that opens the file.
+ \param fileName Pointer to a UNICODE string containing the name of the file.
+ \param append Boolean value that specifies if the data must be appended to the file.
+ \return The status of the operation. See ntstatus.h in the DDK.
+*/
+NTSTATUS NPF_OpenDumpFile(POPEN_INSTANCE Open , PUNICODE_STRING fileName, BOOLEAN append);
+
+/*!
+ \brief Starts dump to file.
+ \param Open The NPF instance that opens the file.
+ \return The status of the operation. See ntstatus.h in the DDK.
+
+ This function performs two operations. First, it writes the libpcap header at the beginning of the file.
+ Second, it starts the thread that asynchronously dumps the network data to the file.
+*/
+NTSTATUS NPF_StartDump(POPEN_INSTANCE Open);
+
+/*!
+ \brief The dump thread.
+ \param Open The NPF instance that creates the thread.
+
+ This function moves the content of the NPF kernel buffer to file. It runs in the user context, so at lower
+ priority than the TAP.
+*/
+VOID NPF_DumpThread(PVOID Open);
+
+/*!
+ \brief Saves the content of the packet buffer to the file associated with current instance.
+ \param Open The NPF instance that creates the thread.
+
+ Used by NPF_DumpThread() and NPF_CloseDumpFile().
+*/
+NTSTATUS NPF_SaveCurrentBuffer(POPEN_INSTANCE Open);
+
+/*!
+ \brief Writes a block of packets on the dump file.
+ \param FileObject The file object that will receive the packets.
+ \param Offset The offset in the file where the packets will be put.
+ \param Length The amount of bytes to write.
+ \param Mdl MDL mapping the memory buffer that will be written to disk.
+ \param IoStatusBlock Used by the function to return the status of the operation.
+ \return The status of the operation. See ntstatus.h in the DDK.
+
+ NPF_WriteDumpFile addresses directly the file system, creating a custom IRP and using it to send a portion
+ of the NPF circular buffer to disk. This function is used by NPF_DumpThread().
+*/
+VOID NPF_WriteDumpFile(PFILE_OBJECT FileObject,
+ PLARGE_INTEGER Offset,
+ ULONG Length,
+ PMDL Mdl,
+ PIO_STATUS_BLOCK IoStatusBlock);
+
+
+
+/*!
+ \brief Closes the dump file associated with an instance of the driver.
+ \param Open The NPF instance that closes the file.
+ \return The status of the operation. See ntstatus.h in the DDK.
+*/
+NTSTATUS NPF_CloseDumpFile(POPEN_INSTANCE Open);
+
+BOOLEAN
+NPF_StartUsingBinding(
+ IN POPEN_INSTANCE pOpen);
+
+VOID
+NPF_StopUsingBinding(
+ IN POPEN_INSTANCE pOpen);
+
+VOID
+NPF_CloseBinding(
+ IN POPEN_INSTANCE pOpen);
+
+BOOLEAN
+NPF_StartUsingOpenInstance(
+ IN POPEN_INSTANCE pOpen);
+
+VOID
+NPF_StopUsingOpenInstance(
+ IN POPEN_INSTANCE pOpen);
+
+VOID
+NPF_CloseOpenInstance(
+ IN POPEN_INSTANCE pOpen);
+
+NTSTATUS
+NPF_GetDeviceMTU(
+ IN POPEN_INSTANCE pOpen,
+ IN PIRP pIrp,
+ OUT PUINT pMtu);
+
+/*!
+ \brief Returns the amount of bytes present in the packet buffer.
+ \param Open The NPF instance that closes the file.
+*/
+UINT GetBuffOccupation(POPEN_INSTANCE Open);
+
+/*!
+ \brief Called by NDIS to notify us of a PNP event. The most significant one for us is power state change.
+
+ \param ProtocolBindingContext Pointer to open context structure. This is NULL for global reconfig
+ events.
+ \param pNetPnPEvent Pointer to the PnP event
+
+ If there is a power state change, the driver is forced to resynchronize the global timer.
+ This hopefully avoids the synchronization issues caused by hibernation or standby.
+ This function is excluded from the NT4 driver, where PnP is not supported
+*/
+#ifdef NDIS50
+NDIS_STATUS NPF_PowerChange(IN NDIS_HANDLE ProtocolBindingContext, IN PNET_PNP_EVENT pNetPnPEvent);
+#endif
+
+//
+// Old registry based WinPcap names
+//
+///*!
+// \brief Helper function to query a value from the global WinPcap registry key
+//*/
+//VOID NPF_QueryWinpcapRegistryString(PWSTR SubKeyName,
+// WCHAR *Value,
+// UINT ValueLen,
+// WCHAR *DefaultValue);
+//
+
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+#endif /*main ifndef/define*/
\ No newline at end of file
diff --git a/drivers/3rdparty/npf/Read.c b/drivers/3rdparty/npf/Read.c
new file mode 100644
index 0000000000000..00f684523ee2f
--- /dev/null
+++ b/drivers/3rdparty/npf/Read.c
@@ -0,0 +1,1052 @@
+/*
+ * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2010 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
+#include
+
+#include "debug.h"
+#include "packet.h"
+#include "win_bpf.h"
+#include "time_calls.h"
+
+#ifdef HAVE_BUGGY_TME_SUPPORT
+#include "tme.h"
+#endif //HAVE_BUGGY_TME_SUPPORT
+
+NTSTATUS NPF_Read(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
+{
+ POPEN_INSTANCE Open;
+ PIO_STACK_LOCATION IrpSp;
+ PUCHAR packp;
+ ULONG Input_Buffer_Length;
+ UINT Thead;
+ UINT Ttail;
+ UINT TLastByte;
+ PUCHAR CurrBuff;
+ LARGE_INTEGER CapTime;
+ LARGE_INTEGER TimeFreq;
+ struct bpf_hdr *header;
+ KIRQL Irql;
+ PUCHAR UserPointer;
+ ULONG bytecopy;
+ UINT SizeToCopy;
+ UINT PktLen;
+ ULONG copied,count,current_cpu,av,plen,increment,ToCopy,available;
+ CpuPrivateData *LocalData;
+ ULONG i;
+ ULONG Occupation;
+
+ IF_LOUD(DbgPrint("NPF: Read\n");)
+
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+ Open=IrpSp->FileObject->FsContext;
+
+
+ if (NPF_StartUsingOpenInstance(Open) == FALSE)
+ {
+ //
+ // an IRP_MJ_CLEANUP was received, just fail the request
+ //
+ Irp->IoStatus.Information = 0;
+ Irp->IoStatus.Status = STATUS_CANCELLED;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ TRACE_EXIT();
+ return STATUS_CANCELLED;
+ }
+
+
+ //
+ // we need to test if the device is still bound to the Network adapter,
+ // so we perform a start/stop using binding.
+ // This is not critical, since we just want to have a quick way to have the
+ // dispatch read fail in case the adapter has been unbound
+
+ if(NPF_StartUsingBinding(Open) == FALSE)
+ {
+ NPF_StopUsingOpenInstance(Open);
+ // The Network adapter has been removed or diasabled
+ EXIT_FAILURE(0);
+ }
+ NPF_StopUsingBinding(Open);
+
+ if (Open->Size == 0)
+ {
+ NPF_StopUsingOpenInstance(Open);
+ EXIT_FAILURE(0);
+ }
+
+ if( Open->mode & MODE_DUMP && Open->DumpFileHandle == NULL ){
+ // this instance is in dump mode, but the dump file has still not been opened
+ NPF_StopUsingOpenInstance(Open);
+ EXIT_FAILURE(0);
+ }
+
+ Occupation=0;
+
+ for(i=0;iSize - Open->CpuData[i].Free);
+
+ //See if the buffer is full enough to be copied
+ if( Occupation <= Open->MinToCopy*g_NCpu || Open->mode & MODE_DUMP )
+ {
+ if (Open->ReadEvent != NULL)
+ {
+ //wait until some packets arrive or the timeout expires
+ if(Open->TimeOut.QuadPart != (LONGLONG)IMMEDIATE)
+ KeWaitForSingleObject(Open->ReadEvent,
+ UserRequest,
+ KernelMode,
+ TRUE,
+ (Open->TimeOut.QuadPart == (LONGLONG)0)? NULL: &(Open->TimeOut));
+
+ KeClearEvent(Open->ReadEvent);
+ }
+
+ if(Open->mode & MODE_STAT)
+ { //this capture instance is in statistics mode
+#ifdef NDIS50
+ CurrBuff=(PUCHAR)MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
+#else
+ CurrBuff=(PUCHAR)MmGetSystemAddressForMdl(Irp->MdlAddress);
+#endif
+
+ if (CurrBuff == NULL)
+ {
+ NPF_StopUsingOpenInstance(Open);
+ EXIT_FAILURE(0);
+ }
+
+ if (Open->mode & MODE_DUMP)
+ {
+ if (IrpSp->Parameters.Read.Length < sizeof(struct bpf_hdr) + 24)
+ {
+ NPF_StopUsingOpenInstance(Open);
+ Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+ }
+ else
+ {
+ if (IrpSp->Parameters.Read.Length < sizeof(struct bpf_hdr) + 16)
+ {
+ NPF_StopUsingOpenInstance(Open);
+ Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+ }
+
+ //fill the bpf header for this packet
+ header=(struct bpf_hdr*)CurrBuff;
+ GET_TIME(&header->bh_tstamp,&G_Start_Time);
+
+ if(Open->mode & MODE_DUMP){
+ *(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr)+16)=Open->DumpOffset.QuadPart;
+ header->bh_caplen=24;
+ header->bh_datalen=24;
+ Irp->IoStatus.Information = 24 + sizeof(struct bpf_hdr);
+ }
+ else{
+ header->bh_caplen=16;
+ header->bh_datalen=16;
+ header->bh_hdrlen=sizeof(struct bpf_hdr);
+ Irp->IoStatus.Information = 16 + sizeof(struct bpf_hdr);
+ }
+
+ *(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr))=Open->Npackets.QuadPart;
+ *(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr)+8)=Open->Nbytes.QuadPart;
+
+ //reset the countetrs
+ NdisAcquireSpinLock( &Open->CountersLock );
+ Open->Npackets.QuadPart=0;
+ Open->Nbytes.QuadPart=0;
+ NdisReleaseSpinLock( &Open->CountersLock );
+
+ NPF_StopUsingOpenInstance(Open);
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ return STATUS_SUCCESS;
+ }
+
+//
+// The MONITOR_MODE (aka TME extensions) is not supported on
+// 64 bit architectures
+//
+#ifdef HAVE_BUGGY_TME_SUPPORT
+
+ if(Open->mode==MODE_MON) //this capture instance is in monitor mode
+ {
+ PTME_DATA data;
+ ULONG cnt;
+ ULONG block_size;
+ PUCHAR tmp;
+
+#ifdef NDIS50
+ UserPointer=MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
+#else
+ UserPointer=MmGetSystemAddressForMdl(Irp->MdlAddress);
+#endif
+
+ if (UserPointer == NULL)
+ {
+ NPF_StopUsingOpenInstance(Open);
+ EXIT_FAILURE(0);
+ }
+
+ if ((!IS_VALIDATED(Open->tme.validated_blocks,Open->tme.active_read))||(IrpSp->Parameters.Read.Lengthbh_tstamp,&G_Start_Time);
+
+
+ header->bh_hdrlen=sizeof(struct bpf_hdr);
+
+
+ //moves user memory pointer
+ UserPointer+=sizeof(struct bpf_hdr);
+
+ //calculus of data to be copied
+ //if the user buffer is smaller than data to be copied,
+ //only some data will be copied
+ data=&Open->tme.block_data[Open->tme.active_read];
+
+ if (data->last_read.tv_sec!=0)
+ data->last_read=header->bh_tstamp;
+
+
+ bytecopy=data->block_size*data->filled_blocks;
+
+ if ((IrpSp->Parameters.Read.Length-sizeof(struct bpf_hdr))Parameters.Read.Length-sizeof(struct bpf_hdr))/ data->block_size;
+ else
+ bytecopy=data->filled_blocks;
+
+ tmp=data->shared_memory_base_address;
+ block_size=data->block_size;
+
+ for (cnt=0;cntMachineLock);
+ RtlCopyMemory(UserPointer,tmp,block_size);
+ NdisReleaseSpinLock(&Open->MachineLock);
+ tmp+=block_size;
+ UserPointer+=block_size;
+ }
+
+ bytecopy*=block_size;
+
+ header->bh_caplen=bytecopy;
+ header->bh_datalen=header->bh_caplen;
+
+ NPF_StopUsingOpenInstance(Open);
+ EXIT_SUCCESS(bytecopy+sizeof(struct bpf_hdr));
+ }
+
+ Occupation=0;
+
+ for(i=0;iSize - Open->CpuData[i].Free);
+
+
+ if ( Occupation == 0 || Open->mode & MODE_DUMP)
+ // The timeout has expired, but the buffer is still empty (or the packets must be written to file).
+ // We must awake the application, returning an empty buffer.
+ {
+ NPF_StopUsingOpenInstance(Open);
+ EXIT_SUCCESS(0);
+ }
+
+#else // not HAVE_BUGGY_TME_SUPPORT
+ if(Open->mode==MODE_MON) //this capture instance is in monitor mode
+ {
+ NPF_StopUsingOpenInstance(Open);
+ EXIT_FAILURE(0);
+ }
+#endif // HAVE_BUGGY_TME_SUPPORT
+
+ }
+
+
+
+//------------------------------------------------------------------------------
+ copied=0;
+ count=0;
+ current_cpu=0;
+ available = IrpSp->Parameters.Read.Length;
+#ifdef NDIS50
+ packp=(PUCHAR)MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
+#else
+ packp=(PUCHAR)MmGetSystemAddressForMdl(Irp->MdlAddress);
+#endif
+
+ if (packp == NULL)
+ {
+ NPF_StopUsingOpenInstance(Open);
+ EXIT_FAILURE(0);
+ }
+
+ if (Open->ReadEvent != NULL)
+ KeClearEvent(Open->ReadEvent);
+
+ while (count < g_NCpu) //round robin on the CPUs, if count = NCpu there are no packets left to be copied
+ {
+ if (available == copied)
+ {
+ NPF_StopUsingOpenInstance(Open);
+ EXIT_SUCCESS(copied);
+ }
+
+ LocalData = &Open->CpuData[current_cpu];
+
+ if (LocalData->Free < Open->Size)
+ { //there are some packets in the selected (aka LocalData) buffer
+ struct PacketHeader *Header = (struct PacketHeader*)(LocalData->Buffer + LocalData->C);
+
+ if ( Header->SN == Open->ReaderSN)
+ { //check if it the next one to be copied
+ plen = Header->header.bh_caplen;
+ if (plen + sizeof (struct bpf_hdr) > available - copied)
+ { //if the packet does not fit into the user buffer, we've ended copying packets
+ NPF_StopUsingOpenInstance(Open);
+ EXIT_SUCCESS(copied);
+ }
+
+// FIX_TIMESTAMPS(&Header->header.bh_tstamp);
+
+ *((struct bpf_hdr*)(&packp[copied]))=Header->header;
+
+ copied += sizeof(struct bpf_hdr);
+ LocalData->C += sizeof(struct PacketHeader);
+
+ if (LocalData->C == Open->Size)
+ LocalData->C = 0;
+
+ if (Open->Size - LocalData->C < plen)
+ {
+ //the packet is fragmented in the buffer (i.e. it skips the buffer boundary)
+ ToCopy = Open->Size - LocalData->C;
+ RtlCopyMemory(packp + copied,LocalData->Buffer + LocalData->C,ToCopy);
+ RtlCopyMemory(packp + copied + ToCopy,LocalData->Buffer,plen-ToCopy);
+ LocalData->C = plen-ToCopy;
+ }
+ else
+ {
+ //the packet is not fragmented
+ RtlCopyMemory(packp + copied ,LocalData->Buffer + LocalData->C ,plen);
+ LocalData->C += plen;
+ // if (c==size) inutile, contemplato nell "header atomico"
+ // c=0;
+ }
+
+ Open->ReaderSN++;
+ copied+=Packet_WORDALIGN(plen);
+
+ increment = plen + sizeof(struct PacketHeader);
+ if ( Open->Size - LocalData->C < sizeof(struct PacketHeader))
+ { //the next packet would be saved at the end of the buffer, but the NewHeader struct would be fragmented
+ //so the producer (--> the consumer) skips to the beginning of the buffer
+ increment += Open->Size-LocalData->C;
+ LocalData->C=0;
+ }
+ InterlockedExchangeAdd(&Open->CpuData[current_cpu].Free,increment);
+ count=0;
+ }
+ else
+ {
+ current_cpu=(current_cpu+1)%g_NCpu;
+ count++;
+ }
+
+ }
+ else
+ {
+ current_cpu=(current_cpu+1)%g_NCpu;
+ count++;
+ }
+ }
+
+ {
+ NPF_StopUsingOpenInstance(Open);
+ EXIT_SUCCESS(copied);
+ }
+
+//------------------------------------------------------------------------------
+
+}
+
+NDIS_STATUS NPF_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE MacReceiveContext,
+ IN PVOID HeaderBuffer,IN UINT HeaderBufferSize,IN PVOID LookaheadBuffer,
+ IN UINT LookaheadBufferSize,IN UINT PacketSize)
+{
+ POPEN_INSTANCE Open;
+ PNDIS_PACKET pPacket;
+ ULONG SizeToTransfer;
+ NDIS_STATUS Status;
+ UINT BytesTransfered;
+ ULONG BufferLength;
+ PMDL pMdl1,pMdl2;
+ LARGE_INTEGER CapTime;
+ LARGE_INTEGER TimeFreq;
+ UINT fres;
+ USHORT NPFHdrSize;
+
+ CpuPrivateData *LocalData;
+ ULONG Cpu;
+ struct PacketHeader *Header;
+ ULONG ToCopy;
+ ULONG increment;
+ ULONG i;
+ BOOLEAN ShouldReleaseBufferLock;
+
+ IF_VERY_LOUD(DbgPrint("NPF: tap\n");)
+ IF_VERY_LOUD(DbgPrint("HeaderBufferSize=%u, LookAheadBuffer=%p, LookaheadBufferSize=%u, PacketSize=%u\n",
+ HeaderBufferSize,
+ LookaheadBuffer,
+ LookaheadBufferSize,
+ PacketSize);)
+
+ Open= (POPEN_INSTANCE)ProtocolBindingContext;
+
+ Cpu = KeGetCurrentProcessorNumber();
+ LocalData = &Open->CpuData[Cpu];
+
+ LocalData->Received++;
+ IF_LOUD(DbgPrint("Received on CPU %d \t%d\n",Cpu,LocalData->Received);)
+// Open->Received++; // Number of packets received by filter ++
+
+
+ NdisAcquireSpinLock(&Open->MachineLock);
+
+ //
+ //Check if the lookahead buffer follows the mac header.
+ //If the data follow the header (i.e. there is only a buffer) a normal bpf_filter() is
+ //executed on the packet.
+ //Otherwise if there are 2 separate buffers (this could be the case of LAN emulation or
+ //things like this) bpf_filter_with_2_buffers() is executed.
+ //
+ if((UINT)((PUCHAR)LookaheadBuffer-(PUCHAR)HeaderBuffer) != HeaderBufferSize)
+ {
+#ifdef HAVE_BUGGY_TME_SUPPORT
+ fres=bpf_filter_with_2_buffers((struct bpf_insn*)(Open->bpfprogram),
+ HeaderBuffer,
+ LookaheadBuffer,
+ HeaderBufferSize,
+ PacketSize+HeaderBufferSize,
+ LookaheadBufferSize+HeaderBufferSize,
+ &Open->mem_ex,
+ &Open->tme,
+ &G_Start_Time);
+#else // HAVE_BUGGY_TME_SUPPORT
+ fres=bpf_filter_with_2_buffers((struct bpf_insn*)(Open->bpfprogram),
+ HeaderBuffer,
+ LookaheadBuffer,
+ HeaderBufferSize,
+ PacketSize+HeaderBufferSize,
+ LookaheadBufferSize+HeaderBufferSize);
+#endif // HAVE_BUGGY_TME_SUPPORT
+ }
+ else
+//
+// the jit filter is available on x86 (32 bit) only
+//
+#ifdef _X86_
+
+ if(Open->Filter != NULL)
+ {
+ if (Open->bpfprogram != NULL)
+ {
+ fres=Open->Filter->Function(HeaderBuffer,
+ PacketSize+HeaderBufferSize,
+ LookaheadBufferSize+HeaderBufferSize);
+ }
+ else
+ fres = -1;
+ }
+ else
+#endif //_X86_
+
+#ifdef HAVE_BUGGY_TME_SUPPORT
+ fres=bpf_filter((struct bpf_insn*)(Open->bpfprogram),
+ HeaderBuffer,
+ PacketSize+HeaderBufferSize,
+ LookaheadBufferSize+HeaderBufferSize,
+ &Open->mem_ex,
+ &Open->tme,
+ &G_Start_Time);
+#else //HAVE_BUGGY_TME_SUPPORT
+ fres=bpf_filter((struct bpf_insn*)(Open->bpfprogram),
+ HeaderBuffer,
+ PacketSize+HeaderBufferSize,
+ LookaheadBufferSize+HeaderBufferSize);
+#endif //HAVE_BUGGY_TME_SUPPORT
+
+ NdisReleaseSpinLock(&Open->MachineLock);
+
+//
+// The MONITOR_MODE (aka TME extensions) is not supported on
+// 64 bit architectures
+//
+#ifdef HAVE_BUGGY_TME_SUPPORT
+ if(Open->mode==MODE_MON)
+ // we are in monitor mode
+ {
+ if (fres==1)
+ {
+ if (Open->ReadEvent != NULL)
+ {
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+ }
+ }
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ }
+#endif //HAVE_BUGGY_TME_SUPPORT
+
+ if(fres==0)
+ {
+ // Packet not accepted by the filter, ignore it.
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+
+ //if the filter returns -1 the whole packet must be accepted
+ if(fres == -1 || fres > PacketSize+HeaderBufferSize)
+ fres = PacketSize+HeaderBufferSize;
+
+ if(Open->mode & MODE_STAT)
+ {
+ // we are in statistics mode
+ NdisAcquireSpinLock( &Open->CountersLock );
+
+ Open->Npackets.QuadPart++;
+
+ if(PacketSize+HeaderBufferSize<60)
+ Open->Nbytes.QuadPart+=60;
+ else
+ Open->Nbytes.QuadPart+=PacketSize+HeaderBufferSize;
+ // add preamble+SFD+FCS to the packet
+ // these values must be considered because are not part of the packet received from NDIS
+ Open->Nbytes.QuadPart+=12;
+
+ NdisReleaseSpinLock( &Open->CountersLock );
+
+ if(!(Open->mode & MODE_DUMP))
+ {
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+ }
+
+ if(Open->Size == 0)
+ {
+ LocalData->Dropped++;
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+
+ if(Open->mode & MODE_DUMP && Open->MaxDumpPacks)
+ {
+ ULONG Accepted=0;
+ for(i=0;iCpuData[i].Accepted;
+
+ if( Accepted > Open->MaxDumpPacks)
+ {
+ // Reached the max number of packets to save in the dump file. Discard the packet and stop the dump thread.
+ Open->DumpLimitReached = TRUE; // This stops the thread
+ // Awake the dump thread
+ NdisSetEvent(&Open->DumpEvent);
+
+ // Awake the application
+ if (Open->ReadEvent != NULL)
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+ }
+
+ //////////////////////////////COPIA.C//////////////////////////////////////////77
+
+ ShouldReleaseBufferLock = TRUE;
+ NdisDprAcquireSpinLock(&LocalData->BufferLock);
+
+ do
+ {
+
+ if (fres + sizeof(struct PacketHeader) > LocalData->Free)
+ {
+ LocalData->Dropped++;
+ break;
+ }
+
+ if (LocalData->TransferMdl1 != NULL)
+ {
+ //
+ //if TransferMdl is not NULL, there is some TransferData pending (i.e. not having called TransferDataComplete, yet)
+ //in order to avoid buffer corruption, we drop the packet
+ //
+ LocalData->Dropped++;
+ break;
+ }
+
+
+ if (LookaheadBufferSize + HeaderBufferSize >= fres)
+ {
+
+ //
+ // we do not need to call NdisTransferData, either because we need only the HeaderBuffer, or because the LookaheadBuffer
+ // contains what we need
+ //
+
+ Header = (struct PacketHeader*)(LocalData->Buffer + LocalData->P);
+ LocalData->Accepted++;
+ GET_TIME(&Header->header.bh_tstamp,&G_Start_Time);
+ Header->SN = InterlockedIncrement(&Open->WriterSN) - 1;
+
+ Header->header.bh_caplen = fres;
+ Header->header.bh_datalen = PacketSize + HeaderBufferSize;
+ Header->header.bh_hdrlen=sizeof(struct bpf_hdr);
+
+ LocalData->P +=sizeof(struct PacketHeader);
+ if (LocalData->P == Open->Size)
+ LocalData->P = 0;
+
+ if ( fres <= HeaderBufferSize || (UINT)( (PUCHAR)LookaheadBuffer - (PUCHAR)HeaderBuffer ) == HeaderBufferSize )
+ {
+ //
+ //we can consider the buffer contiguous, either because we use only the data
+ //present in the HeaderBuffer, or because HeaderBuffer and LookaheadBuffer are contiguous
+ // ;-))))))
+ //
+ if (Open->Size - LocalData->P < fres)
+ {
+ //the packet will be fragmented in the buffer (aka, it will skip the buffer boundary)
+ //two copies!!
+ ToCopy = Open->Size - LocalData->P;
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->P,HeaderBuffer, ToCopy);
+ NdisMoveMappedMemory(LocalData->Buffer + 0 , (PUCHAR)HeaderBuffer + ToCopy, fres - ToCopy);
+ LocalData->P = fres-ToCopy;
+ }
+ else
+ {
+ //the packet does not need to be fragmented in the buffer (aka, it doesn't skip the buffer boundary)
+ // ;-)))))) only ONE copy
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, HeaderBuffer, fres);
+ LocalData->P += fres;
+ }
+ }
+ else
+ {
+ //HeaderBuffer and LookAhead buffer are NOT contiguous,
+ //AND, we need some bytes from the LookaheadBuffer, too
+ if (Open->Size - LocalData->P < fres)
+ {
+ //the packet will be fragmented in the buffer (aka, it will skip the buffer boundary)
+ if (Open->Size - LocalData->P >= HeaderBufferSize)
+ {
+ //HeaderBuffer is NOT fragmented
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, HeaderBuffer, HeaderBufferSize);
+ LocalData->P += HeaderBufferSize;
+
+ if (LocalData->P == Open->Size)
+ {
+ //the fragmentation of the packet in the buffer is the same fragmentation
+ //in HeaderBuffer+LookaheadBuffer
+ LocalData->P=0;
+ NdisMoveMappedMemory(LocalData->Buffer + 0, LookaheadBuffer, fres - HeaderBufferSize);
+ LocalData->P += (fres - HeaderBufferSize);
+ }
+ else
+ {
+ //LookAheadBuffer is fragmented, two copies
+ ToCopy = Open->Size - LocalData->P;
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, LookaheadBuffer, ToCopy);
+ LocalData->P=0;
+ NdisMoveMappedMemory(LocalData->Buffer + 0, (PUCHAR)LookaheadBuffer+ ToCopy, fres - HeaderBufferSize - ToCopy);
+ LocalData->P = fres - HeaderBufferSize - ToCopy;
+ }
+ }
+ else
+ {
+ //HeaderBuffer is fragmented in the buffer (aka, it will skip the buffer boundary)
+ //two copies to copy the HeaderBuffer
+ ToCopy = Open->Size - LocalData->P;
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, HeaderBuffer, ToCopy);
+ LocalData->P = 0;
+ NdisMoveMappedMemory(LocalData->Buffer + 0, (PUCHAR)HeaderBuffer + ToCopy, HeaderBufferSize - ToCopy);
+ LocalData->P = HeaderBufferSize - ToCopy;
+
+ //only one copy to copy the LookaheadBuffer
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, LookaheadBuffer, fres- HeaderBufferSize);
+ LocalData->P += (fres - HeaderBufferSize);
+ }
+ }
+ else
+ {
+ //the packet won't be fragmented in the destination buffer (aka, it won't skip the buffer boundary)
+ //two copies, the former to copy the HeaderBuffer, the latter to copy the LookaheadBuffer
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, HeaderBuffer, HeaderBufferSize);
+ LocalData->P += HeaderBufferSize;
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, LookaheadBuffer, fres - HeaderBufferSize);
+ LocalData->P += (fres - HeaderBufferSize);
+ }
+ }
+
+ increment = fres + sizeof(struct PacketHeader);
+ if (Open->Size - LocalData->P < sizeof(struct PacketHeader)) //we check that the available, AND contiguous, space in the buffer will fit
+ { //the NewHeader structure, at least, otherwise we skip the producer
+ increment += Open->Size-LocalData->P; //at the beginning of the buffer (p = 0), and decrement the free bytes appropriately
+ LocalData->P = 0;
+ }
+
+ InterlockedExchangeAdd(&LocalData->Free, (ULONG)(-(LONG)increment));
+ if(Open->Size - LocalData->Free >= Open->MinToCopy)
+ {
+ if(Open->mode & MODE_DUMP)
+ NdisSetEvent(&Open->DumpEvent);
+ else
+ {
+ if (Open->ReadEvent != NULL)
+ {
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+ }
+ }
+ }
+
+ break;
+ }
+ else
+ {
+ IF_LOUD(DbgPrint("TransferData!!\n");)
+ //ndisTransferData required
+ LocalData->NewP = LocalData->P;
+
+ LocalData->NewP +=sizeof(struct PacketHeader);
+ if (LocalData->NewP == Open->Size)
+ LocalData->NewP = 0;
+
+ //first of all, surely the header must be copied
+ if (Open->Size-LocalData->NewP >= HeaderBufferSize)
+ {
+ //1 copy!
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->NewP, HeaderBuffer, HeaderBufferSize);
+ LocalData->NewP += HeaderBufferSize;
+ if (LocalData->NewP == Open->Size)
+ LocalData->NewP = 0;
+ }
+ else
+ {
+ ToCopy = Open->Size - LocalData->NewP;
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->NewP, HeaderBuffer, ToCopy);
+ NdisMoveMappedMemory(LocalData->Buffer + 0, (PUCHAR)HeaderBuffer + ToCopy, HeaderBufferSize - ToCopy);
+ LocalData->NewP = HeaderBufferSize - ToCopy;
+ }
+
+ //then we copy the Lookahead buffer
+
+ if (Open->Size-LocalData->NewP >= LookaheadBufferSize)
+ {
+ //1 copy!
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->NewP, LookaheadBuffer, LookaheadBufferSize);
+ LocalData->NewP += LookaheadBufferSize;
+ if (LocalData->NewP == Open->Size)
+ LocalData->NewP = 0;
+ }
+ else
+ {
+ ToCopy = Open->Size - LocalData->NewP;
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->NewP, LookaheadBuffer, ToCopy);
+ NdisMoveMappedMemory(LocalData->Buffer + 0, (PUCHAR)LookaheadBuffer + ToCopy, LookaheadBufferSize - ToCopy);
+ LocalData->NewP = LookaheadBufferSize - ToCopy;
+ }
+
+ //Now we must prepare the buffer(s) for the NdisTransferData
+ if ((Open->Size - LocalData->NewP) >= (fres - HeaderBufferSize - LookaheadBufferSize))
+ {
+ //only 1 buffer
+ pMdl1 = IoAllocateMdl(
+ LocalData->Buffer + LocalData->NewP,
+ fres - HeaderBufferSize - LookaheadBufferSize,
+ FALSE,
+ FALSE,
+ NULL);
+
+ if (pMdl1 == NULL)
+ {
+ IF_LOUD(DbgPrint("Error allocating Mdl1\n");)
+ LocalData->Dropped++;
+ break;
+ }
+
+ MmBuildMdlForNonPagedPool(pMdl1);
+ pMdl2=NULL;
+ LocalData->NewP += fres - HeaderBufferSize - LookaheadBufferSize;
+
+
+ }
+ else
+ {
+ //2 buffers
+ pMdl1 = IoAllocateMdl(
+ LocalData->Buffer + LocalData->NewP,
+ Open->Size - LocalData->NewP,
+ FALSE,
+ FALSE,
+ NULL);
+
+ if (pMdl1 == NULL)
+ {
+ IF_LOUD(DbgPrint("Error allocating Mdl1\n");)
+ LocalData->Dropped++;
+ break;
+ }
+
+ pMdl2 = IoAllocateMdl(
+ LocalData->Buffer + 0,
+ fres - HeaderBufferSize - LookaheadBufferSize - (Open->Size - LocalData->NewP),
+ FALSE,
+ FALSE,
+ NULL);
+
+ if (pMdl2 == NULL)
+ {
+ IF_LOUD(DbgPrint("Error allocating Mdl2\n");)
+ IoFreeMdl(pMdl1);
+ LocalData->Dropped++;
+ break;
+ }
+
+ LocalData->NewP = fres - HeaderBufferSize - LookaheadBufferSize - (Open->Size - LocalData->NewP);
+
+ MmBuildMdlForNonPagedPool(pMdl1);
+ MmBuildMdlForNonPagedPool(pMdl2);
+ }
+
+
+ NdisAllocatePacket(&Status, &pPacket, Open->PacketPool);
+
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ IF_LOUD(DbgPrint("NPF: Tap - No free packets\n");)
+ IoFreeMdl(pMdl1);
+ if (pMdl2 != NULL)
+ IoFreeMdl(pMdl2);
+ LocalData->Dropped++;
+ break;
+ }
+
+ if (pMdl2 != NULL)
+ NdisChainBufferAtFront(pPacket,pMdl2);
+
+ NdisChainBufferAtFront(pPacket,pMdl1);
+
+ RESERVED(pPacket)->Cpu = Cpu;
+
+ LocalData->TransferMdl1 = pMdl1;
+ LocalData->TransferMdl2 = pMdl2;
+
+
+ Header = (struct PacketHeader*)(LocalData->Buffer + LocalData->P);
+ Header->header.bh_caplen = fres;
+ Header->header.bh_datalen = PacketSize + HeaderBufferSize;
+ Header->header.bh_hdrlen=sizeof(struct bpf_hdr);
+
+ NdisTransferData(
+ &Status,
+ Open->AdapterHandle,
+ MacReceiveContext,
+ LookaheadBufferSize,
+ fres - HeaderBufferSize - LookaheadBufferSize,
+ pPacket,
+ &BytesTransfered);
+
+ if (Status != NDIS_STATUS_PENDING)
+ {
+ IF_LOUD(DbgPrint("NdisTransferData, not pending!\n");)
+ LocalData->TransferMdl1 = NULL;
+ LocalData->TransferMdl2 = NULL;
+
+ IoFreeMdl(pMdl1);
+ if ( pMdl2 != NULL )
+ IoFreeMdl(pMdl2);
+
+ NdisReinitializePacket(pPacket);
+ // Put the packet on the free queue
+ NdisFreePacket(pPacket);
+
+ LocalData->P = LocalData->NewP;
+
+ LocalData->Accepted++;
+ GET_TIME(&Header->header.bh_tstamp,&G_Start_Time);
+ Header->SN = InterlockedIncrement(&Open->WriterSN) - 1;
+
+ increment = fres + sizeof(struct PacketHeader);
+ if (Open->Size - LocalData->P < sizeof(struct PacketHeader))
+ {
+ increment += Open->Size-LocalData->P;
+ LocalData->P = 0;
+ }
+
+ InterlockedExchangeAdd(&LocalData->Free, (ULONG)(-(LONG)increment));
+
+ if(Open->Size - LocalData->Free >= Open->MinToCopy)
+ {
+ if(Open->mode & MODE_DUMP)
+ NdisSetEvent(&Open->DumpEvent);
+ else
+ {
+ if (Open->ReadEvent != NULL)
+ {
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+ }
+ }
+ }
+
+ break;
+ }
+ else
+ {
+ IF_LOUD(DbgPrint("NdisTransferData, pending!\n");)
+ ShouldReleaseBufferLock = FALSE;
+ }
+ }
+ }
+ while(FALSE);
+
+ if (ShouldReleaseBufferLock)
+ {
+ NdisDprReleaseSpinLock(&LocalData->BufferLock);
+ }
+
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+}
+
+//-------------------------------------------------------------------
+
+VOID NPF_TransferDataComplete (IN NDIS_HANDLE ProtocolBindingContext,IN PNDIS_PACKET pPacket,
+ IN NDIS_STATUS Status,IN UINT BytesTransfered)
+{
+ POPEN_INSTANCE Open;
+ ULONG Cpu;
+ CpuPrivateData *LocalData;
+ struct PacketHeader* Header;
+ ULONG increment;
+
+ IF_LOUD(DbgPrint("NPF: TransferDataComplete\n");)
+
+ Open = (POPEN_INSTANCE)ProtocolBindingContext;
+
+ Cpu = RESERVED(pPacket)->Cpu;
+
+ LocalData = &Open->CpuData[Cpu];
+
+ IoFreeMdl(LocalData->TransferMdl1);
+ if ( LocalData->TransferMdl2 != NULL )
+ IoFreeMdl(LocalData->TransferMdl2);
+
+ NdisReinitializePacket(pPacket);
+ // Put the packet on the free queue
+ NdisFreePacket(pPacket);
+
+ //the packet has been successfully copied to the kernel buffer, we can prepend it with the PacketHeader,
+ //and obtain the sequence number and the timestamp
+
+ LocalData->Accepted++;
+ Header = (struct PacketHeader*)(LocalData->Buffer + LocalData->P);
+ GET_TIME(&Header->header.bh_tstamp,&G_Start_Time);
+ Header->SN = InterlockedIncrement(&Open->WriterSN) - 1;
+
+ LocalData->P = LocalData->NewP;
+
+ increment = Header->header.bh_caplen + sizeof(struct PacketHeader);
+ if (Open->Size - LocalData->P < sizeof(struct PacketHeader))
+ {
+ increment += Open->Size-LocalData->P;
+ LocalData->P = 0;
+ }
+
+ InterlockedExchangeAdd(&LocalData->Free, (ULONG)(-(LONG)increment));
+
+ if(Open->Size - LocalData->Free >= Open->MinToCopy)
+ {
+ if(Open->mode & MODE_DUMP)
+ NdisSetEvent(&Open->DumpEvent);
+ else
+ {
+ if (Open->ReadEvent != NULL)
+ {
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+ }
+ }
+ }
+
+ LocalData->TransferMdl1 = NULL;
+ LocalData->TransferMdl2 = NULL;
+
+//
+// NOTE: this is really bad practice.
+// a better approach would be performing the entire copy here.
+//
+#pragma prefast(suppress:8107, "There's no Spinlock leak here, as it's acquired by the tap.")
+ NdisDprReleaseSpinLock(&LocalData->BufferLock);
+
+// Unfreeze the consumer
+ if(Open->Size - LocalData->Free > Open->MinToCopy)
+ {
+ if(Open->mode & MODE_DUMP)
+ NdisSetEvent(&Open->DumpEvent);
+ else
+ {
+ if (Open->ReadEvent != NULL)
+ {
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+ }
+ }
+ }
+ return;
+}
+
+//-------------------------------------------------------------------
+
+VOID NPF_ReceiveComplete(IN NDIS_HANDLE ProtocolBindingContext)
+{
+ IF_VERY_LOUD(DbgPrint("NPF: NPF_ReceiveComplete\n");)
+ return;
+}
diff --git a/drivers/3rdparty/npf/Sources b/drivers/3rdparty/npf/Sources
new file mode 100644
index 0000000000000..78de4edf0a5fd
--- /dev/null
+++ b/drivers/3rdparty/npf/Sources
@@ -0,0 +1,22 @@
+TARGETNAME=npf
+
+TARGETPATH=bin$(TARGETSUFFIX)
+
+TARGETTYPE=DRIVER
+
+TARGETLIBS=$(DDK_LIB_PATH)\ndis.lib
+
+C_DEFINES=$(C_DEFINES) -DWIN_NT_DRIVER -DWIN32_EXT $(NPF_C_DEFINES)
+
+INCLUDES=..\..\common
+
+SOURCES=packet.c \
+ openclos.c \
+ read.c \
+ write.c \
+ dump.c \
+ win_bpf_filter.c \
+ NPF.rc \
+ $(NPF_TME_FILES)
+
+I386_SOURCES = jitter.c
diff --git a/drivers/3rdparty/npf/WinPcap NTx Driver_2003.vcproj b/drivers/3rdparty/npf/WinPcap NTx Driver_2003.vcproj
new file mode 100644
index 0000000000000..88369a9aef0ad
--- /dev/null
+++ b/drivers/3rdparty/npf/WinPcap NTx Driver_2003.vcproj
@@ -0,0 +1,163 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/drivers/3rdparty/npf/Write.c b/drivers/3rdparty/npf/Write.c
new file mode 100644
index 0000000000000..6a2ad5334652f
--- /dev/null
+++ b/drivers/3rdparty/npf/Write.c
@@ -0,0 +1,635 @@
+/*
+ * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2010 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
+#include
+
+#include "debug.h"
+#include "packet.h"
+
+//-------------------------------------------------------------------
+
+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;
+
+ if (NPF_StartUsingOpenInstance(Open) == FALSE)
+ {
+ //
+ // an IRP_MJ_CLEANUP was received, just fail the request
+ //
+ Irp->IoStatus.Information = 0;
+ Irp->IoStatus.Status = STATUS_CANCELLED;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ TRACE_EXIT();
+ return STATUS_CANCELLED;
+ }
+
+ NumSends = Open->Nwrites;
+
+ //
+ // validate the send parameters set by the IOCTL
+ //
+ if (NumSends == 0)
+ {
+ NPF_StopUsingOpenInstance(Open);
+ 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");
+
+ NPF_StopUsingOpenInstance(Open);
+
+ 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");
+
+ NPF_StopUsingOpenInstance(Open);
+
+ 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.");
+
+ NPF_StopUsingOpenInstance(Open);
+
+ 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);
+
+ NPF_StopUsingOpenInstance(Open);
+
+ //
+ // 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 *pWinpcapHdr;
+ PMDL TmpMdl;
+ ULONG Pos = 0;
+// PCHAR CurPos;
+// PCHAR EndOfUserBuff = UserBuff + UserBuffSize;
+ INT result;
+
+ 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");)
+
+ //
+ // 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;
+
+ // Save the current time stamp counter
+ CurTicks = KeQueryPerformanceCounter(&TimeFreq);
+
+ //
+ // Main loop: send the buffer to the wire
+ //
+ while(TRUE)
+ {
+ if (Pos == UserBuffSize)
+ {
+ //
+ // end of buffer
+ //
+ result = Pos;
+ break;
+ }
+
+ if (UserBuffSize - Pos < sizeof(*pWinpcapHdr))
+ {
+ // Malformed header
+ IF_LOUD(DbgPrint("NPF_BufferedWrite: malformed or bogus user buffer, aborting write.\n");)
+
+ result = -1;
+ break;
+ }
+
+ pWinpcapHdr = (struct sf_pkthdr*)(UserBuff + Pos);
+
+ if(pWinpcapHdr->caplen ==0 || pWinpcapHdr->caplen > Open->MaxFrameSize)
+ {
+ // Malformed header
+ IF_LOUD(DbgPrint("NPF_BufferedWrite: malformed or bogus user buffer, aborting write.\n");)
+
+ result = -1;
+ break;
+ }
+
+ if (Pos == 0)
+ {
+ // Retrieve the time references
+ StartTicks = KeQueryPerformanceCounter(&TimeFreq);
+ BufStartTime.tv_sec = pWinpcapHdr->ts.tv_sec;
+ BufStartTime.tv_usec = pWinpcapHdr->ts.tv_usec;
+ }
+
+ Pos += sizeof(*pWinpcapHdr);
+
+ if (pWinpcapHdr->caplen > UserBuffSize - Pos)
+ {
+ //
+ // the packet is missing!!
+ //
+ IF_LOUD(DbgPrint("NPF_BufferedWrite: malformed or bogus user buffer, aborting write.\n");)
+
+ result = -1;
+ break;
+ }
+
+ // Allocate an MDL to map the packet data
+ TmpMdl = IoAllocateMdl(UserBuff + Pos,
+ pWinpcapHdr->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");)
+
+ result = -1;
+ break;
+ }
+
+ MmBuildMdlForNonPagedPool(TmpMdl); // XXX can this line be removed?
+
+ Pos += pWinpcapHdr->caplen;
+
+ // Allocate a packet from our free list
+ NdisAllocatePacket( &Status, &pPacket, Open->PacketPool);
+
+ 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 (Status != NDIS_STATUS_SUCCESS)
+ {
+ // Second failure, report an error
+ IoFreeMdl(TmpMdl);
+
+ result = -1;
+ break;
+ }
+
+ }
+
+ // 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 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
+ );
+ }
+
+ if( Sync ){
+
+ if (Pos == UserBuffSize)
+ {
+ result = Pos;
+ break;
+ }
+
+ if ((UserBuffSize - Pos) < sizeof(*pWinpcapHdr))
+ {
+ // Malformed header
+ IF_LOUD(DbgPrint("NPF_BufferedWrite: malformed or bogus user buffer, aborting write.\n");)
+
+ result = -1;
+ break;
+ }
+
+ pWinpcapHdr = (struct sf_pkthdr*)(UserBuff + Pos);
+
+ if(pWinpcapHdr->caplen ==0 || pWinpcapHdr->caplen > Open->MaxFrameSize || pWinpcapHdr->caplen > (UserBuffSize - Pos - sizeof(*pWinpcapHdr)))
+ {
+ // Malformed header
+ IF_LOUD(DbgPrint("NPF_BufferedWrite: malformed or bogus user buffer, aborting write.\n");)
+
+ result = -1;
+ break;
+ }
+
+ // Release the application if it has been blocked for approximately more than 1 seconds
+ if( pWinpcapHdr->ts.tv_sec - BufStartTime.tv_sec > 1 )
+ {
+ IF_LOUD(DbgPrint("NPF_BufferedWrite: timestamp elapsed, returning.\n");)
+
+ result = Pos;
+ break;
+ }
+
+ // Calculate the time interval to wait before sending the next packet
+ TargetTicks.QuadPart = StartTicks.QuadPart +
+ (LONGLONG)((pWinpcapHdr->ts.tv_sec - BufStartTime.tv_sec) * 1000000 +
+ pWinpcapHdr->ts.tv_usec - BufStartTime.tv_usec) *
+ (TimeFreq.QuadPart) / 1000000;
+
+ // Wait until the time interval has elapsed
+ while( CurTicks.QuadPart <= TargetTicks.QuadPart )
+ CurTicks = KeQueryPerformanceCounter(NULL);
+ }
+
+ }
+
+ // Wait the completion of pending sends
+ NPF_WaitEndOfBufferedWrite(Open);
+
+ //
+ // release ownership of the NdisAdapter binding
+ //
+ NPF_StopUsingBinding(Open);
+
+ return result;
+}
+
+//-------------------------------------------------------------------
+
+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;
+ }
+
+}
diff --git a/drivers/3rdparty/npf/bucket_lookup.c b/drivers/3rdparty/npf/bucket_lookup.c
new file mode 100644
index 0000000000000..562a8ca62aa45
--- /dev/null
+++ b/drivers/3rdparty/npf/bucket_lookup.c
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * 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 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.
+ *
+ */
+
+#ifdef WIN32
+#include "tme.h"
+#include "bucket_lookup.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include
+#include
+#else
+#include
+#include
+#endif
+
+#endif
+
+#ifndef UNUSED
+#define UNUSED(_x) (_x)
+#endif
+
+
+/* the key is represented by the initial and final value */
+/* of the bucket. At the moment bucket_lookup is able to */
+/* manage values of 16, 32 bits. */
+uint32 bucket_lookup(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref)
+{
+ uint32 value;
+ uint32 i,j;
+ int found=-1;
+ uint32 blocks;
+ uint32 block_size;
+ uint8 *temp;
+
+ UNUSED(mem_ex);
+
+ if ((data->key_len!=1)&& /*16 bit value*/
+ (data->key_len!=2)) /*32 bit value*/
+ return TME_ERROR;
+
+ /*32 bit values*/
+ blocks=data->filled_blocks-1;
+ block_size=data->block_size;
+ i=blocks/2; /*relative shift*/
+ j=i;
+ temp=data->shared_memory_base_address+block_size;
+
+ if (data->key_len==2)
+ {
+ value=SW_ULONG_AT(key,0);
+
+ if((valueSW_ULONG_AT(temp+block_size*(blocks-1),4)))
+ {
+ uint32 *key32=(uint32*) key;
+ key32[0]=key32[1]=0;
+
+ GET_TIME((struct timeval *)(data->shared_memory_base_address+8),time_ref);
+
+ data->last_found=NULL;
+ return TME_FALSE;
+ }
+
+ while(found==-1) /* search routine */
+ {
+ i=(i==1)? 1:i>>1;
+ if (SW_ULONG_AT(temp+block_size*j,0)>value)
+ if (SW_ULONG_AT(temp+block_size*(j-1),4)value)
+ found=-2;
+ else
+ j+=i;
+ else found=j;
+ }
+ if (found<0)
+ {
+ uint32 *key32=(uint32*) key;
+ key32[0]=key32[1]=0;
+
+ GET_TIME((struct timeval *)(data->shared_memory_base_address+8),time_ref);
+
+ data->last_found=NULL;
+ return TME_FALSE;
+ }
+
+ data->last_found=data->lut_base_address+found*sizeof(RECORD);
+
+ COPY_MEMORY(key,temp+block_size*found,8);
+
+ GET_TIME((struct timeval *)(temp+block_size*found+8),time_ref);
+
+ return TME_TRUE;
+ }
+ else
+ {
+ value=SW_USHORT_AT(key,0);
+
+ if((valueSW_USHORT_AT(temp+block_size*(blocks-1),2)))
+ {
+ uint16 *key16=(uint16*) key;
+ key16[0]=key16[1]=0;
+
+ GET_TIME((struct timeval *)(data->shared_memory_base_address+4),time_ref);
+
+ data->last_found=NULL;
+ return TME_FALSE;
+ }
+
+ while(found==-1) /* search routine */
+ {
+ i=(i==1)? 1:i>>1;
+ if (SW_USHORT_AT(temp+block_size*j,0)>value)
+ if (SW_USHORT_AT(temp+block_size*(j-1),2)value)
+ found=-2;
+ else
+ j+=i;
+ else found=j;
+ }
+
+ if (found<0)
+ {
+ uint16 *key16=(uint16*) key;
+ key16[0]=key16[1]=0;
+
+ GET_TIME((struct timeval *)(data->shared_memory_base_address+4),time_ref);
+
+ data->last_found=NULL;
+ return TME_FALSE;
+ }
+
+ data->last_found=data->lut_base_address+found*sizeof(RECORD);
+
+ GET_TIME((struct timeval *)(temp+block_size*found+4),time_ref);
+
+ COPY_MEMORY(key,temp+block_size*found,4);
+
+ return TME_TRUE;
+ }
+
+}
+
+uint32 bucket_lookup_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref)
+{
+ RECORD *records=(RECORD*)data->lut_base_address;
+
+ if ((data->key_len!=1)&& /*16 bit value*/
+ (data->key_len!=2)) /*32 bit value*/
+ return TME_ERROR;
+
+ if(data->key_len==2)
+ {
+ uint32 start,stop;
+ uint8 *tmp;
+
+ start=SW_ULONG_AT(key,0);
+ stop=SW_ULONG_AT(key,4);
+
+ if (start>stop)
+ return TME_ERROR;
+ if (data->filled_entries>0)
+ {
+ tmp=mem_ex->buffer+SW_ULONG_AT(&records[data->filled_entries-1].block,0);
+ /*check if it is coherent with the previous block*/
+ if (SW_ULONG_AT(tmp,4)>=start)
+ return TME_ERROR;
+ }
+
+ if (data->filled_blocks==data->shared_memory_blocks)
+ return TME_ERROR;
+
+ if (data->filled_entries==data->lut_entries)
+ return TME_ERROR;
+
+ tmp=data->shared_memory_base_address+data->block_size*data->filled_blocks;
+
+ COPY_MEMORY(tmp,key,8);
+
+ SW_ULONG_ASSIGN(&records[data->filled_entries].block,tmp-mem_ex->buffer);
+ SW_ULONG_ASSIGN(&records[data->filled_entries].exec_fcn,data->default_exec);
+
+ GET_TIME((struct timeval *)(tmp+8),time_ref);
+
+ data->filled_blocks++;
+ data->filled_entries++;
+
+ return TME_TRUE;
+ }
+ else
+ {
+ uint16 start,stop;
+ uint8 *tmp;
+
+ start=SW_USHORT_AT(key,0);
+ stop=SW_USHORT_AT(key,2);
+
+ if (start>stop)
+ return TME_ERROR;
+ if (data->filled_entries>0)
+ {
+ tmp=mem_ex->buffer+SW_ULONG_AT(&records[data->filled_entries-1].block,0);
+ /*check if it is coherent with the previous block*/
+ if (SW_USHORT_AT(tmp,2)>=start)
+ return TME_ERROR;
+ }
+
+ if (data->filled_blocks==data->shared_memory_blocks)
+ return TME_ERROR;
+
+ if (data->filled_entries==data->lut_entries)
+ return TME_ERROR;
+
+ tmp=mem_ex->buffer+SW_ULONG_AT(&records[data->filled_entries].block,0);
+
+ COPY_MEMORY(tmp,key,4);
+
+ SW_ULONG_ASSIGN(&records[data->filled_entries].block,tmp-mem_ex->buffer);
+ SW_ULONG_ASSIGN(&records[data->filled_entries].exec_fcn,data->default_exec);
+
+ GET_TIME((struct timeval *)(tmp+4),time_ref);
+
+ data->filled_blocks++;
+ data->filled_entries++;
+
+ return TME_TRUE;
+ }
+}
\ No newline at end of file
diff --git a/drivers/3rdparty/npf/bucket_lookup.h b/drivers/3rdparty/npf/bucket_lookup.h
new file mode 100644
index 0000000000000..e614e45d94cd1
--- /dev/null
+++ b/drivers/3rdparty/npf/bucket_lookup.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * 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 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.
+ *
+ */
+
+#ifndef __bucket_lookup
+#define __bucket_lookup
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include
+#else
+#include
+#endif
+
+#endif
+
+#define BUCKET_LOOKUP_INSERT 0x00000011
+uint32 bucket_lookup_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);
+#define BUCKET_LOOKUP 0x00000010
+uint32 bucket_lookup(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);
+
+#endif
\ No newline at end of file
diff --git a/drivers/3rdparty/npf/count_packets.c b/drivers/3rdparty/npf/count_packets.c
new file mode 100644
index 0000000000000..972e1bb9b7d5f
--- /dev/null
+++ b/drivers/3rdparty/npf/count_packets.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * 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 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.
+ *
+ */
+
+#ifdef WIN32
+#include "tme.h"
+#include "count_packets.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include
+#include
+#else
+#include
+#include
+#endif
+
+#endif
+
+#ifndef UNUSED
+#define UNUSED(_x) (_x)
+#endif
+
+
+uint32 count_packets(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data)
+{
+ c_p_data *counters;
+
+ UNUSED(mem_data);
+ UNUSED(mem_ex);
+
+ counters = (c_p_data*)(block+data->key_len*4);
+
+ counters->bytes+=pkt_size;
+ counters->packets++;
+
+ return TME_SUCCESS;
+
+}
diff --git a/drivers/3rdparty/npf/count_packets.h b/drivers/3rdparty/npf/count_packets.h
new file mode 100644
index 0000000000000..2cd1af59793b9
--- /dev/null
+++ b/drivers/3rdparty/npf/count_packets.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * 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 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.
+ *
+ */
+
+#ifndef __count_packets
+#define __count_packets
+
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include
+#else
+#include
+#endif
+
+#endif
+
+typedef struct __c_p_data
+{
+ struct timeval timestamp;
+ uint64 packets;
+ uint64 bytes;
+}
+ c_p_data;
+
+#define COUNT_PACKETS 0x00000000
+uint32 count_packets(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data);
+
+#endif
+
diff --git a/drivers/3rdparty/npf/dump.c b/drivers/3rdparty/npf/dump.c
new file mode 100644
index 0000000000000..b7cfe1e90088e
--- /dev/null
+++ b/drivers/3rdparty/npf/dump.c
@@ -0,0 +1,608 @@
+/*
+ * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2007 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
+#include
+
+#include "debug.h"
+#include "packet.h"
+#include "win_bpf.h"
+
+#ifdef __NPF_NT4__
+extern POBJECT_TYPE *PsThreadType;
+#endif
+
+//-------------------------------------------------------------------
+
+NTSTATUS
+NPF_OpenDumpFile(POPEN_INSTANCE Open , PUNICODE_STRING fileName, BOOLEAN Append)
+{
+ NTSTATUS ntStatus;
+ IO_STATUS_BLOCK IoStatus;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ PWCHAR PathPrefix;
+ USHORT PathLen;
+ UNICODE_STRING FullFileName;
+ ULONG FullFileNameLength;
+ PDEVICE_OBJECT fsdDevice;
+
+ FILE_STANDARD_INFORMATION StandardInfo;
+
+ IF_LOUD(DbgPrint("NPF: OpenDumpFile.\n");)
+
+ if(fileName->Buffer[0] == L'\\' &&
+ fileName->Buffer[1] == L'?' &&
+ fileName->Buffer[2] == L'?' &&
+ fileName->Buffer[3] == L'\\'
+ ){
+ PathLen = 0;
+ }
+ else{
+ PathPrefix = L"\\??\\";
+ PathLen = 8;
+ }
+
+ // Insert the correct path prefix.
+ FullFileNameLength = PathLen + fileName->MaximumLength;
+
+ FullFileName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
+ FullFileNameLength,
+ '0DWA');
+
+ if (FullFileName.Buffer == NULL) {
+ ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+ return ntStatus;
+ }
+
+ FullFileName.Length = PathLen;
+ FullFileName.MaximumLength = (USHORT)FullFileNameLength;
+
+ if(PathLen)
+ RtlMoveMemory (FullFileName.Buffer, PathPrefix, PathLen);
+
+ RtlAppendUnicodeStringToString (&FullFileName, fileName);
+
+ IF_LOUD(DbgPrint( "Packet: Attempting to open %wZ\n", &FullFileName);)
+
+ InitializeObjectAttributes ( &ObjectAttributes,
+ &FullFileName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL );
+
+ // Create the dump file
+ ntStatus = ZwCreateFile( &Open->DumpFileHandle,
+ SYNCHRONIZE | FILE_WRITE_DATA,
+ &ObjectAttributes,
+ &IoStatus,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ,
+ (Append)?FILE_OPEN_IF:FILE_SUPERSEDE,
+ FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL,
+ 0 );
+
+ if ( !NT_SUCCESS( ntStatus ) )
+ {
+ IF_LOUD(DbgPrint("NPF: Error opening file %x\n", ntStatus);)
+
+ ExFreePool(FullFileName.Buffer);
+ Open->DumpFileHandle=NULL;
+ ntStatus = STATUS_NO_SUCH_FILE;
+ return ntStatus;
+ }
+
+ ExFreePool(FullFileName.Buffer);
+
+ ntStatus = ObReferenceObjectByHandle(Open->DumpFileHandle,
+ FILE_WRITE_ACCESS,
+ *IoFileObjectType,
+ KernelMode,
+ &Open->DumpFileObject,
+ 0);
+
+ if ( !NT_SUCCESS( ntStatus ) )
+ {
+ IF_LOUD(DbgPrint("NPF: Error creating file, status=%x\n", ntStatus);)
+
+ ZwClose( Open->DumpFileHandle );
+ Open->DumpFileHandle=NULL;
+
+ ntStatus = STATUS_NO_SUCH_FILE;
+ return ntStatus;
+ }
+
+ fsdDevice = IoGetRelatedDeviceObject(Open->DumpFileObject);
+
+ IF_LOUD(DbgPrint("NPF: Dump: write file created succesfully, status=%d \n",ntStatus);)
+
+ return ntStatus;
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS
+NPF_StartDump(POPEN_INSTANCE Open)
+{
+ NTSTATUS ntStatus;
+ struct packet_file_header hdr;
+ IO_STATUS_BLOCK IoStatus;
+ NDIS_REQUEST pRequest;
+ ULONG MediaType;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+
+ IF_LOUD(DbgPrint("NPF: StartDump.\n");)
+
+ // Init the file header
+ hdr.magic = TCPDUMP_MAGIC;
+ hdr.version_major = PCAP_VERSION_MAJOR;
+ hdr.version_minor = PCAP_VERSION_MINOR;
+ hdr.thiszone = 0; /*Currently not set*/
+ hdr.snaplen = 1514;
+ hdr.sigfigs = 0;
+
+ // Detect the medium type
+ switch (Open->Medium){
+
+ case NdisMediumWan:
+ hdr.linktype = DLT_EN10MB;
+ break;
+
+ case NdisMedium802_3:
+ hdr.linktype = DLT_EN10MB;
+ break;
+
+ case NdisMediumFddi:
+ hdr.linktype = DLT_FDDI;
+ break;
+
+ case NdisMedium802_5:
+ hdr.linktype = DLT_IEEE802;
+ break;
+
+ case NdisMediumArcnet878_2:
+ hdr.linktype = DLT_ARCNET;
+ break;
+
+ case NdisMediumAtm:
+ hdr.linktype = DLT_ATM_RFC1483;
+ break;
+
+ default:
+ hdr.linktype = DLT_EN10MB;
+ }
+
+ // Write the header.
+ // We can use ZwWriteFile because we are in the context of the application
+ ntStatus = ZwWriteFile(Open->DumpFileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatus,
+ &hdr,
+ sizeof(hdr),
+ NULL,
+ NULL );
+
+
+ if ( !NT_SUCCESS( ntStatus ) )
+ {
+ IF_LOUD(DbgPrint("NPF: Error dumping file %x\n", ntStatus);)
+
+ ZwClose( Open->DumpFileHandle );
+ Open->DumpFileHandle=NULL;
+
+ ntStatus = STATUS_NO_SUCH_FILE;
+ return ntStatus;
+ }
+
+ Open->DumpOffset.QuadPart=24;
+
+ ntStatus = PsCreateSystemThread(&Open->DumpThreadHandle,
+ THREAD_ALL_ACCESS,
+ (ACCESS_MASK)0L,
+ 0,
+ 0,
+ NPF_DumpThread,
+ Open);
+
+ if ( !NT_SUCCESS( ntStatus ) )
+ {
+ IF_LOUD(DbgPrint("NPF: Error creating dump thread, status=%x\n", ntStatus);)
+
+ ZwClose( Open->DumpFileHandle );
+ Open->DumpFileHandle=NULL;
+
+ return ntStatus;
+ }
+
+ ntStatus = ObReferenceObjectByHandle(Open->DumpThreadHandle,
+ THREAD_ALL_ACCESS,
+ *PsThreadType,
+ KernelMode,
+ &Open->DumpThreadObject,
+ 0);
+
+ if ( !NT_SUCCESS( ntStatus ) )
+ {
+ IF_LOUD(DbgPrint("NPF: Error creating dump thread, status=%x\n", ntStatus);)
+
+ ObDereferenceObject(Open->DumpFileObject);
+ ZwClose( Open->DumpFileHandle );
+ Open->DumpFileHandle=NULL;
+
+ return ntStatus;
+ }
+
+
+ return ntStatus;
+
+}
+
+//-------------------------------------------------------------------
+// Dump Thread
+//-------------------------------------------------------------------
+
+VOID NPF_DumpThread(POPEN_INSTANCE Open)
+{
+ ULONG FrozenNic;
+
+ IF_LOUD(DbgPrint("NPF: In the work routine. Parameter = 0x%p\n",Open);)
+
+ while(TRUE){
+
+ // Wait until some packets arrive or the timeout expires
+ NdisWaitEvent(&Open->DumpEvent, 5000);
+
+ IF_LOUD(DbgPrint("NPF: Worker Thread - event signalled\n");)
+
+ if(Open->DumpLimitReached ||
+ Open->Size==0){ // BufSize=0 means that this instance was closed, or that the buffer is too
+ // small for any capture. In both cases it is better to end the dump
+
+ IF_LOUD(DbgPrint("NPF: Worker Thread - Exiting happily\n");)
+ IF_LOUD(DbgPrint("Thread: Dumpoffset=%I64d\n",Open->DumpOffset.QuadPart);)
+
+ PsTerminateSystemThread(STATUS_SUCCESS);
+ return;
+ }
+
+ NdisResetEvent(&Open->DumpEvent);
+
+ // Write the content of the buffer to the file
+ if(NPF_SaveCurrentBuffer(Open) != STATUS_SUCCESS){
+ PsTerminateSystemThread(STATUS_SUCCESS);
+ return;
+ }
+
+ }
+
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS NPF_SaveCurrentBuffer(POPEN_INSTANCE Open)
+{
+ UINT Thead;
+ UINT Ttail;
+ UINT TLastByte;
+ PUCHAR CurrBuff;
+ NTSTATUS ntStatus;
+ IO_STATUS_BLOCK IoStatus;
+ PMDL lMdl;
+ UINT SizeToDump;
+
+#if 0
+
+ Thead=Open->Bhead;
+ Ttail=Open->Btail;
+ TLastByte=Open->BLastByte;
+
+ IF_LOUD(DbgPrint("NPF: NPF_SaveCurrentBuffer.\n");)
+
+ // Get the address of the buffer
+ CurrBuff=Open->Buffer;
+ //
+ // Fill the application buffer
+ //
+ if( Ttail < Thead )
+ {
+ if(Open->MaxDumpBytes &&
+ (UINT)Open->DumpOffset.QuadPart /*+ GetBuffOccupation(Open)*/ > Open->MaxDumpBytes)
+ {
+ // Size limit reached
+ UINT PktLen;
+
+ SizeToDump = 0;
+
+ // Scan the buffer to detect the exact amount of data to save
+ while(TRUE){
+ PktLen = ((struct sf_pkthdr*)(CurrBuff + Thead + SizeToDump))->caplen + sizeof(struct sf_pkthdr);
+
+ if((UINT)Open->DumpOffset.QuadPart + SizeToDump + PktLen > Open->MaxDumpBytes)
+ break;
+
+ SizeToDump += PktLen;
+ }
+
+ }
+ else
+ SizeToDump = TLastByte-Thead;
+
+ lMdl=IoAllocateMdl(CurrBuff+Thead, SizeToDump, FALSE, FALSE, NULL);
+ if (lMdl == NULL)
+ {
+ // No memory: stop dump
+ IF_LOUD(DbgPrint("NPF: dump thread: Failed to allocate Mdl\n");)
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ MmBuildMdlForNonPagedPool(lMdl);
+
+ // Write to disk
+ NPF_WriteDumpFile(Open->DumpFileObject,
+ &Open->DumpOffset,
+ SizeToDump,
+ lMdl,
+ &IoStatus);
+
+ IoFreeMdl(lMdl);
+
+ if(!NT_SUCCESS(IoStatus.Status)){
+ // Error
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if(SizeToDump != TLastByte-Thead){
+ // Size limit reached.
+ Open->DumpLimitReached = TRUE;
+
+ // Awake the application
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ // Update the packet buffer
+ Open->DumpOffset.QuadPart+=(TLastByte-Thead);
+ Open->BLastByte=Ttail;
+ Open->Bhead=0;
+ }
+
+ if( Ttail > Thead ){
+
+ if(Open->MaxDumpBytes &&
+ (UINT)Open->DumpOffset.QuadPart /* +GetBuffOccupation(Open)*/ > Open->MaxDumpBytes)
+ {
+ // Size limit reached
+ UINT PktLen;
+
+ SizeToDump = 0;
+
+ // Scan the buffer to detect the exact amount of data to save
+ while(Thead + SizeToDump < Ttail){
+
+ PktLen = ((struct sf_pkthdr*)(CurrBuff + Thead + SizeToDump))->caplen + sizeof(struct sf_pkthdr);
+
+ if((UINT)Open->DumpOffset.QuadPart + SizeToDump + PktLen > Open->MaxDumpBytes)
+ break;
+
+ SizeToDump += PktLen;
+ }
+
+ }
+ else
+ SizeToDump = Ttail-Thead;
+
+ lMdl=IoAllocateMdl(CurrBuff+Thead, SizeToDump, FALSE, FALSE, NULL);
+ if (lMdl == NULL)
+ {
+ // No memory: stop dump
+ IF_LOUD(DbgPrint("NPF: dump thread: Failed to allocate Mdl\n");)
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ MmBuildMdlForNonPagedPool(lMdl);
+
+ // Write to disk
+ NPF_WriteDumpFile(Open->DumpFileObject,
+ &Open->DumpOffset,
+ SizeToDump,
+ lMdl,
+ &IoStatus);
+
+ IoFreeMdl(lMdl);
+
+ if(!NT_SUCCESS(IoStatus.Status)){
+ // Error
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if(SizeToDump != Ttail-Thead){
+ // Size limit reached.
+ Open->DumpLimitReached = TRUE;
+
+ // Awake the application
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ // Update the packet buffer
+ Open->DumpOffset.QuadPart+=(Ttail-Thead);
+ Open->Bhead=Ttail;
+
+ }
+#endif
+ return STATUS_SUCCESS;
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS NPF_CloseDumpFile(POPEN_INSTANCE Open){
+ NTSTATUS ntStatus;
+ IO_STATUS_BLOCK IoStatus;
+ PMDL WriteMdl;
+ PUCHAR VMBuff;
+ UINT VMBufLen;
+
+#if 0
+ IF_LOUD(DbgPrint("NPF: NPF_CloseDumpFile.\n");)
+ IF_LOUD(DbgPrint("Dumpoffset=%d\n",Open->DumpOffset.QuadPart);)
+
+DbgPrint("1\n");
+ // Consistency check
+ if(Open->DumpFileHandle == NULL)
+ return STATUS_UNSUCCESSFUL;
+
+DbgPrint("2\n");
+ ZwClose( Open->DumpFileHandle );
+
+ ObDereferenceObject(Open->DumpFileObject);
+/*
+ if(Open->DumpLimitReached == TRUE)
+ // Limit already reached: don't save the rest of the buffer.
+ return STATUS_SUCCESS;
+*/
+DbgPrint("3\n");
+
+ NPF_OpenDumpFile(Open,&Open->DumpFileName, TRUE);
+
+ // Flush the buffer to file
+ NPF_SaveCurrentBuffer(Open);
+
+ // Close The file
+ ObDereferenceObject(Open->DumpFileObject);
+ ZwClose( Open->DumpFileHandle );
+
+ Open->DumpFileHandle = NULL;
+
+ ObDereferenceObject(Open->DumpFileObject);
+#endif
+ return STATUS_SUCCESS;
+}
+
+//-------------------------------------------------------------------
+
+static NTSTATUS PacketDumpCompletion(PDEVICE_OBJECT DeviceObject,
+ PIRP Irp,
+ PVOID Context)
+{
+
+ //
+ // From Sebastian Gottschalk,
+ // Wednesday, May 07, 2008 4:55 PM
+ //
+ // The issue is within dump.c!PacketDumpCompletion. As an I/O completion
+ // routine it is bound to the contract that every pending IRP passed to this
+ // routine has to be marked as pending in case that is wasn't yet. Since the
+ // device returning this IRP is a filesystem device (PacketDumpCompletion is
+ // setup by WriteDumpFile), such cases might happen and would then hang the
+ // filesystem, soon hanging up then entire system.
+ //
+ // Solution: (TO BE TESTED)
+ //
+ if (Irp->PendingReturned)
+ IoMarkIrpPending(Irp);
+
+ // Copy the status information back into the "user" IOSB
+ *Irp->UserIosb = Irp->IoStatus;
+
+ // Wake up the mainline code
+ KeSetEvent(Irp->UserEvent, 0, FALSE);
+
+ return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+//-------------------------------------------------------------------
+
+VOID NPF_WriteDumpFile(PFILE_OBJECT FileObject,
+ PLARGE_INTEGER Offset,
+ ULONG Length,
+ PMDL Mdl,
+ PIO_STATUS_BLOCK IoStatusBlock)
+{
+ PIRP irp;
+ KEVENT event;
+ PIO_STACK_LOCATION ioStackLocation;
+ PDEVICE_OBJECT fsdDevice = IoGetRelatedDeviceObject(FileObject);
+ NTSTATUS Status;
+
+ // Set up the event we'll use
+ KeInitializeEvent(&event, SynchronizationEvent, FALSE);
+
+ // Allocate and build the IRP we'll be sending to the FSD
+ irp = IoAllocateIrp(fsdDevice->StackSize, FALSE);
+
+ if (!irp) {
+ // Allocation failed, presumably due to memory allocation failure
+ IoStatusBlock->Status = STATUS_INSUFFICIENT_RESOURCES;
+ IoStatusBlock->Information = 0;
+
+ return;
+ }
+
+ irp->MdlAddress = Mdl;
+ irp->UserEvent = &event;
+ irp->UserIosb = IoStatusBlock;
+ irp->Tail.Overlay.Thread = PsGetCurrentThread();
+ irp->Tail.Overlay.OriginalFileObject= FileObject;
+ irp->RequestorMode = KernelMode;
+
+ // Indicate that this is a WRITE operation
+ irp->Flags = IRP_WRITE_OPERATION;
+
+ // Set up the next I/O stack location
+ ioStackLocation = IoGetNextIrpStackLocation(irp);
+ ioStackLocation->MajorFunction = IRP_MJ_WRITE;
+ ioStackLocation->MinorFunction = 0;
+ ioStackLocation->DeviceObject = fsdDevice;
+ ioStackLocation->FileObject = FileObject;
+ IoSetCompletionRoutine(irp, PacketDumpCompletion, 0, TRUE, TRUE, TRUE);
+ ioStackLocation->Parameters.Write.Length = Length;
+ ioStackLocation->Parameters.Write.ByteOffset = *Offset;
+
+
+ // Send it on. Ignore the return code
+ (void) IoCallDriver(fsdDevice, irp);
+
+ // Wait for the I/O to complete.
+ KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, 0);
+
+ // Free the IRP now that we are done with it
+ IoFreeIrp(irp);
+
+ return;
+
+}
diff --git a/drivers/3rdparty/npf/functions.c b/drivers/3rdparty/npf/functions.c
new file mode 100644
index 0000000000000..b4d5d0f46adf2
--- /dev/null
+++ b/drivers/3rdparty/npf/functions.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1999 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * 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 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.
+ *
+ */
+
+#ifdef WIN32
+#include "tme.h"
+#include "functions.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include
+#include
+#include
+#else
+#include
+#include
+#include
+#endif
+
+#endif
+
+
+
+lut_fcn lut_fcn_mapper(uint32 index)
+{
+
+ switch (index)
+ {
+ case NORMAL_LUT_W_INSERT:
+ return (lut_fcn) normal_lut_w_insert;
+
+ case NORMAL_LUT_WO_INSERT:
+ return (lut_fcn) normal_lut_wo_insert;
+
+ case BUCKET_LOOKUP:
+ return (lut_fcn) bucket_lookup;
+
+ case BUCKET_LOOKUP_INSERT:
+ return (lut_fcn) bucket_lookup_insert;
+
+ default:
+ return NULL;
+ }
+
+}
+
+exec_fcn exec_fcn_mapper(uint32 index)
+{
+ switch (index)
+ {
+ case COUNT_PACKETS:
+ return (exec_fcn) count_packets;
+
+ case TCP_SESSION:
+ return (exec_fcn) tcp_session;
+ default:
+ return NULL;
+ }
+}
diff --git a/drivers/3rdparty/npf/functions.h b/drivers/3rdparty/npf/functions.h
new file mode 100644
index 0000000000000..3808a03bed4d2
--- /dev/null
+++ b/drivers/3rdparty/npf/functions.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 1999 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * 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 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.
+ *
+ */
+
+#ifndef __FUNCTIONS
+#define __FUNCTIONS
+
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include
+#else
+#include
+#endif
+
+#endif
+/*function mappers */
+
+lut_fcn lut_fcn_mapper(uint32 index);
+exec_fcn exec_fcn_mapper(uint32 index);
+
+/* lookup functions */
+
+#ifdef WIN32
+#include "bucket_lookup.h"
+#include "normal_lookup.h"
+#endif
+
+#ifdef __FreeBSD__
+#include
+#include
+#endif
+
+/* execution functions */
+
+#ifdef WIN32
+#include "count_packets.h"
+#include "tcp_session.h"
+#endif
+
+#ifdef __FreeBSD__
+#include
+#include
+#endif
+
+#endif
\ No newline at end of file
diff --git a/drivers/3rdparty/npf/ioctls.h b/drivers/3rdparty/npf/ioctls.h
new file mode 100644
index 0000000000000..88ccf270d0732
--- /dev/null
+++ b/drivers/3rdparty/npf/ioctls.h
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2007 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 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.
+ *
+ */
+
+#ifndef __NPF_IOCTLS_H__
+#define __NPF_IOCTLS_H__
+
+/***************************/
+/* IOCTLs */
+/***************************/
+
+/** @addtogroup NPF
+ * @{
+ */
+
+/** @defgroup NPF_ioctl NPF I/O control codes
+ * @{
+ */
+
+/*!
+ \brief IOCTL code: set kernel buffer size.
+
+ This IOCTL is used to set a new size of the circular buffer associated with an instance of NPF.
+ When a BIOCSETBUFFERSIZE command is received, the driver frees the old buffer, allocates the new one
+ and resets all the parameters associated with the buffer in the OPEN_INSTANCE structure. The currently
+ buffered packets are lost.
+*/
+#define BIOCSETBUFFERSIZE 9592
+
+/*!
+ \brief IOCTL code: set packet filtering program.
+
+ This IOCTL sets a new packet filter in the driver. Before allocating any memory for the new filter, the
+ bpf_validate() function is called to check the correctness of the filter. If this function returns TRUE,
+ the filter is copied to the driver's memory, its address is stored in the bpfprogram field of the
+ OPEN_INSTANCE structure associated with current instance of the driver, and the filter will be applied to
+ every incoming packet. This command also empties the circular buffer used by current instance
+ to store packets. This is done to avoid the presence in the buffer of packets that do not match the filter.
+*/
+#define BIOCSETF 9030
+
+/*!
+ \brief IOCTL code: get the capture stats
+
+ This command returns to the application the number of packets received and the number of packets dropped by
+ an instance of the driver.
+*/
+#define BIOCGSTATS 9031
+
+/*!
+ \brief IOCTL code: set the read timeout
+
+ This command sets the maximum timeout after which a read is released, also if no data packets were received.
+*/
+#define BIOCSRTIMEOUT 7416
+
+/*!
+ \brief IOCTL code: set working mode
+
+ This IOCTL can be used to set the working mode of a NPF instance. The new mode, received by the driver in the
+ buffer associated with the IOCTL command, can be #MODE_CAPT for capture mode (the default), #MODE_STAT for
+ statistical mode or #MODE_DUMP for dump mode.
+*/
+#define BIOCSMODE 7412
+
+/*!
+ \brief IOCTL code: set number of physical repetions of every packet written by the app
+
+ Sets the number of times a single write call must be repeated. This command sets the OPEN_INSTANCE::Nwrites
+ member, and is used to implement the 'multiple write' feature of the driver.
+*/
+#define BIOCSWRITEREP 7413
+
+/*!
+ \brief IOCTL code: set minimum amount of data in the kernel buffer that unlocks a read call
+
+ This command sets the OPEN_INSTANCE::MinToCopy member.
+*/
+#define BIOCSMINTOCOPY 7414
+
+/*!
+ \brief IOCTL code: set an OID value
+
+ This IOCTL is used to perform an OID set operation on the NIC driver.
+*/
+#define BIOCSETOID 0x80000000
+
+/*!
+ \brief IOCTL code: get an OID value
+
+ This IOCTL is used to perform an OID get operation on the NIC driver.
+*/
+#define BIOCQUERYOID 0x80000004
+
+/*!
+ \brief IOCTL code: set the name of a the file used by kernel dump mode
+
+ This command opens a file whose name is contained in the IOCTL buffer and associates it with current NPf instance.
+ The dump thread uses it to copy the content of the circular buffer to file.
+ If a file was already opened, the driver closes it before opening the new one.
+*/
+#define BIOCSETDUMPFILENAME 9029
+
+/*!
+ \brief IOCTL code: get the name of the event that the driver signals when some data is present in the buffer
+
+ Command used by the application to retrieve the name of the global event associated with a NPF instance.
+ The event is signaled by the driver when the kernel buffer contains enough data for a transfer.
+*/
+#define BIOCGEVNAME 7415
+
+/*!
+ \brief IOCTL code: Send a buffer containing multiple packets to the network, ignoring the timestamps.
+
+ Command used to send a buffer of packets in a single system call. Every packet in the buffer is preceded by
+ a sf_pkthdr structure. The timestamps of the packets are ignored, i.e. the packets are sent as fast as
+ possible. The NPF_BufferedWrite() function is invoked to send the packets.
+*/
+#define BIOCSENDPACKETSNOSYNC 9032
+
+/*!
+ \brief IOCTL code: Send a buffer containing multiple packets to the network, considering the timestamps.
+
+ Command used to send a buffer of packets in a single system call. Every packet in the buffer is preceded by
+ a sf_pkthdr structure. The timestamps of the packets are used to synchronize the write, i.e. the packets
+ are sent to the network respecting the intervals specified in the sf_pkthdr structure assiciated with each
+ packet. NPF_BufferedWrite() function is invoked to send the packets.
+*/
+#define BIOCSENDPACKETSSYNC 9033
+
+/*!
+ \brief IOCTL code: Set the dump file limits.
+
+ This IOCTL sets the limits (maximum size and maximum number of packets) of the dump file created when the
+ driver works in dump mode.
+*/
+#define BIOCSETDUMPLIMITS 9034
+
+/*!
+ \brief IOCTL code: Get the status of the kernel dump process.
+
+ This command returns TRUE if the kernel dump is ended, i.e if one of the limits set with BIOCSETDUMPLIMITS
+ (amount of bytes or number of packets) has been reached.
+*/
+#define BIOCISDUMPENDED 7411
+
+/*!
+ \brief IOCTL code: set the loopback behavior.
+
+ This IOCTL sets the loopback behavior of the driver with packets sent by itself: capture or drop.
+*/
+#define BIOCISETLOBBEH 7410
+
+/*!
+ \brief This IOCTL passes the read event HANDLE allocated by the user (packet.dll) to kernel level
+
+ Parameter: HANDLE
+ Parameter size: sizeof(HANDLE). If the caller is 32 bit, the parameter size is 4 bytes, even if sizeof(HANDLE) at kernel level
+ is 8 bytes. That's why in this IOCTL code handler we detect a 32bit calling process and do the necessary thunking.
+
+ TODO GV:I will go to hell for this ugly IOCTL definition. We should use CTL_CODE!!
+*/
+#define BIOCSETEVENTHANDLE 7920
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
+
+
+
+
+#endif //__NPF_IOCTLS_H__
diff --git a/drivers/3rdparty/npf/jitter.c b/drivers/3rdparty/npf/jitter.c
new file mode 100644
index 0000000000000..b8e1fafeb4e35
--- /dev/null
+++ b/drivers/3rdparty/npf/jitter.c
@@ -0,0 +1,692 @@
+/*
+ * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2007 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 "packet.h"
+#include "win_bpf.h"
+
+//
+// emit routine to update the jump table
+//
+void emit_lenght(binary_stream *stream, ULONG value, UINT len)
+{
+ (stream->refs)[stream->bpf_pc]+=len;
+ stream->cur_ip+=len;
+}
+
+//
+// emit routine to output the actual binary code
+//
+void emit_code(binary_stream *stream, ULONG value, UINT len)
+{
+
+ switch (len){
+
+ case 1:
+ stream->ibuf[stream->cur_ip]=(UCHAR)value;
+ stream->cur_ip++;
+ break;
+
+ case 2:
+ *((USHORT*)(stream->ibuf+stream->cur_ip))=(USHORT)value;
+ stream->cur_ip+=2;
+ break;
+
+ case 4:
+ *((ULONG*)(stream->ibuf+stream->cur_ip))=value;
+ stream->cur_ip+=4;
+ break;
+
+ default:;
+
+ }
+
+ return;
+
+}
+
+//
+// Function that does the real stuff
+//
+BPF_filter_function BPFtoX86(struct bpf_insn *prog, UINT nins, INT *mem)
+{
+ struct bpf_insn *ins;
+ UINT i, pass;
+ binary_stream stream;
+
+ //NOTE: do not modify the name of this variable, as it's used by the macros to emit code.
+ emit_func emitm;
+
+
+ // Allocate the reference table for the jumps
+#ifdef NTKERNEL
+ stream.refs=(UINT *)ExAllocatePoolWithTag(NonPagedPool, (nins + 1)*sizeof(UINT), '0JWA');
+#else
+ stream.refs=(UINT *)malloc((nins + 1)*sizeof(UINT));
+#endif
+ if(stream.refs==NULL)
+ {
+ return NULL;
+ }
+
+ // Reset the reference table
+ for(i=0; i< nins + 1; i++)
+ stream.refs[i]=0;
+
+ stream.cur_ip=0;
+ stream.bpf_pc=0;
+
+ // the first pass will emit the lengths of the instructions
+ // to create the reference table
+ emitm=emit_lenght;
+
+ for(pass=0;;){
+
+ ins = prog;
+
+ /* create the procedure header */
+ PUSH(EBP)
+ MOVrd(EBP,ESP)
+ PUSH(EBX)
+ PUSH(ECX)
+ PUSH(EDX)
+ PUSH(ESI)
+ PUSH(EDI)
+ MOVodd(EBX, EBP, 8)
+
+ for(i=0;icode) {
+
+ default:
+
+ return NULL;
+
+ case BPF_RET|BPF_K:
+
+ MOVid(EAX,ins->k)
+ POP(EDI)
+ POP(ESI)
+ POP(EDX)
+ POP(ECX)
+ POP(EBX)
+ POP(EBP)
+ RET()
+
+ break;
+
+
+ case BPF_RET|BPF_A:
+
+ POP(EDI)
+ POP(ESI)
+ POP(EDX)
+ POP(ECX)
+ POP(EBX)
+ POP(EBP)
+ RET()
+
+ break;
+
+
+ case BPF_LD|BPF_W|BPF_ABS:
+
+ MOVid(ECX,ins->k)
+ CMPodd(ECX, EBP, 0x10)
+ JAb(10)
+ MOVrd(ESI,ECX)
+ ADDib(ECX,sizeof(INT))
+ CMPodd(ECX, EBP, 0x10)
+ JBEb(12)
+ POP(EDI)
+ POP(ESI)
+ POP(EDX)
+ POP(ECX)
+ POP(EBX)
+ POP(EBP)
+ MOVid(EAX,0) //this can be optimized with xor eax,eax
+ RET()
+ MOVobd(EAX, EBX, ESI)
+ BSWAP(EAX)
+
+ break;
+
+ case BPF_LD|BPF_H|BPF_ABS:
+
+ MOVid(ECX,ins->k)
+ CMPodd(ECX, EBP, 0x10)
+ JAb(10)
+ MOVrd(ESI,ECX)
+ ADDib(ECX,sizeof(SHORT))
+ CMPodd(ECX, EBP, 0x10)
+ JBEb(12)
+ POP(EDI)
+ POP(ESI)
+ POP(EDX)
+ POP(ECX)
+ POP(EBX)
+ POP(EBP)
+ MOVid(EAX,0)
+ RET()
+ MOVid(EAX,0)
+ MOVobw(AX, EBX, ESI)
+ SWAP_AX()
+
+ break;
+
+ case BPF_LD|BPF_B|BPF_ABS:
+
+ MOVid(ECX,ins->k)
+ CMPodd(ECX, EBP, 0x10)
+ JBb(12)
+ POP(EDI)
+ POP(ESI)
+ POP(EDX)
+ POP(ECX)
+ POP(EBX)
+ POP(EBP)
+ MOVid(EAX,0)
+ RET()
+ MOVid(EAX,0)
+ MOVobb(AL,EBX,ECX)
+
+ break;
+
+ case BPF_LD|BPF_W|BPF_LEN:
+
+ MOVodd(EAX, EBP, 0xc)
+
+ break;
+
+ case BPF_LDX|BPF_W|BPF_LEN:
+
+ MOVodd(EDX, EBP, 0xc)
+
+ break;
+
+ case BPF_LD|BPF_W|BPF_IND:
+
+ MOVid(ECX,ins->k)
+ ADDrd(ECX,EDX)
+ CMPodd(ECX, EBP, 0x10)
+ JAb(10)
+ MOVrd(ESI,ECX)
+ ADDib(ECX,sizeof(INT))
+ CMPodd(ECX, EBP, 0x10)
+ JBEb(12)
+ POP(EDI)
+ POP(ESI)
+ POP(EDX)
+ POP(ECX)
+ POP(EBX)
+ POP(EBP)
+ MOVid(EAX,0)
+ RET()
+ MOVobd(EAX, EBX, ESI)
+ BSWAP(EAX)
+
+ break;
+
+ case BPF_LD|BPF_H|BPF_IND:
+
+ MOVid(ECX,ins->k)
+ ADDrd(ECX,EDX)
+ CMPodd(ECX, EBP, 0x10)
+ JAb(10)
+ MOVrd(ESI,ECX)
+ ADDib(ECX,sizeof(SHORT))
+ CMPodd(ECX, EBP, 0x10)
+ JBEb(12)
+ POP(EDI)
+ POP(ESI)
+ POP(EDX)
+ POP(ECX)
+ POP(EBX)
+ POP(EBP)
+ MOVid(EAX,0)
+ RET()
+ MOVid(EAX,0)
+ MOVobw(AX, EBX, ESI)
+ SWAP_AX()
+
+ break;
+
+ case BPF_LD|BPF_B|BPF_IND:
+
+ MOVid(ECX,ins->k)
+ ADDrd(ECX,EDX)
+ CMPodd(ECX, EBP, 0x10)
+ JBb(12)
+ POP(EDI)
+ POP(ESI)
+ POP(EDX)
+ POP(ECX)
+ POP(EBX)
+ POP(EBP)
+ MOVid(EAX,0)
+ RET()
+ MOVid(EAX,0)
+ MOVobb(AL,EBX,ECX)
+
+ break;
+
+ case BPF_LDX|BPF_MSH|BPF_B:
+
+ MOVid(ECX,ins->k)
+ CMPodd(ECX, EBP, 0x10)
+ JBb(12)
+ POP(EDI)
+ POP(ESI)
+ POP(EDX)
+ POP(ECX)
+ POP(EBX)
+ POP(EBP)
+ MOVid(EAX,0)
+ RET()
+ MOVid(EDX,0)
+ MOVobb(DL,EBX,ECX)
+ ANDib(DL, 0xf)
+ SHLib(EDX, 2)
+
+ break;
+
+ case BPF_LD|BPF_IMM:
+
+ MOVid(EAX,ins->k)
+
+ break;
+
+ case BPF_LDX|BPF_IMM:
+
+ MOVid(EDX,ins->k)
+
+ break;
+
+ case BPF_LD|BPF_MEM:
+
+ MOVid(ECX,(INT)mem)
+ MOVid(ESI,ins->k*4)
+ MOVobd(EAX, ECX, ESI)
+
+ break;
+
+ case BPF_LDX|BPF_MEM:
+
+ MOVid(ECX,(INT)mem)
+ MOVid(ESI,ins->k*4)
+ MOVobd(EDX, ECX, ESI)
+
+ break;
+
+ case BPF_ST:
+
+ // XXX: this command and the following could be optimized if the previous
+ // instruction was already of this type
+ MOVid(ECX,(INT)mem)
+ MOVid(ESI,ins->k*4)
+ MOVomd(ECX, ESI, EAX)
+
+ break;
+
+ case BPF_STX:
+
+ MOVid(ECX,(INT)mem)
+ MOVid(ESI,ins->k*4)
+ MOVomd(ECX, ESI, EDX)
+ break;
+
+ case BPF_JMP|BPF_JA:
+
+ JMP(stream.refs[stream.bpf_pc+ins->k]-stream.refs[stream.bpf_pc])
+
+ break;
+
+ case BPF_JMP|BPF_JGT|BPF_K:
+
+ CMPid(EAX, ins->k)
+ JG(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5) // 5 is the size of the following JMP
+ JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
+ break;
+
+ case BPF_JMP|BPF_JGE|BPF_K:
+
+ CMPid(EAX, ins->k)
+ JGE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
+ JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
+
+ break;
+
+ case BPF_JMP|BPF_JEQ|BPF_K:
+
+ CMPid(EAX, ins->k)
+ JE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
+ JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
+
+ break;
+
+ case BPF_JMP|BPF_JSET|BPF_K:
+
+ MOVrd(ECX,EAX)
+ ANDid(ECX,ins->k)
+ JE(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]+5)
+ JMP(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc])
+
+ break;
+
+ case BPF_JMP|BPF_JGT|BPF_X:
+
+ CMPrd(EAX, EDX)
+ JA(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
+ JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
+ break;
+
+ case BPF_JMP|BPF_JGE|BPF_X:
+
+ CMPrd(EAX, EDX)
+ JAE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
+ JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
+
+ break;
+
+ case BPF_JMP|BPF_JEQ|BPF_X:
+
+ CMPrd(EAX, EDX)
+ JE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
+ JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
+
+ break;
+
+ case BPF_JMP|BPF_JSET|BPF_X:
+
+ MOVrd(ECX,EAX)
+ ANDrd(ECX,EDX)
+ JE(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]+5)
+ JMP(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc])
+
+ break;
+
+ case BPF_ALU|BPF_ADD|BPF_X:
+
+ ADDrd(EAX,EDX)
+
+ break;
+
+ case BPF_ALU|BPF_SUB|BPF_X:
+
+ SUBrd(EAX,EDX)
+
+ break;
+
+ case BPF_ALU|BPF_MUL|BPF_X:
+
+ MOVrd(ECX,EDX)
+ MULrd(EDX)
+ MOVrd(EDX,ECX)
+ break;
+
+ case BPF_ALU|BPF_DIV|BPF_X:
+
+ CMPid(EDX, 0)
+ JNEb(12)
+ POP(EDI)
+ POP(ESI)
+ POP(EDX)
+ POP(ECX)
+ POP(EBX)
+ POP(EBP)
+ MOVid(EAX,0)
+ RET()
+ MOVrd(ECX,EDX)
+ MOVid(EDX,0)
+ DIVrd(ECX)
+ MOVrd(EDX,ECX)
+
+ break;
+
+ case BPF_ALU|BPF_AND|BPF_X:
+
+ ANDrd(EAX,EDX)
+
+ break;
+
+ case BPF_ALU|BPF_OR|BPF_X:
+
+ ORrd(EAX,EDX)
+
+ break;
+
+ case BPF_ALU|BPF_LSH|BPF_X:
+
+ MOVrd(ECX,EDX)
+ SHL_CLrb(EAX)
+
+ break;
+
+ case BPF_ALU|BPF_RSH|BPF_X:
+
+ MOVrd(ECX,EDX)
+ SHR_CLrb(EAX)
+
+ break;
+
+ case BPF_ALU|BPF_ADD|BPF_K:
+
+ ADD_EAXi(ins->k)
+
+ break;
+
+ case BPF_ALU|BPF_SUB|BPF_K:
+
+ SUB_EAXi(ins->k)
+
+ break;
+
+ case BPF_ALU|BPF_MUL|BPF_K:
+
+ MOVrd(ECX,EDX)
+ MOVid(EDX,ins->k)
+ MULrd(EDX)
+ MOVrd(EDX,ECX)
+
+ break;
+
+ case BPF_ALU|BPF_DIV|BPF_K:
+
+ MOVrd(ECX,EDX)
+ MOVid(EDX,0)
+ MOVid(ESI,ins->k)
+ DIVrd(ESI)
+ MOVrd(EDX,ECX)
+
+ break;
+
+ case BPF_ALU|BPF_AND|BPF_K:
+
+ ANDid(EAX, ins->k)
+
+ break;
+
+ case BPF_ALU|BPF_OR|BPF_K:
+
+ ORid(EAX, ins->k)
+
+ break;
+
+ case BPF_ALU|BPF_LSH|BPF_K:
+
+ SHLib(EAX, (ins->k) & 255)
+
+ break;
+
+ case BPF_ALU|BPF_RSH|BPF_K:
+
+ SHRib(EAX, (ins->k) & 255)
+
+ break;
+
+ case BPF_ALU|BPF_NEG:
+
+ NEGd(EAX)
+
+ break;
+
+ case BPF_MISC|BPF_TAX:
+
+ MOVrd(EDX,EAX)
+
+ break;
+
+ case BPF_MISC|BPF_TXA:
+
+ MOVrd(EAX,EDX)
+
+ break;
+
+
+
+ }
+
+ ins++;
+ }
+
+ pass++;
+ if(pass == 2) break;
+
+#ifdef NTKERNEL
+ stream.ibuf=(CHAR*)ExAllocatePoolWithTag(NonPagedPool, stream.cur_ip, '1JWA');
+#else
+ stream.ibuf=(CHAR*)malloc(stream.cur_ip);
+#endif
+ if(stream.ibuf==NULL)
+ {
+#ifdef NTKERNEL
+ ExFreePool(stream.refs);
+#else
+ free(stream.refs);
+#endif
+ return NULL;
+ }
+
+ // modify the reference table to contain the offsets and not the lengths of the instructions
+ for(i=1; i< nins + 1; i++)
+ stream.refs[i]+=stream.refs[i-1];
+
+ // Reset the counters
+ stream.cur_ip=0;
+ stream.bpf_pc=0;
+ // the second pass creates the actual code
+ emitm=emit_code;
+
+ }
+
+ // the reference table is needed only during compilation, now we can free it
+#ifdef NTKERNEL
+ ExFreePool(stream.refs);
+#else
+ free(stream.refs);
+#endif
+ return (BPF_filter_function)stream.ibuf;
+
+}
+
+
+JIT_BPF_Filter* BPF_jitter(struct bpf_insn *fp, INT nins)
+{
+ JIT_BPF_Filter *Filter;
+
+
+ // Allocate the filter structure
+#ifdef NTKERNEL
+ Filter=(struct JIT_BPF_Filter*)ExAllocatePoolWithTag(NonPagedPool, sizeof(struct JIT_BPF_Filter), '2JWA');
+#else
+ Filter=(struct JIT_BPF_Filter*)malloc(sizeof(struct JIT_BPF_Filter));
+#endif
+ if(Filter==NULL)
+ {
+ return NULL;
+ }
+
+ // Allocate the filter's memory
+#ifdef NTKERNEL
+ Filter->mem=(INT*)ExAllocatePoolWithTag(NonPagedPool, BPF_MEMWORDS*sizeof(INT), '3JWA');
+#else
+ Filter->mem=(INT*)malloc(BPF_MEMWORDS*sizeof(INT));
+#endif
+ if(Filter->mem==NULL)
+ {
+#ifdef NTKERNEL
+ ExFreePool(Filter);
+#else
+ free(Filter);
+#endif
+ return NULL;
+ }
+
+ // Create the binary
+ if((Filter->Function = BPFtoX86(fp, nins, Filter->mem))==NULL)
+ {
+#ifdef NTKERNEL
+ ExFreePool(Filter->mem);
+ ExFreePool(Filter);
+#else
+ free(Filter->mem);
+ free(Filter);
+#endif
+ return NULL;
+ }
+
+ return Filter;
+
+}
+
+//////////////////////////////////////////////////////////////
+
+void BPF_Destroy_JIT_Filter(JIT_BPF_Filter *Filter){
+
+#ifdef NTKERNEL
+ ExFreePool(Filter->mem);
+ ExFreePool(Filter->Function);
+ ExFreePool(Filter);
+#else
+ free(Filter->mem);
+ free(Filter->Function);
+ free(Filter);
+#endif
+
+}
diff --git a/drivers/3rdparty/npf/jitter.h b/drivers/3rdparty/npf/jitter.h
new file mode 100644
index 0000000000000..42fe38a3bd5d7
--- /dev/null
+++ b/drivers/3rdparty/npf/jitter.h
@@ -0,0 +1,410 @@
+/*
+ * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2007 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.
+ *
+ */
+
+/** @addtogroup NPF
+ * @{
+ */
+
+/** @defgroup NPF_jitter NPF Just-in-time compiler definitions
+ * @{
+ */
+
+//
+// Registers
+//
+#define EAX 0
+#define ECX 1
+#define EDX 2
+#define EBX 3
+#define ESP 4
+#define EBP 5
+#define ESI 6
+#define EDI 7
+
+#define AX 0
+#define CX 1
+#define DX 2
+#define BX 3
+#define SP 4
+#define BP 5
+#define SI 6
+#define DI 7
+
+#define AL 0
+#define CL 1
+#define DL 2
+#define BL 3
+
+/*! \brief A stream of X86 binary code.*/
+typedef struct binary_stream{
+ INT cur_ip; ///< Current X86 instruction pointer.
+ INT bpf_pc; ///< Current BPF instruction pointer, i.e. position in the BPF program reached by the jitter.
+ PCHAR ibuf; ///< Instruction buffer, contains the X86 generated code.
+ PUINT refs; ///< Jumps reference table.
+}binary_stream;
+
+
+/*! \brief Prototype of a filtering function created by the jitter.
+
+ The syntax and the meaning of the parameters is analogous to the one of bpf_filter(). Notice that the filter
+ is not among the parameters, because it is hardwired in the function.
+*/
+typedef UINT (__cdecl *BPF_filter_function)( PVOID *, ULONG, UINT);
+
+/*! \brief Prototype of the emit functions.
+
+ Different emit functions are used to create the reference table and to generate the actual filtering code.
+ This allows to have simpler instruction macros.
+ The first parameter is the stream that will receive the data. The secon one is a variable containing
+ the data, the third one is the length, that can be 1,2 or 4 since it is possible to emit a byte, a short
+ or a work at a time.
+*/
+typedef void (*emit_func)(binary_stream *stream, ULONG value, UINT n);
+
+/*! \brief Structure describing a x86 filtering program created by the jitter.*/
+typedef struct JIT_BPF_Filter{
+ BPF_filter_function Function; ///< The x86 filtering binary, in the form of a BPF_filter_function.
+ PINT mem;
+}
+JIT_BPF_Filter;
+
+
+
+
+/**************************/
+/* X86 INSTRUCTION MACROS */
+/**************************/
+
+/// mov r32,i32
+#define MOVid(r32, i32) \
+ emitm(&stream, 11 << 4 | 1 << 3 | r32 & 0x7, 1); emitm(&stream, i32, 4);
+
+/// mov dr32,sr32
+#define MOVrd(dr32, sr32) \
+ emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
+
+/// mov dr32,sr32[off]
+#define MOVodd(dr32, sr32, off) \
+ emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \
+ emitm(&stream, 1 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);\
+ emitm(&stream, off, 1);
+
+/// mov dr32,sr32[or32]
+#define MOVobd(dr32, sr32, or32) \
+ emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \
+ emitm(&stream, (dr32 & 0x7) << 3 | 4 , 1);\
+ emitm(&stream, (or32 & 0x7) << 3 | (sr32 & 0x7) , 1);
+
+/// mov dr16,sr32[or32]
+#define MOVobw(dr32, sr32, or32) \
+ emitm(&stream, 0x66, 1); \
+ emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \
+ emitm(&stream, (dr32 & 0x7) << 3 | 4 , 1);\
+ emitm(&stream, (or32 & 0x7) << 3 | (sr32 & 0x7) , 1);
+
+/// mov dr8,sr32[or32]
+#define MOVobb(dr8, sr32, or32) \
+ emitm(&stream, 0x8a, 1); \
+ emitm(&stream, (dr8 & 0x7) << 3 | 4 , 1);\
+ emitm(&stream, (or32 & 0x7) << 3 | (sr32 & 0x7) , 1);
+
+/// mov [dr32][or32],sr32
+#define MOVomd(dr32, or32, sr32) \
+ emitm(&stream, 0x89, 1); \
+ emitm(&stream, (sr32 & 0x7) << 3 | 4 , 1);\
+ emitm(&stream, (or32 & 0x7) << 3 | (dr32 & 0x7) , 1);
+
+/// bswap dr32
+#define BSWAP(dr32) \
+ emitm(&stream, 0xf, 1); \
+ emitm(&stream, 0x19 << 3 | dr32 , 1);
+
+/// xchg al,ah
+#define SWAP_AX() \
+ emitm(&stream, 0x86, 1); \
+ emitm(&stream, 0xc4 , 1);
+
+/// push r32
+#define PUSH(r32) \
+ emitm(&stream, 5 << 4 | 0 << 3 | r32 & 0x7, 1);
+
+/// pop r32
+#define POP(r32) \
+ emitm(&stream, 5 << 4 | 1 << 3 | r32 & 0x7, 1);
+
+/// ret
+#define RET() \
+ emitm(&stream, 12 << 4 | 0 << 3 | 3, 1);
+
+/// add dr32,sr32
+#define ADDrd(dr32, sr32) \
+ emitm(&stream, 0x03, 1);\
+ emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | (sr32 & 0x7), 1);
+
+/// add eax,i32
+#define ADD_EAXi(i32) \
+ emitm(&stream, 0x05, 1);\
+ emitm(&stream, i32, 4);
+
+/// add r32,i32
+#define ADDid(r32, i32) \
+ emitm(&stream, 0x81, 1);\
+ emitm(&stream, 24 << 3 | r32, 1);\
+ emitm(&stream, i32, 4);
+
+/// add r32,i8
+#define ADDib(r32, i8) \
+ emitm(&stream, 0x83, 1);\
+ emitm(&stream, 24 << 3 | r32, 1);\
+ emitm(&stream, i8, 1);
+
+/// sub dr32,sr32
+#define SUBrd(dr32, sr32) \
+ emitm(&stream, 0x2b, 1);\
+ emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | (sr32 & 0x7), 1);
+
+/// sub eax,i32
+#define SUB_EAXi(i32) \
+ emitm(&stream, 0x2d, 1);\
+ emitm(&stream, i32, 4);
+
+/// mul r32
+#define MULrd(r32) \
+ emitm(&stream, 0xf7, 1);\
+ emitm(&stream, 7 << 5 | (r32 & 0x7), 1);
+
+/// div r32
+#define DIVrd(r32) \
+ emitm(&stream, 0xf7, 1);\
+ emitm(&stream, 15 << 4 | (r32 & 0x7), 1);
+
+/// and r8,i8
+#define ANDib(r8, i8) \
+ emitm(&stream, 0x80, 1);\
+ emitm(&stream, 7 << 5 | r8, 1);\
+ emitm(&stream, i8, 1);
+
+/// and r32,i32
+#define ANDid(r32, i32) \
+ if (r32 == EAX){ \
+ emitm(&stream, 0x25, 1);\
+ emitm(&stream, i32, 4);}\
+ else{ \
+ emitm(&stream, 0x81, 1);\
+ emitm(&stream, 7 << 5 | r32, 1);\
+ emitm(&stream, i32, 4);}
+
+/// and dr32,sr32
+#define ANDrd(dr32, sr32) \
+ emitm(&stream, 0x23, 1);\
+ emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
+
+/// or dr32,sr32
+#define ORrd(dr32, sr32) \
+ emitm(&stream, 0x0b, 1);\
+ emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
+
+/// or r32,i32
+#define ORid(r32, i32) \
+ if (r32 == EAX){ \
+ emitm(&stream, 0x0d, 1);\
+ emitm(&stream, i32, 4);}\
+ else{ \
+ emitm(&stream, 0x81, 1);\
+ emitm(&stream, 25 << 3 | r32, 1);\
+ emitm(&stream, i32, 4);}
+
+/// shl r32,i8
+#define SHLib(r32, i8) \
+ emitm(&stream, 0xc1, 1);\
+ emitm(&stream, 7 << 5 | r32 & 0x7, 1);\
+ emitm(&stream, i8, 1);
+
+/// shl dr32,cl
+#define SHL_CLrb(dr32) \
+ emitm(&stream, 0xd3, 1);\
+ emitm(&stream, 7 << 5 | dr32 & 0x7, 1);
+
+/// shr r32,i8
+#define SHRib(r32, i8) \
+ emitm(&stream, 0xc1, 1);\
+ emitm(&stream, 29 << 3 | r32 & 0x7, 1);\
+ emitm(&stream, i8, 1);
+
+/// shr dr32,cl
+#define SHR_CLrb(dr32) \
+ emitm(&stream, 0xd3, 1);\
+ emitm(&stream, 29 << 3 | dr32 & 0x7, 1);
+
+/// neg r32
+#define NEGd(r32) \
+ emitm(&stream, 0xf7, 1);\
+ emitm(&stream, 27 << 3 | r32 & 0x7, 1);
+
+/// cmp dr32,sr32[off]
+#define CMPodd(dr32, sr32, off) \
+ emitm(&stream, 3 << 4 | 3 | 1 << 3, 1); \
+ emitm(&stream, 1 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);\
+ emitm(&stream, off, 1);
+
+/// cmp dr32,sr32
+#define CMPrd(dr32, sr32) \
+ emitm(&stream, 0x3b, 1); \
+ emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
+
+/// cmp dr32,i32
+#define CMPid(dr32, i32) \
+ if (dr32 == EAX){ \
+ emitm(&stream, 0x3d, 1); \
+ emitm(&stream, i32, 4);} \
+ else{ \
+ emitm(&stream, 0x81, 1); \
+ emitm(&stream, 0x1f << 3 | (dr32 & 0x7), 1);\
+ emitm(&stream, i32, 4);}
+
+/// jne off32
+#define JNEb(off8) \
+ emitm(&stream, 0x75, 1);\
+ emitm(&stream, off8, 1);
+
+/// ja off32
+#define JAb(off8) \
+ emitm(&stream, 0x77, 1);\
+ emitm(&stream, off8, 1);
+
+/// je off32
+#define JE(off32) \
+ emitm(&stream, 0x0f, 1);\
+ emitm(&stream, 0x84, 1);\
+ emitm(&stream, off32, 4);
+
+/// jle off32
+#define JLE(off32) \
+ emitm(&stream, 0x0f, 1);\
+ emitm(&stream, 0x8e, 1);\
+ emitm(&stream, off32, 4);
+
+/// jle off8
+#define JLEb(off8) \
+ emitm(&stream, 0x7e, 1);\
+ emitm(&stream, off8, 1);
+
+/// jbe off8
+#define JBEb(off8) \
+ emitm(&stream, 0x76, 1);\
+ emitm(&stream, off8, 1);
+
+/// jb off8
+#define JBb(off8) \
+ emitm(&stream, 0x72, 1);\
+ emitm(&stream, off8, 1);
+
+/// ja off32
+#define JA(off32) \
+ emitm(&stream, 0x0f, 1);\
+ emitm(&stream, 0x87, 1);\
+ emitm(&stream, off32, 4);
+
+/// jae off32
+#define JAE(off32) \
+ emitm(&stream, 0x0f, 1);\
+ emitm(&stream, 0x83, 1);\
+ emitm(&stream, off32, 4);
+
+/// jg off32
+#define JG(off32) \
+ emitm(&stream, 0x0f, 1);\
+ emitm(&stream, 0x8f, 1);\
+ emitm(&stream, off32, 4);
+
+/// jge off32
+#define JGE(off32) \
+ emitm(&stream, 0x0f, 1);\
+ emitm(&stream, 0x8d, 1);\
+ emitm(&stream, off32, 4);
+
+/// jmp off32
+#define JMP(off32) \
+ emitm(&stream, 0xe9, 1);\
+ emitm(&stream, off32, 4);
+
+/**
+ * @}
+ */
+
+/**************************/
+/* Prototypes */
+/**************************/
+
+/** @addtogroup NPF_code
+ * @{
+ */
+
+/*!
+ \brief BPF jitter, builds an x86 function from a BPF program.
+ \param fp The BPF pseudo-assembly filter that will be translated into x86 code.
+ \param nins Number of instructions of the input filter.
+ \return The JIT_BPF_Filter structure containing the x86 filtering binary.
+
+ BPF_jitter allocates the buffers for the new native filter and then translates the program pointed by fp
+ calling BPFtoX86().
+*/
+JIT_BPF_Filter* BPF_jitter(struct bpf_insn *fp, INT nins);
+
+/*!
+ \brief Translates a set of BPF instructions in a set of x86 ones.
+ \param ins Pointer to the BPF instructions that will be translated into x86 code.
+ \param nins Number of instructions to translate.
+ \param mem Memory used by the x86 function to emulate the RAM of the BPF pseudo processor.
+ \return The x86 filtering function.
+
+ This function does the hard work for the JIT compilation. It takes a group of BPF pseudo instructions and
+ through the instruction macros defined in jitter.h it is able to create an function directly executable
+ by NPF.
+*/
+BPF_filter_function BPFtoX86(struct bpf_insn *ins, UINT nins, INT *mem);
+/*!
+ \brief Deletes a filtering function that was previously created by BPF_jitter().
+ \param Filter The filter to destroy.
+
+ This function frees the variuos buffers (code, memory, etc.) associated with a filtering function.
+*/
+void BPF_Destroy_JIT_Filter(JIT_BPF_Filter *Filter);
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
diff --git a/drivers/3rdparty/npf/memory_t.h b/drivers/3rdparty/npf/memory_t.h
new file mode 100644
index 0000000000000..b4200168a41c1
--- /dev/null
+++ b/drivers/3rdparty/npf/memory_t.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2001 - 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.
+ *
+ */
+
+#ifndef __memory_t
+#define __memory_t
+
+#define uint8 UCHAR
+#define int8 CHAR
+#define uint16 USHORT
+#define int16 SHORT
+#define uint32 ULONG
+#define int32 LONG
+#define uint64 ULONGLONG
+#define int64 LONGLONG
+
+/*memory type*/
+typedef struct __MEM_TYPE
+{
+ uint8 *buffer;
+ uint32 size;
+} MEM_TYPE, *PMEM_TYPE;
+
+#define LONG_AT(base,offset) (*(int32*)((uint8*)base+(uint32)offset))
+
+#define ULONG_AT(base,offset) (*(uint32*)((uint8*)base+(uint32)offset))
+
+#define SHORT_AT(base,offset) (*(int16*)((uint8*)base+(uint32)offset))
+
+#define USHORT_AT(base,offset) (*(uint16*)((uint8*)base+(uint32)offset))
+
+__inline int32 SW_LONG_AT(void *b, uint32 c)
+{
+ return ((int32)*((uint8 *)b+c)<<24|
+ (int32)*((uint8 *)b+c+1)<<16|
+ (int32)*((uint8 *)b+c+2)<<8|
+ (int32)*((uint8 *)b+c+3)<<0);
+}
+
+
+__inline uint32 SW_ULONG_AT(void *b, uint32 c)
+{
+ return ((uint32)*((uint8 *)b+c)<<24|
+ (uint32)*((uint8 *)b+c+1)<<16|
+ (uint32)*((uint8 *)b+c+2)<<8|
+ (uint32)*((uint8 *)b+c+3)<<0);
+}
+
+__inline int16 SW_SHORT_AT(void *b, uint32 os)
+{
+ return ((int16)
+ ((int16)*((uint8 *)b+os+0)<<8|
+ (int16)*((uint8 *)b+os+1)<<0));
+}
+
+__inline uint16 SW_USHORT_AT(void *b, uint32 os)
+{
+ return ((uint16)
+ ((uint16)*((uint8 *)b+os+0)<<8|
+ (uint16)*((uint8 *)b+os+1)<<0));
+}
+
+__inline VOID SW_ULONG_ASSIGN(void *dst, uint32 src)
+{
+ *((uint8*)dst+0)=*((uint8*)&src+3);
+ *((uint8*)dst+1)=*((uint8*)&src+2);
+ *((uint8*)dst+2)=*((uint8*)&src+1);
+ *((uint8*)dst+3)=*((uint8*)&src+0);
+
+}
+
+#ifdef WIN_NT_DRIVER
+
+#define ALLOCATE_MEMORY(dest,type,amount) \
+ (dest)=ExAllocatePoolWithTag(NonPagedPool,sizeof(type)*(amount), '0TWA');
+#define ALLOCATE_ZERO_MEMORY(dest,type,amount) \
+ { \
+ (dest)=ExAllocatePoolWithTag(NonPagedPool,sizeof(type)*(amount), '1TWA'); \
+ if ((dest)!=NULL) \
+ RtlZeroMemory((dest),sizeof(type)*(amount)); \
+ }
+
+#define FREE_MEMORY(dest) ExFreePool(dest);
+#define ZERO_MEMORY(dest,amount) RtlZeroMemory(dest,amount);
+#define COPY_MEMORY(dest,src,amount) RtlCopyMemory(dest,src,amount);
+
+#else
+
+#define ALLOCATE_MEMORY(dest,type,amount) \
+ (dest)=(type*)GlobalAlloc(GPTR, sizeof(type)*(amount));
+#define ALLOCATE_ZERO_MEMORY(dest,type,amount) \
+ (dest)=(type*)GlobalAlloc(GPTR, sizeof(type)*(amount));
+
+#define FREE_MEMORY(dest) GlobalFree(dest);
+#define ZERO_MEMORY(dest,amount) RtlZeroMemory(dest,amount);
+#define COPY_MEMORY(dest,src,amount) RtlCopyMemory(dest,src,amount);
+
+
+#endif /*WIN_NT_DRIVER*/
+
+
+
+#endif
+
diff --git a/drivers/3rdparty/npf/normal_lookup.c b/drivers/3rdparty/npf/normal_lookup.c
new file mode 100644
index 0000000000000..20f057ca34ac1
--- /dev/null
+++ b/drivers/3rdparty/npf/normal_lookup.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * 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 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.
+ *
+ */
+
+#ifdef WIN32
+#include "tme.h"
+#include "normal_lookup.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include
+#include
+#else
+#include
+#include
+#endif
+
+#endif
+
+
+/* lookup in the table, seen as an hash */
+/* if not found, inserts an element */
+/* returns TME_TRUE if the entry is found or created, */
+/* returns TME_FALSE if no more blocks are available */
+uint32 normal_lut_w_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref)
+{
+ uint32 i;
+ uint32 tocs=0;
+ uint32 *key32=(uint32*) key;
+ uint32 shrinked_key=0;
+ uint32 index;
+ RECORD *records=(RECORD*)data->lut_base_address;
+ uint8 *offset;
+ uint32 key_len=data->key_len;
+ /*the key is shrinked into a 32-bit value */
+ for (i=0; ilut_entries;
+
+ while (tocs<=data->filled_entries)
+ {
+
+ if (records[index].block==0)
+ { /*creation of a new entry*/
+
+ if (data->filled_blocks==data->shared_memory_blocks)
+ {
+ /*no more free blocks*/
+ GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref);
+ data->last_found=NULL;
+ return TME_FALSE;
+ }
+
+ /*offset=absolute pointer to the block associated*/
+ /*with the newly created entry*/
+ offset=data->shared_memory_base_address+
+ data->block_size*data->filled_blocks;
+
+ /*copy the key in the block*/
+ COPY_MEMORY(offset,key32,key_len*4);
+ GET_TIME((struct timeval *)(offset+4*key_len),time_ref);
+ /*assign the block relative offset to the entry, in NBO*/
+ SW_ULONG_ASSIGN(&records[index].block,offset-mem_ex->buffer);
+
+ data->filled_blocks++;
+
+ /*assign the exec function ID to the entry, in NBO*/
+ SW_ULONG_ASSIGN(&records[index].exec_fcn,data->default_exec);
+ data->filled_entries++;
+
+ data->last_found=(uint8*)&records[index];
+
+ return TME_TRUE;
+ }
+ /*offset contains the absolute pointer to the block*/
+ /*associated with the current entry */
+ offset=mem_ex->buffer+SW_ULONG_AT(&records[index].block,0);
+
+ for (i=0; (ilast_found=(uint8*)&records[index];
+ return TME_TRUE;
+ }
+ else
+ {
+ /* wrong entry, rehashing */
+ if (IS_DELETABLE(offset+key_len*4,data))
+ {
+ ZERO_MEMORY(offset,data->block_size);
+ COPY_MEMORY(offset,key32,key_len*4);
+ SW_ULONG_ASSIGN(&records[index].exec_fcn,data->default_exec);
+ GET_TIME((struct timeval*)(offset+key_len*4),time_ref);
+ data->last_found=(uint8*)&records[index];
+ return TME_TRUE;
+ }
+ else
+ {
+ index=(index+data->rehashing_value) % data->lut_entries;
+ tocs++;
+ }
+ }
+ }
+
+ /* nothing found, last found= out of lut */
+ GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref);
+ data->last_found=NULL;
+ return TME_FALSE;
+
+}
+
+/* lookup in the table, seen as an hash */
+/* if not found, returns out of count entry index */
+/* returns TME_TRUE if the entry is found */
+/* returns TME_FALSE if the entry is not found */
+uint32 normal_lut_wo_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref)
+{
+ uint32 i;
+ uint32 tocs=0;
+ uint32 *key32=(uint32*) key;
+ uint32 shrinked_key=0;
+ uint32 index;
+ RECORD *records=(RECORD*)data->lut_base_address;
+ uint8 *offset;
+ uint32 key_len=data->key_len;
+ /*the key is shrinked into a 32-bit value */
+ for (i=0; ilut_entries;
+
+ while (tocs<=data->filled_entries)
+ {
+
+ if (records[index].block==0)
+ { /*out of table, insertion is not allowed*/
+ GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref);
+ data->last_found=NULL;
+ return TME_FALSE;
+ }
+ /*offset contains the absolute pointer to the block*/
+ /*associated with the current entry */
+
+ offset=mem_ex->buffer+SW_ULONG_AT(&records[index].block,0);
+
+ for (i=0; (ilast_found=(uint8*)&records[index];
+ return TME_TRUE;
+ }
+ else
+ {
+ /*wrong entry, rehashing*/
+ index=(index+data->rehashing_value) % data->lut_entries;
+ tocs++;
+ }
+ }
+
+ /*nothing found, last found= out of lut*/
+ GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref);
+ data->last_found=NULL;
+ return TME_FALSE;
+
+}
diff --git a/drivers/3rdparty/npf/normal_lookup.h b/drivers/3rdparty/npf/normal_lookup.h
new file mode 100644
index 0000000000000..62e75f467db30
--- /dev/null
+++ b/drivers/3rdparty/npf/normal_lookup.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * 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 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.
+ *
+ */
+
+#ifndef __normal_lookup
+#define __normal_lookup
+
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include
+#else
+#include
+#endif
+
+#endif
+
+#define NORMAL_LUT_W_INSERT 0x00000000
+uint32 normal_lut_w_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);
+#define NORMAL_LUT_WO_INSERT 0x00000001
+uint32 normal_lut_wo_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);
+#define DUMMY_INSERT 1234
+
+#endif
\ No newline at end of file
diff --git a/drivers/3rdparty/npf/resource.h b/drivers/3rdparty/npf/resource.h
new file mode 100644
index 0000000000000..d704ecaaf4149
--- /dev/null
+++ b/drivers/3rdparty/npf/resource.h
@@ -0,0 +1,15 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by NPF.RC
+//
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 101
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1000
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/drivers/3rdparty/npf/tcp_session.c b/drivers/3rdparty/npf/tcp_session.c
new file mode 100644
index 0000000000000..1848ccf8f32a1
--- /dev/null
+++ b/drivers/3rdparty/npf/tcp_session.c
@@ -0,0 +1,294 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * 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 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.
+ *
+ */
+
+#ifdef WIN32
+#include "tme.h"
+#include "tcp_session.h"
+#endif
+
+#ifdef __FreeBSD
+
+#ifdef _KERNEL
+#include
+#include
+#else
+#include
+#include
+#endif
+
+#endif
+
+uint32 tcp_session(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data)
+
+{
+
+ uint32 next_status;
+ uint32 direction=ULONG_AT(mem_data,12);
+ uint8 flags=mem_ex->buffer[25];
+ tcp_data *session=(tcp_data*)(block+data->key_len*4);
+
+ session->last_timestamp=session->timestamp_block;
+ session->timestamp_block.tv_sec=0x7fffffff;
+
+ if (direction==session->direction)
+ {
+ session->pkts_cln_to_srv++;
+ session->bytes_cln_to_srv+=pkt_size;
+ }
+ else
+ {
+ session->pkts_srv_to_cln++;
+ session->bytes_srv_to_cln+=pkt_size;
+ }
+ /* we use only thes four flags, we don't need PSH or URG */
+ flags&=(ACK|FIN|SYN|RST);
+
+ switch (session->status)
+ {
+ case ERROR_TCP:
+ next_status=ERROR_TCP;
+ break;
+
+ case UNKNOWN:
+ if (flags==SYN)
+ {
+ if (SW_ULONG_AT(mem_ex->buffer,20)!=0)
+ {
+
+ next_status=ERROR_TCP;
+ break;
+ }
+ next_status=SYN_RCV;
+ session->syn_timestamp=session->last_timestamp;
+
+ session->direction=direction;
+ session->seq_n_0_cln=SW_ULONG_AT(mem_ex->buffer,16);
+ }
+ else
+ next_status=UNKNOWN;
+ break;
+
+ case SYN_RCV:
+ if ((flags&RST)&&(direction!=session->direction))
+ {
+ next_status=CLOSED_RST;
+ break;
+ }
+ if ((flags==SYN)&&(direction==session->direction))
+ { /* two syns... */
+ next_status=SYN_RCV;
+ session->seq_n_0_cln=SW_ULONG_AT(mem_ex->buffer,16);
+ break;
+ }
+
+ if ((flags==(SYN|ACK))&&(direction!=session->direction))
+ {
+ if (SW_ULONG_AT(mem_ex->buffer,20)!=session->seq_n_0_cln+1)
+ {
+ next_status=ERROR_TCP;
+ break;
+ }
+ next_status=SYN_ACK_RCV;
+
+ session->syn_ack_timestamp=session->last_timestamp;
+
+ session->seq_n_0_srv=SW_ULONG_AT(mem_ex->buffer,16);
+ session->ack_cln=session->seq_n_0_cln+1;
+ }
+ else
+ {
+ next_status=ERROR_TCP;
+ }
+ break;
+
+ case SYN_ACK_RCV:
+ if ((flags&ACK)&&(flags&RST)&&(direction==session->direction))
+ {
+ next_status=CLOSED_RST;
+ session->ack_srv=SW_ULONG_AT(mem_ex->buffer,20);
+ break;
+ }
+
+ if ((flags==ACK)&&(!(flags&(SYN|FIN|RST)))&&(direction==session->direction))
+ {
+ if (SW_ULONG_AT(mem_ex->buffer,20)!=session->seq_n_0_srv+1)
+ {
+ next_status=ERROR_TCP;
+ break;
+ }
+ next_status=ESTABLISHED;
+ session->ack_srv=session->seq_n_0_srv+1;
+ break;
+ }
+ if ((flags&ACK)&&(flags&SYN)&&(direction!=session->direction))
+ {
+ next_status=SYN_ACK_RCV;
+ break;
+ }
+
+ next_status=ERROR_TCP;
+ break;
+
+ case ESTABLISHED:
+ if (flags&SYN)
+ {
+ if ((flags&ACK)&&
+ (direction!=session->direction)&&
+ ((session->ack_cln-SW_ULONG_AT(mem_ex->buffer,20))direction)&&
+ (SW_ULONG_AT(mem_ex->buffer,16)==session->seq_n_0_cln)&&
+ (ULONG_AT(mem_ex->buffer,20)==0)
+ )
+ { /* syn duplicato */
+ next_status=ESTABLISHED;
+ break;
+ }
+
+ next_status=ERROR_TCP;
+ break;
+ }
+ if (flags&ACK)
+ if (direction==session->direction)
+ {
+ uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
+ if (new_ack-session->ack_srvack_srv=new_ack;
+ }
+ else
+ {
+ uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
+ if (new_ack-session->ack_clnack_cln=new_ack;
+ }
+ if (flags&RST)
+ {
+ next_status=CLOSED_RST;
+ break;
+ }
+ if (flags&FIN)
+ if (direction==session->direction)
+ { /* an hack to make all things work */
+ session->ack_cln=SW_ULONG_AT(mem_ex->buffer,16);
+ next_status=FIN_CLN_RCV;
+ break;
+ }
+ else
+ {
+ session->ack_srv=SW_ULONG_AT(mem_ex->buffer,16);
+ next_status=FIN_SRV_RCV;
+ break;
+ }
+ next_status=ESTABLISHED;
+ break;
+
+ case CLOSED_RST:
+ next_status=CLOSED_RST;
+ break;
+
+ case FIN_SRV_RCV:
+ if (flags&SYN)
+ {
+ next_status=ERROR_TCP;
+ break;
+ }
+
+ next_status=FIN_SRV_RCV;
+
+ if (flags&ACK)
+ {
+ uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
+ if (direction!=session->direction)
+ if ((new_ack-session->ack_cln)ack_cln=new_ack;
+ }
+
+ if (flags&RST)
+ next_status=CLOSED_RST;
+ else
+ if ((flags&FIN)&&(direction==session->direction))
+ {
+ session->ack_cln=SW_ULONG_AT(mem_ex->buffer,16);
+ next_status=CLOSED_FIN;
+ }
+
+ break;
+
+ case FIN_CLN_RCV:
+ if (flags&SYN)
+ {
+ next_status=ERROR_TCP;
+ break;
+ }
+
+ next_status=FIN_CLN_RCV;
+
+ if (flags&ACK)
+ {
+ uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
+ if (direction==session->direction)
+ if (new_ack-session->ack_srvack_srv=new_ack;
+ }
+
+ if (flags&RST)
+ next_status=CLOSED_RST;
+ else
+ if ((flags&FIN)&&(direction!=session->direction))
+ {
+ session->ack_srv=SW_ULONG_AT(mem_ex->buffer,16);
+ next_status=CLOSED_FIN;
+ }
+
+ break;
+
+ case CLOSED_FIN:
+ next_status=CLOSED_FIN;
+ break;
+ default:
+ next_status=ERROR_TCP;
+
+ }
+
+ session->status=next_status;
+
+ if ((next_status==CLOSED_FIN)||(next_status==UNKNOWN)||(next_status==CLOSED_RST)||(next_status==ERROR_TCP))
+ session->timestamp_block=session->last_timestamp;
+
+ return TME_SUCCESS;
+}
\ No newline at end of file
diff --git a/drivers/3rdparty/npf/tcp_session.h b/drivers/3rdparty/npf/tcp_session.h
new file mode 100644
index 0000000000000..73d6bc3573873
--- /dev/null
+++ b/drivers/3rdparty/npf/tcp_session.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * 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 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.
+ *
+ */
+
+#ifndef __tcp_session
+#define __tcp_session
+
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include
+#else
+#include
+#endif
+
+#endif
+
+#define UNKNOWN 0
+#define SYN_RCV 1
+#define SYN_ACK_RCV 2
+#define ESTABLISHED 3
+#define CLOSED_RST 4
+#define FIN_CLN_RCV 5
+#define FIN_SRV_RCV 6
+#define CLOSED_FIN 7
+#define ERROR_TCP 8
+#define FIRST_IS_CLN 0
+#define FIRST_IS_SRV 0xffffffff
+#define FIN_CLN 1
+#define FIN_SRV 2
+
+#define MAX_WINDOW 65536
+
+typedef struct __tcp_data
+{
+ struct timeval timestamp_block; /*DO NOT MOVE THIS VALUE*/
+ struct timeval syn_timestamp;
+ struct timeval last_timestamp;
+ struct timeval syn_ack_timestamp;
+ uint32 direction;
+ uint32 seq_n_0_srv;
+ uint32 seq_n_0_cln;
+ uint32 ack_srv; /* acknowledge of (data sent by server) */
+ uint32 ack_cln; /* acknowledge of (data sent by client) */
+ uint32 status;
+ uint32 pkts_cln_to_srv;
+ uint32 pkts_srv_to_cln;
+ uint32 bytes_srv_to_cln;
+ uint32 bytes_cln_to_srv;
+ uint32 close_state;
+}
+ tcp_data;
+
+#define FIN 1
+#define SYN 2
+#define RST 4
+#define PSH 8
+#define ACK 16
+#define URG 32
+
+#define TCP_SESSION 0x00000800
+uint32 tcp_session(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data);
+
+#endif
\ No newline at end of file
diff --git a/drivers/3rdparty/npf/time_calls.h b/drivers/3rdparty/npf/time_calls.h
new file mode 100644
index 0000000000000..cb378dcfd79fb
--- /dev/null
+++ b/drivers/3rdparty/npf/time_calls.h
@@ -0,0 +1,489 @@
+/*
+ * Copyright (c) 2001 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2007 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.
+ *
+ */
+
+#ifndef _time_calls
+#define _time_calls
+
+#ifdef WIN_NT_DRIVER
+
+#include "debug.h"
+#include "ndis.h"
+
+#define DEFAULT_TIMESTAMPMODE 0
+
+#define TIMESTAMPMODE_SINGLE_SYNCHRONIZATION 0
+#define TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP 1
+#define TIMESTAMPMODE_QUERYSYSTEMTIME 2
+#define TIMESTAMPMODE_RDTSC 3
+
+#define TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_NO_FIXUP 99
+
+#define TIMESTAMPMODE_REGKEY L"TimestampMode"
+
+extern ULONG TimestampMode;
+
+/*!
+ \brief A microsecond precise timestamp.
+
+ included in the sf_pkthdr or the bpf_hdr that NPF associates with every packet.
+*/
+
+struct timeval {
+ long tv_sec; ///< seconds
+ long tv_usec; ///< microseconds
+};
+
+#endif /*WIN_NT_DRIVER*/
+
+struct time_conv
+{
+ ULONGLONG reference;
+ struct timeval start[32];
+};
+
+#ifdef WIN_NT_DRIVER
+
+__inline void TIME_DESYNCHRONIZE(struct time_conv *data)
+{
+ data->reference = 0;
+// data->start.tv_sec = 0;
+// data->start.tv_usec = 0;
+}
+
+
+__inline void ReadTimeStampModeFromRegistry(PUNICODE_STRING RegistryPath)
+{
+ ULONG NewLength;
+ PWSTR NullTerminatedString;
+ RTL_QUERY_REGISTRY_TABLE Queries[2];
+ ULONG DefaultTimestampMode = DEFAULT_TIMESTAMPMODE;
+
+ NewLength = RegistryPath->Length/2;
+
+ NullTerminatedString = ExAllocatePoolWithTag(PagedPool, (NewLength+1) *sizeof(WCHAR), '2TWA');
+
+ if (NullTerminatedString != NULL)
+ {
+ RtlCopyMemory(NullTerminatedString, RegistryPath->Buffer, RegistryPath->Length);
+
+ NullTerminatedString[NewLength]=0;
+
+ RtlZeroMemory(Queries, sizeof(Queries));
+
+ Queries[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
+ Queries[0].Name = TIMESTAMPMODE_REGKEY;
+ Queries[0].EntryContext = &TimestampMode;
+ Queries[0].DefaultType = REG_DWORD;
+ Queries[0].DefaultData = &DefaultTimestampMode;
+ Queries[0].DefaultLength = sizeof(ULONG);
+
+ if(RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, NullTerminatedString, Queries, NULL, NULL) != STATUS_SUCCESS)
+ {
+ TimestampMode = DEFAULT_TIMESTAMPMODE;
+ }
+
+ RtlWriteRegistryValue( RTL_REGISTRY_ABSOLUTE, NullTerminatedString, TIMESTAMPMODE_REGKEY, REG_DWORD, &TimestampMode,sizeof(ULONG));
+ ExFreePool(NullTerminatedString);
+ }
+ else
+ TimestampMode = DEFAULT_TIMESTAMPMODE;
+}
+
+#pragma optimize ("g",off) //Due to some weird behaviour of the optimizer of DDK build 2600
+
+/* KeQueryPerformanceCounter TimeStamps */
+__inline void SynchronizeOnCpu(struct timeval *start)
+{
+// struct timeval *start = (struct timeval*)Data;
+
+ struct timeval tmp;
+ LARGE_INTEGER SystemTime;
+ LARGE_INTEGER i;
+ ULONG tmp2;
+ LARGE_INTEGER TimeFreq,PTime;
+
+ // get the absolute value of the system boot time.
+
+ PTime = KeQueryPerformanceCounter(&TimeFreq);
+ KeQuerySystemTime(&SystemTime);
+
+ start->tv_sec = (LONG)(SystemTime.QuadPart/10000000-11644473600);
+
+ start->tv_usec = (LONG)((SystemTime.QuadPart%10000000)/10);
+
+ start->tv_sec -= (ULONG)(PTime.QuadPart/TimeFreq.QuadPart);
+
+ start->tv_usec -= (LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
+
+ if (start->tv_usec < 0)
+ {
+ start->tv_sec --;
+ start->tv_usec += 1000000;
+ }
+}
+
+//
+// inline assembler is not supported with the current AMD64 compilers
+// At the moment we simply disable this timestamping mode on AMD64.
+// A solution would be to allocate a small memory from the non-paged
+// pool, dump the instructions on that buffer, and then execute them.
+// The non paged pool is needed since it's the only area of kernel
+// data memory that is not subject to the NX protection.
+// Or use some lower level trick, like using an assembler to assemble
+// a small function for this.
+//
+
+#ifdef _X86_
+/*RDTSC timestamps */
+/* callers must be at IRQL=PASSIVE_LEVEL*/
+__inline VOID TimeSynchronizeRDTSC(struct time_conv *data)
+{
+ struct timeval tmp;
+ LARGE_INTEGER system_time;
+ ULONGLONG curr_ticks;
+ KIRQL old;
+ LARGE_INTEGER start_kqpc,stop_kqpc,start_freq,stop_freq;
+ ULONGLONG start_ticks,stop_ticks;
+ ULONGLONG delta,delta2;
+ KEVENT event;
+ LARGE_INTEGER i;
+ ULONGLONG reference;
+
+ if (data->reference!=0)
+ return;
+
+ KeInitializeEvent(&event,NotificationEvent,FALSE);
+
+ i.QuadPart=-3500000;
+
+ KeRaiseIrql(HIGH_LEVEL,&old);
+ start_kqpc=KeQueryPerformanceCounter(&start_freq);
+ __asm
+ {
+ push eax
+ push edx
+ push ecx
+ rdtsc
+ lea ecx, start_ticks
+ mov [ecx+4], edx
+ mov [ecx], eax
+ pop ecx
+ pop edx
+ pop eax
+ }
+
+ KeLowerIrql(old);
+
+ KeWaitForSingleObject(&event,UserRequest,KernelMode,TRUE ,&i);
+
+ KeRaiseIrql(HIGH_LEVEL,&old);
+ stop_kqpc=KeQueryPerformanceCounter(&stop_freq);
+ __asm
+ {
+ push eax
+ push edx
+ push ecx
+ rdtsc
+ lea ecx, stop_ticks
+ mov [ecx+4], edx
+ mov [ecx], eax
+ pop ecx
+ pop edx
+ pop eax
+ }
+ KeLowerIrql(old);
+
+ delta=stop_ticks-start_ticks;
+ delta2=stop_kqpc.QuadPart-start_kqpc.QuadPart;
+ if (delta>10000000000)
+ {
+ delta/=16;
+ delta2/=16;
+ }
+
+ reference=delta*(start_freq.QuadPart)/delta2;
+
+ data->reference=reference/1000;
+
+ if (reference%1000>500)
+ data->reference++;
+
+ data->reference*=1000;
+
+ reference=data->reference;
+
+ KeQuerySystemTime(&system_time);
+
+ __asm
+ {
+ push eax
+ push edx
+ push ecx
+ rdtsc
+ lea ecx, curr_ticks
+ mov [ecx+4], edx
+ mov [ecx], eax
+ pop ecx
+ pop edx
+ pop eax
+ }
+
+ tmp.tv_sec=-(LONG)(curr_ticks/reference);
+
+ tmp.tv_usec=-(LONG)((curr_ticks%reference)*1000000/reference);
+
+ system_time.QuadPart-=116444736000000000;
+
+ tmp.tv_sec+=(LONG)(system_time.QuadPart/10000000);
+ tmp.tv_usec+=(LONG)((system_time.QuadPart%10000000)/10);
+
+ if (tmp.tv_usec<0)
+ {
+ tmp.tv_sec--;
+ tmp.tv_usec+=1000000;
+ }
+
+ data->start[0] = tmp;
+
+ IF_LOUD(DbgPrint("Frequency %I64u MHz\n",data->reference);)
+}
+#endif //_X86_
+
+#pragma optimize ("g",on) //Due to some weird behaviour of the optimizer of DDK build 2600
+
+__inline VOID TIME_SYNCHRONIZE(struct time_conv *data)
+{
+ ULONG NumberOfCpus, i;
+ KAFFINITY AffinityMask;
+
+ if (data->reference != 0)
+ return;
+
+ NumberOfCpus = NdisSystemProcessorCount();
+
+ if ( TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP || TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_NO_FIXUP)
+ {
+ for (i = 0 ; i < NumberOfCpus ; i++ )
+ {
+ //
+ // the following cast is needed because KAFFINITY is defined as a 32bit value on x86 and a 64bit integer on x64.
+ // The constant 1 is implicitely 32bit only, so a shift won't work properly on x64.
+ //
+ AffinityMask = ((KAFFINITY)1 << i);
+ ZwSetInformationThread(NtCurrentThread(), ThreadAffinityMask, &AffinityMask, sizeof(KAFFINITY));
+ SynchronizeOnCpu(&(data->start[i]));
+ }
+ AffinityMask = 0xFFFFFFFF;
+ ZwSetInformationThread(NtCurrentThread(), ThreadAffinityMask, &AffinityMask, sizeof(KAFFINITY));
+ data->reference = 1;
+ }
+ else
+ if ( TimestampMode == TIMESTAMPMODE_QUERYSYSTEMTIME )
+ {
+ //do nothing
+ data->reference = 1;
+ }
+ else
+//
+// This timestamp mode is supported on x86 (32 bit) only
+//
+#ifdef _X86_
+ if ( TimestampMode == TIMESTAMPMODE_RDTSC )
+ {
+ TimeSynchronizeRDTSC(data);
+ }
+ else
+#endif // _X86_
+ { //it should be only the normal case i.e. TIMESTAMPMODE_SINGLESYNCHRONIZATION
+ SynchronizeOnCpu(data->start);
+ data->reference = 1;
+ }
+ return;
+}
+
+
+#pragma optimize ("g",off) //Due to some weird behaviour of the optimizer of DDK build 2600
+
+__inline void GetTimeKQPC(struct timeval *dst, struct time_conv *data)
+{
+ LARGE_INTEGER PTime, TimeFreq;
+ LONG tmp;
+ ULONG CurrentCpu;
+ static struct timeval old_ts={0,0};
+
+
+ PTime = KeQueryPerformanceCounter(&TimeFreq);
+ tmp = (LONG)(PTime.QuadPart/TimeFreq.QuadPart);
+
+ if (TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP || TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_NO_FIXUP)
+ {
+ //actually this code is ok only if we are guaranteed that no thread scheduling will take place.
+ CurrentCpu = KeGetCurrentProcessorNumber();
+
+ dst->tv_sec = data->start[CurrentCpu].tv_sec + tmp;
+ dst->tv_usec = data->start[CurrentCpu].tv_usec + (LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
+
+ if (dst->tv_usec >= 1000000)
+ {
+ dst->tv_sec ++;
+ dst->tv_usec -= 1000000;
+ }
+
+ if (TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP)
+ {
+ if (old_ts.tv_sec > dst->tv_sec || (old_ts.tv_sec == dst->tv_sec && old_ts.tv_usec > dst->tv_usec) )
+ *dst = old_ts;
+
+ else
+ old_ts = *dst;
+ }
+ }
+ else
+ { //it should be only the normal case i.e. TIMESTAMPMODE_SINGLESYNCHRONIZATION
+ dst->tv_sec = data->start[0].tv_sec + tmp;
+ dst->tv_usec = data->start[0].tv_usec + (LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
+
+ if (dst->tv_usec >= 1000000)
+ {
+ dst->tv_sec ++;
+ dst->tv_usec -= 1000000;
+ }
+ }
+}
+
+//
+// inline assembler is not supported with the current AMD64 compilers
+// At the moment we simply disable this timestamping mode on AMD64.
+// A solution would be to allocate a small memory from the non-paged
+// pool, dump the instructions on that buffer, and then execute them.
+// The non paged pool is needed since it's the only area of kernel
+// data memory that is not subject to the NX protection.
+// Or use some lower level trick, like using an assembler to assemble
+// a small function for this.
+//
+
+#ifdef _X86_
+__inline void GetTimeRDTSC(struct timeval *dst, struct time_conv *data)
+{
+
+ ULONGLONG tmp = 0;
+ __asm
+ {
+ push eax
+ push edx
+ push ecx
+ rdtsc
+ lea ecx, tmp
+ mov [ecx+4], edx
+ mov [ecx], eax
+ pop ecx
+ pop edx
+ pop eax
+ }
+
+ if (data->reference==0)
+ {
+ return;
+ }
+ dst->tv_sec=(LONG)(tmp/data->reference);
+
+ dst->tv_usec=(LONG)((tmp-dst->tv_sec*data->reference)*1000000/data->reference);
+
+ dst->tv_sec+=data->start[0].tv_sec;
+
+ dst->tv_usec+=data->start[0].tv_usec;
+
+ if (dst->tv_usec>=1000000)
+ {
+ dst->tv_sec++;
+ dst->tv_usec-=1000000;
+ }
+
+
+}
+#endif //_X86_
+
+__inline void GetTimeQST(struct timeval *dst, struct time_conv *data)
+{
+ LARGE_INTEGER SystemTime;
+
+ KeQuerySystemTime(&SystemTime);
+
+ dst->tv_sec = (LONG)(SystemTime.QuadPart/10000000-11644473600);
+ dst->tv_usec = (LONG)((SystemTime.QuadPart%10000000)/10);
+
+}
+
+#pragma optimize ("g",on) //Due to some weird behaviour of the optimizer of DDK build 2600
+
+
+__inline void GET_TIME(struct timeval *dst, struct time_conv *data)
+{
+
+//
+// This timestamp mode is supported on x86 (32 bit) only
+//
+#ifdef _X86_
+ if ( TimestampMode == TIMESTAMPMODE_RDTSC )
+ {
+ GetTimeRDTSC(dst,data);
+ }
+ else
+#endif // _X86_
+ if ( TimestampMode == TIMESTAMPMODE_QUERYSYSTEMTIME )
+ {
+ GetTimeQST(dst,data);
+ }
+ else
+ {
+ GetTimeKQPC(dst,data);
+ }
+}
+
+
+#else /*WIN_NT_DRIVER*/
+
+__inline void FORCE_TIME(struct timeval *src, struct time_conv *dest)
+{
+ dest->start[0]=*src;
+}
+
+__inline void GET_TIME(struct timeval *dst, struct time_conv *data)
+{
+ *dst=data->start[0];
+}
+
+#endif /*WIN_NT_DRIVER*/
+
+
+#endif /*_time_calls*/
diff --git a/drivers/3rdparty/npf/tme.c b/drivers/3rdparty/npf/tme.c
new file mode 100644
index 0000000000000..92a8644b95bf0
--- /dev/null
+++ b/drivers/3rdparty/npf/tme.c
@@ -0,0 +1,390 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * 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 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 "tme.h"
+
+#ifndef UNUSED
+#define UNUSED(_x) (_x)
+#endif
+
+/* resizes extended memory */
+uint32 init_extended_memory(uint32 size, MEM_TYPE *mem_ex)
+{
+ uint8 *tmp;
+
+ if ((mem_ex==NULL)||(mem_ex->buffer==NULL)||(size==0))
+ return TME_ERROR; /* awfully never reached!!!! */
+
+ tmp=mem_ex->buffer;
+ mem_ex->buffer=NULL;
+ FREE_MEMORY(tmp);
+
+ ALLOCATE_MEMORY(tmp,uint8,size);
+ if (tmp==NULL)
+ return TME_ERROR; /* no memory */
+
+ mem_ex->size=size;
+ mem_ex->buffer=tmp;
+ return TME_SUCCESS;
+
+}
+
+/* activates a block of the TME */
+uint32 set_active_tme_block(TME_CORE *tme, uint32 block)
+{
+
+ if ((block>=MAX_TME_DATA_BLOCKS)||(!IS_VALIDATED(tme->validated_blocks,block)))
+ return TME_ERROR;
+ tme->active=block;
+ tme->working=block;
+ return TME_SUCCESS;
+
+}
+
+/* simply inserts default values in a TME block */
+/* it DOESN'T initialize the block in the core!! */
+/* FIXME default values are defined at compile time, */
+/* it will be useful to store them in the registry */
+uint32 init_tme_block(TME_CORE *tme, uint32 block)
+{
+
+ TME_DATA *data;
+ if (block>=MAX_TME_DATA_BLOCKS)
+ return TME_ERROR;
+ data=&(tme->block_data[block]);
+ tme->working=block;
+
+ ZERO_MEMORY(data,sizeof(TME_DATA));
+
+ /* entries in LUT */
+ data->lut_entries=TME_LUT_ENTRIES_DEFAULT;
+ /* blocks */
+ data->shared_memory_blocks=TME_SHARED_MEMORY_BLOCKS_DEFAULT;
+ /* block size */
+ data->block_size=TME_BLOCK_SIZE_DEFAULT;
+ /* lookup function */
+ data->lookup_code=lut_fcn_mapper(TME_LOOKUP_CODE_DEFAULT);
+ /* rehashing value */
+ data->rehashing_value=TME_REHASHING_VALUE_DEFAULT;
+ /* out lut function */
+ data->out_lut_exec=TME_OUT_LUT_EXEC_DEFAULT;
+ /* default function */
+ data->default_exec=TME_DEFAULT_EXEC_DEFAULT;
+ /* extra segment size */
+ data->extra_segment_size=TME_EXTRA_SEGMENT_SIZE_DEFAULT;
+
+
+ data->enable_deletion=FALSE;
+ data->last_read.tv_sec=0;
+ data->last_read.tv_usec=0;
+ return TME_SUCCESS;
+
+}
+/* it validates a TME block and */
+/* (on OK) inserts the block in the core */
+uint32 validate_tme_block(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 block, uint32 mem_ex_offset)
+{
+ uint32 required_memory;
+ uint8 *base=mem_ex_offset+mem_ex->buffer;
+ TME_DATA *data;
+
+ /* FIXME soluzione un po' posticcia... */
+ if (mem_ex_offset==0)
+ return TME_ERROR;
+
+ if (block>=MAX_TME_DATA_BLOCKS)
+ return TME_ERROR;
+ data=&tme->block_data[block];
+
+ if (data->lut_entries==0)
+ return TME_ERROR;
+
+ if (data->key_len==0)
+ return TME_ERROR;
+
+ if (data->shared_memory_blocks==0)
+ return TME_ERROR;
+
+ if (data->block_size==0)
+ return TME_ERROR;
+
+ /* checks if the lookup function is valid */
+ if (data->lookup_code==NULL)
+ return TME_ERROR;
+
+ /* checks if the out lut exec function is valid */
+ if (exec_fcn_mapper(data->out_lut_exec)==NULL)
+ return TME_ERROR;
+
+ /* checks if the default exec function is valid */
+ if (exec_fcn_mapper(data->default_exec)==NULL)
+ return TME_ERROR;
+
+ /* let's calculate memory needed */
+ required_memory=data->lut_entries*sizeof(RECORD); /*LUT*/
+ required_memory+=data->block_size*data->shared_memory_blocks; /*shared segment*/
+ required_memory+=data->extra_segment_size; /*extra segment*/
+
+ if (required_memory>(mem_ex->size-mem_ex_offset))
+ return TME_ERROR; /*not enough memory*/
+
+ /* the TME block can be initialized */
+ ZERO_MEMORY(base,required_memory);
+
+ data->lut_base_address=base;
+
+ data->shared_memory_base_address=
+ data->lut_base_address+
+ data->lut_entries*sizeof(RECORD);
+
+ data->extra_segment_base_address=
+ data->shared_memory_base_address+
+ data->block_size*data->shared_memory_blocks;
+ data->filled_blocks=1;
+ VALIDATE(tme->validated_blocks,block);
+ tme->active=block;
+ tme->working=block;
+ return TME_SUCCESS;
+}
+
+/* I/F between the bpf machine and the callbacks, just some checks */
+uint32 lookup_frontend(MEM_TYPE *mem_ex, TME_CORE *tme,uint32 mem_ex_offset, struct time_conv *time_ref)
+{
+ if (tme->active==TME_NONE_ACTIVE)
+ return TME_FALSE;
+
+ return (tme->block_data[tme->active].lookup_code)(mem_ex_offset+mem_ex->buffer,&tme->block_data[tme->active],mem_ex, time_ref);
+}
+
+/* I/F between the bpf machine and the callbacks, just some checks */
+uint32 execute_frontend(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 pkt_size, uint32 offset)
+{
+
+ exec_fcn tmp;
+ TME_DATA *data;
+ uint8 *block;
+ uint8 *mem_data;
+
+ if (tme->active==TME_NONE_ACTIVE)
+ return TME_ERROR;
+
+ data=&tme->block_data[tme->active];
+
+ if (data->last_found==NULL)
+ { /*out lut exec */
+ tmp=exec_fcn_mapper(data->out_lut_exec);
+ block=data->shared_memory_base_address;
+ }
+ else
+ { /*checks if last_found is valid */
+ if ((data->last_foundlut_base_address)||(data->last_found>=data->shared_memory_base_address))
+ return TME_ERROR;
+ else
+ {
+ tmp=exec_fcn_mapper(SW_ULONG_AT(&((RECORD*)data->last_found)->exec_fcn,0));
+ if (tmp==NULL)
+ return TME_ERROR;
+ block=SW_ULONG_AT(&((RECORD*)data->last_found)->block,0)+mem_ex->buffer;
+ if ((blockshared_memory_base_address)||(block>=data->extra_segment_base_address))
+ return TME_ERROR;
+ }
+ }
+
+ if (offset>=mem_ex->size)
+ return TME_ERROR;
+
+ mem_data=mem_ex->buffer+offset;
+
+ return tmp(block,pkt_size,data,mem_ex,mem_data);
+}
+
+/*resets all the TME core*/
+uint32 reset_tme(TME_CORE *tme)
+{
+ if (tme==NULL)
+ return TME_ERROR;
+ ZERO_MEMORY(tme, sizeof(TME_CORE));
+ return TME_SUCCESS;
+}
+
+/* returns a register value of the active TME block */
+/* FIXME last found in maniera elegante e veloce ?!?! */
+uint32 get_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 *rval)
+{
+ switch(rgstr)
+ {
+ case TME_LUT_ENTRIES:
+ *rval=data->lut_entries;
+ return TME_SUCCESS;
+ case TME_MAX_FILL_STATE:
+ *rval=data->max_fill_state;
+ return TME_SUCCESS;
+ case TME_REHASHING_VALUE:
+ *rval=data->rehashing_value;
+ return TME_SUCCESS;
+ case TME_KEY_LEN:
+ *rval=data->key_len;
+ return TME_SUCCESS;
+ case TME_SHARED_MEMORY_BLOCKS:
+ *rval=data->shared_memory_blocks;
+ return TME_SUCCESS;
+ case TME_FILLED_ENTRIES:
+ *rval=data->filled_entries;
+ return TME_SUCCESS;
+ case TME_BLOCK_SIZE:
+ *rval=data->block_size;
+ return TME_SUCCESS;
+ case TME_EXTRA_SEGMENT_SIZE:
+ *rval=data->extra_segment_size;
+ return TME_SUCCESS;
+ case TME_FILLED_BLOCKS:
+ *rval=data->filled_blocks;
+ return TME_SUCCESS;
+ case TME_DEFAULT_EXEC:
+ *rval=data->default_exec;
+ return TME_SUCCESS;
+ case TME_OUT_LUT_EXEC:
+ *rval=data->out_lut_exec;
+ return TME_SUCCESS;
+ case TME_SHARED_MEMORY_BASE_ADDRESS:
+ *rval=data->shared_memory_base_address-mem_ex->buffer;
+ return TME_SUCCESS;
+ case TME_LUT_BASE_ADDRESS:
+ *rval=data->lut_base_address-mem_ex->buffer;
+ return TME_SUCCESS;
+ case TME_EXTRA_SEGMENT_BASE_ADDRESS:
+ *rval=data->extra_segment_base_address-mem_ex->buffer;
+ return TME_SUCCESS;
+ case TME_LAST_FOUND_BLOCK:
+ if (data->last_found==NULL)
+ *rval=0;
+ else
+ *rval=data->last_found-mem_ex->buffer;
+ return TME_SUCCESS;
+
+ default:
+ return TME_ERROR;
+ }
+}
+
+/* sets a register value in the active block */
+/* FIXME last found in maniera elegante e veloce ?!?! */
+uint32 set_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 value, int32 init)
+{ /* very very very dangerous!!!!!!!!!!! */
+ lut_fcn tmp;
+
+ UNUSED(mem_ex);
+
+ switch(rgstr)
+ {
+ case TME_MAX_FILL_STATE:
+ data->max_fill_state=value;
+ return TME_SUCCESS;
+ case TME_REHASHING_VALUE:
+ data->rehashing_value=value;
+ return TME_SUCCESS;
+ case TME_FILLED_ENTRIES:
+ data->filled_entries=value;
+ return TME_SUCCESS;
+ case TME_FILLED_BLOCKS:
+ if (value<=data->shared_memory_blocks)
+ {
+ data->filled_blocks=value;
+ return TME_SUCCESS;
+ }
+ else
+ return TME_ERROR;
+ case TME_DEFAULT_EXEC:
+ data->default_exec=value;
+ return TME_SUCCESS;
+ case TME_OUT_LUT_EXEC:
+ data->out_lut_exec=value;
+ return TME_SUCCESS;
+ case TME_LOOKUP_CODE:
+ tmp=lut_fcn_mapper(value);
+ if (tmp==NULL)
+ return TME_ERROR;
+ else
+ data->lookup_code=tmp;
+ return TME_SUCCESS;
+ default:
+ break;
+ }
+
+ if (init)
+ switch (rgstr)
+ {
+
+ case TME_LUT_ENTRIES:
+ data->lut_entries=value;
+ return TME_SUCCESS;
+ case TME_KEY_LEN:
+ data->key_len=value;
+ return TME_SUCCESS;
+ case TME_SHARED_MEMORY_BLOCKS:
+ data->shared_memory_blocks=value;
+ return TME_SUCCESS;
+ case TME_BLOCK_SIZE:
+ data->block_size=value;
+ return TME_SUCCESS;
+ case TME_EXTRA_SEGMENT_SIZE:
+ data->extra_segment_size=value;
+ return TME_SUCCESS;
+ default:
+ return TME_ERROR;
+ }
+ else
+ return TME_ERROR;
+
+}
+
+/* chooses the TME block for read */
+uint32 set_active_read_tme_block(TME_CORE *tme, uint32 block)
+{
+
+ if ((block>=MAX_TME_DATA_BLOCKS)||(!IS_VALIDATED(tme->validated_blocks,block)))
+ return TME_ERROR;
+ tme->active_read=block;
+ return TME_SUCCESS;
+
+}
+
+/* chooses if the autodeletion must be used */
+uint32 set_autodeletion(TME_DATA *data, uint32 value)
+{
+ if (value==0) /* no autodeletion */
+ data->enable_deletion=FALSE;
+ else
+ data->enable_deletion=TRUE;
+
+ return TME_SUCCESS;
+}
\ No newline at end of file
diff --git a/drivers/3rdparty/npf/tme.h b/drivers/3rdparty/npf/tme.h
new file mode 100644
index 0000000000000..41e46326ba2f7
--- /dev/null
+++ b/drivers/3rdparty/npf/tme.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * 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 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.
+ *
+ */
+
+#ifndef __tme_include_
+#define __tme_include_
+
+#ifdef WIN_NT_DRIVER
+#include "ndis.h"
+#else
+#include
+#endif /*WIN_NT_DRIVER*/
+
+#include "memory_t.h"
+#include "time_calls.h"
+
+
+/* error codes */
+#define TME_ERROR 0
+#define TME_SUCCESS 1
+#define TME_TRUE 2
+#define TME_FALSE 3
+
+/* some constants */
+#define DEFAULT_MEM_EX_SIZE 65536
+#define MAX_TME_DATA_BLOCKS 4
+#define TME_NONE_ACTIVE 0xffffffff
+#define DELTA_READ 2 /* secs */
+
+#define TME_LUT_ENTRIES 0x00000000
+#define TME_MAX_FILL_STATE 0x00000001 /*potrebbe servire per un thread a passive level!?!?! */
+#define TME_REHASHING_VALUE 0x00000002
+#define TME_KEY_LEN 0x00000003
+#define TME_SHARED_MEMORY_BLOCKS 0x00000004
+#define TME_FILLED_ENTRIES 0x00000005
+#define TME_BLOCK_SIZE 0x00000006
+#define TME_EXTRA_SEGMENT_SIZE 0x00000007
+#define TME_LOOKUP_CODE 0x00000008
+#define TME_OUT_LUT_EXEC 0x00000009
+#define TME_FILLED_BLOCKS 0x0000000a
+#define TME_DEFAULT_EXEC 0x0000000b
+#define TME_LUT_BASE_ADDRESS 0x0000000c
+#define TME_SHARED_MEMORY_BASE_ADDRESS 0x0000000d
+#define TME_EXTRA_SEGMENT_BASE_ADDRESS 0x0000000e
+#define TME_LAST_FOUND 0x0000000f /* contains the offset of the last found entry */
+#define TME_LAST_FOUND_BLOCK 0x00000010
+/* TME default values */
+#define TME_LUT_ENTRIES_DEFAULT 32007
+#define TME_REHASHING_VALUE_DEFAULT 1
+#define TME_SHARED_MEMORY_BLOCKS_DEFAULT 16000
+#define TME_BLOCK_SIZE_DEFAULT 64
+#define TME_EXTRA_SEGMENT_SIZE_DEFAULT 0
+#define TME_LOOKUP_CODE_DEFAULT 0
+#define TME_OUT_LUT_EXEC_DEFAULT 0
+#define TME_DEFAULT_EXEC_DEFAULT 0
+#define TME_MAX_FILL_STATE_DEFAULT 15000
+
+#define IS_VALIDATED(src,index) (src&(1<tv_sec=0x7fffffff;
+
+struct __TME_DATA;
+
+/* TME callback prototypes */
+typedef uint32 (*lut_fcn)(uint8 *key, struct __TME_DATA *data,MEM_TYPE *mem_ex, struct time_conv *time_ref );
+typedef uint32 (*exec_fcn)(uint8 *block, uint32 pkt_size, struct __TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data);
+
+/* DO NOT MODIFY THIS STRUCTURE!!!! GV */
+typedef struct __RECORD
+
+{
+ uint32 block;
+ uint32 exec_fcn;
+}
+ RECORD, *PRECORD;
+
+/* TME data registers */
+struct __TME_DATA
+{
+ uint32 lut_entries;
+ uint32 max_fill_state;
+ uint32 rehashing_value;
+ uint32 key_len;
+ uint32 shared_memory_blocks;
+ uint32 filled_entries;
+ uint32 block_size;
+ uint32 extra_segment_size;
+ uint32 filled_blocks;
+ lut_fcn lookup_code;
+ uint32 default_exec;
+ uint32 out_lut_exec;
+ uint8 *lut_base_address;
+ uint8 *shared_memory_base_address;
+ uint8 *extra_segment_base_address;
+ struct timeval last_read;
+ uint32 enable_deletion;
+ uint8 *last_found;
+};
+
+typedef struct __TME_DATA TME_DATA,*PTME_DATA;
+
+
+
+/* TME core */
+typedef struct __TME_CORE
+{
+ uint32 working;
+ uint32 active;
+ uint32 validated_blocks;
+ TME_DATA block_data[MAX_TME_DATA_BLOCKS];
+ uint32 active_read;
+
+} TME_CORE, *PTME_CORE;
+
+static __inline int32 IS_DELETABLE(void *timestamp, TME_DATA *data)
+{
+ struct timeval *ts=(struct timeval*)timestamp;
+
+ if (data->enable_deletion==FALSE)
+ return FALSE;
+ if (data->filled_entriesmax_fill_state)
+ return FALSE;
+ if ((ts->tv_sec+DELTA_READ)last_read.tv_sec)
+ return TRUE;
+ return FALSE;
+}
+
+/* functions to manage TME */
+uint32 init_tme_block(TME_CORE *tme, uint32 block);
+uint32 validate_tme_block(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 block, uint32 mem_ex_offset);
+uint32 lookup_frontend(MEM_TYPE *mem_ex, TME_CORE *tme,uint32 mem_ex_offset, struct time_conv *time_ref);
+uint32 execute_frontend(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 pkt_size,uint32 offset);
+uint32 set_active_tme_block(TME_CORE *tme, uint32 block);
+uint32 init_extended_memory(uint32 size, MEM_TYPE *mem_ex);
+uint32 reset_tme(TME_CORE *tme);
+uint32 get_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 *rval);
+uint32 set_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 value, int32 init);
+uint32 set_active_read_tme_block(TME_CORE *tme, uint32 block);
+uint32 set_autodeletion(TME_DATA *data, uint32 value);
+
+/* function mappers */
+lut_fcn lut_fcn_mapper(uint32 index);
+exec_fcn exec_fcn_mapper(uint32 index);
+
+#endif
\ No newline at end of file
diff --git a/drivers/3rdparty/npf/valid_insns.h b/drivers/3rdparty/npf/valid_insns.h
new file mode 100644
index 0000000000000..a1c0e0410eab5
--- /dev/null
+++ b/drivers/3rdparty/npf/valid_insns.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2001 - 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.
+ *
+ */
+
+u_short valid_instructions[]=
+ {
+ BPF_RET|BPF_K,
+ BPF_RET|BPF_A,
+ BPF_LD|BPF_IMM,
+ BPF_LDX|BPF_IMM,
+ BPF_LD|BPF_MEM,
+ BPF_LDX|BPF_MEM,
+
+#ifdef HAVE_BUGGY_TME_SUPPORT
+ BPF_LD|BPF_MEM_EX_IMM|BPF_B,
+ BPF_LD|BPF_MEM_EX_IMM|BPF_H,
+ BPF_LD|BPF_MEM_EX_IMM|BPF_W,
+ BPF_LD|BPF_MEM_EX_IND|BPF_B,
+ BPF_LD|BPF_MEM_EX_IND|BPF_H,
+ BPF_LD|BPF_MEM_EX_IND|BPF_W,
+#endif //HAVE_BUGGY_TME_SUPPORT
+ BPF_LD|BPF_W|BPF_ABS,
+ BPF_LD|BPF_H|BPF_ABS,
+ BPF_LD|BPF_B|BPF_ABS,
+ BPF_LDX|BPF_W|BPF_ABS,
+ BPF_LDX|BPF_H|BPF_ABS,
+ BPF_LDX|BPF_B|BPF_ABS,
+ BPF_LD|BPF_W|BPF_LEN,
+ BPF_LDX|BPF_W|BPF_LEN,
+ BPF_LD|BPF_W|BPF_IND,
+ BPF_LD|BPF_H|BPF_IND,
+ BPF_LD|BPF_B|BPF_IND,
+ BPF_LDX|BPF_MSH|BPF_B,
+ BPF_ST,
+ BPF_STX,
+
+#ifdef HAVE_BUGGY_TME_SUPPORT
+ BPF_ST|BPF_MEM_EX_IMM|BPF_B,
+ BPF_STX|BPF_MEM_EX_IMM|BPF_B,
+ BPF_ST|BPF_MEM_EX_IMM|BPF_W,
+ BPF_STX|BPF_MEM_EX_IMM|BPF_W,
+ BPF_ST|BPF_MEM_EX_IMM|BPF_H,
+ BPF_STX|BPF_MEM_EX_IMM|BPF_H,
+ BPF_ST|BPF_MEM_EX_IND|BPF_B,
+ BPF_ST|BPF_MEM_EX_IND|BPF_W,
+ BPF_ST|BPF_MEM_EX_IND|BPF_H,
+#endif // HAVE_BUGGY_TME_SUPPORT
+
+ BPF_JMP|BPF_JA,
+ BPF_JMP|BPF_JGT|BPF_K,
+ BPF_JMP|BPF_JGE|BPF_K,
+ BPF_JMP|BPF_JEQ|BPF_K,
+ BPF_JMP|BPF_JSET|BPF_K,
+ BPF_JMP|BPF_JGT|BPF_X,
+ BPF_JMP|BPF_JGE|BPF_X,
+ BPF_JMP|BPF_JEQ|BPF_X,
+ BPF_JMP|BPF_JSET|BPF_X,
+ BPF_ALU|BPF_ADD|BPF_X,
+ BPF_ALU|BPF_SUB|BPF_X,
+ BPF_ALU|BPF_MUL|BPF_X,
+ BPF_ALU|BPF_DIV|BPF_X,
+ BPF_ALU|BPF_AND|BPF_X,
+ BPF_ALU|BPF_OR|BPF_X,
+ BPF_ALU|BPF_LSH|BPF_X,
+ BPF_ALU|BPF_RSH|BPF_X,
+ BPF_ALU|BPF_ADD|BPF_K,
+ BPF_ALU|BPF_SUB|BPF_K,
+ BPF_ALU|BPF_MUL|BPF_K,
+ BPF_ALU|BPF_DIV|BPF_K,
+ BPF_ALU|BPF_AND|BPF_K,
+ BPF_ALU|BPF_OR|BPF_K,
+ BPF_ALU|BPF_LSH|BPF_K,
+ BPF_ALU|BPF_RSH|BPF_K,
+ BPF_ALU|BPF_NEG,
+ BPF_MISC|BPF_TAX,
+ BPF_MISC|BPF_TXA,
+
+#ifdef HAVE_BUGGY_TME_SUPPORT
+ BPF_MISC|BPF_TME|BPF_LOOKUP,
+ BPF_MISC|BPF_TME|BPF_EXECUTE,
+ BPF_MISC|BPF_TME|BPF_SET_ACTIVE,
+ BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE,
+ BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE
+#endif //HAVE_BUGGY_TME_SUPPORT
+
+ };
+
+#define VALID_INSTRUCTIONS_LEN (sizeof(valid_instructions)/sizeof(u_short))
diff --git a/drivers/3rdparty/npf/win_bpf.h b/drivers/3rdparty/npf/win_bpf.h
new file mode 100644
index 0000000000000..ed5d4bceed46f
--- /dev/null
+++ b/drivers/3rdparty/npf/win_bpf.h
@@ -0,0 +1,436 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ * @(#)bpf.h 7.1 (Berkeley) 5/7/91
+ *
+ * @(#) $Header: /usr/cvsroot_private/winpcap/packetNtx/driver/win_bpf.h,v 1.4 2007/11/12 23:12:12 gianlucav Exp $ (LBL)
+ */
+
+#ifndef BPF_MAJOR_VERSION
+
+/* BSD style release date */
+#define BPF_RELEASE 199606
+
+#ifdef WIN_NT_DRIVER
+#include
+#endif
+
+#ifdef HAVE_BUGGY_TME_SUPPORT
+#include "tme.h"
+#endif
+#include "time_calls.h"
+
+typedef UCHAR u_char;
+typedef USHORT u_short;
+
+#ifdef WIN_NT_DRIVER
+typedef ULONG u_int;
+#endif
+
+typedef LONG bpf_int32;
+typedef ULONG bpf_u_int32;
+typedef ULONG u_int32;
+
+#define BPF_MAXINSNS 512
+#define BPF_MAXBUFSIZE 0x8000
+#define BPF_MINBUFSIZE 32
+
+/*
+ * The instruction data structure.
+ */
+struct bpf_insn {
+ u_short code;
+ u_char jt;
+ u_char jf;
+ bpf_u_int32 k;
+};
+
+/*
+ * Structure for BIOCSETF.
+ */
+struct bpf_program {
+ u_int bf_len;
+ struct bpf_insn *bf_insns;
+};
+
+/*
+ * Struct returned by BIOCGSTATS.
+ */
+struct bpf_stat {
+ UINT bs_recv; ///< Number of packets that the driver received from the network adapter
+ ///< from the beginning of the current capture. This value includes the packets
+ ///< lost by the driver.
+ UINT bs_drop; ///< number of packets that the driver lost from the beginning of a capture.
+ ///< Basically, a packet is lost when the the buffer of the driver is full.
+ ///< In this situation the packet cannot be stored and the driver rejects it.
+ UINT ps_ifdrop; ///< drops by interface. XXX not yet supported
+ UINT bs_capt; ///< number of packets that pass the filter, find place in the kernel buffer and
+ ///< thus reach the application.
+};
+
+/*
+ * Struct return by BIOCVERSION. This represents the version number of
+ * the filter language described by the instruction encodings below.
+ * bpf understands a program iff kernel_major == filter_major &&
+ * kernel_minor >= filter_minor, that is, if the value returned by the
+ * running kernel has the same major number and a minor number equal
+ * equal to or less than the filter being downloaded. Otherwise, the
+ * results are undefined, meaning an error may be returned or packets
+ * may be accepted haphazardly.
+ * It has nothing to do with the source code version.
+ */
+struct bpf_version {
+ u_short bv_major;
+ u_short bv_minor;
+};
+/* Current version number of filter architecture. */
+#define BPF_MAJOR_VERSION 1
+#define BPF_MINOR_VERSION 1
+
+
+/*
+ * Structure prepended to each packet.
+ */
+struct bpf_hdr {
+ struct timeval bh_tstamp; /* time stamp */
+ bpf_u_int32 bh_caplen; /* length of captured portion */
+ bpf_u_int32 bh_datalen; /* original length of packet */
+ u_short bh_hdrlen; /* length of bpf header (this struct
+ plus alignment padding) */
+};
+
+/*
+ * Data-link level type codes.
+ */
+
+/*
+ * These are the types that are the same on all platforms; on other
+ * platforms, a should be supplied that defines the additional
+ * DLT_* codes appropriately for that platform (the BSDs, for example,
+ * should not just pick up this version of "bpf.h"; they should also define
+ * the additional DLT_* codes used by their kernels, as well as the values
+ * defined here - and, if the values they use for particular DLT_ types
+ * differ from those here, they should use their values, not the ones
+ * here).
+ */
+#define DLT_NULL 0 /* no link-layer encapsulation */
+#define DLT_EN10MB 1 /* Ethernet (10Mb) */
+#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */
+#define DLT_AX25 3 /* Amateur Radio AX.25 */
+#define DLT_PRONET 4 /* Proteon ProNET Token Ring */
+#define DLT_CHAOS 5 /* Chaos */
+#define DLT_IEEE802 6 /* IEEE 802 Networks */
+#define DLT_ARCNET 7 /* ARCNET */
+#define DLT_SLIP 8 /* Serial Line IP */
+#define DLT_PPP 9 /* Point-to-point Protocol */
+#define DLT_FDDI 10 /* FDDI */
+
+/*
+ * These are values from the traditional libpcap "bpf.h".
+ * Ports of this to particular platforms should replace these definitions
+ * with the ones appropriate to that platform, if the values are
+ * different on that platform.
+ */
+#define DLT_ATM_RFC1483 11 /* LLC/SNAP encapsulated atm */
+#define DLT_RAW 12 /* raw IP */
+
+/*
+ * These are values from BSD/OS's "bpf.h".
+ * These are not the same as the values from the traditional libpcap
+ * "bpf.h"; however, these values shouldn't be generated by any
+ * OS other than BSD/OS, so the correct values to use here are the
+ * BSD/OS values.
+ *
+ * Platforms that have already assigned these values to other
+ * DLT_ codes, however, should give these codes the values
+ * from that platform, so that programs that use these codes will
+ * continue to compile - even though they won't correctly read
+ * files of these types.
+ */
+#define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */
+#define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */
+
+#define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */
+
+/*
+ * This value is defined by NetBSD; other platforms should refrain from
+ * using it for other purposes, so that NetBSD savefiles with a link
+ * type of 50 can be read as this type on all platforms.
+ */
+#define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */
+
+/*
+ * This value was defined by libpcap 0.5; platforms that have defined
+ * it with a different value should define it here with that value -
+ * a link type of 104 in a save file will be mapped to DLT_C_HDLC,
+ * whatever value that happens to be, so programs will correctly
+ * handle files with that link type regardless of the value of
+ * DLT_C_HDLC.
+ *
+ * The name DLT_C_HDLC was used by BSD/OS; we use that name for source
+ * compatibility with programs written for BSD/OS.
+ *
+ * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well,
+ * for source compatibility with programs written for libpcap 0.5.
+ */
+#define DLT_C_HDLC 104 /* Cisco HDLC */
+#define DLT_CHDLC DLT_C_HDLC
+
+/*
+ * Reserved for future use.
+ * Do not pick other numerical value for these unless you have also
+ * picked up the tcpdump.org top-of-CVS-tree version of "savefile.c",
+ * which will arrange that capture files for these DLT_ types have
+ * the same "network" value on all platforms, regardless of what
+ * value is chosen for their DLT_ type (thus allowing captures made
+ * on one platform to be read on other platforms, even if the two
+ * platforms don't use the same numerical values for all DLT_ types).
+ */
+#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */
+
+/*
+ * Values between 106 and 107 are used in capture file headers as
+ * link-layer types corresponding to DLT_ types that might differ
+ * between platforms; don't use those values for new DLT_ new types.
+ */
+
+/*
+ * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except
+ * that the AF_ type in the link-layer header is in network byte order.
+ *
+ * OpenBSD defines it as 12, but that collides with DLT_RAW, so we
+ * define it as 108 here. If OpenBSD picks up this file, it should
+ * define DLT_LOOP as 12 in its version, as per the comment above -
+ * and should not use 108 for any purpose.
+ */
+#define DLT_LOOP 108
+
+/*
+ * Values between 109 and 112 are used in capture file headers as
+ * link-layer types corresponding to DLT_ types that might differ
+ * between platforms; don't use those values for new DLT_ new types.
+ */
+
+/*
+ * This is for Linux cooked sockets.
+ */
+#define DLT_LINUX_SLL 113
+
+/*
+ * The instruction encodings.
+ */
+/* instruction classes */
+#define BPF_CLASS(code) ((code) & 0x07)
+#define BPF_LD 0x00
+#define BPF_LDX 0x01
+#define BPF_ST 0x02
+#define BPF_STX 0x03
+#define BPF_ALU 0x04
+#define BPF_JMP 0x05
+#define BPF_RET 0x06
+#define BPF_MISC 0x07
+
+/* ld/ldx fields */
+#define BPF_SIZE(code) ((code) & 0x18)
+#define BPF_W 0x00
+#define BPF_H 0x08
+#define BPF_B 0x10
+#define BPF_MODE(code) ((code) & 0xe0)
+#define BPF_IMM 0x00
+#define BPF_ABS 0x20
+#define BPF_IND 0x40
+#define BPF_MEM 0x60
+#define BPF_LEN 0x80
+#define BPF_MSH 0xa0
+
+/* alu/jmp fields */
+#define BPF_OP(code) ((code) & 0xf0)
+#define BPF_ADD 0x00
+#define BPF_SUB 0x10
+#define BPF_MUL 0x20
+#define BPF_DIV 0x30
+#define BPF_OR 0x40
+#define BPF_AND 0x50
+#define BPF_LSH 0x60
+#define BPF_RSH 0x70
+#define BPF_NEG 0x80
+#define BPF_JA 0x00
+#define BPF_JEQ 0x10
+#define BPF_JGT 0x20
+#define BPF_JGE 0x30
+#define BPF_JSET 0x40
+#define BPF_SRC(code) ((code) & 0x08)
+#define BPF_K 0x00
+#define BPF_X 0x08
+
+/* ret - BPF_K and BPF_X also apply */
+#define BPF_RVAL(code) ((code) & 0x18)
+#define BPF_A 0x10
+
+/* misc */
+#define BPF_MISCOP(code) ((code) & 0xf8)
+#define BPF_TAX 0x00
+#define BPF_TXA 0x80
+
+/* TME instructions */
+#define BPF_TME 0x08
+
+#define BPF_LOOKUP 0x90
+#define BPF_EXECUTE 0xa0
+#define BPF_INIT 0xb0
+#define BPF_VALIDATE 0xc0
+#define BPF_SET_ACTIVE 0xd0
+#define BPF_RESET 0xe0
+#define BPF_SET_MEMORY 0x80
+#define BPF_GET_REGISTER_VALUE 0x70
+#define BPF_SET_REGISTER_VALUE 0x60
+#define BPF_SET_WORKING 0x50
+#define BPF_SET_ACTIVE_READ 0x40
+#define BPF_SET_AUTODELETION 0x30
+#define BPF_SEPARATION 0xff
+
+#define BPF_MEM_EX_IMM 0xc0
+#define BPF_MEM_EX_IND 0xe0
+/*used for ST */
+#define BPF_MEM_EX 0xc0
+
+
+/*
+ * Macros for insn array initializers.
+ */
+#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k }
+#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k }
+
+/*
+ * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST).
+ */
+#define BPF_MEMWORDS 16
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*!
+ \brief Validates a filtering program arriving from the user-level app.
+ \param f The filter.
+ \param len Its length, in pseudo instructions.
+ \param mem_ex_size The length of the extended memory, used to validate LD/ST to that memory
+ \return true if f is a valid filter program..
+
+ The kernel needs to be able to verify an application's filter code. Otherwise, a bogus program could easily
+ crash the system.
+ This function returns true if f is a valid filter program. The constraints are that each jump be forward and
+ to a valid code. The code must terminate with either an accept or reject.
+*/
+#ifdef HAVE_BUGGY_TME_SUPPORT
+int bpf_validate(struct bpf_insn *f,int len, uint32 mem_ex_size);
+#else //HAVE_BUGGY_TME_SUPPORT
+int bpf_validate(struct bpf_insn *f,int len);
+#endif //HAVE_BUGGY_TME_SUPPORT
+
+/*!
+ \brief The filtering pseudo-machine interpreter.
+ \param pc The filter.
+ \param p Pointer to a memory buffer containing the packet on which the filter will be executed.
+ \param wirelen Original length of the packet.
+ \param buflen Current length of the packet. In some cases (for example when the transfer of the packet to the RAM
+ has not yet finished), bpf_filter can be executed on a portion of the packet.
+ \param mem_ex The extended memory.
+ \param tme The virtualization of the TME co-processor
+ \param time_ref Data structure needed by the TME co-processor to timestamp data
+ \return The portion of the packet to keep, in bytes. 0 means that the packet must be rejected, -1 means that
+ the whole packet must be kept.
+
+ \note this function is not used in normal situations, because the jitter creates a native filtering function
+ that is faster than the interpreter.
+*/
+#ifdef HAVE_BUGGY_TME_SUPPORT
+u_int bpf_filter(register struct bpf_insn *pc,
+ register UCHAR *p,
+ u_int wirelen,
+ register u_int buflen ,
+ PMEM_TYPE mem_ex,
+ PTME_CORE tme ,
+ struct time_conv *time_ref);
+#else //HAVE_BUGGY_TME_SUPPORT
+u_int bpf_filter(register struct bpf_insn *pc,
+ register UCHAR *p,
+ u_int wirelen,
+ register u_int buflen);
+#endif //HAVE_BUGGY_TME_SUPPORT
+/*!
+ \brief The filtering pseudo-machine interpreter with two buffers. This function is slower than bpf_filter(),
+ but works correctly also if the MAC header and the data of the packet are in two different buffers.
+ \param pc The filter.
+ \param p Pointer to a memory buffer containing the MAC header of the packet.
+ \param pd Pointer to a memory buffer containing the data of the packet.
+ \param wirelen Original length of the packet.
+ \param buflen Current length of the packet. In some cases (for example when the transfer of the packet to the RAM
+ has not yet finished), bpf_filter can be executed on a portion of the packet.
+ \param mem_ex The extended memory.
+ \param tme The virtualization of the TME co-processor
+ \param time_ref Data structure needed by the TME co-processor to timestamp data
+ \return The portion of the packet to keep, in bytes. 0 means that the packet must be rejected, -1 means that
+ the whole packet must be kept.
+
+ This function is used when NDIS passes the packet to NPF_tap() in two buffers instaed than in a single one.
+*/
+#ifdef HAVE_BUGGY_TME_SUPPORT
+u_int bpf_filter_with_2_buffers(register struct bpf_insn *pc,
+ register u_char *p,
+ register u_char *pd,
+ register int headersize,
+ u_int wirelen,
+ register u_int buflen,
+ PMEM_TYPE mem_ex,
+ PTME_CORE tme,
+ struct time_conv *time_ref);
+#else //HAVE_BUGGY_TME_SUPPORT
+u_int bpf_filter_with_2_buffers(register struct bpf_insn *pc,
+ register u_char *p,
+ register u_char *pd,
+ register int headersize,
+ u_int wirelen,
+ register u_int buflen);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/drivers/3rdparty/npf/win_bpf_filter.c b/drivers/3rdparty/npf/win_bpf_filter.c
new file mode 100644
index 0000000000000..eb0bb958cc4ee
--- /dev/null
+++ b/drivers/3rdparty/npf/win_bpf_filter.c
@@ -0,0 +1,1149 @@
+/*
+ * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2007 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.
+ *
+ */
+
+#ifndef WIN_NT_DRIVER
+#include
+#else
+#include
+#endif
+
+#pragma warning(disable : 4131) //old style function declaration
+#pragma warning(disable : 4127) // conditional expr is constant (used for while(1) loops)
+#pragma warning(disable : 4213) //cast on l-value
+
+#ifndef UNUSED
+#define UNUSED(_x) (_x)
+#endif
+
+#include "win_bpf.h"
+
+#include "debug.h"
+
+#include "valid_insns.h"
+
+#define EXTRACT_SHORT(p)\
+ ((((u_short)(((u_char*)p)[0])) << 8) |\
+ (((u_short)(((u_char*)p)[1])) << 0))
+
+#define EXTRACT_LONG(p)\
+ ((((u_int32)(((u_char*)p)[0])) << 24) |\
+ (((u_int32)(((u_char*)p)[1])) << 16) |\
+ (((u_int32)(((u_char*)p)[2])) << 8 ) |\
+ (((u_int32)(((u_char*)p)[3])) << 0 ))
+
+#ifdef HAVE_BUGGY_TME_SUPPORT
+u_int bpf_filter(pc, p, wirelen, buflen,mem_ex,tme,time_ref)
+ register struct bpf_insn *pc;
+ register u_char *p;
+ u_int wirelen;
+ register u_int buflen;
+ PMEM_TYPE mem_ex;
+ PTME_CORE tme;
+ struct time_conv *time_ref;
+#else //HAVE_BUGGY_TME_SUPPORT
+u_int bpf_filter(pc, p, wirelen, buflen)
+ register struct bpf_insn *pc;
+ register u_char *p;
+ u_int wirelen;
+ register u_int buflen;
+#endif //HAVE_BUGGY_TME_SUPPORT
+
+{
+ register u_int32 A, X;
+ register bpf_u_int32 k;
+
+#ifdef HAVE_BUGGY_TME_SUPPORT
+ u_int32 j,tmp;
+ u_short tmp2;
+#endif //HAVE_BUGGY_TME_SUPPORT
+
+ int mem[BPF_MEMWORDS];
+
+ RtlZeroMemory(mem, sizeof(mem));
+
+ if (pc == 0)
+ /*
+ * No filter means accept all.
+ */
+ return (u_int)-1;
+ A = 0;
+ X = 0;
+ --pc;
+ while (1) {
+ ++pc;
+ switch (pc->code) {
+
+ default:
+
+ return 0;
+
+ case BPF_RET|BPF_K:
+ return (u_int)pc->k;
+
+ case BPF_RET|BPF_A:
+ return (u_int)A;
+
+ case BPF_LD|BPF_W|BPF_ABS:
+ k = pc->k;
+ if (k >= buflen || k + sizeof(int) > buflen) {
+ return 0;
+ }
+ A = EXTRACT_LONG(&p[k]);
+ continue;
+
+ case BPF_LD|BPF_H|BPF_ABS:
+ k = pc->k;
+ if (k >= buflen || k + sizeof(short) > buflen) {
+ return 0;
+ }
+ A = EXTRACT_SHORT(&p[k]);
+ continue;
+
+ case BPF_LD|BPF_B|BPF_ABS:
+ k = pc->k;
+ if (k >= buflen) {
+ return 0;
+ }
+ A = p[k];
+ continue;
+
+ case BPF_LD|BPF_W|BPF_LEN:
+ A = wirelen;
+ continue;
+
+ case BPF_LDX|BPF_W|BPF_LEN:
+ X = wirelen;
+ continue;
+
+ case BPF_LD|BPF_W|BPF_IND:
+ k = X + pc->k;
+ if (k >= buflen || k + sizeof(int) > buflen) {
+ return 0;
+ }
+ A = EXTRACT_LONG(&p[k]);
+ continue;
+
+ case BPF_LD|BPF_H|BPF_IND:
+ k = X + pc->k;
+ if (k >= buflen || k + sizeof(short) > buflen) {
+ return 0;
+ }
+ A = EXTRACT_SHORT(&p[k]);
+ continue;
+
+ case BPF_LD|BPF_B|BPF_IND:
+ k = X + pc->k;
+ if (k >= buflen) {
+ return 0;
+ }
+ A = p[k];
+ continue;
+
+ case BPF_LDX|BPF_MSH|BPF_B:
+ k = pc->k;
+ if (k >= buflen) {
+ return 0;
+ }
+ X = (p[pc->k] & 0xf) << 2;
+ continue;
+
+ case BPF_LD|BPF_IMM:
+ A = pc->k;
+ continue;
+
+ case BPF_LDX|BPF_IMM:
+ X = pc->k;
+ continue;
+
+ case BPF_LD|BPF_MEM:
+ A = mem[pc->k];
+ continue;
+
+ case BPF_LDX|BPF_MEM:
+ X = mem[pc->k];
+ continue;
+
+#ifdef HAVE_BUGGY_TME_SUPPORT
+ //
+ // these instructions use the TME extensions,
+ // not supported on x86-64 and IA64 architectures.
+ //
+
+ /* LD NO PACKET INSTRUCTIONS */
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_B:
+ A= mem_ex->buffer[pc->k];
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_B:
+ X= mem_ex->buffer[pc->k];
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_H:
+ A = EXTRACT_SHORT(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_H:
+ X = EXTRACT_SHORT(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_W:
+ A = EXTRACT_LONG(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_W:
+ X = EXTRACT_LONG(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_B:
+ k = X + pc->k;
+ if ((int32)k>= (int32)mem_ex->size) {
+ return 0;
+ }
+ A= mem_ex->buffer[k];
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_H:
+ k = X + pc->k;
+ if ((int32)(k+1)>= (int32)mem_ex->size) {
+ return 0;
+ }
+ A=EXTRACT_SHORT((uint32*)&mem_ex->buffer[k]);
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_W:
+ k = X + pc->k;
+ if ((int32)(k+3)>= (int32)mem_ex->size) {
+ return 0;
+ }
+ A=EXTRACT_LONG((uint32*)&mem_ex->buffer[k]);
+ continue;
+ /* END LD NO PACKET INSTRUCTIONS */
+
+#endif //HAVE_BUGGY_TME_SUPPORT
+
+ case BPF_ST:
+ mem[pc->k] = A;
+ continue;
+
+ case BPF_STX:
+ mem[pc->k] = X;
+ continue;
+
+#ifdef HAVE_BUGGY_TME_SUPPORT
+ //
+ // these instructions use the TME extensions,
+ // not supported on x86-64 and IA64 architectures.
+ //
+
+ /* STORE INSTRUCTIONS */
+
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_B:
+ mem_ex->buffer[pc->k]=(uint8)A;
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_B:
+ mem_ex->buffer[pc->k]=(uint8)X;
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_W:
+ tmp=A;
+ *(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp);
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_W:
+ tmp=X;
+ *(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp);
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16)A;
+ *(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2);
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16)X;
+ *(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2);
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_B:
+ mem_ex->buffer[pc->k+X]=(uint8)A;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_W:
+ tmp=A;
+ *(uint32*)&mem_ex->buffer[pc->k+X]=EXTRACT_LONG(&tmp);
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_H:
+ tmp2=(uint16)A;
+ *(uint16*)&mem_ex->buffer[pc->k+X]=EXTRACT_SHORT(&tmp2);
+ continue;
+
+ /* END STORE INSTRUCTIONS */
+
+#endif //HAVE_BUGGY_TME_SUPPORT
+
+ case BPF_JMP|BPF_JA:
+ pc += pc->k;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_K:
+ pc += ((int)A > (int)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_K:
+ pc += ((int)A >= (int)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_K:
+ pc += ((int)A == (int)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_K:
+ pc += (A & pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_X:
+ pc += (A > X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_X:
+ pc += (A >= X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_X:
+ pc += (A == X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_X:
+ pc += (A & X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_ALU|BPF_ADD|BPF_X:
+ A += X;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_X:
+ A -= X;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_X:
+ A *= X;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_X:
+ if (X == 0)
+ return 0;
+ A /= X;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_X:
+ A &= X;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_X:
+ A |= X;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_X:
+ A <<= X;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_X:
+ A >>= X;
+ continue;
+
+ case BPF_ALU|BPF_ADD|BPF_K:
+ A += pc->k;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_K:
+ A -= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_K:
+ A *= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_K:
+ A /= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_K:
+ A &= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_K:
+ A |= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_K:
+ A <<= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_K:
+ A >>= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_NEG:
+ (int)A = -((int)A);
+ continue;
+
+ case BPF_MISC|BPF_TAX:
+ X = A;
+ continue;
+
+ case BPF_MISC|BPF_TXA:
+ A = X;
+ continue;
+
+#ifdef HAVE_BUGGY_TME_SUPPORT
+ //
+ // these instructions use the TME extensions,
+ // not supported on x86-64 and IA64 architectures.
+ //
+
+ /* TME INSTRUCTIONS */
+
+ case BPF_MISC|BPF_TME|BPF_LOOKUP:
+ j=lookup_frontend(mem_ex,tme,pc->k,time_ref);
+ if (j==TME_ERROR)
+ return 0;
+ pc += (j == TME_TRUE) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_EXECUTE:
+ if (execute_frontend(mem_ex,tme,wirelen,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_ACTIVE:
+ if (set_active_tme_block(tme,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE:
+ if (get_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,&j)==TME_ERROR)
+ return 0;
+ A=j;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE:
+ if (set_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,A,FALSE)==TME_ERROR)
+ return 0;
+ continue;
+
+ /* END TME INSTRUCTIONS */
+#endif //HAVE_BUGGY_TME_SUPPORT
+
+
+ }
+ }
+}
+
+//-------------------------------------------------------------------
+
+#ifdef HAVE_BUGGY_TME_SUPPORT
+u_int bpf_filter_with_2_buffers(pc, p, pd, headersize, wirelen, buflen, mem_ex,tme,time_ref)
+ register struct bpf_insn *pc;
+ register u_char *p;
+ register u_char *pd;
+ register int headersize;
+ u_int wirelen;
+ register u_int buflen;
+ PMEM_TYPE mem_ex;
+ PTME_CORE tme;
+ struct time_conv *time_ref;
+#else //HAVE_BUGGY_TME_SUPPORT
+u_int bpf_filter_with_2_buffers(pc, p, pd, headersize, wirelen, buflen)
+ register struct bpf_insn *pc;
+ register u_char *p;
+ register u_char *pd;
+ register int headersize;
+ u_int wirelen;
+ register u_int buflen;
+#endif //HAVE_BUGGY_TME_SUPPORT
+ {
+ register u_int32 A, X;
+ register int k;
+ int mem[BPF_MEMWORDS];
+#ifdef HAVE_BUGGY_TME_SUPPORT
+ u_int32 j,tmp;
+ u_short tmp2;
+#endif //HAVE_BUGGY_TME_SUPPORT
+
+ RtlZeroMemory(mem, sizeof(mem));
+
+ if (pc == 0)
+ /*
+ * No filter means accept all.
+ */
+ return (u_int)-1;
+ A = 0;
+ X = 0;
+ --pc;
+ while (1) {
+ ++pc;
+ switch (pc->code) {
+
+ default:
+
+ return 0;
+
+ case BPF_RET|BPF_K:
+ return (u_int)pc->k;
+
+ case BPF_RET|BPF_A:
+ return (u_int)A;
+
+ case BPF_LD|BPF_W|BPF_ABS:
+ k = pc->k;
+ if (k + 4 > (int)buflen) {
+ return 0;
+ }
+
+ if(k + 4 <= headersize)
+ A = EXTRACT_LONG(&p[k]);
+ else if(k + 3 == headersize)
+ {
+ A= (u_int32)*((u_char *)p+k)<<24|
+ (u_int32)*((u_char *)p+k+1)<<16|
+ (u_int32)*((u_char *)p+k+2)<<8|
+ (u_int32)*((u_char *)pd+k-headersize);
+ }
+ else if(k + 2 == headersize)
+ {
+ A= (u_int32)*((u_char *)p+k)<<24|
+ (u_int32)*((u_char *)p+k+1)<<16|
+ (u_int32)*((u_char *)pd+k-headersize)<<8|
+ (u_int32)*((u_char *)pd+k-headersize+1);
+ }
+ else if(k + 1 == headersize){
+ A= (u_int32)*((u_char *)p+k)<<24|
+ (u_int32)*((u_char *)pd+k-headersize+1)<<16|
+ (u_int32)*((u_char *)pd+k-headersize+2)<<8|
+ (u_int32)*((u_char *)pd+k-headersize+3);
+ }
+ else
+ A = EXTRACT_LONG(&pd[k-headersize]);
+
+ continue;
+
+ case BPF_LD|BPF_H|BPF_ABS:
+ k = pc->k;
+ if (k + sizeof(short) > buflen)
+ {
+ return 0;
+ }
+
+ if(k + 2 <= headersize)
+ A = EXTRACT_SHORT(&p[k]);
+ else if(k + 1 == headersize)
+ {
+ A= (u_short)*((u_char *)p+k)<<8|
+ (u_short)*((u_char *)pd+k-headersize);
+ }
+ else
+ A = EXTRACT_SHORT(&pd[k-headersize]);
+
+ continue;
+
+ case BPF_LD|BPF_B|BPF_ABS:
+ k = pc->k;
+ if ((int)k >= (int)buflen) {
+ return 0;
+ }
+
+ if(k +(int) sizeof(char) <= headersize)
+ A = p[k];
+ else
+ A = pd[k-headersize];
+
+ continue;
+
+ case BPF_LD|BPF_W|BPF_LEN:
+ A = wirelen;
+ continue;
+
+ case BPF_LDX|BPF_W|BPF_LEN:
+ X = wirelen;
+ continue;
+
+ case BPF_LD|BPF_W|BPF_IND:
+ k = X + pc->k;
+ if (k + sizeof(int) > buflen) {
+ return 0;
+ }
+
+ if(k + 4 <= headersize)
+ A = EXTRACT_LONG(&p[k]);
+ else if(k + 3 == headersize)
+ {
+ A= (u_int32)*((u_char *)p+k)<<24|
+ (u_int32)*((u_char *)p+k+1)<<16|
+ (u_int32)*((u_char *)p+k+2)<<8|
+ (u_int32)*((u_char *)pd+k-headersize);
+ }
+ else if(k + 2 == headersize)
+ {
+ A= (u_int32)*((u_char *)p+k)<<24|
+ (u_int32)*((u_char *)p+k+1)<<16|
+ (u_int32)*((u_char *)pd+k-headersize)<<8|
+ (u_int32)*((u_char *)pd+k-headersize+1);
+ }
+ else if(k + 1 == headersize)
+ {
+ A= (u_int32)*((u_char *)p+k)<<24|
+ (u_int32)*((u_char *)pd+k-headersize+1)<<16|
+ (u_int32)*((u_char *)pd+k-headersize+2)<<8|
+ (u_int32)*((u_char *)pd+k-headersize+3);
+ }
+ else
+ A = EXTRACT_LONG(&pd[k-headersize]);
+
+ continue;
+
+ case BPF_LD|BPF_H|BPF_IND:
+ k = X + pc->k;
+ if (k + 2 > (int)buflen) {
+ return 0;
+ }
+
+ if(k + 2 <= headersize)
+ A = EXTRACT_SHORT(&p[k]);
+ else if(k +1 == headersize)
+ {
+ A= (u_short)*((u_char *)p+k)<<8|
+ (u_short)*((u_char *)pd+k-headersize);
+ }
+ else
+ A = EXTRACT_SHORT(&pd[k-headersize]);
+
+ continue;
+
+ case BPF_LD|BPF_B|BPF_IND:
+ k = X + pc->k;
+ if ((int)k >= (int)buflen) {
+ return 0;
+ }
+
+ if( k + 1 <= headersize)
+ A = p[k];
+ else
+ A = pd[k-headersize];
+
+ continue;
+
+ case BPF_LDX|BPF_MSH|BPF_B:
+ k = pc->k;
+ if ((int)k >= (int)buflen) {
+ return 0;
+ }
+
+ if( k + 1 <= headersize)
+ X = (p[k] & 0xf) << 2;
+ else
+ X = (pd[k-headersize] & 0xf) << 2;
+
+ continue;
+
+ case BPF_LD|BPF_IMM:
+ A = pc->k;
+ continue;
+
+ case BPF_LDX|BPF_IMM:
+ X = pc->k;
+ continue;
+
+ case BPF_LD|BPF_MEM:
+ A = mem[pc->k];
+ continue;
+
+ case BPF_LDX|BPF_MEM:
+ X = mem[pc->k];
+ continue;
+
+#ifdef HAVE_BUGGY_TME_SUPPORT
+ //
+ // these instructions use the TME extensions,
+ // not supported on x86-64 and IA64 architectures.
+ //
+
+ /* LD NO PACKET INSTRUCTIONS */
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_B:
+ A= mem_ex->buffer[pc->k];
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_B:
+ X= mem_ex->buffer[pc->k];
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_H:
+ A = EXTRACT_SHORT(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_H:
+ X = EXTRACT_SHORT(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_W:
+ A = EXTRACT_LONG(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_W:
+ X = EXTRACT_LONG(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_B:
+ k = X + pc->k;
+ if ((int32)k>= (int32)mem_ex->size) {
+ return 0;
+ }
+ A= mem_ex->buffer[k];
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_H:
+ k = X + pc->k;
+ if ((int32)(k+1)>= (int32)mem_ex->size) {
+ return 0;
+ }
+ A=EXTRACT_SHORT((uint32*)&mem_ex->buffer[k]);
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_W:
+ k = X + pc->k;
+ if ((int32)(k+3)>= (int32)mem_ex->size) {
+ return 0;
+ }
+ A=EXTRACT_LONG((uint32*)&mem_ex->buffer[k]);
+ continue;
+
+ /* END LD NO PACKET INSTRUCTIONS */
+
+#endif //HAVE_BUGGY_TME_SUPPORT
+
+ case BPF_ST:
+ mem[pc->k] = A;
+ continue;
+
+ case BPF_STX:
+ mem[pc->k] = X;
+ continue;
+
+#ifdef HAVE_BUGGY_TME_SUPPORT
+ //
+ // these instructions use the TME extensions,
+ // not supported on x86-64 and IA64 architectures.
+ //
+
+ /* STORE INSTRUCTIONS */
+
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_B:
+ mem_ex->buffer[pc->k]=(uint8)A;
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_B:
+ mem_ex->buffer[pc->k]=(uint8)X;
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_W:
+ tmp=A;
+ *(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp);
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_W:
+ tmp=X;
+ *(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp);
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16)A;
+ *(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2);
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16)X;
+ *(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2);
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_B:
+ mem_ex->buffer[pc->k+X]=(uint8)A;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_W:
+ tmp=A;
+ *(uint32*)&mem_ex->buffer[pc->k+X]=EXTRACT_LONG(&tmp);
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_H:
+ tmp2=(uint16)A;
+ *(uint16*)&mem_ex->buffer[pc->k+X]=EXTRACT_SHORT(&tmp2);
+ continue;
+
+ /* END STORE INSTRUCTIONS */
+
+#endif //HAVE_BUGGY_TME_SUPPORT
+
+ case BPF_JMP|BPF_JA:
+ pc += pc->k;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_K:
+ pc += ((int)A > (int)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_K:
+ pc += ((int)A >= (int)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_K:
+ pc += ((int)A == (int)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_K:
+ pc += (A & pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_X:
+ pc += (A > X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_X:
+ pc += (A >= X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_X:
+ pc += (A == X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_X:
+ pc += (A & X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_ALU|BPF_ADD|BPF_X:
+ A += X;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_X:
+ A -= X;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_X:
+ A *= X;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_X:
+ if (X == 0)
+ return 0;
+ A /= X;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_X:
+ A &= X;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_X:
+ A |= X;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_X:
+ A <<= X;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_X:
+ A >>= X;
+ continue;
+
+ case BPF_ALU|BPF_ADD|BPF_K:
+ A += pc->k;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_K:
+ A -= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_K:
+ A *= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_K:
+ A /= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_K:
+ A &= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_K:
+ A |= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_K:
+ A <<= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_K:
+ A >>= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_NEG:
+ (int)A = -((int)A);
+ continue;
+
+ case BPF_MISC|BPF_TAX:
+ X = A;
+ continue;
+
+ case BPF_MISC|BPF_TXA:
+ A = X;
+ continue;
+
+#ifdef HAVE_BUGGY_TME_SUPPORT
+ //
+ // these instructions use the TME extensions,
+ // not supported on x86-64 and IA64 architectures.
+ //
+
+ /* TME INSTRUCTIONS */
+
+ case BPF_MISC|BPF_TME|BPF_LOOKUP:
+ j=lookup_frontend(mem_ex,tme,pc->k,time_ref);
+ if (j==TME_ERROR)
+ return 0;
+ pc += (j == TME_TRUE) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_EXECUTE:
+ if (execute_frontend(mem_ex,tme,wirelen,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_ACTIVE:
+ if (set_active_tme_block(tme,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE:
+ if (get_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,&j)==TME_ERROR)
+ return 0;
+ A=j;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE:
+ if (set_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,A,FALSE)==TME_ERROR)
+ return 0;
+ continue;
+
+ /* END TME INSTRUCTIONS */
+
+#endif //HAVE_BUGGY_TME_SUPPORT
+
+ }
+ }
+}
+
+#ifdef HAVE_BUGGY_TME_SUPPORT
+int
+bpf_validate(f, len,mem_ex_size)
+ struct bpf_insn *f;
+ int len;
+ uint32 mem_ex_size;
+#else
+int
+bpf_validate(f, len)
+ struct bpf_insn *f;
+ int len;
+#endif //HAVE_BUGGY_TME_SUPPORT
+ {
+ register u_int32 i, from;
+ register int j;
+ register struct bpf_insn *p;
+ int flag;
+
+ if (len < 1)
+ return 0;
+
+ for (i = 0; i < (u_int32)len; ++i) {
+ p = &f[i];
+
+ TRACE_MESSAGE(PACKET_DEBUG_LOUD,"Validating program");
+
+ flag=0;
+ for(j=0;jcode==valid_instructions[j])
+ flag=1;
+ if (flag==0)
+ return 0;
+
+ TRACE_MESSAGE(PACKET_DEBUG_LOUD, "Validating program: no unknown instructions");
+
+ switch (BPF_CLASS(p->code)) {
+ /*
+ * Check that memory operations use valid addresses.
+ */
+ case BPF_LD:
+ case BPF_LDX:
+ switch (BPF_MODE(p->code)) {
+ case BPF_IMM:
+ break;
+ case BPF_ABS:
+ case BPF_IND:
+ case BPF_MSH:
+ break;
+ case BPF_MEM:
+ if (p->k >= BPF_MEMWORDS)
+ return 0;
+ break;
+ case BPF_LEN:
+ break;
+ default:
+ return 0;
+ }
+
+ TRACE_MESSAGE(PACKET_DEBUG_LOUD, "Validating program: no wrong LD memory locations");
+ break;
+
+ case BPF_ST:
+ case BPF_STX:
+
+#ifdef HAVE_BUGGY_TME_SUPPORT
+ //
+ // these instructions use the TME extensions,
+ // not supported on x86-64 and IA64 architectures.
+ //
+ if ((p->code &BPF_MEM_EX_IMM) == BPF_MEM_EX_IMM)
+ {
+ /*
+ * Check if key stores use valid addresses
+ */
+ switch (BPF_SIZE(p->code)) {
+
+ case BPF_W:
+ if (p->k+3 >= mem_ex_size)
+ return 0;
+ break;
+
+ case BPF_H:
+ if (p->k+1 >= mem_ex_size)
+ return 0;
+ break;
+
+ case BPF_B:
+ if (p->k >= mem_ex_size)
+ return 0;
+ break;
+ }
+ }
+ else
+ {
+ if ((p->code & BPF_MEM_EX_IND) != BPF_MEM_EX_IND)
+ {
+ if (p->k >= BPF_MEMWORDS)
+ return 0;
+ }
+ }
+#else // ! HAVE_BUGGY_TME_SUPPORT
+ if (p->k >= BPF_MEMWORDS)
+ return 0;
+#endif // HAVE_BUGGY_TME_SUPPORT
+
+ TRACE_MESSAGE(PACKET_DEBUG_LOUD,"Validating program: no wrong ST memory locations");
+ break;
+
+ case BPF_ALU:
+ switch (BPF_OP(p->code)) {
+ case BPF_ADD:
+ case BPF_SUB:
+ case BPF_MUL:
+ case BPF_OR:
+ case BPF_AND:
+ case BPF_LSH:
+ case BPF_RSH:
+ case BPF_NEG:
+ break;
+ case BPF_DIV:
+ /*
+ * Check for constant division by 0.
+ */
+ if (BPF_SRC(p->code) == BPF_K && p->k == 0)
+ return 0;
+ break;
+ default:
+ return 0;
+ }
+ break;
+ case BPF_JMP:
+ /*
+ * Check that jumps are within the code block,
+ * and that unconditional branches don't go
+ * backwards as a result of an overflow.
+ * Unconditional branches have a 32-bit offset,
+ * so they could overflow; we check to make
+ * sure they don't. Conditional branches have
+ * an 8-bit offset, and the from address is <=
+ * BPF_MAXINSNS, and we assume that BPF_MAXINSNS
+ * is sufficiently small that adding 255 to it
+ * won't overflow.
+ *
+ * We know that len is <= BPF_MAXINSNS, and we
+ * assume that BPF_MAXINSNS is < the maximum size
+ * of a u_int, so that i + 1 doesn't overflow.
+ */
+ from = i + 1;
+ switch (BPF_OP(p->code)) {
+ case BPF_JA:
+ if (from + p->k < from || from + p->k >= (u_int32)len)
+ return 0;
+ break;
+ case BPF_JEQ:
+ case BPF_JGT:
+ case BPF_JGE:
+ case BPF_JSET:
+ if (from + p->jt >= (u_int32)len || from + p->jf >= (u_int32)len)
+ return 0;
+ break;
+ default:
+ return 0;
+ }
+ IF_LOUD(DbgPrint("Validating program: no wrong JUMPS");)
+ break;
+ case BPF_RET:
+ break;
+ case BPF_MISC:
+ break;
+ default:
+ return 0;
+ }
+ }
+ return BPF_CLASS(f[len - 1].code) == BPF_RET;
+}
\ No newline at end of file
diff --git a/drivers/3rdparty/npf/win_bpf_filter_init.c b/drivers/3rdparty/npf/win_bpf_filter_init.c
new file mode 100644
index 0000000000000..36a496120e6be
--- /dev/null
+++ b/drivers/3rdparty/npf/win_bpf_filter_init.c
@@ -0,0 +1,514 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * 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 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 "tme.h"
+#include "win_bpf.h"
+
+#pragma warning(disable : 4131) //old style function declaration
+#pragma warning(disable : 4127) // conditional expr is constant (used for while(1) loops)
+#pragma warning(disable : 4213) //cast on l-value
+
+/*
+ * Initialize the filter machine
+ */
+uint32 bpf_filter_init(register struct bpf_insn *pc, MEM_TYPE *mem_ex, TME_CORE *tme, struct time_conv *time_ref)
+{
+ register uint32 A, X;
+ int32 mem[BPF_MEMWORDS];
+ register int32 k;
+ uint32 *tmp;
+ uint16 *tmp2;
+ uint32 j;
+ if (pc == 0)
+ /*
+ * No filter means accept all.
+ */
+ return (uint32)-1;
+
+ RtlZeroMemory(mem, sizeof(mem));
+
+ A = 0;
+ X = 0;
+ --pc;
+ while (1) {
+ ++pc;
+ switch (pc->code) {
+
+ default:
+ return 0;
+
+/* RET INSTRUCTIONS */
+ case BPF_RET|BPF_K:
+ return (uint32)pc->k;
+
+ case BPF_RET|BPF_A:
+ return (uint32)A;
+/* END RET INSTRUCTIONS */
+
+/* LD NO PACKET INSTRUCTIONS */
+ case BPF_LD|BPF_IMM:
+ A = pc->k;
+ continue;
+
+ case BPF_LDX|BPF_IMM:
+ X = pc->k;
+ continue;
+
+ case BPF_LD|BPF_MEM:
+ A = mem[pc->k];
+ continue;
+
+ case BPF_LDX|BPF_MEM:
+ X = mem[pc->k];
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_B:
+ A= mem_ex->buffer[pc->k];
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_B:
+ X= mem_ex->buffer[pc->k];
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16*)&mem_ex->buffer[pc->k];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx,tmp2
+ xor eax, eax
+ mov ax, [ebx]
+ bswap eax
+ mov A, eax
+ pop ebx
+ pop eax
+ }
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16*)&mem_ex->buffer[pc->k];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx,tmp2
+ xor eax, eax
+ mov ax, [ebx]
+ bswap eax
+ mov X, eax
+ pop ebx
+ pop eax
+ }
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_W:
+ tmp=(uint32*)&mem_ex->buffer[pc->k];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx,tmp
+ mov eax, [ebx]
+ bswap eax
+ mov A, eax
+ pop ebx
+ pop eax
+ }
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_W:
+ tmp=(uint32*)&mem_ex->buffer[pc->k];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx,tmp
+ mov eax, [ebx]
+ bswap eax
+ mov X, eax
+ pop ebx
+ pop eax
+ }
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_B:
+ k = X + pc->k;
+ if ((int32)k>= (int32)mem_ex->size) {
+ return 0;
+ }
+ A= mem_ex->buffer[k];
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_H:
+ k = X + pc->k;
+ if ((int32)(k+1)>= (int32)mem_ex->size) {
+ return 0;
+ }
+ tmp2=(uint16*)&mem_ex->buffer[k];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx,tmp2
+ xor eax, eax
+ mov ax, [ebx]
+ bswap eax
+ mov A, eax
+ pop ebx
+ pop eax
+ }
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_W:
+ k = X + pc->k;
+ if ((int32)(k+3)>= (int32)mem_ex->size) {
+ return 0;
+ }
+ tmp=(uint32*)&mem_ex->buffer[k];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx,tmp
+ mov eax, [ebx]
+ bswap eax
+ mov A, eax
+ pop ebx
+ pop eax
+ }
+ continue;
+/* END LD NO PACKET INSTRUCTIONS */
+
+/* STORE INSTRUCTIONS */
+ case BPF_ST:
+ mem[pc->k] = A;
+ continue;
+
+ case BPF_STX:
+ mem[pc->k] = X;
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_B:
+ mem_ex->buffer[pc->k]=(uint8)A;
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_B:
+ mem_ex->buffer[pc->k]=(uint8)X;
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_W:
+ tmp=(uint32*)&mem_ex->buffer[pc->k];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx, tmp
+ mov eax, A
+ bswap eax
+ mov [ebx], eax
+ pop ebx
+ pop eax
+ }
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_W:
+ tmp=(uint32*)&mem_ex->buffer[pc->k];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx, tmp
+ mov eax, X
+ bswap eax
+ mov [ebx], eax
+ pop ebx
+ pop eax
+ }
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16*)&mem_ex->buffer[pc->k];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx, tmp2
+ mov eax, A
+ xchg ah, al
+ mov [ebx], ax
+ pop ebx
+ pop eax
+ }
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16*)&mem_ex->buffer[pc->k];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx, tmp2
+ mov eax, X
+ xchg ah, al
+ mov [ebx], ax
+ pop ebx
+ pop eax
+ }
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_B:
+ mem_ex->buffer[pc->k+X]=(uint8)A;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_W:
+ tmp=(uint32*)&mem_ex->buffer[pc->k+X];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx, tmp
+ mov eax, A
+ bswap eax
+ mov [ebx], eax
+ pop ebx
+ pop eax
+ }
+
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_H:
+ tmp2=(uint16*)&mem_ex->buffer[pc->k+X];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx, tmp2
+ mov eax, A
+ xchg ah, al
+ mov [ebx], ax
+ pop ebx
+ pop eax
+ }
+ continue;
+/* END STORE INSTRUCTIONS */
+
+/* JUMP INSTRUCTIONS */
+ case BPF_JMP|BPF_JA:
+ pc += pc->k;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_K:
+ pc += ((int32)A > (int32)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_K:
+ pc += ((int32)A >= (int32)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_K:
+ pc += ((int32)A == (int32)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_K:
+ pc += (A & pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_X:
+ pc += (A > X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_X:
+ pc += (A >= X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_X:
+ pc += (A == X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_X:
+ pc += (A & X) ? pc->jt : pc->jf;
+ continue;
+/* END JUMP INSTRUCTIONS */
+
+/* ARITHMETIC INSTRUCTIONS */
+ case BPF_ALU|BPF_ADD|BPF_X:
+ A += X;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_X:
+ A -= X;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_X:
+ A *= X;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_X:
+ if (X == 0)
+ return 0;
+ A /= X;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_X:
+ A &= X;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_X:
+ A |= X;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_X:
+ A <<= X;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_X:
+ A >>= X;
+ continue;
+
+ case BPF_ALU|BPF_ADD|BPF_K:
+ A += pc->k;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_K:
+ A -= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_K:
+ A *= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_K:
+ A /= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_K:
+ A &= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_K:
+ A |= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_K:
+ A <<= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_K:
+ A >>= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_NEG:
+ (int32)A = -((int32)A);
+ continue;
+/* ARITHMETIC INSTRUCTIONS */
+
+/* MISC INSTRUCTIONS */
+ case BPF_MISC|BPF_TAX:
+ X = A;
+ continue;
+
+ case BPF_MISC|BPF_TXA:
+ A = X;
+ continue;
+/* END MISC INSTRUCTIONS */
+
+/* TME INSTRUCTIONS */
+ case BPF_MISC|BPF_TME|BPF_LOOKUP:
+ j=lookup_frontend(mem_ex,tme,pc->k,time_ref);
+ if (j==TME_ERROR)
+ return 0;
+ pc += (j == TME_TRUE) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_EXECUTE:
+ if (execute_frontend(mem_ex,tme,0,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_INIT:
+ if (init_tme_block(tme,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_VALIDATE:
+ if (validate_tme_block(mem_ex,tme,A,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_MEMORY:
+ if (init_extended_memory(pc->k,mem_ex)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_ACTIVE:
+ if (set_active_tme_block(tme,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_ACTIVE_READ:
+ if (set_active_tme_block(tme,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+ case BPF_MISC|BPF_TME|BPF_SET_WORKING:
+ if (pc->k>=MAX_TME_DATA_BLOCKS)
+ return 0;
+ tme->working=pc->k;
+ continue;
+
+
+
+ case BPF_MISC|BPF_TME|BPF_RESET:
+ if (reset_tme(tme)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE:
+ if (get_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,&j)==TME_ERROR)
+ return 0;
+ A=j;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE:
+ if (set_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,A,TRUE)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_AUTODELETION:
+ set_autodeletion(&tme->block_data[tme->working],pc->k);
+ continue;
+
+/* END TME INSTRUCTIONS */
+
+ }
+ }
+}
+
diff --git a/drivers/3rdparty/npf/win_bpf_filter_init.h b/drivers/3rdparty/npf/win_bpf_filter_init.h
new file mode 100644
index 0000000000000..20de2b1b29bce
--- /dev/null
+++ b/drivers/3rdparty/npf/win_bpf_filter_init.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * 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 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.
+ *
+ */
+
+#ifndef __FILTER_INIT
+#define __FILTER_INIT
+
+#include "tme.h"
+
+#define INIT_OK 1
+#define INIT_ERROR 0
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+uint32 bpf_filter_init(register struct bpf_insn *pc,MEM_TYPE *mem_ex, TME_CORE *tme, struct time_conv *time_ref);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file