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.

350 lines
10 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. cdpsend.c
  5. Abstract:
  6. TDI Send datagram routines.
  7. Author:
  8. Mike Massa (mikemas) February 20, 1997
  9. Revision History:
  10. Who When What
  11. -------- -------- ----------------------------------------------
  12. mikemas 02-20-97 created
  13. Notes:
  14. --*/
  15. #include "precomp.h"
  16. #pragma hdrstop
  17. #include "cdpsend.tmh"
  18. #ifdef ALLOC_PRAGMA
  19. #pragma alloc_text(INIT, CdpInitializeSend)
  20. #endif // ALLOC_PRAGMA
  21. //
  22. // Local Types
  23. //
  24. // CDP_SEND_CONTEXT is currently empty
  25. // typedef struct {
  26. // } CDP_SEND_CONTEXT, *PCDP_SEND_CONTEXT;
  27. typedef PVOID PCDP_SEND_CONTEXT;
  28. #define CDP_SEND_REQUEST_POOL_DEPTH 5
  29. //
  30. // Local Data
  31. //
  32. PCN_RESOURCE_POOL CdpSendRequestPool = NULL;
  33. PCN_RESOURCE_POOL CdpMcastSendRequestPool = NULL;
  34. //
  35. // Routines
  36. //
  37. NTSTATUS
  38. CdpInitializeSend(
  39. VOID
  40. )
  41. {
  42. IF_CNDBG(CN_DEBUG_INIT) {
  43. CNPRINT(("[CDP] Initializing send...\n"));
  44. }
  45. CdpSendRequestPool = CnpCreateSendRequestPool(
  46. CNP_VERSION_UNICAST,
  47. PROTOCOL_CDP,
  48. sizeof(CDP_HEADER),
  49. 0, // sizeof(CDP_SEND_CONTEXT),
  50. CDP_SEND_REQUEST_POOL_DEPTH
  51. );
  52. if (CdpSendRequestPool == NULL) {
  53. return(STATUS_INSUFFICIENT_RESOURCES);
  54. }
  55. CdpMcastSendRequestPool = CnpCreateSendRequestPool(
  56. CNP_VERSION_MULTICAST,
  57. PROTOCOL_CDP,
  58. sizeof(CDP_HEADER),
  59. 0, // sizeof(CDP_SEND_CONTEXT)
  60. CDP_SEND_REQUEST_POOL_DEPTH
  61. );
  62. if (CdpMcastSendRequestPool == NULL) {
  63. return(STATUS_INSUFFICIENT_RESOURCES);
  64. }
  65. IF_CNDBG(CN_DEBUG_INIT) {
  66. CNPRINT(("[CDP] Send initialized.\n"));
  67. }
  68. return(STATUS_SUCCESS);
  69. } // CdpInitializeSend
  70. VOID
  71. CdpCleanupSend(
  72. VOID
  73. )
  74. {
  75. IF_CNDBG(CN_DEBUG_INIT) {
  76. CNPRINT(("[CDP] Cleaning up send...\n"));
  77. }
  78. if (CdpSendRequestPool != NULL) {
  79. CnpDeleteSendRequestPool(CdpSendRequestPool);
  80. }
  81. if (CdpMcastSendRequestPool != NULL) {
  82. CnpDeleteSendRequestPool(CdpMcastSendRequestPool);
  83. }
  84. IF_CNDBG(CN_DEBUG_INIT) {
  85. CNPRINT(("[CDP] Send cleanup complete.\n"));
  86. }
  87. return;
  88. } // CdpCleanupSend
  89. VOID
  90. CdpCompleteSendDatagram(
  91. IN NTSTATUS Status,
  92. IN OUT PULONG BytesSent,
  93. IN PCNP_SEND_REQUEST SendRequest,
  94. IN PMDL DataMdl
  95. )
  96. {
  97. PCDP_SEND_CONTEXT sendContext = SendRequest->UpperProtocolContext;
  98. PCNP_HEADER cnpHeader = SendRequest->CnpHeader;
  99. PCDP_HEADER cdpHeader = SendRequest->UpperProtocolHeader;
  100. if (NT_SUCCESS(Status)) {
  101. if (*BytesSent >= sizeof(CDP_HEADER)) {
  102. *BytesSent -= sizeof(CDP_HEADER);
  103. }
  104. else {
  105. *BytesSent = 0;
  106. CnAssert(FALSE);
  107. }
  108. CnTrace(CDP_SEND_DETAIL, CdpTraceSendComplete,
  109. "[CDP] Send of dgram to node %u port %u complete, bytes sent %u.",
  110. cnpHeader->DestinationAddress, // LOGULONG
  111. cdpHeader->DestinationPort, // LOGUSHORT
  112. *BytesSent // LOGULONG
  113. );
  114. }
  115. else {
  116. CnTrace(CDP_SEND_ERROR, CdpTraceSendFailedBelow,
  117. "[CDP] Transport failed to send dgram to node %u port %u, "
  118. "data len %u, status %!status!",
  119. cnpHeader->DestinationAddress, // LOGULONG
  120. cdpHeader->DestinationPort, // LOGUSHORT
  121. cdpHeader->PayloadLength, // LOGUSHORT
  122. Status // LOGSTATUS
  123. );
  124. CnAssert(*BytesSent == 0);
  125. }
  126. CnAssert(sendContext == NULL);
  127. if (cnpHeader->DestinationAddress == ClusterAnyNodeId) {
  128. //
  129. // Dereference the network multicast group data structure.
  130. //
  131. if (SendRequest->McastGroup != NULL) {
  132. CnpDereferenceMulticastGroup(SendRequest->McastGroup);
  133. SendRequest->McastGroup = NULL;
  134. }
  135. }
  136. CnFreeResource((PCN_RESOURCE) SendRequest);
  137. return;
  138. } // CdpCompleteSendDatagram
  139. NTSTATUS
  140. CxSendDatagram(
  141. IN PIRP Irp,
  142. IN PIO_STACK_LOCATION IrpSp
  143. )
  144. {
  145. NTSTATUS status = STATUS_NOT_IMPLEMENTED;
  146. PCX_ADDROBJ addrObj;
  147. PTDI_REQUEST_KERNEL_SENDDG request;
  148. ULONG bytesSent = 0;
  149. CN_IRQL cancelIrql;
  150. USHORT destPort = 0;
  151. CL_NODE_ID destNode = ClusterInvalidNodeId;
  152. addrObj = (PCX_ADDROBJ) IrpSp->FileObject->FsContext;
  153. request = (PTDI_REQUEST_KERNEL_SENDDG) &(IrpSp->Parameters);
  154. if (request->SendLength <= CDP_MAX_SEND_SIZE(CX_SIGNATURE_LENGTH)) {
  155. if ( request->SendDatagramInformation->RemoteAddressLength >=
  156. sizeof(TA_CLUSTER_ADDRESS)
  157. )
  158. {
  159. status = CxParseTransportAddress(
  160. request->SendDatagramInformation->RemoteAddress,
  161. request->SendDatagramInformation->RemoteAddressLength,
  162. &destNode,
  163. &destPort
  164. );
  165. if (status == STATUS_SUCCESS) {
  166. if (destPort != 0) {
  167. PCNP_SEND_REQUEST sendRequest;
  168. if (destNode == ClusterAnyNodeId) {
  169. //
  170. // This is a CNP multicast.
  171. //
  172. sendRequest =
  173. (PCNP_SEND_REQUEST) CnAllocateResource(
  174. CdpMcastSendRequestPool
  175. );
  176. } else {
  177. //
  178. // This is a normal unicast.
  179. //
  180. sendRequest =
  181. (PCNP_SEND_REQUEST) CnAllocateResource(
  182. CdpSendRequestPool
  183. );
  184. }
  185. if (sendRequest != NULL) {
  186. PCDP_HEADER cdpHeader;
  187. PCDP_SEND_CONTEXT sendContext;
  188. BOOLEAN checkState;
  189. CL_NETWORK_ID destNet = ClusterAnyNetworkId;
  190. checkState = (addrObj->Flags &
  191. CX_AO_FLAG_CHECKSTATE) ?
  192. TRUE : FALSE;
  193. //
  194. // Fill in the CDP header.
  195. //
  196. cdpHeader = sendRequest->UpperProtocolHeader;
  197. RtlZeroMemory(cdpHeader, sizeof(CDP_HEADER));
  198. cdpHeader->SourcePort = addrObj->LocalPort;
  199. cdpHeader->DestinationPort = destPort;
  200. cdpHeader->PayloadLength = (USHORT)request->SendLength;
  201. //
  202. // Fill in the caller portion of the CNP
  203. // send request.
  204. //
  205. sendRequest->UpperProtocolIrp = Irp;
  206. sendRequest->CompletionRoutine =
  207. CdpCompleteSendDatagram;
  208. //
  209. // Fill in our own send context
  210. // (currently nothing).
  211. //
  212. sendContext = sendRequest->UpperProtocolContext;
  213. CnAssert(sendContext == NULL);
  214. CnVerifyCpuLockMask(
  215. 0, // Required
  216. CNP_LOCK_RANGE, // Forbidden
  217. CNP_PRECEEDING_LOCK_RANGE // Maximum
  218. );
  219. //
  220. // Send the message.
  221. //
  222. CnTrace(CDP_SEND_DETAIL, CdpTraceSend,
  223. "[CDP] Sending dgram to node %u port %u, "
  224. "data len %u.",
  225. destNode, // LOGULONG
  226. destPort, // LOGUSHORT
  227. request->SendLength // LOGULONG
  228. );
  229. status = CnpSendPacket(
  230. sendRequest,
  231. destNode,
  232. Irp->MdlAddress,
  233. (USHORT) request->SendLength,
  234. checkState,
  235. destNet
  236. );
  237. CnVerifyCpuLockMask(
  238. 0, // Required
  239. CNP_LOCK_RANGE, // Forbidden
  240. CNP_PRECEEDING_LOCK_RANGE // Maximum
  241. );
  242. return(status);
  243. }
  244. else {
  245. status = STATUS_INSUFFICIENT_RESOURCES;
  246. }
  247. }
  248. else {
  249. status = STATUS_INVALID_ADDRESS_COMPONENT;
  250. }
  251. }
  252. }
  253. else {
  254. status = STATUS_INVALID_ADDRESS_COMPONENT;
  255. }
  256. }
  257. else {
  258. status = STATUS_INVALID_BUFFER_SIZE;
  259. }
  260. CnTrace(CDP_SEND_ERROR, CdpTraceSendFailedInternal,
  261. "[CDP] Failed to send dgram to node %u port %u, data len %u, "
  262. "status %!status!",
  263. destNode, // LOGULONG
  264. destPort, // LOGUSHORT
  265. request->SendLength, // LOGULONG
  266. status // LOGSTATUS
  267. );
  268. Irp->IoStatus.Status = status;
  269. Irp->IoStatus.Information = 0;
  270. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  271. CnVerifyCpuLockMask(
  272. 0, // Required
  273. CNP_LOCK_RANGE, // Forbidden
  274. CNP_PRECEEDING_LOCK_RANGE // Maximum
  275. );
  276. return(status);
  277. } // CxSendDatagram