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.

290 lines
6.9 KiB

  1. /*++
  2. Copyright (c) 1989-1993 Microsoft Corporation
  3. Module Name:
  4. loopback.c
  5. Abstract:
  6. This module contains the routines to implement loopback
  7. Author:
  8. Sanjay Anand (SanjayAn) 2/6/96
  9. Environment:
  10. Kernel mode
  11. Revision History:
  12. --*/
  13. #include "precomp.h"
  14. #pragma hdrstop
  15. //
  16. // Global lock to control access to the Loopback queue
  17. //
  18. DEFINE_LOCK_STRUCTURE(LoopLock)
  19. //
  20. // Head and tail of the Loopback queue
  21. //
  22. PNDIS_PACKET LoopXmitHead = (PNDIS_PACKET)NULL;
  23. PNDIS_PACKET LoopXmitTail = (PNDIS_PACKET)NULL;
  24. CTEEvent LoopXmitEvent;
  25. BOOLEAN LoopXmitRtnRunning = 0;
  26. //
  27. // MaximumPacket sized buffer to hold the lookahead data.
  28. //
  29. // In PnP this value can change
  30. //
  31. // PUCHAR LookaheadBuffer=NULL;
  32. #define LOOP_LOOKAHEAD_SIZE 128 + sizeof(IPX_HEADER) + 8 + 34
  33. VOID
  34. IpxDoLoopback(
  35. IN CTEEvent *Event,
  36. IN PVOID Context
  37. )
  38. /*++
  39. Routine Description:
  40. Does the actual loopback.
  41. Arguments:
  42. Event - Pointer to event structure.
  43. Context - Pointer to ZZ
  44. Return Value:
  45. None.
  46. --*/
  47. {
  48. PNDIS_PACKET Packet; // Pointer to packet being transmitted
  49. PNDIS_BUFFER Buffer; // Current NDIS buffer being processed.
  50. ULONG TotalLength; // Total length of send.
  51. ULONG LookaheadLength; // Bytes in lookahead.
  52. ULONG Copied; // Bytes copied so far.
  53. PUCHAR CopyPtr; // Pointer to buffer being copied into.
  54. PUCHAR SrcPtr; // Pointer to buffer being copied from.
  55. ULONG SrcLength; // Length of src buffer.
  56. BOOLEAN Rcvd = FALSE;
  57. PIPX_SEND_RESERVED Reserved;
  58. ULONG MacSize;
  59. PNDIS_PACKET *PacketPtr;
  60. UCHAR LookaheadBuffer[LOOP_LOOKAHEAD_SIZE];
  61. IPX_DEFINE_LOCK_HANDLE(Handle)
  62. KIRQL OldIrql;
  63. CTEAssert(KeGetCurrentIrql() < DISPATCH_LEVEL);
  64. //
  65. // Raise IRQL so we can acquire locks at DPC level in the receive code.
  66. // Also to be able to ReceiveIndicate at DPC
  67. //
  68. KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
  69. IPX_GET_LOCK(&LoopLock, &Handle);
  70. if (LoopXmitRtnRunning) {
  71. IPX_FREE_LOCK(&LoopLock, Handle);
  72. KeLowerIrql(OldIrql);
  73. return;
  74. }
  75. LoopXmitRtnRunning = 1;
  76. for (;;) {
  77. //
  78. // Get the next packet from the list.
  79. //
  80. Packet = LoopXmitHead;
  81. if (Packet != (PNDIS_PACKET)NULL) {
  82. Reserved = (PIPX_SEND_RESERVED)(Packet->ProtocolReserved);
  83. LoopXmitHead = (PNDIS_PACKET)(Reserved->PaddingBuffer);
  84. IPX_FREE_LOCK(&LoopLock, Handle);
  85. } else { // Nothing left to do.
  86. LoopXmitRtnRunning = 0;
  87. IPX_FREE_LOCK(&LoopLock, Handle);
  88. break;
  89. }
  90. //
  91. // We use the PaddingBuffer section as the next ptr.
  92. //
  93. Reserved->PaddingBuffer = NULL;
  94. IPX_DEBUG(LOOPB, ("Packet: %lx\n", Packet));
  95. NdisQueryPacket(Packet, NULL, NULL, &Buffer, &TotalLength);
  96. NdisQueryBuffer(Buffer, NULL, &MacSize);
  97. IPX_DEBUG(LOOPB, ("Buffer: %lx Totalpktlen: %lx MacSize: %lx\n", Buffer, TotalLength, MacSize));
  98. LookaheadLength = MIN(LOOP_LOOKAHEAD_SIZE, TotalLength);
  99. Copied = 0;
  100. CopyPtr = LookaheadBuffer;
  101. while (Copied < LookaheadLength) {
  102. ULONG ThisCopy; // Bytes to copy this time.
  103. #ifdef DBG
  104. if (!Buffer) {
  105. DbgBreakPoint();
  106. IPX_GET_LOCK(&LoopLock, &Handle);
  107. LoopXmitRtnRunning = 0;
  108. IPX_FREE_LOCK(&LoopLock, Handle);
  109. KeLowerIrql(OldIrql);
  110. return;
  111. }
  112. #endif
  113. NdisQueryBufferSafe(Buffer, &SrcPtr, &SrcLength, HighPagePriority);
  114. if (SrcPtr == NULL) {
  115. DbgPrint("IpxDoLoopback: NdisQuerybufferSafe returned null pointer\n");
  116. IPX_GET_LOCK(&LoopLock, &Handle);
  117. LoopXmitRtnRunning = 0;
  118. IPX_FREE_LOCK(&LoopLock, Handle);
  119. KeLowerIrql(OldIrql);
  120. return;
  121. }
  122. ThisCopy = MIN(SrcLength, LookaheadLength - Copied);
  123. CTEMemCopy(CopyPtr, SrcPtr, ThisCopy);
  124. Copied += ThisCopy;
  125. CopyPtr += ThisCopy;
  126. NdisGetNextBuffer(Buffer, &Buffer);
  127. }
  128. Rcvd = TRUE;
  129. #ifdef BACK_FILL
  130. //
  131. // For Backfill packets, the MAC header is not yet set up; for others, it is the size
  132. // of the first MDL (17).
  133. //
  134. if ((Reserved->Identifier == IDENTIFIER_IPX) &&
  135. (Reserved->BackFill)) {
  136. MacSize = 0;
  137. }
  138. #endif
  139. IpxReceiveIndication( (NDIS_HANDLE)IPX_LOOPBACK_COOKIE, // BindingContext
  140. Packet, // ReceiveContext
  141. (MacSize) ? LookaheadBuffer : NULL, // HeaderBuffer
  142. MacSize, // HeaderBufferSize
  143. LookaheadBuffer+MacSize, // LookAheadBuffer
  144. LookaheadLength-MacSize, // LookAheadBufferSize
  145. TotalLength-MacSize); // PacketSize
  146. IpxSendComplete(Context, Packet, NDIS_STATUS_SUCCESS);
  147. //
  148. // Give other threads a chance to run.
  149. //
  150. KeLowerIrql(OldIrql);
  151. KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
  152. IPX_GET_LOCK(&LoopLock, &Handle);
  153. }
  154. if (Rcvd) {
  155. IpxReceiveComplete(Context);
  156. }
  157. KeLowerIrql(OldIrql);
  158. }
  159. VOID
  160. IpxInitLoopback()
  161. /*++
  162. Routine Description:
  163. Initializes various loopback structures.
  164. Arguments:
  165. Return Value:
  166. None.
  167. --*/
  168. {
  169. CTEInitLock(&LoopLock);
  170. CTEInitEvent(&LoopXmitEvent, IpxDoLoopback);
  171. return;
  172. }
  173. VOID
  174. IpxLoopbackEnque(
  175. IN PNDIS_PACKET Packet,
  176. IN PVOID Context
  177. )
  178. /*++
  179. Routine Description:
  180. Enqueues a packet to the loopbackQ
  181. Arguments:
  182. Packet - The packet to be enqueued.
  183. Context - Pointer to the adapter corresp to the first binding.
  184. Return Value:
  185. None.
  186. --*/
  187. {
  188. PIPX_SEND_RESERVED Reserved = (PIPX_SEND_RESERVED)(Packet->ProtocolReserved);
  189. IPX_DEFINE_LOCK_HANDLE(LockHandle)
  190. //
  191. // We use the PaddingBuffer as the next ptr.
  192. //
  193. Reserved->PaddingBuffer = NULL;
  194. IPX_GET_LOCK(&LoopLock, &LockHandle);
  195. //
  196. // LoopbackQ is empty
  197. //
  198. if (LoopXmitHead == (PNDIS_PACKET)NULL) {
  199. LoopXmitHead = Packet;
  200. } else {
  201. Reserved = (PIPX_SEND_RESERVED)(LoopXmitTail->ProtocolReserved);
  202. (PNDIS_PACKET)(Reserved->PaddingBuffer) = Packet;
  203. }
  204. LoopXmitTail = Packet;
  205. IPX_DEBUG(LOOPB, ("Enqued packet: %lx, Reserved: %lx\n", Packet, Reserved));
  206. //
  207. // If this routine is not already running, schedule it as a work item.
  208. //
  209. if (!LoopXmitRtnRunning) {
  210. CTEScheduleEvent(&LoopXmitEvent, Context);
  211. }
  212. IPX_FREE_LOCK(&LoopLock, LockHandle);
  213. }