windows-nt/Source/XPSP1/NT/net/tcpip/apis/iphlpapi/dll/fltapis.hxx

706 lines
14 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1995-1997 Microsoft Corporation
Module Name:
fltapis.hxx
Abstract:
Definitions for the WIN32 filter APIs
Author:
Arnold Miller (arnoldm) 24-Sept-1997
Revision History:
--*/
#ifndef _FLTAPIS_HXX
#define _FILTAPI_HXX
extern "C"
{
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <align.h>
#include <windows.h>
#include <ntioapi.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <winsock2.h>
#include <ntddip.h>
#include <ipfltdrv.h>
#include "iphlpapi.h"
#include "fltdefs.h"
#include <tchar.h>
}
#if 0
#ifdef DBG
#define DBG_BUFFER 4096
#ifdef __cplusplus
extern "C" {
#endif
inline
void __cdecl DbgPrintFunction(const TCHAR * format, ...)
{
va_list argptr;
// Don't mess up the LastError.
DWORD LastError = GetLastError();
TCHAR DbgBuffer[DBG_BUFFER] = TEXT("");
TCHAR * ptr;
va_start(argptr, format);
ptr = DbgBuffer + lstrlen(DbgBuffer);
_vstprintf(ptr, format, argptr);
OutputDebugString(DbgBuffer);
va_end(argptr);
// Don't mess up the LastError.
SetLastError(LastError);
}
#ifdef __cplusplus
}
#endif
#define _DBGPRINT(x) DbgPrintFunction x
#if i386
#define _DbgBreak() { __asm int 3 }
#else // !i386
#define _DbgBreak() DebugBreak()
#endif // i386
#define _DBGASSERT(x) \
if (!(x)) { \
_DBGPRINT(("Assertion!: %s, at %s line %d\n", #x, __FILE__, __LINE__)); \
_DbgBreak(); \
}
#else // !DBG
#define _DbgBreak()
#define _DBGPRINT(x)
#define _DBGASSERT(x)
#endif // DBG
#endif
DWORD
StartIpFilterDriver(VOID);
BOOL
ValidateIndex(DWORD dwIndex);
class PacketFilterInterface;
typedef PVOID INTERFACE_HANDLE;
typedef PVOID FILTER_HANDLE, *PFILTER_HANDLE;
#define SPIN_COUNT 1000
#define RESOURCE_SPIN_COUNT 500
#define HANDLE_INCREMENT 20
class HandleContainer
//
// A class to manage handles. It is designed to handle a modest number
// of handles.
//
{
private:
PVOID * _pTable;
DWORD _dwMaxHandle;
DWORD _dwHandlesInUse;
DWORD _dwNextHandle;
public:
HandleContainer( VOID )
{
_pTable = 0;
_dwMaxHandle = _dwHandlesInUse = _dwNextHandle = 0;
}
~HandleContainer( VOID )
{
delete _pTable;
}
DWORD
NewHandle(PVOID pPointer, PDWORD pdwHandle)
{
if(((3 * _dwMaxHandle) / 4) <= _dwHandlesInUse)
{
//
// table too full. Make it bigger
//
PVOID * pNewTable = new PVOID[_dwMaxHandle + HANDLE_INCREMENT];
if(!pNewTable)
{
return(GetLastError());
}
//
// got it. Copy old handles into new table and start scan
// at the beginning of the new space
//
if(_pTable)
{
memcpy(pNewTable, _pTable, _dwMaxHandle * sizeof(PVOID *));
}
memset(&pNewTable[_dwMaxHandle], 0, HANDLE_INCREMENT * sizeof(PVOID *));
_dwMaxHandle += HANDLE_INCREMENT;
delete _pTable;
_pTable = pNewTable;
}
//
// look for a handle
//
while(TRUE)
{
if(!_pTable[_dwNextHandle])
{
_pTable[_dwNextHandle] = pPointer;
*pdwHandle = ++_dwNextHandle;
_dwHandlesInUse++;
if(_dwNextHandle >= _dwMaxHandle)
{
_dwNextHandle = 0;
}
break;
}
_dwNextHandle++;
if(_dwNextHandle >= _dwMaxHandle)
{
_dwNextHandle = 0;
}
}
return(ERROR_SUCCESS);
}
DWORD
DeleteHandle( DWORD dwHandle)
{
DWORD err;
if((--dwHandle < _dwMaxHandle) && _pTable[dwHandle])
{
_pTable[dwHandle] = 0;
_dwHandlesInUse--;
err = ERROR_SUCCESS;
}
else
{
err = ERROR_INVALID_HANDLE;
}
return(err);
}
PVOID
FetchHandleValue( DWORD dwHandle)
{
if(--dwHandle < _dwMaxHandle)
{
return((PCHAR)_pTable[dwHandle]);
}
return(0);
}
};
//
// Filter class. This encapsulates all of the data structures
// and logic to deal with the creating and deleting interfaces.
// It also manages the handle to the driver.
//
class InterfaceContainer
{
private:
HANDLE _hDriver; // driver handle
RTL_RESOURCE _Resource;
CRITICAL_SECTION _csDriverLock;
DWORD _status;
NTSTATUS _ntStatus;
HandleContainer _hcHandles;
PFLOGGER _Log;
BOOL _Inited;
VOID
_AcquireShared( VOID )
{
RtlAcquireResourceShared(&_Resource, TRUE);
}
VOID
_AcquireExclusive( VOID )
{
RtlAcquireResourceExclusive(&_Resource, TRUE);
}
VOID
_Release( VOID )
{
RtlReleaseResource(&_Resource);
}
VOID
_InitResource()
{
RtlInitializeResource(&_Resource);
// SetCriticalSectionSpinCount(&_Resource.CriticalSection,
// RESOURCE_SPIN_COUNT);
}
VOID
_DestroyResource()
{
RtlDeleteResource(&_Resource);
}
VOID
_LockDriver( VOID )
{
EnterCriticalSection(&_csDriverLock);
}
VOID
_UnLockDriver( VOID )
{
LeaveCriticalSection(&_csDriverLock);
}
VOID
_OpenDriver();
VOID
_CloseDriver();
DWORD
_DriverReady()
{
if(!_hDriver)
{
_LockDriver();
if(!_hDriver)
{
_OpenDriver();
}
_UnLockDriver();
}
if(_hDriver != INVALID_HANDLE_VALUE)
{
return(ERROR_SUCCESS);
}
return(ERROR_NOT_READY);
}
public:
InterfaceContainer()
{
//InitInterfaceContainer();
_Inited = FALSE;
}
VOID
InitInterfaceContainer();
~InterfaceContainer()
{
UnInitInterfaceContainer();
}
VOID
UnInitInterfaceContainer()
{
if(_Inited)
{
_DestroyResource();
DeleteCriticalSection(&_csDriverLock);
_CloseDriver();
_Inited = FALSE;
}
}
DWORD
AddInterface(
DWORD dwName,
PFFORWARD_ACTION inAction,
PFFORWARD_ACTION outAction,
BOOL fUseLog,
BOOL fUnique,
INTERFACE_HANDLE *ppInterface);
DWORD
FindInterfaceAndRef(
INTERFACE_HANDLE pInterface,
PacketFilterInterface ** ppInterface);
VOID
Deref( VOID )
{
_Release();
}
DWORD
DeleteInterface(
INTERFACE_HANDLE pInterface);
VOID
AddressUpdateNotification();
DWORD
MakeLog( HANDLE hEvent );
DWORD
DeleteLog( VOID );
DWORD
SetLogBuffer(
PBYTE pbBuffer,
DWORD dwSize,
DWORD dwThreshold,
DWORD dwEntries,
PDWORD pdwLoggedEntries,
PDWORD pdwLostEntries,
PDWORD pdwSizeUsed);
DWORD
CoerceDriverError(NTSTATUS Status)
{
return(RtlNtStatusToDosError(Status));
}
};
//
// flags for PacketFilterInterface
//
#define PFI_FLAGS_BOUND 0x1
class PacketFilterInterface
{
private:
CRITICAL_SECTION _cs;
HANDLE _hDriver;
PVOID _pvDriverContext;
DWORD _dwFlags;
DWORD _err;
DWORD _dwEpoch; // bind epoch
DWORD
_CommonBind(PFBINDINGTYPE dwBindType, DWORD dwData, DWORD LinkData);
BOOL
_IsBound( VOID )
{
return((_dwFlags & PFI_FLAGS_BOUND) != 0);
}
VOID
_SetBound( VOID )
{
_dwFlags |= PFI_FLAGS_BOUND;
}
VOID
_ClearBound( VOID )
{
_dwFlags &= ~PFI_FLAGS_BOUND;
}
VOID
_Lock( VOID )
{
EnterCriticalSection(&_cs);
}
VOID
_UnLock( VOID )
{
LeaveCriticalSection(&_cs);
}
DWORD
_AddFilters(PFETYPE pfe,
DWORD cInFilters, PPF_FILTER_DESCRIPTOR pfiltIn,
DWORD cOutFilters, PPF_FILTER_DESCRIPTOR pfiltOut,
PFILTER_HANDLE pfHandle);
DWORD
_DeleteFiltersByFilter(PFETYPE pfe,
DWORD cInFilters, PPF_FILTER_DESCRIPTOR pfiltIn,
DWORD cOutFilters, PPF_FILTER_DESCRIPTOR pfiltOut);
PFILTER_DRIVER_SET_FILTERS
_SetFilterBlock(PFETYPE pfe,
DWORD cInFilters, PPF_FILTER_DESCRIPTOR pfiltIn,
DWORD cOutFilters, PPF_FILTER_DESCRIPTOR pfiltOut,
PDWORD pdwSize,
PFILTER_DESCRIPTOR2 * ppfdIn,
PFILTER_DESCRIPTOR2 * ppfdOut);
VOID
_FreeSetBlock(PFILTER_DRIVER_SET_FILTERS pSet)
{
delete (PBYTE)pSet;
}
VOID
_CopyFilterHandles(PFILTER_DESCRIPTOR2 pfd1,
PFILTER_DESCRIPTOR2 pfd2,
PFILTER_HANDLE pfHandle);
DWORD
_MarshallFilter(PFETYPE pfe,
PPF_FILTER_DESCRIPTOR pFilt,
PFILTER_INFOEX pInfo);
VOID
_MarshallCommonStats(PPF_INTERFACE_STATS ppfStats,
PPFGETINTERFACEPARAMETERS pfGetip)
{
memcpy(ppfStats, pfGetip, _IfBaseSize());
}
DWORD
_IpBaseSize( VOID )
{
return(sizeof(PFGETINTERFACEPARAMETERS) - sizeof(FILTER_STATS_EX));
}
DWORD
_IfBaseSize( VOID )
{
return(sizeof(PF_INTERFACE_STATS) - sizeof(PF_FILTER_STATS));
}
DWORD
_PfFilterSize( VOID )
{
//
// N.B. The 4 below is the number of addresses in
// the structure. If this changes, be careful
//
return((sizeof(PF_FILTER_STATS) + (4 * sizeof(DWORD))));
}
DWORD
_IpSizeFromifSize(DWORD dwSize)
{
DWORD dwTemp;
if(dwSize < _IfBaseSize())
{
return(dwSize);
}
dwTemp = dwSize - _IfBaseSize();
//
// compute # of filters
//
dwTemp /= _PfFilterSize();
dwTemp = _IpBaseSize() + (dwTemp * sizeof(FILTER_STATS_EX));
return(dwTemp);
}
DWORD
_IfSizeFromipSize(DWORD dwSize)
{
DWORD dwTemp;
if(dwSize <= _IpBaseSize())
{
return(dwSize);
}
dwTemp = (dwSize - _IpBaseSize()) / sizeof(FILTER_STATS_EX);
//
// dwTemp is the number of filters
//
dwTemp = _IfBaseSize() + (_PfFilterSize() * dwTemp);
return(dwTemp);
}
VOID
_MarshallStatFilter(PFILTER_STATS_EX pstat,
PPF_FILTER_STATS pfstats,
PDWORD * ppdwAddress);
public:
PacketFilterInterface(
HANDLE hDriver,
DWORD dwName,
PFLOGGER pfLog,
BOOL fUnique,
FORWARD_ACTION inAction,
FORWARD_ACTION outAction);
~PacketFilterInterface();
DWORD
BindByIndex(DWORD dwIndex, DWORD LinkAddress)
{
return(_CommonBind(PF_BIND_INTERFACEINDEX, dwIndex, LinkAddress));
}
DWORD
BindByAddress(DWORD dwAddress)
{
return(_CommonBind(PF_BIND_IPV4ADDRESS, dwAddress, 0));
}
DWORD
TestPacket(PacketFilterInterface * pIn,
PacketFilterInterface * pOut,
DWORD cBytes,
PBYTE pbPacket,
PPFFORWARD_ACTION ppAction);
DWORD
UnBindInterface( VOID );
DWORD
DeleteFiltersByHandle(DWORD cFilters, PFILTER_HANDLE pvHandles);
DWORD
DeleteFiltersByFilter(DWORD cInFilters, PPF_FILTER_DESCRIPTOR pfiltIn,
DWORD cOutFilters, PPF_FILTER_DESCRIPTOR pfiltOut)
{
return(
_DeleteFiltersByFilter(PFE_FILTER, cInFilters, pfiltIn,
cOutFilters, pfiltOut));
}
DWORD
AddFilters(DWORD cInFilters, PPF_FILTER_DESCRIPTOR pfiltIn,
DWORD cOutFilters, PPF_FILTER_DESCRIPTOR pfiltOut,
PFILTER_HANDLE pfHandle)
{
return(
_AddFilters(PFE_FILTER, cInFilters, pfiltIn,
cOutFilters, pfiltOut,
pfHandle));
}
DWORD
RebindFilters(PPF_LATEBIND_INFO pLateBindInfo);
DWORD
AddGlobalFilter(GLOBAL_FILTER gf);
DWORD
DeleteGlobalFilter(GLOBAL_FILTER gf);
DWORD
GetStatus( VOID )
{
return(_err);
}
DWORD
GetStatistics(
PPF_INTERFACE_STATS ppfStats,
PDWORD pdwBufferSize,
BOOL fResetCounters);
PVOID
GetDriverContext()
{
return(_pvDriverContext);
}
};
//
// Open the driver
//
inline
VOID
InterfaceContainer::_OpenDriver()
{
static BOOL bStarted = FALSE;
UNICODE_STRING nameString;
IO_STATUS_BLOCK ioStatusBlock;
OBJECT_ATTRIBUTES objectAttributes;
if (!bStarted) {
StartIpFilterDriver();
bStarted = TRUE;
}
RtlInitUnicodeString(&nameString,DD_IPFLTRDRVR_DEVICE_NAME);
InitializeObjectAttributes(&objectAttributes, &nameString,
OBJ_CASE_INSENSITIVE, NULL, NULL);
_status = NtCreateFile(&_hDriver,
SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
&objectAttributes,
&ioStatusBlock,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_OPEN_IF,
0,
NULL,
0);
if(!NT_SUCCESS(_status))
{
_hDriver = INVALID_HANDLE_VALUE;
}
}
inline
VOID
InterfaceContainer::_CloseDriver()
{
if(_hDriver && (_hDriver != INVALID_HANDLE_VALUE))
{
NtClose(_hDriver);
_hDriver = INVALID_HANDLE_VALUE;
}
}
#endif