355 lines
6 KiB
C
355 lines
6 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1999 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
pfd.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains code for a simple packet-filter driver
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Abolade Gbadegesin (aboladeg) 15-Aug-1999
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "precomp.h"
|
|||
|
#pragma hdrstop
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Device- and file-object for the IP driver
|
|||
|
//
|
|||
|
|
|||
|
extern PDEVICE_OBJECT IpDeviceObject = NULL;
|
|||
|
extern PFILE_OBJECT IpFileObject = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Device-object for the filter driver
|
|||
|
//
|
|||
|
|
|||
|
extern PDEVICE_OBJECT PfdDeviceObject = NULL;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// FUNCTION PROTOTYPES (alphabetically)
|
|||
|
//
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
DriverEntry(
|
|||
|
IN PDRIVER_OBJECT DriverObject,
|
|||
|
IN PUNICODE_STRING RegistryPath
|
|||
|
);
|
|||
|
|
|||
|
FORWARD_ACTION
|
|||
|
PfdFilterPacket(
|
|||
|
struct IPHeader UNALIGNED* Header,
|
|||
|
PUCHAR Packet,
|
|||
|
UINT PacketLength,
|
|||
|
UINT ReceivingInterfaceIndex,
|
|||
|
UINT SendingInterfaceIndex,
|
|||
|
IPAddr ReceivingLinkNextHop,
|
|||
|
IPAddr SendingLinkNextHop
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
PfdInitializeDriver(
|
|||
|
VOID
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
PfdSetFilterHook(
|
|||
|
BOOLEAN Install
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
PfdUnloadDriver(
|
|||
|
IN PDRIVER_OBJECT DriverObject
|
|||
|
);
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text(INIT, DriverEntry)
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
DriverEntry(
|
|||
|
IN PDRIVER_OBJECT DriverObject,
|
|||
|
IN PUNICODE_STRING RegistryPath
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Performs driver-initialization for the filter driver.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
STATUS_SUCCESS if initialization succeeded, error code otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
WCHAR DeviceName[] = DD_IP_PFD_DEVICE_NAME;
|
|||
|
UNICODE_STRING DeviceString;
|
|||
|
LONG i;
|
|||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|||
|
HANDLE ParametersKey;
|
|||
|
HANDLE ServiceKey;
|
|||
|
NTSTATUS status;
|
|||
|
UNICODE_STRING String;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
KdPrint(("DriverEntry\n"));
|
|||
|
|
|||
|
//
|
|||
|
// Create the device's object.
|
|||
|
//
|
|||
|
|
|||
|
RtlInitUnicodeString(&DeviceString, DeviceName);
|
|||
|
|
|||
|
status =
|
|||
|
IoCreateDevice(
|
|||
|
DriverObject,
|
|||
|
0,
|
|||
|
&DeviceString,
|
|||
|
FILE_DEVICE_NETWORK,
|
|||
|
FILE_DEVICE_SECURE_OPEN,
|
|||
|
FALSE,
|
|||
|
&PfdDeviceObject
|
|||
|
);
|
|||
|
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
KdPrint(("IoCreateDevice failed (0x%08X)\n", status));
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
DriverObject->DriverUnload = PfdUnloadDriver;
|
|||
|
DriverObject->DriverStartIo = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the driver's structures
|
|||
|
//
|
|||
|
|
|||
|
status = PfdInitializeDriver();
|
|||
|
|
|||
|
return status;
|
|||
|
|
|||
|
} // DriverEntry
|
|||
|
|
|||
|
|
|||
|
FORWARD_ACTION
|
|||
|
PfdFilterPacket(
|
|||
|
struct IPHeader UNALIGNED* Header,
|
|||
|
PUCHAR Packet,
|
|||
|
UINT PacketLength,
|
|||
|
UINT ReceivingInterfaceIndex,
|
|||
|
UINT SendingInterfaceIndex,
|
|||
|
IPAddr ReceivingLinkNextHop,
|
|||
|
IPAddr SendingLinkNextHop
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Invoked to determine the fate of each received packet.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
none used.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
FORWARD_ACTION - indicates whether to forward or drop the given packet.
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Invoked within the context of reception or transmission.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
KdPrint(("PfdFilterPacket\n"));
|
|||
|
return FORWARD;
|
|||
|
} // PfdFilterPacket
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
PfdInitializeDriver(
|
|||
|
VOID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Performs initialization of the driver's structures.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
none.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - success/error code.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|||
|
NTSTATUS status;
|
|||
|
UNICODE_STRING UnicodeString;
|
|||
|
|
|||
|
KdPrint(("PfdInitializeDriver\n"));
|
|||
|
|
|||
|
//
|
|||
|
// Obtain the IP driver device-object
|
|||
|
//
|
|||
|
|
|||
|
RtlInitUnicodeString(&UnicodeString, DD_IP_DEVICE_NAME);
|
|||
|
status =
|
|||
|
IoGetDeviceObjectPointer(
|
|||
|
&UnicodeString,
|
|||
|
SYNCHRONIZE|GENERIC_READ|GENERIC_WRITE,
|
|||
|
&IpFileObject,
|
|||
|
&IpDeviceObject
|
|||
|
);
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
KdPrint(("PfdInitializeDriver: error %X getting IP object\n", status));
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
ObReferenceObject(IpDeviceObject);
|
|||
|
|
|||
|
//
|
|||
|
// Install the filter-hook routine
|
|||
|
//
|
|||
|
|
|||
|
return PfdSetFilterHook(TRUE);
|
|||
|
|
|||
|
} // PfdInitializeDriver
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
PfdSetFilterHook(
|
|||
|
BOOLEAN Install
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is called to set (Install==TRUE) or clear (Install==FALSE) the
|
|||
|
value of the filter-callout function pointer in the IP driver.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Install - indicates whether to install or remove the hook.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NTSTATUS - indicates success/failure
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
The routine assumes the caller is executing at PASSIVE_LEVEL.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
IP_SET_FILTER_HOOK_INFO HookInfo;
|
|||
|
IO_STATUS_BLOCK IoStatus;
|
|||
|
PIRP Irp;
|
|||
|
KEVENT LocalEvent;
|
|||
|
NTSTATUS status;
|
|||
|
|
|||
|
KdPrint(("PfdSetFilterHook\n"));
|
|||
|
|
|||
|
//
|
|||
|
// Register (or deregister) as a filter driver
|
|||
|
//
|
|||
|
|
|||
|
HookInfo.FilterPtr = Install ? PfdFilterPacket : NULL;
|
|||
|
|
|||
|
KeInitializeEvent(&LocalEvent, SynchronizationEvent, FALSE);
|
|||
|
Irp =
|
|||
|
IoBuildDeviceIoControlRequest(
|
|||
|
IOCTL_IP_SET_FILTER_POINTER,
|
|||
|
IpDeviceObject,
|
|||
|
(PVOID)&HookInfo,
|
|||
|
sizeof(HookInfo),
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
FALSE,
|
|||
|
&LocalEvent,
|
|||
|
&IoStatus
|
|||
|
);
|
|||
|
|
|||
|
if (!Irp) {
|
|||
|
KdPrint(("PfdSetFilterHook: IoBuildDeviceIoControlRequest=0\n"));
|
|||
|
return STATUS_UNSUCCESSFUL;
|
|||
|
}
|
|||
|
|
|||
|
status = IoCallDriver(IpDeviceObject, Irp);
|
|||
|
if (status == STATUS_PENDING) {
|
|||
|
KeWaitForSingleObject(&LocalEvent, Executive, KernelMode, FALSE, NULL);
|
|||
|
status = IoStatus.Status;
|
|||
|
}
|
|||
|
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
KdPrint(("PfdSetFilterHook: SetFilterPointer=%x\n", status));
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
|
|||
|
} // PfdSetFilterHook
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
PfdUnloadDriver(
|
|||
|
IN PDRIVER_OBJECT DriverObject
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Performs cleanup for the filter-driver.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
DriverObject - reference to the module's driver-object
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
KdPrint(("PfdUnloadDriver\n"));
|
|||
|
|
|||
|
//
|
|||
|
// Stop translation and clear the periodic timer
|
|||
|
//
|
|||
|
|
|||
|
PfdSetFilterHook(FALSE);
|
|||
|
IoDeleteDevice(DriverObject->DeviceObject);
|
|||
|
|
|||
|
//
|
|||
|
// Release references to the IP device object
|
|||
|
//
|
|||
|
|
|||
|
ObDereferenceObject((PVOID)IpFileObject);
|
|||
|
ObDereferenceObject(IpDeviceObject);
|
|||
|
|
|||
|
} // PfdUnloadDriver
|
|||
|
|