diff options
Diffstat (limited to '')
-rw-r--r-- | private/ntos/tdi/isn/fwd/ipxbind.c | 462 |
1 files changed, 462 insertions, 0 deletions
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; +} + + |