485 lines
13 KiB
C
485 lines
13 KiB
C
/*++
|
||
|
||
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 (ExGetPreviousMode()!=KernelMode)
|
||
ZwClose (HdlIpxFile);
|
||
else
|
||
NtClose (HdlIpxFile);
|
||
IpxFwdDbgPrint (DBG_IPXBIND, DBG_ERROR,
|
||
("IpxFwd: Could not allocate input binding buffer!\n"));
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
|
||
//
|
||
// Zero out the memory so that there are no garbage pointers.
|
||
// - ShreeM
|
||
//
|
||
RtlZeroMemory(bip, sizeof(IPX_INTERNAL_BIND_INPUT));
|
||
|
||
// 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,
|
||
(ULONG)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
|
||
(ULONG)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
|
||
(ULONG)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 = STATUS_NETWORK_UNREACHABLE;
|
||
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);
|
||
}
|
||
|
||
//
|
||
// Fill in the hop count and tick count
|
||
//
|
||
RouteEntry->TickCount = fwRoute->FR_TickCount;
|
||
RouteEntry->HopCount = fwRoute->FR_HopCount;
|
||
|
||
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;
|
||
|
||
//
|
||
// Fill in the hop count and tick count
|
||
//
|
||
RouteEntry->TickCount = fwRoute->FR_TickCount;
|
||
RouteEntry->HopCount = fwRoute->FR_HopCount;
|
||
|
||
|
||
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;
|
||
}
|
||
|
||
|
||
|