Updated with latest version changes to original source.
authorRobert Dickenson <robd@reactos.org>
Tue, 24 Sep 2002 15:16:46 +0000 (15:16 +0000)
committerRobert Dickenson <robd@reactos.org>
Tue, 24 Sep 2002 15:16:46 +0000 (15:16 +0000)
svn path=/trunk/; revision=3555

34 files changed:
reactos/drivers/net/packet/.cvsignore [new file with mode: 0644]
reactos/drivers/net/packet/Makefile
reactos/drivers/net/packet/bucket_lookup.c [new file with mode: 0644]
reactos/drivers/net/packet/bucket_lookup.h [new file with mode: 0644]
reactos/drivers/net/packet/count_packets.c [new file with mode: 0644]
reactos/drivers/net/packet/count_packets.h [new file with mode: 0644]
reactos/drivers/net/packet/debug.h
reactos/drivers/net/packet/dump.c [new file with mode: 0644]
reactos/drivers/net/packet/functions.c [new file with mode: 0644]
reactos/drivers/net/packet/functions.h [new file with mode: 0644]
reactos/drivers/net/packet/jitter.c [new file with mode: 0644]
reactos/drivers/net/packet/jitter.h [new file with mode: 0644]
reactos/drivers/net/packet/memory_t.c [new file with mode: 0644]
reactos/drivers/net/packet/memory_t.h [new file with mode: 0644]
reactos/drivers/net/packet/normal_lookup.c [new file with mode: 0644]
reactos/drivers/net/packet/normal_lookup.h [new file with mode: 0644]
reactos/drivers/net/packet/openclos.c
reactos/drivers/net/packet/packet.c
reactos/drivers/net/packet/packet.h
reactos/drivers/net/packet/packet.rc
reactos/drivers/net/packet/read.c
reactos/drivers/net/packet/resource.h [new file with mode: 0644]
reactos/drivers/net/packet/tcp_session.c [new file with mode: 0644]
reactos/drivers/net/packet/tcp_session.h [new file with mode: 0644]
reactos/drivers/net/packet/time_calls.c [new file with mode: 0644]
reactos/drivers/net/packet/time_calls.h [new file with mode: 0644]
reactos/drivers/net/packet/tme.c [new file with mode: 0644]
reactos/drivers/net/packet/tme.h [new file with mode: 0644]
reactos/drivers/net/packet/valid_insns.h [new file with mode: 0644]
reactos/drivers/net/packet/win_bpf.h
reactos/drivers/net/packet/win_bpf_filter.c
reactos/drivers/net/packet/win_bpf_filter_init.c [new file with mode: 0644]
reactos/drivers/net/packet/win_bpf_filter_init.h [new file with mode: 0644]
reactos/drivers/net/packet/write.c

diff --git a/reactos/drivers/net/packet/.cvsignore b/reactos/drivers/net/packet/.cvsignore
new file mode 100644 (file)
index 0000000..d7687d4
--- /dev/null
@@ -0,0 +1,5 @@
+*.coff
+*.d
+*.o
+*.sym
+*.sys
index e93ab64..0b0ebc5 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.1 2002/06/19 15:43:15 robd Exp $
+# $Id: Makefile,v 1.2 2002/09/24 15:16:46 robd Exp $
 
 PATH_TO_TOP = ../../..
 
@@ -7,15 +7,26 @@ TARGET_TYPE = driver
 
 TARGET_NAME = packet
 
-TARGET_CFLAGS = -DNDIS50
-# -disable-stdcall-fixup
+TARGET_CFLAGS = -DDBG -DWIN_NT_DRIVER -DKQPC_TS
 
 TARGET_OBJECTS = \
-  packet.o \
-  read.o \
-  openclos.o \
-  write.o \
-  win_bpf_filter.o
+       packet.o    \
+       openclos.o  \
+       read.o      \
+       write.o     \
+       dump.o      \
+       jitter.o      \
+       win_bpf_filter.o \
+       tme.o \
+       count_packets.o \
+       win_bpf_filter_init.o \
+       tcp_session.o \
+       memory_t.o \
+       time_calls.o \
+       functions.o \
+       bucket_lookup.o \
+       normal_lookup.o
+
 
 TARGET_DDKLIBS = ndis.a
 
diff --git a/reactos/drivers/net/packet/bucket_lookup.c b/reactos/drivers/net/packet/bucket_lookup.c
new file mode 100644 (file)
index 0000000..e2c5fde
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2001
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef WIN32
+#include "tme.h"
+#include "bucket_lookup.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#include <net/tme/bucket_lookup.h>
+#else
+#include <tme/tme.h>
+#include <tme/bucket_lookup.h>
+#endif
+
+#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;
+       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((value<SW_ULONG_AT(temp,0))||(value>SW_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
+                               if (SW_ULONG_AT(temp+block_size*j,4)<value) 
+                                       if (SW_ULONG_AT(temp+block_size*j,0)>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((value<SW_USHORT_AT(temp,0))||(value>SW_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
+                               if (SW_USHORT_AT(temp+block_size*j,2)<value) 
+                                       if (SW_USHORT_AT(temp+block_size*j,0)>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/reactos/drivers/net/packet/bucket_lookup.h b/reactos/drivers/net/packet/bucket_lookup.h
new file mode 100644 (file)
index 0000000..ffe4523
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2001
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __bucket_lookup
+#define __bucket_lookup
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#else
+#include <tme/tme.h>
+#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/reactos/drivers/net/packet/count_packets.c b/reactos/drivers/net/packet/count_packets.c
new file mode 100644 (file)
index 0000000..71aa61f
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2001
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef WIN32
+#include "tme.h"
+#include "count_packets.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#include <net/tme/count_packets.h>
+#else
+#include <tme/tme.h>
+#include <tme/count_packets.h>
+#endif
+
+#endif
+
+
+
+uint32 count_packets(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data)
+{
+               
+       c_p_data *counters=(c_p_data*)(block+data->key_len*4);
+
+       counters->bytes+=pkt_size;
+       counters->packets++;
+       
+       return TME_SUCCESS;
+
+}
diff --git a/reactos/drivers/net/packet/count_packets.h b/reactos/drivers/net/packet/count_packets.h
new file mode 100644 (file)
index 0000000..0599964
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2001
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __count_packets
+#define __count_packets
+
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#else
+#include <tme/tme.h>
+#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
+
index da2f518..9fcd26b 100644 (file)
@@ -19,6 +19,8 @@
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
 
+#ifndef __DEBUG_INCLUDE
+#define __DEBUG_INCLUDE
 
 
 #if DBG
@@ -46,3 +48,5 @@ extern ULONG PacketDebugFlag;
 #define IF_INIT_LOUD(A)
 
 #endif
+
+#endif /*#define __DEBUG_INCLUDE*/
diff --git a/reactos/drivers/net/packet/dump.c b/reactos/drivers/net/packet/dump.c
new file mode 100644 (file)
index 0000000..e7c40fb
--- /dev/null
@@ -0,0 +1,587 @@
+/*
+ * Copyright (c) 1999, 2000
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef _MSC_VER
+#include "stdarg.h"
+#include "ntddk.h"
+#include "ntiologc.h"
+#include "ndis.h"
+#else
+#include <ddk/ntddk.h>
+#include <net/ndis.h>
+#endif
+
+#include "debug.h"
+#include "packet.h"
+#include "win_bpf.h"
+
+//-------------------------------------------------------------------
+
+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,
+#ifndef __GNUC__
+               *IoFileObjectType,
+#else
+               IoFileObjectType,
+#endif
+               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;
+    }  
+#ifndef __GNUC__
+       ntStatus = ObReferenceObjectByHandle(Open->DumpThreadHandle,
+               THREAD_ALL_ACCESS,
+               NULL,
+               KernelMode,
+               &Open->DumpThreadObject,
+               0);
+#else
+#endif
+    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%0x\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->BufSize==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;
+
+       
+       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;
+               
+       }
+
+       return STATUS_SUCCESS;
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS NPF_CloseDumpFile(POPEN_INSTANCE Open){
+       NTSTATUS        ntStatus;
+       IO_STATUS_BLOCK IoStatus;
+    PMDL               WriteMdl;
+    PUCHAR             VMBuff;
+       UINT            VMBufLen;
+
+
+    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);
+
+       return STATUS_SUCCESS;
+}
+
+//-------------------------------------------------------------------
+
+static NTSTATUS PacketDumpCompletion(PDEVICE_OBJECT DeviceObject,
+                                PIRP Irp,
+                                PVOID Context)
+{
+
+    // 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/reactos/drivers/net/packet/functions.c b/reactos/drivers/net/packet/functions.c
new file mode 100644 (file)
index 0000000..04c7e4b
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2001
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef WIN32
+#include "tme.h"
+#include "functions.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#include <net/bpf.h>
+#include <net/tme/functions.h>
+#else
+#include <tme/tme.h>
+#include <bpf.h>
+#include <tme/functions.h>
+#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;
+       }
+       
+       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;
+       }
+       
+       return NULL;
+}
diff --git a/reactos/drivers/net/packet/functions.h b/reactos/drivers/net/packet/functions.h
new file mode 100644 (file)
index 0000000..91f242a
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2001
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __FUNCTIONS
+#define __FUNCTIONS
+
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#else
+#include <tme/tme.h>
+#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 <net/tme/bucket_lookup.h>
+#include <net/tme/normal_lookup.h>
+#endif
+
+/* execution functions */
+
+#ifdef WIN32
+#include "count_packets.h"
+#include "tcp_session.h"
+#endif
+
+#ifdef __FreeBSD__
+#include <net/tme/count_packets.h>
+#include <ne/tme/tcp_session.h>
+#endif
+
+#endif
\ No newline at end of file
diff --git a/reactos/drivers/net/packet/jitter.c b/reactos/drivers/net/packet/jitter.c
new file mode 100644 (file)
index 0000000..4a71a7c
--- /dev/null
@@ -0,0 +1,677 @@
+/*
+ * Copyright (c) 2002
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef _MSC_VER
+#include "stdarg.h"
+#include "ntddk.h"
+#include "ntiologc.h"
+#include "ndis.h"
+#else
+#include <ddk/ntddk.h>
+#include <net/ndis.h>
+#endif
+
+#include "packet.h"
+#include "win_bpf.h"
+
+emit_func emitm;
+
+//
+// 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;
+
+
+       // 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;i<nins;i++){
+                       
+                       stream.bpf_pc++;
+                       
+                       switch (ins->code) {
+                               
+                       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)
+                               MOVrd(ESI,ECX)
+                               ADDib(ECX,sizeof(INT))
+                               CMPodd(ECX, EBP, 0x10)
+                               JLEb(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)
+                               MOVrd(ESI,ECX)
+                               ADDib(ECX,sizeof(SHORT))
+                               CMPodd(ECX, EBP, 0x10)
+                               JLEb(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)
+                               JLEb(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)
+                               MOVrd(ESI,ECX)
+                               ADDib(ECX,sizeof(INT))
+                               CMPodd(ECX, EBP, 0x10)
+                               JLEb(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)
+                               MOVrd(ESI,ECX)
+                               ADDib(ECX,sizeof(SHORT))
+                               CMPodd(ECX, EBP, 0x10)
+                               JLEb(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)
+                               JLEb(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)
+                               JLEb(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);
+
+               return NULL;
+#endif
+       }
+
+       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/reactos/drivers/net/packet/jitter.h b/reactos/drivers/net/packet/jitter.h
new file mode 100644 (file)
index 0000000..4f9c7fd
--- /dev/null
@@ -0,0 +1,391 @@
+/*
+ * Copyright (c) 2002
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/** @ingroup NPF 
+ *  @{
+ */
+
+/** @defgroup NPF_include NPF structures and 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 (*BPF_filter_function)( binary_stream *, 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);
+
+/// 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);
+
+/// 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             */
+/**************************/
+
+/** @ingroup NPF 
+ *  @{
+ */
+
+/** @defgroup NPF_code NPF functions 
+ *  @{
+ */
+
+/*!
+  \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 *prog, 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/reactos/drivers/net/packet/memory_t.c b/reactos/drivers/net/packet/memory_t.c
new file mode 100644 (file)
index 0000000..2a02998
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2001
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "tme.h"
+#include "memory_t.h"
+
+
+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);
+}
+
+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);
+}
+
+int16 SW_SHORT_AT(void *b, uint32 os)
+{
+       return ((int16)
+               ((int16)*((uint8 *)b+os+0)<<8|
+                (int16)*((uint8 *)b+os+1)<<0));
+}
+
+uint16 SW_USHORT_AT(void *b, uint32 os)
+{
+       return ((uint16)
+               ((uint16)*((uint8 *)b+os+0)<<8|
+                (uint16)*((uint8 *)b+os+1)<<0));
+}
+
+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);
+
+}
+
+void assert(void* assert, const char* file, int line, void* msg) { };
diff --git a/reactos/drivers/net/packet/memory_t.h b/reactos/drivers/net/packet/memory_t.h
new file mode 100644 (file)
index 0000000..0ecd90b
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2001
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#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))
+
+#ifdef __GNUC__
+
+int32 SW_LONG_AT(void *b, uint32 c);
+uint32 SW_ULONG_AT(void *b, uint32 c);
+int16 SW_SHORT_AT(void *b, uint32 os);
+uint16 SW_USHORT_AT(void *b, uint32 os);
+VOID SW_ULONG_ASSIGN(void *dst, uint32 src);
+
+#else /* __GNUC__ */
+
+__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);
+
+}
+
+#endif /* __GNUC__ */
+
+#ifdef WIN_NT_DRIVER
+
+#define ALLOCATE_MEMORY(dest,type,amount) \
+         (dest)=ExAllocatePool(NonPagedPool,sizeof(type)*(amount));
+#define ALLOCATE_ZERO_MEMORY(dest,type,amount) \
+       { \
+               (dest)=ExAllocatePool(NonPagedPool,sizeof(type)*(amount)); \
+               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);
+
+#endif /*WIN_NT_DRIVER*/
+
+
+#endif 
+
diff --git a/reactos/drivers/net/packet/normal_lookup.c b/reactos/drivers/net/packet/normal_lookup.c
new file mode 100644 (file)
index 0000000..ea6442f
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2001
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef WIN32
+#include "tme.h"
+#include "normal_lookup.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#include <net/tme/normal_lookup.h>
+#else
+#include <tme/tme.h>
+#include <tme/normal_lookup.h>
+#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; i<key_len;i++) 
+               shrinked_key^=key32[i];
+    /*the first index in the table is calculated*/
+       index=shrinked_key % data->lut_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; (i<key_len) && (key32[i]==ULONG_AT(offset,i*4)); i++);
+               
+               if (i==key_len)
+                       {
+                               /*key in the block matches the one provided, right entry*/
+                               GET_TIME((struct timeval *)(offset+4*key_len),time_ref);
+                               data->last_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; i<key_len;i++) 
+               shrinked_key^=key32[i];
+    /*the first index in the table is calculated*/
+       index=shrinked_key % data->lut_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; (i<key_len) && (key32[i]==ULONG_AT(offset,i*4)); i++);
+               
+               if (i==key_len)
+                       {
+                               /*key in the block matches the one provided, right entry*/
+                               GET_TIME((struct timeval *)(offset+4*key_len),time_ref);
+                               data->last_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/reactos/drivers/net/packet/normal_lookup.h b/reactos/drivers/net/packet/normal_lookup.h
new file mode 100644 (file)
index 0000000..c88d890
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2001
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __normal_lookup
+#define __normal_lookup
+
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#else
+#include <tme/tme.h>
+#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
index b30c605..6c857a8 100644 (file)
 #include "ndis.h"
 #else
 #include <ddk/ntddk.h>
-//#include <net/miniport.h>
 #include <net/ndis.h>
 #endif
-
 #include "debug.h"
 #include "packet.h"
 
@@ -41,10 +39,9 @@ static NDIS_MEDIUM MediumArray[] = {
        NdisMedium802_5
 };
 
-ULONG NamedEventsCounter=0;
-
 #define NUM_NDIS_MEDIA  (sizeof MediumArray / sizeof MediumArray[0])
 
+ULONG NamedEventsCounter=0;
 
 //Itoa. Replaces the buggy RtlIntegerToUnicodeString
 void PacketItoa(UINT n,PUCHAR buf){
@@ -58,9 +55,20 @@ int i;
 
 }
 
+/// Global start time. Used as an absolute reference for timestamp conversion.
+struct time_conv G_Start_Time = {
+       0,      
+       {0, 0}, 
+};
+
+UINT n_Opened_Instances = 0;
 
-NTSTATUS STDCALL
-PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+NDIS_SPIN_LOCK Opened_Instances_Lock;
+
+//-------------------------------------------------------------------
+
+NTSTATUS
+NPF_Open(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
 {
 
     PDEVICE_EXTENSION DeviceExtension;
@@ -71,33 +79,25 @@ PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
 
     NDIS_STATUS     Status;
     NDIS_STATUS     ErrorStatus;
-    UINT            Medium;
     UINT            i;
        PUCHAR                  tpointer;
     PLIST_ENTRY     PacketListEntry;
-       LARGE_INTEGER   TimeFreq;
-       LARGE_INTEGER   SystemTime;
-       LARGE_INTEGER   PTime;
        PCHAR                   EvName;
 
-    IF_LOUD(DbgPrint("Packet: OpenAdapter\n");)
+
+    IF_LOUD(DbgPrint("NPF: OpenAdapter\n");)
 
     DeviceExtension = DeviceObject->DeviceExtension;
 
 
     IrpSp = IoGetCurrentIrpStackLocation(Irp);
 
-
-    //
     //  allocate some memory for the open structure
-    //
-    Open=ExAllocatePool(NonPagedPool,sizeof(OPEN_INSTANCE));
+    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;
@@ -109,34 +109,26 @@ PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
         );
 
 
-       EvName=ExAllocatePool(NonPagedPool, sizeof(L"\\BaseNamedObjects\\NPF0000000000") );
+       EvName=ExAllocatePoolWithTag(NonPagedPool, sizeof(L"\\BaseNamedObjects\\NPF0000000000"), '1OWA');
 
     if (EvName==NULL) {
-        //
         // no memory
-        //
         ExFreePool(Open);
            Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
         IoCompleteRequest(Irp, IO_NO_INCREMENT);
         return STATUS_INSUFFICIENT_RESOURCES;
     }
 
-    //
     //  Save or open here
-    //
     IrpSp->FileObject->FsContext=Open;
        
     Open->DeviceExtension=DeviceExtension;
        
        
-    //
     //  Save the Irp here for the completeion routine to retrieve
-    //
     Open->OpenCloseIrp=Irp;
        
-    //
     //  Allocate a packet pool for our xmit and receive packets
-    //
     NdisAllocatePacketPool(
         &Status,
         &Open->PacketPool,
@@ -146,7 +138,7 @@ PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
        
     if (Status != NDIS_STATUS_SUCCESS) {
                
-        IF_LOUD(DbgPrint("Packet: Failed to allocate packet pool\n");)
+        IF_LOUD(DbgPrint("NPF: Failed to allocate packet pool\n");)
                        
                ExFreePool(Open);
                ExFreePool(EvName);
@@ -160,6 +152,7 @@ PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
 
        //Create the string containing the name of the read event
        RtlInitUnicodeString(&Open->ReadEventName,(PCWSTR) EvName);
+
        PacketItoa(NamedEventsCounter,(PUCHAR)(Open->ReadEventName.Buffer+21));
 
        InterlockedIncrement(&NamedEventsCounter);
@@ -170,6 +163,7 @@ PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
        Open->ReadEvent=IoCreateNotificationEvent(&Open->ReadEventName,&Open->ReadEventHandle);
        if(Open->ReadEvent==NULL){
                ExFreePool(Open);
+               ExFreePool(EvName);
         Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
         IoCompleteRequest(Irp, IO_NO_INCREMENT);
         return STATUS_INSUFFICIENT_RESOURCES;
@@ -179,51 +173,58 @@ PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
        KeClearEvent(Open->ReadEvent);
        NdisInitializeEvent(&Open->WriteEvent);
        NdisInitializeEvent(&Open->IOEvent);
+       NdisInitializeEvent(&Open->DumpEvent);
+       NdisInitializeEvent(&Open->IOEvent);
+       NdisAllocateSpinLock(&Open->machine_lock);
+
 
-    //
     //  list to hold irp's want to reset the adapter
-    //
     InitializeListHead(&Open->ResetIrpList);
        
        
-    //
-    //  Initialize list for holding pending read requests
-    //
-    KeInitializeSpinLock(&Open->RcvQSpinLock);
-    InitializeListHead(&Open->RcvList);
-       
-    //
     //  Initialize the request list
-    //
     KeInitializeSpinLock(&Open->RequestSpinLock);
     InitializeListHead(&Open->RequestList);
+
+       // Initializes the extended memory of the NPF machine
+       Open->mem_ex.buffer = ExAllocatePoolWithTag(NonPagedPool, DEFAULT_MEM_EX_SIZE, '2OWA');
+       if((Open->mem_ex.buffer) == NULL)
+       {
+        // no memory
+        ExFreePool(Open);
+               ExFreePool(EvName);
+           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);
        
-       // get the absolute value of the system boot time.   
-       PTime=KeQueryPerformanceCounter(&TimeFreq);
-       KeQuerySystemTime(&SystemTime);
-#ifndef __NTDRIVER__ // robert
-       Open->StartTime.QuadPart=(((SystemTime.QuadPart)%10000000)*TimeFreq.QuadPart)/10000000;
-       SystemTime.QuadPart=SystemTime.QuadPart/10000000-11644473600;
-#endif
-       Open->StartTime.QuadPart+=(SystemTime.QuadPart)*TimeFreq.QuadPart-PTime.QuadPart;
-       //initalize the open instance
-       Open->BufSize=0;
-       Open->Buffer=NULL;
-       Open->Bhead=0;
-       Open->Btail=0;
-       Open->BLastByte=0;
-       Open->Dropped=0;                //reset the dropped packets counter
-       Open->Received=0;               //reset the received packets counter
-       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->Bound=TRUE;
+       //
+       // Initialize the open instance
+       //
+       Open->BufSize = 0;
+       Open->Buffer = NULL;
+       Open->Bhead = 0;
+       Open->Btail = 0;
+       Open->BLastByte = 0;
+       Open->Dropped = 0;              //reset the dropped packets counter
+       Open->Received = 0;             //reset the received packets counter
+       Open->Accepted = 0;             //reset the accepted packets counter
+       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->Bound = TRUE;
+       Open->DumpFileName.Buffer = NULL;
+       Open->DumpFileHandle = NULL;
+       Open->tme.active = TME_NONE_ACTIVE;
+       Open->DumpLimitReached = FALSE;
 
        //allocate the spinlock for the statistic counters
     NdisAllocateSpinLock(&Open->CountersLock);
@@ -242,20 +243,19 @@ PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
                
     }
        
-       
+
     IoMarkIrpPending(Irp);
        
-       
     //
     //  Try to open the MAC
     //
-    IF_LOUD(DbgPrint("Packet: Openinig the device %ws, BindingContext=%d\n",DeviceExtension->AdapterName.Buffer, Open);)
+    IF_LOUD(DbgPrint("NPF: Openinig the device %ws, BindingContext=%d\n",DeviceExtension->AdapterName.Buffer, Open);)
 
        NdisOpenAdapter(
         &Status,
         &ErrorStatus,
         &Open->AdapterHandle,
-        &Medium,
+        &Open->Medium,
         MediumArray,
         NUM_NDIS_MEDIA,
         DeviceExtension->NdisProtocolHandle,
@@ -264,11 +264,11 @@ PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
         0,
         NULL);
 
-    IF_LOUD(DbgPrint("Packet: Opened the device, Status=%x\n",Status);)
+    IF_LOUD(DbgPrint("NPF: Opened the device, Status=%x\n",Status);)
 
        if (Status != NDIS_STATUS_PENDING)
     {
-               PacketOpenAdapterComplete(Open,Status,NDIS_STATUS_SUCCESS);
+               NPF_OpenAdapterComplete(Open,Status,NDIS_STATUS_SUCCESS);
     }
        
     return(STATUS_PENDING);
@@ -276,7 +276,7 @@ PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
 
 //-------------------------------------------------------------------
 
-VOID PacketOpenAdapterComplete(
+VOID NPF_OpenAdapterComplete(
        IN NDIS_HANDLE  ProtocolBindingContext,
     IN NDIS_STATUS  Status,
     IN NDIS_STATUS  OpenErrorStatus)
@@ -285,7 +285,7 @@ VOID PacketOpenAdapterComplete(
     PIRP              Irp;
     POPEN_INSTANCE    Open;
 
-    IF_LOUD(DbgPrint("Packet: OpenAdapterComplete\n");)
+    IF_LOUD(DbgPrint("NPF: OpenAdapterComplete\n");)
 
     Open= (POPEN_INSTANCE)ProtocolBindingContext;
 
@@ -296,14 +296,29 @@ VOID PacketOpenAdapterComplete(
 
     if (Status != NDIS_STATUS_SUCCESS) {
 
-        IF_LOUD(DbgPrint("Packet: OpenAdapterComplete-FAILURE\n");)
+        IF_LOUD(DbgPrint("NPF: OpenAdapterComplete-FAILURE\n");)
 
         NdisFreePacketPool(Open->PacketPool);
 
+               //free mem_ex
+               Open->mem_ex.size = 0;
+               if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer);
+
                ExFreePool(Open->ReadEventName.Buffer);
 
         ExFreePool(Open);
     }
+       else {
+               NdisAcquireSpinLock(&Opened_Instances_Lock);
+               n_Opened_Instances++;
+               NdisReleaseSpinLock(&Opened_Instances_Lock);
+               
+               IF_LOUD(DbgPrint("Opened Instances:%d", n_Opened_Instances);)
+
+               // Get the absolute value of the system boot time.
+               // This is used for timestamp conversion.
+               TIME_SYNCHRONIZE(&G_Start_Time);
+       }
 
     Irp->IoStatus.Status = Status;
     Irp->IoStatus.Information = 0;
@@ -315,34 +330,50 @@ VOID PacketOpenAdapterComplete(
 
 //-------------------------------------------------------------------
 
-NTSTATUS STDCALL
-PacketClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
+NTSTATUS
+NPF_Close(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
 {
 
     POPEN_INSTANCE    Open;
     NDIS_STATUS     Status;
     PIO_STACK_LOCATION  IrpSp;
+       LARGE_INTEGER ThreadDelay;
 
-
-    IF_LOUD(DbgPrint("Packet: CloseAdapter\n");)
+    IF_LOUD(DbgPrint("NPF: CloseAdapter\n");)
 
        IrpSp = IoGetCurrentIrpStackLocation(Irp);
 
     Open=IrpSp->FileObject->FsContext;
 
+       // Reset the buffer size. This tells the dump thread to stop.
+       Open->BufSize = 0;
+
        if( Open->Bound == FALSE){
 
                NdisWaitEvent(&Open->IOEvent,10000);
 
-               //free the bpf program
-               if(Open->bpfprogram!=NULL)ExFreePool(Open->bpfprogram);
-               
+               // Free the filter if it's present
+               if(Open->bpfprogram != NULL)
+                       ExFreePool(Open->bpfprogram);
+
+               // Free the jitted filter if it's present
+               if(Open->Filter != NULL)
+                       BPF_Destroy_JIT_Filter(Open->Filter);
+
                //free the buffer
                Open->BufSize=0;
-               if(Open->Buffer!=NULL)ExFreePool(Open->Buffer);
+               if(Open->Buffer != NULL)ExFreePool(Open->Buffer);
                
-               NdisFreePacketPool(Open->PacketPool);
+               //free mem_ex
+               Open->mem_ex.size = 0;
+               if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer);
                                
+               NdisFreePacketPool(Open->PacketPool);
+
+               // Free the string with the name of the dump file
+               if(Open->DumpFileName.Buffer!=NULL)
+                       ExFreePool(Open->DumpFileName.Buffer);
+                       
                ExFreePool(Open->ReadEventName.Buffer);
                ExFreePool(Open);
 
@@ -353,26 +384,50 @@ PacketClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
                return(STATUS_SUCCESS);
        }
 
-       // Eventually unfreeze PacketRead
-       KeSetEvent(Open->ReadEvent,0,FALSE);
+       // Unfreeze the consumer
+       if(Open->mode & MODE_DUMP)
+               NdisSetEvent(&Open->DumpEvent);
+       else
+               KeSetEvent(Open->ReadEvent,0,FALSE);
+
+    // Save the IRP
+    Open->OpenCloseIrp = Irp;
+
+    IoMarkIrpPending(Irp);
+       // If this instance is in dump mode, complete the dump and close the file
+       if((Open->mode & MODE_DUMP) && Open->DumpFileHandle != NULL){
+#ifndef __GNUC__
+               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);
+#endif
+       }
 
        // Destroy the read Event
        ZwClose(Open->ReadEventHandle);
 
-    //  save the IRP
-    Open->OpenCloseIrp=Irp;
-
-    IoMarkIrpPending(Irp);
-       
-       //  close the adapter
+       // Close the adapter
        NdisCloseAdapter(
                &Status,
                Open->AdapterHandle
                );
-       
+
        if (Status != NDIS_STATUS_PENDING) {
                
-               PacketCloseAdapterComplete(
+               NPF_CloseAdapterComplete(
                        Open,
                        Status
                        );
@@ -386,29 +441,42 @@ PacketClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
 //-------------------------------------------------------------------
 
 VOID
-PacketCloseAdapterComplete(IN NDIS_HANDLE  ProtocolBindingContext,IN NDIS_STATUS  Status)
+NPF_CloseAdapterComplete(IN NDIS_HANDLE  ProtocolBindingContext,IN NDIS_STATUS  Status)
 {
     POPEN_INSTANCE    Open;
     PIRP              Irp;
 
-    IF_LOUD(DbgPrint("Packet: CloseAdapterComplete\n");)
+    IF_LOUD(DbgPrint("NPF: CloseAdapterComplete\n");)
 
     Open= (POPEN_INSTANCE)ProtocolBindingContext;
 
        // free the allocated structures only if the instance is still bound to the adapter
        if(Open->Bound == TRUE){
                
-               //free the bpf program
-               if(Open->bpfprogram!=NULL)ExFreePool(Open->bpfprogram);
+               // Free the filter if it's present
+               if(Open->bpfprogram != NULL)
+                       ExFreePool(Open->bpfprogram);
+
+               // Free the jitted filter if it's present
+               if(Open->Filter != NULL)
+                       BPF_Destroy_JIT_Filter(Open->Filter);
                
                //free the buffer
-               Open->BufSize=0;
+               Open->BufSize = 0;
                if(Open->Buffer!=NULL)ExFreePool(Open->Buffer);
                
+               //free mem_ex
+               Open->mem_ex.size = 0;
+               if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer);
+               
                NdisFreePacketPool(Open->PacketPool);
                
                Irp=Open->OpenCloseIrp;
                
+               // Free the string with the name of the dump file
+               if(Open->DumpFileName.Buffer!=NULL)
+                       ExFreePool(Open->DumpFileName.Buffer);
+
                ExFreePool(Open->ReadEventName.Buffer);
                ExFreePool(Open);
                
@@ -420,15 +488,42 @@ PacketCloseAdapterComplete(IN NDIS_HANDLE  ProtocolBindingContext,IN NDIS_STATUS
        else
                NdisSetEvent(&Open->IOEvent);
 
+       // Decrease the counter of open instances
+       NdisAcquireSpinLock(&Opened_Instances_Lock);
+       n_Opened_Instances--;
+       NdisReleaseSpinLock(&Opened_Instances_Lock);
+
+       IF_LOUD(DbgPrint("Opened Instances:%d", n_Opened_Instances);)
+
+       if(n_Opened_Instances == 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);
+       }
 
        return;
 
 }
+//-------------------------------------------------------------------
+
+#ifdef NDIS50
+NDIS_STATUS
+NPF_PowerChange(IN NDIS_HANDLE ProtocolBindingContext, IN PNET_PNP_EVENT pNetPnPEvent)
+{
+    IF_LOUD(DbgPrint("NPF: PowerChange\n");)
+
+       TIME_DESYNCHRONIZE(&G_Start_Time);
+
+       TIME_SYNCHRONIZE(&G_Start_Time);
+
+       return STATUS_SUCCESS;
+}
+#endif
 
 //-------------------------------------------------------------------
 
 VOID
-PacketBindAdapter(
+NPF_BindAdapter(
     OUT PNDIS_STATUS            Status,
     IN  NDIS_HANDLE             BindContext,
     IN  PNDIS_STRING            DeviceName,
@@ -436,13 +531,13 @@ PacketBindAdapter(
     IN  PVOID                   SystemSpecific2
     )
 {
-       IF_LOUD(DbgPrint("Packet: PacketBindAdapter\n");)
+       IF_LOUD(DbgPrint("NPF: NPF_BindAdapter\n");)
 }
 
 //-------------------------------------------------------------------
 
 VOID
-PacketUnbindAdapter(
+NPF_UnbindAdapter(
     OUT PNDIS_STATUS        Status,
     IN  NDIS_HANDLE         ProtocolBindingContext,
     IN  NDIS_HANDLE         UnbindContext
@@ -451,7 +546,10 @@ PacketUnbindAdapter(
     POPEN_INSTANCE   Open =(POPEN_INSTANCE)ProtocolBindingContext;
        NDIS_STATUS              lStatus;
 
-       IF_LOUD(DbgPrint("Packet: PacketUNBindAdapter\n");)
+       IF_LOUD(DbgPrint("NPF: NPF_UnbindAdapter\n");)
+
+       // Reset the buffer size. This tells the dump thread to stop.
+       Open->BufSize=0;
 
        NdisResetEvent(&Open->IOEvent);
 
@@ -459,7 +557,14 @@ PacketUnbindAdapter(
     InterlockedExchange( (PLONG) &Open->Bound, FALSE );
 
        // Awake a possible pending read on this instance
-       KeSetEvent(Open->ReadEvent,0,FALSE);
+       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)
+               NPF_CloseDumpFile(Open);
 
        // Destroy the read Event
        ZwClose(Open->ReadEventHandle);
@@ -472,7 +577,7 @@ PacketUnbindAdapter(
 
     if (lStatus != NDIS_STATUS_PENDING) {
 
-        PacketCloseAdapterComplete(
+        NPF_CloseAdapterComplete(
             Open,
             lStatus
             );
@@ -489,7 +594,7 @@ PacketUnbindAdapter(
 //-------------------------------------------------------------------
 
 VOID
-PacketResetComplete(IN NDIS_HANDLE  ProtocolBindingContext,IN NDIS_STATUS  Status)
+NPF_ResetComplete(IN NDIS_HANDLE  ProtocolBindingContext,IN NDIS_STATUS  Status)
 
 {
     POPEN_INSTANCE      Open;
@@ -497,7 +602,7 @@ PacketResetComplete(IN NDIS_HANDLE  ProtocolBindingContext,IN NDIS_STATUS  Statu
 
     PLIST_ENTRY         ResetListEntry;
 
-    IF_LOUD(DbgPrint("Packet: PacketResetComplte\n");)
+    IF_LOUD(DbgPrint("NPF: PacketResetComplte\n");)
 
     Open= (POPEN_INSTANCE)ProtocolBindingContext;
 
@@ -522,7 +627,7 @@ PacketResetComplete(IN NDIS_HANDLE  ProtocolBindingContext,IN NDIS_STATUS  Statu
     Irp->IoStatus.Status = STATUS_SUCCESS;
     IoCompleteRequest(Irp, IO_NO_INCREMENT);
 
-    IF_LOUD(DbgPrint("Packet: PacketResetComplte exit\n");)
+    IF_LOUD(DbgPrint("NPF: PacketResetComplte exit\n");)
 
     return;
 
index e859290..1891a8a 100644 (file)
 #include "ntiologc.h"
 #include "ndis.h"
 #else
-//#include <net/miniport.h>
 #include <ddk/ntddk.h>
-//#include "<ntiologc.h>"
 #include <net/ndis.h>
 #endif
 
 #include "ntddpack.h"
+
 #include "debug.h"
 #include "packet.h"
+#include "win_bpf.h"
+#include "win_bpf_filter_init.h"
 
+#include "tme.h"
 
 #if DBG
-//
 // Declare the global debug flag for this driver.
-//
-
-ULONG PacketDebugFlag = PACKET_DEBUG_LOUD;
+//ULONG PacketDebugFlag = PACKET_DEBUG_LOUD;
+ULONG PacketDebugFlag = PACKET_DEBUG_LOUD + PACKET_DEBUG_VERY_LOUD + PACKET_DEBUG_INIT;
 
 #endif
 
-
 PDEVICE_EXTENSION GlobalDeviceExtension;
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -60,10 +59,9 @@ PDEVICE_EXTENSION GlobalDeviceExtension;
 #endif // ROBERTS_PATCH
 ////////////////////////////////////////////////////////////////////////////////
 //
-// Strings
+// Global strings
 //
-
-NDIS_STRING PacketName = NDIS_STRING_CONST("Packet_");
+NDIS_STRING NPF_Prefix = NDIS_STRING_CONST("NPF_");
 NDIS_STRING devicePrefix = NDIS_STRING_CONST("\\Device\\");
 NDIS_STRING symbolicLinkPrefix = NDIS_STRING_CONST("\\DosDevices\\");
 NDIS_STRING tcpLinkageKeyName = NDIS_STRING_CONST("\\Registry\\Machine\\System"
@@ -72,32 +70,30 @@ 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");
 
-//
-// Global variable that points to the names of the bound adapters
-//
+
+/// Global variable that points to the names of the bound adapters
 WCHAR* bindP = NULL;
 
+extern struct time_conv G_Start_Time; // from openclos.c
+
+extern NDIS_SPIN_LOCK Opened_Instances_Lock;
+
 //
 //  Packet Driver's entry routine.
 //
-
-//NTSTATUS STDCALL DriverEntry(PDRIVER_OBJECT DriverObject,
-//                          PUNICODE_STRING RegistryPath)
-
 NTSTATUS
-STDCALL
 DriverEntry(
     IN PDRIVER_OBJECT DriverObject,
     IN PUNICODE_STRING RegistryPath
     )
 {
-    NTSTATUS Status = STATUS_SUCCESS;
-    NDIS_STATUS NdisStatus = STATUS_SUCCESS;
+
     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;
@@ -110,92 +106,114 @@ DriverEntry(
        PKEY_VALUE_PARTIAL_INFORMATION tcpBindingsP;
        UNICODE_STRING macName;
        
-       //This driver at the moment works only on single processor machines
+       // This driver at the moment works only on single processor machines
        if(NdisSystemProcessorCount() != 1){
                return STATUS_IMAGE_MP_UP_MISMATCH;
        }
+
     IF_LOUD(DbgPrint("\n\nPacket: DriverEntry\n");)
+
        RtlZeroMemory(&ProtocolChar,sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
+
 #ifdef NDIS50
     ProtocolChar.MajorNdisVersion            = 5;
 #else
     ProtocolChar.MajorNdisVersion            = 3;
 #endif
     ProtocolChar.MinorNdisVersion            = 0;
-//    ProtocolChar.Reserved                    = 0;
-    ProtocolChar.OpenAdapterCompleteHandler  = PacketOpenAdapterComplete;
-    ProtocolChar.CloseAdapterCompleteHandler = PacketCloseAdapterComplete;
-    ProtocolChar.u2.SendCompleteHandler         = PacketSendComplete;
-    ProtocolChar.u3.TransferDataCompleteHandler = PacketTransferDataComplete;
-    ProtocolChar.ResetCompleteHandler        = PacketResetComplete;
-    ProtocolChar.RequestCompleteHandler      = PacketRequestComplete;
-    ProtocolChar.u4.ReceiveHandler              = Packet_tap;
-    ProtocolChar.ReceiveCompleteHandler      = PacketReceiveComplete;
-    ProtocolChar.StatusHandler               = PacketStatus;
-    ProtocolChar.StatusCompleteHandler       = PacketStatusComplete;
+#ifndef __GNUC__
+    ProtocolChar.Reserved                    = 0;
+#endif
+    ProtocolChar.OpenAdapterCompleteHandler  = NPF_OpenAdapterComplete;
+    ProtocolChar.CloseAdapterCompleteHandler = NPF_CloseAdapterComplete;
+#ifndef __GNUC__
+    ProtocolChar.SendCompleteHandler         = NPF_SendComplete;
+    ProtocolChar.TransferDataCompleteHandler = NPF_TransferDataComplete;
+#endif
+    ProtocolChar.ResetCompleteHandler        = NPF_ResetComplete;
+    ProtocolChar.RequestCompleteHandler      = NPF_RequestComplete;
+#ifndef __GNUC__
+    ProtocolChar.ReceiveHandler              = NPF_tap;
+#endif
+    ProtocolChar.ReceiveCompleteHandler      = NPF_ReceiveComplete;
+    ProtocolChar.StatusHandler               = NPF_Status;
+    ProtocolChar.StatusCompleteHandler       = NPF_StatusComplete;
 #ifdef NDIS50
-    ProtocolChar.BindAdapterHandler          = PacketBindAdapter;
-    ProtocolChar.UnbindAdapterHandler        = PacketUnbindAdapter;
+    ProtocolChar.BindAdapterHandler          = NPF_BindAdapter;
+    ProtocolChar.UnbindAdapterHandler        = NPF_UnbindAdapter;
+    ProtocolChar.PnPEventHandler             = NPF_PowerChange;
     ProtocolChar.ReceivePacketHandler        = NULL;
 #endif
     ProtocolChar.Name                        = ProtoName;
-/*
-NdisRegisterProtocol(
-    OUT PNDIS_STATUS                    Status,
-    OUT PNDIS_HANDLE                    NdisProtocolHandle,
-    IN  PNDIS_PROTOCOL_CHARACTERISTICS  ProtocolCharacteristics,
-    IN  UINT                            CharacteristicsLength);
- */
+
     NdisRegisterProtocol(
-        &NdisStatus,
+        &Status,
         &NdisProtocolHandle,
         &ProtocolChar,
         sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
-    if (NdisStatus != NDIS_STATUS_SUCCESS) {
-        IF_LOUD(DbgPrint("Packet: Failed to register protocol with NDIS\n");)
-        return NdisStatus;
+
+    if (Status != NDIS_STATUS_SUCCESS) {
+
+        IF_LOUD(DbgPrint("NPF: Failed to register protocol with NDIS\n");)
+
+        return Status;
+
     }
-    //
+       
+    NdisAllocateSpinLock(&Opened_Instances_Lock);
+
     // Set up the device driver entry points.
-    //
-    DriverObject->MajorFunction[IRP_MJ_CREATE] = PacketOpen;
-    DriverObject->MajorFunction[IRP_MJ_CLOSE]  = PacketClose;
-    DriverObject->MajorFunction[IRP_MJ_READ]   = PacketRead;
-    DriverObject->MajorFunction[IRP_MJ_WRITE]  = PacketWrite;
-    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]  = PacketIoControl;
-    DriverObject->DriverUnload = PacketUnload;
-    //
-    //  Get the name of the Packet driver and the name of the MAC driver
+    DriverObject->MajorFunction[IRP_MJ_CREATE] = NPF_Open;
+    DriverObject->MajorFunction[IRP_MJ_CLOSE]  = NPF_Close;
+    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;
+
+    //  Get the name of the Packet driver and the name of the NIC driver
     //  to bind to from the registry
-    //
-    Status=PacketReadRegistry(
+    Status=NPF_ReadRegistry(
                &BindString,
                &ExportString,
                RegistryPath
                );
+
     if (Status != STATUS_SUCCESS) {
+
                IF_LOUD(DbgPrint("Trying dynamic binding\n");)  
+
                bindP = getAdaptersList();
+
                if (bindP == NULL) {
                        IF_LOUD(DbgPrint("Adapters not found in the registry, try to copy the bindings of TCP-IP.\n");)
+
                        tcpBindingsP = getTcpBindings();
+                       
                        if (tcpBindingsP == NULL){
                                IF_LOUD(DbgPrint("TCP-IP not found, quitting.\n");)
                                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);
                        createDevice(DriverObject, &macName, NdisProtocolHandle);
                }
+
                return STATUS_SUCCESS;
+
     }
+
     BindStringSave   = BindString;
     ExportStringSave = ExportString;
+
+
     //
     //  create a device object for each entry
     //
@@ -207,16 +225,21 @@ NdisRegisterProtocol(
             &MacDriverName,
             BindString
             );
+
         RtlInitUnicodeString(
             &UnicodeDeviceName,
             ExportString
             );
+
         //
         //  Advance to the next string of the MULTI_SZ string
         //
         BindString   += (MacDriverName.Length+sizeof(UNICODE_NULL))/sizeof(WCHAR);
+
         ExportString += (UnicodeDeviceName.Length+sizeof(UNICODE_NULL))/sizeof(WCHAR);
-        IF_LOUD(DbgPrint("Packet: DeviceName=%ws  MacName=%ws\n",UnicodeDeviceName.Buffer,MacDriverName.Buffer);)
+
+        IF_LOUD(DbgPrint("NPF: DeviceName=%ws  MacName=%ws\n",UnicodeDeviceName.Buffer,MacDriverName.Buffer);)
+
         //
         //  Create the device object
         //
@@ -229,55 +252,81 @@ NdisRegisterProtocol(
                     FALSE,
                     &DeviceObject
                     );
+
         if (Status != STATUS_SUCCESS) {
-            IF_LOUD(DbgPrint("Packet: IoCreateDevice() failed:\n");)
+            IF_LOUD(DbgPrint("NPF: IoCreateDevice() failed:\n");)
+
             break;
         }
+
         DevicesCreated++;
+
+
         DeviceObject->Flags |= DO_DIRECT_IO;
         DeviceExtension  =  (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;
         DeviceExtension->DeviceObject = DeviceObject;
+
         //
         //  Save the the name of the MAC driver to open in the Device Extension
         //
+
         DeviceExtension->AdapterName=MacDriverName;
+
         if (DevicesCreated == 1) {
+
             DeviceExtension->BindString   = NULL;
             DeviceExtension->ExportString = NULL;
         }
+
+
         DeviceExtension->NdisProtocolHandle=NdisProtocolHandle;
+
+
     }
+
     if (DevicesCreated > 0) {
         //
-        //  Managed to create at least on device.
+        //  Managed to create at least one device.
         //
+        IF_LOUD(DbgPrint("NPF: Managed to create at least one device.\n");)
         return STATUS_SUCCESS;
     }
+
+
+
     ExFreePool(BindStringSave);
     ExFreePool(ExportStringSave);
+
 RegistryError:
-    NdisDeregisterProtocol(&NdisStatus, NdisProtocolHandle);
+    IF_LOUD(DbgPrint("NPF: RegistryError: calling NdisDeregisterProtocol()\n");)
+    NdisDeregisterProtocol(
+        &Status,
+        NdisProtocolHandle
+        );
+
     Status=STATUS_UNSUCCESSFUL;
+
     return(Status);
+
 }
 
-//
-// Return the list of the MACs from SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}
-//
+//-------------------------------------------------------------------
 
 PWCHAR getAdaptersList(void)
 {
-       PWCHAR DeviceNames = (PWCHAR) ExAllocatePool(PagedPool, 4096);
        PKEY_VALUE_PARTIAL_INFORMATION result = NULL;
        OBJECT_ATTRIBUTES objAttrs;
        NTSTATUS status;
        HANDLE keyHandle;
        UINT BufPos=0;
        
+       PWCHAR DeviceNames = (PWCHAR) ExAllocatePoolWithTag(PagedPool, 4096, '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);
@@ -288,9 +337,11 @@ PWCHAR getAdaptersList(void)
                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=%x\n",DeviceNames);)
+                       
                        // Scan the list of the devices
-                       while((status=ZwEnumerateKey(keyHandle,i,KeyBasicInformation,AdapInfo,sizeof(AdapInfo),&resultLength))==STATUS_SUCCESS) {
+                       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}");
@@ -302,33 +353,43 @@ PWCHAR getAdaptersList(void)
                                HANDLE ExportKeyHandle;
                                KEY_VALUE_PARTIAL_INFORMATION valueInfo;
                                ULONG resultLength;
+                               
                                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)) {
                                        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) ExAllocatePool(PagedPool, valueInfoLength);
+                                       PKEY_VALUE_PARTIAL_INFORMATION valueInfoP =     (PKEY_VALUE_PARTIAL_INFORMATION) ExAllocatePoolWithTag(PagedPool, valueInfoLength, '1PWA');
                                        if (valueInfoP != NULL) {
                                                status = ZwQueryValueKey(ExportKeyHandle, &FinalExportKey,
                                                        KeyValuePartialInformation,
@@ -336,36 +397,41 @@ PWCHAR getAdaptersList(void)
                                                        valueInfoLength, &resultLength);
                                                if (!NT_SUCCESS(status)) {
                                                        IF_LOUD(DbgPrint("Status of %x querying key value\n", status);)
-                        } else{
+                        } else {
                                                        IF_LOUD(DbgPrint("Device %d = %ws\n", i, valueInfoP->Data);)
                                                                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;
+       return DeviceNames;
 }
 
-//
-// Return the MACs that bind to TCP/IP.
-//
+//-------------------------------------------------------------------
 
 PKEY_VALUE_PARTIAL_INFORMATION getTcpBindings(void)
 {
@@ -391,17 +457,17 @@ PKEY_VALUE_PARTIAL_INFORMATION getTcpBindings(void)
     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]);
+      ULONG valueInfoLength = valueInfo.DataLength + FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
       PKEY_VALUE_PARTIAL_INFORMATION valueInfoP =
-        (PKEY_VALUE_PARTIAL_INFORMATION)
-        ExAllocatePool(PagedPool, valueInfoLength);
-      if (valueInfoP != NULL) {
+        (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(PagedPool, valueInfoLength, '2PWA');
+      
+         if (valueInfoP != NULL) {
         status = ZwQueryValueKey(keyHandle, &bindValueName,
                                  KeyValuePartialInformation,
                                  valueInfoP,
                                  valueInfoLength, &resultLength);
-        if (!NT_SUCCESS(status)) {
+      
+               if (!NT_SUCCESS(status)) {
           IF_LOUD(DbgPrint("\n\nStatus of %x querying key value\n", status);)
         }
         else if (valueInfoLength != resultLength) {
@@ -435,17 +501,15 @@ PKEY_VALUE_PARTIAL_INFORMATION getTcpBindings(void)
   return result;
 }
 
-//
-// create a device associated with a given MAC.
-//
+//-------------------------------------------------------------------
 
 BOOLEAN createDevice(IN OUT PDRIVER_OBJECT adriverObjectP,
                      IN PUNICODE_STRING amacNameP, NDIS_HANDLE aProtoHandle)
 {
-  BOOLEAN result = FALSE;
   NTSTATUS status;
   PDEVICE_OBJECT devObjP;
   UNICODE_STRING deviceName;
+  BOOLEAN result = FALSE;
 
   IF_LOUD(DbgPrint("\n\ncreateDevice for MAC %ws\n", amacNameP->Buffer);)
   if (RtlCompareMemory(amacNameP->Buffer, devicePrefix.Buffer,
@@ -454,73 +518,101 @@ BOOLEAN createDevice(IN OUT PDRIVER_OBJECT adriverObjectP,
   }
 
   deviceName.Length = 0;
-  deviceName.MaximumLength = (USHORT)(amacNameP->Length + PacketName.Length + sizeof(UNICODE_NULL));
-  deviceName.Buffer = ExAllocatePool(PagedPool, deviceName.MaximumLength);
+  deviceName.MaximumLength = (USHORT)(amacNameP->Length + NPF_Prefix.Length + sizeof(UNICODE_NULL));
+  deviceName.Buffer = ExAllocatePoolWithTag(PagedPool, deviceName.MaximumLength, '3PWA');
   if (deviceName.Buffer != NULL) {
     RtlAppendUnicodeStringToString(&deviceName, &devicePrefix);
-    RtlAppendUnicodeStringToString(&deviceName, &PacketName);
+    RtlAppendUnicodeStringToString(&deviceName, &NPF_Prefix);
     RtlAppendUnicodeToString(&deviceName, amacNameP->Buffer +
                              devicePrefix.Length / sizeof(WCHAR));
+    
        IF_LOUD(DbgPrint("\n\nDevice name: %ws\n", deviceName.Buffer);)
+    
        status = IoCreateDevice(adriverObjectP, sizeof(PDEVICE_EXTENSION),
                             &deviceName, FILE_DEVICE_TRANSPORT, 0, FALSE,
                             &devObjP);
+
     if (NT_SUCCESS(status)) {
       PDEVICE_EXTENSION devExtP = (PDEVICE_EXTENSION)devObjP->DeviceExtension;
+
          IF_LOUD(DbgPrint("\n\nDevice created succesfully\n");)
+
       devObjP->Flags |= DO_DIRECT_IO;
+      
          devExtP->DeviceObject = devObjP;
       RtlInitUnicodeString(&devExtP->AdapterName,amacNameP->Buffer);   
          devExtP->BindString = NULL;
       devExtP->ExportString = NULL;
          devExtP->NdisProtocolHandle=aProtoHandle;
+
     }
+
     else IF_LOUD(DbgPrint("\n\nIoCreateDevice status = %x\n", status););
+
+       ExFreePool(deviceName.Buffer);
   }
-  if (deviceName.Length > 0) 
-         ExFreePool(deviceName.Buffer);
+  
   return result;
 }
 
+//-------------------------------------------------------------------
 
-
-VOID STDCALL
-PacketUnload(IN PDRIVER_OBJECT DriverObject)
+VOID
+NPF_Unload(IN PDRIVER_OBJECT DriverObject)
 {
+       
     PDEVICE_OBJECT     DeviceObject;
     PDEVICE_OBJECT     OldDeviceObject;
     PDEVICE_EXTENSION  DeviceExtension;
+       
     NDIS_HANDLE        NdisProtocolHandle;
     NDIS_STATUS        Status;
        
-    IF_LOUD(DbgPrint("Packet: Unload\n");)
-               
+    IF_LOUD(DbgPrint("NPF: Unload\n");)
+
+
        DeviceObject    = DriverObject->DeviceObject;
+
     while (DeviceObject != NULL) {
         DeviceExtension = DeviceObject->DeviceExtension;
+
         NdisProtocolHandle=DeviceExtension->NdisProtocolHandle;
         OldDeviceObject=DeviceObject;
+               
         DeviceObject=DeviceObject->NextDevice;
+
+               IF_LOUD(DbgPrint("Deleting Adapter %ws, Protocol Handle=%x, Device Obj=%x (%x)\n",
+                       DeviceExtension->AdapterName.Buffer,
+                       NdisProtocolHandle,
+                       DeviceObject,
+                       OldDeviceObject);)
+               
         IoDeleteDevice(OldDeviceObject);
+               
     }
-    NdisDeregisterProtocol(
+
+       NdisDeregisterProtocol(
         &Status,
         NdisProtocolHandle
         );
+
        // Free the adapters names
-       ExFreePool( bindP ); 
+       ExFreePool( bindP );
+       
 }
 
+//-------------------------------------------------------------------
 
-NTSTATUS STDCALL
-PacketIoControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
+NTSTATUS
+NPF_IoControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
 {
-    NDIS_STATUS                Status;
     POPEN_INSTANCE      Open;
     PIO_STACK_LOCATION  IrpSp;
     PLIST_ENTRY         RequestListEntry;
     PINTERNAL_REQUEST   pRequest;
     ULONG               FunctionCode;
+    NDIS_STATUS                Status;
     PLIST_ENTRY         PacketListEntry;
        UINT                            i;
        PUCHAR                          tpointer;
@@ -529,161 +621,317 @@ PacketIoControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
        PPACKET_OID_DATA    OidData;
        int                                     *StatsBuf;
     PNDIS_PACKET        pPacket;
-    PPACKET_RESERVED    Reserved;
        ULONG                           mode;
+       PWSTR                           DumpNameBuff;
        PUCHAR                          TmpBPFProgram;
-       
-    IF_LOUD(DbgPrint("Packet: IoControl\n");)
+       INT                                     WriteRes;
+       BOOLEAN                         SyncWrite = FALSE;
+       struct bpf_insn         *initprogram;
+       ULONG                           insns;
+       ULONG                           cnt;
+       BOOLEAN                         IsExtendedFilter=FALSE;
+
+    IF_LOUD(DbgPrint("NPF: IoControl\n");)
                
        IrpSp = IoGetCurrentIrpStackLocation(Irp);
     FunctionCode=IrpSp->Parameters.DeviceIoControl.IoControlCode;
     Open=IrpSp->FileObject->FsContext;
-    RequestListEntry=ExInterlockedRemoveHeadList(&Open->RequestList,&Open->RequestSpinLock);
-    if (RequestListEntry == NULL) {
-        Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
-               Irp->IoStatus.Information = 0;
-               IoCompleteRequest(Irp, IO_NO_INCREMENT);
-        return STATUS_UNSUCCESSFUL;
-    }
-    pRequest=CONTAINING_RECORD(RequestListEntry,INTERNAL_REQUEST,ListElement);
-    pRequest->Irp=Irp;
+
     Irp->IoStatus.Status = STATUS_SUCCESS;
-    IF_LOUD(DbgPrint("Packet: Function code is %08lx  buff size=%08lx  %08lx\n",FunctionCode,IrpSp->Parameters.DeviceIoControl.InputBufferLength,IrpSp->Parameters.DeviceIoControl.OutputBufferLength);)
+
+    IF_LOUD(DbgPrint("NPF: Function code is %08lx  buff size=%08lx  %08lx\n",FunctionCode,IrpSp->Parameters.DeviceIoControl.InputBufferLength,IrpSp->Parameters.DeviceIoControl.OutputBufferLength);)
+               
+
        switch (FunctionCode){
+               
        case BIOCGSTATS: //function to get the capture stats
-               StatsBuf=Irp->UserBuffer;
-               StatsBuf[0]=Open->Received;
-               StatsBuf[1]=Open->Dropped;
-               Irp->IoStatus.Information=8;
-               Irp->IoStatus.Status = STATUS_SUCCESS;
-               IoCompleteRequest(Irp, IO_NO_INCREMENT);
-               Status=STATUS_SUCCESS;
+               
+               if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength < 4*sizeof(INT)){                       
+                       EXIT_FAILURE(0);
+               }
+
+               *(((PUINT)Irp->UserBuffer)+3) = Open->Accepted;
+               *(((PUINT)Irp->UserBuffer)) = Open->Received;
+               *(((PUINT)Irp->UserBuffer)+1) = Open->Dropped;
+               *(((PUINT)Irp->UserBuffer)+2) = 0;              // Not yet supported
+               
+               EXIT_SUCCESS(4*sizeof(INT));
+               
                break;
+               
        case BIOCGEVNAME: //function to get the name of the event associated with the current instance
+
                if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength<26){                    
-                       Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
-                       Irp->IoStatus.Information=0;
-                       IoCompleteRequest(Irp, IO_NO_INCREMENT);
-                   ExInterlockedInsertTailList(&Open->RequestList, &pRequest->ListElement, &Open->RequestSpinLock);
-                       return STATUS_UNSUCCESSFUL;
+                       EXIT_FAILURE(0);
                }
+
                RtlCopyMemory(Irp->UserBuffer,(Open->ReadEventName.Buffer)+18,26);
-               Irp->IoStatus.Information=26;
-               Irp->IoStatus.Status = STATUS_SUCCESS;
-               IoCompleteRequest(Irp, IO_NO_INCREMENT);
-               Status=STATUS_SUCCESS;
+
+               EXIT_SUCCESS(26);
+
+               break;
+
+       case BIOCSENDPACKETSSYNC:
+
+               SyncWrite = TRUE;
+
+       case BIOCSENDPACKETSNOSYNC:
+
+               WriteRes = NPF_BufferedWrite(Irp,
+                       (PUCHAR)Irp->AssociatedIrp.SystemBuffer,
+                       IrpSp->Parameters.DeviceIoControl.InputBufferLength,
+                       SyncWrite);
+
+               if( WriteRes != -1)
+               {
+                       EXIT_SUCCESS(WriteRes);
+               }
+               
+               EXIT_FAILURE(WriteRes);
+
                break;
-       case BIOCSETF:  //fuction to set a new bpf filter
-               //free the previous buffer if it was present
+
+       case BIOCSETF:  
+               
+               // Free the previous buffer if it was present
                if(Open->bpfprogram!=NULL){
                        TmpBPFProgram=Open->bpfprogram;
-                       Open->bpfprogram=NULL;
+                       Open->bpfprogram = NULL;
                        ExFreePool(TmpBPFProgram);
                }
-               //get the pointer to the new program
+               
+               if (Open->Filter!=NULL)
+               {
+                       JIT_BPF_Filter *OldFilter=Open->Filter;
+                       Open->Filter=NULL;
+                       BPF_Destroy_JIT_Filter(OldFilter);
+               }
+        
+               // Get the pointer to the new program
                prog=(PUCHAR)Irp->AssociatedIrp.SystemBuffer;
+               
                if(prog==NULL){
-                       Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
-                       Irp->IoStatus.Information=0;
-                       IoCompleteRequest(Irp, IO_NO_INCREMENT);
-                   ExInterlockedInsertTailList(&Open->RequestList, &pRequest->ListElement, &Open->RequestSpinLock);
-                       return STATUS_UNSUCCESSFUL;
+                       IF_LOUD(DbgPrint("0001");)
+                       
+                       EXIT_FAILURE(0);
                }
-               //before accepting the program we must check that it's valid
-               //Otherwise, a bogus program could easily crash the system
-               if(bpf_validate((struct bpf_insn*)prog,(IrpSp->Parameters.DeviceIoControl.InputBufferLength)/sizeof(struct bpf_insn))==0) {
-                       Irp->IoStatus.Information=0;
-                       Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
-                       IoCompleteRequest(Irp, IO_NO_INCREMENT);
-                   ExInterlockedInsertTailList(&Open->RequestList, &pRequest->ListElement, &Open->RequestSpinLock);
-                       return STATUS_UNSUCCESSFUL;
+               
+               insns=(IrpSp->Parameters.DeviceIoControl.InputBufferLength)/sizeof(struct bpf_insn);
+               
+               //count the number of operative instructions
+               for (cnt=0;(cnt<insns) &&(((struct bpf_insn*)prog)[cnt].code!=BPF_SEPARATION); cnt++);
+               
+               IF_LOUD(DbgPrint("Operative instructions=%u\n",cnt);)
+
+               if (((struct bpf_insn*)prog)[cnt].code==BPF_SEPARATION && (insns-cnt-1)!=0) 
+               {
+                       IF_LOUD(DbgPrint("Initialization instructions=%u\n",insns-cnt-1);)
+       
+                       IsExtendedFilter=TRUE;
+
+                       initprogram=&((struct bpf_insn*)prog)[cnt+1];
+                       
+                       if(bpf_filter_init(initprogram,&(Open->mem_ex),&(Open->tme), &G_Start_Time)!=INIT_OK)
+                       {
+                       
+                               IF_LOUD(DbgPrint("Error initializing NPF machine (bpf_filter_init)\n");)
+                               
+                               EXIT_FAILURE(0);
+                       }
                }
-               //allocate the memory to contain the new filter program
-               TmpBPFProgram=(PUCHAR)ExAllocatePool(NonPagedPool, IrpSp->Parameters.DeviceIoControl.InputBufferLength);
+
+               //the NPF processor has been initialized, we have to validate the operative instructions
+               insns=cnt;
+               
+               if(bpf_validate((struct bpf_insn*)prog,cnt,Open->mem_ex.size)==0)
+               {
+                       IF_LOUD(DbgPrint("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
+                       EXIT_FAILURE(0);
+               }
+               
+               // 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){
+                       IF_LOUD(DbgPrint("Error - No memory for filter");)
                        // no memory
-                       Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
-                       Irp->IoStatus.Information=0;
-                       IoCompleteRequest(Irp, IO_NO_INCREMENT);
-                   ExInterlockedInsertTailList(&Open->RequestList, &pRequest->ListElement, &Open->RequestSpinLock);
-                       return STATUS_INSUFFICIENT_RESOURCES;
+                       EXIT_FAILURE(0);
                }
+               
                //copy the program in the new buffer
-               RtlCopyMemory(TmpBPFProgram,prog,IrpSp->Parameters.DeviceIoControl.InputBufferLength);
+               RtlCopyMemory(TmpBPFProgram,prog,cnt*sizeof(struct bpf_insn));
                Open->bpfprogram=TmpBPFProgram;
+               
+               // Create the new JIT filter function
+
+               if(!IsExtendedFilter)
+                       if((Open->Filter=BPF_jitter((struct bpf_insn*)Open->bpfprogram,cnt))
+                       == NULL)
+               {
+                       IF_LOUD(DbgPrint("Error jittering filter");)
+                       EXIT_FAILURE(0);
+               }
+
                //return
-               Irp->IoStatus.Information=IrpSp->Parameters.DeviceIoControl.InputBufferLength;
-               Irp->IoStatus.Status = STATUS_SUCCESS;
-               Open->Bhead=0;
-               Open->Btail=0;
-               Open->BLastByte=0;
-               Open->Received=0;               
-               Open->Dropped=0;
-               IoCompleteRequest(Irp, IO_NO_INCREMENT);
-               Status=STATUS_SUCCESS;
-               break;
+               Open->Bhead = 0;
+               Open->Btail = 0;
+               Open->BLastByte = 0;
+               Open->Received = 0;             
+               Open->Dropped = 0;
+
+               EXIT_SUCCESS(IrpSp->Parameters.DeviceIoControl.InputBufferLength);
+               
+               break;          
+               
        case BIOCSMODE:  //set the capture mode
-               mode=((PULONG)Irp->AssociatedIrp.SystemBuffer)[0];
-               if(mode==MODE_STAT){
-                       Open->mode=MODE_STAT;
-                       Open->Nbytes.QuadPart=0;
-                       Open->Npackets.QuadPart=0;
-                       if(Open->TimeOut.QuadPart==0)Open->TimeOut.QuadPart=-10000000;
-                       Irp->IoStatus.Information=1;
-                       Irp->IoStatus.Status = STATUS_SUCCESS;
-                       IoCompleteRequest(Irp, IO_NO_INCREMENT);
-                       ExInterlockedInsertTailList(&Open->RequestList, &pRequest->ListElement, &Open->RequestSpinLock);
-                       return NDIS_STATUS_SUCCESS;
-               }
-               else if(mode==MODE_CAPT){
+               
+               mode=*((PULONG)Irp->AssociatedIrp.SystemBuffer);
+               
+               if(mode == MODE_CAPT){
                        Open->mode=MODE_CAPT;
-                       Irp->IoStatus.Information=0;
-                       Irp->IoStatus.Status = STATUS_SUCCESS;
-                       IoCompleteRequest(Irp, IO_NO_INCREMENT);
-                   ExInterlockedInsertTailList(&Open->RequestList, &pRequest->ListElement, &Open->RequestSpinLock);
-                       return NDIS_STATUS_SUCCESS;
+                       
+                       EXIT_SUCCESS(0);
                }
+               else if (mode==MODE_MON){
+                       Open->mode=MODE_MON;
+
+                       EXIT_SUCCESS(0);
+               }       
                else{
-                       Irp->IoStatus.Information=0;
-                       Irp->IoStatus.Status = NDIS_STATUS_FAILURE;
-                       IoCompleteRequest(Irp, IO_NO_INCREMENT);
-                   ExInterlockedInsertTailList(&Open->RequestList, &pRequest->ListElement, &Open->RequestSpinLock);
-                       return NDIS_STATUS_FAILURE;
+                       if(mode & MODE_STAT){
+                               Open->mode = MODE_STAT;
+                               Open->Nbytes.QuadPart=0;
+                               Open->Npackets.QuadPart=0;
+                               
+                               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;
+                               
+                       }       
+                       EXIT_SUCCESS(0);
+               }
+               
+               EXIT_FAILURE(0);
+               
+               break;
+
+       case BIOCSETDUMPFILENAME:
+
+               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 
+                       ((SHORT*)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:
+
+               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:
+               if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength < 4){                   
+                       EXIT_FAILURE(0);
                }
+
+               *((UINT*)Irp->UserBuffer) = (Open->DumpLimitReached)?1:0;
+
+               EXIT_SUCCESS(4);
+
                break;
-       case BIOCSETBUFFERSIZE: //function to set the dimension of the buffer for the packets
-               //get the number of buffers to allocate
-               dim=((PULONG)Irp->AssociatedIrp.SystemBuffer)[0];
-               //free the old buffer
-               if(Open->Buffer!=NULL) ExFreePool(Open->Buffer);
-               //allocate the new buffer
+
+       case BIOCSETBUFFERSIZE:
+               
+               // Get the number of bytes to allocate
+               dim = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
+
+               // Free the old buffer
+               tpointer = Open->Buffer;
+               if(tpointer != NULL){
+                       Open->BufSize = 0;
+                       Open->Buffer = NULL;
+                       ExFreePool(tpointer);
+               }
+               // Allocate the new buffer
                if(dim!=0){
-                       tpointer=ExAllocatePool(NonPagedPool,dim);
-                       if (tpointer==NULL) {
+                       tpointer = ExAllocatePoolWithTag(NonPagedPool, dim, '6PWA');
+                       if (tpointer==NULL)     {
                                // no memory
-                               Open->BufSize=0;
-                               Open->Buffer=NULL;
-                               Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
-                               Irp->IoStatus.Information = 0;
-                               IoCompleteRequest(Irp, IO_NO_INCREMENT);
-                               ExInterlockedInsertTailList(&Open->RequestList, &pRequest->ListElement, &Open->RequestSpinLock);
-                               return STATUS_INSUFFICIENT_RESOURCES;
+                               Open->BufSize = 0;
+                               Open->Buffer = NULL;
+                               EXIT_FAILURE(0);
                        }
                }
                else
-                       tpointer=NULL;
-               Open->Buffer=tpointer;
-               Open->Bhead=0;
-               Open->Btail=0;
-               Open->BLastByte=0;
-               Irp->IoStatus.Information=dim;
-               Irp->IoStatus.Status = STATUS_SUCCESS;
-               IoCompleteRequest(Irp, IO_NO_INCREMENT);
-               Open->BufSize=(UINT)dim;
-               Status=STATUS_SUCCESS;
+                       tpointer = NULL;
+
+               Open->Buffer = tpointer;
+               Open->Bhead = 0;
+               Open->Btail = 0;
+               Open->BLastByte = 0;
+               
+               Open->BufSize = (UINT)dim;
+               EXIT_SUCCESS(dim);
+               
                break;
+               
        case BIOCSRTIMEOUT: //set the timeout on the read calls
-               timeout=((PULONG)Irp->AssociatedIrp.SystemBuffer)[0];
+               
+               timeout = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
                if((int)timeout==-1)
                        Open->TimeOut.QuadPart=(LONGLONG)IMMEDIATE;
                else {
@@ -691,43 +939,63 @@ PacketIoControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
                        Open->TimeOut.QuadPart*=10000;
                        Open->TimeOut.QuadPart=-Open->TimeOut.QuadPart;
                }
-               IF_LOUD(DbgPrint("Packet: read timeout set to %d:%d\n",Open->TimeOut.HighPart,Open->TimeOut.LowPart);)
-               Irp->IoStatus.Information=timeout;
-               Irp->IoStatus.Status = STATUS_SUCCESS;
-               IoCompleteRequest(Irp, IO_NO_INCREMENT);
-               Status=STATUS_SUCCESS;
+
+               //IF_LOUD(DbgPrint("NPF: read timeout set to %d:%d\n",Open->TimeOut.HighPart,Open->TimeOut.LowPart);)
+               EXIT_SUCCESS(timeout);
+               
                break;
+               
        case BIOCSWRITEREP: //set the writes repetition number
-               Open->Nwrites=((PULONG)Irp->AssociatedIrp.SystemBuffer)[0];
-               Irp->IoStatus.Information=Open->Nwrites;
-               Irp->IoStatus.Status = STATUS_SUCCESS;
-               IoCompleteRequest(Irp, IO_NO_INCREMENT);
-               Status=STATUS_SUCCESS;
+               
+               Open->Nwrites = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
+               
+               EXIT_SUCCESS(Open->Nwrites);
+               
                break;
+
        case BIOCSMINTOCOPY: //set the minimum buffer's size to copy to the application
-               Open->MinToCopy=((PULONG)Irp->AssociatedIrp.SystemBuffer)[0];
-               Irp->IoStatus.Information=Open->MinToCopy;
-               Irp->IoStatus.Status = STATUS_SUCCESS;
-               IoCompleteRequest(Irp, IO_NO_INCREMENT);
-               Status=STATUS_SUCCESS;
+
+               Open->MinToCopy = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
+               
+               EXIT_SUCCESS(Open->MinToCopy);
+               
                break;
+               
        case IOCTL_PROTOCOL_RESET:
-        IF_LOUD(DbgPrint("Packet: IoControl - Reset request\n");)
+               
+        IF_LOUD(DbgPrint("NPF: IoControl - Reset request\n");)
+
                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("Packet: IoControl - ResetComplete being called\n");)
-                               PacketResetComplete(Open,Status);
+            IF_LOUD(DbgPrint("NPF: IoControl - ResetComplete being called\n");)
+                               NPF_ResetComplete(Open,Status);
         }
+               
                break;
+               
+               
        case BIOCSETOID:
        case BIOCQUERYOID:
-        //
+               
+               // Extract a request from the list of free ones
+               RequestListEntry=ExInterlockedRemoveHeadList(&Open->RequestList,&Open->RequestSpinLock);
+               if (RequestListEntry == NULL)
+               {
+                       EXIT_FAILURE(0);
+               }
+
+               pRequest=CONTAINING_RECORD(RequestListEntry,INTERNAL_REQUEST,ListElement);
+               pRequest->Irp=Irp;
+        
+               //
         //  See if it is an Ndis request
         //
         OidData=Irp->AssociatedIrp.SystemBuffer;
+               
         if (((FunctionCode == BIOCSETOID) || (FunctionCode == BIOCQUERYOID))
             &&
             (IrpSp->Parameters.DeviceIoControl.InputBufferLength == IrpSp->Parameters.DeviceIoControl.OutputBufferLength)
@@ -736,21 +1004,27 @@ PacketIoControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
             &&
             (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA)-1+OidData->Length)) {
                        
-            IF_LOUD(DbgPrint("Packet: IoControl: Request: Oid=%08lx, Length=%08lx\n",OidData->Oid,OidData->Length);)
+            IF_LOUD(DbgPrint("NPF: IoControl: Request: Oid=%08lx, Length=%08lx\n",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(&Open->IOEvent);
                                //
                                //  submit the request
@@ -760,6 +1034,7 @@ PacketIoControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
                                        Open->AdapterHandle,
                                        &pRequest->Request
                                        );
+                               
         } else {
             //
             //  buffer too small
@@ -767,54 +1042,87 @@ PacketIoControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
             Status=NDIS_STATUS_FAILURE;
             pRequest->Request.DATA.SET_INFORMATION.BytesRead=0;
             pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten=0;
+                       
         }
+               
         if (Status != NDIS_STATUS_PENDING) {
-            IF_LOUD(DbgPrint("Packet: Calling RequestCompleteHandler\n");)
-                       PacketRequestComplete(Open, &pRequest->Request, Status);
+            IF_LOUD(DbgPrint("NPF: Calling RequestCompleteHandler\n");)
+                               
+                       NPF_RequestComplete(Open, &pRequest->Request, Status);
             return Status;
+                       
         }
+
                NdisWaitEvent(&Open->IOEvent, 5000);
+
                return(Open->IOStatus);
+               
                break;
+               
+               
        default:
-               return(NDIS_STATUS_FAILURE);
                
+               EXIT_FAILURE(0);
        }
-       ExInterlockedInsertTailList(&Open->RequestList, &pRequest->ListElement, &Open->RequestSpinLock);
+       
        return Status;
 }
 
+//-------------------------------------------------------------------
+
 VOID
-PacketRequestComplete(
+NPF_RequestComplete(
     IN NDIS_HANDLE   ProtocolBindingContext,
     IN PNDIS_REQUEST NdisRequest,
     IN NDIS_STATUS   Status
     )
+
 {
     POPEN_INSTANCE      Open;
     PIO_STACK_LOCATION  IrpSp;
     PIRP                Irp;
     PINTERNAL_REQUEST   pRequest;
-    ULONG               FunctionCode;
+    UINT                FunctionCode;
+       KIRQL                           OldIrq;
 
     PPACKET_OID_DATA    OidData;
 
-    IF_LOUD(DbgPrint("Packet: RequestComplete\n");)
+    IF_LOUD(DbgPrint("NPF: RequestComplete\n");)
 
     Open= (POPEN_INSTANCE)ProtocolBindingContext;
+
     pRequest=CONTAINING_RECORD(NdisRequest,INTERNAL_REQUEST,Request);
     Irp=pRequest->Irp;
+
+       if(Irp == NULL){
+
+               // Put the request in the list of the free ones
+               ExInterlockedInsertTailList(&Open->RequestList, &pRequest->ListElement, &Open->RequestSpinLock);
+               
+               return;
+       }
+
     IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
     FunctionCode=IrpSp->Parameters.DeviceIoControl.IoControlCode;
+
     OidData=Irp->AssociatedIrp.SystemBuffer;
+
     if (FunctionCode == BIOCSETOID) {
+
         OidData->Length=pRequest->Request.DATA.SET_INFORMATION.BytesRead;
+
     } else {
+
         if (FunctionCode == BIOCQUERYOID) {
+
             OidData->Length=pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten;
+
                    IF_LOUD(DbgPrint("RequestComplete: BytesWritten=%d\n",pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten);)
         }
+
     }
+
     Irp->IoStatus.Information=IrpSp->Parameters.DeviceIoControl.InputBufferLength;
 
     IF_LOUD(DbgPrint("RequestComplete: BytesReturned=%d\n",IrpSp->Parameters.DeviceIoControl.InputBufferLength);)
@@ -823,147 +1131,136 @@ PacketRequestComplete(
         &Open->RequestList,
         &pRequest->ListElement,
         &Open->RequestSpinLock);
+
     Irp->IoStatus.Status = Status;
+
        Open->IOStatus = Status;
+
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
        // Unlock the IOCTL call
        NdisSetEvent(&Open->IOEvent);
+
     return;
+
+
 }
 
+//-------------------------------------------------------------------
+
 VOID
-PacketStatus(
+NPF_Status(
     IN NDIS_HANDLE   ProtocolBindingContext,
     IN NDIS_STATUS   Status,
     IN PVOID         StatusBuffer,
     IN UINT          StatusBufferSize
     )
+
 {
-    IF_LOUD(DbgPrint("Packet: Status Indication\n");)
+
+    IF_LOUD(DbgPrint("NPF: Status Indication\n");)
+
     return;
+
 }
 
+//-------------------------------------------------------------------
+
 VOID
-PacketStatusComplete(
+NPF_StatusComplete(
     IN NDIS_HANDLE  ProtocolBindingContext
     )
-{
-    IF_LOUD(DbgPrint("Packet: StatusIndicationComplete\n");)
-    return;
-}
-
-#if 0
 
-NTSTATUS
-PacketCreateSymbolicLink(
-    IN  PUNICODE_STRING  DeviceName,
-    IN  BOOLEAN          Create
-    )
 {
-    UNICODE_STRING UnicodeDosDeviceName;
-    NTSTATUS       Status;
 
-    if (DeviceName->Length < sizeof(L"\\Device\\")) {
-        return STATUS_UNSUCCESSFUL;
-    }
-    RtlInitUnicodeString(&UnicodeDosDeviceName,NULL);
-    UnicodeDosDeviceName.MaximumLength=DeviceName->Length+sizeof(L"\\DosDevices")+sizeof(UNICODE_NULL);
-    UnicodeDosDeviceName.Buffer=ExAllocatePool(
-                                    NonPagedPool,
-                                    UnicodeDosDeviceName.MaximumLength
-                                    );
-    if (UnicodeDosDeviceName.Buffer != NULL) {
-        RtlZeroMemory(
-            UnicodeDosDeviceName.Buffer,
-            UnicodeDosDeviceName.MaximumLength
-            );
-        RtlAppendUnicodeToString(
-            &UnicodeDosDeviceName,
-            L"\\DosDevices\\"
-            );
-        RtlAppendUnicodeToString(
-            &UnicodeDosDeviceName,
-            (DeviceName->Buffer+(sizeof("\\Device")))
-            );
-
-        IF_LOUD(DbgPrint("Packet: DosDeviceName is %ws\n",UnicodeDosDeviceName.Buffer);)
+    IF_LOUD(DbgPrint("NPF: StatusIndicationComplete\n");)
 
-        if (Create) {
-            Status=IoCreateSymbolicLink(&UnicodeDosDeviceName,DeviceName);
-        } else {
-            Status=IoDeleteSymbolicLink(&UnicodeDosDeviceName);
-        }
-        ExFreePool(UnicodeDosDeviceName.Buffer);
+    return;
 
-    }
-    return Status;
 }
 
-#endif
+//-------------------------------------------------------------------
 
 NTSTATUS
-PacketReadRegistry(
+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=ExAllocatePool(
-             PagedPool,
-             RegistryPath->Length+sizeof(WCHAR)
-             );
+    Path=ExAllocatePoolWithTag(PagedPool, RegistryPath->Length+sizeof(WCHAR), '7PWA');
+
     if (Path == NULL) {
+               IF_LOUD(DbgPrint("\nPacketReadRegistry: returing STATUS_INSUFFICIENT_RESOURCES\n");)
         return STATUS_INSUFFICIENT_RESOURCES;
     }
+
     RtlZeroMemory(
         Path,
         RegistryPath->Length+sizeof(WCHAR)
         );
+
     RtlCopyMemory(
         Path,
         RegistryPath->Buffer,
         RegistryPath->Length
         );
 
-    IF_LOUD(DbgPrint("Packet: Reg path is %ws\n",RegistryPath->Buffer);)
+    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].QueryRoutine = NULL;
+    ParamTable[0].QueryRoutine = NPF_QueryRegistryRoutine;
     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 = PacketQueryRegistryRoutine;
+
+    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 = PacketQueryRegistryRoutine;
+
+    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,
@@ -971,13 +1268,29 @@ PacketReadRegistry(
                NULL,
                NULL
                );
+
+    if (Status != STATUS_SUCCESS) {
+               // insert hard coded parameters here while registry on ROS is not working...
+               IF_LOUD(DbgPrint("PacketReadRegistry() RtlQueryRegistryValues failed - returing fixed parameters\n");)
+
+        *MacDriverName = ExAllocatePool(PagedPool, 50 * sizeof(WCHAR));
+               //memcpy(*MacDriverName,    L"\\Device\\ne2000", 15 * sizeof(WCHAR));
+               memcpy(*MacDriverName,    L"\\Device\\ne2000", 15 * sizeof(WCHAR));
+               
+        *PacketDriverName = ExAllocatePool(PagedPool, 50 * sizeof(WCHAR));
+               memcpy(*PacketDriverName, L"\\Device\\NPF_ne2000", 19 * sizeof(WCHAR));
+               Status = STATUS_SUCCESS;
+
+       }
+
     ExFreePool(Path);
     return Status;
 }
 
+//-------------------------------------------------------------------
+
 NTSTATUS
-STDCALL
-PacketQueryRegistryRoutine(
+NPF_QueryRegistryRoutine(
     IN PWSTR     ValueName,
     IN ULONG     ValueType,
     IN PVOID     ValueData,
@@ -985,22 +1298,35 @@ PacketQueryRegistryRoutine(
     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=ExAllocatePool(NonPagedPool,ValueLength);
+
+    Buffer=ExAllocatePoolWithTag(NonPagedPool, ValueLength, '8PWA');
+
     if (Buffer==NULL) {
+
         return STATUS_INSUFFICIENT_RESOURCES;
+
     }
+
     RtlCopyMemory(
         Buffer,
         ValueData,
         ValueLength
         );
+
     *((PUCHAR *)EntryContext)=Buffer;
+
     return STATUS_SUCCESS;
+
 }
index a7dd370..18dfcb1 100644 (file)
  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  */
+
+/** @ingroup NPF 
+ *  @{
+ */
+
+/** @defgroup NPF_include NPF structures and definitions 
+ *  @{
+ */
+
+#ifndef __PACKET_INCLUDE______
+#define __PACKET_INCLUDE______
+
+#define NTKERNEL       ///< Forces the compilation of the jitter with kernel calls 
+
 #define UNICODE_NULL ((WCHAR)0) // winnt
 
-#define  MAX_REQUESTS   32
+#include "win_bpf.h"
 
-#define MAX_PACKET_LENGTH 1514
+#include "jitter.h"
+#include "tme.h"
 
-struct timeval {
-        long    tv_sec;         /* seconds */
-        long    tv_usec;        /* and microseconds */
-};
+#define  MAX_REQUESTS   32 ///< Maximum number of simultaneous IOCTL requests.
 
-/*
- * Alignment macros.  Packet_WORDALIGN rounds up to the next 
* even multiple of Packet_ALIGNMENT. 
- */
-#define Packet_ALIGNMENT sizeof(int)
-#define Packet_WORDALIGN(x) (((x)+(Packet_ALIGNMENT-1))&~(Packet_ALIGNMENT-1))
+#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. 
+/***************************/
+/*         IOCTLs          */
+/***************************/
 
+/*!
+  \brief IOCTL code: set kernel buffer size.
 
-//IOCTLs
+  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
-#define         BIOCSRTIMEOUT 7416
-#define         BIOCSMODE 7412
-#define         BIOCSWRITEREP 7413
-#define         BIOCSMINTOCOPY 7414
-#define         BIOCSETOID 2147483648
-#define         BIOCQUERYOID 2147483652
-#define  BIOCGEVNAME 7415
 
-//working modes
-#define MODE_CAPT 0
-#define MODE_STAT 1
+/*!
+  \brief IOCTL code: set the read timeout
 
-//immediate timeout
-#define IMMEDIATE 1
+  This command sets the maximum timeout after which a read is released, also if no data packets were received.
+*/
+#define         BIOCSRTIMEOUT 7416
 
-struct bpf_insn {
-       USHORT  code;
-       UCHAR   jt;
-       UCHAR   jf;
-       int k;
-};
+/*!
+  \brief IOCTL code: set working mode
 
-struct bpf_hdr {
-       struct timeval          bh_tstamp;      /* time stamp */
-       UINT                            bh_caplen;      /* length of captured portion */
-       UINT                            bh_datalen;     /* original length of packet */
-       USHORT                          bh_hdrlen;      /* length of bpf header (this struct plus alignment padding) */
-};
+  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
 
-typedef struct _INTERNAL_REQUEST {
-    LIST_ENTRY     ListElement;
-    PIRP           Irp;
-    NDIS_REQUEST   Request;
+  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
 
-    } INTERNAL_REQUEST, *PINTERNAL_REQUEST;
+/*!
+  \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
 
-//
-// Port device extension.
-//
-typedef struct _DEVICE_EXTENSION {
+  This IOCTL is used to perform an OID set operation on the NIC driver. 
+*/
+#define         BIOCSETOID 2147483648
 
-    PDEVICE_OBJECT DeviceObject;
+/*!
+  \brief IOCTL code: get an OID value
 
-    NDIS_HANDLE    NdisProtocolHandle;
+  This IOCTL is used to perform an OID get operation on the NIC driver. 
+*/
+#define         BIOCQUERYOID 2147483652
 
-    NDIS_STRING    AdapterName;
+/*!
+  \brief IOCTL code: set the name of a the file used by kernel dump mode
 
-    PWSTR          BindString;
-    PWSTR          ExportString;
+  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
 
-} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
+  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
 
-//
-// Open Instance
-//
-typedef struct _OPEN_INSTANCE
-    {
-        PDEVICE_EXTENSION   DeviceExtension;
-        NDIS_HANDLE         AdapterHandle;
-        NDIS_HANDLE         PacketPool;
-               KSPIN_LOCK                  RcvQSpinLock;
-        LIST_ENTRY          RcvList;
-        PIRP                OpenCloseIrp;
-               KSPIN_LOCK                      RequestSpinLock;
-        LIST_ENTRY          RequestList;
-        LIST_ENTRY          ResetIrpList;
-        INTERNAL_REQUEST    Requests[MAX_REQUESTS];
-               PUCHAR                          Buffer;
-               PMDL                            BufferMdl;
-               PKEVENT                         ReadEvent;
-               HANDLE                          ReadEventHandle;
-               UNICODE_STRING          ReadEventName;
-               int                                     Dropped;                        
-               int                                     Received;
-               PUCHAR                          bpfprogram;
-               LARGE_INTEGER           StartTime;  
-               UINT                            Bhead;
-               UINT                            Btail;
-               UINT                            BufSize;
-               UINT                            BLastByte;
-           PMDL                TransferMdl;
-               NDIS_SPIN_LOCK          BufLock;
-               UINT                            MinToCopy;
-               LARGE_INTEGER           TimeOut;
-               int                                     mode;
-               LARGE_INTEGER           Nbytes;
-               LARGE_INTEGER           Npackets;
-               NDIS_SPIN_LOCK          CountersLock;
-               UINT                            Nwrites;
-               UINT                            Multiple_Write_Counter;
-               NDIS_EVENT                      WriteEvent;    
-               NDIS_EVENT                      IOEvent;
-               NDIS_STATUS                     IOStatus;
-               BOOLEAN                         Bound;
-    } 
-OPEN_INSTANCE, *POPEN_INSTANCE;
+/*!
+  \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
+
+// 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.
+
+
+// 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.
+
+/*!
+  \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).
+};
 
+/*!
+  \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
+    NDIS_REQUEST   Request;                    ///< The structure with the actual request, that will be passed to NdisRequest().
+} 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;
-    PIRP           Irp;
-    PMDL           pMdl;
-    }  PACKET_RESERVED, *PPACKET_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().
+}  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 {
+    PDEVICE_OBJECT DeviceObject;               ///< Adapter's device.
+    NDIS_HANDLE    NdisProtocolHandle; ///< NDIS handle of NPF.
+    NDIS_STRING    AdapterName;                        ///< Name of the adapter.
+    PWSTR          BindString;                 ///< Original  device 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 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.
+       PIRP                OpenCloseIrp;               ///< Pointer used to store the open/close IRP requests and provide them to the 
+                                                                                       ///< callbacks of NDIS.
+       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.
+       HANDLE                          ReadEventHandle;        ///< Handle of the event on which the read calls on this instance must wait.
+       UNICODE_STRING          ReadEventName;          ///< Name of the event on which the read calls on this instance must wait.
+                                                                                       ///< The event is created with a name, so it can be used at user level to know when it 
+                                                                                       ///< is possible to access the driver without being blocked. This fiels stores the name 
+                                                                                       ///< that and is used by the BIOCGEVNAME IOCTL call.
+       INT                                     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.
+       INT                                     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.
+       INT                                     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.
+       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.
+       JIT_BPF_Filter          *Filter;                        ///< Pointer to the native filtering function created by the jitter. 
+                                                                                       ///< See BPF_jitter() for details.
+       PUCHAR                          Buffer;                         ///< Pointer to the circular buffer associated with every driver instance. It contains the 
+                                                                                       ///< data that will be passed to the application. See \ref NPF for details.
+       UINT                            Bhead;                          ///< Head of the circular buffer.
+       UINT                            Btail;                          ///< Tail of the circular buffer.
+       UINT                            BufSize;                        ///< Size of the circular buffer.
+       UINT                            BLastByte;                      ///< Position of the last valid byte in the circular buffer.
+       PMDL                TransferMdl;                ///< MDL used to map the portion of the buffer that will contain an incoming packet. 
+                                                                                       ///< Used by NdisTransferData().
+       NDIS_SPIN_LOCK          BufLock;                        ///< SpinLock that protects the access tho the circular buffer variables.
+       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
+       UINT                            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.
+       NDIS_EVENT                      IOEvent;                        ///< Event used to synchronize I/O requests with the callback structure of NDIS.
+       NDIS_STATUS                     IOStatus;                       ///< Maintains the status of and OID request call, that will be passed to the application.
+       BOOLEAN                         Bound;                          ///< Specifies if NPF is still bound to the adapter used by this instance. Bound can be
+                                                                                       ///< FALSE if a Plug and Play adapter has been removed or disabled by the user.
+       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.
+       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
+       NDIS_SPIN_LOCK          machine_lock;           ///< SpinLock that protects the mem_ex buffer
+} OPEN_INSTANCE, *POPEN_INSTANCE;
+
+
+#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.
+
+#ifdef __GNUC__
+#undef EXIT_SUCCESS
+#undef EXIT_FAILURE
+#endif
+
+/// 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;\
+
+/**
+ *  @}
+ */
 
-#define  ETHERNET_HEADER_LENGTH   14
 
-#define RESERVED(_p) ((PPACKET_RESERVED)((_p)->ProtocolReserved))
+/***************************/
+/*       Prototypes        */
+/***************************/
 
-#define  TRANSMIT_PACKETS    128
+/** @defgroup NPF_code NPF functions 
+ *  @{
+ */
 
-//
-// Prototypes
-//
 
-PKEY_VALUE_PARTIAL_INFORMATION getTcpBindings(
-       VOID
-       );
+/*!
+  \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.
 
-PWCHAR getAdaptersList(
-       VOID
-       );
+  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.
+  \param aProtoHandle NDIS protocol handle of NPF.
+  \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 createDevice(
        IN OUT PDRIVER_OBJECT adriverObjectP,
        IN PUNICODE_STRING amacNameP,
        NDIS_HANDLE aProtoHandle);
 
+/*!
+  \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
+    );
 
-VOID
-PacketCancelRoutine (
-    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
-PacketOpenAdapterComplete(
+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_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
-PacketCloseAdapterComplete(
+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 <b>available to NPF</b>. 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
-Packet_tap(
+NPF_tap(
     IN NDIS_HANDLE ProtocolBindingContext,
     IN NDIS_HANDLE MacReceiveContext,
     IN PVOID HeaderBuffer,
@@ -206,37 +537,157 @@ Packet_tap(
     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
-PacketReceiveComplete(
-    IN NDIS_HANDLE  ProtocolBindingContext
+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
     );
 
 
+/*!
+  \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().
+*/
 VOID
-PacketRequestComplete(
+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.
+  \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 Ends a send operation.
+  \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+  \param pRequest 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
-PacketSendComplete(
+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
-PacketResetComplete(
+NPF_ResetComplete(
     IN NDIS_HANDLE  ProtocolBindingContext,
     IN NDIS_STATUS  Status
     );
 
-
+/*!
+  \brief Callback for NDIS StatusHandler. Not used by NPF
+*/
 VOID
-PacketStatus(
+NPF_Status(
     IN NDIS_HANDLE   ProtocolBindingContext,
     IN NDIS_STATUS   Status,
     IN PVOID         StatusBuffer,
@@ -244,117 +695,68 @@ PacketStatus(
     );
 
 
+/*!
+  \brief Callback for NDIS StatusCompleteHandler. Not used by NPF
+*/
 VOID
-PacketStatusComplete(
-    IN NDIS_HANDLE  ProtocolBindingContext
-    );
-
-VOID
-PacketTransferDataComplete(
-    IN NDIS_HANDLE ProtocolBindingContext,
-    IN PNDIS_PACKET Packet,
-    IN NDIS_STATUS Status,
-    IN UINT BytesTransferred
-    );
+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
-PacketRemoveReference(
-    IN PDEVICE_EXTENSION DeviceExtension
-    );
-
-
+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
-PacketCleanup(
-    IN PDEVICE_OBJECT DeviceObject,
-    IN PIRP FlushIrp
-    );
-
-
-NTSTATUS
-PacketShutdown(
+NPF_Read(
     IN PDEVICE_OBJECT DeviceObject,
     IN PIRP Irp
     );
 
-VOID
-STDCALL
-PacketUnload(
-    IN PDRIVER_OBJECT DriverObject
-    );
+/*!
+  \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
-STDCALL
-PacketOpen(
-    IN PDEVICE_OBJECT DeviceObject,
-    IN PIRP Irp
-    );
-
-NTSTATUS
-STDCALL
-PacketClose(
-    IN PDEVICE_OBJECT DeviceObject,
-    IN PIRP Irp
-    );
-
-NTSTATUS
-STDCALL
-PacketWrite(
-    IN PDEVICE_OBJECT DeviceObject,
-    IN PIRP Irp
-    );
-
-NTSTATUS
-STDCALL
-PacketRead(
-    IN PDEVICE_OBJECT DeviceObject,
-    IN PIRP Irp
-    );
-
-NTSTATUS
-STDCALL
-PacketIoControl(
-    IN PDEVICE_OBJECT DeviceObject,
-    IN PIRP Irp
-    );
-
-NTSTATUS
-STDCALL
-DriverEntry(
-    IN PDRIVER_OBJECT DriverObject,
-    IN PUNICODE_STRING RegistryPath
-    );
-
-NTSTATUS
-PacketReadRegistry(
+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
-PacketCreateSymbolicLink(
-    IN  PUNICODE_STRING  DeviceName,
-    IN  BOOLEAN          Create
-    );
-/*
-typedef NTSTATUS STDCALL
-(*PRTL_QUERY_REGISTRY_ROUTINE)(PWSTR ValueName,
-                              ULONG ValueType,
-                              PVOID ValueData,
-                              ULONG ValueLength,
-                              PVOID Context,
-                              PVOID EntryContext);
-    DriverObject->MajorFunction[IRP_MJ_CREATE] = PacketOpen;
-    DriverObject->MajorFunction[IRP_MJ_CLOSE]  = PacketClose;
-    DriverObject->MajorFunction[IRP_MJ_READ]   = PacketRead;
-    DriverObject->MajorFunction[IRP_MJ_WRITE]  = PacketWrite;
-    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]  = PacketIoControl;
-    DriverObject->DriverUnload = PacketUnload;
- */
-NTSTATUS
-STDCALL
-PacketQueryRegistryRoutine(
+NPF_QueryRegistryRoutine(
     IN PWSTR     ValueName,
     IN ULONG     ValueType,
     IN PVOID     ValueData,
@@ -363,13 +765,12 @@ PacketQueryRegistryRoutine(
     IN PVOID     EntryContext
     );
 
-INT
-Packet_multiple_tap(
-    IN    NDIS_HANDLE         ProtocolBindingContext,
-    IN    PNDIS_PACKET        Packet
-    );
-
-VOID PacketBindAdapter(
+/*!
+  \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,
@@ -377,29 +778,180 @@ VOID PacketBindAdapter(
     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
-PacketUnbindAdapter(
+NPF_UnbindAdapter(
     OUT PNDIS_STATUS        Status,
     IN  NDIS_HANDLE         ProtocolBindingContext,
     IN  NDIS_HANDLE         UnbindContext
     );
 
-
-int bpf_validate(struct bpf_insn *f,int len);
-
+/*!
+  \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. 
+*/
+int bpf_validate(struct bpf_insn *f,int len, uint32 mem_ex_size);
+
+/*!
+  \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.
+*/
 UINT bpf_filter(register struct bpf_insn *pc,
                                register UCHAR *p,
                                UINT wirelen,
-                               register UINT buflen);
-
+                               register UINT buflen,
+                               PMEM_TYPE mem_ex,
+                               PTME_CORE tme,
+                               struct time_conv *time_ref);
+
+/*!
+  \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.
+*/
 UINT bpf_filter_with_2_buffers(register struct bpf_insn *pc,
                                                           register UCHAR *p,
                                                           register UCHAR *pd,
                                                           register int headersize,
                                                           UINT wirelen,
-                                                          register UINT buflen);
+                                                          register UINT buflen,
+                                                          PMEM_TYPE mem_ex,
+                                              PTME_CORE tme,
+                                                          struct time_conv *time_ref);
+
+/*!
+  \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(POPEN_INSTANCE 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);
+
+/*!
+  \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
+
+/**
+ *  @}
+ */
+
+/**
+ *  @}
+ */
+
+#endif  /*main ifndef/define*/
 
-VOID ReadTimeout(IN PKDPC Dpc,
-                                IN PVOID DeferredContext,
-                                IN PVOID SystemContext1,
-                                IN PVOID SystemContext2);
index c1fa496..47f2b3d 100644 (file)
@@ -6,8 +6,8 @@
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,3,0,33
- PRODUCTVERSION 2,3,0,33
+ FILEVERSION 3,0,0,13
+ PRODUCTVERSION 3,0,0,13
  FILEFLAGSMASK 0x3fL
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -24,16 +24,16 @@ BEGIN
         BEGIN
             VALUE "Comments", "Netgroup Packet Filter Driver\0"
             VALUE "CompanyName", "Politecnico di Torino\0"
-            VALUE "FileDescription", "NPF Driver\0"
-            VALUE "FileVersion", "2, 3, 0, 33\0"
-            VALUE "InternalName", "NPF\0"
+            VALUE "FileDescription", "NPF Driver - TME extensions\0"
+            VALUE "FileVersion", "3, 0, 0, 13\0"
+            VALUE "InternalName", "NPF + TME \0"
             VALUE "LegalCopyright", "Copyright © 2002\0"
             VALUE "LegalTrademarks", "\0"
             VALUE "OriginalFilename", "NPF.RC\0"
-            VALUE "PrivateBuild", "\0"
+            VALUE "PrivateBuild", "REACTOS PRIVATE BUILD\0"
             VALUE "ProductName", "NPF Driver\0"
-            VALUE "ProductVersion", "2, 3, 0, 33\0"
-            VALUE "SpecialBuild", "\0"
+            VALUE "ProductVersion", "3, 0, 0, 13\0"
+            VALUE "SpecialBuild", "Beta testing use only\0"
         END
     END
     BLOCK "VarFileInfo"
index eb79455..fc82870 100644 (file)
 #include <ndis.h>
 #else
 #include <ddk/ntddk.h>
-//#include <net/miniport.h>
 #include <net/ndis.h>
 #endif
 
 #include "debug.h"
 #include "packet.h"
+#include "win_bpf.h"
 
+#include "tme.h"
+#include "time_calls.h"
+
+extern struct time_conv G_Start_Time; // from openclos.c
 
 //-------------------------------------------------------------------
 
@@ -80,11 +84,10 @@ UINT n,i,NBlocks;
        *Bhead+=n;
 }
 
-
 //-------------------------------------------------------------------
 
-NTSTATUS STDCALL
-PacketRead(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
+NTSTATUS
+NPF_Read(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
 {
     POPEN_INSTANCE      Open;
     PIO_STACK_LOCATION  IrpSp;
@@ -101,51 +104,57 @@ PacketRead(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
        LARGE_INTEGER           TimeFreq;
        struct bpf_hdr          *header;
        KIRQL                           Irql;
+       PUCHAR                          UserPointer;
+       ULONG                           bytecopy;
 
-       IF_LOUD(DbgPrint("Packet: Read\n");)
-
+       IF_LOUD(DbgPrint("NPF: Read\n");)
+               
        IrpSp = IoGetCurrentIrpStackLocation(Irp);
     Open=IrpSp->FileObject->FsContext;
-
-       if( Open->Bound == FALSE){
-               // The Network adapter was removed. Return immediately with a failure status
-               Irp->IoStatus.Information = 0;
-               Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
-               IoCompleteRequest(Irp, IO_NO_INCREMENT);
-               return(STATUS_UNSUCCESSFUL);
+       
+       if( Open->Bound == FALSE ){
+               // The Network adapter was removed.
+               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
+               EXIT_FAILURE(0);
+       }
+
        //See if the buffer is full enough to be copied
-       if (GetBuffOccupation(Open)<=Open->MinToCopy)
+       if( GetBuffOccupation(Open) <= Open->MinToCopy || Open->mode & MODE_DUMP )
        {
-               //there are not enough buffered packets: the application must wait
-               
                //wait until some packets arrive or the timeout expires         
                if(Open->TimeOut.QuadPart != (LONGLONG)IMMEDIATE)
                        KeWaitForSingleObject(Open->ReadEvent,
                                UserRequest,
                                KernelMode,
-                               TRUE ,
+                               TRUE,
                                (Open->TimeOut.QuadPart == (LONGLONG)0)? NULL: &(Open->TimeOut));
 
                KeClearEvent(Open->ReadEvent);
                
-               if(Open->mode==MODE_STAT){   //this capture instance is in statistics mode
+               if(Open->mode & MODE_STAT){   //this capture instance is in statistics mode
                        CurrBuff=(PUCHAR)MmGetSystemAddressForMdl(Irp->MdlAddress);
                        
-                       //get the timestamp
-                       CapTime=KeQueryPerformanceCounter(&TimeFreq); 
                        //fill the bpf header for this packet
-                       CapTime.QuadPart+=Open->StartTime.QuadPart;
                        header=(struct bpf_hdr*)CurrBuff;
-#ifndef __NTDRIVER__ // robert
-                       header->bh_tstamp.tv_usec=(long)((CapTime.QuadPart%TimeFreq.QuadPart*1000000)/TimeFreq.QuadPart);
-                       header->bh_tstamp.tv_sec=(long)(CapTime.QuadPart/TimeFreq.QuadPart);
-#endif
-            header->bh_caplen=16;
-                       header->bh_datalen=16;
-                       header->bh_hdrlen=sizeof(struct bpf_hdr);
-                       
+                       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;
                        
@@ -155,21 +164,78 @@ PacketRead(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
                        Open->Nbytes.QuadPart=0;
                        NdisReleaseSpinLock( &Open->CountersLock );
                        
-                       Irp->IoStatus.Information = 16 + sizeof(struct bpf_hdr);
                        Irp->IoStatus.Status = STATUS_SUCCESS;
                        IoCompleteRequest(Irp, IO_NO_INCREMENT);
                        
                        return STATUS_SUCCESS;
                }
                
-               if (Open->Bhead == Open->Btail)
-                       //the timeout has expired, but the buffer is still empty.
-                       //we must awake the application returning an empty buffer.
+               if(Open->mode==MODE_MON)   //this capture instance is in monitor mode
+               {   
+                       PTME_DATA data;
+                       ULONG cnt;
+                       ULONG block_size;
+                       PUCHAR tmp;
+
+                       UserPointer=MmGetSystemAddressForMdl(Irp->MdlAddress);
+                       
+                       if ((!IS_VALIDATED(Open->tme.validated_blocks,Open->tme.active_read))||(IrpSp->Parameters.Read.Length<sizeof(struct bpf_hdr)))
+                       {       
+                               EXIT_FAILURE(0);
+                       }
+                       
+                       header=(struct bpf_hdr*)UserPointer;
+       
+                       GET_TIME(&header->bh_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))<bytecopy)
+                               bytecopy=(IrpSp->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;cnt<bytecopy;cnt++)
+                       {
+                               NdisAcquireSpinLock(&Open->machine_lock);
+                               RtlCopyMemory(UserPointer,tmp,block_size);
+                               NdisReleaseSpinLock(&Open->machine_lock);
+                               tmp+=block_size;
+                               UserPointer+=block_size;
+                       }
+                                               
+                       bytecopy*=block_size;
+
+                       header->bh_caplen=bytecopy;
+                       header->bh_datalen=header->bh_caplen;
+
+                       EXIT_SUCCESS(bytecopy+sizeof(struct bpf_hdr));
+               }
+
+               if (Open->Bhead == Open->Btail || 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.
                {
-                       Irp->IoStatus.Information = 0;
-                       Irp->IoStatus.Status = STATUS_SUCCESS;
-                       IoCompleteRequest(Irp, IO_NO_INCREMENT);
-                       return(STATUS_SUCCESS);
+                       EXIT_SUCCESS(0);
                }
                                
        }
@@ -179,66 +245,61 @@ PacketRead(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
        //
        NdisAcquireSpinLock( &Open->BufLock );
        
-       Thead=Open->Bhead;
-       Ttail=Open->Btail;
-       TLastByte=Open->BLastByte;
-       
+       Thead = Open->Bhead;
+       Ttail = Open->Btail;
+       TLastByte = Open->BLastByte;
+
        //get the address of the buffer
        CurrBuff=Open->Buffer;
-
+       
        NdisReleaseSpinLock( &Open->BufLock );
        
        Input_Buffer_Length=IrpSp->Parameters.Read.Length;
        packp=(PUCHAR)MmGetMdlVirtualAddress(Irp->MdlAddress);
-
        
+
        //
        //fill the application buffer
        //
-       if(Ttail>Thead){        //first of all see if it we can copy all the buffer in one time
+       if(Ttail > Thead){      //first of all see if it we can copy all the buffer in one time
                if((Ttail-Thead)<Input_Buffer_Length){
                        KeResetEvent(Open->ReadEvent);
+
                        PacketMoveMem(packp,CurrBuff+Thead,Ttail-Thead,&(Open->Bhead));
-                       Irp->IoStatus.Information = Ttail-Thead;
-                       Irp->IoStatus.Status = STATUS_SUCCESS;
-                       IoCompleteRequest(Irp, IO_NO_INCREMENT);
-                       return(STATUS_SUCCESS);
+                       EXIT_SUCCESS(Ttail-Thead);
                }
        }
-       else if((TLastByte-Thead)<Input_Buffer_Length){
-               PacketMoveMem(packp,CurrBuff+Thead,TLastByte-Thead,&(Open->Bhead));
+       else if((TLastByte - Thead) < Input_Buffer_Length){
+               PacketMoveMem(packp, CurrBuff+Thead, TLastByte - Thead, &(Open->Bhead));
 
                NdisAcquireSpinLock( &Open->BufLock );
                
-               Open->BLastByte=Open->Btail;
-               Open->Bhead=0;
+               Open->BLastByte = Open->Btail;
+               Open->Bhead = 0;
 
                NdisReleaseSpinLock( &Open->BufLock );
                
-               Irp->IoStatus.Information = TLastByte-Thead;
-               Irp->IoStatus.Status = STATUS_SUCCESS;
-               IoCompleteRequest(Irp, IO_NO_INCREMENT);
-               return(STATUS_SUCCESS);
+               EXIT_SUCCESS(TLastByte-Thead);
        }
        
        //the buffer must be scannned to determine the number of bytes to copy
-       i=0;
        CpStart=Thead;
+       i=0;
        while(TRUE){
-               if(Thead==Ttail)break;
+               if(Thead == Ttail)break;
 
-               if(Thead==TLastByte){
+               if(Thead == TLastByte){
                        // Copy the portion between thead and TLastByte
                        PacketMoveMem(packp,CurrBuff+CpStart,Thead-CpStart,&(Open->Bhead));
                        packp+=(Thead-CpStart);
 
                        NdisAcquireSpinLock( &Open->BufLock );
                        
-                       Open->BLastByte=Open->Btail;
-                       Open->Bhead=0;
+                       Open->BLastByte = Open->Btail;
+                       Open->Bhead = 0;
                        
                        NdisReleaseSpinLock( &Open->BufLock );
-                       
+
                        Thead=0;
                        CpStart=0;
                }
@@ -247,11 +308,7 @@ PacketRead(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
                if((i+cplen > Input_Buffer_Length)){//no more space in the application's buffer
                        PacketMoveMem(packp,CurrBuff+CpStart,Thead-CpStart,&(Open->Bhead));
 
-                       Irp->IoStatus.Information = i;
-                       Irp->IoStatus.Status = STATUS_SUCCESS;
-                       IoCompleteRequest(Irp, IO_NO_INCREMENT);
-                       
-                       return(STATUS_SUCCESS); 
+                       EXIT_SUCCESS(i);
                }
                cplen=Packet_WORDALIGN(cplen);
                i+=cplen;
@@ -265,17 +322,13 @@ PacketRead(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
        
        Open->Bhead=Thead;
        
-       Irp->IoStatus.Information = i;
-       Irp->IoStatus.Status = STATUS_SUCCESS;
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-       
-    return(STATUS_SUCCESS);
        
+       EXIT_SUCCESS(i);        
 }
 
 //-------------------------------------------------------------------
 
-NDIS_STATUS Packet_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE MacReceiveContext,
+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)
 {
@@ -285,7 +338,6 @@ NDIS_STATUS Packet_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE Mac
     NDIS_STATUS         Status;
     UINT                BytesTransfered;
     ULONG               BufferLength;
-    PPACKET_RESERVED    Reserved;
     PMDL                pMdl;
        LARGE_INTEGER           CapTime;
        LARGE_INTEGER           TimeFreq;
@@ -296,13 +348,26 @@ NDIS_STATUS Packet_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE Mac
        UINT                            TLastByte;
        UINT                            fres;
        UINT                            maxbufspace;
+       USHORT                          NPFHdrSize;
+       UINT                            BufOccupation;
 
-    IF_LOUD(DbgPrint("Packet: tap\n");)
+    IF_VERY_LOUD(DbgPrint("NPF: tap\n");)
 
        Open= (POPEN_INSTANCE)ProtocolBindingContext;
 
-       Open->Received++;               //number of packets received by filter ++
+       Open->Received++;               // Number of packets received by filter ++
 
+       BufOccupation = GetBuffOccupation(Open);        // Get the full buffer space
+
+       if(((Open->mode&MODE_CAPT)||(Open->mode&MODE_DUMP)) && Open->BufSize - BufOccupation < PacketSize+HeaderBufferSize+sizeof(struct bpf_hdr)){
+               // Heuristic that drops the packet also if it possibly fits in the buffer.
+               // It allows to avoid filtering in critical situations when CPU is very important.
+               Open->Dropped++;
+               return NDIS_STATUS_NOT_ACCEPTED;
+       }
+
+       NdisAcquireSpinLock(&Open->machine_lock);
+       
        //
        //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
@@ -316,24 +381,64 @@ NDIS_STATUS Packet_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE Mac
                                                                           LookAheadBuffer,
                                                                           HeaderBufferSize,
                                                                           PacketSize+HeaderBufferSize,
-                                                                          LookaheadBufferSize+HeaderBufferSize);
-       else
-               fres=bpf_filter((struct bpf_insn*)(Open->bpfprogram),
-                               HeaderBuffer,
-                                               PacketSize+HeaderBufferSize,
-                                               LookaheadBufferSize+HeaderBufferSize);
+                                                                          LookaheadBufferSize+HeaderBufferSize,
+                                                                          &Open->mem_ex,
+                                                                          &Open->tme,
+                                                                          &G_Start_Time);
+       
+       
+       else 
+               if(Open->Filter != NULL)
+               {
+                       if (Open->bpfprogram != NULL)
+                       {
+                               fres=Open->Filter->Function(HeaderBuffer,
+                                                                       PacketSize+HeaderBufferSize,
+                                                                       LookaheadBufferSize+HeaderBufferSize);
+               
+                               // Restore the stack. 
+                               // I ignore the reason, but this instruction is needed only at kernel level
+#ifndef __GNUC__
+                               _asm add esp,12         
+#else
+#endif
+                       }
+                       else
+                               fres = -1;
+               }
+               else
+                       fres=bpf_filter((struct bpf_insn*)(Open->bpfprogram),
+                               HeaderBuffer,
+                                               PacketSize+HeaderBufferSize,
+                                               LookaheadBufferSize+HeaderBufferSize,
+                                               &Open->mem_ex,
+                                               &Open->tme,
+                                               &G_Start_Time);
+
+       NdisReleaseSpinLock(&Open->machine_lock);
+       
+       if(Open->mode==MODE_MON)
+       // we are in monitor mode
+       {
+               if (fres==1) 
+                       KeSetEvent(Open->ReadEvent,0,FALSE);
+               return NDIS_STATUS_NOT_ACCEPTED;
+
+       }
+
+       if(fres==0)
+               // Packet not accepted by the filter, ignore it.
+               return NDIS_STATUS_NOT_ACCEPTED;
 
-       if(fres==0)return NDIS_STATUS_NOT_ACCEPTED; //packet not accepted by the filter
        //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){
+       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
@@ -343,32 +448,42 @@ NDIS_STATUS Packet_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE Mac
                Open->Nbytes.QuadPart+=12;
 
                NdisReleaseSpinLock( &Open->CountersLock );
-
-               return NDIS_STATUS_NOT_ACCEPTED;
+               
+               if(!(Open->mode & MODE_DUMP)){
+                       return NDIS_STATUS_NOT_ACCEPTED;
+               }
        }
 
        if(Open->BufSize==0)return NDIS_STATUS_NOT_ACCEPTED;
+       
+       if(Open->mode & MODE_DUMP && Open->MaxDumpPacks &&      (UINT)Open->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
+               KeSetEvent(Open->ReadEvent,0,FALSE);
 
+               return NDIS_STATUS_NOT_ACCEPTED;
+       }
+
+       // Calculate the correct size for the header associated with the packet
+       NPFHdrSize=(Open->mode==MODE_CAPT)? sizeof(struct bpf_hdr): sizeof(struct sf_pkthdr);
        NdisAcquireSpinLock( &Open->BufLock );
 
        Thead=Open->Bhead;
        Ttail=Open->Btail;
-       TLastByte=Open->BLastByte;
-       NdisReleaseSpinLock( &Open->BufLock );
-
-       maxbufspace=Packet_WORDALIGN(fres+sizeof(struct bpf_hdr));
+       TLastByte = Open->BLastByte;
 
-       if((Ttail < Thead) && (Ttail+maxbufspace+1 >= Thead))
-       {
-               //the buffer is full: the incoming packet is lost
-               Open->Dropped++;
-               return NDIS_STATUS_NOT_ACCEPTED;
-       }
+       NdisReleaseSpinLock( &Open->BufLock );
+       
+       maxbufspace=Packet_WORDALIGN(fres+NPFHdrSize);
 
        if(Ttail+maxbufspace >= Open->BufSize){
-               if(Thead<=maxbufspace)
+               if(Thead <= maxbufspace)
                {
-                       //the buffer is full: the packet is lost
                        Open->Dropped++;
                        return NDIS_STATUS_NOT_ACCEPTED;
                }
@@ -378,97 +493,135 @@ NDIS_STATUS Packet_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE Mac
        }
        
        CurrBuff=Open->Buffer+Ttail;
-       
-       //  Allocate an MDL to map the portion of the buffer following the
-       //  header
-       pMdl=IoAllocateMdl(CurrBuff+HeaderBufferSize+LookaheadBufferSize+sizeof(struct bpf_hdr),maxbufspace,FALSE,FALSE,NULL);
-       if (pMdl == NULL)
-       {
-               //no memory: packet lost
-               IF_LOUD(DbgPrint("Packet: Read-Failed to allocate Mdl\n");)
-               Open->Dropped++;
-               return NDIS_STATUS_NOT_ACCEPTED;
-       }
-       MmBuildMdlForNonPagedPool(pMdl);
-       
-       //allocate the packet from NDIS
-       NdisAllocatePacket(&Status,&pPacketb,Open->PacketPool);
-       if (Status != NDIS_STATUS_SUCCESS)
+
+       if(LookaheadBufferSize != PacketSize || (UINT)LookAheadBuffer-(UINT)HeaderBuffer != HeaderBufferSize)
        {
-               IF_LOUD(DbgPrint("Packet: Read- No free packets\n");)
+               //  Allocate an MDL to map the portion of the buffer following the header
+               pMdl=IoAllocateMdl(CurrBuff+HeaderBufferSize+LookaheadBufferSize+NPFHdrSize,
+                       maxbufspace,
+                       FALSE,
+                       FALSE,
+                       NULL);
+
+               if (pMdl == NULL)
+               {
+                       // Unable to map the memory: packet lost
+                       IF_LOUD(DbgPrint("NPF: Read-Failed to allocate Mdl\n");)
+                               Open->Dropped++;
+                       return NDIS_STATUS_NOT_ACCEPTED;
+               }
+               MmBuildMdlForNonPagedPool(pMdl);
+               
+               //allocate the packet from NDIS
+               NdisAllocatePacket(&Status, &pPacketb, Open->PacketPool);
+               if (Status != NDIS_STATUS_SUCCESS)
+               {
+                       IF_LOUD(DbgPrint("NPF: Tap - No free packets\n");)
                        IoFreeMdl(pMdl);
-               Open->Dropped++;
-               return NDIS_STATUS_NOT_ACCEPTED;
-       }
-       //link the buffer to the packet
-       NdisChainBufferAtFront(pPacketb,pMdl);
+                       Open->Dropped++;
+                       return NDIS_STATUS_NOT_ACCEPTED;
+               }
+               //link the buffer to the packet
+               NdisChainBufferAtFront(pPacketb,pMdl);
                
-       //Find out how much to transfer
-       SizeToTransfer = fres-HeaderBufferSize;
-
-       //copy the ethernet header into buffer
-       NdisMoveMappedMemory((CurrBuff)+sizeof(struct bpf_hdr),HeaderBuffer,HeaderBufferSize);
-
-       //Copy the look ahead buffer
-    if(LookaheadBufferSize)
-       {
-               NdisMoveMappedMemory((CurrBuff)+sizeof(struct bpf_hdr) + HeaderBufferSize,
-                       LookAheadBuffer, 
-                       (SizeToTransfer < LookaheadBufferSize)? SizeToTransfer : LookaheadBufferSize );
+               BufferLength=fres-HeaderBufferSize;
+               //Find out how much to transfer
+               SizeToTransfer = (PacketSize < BufferLength) ? PacketSize : BufferLength;
+               
+               //copy the ethernet header into buffer
+               NdisMoveMappedMemory((CurrBuff)+NPFHdrSize,HeaderBuffer,HeaderBufferSize);
+               
+               //Copy the look ahead buffer
+               if(LookaheadBufferSize)
+               {
+                       NdisMoveMappedMemory((CurrBuff) + NPFHdrSize + HeaderBufferSize,
+                               LookAheadBuffer, 
+                               (SizeToTransfer < LookaheadBufferSize)? SizeToTransfer : LookaheadBufferSize );
+                       
+                       SizeToTransfer = (SizeToTransfer > LookaheadBufferSize)?
+                               SizeToTransfer - LookaheadBufferSize : 0;
+               }
+               
+               Open->TransferMdl=pMdl;
+               
+               if(SizeToTransfer)
+               {
+                       //Call the Mac to transfer the packet
+                       NdisTransferData(&Status,
+                               Open->AdapterHandle,
+                               MacReceiveContext,
+                               LookaheadBufferSize,
+                               SizeToTransfer,
+                               pPacketb,
+                               &BytesTransfered);
+               }
+               else{
+                       BytesTransfered = 0;
+               }
                
-               SizeToTransfer = (SizeToTransfer > LookaheadBufferSize)?
-                       SizeToTransfer - LookaheadBufferSize : 0;
        }
-       
-       Open->TransferMdl=pMdl;
-
-       if(SizeToTransfer)
+       else
        {
-               //Call the Mac to transfer the packet
-               NdisTransferData(&Status,
-                       Open->AdapterHandle,
-                       MacReceiveContext,
-                       LookaheadBufferSize,
-                       SizeToTransfer,
-                       pPacketb,
-                       &BytesTransfered);
-       }
-       else{
-               BytesTransfered = 0;
+       // The whole packet is in the lookahead buffer, we can avoid the call to NdisTransferData.
+       // This allows us to avoid the allocation of the MDL and the NDIS packet as well
+       RtlCopyMemory((CurrBuff) + NPFHdrSize,
+               HeaderBuffer,
+               HeaderBufferSize + LookaheadBufferSize);
+
+               Open->TransferMdl = NULL;
+               Status = NDIS_STATUS_SUCCESS;
        }
 
+       Open->Accepted++;               // Increase the accepted packets counter
+
        if (Status != NDIS_STATUS_FAILURE)
        {
-               //store the capture time
-               CapTime=KeQueryPerformanceCounter(&TimeFreq); 
 
                if( fres > (BytesTransfered+HeaderBufferSize+LookaheadBufferSize) )
                        fres = BytesTransfered+HeaderBufferSize+LookaheadBufferSize;
-
-               //fill the bpf header for this packet
-               CapTime.QuadPart+=Open->StartTime.QuadPart;
+               
+               //
+               // Build the header
+               //
                header=(struct bpf_hdr*)CurrBuff;
-#ifndef __NTDRIVER__ // robert
-               header->bh_tstamp.tv_usec=(long)((CapTime.QuadPart%TimeFreq.QuadPart*1000000)/TimeFreq.QuadPart);
-               header->bh_tstamp.tv_sec=(long)(CapTime.QuadPart/TimeFreq.QuadPart);
-#endif
-        header->bh_caplen=fres;
+               GET_TIME(&header->bh_tstamp,&G_Start_Time);
+               header->bh_caplen=fres;
                header->bh_datalen=PacketSize+HeaderBufferSize;
-               header->bh_hdrlen=sizeof(struct bpf_hdr);
+               if(Open->mode==MODE_CAPT){
+                       header->bh_hdrlen=NPFHdrSize;
+                       // Don't align if the packet goes to disk
+                       Ttail+=Packet_WORDALIGN(fres + NPFHdrSize);
+               }
+               else
+                       Ttail+=fres+NPFHdrSize;
                
                //update the buffer     
-               Ttail+=Packet_WORDALIGN(fres+sizeof(struct bpf_hdr));
-
-               if(Ttail>Thead)TLastByte=Ttail;
+               if(Ttail > Thead)TLastByte = Ttail;
 
                NdisAcquireSpinLock( &Open->BufLock );
+               
                Open->Btail=Ttail;
                Open->BLastByte=TLastByte;
+               
                NdisReleaseSpinLock( &Open->BufLock );
-
        }
+
        if (Status != NDIS_STATUS_PENDING){
-               PacketTransferDataComplete(Open,pPacketb,Status,fres);
+
+               if( Open->TransferMdl != NULL)
+                       // Complete the request and free the buffers
+                       NPF_TransferDataComplete(Open,pPacketb,Status,fres);
+               else{
+                       // Unfreeze the consumer
+                       if(GetBuffOccupation(Open)>Open->MinToCopy){
+                               if(Open->mode & MODE_DUMP){
+                                       NdisSetEvent(&Open->DumpEvent);
+                               }
+                               else
+                                       KeSetEvent(Open->ReadEvent,0,FALSE);    
+                       }
+                       
+               }
        }
        
        return NDIS_STATUS_SUCCESS;
@@ -477,12 +630,12 @@ NDIS_STATUS Packet_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE Mac
 
 //-------------------------------------------------------------------
 
-VOID PacketTransferDataComplete (IN NDIS_HANDLE ProtocolBindingContext,IN PNDIS_PACKET pPacket,
+VOID NPF_TransferDataComplete (IN NDIS_HANDLE ProtocolBindingContext,IN PNDIS_PACKET pPacket,
                                  IN NDIS_STATUS Status,IN UINT BytesTransfered)
 {
     POPEN_INSTANCE      Open;
 
-    IF_LOUD(DbgPrint("Packet: TransferDataComplete\n");)
+    IF_LOUD(DbgPrint("NPF: TransferDataComplete\n");)
     
        Open= (POPEN_INSTANCE)ProtocolBindingContext;
 
@@ -491,18 +644,21 @@ VOID PacketTransferDataComplete (IN NDIS_HANDLE ProtocolBindingContext,IN PNDIS_
        NdisReinitializePacket(pPacket);
        //Put the packet on the free queue
        NdisFreePacket(pPacket);
-       //Unfreeze PacketRead
-       if(GetBuffOccupation(Open)>Open->MinToCopy)
-               KeSetEvent(Open->ReadEvent,0,FALSE);
-
+       // Unfreeze the consumer
+       if(GetBuffOccupation(Open)>Open->MinToCopy){
+               if(Open->mode & MODE_DUMP){
+                       NdisSetEvent(&Open->DumpEvent);
+               }
+               else
+                       KeSetEvent(Open->ReadEvent,0,FALSE);    
+       }
        return;
 }
 
 //-------------------------------------------------------------------
 
-VOID PacketReceiveComplete(IN NDIS_HANDLE ProtocolBindingContext)
+VOID NPF_ReceiveComplete(IN NDIS_HANDLE ProtocolBindingContext)
 {
-    IF_LOUD(DbgPrint("Packet: PacketReceiveComplete\n");)
+    IF_VERY_LOUD(DbgPrint("NPF: NPF_ReceiveComplete\n");)
     return;
 }
-
diff --git a/reactos/drivers/net/packet/resource.h b/reactos/drivers/net/packet/resource.h
new file mode 100644 (file)
index 0000000..d704eca
--- /dev/null
@@ -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/reactos/drivers/net/packet/tcp_session.c b/reactos/drivers/net/packet/tcp_session.c
new file mode 100644 (file)
index 0000000..4eb6410
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2001
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef WIN32
+#include "tme.h"
+#include "tcp_session.h"
+#endif
+
+#ifdef __FreeBSD
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#include <net/tme/tcp_session.h>
+#else
+#include <tme/tme.h>
+#include <tme/tcp_session.h>
+#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))<MAX_WINDOW)
+                               )
+                       {       /* SYN_ACK duplicato */
+                               next_status=ESTABLISHED;
+                               break;
+                       }
+                       
+                       if ((!(flags&ACK))&&
+                               (direction==session->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_srv<MAX_WINDOW)
+                                       session->ack_srv=new_ack;
+                       }
+                       else
+                       {
+                               uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
+                               if (new_ack-session->ack_cln<MAX_WINDOW)
+                                       session->ack_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)<MAX_WINDOW)
+                                       session->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_srv<MAX_WINDOW)
+                                       session->ack_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/reactos/drivers/net/packet/tcp_session.h b/reactos/drivers/net/packet/tcp_session.h
new file mode 100644 (file)
index 0000000..7b0fe91
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2001
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef __tcp_session
+#define __tcp_session
+
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <net/tme/tme.h>
+#else
+#include <tme/tme.h>
+#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/reactos/drivers/net/packet/time_calls.c b/reactos/drivers/net/packet/time_calls.c
new file mode 100644 (file)
index 0000000..66f18b7
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2001
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "tme.h"
+#include "win_bpf.h"
+#include "time_calls.h"
+
+
+void TIME_DESYNCHRONIZE(struct time_conv *data)
+{
+#ifndef __GNUC__
+       data->reference = 0;
+       data->start.tv_sec = 0;
+       data->start.tv_usec = 0;
+#endif
+}
+
+#ifdef KQPC_TS
+
+/* KeQueryPerformanceCounter TimeStamps */
+
+VOID TIME_SYNCHRONIZE(struct time_conv *data)
+{
+#ifndef __GNUC__
+       struct timeval tmp;
+       LARGE_INTEGER SystemTime;
+       LARGE_INTEGER i;
+       ULONG tmp2;
+       LARGE_INTEGER TimeFreq,PTime;
+
+       if (data->reference!=0)
+               return;
+       
+       // get the absolute value of the system boot time.   
+       PTime=KeQueryPerformanceCounter(&TimeFreq);
+       KeQuerySystemTime(&SystemTime);
+       tmp.tv_sec=(LONG)(SystemTime.QuadPart/10000000-11644473600);
+       tmp.tv_usec=(LONG)((SystemTime.QuadPart%10000000)/10);
+       tmp.tv_sec-=(ULONG)(PTime.QuadPart/TimeFreq.QuadPart);
+       tmp.tv_usec-=(LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
+       if (tmp.tv_usec<0) {
+               tmp.tv_sec--;
+               tmp.tv_usec+=1000000;
+       }
+       data->start=tmp;
+       data->reference=1;
+#endif
+}
+
+void FORCE_TIME(struct timeval *src, struct time_conv *dest)
+{
+       dest->start=*src;
+}
+
+void GET_TIME(struct timeval *dst, struct time_conv *data)
+{
+#ifndef __GNUC__
+       LARGE_INTEGER PTime, TimeFreq;
+       LONG tmp;
+
+       PTime=KeQueryPerformanceCounter(&TimeFreq);
+       tmp=(LONG)(PTime.QuadPart/TimeFreq.QuadPart);
+       dst->tv_sec=data->start.tv_sec+tmp;
+       dst->tv_usec=data->start.tv_usec+(LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
+       if (dst->tv_usec>=1000000) {
+               dst->tv_sec++;
+               dst->tv_usec-=1000000;
+       }
+#endif
+}
+
+#else
+
+/*RDTSC timestamps*/
+
+/* callers must be at IRQL=PASSIVE_LEVEL */
+VOID TIME_SYNCHRONIZE(struct time_conv *data)
+{
+#ifndef __GNUC__
+       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);
+#ifndef __GNUC__
+       __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
+       }
+#else
+#endif
+       KeLowerIrql(old);
+    KeWaitForSingleObject(&event,UserRequest,KernelMode,TRUE ,&i);
+       KeRaiseIrql(HIGH_LEVEL,&old);
+       stop_kqpc=KeQueryPerformanceCounter(&stop_freq);
+#ifndef __GNUC__
+       __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
+       }
+#else
+#endif
+       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);
+#ifndef __GNUC__
+       __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
+       }
+#else
+#endif
+       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=tmp;
+       IF_LOUD(DbgPrint("Frequency %I64u MHz\n",data->reference);)
+#else
+#endif
+}
+
+void FORCE_TIME(struct timeval *src, struct time_conv *dest)
+{
+       dest->start=*src;
+}
+
+void GET_TIME(struct timeval *dst, struct time_conv *data)
+{
+#ifndef __GNUC__
+       ULONGLONG tmp;
+#ifndef __GNUC__
+       __asm
+       {
+               push eax
+               push edx
+               push ecx
+               rdtsc
+               lea ecx, tmp
+               mov [ecx+4], edx
+               mov [ecx], eax
+               pop ecx
+               pop edx
+               pop eax
+       }
+#else
+#endif
+       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.tv_sec;
+       dst->tv_usec+=data->start.tv_usec;
+       if (dst->tv_usec>=1000000) {
+               dst->tv_sec++;
+               dst->tv_usec-=1000000;
+       }
+#endif
+}
+
+#endif /*KQPC_TS*/
diff --git a/reactos/drivers/net/packet/time_calls.h b/reactos/drivers/net/packet/time_calls.h
new file mode 100644 (file)
index 0000000..2355d45
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2001
+ *     Politecnico di Torino.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the Politecnico
+ * di Torino, and its contributors.'' 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef _time_calls
+#define _time_calls
+
+#ifdef WIN_NT_DRIVER
+
+#include "debug.h"
+
+/*!
+  \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;
+};
+
+#ifdef __GNUC__
+
+void TIME_DESYNCHRONIZE(struct time_conv *data);
+VOID TIME_SYNCHRONIZE(struct time_conv *data);
+void FORCE_TIME(struct timeval *src, struct time_conv *dest);
+void&n