mirror of
https://github.com/reactos/reactos.git
synced 2025-04-26 16:40:27 +00:00
There's no point in keeping two almost identical packet drivers in the SVN.
svn path=/trunk/; revision=15575
This commit is contained in:
parent
f48663be6d
commit
c5fc491484
35 changed files with 0 additions and 10460 deletions
|
@ -1,36 +0,0 @@
|
|||
# $Id$
|
||||
|
||||
PATH_TO_TOP = ../../..
|
||||
|
||||
#TARGET_TYPE = export_driver
|
||||
TARGET_TYPE = driver
|
||||
|
||||
TARGET_NAME = packet
|
||||
|
||||
#TARGET_CFLAGS = -DDBG -DWIN_NT_DRIVER -DKQPC_TS -I$(PATH_TO_TOP)/ntoskrnl/include
|
||||
|
||||
TARGET_CFLAGS = -DDBG -DWIN_NT_DRIVER -DKQPC_TS -DUSE_KLOCKS -I$(PATH_TO_TOP)/ntoskrnl/include
|
||||
|
||||
TARGET_DDKLIBS = ndis.a
|
||||
|
||||
TARGET_OBJECTS = \
|
||||
packet.o \
|
||||
openclos.o \
|
||||
read.o \
|
||||
write.o \
|
||||
dump.o \
|
||||
jitter.o \
|
||||
win_bpf_filter.o \
|
||||
tme.o \
|
||||
count_packets.o \
|
||||
win_bpf_filter_init.o \
|
||||
tcp_session.o \
|
||||
memory_t.o \
|
||||
time_calls.o \
|
||||
functions.o \
|
||||
bucket_lookup.o \
|
||||
normal_lookup.o
|
||||
|
||||
include $(PATH_TO_TOP)/rules.mak
|
||||
|
||||
include $(TOOLS_PATH)/helper.mk
|
|
@ -1,252 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#include "tme.h"
|
||||
#include "bucket_lookup.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <net/tme/tme.h>
|
||||
#include <net/tme/bucket_lookup.h>
|
||||
#else
|
||||
#include <tme/tme.h>
|
||||
#include <tme/bucket_lookup.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* the key is represented by the initial and final value */
|
||||
/* of the bucket. At the moment bucket_lookup is able to */
|
||||
/* manage values of 16, 32 bits. */
|
||||
uint32 bucket_lookup(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref)
|
||||
{
|
||||
uint32 value;
|
||||
uint32 i,j;
|
||||
int found=-1;
|
||||
uint32 blocks;
|
||||
uint32 block_size;
|
||||
uint8 *temp;
|
||||
if ((data->key_len!=1)&& /*16 bit value*/
|
||||
(data->key_len!=2)) /*32 bit value*/
|
||||
return TME_ERROR;
|
||||
|
||||
/*32 bit values*/
|
||||
blocks=data->filled_blocks-1;
|
||||
block_size=data->block_size;
|
||||
i=blocks/2; /*relative shift*/
|
||||
j=i;
|
||||
temp=data->shared_memory_base_address+block_size;
|
||||
|
||||
if (data->key_len==2)
|
||||
{
|
||||
value=SW_ULONG_AT(key,0);
|
||||
|
||||
if((value<SW_ULONG_AT(temp,0))||(value>SW_ULONG_AT(temp+block_size*(blocks-1),4)))
|
||||
{
|
||||
uint32 *key32=(uint32*) key;
|
||||
key32[0]=key32[1]=0;
|
||||
|
||||
GET_TIME((struct timeval *)(data->shared_memory_base_address+8),time_ref);
|
||||
|
||||
data->last_found=NULL;
|
||||
return TME_FALSE;
|
||||
}
|
||||
|
||||
while(found==-1) /* search routine */
|
||||
{
|
||||
i=(i==1)? 1:i>>1;
|
||||
if (SW_ULONG_AT(temp+block_size*j,0)>value)
|
||||
if (SW_ULONG_AT(temp+block_size*(j-1),4)<value)
|
||||
found=-2;
|
||||
else
|
||||
j-=i;
|
||||
else
|
||||
if (SW_ULONG_AT(temp+block_size*j,4)<value)
|
||||
if (SW_ULONG_AT(temp+block_size*j,0)>value)
|
||||
found=-2;
|
||||
else
|
||||
j+=i;
|
||||
else found=j;
|
||||
}
|
||||
if (found<0)
|
||||
{
|
||||
uint32 *key32=(uint32*) key;
|
||||
key32[0]=key32[1]=0;
|
||||
|
||||
GET_TIME((struct timeval *)(data->shared_memory_base_address+8),time_ref);
|
||||
|
||||
data->last_found=NULL;
|
||||
return TME_FALSE;
|
||||
}
|
||||
|
||||
data->last_found=data->lut_base_address+found*sizeof(RECORD);
|
||||
|
||||
COPY_MEMORY(key,temp+block_size*found,8);
|
||||
|
||||
GET_TIME((struct timeval *)(temp+block_size*found+8),time_ref);
|
||||
|
||||
return TME_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
value=SW_USHORT_AT(key,0);
|
||||
|
||||
if((value<SW_USHORT_AT(temp,0))||(value>SW_USHORT_AT(temp+block_size*(blocks-1),2)))
|
||||
{
|
||||
uint16 *key16=(uint16*) key;
|
||||
key16[0]=key16[1]=0;
|
||||
|
||||
GET_TIME((struct timeval *)(data->shared_memory_base_address+4),time_ref);
|
||||
|
||||
data->last_found=NULL;
|
||||
return TME_FALSE;
|
||||
}
|
||||
|
||||
while(found==-1) /* search routine */
|
||||
{
|
||||
i=(i==1)? 1:i>>1;
|
||||
if (SW_USHORT_AT(temp+block_size*j,0)>value)
|
||||
if (SW_USHORT_AT(temp+block_size*(j-1),2)<value)
|
||||
found=-2;
|
||||
else
|
||||
j-=i;
|
||||
else
|
||||
if (SW_USHORT_AT(temp+block_size*j,2)<value)
|
||||
if (SW_USHORT_AT(temp+block_size*j,0)>value)
|
||||
found=-2;
|
||||
else
|
||||
j+=i;
|
||||
else found=j;
|
||||
}
|
||||
|
||||
if (found<0)
|
||||
{
|
||||
uint16 *key16=(uint16*) key;
|
||||
key16[0]=key16[1]=0;
|
||||
|
||||
GET_TIME((struct timeval *)(data->shared_memory_base_address+4),time_ref);
|
||||
|
||||
data->last_found=NULL;
|
||||
return TME_FALSE;
|
||||
}
|
||||
|
||||
data->last_found=data->lut_base_address+found*sizeof(RECORD);
|
||||
|
||||
GET_TIME((struct timeval *)(temp+block_size*found+4),time_ref);
|
||||
|
||||
COPY_MEMORY(key,temp+block_size*found,4);
|
||||
|
||||
return TME_TRUE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uint32 bucket_lookup_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref)
|
||||
{
|
||||
RECORD *records=(RECORD*)data->lut_base_address;
|
||||
|
||||
if ((data->key_len!=1)&& /*16 bit value*/
|
||||
(data->key_len!=2)) /*32 bit value*/
|
||||
return TME_ERROR;
|
||||
|
||||
if(data->key_len==2)
|
||||
{
|
||||
uint32 start,stop;
|
||||
uint8 *tmp;
|
||||
|
||||
start=SW_ULONG_AT(key,0);
|
||||
stop=SW_ULONG_AT(key,4);
|
||||
|
||||
if (start>stop)
|
||||
return TME_ERROR;
|
||||
if (data->filled_entries>0)
|
||||
{
|
||||
tmp=mem_ex->buffer+SW_ULONG_AT(&records[data->filled_entries-1].block,0);
|
||||
/*check if it is coherent with the previous block*/
|
||||
if (SW_ULONG_AT(tmp,4)>=start)
|
||||
return TME_ERROR;
|
||||
}
|
||||
|
||||
if (data->filled_blocks==data->shared_memory_blocks)
|
||||
return TME_ERROR;
|
||||
|
||||
if (data->filled_entries==data->lut_entries)
|
||||
return TME_ERROR;
|
||||
|
||||
tmp=data->shared_memory_base_address+data->block_size*data->filled_blocks;
|
||||
|
||||
COPY_MEMORY(tmp,key,8);
|
||||
|
||||
SW_ULONG_ASSIGN(&records[data->filled_entries].block,tmp-mem_ex->buffer);
|
||||
SW_ULONG_ASSIGN(&records[data->filled_entries].exec_fcn,data->default_exec);
|
||||
|
||||
GET_TIME((struct timeval *)(tmp+8),time_ref);
|
||||
|
||||
data->filled_blocks++;
|
||||
data->filled_entries++;
|
||||
|
||||
return TME_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16 start,stop;
|
||||
uint8 *tmp;
|
||||
|
||||
start=SW_USHORT_AT(key,0);
|
||||
stop=SW_USHORT_AT(key,2);
|
||||
|
||||
if (start>stop)
|
||||
return TME_ERROR;
|
||||
if (data->filled_entries>0)
|
||||
{
|
||||
tmp=mem_ex->buffer+SW_ULONG_AT(&records[data->filled_entries-1].block,0);
|
||||
/*check if it is coherent with the previous block*/
|
||||
if (SW_USHORT_AT(tmp,2)>=start)
|
||||
return TME_ERROR;
|
||||
}
|
||||
|
||||
if (data->filled_blocks==data->shared_memory_blocks)
|
||||
return TME_ERROR;
|
||||
|
||||
if (data->filled_entries==data->lut_entries)
|
||||
return TME_ERROR;
|
||||
|
||||
tmp=mem_ex->buffer+SW_ULONG_AT(&records[data->filled_entries].block,0);
|
||||
|
||||
COPY_MEMORY(tmp,key,4);
|
||||
|
||||
SW_ULONG_ASSIGN(&records[data->filled_entries].block,tmp-mem_ex->buffer);
|
||||
SW_ULONG_ASSIGN(&records[data->filled_entries].exec_fcn,data->default_exec);
|
||||
|
||||
GET_TIME((struct timeval *)(tmp+4),time_ref);
|
||||
|
||||
data->filled_blocks++;
|
||||
data->filled_entries++;
|
||||
|
||||
return TME_TRUE;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifndef __bucket_lookup
|
||||
#define __bucket_lookup
|
||||
#ifdef WIN32
|
||||
#include "tme.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <net/tme/tme.h>
|
||||
#else
|
||||
#include <tme/tme.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#define BUCKET_LOOKUP_INSERT 0x00000011
|
||||
uint32 bucket_lookup_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);
|
||||
#define BUCKET_LOOKUP 0x00000010
|
||||
uint32 bucket_lookup(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#include "tme.h"
|
||||
#include "count_packets.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <net/tme/tme.h>
|
||||
#include <net/tme/count_packets.h>
|
||||
#else
|
||||
#include <tme/tme.h>
|
||||
#include <tme/count_packets.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
uint32 count_packets(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data)
|
||||
{
|
||||
|
||||
c_p_data *counters=(c_p_data*)(block+data->key_len*4);
|
||||
|
||||
counters->bytes+=pkt_size;
|
||||
counters->packets++;
|
||||
|
||||
return TME_SUCCESS;
|
||||
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifndef __count_packets
|
||||
#define __count_packets
|
||||
|
||||
#ifdef WIN32
|
||||
#include "tme.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <net/tme/tme.h>
|
||||
#else
|
||||
#include <tme/tme.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct __c_p_data
|
||||
{
|
||||
struct timeval timestamp;
|
||||
uint64 packets;
|
||||
uint64 bytes;
|
||||
}
|
||||
c_p_data;
|
||||
|
||||
#define COUNT_PACKETS 0x00000000
|
||||
uint32 count_packets(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2000
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifndef __DEBUG_INCLUDE
|
||||
#define __DEBUG_INCLUDE
|
||||
|
||||
|
||||
#if DBG
|
||||
|
||||
#define IF_PACKETDEBUG(f) if (PacketDebugFlag & (f))
|
||||
extern ULONG PacketDebugFlag;
|
||||
|
||||
#define PACKET_DEBUG_LOUD 0x00000001 // debugging info
|
||||
#define PACKET_DEBUG_VERY_LOUD 0x00000002 // excessive debugging info
|
||||
|
||||
#define PACKET_DEBUG_INIT 0x00000100 // init debugging info
|
||||
|
||||
//
|
||||
// Macro for deciding whether to dump lots of debugging information.
|
||||
//
|
||||
|
||||
#define IF_LOUD(A) IF_PACKETDEBUG( PACKET_DEBUG_LOUD ) { A }
|
||||
#define IF_VERY_LOUD(A) IF_PACKETDEBUG( PACKET_DEBUG_VERY_LOUD ) { A }
|
||||
#define IF_INIT_LOUD(A) IF_PACKETDEBUG( PACKET_DEBUG_INIT ) { A }
|
||||
|
||||
#else
|
||||
|
||||
#define IF_LOUD(A)
|
||||
#define IF_VERY_LOUD(A)
|
||||
#define IF_INIT_LOUD(A)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /*#define __DEBUG_INCLUDE*/
|
|
@ -1,592 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2000
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include "stdarg.h"
|
||||
#include "ntddk.h"
|
||||
#include "ntiologc.h"
|
||||
#include "ndis.h"
|
||||
#else
|
||||
#include <ddk/ntddk.h>
|
||||
#include <net/ndis.h>
|
||||
//#define PsGetCurrentProcess() IoGetCurrentProcess()
|
||||
#ifndef PsGetCurrentThread
|
||||
#define PsGetCurrentThread() ((PETHREAD) (KeGetCurrentThread()))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
#include "packet.h"
|
||||
#include "win_bpf.h"
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
NTSTATUS
|
||||
NPF_OpenDumpFile(POPEN_INSTANCE Open , PUNICODE_STRING fileName, BOOLEAN Append)
|
||||
{
|
||||
NTSTATUS ntStatus;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
PWCHAR PathPrefix;
|
||||
USHORT PathLen;
|
||||
UNICODE_STRING FullFileName;
|
||||
ULONG FullFileNameLength;
|
||||
PDEVICE_OBJECT fsdDevice;
|
||||
|
||||
FILE_STANDARD_INFORMATION StandardInfo;
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: OpenDumpFile.\n");)
|
||||
|
||||
if(fileName->Buffer[0] == L'\\' &&
|
||||
fileName->Buffer[1] == L'?' &&
|
||||
fileName->Buffer[2] == L'?' &&
|
||||
fileName->Buffer[3] == L'\\'
|
||||
){
|
||||
PathLen = 0;
|
||||
}
|
||||
else{
|
||||
PathPrefix = L"\\??\\";
|
||||
PathLen = 8;
|
||||
}
|
||||
|
||||
// Insert the correct path prefix.
|
||||
FullFileNameLength = PathLen + fileName->MaximumLength;
|
||||
|
||||
#define NPF_TAG_FILENAME TAG('0', 'D', 'W', 'A')
|
||||
FullFileName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
|
||||
FullFileNameLength,
|
||||
NPF_TAG_FILENAME);
|
||||
|
||||
if (FullFileName.Buffer == NULL) {
|
||||
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
|
||||
return ntStatus;
|
||||
}
|
||||
|
||||
FullFileName.Length = PathLen;
|
||||
FullFileName.MaximumLength = (USHORT)FullFileNameLength;
|
||||
|
||||
if(PathLen)
|
||||
RtlMoveMemory (FullFileName.Buffer, PathPrefix, PathLen);
|
||||
|
||||
RtlAppendUnicodeStringToString (&FullFileName, fileName);
|
||||
|
||||
IF_LOUD(DbgPrint( "Packet: Attempting to open %wZ\n", &FullFileName);)
|
||||
|
||||
InitializeObjectAttributes ( &ObjectAttributes,
|
||||
&FullFileName,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
NULL,
|
||||
NULL );
|
||||
|
||||
// Create the dump file
|
||||
ntStatus = ZwCreateFile( &Open->DumpFileHandle,
|
||||
SYNCHRONIZE | FILE_WRITE_DATA,
|
||||
&ObjectAttributes,
|
||||
&IoStatus,
|
||||
NULL,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
FILE_SHARE_READ,
|
||||
(Append)?FILE_OPEN_IF:FILE_SUPERSEDE,
|
||||
FILE_SYNCHRONOUS_IO_NONALERT,
|
||||
NULL,
|
||||
0 );
|
||||
|
||||
if ( !NT_SUCCESS( ntStatus ) )
|
||||
{
|
||||
IF_LOUD(DbgPrint("NPF: Error opening file %x\n", ntStatus);)
|
||||
|
||||
ExFreePool(FullFileName.Buffer);
|
||||
Open->DumpFileHandle=NULL;
|
||||
ntStatus = STATUS_NO_SUCH_FILE;
|
||||
return ntStatus;
|
||||
}
|
||||
|
||||
ExFreePool(FullFileName.Buffer);
|
||||
|
||||
ntStatus = ObReferenceObjectByHandle(Open->DumpFileHandle,
|
||||
FILE_WRITE_ACCESS,
|
||||
#ifndef __GNUC__
|
||||
*IoFileObjectType,
|
||||
#else
|
||||
IoFileObjectType,
|
||||
#endif
|
||||
KernelMode,
|
||||
(PVOID)&Open->DumpFileObject,
|
||||
0);
|
||||
|
||||
if ( !NT_SUCCESS( ntStatus ) )
|
||||
{
|
||||
IF_LOUD(DbgPrint("NPF: Error creating file, status=%x\n", ntStatus);)
|
||||
|
||||
ZwClose( Open->DumpFileHandle );
|
||||
Open->DumpFileHandle=NULL;
|
||||
|
||||
ntStatus = STATUS_NO_SUCH_FILE;
|
||||
return ntStatus;
|
||||
}
|
||||
|
||||
fsdDevice = IoGetRelatedDeviceObject(Open->DumpFileObject);
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: Dump: write file created succesfully, status=%d \n",ntStatus);)
|
||||
|
||||
return ntStatus;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
NTSTATUS
|
||||
NPF_StartDump(POPEN_INSTANCE Open)
|
||||
{
|
||||
NTSTATUS ntStatus;
|
||||
struct packet_file_header hdr;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
NDIS_REQUEST pRequest;
|
||||
ULONG MediaType;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: StartDump.\n");)
|
||||
|
||||
// Init the file header
|
||||
hdr.magic = TCPDUMP_MAGIC;
|
||||
hdr.version_major = PCAP_VERSION_MAJOR;
|
||||
hdr.version_minor = PCAP_VERSION_MINOR;
|
||||
hdr.thiszone = 0; /*Currently not set*/
|
||||
hdr.snaplen = 1514;
|
||||
hdr.sigfigs = 0;
|
||||
|
||||
// Detect the medium type
|
||||
switch (Open->Medium){
|
||||
|
||||
case NdisMediumWan:
|
||||
hdr.linktype = DLT_EN10MB;
|
||||
break;
|
||||
|
||||
case NdisMedium802_3:
|
||||
hdr.linktype = DLT_EN10MB;
|
||||
break;
|
||||
|
||||
case NdisMediumFddi:
|
||||
hdr.linktype = DLT_FDDI;
|
||||
break;
|
||||
|
||||
case NdisMedium802_5:
|
||||
hdr.linktype = DLT_IEEE802;
|
||||
break;
|
||||
|
||||
case NdisMediumArcnet878_2:
|
||||
hdr.linktype = DLT_ARCNET;
|
||||
break;
|
||||
|
||||
case NdisMediumAtm:
|
||||
hdr.linktype = DLT_ATM_RFC1483;
|
||||
break;
|
||||
|
||||
default:
|
||||
hdr.linktype = DLT_EN10MB;
|
||||
}
|
||||
|
||||
// Write the header.
|
||||
// We can use ZwWriteFile because we are in the context of the application
|
||||
ntStatus = ZwWriteFile(Open->DumpFileHandle,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&IoStatus,
|
||||
&hdr,
|
||||
sizeof(hdr),
|
||||
NULL,
|
||||
NULL );
|
||||
|
||||
|
||||
if ( !NT_SUCCESS( ntStatus ) )
|
||||
{
|
||||
IF_LOUD(DbgPrint("NPF: Error dumping file %x\n", ntStatus);)
|
||||
|
||||
ZwClose( Open->DumpFileHandle );
|
||||
Open->DumpFileHandle=NULL;
|
||||
|
||||
ntStatus = STATUS_NO_SUCH_FILE;
|
||||
return ntStatus;
|
||||
}
|
||||
|
||||
Open->DumpOffset.QuadPart=24;
|
||||
|
||||
ntStatus = PsCreateSystemThread(&Open->DumpThreadHandle,
|
||||
THREAD_ALL_ACCESS,
|
||||
(ACCESS_MASK)0L,
|
||||
0,
|
||||
0,
|
||||
(PKSTART_ROUTINE)NPF_DumpThread,
|
||||
Open);
|
||||
|
||||
if ( !NT_SUCCESS( ntStatus ) )
|
||||
{
|
||||
IF_LOUD(DbgPrint("NPF: Error creating dump thread, status=%x\n", ntStatus);)
|
||||
|
||||
ZwClose( Open->DumpFileHandle );
|
||||
Open->DumpFileHandle=NULL;
|
||||
|
||||
return ntStatus;
|
||||
}
|
||||
ntStatus = ObReferenceObjectByHandle(Open->DumpThreadHandle,
|
||||
THREAD_ALL_ACCESS,
|
||||
NULL,
|
||||
KernelMode,
|
||||
(VOID **)&Open->DumpThreadObject,
|
||||
0);
|
||||
if ( !NT_SUCCESS( ntStatus ) )
|
||||
{
|
||||
IF_LOUD(DbgPrint("NPF: Error creating dump thread, status=%x\n", ntStatus);)
|
||||
|
||||
ObDereferenceObject(Open->DumpFileObject);
|
||||
ZwClose( Open->DumpFileHandle );
|
||||
Open->DumpFileHandle=NULL;
|
||||
|
||||
return ntStatus;
|
||||
}
|
||||
|
||||
return ntStatus;
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Dump Thread
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
VOID NPF_DumpThread(POPEN_INSTANCE Open)
|
||||
{
|
||||
ULONG FrozenNic;
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: In the work routine. Parameter = 0x%0x\n",Open);)
|
||||
|
||||
while(TRUE){
|
||||
|
||||
// Wait until some packets arrive or the timeout expires
|
||||
NdisWaitEvent(&Open->DumpEvent, 5000);
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: Worker Thread - event signalled\n");)
|
||||
|
||||
if(Open->DumpLimitReached ||
|
||||
Open->BufSize==0){ // BufSize=0 means that this instance was closed, or that the buffer is too
|
||||
// small for any capture. In both cases it is better to end the dump
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: Worker Thread - Exiting happily\n");)
|
||||
IF_LOUD(DbgPrint("Thread: Dumpoffset=%I64d\n",Open->DumpOffset.QuadPart);)
|
||||
|
||||
PsTerminateSystemThread(STATUS_SUCCESS);
|
||||
return;
|
||||
}
|
||||
|
||||
NdisResetEvent(&Open->DumpEvent);
|
||||
|
||||
// Write the content of the buffer to the file
|
||||
if(NPF_SaveCurrentBuffer(Open) != STATUS_SUCCESS){
|
||||
PsTerminateSystemThread(STATUS_SUCCESS);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
NTSTATUS NPF_SaveCurrentBuffer(POPEN_INSTANCE Open)
|
||||
{
|
||||
UINT Thead;
|
||||
UINT Ttail;
|
||||
UINT TLastByte;
|
||||
PUCHAR CurrBuff;
|
||||
NTSTATUS ntStatus;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
PMDL lMdl;
|
||||
UINT SizeToDump;
|
||||
|
||||
|
||||
Thead=Open->Bhead;
|
||||
Ttail=Open->Btail;
|
||||
TLastByte=Open->BLastByte;
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: NPF_SaveCurrentBuffer.\n");)
|
||||
|
||||
// Get the address of the buffer
|
||||
CurrBuff=Open->Buffer;
|
||||
//
|
||||
// Fill the application buffer
|
||||
//
|
||||
if( Ttail < Thead )
|
||||
{
|
||||
if(Open->MaxDumpBytes &&
|
||||
(UINT)Open->DumpOffset.QuadPart + GetBuffOccupation(Open) > Open->MaxDumpBytes)
|
||||
{
|
||||
// Size limit reached
|
||||
UINT PktLen;
|
||||
|
||||
SizeToDump = 0;
|
||||
|
||||
// Scan the buffer to detect the exact amount of data to save
|
||||
while(TRUE){
|
||||
PktLen = ((struct sf_pkthdr*)(CurrBuff + Thead + SizeToDump))->caplen + sizeof(struct sf_pkthdr);
|
||||
|
||||
if((UINT)Open->DumpOffset.QuadPart + SizeToDump + PktLen > Open->MaxDumpBytes)
|
||||
break;
|
||||
|
||||
SizeToDump += PktLen;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
SizeToDump = TLastByte-Thead;
|
||||
|
||||
lMdl=IoAllocateMdl(CurrBuff+Thead, SizeToDump, FALSE, FALSE, NULL);
|
||||
if (lMdl == NULL)
|
||||
{
|
||||
// No memory: stop dump
|
||||
IF_LOUD(DbgPrint("NPF: dump thread: Failed to allocate Mdl\n");)
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
MmBuildMdlForNonPagedPool(lMdl);
|
||||
|
||||
// Write to disk
|
||||
NPF_WriteDumpFile(Open->DumpFileObject,
|
||||
&Open->DumpOffset,
|
||||
SizeToDump,
|
||||
lMdl,
|
||||
&IoStatus);
|
||||
|
||||
IoFreeMdl(lMdl);
|
||||
|
||||
if(!NT_SUCCESS(IoStatus.Status)){
|
||||
// Error
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
if(SizeToDump != TLastByte-Thead){
|
||||
// Size limit reached.
|
||||
Open->DumpLimitReached = TRUE;
|
||||
|
||||
// Awake the application
|
||||
KeSetEvent(Open->ReadEvent,0,FALSE);
|
||||
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
// Update the packet buffer
|
||||
Open->DumpOffset.QuadPart+=(TLastByte-Thead);
|
||||
Open->BLastByte=Ttail;
|
||||
Open->Bhead=0;
|
||||
}
|
||||
|
||||
if( Ttail > Thead ){
|
||||
|
||||
if(Open->MaxDumpBytes &&
|
||||
(UINT)Open->DumpOffset.QuadPart + GetBuffOccupation(Open) > Open->MaxDumpBytes)
|
||||
{
|
||||
// Size limit reached
|
||||
UINT PktLen;
|
||||
|
||||
SizeToDump = 0;
|
||||
|
||||
// Scan the buffer to detect the exact amount of data to save
|
||||
while(Thead + SizeToDump < Ttail){
|
||||
|
||||
PktLen = ((struct sf_pkthdr*)(CurrBuff + Thead + SizeToDump))->caplen + sizeof(struct sf_pkthdr);
|
||||
|
||||
if((UINT)Open->DumpOffset.QuadPart + SizeToDump + PktLen > Open->MaxDumpBytes)
|
||||
break;
|
||||
|
||||
SizeToDump += PktLen;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
SizeToDump = Ttail-Thead;
|
||||
|
||||
lMdl=IoAllocateMdl(CurrBuff+Thead, SizeToDump, FALSE, FALSE, NULL);
|
||||
if (lMdl == NULL)
|
||||
{
|
||||
// No memory: stop dump
|
||||
IF_LOUD(DbgPrint("NPF: dump thread: Failed to allocate Mdl\n");)
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
MmBuildMdlForNonPagedPool(lMdl);
|
||||
|
||||
// Write to disk
|
||||
NPF_WriteDumpFile(Open->DumpFileObject,
|
||||
&Open->DumpOffset,
|
||||
SizeToDump,
|
||||
lMdl,
|
||||
&IoStatus);
|
||||
|
||||
IoFreeMdl(lMdl);
|
||||
|
||||
if(!NT_SUCCESS(IoStatus.Status)){
|
||||
// Error
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
if(SizeToDump != Ttail-Thead){
|
||||
// Size limit reached.
|
||||
Open->DumpLimitReached = TRUE;
|
||||
|
||||
// Awake the application
|
||||
KeSetEvent(Open->ReadEvent,0,FALSE);
|
||||
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
// Update the packet buffer
|
||||
Open->DumpOffset.QuadPart+=(Ttail-Thead);
|
||||
Open->Bhead=Ttail;
|
||||
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
NTSTATUS NPF_CloseDumpFile(POPEN_INSTANCE Open){
|
||||
NTSTATUS ntStatus;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
PMDL WriteMdl;
|
||||
PUCHAR VMBuff;
|
||||
UINT VMBufLen;
|
||||
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: NPF_CloseDumpFile.\n");)
|
||||
IF_LOUD(DbgPrint("Dumpoffset=%d\n",Open->DumpOffset.QuadPart);)
|
||||
|
||||
DbgPrint("1\n");
|
||||
// Consistency check
|
||||
if(Open->DumpFileHandle == NULL)
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
|
||||
DbgPrint("2\n");
|
||||
ZwClose( Open->DumpFileHandle );
|
||||
|
||||
ObDereferenceObject(Open->DumpFileObject);
|
||||
/*
|
||||
if(Open->DumpLimitReached == TRUE)
|
||||
// Limit already reached: don't save the rest of the buffer.
|
||||
return STATUS_SUCCESS;
|
||||
*/
|
||||
DbgPrint("3\n");
|
||||
|
||||
NPF_OpenDumpFile(Open,&Open->DumpFileName, TRUE);
|
||||
|
||||
// Flush the buffer to file
|
||||
NPF_SaveCurrentBuffer(Open);
|
||||
|
||||
// Close The file
|
||||
ObDereferenceObject(Open->DumpFileObject);
|
||||
ZwClose( Open->DumpFileHandle );
|
||||
|
||||
Open->DumpFileHandle = NULL;
|
||||
|
||||
ObDereferenceObject(Open->DumpFileObject);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
#ifndef __GNUC__
|
||||
static NTSTATUS
|
||||
#else
|
||||
NTSTATUS STDCALL
|
||||
#endif
|
||||
PacketDumpCompletion(PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp,
|
||||
PVOID Context)
|
||||
{
|
||||
|
||||
// Copy the status information back into the "user" IOSB
|
||||
*Irp->UserIosb = Irp->IoStatus;
|
||||
|
||||
// Wake up the mainline code
|
||||
KeSetEvent(Irp->UserEvent, 0, FALSE);
|
||||
|
||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
VOID NPF_WriteDumpFile(PFILE_OBJECT FileObject,
|
||||
PLARGE_INTEGER Offset,
|
||||
ULONG Length,
|
||||
PMDL Mdl,
|
||||
PIO_STATUS_BLOCK IoStatusBlock)
|
||||
{
|
||||
PIRP irp;
|
||||
KEVENT event;
|
||||
PIO_STACK_LOCATION ioStackLocation;
|
||||
PDEVICE_OBJECT fsdDevice = IoGetRelatedDeviceObject(FileObject);
|
||||
NTSTATUS Status;
|
||||
|
||||
// Set up the event we'll use
|
||||
KeInitializeEvent(&event, SynchronizationEvent, FALSE);
|
||||
|
||||
// Allocate and build the IRP we'll be sending to the FSD
|
||||
irp = IoAllocateIrp(fsdDevice->StackSize, FALSE);
|
||||
|
||||
if (!irp) {
|
||||
// Allocation failed, presumably due to memory allocation failure
|
||||
IoStatusBlock->Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
IoStatusBlock->Information = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
irp->MdlAddress = Mdl;
|
||||
irp->UserEvent = &event;
|
||||
irp->UserIosb = IoStatusBlock;
|
||||
irp->Tail.Overlay.Thread = PsGetCurrentThread();
|
||||
irp->Tail.Overlay.OriginalFileObject= FileObject;
|
||||
irp->RequestorMode = KernelMode;
|
||||
|
||||
// Indicate that this is a WRITE operation
|
||||
irp->Flags = IRP_WRITE_OPERATION;
|
||||
|
||||
// Set up the next I/O stack location
|
||||
ioStackLocation = IoGetNextIrpStackLocation(irp);
|
||||
ioStackLocation->MajorFunction = IRP_MJ_WRITE;
|
||||
ioStackLocation->MinorFunction = 0;
|
||||
ioStackLocation->DeviceObject = fsdDevice;
|
||||
ioStackLocation->FileObject = FileObject;
|
||||
IoSetCompletionRoutine(irp, PacketDumpCompletion, 0, TRUE, TRUE, TRUE);
|
||||
ioStackLocation->Parameters.Write.Length = Length;
|
||||
ioStackLocation->Parameters.Write.ByteOffset = *Offset;
|
||||
|
||||
|
||||
// Send it on. Ignore the return code
|
||||
(void) IoCallDriver(fsdDevice, irp);
|
||||
|
||||
// Wait for the I/O to complete.
|
||||
KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, 0);
|
||||
|
||||
// Free the IRP now that we are done with it
|
||||
IoFreeIrp(irp);
|
||||
|
||||
return;
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#include "tme.h"
|
||||
#include "functions.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <net/tme/tme.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/tme/functions.h>
|
||||
#else
|
||||
#include <tme/tme.h>
|
||||
#include <bpf.h>
|
||||
#include <tme/functions.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
lut_fcn lut_fcn_mapper(uint32 index)
|
||||
{
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case NORMAL_LUT_W_INSERT:
|
||||
return (lut_fcn) normal_lut_w_insert;
|
||||
|
||||
case NORMAL_LUT_WO_INSERT:
|
||||
return (lut_fcn) normal_lut_wo_insert;
|
||||
|
||||
case BUCKET_LOOKUP:
|
||||
return (lut_fcn) bucket_lookup;
|
||||
|
||||
case BUCKET_LOOKUP_INSERT:
|
||||
return (lut_fcn) bucket_lookup_insert;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
exec_fcn exec_fcn_mapper(uint32 index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case COUNT_PACKETS:
|
||||
return (exec_fcn) count_packets;
|
||||
|
||||
case TCP_SESSION:
|
||||
return (exec_fcn) tcp_session;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifndef __FUNCTIONS
|
||||
#define __FUNCTIONS
|
||||
|
||||
#ifdef WIN32
|
||||
#include "tme.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <net/tme/tme.h>
|
||||
#else
|
||||
#include <tme/tme.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/*function mappers */
|
||||
|
||||
lut_fcn lut_fcn_mapper(uint32 index);
|
||||
exec_fcn exec_fcn_mapper(uint32 index);
|
||||
|
||||
/* lookup functions */
|
||||
|
||||
#ifdef WIN32
|
||||
#include "bucket_lookup.h"
|
||||
#include "normal_lookup.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <net/tme/bucket_lookup.h>
|
||||
#include <net/tme/normal_lookup.h>
|
||||
#endif
|
||||
|
||||
/* execution functions */
|
||||
|
||||
#ifdef WIN32
|
||||
#include "count_packets.h"
|
||||
#include "tcp_session.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <net/tme/count_packets.h>
|
||||
#include <ne/tme/tcp_session.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -1,681 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2002
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include "stdarg.h"
|
||||
#include "ntddk.h"
|
||||
#include "ntiologc.h"
|
||||
#include "ndis.h"
|
||||
#else
|
||||
#include <ddk/ntddk.h>
|
||||
#include <net/ndis.h>
|
||||
#endif
|
||||
|
||||
#include "packet.h"
|
||||
#include "win_bpf.h"
|
||||
|
||||
emit_func emitm;
|
||||
|
||||
//
|
||||
// emit routine to update the jump table
|
||||
//
|
||||
void emit_lenght(binary_stream *stream, ULONG value, UINT len)
|
||||
{
|
||||
(stream->refs)[stream->bpf_pc]+=len;
|
||||
stream->cur_ip+=len;
|
||||
}
|
||||
|
||||
//
|
||||
// emit routine to output the actual binary code
|
||||
//
|
||||
void emit_code(binary_stream *stream, ULONG value, UINT len)
|
||||
{
|
||||
|
||||
switch (len){
|
||||
|
||||
case 1:
|
||||
stream->ibuf[stream->cur_ip]=(UCHAR)value;
|
||||
stream->cur_ip++;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
*((USHORT*)(stream->ibuf+stream->cur_ip))=(USHORT)value;
|
||||
stream->cur_ip+=2;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
*((ULONG*)(stream->ibuf+stream->cur_ip))=value;
|
||||
stream->cur_ip+=4;
|
||||
break;
|
||||
|
||||
default:;
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Function that does the real stuff
|
||||
//
|
||||
BPF_filter_function BPFtoX86(struct bpf_insn *prog, UINT nins, INT *mem)
|
||||
{
|
||||
struct bpf_insn *ins;
|
||||
UINT i, pass;
|
||||
binary_stream stream;
|
||||
|
||||
|
||||
// Allocate the reference table for the jumps
|
||||
#ifdef NTKERNEL
|
||||
#define NPF_TAG_REFTABLE TAG('0', 'J', 'W', 'A')
|
||||
stream.refs=(UINT *)ExAllocatePoolWithTag(NonPagedPool, (nins + 1)*sizeof(UINT), NPF_TAG_REFTABLE);
|
||||
#else
|
||||
stream.refs=(UINT *)malloc((nins + 1)*sizeof(UINT));
|
||||
#endif
|
||||
if(stream.refs==NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Reset the reference table
|
||||
for(i=0; i< nins + 1; i++)
|
||||
stream.refs[i]=0;
|
||||
|
||||
stream.cur_ip=0;
|
||||
stream.bpf_pc=0;
|
||||
|
||||
// the first pass will emit the lengths of the instructions
|
||||
// to create the reference table
|
||||
emitm=emit_lenght;
|
||||
|
||||
for(pass=0;;){
|
||||
|
||||
ins = prog;
|
||||
|
||||
/* create the procedure header */
|
||||
PUSH(EBP)
|
||||
MOVrd(EBP,ESP)
|
||||
PUSH(EBX)
|
||||
PUSH(ECX)
|
||||
PUSH(EDX)
|
||||
PUSH(ESI)
|
||||
PUSH(EDI)
|
||||
MOVodd(EBX, EBP, 8)
|
||||
|
||||
for(i=0;i<nins;i++){
|
||||
|
||||
stream.bpf_pc++;
|
||||
|
||||
switch (ins->code) {
|
||||
|
||||
default:
|
||||
|
||||
return NULL;
|
||||
|
||||
case BPF_RET|BPF_K:
|
||||
|
||||
MOVid(EAX,ins->k)
|
||||
POP(EDI)
|
||||
POP(ESI)
|
||||
POP(EDX)
|
||||
POP(ECX)
|
||||
POP(EBX)
|
||||
POP(EBP)
|
||||
RET()
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case BPF_RET|BPF_A:
|
||||
|
||||
POP(EDI)
|
||||
POP(ESI)
|
||||
POP(EDX)
|
||||
POP(ECX)
|
||||
POP(EBX)
|
||||
POP(EBP)
|
||||
RET()
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case BPF_LD|BPF_W|BPF_ABS:
|
||||
|
||||
MOVid(ECX,ins->k)
|
||||
MOVrd(ESI,ECX)
|
||||
ADDib(ECX,sizeof(INT))
|
||||
CMPodd(ECX, EBP, 0x10)
|
||||
JLEb(12)
|
||||
POP(EDI)
|
||||
POP(ESI)
|
||||
POP(EDX)
|
||||
POP(ECX)
|
||||
POP(EBX)
|
||||
POP(EBP)
|
||||
MOVid(EAX,0) //this can be optimized with xor eax,eax
|
||||
RET()
|
||||
MOVobd(EAX, EBX, ESI)
|
||||
BSWAP(EAX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_LD|BPF_H|BPF_ABS:
|
||||
|
||||
MOVid(ECX,ins->k)
|
||||
MOVrd(ESI,ECX)
|
||||
ADDib(ECX,sizeof(SHORT))
|
||||
CMPodd(ECX, EBP, 0x10)
|
||||
JLEb(12)
|
||||
POP(EDI)
|
||||
POP(ESI)
|
||||
POP(EDX)
|
||||
POP(ECX)
|
||||
POP(EBX)
|
||||
POP(EBP)
|
||||
MOVid(EAX,0)
|
||||
RET()
|
||||
MOVid(EAX,0)
|
||||
MOVobw(AX, EBX, ESI)
|
||||
SWAP_AX()
|
||||
|
||||
break;
|
||||
|
||||
case BPF_LD|BPF_B|BPF_ABS:
|
||||
|
||||
MOVid(ECX,ins->k)
|
||||
CMPodd(ECX, EBP, 0x10)
|
||||
JLEb(12)
|
||||
POP(EDI)
|
||||
POP(ESI)
|
||||
POP(EDX)
|
||||
POP(ECX)
|
||||
POP(EBX)
|
||||
POP(EBP)
|
||||
MOVid(EAX,0)
|
||||
RET()
|
||||
MOVid(EAX,0)
|
||||
MOVobb(AL,EBX,ECX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_LD|BPF_W|BPF_LEN:
|
||||
|
||||
MOVodd(EAX, EBP, 0xc)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_LDX|BPF_W|BPF_LEN:
|
||||
|
||||
MOVodd(EDX, EBP, 0xc)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_LD|BPF_W|BPF_IND:
|
||||
|
||||
MOVid(ECX,ins->k)
|
||||
ADDrd(ECX,EDX)
|
||||
MOVrd(ESI,ECX)
|
||||
ADDib(ECX,sizeof(INT))
|
||||
CMPodd(ECX, EBP, 0x10)
|
||||
JLEb(12)
|
||||
POP(EDI)
|
||||
POP(ESI)
|
||||
POP(EDX)
|
||||
POP(ECX)
|
||||
POP(EBX)
|
||||
POP(EBP)
|
||||
MOVid(EAX,0)
|
||||
RET()
|
||||
MOVobd(EAX, EBX, ESI)
|
||||
BSWAP(EAX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_LD|BPF_H|BPF_IND:
|
||||
|
||||
MOVid(ECX,ins->k)
|
||||
ADDrd(ECX,EDX)
|
||||
MOVrd(ESI,ECX)
|
||||
ADDib(ECX,sizeof(SHORT))
|
||||
CMPodd(ECX, EBP, 0x10)
|
||||
JLEb(12)
|
||||
POP(EDI)
|
||||
POP(ESI)
|
||||
POP(EDX)
|
||||
POP(ECX)
|
||||
POP(EBX)
|
||||
POP(EBP)
|
||||
MOVid(EAX,0)
|
||||
RET()
|
||||
MOVid(EAX,0)
|
||||
MOVobw(AX, EBX, ESI)
|
||||
SWAP_AX()
|
||||
|
||||
break;
|
||||
|
||||
case BPF_LD|BPF_B|BPF_IND:
|
||||
|
||||
MOVid(ECX,ins->k)
|
||||
ADDrd(ECX,EDX)
|
||||
CMPodd(ECX, EBP, 0x10)
|
||||
JLEb(12)
|
||||
POP(EDI)
|
||||
POP(ESI)
|
||||
POP(EDX)
|
||||
POP(ECX)
|
||||
POP(EBX)
|
||||
POP(EBP)
|
||||
MOVid(EAX,0)
|
||||
RET()
|
||||
MOVid(EAX,0)
|
||||
MOVobb(AL,EBX,ECX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_LDX|BPF_MSH|BPF_B:
|
||||
|
||||
MOVid(ECX,ins->k)
|
||||
CMPodd(ECX, EBP, 0x10)
|
||||
JLEb(12)
|
||||
POP(EDI)
|
||||
POP(ESI)
|
||||
POP(EDX)
|
||||
POP(ECX)
|
||||
POP(EBX)
|
||||
POP(EBP)
|
||||
MOVid(EAX,0)
|
||||
RET()
|
||||
MOVid(EDX,0)
|
||||
MOVobb(DL,EBX,ECX)
|
||||
ANDib(DL, 0xf)
|
||||
SHLib(EDX, 2)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_LD|BPF_IMM:
|
||||
|
||||
MOVid(EAX,ins->k)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_LDX|BPF_IMM:
|
||||
|
||||
MOVid(EDX,ins->k)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_LD|BPF_MEM:
|
||||
|
||||
MOVid(ECX,(INT)mem)
|
||||
MOVid(ESI,ins->k*4)
|
||||
MOVobd(EAX, ECX, ESI)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_LDX|BPF_MEM:
|
||||
|
||||
MOVid(ECX,(INT)mem)
|
||||
MOVid(ESI,ins->k*4)
|
||||
MOVobd(EDX, ECX, ESI)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ST:
|
||||
|
||||
// XXX: this command and the following could be optimized if the previous
|
||||
// instruction was already of this type
|
||||
MOVid(ECX,(INT)mem)
|
||||
MOVid(ESI,ins->k*4)
|
||||
MOVomd(ECX, ESI, EAX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_STX:
|
||||
|
||||
MOVid(ECX,(INT)mem)
|
||||
MOVid(ESI,ins->k*4)
|
||||
MOVomd(ECX, ESI, EDX)
|
||||
break;
|
||||
|
||||
case BPF_JMP|BPF_JA:
|
||||
|
||||
JMP(stream.refs[stream.bpf_pc+ins->k]-stream.refs[stream.bpf_pc])
|
||||
|
||||
break;
|
||||
|
||||
case BPF_JMP|BPF_JGT|BPF_K:
|
||||
|
||||
CMPid(EAX, ins->k)
|
||||
JG(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5) // 5 is the size of the following JMP
|
||||
JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
|
||||
break;
|
||||
|
||||
case BPF_JMP|BPF_JGE|BPF_K:
|
||||
|
||||
CMPid(EAX, ins->k)
|
||||
JGE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
|
||||
JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
|
||||
|
||||
break;
|
||||
|
||||
case BPF_JMP|BPF_JEQ|BPF_K:
|
||||
|
||||
CMPid(EAX, ins->k)
|
||||
JE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
|
||||
JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
|
||||
|
||||
break;
|
||||
|
||||
case BPF_JMP|BPF_JSET|BPF_K:
|
||||
|
||||
MOVrd(ECX,EAX)
|
||||
ANDid(ECX,ins->k)
|
||||
JE(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]+5)
|
||||
JMP(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc])
|
||||
|
||||
break;
|
||||
|
||||
case BPF_JMP|BPF_JGT|BPF_X:
|
||||
|
||||
CMPrd(EAX, EDX)
|
||||
JA(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
|
||||
JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
|
||||
break;
|
||||
|
||||
case BPF_JMP|BPF_JGE|BPF_X:
|
||||
|
||||
CMPrd(EAX, EDX)
|
||||
JAE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
|
||||
JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
|
||||
|
||||
break;
|
||||
|
||||
case BPF_JMP|BPF_JEQ|BPF_X:
|
||||
|
||||
CMPrd(EAX, EDX)
|
||||
JE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
|
||||
JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
|
||||
|
||||
break;
|
||||
|
||||
case BPF_JMP|BPF_JSET|BPF_X:
|
||||
|
||||
MOVrd(ECX,EAX)
|
||||
ANDrd(ECX,EDX)
|
||||
JE(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]+5)
|
||||
JMP(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc])
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_ADD|BPF_X:
|
||||
|
||||
ADDrd(EAX,EDX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_SUB|BPF_X:
|
||||
|
||||
SUBrd(EAX,EDX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_MUL|BPF_X:
|
||||
|
||||
MOVrd(ECX,EDX)
|
||||
MULrd(EDX)
|
||||
MOVrd(EDX,ECX)
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_DIV|BPF_X:
|
||||
|
||||
CMPid(EDX, 0)
|
||||
JNEb(12)
|
||||
POP(EDI)
|
||||
POP(ESI)
|
||||
POP(EDX)
|
||||
POP(ECX)
|
||||
POP(EBX)
|
||||
POP(EBP)
|
||||
MOVid(EAX,0)
|
||||
RET()
|
||||
MOVrd(ECX,EDX)
|
||||
MOVid(EDX,0)
|
||||
DIVrd(ECX)
|
||||
MOVrd(EDX,ECX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_AND|BPF_X:
|
||||
|
||||
ANDrd(EAX,EDX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_OR|BPF_X:
|
||||
|
||||
ORrd(EAX,EDX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_LSH|BPF_X:
|
||||
|
||||
MOVrd(ECX,EDX)
|
||||
SHL_CLrb(EAX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_RSH|BPF_X:
|
||||
|
||||
MOVrd(ECX,EDX)
|
||||
SHR_CLrb(EAX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_ADD|BPF_K:
|
||||
|
||||
ADD_EAXi(ins->k)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_SUB|BPF_K:
|
||||
|
||||
SUB_EAXi(ins->k)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_MUL|BPF_K:
|
||||
|
||||
MOVrd(ECX,EDX)
|
||||
MOVid(EDX,ins->k)
|
||||
MULrd(EDX)
|
||||
MOVrd(EDX,ECX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_DIV|BPF_K:
|
||||
|
||||
MOVrd(ECX,EDX)
|
||||
MOVid(EDX,0)
|
||||
MOVid(ESI,ins->k)
|
||||
DIVrd(ESI)
|
||||
MOVrd(EDX,ECX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_AND|BPF_K:
|
||||
|
||||
ANDid(EAX, ins->k)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_OR|BPF_K:
|
||||
|
||||
ORid(EAX, ins->k)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_LSH|BPF_K:
|
||||
|
||||
SHLib(EAX, (ins->k) & 255)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_RSH|BPF_K:
|
||||
|
||||
SHRib(EAX, (ins->k) & 255)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_NEG:
|
||||
|
||||
NEGd(EAX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_MISC|BPF_TAX:
|
||||
|
||||
MOVrd(EDX,EAX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_MISC|BPF_TXA:
|
||||
|
||||
MOVrd(EAX,EDX)
|
||||
|
||||
break;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
ins++;
|
||||
}
|
||||
|
||||
pass++;
|
||||
if(pass == 2) break;
|
||||
|
||||
#ifdef NTKERNEL
|
||||
#define NPF_TAG_STREAMBUF TAG('1', 'J', 'W', 'A')
|
||||
stream.ibuf=(CHAR*)ExAllocatePoolWithTag(NonPagedPool, stream.cur_ip, NPF_TAG_STREAMBUF);
|
||||
#else
|
||||
stream.ibuf=(CHAR*)malloc(stream.cur_ip);
|
||||
#endif
|
||||
if(stream.ibuf==NULL)
|
||||
{
|
||||
#ifdef NTKERNEL
|
||||
ExFreePool(stream.refs);
|
||||
#else
|
||||
free(stream.refs);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// modify the reference table to contain the offsets and not the lengths of the instructions
|
||||
for(i=1; i< nins + 1; i++)
|
||||
stream.refs[i]+=stream.refs[i-1];
|
||||
|
||||
// Reset the counters
|
||||
stream.cur_ip=0;
|
||||
stream.bpf_pc=0;
|
||||
// the second pass creates the actual code
|
||||
emitm=emit_code;
|
||||
|
||||
}
|
||||
|
||||
// the reference table is needed only during compilation, now we can free it
|
||||
#ifdef NTKERNEL
|
||||
ExFreePool(stream.refs);
|
||||
#else
|
||||
free(stream.refs);
|
||||
#endif
|
||||
return (BPF_filter_function)stream.ibuf;
|
||||
|
||||
}
|
||||
|
||||
|
||||
JIT_BPF_Filter* BPF_jitter(struct bpf_insn *fp, INT nins)
|
||||
{
|
||||
JIT_BPF_Filter *Filter;
|
||||
|
||||
|
||||
// Allocate the filter structure
|
||||
#ifdef NTKERNEL
|
||||
#define NPF_TAG_FILTSTRUCT TAG('2', 'J', 'W', 'A')
|
||||
Filter=(struct JIT_BPF_Filter*)ExAllocatePoolWithTag(NonPagedPool, sizeof(struct JIT_BPF_Filter), NPF_TAG_FILTSTRUCT);
|
||||
#else
|
||||
Filter=(struct JIT_BPF_Filter*)malloc(sizeof(struct JIT_BPF_Filter));
|
||||
#endif
|
||||
if(Filter==NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Allocate the filter's memory
|
||||
#ifdef NTKERNEL
|
||||
#define NPF_TAG_FILTMEM TAG('3', 'J', 'W', 'A')
|
||||
Filter->mem=(INT*)ExAllocatePoolWithTag(NonPagedPool, BPF_MEMWORDS*sizeof(INT), NPF_TAG_FILTMEM);
|
||||
#else
|
||||
Filter->mem=(INT*)malloc(BPF_MEMWORDS*sizeof(INT));
|
||||
#endif
|
||||
if(Filter->mem==NULL)
|
||||
{
|
||||
#ifdef NTKERNEL
|
||||
ExFreePool(Filter);
|
||||
#else
|
||||
free(Filter);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create the binary
|
||||
if((Filter->Function = BPFtoX86(fp, nins, Filter->mem))==NULL)
|
||||
{
|
||||
#ifdef NTKERNEL
|
||||
ExFreePool(Filter->mem);
|
||||
ExFreePool(Filter);
|
||||
#else
|
||||
free(Filter->mem);
|
||||
free(Filter);
|
||||
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
return Filter;
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
void BPF_Destroy_JIT_Filter(JIT_BPF_Filter *Filter){
|
||||
|
||||
#ifdef NTKERNEL
|
||||
ExFreePool(Filter->mem);
|
||||
ExFreePool(Filter->Function);
|
||||
ExFreePool(Filter);
|
||||
#else
|
||||
free(Filter->mem);
|
||||
free(Filter->Function);
|
||||
free(Filter);
|
||||
#endif
|
||||
|
||||
}
|
|
@ -1,391 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2002
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/** @ingroup NPF
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup NPF_include NPF structures and definitions
|
||||
* @{
|
||||
*/
|
||||
|
||||
//
|
||||
// Registers
|
||||
//
|
||||
#define EAX 0
|
||||
#define ECX 1
|
||||
#define EDX 2
|
||||
#define EBX 3
|
||||
#define ESP 4
|
||||
#define EBP 5
|
||||
#define ESI 6
|
||||
#define EDI 7
|
||||
|
||||
#define AX 0
|
||||
#define CX 1
|
||||
#define DX 2
|
||||
#define BX 3
|
||||
#define SP 4
|
||||
#define BP 5
|
||||
#define SI 6
|
||||
#define DI 7
|
||||
|
||||
#define AL 0
|
||||
#define CL 1
|
||||
#define DL 2
|
||||
#define BL 3
|
||||
|
||||
/*! \brief A stream of X86 binary code.*/
|
||||
typedef struct binary_stream{
|
||||
INT cur_ip; ///< Current X86 instruction pointer.
|
||||
INT bpf_pc; ///< Current BPF instruction pointer, i.e. position in the BPF program reached by the jitter.
|
||||
PCHAR ibuf; ///< Instruction buffer, contains the X86 generated code.
|
||||
PUINT refs; ///< Jumps reference table.
|
||||
}binary_stream;
|
||||
|
||||
|
||||
/*! \brief Prototype of a filtering function created by the jitter.
|
||||
|
||||
The syntax and the meaning of the parameters is analogous to the one of bpf_filter(). Notice that the filter
|
||||
is not among the parameters, because it is hardwired in the function.
|
||||
*/
|
||||
typedef UINT (*BPF_filter_function)( binary_stream *, ULONG, UINT);
|
||||
|
||||
/*! \brief Prototype of the emit functions.
|
||||
|
||||
Different emit functions are used to create the reference table and to generate the actual filtering code.
|
||||
This allows to have simpler instruction macros.
|
||||
The first parameter is the stream that will receive the data. The secon one is a variable containing
|
||||
the data, the third one is the length, that can be 1,2 or 4 since it is possible to emit a byte, a short
|
||||
or a work at a time.
|
||||
*/
|
||||
typedef void (*emit_func)(binary_stream *stream, ULONG value, UINT n);
|
||||
|
||||
/*! \brief Structure describing a x86 filtering program created by the jitter.*/
|
||||
typedef struct JIT_BPF_Filter{
|
||||
BPF_filter_function Function; ///< The x86 filtering binary, in the form of a BPF_filter_function.
|
||||
PINT mem;
|
||||
}
|
||||
JIT_BPF_Filter;
|
||||
|
||||
|
||||
|
||||
|
||||
/**************************/
|
||||
/* X86 INSTRUCTION MACROS */
|
||||
/**************************/
|
||||
|
||||
/// mov r32,i32
|
||||
#define MOVid(r32, i32) \
|
||||
emitm(&stream, 11 << 4 | 1 << 3 | r32 & 0x7, 1); emitm(&stream, i32, 4);
|
||||
|
||||
/// mov dr32,sr32
|
||||
#define MOVrd(dr32, sr32) \
|
||||
emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
|
||||
|
||||
/// mov dr32,sr32[off]
|
||||
#define MOVodd(dr32, sr32, off) \
|
||||
emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \
|
||||
emitm(&stream, 1 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);\
|
||||
emitm(&stream, off, 1);
|
||||
|
||||
/// mov dr32,sr32[or32]
|
||||
#define MOVobd(dr32, sr32, or32) \
|
||||
emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \
|
||||
emitm(&stream, (dr32 & 0x7) << 3 | 4 , 1);\
|
||||
emitm(&stream, (or32 & 0x7) << 3 | (sr32 & 0x7) , 1);
|
||||
|
||||
/// mov dr16,sr32[or32]
|
||||
#define MOVobw(dr32, sr32, or32) \
|
||||
emitm(&stream, 0x66, 1); \
|
||||
emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \
|
||||
emitm(&stream, (dr32 & 0x7) << 3 | 4 , 1);\
|
||||
emitm(&stream, (or32 & 0x7) << 3 | (sr32 & 0x7) , 1);
|
||||
|
||||
/// mov dr8,sr32[or32]
|
||||
#define MOVobb(dr8, sr32, or32) \
|
||||
emitm(&stream, 0x8a, 1); \
|
||||
emitm(&stream, (dr8 & 0x7) << 3 | 4 , 1);\
|
||||
emitm(&stream, (or32 & 0x7) << 3 | (sr32 & 0x7) , 1);
|
||||
|
||||
/// mov [dr32][or32],sr32
|
||||
#define MOVomd(dr32, or32, sr32) \
|
||||
emitm(&stream, 0x89, 1); \
|
||||
emitm(&stream, (sr32 & 0x7) << 3 | 4 , 1);\
|
||||
emitm(&stream, (or32 & 0x7) << 3 | (dr32 & 0x7) , 1);
|
||||
|
||||
/// bswap dr32
|
||||
#define BSWAP(dr32) \
|
||||
emitm(&stream, 0xf, 1); \
|
||||
emitm(&stream, 0x19 << 3 | dr32 , 1);
|
||||
|
||||
/// xchg al,ah
|
||||
#define SWAP_AX() \
|
||||
emitm(&stream, 0x86, 1); \
|
||||
emitm(&stream, 0xc4 , 1);
|
||||
|
||||
/// push r32
|
||||
#define PUSH(r32) \
|
||||
emitm(&stream, 5 << 4 | 0 << 3 | r32 & 0x7, 1);
|
||||
|
||||
/// pop r32
|
||||
#define POP(r32) \
|
||||
emitm(&stream, 5 << 4 | 1 << 3 | r32 & 0x7, 1);
|
||||
|
||||
/// ret
|
||||
#define RET() \
|
||||
emitm(&stream, 12 << 4 | 0 << 3 | 3, 1);
|
||||
|
||||
/// add dr32,sr32
|
||||
#define ADDrd(dr32, sr32) \
|
||||
emitm(&stream, 0x03, 1);\
|
||||
emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | (sr32 & 0x7), 1);
|
||||
|
||||
/// add eax,i32
|
||||
#define ADD_EAXi(i32) \
|
||||
emitm(&stream, 0x05, 1);\
|
||||
emitm(&stream, i32, 4);
|
||||
|
||||
/// add r32,i32
|
||||
#define ADDid(r32, i32) \
|
||||
emitm(&stream, 0x81, 1);\
|
||||
emitm(&stream, 24 << 3 | r32, 1);\
|
||||
emitm(&stream, i32, 4);
|
||||
|
||||
/// add r32,i8
|
||||
#define ADDib(r32, i8) \
|
||||
emitm(&stream, 0x83, 1);\
|
||||
emitm(&stream, 24 << 3 | r32, 1);\
|
||||
emitm(&stream, i8, 1);
|
||||
|
||||
/// sub dr32,sr32
|
||||
#define SUBrd(dr32, sr32) \
|
||||
emitm(&stream, 0x2b, 1);\
|
||||
emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | (sr32 & 0x7), 1);
|
||||
|
||||
/// sub eax,i32
|
||||
#define SUB_EAXi(i32) \
|
||||
emitm(&stream, 0x2d, 1);\
|
||||
emitm(&stream, i32, 4);
|
||||
|
||||
/// mul r32
|
||||
#define MULrd(r32) \
|
||||
emitm(&stream, 0xf7, 1);\
|
||||
emitm(&stream, 7 << 5 | (r32 & 0x7), 1);
|
||||
|
||||
/// div r32
|
||||
#define DIVrd(r32) \
|
||||
emitm(&stream, 0xf7, 1);\
|
||||
emitm(&stream, 15 << 4 | (r32 & 0x7), 1);
|
||||
|
||||
/// and r8,i8
|
||||
#define ANDib(r8, i8) \
|
||||
emitm(&stream, 0x80, 1);\
|
||||
emitm(&stream, 7 << 5 | r8, 1);\
|
||||
emitm(&stream, i8, 1);
|
||||
|
||||
/// and r32,i32
|
||||
#define ANDid(r32, i32) \
|
||||
if (r32 == EAX){ \
|
||||
emitm(&stream, 0x25, 1);\
|
||||
emitm(&stream, i32, 4);}\
|
||||
else{ \
|
||||
emitm(&stream, 0x81, 1);\
|
||||
emitm(&stream, 7 << 5 | r32, 1);\
|
||||
emitm(&stream, i32, 4);}
|
||||
|
||||
/// and dr32,sr32
|
||||
#define ANDrd(dr32, sr32) \
|
||||
emitm(&stream, 0x23, 1);\
|
||||
emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
|
||||
|
||||
/// or dr32,sr32
|
||||
#define ORrd(dr32, sr32) \
|
||||
emitm(&stream, 0x0b, 1);\
|
||||
emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
|
||||
|
||||
/// or r32,i32
|
||||
#define ORid(r32, i32) \
|
||||
if (r32 == EAX){ \
|
||||
emitm(&stream, 0x0d, 1);\
|
||||
emitm(&stream, i32, 4);}\
|
||||
else{ \
|
||||
emitm(&stream, 0x81, 1);\
|
||||
emitm(&stream, 25 << 3 | r32, 1);\
|
||||
emitm(&stream, i32, 4);}
|
||||
|
||||
/// shl r32,i8
|
||||
#define SHLib(r32, i8) \
|
||||
emitm(&stream, 0xc1, 1);\
|
||||
emitm(&stream, 7 << 5 | r32 & 0x7, 1);\
|
||||
emitm(&stream, i8, 1);
|
||||
|
||||
/// shl dr32,cl
|
||||
#define SHL_CLrb(dr32) \
|
||||
emitm(&stream, 0xd3, 1);\
|
||||
emitm(&stream, 7 << 5 | dr32 & 0x7, 1);
|
||||
|
||||
/// shr r32,i8
|
||||
#define SHRib(r32, i8) \
|
||||
emitm(&stream, 0xc1, 1);\
|
||||
emitm(&stream, 29 << 3 | r32 & 0x7, 1);\
|
||||
emitm(&stream, i8, 1);
|
||||
|
||||
/// shr dr32,cl
|
||||
#define SHR_CLrb(dr32) \
|
||||
emitm(&stream, 0xd3, 1);\
|
||||
emitm(&stream, 29 << 3 | dr32 & 0x7, 1);
|
||||
|
||||
/// neg r32
|
||||
#define NEGd(r32) \
|
||||
emitm(&stream, 0xf7, 1);\
|
||||
emitm(&stream, 27 << 3 | r32 & 0x7, 1);
|
||||
|
||||
/// cmp dr32,sr32[off]
|
||||
#define CMPodd(dr32, sr32, off) \
|
||||
emitm(&stream, 3 << 4 | 3 | 1 << 3, 1); \
|
||||
emitm(&stream, 1 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);\
|
||||
emitm(&stream, off, 1);
|
||||
|
||||
/// cmp dr32,sr32
|
||||
#define CMPrd(dr32, sr32) \
|
||||
emitm(&stream, 0x3b, 1); \
|
||||
emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
|
||||
|
||||
/// cmp dr32,i32
|
||||
#define CMPid(dr32, i32) \
|
||||
if (dr32 == EAX){ \
|
||||
emitm(&stream, 0x3d, 1); \
|
||||
emitm(&stream, i32, 4);} \
|
||||
else{ \
|
||||
emitm(&stream, 0x81, 1); \
|
||||
emitm(&stream, 0x1f << 3 | (dr32 & 0x7), 1);\
|
||||
emitm(&stream, i32, 4);}
|
||||
|
||||
/// jne off32
|
||||
#define JNEb(off8) \
|
||||
emitm(&stream, 0x75, 1);\
|
||||
emitm(&stream, off8, 1);
|
||||
|
||||
/// je off32
|
||||
#define JE(off32) \
|
||||
emitm(&stream, 0x0f, 1);\
|
||||
emitm(&stream, 0x84, 1);\
|
||||
emitm(&stream, off32, 4);
|
||||
|
||||
/// jle off32
|
||||
#define JLE(off32) \
|
||||
emitm(&stream, 0x0f, 1);\
|
||||
emitm(&stream, 0x8e, 1);\
|
||||
emitm(&stream, off32, 4);
|
||||
|
||||
/// jle off8
|
||||
#define JLEb(off8) \
|
||||
emitm(&stream, 0x7e, 1);\
|
||||
emitm(&stream, off8, 1);
|
||||
|
||||
/// ja off32
|
||||
#define JA(off32) \
|
||||
emitm(&stream, 0x0f, 1);\
|
||||
emitm(&stream, 0x87, 1);\
|
||||
emitm(&stream, off32, 4);
|
||||
|
||||
/// jae off32
|
||||
#define JAE(off32) \
|
||||
emitm(&stream, 0x0f, 1);\
|
||||
emitm(&stream, 0x83, 1);\
|
||||
emitm(&stream, off32, 4);
|
||||
|
||||
/// jg off32
|
||||
#define JG(off32) \
|
||||
emitm(&stream, 0x0f, 1);\
|
||||
emitm(&stream, 0x8f, 1);\
|
||||
emitm(&stream, off32, 4);
|
||||
|
||||
/// jge off32
|
||||
#define JGE(off32) \
|
||||
emitm(&stream, 0x0f, 1);\
|
||||
emitm(&stream, 0x8d, 1);\
|
||||
emitm(&stream, off32, 4);
|
||||
|
||||
/// jmp off32
|
||||
#define JMP(off32) \
|
||||
emitm(&stream, 0xe9, 1);\
|
||||
emitm(&stream, off32, 4);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**************************/
|
||||
/* Prototypes */
|
||||
/**************************/
|
||||
|
||||
/** @ingroup NPF
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup NPF_code NPF functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
\brief BPF jitter, builds an x86 function from a BPF program.
|
||||
\param fp The BPF pseudo-assembly filter that will be translated into x86 code.
|
||||
\param nins Number of instructions of the input filter.
|
||||
\return The JIT_BPF_Filter structure containing the x86 filtering binary.
|
||||
|
||||
BPF_jitter allocates the buffers for the new native filter and then translates the program pointed by fp
|
||||
calling BPFtoX86().
|
||||
*/
|
||||
JIT_BPF_Filter* BPF_jitter(struct bpf_insn *fp, INT nins);
|
||||
|
||||
/*!
|
||||
\brief Translates a set of BPF instructions in a set of x86 ones.
|
||||
\param ins Pointer to the BPF instructions that will be translated into x86 code.
|
||||
\param nins Number of instructions to translate.
|
||||
\param mem Memory used by the x86 function to emulate the RAM of the BPF pseudo processor.
|
||||
\return The x86 filtering function.
|
||||
|
||||
This function does the hard work for the JIT compilation. It takes a group of BPF pseudo instructions and
|
||||
through the instruction macros defined in jitter.h it is able to create an function directly executable
|
||||
by NPF.
|
||||
*/
|
||||
BPF_filter_function BPFtoX86(struct bpf_insn *ins, UINT nins, INT *mem);
|
||||
/*!
|
||||
\brief Deletes a filtering function that was previously created by BPF_jitter().
|
||||
\param Filter The filter to destroy.
|
||||
|
||||
This function frees the variuos buffers (code, memory, etc.) associated with a filtering function.
|
||||
*/
|
||||
void BPF_Destroy_JIT_Filter(JIT_BPF_Filter *Filter);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
|
@ -1,68 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#include "tme.h"
|
||||
#include "memory_t.h"
|
||||
|
||||
#ifdef _USE_SW_FUNCS_
|
||||
|
||||
int32 SW_LONG_AT(void *b, uint32 c)
|
||||
{
|
||||
return ((int32)*((uint8 *)b+c)<<24|
|
||||
(int32)*((uint8 *)b+c+1)<<16|
|
||||
(int32)*((uint8 *)b+c+2)<<8|
|
||||
(int32)*((uint8 *)b+c+3)<<0);
|
||||
}
|
||||
|
||||
uint32 SW_ULONG_AT(void *b, uint32 c)
|
||||
{
|
||||
return ((uint32)*((uint8 *)b+c)<<24|
|
||||
(uint32)*((uint8 *)b+c+1)<<16|
|
||||
(uint32)*((uint8 *)b+c+2)<<8|
|
||||
(uint32)*((uint8 *)b+c+3)<<0);
|
||||
}
|
||||
|
||||
int16 SW_SHORT_AT(void *b, uint32 os)
|
||||
{
|
||||
return ((int16)
|
||||
((int16)*((uint8 *)b+os+0)<<8|
|
||||
(int16)*((uint8 *)b+os+1)<<0));
|
||||
}
|
||||
|
||||
uint16 SW_USHORT_AT(void *b, uint32 os)
|
||||
{
|
||||
return ((uint16)
|
||||
((uint16)*((uint8 *)b+os+0)<<8|
|
||||
(uint16)*((uint8 *)b+os+1)<<0));
|
||||
}
|
||||
|
||||
VOID SW_ULONG_ASSIGN(void *dst, uint32 src)
|
||||
{
|
||||
*((uint8*)dst+0)=*((uint8*)&src+3);
|
||||
*((uint8*)dst+1)=*((uint8*)&src+2);
|
||||
*((uint8*)dst+2)=*((uint8*)&src+1);
|
||||
*((uint8*)dst+3)=*((uint8*)&src+0);
|
||||
|
||||
}
|
||||
|
||||
#endif /*_USE_SW_FUNCS_*/
|
||||
|
||||
void assert(void* assert, const char* file, int line, void* msg) { };
|
|
@ -1,124 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifndef __memory_t
|
||||
#define __memory_t
|
||||
|
||||
#define uint8 UCHAR
|
||||
#define int8 CHAR
|
||||
#define uint16 USHORT
|
||||
#define int16 SHORT
|
||||
#define uint32 ULONG
|
||||
#define int32 LONG
|
||||
#define uint64 ULONGLONG
|
||||
#define int64 LONGLONG
|
||||
|
||||
/*memory type*/
|
||||
typedef struct __MEM_TYPE
|
||||
{
|
||||
uint8 *buffer;
|
||||
uint32 size;
|
||||
} MEM_TYPE, *PMEM_TYPE;
|
||||
|
||||
#define LONG_AT(base,offset) (*(int32*)((uint8*)base+(uint32)offset))
|
||||
|
||||
#define ULONG_AT(base,offset) (*(uint32*)((uint8*)base+(uint32)offset))
|
||||
|
||||
#define SHORT_AT(base,offset) (*(int16*)((uint8*)base+(uint32)offset))
|
||||
|
||||
#define USHORT_AT(base,offset) (*(uint16*)((uint8*)base+(uint32)offset))
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define __inline inline
|
||||
#define _USE_SW_FUNCS_
|
||||
#endif
|
||||
|
||||
#ifdef _USE_SW_FUNCS_
|
||||
|
||||
inline int32 SW_LONG_AT(void *b, uint32 c);
|
||||
inline uint32 SW_ULONG_AT(void *b, uint32 c);
|
||||
inline int16 SW_SHORT_AT(void *b, uint32 os);
|
||||
inline uint16 SW_USHORT_AT(void *b, uint32 os);
|
||||
inline VOID SW_ULONG_ASSIGN(void *dst, uint32 src);
|
||||
|
||||
#else /*_USE_SW_FUNCS_*/
|
||||
|
||||
__inline int32 SW_LONG_AT(void *b, uint32 c)
|
||||
{
|
||||
return ((int32)*((uint8 *)b+c)<<24|
|
||||
(int32)*((uint8 *)b+c+1)<<16|
|
||||
(int32)*((uint8 *)b+c+2)<<8|
|
||||
(int32)*((uint8 *)b+c+3)<<0);
|
||||
}
|
||||
|
||||
__inline uint32 SW_ULONG_AT(void *b, uint32 c)
|
||||
{
|
||||
return ((uint32)*((uint8 *)b+c)<<24|
|
||||
(uint32)*((uint8 *)b+c+1)<<16|
|
||||
(uint32)*((uint8 *)b+c+2)<<8|
|
||||
(uint32)*((uint8 *)b+c+3)<<0);
|
||||
}
|
||||
|
||||
__inline int16 SW_SHORT_AT(void *b, uint32 os)
|
||||
{
|
||||
return ((int16)
|
||||
((int16)*((uint8 *)b+os+0)<<8|
|
||||
(int16)*((uint8 *)b+os+1)<<0));
|
||||
}
|
||||
|
||||
__inline uint16 SW_USHORT_AT(void *b, uint32 os)
|
||||
{
|
||||
return ((uint16)
|
||||
((uint16)*((uint8 *)b+os+0)<<8|
|
||||
(uint16)*((uint8 *)b+os+1)<<0));
|
||||
}
|
||||
|
||||
__inline VOID SW_ULONG_ASSIGN(void *dst, uint32 src)
|
||||
{
|
||||
*((uint8*)dst+0)=*((uint8*)&src+3);
|
||||
*((uint8*)dst+1)=*((uint8*)&src+2);
|
||||
*((uint8*)dst+2)=*((uint8*)&src+1);
|
||||
*((uint8*)dst+3)=*((uint8*)&src+0);
|
||||
|
||||
}
|
||||
|
||||
#endif /*_USE_SW_FUNCS_*/
|
||||
|
||||
#ifdef WIN_NT_DRIVER
|
||||
|
||||
#define ALLOCATE_MEMORY(dest,type,amount) \
|
||||
(dest)=ExAllocatePool(NonPagedPool,sizeof(type)*(amount));
|
||||
#define ALLOCATE_ZERO_MEMORY(dest,type,amount) \
|
||||
{ \
|
||||
(dest)=ExAllocatePool(NonPagedPool,sizeof(type)*(amount)); \
|
||||
if ((dest)!=NULL) \
|
||||
RtlZeroMemory((dest),sizeof(type)*(amount)); \
|
||||
}
|
||||
|
||||
#define FREE_MEMORY(dest) ExFreePool(dest);
|
||||
#define ZERO_MEMORY(dest,amount) RtlZeroMemory(dest,amount);
|
||||
#define COPY_MEMORY(dest,src,amount) RtlCopyMemory(dest,src,amount);
|
||||
|
||||
#endif /*WIN_NT_DRIVER*/
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -1,192 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#include "tme.h"
|
||||
#include "normal_lookup.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <net/tme/tme.h>
|
||||
#include <net/tme/normal_lookup.h>
|
||||
#else
|
||||
#include <tme/tme.h>
|
||||
#include <tme/normal_lookup.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* lookup in the table, seen as an hash */
|
||||
/* if not found, inserts an element */
|
||||
/* returns TME_TRUE if the entry is found or created, */
|
||||
/* returns TME_FALSE if no more blocks are available */
|
||||
uint32 normal_lut_w_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref)
|
||||
{
|
||||
uint32 i;
|
||||
uint32 tocs=0;
|
||||
uint32 *key32=(uint32*) key;
|
||||
uint32 shrinked_key=0;
|
||||
uint32 index;
|
||||
RECORD *records=(RECORD*)data->lut_base_address;
|
||||
uint8 *offset;
|
||||
uint32 key_len=data->key_len;
|
||||
/*the key is shrinked into a 32-bit value */
|
||||
for (i=0; i<key_len;i++)
|
||||
shrinked_key^=key32[i];
|
||||
/*the first index in the table is calculated*/
|
||||
index=shrinked_key % data->lut_entries;
|
||||
|
||||
while (tocs<=data->filled_entries)
|
||||
{
|
||||
|
||||
if (records[index].block==0)
|
||||
{ /*creation of a new entry*/
|
||||
|
||||
if (data->filled_blocks==data->shared_memory_blocks)
|
||||
{
|
||||
/*no more free blocks*/
|
||||
GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref);
|
||||
data->last_found=NULL;
|
||||
return TME_FALSE;
|
||||
}
|
||||
|
||||
/*offset=absolute pointer to the block associated*/
|
||||
/*with the newly created entry*/
|
||||
offset=data->shared_memory_base_address+
|
||||
data->block_size*data->filled_blocks;
|
||||
|
||||
/*copy the key in the block*/
|
||||
COPY_MEMORY(offset,key32,key_len*4);
|
||||
GET_TIME((struct timeval *)(offset+4*key_len),time_ref);
|
||||
/*assign the block relative offset to the entry, in NBO*/
|
||||
SW_ULONG_ASSIGN(&records[index].block,offset-mem_ex->buffer);
|
||||
|
||||
data->filled_blocks++;
|
||||
|
||||
/*assign the exec function ID to the entry, in NBO*/
|
||||
SW_ULONG_ASSIGN(&records[index].exec_fcn,data->default_exec);
|
||||
data->filled_entries++;
|
||||
|
||||
data->last_found=(uint8*)&records[index];
|
||||
|
||||
return TME_TRUE;
|
||||
}
|
||||
/*offset contains the absolute pointer to the block*/
|
||||
/*associated with the current entry */
|
||||
offset=mem_ex->buffer+SW_ULONG_AT(&records[index].block,0);
|
||||
|
||||
for (i=0; (i<key_len) && (key32[i]==ULONG_AT(offset,i*4)); i++);
|
||||
|
||||
if (i==key_len)
|
||||
{
|
||||
/*key in the block matches the one provided, right entry*/
|
||||
GET_TIME((struct timeval *)(offset+4*key_len),time_ref);
|
||||
data->last_found=(uint8*)&records[index];
|
||||
return TME_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* wrong entry, rehashing */
|
||||
if (IS_DELETABLE(offset+key_len*4,data))
|
||||
{
|
||||
ZERO_MEMORY(offset,data->block_size);
|
||||
COPY_MEMORY(offset,key32,key_len*4);
|
||||
SW_ULONG_ASSIGN(&records[index].exec_fcn,data->default_exec);
|
||||
GET_TIME((struct timeval*)(offset+key_len*4),time_ref);
|
||||
data->last_found=(uint8*)&records[index];
|
||||
return TME_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
index=(index+data->rehashing_value) % data->lut_entries;
|
||||
tocs++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* nothing found, last found= out of lut */
|
||||
GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref);
|
||||
data->last_found=NULL;
|
||||
return TME_FALSE;
|
||||
|
||||
}
|
||||
|
||||
/* lookup in the table, seen as an hash */
|
||||
/* if not found, returns out of count entry index */
|
||||
/* returns TME_TRUE if the entry is found */
|
||||
/* returns TME_FALSE if the entry is not found */
|
||||
uint32 normal_lut_wo_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref)
|
||||
{
|
||||
uint32 i;
|
||||
uint32 tocs=0;
|
||||
uint32 *key32=(uint32*) key;
|
||||
uint32 shrinked_key=0;
|
||||
uint32 index;
|
||||
RECORD *records=(RECORD*)data->lut_base_address;
|
||||
uint8 *offset;
|
||||
uint32 key_len=data->key_len;
|
||||
/*the key is shrinked into a 32-bit value */
|
||||
for (i=0; i<key_len;i++)
|
||||
shrinked_key^=key32[i];
|
||||
/*the first index in the table is calculated*/
|
||||
index=shrinked_key % data->lut_entries;
|
||||
|
||||
while (tocs<=data->filled_entries)
|
||||
{
|
||||
|
||||
if (records[index].block==0)
|
||||
{ /*out of table, insertion is not allowed*/
|
||||
GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref);
|
||||
data->last_found=NULL;
|
||||
return TME_FALSE;
|
||||
}
|
||||
/*offset contains the absolute pointer to the block*/
|
||||
/*associated with the current entry */
|
||||
|
||||
offset=mem_ex->buffer+SW_ULONG_AT(&records[index].block,0);
|
||||
|
||||
for (i=0; (i<key_len) && (key32[i]==ULONG_AT(offset,i*4)); i++);
|
||||
|
||||
if (i==key_len)
|
||||
{
|
||||
/*key in the block matches the one provided, right entry*/
|
||||
GET_TIME((struct timeval *)(offset+4*key_len),time_ref);
|
||||
data->last_found=(uint8*)&records[index];
|
||||
return TME_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*wrong entry, rehashing*/
|
||||
index=(index+data->rehashing_value) % data->lut_entries;
|
||||
tocs++;
|
||||
}
|
||||
}
|
||||
|
||||
/*nothing found, last found= out of lut*/
|
||||
GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref);
|
||||
data->last_found=NULL;
|
||||
return TME_FALSE;
|
||||
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifndef __normal_lookup
|
||||
#define __normal_lookup
|
||||
|
||||
#ifdef WIN32
|
||||
#include "tme.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <net/tme/tme.h>
|
||||
#else
|
||||
#include <tme/tme.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#define NORMAL_LUT_W_INSERT 0x00000000
|
||||
uint32 normal_lut_w_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);
|
||||
#define NORMAL_LUT_WO_INSERT 0x00000001
|
||||
uint32 normal_lut_wo_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);
|
||||
#define DUMMY_INSERT 1234
|
||||
|
||||
#endif
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
#ifndef __NTDDPACKET
|
||||
#define __NTDDPACKET 1
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include "devioctl.h"
|
||||
/*#include <packon.h> */
|
||||
#else
|
||||
#endif
|
||||
|
||||
struct _PACKET_OID_DATA {
|
||||
ULONG Oid;
|
||||
ULONG Length;
|
||||
UCHAR Data[1];
|
||||
};
|
||||
|
||||
typedef struct _PACKET_OID_DATA PACKET_OID_DATA, *PPACKET_OID_DATA;
|
||||
|
||||
/*#include <packoff.h> */
|
||||
#define FILE_DEVICE_PROTOCOL 0x8000
|
||||
#define IOCTL_PROTOCOL_QUERY_OID CTL_CODE(FILE_DEVICE_PROTOCOL, 0 , METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_PROTOCOL_SET_OID CTL_CODE(FILE_DEVICE_PROTOCOL, 1 , METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_PROTOCOL_STATISTICS CTL_CODE(FILE_DEVICE_PROTOCOL, 2 , METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_PROTOCOL_RESET CTL_CODE(FILE_DEVICE_PROTOCOL, 3 , METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_PROTOCOL_READ CTL_CODE(FILE_DEVICE_PROTOCOL, 4 , METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_PROTOCOL_WRITE CTL_CODE(FILE_DEVICE_PROTOCOL, 5 , METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_PROTOCOL_MACNAME CTL_CODE(FILE_DEVICE_PROTOCOL, 6 , METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_OPEN CTL_CODE(FILE_DEVICE_PROTOCOL, 7 , METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_CLOSE CTL_CODE(FILE_DEVICE_PROTOCOL, 8 , METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#endif
|
|
@ -1,682 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2000
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include "ntddk.h"
|
||||
#include "ntiologc.h"
|
||||
#include "ndis.h"
|
||||
#else
|
||||
#include <ddk/ntddk.h>
|
||||
#include <net/ndis.h>
|
||||
#endif
|
||||
#include "debug.h"
|
||||
#include "packet.h"
|
||||
|
||||
static NDIS_MEDIUM MediumArray[] = {
|
||||
NdisMedium802_3,
|
||||
NdisMediumWan,
|
||||
NdisMediumFddi,
|
||||
NdisMediumArcnet878_2,
|
||||
NdisMediumAtm,
|
||||
NdisMedium802_5
|
||||
};
|
||||
|
||||
#define NUM_NDIS_MEDIA (sizeof MediumArray / sizeof MediumArray[0])
|
||||
|
||||
ULONG NamedEventsCounter=0;
|
||||
|
||||
//Itoa. Replaces the buggy RtlIntegerToUnicodeString
|
||||
void PacketItoa(UINT n,PUCHAR buf){
|
||||
int i;
|
||||
|
||||
for(i=0;i<20;i+=2){
|
||||
buf[18-i]=(n%10)+48;
|
||||
buf[19-i]=0;
|
||||
n/=10;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// Global start time. Used as an absolute reference for timestamp conversion.
|
||||
struct time_conv G_Start_Time = {
|
||||
0,
|
||||
{0, 0},
|
||||
};
|
||||
|
||||
UINT n_Opened_Instances = 0;
|
||||
|
||||
NDIS_SPIN_LOCK Opened_Instances_Lock;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
NTSTATUS NPF_Open(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
||||
{
|
||||
|
||||
PDEVICE_EXTENSION DeviceExtension;
|
||||
|
||||
POPEN_INSTANCE Open;
|
||||
|
||||
PIO_STACK_LOCATION IrpSp;
|
||||
|
||||
NDIS_STATUS Status;
|
||||
NDIS_STATUS ErrorStatus;
|
||||
UINT i;
|
||||
PUCHAR tpointer;
|
||||
PLIST_ENTRY PacketListEntry;
|
||||
PCHAR EvName;
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: OpenAdapter\n");)
|
||||
|
||||
DeviceExtension = DeviceObject->DeviceExtension;
|
||||
|
||||
|
||||
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
// allocate some memory for the open structure
|
||||
#define NPF_TAG_OPENSTRUCT TAG('0', 'O', 'W', 'A')
|
||||
Open=ExAllocatePoolWithTag(NonPagedPool, sizeof(OPEN_INSTANCE), NPF_TAG_OPENSTRUCT);
|
||||
|
||||
|
||||
if (Open==NULL) {
|
||||
// no memory
|
||||
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
RtlZeroMemory(
|
||||
Open,
|
||||
sizeof(OPEN_INSTANCE)
|
||||
);
|
||||
|
||||
|
||||
#define NPF_TAG_EVNAME TAG('1', 'O', 'W', 'A')
|
||||
EvName=ExAllocatePoolWithTag(NonPagedPool, sizeof(L"\\BaseNamedObjects\\NPF0000000000"), NPF_TAG_EVNAME);
|
||||
|
||||
if (EvName==NULL) {
|
||||
// no memory
|
||||
ExFreePool(Open);
|
||||
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
// Save or open here
|
||||
IrpSp->FileObject->FsContext=Open;
|
||||
|
||||
Open->DeviceExtension=DeviceExtension;
|
||||
|
||||
|
||||
// Save the Irp here for the completeion routine to retrieve
|
||||
Open->OpenCloseIrp=Irp;
|
||||
|
||||
// Allocate a packet pool for our xmit and receive packets
|
||||
NdisAllocatePacketPool(
|
||||
&Status,
|
||||
&Open->PacketPool,
|
||||
TRANSMIT_PACKETS,
|
||||
sizeof(PACKET_RESERVED));
|
||||
|
||||
|
||||
if (Status != NDIS_STATUS_SUCCESS) {
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: Failed to allocate packet pool\n");)
|
||||
|
||||
ExFreePool(Open);
|
||||
ExFreePool(EvName);
|
||||
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
|
||||
RtlCopyBytes(EvName,L"\\BaseNamedObjects\\NPF0000000000",sizeof(L"\\BaseNamedObjects\\NPF0000000000"));
|
||||
|
||||
//Create the string containing the name of the read event
|
||||
RtlInitUnicodeString(&Open->ReadEventName,(PCWSTR) EvName);
|
||||
|
||||
PacketItoa(NamedEventsCounter,(PUCHAR)(Open->ReadEventName.Buffer+21));
|
||||
|
||||
InterlockedIncrement(&NamedEventsCounter);
|
||||
|
||||
IF_LOUD(DbgPrint("\nCreated the named event for the read; name=%ws, counter=%d\n", Open->ReadEventName.Buffer,NamedEventsCounter-1);)
|
||||
|
||||
//allocate the event objects
|
||||
Open->ReadEvent=IoCreateNotificationEvent(&Open->ReadEventName,&Open->ReadEventHandle);
|
||||
if(Open->ReadEvent==NULL){
|
||||
ExFreePool(Open);
|
||||
ExFreePool(EvName);
|
||||
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
KeInitializeEvent(Open->ReadEvent, NotificationEvent, FALSE);
|
||||
KeClearEvent(Open->ReadEvent);
|
||||
NdisInitializeEvent(&Open->WriteEvent);
|
||||
NdisInitializeEvent(&Open->IOEvent);
|
||||
NdisInitializeEvent(&Open->DumpEvent);
|
||||
NdisInitializeEvent(&Open->IOEvent);
|
||||
NdisAllocateSpinLock(&Open->machine_lock);
|
||||
|
||||
|
||||
// list to hold irp's want to reset the adapter
|
||||
InitializeListHead(&Open->ResetIrpList);
|
||||
|
||||
|
||||
// Initialize the request list
|
||||
KeInitializeSpinLock(&Open->RequestSpinLock);
|
||||
InitializeListHead(&Open->RequestList);
|
||||
|
||||
// Initializes the extended memory of the NPF machine
|
||||
#define NPF_TAG_MACHINE TAG('2', 'O', 'W', 'A')
|
||||
Open->mem_ex.buffer = ExAllocatePoolWithTag(NonPagedPool, DEFAULT_MEM_EX_SIZE, NPF_TAG_MACHINE);
|
||||
if((Open->mem_ex.buffer) == NULL)
|
||||
{
|
||||
// no memory
|
||||
ExFreePool(Open);
|
||||
ExFreePool(EvName);
|
||||
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
Open->mem_ex.size = DEFAULT_MEM_EX_SIZE;
|
||||
RtlZeroMemory(Open->mem_ex.buffer, DEFAULT_MEM_EX_SIZE);
|
||||
|
||||
//
|
||||
// Initialize the open instance
|
||||
//
|
||||
Open->BufSize = 0;
|
||||
Open->Buffer = NULL;
|
||||
Open->Bhead = 0;
|
||||
Open->Btail = 0;
|
||||
(INT)Open->BLastByte = -1;
|
||||
Open->Dropped = 0; //reset the dropped packets counter
|
||||
Open->Received = 0; //reset the received packets counter
|
||||
Open->Accepted = 0; //reset the accepted packets counter
|
||||
Open->bpfprogram = NULL; //reset the filter
|
||||
Open->mode = MODE_CAPT;
|
||||
Open->Nbytes.QuadPart = 0;
|
||||
Open->Npackets.QuadPart = 0;
|
||||
Open->Nwrites = 1;
|
||||
Open->Multiple_Write_Counter = 0;
|
||||
Open->MinToCopy = 0;
|
||||
Open->TimeOut.QuadPart = (LONGLONG)1;
|
||||
Open->Bound = TRUE;
|
||||
Open->DumpFileName.Buffer = NULL;
|
||||
Open->DumpFileHandle = NULL;
|
||||
Open->tme.active = TME_NONE_ACTIVE;
|
||||
Open->DumpLimitReached = FALSE;
|
||||
Open->MaxFrameSize = 0;
|
||||
|
||||
//allocate the spinlock for the statistic counters
|
||||
NdisAllocateSpinLock(&Open->CountersLock);
|
||||
|
||||
//allocate the spinlock for the buffer pointers
|
||||
NdisAllocateSpinLock(&Open->BufLock);
|
||||
|
||||
//
|
||||
// link up the request stored in our open block
|
||||
//
|
||||
for (i=0;i<MAX_REQUESTS;i++) {
|
||||
ExInterlockedInsertTailList(
|
||||
&Open->RequestList,
|
||||
&Open->Requests[i].ListElement,
|
||||
&Open->RequestSpinLock);
|
||||
|
||||
}
|
||||
|
||||
|
||||
IoMarkIrpPending(Irp);
|
||||
|
||||
//
|
||||
// Try to open the MAC
|
||||
//
|
||||
IF_LOUD(DbgPrint("NPF: Openinig the device %ws, BindingContext=%d\n",DeviceExtension->AdapterName.Buffer, Open);)
|
||||
|
||||
NdisOpenAdapter(
|
||||
&Status,
|
||||
&ErrorStatus,
|
||||
&Open->AdapterHandle,
|
||||
&Open->Medium,
|
||||
MediumArray,
|
||||
NUM_NDIS_MEDIA,
|
||||
DeviceExtension->NdisProtocolHandle,
|
||||
Open,
|
||||
&DeviceExtension->AdapterName,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: Opened the device, Status=%x\n",Status);)
|
||||
|
||||
if (Status != NDIS_STATUS_PENDING)
|
||||
{
|
||||
NPF_OpenAdapterComplete(Open,Status,NDIS_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
return(STATUS_PENDING);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
VOID NPF_OpenAdapterComplete(
|
||||
IN NDIS_HANDLE ProtocolBindingContext,
|
||||
IN NDIS_STATUS Status,
|
||||
IN NDIS_STATUS OpenErrorStatus)
|
||||
{
|
||||
|
||||
PIRP Irp;
|
||||
POPEN_INSTANCE Open;
|
||||
PLIST_ENTRY RequestListEntry;
|
||||
PINTERNAL_REQUEST MaxSizeReq;
|
||||
NDIS_STATUS ReqStatus;
|
||||
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: OpenAdapterComplete\n");)
|
||||
|
||||
Open= (POPEN_INSTANCE)ProtocolBindingContext;
|
||||
|
||||
//
|
||||
// get the open irp
|
||||
//
|
||||
Irp=Open->OpenCloseIrp;
|
||||
|
||||
if (Status != NDIS_STATUS_SUCCESS) {
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: OpenAdapterComplete-FAILURE\n");)
|
||||
|
||||
NdisFreePacketPool(Open->PacketPool);
|
||||
|
||||
//free mem_ex
|
||||
Open->mem_ex.size = 0;
|
||||
if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer);
|
||||
|
||||
ExFreePool(Open->ReadEventName.Buffer);
|
||||
|
||||
ZwClose(Open->ReadEventHandle);
|
||||
|
||||
|
||||
ExFreePool(Open);
|
||||
}
|
||||
else {
|
||||
NdisAcquireSpinLock(&Opened_Instances_Lock);
|
||||
n_Opened_Instances++;
|
||||
NdisReleaseSpinLock(&Opened_Instances_Lock);
|
||||
|
||||
IF_LOUD(DbgPrint("Opened Instances:%d", n_Opened_Instances);)
|
||||
|
||||
// Get the absolute value of the system boot time.
|
||||
// This is used for timestamp conversion.
|
||||
TIME_SYNCHRONIZE(&G_Start_Time);
|
||||
|
||||
// Extract a request from the list of free ones
|
||||
RequestListEntry=ExInterlockedRemoveHeadList(&Open->RequestList, &Open->RequestSpinLock);
|
||||
|
||||
if (RequestListEntry == NULL)
|
||||
{
|
||||
|
||||
Open->MaxFrameSize = 1514; // Assume Ethernet
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
MaxSizeReq = CONTAINING_RECORD(RequestListEntry, INTERNAL_REQUEST, ListElement);
|
||||
MaxSizeReq->Irp = Irp;
|
||||
MaxSizeReq->Internal = TRUE;
|
||||
|
||||
|
||||
MaxSizeReq->Request.RequestType = NdisRequestQueryInformation;
|
||||
MaxSizeReq->Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_MAXIMUM_TOTAL_SIZE;
|
||||
|
||||
|
||||
MaxSizeReq->Request.DATA.QUERY_INFORMATION.InformationBuffer = &Open->MaxFrameSize;
|
||||
MaxSizeReq->Request.DATA.QUERY_INFORMATION.InformationBufferLength = 4;
|
||||
|
||||
// submit the request
|
||||
NdisRequest(
|
||||
&ReqStatus,
|
||||
Open->AdapterHandle,
|
||||
&MaxSizeReq->Request);
|
||||
|
||||
|
||||
if (ReqStatus != NDIS_STATUS_PENDING) {
|
||||
NPF_RequestComplete(Open, &MaxSizeReq->Request, ReqStatus);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
NTSTATUS
|
||||
NPF_Close(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
|
||||
{
|
||||
|
||||
POPEN_INSTANCE Open;
|
||||
NDIS_STATUS Status;
|
||||
PIO_STACK_LOCATION IrpSp;
|
||||
LARGE_INTEGER ThreadDelay;
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: CloseAdapter\n");)
|
||||
|
||||
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
Open=IrpSp->FileObject->FsContext;
|
||||
|
||||
// Reset the buffer size. This tells the dump thread to stop.
|
||||
Open->BufSize = 0;
|
||||
|
||||
if( Open->Bound == FALSE){
|
||||
|
||||
NdisWaitEvent(&Open->IOEvent,10000);
|
||||
|
||||
// Free the filter if it's present
|
||||
if(Open->bpfprogram != NULL)
|
||||
ExFreePool(Open->bpfprogram);
|
||||
|
||||
// Free the jitted filter if it's present
|
||||
if(Open->Filter != NULL)
|
||||
BPF_Destroy_JIT_Filter(Open->Filter);
|
||||
|
||||
//free the buffer
|
||||
Open->BufSize=0;
|
||||
if(Open->Buffer != NULL)ExFreePool(Open->Buffer);
|
||||
|
||||
//free mem_ex
|
||||
Open->mem_ex.size = 0;
|
||||
if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer);
|
||||
|
||||
NdisFreePacketPool(Open->PacketPool);
|
||||
|
||||
// Free the string with the name of the dump file
|
||||
if(Open->DumpFileName.Buffer!=NULL)
|
||||
ExFreePool(Open->DumpFileName.Buffer);
|
||||
|
||||
ExFreePool(Open->ReadEventName.Buffer);
|
||||
ExFreePool(Open);
|
||||
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
// Unfreeze the consumer
|
||||
if(Open->mode & MODE_DUMP)
|
||||
NdisSetEvent(&Open->DumpEvent);
|
||||
else
|
||||
KeSetEvent(Open->ReadEvent,0,FALSE);
|
||||
|
||||
// Save the IRP
|
||||
Open->OpenCloseIrp = Irp;
|
||||
|
||||
IoMarkIrpPending(Irp);
|
||||
|
||||
// If this instance is in dump mode, complete the dump and close the file
|
||||
if((Open->mode & MODE_DUMP) && Open->DumpFileHandle != NULL){
|
||||
NTSTATUS wres;
|
||||
|
||||
ThreadDelay.QuadPart = -50000000;
|
||||
// Wait the completion of the thread
|
||||
wres = KeWaitForSingleObject(Open->DumpThreadObject,
|
||||
UserRequest,
|
||||
KernelMode,
|
||||
TRUE,
|
||||
&ThreadDelay);
|
||||
|
||||
ObDereferenceObject(Open->DumpThreadObject);
|
||||
|
||||
|
||||
// Flush and close the dump file
|
||||
NPF_CloseDumpFile(Open);
|
||||
}
|
||||
|
||||
// Destroy the read Event
|
||||
ZwClose(Open->ReadEventHandle);
|
||||
|
||||
// Close the adapter
|
||||
NdisCloseAdapter(
|
||||
&Status,
|
||||
Open->AdapterHandle
|
||||
);
|
||||
|
||||
if (Status != NDIS_STATUS_PENDING) {
|
||||
|
||||
NPF_CloseAdapterComplete(
|
||||
Open,
|
||||
Status
|
||||
);
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
return(STATUS_PENDING);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
VOID
|
||||
NPF_CloseAdapterComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status)
|
||||
{
|
||||
POPEN_INSTANCE Open;
|
||||
PIRP Irp;
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: CloseAdapterComplete\n");)
|
||||
|
||||
Open= (POPEN_INSTANCE)ProtocolBindingContext;
|
||||
|
||||
// free the allocated structures only if the instance is still bound to the adapter
|
||||
if(Open->Bound == TRUE){
|
||||
|
||||
// Free the filter if it's present
|
||||
if(Open->bpfprogram != NULL)
|
||||
ExFreePool(Open->bpfprogram);
|
||||
|
||||
// Free the jitted filter if it's present
|
||||
if(Open->Filter != NULL)
|
||||
BPF_Destroy_JIT_Filter(Open->Filter);
|
||||
|
||||
//free the buffer
|
||||
Open->BufSize = 0;
|
||||
if(Open->Buffer!=NULL)ExFreePool(Open->Buffer);
|
||||
|
||||
//free mem_ex
|
||||
Open->mem_ex.size = 0;
|
||||
if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer);
|
||||
|
||||
NdisFreePacketPool(Open->PacketPool);
|
||||
|
||||
Irp=Open->OpenCloseIrp;
|
||||
|
||||
// Free the string with the name of the dump file
|
||||
if(Open->DumpFileName.Buffer!=NULL)
|
||||
ExFreePool(Open->DumpFileName.Buffer);
|
||||
|
||||
ExFreePool(Open->ReadEventName.Buffer);
|
||||
ExFreePool(Open);
|
||||
|
||||
// Complete the request only if the instance is still bound to the adapter
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = 0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
}
|
||||
else
|
||||
NdisSetEvent(&Open->IOEvent);
|
||||
|
||||
// Decrease the counter of open instances
|
||||
NdisAcquireSpinLock(&Opened_Instances_Lock);
|
||||
n_Opened_Instances--;
|
||||
NdisReleaseSpinLock(&Opened_Instances_Lock);
|
||||
|
||||
IF_LOUD(DbgPrint("Opened Instances:%d", n_Opened_Instances);)
|
||||
|
||||
if(n_Opened_Instances == 0){
|
||||
// Force a synchronization at the next NPF_Open().
|
||||
// This hopefully avoids the synchronization issues caused by hibernation or standby.
|
||||
TIME_DESYNCHRONIZE(&G_Start_Time);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
#ifdef NDIS50
|
||||
NDIS_STATUS
|
||||
NPF_PowerChange(IN NDIS_HANDLE ProtocolBindingContext, IN PNET_PNP_EVENT pNetPnPEvent)
|
||||
{
|
||||
IF_LOUD(DbgPrint("NPF: PowerChange\n");)
|
||||
|
||||
TIME_DESYNCHRONIZE(&G_Start_Time);
|
||||
|
||||
TIME_SYNCHRONIZE(&G_Start_Time);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
VOID
|
||||
NPF_BindAdapter(
|
||||
OUT PNDIS_STATUS Status,
|
||||
IN NDIS_HANDLE BindContext,
|
||||
IN PNDIS_STRING DeviceName,
|
||||
IN PVOID SystemSpecific1,
|
||||
IN PVOID SystemSpecific2
|
||||
)
|
||||
{
|
||||
IF_LOUD(DbgPrint("NPF: NPF_BindAdapter\n");)
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
VOID
|
||||
NPF_UnbindAdapter(
|
||||
OUT PNDIS_STATUS Status,
|
||||
IN NDIS_HANDLE ProtocolBindingContext,
|
||||
IN NDIS_HANDLE UnbindContext
|
||||
)
|
||||
{
|
||||
POPEN_INSTANCE Open =(POPEN_INSTANCE)ProtocolBindingContext;
|
||||
NDIS_STATUS lStatus;
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: NPF_UnbindAdapter\n");)
|
||||
|
||||
// Reset the buffer size. This tells the dump thread to stop.
|
||||
Open->BufSize=0;
|
||||
|
||||
NdisResetEvent(&Open->IOEvent);
|
||||
|
||||
// This open instance is no more bound to the adapter, set Bound to False
|
||||
InterlockedExchange( (PLONG) &Open->Bound, FALSE );
|
||||
|
||||
// Awake a possible pending read on this instance
|
||||
if(Open->mode & MODE_DUMP)
|
||||
NdisSetEvent(&Open->DumpEvent);
|
||||
else
|
||||
KeSetEvent(Open->ReadEvent,0,FALSE);
|
||||
|
||||
// If this instance is in dump mode, complete the dump and close the file
|
||||
if((Open->mode & MODE_DUMP) && Open->DumpFileHandle != NULL)
|
||||
NPF_CloseDumpFile(Open);
|
||||
|
||||
// Destroy the read Event
|
||||
ZwClose(Open->ReadEventHandle);
|
||||
|
||||
// close the adapter
|
||||
NdisCloseAdapter(
|
||||
&lStatus,
|
||||
Open->AdapterHandle
|
||||
);
|
||||
|
||||
if (lStatus != NDIS_STATUS_PENDING) {
|
||||
|
||||
NPF_CloseAdapterComplete(
|
||||
Open,
|
||||
lStatus
|
||||
);
|
||||
|
||||
*Status = NDIS_STATUS_SUCCESS;
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
*Status = NDIS_STATUS_SUCCESS;
|
||||
return;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
VOID
|
||||
NPF_ResetComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status)
|
||||
|
||||
{
|
||||
POPEN_INSTANCE Open;
|
||||
PIRP Irp;
|
||||
|
||||
PLIST_ENTRY ResetListEntry;
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: PacketResetComplte\n");)
|
||||
|
||||
Open= (POPEN_INSTANCE)ProtocolBindingContext;
|
||||
|
||||
|
||||
//
|
||||
// remove the reset IRP from the list
|
||||
//
|
||||
ResetListEntry=ExInterlockedRemoveHeadList(
|
||||
&Open->ResetIrpList,
|
||||
&Open->RequestSpinLock
|
||||
);
|
||||
|
||||
#if DBG
|
||||
if (ResetListEntry == NULL) {
|
||||
DbgBreakPoint();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
Irp=CONTAINING_RECORD(ResetListEntry,IRP,Tail.Overlay.ListEntry);
|
||||
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: PacketResetComplte exit\n");)
|
||||
|
||||
return;
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,8 +0,0 @@
|
|||
; packet capture driver - ReactOS Operating System
|
||||
|
||||
LIBRARY PACKET.SYS
|
||||
|
||||
EXPORTS
|
||||
DriverEntry@8
|
||||
|
||||
; EOF
|
|
@ -1,960 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2000
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/** @ingroup NPF
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup NPF_include NPF structures and definitions
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef __PACKET_INCLUDE______
|
||||
#define __PACKET_INCLUDE______
|
||||
|
||||
#define NTKERNEL ///< Forces the compilation of the jitter with kernel calls
|
||||
|
||||
#ifdef __GNUC__
|
||||
#undef EXIT_SUCCESS
|
||||
#undef EXIT_FAILURE
|
||||
#define UNICODE_NULL ((WCHAR)0) // winnt
|
||||
#include "win_bpf.h"
|
||||
#include <internal/ps.h>
|
||||
#endif
|
||||
|
||||
#include "jitter.h"
|
||||
#include "tme.h"
|
||||
|
||||
#define MAX_REQUESTS 32 ///< Maximum number of simultaneous IOCTL requests.
|
||||
|
||||
#define Packet_ALIGNMENT sizeof(int) ///< Alignment macro. Defines the alignment size.
|
||||
#define Packet_WORDALIGN(x) (((x)+(Packet_ALIGNMENT-1))&~(Packet_ALIGNMENT-1)) ///< Alignment macro. Rounds up to the next
|
||||
///< even multiple of Packet_ALIGNMENT.
|
||||
|
||||
|
||||
/***************************/
|
||||
/* IOCTLs */
|
||||
/***************************/
|
||||
|
||||
/*!
|
||||
\brief IOCTL code: set kernel buffer size.
|
||||
|
||||
This IOCTL is used to set a new size of the circular buffer associated with an instance of NPF.
|
||||
When a BIOCSETBUFFERSIZE command is received, the driver frees the old buffer, allocates the new one
|
||||
and resets all the parameters associated with the buffer in the OPEN_INSTANCE structure. The currently
|
||||
buffered packets are lost.
|
||||
*/
|
||||
#define BIOCSETBUFFERSIZE 9592
|
||||
|
||||
/*!
|
||||
\brief IOCTL code: set packet filtering program.
|
||||
|
||||
This IOCTL sets a new packet filter in the driver. Before allocating any memory for the new filter, the
|
||||
bpf_validate() function is called to check the correctness of the filter. If this function returns TRUE,
|
||||
the filter is copied to the driver's memory, its address is stored in the bpfprogram field of the
|
||||
OPEN_INSTANCE structure associated with current instance of the driver, and the filter will be applied to
|
||||
every incoming packet. This command also empties the circular buffer used by current instance
|
||||
to store packets. This is done to avoid the presence in the buffer of packets that do not match the filter.
|
||||
*/
|
||||
#define BIOCSETF 9030
|
||||
|
||||
/*!
|
||||
\brief IOCTL code: get the capture stats
|
||||
|
||||
This command returns to the application the number of packets received and the number of packets dropped by
|
||||
an instance of the driver.
|
||||
*/
|
||||
#define BIOCGSTATS 9031
|
||||
|
||||
/*!
|
||||
\brief IOCTL code: set the read timeout
|
||||
|
||||
This command sets the maximum timeout after which a read is released, also if no data packets were received.
|
||||
*/
|
||||
#define BIOCSRTIMEOUT 7416
|
||||
|
||||
/*!
|
||||
\brief IOCTL code: set working mode
|
||||
|
||||
This IOCTL can be used to set the working mode of a NPF instance. The new mode, received by the driver in the
|
||||
buffer associated with the IOCTL command, can be #MODE_CAPT for capture mode (the default), #MODE_STAT for
|
||||
statistical mode or #MODE_DUMP for dump mode.
|
||||
*/
|
||||
#define BIOCSMODE 7412
|
||||
|
||||
/*!
|
||||
\brief IOCTL code: set number of physical repetions of every packet written by the app
|
||||
|
||||
Sets the number of times a single write call must be repeated. This command sets the OPEN_INSTANCE::Nwrites
|
||||
member, and is used to implement the 'multiple write' feature of the driver.
|
||||
*/
|
||||
#define BIOCSWRITEREP 7413
|
||||
|
||||
/*!
|
||||
\brief IOCTL code: set minimum amount of data in the kernel buffer that unlocks a read call
|
||||
|
||||
This command sets the OPEN_INSTANCE::MinToCopy member.
|
||||
*/
|
||||
#define BIOCSMINTOCOPY 7414
|
||||
|
||||
/*!
|
||||
\brief IOCTL code: set an OID value
|
||||
|
||||
This IOCTL is used to perform an OID set operation on the NIC driver.
|
||||
*/
|
||||
#define BIOCSETOID 2147483648U
|
||||
|
||||
/*!
|
||||
\brief IOCTL code: get an OID value
|
||||
|
||||
This IOCTL is used to perform an OID get operation on the NIC driver.
|
||||
*/
|
||||
#define BIOCQUERYOID 2147483652U
|
||||
|
||||
/*!
|
||||
\brief IOCTL code: set the name of a the file used by kernel dump mode
|
||||
|
||||
This command opens a file whose name is contained in the IOCTL buffer and associates it with current NPf instance.
|
||||
The dump thread uses it to copy the content of the circular buffer to file.
|
||||
If a file was already opened, the driver closes it before opening the new one.
|
||||
*/
|
||||
#define BIOCSETDUMPFILENAME 9029
|
||||
|
||||
/*!
|
||||
\brief IOCTL code: get the name of the event that the driver signals when some data is present in the buffer
|
||||
|
||||
Command used by the application to retrieve the name of the global event associated with a NPF instance.
|
||||
The event is signaled by the driver when the kernel buffer contains enough data for a transfer.
|
||||
*/
|
||||
#define BIOCGEVNAME 7415
|
||||
|
||||
/*!
|
||||
\brief IOCTL code: Send a buffer containing multiple packets to the network, ignoring the timestamps.
|
||||
|
||||
Command used to send a buffer of packets in a single system call. Every packet in the buffer is preceded by
|
||||
a sf_pkthdr structure. The timestamps of the packets are ignored, i.e. the packets are sent as fast as
|
||||
possible. The NPF_BufferedWrite() function is invoked to send the packets.
|
||||
*/
|
||||
#define BIOCSENDPACKETSNOSYNC 9032
|
||||
|
||||
/*!
|
||||
\brief IOCTL code: Send a buffer containing multiple packets to the network, considering the timestamps.
|
||||
|
||||
Command used to send a buffer of packets in a single system call. Every packet in the buffer is preceded by
|
||||
a sf_pkthdr structure. The timestamps of the packets are used to synchronize the write, i.e. the packets
|
||||
are sent to the network respecting the intervals specified in the sf_pkthdr structure assiciated with each
|
||||
packet. NPF_BufferedWrite() function is invoked to send the packets.
|
||||
*/
|
||||
#define BIOCSENDPACKETSSYNC 9033
|
||||
|
||||
/*!
|
||||
\brief IOCTL code: Set the dump file limits.
|
||||
|
||||
This IOCTL sets the limits (maximum size and maximum number of packets) of the dump file created when the
|
||||
driver works in dump mode.
|
||||
*/
|
||||
#define BIOCSETDUMPLIMITS 9034
|
||||
|
||||
/*!
|
||||
\brief IOCTL code: Get the status of the kernel dump process.
|
||||
|
||||
This command returns TRUE if the kernel dump is ended, i.e if one of the limits set with BIOCSETDUMPLIMITS
|
||||
(amount of bytes or number of packets) has been reached.
|
||||
*/
|
||||
#define BIOCISDUMPENDED 7411
|
||||
|
||||
// Working modes
|
||||
#define MODE_CAPT 0x0 ///< Capture working mode
|
||||
#define MODE_STAT 0x1 ///< Statistical working mode
|
||||
#define MODE_MON 0x2 ///< Kernel monitoring mode
|
||||
#define MODE_DUMP 0x10 ///< Kernel dump working mode
|
||||
|
||||
|
||||
#define IMMEDIATE 1 ///< Immediate timeout. Forces a read call to return immediately.
|
||||
|
||||
|
||||
// The following definitions are used to provide compatibility
|
||||
// of the dump files with the ones of libpcap
|
||||
#define TCPDUMP_MAGIC 0xa1b2c3d4 ///< Libpcap magic number. Used by programs like tcpdump to recognize a driver's generated dump file.
|
||||
#define PCAP_VERSION_MAJOR 2 ///< Major libpcap version of the dump file. Used by programs like tcpdump to recognize a driver's generated dump file.
|
||||
#define PCAP_VERSION_MINOR 4 ///< Minor libpcap version of the dump file. Used by programs like tcpdump to recognize a driver's generated dump file.
|
||||
|
||||
/*!
|
||||
\brief Header of a libpcap dump file.
|
||||
|
||||
Used when a driver instance is set in dump mode to create a libpcap-compatible file.
|
||||
*/
|
||||
struct packet_file_header
|
||||
{
|
||||
UINT magic; ///< Libpcap magic number
|
||||
USHORT version_major; ///< Libpcap major version
|
||||
USHORT version_minor; ///< Libpcap minor version
|
||||
UINT thiszone; ///< Gmt to local correction
|
||||
UINT sigfigs; ///< Accuracy of timestamps
|
||||
UINT snaplen; ///< Length of the max saved portion of each packet
|
||||
UINT linktype; ///< Data link type (DLT_*). See win_bpf.h for details.
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Header associated to a packet in the driver's buffer when the driver is in dump mode.
|
||||
Similar to the bpf_hdr structure, but simpler.
|
||||
*/
|
||||
struct sf_pkthdr {
|
||||
struct timeval ts; ///< time stamp
|
||||
UINT caplen; ///< Length of captured portion. The captured portion can be different from
|
||||
///< the original packet, because it is possible (with a proper filter) to
|
||||
///< instruct the driver to capture only a portion of the packets.
|
||||
UINT len; ///< Length of the original packet (off wire).
|
||||
};
|
||||
|
||||
/*!
|
||||
\brief Stores an OID request.
|
||||
|
||||
This structure is used by the driver to perform OID query or set operations on the underlying NIC driver.
|
||||
The OID operations be performed usually only by network drivers, but NPF exports this mechanism to user-level
|
||||
applications through an IOCTL interface. The driver uses this structure to wrap a NDIS_REQUEST structure.
|
||||
This allows to handle correctly the callback structure of NdisRequest(), handling multiple requests and
|
||||
maintaining information about the IRPs to complete.
|
||||
*/
|
||||
typedef struct _INTERNAL_REQUEST {
|
||||
LIST_ENTRY ListElement; ///< Used to handle lists of requests.
|
||||
PIRP Irp; ///< Irp that performed the request
|
||||
BOOLEAN Internal; ///< True if the request is for internal use of npf.sys. False if the request is performed by the user through an IOCTL.
|
||||
NDIS_REQUEST Request; ///< The structure with the actual request, that will be passed to NdisRequest().
|
||||
} INTERNAL_REQUEST, *PINTERNAL_REQUEST;
|
||||
|
||||
/*!
|
||||
\brief Contains a NDIS packet.
|
||||
|
||||
The driver uses this structure to wrap a NDIS_PACKET structure.
|
||||
This allows to handle correctly the callback structure of NdisTransferData(), handling multiple requests and
|
||||
maintaining information about the IRPs to complete.
|
||||
*/
|
||||
typedef struct _PACKET_RESERVED {
|
||||
LIST_ENTRY ListElement; ///< Used to handle lists of packets.
|
||||
PIRP Irp; ///< Irp that performed the request
|
||||
PMDL pMdl; ///< MDL mapping the buffer of the packet.
|
||||
BOOLEAN FreeBufAfterWrite; ///< True if the memory buffer associated with the packet must be freed
|
||||
///< after a call to NdisSend().
|
||||
} PACKET_RESERVED, *PPACKET_RESERVED;
|
||||
|
||||
#define RESERVED(_p) ((PPACKET_RESERVED)((_p)->ProtocolReserved)) ///< Macro to obtain a NDIS_PACKET from a PACKET_RESERVED
|
||||
|
||||
/*!
|
||||
\brief Port device extension.
|
||||
|
||||
Structure containing some data relative to every adapter on which NPF is bound.
|
||||
*/
|
||||
typedef struct _DEVICE_EXTENSION {
|
||||
NDIS_HANDLE NdisProtocolHandle; ///< NDIS handle of NPF.
|
||||
NDIS_STRING AdapterName; ///< Name of the adapter.
|
||||
PWSTR ExportString; ///< Name of the exported device, i.e. name that the applications will use
|
||||
///< to open this adapter through WinPcap.
|
||||
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;
|
||||
|
||||
/*!
|
||||
\brief Contains the state of a running instance of the NPF driver.
|
||||
|
||||
This is the most important structure of NPF: it is used by almost all the functions of the driver. An
|
||||
_OPEN_INSTANCE structure is associated with every user-level session, allowing concurrent access
|
||||
to the driver.
|
||||
*/
|
||||
typedef struct _OPEN_INSTANCE
|
||||
{
|
||||
PDEVICE_EXTENSION DeviceExtension; ///< Pointer to the _DEVICE_EXTENSION structure of the device on which
|
||||
///< the instance is bound.
|
||||
NDIS_HANDLE AdapterHandle; ///< NDIS idetifier of the adapter used by this instance.
|
||||
UINT Medium; ///< Type of physical medium the underlying NDIS driver uses. See the
|
||||
///< documentation of NdisOpenAdapter in the MS DDK for details.
|
||||
NDIS_HANDLE PacketPool; ///< Pool of NDIS_PACKET structures used to transfer the packets from and to the NIC driver.
|
||||
PIRP OpenCloseIrp; ///< Pointer used to store the open/close IRP requests and provide them to the
|
||||
///< callbacks of NDIS.
|
||||
KSPIN_LOCK RequestSpinLock; ///< SpinLock used to synchronize the OID requests.
|
||||
LIST_ENTRY RequestList; ///< List of pending OID requests.
|
||||
LIST_ENTRY ResetIrpList; ///< List of pending adapter reset requests.
|
||||
INTERNAL_REQUEST Requests[MAX_REQUESTS]; ///< Array of structures that wrap every single OID request.
|
||||
PMDL BufferMdl; ///< Pointer to a Memory descriptor list (MDL) that maps the circular buffer's memory.
|
||||
PKEVENT ReadEvent; ///< Pointer to the event on which the read calls on this instance must wait.
|
||||
HANDLE ReadEventHandle; ///< Handle of the event on which the read calls on this instance must wait.
|
||||
UNICODE_STRING ReadEventName; ///< Name of the event on which the read calls on this instance must wait.
|
||||
///< The event is created with a name, so it can be used at user level to know when it
|
||||
///< is possible to access the driver without being blocked. This fiels stores the name
|
||||
///< that and is used by the BIOCGEVNAME IOCTL call.
|
||||
INT Received; ///< Number of packets received by current instance from its opening, i.e. number of
|
||||
///< packet received by the network adapter since the beginning of the
|
||||
///< capture/monitoring/dump session.
|
||||
INT Dropped; ///< Number of packet that current instance had to drop, from its opening. A packet
|
||||
///< is dropped if there is no more space to store it in the circular buffer that the
|
||||
///< driver associates to current instance.
|
||||
INT Accepted; ///< Number of packet that current capture instance acepted, from its opening. A packet
|
||||
///< is accepted if it passes the filter and fits in the buffer. Accepted packets are the
|
||||
///< ones that reach the application.
|
||||
PUCHAR bpfprogram; ///< Pointer to the filtering pseudo-code associated with current instance of the driver.
|
||||
///< This code is used only in particular situations (for example when the packet received
|
||||
///< from the NIC driver is stored in two non-consecutive buffers. In normal situations
|
||||
///< the filtering routine created by the JIT compiler and pointed by the next field
|
||||
///< is used. See \ref NPF for details on the filtering process.
|
||||
JIT_BPF_Filter *Filter; ///< Pointer to the native filtering function created by the jitter.
|
||||
///< See BPF_jitter() for details.
|
||||
PUCHAR Buffer; ///< Pointer to the circular buffer associated with every driver instance. It contains the
|
||||
///< data that will be passed to the application. See \ref NPF for details.
|
||||
UINT Bhead; ///< Head of the circular buffer.
|
||||
UINT Btail; ///< Tail of the circular buffer.
|
||||
UINT BufSize; ///< Size of the circular buffer.
|
||||
UINT BLastByte; ///< Position of the last valid byte in the circular buffer.
|
||||
PMDL TransferMdl; ///< MDL used to map the portion of the buffer that will contain an incoming packet.
|
||||
///< Used by NdisTransferData().
|
||||
NDIS_SPIN_LOCK BufLock; ///< SpinLock that protects the access tho the circular buffer variables.
|
||||
UINT MinToCopy; ///< Minimum amount of data in the circular buffer that unlocks a read. Set with the
|
||||
///< BIOCSMINTOCOPY IOCTL.
|
||||
LARGE_INTEGER TimeOut; ///< Timeout after which a read is released, also if the amount of data in the buffer is
|
||||
///< less than MinToCopy. Set with the BIOCSRTIMEOUT IOCTL.
|
||||
|
||||
int mode; ///< Working mode of the driver. See PacketSetMode() for details.
|
||||
LARGE_INTEGER Nbytes; ///< Amount of bytes accepted by the filter when this instance is in statistical mode.
|
||||
LARGE_INTEGER Npackets; ///< Number of packets accepted by the filter when this instance is in statistical mode.
|
||||
NDIS_SPIN_LOCK CountersLock; ///< SpinLock that protects the statistical mode counters.
|
||||
UINT Nwrites; ///< Number of times a single write must be physically repeated. See \ref NPF for an
|
||||
///< explanation
|
||||
UINT Multiple_Write_Counter; ///< Counts the number of times a single write has already physically repeated.
|
||||
NDIS_EVENT WriteEvent; ///< Event used to synchronize the multiple write process.
|
||||
NDIS_EVENT IOEvent; ///< Event used to synchronize I/O requests with the callback structure of NDIS.
|
||||
NDIS_STATUS IOStatus; ///< Maintains the status of and OID request call, that will be passed to the application.
|
||||
BOOLEAN Bound; ///< Specifies if NPF is still bound to the adapter used by this instance. Bound can be
|
||||
///< FALSE if a Plug and Play adapter has been removed or disabled by the user.
|
||||
HANDLE DumpFileHandle; ///< Handle of the file used in dump mode.
|
||||
PFILE_OBJECT DumpFileObject; ///< Pointer to the object of the file used in dump mode.
|
||||
PKTHREAD DumpThreadObject; ///< Pointer to the object of the thread used in dump mode.
|
||||
HANDLE DumpThreadHandle; ///< Handle of the thread created by dump mode to asynchronously move the buffer to disk.
|
||||
NDIS_EVENT DumpEvent; ///< Event used to synchronize the dump thread with the tap when the instance is in dump mode.
|
||||
LARGE_INTEGER DumpOffset; ///< Current offset in the dump file.
|
||||
UNICODE_STRING DumpFileName; ///< String containing the name of the dump file.
|
||||
UINT MaxDumpBytes; ///< Maximum dimension in bytes of the dump file. If the dump file reaches this size it
|
||||
///< will be closed. A value of 0 means unlimited size.
|
||||
UINT MaxDumpPacks; ///< Maximum number of packets that will be saved in the dump file. If this number of
|
||||
///< packets is reached the dump will be closed. A value of 0 means unlimited number of
|
||||
///< packets.
|
||||
BOOLEAN DumpLimitReached; ///< TRUE if the maximum dimension of the dump file (MaxDumpBytes or MaxDumpPacks) is
|
||||
///< reached.
|
||||
MEM_TYPE mem_ex; ///< Memory used by the TME virtual co-processor
|
||||
TME_CORE tme; ///< Data structure containing the virtualization of the TME co-processor
|
||||
NDIS_SPIN_LOCK machine_lock; ///< SpinLock that protects the mem_ex buffer
|
||||
UINT MaxFrameSize; ///< Maximum frame size that the underlying MAC acceptes. Used to perform a check on the
|
||||
///< size of the frames sent with NPF_Write() or NPF_BufferedWrite().
|
||||
} OPEN_INSTANCE, *POPEN_INSTANCE;
|
||||
|
||||
|
||||
#define TRANSMIT_PACKETS 256 ///< Maximum number of packets in the transmit packet pool. This value is an upper bound to the number
|
||||
///< of packets that can be transmitted at the same time or with a single call to NdisSendPackets.
|
||||
|
||||
|
||||
/// Macro used in the I/O routines to return the control to user-mode with a success status.
|
||||
#define EXIT_SUCCESS(quantity) Irp->IoStatus.Information=quantity;\
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;\
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);\
|
||||
return STATUS_SUCCESS;\
|
||||
|
||||
/// Macro used in the I/O routines to return the control to user-mode with a failure status.
|
||||
#define EXIT_FAILURE(quantity) Irp->IoStatus.Information=quantity;\
|
||||
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;\
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);\
|
||||
return STATUS_UNSUCCESSFUL;\
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/***************************/
|
||||
/* Prototypes */
|
||||
/***************************/
|
||||
|
||||
/** @defgroup NPF_code NPF functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/*!
|
||||
\brief The initialization routine of the driver.
|
||||
\param DriverObject The driver object of NPF created by the system.
|
||||
\param RegistryPath The registry path containing the keys related to the driver.
|
||||
\return A string containing a list of network adapters.
|
||||
|
||||
DriverEntry is a mandatory function in a device driver. Like the main() of a user level program, it is called
|
||||
by the system when the driver is loaded in memory and started. Its purpose is to initialize the driver,
|
||||
performing all the allocations and the setup. In particular, DriverEntry registers all the driver's I/O
|
||||
callbacks, creates the devices, defines NPF as a protocol inside NDIS.
|
||||
*/
|
||||
//NTSTATUS
|
||||
//DriverEntry(
|
||||
// IN PDRIVER_OBJECT DriverObject,
|
||||
// IN PUNICODE_STRING RegistryPath
|
||||
// );
|
||||
|
||||
/*!
|
||||
\brief Returns the list of the MACs available on the system.
|
||||
\return A string containing a list of network adapters.
|
||||
|
||||
The list of adapters is retrieved from the
|
||||
SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318} registry key.
|
||||
NPF tries to create its bindings from this list. In this way it is possible to be loaded
|
||||
and unloaded dynamically without passing from the control panel.
|
||||
*/
|
||||
PWCHAR getAdaptersList(VOID);
|
||||
|
||||
/*!
|
||||
\brief Returns the MACs that bind to TCP/IP.
|
||||
\return Pointer to the registry key containing the list of adapters on which TCP/IP is bound.
|
||||
|
||||
If getAdaptersList() fails, NPF tries to obtain the TCP/IP bindings through this function.
|
||||
*/
|
||||
PKEY_VALUE_PARTIAL_INFORMATION getTcpBindings(VOID);
|
||||
|
||||
/*!
|
||||
\brief Creates a device for a given MAC.
|
||||
\param adriverObjectP The driver object that will be associated with the device, i.e. the one of NPF.
|
||||
\param amacNameP The name of the network interface that the device will point.
|
||||
\param aProtoHandle NDIS protocol handle of NPF.
|
||||
\return If the function succeeds, the return value is nonzero.
|
||||
|
||||
NPF creates a device for every valid network adapter. The new device points to the NPF driver, but contains
|
||||
information about the original device. In this way, when the user opens the new device, NPF will be able to
|
||||
determine the correct adapter to use.
|
||||
*/
|
||||
BOOLEAN createDevice(
|
||||
IN OUT PDRIVER_OBJECT adriverObjectP,
|
||||
IN PUNICODE_STRING amacNameP,
|
||||
NDIS_HANDLE aProtoHandle);
|
||||
|
||||
/*!
|
||||
\brief Opens a new instance of the driver.
|
||||
\param DeviceObject Pointer to the device object utilized by the user.
|
||||
\param Irp Pointer to the IRP containing the user request.
|
||||
\return The status of the operation. See ntstatus.h in the DDK.
|
||||
|
||||
This function is called by the OS when a new instance of the driver is opened, i.e. when a user application
|
||||
performs a CreateFile on a device created by NPF. NPF_Open allocates and initializes variables, objects
|
||||
and buffers needed by the new instance, fills the OPEN_INSTANCE structure associated with it and opens the
|
||||
adapter with a call to NdisOpenAdapter.
|
||||
*/
|
||||
NTSTATUS
|
||||
NPF_Open(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
/*!
|
||||
\brief Ends the opening of an adapter.
|
||||
\param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
|
||||
\param Status Status of the opening operation performed by NDIS.
|
||||
\param OpenErrorStatus not used by NPF.
|
||||
|
||||
Callback function associated with the NdisOpenAdapter() NDIS function. It is invoked by NDIS when the NIC
|
||||
driver has finished an open operation that was previously started by NPF_Open().
|
||||
*/
|
||||
VOID
|
||||
NPF_OpenAdapterComplete(
|
||||
IN NDIS_HANDLE ProtocolBindingContext,
|
||||
IN NDIS_STATUS Status,
|
||||
IN NDIS_STATUS OpenErrorStatus
|
||||
);
|
||||
|
||||
/*!
|
||||
\brief Closes an instance of the driver.
|
||||
\param DeviceObject Pointer to the device object utilized by the user.
|
||||
\param Irp Pointer to the IRP containing the user request.
|
||||
\return The status of the operation. See ntstatus.h in the DDK.
|
||||
|
||||
This function is called when a running instance of the driver is closed by the user with a CloseHandle().
|
||||
It stops the capture/monitoring/dump process, deallocates the memory and the objects associated with the
|
||||
instance and closing the files. The network adapter is then closed with a call to NdisCloseAdapter.
|
||||
*/
|
||||
NTSTATUS
|
||||
NPF_Close(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
/*!
|
||||
\brief Ends the closing of an adapter.
|
||||
\param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
|
||||
\param Status Status of the close operation performed by NDIS.
|
||||
|
||||
Callback function associated with the NdisCloseAdapter() NDIS function. It is invoked by NDIS when the NIC
|
||||
driver has finished a close operation that was previously started by NPF_Close().
|
||||
*/
|
||||
VOID
|
||||
NPF_CloseAdapterComplete(
|
||||
IN NDIS_HANDLE ProtocolBindingContext,
|
||||
IN NDIS_STATUS Status
|
||||
);
|
||||
|
||||
/*!
|
||||
\brief Callback invoked by NDIS when a packet arrives from the network.
|
||||
\param ProtocolBindingContext Context of the function. Points to a OPEN_INSTANCE structure that identifies
|
||||
the NPF instance to which the packets are destined.
|
||||
\param MacReceiveContext Handle that identifies the underlying NIC driver that generated the request.
|
||||
This value must be used when the packet is transferred from the NIC driver with NdisTransferData().
|
||||
\param HeaderBuffer Pointer to the buffer in the NIC driver memory that contains the header of the packet.
|
||||
\param HeaderBufferSize Size in bytes of the header.
|
||||
\param LookAheadBuffer Pointer to the buffer in the NIC driver's memory that contains the incoming packet's
|
||||
data <b>available to NPF</b>. This value does not necessarily coincide with the actual size of the packet,
|
||||
since only a portion can be available at this time. The remaining portion can be obtained with the
|
||||
NdisTransferData() NDIS function.
|
||||
\param LookaheadBufferSize Size in bytes of the lookahead buffer.
|
||||
\param PacketSize Total size of the incoming packet, excluded the header.
|
||||
\return The status of the operation. See ntstatus.h in the DDK.
|
||||
|
||||
NPF_tap() is called by the underlying NIC for every incoming packet. It is the most important and one of
|
||||
the most complex functions of NPF: it executes the filter, runs the statistical engine (if the instance is in
|
||||
statistical mode), gathers the timestamp, moves the packet in the buffer. NPF_tap() is the only function,
|
||||
along with the filtering ones, that is executed for every incoming packet, therefore it is carefully
|
||||
optimized.
|
||||
*/
|
||||
NDIS_STATUS
|
||||
NPF_tap(
|
||||
IN NDIS_HANDLE ProtocolBindingContext,
|
||||
IN NDIS_HANDLE MacReceiveContext,
|
||||
IN PVOID HeaderBuffer,
|
||||
IN UINT HeaderBufferSize,
|
||||
IN PVOID LookAheadBuffer,
|
||||
IN UINT LookaheadBufferSize,
|
||||
IN UINT PacketSize
|
||||
);
|
||||
|
||||
/*!
|
||||
\brief Ends the transfer of a packet.
|
||||
\param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
|
||||
\param Packet Pointer to the NDIS_PACKET structure that received the packet data.
|
||||
\param Status Status of the transfer operation.
|
||||
\param BytesTransferred Amount of bytes transferred.
|
||||
|
||||
Callback function associated with the NdisTransferData() NDIS function. It is invoked by NDIS when the NIC
|
||||
driver has finished the transfer of a packet from the NIC driver memory to the NPF circular buffer.
|
||||
*/
|
||||
VOID
|
||||
NPF_TransferDataComplete(
|
||||
IN NDIS_HANDLE ProtocolBindingContext,
|
||||
IN PNDIS_PACKET Packet,
|
||||
IN NDIS_STATUS Status,
|
||||
IN UINT BytesTransferred
|
||||
);
|
||||
|
||||
/*!
|
||||
\brief Callback function that signals the end of a packet reception.
|
||||
\param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
|
||||
|
||||
does nothing in NPF
|
||||
*/
|
||||
VOID
|
||||
NPF_ReceiveComplete(IN NDIS_HANDLE ProtocolBindingContext);
|
||||
|
||||
/*!
|
||||
\brief Handles the IOCTL calls.
|
||||
\param DeviceObject Pointer to the device object utilized by the user.
|
||||
\param Irp Pointer to the IRP containing the user request.
|
||||
\return The status of the operation. See ntstatus.h in the DDK.
|
||||
|
||||
Once the packet capture driver is opened it can be configured from user-level applications with IOCTL commands
|
||||
using the DeviceIoControl() system call. NPF_IoControl receives and serves all the IOCTL calls directed to NPF.
|
||||
The following commands are recognized:
|
||||
- #BIOCSETBUFFERSIZE
|
||||
- #BIOCSETF
|
||||
- #BIOCGSTATS
|
||||
- #BIOCSRTIMEOUT
|
||||
- #BIOCSMODE
|
||||
- #BIOCSWRITEREP
|
||||
- #BIOCSMINTOCOPY
|
||||
- #BIOCSETOID
|
||||
- #BIOCQUERYOID
|
||||
- #BIOCSETDUMPFILENAME
|
||||
- #BIOCGEVNAME
|
||||
- #BIOCSENDPACKETSSYNC
|
||||
- #BIOCSENDPACKETSNOSYNC
|
||||
*/
|
||||
NTSTATUS
|
||||
NPF_IoControl(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
|
||||
/*!
|
||||
\brief Ends an OID request.
|
||||
\param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
|
||||
\param pRequest Pointer to the completed OID request.
|
||||
\param Status Status of the operation.
|
||||
|
||||
Callback function associated with the NdisRequest() NDIS function. It is invoked by NDIS when the NIC
|
||||
driver has finished an OID request operation that was previously started by NPF_IoControl().
|
||||
*/
|
||||
VOID
|
||||
NPF_RequestComplete(
|
||||
IN NDIS_HANDLE ProtocolBindingContext,
|
||||
IN PNDIS_REQUEST pRequest,
|
||||
IN NDIS_STATUS Status
|
||||
);
|
||||
|
||||
/*!
|
||||
\brief Writes a raw packet to the network.
|
||||
\param DeviceObject Pointer to the device object on which the user wrote the packet.
|
||||
\param Irp Pointer to the IRP containing the user request.
|
||||
\return The status of the operation. See ntstatus.h in the DDK.
|
||||
|
||||
This function is called by the OS in consequence of user WriteFile() call, with the data of the packet that must
|
||||
be sent on the net. The data is contained in the buffer associated with Irp, NPF_Write takes it and
|
||||
delivers it to the NIC driver via the NdisSend() function. The Nwrites field of the OPEN_INSTANCE structure
|
||||
associated with Irp indicates the number of copies of the packet that will be sent: more than one copy of the
|
||||
packet can be sent for performance reasons.
|
||||
*/
|
||||
NTSTATUS
|
||||
NPF_Write(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
|
||||
/*!
|
||||
\brief Writes a buffer of raw packets to the network.
|
||||
\param Irp Pointer to the IRP containing the user request.
|
||||
\param UserBuff Pointer to the buffer containing the packets to send.
|
||||
\param UserBuffSize Size of the buffer with the packets.
|
||||
\return The amount of bytes actually sent. If the return value is smaller than the Size parameter, an
|
||||
error occurred during the send. The error can be caused by an adapter problem or by an
|
||||
inconsistent/bogus user buffer.
|
||||
|
||||
This function is called by the OS in consequence of a BIOCSENDPACKETSNOSYNC or a BIOCSENDPACKETSSYNC IOCTL.
|
||||
The buffer received as input parameter contains an arbitrary number of packets, each of which preceded by a
|
||||
sf_pkthdr structure. NPF_BufferedWrite() scans the buffer and sends every packet via the NdisSend() function.
|
||||
When Sync is set to TRUE, the packets are synchronized with the KeQueryPerformanceCounter() function.
|
||||
This requires a remarkable amount of CPU, but allows to respect the timestamps associated with packets with a precision
|
||||
of some microseconds (depending on the precision of the performance counter of the machine).
|
||||
If Sync is false, the timestamps are ignored and the packets are sent as fat as possible.
|
||||
*/
|
||||
|
||||
INT NPF_BufferedWrite(IN PIRP Irp,
|
||||
IN PCHAR UserBuff,
|
||||
IN ULONG UserBuffSize,
|
||||
BOOLEAN sync);
|
||||
|
||||
/*!
|
||||
\brief Ends a send operation.
|
||||
\param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
|
||||
\param pRequest Pointer to the NDIS PACKET structure used by NPF_Write() to send the packet.
|
||||
\param Status Status of the operation.
|
||||
|
||||
Callback function associated with the NdisSend() NDIS function. It is invoked by NDIS when the NIC
|
||||
driver has finished an OID request operation that was previously started by NPF_Write().
|
||||
*/
|
||||
VOID
|
||||
NPF_SendComplete(
|
||||
IN NDIS_HANDLE ProtocolBindingContext,
|
||||
IN PNDIS_PACKET pPacket,
|
||||
IN NDIS_STATUS Status
|
||||
);
|
||||
|
||||
/*!
|
||||
\brief Ends a reset of the adapter.
|
||||
\param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with the current instance.
|
||||
\param Status Status of the operation.
|
||||
|
||||
Callback function associated with the NdisReset() NDIS function. It is invoked by NDIS when the NIC
|
||||
driver has finished an OID request operation that was previously started by NPF_IoControl(), in an IOCTL_PROTOCOL_RESET
|
||||
command.
|
||||
*/
|
||||
VOID
|
||||
NPF_ResetComplete(
|
||||
IN NDIS_HANDLE ProtocolBindingContext,
|
||||
IN NDIS_STATUS Status
|
||||
);
|
||||
|
||||
/*!
|
||||
\brief Callback for NDIS StatusHandler. Not used by NPF
|
||||
*/
|
||||
VOID
|
||||
NPF_Status(
|
||||
IN NDIS_HANDLE ProtocolBindingContext,
|
||||
IN NDIS_STATUS Status,
|
||||
IN PVOID StatusBuffer,
|
||||
IN UINT StatusBufferSize
|
||||
);
|
||||
|
||||
|
||||
/*!
|
||||
\brief Callback for NDIS StatusCompleteHandler. Not used by NPF
|
||||
*/
|
||||
VOID
|
||||
NPF_StatusComplete(IN NDIS_HANDLE ProtocolBindingContext);
|
||||
|
||||
/*!
|
||||
\brief Function called by the OS when NPF is unloaded.
|
||||
\param DriverObject The driver object of NPF created by the system.
|
||||
|
||||
This is the last function executed when the driver is unloaded from the system. It frees global resources,
|
||||
delete the devices and deregisters the protocol. The driver can be unloaded by the user stopping the NPF
|
||||
service (from control panel or with a console 'net stop npf').
|
||||
*/
|
||||
VOID
|
||||
STDCALL_FUNC
|
||||
NPF_Unload(IN PDRIVER_OBJECT DriverObject);
|
||||
|
||||
|
||||
/*!
|
||||
\brief Function that serves the user's reads.
|
||||
\param DeviceObject Pointer to the device used by the user.
|
||||
\param Irp Pointer to the IRP containing the user request.
|
||||
\return The status of the operation. See ntstatus.h in the DDK.
|
||||
|
||||
This function is called by the OS in consequence of user ReadFile() call. It moves the data present in the
|
||||
kernel buffer to the user buffer associated with Irp.
|
||||
First of all, NPF_Read checks the amount of data in kernel buffer associated with current NPF instance.
|
||||
- If the instance is in capture mode and the buffer contains more than OPEN_INSTANCE::MinToCopy bytes,
|
||||
NPF_Read moves the data in the user buffer and returns immediatly. In this way, the read performed by the
|
||||
user is not blocking.
|
||||
- If the buffer contains less than MinToCopy bytes, the application's request isn't
|
||||
satisfied immediately, but it's blocked until at least MinToCopy bytes arrive from the net
|
||||
or the timeout on this read expires. The timeout is kept in the OPEN_INSTANCE::TimeOut field.
|
||||
- If the instance is in statistical mode or in dump mode, the application's request is blocked until the
|
||||
timeout kept in OPEN_INSTANCE::TimeOut expires.
|
||||
*/
|
||||
NTSTATUS
|
||||
NPF_Read(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
/*!
|
||||
\brief Reads the registry keys associated woth NPF if the driver is manually installed via the control panel.
|
||||
|
||||
Normally not used in recent versions of NPF.
|
||||
*/
|
||||
NTSTATUS
|
||||
NPF_ReadRegistry(
|
||||
IN PWSTR *MacDriverName,
|
||||
IN PWSTR *PacketDriverName,
|
||||
IN PUNICODE_STRING RegistryPath
|
||||
);
|
||||
|
||||
/*!
|
||||
\brief Function used by NPF_ReadRegistry() to quesry the registry keys associated woth NPF if the driver
|
||||
is manually installed via the control panel.
|
||||
|
||||
Normally not used in recent versions of NPF.
|
||||
*/
|
||||
NTSTATUS
|
||||
NPF_QueryRegistryRoutine(
|
||||
IN PWSTR ValueName,
|
||||
IN ULONG ValueType,
|
||||
IN PVOID ValueData,
|
||||
IN ULONG ValueLength,
|
||||
IN PVOID Context,
|
||||
IN PVOID EntryContext
|
||||
);
|
||||
|
||||
/*!
|
||||
\brief Callback for NDIS BindAdapterHandler. Not used by NPF.
|
||||
|
||||
Function called by NDIS when a new adapter is installed on the machine With Plug and Play.
|
||||
*/
|
||||
VOID NPF_BindAdapter(
|
||||
OUT PNDIS_STATUS Status,
|
||||
IN NDIS_HANDLE BindContext,
|
||||
IN PNDIS_STRING DeviceName,
|
||||
IN PVOID SystemSpecific1,
|
||||
IN PVOID SystemSpecific2
|
||||
);
|
||||
|
||||
/*!
|
||||
\brief Callback for NDIS UnbindAdapterHandler.
|
||||
\param Status out variable filled by NPF_UnbindAdapter with the status of the unbind operation.
|
||||
\param ProtocolBindingContext Context of the function. Contains a pointer to the OPEN_INSTANCE structure associated with current instance.
|
||||
\param UnbindContext Specifies a handle, supplied by NDIS, that NPF can use to complete the opration.
|
||||
|
||||
Function called by NDIS when a new adapter is removed from the machine without shutting it down.
|
||||
NPF_UnbindAdapter closes the adapter calling NdisCloseAdapter() and frees the memory and the structures
|
||||
associated with it. It also releases the waiting user-level app and closes the dump thread if the instance
|
||||
is in dump mode.
|
||||
*/
|
||||
VOID
|
||||
NPF_UnbindAdapter(
|
||||
OUT PNDIS_STATUS Status,
|
||||
IN NDIS_HANDLE ProtocolBindingContext,
|
||||
IN NDIS_HANDLE UnbindContext
|
||||
);
|
||||
|
||||
/*!
|
||||
\brief Validates a filtering program arriving from the user-level app.
|
||||
\param f The filter.
|
||||
\param len Its length, in pseudo instructions.
|
||||
\param mem_ex_size The length of the extended memory, used to validate LD/ST to that memory
|
||||
\return true if f is a valid filter program..
|
||||
|
||||
The kernel needs to be able to verify an application's filter code. Otherwise, a bogus program could easily
|
||||
crash the system.
|
||||
This function returns true if f is a valid filter program. The constraints are that each jump be forward and
|
||||
to a valid code. The code must terminate with either an accept or reject.
|
||||
*/
|
||||
int bpf_validate(struct bpf_insn *f,int len, uint32 mem_ex_size);
|
||||
|
||||
/*!
|
||||
\brief The filtering pseudo-machine interpreter.
|
||||
\param pc The filter.
|
||||
\param p Pointer to a memory buffer containing the packet on which the filter will be executed.
|
||||
\param wirelen Original length of the packet.
|
||||
\param buflen Current length of the packet. In some cases (for example when the transfer of the packet to the RAM
|
||||
has not yet finished), bpf_filter can be executed on a portion of the packet.
|
||||
\param mem_ex The extended memory.
|
||||
\param tme The virtualization of the TME co-processor
|
||||
\param time_ref Data structure needed by the TME co-processor to timestamp data
|
||||
\return The portion of the packet to keep, in bytes. 0 means that the packet must be rejected, -1 means that
|
||||
the whole packet must be kept.
|
||||
|
||||
\note this function is not used in normal situations, because the jitter creates a native filtering function
|
||||
that is faster than the interpreter.
|
||||
*/
|
||||
UINT bpf_filter(register struct bpf_insn *pc,
|
||||
register UCHAR *p,
|
||||
UINT wirelen,
|
||||
register UINT buflen,
|
||||
PMEM_TYPE mem_ex,
|
||||
PTME_CORE tme,
|
||||
struct time_conv *time_ref);
|
||||
|
||||
/*!
|
||||
\brief The filtering pseudo-machine interpreter with two buffers. This function is slower than bpf_filter(),
|
||||
but works correctly also if the MAC header and the data of the packet are in two different buffers.
|
||||
\param pc The filter.
|
||||
\param p Pointer to a memory buffer containing the MAC header of the packet.
|
||||
\param pd Pointer to a memory buffer containing the data of the packet.
|
||||
\param wirelen Original length of the packet.
|
||||
\param buflen Current length of the packet. In some cases (for example when the transfer of the packet to the RAM
|
||||
has not yet finished), bpf_filter can be executed on a portion of the packet.
|
||||
\param mem_ex The extended memory.
|
||||
\param tme The virtualization of the TME co-processor
|
||||
\param time_ref Data structure needed by the TME co-processor to timestamp data
|
||||
\return The portion of the packet to keep, in bytes. 0 means that the packet must be rejected, -1 means that
|
||||
the whole packet must be kept.
|
||||
|
||||
This function is used when NDIS passes the packet to NPF_tap() in two buffers instaed than in a single one.
|
||||
*/
|
||||
UINT bpf_filter_with_2_buffers(register struct bpf_insn *pc,
|
||||
register UCHAR *p,
|
||||
register UCHAR *pd,
|
||||
register int headersize,
|
||||
UINT wirelen,
|
||||
register UINT buflen,
|
||||
PMEM_TYPE mem_ex,
|
||||
PTME_CORE tme,
|
||||
struct time_conv *time_ref);
|
||||
|
||||
/*!
|
||||
\brief Creates the file that will receive the packets when the driver is in dump mode.
|
||||
\param Open The NPF instance that opens the file.
|
||||
\param fileName Pointer to a UNICODE string containing the name of the file.
|
||||
\param append Boolean value that specifies if the data must be appended to the file.
|
||||
\return The status of the operation. See ntstatus.h in the DDK.
|
||||
*/
|
||||
NTSTATUS NPF_OpenDumpFile(POPEN_INSTANCE Open , PUNICODE_STRING fileName, BOOLEAN append);
|
||||
|
||||
/*!
|
||||
\brief Starts dump to file.
|
||||
\param Open The NPF instance that opens the file.
|
||||
\return The status of the operation. See ntstatus.h in the DDK.
|
||||
|
||||
This function performs two operations. First, it writes the libpcap header at the beginning of the file.
|
||||
Second, it starts the thread that asynchronously dumps the network data to the file.
|
||||
*/
|
||||
NTSTATUS NPF_StartDump(POPEN_INSTANCE Open);
|
||||
|
||||
/*!
|
||||
\brief The dump thread.
|
||||
\param Open The NPF instance that creates the thread.
|
||||
|
||||
This function moves the content of the NPF kernel buffer to file. It runs in the user context, so at lower
|
||||
priority than the TAP.
|
||||
*/
|
||||
VOID NPF_DumpThread(POPEN_INSTANCE Open);
|
||||
|
||||
/*!
|
||||
\brief Saves the content of the packet buffer to the file associated with current instance.
|
||||
\param Open The NPF instance that creates the thread.
|
||||
|
||||
Used by NPF_DumpThread() and NPF_CloseDumpFile().
|
||||
*/
|
||||
NTSTATUS NPF_SaveCurrentBuffer(POPEN_INSTANCE Open);
|
||||
|
||||
/*!
|
||||
\brief Writes a block of packets on the dump file.
|
||||
\param FileObject The file object that will receive the packets.
|
||||
\param Offset The offset in the file where the packets will be put.
|
||||
\param Length The amount of bytes to write.
|
||||
\param Mdl MDL mapping the memory buffer that will be written to disk.
|
||||
\param IoStatusBlock Used by the function to return the status of the operation.
|
||||
\return The status of the operation. See ntstatus.h in the DDK.
|
||||
|
||||
NPF_WriteDumpFile addresses directly the file system, creating a custom IRP and using it to send a portion
|
||||
of the NPF circular buffer to disk. This function is used by NPF_DumpThread().
|
||||
*/
|
||||
VOID NPF_WriteDumpFile(PFILE_OBJECT FileObject,
|
||||
PLARGE_INTEGER Offset,
|
||||
ULONG Length,
|
||||
PMDL Mdl,
|
||||
PIO_STATUS_BLOCK IoStatusBlock);
|
||||
|
||||
|
||||
|
||||
/*!
|
||||
\brief Closes the dump file associated with an instance of the driver.
|
||||
\param Open The NPF instance that closes the file.
|
||||
\return The status of the operation. See ntstatus.h in the DDK.
|
||||
*/
|
||||
NTSTATUS NPF_CloseDumpFile(POPEN_INSTANCE Open);
|
||||
|
||||
/*!
|
||||
\brief Returns the amount of bytes present in the packet buffer.
|
||||
\param Open The NPF instance that closes the file.
|
||||
*/
|
||||
UINT GetBuffOccupation(POPEN_INSTANCE Open);
|
||||
|
||||
/*!
|
||||
\brief Called by NDIS to notify us of a PNP event. The most significant one for us is power state change.
|
||||
|
||||
\param ProtocolBindingContext Pointer to open context structure. This is NULL for global reconfig
|
||||
events.
|
||||
\param pNetPnPEvent Pointer to the PnP event
|
||||
|
||||
If there is a power state change, the driver is forced to resynchronize the global timer.
|
||||
This hopefully avoids the synchronization issues caused by hibernation or standby.
|
||||
This function is excluded from the NT4 driver, where PnP is not supported
|
||||
*/
|
||||
#ifdef NDIS50
|
||||
NDIS_STATUS NPF_PowerChange(IN NDIS_HANDLE ProtocolBindingContext, IN PNET_PNP_EVENT pNetPnPEvent);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /*main ifndef/define*/
|
|
@ -1,47 +0,0 @@
|
|||
//#include "resource.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 3,0,0,13
|
||||
PRODUCTVERSION 3,0,0,13
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS 0x40004L
|
||||
FILETYPE 0x3L
|
||||
FILESUBTYPE 0x7L
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "000004b0"
|
||||
BEGIN
|
||||
VALUE "Comments", "Netgroup Packet Filter Driver\0"
|
||||
VALUE "CompanyName", "Politecnico di Torino\0"
|
||||
VALUE "FileDescription", "NPF Driver - TME extensions\0"
|
||||
VALUE "FileVersion", "3, 0, 0, 13\0"
|
||||
VALUE "InternalName", "NPF + TME \0"
|
||||
VALUE "LegalCopyright", "Copyright © 2002\0"
|
||||
VALUE "LegalTrademarks", "\0"
|
||||
VALUE "OriginalFilename", "NPF.RC\0"
|
||||
VALUE "PrivateBuild", "REACTOS PRIVATE BUILD\0"
|
||||
VALUE "ProductName", "NPF Driver\0"
|
||||
VALUE "ProductVersion", "3, 0, 0, 13\0"
|
||||
VALUE "SpecialBuild", "Beta testing use only\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x0, 1200
|
||||
END
|
||||
END
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -1,680 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2000
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <stdarg.h>
|
||||
#include <ntddk.h>
|
||||
#include <ntiologc.h>
|
||||
#include <ndis.h>
|
||||
#else
|
||||
#include <ddk/ntddk.h>
|
||||
#include <net/ndis.h>
|
||||
|
||||
#define NdisMoveMappedMemory(Destination,Source,Length) RtlCopyMemory(Destination,Source,Length)
|
||||
#define NdisZeroMappedMemory(Destination,Length) RtlZeroMemory(Destination,Length)
|
||||
#define NdisReinitializePacket(Packet) \
|
||||
{ \
|
||||
(Packet)->Private.Head = (PNDIS_BUFFER)NULL; \
|
||||
(Packet)->Private.ValidCounts = FALSE; \
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
#include "packet.h"
|
||||
#include "win_bpf.h"
|
||||
|
||||
#include "tme.h"
|
||||
#include "time_calls.h"
|
||||
|
||||
extern struct time_conv G_Start_Time; // from openclos.c
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
UINT GetBuffOccupation(POPEN_INSTANCE Open)
|
||||
{
|
||||
UINT Occupation;
|
||||
|
||||
NdisAcquireSpinLock( &Open->BufLock );
|
||||
|
||||
if(Open->Btail >= Open->Bhead) Occupation = Open->Btail-Open->Bhead;
|
||||
else Occupation = Open->BLastByte-Open->Bhead+Open->Btail;
|
||||
|
||||
NdisReleaseSpinLock( &Open->BufLock );
|
||||
|
||||
return Occupation;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
void PacketMoveMem(PVOID Destination, PVOID Source, ULONG Length, UINT *Bhead)
|
||||
{
|
||||
ULONG WordLength;
|
||||
UINT n,i,NBlocks;
|
||||
|
||||
WordLength=Length>>2;
|
||||
NBlocks=WordLength>>8;
|
||||
|
||||
for(n=0;n<NBlocks;n++){
|
||||
for(i=0;i<256;i++){
|
||||
*((PULONG)Destination)++=*((PULONG)Source)++;
|
||||
}
|
||||
*Bhead+=1024;
|
||||
}
|
||||
|
||||
n=WordLength-(NBlocks<<8);
|
||||
for(i=0;i<n;i++){
|
||||
*((PULONG)Destination)++=*((PULONG)Source)++;
|
||||
}
|
||||
*Bhead+=n<<2;
|
||||
|
||||
n=Length-(WordLength<<2);
|
||||
for(i=0;i<n;i++){
|
||||
*((PUCHAR)Destination)++=*((PUCHAR)Source)++;
|
||||
}
|
||||
*Bhead+=n;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
NTSTATUS
|
||||
NPF_Read(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
|
||||
{
|
||||
POPEN_INSTANCE Open;
|
||||
PIO_STACK_LOCATION IrpSp;
|
||||
PUCHAR packp;
|
||||
ULONG Input_Buffer_Length;
|
||||
UINT Thead;
|
||||
UINT Ttail;
|
||||
UINT TLastByte;
|
||||
PUCHAR CurrBuff;
|
||||
LARGE_INTEGER CapTime;
|
||||
LARGE_INTEGER TimeFreq;
|
||||
struct bpf_hdr *header;
|
||||
KIRQL Irql;
|
||||
PUCHAR UserPointer;
|
||||
ULONG bytecopy;
|
||||
UINT SizeToCopy;
|
||||
UINT PktLen;
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: Read\n");)
|
||||
|
||||
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
Open=IrpSp->FileObject->FsContext;
|
||||
|
||||
if( Open->Bound == FALSE ){
|
||||
// The Network adapter was removed.
|
||||
EXIT_FAILURE(0);
|
||||
}
|
||||
|
||||
if( Open->mode & MODE_DUMP && Open->DumpFileHandle == NULL ){
|
||||
// this instance is in dump mode, but the dump file has still not been opened
|
||||
EXIT_FAILURE(0);
|
||||
}
|
||||
|
||||
//See if the buffer is full enough to be copied
|
||||
if( GetBuffOccupation(Open) <= Open->MinToCopy || Open->mode & MODE_DUMP )
|
||||
{
|
||||
//wait until some packets arrive or the timeout expires
|
||||
if(Open->TimeOut.QuadPart != (LONGLONG)IMMEDIATE)
|
||||
KeWaitForSingleObject(Open->ReadEvent,
|
||||
UserRequest,
|
||||
KernelMode,
|
||||
TRUE,
|
||||
(Open->TimeOut.QuadPart == (LONGLONG)0)? NULL: &(Open->TimeOut));
|
||||
|
||||
KeClearEvent(Open->ReadEvent);
|
||||
|
||||
if(Open->mode & MODE_STAT){ //this capture instance is in statistics mode
|
||||
CurrBuff=(PUCHAR)MmGetSystemAddressForMdl(Irp->MdlAddress);
|
||||
|
||||
//fill the bpf header for this packet
|
||||
header=(struct bpf_hdr*)CurrBuff;
|
||||
GET_TIME(&header->bh_tstamp,&G_Start_Time);
|
||||
|
||||
if(Open->mode & MODE_DUMP){
|
||||
*(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr)+16)=Open->DumpOffset.QuadPart;
|
||||
header->bh_caplen=24;
|
||||
header->bh_datalen=24;
|
||||
Irp->IoStatus.Information = 24 + sizeof(struct bpf_hdr);
|
||||
}
|
||||
else{
|
||||
header->bh_caplen=16;
|
||||
header->bh_datalen=16;
|
||||
header->bh_hdrlen=sizeof(struct bpf_hdr);
|
||||
Irp->IoStatus.Information = 16 + sizeof(struct bpf_hdr);
|
||||
}
|
||||
|
||||
*(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr))=Open->Npackets.QuadPart;
|
||||
*(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr)+8)=Open->Nbytes.QuadPart;
|
||||
|
||||
//reset the countetrs
|
||||
NdisAcquireSpinLock( &Open->CountersLock );
|
||||
Open->Npackets.QuadPart=0;
|
||||
Open->Nbytes.QuadPart=0;
|
||||
NdisReleaseSpinLock( &Open->CountersLock );
|
||||
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if(Open->mode==MODE_MON) //this capture instance is in monitor mode
|
||||
{
|
||||
PTME_DATA data;
|
||||
ULONG cnt;
|
||||
ULONG block_size;
|
||||
PUCHAR tmp;
|
||||
|
||||
UserPointer=MmGetSystemAddressForMdl(Irp->MdlAddress);
|
||||
|
||||
if ((!IS_VALIDATED(Open->tme.validated_blocks,Open->tme.active_read))||(IrpSp->Parameters.Read.Length<sizeof(struct bpf_hdr)))
|
||||
{
|
||||
EXIT_FAILURE(0);
|
||||
}
|
||||
|
||||
header=(struct bpf_hdr*)UserPointer;
|
||||
|
||||
GET_TIME(&header->bh_tstamp,&G_Start_Time);
|
||||
|
||||
|
||||
header->bh_hdrlen=sizeof(struct bpf_hdr);
|
||||
|
||||
|
||||
//moves user memory pointer
|
||||
UserPointer+=sizeof(struct bpf_hdr);
|
||||
|
||||
//calculus of data to be copied
|
||||
//if the user buffer is smaller than data to be copied,
|
||||
//only some data will be copied
|
||||
data=&Open->tme.block_data[Open->tme.active_read];
|
||||
|
||||
if (data->last_read.tv_sec!=0)
|
||||
data->last_read=header->bh_tstamp;
|
||||
|
||||
|
||||
bytecopy=data->block_size*data->filled_blocks;
|
||||
|
||||
if ((IrpSp->Parameters.Read.Length-sizeof(struct bpf_hdr))<bytecopy)
|
||||
bytecopy=(IrpSp->Parameters.Read.Length-sizeof(struct bpf_hdr))/ data->block_size;
|
||||
else
|
||||
bytecopy=data->filled_blocks;
|
||||
|
||||
tmp=data->shared_memory_base_address;
|
||||
block_size=data->block_size;
|
||||
|
||||
for (cnt=0;cnt<bytecopy;cnt++)
|
||||
{
|
||||
NdisAcquireSpinLock(&Open->machine_lock);
|
||||
RtlCopyMemory(UserPointer,tmp,block_size);
|
||||
NdisReleaseSpinLock(&Open->machine_lock);
|
||||
tmp+=block_size;
|
||||
UserPointer+=block_size;
|
||||
}
|
||||
|
||||
bytecopy*=block_size;
|
||||
|
||||
header->bh_caplen=bytecopy;
|
||||
header->bh_datalen=header->bh_caplen;
|
||||
|
||||
EXIT_SUCCESS(bytecopy+sizeof(struct bpf_hdr));
|
||||
}
|
||||
|
||||
if (Open->Bhead == Open->Btail || Open->mode & MODE_DUMP)
|
||||
// The timeout has expired, but the buffer is still empty (or the packets must be written to file).
|
||||
// We must awake the application, returning an empty buffer.
|
||||
{
|
||||
EXIT_SUCCESS(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// The buffer if full enough to be copied,
|
||||
//
|
||||
NdisAcquireSpinLock( &Open->BufLock );
|
||||
|
||||
Thead = Open->Bhead;
|
||||
Ttail = Open->Btail;
|
||||
TLastByte = Open->BLastByte;
|
||||
|
||||
//get the address of the buffer
|
||||
CurrBuff=Open->Buffer;
|
||||
|
||||
NdisReleaseSpinLock( &Open->BufLock );
|
||||
|
||||
Input_Buffer_Length=IrpSp->Parameters.Read.Length;
|
||||
packp=(PUCHAR)MmGetSystemAddressForMdl(Irp->MdlAddress);
|
||||
|
||||
|
||||
//
|
||||
//fill the application buffer
|
||||
//
|
||||
if(Ttail > Thead){ //first of all see if it we can copy all the buffer in one time
|
||||
if((Ttail-Thead)<Input_Buffer_Length){
|
||||
KeResetEvent(Open->ReadEvent);
|
||||
|
||||
PacketMoveMem(packp,CurrBuff+Thead,Ttail-Thead,&(Open->Bhead));
|
||||
EXIT_SUCCESS(Ttail-Thead);
|
||||
}
|
||||
}
|
||||
else if((TLastByte - Thead) < Input_Buffer_Length){
|
||||
PacketMoveMem(packp, CurrBuff+Thead, TLastByte - Thead, &(Open->Bhead));
|
||||
|
||||
NdisAcquireSpinLock( &Open->BufLock );
|
||||
|
||||
Open->BLastByte = Open->Btail;
|
||||
Open->Bhead = 0;
|
||||
|
||||
NdisReleaseSpinLock( &Open->BufLock );
|
||||
|
||||
EXIT_SUCCESS(TLastByte-Thead);
|
||||
}
|
||||
|
||||
//the buffer must be scannned to determine the number of bytes to copy
|
||||
SizeToCopy = 0;
|
||||
while(TRUE){
|
||||
if(Thead + SizeToCopy == Ttail)
|
||||
break;
|
||||
|
||||
if(Thead + SizeToCopy == TLastByte && TLastByte != Ttail){
|
||||
|
||||
PacketMoveMem(packp, CurrBuff+Thead, SizeToCopy, &(Open->Bhead));
|
||||
// Reset the buffer
|
||||
NdisAcquireSpinLock( &Open->BufLock );
|
||||
(INT)Open->BLastByte = -1;
|
||||
Open->Bhead = 0;
|
||||
NdisReleaseSpinLock( &Open->BufLock );
|
||||
|
||||
EXIT_SUCCESS(SizeToCopy);
|
||||
}
|
||||
|
||||
// Get the size of the next packet in the buffer
|
||||
PktLen = ((struct bpf_hdr*)(CurrBuff + Thead + SizeToCopy))->bh_caplen + sizeof(struct bpf_hdr);
|
||||
|
||||
// The length is aligned to 32-bit boundary
|
||||
PktLen = Packet_WORDALIGN(PktLen);
|
||||
|
||||
if(SizeToCopy + PktLen > Input_Buffer_Length)
|
||||
break;
|
||||
|
||||
SizeToCopy += PktLen;
|
||||
}
|
||||
|
||||
PacketMoveMem(packp, CurrBuff+Thead, SizeToCopy, &(Open->Bhead));
|
||||
EXIT_SUCCESS(SizeToCopy);
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
NDIS_STATUS NPF_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE MacReceiveContext,
|
||||
IN PVOID HeaderBuffer,IN UINT HeaderBufferSize,IN PVOID LookAheadBuffer,
|
||||
IN UINT LookaheadBufferSize,IN UINT PacketSize)
|
||||
{
|
||||
POPEN_INSTANCE Open;
|
||||
PNDIS_PACKET pPacketb;
|
||||
ULONG SizeToTransfer;
|
||||
NDIS_STATUS Status;
|
||||
UINT BytesTransfered;
|
||||
ULONG BufferLength;
|
||||
PMDL pMdl;
|
||||
LARGE_INTEGER CapTime;
|
||||
LARGE_INTEGER TimeFreq;
|
||||
struct bpf_hdr *header;
|
||||
PUCHAR CurrBuff;
|
||||
UINT Thead;
|
||||
UINT Ttail;
|
||||
UINT TLastByte;
|
||||
UINT fres;
|
||||
UINT maxbufspace;
|
||||
USHORT NPFHdrSize;
|
||||
UINT BufOccupation;
|
||||
BOOLEAN ResetBuff = FALSE;
|
||||
|
||||
IF_VERY_LOUD(DbgPrint("NPF: tap\n");)
|
||||
IF_VERY_LOUD(DbgPrint("HeaderBufferSize=%d, LookAheadBuffer=%d, LookaheadBufferSize=%d, PacketSize=%d\n",
|
||||
HeaderBufferSize,
|
||||
LookAheadBuffer,
|
||||
LookaheadBufferSize,
|
||||
PacketSize);)
|
||||
|
||||
Open= (POPEN_INSTANCE)ProtocolBindingContext;
|
||||
|
||||
Open->Received++; // Number of packets received by filter ++
|
||||
|
||||
BufOccupation = GetBuffOccupation(Open); // Get the full buffer space
|
||||
|
||||
if(((Open->mode&MODE_CAPT)||(Open->mode&MODE_DUMP)) && Open->BufSize - BufOccupation < PacketSize+HeaderBufferSize+sizeof(struct bpf_hdr)){
|
||||
// Heuristic that drops the packet also if it possibly fits in the buffer.
|
||||
// It allows to avoid filtering in critical situations when CPU is very important.
|
||||
Open->Dropped++;
|
||||
return NDIS_STATUS_NOT_ACCEPTED;
|
||||
}
|
||||
|
||||
NdisAcquireSpinLock(&Open->machine_lock);
|
||||
|
||||
//
|
||||
//Check if the lookahead buffer follows the mac header.
|
||||
//If the data follow the header (i.e. there is only a buffer) a normal bpf_filter() is
|
||||
//executed on the packet.
|
||||
//Otherwise if there are 2 separate buffers (this could be the case of LAN emulation or
|
||||
//things like this) bpf_filter_with_2_buffers() is executed.
|
||||
//
|
||||
if((UINT)LookAheadBuffer-(UINT)HeaderBuffer != HeaderBufferSize)
|
||||
fres=bpf_filter_with_2_buffers((struct bpf_insn*)(Open->bpfprogram),
|
||||
HeaderBuffer,
|
||||
LookAheadBuffer,
|
||||
HeaderBufferSize,
|
||||
PacketSize+HeaderBufferSize,
|
||||
LookaheadBufferSize+HeaderBufferSize,
|
||||
&Open->mem_ex,
|
||||
&Open->tme,
|
||||
&G_Start_Time);
|
||||
|
||||
|
||||
else
|
||||
if(Open->Filter != NULL)
|
||||
{
|
||||
if (Open->bpfprogram != NULL)
|
||||
{
|
||||
fres=Open->Filter->Function(HeaderBuffer,
|
||||
PacketSize+HeaderBufferSize,
|
||||
LookaheadBufferSize+HeaderBufferSize);
|
||||
|
||||
// Restore the stack.
|
||||
// I ignore the reason, but this instruction is needed only at kernel level
|
||||
#ifndef __GNUC__
|
||||
_asm add esp,12
|
||||
#else
|
||||
asm("add $0x12,%esp;");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
fres = -1;
|
||||
}
|
||||
else
|
||||
fres=bpf_filter((struct bpf_insn*)(Open->bpfprogram),
|
||||
HeaderBuffer,
|
||||
PacketSize+HeaderBufferSize,
|
||||
LookaheadBufferSize+HeaderBufferSize,
|
||||
&Open->mem_ex,
|
||||
&Open->tme,
|
||||
&G_Start_Time);
|
||||
|
||||
NdisReleaseSpinLock(&Open->machine_lock);
|
||||
|
||||
if(Open->mode==MODE_MON)
|
||||
// we are in monitor mode
|
||||
{
|
||||
if (fres==1)
|
||||
KeSetEvent(Open->ReadEvent,0,FALSE);
|
||||
return NDIS_STATUS_NOT_ACCEPTED;
|
||||
|
||||
}
|
||||
|
||||
if(fres==0)
|
||||
// Packet not accepted by the filter, ignore it.
|
||||
return NDIS_STATUS_NOT_ACCEPTED;
|
||||
|
||||
//if the filter returns -1 the whole packet must be accepted
|
||||
if(fres==-1 || fres > PacketSize+HeaderBufferSize)fres=PacketSize+HeaderBufferSize;
|
||||
|
||||
if(Open->mode & MODE_STAT){
|
||||
// we are in statistics mode
|
||||
NdisAcquireSpinLock( &Open->CountersLock );
|
||||
|
||||
Open->Npackets.QuadPart++;
|
||||
|
||||
if(PacketSize+HeaderBufferSize<60)
|
||||
Open->Nbytes.QuadPart+=60;
|
||||
else
|
||||
Open->Nbytes.QuadPart+=PacketSize+HeaderBufferSize;
|
||||
// add preamble+SFD+FCS to the packet
|
||||
// these values must be considered because are not part of the packet received from NDIS
|
||||
Open->Nbytes.QuadPart+=12;
|
||||
|
||||
NdisReleaseSpinLock( &Open->CountersLock );
|
||||
|
||||
if(!(Open->mode & MODE_DUMP)){
|
||||
return NDIS_STATUS_NOT_ACCEPTED;
|
||||
}
|
||||
}
|
||||
|
||||
if(Open->BufSize==0)return NDIS_STATUS_NOT_ACCEPTED;
|
||||
|
||||
if(Open->mode & MODE_DUMP && Open->MaxDumpPacks && (UINT)Open->Accepted > Open->MaxDumpPacks){
|
||||
// Reached the max number of packets to save in the dump file. Discard the packet and stop the dump thread.
|
||||
Open->DumpLimitReached = TRUE; // This stops the thread
|
||||
// Awake the dump thread
|
||||
NdisSetEvent(&Open->DumpEvent);
|
||||
|
||||
// Awake the application
|
||||
KeSetEvent(Open->ReadEvent,0,FALSE);
|
||||
|
||||
return NDIS_STATUS_NOT_ACCEPTED;
|
||||
}
|
||||
|
||||
// Calculate the correct size for the header associated with the packet
|
||||
NPFHdrSize=(Open->mode==MODE_CAPT)? sizeof(struct bpf_hdr): sizeof(struct sf_pkthdr);
|
||||
|
||||
NdisAcquireSpinLock( &Open->BufLock );
|
||||
|
||||
Thead=Open->Bhead;
|
||||
Ttail=Open->Btail;
|
||||
TLastByte = Open->BLastByte;
|
||||
|
||||
NdisReleaseSpinLock( &Open->BufLock );
|
||||
|
||||
maxbufspace=Packet_WORDALIGN(fres+NPFHdrSize);
|
||||
|
||||
if(Ttail+maxbufspace >= Open->BufSize){
|
||||
if(Thead <= maxbufspace)
|
||||
{
|
||||
Open->Dropped++;
|
||||
return NDIS_STATUS_NOT_ACCEPTED;
|
||||
}
|
||||
else{
|
||||
Ttail=0;
|
||||
ResetBuff = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (Thead > Ttail && (Thead-Ttail) <= maxbufspace)
|
||||
{
|
||||
Open->Dropped++;
|
||||
return NDIS_STATUS_NOT_ACCEPTED;
|
||||
}
|
||||
|
||||
CurrBuff=Open->Buffer+Ttail;
|
||||
|
||||
if(LookaheadBufferSize != PacketSize || (UINT)LookAheadBuffer-(UINT)HeaderBuffer != HeaderBufferSize)
|
||||
{
|
||||
// Allocate an MDL to map the portion of the buffer following the header
|
||||
pMdl=IoAllocateMdl(CurrBuff+HeaderBufferSize+LookaheadBufferSize+NPFHdrSize,
|
||||
maxbufspace,
|
||||
FALSE,
|
||||
FALSE,
|
||||
NULL);
|
||||
|
||||
if (pMdl == NULL)
|
||||
{
|
||||
// Unable to map the memory: packet lost
|
||||
IF_LOUD(DbgPrint("NPF: Read-Failed to allocate Mdl\n");)
|
||||
Open->Dropped++;
|
||||
return NDIS_STATUS_NOT_ACCEPTED;
|
||||
}
|
||||
MmBuildMdlForNonPagedPool(pMdl);
|
||||
|
||||
//allocate the packet from NDIS
|
||||
NdisAllocatePacket(&Status, &pPacketb, Open->PacketPool);
|
||||
if (Status != NDIS_STATUS_SUCCESS)
|
||||
{
|
||||
IF_LOUD(DbgPrint("NPF: Tap - No free packets\n");)
|
||||
IoFreeMdl(pMdl);
|
||||
Open->Dropped++;
|
||||
return NDIS_STATUS_NOT_ACCEPTED;
|
||||
}
|
||||
//link the buffer to the packet
|
||||
NdisChainBufferAtFront(pPacketb,pMdl);
|
||||
|
||||
BufferLength=fres-HeaderBufferSize;
|
||||
//Find out how much to transfer
|
||||
SizeToTransfer = (PacketSize < BufferLength) ? PacketSize : BufferLength;
|
||||
|
||||
//copy the ethernet header into buffer
|
||||
NdisMoveMappedMemory((CurrBuff)+NPFHdrSize,HeaderBuffer,HeaderBufferSize);
|
||||
|
||||
//Copy the look ahead buffer
|
||||
if(LookaheadBufferSize)
|
||||
{
|
||||
NdisMoveMappedMemory((CurrBuff) + NPFHdrSize + HeaderBufferSize,
|
||||
LookAheadBuffer,
|
||||
(SizeToTransfer < LookaheadBufferSize)? SizeToTransfer : LookaheadBufferSize );
|
||||
|
||||
SizeToTransfer = (SizeToTransfer > LookaheadBufferSize)?
|
||||
SizeToTransfer - LookaheadBufferSize : 0;
|
||||
}
|
||||
|
||||
Open->TransferMdl=pMdl;
|
||||
|
||||
if(SizeToTransfer)
|
||||
{
|
||||
//Call the Mac to transfer the packet
|
||||
NdisTransferData(&Status,
|
||||
Open->AdapterHandle,
|
||||
MacReceiveContext,
|
||||
LookaheadBufferSize,
|
||||
SizeToTransfer,
|
||||
pPacketb,
|
||||
&BytesTransfered);
|
||||
}
|
||||
else{
|
||||
BytesTransfered = 0;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// The whole packet is in the lookahead buffer, we can avoid the call to NdisTransferData.
|
||||
// This allows us to avoid the allocation of the MDL and the NDIS packet as well
|
||||
RtlCopyMemory((CurrBuff) + NPFHdrSize,
|
||||
HeaderBuffer,
|
||||
HeaderBufferSize + LookaheadBufferSize);
|
||||
|
||||
BytesTransfered = 0;
|
||||
|
||||
Open->TransferMdl = NULL;
|
||||
Status = NDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (Status != NDIS_STATUS_FAILURE)
|
||||
{
|
||||
|
||||
Open->Accepted++; // Increase the accepted packets counter
|
||||
|
||||
if( fres > (BytesTransfered+HeaderBufferSize+LookaheadBufferSize) )
|
||||
fres = BytesTransfered+HeaderBufferSize+LookaheadBufferSize;
|
||||
|
||||
//
|
||||
// Build the header
|
||||
//
|
||||
header=(struct bpf_hdr*)CurrBuff;
|
||||
GET_TIME(&header->bh_tstamp,&G_Start_Time);
|
||||
header->bh_caplen=fres;
|
||||
header->bh_datalen=PacketSize+HeaderBufferSize;
|
||||
if(Open->mode==MODE_CAPT){
|
||||
header->bh_hdrlen=NPFHdrSize;
|
||||
// Don't align if the packet goes to disk
|
||||
Ttail+=Packet_WORDALIGN(fres + NPFHdrSize);
|
||||
}
|
||||
else
|
||||
Ttail+=fres+NPFHdrSize;
|
||||
|
||||
//update the buffer
|
||||
NdisAcquireSpinLock( &Open->BufLock );
|
||||
|
||||
if(ResetBuff){
|
||||
Open->BLastByte = Open->Btail;
|
||||
}
|
||||
Open->Btail=Ttail;
|
||||
|
||||
NdisReleaseSpinLock( &Open->BufLock );
|
||||
}
|
||||
|
||||
if (Status != NDIS_STATUS_PENDING){
|
||||
|
||||
if( Open->TransferMdl != NULL)
|
||||
// Complete the request and free the buffers
|
||||
NPF_TransferDataComplete(Open,pPacketb,Status,fres);
|
||||
else{
|
||||
// Unfreeze the consumer
|
||||
if(GetBuffOccupation(Open)>Open->MinToCopy){
|
||||
if(Open->mode & MODE_DUMP){
|
||||
NdisSetEvent(&Open->DumpEvent);
|
||||
}
|
||||
else
|
||||
KeSetEvent(Open->ReadEvent,0,FALSE);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return NDIS_STATUS_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
VOID NPF_TransferDataComplete (IN NDIS_HANDLE ProtocolBindingContext,IN PNDIS_PACKET pPacket,
|
||||
IN NDIS_STATUS Status,IN UINT BytesTransfered)
|
||||
{
|
||||
POPEN_INSTANCE Open;
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: TransferDataComplete\n");)
|
||||
|
||||
Open= (POPEN_INSTANCE)ProtocolBindingContext;
|
||||
|
||||
IoFreeMdl(Open->TransferMdl);
|
||||
//recylcle the packet
|
||||
NdisReinitializePacket(pPacket);
|
||||
//Put the packet on the free queue
|
||||
NdisFreePacket(pPacket);
|
||||
// Unfreeze the consumer
|
||||
if(GetBuffOccupation(Open)>Open->MinToCopy){
|
||||
if(Open->mode & MODE_DUMP){
|
||||
NdisSetEvent(&Open->DumpEvent);
|
||||
}
|
||||
else
|
||||
KeSetEvent(Open->ReadEvent,0,FALSE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
VOID NPF_ReceiveComplete(IN NDIS_HANDLE ProtocolBindingContext)
|
||||
{
|
||||
IF_VERY_LOUD(DbgPrint("NPF: NPF_ReceiveComplete\n");)
|
||||
return;
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Developer Studio generated include file.
|
||||
// Used by NPF.RC
|
||||
//
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1000
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
|
@ -1,284 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#include "tme.h"
|
||||
#include "tcp_session.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <net/tme/tme.h>
|
||||
#include <net/tme/tcp_session.h>
|
||||
#else
|
||||
#include <tme/tme.h>
|
||||
#include <tme/tcp_session.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
uint32 tcp_session(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data)
|
||||
|
||||
{
|
||||
|
||||
uint32 next_status;
|
||||
uint32 direction=ULONG_AT(mem_data,12);
|
||||
uint8 flags=mem_ex->buffer[25];
|
||||
tcp_data *session=(tcp_data*)(block+data->key_len*4);
|
||||
|
||||
session->last_timestamp=session->timestamp_block;
|
||||
session->timestamp_block.tv_sec=0x7fffffff;
|
||||
|
||||
if (direction==session->direction)
|
||||
{
|
||||
session->pkts_cln_to_srv++;
|
||||
session->bytes_cln_to_srv+=pkt_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
session->pkts_srv_to_cln++;
|
||||
session->bytes_srv_to_cln+=pkt_size;
|
||||
}
|
||||
/* we use only thes four flags, we don't need PSH or URG */
|
||||
flags&=(ACK|FIN|SYN|RST);
|
||||
|
||||
switch (session->status)
|
||||
{
|
||||
case ERROR_TCP:
|
||||
next_status=ERROR_TCP;
|
||||
break;
|
||||
|
||||
case UNKNOWN:
|
||||
if (flags==SYN)
|
||||
{
|
||||
if (SW_ULONG_AT(mem_ex->buffer,20)!=0)
|
||||
{
|
||||
|
||||
next_status=ERROR_TCP;
|
||||
break;
|
||||
}
|
||||
next_status=SYN_RCV;
|
||||
session->syn_timestamp=session->last_timestamp;
|
||||
|
||||
session->direction=direction;
|
||||
session->seq_n_0_cln=SW_ULONG_AT(mem_ex->buffer,16);
|
||||
}
|
||||
else
|
||||
next_status=UNKNOWN;
|
||||
break;
|
||||
|
||||
case SYN_RCV:
|
||||
if ((flags&RST)&&(direction!=session->direction))
|
||||
{
|
||||
next_status=CLOSED_RST;
|
||||
break;
|
||||
}
|
||||
if ((flags==SYN)&&(direction==session->direction))
|
||||
{ /* two syns... */
|
||||
next_status=SYN_RCV;
|
||||
session->seq_n_0_cln=SW_ULONG_AT(mem_ex->buffer,16);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((flags==(SYN|ACK))&&(direction!=session->direction))
|
||||
{
|
||||
if (SW_ULONG_AT(mem_ex->buffer,20)!=session->seq_n_0_cln+1)
|
||||
{
|
||||
next_status=ERROR_TCP;
|
||||
break;
|
||||
}
|
||||
next_status=SYN_ACK_RCV;
|
||||
|
||||
session->syn_ack_timestamp=session->last_timestamp;
|
||||
|
||||
session->seq_n_0_srv=SW_ULONG_AT(mem_ex->buffer,16);
|
||||
session->ack_cln=session->seq_n_0_cln+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
next_status=ERROR_TCP;
|
||||
}
|
||||
break;
|
||||
|
||||
case SYN_ACK_RCV:
|
||||
if ((flags&ACK)&&(flags&RST)&&(direction==session->direction))
|
||||
{
|
||||
next_status=CLOSED_RST;
|
||||
session->ack_srv=SW_ULONG_AT(mem_ex->buffer,20);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((flags==ACK)&&(!(flags&(SYN|FIN|RST)))&&(direction==session->direction))
|
||||
{
|
||||
if (SW_ULONG_AT(mem_ex->buffer,20)!=session->seq_n_0_srv+1)
|
||||
{
|
||||
next_status=ERROR_TCP;
|
||||
break;
|
||||
}
|
||||
next_status=ESTABLISHED;
|
||||
session->ack_srv=session->seq_n_0_srv+1;
|
||||
break;
|
||||
}
|
||||
if ((flags&ACK)&&(flags&SYN)&&(direction!=session->direction))
|
||||
{
|
||||
next_status=SYN_ACK_RCV;
|
||||
break;
|
||||
}
|
||||
|
||||
next_status=ERROR_TCP;
|
||||
break;
|
||||
|
||||
case ESTABLISHED:
|
||||
if (flags&SYN)
|
||||
{
|
||||
if ((flags&ACK)&&
|
||||
(direction!=session->direction)&&
|
||||
((session->ack_cln-SW_ULONG_AT(mem_ex->buffer,20))<MAX_WINDOW)
|
||||
)
|
||||
{ /* SYN_ACK duplicato */
|
||||
next_status=ESTABLISHED;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((!(flags&ACK))&&
|
||||
(direction==session->direction)&&
|
||||
(SW_ULONG_AT(mem_ex->buffer,16)==session->seq_n_0_cln)&&
|
||||
(ULONG_AT(mem_ex->buffer,20)==0)
|
||||
)
|
||||
{ /* syn duplicato */
|
||||
next_status=ESTABLISHED;
|
||||
break;
|
||||
}
|
||||
|
||||
next_status=ERROR_TCP;
|
||||
break;
|
||||
}
|
||||
if (flags&ACK)
|
||||
if (direction==session->direction)
|
||||
{
|
||||
uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
|
||||
if (new_ack-session->ack_srv<MAX_WINDOW)
|
||||
session->ack_srv=new_ack;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
|
||||
if (new_ack-session->ack_cln<MAX_WINDOW)
|
||||
session->ack_cln=new_ack;
|
||||
}
|
||||
if (flags&RST)
|
||||
{
|
||||
next_status=CLOSED_RST;
|
||||
break;
|
||||
}
|
||||
if (flags&FIN)
|
||||
if (direction==session->direction)
|
||||
{ /* an hack to make all things work */
|
||||
session->ack_cln=SW_ULONG_AT(mem_ex->buffer,16);
|
||||
next_status=FIN_CLN_RCV;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
session->ack_srv=SW_ULONG_AT(mem_ex->buffer,16);
|
||||
next_status=FIN_SRV_RCV;
|
||||
break;
|
||||
}
|
||||
next_status=ESTABLISHED;
|
||||
break;
|
||||
|
||||
case CLOSED_RST:
|
||||
next_status=CLOSED_RST;
|
||||
break;
|
||||
|
||||
case FIN_SRV_RCV:
|
||||
if (flags&SYN)
|
||||
{
|
||||
next_status=ERROR_TCP;
|
||||
break;
|
||||
}
|
||||
|
||||
next_status=FIN_SRV_RCV;
|
||||
|
||||
if (flags&ACK)
|
||||
{
|
||||
uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
|
||||
if (direction!=session->direction)
|
||||
if ((new_ack-session->ack_cln)<MAX_WINDOW)
|
||||
session->ack_cln=new_ack;
|
||||
}
|
||||
|
||||
if (flags&RST)
|
||||
next_status=CLOSED_RST;
|
||||
else
|
||||
if ((flags&FIN)&&(direction==session->direction))
|
||||
{
|
||||
session->ack_cln=SW_ULONG_AT(mem_ex->buffer,16);
|
||||
next_status=CLOSED_FIN;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case FIN_CLN_RCV:
|
||||
if (flags&SYN)
|
||||
{
|
||||
next_status=ERROR_TCP;
|
||||
break;
|
||||
}
|
||||
|
||||
next_status=FIN_CLN_RCV;
|
||||
|
||||
if (flags&ACK)
|
||||
{
|
||||
uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
|
||||
if (direction==session->direction)
|
||||
if (new_ack-session->ack_srv<MAX_WINDOW)
|
||||
session->ack_srv=new_ack;
|
||||
}
|
||||
|
||||
if (flags&RST)
|
||||
next_status=CLOSED_RST;
|
||||
else
|
||||
if ((flags&FIN)&&(direction!=session->direction))
|
||||
{
|
||||
session->ack_srv=SW_ULONG_AT(mem_ex->buffer,16);
|
||||
next_status=CLOSED_FIN;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CLOSED_FIN:
|
||||
next_status=CLOSED_FIN;
|
||||
break;
|
||||
default:
|
||||
next_status=ERROR_TCP;
|
||||
|
||||
}
|
||||
|
||||
session->status=next_status;
|
||||
|
||||
if ((next_status==CLOSED_FIN)||(next_status==UNKNOWN)||(next_status==CLOSED_RST)||(next_status==ERROR_TCP))
|
||||
session->timestamp_block=session->last_timestamp;
|
||||
|
||||
return TME_SUCCESS;
|
||||
}
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifndef __tcp_session
|
||||
#define __tcp_session
|
||||
|
||||
#ifdef WIN32
|
||||
#include "tme.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <net/tme/tme.h>
|
||||
#else
|
||||
#include <tme/tme.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#define UNKNOWN 0
|
||||
#define SYN_RCV 1
|
||||
#define SYN_ACK_RCV 2
|
||||
#define ESTABLISHED 3
|
||||
#define CLOSED_RST 4
|
||||
#define FIN_CLN_RCV 5
|
||||
#define FIN_SRV_RCV 6
|
||||
#define CLOSED_FIN 7
|
||||
#define ERROR_TCP 8
|
||||
#define FIRST_IS_CLN 0
|
||||
#define FIRST_IS_SRV 0xffffffff
|
||||
#define FIN_CLN 1
|
||||
#define FIN_SRV 2
|
||||
|
||||
#define MAX_WINDOW 65536
|
||||
|
||||
typedef struct __tcp_data
|
||||
{
|
||||
struct timeval timestamp_block; /*DO NOT MOVE THIS VALUE*/
|
||||
struct timeval syn_timestamp;
|
||||
struct timeval last_timestamp;
|
||||
struct timeval syn_ack_timestamp;
|
||||
uint32 direction;
|
||||
uint32 seq_n_0_srv;
|
||||
uint32 seq_n_0_cln;
|
||||
uint32 ack_srv; /* acknowledge of (data sent by server) */
|
||||
uint32 ack_cln; /* acknowledge of (data sent by client) */
|
||||
uint32 status;
|
||||
uint32 pkts_cln_to_srv;
|
||||
uint32 pkts_srv_to_cln;
|
||||
uint32 bytes_srv_to_cln;
|
||||
uint32 bytes_cln_to_srv;
|
||||
uint32 close_state;
|
||||
}
|
||||
tcp_data;
|
||||
|
||||
#define FIN 1
|
||||
#define SYN 2
|
||||
#define RST 4
|
||||
#define PSH 8
|
||||
#define ACK 16
|
||||
#define URG 32
|
||||
|
||||
#define TCP_SESSION 0x00000800
|
||||
uint32 tcp_session(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,277 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#include "tme.h"
|
||||
#include "win_bpf.h"
|
||||
#include "time_calls.h"
|
||||
|
||||
|
||||
void TIME_DESYNCHRONIZE(struct time_conv *data)
|
||||
{
|
||||
data->reference = 0;
|
||||
data->start.tv_sec = 0;
|
||||
data->start.tv_usec = 0;
|
||||
}
|
||||
|
||||
#ifdef KQPC_TS
|
||||
|
||||
/* KeQueryPerformanceCounter TimeStamps */
|
||||
|
||||
VOID TIME_SYNCHRONIZE(struct time_conv *data)
|
||||
{
|
||||
struct timeval tmp;
|
||||
LARGE_INTEGER SystemTime;
|
||||
LARGE_INTEGER i;
|
||||
ULONG tmp2;
|
||||
LARGE_INTEGER TimeFreq,PTime;
|
||||
|
||||
if (data->reference!=0)
|
||||
return;
|
||||
|
||||
// get the absolute value of the system boot time.
|
||||
PTime=KeQueryPerformanceCounter(&TimeFreq);
|
||||
KeQuerySystemTime(&SystemTime);
|
||||
#ifndef __GNUC__
|
||||
tmp.tv_sec=(LONG)(SystemTime.QuadPart/10000000-11644473600);
|
||||
tmp.tv_usec=(LONG)((SystemTime.QuadPart%10000000)/10);
|
||||
tmp.tv_sec-=(ULONG)(PTime.QuadPart/TimeFreq.QuadPart);
|
||||
tmp.tv_usec-=(LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
|
||||
#else
|
||||
// TODO FIXME:
|
||||
#endif
|
||||
if (tmp.tv_usec<0) {
|
||||
tmp.tv_sec--;
|
||||
tmp.tv_usec+=1000000;
|
||||
}
|
||||
data->start=tmp;
|
||||
data->reference=1;
|
||||
}
|
||||
|
||||
void FORCE_TIME(struct timeval *src, struct time_conv *dest)
|
||||
{
|
||||
dest->start=*src;
|
||||
}
|
||||
|
||||
void GET_TIME(struct timeval *dst, struct time_conv *data)
|
||||
{
|
||||
LARGE_INTEGER PTime, TimeFreq;
|
||||
LONG tmp;
|
||||
|
||||
PTime=KeQueryPerformanceCounter(&TimeFreq);
|
||||
#ifndef __GNUC__
|
||||
tmp=(LONG)(PTime.QuadPart/TimeFreq.QuadPart);
|
||||
dst->tv_sec=data->start.tv_sec+tmp;
|
||||
dst->tv_usec=data->start.tv_usec+(LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
|
||||
#else
|
||||
// TODO FIXME:
|
||||
#endif
|
||||
if (dst->tv_usec>=1000000) {
|
||||
dst->tv_sec++;
|
||||
dst->tv_usec-=1000000;
|
||||
}
|
||||
}
|
||||
|
||||
#else /*KQPC_TS*/
|
||||
|
||||
/*RDTSC timestamps*/
|
||||
|
||||
/* callers must be at IRQL=PASSIVE_LEVEL */
|
||||
VOID TIME_SYNCHRONIZE(struct time_conv *data)
|
||||
{
|
||||
struct timeval tmp;
|
||||
LARGE_INTEGER system_time;
|
||||
ULONGLONG curr_ticks;
|
||||
KIRQL old;
|
||||
LARGE_INTEGER start_kqpc,stop_kqpc,start_freq,stop_freq;
|
||||
ULONGLONG start_ticks,stop_ticks;
|
||||
ULONGLONG delta,delta2;
|
||||
KEVENT event;
|
||||
LARGE_INTEGER i;
|
||||
ULONGLONG reference;
|
||||
|
||||
if (data->reference!=0)
|
||||
return;
|
||||
|
||||
KeInitializeEvent(&event,NotificationEvent,FALSE);
|
||||
i.QuadPart=-3500000;
|
||||
KeRaiseIrql(HIGH_LEVEL,&old);
|
||||
start_kqpc=KeQueryPerformanceCounter(&start_freq);
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push edx
|
||||
push ecx
|
||||
rdtsc
|
||||
lea ecx, start_ticks
|
||||
mov [ecx+4], edx
|
||||
mov [ecx], eax
|
||||
pop ecx
|
||||
pop edx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
asm("push %%eax;"
|
||||
"push %%edx;"
|
||||
"push %%ecx;"
|
||||
"rdtsc;"
|
||||
"lea %0,%%ecx;"
|
||||
"mov %%edx,(%%ecx+4);"
|
||||
"mov %%eax,(%%ecx);"
|
||||
"pop %%ecx;"
|
||||
"pop %%edx;"
|
||||
"pop %%eax;"
|
||||
:"=c"(start_ticks): );
|
||||
#endif
|
||||
KeLowerIrql(old);
|
||||
KeWaitForSingleObject(&event,UserRequest,KernelMode,TRUE ,&i);
|
||||
KeRaiseIrql(HIGH_LEVEL,&old);
|
||||
stop_kqpc=KeQueryPerformanceCounter(&stop_freq);
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push edx
|
||||
push ecx
|
||||
rdtsc
|
||||
lea ecx, stop_ticks
|
||||
mov [ecx+4], edx
|
||||
mov [ecx], eax
|
||||
pop ecx
|
||||
pop edx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
asm("push %%eax;"
|
||||
"push %%edx;"
|
||||
"push %%ecx;"
|
||||
"rdtsc;"
|
||||
"lea %0,%%ecx;"
|
||||
"mov %%edx,(%%ecx+4);"
|
||||
"mov %%eax,(%%ecx);"
|
||||
"pop %%ecx;"
|
||||
"pop %%edx;"
|
||||
"pop %%eax;"
|
||||
:"=c"(stop_ticks): );
|
||||
#endif
|
||||
KeLowerIrql(old);
|
||||
delta=stop_ticks-start_ticks;
|
||||
delta2=stop_kqpc.QuadPart-start_kqpc.QuadPart;
|
||||
if (delta>10000000000) {
|
||||
delta/=16;
|
||||
delta2/=16;
|
||||
}
|
||||
reference=delta*(start_freq.QuadPart)/delta2;
|
||||
data->reference=reference/1000;
|
||||
if (reference%1000>500)
|
||||
data->reference++;
|
||||
data->reference*=1000;
|
||||
reference=data->reference;
|
||||
KeQuerySystemTime(&system_time);
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push edx
|
||||
push ecx
|
||||
rdtsc
|
||||
lea ecx, curr_ticks
|
||||
mov [ecx+4], edx
|
||||
mov [ecx], eax
|
||||
pop ecx
|
||||
pop edx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
asm("push %%eax;"
|
||||
"push %%edx;"
|
||||
"push %%ecx;"
|
||||
"rdtsc;"
|
||||
"lea %0,%%ecx;"
|
||||
"mov %%edx,(%%ecx+4);"
|
||||
"mov %%eax,(%%ecx);"
|
||||
"pop %%ecx;"
|
||||
"pop %%edx;"
|
||||
"pop %%eax;"
|
||||
:"=c"(curr_ticks): );
|
||||
#endif
|
||||
tmp.tv_sec=-(LONG)(curr_ticks/reference);
|
||||
tmp.tv_usec=-(LONG)((curr_ticks%reference)*1000000/reference);
|
||||
system_time.QuadPart-=116444736000000000;
|
||||
tmp.tv_sec+=(LONG)(system_time.QuadPart/10000000);
|
||||
tmp.tv_usec+=(LONG)((system_time.QuadPart%10000000)/10);
|
||||
if (tmp.tv_usec<0) {
|
||||
tmp.tv_sec--;
|
||||
tmp.tv_usec+=1000000;
|
||||
}
|
||||
data->start=tmp;
|
||||
IF_LOUD(DbgPrint("Frequency %I64u MHz\n",data->reference);)
|
||||
}
|
||||
|
||||
void FORCE_TIME(struct timeval *src, struct time_conv *dest)
|
||||
{
|
||||
dest->start=*src;
|
||||
}
|
||||
|
||||
void GET_TIME(struct timeval *dst, struct time_conv *data)
|
||||
{
|
||||
ULONGLONG tmp;
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push edx
|
||||
push ecx
|
||||
rdtsc
|
||||
lea ecx, tmp
|
||||
mov [ecx+4], edx
|
||||
mov [ecx], eax
|
||||
pop ecx
|
||||
pop edx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
asm("push %%eax;"
|
||||
"push %%edx;"
|
||||
"push %%ecx;"
|
||||
"rdtsc;"
|
||||
"lea %0,%%ecx;"
|
||||
"mov %%edx,(%%ecx+4);"
|
||||
"mov %%eax,(%%ecx);"
|
||||
"pop %%ecx;"
|
||||
"pop %%edx;"
|
||||
"pop %%eax;"
|
||||
:"=c"(tmp): );
|
||||
#endif
|
||||
if (data->reference==0) {
|
||||
return;
|
||||
}
|
||||
dst->tv_sec=(LONG)(tmp/data->reference);
|
||||
dst->tv_usec=(LONG)((tmp-dst->tv_sec*data->reference)*1000000/data->reference);
|
||||
dst->tv_sec+=data->start.tv_sec;
|
||||
dst->tv_usec+=data->start.tv_usec;
|
||||
if (dst->tv_usec>=1000000) {
|
||||
dst->tv_sec++;
|
||||
dst->tv_usec-=1000000;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*KQPC_TS*/
|
|
@ -1,262 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifndef _time_calls
|
||||
#define _time_calls
|
||||
|
||||
#ifdef WIN_NT_DRIVER
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
/*!
|
||||
\brief A microsecond precise timestamp.
|
||||
|
||||
included in the sf_pkthdr or the bpf_hdr that NPF associates with every packet.
|
||||
*/
|
||||
|
||||
struct timeval {
|
||||
long tv_sec; ///< seconds
|
||||
long tv_usec; ///< microseconds
|
||||
};
|
||||
|
||||
#endif /*WIN_NT_DRIVER*/
|
||||
|
||||
struct time_conv {
|
||||
ULONGLONG reference;
|
||||
struct timeval start;
|
||||
};
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
void TIME_DESYNCHRONIZE(struct time_conv *data);
|
||||
VOID TIME_SYNCHRONIZE(struct time_conv *data);
|
||||
void FORCE_TIME(struct timeval *src, struct time_conv *dest);
|
||||
void GET_TIME(struct timeval *dst, struct time_conv *data);
|
||||
|
||||
#else /* __GNUC__ */
|
||||
|
||||
#ifdef WIN_NT_DRIVER
|
||||
|
||||
__inline void TIME_DESYNCHRONIZE(struct time_conv *data)
|
||||
{
|
||||
data->reference = 0;
|
||||
data->start.tv_sec = 0;
|
||||
data->start.tv_usec = 0;
|
||||
}
|
||||
|
||||
#ifdef KQPC_TS
|
||||
|
||||
/* KeQueryPerformanceCounter TimeStamps */
|
||||
|
||||
__inline VOID TIME_SYNCHRONIZE(struct time_conv *data)
|
||||
{
|
||||
struct timeval tmp;
|
||||
LARGE_INTEGER SystemTime;
|
||||
LARGE_INTEGER i;
|
||||
ULONG tmp2;
|
||||
LARGE_INTEGER TimeFreq,PTime;
|
||||
|
||||
if (data->reference!=0)
|
||||
return;
|
||||
|
||||
// get the absolute value of the system boot time.
|
||||
PTime=KeQueryPerformanceCounter(&TimeFreq);
|
||||
KeQuerySystemTime(&SystemTime);
|
||||
tmp.tv_sec=(LONG)(SystemTime.QuadPart/10000000-11644473600);
|
||||
tmp.tv_usec=(LONG)((SystemTime.QuadPart%10000000)/10);
|
||||
tmp.tv_sec-=(ULONG)(PTime.QuadPart/TimeFreq.QuadPart);
|
||||
tmp.tv_usec-=(LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
|
||||
if (tmp.tv_usec<0) {
|
||||
tmp.tv_sec--;
|
||||
tmp.tv_usec+=1000000;
|
||||
}
|
||||
data->start=tmp;
|
||||
data->reference=1;
|
||||
}
|
||||
|
||||
__inline void GET_TIME(struct timeval *dst, struct time_conv *data)
|
||||
{
|
||||
LARGE_INTEGER PTime, TimeFreq;
|
||||
LONG tmp;
|
||||
|
||||
PTime=KeQueryPerformanceCounter(&TimeFreq);
|
||||
tmp=(LONG)(PTime.QuadPart/TimeFreq.QuadPart);
|
||||
dst->tv_sec=data->start.tv_sec+tmp;
|
||||
dst->tv_usec=data->start.tv_usec+(LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
|
||||
if (dst->tv_usec>=1000000) {
|
||||
dst->tv_sec++;
|
||||
dst->tv_usec-=1000000;
|
||||
}
|
||||
}
|
||||
|
||||
__inline void FORCE_TIME(struct timeval *src, struct time_conv *dest)
|
||||
{
|
||||
dest->start=*src;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*RDTSC timestamps*/
|
||||
|
||||
/* callers must be at IRQL=PASSIVE_LEVEL */
|
||||
__inline VOID TIME_SYNCHRONIZE(struct time_conv *data)
|
||||
{
|
||||
struct timeval tmp;
|
||||
LARGE_INTEGER system_time;
|
||||
ULONGLONG curr_ticks;
|
||||
KIRQL old;
|
||||
LARGE_INTEGER start_kqpc,stop_kqpc,start_freq,stop_freq;
|
||||
ULONGLONG start_ticks,stop_ticks;
|
||||
ULONGLONG delta,delta2;
|
||||
KEVENT event;
|
||||
LARGE_INTEGER i;
|
||||
ULONGLONG reference;
|
||||
|
||||
if (data->reference!=0)
|
||||
return;
|
||||
|
||||
KeInitializeEvent(&event,NotificationEvent,FALSE);
|
||||
i.QuadPart=-3500000;
|
||||
KeRaiseIrql(HIGH_LEVEL,&old);
|
||||
start_kqpc=KeQueryPerformanceCounter(&start_freq);
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push edx
|
||||
push ecx
|
||||
rdtsc
|
||||
lea ecx, start_ticks
|
||||
mov [ecx+4], edx
|
||||
mov [ecx], eax
|
||||
pop ecx
|
||||
pop edx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
KeLowerIrql(old);
|
||||
KeWaitForSingleObject(&event,UserRequest,KernelMode,TRUE ,&i);
|
||||
KeRaiseIrql(HIGH_LEVEL,&old);
|
||||
stop_kqpc=KeQueryPerformanceCounter(&stop_freq);
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push edx
|
||||
push ecx
|
||||
rdtsc
|
||||
lea ecx, stop_ticks
|
||||
mov [ecx+4], edx
|
||||
mov [ecx], eax
|
||||
pop ecx
|
||||
pop edx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
KeLowerIrql(old);
|
||||
delta=stop_ticks-start_ticks;
|
||||
delta2=stop_kqpc.QuadPart-start_kqpc.QuadPart;
|
||||
if (delta>10000000000) {
|
||||
delta/=16;
|
||||
delta2/=16;
|
||||
}
|
||||
reference=delta*(start_freq.QuadPart)/delta2;
|
||||
data->reference=reference/1000;
|
||||
if (reference%1000>500)
|
||||
data->reference++;
|
||||
data->reference*=1000;
|
||||
reference=data->reference;
|
||||
KeQuerySystemTime(&system_time);
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push edx
|
||||
push ecx
|
||||
rdtsc
|
||||
lea ecx, curr_ticks
|
||||
mov [ecx+4], edx
|
||||
mov [ecx], eax
|
||||
pop ecx
|
||||
pop edx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
tmp.tv_sec=-(LONG)(curr_ticks/reference);
|
||||
tmp.tv_usec=-(LONG)((curr_ticks%reference)*1000000/reference);
|
||||
system_time.QuadPart-=116444736000000000;
|
||||
tmp.tv_sec+=(LONG)(system_time.QuadPart/10000000);
|
||||
tmp.tv_usec+=(LONG)((system_time.QuadPart%10000000)/10);
|
||||
if (tmp.tv_usec<0) {
|
||||
tmp.tv_sec--;
|
||||
tmp.tv_usec+=1000000;
|
||||
}
|
||||
data->start=tmp;
|
||||
IF_LOUD(DbgPrint("Frequency %I64u MHz\n",data->reference);)
|
||||
}
|
||||
|
||||
__inline void FORCE_TIME(struct timeval *src, struct time_conv *dest)
|
||||
{
|
||||
dest->start=*src;
|
||||
}
|
||||
|
||||
__inline void GET_TIME(struct timeval *dst, struct time_conv *data)
|
||||
{
|
||||
ULONGLONG tmp;
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push edx
|
||||
push ecx
|
||||
rdtsc
|
||||
lea ecx, tmp
|
||||
mov [ecx+4], edx
|
||||
mov [ecx], eax
|
||||
pop ecx
|
||||
pop edx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
if (data->reference==0) {
|
||||
return;
|
||||
}
|
||||
dst->tv_sec=(LONG)(tmp/data->reference);
|
||||
dst->tv_usec=(LONG)((tmp-dst->tv_sec*data->reference)*1000000/data->reference);
|
||||
dst->tv_sec+=data->start.tv_sec;
|
||||
dst->tv_usec+=data->start.tv_usec;
|
||||
if (dst->tv_usec>=1000000) {
|
||||
dst->tv_sec++;
|
||||
dst->tv_usec-=1000000;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*KQPC_TS*/
|
||||
|
||||
#endif /*WIN_NT_DRIVER*/
|
||||
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
#endif /*_time_calls*/
|
|
@ -1,379 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#include "tme.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <net/tme/tme.h>
|
||||
#endif
|
||||
|
||||
/* resizes extended memory */
|
||||
uint32 init_extended_memory(uint32 size, MEM_TYPE *mem_ex)
|
||||
{
|
||||
uint8 *tmp;
|
||||
|
||||
if ((mem_ex==NULL)||(mem_ex->buffer==NULL)||(size==0))
|
||||
return TME_ERROR; /* awfully never reached!!!! */
|
||||
|
||||
tmp=mem_ex->buffer;
|
||||
mem_ex->buffer=NULL;
|
||||
FREE_MEMORY(tmp);
|
||||
|
||||
ALLOCATE_MEMORY(tmp,uint8,size);
|
||||
if (tmp==NULL)
|
||||
return TME_ERROR; /* no memory */
|
||||
|
||||
mem_ex->size=size;
|
||||
mem_ex->buffer=tmp;
|
||||
return TME_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
/* activates a block of the TME */
|
||||
uint32 set_active_tme_block(TME_CORE *tme, uint32 block)
|
||||
{
|
||||
|
||||
if ((block>=MAX_TME_DATA_BLOCKS)||(!IS_VALIDATED(tme->validated_blocks,block)))
|
||||
return TME_ERROR;
|
||||
tme->active=block;
|
||||
tme->working=block;
|
||||
return TME_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
/* simply inserts default values in a TME block */
|
||||
/* it DOESN'T initialize the block in the core!! */
|
||||
/* FIXME default values are defined at compile time, */
|
||||
/* it will be useful to store them in the registry */
|
||||
uint32 init_tme_block(TME_CORE *tme, uint32 block)
|
||||
{
|
||||
|
||||
TME_DATA *data;
|
||||
if (block>=MAX_TME_DATA_BLOCKS)
|
||||
return TME_ERROR;
|
||||
data=&(tme->block_data[block]);
|
||||
tme->working=block;
|
||||
|
||||
ZERO_MEMORY(data,sizeof(TME_DATA));
|
||||
|
||||
/* entries in LUT */
|
||||
data->lut_entries=TME_LUT_ENTRIES_DEFAULT;
|
||||
/* blocks */
|
||||
data->shared_memory_blocks=TME_SHARED_MEMORY_BLOCKS_DEFAULT;
|
||||
/* block size */
|
||||
data->block_size=TME_BLOCK_SIZE_DEFAULT;
|
||||
/* lookup function */
|
||||
data->lookup_code=lut_fcn_mapper(TME_LOOKUP_CODE_DEFAULT);
|
||||
/* rehashing value */
|
||||
data->rehashing_value=TME_REHASHING_VALUE_DEFAULT;
|
||||
/* out lut function */
|
||||
data->out_lut_exec=TME_OUT_LUT_EXEC_DEFAULT;
|
||||
/* default function */
|
||||
data->default_exec=TME_DEFAULT_EXEC_DEFAULT;
|
||||
/* extra segment size */
|
||||
data->extra_segment_size=TME_EXTRA_SEGMENT_SIZE_DEFAULT;
|
||||
|
||||
|
||||
data->enable_deletion=FALSE;
|
||||
data->last_read.tv_sec=0;
|
||||
data->last_read.tv_usec=0;
|
||||
return TME_SUCCESS;
|
||||
|
||||
}
|
||||
/* it validates a TME block and */
|
||||
/* (on OK) inserts the block in the core */
|
||||
uint32 validate_tme_block(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 block, uint32 mem_ex_offset)
|
||||
{
|
||||
uint32 required_memory;
|
||||
uint8 *base=mem_ex_offset+mem_ex->buffer;
|
||||
TME_DATA *data;
|
||||
|
||||
/* FIXME soluzione un po' posticcia... */
|
||||
if (mem_ex_offset==0)
|
||||
return TME_ERROR;
|
||||
|
||||
if (block>=MAX_TME_DATA_BLOCKS)
|
||||
return TME_ERROR;
|
||||
data=&tme->block_data[block];
|
||||
|
||||
if (data->lut_entries==0)
|
||||
return TME_ERROR;
|
||||
|
||||
if (data->key_len==0)
|
||||
return TME_ERROR;
|
||||
|
||||
if (data->shared_memory_blocks==0)
|
||||
return TME_ERROR;
|
||||
|
||||
if (data->block_size==0)
|
||||
return TME_ERROR;
|
||||
|
||||
/* checks if the lookup function is valid */
|
||||
if (data->lookup_code==NULL)
|
||||
return TME_ERROR;
|
||||
|
||||
/* checks if the out lut exec function is valid */
|
||||
if (exec_fcn_mapper(data->out_lut_exec)==NULL)
|
||||
return TME_ERROR;
|
||||
|
||||
/* checks if the default exec function is valid */
|
||||
if (exec_fcn_mapper(data->default_exec)==NULL)
|
||||
return TME_ERROR;
|
||||
|
||||
/* let's calculate memory needed */
|
||||
required_memory=data->lut_entries*sizeof(RECORD); /*LUT*/
|
||||
required_memory+=data->block_size*data->shared_memory_blocks; /*shared segment*/
|
||||
required_memory+=data->extra_segment_size; /*extra segment*/
|
||||
|
||||
if (required_memory>(mem_ex->size-mem_ex_offset))
|
||||
return TME_ERROR; /*not enough memory*/
|
||||
|
||||
/* the TME block can be initialized */
|
||||
ZERO_MEMORY(base,required_memory);
|
||||
|
||||
data->lut_base_address=base;
|
||||
|
||||
data->shared_memory_base_address=
|
||||
data->lut_base_address+
|
||||
data->lut_entries*sizeof(RECORD);
|
||||
|
||||
data->extra_segment_base_address=
|
||||
data->shared_memory_base_address+
|
||||
data->block_size*data->shared_memory_blocks;
|
||||
data->filled_blocks=1;
|
||||
VALIDATE(tme->validated_blocks,block);
|
||||
tme->active=block;
|
||||
tme->working=block;
|
||||
return TME_SUCCESS;
|
||||
}
|
||||
|
||||
/* I/F between the bpf machine and the callbacks, just some checks */
|
||||
uint32 lookup_frontend(MEM_TYPE *mem_ex, TME_CORE *tme,uint32 mem_ex_offset, struct time_conv *time_ref)
|
||||
{
|
||||
if (tme->active==TME_NONE_ACTIVE)
|
||||
return TME_FALSE;
|
||||
|
||||
return (tme->block_data[tme->active].lookup_code)(mem_ex_offset+mem_ex->buffer,&tme->block_data[tme->active],mem_ex, time_ref);
|
||||
}
|
||||
|
||||
/* I/F between the bpf machine and the callbacks, just some checks */
|
||||
uint32 execute_frontend(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 pkt_size, uint32 offset)
|
||||
{
|
||||
|
||||
exec_fcn tmp;
|
||||
TME_DATA *data;
|
||||
uint8 *block;
|
||||
uint8 *mem_data;
|
||||
|
||||
if (tme->active==TME_NONE_ACTIVE)
|
||||
return TME_ERROR;
|
||||
|
||||
data=&tme->block_data[tme->active];
|
||||
|
||||
if (data->last_found==NULL)
|
||||
{ /*out lut exec */
|
||||
tmp=exec_fcn_mapper(data->out_lut_exec);
|
||||
block=data->shared_memory_base_address;
|
||||
}
|
||||
else
|
||||
{ /*checks if last_found is valid */
|
||||
if ((data->last_found<data->lut_base_address)||(data->last_found>=data->shared_memory_base_address))
|
||||
return TME_ERROR;
|
||||
else
|
||||
{
|
||||
tmp=exec_fcn_mapper(SW_ULONG_AT(&((RECORD*)data->last_found)->exec_fcn,0));
|
||||
if (tmp==NULL)
|
||||
return TME_ERROR;
|
||||
block=SW_ULONG_AT(&((RECORD*)data->last_found)->block,0)+mem_ex->buffer;
|
||||
if ((block<data->shared_memory_base_address)||(block>=data->extra_segment_base_address))
|
||||
return TME_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (offset>=mem_ex->size)
|
||||
return TME_ERROR;
|
||||
|
||||
mem_data=mem_ex->buffer+offset;
|
||||
|
||||
return tmp(block,pkt_size,data,mem_ex,mem_data);
|
||||
}
|
||||
|
||||
/*resets all the TME core*/
|
||||
uint32 reset_tme(TME_CORE *tme)
|
||||
{
|
||||
if (tme==NULL)
|
||||
return TME_ERROR;
|
||||
ZERO_MEMORY(tme, sizeof(TME_CORE));
|
||||
return TME_SUCCESS;
|
||||
}
|
||||
|
||||
/* returns a register value of the active TME block */
|
||||
/* FIXME last found in maniera elegante e veloce ?!?! */
|
||||
uint32 get_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 *rval)
|
||||
{
|
||||
switch(rgstr)
|
||||
{
|
||||
case TME_LUT_ENTRIES:
|
||||
*rval=data->lut_entries;
|
||||
return TME_SUCCESS;
|
||||
case TME_MAX_FILL_STATE:
|
||||
*rval=data->max_fill_state;
|
||||
return TME_SUCCESS;
|
||||
case TME_REHASHING_VALUE:
|
||||
*rval=data->rehashing_value;
|
||||
return TME_SUCCESS;
|
||||
case TME_KEY_LEN:
|
||||
*rval=data->key_len;
|
||||
return TME_SUCCESS;
|
||||
case TME_SHARED_MEMORY_BLOCKS:
|
||||
*rval=data->shared_memory_blocks;
|
||||
return TME_SUCCESS;
|
||||
case TME_FILLED_ENTRIES:
|
||||
*rval=data->filled_entries;
|
||||
return TME_SUCCESS;
|
||||
case TME_BLOCK_SIZE:
|
||||
*rval=data->block_size;
|
||||
return TME_SUCCESS;
|
||||
case TME_EXTRA_SEGMENT_SIZE:
|
||||
*rval=data->extra_segment_size;
|
||||
return TME_SUCCESS;
|
||||
case TME_FILLED_BLOCKS:
|
||||
*rval=data->filled_blocks;
|
||||
return TME_SUCCESS;
|
||||
case TME_DEFAULT_EXEC:
|
||||
*rval=data->default_exec;
|
||||
return TME_SUCCESS;
|
||||
case TME_OUT_LUT_EXEC:
|
||||
*rval=data->out_lut_exec;
|
||||
return TME_SUCCESS;
|
||||
case TME_SHARED_MEMORY_BASE_ADDRESS:
|
||||
*rval=data->shared_memory_base_address-mem_ex->buffer;
|
||||
return TME_SUCCESS;
|
||||
case TME_LUT_BASE_ADDRESS:
|
||||
*rval=data->lut_base_address-mem_ex->buffer;
|
||||
return TME_SUCCESS;
|
||||
case TME_EXTRA_SEGMENT_BASE_ADDRESS:
|
||||
*rval=data->extra_segment_base_address-mem_ex->buffer;
|
||||
return TME_SUCCESS;
|
||||
case TME_LAST_FOUND_BLOCK:
|
||||
if (data->last_found==NULL)
|
||||
*rval=0;
|
||||
else
|
||||
*rval=data->last_found-mem_ex->buffer;
|
||||
return TME_SUCCESS;
|
||||
|
||||
default:
|
||||
return TME_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* sets a register value in the active block */
|
||||
/* FIXME last found in maniera elegante e veloce ?!?! */
|
||||
uint32 set_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 value, int32 init)
|
||||
{ /* very very very dangerous!!!!!!!!!!! */
|
||||
lut_fcn tmp;
|
||||
switch(rgstr)
|
||||
{
|
||||
case TME_MAX_FILL_STATE:
|
||||
data->max_fill_state=value;
|
||||
return TME_SUCCESS;
|
||||
case TME_REHASHING_VALUE:
|
||||
data->rehashing_value=value;
|
||||
return TME_SUCCESS;
|
||||
case TME_FILLED_ENTRIES:
|
||||
data->filled_entries=value;
|
||||
return TME_SUCCESS;
|
||||
case TME_FILLED_BLOCKS:
|
||||
if (value<=data->shared_memory_blocks)
|
||||
{
|
||||
data->filled_blocks=value;
|
||||
return TME_SUCCESS;
|
||||
}
|
||||
else
|
||||
return TME_ERROR;
|
||||
case TME_DEFAULT_EXEC:
|
||||
data->default_exec=value;
|
||||
return TME_SUCCESS;
|
||||
case TME_OUT_LUT_EXEC:
|
||||
data->out_lut_exec=value;
|
||||
return TME_SUCCESS;
|
||||
case TME_LOOKUP_CODE:
|
||||
tmp=lut_fcn_mapper(value);
|
||||
if (tmp==NULL)
|
||||
return TME_ERROR;
|
||||
else
|
||||
data->lookup_code=tmp;
|
||||
return TME_SUCCESS;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (init)
|
||||
switch (rgstr)
|
||||
{
|
||||
|
||||
case TME_LUT_ENTRIES:
|
||||
data->lut_entries=value;
|
||||
return TME_SUCCESS;
|
||||
case TME_KEY_LEN:
|
||||
data->key_len=value;
|
||||
return TME_SUCCESS;
|
||||
case TME_SHARED_MEMORY_BLOCKS:
|
||||
data->shared_memory_blocks=value;
|
||||
return TME_SUCCESS;
|
||||
case TME_BLOCK_SIZE:
|
||||
data->block_size=value;
|
||||
return TME_SUCCESS;
|
||||
case TME_EXTRA_SEGMENT_SIZE:
|
||||
data->extra_segment_size=value;
|
||||
return TME_SUCCESS;
|
||||
default:
|
||||
return TME_ERROR;
|
||||
}
|
||||
else
|
||||
return TME_ERROR;
|
||||
|
||||
}
|
||||
|
||||
/* chooses the TME block for read */
|
||||
uint32 set_active_read_tme_block(TME_CORE *tme, uint32 block)
|
||||
{
|
||||
|
||||
if ((block>=MAX_TME_DATA_BLOCKS)||(!IS_VALIDATED(tme->validated_blocks,block)))
|
||||
return TME_ERROR;
|
||||
tme->active_read=block;
|
||||
return TME_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
/* chooses if the autodeletion must be used */
|
||||
uint32 set_autodeletion(TME_DATA *data, uint32 value)
|
||||
{
|
||||
if (value==0) /* no autodeletion */
|
||||
data->enable_deletion=FALSE;
|
||||
else
|
||||
data->enable_deletion=TRUE;
|
||||
|
||||
return TME_SUCCESS;
|
||||
}
|
||||
|
|
@ -1,183 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifndef __tme_include_
|
||||
#define __tme_include_
|
||||
|
||||
#ifdef WIN_NT_DRIVER
|
||||
|
||||
#include "ntddk.h"
|
||||
#include "memory_t.h"
|
||||
#include "time_calls.h"
|
||||
#endif /*WIN_NT_DRIVER*/
|
||||
|
||||
#ifdef WIN32
|
||||
#include "memory_t.h"
|
||||
#include "time_calls.h"
|
||||
#endif /*WIN32*/
|
||||
|
||||
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <net/tme/time_calls.h>
|
||||
#else
|
||||
#include <tme/time_calls.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* error codes */
|
||||
#define TME_ERROR 0
|
||||
#define TME_SUCCESS 1
|
||||
#define TME_TRUE 2
|
||||
#define TME_FALSE 3
|
||||
|
||||
/* some constants */
|
||||
#define DEFAULT_MEM_EX_SIZE 65536
|
||||
#define MAX_TME_DATA_BLOCKS 4
|
||||
#define TME_NONE_ACTIVE 0xffffffff
|
||||
#define DELTA_READ 2 /* secs */
|
||||
|
||||
#define TME_LUT_ENTRIES 0x00000000
|
||||
#define TME_MAX_FILL_STATE 0x00000001 /*potrebbe servire per un thread a passive level!?!?! */
|
||||
#define TME_REHASHING_VALUE 0x00000002
|
||||
#define TME_KEY_LEN 0x00000003
|
||||
#define TME_SHARED_MEMORY_BLOCKS 0x00000004
|
||||
#define TME_FILLED_ENTRIES 0x00000005
|
||||
#define TME_BLOCK_SIZE 0x00000006
|
||||
#define TME_EXTRA_SEGMENT_SIZE 0x00000007
|
||||
#define TME_LOOKUP_CODE 0x00000008
|
||||
#define TME_OUT_LUT_EXEC 0x00000009
|
||||
#define TME_FILLED_BLOCKS 0x0000000a
|
||||
#define TME_DEFAULT_EXEC 0x0000000b
|
||||
#define TME_LUT_BASE_ADDRESS 0x0000000c
|
||||
#define TME_SHARED_MEMORY_BASE_ADDRESS 0x0000000d
|
||||
#define TME_EXTRA_SEGMENT_BASE_ADDRESS 0x0000000e
|
||||
#define TME_LAST_FOUND 0x0000000f /* contains the offset of the last found entry */
|
||||
#define TME_LAST_FOUND_BLOCK 0x00000010
|
||||
/* TME default values */
|
||||
#define TME_LUT_ENTRIES_DEFAULT 32007
|
||||
#define TME_REHASHING_VALUE_DEFAULT 1
|
||||
#define TME_SHARED_MEMORY_BLOCKS_DEFAULT 16000
|
||||
#define TME_BLOCK_SIZE_DEFAULT 64
|
||||
#define TME_EXTRA_SEGMENT_SIZE_DEFAULT 0
|
||||
#define TME_LOOKUP_CODE_DEFAULT 0
|
||||
#define TME_OUT_LUT_EXEC_DEFAULT 0
|
||||
#define TME_DEFAULT_EXEC_DEFAULT 0
|
||||
#define TME_MAX_FILL_STATE_DEFAULT 15000
|
||||
|
||||
#define IS_VALIDATED(src,index) (src&(1<<index))
|
||||
|
||||
#define VALIDATE(src,index) src|=(1<<index);
|
||||
|
||||
|
||||
#define FORCE_NO_DELETION(timestamp) (struct timeval*)(timestamp)->tv_sec=0x7fffffff;
|
||||
|
||||
/* TME callback prototypes */
|
||||
#ifndef __GNUC__
|
||||
typedef uint32 (*lut_fcn)(uint8 *key, struct __TME_DATA *data,MEM_TYPE *mem_ex, struct time_conv *time_ref );
|
||||
typedef uint32 (*exec_fcn)(uint8 *block, uint32 pkt_size, struct __TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data);
|
||||
#else
|
||||
typedef uint32 (*lut_fcn)(uint8 *key, void *data,MEM_TYPE *mem_ex, struct time_conv *time_ref );
|
||||
typedef uint32 (*exec_fcn)(uint8 *block, uint32 pkt_size, void *data, MEM_TYPE *mem_ex, uint8 *mem_data);
|
||||
#endif
|
||||
|
||||
/* DO NOT MODIFY THIS STRUCTURE!!!! GV */
|
||||
typedef struct __RECORD
|
||||
|
||||
{
|
||||
uint32 block;
|
||||
uint32 exec_fcn;
|
||||
}
|
||||
RECORD, *PRECORD;
|
||||
|
||||
/* TME data registers */
|
||||
struct __TME_DATA
|
||||
{
|
||||
uint32 lut_entries;
|
||||
uint32 max_fill_state;
|
||||
uint32 rehashing_value;
|
||||
uint32 key_len;
|
||||
uint32 shared_memory_blocks;
|
||||
uint32 filled_entries;
|
||||
uint32 block_size;
|
||||
uint32 extra_segment_size;
|
||||
uint32 filled_blocks;
|
||||
lut_fcn lookup_code;
|
||||
uint32 default_exec;
|
||||
uint32 out_lut_exec;
|
||||
uint8 *lut_base_address;
|
||||
uint8 *shared_memory_base_address;
|
||||
uint8 *extra_segment_base_address;
|
||||
struct timeval last_read;
|
||||
uint32 enable_deletion;
|
||||
uint8 *last_found;
|
||||
};
|
||||
|
||||
typedef struct __TME_DATA TME_DATA,*PTME_DATA;
|
||||
|
||||
|
||||
|
||||
/* TME core */
|
||||
typedef struct __TME_CORE
|
||||
{
|
||||
uint32 working;
|
||||
uint32 active;
|
||||
uint32 validated_blocks;
|
||||
TME_DATA block_data[MAX_TME_DATA_BLOCKS];
|
||||
uint32 active_read;
|
||||
|
||||
} TME_CORE, *PTME_CORE;
|
||||
|
||||
static __inline int32 IS_DELETABLE(void *timestamp, TME_DATA *data)
|
||||
{
|
||||
struct timeval *ts=(struct timeval*)timestamp;
|
||||
|
||||
if (data->enable_deletion==FALSE)
|
||||
return FALSE;
|
||||
if (data->filled_entries<data->max_fill_state)
|
||||
return FALSE;
|
||||
if ((ts->tv_sec+DELTA_READ)<data->last_read.tv_sec)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* functions to manage TME */
|
||||
uint32 init_tme_block(TME_CORE *tme, uint32 block);
|
||||
uint32 validate_tme_block(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 block, uint32 mem_ex_offset);
|
||||
uint32 lookup_frontend(MEM_TYPE *mem_ex, TME_CORE *tme,uint32 mem_ex_offset, struct time_conv *time_ref);
|
||||
uint32 execute_frontend(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 pkt_size,uint32 offset);
|
||||
uint32 set_active_tme_block(TME_CORE *tme, uint32 block);
|
||||
uint32 init_extended_memory(uint32 size, MEM_TYPE *mem_ex);
|
||||
uint32 reset_tme(TME_CORE *tme);
|
||||
uint32 get_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 *rval);
|
||||
uint32 set_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 value, int32 init);
|
||||
uint32 set_active_read_tme_block(TME_CORE *tme, uint32 block);
|
||||
uint32 set_autodeletion(TME_DATA *data, uint32 value);
|
||||
|
||||
/* function mappers */
|
||||
lut_fcn lut_fcn_mapper(uint32 index);
|
||||
exec_fcn exec_fcn_mapper(uint32 index);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
u_short valid_instructions[]=
|
||||
{
|
||||
BPF_RET|BPF_K,
|
||||
BPF_RET|BPF_A,
|
||||
BPF_LD|BPF_IMM,
|
||||
BPF_LDX|BPF_IMM,
|
||||
BPF_LD|BPF_MEM,
|
||||
BPF_LDX|BPF_MEM,
|
||||
BPF_LD|BPF_MEM_EX_IMM|BPF_B,
|
||||
BPF_LD|BPF_MEM_EX_IMM|BPF_H,
|
||||
BPF_LD|BPF_MEM_EX_IMM|BPF_W,
|
||||
BPF_LD|BPF_MEM_EX_IND|BPF_B,
|
||||
BPF_LD|BPF_MEM_EX_IND|BPF_H,
|
||||
BPF_LD|BPF_MEM_EX_IND|BPF_W,
|
||||
BPF_LD|BPF_W|BPF_ABS,
|
||||
BPF_LD|BPF_H|BPF_ABS,
|
||||
BPF_LD|BPF_B|BPF_ABS,
|
||||
BPF_LDX|BPF_W|BPF_ABS,
|
||||
BPF_LDX|BPF_H|BPF_ABS,
|
||||
BPF_LDX|BPF_B|BPF_ABS,
|
||||
BPF_LD|BPF_W|BPF_LEN,
|
||||
BPF_LDX|BPF_W|BPF_LEN,
|
||||
BPF_LD|BPF_W|BPF_IND,
|
||||
BPF_LD|BPF_H|BPF_IND,
|
||||
BPF_LD|BPF_B|BPF_IND,
|
||||
BPF_LDX|BPF_MSH|BPF_B,
|
||||
BPF_ST,
|
||||
BPF_STX,
|
||||
BPF_ST|BPF_MEM_EX_IMM|BPF_B,
|
||||
BPF_STX|BPF_MEM_EX_IMM|BPF_B,
|
||||
BPF_ST|BPF_MEM_EX_IMM|BPF_W,
|
||||
BPF_STX|BPF_MEM_EX_IMM|BPF_W,
|
||||
BPF_ST|BPF_MEM_EX_IMM|BPF_H,
|
||||
BPF_STX|BPF_MEM_EX_IMM|BPF_H,
|
||||
BPF_ST|BPF_MEM_EX_IND|BPF_B,
|
||||
BPF_ST|BPF_MEM_EX_IND|BPF_W,
|
||||
BPF_ST|BPF_MEM_EX_IND|BPF_H,
|
||||
BPF_JMP|BPF_JA,
|
||||
BPF_JMP|BPF_JGT|BPF_K,
|
||||
BPF_JMP|BPF_JGE|BPF_K,
|
||||
BPF_JMP|BPF_JEQ|BPF_K,
|
||||
BPF_JMP|BPF_JSET|BPF_K,
|
||||
BPF_JMP|BPF_JGT|BPF_X,
|
||||
BPF_JMP|BPF_JGE|BPF_X,
|
||||
BPF_JMP|BPF_JEQ|BPF_X,
|
||||
BPF_JMP|BPF_JSET|BPF_X,
|
||||
BPF_ALU|BPF_ADD|BPF_X,
|
||||
BPF_ALU|BPF_SUB|BPF_X,
|
||||
BPF_ALU|BPF_MUL|BPF_X,
|
||||
BPF_ALU|BPF_DIV|BPF_X,
|
||||
BPF_ALU|BPF_AND|BPF_X,
|
||||
BPF_ALU|BPF_OR|BPF_X,
|
||||
BPF_ALU|BPF_LSH|BPF_X,
|
||||
BPF_ALU|BPF_RSH|BPF_X,
|
||||
BPF_ALU|BPF_ADD|BPF_K,
|
||||
BPF_ALU|BPF_SUB|BPF_K,
|
||||
BPF_ALU|BPF_MUL|BPF_K,
|
||||
BPF_ALU|BPF_DIV|BPF_K,
|
||||
BPF_ALU|BPF_AND|BPF_K,
|
||||
BPF_ALU|BPF_OR|BPF_K,
|
||||
BPF_ALU|BPF_LSH|BPF_K,
|
||||
BPF_ALU|BPF_RSH|BPF_K,
|
||||
BPF_ALU|BPF_NEG,
|
||||
BPF_MISC|BPF_TAX,
|
||||
BPF_MISC|BPF_TXA,
|
||||
BPF_MISC|BPF_TME|BPF_LOOKUP,
|
||||
BPF_MISC|BPF_TME|BPF_EXECUTE,
|
||||
BPF_MISC|BPF_TME|BPF_SET_ACTIVE,
|
||||
BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE,
|
||||
BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE
|
||||
};
|
||||
|
||||
#define VALID_INSTRUCTIONS_LEN (sizeof(valid_instructions)/sizeof(u_short))
|
|
@ -1,325 +0,0 @@
|
|||
/*-
|
||||
* Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from the Stanford/CMU enet packet filter,
|
||||
* (net/enet.c) distributed as part of 4.3BSD, and code contributed
|
||||
* to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
|
||||
* Berkeley Laboratory.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)bpf.h 7.1 (Berkeley) 5/7/91
|
||||
*
|
||||
* @(#) $Header: /cygdrive/c/RCVS/CVS/ReactOS/reactos/drivers/net/packet/win_bpf.h,v 1.3 2002/12/21 04:46:09 robd Exp $ (LBL)
|
||||
*/
|
||||
|
||||
#ifndef BPF_MAJOR_VERSION
|
||||
|
||||
/* BSD style release date */
|
||||
#define BPF_RELEASE 199606
|
||||
|
||||
typedef UCHAR u_char;
|
||||
typedef USHORT u_short;
|
||||
typedef ULONG u_int;
|
||||
typedef LONG bpf_int32;
|
||||
typedef ULONG bpf_u_int32;
|
||||
typedef ULONG u_int32;
|
||||
|
||||
#define BPF_MAXINSNS 512
|
||||
#define BPF_MAXBUFSIZE 0x8000
|
||||
#define BPF_MINBUFSIZE 32
|
||||
|
||||
#include "time_calls.h"
|
||||
|
||||
/*
|
||||
* The instruction data structure.
|
||||
*/
|
||||
struct bpf_insn {
|
||||
u_short code;
|
||||
u_char jt;
|
||||
u_char jf;
|
||||
bpf_int32 k;
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure for BIOCSETF.
|
||||
*/
|
||||
struct bpf_program {
|
||||
u_int bf_len;
|
||||
struct bpf_insn *bf_insns;
|
||||
};
|
||||
|
||||
/*
|
||||
* Struct returned by BIOCGSTATS.
|
||||
*/
|
||||
struct bpf_stat {
|
||||
u_int bs_recv; /* number of packets received */
|
||||
u_int bs_drop; /* number of packets dropped */
|
||||
};
|
||||
|
||||
/*
|
||||
* Struct return by BIOCVERSION. This represents the version number of
|
||||
* the filter language described by the instruction encodings below.
|
||||
* bpf understands a program iff kernel_major == filter_major &&
|
||||
* kernel_minor >= filter_minor, that is, if the value returned by the
|
||||
* running kernel has the same major number and a minor number equal
|
||||
* equal to or less than the filter being downloaded. Otherwise, the
|
||||
* results are undefined, meaning an error may be returned or packets
|
||||
* may be accepted haphazardly.
|
||||
* It has nothing to do with the source code version.
|
||||
*/
|
||||
struct bpf_version {
|
||||
u_short bv_major;
|
||||
u_short bv_minor;
|
||||
};
|
||||
/* Current version number of filter architecture. */
|
||||
#define BPF_MAJOR_VERSION 1
|
||||
#define BPF_MINOR_VERSION 1
|
||||
|
||||
|
||||
/*
|
||||
* Structure prepended to each packet.
|
||||
*/
|
||||
struct bpf_hdr {
|
||||
struct timeval bh_tstamp; /* time stamp */
|
||||
bpf_u_int32 bh_caplen; /* length of captured portion */
|
||||
bpf_u_int32 bh_datalen; /* original length of packet */
|
||||
u_short bh_hdrlen; /* length of bpf header (this struct
|
||||
plus alignment padding) */
|
||||
};
|
||||
|
||||
/*
|
||||
* Data-link level type codes.
|
||||
*/
|
||||
|
||||
/*
|
||||
* These are the types that are the same on all platforms; on other
|
||||
* platforms, a <net/bpf.h> should be supplied that defines the additional
|
||||
* DLT_* codes appropriately for that platform (the BSDs, for example,
|
||||
* should not just pick up this version of "bpf.h"; they should also define
|
||||
* the additional DLT_* codes used by their kernels, as well as the values
|
||||
* defined here - and, if the values they use for particular DLT_ types
|
||||
* differ from those here, they should use their values, not the ones
|
||||
* here).
|
||||
*/
|
||||
#define DLT_NULL 0 /* no link-layer encapsulation */
|
||||
#define DLT_EN10MB 1 /* Ethernet (10Mb) */
|
||||
#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */
|
||||
#define DLT_AX25 3 /* Amateur Radio AX.25 */
|
||||
#define DLT_PRONET 4 /* Proteon ProNET Token Ring */
|
||||
#define DLT_CHAOS 5 /* Chaos */
|
||||
#define DLT_IEEE802 6 /* IEEE 802 Networks */
|
||||
#define DLT_ARCNET 7 /* ARCNET */
|
||||
#define DLT_SLIP 8 /* Serial Line IP */
|
||||
#define DLT_PPP 9 /* Point-to-point Protocol */
|
||||
#define DLT_FDDI 10 /* FDDI */
|
||||
|
||||
/*
|
||||
* These are values from the traditional libpcap "bpf.h".
|
||||
* Ports of this to particular platforms should replace these definitions
|
||||
* with the ones appropriate to that platform, if the values are
|
||||
* different on that platform.
|
||||
*/
|
||||
#define DLT_ATM_RFC1483 11 /* LLC/SNAP encapsulated atm */
|
||||
#define DLT_RAW 12 /* raw IP */
|
||||
|
||||
/*
|
||||
* These are values from BSD/OS's "bpf.h".
|
||||
* These are not the same as the values from the traditional libpcap
|
||||
* "bpf.h"; however, these values shouldn't be generated by any
|
||||
* OS other than BSD/OS, so the correct values to use here are the
|
||||
* BSD/OS values.
|
||||
*
|
||||
* Platforms that have already assigned these values to other
|
||||
* DLT_ codes, however, should give these codes the values
|
||||
* from that platform, so that programs that use these codes will
|
||||
* continue to compile - even though they won't correctly read
|
||||
* files of these types.
|
||||
*/
|
||||
#define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */
|
||||
#define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */
|
||||
|
||||
#define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */
|
||||
|
||||
/*
|
||||
* This value is defined by NetBSD; other platforms should refrain from
|
||||
* using it for other purposes, so that NetBSD savefiles with a link
|
||||
* type of 50 can be read as this type on all platforms.
|
||||
*/
|
||||
#define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */
|
||||
|
||||
/*
|
||||
* This value was defined by libpcap 0.5; platforms that have defined
|
||||
* it with a different value should define it here with that value -
|
||||
* a link type of 104 in a save file will be mapped to DLT_C_HDLC,
|
||||
* whatever value that happens to be, so programs will correctly
|
||||
* handle files with that link type regardless of the value of
|
||||
* DLT_C_HDLC.
|
||||
*
|
||||
* The name DLT_C_HDLC was used by BSD/OS; we use that name for source
|
||||
* compatibility with programs written for BSD/OS.
|
||||
*
|
||||
* libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well,
|
||||
* for source compatibility with programs written for libpcap 0.5.
|
||||
*/
|
||||
#define DLT_C_HDLC 104 /* Cisco HDLC */
|
||||
#define DLT_CHDLC DLT_C_HDLC
|
||||
|
||||
/*
|
||||
* Reserved for future use.
|
||||
* Do not pick other numerical value for these unless you have also
|
||||
* picked up the tcpdump.org top-of-CVS-tree version of "savefile.c",
|
||||
* which will arrange that capture files for these DLT_ types have
|
||||
* the same "network" value on all platforms, regardless of what
|
||||
* value is chosen for their DLT_ type (thus allowing captures made
|
||||
* on one platform to be read on other platforms, even if the two
|
||||
* platforms don't use the same numerical values for all DLT_ types).
|
||||
*/
|
||||
#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */
|
||||
|
||||
/*
|
||||
* Values between 106 and 107 are used in capture file headers as
|
||||
* link-layer types corresponding to DLT_ types that might differ
|
||||
* between platforms; don't use those values for new DLT_ new types.
|
||||
*/
|
||||
|
||||
/*
|
||||
* OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except
|
||||
* that the AF_ type in the link-layer header is in network byte order.
|
||||
*
|
||||
* OpenBSD defines it as 12, but that collides with DLT_RAW, so we
|
||||
* define it as 108 here. If OpenBSD picks up this file, it should
|
||||
* define DLT_LOOP as 12 in its version, as per the comment above -
|
||||
* and should not use 108 for any purpose.
|
||||
*/
|
||||
#define DLT_LOOP 108
|
||||
|
||||
/*
|
||||
* Values between 109 and 112 are used in capture file headers as
|
||||
* link-layer types corresponding to DLT_ types that might differ
|
||||
* between platforms; don't use those values for new DLT_ new types.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is for Linux cooked sockets.
|
||||
*/
|
||||
#define DLT_LINUX_SLL 113
|
||||
|
||||
/*
|
||||
* The instruction encodings.
|
||||
*/
|
||||
/* instruction classes */
|
||||
#define BPF_CLASS(code) ((code) & 0x07)
|
||||
#define BPF_LD 0x00
|
||||
#define BPF_LDX 0x01
|
||||
#define BPF_ST 0x02
|
||||
#define BPF_STX 0x03
|
||||
#define BPF_ALU 0x04
|
||||
#define BPF_JMP 0x05
|
||||
#define BPF_RET 0x06
|
||||
#define BPF_MISC 0x07
|
||||
|
||||
/* ld/ldx fields */
|
||||
#define BPF_SIZE(code) ((code) & 0x18)
|
||||
#define BPF_W 0x00
|
||||
#define BPF_H 0x08
|
||||
#define BPF_B 0x10
|
||||
#define BPF_MODE(code) ((code) & 0xe0)
|
||||
#define BPF_IMM 0x00
|
||||
#define BPF_ABS 0x20
|
||||
#define BPF_IND 0x40
|
||||
#define BPF_MEM 0x60
|
||||
#define BPF_LEN 0x80
|
||||
#define BPF_MSH 0xa0
|
||||
|
||||
/* alu/jmp fields */
|
||||
#define BPF_OP(code) ((code) & 0xf0)
|
||||
#define BPF_ADD 0x00
|
||||
#define BPF_SUB 0x10
|
||||
#define BPF_MUL 0x20
|
||||
#define BPF_DIV 0x30
|
||||
#define BPF_OR 0x40
|
||||
#define BPF_AND 0x50
|
||||
#define BPF_LSH 0x60
|
||||
#define BPF_RSH 0x70
|
||||
#define BPF_NEG 0x80
|
||||
#define BPF_JA 0x00
|
||||
#define BPF_JEQ 0x10
|
||||
#define BPF_JGT 0x20
|
||||
#define BPF_JGE 0x30
|
||||
#define BPF_JSET 0x40
|
||||
#define BPF_SRC(code) ((code) & 0x08)
|
||||
#define BPF_K 0x00
|
||||
#define BPF_X 0x08
|
||||
|
||||
/* ret - BPF_K and BPF_X also apply */
|
||||
#define BPF_RVAL(code) ((code) & 0x18)
|
||||
#define BPF_A 0x10
|
||||
|
||||
/* misc */
|
||||
#define BPF_MISCOP(code) ((code) & 0xf8)
|
||||
#define BPF_TAX 0x00
|
||||
#define BPF_TXA 0x80
|
||||
|
||||
/* TME instructions */
|
||||
#define BPF_TME 0x08
|
||||
|
||||
#define BPF_LOOKUP 0x90
|
||||
#define BPF_EXECUTE 0xa0
|
||||
#define BPF_INIT 0xb0
|
||||
#define BPF_VALIDATE 0xc0
|
||||
#define BPF_SET_ACTIVE 0xd0
|
||||
#define BPF_RESET 0xe0
|
||||
#define BPF_SET_MEMORY 0x80
|
||||
#define BPF_GET_REGISTER_VALUE 0x70
|
||||
#define BPF_SET_REGISTER_VALUE 0x60
|
||||
#define BPF_SET_WORKING 0x50
|
||||
#define BPF_SET_ACTIVE_READ 0x40
|
||||
#define BPF_SET_AUTODELETION 0x30
|
||||
#define BPF_SEPARATION 0xff
|
||||
|
||||
#define BPF_MEM_EX_IMM 0xc0
|
||||
#define BPF_MEM_EX_IND 0xe0
|
||||
/*used for ST */
|
||||
#define BPF_MEM_EX 0xc0
|
||||
|
||||
|
||||
/*
|
||||
* Macros for insn array initializers.
|
||||
*/
|
||||
#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k }
|
||||
#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k }
|
||||
|
||||
/*
|
||||
* Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST).
|
||||
*/
|
||||
#define BPF_MEMWORDS 16
|
||||
|
||||
#endif
|
|
@ -1,962 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2000
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Portions copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from the Stanford/CMU enet packet filter,
|
||||
* (net/enet.c) distributed as part of 4.3BSD, and code contributed
|
||||
* to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
|
||||
* Berkeley Laboratory.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
|
||||
@(#)bpf.c 7.5 (Berkeley) 7/15/91
|
||||
*/
|
||||
|
||||
#include "tme.h"
|
||||
#include "win_bpf.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include "valid_insns.h"
|
||||
|
||||
#define EXTRACT_SHORT(p)\
|
||||
((u_short)\
|
||||
((u_short)*((u_char *)p+0)<<8|\
|
||||
(u_short)*((u_char *)p+1)<<0))
|
||||
#define EXTRACT_LONG(p)\
|
||||
((u_int32)*((u_char *)p+0)<<24|\
|
||||
(u_int32)*((u_char *)p+1)<<16|\
|
||||
(u_int32)*((u_char *)p+2)<<8|\
|
||||
(u_int32)*((u_char *)p+3)<<0)
|
||||
|
||||
|
||||
u_int bpf_filter(pc, p, wirelen, buflen,mem_ex,tme,time_ref)
|
||||
register struct bpf_insn *pc;
|
||||
register u_char *p;
|
||||
u_int wirelen;
|
||||
register u_int buflen;
|
||||
PMEM_TYPE mem_ex;
|
||||
PTME_CORE tme;
|
||||
struct time_conv *time_ref;
|
||||
|
||||
{
|
||||
register u_int32 A, X;
|
||||
register int k;
|
||||
u_int32 j,tmp;
|
||||
u_short tmp2;
|
||||
|
||||
int32 mem[BPF_MEMWORDS];
|
||||
|
||||
if (pc == 0)
|
||||
/*
|
||||
* No filter means accept all.
|
||||
*/
|
||||
return (u_int)-1;
|
||||
A = 0;
|
||||
X = 0;
|
||||
--pc;
|
||||
while (1) {
|
||||
++pc;
|
||||
switch (pc->code) {
|
||||
|
||||
default:
|
||||
|
||||
return 0;
|
||||
|
||||
case BPF_RET|BPF_K:
|
||||
return (u_int)pc->k;
|
||||
|
||||
case BPF_RET|BPF_A:
|
||||
return (u_int)A;
|
||||
|
||||
case BPF_LD|BPF_W|BPF_ABS:
|
||||
k = pc->k;
|
||||
if (k + sizeof(int32) > buflen) {
|
||||
return 0;
|
||||
}
|
||||
A = EXTRACT_LONG(&p[k]);
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_H|BPF_ABS:
|
||||
k = pc->k;
|
||||
if (k + sizeof(short) > buflen) {
|
||||
return 0;
|
||||
}
|
||||
A = EXTRACT_SHORT(&p[k]);
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_B|BPF_ABS:
|
||||
k = pc->k;
|
||||
if ((int)k >= (int)buflen) {
|
||||
return 0;
|
||||
}
|
||||
A = p[k];
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_W|BPF_LEN:
|
||||
A = wirelen;
|
||||
continue;
|
||||
|
||||
case BPF_LDX|BPF_W|BPF_LEN:
|
||||
X = wirelen;
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_W|BPF_IND:
|
||||
k = X + pc->k;
|
||||
if (k + sizeof(int32) > buflen) {
|
||||
return 0;
|
||||
}
|
||||
A = EXTRACT_LONG(&p[k]);
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_H|BPF_IND:
|
||||
k = X + pc->k;
|
||||
if (k + sizeof(short) > buflen) {
|
||||
return 0;
|
||||
}
|
||||
A = EXTRACT_SHORT(&p[k]);
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_B|BPF_IND:
|
||||
k = X + pc->k;
|
||||
if ((int)k >= (int)buflen) {
|
||||
return 0;
|
||||
}
|
||||
A = p[k];
|
||||
continue;
|
||||
|
||||
case BPF_LDX|BPF_MSH|BPF_B:
|
||||
k = pc->k;
|
||||
if ((int)k >= (int)buflen) {
|
||||
return 0;
|
||||
}
|
||||
X = (p[pc->k] & 0xf) << 2;
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_IMM:
|
||||
A = pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_LDX|BPF_IMM:
|
||||
X = pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM:
|
||||
A = mem[pc->k];
|
||||
continue;
|
||||
|
||||
case BPF_LDX|BPF_MEM:
|
||||
X = mem[pc->k];
|
||||
continue;
|
||||
|
||||
/* LD NO PACKET INSTRUCTIONS */
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IMM|BPF_B:
|
||||
A= mem_ex->buffer[pc->k];
|
||||
continue;
|
||||
|
||||
case BPF_LDX|BPF_MEM_EX_IMM|BPF_B:
|
||||
X= mem_ex->buffer[pc->k];
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IMM|BPF_H:
|
||||
A = EXTRACT_SHORT(&mem_ex->buffer[pc->k]);
|
||||
continue;
|
||||
|
||||
case BPF_LDX|BPF_MEM_EX_IMM|BPF_H:
|
||||
X = EXTRACT_SHORT(&mem_ex->buffer[pc->k]);
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IMM|BPF_W:
|
||||
A = EXTRACT_LONG(&mem_ex->buffer[pc->k]);
|
||||
continue;
|
||||
|
||||
case BPF_LDX|BPF_MEM_EX_IMM|BPF_W:
|
||||
X = EXTRACT_LONG(&mem_ex->buffer[pc->k]);
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IND|BPF_B:
|
||||
k = X + pc->k;
|
||||
if ((int32)k>= (int32)mem_ex->size) {
|
||||
return 0;
|
||||
}
|
||||
A= mem_ex->buffer[k];
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IND|BPF_H:
|
||||
k = X + pc->k;
|
||||
if ((int32)(k+1)>= (int32)mem_ex->size) {
|
||||
return 0;
|
||||
}
|
||||
A=EXTRACT_SHORT((uint32*)&mem_ex->buffer[k]);
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IND|BPF_W:
|
||||
k = X + pc->k;
|
||||
if ((int32)(k+3)>= (int32)mem_ex->size) {
|
||||
return 0;
|
||||
}
|
||||
A=EXTRACT_LONG((uint32*)&mem_ex->buffer[k]);
|
||||
continue;
|
||||
/* END LD NO PACKET INSTRUCTIONS */
|
||||
|
||||
case BPF_ST:
|
||||
mem[pc->k] = A;
|
||||
continue;
|
||||
|
||||
case BPF_STX:
|
||||
mem[pc->k] = X;
|
||||
continue;
|
||||
|
||||
/* STORE INSTRUCTIONS */
|
||||
case BPF_ST|BPF_MEM_EX_IMM|BPF_B:
|
||||
mem_ex->buffer[pc->k]=(uint8)A;
|
||||
continue;
|
||||
|
||||
case BPF_STX|BPF_MEM_EX_IMM|BPF_B:
|
||||
mem_ex->buffer[pc->k]=(uint8)X;
|
||||
continue;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IMM|BPF_W:
|
||||
tmp=A;
|
||||
*(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp);
|
||||
continue;
|
||||
|
||||
case BPF_STX|BPF_MEM_EX_IMM|BPF_W:
|
||||
tmp=X;
|
||||
*(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp);
|
||||
continue;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IMM|BPF_H:
|
||||
tmp2=(uint16)A;
|
||||
*(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2);
|
||||
continue;
|
||||
|
||||
case BPF_STX|BPF_MEM_EX_IMM|BPF_H:
|
||||
tmp2=(uint16)X;
|
||||
*(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2);
|
||||
continue;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IND|BPF_B:
|
||||
mem_ex->buffer[pc->k+X]=(uint8)A;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IND|BPF_W:
|
||||
tmp=A;
|
||||
*(uint32*)&mem_ex->buffer[pc->k+X]=EXTRACT_LONG(&tmp);
|
||||
continue;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IND|BPF_H:
|
||||
tmp2=(uint16)A;
|
||||
*(uint16*)&mem_ex->buffer[pc->k+X]=EXTRACT_SHORT(&tmp2);
|
||||
continue;
|
||||
/* END STORE INSTRUCTIONS */
|
||||
|
||||
case BPF_JMP|BPF_JA:
|
||||
pc += pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JGT|BPF_K:
|
||||
pc += ((int)A > (int)pc->k) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JGE|BPF_K:
|
||||
pc += ((int)A >= (int)pc->k) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JEQ|BPF_K:
|
||||
pc += ((int)A == (int)pc->k) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JSET|BPF_K:
|
||||
pc += (A & pc->k) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JGT|BPF_X:
|
||||
pc += (A > X) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JGE|BPF_X:
|
||||
pc += (A >= X) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JEQ|BPF_X:
|
||||
pc += (A == X) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JSET|BPF_X:
|
||||
pc += (A & X) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_ADD|BPF_X:
|
||||
A += X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_SUB|BPF_X:
|
||||
A -= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_MUL|BPF_X:
|
||||
A *= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_DIV|BPF_X:
|
||||
if (X == 0)
|
||||
return 0;
|
||||
A /= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_AND|BPF_X:
|
||||
A &= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_OR|BPF_X:
|
||||
A |= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_LSH|BPF_X:
|
||||
A <<= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_RSH|BPF_X:
|
||||
A >>= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_ADD|BPF_K:
|
||||
A += pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_SUB|BPF_K:
|
||||
A -= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_MUL|BPF_K:
|
||||
A *= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_DIV|BPF_K:
|
||||
A /= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_AND|BPF_K:
|
||||
A &= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_OR|BPF_K:
|
||||
A |= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_LSH|BPF_K:
|
||||
A <<= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_RSH|BPF_K:
|
||||
A >>= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_NEG:
|
||||
(int)A = -((int)A);
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TAX:
|
||||
X = A;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TXA:
|
||||
A = X;
|
||||
continue;
|
||||
|
||||
/* TME INSTRUCTIONS */
|
||||
case BPF_MISC|BPF_TME|BPF_LOOKUP:
|
||||
j=lookup_frontend(mem_ex,tme,pc->k,time_ref);
|
||||
if (j==TME_ERROR)
|
||||
return 0;
|
||||
pc += (j == TME_TRUE) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_EXECUTE:
|
||||
if (execute_frontend(mem_ex,tme,wirelen,pc->k)==TME_ERROR)
|
||||
return 0;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_SET_ACTIVE:
|
||||
if (set_active_tme_block(tme,pc->k)==TME_ERROR)
|
||||
return 0;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE:
|
||||
if (get_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,&j)==TME_ERROR)
|
||||
return 0;
|
||||
A=j;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE:
|
||||
if (set_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,A,FALSE)==TME_ERROR)
|
||||
return 0;
|
||||
continue;
|
||||
/* END TME INSTRUCTIONS */
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
u_int bpf_filter_with_2_buffers(pc, p, pd, headersize, wirelen, buflen, mem_ex,tme,time_ref)
|
||||
register struct bpf_insn *pc;
|
||||
register u_char *p;
|
||||
register u_char *pd;
|
||||
register int headersize;
|
||||
u_int wirelen;
|
||||
register u_int buflen;
|
||||
PMEM_TYPE mem_ex;
|
||||
PTME_CORE tme;
|
||||
struct time_conv *time_ref;
|
||||
{
|
||||
register u_int32 A, X;
|
||||
register int k;
|
||||
int32 mem[BPF_MEMWORDS];
|
||||
u_int32 j,tmp;
|
||||
u_short tmp2;
|
||||
|
||||
if (pc == 0)
|
||||
/*
|
||||
* No filter means accept all.
|
||||
*/
|
||||
return (u_int)-1;
|
||||
A = 0;
|
||||
X = 0;
|
||||
--pc;
|
||||
while (1) {
|
||||
++pc;
|
||||
switch (pc->code) {
|
||||
|
||||
default:
|
||||
|
||||
return 0;
|
||||
|
||||
case BPF_RET|BPF_K:
|
||||
return (u_int)pc->k;
|
||||
|
||||
case BPF_RET|BPF_A:
|
||||
return (u_int)A;
|
||||
|
||||
case BPF_LD|BPF_W|BPF_ABS:
|
||||
k = pc->k;
|
||||
if (k + sizeof(int32) > buflen) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(k + (int)sizeof(int32) < headersize) A = EXTRACT_LONG(&p[k]);
|
||||
else if(k + 2 == headersize){
|
||||
A=(u_int32)*((u_char *)p+k)<<24|
|
||||
(u_int32)*((u_char *)p+k+1)<<16|
|
||||
(u_int32)*((u_char *)p+k+2)<<8|
|
||||
(u_int32)*((u_char *)pd+k-headersize);
|
||||
}
|
||||
else if(k == headersize-1){
|
||||
A=(u_int32)*((u_char *)p+k)<<24|
|
||||
(u_int32)*((u_char *)p+k+1)<<16|
|
||||
(u_int32)*((u_char *)pd+k-headersize)<<8|
|
||||
(u_int32)*((u_char *)pd+k-headersize+1);
|
||||
}
|
||||
else if(k == headersize){
|
||||
A=(u_int32)*((u_char *)p+k)<<24|
|
||||
(u_int32)*((u_char *)pd+k-headersize+1)<<16|
|
||||
(u_int32)*((u_char *)pd+k-headersize+2)<<8|
|
||||
(u_int32)*((u_char *)pd+k-headersize+3);
|
||||
}
|
||||
A = EXTRACT_LONG(&pd[k-headersize]);
|
||||
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_H|BPF_ABS:
|
||||
k = pc->k;
|
||||
if (k + sizeof(short) > buflen) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(k + (int)sizeof(short) < headersize) A = EXTRACT_SHORT(&p[k]);
|
||||
else if(k == headersize){
|
||||
A=(u_short)*((u_char *)p+k)<<8|
|
||||
(u_short)*((u_char *)pd+k-headersize);
|
||||
}
|
||||
A = EXTRACT_SHORT(&pd[k-headersize]);
|
||||
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_B|BPF_ABS:
|
||||
k = pc->k;
|
||||
if ((int)k >= (int)buflen) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(k<headersize) A = p[k];
|
||||
else A = pd[k-headersize];
|
||||
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_W|BPF_LEN:
|
||||
A = wirelen;
|
||||
continue;
|
||||
|
||||
case BPF_LDX|BPF_W|BPF_LEN:
|
||||
X = wirelen;
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_W|BPF_IND:
|
||||
k = X + pc->k;
|
||||
if (k + sizeof(int32) > buflen) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(k + (int)sizeof(int32) < headersize) A = EXTRACT_LONG(&p[k]);
|
||||
else if(k + (int)sizeof(int32) == headersize+2){
|
||||
A=(u_int32)*((u_char *)p+k)<<24|
|
||||
(u_int32)*((u_char *)p+k+1)<<16|
|
||||
(u_int32)*((u_char *)p+k+2)<<8|
|
||||
(u_int32)*((u_char *)pd+k-headersize);
|
||||
}
|
||||
else if(k + (int)sizeof(int32) == headersize+3){
|
||||
A=(u_int32)*((u_char *)p+k)<<24|
|
||||
(u_int32)*((u_char *)p+k+1)<<16|
|
||||
(u_int32)*((u_char *)pd+k-headersize)<<8|
|
||||
(u_int32)*((u_char *)pd+k-headersize+1);
|
||||
}
|
||||
else if(k + (int)sizeof(int32) == headersize+4){
|
||||
A=(u_int32)*((u_char *)p+k)<<24|
|
||||
(u_int32)*((u_char *)pd+k-headersize+1)<<16|
|
||||
(u_int32)*((u_char *)pd+k-headersize+2)<<8|
|
||||
(u_int32)*((u_char *)pd+k-headersize+3);
|
||||
}
|
||||
A = EXTRACT_LONG(&pd[k-headersize]);
|
||||
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_H|BPF_IND:
|
||||
k = X + pc->k;
|
||||
if (k + sizeof(short) > buflen) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(k + (int)sizeof(short) < headersize) A = EXTRACT_SHORT(&p[k]);
|
||||
else if(k == headersize){
|
||||
A=(u_short)*((u_char *)p+k)<<8|
|
||||
(u_short)*((u_char *)pd+k-headersize);
|
||||
}
|
||||
A = EXTRACT_SHORT(&pd[k-headersize]);
|
||||
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_B|BPF_IND:
|
||||
k = X + pc->k;
|
||||
if ((int)k >= (int)buflen) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(k<headersize) A = p[k];
|
||||
else A = pd[k-headersize];
|
||||
|
||||
continue;
|
||||
|
||||
case BPF_LDX|BPF_MSH|BPF_B:
|
||||
k = pc->k;
|
||||
if ((int)k >= (int)buflen) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if((pc->k)<headersize) X = (p[pc->k] & 0xf) << 2;
|
||||
else X = (pd[(pc->k)-headersize] & 0xf) << 2;
|
||||
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_IMM:
|
||||
A = pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_LDX|BPF_IMM:
|
||||
X = pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM:
|
||||
A = mem[pc->k];
|
||||
continue;
|
||||
|
||||
case BPF_LDX|BPF_MEM:
|
||||
X = mem[pc->k];
|
||||
continue;
|
||||
|
||||
/* LD NO PACKET INSTRUCTIONS */
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IMM|BPF_B:
|
||||
A= mem_ex->buffer[pc->k];
|
||||
continue;
|
||||
|
||||
case BPF_LDX|BPF_MEM_EX_IMM|BPF_B:
|
||||
X= mem_ex->buffer[pc->k];
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IMM|BPF_H:
|
||||
A = EXTRACT_SHORT(&mem_ex->buffer[pc->k]);
|
||||
continue;
|
||||
|
||||
case BPF_LDX|BPF_MEM_EX_IMM|BPF_H:
|
||||
X = EXTRACT_SHORT(&mem_ex->buffer[pc->k]);
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IMM|BPF_W:
|
||||
A = EXTRACT_LONG(&mem_ex->buffer[pc->k]);
|
||||
continue;
|
||||
|
||||
case BPF_LDX|BPF_MEM_EX_IMM|BPF_W:
|
||||
X = EXTRACT_LONG(&mem_ex->buffer[pc->k]);
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IND|BPF_B:
|
||||
k = X + pc->k;
|
||||
if ((int32)k>= (int32)mem_ex->size) {
|
||||
return 0;
|
||||
}
|
||||
A= mem_ex->buffer[k];
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IND|BPF_H:
|
||||
k = X + pc->k;
|
||||
if ((int32)(k+1)>= (int32)mem_ex->size) {
|
||||
return 0;
|
||||
}
|
||||
A=EXTRACT_SHORT((uint32*)&mem_ex->buffer[k]);
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IND|BPF_W:
|
||||
k = X + pc->k;
|
||||
if ((int32)(k+3)>= (int32)mem_ex->size) {
|
||||
return 0;
|
||||
}
|
||||
A=EXTRACT_LONG((uint32*)&mem_ex->buffer[k]);
|
||||
continue;
|
||||
/* END LD NO PACKET INSTRUCTIONS */
|
||||
|
||||
case BPF_ST:
|
||||
mem[pc->k] = A;
|
||||
continue;
|
||||
|
||||
case BPF_STX:
|
||||
mem[pc->k] = X;
|
||||
continue;
|
||||
|
||||
|
||||
/* STORE INSTRUCTIONS */
|
||||
case BPF_ST|BPF_MEM_EX_IMM|BPF_B:
|
||||
mem_ex->buffer[pc->k]=(uint8)A;
|
||||
continue;
|
||||
|
||||
case BPF_STX|BPF_MEM_EX_IMM|BPF_B:
|
||||
mem_ex->buffer[pc->k]=(uint8)X;
|
||||
continue;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IMM|BPF_W:
|
||||
tmp=A;
|
||||
*(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp);
|
||||
continue;
|
||||
|
||||
case BPF_STX|BPF_MEM_EX_IMM|BPF_W:
|
||||
tmp=X;
|
||||
*(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp);
|
||||
continue;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IMM|BPF_H:
|
||||
tmp2=(uint16)A;
|
||||
*(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2);
|
||||
continue;
|
||||
|
||||
case BPF_STX|BPF_MEM_EX_IMM|BPF_H:
|
||||
tmp2=(uint16)X;
|
||||
*(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2);
|
||||
continue;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IND|BPF_B:
|
||||
mem_ex->buffer[pc->k+X]=(uint8)A;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IND|BPF_W:
|
||||
tmp=A;
|
||||
*(uint32*)&mem_ex->buffer[pc->k+X]=EXTRACT_LONG(&tmp);
|
||||
continue;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IND|BPF_H:
|
||||
tmp2=(uint16)A;
|
||||
*(uint16*)&mem_ex->buffer[pc->k+X]=EXTRACT_SHORT(&tmp2);
|
||||
continue;
|
||||
/* END STORE INSTRUCTIONS */
|
||||
|
||||
|
||||
|
||||
case BPF_JMP|BPF_JA:
|
||||
pc += pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JGT|BPF_K:
|
||||
pc += ((int)A > (int)pc->k) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JGE|BPF_K:
|
||||
pc += ((int)A >= (int)pc->k) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JEQ|BPF_K:
|
||||
pc += ((int)A == (int)pc->k) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JSET|BPF_K:
|
||||
pc += (A & pc->k) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JGT|BPF_X:
|
||||
pc += (A > X) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JGE|BPF_X:
|
||||
pc += (A >= X) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JEQ|BPF_X:
|
||||
pc += (A == X) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JSET|BPF_X:
|
||||
pc += (A & X) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_ADD|BPF_X:
|
||||
A += X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_SUB|BPF_X:
|
||||
A -= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_MUL|BPF_X:
|
||||
A *= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_DIV|BPF_X:
|
||||
if (X == 0)
|
||||
return 0;
|
||||
A /= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_AND|BPF_X:
|
||||
A &= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_OR|BPF_X:
|
||||
A |= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_LSH|BPF_X:
|
||||
A <<= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_RSH|BPF_X:
|
||||
A >>= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_ADD|BPF_K:
|
||||
A += pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_SUB|BPF_K:
|
||||
A -= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_MUL|BPF_K:
|
||||
A *= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_DIV|BPF_K:
|
||||
A /= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_AND|BPF_K:
|
||||
A &= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_OR|BPF_K:
|
||||
A |= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_LSH|BPF_K:
|
||||
A <<= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_RSH|BPF_K:
|
||||
A >>= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_NEG:
|
||||
(int)A = -((int)A);
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TAX:
|
||||
X = A;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TXA:
|
||||
A = X;
|
||||
continue;
|
||||
|
||||
/* TME INSTRUCTIONS */
|
||||
case BPF_MISC|BPF_TME|BPF_LOOKUP:
|
||||
j=lookup_frontend(mem_ex,tme,pc->k,time_ref);
|
||||
if (j==TME_ERROR)
|
||||
return 0;
|
||||
pc += (j == TME_TRUE) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_EXECUTE:
|
||||
if (execute_frontend(mem_ex,tme,wirelen,pc->k)==TME_ERROR)
|
||||
return 0;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_SET_ACTIVE:
|
||||
if (set_active_tme_block(tme,pc->k)==TME_ERROR)
|
||||
return 0;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE:
|
||||
if (get_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,&j)==TME_ERROR)
|
||||
return 0;
|
||||
A=j;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE:
|
||||
if (set_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,A,FALSE)==TME_ERROR)
|
||||
return 0;
|
||||
continue;
|
||||
/* END TME INSTRUCTIONS */
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32
|
||||
bpf_validate(f, len,mem_ex_size)
|
||||
struct bpf_insn *f;
|
||||
int32 len;
|
||||
uint32 mem_ex_size;
|
||||
{
|
||||
register int32 i,j;
|
||||
register struct bpf_insn *p;
|
||||
int32 flag;
|
||||
|
||||
for (i = 0; i < len; ++i) {
|
||||
/*
|
||||
* Check that that jumps are forward, and within
|
||||
* the code block.
|
||||
*/
|
||||
|
||||
p = &f[i];
|
||||
|
||||
IF_LOUD(DbgPrint("Validating program");)
|
||||
|
||||
flag=0;
|
||||
for(j=0;j<VALID_INSTRUCTIONS_LEN;j++)
|
||||
if (p->code==valid_instructions[j])
|
||||
flag=1;
|
||||
if (flag==0)
|
||||
return 0;
|
||||
|
||||
IF_LOUD(DbgPrint("Validating program: no unknown instructions");)
|
||||
|
||||
if (BPF_CLASS(p->code) == BPF_JMP) {
|
||||
register int32 from = i + 1;
|
||||
|
||||
if (BPF_OP(p->code) == BPF_JA) {
|
||||
if (from + p->k >= len)
|
||||
return 0;
|
||||
}
|
||||
else if (from + p->jt >= len || from + p->jf >= len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
IF_LOUD(DbgPrint("Validating program: no wrong JUMPS");)
|
||||
|
||||
/*
|
||||
* Check that memory operations use valid addresses.
|
||||
*/
|
||||
if (((BPF_CLASS(p->code) == BPF_ST && ((p->code &BPF_MEM_EX_IMM)!=BPF_MEM_EX_IMM && (p->code &BPF_MEM_EX_IND)!=BPF_MEM_EX_IND)) ||
|
||||
(BPF_CLASS(p->code) == BPF_LD &&
|
||||
(p->code & 0xe0) == BPF_MEM)) &&
|
||||
(p->k >= BPF_MEMWORDS || p->k < 0))
|
||||
return 0;
|
||||
|
||||
IF_LOUD(DbgPrint("Validating program: no wrong ST/LD memory locations");)
|
||||
|
||||
/*
|
||||
* Check if key stores use valid addresses
|
||||
*/
|
||||
if (BPF_CLASS(p->code) == BPF_ST && (p->code &BPF_MEM_EX_IMM)==BPF_MEM_EX_IMM)
|
||||
switch (BPF_SIZE(p->code))
|
||||
{
|
||||
case BPF_W: if (p->k<0 || p->k+3>=(int32)mem_ex_size) return 0;
|
||||
case BPF_H: if (p->k<0 || p->k+1>=(int32)mem_ex_size) return 0;
|
||||
case BPF_B: if (p->k<0 || p->k>=(int32)mem_ex_size) return 0;
|
||||
}
|
||||
|
||||
IF_LOUD(DbgPrint("Validating program: no wrong ST/LD mem_ex locations");)
|
||||
|
||||
/*
|
||||
* Check for constant division by 0.
|
||||
*/
|
||||
if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0)
|
||||
return 0;
|
||||
}
|
||||
return BPF_CLASS(f[len - 1].code) == BPF_RET;
|
||||
}
|
||||
|
|
@ -1,689 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Portions copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from the Stanford/CMU enet packet filter,
|
||||
* (net/enet.c) distributed as part of 4.3BSD, and code contributed
|
||||
* to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
|
||||
* Berkeley Laboratory.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "tme.h"
|
||||
#include "win_bpf.h"
|
||||
|
||||
/*
|
||||
* Initialize the filter machine
|
||||
*/
|
||||
uint32 bpf_filter_init(register struct bpf_insn *pc, MEM_TYPE *mem_ex, TME_CORE *tme, struct time_conv *time_ref)
|
||||
{
|
||||
register uint32 A, X;
|
||||
int32 mem[BPF_MEMWORDS];
|
||||
register int32 k;
|
||||
uint32 *tmp;
|
||||
uint16 *tmp2;
|
||||
uint32 j;
|
||||
if (pc == 0)
|
||||
/*
|
||||
* No filter means accept all.
|
||||
*/
|
||||
return (uint32)-1;
|
||||
A = 0;
|
||||
X = 0;
|
||||
--pc;
|
||||
while (1) {
|
||||
++pc;
|
||||
switch (pc->code) {
|
||||
|
||||
default:
|
||||
return 0;
|
||||
|
||||
/* RET INSTRUCTIONS */
|
||||
case BPF_RET|BPF_K:
|
||||
return (uint32)pc->k;
|
||||
|
||||
case BPF_RET|BPF_A:
|
||||
return (uint32)A;
|
||||
/* END RET INSTRUCTIONS */
|
||||
|
||||
/* LD NO PACKET INSTRUCTIONS */
|
||||
case BPF_LD|BPF_IMM:
|
||||
A = pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_LDX|BPF_IMM:
|
||||
X = pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM:
|
||||
A = mem[pc->k];
|
||||
continue;
|
||||
|
||||
case BPF_LDX|BPF_MEM:
|
||||
X = mem[pc->k];
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IMM|BPF_B:
|
||||
A= mem_ex->buffer[pc->k];
|
||||
continue;
|
||||
|
||||
case BPF_LDX|BPF_MEM_EX_IMM|BPF_B:
|
||||
X= mem_ex->buffer[pc->k];
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IMM|BPF_H:
|
||||
tmp2=(uint16*)&mem_ex->buffer[pc->k];
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
mov ebx,tmp2
|
||||
xor eax, eax
|
||||
mov ax, [ebx]
|
||||
bswap eax
|
||||
mov A, eax
|
||||
pop ebx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
asm("push %%eax;"
|
||||
"push %%ebx;"
|
||||
"mov %1,%%ebx;"
|
||||
"xor %%eax, %%eax;"
|
||||
"mov (%%ebx), %%ax;"
|
||||
"bswap %%eax;"
|
||||
"mov %%eax, %0;"
|
||||
"pop %%ebx;"
|
||||
"pop %%eax;"
|
||||
:"=a"(A),"=c"(tmp2): );
|
||||
#endif
|
||||
continue;
|
||||
|
||||
case BPF_LDX|BPF_MEM_EX_IMM|BPF_H:
|
||||
tmp2=(uint16*)&mem_ex->buffer[pc->k];
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
mov ebx,tmp2
|
||||
xor eax, eax
|
||||
mov ax, [ebx]
|
||||
bswap eax
|
||||
mov X, eax
|
||||
pop ebx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
asm("push %%eax;"
|
||||
"push %%ebx;"
|
||||
"mov %1,%%ebx;"
|
||||
"xor %%eax, %%eax;"
|
||||
"mov (%%ebx), %%ax;"
|
||||
"bswap %%eax;"
|
||||
"mov %%eax, %0;"
|
||||
"pop %%ebx;"
|
||||
"pop %%eax;"
|
||||
:"=a"(X),"=c"(tmp2): );
|
||||
#endif
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IMM|BPF_W:
|
||||
tmp=(uint32*)&mem_ex->buffer[pc->k];
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
mov ebx,tmp
|
||||
mov eax, [ebx]
|
||||
bswap eax
|
||||
mov A, eax
|
||||
pop ebx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
asm("push %%eax;"
|
||||
"push %%ebx;"
|
||||
"mov %1,%%ebx;"
|
||||
"xor %%eax, %%eax;"
|
||||
"mov (%%ebx), %%ax;"
|
||||
"bswap %%eax;"
|
||||
"mov %%eax, %0;"
|
||||
"pop %%ebx;"
|
||||
"pop %%eax;"
|
||||
:"=a"(A),"=c"(tmp): );
|
||||
#endif
|
||||
continue;
|
||||
|
||||
case BPF_LDX|BPF_MEM_EX_IMM|BPF_W:
|
||||
tmp=(uint32*)&mem_ex->buffer[pc->k];
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
mov ebx,tmp
|
||||
mov eax, [ebx]
|
||||
bswap eax
|
||||
mov X, eax
|
||||
pop ebx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
asm("push %%eax;"
|
||||
"push %%ebx;"
|
||||
"mov %1,%%ebx;"
|
||||
"xor %%eax, %%eax;"
|
||||
"mov (%%ebx), %%ax;"
|
||||
"bswap %%eax;"
|
||||
"mov %%eax, %0;"
|
||||
"pop %%ebx;"
|
||||
"pop %%eax;"
|
||||
:"=a"(X),"=c"(tmp): );
|
||||
#endif
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IND|BPF_B:
|
||||
k = X + pc->k;
|
||||
if ((int32)k>= (int32)mem_ex->size) {
|
||||
return 0;
|
||||
}
|
||||
A= mem_ex->buffer[k];
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IND|BPF_H:
|
||||
k = X + pc->k;
|
||||
if ((int32)(k+1)>= (int32)mem_ex->size) {
|
||||
return 0;
|
||||
}
|
||||
tmp2=(uint16*)&mem_ex->buffer[k];
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
mov ebx,tmp2
|
||||
xor eax, eax
|
||||
mov ax, [ebx]
|
||||
bswap eax
|
||||
mov A, eax
|
||||
pop ebx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
asm("push %%eax;"
|
||||
"push %%ebx;"
|
||||
"mov %1,%%ebx;"
|
||||
"xor %%eax, %%eax;"
|
||||
"mov (%%ebx), %%ax;"
|
||||
"bswap %%eax;"
|
||||
"mov %%eax, %0;"
|
||||
"pop %%ebx;"
|
||||
"pop %%eax;"
|
||||
:"=a"(A),"=c"(tmp2): );
|
||||
#endif
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IND|BPF_W:
|
||||
k = X + pc->k;
|
||||
if ((int32)(k+3)>= (int32)mem_ex->size) {
|
||||
return 0;
|
||||
}
|
||||
tmp=(uint32*)&mem_ex->buffer[k];
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
mov ebx,tmp
|
||||
mov eax, [ebx]
|
||||
bswap eax
|
||||
mov A, eax
|
||||
pop ebx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
asm("push %%eax;"
|
||||
"push %%ebx;"
|
||||
"mov %1,%%ebx;"
|
||||
"xor %%eax, %%eax;"
|
||||
"mov (%%ebx), %%ax;"
|
||||
"bswap %%eax;"
|
||||
"mov %%eax, %0;"
|
||||
"pop %%ebx;"
|
||||
"pop %%eax;"
|
||||
:"=a"(A),"=c"(tmp): );
|
||||
#endif
|
||||
continue;
|
||||
/* END LD NO PACKET INSTRUCTIONS */
|
||||
|
||||
/* STORE INSTRUCTIONS */
|
||||
case BPF_ST:
|
||||
mem[pc->k] = A;
|
||||
continue;
|
||||
|
||||
case BPF_STX:
|
||||
mem[pc->k] = X;
|
||||
continue;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IMM|BPF_B:
|
||||
mem_ex->buffer[pc->k]=(uint8)A;
|
||||
continue;
|
||||
|
||||
case BPF_STX|BPF_MEM_EX_IMM|BPF_B:
|
||||
mem_ex->buffer[pc->k]=(uint8)X;
|
||||
continue;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IMM|BPF_W:
|
||||
tmp=(uint32*)&mem_ex->buffer[pc->k];
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
mov ebx, tmp
|
||||
mov eax, A
|
||||
bswap eax
|
||||
mov [ebx], eax
|
||||
pop ebx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
asm("push %%eax;"
|
||||
"push %%ebx;"
|
||||
"mov %1,%%ebx;"
|
||||
"xor %%eax, %%eax;"
|
||||
"mov (%%ebx), %%ax;"
|
||||
"bswap %%eax;"
|
||||
"mov %%eax, %0;"
|
||||
"pop %%ebx;"
|
||||
"pop %%eax;"
|
||||
:"=a"(A),"=c"(tmp): );
|
||||
#endif
|
||||
continue;
|
||||
|
||||
case BPF_STX|BPF_MEM_EX_IMM|BPF_W:
|
||||
tmp=(uint32*)&mem_ex->buffer[pc->k];
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
mov ebx, tmp
|
||||
mov eax, X
|
||||
bswap eax
|
||||
mov [ebx], eax
|
||||
pop ebx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
asm("push %%eax;"
|
||||
"push %%ebx;"
|
||||
"mov %1,%%ebx;"
|
||||
"xor %%eax, %%eax;"
|
||||
"mov (%%ebx), %%ax;"
|
||||
"bswap %%eax;"
|
||||
"mov %%eax, %0;"
|
||||
"pop %%ebx;"
|
||||
"pop %%eax;"
|
||||
:"=a"(X),"=c"(tmp): );
|
||||
#endif
|
||||
continue;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IMM|BPF_H:
|
||||
tmp2=(uint16*)&mem_ex->buffer[pc->k];
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
mov ebx, tmp2
|
||||
mov eax, A
|
||||
xchg ah, al
|
||||
mov [ebx], ax
|
||||
pop ebx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
asm("push %%eax;"
|
||||
"push %%ebx;"
|
||||
"mov %1,%%ebx;"
|
||||
"xor %%eax, %%eax;"
|
||||
"mov (%%ebx), %%ax;"
|
||||
"bswap %%eax;"
|
||||
"mov %%eax, %0;"
|
||||
"pop %%ebx;"
|
||||
"pop %%eax;"
|
||||
:"=a"(A),"=c"(tmp2): );
|
||||
#endif
|
||||
continue;
|
||||
|
||||
case BPF_STX|BPF_MEM_EX_IMM|BPF_H:
|
||||
tmp2=(uint16*)&mem_ex->buffer[pc->k];
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
mov ebx, tmp2
|
||||
mov eax, X
|
||||
xchg ah, al
|
||||
mov [ebx], ax
|
||||
pop ebx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
asm("push %%eax;"
|
||||
"push %%ebx;"
|
||||
"mov %1,%%ebx;"
|
||||
"xor %%eax, %%eax;"
|
||||
"mov (%%ebx), %%ax;"
|
||||
"bswap %%eax;"
|
||||
"mov %%eax, %0;"
|
||||
"pop %%ebx;"
|
||||
"pop %%eax;"
|
||||
:"=a"(X),"=c"(tmp2): );
|
||||
#endif
|
||||
continue;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IND|BPF_B:
|
||||
mem_ex->buffer[pc->k+X]=(uint8)A;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IND|BPF_W:
|
||||
tmp=(uint32*)&mem_ex->buffer[pc->k+X];
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
mov ebx, tmp
|
||||
mov eax, A
|
||||
bswap eax
|
||||
mov [ebx], eax
|
||||
pop ebx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
asm("push %%eax;"
|
||||
"push %%ebx;"
|
||||
"mov %1,%%ebx;"
|
||||
"xor %%eax, %%eax;"
|
||||
"mov (%%ebx), %%ax;"
|
||||
"bswap %%eax;"
|
||||
"mov %%eax, %0;"
|
||||
"pop %%ebx;"
|
||||
"pop %%eax;"
|
||||
:"=a"(A),"=c"(tmp): );
|
||||
#endif
|
||||
continue;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IND|BPF_H:
|
||||
tmp2=(uint16*)&mem_ex->buffer[pc->k+X];
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
mov ebx, tmp2
|
||||
mov eax, A
|
||||
xchg ah, al
|
||||
mov [ebx], ax
|
||||
pop ebx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
asm("push %%eax;"
|
||||
"push %%ebx;"
|
||||
"mov %1,%%ebx;"
|
||||
"xor %%eax, %%eax;"
|
||||
"mov (%%ebx), %%ax;"
|
||||
"bswap %%eax;"
|
||||
"mov %%eax, %0;"
|
||||
"pop %%ebx;"
|
||||
"pop %%eax;"
|
||||
:"=a"(A),"=c"(tmp2): );
|
||||
#endif
|
||||
continue;
|
||||
/* END STORE INSTRUCTIONS */
|
||||
|
||||
/* JUMP INSTRUCTIONS */
|
||||
case BPF_JMP|BPF_JA:
|
||||
pc += pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JGT|BPF_K:
|
||||
pc += ((int32)A > (int32)pc->k) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JGE|BPF_K:
|
||||
pc += ((int32)A >= (int32)pc->k) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JEQ|BPF_K:
|
||||
pc += ((int32)A == (int32)pc->k) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JSET|BPF_K:
|
||||
pc += (A & pc->k) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JGT|BPF_X:
|
||||
pc += (A > X) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JGE|BPF_X:
|
||||
pc += (A >= X) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JEQ|BPF_X:
|
||||
pc += (A == X) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JSET|BPF_X:
|
||||
pc += (A & X) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
/* END JUMP INSTRUCTIONS */
|
||||
|
||||
/* ARITHMETIC INSTRUCTIONS */
|
||||
case BPF_ALU|BPF_ADD|BPF_X:
|
||||
A += X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_SUB|BPF_X:
|
||||
A -= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_MUL|BPF_X:
|
||||
A *= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_DIV|BPF_X:
|
||||
if (X == 0)
|
||||
return 0;
|
||||
A /= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_AND|BPF_X:
|
||||
A &= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_OR|BPF_X:
|
||||
A |= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_LSH|BPF_X:
|
||||
A <<= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_RSH|BPF_X:
|
||||
A >>= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_ADD|BPF_K:
|
||||
A += pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_SUB|BPF_K:
|
||||
A -= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_MUL|BPF_K:
|
||||
A *= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_DIV|BPF_K:
|
||||
A /= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_AND|BPF_K:
|
||||
A &= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_OR|BPF_K:
|
||||
A |= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_LSH|BPF_K:
|
||||
A <<= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_RSH|BPF_K:
|
||||
A >>= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_NEG:
|
||||
(int32)A = -((int32)A);
|
||||
continue;
|
||||
/* ARITHMETIC INSTRUCTIONS */
|
||||
|
||||
/* MISC INSTRUCTIONS */
|
||||
case BPF_MISC|BPF_TAX:
|
||||
X = A;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TXA:
|
||||
A = X;
|
||||
continue;
|
||||
/* END MISC INSTRUCTIONS */
|
||||
|
||||
/* TME INSTRUCTIONS */
|
||||
case BPF_MISC|BPF_TME|BPF_LOOKUP:
|
||||
j=lookup_frontend(mem_ex,tme,pc->k,time_ref);
|
||||
if (j==TME_ERROR)
|
||||
return 0;
|
||||
pc += (j == TME_TRUE) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_EXECUTE:
|
||||
if (execute_frontend(mem_ex,tme,0,pc->k)==TME_ERROR)
|
||||
return 0;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_INIT:
|
||||
if (init_tme_block(tme,pc->k)==TME_ERROR)
|
||||
return 0;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_VALIDATE:
|
||||
if (validate_tme_block(mem_ex,tme,A,pc->k)==TME_ERROR)
|
||||
return 0;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_SET_MEMORY:
|
||||
if (init_extended_memory(pc->k,mem_ex)==TME_ERROR)
|
||||
return 0;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_SET_ACTIVE:
|
||||
if (set_active_tme_block(tme,pc->k)==TME_ERROR)
|
||||
return 0;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_SET_ACTIVE_READ:
|
||||
if (set_active_tme_block(tme,pc->k)==TME_ERROR)
|
||||
return 0;
|
||||
continue;
|
||||
case BPF_MISC|BPF_TME|BPF_SET_WORKING:
|
||||
if ((pc->k<0)||(pc->k>=MAX_TME_DATA_BLOCKS))
|
||||
return 0;
|
||||
tme->working=pc->k;
|
||||
continue;
|
||||
|
||||
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_RESET:
|
||||
if (reset_tme(tme)==TME_ERROR)
|
||||
return 0;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE:
|
||||
if (get_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,&j)==TME_ERROR)
|
||||
return 0;
|
||||
A=j;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE:
|
||||
if (set_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,A,TRUE)==TME_ERROR)
|
||||
return 0;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_SET_AUTODELETION:
|
||||
set_autodeletion(&tme->block_data[tme->working],pc->k);
|
||||
continue;
|
||||
|
||||
/* END TME INSTRUCTIONS */
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
#ifndef __FILTER_INIT
|
||||
#define __FILTER_INIT
|
||||
|
||||
#include "tme.h"
|
||||
|
||||
#define INIT_OK 1
|
||||
#define INIT_ERROR 0
|
||||
|
||||
uint32 bpf_filter_init(register struct bpf_insn *pc,MEM_TYPE *mem_ex, TME_CORE *tme, struct time_conv *time_ref);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,366 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2000
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include "stdarg.h"
|
||||
#include "ntddk.h"
|
||||
#include "ntiologc.h"
|
||||
#include "ndis.h"
|
||||
#else
|
||||
#include <ddk/ntddk.h>
|
||||
#include <net/ndis.h>
|
||||
#define NdisReinitializePacket(Packet) \
|
||||
{ \
|
||||
(Packet)->Private.Head = (PNDIS_BUFFER)NULL; \
|
||||
(Packet)->Private.ValidCounts = FALSE; \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
#include "packet.h"
|
||||
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
NTSTATUS
|
||||
NPF_Write(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
)
|
||||
|
||||
{
|
||||
POPEN_INSTANCE Open;
|
||||
PIO_STACK_LOCATION IrpSp;
|
||||
PNDIS_PACKET pPacket;
|
||||
UINT i;
|
||||
NDIS_STATUS Status;
|
||||
|
||||
IF_LOUD(DbgPrint("NPF_Write\n");)
|
||||
|
||||
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
|
||||
Open=IrpSp->FileObject->FsContext;
|
||||
|
||||
IF_LOUD(DbgPrint("Max frame size = %d\n", Open->MaxFrameSize);)
|
||||
|
||||
|
||||
if(IrpSp->Parameters.Write.Length == 0 || // Check that the buffer provided by the user is not empty
|
||||
Open->MaxFrameSize == 0 || // Check that the MaxFrameSize is correctly initialized
|
||||
IrpSp->Parameters.Write.Length > Open->MaxFrameSize) // Check that the fame size is smaller that the MTU
|
||||
{
|
||||
IF_LOUD(DbgPrint("frame size out of range, send aborted\n");)
|
||||
|
||||
Irp->IoStatus.Status = NDIS_STATUS_SUCCESS;
|
||||
IoCompleteRequest (Irp, IO_NO_INCREMENT);
|
||||
return NDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
IoMarkIrpPending(Irp);
|
||||
|
||||
Open->Multiple_Write_Counter=Open->Nwrites;
|
||||
|
||||
NdisResetEvent(&Open->WriteEvent);
|
||||
|
||||
|
||||
for(i=0;i<Open->Nwrites;i++){
|
||||
|
||||
// Try to get a packet from our list of free ones
|
||||
NdisAllocatePacket(
|
||||
&Status,
|
||||
&pPacket,
|
||||
Open->PacketPool
|
||||
);
|
||||
|
||||
if (Status != NDIS_STATUS_SUCCESS) {
|
||||
|
||||
// No free packets
|
||||
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
IoCompleteRequest (Irp, IO_NO_INCREMENT);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
// The packet has a buffer that needs not to be freed after every single write
|
||||
RESERVED(pPacket)->FreeBufAfterWrite = FALSE;
|
||||
|
||||
// Save the IRP associated with the packet
|
||||
RESERVED(pPacket)->Irp=Irp;
|
||||
|
||||
// Attach the writes buffer to the packet
|
||||
NdisChainBufferAtFront(pPacket,Irp->MdlAddress);
|
||||
|
||||
// Call the MAC
|
||||
NdisSend(
|
||||
&Status,
|
||||
Open->AdapterHandle,
|
||||
pPacket);
|
||||
|
||||
if (Status != NDIS_STATUS_PENDING) {
|
||||
// The send didn't pend so call the completion handler now
|
||||
NPF_SendComplete(
|
||||
Open,
|
||||
pPacket,
|
||||
Status
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
if(i%100==99){
|
||||
NdisWaitEvent(&Open->WriteEvent,1000);
|
||||
NdisResetEvent(&Open->WriteEvent);
|
||||
}
|
||||
}
|
||||
|
||||
return(STATUS_PENDING);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
INT
|
||||
NPF_BufferedWrite(
|
||||
IN PIRP Irp,
|
||||
IN PCHAR UserBuff,
|
||||
IN ULONG UserBuffSize,
|
||||
BOOLEAN Sync)
|
||||
{
|
||||
POPEN_INSTANCE Open;
|
||||
PIO_STACK_LOCATION IrpSp;
|
||||
PNDIS_PACKET pPacket;
|
||||
UINT i;
|
||||
NDIS_STATUS Status;
|
||||
LARGE_INTEGER StartTicks, CurTicks, TargetTicks;
|
||||
LARGE_INTEGER TimeFreq;
|
||||
struct timeval BufStartTime;
|
||||
struct sf_pkthdr *winpcap_hdr;
|
||||
PMDL TmpMdl;
|
||||
PCHAR CurPos;
|
||||
PCHAR EndOfUserBuff = UserBuff + UserBuffSize;
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: BufferedWrite, UserBuff=%x, Size=%u\n", UserBuff, UserBuffSize);)
|
||||
|
||||
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
Open=IrpSp->FileObject->FsContext;
|
||||
|
||||
// Security check on the length of the user buffer
|
||||
if(UserBuff==0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Check that the MaxFrameSize is correctly initialized
|
||||
if(Open->MaxFrameSize == 0)
|
||||
{
|
||||
IF_LOUD(DbgPrint("BufferedWrite: Open->MaxFrameSize not initialized, probably because of a problem in the OID query\n");)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Start from the first packet
|
||||
winpcap_hdr = (struct sf_pkthdr*)UserBuff;
|
||||
|
||||
// Retrieve the time references
|
||||
StartTicks = KeQueryPerformanceCounter(&TimeFreq);
|
||||
BufStartTime.tv_sec = winpcap_hdr->ts.tv_sec;
|
||||
BufStartTime.tv_usec = winpcap_hdr->ts.tv_usec;
|
||||
|
||||
// Chech the consistency of the user buffer
|
||||
if( (PCHAR)winpcap_hdr + winpcap_hdr->caplen + sizeof(struct sf_pkthdr) > EndOfUserBuff )
|
||||
{
|
||||
IF_LOUD(DbgPrint("Buffered Write: bogus packet buffer\n");)
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Save the current time stamp counter
|
||||
CurTicks = KeQueryPerformanceCounter(NULL);
|
||||
|
||||
// Main loop: send the buffer to the wire
|
||||
while( TRUE ){
|
||||
|
||||
if(winpcap_hdr->caplen ==0 || winpcap_hdr->caplen > Open->MaxFrameSize)
|
||||
{
|
||||
// Malformed header
|
||||
IF_LOUD(DbgPrint("NPF_BufferedWrite: malformed or bogus user buffer, aborting write.\n");)
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Allocate an MDL to map the packet data
|
||||
TmpMdl=IoAllocateMdl((PCHAR)winpcap_hdr + sizeof(struct sf_pkthdr),
|
||||
winpcap_hdr->caplen,
|
||||
FALSE,
|
||||
FALSE,
|
||||
NULL);
|
||||
|
||||
if (TmpMdl == NULL)
|
||||
{
|
||||
// Unable to map the memory: packet lost
|
||||
IF_LOUD(DbgPrint("NPF_BufferedWrite: unable to allocate the MDL.\n");)
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
MmBuildMdlForNonPagedPool(TmpMdl); // XXX can this line be removed?
|
||||
|
||||
// Allocate a packet from our free list
|
||||
NdisAllocatePacket( &Status, &pPacket, Open->PacketPool);
|
||||
|
||||
if (Status != NDIS_STATUS_SUCCESS) {
|
||||
// No free packets
|
||||
IF_LOUD(DbgPrint("NPF_BufferedWrite: no more free packets, returning.\n");)
|
||||
|
||||
return (PCHAR)winpcap_hdr - UserBuff;
|
||||
}
|
||||
|
||||
// The packet has a buffer that needs to be freed after every single write
|
||||
RESERVED(pPacket)->FreeBufAfterWrite = TRUE;
|
||||
|
||||
// Attach the MDL to the packet
|
||||
NdisChainBufferAtFront(pPacket,TmpMdl);
|
||||
|
||||
// Call the MAC
|
||||
NdisSend( &Status, Open->AdapterHandle, pPacket);
|
||||
|
||||
if (Status != NDIS_STATUS_PENDING) {
|
||||
// The send didn't pend so call the completion handler now
|
||||
NPF_SendComplete(
|
||||
Open,
|
||||
pPacket,
|
||||
Status
|
||||
);
|
||||
}
|
||||
|
||||
// Step to the next packet in the buffer
|
||||
(PCHAR)winpcap_hdr += winpcap_hdr->caplen + sizeof(struct sf_pkthdr);
|
||||
|
||||
// Check if the end of the user buffer has been reached
|
||||
if( (PCHAR)winpcap_hdr >= EndOfUserBuff )
|
||||
{
|
||||
IF_LOUD(DbgPrint("NPF_BufferedWrite: End of buffer.\n");)
|
||||
|
||||
return (PCHAR)winpcap_hdr - UserBuff;
|
||||
}
|
||||
|
||||
if( Sync ){
|
||||
|
||||
// Release the application if it has been blocked for approximately more than 1 seconds
|
||||
if( winpcap_hdr->ts.tv_sec - BufStartTime.tv_sec > 1 )
|
||||
{
|
||||
IF_LOUD(DbgPrint("NPF_BufferedWrite: timestamp elapsed, returning.\n");)
|
||||
|
||||
return (PCHAR)winpcap_hdr - UserBuff;
|
||||
}
|
||||
|
||||
#ifndef __GNUC__
|
||||
// Calculate the time interval to wait before sending the next packet
|
||||
TargetTicks.QuadPart = StartTicks.QuadPart +
|
||||
(LONGLONG)((winpcap_hdr->ts.tv_sec - BufStartTime.tv_sec) * 1000000 +
|
||||
winpcap_hdr->ts.tv_usec - BufStartTime.tv_usec) *
|
||||
(TimeFreq.QuadPart) / 1000000;
|
||||
|
||||
// Wait until the time interval has elapsed
|
||||
while( CurTicks.QuadPart <= TargetTicks.QuadPart )
|
||||
CurTicks = KeQueryPerformanceCounter(NULL);
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return (PCHAR)winpcap_hdr - UserBuff;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
VOID
|
||||
NPF_SendComplete(
|
||||
IN NDIS_HANDLE ProtocolBindingContext,
|
||||
IN PNDIS_PACKET pPacket,
|
||||
IN NDIS_STATUS Status
|
||||
)
|
||||
|
||||
{
|
||||
PIRP Irp;
|
||||
PIO_STACK_LOCATION irpSp;
|
||||
POPEN_INSTANCE Open;
|
||||
PMDL TmpMdl;
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: SendComplete, BindingContext=%d\n",ProtocolBindingContext);)
|
||||
|
||||
Open= (POPEN_INSTANCE)ProtocolBindingContext;
|
||||
|
||||
if( RESERVED(pPacket)->FreeBufAfterWrite ){
|
||||
// Free the MDL associated with the packet
|
||||
NdisUnchainBufferAtFront(pPacket, &TmpMdl);
|
||||
IoFreeMdl(TmpMdl);
|
||||
}
|
||||
else{
|
||||
if((Open->Nwrites - Open->Multiple_Write_Counter) %100 == 99)
|
||||
NdisSetEvent(&Open->WriteEvent);
|
||||
|
||||
Open->Multiple_Write_Counter--;
|
||||
}
|
||||
|
||||
// recyle the packet
|
||||
NdisReinitializePacket(pPacket);
|
||||
|
||||
// Put the packet back on the free list
|
||||
NdisFreePacket(pPacket);
|
||||
|
||||
if( !(RESERVED(pPacket)->FreeBufAfterWrite) ){
|
||||
if(Open->Multiple_Write_Counter==0){
|
||||
// Release the buffer and awake the application
|
||||
NdisUnchainBufferAtFront(pPacket, &TmpMdl);
|
||||
|
||||
Irp=RESERVED(pPacket)->Irp;
|
||||
irpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = irpSp->Parameters.Write.Length;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
/*
|
||||
__divdi3()
|
||||
{
|
||||
//_alldiv();
|
||||
}
|
||||
|
||||
//_allmul();
|
||||
//_allrem();
|
||||
|
||||
*/
|
||||
#endif
|
Loading…
Reference in a new issue