|
|
/*++
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; }
|