Source code of Windows XP (NT5)
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.

1267 lines
32 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. ntemgmt.c
  5. Abstract:
  6. Routines for managing IP Network Table Entries.
  7. Author:
  8. Mike Massa (mikemas) April 16, 1997
  9. Revision History:
  10. Who When What
  11. -------- -------- ----------------------------------------------
  12. mikemas 04-16-97 created
  13. Notes:
  14. --*/
  15. #include "clusnet.h"
  16. #include "ntemgmt.tmh"
  17. //
  18. // Types
  19. //
  20. typedef struct {
  21. LIST_ENTRY Linkage;
  22. ULONG Address;
  23. USHORT Context;
  24. ULONG Instance;
  25. } IPA_NTE, *PIPA_NTE;
  26. //
  27. // Data
  28. //
  29. LIST_ENTRY IpaNteList = {NULL,NULL};
  30. KSPIN_LOCK IpaNteListLock = 0;
  31. HANDLE IpaIpHandle = NULL;
  32. PDEVICE_OBJECT IpaIpDeviceObject = NULL;
  33. PFILE_OBJECT IpaIpFileObject = NULL;
  34. //
  35. // Local function prototypes
  36. //
  37. NTSTATUS
  38. IpaIssueDeviceControl (
  39. IN ULONG IoControlCode,
  40. IN PVOID InputBuffer,
  41. IN ULONG InputBufferLength,
  42. IN PVOID OutputBuffer,
  43. IN PULONG OutputBufferLength
  44. );
  45. #ifdef ALLOC_PRAGMA
  46. #pragma alloc_text(INIT, IpaLoad)
  47. #pragma alloc_text(PAGE, IpaIssueDeviceControl)
  48. #pragma alloc_text(PAGE, IpaInitialize)
  49. #endif // ALLOC_PRAGMA
  50. NTSTATUS
  51. IpaIssueDeviceControl(
  52. IN ULONG IoControlCode,
  53. IN PVOID InputBuffer,
  54. IN ULONG InputBufferLength,
  55. IN PVOID OutputBuffer,
  56. IN PULONG OutputBufferLength
  57. )
  58. /*++
  59. Routine Description:
  60. Arguments:
  61. Return Value:
  62. NTSTATUS -- Indicates the status of the request.
  63. Notes:
  64. Called in the context of the system process.
  65. --*/
  66. {
  67. NTSTATUS status = STATUS_SUCCESS;
  68. IO_STATUS_BLOCK ioStatusBlock;
  69. PIRP irp;
  70. PKEVENT event;
  71. PAGED_CODE();
  72. CnAssert(IpaIpHandle != NULL);
  73. CnAssert(IpaIpFileObject != NULL);
  74. CnAssert(IpaIpDeviceObject != NULL);
  75. CnAssert(CnSystemProcess == (PKPROCESS) IoGetCurrentProcess());
  76. //
  77. // Reference the file object. This reference will be removed by the I/O
  78. // completion code.
  79. //
  80. status = ObReferenceObjectByPointer(
  81. IpaIpFileObject,
  82. 0,
  83. NULL,
  84. KernelMode
  85. );
  86. if (!NT_SUCCESS(status)) {
  87. IF_CNDBG(CN_DEBUG_NTE) {
  88. CNPRINT((
  89. "[Clusnet] Failed to reference IP device file handle, status %lx\n",
  90. status
  91. ));
  92. }
  93. CnTrace(NTEMGMT_DETAIL, IpaNteObRefFailed,
  94. "[Clusnet] Failed to reference IP device file handle, status %!status!.",
  95. status // LOGSTATUS
  96. );
  97. return(status);
  98. }
  99. event = ExAllocatePool(NonPagedPool, sizeof(KEVENT));
  100. if (event != NULL) {
  101. KeInitializeEvent(event, NotificationEvent, FALSE);
  102. irp = IoBuildDeviceIoControlRequest(
  103. IoControlCode,
  104. IpaIpDeviceObject,
  105. InputBuffer,
  106. InputBufferLength,
  107. OutputBuffer,
  108. *OutputBufferLength,
  109. FALSE,
  110. event,
  111. &ioStatusBlock
  112. );
  113. if (irp != NULL) {
  114. status = IoCallDriver(IpaIpDeviceObject, irp);
  115. //
  116. // If necessary, wait for the I/O to complete.
  117. //
  118. if (status == STATUS_PENDING) {
  119. KeWaitForSingleObject(
  120. event,
  121. UserRequest,
  122. KernelMode,
  123. FALSE,
  124. NULL
  125. );
  126. }
  127. if (NT_SUCCESS(status)) {
  128. status = ioStatusBlock.Status;
  129. // NOTENOTE: on 64 bit this is a truncation might
  130. // want > check code
  131. *OutputBufferLength = (ULONG)ioStatusBlock.Information;
  132. }
  133. else {
  134. IF_CNDBG(CN_DEBUG_NTE) {
  135. CNPRINT((
  136. "[Clusnet] NTE request failed, status %lx\n",
  137. status
  138. ));
  139. }
  140. CnTrace(NTEMGMT_DETAIL, IpaNteRequestFailed,
  141. "[Clusnet] NTE request failed, status %!status!.",
  142. status // LOGSTATUS
  143. );
  144. *OutputBufferLength = 0;
  145. }
  146. ExFreePool(event);
  147. return(status);
  148. }
  149. else {
  150. status = STATUS_INSUFFICIENT_RESOURCES;
  151. IF_CNDBG(CN_DEBUG_NTE) {
  152. CNPRINT((
  153. "[Clusnet] Failed to build NTE request irp, status %lx\n",
  154. status
  155. ));
  156. }
  157. CnTrace(NTEMGMT_DETAIL, IpaNteIrpAllocFailed,
  158. "[Clusnet] Failed to build NTE request irp, status %!status!.",
  159. status // LOGSTATUS
  160. );
  161. }
  162. ExFreePool(event);
  163. }
  164. else {
  165. status = STATUS_INSUFFICIENT_RESOURCES;
  166. IF_CNDBG(CN_DEBUG_NTE) {
  167. CNPRINT((
  168. "[Clusnet] Failed to allocate memory for event object.\n"
  169. ));
  170. }
  171. CnTrace(NTEMGMT_DETAIL, IpaNteEventAllocFailed,
  172. "[Clusnet] Failed to allocate event object, status %!status!.",
  173. status // LOGSTATUS
  174. );
  175. }
  176. ObDereferenceObject(IpaIpFileObject);
  177. return(status);
  178. } // IpaDeviceControl
  179. PIPA_NTE
  180. IpaFindNTE(
  181. USHORT Context
  182. )
  183. {
  184. PIPA_NTE nte;
  185. PLIST_ENTRY entry;
  186. for ( entry = IpaNteList.Flink;
  187. entry != &IpaNteList;
  188. entry = entry->Flink
  189. )
  190. {
  191. nte = CONTAINING_RECORD(entry, IPA_NTE, Linkage);
  192. if (Context == nte->Context) {
  193. return(nte);
  194. }
  195. }
  196. return(NULL);
  197. } // IpaFindNTE
  198. NTSTATUS
  199. IpaAddNTECompletion(
  200. IN PDEVICE_OBJECT DeviceObject,
  201. IN PIRP Irp,
  202. IN PVOID Context
  203. )
  204. /*++
  205. Routine Description:
  206. IpaAddNTECompletion is the completion routine for an
  207. IOCTL_IP_ADD_NTE IRP. It completes the processing for
  208. an IOCTL_CLUSNET_ADD_NTE request and releases CnResource.
  209. Arguments:
  210. DeviceObject - not used
  211. Irp - completed IRP
  212. Context - local NTE data structure
  213. Return value
  214. Must not be STATUS_MORE_PROCESSING_REQUIRED
  215. --*/
  216. {
  217. PIP_ADD_NTE_RESPONSE response;
  218. PIPA_NTE nte;
  219. NTSTATUS status;
  220. KIRQL irql;
  221. nte = (PIPA_NTE) Context;
  222. status = Irp->IoStatus.Status;
  223. if (status == STATUS_SUCCESS) {
  224. response =
  225. (PIP_ADD_NTE_RESPONSE) Irp->AssociatedIrp.SystemBuffer;
  226. nte->Context = response->Context;
  227. nte->Instance = response->Instance;
  228. CnTrace(NTEMGMT_DETAIL, IpaNteCreatedNte,
  229. "[Clusnet] Created new NTE, context %u, instance %u.",
  230. nte->Context, // LOGUSHORT
  231. nte->Instance // LOGULONG
  232. );
  233. IF_CNDBG(CN_DEBUG_NTE) {
  234. CNPRINT((
  235. "[Clusnet] Created new NTE %lu, instance %u\n",
  236. nte->Context,
  237. nte->Instance
  238. ));
  239. }
  240. KeAcquireSpinLock(&IpaNteListLock, &irql);
  241. InsertTailList(&IpaNteList, &(nte->Linkage));
  242. KeReleaseSpinLock(&IpaNteListLock, irql);
  243. }
  244. else {
  245. CnTrace(NTEMGMT_DETAIL, IpaNteCreateNteFailed,
  246. "[Clusnet] Failed to create new NTE, status %!status!.",
  247. status // LOGSTATUS
  248. );
  249. IF_CNDBG(CN_DEBUG_NTE) {
  250. CNPRINT((
  251. "[Clusnet] Failed to create new NTE, status %lx\n",
  252. status
  253. ));
  254. }
  255. CnFreePool(nte);
  256. }
  257. //
  258. // Irp was already marked pending in our dispatch routine, but leave
  259. // this code in case the dispatch routine is ever changed.
  260. //
  261. if (Irp->PendingReturned) {
  262. IoMarkIrpPending(Irp);
  263. }
  264. return(status);
  265. } // IpaAddNTECompletion
  266. NTSTATUS
  267. IpaDeleteNTECompletion(
  268. IN PDEVICE_OBJECT DeviceObject,
  269. IN PIRP Irp,
  270. IN PVOID Context
  271. )
  272. /*++
  273. Routine Description:
  274. IpaDeleteNTECompletion is the completion routine for an
  275. IOCTL_IP_DELETE_NTE IRP. It completes the processing for
  276. an IOCTL_CLUSNET_ADD_NTE request and releases CnResource.
  277. Arguments:
  278. DeviceObject - not used
  279. Irp - completed IRP
  280. Context - local NTE data structure
  281. Return value
  282. Must not be STATUS_MORE_PROCESSING_REQUIRED
  283. --*/
  284. {
  285. PIPA_NTE nte;
  286. NTSTATUS status;
  287. nte = (PIPA_NTE) Context;
  288. status = Irp->IoStatus.Status;
  289. if (status != STATUS_SUCCESS) {
  290. CnTrace(NTEMGMT_DETAIL, IpaNteDeleteNteFailed,
  291. "[Clusnet] Failed to delete NTE context %u, status %!status!.",
  292. nte->Context, // LOGUSHORT
  293. status // LOGSTATUS
  294. );
  295. IF_CNDBG(CN_DEBUG_NTE) {
  296. CNPRINT(("[Clusnet] Failed to delete NTE %u, status %lx\n",
  297. nte->Context,
  298. status
  299. ));
  300. }
  301. CnAssert(status == STATUS_SUCCESS);
  302. }
  303. else {
  304. CnTrace(NTEMGMT_DETAIL, IpaNteNteDeleted,
  305. "[Clusnet] Deleted NTE %u.",
  306. nte->Context // LOGUSHORT
  307. );
  308. IF_CNDBG(CN_DEBUG_NTE) {
  309. CNPRINT(("[Clusnet] Deleted NTE %u\n", nte->Context));
  310. }
  311. }
  312. CnFreePool(nte);
  313. //
  314. // Irp was already marked pending in our dispatch routine, but leave
  315. // this code in case the dispatch routine is ever changed.
  316. //
  317. if (Irp->PendingReturned) {
  318. IoMarkIrpPending(Irp);
  319. }
  320. return(status);
  321. } // IpaDeleteNTECompletion
  322. NTSTATUS
  323. IpaSetNTEAddressCompletion(
  324. IN PDEVICE_OBJECT DeviceObject,
  325. IN PIRP Irp,
  326. IN PVOID Context
  327. )
  328. /*++
  329. Routine Description
  330. IpaSetNTEAddressCompletion is the completion routine for an
  331. IOCTL_IP_SET_ADDRESS IRP. It completes the processing for
  332. an IOCTL_CLUSNET_SET_NTE_ADDRESS request and releases
  333. CnResource.
  334. Arguments
  335. DeviceObject - not used
  336. Irp - completed IRP
  337. Context - former IP address of NTE, must be restored in
  338. IpaNteList if IOCTL failed
  339. Return value
  340. Must not be STATUS_MORE_PROCESSING_REQUIRED
  341. --*/
  342. {
  343. PIP_SET_ADDRESS_REQUEST request;
  344. NTSTATUS status;
  345. KIRQL irql;
  346. PIPA_NTE nte;
  347. request = (PIP_SET_ADDRESS_REQUEST) Irp->AssociatedIrp.SystemBuffer;
  348. status = Irp->IoStatus.Status;
  349. if (status != STATUS_SUCCESS) {
  350. CnTrace(NTEMGMT_DETAIL, IpaNteSetNteFailed,
  351. "[Clusnet] Failed to set address for NTE %u, status %!status!.",
  352. request->Context, // LOGUSHORT
  353. status // LOGSTATUS
  354. );
  355. IF_CNDBG(CN_DEBUG_NTE) {
  356. CNPRINT((
  357. "[Clusnet] Failed to set NTE %u, status %lx\n",
  358. request->Context,
  359. status
  360. ));
  361. }
  362. KeAcquireSpinLock(&IpaNteListLock, &irql);
  363. nte = IpaFindNTE(request->Context);
  364. if ((nte != NULL) && (nte->Address == request->Address)) {
  365. nte->Address = PtrToUlong(Context);
  366. }
  367. KeReleaseSpinLock(&IpaNteListLock, irql);
  368. }
  369. else {
  370. CnTrace(NTEMGMT_DETAIL, IpaNteSetNteAddress,
  371. "[Clusnet] Set NTE %u to address %x.",
  372. request->Context, // LOGUSHORT
  373. request->Address // LOGXLONG
  374. );
  375. IF_CNDBG(CN_DEBUG_NTE) {
  376. CNPRINT((
  377. "[Clusnet] Set NTE %u to address %lx\n",
  378. request->Context,
  379. request->Address
  380. ));
  381. }
  382. }
  383. //
  384. // Irp was already marked pending in our dispatch routine, but leave
  385. // this code in case the dispatch routine is ever changed.
  386. //
  387. if (Irp->PendingReturned) {
  388. IoMarkIrpPending(Irp);
  389. }
  390. return(status);
  391. } // IpaSetNTEAddressCompletion
  392. //
  393. // Public Routines
  394. //
  395. NTSTATUS
  396. IpaLoad(
  397. VOID
  398. )
  399. {
  400. IF_CNDBG(CN_DEBUG_INIT) {
  401. CNPRINT(("[Clusnet] NTE support loading.\n"));
  402. }
  403. KeInitializeSpinLock(&IpaNteListLock);
  404. InitializeListHead(&IpaNteList);
  405. return(STATUS_SUCCESS);
  406. } // IpaLoad
  407. NTSTATUS
  408. IpaInitialize(
  409. VOID
  410. )
  411. {
  412. NTSTATUS status = STATUS_SUCCESS;
  413. OBJECT_ATTRIBUTES objectAttributes;
  414. UNICODE_STRING nameString;
  415. IO_STATUS_BLOCK ioStatusBlock;
  416. PAGED_CODE( );
  417. IF_CNDBG(CN_DEBUG_INIT) {
  418. CNPRINT(("[Clusnet] NTE support initializing.\n"));
  419. }
  420. CnAssert(IsListEmpty(&IpaNteList));
  421. CnAssert(IpaIpHandle == NULL);
  422. CnAssert(CnSystemProcess != NULL);
  423. //
  424. // Open handles in the context of the system process
  425. //
  426. KeAttachProcess(CnSystemProcess);
  427. //
  428. // Open the IP device.
  429. //
  430. RtlInitUnicodeString(&nameString, DD_IP_DEVICE_NAME);
  431. InitializeObjectAttributes(
  432. &objectAttributes,
  433. &nameString,
  434. OBJ_CASE_INSENSITIVE,
  435. (HANDLE) NULL,
  436. (PSECURITY_DESCRIPTOR) NULL
  437. );
  438. status = ZwCreateFile(
  439. &IpaIpHandle,
  440. SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA,
  441. &objectAttributes,
  442. &ioStatusBlock,
  443. NULL,
  444. FILE_ATTRIBUTE_NORMAL,
  445. FILE_SHARE_READ | FILE_SHARE_WRITE,
  446. FILE_OPEN_IF,
  447. 0,
  448. NULL,
  449. 0
  450. );
  451. if (!NT_SUCCESS(status)) {
  452. CnTrace(NTEMGMT_DETAIL, IpaNteOpenIpFailed,
  453. "[Clusnet] Failed to open IP device, status %!status!.",
  454. status // LOGSTATUS
  455. );
  456. IF_CNDBG(CN_DEBUG_INIT) {
  457. CNPRINT(("[Clusnet] Failed to open IP device, status %lx\n", status));
  458. }
  459. goto error_exit;
  460. }
  461. status = ObReferenceObjectByHandle(
  462. IpaIpHandle,
  463. 0,
  464. NULL,
  465. KernelMode,
  466. &IpaIpFileObject,
  467. NULL
  468. );
  469. if (!NT_SUCCESS(status)) {
  470. CnTrace(NTEMGMT_DETAIL, IpaNteRefIpFailed,
  471. "[Clusnet] Failed to reference IP device, status %!status!.",
  472. status // LOGSTATUS
  473. );
  474. IF_CNDBG(CN_DEBUG_INIT) {
  475. CNPRINT(("[Clusnet] Failed to reference IP device file handle, status %lx\n", status));
  476. }
  477. ZwClose(IpaIpHandle); IpaIpHandle = NULL;
  478. goto error_exit;
  479. }
  480. IpaIpDeviceObject = IoGetRelatedDeviceObject(IpaIpFileObject);
  481. CnAdjustDeviceObjectStackSize(CnDeviceObject, IpaIpDeviceObject);
  482. status = STATUS_SUCCESS;
  483. error_exit:
  484. KeDetachProcess();
  485. return(status);
  486. } // IpaInitialize
  487. VOID
  488. IpaShutdown(
  489. VOID
  490. )
  491. {
  492. NTSTATUS status;
  493. KIRQL irql;
  494. PLIST_ENTRY entry;
  495. PIPA_NTE nte;
  496. IP_DELETE_NTE_REQUEST request;
  497. ULONG responseSize = 0;
  498. IF_CNDBG(CN_DEBUG_INIT) {
  499. CNPRINT(("[Clusnet] Destroying all cluster NTEs...\n"));
  500. }
  501. if (IpaIpHandle != NULL) {
  502. //
  503. // Handles was opened in the context of the system process.
  504. //
  505. CnAssert(CnSystemProcess != NULL);
  506. KeAttachProcess(CnSystemProcess);
  507. KeAcquireSpinLock(&IpaNteListLock, &irql);
  508. while (!IsListEmpty(&IpaNteList)) {
  509. entry = RemoveHeadList(&IpaNteList);
  510. KeReleaseSpinLock(&IpaNteListLock, irql);
  511. nte = CONTAINING_RECORD(entry, IPA_NTE, Linkage);
  512. request.Context = nte->Context;
  513. status = IpaIssueDeviceControl(
  514. IOCTL_IP_DELETE_NTE,
  515. &request,
  516. sizeof(request),
  517. NULL,
  518. &responseSize
  519. );
  520. if (status != STATUS_SUCCESS) {
  521. CnTrace(NTEMGMT_DETAIL, IpaNteShutdownDeleteNteFailed,
  522. "[Clusnet] Shutdown: failed to delete NTE %u, status %!status!.",
  523. nte->Context, // LOGUSHORT
  524. status // LOGSTATUS
  525. );
  526. IF_CNDBG(CN_DEBUG_INIT) {
  527. CNPRINT(("[Clusnet] Failed to delete NTE %u, status %lx\n",
  528. nte->Context,
  529. status
  530. ));
  531. }
  532. }
  533. else {
  534. CnTrace(NTEMGMT_DETAIL, IpaNteShutdownDeletedNte,
  535. "[Clusnet] Shutdown: deleted NTE context %u, instance %u.",
  536. nte->Context, // LOGUSHORT
  537. nte->Instance // LOGULONG
  538. );
  539. IF_CNDBG(CN_DEBUG_INIT) {
  540. CNPRINT(("[Clusnet] Deleted NTE %u\n", request.Context));
  541. }
  542. }
  543. CnFreePool(nte);
  544. KeAcquireSpinLock(&IpaNteListLock, &irql);
  545. }
  546. KeReleaseSpinLock(&IpaNteListLock, irql);
  547. CnTrace(NTEMGMT_DETAIL, IpaNteShutdownNtesDeleted,
  548. "[Clusnet] All cluster NTEs destroyed."
  549. );
  550. IF_CNDBG(CN_DEBUG_INIT) {
  551. CNPRINT(("[Clusnet] All cluster NTEs destroyed.\n"));
  552. }
  553. ObDereferenceObject(IpaIpFileObject);
  554. ZwClose(IpaIpHandle);
  555. IpaIpHandle = NULL;
  556. IpaIpFileObject = NULL;
  557. IpaIpDeviceObject = NULL;
  558. KeDetachProcess();
  559. }
  560. return;
  561. } // IpaShutdown
  562. NTSTATUS
  563. IpaAddNTE(
  564. IN PIRP Irp,
  565. IN PIO_STACK_LOCATION IrpSp
  566. )
  567. /*++
  568. Routine Description
  569. IpaAddNTE issues an IOCTL_IP_ADD_NTE to IP to add an NTE.
  570. Irp is reused. It must be allocated with sufficient stack
  571. locations, as determined when IpaIpDeviceObject was opened
  572. in IpaInitialize.
  573. Arguments
  574. Irp - IRP from I/O manager to clusnet
  575. IrpSp - current IRP stack location
  576. Return Value
  577. STATUS_PENDING, or error status if request is not submitted
  578. to IP.
  579. --*/
  580. {
  581. NTSTATUS status;
  582. PIP_ADD_NTE_REQUEST request;
  583. ULONG requestSize;
  584. ULONG responseSize;
  585. PIPA_NTE nte;
  586. PIO_STACK_LOCATION nextIrpSp;
  587. //
  588. // Verify input parameters
  589. //
  590. requestSize =
  591. IrpSp->Parameters.DeviceIoControl.InputBufferLength;
  592. responseSize =
  593. IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  594. if (requestSize < sizeof(IP_ADD_NTE_REQUEST)) {
  595. ULONG correctSize = sizeof(IP_ADD_NTE_REQUEST);
  596. CnTrace(NTEMGMT_DETAIL, IpaNteAddInvalidReqSize,
  597. "[Clusnet] Add NTE request size %u invalid, "
  598. "should be %u.",
  599. requestSize, // LOGULONG
  600. correctSize // LOGULONG
  601. );
  602. IF_CNDBG(CN_DEBUG_NTE) {
  603. CNPRINT((
  604. "[Clusnet] Add NTE request size %d invalid, should be %d.\n",
  605. requestSize,
  606. sizeof(IP_ADD_NTE_REQUEST)
  607. ));
  608. }
  609. return(STATUS_INVALID_PARAMETER);
  610. } else if (responseSize < sizeof(IP_ADD_NTE_RESPONSE)) {
  611. ULONG correctSize = sizeof(IP_ADD_NTE_RESPONSE);
  612. CnTrace(NTEMGMT_DETAIL, IpaNteAddInvalidResponseSize,
  613. "[Clusnet] Add NTE response size %u invalid, "
  614. "should be %u.",
  615. responseSize, // LOGULONG
  616. correctSize // LOGULONG
  617. );
  618. IF_CNDBG(CN_DEBUG_NTE) {
  619. CNPRINT((
  620. "[Clusnet] Add NTE response size %d invalid, should be %d.\n",
  621. responseSize,
  622. sizeof(IP_ADD_NTE_RESPONSE)
  623. ));
  624. }
  625. return(STATUS_INVALID_PARAMETER);
  626. }
  627. //
  628. // Verify that Irp has sufficient stack locations
  629. //
  630. if (Irp->CurrentLocation - IpaIpDeviceObject->StackSize < 1) {
  631. UCHAR correctSize = IpaIpDeviceObject->StackSize+1;
  632. CnTrace(NTEMGMT_DETAIL, IpaNteAddNoIrpStack,
  633. "[Clusnet] Add NTE IRP has %u remaining stack locations, "
  634. "need %u.",
  635. Irp->CurrentLocation, // LOGUCHAR
  636. correctSize // LOGUCHAR
  637. );
  638. IF_CNDBG(CN_DEBUG_NTE) {
  639. CNPRINT((
  640. "[Clusnet] Add NTE IRP has %d stack locations, need %d.\n",
  641. Irp->CurrentLocation,
  642. IpaIpDeviceObject->StackSize
  643. ));
  644. }
  645. return(STATUS_INVALID_PARAMETER);
  646. }
  647. request = (PIP_ADD_NTE_REQUEST) Irp->AssociatedIrp.SystemBuffer;
  648. CnTrace(NTEMGMT_DETAIL, IpaNteCreatingNte,
  649. "[Clusnet] Creating new NTE for address %x.",
  650. request->Address // LOGXLONG
  651. );
  652. IF_CNDBG(CN_DEBUG_NTE) {
  653. CNPRINT((
  654. "[Clusnet] Creating new NTE for address %lx...\n",
  655. request->Address
  656. ));
  657. }
  658. //
  659. // Allocate a local NTE data structure.
  660. //
  661. nte = CnAllocatePool(sizeof(IPA_NTE));
  662. if (nte == NULL) {
  663. return(STATUS_INSUFFICIENT_RESOURCES);
  664. }
  665. nte->Address = request->Address;
  666. //
  667. // Set up the next IRP stack location for IP.
  668. // IOCTL_CLUSNET_ADD_NTE uses the same request
  669. // and response buffer, so there is no need to
  670. // alter the IRP system buffer.
  671. //
  672. IoCopyCurrentIrpStackLocationToNext(Irp);
  673. nextIrpSp = IoGetNextIrpStackLocation(Irp);
  674. nextIrpSp->Parameters.DeviceIoControl.IoControlCode
  675. = IOCTL_IP_ADD_NTE;
  676. nextIrpSp->FileObject = IpaIpFileObject;
  677. IoSetCompletionRoutine(
  678. Irp,
  679. IpaAddNTECompletion,
  680. (PVOID) nte,
  681. TRUE,
  682. TRUE,
  683. TRUE
  684. );
  685. //
  686. // Mark the IRP pending, since we return STATUS_PENDING
  687. // regardless of the result of IoCallDriver.
  688. //
  689. IoMarkIrpPending(Irp);
  690. //
  691. // Issue the request
  692. //
  693. IoCallDriver(IpaIpDeviceObject, Irp);
  694. //
  695. // At this point we must return STATUS_PENDING so that
  696. // the clusnet dispatch routine will not try to complete
  697. // the IRP. The lower-level driver is required to complete
  698. // the IRP, and errors will be handled in the completion
  699. // routine.
  700. //
  701. return (STATUS_PENDING);
  702. } // IpaAddNTE
  703. NTSTATUS
  704. IpaDeleteNTE(
  705. IN PIRP Irp,
  706. IN PIO_STACK_LOCATION IrpSp
  707. )
  708. /*++
  709. Routine Description
  710. IpaDeleteNTE issues an IOCTL_IP_DELETE_NTE to IP to delete
  711. an NTE. Irp is reused. It must be allocated with sufficient
  712. stack locations, as determined when IpaIpDeviceObject was
  713. opened in IpaInitialize.
  714. Arguments
  715. Irp - IRP from I/O manager to clusnet
  716. IrpSp - current IRP stack location
  717. Return Value
  718. STATUS_PENDING, or error status if request is not submitted
  719. to IP.
  720. --*/
  721. {
  722. NTSTATUS status;
  723. PIP_DELETE_NTE_REQUEST request;
  724. ULONG requestSize;
  725. PIPA_NTE nte;
  726. KIRQL irql;
  727. PIO_STACK_LOCATION nextIrpSp;
  728. //
  729. // Verify input parameters
  730. //
  731. requestSize =
  732. IrpSp->Parameters.DeviceIoControl.InputBufferLength;
  733. if (requestSize < sizeof(IP_DELETE_NTE_REQUEST)) {
  734. ULONG correctSize = sizeof(IP_DELETE_NTE_REQUEST);
  735. CnTrace(NTEMGMT_DETAIL, IpaNteDelInvalidReqSize,
  736. "[Clusnet] Delete NTE request size %u invalid, "
  737. "should be %u.",
  738. requestSize, // LOGULONG
  739. correctSize // LOGULONG
  740. );
  741. IF_CNDBG(CN_DEBUG_NTE) {
  742. CNPRINT((
  743. "[Clusnet] Delete NTE request size %d invalid, "
  744. "should be %d.\n",
  745. requestSize,
  746. sizeof(IP_DELETE_NTE_REQUEST)
  747. ));
  748. }
  749. return(STATUS_INVALID_PARAMETER);
  750. }
  751. //
  752. // Verify that Irp has sufficient stack locations
  753. //
  754. if (Irp->CurrentLocation - IpaIpDeviceObject->StackSize < 1) {
  755. UCHAR correctSize = IpaIpDeviceObject->StackSize+1;
  756. CnTrace(NTEMGMT_DETAIL, IpaNteDeleteNoIrpStack,
  757. "[Clusnet] Delete NTE IRP has %u remaining stack locations, "
  758. "need %u.",
  759. Irp->CurrentLocation, // LOGUCHAR
  760. correctSize // LOGUCHAR
  761. );
  762. IF_CNDBG(CN_DEBUG_NTE) {
  763. CNPRINT((
  764. "[Clusnet] Delete NTE IRP has %d stack locations, "
  765. "need %d.\n",
  766. Irp->CurrentLocation,
  767. IpaIpDeviceObject->StackSize
  768. ));
  769. }
  770. return(STATUS_INVALID_PARAMETER);
  771. }
  772. request = (PIP_DELETE_NTE_REQUEST) Irp->AssociatedIrp.SystemBuffer;
  773. //
  774. // Find the NTE in local NTE list and remove.
  775. //
  776. KeAcquireSpinLock(&IpaNteListLock, &irql);
  777. nte = IpaFindNTE(request->Context);
  778. if (nte == NULL) {
  779. KeReleaseSpinLock(&IpaNteListLock, irql);
  780. CnTrace(NTEMGMT_DETAIL, IpaNteDeleteNteUnknown,
  781. "[Clusnet] NTE %u does not exist.",
  782. request->Context // LOGUSHORT
  783. );
  784. IF_CNDBG(CN_DEBUG_NTE) {
  785. CNPRINT((
  786. "[Clusnet] NTE %u does not exist.\n",
  787. request->Context
  788. ));
  789. }
  790. return(STATUS_UNSUCCESSFUL);
  791. }
  792. RemoveEntryList(&(nte->Linkage));
  793. KeReleaseSpinLock(&IpaNteListLock, irql);
  794. //
  795. // Set up the next IRP stack location for IP.
  796. // IOCTL_CLUSNET_ADD_NTE uses the same request
  797. // and response buffer, so there is no need to
  798. // alter the IRP system buffer.
  799. //
  800. IoCopyCurrentIrpStackLocationToNext(Irp);
  801. nextIrpSp = IoGetNextIrpStackLocation(Irp);
  802. nextIrpSp->Parameters.DeviceIoControl.IoControlCode
  803. = IOCTL_IP_DELETE_NTE;
  804. nextIrpSp->FileObject = IpaIpFileObject;
  805. IoSetCompletionRoutine(
  806. Irp,
  807. IpaDeleteNTECompletion,
  808. (PVOID) nte,
  809. TRUE,
  810. TRUE,
  811. TRUE
  812. );
  813. //
  814. // Mark the IRP pending, since we return STATUS_PENDING
  815. // regardless of the result of IoCallDriver.
  816. //
  817. IoMarkIrpPending(Irp);
  818. //
  819. // Issue the request
  820. //
  821. IoCallDriver(IpaIpDeviceObject, Irp);
  822. //
  823. // At this point we must return STATUS_PENDING so that
  824. // the clusnet dispatch routine will not try to complete
  825. // the IRP. The lower-level driver is required to complete
  826. // the IRP, and errors will be handled in the completion
  827. // routine.
  828. //
  829. return (STATUS_PENDING);
  830. } // IpaDeleteNTE
  831. NTSTATUS
  832. IpaSetNTEAddress(
  833. IN PIRP Irp,
  834. IN PIO_STACK_LOCATION IrpSp
  835. )
  836. /*++
  837. Routine Description
  838. IpaSetNTEAddress issues an IOCTL_IP_SET_ADDRESS to IP in order
  839. to set the IP address for an NTE. Irp is reused. It must be
  840. allocated with sufficient stack locations, as determined when
  841. IpaIpDeviceObject was opened in IpaInitialize.
  842. Arguments
  843. Irp - IRP from I/O manager to clusnet
  844. IrpSp - current IRP stack location
  845. Return Value
  846. STATUS_PENDING, or error status if request is not submitted
  847. to IP.
  848. --*/
  849. {
  850. NTSTATUS status;
  851. PIP_SET_ADDRESS_REQUEST request;
  852. ULONG requestSize;
  853. PIPA_NTE nte;
  854. KIRQL irql;
  855. PIO_STACK_LOCATION nextIrpSp;
  856. ULONG oldAddress;
  857. //
  858. // Verify input parameters
  859. //
  860. requestSize =
  861. IrpSp->Parameters.DeviceIoControl.InputBufferLength;
  862. if (requestSize < sizeof(IP_SET_ADDRESS_REQUEST)) {
  863. ULONG correctSize = sizeof(IP_SET_ADDRESS_REQUEST);
  864. CnTrace(NTEMGMT_DETAIL, IpaNteSetInvalidReqSize,
  865. "[Clusnet] Set NTE request size %u invalid, "
  866. "should be %u.",
  867. requestSize, // LOGULONG
  868. correctSize // LOGULONG
  869. );
  870. IF_CNDBG(CN_DEBUG_NTE) {
  871. CNPRINT((
  872. "[Clusnet] Set NTE request size %d invalid, should be %d.\n",
  873. requestSize,
  874. sizeof(IP_SET_ADDRESS_REQUEST)
  875. ));
  876. }
  877. return(STATUS_INVALID_PARAMETER);
  878. }
  879. //
  880. // Verify that Irp has sufficient stack locations
  881. //
  882. if (Irp->CurrentLocation - IpaIpDeviceObject->StackSize < 1) {
  883. UCHAR correctSize = IpaIpDeviceObject->StackSize+1;
  884. CnTrace(NTEMGMT_DETAIL, IpaNteSetNoIrpStack,
  885. "[Clusnet] Set NTE IRP has %u remaining stack locations, "
  886. "need %u.",
  887. Irp->CurrentLocation, // LOGUCHAR
  888. correctSize // LOGUCHAR
  889. );
  890. IF_CNDBG(CN_DEBUG_NTE) {
  891. CNPRINT((
  892. "[Clusnet] Set NTE IRP has %d stack locations, need %d.\n",
  893. Irp->CurrentLocation,
  894. IpaIpDeviceObject->StackSize
  895. ));
  896. }
  897. return(STATUS_INVALID_PARAMETER);
  898. }
  899. request = (PIP_SET_ADDRESS_REQUEST)
  900. Irp->AssociatedIrp.SystemBuffer;
  901. IF_CNDBG(CN_DEBUG_NTE) {
  902. CNPRINT((
  903. "[Clusnet] Attempting to set NTE %u to address %lx...\n",
  904. request->Context,
  905. request->Address
  906. ));
  907. }
  908. KeAcquireSpinLock(&IpaNteListLock, &irql);
  909. nte = IpaFindNTE(request->Context);
  910. if (nte != NULL) {
  911. oldAddress = nte->Address;
  912. nte->Address = request->Address;
  913. KeReleaseSpinLock(&IpaNteListLock, irql);
  914. //
  915. // Set up the next IRP stack location for IP.
  916. // IOCTL_CLUSNET_SET_NTE_ADDRESS uses the same request
  917. // and response buffer, so there is no need to alter the
  918. // IRP system buffer.
  919. //
  920. IoCopyCurrentIrpStackLocationToNext(Irp);
  921. nextIrpSp = IoGetNextIrpStackLocation(Irp);
  922. nextIrpSp->Parameters.DeviceIoControl.IoControlCode
  923. = IOCTL_IP_SET_ADDRESS;
  924. nextIrpSp->FileObject = IpaIpFileObject;
  925. IoSetCompletionRoutine(
  926. Irp,
  927. IpaSetNTEAddressCompletion,
  928. UlongToPtr(oldAddress),
  929. TRUE,
  930. TRUE,
  931. TRUE
  932. );
  933. //
  934. // Mark the IRP pending, since we return STATUS_PENDING
  935. // regardless of the result of IoCallDriver.
  936. //
  937. IoMarkIrpPending(Irp);
  938. //
  939. // Issue the request
  940. //
  941. IoCallDriver(IpaIpDeviceObject, Irp);
  942. //
  943. // At this point we must return STATUS_PENDING so that
  944. // the clusnet dispatch routine will not try to complete
  945. // the IRP. The lower-level driver is required to complete
  946. // the IRP, and errors will be handled in the completion
  947. // routine.
  948. //
  949. status = STATUS_PENDING;
  950. } else {
  951. KeReleaseSpinLock(&IpaNteListLock, irql);
  952. CnTrace(NTEMGMT_DETAIL, IpaNteSetNteUnknown,
  953. "[Clusnet] NTE %u does not exist.",
  954. request->Context // LOGUSHORT
  955. );
  956. IF_CNDBG(CN_DEBUG_NTE) {
  957. CNPRINT(("[Clusnet] NTE %u does not exist.\n",
  958. request->Context
  959. ));
  960. }
  961. status = STATUS_UNSUCCESSFUL;
  962. }
  963. return(status);
  964. } // IpaSetNTEAddress
  965. BOOLEAN
  966. IpaIsAddressRegistered(
  967. ULONG Address
  968. )
  969. {
  970. PIPA_NTE nte;
  971. KIRQL irql;
  972. PLIST_ENTRY entry;
  973. BOOLEAN isAddressRegistered = FALSE;
  974. KeAcquireSpinLock(&IpaNteListLock, &irql);
  975. for ( entry = IpaNteList.Flink;
  976. entry != &IpaNteList;
  977. entry = entry->Flink
  978. )
  979. {
  980. nte = CONTAINING_RECORD(entry, IPA_NTE, Linkage);
  981. if (nte->Address == Address) {
  982. isAddressRegistered = TRUE;
  983. break;
  984. }
  985. }
  986. KeReleaseSpinLock(&IpaNteListLock, irql);
  987. return(isAddressRegistered);
  988. } // IpaIsAddressRegistered