Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/SoftEtherVPN/SoftEtherVPN_Stable.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src/See
diff options
context:
space:
mode:
authordnobori <da.git@softether.co.jp>2014-01-04 17:00:08 +0400
committerdnobori <da.git@softether.co.jp>2014-01-04 17:00:08 +0400
commit749497dde0a1dd08c434a73b9d4e93dc3e3326d9 (patch)
tree7c83a55919c0f1aa1267c4dbcd008f1644f961ee /src/See
parentd433e567a561f8ae094a535025b02c7dc47026c6 (diff)
v4.03-9408-rtm
Diffstat (limited to 'src/See')
-rw-r--r--src/See/DEBUG.H63
-rw-r--r--src/See/Devioctl.h90
-rw-r--r--src/See/Ntddndis.h1400
-rw-r--r--src/See/Ntddpack.h26
-rw-r--r--src/See/Openclos.c707
-rw-r--r--src/See/Packet.c1607
-rw-r--r--src/See/Packet.h954
-rw-r--r--src/See/Packet32.h423
-rw-r--r--src/See/Read.c938
-rw-r--r--src/See/See.rc63
-rw-r--r--src/See/See.vcproj462
-rw-r--r--src/See/Write.c426
-rw-r--r--src/See/bucket_lookup.c264
-rw-r--r--src/See/bucket_lookup.h54
-rw-r--r--src/See/count_packets.c64
-rw-r--r--src/See/count_packets.h62
-rw-r--r--src/See/dagc.h225
-rw-r--r--src/See/dump.c570
-rw-r--r--src/See/functions.c95
-rw-r--r--src/See/functions.h78
-rw-r--r--src/See/jitter.c687
-rw-r--r--src/See/jitter.h404
-rw-r--r--src/See/memory_t.h132
-rw-r--r--src/See/normal_lookup.c204
-rw-r--r--src/See/normal_lookup.h56
-rw-r--r--src/See/resource.h84
-rw-r--r--src/See/resource1.h84
-rw-r--r--src/See/tcp_session.c296
-rw-r--r--src/See/tcp_session.h96
-rw-r--r--src/See/time_calls.h486
-rw-r--r--src/See/tme.c385
-rw-r--r--src/See/tme.h174
-rw-r--r--src/See/valid_insns.h117
-rw-r--r--src/See/win_bpf.h417
-rw-r--r--src/See/win_bpf_filter.c1086
-rw-r--r--src/See/win_bpf_filter_init.c509
-rw-r--r--src/See/win_bpf_filter_init.h50
37 files changed, 13838 insertions, 0 deletions
diff --git a/src/See/DEBUG.H b/src/See/DEBUG.H
new file mode 100644
index 00000000..ef8174d4
--- /dev/null
+++ b/src/See/DEBUG.H
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 1999 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __DEBUG_INCLUDE
+#define __DEBUG_INCLUDE
+
+
+#if DBG
+
+#define IF_PACKETDEBUG(f) if (PacketDebugFlag & (f))
+extern ULONG PacketDebugFlag;
+
+#define PACKET_DEBUG_LOUD 0x00000001 // debugging info
+#define PACKET_DEBUG_VERY_LOUD 0x00000002 // excessive debugging info
+
+#define PACKET_DEBUG_INIT 0x00000100 // init debugging info
+
+//
+// Macro for deciding whether to dump lots of debugging information.
+//
+
+#define IF_LOUD(A) IF_PACKETDEBUG( PACKET_DEBUG_LOUD ) { A }
+#define IF_VERY_LOUD(A) IF_PACKETDEBUG( PACKET_DEBUG_VERY_LOUD ) { A }
+#define IF_INIT_LOUD(A) IF_PACKETDEBUG( PACKET_DEBUG_INIT ) { A }
+
+#else
+
+#define IF_LOUD(A)
+#define IF_VERY_LOUD(A)
+#define IF_INIT_LOUD(A)
+
+#endif
+
+#endif /*#define __DEBUG_INCLUDE*/
diff --git a/src/See/Devioctl.h b/src/See/Devioctl.h
new file mode 100644
index 00000000..af8784bf
--- /dev/null
+++ b/src/See/Devioctl.h
@@ -0,0 +1,90 @@
+/*++ BUILD Version: 0004 // Increment this if a change has global effects
+ Copyright (c) 1992-1993 Microsoft Corporation
+ Module Name:
+ devioctl.h
+ Revision History:
+ -- */
+// begin_winioctl
+#ifndef _DEVIOCTL_
+#define _DEVIOCTL_
+// begin_ntddk begin_nthal begin_ntifs
+//
+// Define the various device type values. Note that values used by Microsoft
+// Corporation are in the range 0-32767, and 32768-65535 are reserved for use
+// by customers.
+//
+#define DEVICE_TYPE ULONG
+#define FILE_DEVICE_BEEP 0x00000001
+#define FILE_DEVICE_CD_ROM 0x00000002
+#define FILE_DEVICE_CD_ROM_FILE_SYSTEM 0x00000003
+#define FILE_DEVICE_CONTROLLER 0x00000004
+#define FILE_DEVICE_DATALINK 0x00000005
+#define FILE_DEVICE_DFS 0x00000006
+#define FILE_DEVICE_DISK 0x00000007
+#define FILE_DEVICE_DISK_FILE_SYSTEM 0x00000008
+#define FILE_DEVICE_FILE_SYSTEM 0x00000009
+#define FILE_DEVICE_INPORT_PORT 0x0000000a
+#define FILE_DEVICE_KEYBOARD 0x0000000b
+#define FILE_DEVICE_MAILSLOT 0x0000000c
+#define FILE_DEVICE_MIDI_IN 0x0000000d
+#define FILE_DEVICE_MIDI_OUT 0x0000000e
+#define FILE_DEVICE_MOUSE 0x0000000f
+#define FILE_DEVICE_MULTI_UNC_PROVIDER 0x00000010
+#define FILE_DEVICE_NAMED_PIPE 0x00000011
+#define FILE_DEVICE_NETWORK 0x00000012
+#define FILE_DEVICE_NETWORK_BROWSER 0x00000013
+#define FILE_DEVICE_NETWORK_FILE_SYSTEM 0x00000014
+#define FILE_DEVICE_NULL 0x00000015
+#define FILE_DEVICE_PARALLEL_PORT 0x00000016
+#define FILE_DEVICE_PHYSICAL_NETCARD 0x00000017
+#define FILE_DEVICE_PRINTER 0x00000018
+#define FILE_DEVICE_SCANNER 0x00000019
+#define FILE_DEVICE_SERIAL_MOUSE_PORT 0x0000001a
+#define FILE_DEVICE_SERIAL_PORT 0x0000001b
+#define FILE_DEVICE_SCREEN 0x0000001c
+#define FILE_DEVICE_SOUND 0x0000001d
+#define FILE_DEVICE_STREAMS 0x0000001e
+#define FILE_DEVICE_TAPE 0x0000001f
+#define FILE_DEVICE_TAPE_FILE_SYSTEM 0x00000020
+#define FILE_DEVICE_TRANSPORT 0x00000021
+#define FILE_DEVICE_UNKNOWN 0x00000022
+#define FILE_DEVICE_VIDEO 0x00000023
+#define FILE_DEVICE_VIRTUAL_DISK 0x00000024
+#define FILE_DEVICE_WAVE_IN 0x00000025
+#define FILE_DEVICE_WAVE_OUT 0x00000026
+#define FILE_DEVICE_8042_PORT 0x00000027
+#define FILE_DEVICE_NETWORK_REDIRECTOR 0x00000028
+#define FILE_DEVICE_BATTERY 0x00000029
+#define FILE_DEVICE_BUS_EXTENDER 0x0000002a
+#define FILE_DEVICE_MODEM 0x0000002b
+#define FILE_DEVICE_VDM 0x0000002c
+#define FILE_DEVICE_MASS_STORAGE 0x0000002d
+//
+// Macro definition for defining IOCTL and FSCTL function control codes. Note
+// that function codes 0-2047 are reserved for Microsoft Corporation, and
+// 2048-4095 are reserved for customers.
+//
+#define CTL_CODE( DeviceType, Function, Method, Access ) ( \
+ ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
+)
+//
+// Define the method codes for how buffers are passed for I/O and FS controls
+//
+#define METHOD_BUFFERED 0
+#define METHOD_IN_DIRECT 1
+#define METHOD_OUT_DIRECT 2
+#define METHOD_NEITHER 3
+//
+// Define the access check value for any access
+//
+//
+// The FILE_READ_ACCESS and FILE_WRITE_ACCESS constants are also defined in
+// ntioapi.h as FILE_READ_DATA and FILE_WRITE_DATA. The values for these
+// constants *MUST* always be in sync.
+//
+#define FILE_ANY_ACCESS 0
+#define FILE_READ_ACCESS ( 0x0001 ) // file & pipe
+#define FILE_WRITE_ACCESS ( 0x0002 ) // file & pipe
+// end_ntddk end_nthal end_ntifs
+#endif // _DEVIOCTL_
+// end_winioctl
diff --git a/src/See/Ntddndis.h b/src/See/Ntddndis.h
new file mode 100644
index 00000000..0b629806
--- /dev/null
+++ b/src/See/Ntddndis.h
@@ -0,0 +1,1400 @@
+/*++ BUILD Version: 0001 // Increment this if a change has global effects
+ Copyright (c) 1990-1993 Microsoft Corporation
+ Module Name:
+ ntddndis.h
+ Abstract:
+ This is the include file that defines all constants and types for
+ accessing the Network driver interface device.
+ Author:
+ Steve Wood (stevewo) 27-May-1990
+ Revision History:
+ Adam Barr (adamba) 04-Nov-1992 added the correct values for NDIS 3.0.
+ Jameel Hyder (jameelh) 01-Aug-95 added Pnp IoCTLs and structures
+ Kyle Brandon (kyleb) 09/24/96 added general co ndis oids.
+ -- */
+#ifndef _NTDDNDIS_
+#define _NTDDNDIS_
+//
+// Device Name - this string is the name of the device. It is the name
+// that should be passed to NtOpenFile when accessing the device.
+//
+// Note: For devices that support multiple units, it should be suffixed
+// with the Ascii representation of the unit number.
+//
+#define DD_NDIS_DEVICE_NAME "\\Device\\UNKNOWN"
+//
+// NtDeviceIoControlFile IoControlCode values for this device.
+//
+// Warning: Remember that the low two bits of the code specify how the
+// buffers are passed to the driver!
+//
+#define _NDIS_CONTROL_CODE(request,method) \
+ CTL_CODE(FILE_DEVICE_PHYSICAL_NETCARD, request, method, FILE_ANY_ACCESS)
+#define IOCTL_NDIS_QUERY_GLOBAL_STATS _NDIS_CONTROL_CODE( 0, METHOD_OUT_DIRECT )
+#define IOCTL_NDIS_QUERY_ALL_STATS _NDIS_CONTROL_CODE( 1, METHOD_OUT_DIRECT )
+#define IOCTL_NDIS_ADD_DEVICE _NDIS_CONTROL_CODE( 2, METHOD_BUFFERED )
+#define IOCTL_NDIS_DELETE_DEVICE _NDIS_CONTROL_CODE( 3, METHOD_BUFFERED )
+#define IOCTL_NDIS_TRANSLATE_NAME _NDIS_CONTROL_CODE( 4, METHOD_BUFFERED )
+#define IOCTL_NDIS_ADD_TDI_DEVICE _NDIS_CONTROL_CODE( 5, METHOD_BUFFERED )
+#define IOCTL_NDIS_NOTIFY_PROTOCOL _NDIS_CONTROL_CODE( 6, METHOD_BUFFERED )
+#define IOCTL_NDIS_GET_LOG_DATA _NDIS_CONTROL_CODE( 7, METHOD_OUT_DIRECT )
+//
+// NtDeviceIoControlFile InputBuffer/OutputBuffer record structures for
+// this device.
+//
+//
+// This is the type of an NDIS OID value.
+//
+typedef ULONG NDIS_OID, *PNDIS_OID;
+//
+// IOCTL_NDIS_QUERY_ALL_STATS returns a sequence of these, packed
+// together (no padding is required since statistics all have
+// four or eight bytes of data).
+//
+typedef struct _NDIS_STATISTICS_VALUE {
+ NDIS_OID Oid;
+ ULONG DataLength;
+ UCHAR Data[1]; // variable length
+
+} NDIS_STATISTICS_VALUE, *PNDIS_STATISTICS_VALUE;
+
+//
+// Structure used by TRANSLATE_NAME IOCTL
+//
+typedef struct _NET_PNP_ID {
+ ULONG ClassId;
+ ULONG Token;
+} NET_PNP_ID, *PNET_PNP_ID;
+
+typedef struct _NET_PNP_TRANSLATE_LIST {
+ ULONG BytesNeeded;
+ NET_PNP_ID IdArray[ANYSIZE_ARRAY];
+} NET_PNP_TRANSLATE_LIST, *PNET_PNP_TRANSLATE_LIST;
+
+//
+// Structure used to define a self-contained variable data structure
+//
+typedef struct _NDIS_VAR_DATA_DESC {
+ USHORT Length; // # of octects of data
+
+ USHORT MaximumLength; // # of octects available
+
+ LONG Offset; // Offset of data relative to the descriptor
+
+} NDIS_VAR_DATA_DESC, *PNDIS_VAR_DATA_DESC;
+
+//
+// Object Identifiers used by NdisRequest Query/Set Information
+//
+//
+// General Objects
+//
+#define OID_GEN_SUPPORTED_LIST 0x00010101
+#define OID_GEN_HARDWARE_STATUS 0x00010102
+#define OID_GEN_MEDIA_SUPPORTED 0x00010103
+#define OID_GEN_MEDIA_IN_USE 0x00010104
+#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105
+#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106
+#define OID_GEN_LINK_SPEED 0x00010107
+#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108
+#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109
+#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A
+#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B
+#define OID_GEN_VENDOR_ID 0x0001010C
+#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D
+#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E
+#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F
+#define OID_GEN_DRIVER_VERSION 0x00010110
+#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111
+#define OID_GEN_PROTOCOL_OPTIONS 0x00010112
+#define OID_GEN_MAC_OPTIONS 0x00010113
+#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114
+#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115
+#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116
+#define OID_GEN_XMIT_OK 0x00020101
+#define OID_GEN_RCV_OK 0x00020102
+#define OID_GEN_XMIT_ERROR 0x00020103
+#define OID_GEN_RCV_ERROR 0x00020104
+#define OID_GEN_RCV_NO_BUFFER 0x00020105
+#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201
+#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202
+#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203
+#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204
+#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205
+#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206
+#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207
+#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208
+#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209
+#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A
+#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B
+#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C
+#define OID_GEN_RCV_CRC_ERROR 0x0002020D
+#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E
+#define OID_GEN_GET_TIME_CAPS 0x0002020F
+#define OID_GEN_GET_NETCARD_TIME 0x00020210
+//
+// These are connection-oriented general OIDs.
+// These replace the above OIDs for connection-oriented media.
+//
+#define OID_GEN_CO_SUPPORTED_LIST 0x00010101
+#define OID_GEN_CO_HARDWARE_STATUS 0x00010102
+#define OID_GEN_CO_MEDIA_SUPPORTED 0x00010103
+#define OID_GEN_CO_MEDIA_IN_USE 0x00010104
+#define OID_GEN_CO_LINK_SPEED 0x00010105
+#define OID_GEN_CO_VENDOR_ID 0x00010106
+#define OID_GEN_CO_VENDOR_DESCRIPTION 0x00010107
+#define OID_GEN_CO_DRIVER_VERSION 0x00010108
+#define OID_GEN_CO_PROTOCOL_OPTIONS 0x00010109
+#define OID_GEN_CO_MAC_OPTIONS 0x0001010A
+#define OID_GEN_CO_MEDIA_CONNECT_STATUS 0x0001010B
+#define OID_GEN_CO_VENDOR_DRIVER_VERSION 0x0001010C
+#define OID_GEN_CO_MINIMUM_LINK_SPEED 0x0001010D
+#define OID_GEN_CO_GET_TIME_CAPS 0x00010201
+#define OID_GEN_CO_GET_NETCARD_TIME 0x00010202
+//
+// These are connection-oriented statistics OIDs.
+//
+#define OID_GEN_CO_XMIT_PDUS_OK 0x00020101
+#define OID_GEN_CO_RCV_PDUS_OK 0x00020102
+#define OID_GEN_CO_XMIT_PDUS_ERROR 0x00020103
+#define OID_GEN_CO_RCV_PDUS_ERROR 0x00020104
+#define OID_GEN_CO_RCV_PDUS_NO_BUFFER 0x00020105
+#define OID_GEN_CO_RCV_CRC_ERROR 0x00020201
+#define OID_GEN_CO_TRANSMIT_QUEUE_LENGTH 0x00020202
+#define OID_GEN_CO_BYTES_XMIT 0x00020203
+#define OID_GEN_CO_BYTES_RCV 0x00020204
+#define OID_GEN_CO_BYTES_XMIT_OUTSTANDING 0x00020205
+#define OID_GEN_CO_NETCARD_LOAD 0x00020206
+//
+// These are objects for Connection-oriented media call-managers and are not
+// valid for ndis drivers. Under construction.
+//
+#define OID_CO_ADD_PVC 0xFF000001
+#define OID_CO_DELETE_PVC 0xFF000002
+#define OID_CO_GET_CALL_INFORMATION 0xFF000003
+#define OID_CO_ADD_ADDRESS 0xFF000004
+#define OID_CO_DELETE_ADDRESS 0xFF000005
+#define OID_CO_GET_ADDRESSES 0xFF000006
+#define OID_CO_ADDRESS_CHANGE 0xFF000007
+#define OID_CO_SIGNALING_ENABLED 0xFF000008
+#define OID_CO_SIGNALING_DISABLED 0xFF000009
+//
+// 802.3 Objects (Ethernet)
+//
+#define OID_802_3_PERMANENT_ADDRESS 0x01010101
+#define OID_802_3_CURRENT_ADDRESS 0x01010102
+#define OID_802_3_MULTICAST_LIST 0x01010103
+#define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104
+#define OID_802_3_MAC_OPTIONS 0x01010105
+//
+//
+#define NDIS_802_3_MAC_OPTION_PRIORITY 0x00000001
+#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101
+#define OID_802_3_XMIT_ONE_COLLISION 0x01020102
+#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103
+#define OID_802_3_XMIT_DEFERRED 0x01020201
+#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202
+#define OID_802_3_RCV_OVERRUN 0x01020203
+#define OID_802_3_XMIT_UNDERRUN 0x01020204
+#define OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205
+#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206
+#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207
+//
+// 802.5 Objects (Token-Ring)
+//
+#define OID_802_5_PERMANENT_ADDRESS 0x02010101
+#define OID_802_5_CURRENT_ADDRESS 0x02010102
+#define OID_802_5_CURRENT_FUNCTIONAL 0x02010103
+#define OID_802_5_CURRENT_GROUP 0x02010104
+#define OID_802_5_LAST_OPEN_STATUS 0x02010105
+#define OID_802_5_CURRENT_RING_STATUS 0x02010106
+#define OID_802_5_CURRENT_RING_STATE 0x02010107
+#define OID_802_5_LINE_ERRORS 0x02020101
+#define OID_802_5_LOST_FRAMES 0x02020102
+#define OID_802_5_BURST_ERRORS 0x02020201
+#define OID_802_5_AC_ERRORS 0x02020202
+#define OID_802_5_ABORT_DELIMETERS 0x02020203
+#define OID_802_5_FRAME_COPIED_ERRORS 0x02020204
+#define OID_802_5_FREQUENCY_ERRORS 0x02020205
+#define OID_802_5_TOKEN_ERRORS 0x02020206
+#define OID_802_5_INTERNAL_ERRORS 0x02020207
+//
+// FDDI Objects
+//
+#define OID_FDDI_LONG_PERMANENT_ADDR 0x03010101
+#define OID_FDDI_LONG_CURRENT_ADDR 0x03010102
+#define OID_FDDI_LONG_MULTICAST_LIST 0x03010103
+#define OID_FDDI_LONG_MAX_LIST_SIZE 0x03010104
+#define OID_FDDI_SHORT_PERMANENT_ADDR 0x03010105
+#define OID_FDDI_SHORT_CURRENT_ADDR 0x03010106
+#define OID_FDDI_SHORT_MULTICAST_LIST 0x03010107
+#define OID_FDDI_SHORT_MAX_LIST_SIZE 0x03010108
+#define OID_FDDI_ATTACHMENT_TYPE 0x03020101
+#define OID_FDDI_UPSTREAM_NODE_LONG 0x03020102
+#define OID_FDDI_DOWNSTREAM_NODE_LONG 0x03020103
+#define OID_FDDI_FRAME_ERRORS 0x03020104
+#define OID_FDDI_FRAMES_LOST 0x03020105
+#define OID_FDDI_RING_MGT_STATE 0x03020106
+#define OID_FDDI_LCT_FAILURES 0x03020107
+#define OID_FDDI_LEM_REJECTS 0x03020108
+#define OID_FDDI_LCONNECTION_STATE 0x03020109
+#define OID_FDDI_SMT_STATION_ID 0x03030201
+#define OID_FDDI_SMT_OP_VERSION_ID 0x03030202
+#define OID_FDDI_SMT_HI_VERSION_ID 0x03030203
+#define OID_FDDI_SMT_LO_VERSION_ID 0x03030204
+#define OID_FDDI_SMT_MANUFACTURER_DATA 0x03030205
+#define OID_FDDI_SMT_USER_DATA 0x03030206
+#define OID_FDDI_SMT_MIB_VERSION_ID 0x03030207
+#define OID_FDDI_SMT_MAC_CT 0x03030208
+#define OID_FDDI_SMT_NON_MASTER_CT 0x03030209
+#define OID_FDDI_SMT_MASTER_CT 0x0303020A
+#define OID_FDDI_SMT_AVAILABLE_PATHS 0x0303020B
+#define OID_FDDI_SMT_CONFIG_CAPABILITIES 0x0303020C
+#define OID_FDDI_SMT_CONFIG_POLICY 0x0303020D
+#define OID_FDDI_SMT_CONNECTION_POLICY 0x0303020E
+#define OID_FDDI_SMT_T_NOTIFY 0x0303020F
+#define OID_FDDI_SMT_STAT_RPT_POLICY 0x03030210
+#define OID_FDDI_SMT_TRACE_MAX_EXPIRATION 0x03030211
+#define OID_FDDI_SMT_PORT_INDEXES 0x03030212
+#define OID_FDDI_SMT_MAC_INDEXES 0x03030213
+#define OID_FDDI_SMT_BYPASS_PRESENT 0x03030214
+#define OID_FDDI_SMT_ECM_STATE 0x03030215
+#define OID_FDDI_SMT_CF_STATE 0x03030216
+#define OID_FDDI_SMT_HOLD_STATE 0x03030217
+#define OID_FDDI_SMT_REMOTE_DISCONNECT_FLAG 0x03030218
+#define OID_FDDI_SMT_STATION_STATUS 0x03030219
+#define OID_FDDI_SMT_PEER_WRAP_FLAG 0x0303021A
+#define OID_FDDI_SMT_MSG_TIME_STAMP 0x0303021B
+#define OID_FDDI_SMT_TRANSITION_TIME_STAMP 0x0303021C
+#define OID_FDDI_SMT_SET_COUNT 0x0303021D
+#define OID_FDDI_SMT_LAST_SET_STATION_ID 0x0303021E
+#define OID_FDDI_MAC_FRAME_STATUS_FUNCTIONS 0x0303021F
+#define OID_FDDI_MAC_BRIDGE_FUNCTIONS 0x03030220
+#define OID_FDDI_MAC_T_MAX_CAPABILITY 0x03030221
+#define OID_FDDI_MAC_TVX_CAPABILITY 0x03030222
+#define OID_FDDI_MAC_AVAILABLE_PATHS 0x03030223
+#define OID_FDDI_MAC_CURRENT_PATH 0x03030224
+#define OID_FDDI_MAC_UPSTREAM_NBR 0x03030225
+#define OID_FDDI_MAC_DOWNSTREAM_NBR 0x03030226
+#define OID_FDDI_MAC_OLD_UPSTREAM_NBR 0x03030227
+#define OID_FDDI_MAC_OLD_DOWNSTREAM_NBR 0x03030228
+#define OID_FDDI_MAC_DUP_ADDRESS_TEST 0x03030229
+#define OID_FDDI_MAC_REQUESTED_PATHS 0x0303022A
+#define OID_FDDI_MAC_DOWNSTREAM_PORT_TYPE 0x0303022B
+#define OID_FDDI_MAC_INDEX 0x0303022C
+#define OID_FDDI_MAC_SMT_ADDRESS 0x0303022D
+#define OID_FDDI_MAC_LONG_GRP_ADDRESS 0x0303022E
+#define OID_FDDI_MAC_SHORT_GRP_ADDRESS 0x0303022F
+#define OID_FDDI_MAC_T_REQ 0x03030230
+#define OID_FDDI_MAC_T_NEG 0x03030231
+#define OID_FDDI_MAC_T_MAX 0x03030232
+#define OID_FDDI_MAC_TVX_VALUE 0x03030233
+#define OID_FDDI_MAC_T_PRI0 0x03030234
+#define OID_FDDI_MAC_T_PRI1 0x03030235
+#define OID_FDDI_MAC_T_PRI2 0x03030236
+#define OID_FDDI_MAC_T_PRI3 0x03030237
+#define OID_FDDI_MAC_T_PRI4 0x03030238
+#define OID_FDDI_MAC_T_PRI5 0x03030239
+#define OID_FDDI_MAC_T_PRI6 0x0303023A
+#define OID_FDDI_MAC_FRAME_CT 0x0303023B
+#define OID_FDDI_MAC_COPIED_CT 0x0303023C
+#define OID_FDDI_MAC_TRANSMIT_CT 0x0303023D
+#define OID_FDDI_MAC_TOKEN_CT 0x0303023E
+#define OID_FDDI_MAC_ERROR_CT 0x0303023F
+#define OID_FDDI_MAC_LOST_CT 0x03030240
+#define OID_FDDI_MAC_TVX_EXPIRED_CT 0x03030241
+#define OID_FDDI_MAC_NOT_COPIED_CT 0x03030242
+#define OID_FDDI_MAC_LATE_CT 0x03030243
+#define OID_FDDI_MAC_RING_OP_CT 0x03030244
+#define OID_FDDI_MAC_FRAME_ERROR_THRESHOLD 0x03030245
+#define OID_FDDI_MAC_FRAME_ERROR_RATIO 0x03030246
+#define OID_FDDI_MAC_NOT_COPIED_THRESHOLD 0x03030247
+#define OID_FDDI_MAC_NOT_COPIED_RATIO 0x03030248
+#define OID_FDDI_MAC_RMT_STATE 0x03030249
+#define OID_FDDI_MAC_DA_FLAG 0x0303024A
+#define OID_FDDI_MAC_UNDA_FLAG 0x0303024B
+#define OID_FDDI_MAC_FRAME_ERROR_FLAG 0x0303024C
+#define OID_FDDI_MAC_NOT_COPIED_FLAG 0x0303024D
+#define OID_FDDI_MAC_MA_UNITDATA_AVAILABLE 0x0303024E
+#define OID_FDDI_MAC_HARDWARE_PRESENT 0x0303024F
+#define OID_FDDI_MAC_MA_UNITDATA_ENABLE 0x03030250
+#define OID_FDDI_PATH_INDEX 0x03030251
+#define OID_FDDI_PATH_RING_LATENCY 0x03030252
+#define OID_FDDI_PATH_TRACE_STATUS 0x03030253
+#define OID_FDDI_PATH_SBA_PAYLOAD 0x03030254
+#define OID_FDDI_PATH_SBA_OVERHEAD 0x03030255
+#define OID_FDDI_PATH_CONFIGURATION 0x03030256
+#define OID_FDDI_PATH_T_R_MODE 0x03030257
+#define OID_FDDI_PATH_SBA_AVAILABLE 0x03030258
+#define OID_FDDI_PATH_TVX_LOWER_BOUND 0x03030259
+#define OID_FDDI_PATH_T_MAX_LOWER_BOUND 0x0303025A
+#define OID_FDDI_PATH_MAX_T_REQ 0x0303025B
+#define OID_FDDI_PORT_MY_TYPE 0x0303025C
+#define OID_FDDI_PORT_NEIGHBOR_TYPE 0x0303025D
+#define OID_FDDI_PORT_CONNECTION_POLICIES 0x0303025E
+#define OID_FDDI_PORT_MAC_INDICATED 0x0303025F
+#define OID_FDDI_PORT_CURRENT_PATH 0x03030260
+#define OID_FDDI_PORT_REQUESTED_PATHS 0x03030261
+#define OID_FDDI_PORT_MAC_PLACEMENT 0x03030262
+#define OID_FDDI_PORT_AVAILABLE_PATHS 0x03030263
+#define OID_FDDI_PORT_MAC_LOOP_TIME 0x03030264
+#define OID_FDDI_PORT_PMD_CLASS 0x03030265
+#define OID_FDDI_PORT_CONNECTION_CAPABILITIES 0x03030266
+#define OID_FDDI_PORT_INDEX 0x03030267
+#define OID_FDDI_PORT_MAINT_LS 0x03030268
+#define OID_FDDI_PORT_BS_FLAG 0x03030269
+#define OID_FDDI_PORT_PC_LS 0x0303026A
+#define OID_FDDI_PORT_EB_ERROR_CT 0x0303026B
+#define OID_FDDI_PORT_LCT_FAIL_CT 0x0303026C
+#define OID_FDDI_PORT_LER_ESTIMATE 0x0303026D
+#define OID_FDDI_PORT_LEM_REJECT_CT 0x0303026E
+#define OID_FDDI_PORT_LEM_CT 0x0303026F
+#define OID_FDDI_PORT_LER_CUTOFF 0x03030270
+#define OID_FDDI_PORT_LER_ALARM 0x03030271
+#define OID_FDDI_PORT_CONNNECT_STATE 0x03030272
+#define OID_FDDI_PORT_PCM_STATE 0x03030273
+#define OID_FDDI_PORT_PC_WITHHOLD 0x03030274
+#define OID_FDDI_PORT_LER_FLAG 0x03030275
+#define OID_FDDI_PORT_HARDWARE_PRESENT 0x03030276
+#define OID_FDDI_SMT_STATION_ACTION 0x03030277
+#define OID_FDDI_PORT_ACTION 0x03030278
+#define OID_FDDI_IF_DESCR 0x03030279
+#define OID_FDDI_IF_TYPE 0x0303027A
+#define OID_FDDI_IF_MTU 0x0303027B
+#define OID_FDDI_IF_SPEED 0x0303027C
+#define OID_FDDI_IF_PHYS_ADDRESS 0x0303027D
+#define OID_FDDI_IF_ADMIN_STATUS 0x0303027E
+#define OID_FDDI_IF_OPER_STATUS 0x0303027F
+#define OID_FDDI_IF_LAST_CHANGE 0x03030280
+#define OID_FDDI_IF_IN_OCTETS 0x03030281
+#define OID_FDDI_IF_IN_UCAST_PKTS 0x03030282
+#define OID_FDDI_IF_IN_NUCAST_PKTS 0x03030283
+#define OID_FDDI_IF_IN_DISCARDS 0x03030284
+#define OID_FDDI_IF_IN_ERRORS 0x03030285
+#define OID_FDDI_IF_IN_UNKNOWN_PROTOS 0x03030286
+#define OID_FDDI_IF_OUT_OCTETS 0x03030287
+#define OID_FDDI_IF_OUT_UCAST_PKTS 0x03030288
+#define OID_FDDI_IF_OUT_NUCAST_PKTS 0x03030289
+#define OID_FDDI_IF_OUT_DISCARDS 0x0303028A
+#define OID_FDDI_IF_OUT_ERRORS 0x0303028B
+#define OID_FDDI_IF_OUT_QLEN 0x0303028C
+#define OID_FDDI_IF_SPECIFIC 0x0303028D
+//
+// WAN objects
+//
+#define OID_WAN_PERMANENT_ADDRESS 0x04010101
+#define OID_WAN_CURRENT_ADDRESS 0x04010102
+#define OID_WAN_QUALITY_OF_SERVICE 0x04010103
+#define OID_WAN_PROTOCOL_TYPE 0x04010104
+#define OID_WAN_MEDIUM_SUBTYPE 0x04010105
+#define OID_WAN_HEADER_FORMAT 0x04010106
+#define OID_WAN_GET_INFO 0x04010107
+#define OID_WAN_SET_LINK_INFO 0x04010108
+#define OID_WAN_GET_LINK_INFO 0x04010109
+#define OID_WAN_LINE_COUNT 0x0401010A
+#define OID_WAN_GET_BRIDGE_INFO 0x0401020A
+#define OID_WAN_SET_BRIDGE_INFO 0x0401020B
+#define OID_WAN_GET_COMP_INFO 0x0401020C
+#define OID_WAN_SET_COMP_INFO 0x0401020D
+#define OID_WAN_GET_STATS_INFO 0x0401020E
+//
+// LocalTalk objects
+//
+#define OID_LTALK_CURRENT_NODE_ID 0x05010102
+#define OID_LTALK_IN_BROADCASTS 0x05020101
+#define OID_LTALK_IN_LENGTH_ERRORS 0x05020102
+#define OID_LTALK_OUT_NO_HANDLERS 0x05020201
+#define OID_LTALK_COLLISIONS 0x05020202
+#define OID_LTALK_DEFERS 0x05020203
+#define OID_LTALK_NO_DATA_ERRORS 0x05020204
+#define OID_LTALK_RANDOM_CTS_ERRORS 0x05020205
+#define OID_LTALK_FCS_ERRORS 0x05020206
+//
+// Arcnet objects
+//
+#define OID_ARCNET_PERMANENT_ADDRESS 0x06010101
+#define OID_ARCNET_CURRENT_ADDRESS 0x06010102
+#define OID_ARCNET_RECONFIGURATIONS 0x06020201
+//
+// TAPI objects
+//
+#define OID_TAPI_ACCEPT 0x07030101
+#define OID_TAPI_ANSWER 0x07030102
+#define OID_TAPI_CLOSE 0x07030103
+#define OID_TAPI_CLOSE_CALL 0x07030104
+#define OID_TAPI_CONDITIONAL_MEDIA_DETECTION 0x07030105
+#define OID_TAPI_CONFIG_DIALOG 0x07030106
+#define OID_TAPI_DEV_SPECIFIC 0x07030107
+#define OID_TAPI_DIAL 0x07030108
+#define OID_TAPI_DROP 0x07030109
+#define OID_TAPI_GET_ADDRESS_CAPS 0x0703010A
+#define OID_TAPI_GET_ADDRESS_ID 0x0703010B
+#define OID_TAPI_GET_ADDRESS_STATUS 0x0703010C
+#define OID_TAPI_GET_CALL_ADDRESS_ID 0x0703010D
+#define OID_TAPI_GET_CALL_INFO 0x0703010E
+#define OID_TAPI_GET_CALL_STATUS 0x0703010F
+#define OID_TAPI_GET_DEV_CAPS 0x07030110
+#define OID_TAPI_GET_DEV_CONFIG 0x07030111
+#define OID_TAPI_GET_EXTENSION_ID 0x07030112
+#define OID_TAPI_GET_ID 0x07030113
+#define OID_TAPI_GET_LINE_DEV_STATUS 0x07030114
+#define OID_TAPI_MAKE_CALL 0x07030115
+#define OID_TAPI_NEGOTIATE_EXT_VERSION 0x07030116
+#define OID_TAPI_OPEN 0x07030117
+#define OID_TAPI_PROVIDER_INITIALIZE 0x07030118
+#define OID_TAPI_PROVIDER_SHUTDOWN 0x07030119
+#define OID_TAPI_SECURE_CALL 0x0703011A
+#define OID_TAPI_SELECT_EXT_VERSION 0x0703011B
+#define OID_TAPI_SEND_USER_USER_INFO 0x0703011C
+#define OID_TAPI_SET_APP_SPECIFIC 0x0703011D
+#define OID_TAPI_SET_CALL_PARAMS 0x0703011E
+#define OID_TAPI_SET_DEFAULT_MEDIA_DETECTION 0x0703011F
+#define OID_TAPI_SET_DEV_CONFIG 0x07030120
+#define OID_TAPI_SET_MEDIA_MODE 0x07030121
+#define OID_TAPI_SET_STATUS_MESSAGES 0x07030122
+//
+// ATM Connection Oriented Ndis
+//
+#define OID_ATM_SUPPORTED_VC_RATES 0x08010101
+#define OID_ATM_SUPPORTED_SERVICE_CATEGORY 0x08010102
+#define OID_ATM_SUPPORTED_AAL_TYPES 0x08010103
+#define OID_ATM_HW_CURRENT_ADDRESS 0x08010104
+#define OID_ATM_MAX_ACTIVE_VCS 0x08010105
+#define OID_ATM_MAX_ACTIVE_VCI_BITS 0x08010106
+#define OID_ATM_MAX_ACTIVE_VPI_BITS 0x08010107
+#define OID_ATM_MAX_AAL0_PACKET_SIZE 0x08010108
+#define OID_ATM_MAX_AAL1_PACKET_SIZE 0x08010109
+#define OID_ATM_MAX_AAL34_PACKET_SIZE 0x0801010A
+#define OID_ATM_MAX_AAL5_PACKET_SIZE 0x0801010B
+#define OID_ATM_SIGNALING_VPIVCI 0x08010201
+#define OID_ATM_ASSIGNED_VPI 0x08010202
+#define OID_ATM_ACQUIRE_ACCESS_NET_RESOURCES 0x08010203
+#define OID_ATM_RELEASE_ACCESS_NET_RESOURCES 0x08010204
+#define OID_ATM_ILMI_VPIVCI 0x08010205
+#define OID_ATM_DIGITAL_BROADCAST_VPIVCI 0x08010206
+#define OID_ATM_GET_NEAREST_FLOW 0x08010207
+#define OID_ATM_ALIGNMENT_REQUIRED 0x08010208
+//
+// ATM specific statistics OIDs.
+//
+#define OID_ATM_RCV_CELLS_OK 0x08020101
+#define OID_ATM_XMIT_CELLS_OK 0x08020102
+#define OID_ATM_RCV_CELLS_DROPPED 0x08020103
+#define OID_ATM_RCV_INVALID_VPI_VCI 0x08020201
+#define OID_ATM_CELLS_HEC_ERROR 0x08020202
+#define OID_ATM_RCV_REASSEMBLY_ERROR 0x08020203
+//
+// PCCA (Wireless) object
+//
+//
+// All WirelessWAN devices must support the following OIDs
+//
+#define OID_WW_GEN_NETWORK_TYPES_SUPPORTED 0x09010101
+#define OID_WW_GEN_NETWORK_TYPE_IN_USE 0x09010102
+#define OID_WW_GEN_HEADER_FORMATS_SUPPORTED 0x09010103
+#define OID_WW_GEN_HEADER_FORMAT_IN_USE 0x09010104
+#define OID_WW_GEN_INDICATION_REQUEST 0x09010105
+#define OID_WW_GEN_DEVICE_INFO 0x09010106
+#define OID_WW_GEN_OPERATION_MODE 0x09010107
+#define OID_WW_GEN_LOCK_STATUS 0x09010108
+#define OID_WW_GEN_DISABLE_TRANSMITTER 0x09010109
+#define OID_WW_GEN_NETWORK_ID 0x0901010A
+#define OID_WW_GEN_PERMANENT_ADDRESS 0x0901010B
+#define OID_WW_GEN_CURRENT_ADDRESS 0x0901010C
+#define OID_WW_GEN_SUSPEND_DRIVER 0x0901010D
+#define OID_WW_GEN_BASESTATION_ID 0x0901010E
+#define OID_WW_GEN_CHANNEL_ID 0x0901010F
+#define OID_WW_GEN_ENCRYPTION_SUPPORTED 0x09010110
+#define OID_WW_GEN_ENCRYPTION_IN_USE 0x09010111
+#define OID_WW_GEN_ENCRYPTION_STATE 0x09010112
+#define OID_WW_GEN_CHANNEL_QUALITY 0x09010113
+#define OID_WW_GEN_REGISTRATION_STATUS 0x09010114
+#define OID_WW_GEN_RADIO_LINK_SPEED 0x09010115
+#define OID_WW_GEN_LATENCY 0x09010116
+#define OID_WW_GEN_BATTERY_LEVEL 0x09010117
+#define OID_WW_GEN_EXTERNAL_POWER 0x09010118
+//
+// Network Dependent OIDs - Mobitex:
+//
+#define OID_WW_MBX_SUBADDR 0x09050101
+// OID 0x09050102 is reserved and may not be used
+#define OID_WW_MBX_FLEXLIST 0x09050103
+#define OID_WW_MBX_GROUPLIST 0x09050104
+#define OID_WW_MBX_TRAFFIC_AREA 0x09050105
+#define OID_WW_MBX_LIVE_DIE 0x09050106
+#define OID_WW_MBX_TEMP_DEFAULTLIST 0x09050107
+//
+// Network Dependent OIDs - Pinpoint:
+//
+#define OID_WW_PIN_LOC_AUTHORIZE 0x09090101
+#define OID_WW_PIN_LAST_LOCATION 0x09090102
+#define OID_WW_PIN_LOC_FIX 0x09090103
+//
+// Network Dependent - CDPD:
+//
+#define OID_WW_CDPD_SPNI 0x090D0101
+#define OID_WW_CDPD_WASI 0x090D0102
+#define OID_WW_CDPD_AREA_COLOR 0x090D0103
+#define OID_WW_CDPD_TX_POWER_LEVEL 0x090D0104
+#define OID_WW_CDPD_EID 0x090D0105
+#define OID_WW_CDPD_HEADER_COMPRESSION 0x090D0106
+#define OID_WW_CDPD_DATA_COMPRESSION 0x090D0107
+#define OID_WW_CDPD_CHANNEL_SELECT 0x090D0108
+#define OID_WW_CDPD_CHANNEL_STATE 0x090D0109
+#define OID_WW_CDPD_NEI 0x090D010A
+#define OID_WW_CDPD_NEI_STATE 0x090D010B
+#define OID_WW_CDPD_SERVICE_PROVIDER_IDENTIFIER 0x090D010C
+#define OID_WW_CDPD_SLEEP_MODE 0x090D010D
+#define OID_WW_CDPD_CIRCUIT_SWITCHED 0x090D010E
+#define OID_WW_CDPD_TEI 0x090D010F
+#define OID_WW_CDPD_RSSI 0x090D0110
+//
+// Network Dependent - Ardis:
+//
+#define OID_WW_ARD_SNDCP 0x09110101
+#define OID_WW_ARD_TMLY_MSG 0x09110102
+#define OID_WW_ARD_DATAGRAM 0x09110103
+//
+// Network Dependent - DataTac:
+//
+#define OID_WW_TAC_COMPRESSION 0x09150101
+#define OID_WW_TAC_SET_CONFIG 0x09150102
+#define OID_WW_TAC_GET_STATUS 0x09150103
+#define OID_WW_TAC_USER_HEADER 0x09150104
+//
+// Network Dependent - Metricom:
+//
+#define OID_WW_MET_FUNCTION 0x09190101
+//
+// IRDA objects
+//
+#define OID_IRDA_RECEIVING 0x0A010100
+#define OID_IRDA_TURNAROUND_TIME 0x0A010101
+#define OID_IRDA_SUPPORTED_SPEEDS 0x0A010102
+#define OID_IRDA_LINK_SPEED 0x0A010103
+#define OID_IRDA_MEDIA_BUSY 0x0A010104
+#define OID_IRDA_EXTRA_RCV_BOFS 0x0A010200
+#define OID_IRDA_RATE_SNIFF 0x0A010201
+#define OID_IRDA_UNICAST_LIST 0x0A010202
+#define OID_IRDA_MAX_UNICAST_LIST_SIZE 0x0A010203
+#define OID_IRDA_MAX_RECEIVE_WINDOW_SIZE 0x0A010204
+#define OID_IRDA_MAX_SEND_WINDOW_SIZE 0x0A010205
+//
+// Medium the Ndis Driver is running on (OID_GEN_MEDIA_SUPPORTED/
+// OID_GEN_MEDIA_IN_USE).
+//
+typedef enum _NDIS_MEDIUM {
+ NdisMedium802_3,
+ NdisMedium802_5,
+ NdisMediumFddi,
+ NdisMediumWan,
+ NdisMediumLocalTalk,
+ NdisMediumDix, // defined for convenience, not a real medium
+ NdisMediumArcnetRaw,
+ NdisMediumArcnet878_2,
+ NdisMediumAtm,
+ NdisMediumWirelessWan,
+ NdisMediumIrda,
+ NdisMediumMax // Not a real medium, defined as an upper-bound
+} NDIS_MEDIUM, *PNDIS_MEDIUM;
+
+//
+// Hardware status codes (OID_GEN_HARDWARE_STATUS).
+//
+typedef enum _NDIS_HARDWARE_STATUS {
+ NdisHardwareStatusReady,
+ NdisHardwareStatusInitializing,
+ NdisHardwareStatusReset,
+ NdisHardwareStatusClosing,
+ NdisHardwareStatusNotReady
+} NDIS_HARDWARE_STATUS, *PNDIS_HARDWARE_STATUS;
+
+//
+// this is the type passed in the OID_GEN_GET_TIME_CAPS request
+//
+typedef struct _GEN_GET_TIME_CAPS {
+ ULONG Flags; // Bits defined below
+
+ ULONG ClockPrecision;
+} GEN_GET_TIME_CAPS, *PGEN_GET_TIME_CAPS;
+
+#define READABLE_LOCAL_CLOCK 0x000000001
+#define CLOCK_NETWORK_DERIVED 0x000000002
+#define CLOCK_PRECISION 0x000000004
+#define RECEIVE_TIME_INDICATION_CAPABLE 0x000000008
+#define TIMED_SEND_CAPABLE 0x000000010
+#define TIME_STAMP_CAPABLE 0x000000020
+//
+//
+// this is the type passed in the OID_GEN_GET_NETCARD_TIME request
+//
+typedef struct _GEN_GET_NETCARD_TIME {
+ ULONG ReadTime;
+} GEN_GET_NETCARD_TIME, *PGEN_GET_NETCARD_TIME;
+
+//
+// Defines the attachment types for FDDI (OID_FDDI_ATTACHMENT_TYPE).
+//
+typedef enum _NDIS_FDDI_ATTACHMENT_TYPE {
+ NdisFddiTypeIsolated = 1,
+ NdisFddiTypeLocalA,
+ NdisFddiTypeLocalB,
+ NdisFddiTypeLocalAB,
+ NdisFddiTypeLocalS,
+ NdisFddiTypeWrapA,
+ NdisFddiTypeWrapB,
+ NdisFddiTypeWrapAB,
+ NdisFddiTypeWrapS,
+ NdisFddiTypeCWrapA,
+ NdisFddiTypeCWrapB,
+ NdisFddiTypeCWrapS,
+ NdisFddiTypeThrough
+} NDIS_FDDI_ATTACHMENT_TYPE, *PNDIS_FDDI_ATTACHMENT_TYPE;
+
+//
+// Defines the ring management states for FDDI (OID_FDDI_RING_MGT_STATE).
+//
+typedef enum _NDIS_FDDI_RING_MGT_STATE {
+ NdisFddiRingIsolated = 1,
+ NdisFddiRingNonOperational,
+ NdisFddiRingOperational,
+ NdisFddiRingDetect,
+ NdisFddiRingNonOperationalDup,
+ NdisFddiRingOperationalDup,
+ NdisFddiRingDirected,
+ NdisFddiRingTrace
+} NDIS_FDDI_RING_MGT_STATE, *PNDIS_FDDI_RING_MGT_STATE;
+
+//
+// Defines the Lconnection state for FDDI (OID_FDDI_LCONNECTION_STATE).
+//
+typedef enum _NDIS_FDDI_LCONNECTION_STATE {
+ NdisFddiStateOff = 1,
+ NdisFddiStateBreak,
+ NdisFddiStateTrace,
+ NdisFddiStateConnect,
+ NdisFddiStateNext,
+ NdisFddiStateSignal,
+ NdisFddiStateJoin,
+ NdisFddiStateVerify,
+ NdisFddiStateActive,
+ NdisFddiStateMaintenance
+} NDIS_FDDI_LCONNECTION_STATE, *PNDIS_FDDI_LCONNECTION_STATE;
+
+//
+// Defines the medium subtypes for WAN medium (OID_WAN_MEDIUM_SUBTYPE).
+//
+typedef enum _NDIS_WAN_MEDIUM_SUBTYPE {
+ NdisWanMediumHub,
+ NdisWanMediumX_25,
+ NdisWanMediumIsdn,
+ NdisWanMediumSerial,
+ NdisWanMediumFrameRelay,
+ NdisWanMediumAtm,
+ NdisWanMediumSonet,
+ NdisWanMediumSW56K
+} NDIS_WAN_MEDIUM_SUBTYPE, *PNDIS_WAN_MEDIUM_SUBTYPE;
+
+//
+// Defines the header format for WAN medium (OID_WAN_HEADER_FORMAT).
+//
+typedef enum _NDIS_WAN_HEADER_FORMAT {
+ NdisWanHeaderNative, // src/dest based on subtype, followed by NLPID
+ NdisWanHeaderEthernet // emulation of ethernet header
+} NDIS_WAN_HEADER_FORMAT, *PNDIS_WAN_HEADER_FORMAT;
+
+//
+// Defines the line quality on a WAN line (OID_WAN_QUALITY_OF_SERVICE).
+//
+typedef enum _NDIS_WAN_QUALITY {
+ NdisWanRaw,
+ NdisWanErrorControl,
+ NdisWanReliable
+} NDIS_WAN_QUALITY, *PNDIS_WAN_QUALITY;
+
+//
+// Defines the state of a token-ring adapter (OID_802_5_CURRENT_RING_STATE).
+//
+typedef enum _NDIS_802_5_RING_STATE {
+ NdisRingStateOpened = 1,
+ NdisRingStateClosed,
+ NdisRingStateOpening,
+ NdisRingStateClosing,
+ NdisRingStateOpenFailure,
+ NdisRingStateRingFailure
+} NDIS_802_5_RING_STATE, *PNDIS_802_5_RING_STATE;
+
+//
+// Defines the state of the LAN media
+//
+typedef enum _NDIS_MEDIA_STATE {
+ NdisMediaStateConnected,
+ NdisMediaStateDisconnected
+} NDIS_MEDIA_STATE, *PNDIS_MEDIA_STATE;
+
+//
+// The following is set on a per-packet basis as OOB data with NdisClass802_3Priority
+//
+typedef ULONG Priority_802_3; // 0-7 priority levels
+//
+// The following structure is used to query OID_GEN_CO_LINK_SPEED and
+// OID_GEN_CO_MINIMUM_LINK_SPEED. The first OID will return the current
+// link speed of the adapter. The second will return the minimum link speed
+// the adapter is capable of.
+//
+
+typedef struct _NDIS_CO_LINK_SPEED {
+ ULONG Outbound;
+ ULONG Inbound;
+} NDIS_CO_LINK_SPEED,
+
+*PNDIS_CO_LINK_SPEED;
+//
+// Ndis Packet Filter Bits (OID_GEN_CURRENT_PACKET_FILTER).
+//
+#define NDIS_PACKET_TYPE_DIRECTED 0x0001
+#define NDIS_PACKET_TYPE_MULTICAST 0x0002
+#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x0004
+#define NDIS_PACKET_TYPE_BROADCAST 0x0008
+#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x0010
+#define NDIS_PACKET_TYPE_PROMISCUOUS 0x0020
+#define NDIS_PACKET_TYPE_SMT 0x0040
+#define NDIS_PACKET_TYPE_ALL_LOCAL 0x0080
+#define NDIS_PACKET_TYPE_MAC_FRAME 0x8000
+#define NDIS_PACKET_TYPE_FUNCTIONAL 0x4000
+#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x2000
+#define NDIS_PACKET_TYPE_GROUP 0x1000
+//
+// Ndis Token-Ring Ring Status Codes (OID_802_5_CURRENT_RING_STATUS).
+//
+#define NDIS_RING_SIGNAL_LOSS 0x00008000
+#define NDIS_RING_HARD_ERROR 0x00004000
+#define NDIS_RING_SOFT_ERROR 0x00002000
+#define NDIS_RING_TRANSMIT_BEACON 0x00001000
+#define NDIS_RING_LOBE_WIRE_FAULT 0x00000800
+#define NDIS_RING_AUTO_REMOVAL_ERROR 0x00000400
+#define NDIS_RING_REMOVE_RECEIVED 0x00000200
+#define NDIS_RING_COUNTER_OVERFLOW 0x00000100
+#define NDIS_RING_SINGLE_STATION 0x00000080
+#define NDIS_RING_RING_RECOVERY 0x00000040
+//
+// Ndis protocol option bits (OID_GEN_PROTOCOL_OPTIONS).
+//
+#define NDIS_PROT_OPTION_ESTIMATED_LENGTH 0x00000001
+#define NDIS_PROT_OPTION_NO_LOOPBACK 0x00000002
+#define NDIS_PROT_OPTION_NO_RSVD_ON_RCVPKT 0x00000004
+//
+// Ndis MAC option bits (OID_GEN_MAC_OPTIONS).
+//
+#define NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA 0x00000001
+#define NDIS_MAC_OPTION_RECEIVE_SERIALIZED 0x00000002
+#define NDIS_MAC_OPTION_TRANSFERS_NOT_PEND 0x00000004
+#define NDIS_MAC_OPTION_NO_LOOPBACK 0x00000008
+#define NDIS_MAC_OPTION_FULL_DUPLEX 0x00000010
+#define NDIS_MAC_OPTION_EOTX_INDICATION 0x00000020
+#define NDIS_MAC_OPTION_RESERVED 0x80000000
+//
+// NDIS MAC option bits for OID_GEN_CO_MAC_OPTIONS.
+//
+#define NDIS_CO_MAC_OPTION_DYNAMIC_LINK_SPEED 0x00000001
+#ifdef IRDA
+//
+// The following is set on a per-packet basis as OOB data with NdisClassIrdaPacketInfo
+// This is the per-packet info specified on a per-packet basis
+//
+typedef struct _NDIS_IRDA_PACKET_INFO {
+ UINT ExtraBOFs;
+ UINT MinTurnAroundTime;
+} NDIS_IRDA_PACKET_INFO, *PNDIS_IRDA_PACKET_INFO;
+
+#endif
+#ifdef WIRELESS_WAN
+//
+// Wireless WAN structure definitions
+//
+//
+// currently defined Wireless network subtypes
+//
+typedef enum _NDIS_WW_NETWORK_TYPE {
+ NdisWWGeneric,
+ NdisWWMobitex,
+ NdisWWPinpoint,
+ NdisWWCDPD,
+ NdisWWArdis,
+ NdisWWDataTAC,
+ NdisWWMetricom,
+ NdisWWGSM,
+ NdisWWCDMA,
+ NdisWWTDMA,
+ NdisWWAMPS,
+ NdisWWInmarsat,
+ NdisWWpACT
+} NDIS_WW_NETWORK_TYPE;
+
+//
+// currently defined header formats
+//
+typedef enum _NDIS_WW_HEADER_FORMAT {
+ NdisWWDIXEthernetFrames,
+ NdisWWMPAKFrames,
+ NdisWWRDLAPFrames,
+ NdisWWMDC4800Frames
+} NDIS_WW_HEADER_FORMAT;
+
+//
+// currently defined encryption types
+//
+typedef enum _NDIS_WW_ENCRYPTION_TYPE {
+ NdisWWUnknownEncryption = -1,
+ NdisWWNoEncryption,
+ NdisWWDefaultEncryption
+} NDIS_WW_ENCRYPTION_TYPE, *PNDIS_WW_ENCRYPTION_TYPE;
+
+//
+// OID_WW_GEN_INDICATION_REQUEST
+//
+typedef struct _NDIS_WW_INDICATION_REQUEST {
+ NDIS_OID Oid; // IN
+
+ UINT uIndicationFlag; // IN
+
+ UINT uApplicationToken; // IN OUT
+
+ HANDLE hIndicationHandle; // IN OUT
+
+ INT iPollingInterval; // IN OUT
+
+ NDIS_VAR_DATA_DESC InitialValue; // IN OUT
+
+ NDIS_VAR_DATA_DESC OIDIndicationValue; // OUT - only valid after indication
+
+ NDIS_VAR_DATA_DESC TriggerValue; // IN
+
+} NDIS_WW_INDICATION_REQUEST, *PNDIS_WW_INDICATION_REQUEST;
+
+#define OID_INDICATION_REQUEST_ENABLE 0x0000
+#define OID_INDICATION_REQUEST_CANCEL 0x0001
+//
+// OID_WW_GEN_DEVICE_INFO
+//
+typedef struct _WW_DEVICE_INFO {
+ NDIS_VAR_DATA_DESC Manufacturer;
+ NDIS_VAR_DATA_DESC ModelNum;
+ NDIS_VAR_DATA_DESC SWVersionNum;
+ NDIS_VAR_DATA_DESC SerialNum;
+} WW_DEVICE_INFO, *PWW_DEVICE_INFO;
+
+//
+// OID_WW_GEN_OPERATION_MODE
+//
+typedef INT WW_OPERATION_MODE; // 0 = Normal mode
+ // 1 = Power saving mode
+ // -1 = mode unknown
+//
+// OID_WW_GEN_LOCK_STATUS
+//
+
+typedef INT WW_LOCK_STATUS; // 0 = unlocked
+ // 1 = locked
+ // -1 = unknown lock status
+//
+// OID_WW_GEN_DISABLE_TRANSMITTER
+//
+
+typedef INT WW_DISABLE_TRANSMITTER; // 0 = transmitter enabled
+ // 1 = transmitter disabled
+ // -1 = unknown value
+//
+// OID_WW_GEN_NETWORK_ID
+//
+
+typedef NDIS_VAR_DATA_DESC WW_NETWORK_ID;
+//
+// OID_WW_GEN_PERMANENT_ADDRESS
+//
+typedef NDIS_VAR_DATA_DESC WW_PERMANENT_ADDRESS;
+//
+// OID_WW_GEN_CURRENT_ADDRESS
+//
+typedef struct _WW_CURRENT_ADDRESS {
+ NDIS_WW_HEADER_FORMAT Format;
+ NDIS_VAR_DATA_DESC Address;
+} WW_CURRENT_ADDRESS, *PWW_CURRENT_ADDRESS;
+
+//
+// OID_WW_GEN_SUSPEND_DRIVER
+//
+typedef BOOLEAN WW_SUSPEND_DRIVER; // 0 = driver operational
+ // 1 = driver suspended
+//
+// OID_WW_GEN_BASESTATION_ID
+//
+
+typedef NDIS_VAR_DATA_DESC WW_BASESTATION_ID;
+//
+// OID_WW_GEN_CHANNEL_ID
+//
+typedef NDIS_VAR_DATA_DESC WW_CHANNEL_ID;
+//
+// OID_WW_GEN_ENCRYPTION_STATE
+//
+typedef BOOLEAN WW_ENCRYPTION_STATE; // 0 = if encryption is disabled
+ // 1 = if encryption is enabled
+//
+// OID_WW_GEN_CHANNEL_QUALITY
+//
+
+typedef INT WW_CHANNEL_QUALITY; // 0 = Not in network contact,
+ // 1-100 = Quality of Channel (100 is highest quality).
+ // -1 = channel quality is unknown
+//
+// OID_WW_GEN_REGISTRATION_STATUS
+//
+
+typedef INT WW_REGISTRATION_STATUS; // 0 = Registration denied
+ // 1 = Registration pending
+ // 2 = Registered
+ // -1 = unknown registration status
+//
+// OID_WW_GEN_RADIO_LINK_SPEED
+//
+
+typedef UINT WW_RADIO_LINK_SPEED; // Bits per second.
+//
+// OID_WW_GEN_LATENCY
+//
+
+typedef UINT WW_LATENCY; // milliseconds
+//
+// OID_WW_GEN_BATTERY_LEVEL
+//
+
+typedef INT WW_BATTERY_LEVEL; // 0-100 = battery level in percentage
+ // (100=fully charged)
+ // -1 = unknown battery level.
+//
+// OID_WW_GEN_EXTERNAL_POWER
+//
+
+typedef INT WW_EXTERNAL_POWER; // 0 = no external power connected
+ // 1 = external power connected
+ // -1 = unknown
+//
+// OID_WW_MET_FUNCTION
+//
+
+typedef NDIS_VAR_DATA_DESC WW_MET_FUNCTION;
+//
+// OID_WW_TAC_COMPRESSION
+//
+typedef BOOLEAN WW_TAC_COMPRESSION; // Determines whether or not network level compression
+ // is being used.
+//
+// OID_WW_TAC_SET_CONFIG
+//
+
+typedef struct _WW_TAC_SETCONFIG {
+ NDIS_VAR_DATA_DESC RCV_MODE;
+ NDIS_VAR_DATA_DESC TX_CONTROL;
+ NDIS_VAR_DATA_DESC RX_CONTROL;
+ NDIS_VAR_DATA_DESC FLOW_CONTROL;
+ NDIS_VAR_DATA_DESC RESET_CNF;
+ NDIS_VAR_DATA_DESC READ_CNF;
+} WW_TAC_SETCONFIG, *PWW_TAC_SETCONFIG;
+
+//
+// OID_WW_TAC_GET_STATUS
+//
+typedef struct _WW_TAC_GETSTATUS {
+ BOOLEAN Action; // Set = Execute command.
+
+ NDIS_VAR_DATA_DESC Command;
+ NDIS_VAR_DATA_DESC Option;
+ NDIS_VAR_DATA_DESC Response; // The response to the requested command
+ // - max. length of string is 256 octets.
+
+} WW_TAC_GETSTATUS, *PWW_TAC_GETSTATUS;
+
+//
+// OID_WW_TAC_USER_HEADER
+//
+typedef NDIS_VAR_DATA_DESC WW_TAC_USERHEADER; // This will hold the user header - Max. 64 octets.
+//
+// OID_WW_ARD_SNDCP
+//
+
+typedef struct _WW_ARD_SNDCP {
+ NDIS_VAR_DATA_DESC Version; // The version of SNDCP protocol supported.
+
+ INT BlockSize; // The block size used for SNDCP
+
+ INT Window; // The window size used in SNDCP
+
+} WW_ARD_SNDCP, *PWW_ARD_SNDCP;
+
+//
+// OID_WW_ARD_TMLY_MSG
+//
+typedef BOOLEAN WW_ARD_CHANNEL_STATUS; // The current status of the inbound RF Channel.
+//
+// OID_WW_ARD_DATAGRAM
+//
+
+typedef struct _WW_ARD_DATAGRAM {
+ BOOLEAN LoadLevel; // Byte that contains the load level info.
+
+ INT SessionTime; // Datagram session time remaining.
+
+ NDIS_VAR_DATA_DESC HostAddr; // Host address.
+
+ NDIS_VAR_DATA_DESC THostAddr; // Test host address.
+
+} WW_ARD_DATAGRAM, *PWW_ARD_DATAGRAM;
+
+//
+// OID_WW_CDPD_SPNI
+//
+typedef struct _WW_CDPD_SPNI {
+ UINT SPNI[10]; //10 16-bit service provider network IDs
+
+ INT OperatingMode; // 0 = ignore SPNI,
+ // 1 = require SPNI from list,
+ // 2 = prefer SPNI from list.
+ // 3 = exclude SPNI from list.
+
+} WW_CDPD_SPNI, *PWW_CDPD_SPNI;
+
+//
+// OID_WW_CDPD_WASI
+//
+typedef struct _WW_CDPD_WIDE_AREA_SERVICE_ID {
+ UINT WASI[10]; //10 16-bit wide area service IDs
+
+ INT OperatingMode; // 0 = ignore WASI,
+ // 1 = Require WASI from list,
+ // 2 = prefer WASI from list
+ // 3 = exclude WASI from list.
+
+} WW_CDPD_WIDE_AREA_SERVICE_ID, *PWW_CDPD_WIDE_AREA_SERVICE_ID;
+
+//
+// OID_WW_CDPD_AREA_COLOR
+//
+typedef INT WW_CDPD_AREA_COLOR;
+//
+// OID_WW_CDPD_TX_POWER_LEVEL
+//
+typedef UINT WW_CDPD_TX_POWER_LEVEL;
+//
+// OID_WW_CDPD_EID
+//
+typedef NDIS_VAR_DATA_DESC WW_CDPD_EID;
+//
+// OID_WW_CDPD_HEADER_COMPRESSION
+//
+typedef INT WW_CDPD_HEADER_COMPRESSION; // 0 = no header compression,
+ // 1 = always compress headers,
+ // 2 = compress headers if MD-IS does
+ // -1 = unknown
+//
+// OID_WW_CDPD_DATA_COMPRESSION
+//
+
+typedef INT WW_CDPD_DATA_COMPRESSION; // 0 = no data compression,
+ // 1 = data compression enabled
+ // -1 = unknown
+//
+// OID_WW_CDPD_CHANNEL_SELECT
+//
+
+typedef struct _WW_CDPD_CHANNEL_SELECT {
+ UINT ChannelID; // channel number
+
+ UINT fixedDuration; // duration in seconds
+
+} WW_CDPD_CHANNEL_SELECT, *PWW_CDPD_CHANNEL_SELECT;
+
+//
+// OID_WW_CDPD_CHANNEL_STATE
+//
+typedef enum _WW_CDPD_CHANNEL_STATE {
+ CDPDChannelNotAvail,
+ CDPDChannelScanning,
+ CDPDChannelInitAcquired,
+ CDPDChannelAcquired,
+ CDPDChannelSleeping,
+ CDPDChannelWaking,
+ CDPDChannelCSDialing,
+ CDPDChannelCSRedial,
+ CDPDChannelCSAnswering,
+ CDPDChannelCSConnected,
+ CDPDChannelCSSuspended
+} WW_CDPD_CHANNEL_STATE, *PWW_CDPD_CHANNEL_STATE;
+
+//
+// OID_WW_CDPD_NEI
+//
+typedef enum _WW_CDPD_NEI_FORMAT {
+ CDPDNeiIPv4,
+ CDPDNeiCLNP,
+ CDPDNeiIPv6
+} WW_CDPD_NEI_FORMAT, *PWW_CDPD_NEI_FORMAT;
+typedef enum _WW_CDPD_NEI_TYPE {
+ CDPDNeiIndividual,
+ CDPDNeiMulticast,
+ CDPDNeiBroadcast
+} WW_CDPD_NEI_TYPE;
+typedef struct _WW_CDPD_NEI {
+ UINT uNeiIndex;
+ WW_CDPD_NEI_FORMAT NeiFormat;
+ WW_CDPD_NEI_TYPE NeiType;
+ WORD NeiGmid; // group member identifier, only
+ // meaningful if NeiType ==
+ // CDPDNeiMulticast
+
+ NDIS_VAR_DATA_DESC NeiAddress;
+} WW_CDPD_NEI;
+
+//
+// OID_WW_CDPD_NEI_STATE
+//
+typedef enum _WW_CDPD_NEI_STATE {
+ CDPDUnknown,
+ CDPDRegistered,
+ CDPDDeregistered
+} WW_CDPD_NEI_STATE, *PWW_CDPD_NEI_STATE;
+typedef enum _WW_CDPD_NEI_SUB_STATE {
+ CDPDPending, // Registration pending
+ CDPDNoReason, // Registration denied - no reason given
+ CDPDMDISNotCapable, // Registration denied - MD-IS not capable of
+ // handling M-ES at this time
+ CDPDNEINotAuthorized, // Registration denied - NEI is not authorized to
+ // use this subnetwork
+ CDPDInsufficientAuth, // Registration denied - M-ES gave insufficient
+ // authentication credentials
+ CDPDUnsupportedAuth, // Registration denied - M-ES gave unsupported
+ // authentication credentials
+ CDPDUsageExceeded, // Registration denied - NEI has exceeded usage
+ // limitations
+ CDPDDeniedThisNetwork // Registration denied on this network, service
+ // may be obtained on alternate Service Provider
+ // network
+} WW_CDPD_NEI_SUB_STATE;
+typedef struct _WW_CDPD_NEI_REG_STATE {
+ UINT uNeiIndex;
+ WW_CDPD_NEI_STATE NeiState;
+ WW_CDPD_NEI_SUB_STATE NeiSubState;
+} WW_CDPD_NEI_REG_STATE, *PWW_CDPD_NEI_REG_STATE;
+
+//
+// OID_WW_CDPD_SERVICE_PROVIDER_IDENTIFIER
+//
+typedef struct _WW_CDPD_SERVICE_PROVIDER_ID {
+ UINT SPI[10]; //10 16-bit service provider IDs
+
+ INT OperatingMode; // 0 = ignore SPI,
+ // 1 = require SPI from list,
+ // 2 = prefer SPI from list.
+ // 3 = exclude SPI from list.
+
+} WW_CDPD_SERVICE_PROVIDER_ID, *PWW_CDPD_SERVICE_PROVIDER_ID;
+
+//
+// OID_WW_CDPD_SLEEP_MODE
+//
+typedef INT WW_CDPD_SLEEP_MODE;
+//
+// OID_WW_CDPD_TEI
+//
+typedef ULONG WW_CDPD_TEI;
+//
+// OID_WW_CDPD_CIRCUIT_SWITCHED
+//
+typedef struct _WW_CDPD_CIRCUIT_SWITCHED {
+ INT service_preference; // -1 = unknown,
+ // 0 = always use packet switched CDPD,
+ // 1 = always use CS CDPD via AMPS,
+ // 2 = always use CS CDPD via PSTN,
+ // 3 = use circuit switched via AMPS only
+ // when packet switched is not available.
+ // 4 = use packet switched only when circuit
+ // switched via AMPS is not available.
+ // 5 = device manuf. defined service
+ // preference.
+ // 6 = device manuf. defined service
+ // preference.
+
+ INT service_status; // -1 = unknown,
+ // 0 = packet switched CDPD,
+ // 1 = circuit switched CDPD via AMPS,
+ // 2 = circuit switched CDPD via PSTN.
+
+ INT connect_rate; // CS connection bit rate (bits per second).
+ // 0 = no active connection,
+ // -1 = unknown
+ // Dial code last used to dial.
+
+ NDIS_VAR_DATA_DESC dial_code[20];
+
+ UINT sid; // Current AMPS system ID
+
+ INT a_b_side_selection; // -1 = unknown,
+ // 0 = no AMPS service
+ // 1 = AMPS "A" side channels selected
+ // 2 = AMPS "B" side channels selected
+
+ INT AMPS_channel; // -1= unknown
+ // 0 = no AMPS service.
+ // 1-1023 = AMPS channel number in use
+
+ UINT action; // 0 = no action
+ // 1 = suspend (hangup)
+ // 2 = dial
+
+ // Default dial code for CS CDPD service
+ // encoded as specified in the CS CDPD
+ // implementor guidelines.
+ NDIS_VAR_DATA_DESC default_dial[20];
+
+ // Number for the CS CDPD network to call
+ // back the mobile, encoded as specified in
+ // the CS CDPD implementor guidelines.
+ NDIS_VAR_DATA_DESC call_back[20];
+
+ UINT sid_list[10]; // List of 10 16-bit preferred AMPS
+ // system IDs for CS CDPD.
+
+ UINT inactivity_timer; // Wait time after last data before dropping
+ // call.
+ // 0-65535 = inactivity time limit (seconds).
+
+ UINT receive_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT conn_resp_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT reconn_resp_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT disconn_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT NEI_reg_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT reconn_retry_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT link_reset_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT link_reset_ack_timer; // secs. per CS-CDPD Implementor Guidelines.
+
+ UINT n401_retry_limit; // per CS-CDPD Implementor Guidelines.
+
+ UINT n402_retry_limit; // per CS-CDPD Implementor Guidelines.
+
+ UINT n404_retry_limit; // per CS-CDPD Implementor Guidelines.
+
+ UINT n405_retry_limit; // per CS-CDPD Implementor Guidelines.
+
+} WW_CDPD_CIRCUIT_SWITCHED, *WW_PCDPD_CIRCUIT_SWITCHED;
+typedef UINT WW_CDPD_RSSI;
+//
+// OID_WW_PIN_LOC_AUTHORIZE
+//
+typedef INT WW_PIN_AUTHORIZED; // 0 = unauthorized
+ // 1 = authorized
+ // -1 = unknown
+//
+// OID_WW_PIN_LAST_LOCATION
+// OID_WW_PIN_LOC_FIX
+//
+
+typedef struct _WW_PIN_LOCATION {
+ INT Latitude; // Latitude in hundredths of a second
+
+ INT Longitude; // Longitude in hundredths of a second
+
+ INT Altitude; // Altitude in feet
+
+ INT FixTime; // Time of the location fix, since midnight, local time (of the
+ // current day), in tenths of a second
+
+ INT NetTime; // Current local network time of the current day, since midnight,
+ // in tenths of a second
+
+ INT LocQuality; // 0-100 = location quality
+
+ INT LatReg; // Latitude registration offset, in hundredths of a second
+
+ INT LongReg; // Longitude registration offset, in hundredths of a second
+
+ INT GMTOffset; // Offset in minutes of the local time zone from GMT
+
+} WW_PIN_LOCATION, *PWW_PIN_LOCATION;
+
+//
+// The following is set on a per-packet basis as OOB data with NdisClassWirelessWanMbxMailbox
+//
+typedef ULONG WW_MBX_MAILBOX_FLAG; // 1 = set mailbox flag, 0 = do not set mailbox flag
+//
+// OID_WW_MBX_SUBADDR
+//
+
+typedef struct _WW_MBX_PMAN {
+ BOOLEAN ACTION; // 0 = Login PMAN, 1 = Logout PMAN
+
+ UINT MAN;
+ UCHAR PASSWORD[8]; // Password should be null for Logout and indications.
+ // Maximum length of password is 8 chars.
+
+} WW_MBX_PMAN, *PWW_MBX_PMAN;
+
+//
+// OID_WW_MBX_FLEXLIST
+//
+typedef struct _WW_MBX_FLEXLIST {
+ INT count; // Number of MAN entries used.
+ // -1=unknown.
+
+ UINT MAN[7]; // List of MANs.
+
+} WW_MBX_FLEXLIST;
+
+//
+// OID_WW_MBX_GROUPLIST
+//
+typedef struct _WW_MBX_GROUPLIST {
+ INT count; // Number of MAN entries used.
+ // -1=unknown.
+
+ UINT MAN[15]; // List of MANs.
+
+} WW_MBX_GROUPLIST;
+
+//
+// OID_WW_MBX_TRAFFIC_AREA
+//
+typedef enum _WW_MBX_TRAFFIC_AREA {
+ unknown_traffic_area, // The driver has no information about the current traffic area.
+ in_traffic_area, // Mobile unit has entered a subscribed traffic area.
+ in_auth_traffic_area, // Mobile unit is outside traffic area but is authorized.
+ unauth_traffic_area // Mobile unit is outside traffic area but is un-authorized.
+} WW_MBX_TRAFFIC_AREA;
+
+//
+// OID_WW_MBX_LIVE_DIE
+//
+typedef INT WW_MBX_LIVE_DIE; // 0 = DIE last received
+ // 1 = LIVE last received
+ // -1 = unknown
+//
+// OID_WW_MBX_TEMP_DEFAULTLIST
+//
+
+typedef struct _WW_MBX_CHANNEL_PAIR {
+ UINT Mobile_Tx;
+ UINT Mobile_Rx;
+} WW_MBX_CHANNEL_PAIR, *PWW_MBX_CHANNEL_PAIR;
+typedef struct _WW_MBX_TEMPDEFAULTLIST {
+ UINT Length;
+ WW_MBX_CHANNEL_PAIR ChannelPair[1];
+} WW_MBX_TEMPDEFAULTLIST, *WW_PMBX_TEMPDEFAULTLIST;
+
+#endif // WIRELESS_WAN
+#endif // _NTDDNDIS_
diff --git a/src/See/Ntddpack.h b/src/See/Ntddpack.h
new file mode 100644
index 00000000..30945c1e
--- /dev/null
+++ b/src/See/Ntddpack.h
@@ -0,0 +1,26 @@
+
+#ifndef __NTDDPACKET
+#define __NTDDPACKET 1
+#include "devioctl.h"
+/*#include <packon.h> */
+struct _PACKET_OID_DATA {
+ ULONG Oid;
+ ULONG Length;
+ UCHAR Data[1];
+};
+
+typedef struct _PACKET_OID_DATA PACKET_OID_DATA, *PPACKET_OID_DATA;
+
+/*#include <packoff.h> */
+#define FILE_DEVICE_PROTOCOL 0x8000
+#define IOCTL_PROTOCOL_QUERY_OID CTL_CODE(FILE_DEVICE_PROTOCOL, 0 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_SET_OID CTL_CODE(FILE_DEVICE_PROTOCOL, 1 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_STATISTICS CTL_CODE(FILE_DEVICE_PROTOCOL, 2 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_RESET CTL_CODE(FILE_DEVICE_PROTOCOL, 3 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_READ CTL_CODE(FILE_DEVICE_PROTOCOL, 4 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_WRITE CTL_CODE(FILE_DEVICE_PROTOCOL, 5 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_MACNAME CTL_CODE(FILE_DEVICE_PROTOCOL, 6 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_OPEN CTL_CODE(FILE_DEVICE_PROTOCOL, 7 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_CLOSE CTL_CODE(FILE_DEVICE_PROTOCOL, 8 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#endif
diff --git a/src/See/Openclos.c b/src/See/Openclos.c
new file mode 100644
index 00000000..adb9bf22
--- /dev/null
+++ b/src/See/Openclos.c
@@ -0,0 +1,707 @@
+/*
+ * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies
+ * nor the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <GlobalConst.h>
+
+#include "ntddk.h"
+#include "ntiologc.h"
+#include "ndis.h"
+
+#include "debug.h"
+#include "packet.h"
+
+static NDIS_MEDIUM MediumArray[] = {
+ NdisMedium802_3,
+// NdisMediumWan,
+ NdisMediumFddi,
+ NdisMediumArcnet878_2,
+ NdisMediumAtm,
+ NdisMedium802_5
+};
+
+#define NUM_NDIS_MEDIA (sizeof MediumArray / sizeof MediumArray[0])
+
+ULONG NamedEventsCounter=0;
+
+//Itoa. Replaces the buggy RtlIntegerToUnicodeString
+void PacketItoa(UINT n,PUCHAR buf){
+int i;
+
+ for(i=0;i<20;i+=2){
+ buf[18-i]=(n%10)+48;
+ buf[19-i]=0;
+ n/=10;
+ }
+
+}
+
+/// Global start time. Used as an absolute reference for timestamp conversion.
+struct time_conv G_Start_Time = {
+ 0,
+ {0, 0},
+};
+
+UINT n_Opened_Instances = 0;
+
+NDIS_SPIN_LOCK Opened_Instances_Lock;
+
+//-------------------------------------------------------------------
+
+NTSTATUS NPF_Open(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
+{
+
+ PDEVICE_EXTENSION DeviceExtension;
+
+ POPEN_INSTANCE Open;
+
+ PIO_STACK_LOCATION IrpSp;
+
+ NDIS_STATUS Status;
+ NDIS_STATUS ErrorStatus;
+ UINT i;
+ PCHAR EvName;
+
+ IF_LOUD(DbgPrint("NPF: OpenAdapter\n");)
+
+ DeviceExtension = DeviceObject->DeviceExtension;
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+ // allocate some memory for the open structure
+ Open=ExAllocatePoolWithTag(NonPagedPool, sizeof(OPEN_INSTANCE), '0OWA');
+
+ if (Open==NULL) {
+ // no memory
+ Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlZeroMemory(
+ Open,
+ sizeof(OPEN_INSTANCE)
+ );
+
+
+ EvName=ExAllocatePoolWithTag(NonPagedPool, sizeof(L"\\BaseNamedObjects\\SEE0000000000"), '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,
+ TRANSMIT_PACKETS,
+ sizeof(PACKET_RESERVED));
+
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ IF_LOUD(DbgPrint("NPF: Failed to allocate packet pool\n");)
+
+ ExFreePool(Open);
+ ExFreePool(EvName);
+ Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+
+ RtlCopyBytes(EvName,L"\\BaseNamedObjects\\SEE0000000000",sizeof(L"\\BaseNamedObjects\\SEE0000000000"));
+
+ //Create the string containing the name of the read event
+ RtlInitUnicodeString(&Open->ReadEventName,(PCWSTR) EvName);
+
+ PacketItoa(NamedEventsCounter,(PUCHAR)(Open->ReadEventName.Buffer+21));
+
+ InterlockedIncrement(&NamedEventsCounter);
+
+ IF_LOUD(DbgPrint("\nCreated the named event for the read; name=%ws, counter=%d\n", Open->ReadEventName.Buffer,NamedEventsCounter-1);)
+
+ //allocate the event objects
+ 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;
+ }
+
+ KeInitializeEvent(Open->ReadEvent, NotificationEvent, FALSE);
+ KeClearEvent(Open->ReadEvent);
+ NdisInitializeEvent(&Open->WriteEvent);
+ NdisInitializeEvent(&Open->IOEvent);
+ NdisInitializeEvent(&Open->DumpEvent);
+ NdisAllocateSpinLock(&Open->MachineLock);
+ NdisAllocateSpinLock(&Open->WriteLock);
+ Open->WriteInProgress = FALSE;
+
+ // list to hold irp's want to reset the adapter
+ InitializeListHead(&Open->ResetIrpList);
+
+
+ // Initialize the request list
+ KeInitializeSpinLock(&Open->RequestSpinLock);
+ InitializeListHead(&Open->RequestList);
+
+ // Initializes the extended memory of the NPF machine
+ Open->mem_ex.buffer = ExAllocatePoolWithTag(NonPagedPool, DEFAULT_MEM_EX_SIZE, '2OWA');
+ if((Open->mem_ex.buffer) == NULL)
+ {
+ // no memory
+ ExFreePool(Open);
+ 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);
+
+ //
+ // Initialize the open instance
+ //
+// Open->BufSize = 0;
+// Open->Buffer = NULL;
+// Open->Bhead = 0;
+// Open->Btail = 0;
+// (INT)Open->BLastByte = -1;
+// 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;
+ Open->MaxFrameSize = 0;
+ Open->WriterSN=0;
+ Open->ReaderSN=0;
+ Open->Size=0;
+
+
+
+ //allocate the spinlock for the statistic counters
+ NdisAllocateSpinLock(&Open->CountersLock);
+
+ //allocate the spinlock for the buffer pointers
+ // NdisAllocateSpinLock(&Open->BufLock);
+
+ //
+ // link up the request stored in our open block
+ //
+ for (i=0;i<MAX_REQUESTS;i++) {
+ ExInterlockedInsertTailList(
+ &Open->RequestList,
+ &Open->Requests[i].ListElement,
+ &Open->RequestSpinLock);
+
+ }
+
+
+ IoMarkIrpPending(Irp);
+
+ //
+ // Try to open the MAC
+ //
+ IF_LOUD(DbgPrint("NPF: Openinig the device %ws, BindingContext=%d\n",DeviceExtension->AdapterName.Buffer, Open);)
+
+ NdisOpenAdapter(
+ &Status,
+ &ErrorStatus,
+ &Open->AdapterHandle,
+ &Open->Medium,
+ MediumArray,
+ NUM_NDIS_MEDIA,
+ DeviceExtension->NdisProtocolHandle,
+ Open,
+ &DeviceExtension->AdapterName,
+ 0,
+ NULL);
+
+ IF_LOUD(DbgPrint("NPF: Opened the device, Status=%x\n",Status);)
+
+ if (Status != NDIS_STATUS_PENDING)
+ {
+ NPF_OpenAdapterComplete(Open,Status,NDIS_STATUS_SUCCESS);
+ }
+
+ return(STATUS_PENDING);
+}
+
+//-------------------------------------------------------------------
+
+VOID NPF_OpenAdapterComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status,
+ IN NDIS_STATUS OpenErrorStatus)
+{
+
+ PIRP Irp;
+ POPEN_INSTANCE Open;
+ PLIST_ENTRY RequestListEntry;
+ PINTERNAL_REQUEST MaxSizeReq;
+ NDIS_STATUS ReqStatus;
+
+
+ IF_LOUD(DbgPrint("NPF: OpenAdapterComplete\n");)
+
+ Open= (POPEN_INSTANCE)ProtocolBindingContext;
+
+ //
+ // get the open irp
+ //
+ Irp=Open->OpenCloseIrp;
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ 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);
+
+ ZwClose(Open->ReadEventHandle);
+
+
+ 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);
+
+ // Extract a request from the list of free ones
+ RequestListEntry=ExInterlockedRemoveHeadList(&Open->RequestList, &Open->RequestSpinLock);
+
+ if (RequestListEntry == NULL)
+ {
+
+ Open->MaxFrameSize = 1560; // Assume Ethernet
+
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ return;
+ }
+
+ MaxSizeReq = CONTAINING_RECORD(RequestListEntry, INTERNAL_REQUEST, ListElement);
+ MaxSizeReq->Irp = Irp;
+ MaxSizeReq->Internal = TRUE;
+
+
+ MaxSizeReq->Request.RequestType = NdisRequestQueryInformation;
+ MaxSizeReq->Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_MAXIMUM_TOTAL_SIZE;
+
+
+ MaxSizeReq->Request.DATA.QUERY_INFORMATION.InformationBuffer = &Open->MaxFrameSize;
+ MaxSizeReq->Request.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
+
+ // submit the request
+ NdisRequest(
+ &ReqStatus,
+ Open->AdapterHandle,
+ &MaxSizeReq->Request);
+
+
+ if (ReqStatus != NDIS_STATUS_PENDING) {
+ NPF_RequestComplete(Open, &MaxSizeReq->Request, ReqStatus);
+ }
+
+ return;
+
+ }
+
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ return;
+
+}
+
+//-------------------------------------------------------------------
+
+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("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 filter if it's present
+ if(Open->bpfprogram != NULL)
+ ExFreePool(Open->bpfprogram);
+
+//
+// Jitted filters are supported on x86 (32bit) only
+//
+#ifdef __NPF_x86__
+ // Free the jitted filter if it's present
+ if(Open->Filter != NULL)
+ BPF_Destroy_JIT_Filter(Open->Filter);
+#endif
+
+ //free the buffer
+// Open->BufSize=0;
+// if(Open->Buffer != NULL)ExFreePool(Open->Buffer);
+
+ if (Open->Size > 0)
+ ExFreePool(Open->CpuData[0].Buffer);
+
+ //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);
+
+ Irp->IoStatus.Information = 0;
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ return(STATUS_SUCCESS);
+ }
+
+ // 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){
+
+ 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);
+ }
+
+ // Destroy the read Event
+ ZwClose(Open->ReadEventHandle);
+
+ // Close the adapter
+ NdisCloseAdapter(
+ &Status,
+ Open->AdapterHandle
+ );
+
+ if (Status != NDIS_STATUS_PENDING) {
+
+ NPF_CloseAdapterComplete(
+ Open,
+ Status
+ );
+ return STATUS_SUCCESS;
+
+ }
+
+ return(STATUS_PENDING);
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_CloseAdapterComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status)
+{
+ POPEN_INSTANCE Open;
+ PIRP Irp;
+
+ 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 filter if it's present
+ if(Open->bpfprogram != NULL)
+ ExFreePool(Open->bpfprogram);
+
+//
+// Jitted filters are supported on x86 (32bit) only
+//
+#ifdef __NPF_x86__
+ // Free the jitted filter if it's present
+ if(Open->Filter != NULL)
+ BPF_Destroy_JIT_Filter(Open->Filter);
+#endif // __NPF_x86__
+
+ //free the buffer
+// Open->BufSize = 0;
+// if(Open->Buffer!=NULL)ExFreePool(Open->Buffer);
+
+ if (Open->Size > 0)
+ ExFreePool(Open->CpuData[0].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);
+
+ // Complete the request only if the instance is still bound to the adapter
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ }
+ 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
+NPF_BindAdapter(
+ OUT PNDIS_STATUS Status,
+ IN NDIS_HANDLE BindContext,
+ IN PNDIS_STRING DeviceName,
+ IN PVOID SystemSpecific1,
+ IN PVOID SystemSpecific2
+ )
+{
+ IF_LOUD(DbgPrint("NPF: NPF_BindAdapter\n");)
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_UnbindAdapter(
+ OUT PNDIS_STATUS Status,
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_HANDLE UnbindContext
+ )
+{
+ POPEN_INSTANCE Open =(POPEN_INSTANCE)ProtocolBindingContext;
+ NDIS_STATUS lStatus;
+
+ IF_LOUD(DbgPrint("NPF: NPF_UnbindAdapter\n");)
+
+ // Reset the buffer size. This tells the dump thread to stop.
+// Open->BufSize=0;
+
+ NdisResetEvent(&Open->IOEvent);
+
+ // This open instance is no more bound to the adapter, set Bound to False
+ InterlockedExchange( (PLONG) &Open->Bound, FALSE );
+
+ // Awake a possible pending read on this instance
+ 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);
+
+ // close the adapter
+ NdisCloseAdapter(
+ &lStatus,
+ Open->AdapterHandle
+ );
+
+ if (lStatus != NDIS_STATUS_PENDING) {
+
+ NPF_CloseAdapterComplete(
+ Open,
+ lStatus
+ );
+
+ *Status = NDIS_STATUS_SUCCESS;
+ return;
+
+ }
+
+ *Status = NDIS_STATUS_SUCCESS;
+ return;
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_ResetComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status)
+
+{
+ POPEN_INSTANCE Open;
+ PIRP Irp;
+
+ PLIST_ENTRY ResetListEntry;
+
+ IF_LOUD(DbgPrint("NPF: PacketResetComplte\n");)
+
+ Open= (POPEN_INSTANCE)ProtocolBindingContext;
+
+
+ //
+ // remove the reset IRP from the list
+ //
+ ResetListEntry=ExInterlockedRemoveHeadList(
+ &Open->ResetIrpList,
+ &Open->RequestSpinLock
+ );
+
+#if DBG
+ if (ResetListEntry == NULL) {
+ DbgBreakPoint();
+ return;
+ }
+#endif
+
+ Irp=CONTAINING_RECORD(ResetListEntry,IRP,Tail.Overlay.ListEntry);
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ IF_LOUD(DbgPrint("NPF: PacketResetComplte exit\n");)
+
+ return;
+
+}
diff --git a/src/See/Packet.c b/src/See/Packet.c
new file mode 100644
index 00000000..a3718aae
--- /dev/null
+++ b/src/See/Packet.c
@@ -0,0 +1,1607 @@
+/*
+ * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies
+ * nor the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <GlobalConst.h>
+
+#include "stdarg.h"
+#include "ntddk.h"
+#include "ntiologc.h"
+#include "ndis.h"
+
+#include "ntddpack.h"
+
+#include "debug.h"
+#include "packet.h"
+#include "win_bpf.h"
+#include "win_bpf_filter_init.h"
+
+#if DBG
+// Declare the global debug flag for this driver.
+ULONG PacketDebugFlag = PACKET_DEBUG_LOUD;
+
+#endif
+
+PDEVICE_EXTENSION GlobalDeviceExtension;
+
+//
+// Global strings
+//
+NDIS_STRING NPF_Prefix = NDIS_STRING_CONST("SEE_");
+NDIS_STRING devicePrefix = NDIS_STRING_CONST("\\Device\\");
+NDIS_STRING symbolicLinkPrefix = NDIS_STRING_CONST("\\DosDevices\\");
+NDIS_STRING tcpLinkageKeyName = NDIS_STRING_CONST("\\Registry\\Machine\\System"
+ L"\\CurrentControlSet\\Services\\Tcpip\\Linkage");
+NDIS_STRING AdapterListKey = NDIS_STRING_CONST("\\Registry\\Machine\\System"
+ L"\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}");
+NDIS_STRING bindValueName = NDIS_STRING_CONST("Bind");
+
+/// 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;
+
+ULONG NCpu = 1;
+
+ULONG TimestampMode;
+UINT g_SendPacketFlags = 0;
+
+
+// Crush now
+void Crush(UINT a, UINT b, UINT c, UINT d)
+{
+ KeBugCheckEx(0x3f000000 + a, (ULONG_PTR)a, (ULONG_PTR)b, (ULONG_PTR)c, (ULONG_PTR)d);
+}
+
+//
+// Packet Driver's entry routine.
+//
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ )
+{
+
+ NDIS_PROTOCOL_CHARACTERISTICS ProtocolChar;
+ 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;
+ NDIS_HANDLE NdisProtocolHandle;
+ WCHAR* bindT;
+ PKEY_VALUE_PARTIAL_INFORMATION tcpBindingsP;
+ UNICODE_STRING macName;
+ ULONG OsMajorVersion, OsMinorVersion;
+
+ PsGetVersion(&OsMajorVersion, &OsMinorVersion, NULL, NULL);
+ //
+ // Define the correct flag to skip the loopback packets, according to the OS
+ //
+ if((OsMajorVersion == 5) && (OsMinorVersion == 0))
+ {
+ // Windows 2000 wants both NDIS_FLAGS_DONT_LOOPBACK and NDIS_FLAGS_SKIP_LOOPBACK
+ g_SendPacketFlags = NDIS_FLAGS_DONT_LOOPBACK | NDIS_FLAGS_SKIP_LOOPBACK_W2K;
+ }
+ else
+ {
+ // Windows XP, 2003 and follwing want only NDIS_FLAGS_DONT_LOOPBACK
+ g_SendPacketFlags = NDIS_FLAGS_DONT_LOOPBACK;
+ }
+
+ if (((OsMajorVersion == 6) && (OsMinorVersion >= 1)) || (OsMajorVersion >= 7))
+ {
+ // Use KeQueryActiveProcessors to get the number of CPUs in Windows 7 or later
+ KAFFINITY cpus = KeQueryActiveProcessors();
+ NCpu = 0;
+
+ while (cpus)
+ {
+ if (cpus % 2)
+ {
+ NCpu++;
+ }
+
+ cpus = cpus / 2;
+ }
+ }
+ else
+ {
+ // Use NdisSystemProcessorCount in Windows Vista or earlier
+ NCpu = NdisSystemProcessorCount();
+ }
+
+
+ ReadTimeStampModeFromRegistry(RegistryPath);
+
+ IF_LOUD(DbgPrint("%ws",RegistryPath->Buffer);)
+
+ 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 = NPF_OpenAdapterComplete;
+ ProtocolChar.CloseAdapterCompleteHandler = NPF_CloseAdapterComplete;
+ ProtocolChar.SendCompleteHandler = NPF_SendComplete;
+ ProtocolChar.TransferDataCompleteHandler = NPF_TransferDataComplete;
+ ProtocolChar.ResetCompleteHandler = NPF_ResetComplete;
+ ProtocolChar.RequestCompleteHandler = NPF_RequestComplete;
+ ProtocolChar.ReceiveHandler = NPF_tap;
+ ProtocolChar.ReceiveCompleteHandler = NPF_ReceiveComplete;
+ ProtocolChar.StatusHandler = NPF_Status;
+ ProtocolChar.StatusCompleteHandler = NPF_StatusComplete;
+#ifdef NDIS50
+ ProtocolChar.BindAdapterHandler = NPF_BindAdapter;
+ ProtocolChar.UnbindAdapterHandler = NPF_UnbindAdapter;
+ ProtocolChar.PnPEventHandler = NPF_PowerChange;
+ ProtocolChar.ReceivePacketHandler = NULL;
+#endif
+ ProtocolChar.Name = ProtoName;
+
+ NdisRegisterProtocol(
+ &Status,
+ &NdisProtocolHandle,
+ &ProtocolChar,
+ sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
+
+ 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] = 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;
+
+ 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;
+
+RegistryError:
+
+ NdisDeregisterProtocol(
+ &Status,
+ NdisProtocolHandle
+ );
+
+ Status=STATUS_UNSUCCESSFUL;
+
+ return(Status);
+
+}
+
+//-------------------------------------------------------------------
+
+PWCHAR getAdaptersList(void)
+{
+ PKEY_VALUE_PARTIAL_INFORMATION result = NULL;
+ OBJECT_ATTRIBUTES objAttrs;
+ NTSTATUS status;
+ HANDLE keyHandle;
+ UINT BufPos=0;
+ UINT BufLen=4096;
+
+
+ PWCHAR DeviceNames = (PWCHAR) ExAllocatePoolWithTag(PagedPool, BufLen, '0PWA');
+
+ if (DeviceNames == NULL) {
+ IF_LOUD(DbgPrint("Unable the allocate the buffer for the list of the network adapters\n");)
+ return NULL;
+ }
+
+ InitializeObjectAttributes(&objAttrs, &AdapterListKey,
+ OBJ_CASE_INSENSITIVE, NULL, NULL);
+ status = ZwOpenKey(&keyHandle, KEY_READ, &objAttrs);
+ if (!NT_SUCCESS(status)) {
+ IF_LOUD(DbgPrint("\n\nStatus of %x opening %ws\n", status, tcpLinkageKeyName.Buffer);)
+ }
+ else { //OK
+
+ ULONG resultLength;
+ CHAR AdapInfo[1024];
+ UINT i=0;
+ KEY_VALUE_PARTIAL_INFORMATION valueInfo;
+
+ 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)
+ {
+ WCHAR ExportKeyName [512];
+ PWCHAR ExportKeyPrefix = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\";
+ UINT ExportKeyPrefixSize = sizeof(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}");
+ PWCHAR LinkageKeyPrefix = L"\\Linkage";
+ UINT LinkageKeyPrefixSize = sizeof(L"\\Linkage");
+ NDIS_STRING FinalExportKey = NDIS_STRING_CONST("Export");
+ PKEY_BASIC_INFORMATION tInfo= (PKEY_BASIC_INFORMATION)AdapInfo;
+ UNICODE_STRING AdapterKeyName;
+ HANDLE ExportKeyHandle;
+
+ RtlCopyMemory(ExportKeyName,
+ ExportKeyPrefix,
+ ExportKeyPrefixSize);
+
+ RtlCopyMemory((PCHAR)ExportKeyName+ExportKeyPrefixSize,
+ tInfo->Name,
+ tInfo->NameLength+2);
+
+ RtlCopyMemory((PCHAR)ExportKeyName+ExportKeyPrefixSize+tInfo->NameLength,
+ LinkageKeyPrefix,
+ LinkageKeyPrefixSize);
+
+ IF_LOUD(DbgPrint("Key name=%ws\n", ExportKeyName);)
+
+ RtlInitUnicodeString(&AdapterKeyName, ExportKeyName);
+
+ InitializeObjectAttributes(&objAttrs, &AdapterKeyName,
+ OBJ_CASE_INSENSITIVE, NULL, NULL);
+
+ status=ZwOpenKey(&ExportKeyHandle,KEY_READ,&objAttrs);
+
+ if (!NT_SUCCESS(status)) {
+ IF_LOUD(DbgPrint("OpenKey Failed, %d!\n",status);)
+ i++;
+ continue;
+ }
+
+ status = ZwQueryValueKey(ExportKeyHandle, &FinalExportKey,
+ KeyValuePartialInformation, &valueInfo,
+ sizeof(valueInfo), &resultLength);
+
+ if (!NT_SUCCESS(status) && (status != STATUS_BUFFER_OVERFLOW)) {
+ IF_LOUD(DbgPrint("\n\nStatus of %x querying key value for size\n", status);)
+ }
+ else { // We know how big it needs to be.
+ ULONG valueInfoLength = valueInfo.DataLength + FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
+ PKEY_VALUE_PARTIAL_INFORMATION valueInfoP = (PKEY_VALUE_PARTIAL_INFORMATION) ExAllocatePoolWithTag(PagedPool, valueInfoLength, '1PWA');
+ if (valueInfoP != NULL) {
+ status = ZwQueryValueKey(ExportKeyHandle, &FinalExportKey,
+ KeyValuePartialInformation,
+ valueInfoP,
+ valueInfoLength, &resultLength);
+ if (!NT_SUCCESS(status)) {
+ IF_LOUD(DbgPrint("Status of %x querying key value\n", status);)
+ }
+ else{
+ IF_LOUD(DbgPrint("Device %d = %ws\n", i, valueInfoP->Data);)
+ if( BufPos + valueInfoP->DataLength > BufLen ) {
+ // double the buffer size
+ PWCHAR DeviceNames2 = (PWCHAR) ExAllocatePoolWithTag(PagedPool, BufLen
+ << 1, '0PWA');
+ if( DeviceNames2 ) {
+ RtlCopyMemory((PCHAR)DeviceNames2, (PCHAR)DeviceNames, BufLen);
+ BufLen <<= 1;
+ ExFreePool(DeviceNames);
+ DeviceNames = DeviceNames2;
+ }
+ }
+ if( BufPos + valueInfoP->DataLength < BufLen ) {
+ RtlCopyMemory((PCHAR)DeviceNames+BufPos,
+ valueInfoP->Data,
+ valueInfoP->DataLength);
+ BufPos+=valueInfoP->DataLength-2;
+ }
+ }
+
+ ExFreePool(valueInfoP);
+ }
+ else {
+ IF_LOUD(DbgPrint("Error Allocating the buffer for the device name\n");)
+ }
+
+ }
+
+ // terminate the buffer
+ DeviceNames[BufPos/2]=0;
+ DeviceNames[BufPos/2+1]=0;
+
+ ZwClose (ExportKeyHandle);
+ i++;
+
+ }
+
+ ZwClose (keyHandle);
+
+ }
+ if(BufPos==0){
+ ExFreePool(DeviceNames);
+ return NULL;
+ }
+ return DeviceNames;
+}
+
+//-------------------------------------------------------------------
+
+PKEY_VALUE_PARTIAL_INFORMATION getTcpBindings(void)
+{
+ PKEY_VALUE_PARTIAL_INFORMATION result = NULL;
+ OBJECT_ATTRIBUTES objAttrs;
+ NTSTATUS status;
+ HANDLE keyHandle;
+
+ InitializeObjectAttributes(&objAttrs, &tcpLinkageKeyName,
+ OBJ_CASE_INSENSITIVE, NULL, NULL);
+ status = ZwOpenKey(&keyHandle, KEY_READ, &objAttrs);
+ if (!NT_SUCCESS(status)) {
+ IF_LOUD(DbgPrint("\n\nStatus of %x opening %ws\n", status, tcpLinkageKeyName.Buffer);)
+ }
+ else {
+ ULONG resultLength;
+ KEY_VALUE_PARTIAL_INFORMATION valueInfo;
+
+ IF_LOUD(DbgPrint("\n\nOpened %ws\n", tcpLinkageKeyName.Buffer);)
+
+ status = ZwQueryValueKey(keyHandle, &bindValueName,
+ KeyValuePartialInformation, &valueInfo,
+ sizeof(valueInfo), &resultLength);
+ if (!NT_SUCCESS(status) && (status != STATUS_BUFFER_OVERFLOW)) {
+ IF_LOUD(DbgPrint("\n\nStatus of %x querying key value for size\n", status);)
+ }
+ else { // We know how big it needs to be.
+ ULONG valueInfoLength = valueInfo.DataLength + FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]);
+ PKEY_VALUE_PARTIAL_INFORMATION valueInfoP =
+ (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(PagedPool, valueInfoLength, '2PWA');
+
+ if (valueInfoP != NULL) {
+ status = ZwQueryValueKey(keyHandle, &bindValueName,
+ KeyValuePartialInformation,
+ valueInfoP,
+ valueInfoLength, &resultLength);
+
+ if (!NT_SUCCESS(status)) {
+ IF_LOUD(DbgPrint("\n\nStatus of %x querying key value\n", status);)
+ }
+ else if (valueInfoLength != resultLength) {
+ IF_LOUD(DbgPrint("\n\nQuerying key value result len = %u "
+ "but previous len = %u\n",
+ resultLength, valueInfoLength);)
+ }
+ else if (valueInfoP->Type != REG_MULTI_SZ) {
+ IF_LOUD(DbgPrint("\n\nTcpip bind value not REG_MULTI_SZ but %u\n",
+ valueInfoP->Type);)
+ }
+ else { // It's OK
+#if DBG
+ ULONG i;
+ WCHAR* dataP = (WCHAR*)(&valueInfoP->Data[0]);
+ IF_LOUD(DbgPrint("\n\nBind value:\n");)
+ for (i = 0; *dataP != UNICODE_NULL; i++) {
+ UNICODE_STRING macName;
+ RtlInitUnicodeString(&macName, dataP);
+ IF_LOUD(DbgPrint("\n\nMac %u = %ws\n", i, macName.Buffer);)
+ dataP +=
+ (macName.Length + sizeof(UNICODE_NULL)) / sizeof(WCHAR);
+ }
+#endif // DBG
+ result = valueInfoP;
+ }
+ }
+ }
+ ZwClose(keyHandle);
+ }
+ return result;
+}
+
+//-------------------------------------------------------------------
+
+BOOLEAN createDevice(IN OUT PDRIVER_OBJECT adriverObjectP,
+ IN PUNICODE_STRING amacNameP, NDIS_HANDLE aProtoHandle)
+{
+ NTSTATUS status;
+ PDEVICE_OBJECT devObjP;
+ UNICODE_STRING deviceName;
+ UNICODE_STRING deviceSymLink;
+
+ IF_LOUD(DbgPrint("\n\ncreateDevice for MAC %ws\n", amacNameP->Buffer););
+ if (RtlCompareMemory(amacNameP->Buffer, devicePrefix.Buffer,
+ devicePrefix.Length) < devicePrefix.Length)
+ {
+ return FALSE;
+ }
+
+ deviceName.Length = 0;
+ deviceName.MaximumLength = (USHORT)(amacNameP->Length + NPF_Prefix.Length + sizeof(UNICODE_NULL));
+ deviceName.Buffer = ExAllocatePoolWithTag(PagedPool, deviceName.MaximumLength, '3PWA');
+
+ if (deviceName.Buffer == NULL)
+ return FALSE;
+
+ deviceSymLink.Length = 0;
+ deviceSymLink.MaximumLength =(USHORT)(amacNameP->Length-devicePrefix.Length
+ + symbolicLinkPrefix.Length
+ + NPF_Prefix.Length
+ + sizeof(UNICODE_NULL));
+
+ deviceSymLink.Buffer = ExAllocatePoolWithTag(NonPagedPool, deviceSymLink.MaximumLength, '3PWA');
+
+ if (deviceSymLink.Buffer == NULL)
+ {
+ ExFreePool(deviceName.Buffer);
+ return FALSE;
+ }
+
+ RtlAppendUnicodeStringToString(&deviceName, &devicePrefix);
+ RtlAppendUnicodeStringToString(&deviceName, &NPF_Prefix);
+ RtlAppendUnicodeToString(&deviceName, amacNameP->Buffer +
+ devicePrefix.Length / sizeof(WCHAR));
+
+ RtlAppendUnicodeStringToString(&deviceSymLink, &symbolicLinkPrefix);
+ RtlAppendUnicodeStringToString(&deviceSymLink, &NPF_Prefix);
+ RtlAppendUnicodeToString(&deviceSymLink, amacNameP->Buffer +
+ devicePrefix.Length / sizeof(WCHAR));
+
+ IF_LOUD(DbgPrint("Creating device name: %ws\n", deviceName.Buffer);)
+
+ status = IoCreateDevice(adriverObjectP,
+ sizeof(DEVICE_EXTENSION),
+ &deviceName,
+ FILE_DEVICE_TRANSPORT,
+ 0,
+ FALSE,
+ &devObjP);
+
+ if (NT_SUCCESS(status))
+ {
+ PDEVICE_EXTENSION devExtP = (PDEVICE_EXTENSION)devObjP->DeviceExtension;
+
+ IF_LOUD(DbgPrint("Device created successfully\n"););
+
+ devObjP->Flags |= DO_DIRECT_IO;
+ RtlInitUnicodeString(&devExtP->AdapterName,amacNameP->Buffer);
+ devExtP->NdisProtocolHandle=aProtoHandle;
+
+ IF_LOUD(DbgPrint("Trying to create SymLink %ws\n",deviceSymLink.Buffer););
+
+ if (IoCreateSymbolicLink(&deviceSymLink,&deviceName) != STATUS_SUCCESS)
+ {
+ IF_LOUD(DbgPrint("\n\nError creating SymLink %ws\nn", deviceSymLink.Buffer););
+
+ ExFreePool(deviceName.Buffer);
+ ExFreePool(deviceSymLink.Buffer);
+
+ devExtP->ExportString = NULL;
+
+ return FALSE;
+ }
+
+ IF_LOUD(DbgPrint("SymLink %ws successfully created.\n\n", deviceSymLink.Buffer););
+
+ devExtP->ExportString = deviceSymLink.Buffer;
+
+ ExFreePool(deviceName.Buffer);
+
+ return TRUE;
+ }
+
+ else
+ {
+ IF_LOUD(DbgPrint("\n\nIoCreateDevice status = %x\n", status););
+
+ ExFreePool(deviceName.Buffer);
+ ExFreePool(deviceSymLink.Buffer);
+
+ return FALSE;
+ }
+}
+//-------------------------------------------------------------------
+
+VOID NPF_Unload(IN PDRIVER_OBJECT DriverObject)
+{
+ PDEVICE_OBJECT DeviceObject;
+ PDEVICE_OBJECT OldDeviceObject;
+ PDEVICE_EXTENSION DeviceExtension;
+
+ NDIS_HANDLE NdisProtocolHandle = NULL;
+ NDIS_STATUS Status;
+
+ NDIS_STRING SymLink;
+
+ IF_LOUD(DbgPrint("NPF: Unload\n"););
+
+ DeviceObject = DriverObject->DeviceObject;
+
+ while (DeviceObject != NULL) {
+ OldDeviceObject = DeviceObject;
+
+ DeviceObject = DeviceObject->NextDevice;
+
+ DeviceExtension = OldDeviceObject->DeviceExtension;
+
+ NdisProtocolHandle=DeviceExtension->NdisProtocolHandle;
+
+ IF_LOUD(DbgPrint("Deleting Adapter %ws, Protocol Handle=%x, Device Obj=%x (%x)\n",
+ DeviceExtension->AdapterName.Buffer,
+ NdisProtocolHandle,
+ DeviceObject,
+ OldDeviceObject););
+
+ if (DeviceExtension->ExportString)
+ {
+ RtlInitUnicodeString(&SymLink , DeviceExtension->ExportString);
+
+ IF_LOUD(DbgPrint("Deleting SymLink at %p\n", SymLink.Buffer););
+
+ IoDeleteSymbolicLink(&SymLink);
+ ExFreePool(DeviceExtension->ExportString);
+ }
+
+ IoDeleteDevice(OldDeviceObject);
+ }
+
+ NdisDeregisterProtocol(
+ &Status,
+ NdisProtocolHandle
+ );
+
+ // Free the adapters names
+ ExFreePool( bindP );
+}
+
+#define SET_FAILURE_BUFFER_SMALL() do{\
+ Information = 0; \
+ Status = STATUS_BUFFER_TOO_SMALL; \
+} while(FALSE)
+
+#define SET_RESULT_SUCCESS(__a__) do{\
+ Information = __a__; \
+ Status = STATUS_SUCCESS; \
+} while(FALSE)
+
+#define SET_FAILURE_INVALID_REQUEST() do{\
+ Information = 0; \
+ Status = STATUS_INVALID_DEVICE_REQUEST; \
+} while(FALSE)
+
+#define SET_FAILURE_UNSUCCESSFUL() do{\
+ Information = 0; \
+ Status = STATUS_UNSUCCESSFUL; \
+} while(FALSE)
+
+#define SET_FAILURE_NOMEM() do{\
+ Information = 0; \
+ Status = STATUS_INSUFFICIENT_RESOURCES; \
+} while(FALSE)
+
+
+//-------------------------------------------------------------------
+
+NTSTATUS NPF_IoControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
+{
+ POPEN_INSTANCE Open;
+ PIO_STACK_LOCATION IrpSp;
+ PLIST_ENTRY RequestListEntry;
+ PINTERNAL_REQUEST pRequest;
+ ULONG FunctionCode;
+ NDIS_STATUS Status;
+ UINT i;
+ PUCHAR tpointer;
+ ULONG dim,timeout;
+ PUCHAR prog;
+ PPACKET_OID_DATA OidData;
+ ULONG mode;
+// PWSTR DumpNameBuff;
+ PUCHAR TmpBPFProgram;
+ INT WriteRes;
+ BOOLEAN SyncWrite = FALSE;
+// struct bpf_insn *initprogram;
+ ULONG insns;
+ ULONG cnt;
+ BOOLEAN IsExtendedFilter=FALSE;
+
+ BOOLEAN Flag;
+ PUINT pStats;
+ ULONG Information = 0;
+
+ IF_LOUD(DbgPrint("NPF: IoControl\n");)
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+ FunctionCode=IrpSp->Parameters.DeviceIoControl.IoControlCode;
+ Open=IrpSp->FileObject->FsContext;
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+
+ 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
+
+ if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength < 4*sizeof(UINT)){
+ EXIT_FAILURE(0);
+ }
+
+ pStats = (PUINT)(Irp->UserBuffer);
+
+ pStats[3] = 0;
+ pStats[0] = 0;
+ pStats[1] = 0;
+ pStats[2] = 0; // Not yet supported
+
+ for(i = 0 ; i < NCpu ; i++)
+ {
+
+ pStats[3] += Open->CpuData[i].Accepted;
+ pStats[0] += Open->CpuData[i].Received;
+ pStats[1] += Open->CpuData[i].Dropped;
+ pStats[2] += 0; // Not yet supported
+ }
+ EXIT_SUCCESS(4*sizeof(UINT));
+
+ break;
+
+ case BIOCGEVNAME: //function to get the name of the event associated with the current instance
+
+ if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength<26){
+ EXIT_FAILURE(0);
+ }
+
+ RtlCopyMemory(Irp->UserBuffer,(Open->ReadEventName.Buffer)+18,26);
+
+ EXIT_SUCCESS(26);
+
+ break;
+
+ case BIOCSENDPACKETSSYNC:
+
+ SyncWrite = TRUE;
+
+ case BIOCSENDPACKETSNOSYNC:
+
+ NdisAcquireSpinLock(&Open->WriteLock);
+ if(Open->WriteInProgress)
+ {
+ // Another write operation is currently in progress
+ EXIT_FAILURE(0);
+ }
+ else
+ {
+ Open->WriteInProgress = TRUE;
+ }
+ NdisReleaseSpinLock(&Open->WriteLock);
+
+ WriteRes = NPF_BufferedWrite(Irp,
+ (PUCHAR)Irp->AssociatedIrp.SystemBuffer,
+ IrpSp->Parameters.DeviceIoControl.InputBufferLength,
+ SyncWrite);
+
+ NdisAcquireSpinLock(&Open->WriteLock);
+ Open->WriteInProgress = FALSE;
+ NdisReleaseSpinLock(&Open->WriteLock);
+
+ if( WriteRes != -1)
+ {
+ EXIT_SUCCESS(WriteRes);
+ }
+
+ EXIT_FAILURE(WriteRes);
+
+ break;
+
+ case BIOCSETF:
+
+ Open->SkipProcessing = 1;
+
+ do
+ {
+ Flag = FALSE;
+ for(i = 0; i < NCpu ; i++)
+ if (Open->CpuData[i].Processing == 1)
+ Flag = TRUE;
+ }
+ while(Flag); //BUSY FORM WAITING...
+
+
+ // Free the previous buffer if it was present
+ if(Open->bpfprogram != NULL){
+ TmpBPFProgram = Open->bpfprogram;
+ Open->bpfprogram = NULL;
+ ExFreePool(TmpBPFProgram);
+ }
+
+//
+// Jitted filters are supported on x86 (32bit) only
+//
+#ifdef __NPF_x86__
+ if (Open->Filter != NULL)
+ {
+ JIT_BPF_Filter *OldFilter=Open->Filter;
+ Open->Filter=NULL;
+ BPF_Destroy_JIT_Filter(OldFilter);
+ }
+#endif // __NPF_x86__
+
+ // Get the pointer to the new program
+ prog=(PUCHAR)Irp->AssociatedIrp.SystemBuffer;
+
+ if(prog==NULL)
+ {
+ Open->SkipProcessing = 0;
+ EXIT_FAILURE(0);
+ }
+
+ 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);)
+
+#ifdef __NPF_x86__
+ if ( cnt != insns && insns != cnt+1 && ((struct bpf_insn*)prog)[cnt].code == BPF_SEPARATION )
+ {
+ 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");)
+
+ Open->SkipProcessing = 0;
+ EXIT_FAILURE(0);
+ }
+ }
+#else //x86-64 and IA64
+ if ( cnt != insns)
+ {
+ IF_LOUD(DbgPrint("Error installing the BPF filter. The filter contains TME extensions,"
+ " not supported on 64bit platforms.\n");)
+
+ Open->SkipProcessing = 0;
+ EXIT_FAILURE(0);
+ }
+
+
+#endif
+
+ //the NPF processor has been initialized, we have to validate the operative instructions
+ insns = cnt;
+
+ //NOTE: the validation code checks for TME instructions, and fails if a TME instruction is
+ //encountered on 64 bit machines
+ 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
+ Open->SkipProcessing = 0;
+ 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
+ Open->SkipProcessing = 0;
+ EXIT_FAILURE(0);
+ }
+
+ //copy the program in the new buffer
+ RtlCopyMemory(TmpBPFProgram,prog,cnt*sizeof(struct bpf_insn));
+ Open->bpfprogram=TmpBPFProgram;
+
+ //
+ // At the moment the JIT compiler works on x86 (32 bit) only
+ //
+#ifdef __NPF_x86__
+ // 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");)
+ Open->SkipProcessing = 0;
+ EXIT_FAILURE(0);
+ }
+#endif
+
+ //return
+ for (i = 0 ; i < NCpu ; i++)
+ {
+ Open->CpuData[i].C=0;
+ Open->CpuData[i].P=0;
+ Open->CpuData[i].Free = Open->Size;
+ Open->CpuData[i].Accepted=0;
+ Open->CpuData[i].Dropped=0;
+ Open->CpuData[i].Received = 0;
+ }
+
+ Open->ReaderSN=0;
+ Open->WriterSN=0;
+
+ Open->SkipProcessing = 0;
+ EXIT_SUCCESS(IrpSp->Parameters.DeviceIoControl.InputBufferLength);
+
+ break;
+
+ case BIOCSMODE: //set the capture mode
+
+ if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
+ {
+ EXIT_FAILURE(0);
+ }
+
+ mode=*((PULONG)Irp->AssociatedIrp.SystemBuffer);
+
+///////kernel dump does not work at the moment//////////////////////////////////////////
+ if (mode & MODE_DUMP)
+ {
+ EXIT_FAILURE(0);
+ }
+///////kernel dump does not work at the moment//////////////////////////////////////////
+
+ if(mode == MODE_CAPT)
+ {
+ Open->mode = MODE_CAPT;
+
+ EXIT_SUCCESS(0);
+ }
+ else if (mode == MODE_MON)
+ {
+//
+// The MONITOR_MODE (aka TME extensions) is not supported on
+// 64 bit architectures
+//
+#ifdef __NPF_x86__
+ Open->mode = MODE_MON;
+ EXIT_SUCCESS(0);
+#else // _NPF_x86__
+ EXIT_FAILURE(0);
+#endif // __NPF_x86__
+
+ }
+ else{
+ if(mode & MODE_STAT){
+ Open->mode = MODE_STAT;
+ NdisAcquireSpinLock(&Open->CountersLock);
+ Open->Nbytes.QuadPart = 0;
+ Open->Npackets.QuadPart = 0;
+ NdisReleaseSpinLock(&Open->CountersLock);
+
+ if(Open->TimeOut.QuadPart==0)Open->TimeOut.QuadPart = -10000000;
+
+ }
+
+ if(mode & MODE_DUMP){
+
+ Open->mode |= MODE_DUMP;
+// Open->MinToCopy=(Open->BufSize<2000000)?Open->BufSize/2:1000000;
+
+ }
+ EXIT_SUCCESS(0);
+ }
+
+ EXIT_FAILURE(0);
+
+ break;
+
+ case BIOCSETDUMPFILENAME:
+
+///////kernel dump does not work at the moment//////////////////////////////////////////
+ EXIT_FAILURE(0);
+///////kernel dump does not work at the moment//////////////////////////////////////////
+
+//
+// Remove the following #if 0 to enable the kernel dump again
+//
+#if 0
+ if(Open->mode & MODE_DUMP)
+ {
+
+ // Close current dump file
+ if(Open->DumpFileHandle != NULL)
+ {
+ NPF_CloseDumpFile(Open);
+ Open->DumpFileHandle = NULL;
+ }
+
+ if(IrpSp->Parameters.DeviceIoControl.InputBufferLength == 0){
+ EXIT_FAILURE(0);
+ }
+
+ // Allocate the buffer that will contain the string
+ DumpNameBuff=ExAllocatePoolWithTag(NonPagedPool, IrpSp->Parameters.DeviceIoControl.InputBufferLength, '5PWA');
+ if(DumpNameBuff==NULL || Open->DumpFileName.Buffer!=NULL){
+ IF_LOUD(DbgPrint("NPF: unable to allocate the dump filename: not enough memory or name already set\n");)
+ EXIT_FAILURE(0);
+ }
+
+ // Copy the buffer
+ RtlCopyBytes((PVOID)DumpNameBuff,
+ Irp->AssociatedIrp.SystemBuffer,
+ IrpSp->Parameters.DeviceIoControl.InputBufferLength);
+
+ // Force a \0 at the end of the filename to avoid that malformed strings cause RtlInitUnicodeString to crash the system
+ ((PSHORT)DumpNameBuff)[IrpSp->Parameters.DeviceIoControl.InputBufferLength/2-1]=0;
+
+ // Create the unicode string
+ RtlInitUnicodeString(&Open->DumpFileName, DumpNameBuff);
+
+ IF_LOUD(DbgPrint("NPF: dump file name set to %ws, len=%d\n",
+ Open->DumpFileName.Buffer,
+ IrpSp->Parameters.DeviceIoControl.InputBufferLength);)
+
+ // Try to create the file
+ if ( NT_SUCCESS( NPF_OpenDumpFile(Open,&Open->DumpFileName,FALSE)) &&
+ NT_SUCCESS( NPF_StartDump(Open)))
+ {
+ EXIT_SUCCESS(0);
+ }
+ }
+
+ EXIT_FAILURE(0);
+
+ break;
+#endif // #if 0
+ case BIOCSETDUMPLIMITS:
+
+///////kernel dump does not work at the moment//////////////////////////////////////////
+ EXIT_FAILURE(0);
+///////kernel dump does not work at the moment//////////////////////////////////////////
+
+//
+// Remove the following #if 0 to enable the kernel dump again
+//
+#if 0
+ if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < 2*sizeof(ULONG))
+ {
+ EXIT_FAILURE(0);
+ }
+
+ Open->MaxDumpBytes = *(PULONG)Irp->AssociatedIrp.SystemBuffer;
+ Open->MaxDumpPacks = *((PULONG)Irp->AssociatedIrp.SystemBuffer + 1);
+
+ IF_LOUD(DbgPrint("NPF: Set dump limits to %u bytes, %u packs\n", Open->MaxDumpBytes, Open->MaxDumpPacks);)
+
+ EXIT_SUCCESS(0);
+
+ break;
+
+#endif // #if 0
+
+ case BIOCISDUMPENDED:
+
+///////kernel dump does not work at the moment//////////////////////////////////////////
+ EXIT_FAILURE(0);
+///////kernel dump does not work at the moment//////////////////////////////////////////
+
+//
+// Remove the following #if 0 to enable the kernel dump again
+//
+#if 0
+ if(IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(UINT))
+ {
+ EXIT_FAILURE(0);
+ }
+
+ *((UINT*)Irp->UserBuffer) = (Open->DumpLimitReached)?1:0;
+
+ EXIT_SUCCESS(4);
+
+ break;
+
+#endif // #if 0
+
+ case BIOCSETBUFFERSIZE:
+
+
+ if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
+ {
+ EXIT_FAILURE(0);
+ }
+
+ // Get the number of bytes to allocate
+ dim = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
+
+ Open->SkipProcessing = 1;
+
+ do
+ {
+ Flag = FALSE;
+ for(i=0;i<NCpu;i++)
+ if (Open->CpuData[i].Processing == 1)
+ Flag = TRUE;
+ }
+ while(Flag); //BUSY FORM WAITING...
+
+ if (dim / NCpu < sizeof(struct PacketHeader))
+ dim = 0;
+ else
+ {
+ tpointer = ExAllocatePoolWithTag(NonPagedPool, dim, '6PWA');
+ if (tpointer==NULL)
+ {
+ // no memory
+ Open->SkipProcessing = 0;
+ EXIT_FAILURE(0);
+ }
+ }
+
+ if (Open->CpuData[0].Buffer != NULL)
+ ExFreePool(Open->CpuData[0].Buffer);
+
+ for (i = 0 ; i < NCpu ; i++)
+ {
+ if (dim > 0)
+ Open->CpuData[i].Buffer=(PUCHAR)tpointer + (dim/NCpu)*i;
+ else
+ Open->CpuData[i].Buffer = NULL;
+ Open->CpuData[i].Free = dim/NCpu;
+ Open->CpuData[i].P = 0;
+ Open->CpuData[i].C = 0;
+ Open->CpuData[i].Accepted = 0;
+ Open->CpuData[i].Dropped = 0;
+ Open->CpuData[i].Received = 0;
+ }
+
+ Open->ReaderSN=0;
+ Open->WriterSN=0;
+
+ Open->Size = dim/NCpu;
+
+ Open->SkipProcessing = 0;
+ EXIT_SUCCESS(dim);
+
+ break;
+
+ case BIOCSRTIMEOUT: //set the timeout on the read calls
+
+
+ if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
+ {
+ EXIT_FAILURE(0);
+ }
+
+ timeout = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
+ if(timeout == (ULONG)-1)
+ Open->TimeOut.QuadPart=(LONGLONG)IMMEDIATE;
+ else
+ {
+ Open->TimeOut.QuadPart = (LONGLONG)timeout;
+ Open->TimeOut.QuadPart *= 10000;
+ Open->TimeOut.QuadPart = -Open->TimeOut.QuadPart;
+ }
+
+ 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
+
+ if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
+ {
+ EXIT_FAILURE(0);
+ }
+
+ Open->Nwrites = *((PULONG)Irp->AssociatedIrp.SystemBuffer);
+
+ EXIT_SUCCESS(Open->Nwrites);
+
+ break;
+
+ case BIOCSMINTOCOPY: //set the minimum buffer's size to copy to the application
+
+ if(IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG))
+ {
+ EXIT_FAILURE(0);
+ }
+
+ Open->MinToCopy = (*((PULONG)Irp->AssociatedIrp.SystemBuffer))/NCpu; //An hack to make the NCPU-buffers behave like a larger one
+
+ EXIT_SUCCESS(Open->MinToCopy);
+
+ break;
+
+ case IOCTL_PROTOCOL_RESET:
+
+ 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("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;
+ pRequest->Internal = FALSE;
+
+
+ //
+ // See if it is an Ndis request
+ //
+ OidData=Irp->AssociatedIrp.SystemBuffer;
+
+ if (((FunctionCode == BIOCSETOID) || (FunctionCode == BIOCQUERYOID))
+ &&
+ (IrpSp->Parameters.DeviceIoControl.InputBufferLength == IrpSp->Parameters.DeviceIoControl.OutputBufferLength)
+ &&
+ (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA))
+ &&
+ (IrpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA)-1+OidData->Length)) {
+
+ 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
+ //
+ NdisRequest(
+ &Status,
+ Open->AdapterHandle,
+ &pRequest->Request
+ );
+
+ } else {
+ //
+ // buffer too small
+ //
+ 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("NPF: Calling RequestCompleteHandler\n");)
+
+ NPF_RequestComplete(Open, &pRequest->Request, Status);
+ return Status;
+
+ }
+
+ NdisWaitEvent(&Open->IOEvent, 5000);
+
+ return(Open->IOStatus);
+
+ break;
+
+ case BIOCISETLOBBEH:
+
+ if (IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(INT))
+ {
+ SET_FAILURE_BUFFER_SMALL();
+ break;
+ }
+
+#ifdef __NPF_NT4__
+
+ // NT4 doesn't support loopback inhibition / activation
+ SET_FAILURE_INVALID_REQUEST();
+ break;
+
+#else //not __NPF_NT4__
+ //
+ // win2000/xp/2003/vista
+ //
+ if(*(PINT)Irp->AssociatedIrp.SystemBuffer == 1)
+ {
+ Open->SkipSentPackets = TRUE;
+
+ //
+ // Reset the capture buffers, since they could contain loopbacked packets
+ //
+
+// NPF_ResetBufferContents(Open);
+
+ SET_RESULT_SUCCESS(0);
+ break;
+
+ }
+ else
+ if(*(PINT)Irp->AssociatedIrp.SystemBuffer == 2)
+ {
+ Open->SkipSentPackets = FALSE;
+
+ SET_RESULT_SUCCESS(0);
+ break;
+ }
+ else
+ {
+ // Unknown operation
+ SET_FAILURE_INVALID_REQUEST();
+ break;
+ }
+
+#endif // !__NPF_NT4__
+ break;
+
+
+
+ default:
+
+ EXIT_FAILURE(0);
+ }
+
+ if (FunctionCode == BIOCISETLOBBEH)
+ {
+ Irp->IoStatus.Information = Information;
+ Irp->IoStatus.Status = Status;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ }
+
+ return Status;
+}
+
+//-------------------------------------------------------------------
+
+VOID
+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;
+ UINT FunctionCode;
+// KIRQL OldIrq;
+
+ PPACKET_OID_DATA OidData;
+
+ IF_LOUD(DbgPrint("NPF: RequestComplete\n");)
+
+ Open= (POPEN_INSTANCE)ProtocolBindingContext;
+
+ pRequest=CONTAINING_RECORD(NdisRequest,INTERNAL_REQUEST,Request);
+ Irp=pRequest->Irp;
+
+ if(pRequest->Internal == TRUE){
+
+ // Put the request in the list of the free ones
+ ExInterlockedInsertTailList(&Open->RequestList, &pRequest->ListElement, &Open->RequestSpinLock);
+
+ if(Status != NDIS_STATUS_SUCCESS)
+ Open->MaxFrameSize = 1560; // Assume Ethernet
+
+ // We always return success, because the adapter has been already opened
+ Irp->IoStatus.Status = NDIS_STATUS_SUCCESS;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ 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);)
+
+ ExInterlockedInsertTailList(
+ &Open->RequestList,
+ &pRequest->ListElement,
+ &Open->RequestSpinLock);
+
+ Irp->IoStatus.Status = Status;
+
+ Open->IOStatus = Status;
+
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ // Unlock the caller
+ NdisSetEvent(&Open->IOEvent);
+
+ return;
+
+
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_Status(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status,
+ IN PVOID StatusBuffer,
+ IN UINT StatusBufferSize
+ )
+
+{
+
+ IF_LOUD(DbgPrint("NPF: Status Indication\n");)
+
+ return;
+
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_StatusComplete(
+ IN NDIS_HANDLE ProtocolBindingContext
+ )
+
+{
+
+ IF_LOUD(DbgPrint("NPF: StatusIndicationComplete\n");)
+
+ return;
+
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS
+NPF_ReadRegistry(
+ IN PWSTR *MacDriverName,
+ IN PWSTR *PacketDriverName,
+ IN PUNICODE_STRING RegistryPath
+ )
+
+{
+ NTSTATUS Status;
+
+ RTL_QUERY_REGISTRY_TABLE ParamTable[4];
+
+ PWSTR Bind = L"Bind";
+ PWSTR Export = L"Export";
+ PWSTR Parameters = L"Parameters";
+ PWSTR Linkage = L"Linkage";
+
+ PWCHAR Path;
+
+
+
+ Path=ExAllocatePoolWithTag(PagedPool, RegistryPath->Length+sizeof(WCHAR), '7PWA');
+
+ if (Path == NULL) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlZeroMemory(
+ Path,
+ RegistryPath->Length+sizeof(WCHAR)
+ );
+
+ RtlCopyMemory(
+ Path,
+ RegistryPath->Buffer,
+ RegistryPath->Length
+ );
+
+ IF_LOUD(DbgPrint("NPF: Reg path is %ws\n",RegistryPath->Buffer);)
+
+ RtlZeroMemory(
+ ParamTable,
+ sizeof(ParamTable)
+ );
+
+
+
+ //
+ // change to the linkage key
+ //
+
+ ParamTable[0].QueryRoutine = NULL;
+ ParamTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
+ ParamTable[0].Name = Linkage;
+
+
+ //
+ // Get the name of the mac driver we should bind to
+ //
+
+ ParamTable[1].QueryRoutine = NPF_QueryRegistryRoutine;
+ ParamTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED |
+ RTL_QUERY_REGISTRY_NOEXPAND;
+
+ ParamTable[1].Name = Bind;
+ ParamTable[1].EntryContext = (PVOID)MacDriverName;
+ ParamTable[1].DefaultType = REG_MULTI_SZ;
+
+ //
+ // Get the name that we should use for the driver object
+ //
+
+ ParamTable[2].QueryRoutine = NPF_QueryRegistryRoutine;
+ ParamTable[2].Flags = RTL_QUERY_REGISTRY_REQUIRED |
+ RTL_QUERY_REGISTRY_NOEXPAND;
+
+ ParamTable[2].Name = Export;
+ ParamTable[2].EntryContext = (PVOID)PacketDriverName;
+ ParamTable[2].DefaultType = REG_MULTI_SZ;
+
+
+ Status=RtlQueryRegistryValues(
+ RTL_REGISTRY_ABSOLUTE,
+ Path,
+ ParamTable,
+ NULL,
+ NULL
+ );
+
+
+ ExFreePool(Path);
+
+ return Status;
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS
+NPF_QueryRegistryRoutine(
+ IN PWSTR ValueName,
+ IN ULONG ValueType,
+ IN PVOID ValueData,
+ IN ULONG ValueLength,
+ IN PVOID Context,
+ IN PVOID EntryContext
+ )
+
+{
+
+ PUCHAR Buffer;
+
+ IF_LOUD(DbgPrint("Perf: QueryRegistryRoutine\n");)
+
+ if (ValueType != REG_MULTI_SZ) {
+
+ return STATUS_OBJECT_NAME_NOT_FOUND;
+
+ }
+
+ Buffer=ExAllocatePoolWithTag(NonPagedPool, ValueLength, '8PWA');
+
+ if (Buffer==NULL) {
+
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ }
+
+ RtlCopyMemory(
+ Buffer,
+ ValueData,
+ ValueLength
+ );
+
+ *((PUCHAR *)EntryContext)=Buffer;
+
+ return STATUS_SUCCESS;
+
+}
diff --git a/src/See/Packet.h b/src/See/Packet.h
new file mode 100644
index 00000000..f75ed1d9
--- /dev/null
+++ b/src/See/Packet.h
@@ -0,0 +1,954 @@
+/*
+ * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies
+ * nor the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/** @ingroup NPF
+ * @{
+ */
+
+/** @defgroup NPF_include NPF structures and definitions
+ * @{
+ */
+
+#ifndef __PACKET_INCLUDE______
+#define __PACKET_INCLUDE______
+
+#ifdef __NPF_x86__
+#define NTKERNEL ///< Forces the compilation of the jitter with kernel calls
+#include "jitter.h"
+#endif
+
+
+#include "win_bpf.h"
+
+#define MAX_REQUESTS 256 ///< Maximum number of simultaneous IOCTL requests.
+
+#define Packet_ALIGNMENT sizeof(int) ///< Alignment macro. Defines the alignment size.
+#define Packet_WORDALIGN(x) (((x)+(Packet_ALIGNMENT-1))&~(Packet_ALIGNMENT-1)) ///< Alignment macro. Rounds up to the next
+ ///< even multiple of Packet_ALIGNMENT.
+/***************************/
+/* IOCTLs */
+/***************************/
+
+/*!
+ \brief IOCTL code: set kernel buffer size.
+
+ This IOCTL is used to set a new size of the circular buffer associated with an instance of NPF.
+ When a BIOCSETBUFFERSIZE command is received, the driver frees the old buffer, allocates the new one
+ and resets all the parameters associated with the buffer in the OPEN_INSTANCE structure. The currently
+ buffered packets are lost.
+*/
+#define BIOCSETBUFFERSIZE 9592
+
+/*!
+ \brief IOCTL code: set packet filtering program.
+
+ This IOCTL sets a new packet filter in the driver. Before allocating any memory for the new filter, the
+ bpf_validate() function is called to check the correctness of the filter. If this function returns TRUE,
+ the filter is copied to the driver's memory, its address is stored in the bpfprogram field of the
+ OPEN_INSTANCE structure associated with current instance of the driver, and the filter will be applied to
+ every incoming packet. This command also empties the circular buffer used by current instance
+ to store packets. This is done to avoid the presence in the buffer of packets that do not match the filter.
+*/
+#define BIOCSETF 9030
+
+/*!
+ \brief IOCTL code: get the capture stats
+
+ This command returns to the application the number of packets received and the number of packets dropped by
+ an instance of the driver.
+*/
+#define BIOCGSTATS 9031
+
+/*!
+ \brief IOCTL code: set the read timeout
+
+ This command sets the maximum timeout after which a read is released, also if no data packets were received.
+*/
+#define BIOCSRTIMEOUT 7416
+
+/*!
+ \brief IOCTL code: set working mode
+
+ This IOCTL can be used to set the working mode of a NPF instance. The new mode, received by the driver in the
+ buffer associated with the IOCTL command, can be #MODE_CAPT for capture mode (the default), #MODE_STAT for
+ statistical mode or #MODE_DUMP for dump mode.
+*/
+#define BIOCSMODE 7412
+
+/*!
+ \brief IOCTL code: set number of physical repetions of every packet written by the app
+
+ Sets the number of times a single write call must be repeated. This command sets the OPEN_INSTANCE::Nwrites
+ member, and is used to implement the 'multiple write' feature of the driver.
+*/
+#define BIOCSWRITEREP 7413
+
+/*!
+ \brief IOCTL code: set minimum amount of data in the kernel buffer that unlocks a read call
+
+ This command sets the OPEN_INSTANCE::MinToCopy member.
+*/
+#define BIOCSMINTOCOPY 7414
+
+/*!
+ \brief IOCTL code: set an OID value
+
+ This IOCTL is used to perform an OID set operation on the NIC driver.
+*/
+#define BIOCSETOID 2147483648
+
+/*!
+ \brief IOCTL code: get an OID value
+
+ This IOCTL is used to perform an OID get operation on the NIC driver.
+*/
+#define BIOCQUERYOID 2147483652
+#define BIOCISETLOBBEH 7410
+/*!
+ \brief IOCTL code: set the name of a the file used by kernel dump mode
+
+ This command opens a file whose name is contained in the IOCTL buffer and associates it with current NPf instance.
+ The dump thread uses it to copy the content of the circular buffer to file.
+ If a file was already opened, the driver closes it before opening the new one.
+*/
+#define BIOCSETDUMPFILENAME 9029
+
+/*!
+ \brief IOCTL code: get the name of the event that the driver signals when some data is present in the buffer
+
+ Command used by the application to retrieve the name of the global event associated with a NPF instance.
+ The event is signaled by the driver when the kernel buffer contains enough data for a transfer.
+*/
+#define BIOCGEVNAME 7415
+
+/*!
+ \brief IOCTL code: Send a buffer containing multiple packets to the network, ignoring the timestamps.
+
+ Command used to send a buffer of packets in a single system call. Every packet in the buffer is preceded by
+ a sf_pkthdr structure. The timestamps of the packets are ignored, i.e. the packets are sent as fast as
+ possible. The NPF_BufferedWrite() function is invoked to send the packets.
+*/
+#define BIOCSENDPACKETSNOSYNC 9032
+
+/*!
+ \brief IOCTL code: Send a buffer containing multiple packets to the network, considering the timestamps.
+
+ Command used to send a buffer of packets in a single system call. Every packet in the buffer is preceded by
+ a sf_pkthdr structure. The timestamps of the packets are used to synchronize the write, i.e. the packets
+ are sent to the network respecting the intervals specified in the sf_pkthdr structure assiciated with each
+ packet. NPF_BufferedWrite() function is invoked to send the packets.
+*/
+#define BIOCSENDPACKETSSYNC 9033
+
+/*!
+ \brief IOCTL code: Set the dump file limits.
+
+ This IOCTL sets the limits (maximum size and maximum number of packets) of the dump file created when the
+ driver works in dump mode.
+*/
+#define BIOCSETDUMPLIMITS 9034
+
+/*!
+ \brief IOCTL code: Get the status of the kernel dump process.
+
+ This command returns TRUE if the kernel dump is ended, i.e if one of the limits set with BIOCSETDUMPLIMITS
+ (amount of bytes or number of packets) has been reached.
+*/
+#define BIOCISDUMPENDED 7411
+
+// 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
+ BOOLEAN Internal; ///< True if the request is for internal use of npf.sys. False if the request is performed by the user through an IOCTL.
+ NDIS_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; ///< Used to handle lists of packets.
+ PIRP Irp; ///< Irp that performed the request
+ PMDL pMdl; ///< MDL mapping the buffer of the packet.
+ BOOLEAN FreeBufAfterWrite; ///< True if the memory buffer associated with the packet must be freed
+ ///< after a call to NdisSend().
+ ULONG Cpu; ///< The CPU on which the packet was pulled out of the linked list of free packets
+} PACKET_RESERVED, *PPACKET_RESERVED;
+
+#define RESERVED(_p) ((PPACKET_RESERVED)((_p)->ProtocolReserved)) ///< Macro to obtain a NDIS_PACKET from a PACKET_RESERVED
+
+/*!
+ \brief Port device extension.
+
+ Structure containing some data relative to every adapter on which NPF is bound.
+*/
+typedef struct _DEVICE_EXTENSION {
+ NDIS_HANDLE NdisProtocolHandle; ///< NDIS handle of NPF.
+ NDIS_STRING AdapterName; ///< Name of the adapter.
+ PWSTR ExportString; ///< Name of the exported device, i.e. name that the applications will use
+ ///< to open this adapter through WinPcap.
+} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
+
+/*!
+ \brief Kernel buffer of each CPU.
+
+ Structure containing the kernel buffer (and other CPU related fields) used to capture packets.
+*/
+typedef struct __CPU_Private_Data
+{
+ ULONG P; ///< Zero-based index of the producer in the buffer. It indicates the first free byte to be written.
+ ULONG C; ///< Zero-based index of the consumer in the buffer. It indicates the first free byte to be read.
+ ULONG Free; ///< Number of the free bytes in the buffer
+ PUCHAR Buffer; ///< Pointer to the kernel buffer used to capture packets.
+ ULONG Accepted; ///< Number of packet that current capture instance acepted, from its opening. A packet
+ ///< is accepted if it passes the filter and fits in the buffer. Accepted packets are the
+ ///< ones that reach the application.
+ ///< This number is related to the particular CPU this structure is referring to.
+ ULONG Received; ///< Number of packets received by current instance from its opening, i.e. number of
+ ///< packet received by the network adapter since the beginning of the
+ ///< capture/monitoring/dump session.
+ ///< This number is related to the particular CPU this structure is referring to.
+ ULONG Dropped; ///< Number of packet that current instance had to drop, from its opening. A packet
+ ///< is dropped if there is no more space to store it in the circular buffer that the
+ ///< driver associates to current instance.
+ ///< This number is related to the particular CPU this structure is referring to.
+ ULONG Processing; ///< Flag. If set to 1, it indicates that the tap is processing a packet on the CPU this structure is referring to.
+ PMDL TransferMdl1; ///< MDL used to map the portion of the buffer that will contain an incoming packet.
+ PMDL TransferMdl2; ///< Second MDL used to map the portion of the buffer that will contain an incoming packet.
+ ULONG NewP; ///< Used by NdisTransferData() (when we call NdisTransferData, p index must be updated only in the TransferDataComplete.
+}
+ CpuPrivateData;
+
+
+/*!
+ \brief Contains the state of a running instance of the NPF driver.
+
+ This is the most important structure of NPF: it is used by almost all the functions of the driver. An
+ _OPEN_INSTANCE structure is associated with every user-level session, allowing concurrent access
+ to the driver.
+*/
+typedef struct _OPEN_INSTANCE
+{
+ PDEVICE_EXTENSION DeviceExtension; ///< Pointer to the _DEVICE_EXTENSION structure of the device on which
+ ///< the instance is bound.
+ NDIS_HANDLE AdapterHandle; ///< NDIS idetifier of the adapter used by this instance.
+ UINT Medium; ///< Type of physical medium the underlying NDIS driver uses. See the
+ ///< documentation of NdisOpenAdapter in the MS DDK for details.
+ NDIS_HANDLE PacketPool; ///< Pool of NDIS_PACKET structures used to transfer the packets from and to the NIC driver.
+ 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.
+ PUCHAR bpfprogram; ///< Pointer to the filtering pseudo-code associated with current instance of the driver.
+ ///< This code is used only in particular situations (for example when the packet received
+ ///< from the NIC driver is stored in two non-consecutive buffers. In normal situations
+ ///< the filtering routine created by the JIT compiler and pointed by the next field
+ ///< is used. See \ref NPF for details on the filtering process.
+#ifdef __NPF_x86__
+ JIT_BPF_Filter *Filter; ///< Pointer to the native filtering function created by the jitter.
+ ///< See BPF_jitter() for details.
+#endif
+ UINT MinToCopy; ///< Minimum amount of data in the circular buffer that unlocks a read. Set with the
+ ///< BIOCSMINTOCOPY IOCTL.
+ LARGE_INTEGER TimeOut; ///< Timeout after which a read is released, also if the amount of data in the buffer is
+ ///< less than MinToCopy. Set with the BIOCSRTIMEOUT IOCTL.
+
+ int mode; ///< Working mode of the driver. See PacketSetMode() for details.
+ LARGE_INTEGER Nbytes; ///< Amount of bytes accepted by the filter when this instance is in statistical mode.
+ LARGE_INTEGER Npackets; ///< Number of packets accepted by the filter when this instance is in statistical mode.
+ NDIS_SPIN_LOCK CountersLock; ///< SpinLock that protects the statistical mode counters.
+ UINT Nwrites; ///< Number of times a single write must be physically repeated. See \ref NPF for an
+ ///< explanation
+ ULONG Multiple_Write_Counter; ///< Counts the number of times a single write has already physically repeated.
+ NDIS_EVENT WriteEvent; ///< Event used to synchronize the multiple write process.
+ BOOLEAN WriteInProgress; ///< True if a write is currently in progress. NPF currently allows a single wite on
+ ///< the same open instance.
+ NDIS_SPIN_LOCK WriteLock; ///< SpinLock that protects the WriteInProgress variable.
+ NDIS_EVENT 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 MachineLock; ///< SpinLock that protects the mem_ex buffer
+ UINT MaxFrameSize; ///< Maximum frame size that the underlying MAC acceptes. Used to perform a check on the
+ ///< size of the frames sent with NPF_Write() or NPF_BufferedWrite().
+ CpuPrivateData CpuData[1024]; ///< Pool of kernel buffer structures, one for each CPU.
+ ULONG ReaderSN; ///< Sequence number of the next packet to be read from the pool of kernel buffers.
+ ULONG WriterSN; ///< Sequence number of the next packet to be written in the pool of kernel buffers.
+ ///< These two sequence numbers are unique for each capture instance.
+ ULONG Size; ///< Size of each kernel buffer contained in the CpuData field.
+ ULONG SkipProcessing; ///< Flag. When set to 1, the tap discards each packet. It is set to 1 by the IOCTLs that modify
+ ///< some "sensible" fields of the Open structure (e.g. they reallocate the pool of kernel buffers,
+ ///< or change the filter program
+ BOOLEAN SkipSentPackets;
+
+}
+OPEN_INSTANCE, *POPEN_INSTANCE;
+
+/*!
+ \brief Structure prepended to each packet in the kernel buffer pool.
+
+ Each packet in one of the kernel buffers is prepended by this header. It encapsulates the bpf_header,
+ which will be passed to user level programs, as well as the sequence number of the packet, set by the producer (the tap function),
+ and used by the consumer (the read function) to "reorder" the packets contained in the various kernel buffers.
+*/
+struct PacketHeader
+{
+ ULONG SN; ///< Sequence number of the packet.
+ struct bpf_hdr header; ///< bpf header, created by the tap, and copied unmodified to user level programs.
+};
+
+extern UINT g_SendPacketFlags;
+#define NDIS_FLAGS_SKIP_LOOPBACK_W2K 0x400 ///< This is an undocumented flag for NdisSetPacketFlags() that allows to disable loopback reception.
+
+#define TRANSMIT_PACKETS 2048 ///< Maximum number of packets in the transmit packet pool. This value is an upper bound to the number
+ ///< of packets that can be transmitted at the same time or with a single call to NdisSendPackets.
+
+
+/// Macro used in the I/O routines to return the control to user-mode with a success status.
+#define EXIT_SUCCESS(quantity) Irp->IoStatus.Information=quantity;\
+ Irp->IoStatus.Status = STATUS_SUCCESS;\
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);\
+ return STATUS_SUCCESS;\
+
+/// Macro used in the I/O routines to return the control to user-mode with a failure status.
+#define EXIT_FAILURE(quantity) Irp->IoStatus.Information=quantity;\
+ Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;\
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);\
+ return STATUS_UNSUCCESSFUL;\
+
+/**
+ * @}
+ */
+
+
+/***************************/
+/* Prototypes */
+/***************************/
+
+/** @defgroup NPF_code NPF functions
+ * @{
+ */
+
+
+/*!
+ \brief The initialization routine of the driver.
+ \param DriverObject The driver object of NPF created by the system.
+ \param RegistryPath The registry path containing the keys related to the driver.
+ \return A string containing a list of network adapters.
+
+ DriverEntry is a mandatory function in a device driver. Like the main() of a user level program, it is called
+ by the system when the driver is loaded in memory and started. Its purpose is to initialize the driver,
+ performing all the allocations and the setup. In particular, DriverEntry registers all the driver's I/O
+ callbacks, creates the devices, defines NPF as a protocol inside NDIS.
+*/
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ );
+
+/*!
+ \brief Returns the list of the MACs available on the system.
+ \return A string containing a list of network adapters.
+
+ The list of adapters is retrieved from the
+ SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318} registry key.
+ NPF tries to create its bindings from this list. In this way it is possible to be loaded
+ and unloaded dynamically without passing from the control panel.
+*/
+PWCHAR getAdaptersList(VOID);
+
+/*!
+ \brief Returns the MACs that bind to TCP/IP.
+ \return Pointer to the registry key containing the list of adapters on which TCP/IP is bound.
+
+ If getAdaptersList() fails, NPF tries to obtain the TCP/IP bindings through this function.
+*/
+PKEY_VALUE_PARTIAL_INFORMATION getTcpBindings(VOID);
+
+/*!
+ \brief Creates a device for a given MAC.
+ \param adriverObjectP The driver object that will be associated with the device, i.e. the one of NPF.
+ \param amacNameP The name of the network interface that the device will point.
+ \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
+ );
+
+/*!
+ \brief Ends the opening of an adapter.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+ \param Status Status of the opening operation performed by NDIS.
+ \param OpenErrorStatus not used by NPF.
+
+ Callback function associated with the NdisOpenAdapter() NDIS function. It is invoked by NDIS when the NIC
+ driver has finished an open operation that was previously started by NPF_Open().
+*/
+VOID
+NPF_OpenAdapterComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status,
+ IN NDIS_STATUS OpenErrorStatus
+ );
+
+/*!
+ \brief Closes an instance of the driver.
+ \param DeviceObject Pointer to the device object utilized by the user.
+ \param Irp Pointer to the IRP containing the user request.
+ \return The status of the operation. See ntstatus.h in the DDK.
+
+ This function is called when a running instance of the driver is closed by the user with a CloseHandle().
+ It stops the capture/monitoring/dump process, deallocates the memory and the objects associated with the
+ instance and closing the files. The network adapter is then closed with a call to NdisCloseAdapter.
+*/
+NTSTATUS
+NPF_Close(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ );
+
+/*!
+ \brief Ends the closing of an adapter.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+ \param Status Status of the close operation performed by NDIS.
+
+ Callback function associated with the NdisCloseAdapter() NDIS function. It is invoked by NDIS when the NIC
+ driver has finished a close operation that was previously started by NPF_Close().
+*/
+VOID
+NPF_CloseAdapterComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status
+ );
+
+/*!
+ \brief Callback invoked by NDIS when a packet arrives from the network.
+ \param ProtocolBindingContext Context of the function. Points to a OPEN_INSTANCE structure that identifies
+ the NPF instance to which the packets are destined.
+ \param MacReceiveContext Handle that identifies the underlying NIC driver that generated the request.
+ This value must be used when the packet is transferred from the NIC driver with NdisTransferData().
+ \param HeaderBuffer Pointer to the buffer in the NIC driver memory that contains the header of the packet.
+ \param HeaderBufferSize Size in bytes of the header.
+ \param LookAheadBuffer Pointer to the buffer in the NIC driver's memory that contains the incoming packet's
+ data <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
+NPF_tap(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_HANDLE MacReceiveContext,
+ IN PVOID HeaderBuffer,
+ IN UINT HeaderBufferSize,
+ IN PVOID LookAheadBuffer,
+ IN UINT LookaheadBufferSize,
+ IN UINT PacketSize
+ );
+
+/*!
+ \brief Ends the transfer of a packet.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+ \param Packet Pointer to the NDIS_PACKET structure that received the packet data.
+ \param Status Status of the transfer operation.
+ \param BytesTransferred Amount of bytes transferred.
+
+ Callback function associated with the NdisTransferData() NDIS function. It is invoked by NDIS when the NIC
+ driver has finished the transfer of a packet from the NIC driver memory to the NPF circular buffer.
+*/
+VOID
+NPF_TransferDataComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN PNDIS_PACKET Packet,
+ IN NDIS_STATUS Status,
+ IN UINT BytesTransferred
+ );
+
+/*!
+ \brief Callback function that signals the end of a packet reception.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+
+ does nothing in NPF
+*/
+VOID
+NPF_ReceiveComplete(IN NDIS_HANDLE ProtocolBindingContext);
+
+/*!
+ \brief Handles the IOCTL calls.
+ \param DeviceObject Pointer to the device object utilized by the user.
+ \param Irp Pointer to the IRP containing the user request.
+ \return The status of the operation. See ntstatus.h in the DDK.
+
+ Once the packet capture driver is opened it can be configured from user-level applications with IOCTL commands
+ using the DeviceIoControl() system call. NPF_IoControl receives and serves all the IOCTL calls directed to NPF.
+ The following commands are recognized:
+ - #BIOCSETBUFFERSIZE
+ - #BIOCSETF
+ - #BIOCGSTATS
+ - #BIOCSRTIMEOUT
+ - #BIOCSMODE
+ - #BIOCSWRITEREP
+ - #BIOCSMINTOCOPY
+ - #BIOCSETOID
+ - #BIOCQUERYOID
+ - #BIOCSETDUMPFILENAME
+ - #BIOCGEVNAME
+ - #BIOCSENDPACKETSSYNC
+ - #BIOCSENDPACKETSNOSYNC
+*/
+NTSTATUS
+NPF_IoControl(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ );
+
+VOID
+
+/*!
+ \brief Ends an OID request.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+ \param pRequest Pointer to the completed OID request.
+ \param Status Status of the operation.
+
+ Callback function associated with the NdisRequest() NDIS function. It is invoked by NDIS when the NIC
+ driver has finished an OID request operation that was previously started by NPF_IoControl().
+*/
+NPF_RequestComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN PNDIS_REQUEST pRequest,
+ IN NDIS_STATUS Status
+ );
+
+/*!
+ \brief Writes a raw packet to the network.
+ \param DeviceObject Pointer to the device object on which the user wrote the packet.
+ \param Irp Pointer to the IRP containing the user request.
+ \return The status of the operation. See ntstatus.h in the DDK.
+
+ This function is called by the OS in consequence of user WriteFile() call, with the data of the packet that must
+ be sent on the net. The data is contained in the buffer associated with Irp, NPF_Write takes it and
+ delivers it to the NIC driver via the NdisSend() function. The Nwrites field of the OPEN_INSTANCE structure
+ associated with Irp indicates the number of copies of the packet that will be sent: more than one copy of the
+ packet can be sent for performance reasons.
+*/
+NTSTATUS
+NPF_Write(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ );
+
+
+/*!
+ \brief Writes a buffer of raw packets to the network.
+ \param Irp Pointer to the IRP containing the user request.
+ \param UserBuff Pointer to the buffer containing the packets to send.
+ \param UserBuffSize Size of the buffer with the packets.
+ \return The amount of bytes actually sent. If the return value is smaller than the Size parameter, an
+ error occurred during the send. The error can be caused by an adapter problem or by an
+ inconsistent/bogus user buffer.
+
+ This function is called by the OS in consequence of a BIOCSENDPACKETSNOSYNC or a BIOCSENDPACKETSSYNC IOCTL.
+ The buffer received as input parameter contains an arbitrary number of packets, each of which preceded by a
+ sf_pkthdr structure. NPF_BufferedWrite() scans the buffer and sends every packet via the NdisSend() function.
+ When Sync is set to TRUE, the packets are synchronized with the KeQueryPerformanceCounter() function.
+ This requires a remarkable amount of CPU, but allows to respect the timestamps associated with packets with a precision
+ of some microseconds (depending on the precision of the performance counter of the machine).
+ If Sync is false, the timestamps are ignored and the packets are sent as fat as possible.
+*/
+
+INT NPF_BufferedWrite(IN PIRP Irp,
+ IN PCHAR UserBuff,
+ IN ULONG UserBuffSize,
+ BOOLEAN sync);
+
+/*!
+ \brief Waits the completion of all the sends performed by NPF_BufferedWrite.
+
+ \param Open Pointer to open context structure
+
+ Used by NPF_BufferedWrite to wait the completion of all the sends before returning the control to the user.
+*/
+VOID NPF_WaitEndOfBufferedWrite(POPEN_INSTANCE Open);
+
+/*!
+ \brief Ends a send operation.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+ \param 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
+NPF_SendComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN PNDIS_PACKET pPacket,
+ IN NDIS_STATUS Status
+ );
+
+/*!
+ \brief Ends a reset of the adapter.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
+ \param Status Status of the operation.
+
+ Callback function associated with the NdisReset() NDIS function. It is invoked by NDIS when the NIC
+ driver has finished an OID request operation that was previously started by NPF_IoControl(), in an IOCTL_PROTOCOL_RESET
+ command.
+*/
+VOID
+NPF_ResetComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status
+ );
+
+/*!
+ \brief Callback for NDIS StatusHandler. Not used by NPF
+*/
+VOID
+NPF_Status(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status,
+ IN PVOID StatusBuffer,
+ IN UINT StatusBufferSize
+ );
+
+
+/*!
+ \brief Callback for NDIS StatusCompleteHandler. Not used by NPF
+*/
+VOID
+NPF_StatusComplete(IN NDIS_HANDLE ProtocolBindingContext);
+
+/*!
+ \brief Function called by the OS when NPF is unloaded.
+ \param DriverObject The driver object of NPF created by the system.
+
+ This is the last function executed when the driver is unloaded from the system. It frees global resources,
+ delete the devices and deregisters the protocol. The driver can be unloaded by the user stopping the NPF
+ service (from control panel or with a console 'net stop npf').
+*/
+VOID
+NPF_Unload(IN PDRIVER_OBJECT DriverObject);
+
+
+/*!
+ \brief Function that serves the user's reads.
+ \param DeviceObject Pointer to the device used by the user.
+ \param Irp Pointer to the IRP containing the user request.
+ \return The status of the operation. See ntstatus.h in the DDK.
+
+ This function is called by the OS in consequence of user ReadFile() call. It moves the data present in the
+ kernel buffer to the user buffer associated with Irp.
+ First of all, NPF_Read checks the amount of data in kernel buffer associated with current NPF instance.
+ - If the instance is in capture mode and the buffer contains more than OPEN_INSTANCE::MinToCopy bytes,
+ NPF_Read moves the data in the user buffer and returns immediatly. In this way, the read performed by the
+ user is not blocking.
+ - If the buffer contains less than MinToCopy bytes, the application's request isn't
+ satisfied immediately, but it's blocked until at least MinToCopy bytes arrive from the net
+ or the timeout on this read expires. The timeout is kept in the OPEN_INSTANCE::TimeOut field.
+ - If the instance is in statistical mode or in dump mode, the application's request is blocked until the
+ timeout kept in OPEN_INSTANCE::TimeOut expires.
+*/
+NTSTATUS
+NPF_Read(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ );
+
+/*!
+ \brief Reads the registry keys associated woth NPF if the driver is manually installed via the control panel.
+
+ Normally not used in recent versions of NPF.
+*/
+NTSTATUS
+NPF_ReadRegistry(
+ IN PWSTR *MacDriverName,
+ IN PWSTR *PacketDriverName,
+ IN PUNICODE_STRING RegistryPath
+ );
+
+/*!
+ \brief Function used by NPF_ReadRegistry() to quesry the registry keys associated woth NPF if the driver
+ is manually installed via the control panel.
+
+ Normally not used in recent versions of NPF.
+*/
+NTSTATUS
+NPF_QueryRegistryRoutine(
+ IN PWSTR ValueName,
+ IN ULONG ValueType,
+ IN PVOID ValueData,
+ IN ULONG ValueLength,
+ IN PVOID Context,
+ IN PVOID EntryContext
+ );
+
+/*!
+ \brief Callback for NDIS BindAdapterHandler. Not used by NPF.
+
+ Function called by NDIS when a new adapter is installed on the machine With Plug and Play.
+*/
+VOID NPF_BindAdapter(
+ OUT PNDIS_STATUS Status,
+ IN NDIS_HANDLE BindContext,
+ IN PNDIS_STRING DeviceName,
+ IN PVOID SystemSpecific1,
+ IN PVOID SystemSpecific2
+ );
+
+/*!
+ \brief Callback for NDIS UnbindAdapterHandler.
+ \param Status out variable filled by NPF_UnbindAdapter with the status of the unbind operation.
+ \param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with current instance.
+ \param UnbindContext Specifies a handle, supplied by NDIS, that NPF can use to complete the opration.
+
+ Function called by NDIS when a new adapter is removed from the machine without shutting it down.
+ NPF_UnbindAdapter closes the adapter calling NdisCloseAdapter() and frees the memory and the structures
+ associated with it. It also releases the waiting user-level app and closes the dump thread if the instance
+ is in dump mode.
+*/
+VOID
+NPF_UnbindAdapter(
+ OUT PNDIS_STATUS Status,
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_HANDLE UnbindContext
+ );
+
+
+/*!
+ \brief Creates the file that will receive the packets when the driver is in dump mode.
+ \param Open The NPF instance that opens the file.
+ \param fileName Pointer to a UNICODE string containing the name of the file.
+ \param append Boolean value that specifies if the data must be appended to the file.
+ \return The status of the operation. See ntstatus.h in the DDK.
+*/
+NTSTATUS NPF_OpenDumpFile(POPEN_INSTANCE Open , PUNICODE_STRING fileName, BOOLEAN append);
+
+/*!
+ \brief Starts dump to file.
+ \param Open The NPF instance that opens the file.
+ \return The status of the operation. See ntstatus.h in the DDK.
+
+ This function performs two operations. First, it writes the libpcap header at the beginning of the file.
+ Second, it starts the thread that asynchronously dumps the network data to the file.
+*/
+NTSTATUS NPF_StartDump(POPEN_INSTANCE Open);
+
+/*!
+ \brief The dump thread.
+ \param Open The NPF instance that creates the thread.
+
+ This function moves the content of the NPF kernel buffer to file. It runs in the user context, so at lower
+ priority than the TAP.
+*/
+VOID NPF_DumpThread(PVOID Open);
+
+/*!
+ \brief Saves the content of the packet buffer to the file associated with current instance.
+ \param Open The NPF instance that creates the thread.
+
+ Used by NPF_DumpThread() and NPF_CloseDumpFile().
+*/
+NTSTATUS NPF_SaveCurrentBuffer(POPEN_INSTANCE Open);
+
+/*!
+ \brief Writes a block of packets on the dump file.
+ \param FileObject The file object that will receive the packets.
+ \param Offset The offset in the file where the packets will be put.
+ \param Length The amount of bytes to write.
+ \param Mdl MDL mapping the memory buffer that will be written to disk.
+ \param IoStatusBlock Used by the function to return the status of the operation.
+ \return The status of the operation. See ntstatus.h in the DDK.
+
+ NPF_WriteDumpFile addresses directly the file system, creating a custom IRP and using it to send a portion
+ of the NPF circular buffer to disk. This function is used by NPF_DumpThread().
+*/
+VOID NPF_WriteDumpFile(PFILE_OBJECT FileObject,
+ PLARGE_INTEGER Offset,
+ ULONG Length,
+ PMDL Mdl,
+ PIO_STATUS_BLOCK IoStatusBlock);
+
+
+
+/*!
+ \brief Closes the dump file associated with an instance of the driver.
+ \param Open The NPF instance that closes the file.
+ \return The status of the operation. See ntstatus.h in the DDK.
+*/
+NTSTATUS NPF_CloseDumpFile(POPEN_INSTANCE Open);
+
+/*!
+ \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*/
diff --git a/src/See/Packet32.h b/src/See/Packet32.h
new file mode 100644
index 00000000..8c2c8c4a
--- /dev/null
+++ b/src/See/Packet32.h
@@ -0,0 +1,423 @@
+/*
+ * Copyright (c) 1999 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/** @ingroup packetapi
+ * @{
+ */
+
+/** @defgroup packet32h Packet.dll definitions and data structures
+ * Packet32.h contains the data structures and the definitions used by packet.dll.
+ * The file is used both by the Win9x and the WinNTx versions of packet.dll, and can be included
+ * by the applications that use the functions of this library
+ * @{
+ */
+
+#ifndef __PACKET32
+#define __PACKET32
+
+#include <winsock2.h>
+#include "devioctl.h"
+#ifdef HAVE_DAG_API
+#include <dagc.h>
+#endif /* HAVE_DAG_API */
+
+// Working modes
+#define PACKET_MODE_CAPT 0x0 ///< Capture mode
+#define PACKET_MODE_STAT 0x1 ///< Statistical mode
+#define PACKET_MODE_MON 0x2 ///< Monitoring mode
+#define PACKET_MODE_DUMP 0x10 ///< Dump mode
+#define PACKET_MODE_STAT_DUMP MODE_DUMP | MODE_STAT ///< Statistical dump Mode
+
+// ioctls
+#define FILE_DEVICE_PROTOCOL 0x8000
+
+#define IOCTL_PROTOCOL_STATISTICS CTL_CODE(FILE_DEVICE_PROTOCOL, 2 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_RESET CTL_CODE(FILE_DEVICE_PROTOCOL, 3 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_READ CTL_CODE(FILE_DEVICE_PROTOCOL, 4 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_WRITE CTL_CODE(FILE_DEVICE_PROTOCOL, 5 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_PROTOCOL_MACNAME CTL_CODE(FILE_DEVICE_PROTOCOL, 6 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_OPEN CTL_CODE(FILE_DEVICE_PROTOCOL, 7 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+#define IOCTL_CLOSE CTL_CODE(FILE_DEVICE_PROTOCOL, 8 , METHOD_BUFFERED, FILE_ANY_ACCESS)
+
+#define pBIOCSETBUFFERSIZE 9592 ///< IOCTL code: set kernel buffer size.
+#define pBIOCSETF 9030 ///< IOCTL code: set packet filtering program.
+#define pBIOCGSTATS 9031 ///< IOCTL code: get the capture stats.
+#define pBIOCSRTIMEOUT 7416 ///< IOCTL code: set the read timeout.
+#define pBIOCSMODE 7412 ///< IOCTL code: set working mode.
+#define pBIOCSWRITEREP 7413 ///< IOCTL code: set number of physical repetions of every packet written by the app.
+#define pBIOCSMINTOCOPY 7414 ///< IOCTL code: set minimum amount of data in the kernel buffer that unlocks a read call.
+#define pBIOCSETOID 2147483648 ///< IOCTL code: set an OID value.
+#define pBIOCQUERYOID 2147483652 ///< IOCTL code: get an OID value.
+#define pATTACHPROCESS 7117 ///< IOCTL code: attach a process to the driver. Used in Win9x only.
+#define pDETACHPROCESS 7118 ///< IOCTL code: detach a process from the driver. Used in Win9x only.
+#define pBIOCSETDUMPFILENAME 9029 ///< IOCTL code: set the name of a the file used by kernel dump mode.
+#define pBIOCEVNAME 7415 ///< IOCTL code: get the name of the event that the driver signals when some data is present in the buffer.
+#define pBIOCSENDPACKETSNOSYNC 9032 ///< IOCTL code: Send a buffer containing multiple packets to the network, ignoring the timestamps associated with the packets.
+#define pBIOCSENDPACKETSSYNC 9033 ///< IOCTL code: Send a buffer containing multiple packets to the network, respecting the timestamps associated with the packets.
+#define pBIOCSETDUMPLIMITS 9034 ///< IOCTL code: Set the dump file limits. See the PacketSetDumpLimits() function.
+#define pBIOCISDUMPENDED 7411 ///< IOCTL code: Get the status of the kernel dump process. See the PacketIsDumpEnded() function.
+
+#define pBIOCSTIMEZONE 7471 ///< IOCTL code: set time zone. Used in Win9x only.
+
+
+/// Alignment macro. Defines the alignment size.
+#define Packet_ALIGNMENT sizeof(int)
+/// Alignment macro. Rounds up to the next even multiple of Packet_ALIGNMENT.
+#define Packet_WORDALIGN(x) (((x)+(Packet_ALIGNMENT-1))&~(Packet_ALIGNMENT-1))
+
+
+#define NdisMediumNull -1 // Custom linktype: NDIS doesn't provide an equivalent
+#define NdisMediumCHDLC -2 // Custom linktype: NDIS doesn't provide an equivalent
+#define NdisMediumPPPSerial -3 // Custom linktype: NDIS doesn't provide an equivalent
+
+/*!
+ \brief Network type structure.
+
+ This structure is used by the PacketGetNetType() function to return information on the current adapter's type and speed.
+*/
+typedef struct NetType
+{
+ UINT LinkType; ///< The MAC of the current network adapter (see function PacketGetNetType() for more information)
+ ULONGLONG LinkSpeed; ///< The speed of the network in bits per second
+}NetType;
+
+
+//some definitions stolen from libpcap
+
+#ifndef BPF_MAJOR_VERSION
+
+/*!
+ \brief A BPF pseudo-assembly program.
+
+ The program will be injected in the kernel by the PacketSetBPF() function and applied to every incoming packet.
+*/
+struct bpf_program
+{
+ UINT bf_len; ///< Indicates the number of instructions of the program, i.e. the number of struct bpf_insn that will follow.
+ struct bpf_insn *bf_insns; ///< A pointer to the first instruction of the program.
+};
+
+/*!
+ \brief A single BPF pseudo-instruction.
+
+ bpf_insn contains a single instruction for the BPF register-machine. It is used to send a filter program to the driver.
+*/
+struct bpf_insn
+{
+ USHORT code; ///< Instruction type and addressing mode.
+ UCHAR jt; ///< Jump if true
+ UCHAR jf; ///< Jump if false
+ int k; ///< Generic field used for various purposes.
+};
+
+/*!
+ \brief Structure that contains a couple of statistics values on the current capture.
+
+ It is used by packet.dll to return statistics about a capture session.
+*/
+struct bpf_stat
+{
+ UINT bs_recv; ///< Number of packets that the driver received from the network adapter
+ ///< from the beginning of the current capture. This value includes the packets
+ ///< lost by the driver.
+ UINT bs_drop; ///< number of packets that the driver lost from the beginning of a capture.
+ ///< Basically, a packet is lost when the the buffer of the driver is full.
+ ///< In this situation the packet cannot be stored and the driver rejects it.
+ UINT ps_ifdrop; ///< drops by interface. XXX not yet supported
+ UINT bs_capt; ///< number of packets that pass the filter, find place in the kernel buffer and
+ ///< thus reach the application.
+};
+
+/*!
+ \brief Packet header.
+
+ This structure defines the header associated with every packet delivered to the application.
+*/
+struct bpf_hdr
+{
+ struct timeval bh_tstamp; ///< The timestamp associated with the captured packet.
+ ///< It is stored in a TimeVal structure.
+ UINT bh_caplen; ///< Length of captured portion. The captured portion <b>can be different</b>
+ ///< 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 bh_datalen; ///< Original length of packet
+ USHORT bh_hdrlen; ///< Length of bpf header (this struct plus alignment padding). In some cases,
+ ///< a padding could be added between the end of this structure and the packet
+ ///< data for performance reasons. This filed can be used to retrieve the actual data
+ ///< of the packet.
+};
+
+/*!
+ \brief Dump packet header.
+
+ This structure defines the header associated with the packets in a buffer to be used with PacketSendPackets().
+ It is simpler than the bpf_hdr, because it corresponds to the header associated by WinPcap and libpcap to a
+ packet in a dump file. This makes straightforward sending WinPcap dump files to the network.
+*/
+struct dump_bpf_hdr{
+ struct timeval ts; ///< Time stamp of the packet
+ UINT caplen; ///< Length of captured portion. The captured portion can smaller than the
+ ///< 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).
+};
+
+
+#endif
+
+#define DOSNAMEPREFIX TEXT("Packet_") ///< Prefix added to the adapters device names to create the WinPcap devices
+#define MAX_LINK_NAME_LENGTH 64 //< Maximum length of the devices symbolic links
+#define NMAX_PACKET 65535
+
+/*!
+ \brief Addresses of a network adapter.
+
+ This structure is used by the PacketGetNetInfoEx() function to return the IP addresses associated with
+ an adapter.
+*/
+typedef struct npf_if_addr {
+ struct sockaddr_storage IPAddress; ///< IP address.
+ struct sockaddr_storage SubnetMask; ///< Netmask for that address.
+ struct sockaddr_storage Broadcast; ///< Broadcast address.
+}npf_if_addr;
+
+
+#define ADAPTER_NAME_LENGTH 256 + 12 ///< Maximum length for the name of an adapter. The value is the same used by the IP Helper API.
+#define ADAPTER_DESC_LENGTH 128 ///< Maximum length for the description of an adapter. The value is the same used by the IP Helper API.
+#define MAX_MAC_ADDR_LENGTH 8 ///< Maximum length for the link layer address of an adapter. The value is the same used by the IP Helper API.
+#define MAX_NETWORK_ADDRESSES 16 ///< Maximum length for the link layer address of an adapter. The value is the same used by the IP Helper API.
+
+
+typedef struct WAN_ADAPTER_INT WAN_ADAPTER; ///< Describes an opened wan (dialup, VPN...) network adapter using the NetMon API
+typedef WAN_ADAPTER *PWAN_ADAPTER; ///< Describes an opened wan (dialup, VPN...) network adapter using the NetMon API
+
+#define INFO_FLAG_NDIS_ADAPTER 0 ///< Flag for ADAPTER_INFO: this is a traditional ndis adapter
+#define INFO_FLAG_NDISWAN_ADAPTER 1 ///< Flag for ADAPTER_INFO: this is a NdisWan adapter
+#define INFO_FLAG_DAG_CARD 2 ///< Flag for ADAPTER_INFO: this is a DAG card
+#define INFO_FLAG_DAG_FILE 6 ///< Flag for ADAPTER_INFO: this is a DAG file
+#define INFO_FLAG_DONT_EXPORT 8 ///< Flag for ADAPTER_INFO: when this flag is set, the adapter will not be listed or openend by winpcap. This allows to prevent exporting broken network adapters, like for example FireWire ones.
+
+/*!
+ \brief Contains comprehensive information about a network adapter.
+
+ This structure is filled with all the accessory information that the user can need about an adapter installed
+ on his system.
+*/
+typedef struct _ADAPTER_INFO
+{
+ struct _ADAPTER_INFO *Next; ///< Pointer to the next adapter in the list.
+ CHAR Name[ADAPTER_NAME_LENGTH + 1]; ///< Name of the device representing the adapter.
+ CHAR Description[ADAPTER_DESC_LENGTH + 1]; ///< Human understandable description of the adapter
+ UINT MacAddressLen; ///< Length of the link layer address.
+ UCHAR MacAddress[MAX_MAC_ADDR_LENGTH]; ///< Link layer address.
+ NetType LinkLayer; ///< Physical characteristics of this adapter. This NetType structure contains the link type and the speed of the adapter.
+ INT NNetworkAddresses; ///< Number of network layer addresses of this adapter.
+ npf_if_addr *NetworkAddresses; ///< Pointer to an array of npf_if_addr, each of which specifies a network address of this adapter.
+ UINT Flags; ///< Adapter's flags. Tell if this adapter must be treated in a different way, using the Netmon API or the dagc API.
+}
+ADAPTER_INFO, *PADAPTER_INFO;
+
+/*!
+ \brief Describes an opened network adapter.
+
+ This structure is the most important for the functioning of packet.dll, but the great part of its fields
+ should be ignored by the user, since the library offers functions that avoid to cope with low-level parameters
+*/
+typedef struct _ADAPTER {
+ HANDLE hFile; ///< \internal Handle to an open instance of the NPF driver.
+ CHAR SymbolicLink[MAX_LINK_NAME_LENGTH]; ///< \internal A string containing the name of the network adapter currently opened.
+ int NumWrites; ///< \internal Number of times a packets written on this adapter will be repeated
+ ///< on the wire.
+ HANDLE ReadEvent; ///< A notification event associated with the read calls on the adapter.
+ ///< It can be passed to standard Win32 functions (like WaitForSingleObject
+ ///< or WaitForMultipleObjects) to wait until the driver's buffer contains some
+ ///< data. It is particularly useful in GUI applications that need to wait
+ ///< concurrently on several events. In Windows NT/2000 the PacketSetMinToCopy()
+ ///< function can be used to define the minimum amount of data in the kernel buffer
+ ///< that will cause the event to be signalled.
+
+ UINT ReadTimeOut; ///< \internal The amount of time after which a read on the driver will be released and
+ ///< ReadEvent will be signaled, also if no packets were captured
+ CHAR Name[ADAPTER_NAME_LENGTH];
+ PWAN_ADAPTER pWanAdapter;
+ UINT Flags; ///< Adapter's flags. Tell if this adapter must be treated in a different way, using the Netmon API or the dagc API.
+#ifdef HAVE_DAG_API
+ dagc_t *pDagCard; ///< Pointer to the dagc API adapter descriptor for this adapter
+ PCHAR DagBuffer; ///< Pointer to the buffer with the packets that is received from the DAG card
+ struct timeval DagReadTimeout; ///< Read timeout. The dagc API requires a timeval structure
+ unsigned DagFcsLen; ///< Length of the frame check sequence attached to any packet by the card. Obtained from the registry
+ DWORD DagFastProcess; ///< True if the user requests fast capture processing on this card. Higher level applications can use this value to provide a faster but possibly unprecise capture (for example, libpcap doesn't convert the timestamps).
+#endif // HAVE_DAG_API
+} ADAPTER, *LPADAPTER;
+
+/*!
+ \brief Structure that contains a group of packets coming from the driver.
+
+ This structure defines the header associated with every packet delivered to the application.
+*/
+typedef struct _PACKET {
+ HANDLE hEvent; ///< \deprecated Still present for compatibility with old applications.
+ OVERLAPPED OverLapped; ///< \deprecated Still present for compatibility with old applications.
+ PVOID Buffer; ///< Buffer with containing the packets. See the PacketReceivePacket() for
+ ///< details about the organization of the data in this buffer
+ UINT Length; ///< Length of the buffer
+ DWORD ulBytesReceived; ///< Number of valid bytes present in the buffer, i.e. amount of data
+ ///< received by the last call to PacketReceivePacket()
+ BOOLEAN bIoComplete; ///< \deprecated Still present for compatibility with old applications.
+} PACKET, *LPPACKET;
+
+/*!
+ \brief Structure containing an OID request.
+
+ It is used by the PacketRequest() function to send an OID to the interface card driver.
+ It can be used, for example, to retrieve the status of the error counters on the adapter, its MAC address,
+ the list of the multicast groups defined on it, and so on.
+*/
+struct _PACKET_OID_DATA {
+ ULONG Oid; ///< OID code. See the Microsoft DDK documentation or the file ntddndis.h
+ ///< for a complete list of valid codes.
+ ULONG Length; ///< Length of the data field
+ UCHAR Data[1]; ///< variable-lenght field that contains the information passed to or received
+ ///< from the adapter.
+};
+typedef struct _PACKET_OID_DATA PACKET_OID_DATA, *PPACKET_OID_DATA;
+
+
+#if _DBG
+#define ODS(_x) OutputDebugString(TEXT(_x))
+#define ODSEx(_x, _y)
+#else
+#ifdef _DEBUG_TO_FILE
+/*!
+ \brief Macro to print a debug string. The behavior differs depending on the debug level
+*/
+#define ODS(_x) { \
+ FILE *f; \
+ f = fopen("winpcap_debug.txt", "a"); \
+ fprintf(f, "%s", _x); \
+ fclose(f); \
+}
+/*!
+ \brief Macro to print debug data with the printf convention. The behavior differs depending on
+ the debug level
+*/
+#define ODSEx(_x, _y) { \
+ FILE *f; \
+ f = fopen("winpcap_debug.txt", "a"); \
+ fprintf(f, _x, _y); \
+ fclose(f); \
+}
+
+
+
+LONG PacketDumpRegistryKey(PCHAR KeyName, PCHAR FileName);
+#else
+#define ODS(_x)
+#define ODSEx(_x, _y)
+#endif
+#endif
+
+/* We load dinamically the dag library in order link it only when it's present on the system */
+#ifdef HAVE_DAG_API
+typedef dagc_t* (*dagc_open_handler)(const char *source, unsigned flags, char *ebuf); ///< prototype used to dynamically load the dag dll
+typedef void (*dagc_close_handler)(dagc_t *dagcfd); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_getlinktype_handler)(dagc_t *dagcfd); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_getlinkspeed_handler)(dagc_t *dagcfd); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_setsnaplen_handler)(dagc_t *dagcfd, unsigned snaplen); ///< prototype used to dynamically load the dag dll
+typedef unsigned (*dagc_getfcslen_handler)(dagc_t *dagcfd); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_receive_handler)(dagc_t *dagcfd, u_char **buffer, u_int *bufsize); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_stats_handler)(dagc_t *dagcfd, dagc_stats_t *ps); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_wait_handler)(dagc_t *dagcfd, struct timeval *timeout); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_finddevs_handler)(dagc_if_t **alldevsp, char *ebuf); ///< prototype used to dynamically load the dag dll
+typedef int (*dagc_freedevs_handler)(dagc_if_t *alldevsp); ///< prototype used to dynamically load the dag dll
+#endif // HAVE_DAG_API
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @}
+ */
+
+// The following is used to check the adapter name in PacketOpenAdapterNPF and prevent
+// opening of firewire adapters
+#define FIREWIRE_SUBSTR L"1394"
+
+void PacketPopulateAdaptersInfoList();
+PWCHAR SChar2WChar(PCHAR string);
+PCHAR WChar2SChar(PWCHAR string);
+BOOL PacketGetFileVersion(LPTSTR FileName, PCHAR VersionBuff, UINT VersionBuffLen);
+PADAPTER_INFO PacketFindAdInfo(PCHAR AdapterName);
+BOOLEAN PacketUpdateAdInfo(PCHAR AdapterName);
+BOOLEAN IsFireWire(TCHAR *AdapterDesc);
+
+
+//---------------------------------------------------------------------------
+// EXPORTED FUNCTIONS
+//---------------------------------------------------------------------------
+
+PCHAR PacketGetVersion();
+PCHAR PacketGetDriverVersion();
+BOOLEAN PacketSetMinToCopy(LPADAPTER AdapterObject,int nbytes);
+BOOLEAN PacketSetNumWrites(LPADAPTER AdapterObject,int nwrites);
+BOOLEAN PacketSetMode(LPADAPTER AdapterObject,int mode);
+BOOLEAN PacketSetReadTimeout(LPADAPTER AdapterObject,int timeout);
+BOOLEAN PacketSetBpf(LPADAPTER AdapterObject,struct bpf_program *fp);
+INT PacketSetSnapLen(LPADAPTER AdapterObject,int snaplen);
+BOOLEAN PacketGetStats(LPADAPTER AdapterObject,struct bpf_stat *s);
+BOOLEAN PacketGetStatsEx(LPADAPTER AdapterObject,struct bpf_stat *s);
+BOOLEAN PacketSetBuff(LPADAPTER AdapterObject,int dim);
+BOOLEAN PacketGetNetType (LPADAPTER AdapterObject,NetType *type);
+LPADAPTER PacketOpenAdapter(PCHAR AdapterName);
+BOOLEAN PacketSendPacket(LPADAPTER AdapterObject,LPPACKET pPacket,BOOLEAN Sync);
+INT PacketSendPackets(LPADAPTER AdapterObject,PVOID PacketBuff,ULONG Size, BOOLEAN Sync);
+LPPACKET PacketAllocatePacket(void);
+VOID PacketInitPacket(LPPACKET lpPacket,PVOID Buffer,UINT Length);
+VOID PacketFreePacket(LPPACKET lpPacket);
+BOOLEAN PacketReceivePacket(LPADAPTER AdapterObject,LPPACKET lpPacket,BOOLEAN Sync);
+BOOLEAN PacketSetHwFilter(LPADAPTER AdapterObject,ULONG Filter);
+BOOLEAN PacketGetAdapterNames(PTSTR pStr,PULONG BufferSize);
+BOOLEAN PacketGetNetInfoEx(PCHAR AdapterName, npf_if_addr* buffer, PLONG NEntries);
+BOOLEAN PacketRequest(LPADAPTER AdapterObject,BOOLEAN Set,PPACKET_OID_DATA OidData);
+HANDLE PacketGetReadEvent(LPADAPTER AdapterObject);
+BOOLEAN PacketSetDumpName(LPADAPTER AdapterObject, void *name, int len);
+BOOLEAN PacketSetDumpLimits(LPADAPTER AdapterObject, UINT maxfilesize, UINT maxnpacks);
+BOOLEAN PacketIsDumpEnded(LPADAPTER AdapterObject, BOOLEAN sync);
+BOOL PacketStopDriver();
+VOID PacketCloseAdapter(LPADAPTER lpAdapter);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //__PACKET32
diff --git a/src/See/Read.c b/src/See/Read.c
new file mode 100644
index 00000000..03df5c0d
--- /dev/null
+++ b/src/See/Read.c
@@ -0,0 +1,938 @@
+/*
+ * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies
+ * nor the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <GlobalConst.h>
+
+#include <stdarg.h>
+#include "ntddk.h"
+#include <ntiologc.h>
+#include <ndis.h>
+#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
+
+extern ULONG NCpu; //from packet.c
+
+NTSTATUS NPF_Read(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
+{
+ POPEN_INSTANCE Open;
+ PIO_STACK_LOCATION IrpSp;
+ PUCHAR packp;
+ PUCHAR CurrBuff;
+ struct bpf_hdr *header;
+// PUCHAR UserPointer;
+// ULONG bytecopy;
+ ULONG copied,count,current_cpu,plen,increment,ToCopy,available;
+ CpuPrivateData *LocalData;
+ ULONG i;
+ ULONG Occupation;
+
+ IF_LOUD(DbgPrint("NPF: Read\n");)
+
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+ Open=IrpSp->FileObject->FsContext;
+
+ if( Open->Bound == FALSE )
+ {
+ // The Network adapter has been removed or diasabled
+ EXIT_FAILURE(0);
+ }
+
+ if (Open->Size == 0)
+ {
+ 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);
+ }
+
+ Occupation=0;
+
+ for(i=0;i<NCpu;i++)
+ Occupation += (Open->Size - Open->CpuData[i].Free);
+
+ //See if the buffer is full enough to be copied
+ if( Occupation <= Open->MinToCopy*NCpu || Open->mode & MODE_DUMP )
+ {
+ //wait until some packets arrive or the timeout expires
+ if(Open->TimeOut.QuadPart != (LONGLONG)IMMEDIATE)
+ KeWaitForSingleObject(Open->ReadEvent,
+ UserRequest,
+ KernelMode,
+ TRUE,
+ (Open->TimeOut.QuadPart == (LONGLONG)0)? NULL: &(Open->TimeOut));
+
+ KeClearEvent(Open->ReadEvent);
+
+ if(Open->mode & MODE_STAT)
+ { //this capture instance is in statistics mode
+#ifdef NDIS50
+ CurrBuff=(PUCHAR)MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
+#else
+ CurrBuff=(PUCHAR)MmGetSystemAddressForMdl(Irp->MdlAddress);
+#endif
+
+ //fill the bpf header for this packet
+ header=(struct bpf_hdr*)CurrBuff;
+ GET_TIME(&header->bh_tstamp,&G_Start_Time);
+
+ if(Open->mode & MODE_DUMP){
+ *(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr)+16)=Open->DumpOffset.QuadPart;
+ header->bh_caplen=24;
+ header->bh_datalen=24;
+ Irp->IoStatus.Information = 24 + sizeof(struct bpf_hdr);
+ }
+ else{
+ header->bh_caplen=16;
+ header->bh_datalen=16;
+ header->bh_hdrlen=sizeof(struct bpf_hdr);
+ Irp->IoStatus.Information = 16 + sizeof(struct bpf_hdr);
+ }
+
+ *(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr))=Open->Npackets.QuadPart;
+ *(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr)+8)=Open->Nbytes.QuadPart;
+
+ //reset the countetrs
+ NdisAcquireSpinLock( &Open->CountersLock );
+ Open->Npackets.QuadPart=0;
+ Open->Nbytes.QuadPart=0;
+ NdisReleaseSpinLock( &Open->CountersLock );
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ return STATUS_SUCCESS;
+ }
+
+//
+// The MONITOR_MODE (aka TME extensions) is not supported on
+// 64 bit architectures
+//
+#ifdef __NPF_x86__
+
+ if(Open->mode==MODE_MON) //this capture instance is in monitor mode
+ {
+ PTME_DATA data;
+ ULONG cnt;
+ ULONG block_size;
+ PUCHAR tmp;
+
+#ifdef NDIS50
+ UserPointer=MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
+#else
+ UserPointer=MmGetSystemAddressForMdl(Irp->MdlAddress);
+#endif
+
+ if ((!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->MachineLock);
+ RtlCopyMemory(UserPointer,tmp,block_size);
+ NdisReleaseSpinLock(&Open->MachineLock);
+ tmp+=block_size;
+ UserPointer+=block_size;
+ }
+
+ bytecopy*=block_size;
+
+ header->bh_caplen=bytecopy;
+ header->bh_datalen=header->bh_caplen;
+
+ EXIT_SUCCESS(bytecopy+sizeof(struct bpf_hdr));
+ }
+
+ Occupation=0;
+
+ for(i=0;i<NCpu;i++)
+ Occupation += (Open->Size - Open->CpuData[i].Free);
+
+
+ if ( Occupation == 0 || Open->mode & MODE_DUMP)
+ // The timeout has expired, but the buffer is still empty (or the packets must be written to file).
+ // We must awake the application, returning an empty buffer.
+ {
+ EXIT_SUCCESS(0);
+ }
+
+ #else // not __NPF_x86__ , so x86-64 or IA64
+ if(Open->mode==MODE_MON) //this capture instance is in monitor mode
+ {
+ EXIT_FAILURE(0);
+ }
+ #endif // __NPF_x86__
+
+ }
+
+
+
+//------------------------------------------------------------------------------
+ copied=0;
+ count=0;
+ current_cpu=0;
+ available = IrpSp->Parameters.Read.Length;
+#ifdef NDIS50
+ packp=(PUCHAR)MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);
+#else
+ packp=(PUCHAR)MmGetSystemAddressForMdl(Irp->MdlAddress);
+#endif
+
+
+ KeClearEvent(Open->ReadEvent);
+
+ while (count < NCpu) //round robin on the CPUs, if count = NCpu there are no packets left to be copied
+ {
+ if (available == copied)
+ {
+ EXIT_SUCCESS(copied);
+ }
+
+ LocalData = &Open->CpuData[current_cpu];
+
+ if (LocalData->Free < Open->Size)
+ { //there are some packets in the selected (aka LocalData) buffer
+ struct PacketHeader *Header = (struct PacketHeader*)(LocalData->Buffer + LocalData->C);
+
+ if ( Header->SN == Open->ReaderSN)
+ { //check if it the next one to be copied
+ plen = Header->header.bh_caplen;
+ if (plen + sizeof (struct bpf_hdr) > available - copied)
+ { //if the packet does not fit into the user buffer, we've ended copying packets
+ EXIT_SUCCESS(copied);
+ }
+
+// FIX_TIMESTAMPS(&Header->header.bh_tstamp);
+
+ *((struct bpf_hdr*)(&packp[copied]))=Header->header;
+
+ copied += sizeof(struct bpf_hdr);
+ LocalData->C += sizeof(struct PacketHeader);
+
+ if (LocalData->C == Open->Size)
+ LocalData->C = 0;
+
+ if (Open->Size - LocalData->C < plen)
+ {
+ //the packet is fragmented in the buffer (i.e. it skips the buffer boundary)
+ ToCopy = Open->Size - LocalData->C;
+ RtlCopyMemory(packp + copied,LocalData->Buffer + LocalData->C,ToCopy);
+ RtlCopyMemory(packp + copied + ToCopy,LocalData->Buffer,plen-ToCopy);
+ LocalData->C = plen-ToCopy;
+ }
+ else
+ {
+ //the packet is not fragmented
+ RtlCopyMemory(packp + copied ,LocalData->Buffer + LocalData->C ,plen);
+ LocalData->C += plen;
+ // if (c==size) inutile, contemplato nell "header atomico"
+ // c=0;
+ }
+
+ Open->ReaderSN++;
+ copied+=Packet_WORDALIGN(plen);
+
+ increment = plen + sizeof(struct PacketHeader);
+ if ( Open->Size - LocalData->C < sizeof(struct PacketHeader))
+ { //the next packet would be saved at the end of the buffer, but the NewHeader struct would be fragmented
+ //so the producer (--> the consumer) skips to the beginning of the buffer
+ increment += Open->Size-LocalData->C;
+ LocalData->C=0;
+ }
+ InterlockedExchangeAdd(&Open->CpuData[current_cpu].Free,increment);
+ count=0;
+ }
+ else
+ {
+ current_cpu=(current_cpu+1)%NCpu;
+ count++;
+ }
+
+ }
+ else
+ {
+ current_cpu=(current_cpu+1)%NCpu;
+ count++;
+ }
+ }
+
+ {EXIT_SUCCESS(copied);}
+
+//------------------------------------------------------------------------------
+
+}
+
+extern void *test_addr;
+
+NDIS_STATUS NPF_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE MacReceiveContext,
+ IN PVOID HeaderBuffer,IN UINT HeaderBufferSize,IN PVOID LookaheadBuffer,
+ IN UINT LookaheadBufferSize,IN UINT PacketSize)
+{
+ POPEN_INSTANCE Open;
+ PNDIS_PACKET pPacket;
+ NDIS_STATUS Status;
+ UINT BytesTransfered;
+ PMDL pMdl1,pMdl2;
+ UINT fres;
+
+ CpuPrivateData *LocalData;
+ ULONG Cpu;
+ struct PacketHeader *Header;
+ ULONG ToCopy;
+ ULONG increment;
+ ULONG i;
+// BOOLEAN ShouldReleaseMachineLock;
+
+ IF_VERY_LOUD(DbgPrint("NPF: tap\n");)
+ IF_VERY_LOUD(DbgPrint("HeaderBufferSize=%d, LookAheadBuffer=%d, LookaheadBufferSize=%d, PacketSize=%d\n",
+ HeaderBufferSize,
+ LookaheadBuffer,
+ LookaheadBufferSize,
+ PacketSize);)
+
+ Open= (POPEN_INSTANCE)ProtocolBindingContext;
+
+ if (Open->SkipProcessing == 1) //some IoCtl is modifying some shared structure, we must drop the packet.
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ Cpu = KeGetCurrentProcessorNumber();
+ LocalData = &Open->CpuData[Cpu];
+
+ LocalData->Processing = 1; //this tells the Ioctls that we are processing a packet, they cannot modify anything
+ //until ALL the Cpu have terminated their processing (aka, set their LocalData->processing to 0)
+ LocalData->Received++;
+ IF_LOUD(DbgPrint("Received on CPU %d \t%d\n",Cpu,LocalData->Received);)
+// Open->Received++; // Number of packets received by filter ++
+
+//
+// The MONITOR_MODE (aka TME extensions) is not supported on
+// 64 bit architectures
+//
+#ifdef __NPF_x86__
+ if (Open->mode == MODE_MON)
+ {
+ ShouldReleaseMachineLock = TRUE;
+ NdisAcquireSpinLock(&Open->MachineLock);
+ }
+ else
+ ShouldReleaseMachineLock = FALSE;
+#endif
+
+ //
+ //Check if the lookahead buffer follows the mac header.
+ //If the data follow the header (i.e. there is only a buffer) a normal bpf_filter() is
+ //executed on the packet.
+ //Otherwise if there are 2 separate buffers (this could be the case of LAN emulation or
+ //things like this) bpf_filter_with_2_buffers() is executed.
+ //
+ if((UINT)((PUCHAR)LookaheadBuffer-(PUCHAR)HeaderBuffer) != HeaderBufferSize)
+ fres=bpf_filter_with_2_buffers((struct bpf_insn*)(Open->bpfprogram),
+ HeaderBuffer,
+ LookaheadBuffer,
+ HeaderBufferSize,
+ PacketSize+HeaderBufferSize,
+ LookaheadBufferSize+HeaderBufferSize,
+ &Open->mem_ex,
+ &Open->tme,
+ &G_Start_Time);
+
+
+ else
+//
+// the jit filter is available on x86 (32 bit) only
+//
+#ifdef __NPF_x86__
+
+ if(Open->Filter != NULL)
+ {
+ if (Open->bpfprogram != NULL)
+ {
+ fres=Open->Filter->Function(HeaderBuffer,
+ PacketSize+HeaderBufferSize,
+ LookaheadBufferSize+HeaderBufferSize);
+ }
+ else
+ fres = -1;
+ }
+ else
+#endif //__NPF_x86__
+ fres=bpf_filter((struct bpf_insn*)(Open->bpfprogram),
+ HeaderBuffer,
+ PacketSize+HeaderBufferSize,
+ LookaheadBufferSize+HeaderBufferSize,
+ &Open->mem_ex,
+ &Open->tme,
+ &G_Start_Time);
+
+//
+// The MONITOR_MODE (aka TME extensions) is not supported on
+// 64 bit architectures
+//
+#ifdef __NPF_x86__
+ if (ShouldReleaseMachineLock)
+ NdisReleaseSpinLock(&Open->MachineLock);
+#endif
+
+//
+// The MONITOR_MODE (aka TME extensions) is not supported on
+// 64 bit architectures
+//
+#ifdef __NPF_x86__
+ if(Open->mode==MODE_MON)
+ // we are in monitor mode
+ {
+ if (fres==1)
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+ LocalData->Processing = 0;
+ return NDIS_STATUS_NOT_ACCEPTED;
+
+ }
+#endif
+
+ if(fres==0)
+ {
+ // Packet not accepted by the filter, ignore it.
+ LocalData->Processing = 0;
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+
+ //if the filter returns -1 the whole packet must be accepted
+ if(fres==-1 || fres > PacketSize+HeaderBufferSize)
+ fres = PacketSize+HeaderBufferSize;
+
+ if(Open->mode & MODE_STAT)
+ {
+ // we are in statistics mode
+ NdisAcquireSpinLock( &Open->CountersLock );
+
+ Open->Npackets.QuadPart++;
+
+ if(PacketSize+HeaderBufferSize<60)
+ Open->Nbytes.QuadPart+=60;
+ else
+ Open->Nbytes.QuadPart+=PacketSize+HeaderBufferSize;
+ // add preamble+SFD+FCS to the packet
+ // these values must be considered because are not part of the packet received from NDIS
+ Open->Nbytes.QuadPart+=12;
+
+ NdisReleaseSpinLock( &Open->CountersLock );
+
+ if(!(Open->mode & MODE_DUMP))
+ {
+ LocalData->Processing = 0;
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+ }
+
+ if(Open->Size == 0)
+ {
+ LocalData->Dropped++;
+ LocalData->Processing = 0;
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+
+ if(Open->mode & MODE_DUMP && Open->MaxDumpPacks)
+ {
+ ULONG Accepted=0;
+ for(i=0;i<NCpu;i++)
+ Accepted+=Open->CpuData[i].Accepted;
+
+ if( Accepted > Open->MaxDumpPacks)
+ {
+ // Reached the max number of packets to save in the dump file. Discard the packet and stop the dump thread.
+ Open->DumpLimitReached = TRUE; // This stops the thread
+ // Awake the dump thread
+ NdisSetEvent(&Open->DumpEvent);
+
+ // Awake the application
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+
+ LocalData->Processing = 0;
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+ }
+
+ //////////////////////////////COPIA.C//////////////////////////////////////////77
+
+ if (fres + sizeof(struct PacketHeader) > LocalData->Free)
+ {
+ LocalData->Dropped++;
+ LocalData->Processing = 0;
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+
+ if (LocalData->TransferMdl1 != NULL)
+ {
+ //if TransferMdl is not NULL, there is some TransferData pending (i.e. not having called TransferDataComplete, yet)
+ //in order to avoid buffer corruption, we drop the packet
+ LocalData->Dropped++;
+ LocalData->Processing = 0;
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+
+
+ if (LookaheadBufferSize + HeaderBufferSize >= fres)
+ {
+ //we do not need to call NdisTransferData, either because we need only the HeaderBuffer, or because the LookaheadBuffer
+ //contains what we need
+
+
+
+ Header = (struct PacketHeader*)(LocalData->Buffer + LocalData->P);
+ LocalData->Accepted++;
+ GET_TIME(&Header->header.bh_tstamp,&G_Start_Time);
+ Header->SN = InterlockedIncrement(&Open->WriterSN) - 1;
+
+ Header->header.bh_caplen = fres;
+ Header->header.bh_datalen = PacketSize + HeaderBufferSize;
+ Header->header.bh_hdrlen=sizeof(struct bpf_hdr);
+
+ LocalData->P +=sizeof(struct PacketHeader);
+ if (LocalData->P == Open->Size)
+ LocalData->P = 0;
+
+ if ( fres <= HeaderBufferSize || (UINT)( (PUCHAR)LookaheadBuffer - (PUCHAR)HeaderBuffer ) == HeaderBufferSize )
+ {
+ //we can consider the buffer contiguous, either because we use only the data
+ //present in the HeaderBuffer, or because HeaderBuffer and LookaheadBuffer are contiguous
+ // ;-))))))
+
+ if (Open->Size - LocalData->P < fres)
+ {
+ //the packet will be fragmented in the buffer (aka, it will skip the buffer boundary)
+ //two copies!!
+ ToCopy = Open->Size - LocalData->P;
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->P,HeaderBuffer, ToCopy);
+ NdisMoveMappedMemory(LocalData->Buffer + 0 , (PUCHAR)HeaderBuffer + ToCopy, fres - ToCopy);
+ LocalData->P = fres-ToCopy;
+ }
+ else
+ {
+ //the packet does not need to be fragmented in the buffer (aka, it doesn't skip the buffer boundary)
+ // ;-)))))) only ONE copy
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, HeaderBuffer, fres);
+ LocalData->P += fres;
+ }
+ }
+ else
+ {
+ //HeaderBuffer and LookAhead buffer are NOT contiguous,
+ //AND, we need some bytes from the LookaheadBuffer, too
+ if (Open->Size - LocalData->P < fres)
+ {
+ //the packet will be fragmented in the buffer (aka, it will skip the buffer boundary)
+ if (Open->Size - LocalData->P >= HeaderBufferSize)
+ {
+ //HeaderBuffer is NOT fragmented
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, HeaderBuffer, HeaderBufferSize);
+ LocalData->P += HeaderBufferSize;
+
+ if (LocalData->P == Open->Size)
+ {
+ //the fragmentation of the packet in the buffer is the same fragmentation
+ //in HeaderBuffer+LookaheadBuffer
+ LocalData->P=0;
+ NdisMoveMappedMemory(LocalData->Buffer + 0, LookaheadBuffer, fres - HeaderBufferSize);
+ LocalData->P += (fres - HeaderBufferSize);
+ }
+ else
+ {
+ //LookAheadBuffer is fragmented, two copies
+ ToCopy = Open->Size - LocalData->P;
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, LookaheadBuffer, ToCopy);
+ LocalData->P=0;
+ NdisMoveMappedMemory(LocalData->Buffer + 0, (PUCHAR)LookaheadBuffer+ ToCopy, fres - HeaderBufferSize - ToCopy);
+ LocalData->P = fres - HeaderBufferSize - ToCopy;
+ }
+ }
+ else
+ {
+ //HeaderBuffer is fragmented in the buffer (aka, it will skip the buffer boundary)
+ //two copies to copy the HeaderBuffer
+ ToCopy = Open->Size - LocalData->P;
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, HeaderBuffer, ToCopy);
+ LocalData->P = 0;
+ NdisMoveMappedMemory(LocalData->Buffer + 0, (PUCHAR)HeaderBuffer + ToCopy, HeaderBufferSize - ToCopy);
+ LocalData->P = HeaderBufferSize - ToCopy;
+
+ //only one copy to copy the LookaheadBuffer
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, LookaheadBuffer, fres- HeaderBufferSize);
+ LocalData->P += (fres - HeaderBufferSize);
+ }
+ }
+ else
+ {
+ //the packet won't be fragmented in the destination buffer (aka, it won't skip the buffer boundary)
+ //two copies, the former to copy the HeaderBuffer, the latter to copy the LookaheadBuffer
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, HeaderBuffer, HeaderBufferSize);
+ LocalData->P += HeaderBufferSize;
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->P, LookaheadBuffer, fres - HeaderBufferSize);
+ LocalData->P += (fres - HeaderBufferSize);
+ }
+ }
+
+ increment = fres + sizeof(struct PacketHeader);
+ if (Open->Size - LocalData->P < sizeof(struct PacketHeader)) //we check that the available, AND contiguous, space in the buffer will fit
+ { //the NewHeader structure, at least, otherwise we skip the producer
+ increment += Open->Size-LocalData->P; //at the beginning of the buffer (p = 0), and decrement the free bytes appropriately
+ LocalData->P = 0;
+ }
+
+ InterlockedExchangeAdd(&LocalData->Free, (ULONG)(-(LONG)increment));
+ if(Open->Size - LocalData->Free >= Open->MinToCopy)
+ {
+ if(Open->mode & MODE_DUMP)
+ NdisSetEvent(&Open->DumpEvent);
+ else
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+ }
+
+ LocalData->Processing = 0;
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+ else
+ {
+ IF_LOUD(DbgPrint("TransferData!!\n");)
+ //ndisTransferData required
+ LocalData->NewP = LocalData->P;
+
+ LocalData->NewP +=sizeof(struct PacketHeader);
+ if (LocalData->NewP == Open->Size)
+ LocalData->NewP = 0;
+
+ //first of all, surely the header must be copied
+ if (Open->Size-LocalData->NewP >= HeaderBufferSize)
+ {
+ //1 copy!
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->NewP, HeaderBuffer, HeaderBufferSize);
+ LocalData->NewP += HeaderBufferSize;
+ if (LocalData->NewP == Open->Size)
+ LocalData->NewP = 0;
+ }
+ else
+ {
+ ToCopy = Open->Size - LocalData->NewP;
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->NewP, HeaderBuffer, ToCopy);
+ NdisMoveMappedMemory(LocalData->Buffer + 0, (PUCHAR)HeaderBuffer + ToCopy, HeaderBufferSize - ToCopy);
+ LocalData->NewP = HeaderBufferSize - ToCopy;
+ }
+
+ //then we copy the Lookahead buffer
+
+ if (Open->Size-LocalData->NewP >= LookaheadBufferSize)
+ {
+ //1 copy!
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->NewP, LookaheadBuffer, LookaheadBufferSize);
+ LocalData->NewP += LookaheadBufferSize;
+ if (LocalData->NewP == Open->Size)
+ LocalData->NewP = 0;
+ }
+ else
+ {
+ ToCopy = Open->Size - LocalData->NewP;
+ NdisMoveMappedMemory(LocalData->Buffer + LocalData->NewP, LookaheadBuffer, ToCopy);
+ NdisMoveMappedMemory(LocalData->Buffer + 0, (PUCHAR)LookaheadBuffer + ToCopy, LookaheadBufferSize - ToCopy);
+ LocalData->NewP = LookaheadBufferSize - ToCopy;
+ }
+
+ //Now we must prepare the buffer(s) for the NdisTransferData
+ if ((Open->Size - LocalData->NewP) >= (fres - HeaderBufferSize - LookaheadBufferSize))
+ {
+ //only 1 buffer
+ pMdl1 = IoAllocateMdl(
+ LocalData->Buffer + LocalData->NewP,
+ fres - HeaderBufferSize - LookaheadBufferSize,
+ FALSE,
+ FALSE,
+ NULL);
+
+ if (pMdl1 == NULL)
+ {
+ IF_LOUD(DbgPrint("Error allocating Mdl1\n");)
+ LocalData->Dropped++;
+ LocalData->Processing = 0;
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+
+ MmBuildMdlForNonPagedPool(pMdl1);
+ pMdl2=NULL;
+ LocalData->NewP += fres - HeaderBufferSize - LookaheadBufferSize;
+
+
+ }
+ else
+ {
+ //2 buffers
+ pMdl1 = IoAllocateMdl(
+ LocalData->Buffer + LocalData->NewP,
+ Open->Size - LocalData->NewP,
+ FALSE,
+ FALSE,
+ NULL);
+
+ if (pMdl1 == NULL)
+ {
+ IF_LOUD(DbgPrint("Error allocating Mdl1\n");)
+ LocalData->Dropped++;
+ LocalData->Processing = 0;
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+
+ pMdl2 = IoAllocateMdl(
+ LocalData->Buffer + 0,
+ fres - HeaderBufferSize - LookaheadBufferSize - (Open->Size - LocalData->NewP),
+ FALSE,
+ FALSE,
+ NULL);
+
+ if (pMdl2 == NULL)
+ {
+ IF_LOUD(DbgPrint("Error allocating Mdl2\n");)
+ IoFreeMdl(pMdl1);
+ LocalData->Dropped++;
+ LocalData->Processing = 0;
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+
+ LocalData->NewP = fres - HeaderBufferSize - LookaheadBufferSize - (Open->Size - LocalData->NewP);
+
+ MmBuildMdlForNonPagedPool(pMdl1);
+ MmBuildMdlForNonPagedPool(pMdl2);
+ }
+
+
+ NdisAllocatePacket(&Status, &pPacket, Open->PacketPool);
+
+ if (Status != NDIS_STATUS_SUCCESS)
+ {
+ IF_LOUD(DbgPrint("NPF: Tap - No free packets\n");)
+ IoFreeMdl(pMdl1);
+ if (pMdl2 != NULL)
+ IoFreeMdl(pMdl2);
+ LocalData->Dropped++;
+ LocalData->Processing = 0;
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+
+ if (pMdl2 != NULL)
+ NdisChainBufferAtFront(pPacket,pMdl2);
+
+ NdisChainBufferAtFront(pPacket,pMdl1);
+
+ RESERVED(pPacket)->Cpu = Cpu;
+
+ LocalData->TransferMdl1 = pMdl1;
+ LocalData->TransferMdl2 = pMdl2;
+
+
+ Header = (struct PacketHeader*)(LocalData->Buffer + LocalData->P);
+ Header->header.bh_caplen = fres;
+ Header->header.bh_datalen = PacketSize + HeaderBufferSize;
+ Header->header.bh_hdrlen=sizeof(struct bpf_hdr);
+
+ NdisTransferData(
+ &Status,
+ Open->AdapterHandle,
+ MacReceiveContext,
+ LookaheadBufferSize,
+ fres - HeaderBufferSize - LookaheadBufferSize,
+ pPacket,
+ &BytesTransfered);
+
+ if (Status != NDIS_STATUS_PENDING)
+ {
+ IF_LOUD(DbgPrint("NdisTransferData, not pending!\n");)
+ LocalData->TransferMdl1 = NULL;
+ LocalData->TransferMdl2 = NULL;
+
+ IoFreeMdl(pMdl1);
+ if ( pMdl2 != NULL )
+ IoFreeMdl(pMdl2);
+
+ NdisReinitializePacket(pPacket);
+ // Put the packet on the free queue
+ NdisFreePacket(pPacket);
+
+ LocalData->P = LocalData->NewP;
+
+ LocalData->Accepted++;
+ GET_TIME(&Header->header.bh_tstamp,&G_Start_Time);
+ Header->SN = InterlockedIncrement(&Open->WriterSN) - 1;
+
+ increment = fres + sizeof(struct PacketHeader);
+ if (Open->Size - LocalData->P < sizeof(struct PacketHeader))
+ {
+ increment += Open->Size-LocalData->P;
+ LocalData->P = 0;
+ }
+
+ InterlockedExchangeAdd(&LocalData->Free, (ULONG)(-(LONG)increment));
+
+ if(Open->Size - LocalData->Free >= Open->MinToCopy)
+ {
+ if(Open->mode & MODE_DUMP)
+ NdisSetEvent(&Open->DumpEvent);
+ else
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+ }
+
+ LocalData->Processing = 0;
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+ else
+ {
+ DbgPrint("NdisTransferData, pending!\n");
+ return NDIS_STATUS_NOT_ACCEPTED;
+ }
+ }
+
+ return NDIS_STATUS_SUCCESS;
+
+}
+
+//-------------------------------------------------------------------
+
+VOID NPF_TransferDataComplete (IN NDIS_HANDLE ProtocolBindingContext,IN PNDIS_PACKET pPacket,
+ IN NDIS_STATUS Status,IN UINT BytesTransfered)
+{
+ POPEN_INSTANCE Open;
+ ULONG Cpu;
+ CpuPrivateData *LocalData;
+ struct PacketHeader* Header;
+ ULONG increment;
+
+ IF_LOUD(DbgPrint("NPF: TransferDataComplete\n");)
+
+ Open = (POPEN_INSTANCE)ProtocolBindingContext;
+
+ Cpu = RESERVED(pPacket)->Cpu;
+
+ LocalData = &Open->CpuData[Cpu];
+
+ IoFreeMdl(LocalData->TransferMdl1);
+ if ( LocalData->TransferMdl2 != NULL )
+ IoFreeMdl(LocalData->TransferMdl2);
+
+ NdisReinitializePacket(pPacket);
+ // Put the packet on the free queue
+ NdisFreePacket(pPacket);
+
+ //the packet has been successfully copied to the kernel buffer, we can prepend it with the PacketHeader,
+ //and obtain the sequence number and the timestamp
+
+ LocalData->Accepted++;
+ Header = (struct PacketHeader*)(LocalData->Buffer + LocalData->P);
+ GET_TIME(&Header->header.bh_tstamp,&G_Start_Time);
+ Header->SN = InterlockedIncrement(&Open->WriterSN) - 1;
+
+ LocalData->P = LocalData->NewP;
+
+ increment = Header->header.bh_caplen + sizeof(struct PacketHeader);
+ if (Open->Size - LocalData->P < sizeof(struct PacketHeader))
+ {
+ increment += Open->Size-LocalData->P;
+ LocalData->P = 0;
+ }
+
+ InterlockedExchangeAdd(&LocalData->Free, (ULONG)(-(LONG)increment));
+
+ if(Open->Size - LocalData->Free >= Open->MinToCopy)
+ {
+ if(Open->mode & MODE_DUMP)
+ NdisSetEvent(&Open->DumpEvent);
+ else
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+ }
+
+ LocalData->TransferMdl1 = NULL;
+ LocalData->TransferMdl2 = NULL;
+ LocalData->Processing = 0;
+
+// Unfreeze the consumer
+ if(Open->Size - LocalData->Free > Open->MinToCopy)
+ {
+ if(Open->mode & MODE_DUMP)
+ NdisSetEvent(&Open->DumpEvent);
+ else
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+ }
+ return;
+}
+
+//-------------------------------------------------------------------
+
+VOID NPF_ReceiveComplete(IN NDIS_HANDLE ProtocolBindingContext)
+{
+ IF_VERY_LOUD(DbgPrint("NPF: NPF_ReceiveComplete\n");)
+ return;
+}
diff --git a/src/See/See.rc b/src/See/See.rc
new file mode 100644
index 00000000..5c275264
--- /dev/null
+++ b/src/See/See.rc
@@ -0,0 +1,63 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource1.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Japanese resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN)
+#ifdef _WIN32
+LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT
+#pragma code_page(932)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource1.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // Japanese resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/src/See/See.vcproj b/src/See/See.vcproj
new file mode 100644
index 00000000..f5254e95
--- /dev/null
+++ b/src/See/See.vcproj
@@ -0,0 +1,462 @@
+<?xml version="1.0" encoding="shift_jis"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="See"
+ ProjectGUID="{D817977C-481C-4575-B229-DD2896EDF6C9}"
+ RootNamespace="See"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;C:\WINDDK\7600.16385.0\inc\ddk;C:\WinDDK\7600.16385.0\inc\api;C:\WinDDK\7600.16385.0\inc\crt;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;NEO_EXPORTS;VPN_SPEED;WIN_NT_DRIVER;_X86_=1;NDIS50;NTKERNEL"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CallingConvention="2"
+ CompileAs="1"
+ DisableSpecificWarnings="4996"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalOptions="/driver /subsystem:native,5.00 /FULLBUILD /align:0x80 /osversion:5.00 /MERGE:_PAGE=PAGE /MERGE:_TEXT=.text /NODEFAULTLIB"
+ AdditionalDependencies="ntoskrnl.lib hal.lib wmilib.lib ndis.lib &quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\hamcore\not_signed\see.sys"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="C:\WINDDK\7600.16385.0\lib\wnet\i386"
+ GenerateManifest="false"
+ IgnoreAllDefaultLibraries="true"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="0"
+ StackReserveSize="262144"
+ StackCommitSize="4096"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ EntryPointSymbol="DriverEntry"
+ BaseAddress="0x10000"
+ RandomizedBaseAddress="0"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)\$(ProjectName).lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SignCode &quot;$(TargetPath)&quot; /COMMENT:&quot;VPN Software&quot; /KERNEL:yes"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(SolutionDir)bin"
+ IntermediateDirectory="$(PlatformName)_$(ConfigurationName)"
+ ConfigurationType="2"
+ CharacterSet="2"
+ WholeProgramOptimization="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="0"
+ EnableIntrinsicFunctions="false"
+ FavorSizeOrSpeed="0"
+ AdditionalIncludeDirectories="$(SolutionDir)Mayaqua\win32_inc;C:\WINDDK\7600.16385.0\inc\ddk;C:\WinDDK\7600.16385.0\inc\api;C:\WinDDK\7600.16385.0\inc\crt;$(SolutionDir)"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;NEO_EXPORTS;VPN_SPEED;WIN_NT_DRIVER;NDIS50;WIN32_EXT;__NPF_AMD64__;_AMD64_;AMD64;_WIN64;NTKERNEL;CPU_64"
+ StringPooling="false"
+ ExceptionHandling="0"
+ RuntimeLibrary="0"
+ StructMemberAlignment="4"
+ BufferSecurityCheck="false"
+ EnableFunctionLevelLinking="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ CallingConvention="2"
+ CompileAs="1"
+ DisableSpecificWarnings="4996;4334"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:GenerateVersionResource &quot;$(TargetPath)&quot; /OUT:&quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalOptions="/driver /subsystem:native /FULLBUILD /align:0x80 /osversion:5.00 /MERGE:_PAGE=PAGE /MERGE:_TEXT=.text /NODEFAULTLIB"
+ AdditionalDependencies="ntoskrnl.lib hal.lib wmilib.lib ndis.lib &quot;$(SolutionDir)tmp\VersionResources\$(ProjectName)_$(PlatformName).res&quot;"
+ OutputFile="$(OutDir)\hamcore\not_signed\see_x64.sys"
+ LinkIncremental="1"
+ AdditionalLibraryDirectories="C:\WINDDK\7600.16385.0\lib\wnet\amd64"
+ GenerateManifest="false"
+ IgnoreAllDefaultLibraries="true"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(SolutionDir)DebugFiles\pdb\$(PlatformName)_$(ConfigurationName)\$(ProjectName).pdb"
+ GenerateMapFile="true"
+ MapFileName="$(SolutionDir)DebugFiles\map\$(PlatformName)_$(ConfigurationName)\$(ProjectName).map"
+ SubSystem="0"
+ StackReserveSize="262144"
+ StackCommitSize="4096"
+ OptimizeReferences="1"
+ EnableCOMDATFolding="1"
+ EntryPointSymbol="DriverEntry"
+ BaseAddress="0x10000"
+ RandomizedBaseAddress="0"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(SolutionDir)tmp\lib\$(PlatformName)_$(ConfigurationName)\$(ProjectName).lib"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ EmbedManifest="false"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ CommandLine="$(SolutionDir)bin\BuildUtil.exe /CMD:SignCode &quot;$(TargetPath)&quot; /COMMENT:&quot;VPN Software&quot; /KERNEL:yes"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\bucket_lookup.c"
+ >
+ <FileConfiguration
+ Name="Release|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\count_packets.c"
+ >
+ <FileConfiguration
+ Name="Release|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\dump.c"
+ >
+ </File>
+ <File
+ RelativePath=".\functions.c"
+ >
+ <FileConfiguration
+ Name="Release|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\jitter.c"
+ >
+ <FileConfiguration
+ Name="Release|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\normal_lookup.c"
+ >
+ <FileConfiguration
+ Name="Release|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\Openclos.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Packet.c"
+ >
+ </File>
+ <File
+ RelativePath=".\Read.c"
+ >
+ </File>
+ <File
+ RelativePath=".\tcp_session.c"
+ >
+ <FileConfiguration
+ Name="Release|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\tme.c"
+ >
+ <FileConfiguration
+ Name="Release|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\win_bpf_filter.c"
+ >
+ </File>
+ <File
+ RelativePath=".\win_bpf_filter_init.c"
+ >
+ <FileConfiguration
+ Name="Release|x64"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath=".\Write.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\bucket_lookup.h"
+ >
+ </File>
+ <File
+ RelativePath=".\count_packets.h"
+ >
+ </File>
+ <File
+ RelativePath=".\dagc.h"
+ >
+ </File>
+ <File
+ RelativePath=".\DEBUG.H"
+ >
+ </File>
+ <File
+ RelativePath=".\Devioctl.h"
+ >
+ </File>
+ <File
+ RelativePath=".\functions.h"
+ >
+ </File>
+ <File
+ RelativePath=".\jitter.h"
+ >
+ </File>
+ <File
+ RelativePath=".\memory_t.h"
+ >
+ </File>
+ <File
+ RelativePath=".\normal_lookup.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Ntddndis.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Ntddpack.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Packet.h"
+ >
+ </File>
+ <File
+ RelativePath=".\Packet32.h"
+ >
+ </File>
+ <File
+ RelativePath=".\resource.h"
+ >
+ </File>
+ <File
+ RelativePath=".\resource1.h"
+ >
+ </File>
+ <File
+ RelativePath=".\tcp_session.h"
+ >
+ </File>
+ <File
+ RelativePath=".\time_calls.h"
+ >
+ </File>
+ <File
+ RelativePath=".\tme.h"
+ >
+ </File>
+ <File
+ RelativePath=".\valid_insns.h"
+ >
+ </File>
+ <File
+ RelativePath=".\win_bpf.h"
+ >
+ </File>
+ <File
+ RelativePath=".\win_bpf_filter_init.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ <File
+ RelativePath=".\See.rc"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/See/Write.c b/src/See/Write.c
new file mode 100644
index 00000000..a2f1244b
--- /dev/null
+++ b/src/See/Write.c
@@ -0,0 +1,426 @@
+/*
+ * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies
+ * nor the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <GlobalConst.h>
+
+#include "stdarg.h"
+#include "ntddk.h"
+#include "ntiologc.h"
+#include "ndis.h"
+
+#include "debug.h"
+#include "packet.h"
+
+
+void *test_addr = NULL;
+
+//-------------------------------------------------------------------
+
+NTSTATUS
+NPF_Write(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ )
+
+{
+ POPEN_INSTANCE Open;
+ PIO_STACK_LOCATION IrpSp;
+ PNDIS_PACKET pPacket;
+ UINT i;
+ NDIS_STATUS Status;
+
+ IF_LOUD(DbgPrint("NPF_Write\n");)
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+
+ Open=IrpSp->FileObject->FsContext;
+
+ if( Open->Bound == FALSE )
+ {
+ // The Network adapter was removed.
+ EXIT_FAILURE(0);
+ }
+
+ NdisAcquireSpinLock(&Open->WriteLock);
+ if(Open->WriteInProgress)
+ {
+ // Another write operation is currently in progress
+ NdisReleaseSpinLock(&Open->WriteLock);
+ EXIT_FAILURE(0);
+ }
+ else
+ {
+ Open->WriteInProgress = TRUE;
+ }
+
+ NdisReleaseSpinLock(&Open->WriteLock);
+
+ IF_LOUD(DbgPrint("Max frame size = %d, packet size = %d\n", Open->MaxFrameSize, IrpSp->Parameters.Write.Length);)
+
+
+ if(IrpSp->Parameters.Write.Length == 0 || // Check that the buffer provided by the user is not empty
+ Open->MaxFrameSize == 0/* || // Check that the MaxFrameSize is correctly initialized
+ IrpSp->Parameters.Write.Length > Open->MaxFrameSize*/) // Check that the fame size is smaller that the MTU
+ {
+ IF_LOUD(DbgPrint("frame size out of range, send aborted\n");)
+
+ EXIT_FAILURE(0);
+ }
+
+
+ IoMarkIrpPending(Irp);
+
+ Open->Multiple_Write_Counter=Open->Nwrites;
+
+ NdisResetEvent(&Open->WriteEvent);
+
+
+ for(i=0;i<Open->Nwrites;i++){
+
+ // Try to get a packet from our list of free ones
+ NdisAllocatePacket(
+ &Status,
+ &pPacket,
+ Open->PacketPool
+ );
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ // No free packets
+ Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
+ IoCompleteRequest (Irp, IO_NO_INCREMENT);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ if(Open->SkipSentPackets)
+ {
+ NdisSetPacketFlags(
+ pPacket,
+ g_SendPacketFlags);
+ }
+
+ // The packet hasn't a buffer that needs not to be freed after every single write
+ RESERVED(pPacket)->FreeBufAfterWrite = FALSE;
+
+ // Save the IRP associated with the packet
+ RESERVED(pPacket)->Irp=Irp;
+
+ // Attach the writes buffer to the packet
+ NdisChainBufferAtFront(pPacket,Irp->MdlAddress);
+
+ test_addr = MmGetMdlVirtualAddress(Irp->MdlAddress);
+
+ // Call the MAC
+ NdisSend(
+ &Status,
+ Open->AdapterHandle,
+ pPacket);
+
+ if (Status != NDIS_STATUS_PENDING) {
+ // The send didn't pend so call the completion handler now
+ NPF_SendComplete(
+ Open,
+ pPacket,
+ Status
+ );
+
+ }
+
+ if(i%100==99){
+ NdisWaitEvent(&Open->WriteEvent,1000);
+ NdisResetEvent(&Open->WriteEvent);
+ }
+ }
+
+ return(STATUS_PENDING);
+}
+
+//-------------------------------------------------------------------
+
+INT
+NPF_BufferedWrite(
+ IN PIRP Irp,
+ IN PCHAR UserBuff,
+ IN ULONG UserBuffSize,
+ BOOLEAN Sync)
+{
+ POPEN_INSTANCE Open;
+ PIO_STACK_LOCATION IrpSp;
+ PNDIS_PACKET pPacket;
+ NDIS_STATUS Status;
+ struct sf_pkthdr *winpcap_hdr;
+ PMDL TmpMdl;
+ PCHAR EndOfUserBuff = UserBuff + UserBuffSize;
+
+ IF_LOUD(DbgPrint("NPF: BufferedWrite, UserBuff=%x, Size=%u\n", UserBuff, UserBuffSize);)
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+ Open=IrpSp->FileObject->FsContext;
+
+ if( Open->Bound == FALSE ){
+ // The Network adapter was removed.
+ return 0;
+ }
+
+ // Sanity check on the user buffer
+ if(UserBuff == NULL)
+ {
+ return 0;
+ }
+
+ // Check that the MaxFrameSize is correctly initialized
+ if(Open->MaxFrameSize == 0)
+ {
+ IF_LOUD(DbgPrint("BufferedWrite: Open->MaxFrameSize not initialized, probably because of a problem in the OID query\n");)
+
+ return 0;
+ }
+
+ // Reset the event used to synchronize packet allocation
+ NdisResetEvent(&Open->WriteEvent);
+
+ // Reset the pending packets counter
+ Open->Multiple_Write_Counter = 0;
+
+ // Start from the first packet
+ winpcap_hdr = (struct sf_pkthdr*)UserBuff;
+
+ // Chech the consistency of the user buffer
+ if( (PCHAR)winpcap_hdr + winpcap_hdr->caplen + sizeof(struct sf_pkthdr) > EndOfUserBuff )
+ {
+ IF_LOUD(DbgPrint("Buffered Write: bogus packet buffer\n");)
+
+ return -1;
+ }
+
+ //
+ // Main loop: send the buffer to the wire
+ //
+ while(TRUE)
+ {
+
+ if(winpcap_hdr->caplen ==0/* || winpcap_hdr->caplen > Open->MaxFrameSize*/)
+ {
+ // Malformed header
+ IF_LOUD(DbgPrint("NPF_BufferedWrite: malformed or bogus user buffer, aborting write.\n");)
+
+ return -1;
+ }
+
+ // Allocate an MDL to map the packet data
+ TmpMdl = IoAllocateMdl((PCHAR)winpcap_hdr + sizeof(struct sf_pkthdr),
+ winpcap_hdr->caplen,
+ FALSE,
+ FALSE,
+ NULL);
+
+ if (TmpMdl == NULL)
+ {
+ // Unable to map the memory: packet lost
+ IF_LOUD(DbgPrint("NPF_BufferedWrite: unable to allocate the MDL.\n");)
+
+ return -1;
+ }
+
+ MmBuildMdlForNonPagedPool(TmpMdl); // XXX can this line be removed?
+
+ // Allocate a packet from our free list
+ NdisAllocatePacket( &Status, &pPacket, Open->PacketPool);
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+ // No more free packets
+ IF_LOUD(DbgPrint("NPF_BufferedWrite: no more free packets, returning.\n");)
+
+ NdisResetEvent(&Open->WriteEvent);
+
+ NdisWaitEvent(&Open->WriteEvent, 1000);
+
+ // Try again to allocate a packet
+ NdisAllocatePacket( &Status, &pPacket, Open->PacketPool);
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+ // Second failure, report an error
+ IoFreeMdl(TmpMdl);
+ return -1;
+ }
+
+// IoFreeMdl(TmpMdl);
+// return (PCHAR)winpcap_hdr - UserBuff;
+ }
+
+ if(Open->SkipSentPackets)
+ {
+ NdisSetPacketFlags(
+ pPacket,
+ g_SendPacketFlags);
+ }
+
+ // The packet has a buffer that needs to be freed after every single write
+ RESERVED(pPacket)->FreeBufAfterWrite = TRUE;
+
+ TmpMdl->Next = NULL;
+
+ // Attach the MDL to the packet
+ NdisChainBufferAtFront(pPacket, TmpMdl);
+
+ // Increment the number of pending sends
+ InterlockedIncrement(&Open->Multiple_Write_Counter);
+
+ // Call the MAC
+ NdisSend( &Status, Open->AdapterHandle, pPacket);
+
+ if (Status != NDIS_STATUS_PENDING) {
+ // The send didn't pend so call the completion handler now
+ NPF_SendComplete(
+ Open,
+ pPacket,
+ Status
+ );
+ }
+
+ // Step to the next packet in the buffer
+ (PCHAR)winpcap_hdr += winpcap_hdr->caplen + sizeof(struct sf_pkthdr);
+
+ // Check if the end of the user buffer has been reached
+ if( (PCHAR)winpcap_hdr >= EndOfUserBuff )
+ {
+ IF_LOUD(DbgPrint("NPF_BufferedWrite: End of buffer.\n");)
+
+ // Wait the completion of pending sends
+ NPF_WaitEndOfBufferedWrite(Open);
+
+ return (INT)((PCHAR)winpcap_hdr - UserBuff);
+ }
+
+ }
+
+ return (INT)((PCHAR)winpcap_hdr - UserBuff);
+}
+
+//-------------------------------------------------------------------
+
+VOID NPF_WaitEndOfBufferedWrite(POPEN_INSTANCE Open)
+{
+ UINT i;
+
+ NdisResetEvent(&Open->WriteEvent);
+
+ for(i=0; Open->Multiple_Write_Counter > 0 && i < TRANSMIT_PACKETS; i++)
+ {
+ NdisWaitEvent(&Open->WriteEvent, 100);
+ NdisResetEvent(&Open->WriteEvent);
+ }
+
+ return;
+}
+
+//-------------------------------------------------------------------
+
+VOID
+NPF_SendComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN PNDIS_PACKET pPacket,
+ IN NDIS_STATUS Status
+ )
+
+{
+ PIRP Irp;
+ PIO_STACK_LOCATION irpSp;
+ POPEN_INSTANCE Open;
+ PMDL TmpMdl;
+
+ IF_LOUD(DbgPrint("NPF: SendComplete, BindingContext=%d\n",ProtocolBindingContext);)
+
+ Open= (POPEN_INSTANCE)ProtocolBindingContext;
+
+ if( RESERVED(pPacket)->FreeBufAfterWrite )
+ {
+ //
+ // Packet sent by NPF_BufferedWrite()
+ //
+
+
+ // Free the MDL associated with the packet
+ NdisUnchainBufferAtFront(pPacket, &TmpMdl);
+
+ IoFreeMdl(TmpMdl);
+
+ // recyle the packet
+ // NdisReinitializePacket(pPacket);
+
+ NdisFreePacket(pPacket);
+
+ // Increment the number of pending sends
+ InterlockedDecrement(&Open->Multiple_Write_Counter);
+
+ NdisSetEvent(&Open->WriteEvent);
+
+ return;
+ }
+ else
+ {
+ //
+ // Packet sent by NPF_Write()
+ //
+
+ if((Open->Nwrites - Open->Multiple_Write_Counter) %100 == 99)
+ NdisSetEvent(&Open->WriteEvent);
+
+ Open->Multiple_Write_Counter--;
+
+ if(Open->Multiple_Write_Counter == 0){
+ // Release the buffer and awake the application
+ NdisUnchainBufferAtFront(pPacket, &TmpMdl);
+
+ // Complete the request
+ Irp=RESERVED(pPacket)->Irp;
+ irpSp = IoGetCurrentIrpStackLocation(Irp);
+
+ Irp->IoStatus.Status = Status;
+ Irp->IoStatus.Information = irpSp->Parameters.Write.Length;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ NdisAcquireSpinLock(&Open->WriteLock);
+ Open->WriteInProgress = FALSE;
+ NdisReleaseSpinLock(&Open->WriteLock);
+ }
+
+ // Put the packet back on the free list
+ NdisFreePacket(pPacket);
+
+ return;
+ }
+
+}
diff --git a/src/See/bucket_lookup.c b/src/See/bucket_lookup.c
new file mode 100644
index 00000000..569ce163
--- /dev/null
+++ b/src/See/bucket_lookup.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <GlobalConst.h>
+
+#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;
+ }
+}
diff --git a/src/See/bucket_lookup.h b/src/See/bucket_lookup.h
new file mode 100644
index 00000000..d8700b54
--- /dev/null
+++ b/src/See/bucket_lookup.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __bucket_lookup
+#define __bucket_lookup
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <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
diff --git a/src/See/count_packets.c b/src/See/count_packets.c
new file mode 100644
index 00000000..9e69241d
--- /dev/null
+++ b/src/See/count_packets.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <GlobalConst.h>
+
+#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/src/See/count_packets.h b/src/See/count_packets.h
new file mode 100644
index 00000000..9853bda3
--- /dev/null
+++ b/src/See/count_packets.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __count_packets
+#define __count_packets
+
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <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
+
diff --git a/src/See/dagc.h b/src/See/dagc.h
new file mode 100644
index 00000000..6162c4a3
--- /dev/null
+++ b/src/See/dagc.h
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define DAGC_ERRBUF_SIZE 512
+#define FILEBUFSIZE 65536
+#define MAXDAGCARDS 32
+
+#ifndef _WIN32
+
+typedef long long long_long;
+typedef long long ull_t;
+#define TRUE 1
+#define devicestring "/dev/dag%d"
+#define dagc_sleepms(_MS) usleep(_MS * 1000)
+#else /* _WIN32 */
+
+typedef LONGLONG long_long;
+typedef ULONGLONG ull_t;
+#define dagc_sleepms(_MS) Sleep(_MS)
+#define devicestring "\\\\.\\dag%d"
+
+#endif /* _WIN32 */
+
+#define MIN_DAG_SNAPLEN 12
+#define MAX_DAG_SNAPLEN 2040
+
+#define erffilestring "erffile://"
+
+
+#define ATM_SNAPLEN 48
+/* Size of ATM payload */
+#define ATM_WLEN(h) ATM_SNAPLEN
+#define ATM_SLEN(h) ATM_SNAPLEN
+
+/* Size Ethernet payload */
+#define ETHERNET_WLEN(h, b) ((u_int)ntohs((h)->wlen) - ((b) >> 3))
+#define ETHERNET_SLEN(h, b) min(ETHERNET_WLEN(h, b), \
+ (u_int)ntohs((h)->rlen) - dag_record_size - 2)
+
+/* Size of HDLC payload */
+#define HDLC_WLEN(h, b) ((u_int)ntohs((h)->wlen) - ((b) >> 3))
+#define HDLC_SLEN(h, b) min(HDLC_WLEN(h, b), \
+ (u_int)ntohs((h)->rlen) - dag_record_size)
+
+/* Flags for dagc_open */
+#define DAGC_OPEN_SHARED 1
+#define DAGC_OPEN_EXCLUSIVE 2
+
+#define TYPE_LEGACY 0
+#define TYPE_HDLC_POS 1
+#define TYPE_ETH 2
+#define TYPE_ATM 3
+#define TYPE_AAL5 4
+
+/*
+ * Card statistics.
+ */
+typedef struct dagc_stats_t
+{
+ ull_t received; /* (NOT IMPLEMENTED) total number of frames received by the DAG */
+ ull_t dropped; /* number of frames dropped for buffer full */
+ ull_t captured; /* (NOT IMPLEMENTED) number of frames that actually reach the
+ application, i.e that are not filtered or dropped */
+} dagc_stats_t;
+
+/*
+ * Descriptor of an open session.
+ * Note: the dagc_t descriptor is completely opaque to the application. It can be compared
+ * to a file descriptor.
+ */
+typedef struct dagc dagc_t;
+
+/*
+ * Card description.
+ */
+typedef struct dagc_if_t
+{
+ struct dagc_if_t *next;
+ char *name; /* pointer to a string to pass to dagc_open*/
+ char *description; /* human-understandable description (e.g. Endace 3.5e Fast
+ Ethernet Card) */
+} dagc_if_t;
+
+
+
+/*
+ * returns a string with last dagc lib error
+ */
+#define dagc_getlasterror(dagcfd) dagcfd->errbuf
+
+/*
+ * returns a linked list with the cards available on the systems. For every card, it scans the
+ * card type and converts it to a human-understandable string, in order to provide a description
+ * useful for example when a system has more than one card
+ */
+int dagc_finddevs (dagc_if_t **alldevsp, char *ebuf);
+
+
+/*
+ * frees the card list.
+ */
+void dagc_freedevs (dagc_if_t *alldevsp);
+
+
+/*
+ * Opens a card (or a file) for capture. Snaplen is the portion of packet delivered to the
+ * application, flags can contain specific settings (for example promisc mode??), minbufsize
+ * is the smallest buffer that the API can provide to the application (to limit CPU waste
+ * with several small buffers under moderated network throughputs)
+ */
+dagc_t* dagc_open(const char *source, unsigned flags, char *ebuf);
+
+/*
+ * Sets the snaplen of a card
+ * Returns -1 on failure. On success, the actual snaplen is returned (snap len has to be a multiple of 4
+ * with DAG cards).
+ */
+int dagc_setsnaplen(dagc_t *dagcfd, unsigned snaplen);
+
+/*
+ * closes a capture instance
+ */
+void dagc_close(dagc_t *dagcfd);
+
+
+/*
+ * returns the linktype of a card
+ */
+int dagc_getlinktype(dagc_t *dagcfd);
+
+
+/*
+ * returns the link speed of the adapter, in MB/s.
+ * If the link speed of the card is unknown, -1 is returned.
+ * XXX NOTE: Currently, there is no consistent way to get linkspeed querying the card.
+ * As a consequence, we determine this value statically from the card model. For cards that can run at
+ * different speeds, we report only the *maximum* speed.
+ */
+int dagc_getlinkspeed(dagc_t *dagcfd);
+
+
+/*
+ * Returns the length of the CRC checksum that the card associates with any packet in the hole. This
+ * information will be used to understand the actual length of the packet on the wire.
+ * Note: this information is not provided consistently by DAG cards, so we gather it from an environment
+ * variable in Unix and from a registry key in Windows.
+ */
+unsigned dagc_getfcslen(dagc_t *dagcfd);
+
+/*
+ * provides a buffer with the new packets (from the board or from the file) and its size.
+ * On success, the return value is 0. If an error has occurred, the return value is -1.
+ * If EOF has reached, the return value is -2. Note that this function always returns
+ * immediately, eventually with an empty buffer, so it is possible to have a success (0)
+ * return value and bufsize = 0.
+ */
+int dagc_receive(dagc_t *dagcfd, u_char **buffer, u_int *bufsize);
+
+
+/*
+ * returns nonzero if any data is available from dagcfd, -1 if an error occurred. Waits until almost the time
+ * specified by timeout has past or any data is available. If timeout=0, returns immediately.
+ * If timeout=NULL, blocks until a packet arrives.
+ */
+int dagc_wait(dagc_t *dagcfd, struct timeval *timeout);
+
+
+/*
+ * returns statistics about current capture session
+ */
+int dagc_stats(dagc_t *dagcfd, dagc_stats_t *ps);
+
+
+/*
+ * Opens a dump file to store the data of this capture.
+ * Returns 0 on success.
+ * NOTE: currently, dagc_dumpfile_open, dagc_dumpfile_close and dagc_dump are simply wrappers
+ * for open, close and write. However, if the programmer uses these functions, he is more protected
+ * against file format changes (for example if the file format will have an header in the future).
+ * Moreover, assuming that the user knows the file format is a bad practice: providing
+ * simple simple save functionality is more intutive and user-friendly.
+ */
+int dagc_dumpfile_open(dagc_t *dagcfd, char* name);
+
+
+/*
+ * Closes a dump file
+ */
+int dagc_dumpfile_close(dagc_t *dagcfd);
+
+
+/*
+ * Writes a buffer of packets to a dump file
+ * Returns 0 on success.
+ */
+int dagc_dump(dagc_t *dagcfd, u_char *buffer, u_int bufsize);
diff --git a/src/See/dump.c b/src/See/dump.c
new file mode 100644
index 00000000..e60aa6cb
--- /dev/null
+++ b/src/See/dump.c
@@ -0,0 +1,570 @@
+/*
+ * Copyright (c) 1999 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <GlobalConst.h>
+
+#include <stdarg.h>
+#include <ntddk.h>
+#include <ntiologc.h>
+#include <ndis.h>
+#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;
+
+ IF_LOUD(DbgPrint("NPF: OpenDumpFile.\n");)
+
+ if(fileName->Buffer[0] == L'\\' &&
+ fileName->Buffer[1] == L'?' &&
+ fileName->Buffer[2] == L'?' &&
+ fileName->Buffer[3] == L'\\'
+ ){
+ PathLen = 0;
+ }
+ else{
+ PathPrefix = L"\\??\\";
+ PathLen = 8;
+ }
+
+ // Insert the correct path prefix.
+ FullFileNameLength = PathLen + fileName->MaximumLength;
+
+ FullFileName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
+ FullFileNameLength,
+ '0DWA');
+
+ if (FullFileName.Buffer == NULL) {
+ ntStatus = STATUS_INSUFFICIENT_RESOURCES;
+ return ntStatus;
+ }
+
+ FullFileName.Length = PathLen;
+ FullFileName.MaximumLength = (USHORT)FullFileNameLength;
+
+ if(PathLen)
+ RtlMoveMemory (FullFileName.Buffer, PathPrefix, PathLen);
+
+ RtlAppendUnicodeStringToString (&FullFileName, fileName);
+
+ IF_LOUD(DbgPrint( "Packet: Attempting to open %wZ\n", &FullFileName);)
+
+ InitializeObjectAttributes ( &ObjectAttributes,
+ &FullFileName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL );
+
+ // Create the dump file
+ ntStatus = ZwCreateFile( &Open->DumpFileHandle,
+ SYNCHRONIZE | FILE_WRITE_DATA,
+ &ObjectAttributes,
+ &IoStatus,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ,
+ (Append)?FILE_OPEN_IF:FILE_SUPERSEDE,
+ FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL,
+ 0 );
+
+ if ( !NT_SUCCESS( ntStatus ) )
+ {
+ IF_LOUD(DbgPrint("NPF: Error opening file %x\n", ntStatus);)
+
+ ExFreePool(FullFileName.Buffer);
+ Open->DumpFileHandle=NULL;
+ ntStatus = STATUS_NO_SUCH_FILE;
+ return ntStatus;
+ }
+
+ ExFreePool(FullFileName.Buffer);
+
+ ntStatus = ObReferenceObjectByHandle(Open->DumpFileHandle,
+ FILE_WRITE_ACCESS,
+ *IoFileObjectType,
+ KernelMode,
+ &Open->DumpFileObject,
+ 0);
+
+ if ( !NT_SUCCESS( ntStatus ) )
+ {
+ IF_LOUD(DbgPrint("NPF: Error creating file, status=%x\n", ntStatus);)
+
+ ZwClose( Open->DumpFileHandle );
+ Open->DumpFileHandle=NULL;
+
+ ntStatus = STATUS_NO_SUCH_FILE;
+ return ntStatus;
+ }
+
+ fsdDevice = IoGetRelatedDeviceObject(Open->DumpFileObject);
+
+ IF_LOUD(DbgPrint("NPF: Dump: write file created succesfully, status=%d \n",ntStatus);)
+
+ return ntStatus;
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS
+NPF_StartDump(POPEN_INSTANCE Open)
+{
+ NTSTATUS ntStatus;
+ struct packet_file_header hdr;
+ IO_STATUS_BLOCK IoStatus;
+
+ IF_LOUD(DbgPrint("NPF: StartDump.\n");)
+
+ // Init the file header
+ hdr.magic = TCPDUMP_MAGIC;
+ hdr.version_major = PCAP_VERSION_MAJOR;
+ hdr.version_minor = PCAP_VERSION_MINOR;
+ hdr.thiszone = 0; /*Currently not set*/
+ hdr.snaplen = 1514;
+ hdr.sigfigs = 0;
+
+ // Detect the medium type
+ switch (Open->Medium){
+
+ case NdisMediumWan:
+ hdr.linktype = DLT_EN10MB;
+ break;
+
+ case NdisMedium802_3:
+ hdr.linktype = DLT_EN10MB;
+ break;
+
+ case NdisMediumFddi:
+ hdr.linktype = DLT_FDDI;
+ break;
+
+ case NdisMedium802_5:
+ hdr.linktype = DLT_IEEE802;
+ break;
+
+ case NdisMediumArcnet878_2:
+ hdr.linktype = DLT_ARCNET;
+ break;
+
+ case NdisMediumAtm:
+ hdr.linktype = DLT_ATM_RFC1483;
+ break;
+
+ default:
+ hdr.linktype = DLT_EN10MB;
+ }
+
+ // Write the header.
+ // We can use ZwWriteFile because we are in the context of the application
+ ntStatus = ZwWriteFile(Open->DumpFileHandle,
+ NULL,
+ NULL,
+ NULL,
+ &IoStatus,
+ &hdr,
+ sizeof(hdr),
+ NULL,
+ NULL );
+
+
+ if ( !NT_SUCCESS( ntStatus ) )
+ {
+ IF_LOUD(DbgPrint("NPF: Error dumping file %x\n", ntStatus);)
+
+ ZwClose( Open->DumpFileHandle );
+ Open->DumpFileHandle=NULL;
+
+ ntStatus = STATUS_NO_SUCH_FILE;
+ return ntStatus;
+ }
+
+ Open->DumpOffset.QuadPart=24;
+
+ ntStatus = PsCreateSystemThread(&Open->DumpThreadHandle,
+ THREAD_ALL_ACCESS,
+ (ACCESS_MASK)0L,
+ 0,
+ 0,
+ NPF_DumpThread,
+ Open);
+
+ if ( !NT_SUCCESS( ntStatus ) )
+ {
+ IF_LOUD(DbgPrint("NPF: Error creating dump thread, status=%x\n", ntStatus);)
+
+ ZwClose( Open->DumpFileHandle );
+ Open->DumpFileHandle=NULL;
+
+ return ntStatus;
+ }
+
+ ntStatus = ObReferenceObjectByHandle(Open->DumpThreadHandle,
+ THREAD_ALL_ACCESS,
+ NULL,
+ KernelMode,
+ &Open->DumpThreadObject,
+ 0);
+
+ if ( !NT_SUCCESS( ntStatus ) )
+ {
+ IF_LOUD(DbgPrint("NPF: Error creating dump thread, status=%x\n", ntStatus);)
+
+ ObDereferenceObject(Open->DumpFileObject);
+ ZwClose( Open->DumpFileHandle );
+ Open->DumpFileHandle=NULL;
+
+ return ntStatus;
+ }
+
+
+ return ntStatus;
+
+}
+
+//-------------------------------------------------------------------
+// Dump Thread
+//-------------------------------------------------------------------
+
+VOID NPF_DumpThread(POPEN_INSTANCE Open)
+{
+// ULONG FrozenNic;
+
+ IF_LOUD(DbgPrint("NPF: In the work routine. Parameter = 0x%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->Size==0){ // BufSize=0 means that this instance was closed, or that the buffer is too
+ // small for any capture. In both cases it is better to end the dump
+
+ IF_LOUD(DbgPrint("NPF: Worker Thread - Exiting happily\n");)
+ IF_LOUD(DbgPrint("Thread: Dumpoffset=%I64d\n",Open->DumpOffset.QuadPart);)
+
+ PsTerminateSystemThread(STATUS_SUCCESS);
+ return;
+ }
+
+ NdisResetEvent(&Open->DumpEvent);
+
+ // Write the content of the buffer to the file
+ if(NPF_SaveCurrentBuffer(Open) != STATUS_SUCCESS){
+ PsTerminateSystemThread(STATUS_SUCCESS);
+ return;
+ }
+
+ }
+
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS NPF_SaveCurrentBuffer(POPEN_INSTANCE Open)
+{
+#if 0
+
+ Thead=Open->Bhead;
+ Ttail=Open->Btail;
+ TLastByte=Open->BLastByte;
+
+ IF_LOUD(DbgPrint("NPF: NPF_SaveCurrentBuffer.\n");)
+
+ // Get the address of the buffer
+ CurrBuff=Open->Buffer;
+ //
+ // Fill the application buffer
+ //
+ if( Ttail < Thead )
+ {
+ if(Open->MaxDumpBytes &&
+ (UINT)Open->DumpOffset.QuadPart /*+ GetBuffOccupation(Open)*/ > Open->MaxDumpBytes)
+ {
+ // Size limit reached
+ UINT PktLen;
+
+ SizeToDump = 0;
+
+ // Scan the buffer to detect the exact amount of data to save
+ while(TRUE){
+ PktLen = ((struct sf_pkthdr*)(CurrBuff + Thead + SizeToDump))->caplen + sizeof(struct sf_pkthdr);
+
+ if((UINT)Open->DumpOffset.QuadPart + SizeToDump + PktLen > Open->MaxDumpBytes)
+ break;
+
+ SizeToDump += PktLen;
+ }
+
+ }
+ else
+ SizeToDump = TLastByte-Thead;
+
+ lMdl=IoAllocateMdl(CurrBuff+Thead, SizeToDump, FALSE, FALSE, NULL);
+ if (lMdl == NULL)
+ {
+ // No memory: stop dump
+ IF_LOUD(DbgPrint("NPF: dump thread: Failed to allocate Mdl\n");)
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ MmBuildMdlForNonPagedPool(lMdl);
+
+ // Write to disk
+ NPF_WriteDumpFile(Open->DumpFileObject,
+ &Open->DumpOffset,
+ SizeToDump,
+ lMdl,
+ &IoStatus);
+
+ IoFreeMdl(lMdl);
+
+ if(!NT_SUCCESS(IoStatus.Status)){
+ // Error
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if(SizeToDump != TLastByte-Thead){
+ // Size limit reached.
+ Open->DumpLimitReached = TRUE;
+
+ // Awake the application
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ // Update the packet buffer
+ Open->DumpOffset.QuadPart+=(TLastByte-Thead);
+ Open->BLastByte=Ttail;
+ Open->Bhead=0;
+ }
+
+ if( Ttail > Thead ){
+
+ if(Open->MaxDumpBytes &&
+ (UINT)Open->DumpOffset.QuadPart /* +GetBuffOccupation(Open)*/ > Open->MaxDumpBytes)
+ {
+ // Size limit reached
+ UINT PktLen;
+
+ SizeToDump = 0;
+
+ // Scan the buffer to detect the exact amount of data to save
+ while(Thead + SizeToDump < Ttail){
+
+ PktLen = ((struct sf_pkthdr*)(CurrBuff + Thead + SizeToDump))->caplen + sizeof(struct sf_pkthdr);
+
+ if((UINT)Open->DumpOffset.QuadPart + SizeToDump + PktLen > Open->MaxDumpBytes)
+ break;
+
+ SizeToDump += PktLen;
+ }
+
+ }
+ else
+ SizeToDump = Ttail-Thead;
+
+ lMdl=IoAllocateMdl(CurrBuff+Thead, SizeToDump, FALSE, FALSE, NULL);
+ if (lMdl == NULL)
+ {
+ // No memory: stop dump
+ IF_LOUD(DbgPrint("NPF: dump thread: Failed to allocate Mdl\n");)
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ MmBuildMdlForNonPagedPool(lMdl);
+
+ // Write to disk
+ NPF_WriteDumpFile(Open->DumpFileObject,
+ &Open->DumpOffset,
+ SizeToDump,
+ lMdl,
+ &IoStatus);
+
+ IoFreeMdl(lMdl);
+
+ if(!NT_SUCCESS(IoStatus.Status)){
+ // Error
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ if(SizeToDump != Ttail-Thead){
+ // Size limit reached.
+ Open->DumpLimitReached = TRUE;
+
+ // Awake the application
+ KeSetEvent(Open->ReadEvent,0,FALSE);
+
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ // Update the packet buffer
+ Open->DumpOffset.QuadPart+=(Ttail-Thead);
+ Open->Bhead=Ttail;
+
+ }
+#endif
+ return STATUS_SUCCESS;
+}
+
+//-------------------------------------------------------------------
+
+NTSTATUS NPF_CloseDumpFile(POPEN_INSTANCE Open){
+#if 0
+ IF_LOUD(DbgPrint("NPF: NPF_CloseDumpFile.\n");)
+ IF_LOUD(DbgPrint("Dumpoffset=%d\n",Open->DumpOffset.QuadPart);)
+
+DbgPrint("1\n");
+ // Consistency check
+ if(Open->DumpFileHandle == NULL)
+ return STATUS_UNSUCCESSFUL;
+
+DbgPrint("2\n");
+ ZwClose( Open->DumpFileHandle );
+
+ ObDereferenceObject(Open->DumpFileObject);
+/*
+ if(Open->DumpLimitReached == TRUE)
+ // Limit already reached: don't save the rest of the buffer.
+ return STATUS_SUCCESS;
+*/
+DbgPrint("3\n");
+
+ NPF_OpenDumpFile(Open,&Open->DumpFileName, TRUE);
+
+ // Flush the buffer to file
+ NPF_SaveCurrentBuffer(Open);
+
+ // Close The file
+ ObDereferenceObject(Open->DumpFileObject);
+ ZwClose( Open->DumpFileHandle );
+
+ Open->DumpFileHandle = NULL;
+
+ ObDereferenceObject(Open->DumpFileObject);
+#endif
+ return STATUS_SUCCESS;
+}
+
+//-------------------------------------------------------------------
+
+static NTSTATUS PacketDumpCompletion(PDEVICE_OBJECT DeviceObject,
+ PIRP Irp,
+ PVOID Context)
+{
+
+ // 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);
+
+ // 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/src/See/functions.c b/src/See/functions.c
new file mode 100644
index 00000000..e6817343
--- /dev/null
+++ b/src/See/functions.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 1999 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <GlobalConst.h>
+
+#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/src/See/functions.h b/src/See/functions.h
new file mode 100644
index 00000000..9715ce10
--- /dev/null
+++ b/src/See/functions.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 1999 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __FUNCTIONS
+#define __FUNCTIONS
+
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <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
diff --git a/src/See/jitter.c b/src/See/jitter.c
new file mode 100644
index 00000000..b3bf8cb4
--- /dev/null
+++ b/src/See/jitter.c
@@ -0,0 +1,687 @@
+/*
+ * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies
+ * nor the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <GlobalConst.h>
+
+#include "stdarg.h"
+#include "ntddk.h"
+#include "ntiologc.h"
+#include "ndis.h"
+
+#include "packet.h"
+#include "win_bpf.h"
+#include "jitter.h"
+
+//
+// emit routine to update the jump table
+//
+void emit_lenght(binary_stream *stream, ULONG value, UINT len)
+{
+ (stream->refs)[stream->bpf_pc]+=len;
+ stream->cur_ip+=len;
+}
+
+//
+// emit routine to output the actual binary code
+//
+void emit_code(binary_stream *stream, ULONG value, UINT len)
+{
+
+ switch (len){
+
+ case 1:
+ stream->ibuf[stream->cur_ip]=(UCHAR)value;
+ stream->cur_ip++;
+ break;
+
+ case 2:
+ *((USHORT*)(stream->ibuf+stream->cur_ip))=(USHORT)value;
+ stream->cur_ip+=2;
+ break;
+
+ case 4:
+ *((ULONG*)(stream->ibuf+stream->cur_ip))=value;
+ stream->cur_ip+=4;
+ break;
+
+ default:;
+
+ }
+
+ return;
+
+}
+
+//
+// Function that does the real stuff
+//
+BPF_filter_function BPFtoX86(struct bpf_insn *prog, UINT nins, INT *mem)
+{
+ struct bpf_insn *ins;
+ UINT i, pass;
+ binary_stream stream;
+
+ //NOTE: do not modify the name of this variable, as it's used by the macros to emit code.
+ emit_func emitm;
+
+
+ // Allocate the reference table for the jumps
+#ifdef NTKERNEL
+ stream.refs=(UINT *)ExAllocatePoolWithTag(NonPagedPool, (nins + 1)*sizeof(UINT), '0JWA');
+#else
+ stream.refs=(UINT *)malloc((nins + 1)*sizeof(UINT));
+#endif
+ if(stream.refs==NULL)
+ {
+ return NULL;
+ }
+
+ // Reset the reference table
+ for(i=0; i< nins + 1; i++)
+ stream.refs[i]=0;
+
+ stream.cur_ip=0;
+ stream.bpf_pc=0;
+
+ // the first pass will emit the lengths of the instructions
+ // to create the reference table
+ emitm=emit_lenght;
+
+ for(pass=0;;){
+
+ ins = prog;
+
+ /* create the procedure header */
+ PUSH(EBP)
+ MOVrd(EBP,ESP)
+ PUSH(EBX)
+ PUSH(ECX)
+ PUSH(EDX)
+ PUSH(ESI)
+ PUSH(EDI)
+ MOVodd(EBX, EBP, 8)
+
+ for(i=0;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);
+#endif
+ return NULL;
+ }
+
+ return Filter;
+
+}
+
+//////////////////////////////////////////////////////////////
+
+void BPF_Destroy_JIT_Filter(JIT_BPF_Filter *Filter){
+
+#ifdef NTKERNEL
+ ExFreePool(Filter->mem);
+ ExFreePool(Filter->Function);
+ ExFreePool(Filter);
+#else
+ free(Filter->mem);
+ free(Filter->Function);
+ free(Filter);
+#endif
+
+}
diff --git a/src/See/jitter.h b/src/See/jitter.h
new file mode 100644
index 00000000..82edea74
--- /dev/null
+++ b/src/See/jitter.h
@@ -0,0 +1,404 @@
+/*
+ * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies
+ * nor the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+/** @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 (__cdecl *BPF_filter_function)( PVOID *, ULONG, UINT);
+
+/*! \brief Prototype of the emit functions.
+
+ Different emit functions are used to create the reference table and to generate the actual filtering code.
+ This allows to have simpler instruction macros.
+ The first parameter is the stream that will receive the data. The secon one is a variable containing
+ the data, the third one is the length, that can be 1,2 or 4 since it is possible to emit a byte, a short
+ or a work at a time.
+*/
+typedef void (*emit_func)(binary_stream *stream, ULONG value, UINT n);
+
+/*! \brief Structure describing a x86 filtering program created by the jitter.*/
+typedef struct JIT_BPF_Filter{
+ BPF_filter_function Function; ///< The x86 filtering binary, in the form of a BPF_filter_function.
+ PINT mem;
+}
+JIT_BPF_Filter;
+
+
+
+
+/**************************/
+/* X86 INSTRUCTION MACROS */
+/**************************/
+
+/// mov r32,i32
+#define MOVid(r32, i32) \
+ emitm(&stream, 11 << 4 | 1 << 3 | r32 & 0x7, 1); emitm(&stream, i32, 4);
+
+/// mov dr32,sr32
+#define MOVrd(dr32, sr32) \
+ emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
+
+/// mov dr32,sr32[off]
+#define MOVodd(dr32, sr32, off) \
+ emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \
+ emitm(&stream, 1 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);\
+ emitm(&stream, off, 1);
+
+/// mov dr32,sr32[or32]
+#define MOVobd(dr32, sr32, or32) \
+ emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \
+ emitm(&stream, (dr32 & 0x7) << 3 | 4 , 1);\
+ emitm(&stream, (or32 & 0x7) << 3 | (sr32 & 0x7) , 1);
+
+/// mov dr16,sr32[or32]
+#define MOVobw(dr32, sr32, or32) \
+ emitm(&stream, 0x66, 1); \
+ emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \
+ emitm(&stream, (dr32 & 0x7) << 3 | 4 , 1);\
+ emitm(&stream, (or32 & 0x7) << 3 | (sr32 & 0x7) , 1);
+
+/// mov dr8,sr32[or32]
+#define MOVobb(dr8, sr32, or32) \
+ emitm(&stream, 0x8a, 1); \
+ emitm(&stream, (dr8 & 0x7) << 3 | 4 , 1);\
+ emitm(&stream, (or32 & 0x7) << 3 | (sr32 & 0x7) , 1);
+
+/// mov [dr32][or32],sr32
+#define MOVomd(dr32, or32, sr32) \
+ emitm(&stream, 0x89, 1); \
+ emitm(&stream, (sr32 & 0x7) << 3 | 4 , 1);\
+ emitm(&stream, (or32 & 0x7) << 3 | (dr32 & 0x7) , 1);
+
+/// bswap dr32
+#define BSWAP(dr32) \
+ emitm(&stream, 0xf, 1); \
+ emitm(&stream, 0x19 << 3 | dr32 , 1);
+
+/// xchg al,ah
+#define SWAP_AX() \
+ emitm(&stream, 0x86, 1); \
+ emitm(&stream, 0xc4 , 1);
+
+/// push r32
+#define PUSH(r32) \
+ emitm(&stream, 5 << 4 | 0 << 3 | r32 & 0x7, 1);
+
+/// pop r32
+#define POP(r32) \
+ emitm(&stream, 5 << 4 | 1 << 3 | r32 & 0x7, 1);
+
+/// ret
+#define RET() \
+ emitm(&stream, 12 << 4 | 0 << 3 | 3, 1);
+
+/// add dr32,sr32
+#define ADDrd(dr32, sr32) \
+ emitm(&stream, 0x03, 1);\
+ emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | (sr32 & 0x7), 1);
+
+/// add eax,i32
+#define ADD_EAXi(i32) \
+ emitm(&stream, 0x05, 1);\
+ emitm(&stream, i32, 4);
+
+/// add r32,i32
+#define ADDid(r32, i32) \
+ emitm(&stream, 0x81, 1);\
+ emitm(&stream, 24 << 3 | r32, 1);\
+ emitm(&stream, i32, 4);
+
+/// add r32,i8
+#define ADDib(r32, i8) \
+ emitm(&stream, 0x83, 1);\
+ emitm(&stream, 24 << 3 | r32, 1);\
+ emitm(&stream, i8, 1);
+
+/// sub dr32,sr32
+#define SUBrd(dr32, sr32) \
+ emitm(&stream, 0x2b, 1);\
+ emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | (sr32 & 0x7), 1);
+
+/// sub eax,i32
+#define SUB_EAXi(i32) \
+ emitm(&stream, 0x2d, 1);\
+ emitm(&stream, i32, 4);
+
+/// mul r32
+#define MULrd(r32) \
+ emitm(&stream, 0xf7, 1);\
+ emitm(&stream, 7 << 5 | (r32 & 0x7), 1);
+
+/// div r32
+#define DIVrd(r32) \
+ emitm(&stream, 0xf7, 1);\
+ emitm(&stream, 15 << 4 | (r32 & 0x7), 1);
+
+/// and r8,i8
+#define ANDib(r8, i8) \
+ emitm(&stream, 0x80, 1);\
+ emitm(&stream, 7 << 5 | r8, 1);\
+ emitm(&stream, i8, 1);
+
+/// and r32,i32
+#define ANDid(r32, i32) \
+ if (r32 == EAX){ \
+ emitm(&stream, 0x25, 1);\
+ emitm(&stream, i32, 4);}\
+ else{ \
+ emitm(&stream, 0x81, 1);\
+ emitm(&stream, 7 << 5 | r32, 1);\
+ emitm(&stream, i32, 4);}
+
+/// and dr32,sr32
+#define ANDrd(dr32, sr32) \
+ emitm(&stream, 0x23, 1);\
+ emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
+
+/// or dr32,sr32
+#define ORrd(dr32, sr32) \
+ emitm(&stream, 0x0b, 1);\
+ emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
+
+/// or r32,i32
+#define ORid(r32, i32) \
+ if (r32 == EAX){ \
+ emitm(&stream, 0x0d, 1);\
+ emitm(&stream, i32, 4);}\
+ else{ \
+ emitm(&stream, 0x81, 1);\
+ emitm(&stream, 25 << 3 | r32, 1);\
+ emitm(&stream, i32, 4);}
+
+/// shl r32,i8
+#define SHLib(r32, i8) \
+ emitm(&stream, 0xc1, 1);\
+ emitm(&stream, 7 << 5 | r32 & 0x7, 1);\
+ emitm(&stream, i8, 1);
+
+/// shl dr32,cl
+#define SHL_CLrb(dr32) \
+ emitm(&stream, 0xd3, 1);\
+ emitm(&stream, 7 << 5 | dr32 & 0x7, 1);
+
+/// shr r32,i8
+#define SHRib(r32, i8) \
+ emitm(&stream, 0xc1, 1);\
+ emitm(&stream, 29 << 3 | r32 & 0x7, 1);\
+ emitm(&stream, i8, 1);
+
+/// shr dr32,cl
+#define SHR_CLrb(dr32) \
+ emitm(&stream, 0xd3, 1);\
+ emitm(&stream, 29 << 3 | dr32 & 0x7, 1);
+
+/// neg r32
+#define NEGd(r32) \
+ emitm(&stream, 0xf7, 1);\
+ emitm(&stream, 27 << 3 | r32 & 0x7, 1);
+
+/// cmp dr32,sr32[off]
+#define CMPodd(dr32, sr32, off) \
+ emitm(&stream, 3 << 4 | 3 | 1 << 3, 1); \
+ emitm(&stream, 1 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);\
+ emitm(&stream, off, 1);
+
+/// cmp dr32,sr32
+#define CMPrd(dr32, sr32) \
+ emitm(&stream, 0x3b, 1); \
+ emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
+
+/// cmp dr32,i32
+#define CMPid(dr32, i32) \
+ if (dr32 == EAX){ \
+ emitm(&stream, 0x3d, 1); \
+ emitm(&stream, i32, 4);} \
+ else{ \
+ emitm(&stream, 0x81, 1); \
+ emitm(&stream, 0x1f << 3 | (dr32 & 0x7), 1);\
+ emitm(&stream, i32, 4);}
+
+/// jne off32
+#define JNEb(off8) \
+ emitm(&stream, 0x75, 1);\
+ emitm(&stream, off8, 1);
+
+/// 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 *ins, UINT nins, INT *mem);
+/*!
+ \brief Deletes a filtering function that was previously created by BPF_jitter().
+ \param Filter The filter to destroy.
+
+ This function frees the variuos buffers (code, memory, etc.) associated with a filtering function.
+*/
+void BPF_Destroy_JIT_Filter(JIT_BPF_Filter *Filter);
+
+/**
+ * @}
+ */
+
+/**
+ * @}
+ */
diff --git a/src/See/memory_t.h b/src/See/memory_t.h
new file mode 100644
index 00000000..ab3c85db
--- /dev/null
+++ b/src/See/memory_t.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __memory_t
+#define __memory_t
+
+#define uint8 UCHAR
+#define int8 CHAR
+#define uint16 USHORT
+#define int16 SHORT
+#define uint32 ULONG
+#define int32 LONG
+#define uint64 ULONGLONG
+#define int64 LONGLONG
+
+/*memory type*/
+typedef struct __MEM_TYPE
+{
+ uint8 *buffer;
+ uint32 size;
+} MEM_TYPE, *PMEM_TYPE;
+
+#define LONG_AT(base,offset) (*(int32*)((uint8*)base+(uint32)offset))
+
+#define ULONG_AT(base,offset) (*(uint32*)((uint8*)base+(uint32)offset))
+
+#define SHORT_AT(base,offset) (*(int16*)((uint8*)base+(uint32)offset))
+
+#define USHORT_AT(base,offset) (*(uint16*)((uint8*)base+(uint32)offset))
+
+__inline int32 SW_LONG_AT(void *b, uint32 c)
+{
+ return ((int32)*((uint8 *)b+c)<<24|
+ (int32)*((uint8 *)b+c+1)<<16|
+ (int32)*((uint8 *)b+c+2)<<8|
+ (int32)*((uint8 *)b+c+3)<<0);
+}
+
+
+__inline uint32 SW_ULONG_AT(void *b, uint32 c)
+{
+ return ((uint32)*((uint8 *)b+c)<<24|
+ (uint32)*((uint8 *)b+c+1)<<16|
+ (uint32)*((uint8 *)b+c+2)<<8|
+ (uint32)*((uint8 *)b+c+3)<<0);
+}
+
+__inline int16 SW_SHORT_AT(void *b, uint32 os)
+{
+ return ((int16)
+ ((int16)*((uint8 *)b+os+0)<<8|
+ (int16)*((uint8 *)b+os+1)<<0));
+}
+
+__inline uint16 SW_USHORT_AT(void *b, uint32 os)
+{
+ return ((uint16)
+ ((uint16)*((uint8 *)b+os+0)<<8|
+ (uint16)*((uint8 *)b+os+1)<<0));
+}
+
+__inline VOID SW_ULONG_ASSIGN(void *dst, uint32 src)
+{
+ *((uint8*)dst+0)=*((uint8*)&src+3);
+ *((uint8*)dst+1)=*((uint8*)&src+2);
+ *((uint8*)dst+2)=*((uint8*)&src+1);
+ *((uint8*)dst+3)=*((uint8*)&src+0);
+
+}
+
+#ifdef WIN_NT_DRIVER
+
+#define ALLOCATE_MEMORY(dest,type,amount) \
+ (dest)=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);
+
+#else
+
+#define ALLOCATE_MEMORY(dest,type,amount) \
+ (dest)=(type*)GlobalAlloc(GPTR, sizeof(type)*(amount));
+#define ALLOCATE_ZERO_MEMORY(dest,type,amount) \
+ (dest)=(type*)GlobalAlloc(GPTR, sizeof(type)*(amount));
+
+#define FREE_MEMORY(dest) GlobalFree(dest);
+#define ZERO_MEMORY(dest,amount) RtlZeroMemory(dest,amount);
+#define COPY_MEMORY(dest,src,amount) RtlCopyMemory(dest,src,amount);
+
+
+#endif /*WIN_NT_DRIVER*/
+
+
+
+#endif
+
diff --git a/src/See/normal_lookup.c b/src/See/normal_lookup.c
new file mode 100644
index 00000000..24adb62e
--- /dev/null
+++ b/src/See/normal_lookup.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <GlobalConst.h>
+
+#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/src/See/normal_lookup.h b/src/See/normal_lookup.h
new file mode 100644
index 00000000..45ac4fd1
--- /dev/null
+++ b/src/See/normal_lookup.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __normal_lookup
+#define __normal_lookup
+
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <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
diff --git a/src/See/resource.h b/src/See/resource.h
new file mode 100644
index 00000000..a8d305ad
--- /dev/null
+++ b/src/See/resource.h
@@ -0,0 +1,84 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by NPF.RC
+//
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// 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
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/See/resource1.h b/src/See/resource1.h
new file mode 100644
index 00000000..abd60c4b
--- /dev/null
+++ b/src/See/resource1.h
@@ -0,0 +1,84 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by See.rc
+//
+// Comments: Tetsuo Sugiyama, Ph.D.
+//
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+// THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE
+// AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE.
+//
+//
+// THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN,
+// UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY,
+// MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS
+// SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS
+// SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER
+// CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL
+// DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING,
+// MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR
+// SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
+// CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO
+// EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO,
+// JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION
+// AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN
+// THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE.
+//
+// USE ONLY IN JAPAN. DO NOT USE IT IN OTHER COUNTRIES. IMPORTING THIS
+// SOFTWARE INTO OTHER COUNTRIES IS AT YOUR OWN RISK. SOME COUNTRIES
+// PROHIBIT ENCRYPTED COMMUNICATIONS. USING THIS SOFTWARE IN OTHER
+// COUNTRIES MIGHT BE RESTRICTED.
+//
+//
+// DEAR SECURITY EXPERTS
+// ---------------------
+//
+// If you find a bug or a security vulnerability please kindly inform us
+// about the problem immediately so that we can fix the security problem
+// to protect a lot of users around the world as soon as possible.
+//
+// Our e-mail address for security reports is:
+// softether-vpn-security [at] softether.org
+//
+// Please note that the above e-mail address is not a technical support
+// inquiry address. If you need technical assistance, please visit
+// http://www.softether.org/ and ask your question on the users forum.
+//
+// Thank you for your cooperation.
+
+
+// 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
+
+// Developed by SoftEther VPN Project at University of Tsukuba in Japan.
+// Department of Computer Science has dozens of overly-enthusiastic geeks.
+// Join us: http://www.tsukuba.ac.jp/english/admission/
diff --git a/src/See/tcp_session.c b/src/See/tcp_session.c
new file mode 100644
index 00000000..cce97465
--- /dev/null
+++ b/src/See/tcp_session.c
@@ -0,0 +1,296 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <GlobalConst.h>
+
+#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;
+}
diff --git a/src/See/tcp_session.h b/src/See/tcp_session.h
new file mode 100644
index 00000000..33aa99e1
--- /dev/null
+++ b/src/See/tcp_session.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __tcp_session
+#define __tcp_session
+
+#ifdef WIN32
+#include "tme.h"
+#endif
+
+#ifdef __FreeBSD__
+
+#ifdef _KERNEL
+#include <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
diff --git a/src/See/time_calls.h b/src/See/time_calls.h
new file mode 100644
index 00000000..8f02f48f
--- /dev/null
+++ b/src/See/time_calls.h
@@ -0,0 +1,486 @@
+/*
+ * Copyright (c) 2001 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies
+ * nor the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef _time_calls
+#define _time_calls
+
+#ifdef WIN_NT_DRIVER
+
+#include "debug.h"
+#include "ndis.h"
+
+#define DEFAULT_TIMESTAMPMODE 0
+
+#define TIMESTAMPMODE_SINGLE_SYNCHRONIZATION 0
+#define TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP 1
+#define TIMESTAMPMODE_QUERYSYSTEMTIME 2
+#define TIMESTAMPMODE_RDTSC 3
+
+#define TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_NO_FIXUP 99
+
+#define TIMESTAMPMODE_REGKEY L"TimestampMode"
+
+extern ULONG TimestampMode;
+extern ULONG NCpu;
+
+/*!
+ \brief A microsecond precise timestamp.
+
+ included in the sf_pkthdr or the bpf_hdr that NPF associates with every packet.
+*/
+
+struct timeval {
+ long tv_sec; ///< seconds
+ long tv_usec; ///< microseconds
+};
+
+#endif /*WIN_NT_DRIVER*/
+
+struct time_conv
+{
+ ULONGLONG reference;
+ struct timeval start[32];
+};
+
+#ifdef WIN_NT_DRIVER
+
+__inline void TIME_DESYNCHRONIZE(struct time_conv *data)
+{
+ data->reference = 0;
+// data->start.tv_sec = 0;
+// data->start.tv_usec = 0;
+}
+
+
+__inline void ReadTimeStampModeFromRegistry(PUNICODE_STRING RegistryPath)
+{
+ ULONG NewLength;
+ PWSTR NullTerminatedString;
+ RTL_QUERY_REGISTRY_TABLE Queries[2];
+ ULONG DefaultTimestampMode = DEFAULT_TIMESTAMPMODE;
+
+ NewLength = RegistryPath->Length/2;
+
+ NullTerminatedString = ExAllocatePool(PagedPool, (NewLength+1) *sizeof(WCHAR));
+
+ if (NullTerminatedString != NULL)
+ {
+ RtlCopyMemory(NullTerminatedString, RegistryPath->Buffer, RegistryPath->Length);
+
+ NullTerminatedString[NewLength]=0;
+
+ RtlZeroMemory(Queries, sizeof(Queries));
+
+ Queries[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
+ Queries[0].Name = TIMESTAMPMODE_REGKEY;
+ Queries[0].EntryContext = &TimestampMode;
+ Queries[0].DefaultType = REG_DWORD;
+ Queries[0].DefaultData = &DefaultTimestampMode;
+ Queries[0].DefaultLength = sizeof(ULONG);
+
+ if (RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE, NullTerminatedString, Queries, NULL, NULL) != STATUS_SUCCESS)
+ {
+ TimestampMode = DEFAULT_TIMESTAMPMODE;
+ }
+
+ RtlWriteRegistryValue( RTL_REGISTRY_ABSOLUTE, NullTerminatedString, TIMESTAMPMODE_REGKEY, REG_DWORD, &TimestampMode,sizeof(ULONG));
+ ExFreePool(NullTerminatedString);
+ }
+ else
+ TimestampMode = DEFAULT_TIMESTAMPMODE;
+}
+
+#pragma optimize ("g",off) //Due to some weird behaviour of the optimizer of DDK build 2600
+
+/* KeQueryPerformanceCounter TimeStamps */
+__inline void SynchronizeOnCpu(struct timeval *start)
+{
+// struct timeval *start = (struct timeval*)Data;
+
+ LARGE_INTEGER SystemTime;
+ LARGE_INTEGER TimeFreq,PTime;
+
+ // get the absolute value of the system boot time.
+
+ PTime = KeQueryPerformanceCounter(&TimeFreq);
+ KeQuerySystemTime(&SystemTime);
+
+ start->tv_sec = (LONG)(SystemTime.QuadPart/10000000-11644473600);
+
+ start->tv_usec = (LONG)((SystemTime.QuadPart%10000000)/10);
+
+ start->tv_sec -= (ULONG)(PTime.QuadPart/TimeFreq.QuadPart);
+
+ start->tv_usec -= (LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
+
+ if (start->tv_usec < 0)
+ {
+ start->tv_sec --;
+ start->tv_usec += 1000000;
+ }
+}
+
+//
+// inline assembler is not supported with the current AMD64 compilers
+// At the moment we simply disable this timestamping mode on AMD64.
+// A solution would be to allocate a small memory from the non-paged
+// pool, dump the instructions on that buffer, and then execute them.
+// The non paged pool is needed since it's the only area of kernel
+// data memory that is not subject to the NX protection.
+// Or use some lower level trick, like using an assembler to assemble
+// a small function for this.
+//
+
+#ifdef __NPF_x86__
+/*RDTSC timestamps */
+/* callers must be at IRQL=PASSIVE_LEVEL*/
+__inline VOID TimeSynchronizeRDTSC(struct time_conv *data)
+{
+ struct timeval tmp;
+ LARGE_INTEGER system_time;
+ ULONGLONG curr_ticks;
+ KIRQL old;
+ LARGE_INTEGER start_kqpc,stop_kqpc,start_freq,stop_freq;
+ ULONGLONG start_ticks,stop_ticks;
+ ULONGLONG delta,delta2;
+ KEVENT event;
+ LARGE_INTEGER i;
+ ULONGLONG reference;
+
+ if (data->reference!=0)
+ return;
+
+ KeInitializeEvent(&event,NotificationEvent,FALSE);
+
+ i.QuadPart=-3500000;
+
+ KeRaiseIrql(HIGH_LEVEL,&old);
+ start_kqpc=KeQueryPerformanceCounter(&start_freq);
+ __asm
+ {
+ push eax
+ push edx
+ push ecx
+ rdtsc
+ lea ecx, start_ticks
+ mov [ecx+4], edx
+ mov [ecx], eax
+ pop ecx
+ pop edx
+ pop eax
+ }
+
+ KeLowerIrql(old);
+
+ KeWaitForSingleObject(&event,UserRequest,KernelMode,TRUE ,&i);
+
+ KeRaiseIrql(HIGH_LEVEL,&old);
+ stop_kqpc=KeQueryPerformanceCounter(&stop_freq);
+ __asm
+ {
+ push eax
+ push edx
+ push ecx
+ rdtsc
+ lea ecx, stop_ticks
+ mov [ecx+4], edx
+ mov [ecx], eax
+ pop ecx
+ pop edx
+ pop eax
+ }
+ KeLowerIrql(old);
+
+ delta=stop_ticks-start_ticks;
+ delta2=stop_kqpc.QuadPart-start_kqpc.QuadPart;
+ if (delta>10000000000)
+ {
+ delta/=16;
+ delta2/=16;
+ }
+
+ reference=delta*(start_freq.QuadPart)/delta2;
+
+ data->reference=reference/1000;
+
+ if (reference%1000>500)
+ data->reference++;
+
+ data->reference*=1000;
+
+ reference=data->reference;
+
+ KeQuerySystemTime(&system_time);
+
+ __asm
+ {
+ push eax
+ push edx
+ push ecx
+ rdtsc
+ lea ecx, curr_ticks
+ mov [ecx+4], edx
+ mov [ecx], eax
+ pop ecx
+ pop edx
+ pop eax
+ }
+
+ tmp.tv_sec=-(LONG)(curr_ticks/reference);
+
+ tmp.tv_usec=-(LONG)((curr_ticks%reference)*1000000/reference);
+
+ system_time.QuadPart-=116444736000000000;
+
+ tmp.tv_sec+=(LONG)(system_time.QuadPart/10000000);
+ tmp.tv_usec+=(LONG)((system_time.QuadPart%10000000)/10);
+
+ if (tmp.tv_usec<0)
+ {
+ tmp.tv_sec--;
+ tmp.tv_usec+=1000000;
+ }
+
+ data->start[0] = tmp;
+
+ IF_LOUD(DbgPrint("Frequency %I64u MHz\n",data->reference);)
+}
+#endif //__NPF_x86__
+
+#pragma optimize ("g",on) //Due to some weird behaviour of the optimizer of DDK build 2600
+
+__inline VOID TIME_SYNCHRONIZE(struct time_conv *data)
+{
+ ULONG NumberOfCpus, i;
+ KAFFINITY AffinityMask;
+
+ if (data->reference != 0)
+ return;
+
+ NumberOfCpus = NCpu;
+
+ if ( TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP || TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_NO_FIXUP)
+ {
+ for (i = 0 ; i < NumberOfCpus ; i++ )
+ {
+ AffinityMask = (1 << i);
+ ZwSetInformationThread(NtCurrentThread(), ThreadAffinityMask, &AffinityMask, sizeof(KAFFINITY));
+ SynchronizeOnCpu(&(data->start[i]));
+ }
+ AffinityMask = 0xFFFFFFFF;
+ ZwSetInformationThread(NtCurrentThread(), ThreadAffinityMask, &AffinityMask, sizeof(KAFFINITY));
+ data->reference = 1;
+ }
+ else
+ if ( TimestampMode == TIMESTAMPMODE_QUERYSYSTEMTIME )
+ {
+ //do nothing
+ data->reference = 1;
+ }
+ else
+//
+// This timestamp mode is supported on x86 (32 bit) only
+//
+#ifdef __NPF_x86__
+ if ( TimestampMode == TIMESTAMPMODE_RDTSC )
+ {
+ TimeSynchronizeRDTSC(data);
+ }
+ else
+#endif // __NPF_x86__
+ { //it should be only the normal case i.e. TIMESTAMPMODE_SINGLESYNCHRONIZATION
+ SynchronizeOnCpu(data->start);
+ data->reference = 1;
+ }
+ return;
+}
+
+
+#pragma optimize ("g",off) //Due to some weird behaviour of the optimizer of DDK build 2600
+
+__inline void GetTimeKQPC(struct timeval *dst, struct time_conv *data)
+{
+ LARGE_INTEGER PTime, TimeFreq;
+ LONG tmp;
+ ULONG CurrentCpu;
+ static struct timeval old_ts={0,0};
+
+
+ PTime = KeQueryPerformanceCounter(&TimeFreq);
+ tmp = (LONG)(PTime.QuadPart/TimeFreq.QuadPart);
+
+ if (TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP || TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_NO_FIXUP)
+ {
+ //actually this code is ok only if we are guaranteed that no thread scheduling will take place.
+ CurrentCpu = KeGetCurrentProcessorNumber();
+
+ dst->tv_sec = data->start[CurrentCpu].tv_sec + tmp;
+ dst->tv_usec = data->start[CurrentCpu].tv_usec + (LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
+
+ if (dst->tv_usec >= 1000000)
+ {
+ dst->tv_sec ++;
+ dst->tv_usec -= 1000000;
+ }
+
+ if (TimestampMode == TIMESTAMPMODE_SYNCHRONIZATION_ON_CPU_WITH_FIXUP)
+ {
+ if (old_ts.tv_sec > dst->tv_sec || (old_ts.tv_sec == dst->tv_sec && old_ts.tv_usec > dst->tv_usec) )
+ *dst = old_ts;
+
+ else
+ old_ts = *dst;
+ }
+ }
+ else
+ { //it should be only the normal case i.e. TIMESTAMPMODE_SINGLESYNCHRONIZATION
+ dst->tv_sec = data->start[0].tv_sec + tmp;
+ dst->tv_usec = data->start[0].tv_usec + (LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
+
+ if (dst->tv_usec >= 1000000)
+ {
+ dst->tv_sec ++;
+ dst->tv_usec -= 1000000;
+ }
+ }
+}
+
+//
+// inline assembler is not supported with the current AMD64 compilers
+// At the moment we simply disable this timestamping mode on AMD64.
+// A solution would be to allocate a small memory from the non-paged
+// pool, dump the instructions on that buffer, and then execute them.
+// The non paged pool is needed since it's the only area of kernel
+// data memory that is not subject to the NX protection.
+// Or use some lower level trick, like using an assembler to assemble
+// a small function for this.
+//
+
+#ifdef __NPF_x86__
+__inline void GetTimeRDTSC(struct timeval *dst, struct time_conv *data)
+{
+
+ ULONGLONG tmp;
+ __asm
+ {
+ push eax
+ push edx
+ push ecx
+ rdtsc
+ lea ecx, tmp
+ mov [ecx+4], edx
+ mov [ecx], eax
+ pop ecx
+ pop edx
+ pop eax
+ }
+
+ if (data->reference==0)
+ {
+ return;
+ }
+ dst->tv_sec=(LONG)(tmp/data->reference);
+
+ dst->tv_usec=(LONG)((tmp-dst->tv_sec*data->reference)*1000000/data->reference);
+
+ dst->tv_sec+=data->start[0].tv_sec;
+
+ dst->tv_usec+=data->start[0].tv_usec;
+
+ if (dst->tv_usec>=1000000)
+ {
+ dst->tv_sec++;
+ dst->tv_usec-=1000000;
+ }
+
+
+}
+#endif //__NPF_x86__
+
+__inline void GetTimeQST(struct timeval *dst, struct time_conv *data)
+{
+ LARGE_INTEGER SystemTime;
+
+ KeQuerySystemTime(&SystemTime);
+
+ dst->tv_sec = (LONG)(SystemTime.QuadPart/10000000-11644473600);
+ dst->tv_usec = (LONG)((SystemTime.QuadPart%10000000)/10);
+
+}
+
+#pragma optimize ("g",on) //Due to some weird behaviour of the optimizer of DDK build 2600
+
+__inline void GET_TIME(struct timeval *dst, struct time_conv *data)
+{
+ return;
+
+#if 0
+//
+// This timestamp mode is supported on x86 (32 bit) only
+//
+#ifdef __NPF_x86__
+ if ( TimestampMode == TIMESTAMPMODE_RDTSC )
+ {
+ GetTimeRDTSC(dst,data);
+ }
+ else
+#endif
+ if ( TimestampMode == TIMESTAMPMODE_QUERYSYSTEMTIME )
+ {
+ GetTimeQST(dst,data);
+ }
+ else
+ {
+ GetTimeKQPC(dst,data);
+ }
+#endif
+}
+
+
+#else /*WIN_NT_DRIVER*/
+
+__inline void FORCE_TIME(struct timeval *src, struct time_conv *dest)
+{
+ dest->start[0]=*src;
+}
+
+__inline void GET_TIME(struct timeval *dst, struct time_conv *data)
+{
+ return;
+ *dst=data->start[0];
+}
+
+#endif /*WIN_NT_DRIVER*/
+
+
+#endif /*_time_calls*/
diff --git a/src/See/tme.c b/src/See/tme.c
new file mode 100644
index 00000000..1e1a6d87
--- /dev/null
+++ b/src/See/tme.c
@@ -0,0 +1,385 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <GlobalConst.h>
+
+#include "tme.h"
+
+/* resizes extended memory */
+uint32 init_extended_memory(uint32 size, MEM_TYPE *mem_ex)
+{
+ uint8 *tmp;
+
+ if ((mem_ex==NULL)||(mem_ex->buffer==NULL)||(size==0))
+ return TME_ERROR; /* awfully never reached!!!! */
+
+ tmp=mem_ex->buffer;
+ mem_ex->buffer=NULL;
+ FREE_MEMORY(tmp);
+
+ ALLOCATE_MEMORY(tmp,uint8,size);
+ if (tmp==NULL)
+ return TME_ERROR; /* no memory */
+
+ mem_ex->size=size;
+ mem_ex->buffer=tmp;
+ return TME_SUCCESS;
+
+}
+
+/* activates a block of the TME */
+uint32 set_active_tme_block(TME_CORE *tme, uint32 block)
+{
+
+ if ((block>=MAX_TME_DATA_BLOCKS)||(!IS_VALIDATED(tme->validated_blocks,block)))
+ return TME_ERROR;
+ tme->active=block;
+ tme->working=block;
+ return TME_SUCCESS;
+
+}
+
+/* simply inserts default values in a TME block */
+/* it DOESN'T initialize the block in the core!! */
+/* FIXME default values are defined at compile time, */
+/* it will be useful to store them in the registry */
+uint32 init_tme_block(TME_CORE *tme, uint32 block)
+{
+
+ TME_DATA *data;
+ if (block>=MAX_TME_DATA_BLOCKS)
+ return TME_ERROR;
+ data=&(tme->block_data[block]);
+ tme->working=block;
+
+ ZERO_MEMORY(data,sizeof(TME_DATA));
+
+ /* entries in LUT */
+ data->lut_entries=TME_LUT_ENTRIES_DEFAULT;
+ /* blocks */
+ data->shared_memory_blocks=TME_SHARED_MEMORY_BLOCKS_DEFAULT;
+ /* block size */
+ data->block_size=TME_BLOCK_SIZE_DEFAULT;
+ /* lookup function */
+ data->lookup_code=lut_fcn_mapper(TME_LOOKUP_CODE_DEFAULT);
+ /* rehashing value */
+ data->rehashing_value=TME_REHASHING_VALUE_DEFAULT;
+ /* out lut function */
+ data->out_lut_exec=TME_OUT_LUT_EXEC_DEFAULT;
+ /* default function */
+ data->default_exec=TME_DEFAULT_EXEC_DEFAULT;
+ /* extra segment size */
+ data->extra_segment_size=TME_EXTRA_SEGMENT_SIZE_DEFAULT;
+
+
+ data->enable_deletion=FALSE;
+ data->last_read.tv_sec=0;
+ data->last_read.tv_usec=0;
+ return TME_SUCCESS;
+
+}
+/* it validates a TME block and */
+/* (on OK) inserts the block in the core */
+uint32 validate_tme_block(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 block, uint32 mem_ex_offset)
+{
+ uint32 required_memory;
+ uint8 *base=mem_ex_offset+mem_ex->buffer;
+ TME_DATA *data;
+
+ /* FIXME soluzione un po' posticcia... */
+ if (mem_ex_offset==0)
+ return TME_ERROR;
+
+ if (block>=MAX_TME_DATA_BLOCKS)
+ return TME_ERROR;
+ data=&tme->block_data[block];
+
+ if (data->lut_entries==0)
+ return TME_ERROR;
+
+ if (data->key_len==0)
+ return TME_ERROR;
+
+ if (data->shared_memory_blocks==0)
+ return TME_ERROR;
+
+ if (data->block_size==0)
+ return TME_ERROR;
+
+ /* checks if the lookup function is valid */
+ if (data->lookup_code==NULL)
+ return TME_ERROR;
+
+ /* checks if the out lut exec function is valid */
+ if (exec_fcn_mapper(data->out_lut_exec)==NULL)
+ return TME_ERROR;
+
+ /* checks if the default exec function is valid */
+ if (exec_fcn_mapper(data->default_exec)==NULL)
+ return TME_ERROR;
+
+ /* let's calculate memory needed */
+ required_memory=data->lut_entries*sizeof(RECORD); /*LUT*/
+ required_memory+=data->block_size*data->shared_memory_blocks; /*shared segment*/
+ required_memory+=data->extra_segment_size; /*extra segment*/
+
+ if (required_memory>(mem_ex->size-mem_ex_offset))
+ return TME_ERROR; /*not enough memory*/
+
+ /* the TME block can be initialized */
+ ZERO_MEMORY(base,required_memory);
+
+ data->lut_base_address=base;
+
+ data->shared_memory_base_address=
+ data->lut_base_address+
+ data->lut_entries*sizeof(RECORD);
+
+ data->extra_segment_base_address=
+ data->shared_memory_base_address+
+ data->block_size*data->shared_memory_blocks;
+ data->filled_blocks=1;
+ VALIDATE(tme->validated_blocks,block);
+ tme->active=block;
+ tme->working=block;
+ return TME_SUCCESS;
+}
+
+/* I/F between the bpf machine and the callbacks, just some checks */
+uint32 lookup_frontend(MEM_TYPE *mem_ex, TME_CORE *tme,uint32 mem_ex_offset, struct time_conv *time_ref)
+{
+ if (tme->active==TME_NONE_ACTIVE)
+ return TME_FALSE;
+
+ return (tme->block_data[tme->active].lookup_code)(mem_ex_offset+mem_ex->buffer,&tme->block_data[tme->active],mem_ex, time_ref);
+}
+
+/* I/F between the bpf machine and the callbacks, just some checks */
+uint32 execute_frontend(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 pkt_size, uint32 offset)
+{
+
+ exec_fcn tmp;
+ TME_DATA *data;
+ uint8 *block;
+ uint8 *mem_data;
+
+ if (tme->active==TME_NONE_ACTIVE)
+ return TME_ERROR;
+
+ data=&tme->block_data[tme->active];
+
+ if (data->last_found==NULL)
+ { /*out lut exec */
+ tmp=exec_fcn_mapper(data->out_lut_exec);
+ block=data->shared_memory_base_address;
+ }
+ else
+ { /*checks if last_found is valid */
+ if ((data->last_found<data->lut_base_address)||(data->last_found>=data->shared_memory_base_address))
+ return TME_ERROR;
+ else
+ {
+ tmp=exec_fcn_mapper(SW_ULONG_AT(&((RECORD*)data->last_found)->exec_fcn,0));
+ if (tmp==NULL)
+ return TME_ERROR;
+ block=SW_ULONG_AT(&((RECORD*)data->last_found)->block,0)+mem_ex->buffer;
+ if ((block<data->shared_memory_base_address)||(block>=data->extra_segment_base_address))
+ return TME_ERROR;
+ }
+ }
+
+ if (offset>=mem_ex->size)
+ return TME_ERROR;
+
+ mem_data=mem_ex->buffer+offset;
+
+ return tmp(block,pkt_size,data,mem_ex,mem_data);
+}
+
+/*resets all the TME core*/
+uint32 reset_tme(TME_CORE *tme)
+{
+ if (tme==NULL)
+ return TME_ERROR;
+ ZERO_MEMORY(tme, sizeof(TME_CORE));
+ return TME_SUCCESS;
+}
+
+/* returns a register value of the active TME block */
+/* FIXME last found in maniera elegante e veloce ?!?! */
+uint32 get_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 *rval)
+{
+ switch(rgstr)
+ {
+ case TME_LUT_ENTRIES:
+ *rval=data->lut_entries;
+ return TME_SUCCESS;
+ case TME_MAX_FILL_STATE:
+ *rval=data->max_fill_state;
+ return TME_SUCCESS;
+ case TME_REHASHING_VALUE:
+ *rval=data->rehashing_value;
+ return TME_SUCCESS;
+ case TME_KEY_LEN:
+ *rval=data->key_len;
+ return TME_SUCCESS;
+ case TME_SHARED_MEMORY_BLOCKS:
+ *rval=data->shared_memory_blocks;
+ return TME_SUCCESS;
+ case TME_FILLED_ENTRIES:
+ *rval=data->filled_entries;
+ return TME_SUCCESS;
+ case TME_BLOCK_SIZE:
+ *rval=data->block_size;
+ return TME_SUCCESS;
+ case TME_EXTRA_SEGMENT_SIZE:
+ *rval=data->extra_segment_size;
+ return TME_SUCCESS;
+ case TME_FILLED_BLOCKS:
+ *rval=data->filled_blocks;
+ return TME_SUCCESS;
+ case TME_DEFAULT_EXEC:
+ *rval=data->default_exec;
+ return TME_SUCCESS;
+ case TME_OUT_LUT_EXEC:
+ *rval=data->out_lut_exec;
+ return TME_SUCCESS;
+ case TME_SHARED_MEMORY_BASE_ADDRESS:
+ *rval=data->shared_memory_base_address-mem_ex->buffer;
+ return TME_SUCCESS;
+ case TME_LUT_BASE_ADDRESS:
+ *rval=data->lut_base_address-mem_ex->buffer;
+ return TME_SUCCESS;
+ case TME_EXTRA_SEGMENT_BASE_ADDRESS:
+ *rval=data->extra_segment_base_address-mem_ex->buffer;
+ return TME_SUCCESS;
+ case TME_LAST_FOUND_BLOCK:
+ if (data->last_found==NULL)
+ *rval=0;
+ else
+ *rval=data->last_found-mem_ex->buffer;
+ return TME_SUCCESS;
+
+ default:
+ return TME_ERROR;
+ }
+}
+
+/* sets a register value in the active block */
+/* FIXME last found in maniera elegante e veloce ?!?! */
+uint32 set_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 value, int32 init)
+{ /* very very very dangerous!!!!!!!!!!! */
+ lut_fcn tmp;
+ switch(rgstr)
+ {
+ case TME_MAX_FILL_STATE:
+ data->max_fill_state=value;
+ return TME_SUCCESS;
+ case TME_REHASHING_VALUE:
+ data->rehashing_value=value;
+ return TME_SUCCESS;
+ case TME_FILLED_ENTRIES:
+ data->filled_entries=value;
+ return TME_SUCCESS;
+ case TME_FILLED_BLOCKS:
+ if (value<=data->shared_memory_blocks)
+ {
+ data->filled_blocks=value;
+ return TME_SUCCESS;
+ }
+ else
+ return TME_ERROR;
+ case TME_DEFAULT_EXEC:
+ data->default_exec=value;
+ return TME_SUCCESS;
+ case TME_OUT_LUT_EXEC:
+ data->out_lut_exec=value;
+ return TME_SUCCESS;
+ case TME_LOOKUP_CODE:
+ tmp=lut_fcn_mapper(value);
+ if (tmp==NULL)
+ return TME_ERROR;
+ else
+ data->lookup_code=tmp;
+ return TME_SUCCESS;
+ default:
+ break;
+ }
+
+ if (init)
+ switch (rgstr)
+ {
+
+ case TME_LUT_ENTRIES:
+ data->lut_entries=value;
+ return TME_SUCCESS;
+ case TME_KEY_LEN:
+ data->key_len=value;
+ return TME_SUCCESS;
+ case TME_SHARED_MEMORY_BLOCKS:
+ data->shared_memory_blocks=value;
+ return TME_SUCCESS;
+ case TME_BLOCK_SIZE:
+ data->block_size=value;
+ return TME_SUCCESS;
+ case TME_EXTRA_SEGMENT_SIZE:
+ data->extra_segment_size=value;
+ return TME_SUCCESS;
+ default:
+ return TME_ERROR;
+ }
+ else
+ return TME_ERROR;
+
+}
+
+/* chooses the TME block for read */
+uint32 set_active_read_tme_block(TME_CORE *tme, uint32 block)
+{
+
+ if ((block>=MAX_TME_DATA_BLOCKS)||(!IS_VALIDATED(tme->validated_blocks,block)))
+ return TME_ERROR;
+ tme->active_read=block;
+ return TME_SUCCESS;
+
+}
+
+/* chooses if the autodeletion must be used */
+uint32 set_autodeletion(TME_DATA *data, uint32 value)
+{
+ if (value==0) /* no autodeletion */
+ data->enable_deletion=FALSE;
+ else
+ data->enable_deletion=TRUE;
+
+ return TME_SUCCESS;
+}
diff --git a/src/See/tme.h b/src/See/tme.h
new file mode 100644
index 00000000..eb8d4b12
--- /dev/null
+++ b/src/See/tme.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __tme_include_
+#define __tme_include_
+
+#ifdef WIN_NT_DRIVER
+#include "ndis.h"
+#else
+#include <windows.h>
+#endif /*WIN_NT_DRIVER*/
+
+#include "memory_t.h"
+#include "time_calls.h"
+
+
+/* error codes */
+#define TME_ERROR 0
+#define TME_SUCCESS 1
+#define TME_TRUE 2
+#define TME_FALSE 3
+
+/* some constants */
+#define DEFAULT_MEM_EX_SIZE 65536
+#define MAX_TME_DATA_BLOCKS 4
+#define TME_NONE_ACTIVE 0xffffffff
+#define DELTA_READ 2 /* secs */
+
+#define TME_LUT_ENTRIES 0x00000000
+#define TME_MAX_FILL_STATE 0x00000001 /*potrebbe servire per un thread a passive level!?!?! */
+#define TME_REHASHING_VALUE 0x00000002
+#define TME_KEY_LEN 0x00000003
+#define TME_SHARED_MEMORY_BLOCKS 0x00000004
+#define TME_FILLED_ENTRIES 0x00000005
+#define TME_BLOCK_SIZE 0x00000006
+#define TME_EXTRA_SEGMENT_SIZE 0x00000007
+#define TME_LOOKUP_CODE 0x00000008
+#define TME_OUT_LUT_EXEC 0x00000009
+#define TME_FILLED_BLOCKS 0x0000000a
+#define TME_DEFAULT_EXEC 0x0000000b
+#define TME_LUT_BASE_ADDRESS 0x0000000c
+#define TME_SHARED_MEMORY_BASE_ADDRESS 0x0000000d
+#define TME_EXTRA_SEGMENT_BASE_ADDRESS 0x0000000e
+#define TME_LAST_FOUND 0x0000000f /* contains the offset of the last found entry */
+#define TME_LAST_FOUND_BLOCK 0x00000010
+/* TME default values */
+#define TME_LUT_ENTRIES_DEFAULT 32007
+#define TME_REHASHING_VALUE_DEFAULT 1
+#define TME_SHARED_MEMORY_BLOCKS_DEFAULT 16000
+#define TME_BLOCK_SIZE_DEFAULT 64
+#define TME_EXTRA_SEGMENT_SIZE_DEFAULT 0
+#define TME_LOOKUP_CODE_DEFAULT 0
+#define TME_OUT_LUT_EXEC_DEFAULT 0
+#define TME_DEFAULT_EXEC_DEFAULT 0
+#define TME_MAX_FILL_STATE_DEFAULT 15000
+
+#define IS_VALIDATED(src,index) (src&(1<<index))
+
+#define VALIDATE(src,index) src|=(1<<index);
+
+
+#define FORCE_NO_DELETION(timestamp) (struct timeval*)(timestamp)->tv_sec=0x7fffffff;
+
+/* TME callback prototypes */
+typedef uint32 (*lut_fcn)(uint8 *key, struct __TME_DATA *data,MEM_TYPE *mem_ex, struct time_conv *time_ref );
+typedef uint32 (*exec_fcn)(uint8 *block, uint32 pkt_size, struct __TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data);
+
+/* DO NOT MODIFY THIS STRUCTURE!!!! GV */
+typedef struct __RECORD
+
+{
+ uint32 block;
+ uint32 exec_fcn;
+}
+ RECORD, *PRECORD;
+
+/* TME data registers */
+struct __TME_DATA
+{
+ uint32 lut_entries;
+ uint32 max_fill_state;
+ uint32 rehashing_value;
+ uint32 key_len;
+ uint32 shared_memory_blocks;
+ uint32 filled_entries;
+ uint32 block_size;
+ uint32 extra_segment_size;
+ uint32 filled_blocks;
+ lut_fcn lookup_code;
+ uint32 default_exec;
+ uint32 out_lut_exec;
+ uint8 *lut_base_address;
+ uint8 *shared_memory_base_address;
+ uint8 *extra_segment_base_address;
+ struct timeval last_read;
+ uint32 enable_deletion;
+ uint8 *last_found;
+};
+
+typedef struct __TME_DATA TME_DATA,*PTME_DATA;
+
+
+
+/* TME core */
+typedef struct __TME_CORE
+{
+ uint32 working;
+ uint32 active;
+ uint32 validated_blocks;
+ TME_DATA block_data[MAX_TME_DATA_BLOCKS];
+ uint32 active_read;
+
+} TME_CORE, *PTME_CORE;
+
+static __inline int32 IS_DELETABLE(void *timestamp, TME_DATA *data)
+{
+ struct timeval *ts=(struct timeval*)timestamp;
+
+ if (data->enable_deletion==FALSE)
+ return FALSE;
+ if (data->filled_entries<data->max_fill_state)
+ return FALSE;
+ if ((ts->tv_sec+DELTA_READ)<data->last_read.tv_sec)
+ return TRUE;
+ return FALSE;
+}
+
+/* functions to manage TME */
+uint32 init_tme_block(TME_CORE *tme, uint32 block);
+uint32 validate_tme_block(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 block, uint32 mem_ex_offset);
+uint32 lookup_frontend(MEM_TYPE *mem_ex, TME_CORE *tme,uint32 mem_ex_offset, struct time_conv *time_ref);
+uint32 execute_frontend(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 pkt_size,uint32 offset);
+uint32 set_active_tme_block(TME_CORE *tme, uint32 block);
+uint32 init_extended_memory(uint32 size, MEM_TYPE *mem_ex);
+uint32 reset_tme(TME_CORE *tme);
+uint32 get_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 *rval);
+uint32 set_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 value, int32 init);
+uint32 set_active_read_tme_block(TME_CORE *tme, uint32 block);
+uint32 set_autodeletion(TME_DATA *data, uint32 value);
+
+/* function mappers */
+lut_fcn lut_fcn_mapper(uint32 index);
+exec_fcn exec_fcn_mapper(uint32 index);
+
+#endif
diff --git a/src/See/valid_insns.h b/src/See/valid_insns.h
new file mode 100644
index 00000000..f0361021
--- /dev/null
+++ b/src/See/valid_insns.h
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2001 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies
+ * nor the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+u_short valid_instructions[]=
+ {
+ BPF_RET|BPF_K,
+ BPF_RET|BPF_A,
+ BPF_LD|BPF_IMM,
+ BPF_LDX|BPF_IMM,
+ BPF_LD|BPF_MEM,
+ BPF_LDX|BPF_MEM,
+
+#ifdef __NPF_x86__
+ BPF_LD|BPF_MEM_EX_IMM|BPF_B,
+ BPF_LD|BPF_MEM_EX_IMM|BPF_H,
+ BPF_LD|BPF_MEM_EX_IMM|BPF_W,
+ BPF_LD|BPF_MEM_EX_IND|BPF_B,
+ BPF_LD|BPF_MEM_EX_IND|BPF_H,
+ BPF_LD|BPF_MEM_EX_IND|BPF_W,
+#endif
+ BPF_LD|BPF_W|BPF_ABS,
+ BPF_LD|BPF_H|BPF_ABS,
+ BPF_LD|BPF_B|BPF_ABS,
+ BPF_LDX|BPF_W|BPF_ABS,
+ BPF_LDX|BPF_H|BPF_ABS,
+ BPF_LDX|BPF_B|BPF_ABS,
+ BPF_LD|BPF_W|BPF_LEN,
+ BPF_LDX|BPF_W|BPF_LEN,
+ BPF_LD|BPF_W|BPF_IND,
+ BPF_LD|BPF_H|BPF_IND,
+ BPF_LD|BPF_B|BPF_IND,
+ BPF_LDX|BPF_MSH|BPF_B,
+ BPF_ST,
+ BPF_STX,
+
+#ifdef __NPF_x86__
+ BPF_ST|BPF_MEM_EX_IMM|BPF_B,
+ BPF_STX|BPF_MEM_EX_IMM|BPF_B,
+ BPF_ST|BPF_MEM_EX_IMM|BPF_W,
+ BPF_STX|BPF_MEM_EX_IMM|BPF_W,
+ BPF_ST|BPF_MEM_EX_IMM|BPF_H,
+ BPF_STX|BPF_MEM_EX_IMM|BPF_H,
+ BPF_ST|BPF_MEM_EX_IND|BPF_B,
+ BPF_ST|BPF_MEM_EX_IND|BPF_W,
+ BPF_ST|BPF_MEM_EX_IND|BPF_H,
+#endif
+
+ BPF_JMP|BPF_JA,
+ BPF_JMP|BPF_JGT|BPF_K,
+ BPF_JMP|BPF_JGE|BPF_K,
+ BPF_JMP|BPF_JEQ|BPF_K,
+ BPF_JMP|BPF_JSET|BPF_K,
+ BPF_JMP|BPF_JGT|BPF_X,
+ BPF_JMP|BPF_JGE|BPF_X,
+ BPF_JMP|BPF_JEQ|BPF_X,
+ BPF_JMP|BPF_JSET|BPF_X,
+ BPF_ALU|BPF_ADD|BPF_X,
+ BPF_ALU|BPF_SUB|BPF_X,
+ BPF_ALU|BPF_MUL|BPF_X,
+ BPF_ALU|BPF_DIV|BPF_X,
+ BPF_ALU|BPF_AND|BPF_X,
+ BPF_ALU|BPF_OR|BPF_X,
+ BPF_ALU|BPF_LSH|BPF_X,
+ BPF_ALU|BPF_RSH|BPF_X,
+ BPF_ALU|BPF_ADD|BPF_K,
+ BPF_ALU|BPF_SUB|BPF_K,
+ BPF_ALU|BPF_MUL|BPF_K,
+ BPF_ALU|BPF_DIV|BPF_K,
+ BPF_ALU|BPF_AND|BPF_K,
+ BPF_ALU|BPF_OR|BPF_K,
+ BPF_ALU|BPF_LSH|BPF_K,
+ BPF_ALU|BPF_RSH|BPF_K,
+ BPF_ALU|BPF_NEG,
+ BPF_MISC|BPF_TAX,
+ BPF_MISC|BPF_TXA,
+
+#ifdef __NPF_x86__
+ BPF_MISC|BPF_TME|BPF_LOOKUP,
+ BPF_MISC|BPF_TME|BPF_EXECUTE,
+ BPF_MISC|BPF_TME|BPF_SET_ACTIVE,
+ BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE,
+ BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE
+#endif
+
+ };
+
+#define VALID_INSTRUCTIONS_LEN (sizeof(valid_instructions)/sizeof(u_short))
diff --git a/src/See/win_bpf.h b/src/See/win_bpf.h
new file mode 100644
index 00000000..8ca879f5
--- /dev/null
+++ b/src/See/win_bpf.h
@@ -0,0 +1,417 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)bpf.h 7.1 (Berkeley) 5/7/91
+ *
+ * @(#) $Header: /usr/cvsroot_private/winpcap/packetNtx/driver/win_bpf.h,v 1.2.2.1 2005/12/02 22:12:58 gianlucav Exp $ (LBL)
+ */
+
+#ifndef BPF_MAJOR_VERSION
+
+/* BSD style release date */
+#define BPF_RELEASE 199606
+
+#ifdef WIN_NT_DRIVER
+#include <ndis.h>
+#endif
+
+
+#include "tme.h"
+#include "time_calls.h"
+
+typedef UCHAR u_char;
+typedef USHORT u_short;
+
+#ifdef WIN_NT_DRIVER
+typedef ULONG u_int;
+#endif
+
+typedef LONG bpf_int32;
+typedef ULONG bpf_u_int32;
+typedef ULONG u_int32;
+
+#define BPF_MAXINSNS 512
+#define BPF_MAXBUFSIZE 0x8000
+#define BPF_MINBUFSIZE 32
+
+/*
+ * The instruction data structure.
+ */
+struct bpf_insn {
+ u_short code;
+ u_char jt;
+ u_char jf;
+ bpf_u_int32 k;
+};
+
+/*
+ * Structure for BIOCSETF.
+ */
+struct bpf_program {
+ u_int bf_len;
+ struct bpf_insn *bf_insns;
+};
+
+/*
+ * Struct returned by BIOCGSTATS.
+ */
+struct bpf_stat {
+ UINT bs_recv; ///< Number of packets that the driver received from the network adapter
+ ///< from the beginning of the current capture. This value includes the packets
+ ///< lost by the driver.
+ UINT bs_drop; ///< number of packets that the driver lost from the beginning of a capture.
+ ///< Basically, a packet is lost when the the buffer of the driver is full.
+ ///< In this situation the packet cannot be stored and the driver rejects it.
+ UINT ps_ifdrop; ///< drops by interface. XXX not yet supported
+ UINT bs_capt; ///< number of packets that pass the filter, find place in the kernel buffer and
+ ///< thus reach the application.
+};
+
+/*
+ * Struct return by BIOCVERSION. This represents the version number of
+ * the filter language described by the instruction encodings below.
+ * bpf understands a program iff kernel_major == filter_major &&
+ * kernel_minor >= filter_minor, that is, if the value returned by the
+ * running kernel has the same major number and a minor number equal
+ * equal to or less than the filter being downloaded. Otherwise, the
+ * results are undefined, meaning an error may be returned or packets
+ * may be accepted haphazardly.
+ * It has nothing to do with the source code version.
+ */
+struct bpf_version {
+ u_short bv_major;
+ u_short bv_minor;
+};
+/* Current version number of filter architecture. */
+#define BPF_MAJOR_VERSION 1
+#define BPF_MINOR_VERSION 1
+
+
+/*
+ * Structure prepended to each packet.
+ */
+struct bpf_hdr {
+ struct timeval bh_tstamp; /* time stamp */
+ bpf_u_int32 bh_caplen; /* length of captured portion */
+ bpf_u_int32 bh_datalen; /* original length of packet */
+ u_short bh_hdrlen; /* length of bpf header (this struct
+ plus alignment padding) */
+};
+
+/*
+ * Data-link level type codes.
+ */
+
+/*
+ * These are the types that are the same on all platforms; on other
+ * platforms, a <net/bpf.h> should be supplied that defines the additional
+ * DLT_* codes appropriately for that platform (the BSDs, for example,
+ * should not just pick up this version of "bpf.h"; they should also define
+ * the additional DLT_* codes used by their kernels, as well as the values
+ * defined here - and, if the values they use for particular DLT_ types
+ * differ from those here, they should use their values, not the ones
+ * here).
+ */
+#define DLT_NULL 0 /* no link-layer encapsulation */
+#define DLT_EN10MB 1 /* Ethernet (10Mb) */
+#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */
+#define DLT_AX25 3 /* Amateur Radio AX.25 */
+#define DLT_PRONET 4 /* Proteon ProNET Token Ring */
+#define DLT_CHAOS 5 /* Chaos */
+#define DLT_IEEE802 6 /* IEEE 802 Networks */
+#define DLT_ARCNET 7 /* ARCNET */
+#define DLT_SLIP 8 /* Serial Line IP */
+#define DLT_PPP 9 /* Point-to-point Protocol */
+#define DLT_FDDI 10 /* FDDI */
+
+/*
+ * These are values from the traditional libpcap "bpf.h".
+ * Ports of this to particular platforms should replace these definitions
+ * with the ones appropriate to that platform, if the values are
+ * different on that platform.
+ */
+#define DLT_ATM_RFC1483 11 /* LLC/SNAP encapsulated atm */
+#define DLT_RAW 12 /* raw IP */
+
+/*
+ * These are values from BSD/OS's "bpf.h".
+ * These are not the same as the values from the traditional libpcap
+ * "bpf.h"; however, these values shouldn't be generated by any
+ * OS other than BSD/OS, so the correct values to use here are the
+ * BSD/OS values.
+ *
+ * Platforms that have already assigned these values to other
+ * DLT_ codes, however, should give these codes the values
+ * from that platform, so that programs that use these codes will
+ * continue to compile - even though they won't correctly read
+ * files of these types.
+ */
+#define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */
+#define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */
+
+#define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */
+
+/*
+ * This value is defined by NetBSD; other platforms should refrain from
+ * using it for other purposes, so that NetBSD savefiles with a link
+ * type of 50 can be read as this type on all platforms.
+ */
+#define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */
+
+/*
+ * This value was defined by libpcap 0.5; platforms that have defined
+ * it with a different value should define it here with that value -
+ * a link type of 104 in a save file will be mapped to DLT_C_HDLC,
+ * whatever value that happens to be, so programs will correctly
+ * handle files with that link type regardless of the value of
+ * DLT_C_HDLC.
+ *
+ * The name DLT_C_HDLC was used by BSD/OS; we use that name for source
+ * compatibility with programs written for BSD/OS.
+ *
+ * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well,
+ * for source compatibility with programs written for libpcap 0.5.
+ */
+#define DLT_C_HDLC 104 /* Cisco HDLC */
+#define DLT_CHDLC DLT_C_HDLC
+
+/*
+ * Reserved for future use.
+ * Do not pick other numerical value for these unless you have also
+ * picked up the tcpdump.org top-of-CVS-tree version of "savefile.c",
+ * which will arrange that capture files for these DLT_ types have
+ * the same "network" value on all platforms, regardless of what
+ * value is chosen for their DLT_ type (thus allowing captures made
+ * on one platform to be read on other platforms, even if the two
+ * platforms don't use the same numerical values for all DLT_ types).
+ */
+#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */
+
+/*
+ * Values between 106 and 107 are used in capture file headers as
+ * link-layer types corresponding to DLT_ types that might differ
+ * between platforms; don't use those values for new DLT_ new types.
+ */
+
+/*
+ * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except
+ * that the AF_ type in the link-layer header is in network byte order.
+ *
+ * OpenBSD defines it as 12, but that collides with DLT_RAW, so we
+ * define it as 108 here. If OpenBSD picks up this file, it should
+ * define DLT_LOOP as 12 in its version, as per the comment above -
+ * and should not use 108 for any purpose.
+ */
+#define DLT_LOOP 108
+
+/*
+ * Values between 109 and 112 are used in capture file headers as
+ * link-layer types corresponding to DLT_ types that might differ
+ * between platforms; don't use those values for new DLT_ new types.
+ */
+
+/*
+ * This is for Linux cooked sockets.
+ */
+#define DLT_LINUX_SLL 113
+
+/*
+ * The instruction encodings.
+ */
+/* instruction classes */
+#define BPF_CLASS(code) ((code) & 0x07)
+#define BPF_LD 0x00
+#define BPF_LDX 0x01
+#define BPF_ST 0x02
+#define BPF_STX 0x03
+#define BPF_ALU 0x04
+#define BPF_JMP 0x05
+#define BPF_RET 0x06
+#define BPF_MISC 0x07
+
+/* ld/ldx fields */
+#define BPF_SIZE(code) ((code) & 0x18)
+#define BPF_W 0x00
+#define BPF_H 0x08
+#define BPF_B 0x10
+#define BPF_MODE(code) ((code) & 0xe0)
+#define BPF_IMM 0x00
+#define BPF_ABS 0x20
+#define BPF_IND 0x40
+#define BPF_MEM 0x60
+#define BPF_LEN 0x80
+#define BPF_MSH 0xa0
+
+/* alu/jmp fields */
+#define BPF_OP(code) ((code) & 0xf0)
+#define BPF_ADD 0x00
+#define BPF_SUB 0x10
+#define BPF_MUL 0x20
+#define BPF_DIV 0x30
+#define BPF_OR 0x40
+#define BPF_AND 0x50
+#define BPF_LSH 0x60
+#define BPF_RSH 0x70
+#define BPF_NEG 0x80
+#define BPF_JA 0x00
+#define BPF_JEQ 0x10
+#define BPF_JGT 0x20
+#define BPF_JGE 0x30
+#define BPF_JSET 0x40
+#define BPF_SRC(code) ((code) & 0x08)
+#define BPF_K 0x00
+#define BPF_X 0x08
+
+/* ret - BPF_K and BPF_X also apply */
+#define BPF_RVAL(code) ((code) & 0x18)
+#define BPF_A 0x10
+
+/* misc */
+#define BPF_MISCOP(code) ((code) & 0xf8)
+#define BPF_TAX 0x00
+#define BPF_TXA 0x80
+
+/* TME instructions */
+#define BPF_TME 0x08
+
+#define BPF_LOOKUP 0x90
+#define BPF_EXECUTE 0xa0
+#define BPF_INIT 0xb0
+#define BPF_VALIDATE 0xc0
+#define BPF_SET_ACTIVE 0xd0
+#define BPF_RESET 0xe0
+#define BPF_SET_MEMORY 0x80
+#define BPF_GET_REGISTER_VALUE 0x70
+#define BPF_SET_REGISTER_VALUE 0x60
+#define BPF_SET_WORKING 0x50
+#define BPF_SET_ACTIVE_READ 0x40
+#define BPF_SET_AUTODELETION 0x30
+#define BPF_SEPARATION 0xff
+
+#define BPF_MEM_EX_IMM 0xc0
+#define BPF_MEM_EX_IND 0xe0
+/*used for ST */
+#define BPF_MEM_EX 0xc0
+
+
+/*
+ * Macros for insn array initializers.
+ */
+#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k }
+#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k }
+
+/*
+ * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST).
+ */
+#define BPF_MEMWORDS 16
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*!
+ \brief Validates a filtering program arriving from the user-level app.
+ \param f The filter.
+ \param len Its length, in pseudo instructions.
+ \param mem_ex_size The length of the extended memory, used to validate LD/ST to that memory
+ \return true if f is a valid filter program..
+
+ The kernel needs to be able to verify an application's filter code. Otherwise, a bogus program could easily
+ crash the system.
+ This function returns true if f is a valid filter program. The constraints are that each jump be forward and
+ to a valid code. The code must terminate with either an accept or reject.
+*/
+int32 bpf_validate(struct bpf_insn *f,int32 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.
+*/
+u_int bpf_filter(register struct bpf_insn *pc,
+ register UCHAR *p,
+ u_int wirelen,
+ register u_int buflen ,
+ PMEM_TYPE mem_ex,
+ PTME_CORE tme ,
+ struct time_conv *time_ref);
+
+/*!
+ \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.
+*/
+u_int bpf_filter_with_2_buffers(register struct bpf_insn *pc,
+ register u_char *p,
+ register u_char *pd,
+ register int headersize,
+ u_int wirelen,
+ register u_int buflen,
+ PMEM_TYPE mem_ex,
+ PTME_CORE tme,
+ struct time_conv *time_ref);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/src/See/win_bpf_filter.c b/src/See/win_bpf_filter.c
new file mode 100644
index 00000000..8ebb82f5
--- /dev/null
+++ b/src/See/win_bpf_filter.c
@@ -0,0 +1,1086 @@
+/*
+ * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 CACE Technologies, Davis (California)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino, CACE Technologies
+ * nor the names of its contributors may be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <GlobalConst.h>
+
+#ifndef WIN_NT_DRIVER
+#include <windows.h>
+#else
+#include <ndis.h>
+#endif
+
+#include "win_bpf.h"
+
+#include "debug.h"
+
+#include "valid_insns.h"
+
+#define EXTRACT_SHORT(p)\
+ ((u_short)\
+ ((u_short)*((u_char *)p+0)<<8|\
+ (u_short)*((u_char *)p+1)<<0))
+#define EXTRACT_LONG(p)\
+ ((u_int32)*((u_char *)p+0)<<24|\
+ (u_int32)*((u_char *)p+1)<<16|\
+ (u_int32)*((u_char *)p+2)<<8|\
+ (u_int32)*((u_char *)p+3)<<0)
+
+
+u_int bpf_filter(pc, p, wirelen, buflen,mem_ex,tme,time_ref)
+ register struct bpf_insn *pc;
+ register u_char *p;
+ u_int wirelen;
+ register u_int buflen;
+ PMEM_TYPE mem_ex;
+ PTME_CORE tme;
+ struct time_conv *time_ref;
+
+{
+ register u_int32 A, X;
+ register int k;
+ //u_int32 j,tmp;
+ //u_short tmp2;
+
+ int32 mem[BPF_MEMWORDS];
+
+ if (pc == 0)
+ /*
+ * No filter means accept all.
+ */
+ return (u_int)-1;
+ A = 0;
+ X = 0;
+ --pc;
+ while (1) {
+ ++pc;
+ switch (pc->code) {
+
+ default:
+
+ return 0;
+
+ case BPF_RET|BPF_K:
+ return (u_int)pc->k;
+
+ case BPF_RET|BPF_A:
+ return (u_int)A;
+
+ case BPF_LD|BPF_W|BPF_ABS:
+ k = pc->k;
+ if (k + sizeof(int32) > buflen) {
+ return 0;
+ }
+ A = EXTRACT_LONG(&p[k]);
+ continue;
+
+ case BPF_LD|BPF_H|BPF_ABS:
+ k = pc->k;
+ if (k + sizeof(short) > buflen) {
+ return 0;
+ }
+ A = EXTRACT_SHORT(&p[k]);
+ continue;
+
+ case BPF_LD|BPF_B|BPF_ABS:
+ k = pc->k;
+ if ((int)k >= (int)buflen) {
+ return 0;
+ }
+ A = p[k];
+ continue;
+
+ case BPF_LD|BPF_W|BPF_LEN:
+ A = wirelen;
+ continue;
+
+ case BPF_LDX|BPF_W|BPF_LEN:
+ X = wirelen;
+ continue;
+
+ case BPF_LD|BPF_W|BPF_IND:
+ k = X + pc->k;
+ if (k + sizeof(int32) > buflen) {
+ return 0;
+ }
+ A = EXTRACT_LONG(&p[k]);
+ continue;
+
+ case BPF_LD|BPF_H|BPF_IND:
+ k = X + pc->k;
+ if (k + sizeof(short) > buflen) {
+ return 0;
+ }
+ A = EXTRACT_SHORT(&p[k]);
+ continue;
+
+ case BPF_LD|BPF_B|BPF_IND:
+ k = X + pc->k;
+ if ((int)k >= (int)buflen) {
+ return 0;
+ }
+ A = p[k];
+ continue;
+
+ case BPF_LDX|BPF_MSH|BPF_B:
+ k = pc->k;
+ if ((int)k >= (int)buflen) {
+ return 0;
+ }
+ X = (p[pc->k] & 0xf) << 2;
+ continue;
+
+ case BPF_LD|BPF_IMM:
+ A = pc->k;
+ continue;
+
+ case BPF_LDX|BPF_IMM:
+ X = pc->k;
+ continue;
+
+ case BPF_LD|BPF_MEM:
+ A = mem[pc->k];
+ continue;
+
+ case BPF_LDX|BPF_MEM:
+ X = mem[pc->k];
+ continue;
+
+#ifdef __NPF_x86__
+ //
+ // these instructions use the TME extensions,
+ // not supported on x86-64 and IA64 architectures.
+ //
+
+ /* LD NO PACKET INSTRUCTIONS */
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_B:
+ A= mem_ex->buffer[pc->k];
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_B:
+ X= mem_ex->buffer[pc->k];
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_H:
+ A = EXTRACT_SHORT(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_H:
+ X = EXTRACT_SHORT(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_W:
+ A = EXTRACT_LONG(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_W:
+ X = EXTRACT_LONG(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_B:
+ k = X + pc->k;
+ if ((int32)k>= (int32)mem_ex->size) {
+ return 0;
+ }
+ A= mem_ex->buffer[k];
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_H:
+ k = X + pc->k;
+ if ((int32)(k+1)>= (int32)mem_ex->size) {
+ return 0;
+ }
+ A=EXTRACT_SHORT((uint32*)&mem_ex->buffer[k]);
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_W:
+ k = X + pc->k;
+ if ((int32)(k+3)>= (int32)mem_ex->size) {
+ return 0;
+ }
+ A=EXTRACT_LONG((uint32*)&mem_ex->buffer[k]);
+ continue;
+/* END LD NO PACKET INSTRUCTIONS */
+#endif //__NPF_x86__
+
+ case BPF_ST:
+ mem[pc->k] = A;
+ continue;
+
+ case BPF_STX:
+ mem[pc->k] = X;
+ continue;
+
+#ifdef __NPF_x86__
+ //
+ // these instructions use the TME extensions,
+ // not supported on x86-64 and IA64 architectures.
+ //
+
+ /* STORE INSTRUCTIONS */
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_B:
+ mem_ex->buffer[pc->k]=(uint8)A;
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_B:
+ mem_ex->buffer[pc->k]=(uint8)X;
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_W:
+ tmp=A;
+ *(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp);
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_W:
+ tmp=X;
+ *(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp);
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16)A;
+ *(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2);
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16)X;
+ *(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2);
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_B:
+ mem_ex->buffer[pc->k+X]=(uint8)A;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_W:
+ tmp=A;
+ *(uint32*)&mem_ex->buffer[pc->k+X]=EXTRACT_LONG(&tmp);
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_H:
+ tmp2=(uint16)A;
+ *(uint16*)&mem_ex->buffer[pc->k+X]=EXTRACT_SHORT(&tmp2);
+ continue;
+/* END STORE INSTRUCTIONS */
+
+#endif //__NPF_x86__
+
+ case BPF_JMP|BPF_JA:
+ pc += pc->k;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_K:
+ pc += ((int)A > (int)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_K:
+ pc += ((int)A >= (int)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_K:
+ pc += ((int)A == (int)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_K:
+ pc += (A & pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_X:
+ pc += (A > X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_X:
+ pc += (A >= X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_X:
+ pc += (A == X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_X:
+ pc += (A & X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_ALU|BPF_ADD|BPF_X:
+ A += X;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_X:
+ A -= X;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_X:
+ A *= X;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_X:
+ if (X == 0)
+ return 0;
+ A /= X;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_X:
+ A &= X;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_X:
+ A |= X;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_X:
+ A <<= X;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_X:
+ A >>= X;
+ continue;
+
+ case BPF_ALU|BPF_ADD|BPF_K:
+ A += pc->k;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_K:
+ A -= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_K:
+ A *= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_K:
+ A /= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_K:
+ A &= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_K:
+ A |= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_K:
+ A <<= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_K:
+ A >>= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_NEG:
+ (int)A = -((int)A);
+ continue;
+
+ case BPF_MISC|BPF_TAX:
+ X = A;
+ continue;
+
+ case BPF_MISC|BPF_TXA:
+ A = X;
+ continue;
+
+#ifdef __NPF_x86__
+ //
+ // these instructions use the TME extensions,
+ // not supported on x86-64 and IA64 architectures.
+ //
+
+ /* TME INSTRUCTIONS */
+ case BPF_MISC|BPF_TME|BPF_LOOKUP:
+ j=lookup_frontend(mem_ex,tme,pc->k,time_ref);
+ if (j==TME_ERROR)
+ return 0;
+ pc += (j == TME_TRUE) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_EXECUTE:
+ if (execute_frontend(mem_ex,tme,wirelen,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_ACTIVE:
+ if (set_active_tme_block(tme,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE:
+ if (get_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,&j)==TME_ERROR)
+ return 0;
+ A=j;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE:
+ if (set_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,A,FALSE)==TME_ERROR)
+ return 0;
+ continue;
+ /* END TME INSTRUCTIONS */
+
+#endif //__NPF_x86__
+
+ }
+ }
+}
+
+//-------------------------------------------------------------------
+
+u_int bpf_filter_with_2_buffers(pc, p, pd, headersize, wirelen, buflen, mem_ex,tme,time_ref)
+ register struct bpf_insn *pc;
+ register u_char *p;
+ register u_char *pd;
+ register int headersize;
+ u_int wirelen;
+ register u_int buflen;
+ PMEM_TYPE mem_ex;
+ PTME_CORE tme;
+ struct time_conv *time_ref;
+{
+ register u_int32 A, X;
+ register int k;
+ int32 mem[BPF_MEMWORDS];
+// u_int32 j,tmp;
+// u_short tmp2;
+
+ if (pc == 0)
+ /*
+ * No filter means accept all.
+ */
+ return (u_int)-1;
+ A = 0;
+ X = 0;
+ --pc;
+ while (1) {
+ ++pc;
+ switch (pc->code) {
+
+ default:
+
+ return 0;
+
+ case BPF_RET|BPF_K:
+ return (u_int)pc->k;
+
+ case BPF_RET|BPF_A:
+ return (u_int)A;
+
+ case BPF_LD|BPF_W|BPF_ABS:
+ k = pc->k;
+ if (k + 4 > (int)buflen) {
+ return 0;
+ }
+
+ if(k + 4 <= headersize)
+ A = EXTRACT_LONG(&p[k]);
+ else if(k + 3 == headersize)
+ {
+ A= (u_int32)*((u_char *)p+k)<<24|
+ (u_int32)*((u_char *)p+k+1)<<16|
+ (u_int32)*((u_char *)p+k+2)<<8|
+ (u_int32)*((u_char *)pd+k-headersize);
+ }
+ else if(k + 2 == headersize)
+ {
+ A= (u_int32)*((u_char *)p+k)<<24|
+ (u_int32)*((u_char *)p+k+1)<<16|
+ (u_int32)*((u_char *)pd+k-headersize)<<8|
+ (u_int32)*((u_char *)pd+k-headersize+1);
+ }
+ else if(k + 1 == headersize){
+ A= (u_int32)*((u_char *)p+k)<<24|
+ (u_int32)*((u_char *)pd+k-headersize+1)<<16|
+ (u_int32)*((u_char *)pd+k-headersize+2)<<8|
+ (u_int32)*((u_char *)pd+k-headersize+3);
+ }
+ else
+ A = EXTRACT_LONG(&pd[k-headersize]);
+
+ continue;
+
+ case BPF_LD|BPF_H|BPF_ABS:
+ k = pc->k;
+ if (k + sizeof(short) > buflen)
+ {
+ return 0;
+ }
+
+ if(k + 2 <= headersize)
+ A = EXTRACT_SHORT(&p[k]);
+ else if(k + 1 == headersize)
+ {
+ A= (u_short)*((u_char *)p+k)<<8|
+ (u_short)*((u_char *)pd+k-headersize);
+ }
+ else
+ A = EXTRACT_SHORT(&pd[k-headersize]);
+
+ continue;
+
+ case BPF_LD|BPF_B|BPF_ABS:
+ k = pc->k;
+ if ((int)k >= (int)buflen) {
+ return 0;
+ }
+
+ if(k +(int) sizeof(char) <= headersize)
+ A = p[k];
+ else
+ A = pd[k-headersize];
+
+ continue;
+
+ case BPF_LD|BPF_W|BPF_LEN:
+ A = wirelen;
+ continue;
+
+ case BPF_LDX|BPF_W|BPF_LEN:
+ X = wirelen;
+ continue;
+
+ case BPF_LD|BPF_W|BPF_IND:
+ k = X + pc->k;
+ if (k + sizeof(int32) > buflen) {
+ return 0;
+ }
+
+ if(k + 4 <= headersize)
+ A = EXTRACT_LONG(&p[k]);
+ else if(k + 3 == headersize)
+ {
+ A= (u_int32)*((u_char *)p+k)<<24|
+ (u_int32)*((u_char *)p+k+1)<<16|
+ (u_int32)*((u_char *)p+k+2)<<8|
+ (u_int32)*((u_char *)pd+k-headersize);
+ }
+ else if(k + 2 == headersize)
+ {
+ A= (u_int32)*((u_char *)p+k)<<24|
+ (u_int32)*((u_char *)p+k+1)<<16|
+ (u_int32)*((u_char *)pd+k-headersize)<<8|
+ (u_int32)*((u_char *)pd+k-headersize+1);
+ }
+ else if(k + 1 == headersize)
+ {
+ A= (u_int32)*((u_char *)p+k)<<24|
+ (u_int32)*((u_char *)pd+k-headersize+1)<<16|
+ (u_int32)*((u_char *)pd+k-headersize+2)<<8|
+ (u_int32)*((u_char *)pd+k-headersize+3);
+ }
+ else
+ A = EXTRACT_LONG(&pd[k-headersize]);
+
+ continue;
+
+ case BPF_LD|BPF_H|BPF_IND:
+ k = X + pc->k;
+ if (k + 2 > (int)buflen) {
+ return 0;
+ }
+
+ if(k + 2 <= headersize)
+ A = EXTRACT_SHORT(&p[k]);
+ else if(k +1 == headersize)
+ {
+ A= (u_short)*((u_char *)p+k)<<8|
+ (u_short)*((u_char *)pd+k-headersize);
+ }
+ else
+ A = EXTRACT_SHORT(&pd[k-headersize]);
+
+ continue;
+
+ case BPF_LD|BPF_B|BPF_IND:
+ k = X + pc->k;
+ if ((int)k >= (int)buflen) {
+ return 0;
+ }
+
+ if(k <= headersize)
+ A = p[k];
+ else
+ A = pd[k-headersize];
+
+ continue;
+
+ case BPF_LDX|BPF_MSH|BPF_B:
+ k = pc->k;
+ if ((int)k >= (int)buflen) {
+ return 0;
+ }
+
+ if((int)(pc->k) <= headersize)
+ X = (p[pc->k] & 0xf) << 2;
+ else
+ X = (pd[(pc->k)-headersize] & 0xf) << 2;
+
+ continue;
+
+ case BPF_LD|BPF_IMM:
+ A = pc->k;
+ continue;
+
+ case BPF_LDX|BPF_IMM:
+ X = pc->k;
+ continue;
+
+ case BPF_LD|BPF_MEM:
+ A = mem[pc->k];
+ continue;
+
+ case BPF_LDX|BPF_MEM:
+ X = mem[pc->k];
+ continue;
+
+#ifdef __NPF_x86__
+ //
+ // these instructions use the TME extensions,
+ // not supported on x86-64 and IA64 architectures.
+ //
+
+ /* LD NO PACKET INSTRUCTIONS */
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_B:
+ A= mem_ex->buffer[pc->k];
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_B:
+ X= mem_ex->buffer[pc->k];
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_H:
+ A = EXTRACT_SHORT(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_H:
+ X = EXTRACT_SHORT(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_W:
+ A = EXTRACT_LONG(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_W:
+ X = EXTRACT_LONG(&mem_ex->buffer[pc->k]);
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_B:
+ k = X + pc->k;
+ if ((int32)k>= (int32)mem_ex->size) {
+ return 0;
+ }
+ A= mem_ex->buffer[k];
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_H:
+ k = X + pc->k;
+ if ((int32)(k+1)>= (int32)mem_ex->size) {
+ return 0;
+ }
+ A=EXTRACT_SHORT((uint32*)&mem_ex->buffer[k]);
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_W:
+ k = X + pc->k;
+ if ((int32)(k+3)>= (int32)mem_ex->size) {
+ return 0;
+ }
+ A=EXTRACT_LONG((uint32*)&mem_ex->buffer[k]);
+ continue;
+ /* END LD NO PACKET INSTRUCTIONS */
+
+#endif //__NPF_x86__
+
+ case BPF_ST:
+ mem[pc->k] = A;
+ continue;
+
+ case BPF_STX:
+ mem[pc->k] = X;
+ continue;
+
+#ifdef __NPF_x86__
+ //
+ // these instructions use the TME extensions,
+ // not supported on x86-64 and IA64 architectures.
+ //
+
+ /* STORE INSTRUCTIONS */
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_B:
+ mem_ex->buffer[pc->k]=(uint8)A;
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_B:
+ mem_ex->buffer[pc->k]=(uint8)X;
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_W:
+ tmp=A;
+ *(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp);
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_W:
+ tmp=X;
+ *(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp);
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16)A;
+ *(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2);
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16)X;
+ *(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2);
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_B:
+ mem_ex->buffer[pc->k+X]=(uint8)A;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_W:
+ tmp=A;
+ *(uint32*)&mem_ex->buffer[pc->k+X]=EXTRACT_LONG(&tmp);
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_H:
+ tmp2=(uint16)A;
+ *(uint16*)&mem_ex->buffer[pc->k+X]=EXTRACT_SHORT(&tmp2);
+ continue;
+ /* END STORE INSTRUCTIONS */
+
+#endif //__NPF_x86__
+
+ case BPF_JMP|BPF_JA:
+ pc += pc->k;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_K:
+ pc += ((int)A > (int)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_K:
+ pc += ((int)A >= (int)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_K:
+ pc += ((int)A == (int)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_K:
+ pc += (A & pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_X:
+ pc += (A > X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_X:
+ pc += (A >= X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_X:
+ pc += (A == X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_X:
+ pc += (A & X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_ALU|BPF_ADD|BPF_X:
+ A += X;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_X:
+ A -= X;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_X:
+ A *= X;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_X:
+ if (X == 0)
+ return 0;
+ A /= X;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_X:
+ A &= X;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_X:
+ A |= X;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_X:
+ A <<= X;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_X:
+ A >>= X;
+ continue;
+
+ case BPF_ALU|BPF_ADD|BPF_K:
+ A += pc->k;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_K:
+ A -= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_K:
+ A *= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_K:
+ A /= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_K:
+ A &= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_K:
+ A |= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_K:
+ A <<= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_K:
+ A >>= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_NEG:
+ (int)A = -((int)A);
+ continue;
+
+ case BPF_MISC|BPF_TAX:
+ X = A;
+ continue;
+
+ case BPF_MISC|BPF_TXA:
+ A = X;
+ continue;
+
+#ifdef __NPF_x86__
+ //
+ // these instructions use the TME extensions,
+ // not supported on x86-64 and IA64 architectures.
+ //
+
+ /* TME INSTRUCTIONS */
+ case BPF_MISC|BPF_TME|BPF_LOOKUP:
+ j=lookup_frontend(mem_ex,tme,pc->k,time_ref);
+ if (j==TME_ERROR)
+ return 0;
+ pc += (j == TME_TRUE) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_EXECUTE:
+ if (execute_frontend(mem_ex,tme,wirelen,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_ACTIVE:
+ if (set_active_tme_block(tme,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE:
+ if (get_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,&j)==TME_ERROR)
+ return 0;
+ A=j;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE:
+ if (set_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,A,FALSE)==TME_ERROR)
+ return 0;
+ continue;
+ /* END TME INSTRUCTIONS */
+
+#endif //__NPF_x86__
+
+ }
+ }
+}
+
+int32
+bpf_validate(f, len,mem_ex_size)
+ struct bpf_insn *f;
+ int32 len;
+ uint32 mem_ex_size;
+{
+ register uint32 i, from;
+ register int32 j;
+ register struct bpf_insn *p;
+ int32 flag;
+
+ if (len < 1)
+ return 0;
+
+ for (i = 0; i < (uint32)len; ++i) {
+ p = &f[i];
+
+ IF_LOUD(DbgPrint("Validating program");)
+
+ flag=0;
+ for(j=0;j<VALID_INSTRUCTIONS_LEN;j++)
+ if (p->code==valid_instructions[j])
+ flag=1;
+ if (flag==0)
+ return 0;
+
+ IF_LOUD(DbgPrint("Validating program: no unknown instructions");)
+
+ switch (BPF_CLASS(p->code)) {
+ /*
+ * Check that memory operations use valid addresses.
+ */
+ case BPF_LD:
+ case BPF_LDX:
+ switch (BPF_MODE(p->code)) {
+ case BPF_IMM:
+ break;
+ case BPF_ABS:
+ case BPF_IND:
+ case BPF_MSH:
+ break;
+ case BPF_MEM:
+ if (p->k >= BPF_MEMWORDS)
+ return 0;
+ break;
+ case BPF_LEN:
+ break;
+ default:
+ return 0;
+ }
+ IF_LOUD(DbgPrint("Validating program: no wrong LD memory locations");)
+ break;
+ case BPF_ST:
+ case BPF_STX:
+#ifdef __NPF_x86__
+ if ((p->code &BPF_MEM_EX_IMM) == BPF_MEM_EX_IMM)
+ {
+ /*
+ * Check if key stores use valid addresses
+ */
+ switch (BPF_SIZE(p->code)) {
+
+ case BPF_W:
+ if (p->k+3 >= mem_ex_size)
+ return 0;
+ break;
+
+ case BPF_H:
+ if (p->k+1 >= mem_ex_size)
+ return 0;
+ break;
+
+ case BPF_B:
+ if (p->k >= mem_ex_size)
+ return 0;
+ break;
+ }
+ }
+ else
+#endif //__NPF_x86__
+ {
+ if ((p->code & BPF_MEM_EX_IND) != BPF_MEM_EX_IND)
+ {
+ if (p->k >= BPF_MEMWORDS)
+ return 0;
+ }
+ }
+ IF_LOUD(DbgPrint("Validating program: no wrong ST memory locations");)
+ break;
+ case BPF_ALU:
+ switch (BPF_OP(p->code)) {
+ case BPF_ADD:
+ case BPF_SUB:
+ case BPF_OR:
+ case BPF_AND:
+ case BPF_LSH:
+ case BPF_RSH:
+ case BPF_NEG:
+ break;
+ case BPF_DIV:
+ /*
+ * Check for constant division by 0.
+ */
+ if (BPF_RVAL(p->code) == BPF_K && p->k == 0)
+ return 0;
+ default:
+ return 0;
+ }
+ break;
+ case BPF_JMP:
+ /*
+ * Check that jumps are within the code block,
+ * and that unconditional branches don't go
+ * backwards as a result of an overflow.
+ * Unconditional branches have a 32-bit offset,
+ * so they could overflow; we check to make
+ * sure they don't. Conditional branches have
+ * an 8-bit offset, and the from address is <=
+ * BPF_MAXINSNS, and we assume that BPF_MAXINSNS
+ * is sufficiently small that adding 255 to it
+ * won't overflow.
+ *
+ * We know that len is <= BPF_MAXINSNS, and we
+ * assume that BPF_MAXINSNS is < the maximum size
+ * of a u_int, so that i + 1 doesn't overflow.
+ */
+ from = i + 1;
+ switch (BPF_OP(p->code)) {
+ case BPF_JA:
+ if (from + p->k < from || from + p->k >= (uint32)len)
+ return 0;
+ break;
+ case BPF_JEQ:
+ case BPF_JGT:
+ case BPF_JGE:
+ case BPF_JSET:
+ if (from + p->jt >= (uint32)len || from + p->jf >= (uint32)len)
+ return 0;
+ break;
+ default:
+ return 0;
+ }
+ IF_LOUD(DbgPrint("Validating program: no wrong JUMPS");)
+ break;
+ case BPF_RET:
+ break;
+ case BPF_MISC:
+ break;
+ default:
+ return 0;
+ }
+ }
+ return BPF_CLASS(f[len - 1].code) == BPF_RET;
+}
diff --git a/src/See/win_bpf_filter_init.c b/src/See/win_bpf_filter_init.c
new file mode 100644
index 00000000..7703a106
--- /dev/null
+++ b/src/See/win_bpf_filter_init.c
@@ -0,0 +1,509 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <GlobalConst.h>
+
+#include "tme.h"
+#include "win_bpf.h"
+
+/*
+ * Initialize the filter machine
+ */
+uint32 bpf_filter_init(register struct bpf_insn *pc, MEM_TYPE *mem_ex, TME_CORE *tme, struct time_conv *time_ref)
+{
+ register uint32 A, X;
+ int32 mem[BPF_MEMWORDS];
+ register int32 k;
+ uint32 *tmp;
+ uint16 *tmp2;
+ uint32 j;
+ if (pc == 0)
+ /*
+ * No filter means accept all.
+ */
+ return (uint32)-1;
+ A = 0;
+ X = 0;
+ --pc;
+ while (1) {
+ ++pc;
+ switch (pc->code) {
+
+ default:
+ return 0;
+
+/* RET INSTRUCTIONS */
+ case BPF_RET|BPF_K:
+ return (uint32)pc->k;
+
+ case BPF_RET|BPF_A:
+ return (uint32)A;
+/* END RET INSTRUCTIONS */
+
+/* LD NO PACKET INSTRUCTIONS */
+ case BPF_LD|BPF_IMM:
+ A = pc->k;
+ continue;
+
+ case BPF_LDX|BPF_IMM:
+ X = pc->k;
+ continue;
+
+ case BPF_LD|BPF_MEM:
+ A = mem[pc->k];
+ continue;
+
+ case BPF_LDX|BPF_MEM:
+ X = mem[pc->k];
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_B:
+ A= mem_ex->buffer[pc->k];
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_B:
+ X= mem_ex->buffer[pc->k];
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16*)&mem_ex->buffer[pc->k];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx,tmp2
+ xor eax, eax
+ mov ax, [ebx]
+ bswap eax
+ mov A, eax
+ pop ebx
+ pop eax
+ }
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16*)&mem_ex->buffer[pc->k];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx,tmp2
+ xor eax, eax
+ mov ax, [ebx]
+ bswap eax
+ mov X, eax
+ pop ebx
+ pop eax
+ }
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IMM|BPF_W:
+ tmp=(uint32*)&mem_ex->buffer[pc->k];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx,tmp
+ mov eax, [ebx]
+ bswap eax
+ mov A, eax
+ pop ebx
+ pop eax
+ }
+ continue;
+
+ case BPF_LDX|BPF_MEM_EX_IMM|BPF_W:
+ tmp=(uint32*)&mem_ex->buffer[pc->k];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx,tmp
+ mov eax, [ebx]
+ bswap eax
+ mov X, eax
+ pop ebx
+ pop eax
+ }
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_B:
+ k = X + pc->k;
+ if ((int32)k>= (int32)mem_ex->size) {
+ return 0;
+ }
+ A= mem_ex->buffer[k];
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_H:
+ k = X + pc->k;
+ if ((int32)(k+1)>= (int32)mem_ex->size) {
+ return 0;
+ }
+ tmp2=(uint16*)&mem_ex->buffer[k];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx,tmp2
+ xor eax, eax
+ mov ax, [ebx]
+ bswap eax
+ mov A, eax
+ pop ebx
+ pop eax
+ }
+ continue;
+
+ case BPF_LD|BPF_MEM_EX_IND|BPF_W:
+ k = X + pc->k;
+ if ((int32)(k+3)>= (int32)mem_ex->size) {
+ return 0;
+ }
+ tmp=(uint32*)&mem_ex->buffer[k];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx,tmp
+ mov eax, [ebx]
+ bswap eax
+ mov A, eax
+ pop ebx
+ pop eax
+ }
+ continue;
+/* END LD NO PACKET INSTRUCTIONS */
+
+/* STORE INSTRUCTIONS */
+ case BPF_ST:
+ mem[pc->k] = A;
+ continue;
+
+ case BPF_STX:
+ mem[pc->k] = X;
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_B:
+ mem_ex->buffer[pc->k]=(uint8)A;
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_B:
+ mem_ex->buffer[pc->k]=(uint8)X;
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_W:
+ tmp=(uint32*)&mem_ex->buffer[pc->k];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx, tmp
+ mov eax, A
+ bswap eax
+ mov [ebx], eax
+ pop ebx
+ pop eax
+ }
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_W:
+ tmp=(uint32*)&mem_ex->buffer[pc->k];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx, tmp
+ mov eax, X
+ bswap eax
+ mov [ebx], eax
+ pop ebx
+ pop eax
+ }
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16*)&mem_ex->buffer[pc->k];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx, tmp2
+ mov eax, A
+ xchg ah, al
+ mov [ebx], ax
+ pop ebx
+ pop eax
+ }
+ continue;
+
+ case BPF_STX|BPF_MEM_EX_IMM|BPF_H:
+ tmp2=(uint16*)&mem_ex->buffer[pc->k];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx, tmp2
+ mov eax, X
+ xchg ah, al
+ mov [ebx], ax
+ pop ebx
+ pop eax
+ }
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_B:
+ mem_ex->buffer[pc->k+X]=(uint8)A;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_W:
+ tmp=(uint32*)&mem_ex->buffer[pc->k+X];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx, tmp
+ mov eax, A
+ bswap eax
+ mov [ebx], eax
+ pop ebx
+ pop eax
+ }
+
+ continue;
+
+ case BPF_ST|BPF_MEM_EX_IND|BPF_H:
+ tmp2=(uint16*)&mem_ex->buffer[pc->k+X];
+ __asm
+ {
+ push eax
+ push ebx
+ mov ebx, tmp2
+ mov eax, A
+ xchg ah, al
+ mov [ebx], ax
+ pop ebx
+ pop eax
+ }
+ continue;
+/* END STORE INSTRUCTIONS */
+
+/* JUMP INSTRUCTIONS */
+ case BPF_JMP|BPF_JA:
+ pc += pc->k;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_K:
+ pc += ((int32)A > (int32)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_K:
+ pc += ((int32)A >= (int32)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_K:
+ pc += ((int32)A == (int32)pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_K:
+ pc += (A & pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_X:
+ pc += (A > X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_X:
+ pc += (A >= X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_X:
+ pc += (A == X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_X:
+ pc += (A & X) ? pc->jt : pc->jf;
+ continue;
+/* END JUMP INSTRUCTIONS */
+
+/* ARITHMETIC INSTRUCTIONS */
+ case BPF_ALU|BPF_ADD|BPF_X:
+ A += X;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_X:
+ A -= X;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_X:
+ A *= X;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_X:
+ if (X == 0)
+ return 0;
+ A /= X;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_X:
+ A &= X;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_X:
+ A |= X;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_X:
+ A <<= X;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_X:
+ A >>= X;
+ continue;
+
+ case BPF_ALU|BPF_ADD|BPF_K:
+ A += pc->k;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_K:
+ A -= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_K:
+ A *= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_K:
+ A /= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_K:
+ A &= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_K:
+ A |= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_K:
+ A <<= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_K:
+ A >>= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_NEG:
+ (int32)A = -((int32)A);
+ continue;
+/* ARITHMETIC INSTRUCTIONS */
+
+/* MISC INSTRUCTIONS */
+ case BPF_MISC|BPF_TAX:
+ X = A;
+ continue;
+
+ case BPF_MISC|BPF_TXA:
+ A = X;
+ continue;
+/* END MISC INSTRUCTIONS */
+
+/* TME INSTRUCTIONS */
+ case BPF_MISC|BPF_TME|BPF_LOOKUP:
+ j=lookup_frontend(mem_ex,tme,pc->k,time_ref);
+ if (j==TME_ERROR)
+ return 0;
+ pc += (j == TME_TRUE) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_EXECUTE:
+ if (execute_frontend(mem_ex,tme,0,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_INIT:
+ if (init_tme_block(tme,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_VALIDATE:
+ if (validate_tme_block(mem_ex,tme,A,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_MEMORY:
+ if (init_extended_memory(pc->k,mem_ex)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_ACTIVE:
+ if (set_active_tme_block(tme,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_ACTIVE_READ:
+ if (set_active_tme_block(tme,pc->k)==TME_ERROR)
+ return 0;
+ continue;
+ case BPF_MISC|BPF_TME|BPF_SET_WORKING:
+ if (pc->k>=MAX_TME_DATA_BLOCKS)
+ return 0;
+ tme->working=pc->k;
+ continue;
+
+
+
+ case BPF_MISC|BPF_TME|BPF_RESET:
+ if (reset_tme(tme)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE:
+ if (get_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,&j)==TME_ERROR)
+ return 0;
+ A=j;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE:
+ if (set_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,A,TRUE)==TME_ERROR)
+ return 0;
+ continue;
+
+ case BPF_MISC|BPF_TME|BPF_SET_AUTODELETION:
+ set_autodeletion(&tme->block_data[tme->working],pc->k);
+ continue;
+
+/* END TME INSTRUCTIONS */
+
+ }
+ }
+}
+
diff --git a/src/See/win_bpf_filter_init.h b/src/See/win_bpf_filter_init.h
new file mode 100644
index 00000000..c1ad028b
--- /dev/null
+++ b/src/See/win_bpf_filter_init.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2001 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __FILTER_INIT
+#define __FILTER_INIT
+
+#include "tme.h"
+
+#define INIT_OK 1
+#define INIT_ERROR 0
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+uint32 bpf_filter_init(register struct bpf_insn *pc,MEM_TYPE *mem_ex, TME_CORE *tme, struct time_conv *time_ref);
+#ifdef __cplusplus
+}
+#endif
+
+#endif