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.

1967 lines
73 KiB

  1. // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs)
  2. //
  3. // Copyright (c) 1985-2000 Microsoft Corporation
  4. //
  5. // This file is part of the Microsoft Research IPv6 Network Protocol Stack.
  6. // You should have received a copy of the Microsoft End-User License Agreement
  7. // for this software along with this release; see the file "license.txt".
  8. // If not, please see http://www.research.microsoft.com/msripv6/license.htm,
  9. // or write to Microsoft Research, One Microsoft Way, Redmond, WA 98052-6399.
  10. //
  11. // Abstract:
  12. //
  13. // TCP deliver data code.
  14. //
  15. // This file contains the code for delivering data to the user, including
  16. // putting data into recv. buffers and calling indication handlers.
  17. //
  18. #include "oscfg.h"
  19. #include "ndis.h"
  20. #include "ip6imp.h"
  21. #include "ip6def.h"
  22. #include "tdi.h"
  23. #include "tdint.h"
  24. #include "tdistat.h"
  25. #include "queue.h"
  26. #include "transprt.h"
  27. #include "addr.h"
  28. #include "tcp.h"
  29. #include "tcb.h"
  30. #include "tcprcv.h"
  31. #include "tcpsend.h"
  32. #include "tcpconn.h"
  33. #include "tcpdeliv.h"
  34. #include "route.h"
  35. extern KSPIN_LOCK AddrObjTableLock;
  36. extern uint
  37. PutOnRAQ(TCB *RcvTCB, TCPRcvInfo *RcvInfo, IPv6Packet *Packet, uint Size);
  38. extern IPv6Packet *
  39. TrimPacket(IPv6Packet *Packet, uint AmountToTrim);
  40. SLIST_HEADER TCPRcvReqFree; // Rcv req. free list.
  41. KSPIN_LOCK TCPRcvReqFreeLock; // Protects rcv req free list.
  42. uint NumTCPRcvReq = 0; // Current number of RcvReqs in system.
  43. uint MaxRcvReq = 0xffffffff; // Maximum allowed number of SendReqs.
  44. NTSTATUS TCPPrepareIrpForCancel(PTCP_CONTEXT TcpContext, PIRP Irp,
  45. PDRIVER_CANCEL CancelRoutine);
  46. ULONG TCPGetMdlChainByteCount(PMDL Mdl);
  47. void TCPDataRequestComplete(void *Context, unsigned int Status,
  48. unsigned int ByteCount);
  49. VOID TCPCancelRequest(PDEVICE_OBJECT Device, PIRP Irp);
  50. VOID CompleteRcvs(TCB *CmpltTCB);
  51. //* FreeRcvReq - Free a rcv request structure.
  52. //
  53. // Called to free a rcv request structure.
  54. //
  55. void // Returns: Nothing.
  56. FreeRcvReq(
  57. TCPRcvReq *FreedReq) // Rcv request structure to be freed.
  58. {
  59. PSLIST_ENTRY BufferLink;
  60. CHECK_STRUCT(FreedReq, trr);
  61. BufferLink = CONTAINING_RECORD(&(FreedReq->trr_next), SLIST_ENTRY,
  62. Next);
  63. ExInterlockedPushEntrySList(&TCPRcvReqFree, BufferLink,
  64. &TCPRcvReqFreeLock);
  65. }
  66. //* GetRcvReq - Get a recv. request structure.
  67. //
  68. // Called to get a rcv. request structure.
  69. //
  70. TCPRcvReq * // Returns: Pointer to RcvReq structure, or NULL if none.
  71. GetRcvReq(
  72. void) // Nothing.
  73. {
  74. TCPRcvReq *Temp;
  75. PSLIST_ENTRY BufferLink;
  76. BufferLink = ExInterlockedPopEntrySList(&TCPRcvReqFree,
  77. &TCPRcvReqFreeLock);
  78. if (BufferLink != NULL) {
  79. Temp = CONTAINING_RECORD(BufferLink, TCPRcvReq, trr_next);
  80. CHECK_STRUCT(Temp, trr);
  81. } else {
  82. if (NumTCPRcvReq < MaxRcvReq)
  83. Temp = ExAllocatePool(NonPagedPool, sizeof(TCPRcvReq));
  84. else
  85. Temp = NULL;
  86. if (Temp != NULL) {
  87. ExInterlockedAddUlong((PULONG)&NumTCPRcvReq, 1, &TCPRcvReqFreeLock);
  88. #if DBG
  89. Temp->trr_sig = trr_signature;
  90. #endif
  91. }
  92. }
  93. return Temp;
  94. }
  95. //* FindLastPacket - Find the last packet in a chain.
  96. //
  97. // A utility routine to find the last packet in a packet chain.
  98. //
  99. IPv6Packet * // Returns: Pointer to last packet in chain.
  100. FindLastPacket(
  101. IPv6Packet *Packet) // Pointer to packet chain.
  102. {
  103. ASSERT(Packet != NULL);
  104. while (Packet->Next != NULL)
  105. Packet = Packet->Next;
  106. return Packet;
  107. }
  108. //* CovetPacketChain - Take owership of a chain of IP packets.
  109. //
  110. // Called to seize ownership of a chain of IP packets. We copy any
  111. // packets that are not already owned by us. We assume that all packets
  112. // not belonging to us start before those that do, so we quit copying
  113. // when we reach a packet we own.
  114. //
  115. IPv6Packet * // Returns: Pointer to new packet chain.
  116. CovetPacketChain(
  117. IPv6Packet *OrigPkt, // Packet chain to copy from.
  118. IPv6Packet **LastPkt, // Where to return pointer to last packet in chain.
  119. uint Size) // Maximum size in bytes to seize.
  120. {
  121. IPv6Packet *FirstPkt, *EndPkt;
  122. uint BytesToCopy;
  123. ASSERT(OrigPkt != NULL);
  124. ASSERT(Size > 0);
  125. if (!(OrigPkt->Flags & PACKET_OURS)) {
  126. BytesToCopy = MIN(Size, OrigPkt->TotalSize);
  127. FirstPkt = ExAllocatePoolWithTagPriority(NonPagedPool,
  128. sizeof(IPv6Packet) +
  129. BytesToCopy, TCP6_TAG,
  130. LowPoolPriority);
  131. if (FirstPkt != NULL) {
  132. EndPkt = FirstPkt;
  133. FirstPkt->Next = NULL;
  134. FirstPkt->Position = 0;
  135. FirstPkt->FlatData = (uchar *)(FirstPkt + 1);
  136. FirstPkt->Data = FirstPkt->FlatData;
  137. FirstPkt->ContigSize = BytesToCopy;
  138. FirstPkt->TotalSize = BytesToCopy;
  139. FirstPkt->NdisPacket = NULL;
  140. FirstPkt->AuxList = NULL;
  141. FirstPkt->Flags = PACKET_OURS;
  142. CopyPacketToBuffer(FirstPkt->Data, OrigPkt, BytesToCopy,
  143. OrigPkt->Position);
  144. Size -= BytesToCopy;
  145. OrigPkt = OrigPkt->Next;
  146. while (OrigPkt != NULL && !(OrigPkt->Flags & PACKET_OURS)
  147. && Size != 0) {
  148. IPv6Packet *NewPkt;
  149. BytesToCopy = MIN(Size, OrigPkt->TotalSize);
  150. NewPkt = ExAllocatePoolWithTagPriority(NonPagedPool,
  151. sizeof(IPv6Packet) +
  152. BytesToCopy, TCP6_TAG,
  153. LowPoolPriority);
  154. if (NewPkt != NULL) {
  155. NewPkt->Next = NULL;
  156. NewPkt->Position = 0;
  157. NewPkt->FlatData = (uchar *)(NewPkt + 1);
  158. NewPkt->Data = NewPkt->FlatData;
  159. NewPkt->ContigSize = BytesToCopy;
  160. NewPkt->TotalSize = BytesToCopy;
  161. NewPkt->Flags = PACKET_OURS;
  162. NewPkt->NdisPacket = NULL;
  163. NewPkt->AuxList = NULL;
  164. CopyPacketToBuffer(NewPkt->Data, OrigPkt, BytesToCopy,
  165. OrigPkt->Position);
  166. EndPkt->Next = NewPkt;
  167. EndPkt = NewPkt;
  168. Size -= BytesToCopy;
  169. OrigPkt = OrigPkt->Next;
  170. } else {
  171. FreePacketChain(FirstPkt);
  172. return NULL;
  173. }
  174. }
  175. EndPkt->Next = OrigPkt;
  176. } else
  177. return NULL;
  178. } else {
  179. FirstPkt = OrigPkt;
  180. EndPkt = OrigPkt;
  181. if (Size < OrigPkt->TotalSize) {
  182. OrigPkt->TotalSize = Size;
  183. OrigPkt->ContigSize = Size;
  184. }
  185. Size -= OrigPkt->TotalSize;
  186. }
  187. //
  188. // Now walk down the chain, until we run out of Size.
  189. // At this point, Size is the bytes left to 'seize' (it may be 0),
  190. // and the sizes in packets FirstPkt...EndPkt are correct.
  191. //
  192. while (Size != 0) {
  193. EndPkt = EndPkt->Next;
  194. ASSERT(EndPkt != NULL);
  195. if (Size < EndPkt->TotalSize) {
  196. EndPkt->TotalSize = Size;
  197. EndPkt->ContigSize = Size;
  198. }
  199. Size -= EndPkt->TotalSize;
  200. }
  201. // If there's anything left in the chain, free it now.
  202. if (EndPkt->Next != NULL) {
  203. FreePacketChain(EndPkt->Next);
  204. EndPkt->Next = NULL;
  205. }
  206. *LastPkt = EndPkt;
  207. return FirstPkt;
  208. }
  209. //* PendData - Pend incoming data to a client.
  210. //
  211. // Called when we need to buffer data for a client because there's no receive
  212. // down and we can't indicate.
  213. //
  214. // The TCB lock is held throughout this procedure. If this is to be changed,
  215. // make sure consistency of tcb_pendingcnt is preserved. This routine is
  216. // always called at DPC level.
  217. //
  218. uint // Returns: Number of bytes of data taken.
  219. PendData(
  220. TCB *RcvTCB, // TCB on which to receive the data.
  221. uint RcvFlags, // TCP flags for the incoming packet.
  222. IPv6Packet *InPacket, // Input buffer of packet.
  223. uint Size) // Size in bytes of data in InPacket.
  224. {
  225. IPv6Packet *NewPkt, *LastPkt;
  226. UNREFERENCED_PARAMETER(RcvFlags);
  227. CHECK_STRUCT(RcvTCB, tcb);
  228. ASSERT(Size > 0);
  229. ASSERT(InPacket != NULL);
  230. ASSERT(RcvTCB->tcb_refcnt != 0);
  231. ASSERT(RcvTCB->tcb_fastchk & TCP_FLAG_IN_RCV);
  232. ASSERT(RcvTCB->tcb_currcv == NULL);
  233. ASSERT(RcvTCB->tcb_rcvhndlr == PendData);
  234. CheckPacketList(RcvTCB->tcb_pendhead, RcvTCB->tcb_pendingcnt);
  235. NewPkt = CovetPacketChain(InPacket, &LastPkt, Size);
  236. if (NewPkt != NULL) {
  237. //
  238. // We have a duplicate chain. Put it on the end of the pending q.
  239. //
  240. if (RcvTCB->tcb_pendhead == NULL) {
  241. RcvTCB->tcb_pendhead = NewPkt;
  242. RcvTCB->tcb_pendtail = LastPkt;
  243. } else {
  244. RcvTCB->tcb_pendtail->Next = NewPkt;
  245. RcvTCB->tcb_pendtail = LastPkt;
  246. }
  247. RcvTCB->tcb_pendingcnt += Size;
  248. } else {
  249. FreePacketChain(InPacket);
  250. Size = 0;
  251. }
  252. CheckPacketList(RcvTCB->tcb_pendhead, RcvTCB->tcb_pendingcnt);
  253. return Size;
  254. }
  255. //* BufferData - Put incoming data into client's buffer.
  256. //
  257. // Called when we believe we have a buffer into which we can put data. We put
  258. // it in there, and if we've filled the buffer or the incoming data has the
  259. // push flag set we'll mark the TCB to return the buffer. Otherwise we'll
  260. // get out and return the data later.
  261. //
  262. // In NT, this routine is called with the TCB lock held, and holds it for
  263. // the duration of the call. This is important to ensure consistency of
  264. // the tcb_pendingcnt field. If we need to change this to free the lock
  265. // partway through, make sure to take this into account. In particular,
  266. // TdiReceive zeros pendingcnt before calling this routine, and this routine
  267. // may update it. If the lock is freed in here there would be a window where
  268. // we really do have pending data, but it's not on the list or reflected in
  269. // pendingcnt. This could mess up our windowing computations, and we'd have
  270. // to be careful not to end up with more data pending than our window allows.
  271. //
  272. uint // Returns: Number of bytes of data taken.
  273. BufferData(
  274. TCB *RcvTCB, // TCB on which to receive the data.
  275. uint RcvFlags, // TCP rcv flags for the incoming packet.
  276. IPv6Packet *InPacket, // Input buffer of packet.
  277. uint Size) // Size in bytes of data in InPacket.
  278. {
  279. uchar *DestBase; // Destination pointer.
  280. uint DestOffset; // Destination offset.
  281. uint SrcSize; // Size of current source buffer.
  282. uint DestSize; // Size of current destination buffer.
  283. uint Copied; // Total bytes to copy.
  284. uint BytesToCopy; // Bytes of data to copy this time.
  285. TCPRcvReq *DestReq; // Current receive request.
  286. IPv6Packet *SrcPkt; // Current source packet.
  287. PNDIS_BUFFER DestBuf; // Current receive buffer.
  288. uint RcvCmpltd;
  289. uint Flags;
  290. CHECK_STRUCT(RcvTCB, tcb);
  291. ASSERT(Size > 0);
  292. ASSERT(InPacket != NULL);
  293. ASSERT(RcvTCB->tcb_refcnt != 0);
  294. ASSERT(RcvTCB->tcb_rcvhndlr == BufferData);
  295. Copied = 0;
  296. RcvCmpltd = 0;
  297. DestReq = RcvTCB->tcb_currcv;
  298. ASSERT(DestReq != NULL);
  299. CHECK_STRUCT(DestReq, trr);
  300. DestBuf = DestReq->trr_buffer;
  301. DestSize = MIN(NdisBufferLength(DestBuf) - DestReq->trr_offset,
  302. DestReq->trr_size - DestReq->trr_amt);
  303. DestBase = (uchar *)NdisBufferVirtualAddressSafe(DestBuf,
  304. NormalPagePriority);
  305. DestOffset = DestReq->trr_offset;
  306. SrcPkt = InPacket;
  307. SrcSize = SrcPkt->TotalSize;
  308. Flags = (RcvFlags & TCP_FLAG_PUSH) ? TRR_PUSHED : 0;
  309. RcvCmpltd = Flags;
  310. DestReq->trr_flags |= Flags;
  311. do {
  312. BytesToCopy = MIN(Size - Copied, MIN(SrcSize, DestSize));
  313. CopyPacketToFlatOrNdis(DestBuf, DestBase, DestOffset, SrcPkt,
  314. BytesToCopy, SrcPkt->Position);
  315. Copied += BytesToCopy;
  316. DestReq->trr_amt += BytesToCopy;
  317. // Update our source pointers.
  318. if ((SrcSize -= BytesToCopy) == 0) {
  319. IPv6Packet *TempPkt;
  320. // We've copied everything in this packet.
  321. TempPkt = SrcPkt;
  322. SrcPkt = SrcPkt->Next;
  323. if (Size != Copied) {
  324. ASSERT(SrcPkt != NULL);
  325. SrcSize = SrcPkt->TotalSize;
  326. }
  327. TempPkt->Next = NULL;
  328. FreePacketChain(TempPkt);
  329. } else {
  330. if (BytesToCopy < SrcPkt->ContigSize) {
  331. //
  332. // We have a contiguous region, easy to skip forward.
  333. //
  334. AdjustPacketParams(SrcPkt, BytesToCopy);
  335. } else {
  336. //
  337. // REVIEW: This method isn't very efficient.
  338. //
  339. PositionPacketAt(SrcPkt, SrcPkt->Position + BytesToCopy);
  340. }
  341. }
  342. // Now check the destination pointer, and update it if we need to.
  343. if ((DestSize -= BytesToCopy) == 0) {
  344. uint DestAvail;
  345. // Exhausted this buffer. See if there's another one.
  346. DestAvail = DestReq->trr_size - DestReq->trr_amt;
  347. DestBuf = NDIS_BUFFER_LINKAGE(DestBuf);
  348. if (DestBuf != NULL && (DestAvail != 0)) {
  349. // Have another buffer in the chain. Update things.
  350. DestSize = MIN(NdisBufferLength(DestBuf), DestAvail);
  351. DestBase = NdisBufferVirtualAddressSafe(DestBuf,
  352. NormalPagePriority);
  353. DestOffset = 0;
  354. } else {
  355. // No more buffers in the chain. See if we have another buffer
  356. // on the list.
  357. DestReq->trr_flags |= TRR_PUSHED;
  358. // If we've been told there's to be no back traffic, get an ACK
  359. // going right away.
  360. if (DestReq->trr_flags & TDI_RECEIVE_NO_RESPONSE_EXP)
  361. DelayAction(RcvTCB, NEED_ACK);
  362. RcvCmpltd = TRUE;
  363. DestReq = DestReq->trr_next;
  364. if (DestReq != NULL) {
  365. DestBuf = DestReq->trr_buffer;
  366. DestSize = MIN(NdisBufferLength(DestBuf),
  367. DestReq->trr_size);
  368. DestBase = NdisBufferVirtualAddressSafe(DestBuf,
  369. NormalPagePriority);
  370. DestOffset = 0;
  371. // If we have more to put into here, set the flags.
  372. if (Copied != Size)
  373. DestReq->trr_flags |= Flags;
  374. } else {
  375. // All out of buffer space. Reset the data handler pointer.
  376. break;
  377. }
  378. }
  379. } else {
  380. // Current buffer not empty yet.
  381. DestOffset += BytesToCopy;
  382. }
  383. // If we've copied all that we need to, we're done.
  384. } while (Copied != Size);
  385. //
  386. // We've finished copying, and have a few more things to do. We need to
  387. // update the current rcv. pointer and possibly the offset in the
  388. // recv. request. If we need to complete any receives we have to schedule
  389. // that. If there's any data we couldn't copy we'll need to dispose of it.
  390. //
  391. RcvTCB->tcb_currcv = DestReq;
  392. if (DestReq != NULL) {
  393. DestReq->trr_buffer = DestBuf;
  394. DestReq->trr_offset = DestOffset;
  395. RcvTCB->tcb_rcvhndlr = BufferData;
  396. } else
  397. RcvTCB->tcb_rcvhndlr = PendData;
  398. RcvTCB->tcb_indicated -= MIN(Copied, RcvTCB->tcb_indicated);
  399. if (Size != Copied) {
  400. IPv6Packet *NewPkt, *LastPkt;
  401. ASSERT(DestReq == NULL);
  402. // We have data to dispose of. Update the first buffer of the chain
  403. // with the current src pointer and size, and copy it.
  404. ASSERT(SrcSize <= SrcPkt->TotalSize);
  405. NewPkt = CovetPacketChain(SrcPkt, &LastPkt, Size - Copied);
  406. if (NewPkt != NULL) {
  407. // We managed to copy the chain. Push it on the pending queue.
  408. if (RcvTCB->tcb_pendhead == NULL) {
  409. RcvTCB->tcb_pendhead = NewPkt;
  410. RcvTCB->tcb_pendtail = LastPkt;
  411. } else {
  412. LastPkt->Next = RcvTCB->tcb_pendhead;
  413. RcvTCB->tcb_pendhead = NewPkt;
  414. }
  415. RcvTCB->tcb_pendingcnt += Size - Copied;
  416. Copied = Size;
  417. CheckPacketList(RcvTCB->tcb_pendhead, RcvTCB->tcb_pendingcnt);
  418. } else
  419. FreePacketChain(SrcPkt);
  420. } else {
  421. // We copied Size bytes, but the chain could be longer than that. Free
  422. // it if we need to.
  423. if (SrcPkt != NULL)
  424. FreePacketChain(SrcPkt);
  425. }
  426. if (RcvCmpltd != 0) {
  427. DelayAction(RcvTCB, NEED_RCV_CMPLT);
  428. } else {
  429. START_TCB_TIMER(RcvTCB->tcb_pushtimer, PUSH_TO);
  430. }
  431. return Copied;
  432. }
  433. //* IndicateData - Indicate incoming data to a client.
  434. //
  435. // Called when we need to indicate data to an upper layer client. We'll pass
  436. // up a pointer to whatever we have available, and the client may take some
  437. // or all of it.
  438. //
  439. uint // Returns: Number of bytes of data taken.
  440. IndicateData(
  441. TCB *RcvTCB, // TCB on which to receive the data.
  442. uint RcvFlags, // TCP receive flags for the incoming packet.
  443. IPv6Packet *InPacket, // Input buffer of packet.
  444. uint Size) // Size in bytes of data in InPacket.
  445. {
  446. TDI_STATUS Status;
  447. PRcvEvent Event;
  448. PVOID EventContext, ConnContext;
  449. uint BytesTaken = 0;
  450. EventRcvBuffer *ERB = NULL;
  451. PTDI_REQUEST_KERNEL_RECEIVE RequestInformation;
  452. PIO_STACK_LOCATION IrpSp;
  453. TCPRcvReq *RcvReq;
  454. ulong IndFlags;
  455. CHECK_STRUCT(RcvTCB, tcb);
  456. ASSERT(Size > 0);
  457. ASSERT(InPacket != NULL);
  458. ASSERT(RcvTCB->tcb_refcnt != 0);
  459. ASSERT(RcvTCB->tcb_fastchk & TCP_FLAG_IN_RCV);
  460. ASSERT(RcvTCB->tcb_rcvind != NULL);
  461. ASSERT(RcvTCB->tcb_rcvhead == NULL);
  462. ASSERT(RcvTCB->tcb_rcvhndlr == IndicateData);
  463. RcvReq = GetRcvReq();
  464. if (RcvReq != NULL) {
  465. //
  466. // The indicate handler is saved in the TCB. Just call up into it.
  467. //
  468. Event = RcvTCB->tcb_rcvind;
  469. EventContext = RcvTCB->tcb_ricontext;
  470. ConnContext = RcvTCB->tcb_conncontext;
  471. RcvTCB->tcb_indicated = Size;
  472. RcvTCB->tcb_flags |= IN_RCV_IND;
  473. //
  474. // If we're at the end of a contigous data region,
  475. // move forward to the next one. This prevents us
  476. // from making nonsensical zero byte indications.
  477. //
  478. if (InPacket->ContigSize == 0) {
  479. PacketPullupSubr(InPacket, 0, 1, 0);
  480. }
  481. IF_TCPDBG(TCP_DEBUG_RECEIVE) {
  482. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_TCPDBG,
  483. "Indicating %lu bytes, %lu available\n",
  484. MIN(InPacket->ContigSize, Size), Size));
  485. }
  486. #if TCP_FLAG_PUSH >= TDI_RECEIVE_ENTIRE_MESSAGE
  487. IndFlags = TDI_RECEIVE_COPY_LOOKAHEAD | TDI_RECEIVE_NORMAL |
  488. TDI_RECEIVE_AT_DISPATCH_LEVEL |
  489. ((RcvFlags & TCP_FLAG_PUSH) >>
  490. ((TCP_FLAG_PUSH / TDI_RECEIVE_ENTIRE_MESSAGE) - 1));
  491. #else
  492. IndFlags = TDI_RECEIVE_COPY_LOOKAHEAD | TDI_RECEIVE_NORMAL |
  493. TDI_RECEIVE_AT_DISPATCH_LEVEL |
  494. ((RcvFlags & TCP_FLAG_PUSH) <<
  495. ((TDI_RECEIVE_ENTIRE_MESSAGE / TCP_FLAG_PUSH) - 1));
  496. #endif
  497. if ((RcvTCB->tcb_flags & DISC_NOTIFIED) ||
  498. (RcvTCB->tcb_pending & RST_PENDING)) {
  499. KeReleaseSpinLockFromDpcLevel(&RcvTCB->tcb_lock);
  500. Status = TDI_NOT_ACCEPTED;
  501. } else {
  502. KeReleaseSpinLockFromDpcLevel(&RcvTCB->tcb_lock);
  503. Status = (*Event)(EventContext, ConnContext, IndFlags,
  504. MIN(InPacket->ContigSize, Size), Size,
  505. (PULONG)&BytesTaken, InPacket->Data, &ERB);
  506. }
  507. IF_TCPDBG(TCP_DEBUG_RECEIVE) {
  508. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_TCPDBG,
  509. "%lu bytes taken, status %lx\n", BytesTaken, Status));
  510. }
  511. //
  512. // See what the client did. If the return status is MORE_PROCESSING,
  513. // we've been given a buffer. In that case put it on the front of the
  514. // buffer queue, and if all the data wasn't taken go ahead and copy
  515. // it into the new buffer chain.
  516. //
  517. // Note that the size and buffer chain we're concerned with here is
  518. // the one that we passed to the client. Since we're in a recieve
  519. // handler, any data that has come in would have been put on the
  520. // reassembly queue.
  521. //
  522. if (Status == TDI_MORE_PROCESSING) {
  523. ASSERT(ERB != NULL);
  524. IrpSp = IoGetCurrentIrpStackLocation(ERB);
  525. Status = TCPPrepareIrpForCancel(
  526. (PTCP_CONTEXT) IrpSp->FileObject->FsContext, ERB,
  527. TCPCancelRequest);
  528. if (NT_SUCCESS(Status)) {
  529. RequestInformation = (PTDI_REQUEST_KERNEL_RECEIVE)
  530. &(IrpSp->Parameters);
  531. RcvReq->trr_rtn = TCPDataRequestComplete;
  532. RcvReq->trr_context = ERB;
  533. RcvReq->trr_buffer = ERB->MdlAddress;
  534. RcvReq->trr_size = RequestInformation->ReceiveLength;
  535. RcvReq->trr_uflags = (ushort *)
  536. &(RequestInformation->ReceiveFlags);
  537. RcvReq->trr_flags = (uint)(RequestInformation->ReceiveFlags);
  538. RcvReq->trr_offset = 0;
  539. RcvReq->trr_amt = 0;
  540. KeAcquireSpinLockAtDpcLevel(&RcvTCB->tcb_lock);
  541. RcvTCB->tcb_flags &= ~IN_RCV_IND;
  542. ASSERT(RcvTCB->tcb_rcvhndlr == IndicateData);
  543. // Push him on the front of the rcv. queue.
  544. ASSERT((RcvTCB->tcb_currcv == NULL) ||
  545. (RcvTCB->tcb_currcv->trr_amt == 0));
  546. if (RcvTCB->tcb_rcvhead == NULL) {
  547. RcvTCB->tcb_rcvhead = RcvReq;
  548. RcvTCB->tcb_rcvtail = RcvReq;
  549. RcvReq->trr_next = NULL;
  550. } else {
  551. RcvReq->trr_next = RcvTCB->tcb_rcvhead;
  552. RcvTCB->tcb_rcvhead = RcvReq;
  553. }
  554. RcvTCB->tcb_currcv = RcvReq;
  555. RcvTCB->tcb_rcvhndlr = BufferData;
  556. ASSERT(BytesTaken <= Size);
  557. RcvTCB->tcb_indicated -= BytesTaken;
  558. if ((Size -= BytesTaken) != 0) {
  559. //
  560. // Not everything was taken.
  561. // Adjust the buffer chain to point beyond what was taken.
  562. //
  563. InPacket = TrimPacket(InPacket, BytesTaken);
  564. ASSERT(InPacket != NULL);
  565. //
  566. // We've adjusted the buffer chain.
  567. // Call the BufferData handler.
  568. //
  569. BytesTaken += BufferData(RcvTCB, RcvFlags, InPacket, Size);
  570. } else {
  571. // All of the data was taken. Free the buffer chain.
  572. FreePacketChain(InPacket);
  573. }
  574. return BytesTaken;
  575. } else {
  576. //
  577. // The IRP was cancelled before it was handed back to us.
  578. // We'll pretend we never saw it. TCPPrepareIrpForCancel
  579. // already completed it. The client may have taken data,
  580. // so we will act as if success was returned.
  581. //
  582. ERB = NULL;
  583. Status = TDI_SUCCESS;
  584. }
  585. }
  586. KeAcquireSpinLockAtDpcLevel(&RcvTCB->tcb_lock);
  587. RcvTCB->tcb_flags &= ~IN_RCV_IND;
  588. //
  589. // Status is not more processing. If it's not SUCCESS, the client
  590. // didn't take any of the data. In either case we now need to
  591. // see if all of the data was taken. If it wasn't, we'll try and
  592. // push it onto the front of the pending queue.
  593. //
  594. FreeRcvReq(RcvReq); // This won't be needed.
  595. if (Status == TDI_NOT_ACCEPTED)
  596. BytesTaken = 0;
  597. ASSERT(BytesTaken <= Size);
  598. RcvTCB->tcb_indicated -= BytesTaken;
  599. ASSERT(RcvTCB->tcb_rcvhndlr == IndicateData);
  600. // Check to see if a rcv. buffer got posted during the indication.
  601. // If it did, reset the receive handler now.
  602. if (RcvTCB->tcb_rcvhead != NULL) {
  603. RcvTCB->tcb_rcvhndlr = BufferData;
  604. } else if (RcvTCB->tcb_rcvind == NULL) {
  605. RcvTCB->tcb_rcvhndlr = PendData;
  606. }
  607. // See if all of the data was taken.
  608. if (BytesTaken == Size) {
  609. ASSERT(RcvTCB->tcb_indicated == 0);
  610. FreePacketChain(InPacket);
  611. return BytesTaken; // It was all taken.
  612. }
  613. //
  614. // It wasn't all taken. Adjust for what was taken, and push
  615. // on the front of the pending queue. We also need to check to
  616. // see if a receive buffer got posted during the indication. This
  617. // would be weird, but not impossible.
  618. //
  619. InPacket = TrimPacket(InPacket, BytesTaken);
  620. if (RcvTCB->tcb_rcvhead == NULL) {
  621. IPv6Packet *LastPkt, *NewPkt;
  622. RcvTCB->tcb_rcvhndlr = PendData;
  623. NewPkt = CovetPacketChain(InPacket, &LastPkt, Size - BytesTaken);
  624. if (NewPkt != NULL) {
  625. // We have a duplicate chain. Push it on the front of the
  626. // pending q.
  627. if (RcvTCB->tcb_pendhead == NULL) {
  628. RcvTCB->tcb_pendhead = NewPkt;
  629. RcvTCB->tcb_pendtail = LastPkt;
  630. } else {
  631. LastPkt->Next = RcvTCB->tcb_pendhead;
  632. RcvTCB->tcb_pendhead = NewPkt;
  633. }
  634. RcvTCB->tcb_pendingcnt += Size - BytesTaken;
  635. BytesTaken = Size;
  636. } else {
  637. FreePacketChain(InPacket);
  638. }
  639. return BytesTaken;
  640. } else {
  641. //
  642. // Just great. There's now a receive buffer on the TCB.
  643. // Call the BufferData handler now.
  644. //
  645. ASSERT(RcvTCB->tcb_rcvhndlr == BufferData);
  646. BytesTaken += BufferData(RcvTCB, RcvFlags, InPacket,
  647. Size - BytesTaken);
  648. return BytesTaken;
  649. }
  650. } else {
  651. //
  652. // Couldn't get a receive request. We must be really low on resources,
  653. // so just bail out now.
  654. //
  655. FreePacketChain(InPacket);
  656. return 0;
  657. }
  658. }
  659. //* IndicatePendingData - Indicate pending data to a client.
  660. //
  661. // Called when we need to indicate pending data to an upper layer client,
  662. // usually because data arrived when we were in a state that it couldn't
  663. // be indicated.
  664. //
  665. // Many of the comments in the BufferData header about the consistency of
  666. // tcb_pendingcnt apply here also.
  667. //
  668. void // Returns: Nothing.
  669. IndicatePendingData(
  670. TCB *RcvTCB, // TCB on which to indicate the data.
  671. TCPRcvReq *RcvReq, // Receive request to use to indicate it.
  672. KIRQL PreLockIrql) // IRQL prior to acquiring TCB lock.
  673. {
  674. TDI_STATUS Status;
  675. PRcvEvent Event;
  676. PVOID EventContext, ConnContext;
  677. uint BytesTaken = 0;
  678. EventRcvBuffer *ERB = NULL;
  679. PTDI_REQUEST_KERNEL_RECEIVE RequestInformation;
  680. PIO_STACK_LOCATION IrpSp;
  681. IPv6Packet *NewPkt;
  682. uint Size;
  683. uint BytesIndicated;
  684. uint BytesAvailable;
  685. uchar* DataBuffer;
  686. CHECK_STRUCT(RcvTCB, tcb);
  687. ASSERT(RcvTCB->tcb_refcnt != 0);
  688. ASSERT(RcvTCB->tcb_rcvind != NULL);
  689. ASSERT(RcvTCB->tcb_rcvhead == NULL);
  690. ASSERT(RcvTCB->tcb_pendingcnt != 0);
  691. ASSERT(RcvReq != NULL);
  692. for (;;) {
  693. ASSERT(RcvTCB->tcb_rcvhndlr == PendData);
  694. // The indicate handler is saved in the TCB. Just call up into it.
  695. Event = RcvTCB->tcb_rcvind;
  696. EventContext = RcvTCB->tcb_ricontext;
  697. ConnContext = RcvTCB->tcb_conncontext;
  698. BytesIndicated = RcvTCB->tcb_pendhead->ContigSize;
  699. BytesAvailable = RcvTCB->tcb_pendingcnt;
  700. DataBuffer = RcvTCB->tcb_pendhead->Data;
  701. RcvTCB->tcb_indicated = RcvTCB->tcb_pendingcnt;
  702. RcvTCB->tcb_flags |= IN_RCV_IND;
  703. if ((RcvTCB->tcb_flags & DISC_NOTIFIED) ||
  704. (RcvTCB->tcb_pending & RST_PENDING)) {
  705. KeReleaseSpinLock(&RcvTCB->tcb_lock, PreLockIrql);
  706. Status = TDI_NOT_ACCEPTED;
  707. BytesTaken = 0;
  708. } else {
  709. KeReleaseSpinLock(&RcvTCB->tcb_lock, PreLockIrql);
  710. IF_TCPDBG(TCPDebug & TCP_DEBUG_RECEIVE) {
  711. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_TCPDBG,
  712. "Indicating pending %d bytes, %d available\n",
  713. BytesIndicated,
  714. BytesAvailable));
  715. }
  716. Status = (*Event)(EventContext, ConnContext,
  717. TDI_RECEIVE_COPY_LOOKAHEAD | TDI_RECEIVE_NORMAL |
  718. TDI_RECEIVE_ENTIRE_MESSAGE,
  719. BytesIndicated, BytesAvailable,
  720. (PULONG)&BytesTaken, DataBuffer, &ERB);
  721. IF_TCPDBG(TCPDebug & TCP_DEBUG_RECEIVE) {
  722. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_TCPDBG,
  723. "%d bytes taken\n", BytesTaken));
  724. }
  725. }
  726. //
  727. // See what the client did. If the return status is MORE_PROCESSING,
  728. // we've been given a buffer. In that case put it on the front of the
  729. // buffer queue, and if all the data wasn't taken go ahead and copy
  730. // it into the new buffer chain.
  731. //
  732. if (Status == TDI_MORE_PROCESSING) {
  733. IF_TCPDBG(TCP_DEBUG_RECEIVE) {
  734. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_TCPDBG,
  735. "more processing on receive\n"));
  736. }
  737. ASSERT(ERB != NULL);
  738. IrpSp = IoGetCurrentIrpStackLocation(ERB);
  739. Status = TCPPrepareIrpForCancel(
  740. (PTCP_CONTEXT) IrpSp->FileObject->FsContext, ERB,
  741. TCPCancelRequest);
  742. if (NT_SUCCESS(Status)) {
  743. RequestInformation = (PTDI_REQUEST_KERNEL_RECEIVE)
  744. &(IrpSp->Parameters);
  745. RcvReq->trr_rtn = TCPDataRequestComplete;
  746. RcvReq->trr_context = ERB;
  747. RcvReq->trr_buffer = ERB->MdlAddress;
  748. RcvReq->trr_size = RequestInformation->ReceiveLength;
  749. RcvReq->trr_uflags = (ushort *)
  750. &(RequestInformation->ReceiveFlags);
  751. RcvReq->trr_flags = (uint)(RequestInformation->ReceiveFlags);
  752. RcvReq->trr_offset = 0;
  753. RcvReq->trr_amt = 0;
  754. KeAcquireSpinLock(&RcvTCB->tcb_lock, &PreLockIrql);
  755. RcvTCB->tcb_flags &= ~IN_RCV_IND;
  756. // Push him on the front of the receive queue.
  757. ASSERT((RcvTCB->tcb_currcv == NULL) ||
  758. (RcvTCB->tcb_currcv->trr_amt == 0));
  759. if (RcvTCB->tcb_rcvhead == NULL) {
  760. RcvTCB->tcb_rcvhead = RcvReq;
  761. RcvTCB->tcb_rcvtail = RcvReq;
  762. RcvReq->trr_next = NULL;
  763. } else {
  764. RcvReq->trr_next = RcvTCB->tcb_rcvhead;
  765. RcvTCB->tcb_rcvhead = RcvReq;
  766. }
  767. RcvTCB->tcb_currcv = RcvReq;
  768. RcvTCB->tcb_rcvhndlr = BufferData;
  769. //
  770. // Have to pick up the new size and pointers now, since things
  771. // could have changed during the upcall.
  772. //
  773. Size = RcvTCB->tcb_pendingcnt;
  774. NewPkt = RcvTCB->tcb_pendhead;
  775. RcvTCB->tcb_pendingcnt = 0;
  776. RcvTCB->tcb_pendhead = NULL;
  777. ASSERT(BytesTaken <= Size);
  778. RcvTCB->tcb_indicated -= BytesTaken;
  779. if ((Size -= BytesTaken) != 0) {
  780. //
  781. // Not everything was taken. Adjust the buffer chain to
  782. // point beyond what was taken.
  783. //
  784. NewPkt = TrimPacket(NewPkt, BytesTaken);
  785. ASSERT(NewPkt != NULL);
  786. //
  787. // We've adjusted the buffer chain.
  788. // Call the BufferData handler.
  789. //
  790. (void)BufferData(RcvTCB, TCP_FLAG_PUSH, NewPkt, Size);
  791. KeReleaseSpinLock(&RcvTCB->tcb_lock, PreLockIrql);
  792. } else {
  793. //
  794. // All of the data was taken. Free the buffer chain.
  795. // Since we were passed a buffer chain which we put on the
  796. // head of the list, leave the rcvhandler pointing at
  797. // BufferData.
  798. //
  799. ASSERT(RcvTCB->tcb_rcvhndlr == BufferData);
  800. ASSERT(RcvTCB->tcb_indicated == 0);
  801. ASSERT(RcvTCB->tcb_rcvhead != NULL);
  802. KeReleaseSpinLock(&RcvTCB->tcb_lock, PreLockIrql);
  803. FreePacketChain(NewPkt);
  804. }
  805. return;
  806. } else {
  807. //
  808. // The IRP was cancelled before it was handed back to us.
  809. // We'll pretend we never saw it. TCPPrepareIrpForCancel
  810. // already completed it. The client may have taken data,
  811. // so we will act as if success was returned.
  812. //
  813. ERB = NULL;
  814. Status = TDI_SUCCESS;
  815. }
  816. }
  817. KeAcquireSpinLock(&RcvTCB->tcb_lock, &PreLockIrql);
  818. RcvTCB->tcb_flags &= ~IN_RCV_IND;
  819. //
  820. // Status is not more processing. If it's not SUCCESS, the client
  821. // didn't take any of the data. In either case we now need to
  822. // see if all of the data was taken. If it wasn't, we're done.
  823. //
  824. if (Status == TDI_NOT_ACCEPTED)
  825. BytesTaken = 0;
  826. ASSERT(RcvTCB->tcb_rcvhndlr == PendData);
  827. RcvTCB->tcb_indicated -= BytesTaken;
  828. Size = RcvTCB->tcb_pendingcnt;
  829. NewPkt = RcvTCB->tcb_pendhead;
  830. ASSERT(BytesTaken <= Size);
  831. // See if all of the data was taken.
  832. if (BytesTaken == Size) {
  833. // It was all taken. Zap the pending data information.
  834. RcvTCB->tcb_pendingcnt = 0;
  835. RcvTCB->tcb_pendhead = NULL;
  836. ASSERT(RcvTCB->tcb_indicated == 0);
  837. if (RcvTCB->tcb_rcvhead == NULL) {
  838. if (RcvTCB->tcb_rcvind != NULL)
  839. RcvTCB->tcb_rcvhndlr = IndicateData;
  840. } else
  841. RcvTCB->tcb_rcvhndlr = BufferData;
  842. KeReleaseSpinLock(&RcvTCB->tcb_lock, PreLockIrql);
  843. FreePacketChain(NewPkt);
  844. break;
  845. }
  846. //
  847. // It wasn't all taken. Adjust for what was taken; we also need to
  848. // check to see if a receive buffer got posted during the indication.
  849. // This would be weird, but not impossible.
  850. //
  851. NewPkt = TrimPacket(NewPkt, BytesTaken);
  852. ASSERT(RcvTCB->tcb_rcvhndlr == PendData);
  853. if (RcvTCB->tcb_rcvhead == NULL) {
  854. RcvTCB->tcb_pendhead = NewPkt;
  855. RcvTCB->tcb_pendingcnt -= BytesTaken;
  856. if (RcvTCB->tcb_indicated != 0 || RcvTCB->tcb_rcvind == NULL) {
  857. KeReleaseSpinLock(&RcvTCB->tcb_lock, PreLockIrql);
  858. break;
  859. }
  860. // From here, we'll loop around and indicate the new data that
  861. // presumably came in during the previous indication.
  862. } else {
  863. //
  864. // Just great. There's now a receive buffer on the TCB.
  865. // Call the BufferData handler now.
  866. //
  867. RcvTCB->tcb_rcvhndlr = BufferData;
  868. RcvTCB->tcb_pendingcnt = 0;
  869. RcvTCB->tcb_pendhead = NULL;
  870. BytesTaken += BufferData(RcvTCB, TCP_FLAG_PUSH, NewPkt,
  871. Size - BytesTaken);
  872. KeReleaseSpinLock(&RcvTCB->tcb_lock, PreLockIrql);
  873. break;
  874. }
  875. } // for (;;)
  876. FreeRcvReq(RcvReq); // This isn't needed anymore.
  877. }
  878. //* DeliverUrgent - Deliver urgent data to a client.
  879. //
  880. // Called to deliver urgent data to a client. We assume the input
  881. // urgent data is in a buffer we can keep. The buffer can be NULL, in
  882. // which case we'll just look on the urgent pending queue for data.
  883. //
  884. void // Returns: Nothing.
  885. DeliverUrgent(
  886. TCB *RcvTCB, // TCB to deliver on.
  887. IPv6Packet *RcvPkt, // Packet for urgent data.
  888. uint Size, // Number of bytes of urgent data to deliver.
  889. KIRQL *pTCBIrql) // Location of KIRQL prior to acquiring TCB lock.
  890. {
  891. KIRQL Irql1, Irql2, Irql3; // One per lock nesting level.
  892. TCPRcvReq *RcvReq, *PrevReq;
  893. uint BytesTaken = 0;
  894. IPv6Packet *LastPkt;
  895. EventRcvBuffer *ERB;
  896. PRcvEvent ExpRcv;
  897. PVOID ExpRcvContext;
  898. PVOID ConnContext;
  899. TDI_STATUS Status;
  900. CHECK_STRUCT(RcvTCB, tcb);
  901. ASSERT(RcvTCB->tcb_refcnt != 0);
  902. CheckPacketList(RcvTCB->tcb_urgpending, RcvTCB->tcb_urgcnt);
  903. //
  904. // See if we have new data, or are processing old data.
  905. //
  906. if (RcvPkt != NULL) {
  907. //
  908. // We have new data. If the pending queue is not NULL, or we're
  909. // already in this routine, just put the buffer on the end of the
  910. // queue.
  911. //
  912. if (RcvTCB->tcb_urgpending != NULL ||
  913. (RcvTCB->tcb_flags & IN_DELIV_URG)) {
  914. IPv6Packet *PrevRcvPkt;
  915. // Put him on the end of the queue.
  916. PrevRcvPkt = CONTAINING_RECORD(&RcvTCB->tcb_urgpending, IPv6Packet,
  917. Next);
  918. while (PrevRcvPkt->Next != NULL)
  919. PrevRcvPkt = PrevRcvPkt->Next;
  920. PrevRcvPkt->Next = RcvPkt;
  921. RcvTCB->tcb_urgcnt += Size;
  922. return;
  923. }
  924. } else {
  925. //
  926. // The input buffer is NULL. See if we have existing data, or are in
  927. // this routine. If we have no existing data or are in this routine
  928. // just return.
  929. //
  930. if (RcvTCB->tcb_urgpending == NULL ||
  931. (RcvTCB->tcb_flags & IN_DELIV_URG)) {
  932. return;
  933. } else {
  934. RcvPkt = RcvTCB->tcb_urgpending;
  935. Size = RcvTCB->tcb_urgcnt;
  936. RcvTCB->tcb_urgpending = NULL;
  937. RcvTCB->tcb_urgcnt = 0;
  938. }
  939. }
  940. ASSERT(RcvPkt != NULL);
  941. ASSERT(!(RcvTCB->tcb_flags & IN_DELIV_URG));
  942. //
  943. // We know we have data to deliver, and we have a pointer and a size.
  944. // Go into a loop, trying to deliver the data. On each iteration, we'll
  945. // try to find a buffer for the data. If we find one, we'll copy and
  946. // complete it right away. Otherwise we'll try and indicate it. If we
  947. // can't indicate it, we'll put it on the pending queue and leave.
  948. //
  949. RcvTCB->tcb_flags |= IN_DELIV_URG;
  950. RcvTCB->tcb_slowcount++;
  951. RcvTCB->tcb_fastchk |= TCP_FLAG_SLOW;
  952. CheckTCBRcv(RcvTCB);
  953. do {
  954. CheckPacketList(RcvTCB->tcb_urgpending, RcvTCB->tcb_urgcnt);
  955. BytesTaken = 0;
  956. // First check the expedited queue.
  957. if ((RcvReq = RcvTCB->tcb_exprcv) != NULL)
  958. RcvTCB->tcb_exprcv = RcvReq->trr_next;
  959. else {
  960. //
  961. // Nothing in the expedited receive queue. Walk down the ordinary
  962. // receive queue, looking for a buffer that we can steal.
  963. //
  964. PrevReq = CONTAINING_RECORD(&RcvTCB->tcb_rcvhead, TCPRcvReq,
  965. trr_next);
  966. RcvReq = PrevReq->trr_next;
  967. while (RcvReq != NULL) {
  968. CHECK_STRUCT(RcvReq, trr);
  969. if (RcvReq->trr_flags & TDI_RECEIVE_EXPEDITED) {
  970. // This is a candidate.
  971. if (RcvReq->trr_amt == 0) {
  972. ASSERT(RcvTCB->tcb_rcvhndlr == BufferData);
  973. //
  974. // And he has nothing currently in him.
  975. // Pull him out of the queue.
  976. //
  977. if (RcvTCB->tcb_rcvtail == RcvReq) {
  978. if (RcvTCB->tcb_rcvhead == RcvReq)
  979. RcvTCB->tcb_rcvtail = NULL;
  980. else
  981. RcvTCB->tcb_rcvtail = PrevReq;
  982. }
  983. PrevReq->trr_next = RcvReq->trr_next;
  984. if (RcvTCB->tcb_currcv == RcvReq) {
  985. RcvTCB->tcb_currcv = RcvReq->trr_next;
  986. if (RcvTCB->tcb_currcv == NULL) {
  987. //
  988. // We've taken the last receive from the list.
  989. // Reset the rcvhndlr.
  990. //
  991. if (RcvTCB->tcb_rcvind != NULL &&
  992. RcvTCB->tcb_indicated == 0)
  993. RcvTCB->tcb_rcvhndlr = IndicateData;
  994. else
  995. RcvTCB->tcb_rcvhndlr = PendData;
  996. }
  997. }
  998. break;
  999. }
  1000. }
  1001. PrevReq = RcvReq;
  1002. RcvReq = PrevReq->trr_next;
  1003. }
  1004. }
  1005. //
  1006. // We've done our best to get a buffer. If we got one, copy into it
  1007. // now, and complete the request.
  1008. //
  1009. if (RcvReq != NULL) {
  1010. // Got a buffer.
  1011. KeReleaseSpinLock(&RcvTCB->tcb_lock, *pTCBIrql);
  1012. BytesTaken = CopyPacketToNdis(RcvReq->trr_buffer, RcvPkt,
  1013. Size, 0, RcvPkt->Position);
  1014. (*RcvReq->trr_rtn)(RcvReq->trr_context, TDI_SUCCESS, BytesTaken);
  1015. FreeRcvReq(RcvReq);
  1016. KeAcquireSpinLock(&RcvTCB->tcb_lock, pTCBIrql);
  1017. RcvTCB->tcb_urgind -= MIN(RcvTCB->tcb_urgind, BytesTaken);
  1018. } else {
  1019. // No posted buffer. If we can indicate, do so.
  1020. if (RcvTCB->tcb_urgind == 0) {
  1021. TCPConn *Conn;
  1022. // See if he has an expedited rcv handler.
  1023. ConnContext = RcvTCB->tcb_conncontext;
  1024. KeReleaseSpinLock(&RcvTCB->tcb_lock, *pTCBIrql);
  1025. KeAcquireSpinLock(&AddrObjTableLock, &Irql1);
  1026. KeAcquireSpinLock(
  1027. &ConnTable[CONN_BLOCKID(RcvTCB->tcb_connid)]->cb_lock,
  1028. &Irql2);
  1029. KeAcquireSpinLock(&RcvTCB->tcb_lock, pTCBIrql);
  1030. if ((Conn = RcvTCB->tcb_conn) != NULL) {
  1031. CHECK_STRUCT(Conn, tc);
  1032. ASSERT(Conn->tc_tcb == RcvTCB);
  1033. if ((RcvTCB->tcb_flags & DISC_NOTIFIED) ||
  1034. (RcvTCB->tcb_pending & RST_PENDING)) {
  1035. Status = TDI_NOT_ACCEPTED;
  1036. } else {
  1037. Status = TDI_SUCCESS;
  1038. }
  1039. KeReleaseSpinLock(&RcvTCB->tcb_lock, *pTCBIrql);
  1040. if (Conn->tc_ao != NULL) {
  1041. AddrObj *AO;
  1042. AO = Conn->tc_ao;
  1043. KeAcquireSpinLock(&AO->ao_lock, &Irql3);
  1044. if (AO_VALID(AO) && (ExpRcv = AO->ao_exprcv) != NULL) {
  1045. ExpRcvContext = AO->ao_exprcvcontext;
  1046. KeReleaseSpinLock(&AO->ao_lock, Irql3);
  1047. // We're going to indicate.
  1048. RcvTCB->tcb_urgind = Size;
  1049. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock,
  1050. Irql2);
  1051. KeReleaseSpinLock(&AddrObjTableLock, Irql1);
  1052. if (Status != TDI_NOT_ACCEPTED) {
  1053. Status = (*ExpRcv)(ExpRcvContext, ConnContext,
  1054. TDI_RECEIVE_COPY_LOOKAHEAD |
  1055. TDI_RECEIVE_ENTIRE_MESSAGE |
  1056. TDI_RECEIVE_EXPEDITED,
  1057. MIN(RcvPkt->ContigSize,
  1058. Size),
  1059. Size, (PULONG)&BytesTaken,
  1060. RcvPkt->Data, &ERB);
  1061. }
  1062. KeAcquireSpinLock(&RcvTCB->tcb_lock, pTCBIrql);
  1063. // See what he did with it.
  1064. if (Status == TDI_MORE_PROCESSING) {
  1065. uint CopySize;
  1066. // He gave us a buffer.
  1067. if (BytesTaken == Size) {
  1068. //
  1069. // He gave us a buffer, but took all of
  1070. // it. We'll just return it to him.
  1071. //
  1072. CopySize = 0;
  1073. } else {
  1074. // We have some data to copy in.
  1075. RcvPkt = TrimPacket(RcvPkt, BytesTaken);
  1076. ASSERT(RcvPkt->TotalSize != 0);
  1077. CopySize = CopyPacketToNdis(
  1078. ERB->MdlAddress, RcvPkt,
  1079. MIN(Size - BytesTaken,
  1080. TCPGetMdlChainByteCount(
  1081. ERB->MdlAddress)), 0,
  1082. RcvPkt->Position);
  1083. }
  1084. BytesTaken += CopySize;
  1085. RcvTCB->tcb_urgind -= MIN(RcvTCB->tcb_urgind,
  1086. BytesTaken);
  1087. KeReleaseSpinLock(&RcvTCB->tcb_lock,
  1088. *pTCBIrql);
  1089. ERB->IoStatus.Status = TDI_SUCCESS;
  1090. ERB->IoStatus.Information = CopySize;
  1091. IoCompleteRequest(ERB, 2);
  1092. KeAcquireSpinLock(&RcvTCB->tcb_lock, pTCBIrql);
  1093. } else {
  1094. // No buffer to deal with.
  1095. if (Status == TDI_NOT_ACCEPTED)
  1096. BytesTaken = 0;
  1097. RcvTCB->tcb_urgind -= MIN(RcvTCB->tcb_urgind,
  1098. BytesTaken);
  1099. }
  1100. goto checksize;
  1101. } else {
  1102. // No receive handler.
  1103. KeReleaseSpinLock(&AO->ao_lock, Irql3);
  1104. }
  1105. }
  1106. // Conn->tc_ao == NULL.
  1107. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, Irql2);
  1108. KeReleaseSpinLock(&AddrObjTableLock, Irql1);
  1109. KeAcquireSpinLock(&RcvTCB->tcb_lock, pTCBIrql);
  1110. } else {
  1111. // RcvTCB has invalid index.
  1112. KeReleaseSpinLock(
  1113. &ConnTable[CONN_BLOCKID(RcvTCB->tcb_connid)]->cb_lock,
  1114. *pTCBIrql);
  1115. KeReleaseSpinLock(&AddrObjTableLock, Irql2);
  1116. *pTCBIrql = Irql1;
  1117. }
  1118. }
  1119. //
  1120. // For whatever reason we couldn't indicate the data. At this
  1121. // point we hold the lock on the TCB. Push the buffer onto the
  1122. // pending queue and return.
  1123. //
  1124. CheckPacketList(RcvTCB->tcb_urgpending, RcvTCB->tcb_urgcnt);
  1125. LastPkt = FindLastPacket(RcvPkt);
  1126. LastPkt->Next = RcvTCB->tcb_urgpending;
  1127. RcvTCB->tcb_urgpending = RcvPkt;
  1128. RcvTCB->tcb_urgcnt += Size;
  1129. break;
  1130. }
  1131. checksize:
  1132. //
  1133. // See how much we took. If we took it all, check the pending queue.
  1134. // At this point, we should hold the lock on the TCB.
  1135. //
  1136. if (Size == BytesTaken) {
  1137. // Took it all.
  1138. FreePacketChain(RcvPkt);
  1139. RcvPkt = RcvTCB->tcb_urgpending;
  1140. Size = RcvTCB->tcb_urgcnt;
  1141. } else {
  1142. //
  1143. // We didn't manage to take it all. Free what we did take,
  1144. // and then merge with the pending queue.
  1145. //
  1146. RcvPkt = TrimPacket(RcvPkt, BytesTaken);
  1147. Size = Size - BytesTaken + RcvTCB->tcb_urgcnt;
  1148. if (RcvTCB->tcb_urgpending != NULL) {
  1149. //
  1150. // Find the end of the current Packet chain, so we can merge.
  1151. //
  1152. LastPkt = FindLastPacket(RcvPkt);
  1153. LastPkt->Next = RcvTCB->tcb_urgpending;
  1154. }
  1155. }
  1156. RcvTCB->tcb_urgpending = NULL;
  1157. RcvTCB->tcb_urgcnt = 0;
  1158. } while (RcvPkt != NULL);
  1159. CheckPacketList(RcvTCB->tcb_urgpending, RcvTCB->tcb_urgcnt);
  1160. RcvTCB->tcb_flags &= ~IN_DELIV_URG;
  1161. if (--(RcvTCB->tcb_slowcount) == 0) {
  1162. RcvTCB->tcb_fastchk &= ~TCP_FLAG_SLOW;
  1163. CheckTCBRcv(RcvTCB);
  1164. }
  1165. }
  1166. //* PushData - Push all data back to the client.
  1167. //
  1168. // Called when we've received a FIN and need to push data to the client.
  1169. //
  1170. void // Returns: Nothing.
  1171. PushData(
  1172. TCB *PushTCB) // TCB to be pushed.
  1173. {
  1174. TCPRcvReq *RcvReq;
  1175. CHECK_STRUCT(PushTCB, tcb);
  1176. RcvReq = PushTCB->tcb_rcvhead;
  1177. while (RcvReq != NULL) {
  1178. CHECK_STRUCT(RcvReq, trr);
  1179. RcvReq->trr_flags |= TRR_PUSHED;
  1180. RcvReq = RcvReq->trr_next;
  1181. }
  1182. RcvReq = PushTCB->tcb_exprcv;
  1183. while (RcvReq != NULL) {
  1184. CHECK_STRUCT(RcvReq, trr);
  1185. RcvReq->trr_flags |= TRR_PUSHED;
  1186. RcvReq = RcvReq->trr_next;
  1187. }
  1188. if (PushTCB->tcb_rcvhead != NULL || PushTCB->tcb_exprcv != NULL)
  1189. DelayAction(PushTCB, NEED_RCV_CMPLT);
  1190. }
  1191. //* SplitPacket - Split an IPv6Packet into three pieces.
  1192. //
  1193. // This function takes an input IPv6Packet and splits it into three pieces.
  1194. // The first piece is the input buffer, which we just skip over. The second
  1195. // and third pieces are actually copied, even if we already own them, so
  1196. // that they may go to different places.
  1197. //
  1198. // Note: *SecondBuf and *ThirdBuf are set to NULL if we can't allocate
  1199. // memory for them.
  1200. //
  1201. void // Returns: Nothing.
  1202. SplitPacket(
  1203. IPv6Packet *Packet, // Packet chain to be split.
  1204. uint Size, // Total size in bytes of packet chain.
  1205. uint Offset, // Offset to skip over.
  1206. uint SecondSize, // Size in bytes of second piece.
  1207. IPv6Packet **SecondPkt, // Where to return second packet pointer.
  1208. IPv6Packet **ThirdPkt) // Where to return third packet pointer.
  1209. {
  1210. IPv6Packet *Temp;
  1211. uint ThirdSize;
  1212. ASSERT(Offset < Size);
  1213. ASSERT(((Offset + SecondSize) < Size) ||
  1214. (((Offset + SecondSize) == Size) && ThirdPkt == NULL));
  1215. ASSERT(Packet != NULL);
  1216. //
  1217. // Packet points at the packet to copy from, and Offset is the offset into
  1218. // this packet to copy from.
  1219. //
  1220. if (SecondPkt != NULL) {
  1221. //
  1222. // We need to allocate memory for a second packet.
  1223. //
  1224. Temp = ExAllocatePoolWithTagPriority(NonPagedPool,
  1225. sizeof(IPv6Packet) + SecondSize,
  1226. TCP6_TAG, LowPoolPriority);
  1227. if (Temp != NULL) {
  1228. Temp->Next = NULL;
  1229. Temp->Position = 0;
  1230. Temp->FlatData = (uchar *)(Temp + 1);
  1231. Temp->Data = Temp->FlatData;
  1232. Temp->ContigSize = SecondSize;
  1233. Temp->TotalSize = SecondSize;
  1234. Temp->NdisPacket = NULL;
  1235. Temp->AuxList = NULL;
  1236. Temp->Flags = PACKET_OURS;
  1237. CopyPacketToBuffer(Temp->Data, Packet, SecondSize,
  1238. Packet->Position + Offset);
  1239. *SecondPkt = Temp;
  1240. } else {
  1241. *SecondPkt = NULL;
  1242. if (ThirdPkt != NULL)
  1243. *ThirdPkt = NULL;
  1244. return;
  1245. }
  1246. }
  1247. if (ThirdPkt != NULL) {
  1248. //
  1249. // We need to allocate memory for a third buffer.
  1250. //
  1251. ThirdSize = Size - (Offset + SecondSize);
  1252. Temp = ExAllocatePoolWithTagPriority(NonPagedPool,
  1253. sizeof(IPv6Packet) + ThirdSize,
  1254. TCP6_TAG, LowPoolPriority);
  1255. if (Temp != NULL) {
  1256. Temp->Next = NULL;
  1257. Temp->Position = 0;
  1258. Temp->FlatData = (uchar *)(Temp + 1);
  1259. Temp->Data = Temp->FlatData;
  1260. Temp->ContigSize = ThirdSize;
  1261. Temp->TotalSize = ThirdSize;
  1262. Temp->NdisPacket = NULL;
  1263. Temp->AuxList = NULL;
  1264. Temp->Flags = PACKET_OURS;
  1265. CopyPacketToBuffer(Temp->Data, Packet, ThirdSize,
  1266. Packet->Position + Offset + SecondSize);
  1267. *ThirdPkt = Temp;
  1268. } else
  1269. *ThirdPkt = NULL;
  1270. }
  1271. }
  1272. //* HandleUrgent - Handle urgent data.
  1273. //
  1274. // Called when an incoming segment has urgent data in it. We make sure there
  1275. // really is urgent data in the segment, and if there is we try to dispose
  1276. // of it either by putting it into a posted buffer or calling an exp. rcv.
  1277. // indication handler.
  1278. //
  1279. // This routine is called at DPC level, and with the TCP locked.
  1280. //
  1281. // Urgent data handling is a little complicated. Each TCB has the starting
  1282. // and ending sequence numbers of the 'current' (last received) bit of urgent
  1283. // data. It is possible that the start of the current urgent data might be
  1284. // greater than tcb_rcvnext, if urgent data came in, we handled it, and then
  1285. // couldn't take the preceding normal data. The urgent valid flag is cleared
  1286. // when the next byte of data the user would read (rcvnext - pendingcnt) is
  1287. // greater than the end of urgent data - we do this so that we can correctly
  1288. // support SIOCATMARK. We always seperate urgent data out of the data stream.
  1289. // If the urgent valid field is set when we get into this routing we have
  1290. // to play a couple of games. If the incoming segment starts in front of the
  1291. // current urgent data, we truncate it before the urgent data, and put any
  1292. // data after the urgent data on the reassemble queue. These gyrations are
  1293. // done to avoid delivering the same urgent data twice. If the urgent valid
  1294. // field in the TCB is set and the segment starts after the current urgent
  1295. // data the new urgent information will replace the current urgent
  1296. // information.
  1297. //
  1298. void // Returns: Nothing.
  1299. HandleUrgent(
  1300. TCB *RcvTCB, // TCB to recv the data on.
  1301. TCPRcvInfo *RcvInfo, // RcvInfo structure for the incoming segment.
  1302. IPv6Packet *RcvPkt, // Packet chain containing the incoming segment.
  1303. uint *Size) // Size in bytes of data in the segment.
  1304. {
  1305. uint BytesInFront; // Bytes in front of the urgent data.
  1306. uint BytesInBack; // Bytes in back of the urgent data.
  1307. uint UrgSize; // Size in bytes of urgent data.
  1308. SeqNum UrgStart, UrgEnd;
  1309. IPv6Packet *EndPkt, *UrgPkt;
  1310. TCPRcvInfo NewRcvInfo;
  1311. KIRQL TCBIrql;
  1312. CHECK_STRUCT(RcvTCB, tcb);
  1313. ASSERT(RcvTCB->tcb_refcnt != 0);
  1314. ASSERT(RcvInfo->tri_flags & TCP_FLAG_URG);
  1315. ASSERT(SEQ_EQ(RcvInfo->tri_seq, RcvTCB->tcb_rcvnext));
  1316. // First, validate the urgent pointer.
  1317. if (RcvTCB->tcb_flags & BSD_URGENT) {
  1318. //
  1319. // We're using BSD style urgent data. We assume that the urgent
  1320. // data is one byte long, and that the urgent pointer points one
  1321. // after the urgent data instead of at the last byte of urgent data.
  1322. // See if the urgent data is in this segment.
  1323. //
  1324. if (RcvInfo->tri_urgent == 0 || RcvInfo->tri_urgent > *Size) {
  1325. //
  1326. // Not in this segment. Clear the urgent flag and return.
  1327. //
  1328. RcvInfo->tri_flags &= ~TCP_FLAG_URG;
  1329. return;
  1330. }
  1331. UrgSize = 1;
  1332. BytesInFront = RcvInfo->tri_urgent - 1;
  1333. } else {
  1334. //
  1335. // This is not BSD style urgent. We assume that the urgent data
  1336. // starts at the front of the segment and the last byte is pointed
  1337. // to by the urgent data pointer.
  1338. //
  1339. BytesInFront = 0;
  1340. UrgSize = MIN(RcvInfo->tri_urgent + 1, *Size);
  1341. }
  1342. BytesInBack = *Size - BytesInFront - UrgSize;
  1343. //
  1344. // UrgStart and UrgEnd are the first and last sequence numbers of the
  1345. // urgent data in this segment.
  1346. //
  1347. UrgStart = RcvInfo->tri_seq + BytesInFront;
  1348. UrgEnd = UrgStart + UrgSize - 1;
  1349. if (!(RcvTCB->tcb_flags & URG_INLINE)) {
  1350. EndPkt = NULL;
  1351. // Now see if this overlaps with any urgent data we've already seen.
  1352. if (RcvTCB->tcb_flags & URG_VALID) {
  1353. //
  1354. // We have some urgent data still around. See if we've advanced
  1355. // rcvnext beyond the urgent data. If we have, this is new urgent
  1356. // data, and we can go ahead and process it (although anyone doing
  1357. // an SIOCATMARK socket command might get confused). If we haven't
  1358. // consumed the data in front of the existing urgent data yet,
  1359. // we'll truncate this seg. to that amount and push the rest onto
  1360. // the reassembly queue. Note that rcvnext should never fall
  1361. // between tcb_urgstart and tcb_urgend.
  1362. //
  1363. ASSERT(SEQ_LT(RcvTCB->tcb_rcvnext, RcvTCB->tcb_urgstart) ||
  1364. SEQ_GT(RcvTCB->tcb_rcvnext, RcvTCB->tcb_urgend));
  1365. if (SEQ_LT(RcvTCB->tcb_rcvnext, RcvTCB->tcb_urgstart)) {
  1366. //
  1367. // There appears to be some overlap in the data stream.
  1368. // Split the buffer up into pieces that come before the current
  1369. // urgent data and after the current urgent data, putting the
  1370. // latter on the reassembly queue.
  1371. //
  1372. UrgSize = RcvTCB->tcb_urgend - RcvTCB->tcb_urgstart + 1;
  1373. BytesInFront = MIN(RcvTCB->tcb_urgstart - RcvTCB->tcb_rcvnext,
  1374. (int) *Size);
  1375. if (SEQ_GT(RcvTCB->tcb_rcvnext + *Size, RcvTCB->tcb_urgend)) {
  1376. // We have data after this piece of urgent data.
  1377. BytesInBack = RcvTCB->tcb_rcvnext + *Size -
  1378. RcvTCB->tcb_urgend;
  1379. } else
  1380. BytesInBack = 0;
  1381. SplitPacket(RcvPkt, *Size, BytesInFront, UrgSize, NULL,
  1382. (BytesInBack ? &EndPkt : NULL));
  1383. if (EndPkt != NULL) {
  1384. NewRcvInfo.tri_seq = RcvTCB->tcb_urgend + 1;
  1385. if (SEQ_GT(UrgEnd, RcvTCB->tcb_urgend)) {
  1386. NewRcvInfo.tri_flags = RcvInfo->tri_flags;
  1387. NewRcvInfo.tri_urgent = UrgEnd - NewRcvInfo.tri_seq;
  1388. if (RcvTCB->tcb_flags & BSD_URGENT)
  1389. NewRcvInfo.tri_urgent++;
  1390. } else {
  1391. NewRcvInfo.tri_flags = RcvInfo->tri_flags &
  1392. ~TCP_FLAG_URG;
  1393. }
  1394. NewRcvInfo.tri_ack = RcvInfo->tri_ack;
  1395. NewRcvInfo.tri_window = RcvInfo->tri_window;
  1396. PutOnRAQ(RcvTCB, &NewRcvInfo, EndPkt, BytesInBack);
  1397. FreePacketChain(EndPkt);
  1398. }
  1399. *Size = BytesInFront;
  1400. RcvInfo->tri_flags &= ~TCP_FLAG_URG;
  1401. return;
  1402. }
  1403. }
  1404. //
  1405. // We have urgent data we can process now. Split it into its component
  1406. // parts, the first part, the urgent data, and the stuff after the
  1407. // urgent data.
  1408. //
  1409. SplitPacket(RcvPkt, *Size, BytesInFront, UrgSize, &UrgPkt,
  1410. (BytesInBack ? &EndPkt : NULL));
  1411. //
  1412. // If we managed to split out the end stuff, put it on the queue now.
  1413. //
  1414. if (EndPkt != NULL) {
  1415. NewRcvInfo.tri_seq = RcvInfo->tri_seq + BytesInFront + UrgSize;
  1416. NewRcvInfo.tri_flags = RcvInfo->tri_flags & ~TCP_FLAG_URG;
  1417. NewRcvInfo.tri_ack = RcvInfo->tri_ack;
  1418. NewRcvInfo.tri_window = RcvInfo->tri_window;
  1419. PutOnRAQ(RcvTCB, &NewRcvInfo, EndPkt, BytesInBack);
  1420. FreePacketChain(EndPkt);
  1421. }
  1422. if (UrgPkt != NULL) {
  1423. // We succesfully split the urgent data out.
  1424. if (!(RcvTCB->tcb_flags & URG_VALID)) {
  1425. RcvTCB->tcb_flags |= URG_VALID;
  1426. RcvTCB->tcb_slowcount++;
  1427. RcvTCB->tcb_fastchk |= TCP_FLAG_SLOW;
  1428. CheckTCBRcv(RcvTCB);
  1429. }
  1430. RcvTCB->tcb_urgstart = UrgStart;
  1431. RcvTCB->tcb_urgend = UrgEnd;
  1432. TCBIrql = DISPATCH_LEVEL;
  1433. DeliverUrgent(RcvTCB, UrgPkt, UrgSize, &TCBIrql);
  1434. }
  1435. *Size = BytesInFront;
  1436. } else {
  1437. //
  1438. // Urgent data is to be processed inline. We just need to remember
  1439. // where it is and treat it as normal data. If there's already urgent
  1440. // data, we remember the latest urgent data.
  1441. //
  1442. RcvInfo->tri_flags &= ~TCP_FLAG_URG;
  1443. if (RcvTCB->tcb_flags & URG_VALID) {
  1444. //
  1445. // There is urgent data. See if this stuff comes after the
  1446. // existing urgent data.
  1447. //
  1448. if (SEQ_LTE(UrgEnd, RcvTCB->tcb_urgend)) {
  1449. //
  1450. // The existing urgent data completely overlaps this stuff,
  1451. // so ignore this.
  1452. //
  1453. return;
  1454. }
  1455. } else {
  1456. RcvTCB->tcb_flags |= URG_VALID;
  1457. RcvTCB->tcb_slowcount++;
  1458. RcvTCB->tcb_fastchk |= TCP_FLAG_SLOW;
  1459. CheckTCBRcv(RcvTCB);
  1460. }
  1461. RcvTCB->tcb_urgstart = UrgStart;
  1462. RcvTCB->tcb_urgend = UrgEnd;
  1463. }
  1464. return;
  1465. }
  1466. //* TdiReceive - Process a receive request.
  1467. //
  1468. // This is the main TDI receive request handler. We validate the connection
  1469. // and make sure that we have a TCB in the proper state, then we try to
  1470. // allocate a receive request structure. If that succeeds, we'll look and
  1471. // see what's happening on the TCB - if there's pending data, we'll put it
  1472. // in the buffer. Otherwise we'll just queue the receive for later.
  1473. //
  1474. TDI_STATUS // Returns: TDI_STATUS of request.
  1475. TdiReceive(
  1476. PTDI_REQUEST Request, // TDI_REQUEST structure for this request.
  1477. ushort *Flags, // Pointer to flags word.
  1478. uint *RcvLength, // Pointer to length in bytes of receive buffer.
  1479. PNDIS_BUFFER Buffer) // Pointer to buffer to take data.
  1480. {
  1481. TCPConn *Conn;
  1482. TCB *RcvTCB;
  1483. TCPRcvReq *RcvReq;
  1484. KIRQL Irql0, Irql1; // One per lock nesting level.
  1485. ushort UFlags;
  1486. TDI_STATUS Status;
  1487. Conn = GetConnFromConnID(PtrToUlong(Request->Handle.ConnectionContext),
  1488. &Irql0);
  1489. if (Conn == NULL) {
  1490. //
  1491. // No connection.
  1492. //
  1493. return TDI_INVALID_CONNECTION;
  1494. }
  1495. CHECK_STRUCT(Conn, tc);
  1496. RcvTCB = Conn->tc_tcb;
  1497. if (RcvTCB == NULL) {
  1498. //
  1499. // No TCB for connection.
  1500. //
  1501. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, Irql0);
  1502. return TDI_INVALID_STATE;
  1503. }
  1504. CHECK_STRUCT(RcvTCB, tcb);
  1505. KeAcquireSpinLock(&RcvTCB->tcb_lock, &Irql1);
  1506. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, Irql1);
  1507. UFlags = *Flags;
  1508. //
  1509. // Fail new receive requests for TCBs in an invalid state.
  1510. //
  1511. if (CLOSING(RcvTCB)) {
  1512. Status = TDI_INVALID_STATE;
  1513. goto done;
  1514. }
  1515. //
  1516. // Also fail for TCBs that don't have any data available to
  1517. // be read and have route over a disconnected outgoing interface
  1518. // (except when a loopback route is being used).
  1519. //
  1520. if ((RcvTCB->tcb_pendingcnt == 0 || !(UFlags & TDI_RECEIVE_NORMAL)) &&
  1521. (RcvTCB->tcb_urgcnt == 0 || !(UFlags & TDI_RECEIVE_EXPEDITED))) {
  1522. //
  1523. // We have no data waiting to give this type of receive request.
  1524. // Check to see if our TCB is likely to get any more data.
  1525. //
  1526. if (!DATA_RCV_STATE(RcvTCB->tcb_state)) {
  1527. Status = TDI_INVALID_STATE;
  1528. goto done;
  1529. }
  1530. //
  1531. // In order to verify that our outgoing interface hasn't become
  1532. // disconnected, we need to know what route we are using.
  1533. // If we've released our RCE for some reason, reacquire one.
  1534. //
  1535. if (RcvTCB->tcb_rce == NULL) {
  1536. InitRCE(RcvTCB);
  1537. if (RcvTCB->tcb_rce == NULL) {
  1538. Status = TDI_DEST_NET_UNREACH;
  1539. goto done;
  1540. }
  1541. }
  1542. //
  1543. // Verify that the cached RCE is still valid.
  1544. //
  1545. RcvTCB->tcb_rce = ValidateRCE(RcvTCB->tcb_rce, RcvTCB->tcb_nte);
  1546. ASSERT(RcvTCB->tcb_rce != NULL);
  1547. if (IsDisconnectedAndNotLoopbackRCE(RcvTCB->tcb_rce)) {
  1548. Status = TDI_DEST_NET_UNREACH;
  1549. goto done;
  1550. }
  1551. }
  1552. CheckPacketList(RcvTCB->tcb_pendhead, RcvTCB->tcb_pendingcnt);
  1553. //
  1554. // We have a TCB, and it's valid. Get a receive request now.
  1555. //
  1556. RcvReq = GetRcvReq();
  1557. if (RcvReq == NULL) {
  1558. //
  1559. // Couldn't get a receive request.
  1560. //
  1561. Status = TDI_NO_RESOURCES;
  1562. goto done;
  1563. }
  1564. RcvReq->trr_rtn = Request->RequestNotifyObject;
  1565. RcvReq->trr_context = Request->RequestContext;
  1566. RcvReq->trr_buffer = Buffer;
  1567. RcvReq->trr_size = *RcvLength;
  1568. RcvReq->trr_uflags = Flags;
  1569. RcvReq->trr_offset = 0;
  1570. RcvReq->trr_amt = 0;
  1571. RcvReq->trr_flags = (uint)UFlags;
  1572. if ((UFlags & (TDI_RECEIVE_NORMAL | TDI_RECEIVE_EXPEDITED))
  1573. != TDI_RECEIVE_EXPEDITED) {
  1574. //
  1575. // This is not an expedited only receive.
  1576. // Put it on the normal receive queue.
  1577. //
  1578. RcvReq->trr_next = NULL;
  1579. if (RcvTCB->tcb_rcvhead == NULL) {
  1580. // The receive queue is empty.
  1581. // Put it on the front.
  1582. RcvTCB->tcb_rcvhead = RcvReq;
  1583. RcvTCB->tcb_rcvtail = RcvReq;
  1584. } else {
  1585. RcvTCB->tcb_rcvtail->trr_next = RcvReq;
  1586. RcvTCB->tcb_rcvtail = RcvReq;
  1587. }
  1588. //
  1589. // If this receive is for zero length, complete this
  1590. // and indicate pending data again, if any.
  1591. //
  1592. if (RcvReq->trr_size == 0) {
  1593. RcvTCB->tcb_refcnt++;
  1594. RcvReq->trr_flags |= TRR_PUSHED;
  1595. KeReleaseSpinLock(&RcvTCB->tcb_lock, Irql0);
  1596. CompleteRcvs(RcvTCB);
  1597. KeAcquireSpinLock(&RcvTCB->tcb_lock, &Irql0);
  1598. DerefTCB(RcvTCB, Irql0);
  1599. return TDI_PENDING;
  1600. }
  1601. //
  1602. // Check to see if this receive can hold urgent data and also
  1603. // if there is some urgent data pending.
  1604. //
  1605. if ((UFlags & TDI_RECEIVE_EXPEDITED) &&
  1606. RcvTCB->tcb_urgcnt != 0) {
  1607. //
  1608. // This buffer can hold urgent data and we have
  1609. // some pending. Deliver it now.
  1610. //
  1611. RcvTCB->tcb_refcnt++;
  1612. DeliverUrgent(RcvTCB, NULL, 0, &Irql0);
  1613. DerefTCB(RcvTCB, Irql0);
  1614. return TDI_PENDING;
  1615. }
  1616. //
  1617. // Check to see if there is a currently active receive.
  1618. //
  1619. if (RcvTCB->tcb_currcv == NULL) {
  1620. RcvTCB->tcb_currcv = RcvReq;
  1621. //
  1622. // No currently active receive. Check to see if there is
  1623. // pending data and that we are not currently in a receive
  1624. // indication handler. If both of these are true then deal
  1625. // with the pending data.
  1626. //
  1627. if (RcvTCB->tcb_flags & IN_RCV_IND) {
  1628. //
  1629. // In a receive indication. The receive request
  1630. // is now on the queue, so just fall through
  1631. // to the return.
  1632. //
  1633. } else {
  1634. //
  1635. // Not in a receive indication.
  1636. // Check for pending data.
  1637. //
  1638. RcvTCB->tcb_rcvhndlr = BufferData;
  1639. if (RcvTCB->tcb_pendhead == NULL) {
  1640. //
  1641. // No pending data.
  1642. //
  1643. Status = TDI_PENDING;
  1644. goto done;
  1645. } else {
  1646. IPv6Packet *PendPacket;
  1647. uint PendSize;
  1648. uint OldRcvWin;
  1649. //
  1650. // We have pending data to deal with.
  1651. //
  1652. PendPacket = RcvTCB->tcb_pendhead;
  1653. PendSize = RcvTCB->tcb_pendingcnt;
  1654. RcvTCB->tcb_pendhead = NULL;
  1655. RcvTCB->tcb_pendingcnt = 0;
  1656. RcvTCB->tcb_refcnt++;
  1657. //
  1658. // We assume that BufferData holds the lock (does not
  1659. // yield) during this call. If this changes for some
  1660. // reason, we'll have to fix the code below that does
  1661. // the window update check. See the comments in the
  1662. // BufferData() routine for more info.
  1663. //
  1664. (void)BufferData(RcvTCB, TCP_FLAG_PUSH, PendPacket,
  1665. PendSize);
  1666. CheckTCBRcv(RcvTCB);
  1667. //
  1668. // Now we need to see if the window has changed.
  1669. // If it has, send an ACK.
  1670. //
  1671. OldRcvWin = RcvTCB->tcb_rcvwin;
  1672. if (OldRcvWin != RcvWin(RcvTCB)) {
  1673. //
  1674. // The window has changed, so send an ACK.
  1675. //
  1676. DelayAction(RcvTCB, NEED_ACK);
  1677. }
  1678. DerefTCB(RcvTCB, Irql0);
  1679. ProcessTCBDelayQ();
  1680. return TDI_PENDING;
  1681. }
  1682. }
  1683. }
  1684. //
  1685. // A receive is currently active. No need to do
  1686. // anything else.
  1687. //
  1688. Status = TDI_PENDING;
  1689. } else {
  1690. TCPRcvReq *Temp;
  1691. //
  1692. // This is an expedited only receive. Just put it
  1693. // on the end of the expedited receive queue.
  1694. //
  1695. Temp = CONTAINING_RECORD(&RcvTCB->tcb_exprcv, TCPRcvReq, trr_next);
  1696. while (Temp->trr_next != NULL)
  1697. Temp = Temp->trr_next;
  1698. RcvReq->trr_next = NULL;
  1699. Temp->trr_next = RcvReq;
  1700. if (RcvTCB->tcb_urgpending != NULL) {
  1701. RcvTCB->tcb_refcnt++;
  1702. DeliverUrgent(RcvTCB, NULL, 0, &Irql0);
  1703. DerefTCB(RcvTCB, Irql0);
  1704. return TDI_PENDING;
  1705. }
  1706. Status = TDI_PENDING;
  1707. }
  1708. done:
  1709. KeReleaseSpinLock(&RcvTCB->tcb_lock, Irql0);
  1710. return Status;
  1711. }