|
|
/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
ntos\tdi\isn\flt\driver.c
Abstract: IPX Filter driver dispatch routines
Author:
Vadim Eydelman
Revision History:
--*/
#include "precomp.h"
PFILE_OBJECT RouterFile;
NTSTATUS IpxFltDispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp );
VOID IpxFltUnload( IN PDRIVER_OBJECT DriverObject );
VOID IpxFltCancel ( IN PDEVICE_OBJECT DeviceObject, IN PIRP irp ); /*++
D r i v e r E n t r y
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 status; UNICODE_STRING deviceNameUnicodeString;
IpxFltDbgPrint (DBG_IOCTLS, ("IpxFlt: Driver Entry.\n"));
RtlInitUnicodeString (&deviceNameUnicodeString, IPXFLT_NAME);
status = IoCreateDevice (DriverObject, 0, &deviceNameUnicodeString, FILE_DEVICE_IPXFLT, 0, FALSE, // Non-Exclusive
&deviceObject );
if (NT_SUCCESS(status)) { //
// Create dispatch points for device control, create, close.
//
DriverObject->MajorFunction[IRP_MJ_CREATE] = DriverObject->MajorFunction[IRP_MJ_CLEANUP] = DriverObject->MajorFunction[IRP_MJ_CLOSE] = DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IpxFltDispatch; DriverObject->DriverUnload = IpxFltUnload; status = BindToFwdDriver (KernelMode); if (NT_SUCCESS (status)) { RouterFile = NULL; return STATUS_SUCCESS; } else { IoDeleteDevice (DriverObject->DeviceObject); } } else IpxFltDbgPrint (DBG_IOCTLS|DBG_ERRORS, ("IpxFlt: Could not create device object.\n"));
return status; }
/*++
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 IpxFltDispatch( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { PIO_STACK_LOCATION IrpStack; PVOID inBuffer, outBuffer; ULONG inpBufLength; ULONG outBufLength; NTSTATUS status; KIRQL cancelIRQL; ULONG ulBytes;
ulBytes = 0; Irp->IoStatus.Information = 0; status = STATUS_SUCCESS;
//
// Get a pointer to the current location in the Irp. This is where
// the function codes and parameters are located.
//
IrpStack = IoGetCurrentIrpStackLocation(Irp);
switch (IrpStack->MajorFunction) { case IRP_MJ_CREATE: IpxFltDbgPrint (DBG_IOCTLS, ("IpxFlt: IRP_MJ_CREATE.\n")); break;
case IRP_MJ_CLOSE: IpxFltDbgPrint (DBG_IOCTLS, ("IpxFlt: IRP_MJ_CLOSE.\n")); if (IrpStack->FileObject == RouterFile) { DeleteTables (); RouterFile = NULL; } break;
case IRP_MJ_CLEANUP: IpxFltDbgPrint (DBG_IOCTLS, ("IpxFlt: IRP_MJ_CLEANUP.\n")); if (IrpStack->FileObject==RouterFile) { IoAcquireCancelSpinLock (&cancelIRQL); while (!IsListEmpty (&LogIrpQueue)) { PIRP irp = CONTAINING_RECORD (LogIrpQueue.Blink, IRP, Tail.Overlay.ListEntry); irp->Cancel = TRUE; irp->CancelIrql = cancelIRQL; irp->CancelRoutine = NULL; IpxFltCancel(DeviceObject, irp); IoAcquireCancelSpinLock (&cancelIRQL); } IoReleaseCancelSpinLock(cancelIRQL); } break;
case IRP_MJ_DEVICE_CONTROL: //
// Get the pointer to the input/output buffer and it's length
//
status = STATUS_INVALID_PARAMETER; inpBufLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; outBufLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; switch (IrpStack->Parameters.DeviceIoControl.IoControlCode&3) { case METHOD_BUFFERED: inBuffer = outBuffer = Irp->AssociatedIrp.SystemBuffer; break;
case METHOD_IN_DIRECT: case METHOD_OUT_DIRECT: inBuffer = Irp->AssociatedIrp.SystemBuffer; if (outBufLength>0) { outBuffer = MmGetSystemAddressForMdlSafe (Irp->MdlAddress, NormalPagePriority); if (outBuffer == NULL) { IpxFltDbgPrint (DBG_IOCTLS|DBG_ERRORS, ("IpxFlt: System out of PTE's.\n")); goto DispatchExit; } } else { outBuffer = NULL; } break; default: IpxFltDbgPrint (DBG_IOCTLS|DBG_ERRORS, ("IpxFlt: Unsupported io method.\n")); goto DispatchExit; }
if (IrpStack->FileObject==RouterFile) { switch (IrpStack->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_FLT_IF_SET_IN_FILTERS: IpxFltDbgPrint (DBG_IOCTLS, ("IpxFlt: IOCTL_FLT_IF_SET_IN_FILTERS.\n")); if ((inpBufLength==sizeof (FLT_IF_SET_PARAMS)) && (((PFLT_IF_SET_PARAMS)inBuffer)->FilterSize ==sizeof (IPX_TRAFFIC_FILTER_INFO))) status = SetInFilters ( ((PFLT_IF_SET_PARAMS)inBuffer)->InterfaceIndex, ((PFLT_IF_SET_PARAMS)inBuffer)->FilterAction, outBufLength, (PIPX_TRAFFIC_FILTER_INFO)outBuffer); break;
case IOCTL_FLT_IF_SET_OUT_FILTERS: IpxFltDbgPrint (DBG_IOCTLS, ("IpxFlt: IOCTL_FLT_IF_SET_OUT_FILTERS.\n")); if ((inpBufLength==sizeof (FLT_IF_SET_PARAMS)) && (((PFLT_IF_SET_PARAMS)inBuffer)->FilterSize ==sizeof (IPX_TRAFFIC_FILTER_INFO))) status = SetOutFilters ( ((PFLT_IF_SET_PARAMS)inBuffer)->InterfaceIndex, ((PFLT_IF_SET_PARAMS)inBuffer)->FilterAction, outBufLength, (PIPX_TRAFFIC_FILTER_INFO)outBuffer); break; case IOCTL_FLT_IF_RESET_IN_FILTERS: IpxFltDbgPrint (DBG_IOCTLS, ("IpxFlt: IOCTL_FLT_IF_RESET_IN_FILTERS.\n")); if ((inpBufLength==sizeof (ULONG)) && (outBufLength==0)) status = SetInFilters ( *((PULONG)inBuffer), IPX_TRAFFIC_FILTER_ACTION_DENY, 0, NULL); break; case IOCTL_FLT_IF_RESET_OUT_FILTERS: IpxFltDbgPrint (DBG_IOCTLS, ("IpxFlt: IOCTL_FLT_IF_RESET_OUT_FILTERS.\n")); if ((inpBufLength==sizeof (ULONG)) && (outBufLength==0)) status = SetOutFilters ( *((PULONG)inBuffer), IPX_TRAFFIC_FILTER_ACTION_DENY, 0, NULL); break; case IOCTL_FLT_IF_GET_IN_FILTERS: IpxFltDbgPrint (DBG_IOCTLS, ("IpxFlt: IOCTL_FLT_IF_GET_IN_FILTERS.\n")); if ((inpBufLength==sizeof (ULONG)) && (outBufLength>=sizeof (FLT_IF_GET_PARAMS))) { Irp->IoStatus.Information = outBufLength-sizeof (FLT_IF_GET_PARAMS); ulBytes = (ULONG)Irp->IoStatus.Information; status = GetInFilters ( *((PULONG)inBuffer), &((PFLT_IF_GET_PARAMS)outBuffer)->FilterAction, &((PFLT_IF_GET_PARAMS)outBuffer)->TotalSize, (PIPX_TRAFFIC_FILTER_INFO) ((PUCHAR)outBuffer+sizeof (FLT_IF_GET_PARAMS)), &ulBytes); Irp->IoStatus.Information = ulBytes; if (NT_SUCCESS (status)) { Irp->IoStatus.Information += sizeof (FLT_IF_GET_PARAMS); ((PFLT_IF_GET_PARAMS)outBuffer)->FilterSize = sizeof (IPX_TRAFFIC_FILTER_INFO); } else Irp->IoStatus.Information = 0; } break; case IOCTL_FLT_IF_GET_OUT_FILTERS: IpxFltDbgPrint (DBG_IOCTLS, ("IpxFlt: IOCTL_FLT_IF_GET_OUT_FILTERS.\n")); if ((inpBufLength==sizeof (ULONG)) && (outBufLength>=sizeof (FLT_IF_GET_PARAMS))) { Irp->IoStatus.Information = outBufLength-sizeof (FLT_IF_GET_PARAMS); ulBytes = (ULONG)Irp->IoStatus.Information; status = GetOutFilters ( *((PULONG)inBuffer), &((PFLT_IF_GET_PARAMS)outBuffer)->FilterAction, &((PFLT_IF_GET_PARAMS)outBuffer)->TotalSize, (PIPX_TRAFFIC_FILTER_INFO) ((PUCHAR)outBuffer+sizeof (FLT_IF_GET_PARAMS)), &ulBytes); Irp->IoStatus.Information = ulBytes; if (NT_SUCCESS (status)) { Irp->IoStatus.Information += sizeof (FLT_IF_GET_PARAMS); ((PFLT_IF_GET_PARAMS)outBuffer)->FilterSize = sizeof (IPX_TRAFFIC_FILTER_INFO); } else Irp->IoStatus.Information = 0; } break; case IOCTL_FLT_GET_LOGGED_PACKETS: IpxFltDbgPrint (DBG_PKTLOGS, ("IpxFlt: IOCTL_FLT_GET_LOGGED_PACKETS.\n")); Irp->IoStatus.Status = status = STATUS_PENDING; IoMarkIrpPending (Irp); IoAcquireCancelSpinLock (&cancelIRQL); InsertTailList (&LogIrpQueue, &Irp->Tail.Overlay.ListEntry); IoSetCancelRoutine (Irp, IpxFltCancel); if (LogIrpQueue.Flink!=&Irp->Tail.Overlay.ListEntry) { PIRP irp = CONTAINING_RECORD ( LogIrpQueue.Flink, IRP, Tail.Overlay.ListEntry); if (irp->IoStatus.Information>0) { RemoveEntryList (&irp->Tail.Overlay.ListEntry); IoSetCancelRoutine (irp, NULL); irp->IoStatus.Status = STATUS_SUCCESS; IoReleaseCancelSpinLock (cancelIRQL); IpxFltDbgPrint (DBG_PKTLOGS, ("IpxFlt: completing logging request" " with %d bytes of data.\n", irp->IoStatus.Information)); IoCompleteRequest (irp, IO_NO_INCREMENT); break; } } IoReleaseCancelSpinLock (cancelIRQL); break; default: IpxFltDbgPrint (DBG_IOCTLS|DBG_ERRORS, ("IpxFlt: Unsupported IOCTL %lx.\n", IrpStack->Parameters.DeviceIoControl.IoControlCode)); status = STATUS_INVALID_DEVICE_REQUEST; break; } } else if (RouterFile==NULL) { if (IrpStack->Parameters.DeviceIoControl.IoControlCode ==IOCTL_FLT_START) { IpxFltDbgPrint (DBG_IOCTLS, ("IpxFlt: IOCTL_FLT_START.\n")); status = InitializeTables (); if (NT_SUCCESS (status)) { RouterFile = IrpStack->FileObject; status = STATUS_SUCCESS; } } else { IpxFltDbgPrint (DBG_IOCTLS|DBG_ERRORS, ("IpxFlt: Unsupported IOCTL %lx (driver is not started yet)).\n", IrpStack->Parameters.DeviceIoControl.IoControlCode)); status = STATUS_INVALID_DEVICE_REQUEST; } } else { IpxFltDbgPrint (DBG_IOCTLS|DBG_ERRORS, ("IpxFlt: Unsupported IOCTL %lx from non-router client.\n", IrpStack->Parameters.DeviceIoControl.IoControlCode)); status = STATUS_INVALID_DEVICE_REQUEST; }
break; default: IpxFltDbgPrint (DBG_IOCTLS|DBG_ERRORS, ("IpxFlt: Unsupported function %lx.\n", IrpStack->MajorFunction)); status = STATUS_INVALID_DEVICE_REQUEST; break; }
DispatchExit: if (status!=STATUS_PENDING) { Irp->IoStatus.Status = status; if (NT_SUCCESS (status)) ; else IpxFltDbgPrint (DBG_IOCTLS|DBG_ERRORS, ("IpxFlt: Failed call with status %lx.\n", status)); IoCompleteRequest(Irp, IO_NO_INCREMENT); }
return status; }
/*++
Routine Description: Cleans up on driver unload
Arguments:
DriverObject - pointer to a driver object
Return Value:
--*/ VOID IpxFltUnload( IN PDRIVER_OBJECT DriverObject ) { IpxFltDbgPrint (DBG_IOCTLS, ("IpxFlt: Unloading\n")); if (RouterFile!=NULL) { DeleteTables (); RouterFile = NULL; } UnbindFromFwdDriver (KernelMode); IoDeleteDevice (DriverObject->DeviceObject); }
/*++
I p x F l t C a n c e l
Routine Description: Cancels specified IRP
Arguments: DeviceObject - forwarder device object irp - irp to cancel
Return Value: None --*/ VOID IpxFltCancel ( IN PDEVICE_OBJECT DeviceObject, IN PIRP irp ) { RemoveEntryList (&irp->Tail.Overlay.ListEntry); IoReleaseCancelSpinLock (irp->CancelIrql);
irp->IoStatus.Status = STATUS_CANCELLED; IpxFltDbgPrint(DBG_IOCTLS, ("IpxFlt: completing cancelled irp.\n")); IoCompleteRequest(irp, IO_NO_INCREMENT); }
|