/*
DrvFltIp.C
Author: your name
Last Updated: 2001-01-01/0101
This framework is generated by QuickSYS.
*/
#include <string.h>
#include <stdio.h>
#include <ntddk.h>
#include <ntddndis.h>
#include <pfhook.h>
#include "DrvFltIp.h"
#if DBG
#define dprintf DbgPrint
#else
#define dprintf(x)
#endif
NTSTATUS DrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
VOID DrvUnload(IN PDRIVER_OBJECT DriverObject);
NTSTATUS SetFilterFunction(PacketFilterExtensionPtr filterFunction);
NTSTATUS AddFilterToList(IPFilter *pf);
void ClearFilterList(void);
PF_FORWARD_ACTION cbFilterFunction(IN unsigned char *PacketHeader,IN unsigned char *Packet, IN unsigned int PacketLength, IN unsigned int RecvInterfaceIndex, IN unsigned int SendInterfaceIndex, IN unsigned long RecvLinkNextHop, IN unsigned long SendLinkNextHop);
#define NT_DEVICE_NAME L"\\Device\\DrvFltIp"
#define DOS_DEVICE_NAME L"\\DosDevices\\DrvFltIp"
struct filterList *first = NULL;
struct filterList *last = NULL;
/*++
Routine Description:
Installable driver initialization entry point.
This entry point is called directly by the I/O system.
Arguments:
DriverObject - pointer to the driver object
RegistryPath - pointer to a unicode string representing the path
to driver-specific key in the registry
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise
--*/
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
PDEVICE_OBJECT deviceObject = NULL;
NTSTATUS ntStatus;
UNICODE_STRING deviceNameUnicodeString;
UNICODE_STRING deviceLinkUnicodeString;
dprintf("DrvFltIp.SYS: entering DriverEntry\n");
//we have to create the device
RtlInitUnicodeString(&deviceNameUnicodeString, NT_DEVICE_NAME);
ntStatus = IoCreateDevice(DriverObject,
0,
&deviceNameUnicodeString,
FILE_DEVICE_DRVFLTIP,
0,
FALSE,
&deviceObject);
if ( NT_SUCCESS(ntStatus) )
{
// Create a symbolic link that Win32 apps can specify to gain access
// to this driver/device
RtlInitUnicodeString(&deviceLinkUnicodeString, DOS_DEVICE_NAME);
ntStatus = IoCreateSymbolicLink(&deviceLinkUnicodeString, &deviceNameUnicodeString);
if ( !NT_SUCCESS(ntStatus) )
{
dprintf("DrvFltIp.SYS: IoCreateSymbolicLink failed\n");
}
//
// Create dispatch points for device control, create, close.
//
DriverObject->MajorFunction[IRP_MJ_CREATE] =
DriverObject->MajorFunction[IRP_MJ_CLOSE] =
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DrvDispatch;
DriverObject->DriverUnload = DrvUnload;
}
if ( !NT_SUCCESS(ntStatus) )
{
dprintf("Error in initialization. Unloading...");
DrvUnload(DriverObject);
}
return ntStatus;
}
/*++
Routine Description:
Process the IRPs sent to this device.
Arguments:
DeviceObject - pointer to a device object
Irp - pointer to an I/O Request Packet
Return Value:
--*/
NTSTATUS DrvDispatch(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
PIO_STACK_LOCATION irpStack;
PVOID ioBuffer;
ULONG inputBufferLength;
ULONG outputBufferLength;
ULONG ioControlCode;
NTSTATUS ntStatus;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
// Get a pointer to the current location in the Irp. This is where
// the function codes and parameters are located.
irpStack = IoGetCurrentIrpStackLocation(Irp);
// Get the pointer to the input/output buffer and it's length
ioBuffer = Irp->AssociatedIrp.SystemBuffer;
inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
switch (irpStack->MajorFunction)
{
case IRP_MJ_CREATE:
dprintf("DrvFltIp.SYS: IRP_MJ_CREATE\n");
break;
case IRP_MJ_CLOSE:
dprintf("DrvFltIp.SYS: IRP_MJ_CLOSE\n");
break;
case IRP_MJ_DEVICE_CONTROL:
dprintf("DrvFltIp.SYS: IRP_MJ_DEVICE_CONTROL\n");
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
switch (ioControlCode)
{
// ioctl code to start filtering
case START_IP_HOOK:
{
SetFilterFunction(cbFilterFunction);
break;
}
// ioctl to stop filtering
case STOP_IP_HOOK:
{
SetFilterFunction(NULL);
break;
}
// ioctl to add a filter rule
case ADD_FILTER:
{
if(inputBufferLength == sizeof(IPFilter))
{
IPFilter *nf;
nf = (IPFilter *)ioBuffer;
AddFilterToList(nf);
}
break;
}
// ioctl to free filter rule list
case CLEAR_FILTER:
{
ClearFilterList();
break;
}
default:
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
dprintf("DrvFltIp.SYS: unknown IRP_MJ_DEVICE_CONTROL\n");
break;
}
break;
}
//
// DON'T get cute and try to use the status field of
// the irp in the return status. That IRP IS GONE as
// soon as you call IoCompleteRequest.
//
ntStatus = Irp->IoStatus.Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
//
// We never have pending operation so always return the status code.
//
return ntStatus;
}
/*++
Routine Description:
Free all the allocated resources, etc.
Arguments:
DriverObject - pointer to a driver object
Return Value:
--*/
VOID DrvUnload(IN PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING deviceLinkUnicodeString;
dprintf("DrvFltIp.SYS: Unloading\n");
SetFilterFunction(NULL);
// Free any resources
ClearFilterList();
// Delete the symbolic link
RtlInitUnicodeString(&deviceLinkUnicodeString, DOS_DEVICE_NAME);
IoDeleteSymbolicLink(&deviceLinkUnicodeString);
// Delete the device object
IoDeleteDevice(DriverObject->DeviceObject);
}
/*++
Routine Description:
Get a reference to IpFilterDriver so we will be able to install the filter
Arguments:
pDeviceObject - pointer to a pointer of device object
pFileObject - pointer to a pointer of file object
Return Value:
STATUS_SUCCESS if successful,
STATUS_UNSUCCESSFUL otherwise
--*/
NTSTATUS SetFilterFunction(PacketFilterExtensionPtr filterFunction)
{
NTSTATUS status = STATUS_SUCCESS, waitStatus=STATUS_SUCCESS;
UNICODE_STRING filterName;
PDEVICE_OBJECT ipDeviceObject=NULL;
PFILE_OBJECT ipFileObject=NULL;
PF_SET_EXTENSION_HOOK_INFO filterData;
KEVENT event;
IO_STATUS_BLOCK ioStatus;
PIRP irp;
dprintf("Getting pointer to IpFilterDriver\n");
//first of all, we have to get a pointer to IpFilterDriver Device
RtlInitUnicodeString(&filterName, DD_IPFLTRDRVR_DEVICE_NAME);
status = IoGetDeviceObjectPointer(&filterName,STANDARD_RIGHTS_ALL, &ipFileObject, &ipDeviceObject);
if(NT_SUCCESS(status))
{
//initialize the struct with functions parameters
filterData.ExtensionPointer = filterFunction;
//we need initialize the event used later by the IpFilterDriver to signal us
//when it finished its work
KeInitializeEvent(&event, NotificationEvent, FALSE);
//we build the irp needed to establish fitler function
irp = IoBuildDeviceIoControlRequest(IOCTL_PF_SET_EXTENSION_POINTER,
ipDeviceObject,
(PVOID) &filterData,
sizeof(PF_SET_EXTENSION_HOOK_I