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.

549 lines
15 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. cdpsend.c
  5. Abstract:
  6. TDI Receive 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 "cdprecv.tmh"
  18. #include <sspi.h>
  19. #ifdef ALLOC_PRAGMA
  20. #endif // ALLOC_PRAGMA
  21. //
  22. // Local types
  23. //
  24. typedef struct {
  25. CL_NODE_ID SourceNodeId;
  26. USHORT SourcePort;
  27. ULONG TdiReceiveDatagramFlags;
  28. ULONG TsduSize;
  29. PCX_ADDROBJ AddrObj;
  30. PCNP_NETWORK Network;
  31. } CDP_RECEIVE_CONTEXT, *PCDP_RECEIVE_CONTEXT;
  32. //
  33. // Local Data
  34. //
  35. PCN_RESOURCE_POOL CdpReceiveRequestPool = NULL;
  36. #define CDP_RECEIVE_REQUEST_POOL_DEPTH 2
  37. //
  38. // Local utility routines
  39. //
  40. VOID
  41. CdpIndicateReceivePacket(
  42. IN PCX_ADDROBJ AddrObj,
  43. IN CL_NODE_ID SourceNodeId,
  44. IN USHORT SourcePort,
  45. IN ULONG TdiReceiveDatagramFlags,
  46. IN ULONG TsduSize,
  47. IN PVOID Tsdu,
  48. IN BOOLEAN DataVerified
  49. )
  50. /*++
  51. Notes:
  52. Called with address object lock held.
  53. Returns with address object lock released.
  54. --*/
  55. {
  56. NTSTATUS status;
  57. PTDI_IND_RECEIVE_DATAGRAM handler = AddrObj->ReceiveDatagramHandler;
  58. PVOID context = AddrObj->ReceiveDatagramContext;
  59. TA_CLUSTER_ADDRESS sourceTransportAddress;
  60. PIRP irp = NULL;
  61. ULONG bytesTaken = 0;
  62. CnVerifyCpuLockMask(
  63. CX_ADDROBJ_LOCK, // Required
  64. 0, // Forbidden
  65. CX_ADDROBJ_LOCK_MAX // Maximum
  66. );
  67. CnAssert(handler != NULL);
  68. CnReleaseLock(&(AddrObj->Lock), AddrObj->Irql);
  69. //
  70. // Build the source address buffer
  71. //
  72. CxBuildTdiAddress(
  73. &sourceTransportAddress,
  74. SourceNodeId,
  75. SourcePort,
  76. DataVerified
  77. );
  78. CnTrace(CDP_RECV_DETAIL, CdpTraceIndicateReceive,
  79. "[CDP] Indicating dgram, src: node %u port %u, dst: port %u, "
  80. "data len %u",
  81. SourceNodeId, // LOGULONG
  82. SourcePort, // LOGUSHORT
  83. AddrObj->LocalPort, // LOGUSHORT
  84. TsduSize // LOGULONG
  85. );
  86. //
  87. // Call the upper layer indication handler.
  88. //
  89. status = (*handler)(
  90. context,
  91. sizeof(TA_CLUSTER_ADDRESS),
  92. &sourceTransportAddress,
  93. 0, // no options
  94. NULL,
  95. TdiReceiveDatagramFlags,
  96. TsduSize,
  97. TsduSize,
  98. &bytesTaken,
  99. Tsdu,
  100. &irp
  101. );
  102. CnAssert(status != STATUS_MORE_PROCESSING_REQUIRED);
  103. CnAssert(bytesTaken == TsduSize);
  104. CnAssert(irp == NULL);
  105. if (irp != NULL) {
  106. irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
  107. irp->IoStatus.Information = 0;
  108. IoCompleteRequest(irp, IO_NETWORK_INCREMENT);
  109. }
  110. //
  111. // Dereference the address object
  112. //
  113. CnDereferenceFsContext(&(AddrObj->FsContext));
  114. CnVerifyCpuLockMask(
  115. 0, // Required
  116. 0xFFFFFFFF, // Forbidden
  117. 0 // Maximum
  118. );
  119. return;
  120. } // CdpIndicateReceivePacket
  121. NTSTATUS
  122. CdpCompleteReceivePacket(
  123. IN PDEVICE_OBJECT DeviceObject,
  124. IN PIRP Irp,
  125. IN PVOID Context
  126. )
  127. {
  128. NTSTATUS status;
  129. PCNP_RECEIVE_REQUEST request = Context;
  130. PCDP_RECEIVE_CONTEXT context = request->UpperProtocolContext;
  131. PCX_ADDROBJ addrObj = context->AddrObj;
  132. ULONG consumed;
  133. PVOID data;
  134. ULONG dataLength;
  135. BOOLEAN fscontextDereferenced = FALSE;
  136. if (Irp->IoStatus.Status == STATUS_SUCCESS) {
  137. CnAssert(Irp->IoStatus.Information == context->TsduSize);
  138. data = request->DataBuffer;
  139. dataLength = (ULONG)Irp->IoStatus.Information;
  140. CnAcquireLock(&(addrObj->Lock), &(addrObj->Irql));
  141. if (addrObj->ReceiveDatagramHandler != NULL) {
  142. CdpIndicateReceivePacket(
  143. addrObj,
  144. context->SourceNodeId,
  145. context->SourcePort,
  146. context->TdiReceiveDatagramFlags,
  147. dataLength,
  148. data,
  149. FALSE // not verified
  150. );
  151. fscontextDereferenced = TRUE;
  152. }
  153. else {
  154. CnReleaseLock(&(addrObj->Lock), addrObj->Irql);
  155. }
  156. }
  157. else {
  158. CnTrace(CDP_RECV_ERROR, CdpTraceCompleteReceiveFailed,
  159. "[CDP] Failed to fetch dgram data, src: node %u port %u, "
  160. "dst: port %u, status %!status!",
  161. context->SourceNodeId, // LOGULONG
  162. context->SourcePort, // LOGUSHORT
  163. addrObj->LocalPort, // LOGUSHORT
  164. Irp->IoStatus.Status // LOGSTATUS
  165. );
  166. }
  167. //
  168. // Drop the active reference on the network.
  169. //
  170. if (context->Network != NULL) {
  171. CnAcquireLock(&(context->Network->Lock), &(context->Network->Irql));
  172. CnpActiveDereferenceNetwork(context->Network);
  173. context->Network = NULL;
  174. }
  175. //
  176. // Dereference the addr object fscontext (only necessary
  177. // after error condition).
  178. //
  179. if (!fscontextDereferenced) {
  180. CnDereferenceFsContext(&(addrObj->FsContext));
  181. }
  182. CnpFreeReceiveRequest(request);
  183. CnVerifyCpuLockMask(
  184. 0, // Required
  185. 0xFFFFFFFF, // Forbidden
  186. 0 // Maximum
  187. );
  188. return(STATUS_MORE_PROCESSING_REQUIRED);
  189. } // CdpCompleteReceivePacket
  190. //
  191. // Routines exported within the Cluster Transport
  192. //
  193. NTSTATUS
  194. CdpInitializeReceive(
  195. VOID
  196. )
  197. {
  198. IF_CNDBG(CN_DEBUG_INIT){
  199. CNPRINT(("[CDP] Initializing receive...\n"));
  200. }
  201. CdpReceiveRequestPool = CnpCreateReceiveRequestPool(
  202. sizeof(CDP_RECEIVE_CONTEXT),
  203. CDP_RECEIVE_REQUEST_POOL_DEPTH
  204. );
  205. if (CdpReceiveRequestPool == NULL) {
  206. return(STATUS_INSUFFICIENT_RESOURCES);
  207. }
  208. IF_CNDBG(CN_DEBUG_INIT){
  209. CNPRINT(("[CDP] Receive initialized.\n"));
  210. }
  211. return(STATUS_SUCCESS);
  212. } // CdpInitializeReceive
  213. VOID
  214. CdpCleanupReceive(
  215. VOID
  216. )
  217. {
  218. IF_CNDBG(CN_DEBUG_INIT){
  219. CNPRINT(("[CDP] Cleaning up receive...\n"));
  220. }
  221. if (CdpReceiveRequestPool != NULL) {
  222. CnpDeleteReceiveRequestPool(CdpReceiveRequestPool);
  223. CdpReceiveRequestPool = NULL;
  224. }
  225. IF_CNDBG(CN_DEBUG_INIT){
  226. CNPRINT(("[CDP] Receive cleanup complete.\n"));
  227. }
  228. return;
  229. } // CdpCleanupReceive
  230. NTSTATUS
  231. CdpReceivePacketHandler(
  232. IN PVOID Network,
  233. IN CL_NODE_ID SourceNodeId,
  234. IN ULONG CnpReceiveFlags,
  235. IN ULONG TdiReceiveDatagramFlags,
  236. IN ULONG BytesIndicated,
  237. IN ULONG BytesAvailable,
  238. OUT PULONG BytesTaken,
  239. IN PVOID Tsdu,
  240. OUT PIRP * Irp
  241. )
  242. {
  243. NTSTATUS status;
  244. CDP_HEADER UNALIGNED * header = Tsdu;
  245. PCX_ADDROBJ addrObj;
  246. ULONG bytesTaken = 0;
  247. PCNP_RECEIVE_REQUEST request;
  248. USHORT srcPort = 0;
  249. USHORT destPort = 0;
  250. ULONG consumed = 0;
  251. CnAssert(KeGetCurrentIrql() == DISPATCH_LEVEL);
  252. if (BytesIndicated >= sizeof(CDP_HEADER))
  253. {
  254. destPort = header->DestinationPort;
  255. srcPort = header->SourcePort;
  256. //
  257. // Consume the CDP header
  258. //
  259. consumed = sizeof(CDP_HEADER);
  260. //
  261. // Verify that the remaining packet is consistent.
  262. //
  263. if (header->PayloadLength != (BytesAvailable - consumed)) {
  264. goto error_exit;
  265. }
  266. BytesIndicated -= consumed;
  267. BytesAvailable -= consumed;
  268. *BytesTaken += consumed;
  269. Tsdu = (PUCHAR)Tsdu + consumed;
  270. CnAcquireLockAtDpc(&CxAddrObjTableLock);
  271. addrObj = CxFindAddressObject(destPort);
  272. if (addrObj != NULL) {
  273. CnReleaseLockFromDpc(&CxAddrObjTableLock);
  274. if ( ( !(addrObj->Flags & CX_AO_FLAG_CHECKSTATE)
  275. ||
  276. (CnpReceiveFlags & CNP_RECV_FLAG_NODE_STATE_CHECK_PASSED)
  277. )
  278. &&
  279. (addrObj->ReceiveDatagramHandler != NULL)
  280. )
  281. {
  282. //
  283. // Reference the address object so it can't go away during
  284. // the indication.
  285. //
  286. CnReferenceFsContext(&(addrObj->FsContext));
  287. if (BytesAvailable == BytesIndicated) {
  288. CdpIndicateReceivePacket(
  289. addrObj,
  290. SourceNodeId,
  291. srcPort,
  292. TdiReceiveDatagramFlags,
  293. BytesAvailable,
  294. ((BytesAvailable > 0) ? Tsdu : NULL),
  295. (BOOLEAN)(
  296. CnpReceiveFlags & CNP_RECV_FLAG_SIGNATURE_VERIFIED
  297. )
  298. );
  299. //
  300. // The addrObj lock was released.
  301. //
  302. *BytesTaken += BytesAvailable;
  303. *Irp = NULL;
  304. CnVerifyCpuLockMask(
  305. 0, // Required
  306. 0xFFFFFFFF, // Forbidden
  307. 0 // Maximum
  308. );
  309. return(STATUS_SUCCESS);
  310. }
  311. CnReleaseLockFromDpc(&(addrObj->Lock));
  312. //
  313. // This message cannot be a CNP multicast, and it
  314. // cannot have been verified, because the CNP layer
  315. // could not have verified an incomplete message.
  316. //
  317. CnAssert(!(CnpReceiveFlags & CNP_RECV_FLAG_MULTICAST));
  318. CnAssert(!(CnpReceiveFlags & CNP_RECV_FLAG_SIGNATURE_VERIFIED));
  319. //
  320. // We need to fetch the rest of the packet before we
  321. // can indicate it to the upper layer.
  322. //
  323. request = CnpAllocateReceiveRequest(
  324. CdpReceiveRequestPool,
  325. Network,
  326. BytesAvailable,
  327. CdpCompleteReceivePacket
  328. );
  329. if (request != NULL) {
  330. PCDP_RECEIVE_CONTEXT context;
  331. PCNP_NETWORK network = (PCNP_NETWORK)Network;
  332. context = request->UpperProtocolContext;
  333. context->SourceNodeId = SourceNodeId;
  334. context->SourcePort = header->SourcePort;
  335. context->TdiReceiveDatagramFlags = TdiReceiveDatagramFlags;
  336. context->TsduSize = BytesAvailable;
  337. context->AddrObj = addrObj;
  338. context->Network = Network;
  339. //
  340. // Take a reference on the network so that it
  341. // doesn't disappear before the IRP completes.
  342. //
  343. CnAcquireLock(&(network->Lock), &(network->Irql));
  344. CnpActiveReferenceNetwork(Network);
  345. CnReleaseLock(&(network->Lock), network->Irql);
  346. *Irp = request->Irp;
  347. CnTrace(CDP_RECV_DETAIL, CdpTraceCompleteReceive,
  348. "[CDP] Fetching dgram data, src: node %u port %u, "
  349. "dst: port %u, BI %u, BA %u, CNP Flags %x.",
  350. SourceNodeId, // LOGULONG
  351. srcPort, // LOGUSHORT
  352. destPort, // LOGUSHORT
  353. BytesIndicated, // LOGULONG
  354. BytesAvailable, // LOGULONG
  355. CnpReceiveFlags // LOGXLONG
  356. );
  357. CnVerifyCpuLockMask(
  358. 0, // Required
  359. 0xFFFFFFFF, // Forbidden
  360. 0 // Maximum
  361. );
  362. return(STATUS_MORE_PROCESSING_REQUIRED);
  363. }
  364. CnTrace(
  365. CDP_RECV_ERROR, CdpTraceDropReceiveNoIrp,
  366. "[CDP] Dropping dgram: failed to allocate "
  367. "receive request."
  368. );
  369. //
  370. // Out of resources. Drop the packet.
  371. //
  372. }
  373. else {
  374. //
  375. // No receive handler or node state check failed.
  376. //
  377. CnReleaseLockFromDpc(&(addrObj->Lock));
  378. CnTrace(
  379. CDP_RECV_ERROR, CdpTraceDropReceiveState,
  380. "[CDP] Dropping dgram: addr obj flags %x, "
  381. "CNP flags %x, dgram recv handler %p.",
  382. addrObj->Flags,
  383. CnpReceiveFlags,
  384. addrObj->ReceiveDatagramHandler
  385. );
  386. }
  387. }
  388. else {
  389. CnReleaseLockFromDpc(&CxAddrObjTableLock);
  390. CnTrace(
  391. CDP_RECV_ERROR, CdpTraceDropReceiveNoAO,
  392. "[CDP] Dropping dgram: no clusnet addr obj found "
  393. "for dest port %u.",
  394. destPort
  395. );
  396. }
  397. }
  398. error_exit:
  399. //
  400. // Something went wrong. Drop the packet by
  401. // indicating that we consumed it.
  402. //
  403. *BytesTaken += BytesAvailable;
  404. *Irp = NULL;
  405. CnTrace(CDP_RECV_ERROR, CdpTraceDropReceive,
  406. "[CDP] Dropped dgram, src: node %u port %u, dst: port %u, "
  407. "BI %u, BA %u, CNP flags %x.",
  408. SourceNodeId, // LOGULONG
  409. srcPort, // LOGUSHORT
  410. destPort, // LOGUSHORT
  411. BytesIndicated, // LOGULONG
  412. BytesAvailable, // LOGULONG
  413. CnpReceiveFlags // LOGXLONG
  414. );
  415. CnVerifyCpuLockMask(
  416. 0, // Required
  417. 0xFFFFFFFF, // Forbidden
  418. 0 // Maximum
  419. );
  420. return(STATUS_SUCCESS);
  421. } // CdpReceivePacketHandler
  422. //
  423. // Routines exported within the Cluster Network driver
  424. //
  425. NTSTATUS
  426. CxReceiveDatagram(
  427. IN PIRP Irp,
  428. IN PIO_STACK_LOCATION IrpSp
  429. )
  430. {
  431. NTSTATUS status = STATUS_NOT_IMPLEMENTED;
  432. CNPRINT(("[Clusnet] CxReceiveDatagram called!\n"));
  433. Irp->IoStatus.Status = status;
  434. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  435. return(status);
  436. } // CxReceiveDatagram