summaryrefslogtreecommitdiffstats
path: root/private/ntos/tdi/isn/fwd
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/tdi/isn/fwd
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/tdi/isn/fwd')
-rw-r--r--private/ntos/tdi/isn/fwd/ddreqs.c220
-rw-r--r--private/ntos/tdi/isn/fwd/ddreqs.h149
-rw-r--r--private/ntos/tdi/isn/fwd/debug.c7
-rw-r--r--private/ntos/tdi/isn/fwd/debug.h69
-rw-r--r--private/ntos/tdi/isn/fwd/dirs22
-rw-r--r--private/ntos/tdi/isn/fwd/driver.c1157
-rw-r--r--private/ntos/tdi/isn/fwd/driver.h102
-rw-r--r--private/ntos/tdi/isn/fwd/filterif.c211
-rw-r--r--private/ntos/tdi/isn/fwd/filterif.h126
-rw-r--r--private/ntos/tdi/isn/fwd/fwd.mak2427
-rw-r--r--private/ntos/tdi/isn/fwd/fwddefs.h125
-rw-r--r--private/ntos/tdi/isn/fwd/ipxbind.c462
-rw-r--r--private/ntos/tdi/isn/fwd/ipxbind.h75
-rw-r--r--private/ntos/tdi/isn/fwd/lineind.c323
-rw-r--r--private/ntos/tdi/isn/fwd/lineind.h116
-rw-r--r--private/ntos/tdi/isn/fwd/mp/makefile6
-rw-r--r--private/ntos/tdi/isn/fwd/mp/sources29
-rw-r--r--private/ntos/tdi/isn/fwd/netbios.c311
-rw-r--r--private/ntos/tdi/isn/fwd/netbios.h134
-rw-r--r--private/ntos/tdi/isn/fwd/nwlnkfwd.rc12
-rw-r--r--private/ntos/tdi/isn/fwd/packets.c528
-rw-r--r--private/ntos/tdi/isn/fwd/packets.h464
-rw-r--r--private/ntos/tdi/isn/fwd/precomp.h61
-rw-r--r--private/ntos/tdi/isn/fwd/rcvind.c825
-rw-r--r--private/ntos/tdi/isn/fwd/rcvind.h180
-rw-r--r--private/ntos/tdi/isn/fwd/registry.c273
-rw-r--r--private/ntos/tdi/isn/fwd/registry.h61
-rw-r--r--private/ntos/tdi/isn/fwd/rwlock.h179
-rw-r--r--private/ntos/tdi/isn/fwd/send.c1253
-rw-r--r--private/ntos/tdi/isn/fwd/send.h220
-rw-r--r--private/ntos/tdi/isn/fwd/sources.inc61
-rw-r--r--private/ntos/tdi/isn/fwd/tables.c1512
-rw-r--r--private/ntos/tdi/isn/fwd/tables.h708
-rw-r--r--private/ntos/tdi/isn/fwd/up/makefile6
-rw-r--r--private/ntos/tdi/isn/fwd/up/sources31
35 files changed, 12445 insertions, 0 deletions
diff --git a/private/ntos/tdi/isn/fwd/ddreqs.c b/private/ntos/tdi/isn/fwd/ddreqs.c
new file mode 100644
index 000000000..76ab93ea4
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/ddreqs.c
@@ -0,0 +1,220 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ ntos\tdi\isn\fwd\ddreqs.c
+
+Abstract:
+ Management of demand dial request queues
+
+
+Author:
+
+ Vadim Eydelman
+
+Revision History:
+
+--*/
+
+#include "precomp.h"
+
+LIST_ENTRY ConnectionIrpQueue;
+LIST_ENTRY ConnectionRequestQueue;
+
+/*++
+ Q u e u e C o n n e c t i o n R e q u e s t
+
+Routine Description:
+ Adds request to connected the interface to the queue
+
+Arguments:
+ ifCB - control block of the interface that needs to be
+ connected
+ packet - packet that prompted the connection request
+ data - pointer to actual data in the packet
+ oldIRQL - IRQL at which interface lock was acquired
+
+Return Value:
+ None
+
+ Note that interface lock must be acquired before calling this
+ routine which will release it
+
+--*/
+VOID
+QueueConnectionRequest (
+ PINTERFACE_CB ifCB,
+ PNDIS_PACKET packet,
+ PUCHAR data,
+ KIRQL oldIRQL
+ ) {
+ KIRQL cancelIRQL;
+
+ IoAcquireCancelSpinLock (&cancelIRQL);
+ SET_IF_CONNECTING (ifCB);
+ if (!IsListEmpty (&ConnectionIrpQueue)) {
+ PIRP irp = CONTAINING_RECORD (
+ ConnectionIrpQueue.Flink,
+ IRP,
+ Tail.Overlay.ListEntry);
+ PIO_STACK_LOCATION irpStack=IoGetCurrentIrpStackLocation(irp);
+ RemoveEntryList (&irp->Tail.Overlay.ListEntry);
+ ASSERT (irpStack->Parameters.DeviceIoControl.IoControlCode
+ ==IOCTL_FWD_GET_DIAL_REQUEST);
+ ASSERT ((irpStack->Parameters.DeviceIoControl.IoControlCode&3)
+ ==METHOD_BUFFERED);
+ IoSetCancelRoutine (irp, NULL);
+ IoReleaseCancelSpinLock (cancelIRQL);
+
+ FillConnectionRequest (
+ ifCB->ICB_Index,
+ packet,
+ data,
+ (PFWD_DIAL_REQUEST)irp->AssociatedIrp.SystemBuffer,
+ irpStack->Parameters.DeviceIoControl.OutputBufferLength,
+ &irp->IoStatus.Information);
+ irp->IoStatus.Status = STATUS_SUCCESS;
+
+ KeReleaseSpinLock (&ifCB->ICB_Lock, oldIRQL);
+ IpxFwdDbgPrint (DBG_DIALREQS, DBG_WARNING,
+ ("IpxFwd: Passing dial request for if %ld (icb:%08lx) with %d bytes of data.\n",
+ ifCB->ICB_Index, ifCB, irp->IoStatus.Information));
+ IoCompleteRequest (irp, IO_NO_INCREMENT);
+ }
+ else {
+ InsertTailList (&ConnectionRequestQueue, &ifCB->ICB_ConnectionLink);
+ IoReleaseCancelSpinLock (cancelIRQL);
+ ifCB->ICB_ConnectionPacket = packet;
+ ifCB->ICB_ConnectionData = data;
+ KeReleaseSpinLock (&ifCB->ICB_Lock, oldIRQL);
+ }
+}
+
+/*++
+ D e q u e u e C o n n e c t i o n R e q u e s t
+
+Routine Description:
+ Removes conection requset for the interface from the queue
+
+Arguments:
+ ifCB - control block of the interface that needs to be
+ removed
+
+Return Value:
+ None
+
+--*/
+VOID
+DequeueConnectionRequest (
+ PINTERFACE_CB ifCB
+ ) {
+ KIRQL cancelIRQL;
+ IoAcquireCancelSpinLock (&cancelIRQL);
+ if (IsListEntry (&ifCB->ICB_ConnectionLink)) {
+ RemoveEntryList (&ifCB->ICB_ConnectionLink);
+ InitializeListEntry (&ifCB->ICB_ConnectionLink);
+ }
+ IoReleaseCancelSpinLock (cancelIRQL);
+}
+
+/*++
+ F i l l C o n n e c t i o n R e q u e s t
+
+Routine Description:
+ Fills the provided buffer with index of interface that needs
+ to be connected and packet that prompted the request
+
+Arguments:
+ index - if index
+ packet - packet that prompted the request
+ data - pointer to IPX data (IPX header) inside of the packet
+ request - request buffer to fill
+ reqSize - size of request buffer
+ bytesCopied - bytesCopied into the request buffer
+
+Return Value:
+ STATUS_SUCCESS - array was filled successfully
+ This routine assumes that there it is called only when there
+ are outstanding requests in the request queue
+
+--*/
+VOID
+FillConnectionRequest (
+ IN ULONG index,
+ IN PNDIS_PACKET packet,
+ IN PUCHAR data,
+ IN OUT PFWD_DIAL_REQUEST request,
+ IN ULONG reqSize,
+ OUT PULONG bytesCopied
+ ) {
+ PNDIS_BUFFER buf;
+
+ *bytesCopied = 0;
+ request->IfIndex = index;
+ NdisQueryPacket (packet, NULL, NULL, &buf, NULL);
+ do {
+ PVOID va;
+ UINT length;
+
+ NdisQueryBuffer (buf, &va, &length);
+ if (((PUCHAR)va<=data)
+ && ((PUCHAR)va+length>data)) {
+ TdiCopyMdlToBuffer (buf,
+ data-(PUCHAR)va,
+ request,
+ FIELD_OFFSET (FWD_DIAL_REQUEST, Packet),
+ reqSize,
+ bytesCopied);
+ *bytesCopied += FIELD_OFFSET (FWD_DIAL_REQUEST, Packet);
+ break;
+ }
+ NdisGetNextBuffer (buf, &buf);
+ }
+ while (buf!=NULL);
+}
+
+/*++
+ F a i l C o n n e c t i o n R e q u e s t s
+
+Routine Description:
+ Cleans up on connection request failure
+
+Arguments:
+ InterfaceIndex - index of interface that could not be connected
+
+Return Value:
+ STATUS_SUCCESS - clean up was successfull
+ STATUS_UNSUCCESSFUL - interface with this index does not exist
+
+--*/
+NTSTATUS
+FailConnectionRequest (
+ IN ULONG InterfaceIndex
+ ) {
+ PINTERFACE_CB ifCB;
+ KIRQL oldIRQL;
+
+ ASSERT (InterfaceIndex!=FWD_INTERNAL_INTERFACE_INDEX);
+
+ ifCB = GetInterfaceReference (InterfaceIndex);
+ if (ifCB!=NULL) {
+ IpxFwdDbgPrint (DBG_DIALREQS, DBG_WARNING,
+ ("IpxFwd: Dial request failed for if %ld (icb:%08lx).\n",
+ ifCB->ICB_Index, ifCB));
+ ProcessInternalQueue (ifCB);
+ ProcessExternalQueue (ifCB);
+ KeAcquireSpinLock (&ifCB->ICB_Lock, &oldIRQL);
+ if (IS_IF_CONNECTING (ifCB)) {
+ SET_IF_NOT_CONNECTING (ifCB);
+ DequeueConnectionRequest (ifCB);
+ }
+ KeReleaseSpinLock (&ifCB->ICB_Lock, oldIRQL);
+ ReleaseInterfaceReference (ifCB);
+ return STATUS_SUCCESS;
+ }
+ else
+ return STATUS_UNSUCCESSFUL;
+}
+
diff --git a/private/ntos/tdi/isn/fwd/ddreqs.h b/private/ntos/tdi/isn/fwd/ddreqs.h
new file mode 100644
index 000000000..416091c92
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/ddreqs.h
@@ -0,0 +1,149 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ ntos\tdi\isn\fwd\ddreqs.h
+
+Abstract:
+ Management of demand dial request queues
+
+
+Author:
+
+ Vadim Eydelman
+
+Revision History:
+
+--*/
+#ifndef _IPXFWD_DDREQS_
+#define _IPXFWD_DDREQS_
+
+// Connection requests to DIM
+// Queue of request that need to be satisfied by DIM
+extern LIST_ENTRY ConnectionRequestQueue;
+// Queue of request IRPs posted by the router manager
+extern LIST_ENTRY ConnectionIrpQueue;
+
+/*++
+ I n i t i a l i z e C o n n e c t i o n Q u e u e s
+
+Routine Description:
+ Initializes connection request and irp queues
+
+Arguments:
+ None
+
+Return Value:
+ None
+
+--*/
+//VOID
+//InitializeConnectionQueues (
+// void
+// );
+#define InitializeConnectionQueues() { \
+ InitializeListHead (&ConnectionIrpQueue); \
+ InitializeListHead (&ConnectionRequestQueue); \
+}
+
+/*++
+ F i l l C o n n e c t i o n R e q u e s t
+
+Routine Description:
+ Fills the provided buffer with index of interface that needs
+ to be connected and packet that prompted the request
+
+Arguments:
+ index - if index
+ packet - packet that prompted the request
+ data - pointer to IPX data (IPX header) inside of the packet
+ request - request buffer to fill
+ reqSize - size of request buffer
+ bytesCopied - bytesCopied into the request buffer
+
+Return Value:
+ STATUS_SUCCESS - array was filled successfully
+ This routine assumes that there it is called only when there
+ are outstanding requests in the request queue
+
+--*/
+VOID
+FillConnectionRequest (
+ IN ULONG index,
+ IN PNDIS_PACKET packet,
+ IN PUCHAR data,
+ IN OUT PFWD_DIAL_REQUEST request,
+ IN ULONG reqSize,
+ OUT PULONG bytesCopied
+ );
+
+/*++
+ F a i l C o n n e c t i o n R e q u e s t s
+
+Routine Description:
+ Cleans up on connection request failure
+
+Arguments:
+ InterfaceIndex - index of interface that could not be connected
+
+Return Value:
+ STATUS_SUCCESS - clean up was successfull
+ STATUS_UNSUCCESSFUL - interface with this index does not exist
+
+--*/
+NTSTATUS
+FailConnectionRequest (
+ IN ULONG InterfaceIndex
+ );
+
+/*++
+ Q u e u e C o n n e c t i o n R e q u e s t
+
+Routine Description:
+ Adds request to connected the interface to the queue
+
+Arguments:
+ ifCB - control block of the interface that needs to be
+ connected
+ packet - packet that prompted the connection request
+ data - pointer to actual data in the packet
+ oldIRQL - IRQL at which interface lock was acquired
+
+Return Value:
+ None
+
+ Note that interface lock must be acquired before calling this
+ routine which will release it
+
+--*/
+VOID
+QueueConnectionRequest (
+ PINTERFACE_CB ifCB,
+ PNDIS_PACKET packet,
+ PUCHAR data,
+ KIRQL oldIRQL
+ );
+
+/*++
+ D e q u e u e C o n n e c t i o n R e q u e s t
+
+Routine Description:
+ Removes conection requset for the interface from the queue
+
+Arguments:
+ ifCB - control block of the interface that needs to be
+ removed
+
+Return Value:
+ None
+
+--*/
+VOID
+DequeueConnectionRequest (
+ PINTERFACE_CB ifCB
+ );
+
+#endif
+
diff --git a/private/ntos/tdi/isn/fwd/debug.c b/private/ntos/tdi/isn/fwd/debug.c
new file mode 100644
index 000000000..9fa2f3f1c
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/debug.c
@@ -0,0 +1,7 @@
+#include "precomp.h"
+
+#if DBG
+ULONG DbgLevel = DEF_DBG_LEVEL;
+LONGLONG ActivityTreshhold = _I64_MAX;
+LARGE_INTEGER CounterFrequency;
+#endif
diff --git a/private/ntos/tdi/isn/fwd/debug.h b/private/ntos/tdi/isn/fwd/debug.h
new file mode 100644
index 000000000..251d23895
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/debug.h
@@ -0,0 +1,69 @@
+/*******************************************************************/
+/* Copyright(c) 1993 Microsoft Corporation */
+/*******************************************************************/
+
+//***
+//
+// Filename: debug.h
+//
+// Description: Debug macros definitions
+//
+// Author: Stefan Solomon (stefans) October 4, 1993.
+//
+// Revision History:
+//
+//***
+
+#ifndef _IPXFWD_DEBUG_
+#define _IPXFWD_DEBUG_
+
+#if DBG
+#define DBG_PACKET_ALLOC ((ULONG)0x00000001)
+#define DBG_INTF_TABLE ((ULONG)0x00000002)
+#define DBG_ROUTE_TABLE ((ULONG)0x00000004)
+#define DBG_NBROUTE_TABLE ((ULONG)0x00000008)
+#define DBG_IOCTLS ((ULONG)0x00000010)
+#define DBG_LINEIND ((ULONG)0x00000020)
+#define DBG_IPXBIND ((ULONG)0x00000040)
+#define DBG_REGISTRY ((ULONG)0x00000080)
+#define DBG_INT_RECV ((ULONG)0x00000100)
+#define DBG_RECV ((ULONG)0x00000200)
+#define DBG_SEND ((ULONG)0x00000400)
+#define DBG_INT_SEND ((ULONG)0x00000800)
+#define DBG_NETBIOS ((ULONG)0x00001000)
+#define DBG_IPXROUTE ((ULONG)0x00002000)
+#define DBG_DIALREQS ((ULONG)0x00004000)
+#define DBG_SPOOFING ((ULONG)0x00008000)
+
+#define DBG_INFORMATION ((ULONG)0x10000000)
+#define DBG_WARNING ((ULONG)0x20000000)
+#define DBG_ERROR ((ULONG)0x40000000)
+
+#define DEF_DBG_LEVEL ( \
+ DBG_ERROR|DBG_WARNING \
+ | DBG_INTF_TABLE \
+ | DBG_LINEIND \
+ | DBG_IPXBIND \
+ | DBG_REGISTRY \
+ | DBG_IPXROUTE \
+ | DBG_IOCTLS \
+ | DBG_DIALREQS \
+ | DBG_SPOOFING \
+ )
+
+extern ULONG DbgLevel;
+extern LONGLONG ActivityTreshhold;
+extern LARGE_INTEGER CounterFrequency;
+
+#define IpxFwdDbgPrint(COMPONENT,LEVEL,ARGS) \
+ do { \
+ if ((DbgLevel & ((COMPONENT)|(LEVEL)))==((COMPONENT)|(LEVEL))){ \
+ DbgPrint ARGS; \
+ } \
+ } while (0)
+
+#else
+#define IpxFwdDbgPrint(COMPONENT,LEVEL,ARGS) do {NOTHING;} while (0)
+#endif
+
+#endif
diff --git a/private/ntos/tdi/isn/fwd/dirs b/private/ntos/tdi/isn/fwd/dirs
new file mode 100644
index 000000000..0dab2f056
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/dirs
@@ -0,0 +1,22 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+
+NOTE: Commented description of this file is in \nt\bak\bin\dirs.tpl
+
+!ENDIF
+
+DIRS=up mp
diff --git a/private/ntos/tdi/isn/fwd/driver.c b/private/ntos/tdi/isn/fwd/driver.c
new file mode 100644
index 000000000..ac03cb31e
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/driver.c
@@ -0,0 +1,1157 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ ntos\tdi\isn\fwd\driver.c
+
+Abstract:
+ IPX Forwarder driver dispatch routines
+
+
+Author:
+
+ Vadim Eydelman
+
+Revision History:
+
+--*/
+
+#include "precomp.h"
+
+const UCHAR BROADCAST_NODE[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+const LONGLONG WaitTimeout = -50000000i64;
+volatile BOOLEAN IpxFwdInitialized = FALSE;
+
+BOOLEAN MeasuringPerformance = FALSE;
+KSPIN_LOCK PerfCounterLock;
+FWD_PERFORMANCE PerfBlock;
+
+LONG ClientCount = 0;
+KEVENT ClientsGoneEvent;
+
+PFILE_OBJECT RouterFile, FilterFile;
+
+NTSTATUS
+IpxFwdDispatch(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ );
+
+VOID
+IpxFwdUnload(
+ IN PDRIVER_OBJECT DriverObject
+ );
+
+NTSTATUS
+DoStart (
+ IN ULONG RouteHashTableSize,
+ IN BOOLEAN thisMachineOnly
+ );
+
+NTSTATUS
+DoStop (
+ void
+ );
+
+NTSTATUS
+DoSetInterface (
+ IN ULONG InterfaceIndex,
+ IN BOOLEAN NetbiosAccept,
+ IN UCHAR NetbiosDeliver
+ );
+
+NTSTATUS
+DoGetInterface (
+ IN ULONG InterfaceIndex,
+ OUT PFWD_IF_STATS stats,
+ OUT BOOLEAN *NetbiosAccept,
+ OUT UCHAR *NetbiosDeliver
+ );
+
+NTSTATUS
+DoSetNbNames (
+ IN ULONG InterfaceIndex,
+ IN ULONG Count,
+ IN PFWD_NB_NAME Names
+ );
+
+NTSTATUS
+DoGetNbNames (
+ IN ULONG InterfaceIndex,
+ IN OUT ULONG *BufferSize,
+ OUT ULONG *Count,
+ OUT PFWD_NB_NAME Names
+ );
+
+NTSTATUS
+DoBindInterface (
+ IN ULONG InterfaceIndex,
+ IN PFWD_ADAPTER_BINDING_INFO info
+ );
+
+NTSTATUS
+DoUnbindInterface (
+ IN ULONG InterfaceIndex
+ );
+
+NTSTATUS
+DoDisableInterface (
+ IN ULONG InterfaceIndex
+ );
+
+NTSTATUS
+DoEnableInterface (
+ IN ULONG InterfaceIndex
+ );
+
+NTSTATUS
+DoSetRoutes (
+ IN PFWD_ROUTE_SET_PARAMS routeArray,
+ IN ULONG nRoutes,
+ OUT PULONG nProcessed
+ );
+
+VOID
+IpxFwdCancel (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP irp
+ );
+
+NTSTATUS
+DoGetPerfCounters (
+ PFWD_PERFORMANCE_PARAMS perfParams
+ );
+
+/*++
+ 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;
+ WCHAR deviceNameBuffer[] = IPXFWD_NAME;
+ UNICODE_STRING deviceNameUnicodeString;
+
+ IpxFwdDbgPrint(DBG_IOCTLS, DBG_INFORMATION,
+ ("IpxFwd: Entering DriverEntry\n"));
+
+ //
+ // Create an non-EXCLUSIVE device object
+ //
+
+ RtlInitUnicodeString (&deviceNameUnicodeString,
+ deviceNameBuffer);
+
+ status = IoCreateDevice (DriverObject,
+ 0,
+ &deviceNameUnicodeString,
+ FILE_DEVICE_IPXFWD,
+ 0,
+ FALSE, // Non-Exclusive
+ &deviceObject
+ );
+
+ if (NT_SUCCESS(status)) {
+ //
+ // Create dispatch points for device control, create, close.
+ //
+ GetForwarderParameters (RegistryPath);
+ DriverObject->MajorFunction[IRP_MJ_CREATE]
+ = DriverObject->MajorFunction[IRP_MJ_CLEANUP]
+ = DriverObject->MajorFunction[IRP_MJ_CLOSE]
+ = DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]
+ = IpxFwdDispatch;
+ DriverObject->DriverUnload = IpxFwdUnload;
+ status = BindToIpxDriver (KernelMode);
+ if (NT_SUCCESS (status)) {
+
+#if DBG
+ KeQueryPerformanceCounter (&CounterFrequency);
+#endif
+ FilterFile = RouterFile = NULL;
+ ClientCount = 0;
+ return STATUS_SUCCESS;
+ }
+ IoDeleteDevice (DriverObject->DeviceObject);
+ }
+ else
+ IpxFwdDbgPrint (DBG_IOCTLS, DBG_ERROR,
+ ("IpxFwd: IoCreateDevice failed\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
+IpxFwdDispatch(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+ ) {
+ PIO_STACK_LOCATION IrpStack;
+ PVOID inBuffer, outBuffer;
+ ULONG inpBufLength;
+ ULONG outBufLength;
+ NTSTATUS status;
+ KIRQL cancelIRQL;
+
+
+ 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:
+ IpxFwdDbgPrint(DBG_IOCTLS, DBG_WARNING, ("IpxFwd: IRP_MJ_CREATE\n"));
+ break;
+
+ case IRP_MJ_CLOSE:
+ IpxFwdDbgPrint(DBG_IOCTLS, DBG_WARNING, ("IpxFwd: IRP_MJ_CLOSE\n"));
+ if (EnterForwarder ()) {
+ if (IrpStack->FileObject==RouterFile) {
+ LeaveForwarder ();
+ IpxFwdInitialized = FALSE;
+ while (InterlockedDecrement (&ClientCount)>=0) {
+ KeWaitForSingleObject (&ClientsGoneEvent,
+ Executive,
+ KernelMode,
+ FALSE,
+ (PLARGE_INTEGER)&WaitTimeout);
+ InterlockedIncrement (&ClientCount);
+ IpxFwdDbgPrint(DBG_IOCTLS, DBG_ERROR,
+ ("IpxFwd: Waiting for all clients (%ld) to exit.\n",
+ ClientCount));
+ }
+ status = DoStop ();
+ ClientCount = 0;
+ RouterFile = NULL;
+ }
+ else if (IrpStack->FileObject==FilterFile) {
+ UnbindFilterDriver ();
+ FilterFile = NULL;
+ LeaveForwarder ();
+ }
+ else
+ LeaveForwarder ();
+ }
+ break;
+
+ case IRP_MJ_CLEANUP:
+ IpxFwdDbgPrint(DBG_IOCTLS, DBG_WARNING, ("IpxFwd: IRP_MJ_CLEANUP\n"));
+ if (EnterForwarder ()) {
+ if (IrpStack->FileObject==RouterFile) {
+ IoAcquireCancelSpinLock (&cancelIRQL);
+ while (!IsListEmpty (&ConnectionIrpQueue)) {
+ PIRP irp = CONTAINING_RECORD (ConnectionIrpQueue.Blink,
+ IRP, Tail.Overlay.ListEntry);
+ irp->Cancel = TRUE;
+ irp->CancelIrql = cancelIRQL;
+ irp->CancelRoutine = NULL;
+ IpxFwdCancel(DeviceObject, irp);
+ IoAcquireCancelSpinLock (&cancelIRQL);
+ }
+ IoReleaseCancelSpinLock(cancelIRQL);
+ }
+ LeaveForwarder ();
+ }
+ 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 = MmGetSystemAddressForMdl (Irp->MdlAddress);
+ }
+ else {
+ outBuffer = NULL;
+ IpxFwdDbgPrint(DBG_IOCTLS, DBG_ERROR,
+ ("IpxFwd: IOCTL...METHOD_DIRECT with 0 output buffer ???\n"));
+ }
+ break;
+ default:
+ IpxFwdDbgPrint(DBG_IOCTLS, DBG_ERROR,
+ ("IpxFwd: IOCTL...METHOD_NEITHER ???\n"));
+ goto DispatchExit;
+ }
+
+
+ if (EnterForwarder ()) {
+ if (IrpStack->FileObject==RouterFile) {
+ switch (IrpStack->Parameters.DeviceIoControl.IoControlCode) {
+ case IOCTL_FWD_SET_ROUTES:
+ IpxFwdDbgPrint(DBG_IOCTLS, DBG_INFORMATION, ("IpxFwd: IOCTL_FWD_SET_ROUTES\n"));
+ if (inpBufLength>=sizeof (FWD_ROUTE_SET_PARAMS))
+ status = DoSetRoutes (
+ (PFWD_ROUTE_SET_PARAMS)inBuffer,
+ inpBufLength/sizeof(FWD_ROUTE_SET_PARAMS),
+ &Irp->IoStatus.Information);
+
+ break;
+
+ case IOCTL_FWD_SET_NB_NAMES:
+ IpxFwdDbgPrint(DBG_IOCTLS, DBG_INFORMATION, ("IpxFwd: IOCTL_FWD_SET_NB_NAMES\n"));
+ if (inpBufLength==sizeof (ULONG))
+ status = DoSetNbNames (
+ *((PULONG)inBuffer),
+ outBufLength/sizeof (FWD_NB_NAME),
+ (PFWD_NB_NAME)outBuffer);
+ break;
+
+ case IOCTL_FWD_RESET_NB_NAMES:
+ IpxFwdDbgPrint(DBG_IOCTLS, DBG_INFORMATION, ("IpxFwd: IOCTL_FWD_RESET_NB_NAMES\n"));
+ if (inpBufLength==sizeof (ULONG))
+ status = DoSetNbNames (*((PULONG)inBuffer), 0, NULL);
+
+ break;
+ case IOCTL_FWD_GET_NB_NAMES:
+ IpxFwdDbgPrint(DBG_IOCTLS, DBG_INFORMATION, ("IpxFwd: IOCTL_FWD_GET_NB_NAMES\n"));
+ if ((inpBufLength==sizeof (ULONG))
+ && (outBufLength>=sizeof(ULONG))) {
+ Irp->IoStatus.Information = outBufLength
+ -FIELD_OFFSET (FWD_NB_NAMES_PARAMS, Names);
+ status = DoGetNbNames (
+ *((PULONG)inBuffer),
+ &Irp->IoStatus.Information,
+ &((PFWD_NB_NAMES_PARAMS)outBuffer)->TotalCount,
+ ((PFWD_NB_NAMES_PARAMS)outBuffer)->Names);
+ if (NT_SUCCESS (status)) {
+ Irp->IoStatus.Information += FIELD_OFFSET (
+ FWD_NB_NAMES_PARAMS, Names);
+ }
+ }
+ break;
+
+ case IOCTL_FWD_CREATE_INTERFACE:
+ IpxFwdDbgPrint(DBG_IOCTLS, DBG_INFORMATION, ("IpxFwd: IOCTL_FWD_CREATE_INTERFACE\n"));
+ if (inpBufLength==sizeof(FWD_IF_CREATE_PARAMS))
+ status = AddInterface (
+ ((PFWD_IF_CREATE_PARAMS)inBuffer)->Index,
+ ((PFWD_IF_CREATE_PARAMS)inBuffer)->InterfaceType,
+ ((PFWD_IF_CREATE_PARAMS)inBuffer)->NetbiosAccept,
+ ((PFWD_IF_CREATE_PARAMS)inBuffer)->NetbiosDeliver);
+ break;
+
+ case IOCTL_FWD_DELETE_INTERFACE:
+ IpxFwdDbgPrint(DBG_IOCTLS, DBG_INFORMATION, ("IpxFwd: IOCTL_FWD_DELETE_INTERFACE\n"));
+ if (inpBufLength==sizeof(ULONG))
+ status = DeleteInterface (
+ *((PULONG)inBuffer));
+
+ break;
+
+ case IOCTL_FWD_SET_INTERFACE:
+ IpxFwdDbgPrint(DBG_IOCTLS, DBG_INFORMATION, ("IpxFwd: IOCTL_FWD_SET_INTERFACE\n"));
+ if (inpBufLength==sizeof(FWD_IF_SET_PARAMS))
+ status = DoSetInterface (
+ ((PFWD_IF_SET_PARAMS)inBuffer)->Index,
+ ((PFWD_IF_SET_PARAMS)inBuffer)->NetbiosAccept,
+ ((PFWD_IF_SET_PARAMS)inBuffer)->NetbiosDeliver);
+ break;
+
+ case IOCTL_FWD_GET_INTERFACE:
+ IpxFwdDbgPrint(DBG_IOCTLS, DBG_INFORMATION, ("IpxFwd: IOCTL_FWD_GET_INTERFACE\n"));
+ if ((inpBufLength==sizeof(ULONG))
+ && (outBufLength==sizeof(FWD_IF_GET_PARAMS))) {
+ status = DoGetInterface (
+ *((PULONG)inBuffer),
+ &((PFWD_IF_GET_PARAMS)outBuffer)->Stats,
+ &((PFWD_IF_GET_PARAMS)outBuffer)->NetbiosAccept,
+ &((PFWD_IF_GET_PARAMS)outBuffer)->NetbiosDeliver);
+ if (NT_SUCCESS (status))
+ Irp->IoStatus.Information = sizeof(FWD_IF_GET_PARAMS);
+ }
+ break;
+
+ case IOCTL_FWD_BIND_INTERFACE:
+ IpxFwdDbgPrint(DBG_IOCTLS, DBG_INFORMATION, ("IpxFwd: IOCTL_FWD_BIND_INTERFACE\n"));
+ if (inpBufLength==sizeof(FWD_IF_BIND_PARAMS))
+ status = DoBindInterface (
+ ((PFWD_IF_BIND_PARAMS)inBuffer)->Index,
+ &((PFWD_IF_BIND_PARAMS)inBuffer)->Info);
+ break;
+
+ case IOCTL_FWD_UNBIND_INTERFACE:
+ IpxFwdDbgPrint(DBG_IOCTLS, DBG_INFORMATION, ("IpxFwd: IOCTL_FWD_UNBIND_INTERFACE\n"));
+ if (inpBufLength==sizeof(ULONG))
+ status = DoUnbindInterface (*((PULONG)inBuffer));
+ break;
+
+ case IOCTL_FWD_GET_DIAL_REQUEST:
+ IpxFwdDbgPrint(DBG_IOCTLS, DBG_INFORMATION, ("IpxFwd: IOCTL_FWD_GET_DIAL_REQUEST\n"));
+ if (outBufLength>=sizeof (ULONG)) {
+ IoAcquireCancelSpinLock (&cancelIRQL);
+ if (!IsListEmpty (&ConnectionRequestQueue)) {
+ PINTERFACE_CB ifCB = CONTAINING_RECORD (
+ ConnectionRequestQueue.Flink,
+ INTERFACE_CB,
+ ICB_ConnectionLink);
+ RemoveEntryList (&ifCB->ICB_ConnectionLink);
+ InitializeListEntry (&ifCB->ICB_ConnectionLink);
+ IoReleaseCancelSpinLock (cancelIRQL);
+ KeAcquireSpinLock (&ifCB->ICB_Lock, &cancelIRQL);
+ FillConnectionRequest (
+ ifCB->ICB_Index,
+ ifCB->ICB_ConnectionPacket,
+ ifCB->ICB_ConnectionData,
+ (PFWD_DIAL_REQUEST)outBuffer,
+ outBufLength,
+ &Irp->IoStatus.Information);
+ status = STATUS_SUCCESS;
+ KeReleaseSpinLock (&ifCB->ICB_Lock, cancelIRQL);
+ }
+ else {
+ InsertTailList (&ConnectionIrpQueue,
+ &Irp->Tail.Overlay.ListEntry);
+ IoSetCancelRoutine (Irp, IpxFwdCancel);
+ IoReleaseCancelSpinLock (cancelIRQL);
+ IoMarkIrpPending (Irp);
+ Irp->IoStatus.Status = status = STATUS_PENDING;
+ }
+ }
+ break;
+ case IOCTL_FWD_DIAL_REQUEST_FAILED:
+ IpxFwdDbgPrint(DBG_IOCTLS, DBG_INFORMATION, ("IpxFwd: IOCTL_FWD_DIAL_REQUEST_FAILED\n"));
+ if (inpBufLength==sizeof (ULONG))
+ status = FailConnectionRequest (
+ *((PULONG)inBuffer));
+ break;
+ case IOCTL_FWD_DISABLE_INTERFACE:
+ IpxFwdDbgPrint(DBG_IOCTLS, DBG_INFORMATION, ("IpxFwd: IOCTL_FWD_DISABLE_INTERFACE\n"));
+ if (inpBufLength==sizeof (ULONG))
+ status = DoDisableInterface (
+ *((PULONG)inBuffer));
+ break;
+ case IOCTL_FWD_ENABLE_INTERFACE:
+ IpxFwdDbgPrint(DBG_IOCTLS, DBG_INFORMATION, ("IpxFwd: IOCTL_FWD_ENABLE_INTERFACE\n"));
+ if (inpBufLength==sizeof (ULONG))
+ status = DoEnableInterface (
+ *((PULONG)inBuffer));
+ break;
+ default:
+ IpxFwdDbgPrint (DBG_IOCTLS, DBG_WARNING, ("IpxFwd: unknown IRP_MJ_DEVICE_CONTROL\n"));
+ break;
+
+ }
+ }
+ else if (IrpStack->Parameters.DeviceIoControl.IoControlCode
+ ==IOCTL_FWD_INTERNAL_BIND_FILTER) {
+ IpxFwdDbgPrint(DBG_IOCTLS, DBG_INFORMATION, ("IpxFwd: IOCTL_FWD_INTERNAL_BIND_FILTER\n"));
+ if ((inpBufLength==sizeof (IPX_FLT_BIND_INPUT))
+ && (outBufLength>=sizeof (ULONG))) {
+ if (outBufLength>=sizeof (IPX_FLT_BIND_OUTPUT)) {
+ BindFilterDriver (
+ (PIPX_FLT_BIND_INPUT)inBuffer,
+ (PIPX_FLT_BIND_OUTPUT)outBuffer);
+ Irp->IoStatus.Information = sizeof (IPX_FLT_BIND_OUTPUT);
+ FilterFile = IrpStack->FileObject;
+ status = STATUS_SUCCESS;
+ }
+ else {
+ IPX_FLT_BIND_OUTPUT bindOutput;
+ BindFilterDriver (
+ (PIPX_FLT_BIND_INPUT)inBuffer,
+ &bindOutput);
+ memcpy (outBuffer, &bindOutput, outBufLength);
+ Irp->IoStatus.Information = outBufLength;
+ status = STATUS_BUFFER_OVERFLOW;
+ }
+ }
+ }
+ else if (IrpStack->Parameters.DeviceIoControl.IoControlCode
+ ==IOCTL_FWD_GET_PERF_COUNTERS) {
+ IpxFwdDbgPrint(DBG_IOCTLS, DBG_INFORMATION, ("IpxFwd: IOCTL_FWD_GET_PERF_COUNTERS\n"));
+ if (outBufLength==sizeof (FWD_PERFORMANCE_PARAMS))
+ status = DoGetPerfCounters (
+ ((PFWD_PERFORMANCE_PARAMS)outBuffer));
+ }
+ else {
+ status = STATUS_ACCESS_DENIED;
+ IpxFwdDbgPrint(DBG_IOCTLS, DBG_WARNING,
+ ("IpxFwd: IOCTL: %08lx on non-router file object!\n",
+ IrpStack->Parameters.DeviceIoControl.IoControlCode));
+ }
+ LeaveForwarder ();
+ } else {
+ if (IrpStack->Parameters.DeviceIoControl.IoControlCode==IOCTL_FWD_START) {
+ IpxFwdDbgPrint (DBG_IOCTLS, DBG_WARNING,
+ ("IpxFwd: IOCTL_FWD_START\n"));
+ if (inpBufLength==sizeof (FWD_START_PARAMS)) {
+ KeInitializeEvent (&ClientsGoneEvent,
+ SynchronizationEvent,
+ FALSE);
+ status = DoStart (
+ ((PFWD_START_PARAMS)inBuffer)->RouteHashTableSize,
+ ((PFWD_START_PARAMS)inBuffer)->ThisMachineOnly);
+ if (NT_SUCCESS (status)) {
+ RouterFile = IrpStack->FileObject;
+ IpxFwdInitialized = TRUE;
+ }
+ }
+ }
+ else {
+ IpxFwdDbgPrint (DBG_IOCTLS, DBG_ERROR,
+ ("IpxFwd: IOCTL: %08lx but fwd not started.\n",
+ IrpStack->Parameters.DeviceIoControl.IoControlCode));
+ }
+ }
+ break;
+ default:
+ IpxFwdDbgPrint (DBG_IOCTLS, DBG_ERROR,
+ ("IpxFwd: unknown MajorFunction.\n"));
+ break;
+ }
+
+DispatchExit:
+ if (status!=STATUS_PENDING) {
+ IpxFwdDbgPrint(DBG_IOCTLS,
+ NT_ERROR(status) ? DBG_WARNING : DBG_INFORMATION,
+ ("IpxFwd: completing IOCTL %08lx with status %08lx.\n",
+ IrpStack->Parameters.DeviceIoControl.IoControlCode,
+ status));
+ Irp->IoStatus.Status = 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
+IpxFwdUnload(
+ IN PDRIVER_OBJECT DriverObject
+ ) {
+ IpxFwdDbgPrint(DBG_IOCTLS, DBG_WARNING, ("IpxFwd: unloading\n"));
+ if (EnterForwarder ()) {
+ LeaveForwarder ();
+ IpxFwdInitialized = FALSE;
+ while (InterlockedDecrement (&ClientCount)>=0) {
+ KeWaitForSingleObject (&ClientsGoneEvent,
+ Executive,
+ KernelMode,
+ FALSE,
+ (PLARGE_INTEGER)&WaitTimeout);
+ InterlockedIncrement (&ClientCount);
+ IpxFwdDbgPrint(DBG_IOCTLS, DBG_ERROR,
+ ("IpxFwd: Waiting for all clients (%ld) to exit.\n",
+ ClientCount));
+ }
+ DoStop ();
+ }
+
+ UnbindFromIpxDriver (KernelMode);
+ IoDeleteDevice (DriverObject->DeviceObject);
+}
+
+
+
+/*++
+ D o S t a r t
+
+Routine Description:
+ Initializes all driver components and binds to IPX
+ stack driver at strat up
+
+Arguments:
+ RouteHashTableSize - size of route hash table
+ thisMachineOnly - whether to forward dialin client packets
+ to other dests on the net
+
+Return Value:
+ STATUS_SUCCESS - initialization succeded
+ STATUS_UNSUCCESSFULL - failure
+
+--*/
+NTSTATUS
+DoStart (
+ IN ULONG RouteHashTableSize,
+ IN BOOLEAN thisMachineOnly
+ ) {
+ NTSTATUS status;
+
+ InitializeConnectionQueues ();
+ RouteHashSize = RouteHashTableSize;
+ status = CreateTables ();
+ if (NT_SUCCESS (status)) {
+ InitializePacketAllocator ();
+ InitializeNetbiosQueue ();
+ InitializeRecvQueue ();
+ InitializeSendQueue ();
+ MeasuringPerformance = FALSE;
+ KeInitializeSpinLock (&PerfCounterLock);
+ ThisMachineOnly = thisMachineOnly;
+
+ return STATUS_SUCCESS;
+ }
+ return status;
+}
+
+/*++
+ D o S t o p
+
+Routine Description:
+ Cleans up allocated resources and unbinds from IPX stack
+ driver when forwarder is stopped
+
+Arguments:
+ None
+
+Return Value:
+ STATUS_SUCCESS - cleanup succeded
+
+--*/
+NTSTATUS
+DoStop (
+ void
+ ) {
+ if (FilterFile!=NULL) {
+ UnbindFilterDriver ();
+ FilterFile = NULL;
+ }
+ DeleteSendQueue ();
+ DeleteRecvQueue ();
+ DeleteNetbiosQueue ();
+ DeleteTables (); // Unbinds all bound interfaces
+ if (WanPacketListId!=-1) {
+ DeregisterPacketConsumer (WanPacketListId);
+ WanPacketListId = -1;
+ }
+ DeletePacketAllocator ();
+ return STATUS_SUCCESS;
+}
+
+/*++
+ D o S e t R o u t e s
+
+Routine Description:
+ Updates route table with supplied routes
+
+Arguments:
+ routeArray - array of routes to add/de;ete/update
+ nRoutes - number of routes in the array
+ nProcessed - number of routes that were processed successfully
+
+Return Value:
+ STATUS_SUCCESS - all routes were processed ok
+ error status - reason of failure for the first unprocessed route
+
+--*/
+NTSTATUS
+DoSetRoutes (
+ IN PFWD_ROUTE_SET_PARAMS routeArray,
+ IN ULONG nRoutes,
+ OUT PULONG nProcessed
+ ) {
+ NTSTATUS status=STATUS_SUCCESS;
+ UINT i;
+
+ for (i=0; i<nRoutes; i++, routeArray++) {
+ switch (routeArray->Action) {
+ case FWD_ADD_ROUTE:
+ status = AddRoute (routeArray->Network,
+ routeArray->NextHopAddress,
+ routeArray->TickCount,
+ routeArray->HopCount,
+ routeArray->InterfaceIndex);
+ break;
+ case FWD_DELETE_ROUTE:
+ status = DeleteRoute (routeArray->Network);
+ break;
+ case FWD_UPDATE_ROUTE:
+ status = UpdateRoute (routeArray->Network,
+ routeArray->NextHopAddress,
+ routeArray->TickCount,
+ routeArray->HopCount,
+ routeArray->InterfaceIndex);
+ break;
+ default:
+ status = STATUS_INVALID_PARAMETER;
+ break;
+ }
+ if (!NT_SUCCESS (status))
+ break;
+ }
+ *nProcessed = i;
+ return status;
+}
+
+
+/*++
+ D o S e t N b N a m e s
+
+Routine Description:
+ Sets static Netbios Names on the interface
+
+Arguments:
+ InterfaceIndex - index oc interface on which to set names
+ Count - number of names to set
+ Names - array of netbios names
+
+Return Value:
+ STATUS_SUCCESS - names were set OK
+ STATUS_UNSUCCESSFULL - interface does not exist
+ STATUS_INSUFFICIENT_RESOURCES - not enough resources to complete
+ the operation
+
+--*/
+NTSTATUS
+DoSetNbNames (
+ IN ULONG InterfaceIndex,
+ IN ULONG Count,
+ IN PFWD_NB_NAME Names
+ ) {
+ PINTERFACE_CB ifCB;
+ KIRQL oldIRQL;
+ PNB_ROUTE nbRoutes;
+ NTSTATUS status=STATUS_SUCCESS;
+
+ ifCB = GetInterfaceReference (InterfaceIndex);
+ if (ifCB!=NULL) {
+ if (ifCB->ICB_NBRoutes!=NULL) {
+ DeleteNBRoutes (ifCB->ICB_NBRoutes, ifCB->ICB_NBRouteCount);
+ ifCB->ICB_NBRoutes = NULL;
+ ifCB->ICB_NBRouteCount = 0;
+ }
+ if (Count>0) {
+ status = AddNBRoutes (ifCB, Names, Count, &nbRoutes);
+ if (NT_SUCCESS (status)) {
+ ifCB->ICB_NBRoutes = nbRoutes;
+ ifCB->ICB_NBRouteCount = Count;
+ }
+ }
+ ReleaseInterfaceReference (ifCB);
+ }
+ else
+ status = STATUS_UNSUCCESSFUL;
+
+ return status;
+}
+
+
+/*++
+ D o G e t N b N a m e s
+
+Routine Description:
+ Gets all static Netbios Names on the interface
+
+Arguments:
+ InterfaceIndex - index of interface from which to get names
+ ArraySize - on input: size of the buffer to put names into
+ on output: size of data put into the array
+ Names - buffer to put names into names, if buffer
+ is to small to hold all names, this orutine stuffs
+ total number of names into the first ULONG in the
+ array (this is the only way to return in to the
+ caller through the IOCTL interface)
+
+Return Value:
+ STATUS_SUCCESS - names were copied into the array
+ STATUS_UNSUCCESSFULL - interface does not exist
+ STATUS_BUFFER_OVERFLOW - buffer is too small to copy all the
+ names, number of names are in the first ULONG of
+ the buffer
+
+--*/
+NTSTATUS
+DoGetNbNames (
+ IN ULONG InterfaceIndex,
+ IN OUT ULONG *ArraySize,
+ OUT ULONG *TotalCount,
+ OUT PFWD_NB_NAME Names
+ ) {
+ PINTERFACE_CB ifCB;
+ KIRQL oldIRQL;
+ NTSTATUS status=STATUS_SUCCESS;
+
+ ifCB = GetInterfaceReference (InterfaceIndex);
+ if (ifCB!=NULL) {
+ if (ifCB->ICB_NBRoutes!=NULL) {
+ ULONG i;
+ PFWD_NB_NAME nameLM = Names+(*ArraySize/sizeof(FWD_NB_NAME));
+ for (i=0; (i<ifCB->ICB_NBRouteCount)&&(Names<nameLM); i++, Names++)
+ NB_NAME_CPY (Names, &ifCB->ICB_NBRoutes[i].NBR_Name);
+ *ArraySize = sizeof (FWD_NB_NAME)*i;
+ *TotalCount = ifCB->ICB_NBRouteCount;
+ }
+ else {
+ *ArraySize = 0;
+ *TotalCount = 0;
+ }
+ ReleaseInterfaceReference (ifCB);
+ }
+ else
+ status = STATUS_UNSUCCESSFUL;
+
+ return status;
+}
+
+
+/*++
+ D o S e t I n t e r f a c e
+
+Routine Description:
+ Sets interface configurable parameters
+
+Arguments:
+ InterfaceIndex - index of interface to set
+ NetbiosAccept - whether to accept nb packets on the interface
+ NetbiosDeliver - whether to deliver nb packets on the interface
+
+Return Value:
+ STATUS_SUCCESS - interface was set OK
+ STATUS_UNSUCCESSFULL - interface does not exist
+
+--*/
+NTSTATUS
+DoSetInterface (
+ IN ULONG InterfaceIndex,
+ IN BOOLEAN NetbiosAccept,
+ IN UCHAR NetbiosDeliver
+ ) {
+ PINTERFACE_CB ifCB;
+ KIRQL oldIRQL;
+
+ ifCB = GetInterfaceReference (InterfaceIndex);
+ if (ifCB!=NULL) {
+ KeAcquireSpinLock (&ifCB->ICB_Lock, &oldIRQL);
+ ifCB->ICB_NetbiosAccept = NetbiosAccept;
+ ifCB->ICB_NetbiosDeliver = NetbiosDeliver;
+ KeReleaseSpinLock (&ifCB->ICB_Lock, oldIRQL);
+ ReleaseInterfaceReference (ifCB);
+ return STATUS_SUCCESS;
+ }
+ else
+ return STATUS_UNSUCCESSFUL;
+}
+
+
+/*++
+ D o G e t I n t e r f a c e
+
+Routine Description:
+ Gets interface configurable parameters and statistics
+
+Arguments:
+ InterfaceIndex - index of interface to query
+ stats - interface statistics
+ NetbiosAccept - whether nb packets accepter on the interface
+ NetbiosDeliver - whether nb packets delivered on the interface
+
+Return Value:
+ STATUS_SUCCESS - interface data was queried OK
+ STATUS_UNSUCCESSFULL - interface does not exist
+
+--*/
+NTSTATUS
+DoGetInterface (
+ IN ULONG InterfaceIndex,
+ OUT PFWD_IF_STATS stats,
+ OUT BOOLEAN *NetbiosAccept,
+ OUT UCHAR *NetbiosDeliver
+ ) {
+ PINTERFACE_CB ifCB;
+ KIRQL oldIRQL;
+
+ ifCB = GetInterfaceReference (InterfaceIndex);
+ if (ifCB!=NULL) {
+ *NetbiosAccept = ifCB->ICB_NetbiosAccept;
+ *NetbiosDeliver = ifCB->ICB_NetbiosDeliver;
+ IF_STATS_CPY (stats, &ifCB->ICB_Stats);
+ if (!IS_IF_ENABLED(ifCB))
+ stats->OperationalState = FWD_OPER_STATE_DOWN;
+ ReleaseInterfaceReference (ifCB);
+ return STATUS_SUCCESS;
+ }
+ else
+ return STATUS_UNSUCCESSFUL;
+}
+
+/*++
+ D o B i n d I n t e r f a c e
+
+Routine Description:
+ Binds interface to the specified adapter and sets binding
+ parameters
+
+Arguments:
+ InterfaceIndex - index of interface to bind
+ info - binding info
+
+Return Value:
+ STATUS_SUCCESS - interface was bound OK
+ STATUS_UNSUCCESSFULL - interface does not exist or could not be
+ bound
+--*/
+NTSTATUS
+DoBindInterface (
+ IN ULONG InterfaceIndex,
+ IN PFWD_ADAPTER_BINDING_INFO info
+ ) {
+ PINTERFACE_CB ifCB;
+ NTSTATUS status;
+
+ ifCB = GetInterfaceReference (InterfaceIndex);
+ if (ifCB!=NULL) {
+ if (ifCB->ICB_InterfaceType==FWD_IF_PERMANENT)
+ status = BindInterface (ifCB,
+ (USHORT)info->AdapterIndex,
+ info->MaxPacketSize,
+ info->Network,
+ info->LocalNode,
+ info->RemoteNode);
+ else
+ status = STATUS_SUCCESS;
+ ReleaseInterfaceReference (ifCB);
+ return status;
+ }
+ else
+ return STATUS_UNSUCCESSFUL;
+}
+
+
+/*++
+ D o U n b i n d I n t e r f a c e
+
+Routine Description:
+ Unbinds interface from the adapter and invalidates binding
+ parameters
+
+Arguments:
+ InterfaceIndex - index of interface to unbind
+
+Return Value:
+ STATUS_SUCCESS - interface was unbound OK
+ STATUS_UNSUCCESSFULL - interface does not exist
+--*/
+NTSTATUS
+DoUnbindInterface (
+ IN ULONG InterfaceIndex
+ ) {
+ PINTERFACE_CB ifCB;
+
+ ifCB = GetInterfaceReference (InterfaceIndex);
+ if (ifCB!=NULL) {
+ if (ifCB->ICB_InterfaceType==FWD_IF_PERMANENT)
+ UnbindInterface (ifCB);
+
+ ReleaseInterfaceReference (ifCB);
+ return STATUS_SUCCESS;
+ }
+ else
+ return STATUS_UNSUCCESSFUL;
+}
+
+/*++
+ D o D i s a b l e I n t e r f a c e
+
+Routine Description:
+ Disables all packet traffic through the interface
+
+Arguments:
+ InterfaceIndex - index of interface to disable
+
+Return Value:
+ STATUS_SUCCESS - interface was disabled OK
+ STATUS_UNSUCCESSFULL - interface does not exist
+--*/
+NTSTATUS
+DoDisableInterface (
+ IN ULONG InterfaceIndex
+ ) {
+ PINTERFACE_CB ifCB;
+
+ ifCB = GetInterfaceReference (InterfaceIndex);
+ if (ifCB!=NULL) {
+ KIRQL oldIRQL;
+ KeAcquireSpinLock (&ifCB->ICB_Lock, &oldIRQL);
+ if (IS_IF_ENABLED (ifCB)) {
+ SET_IF_DISABLED (ifCB);
+ KeReleaseSpinLock (&ifCB->ICB_Lock, oldIRQL);
+ if (InterfaceIndex!=FWD_INTERNAL_INTERFACE_INDEX) {
+ ProcessInternalQueue (ifCB);
+ ProcessExternalQueue (ifCB);
+ }
+ }
+ else
+ KeReleaseSpinLock (&ifCB->ICB_Lock, oldIRQL);
+ ReleaseInterfaceReference (ifCB);
+ return STATUS_SUCCESS;
+ }
+ else
+ return STATUS_UNSUCCESSFUL;
+}
+
+
+/*++
+ D o E n a b l e I n t e r f a c e
+
+Routine Description:
+ Enables all packet traffic through the interface
+
+Arguments:
+ InterfaceIndex - index of interface to enable
+
+Return Value:
+ STATUS_SUCCESS - interface was disabled OK
+ STATUS_UNSUCCESSFULL - interface does not exist
+--*/
+NTSTATUS
+DoEnableInterface (
+ IN ULONG InterfaceIndex
+ ) {
+ PINTERFACE_CB ifCB;
+
+ ifCB = GetInterfaceReference (InterfaceIndex);
+ if (ifCB!=NULL) {
+ SET_IF_ENABLED (ifCB);
+ ReleaseInterfaceReference (ifCB);
+ return STATUS_SUCCESS;
+ }
+ else
+ return STATUS_UNSUCCESSFUL;
+}
+
+
+
+/*++
+ I p x F w d C a n c e l
+
+Routine Description:
+ Cancels specified IRP
+
+Arguments:
+ DeviceObject - forwarder device object
+ irp - irp to cancel
+
+Return Value:
+ None
+--*/
+VOID
+IpxFwdCancel (
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP irp
+ ) {
+ RemoveEntryList (&irp->Tail.Overlay.ListEntry);
+ IoReleaseCancelSpinLock (irp->CancelIrql);
+
+ irp->IoStatus.Information = 0;
+ irp->IoStatus.Status = STATUS_CANCELLED;
+ IpxFwdDbgPrint(DBG_IOCTLS, DBG_WARNING, ("IpxFwd: completing cancelled irp.\n"));
+ IoCompleteRequest(irp, IO_NO_INCREMENT);
+}
+
+/*++
+ D o G e t P e r f C o u n t e r s
+
+Routine Description:
+ Gets performance counters
+
+Arguments:
+ perfParams - buffer ot pu counters into
+
+Return Value:
+ STATUS_SUCCESS - counter were copied ok
+ STATUS_UNSUCCESSFULL - performance measurement were not enabled
+--*/
+NTSTATUS
+DoGetPerfCounters (
+ OUT PFWD_PERFORMANCE_PARAMS perfParams
+ ) {
+ LONGLONG lTotalPacketProcessingTime;
+ LONGLONG lMaxPacketProcessingTime;
+ LONG lPacketCounter;
+ LONGLONG lTotalNbPacketProcessingTime;
+ LONGLONG lMaxNbPacketProcessingTime;
+ LONG lNbPacketCounter;
+ KIRQL oldIRQL;
+
+ if (!MeasuringPerformance)
+ return STATUS_UNSUCCESSFUL;
+
+ KeAcquireSpinLock (&PerfCounterLock, &oldIRQL);
+ *perfParams = PerfBlock;
+ memset (&PerfBlock, 0, sizeof (PerfBlock));
+ KeReleaseSpinLock (&PerfCounterLock, oldIRQL);
+ return STATUS_SUCCESS;
+}
+
+
+BOOLEAN
+DoLeaveForwarder (
+ VOID
+ ) {
+ return LeaveForwarder ();
+}
diff --git a/private/ntos/tdi/isn/fwd/driver.h b/private/ntos/tdi/isn/fwd/driver.h
new file mode 100644
index 000000000..ecc298345
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/driver.h
@@ -0,0 +1,102 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ ntos\tdi\isn\fwd\driver.h
+
+Abstract:
+ IPX Forwarder driver dispatch routines
+
+
+Author:
+
+ Vadim Eydelman
+
+Revision History:
+
+--*/
+
+
+#ifndef _IPXFWD_DRIVER_
+#define _IPXFWD_DRIVER_
+
+// Pseudo constant 0xFFFFFFFFFFFFF
+extern const UCHAR BROADCAST_NODE[6];
+
+// Performance measurement:
+// Enabling flag
+extern BOOLEAN MeasuringPerformance;
+// Access control
+extern KSPIN_LOCK PerfCounterLock;
+// Statistic accumulators (counters)
+extern FWD_PERFORMANCE PerfBlock;
+
+// Access control for external callers (ipx stack, filter driver)
+// Flag set upon completion of initialization of all components
+extern volatile BOOLEAN IpxFwdInitialized;
+// Number of clients executing forwarder code (if -1, the forwarder
+// is being stopped)
+extern LONG ClientCount;
+// Event to be signalled by the last client inside forwarder
+extern KEVENT ClientsGoneEvent;
+
+
+/*++
+ E n t e r F o r w a r d e r
+
+Routine Description:
+ Checks if forwarder is initialized and grants access
+ to it (records the entrance as well
+
+Arguments:
+ None
+
+Return Value:
+ TRUE - access granted
+ FALSE - forwarder is not yet initialized or is being stopped
+
+--*/
+//BOOLEAN
+//EnterForwarder (
+// void
+// );
+#define EnterForwarder() ( \
+ (InterlockedIncrement(&ClientCount), IpxFwdInitialized) \
+ ? TRUE \
+ : (DoLeaveForwarder(), FALSE) \
+ )
+
+/*++
+ L e a v e F o r w a r d e r
+
+Routine Description:
+ Records the fact that external client stopped using forwarder
+
+Arguments:
+ None
+
+Return Value:
+ None
+
+--*/
+//BOOLEAN
+//EnterForwarder (
+// void
+// );
+#define LeaveForwarder() \
+ ((InterlockedDecrement(&ClientCount)<0) \
+ ? KeSetEvent (&ClientsGoneEvent,0,FALSE) \
+ : 0 \
+ )
+
+// Same as above but implemented as a routine to be used in
+// the EnterForwarder macro above (this reduces code size
+// and aids in debugging by improving readability of disassembly
+BOOLEAN
+DoLeaveForwarder (
+ VOID
+ );
+
+#endif
diff --git a/private/ntos/tdi/isn/fwd/filterif.c b/private/ntos/tdi/isn/fwd/filterif.c
new file mode 100644
index 000000000..f1fa584a3
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/filterif.c
@@ -0,0 +1,211 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ ntos\tdi\isn\fwd\filterif.c
+
+Abstract:
+ IPX Forwarder driver interface with filter driver
+
+
+Author:
+
+ Vadim Eydelman
+
+Revision History:
+
+--*/
+
+#include "precomp.h"
+
+ // Filter driver entry points
+IPX_FLT_BIND_INPUT FltBindInput = {NULL, NULL};
+ // Protects access to filter driver contexts
+RW_LOCK FltLock;
+
+
+/*++
+ D o F i l t e r
+
+Routine Description:
+
+ Calls filter driver entry point while holding reader access
+ to interface contexts
+
+Arguments:
+ ipxHdr - pointer to packet header
+ ipxHdrLength - size of the header buffer (must be at least 30)
+ ifInContext - context associated with interface on which packet
+ was received
+ ifOutContext - context associated with interface on which packet
+ will be sent
+Return Value:
+ FILTER_PERMIT - packet should be passed on by the forwarder
+ FILTER_DENY - packet should be dropped
+
+--*/
+FILTER_ACTION
+DoFilter (
+ IN PUCHAR ipxHdr,
+ IN ULONG ipxHdrLength,
+ IN PVOID ifInContext,
+ IN PVOID ifOutContex
+ ) {
+ RWCOOKIE cookie;
+ FILTER_ACTION result;
+ AcquireReaderAccess (&FltLock, cookie);
+ result = FltBindInput.FilterHandler (ipxHdr,
+ ipxHdrLength,
+ ifInContext,
+ ifOutContex);
+ ReleaseReaderAccess (&FltLock, cookie);
+ return result;
+}
+
+/*++
+ D o I n t e r f a c e D e l e t e d
+
+Routine Description:
+ Resets interface contexts and calls filter dirver entry point
+ making sure that all no one holds reader access to filter driver
+ interface contexts
+Arguments:
+ ifCB - interface to be deleted
+Return Value:
+ None
+
+--*/
+VOID
+DoInterfaceDeleted (
+ PINTERFACE_CB ifCB
+ ) {
+ PVOID inContext = ifCB->ICB_FilterInContext,
+ outContext = ifCB->ICB_FilterOutContext;
+ ifCB->ICB_FilterInContext = NO_FILTER_CONTEXT;
+ ifCB->ICB_FilterOutContext = NO_FILTER_CONTEXT;
+ WaitForAllReaders (&FltLock);
+ FltBindInput.InterfaceDeletedHandler(inContext,
+ outContext);
+}
+
+/*++
+ S e t I f I n C o n t e x t
+
+Routine Description:
+ Associates filter driver context with
+ the packets received on the interface
+Arguments:
+ InterfaceIndex - index of the interface
+ ifInContext - filter driver context
+Return Value:
+ STATUS_SUCCESS - context associated ok
+ STATUS_UNSUCCESSFUL - interface does not exist
+--*/
+NTSTATUS
+SetIfInContext (
+ IN ULONG InterfaceIndex,
+ IN PVOID ifInContext
+ ) {
+ PINTERFACE_CB ifCB;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ if (EnterForwarder ()) {
+ ifCB = GetInterfaceReference (InterfaceIndex);
+ if (ifCB!=NULL) {
+ ifCB->ICB_FilterInContext = ifInContext;
+ WaitForAllReaders (&FltLock);
+ }
+ else
+ status = STATUS_UNSUCCESSFUL;
+ LeaveForwarder ();
+ }
+ return status;
+}
+
+/*++
+ S e t I f O u t C o n t e x t
+
+Routine Description:
+ Associates filter driver context with
+ the packets sent on the interface
+Arguments:
+ InterfaceIndex - index of the interface
+ ifOutContext - filter driver context
+Return Value:
+ STATUS_SUCCESS - context associated ok
+ STATUS_UNSUCCESSFUL - interface does not exist
+--*/
+NTSTATUS
+SetIfOutContext (
+ IN ULONG InterfaceIndex,
+ IN PVOID ifOutContext
+ ) {
+ PINTERFACE_CB ifCB;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ if (EnterForwarder ()) {
+ ifCB = GetInterfaceReference (InterfaceIndex);
+ if (ifCB!=NULL) {
+ ifCB->ICB_FilterOutContext = ifOutContext;
+ WaitForAllReaders (&FltLock);
+ }
+ else
+ status = STATUS_UNSUCCESSFUL;
+ LeaveForwarder ();
+ }
+ return status;
+}
+
+/*++
+ B i n d F i l t e r D r i v e r
+
+Routine Description:
+ Exchanges entry points with filter driver
+Arguments:
+ bindInput - filter driver entry points
+ bindOutput - forwarder driver entry points
+Return Value:
+ None
+--*/
+VOID
+BindFilterDriver (
+ IN PIPX_FLT_BIND_INPUT bindInput,
+ OUT PIPX_FLT_BIND_OUTPUT bindOutput
+ ) {
+ memcpy (&FltBindInput, bindInput, sizeof (IPX_FLT_BIND_INPUT));
+ bindOutput->Size = sizeof (IPX_FLT_BIND_OUTPUT);
+ bindOutput->SetIfInContextHandler = SetIfInContext;
+ bindOutput->SetIfOutContextHandler = SetIfOutContext;
+ InitializeRWLock (&FltLock);
+}
+
+/*++
+ U n b i n d F i l t e r D r i v e r
+
+Routine Description:
+ Resets locally stored filter driver entry points
+ and resets filter driver contexts on all interfaces
+Arguments:
+ None
+Return Value:
+ None
+--*/
+VOID
+UnbindFilterDriver (
+ VOID
+ ) {
+ PINTERFACE_CB ifCB = NULL;
+ FltBindInput.FilterHandler = NULL;
+ FltBindInput.InterfaceDeletedHandler = NULL;
+
+ while ((ifCB=GetNextInterfaceReference (ifCB))!=NULL) {
+ ifCB->ICB_FilterInContext = NO_FILTER_CONTEXT;
+ ifCB->ICB_FilterOutContext = NO_FILTER_CONTEXT;
+ }
+ InternalInterface->ICB_FilterInContext = NO_FILTER_CONTEXT;
+ InternalInterface->ICB_FilterOutContext = NO_FILTER_CONTEXT;
+ WaitForAllReaders (&FltLock);
+}
+
diff --git a/private/ntos/tdi/isn/fwd/filterif.h b/private/ntos/tdi/isn/fwd/filterif.h
new file mode 100644
index 000000000..0e09df1de
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/filterif.h
@@ -0,0 +1,126 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ ntos\tdi\isn\fwd\filterif.h
+
+Abstract:
+ IPX Forwarder interface with filter driver
+
+
+Author:
+
+ Vadim Eydelman
+
+Revision History:
+
+--*/
+
+
+#ifndef _IPXFWD_FILTERIF_
+#define _IPXFWD_FILTERIF_
+ // Filter driver entry points
+extern IPX_FLT_BIND_INPUT FltBindInput;
+
+ // Macros to improve performance when filter driver
+ // is not bound or has not associated its contexts
+ // with interfaces of interest
+#define FltFilter(hdr,hdrSize,inContext,outContext) ( \
+ ((FltBindInput.FilterHandler==NULL) \
+ || ((inContext==NO_FILTER_CONTEXT) \
+ &&(outContext==NO_FILTER_CONTEXT))) \
+ ? FILTER_PERMIT \
+ : DoFilter (hdr,hdrSize,inContext,outContext) \
+)
+
+#define FltInterfaceDeleted(ifCB) { \
+ if ((FltBindInput.InterfaceDeletedHandler!=NULL) \
+ && ((ifCB->ICB_FilterInContext!=NO_FILTER_CONTEXT) \
+ ||(ifCB->ICB_FilterOutContext!=NO_FILTER_CONTEXT))) \
+ DoInterfaceDeleted (ifCB); \
+}
+
+/*++
+ B i n d F i l t e r D r i v e r
+
+Routine Description:
+ Exchanges entry points with filter driver
+Arguments:
+ bindInput - filter driver entry points
+ bindOutput - forwarder driver entry points
+Return Value:
+ None
+--*/
+VOID
+BindFilterDriver (
+ IN PIPX_FLT_BIND_INPUT bindInput,
+ OUT PIPX_FLT_BIND_OUTPUT bindOutput
+ );
+
+/*++
+ U n b i n d F i l t e r D r i v e r
+
+Routine Description:
+ Resets locally stored filter driver entry points
+ and resets filter driver contexts on all interfaces
+Arguments:
+ None
+Return Value:
+ None
+--*/
+VOID
+UnbindFilterDriver (
+ VOID
+ );
+
+
+/*++
+ D o F i l t e r
+
+Routine Description:
+
+ Calls filter driver entry point while holding reader access
+ to interface contexts
+
+Arguments:
+ ipxHdr - pointer to packet header
+ ipxHdrLength - size of the header buffer (must be at least 30)
+ ifInContext - context associated with interface on which packet
+ was received
+ ifOutContext - context associated with interface on which packet
+ will be sent
+Return Value:
+ FILTER_PERMIT - packet should be passed on by the forwarder
+ FILTER_DENY - packet should be dropped
+
+--*/
+FILTER_ACTION
+DoFilter (
+ IN PUCHAR ipxHdr,
+ IN ULONG ipxHdrLength,
+ IN PVOID ifInContext,
+ IN PVOID ifOutContex
+ );
+
+/*++
+ D o I n t e r f a c e D e l e t e d
+
+Routine Description:
+ Resets interface contexts and calls filter dirver entry point
+ making sure that all no one holds reader access to filter driver
+ interface contexts
+Arguments:
+ ifCB - interface to be deleted
+Return Value:
+ None
+
+--*/
+VOID
+DoInterfaceDeleted (
+ PINTERFACE_CB ifCB
+ );
+
+#endif
+
diff --git a/private/ntos/tdi/isn/fwd/fwd.mak b/private/ntos/tdi/isn/fwd/fwd.mak
new file mode 100644
index 000000000..e47660250
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/fwd.mak
@@ -0,0 +1,2427 @@
+# Microsoft Developer Studio Generated NMAKE File, Format Version 4.10
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (PPC) Dynamic-Link Library" 0x0702
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+!IF "$(CFG)" == ""
+CFG=fwd - Win32 Release
+!MESSAGE No configuration specified. Defaulting to fwd - Win32 Release.
+!ENDIF
+
+!IF "$(CFG)" != "fwd - Win32 Release" && "$(CFG)" !=\
+ "fwd - Win32 (PPC) Release"
+!MESSAGE Invalid configuration "$(CFG)" specified.
+!MESSAGE You can specify a configuration when running NMAKE on this makefile
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "fwd.mak" CFG="fwd - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "fwd - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "fwd - Win32 (PPC) Release" (based on\
+ "Win32 (PPC) Dynamic-Link Library")
+!MESSAGE
+!ERROR An invalid configuration is specified.
+!ENDIF
+
+!IF "$(OS)" == "Windows_NT"
+NULL=
+!ELSE
+NULL=nul
+!ENDIF
+################################################################################
+# Begin Project
+# PROP Target_Last_Scanned "fwd - Win32 Release"
+
+!IF "$(CFG)" == "fwd - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+OUTDIR=.\Release
+INTDIR=.\Release
+
+ALL : "$(OUTDIR)\fwd.dll"
+
+CLEAN :
+ -@erase "$(INTDIR)\ddreqs.obj"
+ -@erase "$(INTDIR)\debug.obj"
+ -@erase "$(INTDIR)\driver.obj"
+ -@erase "$(INTDIR)\filterif.obj"
+ -@erase "$(INTDIR)\ipxbind.obj"
+ -@erase "$(INTDIR)\lineind.obj"
+ -@erase "$(INTDIR)\netbios.obj"
+ -@erase "$(INTDIR)\nwlnkfwd.res"
+ -@erase "$(INTDIR)\packets.obj"
+ -@erase "$(INTDIR)\rcvind.obj"
+ -@erase "$(INTDIR)\registry.obj"
+ -@erase "$(INTDIR)\send.obj"
+ -@erase "$(INTDIR)\tables.obj"
+ -@erase "$(OUTDIR)\fwd.dll"
+ -@erase "$(OUTDIR)\fwd.exp"
+ -@erase "$(OUTDIR)\fwd.lib"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CPP=cl.exe
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\inc" /I "..\..\inc" /I "..\..\..\inc" /I "..\..\..\..\net\routing\inc" /I "..\..\..\..\inc" /D _X86_=1 /D i386=1 /D "STD_CALL" /D CONDITION_HANDLING=1 /D NT_UP=1 /D NT_INST=0 /D WIN32=100 /D _NT1X_=100 /D WINNT=1 /D WIN32_LEAN_AND_MEAN=1 /D DBG=1 /D DEVL=1 /D FPO=0 /D "_NTDRIVER_" /YX /c
+CPP_PROJ=/nologo /MT /W3 /GX /O2 /I "..\inc" /I "..\..\inc" /I "..\..\..\inc"\
+ /I "..\..\..\..\net\routing\inc" /I "..\..\..\..\inc" /D _X86_=1 /D i386=1 /D\
+ "STD_CALL" /D CONDITION_HANDLING=1 /D NT_UP=1 /D NT_INST=0 /D WIN32=100 /D\
+ _NT1X_=100 /D WINNT=1 /D WIN32_LEAN_AND_MEAN=1 /D DBG=1 /D DEVL=1 /D FPO=0 /D\
+ "_NTDRIVER_" /Fp"$(INTDIR)/fwd.pch" /YX /Fo"$(INTDIR)/" /c
+CPP_OBJS=.\Release/
+CPP_SBRS=.\.
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+MTL=mktyplib.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /win32
+# ADD MTL /nologo /D "NDEBUG" /win32
+MTL_PROJ=/nologo /D "NDEBUG" /win32
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)/nwlnkfwd.res" /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/fwd.bsc"
+BSC32_SBRS= \
+
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /machine:I386
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo\
+ /subsystem:windows /dll /incremental:no /pdb:"$(OUTDIR)/fwd.pdb" /machine:I386\
+ /out:"$(OUTDIR)/fwd.dll" /implib:"$(OUTDIR)/fwd.lib"
+LINK32_OBJS= \
+ "$(INTDIR)\ddreqs.obj" \
+ "$(INTDIR)\debug.obj" \
+ "$(INTDIR)\driver.obj" \
+ "$(INTDIR)\filterif.obj" \
+ "$(INTDIR)\ipxbind.obj" \
+ "$(INTDIR)\lineind.obj" \
+ "$(INTDIR)\netbios.obj" \
+ "$(INTDIR)\nwlnkfwd.res" \
+ "$(INTDIR)\packets.obj" \
+ "$(INTDIR)\rcvind.obj" \
+ "$(INTDIR)\registry.obj" \
+ "$(INTDIR)\send.obj" \
+ "$(INTDIR)\tables.obj"
+
+"$(OUTDIR)\fwd.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ELSEIF "$(CFG)" == "fwd - Win32 (PPC) Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "fwd___Wi"
+# PROP BASE Intermediate_Dir "fwd___Wi"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "fwd___Wi"
+# PROP Intermediate_Dir "fwd___Wi"
+# PROP Target_Dir ""
+OUTDIR=.\fwd___Wi
+INTDIR=.\fwd___Wi
+
+ALL : "$(OUTDIR)\fwd.dll"
+
+"$(OUTDIR)" :
+ if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)"
+
+CLEAN :
+ -@erase ".\fwd___Wi\fwd.dll"
+ -@erase ".\fwd___Wi\Tables.obj"
+ -@erase ".\fwd___Wi\rcvind.obj"
+ -@erase ".\fwd___Wi\packets.obj"
+ -@erase ".\fwd___Wi\ipxbind.obj"
+ -@erase ".\fwd___Wi\driver.obj"
+ -@erase ".\fwd___Wi\send.obj"
+ -@erase ".\fwd___Wi\registry.obj"
+ -@erase ".\fwd___Wi\netbios.obj"
+ -@erase ".\fwd___Wi\lineind.obj"
+ -@erase ".\fwd___Wi\nwlnkfwd.res"
+ -@erase ".\fwd___Wi\fwd.lib"
+ -@erase ".\fwd___Wi\fwd.exp"
+
+MTL=mktyplib.exe
+# ADD BASE MTL /nologo /D "NDEBUG" /PPC32
+# ADD MTL /nologo /D "NDEBUG" /PPC32
+MTL_PROJ=/nologo /D "NDEBUG" /PPC32
+CPP=cl.exe
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
+# ADD CPP /nologo /W3 /Z7 /Oi /Gy /I "..\inc" /I "..\..\..\inc" /I "..\..\..\..\inc" /I "e:\NT\public\oak\inc" /I "e:\NT\public\sdk\inc" /I "e:\NT\public\sdk\inc\crt" /FI"e:\NT\public\sdk\inc\warning.h" /D PPC=1 /D _PPC_=1 /D "NO_EXT_KEYS" /D CONDITION_HANDLING=1 /D NT_UP=1 /D NT_INST=0 /D WIN32=100 /D _NT1X_=100 /D WINNT=1 /D WIN32_LEAN_AND_MEAN=1 /D _M_PPC=1 /D DBG=1 /D DEVL=1 /D "_NTDRIVER_" /D __stdcall= /D __cdecl= /D _cdecl= /D cdecl= /D FPO=1 /D "LANGUAGE_C" -Zel -ZB64 /c
+CPP_PROJ=/nologo /ML /W3 /Z7 /Oi /Gy /I "..\inc" /I "..\..\..\inc" /I\
+ "..\..\..\..\inc" /I "e:\NT\public\oak\inc" /I "e:\NT\public\sdk\inc" /I\
+ "e:\NT\public\sdk\inc\crt" /FI"e:\NT\public\sdk\inc\warning.h" /D PPC=1 /D\
+ _PPC_=1 /D "NO_EXT_KEYS" /D CONDITION_HANDLING=1 /D NT_UP=1 /D NT_INST=0 /D\
+ WIN32=100 /D _NT1X_=100 /D WINNT=1 /D WIN32_LEAN_AND_MEAN=1 /D _M_PPC=1 /D\
+ DBG=1 /D DEVL=1 /D "_NTDRIVER_" /D __stdcall= /D __cdecl= /D _cdecl= /D cdecl=\
+ /D FPO=1 /D "LANGUAGE_C" /Fo"$(INTDIR)/" -Zel -ZB64 /c
+CPP_OBJS=.\fwd___Wi/
+CPP_SBRS=
+
+.c{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_OBJS)}.obj:
+ $(CPP) $(CPP_PROJ) $<
+
+.c{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cpp{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+.cxx{$(CPP_SBRS)}.sbr:
+ $(CPP) $(CPP_PROJ) $<
+
+RSC=rc.exe
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+RSC_PROJ=/l 0x409 /fo"$(INTDIR)/nwlnkfwd.res" /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+BSC32_FLAGS=/nologo /o"$(OUTDIR)/fwd.bsc"
+BSC32_SBRS=
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /machine:PPC
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /subsystem:windows /dll /machine:PPC
+LINK32_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib\
+ advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo\
+ /subsystem:windows /dll /pdb:"$(OUTDIR)/fwd.pdb" /machine:PPC\
+ /out:"$(OUTDIR)/fwd.dll" /implib:"$(OUTDIR)/fwd.lib"
+LINK32_OBJS= \
+ "$(INTDIR)/Tables.obj" \
+ "$(INTDIR)/rcvind.obj" \
+ "$(INTDIR)/packets.obj" \
+ "$(INTDIR)/ipxbind.obj" \
+ "$(INTDIR)/driver.obj" \
+ "$(INTDIR)/send.obj" \
+ "$(INTDIR)/registry.obj" \
+ "$(INTDIR)/netbios.obj" \
+ "$(INTDIR)/lineind.obj" \
+ "$(INTDIR)/nwlnkfwd.res"
+
+"$(OUTDIR)\fwd.dll" : "$(OUTDIR)" $(DEF_FILE) $(LINK32_OBJS)
+ $(LINK32) @<<
+ $(LINK32_FLAGS) $(LINK32_OBJS)
+<<
+
+!ENDIF
+
+################################################################################
+# Begin Target
+
+# Name "fwd - Win32 Release"
+# Name "fwd - Win32 (PPC) Release"
+
+!IF "$(CFG)" == "fwd - Win32 Release"
+
+!ELSEIF "$(CFG)" == "fwd - Win32 (PPC) Release"
+
+!ENDIF
+
+################################################################################
+# Begin Source File
+
+SOURCE=.\sources.inc
+
+!IF "$(CFG)" == "fwd - Win32 Release"
+
+!ELSEIF "$(CFG)" == "fwd - Win32 (PPC) Release"
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\send.c
+
+!IF "$(CFG)" == "fwd - Win32 Release"
+
+DEP_CPP_SEND_=\
+ "..\..\..\..\inc\ipxfwd.h"\
+ "..\..\..\..\inc\nettypes.h"\
+ "..\..\..\..\inc\packoff.h"\
+ "..\..\..\..\inc\packon.h"\
+ "..\..\..\..\inc\tdi.h"\
+ "..\..\..\..\inc\tdikrnl.h"\
+ "..\..\..\inc\afilter.h"\
+ "..\..\..\inc\bugcodes.h"\
+ "..\..\..\inc\efilter.h"\
+ "..\..\..\inc\exlevels.h"\
+ "..\..\..\inc\ffilter.h"\
+ "..\..\..\inc\ndis.h"\
+ "..\..\..\inc\ntddk.h"\
+ "..\..\..\inc\ntiologc.h"\
+ "..\..\..\inc\ntos.h"\
+ "..\..\..\inc\tfilter.h"\
+ "..\inc\bind.h"\
+ "..\inc\ipxfltif.h"\
+ "..\inc\isnkrnl.h"\
+ ".\..\..\..\inc\alpha.h"\
+ ".\..\..\..\inc\alpharef.h"\
+ ".\..\..\..\inc\arc.h"\
+ ".\..\..\..\inc\cache.h"\
+ ".\..\..\..\inc\cm.h"\
+ ".\..\..\..\inc\dbgk.h"\
+ ".\..\..\..\inc\ex.h"\
+ ".\..\..\..\inc\exboosts.h"\
+ ".\..\..\..\inc\hal.h"\
+ ".\..\..\..\inc\i386.h"\
+ ".\..\..\..\inc\init.h"\
+ ".\..\..\..\inc\kd.h"\
+ ".\..\..\..\inc\ke.h"\
+ ".\..\..\..\inc\lfs.h"\
+ ".\..\..\..\inc\lpc.h"\
+ ".\..\..\..\inc\mips.h"\
+ ".\..\..\..\inc\mm.h"\
+ ".\..\..\..\inc\ntosdef.h"\
+ ".\..\..\..\inc\ob.h"\
+ ".\..\..\..\inc\pnp.h"\
+ ".\..\..\..\inc\po.h"\
+ ".\..\..\..\inc\ppc.h"\
+ ".\..\..\..\inc\ps.h"\
+ ".\..\..\..\inc\se.h"\
+ ".\..\..\..\inc\v86emul.h"\
+ ".\ddreqs.h"\
+ ".\debug.h"\
+ ".\driver.h"\
+ ".\filterif.h"\
+ ".\fwddefs.h"\
+ ".\ipxbind.h"\
+ ".\lineind.h"\
+ ".\netbios.h"\
+ ".\packets.h"\
+ ".\precomp.h"\
+ ".\rcvind.h"\
+ ".\registry.h"\
+ ".\rwlock.h"\
+ ".\send.h"\
+ ".\tables.h"\
+ "c:\nt\public\sdk\inc\mipsinst.h"\
+ "c:\nt\public\sdk\inc\ntalpha.h"\
+ "c:\nt\public\sdk\inc\nti386.h"\
+ "c:\nt\public\sdk\inc\ntmips.h"\
+ "c:\nt\public\sdk\inc\ntppc.h"\
+ "c:\nt\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\cfg.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+ {$(INCLUDE)}"\netevent.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntconfig.h"\
+ {$(INCLUDE)}"\ntddndis.h"\
+ {$(INCLUDE)}"\ntddtdi.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntelfapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntmmapi.h"\
+ {$(INCLUDE)}"\ntnls.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntpnpapi.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntregapi.h"\
+ {$(INCLUDE)}"\ntrtl.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\zwapi.h"\
+
+
+"$(INTDIR)\send.obj" : $(SOURCE) $(DEP_CPP_SEND_) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "fwd - Win32 (PPC) Release"
+
+DEP_CPP_SEND_=\
+ "..\..\..\..\inc\nettypes.h"\
+ "..\..\..\..\inc\packoff.h"\
+ "..\..\..\..\inc\packon.h"\
+ "..\..\..\..\inc\tdi.h"\
+ "..\..\..\..\inc\tdikrnl.h"\
+ "..\..\..\inc\afilter.h"\
+ "..\..\..\inc\bugcodes.h"\
+ "..\..\..\inc\efilter.h"\
+ "..\..\..\inc\exlevels.h"\
+ "..\..\..\inc\ffilter.h"\
+ "..\..\..\inc\ndis.h"\
+ "..\..\..\inc\ntddk.h"\
+ "..\..\..\inc\ntiologc.h"\
+ "..\..\..\inc\ntos.h"\
+ "..\..\..\inc\tfilter.h"\
+ "..\inc\bind.h"\
+ "..\inc\isnkrnl.h"\
+ ".\..\..\..\inc\alpha.h"\
+ ".\..\..\..\inc\alpharef.h"\
+ ".\..\..\..\inc\arc.h"\
+ ".\..\..\..\inc\cache.h"\
+ ".\..\..\..\inc\cm.h"\
+ ".\..\..\..\inc\dbgk.h"\
+ ".\..\..\..\inc\ex.h"\
+ ".\..\..\..\inc\exboosts.h"\
+ ".\..\..\..\inc\hal.h"\
+ ".\..\..\..\inc\i386.h"\
+ ".\..\..\..\inc\init.h"\
+ ".\..\..\..\inc\kd.h"\
+ ".\..\..\..\inc\ke.h"\
+ ".\..\..\..\inc\lfs.h"\
+ ".\..\..\..\inc\lpc.h"\
+ ".\..\..\..\inc\mips.h"\
+ ".\..\..\..\inc\mm.h"\
+ ".\..\..\..\inc\ntmp.h"\
+ ".\..\..\..\inc\ntosdef.h"\
+ ".\..\..\..\inc\ob.h"\
+ ".\..\..\..\inc\pnp.h"\
+ ".\..\..\..\inc\po.h"\
+ ".\..\..\..\inc\ppc.h"\
+ ".\..\..\..\inc\ps.h"\
+ ".\..\..\..\inc\se.h"\
+ ".\..\..\..\inc\v86emul.h"\
+ ".\..\inc\ipxfwd.h"\
+ ".\debug.h"\
+ ".\driver.h"\
+ ".\ipxbind.h"\
+ ".\lineind.h"\
+ ".\netbios.h"\
+ ".\packets.h"\
+ ".\rcvind.h"\
+ ".\registry.h"\
+ ".\send.h"\
+ ".\tables.h"\
+ "e:\NT\public\oak\inc\zwapi.h"\
+ "e:\NT\public\sdk\inc\cfg.h"\
+ "e:\NT\public\sdk\inc\devioctl.h"\
+ "E:\NT\public\sdk\inc\mipsinst.h"\
+ "e:\NT\public\sdk\inc\netevent.h"\
+ "e:\NT\public\sdk\inc\nt.h"\
+ "E:\nt\public\sdk\inc\ntalpha.h"\
+ "e:\NT\public\sdk\inc\ntconfig.h"\
+ "e:\NT\public\sdk\inc\ntddndis.h"\
+ "e:\NT\public\sdk\inc\ntddtdi.h"\
+ "e:\NT\public\sdk\inc\ntdef.h"\
+ "e:\NT\public\sdk\inc\ntelfapi.h"\
+ "e:\NT\public\sdk\inc\ntexapi.h"\
+ "E:\nt\public\sdk\inc\nti386.h"\
+ "e:\NT\public\sdk\inc\ntimage.h"\
+ "e:\NT\public\sdk\inc\ntioapi.h"\
+ "e:\NT\public\sdk\inc\ntiolog.h"\
+ "e:\NT\public\sdk\inc\ntkeapi.h"\
+ "e:\NT\public\sdk\inc\ntkxapi.h"\
+ "e:\NT\public\sdk\inc\ntldr.h"\
+ "e:\NT\public\sdk\inc\ntlpcapi.h"\
+ "E:\nt\public\sdk\inc\ntmips.h"\
+ "e:\NT\public\sdk\inc\ntmmapi.h"\
+ "e:\NT\public\sdk\inc\ntnls.h"\
+ "e:\NT\public\sdk\inc\ntobapi.h"\
+ "e:\NT\public\sdk\inc\ntpnpapi.h"\
+ "e:\NT\public\sdk\inc\ntpoapi.h"\
+ "E:\nt\public\sdk\inc\ntppc.h"\
+ "e:\NT\public\sdk\inc\ntpsapi.h"\
+ "e:\NT\public\sdk\inc\ntregapi.h"\
+ "e:\NT\public\sdk\inc\ntrtl.h"\
+ "e:\NT\public\sdk\inc\ntseapi.h"\
+ "e:\NT\public\sdk\inc\ntstatus.h"\
+ "e:\NT\public\sdk\inc\ntxcapi.h"\
+ "E:\NT\public\sdk\inc\ppcinst.h"\
+
+
+"$(INTDIR)\send.obj" : $(SOURCE) $(DEP_CPP_SEND_) "$(INTDIR)"
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\rcvind.c
+
+!IF "$(CFG)" == "fwd - Win32 Release"
+
+DEP_CPP_RCVIN=\
+ "..\..\..\..\inc\ipxfwd.h"\
+ "..\..\..\..\inc\nettypes.h"\
+ "..\..\..\..\inc\packoff.h"\
+ "..\..\..\..\inc\packon.h"\
+ "..\..\..\..\inc\tdi.h"\
+ "..\..\..\..\inc\tdikrnl.h"\
+ "..\..\..\inc\afilter.h"\
+ "..\..\..\inc\bugcodes.h"\
+ "..\..\..\inc\efilter.h"\
+ "..\..\..\inc\exlevels.h"\
+ "..\..\..\inc\ffilter.h"\
+ "..\..\..\inc\ndis.h"\
+ "..\..\..\inc\ntddk.h"\
+ "..\..\..\inc\ntiologc.h"\
+ "..\..\..\inc\ntos.h"\
+ "..\..\..\inc\tfilter.h"\
+ "..\inc\bind.h"\
+ "..\inc\ipxfltif.h"\
+ "..\inc\isnkrnl.h"\
+ ".\..\..\..\inc\alpha.h"\
+ ".\..\..\..\inc\alpharef.h"\
+ ".\..\..\..\inc\arc.h"\
+ ".\..\..\..\inc\cache.h"\
+ ".\..\..\..\inc\cm.h"\
+ ".\..\..\..\inc\dbgk.h"\
+ ".\..\..\..\inc\ex.h"\
+ ".\..\..\..\inc\exboosts.h"\
+ ".\..\..\..\inc\hal.h"\
+ ".\..\..\..\inc\i386.h"\
+ ".\..\..\..\inc\init.h"\
+ ".\..\..\..\inc\kd.h"\
+ ".\..\..\..\inc\ke.h"\
+ ".\..\..\..\inc\lfs.h"\
+ ".\..\..\..\inc\lpc.h"\
+ ".\..\..\..\inc\mips.h"\
+ ".\..\..\..\inc\mm.h"\
+ ".\..\..\..\inc\ntosdef.h"\
+ ".\..\..\..\inc\ob.h"\
+ ".\..\..\..\inc\pnp.h"\
+ ".\..\..\..\inc\po.h"\
+ ".\..\..\..\inc\ppc.h"\
+ ".\..\..\..\inc\ps.h"\
+ ".\..\..\..\inc\se.h"\
+ ".\..\..\..\inc\v86emul.h"\
+ ".\ddreqs.h"\
+ ".\debug.h"\
+ ".\driver.h"\
+ ".\filterif.h"\
+ ".\fwddefs.h"\
+ ".\ipxbind.h"\
+ ".\lineind.h"\
+ ".\netbios.h"\
+ ".\packets.h"\
+ ".\precomp.h"\
+ ".\rcvind.h"\
+ ".\registry.h"\
+ ".\rwlock.h"\
+ ".\send.h"\
+ ".\tables.h"\
+ "c:\nt\public\sdk\inc\mipsinst.h"\
+ "c:\nt\public\sdk\inc\ntalpha.h"\
+ "c:\nt\public\sdk\inc\nti386.h"\
+ "c:\nt\public\sdk\inc\ntmips.h"\
+ "c:\nt\public\sdk\inc\ntppc.h"\
+ "c:\nt\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\cfg.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+ {$(INCLUDE)}"\netevent.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntconfig.h"\
+ {$(INCLUDE)}"\ntddndis.h"\
+ {$(INCLUDE)}"\ntddtdi.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntelfapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntmmapi.h"\
+ {$(INCLUDE)}"\ntnls.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntpnpapi.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntregapi.h"\
+ {$(INCLUDE)}"\ntrtl.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\zwapi.h"\
+
+
+"$(INTDIR)\rcvind.obj" : $(SOURCE) $(DEP_CPP_RCVIN) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "fwd - Win32 (PPC) Release"
+
+DEP_CPP_RCVIN=\
+ "..\..\..\..\inc\nettypes.h"\
+ "..\..\..\..\inc\packoff.h"\
+ "..\..\..\..\inc\packon.h"\
+ "..\..\..\..\inc\tdi.h"\
+ "..\..\..\..\inc\tdikrnl.h"\
+ "..\..\..\inc\afilter.h"\
+ "..\..\..\inc\bugcodes.h"\
+ "..\..\..\inc\efilter.h"\
+ "..\..\..\inc\exlevels.h"\
+ "..\..\..\inc\ffilter.h"\
+ "..\..\..\inc\ndis.h"\
+ "..\..\..\inc\ntddk.h"\
+ "..\..\..\inc\ntiologc.h"\
+ "..\..\..\inc\ntos.h"\
+ "..\..\..\inc\tfilter.h"\
+ "..\inc\bind.h"\
+ "..\inc\isnkrnl.h"\
+ ".\..\..\..\inc\alpha.h"\
+ ".\..\..\..\inc\alpharef.h"\
+ ".\..\..\..\inc\arc.h"\
+ ".\..\..\..\inc\cache.h"\
+ ".\..\..\..\inc\cm.h"\
+ ".\..\..\..\inc\dbgk.h"\
+ ".\..\..\..\inc\ex.h"\
+ ".\..\..\..\inc\exboosts.h"\
+ ".\..\..\..\inc\hal.h"\
+ ".\..\..\..\inc\i386.h"\
+ ".\..\..\..\inc\init.h"\
+ ".\..\..\..\inc\kd.h"\
+ ".\..\..\..\inc\ke.h"\
+ ".\..\..\..\inc\lfs.h"\
+ ".\..\..\..\inc\lpc.h"\
+ ".\..\..\..\inc\mips.h"\
+ ".\..\..\..\inc\mm.h"\
+ ".\..\..\..\inc\ntmp.h"\
+ ".\..\..\..\inc\ntosdef.h"\
+ ".\..\..\..\inc\ob.h"\
+ ".\..\..\..\inc\pnp.h"\
+ ".\..\..\..\inc\po.h"\
+ ".\..\..\..\inc\ppc.h"\
+ ".\..\..\..\inc\ps.h"\
+ ".\..\..\..\inc\se.h"\
+ ".\..\..\..\inc\v86emul.h"\
+ ".\..\inc\ipxfwd.h"\
+ ".\debug.h"\
+ ".\driver.h"\
+ ".\ipxbind.h"\
+ ".\lineind.h"\
+ ".\netbios.h"\
+ ".\packets.h"\
+ ".\rcvind.h"\
+ ".\registry.h"\
+ ".\send.h"\
+ ".\tables.h"\
+ "e:\NT\public\oak\inc\zwapi.h"\
+ "e:\NT\public\sdk\inc\cfg.h"\
+ "e:\NT\public\sdk\inc\devioctl.h"\
+ "E:\NT\public\sdk\inc\mipsinst.h"\
+ "e:\NT\public\sdk\inc\netevent.h"\
+ "e:\NT\public\sdk\inc\nt.h"\
+ "E:\nt\public\sdk\inc\ntalpha.h"\
+ "e:\NT\public\sdk\inc\ntconfig.h"\
+ "e:\NT\public\sdk\inc\ntddndis.h"\
+ "e:\NT\public\sdk\inc\ntddtdi.h"\
+ "e:\NT\public\sdk\inc\ntdef.h"\
+ "e:\NT\public\sdk\inc\ntelfapi.h"\
+ "e:\NT\public\sdk\inc\ntexapi.h"\
+ "E:\nt\public\sdk\inc\nti386.h"\
+ "e:\NT\public\sdk\inc\ntimage.h"\
+ "e:\NT\public\sdk\inc\ntioapi.h"\
+ "e:\NT\public\sdk\inc\ntiolog.h"\
+ "e:\NT\public\sdk\inc\ntkeapi.h"\
+ "e:\NT\public\sdk\inc\ntkxapi.h"\
+ "e:\NT\public\sdk\inc\ntldr.h"\
+ "e:\NT\public\sdk\inc\ntlpcapi.h"\
+ "E:\nt\public\sdk\inc\ntmips.h"\
+ "e:\NT\public\sdk\inc\ntmmapi.h"\
+ "e:\NT\public\sdk\inc\ntnls.h"\
+ "e:\NT\public\sdk\inc\ntobapi.h"\
+ "e:\NT\public\sdk\inc\ntpnpapi.h"\
+ "e:\NT\public\sdk\inc\ntpoapi.h"\
+ "E:\nt\public\sdk\inc\ntppc.h"\
+ "e:\NT\public\sdk\inc\ntpsapi.h"\
+ "e:\NT\public\sdk\inc\ntregapi.h"\
+ "e:\NT\public\sdk\inc\ntrtl.h"\
+ "e:\NT\public\sdk\inc\ntseapi.h"\
+ "e:\NT\public\sdk\inc\ntstatus.h"\
+ "e:\NT\public\sdk\inc\ntxcapi.h"\
+ "E:\NT\public\sdk\inc\ppcinst.h"\
+
+
+"$(INTDIR)\rcvind.obj" : $(SOURCE) $(DEP_CPP_RCVIN) "$(INTDIR)"
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\netbios.c
+
+!IF "$(CFG)" == "fwd - Win32 Release"
+
+DEP_CPP_NETBI=\
+ "..\..\..\..\inc\ipxfwd.h"\
+ "..\..\..\..\inc\nettypes.h"\
+ "..\..\..\..\inc\packoff.h"\
+ "..\..\..\..\inc\packon.h"\
+ "..\..\..\..\inc\tdi.h"\
+ "..\..\..\..\inc\tdikrnl.h"\
+ "..\..\..\inc\afilter.h"\
+ "..\..\..\inc\bugcodes.h"\
+ "..\..\..\inc\efilter.h"\
+ "..\..\..\inc\exlevels.h"\
+ "..\..\..\inc\ffilter.h"\
+ "..\..\..\inc\ndis.h"\
+ "..\..\..\inc\ntddk.h"\
+ "..\..\..\inc\ntiologc.h"\
+ "..\..\..\inc\ntos.h"\
+ "..\..\..\inc\tfilter.h"\
+ "..\inc\bind.h"\
+ "..\inc\ipxfltif.h"\
+ "..\inc\isnkrnl.h"\
+ ".\..\..\..\inc\alpha.h"\
+ ".\..\..\..\inc\alpharef.h"\
+ ".\..\..\..\inc\arc.h"\
+ ".\..\..\..\inc\cache.h"\
+ ".\..\..\..\inc\cm.h"\
+ ".\..\..\..\inc\dbgk.h"\
+ ".\..\..\..\inc\ex.h"\
+ ".\..\..\..\inc\exboosts.h"\
+ ".\..\..\..\inc\hal.h"\
+ ".\..\..\..\inc\i386.h"\
+ ".\..\..\..\inc\init.h"\
+ ".\..\..\..\inc\kd.h"\
+ ".\..\..\..\inc\ke.h"\
+ ".\..\..\..\inc\lfs.h"\
+ ".\..\..\..\inc\lpc.h"\
+ ".\..\..\..\inc\mips.h"\
+ ".\..\..\..\inc\mm.h"\
+ ".\..\..\..\inc\ntosdef.h"\
+ ".\..\..\..\inc\ob.h"\
+ ".\..\..\..\inc\pnp.h"\
+ ".\..\..\..\inc\po.h"\
+ ".\..\..\..\inc\ppc.h"\
+ ".\..\..\..\inc\ps.h"\
+ ".\..\..\..\inc\se.h"\
+ ".\..\..\..\inc\v86emul.h"\
+ ".\ddreqs.h"\
+ ".\debug.h"\
+ ".\driver.h"\
+ ".\filterif.h"\
+ ".\fwddefs.h"\
+ ".\ipxbind.h"\
+ ".\lineind.h"\
+ ".\netbios.h"\
+ ".\packets.h"\
+ ".\precomp.h"\
+ ".\rcvind.h"\
+ ".\registry.h"\
+ ".\rwlock.h"\
+ ".\send.h"\
+ ".\tables.h"\
+ "c:\nt\public\sdk\inc\mipsinst.h"\
+ "c:\nt\public\sdk\inc\ntalpha.h"\
+ "c:\nt\public\sdk\inc\nti386.h"\
+ "c:\nt\public\sdk\inc\ntmips.h"\
+ "c:\nt\public\sdk\inc\ntppc.h"\
+ "c:\nt\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\cfg.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+ {$(INCLUDE)}"\netevent.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntconfig.h"\
+ {$(INCLUDE)}"\ntddndis.h"\
+ {$(INCLUDE)}"\ntddtdi.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntelfapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntmmapi.h"\
+ {$(INCLUDE)}"\ntnls.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntpnpapi.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntregapi.h"\
+ {$(INCLUDE)}"\ntrtl.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\zwapi.h"\
+
+
+"$(INTDIR)\netbios.obj" : $(SOURCE) $(DEP_CPP_NETBI) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "fwd - Win32 (PPC) Release"
+
+DEP_CPP_NETBI=\
+ "..\..\..\..\inc\nettypes.h"\
+ "..\..\..\..\inc\packoff.h"\
+ "..\..\..\..\inc\packon.h"\
+ "..\..\..\..\inc\tdi.h"\
+ "..\..\..\..\inc\tdikrnl.h"\
+ "..\..\..\inc\afilter.h"\
+ "..\..\..\inc\bugcodes.h"\
+ "..\..\..\inc\efilter.h"\
+ "..\..\..\inc\exlevels.h"\
+ "..\..\..\inc\ffilter.h"\
+ "..\..\..\inc\ndis.h"\
+ "..\..\..\inc\ntddk.h"\
+ "..\..\..\inc\ntiologc.h"\
+ "..\..\..\inc\ntos.h"\
+ "..\..\..\inc\tfilter.h"\
+ "..\inc\bind.h"\
+ "..\inc\isnkrnl.h"\
+ ".\..\..\..\inc\alpha.h"\
+ ".\..\..\..\inc\alpharef.h"\
+ ".\..\..\..\inc\arc.h"\
+ ".\..\..\..\inc\cache.h"\
+ ".\..\..\..\inc\cm.h"\
+ ".\..\..\..\inc\dbgk.h"\
+ ".\..\..\..\inc\ex.h"\
+ ".\..\..\..\inc\exboosts.h"\
+ ".\..\..\..\inc\hal.h"\
+ ".\..\..\..\inc\i386.h"\
+ ".\..\..\..\inc\init.h"\
+ ".\..\..\..\inc\kd.h"\
+ ".\..\..\..\inc\ke.h"\
+ ".\..\..\..\inc\lfs.h"\
+ ".\..\..\..\inc\lpc.h"\
+ ".\..\..\..\inc\mips.h"\
+ ".\..\..\..\inc\mm.h"\
+ ".\..\..\..\inc\ntmp.h"\
+ ".\..\..\..\inc\ntosdef.h"\
+ ".\..\..\..\inc\ob.h"\
+ ".\..\..\..\inc\pnp.h"\
+ ".\..\..\..\inc\po.h"\
+ ".\..\..\..\inc\ppc.h"\
+ ".\..\..\..\inc\ps.h"\
+ ".\..\..\..\inc\se.h"\
+ ".\..\..\..\inc\v86emul.h"\
+ ".\..\inc\ipxfwd.h"\
+ ".\debug.h"\
+ ".\driver.h"\
+ ".\ipxbind.h"\
+ ".\lineind.h"\
+ ".\netbios.h"\
+ ".\packets.h"\
+ ".\rcvind.h"\
+ ".\registry.h"\
+ ".\send.h"\
+ ".\tables.h"\
+ "e:\NT\public\oak\inc\zwapi.h"\
+ "e:\NT\public\sdk\inc\cfg.h"\
+ "e:\NT\public\sdk\inc\devioctl.h"\
+ "E:\NT\public\sdk\inc\mipsinst.h"\
+ "e:\NT\public\sdk\inc\netevent.h"\
+ "e:\NT\public\sdk\inc\nt.h"\
+ "E:\nt\public\sdk\inc\ntalpha.h"\
+ "e:\NT\public\sdk\inc\ntconfig.h"\
+ "e:\NT\public\sdk\inc\ntddndis.h"\
+ "e:\NT\public\sdk\inc\ntddtdi.h"\
+ "e:\NT\public\sdk\inc\ntdef.h"\
+ "e:\NT\public\sdk\inc\ntelfapi.h"\
+ "e:\NT\public\sdk\inc\ntexapi.h"\
+ "E:\nt\public\sdk\inc\nti386.h"\
+ "e:\NT\public\sdk\inc\ntimage.h"\
+ "e:\NT\public\sdk\inc\ntioapi.h"\
+ "e:\NT\public\sdk\inc\ntiolog.h"\
+ "e:\NT\public\sdk\inc\ntkeapi.h"\
+ "e:\NT\public\sdk\inc\ntkxapi.h"\
+ "e:\NT\public\sdk\inc\ntldr.h"\
+ "e:\NT\public\sdk\inc\ntlpcapi.h"\
+ "E:\nt\public\sdk\inc\ntmips.h"\
+ "e:\NT\public\sdk\inc\ntmmapi.h"\
+ "e:\NT\public\sdk\inc\ntnls.h"\
+ "e:\NT\public\sdk\inc\ntobapi.h"\
+ "e:\NT\public\sdk\inc\ntpnpapi.h"\
+ "e:\NT\public\sdk\inc\ntpoapi.h"\
+ "E:\nt\public\sdk\inc\ntppc.h"\
+ "e:\NT\public\sdk\inc\ntpsapi.h"\
+ "e:\NT\public\sdk\inc\ntregapi.h"\
+ "e:\NT\public\sdk\inc\ntrtl.h"\
+ "e:\NT\public\sdk\inc\ntseapi.h"\
+ "e:\NT\public\sdk\inc\ntstatus.h"\
+ "e:\NT\public\sdk\inc\ntxcapi.h"\
+ "E:\NT\public\sdk\inc\ppcinst.h"\
+
+
+"$(INTDIR)\netbios.obj" : $(SOURCE) $(DEP_CPP_NETBI) "$(INTDIR)"
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\lineind.c
+
+!IF "$(CFG)" == "fwd - Win32 Release"
+
+DEP_CPP_LINEI=\
+ "..\..\..\..\inc\ipxfwd.h"\
+ "..\..\..\..\inc\nettypes.h"\
+ "..\..\..\..\inc\packoff.h"\
+ "..\..\..\..\inc\packon.h"\
+ "..\..\..\..\inc\tdi.h"\
+ "..\..\..\..\inc\tdikrnl.h"\
+ "..\..\..\inc\afilter.h"\
+ "..\..\..\inc\bugcodes.h"\
+ "..\..\..\inc\efilter.h"\
+ "..\..\..\inc\exlevels.h"\
+ "..\..\..\inc\ffilter.h"\
+ "..\..\..\inc\ndis.h"\
+ "..\..\..\inc\ntddk.h"\
+ "..\..\..\inc\ntiologc.h"\
+ "..\..\..\inc\ntos.h"\
+ "..\..\..\inc\tfilter.h"\
+ "..\inc\bind.h"\
+ "..\inc\ipxfltif.h"\
+ "..\inc\isnkrnl.h"\
+ ".\..\..\..\inc\alpha.h"\
+ ".\..\..\..\inc\alpharef.h"\
+ ".\..\..\..\inc\arc.h"\
+ ".\..\..\..\inc\cache.h"\
+ ".\..\..\..\inc\cm.h"\
+ ".\..\..\..\inc\dbgk.h"\
+ ".\..\..\..\inc\ex.h"\
+ ".\..\..\..\inc\exboosts.h"\
+ ".\..\..\..\inc\hal.h"\
+ ".\..\..\..\inc\i386.h"\
+ ".\..\..\..\inc\init.h"\
+ ".\..\..\..\inc\kd.h"\
+ ".\..\..\..\inc\ke.h"\
+ ".\..\..\..\inc\lfs.h"\
+ ".\..\..\..\inc\lpc.h"\
+ ".\..\..\..\inc\mips.h"\
+ ".\..\..\..\inc\mm.h"\
+ ".\..\..\..\inc\ntosdef.h"\
+ ".\..\..\..\inc\ob.h"\
+ ".\..\..\..\inc\pnp.h"\
+ ".\..\..\..\inc\po.h"\
+ ".\..\..\..\inc\ppc.h"\
+ ".\..\..\..\inc\ps.h"\
+ ".\..\..\..\inc\se.h"\
+ ".\..\..\..\inc\v86emul.h"\
+ ".\ddreqs.h"\
+ ".\debug.h"\
+ ".\driver.h"\
+ ".\filterif.h"\
+ ".\fwddefs.h"\
+ ".\ipxbind.h"\
+ ".\lineind.h"\
+ ".\netbios.h"\
+ ".\packets.h"\
+ ".\precomp.h"\
+ ".\rcvind.h"\
+ ".\registry.h"\
+ ".\rwlock.h"\
+ ".\send.h"\
+ ".\tables.h"\
+ "c:\nt\public\sdk\inc\mipsinst.h"\
+ "c:\nt\public\sdk\inc\ntalpha.h"\
+ "c:\nt\public\sdk\inc\nti386.h"\
+ "c:\nt\public\sdk\inc\ntmips.h"\
+ "c:\nt\public\sdk\inc\ntppc.h"\
+ "c:\nt\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\cfg.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+ {$(INCLUDE)}"\netevent.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntconfig.h"\
+ {$(INCLUDE)}"\ntddndis.h"\
+ {$(INCLUDE)}"\ntddtdi.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntelfapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntmmapi.h"\
+ {$(INCLUDE)}"\ntnls.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntpnpapi.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntregapi.h"\
+ {$(INCLUDE)}"\ntrtl.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\zwapi.h"\
+
+
+"$(INTDIR)\lineind.obj" : $(SOURCE) $(DEP_CPP_LINEI) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "fwd - Win32 (PPC) Release"
+
+DEP_CPP_LINEI=\
+ "..\..\..\..\inc\nettypes.h"\
+ "..\..\..\..\inc\packoff.h"\
+ "..\..\..\..\inc\packon.h"\
+ "..\..\..\..\inc\tdi.h"\
+ "..\..\..\..\inc\tdikrnl.h"\
+ "..\..\..\inc\afilter.h"\
+ "..\..\..\inc\bugcodes.h"\
+ "..\..\..\inc\efilter.h"\
+ "..\..\..\inc\exlevels.h"\
+ "..\..\..\inc\ffilter.h"\
+ "..\..\..\inc\ndis.h"\
+ "..\..\..\inc\ntddk.h"\
+ "..\..\..\inc\ntiologc.h"\
+ "..\..\..\inc\ntos.h"\
+ "..\..\..\inc\tfilter.h"\
+ "..\inc\bind.h"\
+ "..\inc\isnkrnl.h"\
+ ".\..\..\..\inc\alpha.h"\
+ ".\..\..\..\inc\alpharef.h"\
+ ".\..\..\..\inc\arc.h"\
+ ".\..\..\..\inc\cache.h"\
+ ".\..\..\..\inc\cm.h"\
+ ".\..\..\..\inc\dbgk.h"\
+ ".\..\..\..\inc\ex.h"\
+ ".\..\..\..\inc\exboosts.h"\
+ ".\..\..\..\inc\hal.h"\
+ ".\..\..\..\inc\i386.h"\
+ ".\..\..\..\inc\init.h"\
+ ".\..\..\..\inc\kd.h"\
+ ".\..\..\..\inc\ke.h"\
+ ".\..\..\..\inc\lfs.h"\
+ ".\..\..\..\inc\lpc.h"\
+ ".\..\..\..\inc\mips.h"\
+ ".\..\..\..\inc\mm.h"\
+ ".\..\..\..\inc\ntmp.h"\
+ ".\..\..\..\inc\ntosdef.h"\
+ ".\..\..\..\inc\ob.h"\
+ ".\..\..\..\inc\pnp.h"\
+ ".\..\..\..\inc\po.h"\
+ ".\..\..\..\inc\ppc.h"\
+ ".\..\..\..\inc\ps.h"\
+ ".\..\..\..\inc\se.h"\
+ ".\..\..\..\inc\v86emul.h"\
+ ".\..\inc\ipxfwd.h"\
+ ".\debug.h"\
+ ".\driver.h"\
+ ".\ipxbind.h"\
+ ".\lineind.h"\
+ ".\netbios.h"\
+ ".\packets.h"\
+ ".\rcvind.h"\
+ ".\registry.h"\
+ ".\send.h"\
+ ".\tables.h"\
+ "e:\NT\public\oak\inc\zwapi.h"\
+ "e:\NT\public\sdk\inc\cfg.h"\
+ "e:\NT\public\sdk\inc\devioctl.h"\
+ "E:\NT\public\sdk\inc\mipsinst.h"\
+ "e:\NT\public\sdk\inc\netevent.h"\
+ "e:\NT\public\sdk\inc\nt.h"\
+ "E:\nt\public\sdk\inc\ntalpha.h"\
+ "e:\NT\public\sdk\inc\ntconfig.h"\
+ "e:\NT\public\sdk\inc\ntddndis.h"\
+ "e:\NT\public\sdk\inc\ntddtdi.h"\
+ "e:\NT\public\sdk\inc\ntdef.h"\
+ "e:\NT\public\sdk\inc\ntelfapi.h"\
+ "e:\NT\public\sdk\inc\ntexapi.h"\
+ "E:\nt\public\sdk\inc\nti386.h"\
+ "e:\NT\public\sdk\inc\ntimage.h"\
+ "e:\NT\public\sdk\inc\ntioapi.h"\
+ "e:\NT\public\sdk\inc\ntiolog.h"\
+ "e:\NT\public\sdk\inc\ntkeapi.h"\
+ "e:\NT\public\sdk\inc\ntkxapi.h"\
+ "e:\NT\public\sdk\inc\ntldr.h"\
+ "e:\NT\public\sdk\inc\ntlpcapi.h"\
+ "E:\nt\public\sdk\inc\ntmips.h"\
+ "e:\NT\public\sdk\inc\ntmmapi.h"\
+ "e:\NT\public\sdk\inc\ntnls.h"\
+ "e:\NT\public\sdk\inc\ntobapi.h"\
+ "e:\NT\public\sdk\inc\ntpnpapi.h"\
+ "e:\NT\public\sdk\inc\ntpoapi.h"\
+ "E:\nt\public\sdk\inc\ntppc.h"\
+ "e:\NT\public\sdk\inc\ntpsapi.h"\
+ "e:\NT\public\sdk\inc\ntregapi.h"\
+ "e:\NT\public\sdk\inc\ntrtl.h"\
+ "e:\NT\public\sdk\inc\ntseapi.h"\
+ "e:\NT\public\sdk\inc\ntstatus.h"\
+ "e:\NT\public\sdk\inc\ntxcapi.h"\
+ "E:\NT\public\sdk\inc\ppcinst.h"\
+
+
+"$(INTDIR)\lineind.obj" : $(SOURCE) $(DEP_CPP_LINEI) "$(INTDIR)"
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\ipxbind.c
+
+!IF "$(CFG)" == "fwd - Win32 Release"
+
+DEP_CPP_IPXBI=\
+ "..\..\..\..\inc\ipxfwd.h"\
+ "..\..\..\..\inc\nettypes.h"\
+ "..\..\..\..\inc\packoff.h"\
+ "..\..\..\..\inc\packon.h"\
+ "..\..\..\..\inc\tdi.h"\
+ "..\..\..\..\inc\tdikrnl.h"\
+ "..\..\..\inc\afilter.h"\
+ "..\..\..\inc\bugcodes.h"\
+ "..\..\..\inc\efilter.h"\
+ "..\..\..\inc\exlevels.h"\
+ "..\..\..\inc\ffilter.h"\
+ "..\..\..\inc\ndis.h"\
+ "..\..\..\inc\ntddk.h"\
+ "..\..\..\inc\ntiologc.h"\
+ "..\..\..\inc\ntos.h"\
+ "..\..\..\inc\tfilter.h"\
+ "..\inc\bind.h"\
+ "..\inc\ipxfltif.h"\
+ "..\inc\isnkrnl.h"\
+ ".\..\..\..\inc\alpha.h"\
+ ".\..\..\..\inc\alpharef.h"\
+ ".\..\..\..\inc\arc.h"\
+ ".\..\..\..\inc\cache.h"\
+ ".\..\..\..\inc\cm.h"\
+ ".\..\..\..\inc\dbgk.h"\
+ ".\..\..\..\inc\ex.h"\
+ ".\..\..\..\inc\exboosts.h"\
+ ".\..\..\..\inc\hal.h"\
+ ".\..\..\..\inc\i386.h"\
+ ".\..\..\..\inc\init.h"\
+ ".\..\..\..\inc\kd.h"\
+ ".\..\..\..\inc\ke.h"\
+ ".\..\..\..\inc\lfs.h"\
+ ".\..\..\..\inc\lpc.h"\
+ ".\..\..\..\inc\mips.h"\
+ ".\..\..\..\inc\mm.h"\
+ ".\..\..\..\inc\ntosdef.h"\
+ ".\..\..\..\inc\ob.h"\
+ ".\..\..\..\inc\pnp.h"\
+ ".\..\..\..\inc\po.h"\
+ ".\..\..\..\inc\ppc.h"\
+ ".\..\..\..\inc\ps.h"\
+ ".\..\..\..\inc\se.h"\
+ ".\..\..\..\inc\v86emul.h"\
+ ".\ddreqs.h"\
+ ".\debug.h"\
+ ".\driver.h"\
+ ".\filterif.h"\
+ ".\fwddefs.h"\
+ ".\ipxbind.h"\
+ ".\lineind.h"\
+ ".\netbios.h"\
+ ".\packets.h"\
+ ".\precomp.h"\
+ ".\rcvind.h"\
+ ".\registry.h"\
+ ".\rwlock.h"\
+ ".\send.h"\
+ ".\tables.h"\
+ "c:\nt\public\sdk\inc\mipsinst.h"\
+ "c:\nt\public\sdk\inc\ntalpha.h"\
+ "c:\nt\public\sdk\inc\nti386.h"\
+ "c:\nt\public\sdk\inc\ntmips.h"\
+ "c:\nt\public\sdk\inc\ntppc.h"\
+ "c:\nt\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\cfg.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+ {$(INCLUDE)}"\netevent.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntconfig.h"\
+ {$(INCLUDE)}"\ntddndis.h"\
+ {$(INCLUDE)}"\ntddtdi.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntelfapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntmmapi.h"\
+ {$(INCLUDE)}"\ntnls.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntpnpapi.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntregapi.h"\
+ {$(INCLUDE)}"\ntrtl.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\zwapi.h"\
+
+
+"$(INTDIR)\ipxbind.obj" : $(SOURCE) $(DEP_CPP_IPXBI) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "fwd - Win32 (PPC) Release"
+
+DEP_CPP_IPXBI=\
+ "..\..\..\..\inc\nettypes.h"\
+ "..\..\..\..\inc\packoff.h"\
+ "..\..\..\..\inc\packon.h"\
+ "..\..\..\..\inc\tdi.h"\
+ "..\..\..\..\inc\tdikrnl.h"\
+ "..\..\..\inc\afilter.h"\
+ "..\..\..\inc\bugcodes.h"\
+ "..\..\..\inc\efilter.h"\
+ "..\..\..\inc\exlevels.h"\
+ "..\..\..\inc\ffilter.h"\
+ "..\..\..\inc\ndis.h"\
+ "..\..\..\inc\ntddk.h"\
+ "..\..\..\inc\ntiologc.h"\
+ "..\..\..\inc\ntos.h"\
+ "..\..\..\inc\tfilter.h"\
+ "..\inc\bind.h"\
+ "..\inc\isnkrnl.h"\
+ ".\..\..\..\inc\alpha.h"\
+ ".\..\..\..\inc\alpharef.h"\
+ ".\..\..\..\inc\arc.h"\
+ ".\..\..\..\inc\cache.h"\
+ ".\..\..\..\inc\cm.h"\
+ ".\..\..\..\inc\dbgk.h"\
+ ".\..\..\..\inc\ex.h"\
+ ".\..\..\..\inc\exboosts.h"\
+ ".\..\..\..\inc\hal.h"\
+ ".\..\..\..\inc\i386.h"\
+ ".\..\..\..\inc\init.h"\
+ ".\..\..\..\inc\kd.h"\
+ ".\..\..\..\inc\ke.h"\
+ ".\..\..\..\inc\lfs.h"\
+ ".\..\..\..\inc\lpc.h"\
+ ".\..\..\..\inc\mips.h"\
+ ".\..\..\..\inc\mm.h"\
+ ".\..\..\..\inc\ntmp.h"\
+ ".\..\..\..\inc\ntosdef.h"\
+ ".\..\..\..\inc\ob.h"\
+ ".\..\..\..\inc\pnp.h"\
+ ".\..\..\..\inc\po.h"\
+ ".\..\..\..\inc\ppc.h"\
+ ".\..\..\..\inc\ps.h"\
+ ".\..\..\..\inc\se.h"\
+ ".\..\..\..\inc\v86emul.h"\
+ ".\..\inc\ipxfwd.h"\
+ ".\debug.h"\
+ ".\driver.h"\
+ ".\ipxbind.h"\
+ ".\lineind.h"\
+ ".\netbios.h"\
+ ".\packets.h"\
+ ".\rcvind.h"\
+ ".\registry.h"\
+ ".\send.h"\
+ ".\tables.h"\
+ "e:\NT\public\oak\inc\zwapi.h"\
+ "e:\NT\public\sdk\inc\cfg.h"\
+ "e:\NT\public\sdk\inc\devioctl.h"\
+ "E:\NT\public\sdk\inc\mipsinst.h"\
+ "e:\NT\public\sdk\inc\netevent.h"\
+ "e:\NT\public\sdk\inc\nt.h"\
+ "E:\nt\public\sdk\inc\ntalpha.h"\
+ "e:\NT\public\sdk\inc\ntconfig.h"\
+ "e:\NT\public\sdk\inc\ntddndis.h"\
+ "e:\NT\public\sdk\inc\ntddtdi.h"\
+ "e:\NT\public\sdk\inc\ntdef.h"\
+ "e:\NT\public\sdk\inc\ntelfapi.h"\
+ "e:\NT\public\sdk\inc\ntexapi.h"\
+ "E:\nt\public\sdk\inc\nti386.h"\
+ "e:\NT\public\sdk\inc\ntimage.h"\
+ "e:\NT\public\sdk\inc\ntioapi.h"\
+ "e:\NT\public\sdk\inc\ntiolog.h"\
+ "e:\NT\public\sdk\inc\ntkeapi.h"\
+ "e:\NT\public\sdk\inc\ntkxapi.h"\
+ "e:\NT\public\sdk\inc\ntldr.h"\
+ "e:\NT\public\sdk\inc\ntlpcapi.h"\
+ "E:\nt\public\sdk\inc\ntmips.h"\
+ "e:\NT\public\sdk\inc\ntmmapi.h"\
+ "e:\NT\public\sdk\inc\ntnls.h"\
+ "e:\NT\public\sdk\inc\ntobapi.h"\
+ "e:\NT\public\sdk\inc\ntpnpapi.h"\
+ "e:\NT\public\sdk\inc\ntpoapi.h"\
+ "E:\nt\public\sdk\inc\ntppc.h"\
+ "e:\NT\public\sdk\inc\ntpsapi.h"\
+ "e:\NT\public\sdk\inc\ntregapi.h"\
+ "e:\NT\public\sdk\inc\ntrtl.h"\
+ "e:\NT\public\sdk\inc\ntseapi.h"\
+ "e:\NT\public\sdk\inc\ntstatus.h"\
+ "e:\NT\public\sdk\inc\ntxcapi.h"\
+ "E:\NT\public\sdk\inc\ppcinst.h"\
+
+
+"$(INTDIR)\ipxbind.obj" : $(SOURCE) $(DEP_CPP_IPXBI) "$(INTDIR)"
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\driver.c
+
+!IF "$(CFG)" == "fwd - Win32 Release"
+
+DEP_CPP_DRIVE=\
+ "..\..\..\..\inc\ipxfwd.h"\
+ "..\..\..\..\inc\nettypes.h"\
+ "..\..\..\..\inc\packoff.h"\
+ "..\..\..\..\inc\packon.h"\
+ "..\..\..\..\inc\tdi.h"\
+ "..\..\..\..\inc\tdikrnl.h"\
+ "..\..\..\inc\afilter.h"\
+ "..\..\..\inc\bugcodes.h"\
+ "..\..\..\inc\efilter.h"\
+ "..\..\..\inc\exlevels.h"\
+ "..\..\..\inc\ffilter.h"\
+ "..\..\..\inc\ndis.h"\
+ "..\..\..\inc\ntddk.h"\
+ "..\..\..\inc\ntiologc.h"\
+ "..\..\..\inc\ntos.h"\
+ "..\..\..\inc\tfilter.h"\
+ "..\inc\bind.h"\
+ "..\inc\ipxfltif.h"\
+ "..\inc\isnkrnl.h"\
+ ".\..\..\..\inc\alpha.h"\
+ ".\..\..\..\inc\alpharef.h"\
+ ".\..\..\..\inc\arc.h"\
+ ".\..\..\..\inc\cache.h"\
+ ".\..\..\..\inc\cm.h"\
+ ".\..\..\..\inc\dbgk.h"\
+ ".\..\..\..\inc\ex.h"\
+ ".\..\..\..\inc\exboosts.h"\
+ ".\..\..\..\inc\hal.h"\
+ ".\..\..\..\inc\i386.h"\
+ ".\..\..\..\inc\init.h"\
+ ".\..\..\..\inc\kd.h"\
+ ".\..\..\..\inc\ke.h"\
+ ".\..\..\..\inc\lfs.h"\
+ ".\..\..\..\inc\lpc.h"\
+ ".\..\..\..\inc\mips.h"\
+ ".\..\..\..\inc\mm.h"\
+ ".\..\..\..\inc\ntosdef.h"\
+ ".\..\..\..\inc\ob.h"\
+ ".\..\..\..\inc\pnp.h"\
+ ".\..\..\..\inc\po.h"\
+ ".\..\..\..\inc\ppc.h"\
+ ".\..\..\..\inc\ps.h"\
+ ".\..\..\..\inc\se.h"\
+ ".\..\..\..\inc\v86emul.h"\
+ ".\ddreqs.h"\
+ ".\debug.h"\
+ ".\driver.h"\
+ ".\filterif.h"\
+ ".\fwddefs.h"\
+ ".\ipxbind.h"\
+ ".\lineind.h"\
+ ".\netbios.h"\
+ ".\packets.h"\
+ ".\precomp.h"\
+ ".\rcvind.h"\
+ ".\registry.h"\
+ ".\rwlock.h"\
+ ".\send.h"\
+ ".\tables.h"\
+ "c:\nt\public\sdk\inc\mipsinst.h"\
+ "c:\nt\public\sdk\inc\ntalpha.h"\
+ "c:\nt\public\sdk\inc\nti386.h"\
+ "c:\nt\public\sdk\inc\ntmips.h"\
+ "c:\nt\public\sdk\inc\ntppc.h"\
+ "c:\nt\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\cfg.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+ {$(INCLUDE)}"\netevent.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntconfig.h"\
+ {$(INCLUDE)}"\ntddndis.h"\
+ {$(INCLUDE)}"\ntddtdi.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntelfapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntmmapi.h"\
+ {$(INCLUDE)}"\ntnls.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntpnpapi.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntregapi.h"\
+ {$(INCLUDE)}"\ntrtl.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\zwapi.h"\
+
+
+"$(INTDIR)\driver.obj" : $(SOURCE) $(DEP_CPP_DRIVE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "fwd - Win32 (PPC) Release"
+
+DEP_CPP_DRIVE=\
+ "..\..\..\..\inc\nettypes.h"\
+ "..\..\..\..\inc\packoff.h"\
+ "..\..\..\..\inc\packon.h"\
+ "..\..\..\..\inc\tdi.h"\
+ "..\..\..\..\inc\tdikrnl.h"\
+ "..\..\..\inc\afilter.h"\
+ "..\..\..\inc\bugcodes.h"\
+ "..\..\..\inc\efilter.h"\
+ "..\..\..\inc\exlevels.h"\
+ "..\..\..\inc\ffilter.h"\
+ "..\..\..\inc\ndis.h"\
+ "..\..\..\inc\ntddk.h"\
+ "..\..\..\inc\ntiologc.h"\
+ "..\..\..\inc\ntos.h"\
+ "..\..\..\inc\tfilter.h"\
+ "..\inc\bind.h"\
+ "..\inc\isnkrnl.h"\
+ ".\..\..\..\inc\alpha.h"\
+ ".\..\..\..\inc\alpharef.h"\
+ ".\..\..\..\inc\arc.h"\
+ ".\..\..\..\inc\cache.h"\
+ ".\..\..\..\inc\cm.h"\
+ ".\..\..\..\inc\dbgk.h"\
+ ".\..\..\..\inc\ex.h"\
+ ".\..\..\..\inc\exboosts.h"\
+ ".\..\..\..\inc\hal.h"\
+ ".\..\..\..\inc\i386.h"\
+ ".\..\..\..\inc\init.h"\
+ ".\..\..\..\inc\kd.h"\
+ ".\..\..\..\inc\ke.h"\
+ ".\..\..\..\inc\lfs.h"\
+ ".\..\..\..\inc\lpc.h"\
+ ".\..\..\..\inc\mips.h"\
+ ".\..\..\..\inc\mm.h"\
+ ".\..\..\..\inc\ntmp.h"\
+ ".\..\..\..\inc\ntosdef.h"\
+ ".\..\..\..\inc\ob.h"\
+ ".\..\..\..\inc\pnp.h"\
+ ".\..\..\..\inc\po.h"\
+ ".\..\..\..\inc\ppc.h"\
+ ".\..\..\..\inc\ps.h"\
+ ".\..\..\..\inc\se.h"\
+ ".\..\..\..\inc\v86emul.h"\
+ ".\..\inc\ipxfwd.h"\
+ ".\debug.h"\
+ ".\driver.h"\
+ ".\ipxbind.h"\
+ ".\lineind.h"\
+ ".\netbios.h"\
+ ".\packets.h"\
+ ".\rcvind.h"\
+ ".\registry.h"\
+ ".\send.h"\
+ ".\tables.h"\
+ "e:\NT\public\oak\inc\zwapi.h"\
+ "e:\NT\public\sdk\inc\cfg.h"\
+ "e:\NT\public\sdk\inc\devioctl.h"\
+ "E:\NT\public\sdk\inc\mipsinst.h"\
+ "e:\NT\public\sdk\inc\netevent.h"\
+ "e:\NT\public\sdk\inc\nt.h"\
+ "E:\nt\public\sdk\inc\ntalpha.h"\
+ "e:\NT\public\sdk\inc\ntconfig.h"\
+ "e:\NT\public\sdk\inc\ntddndis.h"\
+ "e:\NT\public\sdk\inc\ntddtdi.h"\
+ "e:\NT\public\sdk\inc\ntdef.h"\
+ "e:\NT\public\sdk\inc\ntelfapi.h"\
+ "e:\NT\public\sdk\inc\ntexapi.h"\
+ "E:\nt\public\sdk\inc\nti386.h"\
+ "e:\NT\public\sdk\inc\ntimage.h"\
+ "e:\NT\public\sdk\inc\ntioapi.h"\
+ "e:\NT\public\sdk\inc\ntiolog.h"\
+ "e:\NT\public\sdk\inc\ntkeapi.h"\
+ "e:\NT\public\sdk\inc\ntkxapi.h"\
+ "e:\NT\public\sdk\inc\ntldr.h"\
+ "e:\NT\public\sdk\inc\ntlpcapi.h"\
+ "E:\nt\public\sdk\inc\ntmips.h"\
+ "e:\NT\public\sdk\inc\ntmmapi.h"\
+ "e:\NT\public\sdk\inc\ntnls.h"\
+ "e:\NT\public\sdk\inc\ntobapi.h"\
+ "e:\NT\public\sdk\inc\ntpnpapi.h"\
+ "e:\NT\public\sdk\inc\ntpoapi.h"\
+ "E:\nt\public\sdk\inc\ntppc.h"\
+ "e:\NT\public\sdk\inc\ntpsapi.h"\
+ "e:\NT\public\sdk\inc\ntregapi.h"\
+ "e:\NT\public\sdk\inc\ntrtl.h"\
+ "e:\NT\public\sdk\inc\ntseapi.h"\
+ "e:\NT\public\sdk\inc\ntstatus.h"\
+ "e:\NT\public\sdk\inc\ntxcapi.h"\
+ "E:\NT\public\sdk\inc\ppcinst.h"\
+
+
+"$(INTDIR)\driver.obj" : $(SOURCE) $(DEP_CPP_DRIVE) "$(INTDIR)"
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\mp\sources
+
+!IF "$(CFG)" == "fwd - Win32 Release"
+
+!ELSEIF "$(CFG)" == "fwd - Win32 (PPC) Release"
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\up\sources
+
+!IF "$(CFG)" == "fwd - Win32 Release"
+
+!ELSEIF "$(CFG)" == "fwd - Win32 (PPC) Release"
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\registry.c
+
+!IF "$(CFG)" == "fwd - Win32 Release"
+
+DEP_CPP_REGIS=\
+ "..\..\..\..\inc\ipxfwd.h"\
+ "..\..\..\..\inc\nettypes.h"\
+ "..\..\..\..\inc\packoff.h"\
+ "..\..\..\..\inc\packon.h"\
+ "..\..\..\..\inc\tdi.h"\
+ "..\..\..\..\inc\tdikrnl.h"\
+ "..\..\..\inc\afilter.h"\
+ "..\..\..\inc\bugcodes.h"\
+ "..\..\..\inc\efilter.h"\
+ "..\..\..\inc\exlevels.h"\
+ "..\..\..\inc\ffilter.h"\
+ "..\..\..\inc\ndis.h"\
+ "..\..\..\inc\ntddk.h"\
+ "..\..\..\inc\ntiologc.h"\
+ "..\..\..\inc\ntos.h"\
+ "..\..\..\inc\tfilter.h"\
+ "..\inc\bind.h"\
+ "..\inc\ipxfltif.h"\
+ "..\inc\isnkrnl.h"\
+ ".\..\..\..\inc\alpha.h"\
+ ".\..\..\..\inc\alpharef.h"\
+ ".\..\..\..\inc\arc.h"\
+ ".\..\..\..\inc\cache.h"\
+ ".\..\..\..\inc\cm.h"\
+ ".\..\..\..\inc\dbgk.h"\
+ ".\..\..\..\inc\ex.h"\
+ ".\..\..\..\inc\exboosts.h"\
+ ".\..\..\..\inc\hal.h"\
+ ".\..\..\..\inc\i386.h"\
+ ".\..\..\..\inc\init.h"\
+ ".\..\..\..\inc\kd.h"\
+ ".\..\..\..\inc\ke.h"\
+ ".\..\..\..\inc\lfs.h"\
+ ".\..\..\..\inc\lpc.h"\
+ ".\..\..\..\inc\mips.h"\
+ ".\..\..\..\inc\mm.h"\
+ ".\..\..\..\inc\ntosdef.h"\
+ ".\..\..\..\inc\ob.h"\
+ ".\..\..\..\inc\pnp.h"\
+ ".\..\..\..\inc\po.h"\
+ ".\..\..\..\inc\ppc.h"\
+ ".\..\..\..\inc\ps.h"\
+ ".\..\..\..\inc\se.h"\
+ ".\..\..\..\inc\v86emul.h"\
+ ".\ddreqs.h"\
+ ".\debug.h"\
+ ".\driver.h"\
+ ".\filterif.h"\
+ ".\fwddefs.h"\
+ ".\ipxbind.h"\
+ ".\lineind.h"\
+ ".\netbios.h"\
+ ".\packets.h"\
+ ".\precomp.h"\
+ ".\rcvind.h"\
+ ".\registry.h"\
+ ".\rwlock.h"\
+ ".\send.h"\
+ ".\tables.h"\
+ "c:\nt\public\sdk\inc\mipsinst.h"\
+ "c:\nt\public\sdk\inc\ntalpha.h"\
+ "c:\nt\public\sdk\inc\nti386.h"\
+ "c:\nt\public\sdk\inc\ntmips.h"\
+ "c:\nt\public\sdk\inc\ntppc.h"\
+ "c:\nt\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\cfg.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+ {$(INCLUDE)}"\netevent.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntconfig.h"\
+ {$(INCLUDE)}"\ntddndis.h"\
+ {$(INCLUDE)}"\ntddtdi.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntelfapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntmmapi.h"\
+ {$(INCLUDE)}"\ntnls.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntpnpapi.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntregapi.h"\
+ {$(INCLUDE)}"\ntrtl.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\zwapi.h"\
+
+
+"$(INTDIR)\registry.obj" : $(SOURCE) $(DEP_CPP_REGIS) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "fwd - Win32 (PPC) Release"
+
+DEP_CPP_REGIS=\
+ "..\..\..\..\inc\nettypes.h"\
+ "..\..\..\..\inc\packoff.h"\
+ "..\..\..\..\inc\packon.h"\
+ "..\..\..\..\inc\tdi.h"\
+ "..\..\..\..\inc\tdikrnl.h"\
+ "..\..\..\inc\afilter.h"\
+ "..\..\..\inc\bugcodes.h"\
+ "..\..\..\inc\efilter.h"\
+ "..\..\..\inc\exlevels.h"\
+ "..\..\..\inc\ffilter.h"\
+ "..\..\..\inc\ndis.h"\
+ "..\..\..\inc\ntddk.h"\
+ "..\..\..\inc\ntiologc.h"\
+ "..\..\..\inc\ntos.h"\
+ "..\..\..\inc\tfilter.h"\
+ "..\inc\bind.h"\
+ "..\inc\isnkrnl.h"\
+ ".\..\..\..\inc\alpha.h"\
+ ".\..\..\..\inc\alpharef.h"\
+ ".\..\..\..\inc\arc.h"\
+ ".\..\..\..\inc\cache.h"\
+ ".\..\..\..\inc\cm.h"\
+ ".\..\..\..\inc\dbgk.h"\
+ ".\..\..\..\inc\ex.h"\
+ ".\..\..\..\inc\exboosts.h"\
+ ".\..\..\..\inc\hal.h"\
+ ".\..\..\..\inc\i386.h"\
+ ".\..\..\..\inc\init.h"\
+ ".\..\..\..\inc\kd.h"\
+ ".\..\..\..\inc\ke.h"\
+ ".\..\..\..\inc\lfs.h"\
+ ".\..\..\..\inc\lpc.h"\
+ ".\..\..\..\inc\mips.h"\
+ ".\..\..\..\inc\mm.h"\
+ ".\..\..\..\inc\ntmp.h"\
+ ".\..\..\..\inc\ntosdef.h"\
+ ".\..\..\..\inc\ob.h"\
+ ".\..\..\..\inc\pnp.h"\
+ ".\..\..\..\inc\po.h"\
+ ".\..\..\..\inc\ppc.h"\
+ ".\..\..\..\inc\ps.h"\
+ ".\..\..\..\inc\se.h"\
+ ".\..\..\..\inc\v86emul.h"\
+ ".\..\inc\ipxfwd.h"\
+ ".\debug.h"\
+ ".\driver.h"\
+ ".\ipxbind.h"\
+ ".\lineind.h"\
+ ".\netbios.h"\
+ ".\packets.h"\
+ ".\rcvind.h"\
+ ".\registry.h"\
+ ".\send.h"\
+ ".\tables.h"\
+ "e:\NT\public\oak\inc\zwapi.h"\
+ "e:\NT\public\sdk\inc\cfg.h"\
+ "e:\NT\public\sdk\inc\devioctl.h"\
+ "E:\NT\public\sdk\inc\mipsinst.h"\
+ "e:\NT\public\sdk\inc\netevent.h"\
+ "e:\NT\public\sdk\inc\nt.h"\
+ "E:\nt\public\sdk\inc\ntalpha.h"\
+ "e:\NT\public\sdk\inc\ntconfig.h"\
+ "e:\NT\public\sdk\inc\ntddndis.h"\
+ "e:\NT\public\sdk\inc\ntddtdi.h"\
+ "e:\NT\public\sdk\inc\ntdef.h"\
+ "e:\NT\public\sdk\inc\ntelfapi.h"\
+ "e:\NT\public\sdk\inc\ntexapi.h"\
+ "E:\nt\public\sdk\inc\nti386.h"\
+ "e:\NT\public\sdk\inc\ntimage.h"\
+ "e:\NT\public\sdk\inc\ntioapi.h"\
+ "e:\NT\public\sdk\inc\ntiolog.h"\
+ "e:\NT\public\sdk\inc\ntkeapi.h"\
+ "e:\NT\public\sdk\inc\ntkxapi.h"\
+ "e:\NT\public\sdk\inc\ntldr.h"\
+ "e:\NT\public\sdk\inc\ntlpcapi.h"\
+ "E:\nt\public\sdk\inc\ntmips.h"\
+ "e:\NT\public\sdk\inc\ntmmapi.h"\
+ "e:\NT\public\sdk\inc\ntnls.h"\
+ "e:\NT\public\sdk\inc\ntobapi.h"\
+ "e:\NT\public\sdk\inc\ntpnpapi.h"\
+ "e:\NT\public\sdk\inc\ntpoapi.h"\
+ "E:\nt\public\sdk\inc\ntppc.h"\
+ "e:\NT\public\sdk\inc\ntpsapi.h"\
+ "e:\NT\public\sdk\inc\ntregapi.h"\
+ "e:\NT\public\sdk\inc\ntrtl.h"\
+ "e:\NT\public\sdk\inc\ntseapi.h"\
+ "e:\NT\public\sdk\inc\ntstatus.h"\
+ "e:\NT\public\sdk\inc\ntxcapi.h"\
+ "E:\NT\public\sdk\inc\ppcinst.h"\
+
+
+"$(INTDIR)\registry.obj" : $(SOURCE) $(DEP_CPP_REGIS) "$(INTDIR)"
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\packets.c
+
+!IF "$(CFG)" == "fwd - Win32 Release"
+
+DEP_CPP_PACKE=\
+ "..\..\..\..\inc\ipxfwd.h"\
+ "..\..\..\..\inc\nettypes.h"\
+ "..\..\..\..\inc\packoff.h"\
+ "..\..\..\..\inc\packon.h"\
+ "..\..\..\..\inc\tdi.h"\
+ "..\..\..\..\inc\tdikrnl.h"\
+ "..\..\..\inc\afilter.h"\
+ "..\..\..\inc\bugcodes.h"\
+ "..\..\..\inc\efilter.h"\
+ "..\..\..\inc\exlevels.h"\
+ "..\..\..\inc\ffilter.h"\
+ "..\..\..\inc\ndis.h"\
+ "..\..\..\inc\ntddk.h"\
+ "..\..\..\inc\ntiologc.h"\
+ "..\..\..\inc\ntos.h"\
+ "..\..\..\inc\tfilter.h"\
+ "..\inc\bind.h"\
+ "..\inc\ipxfltif.h"\
+ "..\inc\isnkrnl.h"\
+ ".\..\..\..\inc\alpha.h"\
+ ".\..\..\..\inc\alpharef.h"\
+ ".\..\..\..\inc\arc.h"\
+ ".\..\..\..\inc\cache.h"\
+ ".\..\..\..\inc\cm.h"\
+ ".\..\..\..\inc\dbgk.h"\
+ ".\..\..\..\inc\ex.h"\
+ ".\..\..\..\inc\exboosts.h"\
+ ".\..\..\..\inc\hal.h"\
+ ".\..\..\..\inc\i386.h"\
+ ".\..\..\..\inc\init.h"\
+ ".\..\..\..\inc\kd.h"\
+ ".\..\..\..\inc\ke.h"\
+ ".\..\..\..\inc\lfs.h"\
+ ".\..\..\..\inc\lpc.h"\
+ ".\..\..\..\inc\mips.h"\
+ ".\..\..\..\inc\mm.h"\
+ ".\..\..\..\inc\ntosdef.h"\
+ ".\..\..\..\inc\ob.h"\
+ ".\..\..\..\inc\pnp.h"\
+ ".\..\..\..\inc\po.h"\
+ ".\..\..\..\inc\ppc.h"\
+ ".\..\..\..\inc\ps.h"\
+ ".\..\..\..\inc\se.h"\
+ ".\..\..\..\inc\v86emul.h"\
+ ".\ddreqs.h"\
+ ".\debug.h"\
+ ".\driver.h"\
+ ".\filterif.h"\
+ ".\fwddefs.h"\
+ ".\ipxbind.h"\
+ ".\lineind.h"\
+ ".\netbios.h"\
+ ".\packets.h"\
+ ".\precomp.h"\
+ ".\rcvind.h"\
+ ".\registry.h"\
+ ".\rwlock.h"\
+ ".\send.h"\
+ ".\tables.h"\
+ "c:\nt\public\sdk\inc\mipsinst.h"\
+ "c:\nt\public\sdk\inc\ntalpha.h"\
+ "c:\nt\public\sdk\inc\nti386.h"\
+ "c:\nt\public\sdk\inc\ntmips.h"\
+ "c:\nt\public\sdk\inc\ntppc.h"\
+ "c:\nt\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\cfg.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+ {$(INCLUDE)}"\netevent.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntconfig.h"\
+ {$(INCLUDE)}"\ntddndis.h"\
+ {$(INCLUDE)}"\ntddtdi.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntelfapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntmmapi.h"\
+ {$(INCLUDE)}"\ntnls.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntpnpapi.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntregapi.h"\
+ {$(INCLUDE)}"\ntrtl.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\zwapi.h"\
+
+
+"$(INTDIR)\packets.obj" : $(SOURCE) $(DEP_CPP_PACKE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "fwd - Win32 (PPC) Release"
+
+DEP_CPP_PACKE=\
+ "..\..\..\..\inc\nettypes.h"\
+ "..\..\..\..\inc\packoff.h"\
+ "..\..\..\..\inc\packon.h"\
+ "..\..\..\..\inc\tdi.h"\
+ "..\..\..\..\inc\tdikrnl.h"\
+ "..\..\..\inc\afilter.h"\
+ "..\..\..\inc\bugcodes.h"\
+ "..\..\..\inc\efilter.h"\
+ "..\..\..\inc\exlevels.h"\
+ "..\..\..\inc\ffilter.h"\
+ "..\..\..\inc\ndis.h"\
+ "..\..\..\inc\ntddk.h"\
+ "..\..\..\inc\ntiologc.h"\
+ "..\..\..\inc\ntos.h"\
+ "..\..\..\inc\tfilter.h"\
+ "..\inc\bind.h"\
+ "..\inc\isnkrnl.h"\
+ ".\..\..\..\inc\alpha.h"\
+ ".\..\..\..\inc\alpharef.h"\
+ ".\..\..\..\inc\arc.h"\
+ ".\..\..\..\inc\cache.h"\
+ ".\..\..\..\inc\cm.h"\
+ ".\..\..\..\inc\dbgk.h"\
+ ".\..\..\..\inc\ex.h"\
+ ".\..\..\..\inc\exboosts.h"\
+ ".\..\..\..\inc\hal.h"\
+ ".\..\..\..\inc\i386.h"\
+ ".\..\..\..\inc\init.h"\
+ ".\..\..\..\inc\kd.h"\
+ ".\..\..\..\inc\ke.h"\
+ ".\..\..\..\inc\lfs.h"\
+ ".\..\..\..\inc\lpc.h"\
+ ".\..\..\..\inc\mips.h"\
+ ".\..\..\..\inc\mm.h"\
+ ".\..\..\..\inc\ntmp.h"\
+ ".\..\..\..\inc\ntosdef.h"\
+ ".\..\..\..\inc\ob.h"\
+ ".\..\..\..\inc\pnp.h"\
+ ".\..\..\..\inc\po.h"\
+ ".\..\..\..\inc\ppc.h"\
+ ".\..\..\..\inc\ps.h"\
+ ".\..\..\..\inc\se.h"\
+ ".\..\..\..\inc\v86emul.h"\
+ ".\..\inc\ipxfwd.h"\
+ ".\debug.h"\
+ ".\driver.h"\
+ ".\ipxbind.h"\
+ ".\lineind.h"\
+ ".\netbios.h"\
+ ".\packets.h"\
+ ".\rcvind.h"\
+ ".\registry.h"\
+ ".\send.h"\
+ ".\tables.h"\
+ "e:\NT\public\oak\inc\zwapi.h"\
+ "e:\NT\public\sdk\inc\cfg.h"\
+ "e:\NT\public\sdk\inc\devioctl.h"\
+ "E:\NT\public\sdk\inc\mipsinst.h"\
+ "e:\NT\public\sdk\inc\netevent.h"\
+ "e:\NT\public\sdk\inc\nt.h"\
+ "E:\nt\public\sdk\inc\ntalpha.h"\
+ "e:\NT\public\sdk\inc\ntconfig.h"\
+ "e:\NT\public\sdk\inc\ntddndis.h"\
+ "e:\NT\public\sdk\inc\ntddtdi.h"\
+ "e:\NT\public\sdk\inc\ntdef.h"\
+ "e:\NT\public\sdk\inc\ntelfapi.h"\
+ "e:\NT\public\sdk\inc\ntexapi.h"\
+ "E:\nt\public\sdk\inc\nti386.h"\
+ "e:\NT\public\sdk\inc\ntimage.h"\
+ "e:\NT\public\sdk\inc\ntioapi.h"\
+ "e:\NT\public\sdk\inc\ntiolog.h"\
+ "e:\NT\public\sdk\inc\ntkeapi.h"\
+ "e:\NT\public\sdk\inc\ntkxapi.h"\
+ "e:\NT\public\sdk\inc\ntldr.h"\
+ "e:\NT\public\sdk\inc\ntlpcapi.h"\
+ "E:\nt\public\sdk\inc\ntmips.h"\
+ "e:\NT\public\sdk\inc\ntmmapi.h"\
+ "e:\NT\public\sdk\inc\ntnls.h"\
+ "e:\NT\public\sdk\inc\ntobapi.h"\
+ "e:\NT\public\sdk\inc\ntpnpapi.h"\
+ "e:\NT\public\sdk\inc\ntpoapi.h"\
+ "E:\nt\public\sdk\inc\ntppc.h"\
+ "e:\NT\public\sdk\inc\ntpsapi.h"\
+ "e:\NT\public\sdk\inc\ntregapi.h"\
+ "e:\NT\public\sdk\inc\ntrtl.h"\
+ "e:\NT\public\sdk\inc\ntseapi.h"\
+ "e:\NT\public\sdk\inc\ntstatus.h"\
+ "e:\NT\public\sdk\inc\ntxcapi.h"\
+ "E:\NT\public\sdk\inc\ppcinst.h"\
+
+
+"$(INTDIR)\packets.obj" : $(SOURCE) $(DEP_CPP_PACKE) "$(INTDIR)"
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\nwlnkfwd.rc
+
+!IF "$(CFG)" == "fwd - Win32 Release"
+
+DEP_RSC_NWLNK=\
+ {$(INCLUDE)}"\common.ver"\
+ {$(INCLUDE)}"\ntverp.h"\
+
+
+"$(INTDIR)\nwlnkfwd.res" : $(SOURCE) $(DEP_RSC_NWLNK) "$(INTDIR)"
+ $(RSC) $(RSC_PROJ) $(SOURCE)
+
+
+!ELSEIF "$(CFG)" == "fwd - Win32 (PPC) Release"
+
+DEP_RSC_NWLNK=\
+ ".\common.ver"\
+ ".\ntverp.h"\
+
+
+"$(INTDIR)\nwlnkfwd.res" : $(SOURCE) $(DEP_RSC_NWLNK) "$(INTDIR)"
+ $(RSC) /l 0x409 /fo"$(INTDIR)/nwlnkfwd.res" /d "NDEBUG" $(SOURCE)
+
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\tables.c
+
+!IF "$(CFG)" == "fwd - Win32 Release"
+
+DEP_CPP_TABLE=\
+ "..\..\..\..\inc\ipxfwd.h"\
+ "..\..\..\..\inc\nettypes.h"\
+ "..\..\..\..\inc\packoff.h"\
+ "..\..\..\..\inc\packon.h"\
+ "..\..\..\..\inc\tdi.h"\
+ "..\..\..\..\inc\tdikrnl.h"\
+ "..\..\..\inc\afilter.h"\
+ "..\..\..\inc\bugcodes.h"\
+ "..\..\..\inc\efilter.h"\
+ "..\..\..\inc\exlevels.h"\
+ "..\..\..\inc\ffilter.h"\
+ "..\..\..\inc\ndis.h"\
+ "..\..\..\inc\ntddk.h"\
+ "..\..\..\inc\ntiologc.h"\
+ "..\..\..\inc\ntos.h"\
+ "..\..\..\inc\tfilter.h"\
+ "..\inc\bind.h"\
+ "..\inc\ipxfltif.h"\
+ "..\inc\isnkrnl.h"\
+ ".\..\..\..\inc\alpha.h"\
+ ".\..\..\..\inc\alpharef.h"\
+ ".\..\..\..\inc\arc.h"\
+ ".\..\..\..\inc\cache.h"\
+ ".\..\..\..\inc\cm.h"\
+ ".\..\..\..\inc\dbgk.h"\
+ ".\..\..\..\inc\ex.h"\
+ ".\..\..\..\inc\exboosts.h"\
+ ".\..\..\..\inc\hal.h"\
+ ".\..\..\..\inc\i386.h"\
+ ".\..\..\..\inc\init.h"\
+ ".\..\..\..\inc\kd.h"\
+ ".\..\..\..\inc\ke.h"\
+ ".\..\..\..\inc\lfs.h"\
+ ".\..\..\..\inc\lpc.h"\
+ ".\..\..\..\inc\mips.h"\
+ ".\..\..\..\inc\mm.h"\
+ ".\..\..\..\inc\ntosdef.h"\
+ ".\..\..\..\inc\ob.h"\
+ ".\..\..\..\inc\pnp.h"\
+ ".\..\..\..\inc\po.h"\
+ ".\..\..\..\inc\ppc.h"\
+ ".\..\..\..\inc\ps.h"\
+ ".\..\..\..\inc\se.h"\
+ ".\..\..\..\inc\v86emul.h"\
+ ".\ddreqs.h"\
+ ".\debug.h"\
+ ".\driver.h"\
+ ".\filterif.h"\
+ ".\fwddefs.h"\
+ ".\ipxbind.h"\
+ ".\lineind.h"\
+ ".\netbios.h"\
+ ".\packets.h"\
+ ".\precomp.h"\
+ ".\rcvind.h"\
+ ".\registry.h"\
+ ".\rwlock.h"\
+ ".\send.h"\
+ ".\tables.h"\
+ "c:\nt\public\sdk\inc\mipsinst.h"\
+ "c:\nt\public\sdk\inc\ntalpha.h"\
+ "c:\nt\public\sdk\inc\nti386.h"\
+ "c:\nt\public\sdk\inc\ntmips.h"\
+ "c:\nt\public\sdk\inc\ntppc.h"\
+ "c:\nt\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\cfg.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+ {$(INCLUDE)}"\netevent.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntconfig.h"\
+ {$(INCLUDE)}"\ntddndis.h"\
+ {$(INCLUDE)}"\ntddtdi.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntelfapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntmmapi.h"\
+ {$(INCLUDE)}"\ntnls.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntpnpapi.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntregapi.h"\
+ {$(INCLUDE)}"\ntrtl.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\zwapi.h"\
+
+
+"$(INTDIR)\tables.obj" : $(SOURCE) $(DEP_CPP_TABLE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "fwd - Win32 (PPC) Release"
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\ddreqs.c
+
+!IF "$(CFG)" == "fwd - Win32 Release"
+
+DEP_CPP_DDREQ=\
+ "..\..\..\..\inc\ipxfwd.h"\
+ "..\..\..\..\inc\nettypes.h"\
+ "..\..\..\..\inc\packoff.h"\
+ "..\..\..\..\inc\packon.h"\
+ "..\..\..\..\inc\tdi.h"\
+ "..\..\..\..\inc\tdikrnl.h"\
+ "..\..\..\inc\afilter.h"\
+ "..\..\..\inc\bugcodes.h"\
+ "..\..\..\inc\efilter.h"\
+ "..\..\..\inc\exlevels.h"\
+ "..\..\..\inc\ffilter.h"\
+ "..\..\..\inc\ndis.h"\
+ "..\..\..\inc\ntddk.h"\
+ "..\..\..\inc\ntiologc.h"\
+ "..\..\..\inc\ntos.h"\
+ "..\..\..\inc\tfilter.h"\
+ "..\inc\bind.h"\
+ "..\inc\ipxfltif.h"\
+ "..\inc\isnkrnl.h"\
+ ".\..\..\..\inc\alpha.h"\
+ ".\..\..\..\inc\alpharef.h"\
+ ".\..\..\..\inc\arc.h"\
+ ".\..\..\..\inc\cache.h"\
+ ".\..\..\..\inc\cm.h"\
+ ".\..\..\..\inc\dbgk.h"\
+ ".\..\..\..\inc\ex.h"\
+ ".\..\..\..\inc\exboosts.h"\
+ ".\..\..\..\inc\hal.h"\
+ ".\..\..\..\inc\i386.h"\
+ ".\..\..\..\inc\init.h"\
+ ".\..\..\..\inc\kd.h"\
+ ".\..\..\..\inc\ke.h"\
+ ".\..\..\..\inc\lfs.h"\
+ ".\..\..\..\inc\lpc.h"\
+ ".\..\..\..\inc\mips.h"\
+ ".\..\..\..\inc\mm.h"\
+ ".\..\..\..\inc\ntosdef.h"\
+ ".\..\..\..\inc\ob.h"\
+ ".\..\..\..\inc\pnp.h"\
+ ".\..\..\..\inc\po.h"\
+ ".\..\..\..\inc\ppc.h"\
+ ".\..\..\..\inc\ps.h"\
+ ".\..\..\..\inc\se.h"\
+ ".\..\..\..\inc\v86emul.h"\
+ ".\ddreqs.h"\
+ ".\debug.h"\
+ ".\driver.h"\
+ ".\filterif.h"\
+ ".\fwddefs.h"\
+ ".\ipxbind.h"\
+ ".\lineind.h"\
+ ".\netbios.h"\
+ ".\packets.h"\
+ ".\precomp.h"\
+ ".\rcvind.h"\
+ ".\registry.h"\
+ ".\rwlock.h"\
+ ".\send.h"\
+ ".\tables.h"\
+ "c:\nt\public\sdk\inc\mipsinst.h"\
+ "c:\nt\public\sdk\inc\ntalpha.h"\
+ "c:\nt\public\sdk\inc\nti386.h"\
+ "c:\nt\public\sdk\inc\ntmips.h"\
+ "c:\nt\public\sdk\inc\ntppc.h"\
+ "c:\nt\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\cfg.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+ {$(INCLUDE)}"\netevent.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntconfig.h"\
+ {$(INCLUDE)}"\ntddndis.h"\
+ {$(INCLUDE)}"\ntddtdi.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntelfapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntmmapi.h"\
+ {$(INCLUDE)}"\ntnls.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntpnpapi.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntregapi.h"\
+ {$(INCLUDE)}"\ntrtl.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\zwapi.h"\
+
+
+"$(INTDIR)\ddreqs.obj" : $(SOURCE) $(DEP_CPP_DDREQ) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "fwd - Win32 (PPC) Release"
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\debug.c
+
+!IF "$(CFG)" == "fwd - Win32 Release"
+
+DEP_CPP_DEBUG=\
+ "..\..\..\..\inc\ipxfwd.h"\
+ "..\..\..\..\inc\nettypes.h"\
+ "..\..\..\..\inc\packoff.h"\
+ "..\..\..\..\inc\packon.h"\
+ "..\..\..\..\inc\tdi.h"\
+ "..\..\..\..\inc\tdikrnl.h"\
+ "..\..\..\inc\afilter.h"\
+ "..\..\..\inc\bugcodes.h"\
+ "..\..\..\inc\efilter.h"\
+ "..\..\..\inc\exlevels.h"\
+ "..\..\..\inc\ffilter.h"\
+ "..\..\..\inc\ndis.h"\
+ "..\..\..\inc\ntddk.h"\
+ "..\..\..\inc\ntiologc.h"\
+ "..\..\..\inc\ntos.h"\
+ "..\..\..\inc\tfilter.h"\
+ "..\inc\bind.h"\
+ "..\inc\ipxfltif.h"\
+ "..\inc\isnkrnl.h"\
+ ".\..\..\..\inc\alpha.h"\
+ ".\..\..\..\inc\alpharef.h"\
+ ".\..\..\..\inc\arc.h"\
+ ".\..\..\..\inc\cache.h"\
+ ".\..\..\..\inc\cm.h"\
+ ".\..\..\..\inc\dbgk.h"\
+ ".\..\..\..\inc\ex.h"\
+ ".\..\..\..\inc\exboosts.h"\
+ ".\..\..\..\inc\hal.h"\
+ ".\..\..\..\inc\i386.h"\
+ ".\..\..\..\inc\init.h"\
+ ".\..\..\..\inc\kd.h"\
+ ".\..\..\..\inc\ke.h"\
+ ".\..\..\..\inc\lfs.h"\
+ ".\..\..\..\inc\lpc.h"\
+ ".\..\..\..\inc\mips.h"\
+ ".\..\..\..\inc\mm.h"\
+ ".\..\..\..\inc\ntosdef.h"\
+ ".\..\..\..\inc\ob.h"\
+ ".\..\..\..\inc\pnp.h"\
+ ".\..\..\..\inc\po.h"\
+ ".\..\..\..\inc\ppc.h"\
+ ".\..\..\..\inc\ps.h"\
+ ".\..\..\..\inc\se.h"\
+ ".\..\..\..\inc\v86emul.h"\
+ ".\ddreqs.h"\
+ ".\debug.h"\
+ ".\driver.h"\
+ ".\filterif.h"\
+ ".\fwddefs.h"\
+ ".\ipxbind.h"\
+ ".\lineind.h"\
+ ".\netbios.h"\
+ ".\packets.h"\
+ ".\precomp.h"\
+ ".\rcvind.h"\
+ ".\registry.h"\
+ ".\rwlock.h"\
+ ".\send.h"\
+ ".\tables.h"\
+ "c:\nt\public\sdk\inc\mipsinst.h"\
+ "c:\nt\public\sdk\inc\ntalpha.h"\
+ "c:\nt\public\sdk\inc\nti386.h"\
+ "c:\nt\public\sdk\inc\ntmips.h"\
+ "c:\nt\public\sdk\inc\ntppc.h"\
+ "c:\nt\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\cfg.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+ {$(INCLUDE)}"\netevent.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntconfig.h"\
+ {$(INCLUDE)}"\ntddndis.h"\
+ {$(INCLUDE)}"\ntddtdi.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntelfapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntmmapi.h"\
+ {$(INCLUDE)}"\ntnls.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntpnpapi.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntregapi.h"\
+ {$(INCLUDE)}"\ntrtl.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\zwapi.h"\
+
+
+"$(INTDIR)\debug.obj" : $(SOURCE) $(DEP_CPP_DEBUG) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "fwd - Win32 (PPC) Release"
+
+!ENDIF
+
+# End Source File
+################################################################################
+# Begin Source File
+
+SOURCE=.\filterif.c
+
+!IF "$(CFG)" == "fwd - Win32 Release"
+
+DEP_CPP_FILTE=\
+ "..\..\..\..\inc\ipxfwd.h"\
+ "..\..\..\..\inc\nettypes.h"\
+ "..\..\..\..\inc\packoff.h"\
+ "..\..\..\..\inc\packon.h"\
+ "..\..\..\..\inc\tdi.h"\
+ "..\..\..\..\inc\tdikrnl.h"\
+ "..\..\..\inc\afilter.h"\
+ "..\..\..\inc\bugcodes.h"\
+ "..\..\..\inc\efilter.h"\
+ "..\..\..\inc\exlevels.h"\
+ "..\..\..\inc\ffilter.h"\
+ "..\..\..\inc\ndis.h"\
+ "..\..\..\inc\ntddk.h"\
+ "..\..\..\inc\ntiologc.h"\
+ "..\..\..\inc\ntos.h"\
+ "..\..\..\inc\tfilter.h"\
+ "..\inc\bind.h"\
+ "..\inc\ipxfltif.h"\
+ "..\inc\isnkrnl.h"\
+ ".\..\..\..\inc\alpha.h"\
+ ".\..\..\..\inc\alpharef.h"\
+ ".\..\..\..\inc\arc.h"\
+ ".\..\..\..\inc\cache.h"\
+ ".\..\..\..\inc\cm.h"\
+ ".\..\..\..\inc\dbgk.h"\
+ ".\..\..\..\inc\ex.h"\
+ ".\..\..\..\inc\exboosts.h"\
+ ".\..\..\..\inc\hal.h"\
+ ".\..\..\..\inc\i386.h"\
+ ".\..\..\..\inc\init.h"\
+ ".\..\..\..\inc\kd.h"\
+ ".\..\..\..\inc\ke.h"\
+ ".\..\..\..\inc\lfs.h"\
+ ".\..\..\..\inc\lpc.h"\
+ ".\..\..\..\inc\mips.h"\
+ ".\..\..\..\inc\mm.h"\
+ ".\..\..\..\inc\ntosdef.h"\
+ ".\..\..\..\inc\ob.h"\
+ ".\..\..\..\inc\pnp.h"\
+ ".\..\..\..\inc\po.h"\
+ ".\..\..\..\inc\ppc.h"\
+ ".\..\..\..\inc\ps.h"\
+ ".\..\..\..\inc\se.h"\
+ ".\..\..\..\inc\v86emul.h"\
+ ".\ddreqs.h"\
+ ".\debug.h"\
+ ".\driver.h"\
+ ".\filterif.h"\
+ ".\fwddefs.h"\
+ ".\ipxbind.h"\
+ ".\lineind.h"\
+ ".\netbios.h"\
+ ".\packets.h"\
+ ".\precomp.h"\
+ ".\rcvind.h"\
+ ".\registry.h"\
+ ".\rwlock.h"\
+ ".\send.h"\
+ ".\tables.h"\
+ "c:\nt\public\sdk\inc\mipsinst.h"\
+ "c:\nt\public\sdk\inc\ntalpha.h"\
+ "c:\nt\public\sdk\inc\nti386.h"\
+ "c:\nt\public\sdk\inc\ntmips.h"\
+ "c:\nt\public\sdk\inc\ntppc.h"\
+ "c:\nt\public\sdk\inc\ppcinst.h"\
+ {$(INCLUDE)}"\cfg.h"\
+ {$(INCLUDE)}"\devioctl.h"\
+ {$(INCLUDE)}"\netevent.h"\
+ {$(INCLUDE)}"\nt.h"\
+ {$(INCLUDE)}"\ntconfig.h"\
+ {$(INCLUDE)}"\ntddndis.h"\
+ {$(INCLUDE)}"\ntddtdi.h"\
+ {$(INCLUDE)}"\ntdef.h"\
+ {$(INCLUDE)}"\ntelfapi.h"\
+ {$(INCLUDE)}"\ntexapi.h"\
+ {$(INCLUDE)}"\ntimage.h"\
+ {$(INCLUDE)}"\ntioapi.h"\
+ {$(INCLUDE)}"\ntiolog.h"\
+ {$(INCLUDE)}"\ntkeapi.h"\
+ {$(INCLUDE)}"\ntkxapi.h"\
+ {$(INCLUDE)}"\ntldr.h"\
+ {$(INCLUDE)}"\ntlpcapi.h"\
+ {$(INCLUDE)}"\ntmmapi.h"\
+ {$(INCLUDE)}"\ntnls.h"\
+ {$(INCLUDE)}"\ntobapi.h"\
+ {$(INCLUDE)}"\ntpnpapi.h"\
+ {$(INCLUDE)}"\ntpoapi.h"\
+ {$(INCLUDE)}"\ntpsapi.h"\
+ {$(INCLUDE)}"\ntregapi.h"\
+ {$(INCLUDE)}"\ntrtl.h"\
+ {$(INCLUDE)}"\ntseapi.h"\
+ {$(INCLUDE)}"\ntstatus.h"\
+ {$(INCLUDE)}"\ntxcapi.h"\
+ {$(INCLUDE)}"\zwapi.h"\
+
+
+"$(INTDIR)\filterif.obj" : $(SOURCE) $(DEP_CPP_FILTE) "$(INTDIR)"
+
+
+!ELSEIF "$(CFG)" == "fwd - Win32 (PPC) Release"
+
+!ENDIF
+
+# End Source File
+# End Target
+# End Project
+################################################################################
diff --git a/private/ntos/tdi/isn/fwd/fwddefs.h b/private/ntos/tdi/isn/fwd/fwddefs.h
new file mode 100644
index 000000000..af862b3b5
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/fwddefs.h
@@ -0,0 +1,125 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ ntos\tdi\isn\fwd\fwddefs.h
+
+Abstract:
+ IPX Forwarder driver constants and general macro definitions
+
+Author:
+
+ Vadim Eydelman
+
+Revision History:
+
+--*/
+
+#ifndef _IPXFWD_FWDDEFS_
+#define _IPXFWD_FWDDEFS_
+
+
+// Forwarder tag used in memory allocations
+#define FWD_POOL_TAG 'wFwN'
+
+//*** Offsets into the IPX header
+#define IPXH_HDRSIZE 30 // Size of the IPX header
+#define IPXH_CHECKSUM 0 // Checksum
+#define IPXH_LENGTH 2 // Length
+#define IPXH_XPORTCTL 4 // Transport Control
+#define IPXH_PKTTYPE 5 // Packet Type
+#define IPXH_DESTADDR 6 // Dest. Address (Total)
+#define IPXH_DESTNET 6 // Dest. Network Address
+#define IPXH_DESTNODE 10 // Dest. Node Address
+#define IPXH_DESTSOCK 16 // Dest. Socket Number
+#define IPXH_SRCADDR 18 // Source Address (Total)
+#define IPXH_SRCNET 18 // Source Network Address
+#define IPXH_SRCNODE 22 // Source Node Address
+#define IPXH_SRCSOCK 28 // Source Socket Number
+
+//*** Packet Types we care about
+#define IPX_NETBIOS_TYPE 20 // Netbios propagated packet
+
+//*** Socket Numbers we care about
+#define IPX_NETBIOS_SOCKET ((USHORT)0x0455)
+#define IPX_SAP_SOCKET ((USHORT)0x0452)
+#define IPX_SMB_NAME_SOCKET ((USHORT)0x0551)
+
+//*** maximum nr of hops for a normal packet ***
+#define IPX_MAX_HOPS 16
+
+//*** offsets into the netbios name frames ***
+#define NB_NAME_TYPE_FLAG 62
+#define NB_DATA_STREAM_TYPE2 63
+#define NB_NAME 64
+#define NB_TOTAL_DATA_LENGTH 80
+// *** offsets into smb name claim/query frames
+#define SMB_OPERATION 62
+#define SMB_NAME_TYPE 63
+#define SMB_MESSAGE_IF 64
+#define SMB_NAME 66
+
+
+// Some commonly used macros
+#define IPX_NODE_CPY(dst,src) memcpy(dst,src,6)
+#define IPX_NODE_CMP(node1,node2) memcmp(node1,node2,6)
+
+#define IPX_NET_CPY(dst,src) memcpy(dst,src,4)
+#define IPX_NET_CMP(net1,net2) memcmp(net1,net2,4)
+
+#define NB_NAME_CPY(dst,src) strncpy((char *)dst,(char *)src,16)
+#define NB_NAME_CMP(name1,name2) strncmp((char *)name1,(char *)name2,16)
+
+// Make sure the structure is copied with DWORD granularity
+#define IF_STATS_CPY(dst,src) \
+ (dst)->OperationalState = (src)->OperationalState; \
+ (dst)->MaxPacketSize = (src)->MaxPacketSize; \
+ (dst)->InHdrErrors = (src)->InHdrErrors; \
+ (dst)->InFiltered = (src)->InFiltered; \
+ (dst)->InNoRoutes = (src)->InNoRoutes; \
+ (dst)->InDiscards = (src)->InDiscards; \
+ (dst)->InDelivers = (src)->InDelivers; \
+ (dst)->OutFiltered = (src)->OutFiltered; \
+ (dst)->OutDiscards = (src)->OutDiscards; \
+ (dst)->OutDelivers = (src)->OutDelivers; \
+ (dst)->NetbiosReceived = (src)->NetbiosReceived; \
+ (dst)->NetbiosSent = (src)->NetbiosSent;
+
+// Extensions to list macros
+#define InitializeListEntry(entry) InitializeListHead(entry)
+#define IsListEntry(entry) IsListEmpty(entry)
+#define IsSingleEntry(head) ((head)->Flink==(head)->Blink)
+
+// Conversions from/to on-the-wire format
+#define GETUSHORT(src) ( \
+ (USHORT)( \
+ (((UCHAR *)src)[0]<<8) \
+ + (((UCHAR *)src)[1]) \
+ ) \
+)
+
+#define GETULONG(src) ( \
+ (ULONG)( \
+ (((UCHAR *)src)[0]<<24) \
+ + (((UCHAR *)src)[1]<<16) \
+ + (((UCHAR *)src)[2]<<8) \
+ + (((UCHAR *)src)[3]) \
+ ) \
+)
+
+#define PUTUSHORT(src,dst) { \
+ ((UCHAR *)dst)[0] = ((UCHAR)(src>>8)); \
+ ((UCHAR *)dst)[1] = ((UCHAR)src); \
+}
+
+#define PUTULONG(src,dst) { \
+ ((UCHAR *)dst)[0] = ((UCHAR)(src>>24)); \
+ ((UCHAR *)dst)[1] = ((UCHAR)(src>>16)); \
+ ((UCHAR *)dst)[2] = ((UCHAR)(src>>8)); \
+ ((UCHAR *)dst)[3] = ((UCHAR)src); \
+}
+
+
+#endif
diff --git a/private/ntos/tdi/isn/fwd/ipxbind.c b/private/ntos/tdi/isn/fwd/ipxbind.c
new file mode 100644
index 000000000..71c7a37b3
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/ipxbind.c
@@ -0,0 +1,462 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ ntos\tdi\isn\fwd\ipxbind.c
+
+Abstract:
+ IPX Forwarder Driver interface with IPX stack driver
+
+
+Author:
+
+ Vadim Eydelman
+
+Revision History:
+
+--*/
+
+#include "precomp.h"
+
+
+// global handle of the IPX driver
+HANDLE HdlIpxFile;
+
+
+// Buffer for IPX binding output structure
+PIPX_INTERNAL_BIND_RIP_OUTPUT IPXBindOutput=NULL;
+
+NTSTATUS
+IpxFwdFindRoute (
+ IN PUCHAR Network,
+ IN PUCHAR Node,
+ OUT PIPX_FIND_ROUTE_REQUEST RouteEntry
+ );
+
+/*++
+*******************************************************************
+ B i n d T o I p x D r i v e r
+
+Routine Description:
+ Exchanges binding information with IPX stack driver
+Arguments:
+ None
+Return Value:
+ STATUS_SUCCESS - exchange was done OK
+ STATUS_INSUFFICIENT_RESOURCES - could not allocate buffers for
+ info exchange
+ error status returned by IPX stack driver
+
+*******************************************************************
+--*/
+NTSTATUS
+BindToIpxDriver (
+ KPROCESSOR_MODE requestorMode
+ ) {
+ NTSTATUS status;
+ IO_STATUS_BLOCK IoStatusBlock;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ PIPX_INTERNAL_BIND_INPUT bip;
+ UNICODE_STRING UstrIpxFileName;
+ PWSTR WstrIpxFileName;
+
+ ASSERT (IPXBindOutput==NULL);
+
+ // Read Ipx exported device name from the registry
+ status = ReadIpxDeviceName (&WstrIpxFileName);
+ if (!NT_SUCCESS (status))
+ return status;
+
+ RtlInitUnicodeString (&UstrIpxFileName, WstrIpxFileName);
+ InitializeObjectAttributes(
+ &ObjectAttributes,
+ &UstrIpxFileName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL
+ );
+
+ if (requestorMode==UserMode)
+ status = ZwCreateFile(&HdlIpxFile,
+ SYNCHRONIZE | GENERIC_READ,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_OPEN,
+ FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL,
+ 0L);
+ else
+ status = NtCreateFile(&HdlIpxFile,
+ SYNCHRONIZE | GENERIC_READ,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_OPEN,
+ FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL,
+ 0L);
+
+ if (!NT_SUCCESS(status)) {
+ IpxFwdDbgPrint (DBG_IPXBIND, DBG_ERROR,
+ ("IpxFwd: Open of the IPX driver failed with %lx\n", status));
+ return status;
+ }
+
+ IpxFwdDbgPrint (DBG_IPXBIND, DBG_INFORMATION,
+ ("IpxFwd: Open of the IPX driver was successful.\n"));
+
+ // First, send a IOCTL to find out how much data we need to allocate
+ if ((bip = ExAllocatePoolWithTag (
+ PagedPool,
+ sizeof(IPX_INTERNAL_BIND_INPUT),
+ FWD_POOL_TAG)) == NULL) {
+
+ if (KeGetPreviousMode()!=KernelMode)
+ ZwClose (HdlIpxFile);
+ else
+ NtClose (HdlIpxFile);
+ IpxFwdDbgPrint (DBG_IPXBIND, DBG_ERROR,
+ ("IpxFwd: Could not allocate input binding buffer!\n"));
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ // fill in our bind data
+ // bip->Version = 1;
+ bip->Version = ISN_VERSION;
+ bip->Identifier = IDENTIFIER_RIP;
+ bip->BroadcastEnable = TRUE;
+ bip->LookaheadRequired = IPXH_HDRSIZE;
+ bip->ProtocolOptions = 0;
+ bip->ReceiveHandler = IpxFwdReceive;
+ bip->ReceiveCompleteHandler = IpxFwdReceiveComplete;
+ bip->SendCompleteHandler = IpxFwdSendComplete;
+ bip->TransferDataCompleteHandler = IpxFwdTransferDataComplete;
+ bip->FindRouteCompleteHandler = NULL;
+ bip->LineUpHandler = IpxFwdLineUp;
+ bip->LineDownHandler = IpxFwdLineDown;
+ bip->InternalSendHandler = IpxFwdInternalSend;
+ bip->FindRouteHandler = IpxFwdFindRoute;
+ bip->InternalReceiveHandler = IpxFwdInternalReceive;
+// bip->RipParameters = GlobalWanNetwork ? IPX_RIP_PARAM_GLOBAL_NETWORK : 0;
+
+
+ if (requestorMode==UserMode)
+ status = ZwDeviceIoControlFile(
+ HdlIpxFile, // HANDLE to File
+ NULL, // HANDLE to Event
+ NULL, // ApcRoutine
+ NULL, // ApcContext
+ &IoStatusBlock, // IO_STATUS_BLOCK
+ IOCTL_IPX_INTERNAL_BIND, // IoControlCode
+ bip, // Input Buffer
+ sizeof(IPX_INTERNAL_BIND_INPUT),// Input Buffer Length
+ NULL, // Output Buffer
+ 0); // Output Buffer Length
+ else
+ status = NtDeviceIoControlFile(
+ HdlIpxFile, // HANDLE to File
+ NULL, // HANDLE to Event
+ NULL, // ApcRoutine
+ NULL, // ApcContext
+ &IoStatusBlock, // IO_STATUS_BLOCK
+ IOCTL_IPX_INTERNAL_BIND, // IoControlCode
+ bip, // Input Buffer
+ sizeof(IPX_INTERNAL_BIND_INPUT),// Input Buffer Length
+ NULL, // Output Buffer
+ 0); // Output Buffer Length
+
+
+ if (status == STATUS_PENDING) {
+ if (requestorMode==UserMode)
+ status = ZwWaitForSingleObject(
+ HdlIpxFile,
+ FALSE,
+ NULL);
+ else
+ status = NtWaitForSingleObject(
+ HdlIpxFile,
+ FALSE,
+ NULL);
+ if (NT_SUCCESS(status))
+ status = IoStatusBlock.Status;
+ }
+
+ if (status != STATUS_BUFFER_TOO_SMALL) {
+ IpxFwdDbgPrint (DBG_IPXBIND, DBG_ERROR,
+ ("IpxFwd: Ioctl to the IPX driver failed with %lx\n", status));
+
+ ExFreePool(bip);
+ if (requestorMode==UserMode)
+ ZwClose (HdlIpxFile);
+ else
+ NtClose (HdlIpxFile);
+ return STATUS_INVALID_PARAMETER;
+ }
+
+ if ((IPXBindOutput = (PIPX_INTERNAL_BIND_RIP_OUTPUT)
+ ExAllocatePoolWithTag(NonPagedPool,
+ IoStatusBlock.Information,
+ FWD_POOL_TAG)) == NULL) {
+
+ ExFreePool(bip);
+ if (requestorMode==UserMode)
+ ZwClose (HdlIpxFile);
+ else
+ NtClose (HdlIpxFile);
+ IpxFwdDbgPrint (DBG_IPXBIND, DBG_ERROR,
+ ("IpxFwd: Could not allocate output binding buffer!\n"));
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+
+ if (requestorMode==UserMode)
+ status = ZwDeviceIoControlFile(
+ HdlIpxFile, // HANDLE to File
+ NULL, // HANDLE to Event
+ NULL, // ApcRoutine
+ NULL, // ApcContext
+ &IoStatusBlock, // IO_STATUS_BLOCK
+ IOCTL_IPX_INTERNAL_BIND, // IoControlCode
+ bip, // Input Buffer
+ sizeof(IPX_INTERNAL_BIND_INPUT),// Input Buffer Length
+ IPXBindOutput, // Output Buffer
+ IoStatusBlock.Information); // Output Buffer Length
+ else
+ status = NtDeviceIoControlFile(
+ HdlIpxFile, // HANDLE to File
+ NULL, // HANDLE to Event
+ NULL, // ApcRoutine
+ NULL, // ApcContext
+ &IoStatusBlock, // IO_STATUS_BLOCK
+ IOCTL_IPX_INTERNAL_BIND, // IoControlCode
+ bip, // Input Buffer
+ sizeof(IPX_INTERNAL_BIND_INPUT),// Input Buffer Length
+ IPXBindOutput, // Output Buffer
+ IoStatusBlock.Information); // Output Buffer Length
+
+
+ if (status == STATUS_PENDING) {
+ if (requestorMode==UserMode)
+ status = ZwWaitForSingleObject(
+ HdlIpxFile,
+ (BOOLEAN)FALSE,
+ NULL);
+ else
+ status = NtWaitForSingleObject(
+ HdlIpxFile,
+ (BOOLEAN)FALSE,
+ NULL);
+ if (NT_SUCCESS(status))
+ status = IoStatusBlock.Status;
+ }
+
+ if (!NT_SUCCESS (status)) {
+ IpxFwdDbgPrint (DBG_IPXBIND, DBG_ERROR,
+ ("IpxFwd: Ioctl to the IPX driver failed with %lx\n", IoStatusBlock.Status));
+
+ ExFreePool(bip);
+ ExFreePool(IPXBindOutput);
+ IPXBindOutput = NULL;
+ if (requestorMode==UserMode)
+ ZwClose (HdlIpxFile);
+ else
+ NtClose (HdlIpxFile);
+ return status;
+ }
+
+ IpxFwdDbgPrint (DBG_IPXBIND, DBG_INFORMATION,
+ ("IpxFwd: Succesfuly bound to the IPX driver\n"));
+
+ ExFreePool (bip);
+ ExFreePool (WstrIpxFileName);
+
+ return status;
+}
+
+
+/*++
+*******************************************************************
+ U n b i n d F r o m I p x D r i v e r
+
+Routine Description:
+ Closes connection to IPX stack driver
+Arguments:
+ None
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+UnbindFromIpxDriver (
+ KPROCESSOR_MODE requestorMode
+ ) {
+ // Free binding output buffer and close driver handle
+ ASSERT (IPXBindOutput!=NULL);
+ ExFreePool (IPXBindOutput);
+ IPXBindOutput = NULL;
+ IpxFwdDbgPrint (DBG_IPXBIND, DBG_WARNING,
+ ("IpxFwd: Closing IPX driver handle\n"));
+ if (requestorMode==UserMode)
+ ZwClose (HdlIpxFile);
+ else
+ NtClose (HdlIpxFile);
+}
+
+
+/*++
+*******************************************************************
+ F w F i n d R o u t e
+
+Routine Description:
+ This routine is provided by the Kernel Forwarder to find the route
+ to a given node and network
+Arguments:
+ Network - the destination network
+ Node - destination node
+ RouteEntry - filled in by the Forwarder if a route exists
+Return Value:
+ STATUS_SUCCESS
+ STATUS_NETWORK_UNREACHABLE - if the findroute failed
+*******************************************************************
+--*/
+NTSTATUS
+IpxFwdFindRoute (
+ IN PUCHAR Network,
+ IN PUCHAR Node,
+ OUT PIPX_FIND_ROUTE_REQUEST RouteEntry
+ ) {
+ PINTERFACE_CB ifCB;
+ ULONG net;
+ KIRQL oldIRQL;
+ NTSTATUS status;
+ PFWD_ROUTE fwRoute;
+
+ if (!EnterForwarder ())
+ return STATUS_UNSUCCESSFUL;
+
+ net = GETULONG (Network);
+
+ ifCB = FindDestination (net, Node, &fwRoute);
+ if (ifCB!=NULL) {
+ if (IS_IF_ENABLED(ifCB)) {
+ KeAcquireSpinLock (&ifCB->ICB_Lock, &oldIRQL);
+ switch (ifCB->ICB_Stats.OperationalState) {
+ case FWD_OPER_STATE_UP:
+ IPX_NET_CPY (&RouteEntry->Network, Network);
+ if (fwRoute->FR_Network==ifCB->ICB_Network) {
+ if (Node!=NULL) {
+ IPX_NODE_CPY (RouteEntry->LocalTarget.MacAddress, Node);
+ }
+ else {
+ IPX_NODE_CPY (RouteEntry->LocalTarget.MacAddress,
+ BROADCAST_NODE);
+ }
+ }
+ else {
+ IPX_NODE_CPY (RouteEntry->LocalTarget.MacAddress,
+ fwRoute->FR_NextHopAddress);
+ }
+ if (ifCB!=InternalInterface) {
+ ADAPTER_CONTEXT_TO_LOCAL_TARGET (
+ ifCB->ICB_AdapterContext,
+ &RouteEntry->LocalTarget);
+ }
+ else {
+ CONSTANT_ADAPTER_CONTEXT_TO_LOCAL_TARGET (
+ VIRTUAL_NET_ADAPTER_CONTEXT,
+ &RouteEntry->LocalTarget);
+ }
+ status = STATUS_SUCCESS;
+ break;
+ case FWD_OPER_STATE_SLEEPING:
+ IPX_NODE_CPY (&RouteEntry->LocalTarget.MacAddress,
+ fwRoute->FR_NextHopAddress);
+ CONSTANT_ADAPTER_CONTEXT_TO_LOCAL_TARGET (DEMAND_DIAL_ADAPTER_CONTEXT,
+ &RouteEntry->LocalTarget);
+ status = STATUS_SUCCESS;
+ break;
+ case FWD_OPER_STATE_DOWN:
+ status = STATUS_NETWORK_UNREACHABLE;
+ break;
+ default:
+ ASSERTMSG ("Inavalid operational state", FALSE);
+ }
+ KeReleaseSpinLock (&ifCB->ICB_Lock, oldIRQL);
+ #if DBG
+ if (Node!=NULL) {
+ if (NT_SUCCESS (status)) {
+ IpxFwdDbgPrint (DBG_IPXBIND, DBG_INFORMATION,
+ ("IpxFwd: Found route for IPX driver:"
+ " %08lX:%02X%02X%02X%02X%02X%02X"
+ " -> %ld(%ld):%02X%02X%02X%02X%02X%02X\n",
+ net, Node[0],Node[1],Node[2],Node[3],Node[4],Node[5],
+ ifCB->ICB_Index, RouteEntry->LocalTarget.NicId,
+ RouteEntry->LocalTarget.MacAddress[0],
+ RouteEntry->LocalTarget.MacAddress[1],
+ RouteEntry->LocalTarget.MacAddress[2],
+ RouteEntry->LocalTarget.MacAddress[3],
+ RouteEntry->LocalTarget.MacAddress[4],
+ RouteEntry->LocalTarget.MacAddress[5]));
+ }
+ else {
+ IpxFwdDbgPrint (DBG_IPXROUTE, DBG_WARNING,
+ ("IpxFwd: Network unreachable for:"
+ " %08lX:%02X%02X%02X%02X%02X%02X -> %ld.\n",
+ net, Node[0],Node[1],Node[2],Node[3],Node[4],Node[5],
+ ifCB->ICB_Index));
+ }
+ }
+ else {
+ if (NT_SUCCESS (status)) {
+ IpxFwdDbgPrint (DBG_IPXBIND, DBG_INFORMATION,
+ ("IpxFwd: Found route for IPX driver:"
+ " %08lX"
+ " -> %ld(%ld):%02X%02X%02X%02X%02X%02X\n",
+ net, ifCB->ICB_Index, RouteEntry->LocalTarget.NicId,
+ RouteEntry->LocalTarget.MacAddress[0],
+ RouteEntry->LocalTarget.MacAddress[1],
+ RouteEntry->LocalTarget.MacAddress[2],
+ RouteEntry->LocalTarget.MacAddress[3],
+ RouteEntry->LocalTarget.MacAddress[4],
+ RouteEntry->LocalTarget.MacAddress[5]));
+ }
+ else {
+ IpxFwdDbgPrint (DBG_IPXROUTE, DBG_WARNING,
+ ("IpxFwd: Network unreachable for:"
+ " %08lX -> %ld.\n", net));
+ }
+ }
+ #endif
+ ReleaseInterfaceReference (ifCB);
+ ReleaseRouteReference (fwRoute);
+
+ }
+ }
+ else {
+#if DBG
+ if (Node!=NULL) {
+ IpxFwdDbgPrint (DBG_IPXROUTE, DBG_WARNING,
+ ("IpxFwd: No route for:"
+ " %08lX:%02X%02X%02X%02X%02X%02X.\n",
+ net, Node[0],Node[1],Node[2],Node[3],Node[4],Node[5]));
+ }
+ else {
+ IpxFwdDbgPrint (DBG_IPXROUTE, DBG_WARNING,
+ ("IpxFwd: No route for: %08lX.\n", net));
+ }
+#endif
+ status = STATUS_NETWORK_UNREACHABLE;
+ }
+ LeaveForwarder ();
+ return status;
+}
+
+
diff --git a/private/ntos/tdi/isn/fwd/ipxbind.h b/private/ntos/tdi/isn/fwd/ipxbind.h
new file mode 100644
index 000000000..7cf367a2b
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/ipxbind.h
@@ -0,0 +1,75 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ ntos\tdi\isn\fwd\ipxbind.h
+
+Abstract:
+ IPX Forwarder Driver interface with IPX stack driver
+
+
+Author:
+
+ Vadim Eydelman
+
+Revision History:
+
+--*/
+
+
+#ifndef _IPXFWD_IPXBIND_
+#define _IPXFWD_IPXBIND_
+
+extern PIPX_INTERNAL_BIND_RIP_OUTPUT IPXBindOutput;
+#define IPXMacHeaderSize (IPXBindOutput->MacHeaderNeeded)
+#define IPXOpenAdapterProc (IPXBindOutput->OpenAdapterHandler)
+#define IPXCloseAdapterProc (IPXBindOutput->CloseAdapterHandler)
+#define IPXInternalSendCompletProc (IPXBindOutput->InternalSendCompleteHandler)
+#define IPXSendProc (IPXBindOutput->SendHandler)
+#define IPXTransferData (IPXBindOutput->TransferDataHandler)
+
+
+/*++
+*******************************************************************
+ B i n d T o I p x D r i v e r
+
+Routine Description:
+ Exchanges binding information with IPX stack driver
+Arguments:
+Return Value:
+ STATUS_SUCCESS - exchange was done OK
+ STATUS_INSUFFICIENT_RESOURCES - could not allocate buffers for
+ info exchange
+ error status returned by IPX stack driver
+
+*******************************************************************
+--*/
+NTSTATUS
+BindToIpxDriver (
+ KPROCESSOR_MODE requestorMode
+ );
+
+
+/*++
+*******************************************************************
+ U n b i n d T o I p x D r i v e r
+
+Routine Description:
+ Closes connection to IPX stack driver
+Arguments:
+ None
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+UnbindFromIpxDriver (
+ KPROCESSOR_MODE requestorMode
+ );
+
+
+#endif
+
diff --git a/private/ntos/tdi/isn/fwd/lineind.c b/private/ntos/tdi/isn/fwd/lineind.c
new file mode 100644
index 000000000..e00518d6a
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/lineind.c
@@ -0,0 +1,323 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ ntos\tdi\isn\fwd\lineind.c
+
+Abstract:
+ Processing line indication (bind/unbind)
+
+
+Author:
+
+ Vadim Eydelman
+
+Revision History:
+
+--*/
+
+#include "precomp.h"
+
+
+/*++
+*******************************************************************
+ B i n d I n t e r f a c e
+
+Routine Description:
+ Binds interface to physical adapter and exchanges contexts
+ with IPX stack
+Arguments:
+ ifCB - interface to bind
+ NicId - id of an adapter
+ MaxPacketSize - max size of packet allowed
+ Network - adapter network address
+ LocalNode - adapter local node address
+ RemoteNode - peer node address (for clients on global
+ net)
+Return Value:
+ STATUS_SUCCESS - interface was bound OK
+ error status returned by IPX stack driver
+
+*******************************************************************
+--*/
+NTSTATUS
+BindInterface (
+ IN PINTERFACE_CB ifCB,
+ IN USHORT NicId,
+ IN ULONG MaxPacketSize,
+ IN ULONG Network,
+ IN PUCHAR LocalNode,
+ IN PUCHAR RemoteNode
+ ) {
+ KIRQL oldIRQL;
+ NTSTATUS status;
+ NIC_HANDLE NicHandle={0};
+
+ KeAcquireSpinLock (&ifCB->ICB_Lock, &oldIRQL);
+ if (ifCB->ICB_Stats.OperationalState!=FWD_OPER_STATE_UP) {
+ switch (ifCB->ICB_InterfaceType) {
+ case FWD_IF_PERMANENT:
+ if (ifCB->ICB_Index!=FWD_INTERNAL_INTERFACE_INDEX)
+ status = RegisterPacketConsumer (MaxPacketSize,
+ &ifCB->ICB_PacketListId);
+ else
+ status = STATUS_SUCCESS;
+ break;
+ case FWD_IF_DEMAND_DIAL:
+ case FWD_IF_LOCAL_WORKSTATION:
+ case FWD_IF_REMOTE_WORKSTATION:
+ if (IS_IF_CONNECTING (ifCB)) {
+ SET_IF_NOT_CONNECTING (ifCB);
+ DequeueConnectionRequest (ifCB);
+ }
+ status = STATUS_SUCCESS;
+ break;
+ default:
+ ASSERTMSG ("Invalid interface type ", FALSE);
+ break;
+ }
+ if (NT_SUCCESS (status)) {
+ if (Network==GlobalNetwork) {
+ ASSERT (ifCB->ICB_Index!=FWD_INTERNAL_INTERFACE_INDEX);
+ IPX_NODE_CPY (ifCB->ICB_RemoteNode, RemoteNode);
+ status = AddGlobalNetClient (ifCB);
+ ASSERT (status==STATUS_SUCCESS);
+ }
+ KeReleaseSpinLock (&ifCB->ICB_Lock, oldIRQL);
+
+ if (ifCB->ICB_Index!=FWD_INTERNAL_INTERFACE_INDEX) {
+ NIC_HANDLE_FROM_NIC(NicHandle, NicId);
+ status = IPXOpenAdapterProc (NicHandle, (ULONG)ifCB,
+ &ifCB->ICB_AdapterContext);
+ }
+
+ if (NT_SUCCESS (status)) {
+ ifCB->ICB_Network = Network;
+ IPX_NODE_CPY (ifCB->ICB_RemoteNode, RemoteNode);
+ IPX_NODE_CPY (ifCB->ICB_LocalNode, LocalNode);
+ if (ifCB->ICB_InterfaceType==FWD_IF_PERMANENT)
+ ifCB->ICB_Stats.MaxPacketSize = MaxPacketSize;
+ else
+ ifCB->ICB_Stats.MaxPacketSize = WAN_PACKET_SIZE;
+ ifCB->ICB_NicId = NicId;
+ ifCB->ICB_Stats.OperationalState = FWD_OPER_STATE_UP;
+
+ AcquireInterfaceReference (ifCB);
+ IpxFwdDbgPrint (DBG_LINEIND, DBG_INFORMATION,
+ ("IpxFwd: Bound interface %ld (icb: %08lx):"
+ " Nic-%d, Net-%08lx,"
+ " LocalNode-%02x%02x%02x%02x%02x%02x,"
+ " RemoteNode-%02x%02x%02x%02x%02x%02x.\n",
+ ifCB->ICB_Index, ifCB, NicId, Network,
+ LocalNode[0], LocalNode[1], LocalNode[2],
+ LocalNode[3], LocalNode[4], LocalNode[5],
+ RemoteNode[0], RemoteNode[1], RemoteNode[2],
+ RemoteNode[3], RemoteNode[4], RemoteNode[5]));
+
+ if (ifCB->ICB_Index!=FWD_INTERNAL_INTERFACE_INDEX) {
+ ProcessInternalQueue (ifCB);
+ ProcessExternalQueue (ifCB);
+ }
+ return STATUS_SUCCESS;
+ }
+
+ IpxFwdDbgPrint (DBG_LINEIND, DBG_ERROR,
+ ("IpxFwd: Could not open adapter %d to bind"
+ " interface %ld (icb: %08lx)!\n",
+ NicId, ifCB->ICB_Index, ifCB));
+
+ KeAcquireSpinLock (&ifCB->ICB_Lock, &oldIRQL);
+ if (Network==GlobalNetwork) {
+ DeleteGlobalNetClient (ifCB);
+ }
+
+ switch (ifCB->ICB_InterfaceType) {
+ case FWD_IF_PERMANENT:
+ DeregisterPacketConsumer (ifCB->ICB_PacketListId);
+ break;
+ case FWD_IF_DEMAND_DIAL:
+ case FWD_IF_LOCAL_WORKSTATION:
+ case FWD_IF_REMOTE_WORKSTATION:
+ break;
+ }
+ }
+ ifCB->ICB_Stats.OperationalState = FWD_OPER_STATE_DOWN;
+ KeReleaseSpinLock (&ifCB->ICB_Lock, oldIRQL);
+
+ ProcessInternalQueue (ifCB);
+ ProcessExternalQueue (ifCB);
+ }
+ else {
+ ASSERT (Network==ifCB->ICB_Network);
+ ASSERT (NicId==(USHORT)ifCB->ICB_AdapterContext.NicId);
+ KeReleaseSpinLock (&ifCB->ICB_Lock, oldIRQL);
+ status = STATUS_SUCCESS; // Report success if already
+ // connected
+ IpxFwdDbgPrint (DBG_LINEIND, DBG_WARNING,
+ ("IpxFwd: Interface %ld (icb: %08lx) is already bound to Nic %d.\n",
+ ifCB->ICB_Index, ifCB, NicId));
+ }
+ return status;
+}
+
+
+/*++
+*******************************************************************
+ U n b i n d I n t e r f a c e
+
+Routine Description:
+ Unbinds interface from physical adapter and breaks connection
+ with IPX stack
+Arguments:
+ ifCB - interface to unbind
+Return Value:
+ None
+*******************************************************************
+--*/
+VOID
+UnbindInterface (
+ PINTERFACE_CB ifCB
+ ) {
+ KIRQL oldIRQL;
+ KeAcquireSpinLock (&ifCB->ICB_Lock, &oldIRQL);
+ if (ifCB->ICB_Stats.OperationalState==FWD_OPER_STATE_UP) {
+ switch (ifCB->ICB_InterfaceType) {
+ case FWD_IF_PERMANENT:
+ ifCB->ICB_Stats.OperationalState = FWD_OPER_STATE_DOWN;
+ if (ifCB->ICB_Index!=FWD_INTERNAL_INTERFACE_INDEX)
+ DeregisterPacketConsumer (ifCB->ICB_PacketListId);
+ break;
+ case FWD_IF_DEMAND_DIAL:
+ case FWD_IF_LOCAL_WORKSTATION:
+ case FWD_IF_REMOTE_WORKSTATION:
+ ifCB->ICB_Stats.OperationalState = FWD_OPER_STATE_SLEEPING;
+ KeQuerySystemTime ((PLARGE_INTEGER)&ifCB->ICB_DisconnectTime);
+ break;
+ default:
+ ASSERTMSG ("Invalid interface type ", FALSE);
+ break;
+ }
+ if (ifCB->ICB_CashedInterface!=NULL)
+ ReleaseInterfaceReference (ifCB->ICB_CashedInterface);
+ ifCB->ICB_CashedInterface = NULL;
+ if (ifCB->ICB_CashedRoute!=NULL)
+ ReleaseRouteReference (ifCB->ICB_CashedRoute);
+ ifCB->ICB_CashedRoute = NULL;
+ if (ifCB->ICB_Network==GlobalNetwork)
+ DeleteGlobalNetClient (ifCB);
+ KeReleaseSpinLock (&ifCB->ICB_Lock, oldIRQL);
+
+ IpxFwdDbgPrint (DBG_LINEIND, DBG_INFORMATION,
+ ("IpxFwd: Unbinding interface %ld (icb: %08lx) from Nic %ld.\n",
+ ifCB->ICB_Index, ifCB, ifCB->ICB_AdapterContext));
+ if (ifCB->ICB_Index!=FWD_INTERNAL_INTERFACE_INDEX) {
+ IPXCloseAdapterProc (ifCB->ICB_AdapterContext);
+ ProcessInternalQueue (ifCB);
+ ProcessExternalQueue (ifCB);
+ }
+ ReleaseInterfaceReference (ifCB);
+ }
+ else {
+ KeReleaseSpinLock (&ifCB->ICB_Lock, oldIRQL);
+ IpxFwdDbgPrint (DBG_LINEIND, DBG_WARNING,
+ ("IpxFwd: Interface %ld (icb: %08lx) is already unbound.\n",
+ ifCB->ICB_Index, ifCB));
+ }
+}
+
+
+
+/*++
+*******************************************************************
+ F w L i n e U p
+
+Routine Description:
+ Process line up indication delivered by IPX stack
+Arguments:
+ NicId - adapter ID on which connection was established
+ LineInfo - NDIS/IPX line information
+ DeviceType - medium specs
+ ConfigurationData - IPX CP configuration data
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+IpxFwdLineUp (
+ IN USHORT NicId,
+ IN PIPX_LINE_INFO LineInfo,
+ IN NDIS_MEDIUM DeviceType,
+ IN PVOID ConfigurationData
+ ) {
+ PINTERFACE_CB ifCB;
+ if (ConfigurationData==NULL) // This is just an update for multilink
+ // connections
+ return;
+
+ if (!EnterForwarder()) {
+ return;
+ }
+ IpxFwdDbgPrint (DBG_LINEIND, DBG_INFORMATION, ("IpxFwd: FwdLineUp.\n"));
+
+ ifCB = GetInterfaceReference (
+ ((PIPXCP_CONFIGURATION)ConfigurationData)->InterfaceIndex);
+ if (ifCB!=NULL) {
+ LONG Net = GETULONG (((PIPXCP_CONFIGURATION)ConfigurationData)->Network);
+
+ ASSERT (ifCB->ICB_Index!=FWD_INTERNAL_INTERFACE_INDEX);
+ ASSERT (ifCB->ICB_InterfaceType!=FWD_IF_PERMANENT);
+
+ BindInterface (ifCB,
+ NicId,
+ LineInfo->MaximumPacketSize,
+ Net,
+ ((PIPXCP_CONFIGURATION)ConfigurationData)->LocalNode,
+ ((PIPXCP_CONFIGURATION)ConfigurationData)->RemoteNode
+ );
+ ReleaseInterfaceReference (ifCB);
+ }
+ LeaveForwarder ();
+}
+
+
+
+
+/*++
+*******************************************************************
+ F w L i n e D o w n
+
+Routine Description:
+ Process line down indication delivered by IPX stack
+Arguments:
+ NicId - disconnected adapter ID
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+IpxFwdLineDown (
+ IN USHORT NicId,
+ IN ULONG Context
+ ) {
+ PINTERFACE_CB ifCB;
+
+ if (!EnterForwarder()) {
+ return;
+ }
+ IpxFwdDbgPrint (DBG_LINEIND, DBG_INFORMATION, ("IpxFwd: FwdLineDown.\n"));
+
+
+ ifCB = InterfaceContextToReference ((PVOID)Context, NicId);
+ if (ifCB!=NULL) {
+ ASSERT (ifCB->ICB_Index!=FWD_INTERNAL_INTERFACE_INDEX);
+ ASSERT (ifCB->ICB_InterfaceType!=FWD_IF_PERMANENT);
+ UnbindInterface (ifCB);
+ ReleaseInterfaceReference (ifCB);
+ }
+ LeaveForwarder ();
+}
+
diff --git a/private/ntos/tdi/isn/fwd/lineind.h b/private/ntos/tdi/isn/fwd/lineind.h
new file mode 100644
index 000000000..bbc8df7ac
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/lineind.h
@@ -0,0 +1,116 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ ntos\tdi\isn\fwd\lineind.h
+
+Abstract:
+ Processing line indication (bind/unbind)
+
+
+Author:
+
+ Vadim Eydelman
+
+Revision History:
+
+--*/
+
+#ifndef _IPXFWD_LINEIND_
+#define _IPXFWD_LINEIND_
+
+/*++
+*******************************************************************
+ B i n d I n t e r f a c e
+
+Routine Description:
+ Binds interface to physical adapter and exchanges contexts
+ with IPX stack
+Arguments:
+ ifCB - interface to bind
+ NicId - id of an adapter
+ MaxPacketSize - max size of packet allowed
+ Network - adapter network address
+ LocalNode - adapter local node address
+ RemoteNode - peer node address (for clients on global
+ net)
+Return Value:
+ STATUS_SUCCESS - interface was bound OK
+ error status returned by IPX stack driver
+
+*******************************************************************
+--*/
+NTSTATUS
+BindInterface (
+ IN PINTERFACE_CB ifCB,
+ IN USHORT NicId,
+ IN ULONG MaxPacketSize,
+ IN ULONG Network,
+ IN PUCHAR LocalNode,
+ IN PUCHAR RemoteNode
+ );
+
+/*++
+*******************************************************************
+ U n b i n d I n t e r f a c e
+
+Routine Description:
+ Unbinds interface from physical adapter and breaks connection
+ with IPX stack
+Arguments:
+ ifCB - interface to unbind
+Return Value:
+ None
+*******************************************************************
+--*/
+VOID
+UnbindInterface (
+ PINTERFACE_CB ifCB
+ );
+
+/*++
+*******************************************************************
+ F w L i n e U p
+
+Routine Description:
+ Process line up indication delivered by IPX stack
+Arguments:
+ NicId - adapter ID on which connection was established
+ LineInfo - NDIS/IPX line information
+ DeviceType - medium specs
+ ConfigurationData - IPX CP configuration data
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+IpxFwdLineUp (
+ IN USHORT NicId,
+ IN PIPX_LINE_INFO LineInfo,
+ IN NDIS_MEDIUM DeviceType,
+ IN PVOID ConfigurationData
+ );
+
+/*++
+*******************************************************************
+ F w L i n e D o w n
+
+Routine Description:
+ Process line down indication delivered by IPX stack
+Arguments:
+ NicId - disconnected adapter ID
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+IpxFwdLineDown (
+ IN USHORT NicId,
+ IN ULONG Context
+ );
+
+#endif
diff --git a/private/ntos/tdi/isn/fwd/mp/makefile b/private/ntos/tdi/isn/fwd/mp/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/mp/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/tdi/isn/fwd/mp/sources b/private/ntos/tdi/isn/fwd/mp/sources
new file mode 100644
index 000000000..dc48d81bb
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/mp/sources
@@ -0,0 +1,29 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+NT_UP=0
+
+TARGETPATH=\nt\public\sdk\lib
+
+!include ..\sources.inc
diff --git a/private/ntos/tdi/isn/fwd/netbios.c b/private/ntos/tdi/isn/fwd/netbios.c
new file mode 100644
index 000000000..4a1f9b84b
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/netbios.c
@@ -0,0 +1,311 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ ntos\tdi\isn\fwd\netbios.c
+
+Abstract:
+ Netbios packet processing
+
+Author:
+
+ Vadim Eydelman
+
+Revision History:
+
+--*/
+#include "precomp.h"
+
+LIST_ENTRY NetbiosQueue;
+KSPIN_LOCK NetbiosQueueLock;
+WORK_QUEUE_ITEM NetbiosWorker;
+BOOLEAN NetbiosWorkerScheduled=FALSE;
+ULONG NetbiosPacketsQuota;
+ULONG MaxNetbiosPacketsQueued = DEF_MAX_NETBIOS_PACKETS_QUEUED;
+
+
+/*++
+*******************************************************************
+ P r o c e s s N e t b i o s Q u e u e
+
+Routine Description:
+ Process packets in the netbios broadcast queue (sends them on
+ all interfaces in sequence)
+Arguments:
+ Context - unused
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+ProcessNetbiosQueue (
+ PVOID Context
+ ) {
+ KIRQL oldIRQL;
+ LIST_ENTRY tempQueue;
+
+ KeAcquireSpinLock (&NetbiosQueueLock, &oldIRQL);
+ // Check if there is something in the queue
+ if (!IsListEmpty (&NetbiosQueue)) {
+ // Move the queue to local variable
+ InsertHeadList (&NetbiosQueue, &tempQueue);
+ RemoveEntryList (&NetbiosQueue);
+ InitializeListHead (&NetbiosQueue);
+
+ KeReleaseSpinLock (&NetbiosQueueLock, oldIRQL);
+ do {
+ PLIST_ENTRY cur;
+ PPACKET_TAG pktTag;
+
+ cur = RemoveHeadList (&tempQueue);
+ pktTag = CONTAINING_RECORD (cur, PACKET_TAG, PT_QueueLink);
+ // Check if this packet has to be sent on other
+ // interfaces
+ if (!(pktTag->PT_Flags&PT_NB_DESTROY)) {
+ PINTERFACE_CB dstIf = pktTag->PT_InterfaceReference;
+ PUCHAR dataPtr = pktTag->PT_Data;
+ UINT rtCount = *(dataPtr+IPXH_XPORTCTL);
+ PUCHAR netListPtr;
+ UINT i;
+
+ if (dstIf==NULL) {
+ // This is a brand new packet: not sent on any
+ // interface yet
+ USHORT dstSock = GETUSHORT (dataPtr+IPXH_DESTSOCK);
+ // Check if we have a static route for this name
+ // (offset to name depends on packet dest socket)
+ if (dstSock==IPX_NETBIOS_SOCKET)
+ dstIf = FindNBDestination (dataPtr+NB_NAME);
+ else if (dstSock==IPX_SMB_NAME_SOCKET)
+ dstIf = FindNBDestination (dataPtr+SMB_NAME);
+ else
+ dstIf = NULL;
+
+ if (dstIf!=NULL) {
+ // Static route found, make sure this packet
+ // won't be sent on any other interface
+ pktTag->PT_Flags |= PT_NB_DESTROY;
+ InterlockedIncrement (&NetbiosPacketsQuota);
+ // Make sure the packet has not traversed
+ // this network already
+ for (i=0, netListPtr=dataPtr+IPXH_HDRSIZE; i<rtCount; i++,netListPtr+=4) {
+ if (GETULONG (netListPtr)==dstIf->ICB_Network)
+ break;
+ }
+ // Make sure we are allowed to send on this
+ // interface
+ if ((dstIf!=InternalInterface)
+ && (i==rtCount) // Has not already traversed
+ // this network
+ && IS_IF_ENABLED (dstIf)
+ && ((dstIf->ICB_NetbiosDeliver==FWD_NB_DELIVER_ALL)
+ || (dstIf->ICB_NetbiosDeliver
+ ==FWD_NB_DELIVER_STATIC)
+ || ((dstIf->ICB_NetbiosDeliver
+ ==FWD_NB_DELIVER_IF_UP)
+ && (dstIf->ICB_Stats.OperationalState
+ ==FWD_OPER_STATE_UP)))) {
+ NOTHING;
+ }
+ else {
+ // We have static route, but can't send it,
+ // no point to propagate in on other interfaces
+ // as well
+ ReleaseInterfaceReference (dstIf);
+ dstIf = NULL;
+ goto FreePacket;
+ }
+ }
+ else { // no static route
+ goto FindNextInterface;
+ }
+ }
+ else { // not a brand new packet (already sent on some
+ // interfaces)
+
+ FindNextInterface:
+
+ // Loop through the interface list till we find
+ // the one on which we can send
+ while ((dstIf=GetNextInterfaceReference (dstIf))!=NULL) {
+ // Check if we allowed to send on this interface
+ if (IS_IF_ENABLED (dstIf)
+ && ((dstIf->ICB_NetbiosDeliver==FWD_NB_DELIVER_ALL)
+ || ((dstIf->ICB_NetbiosDeliver
+ ==FWD_NB_DELIVER_IF_UP)
+ && (dstIf->ICB_Stats.OperationalState
+ ==FWD_OPER_STATE_UP)))) {
+ // Make sure the packet has not traversed
+ // this network already
+ for (i=0, netListPtr=dataPtr+IPXH_HDRSIZE; i<rtCount; i++,netListPtr+=4) {
+ if (GETULONG (netListPtr)==dstIf->ICB_Network)
+ break;
+ }
+ // Network was not in the list
+ if (i==rtCount)
+ break;
+ }
+ }
+ }
+ // Save the destination interface in the packet
+ pktTag->PT_InterfaceReference = dstIf;
+ // Go ahead and send if we have a valid destination
+ if (dstIf!=NULL) {
+ SendPacket (dstIf, pktTag);
+ // The rest does not apply: if the packet was sent or
+ // failed, it will be queued back to NetbiosQueue;
+ // if it was queued to interface to be connected,
+ // a copy of it will be queued to NetbiosQueue
+ continue;
+ }
+ // else no more destinations to send this packet on
+ }
+ else { // Packet has to be destroyed
+ if (pktTag->PT_InterfaceReference!=NULL)
+ ReleaseInterfaceReference (pktTag->PT_InterfaceReference);
+ }
+
+ FreePacket:
+ IpxFwdDbgPrint (DBG_NETBIOS, DBG_INFORMATION,
+ ("IpxFwd: No more interfaces for nb packet %08lx.\n",
+ pktTag));
+ if (MeasuringPerformance
+ && (pktTag->PT_PerfCounter!=0)) {
+ LARGE_INTEGER PerfCounter = KeQueryPerformanceCounter (NULL);
+ PerfCounter.QuadPart -= pktTag->PT_PerfCounter;
+ KeAcquireSpinLock (&PerfCounterLock, &oldIRQL);
+ PerfBlock.TotalNbPacketProcessingTime += PerfCounter.QuadPart;
+ PerfBlock.NbPacketCounter += 1;
+ if (PerfBlock.MaxNbPacketProcessingTime < PerfCounter.QuadPart)
+ PerfBlock.MaxNbPacketProcessingTime = PerfCounter.QuadPart;
+ KeReleaseSpinLock (&PerfCounterLock, oldIRQL);
+ }
+ if (!(pktTag->PT_Flags&PT_NB_DESTROY))
+ InterlockedIncrement (&NetbiosPacketsQuota);
+ FreePacket (pktTag);
+ } while (!IsListEmpty (&tempQueue));
+
+ KeAcquireSpinLock (&NetbiosQueueLock, &oldIRQL);
+ if (IsListEmpty (&NetbiosQueue)
+ || !EnterForwarder ()) {
+ NetbiosWorkerScheduled = FALSE;
+ }
+ else {
+ ExQueueWorkItem (&NetbiosWorker, DelayedWorkQueue);
+ }
+ }
+ KeReleaseSpinLock (&NetbiosQueueLock, oldIRQL);
+ LeaveForwarder ();
+}
+
+/*++
+*******************************************************************
+ P r o c e s s N e t b i o s P a c k e t
+
+Routine Description:
+ Processes received netbios broadcast packet (checks network list
+ and source filter, updates input statistics)
+Arguments:
+ srcIf - interfae on which packet was received
+ pktTag - netbios packet
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+ProcessNetbiosPacket (
+ PINTERFACE_CB srcIf,
+ PPACKET_TAG pktTag
+ ) {
+ PUCHAR dataPtr;
+ UINT rtCount;
+ UINT i;
+ KIRQL oldIRQL;
+
+
+ dataPtr = pktTag->PT_Data;
+ rtCount = *(dataPtr+IPXH_XPORTCTL);
+
+ // Check if source network is already in the packet network list
+ for (i=0, dataPtr+=IPXH_HDRSIZE; i<rtCount; i++, dataPtr+=4) {
+ if (srcIf->ICB_Network==GETULONG (dataPtr))
+ break;
+ }
+ // We scaned the whole list and we haven't found it
+ if (i==rtCount) {
+ FILTER_ACTION action;
+ action = FltFilter (pktTag->PT_Data,
+ GETUSHORT (pktTag->PT_Data+IPXH_LENGTH),
+ srcIf->ICB_FilterInContext, NULL);
+ // Apply the input filter
+ if (action==FILTER_PERMIT) {
+ InterlockedIncrement (&srcIf->ICB_Stats.NetbiosReceived);
+ InterlockedIncrement (&srcIf->ICB_Stats.InDelivers);
+ PUTULONG (srcIf->ICB_Network, dataPtr);
+ *(pktTag->PT_Data+IPXH_XPORTCTL) += 1;
+ IPX_NODE_CPY (pktTag->PT_Target.MacAddress, BROADCAST_NODE);
+ // Initialize the packet
+ pktTag->PT_InterfaceReference = NULL; // not yet sent on any
+ // interfaces
+ pktTag->PT_Flags = 0; // No flags
+ QueueNetbiosPacket (pktTag);
+ IpxFwdDbgPrint (DBG_NETBIOS, DBG_INFORMATION,
+ ("IpxFwd: Queued nb packet %08lx from if %ld.\n",
+ pktTag, srcIf->ICB_Index));
+ }
+ else {
+ ASSERT (action==FILTER_DENY_IN);
+ IpxFwdDbgPrint (DBG_NETBIOS, DBG_WARNING,
+ ("IpxFwd: Filtered out nb packet %08lx"
+ " from if %ld.\n", pktTag, srcIf->ICB_Index));
+ InterlockedIncrement (&NetbiosPacketsQuota);
+ InterlockedIncrement (&srcIf->ICB_Stats.InFiltered);
+ FreePacket (pktTag);
+ }
+ }
+ else {
+ IpxFwdDbgPrint (DBG_NETBIOS, DBG_WARNING,
+ ("IpxFwd: Source net is already in nb packet %08lx"
+ " from if %ld.\n", pktTag, srcIf->ICB_Index));
+ InterlockedIncrement (&NetbiosPacketsQuota);
+ InterlockedIncrement (&srcIf->ICB_Stats.InDiscards);
+ FreePacket (pktTag);
+ }
+ ReleaseInterfaceReference (srcIf);
+
+}
+
+
+/*++
+*******************************************************************
+ D e l e t e N e t b i o s Q u e u e
+
+Routine Description:
+ Deletes the netbios bradcast queue
+Arguments:
+ None
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+DeleteNetbiosQueue (
+ void
+ ) {
+ while (!IsListEmpty (&NetbiosQueue)) {
+ PPACKET_TAG pktTag = CONTAINING_RECORD (NetbiosQueue.Flink,
+ PACKET_TAG,
+ PT_QueueLink);
+ RemoveEntryList (&pktTag->PT_QueueLink);
+ if (pktTag->PT_InterfaceReference!=NULL) {
+ ReleaseInterfaceReference (pktTag->PT_InterfaceReference);
+ }
+ FreePacket (pktTag);
+ }
+}
+
diff --git a/private/ntos/tdi/isn/fwd/netbios.h b/private/ntos/tdi/isn/fwd/netbios.h
new file mode 100644
index 000000000..ffa6da1c4
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/netbios.h
@@ -0,0 +1,134 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ ntos\tdi\isn\fwd\netbios.h
+
+Abstract:
+ Netbios packet processing
+
+Author:
+
+ Vadim Eydelman
+
+Revision History:
+
+--*/
+
+#ifndef IPXFWD_NETBIOS
+#define IPXFWD_NETBIOS
+
+extern LIST_ENTRY NetbiosQueue;
+extern KSPIN_LOCK NetbiosQueueLock;
+extern WORK_QUEUE_ITEM NetbiosWorker;
+extern BOOLEAN NetbiosWorkerScheduled;
+extern ULONG NetbiosPacketsQuota;
+extern ULONG MaxNetbiosPacketsQueued;
+#define DEF_MAX_NETBIOS_PACKETS_QUEUED 256
+
+
+/*++
+*******************************************************************
+ I n i t i a l i z e N e t b i o s Q u e u e
+
+Routine Description:
+ Initializes the netbios bradcast queue
+Arguments:
+ None
+Return Value:
+ None
+
+*******************************************************************
+--*/
+//VOID
+//InitializeNetbiosQueue (
+// void
+// )
+#define InitializeNetbiosQueue() { \
+ InitializeListHead (&NetbiosQueue); \
+ KeInitializeSpinLock (&NetbiosQueueLock); \
+ ExInitializeWorkItem (&NetbiosWorker, &ProcessNetbiosQueue, NULL);\
+ NetbiosWorkerScheduled = FALSE; \
+ NetbiosPacketsQuota = MaxNetbiosPacketsQueued; \
+}
+
+/*++
+*******************************************************************
+ D e l e t e N e t b i o s Q u e u e
+
+Routine Description:
+ Deletes the netbios bradcast queue
+Arguments:
+ None
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+DeleteNetbiosQueue (
+ void
+ );
+
+
+/*++
+*******************************************************************
+ P r o c e s s N e t b i o s Q u e u e
+
+Routine Description:
+ Process packets in the netbios bradcast queue
+Arguments:
+ Context - unused
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+ProcessNetbiosQueue (
+ PVOID Context
+ );
+
+/*++
+*******************************************************************
+ P r o c e s s N e t b i o s P a c k e t
+
+Routine Description:
+ Processes received netbios broadcast packet
+Arguments:
+ None
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+ProcessNetbiosPacket (
+ PINTERFACE_CB srcIf,
+ PPACKET_TAG pktTag
+ );
+
+
+#define QueueNetbiosPacket(pktTag) { \
+ KIRQL oldIRQL; \
+ KeAcquireSpinLock (&NetbiosQueueLock, &oldIRQL); \
+ InsertTailList (&NetbiosQueue, &pktTag->PT_QueueLink); \
+ KeReleaseSpinLock (&NetbiosQueueLock, oldIRQL); \
+}
+
+#define ScheduleNetbiosWorker() { \
+ KIRQL oldIRQL; \
+ KeAcquireSpinLock (&NetbiosQueueLock, &oldIRQL); \
+ if (!NetbiosWorkerScheduled \
+ && !IsListEmpty (&NetbiosQueue) \
+ && EnterForwarder ()) { \
+ NetbiosWorkerScheduled = TRUE; \
+ ExQueueWorkItem (&NetbiosWorker, DelayedWorkQueue); \
+ } \
+ KeReleaseSpinLock (&NetbiosQueueLock, oldIRQL); \
+}
+
+#endif
+
diff --git a/private/ntos/tdi/isn/fwd/nwlnkfwd.rc b/private/ntos/tdi/isn/fwd/nwlnkfwd.rc
new file mode 100644
index 000000000..477fd6e01
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/nwlnkfwd.rc
@@ -0,0 +1,12 @@
+#include <windows.h>
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DRV
+#define VER_FILESUBTYPE VFT2_DRV_NETWORK
+#define VER_FILEDESCRIPTION_STR "NWLINK2 Forwarder Driver"
+#define VER_INTERNALNAME_STR "nwlnkfwd.sys"
+#define VER_ORIGINALFILENAME_STR "nwlnkfwd.sys"
+
+#include "common.ver"
+
diff --git a/private/ntos/tdi/isn/fwd/packets.c b/private/ntos/tdi/isn/fwd/packets.c
new file mode 100644
index 000000000..9577a6d2c
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/packets.c
@@ -0,0 +1,528 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ ntos\tdi\isn\fwd\packets.c
+
+Abstract:
+ IPX Forwarder Driver packet allocator
+
+
+Author:
+
+ Vadim Eydelman
+
+Revision History:
+
+--*/
+
+#include "precomp.h"
+
+ULONG RcvPktsPerSegment = DEF_RCV_PKTS_PER_SEGMENT;
+ULONG MaxRcvPktsPoolSize =0;
+ULONG RcvPktsPoolSize = 0;
+KSPIN_LOCK AllocatorLock;
+const LONGLONG SegmentTimeout = -10i64*10000000i64;
+
+SEGMENT_LIST ListEther={1500};
+SEGMENT_LIST ListTR4={4500};
+SEGMENT_LIST ListTR16={17986};
+
+PSEGMENT_LIST SegmentMap[FRAME_SIZE_VARIATIONS][FRAME_SIZE_VARIATIONS] = {
+ {&ListEther, &ListEther, &ListEther},
+ {&ListEther, &ListTR4, &ListTR4},
+ {&ListEther, &ListTR4, &ListTR16}
+};
+
+VOID
+AllocationWorker (
+ PVOID Context
+ );
+
+VOID
+SegmentTimeoutDpc (
+ PKDPC dpc,
+ PVOID Context,
+ PVOID SystemArgument1,
+ PVOID SystemArgument2
+ );
+
+/*++
+*******************************************************************
+ C r e a t e S e g m e n t
+
+Routine Description:
+ Allocates and initializes packet segment
+Arguments:
+ list - segment list to which new segment will be added
+Return Value:
+ Pointer to allocated segment, NULL if fails
+
+*******************************************************************
+--*/
+PPACKET_SEGMENT
+CreateSegment (
+ PSEGMENT_LIST list
+ ) {
+ KIRQL oldIRQL;
+ NDIS_STATUS status;
+ PPACKET_SEGMENT segment;
+ ULONG segmentsize = list->SL_BlockCount*list->SL_BlockSize
+ +FIELD_OFFSET(PACKET_SEGMENT,PS_Buffers);
+ if (MaxRcvPktsPoolSize!=0) {
+ // Check if this allocation would exceed the limit
+ KeAcquireSpinLock (&AllocatorLock, &oldIRQL);
+ if (RcvPktsPoolSize+segmentsize<MaxRcvPktsPoolSize) {
+ RcvPktsPoolSize += segmentsize;
+ KeReleaseSpinLock (&AllocatorLock, oldIRQL);
+ }
+ else {
+ KeReleaseSpinLock (&AllocatorLock, oldIRQL);
+ return NULL;
+ }
+ }
+
+ // Allocate chunk of memory to hold segment header and buffers
+ segment = ExAllocatePoolWithTag (
+ NonPagedPool,
+ segmentsize,
+ FWD_POOL_TAG);
+ if (segment!=NULL) {
+ segment->PS_SegmentList = list;
+ segment->PS_FreeHead = NULL;
+ segment->PS_BusyCount = 0;
+ KeQuerySystemTime ((PLARGE_INTEGER)&segment->PS_FreeStamp);
+ NdisAllocatePacketPool (
+ &status,
+ &segment->PS_PacketPool,
+ list->SL_BlockCount,
+ IPXMacHeaderSize
+ +FIELD_OFFSET (PACKET_TAG, PT_MacHeader));
+ if (status==NDIS_STATUS_SUCCESS) {
+ NdisAllocateBufferPool (
+ &status,
+ &segment->PS_BufferPool,
+ list->SL_BlockCount*2);
+ if (status==NDIS_STATUS_SUCCESS) {
+ PUCHAR bufferptr = segment->PS_Buffers;
+ PNDIS_PACKET packetDscr;
+ PNDIS_BUFFER bufferDscr;
+ PPACKET_TAG packetTag;
+ ULONG i;
+
+ for (i=0; i<list->SL_BlockCount; i++,
+ bufferptr+=list->SL_BlockSize) {
+ NdisAllocatePacket (
+ &status,
+ &packetDscr,
+ segment->PS_PacketPool);
+ ASSERT (status==NDIS_STATUS_SUCCESS);
+
+ packetTag = (PPACKET_TAG)packetDscr->ProtocolReserved;
+ packetTag->PT_Segment = segment;
+ packetTag->PT_Data = bufferptr;
+ packetTag->PT_InterfaceReference = NULL;
+
+ NdisAllocateBuffer (
+ &status,
+ &packetTag->PT_MacHdrBufDscr,
+ segment->PS_BufferPool,
+ packetTag->PT_MacHeader,
+ IPXMacHeaderSize);
+ ASSERT (status==NDIS_STATUS_SUCCESS);
+
+ NdisAllocateBuffer (
+ &status,
+ &bufferDscr,
+ segment->PS_BufferPool,
+ bufferptr,
+ list->SL_BlockSize);
+ ASSERT (status==NDIS_STATUS_SUCCESS);
+ NdisChainBufferAtFront (packetDscr, bufferDscr);
+
+ packetTag->PT_Next = segment->PS_FreeHead;
+ segment->PS_FreeHead = packetTag;
+ }
+ IpxFwdDbgPrint (DBG_PACKET_ALLOC, DBG_WARNING,
+ ("IpxFwd: Allocated packet segment %08lx for list %ld.\n",
+ segment, list->SL_BlockSize));
+ return segment;
+ }
+ else {
+ IpxFwdDbgPrint (DBG_PACKET_ALLOC, DBG_ERROR,
+ ("IpxFwd: Failed to allocate buffer pool"
+ " for new segment in list %ld.\n",
+ list->SL_BlockSize));
+ }
+ NdisFreePacketPool (segment->PS_PacketPool);
+ }
+ else {
+ IpxFwdDbgPrint (DBG_PACKET_ALLOC, DBG_ERROR,
+ ("IpxFwd: Failed to allocate packet pool"
+ " for new segment in list %ld.\n",
+ list->SL_BlockSize));
+ }
+ ExFreePool (segment);
+ }
+ else {
+ IpxFwdDbgPrint (DBG_PACKET_ALLOC, DBG_ERROR,
+ ("IpxFwd: Failed to allocate new segment for list %ld.\n",
+ list->SL_BlockSize));
+ }
+
+ return NULL;
+}
+
+
+/*++
+*******************************************************************
+ D e l e t e S e g m e n t
+
+Routine Description:
+ Frees packet segment
+Arguments:
+ segment - segment to free
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+DeleteSegment (
+ PPACKET_SEGMENT segment
+ ) {
+ PSEGMENT_LIST list = segment->PS_SegmentList;
+
+ ASSERT (segment->PS_BusyCount == 0);
+ // Free all NDIS packet and buffer descriptors first
+ while (segment->PS_FreeHead!=NULL) {
+ PNDIS_BUFFER bufferDscr;
+ PPACKET_TAG packetTag = segment->PS_FreeHead;
+ PNDIS_PACKET packetDscr = CONTAINING_RECORD (packetTag,
+ NDIS_PACKET, ProtocolReserved);
+
+ segment->PS_FreeHead = packetTag->PT_Next;
+
+ ASSERT (packetTag->PT_MacHdrBufDscr!=NULL);
+ NdisFreeBuffer (packetTag->PT_MacHdrBufDscr);
+
+ NdisUnchainBufferAtFront (packetDscr, &bufferDscr);
+ ASSERT (bufferDscr!=NULL);
+ NdisFreeBuffer (bufferDscr);
+
+ NdisFreePacket (packetDscr);
+ }
+ NdisFreeBufferPool (segment->PS_BufferPool);
+ NdisFreePacketPool (segment->PS_PacketPool);
+
+ // Decrement memory used if we have a quota
+ if (MaxRcvPktsPoolSize!=0) {
+ KIRQL oldIRQL;
+ ULONG segmentsize = list->SL_BlockCount*list->SL_BlockSize
+ +FIELD_OFFSET(PACKET_SEGMENT,PS_Buffers);
+ KeAcquireSpinLock (&AllocatorLock, &oldIRQL);
+ RcvPktsPoolSize -= segmentsize;
+ KeReleaseSpinLock (&AllocatorLock, oldIRQL);
+ }
+ ExFreePool (segment);
+ IpxFwdDbgPrint (DBG_PACKET_ALLOC, DBG_WARNING,
+ ("IpxFwd: Deleting segment %08lx in list %ld.\n",
+ segment, list->SL_BlockSize));
+}
+
+
+/*++
+*******************************************************************
+ R e g i s t e r P a c k e t C o n s u m e r
+
+Routine Description:
+ Registers a consumer (bound interface) of packets of the
+ given size
+Arguments:
+ pktsize - maximum size of packets needed
+ listId - buffer to return packet list id where packets
+ of required size are located
+Return Value:
+ STATUS_SUCCESS - registration succeded
+ STATUS_INSUFFICIENT_RESOURCES - not enogh resources to register
+
+*******************************************************************
+--*/
+NTSTATUS
+RegisterPacketConsumer (
+ IN ULONG pktsize,
+ OUT INT *listID
+ ) {
+ NTSTATUS status=STATUS_SUCCESS;
+ KIRQL oldIRQL;
+ PSEGMENT_LIST list;
+ INT i;
+ LONG addRefCount = 1;
+
+ KeAcquireSpinLock (&AllocatorLock, &oldIRQL);
+ ASSERT (pktsize<=SegmentMap[FRAME_SIZE_VARIATIONS-1]
+ [FRAME_SIZE_VARIATIONS-1]->SL_BlockSize);
+
+ for (i=0; i<FRAME_SIZE_VARIATIONS; i++) {
+ list = SegmentMap[i][i];
+ if (pktsize<=list->SL_BlockSize) {
+ list->SL_RefCount += 1;
+ *listID = i;
+ break;
+ }
+ }
+ KeReleaseSpinLock (&AllocatorLock, oldIRQL);
+ IpxFwdDbgPrint (DBG_PACKET_ALLOC, DBG_WARNING,
+ ("IpxFwd: Registered packet consumer, pktsz: %ld, list: %ld.\n",
+ pktsize, list->SL_BlockSize));
+ return status;
+}
+
+/*++
+*******************************************************************
+ D e r e g i s t e r P a c k e t C o n s u m e r
+
+Routine Description:
+ Deregisters a consumer (bound interface) of packets of the
+ given size
+Arguments:
+ listId - packet list id used by the consumer
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+DeregisterPacketConsumer (
+ IN INT listID
+ ) {
+ KIRQL oldIRQL;
+ PSEGMENT_LIST list;
+
+ ASSERT ((listID>=0) && (listID<FRAME_SIZE_VARIATIONS));
+
+ KeAcquireSpinLock (&AllocatorLock, &oldIRQL);
+ list = SegmentMap[listID][listID];
+
+ ASSERT (list->SL_RefCount>0);
+
+ list->SL_RefCount -= 1;
+
+ KeReleaseSpinLock (&AllocatorLock, oldIRQL);
+ IpxFwdDbgPrint (DBG_PACKET_ALLOC, DBG_WARNING,
+ ("IpxFwd: Deregistered packet consumer, list: %ld.\n",
+ list->SL_BlockSize));
+
+ }
+
+/*++
+*******************************************************************
+ I n i t i a l i z e S e g m e n t L i s t
+
+Routine Description:
+ Initializes list of packet segments
+Arguments:
+ list - list to initalize
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+InitializeSegmentList(
+ PSEGMENT_LIST list
+ ) {
+ InitializeListHead (&list->SL_Head);
+ list->SL_FreeCount = 0;
+ // Make sure we don't have any leftover larger than
+ // the buffer size (kernel memory allocator
+ // allocates full pages)
+ list->SL_BlockCount =
+ (ROUND_TO_PAGES (
+ list->SL_BlockSize*RcvPktsPerSegment
+ +FIELD_OFFSET(PACKET_SEGMENT,PS_Buffers))
+ -FIELD_OFFSET(PACKET_SEGMENT,PS_Buffers))
+ /list->SL_BlockSize;
+ list->SL_LowCount = list->SL_BlockCount/2;
+ list->SL_RefCount = 0;
+ list->SL_AllocatorPending = FALSE;
+ list->SL_TimerDpcPending = FALSE;
+ KeInitializeSpinLock (&list->SL_Lock);
+ KeInitializeTimer (&list->SL_Timer);
+ KeInitializeDpc (&list->SL_TimerDpc, SegmentTimeoutDpc, list);
+ ExInitializeWorkItem (&list->SL_Allocator, AllocationWorker, list);
+}
+
+/*++
+*******************************************************************
+ D e l e t e S e g m e n t L i s t
+
+Routine Description:
+ Deletes list of packet segments
+Arguments:
+ list - list to delete
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+DeleteSegmentList (
+ PSEGMENT_LIST list
+ ) {
+ KeCancelTimer (&list->SL_Timer);
+ while (!IsListEmpty (&list->SL_Head)) {
+ PPACKET_SEGMENT segment;
+ segment = CONTAINING_RECORD (list->SL_Head.Blink,
+ PACKET_SEGMENT, PS_Link);
+
+ RemoveEntryList (&segment->PS_Link);
+ DeleteSegment (segment);
+ }
+}
+
+
+/*++
+*******************************************************************
+ S e g m e n t T i m e o u t D p c
+
+Routine Description:
+ Timer DPC that launches allocator worker to get rid of unused
+ segments
+Arguments:
+ Context - segment list to check for unused segments
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+SegmentTimeoutDpc (
+ PKDPC dpc,
+ PVOID Context,
+ PVOID SystemArgument1,
+ PVOID SystemArgument2
+ ) {
+#define list ((PSEGMENT_LIST)Context)
+ KIRQL oldIRQL;
+ IpxFwdDbgPrint (DBG_PACKET_ALLOC, DBG_INFORMATION,
+ ("IpxFwd: Segment timed out in list: %ld.\n",
+ list->SL_BlockSize));
+ KeAcquireSpinLock (&list->SL_Lock, &oldIRQL);
+ list->SL_TimerDpcPending = FALSE;
+ if (!list->SL_AllocatorPending
+ && (list->SL_FreeCount>=list->SL_BlockCount)
+ && EnterForwarder ()) {
+ list->SL_AllocatorPending = TRUE;
+ KeReleaseSpinLock (&list->SL_Lock, oldIRQL);
+ ExQueueWorkItem (&list->SL_Allocator, DelayedWorkQueue);
+ }
+ else {
+ KeReleaseSpinLock (&list->SL_Lock, oldIRQL);
+ }
+ LeaveForwarder ();
+#undef list
+}
+
+
+/*++
+*******************************************************************
+ A l l o c a t i o n W o r k e r
+
+Routine Description:
+ Adds new segment or releases unused segments from the list
+ depending on the free packet count and time that segments
+ are not used
+Arguments:
+ Context - packet list to process
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+AllocationWorker (
+ PVOID Context
+ ) {
+#define list ((PSEGMENT_LIST)Context)
+ KIRQL oldIRQL;
+ PPACKET_SEGMENT segment = NULL;
+ LONGLONG curTime;
+
+ IpxFwdDbgPrint (DBG_PACKET_ALLOC, DBG_INFORMATION,
+ ("IpxFwd: Allocating/scavenging segment(s) in list: %ld.\n",
+ list->SL_BlockSize));
+ KeQuerySystemTime ((PLARGE_INTEGER)&curTime);
+ KeAcquireSpinLock (&list->SL_Lock, &oldIRQL);
+ list->SL_AllocatorPending = FALSE;
+ if (list->SL_FreeCount<list->SL_BlockCount) {
+ KeReleaseSpinLock (&list->SL_Lock, oldIRQL);
+ // First allocate a segment
+ segment = CreateSegment (list);
+ if (segment!=NULL) {
+ KeAcquireSpinLock (&list->SL_Lock, &oldIRQL);
+ InsertTailList (&list->SL_Head, &segment->PS_Link);
+ list->SL_FreeCount += list->SL_BlockCount;
+ if (!list->SL_TimerDpcPending
+ && EnterForwarder ()) {
+ list->SL_TimerDpcPending = TRUE;
+ KeReleaseSpinLock (&list->SL_Lock, oldIRQL);
+ KeSetTimer (&list->SL_Timer, *((PLARGE_INTEGER)&SegmentTimeout), &list->SL_TimerDpc);
+ }
+ else {
+ KeReleaseSpinLock (&list->SL_Lock, oldIRQL);
+ }
+ }
+ }
+ else {
+ // Make sure that there is either more than segment in the list
+ // or there is one and no registered users
+ if (!IsListEmpty (&list->SL_Head)) {
+ segment = CONTAINING_RECORD (list->SL_Head.Blink,
+ PACKET_SEGMENT, PS_Link);
+ // Check for all segments with no used blocks
+ // except for the last one (delete event the last
+ // one if there are no clients)
+ while ((segment->PS_BusyCount==0)
+ && ((list->SL_Head.Flink!=&segment->PS_Link)
+ || (list->SL_RefCount<=0))) {
+ LONGLONG timeDiff;
+ // Check if it has not been used for long enough
+ timeDiff = SegmentTimeout - (segment->PS_FreeStamp-curTime);
+ if (timeDiff>=0) {
+ // Delete the segment
+ RemoveEntryList (&segment->PS_Link);
+ list->SL_FreeCount -= list->SL_BlockCount;
+ KeReleaseSpinLock (&list->SL_Lock, oldIRQL);
+ DeleteSegment (segment);
+ KeAcquireSpinLock (&list->SL_Lock, &oldIRQL);
+ if (!IsListEmpty (&list->SL_Head)) {
+ segment = CONTAINING_RECORD (list->SL_Head.Blink,
+ PACKET_SEGMENT, PS_Link);
+ continue;
+ }
+ }
+ else { // Reschedule the timer otherwise
+ if (!list->SL_TimerDpcPending
+ && EnterForwarder ()) {
+ list->SL_TimerDpcPending = TRUE;
+ KeReleaseSpinLock (&list->SL_Lock, oldIRQL);
+ KeSetTimer (&list->SL_Timer,
+ *((PLARGE_INTEGER)&timeDiff),
+ &list->SL_TimerDpc);
+ goto ExitAllocator; // Spinlock is already released
+ }
+ }
+ break;
+ } // while
+ } // if (IsListEmpty)
+ KeReleaseSpinLock (&list->SL_Lock, oldIRQL);
+ }
+ExitAllocator:
+ LeaveForwarder ();
+#undef list
+}
+
+
diff --git a/private/ntos/tdi/isn/fwd/packets.h b/private/ntos/tdi/isn/fwd/packets.h
new file mode 100644
index 000000000..98de68377
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/packets.h
@@ -0,0 +1,464 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ ntos\tdi\isn\fwd\packets.h
+
+Abstract:
+ IPX Forwarder Driver packet allocator
+
+
+Author:
+
+ Vadim Eydelman
+
+Revision History:
+
+--*/
+
+#ifndef _IPXFWD_PACKETS_
+#define _IPXFWD_PACKETS_
+
+// Forward structure prototypes
+struct _SEGMENT_LIST;
+typedef struct _SEGMENT_LIST SEGMENT_LIST, *PSEGMENT_LIST;
+struct _PACKET_SEGMENT;
+typedef struct _PACKET_SEGMENT PACKET_SEGMENT, *PPACKET_SEGMENT;
+struct _PACKET_TAG;
+typedef struct _PACKET_TAG PACKET_TAG, *PPACKET_TAG;
+
+// Forwarder data associated with each packet it allocates
+struct _PACKET_TAG {
+ union {
+ UCHAR PT_Identifier; // this should be IDENTIFIER_RIP
+ PPACKET_TAG PT_Next; // link in packet segment
+ };
+ union {
+ PVOID SEND_RESERVED[SEND_RESERVED_COMMON_SIZE]; // needed by ipx
+ // for padding on ethernet
+ PINTERFACE_CB PT_SourceIf; // Source interface reference needed
+ // for spoofing keep-alives and
+ // queuing connection requests
+ };
+ PPACKET_SEGMENT PT_Segment; // segment where it belongs
+ LONGLONG PT_PerfCounter;
+ ULONG PT_Flags;
+#define PT_NB_DESTROY 0x1 // NB packet to be not requeued
+#define PT_SOURCE_IF 0x2 // Spoofing packet with src if reference
+ PUCHAR PT_Data; // Data buffer
+ PNDIS_BUFFER PT_MacHdrBufDscr; // buffer descriptor for
+ // mac header buffer required
+ // by IPX
+ PINTERFACE_CB PT_InterfaceReference; // points to the interface CB where
+ // it is queued
+ LIST_ENTRY PT_QueueLink; // links this packet in send queue
+ IPX_LOCAL_TARGET PT_Target; // destination target for ipx
+ // stack
+ UCHAR PT_MacHeader[1];// Mac header buffer reserved for IPX
+};
+
+// Segment of preallocated packets complete with buffers
+struct _PACKET_SEGMENT {
+ LIST_ENTRY PS_Link; // Link in segment list
+ PSEGMENT_LIST PS_SegmentList; // Segment list we belong to
+ PPACKET_TAG PS_FreeHead; // List of free packets in
+ // this segment
+ ULONG PS_BusyCount; // Count of packets allocated
+ // from this segment
+ NDIS_HANDLE PS_PacketPool; // Pool of NDIS packet
+ // descriptors used by the
+ // packets in this segment
+ NDIS_HANDLE PS_BufferPool; // Pool of NDIS buffer
+ // descriptors used by the
+ // packets in this segment
+ LONGLONG PS_FreeStamp; // Time when last packet was freed
+ union {
+ UCHAR PS_Buffers[1]; // Memory used by buffers
+ LONGLONG PS_BuffersAlign;
+ };
+};
+
+
+// List of segment with preallocated packets
+struct _SEGMENT_LIST {
+ const ULONG SL_BlockSize; // Size of packet's buffer
+ LIST_ENTRY SL_Head; // Head of the segment list
+ ULONG SL_FreeCount; // Total number of free packets
+ // in all segment in the list
+ ULONG SL_BlockCount; // Number of packets per segment
+ ULONG SL_LowCount; // Free count at which we
+ // will preallocate new segment
+ LONG SL_RefCount; // Number of consumers that are
+ // using packets in this list
+ BOOLEAN SL_TimerDpcPending;
+ BOOLEAN SL_AllocatorPending;
+ WORK_QUEUE_ITEM SL_Allocator; // Allocation work item
+ KTIMER SL_Timer; // Timer to free unused segments
+ KDPC SL_TimerDpc; // DPC of the timer of unused segments
+ KSPIN_LOCK SL_Lock; // Access control
+};
+
+
+// The number of rcv packets per segment (config parameter)
+#define MIN_RCV_PKTS_PER_SEGMENT 8
+#define DEF_RCV_PKTS_PER_SEGMENT 64
+#define MAX_RCV_PKTS_PER_SEGMENT 256
+extern ULONG RcvPktsPerSegment;
+
+// Maximum size of memory that can be used to allocate packets (config
+// param). 0 means no limit
+extern ULONG MaxRcvPktsPoolSize;
+
+// There are currently three known frame sizes: ethernet-1500,
+// token ring 4k - 4500, token ring 16k - 17986
+#define FRAME_SIZE_VARIATIONS 3
+
+// List of packet segments for Ethernet packets
+extern SEGMENT_LIST ListEther;
+// List of packet segments for Token Ring 4K packets
+extern SEGMENT_LIST ListTR4;
+// List of packet segments for Token Ring 16K packets
+extern SEGMENT_LIST ListTR16;
+// Mapping from src and destination packet size requirments
+// to the appropriate segment list
+extern PSEGMENT_LIST SegmentMap[FRAME_SIZE_VARIATIONS][FRAME_SIZE_VARIATIONS];
+// Timeout for unused segment
+extern const LONGLONG SegmentTimeout;
+extern KSPIN_LOCK AllocatorLock;
+
+/*++
+*******************************************************************
+ I n i t i a l i z e P a c k e t A l l o c a t o r
+
+Routine Description:
+ Initializes packet allocator
+Arguments:
+ None
+Return Value:
+ None
+
+*******************************************************************
+--*/
+// VOID
+// InitializePacketAllocator (
+// void
+// );
+#define InitializePacketAllocator() { \
+ KeInitializeSpinLock(&AllocatorLock); \
+ InitializeSegmentList(&ListEther); \
+ InitializeSegmentList(&ListTR4); \
+ InitializeSegmentList(&ListTR16); \
+}
+
+/*++
+*******************************************************************
+ D e l e t e P a c k e t A l l o c a t o r
+
+Routine Description:
+ Disposes of all resources in packet allocator
+Arguments:
+ None
+Return Value:
+ None
+
+*******************************************************************
+--*/
+// VOID
+// DeletePacketAllocator (
+// void
+// );
+#define DeletePacketAllocator() { \
+ DeleteSegmentList(&ListEther); \
+ DeleteSegmentList(&ListTR4); \
+ DeleteSegmentList(&ListTR16); \
+}
+
+
+/*++
+*******************************************************************
+ A l l o c a t e P a c k e t
+
+Routine Description:
+ Allocate packet for source - destination combination
+Arguments:
+ srcListId - identifies max frame size for source interface
+ dstListId - identifies max frame size for destination
+ packet - receives pointer to allocated packet or NULL if allocation
+ fails
+Return Value:
+ None
+
+*******************************************************************
+--*/
+// VOID
+// AllocatePacket (
+// IN INT srcListId,
+// IN INT dstListId,
+// OUT PPACKET_TAG packet
+// );
+#define AllocatePacket(srcListId,dstListId,packet) { \
+ PSEGMENT_LIST list; \
+ ASSERT ((srcListId>=0) && (srcListId<FRAME_SIZE_VARIATIONS)); \
+ ASSERT ((dstListId>=0) && (dstListId<FRAME_SIZE_VARIATIONS)); \
+ list = SegmentMap[srcListId][dstListId]; \
+ AllocatePacketFromList(list,packet); \
+}
+
+/*++
+*******************************************************************
+ D u p l i c a t e P a c k e t
+
+Routine Description:
+ Duplicates packet
+Arguments:
+ src - source packet
+ dst - receives pointer to duplicated packet or NUUL if operation
+ failed
+Return Value:
+ None
+
+*******************************************************************
+--*/
+// VOID
+// DuplicatePacket (
+// IN PPACKET_TAG src
+// OUT PPACKET_TAG dst
+// );
+#define DuplicatePacket(src,dst) { \
+ PSEGMENT_LIST list; \
+ list = src->PT_Segment->PS_SegmentList; \
+ AllocatePacketFromList(list,dst); \
+}
+
+
+/*++
+*******************************************************************
+ A l l o c a t e P a c k e t F r o m L i s t
+
+Routine Description:
+ Allocate packet from specified packet segment list
+Arguments:
+ list - list from which to allocate
+ packet - receives pointer to allocated packet or NULL if allocation
+ fails
+Return Value:
+ None
+
+*******************************************************************
+--*/
+// VOID
+// AllocatePacketFromList (
+// IN PSEGMENT_LIST list
+// OUT PPACKET_TAG packet
+// );
+#define AllocatePacketFromList(list,packet) { \
+ PPACKET_SEGMENT segment; \
+ KIRQL oldIRQL; \
+ KeAcquireSpinLock (&list->SL_Lock, &oldIRQL); \
+ do { \
+ if (list->SL_FreeCount>0) { \
+ segment = CONTAINING_RECORD (list->SL_Head.Flink, \
+ PACKET_SEGMENT, PS_Link); \
+ while (segment->PS_FreeHead==NULL) { \
+ segment = CONTAINING_RECORD (segment->PS_Link.Flink, \
+ PACKET_SEGMENT, PS_Link); \
+ ASSERT (&segment->PS_Link!=&list->SL_Head); \
+ } \
+ list->SL_FreeCount -= 1; \
+ if ((list->SL_FreeCount<list->SL_LowCount) \
+ && !list->SL_AllocatorPending \
+ && EnterForwarder ()) { \
+ list->SL_AllocatorPending = TRUE; \
+ ExQueueWorkItem (&list->SL_Allocator, DelayedWorkQueue);\
+ } \
+ } \
+ else { \
+ segment = CreateSegment (list); \
+ if (segment!=NULL) { \
+ InsertTailList (&list->SL_Head, &segment->PS_Link); \
+ segment->PS_SegmentList = list; \
+ list->SL_FreeCount = list->SL_BlockCount-1; \
+ } \
+ else { \
+ packet = NULL; \
+ break; \
+ } \
+ } \
+ packet = segment->PS_FreeHead; \
+ segment->PS_FreeHead = packet->PT_Next; \
+ segment->PS_BusyCount += 1; \
+ packet->PT_Identifier = IDENTIFIER_RIP; \
+ packet->PT_Flags = 0; \
+ } \
+ while (FALSE); \
+ KeReleaseSpinLock (&list->SL_Lock, oldIRQL); \
+}
+
+/*++
+*******************************************************************
+ F r e e P a c k e t
+
+Routine Description:
+ Free allocated packet
+Arguments:
+ packet - packet to free
+Return Value:
+ None
+
+*******************************************************************
+--*/
+// VOID
+// FreePacket (
+// IN PPACKET_TAG packet
+// );
+#define FreePacket(packet) { \
+ PPACKET_SEGMENT segment=packet->PT_Segment; \
+ PSEGMENT_LIST list; \
+ KIRQL oldIRQL; \
+ list = segment->PS_SegmentList; \
+ KeAcquireSpinLock (&list->SL_Lock, &oldIRQL); \
+ packet->PT_Next = segment->PS_FreeHead; \
+ segment->PS_FreeHead = packet; \
+ list->SL_FreeCount += 1; \
+ segment->PS_BusyCount -= 1; \
+ if (segment->PS_BusyCount==0) { \
+ if (list->SL_TimerDpcPending) { \
+ KeQuerySystemTime ((PLARGE_INTEGER)&segment->PS_FreeStamp); \
+ KeReleaseSpinLock (&list->SL_Lock, oldIRQL);\
+ } \
+ else if (EnterForwarder ()) { \
+ list->SL_TimerDpcPending = TRUE; \
+ KeReleaseSpinLock (&list->SL_Lock, oldIRQL);\
+ KeSetTimer (&list->SL_Timer, \
+ *((PLARGE_INTEGER)&SegmentTimeout), \
+ &list->SL_TimerDpc); \
+ } \
+ else { \
+ KeReleaseSpinLock (&list->SL_Lock, oldIRQL);\
+ } \
+ } \
+ else { \
+ KeReleaseSpinLock (&list->SL_Lock, oldIRQL); \
+ } \
+}
+
+
+/*++
+*******************************************************************
+ C r e a t e S e g m e n t
+
+Routine Description:
+ Allocates and initializes packet segment
+Arguments:
+ list - segment list to which new segment will be added
+Return Value:
+ Pointer to allocated segment, NULL if fails
+
+*******************************************************************
+--*/
+PPACKET_SEGMENT
+CreateSegment (
+ PSEGMENT_LIST list
+ );
+
+/*++
+*******************************************************************
+ D e l e t e S e g m e n t
+
+Routine Description:
+ Frees packet segment
+Arguments:
+ segment - segment to free
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+DeleteSegment (
+ PPACKET_SEGMENT segment
+ );
+
+/*++
+*******************************************************************
+ R e g i s t e r P a c k e t C o n s u m e r
+
+Routine Description:
+ Registers a consumer (bound interface) of packets of the
+ given size
+Arguments:
+ pktsize - maximum size of packets needed
+ listId - buffer to return packet list id where packets
+ of required size are located
+Return Value:
+ STATUS_SUCCESS - registration succeded
+ STATUS_INSUFFICIENT_RESOURCES - not enogh resources to register
+
+*******************************************************************
+--*/
+NTSTATUS
+RegisterPacketConsumer (
+ IN ULONG pktsize,
+ OUT INT *listID
+ );
+
+/*++
+*******************************************************************
+ D e r e g i s t e r P a c k e t C o n s u m e r
+
+Routine Description:
+ Deregisters a consumer (bound interface) of packets of the
+ given size
+Arguments:
+ listId - packet list id used by the consumer
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+DeregisterPacketConsumer (
+ IN INT listID
+ );
+
+/*++
+*******************************************************************
+ I n i t i a l i z e S e g m e n t L i s t
+
+Routine Description:
+ Initializes list of packet segments
+Arguments:
+ list - list to initalize
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+InitializeSegmentList(
+ PSEGMENT_LIST list
+ );
+
+
+/*++
+*******************************************************************
+ D e l e t e S e g m e n t L i s t
+
+Routine Description:
+ Deletes list of packet segments
+Arguments:
+ list - list to delete
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+DeleteSegmentList (
+ PSEGMENT_LIST list
+ );
+
+#endif
+
diff --git a/private/ntos/tdi/isn/fwd/precomp.h b/private/ntos/tdi/isn/fwd/precomp.h
new file mode 100644
index 000000000..bc471bd40
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/precomp.h
@@ -0,0 +1,61 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ ntos\tdi\isn\fwd\precomp.h
+
+Abstract:
+ IPX Forwarder driver precompiled header file
+
+
+Author:
+
+ Vadim Eydelman
+
+Revision History:
+
+--*/
+
+#define ISN_NT 1
+#define NT 1
+
+#if DBG
+#define DEBUG 1
+#endif
+
+// System includes
+#include <ntos.h>
+#include <tdikrnl.h>
+#include <ndis.h>
+#include <zwapi.h>
+#include <limits.h>
+
+// IPX shared includes
+#include "bind.h"
+#include "ipxfwd.h"
+#include "ipxfltif.h"
+
+// Constants and macros
+#include "fwddefs.h"
+#include "rwlock.h"
+
+// Internal module prototypes
+#include "tables.h"
+#include "registry.h"
+#include "packets.h"
+#include "ipxbind.h"
+#include "rcvind.h"
+#include "send.h"
+#include "netbios.h"
+#include "lineind.h"
+#include "ddreqs.h"
+#include "driver.h"
+#include "filterif.h"
+#include "debug.h"
+
+#pragma hdrstop
+
+
+
diff --git a/private/ntos/tdi/isn/fwd/rcvind.c b/private/ntos/tdi/isn/fwd/rcvind.c
new file mode 100644
index 000000000..7c4bc2d39
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/rcvind.c
@@ -0,0 +1,825 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ ntos\tdi\isn\fwd\rcvind.c
+
+Abstract:
+ Receive indication processing
+
+Author:
+
+ Vadim Eydelman
+
+Revision History:
+
+--*/
+#include "precomp.h"
+
+#if DBG
+VOID
+DbgFilterReceivedPacket(PUCHAR hdrp);
+#endif
+
+// Doesn't allow accepting packets (for routing) from dial-in clients
+BOOLEAN ThisMachineOnly = FALSE;
+
+/*++
+*******************************************************************
+ F w R e c e i v e
+
+Routine Description:
+ Called by the IPX stack to indicate that the IPX packet was
+ received by the NIC dirver. Only external destined packets are
+ indicated by this routine (with the exception of Netbios boradcasts
+ that indicated both for internal and external handlers)
+Arguments:
+ MacBindingHandle - handle of NIC driver
+ MaxReceiveContext - NIC driver context
+ RemoteAddress - sender's address
+ MacOptions -
+ LookaheadBuffer - packet lookahead buffer that contains complete
+ IPX header
+ LookaheadBufferSize - its size (at least 30 bytes)
+ LookaheadBufferOffset - offset of lookahead buffer in the physical
+ packet
+Return Value:
+ TRUE if we take the MDL chain to return later with NdisReturnPacket
+
+*******************************************************************
+--*/
+BOOLEAN
+IpxFwdReceive (
+ NDIS_HANDLE MacBindingHandle,
+ NDIS_HANDLE MacReceiveContext,
+ ULONG Context,
+ PIPX_LOCAL_TARGET RemoteAddress,
+ ULONG MacOptions,
+ PUCHAR LookaheadBuffer,
+ UINT LookaheadBufferSize,
+ UINT LookaheadBufferOffset,
+ UINT PacketSize,
+ PMDL pMdl
+ ) {
+ PINTERFACE_CB srcIf, dstIf;
+ PPACKET_TAG pktTag;
+ PNDIS_PACKET pktDscr;
+ NDIS_STATUS status;
+ UINT BytesTransferred;
+ LARGE_INTEGER PerfCounter;
+
+ // check that our configuration process has terminated OK
+ if (!EnterForwarder ()) {
+ return FALSE;
+ }
+
+ if (!MeasuringPerformance) {
+ PerfCounter.QuadPart = 0;
+ }
+ else {
+#if DBG
+ static LONGLONG LastCall = 0;
+ KIRQL oldIRQL;
+#endif
+ PerfCounter = KeQueryPerformanceCounter (NULL);
+#if DBG
+ KeAcquireSpinLock (&PerfCounterLock, &oldIRQL);
+ ASSERT (PerfCounter.QuadPart-LastCall<ActivityTreshhold);
+ LastCall = PerfCounter.QuadPart;
+ KeReleaseSpinLock (&PerfCounterLock, oldIRQL);
+#endif
+ }
+
+ IpxFwdDbgPrint (DBG_RECV, DBG_INFORMATION,
+ ("IpxFwd: FwdReceive on %0lx,"
+ " dst-%08lx:%02x%02x%02x%02x%02x%02x, type-%02x.\n",
+ Context, GETULONG (LookaheadBuffer+IPXH_DESTNET),
+ LookaheadBuffer[IPXH_DESTNODE], LookaheadBuffer[IPXH_DESTNODE+1],
+ LookaheadBuffer[IPXH_DESTNODE+2], LookaheadBuffer[IPXH_DESTNODE+3],
+ LookaheadBuffer[IPXH_DESTNODE+4], LookaheadBuffer[IPXH_DESTNODE+5],
+ LookaheadBuffer[IPXH_PKTTYPE]));
+
+#if DBG
+ DbgFilterReceivedPacket (LookaheadBuffer);
+#endif
+ srcIf = InterfaceContextToReference ((PVOID)Context, RemoteAddress->NicId);
+ // Check if interface is valid
+ if (srcIf!=NULL) {
+ USHORT pktlen;
+ ULONG dstNet;
+ KIRQL oldIRQL;
+
+ dstNet = GETULONG (LookaheadBuffer + IPXH_DESTNET);
+ pktlen = GETUSHORT(LookaheadBuffer + IPXH_LENGTH);
+
+ // check if we got the whole IPX header in the lookahead buffer
+ if ((LookaheadBufferSize >= IPXH_HDRSIZE)
+ && (*(LookaheadBuffer + IPXH_XPORTCTL) < 16)
+ && (pktlen<=PacketSize)) {
+ // Lock interface CB to ensure coherency of information in it
+ KeAcquireSpinLock(&srcIf->ICB_Lock, &oldIRQL);
+ // Check if shoud accept packets on this interface
+ if (IS_IF_ENABLED(srcIf)
+ && (srcIf->ICB_Stats.OperationalState!=FWD_OPER_STATE_DOWN)
+ && (!ThisMachineOnly
+ || (srcIf->ICB_InterfaceType
+ !=FWD_IF_REMOTE_WORKSTATION))) {
+ // Check for looped back packets
+ if (IPX_NODE_CMP (RemoteAddress->MacAddress,
+ srcIf->ICB_LocalNode)!=0) {
+
+ // Separate processing of netbios broadcast packets (20)
+ if (*(LookaheadBuffer + IPXH_PKTTYPE) != IPX_NETBIOS_TYPE) {
+ PFWD_ROUTE dstRoute;
+ INT srcListId, dstListId;
+ // Temp IPX bug fix, they shou;d ensure that
+ // we only get packets that can be routed
+ if ((dstNet==srcIf->ICB_Network)
+ || (dstNet==InternalInterface->ICB_Network)) {
+ InterlockedIncrement (&srcIf->ICB_Stats.InDiscards);
+ KeReleaseSpinLock(&srcIf->ICB_Lock, oldIRQL);
+ ReleaseInterfaceReference (srcIf);
+ LeaveForwarder ();
+ return FALSE;
+ }
+// ASSERT (dstNet!=srcIf->ICB_Network);
+// ASSERT ((InternalInterface==NULL)
+// || (InternalInterface->ICB_Network==0)
+// || (dstNet!=InternalInterface->ICB_Network));
+ // Check if needed route is in cash
+ if ((srcIf->ICB_CashedRoute!=NULL)
+ && (dstNet==srcIf->ICB_CashedRoute->FR_Network)
+ // If route was changed or deleted, this will fail
+ && (srcIf->ICB_CashedRoute->FR_InterfaceReference
+ ==srcIf->ICB_CashedInterface)) {
+ dstIf = srcIf->ICB_CashedInterface;
+ dstRoute = srcIf->ICB_CashedRoute;
+ AcquireInterfaceReference (dstIf);
+ AcquireRouteReference (dstRoute);
+ IpxFwdDbgPrint (DBG_RECV, DBG_INFORMATION,
+ ("IpxFwd: Destination in cash.\n"));
+ }
+ else { // Find and cash the route
+ dstIf = FindDestination (dstNet,
+ LookaheadBuffer+IPXH_DESTNODE,
+ &dstRoute
+ );
+
+ if (dstIf!=NULL) { // If route is found
+ IpxFwdDbgPrint (DBG_RECV, DBG_INFORMATION,
+ ("IpxFwd: Found destination %0lx.\n", dstIf));
+ // Don't cash global wan clients and
+ // routes to the same net
+ if ((dstNet!=GlobalNetwork)
+ && (dstIf!=srcIf)) {
+ if (srcIf->ICB_CashedInterface!=NULL)
+ ReleaseInterfaceReference (srcIf->ICB_CashedInterface);
+ if (srcIf->ICB_CashedRoute!=NULL)
+ ReleaseRouteReference (srcIf->ICB_CashedRoute);
+ srcIf->ICB_CashedInterface = dstIf;
+ srcIf->ICB_CashedRoute = dstRoute;
+ AcquireInterfaceReference (dstIf);
+ AcquireRouteReference (dstRoute);
+ }
+ }
+ else { // No route
+ InterlockedIncrement (&srcIf->ICB_Stats.InNoRoutes);
+ KeReleaseSpinLock(&srcIf->ICB_Lock, oldIRQL);
+ IpxFwdDbgPrint (DBG_RECV, DBG_WARNING,
+ ("IpxFwd: No route for packet on interface %ld (icb:%0lx),"
+ " dst-%08lx:%02x%02x%02x%02x%02x%02x, type-%02x.\n",
+ srcIf->ICB_Index, srcIf, dstNet,
+ LookaheadBuffer[IPXH_DESTNODE], LookaheadBuffer[IPXH_DESTNODE+1],
+ LookaheadBuffer[IPXH_DESTNODE+2], LookaheadBuffer[IPXH_DESTNODE+3],
+ LookaheadBuffer[IPXH_DESTNODE+4], LookaheadBuffer[IPXH_DESTNODE+5],
+ LookaheadBuffer[IPXH_PKTTYPE]));
+ ReleaseInterfaceReference (srcIf);
+ LeaveForwarder ();
+ return FALSE;
+ }
+ }
+ srcListId = srcIf->ICB_PacketListId;
+ KeReleaseSpinLock(&srcIf->ICB_Lock, oldIRQL);
+
+ // Check if destination if can take the packet
+ if (IS_IF_ENABLED (dstIf)
+ // If interface is UP check packet againts actual size limit
+ && (((dstIf->ICB_Stats.OperationalState==FWD_OPER_STATE_UP)
+ && (PacketSize<=dstIf->ICB_Stats.MaxPacketSize))
+ // if sleeping (WAN), check we can allocate it from WAN list
+ || ((dstIf->ICB_Stats.OperationalState==FWD_OPER_STATE_SLEEPING)
+ && (PacketSize<=WAN_PACKET_SIZE))
+ // otherwise, interface is down and we can't take the packet
+ ) ){
+ FILTER_ACTION action;
+ action = FltFilter (LookaheadBuffer, LookaheadBufferSize,
+ srcIf->ICB_FilterInContext,
+ dstIf->ICB_FilterOutContext);
+ if (action==FILTER_PERMIT) {
+ InterlockedIncrement (&srcIf->ICB_Stats.InDelivers);
+ dstListId = dstIf->ICB_PacketListId;
+ // try to get a packet from the rcv pkt pool
+ AllocatePacket (srcListId, dstListId, pktTag);
+ if (pktTag!=NULL) {
+ // Set destination mac in local target if
+ // possible
+ KeAcquireSpinLock (&dstIf->ICB_Lock, &oldIRQL);
+ if (dstIf->ICB_InterfaceType==FWD_IF_PERMANENT) {
+ // Permanent interface: send to the next
+ // hop router if net is not directly connected
+ // or to the dest node otherwise
+ if (dstNet!=dstIf->ICB_Network) {
+ IPX_NODE_CPY (pktTag->PT_Target.MacAddress,
+ dstRoute->FR_NextHopAddress);
+ }
+ else {
+ IPX_NODE_CPY (pktTag->PT_Target.MacAddress,
+ LookaheadBuffer+IPXH_DESTNODE);
+ }
+ }
+ else { // Demand dial interface: assumed to be
+ // point to point connection -> send to
+ // the other party if connection has already
+ // been made, otherwise wait till connected
+ if (dstIf->ICB_Stats.OperationalState
+ == FWD_OPER_STATE_UP) {
+ IPX_NODE_CPY (pktTag->PT_Target.MacAddress,
+ dstIf->ICB_RemoteNode);
+ } // Copy source mac address and nic id in case
+ // we need to spoof this packet
+ else if ((*(LookaheadBuffer+IPXH_PKTTYPE)==0)
+ && (pktlen==IPXH_HDRSIZE+2)
+ && ((LookaheadBufferSize<IPXH_HDRSIZE+2)
+ ||(*(LookaheadBuffer+IPXH_HDRSIZE+1)=='?'))) {
+ IPX_NODE_CPY (pktTag->PT_Target.MacAddress,
+ RemoteAddress->MacAddress);
+ pktTag->PT_SourceIf = srcIf;
+ AcquireInterfaceReference (srcIf);
+ pktTag->PT_Flags |= PT_SOURCE_IF;
+ }
+
+ }
+ KeReleaseSpinLock (&dstIf->ICB_Lock, oldIRQL);
+ ReleaseRouteReference (dstRoute);
+ goto GetPacket;
+ }
+ else { // Allocation failure
+ InterlockedIncrement (&dstIf->ICB_Stats.OutDiscards);
+ }
+ }
+ else {// Filtered out
+ if (action==FILTER_DENY_OUT)
+ InterlockedIncrement (&dstIf->ICB_Stats.OutFiltered);
+ else {
+ ASSERT (action==FILTER_DENY_IN);
+ InterlockedIncrement (&srcIf->ICB_Stats.InFiltered);
+ }
+ IpxFwdDbgPrint (DBG_RECV, DBG_WARNING,
+ ("IpxFwd: Filtered out"
+ " packet on interface %ld (icb:%0lx),"
+ " dst-%ld (icb %08lx) %08lx:%02x%02x%02x%02x%02x%02x, type-%02x.\n",
+ srcIf->ICB_Index, srcIf, dstIf->ICB_Index, dstIf, dstNet,
+ LookaheadBuffer[IPXH_DESTNODE], LookaheadBuffer[IPXH_DESTNODE+1],
+ LookaheadBuffer[IPXH_DESTNODE+2], LookaheadBuffer[IPXH_DESTNODE+3],
+ LookaheadBuffer[IPXH_DESTNODE+4], LookaheadBuffer[IPXH_DESTNODE+5],
+ LookaheadBuffer[IPXH_PKTTYPE]));
+ }
+ }
+ else { // Destination interface is down
+ InterlockedIncrement (&srcIf->ICB_Stats.InDelivers);
+ InterlockedIncrement (&dstIf->ICB_Stats.OutDiscards);
+ IpxFwdDbgPrint (DBG_RECV, DBG_WARNING,
+ ("IpxFwd: Dest interface %ld (icb %08lx) down"
+ " for packet on interface %ld (icb:%0lx),"
+ " dst-%08lx:%02x%02x%02x%02x%02x%02x, type-%02x.\n",
+ dstIf->ICB_Index, dstIf, srcIf->ICB_Index, srcIf, dstNet,
+ LookaheadBuffer[IPXH_DESTNODE], LookaheadBuffer[IPXH_DESTNODE+1],
+ LookaheadBuffer[IPXH_DESTNODE+2], LookaheadBuffer[IPXH_DESTNODE+3],
+ LookaheadBuffer[IPXH_DESTNODE+4], LookaheadBuffer[IPXH_DESTNODE+5],
+ LookaheadBuffer[IPXH_PKTTYPE]));
+ }
+ ReleaseInterfaceReference (dstIf);
+ ReleaseRouteReference (dstRoute);
+ }
+ else { // if netbios
+ // check that this is a netbios bcast packet and
+ // didnt exceed the limit of routers to traverse
+ // and we can accept it on this interface
+ if (srcIf->ICB_NetbiosAccept
+ && (*(LookaheadBuffer + IPXH_XPORTCTL) < 8)) {
+ INT srcListId;
+ srcListId = srcIf->ICB_PacketListId;
+ KeReleaseSpinLock(&srcIf->ICB_Lock, oldIRQL);
+ // Check if packet is valid
+ if (IPX_NODE_CMP (LookaheadBuffer + IPXH_DESTNODE,
+ BROADCAST_NODE)==0) {
+ // Check if we haven't exceeded the quota
+ if (InterlockedDecrement (&NetbiosPacketsQuota)>=0) {
+ // try to get a packet from the rcv pkt pool
+ AllocatePacket (srcListId, srcListId, pktTag);
+ if (pktTag!=NULL) {
+ dstIf = srcIf;
+ AcquireInterfaceReference (dstIf);
+ goto GetPacket;
+ }
+ }
+ else {// Netbios quota exceded
+ IpxFwdDbgPrint (DBG_NETBIOS, DBG_WARNING,
+ ("IpxFwd: Netbios quota exceded"
+ " for packet on interface %ld (icb:%0lx),"
+ " dst-%08lx:%02x%02x%02x%02x%02x%02x, type-%02x.\n",
+ srcIf->ICB_Index, srcIf, dstNet,
+ LookaheadBuffer[IPXH_DESTNODE], LookaheadBuffer[IPXH_DESTNODE+1],
+ LookaheadBuffer[IPXH_DESTNODE+2], LookaheadBuffer[IPXH_DESTNODE+3],
+ LookaheadBuffer[IPXH_DESTNODE+4], LookaheadBuffer[IPXH_DESTNODE+5],
+ LookaheadBuffer[IPXH_PKTTYPE]));
+ InterlockedIncrement (&srcIf->ICB_Stats.InDiscards);
+ }
+ InterlockedIncrement (&NetbiosPacketsQuota);
+ }
+ else { // Bad netbios packet
+ IpxFwdDbgPrint (DBG_NETBIOS, DBG_WARNING,
+ ("IpxFwd: Bad nb packet on interface %ld (icb:%0lx),"
+ " dst-%08lx:%02x%02x%02x%02x%02x%02x, type-%02x.\n",
+ srcIf->ICB_Index, srcIf, dstNet,
+ LookaheadBuffer[IPXH_DESTNODE], LookaheadBuffer[IPXH_DESTNODE+1],
+ LookaheadBuffer[IPXH_DESTNODE+2], LookaheadBuffer[IPXH_DESTNODE+3],
+ LookaheadBuffer[IPXH_DESTNODE+4], LookaheadBuffer[IPXH_DESTNODE+5],
+ LookaheadBuffer[IPXH_PKTTYPE]));
+ InterlockedIncrement (&srcIf->ICB_Stats.InHdrErrors);
+ }
+ }
+ else { // Netbios accept disabled or to many routers crossed
+ KeReleaseSpinLock(&srcIf->ICB_Lock, oldIRQL);
+ InterlockedIncrement (&srcIf->ICB_Stats.InDiscards);
+ IpxFwdDbgPrint (DBG_NETBIOS, DBG_WARNING,
+ ("IpxFwd: NB packet dropped on disabled interface %ld (icb:%0lx),"
+ " dst-%08lx:%02x%02x%02x%02x%02x%02x, type-%02x.\n",
+ srcIf->ICB_Index, srcIf, dstNet,
+ LookaheadBuffer[IPXH_DESTNODE], LookaheadBuffer[IPXH_DESTNODE+1],
+ LookaheadBuffer[IPXH_DESTNODE+2], LookaheadBuffer[IPXH_DESTNODE+3],
+ LookaheadBuffer[IPXH_DESTNODE+4], LookaheadBuffer[IPXH_DESTNODE+5],
+ LookaheadBuffer[IPXH_PKTTYPE]));
+ }
+ } // End netbios specific processing (else if netbios)
+ }
+ else { // Looped back packets discarded without counting
+ // (We shouldn't get them in IPX stack does the right job)
+ KeReleaseSpinLock(&srcIf->ICB_Lock, oldIRQL);
+ }
+ }
+ else { // Interface is down or disabled
+ KeReleaseSpinLock(&srcIf->ICB_Lock, oldIRQL);
+ InterlockedIncrement (&srcIf->ICB_Stats.InDiscards);
+ IpxFwdDbgPrint (DBG_RECV, DBG_WARNING,
+ ("IpxFwd: Packet dropped on disabled interface %ld (icb:%0lx),"
+ " dst-%08lx:%02x%02x%02x%02x%02x%02x, type-%02x.\n",
+ srcIf->ICB_Index, srcIf, dstNet,
+ LookaheadBuffer[IPXH_DESTNODE], LookaheadBuffer[IPXH_DESTNODE+1],
+ LookaheadBuffer[IPXH_DESTNODE+2], LookaheadBuffer[IPXH_DESTNODE+3],
+ LookaheadBuffer[IPXH_DESTNODE+4], LookaheadBuffer[IPXH_DESTNODE+5],
+ LookaheadBuffer[IPXH_PKTTYPE]));
+ }
+ }
+ else { // Obvious header errors (shouldn't IPX do this for us ?
+ InterlockedIncrement (&srcIf->ICB_Stats.InHdrErrors);
+ IpxFwdDbgPrint (DBG_RECV, DBG_ERROR,
+ ("IpxFwd: Header errors in packet on interface %ld (icb:%0lx),"
+ " dst-%08lx:%02x%02x%02x%02x%02x%02x, type-%02x.\n",
+ srcIf->ICB_Index, srcIf, dstNet,
+ LookaheadBuffer[IPXH_DESTNODE], LookaheadBuffer[IPXH_DESTNODE+1],
+ LookaheadBuffer[IPXH_DESTNODE+2], LookaheadBuffer[IPXH_DESTNODE+3],
+ LookaheadBuffer[IPXH_DESTNODE+4], LookaheadBuffer[IPXH_DESTNODE+5],
+ LookaheadBuffer[IPXH_PKTTYPE]));
+ }
+ ReleaseInterfaceReference (srcIf);
+ } // We could not locate the interface from IPX supplied context: there
+ // is just a little time window when interface is deleted
+ // but IPX had already pushed the context on the stack
+ else {
+ IpxFwdDbgPrint (DBG_RECV, DBG_ERROR,
+ ("IpxFwd: Receive, type-%02x"
+ " - src interface context is invalid.\n",
+ LookaheadBuffer[IPXH_PKTTYPE]));
+ }
+ LeaveForwarder ();
+ return FALSE ;
+
+GetPacket:
+
+ InterlockedIncrement (&srcIf->ICB_Stats.InDelivers);
+ ReleaseInterfaceReference (srcIf);
+
+ pktDscr = CONTAINING_RECORD (pktTag, NDIS_PACKET, ProtocolReserved);
+ pktTag->PT_InterfaceReference = dstIf;
+ pktTag->PT_PerfCounter = PerfCounter.QuadPart;
+
+ // try to get the packet data
+ IPXTransferData(&status,
+ MacBindingHandle,
+ MacReceiveContext,
+ LookaheadBufferOffset, // start of IPX header
+ PacketSize, // packet size starting at IPX header
+ pktDscr,
+ &BytesTransferred);
+
+ if (status != NDIS_STATUS_PENDING) {
+ // complete the frame processing (LeaveForwarder will be called there)
+ IpxFwdTransferDataComplete(pktDscr, status, BytesTransferred);
+ }
+ return FALSE;
+}
+
+
+/*++
+*******************************************************************
+ F w T r a n s f e r D a t a C o m p l e t e
+
+Routine Description:
+ Called by the IPX stack when NIC driver completes data transger.
+Arguments:
+ pktDscr - handle of NIC driver
+ status - result of the transfer
+ bytesTransferred - number of bytest trasferred
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+IpxFwdTransferDataComplete (
+ PNDIS_PACKET pktDscr,
+ NDIS_STATUS status,
+ UINT bytesTransferred
+ ) {
+ PPACKET_TAG pktTag;
+
+ pktTag = (PPACKET_TAG)(&pktDscr->ProtocolReserved);
+
+ // If transfer failed, release the packet and interface
+ if (status==NDIS_STATUS_SUCCESS) {
+ if (*(pktTag->PT_Data + IPXH_PKTTYPE) != IPX_NETBIOS_TYPE)
+ SendPacket (pktTag->PT_InterfaceReference, pktTag);
+ else
+ ProcessNetbiosPacket (pktTag->PT_InterfaceReference, pktTag);
+
+ }
+ else {
+ IpxFwdDbgPrint (DBG_RECV, DBG_ERROR,
+ ("IpxFwd: Transfer data failed for packet %08lx on interface %08lx!\n",
+ pktTag, pktTag->PT_InterfaceReference));
+ if (*(pktTag->PT_Data + IPXH_PKTTYPE) != IPX_NETBIOS_TYPE) {
+ InterlockedIncrement (
+ &pktTag->PT_InterfaceReference->ICB_Stats.OutDiscards);
+ }
+ else { // For netbios packets interface reference is
+ // actually a source interface
+ InterlockedIncrement (&NetbiosPacketsQuota);
+ InterlockedIncrement (
+ &pktTag->PT_InterfaceReference->ICB_Stats.InDiscards);
+ }
+ ReleaseInterfaceReference (pktTag->PT_InterfaceReference);
+ FreePacket (pktTag);
+ }
+
+ LeaveForwarder ();
+ return;
+}
+
+
+/*++
+*******************************************************************
+ F w R e c e i v e C o m p l e t e
+
+Routine Description:
+
+ This routine receives control from the IPX driver after one or
+ more receive operations have completed and no receive is in progress.
+ It is called under less severe time constraints than IpxFwdReceive.
+ It is used to process netbios queue
+
+Arguments:
+ None
+Return Value:
+ None
+*******************************************************************
+--*/
+VOID
+IpxFwdReceiveComplete (
+ USHORT NicId
+ ) {
+
+ // check that our configuration process has terminated OK
+ if(!EnterForwarder ()) {
+ return;
+ }
+ IpxFwdDbgPrint (DBG_RECV, DBG_INFORMATION, ("IpxFwd: FwdReceiveComplete.\n"));
+ ScheduleNetbiosWorker ();
+ LeaveForwarder ();
+}
+
+/*++
+*******************************************************************
+ I p x F w d I n t e r n a l R e c e i v e
+
+Routine Description:
+ Called by the IPX stack to indicate that the IPX packet destined
+ to local client was received by the NIC dirver.
+Arguments:
+ Context - forwarder context associated with
+ the NIC (interface block pointer)
+ RemoteAddress - sender's address
+ LookaheadBuffer - packet lookahead buffer that contains complete
+ IPX header
+ LookaheadBufferSize - its size (at least 30 bytes)
+Return Value:
+ STATUS_SUCCESS - the packet will be delivered to local destination
+ STATUS_UNSUCCESSFUL - the packet will be dropped
+
+*******************************************************************
+--*/
+NTSTATUS
+IpxFwdInternalReceive (
+ IN ULONG Context,
+ IN PIPX_LOCAL_TARGET RemoteAddress,
+ IN PUCHAR LookAheadBuffer,
+ IN UINT LookAheadBufferSize
+ ) {
+ NTSTATUS status = STATUS_SUCCESS;
+ PINTERFACE_CB srcIf;
+
+ if (!EnterForwarder ()) {
+ return STATUS_UNSUCCESSFUL;
+ }
+ if (Context!=VIRTUAL_NET_FORWARDER_CONTEXT) {
+ // Check if interface context supplied by IPX driver is valid
+ srcIf = InterfaceContextToReference ((PVOID)Context, RemoteAddress->NicId);
+ }
+ else {
+ srcIf = InternalInterface;
+ AcquireInterfaceReference (srcIf);
+ }
+
+ if (srcIf!=NULL) {
+ // Check if we can accept on this interface
+ if (IS_IF_ENABLED (srcIf)
+ && (srcIf->ICB_Stats.OperationalState!=FWD_OPER_STATE_DOWN)
+ && ((*(LookAheadBuffer + IPXH_PKTTYPE) != IPX_NETBIOS_TYPE)
+ || srcIf->ICB_NetbiosAccept)) {
+ // Check if we can accept on internal interface
+ if (IS_IF_ENABLED(InternalInterface)) {
+ FILTER_ACTION action;
+ action = FltFilter (LookAheadBuffer, LookAheadBufferSize,
+ srcIf->ICB_FilterInContext,
+ InternalInterface->ICB_FilterOutContext);
+ // Check the filter
+ if (action==FILTER_PERMIT) {
+ // Update source interface statistics
+ InterlockedIncrement (&srcIf->ICB_Stats.InDelivers);
+ // Handle NB packets separatedly
+ if (*(LookAheadBuffer + IPXH_PKTTYPE) != IPX_NETBIOS_TYPE) {
+ InterlockedIncrement (
+ &InternalInterface->ICB_Stats.OutDelivers);
+ IpxFwdDbgPrint (DBG_INT_RECV, DBG_INFORMATION,
+ ("IpxFwd: FwdInternalReceive,"
+ " from %d(%lx)-%.2x%.2x%.2x%.2x:%.2x%.2x%.2x%.2x%.2x%.2x,"
+ " type-%02x.\n",
+ srcIf->ICB_Index, srcIf,
+ LookAheadBuffer[IPXH_SRCNET],LookAheadBuffer[IPXH_SRCNET+1],
+ LookAheadBuffer[IPXH_SRCNET+2],LookAheadBuffer[IPXH_SRCNET+3],
+ LookAheadBuffer[IPXH_SRCNODE],LookAheadBuffer[IPXH_SRCNODE+1],
+ LookAheadBuffer[IPXH_SRCNODE+2],LookAheadBuffer[IPXH_SRCNODE+3],
+ LookAheadBuffer[IPXH_SRCNODE+4],LookAheadBuffer[IPXH_SRCNODE+5],
+ LookAheadBuffer[IPXH_PKTTYPE]));
+ }
+ else {
+ // Check if destination netbios name is staticly assigned to
+ // an external interface or netbios delivery options do not
+ // allow us to deliver this packet
+ PINTERFACE_CB dstIf;
+ USHORT dstSock = GETUSHORT (LookAheadBuffer+IPXH_DESTSOCK);
+
+ InterlockedIncrement (&srcIf->ICB_Stats.NetbiosReceived);
+ // First try to find a static name if we have enough data
+ // in the lookahead buffer
+ if ((dstSock==IPX_NETBIOS_SOCKET)
+ && (LookAheadBufferSize>(NB_NAME+16)))
+ dstIf = FindNBDestination (LookAheadBuffer+(NB_NAME-IPXH_HDRSIZE));
+ else if ((dstSock==IPX_SMB_NAME_SOCKET)
+ && (LookAheadBufferSize>(SMB_NAME+16)))
+ dstIf = FindNBDestination (LookAheadBuffer+(SMB_NAME-IPXH_HDRSIZE));
+ else
+ dstIf = NULL;
+ // Now see, if we can deliver the packet
+ if ((((dstIf==NULL) || (dstIf==InternalInterface))
+ && (InternalInterface->ICB_NetbiosDeliver==FWD_NB_DELIVER_ALL))
+ || ((dstIf==InternalInterface)
+ && (InternalInterface->ICB_NetbiosDeliver==FWD_NB_DELIVER_STATIC))) {
+ InterlockedIncrement (
+ &InternalInterface->ICB_Stats.NetbiosSent);
+ InterlockedIncrement (
+ &InternalInterface->ICB_Stats.OutDelivers);
+ IpxFwdDbgPrint (DBG_INT_RECV, DBG_INFORMATION,
+ ("IpxFwd: FwdInternalReceive, NB"
+ " from %d(%lx)-%.2x%.2x%.2x%.2x:%.2x%.2x%.2x%.2x%.2x%.2x\n",
+ srcIf->ICB_Index, srcIf,
+ LookAheadBuffer[IPXH_SRCNET],LookAheadBuffer[IPXH_SRCNET+1],
+ LookAheadBuffer[IPXH_SRCNET+2],LookAheadBuffer[IPXH_SRCNET+3],
+ LookAheadBuffer[IPXH_SRCNODE],LookAheadBuffer[IPXH_SRCNODE+1],
+ LookAheadBuffer[IPXH_SRCNODE+2],LookAheadBuffer[IPXH_SRCNODE+3],
+ LookAheadBuffer[IPXH_SRCNODE+4],LookAheadBuffer[IPXH_SRCNODE+5]));
+ }
+ else {
+ InterlockedIncrement (
+ &InternalInterface->ICB_Stats.OutDiscards);
+ IpxFwdDbgPrint (DBG_INT_RECV, DBG_WARNING,
+ ("IpxFwd: FwdInternalReceive, NB dropped because delivery disabled"
+ " from %d(%lx)-%.2x%.2x%.2x%.2x:%.2x%.2x%.2x%.2x%.2x%.2x\n",
+ srcIf->ICB_Index, srcIf,
+ LookAheadBuffer[IPXH_SRCNET],LookAheadBuffer[IPXH_SRCNET+1],
+ LookAheadBuffer[IPXH_SRCNET+2],LookAheadBuffer[IPXH_SRCNET+3],
+ LookAheadBuffer[IPXH_SRCNODE],LookAheadBuffer[IPXH_SRCNODE+1],
+ LookAheadBuffer[IPXH_SRCNODE+2],LookAheadBuffer[IPXH_SRCNODE+3],
+ LookAheadBuffer[IPXH_SRCNODE+4],LookAheadBuffer[IPXH_SRCNODE+5]));
+ status = STATUS_UNSUCCESSFUL;
+ }
+ if (dstIf!=NULL)
+ ReleaseInterfaceReference (dstIf);
+ }
+ }
+ else {// Filtered Out
+ if (action==FILTER_DENY_OUT)
+ InterlockedIncrement (
+ &InternalInterface->ICB_Stats.OutFiltered);
+ else {
+ ASSERT (action==FILTER_DENY_IN);
+ InterlockedIncrement (&srcIf->ICB_Stats.InFiltered);
+ }
+ IpxFwdDbgPrint (DBG_INT_RECV, DBG_WARNING,
+ ("IpxFwd: FwdInternalReceive, filtered out"
+ " from %d(%lx)-%.2x%.2x%.2x%.2x:%.2x%.2x%.2x%.2x%.2x%.2x,"
+ " type-%02x.\n",
+ srcIf->ICB_Index, srcIf,
+ LookAheadBuffer[IPXH_SRCNET],LookAheadBuffer[IPXH_SRCNET+1],
+ LookAheadBuffer[IPXH_SRCNET+2],LookAheadBuffer[IPXH_SRCNET+3],
+ LookAheadBuffer[IPXH_SRCNODE],LookAheadBuffer[IPXH_SRCNODE+1],
+ LookAheadBuffer[IPXH_SRCNODE+2],LookAheadBuffer[IPXH_SRCNODE+3],
+ LookAheadBuffer[IPXH_SRCNODE+4],LookAheadBuffer[IPXH_SRCNODE+5],
+ LookAheadBuffer[IPXH_PKTTYPE]));
+ }
+ }
+ else {// Internal interface is disabled
+ InterlockedIncrement (
+ &InternalInterface->ICB_Stats.OutDiscards);
+ status = STATUS_UNSUCCESSFUL;
+ IpxFwdDbgPrint (DBG_INT_RECV, DBG_WARNING,
+ ("IpxFwd: FwdInternalReceive, internal if disabled"
+ " from %d(%lx)-%.2x%.2x%.2x%.2x:%.2x%.2x%.2x%.2x%.2x%.2x,"
+ " type-%02x.\n",
+ srcIf->ICB_Index, srcIf,
+ LookAheadBuffer[IPXH_SRCNET],LookAheadBuffer[IPXH_SRCNET+1],
+ LookAheadBuffer[IPXH_SRCNET+2],LookAheadBuffer[IPXH_SRCNET+3],
+ LookAheadBuffer[IPXH_SRCNODE],LookAheadBuffer[IPXH_SRCNODE+1],
+ LookAheadBuffer[IPXH_SRCNODE+2],LookAheadBuffer[IPXH_SRCNODE+3],
+ LookAheadBuffer[IPXH_SRCNODE+4],LookAheadBuffer[IPXH_SRCNODE+5],
+ LookAheadBuffer[IPXH_PKTTYPE]));
+ }
+ }
+ else { // Disabled source interface
+ InterlockedIncrement (&srcIf->ICB_Stats.InDiscards);
+ IpxFwdDbgPrint (DBG_INT_RECV, DBG_ERROR,
+ ("IpxFwd: FwdInternalReceive, source if disabled"
+ " from %d(%lx)-%.2x%.2x%.2x%.2x:%.2x%.2x%.2x%.2x%.2x%.2x,"
+ " type-%02x.\n",
+ srcIf->ICB_Index, srcIf,
+ LookAheadBuffer[IPXH_SRCNET],LookAheadBuffer[IPXH_SRCNET+1],
+ LookAheadBuffer[IPXH_SRCNET+2],LookAheadBuffer[IPXH_SRCNET+3],
+ LookAheadBuffer[IPXH_SRCNODE],LookAheadBuffer[IPXH_SRCNODE+1],
+ LookAheadBuffer[IPXH_SRCNODE+2],LookAheadBuffer[IPXH_SRCNODE+3],
+ LookAheadBuffer[IPXH_SRCNODE+4],LookAheadBuffer[IPXH_SRCNODE+5],
+ LookAheadBuffer[IPXH_PKTTYPE]));
+ status = STATUS_UNSUCCESSFUL;
+ }
+ ReleaseInterfaceReference (srcIf);
+ }
+ else { // Invalid source interface context
+ IpxFwdDbgPrint (DBG_INT_RECV, DBG_ERROR,
+ ("IpxFwd: FwdInternalReceive, source if context is invalid"
+ " from (%lx:%d)-%.2x%.2x%.2x%.2x:%.2x%.2x%.2x%.2x%.2x%.2x,"
+ " type-%02x.\n",
+ Context, RemoteAddress->NicId,
+ LookAheadBuffer[IPXH_SRCNET],LookAheadBuffer[IPXH_SRCNET+1],
+ LookAheadBuffer[IPXH_SRCNET+2],LookAheadBuffer[IPXH_SRCNET+3],
+ LookAheadBuffer[IPXH_SRCNODE],LookAheadBuffer[IPXH_SRCNODE+1],
+ LookAheadBuffer[IPXH_SRCNODE+2],LookAheadBuffer[IPXH_SRCNODE+3],
+ LookAheadBuffer[IPXH_SRCNODE+4],LookAheadBuffer[IPXH_SRCNODE+5],
+ LookAheadBuffer[IPXH_PKTTYPE]));
+ status = STATUS_UNSUCCESSFUL;
+ }
+ LeaveForwarder ();
+ return status;
+}
+
+/*++
+*******************************************************************
+ D e l e t e R e c v Q u e u e
+
+Routine Description:
+ Initializes the netbios bradcast queue
+Arguments:
+ None
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+DeleteRecvQueue (
+ void
+ ) {
+// while (!IsListEmpty (&RecvQueue)) {
+// PPACKET_TAG pktTag = CONTAINING_RECORD (RecvQueue.Flink,
+// PACKET_TAG,
+// PT_QueueLink);
+// RemoveEntryList (&pktTag->PT_QueueLink);
+// if (pktTag->PT_InterfaceReference!=NULL) {
+// ReleaseInterfaceReference (pktTag->PT_InterfaceReference);
+// }
+// FreePacket (pktTag);
+// }
+}
+#if DBG
+
+ULONG DbgFilterTrap = 0; // 1 - on dst and src (net + node),
+ // 2 - on dst (net + node),
+ // 3 - on src (net + node),
+ // 4 - on dst (net + node + socket)
+
+UCHAR DbgFilterDstNet[4];
+UCHAR DbgFilterDstNode[6];
+UCHAR DbgFilterDstSocket[2];
+UCHAR DbgFilterSrcNet[4];
+UCHAR DbgFilterSrcNode[6];
+UCHAR DbgFilterSrcSocket[2];
+PUCHAR DbgFilterFrame;
+
+VOID
+DbgFilterReceivedPacket(PUCHAR hdrp)
+{
+ switch(DbgFilterTrap) {
+
+ case 1:
+
+ if(!memcmp(hdrp + IPXH_DESTNET, DbgFilterDstNet, 4) &&
+ !memcmp(hdrp + IPXH_DESTNODE, DbgFilterDstNode, 6) &&
+ !memcmp(hdrp + IPXH_SRCNET, DbgFilterSrcNet, 4) &&
+ !memcmp(hdrp + IPXH_SRCNODE, DbgFilterSrcNode, 6)) {
+
+ DbgBreakPoint();
+ }
+
+ break;
+
+ case 2:
+
+ if(!memcmp(hdrp + IPXH_DESTNET, DbgFilterDstNet, 4) &&
+ !memcmp(hdrp + IPXH_DESTNODE, DbgFilterDstNode, 6)) {
+
+ DbgBreakPoint();
+ }
+
+ break;
+
+ case 3:
+
+ if(!memcmp(hdrp + IPXH_SRCNET, DbgFilterSrcNet, 4) &&
+ !memcmp(hdrp + IPXH_SRCNODE, DbgFilterSrcNode, 6)) {
+
+ DbgBreakPoint();
+ }
+
+ break;
+
+ case 4:
+
+ if(!memcmp(hdrp + IPXH_DESTNET, DbgFilterDstNet, 4) &&
+ !memcmp(hdrp + IPXH_DESTNODE, DbgFilterDstNode, 6) &&
+ !memcmp(hdrp + IPXH_DESTSOCK, DbgFilterDstSocket, 2)) {
+
+ DbgBreakPoint();
+ }
+
+ break;
+
+ default:
+
+ break;
+ }
+
+ DbgFilterFrame = hdrp;
+}
+
+#endif
+
diff --git a/private/ntos/tdi/isn/fwd/rcvind.h b/private/ntos/tdi/isn/fwd/rcvind.h
new file mode 100644
index 000000000..50f240bdd
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/rcvind.h
@@ -0,0 +1,180 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ ntos\tdi\isn\fwd\rcvind.h
+
+Abstract:
+ Receive indication processing
+
+Author:
+
+ Vadim Eydelman
+
+Revision History:
+
+--*/
+
+#ifndef _IPXFWD_RCVIND
+#define _IPXFWD_RCVIND
+
+// Doesn't allow accepting packets (for routing) from dial-in clients
+extern BOOLEAN ThisMachineOnly;
+
+/*++
+*******************************************************************
+ I n i t i a l i z e R e c v Q u e u e
+
+Routine Description:
+ Initializes recv queue
+Arguments:
+ None
+Return Value:
+ None
+
+*******************************************************************
+--*/
+//VOID
+//DeleteRecvQueue (
+// void
+// )
+#define InitializeRecvQueue() { \
+}
+
+/*++
+*******************************************************************
+ D e l e t e R e c v Q u e u e
+
+Routine Description:
+ Deletes recv queue
+Arguments:
+ None
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+DeleteRecvQueue (
+ void
+ );
+
+/*++
+*******************************************************************
+ F w R e c e i v e
+
+Routine Description:
+ Called by the IPX stack to indicate that the IPX packet was
+ received by the NIC dirver. Only external destined packets are
+ indicated by this routine (with the exception of Netbios boradcasts
+ that indicated both for internal and external handlers)
+Arguments:
+ MacBindingHandle - handle of NIC driver
+ MaxReceiveContext - NIC driver context
+ Context - forwarder context associated with
+ the NIC (interface block pointer)
+ RemoteAddress - sender's address
+ MacOptions -
+ LookaheadBuffer - packet lookahead buffer that contains complete
+ IPX header
+ LookaheadBufferSize - its size (at least 30 bytes)
+ LookaheadBufferOffset - offset of lookahead buffer in the physical
+ packet
+Return Value:
+ None
+
+*******************************************************************
+--*/
+BOOLEAN
+IpxFwdReceive (
+ NDIS_HANDLE MacBindingHandle,
+ NDIS_HANDLE MacReceiveContext,
+ ULONG Context,
+ PIPX_LOCAL_TARGET RemoteAddress,
+ ULONG MacOptions,
+ PUCHAR LookaheadBuffer,
+ UINT LookaheadBufferSize,
+ UINT LookaheadBufferOffset,
+ UINT PacketSize,
+ PMDL pMdl
+
+ );
+
+
+/*++
+*******************************************************************
+ F w T r a n s f e r D a t a C o m p l e t e
+
+Routine Description:
+ Called by the IPX stack when NIC driver completes data transger.
+Arguments:
+ pktDscr - handle of NIC driver
+ status - result of the transfer
+ bytesTransferred - number of bytest trasferred
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+IpxFwdTransferDataComplete (
+ PNDIS_PACKET pktDscr,
+ NDIS_STATUS status,
+ UINT bytesTransferred
+ );
+
+
+/*++
+*******************************************************************
+ F w T r a n s f e r D a t a C o m p l e t e
+
+Routine Description:
+
+ This routine receives control from the IPX driver after one or
+ more receive operations have completed and no receive is in progress.
+ It is called under less severe time constraints than IpxFwdReceive.
+ It is used to process netbios queue
+
+Arguments:
+ None
+Return Value:
+ None
+*******************************************************************
+--*/
+VOID
+IpxFwdReceiveComplete (
+ USHORT NicId
+ );
+
+/*++
+*******************************************************************
+ F w R e c e i v e
+
+Routine Description:
+ Called by the IPX stack to indicate that the IPX packet destined
+ to local client was received by the NIC dirver.
+Arguments:
+ Context - forwarder context associated with
+ the NIC (interface block pointer)
+ RemoteAddress - sender's address
+ LookaheadBuffer - packet lookahead buffer that contains complete
+ IPX header
+ LookaheadBufferSize - its size (at least 30 bytes)
+Return Value:
+ STATUS_SUCCESS - the packet will be delivered to local destination
+ STATUS_UNSUCCESSFUL - the packet will be dropped
+
+*******************************************************************
+--*/
+NTSTATUS
+IpxFwdInternalReceive (
+ IN ULONG FwdAdapterContext,
+ IN PIPX_LOCAL_TARGET RemoteAddress,
+ IN PUCHAR LookAheadBuffer,
+ IN UINT LookAheadBufferSize
+ );
+
+#endif
+
diff --git a/private/ntos/tdi/isn/fwd/registry.c b/private/ntos/tdi/isn/fwd/registry.c
new file mode 100644
index 000000000..b38a3b4e1
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/registry.c
@@ -0,0 +1,273 @@
+/*******************************************************************/
+/* Copyright(c) 1993 Microsoft Corporation */
+/*******************************************************************/
+
+//***
+//
+// Filename: registry.c
+//
+// Description: routines for reading the registry configuration
+//
+// Author: Stefan Solomon (stefans) November 9, 1993.
+//
+// Revision History:
+// Updated to read parameters of new forwarder driver (11/95)
+//
+//***
+
+#include "precomp.h"
+
+NTSTATUS
+SetIpxDeviceName(
+ IN PWSTR ValueName,
+ IN ULONG ValueType,
+ IN PVOID ValueData,
+ IN ULONG ValueLength,
+ IN PVOID Context,
+ IN PVOID EntryContext
+ );
+
+/*++
+*******************************************************************
+ R e a d I p x D e v i c e N a m e
+
+Routine Description:
+ Allocates buffer and reads device name exported by the IPX stack
+ into it
+Arguments:
+ FileName - pointer to buffer to hold the name
+Return Value:
+ STATUS_SUCCESS - tables were created ok
+ STATUS_INSUFFICIENT_RESOURCES - resource allocation failed
+ STATUS_OBJECT_NAME_NOT_FOUND - if name value is not found
+*******************************************************************
+--*/
+NTSTATUS
+ReadIpxDeviceName (
+ PWSTR *FileName
+ ) {
+ NTSTATUS Status;
+ RTL_QUERY_REGISTRY_TABLE QueryTable[2];
+ PWSTR Export = L"Export";
+ PWSTR IpxRegistryPath = L"NwLnkIpx\\Linkage";
+
+ //
+ // Set up QueryTable to do the following:
+ //
+
+ //
+ // 1) Call SetIpxDeviceName for the string in "Export"
+ //
+
+ QueryTable[0].QueryRoutine = SetIpxDeviceName;
+ QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
+ QueryTable[0].Name = Export;
+ QueryTable[0].EntryContext = FileName;
+ QueryTable[0].DefaultType = 0;
+
+ //
+ // 2) Stop
+ //
+
+ QueryTable[1].QueryRoutine = NULL;
+ QueryTable[1].Flags = 0;
+ QueryTable[1].Name = NULL;
+
+ Status = RtlQueryRegistryValues(
+ RTL_REGISTRY_SERVICES,
+ IpxRegistryPath,
+ QueryTable,
+ NULL,
+ NULL);
+
+ return Status;
+}
+
+
+/*++
+*******************************************************************
+ S e t I p x D e v i c e N a m e
+
+Routine Description:
+ This routine is a callback routine for RtlQueryRegistryValues
+ It is called for each piece of the "Export" multi-string and
+ saves the information in a ConfigurationInfo structure.
+Arguments:
+ ValueName - The name of the value ("Export" -- ignored).
+ ValueType - The type of the value (REG_SZ -- ignored).
+ ValueData - The null-terminated data for the value.
+ ValueLength - The length of ValueData.
+ Context - NULL.
+ EntryContext - file name pointer.
+Return Value:
+ STATUS_SUCCESS - name was allocated and copied OK
+ STATUS_INSUFFICIENT_RESOURCES - name allocation failed
+*******************************************************************
+--*/
+NTSTATUS
+SetIpxDeviceName(
+ IN PWSTR ValueName,
+ IN ULONG ValueType,
+ IN PVOID ValueData,
+ IN ULONG ValueLength,
+ IN PVOID Context,
+ IN PVOID EntryContext
+ ) {
+ PWSTR *FileName = (PWSTR *)EntryContext;
+
+ ASSERT (ValueType==REG_SZ);
+ *FileName = (PWSTR)ExAllocatePoolWithTag(NonPagedPool,
+ ValueLength, FWD_POOL_TAG);
+ if (*FileName != NULL) {
+ RtlCopyMemory (*FileName, ValueData, ValueLength);
+ return STATUS_SUCCESS;
+ }
+ else
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+}
+
+/*++
+*******************************************************************
+ G e t R o u t e r P a r a m e t e r s
+
+Routine Description:
+ Reads the parameters from the registry or sets the defaults
+Arguments:
+ RegistryPath - where to read from.
+Return Value:
+ STATUS_SUCCESS
+*******************************************************************
+--*/
+NTSTATUS
+GetForwarderParameters (
+ IN PUNICODE_STRING RegistryPath
+ ) {
+ NTSTATUS Status;
+ PWSTR RegistryPathBuffer;
+ PWSTR Parameters = L"Parameters";
+ RTL_QUERY_REGISTRY_TABLE paramTable[11]; // table size = nr of params + 1
+
+ RegistryPathBuffer = (PWSTR)ExAllocatePool(NonPagedPool, RegistryPath->Length + sizeof(WCHAR));
+
+ if (RegistryPathBuffer == NULL) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlCopyMemory (RegistryPathBuffer, RegistryPath->Buffer, RegistryPath->Length);
+ *(PWCHAR)(((PUCHAR)RegistryPathBuffer)+RegistryPath->Length) = (WCHAR)'\0';
+
+ RtlZeroMemory(&paramTable[0], sizeof(paramTable));
+
+ paramTable[0].QueryRoutine = NULL;
+ paramTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
+ paramTable[0].Name = Parameters;
+
+ paramTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
+ paramTable[1].Name = L"MaxRcvPktPoolSize";
+ paramTable[1].EntryContext = &MaxRcvPktsPoolSize;
+ paramTable[1].DefaultType = REG_DWORD;
+ paramTable[1].DefaultData = &MaxRcvPktsPoolSize;
+ paramTable[1].DefaultLength = sizeof(ULONG);
+
+ paramTable[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
+ paramTable[2].Name = L"RcvPktsPerSegment";
+ paramTable[2].EntryContext = &RcvPktsPerSegment;
+ paramTable[2].DefaultType = REG_DWORD;
+ paramTable[2].DefaultData = &RcvPktsPerSegment;
+ paramTable[2].DefaultLength = sizeof(ULONG);
+
+ paramTable[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
+ paramTable[3].Name = L"RouteTableSegmentSize";
+ paramTable[3].EntryContext = &RouteSegmentSize;
+ paramTable[3].DefaultType = REG_DWORD;
+ paramTable[3].DefaultData = &RouteSegmentSize;
+ paramTable[3].DefaultLength = sizeof(ULONG);
+
+ paramTable[4].Flags = RTL_QUERY_REGISTRY_DIRECT;
+ paramTable[4].Name = L"MaxSendPktsQueued";
+ paramTable[4].EntryContext = &MaxSendPktsQueued;
+ paramTable[4].DefaultType = REG_DWORD;
+ paramTable[4].DefaultData = &MaxSendPktsQueued;
+ paramTable[4].DefaultLength = sizeof(ULONG);
+
+ paramTable[5].Flags = RTL_QUERY_REGISTRY_DIRECT;
+ paramTable[5].Name = L"ClientHashSize";
+ paramTable[5].EntryContext = &ClientHashSize;
+ paramTable[5].DefaultType = REG_DWORD;
+ paramTable[5].DefaultData = &ClientHashSize;
+ paramTable[5].DefaultLength = sizeof(ULONG);
+
+ paramTable[6].Flags = RTL_QUERY_REGISTRY_DIRECT;
+ paramTable[6].Name = L"InterfaceHashSize";
+ paramTable[6].EntryContext = &InterfaceHashSize;
+ paramTable[6].DefaultType = REG_DWORD;
+ paramTable[6].DefaultData = &InterfaceHashSize;
+ paramTable[6].DefaultLength = sizeof(ULONG);
+
+ paramTable[7].Flags = RTL_QUERY_REGISTRY_DIRECT;
+ paramTable[7].Name = L"MaxNetbiosPacketsQueued";
+ paramTable[7].EntryContext = &MaxNetbiosPacketsQueued;
+ paramTable[7].DefaultType = REG_DWORD;
+ paramTable[7].DefaultData = &MaxNetbiosPacketsQueued;
+ paramTable[7].DefaultLength = sizeof(ULONG);
+
+ paramTable[8].Flags = RTL_QUERY_REGISTRY_DIRECT;
+ paramTable[8].Name = L"SpoofingTimeout";
+ paramTable[8].EntryContext = &SpoofingTimeout;
+ paramTable[8].DefaultType = REG_DWORD;
+ paramTable[8].DefaultData = &SpoofingTimeout;
+ paramTable[8].DefaultLength = sizeof(ULONG);
+
+ paramTable[9].Flags = RTL_QUERY_REGISTRY_DIRECT;
+ paramTable[9].Name = L"DontSuppressNonAgentSapAdvertisements";
+ paramTable[9].EntryContext = &DontSuppressNonAgentSapAdvertisements;
+ paramTable[9].DefaultType = REG_DWORD;
+ paramTable[9].DefaultData = &DontSuppressNonAgentSapAdvertisements;
+ paramTable[9].DefaultLength = sizeof(ULONG);
+
+ Status = RtlQueryRegistryValues(
+ RTL_REGISTRY_ABSOLUTE,
+ RegistryPathBuffer,
+ paramTable,
+ NULL,
+ NULL);
+
+ if(!NT_SUCCESS(Status)) {
+
+ IpxFwdDbgPrint (DBG_REGISTRY, DBG_WARNING,
+ ("IpxFwd: Missing Parameters key in the registry\n"));
+ }
+
+ ExFreePool(RegistryPathBuffer);
+
+ if ((RcvPktsPerSegment > MAX_RCV_PKTS_PER_SEGMENT) ||
+ (RcvPktsPerSegment < MIN_RCV_PKTS_PER_SEGMENT)) {
+
+ RcvPktsPerSegment = DEF_RCV_PKTS_PER_SEGMENT;
+ }
+
+ if ((RouteSegmentSize > MAX_ROUTE_SEGMENT_SIZE) ||
+ (RouteSegmentSize < MIN_ROUTE_SEGMENT_SIZE)) {
+
+ RouteSegmentSize = DEF_ROUTE_SEGMENT_SIZE;
+ }
+ else
+ RouteSegmentSize = ROUND_TO_PAGES(RouteSegmentSize);
+
+ if ((InterfaceHashSize > MAX_INTERFACE_HASH_SIZE) ||
+ (InterfaceHashSize < MIN_INTERFACE_HASH_SIZE)) {
+
+ InterfaceHashSize = DEF_INTERFACE_HASH_SIZE;
+ }
+
+ if ((ClientHashSize > MAX_CLIENT_HASH_SIZE) ||
+ (ClientHashSize < MIN_CLIENT_HASH_SIZE)) {
+
+ ClientHashSize = DEF_CLIENT_HASH_SIZE;
+ }
+ // even if the RtlQueryRegistryValues has failed, we return success and will
+ // use the defaults.
+ return STATUS_SUCCESS;
+}
+
diff --git a/private/ntos/tdi/isn/fwd/registry.h b/private/ntos/tdi/isn/fwd/registry.h
new file mode 100644
index 000000000..6cff0eef2
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/registry.h
@@ -0,0 +1,61 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ ntos\tdi\isn\fwd\registry.h
+
+Abstract:
+ IPX Forwarder Driver registry interface
+
+
+Author:
+
+ Vadim Eydelman
+
+Revision History:
+
+--*/
+#ifndef _IPXFWD_REGISTRY_
+#define _IPXFWD_REGISTRY_
+
+/*++
+*******************************************************************
+ R e a d I p x D e v i c e N a m e
+
+Routine Description:
+ Allocates buffer and reads device name exported by the IPX stack
+ into it
+Arguments:
+ FileName - pointer to variable to hold the name buffer
+Return Value:
+ STATUS_SUCCESS - tables were created ok
+ STATUS_INSUFFICIENT_RESOURCES - resource allocation failed
+ STATUS_OBJECT_NAME_NOT_FOUND - if name value is not found
+*******************************************************************
+--*/
+NTSTATUS
+ReadIpxDeviceName (
+ PWSTR *FileName
+ );
+
+/*++
+*******************************************************************
+ G e t R o u t e r P a r a m e t e r s
+
+Routine Description:
+ Reads the parameters from the registry or sets the defaults
+Arguments:
+ RegistryPath - where to read from.
+Return Value:
+ STATUS_SUCCESS
+*******************************************************************
+--*/
+NTSTATUS
+GetForwarderParameters (
+ IN PUNICODE_STRING RegistryPath
+ );
+
+#endif
+
diff --git a/private/ntos/tdi/isn/fwd/rwlock.h b/private/ntos/tdi/isn/fwd/rwlock.h
new file mode 100644
index 000000000..d1a390651
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/rwlock.h
@@ -0,0 +1,179 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ ntos\tdi\isn\fwd\rwlock.h
+
+Abstract:
+ Reader-Writer lock macros
+
+
+Author:
+
+ Vadim Eydelman
+
+Revision History:
+
+--*/
+
+#ifndef _IPXFWD_RWLOCK_
+#define _IPXFWD_RWLOCK_
+
+typedef volatile LONG VOLCTR, *PVOLCTR;
+typedef PVOLCTR RWCOOKIE, *PRWCOOKIE;
+
+// Reader- writer lock.
+// Allows no-lock access to the tables for readers - they merely
+// increment the counter to record their presence upon entrance
+// and decrement the same counter as they leave.
+// Writers are supposed to be serialized (externally) and their
+// actions are limited to ATOMIC insertions of new elements and
+// ATOMIC removals/replacements. The removals/replacements MUST
+// be followed by a wait for all potential readers who might still
+// be using the element that was removed/replaced
+
+typedef struct _RW_LOCK {
+ KEVENT Event; // Event to release waiting writer
+ VOLCTR Ctr1; // Two alternating
+ VOLCTR Ctr2; // reader counters
+ volatile PVOLCTR CurCtr; // Counter currently in use
+} RW_LOCK, *PRW_LOCK;
+
+
+/*++
+*******************************************************************
+ I n i t i a l i z e R W L o c k
+
+Routine Description:
+ Initializes RW lock
+Arguments:
+ lock - pointer to lock to initialize
+Return Value:
+ None
+*******************************************************************
+--*/
+//VOID
+//InitializeRWLock (
+// PRW_LOCK lock
+// );
+#define InitializeRWLock(lock) { \
+ KeInitializeEvent (&(lock)->Event, \
+ SynchronizationEvent, \
+ FALSE); \
+ (lock)->Ctr1 = (lock)->Ctr2 = 0; \
+ (lock)->CurCtr = &(lock)->Ctr1; \
+}
+
+/*++
+*******************************************************************
+ A c q u i r e R e a d e r A c c e s s
+
+Routine Description:
+ Acquires reader access to resource protected by the lock
+Arguments:
+ lock - pointer to lock
+ cookie - pointer to buffer to store lock state for subsequent
+ release operation
+Return Value:
+ None
+*******************************************************************
+--*/
+//VOID
+//AcquireReaderAccess (
+// IN PRW_LOCK lock,
+// OUT RWCOOKIE cookie
+// );
+#define AcquireReaderAccess(lock,cookie) \
+ do { \
+ register LONG local,local1; \
+ cookie = (lock)->CurCtr; /*Get current counter pointer*/ \
+ local = *(cookie); /*Copy counter value*/ \
+ local1 = local + 1; \
+ if ((local>=0) /*If counter is valid*/ \
+ /*and it hasn't changed while*/ \
+ /*we were checking and trying*/ \
+ /*to increment it,*/ \
+ && (InterlockedCompareExchange ( \
+ (PVOID *)(cookie), \
+ (PVOID)(local1), \
+ (PVOID)local) \
+ ==(PVOID)local)) \
+ break; /*then we obtained the access*/ \
+ } while (1) /*otherwise, we have to do it again (possibly with*/\
+ /*the other counter if writer switched it on us)*/
+
+
+/*++
+*******************************************************************
+ R e l e a s e R e a d e r A c c e s s
+
+Routine Description:
+ Releases reader access to resource protected by the lock
+Arguments:
+ lock - pointer to lock
+ cookie - lock state for subsequent stored during acquire operation
+Return Value:
+ None
+*******************************************************************
+--*/
+//VOID
+//ReleaseReaderAccess (
+// IN PRW_LOCK lock,
+// IN RWCOOKIE cookie
+// );
+#define ReleaseReaderAccess(lock,cookie) { \
+ /*If counter drops below 0, we have to signal the writer*/ \
+ if (InterlockedDecrement((PLONG)cookie)<0) { \
+ LONG res; \
+ ASSERT (*(cookie)==-1); \
+ res = KeSetEvent (&(lock)->Event, 0, FALSE); \
+ ASSERT (res==0); \
+ } \
+}
+
+/*++
+*******************************************************************
+ W a i t F o r A l l R e a d e r s
+
+Routine Description:
+ Waits for all readers that were accessing the resource prior
+ to the call to exit (New readers are not included)
+Arguments:
+ lock - pointer to lock
+Return Value:
+ None
+*******************************************************************
+--*/
+//VOID
+//WaitForAllReaders (
+// PRW_LOCK lock
+// );
+#define WaitForAllReaders(lock) { \
+ RWCOOKIE prevCtr = (lock)->CurCtr; \
+ /*Switch the counter first*/ \
+ if (prevCtr==&(lock)->Ctr1) { \
+ (lock)->Ctr2 = 0; \
+ (lock)->CurCtr = &(lock)->Ctr2; \
+ } \
+ else { \
+ ASSERT (prevCtr==&(lock)->Ctr2); \
+ (lock)->Ctr1 = 0; \
+ (lock)->CurCtr = &(lock)->Ctr1; \
+ } \
+ /* If not all readers are gone, we'll have to wait for them*/ \
+ if (InterlockedDecrement((PLONG)prevCtr)>=0) { \
+ NTSTATUS status \
+ = KeWaitForSingleObject ( \
+ &(lock)->Event, \
+ Executive, \
+ KeGetPreviousMode(),\
+ FALSE, \
+ 0); \
+ ASSERT (NT_SUCCESS(status)); \
+ ASSERT (*prevCtr==-1); \
+ } \
+}
+
+#endif
diff --git a/private/ntos/tdi/isn/fwd/send.c b/private/ntos/tdi/isn/fwd/send.c
new file mode 100644
index 000000000..35c3ea2d6
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/send.c
@@ -0,0 +1,1253 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ ntos\tdi\isn\fwd\send.c
+
+Abstract:
+ Send routines
+
+Author:
+
+ Vadim Eydelman
+
+Revision History:
+
+--*/
+
+#include "precomp.h"
+
+
+ULONG SpoofingTimeout=DEF_SPOOFING_TIMEOUT;
+LIST_ENTRY SpoofingQueue;
+KSPIN_LOCK SpoofingQueueLock;
+WORK_QUEUE_ITEM SpoofingWorker;
+BOOLEAN SpoofingWorkerActive = FALSE;
+ULONG DontSuppressNonAgentSapAdvertisements = 0;
+
+#define IsLocalSapNonAgentAdvertisement(hdr,data,ln,ifCB) ( \
+ (DontSuppressNonAgentSapAdvertisements==0) \
+ && (GETUSHORT(hdr+IPXH_DESTSOCK)==IPX_SAP_SOCKET) \
+ && (GETUSHORT(hdr+IPXH_SRCSOCK)!=IPX_SAP_SOCKET) \
+ && (ln>=IPXH_HDRSIZE+2) \
+ && (GETUSHORT(data)==2) \
+ && ((IPX_NODE_CMP(hdr+IPXH_DESTNODE,BROADCAST_NODE)==0) \
+ || (IPX_NODE_CMP(hdr+IPXH_DESTNODE,ifCB->ICB_RemoteNode)==0)) \
+)
+
+/*++
+*******************************************************************
+ D o S e n d
+
+Routine Description:
+ Prepares and sends packet. Interface lock must be help while
+ callin this routine
+Arguments:
+ dstIf - over which interface to send
+ pktTag - packet to send
+Return Value:
+ result returned by IPX
+
+*******************************************************************
+--*/
+NDIS_STATUS
+DoSend (
+ PINTERFACE_CB dstIf,
+ PPACKET_TAG pktTag,
+ KIRQL oldIRQL
+ ) {
+ NDIS_STATUS status;
+ PNDIS_PACKET pktDscr;
+ PNDIS_BUFFER bufDscr, aDscr;
+ UINT dataLen;
+ ULONG dstNet = GETULONG (pktTag->PT_Data+IPXH_DESTNET);
+
+ if (dstIf!=InternalInterface) {
+ ADAPTER_CONTEXT_TO_LOCAL_TARGET (dstIf->ICB_AdapterContext,
+ &pktTag->PT_Target);
+ }
+ else {
+ CONSTANT_ADAPTER_CONTEXT_TO_LOCAL_TARGET (
+ VIRTUAL_NET_ADAPTER_CONTEXT,
+ &pktTag->PT_Target);
+ }
+
+#if DBG
+ // Keep track of packets being processed by IPX stack
+ InsertTailList (&dstIf->ICB_InSendQueue, &pktTag->PT_QueueLink);
+#endif
+ KeReleaseSpinLock (&dstIf->ICB_Lock, oldIRQL);
+
+ if (pktTag->PT_Flags&PT_SOURCE_IF)
+ ReleaseInterfaceReference (pktTag->PT_SourceIf);
+ pktTag->SEND_RESERVED[0] = pktTag->SEND_RESERVED[1] = 0;
+ pktDscr = CONTAINING_RECORD(pktTag, NDIS_PACKET, ProtocolReserved);
+ NdisQueryPacket(pktDscr, NULL, NULL, &bufDscr, NULL);
+#if DBG
+ { // Verify packet integrity
+ PUCHAR dataPtr;
+ UINT bufLen;
+ ASSERT (NDIS_BUFFER_LINKAGE (bufDscr)==NULL);
+ NdisQueryBuffer (bufDscr, &dataPtr, &bufLen);
+ ASSERT (dataPtr==pktTag->PT_Data);
+ ASSERT (bufLen==pktTag->PT_Segment->PS_SegmentList->SL_BlockSize);
+ }
+#endif
+ // Prepare packet for IPX stack (mac header buffer goes in
+ // front and packet length adjusted to reflect the size of the data
+ dataLen = GETUSHORT(pktTag->PT_Data+IPXH_LENGTH);
+ NdisAdjustBufferLength(bufDscr, dataLen);
+ NdisChainBufferAtFront(pktDscr, pktTag->PT_MacHdrBufDscr);
+
+
+ if (EnterForwarder ()) {// To make sure that we won't unload
+ // until IPX driver has a chance to call us back
+ status = IPXSendProc (&pktTag->PT_Target, pktDscr, dataLen, 0);
+
+ if (status!=NDIS_STATUS_PENDING) {
+ LeaveForwarder (); // No callback
+
+ // Restore original packet structure
+ NdisUnchainBufferAtFront (pktDscr, &aDscr);
+#if DBG
+ // Make sure IPX stack did not mess our packet
+ ASSERT (aDscr==pktTag->PT_MacHdrBufDscr);
+ NdisQueryPacket(pktDscr, NULL, NULL, &aDscr, NULL);
+ ASSERT (aDscr==bufDscr);
+ ASSERT (NDIS_BUFFER_LINKAGE (aDscr)==NULL);
+#endif
+ // Restore original packet size
+ NdisAdjustBufferLength(bufDscr,
+ pktTag->PT_Segment->PS_SegmentList->SL_BlockSize);
+#if DBG
+ // Remove packet from temp queue
+ KeAcquireSpinLock (&pktTag->PT_InterfaceReference->ICB_Lock, &oldIRQL);
+ RemoveEntryList (&pktTag->PT_QueueLink);
+ KeReleaseSpinLock (&pktTag->PT_InterfaceReference->ICB_Lock, oldIRQL);
+#endif
+ }
+ }
+ else {
+ // We are going down, restore the packet
+ NdisUnchainBufferAtFront (pktDscr, &aDscr);
+ NdisAdjustBufferLength(bufDscr,
+ pktTag->PT_Segment->PS_SegmentList->SL_BlockSize);
+ NdisRecalculatePacketCounts (pktDscr);
+ status = STATUS_UNSUCCESSFUL;
+#if DBG
+ KeAcquireSpinLock (&pktTag->PT_InterfaceReference->ICB_Lock, &oldIRQL);
+ RemoveEntryList (&pktTag->PT_QueueLink);
+ KeReleaseSpinLock (&pktTag->PT_InterfaceReference->ICB_Lock, oldIRQL);
+#endif
+ }
+ return status;
+}
+
+
+/*++
+*******************************************************************
+ P r o c e s s S e n t P a c k e t
+
+Routine Description:
+ Process completed sent packets
+Arguments:
+ dstIf - interface over which packet was sent
+ pktTag - completed packet
+ status - result of send operation
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+ProcessSentPacket (
+ PINTERFACE_CB dstIf,
+ PPACKET_TAG pktTag,
+ NDIS_STATUS status
+ ) {
+ KIRQL oldIRQL;
+
+ // Packet processing is completed -> can take more packets
+ InterlockedIncrement (&dstIf->ICB_PendingQuota);
+
+ if (*(pktTag->PT_Data+IPXH_PKTTYPE) == IPX_NETBIOS_TYPE) {
+ // Continue processing netbios packets
+ if (status==NDIS_STATUS_SUCCESS) {
+ IpxFwdDbgPrint (DBG_NETBIOS, DBG_INFORMATION,
+ ("IpxFwd: NB Packet %08lx sent.", pktTag));
+ InterlockedIncrement (&dstIf->ICB_Stats.OutDelivers);
+ InterlockedIncrement (&dstIf->ICB_Stats.NetbiosSent);
+ }
+ else {
+ IpxFwdDbgPrint (DBG_NETBIOS, DBG_ERROR,
+ ("IpxFwd: NB Packet %08lx send failed with error: %08lx.\n",
+ pktTag, status));
+ }
+ // Queue nb packet for further processing (broadcast on all interfaces)
+ QueueNetbiosPacket (pktTag);
+ }
+ else {
+ // Destroy completed packet
+ if (status==NDIS_STATUS_SUCCESS) {
+ InterlockedIncrement (&dstIf->ICB_Stats.OutDelivers);
+ IpxFwdDbgPrint (DBG_SEND, DBG_INFORMATION,
+ ("IpxFwd: Packet %08lx sent.", pktTag));
+ }
+ else {
+ InterlockedIncrement (&dstIf->ICB_Stats.OutDiscards);
+ IpxFwdDbgPrint (DBG_SEND, DBG_ERROR,
+ ("IpxFwd: Packet %08lx send failed with error: %08lx.\n",
+ pktTag, status));
+ }
+ ReleaseInterfaceReference (dstIf);
+ if (MeasuringPerformance
+ && (pktTag->PT_PerfCounter!=0)) {
+ LARGE_INTEGER PerfCounter = KeQueryPerformanceCounter (NULL);
+ PerfCounter.QuadPart -= pktTag->PT_PerfCounter;
+ KeAcquireSpinLock (&PerfCounterLock, &oldIRQL);
+ ASSERT (PerfCounter.QuadPart<ActivityTreshhold);
+ PerfBlock.TotalPacketProcessingTime += PerfCounter.QuadPart;
+ PerfBlock.PacketCounter += 1;
+ if (PerfBlock.MaxPacketProcessingTime < PerfCounter.QuadPart)
+ PerfBlock.MaxPacketProcessingTime = PerfCounter.QuadPart;
+ KeReleaseSpinLock (&PerfCounterLock, oldIRQL);
+ }
+ FreePacket (pktTag);
+ }
+}
+
+/*++
+*******************************************************************
+ S e n d P a c k e t
+
+Routine Description:
+ Enqueues packets to be sent by IPX stack
+Arguments:
+ dstIf - over which interface to send
+ pktTag - packet to send
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+SendPacket (
+ PINTERFACE_CB dstIf,
+ PPACKET_TAG pktTag
+ ) {
+ NDIS_STATUS status;
+ KIRQL oldIRQL;
+
+
+ ASSERT (dstIf->ICB_Index!=FWD_INTERNAL_INTERFACE_INDEX);
+ // Make sure we have not exceded the quota of pending packets on the interface
+ if (InterlockedDecrement (&dstIf->ICB_PendingQuota)>=0) {
+ KeAcquireSpinLock (&dstIf->ICB_Lock, &oldIRQL);
+ // Decide what to do with the packet based on the interface state
+ switch (dstIf->ICB_Stats.OperationalState) {
+ case FWD_OPER_STATE_UP:
+ if (*(pktTag->PT_Data + IPXH_PKTTYPE) != IPX_NETBIOS_TYPE)
+ NOTHING;
+ else {
+ PUTULONG (dstIf->ICB_Network, pktTag->PT_Data+IPXH_DESTNET);
+ }
+ status = DoSend (dstIf, pktTag, oldIRQL);
+ IpxFwdDbgPrint (DBG_SEND, DBG_INFORMATION,
+ ("IpxFwd: Sent external packet %08lx on if %ld.\n",
+ pktTag, dstIf->ICB_Index));
+ break;
+ case FWD_OPER_STATE_SLEEPING:
+ if ((*(pktTag->PT_Data+IPXH_PKTTYPE)!=0)
+ || (GETUSHORT(pktTag->PT_Data+IPXH_LENGTH)!=IPXH_HDRSIZE+2)
+ || (*(pktTag->PT_Data+IPXH_HDRSIZE+1)!='?')) {
+ // Queue this packet on the interface until it is connected
+ // by Router Manager (DIM) if this is not a NCP keepalive
+ // (watchdog)
+ InsertTailList (&dstIf->ICB_ExternalQueue, &pktTag->PT_QueueLink);
+ if (!IS_IF_CONNECTING (dstIf)) {
+ // Ask for connection if interface is not in the connection
+ // queue yet
+ QueueConnectionRequest (dstIf,
+ CONTAINING_RECORD (pktTag,
+ NDIS_PACKET,
+ ProtocolReserved),
+ pktTag->PT_Data,
+ oldIRQL);
+ IpxFwdDbgPrint (DBG_DIALREQS, DBG_WARNING,
+ ("IpxFwd: Queued dd request on if %ld (ifCB:%08lx)"
+ " for packet to %02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%02x%02x"
+ " from %02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%02x%02x\n",
+ dstIf->ICB_Index, dstIf,
+ *(pktTag->PT_Data+6),*(pktTag->PT_Data+7),
+ *(pktTag->PT_Data+8),*(pktTag->PT_Data+9),
+ *(pktTag->PT_Data+10),*(pktTag->PT_Data+11),
+ *(pktTag->PT_Data+12),*(pktTag->PT_Data+13),
+ *(pktTag->PT_Data+14),*(pktTag->PT_Data+15),
+ *(pktTag->PT_Data+16),*(pktTag->PT_Data+17),
+ *(pktTag->PT_Data+18),*(pktTag->PT_Data+19),
+ *(pktTag->PT_Data+20),*(pktTag->PT_Data+21),
+ *(pktTag->PT_Data+22),*(pktTag->PT_Data+23),
+ *(pktTag->PT_Data+24),*(pktTag->PT_Data+25),
+ *(pktTag->PT_Data+26),*(pktTag->PT_Data+27),
+ *(pktTag->PT_Data+28),*(pktTag->PT_Data+29)));
+ }
+ else
+ KeReleaseSpinLock (&dstIf->ICB_Lock, oldIRQL);
+ IpxFwdDbgPrint (DBG_SEND, DBG_INFORMATION,
+ ("IpxFwd: Queued external packet %08lx on if %ld.\n",
+ pktTag, dstIf->ICB_Index));
+ if (*(pktTag->PT_Data + IPXH_PKTTYPE) != IPX_NETBIOS_TYPE)
+ NOTHING;
+ else if (!(pktTag->PT_Flags&PT_NB_DESTROY)) {
+ // If this nb packet is not to be destroyed after this
+ // send, we have to make a copy of it to send on
+ // other interfaces while the original is waiting
+ // for connection
+ PPACKET_TAG newPktTag;
+ DuplicatePacket (pktTag, newPktTag);
+ if (newPktTag!=NULL) {
+ UINT bytesCopied;
+ PNDIS_PACKET packet = CONTAINING_RECORD (pktTag,
+ NDIS_PACKET,
+ ProtocolReserved);
+ PNDIS_PACKET newPacket = CONTAINING_RECORD (newPktTag,
+ NDIS_PACKET,
+ ProtocolReserved);
+ NdisCopyFromPacketToPacket (newPacket, 0,
+ GETUSHORT(pktTag->PT_Data+IPXH_LENGTH),
+ packet, 0, &bytesCopied);
+
+ ASSERT (bytesCopied==GETUSHORT(pktTag->PT_Data+IPXH_LENGTH));
+ IpxFwdDbgPrint (DBG_NETBIOS,
+ DBG_INFORMATION,
+ ("IpxFwd: Duplicated queued nb packet"
+ " %08lx -> %08lx on if %ld.\n",
+ pktTag, newPktTag, dstIf->ICB_Index));
+ AcquireInterfaceReference (dstIf);
+ newPktTag->PT_InterfaceReference = dstIf;
+ newPktTag->PT_PerfCounter = pktTag->PT_PerfCounter;
+ QueueNetbiosPacket (newPktTag);
+ // The original copy will have to be
+ // destroyed after it is sent on the
+ // connected interface
+ pktTag->PT_Flags |= PT_NB_DESTROY;
+ }
+ }
+ status = NDIS_STATUS_PENDING;
+ break;
+ }
+ else { // Process keepalives
+ LONGLONG curTime;
+ KeQuerySystemTime ((PLARGE_INTEGER)&curTime);
+ if (((curTime-dstIf->ICB_DisconnectTime)/10000000) < SpoofingTimeout) {
+ KeReleaseSpinLock (&dstIf->ICB_Lock, oldIRQL);
+ IpxFwdDbgPrint (DBG_SPOOFING, DBG_INFORMATION,
+ ("IpxFwd: Queueing reply to keepalive from server"
+ " on if %ld (ifCB %lx)"
+ " at %02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%02x%02x.\n",
+ dstIf->ICB_Index, dstIf,
+ *(pktTag->PT_Data+IPXH_SRCNET),*(pktTag->PT_Data+IPXH_SRCNET+1),
+ *(pktTag->PT_Data+IPXH_SRCNET+2),*(pktTag->PT_Data+IPXH_SRCNET+3),
+ *(pktTag->PT_Data+IPXH_SRCNODE),*(pktTag->PT_Data+IPXH_SRCNODE+1),
+ *(pktTag->PT_Data+IPXH_SRCNODE+2),*(pktTag->PT_Data+IPXH_SRCNODE+3),
+ *(pktTag->PT_Data+IPXH_SRCNODE+4),*(pktTag->PT_Data+IPXH_SRCNODE+5),
+ *(pktTag->PT_Data+IPXH_SRCSOCK),*(pktTag->PT_Data+IPXH_SRCNODE+1)));
+ // Spoof the packet if timeout has not been exceeded
+ KeAcquireSpinLock (&SpoofingQueueLock, &oldIRQL);
+ InsertTailList (&SpoofingQueue, &pktTag->PT_QueueLink);
+ if (!SpoofingWorkerActive
+ && EnterForwarder()) {
+ SpoofingWorkerActive = TRUE;
+ ExQueueWorkItem (&SpoofingWorker, DelayedWorkQueue);
+ }
+ KeReleaseSpinLock (&SpoofingQueueLock, oldIRQL);
+ // We will actually send this packet though
+ // in other direction, so mark it as pending
+ // to prevent ProcessSentPacket to be called
+ status = NDIS_STATUS_PENDING;
+ break;
+ }
+ // else don't spoof (fall through and fail the packet)
+ }
+ case FWD_OPER_STATE_DOWN:
+ KeReleaseSpinLock (&dstIf->ICB_Lock, oldIRQL);
+ status = NDIS_STATUS_ADAPTER_NOT_READY;
+ IpxFwdDbgPrint (DBG_SEND, DBG_WARNING,
+ ("IpxFwd: Failed external packet %08lx on if %ld(down?).\n",
+ pktTag, dstIf->ICB_Index));
+ break;
+ default:
+ ASSERTMSG ("Invalid operational state ", FALSE);
+ }
+ }
+ else {
+ IpxFwdDbgPrint (DBG_SEND, DBG_WARNING,
+ ("IpxFwd: Could not send packet %08lx on if %ld (quota exceeded).\n",
+ pktTag, dstIf->ICB_Index));
+ status = NDIS_STATUS_RESOURCES;
+ }
+
+ if (status!=NDIS_STATUS_PENDING)
+ ProcessSentPacket (dstIf, pktTag, status);
+}
+
+/*++
+*******************************************************************
+ F w S e n d C o m p l e t e
+
+Routine Description:
+ Called by IPX stack when send completes asynchronously
+Arguments:
+ pktDscr - descriptor of the completed packet
+ status - result of send operation
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+IpxFwdSendComplete (
+ PNDIS_PACKET pktDscr,
+ NDIS_STATUS status
+ ) {
+ PPACKET_TAG pktTag;
+ PNDIS_BUFFER bufDscr;
+
+ pktTag = (PPACKET_TAG)pktDscr->ProtocolReserved;
+
+ NdisUnchainBufferAtFront (pktDscr, &bufDscr);
+ ASSERT (bufDscr==pktTag->PT_MacHdrBufDscr);
+
+ NdisQueryPacket(pktDscr,
+ NULL,
+ NULL,
+ &bufDscr,
+ NULL);
+ NdisAdjustBufferLength(bufDscr,
+ pktTag->PT_Segment->PS_SegmentList->SL_BlockSize);
+ NdisRecalculatePacketCounts (pktDscr);
+#if DBG
+ {
+ KIRQL oldIRQL;
+ KeAcquireSpinLock (&pktTag->PT_InterfaceReference->ICB_Lock, &oldIRQL);
+ RemoveEntryList (&pktTag->PT_QueueLink);
+ KeReleaseSpinLock (&pktTag->PT_InterfaceReference->ICB_Lock, oldIRQL);
+ }
+#endif
+ ProcessSentPacket (pktTag->PT_InterfaceReference, pktTag, status);
+ LeaveForwarder (); // Entered before calling IpxSendPacket
+}
+
+
+/*++
+*******************************************************************
+
+ F w I n t e r n a l S e n d
+
+Routine Description:
+ Filter and routes packets sent by IPX stack
+Arguments:
+ LocalTarget - the NicId and next hop router MAC address
+ Context - preferred interface on which to send
+ Packet - packet to be sent
+ ipxHdr - pointer to ipx header inside the packet
+ PacketLength - length of the packet
+ fIterate - a flag to indicate if this is a packet for the
+ iteration of which the Fwd takes responsibility
+ - typically type 20 NetBIOS frames
+Return Value:
+
+ STATUS_SUCCESS - if the preferred NIC was OK and packet passed filtering
+ STATUS_NETWORK_UNREACHABLE - if the preferred was not OK or packet failed filtering
+ STATUS_PENDING - packet was queued until connection is established
+*******************************************************************
+--*/
+NTSTATUS
+IpxFwdInternalSend (
+ IN OUT PIPX_LOCAL_TARGET LocalTarget,
+ IN ULONG Context,
+ IN PNDIS_PACKET pktDscr,
+ IN PUCHAR ipxHdr,
+ IN PUCHAR data,
+ IN ULONG PacketLength,
+ IN BOOLEAN fIterate
+ ) {
+ PINTERFACE_CB dstIf = NULL, // Initialized to indicate
+ // first path through the iteration
+ // as well as the fact the we do not
+ // know it initially
+ stDstIf; // Static destination for
+ // NetBIOS names
+ PFWD_ROUTE fwRoute = NULL;
+ ULONG dstNet;
+ USHORT dstSock;
+ NTSTATUS status;
+
+ if (!EnterForwarder())
+ return STATUS_NETWORK_UNREACHABLE;
+
+ if (IS_IF_ENABLED(InternalInterface)
+ && ((*(ipxHdr+IPXH_PKTTYPE) != IPX_NETBIOS_TYPE)
+ || InternalInterface->ICB_NetbiosAccept)) {
+
+ do { // Big loop used to iterate over interfaces
+ status = STATUS_SUCCESS; // Assume success
+ if (!fIterate) {
+ dstNet = GETULONG (ipxHdr+IPXH_DESTNET);
+
+ if (Context!=INVALID_CONTEXT_VALUE) {
+ if (Context!=VIRTUAL_NET_FORWARDER_CONTEXT) {
+ // IPX driver supplied interface context, just verify that it
+ // exists and can be used to reach the destination network
+ dstIf = InterfaceContextToReference ((PVOID)Context,
+ LocalTarget->NicId);
+ }
+ else {
+ dstIf = InternalInterface;
+ AcquireInterfaceReference (dstIf);
+ }
+ if (dstIf!=NULL) {
+ // It does exist
+ // First process direct connections
+ if ((dstNet==0)
+ || (dstNet==dstIf->ICB_Network)) {
+ NOTHING;
+ }
+ else { // Network is not connected directly
+ PINTERFACE_CB dstIf2;
+ // Verify the route
+ dstIf2 = FindDestination (dstNet,
+ ipxHdr+IPXH_DESTNODE,
+ &fwRoute);
+ if (dstIf==dstIf2) {
+ // Route OK, release the extra interface reference
+ ReleaseInterfaceReference (dstIf2);
+ }
+ else {
+ // Route not OK, release interface/route references
+ InterlockedIncrement (&InternalInterface->ICB_Stats.InNoRoutes);
+ IpxFwdDbgPrint (DBG_INT_SEND, DBG_WARNING,
+ ("IpxFwd: Failed direct internal send on"
+ " if %ld to %08lx:%02x%02x%02x%02x%02x%02x"
+ " (no route).\n",
+ dstIf->ICB_Index, dstNet,
+ LocalTarget->MacAddress[0],
+ LocalTarget->MacAddress[1],
+ LocalTarget->MacAddress[2],
+ LocalTarget->MacAddress[3],
+ LocalTarget->MacAddress[4],
+ LocalTarget->MacAddress[5]));
+ if (dstIf2!=NULL) {
+ ReleaseInterfaceReference (dstIf2);
+ }
+ status = STATUS_NETWORK_UNREACHABLE;
+ break;
+ }
+ }
+ }
+ else {
+ InterlockedIncrement (&InternalInterface->ICB_Stats.InDiscards);
+ IpxFwdDbgPrint (DBG_INT_SEND, DBG_WARNING,
+ ("IpxFwd: Invalid interface context (%08lx)"
+ " from IPX driver on internal send to"
+ " %08lx:%02x%02x%02x%02x%02x%02x.\n",
+ Context, dstNet,
+ LocalTarget->MacAddress[0],
+ LocalTarget->MacAddress[1],
+ LocalTarget->MacAddress[2],
+ LocalTarget->MacAddress[3],
+ LocalTarget->MacAddress[4],
+ LocalTarget->MacAddress[5]));
+ status = STATUS_NO_SUCH_DEVICE;
+ break;
+ }
+ }
+ else {// No interface context supplied by IPX driver, have to find the route
+ dstIf = FindDestination (dstNet, ipxHdr+IPXH_DESTNODE,
+ &fwRoute);
+ if (dstIf!=NULL)
+ NOTHING;
+ else {
+ InterlockedIncrement (&InternalInterface->ICB_Stats.InNoRoutes);
+ IpxFwdDbgPrint (DBG_INT_SEND, DBG_WARNING,
+ ("IpxFwd: Failed internal send because no route to"
+ " %08lx:%02x%02x%02x%02x%02x%02x exists.\n",
+ LocalTarget->MacAddress[0],
+ LocalTarget->MacAddress[1],
+ LocalTarget->MacAddress[2],
+ LocalTarget->MacAddress[3],
+ LocalTarget->MacAddress[4],
+ LocalTarget->MacAddress[5]));
+ status = STATUS_NETWORK_UNREACHABLE;
+ break;
+ }
+ }
+ InterlockedIncrement (&InternalInterface->ICB_Stats.InDelivers);
+ }
+ else { // Iterative sends
+ dstNet = 0; // Don't care, it must be a local send
+ if (*(ipxHdr+IPXH_PKTTYPE) == IPX_NETBIOS_TYPE) {
+ if (dstIf==NULL) { // First time through internal loop
+ dstSock = GETUSHORT (ipxHdr+IPXH_DESTSOCK);
+
+ // See if we can get a static route for this packet
+ if (dstSock==IPX_NETBIOS_SOCKET)
+ stDstIf = FindNBDestination (data+(NB_NAME-IPXH_HDRSIZE));
+ else if (dstSock==IPX_SMB_NAME_SOCKET)
+ stDstIf = FindNBDestination (data+(SMB_NAME-IPXH_HDRSIZE));
+ else
+ stDstIf = NULL;
+ }
+
+ if ((Context==INVALID_CONTEXT_VALUE) && (dstIf==NULL)) {
+ // First time through the loop, increment counters
+ InterlockedIncrement (&InternalInterface->ICB_Stats.InDelivers);
+ InterlockedIncrement (&InternalInterface->ICB_Stats.NetbiosSent);
+
+ if (stDstIf!=NULL) {
+ dstIf = stDstIf;
+ IpxFwdDbgPrint (DBG_NETBIOS, DBG_INFORMATION,
+ ("IpxFwd: Allowed internal NB broadcast (1st iteration) on if %d (%lx)"
+ " to static name %.16s.\n",
+ dstIf->ICB_Index, dstIf,
+ (dstSock==IPX_NETBIOS_SOCKET)
+ ? data+(NB_NAME-IPXH_HDRSIZE)
+ : ((dstSock==IPX_SMB_NAME_SOCKET)
+ ? data+(SMB_NAME-IPXH_HDRSIZE)
+ : "Not a name frame")
+ ));
+ }
+ else { // No static route
+ dstIf = GetNextInterfaceReference (NULL);
+ if (dstIf!=NULL)
+ IpxFwdDbgPrint (DBG_NETBIOS, DBG_INFORMATION,
+ ("IpxFwd: Allowed internal nb broadcast (1st iteration) on if %d (%lx),"
+ " to name %.16s.\n",
+ dstIf->ICB_Index, dstIf,
+ (dstSock==IPX_NETBIOS_SOCKET)
+ ? data+(NB_NAME-IPXH_HDRSIZE)
+ : ((dstSock==IPX_SMB_NAME_SOCKET)
+ ? data+(SMB_NAME-IPXH_HDRSIZE)
+ : "Not a name frame")
+ ));
+ else {
+ IpxFwdDbgPrint (DBG_NETBIOS, DBG_INFORMATION,
+ ("IpxFwd: Nb broadcast no destinations"
+ " to name %.16s.\n",
+ (dstSock==IPX_NETBIOS_SOCKET)
+ ? data+(NB_NAME-IPXH_HDRSIZE)
+ : ((dstSock==IPX_SMB_NAME_SOCKET)
+ ? data+(SMB_NAME-IPXH_HDRSIZE)
+ : "Not a name frame")
+ ));
+ status = STATUS_NETWORK_UNREACHABLE;
+ break;
+ }
+ }
+ }
+ else {
+ // N-th iteration
+ if (stDstIf==NULL) {
+ if (dstIf==NULL)
+ dstIf = InterfaceContextToReference ((PVOID)Context,
+ LocalTarget->NicId);
+ dstIf = GetNextInterfaceReference (dstIf);
+ if (dstIf!=NULL) {
+ IpxFwdDbgPrint (DBG_NETBIOS, DBG_INFORMATION,
+ ("IpxFwd: Allowed internal NB broadcast (1+ iteration)"
+ " on if %d (%lx, ctx: %08lx, nic: %d)"
+ " to name %.16s.\n",
+ dstIf->ICB_Index, dstIf,
+ Context, LocalTarget->NicId,
+ (dstSock==IPX_NETBIOS_SOCKET)
+ ? data+(NB_NAME-IPXH_HDRSIZE)
+ : ((dstSock==IPX_SMB_NAME_SOCKET)
+ ? data+(SMB_NAME-IPXH_HDRSIZE)
+ : "Not a name frame")
+ ));
+ }
+ else {
+ IpxFwdDbgPrint (DBG_NETBIOS, DBG_INFORMATION,
+ ("IpxFwd: NB broadcast no more iterations"
+ " for ctx: %08lx, nic: %d"
+ " to name %.16s.\n",
+ Context, LocalTarget->NicId,
+ (dstSock==IPX_NETBIOS_SOCKET)
+ ? data+(NB_NAME-IPXH_HDRSIZE)
+ : ((dstSock==IPX_SMB_NAME_SOCKET)
+ ? data+(SMB_NAME-IPXH_HDRSIZE)
+ : "Not a name frame")
+ ));
+ status = STATUS_NETWORK_UNREACHABLE;
+ break;
+ }
+ }
+ else {
+ IpxFwdDbgPrint (DBG_NETBIOS, DBG_INFORMATION,
+ ("IpxFwd: Static NB broadcast (1+ iteration)"
+ " on if %d (%lx, ctx: %08lx, nic: %d)"
+ " to name %.16s.\n",
+ stDstIf->ICB_Index, stDstIf,
+ Context, LocalTarget->NicId,
+ (dstSock==IPX_NETBIOS_SOCKET)
+ ? data+(NB_NAME-IPXH_HDRSIZE)
+ : ((dstSock==IPX_SMB_NAME_SOCKET)
+ ? data+(SMB_NAME-IPXH_HDRSIZE)
+ : "Not a name frame")
+ ));
+ ReleaseInterfaceReference (stDstIf);
+ status = STATUS_NETWORK_UNREACHABLE;
+ break;
+ }
+ }
+ }
+ else {
+ if ((dstIf==NULL)
+ && (Context!=INVALID_CONTEXT_VALUE))
+ dstIf = InterfaceContextToReference ((PVOID)Context,
+ LocalTarget->NicId);
+ dstIf = GetNextInterfaceReference (dstIf);
+ if (dstIf!=NULL) {
+ IpxFwdDbgPrint (DBG_NETBIOS, DBG_INFORMATION,
+ ("IpxFwd: Allowed internal iterative send"
+ " on if %d (%lx, ctx: %08lx, nic: %d)"
+ " to %02x%02x%02x%02x%02x%02x.\n",
+ dstIf->ICB_Index, dstIf,
+ Context, LocalTarget->NicId,
+ LocalTarget->MacAddress[0],
+ LocalTarget->MacAddress[1],
+ LocalTarget->MacAddress[2],
+ LocalTarget->MacAddress[3],
+ LocalTarget->MacAddress[4],
+ LocalTarget->MacAddress[5]));
+
+ }
+ else {
+ IpxFwdDbgPrint (DBG_NETBIOS, DBG_INFORMATION,
+ ("IpxFwd: No destinations to internal iterative send"
+ " for ctx: %08lx, nic: %d"
+ " to %02x%02x%02x%02x%02x%02x.\n",
+ Context, LocalTarget->NicId,
+ LocalTarget->MacAddress[0],
+ LocalTarget->MacAddress[1],
+ LocalTarget->MacAddress[2],
+ LocalTarget->MacAddress[3],
+ LocalTarget->MacAddress[4],
+ LocalTarget->MacAddress[5]));
+ status = STATUS_NETWORK_UNREACHABLE;
+ break;
+ }
+ }
+
+ } // End iterative send processing
+
+ // We were able to find a destination interface
+ if (IS_IF_ENABLED (dstIf)
+ && ((*(ipxHdr+IPXH_PKTTYPE) != IPX_NETBIOS_TYPE)
+ || (dstIf->ICB_NetbiosDeliver==FWD_NB_DELIVER_ALL)
+ || ((dstIf->ICB_NetbiosDeliver==FWD_NB_DELIVER_IF_UP)
+ && (dstIf->ICB_Stats.OperationalState==FWD_OPER_STATE_UP))
+ || ((stDstIf!=NULL)
+ && (dstIf->ICB_NetbiosDeliver==FWD_NB_DELIVER_STATIC)))) {
+ KIRQL oldIRQL;
+ FILTER_ACTION action;
+
+ // In/Out filter check and statistics update
+
+ action = FltFilter (ipxHdr, IPXH_HDRSIZE,
+ InternalInterface->ICB_FilterInContext,
+ dstIf->ICB_FilterOutContext);
+ if (action==FILTER_PERMIT) {
+ NOTHING;
+ }
+ else {
+ InterlockedIncrement (&dstIf->ICB_Stats.OutFiltered);
+ status = STATUS_NETWORK_UNREACHABLE;
+ break;
+ }
+
+ KeAcquireSpinLock (&dstIf->ICB_Lock, &oldIRQL);
+ // All set, try to send now
+ switch (dstIf->ICB_Stats.OperationalState) {
+ case FWD_OPER_STATE_UP:
+ // Interface is up, let it go right away
+ // Set NIC ID
+ if (dstIf!=InternalInterface) {
+ ADAPTER_CONTEXT_TO_LOCAL_TARGET (
+ dstIf->ICB_AdapterContext,
+ LocalTarget);
+ }
+ else {
+ CONSTANT_ADAPTER_CONTEXT_TO_LOCAL_TARGET (
+ VIRTUAL_NET_ADAPTER_CONTEXT,
+ LocalTarget);
+ }
+ // Set destination node
+ if (IsLocalSapNonAgentAdvertisement (ipxHdr,data,PacketLength,dstIf)) {
+ // Loop back sap ads from non-sap socket
+ IPX_NODE_CPY (&LocalTarget->MacAddress,
+ dstIf->ICB_LocalNode);
+ }
+ else if ((dstNet==0) || (dstNet==dstIf->ICB_Network)) {
+ // Direct connection: send to destination specified
+ // in the header
+ IPX_NODE_CPY (LocalTarget->MacAddress,
+ ipxHdr+IPXH_DESTNODE);
+ }
+ else { // Indirect connection: send to next hop router
+ if (dstIf->ICB_InterfaceType==FWD_IF_PERMANENT) {
+ ASSERT (fwRoute!=NULL);
+ IPX_NODE_CPY (LocalTarget->MacAddress,
+ fwRoute->FR_NextHopAddress);
+ }
+ else {
+ // Only one peer on the other side
+ IPX_NODE_CPY (LocalTarget->MacAddress,
+ dstIf->ICB_RemoteNode);
+ }
+ }
+ KeReleaseSpinLock (&dstIf->ICB_Lock, oldIRQL);
+ // Update statistics
+ InterlockedIncrement (
+ &dstIf->ICB_Stats.OutDelivers);
+ if (*(ipxHdr+IPXH_PKTTYPE)==IPX_NETBIOS_TYPE)
+ InterlockedIncrement (
+ &dstIf->ICB_Stats.NetbiosSent);
+
+ IpxFwdDbgPrint (DBG_INT_SEND, DBG_INFORMATION,
+ ("IpxFwd: Allowed internal send:"
+ " %ld-%08lx:%02x%02x%02x%02x%02x%02x.\n",
+ dstIf->ICB_Index, dstNet,
+ LocalTarget->MacAddress[0],
+ LocalTarget->MacAddress[1],
+ LocalTarget->MacAddress[2],
+ LocalTarget->MacAddress[3],
+ LocalTarget->MacAddress[4],
+ LocalTarget->MacAddress[5]));
+ // status = STATUS_SUCCESS; // Let it go
+ break;
+ case FWD_OPER_STATE_SLEEPING:
+ // Interface is disconnected, queue the packet and try to connecte
+ if ((*(ipxHdr+IPXH_PKTTYPE)!=0)
+ || (*(ipxHdr+IPXH_LENGTH)!=IPXH_HDRSIZE+2)
+ || (*(data+1)!='?')) {
+ // Not a keep-alive packet,
+ if (((*(ipxHdr+IPXH_PKTTYPE)!=IPX_NETBIOS_TYPE))
+ || (dstIf->ICB_NetbiosDeliver!=FWD_NB_DELIVER_IF_UP)) {
+ // Not a netbios broadcast or we are allowed to connect
+ // the interface to deliver netbios broadcasts
+ if (InterlockedDecrement (&dstIf->ICB_PendingQuota)>=0) {
+ PINTERNAL_PACKET_TAG pktTag;
+ // Create a queue element to enqueue the packet
+ pktTag = (PINTERNAL_PACKET_TAG)ExAllocatePoolWithTag (
+ NonPagedPool,
+ sizeof (INTERNAL_PACKET_TAG),
+ FWD_POOL_TAG);
+ if (pktTag!=NULL) {
+ pktTag->IPT_Packet = pktDscr;
+ pktTag->IPT_Length = PacketLength;
+ pktTag->IPT_DataPtr = ipxHdr;
+ // Save next hop address if after connection is
+ // established we determine that destination net
+ // is not connected directly
+ if (fwRoute!=NULL)
+ IPX_NODE_CPY (pktTag->IPT_Target.MacAddress,
+ fwRoute->FR_NextHopAddress);
+ AcquireInterfaceReference (dstIf); // To make sure interface
+ // block won't go away until we are done with
+ // the packet
+ pktTag->IPT_InterfaceReference = dstIf;
+ InsertTailList (&dstIf->ICB_InternalQueue,
+ &pktTag->IPT_QueueLink);
+ if (!IS_IF_CONNECTING (dstIf)) {
+ QueueConnectionRequest (dstIf, pktDscr, ipxHdr, oldIRQL);
+ IpxFwdDbgPrint (DBG_DIALREQS, DBG_WARNING,
+ ("IpxFwd: Queued dd request on if %ld (ifCB:%08lx)"
+ " for internal packet"
+ " to %02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%02x%02x"
+ " from socket:%02x%02x\n",
+ dstIf->ICB_Index, dstIf,
+ *(ipxHdr+6),*(ipxHdr+7),
+ *(ipxHdr+8),*(ipxHdr+9),
+ *(ipxHdr+10),*(ipxHdr+11),
+ *(ipxHdr+12),*(ipxHdr+13),
+ *(ipxHdr+14),*(ipxHdr+15),
+ *(ipxHdr+16),*(ipxHdr+17),
+ *(ipxHdr+28),*(ipxHdr+29)));
+ }
+ else
+ KeReleaseSpinLock (&dstIf->ICB_Lock, oldIRQL);
+ IpxFwdDbgPrint (DBG_INT_SEND, DBG_INFORMATION,
+ ("IpxFwd: Queueing internal send packet %08lx on if %ld.\n",
+ pktTag, dstIf->ICB_Index));
+ status = STATUS_PENDING;
+ break;
+ }
+ else {
+ IpxFwdDbgPrint (DBG_INT_SEND, DBG_ERROR,
+ ("IpxFwd: Could not allocate"
+ " internal packet tag.\n"));
+ }
+ }
+ InterlockedIncrement (&dstIf->ICB_PendingQuota);
+ }
+ else {
+ IpxFwdDbgPrint (DBG_NETBIOS, DBG_WARNING,
+ ("IpxFwd: Droped internal NB packet"
+ " because FWD_NB_DELIVER_IF_UP.\n"));
+ }
+ }
+ else { // Process keep-alives
+ LONGLONG curTime;
+ KeQuerySystemTime ((PLARGE_INTEGER)&curTime);
+ if (((curTime-dstIf->ICB_DisconnectTime)/10000000) < SpoofingTimeout) {
+ PPACKET_TAG pktTag;
+ // Spoofing timeout has not been exceeded,
+ // Create a reply packet
+ AllocatePacket (WanPacketListId,
+ WanPacketListId,
+ pktTag);
+ if (pktTag!=NULL) {
+ KeReleaseSpinLock (&dstIf->ICB_Lock, oldIRQL);
+ PUTUSHORT (0xFFFF, pktTag->PT_Data+IPXH_CHECKSUM);
+ PUTUSHORT (IPXH_HDRSIZE+2, pktTag->PT_Data+IPXH_LENGTH);
+ *(pktTag->PT_Data+IPXH_XPORTCTL) = 0;
+ *(pktTag->PT_Data+IPXH_PKTTYPE) = 0;
+ memcpy (pktTag->PT_Data+IPXH_DESTADDR,
+ ipxHdr+IPXH_SRCADDR,
+ 12);
+ memcpy (pktTag->PT_Data+IPXH_SRCADDR,
+ ipxHdr+IPXH_DESTADDR,
+ 12);
+ *(pktTag->PT_Data+IPXH_HDRSIZE) = *data;
+ *(pktTag->PT_Data+IPXH_HDRSIZE+1) = 'Y';
+ // Destination for this packet will have to
+ // be the first active LAN adapter in the system
+ // SHOULD BE REMOVED WHEN LOOPBACK SUPPORT US ADDED BY IPX
+
+ pktTag->PT_InterfaceReference = NULL;
+ IpxFwdDbgPrint (DBG_SPOOFING, DBG_INFORMATION,
+ ("IpxFwd: Queueing reply to keepalive from internal server"
+ " at %02x%02x.\n",*(ipxHdr+IPXH_DESTSOCK),*(ipxHdr+IPXH_DESTSOCK+1)));
+ // Enqueue to spoofing queue to be sent back
+ // to the server
+ KeAcquireSpinLock (&SpoofingQueueLock, &oldIRQL);
+ InsertTailList (&SpoofingQueue, &pktTag->PT_QueueLink);
+ // Start worker if not running already
+ if (!SpoofingWorkerActive
+ && EnterForwarder()) {
+ SpoofingWorkerActive = TRUE;
+ ExQueueWorkItem (&SpoofingWorker, DelayedWorkQueue);
+ }
+ KeReleaseSpinLock (&SpoofingQueueLock, oldIRQL);
+ status = STATUS_DROP_SILENTLY;
+ break;
+ }
+ else {
+ IpxFwdDbgPrint (DBG_SPOOFING, DBG_ERROR,
+ ("IpxFwd: Could not allocate"
+ " packet tag for spoofing.\n"));
+ }
+ }
+ else {
+ IpxFwdDbgPrint (DBG_SPOOFING, DBG_WARNING,
+ ("IpxFwd: Internal spoofing"
+ " timeout exceded.\n"));
+ }
+ }
+ case FWD_OPER_STATE_DOWN:
+ // Interface down or send failed
+ KeReleaseSpinLock (&dstIf->ICB_Lock, oldIRQL);
+ if (*(ipxHdr+IPXH_PKTTYPE)!=IPX_NETBIOS_TYPE)
+ InterlockedIncrement (
+ &dstIf->ICB_Stats.OutDiscards);
+ IpxFwdDbgPrint (DBG_INT_SEND, DBG_WARNING,
+ ("IpxFwd: Internal send not allowed"
+ " on if %ld (down?).\n", dstIf->ICB_Index));
+ status = STATUS_NETWORK_UNREACHABLE;
+ break;
+ default:
+ ASSERTMSG ("Invalid operational state ", FALSE);
+ }
+ }
+ else {// Interface is disabled
+ if (*(ipxHdr+IPXH_PKTTYPE)!=IPX_NETBIOS_TYPE)
+ InterlockedIncrement (&dstIf->ICB_Stats.OutDiscards);
+ IpxFwdDbgPrint (DBG_INT_SEND, DBG_WARNING,
+ ("IpxFwd: Internal send not allowed"
+ " on because dst if (or Netbios deliver on it) %ld (ifCB: %08lx) is disabled.\n",
+ dstIf->ICB_Index, dstIf));
+ status = STATUS_NETWORK_UNREACHABLE;
+ }
+
+
+ }
+ while (fIterate && (status!=STATUS_SUCCESS) && (status!=STATUS_PENDING));
+
+ if (dstIf!=NULL)
+ ReleaseInterfaceReference (dstIf);
+ if (fwRoute!=NULL)
+ ReleaseRouteReference (fwRoute);
+ }
+ else { // Internal interface is disabled
+ IpxFwdDbgPrint (DBG_INT_SEND, DBG_WARNING,
+ ("IpxFwd: Internal send not allowed"
+ " because internal if (or Netbios accept on it) is disabled.\n"));
+ InterlockedIncrement (
+ &InternalInterface->ICB_Stats.InDiscards);
+ status = STATUS_NETWORK_UNREACHABLE;
+ }
+
+ LeaveForwarder ();
+ return status;
+}
+
+
+/*++
+*******************************************************************
+
+ P r o c e s s I n t e r n a l Q u e u e
+
+Routine Description:
+ Processes packets in the interface internal queue.
+ Called when connection request completes
+Arguments:
+ dstIf - interface to process
+Return Value:
+ None
+*******************************************************************
+--*/
+VOID
+ProcessInternalQueue (
+ PINTERFACE_CB dstIf
+ ) {
+ KIRQL oldIRQL;
+ LIST_ENTRY tempQueue;
+
+ KeAcquireSpinLock (&dstIf->ICB_Lock, &oldIRQL);
+ InsertHeadList (&dstIf->ICB_InternalQueue, &tempQueue);
+ RemoveEntryList (&dstIf->ICB_InternalQueue);
+ InitializeListHead (&dstIf->ICB_InternalQueue);
+ KeReleaseSpinLock (&dstIf->ICB_Lock, oldIRQL);
+
+ while (!IsListEmpty (&tempQueue)) {
+ PINTERNAL_PACKET_TAG pktTag;
+ PLIST_ENTRY cur;
+ NTSTATUS status;
+
+ cur = RemoveHeadList (&tempQueue);
+ pktTag = CONTAINING_RECORD (cur, INTERNAL_PACKET_TAG, IPT_QueueLink);
+ InterlockedIncrement (&dstIf->ICB_PendingQuota);
+
+ KeAcquireSpinLock (&dstIf->ICB_Lock, &oldIRQL);
+ if (IS_IF_ENABLED(dstIf)
+ && (dstIf->ICB_Stats.OperationalState==FWD_OPER_STATE_UP)) {
+ IPX_NODE_CPY (pktTag->IPT_Target.MacAddress,
+ dstIf->ICB_RemoteNode);
+ ADAPTER_CONTEXT_TO_LOCAL_TARGET (
+ dstIf->ICB_AdapterContext,
+ &pktTag->IPT_Target);
+ KeReleaseSpinLock (&dstIf->ICB_Lock, oldIRQL);
+ InterlockedIncrement (&dstIf->ICB_Stats.OutDelivers);
+ if (*(pktTag->IPT_DataPtr + IPXH_PKTTYPE) == IPX_NETBIOS_TYPE) {
+ InterlockedIncrement (&dstIf->ICB_Stats.NetbiosSent);
+ }
+ status = STATUS_SUCCESS;
+ }
+ else {
+ KeReleaseSpinLock (&dstIf->ICB_Lock, oldIRQL);
+ InterlockedIncrement (&dstIf->ICB_Stats.OutDiscards);
+ status = STATUS_NETWORK_UNREACHABLE;
+ }
+
+ IPXInternalSendCompletProc (&pktTag->IPT_Target,
+ pktTag->IPT_Packet,
+ pktTag->IPT_Length,
+ status);
+ IpxFwdDbgPrint (DBG_INT_SEND,
+ NT_SUCCESS (status) ? DBG_INFORMATION : DBG_WARNING,
+ ("IpxFwd: Returned internal packet %08lx"
+ " for send on if %ld with status %08lx.\n",
+ pktTag, dstIf->ICB_Index, status));
+ ReleaseInterfaceReference (pktTag->IPT_InterfaceReference);
+ ExFreePool (pktTag);
+ }
+}
+
+
+
+/*++
+*******************************************************************
+
+ P r o c e s s E x t e r n a l Q u e u e
+
+Routine Description:
+ Processes packets in the interface external queue.
+ Called when connection request completes
+Arguments:
+ dstIf - interface to process
+Return Value:
+ None
+*******************************************************************
+--*/
+VOID
+ProcessExternalQueue (
+ PINTERFACE_CB dstIf
+ ) {
+ KIRQL oldIRQL;
+ LIST_ENTRY tempQueue;
+
+ KeAcquireSpinLock (&dstIf->ICB_Lock, &oldIRQL);
+ InsertHeadList (&dstIf->ICB_ExternalQueue, &tempQueue);
+ RemoveEntryList (&dstIf->ICB_ExternalQueue);
+ InitializeListHead (&dstIf->ICB_ExternalQueue);
+ KeReleaseSpinLock (&dstIf->ICB_Lock, oldIRQL);
+
+ while (!IsListEmpty (&tempQueue)) {
+ PPACKET_TAG pktTag;
+ PLIST_ENTRY cur;
+ NDIS_STATUS status;
+
+ cur = RemoveHeadList (&tempQueue);
+ pktTag = CONTAINING_RECORD (cur, PACKET_TAG, PT_QueueLink);
+
+ KeAcquireSpinLock (&dstIf->ICB_Lock, &oldIRQL);
+ if (IS_IF_ENABLED(dstIf)
+ && (dstIf->ICB_Stats.OperationalState==FWD_OPER_STATE_UP)) {
+ IPX_NODE_CPY (pktTag->PT_Target.MacAddress,
+ dstIf->ICB_RemoteNode);
+ if (*(pktTag->PT_Data + IPXH_PKTTYPE) == IPX_NETBIOS_TYPE) {
+ PUTULONG (dstIf->ICB_Network, pktTag->PT_Data+IPXH_DESTNET);
+ }
+ status = DoSend (dstIf, pktTag, oldIRQL);
+ IpxFwdDbgPrint (DBG_SEND, DBG_INFORMATION,
+ ("IpxFwd: Sent queued external packet %08lx if %ld.\n",
+ pktTag, dstIf->ICB_Index));
+ }
+ else {
+ KeReleaseSpinLock (&dstIf->ICB_Lock, oldIRQL);
+ IpxFwdDbgPrint (DBG_SEND, DBG_WARNING,
+ ("IpxFwd: Dropped queued external packet %08lx on dead if %ld.\n",
+ pktTag, dstIf->ICB_Index));
+ status = STATUS_UNSUCCESSFUL;
+ }
+
+ if (status!=STATUS_PENDING)
+ ProcessSentPacket (dstIf, pktTag, status);
+ }
+}
+
+
+/*++
+*******************************************************************
+
+ S p o o f e r
+
+Routine Description:
+ Processes packets in spoofing queue
+Arguments:
+ None
+Return Value:
+ None
+*******************************************************************
+--*/
+VOID
+Spoofer (
+ PVOID Context
+ ) {
+ KIRQL oldIRQL;
+ NTSTATUS status;
+ UNREFERENCED_PARAMETER (Context);
+
+ KeAcquireSpinLock (&SpoofingQueueLock, &oldIRQL);
+ // Keep going till queue is empty
+ while (!IsListEmpty (&SpoofingQueue)) {
+ PINTERFACE_CB dstIf;
+ PPACKET_TAG pktTag = CONTAINING_RECORD (SpoofingQueue.Flink,
+ PACKET_TAG,
+ PT_QueueLink);
+ RemoveEntryList (&pktTag->PT_QueueLink);
+ KeReleaseSpinLock (&SpoofingQueueLock, oldIRQL);
+ dstIf = pktTag->PT_InterfaceReference;
+ if (dstIf==NULL) {
+ // Replies for internal server require first active LAN adapter
+ // SHOULD BE REMOVED WHEN LOOPBACK SUPPORT US ADDED BY IPX
+ while ((dstIf=GetNextInterfaceReference (dstIf))!=NULL) {
+ KeAcquireSpinLock (&dstIf->ICB_Lock, &oldIRQL);
+ if (IS_IF_ENABLED (dstIf)
+ && (dstIf->ICB_Stats.OperationalState==FWD_OPER_STATE_UP)
+ && (dstIf->ICB_InterfaceType==FWD_IF_PERMANENT)) {
+ pktTag->PT_InterfaceReference = dstIf;
+ IPX_NODE_CPY (&pktTag->PT_Target.MacAddress, dstIf->ICB_LocalNode);
+ status = DoSend (dstIf, pktTag, oldIRQL); // releases spin lock
+ if (status!=STATUS_PENDING)
+ ProcessSentPacket (dstIf, pktTag, status);
+ break;
+ }
+ else
+ KeReleaseSpinLock (&dstIf->ICB_Lock, oldIRQL);
+ }
+ if (dstIf==NULL) {
+ FreePacket (pktTag);
+ }
+
+ }
+ else { // Reply for external server, interface is already known
+ UCHAR addr[12];
+ FILTER_ACTION action;
+ pktTag->PT_Flags &= (~PT_SOURCE_IF);
+
+ // Switch source and destination
+ memcpy (addr, pktTag->PT_Data+IPXH_DESTADDR, 12);
+ memcpy (pktTag->PT_Data+IPXH_DESTADDR,
+ pktTag->PT_Data+IPXH_SRCADDR, 12);
+ memcpy (pktTag->PT_Data+IPXH_SRCADDR, addr, 12);
+ // Say yes in reply
+ *(pktTag->PT_Data+IPXH_HDRSIZE+1) = 'Y';
+
+ action = FltFilter (pktTag->PT_Data,
+ GETUSHORT (pktTag->PT_Data+IPXH_LENGTH),
+ dstIf->ICB_FilterInContext,
+ pktTag->PT_SourceIf->ICB_FilterOutContext);
+ if (action==FILTER_PERMIT) {
+
+ // Release destination if and use source as destination
+ ReleaseInterfaceReference (dstIf);
+ dstIf = pktTag->PT_InterfaceReference = pktTag->PT_SourceIf;
+ // Send the packet if we can
+ KeAcquireSpinLock (&dstIf->ICB_Lock, &oldIRQL);
+ if (IS_IF_ENABLED (dstIf)
+ && (dstIf->ICB_Stats.OperationalState==FWD_OPER_STATE_UP)) {
+ status = DoSend (dstIf, pktTag, oldIRQL);
+ if (status!=STATUS_PENDING)
+ ProcessSentPacket (dstIf, pktTag, status);
+ }
+ else {
+ KeReleaseSpinLock (&dstIf->ICB_Lock, oldIRQL);
+ InterlockedIncrement (&dstIf->ICB_Stats.OutDiscards);
+ ReleaseInterfaceReference (dstIf);
+ FreePacket (pktTag);
+ }
+ }
+ else {
+ if (action==FILTER_DENY_OUT)
+ InterlockedIncrement (&pktTag->PT_SourceIf->ICB_Stats.OutFiltered);
+ else {
+ ASSERT (action==FILTER_DENY_IN);
+ InterlockedIncrement (&dstIf->ICB_Stats.InFiltered);
+ }
+ ReleaseInterfaceReference (dstIf);
+ ReleaseInterfaceReference (pktTag->PT_SourceIf);
+ FreePacket (pktTag);
+ }
+ }
+ KeAcquireSpinLock (&SpoofingQueueLock, &oldIRQL);
+ } // end while
+ SpoofingWorkerActive = FALSE;
+ KeReleaseSpinLock (&SpoofingQueueLock, oldIRQL);
+ LeaveForwarder ();
+}
+
+
diff --git a/private/ntos/tdi/isn/fwd/send.h b/private/ntos/tdi/isn/fwd/send.h
new file mode 100644
index 000000000..e46651e13
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/send.h
@@ -0,0 +1,220 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ ntos\tdi\isn\fwd\send.c
+
+Abstract:
+ Send routines
+
+Author:
+
+ Vadim Eydelman
+
+Revision History:
+
+--*/
+#ifndef IPXFWD_SEND
+#define IPXFWD_SEND
+
+typedef struct _INTERNAL_PACKET_TAG {
+ LIST_ENTRY IPT_QueueLink;
+ PNDIS_PACKET IPT_Packet;
+ PUCHAR IPT_DataPtr;
+ ULONG IPT_Length;
+ PINTERFACE_CB IPT_InterfaceReference;
+ IPX_LOCAL_TARGET IPT_Target;
+} INTERNAL_PACKET_TAG, *PINTERNAL_PACKET_TAG;
+
+
+#define DEF_SPOOFING_TIMEOUT (120*60) // Seconds
+extern ULONG SpoofingTimeout;
+extern LIST_ENTRY SpoofingQueue;
+extern KSPIN_LOCK SpoofingQueueLock;
+extern WORK_QUEUE_ITEM SpoofingWorker;
+extern BOOLEAN SpoofingWorkerActive;
+extern ULONG DontSuppressNonAgentSapAdvertisements;
+VOID
+Spoofer (
+ PVOID Context
+ );
+
+#define InitializeSendQueue() { \
+ InitializeListHead (&SpoofingQueue); \
+ KeInitializeSpinLock (&SpoofingQueueLock); \
+ ExInitializeWorkItem (&SpoofingWorker, Spoofer, NULL); \
+ SpoofingWorkerActive = FALSE; \
+}
+
+#define DeleteSendQueue() { \
+ while (!IsListEmpty (&SpoofingQueue)) { \
+ PPACKET_TAG pktTag = CONTAINING_RECORD (SpoofingQueue.Flink, \
+ PACKET_TAG, \
+ PT_QueueLink); \
+ RemoveEntryList (&pktTag->PT_QueueLink); \
+ if (pktTag->PT_InterfaceReference!=NULL) \
+ ReleaseInterfaceReference (pktTag->PT_InterfaceReference); \
+ FreePacket (pktTag); \
+ } \
+}
+
+
+/*++
+*******************************************************************
+ S e n d P a c k e t
+
+Routine Description:
+ Enqueues packets to be sent by IPX stack
+Arguments:
+ dstIf - over which interface to send
+ pktTag - packet to send
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+SendPacket (
+ PINTERFACE_CB dstIf,
+ PPACKET_TAG pktTag
+ );
+
+/*++
+*******************************************************************
+ F w S e n d C o m p l e t e
+
+Routine Description:
+ Called by IPX stack when send completes asynchronously
+Arguments:
+ pktDscr - descriptor of the completed packet
+ status - result of send operation
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+IpxFwdSendComplete (
+ PNDIS_PACKET pktDscr,
+ NDIS_STATUS NdisStatus
+ );
+
+/*++
+*******************************************************************
+
+ F w I n t e r n a l S e n d
+
+Routine Description:
+ Filter and routes packets sent by IPX stack
+Arguments:
+ LocalTarget - the NicId and next hop router MAC address
+ Context - preferred interface on which to send
+ Packet - packet to be sent
+ ipxHdr - pointer to ipx header inside the packet
+ PacketLength - length of the packet
+ fIterate - a flag to indicate if this is a packet for the
+ iteration of which the Fwd takes responsibility
+ - typically type 20 NetBIOS frames
+
+Return Value:
+
+ STATUS_SUCCESS - if the preferred NIC was OK and packet passed filtering
+ STATUS_NETWORK_UNREACHABLE - if the preferred was not OK or packet failed filtering
+ STATUS_PENDING - packet was queued until connection is established
+*******************************************************************
+--*/
+NTSTATUS
+IpxFwdInternalSend (
+ IN OUT PIPX_LOCAL_TARGET LocalTarget,
+ IN ULONG Context,
+ IN PNDIS_PACKET pktDscr,
+ IN PUCHAR ipxHdr,
+ IN PUCHAR data,
+ IN ULONG PacketLength,
+ IN BOOLEAN fIterate
+ );
+
+/*++
+*******************************************************************
+
+ P r o c e s s I n t e r n a l Q u e u e
+
+Routine Description:
+ Processes packets in the interface internal queue.
+ Called when connection request completes
+Arguments:
+ dstIf - interface to process
+Return Value:
+ None
+*******************************************************************
+--*/
+VOID
+ProcessInternalQueue (
+ PINTERFACE_CB dstIf
+ );
+
+
+/*++
+*******************************************************************
+
+ P r o c e s s E x t e r n a l Q u e u e
+
+Routine Description:
+ Processes packets in the interface external queue.
+ Called when connection request completes
+Arguments:
+ dstIf - interface to process
+Return Value:
+ None
+*******************************************************************
+--*/
+VOID
+ProcessExternalQueue (
+ PINTERFACE_CB dstIf
+ );
+/*++
+*******************************************************************
+ D o S e n d
+
+Routine Description:
+ Prepares and sends packet. Interface lock must be help while
+ callin this routine
+Arguments:
+ dstIf - over which interface to send
+ pktTag - packet to send
+Return Value:
+ result returned by IPX
+
+*******************************************************************
+--*/
+NDIS_STATUS
+DoSend (
+ PINTERFACE_CB dstIf,
+ PPACKET_TAG pktTag,
+ KIRQL oldIRQL
+ );
+
+/*++
+*******************************************************************
+ P r o c e s s S e n t P a c k e t
+
+Routine Description:
+ Process completed sent packets
+Arguments:
+ dstIf - interface over which packet was sent
+ pktTag - completed packet
+ status - result of send operation
+Return Value:
+ None
+
+*******************************************************************
+--*/
+VOID
+ProcessSentPacket (
+ PINTERFACE_CB dstIf,
+ PPACKET_TAG pktTag,
+ NDIS_STATUS status
+ );
+#endif
diff --git a/private/ntos/tdi/isn/fwd/sources.inc b/private/ntos/tdi/isn/fwd/sources.inc
new file mode 100644
index 000000000..3a7cd7ab5
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/sources.inc
@@ -0,0 +1,61 @@
+!IF 0
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author: Vadim Eydelman
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=ndis
+
+TARGETNAME=nwlnkfwd
+TARGETTYPE=DRIVER
+
+TARGETLIBS=\
+ $(BASEDIR)\public\sdk\lib\*\tdi.lib \
+ $(BASEDIR)\public\sdk\lib\*\ndis.lib
+
+INCLUDES=..\;..\..\inc;..\..\..\..\inc;..\..\..\..\..\inc
+
+C_DEFINES=$(C_DEFINES) -D_NTDRIVER_ -D_PNP_POWER
+
+!IFDEF BUILD_FOR_3_51
+C_DEFINES= $(C_DEFINES) -D_NTIFS_
+!ENDIF
+
+PRECOMPILED_INCLUDE=..\precomp.h
+PRECOMPILED_PCH=precomp.pch
+PRECOMPILED_OBJ=precomp.obj
+MSC_WARNING_LEVEL=/W3 /WX
+
+SOURCES=..\driver.c \
+ ..\ipxbind.c \
+ ..\rcvind.c \
+ ..\send.c \
+ ..\registry.c \
+ ..\lineind.c \
+ ..\ddreqs.c \
+ ..\netbios.c \
+ ..\packets.c \
+ ..\tables.c \
+ ..\debug.c \
+ ..\filterif.c \
+ ..\nwlnkfwd.rc
+
+RELATIVE_DEPTH=..\..
+ALT_PROJECT_TARGET=Routing
+
+ \ No newline at end of file
diff --git a/private/ntos/tdi/isn/fwd/tables.c b/private/ntos/tdi/isn/fwd/tables.c
new file mode 100644
index 000000000..baec3cced
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/tables.c
@@ -0,0 +1,1512 @@
+
+#include "precomp.h"
+
+// Memory zone for interfaces
+ZONE_HEADER InterfaceZone;
+// Segment size in interface sone
+ULONG InterfaceSegmentSize=
+ sizeof(INTERFACE_CB)*NUM_INTERFACES_PER_SEGMENT
+ +sizeof (ZONE_SEGMENT_HEADER);
+KSPIN_LOCK InterfaceZoneLock;
+
+// Interface tables
+LIST_ENTRY *InterfaceIndexHash; // Hash by interface index
+PINTERFACE_CB *ClientNodeHash; // Hash by node on qlobal net
+INTERFACE_CB TheInternalInterface; // The internal interface
+PINTERFACE_CB InternalInterface=&TheInternalInterface;
+KSPIN_LOCK InterfaceTableLock; // Protection for interface hash tables
+
+// Memory Zone for routes
+ZONE_HEADER RouteZone;
+// Segment size in route sone
+ULONG RouteSegmentSize=DEF_ROUTE_SEGMENT_SIZE;
+KSPIN_LOCK RouteZoneLock;
+
+// Route tables
+PFWD_ROUTE *RouteHash;
+PFWD_ROUTE GlobalRoute;
+ULONG GlobalNetwork;
+
+
+// NB Route table
+PNB_ROUTE *NBRouteHash;
+
+
+// Reader-writer lock to wait for all readers to drain when
+// updating the route tables
+RW_LOCK RWLock;
+// Mutex to serialize writers to route tables
+FAST_MUTEX WriterMutex;
+
+
+// Sizes of the tables
+ULONG RouteHashSize; // Must be specified
+ULONG InterfaceHashSize=DEF_INTERFACE_HASH_SIZE;
+ULONG ClientHashSize=DEF_CLIENT_HASH_SIZE;
+ULONG NBRouteHashSize=DEF_NB_ROUTE_HASH_SIZE;
+
+//*** max send pkts queued limit: over this limit the send pkts get discarded
+ULONG MaxSendPktsQueued = MAX_SEND_PKTS_QUEUED;
+INT WanPacketListId = -1;
+
+// Initial memory block allocated for the tables
+CHAR *TableBlock = NULL;
+
+// Hash functions
+#define InterfaceIndexHashFunc(Interface) (Interface%InterfaceHashSize)
+#define ClientNodeHashFunc(Node64) ((UINT)(Node64%ClientHashSize))
+#define NetworkNumberHashFunc(Network) (Network%RouteHashSize)
+#define NetbiosNameHashFunc(Name128) ((UINT)(Name128[0]+Name128[1])%NBRouteHashSize)
+
+/*++
+*******************************************************************
+ A l l o c a t e R o u t e
+
+Routine Description:
+ Allocates memory for route from memory zone reserved
+ for route storage. Extends zone if there are no
+ free blocks in currently allocated segements.
+Arguments:
+ None
+Return Value:
+ Pointer to allocated route
+
+*******************************************************************
+--*/
+PFWD_ROUTE
+AllocateRoute (
+ void
+ ) {
+ PFWD_ROUTE fwRoute;
+ KIRQL oldIRQL;
+
+ KeAcquireSpinLock (&RouteZoneLock, &oldIRQL);
+ // Check if there are free blocks in the zone
+ if (ExIsFullZone (&RouteZone)) {
+ // Try to allocate new segment if not
+ NTSTATUS status;
+ PVOID segment = ExAllocatePoolWithTag
+ (NonPagedPool, RouteSegmentSize, FWD_POOL_TAG);
+ if (segment==NULL) {
+ KeReleaseSpinLock (&RouteZoneLock, oldIRQL);
+ IpxFwdDbgPrint (DBG_ROUTE_TABLE, DBG_ERROR,
+ ("IpxFwd: Can't allocate route zone segment.\n"));
+ return NULL;
+ }
+ status = ExExtendZone (&RouteZone, segment, RouteSegmentSize);
+ ASSERTMSG ("Could not extend RouteZone ", NT_SUCCESS (status));
+ }
+ fwRoute = (PFWD_ROUTE)ExAllocateFromZone (&RouteZone);
+ KeReleaseSpinLock (&RouteZoneLock, oldIRQL);
+ return fwRoute;
+}
+
+/*++
+*******************************************************************
+ F r e e R o u t e
+
+Routine Description:
+ Releases memory allocated for route to route memory
+ zone.
+Arguments:
+ fwRoute - route block to release
+Return Value:
+ None
+*******************************************************************
+--*/
+VOID
+FreeRoute (
+ PFWD_ROUTE fwRoute
+ ) {
+ IpxFwdDbgPrint (DBG_ROUTE_TABLE, DBG_INFORMATION,
+ ("IpxFwd: Freeing route block %08lx.\n", fwRoute));
+ ASSERT (fwRoute->FR_InterfaceReference==NULL);
+ ExInterlockedFreeToZone(&RouteZone,fwRoute,&RouteZoneLock);
+}
+
+
+/*++
+*******************************************************************
+ A l l o c a t e I n t e r f a c e
+
+Routine Description:
+ Allocates memory for interface from memory zone reserved
+ for interface storage. Extends zone if there are no
+ free blocks in currently allocated segements.
+Arguments:
+ None
+Return Value:
+ Pointer to allocated route
+
+*******************************************************************
+--*/
+PINTERFACE_CB
+AllocateInterface (
+ void
+ ) {
+ PINTERFACE_CB ifCB;
+ KIRQL oldIRQL;
+
+ KeAcquireSpinLock (&RouteZoneLock, &oldIRQL);
+ // Check if there are free blocks in the zone
+ if (ExIsFullZone (&InterfaceZone)) {
+ // Try to allocate new segment if not
+ NTSTATUS status;
+ PVOID segment = ExAllocatePoolWithTag
+ (NonPagedPool, InterfaceSegmentSize, FWD_POOL_TAG);
+ if (segment==NULL) {
+ KeReleaseSpinLock (&RouteZoneLock, oldIRQL);
+ IpxFwdDbgPrint (DBG_INTF_TABLE, DBG_ERROR,
+ ("IpxFwd: Can't allocate interface zone segment.\n"));
+ return NULL;
+ }
+ status = ExExtendZone (&InterfaceZone, segment, InterfaceSegmentSize);
+ ASSERTMSG ("Could not extend InterfaceZone ", NT_SUCCESS (status));
+ }
+ ifCB = (PINTERFACE_CB)ExAllocateFromZone (&InterfaceZone);
+ KeReleaseSpinLock (&RouteZoneLock, oldIRQL);
+ return ifCB;
+}
+
+/*++
+*******************************************************************
+ F r e e I n t e r f a c e
+
+Routine Description:
+ Releases memory allocated for interface to interface memory
+ zone.
+Arguments:
+ fwRoute - route block to release
+Return Value:
+ None
+*******************************************************************
+--*/
+VOID
+FreeInterface (
+ PINTERFACE_CB ifCB
+ ) {
+ KIRQL oldIRQL;
+
+ IpxFwdDbgPrint (DBG_INTF_TABLE, DBG_WARNING,
+ ("IpxFwd: Freeing icb %08lx.\n", ifCB));
+
+ ASSERT(ifCB->ICB_Stats.OperationalState==FWD_OPER_STATE_DOWN);
+ KeAcquireSpinLock (&InterfaceZoneLock, &oldIRQL);
+ ExFreeToZone(&InterfaceZone, ifCB);
+ KeReleaseSpinLock (&InterfaceZoneLock, oldIRQL);
+}
+
+/*++
+*******************************************************************
+ C r e a t e T a b l e s
+
+Routine Description:
+ Allocates and intializes all hash tables and related structures
+Arguments:
+ None
+Return Value:
+ STATUS_SUCCESS - tables were created ok
+ STATUS_INSUFFICIENT_RESOURCES - resource allocation failed
+*******************************************************************
+--*/
+NTSTATUS
+CreateTables (
+ void
+ ) {
+ UINT i;
+ CHAR *segment;
+ NTSTATUS status;
+ ULONG blockSize;
+
+ ASSERT (TableBlock==NULL);
+
+ blockSize = ROUND_TO_PAGES (
+ InterfaceHashSize*sizeof(*InterfaceIndexHash)
+ +ClientHashSize*sizeof(*ClientNodeHash)
+ +RouteHashSize*sizeof(*RouteHash)
+ +NBRouteHashSize*sizeof(*NBRouteHash)
+ +InterfaceSegmentSize
+ +RouteSegmentSize
+ );
+
+ // Allocate first segment for route zone
+ TableBlock = segment = (CHAR *)ExAllocatePoolWithTag (
+ NonPagedPool, blockSize, FWD_POOL_TAG);
+ if (segment!=NULL) {
+ InterfaceIndexHash = (LIST_ENTRY *)segment;
+ segment = (CHAR *)ALIGN_UP((ULONG)(InterfaceIndexHash+InterfaceHashSize),ULONGLONG);
+
+ ClientNodeHash = (PINTERFACE_CB *)segment;
+ segment = (CHAR *)ALIGN_UP((ULONG)(ClientNodeHash+ClientHashSize),ULONGLONG);
+
+ RouteHash = (PFWD_ROUTE *)segment;
+ segment = (CHAR *)ALIGN_UP((ULONG)(RouteHash + RouteHashSize),ULONGLONG);
+
+ NBRouteHash = (PNB_ROUTE *)segment;
+ segment = (CHAR *)ALIGN_UP((ULONG)(NBRouteHash + NBRouteHashSize),ULONGLONG);
+
+ status = ExInitializeZone (&InterfaceZone,
+ ALIGN_UP(sizeof (INTERFACE_CB),ULONGLONG),
+ segment,
+ InterfaceSegmentSize);
+ ASSERTMSG ("Could not initalize InterfaceZone ",
+ NT_SUCCESS (status));
+ segment = (CHAR *)ALIGN_UP((ULONG)(segment+InterfaceSegmentSize),ULONGLONG);
+
+ status = ExInitializeZone (&RouteZone,
+ ALIGN_UP(sizeof (FWD_ROUTE), ULONGLONG),
+ segment,
+ blockSize - (segment - TableBlock));
+
+ ASSERTMSG ("Could not initalize RouteZone ", NT_SUCCESS (status));
+
+
+ // No global route yet
+ GlobalRoute = NULL;
+ GlobalNetwork = 0xFFFFFFFF;
+
+ InternalInterface = &TheInternalInterface;
+ InitICB (InternalInterface,
+ FWD_INTERNAL_INTERFACE_INDEX,
+ FWD_IF_PERMANENT,
+ TRUE,
+ FWD_NB_DELIVER_ALL);
+#if DBG
+ InitializeListHead (&InternalInterface->ICB_InSendQueue);
+#endif
+
+ KeInitializeSpinLock (&InterfaceTableLock);
+ KeInitializeSpinLock (&InterfaceZoneLock);
+ KeInitializeSpinLock (&RouteZoneLock);
+ InitializeRWLock (&RWLock);
+ ExInitializeFastMutex (&WriterMutex);
+
+ // Initialize hash tables buckets
+ for (i=0; i<InterfaceHashSize; i++)
+ InitializeListHead (&InterfaceIndexHash[i]);
+
+ for (i=0; i<ClientHashSize; i++) {
+ ClientNodeHash[i] = NULL;
+ }
+
+ for (i=0; i<RouteHashSize; i++) {
+ RouteHash[i] = NULL;
+ }
+
+ for (i=0; i<NBRouteHashSize; i++) {
+ NBRouteHash[i] = NULL;
+ }
+ return STATUS_SUCCESS;
+ }
+ else {
+ IpxFwdDbgPrint (DBG_INTF_TABLE, DBG_ERROR,
+ ("IpxFwd: Could not allocate table block!\n"));
+ }
+
+ return STATUS_INSUFFICIENT_RESOURCES;
+}
+
+/*++
+*******************************************************************
+ D e l e t e T a b l e s
+
+Routine Description:
+ Releases resources allocated for all hash tables
+Arguments:
+ None
+Return Value:
+ STATUS_SUCCESS - tables were freed ok
+*******************************************************************
+--*/
+NTSTATUS
+DeleteTables (
+ void
+ ) {
+ UINT i;
+ PVOID segment;
+
+
+ if (TableBlock==NULL) {
+ IpxFwdDbgPrint (DBG_INTF_TABLE, DBG_ERROR, ("Tables already deleted.\n"));
+ return STATUS_SUCCESS;
+ }
+ // First get rid of all routes
+ // (that should release all references to interface
+ // control blocks
+ for (i=0; i<RouteHashSize; i++) {
+ while (RouteHash[i]!=NULL) {
+ PFWD_ROUTE fwRoute = RouteHash[i];
+ RouteHash[i] = fwRoute->FR_Next;
+ if (fwRoute->FR_InterfaceReference!=GLOBAL_INTERFACE_REFERENCE) {
+ ReleaseInterfaceReference (fwRoute->FR_InterfaceReference);
+ }
+ fwRoute->FR_InterfaceReference = NULL;
+ ReleaseRouteReference (fwRoute);
+ }
+ }
+ // Don't forget about global route
+ if (GlobalRoute!=NULL) {
+ GlobalRoute->FR_InterfaceReference = NULL;
+ ReleaseRouteReference (GlobalRoute);
+ GlobalRoute = NULL;
+ GlobalNetwork = 0xFFFFFFFF;
+ }
+
+ // Now we should be able to release all interfaces
+ for (i=0; i<InterfaceHashSize; i++) {
+ while (!IsListEmpty (&InterfaceIndexHash[i])) {
+ PINTERFACE_CB ifCB = CONTAINING_RECORD (InterfaceIndexHash[i].Flink,
+ INTERFACE_CB,
+ ICB_IndexHashLink);
+ RemoveEntryList (&ifCB->ICB_IndexHashLink);
+ if (ifCB->ICB_Stats.OperationalState==FWD_OPER_STATE_UP) {
+ switch (ifCB->ICB_InterfaceType) {
+ case FWD_IF_PERMANENT:
+ DeregisterPacketConsumer (ifCB->ICB_PacketListId);
+ break;
+ case FWD_IF_DEMAND_DIAL:
+ case FWD_IF_LOCAL_WORKSTATION:
+ case FWD_IF_REMOTE_WORKSTATION:
+ break;
+ default:
+ ASSERTMSG ("Invalid interface type ", FALSE);
+ break;
+ }
+ if (ifCB->ICB_CashedInterface!=NULL)
+ ReleaseInterfaceReference (ifCB->ICB_CashedInterface);
+ ifCB->ICB_CashedInterface = NULL;
+ if (ifCB->ICB_CashedRoute!=NULL)
+ ReleaseRouteReference (ifCB->ICB_CashedRoute);
+ ifCB->ICB_CashedRoute = NULL;
+ if (ifCB->ICB_Network==GlobalNetwork)
+ DeleteGlobalNetClient (ifCB);
+ IPXCloseAdapterProc (ifCB->ICB_AdapterContext);
+ ReleaseInterfaceReference (ifCB); // Binding reference
+ }
+
+ if (IS_IF_CONNECTING (ifCB)) {
+ SET_IF_NOT_CONNECTING (ifCB);
+ DequeueConnectionRequest (ifCB);
+ }
+
+ while (!IsListEmpty (&ifCB->ICB_ExternalQueue)) {
+ PPACKET_TAG pktTag;
+
+ pktTag = CONTAINING_RECORD (ifCB->ICB_ExternalQueue.Flink,
+ PACKET_TAG, PT_QueueLink);
+ RemoveEntryList (&pktTag->PT_QueueLink);
+ ReleaseInterfaceReference (pktTag->PT_InterfaceReference);
+ FreePacket (pktTag);
+ }
+
+ while (!IsListEmpty (&ifCB->ICB_InternalQueue)) {
+ PINTERNAL_PACKET_TAG pktTag;
+
+ pktTag = CONTAINING_RECORD (ifCB->ICB_InternalQueue.Flink,
+ INTERNAL_PACKET_TAG, IPT_QueueLink);
+ RemoveEntryList (&pktTag->IPT_QueueLink);
+ IPXInternalSendCompletProc (&pktTag->IPT_Target,
+ pktTag->IPT_Packet,
+ pktTag->IPT_Length,
+ STATUS_NETWORK_UNREACHABLE);
+ ReleaseInterfaceReference (pktTag->IPT_InterfaceReference);
+ ExFreePool (pktTag);
+ }
+
+ ifCB->ICB_Stats.OperationalState = FWD_OPER_STATE_DOWN;
+ if (ifCB->ICB_NBRoutes!=NULL) {
+ DeleteNBRoutes (ifCB->ICB_NBRoutes, ifCB->ICB_NBRouteCount);
+ ifCB->ICB_NBRoutes = NULL;
+ }
+ ReleaseInterfaceReference (ifCB);
+ }
+ }
+
+ if (InternalInterface->ICB_NBRoutes!=NULL) {
+ DeleteNBRoutes (InternalInterface->ICB_NBRoutes,
+ InternalInterface->ICB_NBRouteCount);
+ InternalInterface->ICB_NBRoutes = NULL;
+ }
+ if (InternalInterface->ICB_Stats.OperationalState==FWD_OPER_STATE_UP) {
+ InternalInterface->ICB_Stats.OperationalState = FWD_OPER_STATE_DOWN;
+ ReleaseInterfaceReference (InternalInterface); // Binding reference
+ }
+ ReleaseInterfaceReference (InternalInterface);
+
+
+
+ // Release extra memory segments used for route table entries
+ segment = PopEntryList (&RouteZone.SegmentList);
+ while (RouteZone.SegmentList.Next!=NULL) {
+ ExFreePool (segment);
+ segment = PopEntryList (&RouteZone.SegmentList);
+ }
+
+ // Release extra memory segments used for interface table entries
+ segment = PopEntryList (&InterfaceZone.SegmentList);
+ while (InterfaceZone.SegmentList.Next!=NULL) {
+ ExFreePool (segment);
+ segment = PopEntryList (&InterfaceZone.SegmentList);
+ }
+
+ ExFreePool (TableBlock);
+ TableBlock = NULL;
+ return STATUS_SUCCESS;
+}
+
+/*++
+*******************************************************************
+ L o c a t e I n t e r f a c e
+
+Routine Description:
+ Finds interface control block in interface
+ index hash table. Optionally returns the
+ insertion point pointer if interface block
+ with given index is not in the table.
+Arguments:
+ InterfaceIndex - unique id of the interface
+ insertBefore - buffer to place the pointer to
+ hash table element where interface
+ block should be inserted if it is not
+ already in the table
+Return Value:
+ Pointer to interface control block if found
+ NULL otherwise
+*******************************************************************
+--*/
+PINTERFACE_CB
+LocateInterface (
+ ULONG InterfaceIndex,
+ PLIST_ENTRY *insertBefore OPTIONAL
+ ) {
+ PLIST_ENTRY cur;
+ PINTERFACE_CB ifCB;
+ PLIST_ENTRY HashList;
+
+ ASSERT (InterfaceIndex!=FWD_INTERNAL_INTERFACE_INDEX);
+
+ // Find hash bucket
+ HashList = &InterfaceIndexHash[InterfaceIndexHashFunc(InterfaceIndex)];
+ cur = HashList->Flink;
+ // Walk the list
+ while (cur!=HashList) {
+ ifCB = CONTAINING_RECORD(cur, INTERFACE_CB, ICB_IndexHashLink);
+
+ if (ifCB->ICB_Index==InterfaceIndex)
+ // Found, return it (insertion point is irrelevant)
+ return ifCB;
+ else if (ifCB->ICB_Index>InterfaceIndex)
+ // No chance to find it
+ break;
+ cur = cur->Flink;
+ }
+ // Return insertion point if asked
+ if (ARGUMENT_PRESENT(insertBefore))
+ *insertBefore = cur;
+ return NULL;
+}
+
+/*++
+*******************************************************************
+ L o c a t e C l i e n t I n t e r f a c e
+
+Routine Description:
+ Finds interface control block in client
+ node hash bucket. Optionally returns the
+ insertion point pointer if interface block
+ with given node is not in the table
+Arguments:
+ ClientNode - node address of the client on global network
+ insertBefore - buffer to place the pointer to
+ hash table element where interface
+ block should be inserted if it is not
+ already in the table
+Return Value:
+ Pointer to interface control block if found
+ NULL otherwise
+*******************************************************************
+--*/
+PINTERFACE_CB
+LocateClientInterface (
+ ULONGLONG *NodeAddress64,
+ PINTERFACE_CB **prevLink OPTIONAL
+ ) {
+ PINTERFACE_CB cur, *prev;
+
+ prev = &ClientNodeHash[ClientNodeHashFunc (*NodeAddress64)];
+ cur = *prev;
+ while (cur!=NULL) {
+ if (*NodeAddress64==cur->ICB_ClientNode64[0])
+ break;
+ else if (*NodeAddress64>cur->ICB_ClientNode64[0]) {
+ // No chance to find it
+ cur = NULL;
+ break;
+ }
+ prev = &cur->ICB_NodeHashLink;
+ cur = cur->ICB_NodeHashLink;
+ }
+ if (ARGUMENT_PRESENT(prevLink))
+ *prevLink = prev;
+ return cur;
+}
+
+/*++
+*******************************************************************
+ L o c a t e R o u t e
+
+Routine Description:
+ Finds route block in network number
+ hash table. Optionally returns the
+ insertion point pointer if route
+ for given destination netowrk is not in the table
+Arguments:
+ Network - destination netowork number
+ insertBefore - buffer to place the pointer to
+ hash table element where route
+ block should be inserted if it is not
+ already in the table
+Return Value:
+ Pointer to route block if found
+ NULL otherwise
+*******************************************************************
+--*/
+PFWD_ROUTE
+LocateRoute (
+ ULONG Network,
+ PFWD_ROUTE **prevLink OPTIONAL
+ ) {
+ PFWD_ROUTE cur, *prev;
+
+ prev = &RouteHash[NetworkNumberHashFunc(Network)];
+ cur = *prev;
+
+ while (cur!=NULL) {
+ if (cur->FR_Network==Network)
+ break;
+ else if (cur->FR_Network>Network) {
+ cur = NULL;
+ // No chance to find it
+ break;
+ }
+ prev = &cur->FR_Next;
+ cur = *prev;
+ }
+ if (ARGUMENT_PRESENT(prevLink))
+ *prevLink = prev;
+
+ return cur;
+}
+
+/*++
+*******************************************************************
+ L o c a t e N B R o u t e
+
+Routine Description:
+ Finds nb route block in nb name
+ hash table. Optionally returns the
+ insertion point pointer if nb route
+ for given name is not in the table
+Arguments:
+ Name - netbios name
+ insertBefore - buffer to place the pointer to
+ hash table element where route
+ block should be inserted if it is not
+ already in the table
+Return Value:
+ Pointer to nb route block if found
+ NULL otherwise
+*******************************************************************
+--*/
+PNB_ROUTE
+LocateNBRoute (
+ ULONGLONG *Name128,
+ PNB_ROUTE **prevLink OPTIONAL
+ ) {
+ PNB_ROUTE cur, *prev;
+
+ prev = &NBRouteHash[NetbiosNameHashFunc(Name128)];
+ cur = *prev;
+
+ while (cur!=NULL) {
+ if ((cur->NBR_Name128[0]==Name128[0])
+ && (cur->NBR_Name128[1]==Name128[1]))
+ break;
+ else if ((cur->NBR_Name128[0]>Name128[0])
+ || ((cur->NBR_Name128[0]==Name128[0])
+ && (cur->NBR_Name128[1]>Name128[1]))) {
+ cur = NULL;
+ // No chance to find it
+ break;
+ }
+ prev = &cur->NBR_Next;
+ cur = *prev;
+ }
+ if (ARGUMENT_PRESENT(prevLink))
+ *prevLink = prev;
+
+ return cur;
+}
+
+/*++
+*******************************************************************
+ G e t I n t e r f a c e R e f e r e n c e
+
+Routine Description:
+ Returns reference interface based on its index
+Arguments:
+ InterfaceIndex - unique id of the interface
+Return Value:
+ Pointer to interface control block if there is one in the table
+ NULL otherwise
+*******************************************************************
+--*/
+PINTERFACE_CB
+GetInterfaceReference (
+ ULONG InterfaceIndex
+ ) {
+ KIRQL oldIRQL;
+ PINTERFACE_CB ifCB;
+
+ KeAcquireSpinLock (&InterfaceTableLock, &oldIRQL);
+ if (InterfaceIndex!=FWD_INTERNAL_INTERFACE_INDEX)
+ ifCB = LocateInterface (InterfaceIndex, NULL);
+ else
+ ifCB = InternalInterface;
+
+ if (ifCB!=NULL)
+ AcquireInterfaceReference (ifCB);
+ else {
+ IpxFwdDbgPrint (DBG_INTF_TABLE, DBG_ERROR,
+ ("IpxFwd: Could not get interface reference %ld.\n", InterfaceIndex));
+ }
+ KeReleaseSpinLock (&InterfaceTableLock, oldIRQL);
+ return ifCB;
+}
+
+/*++
+*******************************************************************
+ G e t N e x t I n t e r f a c e R e f e r e n c e
+
+Routine Description:
+ Returns reference to the next interface in the table
+ Reference to the provided interface is released
+Arguments:
+ ifCB - interface to start with or NULL to start from the
+ beginning of the interface table
+Return Value:
+ Pointer to interface control block if thare are any more interfaces
+ in the table
+ NULL otherwise
+*******************************************************************
+--*/
+PINTERFACE_CB
+GetNextInterfaceReference (
+ PINTERFACE_CB ifCB
+ ) {
+ PLIST_ENTRY cur;
+ PLIST_ENTRY HashList;
+ KIRQL oldIRQL;
+
+ KeAcquireSpinLock (&InterfaceTableLock, &oldIRQL);
+ if (ifCB!=NULL) {
+ // Find hash bucket
+ ASSERT (ifCB->ICB_Index!=FWD_INTERNAL_INTERFACE_INDEX);
+ HashList = &InterfaceIndexHash[InterfaceIndexHashFunc(ifCB->ICB_Index)];
+ if (LocateInterface (ifCB->ICB_Index, &cur)!=NULL)
+ cur = ifCB->ICB_IndexHashLink.Flink;
+ ReleaseInterfaceReference (ifCB);
+ ifCB = NULL;
+ }
+ else
+ cur = HashList = InterfaceIndexHash-1;
+
+ if (cur==HashList) {
+ do {
+ HashList += 1;
+ if (HashList==&InterfaceIndexHash[InterfaceHashSize]) {
+ KeReleaseSpinLock (&InterfaceTableLock, oldIRQL);
+ return NULL;
+ }
+ } while (IsListEmpty (HashList));
+ cur = HashList->Flink;
+ }
+ ifCB = CONTAINING_RECORD (cur, INTERFACE_CB, ICB_IndexHashLink);
+ AcquireInterfaceReference (ifCB);
+ KeReleaseSpinLock (&InterfaceTableLock, oldIRQL);
+
+ return ifCB;
+}
+
+
+/*++
+*******************************************************************
+ A d d I n t e r f a c e
+
+Routine Description:
+ Adds interface control block to the table.
+Arguments:
+ InterfaceIndex - unique if of the interface
+ Info - interface paramters
+Return Value:
+ STATUS_SUCCESS - interface added ok
+ STATUS_UNSUCCESSFUL - interface is already in the table
+ STATUS_INSUFFICIENT_RESOURCES - can't allocate memory for
+ interface CB
+*******************************************************************
+--*/
+NTSTATUS
+AddInterface (
+ ULONG InterfaceIndex,
+ UCHAR InterfaceType,
+ BOOLEAN NetbiosAccept,
+ UCHAR NetbiosDeliver
+ ) {
+ PINTERFACE_CB ifCB;
+ PLIST_ENTRY cur;
+ KIRQL oldIRQL;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ KeAcquireSpinLock (&InterfaceTableLock, &oldIRQL);
+ if (InterfaceIndex!=FWD_INTERNAL_INTERFACE_INDEX) {
+ ifCB = LocateInterface (InterfaceIndex, &cur);
+ if (ifCB==NULL) {
+ ifCB = AllocateInterface ();
+ if (ifCB!=NULL)
+ NOTHING;
+ else {
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ goto AddEnd;
+ }
+ }
+ else {
+ IpxFwdDbgPrint (DBG_INTF_TABLE, DBG_ERROR,
+ ("IpxFwd: Interface %ld is already in the table!\n", InterfaceIndex));
+ status = STATUS_UNSUCCESSFUL;
+ goto AddEnd;
+ }
+ }
+ else
+ ifCB = InternalInterface;
+
+ InitICB (ifCB, InterfaceIndex,InterfaceType,NetbiosAccept,NetbiosDeliver);
+#if DBG
+ InitializeListHead (&ifCB->ICB_InSendQueue);
+#endif
+
+ switch (InterfaceType) {
+ case FWD_IF_PERMANENT:
+ break;
+ case FWD_IF_DEMAND_DIAL:
+ case FWD_IF_LOCAL_WORKSTATION:
+ case FWD_IF_REMOTE_WORKSTATION:
+ ASSERT (InterfaceIndex!=FWD_INTERNAL_INTERFACE_INDEX);
+ if (WanPacketListId==-1) {
+ status = RegisterPacketConsumer (
+ WAN_PACKET_SIZE,
+ &WanPacketListId);
+ if (!NT_SUCCESS (status)) {
+ WanPacketListId = -1;
+ break;
+ }
+ }
+ ifCB->ICB_PacketListId = WanPacketListId;
+ break;
+ }
+
+ if (NT_SUCCESS (status)) {
+ if (InterfaceIndex!=FWD_INTERNAL_INTERFACE_INDEX) {
+ InsertTailList (cur, &ifCB->ICB_IndexHashLink);
+ }
+ IpxFwdDbgPrint (DBG_INTF_TABLE, DBG_WARNING,
+ ("IpxFwd: Adding interface %d (icb: %08lx, plid: %d)\n",
+ InterfaceIndex, ifCB, ifCB->ICB_PacketListId));
+ }
+ else
+ FreeInterface (ifCB);
+
+AddEnd:
+ KeReleaseSpinLock (&InterfaceTableLock, oldIRQL);
+ return status;
+}
+
+
+/*++
+*******************************************************************
+ A d d G l o b a l N e t C l i e n t
+
+Routine Description:
+ Adds interface control block to the table of
+ clients on the global network (should be done when
+ client connects)
+Arguments:
+ ifCB - interface control block to add to the table
+Return Value:
+ STATUS_SUCCESS - interface was added ok
+ STATUS_UNSUCCESSFUL - another interface with the same
+ node address is already in the table
+*******************************************************************
+--*/
+NTSTATUS
+AddGlobalNetClient (
+ PINTERFACE_CB ifCB
+ ) {
+ KIRQL oldIRQL;
+ RWCOOKIE cookie;
+ PINTERFACE_CB *prev;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ ASSERT (ifCB->ICB_Index!=FWD_INTERNAL_INTERFACE_INDEX);
+
+ AcquireReaderAccess (&RWLock, cookie);
+ KeAcquireSpinLock (&InterfaceTableLock, &oldIRQL);
+ if (LocateClientInterface (ifCB->ICB_ClientNode64, &prev)==NULL) {
+ ifCB->ICB_NodeHashLink = *prev;
+ *prev = ifCB;
+ KeReleaseSpinLock (&InterfaceTableLock, oldIRQL);
+ ReleaseReaderAccess (&RWLock, cookie);
+ AcquireInterfaceReference (ifCB); // To make sure that
+ // interface block does not
+ // get deleted until it is
+ // removed from the node table
+ IpxFwdDbgPrint (DBG_INTF_TABLE, DBG_WARNING,
+ ("IpxFwd: Adding interface %ld (icb: %08lx)"
+ " to global client table.\n", ifCB->ICB_Index, ifCB));
+ }
+ else {
+ KeReleaseSpinLock (&InterfaceTableLock, oldIRQL);
+ ReleaseReaderAccess (&RWLock, cookie);
+ IpxFwdDbgPrint (DBG_INTF_TABLE, DBG_ERROR,
+ ("IpxFwd: Interface %ld (icb: %08lx)"
+ " is already in the global client table.\n",
+ ifCB->ICB_Index, ifCB));
+ status = STATUS_UNSUCCESSFUL;
+ }
+
+ return status;
+}
+
+/*++
+*******************************************************************
+ D e l e t e G l o b a l N e t C l i e n t
+
+Routine Description:
+ Removes interface control block from the table of
+ clients on the global network (should be done when
+ client disconnects)
+Arguments:
+ ifCB - interface control block to remove from the table
+Return Value:
+ STATUS_SUCCESS - interface was removed ok
+*******************************************************************
+--*/
+NTSTATUS
+DeleteGlobalNetClient (
+ PINTERFACE_CB ifCB
+ ) {
+ KIRQL oldIRQL;
+ RWCOOKIE cookie;
+ PINTERFACE_CB cur, *prev;
+
+ IpxFwdDbgPrint (DBG_INTF_TABLE, DBG_WARNING,
+ ("IpxFwd: Deleting interface %ld (icb: %08lx)"
+ " from global client table.\n", ifCB->ICB_Index, ifCB));
+
+ ASSERT (ifCB->ICB_Index!=FWD_INTERNAL_INTERFACE_INDEX);
+
+ AcquireReaderAccess (&RWLock, cookie);
+ KeAcquireSpinLock (&InterfaceTableLock, &oldIRQL);
+ cur = LocateClientInterface (ifCB->ICB_ClientNode64, &prev);
+ ASSERT (cur==ifCB);
+ *prev = ifCB->ICB_NodeHashLink;
+ KeReleaseSpinLock (&InterfaceTableLock, oldIRQL);
+ ReleaseReaderAccess (&RWLock, cookie);
+
+ ReleaseInterfaceReference (ifCB);
+ return STATUS_SUCCESS;
+}
+
+
+/*++
+*******************************************************************
+ D e l e t e I n t e r f a c e
+
+Routine Description:
+ Deletes interface control block (the block is not actually
+ disposed of until all references to it are released).
+Arguments:
+ InterfaceIndex - unique if of the interface
+Return Value:
+ STATUS_SUCCESS - interface info retreived ok
+ STATUS_UNSUCCESSFUL - interface is not in the table
+*******************************************************************
+--*/
+NTSTATUS
+DeleteInterface (
+ ULONG InterfaceIndex
+ ) {
+ PINTERFACE_CB ifCB;
+ KIRQL oldIRQL;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ KeAcquireSpinLock (&InterfaceTableLock, &oldIRQL);
+
+ if (InterfaceIndex!=FWD_INTERNAL_INTERFACE_INDEX)
+ ifCB = LocateInterface (InterfaceIndex, NULL);
+ else
+ ifCB = InternalInterface;
+ if (ifCB!=NULL) {
+ if (InterfaceIndex!=FWD_INTERNAL_INTERFACE_INDEX) {
+ RemoveEntryList (&ifCB->ICB_IndexHashLink);
+ }
+ KeReleaseSpinLock (&InterfaceTableLock, oldIRQL);
+ if (ifCB->ICB_Stats.OperationalState == FWD_OPER_STATE_UP) {
+ IpxFwdDbgPrint (DBG_INTF_TABLE, DBG_ERROR,
+ ("IpxFwd: Interface %ld (icb: %08lx) was still bound"
+ " when asked to delete it.\n",
+ ifCB->ICB_Index, ifCB));
+ UnbindInterface (ifCB);
+ }
+ else if (IS_IF_CONNECTING (ifCB)) {
+ IpxFwdDbgPrint (DBG_INTF_TABLE, DBG_ERROR,
+ ("IpxFwd: Interface %ld (icb: %08lx) was still being connected"
+ " when asked to delete it.\n",
+ ifCB->ICB_Index, ifCB));
+ SET_IF_NOT_CONNECTING (ifCB);
+ DequeueConnectionRequest (ifCB);
+ ProcessInternalQueue (ifCB);
+ ProcessExternalQueue (ifCB);
+ }
+
+ ifCB->ICB_Stats.OperationalState = FWD_OPER_STATE_DOWN;
+
+ IpxFwdDbgPrint (DBG_INTF_TABLE, DBG_WARNING,
+ ("IpxFwd: Deleting interface %ld (icb: %08lx).\n",
+ ifCB->ICB_Index, ifCB));
+
+ if (ifCB->ICB_NBRoutes!=NULL) {
+ DeleteNBRoutes (ifCB->ICB_NBRoutes, ifCB->ICB_NBRouteCount);
+ ifCB->ICB_NBRoutes = NULL;
+ }
+
+ FltInterfaceDeleted (ifCB);
+ ReleaseInterfaceReference (ifCB);
+ }
+ else {
+ KeReleaseSpinLock (&InterfaceTableLock, oldIRQL);
+ IpxFwdDbgPrint (DBG_INTF_TABLE, DBG_ERROR,
+ ("IpxFwd: Could not delete interface %ld because it is not found.\n",
+ InterfaceIndex));
+ status = STATUS_UNSUCCESSFUL;
+ }
+ return status;
+
+}
+
+/*++
+*******************************************************************
+ A d d R o u t e
+
+Routine Description:
+ Adds route to the hash table and finds and stores the reference
+ to the associated interface control block in the route.
+Arguments:
+ Network - route's destination network
+ NextHopAddress - mac address of next hop router if network is not
+ directly connected
+ TickCount - ticks to reach the destination net
+ HopCount - hopss to reach the destination net
+ InterfaceIndex - index of the associated interface (through which
+ packets destined to the network are to be sent)
+Return Value:
+ STATUS_SUCCESS - route was added ok
+ STATUS_UNSUCCESSFUL - route is already in the table
+ STATUS_INSUFFICIENT_RESOURCES - can't allocate memory for
+ route block
+*******************************************************************
+--*/
+NTSTATUS
+AddRoute (
+ ULONG Network,
+ UCHAR *NextHopAddress,
+ USHORT TickCount,
+ USHORT HopCount,
+ ULONG InterfaceIndex
+ ) {
+ PFWD_ROUTE fwRoute;
+ PFWD_ROUTE *prev;
+ NTSTATUS status = STATUS_SUCCESS;
+ KIRQL oldIRQL;
+
+ // Assume success, allocate route and intialize it
+ // (the goal is to spend as little time as possible
+ // inside exclusive usage zone)
+ fwRoute = AllocateRoute ();
+ if (fwRoute!=NULL) {
+ fwRoute->FR_Network = Network;
+ IPX_NODE_CPY (fwRoute->FR_NextHopAddress, NextHopAddress);
+ fwRoute->FR_TickCount = TickCount;
+ fwRoute->FR_HopCount = HopCount;
+ fwRoute->FR_ReferenceCount = 0;
+
+ if (InterfaceIndex!=0xFFFFFFFF) {
+ // See if interface is there
+ KeAcquireSpinLock (&InterfaceTableLock, &oldIRQL);
+ if (InterfaceIndex!=FWD_INTERNAL_INTERFACE_INDEX)
+ fwRoute->FR_InterfaceReference
+ = LocateInterface (InterfaceIndex, NULL);
+ else
+ fwRoute->FR_InterfaceReference = InternalInterface;
+ if (fwRoute->FR_InterfaceReference!=NULL) {
+ AcquireInterfaceReference (fwRoute->FR_InterfaceReference);
+ KeReleaseSpinLock (&InterfaceTableLock, oldIRQL);
+
+ ExAcquireFastMutex (&WriterMutex);
+ // Check if route is already there
+ if (LocateRoute (Network, &prev)==NULL) {
+ fwRoute->FR_Next = *prev;
+ *prev = fwRoute;
+ }
+ else {
+ ReleaseInterfaceReference (fwRoute->FR_InterfaceReference);
+ fwRoute->FR_InterfaceReference = NULL;
+ IpxFwdDbgPrint (DBG_ROUTE_TABLE, DBG_ERROR,
+ ("IpxFwd: Route for net %08lx"
+ " is already in the table!\n", Network));
+ status = STATUS_UNSUCCESSFUL;
+ }
+
+ ExReleaseFastMutex (&WriterMutex);
+ }
+ else {
+ KeReleaseSpinLock (&InterfaceTableLock, oldIRQL);
+ IpxFwdDbgPrint (DBG_ROUTE_TABLE, DBG_ERROR,
+ ("IpxFwd: Interface %ld for route for net %08lx"
+ " is not in the table!\n", InterfaceIndex, Network));
+ status = STATUS_UNSUCCESSFUL;
+ }
+ }
+ else {
+ ExAcquireFastMutex (&WriterMutex);
+ // Just check if we do not have it already
+ if (GlobalRoute==NULL) {
+ fwRoute->FR_InterfaceReference = GLOBAL_INTERFACE_REFERENCE;
+ GlobalNetwork = Network;
+ GlobalRoute = fwRoute;
+ }
+ else {
+ IpxFwdDbgPrint (DBG_ROUTE_TABLE, DBG_ERROR,
+ ("IpxFwd: Route for global net %08lx"
+ " is already in the table!\n", Network));
+ status = STATUS_UNSUCCESSFUL;
+ }
+ ExReleaseFastMutex (&WriterMutex);
+ }
+
+ if (NT_SUCCESS (status)) {
+ IpxFwdDbgPrint (DBG_ROUTE_TABLE, DBG_WARNING,
+ ("IpxFwd: Adding route for net %08lx"
+ " (rb: %08lx, NHA: %02x%02x%02x%02x%02x%02x,"
+ " if: %ld, icb: %08lx).\n",
+ Network, fwRoute,
+ NextHopAddress[0], NextHopAddress[1],
+ NextHopAddress[2], NextHopAddress[3],
+ NextHopAddress[4], NextHopAddress[5],
+ InterfaceIndex, fwRoute->FR_InterfaceReference));
+ }
+ else {
+ FreeRoute (fwRoute);
+ }
+ }
+ else
+ status = STATUS_INSUFFICIENT_RESOURCES;
+
+ return status;
+}
+
+/*++
+*******************************************************************
+ D e l e t e R o u t e
+
+Routine Description:
+ Deletes route from the hash table and releases the reference
+ to the interface control block associated with the route.
+Arguments:
+ Network - route's destination network
+Return Value:
+ STATUS_SUCCESS - route was deleted ok
+ STATUS_UNSUCCESSFUL - route is not in the table
+*******************************************************************
+--*/
+NTSTATUS
+DeleteRoute (
+ ULONG Network
+ ) {
+ PFWD_ROUTE fwRoute, *prev;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ ExAcquireFastMutex (&WriterMutex);
+
+ if ((GlobalRoute!=NULL)
+ && (GlobalNetwork==Network)) {
+ fwRoute = GlobalRoute;
+ GlobalNetwork = 0xFFFFFFFF;
+ GlobalRoute = NULL;
+ }
+ else if ((fwRoute=LocateRoute (Network, &prev))!=NULL) {
+ *prev = fwRoute->FR_Next;
+ }
+
+ if (fwRoute!=NULL) {
+ IpxFwdDbgPrint (DBG_ROUTE_TABLE, DBG_WARNING,
+ ("IpxFwd: Deleting route for net %08lx (rb: %08lx).\n",
+ Network, fwRoute));
+ WaitForAllReaders (&RWLock);
+ if (fwRoute->FR_InterfaceReference!=GLOBAL_INTERFACE_REFERENCE) {
+ ReleaseInterfaceReference (fwRoute->FR_InterfaceReference);
+ }
+ fwRoute->FR_InterfaceReference = NULL;
+ ReleaseRouteReference (fwRoute);
+ }
+ else {
+ IpxFwdDbgPrint (DBG_ROUTE_TABLE, DBG_ERROR,
+ ("IpxFwd: Could not delete route for net %08lx because it is not in the table.\n",
+ Network));
+ status = STATUS_UNSUCCESSFUL;
+ }
+
+ ExReleaseFastMutex (&WriterMutex);
+ return status;
+}
+
+
+/*++
+*******************************************************************
+ U p d a t e R o u t e
+
+Routine Description:
+ Updates route in the hash table
+Arguments:
+ Network - route's destination network
+ NextHopAddress - mac address of next hop router if network is not
+ directly connected
+ TickCount - ticks to reach the destination net
+ HopCount - hopss to reach the destination net
+ InterfaceIndex - index of the associated interface (through which
+ packets destined to the network are to be sent)
+Return Value:
+ STATUS_SUCCESS - interface info retreived ok
+ STATUS_UNSUCCESSFUL - interface is not in the table
+*******************************************************************
+--*/
+NTSTATUS
+UpdateRoute (
+ ULONG Network,
+ UCHAR *NextHopAddress,
+ USHORT TickCount,
+ USHORT HopCount,
+ ULONG InterfaceIndex
+ ) {
+ PFWD_ROUTE fwRoute = NULL, newRoute, *prev;
+ PINTERFACE_CB ifCB = NULL;
+ KIRQL oldIRQL;
+ NTSTATUS status = STATUS_SUCCESS;
+
+
+ ExAcquireFastMutex (&WriterMutex);
+
+ if ((GlobalRoute!=NULL)
+ && (GlobalNetwork==Network)) {
+ ASSERT (InterfaceIndex==0xFFFFFFFF);
+ fwRoute = GlobalRoute;
+ }
+ else {
+ ASSERT (InterfaceIndex!=0xFFFFFFFF);
+ fwRoute = LocateRoute (Network, &prev);
+ }
+
+ if (fwRoute!=NULL) {
+ if (InterfaceIndex!=0xFFFFFFFF) {
+ if (fwRoute->FR_InterfaceReference->ICB_Index!=InterfaceIndex) {
+ // Get a reference to new interface
+ KeAcquireSpinLock (&InterfaceTableLock, &oldIRQL);
+ if (InterfaceIndex!=FWD_INTERNAL_INTERFACE_INDEX)
+ ifCB = LocateInterface (InterfaceIndex, NULL);
+ else
+ ifCB = InternalInterface;
+ if (ifCB!=NULL) {
+ AcquireInterfaceReference (ifCB);
+ }
+ else {
+ KeReleaseSpinLock (&InterfaceTableLock, oldIRQL);
+ status = STATUS_UNSUCCESSFUL;
+ goto ExitUpdate;
+ }
+ KeReleaseSpinLock (&InterfaceTableLock, oldIRQL);
+ }
+ else {
+ ifCB = fwRoute->FR_InterfaceReference;
+ AcquireInterfaceReference (ifCB);
+ }
+ }
+ else
+ ifCB = GLOBAL_INTERFACE_REFERENCE;
+ newRoute = AllocateRoute ();
+ if (newRoute!=NULL) {
+ newRoute->FR_Network = Network;
+ IPX_NODE_CPY (newRoute->FR_NextHopAddress, NextHopAddress);
+ newRoute->FR_TickCount = TickCount;
+ newRoute->FR_HopCount = HopCount;
+ newRoute->FR_ReferenceCount = 0;
+ newRoute->FR_InterfaceReference = ifCB;
+ // Lock the table only when updating it
+ if (InterfaceIndex!=0xFFFFFFFF) {
+ newRoute->FR_Next = fwRoute->FR_Next;
+ *prev = newRoute;
+ }
+ else
+ GlobalRoute = newRoute;
+
+ WaitForAllReaders (&RWLock)
+ if (fwRoute->FR_InterfaceReference!=GLOBAL_INTERFACE_REFERENCE) {
+ ReleaseInterfaceReference (fwRoute->FR_InterfaceReference);
+ }
+ fwRoute->FR_InterfaceReference = NULL;
+ ReleaseRouteReference (fwRoute);
+
+ }
+ else
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ else
+ status = STATUS_UNSUCCESSFUL;
+
+ExitUpdate:
+ ExReleaseFastMutex (&WriterMutex);
+ return status;
+}
+
+
+/*++
+*******************************************************************
+ F i n d D e s t i n a t i o n
+
+Routine Description:
+ Finds destination interface for IPX address and
+ returns reference to its control block.
+Arguments:
+ Network - destination network
+ Node - destination node (needed in case of global client)
+ Route - buffer to hold reference to route block
+Return Value:
+ Reference to destination interface CB
+ NULL if route it not found
+*******************************************************************
+--*/
+PINTERFACE_CB
+FindDestination (
+ IN ULONG Network,
+ IN PUCHAR Node,
+ OUT PFWD_ROUTE *Route
+ ) {
+ PFWD_ROUTE fwRoute;
+ PINTERFACE_CB ifCB;
+ RWCOOKIE cookie;
+
+ AcquireReaderAccess (&RWLock, cookie);
+ if ((GlobalRoute!=NULL)
+ && (GlobalNetwork==Network)) {
+ if (Node!=NULL) { // If caller did not specify node,
+ // we can't find the route
+ union {
+ ULONGLONG Node64[1];
+ UCHAR Node[6];
+ } u;
+ u.Node64[0] = 0;
+ IPX_NODE_CPY (u.Node, Node);
+
+ ifCB = LocateClientInterface (u.Node64, NULL);
+ if (ifCB!=NULL) {
+ AcquireRouteReference (GlobalRoute);
+ *Route = GlobalRoute;
+ AcquireInterfaceReference (ifCB);
+ }
+ else
+ *Route = NULL;
+ }
+ else {
+ ifCB = NULL;
+ *Route = NULL;
+ }
+ }
+ else {
+ *Route = fwRoute = LocateRoute (Network, NULL);
+ if (fwRoute!=NULL) {
+ AcquireRouteReference (fwRoute);
+ ifCB = fwRoute->FR_InterfaceReference;
+ AcquireInterfaceReference (ifCB);
+ }
+ else
+ ifCB = NULL;
+ }
+ ReleaseReaderAccess (&RWLock, cookie);
+ return ifCB;
+}
+
+/*++
+*******************************************************************
+ A d d N B R o u t e s
+
+Routine Description:
+ Adds netbios names associated with interface to netbios
+ route hash table
+Arguments:
+ ifCB - interface with which names are associated
+ Names - array of names
+ Count - number of names in the array
+ routeArray - buffer to place allocated array of routes
+Return Value:
+ STATUS_SUCCESS - names were added ok
+ STATUS_UNSUCCESSFUL - one of the names is already in the table
+ STATUS_INSUFFICIENT_RESOURCES - can't allocate memory for
+ route array
+*******************************************************************
+--*/
+NTSTATUS
+AddNBRoutes (
+ PINTERFACE_CB ifCB,
+ FWD_NB_NAME Names[],
+ ULONG Count,
+ PNB_ROUTE *routeArray
+ ) {
+ PNB_ROUTE nbRoutes, *prev;
+ NTSTATUS status = STATUS_SUCCESS;
+
+ nbRoutes = (PNB_ROUTE)ExAllocatePoolWithTag (
+ NonPagedPool, sizeof (NB_ROUTE)*Count, FWD_POOL_TAG);
+ if (nbRoutes!=NULL) {
+ ULONG i;
+
+ ExAcquireFastMutex (&WriterMutex);
+
+ for (i=0; i<Count; i++) {
+ nbRoutes[i].NBR_Name128[0] = nbRoutes[i].NBR_Name128[1] = 0;
+ NB_NAME_CPY (nbRoutes[i].NBR_Name, &Names[i]);
+ // Check if route is already there
+ if (LocateNBRoute (nbRoutes[i].NBR_Name128, &prev)==NULL) {
+ nbRoutes[i].NBR_Destination = ifCB;
+ nbRoutes[i].NBR_Next = *prev;
+ *prev = &nbRoutes[i];
+ IpxFwdDbgPrint (DBG_NBROUTE_TABLE, DBG_WARNING,
+ ("IpxFwd: Adding nb route for name %16s.\n",Names[i]));
+ }
+ else {
+ IpxFwdDbgPrint (DBG_NBROUTE_TABLE, DBG_ERROR,
+ ("IpxFwd: Route for nb name %16s"
+ " is already in the table!\n", Names[i]));
+ break;
+ }
+ }
+ ExReleaseFastMutex (&WriterMutex);
+ if (i==Count) {
+ *routeArray = nbRoutes;
+ status = STATUS_SUCCESS;
+
+ }
+ else {
+ status = STATUS_UNSUCCESSFUL;
+ DeleteNBRoutes (nbRoutes, i);
+ }
+ }
+ else {
+ IpxFwdDbgPrint (DBG_NBROUTE_TABLE, DBG_ERROR,
+ ("IpxFwd: Could allocate nb route array for if: %ld"
+ " (icb: %08lx).\n", ifCB->ICB_Index, ifCB));
+ status = STATUS_INSUFFICIENT_RESOURCES;
+ }
+ return status;
+}
+
+/*++
+*******************************************************************
+ D e l e t e N B R o u t e s
+
+Routine Description:
+ Deletes nb routes in the array from the route table and frees
+ the array
+Arguments:
+ nbRoutes - array of routes
+ Count - number of routes in the array
+Return Value:
+ STATUS_SUCCESS - route was deleted ok
+ STATUS_UNSUCCESSFUL - route is not in the table
+*******************************************************************
+--*/
+NTSTATUS
+DeleteNBRoutes (
+ PNB_ROUTE nbRoutes,
+ ULONG Count
+ ) {
+ PNB_ROUTE *prev;
+ NTSTATUS status = STATUS_SUCCESS;
+ ULONG i;
+
+ ExAcquireFastMutex (&WriterMutex);
+ for (i=0; i<Count; i++) {
+ PNB_ROUTE cur = LocateNBRoute (nbRoutes[i].NBR_Name128, &prev);
+ ASSERT (cur==&nbRoutes[i]);
+ *prev = nbRoutes[i].NBR_Next;
+ IpxFwdDbgPrint (DBG_NBROUTE_TABLE, DBG_WARNING,
+ ("IpxFwd: Deleting nb route for name %16s.\n",
+ nbRoutes[i].NBR_Name));
+ }
+
+ WaitForAllReaders (&RWLock);
+ ExReleaseFastMutex (&WriterMutex);
+
+ ExFreePool (nbRoutes);
+
+ return STATUS_SUCCESS;
+}
+
+
+/*++
+*******************************************************************
+ F i n d N B D e s t i n a t i o n
+
+Routine Description:
+ Finds destination interface for nb name and
+ returns reference to its control block.
+Arguments:
+ Name - name to look for
+Return Value:
+ Reference to destination interface CB
+ NULL if route it not found
+*******************************************************************
+--*/
+PINTERFACE_CB
+FindNBDestination (
+ IN PUCHAR Name
+ ) {
+ PNB_ROUTE nbRoute;
+ PINTERFACE_CB ifCB;
+ RWCOOKIE cookie;
+ union {
+ ULONGLONG Name128[2];
+ UCHAR Name[16];
+ } u;
+ u.Name128[0] = u.Name128[1] = 0;
+ NB_NAME_CPY (u.Name, Name);
+
+ AcquireReaderAccess (&RWLock, cookie);
+ nbRoute = LocateNBRoute (u.Name128, NULL);
+ if (nbRoute!=NULL) {
+ ifCB = nbRoute->NBR_Destination;
+ AcquireInterfaceReference (ifCB);
+ }
+ else
+ ifCB = NULL;
+ ReleaseReaderAccess (&RWLock, cookie);
+ return ifCB;
+}
+
diff --git a/private/ntos/tdi/isn/fwd/tables.h b/private/ntos/tdi/isn/fwd/tables.h
new file mode 100644
index 000000000..6f86e52a8
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/tables.h
@@ -0,0 +1,708 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ ntos\tdi\isn\fwd\tables.h
+
+Abstract:
+ IPX Forwarder Driver Tables
+
+
+Author:
+
+ Vadim Eydelman
+
+Revision History:
+
+--*/
+
+#ifndef _IPXFWD_TABLES_
+#define _IPXFWD_TABLES_
+
+// Ranges and defaults for registry configurable parameters
+#define MIN_ROUTE_SEGMENT_SIZE PAGE_SIZE
+#define MAX_ROUTE_SEGMENT_SIZE (PAGE_SIZE*8)
+#define DEF_ROUTE_SEGMENT_SIZE MIN_ROUTE_SEGMENT_SIZE
+
+#define MIN_INTERFACE_HASH_SIZE 31
+#define MAX_INTERFACE_HASH_SIZE 257
+#define DEF_INTERFACE_HASH_SIZE MAX_INTERFACE_HASH_SIZE
+
+#define MIN_CLIENT_HASH_SIZE 31
+#define MAX_CLIENT_HASH_SIZE 257
+#define DEF_CLIENT_HASH_SIZE MAX_CLIENT_HASH_SIZE
+
+#define MIN_NB_ROUTE_HASH_SIZE 31
+#define MAX_NB_ROUTE_HASH_SIZE 1023
+#define DEF_NB_ROUTE_HASH_SIZE 257
+
+#define MAX_SEND_PKTS_QUEUED 256 // No defined range
+
+#define NUM_INTERFACES_PER_SEGMENT 16 // Not configurable currently
+#define NUM_NB_ROUTES_PER_SEGMENT 16 // Not configurable currently
+
+
+// Special number reserved for routes that point to
+// client on global net
+#define GLOBAL_INTERFACE_REFERENCE ((PINTERFACE_CB)-1)
+
+// All types of WAN are emulated as ETHERNET by NDIS
+#define WAN_PACKET_SIZE 1500
+
+
+#define INVALID_NETWORK_NUMBER 0xFFFFFFFF
+#define INVALID_NIC_ID 0xFFFF
+
+
+// Interface control block
+struct _INTERFACE_CB;
+typedef struct _INTERFACE_CB INTERFACE_CB, *PINTERFACE_CB;
+struct _FWD_ROUTE;
+typedef struct _FWD_ROUTE FWD_ROUTE, *PFWD_ROUTE;
+struct _NB_ROUTE;
+typedef struct _NB_ROUTE NB_ROUTE, *PNB_ROUTE;
+
+struct _FWD_ROUTE {
+ ULONG FR_Network; // Dest network
+ USHORT FR_TickCount; // Route params
+ USHORT FR_HopCount; //
+ UCHAR FR_NextHopAddress[6]; // Next hop router
+ PINTERFACE_CB FR_InterfaceReference; // Associated if CB
+ // or NULL if global
+ // network for clients
+ LONG FR_ReferenceCount; // Number of external
+ // references for this
+ // block (must keep the
+ // it till all of them
+ // are released
+ PFWD_ROUTE FR_Next; // Next route in the
+ // table
+};
+
+struct _INTERFACE_CB {
+ ULONG ICB_Index; // Unique ID
+ ULONG ICB_Network; // Network we boud to
+ union {
+ ULONGLONG ICB_ClientNode64[1];// For clients on
+ // global net (faster
+ // comparisons and
+ // hashing using 64
+ // bit support)
+ UCHAR ICB_RemoteNode[6]; // Peer node for demand
+ // dial connections
+ };
+ UCHAR ICB_LocalNode[6]; // Node we bound to
+ USHORT ICB_Flags;
+#define FWD_IF_ENABLED 0x0001
+#define SET_IF_ENABLED(ifCB) ifCB->ICB_Flags |= FWD_IF_ENABLED;
+#define SET_IF_DISABLED(ifCB) ifCB->ICB_Flags &= ~FWD_IF_ENABLED;
+#define IS_IF_ENABLED(ifCB) (ifCB->ICB_Flags&FWD_IF_ENABLED)
+
+#define FWD_IF_CONNECTING 0x0002
+#define SET_IF_CONNECTING(ifCB) ifCB->ICB_Flags |= FWD_IF_CONNECTING;
+#define SET_IF_NOT_CONNECTING(ifCB) ifCB->ICB_Flags &= ~FWD_IF_CONNECTING;
+#define IS_IF_CONNECTING(ifCB) (ifCB->ICB_Flags&FWD_IF_CONNECTING)
+ USHORT ICB_NicId; // Nic id we bound to
+ UCHAR ICB_InterfaceType;
+ UCHAR ICB_NetbiosDeliver;
+ BOOLEAN ICB_NetbiosAccept;
+
+ PNB_ROUTE ICB_NBRoutes; // Array of associated
+ // NB routes
+ ULONG ICB_NBRouteCount; // Number of nb routes
+
+ LONGLONG ICB_DisconnectTime; // Time when if was disconnected
+ FWD_IF_STATS ICB_Stats; // Accumulated
+ PFWD_ROUTE ICB_CashedRoute; // MRU dest route
+ PINTERFACE_CB ICB_CashedInterface;// MRU dest if
+ NIC_HANDLE ICB_AdapterContext; // IPX stack supplied
+ PVOID ICB_FilterInContext;
+ PVOID ICB_FilterOutContext;
+ LONG ICB_PendingQuota; // Remaining quota of
+ // packets that can be
+ // pending on
+ // the interface
+ LIST_ENTRY ICB_ExternalQueue; // Queue of external (received)
+ // packets
+ LIST_ENTRY ICB_InternalQueue; // Queue of internal (send)
+ // requests
+#if DBG
+ LIST_ENTRY ICB_InSendQueue; // packets being
+ // sent by ipx
+#endif
+ INT ICB_PacketListId; // ID of the packet list
+ // (for the max frame size
+ // on this interface)
+ LIST_ENTRY ICB_IndexHashLink; // Link in interface idx hash
+ LIST_ENTRY ICB_ConnectionLink; // Link in connection queue
+ PNDIS_PACKET ICB_ConnectionPacket; // Packet that caused connection
+ // request
+ PUCHAR ICB_ConnectionData; // Pointer into packet to
+ // place where actual data
+ // (header) starts
+ PINTERFACE_CB ICB_NodeHashLink; // Link in client node hash
+ ULONG ICB_ReferenceCount; // Number of routes that
+ // point to this CB
+ KSPIN_LOCK ICB_Lock; // Protects state,
+ // queues
+};
+
+#define InitICB(ifCB,IfIndex,IfType,NbAccept,NbDeliver) { \
+ (ifCB)->ICB_Index = IfIndex; \
+ (ifCB)->ICB_Network = INVALID_NETWORK_NUMBER; \
+ (ifCB)->ICB_Flags = 0; \
+ (ifCB)->ICB_NicId = INVALID_NIC_ID; \
+ (ifCB)->ICB_InterfaceType = IfType; \
+ (ifCB)->ICB_NetbiosAccept = NbAccept; \
+ (ifCB)->ICB_NetbiosDeliver = NbDeliver; \
+ memset (&(ifCB)->ICB_Stats, 0, sizeof (FWD_IF_STATS));\
+ KeInitializeSpinLock (&(ifCB)->ICB_Lock); \
+ (ifCB)->ICB_CashedInterface = NULL; \
+ (ifCB)->ICB_CashedRoute = NULL; \
+ (ifCB)->ICB_ReferenceCount = 0; \
+ (ifCB)->ICB_FilterInContext = NULL; \
+ (ifCB)->ICB_FilterOutContext = NULL; \
+ (ifCB)->ICB_ClientNode64[0] = 0; \
+ (ifCB)->ICB_NBRoutes = NULL; \
+ (ifCB)->ICB_PacketListId = -1; \
+ InitializeListHead (&(ifCB)->ICB_InternalQueue); \
+ InitializeListHead (&(ifCB)->ICB_ExternalQueue); \
+ (ifCB)->ICB_PendingQuota = MaxSendPktsQueued; \
+ switch ((ifCB)->ICB_InterfaceType) { \
+ case FWD_IF_PERMANENT: \
+ (ifCB)->ICB_Stats.OperationalState = FWD_OPER_STATE_DOWN;\
+ break; \
+ case FWD_IF_DEMAND_DIAL: \
+ case FWD_IF_LOCAL_WORKSTATION: \
+ case FWD_IF_REMOTE_WORKSTATION: \
+ (ifCB)->ICB_Stats.OperationalState = FWD_OPER_STATE_SLEEPING;\
+ KeQuerySystemTime ((PLARGE_INTEGER)&(ifCB)->ICB_DisconnectTime);\
+ (ifCB)->ICB_DisconnectTime -= (LONGLONG)SpoofingTimeout*10000000;\
+ break; \
+ } \
+}
+
+
+// Routes for netbios names (staticly seeded to reduce
+// internet broadcast traffic)
+struct _NB_ROUTE {
+ union {
+ ULONGLONG NBR_Name128[2];
+ UCHAR NBR_Name[16]; // Netbios name of destination
+ };
+ PINTERFACE_CB NBR_Destination; // Interface to send to
+ PNB_ROUTE NBR_Next; // Next route in the name list
+};
+
+
+// List used to allocate packets destined to WAN interfaces
+extern INT WanPacketListId;
+// Max number of outstanding sends
+extern ULONG MaxSendPktsQueued;
+
+// Segment sizes
+extern ULONG RouteSegmentSize;
+extern ULONG InterfaceSegmentSize;
+extern ULONG NBNameSegementSize;
+
+// Sizes of hash tables
+extern ULONG RouteHashSize;
+extern ULONG InterfaceHashSize;
+extern ULONG ClientHashSize;
+extern ULONG NBRouteHashSize;
+
+// Number of global client network
+extern ULONG GlobalNetwork;
+// Interface reserved for internal network
+extern PINTERFACE_CB InternalInterface;
+
+/*++
+*******************************************************************
+ C r e a t e T a b l e s
+
+Routine Description:
+ Allocates and intializes all hash tables and related structures
+Arguments:
+ None
+Return Value:
+ STATUS_SUCCESS - tables were created ok
+ STATUS_INSUFFICIENT_RESOURCES - resource allocation failed
+*******************************************************************
+--*/
+NTSTATUS
+CreateTables (
+ void
+ );
+
+/*++
+*******************************************************************
+ D e l e t e T a b l e s
+
+Routine Description:
+ Releases resources allocated for all hash tables
+Arguments:
+ None
+Return Value:
+ STATUS_SUCCESS - tables were freed ok
+*******************************************************************
+--*/
+NTSTATUS
+DeleteTables (
+ void
+ );
+
+/*++
+*******************************************************************
+ F r e e I n t e r f a c e
+
+Routine Description:
+ Releases memory allocated for interface to interface memory
+ zone.
+Arguments:
+ fwRoute - route block to release
+Return Value:
+ None
+*******************************************************************
+--*/
+VOID
+FreeInterface (
+ PINTERFACE_CB ifCB
+ );
+
+/*++
+*******************************************************************
+ F r e e R o u t e
+
+Routine Description:
+ Releases memory allocated for route to route memory
+ zone.
+Arguments:
+ fwRoute - route block to release
+Return Value:
+ None
+*******************************************************************
+--*/
+VOID
+FreeRoute (
+ PFWD_ROUTE fwRoute
+ );
+/*++
+*******************************************************************
+ A c q u i r e I n t e r f a c e R e f e r e n c e
+
+Routine Description:
+ Increments refernce count of interface control block
+ ICB can't be freed until all references to it are released.
+ The caller of this routine should have already had a reference
+ to the interface or must hold an InterfaceLock
+Arguments:
+ ifCB - interface control block to reference
+Return Value:
+ None
+*******************************************************************
+--*/
+//VOID
+//AcquireInterfaceReference (
+// PINTERFACE_CB ifCB
+// );
+#if DBG
+#define AcquireInterfaceReference(ifCB) \
+ do { \
+ ASSERTMSG ("Referenced ifCB is dead ", \
+ InterlockedIncrement(&ifCB->ICB_ReferenceCount)>0); \
+ } while (0)
+#else
+#define AcquireInterfaceReference(ifCB) \
+ InterlockedIncrement(&ifCB->ICB_ReferenceCount)
+#endif
+/*++
+*******************************************************************
+ R e l e a s e I n t e r f a c e R e f e r e n c e
+
+Routine Description:
+ Decrements refernce count of interface control block
+Arguments:
+ ifCB - interface control block to release
+Return Value:
+ None
+*******************************************************************
+--*/
+//PINTERFACE_CB
+//ReleaseInterfaceReference (
+// PINTERFACE_CB ifCB
+// );
+// if it drops below 0, it has alredy been removed from the table
+#define ReleaseInterfaceReference(ifCB) ( \
+ (InterlockedDecrement (&ifCB->ICB_ReferenceCount)>=0) \
+ ? ifCB \
+ : (FreeInterface (ifCB), (ifCB = NULL)) \
+)
+
+/*++
+*******************************************************************
+ I n t e r f a c e C o n t e x t T o R e f e r e n c e
+
+Routine Description:
+ Verifies that context supplied by the IPX stack is a valid
+ interface block and is still bound to the adapter with which
+ it is associated in the IPX stack
+Arguments:
+ ifCB - interface control block to reference
+ NicId - id of the adapter to which interface is bound
+Return Value:
+ None
+*******************************************************************
+--*/
+//PINTERFACE_CB
+//InterfaceContextToReference (
+// PVOID Context
+// );
+#define InterfaceContextToReference(Context,NicId) ( \
+ (InterlockedIncrement(&((PINTERFACE_CB)Context)->ICB_ReferenceCount)>0) \
+ ? ((NicId==((PINTERFACE_CB)Context)->ICB_NicId) \
+ ? (PINTERFACE_CB)Context \
+ : (ReleaseInterfaceReference(((PINTERFACE_CB)Context)), NULL)) \
+ : NULL \
+ )
+
+/*++
+*******************************************************************
+ G e t I n t e r f a c e R e f e r e n c e
+
+Routine Description:
+ Returns reference interface based on its index
+Arguments:
+ InterfaceIndex - unique id of the interface
+Return Value:
+ Pointer to interface control block if there is one in the table
+ NULL otherwise
+*******************************************************************
+--*/
+PINTERFACE_CB
+GetInterfaceReference (
+ ULONG InterfaceIndex
+ );
+
+
+/*++
+*******************************************************************
+ G e t N e x t I n t e r f a c e R e f e r e n c e
+
+Routine Description:
+ Returns reference to the next interface in the table
+ Reference to the provided interface is released
+Arguments:
+ ifCB - interface to start with or NULL to start from the
+ beginning of the interface table
+Return Value:
+ Pointer to interface control block if thare are any more interfaces
+ in the table
+ NULL otherwise
+*******************************************************************
+--*/
+PINTERFACE_CB
+GetNextInterfaceReference (
+ PINTERFACE_CB ifCB
+ );
+
+/*++
+*******************************************************************
+ A d d I n t e r f a c e
+
+Routine Description:
+ Adds interface control block to the table.
+Arguments:
+ InterfaceIndex - unique if of the interface
+ Info - interface paramters
+Return Value:
+ STATUS_SUCCESS - interface added ok
+ STATUS_UNSUCCESSFULL - interface is already in the table
+ STATUS_INSUFFICIENT_RESOURCES - can't allocate memory for
+ interface CB
+*******************************************************************
+--*/
+NTSTATUS
+AddInterface (
+ ULONG InterfaceIndex,
+ UCHAR InterfaceType,
+ BOOLEAN NetbiosAccept,
+ UCHAR NetbiosDeliver
+ );
+
+/*++
+*******************************************************************
+ A d d G l o b a l N e t C l i e n t
+
+Routine Description:
+ Adds interface control block to the table of
+ clients on the global network (should be done when
+ client connects)
+Arguments:
+ ifCB - interface control block to add to the table
+Return Value:
+ STATUS_SUCCESS - interface was added ok
+ STATUS_UNSUCCESSFULL - another interface with the same
+ node address is already in the table
+*******************************************************************
+--*/
+NTSTATUS
+AddGlobalNetClient (
+ PINTERFACE_CB ifCB
+ );
+
+/*++
+*******************************************************************
+ D e l e t e G l o b a l N e t C l i e n t
+
+Routine Description:
+ Removes interface control block from the table of
+ clients on the global network (should be done when
+ client disconnects)
+Arguments:
+ ifCB - interface control block to remove from the table
+Return Value:
+ STATUS_SUCCESS - interface was removed ok
+*******************************************************************
+--*/
+NTSTATUS
+DeleteGlobalNetClient (
+ PINTERFACE_CB ifCB
+ );
+
+/*++
+*******************************************************************
+ D e l e t e I n t e r f a c e
+
+Routine Description:
+ Deletes interface control block (the block is not actually
+ disposed of until all references to it are released).
+Arguments:
+ InterfaceIndex - unique if of the interface
+Return Value:
+ STATUS_SUCCESS - interface info retreived ok
+ STATUS_UNSUCCESSFULL - interface is not in the table
+*******************************************************************
+--*/
+NTSTATUS
+DeleteInterface (
+ ULONG InterfaceIndex
+ );
+
+/*++
+*******************************************************************
+ A d d R o u t e
+
+Routine Description:
+ Adds route to the hash table and finds and stores the reference
+ to the associated interface control block in the route.
+Arguments:
+ Network - route's destination network
+ NextHopAddress - mac address of next hop router if network is not
+ directly connected
+ TickCount - ticks to reach the destination net
+ HopCount - hopss to reach the destination net
+ InterfaceIndex - index of the associated interface (through which
+ packets destined to the network are to be sent)
+Return Value:
+ STATUS_SUCCESS - route was added ok
+ STATUS_UNSUCCESSFUL - route is already in the table
+ STATUS_INSUFFICIENT_RESOURCES - can't allocate memory for
+ route block
+*******************************************************************
+--*/
+NTSTATUS
+AddRoute (
+ ULONG Network,
+ UCHAR *NextHopAddress,
+ USHORT TickCount,
+ USHORT HopCount,
+ ULONG InterfaceIndex
+ );
+
+/*++
+*******************************************************************
+ D e l e t e R o u t e
+
+Routine Description:
+ Deletes route from the hash table and releases the reference
+ to the interface control block associated with the route.
+Arguments:
+ Network - route's destination network
+Return Value:
+ STATUS_SUCCESS - route was deleted ok
+ STATUS_UNSUCCESSFUL - route is not in the table
+*******************************************************************
+--*/
+NTSTATUS
+DeleteRoute (
+ ULONG Network
+ );
+
+/*++
+*******************************************************************
+ U p d a t e R o u t e
+
+Routine Description:
+ Updates route in the hash table
+Arguments:
+ Network - route's destination network
+ NextHopAddress - mac address of next hop router if network is not
+ directly connected
+ TickCount - ticks to reach the destination net
+ HopCount - hopss to reach the destination net
+ InterfaceIndex - index of the associated interface (through which
+ packets destined to the network are to be sent)
+Return Value:
+ STATUS_SUCCESS - interface info retreived ok
+ STATUS_UNSUCCESSFUL - interface is not in the table
+*******************************************************************
+--*/
+NTSTATUS
+UpdateRoute (
+ ULONG Network,
+ UCHAR *NextHopAddress,
+ USHORT TickCount,
+ USHORT HopCount,
+ ULONG InterfaceIndex
+ );
+
+/*++
+*******************************************************************
+ F i n d D e s t i n a t i o n
+
+Routine Description:
+ Finds destination interface for IPX address and
+ returns reference to its control block.
+Arguments:
+ Network - destination network
+ Node - destination node (needed in case of global client)
+ Route - buffer to place route reference
+Return Value:
+ Reference to destination interface CB
+ NULL if route it not found
+*******************************************************************
+--*/
+PINTERFACE_CB
+FindDestination (
+ IN ULONG Network,
+ IN PUCHAR Node,
+ OUT PFWD_ROUTE *Route
+ );
+/*++
+*******************************************************************
+ A c q u i r e R o u t e R e f e r e n c e
+
+Routine Description:
+ Increments refernce count of the route block
+ Route block can't be freed until all references to it are released.
+ The caller of this routine should have already had a reference
+ to the route or must hold an TableWriteLock
+Arguments:
+ fwRoute - route block to reference
+Return Value:
+ None
+*******************************************************************
+--*/
+//VOID
+//AcquireRouteReference (
+// PFW+ROUTE fwRoute
+// );
+#define AcquireRouteReference(fwRoute) \
+ InterlockedIncrement(&fwRoute->FR_ReferenceCount)
+
+
+
+/*++
+*******************************************************************
+ R e l e a s e R o u t e R e f e r e n c e
+
+Routine Description:
+ Decrements refernce count of route block
+Arguments:
+ fwRoute - route block to release
+Return Value:
+ None
+*******************************************************************
+--*/
+//VOID
+//ReleaseRouteReference (
+// PFW_ROUTE fwRoute
+// );
+// if it drops below 0, it has alredy been removed from the table
+#define ReleaseRouteReference(fwRoute) { \
+ if (InterlockedDecrement (&fwRoute->FR_ReferenceCount)<0) { \
+ FreeRoute (fwRoute); \
+ fwRoute = NULL; \
+ } \
+}
+
+
+/*++
+*******************************************************************
+ A d d N B R o u t e s
+
+Routine Description:
+ Adds netbios names associated with interface to netbios
+ route hash table
+Arguments:
+ ifCB - interface with which names are associated
+ Names - array of names
+ Count - number of names in the array
+ routeArray - buffer to place pointer to allocated array of routes
+Return Value:
+ STATUS_SUCCESS - names were added ok
+ STATUS_UNSUCCESSFUL - one of the names is already in the table
+ STATUS_INSUFFICIENT_RESOURCES - can't allocate memory for
+ route array
+*******************************************************************
+--*/
+NTSTATUS
+AddNBRoutes (
+ PINTERFACE_CB ifCB,
+ FWD_NB_NAME Names[],
+ ULONG Count,
+ PNB_ROUTE *routeArray
+ );
+
+/*++
+*******************************************************************
+ D e l e t e N B R o u t e s
+
+Routine Description:
+ Deletes nb routes in the array from the route table and frees
+ the array
+Arguments:
+ nbRoutes - array of routes
+ Count - number of routes in the array
+Return Value:
+ STATUS_SUCCESS - route was deleted ok
+ STATUS_UNSUCCESSFUL - route is not in the table
+*******************************************************************
+--*/
+NTSTATUS
+DeleteNBRoutes (
+ PNB_ROUTE nbRoutes,
+ ULONG Count
+ );
+
+/*++
+*******************************************************************
+ F i n d N B D e s t i n a t i o n
+
+Routine Description:
+ Finds destination interface for nb name and
+ returns reference to its control block.
+Arguments:
+ Name - name to look for
+Return Value:
+ Reference to destination interface CB
+ NULL if route it not found
+*******************************************************************
+--*/
+PINTERFACE_CB
+FindNBDestination (
+ IN PUCHAR Name
+ );
+#endif
diff --git a/private/ntos/tdi/isn/fwd/up/makefile b/private/ntos/tdi/isn/fwd/up/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/up/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/tdi/isn/fwd/up/sources b/private/ntos/tdi/isn/fwd/up/sources
new file mode 100644
index 000000000..229bd8e34
--- /dev/null
+++ b/private/ntos/tdi/isn/fwd/up/sources
@@ -0,0 +1,31 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+UP_DRIVER=yes
+
+BINPLACE_FLAGS=$(BINPLACE_FLAGS) -d dump\up
+
+TARGETPATH=obj
+
+!include ..\sources.inc