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.

1065 lines
29 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. cnpsend.c
  5. Abstract:
  6. Cluster Network Protocol send processing code.
  7. Author:
  8. Mike Massa (mikemas) January 24, 1997
  9. Revision History:
  10. Who When What
  11. -------- -------- ----------------------------------------------
  12. mikemas 01-24-97 created
  13. Notes:
  14. --*/
  15. #include "precomp.h"
  16. #pragma hdrstop
  17. #include "cnpsend.tmh"
  18. #ifdef ALLOC_PRAGMA
  19. #pragma alloc_text(PAGE, CnpCreateSendRequestPool)
  20. #endif // ALLOC_PRAGMA
  21. //
  22. // Private Utility Functions
  23. //
  24. PCN_RESOURCE
  25. CnpCreateSendRequest(
  26. IN PVOID Context
  27. )
  28. {
  29. PCNP_SEND_REQUEST_POOL_CONTEXT context = Context;
  30. PCNP_SEND_REQUEST request;
  31. PCNP_HEADER cnpHeader;
  32. ULONG cnpHeaderSize;
  33. //
  34. // The CNP header size includes signature data for version 2.
  35. //
  36. cnpHeaderSize = sizeof(CNP_HEADER);
  37. if (context->CnpVersionNumber == 2) {
  38. cnpHeaderSize += CNP_SIG_LENGTH(CX_SIGNATURE_DATA_LENGTH);
  39. }
  40. //
  41. // Allocate a new send request. Include space for the upper protocol
  42. // and CNP headers.
  43. //
  44. request = CnAllocatePool(
  45. sizeof(CNP_SEND_REQUEST) + cnpHeaderSize +
  46. ((ULONG) context->UpperProtocolHeaderLength) +
  47. context->UpperProtocolContextSize
  48. );
  49. if (request != NULL) {
  50. //
  51. // Allocate an MDL to describe the CNP and upper transport headers.
  52. //
  53. // On I64 Context has to be 64 bit aligned,
  54. // let's put it before CnpHeader
  55. if (context->UpperProtocolContextSize > 0) {
  56. request->UpperProtocolContext = request + 1;
  57. request->CnpHeader = ( ((PCHAR) request->UpperProtocolContext) +
  58. context->UpperProtocolContextSize );
  59. } else {
  60. request->UpperProtocolContext = NULL;
  61. request->CnpHeader = request + 1;
  62. }
  63. request->HeaderMdl = IoAllocateMdl(
  64. request->CnpHeader,
  65. (ULONG) (context->UpperProtocolHeaderLength +
  66. cnpHeaderSize),
  67. FALSE,
  68. FALSE,
  69. NULL
  70. );
  71. if (request->HeaderMdl != NULL) {
  72. MmBuildMdlForNonPagedPool(request->HeaderMdl);
  73. //
  74. // Finish initializing the request.
  75. //
  76. request->UpperProtocolHeader = ( ((PCHAR) request->CnpHeader) +
  77. cnpHeaderSize );
  78. request->UpperProtocolHeaderLength =
  79. context->UpperProtocolHeaderLength;
  80. RtlZeroMemory(
  81. &(request->TdiSendDatagramInfo),
  82. sizeof(request->TdiSendDatagramInfo)
  83. );
  84. request->McastGroup = NULL;
  85. //
  86. // Fill in the constant CNP header values.
  87. //
  88. cnpHeader = request->CnpHeader;
  89. cnpHeader->Version = context->CnpVersionNumber;
  90. cnpHeader->NextHeader = context->UpperProtocolNumber;
  91. return((PCN_RESOURCE) request);
  92. }
  93. CnFreePool(request);
  94. }
  95. return(NULL);
  96. } // CnpCreateSendRequest
  97. VOID
  98. CnpDeleteSendRequest(
  99. PCN_RESOURCE Resource
  100. )
  101. {
  102. PCNP_SEND_REQUEST request = (PCNP_SEND_REQUEST) Resource;
  103. IoFreeMdl(request->HeaderMdl);
  104. CnFreePool(request);
  105. return;
  106. } // CnpDeleteSendRequest
  107. //
  108. // Routines Exported within the Cluster Transport
  109. //
  110. PCN_RESOURCE_POOL
  111. CnpCreateSendRequestPool(
  112. IN UCHAR CnpVersionNumber,
  113. IN UCHAR UpperProtocolNumber,
  114. IN USHORT UpperProtocolHeaderSize,
  115. IN USHORT UpperProtocolContextSize,
  116. IN USHORT PoolDepth
  117. )
  118. {
  119. PCN_RESOURCE_POOL pool;
  120. PCNP_SEND_REQUEST_POOL_CONTEXT context;
  121. PAGED_CODE();
  122. CnAssert((0xFFFF - sizeof(CNP_HEADER)) >= UpperProtocolHeaderSize);
  123. pool = CnAllocatePool(
  124. sizeof(CN_RESOURCE_POOL) +
  125. sizeof(CNP_SEND_REQUEST_POOL_CONTEXT)
  126. );
  127. if (pool != NULL) {
  128. context = (PCNP_SEND_REQUEST_POOL_CONTEXT) (pool + 1);
  129. context->UpperProtocolNumber = UpperProtocolNumber;
  130. context->UpperProtocolHeaderLength = UpperProtocolHeaderSize;
  131. context->UpperProtocolContextSize = UpperProtocolContextSize;
  132. context->CnpVersionNumber = CnpVersionNumber;
  133. CnInitializeResourcePool(
  134. pool,
  135. PoolDepth,
  136. CnpCreateSendRequest,
  137. context,
  138. CnpDeleteSendRequest
  139. );
  140. }
  141. return(pool);
  142. } // CnpCreateSendRequestPool
  143. VOID
  144. CnpCompleteSendPacketCommon(
  145. IN PIRP Irp,
  146. IN PCNP_SEND_REQUEST Request,
  147. IN PMDL DataMdl
  148. )
  149. {
  150. PCNP_NETWORK network = Request->Network;
  151. ULONG bytesSent = (ULONG)Irp->IoStatus.Information;
  152. NTSTATUS status = Irp->IoStatus.Status;
  153. PCNP_HEADER cnpHeader = Request->CnpHeader;
  154. CnVerifyCpuLockMask(
  155. 0, // Required
  156. 0xFFFFFFFF, // Forbidden
  157. 0 // Maximum
  158. );
  159. if (NT_SUCCESS(status)) {
  160. //
  161. // Subtract the CNP header from the count of bytes sent.
  162. //
  163. if (bytesSent >= sizeof(CNP_HEADER)) {
  164. bytesSent -= sizeof(CNP_HEADER);
  165. }
  166. else {
  167. CnAssert(FALSE);
  168. bytesSent = 0;
  169. }
  170. //
  171. // If CNP signed the message, subtract the signature
  172. // data from the count of bytes sent.
  173. //
  174. if (cnpHeader->Version == CNP_VERSION_MULTICAST) {
  175. CNP_SIGNATURE UNALIGNED * cnpSig;
  176. ULONG cnpSigDataLength;
  177. cnpSig = (CNP_SIGNATURE UNALIGNED *)(cnpHeader + 1);
  178. cnpSigDataLength = CNP_SIG_LENGTH(
  179. cnpSig->SigLength + cnpSig->SaltLength
  180. );
  181. if (bytesSent >= cnpSigDataLength) {
  182. bytesSent -= cnpSigDataLength;
  183. } else {
  184. CnAssert(FALSE);
  185. bytesSent = 0;
  186. }
  187. }
  188. CnTrace(CNP_SEND_DETAIL, CnpTraceSendComplete,
  189. "[CNP] Send of packet to node %u on net %u complete, "
  190. "bytes sent %u.",
  191. cnpHeader->DestinationAddress, // LOGULONG
  192. network->Id, // LOGULONG
  193. bytesSent // LOGULONG
  194. );
  195. }
  196. else {
  197. //
  198. // It is possible to reach this path with
  199. // status = c0000240 (STATUS_REQUEST_ABORTED) and
  200. // bytesSent > 0.
  201. //
  202. bytesSent = 0;
  203. CnTrace(CNP_SEND_ERROR, CnpTraceSendFailedBelow,
  204. "[CNP] Tcpip failed to send packet to node %u on net %u, "
  205. "data len %u, status %!status!",
  206. cnpHeader->DestinationAddress, // LOGULONG
  207. network->Id, // LOGULONG
  208. cnpHeader->PayloadLength, // LOGUSHORT
  209. status // LOGSTATUS
  210. );
  211. }
  212. //
  213. // Remove the active reference we put on the network.
  214. //
  215. CnAcquireLock(&(network->Lock), &(network->Irql));
  216. CnpActiveDereferenceNetwork(network);
  217. //
  218. // Free the TDI address buffer
  219. //
  220. CnFreePool(Request->TdiSendDatagramInfo.RemoteAddress);
  221. //
  222. // Call the upper protocol's completion routine
  223. //
  224. if (Request->CompletionRoutine) {
  225. (*(Request->CompletionRoutine))(
  226. status,
  227. &bytesSent,
  228. Request,
  229. DataMdl
  230. );
  231. }
  232. //
  233. // Update the Information field of the completed IRP to
  234. // reflect the actual bytes sent (adjusted for the CNP
  235. // and upper protocol headers).
  236. //
  237. Irp->IoStatus.Information = bytesSent;
  238. CnVerifyCpuLockMask(
  239. 0, // Required
  240. 0xFFFFFFFF, // Forbidden
  241. 0 // Maximum
  242. );
  243. return;
  244. } // CnpCompleteSendPacketCommon
  245. NTSTATUS
  246. CnpCompleteSendPacketNewIrp(
  247. IN PDEVICE_OBJECT DeviceObject,
  248. IN PIRP Irp,
  249. IN PVOID Context
  250. )
  251. {
  252. PCNP_SEND_REQUEST request = Context;
  253. PIRP upperIrp = request->UpperProtocolIrp;
  254. PMDL dataMdl;
  255. CnVerifyCpuLockMask(
  256. 0, // Required
  257. 0xFFFFFFFF, // Forbidden
  258. 0 // Maximum
  259. );
  260. //
  261. // Unlink the data MDL chain from the header MDL.
  262. //
  263. CnAssert(Irp->MdlAddress == request->HeaderMdl);
  264. dataMdl = request->HeaderMdl->Next;
  265. request->HeaderMdl->Next = NULL;
  266. Irp->MdlAddress = NULL;
  267. CnpCompleteSendPacketCommon(Irp, request, dataMdl);
  268. //
  269. // Complete the upper-level IRP, if there is one
  270. //
  271. if (upperIrp != NULL) {
  272. IF_CNDBG( CN_DEBUG_CNPSEND )
  273. CNPRINT(("[CNP] CnpCompleteSendPacketNewIrp calling "
  274. "CnCompleteRequest for IRP %p with status "
  275. "%08x\n",
  276. upperIrp, Irp->IoStatus.Status));
  277. CnAcquireCancelSpinLock(&(upperIrp->CancelIrql));
  278. CnCompletePendingRequest(
  279. upperIrp,
  280. Irp->IoStatus.Status, // status
  281. (ULONG)Irp->IoStatus.Information // bytes returned
  282. );
  283. //
  284. // The IoCancelSpinLock was released by the completion routine.
  285. //
  286. }
  287. //
  288. // Free the new IRP
  289. //
  290. IoFreeIrp(Irp);
  291. CnVerifyCpuLockMask(
  292. 0, // Required
  293. 0xFFFFFFFF, // Forbidden
  294. 0 // Maximum
  295. );
  296. return(STATUS_MORE_PROCESSING_REQUIRED);
  297. } // CnpCompleteSendPacketNewIrp
  298. NTSTATUS
  299. CnpCompleteSendPacketReuseIrp(
  300. IN PDEVICE_OBJECT DeviceObject,
  301. IN PIRP Irp,
  302. IN PVOID Context
  303. )
  304. {
  305. PCNP_SEND_REQUEST request = Context;
  306. PMDL dataMdl;
  307. CnVerifyCpuLockMask(
  308. 0, // Required
  309. 0xFFFFFFFF, // Forbidden
  310. 0 // Maximum
  311. );
  312. //
  313. // Unlink the data MDL chain from the header MDL.
  314. //
  315. CnAssert(Irp->MdlAddress == request->HeaderMdl);
  316. dataMdl = request->HeaderMdl->Next;
  317. request->HeaderMdl->Next = NULL;
  318. //
  319. // Restore the requestor mode of the upper protocol IRP.
  320. //
  321. Irp->RequestorMode = request->UpperProtocolIrpMode;
  322. //
  323. // Restore the MDL of the upper protocol IRP.
  324. //
  325. Irp->MdlAddress = request->UpperProtocolMdl;
  326. CnpCompleteSendPacketCommon(Irp, request, dataMdl);
  327. if (Irp->PendingReturned) {
  328. IoMarkIrpPending(Irp);
  329. }
  330. IF_CNDBG( CN_DEBUG_CNPSEND )
  331. CNPRINT(("[CNP] CnpCompleteSendPacketReuseIrp returning "
  332. "IRP %p to I/O Manager\n",
  333. Irp));
  334. CnVerifyCpuLockMask(
  335. 0, // Required
  336. 0xFFFFFFFF, // Forbidden
  337. 0 // Maximum
  338. );
  339. return(STATUS_SUCCESS);
  340. } // CnpCompleteSendPacketReuseIrp
  341. NTSTATUS
  342. CnpSendPacket(
  343. IN PCNP_SEND_REQUEST SendRequest,
  344. IN CL_NODE_ID DestNodeId,
  345. IN PMDL DataMdl,
  346. IN USHORT DataLength,
  347. IN BOOLEAN CheckDestState,
  348. IN CL_NETWORK_ID NetworkId OPTIONAL
  349. )
  350. /*++
  351. Routine Description:
  352. Main send routine for CNP. Handles unicast and multicast
  353. sends.
  354. --*/
  355. {
  356. NTSTATUS status = STATUS_SUCCESS;
  357. PCNP_HEADER cnpHeader = SendRequest->CnpHeader;
  358. PIRP upperIrp = SendRequest->UpperProtocolIrp;
  359. CN_IRQL tableIrql;
  360. BOOLEAN multicast = FALSE;
  361. CL_NETWORK_ID networkId = NetworkId;
  362. CN_IRQL cancelIrql;
  363. BOOLEAN cnComplete = FALSE;
  364. BOOLEAN destNodeLocked = FALSE;
  365. PCNP_NODE destNode;
  366. ULONG sigDataLen;
  367. PCNP_INTERFACE interface;
  368. PCNP_NETWORK network;
  369. BOOLEAN networkReferenced = FALSE;
  370. PIRP irp;
  371. PVOID addressBuffer = NULL;
  372. PIO_COMPLETION_ROUTINE compRoutine;
  373. PDEVICE_OBJECT targetDeviceObject;
  374. PFILE_OBJECT targetFileObject;
  375. BOOLEAN mcastGroupReferenced = FALSE;
  376. CnVerifyCpuLockMask(
  377. 0, // Required
  378. CNP_LOCK_RANGE, // Forbidden
  379. CNP_PRECEEDING_LOCK_RANGE // Maximum
  380. );
  381. IF_CNDBG( CN_DEBUG_CNPSEND )
  382. CNPRINT(("[CNP] CnpSendPacket called with upper IRP %p\n",
  383. upperIrp));
  384. //
  385. // Make all the tests to see if we can send the packet.
  386. //
  387. //
  388. // Acquire the node table lock to match the destination node id
  389. // to a node object.
  390. //
  391. CnAcquireLock(&CnpNodeTableLock, &tableIrql);
  392. if (CnpNodeTable == NULL) {
  393. CnReleaseLock(&CnpNodeTableLock, tableIrql);
  394. status = STATUS_NETWORK_UNREACHABLE;
  395. goto error_exit;
  396. }
  397. //
  398. // Fill in the local node ID while we still hold the node table lock.
  399. //
  400. CnAssert(CnLocalNodeId != ClusterInvalidNodeId);
  401. cnpHeader->SourceAddress = CnLocalNodeId;
  402. //
  403. // Check first if the destination node id indicates that this is
  404. // a multicast.
  405. //
  406. if (DestNodeId == ClusterAnyNodeId) {
  407. //
  408. // This is a multicast. For multicasts, we use the local
  409. // node in place of the dest node to validate the network
  410. // and interface.
  411. //
  412. multicast = TRUE;
  413. destNode = CnpLockedFindNode(CnLocalNodeId, tableIrql);
  414. }
  415. //
  416. // Not a multicast. The destination node id must be valid.
  417. //
  418. else if (!CnIsValidNodeId(DestNodeId)) {
  419. CnReleaseLock(&CnpNodeTableLock, tableIrql);
  420. status = STATUS_INVALID_ADDRESS_COMPONENT;
  421. goto error_exit;
  422. }
  423. //
  424. // Find the destination node object in the node table.
  425. //
  426. else {
  427. destNode = CnpLockedFindNode(DestNodeId, tableIrql);
  428. }
  429. //
  430. // The NodeTableLock was released. Verify that we know about
  431. // the destination node.
  432. //
  433. if (destNode == NULL) {
  434. status = STATUS_HOST_UNREACHABLE;
  435. goto error_exit;
  436. }
  437. destNodeLocked = TRUE;
  438. //
  439. // CNP multicast messages must be signed.
  440. //
  441. if (multicast) {
  442. CnAssert(((CNP_HEADER UNALIGNED *)(SendRequest->CnpHeader))
  443. ->Version = CNP_VERSION_MULTICAST);
  444. //
  445. // Sign the data, starting with the upper protocol header
  446. // and finishing with the data payload.
  447. //
  448. // If we are requesting the current best multicast network,
  449. // we need to make sure that the mcast group data structure
  450. // is dereferenced.
  451. //
  452. mcastGroupReferenced = (BOOLEAN)(networkId == ClusterAnyNetworkId);
  453. status = CnpSignMulticastMessage(
  454. SendRequest,
  455. DataMdl,
  456. &networkId,
  457. &sigDataLen
  458. );
  459. if (status != STATUS_SUCCESS) {
  460. mcastGroupReferenced = FALSE;
  461. goto error_exit;
  462. }
  463. } else {
  464. sigDataLen = 0;
  465. }
  466. //
  467. // Choose the destination interface.
  468. //
  469. if (networkId != ClusterAnyNetworkId) {
  470. //
  471. // we really want to send this packet over the indicated
  472. // network. walk the node's interface list matching the
  473. // supplied network id to the interface's network ID and
  474. // send the packet on that interface
  475. //
  476. PLIST_ENTRY entry;
  477. for (entry = destNode->InterfaceList.Flink;
  478. entry != &(destNode->InterfaceList);
  479. entry = entry->Flink
  480. )
  481. {
  482. interface = CONTAINING_RECORD(
  483. entry,
  484. CNP_INTERFACE,
  485. NodeLinkage
  486. );
  487. if ( interface->Network->Id == networkId ) {
  488. break;
  489. }
  490. }
  491. if ( entry == &destNode->InterfaceList ) {
  492. //
  493. // no network object with the specified ID. if
  494. // this is the network the sender designated,
  495. // fail the send.
  496. //
  497. status = STATUS_NETWORK_UNREACHABLE;
  498. goto error_exit;
  499. }
  500. } else {
  501. interface = destNode->CurrentInterface;
  502. }
  503. //
  504. // Verify that we know about the destination interface.
  505. //
  506. if (interface == NULL) {
  507. // No interface for node. Must be down. Note that the
  508. // HOST_DOWN error code should cause the caller to give
  509. // up immediately.
  510. status = STATUS_HOST_DOWN;
  511. // status = STATUS_HOST_UNREACHABLE;
  512. goto error_exit;
  513. }
  514. //
  515. // Verify that everything is online. If all looks okay,
  516. // take an active reference on the network.
  517. //
  518. // For unicasts, verify the state of destination interface,
  519. // node, and intervening network.
  520. //
  521. // For multicasts, verify the state of the network and
  522. // its multicast capability.
  523. //
  524. network = interface->Network;
  525. if ( (!multicast)
  526. &&
  527. ( (interface->State > ClusnetInterfaceStateOfflinePending)
  528. &&
  529. (destNode->CommState == ClusnetNodeCommStateOnline)
  530. )
  531. )
  532. {
  533. //
  534. // Everything checks out. Reference the network so
  535. // it can't go offline while we are using it.
  536. //
  537. CnAcquireLockAtDpc(&(network->Lock));
  538. CnAssert(network->State >= ClusnetNetworkStateOfflinePending);
  539. if (!CnpActiveReferenceNetwork(network)) {
  540. // This Network is being closed down. We
  541. // cannot send the data.
  542. CnReleaseLockFromDpc(&(network->Lock));
  543. status = STATUS_HOST_UNREACHABLE;
  544. goto error_exit;
  545. }
  546. CnReleaseLockFromDpc(&(network->Lock));
  547. networkReferenced = TRUE;
  548. } else {
  549. //
  550. // Either the node is not online or this is a
  551. // multicast (in which case we don't bother checking
  552. // the status of all the nodes). Figure out what to do.
  553. //
  554. if (!multicast && CheckDestState) {
  555. //
  556. // Caller doesn't want to send to a down node.
  557. // Bail out. Note that the HOST_DOWN error code
  558. // should cause the caller to give up immediately.
  559. //
  560. status = STATUS_HOST_DOWN;
  561. // status = STATUS_HOST_UNREACHABLE;
  562. goto error_exit;
  563. }
  564. CnAcquireLockAtDpc(&(network->Lock));
  565. if (network->State <= ClusnetNetworkStateOfflinePending) {
  566. //
  567. // The chosen network is not online.
  568. // Bail out.
  569. //
  570. CnReleaseLockFromDpc(&(network->Lock));
  571. status = STATUS_HOST_UNREACHABLE;
  572. goto error_exit;
  573. }
  574. //
  575. // Verify that the chosen network has been
  576. // enabled for multicast.
  577. //
  578. if (multicast && !CnpIsNetworkMulticastCapable(network)) {
  579. CnReleaseLockFromDpc(&(network->Lock));
  580. status = STATUS_HOST_UNREACHABLE;
  581. goto error_exit;
  582. }
  583. //
  584. // Reference the network so it can't go offline
  585. // while we are using it.
  586. //
  587. if (!CnpActiveReferenceNetwork(network)) {
  588. // This Network is being closed down. We
  589. // cannot send the data.
  590. CnReleaseLockFromDpc(&(network->Lock));
  591. status = STATUS_HOST_UNREACHABLE;
  592. goto error_exit;
  593. }
  594. //
  595. // The network is online, even if the host isn't.
  596. // The caller doesn't care. Go for it.
  597. //
  598. CnReleaseLockFromDpc(&(network->Lock));
  599. networkReferenced = TRUE;
  600. }
  601. //
  602. // Allocate a buffer for the destination address.
  603. //
  604. addressBuffer = CnAllocatePool(interface->TdiAddressLength);
  605. if (addressBuffer == NULL) {
  606. status = STATUS_INSUFFICIENT_RESOURCES;
  607. goto error_exit;
  608. }
  609. //
  610. // Fill in the address buffer, and save it in the send
  611. // request data structure.
  612. //
  613. if (multicast) {
  614. PCNP_MULTICAST_GROUP mcastGroup = SendRequest->McastGroup;
  615. CnAssert(mcastGroup != NULL);
  616. CnAssert(
  617. CnpIsIPv4McastTransportAddress(mcastGroup->McastTdiAddress)
  618. );
  619. CnAssert(
  620. mcastGroup->McastTdiAddressLength == interface->TdiAddressLength
  621. );
  622. RtlMoveMemory(
  623. addressBuffer,
  624. mcastGroup->McastTdiAddress,
  625. mcastGroup->McastTdiAddressLength
  626. );
  627. SendRequest->TdiSendDatagramInfo.RemoteAddressLength =
  628. mcastGroup->McastTdiAddressLength;
  629. if (mcastGroupReferenced) {
  630. CnpDereferenceMulticastGroup(mcastGroup);
  631. mcastGroupReferenced = FALSE;
  632. SendRequest->McastGroup = NULL;
  633. }
  634. targetFileObject = network->DatagramFileObject;
  635. targetDeviceObject = network->DatagramDeviceObject;
  636. } else {
  637. CnAssert(mcastGroupReferenced == FALSE);
  638. RtlMoveMemory(
  639. addressBuffer,
  640. &(interface->TdiAddress),
  641. interface->TdiAddressLength
  642. );
  643. SendRequest->TdiSendDatagramInfo.RemoteAddressLength =
  644. interface->TdiAddressLength;
  645. targetFileObject = network->DatagramFileObject;
  646. targetDeviceObject = network->DatagramDeviceObject;
  647. }
  648. SendRequest->TdiSendDatagramInfo.RemoteAddress =
  649. addressBuffer;
  650. //
  651. // Release the node lock.
  652. //
  653. CnReleaseLock(&(destNode->Lock), destNode->Irql);
  654. destNodeLocked = FALSE;
  655. //
  656. // If there is an upper protocol IRP, see
  657. // if it has enough stack locations.
  658. //
  659. if ( (upperIrp != NULL)
  660. &&
  661. (CnpIsIrpStackSufficient(upperIrp, targetDeviceObject))
  662. ) {
  663. //
  664. // We can use the upper protocol IRP.
  665. //
  666. irp = upperIrp;
  667. compRoutine = CnpCompleteSendPacketReuseIrp;
  668. //
  669. // Ensure that IRP is marked as a kernel request,
  670. // but first save the current requestor mode so
  671. // that it can be restored later.
  672. //
  673. SendRequest->UpperProtocolIrpMode = irp->RequestorMode;
  674. irp->RequestorMode = KernelMode;
  675. //
  676. // Save the upper protocol IRP MDL to restore
  677. // later. This is probably the same as DataMdl,
  678. // but we don't want to make any assumptions.
  679. //
  680. SendRequest->UpperProtocolMdl = irp->MdlAddress;
  681. } else {
  682. //
  683. // We cannot use the upper protocol IRP.
  684. //
  685. // If there is an upper protocol IRP, it needs
  686. // to be marked pending.
  687. //
  688. if (upperIrp != NULL) {
  689. CnAcquireCancelSpinLock(&cancelIrql);
  690. status = CnMarkRequestPending(
  691. upperIrp,
  692. IoGetCurrentIrpStackLocation(upperIrp),
  693. NULL
  694. );
  695. CnReleaseCancelSpinLock(cancelIrql);
  696. if (status == STATUS_CANCELLED) {
  697. //
  698. // Bail out
  699. //
  700. status = STATUS_INSUFFICIENT_RESOURCES;
  701. goto error_exit;
  702. } else {
  703. //
  704. // If IoAllocateIrp fails, we need
  705. // to call CnCompletePendingRequest
  706. // now that we've called
  707. // CnMarkRequestPending.
  708. //
  709. cnComplete = TRUE;
  710. }
  711. }
  712. //
  713. // Allocate a new IRP
  714. //
  715. irp = IoAllocateIrp(
  716. targetDeviceObject->StackSize,
  717. FALSE
  718. );
  719. if (irp == NULL) {
  720. status = STATUS_INSUFFICIENT_RESOURCES;
  721. goto error_exit;
  722. }
  723. //
  724. // Use the completion routine for having
  725. // allocated a new IRP
  726. //
  727. compRoutine = CnpCompleteSendPacketNewIrp;
  728. //
  729. // Fill in IRP fields that are not specific
  730. // to any one stack location.
  731. //
  732. irp->Flags = 0;
  733. irp->RequestorMode = KernelMode;
  734. irp->PendingReturned = FALSE;
  735. irp->UserIosb = NULL;
  736. irp->UserEvent = NULL;
  737. irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
  738. irp->AssociatedIrp.SystemBuffer = NULL;
  739. irp->UserBuffer = NULL;
  740. irp->Tail.Overlay.Thread = PsGetCurrentThread();
  741. irp->Tail.Overlay.AuxiliaryBuffer = NULL;
  742. }
  743. //
  744. // Ok, we can finally send the packet.
  745. //
  746. SendRequest->Network = network;
  747. //
  748. // Link the data MDL chain after the header MDL.
  749. //
  750. SendRequest->HeaderMdl->Next = DataMdl;
  751. //
  752. // Finish building the CNP header.
  753. //
  754. cnpHeader->DestinationAddress = DestNodeId;
  755. cnpHeader->PayloadLength =
  756. SendRequest->UpperProtocolHeaderLength + DataLength;
  757. //
  758. // Build the next irp stack location.
  759. //
  760. TdiBuildSendDatagram(
  761. irp,
  762. targetDeviceObject,
  763. targetFileObject,
  764. compRoutine,
  765. SendRequest,
  766. SendRequest->HeaderMdl,
  767. cnpHeader->PayloadLength + sizeof(CNP_HEADER) + sigDataLen,
  768. &(SendRequest->TdiSendDatagramInfo)
  769. );
  770. CnTrace(CNP_SEND_DETAIL, CnpTraceSend,
  771. "[CNP] Sending packet to node %u on net %u, "
  772. "data len %u",
  773. cnpHeader->DestinationAddress, // LOGULONG
  774. network->Id, // LOGULONG
  775. cnpHeader->PayloadLength // LOGUSHORT
  776. );
  777. //
  778. // Now send the packet.
  779. //
  780. status = IoCallDriver(
  781. targetDeviceObject,
  782. irp
  783. );
  784. CnVerifyCpuLockMask(
  785. 0, // Required
  786. CNP_LOCK_RANGE, // Forbidden
  787. CNP_PRECEEDING_LOCK_RANGE // Maximum
  788. );
  789. return(status);
  790. //
  791. // The following code is only executed in an error condition,
  792. // No send IRP has been submitted to a lower-level driver.
  793. //
  794. error_exit:
  795. CnTrace(CNP_SEND_ERROR, CnpTraceSendFailedInternal,
  796. "[CNP] Failed to send packet to node %u on net %u, "
  797. "data len %u, status %!status!",
  798. cnpHeader->DestinationAddress, // LOGULONG
  799. NetworkId, // LOGULONG
  800. cnpHeader->PayloadLength, // LOGUSHORT
  801. status // LOGSTATUS
  802. );
  803. if (destNodeLocked) {
  804. CnReleaseLock(&(destNode->Lock), destNode->Irql);
  805. destNodeLocked = FALSE;
  806. }
  807. if (networkReferenced) {
  808. //
  809. // Remove the active reference we put on the network.
  810. //
  811. CnAcquireLock(&(network->Lock), &(network->Irql));
  812. CnpActiveDereferenceNetwork(network);
  813. networkReferenced = FALSE;
  814. }
  815. if (mcastGroupReferenced) {
  816. CnAssert(SendRequest->McastGroup != NULL);
  817. CnpDereferenceMulticastGroup(SendRequest->McastGroup);
  818. SendRequest->McastGroup = NULL;
  819. mcastGroupReferenced = FALSE;
  820. }
  821. if (addressBuffer != NULL) {
  822. CnFreePool(addressBuffer);
  823. }
  824. //
  825. // Call the upper protocol completion routine
  826. //
  827. if (SendRequest->CompletionRoutine) {
  828. ULONG bytesSent = 0;
  829. (*SendRequest->CompletionRoutine)(
  830. status,
  831. &bytesSent,
  832. SendRequest,
  833. DataMdl
  834. );
  835. }
  836. //
  837. // Complete the upper protocol IRP, if there is one
  838. //
  839. if (upperIrp) {
  840. if (cnComplete) {
  841. //
  842. // CnMarkRequestPending was called for upperIrp.
  843. //
  844. IF_CNDBG( CN_DEBUG_CNPSEND )
  845. CNPRINT(("[CNP] Calling CnCompletePendingRequest "
  846. "for IRP %p with status %08x\n",
  847. upperIrp, status));
  848. CnCompletePendingRequest(upperIrp, status, 0);
  849. } else {
  850. IF_CNDBG( CN_DEBUG_CNPSEND )
  851. CNPRINT(("[CNP] Completing IRP %p with status %08x\n",
  852. upperIrp, status));
  853. upperIrp->IoStatus.Status = status;
  854. upperIrp->IoStatus.Information = 0;
  855. IoCompleteRequest(upperIrp, IO_NO_INCREMENT);
  856. }
  857. }
  858. CnVerifyCpuLockMask(
  859. 0, // Required
  860. CNP_LOCK_RANGE, // Forbidden
  861. CNP_PRECEEDING_LOCK_RANGE // Maximum
  862. );
  863. return(status);
  864. } // CnpSendPacket