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.

558 lines
16 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. ULONG refCount;
  333. context = request->UpperProtocolContext;
  334. context->SourceNodeId = SourceNodeId;
  335. context->SourcePort = header->SourcePort;
  336. context->TdiReceiveDatagramFlags = TdiReceiveDatagramFlags;
  337. context->TsduSize = BytesAvailable;
  338. context->AddrObj = addrObj;
  339. context->Network = Network;
  340. //
  341. // Take a reference on the network so that it
  342. // doesn't disappear before the IRP completes.
  343. //
  344. CnAcquireLock(&(network->Lock), &(network->Irql));
  345. refCount = CnpActiveReferenceNetwork(Network);
  346. CnReleaseLock(&(network->Lock), network->Irql);
  347. if (refCount == 0) {
  348. // This Network is being closed down. We
  349. // cannot retrieve or deliver the data. Drop
  350. // the packet.
  351. CnpFreeReceiveRequest(request);
  352. goto error_exit;
  353. }
  354. *Irp = request->Irp;
  355. CnTrace(CDP_RECV_DETAIL, CdpTraceCompleteReceive,
  356. "[CDP] Fetching dgram data, src: node %u port %u, "
  357. "dst: port %u, BI %u, BA %u, CNP Flags %x.",
  358. SourceNodeId, // LOGULONG
  359. srcPort, // LOGUSHORT
  360. destPort, // LOGUSHORT
  361. BytesIndicated, // LOGULONG
  362. BytesAvailable, // LOGULONG
  363. CnpReceiveFlags // LOGXLONG
  364. );
  365. CnVerifyCpuLockMask(
  366. 0, // Required
  367. 0xFFFFFFFF, // Forbidden
  368. 0 // Maximum
  369. );
  370. return(STATUS_MORE_PROCESSING_REQUIRED);
  371. }
  372. CnTrace(
  373. CDP_RECV_ERROR, CdpTraceDropReceiveNoIrp,
  374. "[CDP] Dropping dgram: failed to allocate "
  375. "receive request."
  376. );
  377. //
  378. // Out of resources. Drop the packet.
  379. //
  380. }
  381. else {
  382. //
  383. // No receive handler or node state check failed.
  384. //
  385. CnReleaseLockFromDpc(&(addrObj->Lock));
  386. CnTrace(
  387. CDP_RECV_ERROR, CdpTraceDropReceiveState,
  388. "[CDP] Dropping dgram: addr obj flags %x, "
  389. "CNP flags %x, dgram recv handler %p.",
  390. addrObj->Flags,
  391. CnpReceiveFlags,
  392. addrObj->ReceiveDatagramHandler
  393. );
  394. }
  395. }
  396. else {
  397. CnReleaseLockFromDpc(&CxAddrObjTableLock);
  398. CnTrace(
  399. CDP_RECV_ERROR, CdpTraceDropReceiveNoAO,
  400. "[CDP] Dropping dgram: no clusnet addr obj found "
  401. "for dest port %u.",
  402. destPort
  403. );
  404. }
  405. }
  406. error_exit:
  407. //
  408. // Something went wrong. Drop the packet by
  409. // indicating that we consumed it.
  410. //
  411. *BytesTaken += BytesAvailable;
  412. *Irp = NULL;
  413. CnTrace(CDP_RECV_ERROR, CdpTraceDropReceive,
  414. "[CDP] Dropped dgram, src: node %u port %u, dst: port %u, "
  415. "BI %u, BA %u, CNP flags %x.",
  416. SourceNodeId, // LOGULONG
  417. srcPort, // LOGUSHORT
  418. destPort, // LOGUSHORT
  419. BytesIndicated, // LOGULONG
  420. BytesAvailable, // LOGULONG
  421. CnpReceiveFlags // LOGXLONG
  422. );
  423. CnVerifyCpuLockMask(
  424. 0, // Required
  425. 0xFFFFFFFF, // Forbidden
  426. 0 // Maximum
  427. );
  428. return(STATUS_SUCCESS);
  429. } // CdpReceivePacketHandler
  430. //
  431. // Routines exported within the Cluster Network driver
  432. //
  433. NTSTATUS
  434. CxReceiveDatagram(
  435. IN PIRP Irp,
  436. IN PIO_STACK_LOCATION IrpSp
  437. )
  438. {
  439. NTSTATUS status = STATUS_NOT_IMPLEMENTED;
  440. CNPRINT(("[Clusnet] CxReceiveDatagram called!\n"));
  441. Irp->IoStatus.Status = status;
  442. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  443. return(status);
  444. } // CxReceiveDatagram