Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

484 lines
13 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. ntos\tdi\isn\fwd\ipxbind.c
  5. Abstract:
  6. IPX Forwarder Driver interface with IPX stack driver
  7. Author:
  8. Vadim Eydelman
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. // global handle of the IPX driver
  13. HANDLE HdlIpxFile;
  14. // Buffer for IPX binding output structure
  15. PIPX_INTERNAL_BIND_RIP_OUTPUT IPXBindOutput=NULL;
  16. NTSTATUS
  17. IpxFwdFindRoute (
  18. IN PUCHAR Network,
  19. IN PUCHAR Node,
  20. OUT PIPX_FIND_ROUTE_REQUEST RouteEntry
  21. );
  22. /*++
  23. *******************************************************************
  24. B i n d T o I p x D r i v e r
  25. Routine Description:
  26. Exchanges binding information with IPX stack driver
  27. Arguments:
  28. None
  29. Return Value:
  30. STATUS_SUCCESS - exchange was done OK
  31. STATUS_INSUFFICIENT_RESOURCES - could not allocate buffers for
  32. info exchange
  33. error status returned by IPX stack driver
  34. *******************************************************************
  35. --*/
  36. NTSTATUS
  37. BindToIpxDriver (
  38. KPROCESSOR_MODE requestorMode
  39. ) {
  40. NTSTATUS status;
  41. IO_STATUS_BLOCK IoStatusBlock;
  42. OBJECT_ATTRIBUTES ObjectAttributes;
  43. PIPX_INTERNAL_BIND_INPUT bip;
  44. UNICODE_STRING UstrIpxFileName;
  45. PWSTR WstrIpxFileName;
  46. ASSERT (IPXBindOutput==NULL);
  47. // Read Ipx exported device name from the registry
  48. status = ReadIpxDeviceName (&WstrIpxFileName);
  49. if (!NT_SUCCESS (status))
  50. return status;
  51. RtlInitUnicodeString (&UstrIpxFileName, WstrIpxFileName);
  52. InitializeObjectAttributes(
  53. &ObjectAttributes,
  54. &UstrIpxFileName,
  55. OBJ_CASE_INSENSITIVE,
  56. NULL,
  57. NULL
  58. );
  59. if (requestorMode==UserMode)
  60. status = ZwCreateFile(&HdlIpxFile,
  61. SYNCHRONIZE | GENERIC_READ,
  62. &ObjectAttributes,
  63. &IoStatusBlock,
  64. NULL,
  65. FILE_ATTRIBUTE_NORMAL,
  66. FILE_SHARE_READ | FILE_SHARE_WRITE,
  67. FILE_OPEN,
  68. FILE_SYNCHRONOUS_IO_NONALERT,
  69. NULL,
  70. 0L);
  71. else
  72. status = NtCreateFile(&HdlIpxFile,
  73. SYNCHRONIZE | GENERIC_READ,
  74. &ObjectAttributes,
  75. &IoStatusBlock,
  76. NULL,
  77. FILE_ATTRIBUTE_NORMAL,
  78. FILE_SHARE_READ | FILE_SHARE_WRITE,
  79. FILE_OPEN,
  80. FILE_SYNCHRONOUS_IO_NONALERT,
  81. NULL,
  82. 0L);
  83. if (!NT_SUCCESS(status)) {
  84. IpxFwdDbgPrint (DBG_IPXBIND, DBG_ERROR,
  85. ("IpxFwd: Open of the IPX driver failed with %lx\n", status));
  86. return status;
  87. }
  88. IpxFwdDbgPrint (DBG_IPXBIND, DBG_INFORMATION,
  89. ("IpxFwd: Open of the IPX driver was successful.\n"));
  90. // First, send a IOCTL to find out how much data we need to allocate
  91. if ((bip = ExAllocatePoolWithTag (
  92. PagedPool,
  93. sizeof(IPX_INTERNAL_BIND_INPUT),
  94. FWD_POOL_TAG)) == NULL) {
  95. if (ExGetPreviousMode()!=KernelMode)
  96. ZwClose (HdlIpxFile);
  97. else
  98. NtClose (HdlIpxFile);
  99. IpxFwdDbgPrint (DBG_IPXBIND, DBG_ERROR,
  100. ("IpxFwd: Could not allocate input binding buffer!\n"));
  101. return STATUS_INSUFFICIENT_RESOURCES;
  102. }
  103. //
  104. // Zero out the memory so that there are no garbage pointers.
  105. // - ShreeM
  106. //
  107. RtlZeroMemory(bip, sizeof(IPX_INTERNAL_BIND_INPUT));
  108. // fill in our bind data
  109. // bip->Version = 1;
  110. bip->Version = ISN_VERSION;
  111. bip->Identifier = IDENTIFIER_RIP;
  112. bip->BroadcastEnable = TRUE;
  113. bip->LookaheadRequired = IPXH_HDRSIZE;
  114. bip->ProtocolOptions = 0;
  115. bip->ReceiveHandler = IpxFwdReceive;
  116. bip->ReceiveCompleteHandler = IpxFwdReceiveComplete;
  117. bip->SendCompleteHandler = IpxFwdSendComplete;
  118. bip->TransferDataCompleteHandler = IpxFwdTransferDataComplete;
  119. bip->FindRouteCompleteHandler = NULL;
  120. bip->LineUpHandler = IpxFwdLineUp;
  121. bip->LineDownHandler = IpxFwdLineDown;
  122. bip->InternalSendHandler = IpxFwdInternalSend;
  123. bip->FindRouteHandler = IpxFwdFindRoute;
  124. bip->InternalReceiveHandler = IpxFwdInternalReceive;
  125. // bip->RipParameters = GlobalWanNetwork ? IPX_RIP_PARAM_GLOBAL_NETWORK : 0;
  126. if (requestorMode==UserMode)
  127. status = ZwDeviceIoControlFile(
  128. HdlIpxFile, // HANDLE to File
  129. NULL, // HANDLE to Event
  130. NULL, // ApcRoutine
  131. NULL, // ApcContext
  132. &IoStatusBlock, // IO_STATUS_BLOCK
  133. IOCTL_IPX_INTERNAL_BIND, // IoControlCode
  134. bip, // Input Buffer
  135. sizeof(IPX_INTERNAL_BIND_INPUT),// Input Buffer Length
  136. NULL, // Output Buffer
  137. 0); // Output Buffer Length
  138. else
  139. status = NtDeviceIoControlFile(
  140. HdlIpxFile, // HANDLE to File
  141. NULL, // HANDLE to Event
  142. NULL, // ApcRoutine
  143. NULL, // ApcContext
  144. &IoStatusBlock, // IO_STATUS_BLOCK
  145. IOCTL_IPX_INTERNAL_BIND, // IoControlCode
  146. bip, // Input Buffer
  147. sizeof(IPX_INTERNAL_BIND_INPUT),// Input Buffer Length
  148. NULL, // Output Buffer
  149. 0); // Output Buffer Length
  150. if (status == STATUS_PENDING) {
  151. if (requestorMode==UserMode)
  152. status = ZwWaitForSingleObject(
  153. HdlIpxFile,
  154. FALSE,
  155. NULL);
  156. else
  157. status = NtWaitForSingleObject(
  158. HdlIpxFile,
  159. FALSE,
  160. NULL);
  161. if (NT_SUCCESS(status))
  162. status = IoStatusBlock.Status;
  163. }
  164. if (status != STATUS_BUFFER_TOO_SMALL) {
  165. IpxFwdDbgPrint (DBG_IPXBIND, DBG_ERROR,
  166. ("IpxFwd: Ioctl to the IPX driver failed with %lx\n", status));
  167. ExFreePool(bip);
  168. if (requestorMode==UserMode)
  169. ZwClose (HdlIpxFile);
  170. else
  171. NtClose (HdlIpxFile);
  172. return STATUS_INVALID_PARAMETER;
  173. }
  174. if ((IPXBindOutput = (PIPX_INTERNAL_BIND_RIP_OUTPUT)
  175. ExAllocatePoolWithTag(NonPagedPool,
  176. (ULONG)IoStatusBlock.Information,
  177. FWD_POOL_TAG)) == NULL) {
  178. ExFreePool(bip);
  179. if (requestorMode==UserMode)
  180. ZwClose (HdlIpxFile);
  181. else
  182. NtClose (HdlIpxFile);
  183. IpxFwdDbgPrint (DBG_IPXBIND, DBG_ERROR,
  184. ("IpxFwd: Could not allocate output binding buffer!\n"));
  185. return STATUS_INSUFFICIENT_RESOURCES;
  186. }
  187. if (requestorMode==UserMode)
  188. status = ZwDeviceIoControlFile(
  189. HdlIpxFile, // HANDLE to File
  190. NULL, // HANDLE to Event
  191. NULL, // ApcRoutine
  192. NULL, // ApcContext
  193. &IoStatusBlock, // IO_STATUS_BLOCK
  194. IOCTL_IPX_INTERNAL_BIND, // IoControlCode
  195. bip, // Input Buffer
  196. sizeof(IPX_INTERNAL_BIND_INPUT),// Input Buffer Length
  197. IPXBindOutput, // Output Buffer
  198. (ULONG)IoStatusBlock.Information); // Output Buffer Length
  199. else
  200. status = NtDeviceIoControlFile(
  201. HdlIpxFile, // HANDLE to File
  202. NULL, // HANDLE to Event
  203. NULL, // ApcRoutine
  204. NULL, // ApcContext
  205. &IoStatusBlock, // IO_STATUS_BLOCK
  206. IOCTL_IPX_INTERNAL_BIND, // IoControlCode
  207. bip, // Input Buffer
  208. sizeof(IPX_INTERNAL_BIND_INPUT),// Input Buffer Length
  209. IPXBindOutput, // Output Buffer
  210. (ULONG)IoStatusBlock.Information); // Output Buffer Length
  211. if (status == STATUS_PENDING) {
  212. if (requestorMode==UserMode)
  213. status = ZwWaitForSingleObject(
  214. HdlIpxFile,
  215. (BOOLEAN)FALSE,
  216. NULL);
  217. else
  218. status = NtWaitForSingleObject(
  219. HdlIpxFile,
  220. (BOOLEAN)FALSE,
  221. NULL);
  222. if (NT_SUCCESS(status))
  223. status = IoStatusBlock.Status;
  224. }
  225. if (!NT_SUCCESS (status)) {
  226. IpxFwdDbgPrint (DBG_IPXBIND, DBG_ERROR,
  227. ("IpxFwd: Ioctl to the IPX driver failed with %lx\n", IoStatusBlock.Status));
  228. ExFreePool(bip);
  229. ExFreePool(IPXBindOutput);
  230. IPXBindOutput = NULL;
  231. if (requestorMode==UserMode)
  232. ZwClose (HdlIpxFile);
  233. else
  234. NtClose (HdlIpxFile);
  235. return status;
  236. }
  237. IpxFwdDbgPrint (DBG_IPXBIND, DBG_INFORMATION,
  238. ("IpxFwd: Succesfuly bound to the IPX driver\n"));
  239. ExFreePool (bip);
  240. ExFreePool (WstrIpxFileName);
  241. return status;
  242. }
  243. /*++
  244. *******************************************************************
  245. U n b i n d F r o m I p x D r i v e r
  246. Routine Description:
  247. Closes connection to IPX stack driver
  248. Arguments:
  249. None
  250. Return Value:
  251. None
  252. *******************************************************************
  253. --*/
  254. VOID
  255. UnbindFromIpxDriver (
  256. KPROCESSOR_MODE requestorMode
  257. ) {
  258. // Free binding output buffer and close driver handle
  259. ASSERT (IPXBindOutput!=NULL);
  260. ExFreePool (IPXBindOutput);
  261. IPXBindOutput = NULL;
  262. IpxFwdDbgPrint (DBG_IPXBIND, DBG_WARNING,
  263. ("IpxFwd: Closing IPX driver handle\n"));
  264. if (requestorMode==UserMode)
  265. ZwClose (HdlIpxFile);
  266. else
  267. NtClose (HdlIpxFile);
  268. }
  269. /*++
  270. *******************************************************************
  271. F w F i n d R o u t e
  272. Routine Description:
  273. This routine is provided by the Kernel Forwarder to find the route
  274. to a given node and network
  275. Arguments:
  276. Network - the destination network
  277. Node - destination node
  278. RouteEntry - filled in by the Forwarder if a route exists
  279. Return Value:
  280. STATUS_SUCCESS
  281. STATUS_NETWORK_UNREACHABLE - if the findroute failed
  282. *******************************************************************
  283. --*/
  284. NTSTATUS
  285. IpxFwdFindRoute (
  286. IN PUCHAR Network,
  287. IN PUCHAR Node,
  288. OUT PIPX_FIND_ROUTE_REQUEST RouteEntry
  289. ) {
  290. PINTERFACE_CB ifCB;
  291. ULONG net;
  292. KIRQL oldIRQL;
  293. NTSTATUS status = STATUS_NETWORK_UNREACHABLE;
  294. PFWD_ROUTE fwRoute;
  295. if (!EnterForwarder ())
  296. return STATUS_UNSUCCESSFUL;
  297. net = GETULONG (Network);
  298. ifCB = FindDestination (net, Node, &fwRoute);
  299. if (ifCB!=NULL) {
  300. if (IS_IF_ENABLED(ifCB)) {
  301. KeAcquireSpinLock (&ifCB->ICB_Lock, &oldIRQL);
  302. switch (ifCB->ICB_Stats.OperationalState) {
  303. case FWD_OPER_STATE_UP:
  304. IPX_NET_CPY (&RouteEntry->Network, Network);
  305. if (fwRoute->FR_Network==ifCB->ICB_Network) {
  306. if (Node!=NULL) {
  307. IPX_NODE_CPY (RouteEntry->LocalTarget.MacAddress, Node);
  308. }
  309. else {
  310. IPX_NODE_CPY (RouteEntry->LocalTarget.MacAddress,
  311. BROADCAST_NODE);
  312. }
  313. }
  314. else {
  315. IPX_NODE_CPY (RouteEntry->LocalTarget.MacAddress,
  316. fwRoute->FR_NextHopAddress);
  317. }
  318. if (ifCB!=InternalInterface) {
  319. ADAPTER_CONTEXT_TO_LOCAL_TARGET (
  320. ifCB->ICB_AdapterContext,
  321. &RouteEntry->LocalTarget);
  322. }
  323. else {
  324. CONSTANT_ADAPTER_CONTEXT_TO_LOCAL_TARGET (
  325. VIRTUAL_NET_ADAPTER_CONTEXT,
  326. &RouteEntry->LocalTarget);
  327. }
  328. //
  329. // Fill in the hop count and tick count
  330. //
  331. RouteEntry->TickCount = fwRoute->FR_TickCount;
  332. RouteEntry->HopCount = fwRoute->FR_HopCount;
  333. status = STATUS_SUCCESS;
  334. break;
  335. case FWD_OPER_STATE_SLEEPING:
  336. IPX_NODE_CPY (&RouteEntry->LocalTarget.MacAddress,
  337. fwRoute->FR_NextHopAddress);
  338. CONSTANT_ADAPTER_CONTEXT_TO_LOCAL_TARGET (DEMAND_DIAL_ADAPTER_CONTEXT,
  339. &RouteEntry->LocalTarget);
  340. status = STATUS_SUCCESS;
  341. //
  342. // Fill in the hop count and tick count
  343. //
  344. RouteEntry->TickCount = fwRoute->FR_TickCount;
  345. RouteEntry->HopCount = fwRoute->FR_HopCount;
  346. break;
  347. case FWD_OPER_STATE_DOWN:
  348. status = STATUS_NETWORK_UNREACHABLE;
  349. break;
  350. default:
  351. ASSERTMSG ("Inavalid operational state", FALSE);
  352. }
  353. KeReleaseSpinLock (&ifCB->ICB_Lock, oldIRQL);
  354. #if DBG
  355. if (Node!=NULL) {
  356. if (NT_SUCCESS (status)) {
  357. IpxFwdDbgPrint (DBG_IPXBIND, DBG_INFORMATION,
  358. ("IpxFwd: Found route for IPX driver:"
  359. " %08lX:%02X%02X%02X%02X%02X%02X"
  360. " -> %ld(%ld):%02X%02X%02X%02X%02X%02X\n",
  361. net, Node[0],Node[1],Node[2],Node[3],Node[4],Node[5],
  362. ifCB->ICB_Index, RouteEntry->LocalTarget.NicId,
  363. RouteEntry->LocalTarget.MacAddress[0],
  364. RouteEntry->LocalTarget.MacAddress[1],
  365. RouteEntry->LocalTarget.MacAddress[2],
  366. RouteEntry->LocalTarget.MacAddress[3],
  367. RouteEntry->LocalTarget.MacAddress[4],
  368. RouteEntry->LocalTarget.MacAddress[5]));
  369. }
  370. else {
  371. IpxFwdDbgPrint (DBG_IPXROUTE, DBG_WARNING,
  372. ("IpxFwd: Network unreachable for:"
  373. " %08lX:%02X%02X%02X%02X%02X%02X -> %ld.\n",
  374. net, Node[0],Node[1],Node[2],Node[3],Node[4],Node[5],
  375. ifCB->ICB_Index));
  376. }
  377. }
  378. else {
  379. if (NT_SUCCESS (status)) {
  380. IpxFwdDbgPrint (DBG_IPXBIND, DBG_INFORMATION,
  381. ("IpxFwd: Found route for IPX driver:"
  382. " %08lX"
  383. " -> %ld(%ld):%02X%02X%02X%02X%02X%02X\n",
  384. net, ifCB->ICB_Index, RouteEntry->LocalTarget.NicId,
  385. RouteEntry->LocalTarget.MacAddress[0],
  386. RouteEntry->LocalTarget.MacAddress[1],
  387. RouteEntry->LocalTarget.MacAddress[2],
  388. RouteEntry->LocalTarget.MacAddress[3],
  389. RouteEntry->LocalTarget.MacAddress[4],
  390. RouteEntry->LocalTarget.MacAddress[5]));
  391. }
  392. else {
  393. IpxFwdDbgPrint (DBG_IPXROUTE, DBG_WARNING,
  394. ("IpxFwd: Network unreachable for:"
  395. " %08lX -> %ld.\n", net));
  396. }
  397. }
  398. #endif
  399. ReleaseInterfaceReference (ifCB);
  400. ReleaseRouteReference (fwRoute);
  401. }
  402. }
  403. else {
  404. #if DBG
  405. if (Node!=NULL) {
  406. IpxFwdDbgPrint (DBG_IPXROUTE, DBG_WARNING,
  407. ("IpxFwd: No route for:"
  408. " %08lX:%02X%02X%02X%02X%02X%02X.\n",
  409. net, Node[0],Node[1],Node[2],Node[3],Node[4],Node[5]));
  410. }
  411. else {
  412. IpxFwdDbgPrint (DBG_IPXROUTE, DBG_WARNING,
  413. ("IpxFwd: No route for: %08lX.\n", net));
  414. }
  415. #endif
  416. status = STATUS_NETWORK_UNREACHABLE;
  417. }
  418. LeaveForwarder ();
  419. return status;
  420. }
  421.