There's no point in keeping two almost identical packet drivers in the SVN.

svn path=/trunk/; revision=15575
This commit is contained in:
Filip Navara 2005-05-28 11:38:11 +00:00
parent f48663be6d
commit c5fc491484
35 changed files with 0 additions and 10460 deletions

View file

@ -1,36 +0,0 @@
# $Id$
PATH_TO_TOP = ../../..
#TARGET_TYPE = export_driver
TARGET_TYPE = driver
TARGET_NAME = packet
#TARGET_CFLAGS = -DDBG -DWIN_NT_DRIVER -DKQPC_TS -I$(PATH_TO_TOP)/ntoskrnl/include
TARGET_CFLAGS = -DDBG -DWIN_NT_DRIVER -DKQPC_TS -DUSE_KLOCKS -I$(PATH_TO_TOP)/ntoskrnl/include
TARGET_DDKLIBS = ndis.a
TARGET_OBJECTS = \
packet.o \
openclos.o \
read.o \
write.o \
dump.o \
jitter.o \
win_bpf_filter.o \
tme.o \
count_packets.o \
win_bpf_filter_init.o \
tcp_session.o \
memory_t.o \
time_calls.o \
functions.o \
bucket_lookup.o \
normal_lookup.o
include $(PATH_TO_TOP)/rules.mak
include $(TOOLS_PATH)/helper.mk

View file

@ -1,252 +0,0 @@
/*
* Copyright (c) 2001
* Politecnico di Torino. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the Politecnico
* di Torino, and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifdef WIN32
#include "tme.h"
#include "bucket_lookup.h"
#endif
#ifdef __FreeBSD__
#ifdef _KERNEL
#include <net/tme/tme.h>
#include <net/tme/bucket_lookup.h>
#else
#include <tme/tme.h>
#include <tme/bucket_lookup.h>
#endif
#endif
/* the key is represented by the initial and final value */
/* of the bucket. At the moment bucket_lookup is able to */
/* manage values of 16, 32 bits. */
uint32 bucket_lookup(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref)
{
uint32 value;
uint32 i,j;
int found=-1;
uint32 blocks;
uint32 block_size;
uint8 *temp;
if ((data->key_len!=1)&& /*16 bit value*/
(data->key_len!=2)) /*32 bit value*/
return TME_ERROR;
/*32 bit values*/
blocks=data->filled_blocks-1;
block_size=data->block_size;
i=blocks/2; /*relative shift*/
j=i;
temp=data->shared_memory_base_address+block_size;
if (data->key_len==2)
{
value=SW_ULONG_AT(key,0);
if((value<SW_ULONG_AT(temp,0))||(value>SW_ULONG_AT(temp+block_size*(blocks-1),4)))
{
uint32 *key32=(uint32*) key;
key32[0]=key32[1]=0;
GET_TIME((struct timeval *)(data->shared_memory_base_address+8),time_ref);
data->last_found=NULL;
return TME_FALSE;
}
while(found==-1) /* search routine */
{
i=(i==1)? 1:i>>1;
if (SW_ULONG_AT(temp+block_size*j,0)>value)
if (SW_ULONG_AT(temp+block_size*(j-1),4)<value)
found=-2;
else
j-=i;
else
if (SW_ULONG_AT(temp+block_size*j,4)<value)
if (SW_ULONG_AT(temp+block_size*j,0)>value)
found=-2;
else
j+=i;
else found=j;
}
if (found<0)
{
uint32 *key32=(uint32*) key;
key32[0]=key32[1]=0;
GET_TIME((struct timeval *)(data->shared_memory_base_address+8),time_ref);
data->last_found=NULL;
return TME_FALSE;
}
data->last_found=data->lut_base_address+found*sizeof(RECORD);
COPY_MEMORY(key,temp+block_size*found,8);
GET_TIME((struct timeval *)(temp+block_size*found+8),time_ref);
return TME_TRUE;
}
else
{
value=SW_USHORT_AT(key,0);
if((value<SW_USHORT_AT(temp,0))||(value>SW_USHORT_AT(temp+block_size*(blocks-1),2)))
{
uint16 *key16=(uint16*) key;
key16[0]=key16[1]=0;
GET_TIME((struct timeval *)(data->shared_memory_base_address+4),time_ref);
data->last_found=NULL;
return TME_FALSE;
}
while(found==-1) /* search routine */
{
i=(i==1)? 1:i>>1;
if (SW_USHORT_AT(temp+block_size*j,0)>value)
if (SW_USHORT_AT(temp+block_size*(j-1),2)<value)
found=-2;
else
j-=i;
else
if (SW_USHORT_AT(temp+block_size*j,2)<value)
if (SW_USHORT_AT(temp+block_size*j,0)>value)
found=-2;
else
j+=i;
else found=j;
}
if (found<0)
{
uint16 *key16=(uint16*) key;
key16[0]=key16[1]=0;
GET_TIME((struct timeval *)(data->shared_memory_base_address+4),time_ref);
data->last_found=NULL;
return TME_FALSE;
}
data->last_found=data->lut_base_address+found*sizeof(RECORD);
GET_TIME((struct timeval *)(temp+block_size*found+4),time_ref);
COPY_MEMORY(key,temp+block_size*found,4);
return TME_TRUE;
}
}
uint32 bucket_lookup_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref)
{
RECORD *records=(RECORD*)data->lut_base_address;
if ((data->key_len!=1)&& /*16 bit value*/
(data->key_len!=2)) /*32 bit value*/
return TME_ERROR;
if(data->key_len==2)
{
uint32 start,stop;
uint8 *tmp;
start=SW_ULONG_AT(key,0);
stop=SW_ULONG_AT(key,4);
if (start>stop)
return TME_ERROR;
if (data->filled_entries>0)
{
tmp=mem_ex->buffer+SW_ULONG_AT(&records[data->filled_entries-1].block,0);
/*check if it is coherent with the previous block*/
if (SW_ULONG_AT(tmp,4)>=start)
return TME_ERROR;
}
if (data->filled_blocks==data->shared_memory_blocks)
return TME_ERROR;
if (data->filled_entries==data->lut_entries)
return TME_ERROR;
tmp=data->shared_memory_base_address+data->block_size*data->filled_blocks;
COPY_MEMORY(tmp,key,8);
SW_ULONG_ASSIGN(&records[data->filled_entries].block,tmp-mem_ex->buffer);
SW_ULONG_ASSIGN(&records[data->filled_entries].exec_fcn,data->default_exec);
GET_TIME((struct timeval *)(tmp+8),time_ref);
data->filled_blocks++;
data->filled_entries++;
return TME_TRUE;
}
else
{
uint16 start,stop;
uint8 *tmp;
start=SW_USHORT_AT(key,0);
stop=SW_USHORT_AT(key,2);
if (start>stop)
return TME_ERROR;
if (data->filled_entries>0)
{
tmp=mem_ex->buffer+SW_ULONG_AT(&records[data->filled_entries-1].block,0);
/*check if it is coherent with the previous block*/
if (SW_USHORT_AT(tmp,2)>=start)
return TME_ERROR;
}
if (data->filled_blocks==data->shared_memory_blocks)
return TME_ERROR;
if (data->filled_entries==data->lut_entries)
return TME_ERROR;
tmp=mem_ex->buffer+SW_ULONG_AT(&records[data->filled_entries].block,0);
COPY_MEMORY(tmp,key,4);
SW_ULONG_ASSIGN(&records[data->filled_entries].block,tmp-mem_ex->buffer);
SW_ULONG_ASSIGN(&records[data->filled_entries].exec_fcn,data->default_exec);
GET_TIME((struct timeval *)(tmp+4),time_ref);
data->filled_blocks++;
data->filled_entries++;
return TME_TRUE;
}
}

View file

@ -1,44 +0,0 @@
/*
* Copyright (c) 2001
* Politecnico di Torino. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the Politecnico
* di Torino, and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef __bucket_lookup
#define __bucket_lookup
#ifdef WIN32
#include "tme.h"
#endif
#ifdef __FreeBSD__
#ifdef _KERNEL
#include <net/tme/tme.h>
#else
#include <tme/tme.h>
#endif
#endif
#define BUCKET_LOOKUP_INSERT 0x00000011
uint32 bucket_lookup_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);
#define BUCKET_LOOKUP 0x00000010
uint32 bucket_lookup(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);
#endif

View file

@ -1,51 +0,0 @@
/*
* Copyright (c) 2001
* Politecnico di Torino. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the Politecnico
* di Torino, and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifdef WIN32
#include "tme.h"
#include "count_packets.h"
#endif
#ifdef __FreeBSD__
#ifdef _KERNEL
#include <net/tme/tme.h>
#include <net/tme/count_packets.h>
#else
#include <tme/tme.h>
#include <tme/count_packets.h>
#endif
#endif
uint32 count_packets(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data)
{
c_p_data *counters=(c_p_data*)(block+data->key_len*4);
counters->bytes+=pkt_size;
counters->packets++;
return TME_SUCCESS;
}

View file

@ -1,51 +0,0 @@
/*
* Copyright (c) 2001
* Politecnico di Torino. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the Politecnico
* di Torino, and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef __count_packets
#define __count_packets
#ifdef WIN32
#include "tme.h"
#endif
#ifdef __FreeBSD__
#ifdef _KERNEL
#include <net/tme/tme.h>
#else
#include <tme/tme.h>
#endif
#endif
typedef struct __c_p_data
{
struct timeval timestamp;
uint64 packets;
uint64 bytes;
}
c_p_data;
#define COUNT_PACKETS 0x00000000
uint32 count_packets(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data);
#endif

View file

@ -1,52 +0,0 @@
/*
* Copyright (c) 1999, 2000
* Politecnico di Torino. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the Politecnico
* di Torino, and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#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*/

View file

@ -1,592 +0,0 @@
/*
* Copyright (c) 1999, 2000
* Politecnico di Torino. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the Politecnico
* di Torino, and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifdef _MSC_VER
#include "stdarg.h"
#include "ntddk.h"
#include "ntiologc.h"
#include "ndis.h"
#else
#include <ddk/ntddk.h>
#include <net/ndis.h>
//#define PsGetCurrentProcess() IoGetCurrentProcess()
#ifndef PsGetCurrentThread
#define PsGetCurrentThread() ((PETHREAD) (KeGetCurrentThread()))
#endif
#endif
#include "debug.h"
#include "packet.h"
#include "win_bpf.h"
//-------------------------------------------------------------------
NTSTATUS
NPF_OpenDumpFile(POPEN_INSTANCE Open , PUNICODE_STRING fileName, BOOLEAN Append)
{
NTSTATUS ntStatus;
IO_STATUS_BLOCK IoStatus;
OBJECT_ATTRIBUTES ObjectAttributes;
PWCHAR PathPrefix;
USHORT PathLen;
UNICODE_STRING FullFileName;
ULONG FullFileNameLength;
PDEVICE_OBJECT fsdDevice;
FILE_STANDARD_INFORMATION StandardInfo;
IF_LOUD(DbgPrint("NPF: OpenDumpFile.\n");)
if(fileName->Buffer[0] == L'\\' &&
fileName->Buffer[1] == L'?' &&
fileName->Buffer[2] == L'?' &&
fileName->Buffer[3] == L'\\'
){
PathLen = 0;
}
else{
PathPrefix = L"\\??\\";
PathLen = 8;
}
// Insert the correct path prefix.
FullFileNameLength = PathLen + fileName->MaximumLength;
#define NPF_TAG_FILENAME TAG('0', 'D', 'W', 'A')
FullFileName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
FullFileNameLength,
NPF_TAG_FILENAME);
if (FullFileName.Buffer == NULL) {
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
return ntStatus;
}
FullFileName.Length = PathLen;
FullFileName.MaximumLength = (USHORT)FullFileNameLength;
if(PathLen)
RtlMoveMemory (FullFileName.Buffer, PathPrefix, PathLen);
RtlAppendUnicodeStringToString (&FullFileName, fileName);
IF_LOUD(DbgPrint( "Packet: Attempting to open %wZ\n", &FullFileName);)
InitializeObjectAttributes ( &ObjectAttributes,
&FullFileName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL );
// Create the dump file
ntStatus = ZwCreateFile( &Open->DumpFileHandle,
SYNCHRONIZE | FILE_WRITE_DATA,
&ObjectAttributes,
&IoStatus,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
(Append)?FILE_OPEN_IF:FILE_SUPERSEDE,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0 );
if ( !NT_SUCCESS( ntStatus ) )
{
IF_LOUD(DbgPrint("NPF: Error opening file %x\n", ntStatus);)
ExFreePool(FullFileName.Buffer);
Open->DumpFileHandle=NULL;
ntStatus = STATUS_NO_SUCH_FILE;
return ntStatus;
}
ExFreePool(FullFileName.Buffer);
ntStatus = ObReferenceObjectByHandle(Open->DumpFileHandle,
FILE_WRITE_ACCESS,
#ifndef __GNUC__
*IoFileObjectType,
#else
IoFileObjectType,
#endif
KernelMode,
(PVOID)&Open->DumpFileObject,
0);
if ( !NT_SUCCESS( ntStatus ) )
{
IF_LOUD(DbgPrint("NPF: Error creating file, status=%x\n", ntStatus);)
ZwClose( Open->DumpFileHandle );
Open->DumpFileHandle=NULL;
ntStatus = STATUS_NO_SUCH_FILE;
return ntStatus;
}
fsdDevice = IoGetRelatedDeviceObject(Open->DumpFileObject);
IF_LOUD(DbgPrint("NPF: Dump: write file created succesfully, status=%d \n",ntStatus);)
return ntStatus;
}
//-------------------------------------------------------------------
NTSTATUS
NPF_StartDump(POPEN_INSTANCE Open)
{
NTSTATUS ntStatus;
struct packet_file_header hdr;
IO_STATUS_BLOCK IoStatus;
NDIS_REQUEST pRequest;
ULONG MediaType;
OBJECT_ATTRIBUTES ObjectAttributes;
IF_LOUD(DbgPrint("NPF: StartDump.\n");)
// Init the file header
hdr.magic = TCPDUMP_MAGIC;
hdr.version_major = PCAP_VERSION_MAJOR;
hdr.version_minor = PCAP_VERSION_MINOR;
hdr.thiszone = 0; /*Currently not set*/
hdr.snaplen = 1514;
hdr.sigfigs = 0;
// Detect the medium type
switch (Open->Medium){
case NdisMediumWan:
hdr.linktype = DLT_EN10MB;
break;
case NdisMedium802_3:
hdr.linktype = DLT_EN10MB;
break;
case NdisMediumFddi:
hdr.linktype = DLT_FDDI;
break;
case NdisMedium802_5:
hdr.linktype = DLT_IEEE802;
break;
case NdisMediumArcnet878_2:
hdr.linktype = DLT_ARCNET;
break;
case NdisMediumAtm:
hdr.linktype = DLT_ATM_RFC1483;
break;
default:
hdr.linktype = DLT_EN10MB;
}
// Write the header.
// We can use ZwWriteFile because we are in the context of the application
ntStatus = ZwWriteFile(Open->DumpFileHandle,
NULL,
NULL,
NULL,
&IoStatus,
&hdr,
sizeof(hdr),
NULL,
NULL );
if ( !NT_SUCCESS( ntStatus ) )
{
IF_LOUD(DbgPrint("NPF: Error dumping file %x\n", ntStatus);)
ZwClose( Open->DumpFileHandle );
Open->DumpFileHandle=NULL;
ntStatus = STATUS_NO_SUCH_FILE;
return ntStatus;
}
Open->DumpOffset.QuadPart=24;
ntStatus = PsCreateSystemThread(&Open->DumpThreadHandle,
THREAD_ALL_ACCESS,
(ACCESS_MASK)0L,
0,
0,
(PKSTART_ROUTINE)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,
(VOID **)&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->BufSize==0){ // BufSize=0 means that this instance was closed, or that the buffer is too
// small for any capture. In both cases it is better to end the dump
IF_LOUD(DbgPrint("NPF: Worker Thread - Exiting happily\n");)
IF_LOUD(DbgPrint("Thread: Dumpoffset=%I64d\n",Open->DumpOffset.QuadPart);)
PsTerminateSystemThread(STATUS_SUCCESS);
return;
}
NdisResetEvent(&Open->DumpEvent);
// Write the content of the buffer to the file
if(NPF_SaveCurrentBuffer(Open) != STATUS_SUCCESS){
PsTerminateSystemThread(STATUS_SUCCESS);
return;
}
}
}
//-------------------------------------------------------------------
NTSTATUS NPF_SaveCurrentBuffer(POPEN_INSTANCE Open)
{
UINT Thead;
UINT Ttail;
UINT TLastByte;
PUCHAR CurrBuff;
NTSTATUS ntStatus;
IO_STATUS_BLOCK IoStatus;
PMDL lMdl;
UINT SizeToDump;
Thead=Open->Bhead;
Ttail=Open->Btail;
TLastByte=Open->BLastByte;
IF_LOUD(DbgPrint("NPF: NPF_SaveCurrentBuffer.\n");)
// Get the address of the buffer
CurrBuff=Open->Buffer;
//
// Fill the application buffer
//
if( Ttail < Thead )
{
if(Open->MaxDumpBytes &&
(UINT)Open->DumpOffset.QuadPart + GetBuffOccupation(Open) > Open->MaxDumpBytes)
{
// Size limit reached
UINT PktLen;
SizeToDump = 0;
// Scan the buffer to detect the exact amount of data to save
while(TRUE){
PktLen = ((struct sf_pkthdr*)(CurrBuff + Thead + SizeToDump))->caplen + sizeof(struct sf_pkthdr);
if((UINT)Open->DumpOffset.QuadPart + SizeToDump + PktLen > Open->MaxDumpBytes)
break;
SizeToDump += PktLen;
}
}
else
SizeToDump = TLastByte-Thead;
lMdl=IoAllocateMdl(CurrBuff+Thead, SizeToDump, FALSE, FALSE, NULL);
if (lMdl == NULL)
{
// No memory: stop dump
IF_LOUD(DbgPrint("NPF: dump thread: Failed to allocate Mdl\n");)
return STATUS_UNSUCCESSFUL;
}
MmBuildMdlForNonPagedPool(lMdl);
// Write to disk
NPF_WriteDumpFile(Open->DumpFileObject,
&Open->DumpOffset,
SizeToDump,
lMdl,
&IoStatus);
IoFreeMdl(lMdl);
if(!NT_SUCCESS(IoStatus.Status)){
// Error
return STATUS_UNSUCCESSFUL;
}
if(SizeToDump != TLastByte-Thead){
// Size limit reached.
Open->DumpLimitReached = TRUE;
// Awake the application
KeSetEvent(Open->ReadEvent,0,FALSE);
return STATUS_UNSUCCESSFUL;
}
// Update the packet buffer
Open->DumpOffset.QuadPart+=(TLastByte-Thead);
Open->BLastByte=Ttail;
Open->Bhead=0;
}
if( Ttail > Thead ){
if(Open->MaxDumpBytes &&
(UINT)Open->DumpOffset.QuadPart + GetBuffOccupation(Open) > Open->MaxDumpBytes)
{
// Size limit reached
UINT PktLen;
SizeToDump = 0;
// Scan the buffer to detect the exact amount of data to save
while(Thead + SizeToDump < Ttail){
PktLen = ((struct sf_pkthdr*)(CurrBuff + Thead + SizeToDump))->caplen + sizeof(struct sf_pkthdr);
if((UINT)Open->DumpOffset.QuadPart + SizeToDump + PktLen > Open->MaxDumpBytes)
break;
SizeToDump += PktLen;
}
}
else
SizeToDump = Ttail-Thead;
lMdl=IoAllocateMdl(CurrBuff+Thead, SizeToDump, FALSE, FALSE, NULL);
if (lMdl == NULL)
{
// No memory: stop dump
IF_LOUD(DbgPrint("NPF: dump thread: Failed to allocate Mdl\n");)
return STATUS_UNSUCCESSFUL;
}
MmBuildMdlForNonPagedPool(lMdl);
// Write to disk
NPF_WriteDumpFile(Open->DumpFileObject,
&Open->DumpOffset,
SizeToDump,
lMdl,
&IoStatus);
IoFreeMdl(lMdl);
if(!NT_SUCCESS(IoStatus.Status)){
// Error
return STATUS_UNSUCCESSFUL;
}
if(SizeToDump != Ttail-Thead){
// Size limit reached.
Open->DumpLimitReached = TRUE;
// Awake the application
KeSetEvent(Open->ReadEvent,0,FALSE);
return STATUS_UNSUCCESSFUL;
}
// Update the packet buffer
Open->DumpOffset.QuadPart+=(Ttail-Thead);
Open->Bhead=Ttail;
}
return STATUS_SUCCESS;
}
//-------------------------------------------------------------------
NTSTATUS NPF_CloseDumpFile(POPEN_INSTANCE Open){
NTSTATUS ntStatus;
IO_STATUS_BLOCK IoStatus;
PMDL WriteMdl;
PUCHAR VMBuff;
UINT VMBufLen;
IF_LOUD(DbgPrint("NPF: NPF_CloseDumpFile.\n");)
IF_LOUD(DbgPrint("Dumpoffset=%d\n",Open->DumpOffset.QuadPart);)
DbgPrint("1\n");
// Consistency check
if(Open->DumpFileHandle == NULL)
return STATUS_UNSUCCESSFUL;
DbgPrint("2\n");
ZwClose( Open->DumpFileHandle );
ObDereferenceObject(Open->DumpFileObject);
/*
if(Open->DumpLimitReached == TRUE)
// Limit already reached: don't save the rest of the buffer.
return STATUS_SUCCESS;
*/
DbgPrint("3\n");
NPF_OpenDumpFile(Open,&Open->DumpFileName, TRUE);
// Flush the buffer to file
NPF_SaveCurrentBuffer(Open);
// Close The file
ObDereferenceObject(Open->DumpFileObject);
ZwClose( Open->DumpFileHandle );
Open->DumpFileHandle = NULL;
ObDereferenceObject(Open->DumpFileObject);
return STATUS_SUCCESS;
}
//-------------------------------------------------------------------
#ifndef __GNUC__
static NTSTATUS
#else
NTSTATUS STDCALL
#endif
PacketDumpCompletion(PDEVICE_OBJECT DeviceObject,
PIRP Irp,
PVOID Context)
{
// Copy the status information back into the "user" IOSB
*Irp->UserIosb = Irp->IoStatus;
// Wake up the mainline code
KeSetEvent(Irp->UserEvent, 0, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
//-------------------------------------------------------------------
VOID NPF_WriteDumpFile(PFILE_OBJECT FileObject,
PLARGE_INTEGER Offset,
ULONG Length,
PMDL Mdl,
PIO_STATUS_BLOCK IoStatusBlock)
{
PIRP irp;
KEVENT event;
PIO_STACK_LOCATION ioStackLocation;
PDEVICE_OBJECT fsdDevice = IoGetRelatedDeviceObject(FileObject);
NTSTATUS Status;
// Set up the event we'll use
KeInitializeEvent(&event, SynchronizationEvent, FALSE);
// Allocate and build the IRP we'll be sending to the FSD
irp = IoAllocateIrp(fsdDevice->StackSize, FALSE);
if (!irp) {
// Allocation failed, presumably due to memory allocation failure
IoStatusBlock->Status = STATUS_INSUFFICIENT_RESOURCES;
IoStatusBlock->Information = 0;
return;
}
irp->MdlAddress = Mdl;
irp->UserEvent = &event;
irp->UserIosb = IoStatusBlock;
irp->Tail.Overlay.Thread = PsGetCurrentThread();
irp->Tail.Overlay.OriginalFileObject= FileObject;
irp->RequestorMode = KernelMode;
// Indicate that this is a WRITE operation
irp->Flags = IRP_WRITE_OPERATION;
// Set up the next I/O stack location
ioStackLocation = IoGetNextIrpStackLocation(irp);
ioStackLocation->MajorFunction = IRP_MJ_WRITE;
ioStackLocation->MinorFunction = 0;
ioStackLocation->DeviceObject = fsdDevice;
ioStackLocation->FileObject = FileObject;
IoSetCompletionRoutine(irp, PacketDumpCompletion, 0, TRUE, TRUE, TRUE);
ioStackLocation->Parameters.Write.Length = Length;
ioStackLocation->Parameters.Write.ByteOffset = *Offset;
// Send it on. Ignore the return code
(void) IoCallDriver(fsdDevice, irp);
// Wait for the I/O to complete.
KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, 0);
// Free the IRP now that we are done with it
IoFreeIrp(irp);
return;
}

View file

@ -1,83 +0,0 @@
/*
* Copyright (c) 2001
* Politecnico di Torino. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the Politecnico
* di Torino, and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifdef WIN32
#include "tme.h"
#include "functions.h"
#endif
#ifdef __FreeBSD__
#ifdef _KERNEL
#include <net/tme/tme.h>
#include <net/bpf.h>
#include <net/tme/functions.h>
#else
#include <tme/tme.h>
#include <bpf.h>
#include <tme/functions.h>
#endif
#endif
lut_fcn lut_fcn_mapper(uint32 index)
{
switch (index)
{
case NORMAL_LUT_W_INSERT:
return (lut_fcn) normal_lut_w_insert;
case NORMAL_LUT_WO_INSERT:
return (lut_fcn) normal_lut_wo_insert;
case BUCKET_LOOKUP:
return (lut_fcn) bucket_lookup;
case BUCKET_LOOKUP_INSERT:
return (lut_fcn) bucket_lookup_insert;
default:
return NULL;
}
return NULL;
}
exec_fcn exec_fcn_mapper(uint32 index)
{
switch (index)
{
case COUNT_PACKETS:
return (exec_fcn) count_packets;
case TCP_SESSION:
return (exec_fcn) tcp_session;
default:
return NULL;
}
return NULL;
}

View file

@ -1,68 +0,0 @@
/*
* Copyright (c) 2001
* Politecnico di Torino. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the Politecnico
* di Torino, and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef __FUNCTIONS
#define __FUNCTIONS
#ifdef WIN32
#include "tme.h"
#endif
#ifdef __FreeBSD__
#ifdef _KERNEL
#include <net/tme/tme.h>
#else
#include <tme/tme.h>
#endif
#endif
/*function mappers */
lut_fcn lut_fcn_mapper(uint32 index);
exec_fcn exec_fcn_mapper(uint32 index);
/* lookup functions */
#ifdef WIN32
#include "bucket_lookup.h"
#include "normal_lookup.h"
#endif
#ifdef __FreeBSD__
#include <net/tme/bucket_lookup.h>
#include <net/tme/normal_lookup.h>
#endif
/* execution functions */
#ifdef WIN32
#include "count_packets.h"
#include "tcp_session.h"
#endif
#ifdef __FreeBSD__
#include <net/tme/count_packets.h>
#include <ne/tme/tcp_session.h>
#endif
#endif

View file

@ -1,681 +0,0 @@
/*
* Copyright (c) 2002
* Politecnico di Torino. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the Politecnico
* di Torino, and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifdef _MSC_VER
#include "stdarg.h"
#include "ntddk.h"
#include "ntiologc.h"
#include "ndis.h"
#else
#include <ddk/ntddk.h>
#include <net/ndis.h>
#endif
#include "packet.h"
#include "win_bpf.h"
emit_func emitm;
//
// emit routine to update the jump table
//
void emit_lenght(binary_stream *stream, ULONG value, UINT len)
{
(stream->refs)[stream->bpf_pc]+=len;
stream->cur_ip+=len;
}
//
// emit routine to output the actual binary code
//
void emit_code(binary_stream *stream, ULONG value, UINT len)
{
switch (len){
case 1:
stream->ibuf[stream->cur_ip]=(UCHAR)value;
stream->cur_ip++;
break;
case 2:
*((USHORT*)(stream->ibuf+stream->cur_ip))=(USHORT)value;
stream->cur_ip+=2;
break;
case 4:
*((ULONG*)(stream->ibuf+stream->cur_ip))=value;
stream->cur_ip+=4;
break;
default:;
}
return;
}
//
// Function that does the real stuff
//
BPF_filter_function BPFtoX86(struct bpf_insn *prog, UINT nins, INT *mem)
{
struct bpf_insn *ins;
UINT i, pass;
binary_stream stream;
// Allocate the reference table for the jumps
#ifdef NTKERNEL
#define NPF_TAG_REFTABLE TAG('0', 'J', 'W', 'A')
stream.refs=(UINT *)ExAllocatePoolWithTag(NonPagedPool, (nins + 1)*sizeof(UINT), NPF_TAG_REFTABLE);
#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
#define NPF_TAG_STREAMBUF TAG('1', 'J', 'W', 'A')
stream.ibuf=(CHAR*)ExAllocatePoolWithTag(NonPagedPool, stream.cur_ip, NPF_TAG_STREAMBUF);
#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
#define NPF_TAG_FILTSTRUCT TAG('2', 'J', 'W', 'A')
Filter=(struct JIT_BPF_Filter*)ExAllocatePoolWithTag(NonPagedPool, sizeof(struct JIT_BPF_Filter), NPF_TAG_FILTSTRUCT);
#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
#define NPF_TAG_FILTMEM TAG('3', 'J', 'W', 'A')
Filter->mem=(INT*)ExAllocatePoolWithTag(NonPagedPool, BPF_MEMWORDS*sizeof(INT), NPF_TAG_FILTMEM);
#else
Filter->mem=(INT*)malloc(BPF_MEMWORDS*sizeof(INT));
#endif
if(Filter->mem==NULL)
{
#ifdef NTKERNEL
ExFreePool(Filter);
#else
free(Filter);
#endif
return NULL;
}
// Create the binary
if((Filter->Function = BPFtoX86(fp, nins, Filter->mem))==NULL)
{
#ifdef NTKERNEL
ExFreePool(Filter->mem);
ExFreePool(Filter);
#else
free(Filter->mem);
free(Filter);
return NULL;
#endif
}
return Filter;
}
//////////////////////////////////////////////////////////////
void BPF_Destroy_JIT_Filter(JIT_BPF_Filter *Filter){
#ifdef NTKERNEL
ExFreePool(Filter->mem);
ExFreePool(Filter->Function);
ExFreePool(Filter);
#else
free(Filter->mem);
free(Filter->Function);
free(Filter);
#endif
}

View file

@ -1,391 +0,0 @@
/*
* Copyright (c) 2002
* Politecnico di Torino. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the Politecnico
* di Torino, and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/** @ingroup NPF
* @{
*/
/** @defgroup NPF_include NPF structures and definitions
* @{
*/
//
// Registers
//
#define EAX 0
#define ECX 1
#define EDX 2
#define EBX 3
#define ESP 4
#define EBP 5
#define ESI 6
#define EDI 7
#define AX 0
#define CX 1
#define DX 2
#define BX 3
#define SP 4
#define BP 5
#define SI 6
#define DI 7
#define AL 0
#define CL 1
#define DL 2
#define BL 3
/*! \brief A stream of X86 binary code.*/
typedef struct binary_stream{
INT cur_ip; ///< Current X86 instruction pointer.
INT bpf_pc; ///< Current BPF instruction pointer, i.e. position in the BPF program reached by the jitter.
PCHAR ibuf; ///< Instruction buffer, contains the X86 generated code.
PUINT refs; ///< Jumps reference table.
}binary_stream;
/*! \brief Prototype of a filtering function created by the jitter.
The syntax and the meaning of the parameters is analogous to the one of bpf_filter(). Notice that the filter
is not among the parameters, because it is hardwired in the function.
*/
typedef UINT (*BPF_filter_function)( binary_stream *, ULONG, UINT);
/*! \brief Prototype of the emit functions.
Different emit functions are used to create the reference table and to generate the actual filtering code.
This allows to have simpler instruction macros.
The first parameter is the stream that will receive the data. The secon one is a variable containing
the data, the third one is the length, that can be 1,2 or 4 since it is possible to emit a byte, a short
or a work at a time.
*/
typedef void (*emit_func)(binary_stream *stream, ULONG value, UINT n);
/*! \brief Structure describing a x86 filtering program created by the jitter.*/
typedef struct JIT_BPF_Filter{
BPF_filter_function Function; ///< The x86 filtering binary, in the form of a BPF_filter_function.
PINT mem;
}
JIT_BPF_Filter;
/**************************/
/* X86 INSTRUCTION MACROS */
/**************************/
/// mov r32,i32
#define MOVid(r32, i32) \
emitm(&stream, 11 << 4 | 1 << 3 | r32 & 0x7, 1); emitm(&stream, i32, 4);
/// mov dr32,sr32
#define MOVrd(dr32, sr32) \
emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
/// mov dr32,sr32[off]
#define MOVodd(dr32, sr32, off) \
emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \
emitm(&stream, 1 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);\
emitm(&stream, off, 1);
/// mov dr32,sr32[or32]
#define MOVobd(dr32, sr32, or32) \
emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \
emitm(&stream, (dr32 & 0x7) << 3 | 4 , 1);\
emitm(&stream, (or32 & 0x7) << 3 | (sr32 & 0x7) , 1);
/// mov dr16,sr32[or32]
#define MOVobw(dr32, sr32, or32) \
emitm(&stream, 0x66, 1); \
emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \
emitm(&stream, (dr32 & 0x7) << 3 | 4 , 1);\
emitm(&stream, (or32 & 0x7) << 3 | (sr32 & 0x7) , 1);
/// mov dr8,sr32[or32]
#define MOVobb(dr8, sr32, or32) \
emitm(&stream, 0x8a, 1); \
emitm(&stream, (dr8 & 0x7) << 3 | 4 , 1);\
emitm(&stream, (or32 & 0x7) << 3 | (sr32 & 0x7) , 1);
/// mov [dr32][or32],sr32
#define MOVomd(dr32, or32, sr32) \
emitm(&stream, 0x89, 1); \
emitm(&stream, (sr32 & 0x7) << 3 | 4 , 1);\
emitm(&stream, (or32 & 0x7) << 3 | (dr32 & 0x7) , 1);
/// bswap dr32
#define BSWAP(dr32) \
emitm(&stream, 0xf, 1); \
emitm(&stream, 0x19 << 3 | dr32 , 1);
/// xchg al,ah
#define SWAP_AX() \
emitm(&stream, 0x86, 1); \
emitm(&stream, 0xc4 , 1);
/// push r32
#define PUSH(r32) \
emitm(&stream, 5 << 4 | 0 << 3 | r32 & 0x7, 1);
/// pop r32
#define POP(r32) \
emitm(&stream, 5 << 4 | 1 << 3 | r32 & 0x7, 1);
/// ret
#define RET() \
emitm(&stream, 12 << 4 | 0 << 3 | 3, 1);
/// add dr32,sr32
#define ADDrd(dr32, sr32) \
emitm(&stream, 0x03, 1);\
emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | (sr32 & 0x7), 1);
/// add eax,i32
#define ADD_EAXi(i32) \
emitm(&stream, 0x05, 1);\
emitm(&stream, i32, 4);
/// add r32,i32
#define ADDid(r32, i32) \
emitm(&stream, 0x81, 1);\
emitm(&stream, 24 << 3 | r32, 1);\
emitm(&stream, i32, 4);
/// add r32,i8
#define ADDib(r32, i8) \
emitm(&stream, 0x83, 1);\
emitm(&stream, 24 << 3 | r32, 1);\
emitm(&stream, i8, 1);
/// sub dr32,sr32
#define SUBrd(dr32, sr32) \
emitm(&stream, 0x2b, 1);\
emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | (sr32 & 0x7), 1);
/// sub eax,i32
#define SUB_EAXi(i32) \
emitm(&stream, 0x2d, 1);\
emitm(&stream, i32, 4);
/// mul r32
#define MULrd(r32) \
emitm(&stream, 0xf7, 1);\
emitm(&stream, 7 << 5 | (r32 & 0x7), 1);
/// div r32
#define DIVrd(r32) \
emitm(&stream, 0xf7, 1);\
emitm(&stream, 15 << 4 | (r32 & 0x7), 1);
/// and r8,i8
#define ANDib(r8, i8) \
emitm(&stream, 0x80, 1);\
emitm(&stream, 7 << 5 | r8, 1);\
emitm(&stream, i8, 1);
/// and r32,i32
#define ANDid(r32, i32) \
if (r32 == EAX){ \
emitm(&stream, 0x25, 1);\
emitm(&stream, i32, 4);}\
else{ \
emitm(&stream, 0x81, 1);\
emitm(&stream, 7 << 5 | r32, 1);\
emitm(&stream, i32, 4);}
/// and dr32,sr32
#define ANDrd(dr32, sr32) \
emitm(&stream, 0x23, 1);\
emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
/// or dr32,sr32
#define ORrd(dr32, sr32) \
emitm(&stream, 0x0b, 1);\
emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
/// or r32,i32
#define ORid(r32, i32) \
if (r32 == EAX){ \
emitm(&stream, 0x0d, 1);\
emitm(&stream, i32, 4);}\
else{ \
emitm(&stream, 0x81, 1);\
emitm(&stream, 25 << 3 | r32, 1);\
emitm(&stream, i32, 4);}
/// shl r32,i8
#define SHLib(r32, i8) \
emitm(&stream, 0xc1, 1);\
emitm(&stream, 7 << 5 | r32 & 0x7, 1);\
emitm(&stream, i8, 1);
/// shl dr32,cl
#define SHL_CLrb(dr32) \
emitm(&stream, 0xd3, 1);\
emitm(&stream, 7 << 5 | dr32 & 0x7, 1);
/// shr r32,i8
#define SHRib(r32, i8) \
emitm(&stream, 0xc1, 1);\
emitm(&stream, 29 << 3 | r32 & 0x7, 1);\
emitm(&stream, i8, 1);
/// shr dr32,cl
#define SHR_CLrb(dr32) \
emitm(&stream, 0xd3, 1);\
emitm(&stream, 29 << 3 | dr32 & 0x7, 1);
/// neg r32
#define NEGd(r32) \
emitm(&stream, 0xf7, 1);\
emitm(&stream, 27 << 3 | r32 & 0x7, 1);
/// cmp dr32,sr32[off]
#define CMPodd(dr32, sr32, off) \
emitm(&stream, 3 << 4 | 3 | 1 << 3, 1); \
emitm(&stream, 1 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);\
emitm(&stream, off, 1);
/// cmp dr32,sr32
#define CMPrd(dr32, sr32) \
emitm(&stream, 0x3b, 1); \
emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
/// cmp dr32,i32
#define CMPid(dr32, i32) \
if (dr32 == EAX){ \
emitm(&stream, 0x3d, 1); \
emitm(&stream, i32, 4);} \
else{ \
emitm(&stream, 0x81, 1); \
emitm(&stream, 0x1f << 3 | (dr32 & 0x7), 1);\
emitm(&stream, i32, 4);}
/// jne off32
#define JNEb(off8) \
emitm(&stream, 0x75, 1);\
emitm(&stream, off8, 1);
/// je off32
#define JE(off32) \
emitm(&stream, 0x0f, 1);\
emitm(&stream, 0x84, 1);\
emitm(&stream, off32, 4);
/// jle off32
#define JLE(off32) \
emitm(&stream, 0x0f, 1);\
emitm(&stream, 0x8e, 1);\
emitm(&stream, off32, 4);
/// jle off8
#define JLEb(off8) \
emitm(&stream, 0x7e, 1);\
emitm(&stream, off8, 1);
/// ja off32
#define JA(off32) \
emitm(&stream, 0x0f, 1);\
emitm(&stream, 0x87, 1);\
emitm(&stream, off32, 4);
/// jae off32
#define JAE(off32) \
emitm(&stream, 0x0f, 1);\
emitm(&stream, 0x83, 1);\
emitm(&stream, off32, 4);
/// jg off32
#define JG(off32) \
emitm(&stream, 0x0f, 1);\
emitm(&stream, 0x8f, 1);\
emitm(&stream, off32, 4);
/// jge off32
#define JGE(off32) \
emitm(&stream, 0x0f, 1);\
emitm(&stream, 0x8d, 1);\
emitm(&stream, off32, 4);
/// jmp off32
#define JMP(off32) \
emitm(&stream, 0xe9, 1);\
emitm(&stream, off32, 4);
/**
* @}
*/
/**
* @}
*/
/**************************/
/* Prototypes */
/**************************/
/** @ingroup NPF
* @{
*/
/** @defgroup NPF_code NPF functions
* @{
*/
/*!
\brief BPF jitter, builds an x86 function from a BPF program.
\param fp The BPF pseudo-assembly filter that will be translated into x86 code.
\param nins Number of instructions of the input filter.
\return The JIT_BPF_Filter structure containing the x86 filtering binary.
BPF_jitter allocates the buffers for the new native filter and then translates the program pointed by fp
calling BPFtoX86().
*/
JIT_BPF_Filter* BPF_jitter(struct bpf_insn *fp, INT nins);
/*!
\brief Translates a set of BPF instructions in a set of x86 ones.
\param ins Pointer to the BPF instructions that will be translated into x86 code.
\param nins Number of instructions to translate.
\param mem Memory used by the x86 function to emulate the RAM of the BPF pseudo processor.
\return The x86 filtering function.
This function does the hard work for the JIT compilation. It takes a group of BPF pseudo instructions and
through the instruction macros defined in jitter.h it is able to create an function directly executable
by NPF.
*/
BPF_filter_function BPFtoX86(struct bpf_insn *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);
/**
* @}
*/
/**
* @}
*/

View file

@ -1,68 +0,0 @@
/*
* Copyright (c) 2001
* Politecnico di Torino. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the Politecnico
* di Torino, and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "tme.h"
#include "memory_t.h"
#ifdef _USE_SW_FUNCS_
int32 SW_LONG_AT(void *b, uint32 c)
{
return ((int32)*((uint8 *)b+c)<<24|
(int32)*((uint8 *)b+c+1)<<16|
(int32)*((uint8 *)b+c+2)<<8|
(int32)*((uint8 *)b+c+3)<<0);
}
uint32 SW_ULONG_AT(void *b, uint32 c)
{
return ((uint32)*((uint8 *)b+c)<<24|
(uint32)*((uint8 *)b+c+1)<<16|
(uint32)*((uint8 *)b+c+2)<<8|
(uint32)*((uint8 *)b+c+3)<<0);
}
int16 SW_SHORT_AT(void *b, uint32 os)
{
return ((int16)
((int16)*((uint8 *)b+os+0)<<8|
(int16)*((uint8 *)b+os+1)<<0));
}
uint16 SW_USHORT_AT(void *b, uint32 os)
{
return ((uint16)
((uint16)*((uint8 *)b+os+0)<<8|
(uint16)*((uint8 *)b+os+1)<<0));
}
VOID SW_ULONG_ASSIGN(void *dst, uint32 src)
{
*((uint8*)dst+0)=*((uint8*)&src+3);
*((uint8*)dst+1)=*((uint8*)&src+2);
*((uint8*)dst+2)=*((uint8*)&src+1);
*((uint8*)dst+3)=*((uint8*)&src+0);
}
#endif /*_USE_SW_FUNCS_*/
void assert(void* assert, const char* file, int line, void* msg) { };

View file

@ -1,124 +0,0 @@
/*
* Copyright (c) 2001
* Politecnico di Torino. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the Politecnico
* di Torino, and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef __memory_t
#define __memory_t
#define uint8 UCHAR
#define int8 CHAR
#define uint16 USHORT
#define int16 SHORT
#define uint32 ULONG
#define int32 LONG
#define uint64 ULONGLONG
#define int64 LONGLONG
/*memory type*/
typedef struct __MEM_TYPE
{
uint8 *buffer;
uint32 size;
} MEM_TYPE, *PMEM_TYPE;
#define LONG_AT(base,offset) (*(int32*)((uint8*)base+(uint32)offset))
#define ULONG_AT(base,offset) (*(uint32*)((uint8*)base+(uint32)offset))
#define SHORT_AT(base,offset) (*(int16*)((uint8*)base+(uint32)offset))
#define USHORT_AT(base,offset) (*(uint16*)((uint8*)base+(uint32)offset))
#ifdef __GNUC__
#define __inline inline
#define _USE_SW_FUNCS_
#endif
#ifdef _USE_SW_FUNCS_
inline int32 SW_LONG_AT(void *b, uint32 c);
inline uint32 SW_ULONG_AT(void *b, uint32 c);
inline int16 SW_SHORT_AT(void *b, uint32 os);
inline uint16 SW_USHORT_AT(void *b, uint32 os);
inline VOID SW_ULONG_ASSIGN(void *dst, uint32 src);
#else /*_USE_SW_FUNCS_*/
__inline int32 SW_LONG_AT(void *b, uint32 c)
{
return ((int32)*((uint8 *)b+c)<<24|
(int32)*((uint8 *)b+c+1)<<16|
(int32)*((uint8 *)b+c+2)<<8|
(int32)*((uint8 *)b+c+3)<<0);
}
__inline uint32 SW_ULONG_AT(void *b, uint32 c)
{
return ((uint32)*((uint8 *)b+c)<<24|
(uint32)*((uint8 *)b+c+1)<<16|
(uint32)*((uint8 *)b+c+2)<<8|
(uint32)*((uint8 *)b+c+3)<<0);
}
__inline int16 SW_SHORT_AT(void *b, uint32 os)
{
return ((int16)
((int16)*((uint8 *)b+os+0)<<8|
(int16)*((uint8 *)b+os+1)<<0));
}
__inline uint16 SW_USHORT_AT(void *b, uint32 os)
{
return ((uint16)
((uint16)*((uint8 *)b+os+0)<<8|
(uint16)*((uint8 *)b+os+1)<<0));
}
__inline VOID SW_ULONG_ASSIGN(void *dst, uint32 src)
{
*((uint8*)dst+0)=*((uint8*)&src+3);
*((uint8*)dst+1)=*((uint8*)&src+2);
*((uint8*)dst+2)=*((uint8*)&src+1);
*((uint8*)dst+3)=*((uint8*)&src+0);
}
#endif /*_USE_SW_FUNCS_*/
#ifdef WIN_NT_DRIVER
#define ALLOCATE_MEMORY(dest,type,amount) \
(dest)=ExAllocatePool(NonPagedPool,sizeof(type)*(amount));
#define ALLOCATE_ZERO_MEMORY(dest,type,amount) \
{ \
(dest)=ExAllocatePool(NonPagedPool,sizeof(type)*(amount)); \
if ((dest)!=NULL) \
RtlZeroMemory((dest),sizeof(type)*(amount)); \
}
#define FREE_MEMORY(dest) ExFreePool(dest);
#define ZERO_MEMORY(dest,amount) RtlZeroMemory(dest,amount);
#define COPY_MEMORY(dest,src,amount) RtlCopyMemory(dest,src,amount);
#endif /*WIN_NT_DRIVER*/
#endif

View file

@ -1,192 +0,0 @@
/*
* Copyright (c) 2001
* Politecnico di Torino. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the Politecnico
* di Torino, and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifdef WIN32
#include "tme.h"
#include "normal_lookup.h"
#endif
#ifdef __FreeBSD__
#ifdef _KERNEL
#include <net/tme/tme.h>
#include <net/tme/normal_lookup.h>
#else
#include <tme/tme.h>
#include <tme/normal_lookup.h>
#endif
#endif
/* lookup in the table, seen as an hash */
/* if not found, inserts an element */
/* returns TME_TRUE if the entry is found or created, */
/* returns TME_FALSE if no more blocks are available */
uint32 normal_lut_w_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref)
{
uint32 i;
uint32 tocs=0;
uint32 *key32=(uint32*) key;
uint32 shrinked_key=0;
uint32 index;
RECORD *records=(RECORD*)data->lut_base_address;
uint8 *offset;
uint32 key_len=data->key_len;
/*the key is shrinked into a 32-bit value */
for (i=0; i<key_len;i++)
shrinked_key^=key32[i];
/*the first index in the table is calculated*/
index=shrinked_key % data->lut_entries;
while (tocs<=data->filled_entries)
{
if (records[index].block==0)
{ /*creation of a new entry*/
if (data->filled_blocks==data->shared_memory_blocks)
{
/*no more free blocks*/
GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref);
data->last_found=NULL;
return TME_FALSE;
}
/*offset=absolute pointer to the block associated*/
/*with the newly created entry*/
offset=data->shared_memory_base_address+
data->block_size*data->filled_blocks;
/*copy the key in the block*/
COPY_MEMORY(offset,key32,key_len*4);
GET_TIME((struct timeval *)(offset+4*key_len),time_ref);
/*assign the block relative offset to the entry, in NBO*/
SW_ULONG_ASSIGN(&records[index].block,offset-mem_ex->buffer);
data->filled_blocks++;
/*assign the exec function ID to the entry, in NBO*/
SW_ULONG_ASSIGN(&records[index].exec_fcn,data->default_exec);
data->filled_entries++;
data->last_found=(uint8*)&records[index];
return TME_TRUE;
}
/*offset contains the absolute pointer to the block*/
/*associated with the current entry */
offset=mem_ex->buffer+SW_ULONG_AT(&records[index].block,0);
for (i=0; (i<key_len) && (key32[i]==ULONG_AT(offset,i*4)); i++);
if (i==key_len)
{
/*key in the block matches the one provided, right entry*/
GET_TIME((struct timeval *)(offset+4*key_len),time_ref);
data->last_found=(uint8*)&records[index];
return TME_TRUE;
}
else
{
/* wrong entry, rehashing */
if (IS_DELETABLE(offset+key_len*4,data))
{
ZERO_MEMORY(offset,data->block_size);
COPY_MEMORY(offset,key32,key_len*4);
SW_ULONG_ASSIGN(&records[index].exec_fcn,data->default_exec);
GET_TIME((struct timeval*)(offset+key_len*4),time_ref);
data->last_found=(uint8*)&records[index];
return TME_TRUE;
}
else
{
index=(index+data->rehashing_value) % data->lut_entries;
tocs++;
}
}
}
/* nothing found, last found= out of lut */
GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref);
data->last_found=NULL;
return TME_FALSE;
}
/* lookup in the table, seen as an hash */
/* if not found, returns out of count entry index */
/* returns TME_TRUE if the entry is found */
/* returns TME_FALSE if the entry is not found */
uint32 normal_lut_wo_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref)
{
uint32 i;
uint32 tocs=0;
uint32 *key32=(uint32*) key;
uint32 shrinked_key=0;
uint32 index;
RECORD *records=(RECORD*)data->lut_base_address;
uint8 *offset;
uint32 key_len=data->key_len;
/*the key is shrinked into a 32-bit value */
for (i=0; i<key_len;i++)
shrinked_key^=key32[i];
/*the first index in the table is calculated*/
index=shrinked_key % data->lut_entries;
while (tocs<=data->filled_entries)
{
if (records[index].block==0)
{ /*out of table, insertion is not allowed*/
GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref);
data->last_found=NULL;
return TME_FALSE;
}
/*offset contains the absolute pointer to the block*/
/*associated with the current entry */
offset=mem_ex->buffer+SW_ULONG_AT(&records[index].block,0);
for (i=0; (i<key_len) && (key32[i]==ULONG_AT(offset,i*4)); i++);
if (i==key_len)
{
/*key in the block matches the one provided, right entry*/
GET_TIME((struct timeval *)(offset+4*key_len),time_ref);
data->last_found=(uint8*)&records[index];
return TME_TRUE;
}
else
{
/*wrong entry, rehashing*/
index=(index+data->rehashing_value) % data->lut_entries;
tocs++;
}
}
/*nothing found, last found= out of lut*/
GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref);
data->last_found=NULL;
return TME_FALSE;
}

View file

@ -1,46 +0,0 @@
/*
* Copyright (c) 2001
* Politecnico di Torino. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the Politecnico
* di Torino, and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef __normal_lookup
#define __normal_lookup
#ifdef WIN32
#include "tme.h"
#endif
#ifdef __FreeBSD__
#ifdef _KERNEL
#include <net/tme/tme.h>
#else
#include <tme/tme.h>
#endif
#endif
#define NORMAL_LUT_W_INSERT 0x00000000
uint32 normal_lut_w_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);
#define NORMAL_LUT_WO_INSERT 0x00000001
uint32 normal_lut_wo_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);
#define DUMMY_INSERT 1234
#endif

View file

@ -1,30 +0,0 @@
#ifndef __NTDDPACKET
#define __NTDDPACKET 1
#ifdef _MSC_VER
#include "devioctl.h"
/*#include <packon.h> */
#else
#endif
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

View file

@ -1,682 +0,0 @@
/*
* Copyright (c) 1999, 2000
* Politecnico di Torino. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the Politecnico
* di Torino, and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifdef _MSC_VER
#include "ntddk.h"
#include "ntiologc.h"
#include "ndis.h"
#else
#include <ddk/ntddk.h>
#include <net/ndis.h>
#endif
#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;
PUCHAR tpointer;
PLIST_ENTRY PacketListEntry;
PCHAR EvName;
IF_LOUD(DbgPrint("NPF: OpenAdapter\n");)
DeviceExtension = DeviceObject->DeviceExtension;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
// allocate some memory for the open structure
#define NPF_TAG_OPENSTRUCT TAG('0', 'O', 'W', 'A')
Open=ExAllocatePoolWithTag(NonPagedPool, sizeof(OPEN_INSTANCE), NPF_TAG_OPENSTRUCT);
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)
);
#define NPF_TAG_EVNAME TAG('1', 'O', 'W', 'A')
EvName=ExAllocatePoolWithTag(NonPagedPool, sizeof(L"\\BaseNamedObjects\\NPF0000000000"), NPF_TAG_EVNAME);
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\\NPF0000000000",sizeof(L"\\BaseNamedObjects\\NPF0000000000"));
//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);
NdisInitializeEvent(&Open->IOEvent);
NdisAllocateSpinLock(&Open->machine_lock);
// 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
#define NPF_TAG_MACHINE TAG('2', 'O', 'W', 'A')
Open->mem_ex.buffer = ExAllocatePoolWithTag(NonPagedPool, DEFAULT_MEM_EX_SIZE, NPF_TAG_MACHINE);
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;
//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 = 1514; // 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);
// Free the jitted filter if it's present
if(Open->Filter != NULL)
BPF_Destroy_JIT_Filter(Open->Filter);
//free the buffer
Open->BufSize=0;
if(Open->Buffer != NULL)ExFreePool(Open->Buffer);
//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);
// Free the jitted filter if it's present
if(Open->Filter != NULL)
BPF_Destroy_JIT_Filter(Open->Filter);
//free the buffer
Open->BufSize = 0;
if(Open->Buffer!=NULL)ExFreePool(Open->Buffer);
//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;
}

File diff suppressed because it is too large Load diff

View file

@ -1,8 +0,0 @@
; packet capture driver - ReactOS Operating System
LIBRARY PACKET.SYS
EXPORTS
DriverEntry@8
; EOF

View file

@ -1,960 +0,0 @@
/*
* Copyright (c) 1999, 2000
* Politecnico di Torino. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the Politecnico
* di Torino, and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
/** @ingroup NPF
* @{
*/
/** @defgroup NPF_include NPF structures and definitions
* @{
*/
#ifndef __PACKET_INCLUDE______
#define __PACKET_INCLUDE______
#define NTKERNEL ///< Forces the compilation of the jitter with kernel calls
#ifdef __GNUC__
#undef EXIT_SUCCESS
#undef EXIT_FAILURE
#define UNICODE_NULL ((WCHAR)0) // winnt
#include "win_bpf.h"
#include <internal/ps.h>
#endif
#include "jitter.h"
#include "tme.h"
#define MAX_REQUESTS 32 ///< Maximum number of simultaneous IOCTL requests.
#define Packet_ALIGNMENT sizeof(int) ///< Alignment macro. Defines the alignment size.
#define Packet_WORDALIGN(x) (((x)+(Packet_ALIGNMENT-1))&~(Packet_ALIGNMENT-1)) ///< Alignment macro. Rounds up to the next
///< even multiple of Packet_ALIGNMENT.
/***************************/
/* 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 2147483648U
/*!
\brief IOCTL code: get an OID value
This IOCTL is used to perform an OID get operation on the NIC driver.
*/
#define BIOCQUERYOID 2147483652U
/*!
\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().
} 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 Contains the state of a running instance of the NPF driver.
This is the most important structure of NPF: it is used by almost all the functions of the driver. An
_OPEN_INSTANCE structure is associated with every user-level session, allowing concurrent access
to the driver.
*/
typedef struct _OPEN_INSTANCE
{
PDEVICE_EXTENSION DeviceExtension; ///< Pointer to the _DEVICE_EXTENSION structure of the device on which
///< the instance is bound.
NDIS_HANDLE AdapterHandle; ///< NDIS idetifier of the adapter used by this instance.
UINT Medium; ///< Type of physical medium the underlying NDIS driver uses. See the
///< documentation of NdisOpenAdapter in the MS DDK for details.
NDIS_HANDLE PacketPool; ///< Pool of NDIS_PACKET structures used to transfer the packets from and to the NIC driver.
PIRP OpenCloseIrp; ///< Pointer used to store the open/close IRP requests and provide them to the
///< callbacks of NDIS.
KSPIN_LOCK RequestSpinLock; ///< SpinLock used to synchronize the OID requests.
LIST_ENTRY RequestList; ///< List of pending OID requests.
LIST_ENTRY ResetIrpList; ///< List of pending adapter reset requests.
INTERNAL_REQUEST Requests[MAX_REQUESTS]; ///< Array of structures that wrap every single OID request.
PMDL BufferMdl; ///< Pointer to a Memory descriptor list (MDL) that maps the circular buffer's memory.
PKEVENT ReadEvent; ///< Pointer to the event on which the read calls on this instance must wait.
HANDLE ReadEventHandle; ///< Handle of the event on which the read calls on this instance must wait.
UNICODE_STRING ReadEventName; ///< Name of the event on which the read calls on this instance must wait.
///< The event is created with a name, so it can be used at user level to know when it
///< is possible to access the driver without being blocked. This fiels stores the name
///< that and is used by the BIOCGEVNAME IOCTL call.
INT Received; ///< Number of packets received by current instance from its opening, i.e. number of
///< packet received by the network adapter since the beginning of the
///< capture/monitoring/dump session.
INT Dropped; ///< Number of packet that current instance had to drop, from its opening. A packet
///< is dropped if there is no more space to store it in the circular buffer that the
///< driver associates to current instance.
INT Accepted; ///< Number of packet that current capture instance acepted, from its opening. A packet
///< is accepted if it passes the filter and fits in the buffer. Accepted packets are the
///< ones that reach the application.
PUCHAR bpfprogram; ///< Pointer to the filtering pseudo-code associated with current instance of the driver.
///< This code is used only in particular situations (for example when the packet received
///< from the NIC driver is stored in two non-consecutive buffers. In normal situations
///< the filtering routine created by the JIT compiler and pointed by the next field
///< is used. See \ref NPF for details on the filtering process.
JIT_BPF_Filter *Filter; ///< Pointer to the native filtering function created by the jitter.
///< See BPF_jitter() for details.
PUCHAR Buffer; ///< Pointer to the circular buffer associated with every driver instance. It contains the
///< data that will be passed to the application. See \ref NPF for details.
UINT Bhead; ///< Head of the circular buffer.
UINT Btail; ///< Tail of the circular buffer.
UINT BufSize; ///< Size of the circular buffer.
UINT BLastByte; ///< Position of the last valid byte in the circular buffer.
PMDL TransferMdl; ///< MDL used to map the portion of the buffer that will contain an incoming packet.
///< Used by NdisTransferData().
NDIS_SPIN_LOCK BufLock; ///< SpinLock that protects the access tho the circular buffer variables.
UINT MinToCopy; ///< Minimum amount of data in the circular buffer that unlocks a read. Set with the
///< BIOCSMINTOCOPY IOCTL.
LARGE_INTEGER TimeOut; ///< Timeout after which a read is released, also if the amount of data in the buffer is
///< less than MinToCopy. Set with the BIOCSRTIMEOUT IOCTL.
int mode; ///< Working mode of the driver. See PacketSetMode() for details.
LARGE_INTEGER Nbytes; ///< Amount of bytes accepted by the filter when this instance is in statistical mode.
LARGE_INTEGER Npackets; ///< Number of packets accepted by the filter when this instance is in statistical mode.
NDIS_SPIN_LOCK CountersLock; ///< SpinLock that protects the statistical mode counters.
UINT Nwrites; ///< Number of times a single write must be physically repeated. See \ref NPF for an
///< explanation
UINT Multiple_Write_Counter; ///< Counts the number of times a single write has already physically repeated.
NDIS_EVENT WriteEvent; ///< Event used to synchronize the multiple write process.
NDIS_EVENT IOEvent; ///< Event used to synchronize I/O requests with the callback structure of NDIS.
NDIS_STATUS IOStatus; ///< Maintains the status of and OID request call, that will be passed to the application.
BOOLEAN Bound; ///< Specifies if NPF is still bound to the adapter used by this instance. Bound can be
///< FALSE if a Plug and Play adapter has been removed or disabled by the user.
HANDLE DumpFileHandle; ///< Handle of the file used in dump mode.
PFILE_OBJECT DumpFileObject; ///< Pointer to the object of the file used in dump mode.
PKTHREAD DumpThreadObject; ///< Pointer to the object of the thread used in dump mode.
HANDLE DumpThreadHandle; ///< Handle of the thread created by dump mode to asynchronously move the buffer to disk.
NDIS_EVENT DumpEvent; ///< Event used to synchronize the dump thread with the tap when the instance is in dump mode.
LARGE_INTEGER DumpOffset; ///< Current offset in the dump file.
UNICODE_STRING DumpFileName; ///< String containing the name of the dump file.
UINT MaxDumpBytes; ///< Maximum dimension in bytes of the dump file. If the dump file reaches this size it
///< will be closed. A value of 0 means unlimited size.
UINT MaxDumpPacks; ///< Maximum number of packets that will be saved in the dump file. If this number of
///< packets is reached the dump will be closed. A value of 0 means unlimited number of
///< packets.
BOOLEAN DumpLimitReached; ///< TRUE if the maximum dimension of the dump file (MaxDumpBytes or MaxDumpPacks) is
///< reached.
MEM_TYPE mem_ex; ///< Memory used by the TME virtual co-processor
TME_CORE tme; ///< Data structure containing the virtualization of the TME co-processor
NDIS_SPIN_LOCK machine_lock; ///< SpinLock that protects the mem_ex buffer
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().
} OPEN_INSTANCE, *POPEN_INSTANCE;
#define TRANSMIT_PACKETS 256 ///< Maximum number of packets in the transmit packet pool. This value is an upper bound to the number
///< of packets that can be transmitted at the same time or with a single call to NdisSendPackets.
/// 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
);
/*!
\brief Ends an OID request.
\param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
\param pRequest Pointer to the completed OID request.
\param Status Status of the operation.
Callback function associated with the NdisRequest() NDIS function. It is invoked by NDIS when the NIC
driver has finished an OID request operation that was previously started by NPF_IoControl().
*/
VOID
NPF_RequestComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_REQUEST pRequest,
IN NDIS_STATUS Status
);
/*!
\brief Writes a raw packet to the network.
\param DeviceObject Pointer to the device object on which the user wrote the packet.
\param Irp Pointer to the IRP containing the user request.
\return The status of the operation. See ntstatus.h in the DDK.
This function is called by the OS in consequence of user WriteFile() call, with the data of the packet that must
be sent on the net. The data is contained in the buffer associated with Irp, NPF_Write takes it and
delivers it to the NIC driver via the NdisSend() function. The Nwrites field of the OPEN_INSTANCE structure
associated with Irp indicates the number of copies of the packet that will be sent: more than one copy of the
packet can be sent for performance reasons.
*/
NTSTATUS
NPF_Write(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
/*!
\brief Writes a buffer of raw packets to the network.
\param Irp Pointer to the IRP containing the user request.
\param UserBuff Pointer to the buffer containing the packets to send.
\param UserBuffSize Size of the buffer with the packets.
\return The amount of bytes actually sent. If the return value is smaller than the Size parameter, an
error occurred during the send. The error can be caused by an adapter problem or by an
inconsistent/bogus user buffer.
This function is called by the OS in consequence of a BIOCSENDPACKETSNOSYNC or a BIOCSENDPACKETSSYNC IOCTL.
The buffer received as input parameter contains an arbitrary number of packets, each of which preceded by a
sf_pkthdr structure. NPF_BufferedWrite() scans the buffer and sends every packet via the NdisSend() function.
When Sync is set to TRUE, the packets are synchronized with the KeQueryPerformanceCounter() function.
This requires a remarkable amount of CPU, but allows to respect the timestamps associated with packets with a precision
of some microseconds (depending on the precision of the performance counter of the machine).
If Sync is false, the timestamps are ignored and the packets are sent as fat as possible.
*/
INT NPF_BufferedWrite(IN PIRP Irp,
IN PCHAR UserBuff,
IN ULONG UserBuffSize,
BOOLEAN sync);
/*!
\brief Ends a send operation.
\param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
\param pRequest Pointer to the NDIS PACKET structure used by NPF_Write() to send the packet.
\param Status Status of the operation.
Callback function associated with the NdisSend() NDIS function. It is invoked by NDIS when the NIC
driver has finished an OID request operation that was previously started by NPF_Write().
*/
VOID
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
STDCALL_FUNC
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 Validates a filtering program arriving from the user-level app.
\param f The filter.
\param len Its length, in pseudo instructions.
\param mem_ex_size The length of the extended memory, used to validate LD/ST to that memory
\return true if f is a valid filter program..
The kernel needs to be able to verify an application's filter code. Otherwise, a bogus program could easily
crash the system.
This function returns true if f is a valid filter program. The constraints are that each jump be forward and
to a valid code. The code must terminate with either an accept or reject.
*/
int bpf_validate(struct bpf_insn *f,int len, uint32 mem_ex_size);
/*!
\brief The filtering pseudo-machine interpreter.
\param pc The filter.
\param p Pointer to a memory buffer containing the packet on which the filter will be executed.
\param wirelen Original length of the packet.
\param buflen Current length of the packet. In some cases (for example when the transfer of the packet to the RAM
has not yet finished), bpf_filter can be executed on a portion of the packet.
\param mem_ex The extended memory.
\param tme The virtualization of the TME co-processor
\param time_ref Data structure needed by the TME co-processor to timestamp data
\return The portion of the packet to keep, in bytes. 0 means that the packet must be rejected, -1 means that
the whole packet must be kept.
\note this function is not used in normal situations, because the jitter creates a native filtering function
that is faster than the interpreter.
*/
UINT bpf_filter(register struct bpf_insn *pc,
register UCHAR *p,
UINT wirelen,
register UINT buflen,
PMEM_TYPE mem_ex,
PTME_CORE tme,
struct time_conv *time_ref);
/*!
\brief The filtering pseudo-machine interpreter with two buffers. This function is slower than bpf_filter(),
but works correctly also if the MAC header and the data of the packet are in two different buffers.
\param pc The filter.
\param p Pointer to a memory buffer containing the MAC header of the packet.
\param pd Pointer to a memory buffer containing the data of the packet.
\param wirelen Original length of the packet.
\param buflen Current length of the packet. In some cases (for example when the transfer of the packet to the RAM
has not yet finished), bpf_filter can be executed on a portion of the packet.
\param mem_ex The extended memory.
\param tme The virtualization of the TME co-processor
\param time_ref Data structure needed by the TME co-processor to timestamp data
\return The portion of the packet to keep, in bytes. 0 means that the packet must be rejected, -1 means that
the whole packet must be kept.
This function is used when NDIS passes the packet to NPF_tap() in two buffers instaed than in a single one.
*/
UINT bpf_filter_with_2_buffers(register struct bpf_insn *pc,
register UCHAR *p,
register UCHAR *pd,
register int headersize,
UINT wirelen,
register UINT buflen,
PMEM_TYPE mem_ex,
PTME_CORE tme,
struct time_conv *time_ref);
/*!
\brief Creates the file that will receive the packets when the driver is in dump mode.
\param Open The NPF instance that opens the file.
\param fileName Pointer to a UNICODE string containing the name of the file.
\param append Boolean value that specifies if the data must be appended to the file.
\return The status of the operation. See ntstatus.h in the DDK.
*/
NTSTATUS NPF_OpenDumpFile(POPEN_INSTANCE Open , PUNICODE_STRING fileName, BOOLEAN append);
/*!
\brief Starts dump to file.
\param Open The NPF instance that opens the file.
\return The status of the operation. See ntstatus.h in the DDK.
This function performs two operations. First, it writes the libpcap header at the beginning of the file.
Second, it starts the thread that asynchronously dumps the network data to the file.
*/
NTSTATUS NPF_StartDump(POPEN_INSTANCE Open);
/*!
\brief The dump thread.
\param Open The NPF instance that creates the thread.
This function moves the content of the NPF kernel buffer to file. It runs in the user context, so at lower
priority than the TAP.
*/
VOID NPF_DumpThread(POPEN_INSTANCE Open);
/*!
\brief Saves the content of the packet buffer to the file associated with current instance.
\param Open The NPF instance that creates the thread.
Used by NPF_DumpThread() and NPF_CloseDumpFile().
*/
NTSTATUS NPF_SaveCurrentBuffer(POPEN_INSTANCE Open);
/*!
\brief Writes a block of packets on the dump file.
\param FileObject The file object that will receive the packets.
\param Offset The offset in the file where the packets will be put.
\param Length The amount of bytes to write.
\param Mdl MDL mapping the memory buffer that will be written to disk.
\param IoStatusBlock Used by the function to return the status of the operation.
\return The status of the operation. See ntstatus.h in the DDK.
NPF_WriteDumpFile addresses directly the file system, creating a custom IRP and using it to send a portion
of the NPF circular buffer to disk. This function is used by NPF_DumpThread().
*/
VOID NPF_WriteDumpFile(PFILE_OBJECT FileObject,
PLARGE_INTEGER Offset,
ULONG Length,
PMDL Mdl,
PIO_STATUS_BLOCK IoStatusBlock);
/*!
\brief Closes the dump file associated with an instance of the driver.
\param Open The NPF instance that closes the file.
\return The status of the operation. See ntstatus.h in the DDK.
*/
NTSTATUS NPF_CloseDumpFile(POPEN_INSTANCE Open);
/*!
\brief Returns the amount of bytes present in the packet buffer.
\param Open The NPF instance that closes the file.
*/
UINT GetBuffOccupation(POPEN_INSTANCE Open);
/*!
\brief Called by NDIS to notify us of a PNP event. The most significant one for us is power state change.
\param ProtocolBindingContext Pointer to open context structure. This is NULL for global reconfig
events.
\param pNetPnPEvent Pointer to the PnP event
If there is a power state change, the driver is forced to resynchronize the global timer.
This hopefully avoids the synchronization issues caused by hibernation or standby.
This function is excluded from the NT4 driver, where PnP is not supported
*/
#ifdef NDIS50
NDIS_STATUS NPF_PowerChange(IN NDIS_HANDLE ProtocolBindingContext, IN PNET_PNP_EVENT pNetPnPEvent);
#endif
/**
* @}
*/
/**
* @}
*/
#endif /*main ifndef/define*/

View file

@ -1,47 +0,0 @@
//#include "resource.h"
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,0,0,13
PRODUCTVERSION 3,0,0,13
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x3L
FILESUBTYPE 0x7L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "000004b0"
BEGIN
VALUE "Comments", "Netgroup Packet Filter Driver\0"
VALUE "CompanyName", "Politecnico di Torino\0"
VALUE "FileDescription", "NPF Driver - TME extensions\0"
VALUE "FileVersion", "3, 0, 0, 13\0"
VALUE "InternalName", "NPF + TME \0"
VALUE "LegalCopyright", "Copyright © 2002\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "NPF.RC\0"
VALUE "PrivateBuild", "REACTOS PRIVATE BUILD\0"
VALUE "ProductName", "NPF Driver\0"
VALUE "ProductVersion", "3, 0, 0, 13\0"
VALUE "SpecialBuild", "Beta testing use only\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x0, 1200
END
END
/////////////////////////////////////////////////////////////////////////////

View file

@ -1,680 +0,0 @@
/*
* Copyright (c) 1999, 2000
* Politecnico di Torino. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the Politecnico
* di Torino, and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifdef _MSC_VER
#include <stdarg.h>
#include <ntddk.h>
#include <ntiologc.h>
#include <ndis.h>
#else
#include <ddk/ntddk.h>
#include <net/ndis.h>
#define NdisMoveMappedMemory(Destination,Source,Length) RtlCopyMemory(Destination,Source,Length)
#define NdisZeroMappedMemory(Destination,Length) RtlZeroMemory(Destination,Length)
#define NdisReinitializePacket(Packet) \
{ \
(Packet)->Private.Head = (PNDIS_BUFFER)NULL; \
(Packet)->Private.ValidCounts = FALSE; \
}
#endif
#include "debug.h"
#include "packet.h"
#include "win_bpf.h"
#include "tme.h"
#include "time_calls.h"
extern struct time_conv G_Start_Time; // from openclos.c
//-------------------------------------------------------------------
UINT GetBuffOccupation(POPEN_INSTANCE Open)
{
UINT Occupation;
NdisAcquireSpinLock( &Open->BufLock );
if(Open->Btail >= Open->Bhead) Occupation = Open->Btail-Open->Bhead;
else Occupation = Open->BLastByte-Open->Bhead+Open->Btail;
NdisReleaseSpinLock( &Open->BufLock );
return Occupation;
}
//-------------------------------------------------------------------
void PacketMoveMem(PVOID Destination, PVOID Source, ULONG Length, UINT *Bhead)
{
ULONG WordLength;
UINT n,i,NBlocks;
WordLength=Length>>2;
NBlocks=WordLength>>8;
for(n=0;n<NBlocks;n++){
for(i=0;i<256;i++){
*((PULONG)Destination)++=*((PULONG)Source)++;
}
*Bhead+=1024;
}
n=WordLength-(NBlocks<<8);
for(i=0;i<n;i++){
*((PULONG)Destination)++=*((PULONG)Source)++;
}
*Bhead+=n<<2;
n=Length-(WordLength<<2);
for(i=0;i<n;i++){
*((PUCHAR)Destination)++=*((PUCHAR)Source)++;
}
*Bhead+=n;
}
//-------------------------------------------------------------------
NTSTATUS
NPF_Read(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
{
POPEN_INSTANCE Open;
PIO_STACK_LOCATION IrpSp;
PUCHAR packp;
ULONG Input_Buffer_Length;
UINT Thead;
UINT Ttail;
UINT TLastByte;
PUCHAR CurrBuff;
LARGE_INTEGER CapTime;
LARGE_INTEGER TimeFreq;
struct bpf_hdr *header;
KIRQL Irql;
PUCHAR UserPointer;
ULONG bytecopy;
UINT SizeToCopy;
UINT PktLen;
IF_LOUD(DbgPrint("NPF: Read\n");)
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Open=IrpSp->FileObject->FsContext;
if( Open->Bound == FALSE ){
// The Network adapter was removed.
EXIT_FAILURE(0);
}
if( Open->mode & MODE_DUMP && Open->DumpFileHandle == NULL ){
// this instance is in dump mode, but the dump file has still not been opened
EXIT_FAILURE(0);
}
//See if the buffer is full enough to be copied
if( GetBuffOccupation(Open) <= Open->MinToCopy || 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
CurrBuff=(PUCHAR)MmGetSystemAddressForMdl(Irp->MdlAddress);
//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;
}
if(Open->mode==MODE_MON) //this capture instance is in monitor mode
{
PTME_DATA data;
ULONG cnt;
ULONG block_size;
PUCHAR tmp;
UserPointer=MmGetSystemAddressForMdl(Irp->MdlAddress);
if ((!IS_VALIDATED(Open->tme.validated_blocks,Open->tme.active_read))||(IrpSp->Parameters.Read.Length<sizeof(struct bpf_hdr)))
{
EXIT_FAILURE(0);
}
header=(struct bpf_hdr*)UserPointer;
GET_TIME(&header->bh_tstamp,&G_Start_Time);
header->bh_hdrlen=sizeof(struct bpf_hdr);
//moves user memory pointer
UserPointer+=sizeof(struct bpf_hdr);
//calculus of data to be copied
//if the user buffer is smaller than data to be copied,
//only some data will be copied
data=&Open->tme.block_data[Open->tme.active_read];
if (data->last_read.tv_sec!=0)
data->last_read=header->bh_tstamp;
bytecopy=data->block_size*data->filled_blocks;
if ((IrpSp->Parameters.Read.Length-sizeof(struct bpf_hdr))<bytecopy)
bytecopy=(IrpSp->Parameters.Read.Length-sizeof(struct bpf_hdr))/ data->block_size;
else
bytecopy=data->filled_blocks;
tmp=data->shared_memory_base_address;
block_size=data->block_size;
for (cnt=0;cnt<bytecopy;cnt++)
{
NdisAcquireSpinLock(&Open->machine_lock);
RtlCopyMemory(UserPointer,tmp,block_size);
NdisReleaseSpinLock(&Open->machine_lock);
tmp+=block_size;
UserPointer+=block_size;
}
bytecopy*=block_size;
header->bh_caplen=bytecopy;
header->bh_datalen=header->bh_caplen;
EXIT_SUCCESS(bytecopy+sizeof(struct bpf_hdr));
}
if (Open->Bhead == Open->Btail || Open->mode & MODE_DUMP)
// The timeout has expired, but the buffer is still empty (or the packets must be written to file).
// We must awake the application, returning an empty buffer.
{
EXIT_SUCCESS(0);
}
}
//
// The buffer if full enough to be copied,
//
NdisAcquireSpinLock( &Open->BufLock );
Thead = Open->Bhead;
Ttail = Open->Btail;
TLastByte = Open->BLastByte;
//get the address of the buffer
CurrBuff=Open->Buffer;
NdisReleaseSpinLock( &Open->BufLock );
Input_Buffer_Length=IrpSp->Parameters.Read.Length;
packp=(PUCHAR)MmGetSystemAddressForMdl(Irp->MdlAddress);
//
//fill the application buffer
//
if(Ttail > Thead){ //first of all see if it we can copy all the buffer in one time
if((Ttail-Thead)<Input_Buffer_Length){
KeResetEvent(Open->ReadEvent);
PacketMoveMem(packp,CurrBuff+Thead,Ttail-Thead,&(Open->Bhead));
EXIT_SUCCESS(Ttail-Thead);
}
}
else if((TLastByte - Thead) < Input_Buffer_Length){
PacketMoveMem(packp, CurrBuff+Thead, TLastByte - Thead, &(Open->Bhead));
NdisAcquireSpinLock( &Open->BufLock );
Open->BLastByte = Open->Btail;
Open->Bhead = 0;
NdisReleaseSpinLock( &Open->BufLock );
EXIT_SUCCESS(TLastByte-Thead);
}
//the buffer must be scannned to determine the number of bytes to copy
SizeToCopy = 0;
while(TRUE){
if(Thead + SizeToCopy == Ttail)
break;
if(Thead + SizeToCopy == TLastByte && TLastByte != Ttail){
PacketMoveMem(packp, CurrBuff+Thead, SizeToCopy, &(Open->Bhead));
// Reset the buffer
NdisAcquireSpinLock( &Open->BufLock );
(INT)Open->BLastByte = -1;
Open->Bhead = 0;
NdisReleaseSpinLock( &Open->BufLock );
EXIT_SUCCESS(SizeToCopy);
}
// Get the size of the next packet in the buffer
PktLen = ((struct bpf_hdr*)(CurrBuff + Thead + SizeToCopy))->bh_caplen + sizeof(struct bpf_hdr);
// The length is aligned to 32-bit boundary
PktLen = Packet_WORDALIGN(PktLen);
if(SizeToCopy + PktLen > Input_Buffer_Length)
break;
SizeToCopy += PktLen;
}
PacketMoveMem(packp, CurrBuff+Thead, SizeToCopy, &(Open->Bhead));
EXIT_SUCCESS(SizeToCopy);
}
//-------------------------------------------------------------------
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 pPacketb;
ULONG SizeToTransfer;
NDIS_STATUS Status;
UINT BytesTransfered;
ULONG BufferLength;
PMDL pMdl;
LARGE_INTEGER CapTime;
LARGE_INTEGER TimeFreq;
struct bpf_hdr *header;
PUCHAR CurrBuff;
UINT Thead;
UINT Ttail;
UINT TLastByte;
UINT fres;
UINT maxbufspace;
USHORT NPFHdrSize;
UINT BufOccupation;
BOOLEAN ResetBuff = FALSE;
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;
Open->Received++; // Number of packets received by filter ++
BufOccupation = GetBuffOccupation(Open); // Get the full buffer space
if(((Open->mode&MODE_CAPT)||(Open->mode&MODE_DUMP)) && Open->BufSize - BufOccupation < PacketSize+HeaderBufferSize+sizeof(struct bpf_hdr)){
// Heuristic that drops the packet also if it possibly fits in the buffer.
// It allows to avoid filtering in critical situations when CPU is very important.
Open->Dropped++;
return NDIS_STATUS_NOT_ACCEPTED;
}
NdisAcquireSpinLock(&Open->machine_lock);
//
//Check if the lookahead buffer follows the mac header.
//If the data follow the header (i.e. there is only a buffer) a normal bpf_filter() is
//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)LookAheadBuffer-(UINT)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
if(Open->Filter != NULL)
{
if (Open->bpfprogram != NULL)
{
fres=Open->Filter->Function(HeaderBuffer,
PacketSize+HeaderBufferSize,
LookaheadBufferSize+HeaderBufferSize);
// Restore the stack.
// I ignore the reason, but this instruction is needed only at kernel level
#ifndef __GNUC__
_asm add esp,12
#else
asm("add $0x12,%esp;");
#endif
}
else
fres = -1;
}
else
fres=bpf_filter((struct bpf_insn*)(Open->bpfprogram),
HeaderBuffer,
PacketSize+HeaderBufferSize,
LookaheadBufferSize+HeaderBufferSize,
&Open->mem_ex,
&Open->tme,
&G_Start_Time);
NdisReleaseSpinLock(&Open->machine_lock);
if(Open->mode==MODE_MON)
// we are in monitor mode
{
if (fres==1)
KeSetEvent(Open->ReadEvent,0,FALSE);
return NDIS_STATUS_NOT_ACCEPTED;
}
if(fres==0)
// Packet not accepted by the filter, ignore it.
return NDIS_STATUS_NOT_ACCEPTED;
//if the filter returns -1 the whole packet must be accepted
if(fres==-1 || fres > PacketSize+HeaderBufferSize)fres=PacketSize+HeaderBufferSize;
if(Open->mode & MODE_STAT){
// we are in statistics mode
NdisAcquireSpinLock( &Open->CountersLock );
Open->Npackets.QuadPart++;
if(PacketSize+HeaderBufferSize<60)
Open->Nbytes.QuadPart+=60;
else
Open->Nbytes.QuadPart+=PacketSize+HeaderBufferSize;
// add preamble+SFD+FCS to the packet
// these values must be considered because are not part of the packet received from NDIS
Open->Nbytes.QuadPart+=12;
NdisReleaseSpinLock( &Open->CountersLock );
if(!(Open->mode & MODE_DUMP)){
return NDIS_STATUS_NOT_ACCEPTED;
}
}
if(Open->BufSize==0)return NDIS_STATUS_NOT_ACCEPTED;
if(Open->mode & MODE_DUMP && Open->MaxDumpPacks && (UINT)Open->Accepted > Open->MaxDumpPacks){
// Reached the max number of packets to save in the dump file. Discard the packet and stop the dump thread.
Open->DumpLimitReached = TRUE; // This stops the thread
// Awake the dump thread
NdisSetEvent(&Open->DumpEvent);
// Awake the application
KeSetEvent(Open->ReadEvent,0,FALSE);
return NDIS_STATUS_NOT_ACCEPTED;
}
// Calculate the correct size for the header associated with the packet
NPFHdrSize=(Open->mode==MODE_CAPT)? sizeof(struct bpf_hdr): sizeof(struct sf_pkthdr);
NdisAcquireSpinLock( &Open->BufLock );
Thead=Open->Bhead;
Ttail=Open->Btail;
TLastByte = Open->BLastByte;
NdisReleaseSpinLock( &Open->BufLock );
maxbufspace=Packet_WORDALIGN(fres+NPFHdrSize);
if(Ttail+maxbufspace >= Open->BufSize){
if(Thead <= maxbufspace)
{
Open->Dropped++;
return NDIS_STATUS_NOT_ACCEPTED;
}
else{
Ttail=0;
ResetBuff = TRUE;
}
}
if (Thead > Ttail && (Thead-Ttail) <= maxbufspace)
{
Open->Dropped++;
return NDIS_STATUS_NOT_ACCEPTED;
}
CurrBuff=Open->Buffer+Ttail;
if(LookaheadBufferSize != PacketSize || (UINT)LookAheadBuffer-(UINT)HeaderBuffer != HeaderBufferSize)
{
// Allocate an MDL to map the portion of the buffer following the header
pMdl=IoAllocateMdl(CurrBuff+HeaderBufferSize+LookaheadBufferSize+NPFHdrSize,
maxbufspace,
FALSE,
FALSE,
NULL);
if (pMdl == NULL)
{
// Unable to map the memory: packet lost
IF_LOUD(DbgPrint("NPF: Read-Failed to allocate Mdl\n");)
Open->Dropped++;
return NDIS_STATUS_NOT_ACCEPTED;
}
MmBuildMdlForNonPagedPool(pMdl);
//allocate the packet from NDIS
NdisAllocatePacket(&Status, &pPacketb, Open->PacketPool);
if (Status != NDIS_STATUS_SUCCESS)
{
IF_LOUD(DbgPrint("NPF: Tap - No free packets\n");)
IoFreeMdl(pMdl);
Open->Dropped++;
return NDIS_STATUS_NOT_ACCEPTED;
}
//link the buffer to the packet
NdisChainBufferAtFront(pPacketb,pMdl);
BufferLength=fres-HeaderBufferSize;
//Find out how much to transfer
SizeToTransfer = (PacketSize < BufferLength) ? PacketSize : BufferLength;
//copy the ethernet header into buffer
NdisMoveMappedMemory((CurrBuff)+NPFHdrSize,HeaderBuffer,HeaderBufferSize);
//Copy the look ahead buffer
if(LookaheadBufferSize)
{
NdisMoveMappedMemory((CurrBuff) + NPFHdrSize + HeaderBufferSize,
LookAheadBuffer,
(SizeToTransfer < LookaheadBufferSize)? SizeToTransfer : LookaheadBufferSize );
SizeToTransfer = (SizeToTransfer > LookaheadBufferSize)?
SizeToTransfer - LookaheadBufferSize : 0;
}
Open->TransferMdl=pMdl;
if(SizeToTransfer)
{
//Call the Mac to transfer the packet
NdisTransferData(&Status,
Open->AdapterHandle,
MacReceiveContext,
LookaheadBufferSize,
SizeToTransfer,
pPacketb,
&BytesTransfered);
}
else{
BytesTransfered = 0;
}
}
else
{
// The whole packet is in the lookahead buffer, we can avoid the call to NdisTransferData.
// This allows us to avoid the allocation of the MDL and the NDIS packet as well
RtlCopyMemory((CurrBuff) + NPFHdrSize,
HeaderBuffer,
HeaderBufferSize + LookaheadBufferSize);
BytesTransfered = 0;
Open->TransferMdl = NULL;
Status = NDIS_STATUS_SUCCESS;
}
if (Status != NDIS_STATUS_FAILURE)
{
Open->Accepted++; // Increase the accepted packets counter
if( fres > (BytesTransfered+HeaderBufferSize+LookaheadBufferSize) )
fres = BytesTransfered+HeaderBufferSize+LookaheadBufferSize;
//
// Build the header
//
header=(struct bpf_hdr*)CurrBuff;
GET_TIME(&header->bh_tstamp,&G_Start_Time);
header->bh_caplen=fres;
header->bh_datalen=PacketSize+HeaderBufferSize;
if(Open->mode==MODE_CAPT){
header->bh_hdrlen=NPFHdrSize;
// Don't align if the packet goes to disk
Ttail+=Packet_WORDALIGN(fres + NPFHdrSize);
}
else
Ttail+=fres+NPFHdrSize;
//update the buffer
NdisAcquireSpinLock( &Open->BufLock );
if(ResetBuff){
Open->BLastByte = Open->Btail;
}
Open->Btail=Ttail;
NdisReleaseSpinLock( &Open->BufLock );
}
if (Status != NDIS_STATUS_PENDING){
if( Open->TransferMdl != NULL)
// Complete the request and free the buffers
NPF_TransferDataComplete(Open,pPacketb,Status,fres);
else{
// Unfreeze the consumer
if(GetBuffOccupation(Open)>Open->MinToCopy){
if(Open->mode & MODE_DUMP){
NdisSetEvent(&Open->DumpEvent);
}
else
KeSetEvent(Open->ReadEvent,0,FALSE);
}
}
}
return NDIS_STATUS_SUCCESS;
}
//-------------------------------------------------------------------
VOID NPF_TransferDataComplete (IN NDIS_HANDLE ProtocolBindingContext,IN PNDIS_PACKET pPacket,
IN NDIS_STATUS Status,IN UINT BytesTransfered)
{
POPEN_INSTANCE Open;
IF_LOUD(DbgPrint("NPF: TransferDataComplete\n");)
Open= (POPEN_INSTANCE)ProtocolBindingContext;
IoFreeMdl(Open->TransferMdl);
//recylcle the packet
NdisReinitializePacket(pPacket);
//Put the packet on the free queue
NdisFreePacket(pPacket);
// Unfreeze the consumer
if(GetBuffOccupation(Open)>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;
}

View file

@ -1,15 +0,0 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by NPF.RC
//
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View file

@ -1,284 +0,0 @@
/*
* Copyright (c) 2001
* Politecnico di Torino. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the Politecnico
* di Torino, and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifdef WIN32
#include "tme.h"
#include "tcp_session.h"
#endif
#ifdef __FreeBSD
#ifdef _KERNEL
#include <net/tme/tme.h>
#include <net/tme/tcp_session.h>
#else
#include <tme/tme.h>
#include <tme/tcp_session.h>
#endif
#endif
uint32 tcp_session(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data)
{
uint32 next_status;
uint32 direction=ULONG_AT(mem_data,12);
uint8 flags=mem_ex->buffer[25];
tcp_data *session=(tcp_data*)(block+data->key_len*4);
session->last_timestamp=session->timestamp_block;
session->timestamp_block.tv_sec=0x7fffffff;
if (direction==session->direction)
{
session->pkts_cln_to_srv++;
session->bytes_cln_to_srv+=pkt_size;
}
else
{
session->pkts_srv_to_cln++;
session->bytes_srv_to_cln+=pkt_size;
}
/* we use only thes four flags, we don't need PSH or URG */
flags&=(ACK|FIN|SYN|RST);
switch (session->status)
{
case ERROR_TCP:
next_status=ERROR_TCP;
break;
case UNKNOWN:
if (flags==SYN)
{
if (SW_ULONG_AT(mem_ex->buffer,20)!=0)
{
next_status=ERROR_TCP;
break;
}
next_status=SYN_RCV;
session->syn_timestamp=session->last_timestamp;
session->direction=direction;
session->seq_n_0_cln=SW_ULONG_AT(mem_ex->buffer,16);
}
else
next_status=UNKNOWN;
break;
case SYN_RCV:
if ((flags&RST)&&(direction!=session->direction))
{
next_status=CLOSED_RST;
break;
}
if ((flags==SYN)&&(direction==session->direction))
{ /* two syns... */
next_status=SYN_RCV;
session->seq_n_0_cln=SW_ULONG_AT(mem_ex->buffer,16);
break;
}
if ((flags==(SYN|ACK))&&(direction!=session->direction))
{
if (SW_ULONG_AT(mem_ex->buffer,20)!=session->seq_n_0_cln+1)
{
next_status=ERROR_TCP;
break;
}
next_status=SYN_ACK_RCV;
session->syn_ack_timestamp=session->last_timestamp;
session->seq_n_0_srv=SW_ULONG_AT(mem_ex->buffer,16);
session->ack_cln=session->seq_n_0_cln+1;
}
else
{
next_status=ERROR_TCP;
}
break;
case SYN_ACK_RCV:
if ((flags&ACK)&&(flags&RST)&&(direction==session->direction))
{
next_status=CLOSED_RST;
session->ack_srv=SW_ULONG_AT(mem_ex->buffer,20);
break;
}
if ((flags==ACK)&&(!(flags&(SYN|FIN|RST)))&&(direction==session->direction))
{
if (SW_ULONG_AT(mem_ex->buffer,20)!=session->seq_n_0_srv+1)
{
next_status=ERROR_TCP;
break;
}
next_status=ESTABLISHED;
session->ack_srv=session->seq_n_0_srv+1;
break;
}
if ((flags&ACK)&&(flags&SYN)&&(direction!=session->direction))
{
next_status=SYN_ACK_RCV;
break;
}
next_status=ERROR_TCP;
break;
case ESTABLISHED:
if (flags&SYN)
{
if ((flags&ACK)&&
(direction!=session->direction)&&
((session->ack_cln-SW_ULONG_AT(mem_ex->buffer,20))<MAX_WINDOW)
)
{ /* SYN_ACK duplicato */
next_status=ESTABLISHED;
break;
}
if ((!(flags&ACK))&&
(direction==session->direction)&&
(SW_ULONG_AT(mem_ex->buffer,16)==session->seq_n_0_cln)&&
(ULONG_AT(mem_ex->buffer,20)==0)
)
{ /* syn duplicato */
next_status=ESTABLISHED;
break;
}
next_status=ERROR_TCP;
break;
}
if (flags&ACK)
if (direction==session->direction)
{
uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
if (new_ack-session->ack_srv<MAX_WINDOW)
session->ack_srv=new_ack;
}
else
{
uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
if (new_ack-session->ack_cln<MAX_WINDOW)
session->ack_cln=new_ack;
}
if (flags&RST)
{
next_status=CLOSED_RST;
break;
}
if (flags&FIN)
if (direction==session->direction)
{ /* an hack to make all things work */
session->ack_cln=SW_ULONG_AT(mem_ex->buffer,16);
next_status=FIN_CLN_RCV;
break;
}
else
{
session->ack_srv=SW_ULONG_AT(mem_ex->buffer,16);
next_status=FIN_SRV_RCV;
break;
}
next_status=ESTABLISHED;
break;
case CLOSED_RST:
next_status=CLOSED_RST;
break;
case FIN_SRV_RCV:
if (flags&SYN)
{
next_status=ERROR_TCP;
break;
}
next_status=FIN_SRV_RCV;
if (flags&ACK)
{
uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
if (direction!=session->direction)
if ((new_ack-session->ack_cln)<MAX_WINDOW)
session->ack_cln=new_ack;
}
if (flags&RST)
next_status=CLOSED_RST;
else
if ((flags&FIN)&&(direction==session->direction))
{
session->ack_cln=SW_ULONG_AT(mem_ex->buffer,16);
next_status=CLOSED_FIN;
}
break;
case FIN_CLN_RCV:
if (flags&SYN)
{
next_status=ERROR_TCP;
break;
}
next_status=FIN_CLN_RCV;
if (flags&ACK)
{
uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
if (direction==session->direction)
if (new_ack-session->ack_srv<MAX_WINDOW)
session->ack_srv=new_ack;
}
if (flags&RST)
next_status=CLOSED_RST;
else
if ((flags&FIN)&&(direction!=session->direction))
{
session->ack_srv=SW_ULONG_AT(mem_ex->buffer,16);
next_status=CLOSED_FIN;
}
break;
case CLOSED_FIN:
next_status=CLOSED_FIN;
break;
default:
next_status=ERROR_TCP;
}
session->status=next_status;
if ((next_status==CLOSED_FIN)||(next_status==UNKNOWN)||(next_status==CLOSED_RST)||(next_status==ERROR_TCP))
session->timestamp_block=session->last_timestamp;
return TME_SUCCESS;
}

View file

@ -1,86 +0,0 @@
/*
* Copyright (c) 2001
* Politecnico di Torino. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the Politecnico
* di Torino, and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef __tcp_session
#define __tcp_session
#ifdef WIN32
#include "tme.h"
#endif
#ifdef __FreeBSD__
#ifdef _KERNEL
#include <net/tme/tme.h>
#else
#include <tme/tme.h>
#endif
#endif
#define UNKNOWN 0
#define SYN_RCV 1
#define SYN_ACK_RCV 2
#define ESTABLISHED 3
#define CLOSED_RST 4
#define FIN_CLN_RCV 5
#define FIN_SRV_RCV 6
#define CLOSED_FIN 7
#define ERROR_TCP 8
#define FIRST_IS_CLN 0
#define FIRST_IS_SRV 0xffffffff
#define FIN_CLN 1
#define FIN_SRV 2
#define MAX_WINDOW 65536
typedef struct __tcp_data
{
struct timeval timestamp_block; /*DO NOT MOVE THIS VALUE*/
struct timeval syn_timestamp;
struct timeval last_timestamp;
struct timeval syn_ack_timestamp;
uint32 direction;
uint32 seq_n_0_srv;
uint32 seq_n_0_cln;
uint32 ack_srv; /* acknowledge of (data sent by server) */
uint32 ack_cln; /* acknowledge of (data sent by client) */
uint32 status;
uint32 pkts_cln_to_srv;
uint32 pkts_srv_to_cln;
uint32 bytes_srv_to_cln;
uint32 bytes_cln_to_srv;
uint32 close_state;
}
tcp_data;
#define FIN 1
#define SYN 2
#define RST 4
#define PSH 8
#define ACK 16
#define URG 32
#define TCP_SESSION 0x00000800
uint32 tcp_session(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data);
#endif

View file

@ -1,277 +0,0 @@
/*
* Copyright (c) 2001
* Politecnico di Torino. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the Politecnico
* di Torino, and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "tme.h"
#include "win_bpf.h"
#include "time_calls.h"
void TIME_DESYNCHRONIZE(struct time_conv *data)
{
data->reference = 0;
data->start.tv_sec = 0;
data->start.tv_usec = 0;
}
#ifdef KQPC_TS
/* KeQueryPerformanceCounter TimeStamps */
VOID TIME_SYNCHRONIZE(struct time_conv *data)
{
struct timeval tmp;
LARGE_INTEGER SystemTime;
LARGE_INTEGER i;
ULONG tmp2;
LARGE_INTEGER TimeFreq,PTime;
if (data->reference!=0)
return;
// get the absolute value of the system boot time.
PTime=KeQueryPerformanceCounter(&TimeFreq);
KeQuerySystemTime(&SystemTime);
#ifndef __GNUC__
tmp.tv_sec=(LONG)(SystemTime.QuadPart/10000000-11644473600);
tmp.tv_usec=(LONG)((SystemTime.QuadPart%10000000)/10);
tmp.tv_sec-=(ULONG)(PTime.QuadPart/TimeFreq.QuadPart);
tmp.tv_usec-=(LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
#else
// TODO FIXME:
#endif
if (tmp.tv_usec<0) {
tmp.tv_sec--;
tmp.tv_usec+=1000000;
}
data->start=tmp;
data->reference=1;
}
void FORCE_TIME(struct timeval *src, struct time_conv *dest)
{
dest->start=*src;
}
void GET_TIME(struct timeval *dst, struct time_conv *data)
{
LARGE_INTEGER PTime, TimeFreq;
LONG tmp;
PTime=KeQueryPerformanceCounter(&TimeFreq);
#ifndef __GNUC__
tmp=(LONG)(PTime.QuadPart/TimeFreq.QuadPart);
dst->tv_sec=data->start.tv_sec+tmp;
dst->tv_usec=data->start.tv_usec+(LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
#else
// TODO FIXME:
#endif
if (dst->tv_usec>=1000000) {
dst->tv_sec++;
dst->tv_usec-=1000000;
}
}
#else /*KQPC_TS*/
/*RDTSC timestamps*/
/* callers must be at IRQL=PASSIVE_LEVEL */
VOID TIME_SYNCHRONIZE(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);
#ifndef __GNUC__
__asm
{
push eax
push edx
push ecx
rdtsc
lea ecx, start_ticks
mov [ecx+4], edx
mov [ecx], eax
pop ecx
pop edx
pop eax
}
#else
asm("push %%eax;"
"push %%edx;"
"push %%ecx;"
"rdtsc;"
"lea %0,%%ecx;"
"mov %%edx,(%%ecx+4);"
"mov %%eax,(%%ecx);"
"pop %%ecx;"
"pop %%edx;"
"pop %%eax;"
:"=c"(start_ticks): );
#endif
KeLowerIrql(old);
KeWaitForSingleObject(&event,UserRequest,KernelMode,TRUE ,&i);
KeRaiseIrql(HIGH_LEVEL,&old);
stop_kqpc=KeQueryPerformanceCounter(&stop_freq);
#ifndef __GNUC__
__asm
{
push eax
push edx
push ecx
rdtsc
lea ecx, stop_ticks
mov [ecx+4], edx
mov [ecx], eax
pop ecx
pop edx
pop eax
}
#else
asm("push %%eax;"
"push %%edx;"
"push %%ecx;"
"rdtsc;"
"lea %0,%%ecx;"
"mov %%edx,(%%ecx+4);"
"mov %%eax,(%%ecx);"
"pop %%ecx;"
"pop %%edx;"
"pop %%eax;"
:"=c"(stop_ticks): );
#endif
KeLowerIrql(old);
delta=stop_ticks-start_ticks;
delta2=stop_kqpc.QuadPart-start_kqpc.QuadPart;
if (delta>10000000000) {
delta/=16;
delta2/=16;
}
reference=delta*(start_freq.QuadPart)/delta2;
data->reference=reference/1000;
if (reference%1000>500)
data->reference++;
data->reference*=1000;
reference=data->reference;
KeQuerySystemTime(&system_time);
#ifndef __GNUC__
__asm
{
push eax
push edx
push ecx
rdtsc
lea ecx, curr_ticks
mov [ecx+4], edx
mov [ecx], eax
pop ecx
pop edx
pop eax
}
#else
asm("push %%eax;"
"push %%edx;"
"push %%ecx;"
"rdtsc;"
"lea %0,%%ecx;"
"mov %%edx,(%%ecx+4);"
"mov %%eax,(%%ecx);"
"pop %%ecx;"
"pop %%edx;"
"pop %%eax;"
:"=c"(curr_ticks): );
#endif
tmp.tv_sec=-(LONG)(curr_ticks/reference);
tmp.tv_usec=-(LONG)((curr_ticks%reference)*1000000/reference);
system_time.QuadPart-=116444736000000000;
tmp.tv_sec+=(LONG)(system_time.QuadPart/10000000);
tmp.tv_usec+=(LONG)((system_time.QuadPart%10000000)/10);
if (tmp.tv_usec<0) {
tmp.tv_sec--;
tmp.tv_usec+=1000000;
}
data->start=tmp;
IF_LOUD(DbgPrint("Frequency %I64u MHz\n",data->reference);)
}
void FORCE_TIME(struct timeval *src, struct time_conv *dest)
{
dest->start=*src;
}
void GET_TIME(struct timeval *dst, struct time_conv *data)
{
ULONGLONG tmp;
#ifndef __GNUC__
__asm
{
push eax
push edx
push ecx
rdtsc
lea ecx, tmp
mov [ecx+4], edx
mov [ecx], eax
pop ecx
pop edx
pop eax
}
#else
asm("push %%eax;"
"push %%edx;"
"push %%ecx;"
"rdtsc;"
"lea %0,%%ecx;"
"mov %%edx,(%%ecx+4);"
"mov %%eax,(%%ecx);"
"pop %%ecx;"
"pop %%edx;"
"pop %%eax;"
:"=c"(tmp): );
#endif
if (data->reference==0) {
return;
}
dst->tv_sec=(LONG)(tmp/data->reference);
dst->tv_usec=(LONG)((tmp-dst->tv_sec*data->reference)*1000000/data->reference);
dst->tv_sec+=data->start.tv_sec;
dst->tv_usec+=data->start.tv_usec;
if (dst->tv_usec>=1000000) {
dst->tv_sec++;
dst->tv_usec-=1000000;
}
}
#endif /*KQPC_TS*/

View file

@ -1,262 +0,0 @@
/*
* Copyright (c) 2001
* Politecnico di Torino. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the Politecnico
* di Torino, and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef _time_calls
#define _time_calls
#ifdef WIN_NT_DRIVER
#include "debug.h"
/*!
\brief A microsecond precise timestamp.
included in the sf_pkthdr or the bpf_hdr that NPF associates with every packet.
*/
struct timeval {
long tv_sec; ///< seconds
long tv_usec; ///< microseconds
};
#endif /*WIN_NT_DRIVER*/
struct time_conv {
ULONGLONG reference;
struct timeval start;
};
#ifdef __GNUC__
void TIME_DESYNCHRONIZE(struct time_conv *data);
VOID TIME_SYNCHRONIZE(struct time_conv *data);
void FORCE_TIME(struct timeval *src, struct time_conv *dest);
void GET_TIME(struct timeval *dst, struct time_conv *data);
#else /* __GNUC__ */
#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;
}
#ifdef KQPC_TS
/* KeQueryPerformanceCounter TimeStamps */
__inline VOID TIME_SYNCHRONIZE(struct time_conv *data)
{
struct timeval tmp;
LARGE_INTEGER SystemTime;
LARGE_INTEGER i;
ULONG tmp2;
LARGE_INTEGER TimeFreq,PTime;
if (data->reference!=0)
return;
// get the absolute value of the system boot time.
PTime=KeQueryPerformanceCounter(&TimeFreq);
KeQuerySystemTime(&SystemTime);
tmp.tv_sec=(LONG)(SystemTime.QuadPart/10000000-11644473600);
tmp.tv_usec=(LONG)((SystemTime.QuadPart%10000000)/10);
tmp.tv_sec-=(ULONG)(PTime.QuadPart/TimeFreq.QuadPart);
tmp.tv_usec-=(LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
if (tmp.tv_usec<0) {
tmp.tv_sec--;
tmp.tv_usec+=1000000;
}
data->start=tmp;
data->reference=1;
}
__inline void GET_TIME(struct timeval *dst, struct time_conv *data)
{
LARGE_INTEGER PTime, TimeFreq;
LONG tmp;
PTime=KeQueryPerformanceCounter(&TimeFreq);
tmp=(LONG)(PTime.QuadPart/TimeFreq.QuadPart);
dst->tv_sec=data->start.tv_sec+tmp;
dst->tv_usec=data->start.tv_usec+(LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
if (dst->tv_usec>=1000000) {
dst->tv_sec++;
dst->tv_usec-=1000000;
}
}
__inline void FORCE_TIME(struct timeval *src, struct time_conv *dest)
{
dest->start=*src;
}
#else
/*RDTSC timestamps*/
/* callers must be at IRQL=PASSIVE_LEVEL */
__inline VOID TIME_SYNCHRONIZE(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);
#ifndef __GNUC__
__asm
{
push eax
push edx
push ecx
rdtsc
lea ecx, start_ticks
mov [ecx+4], edx
mov [ecx], eax
pop ecx
pop edx
pop eax
}
#else
#endif
KeLowerIrql(old);
KeWaitForSingleObject(&event,UserRequest,KernelMode,TRUE ,&i);
KeRaiseIrql(HIGH_LEVEL,&old);
stop_kqpc=KeQueryPerformanceCounter(&stop_freq);
#ifndef __GNUC__
__asm
{
push eax
push edx
push ecx
rdtsc
lea ecx, stop_ticks
mov [ecx+4], edx
mov [ecx], eax
pop ecx
pop edx
pop eax
}
#else
#endif
KeLowerIrql(old);
delta=stop_ticks-start_ticks;
delta2=stop_kqpc.QuadPart-start_kqpc.QuadPart;
if (delta>10000000000) {
delta/=16;
delta2/=16;
}
reference=delta*(start_freq.QuadPart)/delta2;
data->reference=reference/1000;
if (reference%1000>500)
data->reference++;
data->reference*=1000;
reference=data->reference;
KeQuerySystemTime(&system_time);
#ifndef __GNUC__
__asm
{
push eax
push edx
push ecx
rdtsc
lea ecx, curr_ticks
mov [ecx+4], edx
mov [ecx], eax
pop ecx
pop edx
pop eax
}
#else
#endif
tmp.tv_sec=-(LONG)(curr_ticks/reference);
tmp.tv_usec=-(LONG)((curr_ticks%reference)*1000000/reference);
system_time.QuadPart-=116444736000000000;
tmp.tv_sec+=(LONG)(system_time.QuadPart/10000000);
tmp.tv_usec+=(LONG)((system_time.QuadPart%10000000)/10);
if (tmp.tv_usec<0) {
tmp.tv_sec--;
tmp.tv_usec+=1000000;
}
data->start=tmp;
IF_LOUD(DbgPrint("Frequency %I64u MHz\n",data->reference);)
}
__inline void FORCE_TIME(struct timeval *src, struct time_conv *dest)
{
dest->start=*src;
}
__inline void GET_TIME(struct timeval *dst, struct time_conv *data)
{
ULONGLONG tmp;
#ifndef __GNUC__
__asm
{
push eax
push edx
push ecx
rdtsc
lea ecx, tmp
mov [ecx+4], edx
mov [ecx], eax
pop ecx
pop edx
pop eax
}
#else
#endif
if (data->reference==0) {
return;
}
dst->tv_sec=(LONG)(tmp/data->reference);
dst->tv_usec=(LONG)((tmp-dst->tv_sec*data->reference)*1000000/data->reference);
dst->tv_sec+=data->start.tv_sec;
dst->tv_usec+=data->start.tv_usec;
if (dst->tv_usec>=1000000) {
dst->tv_sec++;
dst->tv_usec-=1000000;
}
}
#endif /*KQPC_TS*/
#endif /*WIN_NT_DRIVER*/
#endif /* __GNUC__ */
#endif /*_time_calls*/

View file

@ -1,379 +0,0 @@
/*
* Copyright (c) 2001
* Politecnico di Torino. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the Politecnico
* di Torino, and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifdef WIN32
#include "tme.h"
#endif
#ifdef __FreeBSD__
#include <net/tme/tme.h>
#endif
/* resizes extended memory */
uint32 init_extended_memory(uint32 size, MEM_TYPE *mem_ex)
{
uint8 *tmp;
if ((mem_ex==NULL)||(mem_ex->buffer==NULL)||(size==0))
return TME_ERROR; /* awfully never reached!!!! */
tmp=mem_ex->buffer;
mem_ex->buffer=NULL;
FREE_MEMORY(tmp);
ALLOCATE_MEMORY(tmp,uint8,size);
if (tmp==NULL)
return TME_ERROR; /* no memory */
mem_ex->size=size;
mem_ex->buffer=tmp;
return TME_SUCCESS;
}
/* activates a block of the TME */
uint32 set_active_tme_block(TME_CORE *tme, uint32 block)
{
if ((block>=MAX_TME_DATA_BLOCKS)||(!IS_VALIDATED(tme->validated_blocks,block)))
return TME_ERROR;
tme->active=block;
tme->working=block;
return TME_SUCCESS;
}
/* simply inserts default values in a TME block */
/* it DOESN'T initialize the block in the core!! */
/* FIXME default values are defined at compile time, */
/* it will be useful to store them in the registry */
uint32 init_tme_block(TME_CORE *tme, uint32 block)
{
TME_DATA *data;
if (block>=MAX_TME_DATA_BLOCKS)
return TME_ERROR;
data=&(tme->block_data[block]);
tme->working=block;
ZERO_MEMORY(data,sizeof(TME_DATA));
/* entries in LUT */
data->lut_entries=TME_LUT_ENTRIES_DEFAULT;
/* blocks */
data->shared_memory_blocks=TME_SHARED_MEMORY_BLOCKS_DEFAULT;
/* block size */
data->block_size=TME_BLOCK_SIZE_DEFAULT;
/* lookup function */
data->lookup_code=lut_fcn_mapper(TME_LOOKUP_CODE_DEFAULT);
/* rehashing value */
data->rehashing_value=TME_REHASHING_VALUE_DEFAULT;
/* out lut function */
data->out_lut_exec=TME_OUT_LUT_EXEC_DEFAULT;
/* default function */
data->default_exec=TME_DEFAULT_EXEC_DEFAULT;
/* extra segment size */
data->extra_segment_size=TME_EXTRA_SEGMENT_SIZE_DEFAULT;
data->enable_deletion=FALSE;
data->last_read.tv_sec=0;
data->last_read.tv_usec=0;
return TME_SUCCESS;
}
/* it validates a TME block and */
/* (on OK) inserts the block in the core */
uint32 validate_tme_block(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 block, uint32 mem_ex_offset)
{
uint32 required_memory;
uint8 *base=mem_ex_offset+mem_ex->buffer;
TME_DATA *data;
/* FIXME soluzione un po' posticcia... */
if (mem_ex_offset==0)
return TME_ERROR;
if (block>=MAX_TME_DATA_BLOCKS)
return TME_ERROR;
data=&tme->block_data[block];
if (data->lut_entries==0)
return TME_ERROR;
if (data->key_len==0)
return TME_ERROR;
if (data->shared_memory_blocks==0)
return TME_ERROR;
if (data->block_size==0)
return TME_ERROR;
/* checks if the lookup function is valid */
if (data->lookup_code==NULL)
return TME_ERROR;
/* checks if the out lut exec function is valid */
if (exec_fcn_mapper(data->out_lut_exec)==NULL)
return TME_ERROR;
/* checks if the default exec function is valid */
if (exec_fcn_mapper(data->default_exec)==NULL)
return TME_ERROR;
/* let's calculate memory needed */
required_memory=data->lut_entries*sizeof(RECORD); /*LUT*/
required_memory+=data->block_size*data->shared_memory_blocks; /*shared segment*/
required_memory+=data->extra_segment_size; /*extra segment*/
if (required_memory>(mem_ex->size-mem_ex_offset))
return TME_ERROR; /*not enough memory*/
/* the TME block can be initialized */
ZERO_MEMORY(base,required_memory);
data->lut_base_address=base;
data->shared_memory_base_address=
data->lut_base_address+
data->lut_entries*sizeof(RECORD);
data->extra_segment_base_address=
data->shared_memory_base_address+
data->block_size*data->shared_memory_blocks;
data->filled_blocks=1;
VALIDATE(tme->validated_blocks,block);
tme->active=block;
tme->working=block;
return TME_SUCCESS;
}
/* I/F between the bpf machine and the callbacks, just some checks */
uint32 lookup_frontend(MEM_TYPE *mem_ex, TME_CORE *tme,uint32 mem_ex_offset, struct time_conv *time_ref)
{
if (tme->active==TME_NONE_ACTIVE)
return TME_FALSE;
return (tme->block_data[tme->active].lookup_code)(mem_ex_offset+mem_ex->buffer,&tme->block_data[tme->active],mem_ex, time_ref);
}
/* I/F between the bpf machine and the callbacks, just some checks */
uint32 execute_frontend(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 pkt_size, uint32 offset)
{
exec_fcn tmp;
TME_DATA *data;
uint8 *block;
uint8 *mem_data;
if (tme->active==TME_NONE_ACTIVE)
return TME_ERROR;
data=&tme->block_data[tme->active];
if (data->last_found==NULL)
{ /*out lut exec */
tmp=exec_fcn_mapper(data->out_lut_exec);
block=data->shared_memory_base_address;
}
else
{ /*checks if last_found is valid */
if ((data->last_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;
}

View file

@ -1,183 +0,0 @@
/*
* Copyright (c) 2001
* Politecnico di Torino. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the Politecnico
* di Torino, and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef __tme_include_
#define __tme_include_
#ifdef WIN_NT_DRIVER
#include "ntddk.h"
#include "memory_t.h"
#include "time_calls.h"
#endif /*WIN_NT_DRIVER*/
#ifdef WIN32
#include "memory_t.h"
#include "time_calls.h"
#endif /*WIN32*/
#ifdef __FreeBSD__
#ifdef _KERNEL
#include <net/tme/time_calls.h>
#else
#include <tme/time_calls.h>
#endif
#endif
/* 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 */
#ifndef __GNUC__
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);
#else
typedef uint32 (*lut_fcn)(uint8 *key, void *data,MEM_TYPE *mem_ex, struct time_conv *time_ref );
typedef uint32 (*exec_fcn)(uint8 *block, uint32 pkt_size, void *data, MEM_TYPE *mem_ex, uint8 *mem_data);
#endif
/* 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

View file

@ -1,73 +0,0 @@
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,
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,
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,
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,
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,
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
};
#define VALID_INSTRUCTIONS_LEN (sizeof(valid_instructions)/sizeof(u_short))

View file

@ -1,325 +0,0 @@
/*-
* 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: /cygdrive/c/RCVS/CVS/ReactOS/reactos/drivers/net/packet/win_bpf.h,v 1.3 2002/12/21 04:46:09 robd Exp $ (LBL)
*/
#ifndef BPF_MAJOR_VERSION
/* BSD style release date */
#define BPF_RELEASE 199606
typedef UCHAR u_char;
typedef USHORT u_short;
typedef ULONG u_int;
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
#include "time_calls.h"
/*
* The instruction data structure.
*/
struct bpf_insn {
u_short code;
u_char jt;
u_char jf;
bpf_int32 k;
};
/*
* Structure for BIOCSETF.
*/
struct bpf_program {
u_int bf_len;
struct bpf_insn *bf_insns;
};
/*
* Struct returned by BIOCGSTATS.
*/
struct bpf_stat {
u_int bs_recv; /* number of packets received */
u_int bs_drop; /* number of packets dropped */
};
/*
* 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
#endif

View file

@ -1,962 +0,0 @@
/*
* Copyright (c) 1999, 2000
* Politecnico di Torino. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the Politecnico
* di Torino, and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
*
*
* Portions 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.c 7.5 (Berkeley) 7/15/91
*/
#include "tme.h"
#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;
/* 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 */
case BPF_ST:
mem[pc->k] = A;
continue;
case BPF_STX:
mem[pc->k] = X;
continue;
/* 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 */
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;
/* 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 */
}
}
}
//-------------------------------------------------------------------
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 + sizeof(int32) > buflen) {
return 0;
}
if(k + (int)sizeof(int32) < headersize) A = EXTRACT_LONG(&p[k]);
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 *)p+k+2)<<8|
(u_int32)*((u_char *)pd+k-headersize);
}
else if(k == headersize-1){
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 == 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);
}
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 + (int)sizeof(short) < headersize) A = EXTRACT_SHORT(&p[k]);
else if(k == headersize){
A=(u_short)*((u_char *)p+k)<<8|
(u_short)*((u_char *)pd+k-headersize);
}
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<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 + (int)sizeof(int32) < headersize) A = EXTRACT_LONG(&p[k]);
else if(k + (int)sizeof(int32) == headersize+2){
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 + (int)sizeof(int32) == headersize+3){
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 + (int)sizeof(int32) == headersize+4){
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);
}
A = EXTRACT_LONG(&pd[k-headersize]);
continue;
case BPF_LD|BPF_H|BPF_IND:
k = X + pc->k;
if (k + sizeof(short) > buflen) {
return 0;
}
if(k + (int)sizeof(short) < headersize) A = EXTRACT_SHORT(&p[k]);
else if(k == headersize){
A=(u_short)*((u_char *)p+k)<<8|
(u_short)*((u_char *)pd+k-headersize);
}
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((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;
/* 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 */
case BPF_ST:
mem[pc->k] = A;
continue;
case BPF_STX:
mem[pc->k] = X;
continue;
/* 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 */
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;
/* 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 */
}
}
}
int32
bpf_validate(f, len,mem_ex_size)
struct bpf_insn *f;
int32 len;
uint32 mem_ex_size;
{
register int32 i,j;
register struct bpf_insn *p;
int32 flag;
for (i = 0; i < len; ++i) {
/*
* Check that that jumps are forward, and within
* the code block.
*/
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");)
if (BPF_CLASS(p->code) == BPF_JMP) {
register int32 from = i + 1;
if (BPF_OP(p->code) == BPF_JA) {
if (from + p->k >= len)
return 0;
}
else if (from + p->jt >= len || from + p->jf >= len)
return 0;
}
IF_LOUD(DbgPrint("Validating program: no wrong JUMPS");)
/*
* Check that memory operations use valid addresses.
*/
if (((BPF_CLASS(p->code) == BPF_ST && ((p->code &BPF_MEM_EX_IMM)!=BPF_MEM_EX_IMM && (p->code &BPF_MEM_EX_IND)!=BPF_MEM_EX_IND)) ||
(BPF_CLASS(p->code) == BPF_LD &&
(p->code & 0xe0) == BPF_MEM)) &&
(p->k >= BPF_MEMWORDS || p->k < 0))
return 0;
IF_LOUD(DbgPrint("Validating program: no wrong ST/LD memory locations");)
/*
* Check if key stores use valid addresses
*/
if (BPF_CLASS(p->code) == BPF_ST && (p->code &BPF_MEM_EX_IMM)==BPF_MEM_EX_IMM)
switch (BPF_SIZE(p->code))
{
case BPF_W: if (p->k<0 || p->k+3>=(int32)mem_ex_size) return 0;
case BPF_H: if (p->k<0 || p->k+1>=(int32)mem_ex_size) return 0;
case BPF_B: if (p->k<0 || p->k>=(int32)mem_ex_size) return 0;
}
IF_LOUD(DbgPrint("Validating program: no wrong ST/LD mem_ex locations");)
/*
* Check for constant division by 0.
*/
if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0)
return 0;
}
return BPF_CLASS(f[len - 1].code) == BPF_RET;
}

View file

@ -1,689 +0,0 @@
/*
* Copyright (c) 2001
* Politecnico di Torino. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the Politecnico
* di Torino, and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
*
*
* Portions 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.
*/
#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];
#ifndef __GNUC__
__asm
{
push eax
push ebx
mov ebx,tmp2
xor eax, eax
mov ax, [ebx]
bswap eax
mov A, eax
pop ebx
pop eax
}
#else
asm("push %%eax;"
"push %%ebx;"
"mov %1,%%ebx;"
"xor %%eax, %%eax;"
"mov (%%ebx), %%ax;"
"bswap %%eax;"
"mov %%eax, %0;"
"pop %%ebx;"
"pop %%eax;"
:"=a"(A),"=c"(tmp2): );
#endif
continue;
case BPF_LDX|BPF_MEM_EX_IMM|BPF_H:
tmp2=(uint16*)&mem_ex->buffer[pc->k];
#ifndef __GNUC__
__asm
{
push eax
push ebx
mov ebx,tmp2
xor eax, eax
mov ax, [ebx]
bswap eax
mov X, eax
pop ebx
pop eax
}
#else
asm("push %%eax;"
"push %%ebx;"
"mov %1,%%ebx;"
"xor %%eax, %%eax;"
"mov (%%ebx), %%ax;"
"bswap %%eax;"
"mov %%eax, %0;"
"pop %%ebx;"
"pop %%eax;"
:"=a"(X),"=c"(tmp2): );
#endif
continue;
case BPF_LD|BPF_MEM_EX_IMM|BPF_W:
tmp=(uint32*)&mem_ex->buffer[pc->k];
#ifndef __GNUC__
__asm
{
push eax
push ebx
mov ebx,tmp
mov eax, [ebx]
bswap eax
mov A, eax
pop ebx
pop eax
}
#else
asm("push %%eax;"
"push %%ebx;"
"mov %1,%%ebx;"
"xor %%eax, %%eax;"
"mov (%%ebx), %%ax;"
"bswap %%eax;"
"mov %%eax, %0;"
"pop %%ebx;"
"pop %%eax;"
:"=a"(A),"=c"(tmp): );
#endif
continue;
case BPF_LDX|BPF_MEM_EX_IMM|BPF_W:
tmp=(uint32*)&mem_ex->buffer[pc->k];
#ifndef __GNUC__
__asm
{
push eax
push ebx
mov ebx,tmp
mov eax, [ebx]
bswap eax
mov X, eax
pop ebx
pop eax
}
#else
asm("push %%eax;"
"push %%ebx;"
"mov %1,%%ebx;"
"xor %%eax, %%eax;"
"mov (%%ebx), %%ax;"
"bswap %%eax;"
"mov %%eax, %0;"
"pop %%ebx;"
"pop %%eax;"
:"=a"(X),"=c"(tmp): );
#endif
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];
#ifndef __GNUC__
__asm
{
push eax
push ebx
mov ebx,tmp2
xor eax, eax
mov ax, [ebx]
bswap eax
mov A, eax
pop ebx
pop eax
}
#else
asm("push %%eax;"
"push %%ebx;"
"mov %1,%%ebx;"
"xor %%eax, %%eax;"
"mov (%%ebx), %%ax;"
"bswap %%eax;"
"mov %%eax, %0;"
"pop %%ebx;"
"pop %%eax;"
:"=a"(A),"=c"(tmp2): );
#endif
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];
#ifndef __GNUC__
__asm
{
push eax
push ebx
mov ebx,tmp
mov eax, [ebx]
bswap eax
mov A, eax
pop ebx
pop eax
}
#else
asm("push %%eax;"
"push %%ebx;"
"mov %1,%%ebx;"
"xor %%eax, %%eax;"
"mov (%%ebx), %%ax;"
"bswap %%eax;"
"mov %%eax, %0;"
"pop %%ebx;"
"pop %%eax;"
:"=a"(A),"=c"(tmp): );
#endif
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];
#ifndef __GNUC__
__asm
{
push eax
push ebx
mov ebx, tmp
mov eax, A
bswap eax
mov [ebx], eax
pop ebx
pop eax
}
#else
asm("push %%eax;"
"push %%ebx;"
"mov %1,%%ebx;"
"xor %%eax, %%eax;"
"mov (%%ebx), %%ax;"
"bswap %%eax;"
"mov %%eax, %0;"
"pop %%ebx;"
"pop %%eax;"
:"=a"(A),"=c"(tmp): );
#endif
continue;
case BPF_STX|BPF_MEM_EX_IMM|BPF_W:
tmp=(uint32*)&mem_ex->buffer[pc->k];
#ifndef __GNUC__
__asm
{
push eax
push ebx
mov ebx, tmp
mov eax, X
bswap eax
mov [ebx], eax
pop ebx
pop eax
}
#else
asm("push %%eax;"
"push %%ebx;"
"mov %1,%%ebx;"
"xor %%eax, %%eax;"
"mov (%%ebx), %%ax;"
"bswap %%eax;"
"mov %%eax, %0;"
"pop %%ebx;"
"pop %%eax;"
:"=a"(X),"=c"(tmp): );
#endif
continue;
case BPF_ST|BPF_MEM_EX_IMM|BPF_H:
tmp2=(uint16*)&mem_ex->buffer[pc->k];
#ifndef __GNUC__
__asm
{
push eax
push ebx
mov ebx, tmp2
mov eax, A
xchg ah, al
mov [ebx], ax
pop ebx
pop eax
}
#else
asm("push %%eax;"
"push %%ebx;"
"mov %1,%%ebx;"
"xor %%eax, %%eax;"
"mov (%%ebx), %%ax;"
"bswap %%eax;"
"mov %%eax, %0;"
"pop %%ebx;"
"pop %%eax;"
:"=a"(A),"=c"(tmp2): );
#endif
continue;
case BPF_STX|BPF_MEM_EX_IMM|BPF_H:
tmp2=(uint16*)&mem_ex->buffer[pc->k];
#ifndef __GNUC__
__asm
{
push eax
push ebx
mov ebx, tmp2
mov eax, X
xchg ah, al
mov [ebx], ax
pop ebx
pop eax
}
#else
asm("push %%eax;"
"push %%ebx;"
"mov %1,%%ebx;"
"xor %%eax, %%eax;"
"mov (%%ebx), %%ax;"
"bswap %%eax;"
"mov %%eax, %0;"
"pop %%ebx;"
"pop %%eax;"
:"=a"(X),"=c"(tmp2): );
#endif
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];
#ifndef __GNUC__
__asm
{
push eax
push ebx
mov ebx, tmp
mov eax, A
bswap eax
mov [ebx], eax
pop ebx
pop eax
}
#else
asm("push %%eax;"
"push %%ebx;"
"mov %1,%%ebx;"
"xor %%eax, %%eax;"
"mov (%%ebx), %%ax;"
"bswap %%eax;"
"mov %%eax, %0;"
"pop %%ebx;"
"pop %%eax;"
:"=a"(A),"=c"(tmp): );
#endif
continue;
case BPF_ST|BPF_MEM_EX_IND|BPF_H:
tmp2=(uint16*)&mem_ex->buffer[pc->k+X];
#ifndef __GNUC__
__asm
{
push eax
push ebx
mov ebx, tmp2
mov eax, A
xchg ah, al
mov [ebx], ax
pop ebx
pop eax
}
#else
asm("push %%eax;"
"push %%ebx;"
"mov %1,%%ebx;"
"xor %%eax, %%eax;"
"mov (%%ebx), %%ax;"
"bswap %%eax;"
"mov %%eax, %0;"
"pop %%ebx;"
"pop %%eax;"
:"=a"(A),"=c"(tmp2): );
#endif
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<0)||(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 */
}
}
}

View file

@ -1,32 +0,0 @@
/*
* Copyright (c) 2001
* Politecnico di Torino. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the Politecnico
* di Torino, and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef __FILTER_INIT
#define __FILTER_INIT
#include "tme.h"
#define INIT_OK 1
#define INIT_ERROR 0
uint32 bpf_filter_init(register struct bpf_insn *pc,MEM_TYPE *mem_ex, TME_CORE *tme, struct time_conv *time_ref);
#endif

View file

@ -1,366 +0,0 @@
/*
* Copyright (c) 1999, 2000
* Politecnico di Torino. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the Politecnico
* di Torino, and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifdef _MSC_VER
#include "stdarg.h"
#include "ntddk.h"
#include "ntiologc.h"
#include "ndis.h"
#else
#include <ddk/ntddk.h>
#include <net/ndis.h>
#define NdisReinitializePacket(Packet) \
{ \
(Packet)->Private.Head = (PNDIS_BUFFER)NULL; \
(Packet)->Private.ValidCounts = FALSE; \
}
#endif
#include "debug.h"
#include "packet.h"
//-------------------------------------------------------------------
NTSTATUS
NPF_Write(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
POPEN_INSTANCE Open;
PIO_STACK_LOCATION IrpSp;
PNDIS_PACKET pPacket;
UINT i;
NDIS_STATUS Status;
IF_LOUD(DbgPrint("NPF_Write\n");)
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Open=IrpSp->FileObject->FsContext;
IF_LOUD(DbgPrint("Max frame size = %d\n", Open->MaxFrameSize);)
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");)
Irp->IoStatus.Status = NDIS_STATUS_SUCCESS;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return NDIS_STATUS_SUCCESS;
}
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;
}
// The packet has 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);
// 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;
UINT i;
NDIS_STATUS Status;
LARGE_INTEGER StartTicks, CurTicks, TargetTicks;
LARGE_INTEGER TimeFreq;
struct timeval BufStartTime;
struct sf_pkthdr *winpcap_hdr;
PMDL TmpMdl;
PCHAR CurPos;
PCHAR EndOfUserBuff = UserBuff + UserBuffSize;
IF_LOUD(DbgPrint("NPF: BufferedWrite, UserBuff=%x, Size=%u\n", UserBuff, UserBuffSize);)
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Open=IrpSp->FileObject->FsContext;
// Security check on the length of the user buffer
if(UserBuff==0)
{
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;
}
// Start from the first packet
winpcap_hdr = (struct sf_pkthdr*)UserBuff;
// Retrieve the time references
StartTicks = KeQueryPerformanceCounter(&TimeFreq);
BufStartTime.tv_sec = winpcap_hdr->ts.tv_sec;
BufStartTime.tv_usec = winpcap_hdr->ts.tv_usec;
// 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;
}
// Save the current time stamp counter
CurTicks = KeQueryPerformanceCounter(NULL);
// 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 free packets
IF_LOUD(DbgPrint("NPF_BufferedWrite: no more free packets, returning.\n");)
return (PCHAR)winpcap_hdr - UserBuff;
}
// The packet has a buffer that needs to be freed after every single write
RESERVED(pPacket)->FreeBufAfterWrite = TRUE;
// Attach the MDL to the packet
NdisChainBufferAtFront(pPacket,TmpMdl);
// 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");)
return (PCHAR)winpcap_hdr - UserBuff;
}
if( Sync ){
// Release the application if it has been blocked for approximately more than 1 seconds
if( winpcap_hdr->ts.tv_sec - BufStartTime.tv_sec > 1 )
{
IF_LOUD(DbgPrint("NPF_BufferedWrite: timestamp elapsed, returning.\n");)
return (PCHAR)winpcap_hdr - UserBuff;
}
#ifndef __GNUC__
// Calculate the time interval to wait before sending the next packet
TargetTicks.QuadPart = StartTicks.QuadPart +
(LONGLONG)((winpcap_hdr->ts.tv_sec - BufStartTime.tv_sec) * 1000000 +
winpcap_hdr->ts.tv_usec - BufStartTime.tv_usec) *
(TimeFreq.QuadPart) / 1000000;
// Wait until the time interval has elapsed
while( CurTicks.QuadPart <= TargetTicks.QuadPart )
CurTicks = KeQueryPerformanceCounter(NULL);
#else
#endif
}
}
return (PCHAR)winpcap_hdr - UserBuff;
}
//-------------------------------------------------------------------
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 ){
// Free the MDL associated with the packet
NdisUnchainBufferAtFront(pPacket, &TmpMdl);
IoFreeMdl(TmpMdl);
}
else{
if((Open->Nwrites - Open->Multiple_Write_Counter) %100 == 99)
NdisSetEvent(&Open->WriteEvent);
Open->Multiple_Write_Counter--;
}
// recyle the packet
NdisReinitializePacket(pPacket);
// Put the packet back on the free list
NdisFreePacket(pPacket);
if( !(RESERVED(pPacket)->FreeBufAfterWrite) ){
if(Open->Multiple_Write_Counter==0){
// Release the buffer and awake the application
NdisUnchainBufferAtFront(pPacket, &TmpMdl);
Irp=RESERVED(pPacket)->Irp;
irpSp = IoGetCurrentIrpStackLocation(Irp);
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = irpSp->Parameters.Write.Length;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
}
return;
}
#ifdef __GNUC__
/*
__divdi3()
{
//_alldiv();
}
//_allmul();
//_allrem();
*/
#endif