Updated with latest version changes to original source.

svn path=/trunk/; revision=3555
This commit is contained in:
Robert Dickenson 2002-09-24 15:16:46 +00:00
parent 2217a4d789
commit 5f1366aacc
34 changed files with 7284 additions and 1033 deletions

View file

@ -0,0 +1,5 @@
*.coff
*.d
*.o
*.sym
*.sys

View file

@ -1,4 +1,4 @@
# $Id: Makefile,v 1.1 2002/06/19 15:43:15 robd Exp $
# $Id: Makefile,v 1.2 2002/09/24 15:16:46 robd Exp $
PATH_TO_TOP = ../../..
@ -7,15 +7,26 @@ TARGET_TYPE = driver
TARGET_NAME = packet
TARGET_CFLAGS = -DNDIS50
# -disable-stdcall-fixup
TARGET_CFLAGS = -DDBG -DWIN_NT_DRIVER -DKQPC_TS
TARGET_OBJECTS = \
packet.o \
read.o \
openclos.o \
write.o \
win_bpf_filter.o
packet.o \
openclos.o \
read.o \
write.o \
dump.o \
jitter.o \
win_bpf_filter.o \
tme.o \
count_packets.o \
win_bpf_filter_init.o \
tcp_session.o \
memory_t.o \
time_calls.o \
functions.o \
bucket_lookup.o \
normal_lookup.o
TARGET_DDKLIBS = ndis.a

View file

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

View file

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

View file

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

View file

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

View file

@ -19,6 +19,8 @@
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef __DEBUG_INCLUDE
#define __DEBUG_INCLUDE
#if DBG
@ -46,3 +48,5 @@ extern ULONG PacketDebugFlag;
#define IF_INIT_LOUD(A)
#endif
#endif /*#define __DEBUG_INCLUDE*/

View file

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

View file

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

View file

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

View file

@ -0,0 +1,677 @@
/*
* Copyright (c) 2002
* Politecnico di Torino. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the Politecnico
* di Torino, and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifdef _MSC_VER
#include "stdarg.h"
#include "ntddk.h"
#include "ntiologc.h"
#include "ndis.h"
#else
#include <ddk/ntddk.h>
#include <net/ndis.h>
#endif
#include "packet.h"
#include "win_bpf.h"
emit_func emitm;
//
// emit routine to update the jump table
//
void emit_lenght(binary_stream *stream, ULONG value, UINT len)
{
(stream->refs)[stream->bpf_pc]+=len;
stream->cur_ip+=len;
}
//
// emit routine to output the actual binary code
//
void emit_code(binary_stream *stream, ULONG value, UINT len)
{
switch (len){
case 1:
stream->ibuf[stream->cur_ip]=(UCHAR)value;
stream->cur_ip++;
break;
case 2:
*((USHORT*)(stream->ibuf+stream->cur_ip))=(USHORT)value;
stream->cur_ip+=2;
break;
case 4:
*((ULONG*)(stream->ibuf+stream->cur_ip))=value;
stream->cur_ip+=4;
break;
default:;
}
return;
}
//
// Function that does the real stuff
//
BPF_filter_function BPFtoX86(struct bpf_insn *prog, UINT nins, INT *mem)
{
struct bpf_insn *ins;
UINT i, pass;
binary_stream stream;
// Allocate the reference table for the jumps
#ifdef NTKERNEL
stream.refs=(UINT *)ExAllocatePoolWithTag(NonPagedPool, (nins + 1)*sizeof(UINT), '0JWA');
#else
stream.refs=(UINT *)malloc((nins + 1)*sizeof(UINT));
#endif
if(stream.refs==NULL)
{
return NULL;
}
// Reset the reference table
for(i=0; i< nins + 1; i++)
stream.refs[i]=0;
stream.cur_ip=0;
stream.bpf_pc=0;
// the first pass will emit the lengths of the instructions
// to create the reference table
emitm=emit_lenght;
for(pass=0;;){
ins = prog;
/* create the procedure header */
PUSH(EBP)
MOVrd(EBP,ESP)
PUSH(EBX)
PUSH(ECX)
PUSH(EDX)
PUSH(ESI)
PUSH(EDI)
MOVodd(EBX, EBP, 8)
for(i=0;i<nins;i++){
stream.bpf_pc++;
switch (ins->code) {
default:
return NULL;
case BPF_RET|BPF_K:
MOVid(EAX,ins->k)
POP(EDI)
POP(ESI)
POP(EDX)
POP(ECX)
POP(EBX)
POP(EBP)
RET()
break;
case BPF_RET|BPF_A:
POP(EDI)
POP(ESI)
POP(EDX)
POP(ECX)
POP(EBX)
POP(EBP)
RET()
break;
case BPF_LD|BPF_W|BPF_ABS:
MOVid(ECX,ins->k)
MOVrd(ESI,ECX)
ADDib(ECX,sizeof(INT))
CMPodd(ECX, EBP, 0x10)
JLEb(12)
POP(EDI)
POP(ESI)
POP(EDX)
POP(ECX)
POP(EBX)
POP(EBP)
MOVid(EAX,0) //this can be optimized with xor eax,eax
RET()
MOVobd(EAX, EBX, ESI)
BSWAP(EAX)
break;
case BPF_LD|BPF_H|BPF_ABS:
MOVid(ECX,ins->k)
MOVrd(ESI,ECX)
ADDib(ECX,sizeof(SHORT))
CMPodd(ECX, EBP, 0x10)
JLEb(12)
POP(EDI)
POP(ESI)
POP(EDX)
POP(ECX)
POP(EBX)
POP(EBP)
MOVid(EAX,0)
RET()
MOVid(EAX,0)
MOVobw(AX, EBX, ESI)
SWAP_AX()
break;
case BPF_LD|BPF_B|BPF_ABS:
MOVid(ECX,ins->k)
CMPodd(ECX, EBP, 0x10)
JLEb(12)
POP(EDI)
POP(ESI)
POP(EDX)
POP(ECX)
POP(EBX)
POP(EBP)
MOVid(EAX,0)
RET()
MOVid(EAX,0)
MOVobb(AL,EBX,ECX)
break;
case BPF_LD|BPF_W|BPF_LEN:
MOVodd(EAX, EBP, 0xc)
break;
case BPF_LDX|BPF_W|BPF_LEN:
MOVodd(EDX, EBP, 0xc)
break;
case BPF_LD|BPF_W|BPF_IND:
MOVid(ECX,ins->k)
ADDrd(ECX,EDX)
MOVrd(ESI,ECX)
ADDib(ECX,sizeof(INT))
CMPodd(ECX, EBP, 0x10)
JLEb(12)
POP(EDI)
POP(ESI)
POP(EDX)
POP(ECX)
POP(EBX)
POP(EBP)
MOVid(EAX,0)
RET()
MOVobd(EAX, EBX, ESI)
BSWAP(EAX)
break;
case BPF_LD|BPF_H|BPF_IND:
MOVid(ECX,ins->k)
ADDrd(ECX,EDX)
MOVrd(ESI,ECX)
ADDib(ECX,sizeof(SHORT))
CMPodd(ECX, EBP, 0x10)
JLEb(12)
POP(EDI)
POP(ESI)
POP(EDX)
POP(ECX)
POP(EBX)
POP(EBP)
MOVid(EAX,0)
RET()
MOVid(EAX,0)
MOVobw(AX, EBX, ESI)
SWAP_AX()
break;
case BPF_LD|BPF_B|BPF_IND:
MOVid(ECX,ins->k)
ADDrd(ECX,EDX)
CMPodd(ECX, EBP, 0x10)
JLEb(12)
POP(EDI)
POP(ESI)
POP(EDX)
POP(ECX)
POP(EBX)
POP(EBP)
MOVid(EAX,0)
RET()
MOVid(EAX,0)
MOVobb(AL,EBX,ECX)
break;
case BPF_LDX|BPF_MSH|BPF_B:
MOVid(ECX,ins->k)
CMPodd(ECX, EBP, 0x10)
JLEb(12)
POP(EDI)
POP(ESI)
POP(EDX)
POP(ECX)
POP(EBX)
POP(EBP)
MOVid(EAX,0)
RET()
MOVid(EDX,0)
MOVobb(DL,EBX,ECX)
ANDib(DL, 0xf)
SHLib(EDX, 2)
break;
case BPF_LD|BPF_IMM:
MOVid(EAX,ins->k)
break;
case BPF_LDX|BPF_IMM:
MOVid(EDX,ins->k)
break;
case BPF_LD|BPF_MEM:
MOVid(ECX,(INT)mem)
MOVid(ESI,ins->k*4)
MOVobd(EAX, ECX, ESI)
break;
case BPF_LDX|BPF_MEM:
MOVid(ECX,(INT)mem)
MOVid(ESI,ins->k*4)
MOVobd(EDX, ECX, ESI)
break;
case BPF_ST:
// XXX: this command and the following could be optimized if the previous
// instruction was already of this type
MOVid(ECX,(INT)mem)
MOVid(ESI,ins->k*4)
MOVomd(ECX, ESI, EAX)
break;
case BPF_STX:
MOVid(ECX,(INT)mem)
MOVid(ESI,ins->k*4)
MOVomd(ECX, ESI, EDX)
break;
case BPF_JMP|BPF_JA:
JMP(stream.refs[stream.bpf_pc+ins->k]-stream.refs[stream.bpf_pc])
break;
case BPF_JMP|BPF_JGT|BPF_K:
CMPid(EAX, ins->k)
JG(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5) // 5 is the size of the following JMP
JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
break;
case BPF_JMP|BPF_JGE|BPF_K:
CMPid(EAX, ins->k)
JGE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
break;
case BPF_JMP|BPF_JEQ|BPF_K:
CMPid(EAX, ins->k)
JE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
break;
case BPF_JMP|BPF_JSET|BPF_K:
MOVrd(ECX,EAX)
ANDid(ECX,ins->k)
JE(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]+5)
JMP(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc])
break;
case BPF_JMP|BPF_JGT|BPF_X:
CMPrd(EAX, EDX)
JA(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
break;
case BPF_JMP|BPF_JGE|BPF_X:
CMPrd(EAX, EDX)
JAE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
break;
case BPF_JMP|BPF_JEQ|BPF_X:
CMPrd(EAX, EDX)
JE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
break;
case BPF_JMP|BPF_JSET|BPF_X:
MOVrd(ECX,EAX)
ANDrd(ECX,EDX)
JE(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]+5)
JMP(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc])
break;
case BPF_ALU|BPF_ADD|BPF_X:
ADDrd(EAX,EDX)
break;
case BPF_ALU|BPF_SUB|BPF_X:
SUBrd(EAX,EDX)
break;
case BPF_ALU|BPF_MUL|BPF_X:
MOVrd(ECX,EDX)
MULrd(EDX)
MOVrd(EDX,ECX)
break;
case BPF_ALU|BPF_DIV|BPF_X:
CMPid(EDX, 0)
JNEb(12)
POP(EDI)
POP(ESI)
POP(EDX)
POP(ECX)
POP(EBX)
POP(EBP)
MOVid(EAX,0)
RET()
MOVrd(ECX,EDX)
MOVid(EDX,0)
DIVrd(ECX)
MOVrd(EDX,ECX)
break;
case BPF_ALU|BPF_AND|BPF_X:
ANDrd(EAX,EDX)
break;
case BPF_ALU|BPF_OR|BPF_X:
ORrd(EAX,EDX)
break;
case BPF_ALU|BPF_LSH|BPF_X:
MOVrd(ECX,EDX)
SHL_CLrb(EAX)
break;
case BPF_ALU|BPF_RSH|BPF_X:
MOVrd(ECX,EDX)
SHR_CLrb(EAX)
break;
case BPF_ALU|BPF_ADD|BPF_K:
ADD_EAXi(ins->k)
break;
case BPF_ALU|BPF_SUB|BPF_K:
SUB_EAXi(ins->k)
break;
case BPF_ALU|BPF_MUL|BPF_K:
MOVrd(ECX,EDX)
MOVid(EDX,ins->k)
MULrd(EDX)
MOVrd(EDX,ECX)
break;
case BPF_ALU|BPF_DIV|BPF_K:
MOVrd(ECX,EDX)
MOVid(EDX,0)
MOVid(ESI,ins->k)
DIVrd(ESI)
MOVrd(EDX,ECX)
break;
case BPF_ALU|BPF_AND|BPF_K:
ANDid(EAX, ins->k)
break;
case BPF_ALU|BPF_OR|BPF_K:
ORid(EAX, ins->k)
break;
case BPF_ALU|BPF_LSH|BPF_K:
SHLib(EAX, (ins->k) & 255)
break;
case BPF_ALU|BPF_RSH|BPF_K:
SHRib(EAX, (ins->k) & 255)
break;
case BPF_ALU|BPF_NEG:
NEGd(EAX)
break;
case BPF_MISC|BPF_TAX:
MOVrd(EDX,EAX)
break;
case BPF_MISC|BPF_TXA:
MOVrd(EAX,EDX)
break;
}
ins++;
}
pass++;
if(pass == 2) break;
#ifdef NTKERNEL
stream.ibuf=(CHAR*)ExAllocatePoolWithTag(NonPagedPool, stream.cur_ip, '1JWA');
#else
stream.ibuf=(CHAR*)malloc(stream.cur_ip);
#endif
if(stream.ibuf==NULL)
{
#ifdef NTKERNEL
ExFreePool(stream.refs);
#else
free(stream.refs);
#endif
return NULL;
}
// modify the reference table to contain the offsets and not the lengths of the instructions
for(i=1; i< nins + 1; i++)
stream.refs[i]+=stream.refs[i-1];
// Reset the counters
stream.cur_ip=0;
stream.bpf_pc=0;
// the second pass creates the actual code
emitm=emit_code;
}
// the reference table is needed only during compilation, now we can free it
#ifdef NTKERNEL
ExFreePool(stream.refs);
#else
free(stream.refs);
#endif
return (BPF_filter_function)stream.ibuf;
}
JIT_BPF_Filter* BPF_jitter(struct bpf_insn *fp, INT nins)
{
JIT_BPF_Filter *Filter;
// Allocate the filter structure
#ifdef NTKERNEL
Filter=(struct JIT_BPF_Filter*)ExAllocatePoolWithTag(NonPagedPool, sizeof(struct JIT_BPF_Filter), '2JWA');
#else
Filter=(struct JIT_BPF_Filter*)malloc(sizeof(struct JIT_BPF_Filter));
#endif
if(Filter==NULL)
{
return NULL;
}
// Allocate the filter's memory
#ifdef NTKERNEL
Filter->mem=(INT*)ExAllocatePoolWithTag(NonPagedPool, BPF_MEMWORDS*sizeof(INT), '3JWA');
#else
Filter->mem=(INT*)malloc(BPF_MEMWORDS*sizeof(INT));
#endif
if(Filter->mem==NULL)
{
#ifdef NTKERNEL
ExFreePool(Filter);
#else
free(Filter);
#endif
return NULL;
}
// Create the binary
if((Filter->Function = BPFtoX86(fp, nins, Filter->mem))==NULL)
{
#ifdef NTKERNEL
ExFreePool(Filter->mem);
ExFreePool(Filter);
#else
free(Filter->mem);
free(Filter);
return NULL;
#endif
}
return Filter;
}
//////////////////////////////////////////////////////////////
void BPF_Destroy_JIT_Filter(JIT_BPF_Filter *Filter){
#ifdef NTKERNEL
ExFreePool(Filter->mem);
ExFreePool(Filter->Function);
ExFreePool(Filter);
#else
free(Filter->mem);
free(Filter->Function);
free(Filter);
#endif
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -25,10 +25,8 @@
#include "ndis.h"
#else
#include <ddk/ntddk.h>
//#include <net/miniport.h>
#include <net/ndis.h>
#endif
#include "debug.h"
#include "packet.h"
@ -41,10 +39,9 @@ static NDIS_MEDIUM MediumArray[] = {
NdisMedium802_5
};
ULONG NamedEventsCounter=0;
#define NUM_NDIS_MEDIA (sizeof MediumArray / sizeof MediumArray[0])
ULONG NamedEventsCounter=0;
//Itoa. Replaces the buggy RtlIntegerToUnicodeString
void PacketItoa(UINT n,PUCHAR buf){
@ -58,9 +55,20 @@ int i;
}
/// Global start time. Used as an absolute reference for timestamp conversion.
struct time_conv G_Start_Time = {
0,
{0, 0},
};
NTSTATUS STDCALL
PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
UINT n_Opened_Instances = 0;
NDIS_SPIN_LOCK Opened_Instances_Lock;
//-------------------------------------------------------------------
NTSTATUS
NPF_Open(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
PDEVICE_EXTENSION DeviceExtension;
@ -71,33 +79,25 @@ PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
NDIS_STATUS Status;
NDIS_STATUS ErrorStatus;
UINT Medium;
UINT i;
PUCHAR tpointer;
PLIST_ENTRY PacketListEntry;
LARGE_INTEGER TimeFreq;
LARGE_INTEGER SystemTime;
LARGE_INTEGER PTime;
PCHAR EvName;
IF_LOUD(DbgPrint("Packet: OpenAdapter\n");)
IF_LOUD(DbgPrint("NPF: OpenAdapter\n");)
DeviceExtension = DeviceObject->DeviceExtension;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
//
// allocate some memory for the open structure
//
Open=ExAllocatePool(NonPagedPool,sizeof(OPEN_INSTANCE));
Open=ExAllocatePoolWithTag(NonPagedPool, sizeof(OPEN_INSTANCE), '0OWA');
if (Open==NULL) {
//
// no memory
//
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
@ -109,34 +109,26 @@ PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
);
EvName=ExAllocatePool(NonPagedPool, sizeof(L"\\BaseNamedObjects\\NPF0000000000") );
EvName=ExAllocatePoolWithTag(NonPagedPool, sizeof(L"\\BaseNamedObjects\\NPF0000000000"), '1OWA');
if (EvName==NULL) {
//
// no memory
//
ExFreePool(Open);
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Save or open here
//
IrpSp->FileObject->FsContext=Open;
Open->DeviceExtension=DeviceExtension;
//
// Save the Irp here for the completeion routine to retrieve
//
Open->OpenCloseIrp=Irp;
//
// Allocate a packet pool for our xmit and receive packets
//
NdisAllocatePacketPool(
&Status,
&Open->PacketPool,
@ -146,7 +138,7 @@ PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
if (Status != NDIS_STATUS_SUCCESS) {
IF_LOUD(DbgPrint("Packet: Failed to allocate packet pool\n");)
IF_LOUD(DbgPrint("NPF: Failed to allocate packet pool\n");)
ExFreePool(Open);
ExFreePool(EvName);
@ -160,6 +152,7 @@ PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
//Create the string containing the name of the read event
RtlInitUnicodeString(&Open->ReadEventName,(PCWSTR) EvName);
PacketItoa(NamedEventsCounter,(PUCHAR)(Open->ReadEventName.Buffer+21));
InterlockedIncrement(&NamedEventsCounter);
@ -170,6 +163,7 @@ PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Open->ReadEvent=IoCreateNotificationEvent(&Open->ReadEventName,&Open->ReadEventHandle);
if(Open->ReadEvent==NULL){
ExFreePool(Open);
ExFreePool(EvName);
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
@ -179,51 +173,58 @@ PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
KeClearEvent(Open->ReadEvent);
NdisInitializeEvent(&Open->WriteEvent);
NdisInitializeEvent(&Open->IOEvent);
NdisInitializeEvent(&Open->DumpEvent);
NdisInitializeEvent(&Open->IOEvent);
NdisAllocateSpinLock(&Open->machine_lock);
//
// list to hold irp's want to reset the adapter
//
InitializeListHead(&Open->ResetIrpList);
//
// Initialize list for holding pending read requests
//
KeInitializeSpinLock(&Open->RcvQSpinLock);
InitializeListHead(&Open->RcvList);
//
// Initialize the request list
//
KeInitializeSpinLock(&Open->RequestSpinLock);
InitializeListHead(&Open->RequestList);
// Initializes the extended memory of the NPF machine
Open->mem_ex.buffer = ExAllocatePoolWithTag(NonPagedPool, DEFAULT_MEM_EX_SIZE, '2OWA');
if((Open->mem_ex.buffer) == NULL)
{
// no memory
ExFreePool(Open);
ExFreePool(EvName);
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_INSUFFICIENT_RESOURCES;
}
Open->mem_ex.size = DEFAULT_MEM_EX_SIZE;
RtlZeroMemory(Open->mem_ex.buffer, DEFAULT_MEM_EX_SIZE);
// get the absolute value of the system boot time.
PTime=KeQueryPerformanceCounter(&TimeFreq);
KeQuerySystemTime(&SystemTime);
#ifndef __NTDRIVER__ // robert
Open->StartTime.QuadPart=(((SystemTime.QuadPart)%10000000)*TimeFreq.QuadPart)/10000000;
SystemTime.QuadPart=SystemTime.QuadPart/10000000-11644473600;
#endif
Open->StartTime.QuadPart+=(SystemTime.QuadPart)*TimeFreq.QuadPart-PTime.QuadPart;
//initalize the open instance
Open->BufSize=0;
Open->Buffer=NULL;
Open->Bhead=0;
Open->Btail=0;
Open->BLastByte=0;
Open->Dropped=0; //reset the dropped packets counter
Open->Received=0; //reset the received packets counter
Open->bpfprogram=NULL; //reset the filter
Open->mode=MODE_CAPT;
Open->Nbytes.QuadPart=0;
Open->Npackets.QuadPart=0;
Open->Nwrites=1;
Open->Multiple_Write_Counter=0;
Open->MinToCopy=0;
Open->TimeOut.QuadPart=(LONGLONG)1;
Open->Bound=TRUE;
//
// Initialize the open instance
//
Open->BufSize = 0;
Open->Buffer = NULL;
Open->Bhead = 0;
Open->Btail = 0;
Open->BLastByte = 0;
Open->Dropped = 0; //reset the dropped packets counter
Open->Received = 0; //reset the received packets counter
Open->Accepted = 0; //reset the accepted packets counter
Open->bpfprogram = NULL; //reset the filter
Open->mode = MODE_CAPT;
Open->Nbytes.QuadPart = 0;
Open->Npackets.QuadPart = 0;
Open->Nwrites = 1;
Open->Multiple_Write_Counter = 0;
Open->MinToCopy = 0;
Open->TimeOut.QuadPart = (LONGLONG)1;
Open->Bound = TRUE;
Open->DumpFileName.Buffer = NULL;
Open->DumpFileHandle = NULL;
Open->tme.active = TME_NONE_ACTIVE;
Open->DumpLimitReached = FALSE;
//allocate the spinlock for the statistic counters
NdisAllocateSpinLock(&Open->CountersLock);
@ -242,20 +243,19 @@ PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
}
IoMarkIrpPending(Irp);
//
// Try to open the MAC
//
IF_LOUD(DbgPrint("Packet: Openinig the device %ws, BindingContext=%d\n",DeviceExtension->AdapterName.Buffer, Open);)
IF_LOUD(DbgPrint("NPF: Openinig the device %ws, BindingContext=%d\n",DeviceExtension->AdapterName.Buffer, Open);)
NdisOpenAdapter(
&Status,
&ErrorStatus,
&Open->AdapterHandle,
&Medium,
&Open->Medium,
MediumArray,
NUM_NDIS_MEDIA,
DeviceExtension->NdisProtocolHandle,
@ -264,11 +264,11 @@ PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
0,
NULL);
IF_LOUD(DbgPrint("Packet: Opened the device, Status=%x\n",Status);)
IF_LOUD(DbgPrint("NPF: Opened the device, Status=%x\n",Status);)
if (Status != NDIS_STATUS_PENDING)
{
PacketOpenAdapterComplete(Open,Status,NDIS_STATUS_SUCCESS);
NPF_OpenAdapterComplete(Open,Status,NDIS_STATUS_SUCCESS);
}
return(STATUS_PENDING);
@ -276,7 +276,7 @@ PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
//-------------------------------------------------------------------
VOID PacketOpenAdapterComplete(
VOID NPF_OpenAdapterComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status,
IN NDIS_STATUS OpenErrorStatus)
@ -285,7 +285,7 @@ VOID PacketOpenAdapterComplete(
PIRP Irp;
POPEN_INSTANCE Open;
IF_LOUD(DbgPrint("Packet: OpenAdapterComplete\n");)
IF_LOUD(DbgPrint("NPF: OpenAdapterComplete\n");)
Open= (POPEN_INSTANCE)ProtocolBindingContext;
@ -296,14 +296,29 @@ VOID PacketOpenAdapterComplete(
if (Status != NDIS_STATUS_SUCCESS) {
IF_LOUD(DbgPrint("Packet: OpenAdapterComplete-FAILURE\n");)
IF_LOUD(DbgPrint("NPF: OpenAdapterComplete-FAILURE\n");)
NdisFreePacketPool(Open->PacketPool);
//free mem_ex
Open->mem_ex.size = 0;
if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer);
ExFreePool(Open->ReadEventName.Buffer);
ExFreePool(Open);
}
else {
NdisAcquireSpinLock(&Opened_Instances_Lock);
n_Opened_Instances++;
NdisReleaseSpinLock(&Opened_Instances_Lock);
IF_LOUD(DbgPrint("Opened Instances:%d", n_Opened_Instances);)
// Get the absolute value of the system boot time.
// This is used for timestamp conversion.
TIME_SYNCHRONIZE(&G_Start_Time);
}
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
@ -315,34 +330,50 @@ VOID PacketOpenAdapterComplete(
//-------------------------------------------------------------------
NTSTATUS STDCALL
PacketClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
NTSTATUS
NPF_Close(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
{
POPEN_INSTANCE Open;
NDIS_STATUS Status;
PIO_STACK_LOCATION IrpSp;
LARGE_INTEGER ThreadDelay;
IF_LOUD(DbgPrint("Packet: CloseAdapter\n");)
IF_LOUD(DbgPrint("NPF: CloseAdapter\n");)
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Open=IrpSp->FileObject->FsContext;
// Reset the buffer size. This tells the dump thread to stop.
Open->BufSize = 0;
if( Open->Bound == FALSE){
NdisWaitEvent(&Open->IOEvent,10000);
//free the bpf program
if(Open->bpfprogram!=NULL)ExFreePool(Open->bpfprogram);
// Free the filter if it's present
if(Open->bpfprogram != NULL)
ExFreePool(Open->bpfprogram);
// Free the jitted filter if it's present
if(Open->Filter != NULL)
BPF_Destroy_JIT_Filter(Open->Filter);
//free the buffer
Open->BufSize=0;
if(Open->Buffer!=NULL)ExFreePool(Open->Buffer);
if(Open->Buffer != NULL)ExFreePool(Open->Buffer);
NdisFreePacketPool(Open->PacketPool);
//free mem_ex
Open->mem_ex.size = 0;
if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer);
NdisFreePacketPool(Open->PacketPool);
// Free the string with the name of the dump file
if(Open->DumpFileName.Buffer!=NULL)
ExFreePool(Open->DumpFileName.Buffer);
ExFreePool(Open->ReadEventName.Buffer);
ExFreePool(Open);
@ -353,26 +384,50 @@ PacketClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
return(STATUS_SUCCESS);
}
// Eventually unfreeze PacketRead
KeSetEvent(Open->ReadEvent,0,FALSE);
// Unfreeze the consumer
if(Open->mode & MODE_DUMP)
NdisSetEvent(&Open->DumpEvent);
else
KeSetEvent(Open->ReadEvent,0,FALSE);
// Save the IRP
Open->OpenCloseIrp = Irp;
IoMarkIrpPending(Irp);
// If this instance is in dump mode, complete the dump and close the file
if((Open->mode & MODE_DUMP) && Open->DumpFileHandle != NULL){
#ifndef __GNUC__
NTSTATUS wres;
ThreadDelay.QuadPart = -50000000;
// Wait the completion of the thread
wres = KeWaitForSingleObject(Open->DumpThreadObject,
UserRequest,
KernelMode,
TRUE,
&ThreadDelay);
ObDereferenceObject(Open->DumpThreadObject);
// Flush and close the dump file
NPF_CloseDumpFile(Open);
#endif
}
// Destroy the read Event
ZwClose(Open->ReadEventHandle);
// save the IRP
Open->OpenCloseIrp=Irp;
IoMarkIrpPending(Irp);
// close the adapter
// Close the adapter
NdisCloseAdapter(
&Status,
Open->AdapterHandle
);
if (Status != NDIS_STATUS_PENDING) {
PacketCloseAdapterComplete(
NPF_CloseAdapterComplete(
Open,
Status
);
@ -386,29 +441,42 @@ PacketClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
//-------------------------------------------------------------------
VOID
PacketCloseAdapterComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status)
NPF_CloseAdapterComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status)
{
POPEN_INSTANCE Open;
PIRP Irp;
IF_LOUD(DbgPrint("Packet: CloseAdapterComplete\n");)
IF_LOUD(DbgPrint("NPF: CloseAdapterComplete\n");)
Open= (POPEN_INSTANCE)ProtocolBindingContext;
// free the allocated structures only if the instance is still bound to the adapter
if(Open->Bound == TRUE){
//free the bpf program
if(Open->bpfprogram!=NULL)ExFreePool(Open->bpfprogram);
// Free the filter if it's present
if(Open->bpfprogram != NULL)
ExFreePool(Open->bpfprogram);
// Free the jitted filter if it's present
if(Open->Filter != NULL)
BPF_Destroy_JIT_Filter(Open->Filter);
//free the buffer
Open->BufSize=0;
Open->BufSize = 0;
if(Open->Buffer!=NULL)ExFreePool(Open->Buffer);
//free mem_ex
Open->mem_ex.size = 0;
if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer);
NdisFreePacketPool(Open->PacketPool);
Irp=Open->OpenCloseIrp;
// Free the string with the name of the dump file
if(Open->DumpFileName.Buffer!=NULL)
ExFreePool(Open->DumpFileName.Buffer);
ExFreePool(Open->ReadEventName.Buffer);
ExFreePool(Open);
@ -420,15 +488,42 @@ PacketCloseAdapterComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS
else
NdisSetEvent(&Open->IOEvent);
// Decrease the counter of open instances
NdisAcquireSpinLock(&Opened_Instances_Lock);
n_Opened_Instances--;
NdisReleaseSpinLock(&Opened_Instances_Lock);
IF_LOUD(DbgPrint("Opened Instances:%d", n_Opened_Instances);)
if(n_Opened_Instances == 0){
// Force a synchronization at the next NPF_Open().
// This hopefully avoids the synchronization issues caused by hibernation or standby.
TIME_DESYNCHRONIZE(&G_Start_Time);
}
return;
}
//-------------------------------------------------------------------
#ifdef NDIS50
NDIS_STATUS
NPF_PowerChange(IN NDIS_HANDLE ProtocolBindingContext, IN PNET_PNP_EVENT pNetPnPEvent)
{
IF_LOUD(DbgPrint("NPF: PowerChange\n");)
TIME_DESYNCHRONIZE(&G_Start_Time);
TIME_SYNCHRONIZE(&G_Start_Time);
return STATUS_SUCCESS;
}
#endif
//-------------------------------------------------------------------
VOID
PacketBindAdapter(
NPF_BindAdapter(
OUT PNDIS_STATUS Status,
IN NDIS_HANDLE BindContext,
IN PNDIS_STRING DeviceName,
@ -436,13 +531,13 @@ PacketBindAdapter(
IN PVOID SystemSpecific2
)
{
IF_LOUD(DbgPrint("Packet: PacketBindAdapter\n");)
IF_LOUD(DbgPrint("NPF: NPF_BindAdapter\n");)
}
//-------------------------------------------------------------------
VOID
PacketUnbindAdapter(
NPF_UnbindAdapter(
OUT PNDIS_STATUS Status,
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_HANDLE UnbindContext
@ -451,7 +546,10 @@ PacketUnbindAdapter(
POPEN_INSTANCE Open =(POPEN_INSTANCE)ProtocolBindingContext;
NDIS_STATUS lStatus;
IF_LOUD(DbgPrint("Packet: PacketUNBindAdapter\n");)
IF_LOUD(DbgPrint("NPF: NPF_UnbindAdapter\n");)
// Reset the buffer size. This tells the dump thread to stop.
Open->BufSize=0;
NdisResetEvent(&Open->IOEvent);
@ -459,7 +557,14 @@ PacketUnbindAdapter(
InterlockedExchange( (PLONG) &Open->Bound, FALSE );
// Awake a possible pending read on this instance
KeSetEvent(Open->ReadEvent,0,FALSE);
if(Open->mode & MODE_DUMP)
NdisSetEvent(&Open->DumpEvent);
else
KeSetEvent(Open->ReadEvent,0,FALSE);
// If this instance is in dump mode, complete the dump and close the file
if((Open->mode & MODE_DUMP) && Open->DumpFileHandle != NULL)
NPF_CloseDumpFile(Open);
// Destroy the read Event
ZwClose(Open->ReadEventHandle);
@ -472,7 +577,7 @@ PacketUnbindAdapter(
if (lStatus != NDIS_STATUS_PENDING) {
PacketCloseAdapterComplete(
NPF_CloseAdapterComplete(
Open,
lStatus
);
@ -489,7 +594,7 @@ PacketUnbindAdapter(
//-------------------------------------------------------------------
VOID
PacketResetComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status)
NPF_ResetComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status)
{
POPEN_INSTANCE Open;
@ -497,7 +602,7 @@ PacketResetComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Statu
PLIST_ENTRY ResetListEntry;
IF_LOUD(DbgPrint("Packet: PacketResetComplte\n");)
IF_LOUD(DbgPrint("NPF: PacketResetComplte\n");)
Open= (POPEN_INSTANCE)ProtocolBindingContext;
@ -522,7 +627,7 @@ PacketResetComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Statu
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
IF_LOUD(DbgPrint("Packet: PacketResetComplte exit\n");)
IF_LOUD(DbgPrint("NPF: PacketResetComplte exit\n");)
return;

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -6,8 +6,8 @@
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 2,3,0,33
PRODUCTVERSION 2,3,0,33
FILEVERSION 3,0,0,13
PRODUCTVERSION 3,0,0,13
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -24,16 +24,16 @@ BEGIN
BEGIN
VALUE "Comments", "Netgroup Packet Filter Driver\0"
VALUE "CompanyName", "Politecnico di Torino\0"
VALUE "FileDescription", "NPF Driver\0"
VALUE "FileVersion", "2, 3, 0, 33\0"
VALUE "InternalName", "NPF\0"
VALUE "FileDescription", "NPF Driver - TME extensions\0"
VALUE "FileVersion", "3, 0, 0, 13\0"
VALUE "InternalName", "NPF + TME \0"
VALUE "LegalCopyright", "Copyright © 2002\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "NPF.RC\0"
VALUE "PrivateBuild", "\0"
VALUE "PrivateBuild", "REACTOS PRIVATE BUILD\0"
VALUE "ProductName", "NPF Driver\0"
VALUE "ProductVersion", "2, 3, 0, 33\0"
VALUE "SpecialBuild", "\0"
VALUE "ProductVersion", "3, 0, 0, 13\0"
VALUE "SpecialBuild", "Beta testing use only\0"
END
END
BLOCK "VarFileInfo"

View file

@ -26,13 +26,17 @@
#include <ndis.h>
#else
#include <ddk/ntddk.h>
//#include <net/miniport.h>
#include <net/ndis.h>
#endif
#include "debug.h"
#include "packet.h"
#include "win_bpf.h"
#include "tme.h"
#include "time_calls.h"
extern struct time_conv G_Start_Time; // from openclos.c
//-------------------------------------------------------------------
@ -80,11 +84,10 @@ UINT n,i,NBlocks;
*Bhead+=n;
}
//-------------------------------------------------------------------
NTSTATUS STDCALL
PacketRead(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
NTSTATUS
NPF_Read(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
{
POPEN_INSTANCE Open;
PIO_STACK_LOCATION IrpSp;
@ -101,51 +104,57 @@ PacketRead(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
LARGE_INTEGER TimeFreq;
struct bpf_hdr *header;
KIRQL Irql;
PUCHAR UserPointer;
ULONG bytecopy;
IF_LOUD(DbgPrint("Packet: Read\n");)
IF_LOUD(DbgPrint("NPF: Read\n");)
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Open=IrpSp->FileObject->FsContext;
if( Open->Bound == FALSE){
// The Network adapter was removed. Return immediately with a failure status
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(STATUS_UNSUCCESSFUL);
if( Open->Bound == FALSE ){
// The Network adapter was removed.
EXIT_FAILURE(0);
}
if( Open->mode & MODE_DUMP && Open->DumpFileHandle == NULL ){
// this instance is in dump mode, but the dump file has still not been opened
EXIT_FAILURE(0);
}
//See if the buffer is full enough to be copied
if (GetBuffOccupation(Open)<=Open->MinToCopy)
if( GetBuffOccupation(Open) <= Open->MinToCopy || Open->mode & MODE_DUMP )
{
//there are not enough buffered packets: the application must wait
//wait until some packets arrive or the timeout expires
if(Open->TimeOut.QuadPart != (LONGLONG)IMMEDIATE)
KeWaitForSingleObject(Open->ReadEvent,
UserRequest,
KernelMode,
TRUE ,
TRUE,
(Open->TimeOut.QuadPart == (LONGLONG)0)? NULL: &(Open->TimeOut));
KeClearEvent(Open->ReadEvent);
if(Open->mode==MODE_STAT){ //this capture instance is in statistics mode
if(Open->mode & MODE_STAT){ //this capture instance is in statistics mode
CurrBuff=(PUCHAR)MmGetSystemAddressForMdl(Irp->MdlAddress);
//get the timestamp
CapTime=KeQueryPerformanceCounter(&TimeFreq);
//fill the bpf header for this packet
CapTime.QuadPart+=Open->StartTime.QuadPart;
header=(struct bpf_hdr*)CurrBuff;
#ifndef __NTDRIVER__ // robert
header->bh_tstamp.tv_usec=(long)((CapTime.QuadPart%TimeFreq.QuadPart*1000000)/TimeFreq.QuadPart);
header->bh_tstamp.tv_sec=(long)(CapTime.QuadPart/TimeFreq.QuadPart);
#endif
header->bh_caplen=16;
header->bh_datalen=16;
header->bh_hdrlen=sizeof(struct bpf_hdr);
GET_TIME(&header->bh_tstamp,&G_Start_Time);
if(Open->mode & MODE_DUMP){
*(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr)+16)=Open->DumpOffset.QuadPart;
header->bh_caplen=24;
header->bh_datalen=24;
Irp->IoStatus.Information = 24 + sizeof(struct bpf_hdr);
}
else{
header->bh_caplen=16;
header->bh_datalen=16;
header->bh_hdrlen=sizeof(struct bpf_hdr);
Irp->IoStatus.Information = 16 + sizeof(struct bpf_hdr);
}
*(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr))=Open->Npackets.QuadPart;
*(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr)+8)=Open->Nbytes.QuadPart;
@ -155,21 +164,78 @@ PacketRead(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
Open->Nbytes.QuadPart=0;
NdisReleaseSpinLock( &Open->CountersLock );
Irp->IoStatus.Information = 16 + sizeof(struct bpf_hdr);
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
if (Open->Bhead == Open->Btail)
//the timeout has expired, but the buffer is still empty.
//we must awake the application returning an empty buffer.
if(Open->mode==MODE_MON) //this capture instance is in monitor mode
{
PTME_DATA data;
ULONG cnt;
ULONG block_size;
PUCHAR tmp;
UserPointer=MmGetSystemAddressForMdl(Irp->MdlAddress);
if ((!IS_VALIDATED(Open->tme.validated_blocks,Open->tme.active_read))||(IrpSp->Parameters.Read.Length<sizeof(struct bpf_hdr)))
{
EXIT_FAILURE(0);
}
header=(struct bpf_hdr*)UserPointer;
GET_TIME(&header->bh_tstamp,&G_Start_Time);
header->bh_hdrlen=sizeof(struct bpf_hdr);
//moves user memory pointer
UserPointer+=sizeof(struct bpf_hdr);
//calculus of data to be copied
//if the user buffer is smaller than data to be copied,
//only some data will be copied
data=&Open->tme.block_data[Open->tme.active_read];
if (data->last_read.tv_sec!=0)
data->last_read=header->bh_tstamp;
bytecopy=data->block_size*data->filled_blocks;
if ((IrpSp->Parameters.Read.Length-sizeof(struct bpf_hdr))<bytecopy)
bytecopy=(IrpSp->Parameters.Read.Length-sizeof(struct bpf_hdr))/ data->block_size;
else
bytecopy=data->filled_blocks;
tmp=data->shared_memory_base_address;
block_size=data->block_size;
for (cnt=0;cnt<bytecopy;cnt++)
{
NdisAcquireSpinLock(&Open->machine_lock);
RtlCopyMemory(UserPointer,tmp,block_size);
NdisReleaseSpinLock(&Open->machine_lock);
tmp+=block_size;
UserPointer+=block_size;
}
bytecopy*=block_size;
header->bh_caplen=bytecopy;
header->bh_datalen=header->bh_caplen;
EXIT_SUCCESS(bytecopy+sizeof(struct bpf_hdr));
}
if (Open->Bhead == Open->Btail || Open->mode & MODE_DUMP)
// The timeout has expired, but the buffer is still empty (or the packets must be written to file).
// We must awake the application, returning an empty buffer.
{
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(STATUS_SUCCESS);
EXIT_SUCCESS(0);
}
}
@ -179,66 +245,61 @@ PacketRead(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
//
NdisAcquireSpinLock( &Open->BufLock );
Thead=Open->Bhead;
Ttail=Open->Btail;
TLastByte=Open->BLastByte;
Thead = Open->Bhead;
Ttail = Open->Btail;
TLastByte = Open->BLastByte;
//get the address of the buffer
CurrBuff=Open->Buffer;
NdisReleaseSpinLock( &Open->BufLock );
Input_Buffer_Length=IrpSp->Parameters.Read.Length;
packp=(PUCHAR)MmGetMdlVirtualAddress(Irp->MdlAddress);
//
//fill the application buffer
//
if(Ttail>Thead){ //first of all see if it we can copy all the buffer in one time
if(Ttail > Thead){ //first of all see if it we can copy all the buffer in one time
if((Ttail-Thead)<Input_Buffer_Length){
KeResetEvent(Open->ReadEvent);
PacketMoveMem(packp,CurrBuff+Thead,Ttail-Thead,&(Open->Bhead));
Irp->IoStatus.Information = Ttail-Thead;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(STATUS_SUCCESS);
EXIT_SUCCESS(Ttail-Thead);
}
}
else if((TLastByte-Thead)<Input_Buffer_Length){
PacketMoveMem(packp,CurrBuff+Thead,TLastByte-Thead,&(Open->Bhead));
else if((TLastByte - Thead) < Input_Buffer_Length){
PacketMoveMem(packp, CurrBuff+Thead, TLastByte - Thead, &(Open->Bhead));
NdisAcquireSpinLock( &Open->BufLock );
Open->BLastByte=Open->Btail;
Open->Bhead=0;
Open->BLastByte = Open->Btail;
Open->Bhead = 0;
NdisReleaseSpinLock( &Open->BufLock );
Irp->IoStatus.Information = TLastByte-Thead;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(STATUS_SUCCESS);
EXIT_SUCCESS(TLastByte-Thead);
}
//the buffer must be scannned to determine the number of bytes to copy
i=0;
CpStart=Thead;
i=0;
while(TRUE){
if(Thead==Ttail)break;
if(Thead == Ttail)break;
if(Thead==TLastByte){
if(Thead == TLastByte){
// Copy the portion between thead and TLastByte
PacketMoveMem(packp,CurrBuff+CpStart,Thead-CpStart,&(Open->Bhead));
packp+=(Thead-CpStart);
NdisAcquireSpinLock( &Open->BufLock );
Open->BLastByte=Open->Btail;
Open->Bhead=0;
Open->BLastByte = Open->Btail;
Open->Bhead = 0;
NdisReleaseSpinLock( &Open->BufLock );
Thead=0;
CpStart=0;
}
@ -247,11 +308,7 @@ PacketRead(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
if((i+cplen > Input_Buffer_Length)){//no more space in the application's buffer
PacketMoveMem(packp,CurrBuff+CpStart,Thead-CpStart,&(Open->Bhead));
Irp->IoStatus.Information = i;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(STATUS_SUCCESS);
EXIT_SUCCESS(i);
}
cplen=Packet_WORDALIGN(cplen);
i+=cplen;
@ -265,17 +322,13 @@ PacketRead(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
Open->Bhead=Thead;
Irp->IoStatus.Information = i;
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return(STATUS_SUCCESS);
EXIT_SUCCESS(i);
}
//-------------------------------------------------------------------
NDIS_STATUS Packet_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE MacReceiveContext,
NDIS_STATUS NPF_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE MacReceiveContext,
IN PVOID HeaderBuffer,IN UINT HeaderBufferSize,IN PVOID LookAheadBuffer,
IN UINT LookaheadBufferSize,IN UINT PacketSize)
{
@ -285,7 +338,6 @@ NDIS_STATUS Packet_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE Mac
NDIS_STATUS Status;
UINT BytesTransfered;
ULONG BufferLength;
PPACKET_RESERVED Reserved;
PMDL pMdl;
LARGE_INTEGER CapTime;
LARGE_INTEGER TimeFreq;
@ -296,13 +348,26 @@ NDIS_STATUS Packet_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE Mac
UINT TLastByte;
UINT fres;
UINT maxbufspace;
USHORT NPFHdrSize;
UINT BufOccupation;
IF_LOUD(DbgPrint("Packet: tap\n");)
IF_VERY_LOUD(DbgPrint("NPF: tap\n");)
Open= (POPEN_INSTANCE)ProtocolBindingContext;
Open->Received++; //number of packets received by filter ++
Open->Received++; // Number of packets received by filter ++
BufOccupation = GetBuffOccupation(Open); // Get the full buffer space
if(((Open->mode&MODE_CAPT)||(Open->mode&MODE_DUMP)) && Open->BufSize - BufOccupation < PacketSize+HeaderBufferSize+sizeof(struct bpf_hdr)){
// Heuristic that drops the packet also if it possibly fits in the buffer.
// It allows to avoid filtering in critical situations when CPU is very important.
Open->Dropped++;
return NDIS_STATUS_NOT_ACCEPTED;
}
NdisAcquireSpinLock(&Open->machine_lock);
//
//Check if the lookahead buffer follows the mac header.
//If the data follow the header (i.e. there is only a buffer) a normal bpf_filter() is
@ -316,24 +381,64 @@ NDIS_STATUS Packet_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE Mac
LookAheadBuffer,
HeaderBufferSize,
PacketSize+HeaderBufferSize,
LookaheadBufferSize+HeaderBufferSize);
else
fres=bpf_filter((struct bpf_insn*)(Open->bpfprogram),
HeaderBuffer,
PacketSize+HeaderBufferSize,
LookaheadBufferSize+HeaderBufferSize);
LookaheadBufferSize+HeaderBufferSize,
&Open->mem_ex,
&Open->tme,
&G_Start_Time);
else
if(Open->Filter != NULL)
{
if (Open->bpfprogram != NULL)
{
fres=Open->Filter->Function(HeaderBuffer,
PacketSize+HeaderBufferSize,
LookaheadBufferSize+HeaderBufferSize);
// Restore the stack.
// I ignore the reason, but this instruction is needed only at kernel level
#ifndef __GNUC__
_asm add esp,12
#else
#endif
}
else
fres = -1;
}
else
fres=bpf_filter((struct bpf_insn*)(Open->bpfprogram),
HeaderBuffer,
PacketSize+HeaderBufferSize,
LookaheadBufferSize+HeaderBufferSize,
&Open->mem_ex,
&Open->tme,
&G_Start_Time);
NdisReleaseSpinLock(&Open->machine_lock);
if(Open->mode==MODE_MON)
// we are in monitor mode
{
if (fres==1)
KeSetEvent(Open->ReadEvent,0,FALSE);
return NDIS_STATUS_NOT_ACCEPTED;
}
if(fres==0)
// Packet not accepted by the filter, ignore it.
return NDIS_STATUS_NOT_ACCEPTED;
if(fres==0)return NDIS_STATUS_NOT_ACCEPTED; //packet not accepted by the filter
//if the filter returns -1 the whole packet must be accepted
if(fres==-1 || fres > PacketSize+HeaderBufferSize)fres=PacketSize+HeaderBufferSize;
if(Open->mode==MODE_STAT){
if(Open->mode & MODE_STAT){
// we are in statistics mode
NdisAcquireSpinLock( &Open->CountersLock );
Open->Npackets.QuadPart++;
if(PacketSize+HeaderBufferSize<60)
Open->Nbytes.QuadPart+=60;
else
@ -343,32 +448,42 @@ NDIS_STATUS Packet_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE Mac
Open->Nbytes.QuadPart+=12;
NdisReleaseSpinLock( &Open->CountersLock );
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;
}
if(Open->BufSize==0)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;
TLastByte = Open->BLastByte;
NdisReleaseSpinLock( &Open->BufLock );
maxbufspace=Packet_WORDALIGN(fres+sizeof(struct bpf_hdr));
if((Ttail < Thead) && (Ttail+maxbufspace+1 >= Thead))
{
//the buffer is full: the incoming packet is lost
Open->Dropped++;
return NDIS_STATUS_NOT_ACCEPTED;
}
maxbufspace=Packet_WORDALIGN(fres+NPFHdrSize);
if(Ttail+maxbufspace >= Open->BufSize){
if(Thead<=maxbufspace)
if(Thead <= maxbufspace)
{
//the buffer is full: the packet is lost
Open->Dropped++;
return NDIS_STATUS_NOT_ACCEPTED;
}
@ -378,97 +493,135 @@ NDIS_STATUS Packet_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE Mac
}
CurrBuff=Open->Buffer+Ttail;
// Allocate an MDL to map the portion of the buffer following the
// header
pMdl=IoAllocateMdl(CurrBuff+HeaderBufferSize+LookaheadBufferSize+sizeof(struct bpf_hdr),maxbufspace,FALSE,FALSE,NULL);
if (pMdl == NULL)
if(LookaheadBufferSize != PacketSize || (UINT)LookAheadBuffer-(UINT)HeaderBuffer != HeaderBufferSize)
{
//no memory: packet lost
IF_LOUD(DbgPrint("Packet: Read-Failed to allocate Mdl\n");)
Open->Dropped++;
return NDIS_STATUS_NOT_ACCEPTED;
}
MmBuildMdlForNonPagedPool(pMdl);
//allocate the packet from NDIS
NdisAllocatePacket(&Status,&pPacketb,Open->PacketPool);
if (Status != NDIS_STATUS_SUCCESS)
{
IF_LOUD(DbgPrint("Packet: Read- No free packets\n");)
// Allocate an MDL to map the portion of the buffer following the header
pMdl=IoAllocateMdl(CurrBuff+HeaderBufferSize+LookaheadBufferSize+NPFHdrSize,
maxbufspace,
FALSE,
FALSE,
NULL);
if (pMdl == NULL)
{
// Unable to map the memory: packet lost
IF_LOUD(DbgPrint("NPF: Read-Failed to allocate Mdl\n");)
Open->Dropped++;
return NDIS_STATUS_NOT_ACCEPTED;
}
MmBuildMdlForNonPagedPool(pMdl);
//allocate the packet from NDIS
NdisAllocatePacket(&Status, &pPacketb, Open->PacketPool);
if (Status != NDIS_STATUS_SUCCESS)
{
IF_LOUD(DbgPrint("NPF: Tap - No free packets\n");)
IoFreeMdl(pMdl);
Open->Dropped++;
return NDIS_STATUS_NOT_ACCEPTED;
}
//link the buffer to the packet
NdisChainBufferAtFront(pPacketb,pMdl);
Open->Dropped++;
return NDIS_STATUS_NOT_ACCEPTED;
}
//link the buffer to the packet
NdisChainBufferAtFront(pPacketb,pMdl);
//Find out how much to transfer
SizeToTransfer = fres-HeaderBufferSize;
//copy the ethernet header into buffer
NdisMoveMappedMemory((CurrBuff)+sizeof(struct bpf_hdr),HeaderBuffer,HeaderBufferSize);
//Copy the look ahead buffer
if(LookaheadBufferSize)
{
NdisMoveMappedMemory((CurrBuff)+sizeof(struct bpf_hdr) + HeaderBufferSize,
LookAheadBuffer,
(SizeToTransfer < LookaheadBufferSize)? SizeToTransfer : LookaheadBufferSize );
BufferLength=fres-HeaderBufferSize;
//Find out how much to transfer
SizeToTransfer = (PacketSize < BufferLength) ? PacketSize : BufferLength;
//copy the ethernet header into buffer
NdisMoveMappedMemory((CurrBuff)+NPFHdrSize,HeaderBuffer,HeaderBufferSize);
//Copy the look ahead buffer
if(LookaheadBufferSize)
{
NdisMoveMappedMemory((CurrBuff) + NPFHdrSize + HeaderBufferSize,
LookAheadBuffer,
(SizeToTransfer < LookaheadBufferSize)? SizeToTransfer : LookaheadBufferSize );
SizeToTransfer = (SizeToTransfer > LookaheadBufferSize)?
SizeToTransfer - LookaheadBufferSize : 0;
}
Open->TransferMdl=pMdl;
if(SizeToTransfer)
{
//Call the Mac to transfer the packet
NdisTransferData(&Status,
Open->AdapterHandle,
MacReceiveContext,
LookaheadBufferSize,
SizeToTransfer,
pPacketb,
&BytesTransfered);
}
else{
BytesTransfered = 0;
}
SizeToTransfer = (SizeToTransfer > LookaheadBufferSize)?
SizeToTransfer - LookaheadBufferSize : 0;
}
Open->TransferMdl=pMdl;
if(SizeToTransfer)
else
{
//Call the Mac to transfer the packet
NdisTransferData(&Status,
Open->AdapterHandle,
MacReceiveContext,
LookaheadBufferSize,
SizeToTransfer,
pPacketb,
&BytesTransfered);
}
else{
BytesTransfered = 0;
// The whole packet is in the lookahead buffer, we can avoid the call to NdisTransferData.
// This allows us to avoid the allocation of the MDL and the NDIS packet as well
RtlCopyMemory((CurrBuff) + NPFHdrSize,
HeaderBuffer,
HeaderBufferSize + LookaheadBufferSize);
Open->TransferMdl = NULL;
Status = NDIS_STATUS_SUCCESS;
}
Open->Accepted++; // Increase the accepted packets counter
if (Status != NDIS_STATUS_FAILURE)
{
//store the capture time
CapTime=KeQueryPerformanceCounter(&TimeFreq);
if( fres > (BytesTransfered+HeaderBufferSize+LookaheadBufferSize) )
fres = BytesTransfered+HeaderBufferSize+LookaheadBufferSize;
//fill the bpf header for this packet
CapTime.QuadPart+=Open->StartTime.QuadPart;
//
// Build the header
//
header=(struct bpf_hdr*)CurrBuff;
#ifndef __NTDRIVER__ // robert
header->bh_tstamp.tv_usec=(long)((CapTime.QuadPart%TimeFreq.QuadPart*1000000)/TimeFreq.QuadPart);
header->bh_tstamp.tv_sec=(long)(CapTime.QuadPart/TimeFreq.QuadPart);
#endif
header->bh_caplen=fres;
GET_TIME(&header->bh_tstamp,&G_Start_Time);
header->bh_caplen=fres;
header->bh_datalen=PacketSize+HeaderBufferSize;
header->bh_hdrlen=sizeof(struct bpf_hdr);
if(Open->mode==MODE_CAPT){
header->bh_hdrlen=NPFHdrSize;
// Don't align if the packet goes to disk
Ttail+=Packet_WORDALIGN(fres + NPFHdrSize);
}
else
Ttail+=fres+NPFHdrSize;
//update the buffer
Ttail+=Packet_WORDALIGN(fres+sizeof(struct bpf_hdr));
if(Ttail>Thead)TLastByte=Ttail;
if(Ttail > Thead)TLastByte = Ttail;
NdisAcquireSpinLock( &Open->BufLock );
Open->Btail=Ttail;
Open->BLastByte=TLastByte;
NdisReleaseSpinLock( &Open->BufLock );
}
if (Status != NDIS_STATUS_PENDING){
PacketTransferDataComplete(Open,pPacketb,Status,fres);
if( Open->TransferMdl != NULL)
// Complete the request and free the buffers
NPF_TransferDataComplete(Open,pPacketb,Status,fres);
else{
// Unfreeze the consumer
if(GetBuffOccupation(Open)>Open->MinToCopy){
if(Open->mode & MODE_DUMP){
NdisSetEvent(&Open->DumpEvent);
}
else
KeSetEvent(Open->ReadEvent,0,FALSE);
}
}
}
return NDIS_STATUS_SUCCESS;
@ -477,12 +630,12 @@ NDIS_STATUS Packet_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE Mac
//-------------------------------------------------------------------
VOID PacketTransferDataComplete (IN NDIS_HANDLE ProtocolBindingContext,IN PNDIS_PACKET pPacket,
VOID NPF_TransferDataComplete (IN NDIS_HANDLE ProtocolBindingContext,IN PNDIS_PACKET pPacket,
IN NDIS_STATUS Status,IN UINT BytesTransfered)
{
POPEN_INSTANCE Open;
IF_LOUD(DbgPrint("Packet: TransferDataComplete\n");)
IF_LOUD(DbgPrint("NPF: TransferDataComplete\n");)
Open= (POPEN_INSTANCE)ProtocolBindingContext;
@ -491,18 +644,21 @@ VOID PacketTransferDataComplete (IN NDIS_HANDLE ProtocolBindingContext,IN PNDIS_
NdisReinitializePacket(pPacket);
//Put the packet on the free queue
NdisFreePacket(pPacket);
//Unfreeze PacketRead
if(GetBuffOccupation(Open)>Open->MinToCopy)
KeSetEvent(Open->ReadEvent,0,FALSE);
// Unfreeze the consumer
if(GetBuffOccupation(Open)>Open->MinToCopy){
if(Open->mode & MODE_DUMP){
NdisSetEvent(&Open->DumpEvent);
}
else
KeSetEvent(Open->ReadEvent,0,FALSE);
}
return;
}
//-------------------------------------------------------------------
VOID PacketReceiveComplete(IN NDIS_HANDLE ProtocolBindingContext)
VOID NPF_ReceiveComplete(IN NDIS_HANDLE ProtocolBindingContext)
{
IF_LOUD(DbgPrint("Packet: PacketReceiveComplete\n");)
IF_VERY_LOUD(DbgPrint("NPF: NPF_ReceiveComplete\n");)
return;
}

View file

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1,262 @@
/*
* Copyright (c) 2001
* Politecnico di Torino. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the Politecnico
* di Torino, and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef _time_calls
#define _time_calls
#ifdef WIN_NT_DRIVER
#include "debug.h"
/*!
\brief A microsecond precise timestamp.
included in the sf_pkthdr or the bpf_hdr that NPF associates with every packet.
*/
struct timeval {
long tv_sec; ///< seconds
long tv_usec; ///< microseconds
};
#endif /*WIN_NT_DRIVER*/
struct time_conv {
ULONGLONG reference;
struct timeval start;
};
#ifdef __GNUC__
void TIME_DESYNCHRONIZE(struct time_conv *data);
VOID TIME_SYNCHRONIZE(struct time_conv *data);
void FORCE_TIME(struct timeval *src, struct time_conv *dest);
void 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 FORCE_TIME(struct timeval *src, struct time_conv *dest)
{
dest->start=*src;
}
__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;
}
}
#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

@ -0,0 +1,378 @@
/*
* 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

@ -0,0 +1,182 @@
/*
* 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

@ -0,0 +1,73 @@
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

@ -37,7 +37,7 @@
*
* @(#)bpf.h 7.1 (Berkeley) 5/7/91
*
* @(#) $Header: /cygdrive/c/RCVS/CVS/ReactOS/reactos/drivers/net/packet/win_bpf.h,v 1.1 2002/06/19 15:43:15 robd Exp $ (LBL)
* @(#) $Header: /cygdrive/c/RCVS/CVS/ReactOS/reactos/drivers/net/packet/win_bpf.h,v 1.2 2002/09/24 15:16:46 robd Exp $ (LBL)
*/
#ifndef BPF_MAJOR_VERSION
@ -45,37 +45,29 @@
/* BSD style release date */
#define BPF_RELEASE 199606
#ifdef __NTDRIVER__
#define NTKERNEL
#endif
#ifndef NTKERNEL
#include <winsock2.h>
typedef int bpf_int32;
typedef u_int bpf_u_int32;
#else
typedef UCHAR u_char;
typedef USHORT u_short;
typedef UINT u_int;
typedef INT bpf_int32;
typedef UINT bpf_u_int32;
#endif
/*
* Alignment macros. BPF_WORDALIGN rounds up to the next
* even multiple of BPF_ALIGNMENT.
*/
#ifndef __NetBSD__
#define BPF_ALIGNMENT sizeof(bpf_int32)
#else
#define BPF_ALIGNMENT sizeof(long)
#endif
#define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1))
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.
*/
@ -122,14 +114,6 @@ struct bpf_hdr {
u_short bh_hdrlen; /* length of bpf header (this struct
plus alignment padding) */
};
/*
* Because the structure above is not a multiple of 4 bytes, some compilers
* will insist on inserting padding; hence, sizeof(struct bpf_hdr) won't work.
* Only the kernel needs to know about it; applications use bh_hdrlen.
*/
#if defined(KERNEL) || defined(_KERNEL)
#define SIZEOF_BPF_HDR 18
#endif
/*
* Data-link level type codes.
@ -304,15 +288,28 @@ struct bpf_hdr {
#define BPF_TAX 0x00
#define BPF_TXA 0x80
/*
* The instruction data structure.
*/
struct bpf_insn {
u_short code;
u_char jt;
u_char jf;
bpf_int32 k;
};
/* 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.
@ -320,35 +317,6 @@ struct bpf_insn {
#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k }
#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k }
/**
* @}
*/
#if defined(BSD) && (defined(KERNEL) || defined(_KERNEL))
/*
* Systems based on non-BSD kernels don't have ifnet's (or they don't mean
* anything if it is in <net/if.h>) and won't work like this.
*/
# if __STDC__
extern void bpf_tap(struct ifnet *, u_char *, u_int);
extern void bpf_mtap(struct ifnet *, struct mbuf *);
extern void bpfattach(struct ifnet *, u_int, u_int);
extern void bpfilterattach(int);
# else
extern void bpf_tap();
extern void bpf_mtap();
extern void bpfattach();
extern void bpfilterattach();
# endif /* __STDC__ */
#endif /* BSD && (_KERNEL || KERNEL) */
#if __STDC__
extern int bpf_validate(struct bpf_insn *, int);
extern u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int);
#else
extern int bpf_validate();
extern u_int bpf_filter();
#endif
/*
* Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST).
*/

View file

@ -59,35 +59,12 @@
@(#)bpf.c 7.5 (Berkeley) 7/15/91
*/
#if !(defined(lint) || defined(KERNEL))
static const char rcsid[] =
"@(#) $Header: /cygdrive/c/RCVS/CVS/ReactOS/reactos/drivers/net/packet/win_bpf_filter.c,v 1.1 2002/06/19 15:43:15 robd Exp $ (LBL)";
#endif
#ifndef WIN32
#include <sys/param.h>
#include <sys/time.h>
#else
#include <winsock2.h>
#endif
#include <sys/types.h>
#include "tme.h"
#include "win_bpf.h"
#define int32 bpf_int32
#define u_int32 bpf_u_int32
#include "debug.h"
#ifndef LBL_ALIGN
#if defined(sparc) || defined(mips) || defined(ibm032) || \
defined(__alpha) || defined(__hpux)
#define LBL_ALIGN
#endif
#endif
#ifndef LBL_ALIGN
#ifndef WIN32
#include <netinet/in.h>
#endif
#include "valid_insns.h"
#define EXTRACT_SHORT(p)\
((u_short)\
@ -98,29 +75,23 @@ static const char rcsid[] =
(u_int32)*((u_char *)p+1)<<16|\
(u_int32)*((u_char *)p+2)<<8|\
(u_int32)*((u_char *)p+3)<<0)
#endif
/** @ingroup NPF
* @{
*/
/** @defgroup NPF_code NPF functions
* @{
*/
/*
* Execute the filter program starting at pc on the packet p
* wirelen is the length of the original packet
* buflen is the amount of data present
*/
u_int bpf_filter(pc, p, wirelen, buflen)
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)
@ -225,6 +196,57 @@ u_int bpf_filter(pc, p, wirelen, buflen)
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;
@ -233,6 +255,49 @@ u_int bpf_filter(pc, p, wirelen, buflen)
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;
@ -346,30 +411,59 @@ u_int bpf_filter(pc, p, wirelen, buflen)
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 */
}
}
}
//-------------------------------------------------------------------
/*
* Execute the filter program starting at pc on the packet whose header is
* pointed by p and whose data is pointed by pd.
* headersize is the size of the the header
* wirelen is the length of the original packet
* buflen is the amount of data present
*/
u_int bpf_filter_with_2_buffers(pc, p, pd, headersize, wirelen, buflen)
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)
/*
@ -538,6 +632,57 @@ u_int bpf_filter_with_2_buffers(pc, p, pd, headersize, wirelen, buflen)
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;
@ -546,6 +691,52 @@ u_int bpf_filter_with_2_buffers(pc, p, pd, headersize, wirelen, buflen)
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;
@ -659,37 +850,72 @@ u_int bpf_filter_with_2_buffers(pc, p, pd, headersize, wirelen, buflen)
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 */
}
}
}
/*
* Return true if the 'fcode' 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.
* 'valid' is an array for use by the routine (it must be at least
* 'len' bytes long).
*
* The kernel needs to be able to verify an application's filter code.
* Otherwise, a bogus program could easily crash the system.
*/
int
bpf_validate(f, len)
int32
bpf_validate(f, len,mem_ex_size)
struct bpf_insn *f;
int len;
int32 len;
uint32 mem_ex_size;
{
register int i;
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 int from = i + 1;
register int32 from = i + 1;
if (BPF_OP(p->code) == BPF_JA) {
if (from + p->k >= len)
@ -698,14 +924,33 @@ bpf_validate(f, len)
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 ||
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))
(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.
*/
@ -713,4 +958,4 @@ bpf_validate(f, len)
return 0;
}
return BPF_CLASS(f[len - 1].code) == BPF_RET;
}
}

View file

@ -0,0 +1,569 @@
/*
* 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
#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
#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
#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
#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
#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
#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
#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
#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
#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
#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
#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
#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

@ -0,0 +1,31 @@
/*
* 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

@ -26,7 +26,6 @@
#include "ndis.h"
#else
#include <ddk/ntddk.h>
//#include <net/miniport.h>
#include <net/ndis.h>
#endif
@ -34,12 +33,10 @@
#include "packet.h"
int nsent;
//-------------------------------------------------------------------
NTSTATUS STDCALL
PacketWrite(
NTSTATUS
//STDCALL
NPF_Write(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
@ -59,9 +56,7 @@ PacketWrite(
Open=IrpSp->FileObject->FsContext;
//
// Check the length of the packet to avoid to use an empty packet
//
if(IrpSp->Parameters.Write.Length==0)
{
Irp->IoStatus.Status = NDIS_STATUS_SUCCESS;
@ -79,9 +74,7 @@ PacketWrite(
for(i=0;i<Open->Nwrites;i++){
//
// Try to get a packet from our list of free ones
//
NdisAllocatePacket(
&Status,
&pPacket,
@ -90,35 +83,30 @@ PacketWrite(
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
//
PacketSendComplete(
NPF_SendComplete(
Open,
pPacket,
Status
@ -138,50 +126,207 @@ PacketWrite(
//-------------------------------------------------------------------
VOID
PacketSendComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET pPacket,
IN NDIS_STATUS Status
)
INT
NPF_BufferedWrite(
IN PIRP Irp,
IN PCHAR UserBuff,
IN ULONG UserBuffSize,
BOOLEAN Sync)
{
PIRP Irp;
PIO_STACK_LOCATION irpSp;
POPEN_INSTANCE Open;
IF_LOUD(DbgPrint("Packet: SendComplete, BindingContext=%d\n",ProtocolBindingContext);)
Open= (POPEN_INSTANCE)ProtocolBindingContext;
if((Open->Nwrites-Open->Multiple_Write_Counter)%100==99)
NdisSetEvent(&Open->WriteEvent);
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;
Open->Multiple_Write_Counter--;
IF_LOUD(DbgPrint("NPF: BufferedWrite, UserBuff=%x, Size=%u\n", UserBuff, UserBuffSize);)
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Irp=RESERVED(pPacket)->Irp;
irpSp = IoGetCurrentIrpStackLocation(Irp);
Open=IrpSp->FileObject->FsContext;
// Security check on the length of the user buffer
if(UserBuff==0)
{
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 > 65536)
{
// Malformed header
IF_LOUD(DbgPrint("NPF_BufferedWrite: malformed 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 ){
#if 0
// 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;
}
// 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);
#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(Open->Multiple_Write_Counter==0){
//
// wake the application
//
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = irpSp->Parameters.Write.Length;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
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;
return;
}