mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 08:55:19 +00:00
Updated with latest version changes to original source.
svn path=/trunk/; revision=3555
This commit is contained in:
parent
2217a4d789
commit
5f1366aacc
34 changed files with 7284 additions and 1033 deletions
5
reactos/drivers/net/packet/.cvsignore
Normal file
5
reactos/drivers/net/packet/.cvsignore
Normal file
|
@ -0,0 +1,5 @@
|
|||
*.coff
|
||||
*.d
|
||||
*.o
|
||||
*.sym
|
||||
*.sys
|
|
@ -1,4 +1,4 @@
|
|||
# $Id: Makefile,v 1.1 2002/06/19 15:43:15 robd Exp $
|
||||
# $Id: Makefile,v 1.2 2002/09/24 15:16:46 robd Exp $
|
||||
|
||||
PATH_TO_TOP = ../../..
|
||||
|
||||
|
@ -7,15 +7,26 @@ TARGET_TYPE = driver
|
|||
|
||||
TARGET_NAME = packet
|
||||
|
||||
TARGET_CFLAGS = -DNDIS50
|
||||
# -disable-stdcall-fixup
|
||||
TARGET_CFLAGS = -DDBG -DWIN_NT_DRIVER -DKQPC_TS
|
||||
|
||||
TARGET_OBJECTS = \
|
||||
packet.o \
|
||||
read.o \
|
||||
openclos.o \
|
||||
write.o \
|
||||
win_bpf_filter.o
|
||||
packet.o \
|
||||
openclos.o \
|
||||
read.o \
|
||||
write.o \
|
||||
dump.o \
|
||||
jitter.o \
|
||||
win_bpf_filter.o \
|
||||
tme.o \
|
||||
count_packets.o \
|
||||
win_bpf_filter_init.o \
|
||||
tcp_session.o \
|
||||
memory_t.o \
|
||||
time_calls.o \
|
||||
functions.o \
|
||||
bucket_lookup.o \
|
||||
normal_lookup.o
|
||||
|
||||
|
||||
TARGET_DDKLIBS = ndis.a
|
||||
|
||||
|
|
251
reactos/drivers/net/packet/bucket_lookup.c
Normal file
251
reactos/drivers/net/packet/bucket_lookup.c
Normal file
|
@ -0,0 +1,251 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#include "tme.h"
|
||||
#include "bucket_lookup.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <net/tme/tme.h>
|
||||
#include <net/tme/bucket_lookup.h>
|
||||
#else
|
||||
#include <tme/tme.h>
|
||||
#include <tme/bucket_lookup.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* the key is represented by the initial and final value */
|
||||
/* of the bucket. At the moment bucket_lookup is able to */
|
||||
/* manage values of 16, 32 bits. */
|
||||
uint32 bucket_lookup(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref)
|
||||
{
|
||||
uint32 value;
|
||||
uint32 i,j;
|
||||
int found=-1;
|
||||
uint32 blocks;
|
||||
uint32 block_size;
|
||||
uint8 *temp;
|
||||
if ((data->key_len!=1)&& /*16 bit value*/
|
||||
(data->key_len!=2)) /*32 bit value*/
|
||||
return TME_ERROR;
|
||||
|
||||
/*32 bit values*/
|
||||
blocks=data->filled_blocks-1;
|
||||
block_size=data->block_size;
|
||||
i=blocks/2; /*relative shift*/
|
||||
j=i;
|
||||
temp=data->shared_memory_base_address+block_size;
|
||||
|
||||
if (data->key_len==2)
|
||||
{
|
||||
value=SW_ULONG_AT(key,0);
|
||||
|
||||
if((value<SW_ULONG_AT(temp,0))||(value>SW_ULONG_AT(temp+block_size*(blocks-1),4)))
|
||||
{
|
||||
uint32 *key32=(uint32*) key;
|
||||
key32[0]=key32[1]=0;
|
||||
|
||||
GET_TIME((struct timeval *)(data->shared_memory_base_address+8),time_ref);
|
||||
|
||||
data->last_found=NULL;
|
||||
return TME_FALSE;
|
||||
}
|
||||
|
||||
while(found==-1) /* search routine */
|
||||
{
|
||||
i=(i==1)? 1:i>>1;
|
||||
if (SW_ULONG_AT(temp+block_size*j,0)>value)
|
||||
if (SW_ULONG_AT(temp+block_size*(j-1),4)<value)
|
||||
found=-2;
|
||||
else
|
||||
j-=i;
|
||||
else
|
||||
if (SW_ULONG_AT(temp+block_size*j,4)<value)
|
||||
if (SW_ULONG_AT(temp+block_size*j,0)>value)
|
||||
found=-2;
|
||||
else
|
||||
j+=i;
|
||||
else found=j;
|
||||
}
|
||||
if (found<0)
|
||||
{
|
||||
uint32 *key32=(uint32*) key;
|
||||
key32[0]=key32[1]=0;
|
||||
|
||||
GET_TIME((struct timeval *)(data->shared_memory_base_address+8),time_ref);
|
||||
|
||||
data->last_found=NULL;
|
||||
return TME_FALSE;
|
||||
}
|
||||
|
||||
data->last_found=data->lut_base_address+found*sizeof(RECORD);
|
||||
|
||||
COPY_MEMORY(key,temp+block_size*found,8);
|
||||
|
||||
GET_TIME((struct timeval *)(temp+block_size*found+8),time_ref);
|
||||
|
||||
return TME_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
value=SW_USHORT_AT(key,0);
|
||||
|
||||
if((value<SW_USHORT_AT(temp,0))||(value>SW_USHORT_AT(temp+block_size*(blocks-1),2)))
|
||||
{
|
||||
uint16 *key16=(uint16*) key;
|
||||
key16[0]=key16[1]=0;
|
||||
|
||||
GET_TIME((struct timeval *)(data->shared_memory_base_address+4),time_ref);
|
||||
|
||||
data->last_found=NULL;
|
||||
return TME_FALSE;
|
||||
}
|
||||
|
||||
while(found==-1) /* search routine */
|
||||
{
|
||||
i=(i==1)? 1:i>>1;
|
||||
if (SW_USHORT_AT(temp+block_size*j,0)>value)
|
||||
if (SW_USHORT_AT(temp+block_size*(j-1),2)<value)
|
||||
found=-2;
|
||||
else
|
||||
j-=i;
|
||||
else
|
||||
if (SW_USHORT_AT(temp+block_size*j,2)<value)
|
||||
if (SW_USHORT_AT(temp+block_size*j,0)>value)
|
||||
found=-2;
|
||||
else
|
||||
j+=i;
|
||||
else found=j;
|
||||
}
|
||||
|
||||
if (found<0)
|
||||
{
|
||||
uint16 *key16=(uint16*) key;
|
||||
key16[0]=key16[1]=0;
|
||||
|
||||
GET_TIME((struct timeval *)(data->shared_memory_base_address+4),time_ref);
|
||||
|
||||
data->last_found=NULL;
|
||||
return TME_FALSE;
|
||||
}
|
||||
|
||||
data->last_found=data->lut_base_address+found*sizeof(RECORD);
|
||||
|
||||
GET_TIME((struct timeval *)(temp+block_size*found+4),time_ref);
|
||||
|
||||
COPY_MEMORY(key,temp+block_size*found,4);
|
||||
|
||||
return TME_TRUE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uint32 bucket_lookup_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref)
|
||||
{
|
||||
RECORD *records=(RECORD*)data->lut_base_address;
|
||||
|
||||
if ((data->key_len!=1)&& /*16 bit value*/
|
||||
(data->key_len!=2)) /*32 bit value*/
|
||||
return TME_ERROR;
|
||||
|
||||
if(data->key_len==2)
|
||||
{
|
||||
uint32 start,stop;
|
||||
uint8 *tmp;
|
||||
|
||||
start=SW_ULONG_AT(key,0);
|
||||
stop=SW_ULONG_AT(key,4);
|
||||
|
||||
if (start>stop)
|
||||
return TME_ERROR;
|
||||
if (data->filled_entries>0)
|
||||
{
|
||||
tmp=mem_ex->buffer+SW_ULONG_AT(&records[data->filled_entries-1].block,0);
|
||||
/*check if it is coherent with the previous block*/
|
||||
if (SW_ULONG_AT(tmp,4)>=start)
|
||||
return TME_ERROR;
|
||||
}
|
||||
|
||||
if (data->filled_blocks==data->shared_memory_blocks)
|
||||
return TME_ERROR;
|
||||
|
||||
if (data->filled_entries==data->lut_entries)
|
||||
return TME_ERROR;
|
||||
|
||||
tmp=data->shared_memory_base_address+data->block_size*data->filled_blocks;
|
||||
|
||||
COPY_MEMORY(tmp,key,8);
|
||||
|
||||
SW_ULONG_ASSIGN(&records[data->filled_entries].block,tmp-mem_ex->buffer);
|
||||
SW_ULONG_ASSIGN(&records[data->filled_entries].exec_fcn,data->default_exec);
|
||||
|
||||
GET_TIME((struct timeval *)(tmp+8),time_ref);
|
||||
|
||||
data->filled_blocks++;
|
||||
data->filled_entries++;
|
||||
|
||||
return TME_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16 start,stop;
|
||||
uint8 *tmp;
|
||||
|
||||
start=SW_USHORT_AT(key,0);
|
||||
stop=SW_USHORT_AT(key,2);
|
||||
|
||||
if (start>stop)
|
||||
return TME_ERROR;
|
||||
if (data->filled_entries>0)
|
||||
{
|
||||
tmp=mem_ex->buffer+SW_ULONG_AT(&records[data->filled_entries-1].block,0);
|
||||
/*check if it is coherent with the previous block*/
|
||||
if (SW_USHORT_AT(tmp,2)>=start)
|
||||
return TME_ERROR;
|
||||
}
|
||||
|
||||
if (data->filled_blocks==data->shared_memory_blocks)
|
||||
return TME_ERROR;
|
||||
|
||||
if (data->filled_entries==data->lut_entries)
|
||||
return TME_ERROR;
|
||||
|
||||
tmp=mem_ex->buffer+SW_ULONG_AT(&records[data->filled_entries].block,0);
|
||||
|
||||
COPY_MEMORY(tmp,key,4);
|
||||
|
||||
SW_ULONG_ASSIGN(&records[data->filled_entries].block,tmp-mem_ex->buffer);
|
||||
SW_ULONG_ASSIGN(&records[data->filled_entries].exec_fcn,data->default_exec);
|
||||
|
||||
GET_TIME((struct timeval *)(tmp+4),time_ref);
|
||||
|
||||
data->filled_blocks++;
|
||||
data->filled_entries++;
|
||||
|
||||
return TME_TRUE;
|
||||
}
|
||||
}
|
43
reactos/drivers/net/packet/bucket_lookup.h
Normal file
43
reactos/drivers/net/packet/bucket_lookup.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifndef __bucket_lookup
|
||||
#define __bucket_lookup
|
||||
#ifdef WIN32
|
||||
#include "tme.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <net/tme/tme.h>
|
||||
#else
|
||||
#include <tme/tme.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#define BUCKET_LOOKUP_INSERT 0x00000011
|
||||
uint32 bucket_lookup_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);
|
||||
#define BUCKET_LOOKUP 0x00000010
|
||||
uint32 bucket_lookup(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);
|
||||
|
||||
#endif
|
51
reactos/drivers/net/packet/count_packets.c
Normal file
51
reactos/drivers/net/packet/count_packets.c
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#include "tme.h"
|
||||
#include "count_packets.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <net/tme/tme.h>
|
||||
#include <net/tme/count_packets.h>
|
||||
#else
|
||||
#include <tme/tme.h>
|
||||
#include <tme/count_packets.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
uint32 count_packets(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data)
|
||||
{
|
||||
|
||||
c_p_data *counters=(c_p_data*)(block+data->key_len*4);
|
||||
|
||||
counters->bytes+=pkt_size;
|
||||
counters->packets++;
|
||||
|
||||
return TME_SUCCESS;
|
||||
|
||||
}
|
51
reactos/drivers/net/packet/count_packets.h
Normal file
51
reactos/drivers/net/packet/count_packets.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifndef __count_packets
|
||||
#define __count_packets
|
||||
|
||||
#ifdef WIN32
|
||||
#include "tme.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <net/tme/tme.h>
|
||||
#else
|
||||
#include <tme/tme.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct __c_p_data
|
||||
{
|
||||
struct timeval timestamp;
|
||||
uint64 packets;
|
||||
uint64 bytes;
|
||||
}
|
||||
c_p_data;
|
||||
|
||||
#define COUNT_PACKETS 0x00000000
|
||||
uint32 count_packets(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data);
|
||||
|
||||
#endif
|
||||
|
|
@ -19,6 +19,8 @@
|
|||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifndef __DEBUG_INCLUDE
|
||||
#define __DEBUG_INCLUDE
|
||||
|
||||
|
||||
#if DBG
|
||||
|
@ -46,3 +48,5 @@ extern ULONG PacketDebugFlag;
|
|||
#define IF_INIT_LOUD(A)
|
||||
|
||||
#endif
|
||||
|
||||
#endif /*#define __DEBUG_INCLUDE*/
|
||||
|
|
587
reactos/drivers/net/packet/dump.c
Normal file
587
reactos/drivers/net/packet/dump.c
Normal file
|
@ -0,0 +1,587 @@
|
|||
/*
|
||||
* Copyright (c) 1999, 2000
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include "stdarg.h"
|
||||
#include "ntddk.h"
|
||||
#include "ntiologc.h"
|
||||
#include "ndis.h"
|
||||
#else
|
||||
#include <ddk/ntddk.h>
|
||||
#include <net/ndis.h>
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
#include "packet.h"
|
||||
#include "win_bpf.h"
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
NTSTATUS
|
||||
NPF_OpenDumpFile(POPEN_INSTANCE Open , PUNICODE_STRING fileName, BOOLEAN Append)
|
||||
{
|
||||
NTSTATUS ntStatus;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
PWCHAR PathPrefix;
|
||||
USHORT PathLen;
|
||||
UNICODE_STRING FullFileName;
|
||||
ULONG FullFileNameLength;
|
||||
PDEVICE_OBJECT fsdDevice;
|
||||
|
||||
FILE_STANDARD_INFORMATION StandardInfo;
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: OpenDumpFile.\n");)
|
||||
|
||||
if(fileName->Buffer[0] == L'\\' &&
|
||||
fileName->Buffer[1] == L'?' &&
|
||||
fileName->Buffer[2] == L'?' &&
|
||||
fileName->Buffer[3] == L'\\'
|
||||
){
|
||||
PathLen = 0;
|
||||
}
|
||||
else{
|
||||
PathPrefix = L"\\??\\";
|
||||
PathLen = 8;
|
||||
}
|
||||
|
||||
// Insert the correct path prefix.
|
||||
FullFileNameLength = PathLen + fileName->MaximumLength;
|
||||
|
||||
FullFileName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
|
||||
FullFileNameLength,
|
||||
'0DWA');
|
||||
|
||||
if (FullFileName.Buffer == NULL) {
|
||||
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
|
||||
return ntStatus;
|
||||
}
|
||||
|
||||
FullFileName.Length = PathLen;
|
||||
FullFileName.MaximumLength = (USHORT)FullFileNameLength;
|
||||
|
||||
if(PathLen)
|
||||
RtlMoveMemory (FullFileName.Buffer, PathPrefix, PathLen);
|
||||
|
||||
RtlAppendUnicodeStringToString (&FullFileName, fileName);
|
||||
|
||||
IF_LOUD(DbgPrint( "Packet: Attempting to open %wZ\n", &FullFileName);)
|
||||
|
||||
InitializeObjectAttributes ( &ObjectAttributes,
|
||||
&FullFileName,
|
||||
OBJ_CASE_INSENSITIVE,
|
||||
NULL,
|
||||
NULL );
|
||||
|
||||
// Create the dump file
|
||||
ntStatus = ZwCreateFile( &Open->DumpFileHandle,
|
||||
SYNCHRONIZE | FILE_WRITE_DATA,
|
||||
&ObjectAttributes,
|
||||
&IoStatus,
|
||||
NULL,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
FILE_SHARE_READ,
|
||||
(Append)?FILE_OPEN_IF:FILE_SUPERSEDE,
|
||||
FILE_SYNCHRONOUS_IO_NONALERT,
|
||||
NULL,
|
||||
0 );
|
||||
|
||||
if ( !NT_SUCCESS( ntStatus ) )
|
||||
{
|
||||
IF_LOUD(DbgPrint("NPF: Error opening file %x\n", ntStatus);)
|
||||
|
||||
ExFreePool(FullFileName.Buffer);
|
||||
Open->DumpFileHandle=NULL;
|
||||
ntStatus = STATUS_NO_SUCH_FILE;
|
||||
return ntStatus;
|
||||
}
|
||||
|
||||
ExFreePool(FullFileName.Buffer);
|
||||
|
||||
ntStatus = ObReferenceObjectByHandle(Open->DumpFileHandle,
|
||||
FILE_WRITE_ACCESS,
|
||||
#ifndef __GNUC__
|
||||
*IoFileObjectType,
|
||||
#else
|
||||
IoFileObjectType,
|
||||
#endif
|
||||
KernelMode,
|
||||
&Open->DumpFileObject,
|
||||
0);
|
||||
|
||||
if ( !NT_SUCCESS( ntStatus ) )
|
||||
{
|
||||
IF_LOUD(DbgPrint("NPF: Error creating file, status=%x\n", ntStatus);)
|
||||
|
||||
ZwClose( Open->DumpFileHandle );
|
||||
Open->DumpFileHandle=NULL;
|
||||
|
||||
ntStatus = STATUS_NO_SUCH_FILE;
|
||||
return ntStatus;
|
||||
}
|
||||
|
||||
fsdDevice = IoGetRelatedDeviceObject(Open->DumpFileObject);
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: Dump: write file created succesfully, status=%d \n",ntStatus);)
|
||||
|
||||
return ntStatus;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
NTSTATUS
|
||||
NPF_StartDump(POPEN_INSTANCE Open)
|
||||
{
|
||||
NTSTATUS ntStatus;
|
||||
struct packet_file_header hdr;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
NDIS_REQUEST pRequest;
|
||||
ULONG MediaType;
|
||||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: StartDump.\n");)
|
||||
|
||||
// Init the file header
|
||||
hdr.magic = TCPDUMP_MAGIC;
|
||||
hdr.version_major = PCAP_VERSION_MAJOR;
|
||||
hdr.version_minor = PCAP_VERSION_MINOR;
|
||||
hdr.thiszone = 0; /*Currently not set*/
|
||||
hdr.snaplen = 1514;
|
||||
hdr.sigfigs = 0;
|
||||
|
||||
// Detect the medium type
|
||||
switch (Open->Medium){
|
||||
|
||||
case NdisMediumWan:
|
||||
hdr.linktype = DLT_EN10MB;
|
||||
break;
|
||||
|
||||
case NdisMedium802_3:
|
||||
hdr.linktype = DLT_EN10MB;
|
||||
break;
|
||||
|
||||
case NdisMediumFddi:
|
||||
hdr.linktype = DLT_FDDI;
|
||||
break;
|
||||
|
||||
case NdisMedium802_5:
|
||||
hdr.linktype = DLT_IEEE802;
|
||||
break;
|
||||
|
||||
case NdisMediumArcnet878_2:
|
||||
hdr.linktype = DLT_ARCNET;
|
||||
break;
|
||||
|
||||
case NdisMediumAtm:
|
||||
hdr.linktype = DLT_ATM_RFC1483;
|
||||
break;
|
||||
|
||||
default:
|
||||
hdr.linktype = DLT_EN10MB;
|
||||
}
|
||||
|
||||
// Write the header.
|
||||
// We can use ZwWriteFile because we are in the context of the application
|
||||
ntStatus = ZwWriteFile(Open->DumpFileHandle,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&IoStatus,
|
||||
&hdr,
|
||||
sizeof(hdr),
|
||||
NULL,
|
||||
NULL );
|
||||
|
||||
|
||||
if ( !NT_SUCCESS( ntStatus ) )
|
||||
{
|
||||
IF_LOUD(DbgPrint("NPF: Error dumping file %x\n", ntStatus);)
|
||||
|
||||
ZwClose( Open->DumpFileHandle );
|
||||
Open->DumpFileHandle=NULL;
|
||||
|
||||
ntStatus = STATUS_NO_SUCH_FILE;
|
||||
return ntStatus;
|
||||
}
|
||||
|
||||
Open->DumpOffset.QuadPart=24;
|
||||
|
||||
ntStatus = PsCreateSystemThread(&Open->DumpThreadHandle,
|
||||
THREAD_ALL_ACCESS,
|
||||
(ACCESS_MASK)0L,
|
||||
0,
|
||||
0,
|
||||
NPF_DumpThread,
|
||||
Open);
|
||||
|
||||
if ( !NT_SUCCESS( ntStatus ) )
|
||||
{
|
||||
IF_LOUD(DbgPrint("NPF: Error creating dump thread, status=%x\n", ntStatus);)
|
||||
|
||||
ZwClose( Open->DumpFileHandle );
|
||||
Open->DumpFileHandle=NULL;
|
||||
|
||||
return ntStatus;
|
||||
}
|
||||
#ifndef __GNUC__
|
||||
ntStatus = ObReferenceObjectByHandle(Open->DumpThreadHandle,
|
||||
THREAD_ALL_ACCESS,
|
||||
NULL,
|
||||
KernelMode,
|
||||
&Open->DumpThreadObject,
|
||||
0);
|
||||
#else
|
||||
#endif
|
||||
if ( !NT_SUCCESS( ntStatus ) )
|
||||
{
|
||||
IF_LOUD(DbgPrint("NPF: Error creating dump thread, status=%x\n", ntStatus);)
|
||||
|
||||
ObDereferenceObject(Open->DumpFileObject);
|
||||
ZwClose( Open->DumpFileHandle );
|
||||
Open->DumpFileHandle=NULL;
|
||||
|
||||
return ntStatus;
|
||||
}
|
||||
|
||||
|
||||
return ntStatus;
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
// Dump Thread
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
VOID NPF_DumpThread(POPEN_INSTANCE Open)
|
||||
{
|
||||
ULONG FrozenNic;
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: In the work routine. Parameter = 0x%0x\n",Open);)
|
||||
|
||||
while(TRUE){
|
||||
|
||||
// Wait until some packets arrive or the timeout expires
|
||||
NdisWaitEvent(&Open->DumpEvent, 5000);
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: Worker Thread - event signalled\n");)
|
||||
|
||||
if(Open->DumpLimitReached ||
|
||||
Open->BufSize==0){ // BufSize=0 means that this instance was closed, or that the buffer is too
|
||||
// small for any capture. In both cases it is better to end the dump
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: Worker Thread - Exiting happily\n");)
|
||||
IF_LOUD(DbgPrint("Thread: Dumpoffset=%I64d\n",Open->DumpOffset.QuadPart);)
|
||||
|
||||
PsTerminateSystemThread(STATUS_SUCCESS);
|
||||
return;
|
||||
}
|
||||
|
||||
NdisResetEvent(&Open->DumpEvent);
|
||||
|
||||
// Write the content of the buffer to the file
|
||||
if(NPF_SaveCurrentBuffer(Open) != STATUS_SUCCESS){
|
||||
PsTerminateSystemThread(STATUS_SUCCESS);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
NTSTATUS NPF_SaveCurrentBuffer(POPEN_INSTANCE Open)
|
||||
{
|
||||
UINT Thead;
|
||||
UINT Ttail;
|
||||
UINT TLastByte;
|
||||
PUCHAR CurrBuff;
|
||||
NTSTATUS ntStatus;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
PMDL lMdl;
|
||||
UINT SizeToDump;
|
||||
|
||||
|
||||
Thead=Open->Bhead;
|
||||
Ttail=Open->Btail;
|
||||
TLastByte=Open->BLastByte;
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: NPF_SaveCurrentBuffer.\n");)
|
||||
|
||||
// Get the address of the buffer
|
||||
CurrBuff=Open->Buffer;
|
||||
//
|
||||
// Fill the application buffer
|
||||
//
|
||||
if( Ttail < Thead )
|
||||
{
|
||||
if(Open->MaxDumpBytes &&
|
||||
(UINT)Open->DumpOffset.QuadPart + GetBuffOccupation(Open) > Open->MaxDumpBytes)
|
||||
{
|
||||
// Size limit reached
|
||||
UINT PktLen;
|
||||
|
||||
SizeToDump = 0;
|
||||
|
||||
// Scan the buffer to detect the exact amount of data to save
|
||||
while(TRUE){
|
||||
PktLen = ((struct sf_pkthdr*)(CurrBuff + Thead + SizeToDump))->caplen + sizeof(struct sf_pkthdr);
|
||||
|
||||
if((UINT)Open->DumpOffset.QuadPart + SizeToDump + PktLen > Open->MaxDumpBytes)
|
||||
break;
|
||||
|
||||
SizeToDump += PktLen;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
SizeToDump = TLastByte-Thead;
|
||||
|
||||
lMdl=IoAllocateMdl(CurrBuff+Thead, SizeToDump, FALSE, FALSE, NULL);
|
||||
if (lMdl == NULL)
|
||||
{
|
||||
// No memory: stop dump
|
||||
IF_LOUD(DbgPrint("NPF: dump thread: Failed to allocate Mdl\n");)
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
MmBuildMdlForNonPagedPool(lMdl);
|
||||
|
||||
// Write to disk
|
||||
NPF_WriteDumpFile(Open->DumpFileObject,
|
||||
&Open->DumpOffset,
|
||||
SizeToDump,
|
||||
lMdl,
|
||||
&IoStatus);
|
||||
|
||||
IoFreeMdl(lMdl);
|
||||
|
||||
if(!NT_SUCCESS(IoStatus.Status)){
|
||||
// Error
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
if(SizeToDump != TLastByte-Thead){
|
||||
// Size limit reached.
|
||||
Open->DumpLimitReached = TRUE;
|
||||
|
||||
// Awake the application
|
||||
KeSetEvent(Open->ReadEvent,0,FALSE);
|
||||
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
// Update the packet buffer
|
||||
Open->DumpOffset.QuadPart+=(TLastByte-Thead);
|
||||
Open->BLastByte=Ttail;
|
||||
Open->Bhead=0;
|
||||
}
|
||||
|
||||
if( Ttail > Thead ){
|
||||
|
||||
if(Open->MaxDumpBytes &&
|
||||
(UINT)Open->DumpOffset.QuadPart + GetBuffOccupation(Open) > Open->MaxDumpBytes)
|
||||
{
|
||||
// Size limit reached
|
||||
UINT PktLen;
|
||||
|
||||
SizeToDump = 0;
|
||||
|
||||
// Scan the buffer to detect the exact amount of data to save
|
||||
while(Thead + SizeToDump < Ttail){
|
||||
|
||||
PktLen = ((struct sf_pkthdr*)(CurrBuff + Thead + SizeToDump))->caplen + sizeof(struct sf_pkthdr);
|
||||
|
||||
if((UINT)Open->DumpOffset.QuadPart + SizeToDump + PktLen > Open->MaxDumpBytes)
|
||||
break;
|
||||
|
||||
SizeToDump += PktLen;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
SizeToDump = Ttail-Thead;
|
||||
|
||||
lMdl=IoAllocateMdl(CurrBuff+Thead, SizeToDump, FALSE, FALSE, NULL);
|
||||
if (lMdl == NULL)
|
||||
{
|
||||
// No memory: stop dump
|
||||
IF_LOUD(DbgPrint("NPF: dump thread: Failed to allocate Mdl\n");)
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
MmBuildMdlForNonPagedPool(lMdl);
|
||||
|
||||
// Write to disk
|
||||
NPF_WriteDumpFile(Open->DumpFileObject,
|
||||
&Open->DumpOffset,
|
||||
SizeToDump,
|
||||
lMdl,
|
||||
&IoStatus);
|
||||
|
||||
IoFreeMdl(lMdl);
|
||||
|
||||
if(!NT_SUCCESS(IoStatus.Status)){
|
||||
// Error
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
if(SizeToDump != Ttail-Thead){
|
||||
// Size limit reached.
|
||||
Open->DumpLimitReached = TRUE;
|
||||
|
||||
// Awake the application
|
||||
KeSetEvent(Open->ReadEvent,0,FALSE);
|
||||
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
// Update the packet buffer
|
||||
Open->DumpOffset.QuadPart+=(Ttail-Thead);
|
||||
Open->Bhead=Ttail;
|
||||
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
NTSTATUS NPF_CloseDumpFile(POPEN_INSTANCE Open){
|
||||
NTSTATUS ntStatus;
|
||||
IO_STATUS_BLOCK IoStatus;
|
||||
PMDL WriteMdl;
|
||||
PUCHAR VMBuff;
|
||||
UINT VMBufLen;
|
||||
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: NPF_CloseDumpFile.\n");)
|
||||
IF_LOUD(DbgPrint("Dumpoffset=%d\n",Open->DumpOffset.QuadPart);)
|
||||
|
||||
DbgPrint("1\n");
|
||||
// Consistency check
|
||||
if(Open->DumpFileHandle == NULL)
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
|
||||
DbgPrint("2\n");
|
||||
ZwClose( Open->DumpFileHandle );
|
||||
|
||||
ObDereferenceObject(Open->DumpFileObject);
|
||||
/*
|
||||
if(Open->DumpLimitReached == TRUE)
|
||||
// Limit already reached: don't save the rest of the buffer.
|
||||
return STATUS_SUCCESS;
|
||||
*/
|
||||
DbgPrint("3\n");
|
||||
|
||||
NPF_OpenDumpFile(Open,&Open->DumpFileName, TRUE);
|
||||
|
||||
// Flush the buffer to file
|
||||
NPF_SaveCurrentBuffer(Open);
|
||||
|
||||
// Close The file
|
||||
ObDereferenceObject(Open->DumpFileObject);
|
||||
ZwClose( Open->DumpFileHandle );
|
||||
|
||||
Open->DumpFileHandle = NULL;
|
||||
|
||||
ObDereferenceObject(Open->DumpFileObject);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
static NTSTATUS PacketDumpCompletion(PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp,
|
||||
PVOID Context)
|
||||
{
|
||||
|
||||
// Copy the status information back into the "user" IOSB
|
||||
*Irp->UserIosb = Irp->IoStatus;
|
||||
|
||||
// Wake up the mainline code
|
||||
KeSetEvent(Irp->UserEvent, 0, FALSE);
|
||||
|
||||
return STATUS_MORE_PROCESSING_REQUIRED;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
VOID NPF_WriteDumpFile(PFILE_OBJECT FileObject,
|
||||
PLARGE_INTEGER Offset,
|
||||
ULONG Length,
|
||||
PMDL Mdl,
|
||||
PIO_STATUS_BLOCK IoStatusBlock)
|
||||
{
|
||||
PIRP irp;
|
||||
KEVENT event;
|
||||
PIO_STACK_LOCATION ioStackLocation;
|
||||
PDEVICE_OBJECT fsdDevice = IoGetRelatedDeviceObject(FileObject);
|
||||
NTSTATUS Status;
|
||||
|
||||
// Set up the event we'll use
|
||||
KeInitializeEvent(&event, SynchronizationEvent, FALSE);
|
||||
|
||||
// Allocate and build the IRP we'll be sending to the FSD
|
||||
irp = IoAllocateIrp(fsdDevice->StackSize, FALSE);
|
||||
|
||||
if (!irp) {
|
||||
// Allocation failed, presumably due to memory allocation failure
|
||||
IoStatusBlock->Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
IoStatusBlock->Information = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
irp->MdlAddress = Mdl;
|
||||
irp->UserEvent = &event;
|
||||
irp->UserIosb = IoStatusBlock;
|
||||
irp->Tail.Overlay.Thread = PsGetCurrentThread();
|
||||
irp->Tail.Overlay.OriginalFileObject= FileObject;
|
||||
irp->RequestorMode = KernelMode;
|
||||
|
||||
// Indicate that this is a WRITE operation
|
||||
irp->Flags = IRP_WRITE_OPERATION;
|
||||
|
||||
// Set up the next I/O stack location
|
||||
ioStackLocation = IoGetNextIrpStackLocation(irp);
|
||||
ioStackLocation->MajorFunction = IRP_MJ_WRITE;
|
||||
ioStackLocation->MinorFunction = 0;
|
||||
ioStackLocation->DeviceObject = fsdDevice;
|
||||
ioStackLocation->FileObject = FileObject;
|
||||
IoSetCompletionRoutine(irp, PacketDumpCompletion, 0, TRUE, TRUE, TRUE);
|
||||
ioStackLocation->Parameters.Write.Length = Length;
|
||||
ioStackLocation->Parameters.Write.ByteOffset = *Offset;
|
||||
|
||||
|
||||
// Send it on. Ignore the return code
|
||||
(void) IoCallDriver(fsdDevice, irp);
|
||||
|
||||
// Wait for the I/O to complete.
|
||||
KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, 0);
|
||||
|
||||
// Free the IRP now that we are done with it
|
||||
IoFreeIrp(irp);
|
||||
|
||||
return;
|
||||
|
||||
}
|
82
reactos/drivers/net/packet/functions.c
Normal file
82
reactos/drivers/net/packet/functions.c
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#include "tme.h"
|
||||
#include "functions.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <net/tme/tme.h>
|
||||
#include <net/bpf.h>
|
||||
#include <net/tme/functions.h>
|
||||
#else
|
||||
#include <tme/tme.h>
|
||||
#include <bpf.h>
|
||||
#include <tme/functions.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
lut_fcn lut_fcn_mapper(uint32 index)
|
||||
{
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case NORMAL_LUT_W_INSERT:
|
||||
return (lut_fcn) normal_lut_w_insert;
|
||||
|
||||
case NORMAL_LUT_WO_INSERT:
|
||||
return (lut_fcn) normal_lut_wo_insert;
|
||||
|
||||
case BUCKET_LOOKUP:
|
||||
return (lut_fcn) bucket_lookup;
|
||||
|
||||
case BUCKET_LOOKUP_INSERT:
|
||||
return (lut_fcn) bucket_lookup_insert;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
exec_fcn exec_fcn_mapper(uint32 index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case COUNT_PACKETS:
|
||||
return (exec_fcn) count_packets;
|
||||
|
||||
case TCP_SESSION:
|
||||
return (exec_fcn) tcp_session;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
67
reactos/drivers/net/packet/functions.h
Normal file
67
reactos/drivers/net/packet/functions.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifndef __FUNCTIONS
|
||||
#define __FUNCTIONS
|
||||
|
||||
#ifdef WIN32
|
||||
#include "tme.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <net/tme/tme.h>
|
||||
#else
|
||||
#include <tme/tme.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/*function mappers */
|
||||
|
||||
lut_fcn lut_fcn_mapper(uint32 index);
|
||||
exec_fcn exec_fcn_mapper(uint32 index);
|
||||
|
||||
/* lookup functions */
|
||||
|
||||
#ifdef WIN32
|
||||
#include "bucket_lookup.h"
|
||||
#include "normal_lookup.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <net/tme/bucket_lookup.h>
|
||||
#include <net/tme/normal_lookup.h>
|
||||
#endif
|
||||
|
||||
/* execution functions */
|
||||
|
||||
#ifdef WIN32
|
||||
#include "count_packets.h"
|
||||
#include "tcp_session.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <net/tme/count_packets.h>
|
||||
#include <ne/tme/tcp_session.h>
|
||||
#endif
|
||||
|
||||
#endif
|
677
reactos/drivers/net/packet/jitter.c
Normal file
677
reactos/drivers/net/packet/jitter.c
Normal file
|
@ -0,0 +1,677 @@
|
|||
/*
|
||||
* Copyright (c) 2002
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include "stdarg.h"
|
||||
#include "ntddk.h"
|
||||
#include "ntiologc.h"
|
||||
#include "ndis.h"
|
||||
#else
|
||||
#include <ddk/ntddk.h>
|
||||
#include <net/ndis.h>
|
||||
#endif
|
||||
|
||||
#include "packet.h"
|
||||
#include "win_bpf.h"
|
||||
|
||||
emit_func emitm;
|
||||
|
||||
//
|
||||
// emit routine to update the jump table
|
||||
//
|
||||
void emit_lenght(binary_stream *stream, ULONG value, UINT len)
|
||||
{
|
||||
(stream->refs)[stream->bpf_pc]+=len;
|
||||
stream->cur_ip+=len;
|
||||
}
|
||||
|
||||
//
|
||||
// emit routine to output the actual binary code
|
||||
//
|
||||
void emit_code(binary_stream *stream, ULONG value, UINT len)
|
||||
{
|
||||
|
||||
switch (len){
|
||||
|
||||
case 1:
|
||||
stream->ibuf[stream->cur_ip]=(UCHAR)value;
|
||||
stream->cur_ip++;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
*((USHORT*)(stream->ibuf+stream->cur_ip))=(USHORT)value;
|
||||
stream->cur_ip+=2;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
*((ULONG*)(stream->ibuf+stream->cur_ip))=value;
|
||||
stream->cur_ip+=4;
|
||||
break;
|
||||
|
||||
default:;
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Function that does the real stuff
|
||||
//
|
||||
BPF_filter_function BPFtoX86(struct bpf_insn *prog, UINT nins, INT *mem)
|
||||
{
|
||||
struct bpf_insn *ins;
|
||||
UINT i, pass;
|
||||
binary_stream stream;
|
||||
|
||||
|
||||
// Allocate the reference table for the jumps
|
||||
#ifdef NTKERNEL
|
||||
stream.refs=(UINT *)ExAllocatePoolWithTag(NonPagedPool, (nins + 1)*sizeof(UINT), '0JWA');
|
||||
#else
|
||||
stream.refs=(UINT *)malloc((nins + 1)*sizeof(UINT));
|
||||
#endif
|
||||
if(stream.refs==NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Reset the reference table
|
||||
for(i=0; i< nins + 1; i++)
|
||||
stream.refs[i]=0;
|
||||
|
||||
stream.cur_ip=0;
|
||||
stream.bpf_pc=0;
|
||||
|
||||
// the first pass will emit the lengths of the instructions
|
||||
// to create the reference table
|
||||
emitm=emit_lenght;
|
||||
|
||||
for(pass=0;;){
|
||||
|
||||
ins = prog;
|
||||
|
||||
/* create the procedure header */
|
||||
PUSH(EBP)
|
||||
MOVrd(EBP,ESP)
|
||||
PUSH(EBX)
|
||||
PUSH(ECX)
|
||||
PUSH(EDX)
|
||||
PUSH(ESI)
|
||||
PUSH(EDI)
|
||||
MOVodd(EBX, EBP, 8)
|
||||
|
||||
for(i=0;i<nins;i++){
|
||||
|
||||
stream.bpf_pc++;
|
||||
|
||||
switch (ins->code) {
|
||||
|
||||
default:
|
||||
|
||||
return NULL;
|
||||
|
||||
case BPF_RET|BPF_K:
|
||||
|
||||
MOVid(EAX,ins->k)
|
||||
POP(EDI)
|
||||
POP(ESI)
|
||||
POP(EDX)
|
||||
POP(ECX)
|
||||
POP(EBX)
|
||||
POP(EBP)
|
||||
RET()
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case BPF_RET|BPF_A:
|
||||
|
||||
POP(EDI)
|
||||
POP(ESI)
|
||||
POP(EDX)
|
||||
POP(ECX)
|
||||
POP(EBX)
|
||||
POP(EBP)
|
||||
RET()
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case BPF_LD|BPF_W|BPF_ABS:
|
||||
|
||||
MOVid(ECX,ins->k)
|
||||
MOVrd(ESI,ECX)
|
||||
ADDib(ECX,sizeof(INT))
|
||||
CMPodd(ECX, EBP, 0x10)
|
||||
JLEb(12)
|
||||
POP(EDI)
|
||||
POP(ESI)
|
||||
POP(EDX)
|
||||
POP(ECX)
|
||||
POP(EBX)
|
||||
POP(EBP)
|
||||
MOVid(EAX,0) //this can be optimized with xor eax,eax
|
||||
RET()
|
||||
MOVobd(EAX, EBX, ESI)
|
||||
BSWAP(EAX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_LD|BPF_H|BPF_ABS:
|
||||
|
||||
MOVid(ECX,ins->k)
|
||||
MOVrd(ESI,ECX)
|
||||
ADDib(ECX,sizeof(SHORT))
|
||||
CMPodd(ECX, EBP, 0x10)
|
||||
JLEb(12)
|
||||
POP(EDI)
|
||||
POP(ESI)
|
||||
POP(EDX)
|
||||
POP(ECX)
|
||||
POP(EBX)
|
||||
POP(EBP)
|
||||
MOVid(EAX,0)
|
||||
RET()
|
||||
MOVid(EAX,0)
|
||||
MOVobw(AX, EBX, ESI)
|
||||
SWAP_AX()
|
||||
|
||||
break;
|
||||
|
||||
case BPF_LD|BPF_B|BPF_ABS:
|
||||
|
||||
MOVid(ECX,ins->k)
|
||||
CMPodd(ECX, EBP, 0x10)
|
||||
JLEb(12)
|
||||
POP(EDI)
|
||||
POP(ESI)
|
||||
POP(EDX)
|
||||
POP(ECX)
|
||||
POP(EBX)
|
||||
POP(EBP)
|
||||
MOVid(EAX,0)
|
||||
RET()
|
||||
MOVid(EAX,0)
|
||||
MOVobb(AL,EBX,ECX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_LD|BPF_W|BPF_LEN:
|
||||
|
||||
MOVodd(EAX, EBP, 0xc)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_LDX|BPF_W|BPF_LEN:
|
||||
|
||||
MOVodd(EDX, EBP, 0xc)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_LD|BPF_W|BPF_IND:
|
||||
|
||||
MOVid(ECX,ins->k)
|
||||
ADDrd(ECX,EDX)
|
||||
MOVrd(ESI,ECX)
|
||||
ADDib(ECX,sizeof(INT))
|
||||
CMPodd(ECX, EBP, 0x10)
|
||||
JLEb(12)
|
||||
POP(EDI)
|
||||
POP(ESI)
|
||||
POP(EDX)
|
||||
POP(ECX)
|
||||
POP(EBX)
|
||||
POP(EBP)
|
||||
MOVid(EAX,0)
|
||||
RET()
|
||||
MOVobd(EAX, EBX, ESI)
|
||||
BSWAP(EAX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_LD|BPF_H|BPF_IND:
|
||||
|
||||
MOVid(ECX,ins->k)
|
||||
ADDrd(ECX,EDX)
|
||||
MOVrd(ESI,ECX)
|
||||
ADDib(ECX,sizeof(SHORT))
|
||||
CMPodd(ECX, EBP, 0x10)
|
||||
JLEb(12)
|
||||
POP(EDI)
|
||||
POP(ESI)
|
||||
POP(EDX)
|
||||
POP(ECX)
|
||||
POP(EBX)
|
||||
POP(EBP)
|
||||
MOVid(EAX,0)
|
||||
RET()
|
||||
MOVid(EAX,0)
|
||||
MOVobw(AX, EBX, ESI)
|
||||
SWAP_AX()
|
||||
|
||||
break;
|
||||
|
||||
case BPF_LD|BPF_B|BPF_IND:
|
||||
|
||||
MOVid(ECX,ins->k)
|
||||
ADDrd(ECX,EDX)
|
||||
CMPodd(ECX, EBP, 0x10)
|
||||
JLEb(12)
|
||||
POP(EDI)
|
||||
POP(ESI)
|
||||
POP(EDX)
|
||||
POP(ECX)
|
||||
POP(EBX)
|
||||
POP(EBP)
|
||||
MOVid(EAX,0)
|
||||
RET()
|
||||
MOVid(EAX,0)
|
||||
MOVobb(AL,EBX,ECX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_LDX|BPF_MSH|BPF_B:
|
||||
|
||||
MOVid(ECX,ins->k)
|
||||
CMPodd(ECX, EBP, 0x10)
|
||||
JLEb(12)
|
||||
POP(EDI)
|
||||
POP(ESI)
|
||||
POP(EDX)
|
||||
POP(ECX)
|
||||
POP(EBX)
|
||||
POP(EBP)
|
||||
MOVid(EAX,0)
|
||||
RET()
|
||||
MOVid(EDX,0)
|
||||
MOVobb(DL,EBX,ECX)
|
||||
ANDib(DL, 0xf)
|
||||
SHLib(EDX, 2)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_LD|BPF_IMM:
|
||||
|
||||
MOVid(EAX,ins->k)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_LDX|BPF_IMM:
|
||||
|
||||
MOVid(EDX,ins->k)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_LD|BPF_MEM:
|
||||
|
||||
MOVid(ECX,(INT)mem)
|
||||
MOVid(ESI,ins->k*4)
|
||||
MOVobd(EAX, ECX, ESI)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_LDX|BPF_MEM:
|
||||
|
||||
MOVid(ECX,(INT)mem)
|
||||
MOVid(ESI,ins->k*4)
|
||||
MOVobd(EDX, ECX, ESI)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ST:
|
||||
|
||||
// XXX: this command and the following could be optimized if the previous
|
||||
// instruction was already of this type
|
||||
MOVid(ECX,(INT)mem)
|
||||
MOVid(ESI,ins->k*4)
|
||||
MOVomd(ECX, ESI, EAX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_STX:
|
||||
|
||||
MOVid(ECX,(INT)mem)
|
||||
MOVid(ESI,ins->k*4)
|
||||
MOVomd(ECX, ESI, EDX)
|
||||
break;
|
||||
|
||||
case BPF_JMP|BPF_JA:
|
||||
|
||||
JMP(stream.refs[stream.bpf_pc+ins->k]-stream.refs[stream.bpf_pc])
|
||||
|
||||
break;
|
||||
|
||||
case BPF_JMP|BPF_JGT|BPF_K:
|
||||
|
||||
CMPid(EAX, ins->k)
|
||||
JG(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5) // 5 is the size of the following JMP
|
||||
JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
|
||||
break;
|
||||
|
||||
case BPF_JMP|BPF_JGE|BPF_K:
|
||||
|
||||
CMPid(EAX, ins->k)
|
||||
JGE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
|
||||
JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
|
||||
|
||||
break;
|
||||
|
||||
case BPF_JMP|BPF_JEQ|BPF_K:
|
||||
|
||||
CMPid(EAX, ins->k)
|
||||
JE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
|
||||
JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
|
||||
|
||||
break;
|
||||
|
||||
case BPF_JMP|BPF_JSET|BPF_K:
|
||||
|
||||
MOVrd(ECX,EAX)
|
||||
ANDid(ECX,ins->k)
|
||||
JE(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]+5)
|
||||
JMP(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc])
|
||||
|
||||
break;
|
||||
|
||||
case BPF_JMP|BPF_JGT|BPF_X:
|
||||
|
||||
CMPrd(EAX, EDX)
|
||||
JA(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
|
||||
JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
|
||||
break;
|
||||
|
||||
case BPF_JMP|BPF_JGE|BPF_X:
|
||||
|
||||
CMPrd(EAX, EDX)
|
||||
JAE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
|
||||
JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
|
||||
|
||||
break;
|
||||
|
||||
case BPF_JMP|BPF_JEQ|BPF_X:
|
||||
|
||||
CMPrd(EAX, EDX)
|
||||
JE(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc]+5)
|
||||
JMP(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc])
|
||||
|
||||
break;
|
||||
|
||||
case BPF_JMP|BPF_JSET|BPF_X:
|
||||
|
||||
MOVrd(ECX,EAX)
|
||||
ANDrd(ECX,EDX)
|
||||
JE(stream.refs[stream.bpf_pc+ins->jf]-stream.refs[stream.bpf_pc]+5)
|
||||
JMP(stream.refs[stream.bpf_pc+ins->jt]-stream.refs[stream.bpf_pc])
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_ADD|BPF_X:
|
||||
|
||||
ADDrd(EAX,EDX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_SUB|BPF_X:
|
||||
|
||||
SUBrd(EAX,EDX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_MUL|BPF_X:
|
||||
|
||||
MOVrd(ECX,EDX)
|
||||
MULrd(EDX)
|
||||
MOVrd(EDX,ECX)
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_DIV|BPF_X:
|
||||
|
||||
CMPid(EDX, 0)
|
||||
JNEb(12)
|
||||
POP(EDI)
|
||||
POP(ESI)
|
||||
POP(EDX)
|
||||
POP(ECX)
|
||||
POP(EBX)
|
||||
POP(EBP)
|
||||
MOVid(EAX,0)
|
||||
RET()
|
||||
MOVrd(ECX,EDX)
|
||||
MOVid(EDX,0)
|
||||
DIVrd(ECX)
|
||||
MOVrd(EDX,ECX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_AND|BPF_X:
|
||||
|
||||
ANDrd(EAX,EDX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_OR|BPF_X:
|
||||
|
||||
ORrd(EAX,EDX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_LSH|BPF_X:
|
||||
|
||||
MOVrd(ECX,EDX)
|
||||
SHL_CLrb(EAX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_RSH|BPF_X:
|
||||
|
||||
MOVrd(ECX,EDX)
|
||||
SHR_CLrb(EAX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_ADD|BPF_K:
|
||||
|
||||
ADD_EAXi(ins->k)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_SUB|BPF_K:
|
||||
|
||||
SUB_EAXi(ins->k)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_MUL|BPF_K:
|
||||
|
||||
MOVrd(ECX,EDX)
|
||||
MOVid(EDX,ins->k)
|
||||
MULrd(EDX)
|
||||
MOVrd(EDX,ECX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_DIV|BPF_K:
|
||||
|
||||
MOVrd(ECX,EDX)
|
||||
MOVid(EDX,0)
|
||||
MOVid(ESI,ins->k)
|
||||
DIVrd(ESI)
|
||||
MOVrd(EDX,ECX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_AND|BPF_K:
|
||||
|
||||
ANDid(EAX, ins->k)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_OR|BPF_K:
|
||||
|
||||
ORid(EAX, ins->k)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_LSH|BPF_K:
|
||||
|
||||
SHLib(EAX, (ins->k) & 255)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_RSH|BPF_K:
|
||||
|
||||
SHRib(EAX, (ins->k) & 255)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_ALU|BPF_NEG:
|
||||
|
||||
NEGd(EAX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_MISC|BPF_TAX:
|
||||
|
||||
MOVrd(EDX,EAX)
|
||||
|
||||
break;
|
||||
|
||||
case BPF_MISC|BPF_TXA:
|
||||
|
||||
MOVrd(EAX,EDX)
|
||||
|
||||
break;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
ins++;
|
||||
}
|
||||
|
||||
pass++;
|
||||
if(pass == 2) break;
|
||||
|
||||
#ifdef NTKERNEL
|
||||
stream.ibuf=(CHAR*)ExAllocatePoolWithTag(NonPagedPool, stream.cur_ip, '1JWA');
|
||||
#else
|
||||
stream.ibuf=(CHAR*)malloc(stream.cur_ip);
|
||||
#endif
|
||||
if(stream.ibuf==NULL)
|
||||
{
|
||||
#ifdef NTKERNEL
|
||||
ExFreePool(stream.refs);
|
||||
#else
|
||||
free(stream.refs);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// modify the reference table to contain the offsets and not the lengths of the instructions
|
||||
for(i=1; i< nins + 1; i++)
|
||||
stream.refs[i]+=stream.refs[i-1];
|
||||
|
||||
// Reset the counters
|
||||
stream.cur_ip=0;
|
||||
stream.bpf_pc=0;
|
||||
// the second pass creates the actual code
|
||||
emitm=emit_code;
|
||||
|
||||
}
|
||||
|
||||
// the reference table is needed only during compilation, now we can free it
|
||||
#ifdef NTKERNEL
|
||||
ExFreePool(stream.refs);
|
||||
#else
|
||||
free(stream.refs);
|
||||
#endif
|
||||
return (BPF_filter_function)stream.ibuf;
|
||||
|
||||
}
|
||||
|
||||
|
||||
JIT_BPF_Filter* BPF_jitter(struct bpf_insn *fp, INT nins)
|
||||
{
|
||||
JIT_BPF_Filter *Filter;
|
||||
|
||||
|
||||
// Allocate the filter structure
|
||||
#ifdef NTKERNEL
|
||||
Filter=(struct JIT_BPF_Filter*)ExAllocatePoolWithTag(NonPagedPool, sizeof(struct JIT_BPF_Filter), '2JWA');
|
||||
#else
|
||||
Filter=(struct JIT_BPF_Filter*)malloc(sizeof(struct JIT_BPF_Filter));
|
||||
#endif
|
||||
if(Filter==NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Allocate the filter's memory
|
||||
#ifdef NTKERNEL
|
||||
Filter->mem=(INT*)ExAllocatePoolWithTag(NonPagedPool, BPF_MEMWORDS*sizeof(INT), '3JWA');
|
||||
#else
|
||||
Filter->mem=(INT*)malloc(BPF_MEMWORDS*sizeof(INT));
|
||||
#endif
|
||||
if(Filter->mem==NULL)
|
||||
{
|
||||
#ifdef NTKERNEL
|
||||
ExFreePool(Filter);
|
||||
#else
|
||||
free(Filter);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create the binary
|
||||
if((Filter->Function = BPFtoX86(fp, nins, Filter->mem))==NULL)
|
||||
{
|
||||
#ifdef NTKERNEL
|
||||
ExFreePool(Filter->mem);
|
||||
ExFreePool(Filter);
|
||||
#else
|
||||
free(Filter->mem);
|
||||
free(Filter);
|
||||
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
return Filter;
|
||||
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
void BPF_Destroy_JIT_Filter(JIT_BPF_Filter *Filter){
|
||||
|
||||
#ifdef NTKERNEL
|
||||
ExFreePool(Filter->mem);
|
||||
ExFreePool(Filter->Function);
|
||||
ExFreePool(Filter);
|
||||
#else
|
||||
free(Filter->mem);
|
||||
free(Filter->Function);
|
||||
free(Filter);
|
||||
#endif
|
||||
|
||||
}
|
391
reactos/drivers/net/packet/jitter.h
Normal file
391
reactos/drivers/net/packet/jitter.h
Normal file
|
@ -0,0 +1,391 @@
|
|||
/*
|
||||
* Copyright (c) 2002
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
/** @ingroup NPF
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup NPF_include NPF structures and definitions
|
||||
* @{
|
||||
*/
|
||||
|
||||
//
|
||||
// Registers
|
||||
//
|
||||
#define EAX 0
|
||||
#define ECX 1
|
||||
#define EDX 2
|
||||
#define EBX 3
|
||||
#define ESP 4
|
||||
#define EBP 5
|
||||
#define ESI 6
|
||||
#define EDI 7
|
||||
|
||||
#define AX 0
|
||||
#define CX 1
|
||||
#define DX 2
|
||||
#define BX 3
|
||||
#define SP 4
|
||||
#define BP 5
|
||||
#define SI 6
|
||||
#define DI 7
|
||||
|
||||
#define AL 0
|
||||
#define CL 1
|
||||
#define DL 2
|
||||
#define BL 3
|
||||
|
||||
/*! \brief A stream of X86 binary code.*/
|
||||
typedef struct binary_stream{
|
||||
INT cur_ip; ///< Current X86 instruction pointer.
|
||||
INT bpf_pc; ///< Current BPF instruction pointer, i.e. position in the BPF program reached by the jitter.
|
||||
PCHAR ibuf; ///< Instruction buffer, contains the X86 generated code.
|
||||
PUINT refs; ///< Jumps reference table.
|
||||
}binary_stream;
|
||||
|
||||
|
||||
/*! \brief Prototype of a filtering function created by the jitter.
|
||||
|
||||
The syntax and the meaning of the parameters is analogous to the one of bpf_filter(). Notice that the filter
|
||||
is not among the parameters, because it is hardwired in the function.
|
||||
*/
|
||||
typedef UINT (*BPF_filter_function)( binary_stream *, ULONG, UINT);
|
||||
|
||||
/*! \brief Prototype of the emit functions.
|
||||
|
||||
Different emit functions are used to create the reference table and to generate the actual filtering code.
|
||||
This allows to have simpler instruction macros.
|
||||
The first parameter is the stream that will receive the data. The secon one is a variable containing
|
||||
the data, the third one is the length, that can be 1,2 or 4 since it is possible to emit a byte, a short
|
||||
or a work at a time.
|
||||
*/
|
||||
typedef void (*emit_func)(binary_stream *stream, ULONG value, UINT n);
|
||||
|
||||
/*! \brief Structure describing a x86 filtering program created by the jitter.*/
|
||||
typedef struct JIT_BPF_Filter{
|
||||
BPF_filter_function Function; ///< The x86 filtering binary, in the form of a BPF_filter_function.
|
||||
PINT mem;
|
||||
}
|
||||
JIT_BPF_Filter;
|
||||
|
||||
|
||||
|
||||
|
||||
/**************************/
|
||||
/* X86 INSTRUCTION MACROS */
|
||||
/**************************/
|
||||
|
||||
/// mov r32,i32
|
||||
#define MOVid(r32, i32) \
|
||||
emitm(&stream, 11 << 4 | 1 << 3 | r32 & 0x7, 1); emitm(&stream, i32, 4);
|
||||
|
||||
/// mov dr32,sr32
|
||||
#define MOVrd(dr32, sr32) \
|
||||
emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
|
||||
|
||||
/// mov dr32,sr32[off]
|
||||
#define MOVodd(dr32, sr32, off) \
|
||||
emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \
|
||||
emitm(&stream, 1 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);\
|
||||
emitm(&stream, off, 1);
|
||||
|
||||
/// mov dr32,sr32[or32]
|
||||
#define MOVobd(dr32, sr32, or32) \
|
||||
emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \
|
||||
emitm(&stream, (dr32 & 0x7) << 3 | 4 , 1);\
|
||||
emitm(&stream, (or32 & 0x7) << 3 | (sr32 & 0x7) , 1);
|
||||
|
||||
/// mov dr16,sr32[or32]
|
||||
#define MOVobw(dr32, sr32, or32) \
|
||||
emitm(&stream, 0x66, 1); \
|
||||
emitm(&stream, 8 << 4 | 3 | 1 << 3, 1); \
|
||||
emitm(&stream, (dr32 & 0x7) << 3 | 4 , 1);\
|
||||
emitm(&stream, (or32 & 0x7) << 3 | (sr32 & 0x7) , 1);
|
||||
|
||||
/// mov dr8,sr32[or32]
|
||||
#define MOVobb(dr8, sr32, or32) \
|
||||
emitm(&stream, 0x8a, 1); \
|
||||
emitm(&stream, (dr8 & 0x7) << 3 | 4 , 1);\
|
||||
emitm(&stream, (or32 & 0x7) << 3 | (sr32 & 0x7) , 1);
|
||||
|
||||
/// mov [dr32][or32],sr32
|
||||
#define MOVomd(dr32, or32, sr32) \
|
||||
emitm(&stream, 0x89, 1); \
|
||||
emitm(&stream, (sr32 & 0x7) << 3 | 4 , 1);\
|
||||
emitm(&stream, (or32 & 0x7) << 3 | (dr32 & 0x7) , 1);
|
||||
|
||||
/// bswap dr32
|
||||
#define BSWAP(dr32) \
|
||||
emitm(&stream, 0xf, 1); \
|
||||
emitm(&stream, 0x19 << 3 | dr32 , 1);
|
||||
|
||||
/// xchg al,ah
|
||||
#define SWAP_AX() \
|
||||
emitm(&stream, 0x86, 1); \
|
||||
emitm(&stream, 0xc4 , 1);
|
||||
|
||||
/// push r32
|
||||
#define PUSH(r32) \
|
||||
emitm(&stream, 5 << 4 | 0 << 3 | r32 & 0x7, 1);
|
||||
|
||||
/// pop r32
|
||||
#define POP(r32) \
|
||||
emitm(&stream, 5 << 4 | 1 << 3 | r32 & 0x7, 1);
|
||||
|
||||
/// ret
|
||||
#define RET() \
|
||||
emitm(&stream, 12 << 4 | 0 << 3 | 3, 1);
|
||||
|
||||
/// add dr32,sr32
|
||||
#define ADDrd(dr32, sr32) \
|
||||
emitm(&stream, 0x03, 1);\
|
||||
emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | (sr32 & 0x7), 1);
|
||||
|
||||
/// add eax,i32
|
||||
#define ADD_EAXi(i32) \
|
||||
emitm(&stream, 0x05, 1);\
|
||||
emitm(&stream, i32, 4);
|
||||
|
||||
/// add r32,i32
|
||||
#define ADDid(r32, i32) \
|
||||
emitm(&stream, 0x81, 1);\
|
||||
emitm(&stream, 24 << 3 | r32, 1);\
|
||||
emitm(&stream, i32, 4);
|
||||
|
||||
/// add r32,i8
|
||||
#define ADDib(r32, i8) \
|
||||
emitm(&stream, 0x83, 1);\
|
||||
emitm(&stream, 24 << 3 | r32, 1);\
|
||||
emitm(&stream, i8, 1);
|
||||
|
||||
/// sub dr32,sr32
|
||||
#define SUBrd(dr32, sr32) \
|
||||
emitm(&stream, 0x2b, 1);\
|
||||
emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | (sr32 & 0x7), 1);
|
||||
|
||||
/// sub eax,i32
|
||||
#define SUB_EAXi(i32) \
|
||||
emitm(&stream, 0x2d, 1);\
|
||||
emitm(&stream, i32, 4);
|
||||
|
||||
/// mul r32
|
||||
#define MULrd(r32) \
|
||||
emitm(&stream, 0xf7, 1);\
|
||||
emitm(&stream, 7 << 5 | (r32 & 0x7), 1);
|
||||
|
||||
/// div r32
|
||||
#define DIVrd(r32) \
|
||||
emitm(&stream, 0xf7, 1);\
|
||||
emitm(&stream, 15 << 4 | (r32 & 0x7), 1);
|
||||
|
||||
/// and r8,i8
|
||||
#define ANDib(r8, i8) \
|
||||
emitm(&stream, 0x80, 1);\
|
||||
emitm(&stream, 7 << 5 | r8, 1);\
|
||||
emitm(&stream, i8, 1);
|
||||
|
||||
/// and r32,i32
|
||||
#define ANDid(r32, i32) \
|
||||
if (r32 == EAX){ \
|
||||
emitm(&stream, 0x25, 1);\
|
||||
emitm(&stream, i32, 4);}\
|
||||
else{ \
|
||||
emitm(&stream, 0x81, 1);\
|
||||
emitm(&stream, 7 << 5 | r32, 1);\
|
||||
emitm(&stream, i32, 4);}
|
||||
|
||||
/// and dr32,sr32
|
||||
#define ANDrd(dr32, sr32) \
|
||||
emitm(&stream, 0x23, 1);\
|
||||
emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
|
||||
|
||||
/// or dr32,sr32
|
||||
#define ORrd(dr32, sr32) \
|
||||
emitm(&stream, 0x0b, 1);\
|
||||
emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
|
||||
|
||||
/// or r32,i32
|
||||
#define ORid(r32, i32) \
|
||||
if (r32 == EAX){ \
|
||||
emitm(&stream, 0x0d, 1);\
|
||||
emitm(&stream, i32, 4);}\
|
||||
else{ \
|
||||
emitm(&stream, 0x81, 1);\
|
||||
emitm(&stream, 25 << 3 | r32, 1);\
|
||||
emitm(&stream, i32, 4);}
|
||||
|
||||
/// shl r32,i8
|
||||
#define SHLib(r32, i8) \
|
||||
emitm(&stream, 0xc1, 1);\
|
||||
emitm(&stream, 7 << 5 | r32 & 0x7, 1);\
|
||||
emitm(&stream, i8, 1);
|
||||
|
||||
/// shl dr32,cl
|
||||
#define SHL_CLrb(dr32) \
|
||||
emitm(&stream, 0xd3, 1);\
|
||||
emitm(&stream, 7 << 5 | dr32 & 0x7, 1);
|
||||
|
||||
/// shr r32,i8
|
||||
#define SHRib(r32, i8) \
|
||||
emitm(&stream, 0xc1, 1);\
|
||||
emitm(&stream, 29 << 3 | r32 & 0x7, 1);\
|
||||
emitm(&stream, i8, 1);
|
||||
|
||||
/// shr dr32,cl
|
||||
#define SHR_CLrb(dr32) \
|
||||
emitm(&stream, 0xd3, 1);\
|
||||
emitm(&stream, 29 << 3 | dr32 & 0x7, 1);
|
||||
|
||||
/// neg r32
|
||||
#define NEGd(r32) \
|
||||
emitm(&stream, 0xf7, 1);\
|
||||
emitm(&stream, 27 << 3 | r32 & 0x7, 1);
|
||||
|
||||
/// cmp dr32,sr32[off]
|
||||
#define CMPodd(dr32, sr32, off) \
|
||||
emitm(&stream, 3 << 4 | 3 | 1 << 3, 1); \
|
||||
emitm(&stream, 1 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);\
|
||||
emitm(&stream, off, 1);
|
||||
|
||||
/// cmp dr32,sr32
|
||||
#define CMPrd(dr32, sr32) \
|
||||
emitm(&stream, 0x3b, 1); \
|
||||
emitm(&stream, 3 << 6 | (dr32 & 0x7) << 3 | sr32 & 0x7, 1);
|
||||
|
||||
/// cmp dr32,i32
|
||||
#define CMPid(dr32, i32) \
|
||||
if (dr32 == EAX){ \
|
||||
emitm(&stream, 0x3d, 1); \
|
||||
emitm(&stream, i32, 4);} \
|
||||
else{ \
|
||||
emitm(&stream, 0x81, 1); \
|
||||
emitm(&stream, 0x1f << 3 | (dr32 & 0x7), 1);\
|
||||
emitm(&stream, i32, 4);}
|
||||
|
||||
/// jne off32
|
||||
#define JNEb(off8) \
|
||||
emitm(&stream, 0x75, 1);\
|
||||
emitm(&stream, off8, 1);
|
||||
|
||||
/// je off32
|
||||
#define JE(off32) \
|
||||
emitm(&stream, 0x0f, 1);\
|
||||
emitm(&stream, 0x84, 1);\
|
||||
emitm(&stream, off32, 4);
|
||||
|
||||
/// jle off32
|
||||
#define JLE(off32) \
|
||||
emitm(&stream, 0x0f, 1);\
|
||||
emitm(&stream, 0x8e, 1);\
|
||||
emitm(&stream, off32, 4);
|
||||
|
||||
/// jle off8
|
||||
#define JLEb(off8) \
|
||||
emitm(&stream, 0x7e, 1);\
|
||||
emitm(&stream, off8, 1);
|
||||
|
||||
/// ja off32
|
||||
#define JA(off32) \
|
||||
emitm(&stream, 0x0f, 1);\
|
||||
emitm(&stream, 0x87, 1);\
|
||||
emitm(&stream, off32, 4);
|
||||
|
||||
/// jae off32
|
||||
#define JAE(off32) \
|
||||
emitm(&stream, 0x0f, 1);\
|
||||
emitm(&stream, 0x83, 1);\
|
||||
emitm(&stream, off32, 4);
|
||||
|
||||
/// jg off32
|
||||
#define JG(off32) \
|
||||
emitm(&stream, 0x0f, 1);\
|
||||
emitm(&stream, 0x8f, 1);\
|
||||
emitm(&stream, off32, 4);
|
||||
|
||||
/// jge off32
|
||||
#define JGE(off32) \
|
||||
emitm(&stream, 0x0f, 1);\
|
||||
emitm(&stream, 0x8d, 1);\
|
||||
emitm(&stream, off32, 4);
|
||||
|
||||
/// jmp off32
|
||||
#define JMP(off32) \
|
||||
emitm(&stream, 0xe9, 1);\
|
||||
emitm(&stream, off32, 4);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**************************/
|
||||
/* Prototypes */
|
||||
/**************************/
|
||||
|
||||
/** @ingroup NPF
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup NPF_code NPF functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*!
|
||||
\brief BPF jitter, builds an x86 function from a BPF program.
|
||||
\param fp The BPF pseudo-assembly filter that will be translated into x86 code.
|
||||
\param nins Number of instructions of the input filter.
|
||||
\return The JIT_BPF_Filter structure containing the x86 filtering binary.
|
||||
|
||||
BPF_jitter allocates the buffers for the new native filter and then translates the program pointed by fp
|
||||
calling BPFtoX86().
|
||||
*/
|
||||
JIT_BPF_Filter* BPF_jitter(struct bpf_insn *fp, INT nins);
|
||||
|
||||
/*!
|
||||
\brief Translates a set of BPF instructions in a set of x86 ones.
|
||||
\param ins Pointer to the BPF instructions that will be translated into x86 code.
|
||||
\param nins Number of instructions to translate.
|
||||
\param mem Memory used by the x86 function to emulate the RAM of the BPF pseudo processor.
|
||||
\return The x86 filtering function.
|
||||
|
||||
This function does the hard work for the JIT compilation. It takes a group of BPF pseudo instructions and
|
||||
through the instruction macros defined in jitter.h it is able to create an function directly executable
|
||||
by NPF.
|
||||
*/
|
||||
BPF_filter_function BPFtoX86(struct bpf_insn *prog, UINT nins, INT *mem);
|
||||
/*!
|
||||
\brief Deletes a filtering function that was previously created by BPF_jitter().
|
||||
\param Filter The filter to destroy.
|
||||
|
||||
This function frees the variuos buffers (code, memory, etc.) associated with a filtering function.
|
||||
*/
|
||||
void BPF_Destroy_JIT_Filter(JIT_BPF_Filter *Filter);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
65
reactos/drivers/net/packet/memory_t.c
Normal file
65
reactos/drivers/net/packet/memory_t.c
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#include "tme.h"
|
||||
#include "memory_t.h"
|
||||
|
||||
|
||||
int32 SW_LONG_AT(void *b, uint32 c)
|
||||
{
|
||||
return ((int32)*((uint8 *)b+c)<<24|
|
||||
(int32)*((uint8 *)b+c+1)<<16|
|
||||
(int32)*((uint8 *)b+c+2)<<8|
|
||||
(int32)*((uint8 *)b+c+3)<<0);
|
||||
}
|
||||
|
||||
uint32 SW_ULONG_AT(void *b, uint32 c)
|
||||
{
|
||||
return ((uint32)*((uint8 *)b+c)<<24|
|
||||
(uint32)*((uint8 *)b+c+1)<<16|
|
||||
(uint32)*((uint8 *)b+c+2)<<8|
|
||||
(uint32)*((uint8 *)b+c+3)<<0);
|
||||
}
|
||||
|
||||
int16 SW_SHORT_AT(void *b, uint32 os)
|
||||
{
|
||||
return ((int16)
|
||||
((int16)*((uint8 *)b+os+0)<<8|
|
||||
(int16)*((uint8 *)b+os+1)<<0));
|
||||
}
|
||||
|
||||
uint16 SW_USHORT_AT(void *b, uint32 os)
|
||||
{
|
||||
return ((uint16)
|
||||
((uint16)*((uint8 *)b+os+0)<<8|
|
||||
(uint16)*((uint8 *)b+os+1)<<0));
|
||||
}
|
||||
|
||||
VOID SW_ULONG_ASSIGN(void *dst, uint32 src)
|
||||
{
|
||||
*((uint8*)dst+0)=*((uint8*)&src+3);
|
||||
*((uint8*)dst+1)=*((uint8*)&src+2);
|
||||
*((uint8*)dst+2)=*((uint8*)&src+1);
|
||||
*((uint8*)dst+3)=*((uint8*)&src+0);
|
||||
|
||||
}
|
||||
|
||||
void assert(void* assert, const char* file, int line, void* msg) { };
|
119
reactos/drivers/net/packet/memory_t.h
Normal file
119
reactos/drivers/net/packet/memory_t.h
Normal file
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifndef __memory_t
|
||||
#define __memory_t
|
||||
|
||||
#define uint8 UCHAR
|
||||
#define int8 CHAR
|
||||
#define uint16 USHORT
|
||||
#define int16 SHORT
|
||||
#define uint32 ULONG
|
||||
#define int32 LONG
|
||||
#define uint64 ULONGLONG
|
||||
#define int64 LONGLONG
|
||||
|
||||
/*memory type*/
|
||||
typedef struct __MEM_TYPE
|
||||
{
|
||||
uint8 *buffer;
|
||||
uint32 size;
|
||||
} MEM_TYPE, *PMEM_TYPE;
|
||||
|
||||
#define LONG_AT(base,offset) (*(int32*)((uint8*)base+(uint32)offset))
|
||||
|
||||
#define ULONG_AT(base,offset) (*(uint32*)((uint8*)base+(uint32)offset))
|
||||
|
||||
#define SHORT_AT(base,offset) (*(int16*)((uint8*)base+(uint32)offset))
|
||||
|
||||
#define USHORT_AT(base,offset) (*(uint16*)((uint8*)base+(uint32)offset))
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
int32 SW_LONG_AT(void *b, uint32 c);
|
||||
uint32 SW_ULONG_AT(void *b, uint32 c);
|
||||
int16 SW_SHORT_AT(void *b, uint32 os);
|
||||
uint16 SW_USHORT_AT(void *b, uint32 os);
|
||||
VOID SW_ULONG_ASSIGN(void *dst, uint32 src);
|
||||
|
||||
#else /* __GNUC__ */
|
||||
|
||||
__inline int32 SW_LONG_AT(void *b, uint32 c)
|
||||
{
|
||||
return ((int32)*((uint8 *)b+c)<<24|
|
||||
(int32)*((uint8 *)b+c+1)<<16|
|
||||
(int32)*((uint8 *)b+c+2)<<8|
|
||||
(int32)*((uint8 *)b+c+3)<<0);
|
||||
}
|
||||
|
||||
__inline uint32 SW_ULONG_AT(void *b, uint32 c)
|
||||
{
|
||||
return ((uint32)*((uint8 *)b+c)<<24|
|
||||
(uint32)*((uint8 *)b+c+1)<<16|
|
||||
(uint32)*((uint8 *)b+c+2)<<8|
|
||||
(uint32)*((uint8 *)b+c+3)<<0);
|
||||
}
|
||||
|
||||
__inline int16 SW_SHORT_AT(void *b, uint32 os)
|
||||
{
|
||||
return ((int16)
|
||||
((int16)*((uint8 *)b+os+0)<<8|
|
||||
(int16)*((uint8 *)b+os+1)<<0));
|
||||
}
|
||||
|
||||
__inline uint16 SW_USHORT_AT(void *b, uint32 os)
|
||||
{
|
||||
return ((uint16)
|
||||
((uint16)*((uint8 *)b+os+0)<<8|
|
||||
(uint16)*((uint8 *)b+os+1)<<0));
|
||||
}
|
||||
|
||||
__inline VOID SW_ULONG_ASSIGN(void *dst, uint32 src)
|
||||
{
|
||||
*((uint8*)dst+0)=*((uint8*)&src+3);
|
||||
*((uint8*)dst+1)=*((uint8*)&src+2);
|
||||
*((uint8*)dst+2)=*((uint8*)&src+1);
|
||||
*((uint8*)dst+3)=*((uint8*)&src+0);
|
||||
|
||||
}
|
||||
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
#ifdef WIN_NT_DRIVER
|
||||
|
||||
#define ALLOCATE_MEMORY(dest,type,amount) \
|
||||
(dest)=ExAllocatePool(NonPagedPool,sizeof(type)*(amount));
|
||||
#define ALLOCATE_ZERO_MEMORY(dest,type,amount) \
|
||||
{ \
|
||||
(dest)=ExAllocatePool(NonPagedPool,sizeof(type)*(amount)); \
|
||||
if ((dest)!=NULL) \
|
||||
RtlZeroMemory((dest),sizeof(type)*(amount)); \
|
||||
}
|
||||
|
||||
#define FREE_MEMORY(dest) ExFreePool(dest);
|
||||
#define ZERO_MEMORY(dest,amount) RtlZeroMemory(dest,amount);
|
||||
#define COPY_MEMORY(dest,src,amount) RtlCopyMemory(dest,src,amount);
|
||||
|
||||
#endif /*WIN_NT_DRIVER*/
|
||||
|
||||
|
||||
#endif
|
||||
|
191
reactos/drivers/net/packet/normal_lookup.c
Normal file
191
reactos/drivers/net/packet/normal_lookup.c
Normal file
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#include "tme.h"
|
||||
#include "normal_lookup.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <net/tme/tme.h>
|
||||
#include <net/tme/normal_lookup.h>
|
||||
#else
|
||||
#include <tme/tme.h>
|
||||
#include <tme/normal_lookup.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* lookup in the table, seen as an hash */
|
||||
/* if not found, inserts an element */
|
||||
/* returns TME_TRUE if the entry is found or created, */
|
||||
/* returns TME_FALSE if no more blocks are available */
|
||||
uint32 normal_lut_w_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref)
|
||||
{
|
||||
uint32 i;
|
||||
uint32 tocs=0;
|
||||
uint32 *key32=(uint32*) key;
|
||||
uint32 shrinked_key=0;
|
||||
uint32 index;
|
||||
RECORD *records=(RECORD*)data->lut_base_address;
|
||||
uint8 *offset;
|
||||
uint32 key_len=data->key_len;
|
||||
/*the key is shrinked into a 32-bit value */
|
||||
for (i=0; i<key_len;i++)
|
||||
shrinked_key^=key32[i];
|
||||
/*the first index in the table is calculated*/
|
||||
index=shrinked_key % data->lut_entries;
|
||||
|
||||
while (tocs<=data->filled_entries)
|
||||
{
|
||||
|
||||
if (records[index].block==0)
|
||||
{ /*creation of a new entry*/
|
||||
|
||||
if (data->filled_blocks==data->shared_memory_blocks)
|
||||
{
|
||||
/*no more free blocks*/
|
||||
GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref);
|
||||
data->last_found=NULL;
|
||||
return TME_FALSE;
|
||||
}
|
||||
|
||||
/*offset=absolute pointer to the block associated*/
|
||||
/*with the newly created entry*/
|
||||
offset=data->shared_memory_base_address+
|
||||
data->block_size*data->filled_blocks;
|
||||
|
||||
/*copy the key in the block*/
|
||||
COPY_MEMORY(offset,key32,key_len*4);
|
||||
GET_TIME((struct timeval *)(offset+4*key_len),time_ref);
|
||||
/*assign the block relative offset to the entry, in NBO*/
|
||||
SW_ULONG_ASSIGN(&records[index].block,offset-mem_ex->buffer);
|
||||
|
||||
data->filled_blocks++;
|
||||
|
||||
/*assign the exec function ID to the entry, in NBO*/
|
||||
SW_ULONG_ASSIGN(&records[index].exec_fcn,data->default_exec);
|
||||
data->filled_entries++;
|
||||
|
||||
data->last_found=(uint8*)&records[index];
|
||||
|
||||
return TME_TRUE;
|
||||
}
|
||||
/*offset contains the absolute pointer to the block*/
|
||||
/*associated with the current entry */
|
||||
offset=mem_ex->buffer+SW_ULONG_AT(&records[index].block,0);
|
||||
|
||||
for (i=0; (i<key_len) && (key32[i]==ULONG_AT(offset,i*4)); i++);
|
||||
|
||||
if (i==key_len)
|
||||
{
|
||||
/*key in the block matches the one provided, right entry*/
|
||||
GET_TIME((struct timeval *)(offset+4*key_len),time_ref);
|
||||
data->last_found=(uint8*)&records[index];
|
||||
return TME_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* wrong entry, rehashing */
|
||||
if (IS_DELETABLE(offset+key_len*4,data))
|
||||
{
|
||||
ZERO_MEMORY(offset,data->block_size);
|
||||
COPY_MEMORY(offset,key32,key_len*4);
|
||||
SW_ULONG_ASSIGN(&records[index].exec_fcn,data->default_exec);
|
||||
GET_TIME((struct timeval*)(offset+key_len*4),time_ref);
|
||||
data->last_found=(uint8*)&records[index];
|
||||
return TME_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
index=(index+data->rehashing_value) % data->lut_entries;
|
||||
tocs++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* nothing found, last found= out of lut */
|
||||
GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref);
|
||||
data->last_found=NULL;
|
||||
return TME_FALSE;
|
||||
|
||||
}
|
||||
|
||||
/* lookup in the table, seen as an hash */
|
||||
/* if not found, returns out of count entry index */
|
||||
/* returns TME_TRUE if the entry is found */
|
||||
/* returns TME_FALSE if the entry is not found */
|
||||
uint32 normal_lut_wo_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref)
|
||||
{
|
||||
uint32 i;
|
||||
uint32 tocs=0;
|
||||
uint32 *key32=(uint32*) key;
|
||||
uint32 shrinked_key=0;
|
||||
uint32 index;
|
||||
RECORD *records=(RECORD*)data->lut_base_address;
|
||||
uint8 *offset;
|
||||
uint32 key_len=data->key_len;
|
||||
/*the key is shrinked into a 32-bit value */
|
||||
for (i=0; i<key_len;i++)
|
||||
shrinked_key^=key32[i];
|
||||
/*the first index in the table is calculated*/
|
||||
index=shrinked_key % data->lut_entries;
|
||||
|
||||
while (tocs<=data->filled_entries)
|
||||
{
|
||||
|
||||
if (records[index].block==0)
|
||||
{ /*out of table, insertion is not allowed*/
|
||||
GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref);
|
||||
data->last_found=NULL;
|
||||
return TME_FALSE;
|
||||
}
|
||||
/*offset contains the absolute pointer to the block*/
|
||||
/*associated with the current entry */
|
||||
|
||||
offset=mem_ex->buffer+SW_ULONG_AT(&records[index].block,0);
|
||||
|
||||
for (i=0; (i<key_len) && (key32[i]==ULONG_AT(offset,i*4)); i++);
|
||||
|
||||
if (i==key_len)
|
||||
{
|
||||
/*key in the block matches the one provided, right entry*/
|
||||
GET_TIME((struct timeval *)(offset+4*key_len),time_ref);
|
||||
data->last_found=(uint8*)&records[index];
|
||||
return TME_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*wrong entry, rehashing*/
|
||||
index=(index+data->rehashing_value) % data->lut_entries;
|
||||
tocs++;
|
||||
}
|
||||
}
|
||||
|
||||
/*nothing found, last found= out of lut*/
|
||||
GET_TIME((struct timeval *)(data->shared_memory_base_address+4*key_len),time_ref);
|
||||
data->last_found=NULL;
|
||||
return TME_FALSE;
|
||||
|
||||
}
|
45
reactos/drivers/net/packet/normal_lookup.h
Normal file
45
reactos/drivers/net/packet/normal_lookup.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifndef __normal_lookup
|
||||
#define __normal_lookup
|
||||
|
||||
#ifdef WIN32
|
||||
#include "tme.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <net/tme/tme.h>
|
||||
#else
|
||||
#include <tme/tme.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#define NORMAL_LUT_W_INSERT 0x00000000
|
||||
uint32 normal_lut_w_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);
|
||||
#define NORMAL_LUT_WO_INSERT 0x00000001
|
||||
uint32 normal_lut_wo_insert(uint8 *key, TME_DATA *data, MEM_TYPE *mem_ex, struct time_conv *time_ref);
|
||||
#define DUMMY_INSERT 1234
|
||||
|
||||
#endif
|
|
@ -25,10 +25,8 @@
|
|||
#include "ndis.h"
|
||||
#else
|
||||
#include <ddk/ntddk.h>
|
||||
//#include <net/miniport.h>
|
||||
#include <net/ndis.h>
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
#include "packet.h"
|
||||
|
||||
|
@ -41,10 +39,9 @@ static NDIS_MEDIUM MediumArray[] = {
|
|||
NdisMedium802_5
|
||||
};
|
||||
|
||||
ULONG NamedEventsCounter=0;
|
||||
|
||||
#define NUM_NDIS_MEDIA (sizeof MediumArray / sizeof MediumArray[0])
|
||||
|
||||
ULONG NamedEventsCounter=0;
|
||||
|
||||
//Itoa. Replaces the buggy RtlIntegerToUnicodeString
|
||||
void PacketItoa(UINT n,PUCHAR buf){
|
||||
|
@ -58,9 +55,20 @@ int i;
|
|||
|
||||
}
|
||||
|
||||
/// Global start time. Used as an absolute reference for timestamp conversion.
|
||||
struct time_conv G_Start_Time = {
|
||||
0,
|
||||
{0, 0},
|
||||
};
|
||||
|
||||
NTSTATUS STDCALL
|
||||
PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
||||
UINT n_Opened_Instances = 0;
|
||||
|
||||
NDIS_SPIN_LOCK Opened_Instances_Lock;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
NTSTATUS
|
||||
NPF_Open(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
||||
{
|
||||
|
||||
PDEVICE_EXTENSION DeviceExtension;
|
||||
|
@ -71,33 +79,25 @@ PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
|||
|
||||
NDIS_STATUS Status;
|
||||
NDIS_STATUS ErrorStatus;
|
||||
UINT Medium;
|
||||
UINT i;
|
||||
PUCHAR tpointer;
|
||||
PLIST_ENTRY PacketListEntry;
|
||||
LARGE_INTEGER TimeFreq;
|
||||
LARGE_INTEGER SystemTime;
|
||||
LARGE_INTEGER PTime;
|
||||
PCHAR EvName;
|
||||
|
||||
IF_LOUD(DbgPrint("Packet: OpenAdapter\n");)
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: OpenAdapter\n");)
|
||||
|
||||
DeviceExtension = DeviceObject->DeviceExtension;
|
||||
|
||||
|
||||
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
|
||||
//
|
||||
// allocate some memory for the open structure
|
||||
//
|
||||
Open=ExAllocatePool(NonPagedPool,sizeof(OPEN_INSTANCE));
|
||||
Open=ExAllocatePoolWithTag(NonPagedPool, sizeof(OPEN_INSTANCE), '0OWA');
|
||||
|
||||
|
||||
if (Open==NULL) {
|
||||
//
|
||||
// no memory
|
||||
//
|
||||
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
@ -109,34 +109,26 @@ PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
|||
);
|
||||
|
||||
|
||||
EvName=ExAllocatePool(NonPagedPool, sizeof(L"\\BaseNamedObjects\\NPF0000000000") );
|
||||
EvName=ExAllocatePoolWithTag(NonPagedPool, sizeof(L"\\BaseNamedObjects\\NPF0000000000"), '1OWA');
|
||||
|
||||
if (EvName==NULL) {
|
||||
//
|
||||
// no memory
|
||||
//
|
||||
ExFreePool(Open);
|
||||
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
//
|
||||
// Save or open here
|
||||
//
|
||||
IrpSp->FileObject->FsContext=Open;
|
||||
|
||||
Open->DeviceExtension=DeviceExtension;
|
||||
|
||||
|
||||
//
|
||||
// Save the Irp here for the completeion routine to retrieve
|
||||
//
|
||||
Open->OpenCloseIrp=Irp;
|
||||
|
||||
//
|
||||
// Allocate a packet pool for our xmit and receive packets
|
||||
//
|
||||
NdisAllocatePacketPool(
|
||||
&Status,
|
||||
&Open->PacketPool,
|
||||
|
@ -146,7 +138,7 @@ PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
|||
|
||||
if (Status != NDIS_STATUS_SUCCESS) {
|
||||
|
||||
IF_LOUD(DbgPrint("Packet: Failed to allocate packet pool\n");)
|
||||
IF_LOUD(DbgPrint("NPF: Failed to allocate packet pool\n");)
|
||||
|
||||
ExFreePool(Open);
|
||||
ExFreePool(EvName);
|
||||
|
@ -160,6 +152,7 @@ PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
|||
|
||||
//Create the string containing the name of the read event
|
||||
RtlInitUnicodeString(&Open->ReadEventName,(PCWSTR) EvName);
|
||||
|
||||
PacketItoa(NamedEventsCounter,(PUCHAR)(Open->ReadEventName.Buffer+21));
|
||||
|
||||
InterlockedIncrement(&NamedEventsCounter);
|
||||
|
@ -170,6 +163,7 @@ PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
|||
Open->ReadEvent=IoCreateNotificationEvent(&Open->ReadEventName,&Open->ReadEventHandle);
|
||||
if(Open->ReadEvent==NULL){
|
||||
ExFreePool(Open);
|
||||
ExFreePool(EvName);
|
||||
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
@ -179,51 +173,58 @@ PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
|||
KeClearEvent(Open->ReadEvent);
|
||||
NdisInitializeEvent(&Open->WriteEvent);
|
||||
NdisInitializeEvent(&Open->IOEvent);
|
||||
NdisInitializeEvent(&Open->DumpEvent);
|
||||
NdisInitializeEvent(&Open->IOEvent);
|
||||
NdisAllocateSpinLock(&Open->machine_lock);
|
||||
|
||||
|
||||
//
|
||||
// list to hold irp's want to reset the adapter
|
||||
//
|
||||
InitializeListHead(&Open->ResetIrpList);
|
||||
|
||||
|
||||
//
|
||||
// Initialize list for holding pending read requests
|
||||
//
|
||||
KeInitializeSpinLock(&Open->RcvQSpinLock);
|
||||
InitializeListHead(&Open->RcvList);
|
||||
|
||||
//
|
||||
// Initialize the request list
|
||||
//
|
||||
KeInitializeSpinLock(&Open->RequestSpinLock);
|
||||
InitializeListHead(&Open->RequestList);
|
||||
|
||||
// Initializes the extended memory of the NPF machine
|
||||
Open->mem_ex.buffer = ExAllocatePoolWithTag(NonPagedPool, DEFAULT_MEM_EX_SIZE, '2OWA');
|
||||
if((Open->mem_ex.buffer) == NULL)
|
||||
{
|
||||
// no memory
|
||||
ExFreePool(Open);
|
||||
ExFreePool(EvName);
|
||||
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
Open->mem_ex.size = DEFAULT_MEM_EX_SIZE;
|
||||
RtlZeroMemory(Open->mem_ex.buffer, DEFAULT_MEM_EX_SIZE);
|
||||
|
||||
// get the absolute value of the system boot time.
|
||||
PTime=KeQueryPerformanceCounter(&TimeFreq);
|
||||
KeQuerySystemTime(&SystemTime);
|
||||
#ifndef __NTDRIVER__ // robert
|
||||
Open->StartTime.QuadPart=(((SystemTime.QuadPart)%10000000)*TimeFreq.QuadPart)/10000000;
|
||||
SystemTime.QuadPart=SystemTime.QuadPart/10000000-11644473600;
|
||||
#endif
|
||||
Open->StartTime.QuadPart+=(SystemTime.QuadPart)*TimeFreq.QuadPart-PTime.QuadPart;
|
||||
//initalize the open instance
|
||||
Open->BufSize=0;
|
||||
Open->Buffer=NULL;
|
||||
Open->Bhead=0;
|
||||
Open->Btail=0;
|
||||
Open->BLastByte=0;
|
||||
Open->Dropped=0; //reset the dropped packets counter
|
||||
Open->Received=0; //reset the received packets counter
|
||||
Open->bpfprogram=NULL; //reset the filter
|
||||
Open->mode=MODE_CAPT;
|
||||
Open->Nbytes.QuadPart=0;
|
||||
Open->Npackets.QuadPart=0;
|
||||
Open->Nwrites=1;
|
||||
Open->Multiple_Write_Counter=0;
|
||||
Open->MinToCopy=0;
|
||||
Open->TimeOut.QuadPart=(LONGLONG)1;
|
||||
Open->Bound=TRUE;
|
||||
//
|
||||
// Initialize the open instance
|
||||
//
|
||||
Open->BufSize = 0;
|
||||
Open->Buffer = NULL;
|
||||
Open->Bhead = 0;
|
||||
Open->Btail = 0;
|
||||
Open->BLastByte = 0;
|
||||
Open->Dropped = 0; //reset the dropped packets counter
|
||||
Open->Received = 0; //reset the received packets counter
|
||||
Open->Accepted = 0; //reset the accepted packets counter
|
||||
Open->bpfprogram = NULL; //reset the filter
|
||||
Open->mode = MODE_CAPT;
|
||||
Open->Nbytes.QuadPart = 0;
|
||||
Open->Npackets.QuadPart = 0;
|
||||
Open->Nwrites = 1;
|
||||
Open->Multiple_Write_Counter = 0;
|
||||
Open->MinToCopy = 0;
|
||||
Open->TimeOut.QuadPart = (LONGLONG)1;
|
||||
Open->Bound = TRUE;
|
||||
Open->DumpFileName.Buffer = NULL;
|
||||
Open->DumpFileHandle = NULL;
|
||||
Open->tme.active = TME_NONE_ACTIVE;
|
||||
Open->DumpLimitReached = FALSE;
|
||||
|
||||
//allocate the spinlock for the statistic counters
|
||||
NdisAllocateSpinLock(&Open->CountersLock);
|
||||
|
@ -242,20 +243,19 @@ PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
||||
IoMarkIrpPending(Irp);
|
||||
|
||||
|
||||
//
|
||||
// Try to open the MAC
|
||||
//
|
||||
IF_LOUD(DbgPrint("Packet: Openinig the device %ws, BindingContext=%d\n",DeviceExtension->AdapterName.Buffer, Open);)
|
||||
IF_LOUD(DbgPrint("NPF: Openinig the device %ws, BindingContext=%d\n",DeviceExtension->AdapterName.Buffer, Open);)
|
||||
|
||||
NdisOpenAdapter(
|
||||
&Status,
|
||||
&ErrorStatus,
|
||||
&Open->AdapterHandle,
|
||||
&Medium,
|
||||
&Open->Medium,
|
||||
MediumArray,
|
||||
NUM_NDIS_MEDIA,
|
||||
DeviceExtension->NdisProtocolHandle,
|
||||
|
@ -264,11 +264,11 @@ PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
|||
0,
|
||||
NULL);
|
||||
|
||||
IF_LOUD(DbgPrint("Packet: Opened the device, Status=%x\n",Status);)
|
||||
IF_LOUD(DbgPrint("NPF: Opened the device, Status=%x\n",Status);)
|
||||
|
||||
if (Status != NDIS_STATUS_PENDING)
|
||||
{
|
||||
PacketOpenAdapterComplete(Open,Status,NDIS_STATUS_SUCCESS);
|
||||
NPF_OpenAdapterComplete(Open,Status,NDIS_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
return(STATUS_PENDING);
|
||||
|
@ -276,7 +276,7 @@ PacketOpen(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
|
|||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
VOID PacketOpenAdapterComplete(
|
||||
VOID NPF_OpenAdapterComplete(
|
||||
IN NDIS_HANDLE ProtocolBindingContext,
|
||||
IN NDIS_STATUS Status,
|
||||
IN NDIS_STATUS OpenErrorStatus)
|
||||
|
@ -285,7 +285,7 @@ VOID PacketOpenAdapterComplete(
|
|||
PIRP Irp;
|
||||
POPEN_INSTANCE Open;
|
||||
|
||||
IF_LOUD(DbgPrint("Packet: OpenAdapterComplete\n");)
|
||||
IF_LOUD(DbgPrint("NPF: OpenAdapterComplete\n");)
|
||||
|
||||
Open= (POPEN_INSTANCE)ProtocolBindingContext;
|
||||
|
||||
|
@ -296,14 +296,29 @@ VOID PacketOpenAdapterComplete(
|
|||
|
||||
if (Status != NDIS_STATUS_SUCCESS) {
|
||||
|
||||
IF_LOUD(DbgPrint("Packet: OpenAdapterComplete-FAILURE\n");)
|
||||
IF_LOUD(DbgPrint("NPF: OpenAdapterComplete-FAILURE\n");)
|
||||
|
||||
NdisFreePacketPool(Open->PacketPool);
|
||||
|
||||
//free mem_ex
|
||||
Open->mem_ex.size = 0;
|
||||
if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer);
|
||||
|
||||
ExFreePool(Open->ReadEventName.Buffer);
|
||||
|
||||
ExFreePool(Open);
|
||||
}
|
||||
else {
|
||||
NdisAcquireSpinLock(&Opened_Instances_Lock);
|
||||
n_Opened_Instances++;
|
||||
NdisReleaseSpinLock(&Opened_Instances_Lock);
|
||||
|
||||
IF_LOUD(DbgPrint("Opened Instances:%d", n_Opened_Instances);)
|
||||
|
||||
// Get the absolute value of the system boot time.
|
||||
// This is used for timestamp conversion.
|
||||
TIME_SYNCHRONIZE(&G_Start_Time);
|
||||
}
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = 0;
|
||||
|
@ -315,34 +330,50 @@ VOID PacketOpenAdapterComplete(
|
|||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
NTSTATUS STDCALL
|
||||
PacketClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
|
||||
NTSTATUS
|
||||
NPF_Close(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
|
||||
{
|
||||
|
||||
POPEN_INSTANCE Open;
|
||||
NDIS_STATUS Status;
|
||||
PIO_STACK_LOCATION IrpSp;
|
||||
LARGE_INTEGER ThreadDelay;
|
||||
|
||||
|
||||
IF_LOUD(DbgPrint("Packet: CloseAdapter\n");)
|
||||
IF_LOUD(DbgPrint("NPF: CloseAdapter\n");)
|
||||
|
||||
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
Open=IrpSp->FileObject->FsContext;
|
||||
|
||||
// Reset the buffer size. This tells the dump thread to stop.
|
||||
Open->BufSize = 0;
|
||||
|
||||
if( Open->Bound == FALSE){
|
||||
|
||||
NdisWaitEvent(&Open->IOEvent,10000);
|
||||
|
||||
//free the bpf program
|
||||
if(Open->bpfprogram!=NULL)ExFreePool(Open->bpfprogram);
|
||||
|
||||
// Free the filter if it's present
|
||||
if(Open->bpfprogram != NULL)
|
||||
ExFreePool(Open->bpfprogram);
|
||||
|
||||
// Free the jitted filter if it's present
|
||||
if(Open->Filter != NULL)
|
||||
BPF_Destroy_JIT_Filter(Open->Filter);
|
||||
|
||||
//free the buffer
|
||||
Open->BufSize=0;
|
||||
if(Open->Buffer!=NULL)ExFreePool(Open->Buffer);
|
||||
if(Open->Buffer != NULL)ExFreePool(Open->Buffer);
|
||||
|
||||
NdisFreePacketPool(Open->PacketPool);
|
||||
//free mem_ex
|
||||
Open->mem_ex.size = 0;
|
||||
if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer);
|
||||
|
||||
NdisFreePacketPool(Open->PacketPool);
|
||||
|
||||
// Free the string with the name of the dump file
|
||||
if(Open->DumpFileName.Buffer!=NULL)
|
||||
ExFreePool(Open->DumpFileName.Buffer);
|
||||
|
||||
ExFreePool(Open->ReadEventName.Buffer);
|
||||
ExFreePool(Open);
|
||||
|
||||
|
@ -353,26 +384,50 @@ PacketClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
|
|||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
// Eventually unfreeze PacketRead
|
||||
KeSetEvent(Open->ReadEvent,0,FALSE);
|
||||
// Unfreeze the consumer
|
||||
if(Open->mode & MODE_DUMP)
|
||||
NdisSetEvent(&Open->DumpEvent);
|
||||
else
|
||||
KeSetEvent(Open->ReadEvent,0,FALSE);
|
||||
|
||||
// Save the IRP
|
||||
Open->OpenCloseIrp = Irp;
|
||||
|
||||
IoMarkIrpPending(Irp);
|
||||
|
||||
// If this instance is in dump mode, complete the dump and close the file
|
||||
if((Open->mode & MODE_DUMP) && Open->DumpFileHandle != NULL){
|
||||
#ifndef __GNUC__
|
||||
NTSTATUS wres;
|
||||
|
||||
ThreadDelay.QuadPart = -50000000;
|
||||
// Wait the completion of the thread
|
||||
wres = KeWaitForSingleObject(Open->DumpThreadObject,
|
||||
UserRequest,
|
||||
KernelMode,
|
||||
TRUE,
|
||||
&ThreadDelay);
|
||||
|
||||
ObDereferenceObject(Open->DumpThreadObject);
|
||||
|
||||
|
||||
// Flush and close the dump file
|
||||
NPF_CloseDumpFile(Open);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Destroy the read Event
|
||||
ZwClose(Open->ReadEventHandle);
|
||||
|
||||
// save the IRP
|
||||
Open->OpenCloseIrp=Irp;
|
||||
|
||||
IoMarkIrpPending(Irp);
|
||||
|
||||
// close the adapter
|
||||
// Close the adapter
|
||||
NdisCloseAdapter(
|
||||
&Status,
|
||||
Open->AdapterHandle
|
||||
);
|
||||
|
||||
|
||||
if (Status != NDIS_STATUS_PENDING) {
|
||||
|
||||
PacketCloseAdapterComplete(
|
||||
NPF_CloseAdapterComplete(
|
||||
Open,
|
||||
Status
|
||||
);
|
||||
|
@ -386,29 +441,42 @@ PacketClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
|
|||
//-------------------------------------------------------------------
|
||||
|
||||
VOID
|
||||
PacketCloseAdapterComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status)
|
||||
NPF_CloseAdapterComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status)
|
||||
{
|
||||
POPEN_INSTANCE Open;
|
||||
PIRP Irp;
|
||||
|
||||
IF_LOUD(DbgPrint("Packet: CloseAdapterComplete\n");)
|
||||
IF_LOUD(DbgPrint("NPF: CloseAdapterComplete\n");)
|
||||
|
||||
Open= (POPEN_INSTANCE)ProtocolBindingContext;
|
||||
|
||||
// free the allocated structures only if the instance is still bound to the adapter
|
||||
if(Open->Bound == TRUE){
|
||||
|
||||
//free the bpf program
|
||||
if(Open->bpfprogram!=NULL)ExFreePool(Open->bpfprogram);
|
||||
// Free the filter if it's present
|
||||
if(Open->bpfprogram != NULL)
|
||||
ExFreePool(Open->bpfprogram);
|
||||
|
||||
// Free the jitted filter if it's present
|
||||
if(Open->Filter != NULL)
|
||||
BPF_Destroy_JIT_Filter(Open->Filter);
|
||||
|
||||
//free the buffer
|
||||
Open->BufSize=0;
|
||||
Open->BufSize = 0;
|
||||
if(Open->Buffer!=NULL)ExFreePool(Open->Buffer);
|
||||
|
||||
//free mem_ex
|
||||
Open->mem_ex.size = 0;
|
||||
if(Open->mem_ex.buffer != NULL)ExFreePool(Open->mem_ex.buffer);
|
||||
|
||||
NdisFreePacketPool(Open->PacketPool);
|
||||
|
||||
Irp=Open->OpenCloseIrp;
|
||||
|
||||
// Free the string with the name of the dump file
|
||||
if(Open->DumpFileName.Buffer!=NULL)
|
||||
ExFreePool(Open->DumpFileName.Buffer);
|
||||
|
||||
ExFreePool(Open->ReadEventName.Buffer);
|
||||
ExFreePool(Open);
|
||||
|
||||
|
@ -420,15 +488,42 @@ PacketCloseAdapterComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS
|
|||
else
|
||||
NdisSetEvent(&Open->IOEvent);
|
||||
|
||||
// Decrease the counter of open instances
|
||||
NdisAcquireSpinLock(&Opened_Instances_Lock);
|
||||
n_Opened_Instances--;
|
||||
NdisReleaseSpinLock(&Opened_Instances_Lock);
|
||||
|
||||
IF_LOUD(DbgPrint("Opened Instances:%d", n_Opened_Instances);)
|
||||
|
||||
if(n_Opened_Instances == 0){
|
||||
// Force a synchronization at the next NPF_Open().
|
||||
// This hopefully avoids the synchronization issues caused by hibernation or standby.
|
||||
TIME_DESYNCHRONIZE(&G_Start_Time);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
#ifdef NDIS50
|
||||
NDIS_STATUS
|
||||
NPF_PowerChange(IN NDIS_HANDLE ProtocolBindingContext, IN PNET_PNP_EVENT pNetPnPEvent)
|
||||
{
|
||||
IF_LOUD(DbgPrint("NPF: PowerChange\n");)
|
||||
|
||||
TIME_DESYNCHRONIZE(&G_Start_Time);
|
||||
|
||||
TIME_SYNCHRONIZE(&G_Start_Time);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
VOID
|
||||
PacketBindAdapter(
|
||||
NPF_BindAdapter(
|
||||
OUT PNDIS_STATUS Status,
|
||||
IN NDIS_HANDLE BindContext,
|
||||
IN PNDIS_STRING DeviceName,
|
||||
|
@ -436,13 +531,13 @@ PacketBindAdapter(
|
|||
IN PVOID SystemSpecific2
|
||||
)
|
||||
{
|
||||
IF_LOUD(DbgPrint("Packet: PacketBindAdapter\n");)
|
||||
IF_LOUD(DbgPrint("NPF: NPF_BindAdapter\n");)
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
VOID
|
||||
PacketUnbindAdapter(
|
||||
NPF_UnbindAdapter(
|
||||
OUT PNDIS_STATUS Status,
|
||||
IN NDIS_HANDLE ProtocolBindingContext,
|
||||
IN NDIS_HANDLE UnbindContext
|
||||
|
@ -451,7 +546,10 @@ PacketUnbindAdapter(
|
|||
POPEN_INSTANCE Open =(POPEN_INSTANCE)ProtocolBindingContext;
|
||||
NDIS_STATUS lStatus;
|
||||
|
||||
IF_LOUD(DbgPrint("Packet: PacketUNBindAdapter\n");)
|
||||
IF_LOUD(DbgPrint("NPF: NPF_UnbindAdapter\n");)
|
||||
|
||||
// Reset the buffer size. This tells the dump thread to stop.
|
||||
Open->BufSize=0;
|
||||
|
||||
NdisResetEvent(&Open->IOEvent);
|
||||
|
||||
|
@ -459,7 +557,14 @@ PacketUnbindAdapter(
|
|||
InterlockedExchange( (PLONG) &Open->Bound, FALSE );
|
||||
|
||||
// Awake a possible pending read on this instance
|
||||
KeSetEvent(Open->ReadEvent,0,FALSE);
|
||||
if(Open->mode & MODE_DUMP)
|
||||
NdisSetEvent(&Open->DumpEvent);
|
||||
else
|
||||
KeSetEvent(Open->ReadEvent,0,FALSE);
|
||||
|
||||
// If this instance is in dump mode, complete the dump and close the file
|
||||
if((Open->mode & MODE_DUMP) && Open->DumpFileHandle != NULL)
|
||||
NPF_CloseDumpFile(Open);
|
||||
|
||||
// Destroy the read Event
|
||||
ZwClose(Open->ReadEventHandle);
|
||||
|
@ -472,7 +577,7 @@ PacketUnbindAdapter(
|
|||
|
||||
if (lStatus != NDIS_STATUS_PENDING) {
|
||||
|
||||
PacketCloseAdapterComplete(
|
||||
NPF_CloseAdapterComplete(
|
||||
Open,
|
||||
lStatus
|
||||
);
|
||||
|
@ -489,7 +594,7 @@ PacketUnbindAdapter(
|
|||
//-------------------------------------------------------------------
|
||||
|
||||
VOID
|
||||
PacketResetComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status)
|
||||
NPF_ResetComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Status)
|
||||
|
||||
{
|
||||
POPEN_INSTANCE Open;
|
||||
|
@ -497,7 +602,7 @@ PacketResetComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Statu
|
|||
|
||||
PLIST_ENTRY ResetListEntry;
|
||||
|
||||
IF_LOUD(DbgPrint("Packet: PacketResetComplte\n");)
|
||||
IF_LOUD(DbgPrint("NPF: PacketResetComplte\n");)
|
||||
|
||||
Open= (POPEN_INSTANCE)ProtocolBindingContext;
|
||||
|
||||
|
@ -522,7 +627,7 @@ PacketResetComplete(IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_STATUS Statu
|
|||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
IF_LOUD(DbgPrint("Packet: PacketResetComplte exit\n");)
|
||||
IF_LOUD(DbgPrint("NPF: PacketResetComplte exit\n");)
|
||||
|
||||
return;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -6,8 +6,8 @@
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 2,3,0,33
|
||||
PRODUCTVERSION 2,3,0,33
|
||||
FILEVERSION 3,0,0,13
|
||||
PRODUCTVERSION 3,0,0,13
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -24,16 +24,16 @@ BEGIN
|
|||
BEGIN
|
||||
VALUE "Comments", "Netgroup Packet Filter Driver\0"
|
||||
VALUE "CompanyName", "Politecnico di Torino\0"
|
||||
VALUE "FileDescription", "NPF Driver\0"
|
||||
VALUE "FileVersion", "2, 3, 0, 33\0"
|
||||
VALUE "InternalName", "NPF\0"
|
||||
VALUE "FileDescription", "NPF Driver - TME extensions\0"
|
||||
VALUE "FileVersion", "3, 0, 0, 13\0"
|
||||
VALUE "InternalName", "NPF + TME \0"
|
||||
VALUE "LegalCopyright", "Copyright © 2002\0"
|
||||
VALUE "LegalTrademarks", "\0"
|
||||
VALUE "OriginalFilename", "NPF.RC\0"
|
||||
VALUE "PrivateBuild", "\0"
|
||||
VALUE "PrivateBuild", "REACTOS PRIVATE BUILD\0"
|
||||
VALUE "ProductName", "NPF Driver\0"
|
||||
VALUE "ProductVersion", "2, 3, 0, 33\0"
|
||||
VALUE "SpecialBuild", "\0"
|
||||
VALUE "ProductVersion", "3, 0, 0, 13\0"
|
||||
VALUE "SpecialBuild", "Beta testing use only\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -26,13 +26,17 @@
|
|||
#include <ndis.h>
|
||||
#else
|
||||
#include <ddk/ntddk.h>
|
||||
//#include <net/miniport.h>
|
||||
#include <net/ndis.h>
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
#include "packet.h"
|
||||
#include "win_bpf.h"
|
||||
|
||||
#include "tme.h"
|
||||
#include "time_calls.h"
|
||||
|
||||
extern struct time_conv G_Start_Time; // from openclos.c
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
|
@ -80,11 +84,10 @@ UINT n,i,NBlocks;
|
|||
*Bhead+=n;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
NTSTATUS STDCALL
|
||||
PacketRead(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
|
||||
NTSTATUS
|
||||
NPF_Read(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
|
||||
{
|
||||
POPEN_INSTANCE Open;
|
||||
PIO_STACK_LOCATION IrpSp;
|
||||
|
@ -101,51 +104,57 @@ PacketRead(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
|
|||
LARGE_INTEGER TimeFreq;
|
||||
struct bpf_hdr *header;
|
||||
KIRQL Irql;
|
||||
PUCHAR UserPointer;
|
||||
ULONG bytecopy;
|
||||
|
||||
IF_LOUD(DbgPrint("Packet: Read\n");)
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: Read\n");)
|
||||
|
||||
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
Open=IrpSp->FileObject->FsContext;
|
||||
|
||||
if( Open->Bound == FALSE){
|
||||
// The Network adapter was removed. Return immediately with a failure status
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
|
||||
if( Open->Bound == FALSE ){
|
||||
// The Network adapter was removed.
|
||||
EXIT_FAILURE(0);
|
||||
}
|
||||
|
||||
if( Open->mode & MODE_DUMP && Open->DumpFileHandle == NULL ){
|
||||
// this instance is in dump mode, but the dump file has still not been opened
|
||||
EXIT_FAILURE(0);
|
||||
}
|
||||
|
||||
//See if the buffer is full enough to be copied
|
||||
if (GetBuffOccupation(Open)<=Open->MinToCopy)
|
||||
if( GetBuffOccupation(Open) <= Open->MinToCopy || Open->mode & MODE_DUMP )
|
||||
{
|
||||
//there are not enough buffered packets: the application must wait
|
||||
|
||||
//wait until some packets arrive or the timeout expires
|
||||
if(Open->TimeOut.QuadPart != (LONGLONG)IMMEDIATE)
|
||||
KeWaitForSingleObject(Open->ReadEvent,
|
||||
UserRequest,
|
||||
KernelMode,
|
||||
TRUE ,
|
||||
TRUE,
|
||||
(Open->TimeOut.QuadPart == (LONGLONG)0)? NULL: &(Open->TimeOut));
|
||||
|
||||
KeClearEvent(Open->ReadEvent);
|
||||
|
||||
if(Open->mode==MODE_STAT){ //this capture instance is in statistics mode
|
||||
if(Open->mode & MODE_STAT){ //this capture instance is in statistics mode
|
||||
CurrBuff=(PUCHAR)MmGetSystemAddressForMdl(Irp->MdlAddress);
|
||||
|
||||
//get the timestamp
|
||||
CapTime=KeQueryPerformanceCounter(&TimeFreq);
|
||||
//fill the bpf header for this packet
|
||||
CapTime.QuadPart+=Open->StartTime.QuadPart;
|
||||
header=(struct bpf_hdr*)CurrBuff;
|
||||
#ifndef __NTDRIVER__ // robert
|
||||
header->bh_tstamp.tv_usec=(long)((CapTime.QuadPart%TimeFreq.QuadPart*1000000)/TimeFreq.QuadPart);
|
||||
header->bh_tstamp.tv_sec=(long)(CapTime.QuadPart/TimeFreq.QuadPart);
|
||||
#endif
|
||||
header->bh_caplen=16;
|
||||
header->bh_datalen=16;
|
||||
header->bh_hdrlen=sizeof(struct bpf_hdr);
|
||||
|
||||
GET_TIME(&header->bh_tstamp,&G_Start_Time);
|
||||
|
||||
if(Open->mode & MODE_DUMP){
|
||||
*(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr)+16)=Open->DumpOffset.QuadPart;
|
||||
header->bh_caplen=24;
|
||||
header->bh_datalen=24;
|
||||
Irp->IoStatus.Information = 24 + sizeof(struct bpf_hdr);
|
||||
}
|
||||
else{
|
||||
header->bh_caplen=16;
|
||||
header->bh_datalen=16;
|
||||
header->bh_hdrlen=sizeof(struct bpf_hdr);
|
||||
Irp->IoStatus.Information = 16 + sizeof(struct bpf_hdr);
|
||||
}
|
||||
|
||||
*(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr))=Open->Npackets.QuadPart;
|
||||
*(LONGLONG*)(CurrBuff+sizeof(struct bpf_hdr)+8)=Open->Nbytes.QuadPart;
|
||||
|
||||
|
@ -155,21 +164,78 @@ PacketRead(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
|
|||
Open->Nbytes.QuadPart=0;
|
||||
NdisReleaseSpinLock( &Open->CountersLock );
|
||||
|
||||
Irp->IoStatus.Information = 16 + sizeof(struct bpf_hdr);
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (Open->Bhead == Open->Btail)
|
||||
//the timeout has expired, but the buffer is still empty.
|
||||
//we must awake the application returning an empty buffer.
|
||||
if(Open->mode==MODE_MON) //this capture instance is in monitor mode
|
||||
{
|
||||
PTME_DATA data;
|
||||
ULONG cnt;
|
||||
ULONG block_size;
|
||||
PUCHAR tmp;
|
||||
|
||||
UserPointer=MmGetSystemAddressForMdl(Irp->MdlAddress);
|
||||
|
||||
if ((!IS_VALIDATED(Open->tme.validated_blocks,Open->tme.active_read))||(IrpSp->Parameters.Read.Length<sizeof(struct bpf_hdr)))
|
||||
{
|
||||
EXIT_FAILURE(0);
|
||||
}
|
||||
|
||||
header=(struct bpf_hdr*)UserPointer;
|
||||
|
||||
GET_TIME(&header->bh_tstamp,&G_Start_Time);
|
||||
|
||||
|
||||
header->bh_hdrlen=sizeof(struct bpf_hdr);
|
||||
|
||||
|
||||
//moves user memory pointer
|
||||
UserPointer+=sizeof(struct bpf_hdr);
|
||||
|
||||
//calculus of data to be copied
|
||||
//if the user buffer is smaller than data to be copied,
|
||||
//only some data will be copied
|
||||
data=&Open->tme.block_data[Open->tme.active_read];
|
||||
|
||||
if (data->last_read.tv_sec!=0)
|
||||
data->last_read=header->bh_tstamp;
|
||||
|
||||
|
||||
bytecopy=data->block_size*data->filled_blocks;
|
||||
|
||||
if ((IrpSp->Parameters.Read.Length-sizeof(struct bpf_hdr))<bytecopy)
|
||||
bytecopy=(IrpSp->Parameters.Read.Length-sizeof(struct bpf_hdr))/ data->block_size;
|
||||
else
|
||||
bytecopy=data->filled_blocks;
|
||||
|
||||
tmp=data->shared_memory_base_address;
|
||||
block_size=data->block_size;
|
||||
|
||||
for (cnt=0;cnt<bytecopy;cnt++)
|
||||
{
|
||||
NdisAcquireSpinLock(&Open->machine_lock);
|
||||
RtlCopyMemory(UserPointer,tmp,block_size);
|
||||
NdisReleaseSpinLock(&Open->machine_lock);
|
||||
tmp+=block_size;
|
||||
UserPointer+=block_size;
|
||||
}
|
||||
|
||||
bytecopy*=block_size;
|
||||
|
||||
header->bh_caplen=bytecopy;
|
||||
header->bh_datalen=header->bh_caplen;
|
||||
|
||||
EXIT_SUCCESS(bytecopy+sizeof(struct bpf_hdr));
|
||||
}
|
||||
|
||||
if (Open->Bhead == Open->Btail || Open->mode & MODE_DUMP)
|
||||
// The timeout has expired, but the buffer is still empty (or the packets must be written to file).
|
||||
// We must awake the application, returning an empty buffer.
|
||||
{
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return(STATUS_SUCCESS);
|
||||
EXIT_SUCCESS(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -179,66 +245,61 @@ PacketRead(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
|
|||
//
|
||||
NdisAcquireSpinLock( &Open->BufLock );
|
||||
|
||||
Thead=Open->Bhead;
|
||||
Ttail=Open->Btail;
|
||||
TLastByte=Open->BLastByte;
|
||||
|
||||
Thead = Open->Bhead;
|
||||
Ttail = Open->Btail;
|
||||
TLastByte = Open->BLastByte;
|
||||
|
||||
//get the address of the buffer
|
||||
CurrBuff=Open->Buffer;
|
||||
|
||||
|
||||
NdisReleaseSpinLock( &Open->BufLock );
|
||||
|
||||
Input_Buffer_Length=IrpSp->Parameters.Read.Length;
|
||||
packp=(PUCHAR)MmGetMdlVirtualAddress(Irp->MdlAddress);
|
||||
|
||||
|
||||
|
||||
//
|
||||
//fill the application buffer
|
||||
//
|
||||
if(Ttail>Thead){ //first of all see if it we can copy all the buffer in one time
|
||||
if(Ttail > Thead){ //first of all see if it we can copy all the buffer in one time
|
||||
if((Ttail-Thead)<Input_Buffer_Length){
|
||||
KeResetEvent(Open->ReadEvent);
|
||||
|
||||
PacketMoveMem(packp,CurrBuff+Thead,Ttail-Thead,&(Open->Bhead));
|
||||
Irp->IoStatus.Information = Ttail-Thead;
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return(STATUS_SUCCESS);
|
||||
EXIT_SUCCESS(Ttail-Thead);
|
||||
}
|
||||
}
|
||||
else if((TLastByte-Thead)<Input_Buffer_Length){
|
||||
PacketMoveMem(packp,CurrBuff+Thead,TLastByte-Thead,&(Open->Bhead));
|
||||
else if((TLastByte - Thead) < Input_Buffer_Length){
|
||||
PacketMoveMem(packp, CurrBuff+Thead, TLastByte - Thead, &(Open->Bhead));
|
||||
|
||||
NdisAcquireSpinLock( &Open->BufLock );
|
||||
|
||||
Open->BLastByte=Open->Btail;
|
||||
Open->Bhead=0;
|
||||
Open->BLastByte = Open->Btail;
|
||||
Open->Bhead = 0;
|
||||
|
||||
NdisReleaseSpinLock( &Open->BufLock );
|
||||
|
||||
Irp->IoStatus.Information = TLastByte-Thead;
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return(STATUS_SUCCESS);
|
||||
EXIT_SUCCESS(TLastByte-Thead);
|
||||
}
|
||||
|
||||
//the buffer must be scannned to determine the number of bytes to copy
|
||||
i=0;
|
||||
CpStart=Thead;
|
||||
i=0;
|
||||
while(TRUE){
|
||||
if(Thead==Ttail)break;
|
||||
if(Thead == Ttail)break;
|
||||
|
||||
if(Thead==TLastByte){
|
||||
if(Thead == TLastByte){
|
||||
// Copy the portion between thead and TLastByte
|
||||
PacketMoveMem(packp,CurrBuff+CpStart,Thead-CpStart,&(Open->Bhead));
|
||||
packp+=(Thead-CpStart);
|
||||
|
||||
NdisAcquireSpinLock( &Open->BufLock );
|
||||
|
||||
Open->BLastByte=Open->Btail;
|
||||
Open->Bhead=0;
|
||||
Open->BLastByte = Open->Btail;
|
||||
Open->Bhead = 0;
|
||||
|
||||
NdisReleaseSpinLock( &Open->BufLock );
|
||||
|
||||
|
||||
Thead=0;
|
||||
CpStart=0;
|
||||
}
|
||||
|
@ -247,11 +308,7 @@ PacketRead(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
|
|||
if((i+cplen > Input_Buffer_Length)){//no more space in the application's buffer
|
||||
PacketMoveMem(packp,CurrBuff+CpStart,Thead-CpStart,&(Open->Bhead));
|
||||
|
||||
Irp->IoStatus.Information = i;
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
EXIT_SUCCESS(i);
|
||||
}
|
||||
cplen=Packet_WORDALIGN(cplen);
|
||||
i+=cplen;
|
||||
|
@ -265,17 +322,13 @@ PacketRead(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
|
|||
|
||||
Open->Bhead=Thead;
|
||||
|
||||
Irp->IoStatus.Information = i;
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
|
||||
EXIT_SUCCESS(i);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
NDIS_STATUS Packet_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE MacReceiveContext,
|
||||
NDIS_STATUS NPF_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE MacReceiveContext,
|
||||
IN PVOID HeaderBuffer,IN UINT HeaderBufferSize,IN PVOID LookAheadBuffer,
|
||||
IN UINT LookaheadBufferSize,IN UINT PacketSize)
|
||||
{
|
||||
|
@ -285,7 +338,6 @@ NDIS_STATUS Packet_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE Mac
|
|||
NDIS_STATUS Status;
|
||||
UINT BytesTransfered;
|
||||
ULONG BufferLength;
|
||||
PPACKET_RESERVED Reserved;
|
||||
PMDL pMdl;
|
||||
LARGE_INTEGER CapTime;
|
||||
LARGE_INTEGER TimeFreq;
|
||||
|
@ -296,13 +348,26 @@ NDIS_STATUS Packet_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE Mac
|
|||
UINT TLastByte;
|
||||
UINT fres;
|
||||
UINT maxbufspace;
|
||||
USHORT NPFHdrSize;
|
||||
UINT BufOccupation;
|
||||
|
||||
IF_LOUD(DbgPrint("Packet: tap\n");)
|
||||
IF_VERY_LOUD(DbgPrint("NPF: tap\n");)
|
||||
|
||||
Open= (POPEN_INSTANCE)ProtocolBindingContext;
|
||||
|
||||
Open->Received++; //number of packets received by filter ++
|
||||
Open->Received++; // Number of packets received by filter ++
|
||||
|
||||
BufOccupation = GetBuffOccupation(Open); // Get the full buffer space
|
||||
|
||||
if(((Open->mode&MODE_CAPT)||(Open->mode&MODE_DUMP)) && Open->BufSize - BufOccupation < PacketSize+HeaderBufferSize+sizeof(struct bpf_hdr)){
|
||||
// Heuristic that drops the packet also if it possibly fits in the buffer.
|
||||
// It allows to avoid filtering in critical situations when CPU is very important.
|
||||
Open->Dropped++;
|
||||
return NDIS_STATUS_NOT_ACCEPTED;
|
||||
}
|
||||
|
||||
NdisAcquireSpinLock(&Open->machine_lock);
|
||||
|
||||
//
|
||||
//Check if the lookahead buffer follows the mac header.
|
||||
//If the data follow the header (i.e. there is only a buffer) a normal bpf_filter() is
|
||||
|
@ -316,24 +381,64 @@ NDIS_STATUS Packet_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE Mac
|
|||
LookAheadBuffer,
|
||||
HeaderBufferSize,
|
||||
PacketSize+HeaderBufferSize,
|
||||
LookaheadBufferSize+HeaderBufferSize);
|
||||
else
|
||||
fres=bpf_filter((struct bpf_insn*)(Open->bpfprogram),
|
||||
HeaderBuffer,
|
||||
PacketSize+HeaderBufferSize,
|
||||
LookaheadBufferSize+HeaderBufferSize);
|
||||
LookaheadBufferSize+HeaderBufferSize,
|
||||
&Open->mem_ex,
|
||||
&Open->tme,
|
||||
&G_Start_Time);
|
||||
|
||||
|
||||
else
|
||||
if(Open->Filter != NULL)
|
||||
{
|
||||
if (Open->bpfprogram != NULL)
|
||||
{
|
||||
fres=Open->Filter->Function(HeaderBuffer,
|
||||
PacketSize+HeaderBufferSize,
|
||||
LookaheadBufferSize+HeaderBufferSize);
|
||||
|
||||
// Restore the stack.
|
||||
// I ignore the reason, but this instruction is needed only at kernel level
|
||||
#ifndef __GNUC__
|
||||
_asm add esp,12
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
else
|
||||
fres = -1;
|
||||
}
|
||||
else
|
||||
fres=bpf_filter((struct bpf_insn*)(Open->bpfprogram),
|
||||
HeaderBuffer,
|
||||
PacketSize+HeaderBufferSize,
|
||||
LookaheadBufferSize+HeaderBufferSize,
|
||||
&Open->mem_ex,
|
||||
&Open->tme,
|
||||
&G_Start_Time);
|
||||
|
||||
NdisReleaseSpinLock(&Open->machine_lock);
|
||||
|
||||
if(Open->mode==MODE_MON)
|
||||
// we are in monitor mode
|
||||
{
|
||||
if (fres==1)
|
||||
KeSetEvent(Open->ReadEvent,0,FALSE);
|
||||
return NDIS_STATUS_NOT_ACCEPTED;
|
||||
|
||||
}
|
||||
|
||||
if(fres==0)
|
||||
// Packet not accepted by the filter, ignore it.
|
||||
return NDIS_STATUS_NOT_ACCEPTED;
|
||||
|
||||
if(fres==0)return NDIS_STATUS_NOT_ACCEPTED; //packet not accepted by the filter
|
||||
//if the filter returns -1 the whole packet must be accepted
|
||||
if(fres==-1 || fres > PacketSize+HeaderBufferSize)fres=PacketSize+HeaderBufferSize;
|
||||
|
||||
|
||||
if(Open->mode==MODE_STAT){
|
||||
if(Open->mode & MODE_STAT){
|
||||
// we are in statistics mode
|
||||
NdisAcquireSpinLock( &Open->CountersLock );
|
||||
|
||||
Open->Npackets.QuadPart++;
|
||||
|
||||
|
||||
if(PacketSize+HeaderBufferSize<60)
|
||||
Open->Nbytes.QuadPart+=60;
|
||||
else
|
||||
|
@ -343,32 +448,42 @@ NDIS_STATUS Packet_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE Mac
|
|||
Open->Nbytes.QuadPart+=12;
|
||||
|
||||
NdisReleaseSpinLock( &Open->CountersLock );
|
||||
|
||||
if(!(Open->mode & MODE_DUMP)){
|
||||
return NDIS_STATUS_NOT_ACCEPTED;
|
||||
}
|
||||
}
|
||||
|
||||
if(Open->BufSize==0)return NDIS_STATUS_NOT_ACCEPTED;
|
||||
|
||||
if(Open->mode & MODE_DUMP && Open->MaxDumpPacks && (UINT)Open->Accepted > Open->MaxDumpPacks){
|
||||
// Reached the max number of packets to save in the dump file. Discard the packet and stop the dump thread.
|
||||
Open->DumpLimitReached = TRUE; // This stops the thread
|
||||
// Awake the dump thread
|
||||
NdisSetEvent(&Open->DumpEvent);
|
||||
|
||||
// Awake the application
|
||||
KeSetEvent(Open->ReadEvent,0,FALSE);
|
||||
|
||||
return NDIS_STATUS_NOT_ACCEPTED;
|
||||
}
|
||||
|
||||
if(Open->BufSize==0)return NDIS_STATUS_NOT_ACCEPTED;
|
||||
|
||||
// Calculate the correct size for the header associated with the packet
|
||||
NPFHdrSize=(Open->mode==MODE_CAPT)? sizeof(struct bpf_hdr): sizeof(struct sf_pkthdr);
|
||||
|
||||
NdisAcquireSpinLock( &Open->BufLock );
|
||||
|
||||
Thead=Open->Bhead;
|
||||
Ttail=Open->Btail;
|
||||
TLastByte=Open->BLastByte;
|
||||
TLastByte = Open->BLastByte;
|
||||
|
||||
NdisReleaseSpinLock( &Open->BufLock );
|
||||
|
||||
maxbufspace=Packet_WORDALIGN(fres+sizeof(struct bpf_hdr));
|
||||
|
||||
if((Ttail < Thead) && (Ttail+maxbufspace+1 >= Thead))
|
||||
{
|
||||
//the buffer is full: the incoming packet is lost
|
||||
Open->Dropped++;
|
||||
return NDIS_STATUS_NOT_ACCEPTED;
|
||||
}
|
||||
|
||||
maxbufspace=Packet_WORDALIGN(fres+NPFHdrSize);
|
||||
|
||||
if(Ttail+maxbufspace >= Open->BufSize){
|
||||
if(Thead<=maxbufspace)
|
||||
if(Thead <= maxbufspace)
|
||||
{
|
||||
//the buffer is full: the packet is lost
|
||||
Open->Dropped++;
|
||||
return NDIS_STATUS_NOT_ACCEPTED;
|
||||
}
|
||||
|
@ -378,97 +493,135 @@ NDIS_STATUS Packet_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE Mac
|
|||
}
|
||||
|
||||
CurrBuff=Open->Buffer+Ttail;
|
||||
|
||||
// Allocate an MDL to map the portion of the buffer following the
|
||||
// header
|
||||
pMdl=IoAllocateMdl(CurrBuff+HeaderBufferSize+LookaheadBufferSize+sizeof(struct bpf_hdr),maxbufspace,FALSE,FALSE,NULL);
|
||||
if (pMdl == NULL)
|
||||
|
||||
if(LookaheadBufferSize != PacketSize || (UINT)LookAheadBuffer-(UINT)HeaderBuffer != HeaderBufferSize)
|
||||
{
|
||||
//no memory: packet lost
|
||||
IF_LOUD(DbgPrint("Packet: Read-Failed to allocate Mdl\n");)
|
||||
Open->Dropped++;
|
||||
return NDIS_STATUS_NOT_ACCEPTED;
|
||||
}
|
||||
MmBuildMdlForNonPagedPool(pMdl);
|
||||
|
||||
//allocate the packet from NDIS
|
||||
NdisAllocatePacket(&Status,&pPacketb,Open->PacketPool);
|
||||
if (Status != NDIS_STATUS_SUCCESS)
|
||||
{
|
||||
IF_LOUD(DbgPrint("Packet: Read- No free packets\n");)
|
||||
// Allocate an MDL to map the portion of the buffer following the header
|
||||
pMdl=IoAllocateMdl(CurrBuff+HeaderBufferSize+LookaheadBufferSize+NPFHdrSize,
|
||||
maxbufspace,
|
||||
FALSE,
|
||||
FALSE,
|
||||
NULL);
|
||||
|
||||
if (pMdl == NULL)
|
||||
{
|
||||
// Unable to map the memory: packet lost
|
||||
IF_LOUD(DbgPrint("NPF: Read-Failed to allocate Mdl\n");)
|
||||
Open->Dropped++;
|
||||
return NDIS_STATUS_NOT_ACCEPTED;
|
||||
}
|
||||
MmBuildMdlForNonPagedPool(pMdl);
|
||||
|
||||
//allocate the packet from NDIS
|
||||
NdisAllocatePacket(&Status, &pPacketb, Open->PacketPool);
|
||||
if (Status != NDIS_STATUS_SUCCESS)
|
||||
{
|
||||
IF_LOUD(DbgPrint("NPF: Tap - No free packets\n");)
|
||||
IoFreeMdl(pMdl);
|
||||
Open->Dropped++;
|
||||
return NDIS_STATUS_NOT_ACCEPTED;
|
||||
}
|
||||
//link the buffer to the packet
|
||||
NdisChainBufferAtFront(pPacketb,pMdl);
|
||||
Open->Dropped++;
|
||||
return NDIS_STATUS_NOT_ACCEPTED;
|
||||
}
|
||||
//link the buffer to the packet
|
||||
NdisChainBufferAtFront(pPacketb,pMdl);
|
||||
|
||||
//Find out how much to transfer
|
||||
SizeToTransfer = fres-HeaderBufferSize;
|
||||
|
||||
//copy the ethernet header into buffer
|
||||
NdisMoveMappedMemory((CurrBuff)+sizeof(struct bpf_hdr),HeaderBuffer,HeaderBufferSize);
|
||||
|
||||
//Copy the look ahead buffer
|
||||
if(LookaheadBufferSize)
|
||||
{
|
||||
NdisMoveMappedMemory((CurrBuff)+sizeof(struct bpf_hdr) + HeaderBufferSize,
|
||||
LookAheadBuffer,
|
||||
(SizeToTransfer < LookaheadBufferSize)? SizeToTransfer : LookaheadBufferSize );
|
||||
BufferLength=fres-HeaderBufferSize;
|
||||
//Find out how much to transfer
|
||||
SizeToTransfer = (PacketSize < BufferLength) ? PacketSize : BufferLength;
|
||||
|
||||
//copy the ethernet header into buffer
|
||||
NdisMoveMappedMemory((CurrBuff)+NPFHdrSize,HeaderBuffer,HeaderBufferSize);
|
||||
|
||||
//Copy the look ahead buffer
|
||||
if(LookaheadBufferSize)
|
||||
{
|
||||
NdisMoveMappedMemory((CurrBuff) + NPFHdrSize + HeaderBufferSize,
|
||||
LookAheadBuffer,
|
||||
(SizeToTransfer < LookaheadBufferSize)? SizeToTransfer : LookaheadBufferSize );
|
||||
|
||||
SizeToTransfer = (SizeToTransfer > LookaheadBufferSize)?
|
||||
SizeToTransfer - LookaheadBufferSize : 0;
|
||||
}
|
||||
|
||||
Open->TransferMdl=pMdl;
|
||||
|
||||
if(SizeToTransfer)
|
||||
{
|
||||
//Call the Mac to transfer the packet
|
||||
NdisTransferData(&Status,
|
||||
Open->AdapterHandle,
|
||||
MacReceiveContext,
|
||||
LookaheadBufferSize,
|
||||
SizeToTransfer,
|
||||
pPacketb,
|
||||
&BytesTransfered);
|
||||
}
|
||||
else{
|
||||
BytesTransfered = 0;
|
||||
}
|
||||
|
||||
SizeToTransfer = (SizeToTransfer > LookaheadBufferSize)?
|
||||
SizeToTransfer - LookaheadBufferSize : 0;
|
||||
}
|
||||
|
||||
Open->TransferMdl=pMdl;
|
||||
|
||||
if(SizeToTransfer)
|
||||
else
|
||||
{
|
||||
//Call the Mac to transfer the packet
|
||||
NdisTransferData(&Status,
|
||||
Open->AdapterHandle,
|
||||
MacReceiveContext,
|
||||
LookaheadBufferSize,
|
||||
SizeToTransfer,
|
||||
pPacketb,
|
||||
&BytesTransfered);
|
||||
}
|
||||
else{
|
||||
BytesTransfered = 0;
|
||||
// The whole packet is in the lookahead buffer, we can avoid the call to NdisTransferData.
|
||||
// This allows us to avoid the allocation of the MDL and the NDIS packet as well
|
||||
RtlCopyMemory((CurrBuff) + NPFHdrSize,
|
||||
HeaderBuffer,
|
||||
HeaderBufferSize + LookaheadBufferSize);
|
||||
|
||||
Open->TransferMdl = NULL;
|
||||
Status = NDIS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
Open->Accepted++; // Increase the accepted packets counter
|
||||
|
||||
if (Status != NDIS_STATUS_FAILURE)
|
||||
{
|
||||
//store the capture time
|
||||
CapTime=KeQueryPerformanceCounter(&TimeFreq);
|
||||
|
||||
if( fres > (BytesTransfered+HeaderBufferSize+LookaheadBufferSize) )
|
||||
fres = BytesTransfered+HeaderBufferSize+LookaheadBufferSize;
|
||||
|
||||
//fill the bpf header for this packet
|
||||
CapTime.QuadPart+=Open->StartTime.QuadPart;
|
||||
|
||||
//
|
||||
// Build the header
|
||||
//
|
||||
header=(struct bpf_hdr*)CurrBuff;
|
||||
#ifndef __NTDRIVER__ // robert
|
||||
header->bh_tstamp.tv_usec=(long)((CapTime.QuadPart%TimeFreq.QuadPart*1000000)/TimeFreq.QuadPart);
|
||||
header->bh_tstamp.tv_sec=(long)(CapTime.QuadPart/TimeFreq.QuadPart);
|
||||
#endif
|
||||
header->bh_caplen=fres;
|
||||
GET_TIME(&header->bh_tstamp,&G_Start_Time);
|
||||
header->bh_caplen=fres;
|
||||
header->bh_datalen=PacketSize+HeaderBufferSize;
|
||||
header->bh_hdrlen=sizeof(struct bpf_hdr);
|
||||
if(Open->mode==MODE_CAPT){
|
||||
header->bh_hdrlen=NPFHdrSize;
|
||||
// Don't align if the packet goes to disk
|
||||
Ttail+=Packet_WORDALIGN(fres + NPFHdrSize);
|
||||
}
|
||||
else
|
||||
Ttail+=fres+NPFHdrSize;
|
||||
|
||||
//update the buffer
|
||||
Ttail+=Packet_WORDALIGN(fres+sizeof(struct bpf_hdr));
|
||||
|
||||
if(Ttail>Thead)TLastByte=Ttail;
|
||||
if(Ttail > Thead)TLastByte = Ttail;
|
||||
|
||||
NdisAcquireSpinLock( &Open->BufLock );
|
||||
|
||||
Open->Btail=Ttail;
|
||||
Open->BLastByte=TLastByte;
|
||||
|
||||
NdisReleaseSpinLock( &Open->BufLock );
|
||||
|
||||
}
|
||||
|
||||
if (Status != NDIS_STATUS_PENDING){
|
||||
PacketTransferDataComplete(Open,pPacketb,Status,fres);
|
||||
|
||||
if( Open->TransferMdl != NULL)
|
||||
// Complete the request and free the buffers
|
||||
NPF_TransferDataComplete(Open,pPacketb,Status,fres);
|
||||
else{
|
||||
// Unfreeze the consumer
|
||||
if(GetBuffOccupation(Open)>Open->MinToCopy){
|
||||
if(Open->mode & MODE_DUMP){
|
||||
NdisSetEvent(&Open->DumpEvent);
|
||||
}
|
||||
else
|
||||
KeSetEvent(Open->ReadEvent,0,FALSE);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return NDIS_STATUS_SUCCESS;
|
||||
|
@ -477,12 +630,12 @@ NDIS_STATUS Packet_tap (IN NDIS_HANDLE ProtocolBindingContext,IN NDIS_HANDLE Mac
|
|||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
VOID PacketTransferDataComplete (IN NDIS_HANDLE ProtocolBindingContext,IN PNDIS_PACKET pPacket,
|
||||
VOID NPF_TransferDataComplete (IN NDIS_HANDLE ProtocolBindingContext,IN PNDIS_PACKET pPacket,
|
||||
IN NDIS_STATUS Status,IN UINT BytesTransfered)
|
||||
{
|
||||
POPEN_INSTANCE Open;
|
||||
|
||||
IF_LOUD(DbgPrint("Packet: TransferDataComplete\n");)
|
||||
IF_LOUD(DbgPrint("NPF: TransferDataComplete\n");)
|
||||
|
||||
Open= (POPEN_INSTANCE)ProtocolBindingContext;
|
||||
|
||||
|
@ -491,18 +644,21 @@ VOID PacketTransferDataComplete (IN NDIS_HANDLE ProtocolBindingContext,IN PNDIS_
|
|||
NdisReinitializePacket(pPacket);
|
||||
//Put the packet on the free queue
|
||||
NdisFreePacket(pPacket);
|
||||
//Unfreeze PacketRead
|
||||
if(GetBuffOccupation(Open)>Open->MinToCopy)
|
||||
KeSetEvent(Open->ReadEvent,0,FALSE);
|
||||
|
||||
// Unfreeze the consumer
|
||||
if(GetBuffOccupation(Open)>Open->MinToCopy){
|
||||
if(Open->mode & MODE_DUMP){
|
||||
NdisSetEvent(&Open->DumpEvent);
|
||||
}
|
||||
else
|
||||
KeSetEvent(Open->ReadEvent,0,FALSE);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
VOID PacketReceiveComplete(IN NDIS_HANDLE ProtocolBindingContext)
|
||||
VOID NPF_ReceiveComplete(IN NDIS_HANDLE ProtocolBindingContext)
|
||||
{
|
||||
IF_LOUD(DbgPrint("Packet: PacketReceiveComplete\n");)
|
||||
IF_VERY_LOUD(DbgPrint("NPF: NPF_ReceiveComplete\n");)
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
15
reactos/drivers/net/packet/resource.h
Normal file
15
reactos/drivers/net/packet/resource.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Developer Studio generated include file.
|
||||
// Used by NPF.RC
|
||||
//
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 101
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1000
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
283
reactos/drivers/net/packet/tcp_session.c
Normal file
283
reactos/drivers/net/packet/tcp_session.c
Normal file
|
@ -0,0 +1,283 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#include "tme.h"
|
||||
#include "tcp_session.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <net/tme/tme.h>
|
||||
#include <net/tme/tcp_session.h>
|
||||
#else
|
||||
#include <tme/tme.h>
|
||||
#include <tme/tcp_session.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
uint32 tcp_session(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data)
|
||||
|
||||
{
|
||||
|
||||
uint32 next_status;
|
||||
uint32 direction=ULONG_AT(mem_data,12);
|
||||
uint8 flags=mem_ex->buffer[25];
|
||||
tcp_data *session=(tcp_data*)(block+data->key_len*4);
|
||||
|
||||
session->last_timestamp=session->timestamp_block;
|
||||
session->timestamp_block.tv_sec=0x7fffffff;
|
||||
|
||||
if (direction==session->direction)
|
||||
{
|
||||
session->pkts_cln_to_srv++;
|
||||
session->bytes_cln_to_srv+=pkt_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
session->pkts_srv_to_cln++;
|
||||
session->bytes_srv_to_cln+=pkt_size;
|
||||
}
|
||||
/* we use only thes four flags, we don't need PSH or URG */
|
||||
flags&=(ACK|FIN|SYN|RST);
|
||||
|
||||
switch (session->status)
|
||||
{
|
||||
case ERROR_TCP:
|
||||
next_status=ERROR_TCP;
|
||||
break;
|
||||
|
||||
case UNKNOWN:
|
||||
if (flags==SYN)
|
||||
{
|
||||
if (SW_ULONG_AT(mem_ex->buffer,20)!=0)
|
||||
{
|
||||
|
||||
next_status=ERROR_TCP;
|
||||
break;
|
||||
}
|
||||
next_status=SYN_RCV;
|
||||
session->syn_timestamp=session->last_timestamp;
|
||||
|
||||
session->direction=direction;
|
||||
session->seq_n_0_cln=SW_ULONG_AT(mem_ex->buffer,16);
|
||||
}
|
||||
else
|
||||
next_status=UNKNOWN;
|
||||
break;
|
||||
|
||||
case SYN_RCV:
|
||||
if ((flags&RST)&&(direction!=session->direction))
|
||||
{
|
||||
next_status=CLOSED_RST;
|
||||
break;
|
||||
}
|
||||
if ((flags==SYN)&&(direction==session->direction))
|
||||
{ /* two syns... */
|
||||
next_status=SYN_RCV;
|
||||
session->seq_n_0_cln=SW_ULONG_AT(mem_ex->buffer,16);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((flags==(SYN|ACK))&&(direction!=session->direction))
|
||||
{
|
||||
if (SW_ULONG_AT(mem_ex->buffer,20)!=session->seq_n_0_cln+1)
|
||||
{
|
||||
next_status=ERROR_TCP;
|
||||
break;
|
||||
}
|
||||
next_status=SYN_ACK_RCV;
|
||||
|
||||
session->syn_ack_timestamp=session->last_timestamp;
|
||||
|
||||
session->seq_n_0_srv=SW_ULONG_AT(mem_ex->buffer,16);
|
||||
session->ack_cln=session->seq_n_0_cln+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
next_status=ERROR_TCP;
|
||||
}
|
||||
break;
|
||||
|
||||
case SYN_ACK_RCV:
|
||||
if ((flags&ACK)&&(flags&RST)&&(direction==session->direction))
|
||||
{
|
||||
next_status=CLOSED_RST;
|
||||
session->ack_srv=SW_ULONG_AT(mem_ex->buffer,20);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((flags==ACK)&&(!(flags&(SYN|FIN|RST)))&&(direction==session->direction))
|
||||
{
|
||||
if (SW_ULONG_AT(mem_ex->buffer,20)!=session->seq_n_0_srv+1)
|
||||
{
|
||||
next_status=ERROR_TCP;
|
||||
break;
|
||||
}
|
||||
next_status=ESTABLISHED;
|
||||
session->ack_srv=session->seq_n_0_srv+1;
|
||||
break;
|
||||
}
|
||||
if ((flags&ACK)&&(flags&SYN)&&(direction!=session->direction))
|
||||
{
|
||||
next_status=SYN_ACK_RCV;
|
||||
break;
|
||||
}
|
||||
|
||||
next_status=ERROR_TCP;
|
||||
break;
|
||||
|
||||
case ESTABLISHED:
|
||||
if (flags&SYN)
|
||||
{
|
||||
if ((flags&ACK)&&
|
||||
(direction!=session->direction)&&
|
||||
((session->ack_cln-SW_ULONG_AT(mem_ex->buffer,20))<MAX_WINDOW)
|
||||
)
|
||||
{ /* SYN_ACK duplicato */
|
||||
next_status=ESTABLISHED;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((!(flags&ACK))&&
|
||||
(direction==session->direction)&&
|
||||
(SW_ULONG_AT(mem_ex->buffer,16)==session->seq_n_0_cln)&&
|
||||
(ULONG_AT(mem_ex->buffer,20)==0)
|
||||
)
|
||||
{ /* syn duplicato */
|
||||
next_status=ESTABLISHED;
|
||||
break;
|
||||
}
|
||||
|
||||
next_status=ERROR_TCP;
|
||||
break;
|
||||
}
|
||||
if (flags&ACK)
|
||||
if (direction==session->direction)
|
||||
{
|
||||
uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
|
||||
if (new_ack-session->ack_srv<MAX_WINDOW)
|
||||
session->ack_srv=new_ack;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
|
||||
if (new_ack-session->ack_cln<MAX_WINDOW)
|
||||
session->ack_cln=new_ack;
|
||||
}
|
||||
if (flags&RST)
|
||||
{
|
||||
next_status=CLOSED_RST;
|
||||
break;
|
||||
}
|
||||
if (flags&FIN)
|
||||
if (direction==session->direction)
|
||||
{ /* an hack to make all things work */
|
||||
session->ack_cln=SW_ULONG_AT(mem_ex->buffer,16);
|
||||
next_status=FIN_CLN_RCV;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
session->ack_srv=SW_ULONG_AT(mem_ex->buffer,16);
|
||||
next_status=FIN_SRV_RCV;
|
||||
break;
|
||||
}
|
||||
next_status=ESTABLISHED;
|
||||
break;
|
||||
|
||||
case CLOSED_RST:
|
||||
next_status=CLOSED_RST;
|
||||
break;
|
||||
|
||||
case FIN_SRV_RCV:
|
||||
if (flags&SYN)
|
||||
{
|
||||
next_status=ERROR_TCP;
|
||||
break;
|
||||
}
|
||||
|
||||
next_status=FIN_SRV_RCV;
|
||||
|
||||
if (flags&ACK)
|
||||
{
|
||||
uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
|
||||
if (direction!=session->direction)
|
||||
if ((new_ack-session->ack_cln)<MAX_WINDOW)
|
||||
session->ack_cln=new_ack;
|
||||
}
|
||||
|
||||
if (flags&RST)
|
||||
next_status=CLOSED_RST;
|
||||
else
|
||||
if ((flags&FIN)&&(direction==session->direction))
|
||||
{
|
||||
session->ack_cln=SW_ULONG_AT(mem_ex->buffer,16);
|
||||
next_status=CLOSED_FIN;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case FIN_CLN_RCV:
|
||||
if (flags&SYN)
|
||||
{
|
||||
next_status=ERROR_TCP;
|
||||
break;
|
||||
}
|
||||
|
||||
next_status=FIN_CLN_RCV;
|
||||
|
||||
if (flags&ACK)
|
||||
{
|
||||
uint32 new_ack=SW_ULONG_AT(mem_ex->buffer,20);
|
||||
if (direction==session->direction)
|
||||
if (new_ack-session->ack_srv<MAX_WINDOW)
|
||||
session->ack_srv=new_ack;
|
||||
}
|
||||
|
||||
if (flags&RST)
|
||||
next_status=CLOSED_RST;
|
||||
else
|
||||
if ((flags&FIN)&&(direction!=session->direction))
|
||||
{
|
||||
session->ack_srv=SW_ULONG_AT(mem_ex->buffer,16);
|
||||
next_status=CLOSED_FIN;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CLOSED_FIN:
|
||||
next_status=CLOSED_FIN;
|
||||
break;
|
||||
default:
|
||||
next_status=ERROR_TCP;
|
||||
|
||||
}
|
||||
|
||||
session->status=next_status;
|
||||
|
||||
if ((next_status==CLOSED_FIN)||(next_status==UNKNOWN)||(next_status==CLOSED_RST)||(next_status==ERROR_TCP))
|
||||
session->timestamp_block=session->last_timestamp;
|
||||
|
||||
return TME_SUCCESS;
|
||||
}
|
85
reactos/drivers/net/packet/tcp_session.h
Normal file
85
reactos/drivers/net/packet/tcp_session.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifndef __tcp_session
|
||||
#define __tcp_session
|
||||
|
||||
#ifdef WIN32
|
||||
#include "tme.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <net/tme/tme.h>
|
||||
#else
|
||||
#include <tme/tme.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#define UNKNOWN 0
|
||||
#define SYN_RCV 1
|
||||
#define SYN_ACK_RCV 2
|
||||
#define ESTABLISHED 3
|
||||
#define CLOSED_RST 4
|
||||
#define FIN_CLN_RCV 5
|
||||
#define FIN_SRV_RCV 6
|
||||
#define CLOSED_FIN 7
|
||||
#define ERROR_TCP 8
|
||||
#define FIRST_IS_CLN 0
|
||||
#define FIRST_IS_SRV 0xffffffff
|
||||
#define FIN_CLN 1
|
||||
#define FIN_SRV 2
|
||||
|
||||
#define MAX_WINDOW 65536
|
||||
|
||||
typedef struct __tcp_data
|
||||
{
|
||||
struct timeval timestamp_block; /*DO NOT MOVE THIS VALUE*/
|
||||
struct timeval syn_timestamp;
|
||||
struct timeval last_timestamp;
|
||||
struct timeval syn_ack_timestamp;
|
||||
uint32 direction;
|
||||
uint32 seq_n_0_srv;
|
||||
uint32 seq_n_0_cln;
|
||||
uint32 ack_srv; /* acknowledge of (data sent by server) */
|
||||
uint32 ack_cln; /* acknowledge of (data sent by client) */
|
||||
uint32 status;
|
||||
uint32 pkts_cln_to_srv;
|
||||
uint32 pkts_srv_to_cln;
|
||||
uint32 bytes_srv_to_cln;
|
||||
uint32 bytes_cln_to_srv;
|
||||
uint32 close_state;
|
||||
}
|
||||
tcp_data;
|
||||
|
||||
#define FIN 1
|
||||
#define SYN 2
|
||||
#define RST 4
|
||||
#define PSH 8
|
||||
#define ACK 16
|
||||
#define URG 32
|
||||
|
||||
#define TCP_SESSION 0x00000800
|
||||
uint32 tcp_session(uint8 *block, uint32 pkt_size, TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data);
|
||||
|
||||
#endif
|
236
reactos/drivers/net/packet/time_calls.c
Normal file
236
reactos/drivers/net/packet/time_calls.c
Normal file
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#include "tme.h"
|
||||
#include "win_bpf.h"
|
||||
#include "time_calls.h"
|
||||
|
||||
|
||||
void TIME_DESYNCHRONIZE(struct time_conv *data)
|
||||
{
|
||||
#ifndef __GNUC__
|
||||
data->reference = 0;
|
||||
data->start.tv_sec = 0;
|
||||
data->start.tv_usec = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef KQPC_TS
|
||||
|
||||
/* KeQueryPerformanceCounter TimeStamps */
|
||||
|
||||
VOID TIME_SYNCHRONIZE(struct time_conv *data)
|
||||
{
|
||||
#ifndef __GNUC__
|
||||
struct timeval tmp;
|
||||
LARGE_INTEGER SystemTime;
|
||||
LARGE_INTEGER i;
|
||||
ULONG tmp2;
|
||||
LARGE_INTEGER TimeFreq,PTime;
|
||||
|
||||
if (data->reference!=0)
|
||||
return;
|
||||
|
||||
// get the absolute value of the system boot time.
|
||||
PTime=KeQueryPerformanceCounter(&TimeFreq);
|
||||
KeQuerySystemTime(&SystemTime);
|
||||
tmp.tv_sec=(LONG)(SystemTime.QuadPart/10000000-11644473600);
|
||||
tmp.tv_usec=(LONG)((SystemTime.QuadPart%10000000)/10);
|
||||
tmp.tv_sec-=(ULONG)(PTime.QuadPart/TimeFreq.QuadPart);
|
||||
tmp.tv_usec-=(LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
|
||||
if (tmp.tv_usec<0) {
|
||||
tmp.tv_sec--;
|
||||
tmp.tv_usec+=1000000;
|
||||
}
|
||||
data->start=tmp;
|
||||
data->reference=1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void FORCE_TIME(struct timeval *src, struct time_conv *dest)
|
||||
{
|
||||
dest->start=*src;
|
||||
}
|
||||
|
||||
void GET_TIME(struct timeval *dst, struct time_conv *data)
|
||||
{
|
||||
#ifndef __GNUC__
|
||||
LARGE_INTEGER PTime, TimeFreq;
|
||||
LONG tmp;
|
||||
|
||||
PTime=KeQueryPerformanceCounter(&TimeFreq);
|
||||
tmp=(LONG)(PTime.QuadPart/TimeFreq.QuadPart);
|
||||
dst->tv_sec=data->start.tv_sec+tmp;
|
||||
dst->tv_usec=data->start.tv_usec+(LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
|
||||
if (dst->tv_usec>=1000000) {
|
||||
dst->tv_sec++;
|
||||
dst->tv_usec-=1000000;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*RDTSC timestamps*/
|
||||
|
||||
/* callers must be at IRQL=PASSIVE_LEVEL */
|
||||
VOID TIME_SYNCHRONIZE(struct time_conv *data)
|
||||
{
|
||||
#ifndef __GNUC__
|
||||
struct timeval tmp;
|
||||
LARGE_INTEGER system_time;
|
||||
ULONGLONG curr_ticks;
|
||||
KIRQL old;
|
||||
LARGE_INTEGER start_kqpc,stop_kqpc,start_freq,stop_freq;
|
||||
ULONGLONG start_ticks,stop_ticks;
|
||||
ULONGLONG delta,delta2;
|
||||
KEVENT event;
|
||||
LARGE_INTEGER i;
|
||||
ULONGLONG reference;
|
||||
|
||||
if (data->reference!=0)
|
||||
return;
|
||||
|
||||
KeInitializeEvent(&event,NotificationEvent,FALSE);
|
||||
i.QuadPart=-3500000;
|
||||
KeRaiseIrql(HIGH_LEVEL,&old);
|
||||
start_kqpc=KeQueryPerformanceCounter(&start_freq);
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push edx
|
||||
push ecx
|
||||
rdtsc
|
||||
lea ecx, start_ticks
|
||||
mov [ecx+4], edx
|
||||
mov [ecx], eax
|
||||
pop ecx
|
||||
pop edx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
KeLowerIrql(old);
|
||||
KeWaitForSingleObject(&event,UserRequest,KernelMode,TRUE ,&i);
|
||||
KeRaiseIrql(HIGH_LEVEL,&old);
|
||||
stop_kqpc=KeQueryPerformanceCounter(&stop_freq);
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push edx
|
||||
push ecx
|
||||
rdtsc
|
||||
lea ecx, stop_ticks
|
||||
mov [ecx+4], edx
|
||||
mov [ecx], eax
|
||||
pop ecx
|
||||
pop edx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
KeLowerIrql(old);
|
||||
delta=stop_ticks-start_ticks;
|
||||
delta2=stop_kqpc.QuadPart-start_kqpc.QuadPart;
|
||||
if (delta>10000000000) {
|
||||
delta/=16;
|
||||
delta2/=16;
|
||||
}
|
||||
reference=delta*(start_freq.QuadPart)/delta2;
|
||||
data->reference=reference/1000;
|
||||
if (reference%1000>500)
|
||||
data->reference++;
|
||||
data->reference*=1000;
|
||||
reference=data->reference;
|
||||
KeQuerySystemTime(&system_time);
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push edx
|
||||
push ecx
|
||||
rdtsc
|
||||
lea ecx, curr_ticks
|
||||
mov [ecx+4], edx
|
||||
mov [ecx], eax
|
||||
pop ecx
|
||||
pop edx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
tmp.tv_sec=-(LONG)(curr_ticks/reference);
|
||||
tmp.tv_usec=-(LONG)((curr_ticks%reference)*1000000/reference);
|
||||
system_time.QuadPart-=116444736000000000;
|
||||
tmp.tv_sec+=(LONG)(system_time.QuadPart/10000000);
|
||||
tmp.tv_usec+=(LONG)((system_time.QuadPart%10000000)/10);
|
||||
if (tmp.tv_usec<0) {
|
||||
tmp.tv_sec--;
|
||||
tmp.tv_usec+=1000000;
|
||||
}
|
||||
data->start=tmp;
|
||||
IF_LOUD(DbgPrint("Frequency %I64u MHz\n",data->reference);)
|
||||
#else
|
||||
#endif
|
||||
}
|
||||
|
||||
void FORCE_TIME(struct timeval *src, struct time_conv *dest)
|
||||
{
|
||||
dest->start=*src;
|
||||
}
|
||||
|
||||
void GET_TIME(struct timeval *dst, struct time_conv *data)
|
||||
{
|
||||
#ifndef __GNUC__
|
||||
ULONGLONG tmp;
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push edx
|
||||
push ecx
|
||||
rdtsc
|
||||
lea ecx, tmp
|
||||
mov [ecx+4], edx
|
||||
mov [ecx], eax
|
||||
pop ecx
|
||||
pop edx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
if (data->reference==0) {
|
||||
return;
|
||||
}
|
||||
dst->tv_sec=(LONG)(tmp/data->reference);
|
||||
dst->tv_usec=(LONG)((tmp-dst->tv_sec*data->reference)*1000000/data->reference);
|
||||
dst->tv_sec+=data->start.tv_sec;
|
||||
dst->tv_usec+=data->start.tv_usec;
|
||||
if (dst->tv_usec>=1000000) {
|
||||
dst->tv_sec++;
|
||||
dst->tv_usec-=1000000;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /*KQPC_TS*/
|
262
reactos/drivers/net/packet/time_calls.h
Normal file
262
reactos/drivers/net/packet/time_calls.h
Normal file
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifndef _time_calls
|
||||
#define _time_calls
|
||||
|
||||
#ifdef WIN_NT_DRIVER
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
/*!
|
||||
\brief A microsecond precise timestamp.
|
||||
|
||||
included in the sf_pkthdr or the bpf_hdr that NPF associates with every packet.
|
||||
*/
|
||||
|
||||
struct timeval {
|
||||
long tv_sec; ///< seconds
|
||||
long tv_usec; ///< microseconds
|
||||
};
|
||||
|
||||
#endif /*WIN_NT_DRIVER*/
|
||||
|
||||
struct time_conv {
|
||||
ULONGLONG reference;
|
||||
struct timeval start;
|
||||
};
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
void TIME_DESYNCHRONIZE(struct time_conv *data);
|
||||
VOID TIME_SYNCHRONIZE(struct time_conv *data);
|
||||
void FORCE_TIME(struct timeval *src, struct time_conv *dest);
|
||||
void GET_TIME(struct timeval *dst, struct time_conv *data);
|
||||
|
||||
#else /* __GNUC__ */
|
||||
|
||||
#ifdef WIN_NT_DRIVER
|
||||
|
||||
__inline void TIME_DESYNCHRONIZE(struct time_conv *data)
|
||||
{
|
||||
data->reference = 0;
|
||||
data->start.tv_sec = 0;
|
||||
data->start.tv_usec = 0;
|
||||
}
|
||||
|
||||
#ifdef KQPC_TS
|
||||
|
||||
/* KeQueryPerformanceCounter TimeStamps */
|
||||
|
||||
__inline VOID TIME_SYNCHRONIZE(struct time_conv *data)
|
||||
{
|
||||
struct timeval tmp;
|
||||
LARGE_INTEGER SystemTime;
|
||||
LARGE_INTEGER i;
|
||||
ULONG tmp2;
|
||||
LARGE_INTEGER TimeFreq,PTime;
|
||||
|
||||
if (data->reference!=0)
|
||||
return;
|
||||
|
||||
// get the absolute value of the system boot time.
|
||||
PTime=KeQueryPerformanceCounter(&TimeFreq);
|
||||
KeQuerySystemTime(&SystemTime);
|
||||
tmp.tv_sec=(LONG)(SystemTime.QuadPart/10000000-11644473600);
|
||||
tmp.tv_usec=(LONG)((SystemTime.QuadPart%10000000)/10);
|
||||
tmp.tv_sec-=(ULONG)(PTime.QuadPart/TimeFreq.QuadPart);
|
||||
tmp.tv_usec-=(LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
|
||||
if (tmp.tv_usec<0) {
|
||||
tmp.tv_sec--;
|
||||
tmp.tv_usec+=1000000;
|
||||
}
|
||||
data->start=tmp;
|
||||
data->reference=1;
|
||||
}
|
||||
|
||||
__inline void FORCE_TIME(struct timeval *src, struct time_conv *dest)
|
||||
{
|
||||
dest->start=*src;
|
||||
}
|
||||
|
||||
__inline void GET_TIME(struct timeval *dst, struct time_conv *data)
|
||||
{
|
||||
LARGE_INTEGER PTime, TimeFreq;
|
||||
LONG tmp;
|
||||
|
||||
PTime=KeQueryPerformanceCounter(&TimeFreq);
|
||||
tmp=(LONG)(PTime.QuadPart/TimeFreq.QuadPart);
|
||||
dst->tv_sec=data->start.tv_sec+tmp;
|
||||
dst->tv_usec=data->start.tv_usec+(LONG)((PTime.QuadPart%TimeFreq.QuadPart)*1000000/TimeFreq.QuadPart);
|
||||
if (dst->tv_usec>=1000000) {
|
||||
dst->tv_sec++;
|
||||
dst->tv_usec-=1000000;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*RDTSC timestamps*/
|
||||
|
||||
/* callers must be at IRQL=PASSIVE_LEVEL */
|
||||
__inline VOID TIME_SYNCHRONIZE(struct time_conv *data)
|
||||
{
|
||||
struct timeval tmp;
|
||||
LARGE_INTEGER system_time;
|
||||
ULONGLONG curr_ticks;
|
||||
KIRQL old;
|
||||
LARGE_INTEGER start_kqpc,stop_kqpc,start_freq,stop_freq;
|
||||
ULONGLONG start_ticks,stop_ticks;
|
||||
ULONGLONG delta,delta2;
|
||||
KEVENT event;
|
||||
LARGE_INTEGER i;
|
||||
ULONGLONG reference;
|
||||
|
||||
if (data->reference!=0)
|
||||
return;
|
||||
|
||||
KeInitializeEvent(&event,NotificationEvent,FALSE);
|
||||
i.QuadPart=-3500000;
|
||||
KeRaiseIrql(HIGH_LEVEL,&old);
|
||||
start_kqpc=KeQueryPerformanceCounter(&start_freq);
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push edx
|
||||
push ecx
|
||||
rdtsc
|
||||
lea ecx, start_ticks
|
||||
mov [ecx+4], edx
|
||||
mov [ecx], eax
|
||||
pop ecx
|
||||
pop edx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
KeLowerIrql(old);
|
||||
KeWaitForSingleObject(&event,UserRequest,KernelMode,TRUE ,&i);
|
||||
KeRaiseIrql(HIGH_LEVEL,&old);
|
||||
stop_kqpc=KeQueryPerformanceCounter(&stop_freq);
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push edx
|
||||
push ecx
|
||||
rdtsc
|
||||
lea ecx, stop_ticks
|
||||
mov [ecx+4], edx
|
||||
mov [ecx], eax
|
||||
pop ecx
|
||||
pop edx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
KeLowerIrql(old);
|
||||
delta=stop_ticks-start_ticks;
|
||||
delta2=stop_kqpc.QuadPart-start_kqpc.QuadPart;
|
||||
if (delta>10000000000) {
|
||||
delta/=16;
|
||||
delta2/=16;
|
||||
}
|
||||
reference=delta*(start_freq.QuadPart)/delta2;
|
||||
data->reference=reference/1000;
|
||||
if (reference%1000>500)
|
||||
data->reference++;
|
||||
data->reference*=1000;
|
||||
reference=data->reference;
|
||||
KeQuerySystemTime(&system_time);
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push edx
|
||||
push ecx
|
||||
rdtsc
|
||||
lea ecx, curr_ticks
|
||||
mov [ecx+4], edx
|
||||
mov [ecx], eax
|
||||
pop ecx
|
||||
pop edx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
tmp.tv_sec=-(LONG)(curr_ticks/reference);
|
||||
tmp.tv_usec=-(LONG)((curr_ticks%reference)*1000000/reference);
|
||||
system_time.QuadPart-=116444736000000000;
|
||||
tmp.tv_sec+=(LONG)(system_time.QuadPart/10000000);
|
||||
tmp.tv_usec+=(LONG)((system_time.QuadPart%10000000)/10);
|
||||
if (tmp.tv_usec<0) {
|
||||
tmp.tv_sec--;
|
||||
tmp.tv_usec+=1000000;
|
||||
}
|
||||
data->start=tmp;
|
||||
IF_LOUD(DbgPrint("Frequency %I64u MHz\n",data->reference);)
|
||||
}
|
||||
|
||||
__inline void FORCE_TIME(struct timeval *src, struct time_conv *dest)
|
||||
{
|
||||
dest->start=*src;
|
||||
}
|
||||
|
||||
__inline void GET_TIME(struct timeval *dst, struct time_conv *data)
|
||||
{
|
||||
ULONGLONG tmp;
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push edx
|
||||
push ecx
|
||||
rdtsc
|
||||
lea ecx, tmp
|
||||
mov [ecx+4], edx
|
||||
mov [ecx], eax
|
||||
pop ecx
|
||||
pop edx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
if (data->reference==0) {
|
||||
return;
|
||||
}
|
||||
dst->tv_sec=(LONG)(tmp/data->reference);
|
||||
dst->tv_usec=(LONG)((tmp-dst->tv_sec*data->reference)*1000000/data->reference);
|
||||
dst->tv_sec+=data->start.tv_sec;
|
||||
dst->tv_usec+=data->start.tv_usec;
|
||||
if (dst->tv_usec>=1000000) {
|
||||
dst->tv_sec++;
|
||||
dst->tv_usec-=1000000;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /*KQPC_TS*/
|
||||
|
||||
#endif /*WIN_NT_DRIVER*/
|
||||
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
#endif /*_time_calls*/
|
378
reactos/drivers/net/packet/tme.c
Normal file
378
reactos/drivers/net/packet/tme.c
Normal file
|
@ -0,0 +1,378 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#include "tme.h"
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <net/tme/tme.h>
|
||||
#endif
|
||||
|
||||
/* resizes extended memory */
|
||||
uint32 init_extended_memory(uint32 size, MEM_TYPE *mem_ex)
|
||||
{
|
||||
uint8 *tmp;
|
||||
|
||||
if ((mem_ex==NULL)||(mem_ex->buffer==NULL)||(size==0))
|
||||
return TME_ERROR; /* awfully never reached!!!! */
|
||||
|
||||
tmp=mem_ex->buffer;
|
||||
mem_ex->buffer=NULL;
|
||||
FREE_MEMORY(tmp);
|
||||
|
||||
ALLOCATE_MEMORY(tmp,uint8,size);
|
||||
if (tmp==NULL)
|
||||
return TME_ERROR; /* no memory */
|
||||
|
||||
mem_ex->size=size;
|
||||
mem_ex->buffer=tmp;
|
||||
return TME_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
/* activates a block of the TME */
|
||||
uint32 set_active_tme_block(TME_CORE *tme, uint32 block)
|
||||
{
|
||||
|
||||
if ((block>=MAX_TME_DATA_BLOCKS)||(!IS_VALIDATED(tme->validated_blocks,block)))
|
||||
return TME_ERROR;
|
||||
tme->active=block;
|
||||
tme->working=block;
|
||||
return TME_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
/* simply inserts default values in a TME block */
|
||||
/* it DOESN'T initialize the block in the core!! */
|
||||
/* FIXME default values are defined at compile time, */
|
||||
/* it will be useful to store them in the registry */
|
||||
uint32 init_tme_block(TME_CORE *tme, uint32 block)
|
||||
{
|
||||
|
||||
TME_DATA *data;
|
||||
if (block>=MAX_TME_DATA_BLOCKS)
|
||||
return TME_ERROR;
|
||||
data=&(tme->block_data[block]);
|
||||
tme->working=block;
|
||||
|
||||
ZERO_MEMORY(data,sizeof(TME_DATA));
|
||||
|
||||
/* entries in LUT */
|
||||
data->lut_entries=TME_LUT_ENTRIES_DEFAULT;
|
||||
/* blocks */
|
||||
data->shared_memory_blocks=TME_SHARED_MEMORY_BLOCKS_DEFAULT;
|
||||
/* block size */
|
||||
data->block_size=TME_BLOCK_SIZE_DEFAULT;
|
||||
/* lookup function */
|
||||
data->lookup_code=lut_fcn_mapper(TME_LOOKUP_CODE_DEFAULT);
|
||||
/* rehashing value */
|
||||
data->rehashing_value=TME_REHASHING_VALUE_DEFAULT;
|
||||
/* out lut function */
|
||||
data->out_lut_exec=TME_OUT_LUT_EXEC_DEFAULT;
|
||||
/* default function */
|
||||
data->default_exec=TME_DEFAULT_EXEC_DEFAULT;
|
||||
/* extra segment size */
|
||||
data->extra_segment_size=TME_EXTRA_SEGMENT_SIZE_DEFAULT;
|
||||
|
||||
|
||||
data->enable_deletion=FALSE;
|
||||
data->last_read.tv_sec=0;
|
||||
data->last_read.tv_usec=0;
|
||||
return TME_SUCCESS;
|
||||
|
||||
}
|
||||
/* it validates a TME block and */
|
||||
/* (on OK) inserts the block in the core */
|
||||
uint32 validate_tme_block(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 block, uint32 mem_ex_offset)
|
||||
{
|
||||
uint32 required_memory;
|
||||
uint8 *base=mem_ex_offset+mem_ex->buffer;
|
||||
TME_DATA *data;
|
||||
|
||||
/* FIXME soluzione un po' posticcia... */
|
||||
if (mem_ex_offset==0)
|
||||
return TME_ERROR;
|
||||
|
||||
if (block>=MAX_TME_DATA_BLOCKS)
|
||||
return TME_ERROR;
|
||||
data=&tme->block_data[block];
|
||||
|
||||
if (data->lut_entries==0)
|
||||
return TME_ERROR;
|
||||
|
||||
if (data->key_len==0)
|
||||
return TME_ERROR;
|
||||
|
||||
if (data->shared_memory_blocks==0)
|
||||
return TME_ERROR;
|
||||
|
||||
if (data->block_size==0)
|
||||
return TME_ERROR;
|
||||
|
||||
/* checks if the lookup function is valid */
|
||||
if (data->lookup_code==NULL)
|
||||
return TME_ERROR;
|
||||
|
||||
/* checks if the out lut exec function is valid */
|
||||
if (exec_fcn_mapper(data->out_lut_exec)==NULL)
|
||||
return TME_ERROR;
|
||||
|
||||
/* checks if the default exec function is valid */
|
||||
if (exec_fcn_mapper(data->default_exec)==NULL)
|
||||
return TME_ERROR;
|
||||
|
||||
/* let's calculate memory needed */
|
||||
required_memory=data->lut_entries*sizeof(RECORD); /*LUT*/
|
||||
required_memory+=data->block_size*data->shared_memory_blocks; /*shared segment*/
|
||||
required_memory+=data->extra_segment_size; /*extra segment*/
|
||||
|
||||
if (required_memory>(mem_ex->size-mem_ex_offset))
|
||||
return TME_ERROR; /*not enough memory*/
|
||||
|
||||
/* the TME block can be initialized */
|
||||
ZERO_MEMORY(base,required_memory);
|
||||
|
||||
data->lut_base_address=base;
|
||||
|
||||
data->shared_memory_base_address=
|
||||
data->lut_base_address+
|
||||
data->lut_entries*sizeof(RECORD);
|
||||
|
||||
data->extra_segment_base_address=
|
||||
data->shared_memory_base_address+
|
||||
data->block_size*data->shared_memory_blocks;
|
||||
data->filled_blocks=1;
|
||||
VALIDATE(tme->validated_blocks,block);
|
||||
tme->active=block;
|
||||
tme->working=block;
|
||||
return TME_SUCCESS;
|
||||
}
|
||||
|
||||
/* I/F between the bpf machine and the callbacks, just some checks */
|
||||
uint32 lookup_frontend(MEM_TYPE *mem_ex, TME_CORE *tme,uint32 mem_ex_offset, struct time_conv *time_ref)
|
||||
{
|
||||
if (tme->active==TME_NONE_ACTIVE)
|
||||
return TME_FALSE;
|
||||
|
||||
return (tme->block_data[tme->active].lookup_code)(mem_ex_offset+mem_ex->buffer,&tme->block_data[tme->active],mem_ex, time_ref);
|
||||
}
|
||||
|
||||
/* I/F between the bpf machine and the callbacks, just some checks */
|
||||
uint32 execute_frontend(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 pkt_size, uint32 offset)
|
||||
{
|
||||
|
||||
exec_fcn tmp;
|
||||
TME_DATA *data;
|
||||
uint8 *block;
|
||||
uint8 *mem_data;
|
||||
|
||||
if (tme->active==TME_NONE_ACTIVE)
|
||||
return TME_ERROR;
|
||||
|
||||
data=&tme->block_data[tme->active];
|
||||
|
||||
if (data->last_found==NULL)
|
||||
{ /*out lut exec */
|
||||
tmp=exec_fcn_mapper(data->out_lut_exec);
|
||||
block=data->shared_memory_base_address;
|
||||
}
|
||||
else
|
||||
{ /*checks if last_found is valid */
|
||||
if ((data->last_found<data->lut_base_address)||(data->last_found>=data->shared_memory_base_address))
|
||||
return TME_ERROR;
|
||||
else
|
||||
{
|
||||
tmp=exec_fcn_mapper(SW_ULONG_AT(&((RECORD*)data->last_found)->exec_fcn,0));
|
||||
if (tmp==NULL)
|
||||
return TME_ERROR;
|
||||
block=SW_ULONG_AT(&((RECORD*)data->last_found)->block,0)+mem_ex->buffer;
|
||||
if ((block<data->shared_memory_base_address)||(block>=data->extra_segment_base_address))
|
||||
return TME_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (offset>=mem_ex->size)
|
||||
return TME_ERROR;
|
||||
|
||||
mem_data=mem_ex->buffer+offset;
|
||||
|
||||
return tmp(block,pkt_size,data,mem_ex,mem_data);
|
||||
}
|
||||
|
||||
/*resets all the TME core*/
|
||||
uint32 reset_tme(TME_CORE *tme)
|
||||
{
|
||||
if (tme==NULL)
|
||||
return TME_ERROR;
|
||||
ZERO_MEMORY(tme, sizeof(TME_CORE));
|
||||
return TME_SUCCESS;
|
||||
}
|
||||
|
||||
/* returns a register value of the active TME block */
|
||||
/* FIXME last found in maniera elegante e veloce ?!?! */
|
||||
uint32 get_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 *rval)
|
||||
{
|
||||
switch(rgstr)
|
||||
{
|
||||
case TME_LUT_ENTRIES:
|
||||
*rval=data->lut_entries;
|
||||
return TME_SUCCESS;
|
||||
case TME_MAX_FILL_STATE:
|
||||
*rval=data->max_fill_state;
|
||||
return TME_SUCCESS;
|
||||
case TME_REHASHING_VALUE:
|
||||
*rval=data->rehashing_value;
|
||||
return TME_SUCCESS;
|
||||
case TME_KEY_LEN:
|
||||
*rval=data->key_len;
|
||||
return TME_SUCCESS;
|
||||
case TME_SHARED_MEMORY_BLOCKS:
|
||||
*rval=data->shared_memory_blocks;
|
||||
return TME_SUCCESS;
|
||||
case TME_FILLED_ENTRIES:
|
||||
*rval=data->filled_entries;
|
||||
return TME_SUCCESS;
|
||||
case TME_BLOCK_SIZE:
|
||||
*rval=data->block_size;
|
||||
return TME_SUCCESS;
|
||||
case TME_EXTRA_SEGMENT_SIZE:
|
||||
*rval=data->extra_segment_size;
|
||||
return TME_SUCCESS;
|
||||
case TME_FILLED_BLOCKS:
|
||||
*rval=data->filled_blocks;
|
||||
return TME_SUCCESS;
|
||||
case TME_DEFAULT_EXEC:
|
||||
*rval=data->default_exec;
|
||||
return TME_SUCCESS;
|
||||
case TME_OUT_LUT_EXEC:
|
||||
*rval=data->out_lut_exec;
|
||||
return TME_SUCCESS;
|
||||
case TME_SHARED_MEMORY_BASE_ADDRESS:
|
||||
*rval=data->shared_memory_base_address-mem_ex->buffer;
|
||||
return TME_SUCCESS;
|
||||
case TME_LUT_BASE_ADDRESS:
|
||||
*rval=data->lut_base_address-mem_ex->buffer;
|
||||
return TME_SUCCESS;
|
||||
case TME_EXTRA_SEGMENT_BASE_ADDRESS:
|
||||
*rval=data->extra_segment_base_address-mem_ex->buffer;
|
||||
return TME_SUCCESS;
|
||||
case TME_LAST_FOUND_BLOCK:
|
||||
if (data->last_found==NULL)
|
||||
*rval=0;
|
||||
else
|
||||
*rval=data->last_found-mem_ex->buffer;
|
||||
return TME_SUCCESS;
|
||||
|
||||
default:
|
||||
return TME_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* sets a register value in the active block */
|
||||
/* FIXME last found in maniera elegante e veloce ?!?! */
|
||||
uint32 set_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 value, int32 init)
|
||||
{ /* very very very dangerous!!!!!!!!!!! */
|
||||
lut_fcn tmp;
|
||||
switch(rgstr)
|
||||
{
|
||||
case TME_MAX_FILL_STATE:
|
||||
data->max_fill_state=value;
|
||||
return TME_SUCCESS;
|
||||
case TME_REHASHING_VALUE:
|
||||
data->rehashing_value=value;
|
||||
return TME_SUCCESS;
|
||||
case TME_FILLED_ENTRIES:
|
||||
data->filled_entries=value;
|
||||
return TME_SUCCESS;
|
||||
case TME_FILLED_BLOCKS:
|
||||
if (value<=data->shared_memory_blocks)
|
||||
{
|
||||
data->filled_blocks=value;
|
||||
return TME_SUCCESS;
|
||||
}
|
||||
else
|
||||
return TME_ERROR;
|
||||
case TME_DEFAULT_EXEC:
|
||||
data->default_exec=value;
|
||||
return TME_SUCCESS;
|
||||
case TME_OUT_LUT_EXEC:
|
||||
data->out_lut_exec=value;
|
||||
return TME_SUCCESS;
|
||||
case TME_LOOKUP_CODE:
|
||||
tmp=lut_fcn_mapper(value);
|
||||
if (tmp==NULL)
|
||||
return TME_ERROR;
|
||||
else
|
||||
data->lookup_code=tmp;
|
||||
return TME_SUCCESS;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (init)
|
||||
switch (rgstr)
|
||||
{
|
||||
|
||||
case TME_LUT_ENTRIES:
|
||||
data->lut_entries=value;
|
||||
return TME_SUCCESS;
|
||||
case TME_KEY_LEN:
|
||||
data->key_len=value;
|
||||
return TME_SUCCESS;
|
||||
case TME_SHARED_MEMORY_BLOCKS:
|
||||
data->shared_memory_blocks=value;
|
||||
return TME_SUCCESS;
|
||||
case TME_BLOCK_SIZE:
|
||||
data->block_size=value;
|
||||
return TME_SUCCESS;
|
||||
case TME_EXTRA_SEGMENT_SIZE:
|
||||
data->extra_segment_size=value;
|
||||
return TME_SUCCESS;
|
||||
default:
|
||||
return TME_ERROR;
|
||||
}
|
||||
else
|
||||
return TME_ERROR;
|
||||
|
||||
}
|
||||
|
||||
/* chooses the TME block for read */
|
||||
uint32 set_active_read_tme_block(TME_CORE *tme, uint32 block)
|
||||
{
|
||||
|
||||
if ((block>=MAX_TME_DATA_BLOCKS)||(!IS_VALIDATED(tme->validated_blocks,block)))
|
||||
return TME_ERROR;
|
||||
tme->active_read=block;
|
||||
return TME_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
/* chooses if the autodeletion must be used */
|
||||
uint32 set_autodeletion(TME_DATA *data, uint32 value)
|
||||
{
|
||||
if (value==0) /* no autodeletion */
|
||||
data->enable_deletion=FALSE;
|
||||
else
|
||||
data->enable_deletion=TRUE;
|
||||
|
||||
return TME_SUCCESS;
|
||||
}
|
182
reactos/drivers/net/packet/tme.h
Normal file
182
reactos/drivers/net/packet/tme.h
Normal file
|
@ -0,0 +1,182 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#ifndef __tme_include_
|
||||
#define __tme_include_
|
||||
|
||||
#ifdef WIN_NT_DRIVER
|
||||
|
||||
#include "ntddk.h"
|
||||
#include "memory_t.h"
|
||||
#include "time_calls.h"
|
||||
#endif /*WIN_NT_DRIVER*/
|
||||
|
||||
#ifdef WIN32
|
||||
#include "memory_t.h"
|
||||
#include "time_calls.h"
|
||||
#endif /*WIN32*/
|
||||
|
||||
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
#ifdef _KERNEL
|
||||
#include <net/tme/time_calls.h>
|
||||
#else
|
||||
#include <tme/time_calls.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* error codes */
|
||||
#define TME_ERROR 0
|
||||
#define TME_SUCCESS 1
|
||||
#define TME_TRUE 2
|
||||
#define TME_FALSE 3
|
||||
|
||||
/* some constants */
|
||||
#define DEFAULT_MEM_EX_SIZE 65536
|
||||
#define MAX_TME_DATA_BLOCKS 4
|
||||
#define TME_NONE_ACTIVE 0xffffffff
|
||||
#define DELTA_READ 2 /* secs */
|
||||
|
||||
#define TME_LUT_ENTRIES 0x00000000
|
||||
#define TME_MAX_FILL_STATE 0x00000001 /*potrebbe servire per un thread a passive level!?!?! */
|
||||
#define TME_REHASHING_VALUE 0x00000002
|
||||
#define TME_KEY_LEN 0x00000003
|
||||
#define TME_SHARED_MEMORY_BLOCKS 0x00000004
|
||||
#define TME_FILLED_ENTRIES 0x00000005
|
||||
#define TME_BLOCK_SIZE 0x00000006
|
||||
#define TME_EXTRA_SEGMENT_SIZE 0x00000007
|
||||
#define TME_LOOKUP_CODE 0x00000008
|
||||
#define TME_OUT_LUT_EXEC 0x00000009
|
||||
#define TME_FILLED_BLOCKS 0x0000000a
|
||||
#define TME_DEFAULT_EXEC 0x0000000b
|
||||
#define TME_LUT_BASE_ADDRESS 0x0000000c
|
||||
#define TME_SHARED_MEMORY_BASE_ADDRESS 0x0000000d
|
||||
#define TME_EXTRA_SEGMENT_BASE_ADDRESS 0x0000000e
|
||||
#define TME_LAST_FOUND 0x0000000f /* contains the offset of the last found entry */
|
||||
#define TME_LAST_FOUND_BLOCK 0x00000010
|
||||
/* TME default values */
|
||||
#define TME_LUT_ENTRIES_DEFAULT 32007
|
||||
#define TME_REHASHING_VALUE_DEFAULT 1
|
||||
#define TME_SHARED_MEMORY_BLOCKS_DEFAULT 16000
|
||||
#define TME_BLOCK_SIZE_DEFAULT 64
|
||||
#define TME_EXTRA_SEGMENT_SIZE_DEFAULT 0
|
||||
#define TME_LOOKUP_CODE_DEFAULT 0
|
||||
#define TME_OUT_LUT_EXEC_DEFAULT 0
|
||||
#define TME_DEFAULT_EXEC_DEFAULT 0
|
||||
#define TME_MAX_FILL_STATE_DEFAULT 15000
|
||||
|
||||
#define IS_VALIDATED(src,index) (src&(1<<index))
|
||||
|
||||
#define VALIDATE(src,index) src|=(1<<index);
|
||||
|
||||
|
||||
#define FORCE_NO_DELETION(timestamp) (struct timeval*)(timestamp)->tv_sec=0x7fffffff;
|
||||
|
||||
/* TME callback prototypes */
|
||||
#ifndef __GNUC__
|
||||
typedef uint32 (*lut_fcn)(uint8 *key, struct __TME_DATA *data,MEM_TYPE *mem_ex, struct time_conv *time_ref );
|
||||
typedef uint32 (*exec_fcn)(uint8 *block, uint32 pkt_size, struct __TME_DATA *data, MEM_TYPE *mem_ex, uint8 *mem_data);
|
||||
#else
|
||||
typedef uint32 (*lut_fcn)(uint8 *key, void *data,MEM_TYPE *mem_ex, struct time_conv *time_ref );
|
||||
typedef uint32 (*exec_fcn)(uint8 *block, uint32 pkt_size, void *data, MEM_TYPE *mem_ex, uint8 *mem_data);
|
||||
#endif
|
||||
|
||||
/* DO NOT MODIFY THIS STRUCTURE!!!! GV */
|
||||
typedef struct __RECORD
|
||||
|
||||
{
|
||||
uint32 block;
|
||||
uint32 exec_fcn;
|
||||
}
|
||||
RECORD, *PRECORD;
|
||||
|
||||
/* TME data registers */
|
||||
struct __TME_DATA
|
||||
{
|
||||
uint32 lut_entries;
|
||||
uint32 max_fill_state;
|
||||
uint32 rehashing_value;
|
||||
uint32 key_len;
|
||||
uint32 shared_memory_blocks;
|
||||
uint32 filled_entries;
|
||||
uint32 block_size;
|
||||
uint32 extra_segment_size;
|
||||
uint32 filled_blocks;
|
||||
lut_fcn lookup_code;
|
||||
uint32 default_exec;
|
||||
uint32 out_lut_exec;
|
||||
uint8 *lut_base_address;
|
||||
uint8 *shared_memory_base_address;
|
||||
uint8 *extra_segment_base_address;
|
||||
struct timeval last_read;
|
||||
uint32 enable_deletion;
|
||||
uint8 *last_found;
|
||||
};
|
||||
|
||||
typedef struct __TME_DATA TME_DATA,*PTME_DATA;
|
||||
|
||||
|
||||
|
||||
/* TME core */
|
||||
typedef struct __TME_CORE
|
||||
{
|
||||
uint32 working;
|
||||
uint32 active;
|
||||
uint32 validated_blocks;
|
||||
TME_DATA block_data[MAX_TME_DATA_BLOCKS];
|
||||
uint32 active_read;
|
||||
|
||||
} TME_CORE, *PTME_CORE;
|
||||
|
||||
static __inline int32 IS_DELETABLE(void *timestamp, TME_DATA *data)
|
||||
{
|
||||
struct timeval *ts=(struct timeval*)timestamp;
|
||||
|
||||
if (data->enable_deletion==FALSE)
|
||||
return FALSE;
|
||||
if (data->filled_entries<data->max_fill_state)
|
||||
return FALSE;
|
||||
if ((ts->tv_sec+DELTA_READ)<data->last_read.tv_sec)
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* functions to manage TME */
|
||||
uint32 init_tme_block(TME_CORE *tme, uint32 block);
|
||||
uint32 validate_tme_block(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 block, uint32 mem_ex_offset);
|
||||
uint32 lookup_frontend(MEM_TYPE *mem_ex, TME_CORE *tme,uint32 mem_ex_offset, struct time_conv *time_ref);
|
||||
uint32 execute_frontend(MEM_TYPE *mem_ex, TME_CORE *tme, uint32 pkt_size,uint32 offset);
|
||||
uint32 set_active_tme_block(TME_CORE *tme, uint32 block);
|
||||
uint32 init_extended_memory(uint32 size, MEM_TYPE *mem_ex);
|
||||
uint32 reset_tme(TME_CORE *tme);
|
||||
uint32 get_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 *rval);
|
||||
uint32 set_tme_block_register(TME_DATA *data,MEM_TYPE *mem_ex,uint32 rgstr,uint32 value, int32 init);
|
||||
uint32 set_active_read_tme_block(TME_CORE *tme, uint32 block);
|
||||
uint32 set_autodeletion(TME_DATA *data, uint32 value);
|
||||
|
||||
/* function mappers */
|
||||
lut_fcn lut_fcn_mapper(uint32 index);
|
||||
exec_fcn exec_fcn_mapper(uint32 index);
|
||||
|
||||
#endif
|
73
reactos/drivers/net/packet/valid_insns.h
Normal file
73
reactos/drivers/net/packet/valid_insns.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
u_short valid_instructions[]=
|
||||
{
|
||||
BPF_RET|BPF_K,
|
||||
BPF_RET|BPF_A,
|
||||
BPF_LD|BPF_IMM,
|
||||
BPF_LDX|BPF_IMM,
|
||||
BPF_LD|BPF_MEM,
|
||||
BPF_LDX|BPF_MEM,
|
||||
BPF_LD|BPF_MEM_EX_IMM|BPF_B,
|
||||
BPF_LD|BPF_MEM_EX_IMM|BPF_H,
|
||||
BPF_LD|BPF_MEM_EX_IMM|BPF_W,
|
||||
BPF_LD|BPF_MEM_EX_IND|BPF_B,
|
||||
BPF_LD|BPF_MEM_EX_IND|BPF_H,
|
||||
BPF_LD|BPF_MEM_EX_IND|BPF_W,
|
||||
BPF_LD|BPF_W|BPF_ABS,
|
||||
BPF_LD|BPF_H|BPF_ABS,
|
||||
BPF_LD|BPF_B|BPF_ABS,
|
||||
BPF_LDX|BPF_W|BPF_ABS,
|
||||
BPF_LDX|BPF_H|BPF_ABS,
|
||||
BPF_LDX|BPF_B|BPF_ABS,
|
||||
BPF_LD|BPF_W|BPF_LEN,
|
||||
BPF_LDX|BPF_W|BPF_LEN,
|
||||
BPF_LD|BPF_W|BPF_IND,
|
||||
BPF_LD|BPF_H|BPF_IND,
|
||||
BPF_LD|BPF_B|BPF_IND,
|
||||
BPF_LDX|BPF_MSH|BPF_B,
|
||||
BPF_ST,
|
||||
BPF_STX,
|
||||
BPF_ST|BPF_MEM_EX_IMM|BPF_B,
|
||||
BPF_STX|BPF_MEM_EX_IMM|BPF_B,
|
||||
BPF_ST|BPF_MEM_EX_IMM|BPF_W,
|
||||
BPF_STX|BPF_MEM_EX_IMM|BPF_W,
|
||||
BPF_ST|BPF_MEM_EX_IMM|BPF_H,
|
||||
BPF_STX|BPF_MEM_EX_IMM|BPF_H,
|
||||
BPF_ST|BPF_MEM_EX_IND|BPF_B,
|
||||
BPF_ST|BPF_MEM_EX_IND|BPF_W,
|
||||
BPF_ST|BPF_MEM_EX_IND|BPF_H,
|
||||
BPF_JMP|BPF_JA,
|
||||
BPF_JMP|BPF_JGT|BPF_K,
|
||||
BPF_JMP|BPF_JGE|BPF_K,
|
||||
BPF_JMP|BPF_JEQ|BPF_K,
|
||||
BPF_JMP|BPF_JSET|BPF_K,
|
||||
BPF_JMP|BPF_JGT|BPF_X,
|
||||
BPF_JMP|BPF_JGE|BPF_X,
|
||||
BPF_JMP|BPF_JEQ|BPF_X,
|
||||
BPF_JMP|BPF_JSET|BPF_X,
|
||||
BPF_ALU|BPF_ADD|BPF_X,
|
||||
BPF_ALU|BPF_SUB|BPF_X,
|
||||
BPF_ALU|BPF_MUL|BPF_X,
|
||||
BPF_ALU|BPF_DIV|BPF_X,
|
||||
BPF_ALU|BPF_AND|BPF_X,
|
||||
BPF_ALU|BPF_OR|BPF_X,
|
||||
BPF_ALU|BPF_LSH|BPF_X,
|
||||
BPF_ALU|BPF_RSH|BPF_X,
|
||||
BPF_ALU|BPF_ADD|BPF_K,
|
||||
BPF_ALU|BPF_SUB|BPF_K,
|
||||
BPF_ALU|BPF_MUL|BPF_K,
|
||||
BPF_ALU|BPF_DIV|BPF_K,
|
||||
BPF_ALU|BPF_AND|BPF_K,
|
||||
BPF_ALU|BPF_OR|BPF_K,
|
||||
BPF_ALU|BPF_LSH|BPF_K,
|
||||
BPF_ALU|BPF_RSH|BPF_K,
|
||||
BPF_ALU|BPF_NEG,
|
||||
BPF_MISC|BPF_TAX,
|
||||
BPF_MISC|BPF_TXA,
|
||||
BPF_MISC|BPF_TME|BPF_LOOKUP,
|
||||
BPF_MISC|BPF_TME|BPF_EXECUTE,
|
||||
BPF_MISC|BPF_TME|BPF_SET_ACTIVE,
|
||||
BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE,
|
||||
BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE
|
||||
};
|
||||
|
||||
#define VALID_INSTRUCTIONS_LEN (sizeof(valid_instructions)/sizeof(u_short))
|
|
@ -37,7 +37,7 @@
|
|||
*
|
||||
* @(#)bpf.h 7.1 (Berkeley) 5/7/91
|
||||
*
|
||||
* @(#) $Header: /cygdrive/c/RCVS/CVS/ReactOS/reactos/drivers/net/packet/win_bpf.h,v 1.1 2002/06/19 15:43:15 robd Exp $ (LBL)
|
||||
* @(#) $Header: /cygdrive/c/RCVS/CVS/ReactOS/reactos/drivers/net/packet/win_bpf.h,v 1.2 2002/09/24 15:16:46 robd Exp $ (LBL)
|
||||
*/
|
||||
|
||||
#ifndef BPF_MAJOR_VERSION
|
||||
|
@ -45,37 +45,29 @@
|
|||
/* BSD style release date */
|
||||
#define BPF_RELEASE 199606
|
||||
|
||||
#ifdef __NTDRIVER__
|
||||
#define NTKERNEL
|
||||
#endif
|
||||
|
||||
#ifndef NTKERNEL
|
||||
#include <winsock2.h>
|
||||
typedef int bpf_int32;
|
||||
typedef u_int bpf_u_int32;
|
||||
#else
|
||||
typedef UCHAR u_char;
|
||||
typedef USHORT u_short;
|
||||
typedef UINT u_int;
|
||||
typedef INT bpf_int32;
|
||||
typedef UINT bpf_u_int32;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Alignment macros. BPF_WORDALIGN rounds up to the next
|
||||
* even multiple of BPF_ALIGNMENT.
|
||||
*/
|
||||
#ifndef __NetBSD__
|
||||
#define BPF_ALIGNMENT sizeof(bpf_int32)
|
||||
#else
|
||||
#define BPF_ALIGNMENT sizeof(long)
|
||||
#endif
|
||||
#define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1))
|
||||
typedef ULONG u_int;
|
||||
typedef LONG bpf_int32;
|
||||
typedef ULONG bpf_u_int32;
|
||||
typedef ULONG u_int32;
|
||||
|
||||
#define BPF_MAXINSNS 512
|
||||
#define BPF_MAXBUFSIZE 0x8000
|
||||
#define BPF_MINBUFSIZE 32
|
||||
|
||||
#include "time_calls.h"
|
||||
|
||||
/*
|
||||
* The instruction data structure.
|
||||
*/
|
||||
struct bpf_insn {
|
||||
u_short code;
|
||||
u_char jt;
|
||||
u_char jf;
|
||||
bpf_int32 k;
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure for BIOCSETF.
|
||||
*/
|
||||
|
@ -122,14 +114,6 @@ struct bpf_hdr {
|
|||
u_short bh_hdrlen; /* length of bpf header (this struct
|
||||
plus alignment padding) */
|
||||
};
|
||||
/*
|
||||
* Because the structure above is not a multiple of 4 bytes, some compilers
|
||||
* will insist on inserting padding; hence, sizeof(struct bpf_hdr) won't work.
|
||||
* Only the kernel needs to know about it; applications use bh_hdrlen.
|
||||
*/
|
||||
#if defined(KERNEL) || defined(_KERNEL)
|
||||
#define SIZEOF_BPF_HDR 18
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Data-link level type codes.
|
||||
|
@ -304,15 +288,28 @@ struct bpf_hdr {
|
|||
#define BPF_TAX 0x00
|
||||
#define BPF_TXA 0x80
|
||||
|
||||
/*
|
||||
* The instruction data structure.
|
||||
*/
|
||||
struct bpf_insn {
|
||||
u_short code;
|
||||
u_char jt;
|
||||
u_char jf;
|
||||
bpf_int32 k;
|
||||
};
|
||||
/* TME instructions */
|
||||
#define BPF_TME 0x08
|
||||
|
||||
#define BPF_LOOKUP 0x90
|
||||
#define BPF_EXECUTE 0xa0
|
||||
#define BPF_INIT 0xb0
|
||||
#define BPF_VALIDATE 0xc0
|
||||
#define BPF_SET_ACTIVE 0xd0
|
||||
#define BPF_RESET 0xe0
|
||||
#define BPF_SET_MEMORY 0x80
|
||||
#define BPF_GET_REGISTER_VALUE 0x70
|
||||
#define BPF_SET_REGISTER_VALUE 0x60
|
||||
#define BPF_SET_WORKING 0x50
|
||||
#define BPF_SET_ACTIVE_READ 0x40
|
||||
#define BPF_SET_AUTODELETION 0x30
|
||||
#define BPF_SEPARATION 0xff
|
||||
|
||||
#define BPF_MEM_EX_IMM 0xc0
|
||||
#define BPF_MEM_EX_IND 0xe0
|
||||
/*used for ST */
|
||||
#define BPF_MEM_EX 0xc0
|
||||
|
||||
|
||||
/*
|
||||
* Macros for insn array initializers.
|
||||
|
@ -320,35 +317,6 @@ struct bpf_insn {
|
|||
#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k }
|
||||
#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k }
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#if defined(BSD) && (defined(KERNEL) || defined(_KERNEL))
|
||||
/*
|
||||
* Systems based on non-BSD kernels don't have ifnet's (or they don't mean
|
||||
* anything if it is in <net/if.h>) and won't work like this.
|
||||
*/
|
||||
# if __STDC__
|
||||
extern void bpf_tap(struct ifnet *, u_char *, u_int);
|
||||
extern void bpf_mtap(struct ifnet *, struct mbuf *);
|
||||
extern void bpfattach(struct ifnet *, u_int, u_int);
|
||||
extern void bpfilterattach(int);
|
||||
# else
|
||||
extern void bpf_tap();
|
||||
extern void bpf_mtap();
|
||||
extern void bpfattach();
|
||||
extern void bpfilterattach();
|
||||
# endif /* __STDC__ */
|
||||
#endif /* BSD && (_KERNEL || KERNEL) */
|
||||
#if __STDC__
|
||||
extern int bpf_validate(struct bpf_insn *, int);
|
||||
extern u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int);
|
||||
#else
|
||||
extern int bpf_validate();
|
||||
extern u_int bpf_filter();
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST).
|
||||
*/
|
||||
|
|
|
@ -59,35 +59,12 @@
|
|||
@(#)bpf.c 7.5 (Berkeley) 7/15/91
|
||||
*/
|
||||
|
||||
#if !(defined(lint) || defined(KERNEL))
|
||||
static const char rcsid[] =
|
||||
"@(#) $Header: /cygdrive/c/RCVS/CVS/ReactOS/reactos/drivers/net/packet/win_bpf_filter.c,v 1.1 2002/06/19 15:43:15 robd Exp $ (LBL)";
|
||||
#endif
|
||||
|
||||
#ifndef WIN32
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include "tme.h"
|
||||
#include "win_bpf.h"
|
||||
|
||||
#define int32 bpf_int32
|
||||
#define u_int32 bpf_u_int32
|
||||
#include "debug.h"
|
||||
|
||||
|
||||
#ifndef LBL_ALIGN
|
||||
#if defined(sparc) || defined(mips) || defined(ibm032) || \
|
||||
defined(__alpha) || defined(__hpux)
|
||||
#define LBL_ALIGN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef LBL_ALIGN
|
||||
#ifndef WIN32
|
||||
#include <netinet/in.h>
|
||||
#endif
|
||||
#include "valid_insns.h"
|
||||
|
||||
#define EXTRACT_SHORT(p)\
|
||||
((u_short)\
|
||||
|
@ -98,29 +75,23 @@ static const char rcsid[] =
|
|||
(u_int32)*((u_char *)p+1)<<16|\
|
||||
(u_int32)*((u_char *)p+2)<<8|\
|
||||
(u_int32)*((u_char *)p+3)<<0)
|
||||
#endif
|
||||
|
||||
/** @ingroup NPF
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup NPF_code NPF functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*
|
||||
* Execute the filter program starting at pc on the packet p
|
||||
* wirelen is the length of the original packet
|
||||
* buflen is the amount of data present
|
||||
*/
|
||||
u_int bpf_filter(pc, p, wirelen, buflen)
|
||||
u_int bpf_filter(pc, p, wirelen, buflen,mem_ex,tme,time_ref)
|
||||
register struct bpf_insn *pc;
|
||||
register u_char *p;
|
||||
u_int wirelen;
|
||||
register u_int buflen;
|
||||
PMEM_TYPE mem_ex;
|
||||
PTME_CORE tme;
|
||||
struct time_conv *time_ref;
|
||||
|
||||
{
|
||||
register u_int32 A, X;
|
||||
register int k;
|
||||
u_int32 j,tmp;
|
||||
u_short tmp2;
|
||||
|
||||
int32 mem[BPF_MEMWORDS];
|
||||
|
||||
if (pc == 0)
|
||||
|
@ -225,6 +196,57 @@ u_int bpf_filter(pc, p, wirelen, buflen)
|
|||
X = mem[pc->k];
|
||||
continue;
|
||||
|
||||
/* LD NO PACKET INSTRUCTIONS */
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IMM|BPF_B:
|
||||
A= mem_ex->buffer[pc->k];
|
||||
continue;
|
||||
|
||||
case BPF_LDX|BPF_MEM_EX_IMM|BPF_B:
|
||||
X= mem_ex->buffer[pc->k];
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IMM|BPF_H:
|
||||
A = EXTRACT_SHORT(&mem_ex->buffer[pc->k]);
|
||||
continue;
|
||||
|
||||
case BPF_LDX|BPF_MEM_EX_IMM|BPF_H:
|
||||
X = EXTRACT_SHORT(&mem_ex->buffer[pc->k]);
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IMM|BPF_W:
|
||||
A = EXTRACT_LONG(&mem_ex->buffer[pc->k]);
|
||||
continue;
|
||||
|
||||
case BPF_LDX|BPF_MEM_EX_IMM|BPF_W:
|
||||
X = EXTRACT_LONG(&mem_ex->buffer[pc->k]);
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IND|BPF_B:
|
||||
k = X + pc->k;
|
||||
if ((int32)k>= (int32)mem_ex->size) {
|
||||
return 0;
|
||||
}
|
||||
A= mem_ex->buffer[k];
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IND|BPF_H:
|
||||
k = X + pc->k;
|
||||
if ((int32)(k+1)>= (int32)mem_ex->size) {
|
||||
return 0;
|
||||
}
|
||||
A=EXTRACT_SHORT((uint32*)&mem_ex->buffer[k]);
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IND|BPF_W:
|
||||
k = X + pc->k;
|
||||
if ((int32)(k+3)>= (int32)mem_ex->size) {
|
||||
return 0;
|
||||
}
|
||||
A=EXTRACT_LONG((uint32*)&mem_ex->buffer[k]);
|
||||
continue;
|
||||
/* END LD NO PACKET INSTRUCTIONS */
|
||||
|
||||
case BPF_ST:
|
||||
mem[pc->k] = A;
|
||||
continue;
|
||||
|
@ -233,6 +255,49 @@ u_int bpf_filter(pc, p, wirelen, buflen)
|
|||
mem[pc->k] = X;
|
||||
continue;
|
||||
|
||||
/* STORE INSTRUCTIONS */
|
||||
case BPF_ST|BPF_MEM_EX_IMM|BPF_B:
|
||||
mem_ex->buffer[pc->k]=(uint8)A;
|
||||
continue;
|
||||
|
||||
case BPF_STX|BPF_MEM_EX_IMM|BPF_B:
|
||||
mem_ex->buffer[pc->k]=(uint8)X;
|
||||
continue;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IMM|BPF_W:
|
||||
tmp=A;
|
||||
*(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp);
|
||||
continue;
|
||||
|
||||
case BPF_STX|BPF_MEM_EX_IMM|BPF_W:
|
||||
tmp=X;
|
||||
*(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp);
|
||||
continue;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IMM|BPF_H:
|
||||
tmp2=(uint16)A;
|
||||
*(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2);
|
||||
continue;
|
||||
|
||||
case BPF_STX|BPF_MEM_EX_IMM|BPF_H:
|
||||
tmp2=(uint16)X;
|
||||
*(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2);
|
||||
continue;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IND|BPF_B:
|
||||
mem_ex->buffer[pc->k+X]=(uint8)A;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IND|BPF_W:
|
||||
tmp=A;
|
||||
*(uint32*)&mem_ex->buffer[pc->k+X]=EXTRACT_LONG(&tmp);
|
||||
continue;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IND|BPF_H:
|
||||
tmp2=(uint16)A;
|
||||
*(uint16*)&mem_ex->buffer[pc->k+X]=EXTRACT_SHORT(&tmp2);
|
||||
continue;
|
||||
/* END STORE INSTRUCTIONS */
|
||||
|
||||
case BPF_JMP|BPF_JA:
|
||||
pc += pc->k;
|
||||
continue;
|
||||
|
@ -346,30 +411,59 @@ u_int bpf_filter(pc, p, wirelen, buflen)
|
|||
case BPF_MISC|BPF_TXA:
|
||||
A = X;
|
||||
continue;
|
||||
|
||||
/* TME INSTRUCTIONS */
|
||||
case BPF_MISC|BPF_TME|BPF_LOOKUP:
|
||||
j=lookup_frontend(mem_ex,tme,pc->k,time_ref);
|
||||
if (j==TME_ERROR)
|
||||
return 0;
|
||||
pc += (j == TME_TRUE) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_EXECUTE:
|
||||
if (execute_frontend(mem_ex,tme,wirelen,pc->k)==TME_ERROR)
|
||||
return 0;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_SET_ACTIVE:
|
||||
if (set_active_tme_block(tme,pc->k)==TME_ERROR)
|
||||
return 0;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE:
|
||||
if (get_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,&j)==TME_ERROR)
|
||||
return 0;
|
||||
A=j;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE:
|
||||
if (set_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,A,FALSE)==TME_ERROR)
|
||||
return 0;
|
||||
continue;
|
||||
/* END TME INSTRUCTIONS */
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* Execute the filter program starting at pc on the packet whose header is
|
||||
* pointed by p and whose data is pointed by pd.
|
||||
* headersize is the size of the the header
|
||||
* wirelen is the length of the original packet
|
||||
* buflen is the amount of data present
|
||||
*/
|
||||
|
||||
u_int bpf_filter_with_2_buffers(pc, p, pd, headersize, wirelen, buflen)
|
||||
u_int bpf_filter_with_2_buffers(pc, p, pd, headersize, wirelen, buflen, mem_ex,tme,time_ref)
|
||||
register struct bpf_insn *pc;
|
||||
register u_char *p;
|
||||
register u_char *pd;
|
||||
register int headersize;
|
||||
u_int wirelen;
|
||||
register u_int buflen;
|
||||
PMEM_TYPE mem_ex;
|
||||
PTME_CORE tme;
|
||||
struct time_conv *time_ref;
|
||||
{
|
||||
register u_int32 A, X;
|
||||
register int k;
|
||||
int32 mem[BPF_MEMWORDS];
|
||||
u_int32 j,tmp;
|
||||
u_short tmp2;
|
||||
|
||||
if (pc == 0)
|
||||
/*
|
||||
|
@ -538,6 +632,57 @@ u_int bpf_filter_with_2_buffers(pc, p, pd, headersize, wirelen, buflen)
|
|||
X = mem[pc->k];
|
||||
continue;
|
||||
|
||||
/* LD NO PACKET INSTRUCTIONS */
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IMM|BPF_B:
|
||||
A= mem_ex->buffer[pc->k];
|
||||
continue;
|
||||
|
||||
case BPF_LDX|BPF_MEM_EX_IMM|BPF_B:
|
||||
X= mem_ex->buffer[pc->k];
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IMM|BPF_H:
|
||||
A = EXTRACT_SHORT(&mem_ex->buffer[pc->k]);
|
||||
continue;
|
||||
|
||||
case BPF_LDX|BPF_MEM_EX_IMM|BPF_H:
|
||||
X = EXTRACT_SHORT(&mem_ex->buffer[pc->k]);
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IMM|BPF_W:
|
||||
A = EXTRACT_LONG(&mem_ex->buffer[pc->k]);
|
||||
continue;
|
||||
|
||||
case BPF_LDX|BPF_MEM_EX_IMM|BPF_W:
|
||||
X = EXTRACT_LONG(&mem_ex->buffer[pc->k]);
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IND|BPF_B:
|
||||
k = X + pc->k;
|
||||
if ((int32)k>= (int32)mem_ex->size) {
|
||||
return 0;
|
||||
}
|
||||
A= mem_ex->buffer[k];
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IND|BPF_H:
|
||||
k = X + pc->k;
|
||||
if ((int32)(k+1)>= (int32)mem_ex->size) {
|
||||
return 0;
|
||||
}
|
||||
A=EXTRACT_SHORT((uint32*)&mem_ex->buffer[k]);
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IND|BPF_W:
|
||||
k = X + pc->k;
|
||||
if ((int32)(k+3)>= (int32)mem_ex->size) {
|
||||
return 0;
|
||||
}
|
||||
A=EXTRACT_LONG((uint32*)&mem_ex->buffer[k]);
|
||||
continue;
|
||||
/* END LD NO PACKET INSTRUCTIONS */
|
||||
|
||||
case BPF_ST:
|
||||
mem[pc->k] = A;
|
||||
continue;
|
||||
|
@ -546,6 +691,52 @@ u_int bpf_filter_with_2_buffers(pc, p, pd, headersize, wirelen, buflen)
|
|||
mem[pc->k] = X;
|
||||
continue;
|
||||
|
||||
|
||||
/* STORE INSTRUCTIONS */
|
||||
case BPF_ST|BPF_MEM_EX_IMM|BPF_B:
|
||||
mem_ex->buffer[pc->k]=(uint8)A;
|
||||
continue;
|
||||
|
||||
case BPF_STX|BPF_MEM_EX_IMM|BPF_B:
|
||||
mem_ex->buffer[pc->k]=(uint8)X;
|
||||
continue;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IMM|BPF_W:
|
||||
tmp=A;
|
||||
*(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp);
|
||||
continue;
|
||||
|
||||
case BPF_STX|BPF_MEM_EX_IMM|BPF_W:
|
||||
tmp=X;
|
||||
*(uint32*)&(mem_ex->buffer[pc->k])=EXTRACT_LONG(&tmp);
|
||||
continue;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IMM|BPF_H:
|
||||
tmp2=(uint16)A;
|
||||
*(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2);
|
||||
continue;
|
||||
|
||||
case BPF_STX|BPF_MEM_EX_IMM|BPF_H:
|
||||
tmp2=(uint16)X;
|
||||
*(uint16*)&mem_ex->buffer[pc->k]=EXTRACT_SHORT(&tmp2);
|
||||
continue;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IND|BPF_B:
|
||||
mem_ex->buffer[pc->k+X]=(uint8)A;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IND|BPF_W:
|
||||
tmp=A;
|
||||
*(uint32*)&mem_ex->buffer[pc->k+X]=EXTRACT_LONG(&tmp);
|
||||
continue;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IND|BPF_H:
|
||||
tmp2=(uint16)A;
|
||||
*(uint16*)&mem_ex->buffer[pc->k+X]=EXTRACT_SHORT(&tmp2);
|
||||
continue;
|
||||
/* END STORE INSTRUCTIONS */
|
||||
|
||||
|
||||
|
||||
case BPF_JMP|BPF_JA:
|
||||
pc += pc->k;
|
||||
continue;
|
||||
|
@ -659,37 +850,72 @@ u_int bpf_filter_with_2_buffers(pc, p, pd, headersize, wirelen, buflen)
|
|||
case BPF_MISC|BPF_TXA:
|
||||
A = X;
|
||||
continue;
|
||||
|
||||
/* TME INSTRUCTIONS */
|
||||
case BPF_MISC|BPF_TME|BPF_LOOKUP:
|
||||
j=lookup_frontend(mem_ex,tme,pc->k,time_ref);
|
||||
if (j==TME_ERROR)
|
||||
return 0;
|
||||
pc += (j == TME_TRUE) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_EXECUTE:
|
||||
if (execute_frontend(mem_ex,tme,wirelen,pc->k)==TME_ERROR)
|
||||
return 0;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_SET_ACTIVE:
|
||||
if (set_active_tme_block(tme,pc->k)==TME_ERROR)
|
||||
return 0;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE:
|
||||
if (get_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,&j)==TME_ERROR)
|
||||
return 0;
|
||||
A=j;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE:
|
||||
if (set_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,A,FALSE)==TME_ERROR)
|
||||
return 0;
|
||||
continue;
|
||||
/* END TME INSTRUCTIONS */
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Return true if the 'fcode' is a valid filter program.
|
||||
* The constraints are that each jump be forward and to a valid
|
||||
* code. The code must terminate with either an accept or reject.
|
||||
* 'valid' is an array for use by the routine (it must be at least
|
||||
* 'len' bytes long).
|
||||
*
|
||||
* The kernel needs to be able to verify an application's filter code.
|
||||
* Otherwise, a bogus program could easily crash the system.
|
||||
*/
|
||||
int
|
||||
bpf_validate(f, len)
|
||||
int32
|
||||
bpf_validate(f, len,mem_ex_size)
|
||||
struct bpf_insn *f;
|
||||
int len;
|
||||
int32 len;
|
||||
uint32 mem_ex_size;
|
||||
{
|
||||
register int i;
|
||||
register int32 i,j;
|
||||
register struct bpf_insn *p;
|
||||
|
||||
int32 flag;
|
||||
|
||||
for (i = 0; i < len; ++i) {
|
||||
/*
|
||||
* Check that that jumps are forward, and within
|
||||
* the code block.
|
||||
*/
|
||||
|
||||
p = &f[i];
|
||||
|
||||
IF_LOUD(DbgPrint("Validating program");)
|
||||
|
||||
flag=0;
|
||||
for(j=0;j<VALID_INSTRUCTIONS_LEN;j++)
|
||||
if (p->code==valid_instructions[j])
|
||||
flag=1;
|
||||
if (flag==0)
|
||||
return 0;
|
||||
|
||||
IF_LOUD(DbgPrint("Validating program: no unknown instructions");)
|
||||
|
||||
if (BPF_CLASS(p->code) == BPF_JMP) {
|
||||
register int from = i + 1;
|
||||
register int32 from = i + 1;
|
||||
|
||||
if (BPF_OP(p->code) == BPF_JA) {
|
||||
if (from + p->k >= len)
|
||||
|
@ -698,14 +924,33 @@ bpf_validate(f, len)
|
|||
else if (from + p->jt >= len || from + p->jf >= len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
IF_LOUD(DbgPrint("Validating program: no wrong JUMPS");)
|
||||
|
||||
/*
|
||||
* Check that memory operations use valid addresses.
|
||||
*/
|
||||
if ((BPF_CLASS(p->code) == BPF_ST ||
|
||||
if (((BPF_CLASS(p->code) == BPF_ST && ((p->code &BPF_MEM_EX_IMM)!=BPF_MEM_EX_IMM && (p->code &BPF_MEM_EX_IND)!=BPF_MEM_EX_IND)) ||
|
||||
(BPF_CLASS(p->code) == BPF_LD &&
|
||||
(p->code & 0xe0) == BPF_MEM)) &&
|
||||
(p->k >= BPF_MEMWORDS || p->k < 0))
|
||||
(p->k >= BPF_MEMWORDS || p->k < 0))
|
||||
return 0;
|
||||
|
||||
IF_LOUD(DbgPrint("Validating program: no wrong ST/LD memory locations");)
|
||||
|
||||
/*
|
||||
* Check if key stores use valid addresses
|
||||
*/
|
||||
if (BPF_CLASS(p->code) == BPF_ST && (p->code &BPF_MEM_EX_IMM)==BPF_MEM_EX_IMM)
|
||||
switch (BPF_SIZE(p->code))
|
||||
{
|
||||
case BPF_W: if (p->k<0 || p->k+3>=(int32)mem_ex_size) return 0;
|
||||
case BPF_H: if (p->k<0 || p->k+1>=(int32)mem_ex_size) return 0;
|
||||
case BPF_B: if (p->k<0 || p->k>=(int32)mem_ex_size) return 0;
|
||||
}
|
||||
|
||||
IF_LOUD(DbgPrint("Validating program: no wrong ST/LD mem_ex locations");)
|
||||
|
||||
/*
|
||||
* Check for constant division by 0.
|
||||
*/
|
||||
|
@ -713,4 +958,4 @@ bpf_validate(f, len)
|
|||
return 0;
|
||||
}
|
||||
return BPF_CLASS(f[len - 1].code) == BPF_RET;
|
||||
}
|
||||
}
|
569
reactos/drivers/net/packet/win_bpf_filter_init.c
Normal file
569
reactos/drivers/net/packet/win_bpf_filter_init.c
Normal file
|
@ -0,0 +1,569 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Portions copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* This code is derived from the Stanford/CMU enet packet filter,
|
||||
* (net/enet.c) distributed as part of 4.3BSD, and code contributed
|
||||
* to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
|
||||
* Berkeley Laboratory.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "tme.h"
|
||||
#include "win_bpf.h"
|
||||
|
||||
/*
|
||||
* Initialize the filter machine
|
||||
*/
|
||||
uint32 bpf_filter_init(register struct bpf_insn *pc, MEM_TYPE *mem_ex, TME_CORE *tme, struct time_conv *time_ref)
|
||||
{
|
||||
register uint32 A, X;
|
||||
int32 mem[BPF_MEMWORDS];
|
||||
register int32 k;
|
||||
uint32 *tmp;
|
||||
uint16 *tmp2;
|
||||
uint32 j;
|
||||
if (pc == 0)
|
||||
/*
|
||||
* No filter means accept all.
|
||||
*/
|
||||
return (uint32)-1;
|
||||
A = 0;
|
||||
X = 0;
|
||||
--pc;
|
||||
while (1) {
|
||||
++pc;
|
||||
switch (pc->code) {
|
||||
|
||||
default:
|
||||
return 0;
|
||||
|
||||
/* RET INSTRUCTIONS */
|
||||
case BPF_RET|BPF_K:
|
||||
return (uint32)pc->k;
|
||||
|
||||
case BPF_RET|BPF_A:
|
||||
return (uint32)A;
|
||||
/* END RET INSTRUCTIONS */
|
||||
|
||||
/* LD NO PACKET INSTRUCTIONS */
|
||||
case BPF_LD|BPF_IMM:
|
||||
A = pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_LDX|BPF_IMM:
|
||||
X = pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM:
|
||||
A = mem[pc->k];
|
||||
continue;
|
||||
|
||||
case BPF_LDX|BPF_MEM:
|
||||
X = mem[pc->k];
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IMM|BPF_B:
|
||||
A= mem_ex->buffer[pc->k];
|
||||
continue;
|
||||
|
||||
case BPF_LDX|BPF_MEM_EX_IMM|BPF_B:
|
||||
X= mem_ex->buffer[pc->k];
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IMM|BPF_H:
|
||||
tmp2=(uint16*)&mem_ex->buffer[pc->k];
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
mov ebx,tmp2
|
||||
xor eax, eax
|
||||
mov ax, [ebx]
|
||||
bswap eax
|
||||
mov A, eax
|
||||
pop ebx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
continue;
|
||||
|
||||
case BPF_LDX|BPF_MEM_EX_IMM|BPF_H:
|
||||
tmp2=(uint16*)&mem_ex->buffer[pc->k];
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
mov ebx,tmp2
|
||||
xor eax, eax
|
||||
mov ax, [ebx]
|
||||
bswap eax
|
||||
mov X, eax
|
||||
pop ebx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IMM|BPF_W:
|
||||
tmp=(uint32*)&mem_ex->buffer[pc->k];
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
mov ebx,tmp
|
||||
mov eax, [ebx]
|
||||
bswap eax
|
||||
mov A, eax
|
||||
pop ebx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
continue;
|
||||
|
||||
case BPF_LDX|BPF_MEM_EX_IMM|BPF_W:
|
||||
tmp=(uint32*)&mem_ex->buffer[pc->k];
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
mov ebx,tmp
|
||||
mov eax, [ebx]
|
||||
bswap eax
|
||||
mov X, eax
|
||||
pop ebx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IND|BPF_B:
|
||||
k = X + pc->k;
|
||||
if ((int32)k>= (int32)mem_ex->size) {
|
||||
return 0;
|
||||
}
|
||||
A= mem_ex->buffer[k];
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IND|BPF_H:
|
||||
k = X + pc->k;
|
||||
if ((int32)(k+1)>= (int32)mem_ex->size) {
|
||||
return 0;
|
||||
}
|
||||
tmp2=(uint16*)&mem_ex->buffer[k];
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
mov ebx,tmp2
|
||||
xor eax, eax
|
||||
mov ax, [ebx]
|
||||
bswap eax
|
||||
mov A, eax
|
||||
pop ebx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
continue;
|
||||
|
||||
case BPF_LD|BPF_MEM_EX_IND|BPF_W:
|
||||
k = X + pc->k;
|
||||
if ((int32)(k+3)>= (int32)mem_ex->size) {
|
||||
return 0;
|
||||
}
|
||||
tmp=(uint32*)&mem_ex->buffer[k];
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
mov ebx,tmp
|
||||
mov eax, [ebx]
|
||||
bswap eax
|
||||
mov A, eax
|
||||
pop ebx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
continue;
|
||||
/* END LD NO PACKET INSTRUCTIONS */
|
||||
|
||||
/* STORE INSTRUCTIONS */
|
||||
case BPF_ST:
|
||||
mem[pc->k] = A;
|
||||
continue;
|
||||
|
||||
case BPF_STX:
|
||||
mem[pc->k] = X;
|
||||
continue;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IMM|BPF_B:
|
||||
mem_ex->buffer[pc->k]=(uint8)A;
|
||||
continue;
|
||||
|
||||
case BPF_STX|BPF_MEM_EX_IMM|BPF_B:
|
||||
mem_ex->buffer[pc->k]=(uint8)X;
|
||||
continue;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IMM|BPF_W:
|
||||
tmp=(uint32*)&mem_ex->buffer[pc->k];
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
mov ebx, tmp
|
||||
mov eax, A
|
||||
bswap eax
|
||||
mov [ebx], eax
|
||||
pop ebx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
continue;
|
||||
|
||||
case BPF_STX|BPF_MEM_EX_IMM|BPF_W:
|
||||
tmp=(uint32*)&mem_ex->buffer[pc->k];
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
mov ebx, tmp
|
||||
mov eax, X
|
||||
bswap eax
|
||||
mov [ebx], eax
|
||||
pop ebx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
continue;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IMM|BPF_H:
|
||||
tmp2=(uint16*)&mem_ex->buffer[pc->k];
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
mov ebx, tmp2
|
||||
mov eax, A
|
||||
xchg ah, al
|
||||
mov [ebx], ax
|
||||
pop ebx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
continue;
|
||||
|
||||
case BPF_STX|BPF_MEM_EX_IMM|BPF_H:
|
||||
tmp2=(uint16*)&mem_ex->buffer[pc->k];
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
mov ebx, tmp2
|
||||
mov eax, X
|
||||
xchg ah, al
|
||||
mov [ebx], ax
|
||||
pop ebx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
continue;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IND|BPF_B:
|
||||
mem_ex->buffer[pc->k+X]=(uint8)A;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IND|BPF_W:
|
||||
tmp=(uint32*)&mem_ex->buffer[pc->k+X];
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
mov ebx, tmp
|
||||
mov eax, A
|
||||
bswap eax
|
||||
mov [ebx], eax
|
||||
pop ebx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
continue;
|
||||
|
||||
case BPF_ST|BPF_MEM_EX_IND|BPF_H:
|
||||
tmp2=(uint16*)&mem_ex->buffer[pc->k+X];
|
||||
#ifndef __GNUC__
|
||||
__asm
|
||||
{
|
||||
push eax
|
||||
push ebx
|
||||
mov ebx, tmp2
|
||||
mov eax, A
|
||||
xchg ah, al
|
||||
mov [ebx], ax
|
||||
pop ebx
|
||||
pop eax
|
||||
}
|
||||
#else
|
||||
#endif
|
||||
continue;
|
||||
/* END STORE INSTRUCTIONS */
|
||||
|
||||
/* JUMP INSTRUCTIONS */
|
||||
case BPF_JMP|BPF_JA:
|
||||
pc += pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JGT|BPF_K:
|
||||
pc += ((int32)A > (int32)pc->k) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JGE|BPF_K:
|
||||
pc += ((int32)A >= (int32)pc->k) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JEQ|BPF_K:
|
||||
pc += ((int32)A == (int32)pc->k) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JSET|BPF_K:
|
||||
pc += (A & pc->k) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JGT|BPF_X:
|
||||
pc += (A > X) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JGE|BPF_X:
|
||||
pc += (A >= X) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JEQ|BPF_X:
|
||||
pc += (A == X) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_JMP|BPF_JSET|BPF_X:
|
||||
pc += (A & X) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
/* END JUMP INSTRUCTIONS */
|
||||
|
||||
/* ARITHMETIC INSTRUCTIONS */
|
||||
case BPF_ALU|BPF_ADD|BPF_X:
|
||||
A += X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_SUB|BPF_X:
|
||||
A -= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_MUL|BPF_X:
|
||||
A *= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_DIV|BPF_X:
|
||||
if (X == 0)
|
||||
return 0;
|
||||
A /= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_AND|BPF_X:
|
||||
A &= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_OR|BPF_X:
|
||||
A |= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_LSH|BPF_X:
|
||||
A <<= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_RSH|BPF_X:
|
||||
A >>= X;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_ADD|BPF_K:
|
||||
A += pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_SUB|BPF_K:
|
||||
A -= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_MUL|BPF_K:
|
||||
A *= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_DIV|BPF_K:
|
||||
A /= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_AND|BPF_K:
|
||||
A &= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_OR|BPF_K:
|
||||
A |= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_LSH|BPF_K:
|
||||
A <<= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_RSH|BPF_K:
|
||||
A >>= pc->k;
|
||||
continue;
|
||||
|
||||
case BPF_ALU|BPF_NEG:
|
||||
(int32)A = -((int32)A);
|
||||
continue;
|
||||
/* ARITHMETIC INSTRUCTIONS */
|
||||
|
||||
/* MISC INSTRUCTIONS */
|
||||
case BPF_MISC|BPF_TAX:
|
||||
X = A;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TXA:
|
||||
A = X;
|
||||
continue;
|
||||
/* END MISC INSTRUCTIONS */
|
||||
|
||||
/* TME INSTRUCTIONS */
|
||||
case BPF_MISC|BPF_TME|BPF_LOOKUP:
|
||||
j=lookup_frontend(mem_ex,tme,pc->k,time_ref);
|
||||
if (j==TME_ERROR)
|
||||
return 0;
|
||||
pc += (j == TME_TRUE) ? pc->jt : pc->jf;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_EXECUTE:
|
||||
if (execute_frontend(mem_ex,tme,0,pc->k)==TME_ERROR)
|
||||
return 0;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_INIT:
|
||||
if (init_tme_block(tme,pc->k)==TME_ERROR)
|
||||
return 0;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_VALIDATE:
|
||||
if (validate_tme_block(mem_ex,tme,A,pc->k)==TME_ERROR)
|
||||
return 0;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_SET_MEMORY:
|
||||
if (init_extended_memory(pc->k,mem_ex)==TME_ERROR)
|
||||
return 0;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_SET_ACTIVE:
|
||||
if (set_active_tme_block(tme,pc->k)==TME_ERROR)
|
||||
return 0;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_SET_ACTIVE_READ:
|
||||
if (set_active_tme_block(tme,pc->k)==TME_ERROR)
|
||||
return 0;
|
||||
continue;
|
||||
case BPF_MISC|BPF_TME|BPF_SET_WORKING:
|
||||
if ((pc->k<0)||(pc->k>=MAX_TME_DATA_BLOCKS))
|
||||
return 0;
|
||||
tme->working=pc->k;
|
||||
continue;
|
||||
|
||||
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_RESET:
|
||||
if (reset_tme(tme)==TME_ERROR)
|
||||
return 0;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_GET_REGISTER_VALUE:
|
||||
if (get_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,&j)==TME_ERROR)
|
||||
return 0;
|
||||
A=j;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_SET_REGISTER_VALUE:
|
||||
if (set_tme_block_register(&tme->block_data[tme->working],mem_ex,pc->k,A,TRUE)==TME_ERROR)
|
||||
return 0;
|
||||
continue;
|
||||
|
||||
case BPF_MISC|BPF_TME|BPF_SET_AUTODELETION:
|
||||
set_autodeletion(&tme->block_data[tme->working],pc->k);
|
||||
continue;
|
||||
|
||||
/* END TME INSTRUCTIONS */
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
31
reactos/drivers/net/packet/win_bpf_filter_init.h
Normal file
31
reactos/drivers/net/packet/win_bpf_filter_init.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2001
|
||||
* Politecnico di Torino. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that: (1) source code distributions
|
||||
* retain the above copyright notice and this paragraph in its entirety, (2)
|
||||
* distributions including binary code include the above copyright notice and
|
||||
* this paragraph in its entirety in the documentation or other materials
|
||||
* provided with the distribution, and (3) all advertising materials mentioning
|
||||
* features or use of this software display the following acknowledgement:
|
||||
* ``This product includes software developed by the Politecnico
|
||||
* di Torino, and its contributors.'' Neither the name of
|
||||
* the University nor the names of its contributors may be used to endorse
|
||||
* or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
#ifndef __FILTER_INIT
|
||||
#define __FILTER_INIT
|
||||
|
||||
#include "tme.h"
|
||||
|
||||
#define INIT_OK 1
|
||||
#define INIT_ERROR 0
|
||||
|
||||
uint32 bpf_filter_init(register struct bpf_insn *pc,MEM_TYPE *mem_ex, TME_CORE *tme, struct time_conv *time_ref);
|
||||
|
||||
#endif
|
|
@ -26,7 +26,6 @@
|
|||
#include "ndis.h"
|
||||
#else
|
||||
#include <ddk/ntddk.h>
|
||||
//#include <net/miniport.h>
|
||||
#include <net/ndis.h>
|
||||
#endif
|
||||
|
||||
|
@ -34,12 +33,10 @@
|
|||
#include "packet.h"
|
||||
|
||||
|
||||
|
||||
int nsent;
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
NTSTATUS STDCALL
|
||||
PacketWrite(
|
||||
NTSTATUS
|
||||
//STDCALL
|
||||
NPF_Write(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
)
|
||||
|
@ -59,9 +56,7 @@ PacketWrite(
|
|||
|
||||
Open=IrpSp->FileObject->FsContext;
|
||||
|
||||
//
|
||||
// Check the length of the packet to avoid to use an empty packet
|
||||
//
|
||||
if(IrpSp->Parameters.Write.Length==0)
|
||||
{
|
||||
Irp->IoStatus.Status = NDIS_STATUS_SUCCESS;
|
||||
|
@ -79,9 +74,7 @@ PacketWrite(
|
|||
|
||||
for(i=0;i<Open->Nwrites;i++){
|
||||
|
||||
//
|
||||
// Try to get a packet from our list of free ones
|
||||
//
|
||||
NdisAllocatePacket(
|
||||
&Status,
|
||||
&pPacket,
|
||||
|
@ -90,35 +83,30 @@ PacketWrite(
|
|||
|
||||
if (Status != NDIS_STATUS_SUCCESS) {
|
||||
|
||||
//
|
||||
// No free packets
|
||||
//
|
||||
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
IoCompleteRequest (Irp, IO_NO_INCREMENT);
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
// The packet has a buffer that needs not to be freed after every single write
|
||||
RESERVED(pPacket)->FreeBufAfterWrite = FALSE;
|
||||
|
||||
// Save the IRP associated with the packet
|
||||
RESERVED(pPacket)->Irp=Irp;
|
||||
|
||||
//
|
||||
// Attach the writes buffer to the packet
|
||||
//
|
||||
NdisChainBufferAtFront(pPacket,Irp->MdlAddress);
|
||||
|
||||
//
|
||||
// Call the MAC
|
||||
//
|
||||
|
||||
NdisSend(
|
||||
&Status,
|
||||
Open->AdapterHandle,
|
||||
pPacket);
|
||||
|
||||
if (Status != NDIS_STATUS_PENDING) {
|
||||
//
|
||||
// The send didn't pend so call the completion handler now
|
||||
//
|
||||
PacketSendComplete(
|
||||
NPF_SendComplete(
|
||||
Open,
|
||||
pPacket,
|
||||
Status
|
||||
|
@ -138,50 +126,207 @@ PacketWrite(
|
|||
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
VOID
|
||||
PacketSendComplete(
|
||||
IN NDIS_HANDLE ProtocolBindingContext,
|
||||
IN PNDIS_PACKET pPacket,
|
||||
IN NDIS_STATUS Status
|
||||
)
|
||||
|
||||
INT
|
||||
NPF_BufferedWrite(
|
||||
IN PIRP Irp,
|
||||
IN PCHAR UserBuff,
|
||||
IN ULONG UserBuffSize,
|
||||
BOOLEAN Sync)
|
||||
{
|
||||
PIRP Irp;
|
||||
PIO_STACK_LOCATION irpSp;
|
||||
POPEN_INSTANCE Open;
|
||||
|
||||
IF_LOUD(DbgPrint("Packet: SendComplete, BindingContext=%d\n",ProtocolBindingContext);)
|
||||
|
||||
Open= (POPEN_INSTANCE)ProtocolBindingContext;
|
||||
|
||||
if((Open->Nwrites-Open->Multiple_Write_Counter)%100==99)
|
||||
NdisSetEvent(&Open->WriteEvent);
|
||||
POPEN_INSTANCE Open;
|
||||
PIO_STACK_LOCATION IrpSp;
|
||||
PNDIS_PACKET pPacket;
|
||||
UINT i;
|
||||
NDIS_STATUS Status;
|
||||
LARGE_INTEGER StartTicks, CurTicks, TargetTicks;
|
||||
LARGE_INTEGER TimeFreq;
|
||||
struct timeval BufStartTime;
|
||||
struct sf_pkthdr *winpcap_hdr;
|
||||
PMDL TmpMdl;
|
||||
PCHAR CurPos;
|
||||
PCHAR EndOfUserBuff = UserBuff + UserBuffSize;
|
||||
|
||||
Open->Multiple_Write_Counter--;
|
||||
IF_LOUD(DbgPrint("NPF: BufferedWrite, UserBuff=%x, Size=%u\n", UserBuff, UserBuffSize);)
|
||||
|
||||
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
Irp=RESERVED(pPacket)->Irp;
|
||||
irpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
Open=IrpSp->FileObject->FsContext;
|
||||
|
||||
// Security check on the length of the user buffer
|
||||
if(UserBuff==0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Start from the first packet
|
||||
winpcap_hdr = (struct sf_pkthdr*)UserBuff;
|
||||
|
||||
// Retrieve the time references
|
||||
StartTicks = KeQueryPerformanceCounter(&TimeFreq);
|
||||
BufStartTime.tv_sec = winpcap_hdr->ts.tv_sec;
|
||||
BufStartTime.tv_usec = winpcap_hdr->ts.tv_usec;
|
||||
|
||||
// Chech the consistency of the user buffer
|
||||
if( (PCHAR)winpcap_hdr + winpcap_hdr->caplen + sizeof(struct sf_pkthdr) > EndOfUserBuff )
|
||||
{
|
||||
IF_LOUD(DbgPrint("Buffered Write: bogus packet buffer\n");)
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Save the current time stamp counter
|
||||
CurTicks = KeQueryPerformanceCounter(NULL);
|
||||
|
||||
// Main loop: send the buffer to the wire
|
||||
while( TRUE ){
|
||||
|
||||
if(winpcap_hdr->caplen ==0 || winpcap_hdr->caplen > 65536)
|
||||
{
|
||||
// Malformed header
|
||||
IF_LOUD(DbgPrint("NPF_BufferedWrite: malformed user buffer, aborting write.\n");)
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Allocate an MDL to map the packet data
|
||||
TmpMdl=IoAllocateMdl((PCHAR)winpcap_hdr + sizeof(struct sf_pkthdr),
|
||||
winpcap_hdr->caplen,
|
||||
FALSE,
|
||||
FALSE,
|
||||
NULL);
|
||||
|
||||
if (TmpMdl == NULL)
|
||||
{
|
||||
// Unable to map the memory: packet lost
|
||||
IF_LOUD(DbgPrint("NPF_BufferedWrite: unable to allocate the MDL.\n");)
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
MmBuildMdlForNonPagedPool(TmpMdl); // XXX can this line be removed?
|
||||
|
||||
// Allocate a packet from our free list
|
||||
NdisAllocatePacket( &Status, &pPacket, Open->PacketPool);
|
||||
|
||||
if (Status != NDIS_STATUS_SUCCESS) {
|
||||
// No free packets
|
||||
IF_LOUD(DbgPrint("NPF_BufferedWrite: no more free packets, returning.\n");)
|
||||
|
||||
return (PCHAR)winpcap_hdr - UserBuff;
|
||||
}
|
||||
|
||||
// The packet has a buffer that needs to be freed after every single write
|
||||
RESERVED(pPacket)->FreeBufAfterWrite = TRUE;
|
||||
|
||||
// Attach the MDL to the packet
|
||||
NdisChainBufferAtFront(pPacket,TmpMdl);
|
||||
|
||||
// Call the MAC
|
||||
NdisSend( &Status, Open->AdapterHandle, pPacket);
|
||||
|
||||
if (Status != NDIS_STATUS_PENDING) {
|
||||
// The send didn't pend so call the completion handler now
|
||||
NPF_SendComplete(
|
||||
Open,
|
||||
pPacket,
|
||||
Status
|
||||
);
|
||||
}
|
||||
|
||||
// Step to the next packet in the buffer
|
||||
(PCHAR)winpcap_hdr += winpcap_hdr->caplen + sizeof(struct sf_pkthdr);
|
||||
|
||||
// Check if the end of the user buffer has been reached
|
||||
if( (PCHAR)winpcap_hdr >= EndOfUserBuff )
|
||||
{
|
||||
IF_LOUD(DbgPrint("NPF_BufferedWrite: End of buffer.\n");)
|
||||
|
||||
return (PCHAR)winpcap_hdr - UserBuff;
|
||||
}
|
||||
|
||||
if( Sync ){
|
||||
|
||||
#if 0
|
||||
// Release the application if it has been blocked for approximately more than 1 seconds
|
||||
if( winpcap_hdr->ts.tv_sec - BufStartTime.tv_sec > 1 )
|
||||
{
|
||||
IF_LOUD(DbgPrint("NPF_BufferedWrite: timestamp elapsed, returning.\n");)
|
||||
|
||||
return (PCHAR)winpcap_hdr - UserBuff;
|
||||
}
|
||||
|
||||
// Calculate the time interval to wait before sending the next packet
|
||||
TargetTicks.QuadPart = StartTicks.QuadPart +
|
||||
(LONGLONG)((winpcap_hdr->ts.tv_sec - BufStartTime.tv_sec) * 1000000 +
|
||||
winpcap_hdr->ts.tv_usec - BufStartTime.tv_usec) *
|
||||
(TimeFreq.QuadPart) / 1000000;
|
||||
|
||||
// Wait until the time interval has elapsed
|
||||
while( CurTicks.QuadPart <= TargetTicks.QuadPart )
|
||||
CurTicks = KeQueryPerformanceCounter(NULL);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return (PCHAR)winpcap_hdr - UserBuff;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
VOID
|
||||
NPF_SendComplete(
|
||||
IN NDIS_HANDLE ProtocolBindingContext,
|
||||
IN PNDIS_PACKET pPacket,
|
||||
IN NDIS_STATUS Status
|
||||
)
|
||||
|
||||
{
|
||||
PIRP Irp;
|
||||
PIO_STACK_LOCATION irpSp;
|
||||
POPEN_INSTANCE Open;
|
||||
PMDL TmpMdl;
|
||||
|
||||
IF_LOUD(DbgPrint("NPF: SendComplete, BindingContext=%d\n",ProtocolBindingContext);)
|
||||
|
||||
Open= (POPEN_INSTANCE)ProtocolBindingContext;
|
||||
|
||||
if( RESERVED(pPacket)->FreeBufAfterWrite ){
|
||||
// Free the MDL associated with the packet
|
||||
NdisUnchainBufferAtFront(pPacket, &TmpMdl);
|
||||
IoFreeMdl(TmpMdl);
|
||||
}
|
||||
else{
|
||||
if((Open->Nwrites - Open->Multiple_Write_Counter) %100 == 99)
|
||||
NdisSetEvent(&Open->WriteEvent);
|
||||
|
||||
Open->Multiple_Write_Counter--;
|
||||
}
|
||||
|
||||
//
|
||||
// recyle the packet
|
||||
//
|
||||
NdisReinitializePacket(pPacket);
|
||||
|
||||
//
|
||||
// Put the packet back on the free list
|
||||
//
|
||||
NdisFreePacket(pPacket);
|
||||
|
||||
if(Open->Multiple_Write_Counter==0){
|
||||
//
|
||||
// wake the application
|
||||
//
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = irpSp->Parameters.Write.Length;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
if( !(RESERVED(pPacket)->FreeBufAfterWrite) ){
|
||||
if(Open->Multiple_Write_Counter==0){
|
||||
// Release the buffer and awake the application
|
||||
NdisUnchainBufferAtFront(pPacket, &TmpMdl);
|
||||
|
||||
Irp=RESERVED(pPacket)->Irp;
|
||||
irpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
Irp->IoStatus.Information = irpSp->Parameters.Write.Length;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue