mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1023 lines
28 KiB
1023 lines
28 KiB
/*******************************************************************/
|
|
/* Copyright(c) 1993 Microsoft Corporation */
|
|
/*******************************************************************/
|
|
|
|
//***
|
|
//
|
|
// Filename: driver.c
|
|
//
|
|
// Description: router driver entry point
|
|
//
|
|
// Author: Stefan Solomon (stefans) October 13, 1993.
|
|
//
|
|
// Revision History:
|
|
//
|
|
//***
|
|
|
|
#include <stdarg.h>
|
|
#include "rtdefs.h"
|
|
#include "driver.h"
|
|
|
|
#if DBG
|
|
ULONG RouterDebugLevel = DEF_DBG_LEVEL;
|
|
#else
|
|
ULONG RouterDebugLevel;
|
|
#endif
|
|
|
|
NTSTATUS
|
|
GetRouterParameters(PUNICODE_STRING);
|
|
|
|
NTSTATUS
|
|
RouterDispatch(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
VOID
|
|
RouterUnload(
|
|
IN PDRIVER_OBJECT DriverObject
|
|
);
|
|
|
|
NTSTATUS
|
|
RouterIoctl(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PVOID ioBuffer,
|
|
IN ULONG inputBufferLength,
|
|
IN ULONG outputBufferLength
|
|
);
|
|
|
|
USHORT dbgpktnr;
|
|
|
|
NTSTATUS
|
|
IoctlSnapRoutes(VOID);
|
|
|
|
NTSTATUS
|
|
IoctlGetNextRoute(PVOID iobufferp,
|
|
ULONG inbufflen,
|
|
ULONG outbufflen,
|
|
PULONG sizep);
|
|
|
|
NTSTATUS
|
|
IoctlCheckNetNumber(PVOID iobufferp,
|
|
ULONG inbufflen,
|
|
ULONG outbufflen,
|
|
PULONG bytestransfp);
|
|
|
|
NTSTATUS
|
|
IoctlShowNicInfo(PVOID iobufferp,
|
|
ULONG inbufflen,
|
|
ULONG outbufflen,
|
|
PULONG bytestransfp);
|
|
|
|
NTSTATUS
|
|
IoctlZeroNicStatistics(PVOID iobufferp,
|
|
ULONG inbufflen,
|
|
ULONG outbufflen,
|
|
PULONG bytestransfp);
|
|
|
|
NTSTATUS
|
|
IoctlShowMemStatistics(PVOID iobufferp,
|
|
ULONG inbufflen,
|
|
ULONG outbufflen,
|
|
PULONG bytestransfp);
|
|
|
|
NTSTATUS
|
|
IoctlGetWanInactivity(PVOID iobufferp,
|
|
ULONG inbufflen,
|
|
ULONG outbufflen,
|
|
PULONG bytestransfp);
|
|
|
|
NTSTATUS
|
|
IoctlSetWanGlobalNet(PVOID iobufferp,
|
|
ULONG inbufflen,
|
|
ULONG outbufflen,
|
|
PULONG bytestransfp);
|
|
|
|
NTSTATUS
|
|
IoctlDeleteWanGlobalAddress(PVOID iobufferp,
|
|
ULONG inbufflen,
|
|
ULONG outbufflen,
|
|
PULONG bytestransfp);
|
|
|
|
VOID
|
|
DeleteGlobalWanNet(VOID);
|
|
|
|
|
|
NTSTATUS
|
|
DriverEntry(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING RegistryPath
|
|
)
|
|
/*++
|
|
|
|
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
|
|
|
|
--*/
|
|
{
|
|
|
|
PDEVICE_OBJECT deviceObject = NULL;
|
|
NTSTATUS ntStatus;
|
|
WCHAR deviceNameBuffer[] = L"\\Device\\Ipxroute";
|
|
UNICODE_STRING deviceNameUnicodeString;
|
|
PIPX_INTERNAL_BIND_RIP_OUTPUT IpxBindBuffp = NULL;
|
|
|
|
RtPrint(DBG_INIT, ("IPXROUTER: Entering DriverEntry\n"));
|
|
|
|
//
|
|
// Create a non - EXCLUSIVE device object (more than 1 thread at a time
|
|
// can make requests to this device)
|
|
//
|
|
|
|
RtlInitUnicodeString (&deviceNameUnicodeString,
|
|
deviceNameBuffer);
|
|
|
|
ntStatus = IoCreateDevice (DriverObject,
|
|
0,
|
|
&deviceNameUnicodeString,
|
|
FILE_DEVICE_IPXROUTER,
|
|
0,
|
|
FALSE,
|
|
&deviceObject
|
|
);
|
|
|
|
if (NT_SUCCESS(ntStatus))
|
|
{
|
|
//
|
|
// Create dispatch points for device control, create, close.
|
|
//
|
|
|
|
DriverObject->MajorFunction[IRP_MJ_CREATE] =
|
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] =
|
|
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = RouterDispatch;
|
|
DriverObject->DriverUnload = RouterUnload;
|
|
|
|
}
|
|
else
|
|
{
|
|
RtPrint (DBG_INIT, ("IPXROUTER: IoCreateDevice failed\n"));
|
|
goto failure_exit;
|
|
}
|
|
|
|
// get registry configuration
|
|
ntStatus = GetRouterParameters(RegistryPath);
|
|
|
|
if(!NT_SUCCESS(ntStatus)) {
|
|
|
|
RtPrint (DBG_INIT, ("IPXROUTER: Error reading registry parameters\n"));
|
|
goto failure_exit;
|
|
}
|
|
|
|
// Bind to the ipx driver.
|
|
// If succesful, it will point the argument to a paged pool buffered with
|
|
// the Ipx driver output data. This buffer has to be freed after usage.
|
|
// The buffer is freed in the RouterInit routine.
|
|
ntStatus = BindToIpxDriver(&IpxBindBuffp);
|
|
|
|
if(!NT_SUCCESS(ntStatus)) {
|
|
|
|
RtPrint (DBG_INIT, ("IPXROUTER: Bind to Ipx driver failed\n"));
|
|
goto failure_exit;
|
|
}
|
|
|
|
// initialize the router
|
|
ntStatus = RouterInit(IpxBindBuffp);
|
|
|
|
if(!NT_SUCCESS(ntStatus)) {
|
|
|
|
RtPrint (DBG_INIT, ("IPXROUTER: Error initializing the router\n"));
|
|
goto failure_exit;
|
|
}
|
|
|
|
// Start the global timer
|
|
StartRtTimer();
|
|
|
|
// all initialization done
|
|
RouterInitialized = TRUE;
|
|
|
|
// Start the routing functionality
|
|
ntStatus = RouterStart();
|
|
|
|
if(!NT_SUCCESS(ntStatus)) {
|
|
|
|
RtPrint (DBG_INIT, ("IPXROUTER: Error starting the router\n"));
|
|
goto failure_exit;
|
|
}
|
|
|
|
// started OK
|
|
return STATUS_SUCCESS;
|
|
|
|
failure_exit:
|
|
|
|
IoDeleteDevice (DriverObject->DeviceObject);
|
|
return ntStatus;
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
RouterDispatch(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
)
|
|
/*++
|
|
|
|
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:
|
|
|
|
|
|
--*/
|
|
{
|
|
PIO_STACK_LOCATION irpStack;
|
|
PVOID ioBuffer;
|
|
ULONG inputBufferLength;
|
|
ULONG outputBufferLength;
|
|
ULONG ioControlCode;
|
|
NTSTATUS ntStatus;
|
|
|
|
|
|
//
|
|
// Init to default settings- we only expect 1 type of
|
|
// IOCTL to roll through here, all others an error.
|
|
//
|
|
|
|
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:
|
|
|
|
RtPrint(DBG_IOCTL, ("IPXROUTER: IRP_MJ_CREATE\n"));
|
|
dbgpktnr = 0x5000;
|
|
|
|
break;
|
|
|
|
case IRP_MJ_CLOSE:
|
|
|
|
RtPrint(DBG_IOCTL, ("IPXROUTER: IRP_MJ_CLOSE\n"));
|
|
|
|
break;
|
|
|
|
case IRP_MJ_DEVICE_CONTROL:
|
|
|
|
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
|
|
|
|
switch (ioControlCode)
|
|
{
|
|
|
|
case IOCTL_IPXROUTER_SNAPROUTES:
|
|
|
|
Irp->IoStatus.Status = IoctlSnapRoutes();
|
|
break;
|
|
|
|
case IOCTL_IPXROUTER_GETNEXTROUTE:
|
|
|
|
Irp->IoStatus.Status = IoctlGetNextRoute (
|
|
ioBuffer,
|
|
inputBufferLength,
|
|
outputBufferLength,
|
|
&Irp->IoStatus.Information
|
|
);
|
|
break;
|
|
|
|
case IOCTL_IPXROUTER_CHECKNETNUMBER:
|
|
|
|
Irp->IoStatus.Status = IoctlCheckNetNumber (
|
|
ioBuffer,
|
|
inputBufferLength,
|
|
outputBufferLength,
|
|
&Irp->IoStatus.Information
|
|
);
|
|
break;
|
|
|
|
case IOCTL_IPXROUTER_SHOWNICINFO:
|
|
|
|
Irp->IoStatus.Status = IoctlShowNicInfo (
|
|
ioBuffer,
|
|
inputBufferLength,
|
|
outputBufferLength,
|
|
&Irp->IoStatus.Information
|
|
);
|
|
break;
|
|
|
|
case IOCTL_IPXROUTER_ZERONICSTATISTICS:
|
|
|
|
Irp->IoStatus.Status = IoctlZeroNicStatistics (
|
|
ioBuffer,
|
|
inputBufferLength,
|
|
outputBufferLength,
|
|
&Irp->IoStatus.Information
|
|
);
|
|
break;
|
|
|
|
case IOCTL_IPXROUTER_SHOWMEMSTATISTICS:
|
|
|
|
Irp->IoStatus.Status = IoctlShowMemStatistics (
|
|
ioBuffer,
|
|
inputBufferLength,
|
|
outputBufferLength,
|
|
&Irp->IoStatus.Information
|
|
);
|
|
break;
|
|
|
|
case IOCTL_IPXROUTER_GETWANINNACTIVITY:
|
|
|
|
Irp->IoStatus.Status = IoctlGetWanInactivity (
|
|
ioBuffer,
|
|
inputBufferLength,
|
|
outputBufferLength,
|
|
&Irp->IoStatus.Information
|
|
);
|
|
break;
|
|
|
|
case IOCTL_IPXROUTER_SETWANGLOBALADDRESS:
|
|
|
|
Irp->IoStatus.Status = IoctlSetWanGlobalNet(
|
|
ioBuffer,
|
|
inputBufferLength,
|
|
outputBufferLength,
|
|
&Irp->IoStatus.Information
|
|
);
|
|
break;
|
|
|
|
case IOCTL_IPXROUTER_DELETEWANGLOBALADDRESS:
|
|
|
|
Irp->IoStatus.Status = IoctlDeleteWanGlobalAddress(
|
|
ioBuffer,
|
|
inputBufferLength,
|
|
outputBufferLength,
|
|
&Irp->IoStatus.Information
|
|
);
|
|
break;
|
|
|
|
default:
|
|
|
|
RtPrint (DBG_INIT, ("IPXROUTER: unknown IRP_MJ_DEVICE_CONTROL\n"));
|
|
|
|
Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
RouterUnload(
|
|
IN PDRIVER_OBJECT DriverObject
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
DriverObject - pointer to a driver object
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
PNICCB niccbp;
|
|
USHORT i;
|
|
|
|
RouterUnloading = TRUE;
|
|
|
|
// stop the global timer
|
|
StopRtTimer();
|
|
|
|
// stop the rip timer. If the rip timer work item has already been scheduled
|
|
// wait until it completes
|
|
StopRipTimer();
|
|
|
|
// stop the routing functionality
|
|
RouterStop();
|
|
|
|
// close all nics
|
|
for(i=0; i<MaximumNicCount; i++) {
|
|
|
|
niccbp = NicCbPtrTab[i];
|
|
|
|
if(NicClose(niccbp,
|
|
SIGNAL_CLOSE_COMPLETION_EVENT) == NIC_CLOSE_PENDING) {
|
|
|
|
// wait for the close timer to detect complete closing
|
|
KeWaitForSingleObject(
|
|
&niccbp->NicClosedEvent,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
(PLARGE_INTEGER)NULL
|
|
);
|
|
}
|
|
}
|
|
|
|
// free resources allocated by all nics
|
|
for(i=0; i<MaximumNicCount; i++) {
|
|
|
|
niccbp = NicCbPtrTab[i];
|
|
|
|
if(NicFreeResources(niccbp) == NIC_RESOURCES_PENDING) {
|
|
|
|
// wait for the close timer to detect resources freed
|
|
KeWaitForSingleObject(
|
|
&niccbp->NicClosedEvent,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
(PLARGE_INTEGER)NULL
|
|
);
|
|
}
|
|
}
|
|
|
|
// at this point, all rcv pkts are returned to the pool and no new packets
|
|
// can be allocated.
|
|
// all send packets have been freed and no new send requests are permitted.
|
|
|
|
// unbind from the IPX driver
|
|
UnbindFromIpxDriver();
|
|
|
|
// free the allocated memory
|
|
DestroyNicCbs();
|
|
DestroyRcvPktPool();
|
|
|
|
//
|
|
// Delete the device object
|
|
//
|
|
|
|
RtPrint(DBG_UNLOAD, ("IPXROUTER: unloading\n"));
|
|
|
|
IoDeleteDevice (DriverObject->DeviceObject);
|
|
}
|
|
|
|
LIST_ENTRY displayroutes;
|
|
|
|
NTSTATUS
|
|
IoctlGetNextRoute(PVOID iobufferp,
|
|
ULONG inbufflen,
|
|
ULONG outbufflen,
|
|
PULONG bytestransfp)
|
|
{
|
|
PIPX_ROUTE_ENTRY rtep, drtep;
|
|
PLIST_ENTRY lep;
|
|
|
|
ASSERT(outbufflen >= sizeof(IPX_ROUTE_ENTRY));
|
|
|
|
if(IsListEmpty(&displayroutes)) {
|
|
|
|
return STATUS_NO_MORE_ENTRIES;
|
|
}
|
|
|
|
lep = RemoveHeadList(&displayroutes);
|
|
|
|
rtep = CONTAINING_RECORD(lep, IPX_ROUTE_ENTRY, PRIVATE.Linkage);
|
|
drtep = (PIPX_ROUTE_ENTRY)iobufferp;
|
|
|
|
*drtep = *rtep;
|
|
*bytestransfp = sizeof(IPX_ROUTE_ENTRY);
|
|
|
|
ExFreePool(rtep);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
IoctlSnapRoutes(VOID)
|
|
{
|
|
PIPX_ROUTE_ENTRY rtep, drtep;
|
|
UINT i;
|
|
KIRQL oldirql;
|
|
|
|
InitializeListHead(&displayroutes);
|
|
|
|
for(i=0; i<SegmentCount; i++) {
|
|
|
|
// LOCK THE ROUTING TABLE
|
|
ExAcquireSpinLock(&SegmentLocksTable[i], &oldirql);
|
|
|
|
if((rtep = IpxGetFirstRoute(i)) == NULL) {
|
|
|
|
// UNLOCK THE ROUTING TABLE
|
|
ExReleaseSpinLock(&SegmentLocksTable[i], oldirql);
|
|
|
|
continue;
|
|
}
|
|
|
|
drtep = ExAllocatePool(NonPagedPool, sizeof(IPX_ROUTE_ENTRY));
|
|
|
|
*drtep = *rtep;
|
|
|
|
InsertTailList(&displayroutes, &drtep->PRIVATE.Linkage);
|
|
|
|
while((rtep = IpxGetNextRoute(i)) != NULL) {
|
|
|
|
drtep = ExAllocatePool(NonPagedPool, sizeof(IPX_ROUTE_ENTRY));
|
|
*drtep = *rtep;
|
|
InsertTailList(&displayroutes, &drtep->PRIVATE.Linkage);
|
|
}
|
|
|
|
// UNLOCK THE ROUTING TABLE
|
|
ExReleaseSpinLock(&SegmentLocksTable[i], oldirql);
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
IoctlCheckNetNumber(PVOID iobufferp,
|
|
ULONG inbufflen,
|
|
ULONG outbufflen,
|
|
PULONG bytestransfp)
|
|
{
|
|
UINT seg;
|
|
UCHAR CheckNetwork[4];
|
|
KIRQL oldirql;
|
|
|
|
ASSERT(outbufflen >= sizeof(ULONG));
|
|
|
|
memcpy(CheckNetwork, iobufferp, 4);
|
|
|
|
// set the output to no-conflict
|
|
*(PULONG)iobufferp = 1;
|
|
|
|
seg = IpxGetSegment(CheckNetwork);
|
|
|
|
// LOCK THE ROUTING TABLE
|
|
ExAcquireSpinLock(&SegmentLocksTable[seg], &oldirql);
|
|
|
|
if(IpxGetRoute(seg, CheckNetwork)) {
|
|
|
|
*(PULONG)iobufferp = 0;
|
|
}
|
|
|
|
// UNLOCK THE ROUTING TABLE
|
|
ExReleaseSpinLock(&SegmentLocksTable[seg], oldirql);
|
|
|
|
*bytestransfp = sizeof(ULONG);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
IoctlShowNicInfo(PVOID iobufferp,
|
|
ULONG inbufflen,
|
|
ULONG outbufflen,
|
|
PULONG bytestransfp)
|
|
{
|
|
PNICCB niccbp;
|
|
USHORT index;
|
|
USHORT i;
|
|
PSHOW_NIC_INFO nisp;
|
|
|
|
ASSERT(outbufflen >= sizeof(SHOW_NIC_INFO));
|
|
|
|
index = *(PUSHORT)iobufferp;
|
|
|
|
for(i=0; i<MaximumNicCount; i++) {
|
|
|
|
niccbp=NicCbPtrTab[i];
|
|
|
|
if(niccbp->DeviceType == IPX_ROUTER_INVALID_DEVICE_TYPE) {
|
|
|
|
// skip the non configured nic
|
|
continue;
|
|
}
|
|
|
|
// configured nic
|
|
if(index--) {
|
|
|
|
// skip this
|
|
continue;
|
|
}
|
|
|
|
// configured nic and index == 0
|
|
nisp = (PSHOW_NIC_INFO)iobufferp;
|
|
|
|
nisp->NicId = niccbp->NicId;
|
|
|
|
if(niccbp->DeviceType == NdisMediumWan) {
|
|
|
|
nisp->DeviceType = SHOW_NIC_WAN;
|
|
}
|
|
else
|
|
{
|
|
nisp->DeviceType = SHOW_NIC_LAN;
|
|
}
|
|
|
|
nisp->NicState = niccbp->NicState;
|
|
memcpy(nisp->Network, niccbp->Network, 4);
|
|
memcpy(nisp->Node, niccbp->Node, 6);
|
|
nisp->TickCount = niccbp->TickCount;
|
|
nisp->StatBadReceived = niccbp->StatBadReceived;
|
|
nisp->StatRipReceived = niccbp->StatRipReceived;
|
|
nisp->StatRipSent = niccbp->StatRipSent;
|
|
nisp->StatRoutedReceived = niccbp->StatRoutedReceived;
|
|
nisp->StatRoutedSent = niccbp->StatRoutedSent;
|
|
nisp->StatType20Received = niccbp->StatType20Received;
|
|
nisp->StatType20Sent = niccbp->StatType20Sent;
|
|
|
|
*bytestransfp = sizeof(SHOW_NIC_INFO);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
return STATUS_NO_MORE_ENTRIES;
|
|
}
|
|
|
|
NTSTATUS
|
|
IoctlZeroNicStatistics(PVOID iobufferp,
|
|
ULONG inbufflen,
|
|
ULONG outbufflen,
|
|
PULONG bytestransfp)
|
|
{
|
|
PNICCB niccbp;
|
|
USHORT i;
|
|
|
|
for(i=0; i<MaximumNicCount; i++) {
|
|
|
|
niccbp=NicCbPtrTab[i];
|
|
|
|
if(niccbp->DeviceType == IPX_ROUTER_INVALID_DEVICE_TYPE) {
|
|
|
|
// skip the non configured nic
|
|
continue;
|
|
}
|
|
|
|
// configured nic
|
|
ZeroNicStatistics(niccbp);
|
|
}
|
|
|
|
StatMemPeakCount = 0;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
IoctlShowMemStatistics(PVOID iobufferp,
|
|
ULONG inbufflen,
|
|
ULONG outbufflen,
|
|
PULONG bytestransfp)
|
|
{
|
|
PSHOW_MEM_STAT smsp;
|
|
|
|
smsp = (PSHOW_MEM_STAT)iobufferp;
|
|
|
|
smsp->PeakPktAllocCount = StatMemPeakCount;
|
|
smsp->CurrentPktAllocCount = StatMemAllocCount;
|
|
smsp->CurrentPktPoolCount = RcvPktCount;
|
|
smsp->PacketSize = UlongMaxFrameSize * sizeof(ULONG);
|
|
|
|
*bytestransfp = sizeof(SHOW_MEM_STAT);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
IoctlGetWanInactivity(PVOID iobufferp,
|
|
ULONG inbufflen,
|
|
ULONG outbufflen,
|
|
PULONG bytestransfp)
|
|
{
|
|
PGET_WAN_INNACTIVITY pgwi;
|
|
PNICCB niccbp;
|
|
USHORT i;
|
|
|
|
pgwi = (PGET_WAN_INNACTIVITY)iobufferp;
|
|
|
|
// check that we have a valid NicId
|
|
if(pgwi->NicId == 0xFFFF) {
|
|
|
|
// get the valid NicId for this remote node
|
|
for(i=0; i<MaximumNicCount; i++) {
|
|
|
|
niccbp = NicCbPtrTab[i];
|
|
if((niccbp->DeviceType == NdisMediumWan) &&
|
|
(niccbp->NicState == NIC_ACTIVE)) {
|
|
|
|
// check if this is the one we look for
|
|
if(!memcmp(pgwi->RemoteNode, niccbp->RemoteNode, 6)) {
|
|
|
|
// this is the one
|
|
pgwi->NicId = niccbp->NicId;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// check that we have found the nic
|
|
if(pgwi->NicId == 0xFFFF) {
|
|
|
|
// ERROR: no nic coresponding to this remote node
|
|
goto WanInactivityExit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// check that we have a valid handle indeed
|
|
if(pgwi->NicId < MaximumNicCount) {
|
|
|
|
// Nic id looks valid
|
|
niccbp = NicCbPtrTab[pgwi->NicId];
|
|
|
|
if(memcmp(pgwi->RemoteNode, niccbp->RemoteNode, 6)) {
|
|
|
|
// ERROR: this nic id has a wrong remote node
|
|
// reset the nic id to indicate the error
|
|
pgwi->NicId = 0xFFFF;
|
|
|
|
goto WanInactivityExit;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// ERROR: wrong nic id -> too big
|
|
// reset the nicid to indicate the error
|
|
pgwi->NicId = 0xFFFF;
|
|
|
|
goto WanInactivityExit;
|
|
}
|
|
}
|
|
|
|
// we got the correct nic id
|
|
pgwi->WanInnactivityCount = IpxGetWanInactivity(niccbp->NicId);
|
|
|
|
WanInactivityExit:
|
|
|
|
*bytestransfp = sizeof(GET_WAN_INNACTIVITY);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
//***
|
|
//
|
|
// Function: IoctlSetWanGlobalNet
|
|
//
|
|
// Descr: Called by ipxcp when the dll gets loaded, if configured with
|
|
// global wan net option.
|
|
// It generates a net number using the last four bytes of the address of
|
|
// the first lan net, checks that the net number is unique and then adds it
|
|
// to the routing table and marks the route as wan global.
|
|
// Returns the wan global net number to the caller.
|
|
//
|
|
//***
|
|
|
|
NTSTATUS
|
|
IoctlSetWanGlobalNet(PVOID iobufferp,
|
|
ULONG inbufflen,
|
|
ULONG outbufflen,
|
|
PULONG bytestransfp)
|
|
{
|
|
UCHAR wnet[4]; // wan global net number
|
|
USHORT i;
|
|
PNICCB niccbp;
|
|
UINT seg;
|
|
KIRQL oldirql;
|
|
PIPX_ROUTE_ENTRY rtep;
|
|
PSET_WAN_GLOBAL_ADDRESS wgap;
|
|
BOOLEAN statconfig; // TRUE -> static net config
|
|
// FALSE -> dynamic net config
|
|
ULONG wnetnumber;
|
|
LARGE_INTEGER tickcount;
|
|
|
|
// check if we have already been called to configure the router for a WanGlobalNet.
|
|
// If this has hapened, clean up before seting the new wan global network number
|
|
DeleteGlobalWanNet();
|
|
|
|
// get the wnet desired value from the ioctl request
|
|
wgap = (PSET_WAN_GLOBAL_ADDRESS)iobufferp;
|
|
memcpy(wnet, wgap->WanGlobalNetwork, 4);
|
|
|
|
// assume success and set the final error code
|
|
wgap->ErrorCode = 0;
|
|
*bytestransfp = sizeof(SET_WAN_GLOBAL_ADDRESS);
|
|
|
|
// check if this is a static value or dynamic config is wanted
|
|
if(!memcmp(wnet, nulladdress, 4)) {
|
|
|
|
// wnet is null -> we are requested to make the address
|
|
// get the node address of the first LAN card and make the net address with its last
|
|
// four bytes
|
|
|
|
// Put the tick count value in case we don't find a LAN card !
|
|
KeQueryTickCount(&tickcount);
|
|
PUTULONG2LONG(wnet, tickcount.LowPart);
|
|
|
|
statconfig = FALSE;
|
|
|
|
for(i=0; i<MaximumNicCount; i++) {
|
|
|
|
niccbp = NicCbPtrTab[i];
|
|
|
|
if((niccbp->DeviceType != IPX_ROUTER_INVALID_DEVICE_TYPE) && // configured nic
|
|
(niccbp->DeviceType != NdisMediumWan)) { // LAN nic
|
|
|
|
memcpy(wnet, &niccbp->Node[2], 4);
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
// wnet is the number the user requests
|
|
statconfig = TRUE;
|
|
}
|
|
|
|
// Check that the static/dynamic wan global net nr is a unique net number
|
|
seg = IpxGetSegment(wnet);
|
|
|
|
// LOCK THE ROUTING TABLE
|
|
ExAcquireSpinLock(&SegmentLocksTable[seg], &oldirql);
|
|
|
|
while(IpxGetRoute(seg, wnet)) {
|
|
|
|
// the network number exists -> we are allowed to resolve the conflict only in
|
|
// the case we are configuring dynamically
|
|
if(!statconfig) {
|
|
|
|
// increment the number and try again
|
|
GETLONG2ULONG(&wnetnumber, wnet);
|
|
wnetnumber++;
|
|
PUTULONG2LONG(wnet, wnetnumber);
|
|
|
|
// UNLOCK THE ROUTING TABLE
|
|
ExReleaseSpinLock(&SegmentLocksTable[seg], oldirql);
|
|
|
|
seg = IpxGetSegment(wnet);
|
|
// RELOCK THE ROUTING TABLE
|
|
ExAcquireSpinLock(&SegmentLocksTable[seg], &oldirql);
|
|
}
|
|
else
|
|
{
|
|
// return and report the error
|
|
wgap->ErrorCode = ERROR_IPXCP_NETWORK_NUMBER_IN_USE;
|
|
|
|
// UNLOCK THE ROUTING TABLE
|
|
ExReleaseSpinLock(&SegmentLocksTable[seg], oldirql);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
}
|
|
|
|
// there is no such net, add it
|
|
if((rtep = ExAllocatePool(NonPagedPool, sizeof(IPX_ROUTE_ENTRY))) == NULL) {
|
|
|
|
// can't allocate the route entry -> return
|
|
wgap->ErrorCode = ERROR_IPXCP_MEMORY_ALLOCATION_FAILURE;
|
|
|
|
// UNLOCK THE ROUTING TABLE
|
|
ExReleaseSpinLock(&SegmentLocksTable[seg], oldirql);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
// set up the new route entry
|
|
memcpy(rtep->Network, wnet, IPX_NET_LEN);
|
|
|
|
rtep->NicId = 0xFFFE; // that's what we use for the global wan net
|
|
|
|
memcpy(rtep->NextRouter, nulladdress, IPX_NODE_LEN);
|
|
rtep->Flags = IPX_ROUTER_LOCAL_NET | IPX_ROUTER_PERMANENT_ENTRY | IPX_ROUTER_GLOBAL_WAN_NET;
|
|
rtep->Timer = 0; // TTL of this route entry is 3 min
|
|
rtep->Segment = seg;
|
|
rtep->TickCount = DEFAULT_WAN_GLOBAL_NET_TICKCOUNT;
|
|
rtep->HopCount = 1;
|
|
|
|
InitializeListHead(&rtep->AlternateRoute);
|
|
|
|
RtPrint(DBG_INIT, ("IpxRouter: IoctlSetWanGlobalNet: Adding route entry for global WAN net %x-%x-%x-%x \n",
|
|
wnet[0],
|
|
wnet[1],
|
|
wnet[2],
|
|
wnet[3]));
|
|
|
|
IpxAddRoute(seg, rtep);
|
|
|
|
// set our global variable to indicate we have a global wan net
|
|
WanGlobalNetworkEnabled = TRUE;
|
|
memcpy(WanGlobalNetwork, rtep->Network, 4);
|
|
|
|
// UNLOCK THE ROUTING TABLE
|
|
ExReleaseSpinLock(&SegmentLocksTable[seg], oldirql);
|
|
|
|
// Broadcast the new route entry on all the LAN segments
|
|
BroadcastWanNetUpdate(rtep, NULL, NULL);
|
|
|
|
// copy the net and return
|
|
memcpy(wgap->WanGlobalNetwork, wnet, IPX_NET_LEN);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
DeleteGlobalWanNet(VOID)
|
|
{
|
|
UINT seg;
|
|
KIRQL oldirql;
|
|
PIPX_ROUTE_ENTRY rtep;
|
|
|
|
// if configured with a wan global network, delete and free the route entry now
|
|
if(WanGlobalNetworkEnabled) {
|
|
|
|
WanGlobalNetworkEnabled = FALSE;
|
|
|
|
seg = IpxGetSegment(WanGlobalNetwork);
|
|
|
|
// LOCK THE ROUTING TABLE
|
|
ExAcquireSpinLock(&SegmentLocksTable[seg], &oldirql);
|
|
|
|
if(rtep = IpxGetRoute(seg, WanGlobalNetwork)) {
|
|
|
|
IpxDeleteRoute(seg, rtep);
|
|
|
|
RtPrint(DBG_INIT, ("IpxRouter: DeleteGlobalWanNet: Deleted wan global net route entry\n"));
|
|
}
|
|
|
|
// UNLOCK THE ROUTING TABLE
|
|
ExReleaseSpinLock(&SegmentLocksTable[seg], oldirql);
|
|
|
|
if(rtep) {
|
|
|
|
ExFreePool(rtep);
|
|
}
|
|
}
|
|
}
|
|
|
|
NTSTATUS
|
|
IoctlDeleteWanGlobalAddress(PVOID iobufferp,
|
|
ULONG inbufflen,
|
|
ULONG outbufflen,
|
|
PULONG bytestransfp)
|
|
{
|
|
// If we are called with this IOCtl, it means IPXCP has been reconfigured to
|
|
// to use static/dynamic wan nets allocation and NOT the global wan net.
|
|
// If the router had been configured previously for the global wan net, delete the
|
|
// net and reconfigure now.
|
|
DeleteGlobalWanNet();
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|