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.

3687 lines
120 KiB

  1. /********************************************************************/
  2. /** Microsoft LAN Manager **/
  3. /** Copyright(c) Microsoft Corp., 1990-1993 **/
  4. /********************************************************************/
  5. /* :ts=4 */
  6. //** TCB.C - TCP TCB management code.
  7. //
  8. // This file contains the code for managing TCBs.
  9. //
  10. #include "precomp.h"
  11. #include "addr.h"
  12. #include "tcp.h"
  13. #include "tcb.h"
  14. #include "tlcommon.h"
  15. #include "tcpconn.h"
  16. #include "tcpsend.h"
  17. #include "tcprcv.h"
  18. #include "info.h"
  19. #include "tcpcfg.h"
  20. #include "pplasl.h"
  21. #include "tcpdeliv.h"
  22. #include <acd.h>
  23. #include <acdapi.h>
  24. HANDLE TcbPool;
  25. HANDLE SynTcbPool;
  26. HANDLE IprBufPool = NULL;
  27. extern HANDLE TcpRequestPool;
  28. //Special spinlock and table for TIMED_WAIT states.
  29. extern CTELock *pTWTCBTableLock;
  30. extern CTELock *pSynTCBTableLock;
  31. Queue *TWTCBTable;
  32. PTIMER_WHEEL TimerWheel;
  33. // This queue is used for faster scavenging
  34. Queue *TWQueue;
  35. ulong numtwqueue = 0;
  36. ulong numtwtimedout = 0;
  37. extern
  38. void
  39. ClassifyPacket(TCB *SendTCB);
  40. void
  41. TCBTimeoutdpc(
  42. #if !MILLEN
  43. PKDPC Dpc,
  44. #else // !MILLEN
  45. PVOID arg0,
  46. #endif // MILLEN
  47. PVOID DeferredContext,
  48. PVOID arg1,
  49. PVOID arg2
  50. );
  51. extern CTELock *pTCBTableLock;
  52. #if MILLEN
  53. #define MAX_TIMER_PROCS 1
  54. #else // MILLEN
  55. #define MAX_TIMER_PROCS MAXIMUM_PROCESSORS
  56. #endif // !MILLEN
  57. uint TCPTime;
  58. uint CPUTCPTime[MAX_TIMER_PROCS];
  59. uint TCBWalkCount;
  60. uint PerTimerSize = 0;
  61. uint Time_Proc = 0;
  62. TCB **TCBTable;
  63. TCB *PendingFreeList=NULL;
  64. SYNTCB *PendingSynFreeList=NULL;
  65. Queue *SYNTCBTable;
  66. CACHE_LINE_KSPIN_LOCK PendingFreeLock;
  67. #define NUM_DEADMAN_TICKS MS_TO_TICKS(1000)
  68. #define NUM_DEADMAN_TIME 1000
  69. #define DQ_PARTITION_TIME 8
  70. uint LastDelayQPartitionTime = 0;
  71. uint MaxHashTableSize = 512;
  72. uint DeadmanTicks;
  73. //choose reasonable defaults
  74. uint NumTcbTablePartitions = 4;
  75. uint PerPartitionSize = 128;
  76. uint LogPerPartitionSize = 7;
  77. CTETimer TCBTimer[MAX_TIMER_PROCS];
  78. ULONGLONG LastTimeoutTime;
  79. ULONG CumulativeCarryOver=0;
  80. extern IPInfo LocalNetInfo;
  81. extern SeqNum g_CurISN;
  82. extern int g_Credits;
  83. extern int g_LastIsnUpdateTime;
  84. extern int g_MaxCredits;
  85. //
  86. // All of the init code can be discarded.
  87. //
  88. int InitTCB(void);
  89. void UnInitTCB(void);
  90. #ifdef ALLOC_PRAGMA
  91. #pragma alloc_text(INIT, InitTCB)
  92. #pragma alloc_text(INIT, UnInitTCB)
  93. #endif
  94. extern CTEBlockStruc TcpipUnloadBlock;
  95. BOOLEAN fTCBTimerStopping = FALSE;
  96. extern ACD_DRIVER AcdDriverG;
  97. VOID
  98. TCPNoteNewConnection(
  99. IN TCB * pTCB,
  100. IN CTELockHandle Handle
  101. );
  102. NTSTATUS
  103. GetTCBInfo(PTCP_FINDTCB_RESPONSE TCBInfo,
  104. IPAddr Dest,
  105. IPAddr Src,
  106. ushort DestPort,
  107. ushort SrcPort
  108. );
  109. void
  110. TCBTimeoutdpc(
  111. #if !MILLEN
  112. PKDPC Dpc,
  113. #else // !MILLEN
  114. PVOID arg0,
  115. #endif // MILLEN
  116. PVOID DeferredContext,
  117. PVOID arg1,
  118. PVOID arg2
  119. )
  120. /*++
  121. Routine Description:
  122. System timer dpc wrapper routine for TCBTimeout().
  123. Arguments:
  124. Return Value:
  125. None.
  126. --*/
  127. {
  128. CTETimer *Timer;
  129. Timer = (CTETimer *) DeferredContext;
  130. #if MILLEN
  131. // Set the timer again to make it periodic.
  132. NdisSetTimer(&Timer->t_timer, MS_PER_TICK);
  133. #endif // MILLEN
  134. (*Timer->t_handler)((CTEEvent *)Timer, Timer->t_arg);
  135. }
  136. void
  137. CTEInitTimerEx(
  138. CTETimer *Timer
  139. )
  140. /*++
  141. Routine Description:
  142. Initializes a CTE Timer variable for periodic timer.
  143. Arguments:
  144. Timer - Timer variable to initialize.
  145. Return Value:
  146. None.
  147. --*/
  148. {
  149. Timer->t_handler = NULL;
  150. Timer->t_arg = NULL;
  151. #if !MILLEN
  152. KeInitializeDpc(&(Timer->t_dpc), TCBTimeoutdpc, Timer);
  153. KeInitializeTimerEx(&(Timer->t_timer),NotificationTimer);
  154. #else !MILLEN
  155. NdisInitializeTimer(&Timer->t_timer, TCBTimeoutdpc, Timer);
  156. #endif // MILLEN
  157. }
  158. void *
  159. CTEStartTimerEx(
  160. CTETimer *Timer,
  161. unsigned long DueTime,
  162. CTEEventRtn Handler,
  163. void *Context
  164. )
  165. /*++
  166. Routine Description:
  167. Sets a CTE Timer for expiration for periodic timer.
  168. Arguments:
  169. Timer - Pointer to a CTE Timer variable.
  170. DueTime - Time in milliseconds after which the timer should expire.
  171. Handler - Timer expiration handler routine.
  172. Context - Argument to pass to the handler.
  173. Return Value:
  174. 0 if the timer could not be set. Nonzero otherwise.
  175. --*/
  176. {
  177. #if !MILLEN
  178. LARGE_INTEGER LargeDueTime;
  179. ASSERT(Handler != NULL);
  180. //
  181. // Convert milliseconds to hundreds of nanoseconds and negate to make
  182. // an NT relative timeout.
  183. //
  184. LargeDueTime.HighPart = 0;
  185. LargeDueTime.LowPart = DueTime;
  186. LargeDueTime = RtlExtendedIntegerMultiply(LargeDueTime, 10000);
  187. LargeDueTime.QuadPart = -LargeDueTime.QuadPart;
  188. Timer->t_handler = Handler;
  189. Timer->t_arg = Context;
  190. KeSetTimerEx(
  191. &(Timer->t_timer),
  192. LargeDueTime,
  193. MS_PER_TICK,
  194. &(Timer->t_dpc)
  195. );
  196. #else // !MILLEN
  197. ASSERT(Handler != NULL);
  198. Timer->t_handler = Handler;
  199. Timer->t_arg = Context;
  200. NdisSetTimer(&Timer->t_timer, DueTime);
  201. #endif // MILLEN
  202. return((void *) 1);
  203. }
  204. //* ReadNextTCB - Read the next TCB in the table.
  205. //
  206. // Called to read the next TCB in the table. The needed information
  207. // is derived from the incoming context, which is assumed to be valid.
  208. // We'll copy the information, and then update the context value with
  209. // the next TCB to be read.
  210. // The table lock for the given index is assumed to be held when this
  211. // function is called.
  212. //
  213. // Input: Context - Poiner to a TCPConnContext.
  214. // Buffer - Pointer to a TCPConnTableEntry structure.
  215. //
  216. // Returns: TRUE if more data is available to be read, FALSE is not.
  217. //
  218. uint
  219. ReadNextTCB(void *Context, void *Buffer)
  220. {
  221. TCPConnContext *TCContext = (TCPConnContext *) Context;
  222. TCPConnTableEntry *TCEntry = (TCPConnTableEntry *) Buffer;
  223. CTELockHandle Handle;
  224. TCB *CurrentTCB;
  225. TWTCB *CurrentTWTCB;
  226. Queue *Scan;
  227. uint i;
  228. if (TCContext->tcc_index >= TCB_TABLE_SIZE) {
  229. CurrentTWTCB = (TWTCB *) TCContext->tcc_tcb;
  230. CTEStructAssert(CurrentTWTCB, twtcb);
  231. TCEntry->tct_state = TCB_TIME_WAIT + TCB_STATE_DELTA;
  232. TCEntry->tct_localaddr = CurrentTWTCB->twtcb_saddr;
  233. TCEntry->tct_localport = CurrentTWTCB->twtcb_sport;
  234. TCEntry->tct_remoteaddr = CurrentTWTCB->twtcb_daddr;
  235. TCEntry->tct_remoteport = CurrentTWTCB->twtcb_dport;
  236. if (TCContext->tcc_infosize > sizeof(TCPConnTableEntry)) {
  237. ((TCPConnTableEntryEx*)TCEntry)->tcte_owningpid = 0;
  238. }
  239. i = TCContext->tcc_index - TCB_TABLE_SIZE;
  240. Scan = QNEXT(&CurrentTWTCB->twtcb_link);
  241. if (Scan != QEND(&TWTCBTable[i])) {
  242. TCContext->tcc_tcb = (TCB *) QSTRUCT(TWTCB, Scan, twtcb_link);
  243. return TRUE;
  244. }
  245. } else {
  246. CurrentTCB = TCContext->tcc_tcb;
  247. CTEStructAssert(CurrentTCB, tcb);
  248. CTEGetLock(&CurrentTCB->tcb_lock, &Handle);
  249. if (CLOSING(CurrentTCB))
  250. TCEntry->tct_state = TCP_CONN_CLOSED;
  251. else
  252. TCEntry->tct_state = (uint) CurrentTCB->tcb_state + TCB_STATE_DELTA;
  253. TCEntry->tct_localaddr = CurrentTCB->tcb_saddr;
  254. TCEntry->tct_localport = CurrentTCB->tcb_sport;
  255. TCEntry->tct_remoteaddr = CurrentTCB->tcb_daddr;
  256. TCEntry->tct_remoteport = CurrentTCB->tcb_dport;
  257. if (TCContext->tcc_infosize > sizeof(TCPConnTableEntry)) {
  258. ((TCPConnTableEntryEx*)TCEntry)->tcte_owningpid =
  259. (CurrentTCB->tcb_conn) ? CurrentTCB->tcb_conn->tc_owningpid
  260. : 0;
  261. }
  262. CTEFreeLock(&CurrentTCB->tcb_lock, Handle);
  263. if (CurrentTCB->tcb_next != NULL) {
  264. TCContext->tcc_tcb = CurrentTCB->tcb_next;
  265. return TRUE;
  266. }
  267. }
  268. // NextTCB is NULL. Loop through the TCBTable looking for a new
  269. // one.
  270. i = TCContext->tcc_index + 1;
  271. if (i >= TCB_TABLE_SIZE) {
  272. // If the index is greater than the TCB_TABLE_SIZE,
  273. // Then it must be referring to the TIM_WAIT table.
  274. // Get the correct hash index and search in TW table.
  275. i = i - TCB_TABLE_SIZE;
  276. while (i < TCB_TABLE_SIZE) {
  277. if (!EMPTYQ(&TWTCBTable[i])) {
  278. TCContext->tcc_tcb = (TCB *)
  279. QSTRUCT(TWTCB, QHEAD(&TWTCBTable[i]), twtcb_link);
  280. TCContext->tcc_index = i + TCB_TABLE_SIZE;
  281. return TRUE;
  282. break;
  283. } else
  284. i++;
  285. }
  286. } else {
  287. //Normal table scan
  288. while (i < TCB_TABLE_SIZE) {
  289. if (TCBTable[i] != NULL) {
  290. TCContext->tcc_tcb = TCBTable[i];
  291. TCContext->tcc_index = i;
  292. return TRUE;
  293. break;
  294. } else
  295. i++;
  296. }
  297. // We exhausted normal table move on to TIM_WAIT table
  298. i = i - TCB_TABLE_SIZE;
  299. while (i < TCB_TABLE_SIZE) {
  300. if (!EMPTYQ(&TWTCBTable[i])) {
  301. TCContext->tcc_tcb = (TCB *)
  302. QSTRUCT(TWTCB, QHEAD(&TWTCBTable[i]), twtcb_link);
  303. TCContext->tcc_index = i + TCB_TABLE_SIZE;
  304. return TRUE;
  305. break;
  306. } else
  307. i++;
  308. }
  309. }
  310. TCContext->tcc_index = 0;
  311. TCContext->tcc_tcb = NULL;
  312. return FALSE;
  313. }
  314. //* ValidateTCBContext - Validate the context for reading a TCB table.
  315. //
  316. // Called to start reading the TCB table sequentially. We take in
  317. // a context, and if the values are 0 we return information about the
  318. // first TCB in the table. Otherwise we make sure that the context value
  319. // is valid, and if it is we return TRUE.
  320. // We assume the caller holds the TCB table lock.
  321. //
  322. // Input: Context - Pointer to a TCPConnContext.
  323. // Valid - Where to return information about context being
  324. // valid.
  325. //
  326. // Returns: TRUE if data in table, FALSE if not. *Valid set to true if the
  327. // context is valid.
  328. //
  329. uint
  330. ValidateTCBContext(void *Context, uint * Valid)
  331. {
  332. TCPConnContext *TCContext = (TCPConnContext *) Context;
  333. uint i;
  334. TCB *TargetTCB;
  335. TCB *CurrentTCB;
  336. TWTCB *CurrentTWTCB;
  337. Queue *Scan;
  338. i = TCContext->tcc_index;
  339. TargetTCB = TCContext->tcc_tcb;
  340. // If the context values are 0 and NULL, we're starting from the beginning.
  341. if (i == 0 && TargetTCB == NULL) {
  342. *Valid = TRUE;
  343. do {
  344. if ((CurrentTCB = TCBTable[i]) != NULL) {
  345. CTEStructAssert(CurrentTCB, tcb);
  346. TCContext->tcc_index = i;
  347. TCContext->tcc_tcb = CurrentTCB;
  348. return TRUE;
  349. }
  350. i++;
  351. } while (i < TCB_TABLE_SIZE);
  352. // We have TCBs in time wait table also...
  353. i = 0;
  354. do {
  355. if (!EMPTYQ(&TWTCBTable[i])) {
  356. CurrentTWTCB =
  357. QSTRUCT(TWTCB, QHEAD(&TWTCBTable[i]), twtcb_link);
  358. CTEStructAssert(CurrentTWTCB, twtcb);
  359. TCContext->tcc_index = i + TCB_TABLE_SIZE;
  360. TCContext->tcc_tcb = (TCB *) CurrentTWTCB;
  361. return TRUE;
  362. }
  363. i++;
  364. } while (i < TCB_TABLE_SIZE);
  365. return FALSE;
  366. } else {
  367. // We've been given a context. We just need to make sure that it's
  368. // valid.
  369. if (i >= TCB_TABLE_SIZE) {
  370. // If the index is greater than the TCB_TABLE_SIZE,
  371. // Then it must be referring to the TIM_WAIT table.
  372. // Get the correct hash index and search in TW table.
  373. i = i - TCB_TABLE_SIZE;
  374. if (i < TCB_TABLE_SIZE) {
  375. Scan = QHEAD(&TWTCBTable[i]);
  376. while (Scan != QEND(&TWTCBTable[i])) {
  377. CurrentTWTCB = QSTRUCT(TWTCB, Scan, twtcb_link);
  378. if (CurrentTWTCB == (TWTCB *) TargetTCB) {
  379. *Valid = TRUE;
  380. return TRUE;
  381. break;
  382. } else {
  383. Scan = QNEXT(Scan);
  384. }
  385. }
  386. }
  387. } else {
  388. //Normal table
  389. if (i < TCB_TABLE_SIZE) {
  390. CurrentTCB = TCBTable[i];
  391. while (CurrentTCB != NULL) {
  392. if (CurrentTCB == TargetTCB) {
  393. *Valid = TRUE;
  394. return TRUE;
  395. break;
  396. } else {
  397. CurrentTCB = CurrentTCB->tcb_next;
  398. }
  399. }
  400. }
  401. }
  402. // If we get here, we didn't find the matching TCB.
  403. *Valid = FALSE;
  404. return FALSE;
  405. }
  406. }
  407. //* FindNextTCB - Find the next TCB in a particular chain.
  408. //
  409. // This routine is used to find the 'next' TCB in a chain. Since we keep
  410. // the chain in ascending order, we look for a TCB which is greater than
  411. // the input TCB. When we find one, we return it.
  412. //
  413. // This routine is mostly used when someone is walking the table and needs
  414. // to free the various locks to perform some action.
  415. //
  416. // Input: Index - Index into TCBTable
  417. // Current - Current TCB - we find the one after this one.
  418. //
  419. // Returns: Pointer to the next TCB, or NULL.
  420. //
  421. TCB *
  422. FindNextTCB(uint Index, TCB * Current)
  423. {
  424. TCB *Next;
  425. ASSERT(Index < TCB_TABLE_SIZE);
  426. Next = TCBTable[Index];
  427. while (Next != NULL && (Next <= Current))
  428. Next = Next->tcb_next;
  429. return Next;
  430. }
  431. //* ResetSendNext - Set the sendnext value of a TCB.
  432. //
  433. // Called to set the send next value of a TCB. We do that, and adjust all
  434. // pointers to the appropriate places. We assume the caller holds the lock
  435. // on the TCB.
  436. //
  437. // Input: SeqTCB - Pointer to TCB to be updated.
  438. // NewSeq - Sequence number to set.
  439. //
  440. // Returns: Nothing.
  441. //
  442. void
  443. ResetSendNext(TCB *SeqTCB, SeqNum NewSeq)
  444. {
  445. TCPSendReq *SendReq;
  446. uint AmtForward;
  447. Queue *CurQ;
  448. PNDIS_BUFFER Buffer;
  449. uint Offset;
  450. CTEStructAssert(SeqTCB, tcb);
  451. ASSERT(SEQ_GTE(NewSeq, SeqTCB->tcb_senduna));
  452. // The new seq must be less than send max, or NewSeq, senduna, sendnext,
  453. // and sendmax must all be equal. (The latter case happens when we're
  454. // called exiting TIME_WAIT, or possibly when we're retransmitting
  455. // during a flow controlled situation).
  456. ASSERT(SEQ_LT(NewSeq, SeqTCB->tcb_sendmax) ||
  457. (SEQ_EQ(SeqTCB->tcb_senduna, SeqTCB->tcb_sendnext) &&
  458. SEQ_EQ(SeqTCB->tcb_senduna, SeqTCB->tcb_sendmax) &&
  459. SEQ_EQ(SeqTCB->tcb_senduna, NewSeq)));
  460. AmtForward = NewSeq - SeqTCB->tcb_senduna;
  461. if ((AmtForward == 1) && (SeqTCB->tcb_flags & FIN_SENT) &&
  462. !((SeqTCB->tcb_sendnext-SeqTCB->tcb_senduna) > 1) &&
  463. (SEQ_EQ(SeqTCB->tcb_sendnext, SeqTCB->tcb_sendmax))) {
  464. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,
  465. "tcpip: trying to set sendnext for FIN_SENT\n"));
  466. //CheckTCBSends(SeqTCB);
  467. //allow retransmits of this FIN
  468. SeqTCB->tcb_sendnext = NewSeq;
  469. SeqTCB->tcb_flags &= ~FIN_OUTSTANDING;
  470. return;
  471. }
  472. if ((SeqTCB->tcb_flags & FIN_SENT) &&
  473. (SEQ_EQ(SeqTCB->tcb_sendnext, SeqTCB->tcb_sendmax)) &&
  474. ((SeqTCB->tcb_sendnext - NewSeq) == 1)) {
  475. //There is only FIN that is left beyond sendnext.
  476. //allow retransmits of this FIN
  477. SeqTCB->tcb_sendnext = NewSeq;
  478. SeqTCB->tcb_flags &= ~FIN_OUTSTANDING;
  479. return;
  480. }
  481. SeqTCB->tcb_sendnext = NewSeq;
  482. // If we're backing off send next, turn off the FIN_OUTSTANDING flag to
  483. // maintain a consistent state.
  484. if (!SEQ_EQ(NewSeq, SeqTCB->tcb_sendmax))
  485. SeqTCB->tcb_flags &= ~FIN_OUTSTANDING;
  486. if (SYNC_STATE(SeqTCB->tcb_state) && SeqTCB->tcb_state != TCB_TIME_WAIT) {
  487. // In these states we need to update the send queue.
  488. if (!EMPTYQ(&SeqTCB->tcb_sendq)) {
  489. CurQ = QHEAD(&SeqTCB->tcb_sendq);
  490. SendReq = (TCPSendReq *) STRUCT_OF(TCPReq, CurQ, tr_q);
  491. // SendReq points to the first send request on the send queue.
  492. // Move forward AmtForward bytes on the send queue, and set the
  493. // TCB pointers to the resultant SendReq, buffer, offset, size.
  494. while (AmtForward) {
  495. CTEStructAssert(SendReq, tsr);
  496. if (AmtForward >= SendReq->tsr_unasize) {
  497. // We're going to move completely past this one. Subtract
  498. // his size from AmtForward and get the next one.
  499. AmtForward -= SendReq->tsr_unasize;
  500. CurQ = QNEXT(CurQ);
  501. ASSERT(CurQ != QEND(&SeqTCB->tcb_sendq));
  502. SendReq = (TCPSendReq *) STRUCT_OF(TCPReq, CurQ, tr_q);
  503. } else {
  504. // We're pointing at the proper send req now. Break out
  505. // of this loop and save the information. Further down
  506. // we'll need to walk down the buffer chain to find
  507. // the proper buffer and offset.
  508. break;
  509. }
  510. }
  511. // We're pointing at the proper send req now. We need to go down
  512. // the buffer chain here to find the proper buffer and offset.
  513. SeqTCB->tcb_cursend = SendReq;
  514. SeqTCB->tcb_sendsize = SendReq->tsr_unasize - AmtForward;
  515. Buffer = SendReq->tsr_buffer;
  516. Offset = SendReq->tsr_offset;
  517. while (AmtForward) {
  518. // Walk the buffer chain.
  519. uint Length;
  520. // We'll need the length of this buffer. Use the portable
  521. // macro to get it. We have to adjust the length by the offset
  522. // into it, also.
  523. ASSERT((Offset < NdisBufferLength(Buffer)) ||
  524. ((Offset == 0) && (NdisBufferLength(Buffer) == 0)));
  525. Length = NdisBufferLength(Buffer) - Offset;
  526. if (AmtForward >= Length) {
  527. // We're moving past this one. Skip over him, and 0 the
  528. // Offset we're keeping.
  529. AmtForward -= Length;
  530. Offset = 0;
  531. Buffer = NDIS_BUFFER_LINKAGE(Buffer);
  532. ASSERT(Buffer != NULL);
  533. } else
  534. break;
  535. }
  536. // Save the buffer we found, and the offset into that buffer.
  537. SeqTCB->tcb_sendbuf = Buffer;
  538. SeqTCB->tcb_sendofs = Offset + AmtForward;
  539. } else {
  540. ASSERT(SeqTCB->tcb_cursend == NULL);
  541. ASSERT(AmtForward == 0);
  542. }
  543. }
  544. CheckTCBSends(SeqTCB);
  545. }
  546. //* TCPAbortAndIndicateDisconnect
  547. //
  548. // Abortively closes a TCB and issues a disconnect indication up the the
  549. // transport user. This function is used to support cancellation of
  550. // TDI send and receive requests.
  551. //
  552. // Input: ConnectionContext - The connection ID to find a TCB for.
  553. //
  554. // Returns: Nothing.
  555. //
  556. BOOLEAN
  557. TCPAbortAndIndicateDisconnect(
  558. uint ConnectionContext,
  559. PVOID Irp,
  560. uint Rcv,
  561. CTELockHandle inHandle
  562. )
  563. {
  564. TCB *AbortTCB;
  565. CTELockHandle ConnTableHandle;
  566. TCPConn *Conn;
  567. VOID *CancelContext, *CancelID;
  568. PTCP_CONTEXT tcpContext;
  569. PIO_STACK_LOCATION irpSp;
  570. irpSp = IoGetCurrentIrpStackLocation((PIRP)Irp);
  571. tcpContext = (PTCP_CONTEXT) irpSp->FileObject->FsContext;
  572. Conn = GetConnFromConnID(ConnectionContext, &ConnTableHandle);
  573. if (Conn != NULL) {
  574. CTEStructAssert(Conn, tc);
  575. AbortTCB = Conn->tc_tcb;
  576. if (AbortTCB != NULL) {
  577. // If it's CLOSING or CLOSED, skip it.
  578. if ((AbortTCB->tcb_state != TCB_CLOSED) && !CLOSING(AbortTCB)) {
  579. CTEStructAssert(AbortTCB, tcb);
  580. CTEGetLockAtDPC(&AbortTCB->tcb_lock);
  581. CTEFreeLockFromDPC(&(Conn->tc_ConnBlock->cb_lock));
  582. if (AbortTCB->tcb_state == TCB_CLOSED || CLOSING(AbortTCB)) {
  583. CTEFreeLockFromDPC(&AbortTCB->tcb_lock);
  584. CTEFreeLock(&tcpContext->EndpointLock, inHandle);
  585. return FALSE;
  586. }
  587. if (Rcv && AbortTCB->tcb_rcvhndlr == BufferData) {
  588. // First, search for the IRP in the normal-receive queue.
  589. if (AbortTCB->tcb_rcvhead) {
  590. TCPRcvReq *RcvReq = AbortTCB->tcb_rcvhead;
  591. while (RcvReq) {
  592. CTEStructAssert(RcvReq, trr);
  593. if (RcvReq->trr_context == Irp) {
  594. break;
  595. }
  596. RcvReq = RcvReq->trr_next;
  597. }
  598. // If the IRP was found, push it and all of its
  599. // predecessors, then let CompleteRcvs complete them.
  600. if (RcvReq) {
  601. TCPRcvReq* TmpReq = AbortTCB->tcb_rcvhead;
  602. while (TmpReq != RcvReq) {
  603. TmpReq->trr_flags |= TRR_PUSHED;
  604. TmpReq = TmpReq->trr_next;
  605. }
  606. RcvReq->trr_flags |= TRR_PUSHED;
  607. RcvReq->trr_status = TDI_CANCELLED;
  608. REFERENCE_TCB(AbortTCB);
  609. CTEFreeLockFromDPC(&AbortTCB->tcb_lock);
  610. CTEFreeLock(&tcpContext->EndpointLock, inHandle);
  611. CompleteRcvs(AbortTCB);
  612. CTEGetLock(&AbortTCB->tcb_lock, &inHandle);
  613. DerefTCB(AbortTCB, inHandle);
  614. return FALSE;
  615. }
  616. }
  617. // Next, search for the IRP in the expedited-receive queue.
  618. if (AbortTCB->tcb_exprcv) {
  619. TCPRcvReq *RcvReq, *PrevReq;
  620. PrevReq = STRUCT_OF(TCPRcvReq, &AbortTCB->tcb_exprcv,
  621. trr_next);
  622. RcvReq = PrevReq->trr_next;
  623. while (RcvReq) {
  624. CTEStructAssert(RcvReq, trr);
  625. if (RcvReq->trr_context == Irp) {
  626. PrevReq->trr_next = RcvReq->trr_next;
  627. FreeRcvReq(RcvReq);
  628. CTEFreeLockFromDPC(&AbortTCB->tcb_lock);
  629. //
  630. // Account for reference count
  631. // on endoint, as we are not calling
  632. // TCPDataRequestComplete() for this
  633. // request.
  634. //
  635. tcpContext->ReferenceCount--;
  636. CTEFreeLock(&tcpContext->EndpointLock,
  637. inHandle);
  638. return TRUE;
  639. }
  640. PrevReq = RcvReq;
  641. RcvReq = RcvReq->trr_next;
  642. }
  643. }
  644. }
  645. CancelContext = ((PIRP)Irp)->Tail.Overlay.DriverContext[0];
  646. CancelID = ((PIRP)Irp)->Tail.Overlay.DriverContext[1];
  647. CTEFreeLockFromDPC(&tcpContext->EndpointLock);
  648. REFERENCE_TCB(AbortTCB);
  649. if (!Rcv) {
  650. CTEFreeLockFromDPC(&AbortTCB->tcb_lock);
  651. // Call ndis cancel packets routine to free up
  652. // queued send packets
  653. (*LocalNetInfo.ipi_cancelpackets) (CancelContext, CancelID);
  654. CTEGetLockAtDPC(&AbortTCB->tcb_lock);
  655. }
  656. AbortTCB->tcb_flags |= NEED_RST; // send a reset if connected
  657. TryToCloseTCB(AbortTCB, TCB_CLOSE_ABORTED, DISPATCH_LEVEL);
  658. RemoveTCBFromConn(AbortTCB);
  659. IF_TCPDBG(TCP_DEBUG_IRP) {
  660. TCPTRACE((
  661. "TCPAbortAndIndicateDisconnect, indicating discon\n"
  662. ));
  663. }
  664. NotifyOfDisc(AbortTCB, NULL, TDI_CONNECTION_ABORTED, NULL);
  665. CTEGetLockAtDPC(&AbortTCB->tcb_lock);
  666. DerefTCB(AbortTCB, inHandle);
  667. return FALSE;
  668. } else
  669. CTEFreeLockFromDPC(&(Conn->tc_ConnBlock->cb_lock));
  670. } else
  671. CTEFreeLockFromDPC(&(Conn->tc_ConnBlock->cb_lock));
  672. }
  673. CTEFreeLock(&tcpContext->EndpointLock, inHandle);
  674. return FALSE;
  675. }
  676. //* AddHalfOpenTCB
  677. //
  678. // Called to update the count of half-open connections and, if necessary,
  679. // adjust retransmission thresholds.
  680. //
  681. // Input: None.
  682. //
  683. // Returns: Nothing.
  684. //
  685. void
  686. AddHalfOpenTCB(void)
  687. {
  688. ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
  689. CTEGetLockAtDPC(&SynAttLock.Lock);
  690. if (++TCPHalfOpen >= TCPMaxHalfOpen &&
  691. TCPHalfOpenRetried >= TCPMaxHalfOpenRetried &&
  692. MaxConnectResponseRexmitCountTmp == MAX_CONNECT_RESPONSE_REXMIT_CNT) {
  693. MaxConnectResponseRexmitCountTmp =
  694. ADAPTED_MAX_CONNECT_RESPONSE_REXMIT_CNT;
  695. }
  696. CTEFreeLockFromDPC(&SynAttLock.Lock);
  697. }
  698. //* AddHalfOpenRetry
  699. //
  700. // Called to update the count of half-open connections which have reached our
  701. // threshold for the number of SYN-ACK retransmissions. If necessary,
  702. // the routine adjusts overall retransmission thresholds.
  703. //
  704. // Input: RexmitCnt - number of rexmits on the TCB for whom we're called.
  705. //
  706. // Returns: Nothing.
  707. //
  708. void
  709. AddHalfOpenRetry(uint RexmitCnt)
  710. {
  711. ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
  712. if (RexmitCnt == ADAPTED_MAX_CONNECT_RESPONSE_REXMIT_CNT) {
  713. CTEGetLockAtDPC(&SynAttLock.Lock);
  714. if (++TCPHalfOpenRetried >= TCPMaxHalfOpenRetried &&
  715. TCPHalfOpen >= TCPMaxHalfOpen &&
  716. MaxConnectResponseRexmitCountTmp ==
  717. MAX_CONNECT_RESPONSE_REXMIT_CNT) {
  718. MaxConnectResponseRexmitCountTmp =
  719. ADAPTED_MAX_CONNECT_RESPONSE_REXMIT_CNT;
  720. }
  721. CTEFreeLockFromDPC(&SynAttLock.Lock);
  722. }
  723. }
  724. //* DropHalfOpenTCB
  725. //
  726. // Called to update the count of half-open connections and, if necessary,
  727. // adjust retransmission thresholds.
  728. //
  729. // Input: RexmitCnt - number of rexmits on the TCB for whom we're called.
  730. //
  731. // Returns: Nothing.
  732. //
  733. void
  734. DropHalfOpenTCB(uint RexmitCnt)
  735. {
  736. ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
  737. CTEGetLockAtDPC(&SynAttLock.Lock);
  738. // Drop the count of half-open connections. If this one's retransmissions
  739. // reached the adaptation threshold, drop the count of retries too.
  740. --TCPHalfOpen;
  741. if (RexmitCnt >= ADAPTED_MAX_CONNECT_RESPONSE_REXMIT_CNT) {
  742. --TCPHalfOpenRetried;
  743. }
  744. if ((TCPHalfOpen < TCPMaxHalfOpen ||
  745. TCPHalfOpenRetried < TCPMaxHalfOpenRetriedLW) &&
  746. MaxConnectResponseRexmitCountTmp ==
  747. ADAPTED_MAX_CONNECT_RESPONSE_REXMIT_CNT) {
  748. MaxConnectResponseRexmitCountTmp = MAX_CONNECT_RESPONSE_REXMIT_CNT;
  749. }
  750. CTEFreeLockFromDPC(&SynAttLock.Lock);
  751. }
  752. //* ProcessSynTcbs
  753. //
  754. // Called from timeout routine to handle syntcbs in syntcb table
  755. // Retransmits SYN if rexmitcnt has not expired. Else removes the
  756. // syntcb from the table and frees it.
  757. //
  758. // Input: Processor number that is used to select the syntcb space
  759. // to handle.
  760. //
  761. // Returns: Nothing.
  762. //
  763. void
  764. ProcessSynTcbs(uint Processor)
  765. {
  766. Queue *Scan;
  767. SYNTCB *SynTCB;
  768. uint i, maxRexmitCnt, StartIndex = 0;
  769. StartIndex = Processor * PerTimerSize;
  770. for (i = StartIndex; i < MIN(TCB_TABLE_SIZE, StartIndex+PerTimerSize); i++) {
  771. Scan = QHEAD(&SYNTCBTable[i]);
  772. while (Scan != QEND(&SYNTCBTable[i])) {
  773. SynTCB = QSTRUCT(SYNTCB, Scan, syntcb_link);
  774. CTEStructAssert(SynTCB, syntcb);
  775. CTEGetLockAtDPC(&SynTCB->syntcb_lock);
  776. Scan = QNEXT(Scan);
  777. // This TCB needs to be processed further only if it is in the
  778. // table, which means it is active still.
  779. // (N.B. This is a more restrictive check than ref-count != 0).
  780. if ((SynTCB->syntcb_flags & IN_SYNTCB_TABLE) &&
  781. (TCB_TIMER_RUNNING(SynTCB->syntcb_rexmittimer))) {
  782. // The timer is running.
  783. if (--(SynTCB->syntcb_rexmittimer) == 0) {
  784. maxRexmitCnt = MIN(MaxConnectResponseRexmitCountTmp,
  785. MaxConnectResponseRexmitCount);
  786. // Need a (greater or equal) here, because, we want to stop
  787. // when the count reaches the max.
  788. if (SynTCB->syntcb_rexmitcnt++ >= maxRexmitCnt) {
  789. uint RexmitCnt = SynTCB->syntcb_rexmitcnt;
  790. AddHalfOpenRetry(RexmitCnt);
  791. SynTCB->syntcb_refcnt++;
  792. CTEFreeLockFromDPC(&SynTCB->syntcb_lock);
  793. CTEGetLockAtDPC(&pSynTCBTableLock[SynTCB->syntcb_partition]);
  794. CTEGetLockAtDPC(&SynTCB->syntcb_lock);
  795. if (SynTCB->syntcb_flags & IN_SYNTCB_TABLE) {
  796. REMOVEQ(&SynTCB->syntcb_link);
  797. SynTCB->syntcb_flags &= ~IN_SYNTCB_TABLE;
  798. // We indeed removed the Syn TCB; so, notify.
  799. TcpInvokeCcb(TCP_CONN_SYN_RCVD, TCP_CONN_CLOSED,
  800. &SynTCB->syntcb_addrbytes, 0);
  801. DropHalfOpenTCB(RexmitCnt);
  802. SynTCB->syntcb_refcnt--;
  803. }
  804. CTEFreeLockFromDPC(
  805. &pSynTCBTableLock[SynTCB->syntcb_partition]);
  806. DerefSynTCB(SynTCB, DISPATCH_LEVEL);
  807. } else {
  808. AddHalfOpenRetry(SynTCB->syntcb_rexmitcnt);
  809. --SynTCB->syntcb_sendnext;
  810. SendSYNOnSynTCB(SynTCB, DISPATCH_LEVEL);
  811. }
  812. } else {
  813. CTEFreeLockFromDPC(&SynTCB->syntcb_lock);
  814. }
  815. } else {
  816. CTEFreeLockFromDPC(&SynTCB->syntcb_lock);
  817. }
  818. }
  819. }
  820. }
  821. __inline void
  822. InsertIntoTimerWheel(TCB *InsertTCB, ushort Slot)
  823. {
  824. PTIMER_WHEEL WheelPtr;
  825. Queue* TimerSlotPtr;
  826. WheelPtr = &TimerWheel[InsertTCB->tcb_partition];
  827. TimerSlotPtr = &WheelPtr->tw_timerslot[Slot];
  828. ASSERT(InsertTCB->tcb_timerslot == DUMMY_SLOT);
  829. CTEGetLockAtDPC(&(WheelPtr->tw_lock));
  830. InsertTCB->tcb_timerslot = Slot;
  831. PUSHQ(TimerSlotPtr, &InsertTCB->tcb_timerwheelq);
  832. CTEFreeLockFromDPC(&(WheelPtr->tw_lock));
  833. }
  834. __inline void
  835. RemoveFromTimerWheel(TCB *RemoveTCB)
  836. {
  837. PTIMER_WHEEL WheelPtr;
  838. WheelPtr = &TimerWheel[RemoveTCB->tcb_partition];
  839. ASSERT(RemoveTCB->tcb_timerslot < TIMER_WHEEL_SIZE);
  840. CTEGetLockAtDPC(&(WheelPtr->tw_lock));
  841. RemoveTCB->tcb_timerslot = DUMMY_SLOT;
  842. RemoveTCB->tcb_timertime = 0;
  843. REMOVEQ(&RemoveTCB->tcb_timerwheelq);
  844. CTEFreeLockFromDPC(&(WheelPtr->tw_lock));
  845. }
  846. __inline void
  847. RemoveAndInsertIntoTimerWheel(TCB *RemInsTCB, ushort InsertSlot)
  848. {
  849. PTIMER_WHEEL WheelPtr;
  850. Queue* InsertSlotPtr;
  851. ASSERT(RemInsTCB->tcb_timerslot < TIMER_WHEEL_SIZE);
  852. WheelPtr = &TimerWheel[RemInsTCB->tcb_partition];
  853. InsertSlotPtr = &WheelPtr->tw_timerslot[InsertSlot];
  854. CTEGetLockAtDPC(&WheelPtr->tw_lock);
  855. REMOVEQ(&RemInsTCB->tcb_timerwheelq);
  856. RemInsTCB->tcb_timerslot = InsertSlot;
  857. PUSHQ(InsertSlotPtr, &RemInsTCB->tcb_timerwheelq);
  858. CTEFreeLockFromDPC(&WheelPtr->tw_lock);
  859. }
  860. __inline void
  861. RecomputeTimerState(TCB *TimerTCB)
  862. {
  863. TCP_TIMER_TYPE i;
  864. TimerTCB->tcb_timertype = NO_TIMER;
  865. TimerTCB->tcb_timertime = 0;
  866. for(i = 0; i < NUM_TIMERS; i++) {
  867. if ((TimerTCB->tcb_timer[i] != 0) &&
  868. ((TimerTCB->tcb_timertime == 0) ||
  869. (TCPTIME_LTE(TimerTCB->tcb_timer[i], TimerTCB->tcb_timertime)))) {
  870. TimerTCB->tcb_timertime = TimerTCB->tcb_timer[i];
  871. TimerTCB->tcb_timertype = i;
  872. }
  873. }
  874. }
  875. // StartTCBTimerR
  876. // Arguments: A TCB, timer type, and the interval in ticks after which the
  877. // timer is supposed to fire.
  878. // Description:
  879. // Sets the array element in tcb_timer for that particular timer to the
  880. // appropriate value, and recomputes the tcb_timertime and tcb_timertype
  881. // values ONLY if we need to. All shortcuts and optimizations are done to
  882. // avoid recomputing the tcb_timertime and tcb_timertype by going through
  883. // the whole array.
  884. // return value: TRUE if minimum got changed; FALSE if not.
  885. BOOLEAN
  886. StartTCBTimerR(TCB *StartTCB, TCP_TIMER_TYPE TimerType, uint DeltaTime)
  887. {
  888. ASSERT(TimerType < NUM_TIMERS);
  889. StartTCB->tcb_timer[TimerType] = TCPTime + DeltaTime;
  890. // Make a check for the case where TCPTime + DeltaTime is 0
  891. // because of wraparound
  892. if (StartTCB->tcb_timer[TimerType] == 0) {
  893. StartTCB->tcb_timer[TimerType] = 1;
  894. }
  895. // This is really simple logic. Find out if the setting of
  896. // this timer changes the minimum. Don't care whether it was
  897. // already running, or whether it already the minimum...
  898. if ((StartTCB->tcb_timertime == 0 ) ||
  899. (TCPTIME_LT(StartTCB->tcb_timer[TimerType], StartTCB->tcb_timertime))
  900. )
  901. {
  902. // Yup it changed the minimum...
  903. StartTCB->tcb_timertime = StartTCB->tcb_timer[TimerType];
  904. StartTCB->tcb_timertype = TimerType;
  905. return TRUE;
  906. }
  907. // No it did not change the minimum.
  908. // You only have to recompute if it was already the minimum
  909. if (StartTCB->tcb_timertype == TimerType) {
  910. RecomputeTimerState(StartTCB);
  911. }
  912. return FALSE;
  913. }
  914. // StopTCBTimerR
  915. // Arguments: A TCB, and a timer type
  916. // Description:
  917. // Sets the array element for that timer to 0, and recomputes
  918. // tcb_timertime and tcb_timertype. It automatically handles
  919. // the case where the function is called for a timer which has
  920. // already stopped.
  921. void
  922. StopTCBTimerR(TCB *StopTCB, TCP_TIMER_TYPE TimerType)
  923. {
  924. ASSERT(TimerType < NUM_TIMERS);
  925. StopTCB->tcb_timer[TimerType] = 0;
  926. // Is this the lowest timer value we are running?
  927. if (StopTCB->tcb_timertype == TimerType)
  928. {
  929. // Stopping a timer can only push back the firing
  930. // time, so we will never remove a TCB from a slot.
  931. RecomputeTimerState(StopTCB);
  932. }
  933. return;
  934. }
  935. // START_TCB_TIMER_R modifies the timer state and only modifies
  936. // wheel state if the timer that was started was earlier than all the
  937. // other timers on that TCB. This is in accordance with the lazy evaluation
  938. // strategy.
  939. __inline void
  940. START_TCB_TIMER_R(TCB *StartTCB, TCP_TIMER_TYPE Type, uint Value)
  941. {
  942. ushort Slot;
  943. // The value of the delta ticks has to be atleast 2.
  944. if (Value < 2) {
  945. Value = 2;
  946. }
  947. if( StartTCB->tcb_timerslot == DUMMY_SLOT ) {
  948. StartTCBTimerR(StartTCB, Type, Value);
  949. Slot = COMPUTE_SLOT(StartTCB->tcb_timertime);
  950. InsertIntoTimerWheel(StartTCB, Slot);
  951. } else if ( StartTCBTimerR(StartTCB, Type, Value)) {
  952. Slot = COMPUTE_SLOT(StartTCB->tcb_timertime);
  953. RemoveAndInsertIntoTimerWheel(StartTCB, Slot);
  954. }
  955. }
  956. __inline void
  957. STOP_TCB_TIMER_R(TCB *StopTCB, TCP_TIMER_TYPE Type)
  958. {
  959. StopTCBTimerR(StopTCB, Type);
  960. return;
  961. }
  962. void
  963. MakeTimerStateConsistent(TCB *TimerTCB, uint CurrentTime)
  964. {
  965. uint i;
  966. BOOLEAN TimesChanged = FALSE;
  967. for(i = 0; i < NUM_TIMERS; i++) {
  968. if (TimerTCB->tcb_timer[i] != 0) {
  969. if (TCPTIME_LTE(TimerTCB->tcb_timer[i], CurrentTime)) {
  970. // This should not happen. If it does, we either have a bug in the current code
  971. // or in the TimerWheel code.
  972. // This assert was modified because it was found that, at some point of time
  973. // ACD_CON_NOTIF was ON but not looked at after processing CONN_TIMER. So, it
  974. // alright to advance timers by 1 tick if they were supposed to go off on the
  975. // 'current' tick. Otherwise, assert.
  976. if( TCPTIME_LT(TimerTCB->tcb_timer[i], CurrentTime )) {
  977. ASSERT(0);
  978. }
  979. TimesChanged = TRUE;
  980. TimerTCB->tcb_timer[i] = CurrentTime + 1;
  981. // Code to handle wraparound.
  982. if (TimerTCB->tcb_timer[i] == 0) {
  983. TimerTCB->tcb_timer[i] = 1;
  984. }
  985. }
  986. }
  987. }
  988. return;
  989. }
  990. //* TCBTimeout - Do timeout events on TCBs.
  991. //
  992. // Called every MS_PER_TICKS milliseconds to do timeout processing on TCBs.
  993. // We run throught the TCB table, decrementing timers. If one goes to zero
  994. // we look at it's state to decide what to do.
  995. //
  996. // Input: Timer - Event structure for timer that fired.
  997. // Context - Context for timer (NULL in this case.
  998. //
  999. // Returns: Nothing.
  1000. //
  1001. void
  1002. TCBTimeout(CTEEvent * Timer, void *Context)
  1003. {
  1004. CTELockHandle TCBHandle;
  1005. uint i, j;
  1006. TCB *CurrentTCB;
  1007. uint Delayed = FALSE;
  1008. uint ProcessDelayQ = FALSE;
  1009. ULONGLONG CurrentTime;
  1010. ULONG TimeDiff;
  1011. uint Processor, StartIndex, EndIndex;
  1012. #if TRACE_EVENT
  1013. PTDI_DATA_REQUEST_NOTIFY_ROUTINE CPCallBack;
  1014. WMIData WMIInfo;
  1015. #endif
  1016. // LocalTime must remain a uint. A loop below uses the
  1017. // termination condition j != (LocalTime + 1) and that
  1018. // works only if LocalTime is a uint so that wraparound
  1019. // can be handled correctly.
  1020. uint LocalTime = 0;
  1021. uint PerProcPartitions, ExtraPartitions;
  1022. Processor = KeGetCurrentProcessorNumber();
  1023. // Update our free running counter.
  1024. if (Processor == 0) {
  1025. int Delta;
  1026. ULONG CarryOver;
  1027. int ElapsedTicks, ExtraTicks;
  1028. CurrentTime = KeQueryInterruptTime();
  1029. // This is time between when we processed the timer last and now.
  1030. TimeDiff = (ULONG)(CurrentTime - LastTimeoutTime);
  1031. LastTimeoutTime = CurrentTime;
  1032. // This is the extra time we have to carry forward.
  1033. ElapsedTicks = TimeDiff / 1000000;
  1034. CarryOver = TimeDiff % 1000000;
  1035. // This is the total extra time we have seen so far:
  1036. CumulativeCarryOver = CumulativeCarryOver + CarryOver;
  1037. // If that exceeds 1 tick, we remember that.
  1038. if(CumulativeCarryOver > 1000000) {
  1039. ExtraTicks = CumulativeCarryOver / 1000000;
  1040. CumulativeCarryOver = CumulativeCarryOver % 1000000;
  1041. } else {
  1042. ExtraTicks = 0;
  1043. }
  1044. // Preserved for historic reasons. I can't think of a case where
  1045. // this is required!
  1046. CPUTCPTime[0] += MIN(200, ElapsedTicks);
  1047. LocalTime = TCPTime = CPUTCPTime[0];
  1048. if (ExtraTicks) {
  1049. // This makes the timer process 1 (or more) extra tick(s) when the
  1050. // timer fires next time. However, this will not make us process
  1051. // 2 ticks immediately after TCPTime is incremented by 2 ticks,
  1052. // which is going to take care of delayed-ack timers.
  1053. CPUTCPTime[0] += ExtraTicks;
  1054. TCPTime = CPUTCPTime[0];
  1055. }
  1056. // Set credits so that some more connections can increment the
  1057. // Initial Sequence Number, during the next 100 ms.
  1058. InterlockedExchange((PLONG)&g_Credits, g_MaxCredits);
  1059. Delta = GetDeltaTime();
  1060. // The increment made is (256)*(Time in milliseconds). This is really
  1061. // close to 25000 increment made originally every 100 ms.
  1062. if(Delta > 0) {
  1063. Delta *= 0x100;
  1064. InterlockedExchangeAdd((PLONG)&g_CurISN, Delta);
  1065. }
  1066. } else {
  1067. // This is the tick upto which we are going to process this time.
  1068. LocalTime = TCPTime;
  1069. }
  1070. CTEInterlockedAddUlong((PULONG)&TCBWalkCount, 1, &PendingFreeLock.Lock);
  1071. TCBHandle = DISPATCH_LEVEL;
  1072. // First compute the indexes of the timer wheels that we need to
  1073. // visit on this processor.
  1074. PerProcPartitions = NumTcbTablePartitions / KeNumberProcessors;
  1075. ExtraPartitions = NumTcbTablePartitions % KeNumberProcessors;
  1076. StartIndex = Processor * PerProcPartitions;
  1077. StartIndex += MIN(Processor, ExtraPartitions);
  1078. EndIndex = MIN(NumTcbTablePartitions, StartIndex + PerProcPartitions);
  1079. if (Processor < ExtraPartitions) {
  1080. EndIndex++;
  1081. }
  1082. // Now loop through the timer wheels.
  1083. for (i = StartIndex; i < EndIndex; i++) {
  1084. // For each timer wheel, tw_starttick stores the first time tick which
  1085. // needs to be checked. We loop from tw_starttick to the current time,
  1086. // and each time we figure out the slot corresponding to that tick,
  1087. // and visit all the TCBs on that slot's queue.
  1088. //
  1089. ushort CurrentSlot = COMPUTE_SLOT(TimerWheel[i].tw_starttick);
  1090. // In this for-loop, the termination condition is not j <= LocalTime,
  1091. // but j != LocalTime + 1. This is because TCPTime can wraparound, and
  1092. // tw_starttick may actually be higher that LocalTime.
  1093. // It is important to make sure that j is a uint, otherwise this logic
  1094. // does not hold.
  1095. for (j = TimerWheel[i].tw_starttick;
  1096. j != (LocalTime + 1);
  1097. j++, CurrentSlot = (CurrentSlot == (TIMER_WHEEL_SIZE - 1)) ? 0 : CurrentSlot + 1) {
  1098. Queue MarkerElement;
  1099. uint maxRexmitCnt;
  1100. ushort Slot;
  1101. // Our basic loop is going to be:
  1102. // Pull out a TCB from the timer slot queue. Process it. Put it
  1103. // back into the timer wheel if we need to, depending on if other
  1104. // timers need to be fired. The problem with this is if the TCB
  1105. // ends up falling in the same slot, we get into this loop where
  1106. // we pull the TCB out, process it, put it back into the current
  1107. // slot, pull it out again, process it, ad infinitum.
  1108. //
  1109. // So we introduce a dummy element called MarkerElement. We begin
  1110. // our processing by inserting this element into the head of the
  1111. // queue. Now we always pull out a TCB which the MarkerElement points
  1112. // to, process it, and then push it to the head of the timer slot
  1113. // queue. Since no TCBs are ever added to the timer slot queue after
  1114. // the MarkerElement (elements are always added to the head of the
  1115. // queue), MarkerElement will eventually point to the head of the
  1116. // timer slot queue, at which point we know that we are done.
  1117. CTEGetLockAtDPC(&TimerWheel[i].tw_lock);
  1118. PUSHQ(&TimerWheel[i].tw_timerslot[CurrentSlot], &MarkerElement);
  1119. CTEFreeLockFromDPC(&TimerWheel[i].tw_lock);
  1120. for (; ;) {
  1121. // First remove the tcb at the head of the list
  1122. CTEGetLockAtDPC(&TimerWheel[i].tw_lock);
  1123. // The list is empty if the marker points to timer slot
  1124. if (QNEXT(&MarkerElement) == &TimerWheel[i].tw_timerslot[CurrentSlot]) {
  1125. REMOVEQ(&MarkerElement);
  1126. CTEFreeLockFromDPC(&TimerWheel[i].tw_lock);
  1127. break;
  1128. }
  1129. CurrentTCB = STRUCT_OF(TCB, QNEXT(&MarkerElement), tcb_timerwheelq);
  1130. CTEFreeLockFromDPC(&TimerWheel[i].tw_lock);
  1131. CTEStructAssert(CurrentTCB, tcb);
  1132. CTEGetLockAtDPC(&CurrentTCB->tcb_lock);
  1133. // Someone may have removed this TCB before we reacquired the tcb
  1134. // lock. Check if it is still in the list and still in the same slot.
  1135. if (CurrentTCB->tcb_timerslot != CurrentSlot) {
  1136. CTEFreeLockFromDPC(&CurrentTCB->tcb_lock);
  1137. continue;
  1138. }
  1139. // This TCB may not be in the TCB table anymore.
  1140. // In that case, it should not be processed.
  1141. if (!(CurrentTCB->tcb_flags & IN_TCB_TABLE)) {
  1142. RemoveFromTimerWheel(CurrentTCB);
  1143. CTEFreeLockFromDPC(&CurrentTCB->tcb_lock);
  1144. continue;
  1145. }
  1146. // Check if this is firing at the current time. In case of keepalive
  1147. // timers (which fire after hours), sometimes TCBs may queue to the
  1148. // current slot but their firing time is not the current time.
  1149. // This if statement also does the lazy evaluation -- if all timers
  1150. // have been stopped on this TCB just remove the TCB out.
  1151. // Callers of STOP_TCB_TIMER_R never end up removing the TCB. That
  1152. // job is left to this routine.
  1153. if (CurrentTCB->tcb_timertime != j) {
  1154. MakeTimerStateConsistent(CurrentTCB, j);
  1155. ASSERT(CurrentTCB->tcb_timerslot < TIMER_WHEEL_SIZE);
  1156. RecomputeTimerState(CurrentTCB);
  1157. if (CurrentTCB->tcb_timertype == NO_TIMER) {
  1158. RemoveFromTimerWheel(CurrentTCB);
  1159. } else {
  1160. Slot = COMPUTE_SLOT(CurrentTCB->tcb_timertime);
  1161. RemoveAndInsertIntoTimerWheel(CurrentTCB, Slot);
  1162. }
  1163. CTEFreeLockFromDPC(&CurrentTCB->tcb_lock);
  1164. continue;
  1165. }
  1166. // If it's CLOSING or CLOSED, skip it.
  1167. if (CurrentTCB->tcb_state == TCB_CLOSED || CLOSING(CurrentTCB)) {
  1168. // CloseTCB will handle all outstanding requests.
  1169. // So, it is safe to remove the TCB from timer wheel.
  1170. RemoveFromTimerWheel(CurrentTCB);
  1171. CTEFreeLockFromDPC(&CurrentTCB->tcb_lock);
  1172. continue;
  1173. }
  1174. CheckTCBSends(CurrentTCB);
  1175. CheckTCBRcv(CurrentTCB);
  1176. // First check the rexmit timer.
  1177. if (TCB_TIMER_FIRED_R(CurrentTCB, RXMIT_TIMER, j)) {
  1178. StopTCBTimerR(CurrentTCB, RXMIT_TIMER);
  1179. // And it's fired. Figure out what to do now.
  1180. // Remove all SACK rcvd entries (per RFC 2018)
  1181. if ((CurrentTCB->tcb_tcpopts & TCP_FLAG_SACK) &&
  1182. CurrentTCB->tcb_SackRcvd) {
  1183. SackListEntry *Prev, *Current;
  1184. Prev = STRUCT_OF(SackListEntry, &CurrentTCB->tcb_SackRcvd, next);
  1185. Current = CurrentTCB->tcb_SackRcvd;
  1186. while (Current) {
  1187. Prev->next = Current->next;
  1188. CTEFreeMem(Current);
  1189. Current = Prev->next;
  1190. }
  1191. }
  1192. // If we've had too many retransits, abort now.
  1193. CurrentTCB->tcb_rexmitcnt++;
  1194. if (CurrentTCB->tcb_state == TCB_SYN_SENT) {
  1195. maxRexmitCnt = MaxConnectRexmitCount;
  1196. } else if (CurrentTCB->tcb_state == TCB_SYN_RCVD) {
  1197. // Save on locking. Though MaxConnectRexmitCountTmp may
  1198. // be changing, we are assured that we will not use
  1199. // more than the MaxConnectRexmitCount.
  1200. maxRexmitCnt = MIN(MaxConnectResponseRexmitCountTmp,
  1201. MaxConnectResponseRexmitCount);
  1202. if (SynAttackProtect) {
  1203. AddHalfOpenRetry(CurrentTCB->tcb_rexmitcnt);
  1204. }
  1205. } else {
  1206. maxRexmitCnt = MaxDataRexmitCount;
  1207. }
  1208. // If we've run out of retransmits or we're in FIN_WAIT2,
  1209. // time out.
  1210. if (CurrentTCB->tcb_rexmitcnt > maxRexmitCnt) {
  1211. ASSERT(CurrentTCB->tcb_state > TCB_LISTEN);
  1212. // This connection has timed out. Abort it. First
  1213. // reference him, then mark as closed, notify the
  1214. // user, and finally dereference and close him.
  1215. TimeoutTCB:
  1216. // This call may not be needed, but I've just added it
  1217. // for safety.
  1218. MakeTimerStateConsistent(CurrentTCB, j);
  1219. RecomputeTimerState(CurrentTCB);
  1220. ASSERT(CurrentTCB->tcb_timerslot < TIMER_WHEEL_SIZE);
  1221. if (CurrentTCB->tcb_timertype == NO_TIMER) {
  1222. RemoveFromTimerWheel(CurrentTCB);
  1223. } else {
  1224. Slot = COMPUTE_SLOT(CurrentTCB->tcb_timertime);
  1225. RemoveAndInsertIntoTimerWheel(CurrentTCB, Slot);
  1226. }
  1227. REFERENCE_TCB(CurrentTCB);
  1228. TryToCloseTCB(CurrentTCB, TCB_CLOSE_TIMEOUT, TCBHandle);
  1229. RemoveTCBFromConn(CurrentTCB);
  1230. NotifyOfDisc(CurrentTCB, NULL, TDI_TIMED_OUT, NULL);
  1231. CTEGetLockAtDPC(&CurrentTCB->tcb_lock);
  1232. DerefTCB(CurrentTCB, TCBHandle);
  1233. continue;
  1234. }
  1235. #if TRACE_EVENT
  1236. if ((CurrentTCB->tcb_state == TCB_SYN_SENT) ||
  1237. (CurrentTCB->tcb_state == TCB_ESTAB)) {
  1238. CPCallBack = TCPCPHandlerRoutine;
  1239. if (CPCallBack != NULL) {
  1240. ulong GroupType;
  1241. WMIInfo.wmi_destaddr = CurrentTCB->tcb_daddr;
  1242. WMIInfo.wmi_destport = CurrentTCB->tcb_dport;
  1243. WMIInfo.wmi_srcaddr = CurrentTCB->tcb_saddr;
  1244. WMIInfo.wmi_srcport = CurrentTCB->tcb_sport;
  1245. WMIInfo.wmi_size = 0;
  1246. WMIInfo.wmi_context = CurrentTCB->tcb_cpcontext;
  1247. if (CurrentTCB->tcb_state == TCB_ESTAB) {
  1248. GroupType = EVENT_TRACE_GROUP_TCPIP + EVENT_TRACE_TYPE_RETRANSMIT;
  1249. } else {
  1250. GroupType = EVENT_TRACE_GROUP_TCPIP + EVENT_TRACE_TYPE_RECONNECT;
  1251. }
  1252. (*CPCallBack) (GroupType, (PVOID)&WMIInfo, sizeof(WMIInfo), NULL);
  1253. }
  1254. }
  1255. #endif
  1256. CurrentTCB->tcb_rtt = 0; // Stop round trip time
  1257. // measurement.
  1258. // Figure out what our new retransmit timeout should be. We
  1259. // double it each time we get a retransmit, and reset it
  1260. // back when we get an ack for new data.
  1261. CurrentTCB->tcb_rexmit = MIN(CurrentTCB->tcb_rexmit << 1,
  1262. MAX_REXMIT_TO);
  1263. // Reset the sequence number, and reset the congestion
  1264. // window.
  1265. ResetSendNext(CurrentTCB, CurrentTCB->tcb_senduna);
  1266. if (!(CurrentTCB->tcb_flags & FLOW_CNTLD)) {
  1267. // Don't let the slow start threshold go below 2
  1268. // segments
  1269. CurrentTCB->tcb_ssthresh =
  1270. MAX(
  1271. MIN(
  1272. CurrentTCB->tcb_cwin,
  1273. CurrentTCB->tcb_sendwin
  1274. ) / 2,
  1275. (uint) CurrentTCB->tcb_mss * 2
  1276. );
  1277. CurrentTCB->tcb_cwin = CurrentTCB->tcb_mss;
  1278. } else {
  1279. // We're probing, and the probe timer has fired. We
  1280. // need to set the FORCE_OUTPUT bit here.
  1281. CurrentTCB->tcb_flags |= FORCE_OUTPUT;
  1282. }
  1283. // See if we need to probe for a PMTU black hole.
  1284. if (PMTUBHDetect &&
  1285. CurrentTCB->tcb_rexmitcnt == ((maxRexmitCnt + 1) / 2)) {
  1286. // We may need to probe for a black hole. If we're
  1287. // doing MTU discovery on this connection and we
  1288. // are retransmitting more than a minimum segment
  1289. // size, or we are probing for a PMTU BH already, turn
  1290. // off the DF flag and bump the probe count. If the
  1291. // probe count gets too big we'll assume it's not
  1292. // a PMTU black hole, and we'll try to switch the
  1293. // router.
  1294. if ((CurrentTCB->tcb_flags & PMTU_BH_PROBE) ||
  1295. ((CurrentTCB->tcb_opt.ioi_flags & IP_FLAG_DF) &&
  1296. (CurrentTCB->tcb_sendmax - CurrentTCB->tcb_senduna)
  1297. > 8)) {
  1298. // May need to probe. If we haven't exceeded our
  1299. // probe count, do so, otherwise restore those
  1300. // values.
  1301. if (CurrentTCB->tcb_bhprobecnt++ < 2) {
  1302. // We're going to probe. Turn on the flag,
  1303. // drop the MSS, and turn off the don't
  1304. // fragment bit.
  1305. if (!(CurrentTCB->tcb_flags & PMTU_BH_PROBE)) {
  1306. CurrentTCB->tcb_flags |= PMTU_BH_PROBE;
  1307. CurrentTCB->tcb_slowcount++;
  1308. CurrentTCB->tcb_fastchk |= TCP_FLAG_SLOW;
  1309. // Drop the MSS to the minimum. Save the old
  1310. // one in case we need it later.
  1311. CurrentTCB->tcb_mss = MIN(MAX_REMOTE_MSS -
  1312. CurrentTCB->tcb_opt.ioi_optlength,
  1313. CurrentTCB->tcb_remmss);
  1314. ASSERT(CurrentTCB->tcb_mss > 0);
  1315. CurrentTCB->tcb_cwin = CurrentTCB->tcb_mss;
  1316. CurrentTCB->tcb_opt.ioi_flags &= ~IP_FLAG_DF;
  1317. }
  1318. // Drop the rexmit count so we come here again,
  1319. // and don't retrigger DeadGWDetect.
  1320. CurrentTCB->tcb_rexmitcnt--;
  1321. } else {
  1322. // Too many probes. Stop probing, and allow fallover
  1323. // to the next gateway.
  1324. //
  1325. // Currently this code won't do BH probing on the 2nd
  1326. // gateway. The MSS will stay at the minimum size. This
  1327. // might be a little suboptimal, but it's
  1328. // easy to implement for the Sept. 95 service pack
  1329. // and will keep connections alive if possible.
  1330. //
  1331. // In the future we should investigate doing
  1332. // dead g/w detect on a per-connection basis, and then
  1333. // doing PMTU probing for each connection.
  1334. if (CurrentTCB->tcb_flags & PMTU_BH_PROBE) {
  1335. CurrentTCB->tcb_flags &= ~PMTU_BH_PROBE;
  1336. if (--(CurrentTCB->tcb_slowcount) == 0)
  1337. CurrentTCB->tcb_fastchk &=
  1338. ~TCP_FLAG_SLOW;
  1339. }
  1340. CurrentTCB->tcb_bhprobecnt = 0;
  1341. }
  1342. }
  1343. }
  1344. // Check to see if we're doing dead gateway detect. If we
  1345. // are, see if it's time to ask IP.
  1346. if (DeadGWDetect &&
  1347. (SYNC_STATE(CurrentTCB->tcb_state) ||
  1348. !(CurrentTCB->tcb_fastchk & TCP_FLAG_RST_WHILE_SYN)) &&
  1349. (CurrentTCB->tcb_rexmitcnt == ((maxRexmitCnt + 1) / 2)) &&
  1350. (CurrentTCB->tcb_rce != NULL)) {
  1351. uint CheckRouteFlag;
  1352. if (SYNC_STATE(CurrentTCB->tcb_state)) {
  1353. CheckRouteFlag = 0;
  1354. } else {
  1355. CheckRouteFlag = CHECK_RCE_ONLY;
  1356. }
  1357. (*LocalNetInfo.ipi_checkroute) (CurrentTCB->tcb_daddr,
  1358. CurrentTCB->tcb_saddr,
  1359. CurrentTCB->tcb_rce,
  1360. &CurrentTCB->tcb_opt,
  1361. CheckRouteFlag);
  1362. }
  1363. if (CurrentTCB->tcb_fastchk & TCP_FLAG_RST_WHILE_SYN) {
  1364. CurrentTCB->tcb_fastchk &= ~TCP_FLAG_RST_WHILE_SYN;
  1365. if (--(CurrentTCB->tcb_slowcount) == 0) {
  1366. CurrentTCB->tcb_fastchk &= ~TCP_FLAG_SLOW;
  1367. }
  1368. }
  1369. // Now handle the various cases.
  1370. switch (CurrentTCB->tcb_state) {
  1371. // In SYN-SENT or SYN-RCVD we'll need to retransmit
  1372. // the SYN.
  1373. case TCB_SYN_SENT:
  1374. case TCB_SYN_RCVD:
  1375. MakeTimerStateConsistent(CurrentTCB, j);
  1376. RecomputeTimerState( CurrentTCB );
  1377. if (CurrentTCB->tcb_timertype == NO_TIMER) {
  1378. RemoveFromTimerWheel(CurrentTCB);
  1379. } else {
  1380. Slot = COMPUTE_SLOT(CurrentTCB->tcb_timertime);
  1381. RemoveAndInsertIntoTimerWheel(CurrentTCB, Slot);
  1382. }
  1383. SendSYN(CurrentTCB, TCBHandle);
  1384. continue;
  1385. case TCB_FIN_WAIT1:
  1386. case TCB_CLOSING:
  1387. case TCB_LAST_ACK:
  1388. // The call to ResetSendNext (above) will have
  1389. // turned off the FIN_OUTSTANDING flag.
  1390. CurrentTCB->tcb_flags |= FIN_NEEDED;
  1391. case TCB_CLOSE_WAIT:
  1392. case TCB_ESTAB:
  1393. // In this state we have data to retransmit, unless
  1394. // the window is zero (in which case we need to
  1395. // probe), or we're just sending a FIN.
  1396. CheckTCBSends(CurrentTCB);
  1397. Delayed = TRUE;
  1398. DelayAction(CurrentTCB, NEED_OUTPUT);
  1399. break;
  1400. // If it's fired in TIME-WAIT, we're all done and
  1401. // can clean up. We'll call TryToCloseTCB even
  1402. // though he's already sort of closed. TryToCloseTCB
  1403. // will figure this out and do the right thing.
  1404. case TCB_TIME_WAIT:
  1405. MakeTimerStateConsistent(CurrentTCB, j);
  1406. RecomputeTimerState(CurrentTCB);
  1407. if (CurrentTCB->tcb_timertype == NO_TIMER) {
  1408. RemoveFromTimerWheel(CurrentTCB);
  1409. } else {
  1410. Slot = COMPUTE_SLOT(CurrentTCB->tcb_timertime);
  1411. RemoveAndInsertIntoTimerWheel(CurrentTCB, Slot);
  1412. }
  1413. TryToCloseTCB(CurrentTCB, TCB_CLOSE_SUCCESS,
  1414. TCBHandle);
  1415. continue;
  1416. default:
  1417. break;
  1418. }
  1419. }
  1420. // Now check the SWS deadlock timer..
  1421. if (TCB_TIMER_FIRED_R(CurrentTCB, SWS_TIMER, j)) {
  1422. StopTCBTimerR(CurrentTCB, SWS_TIMER);
  1423. // And it's fired. Force output now.
  1424. CurrentTCB->tcb_flags |= FORCE_OUTPUT;
  1425. Delayed = TRUE;
  1426. DelayAction(CurrentTCB, NEED_OUTPUT);
  1427. }
  1428. // Check the push data timer.
  1429. if (TCB_TIMER_FIRED_R(CurrentTCB, PUSH_TIMER, j)) {
  1430. StopTCBTimerR(CurrentTCB, PUSH_TIMER);
  1431. // It's fired.
  1432. PushData(CurrentTCB, FALSE);
  1433. Delayed = TRUE;
  1434. }
  1435. // Check the delayed ack timer.
  1436. if (TCB_TIMER_FIRED_R(CurrentTCB, DELACK_TIMER, j)) {
  1437. StopTCBTimerR(CurrentTCB, DELACK_TIMER);
  1438. // And it's fired. Set up to send an ACK.
  1439. Delayed = TRUE;
  1440. DelayAction(CurrentTCB, NEED_ACK);
  1441. }
  1442. if (TCB_TIMER_FIRED_R(CurrentTCB, KA_TIMER, j)) {
  1443. StopTCBTimerR(CurrentTCB, KA_TIMER);
  1444. // Finally check the keepalive timer.
  1445. if (SYNC_STATE(CurrentTCB->tcb_state) &&
  1446. (CurrentTCB->tcb_flags & KEEPALIVE) &&
  1447. CurrentTCB->tcb_conn != NULL) {
  1448. if (CurrentTCB->tcb_kacount < MaxDataRexmitCount) {
  1449. MakeTimerStateConsistent(CurrentTCB, j);
  1450. RecomputeTimerState( CurrentTCB );
  1451. START_TCB_TIMER_R(CurrentTCB, KA_TIMER,
  1452. CurrentTCB->tcb_conn->tc_tcbkainterval);
  1453. ASSERT(CurrentTCB->tcb_timertype != NO_TIMER);
  1454. ASSERT(CurrentTCB->tcb_timerslot < TIMER_WHEEL_SIZE);
  1455. SendKA(CurrentTCB, TCBHandle);
  1456. continue;
  1457. } else {
  1458. goto TimeoutTCB;
  1459. }
  1460. }
  1461. }
  1462. if (TCB_TIMER_FIRED_R(CurrentTCB, CONN_TIMER, j)) {
  1463. StopTCBTimerR(CurrentTCB, CONN_TIMER);
  1464. // If this is an active open connection in SYN-SENT or SYN-RCVD,
  1465. // or we have a FIN pending, check the connect timer.
  1466. if (CurrentTCB->tcb_flags & (ACTIVE_OPEN | FIN_NEEDED | FIN_SENT)) {
  1467. if (CurrentTCB->tcb_connreq) {
  1468. // The connection timer has timed out.
  1469. CurrentTCB->tcb_flags |= NEED_RST;
  1470. MakeTimerStateConsistent(CurrentTCB, j);
  1471. RecomputeTimerState( CurrentTCB );
  1472. START_TCB_TIMER_R(CurrentTCB, RXMIT_TIMER,
  1473. CurrentTCB->tcb_rexmit);
  1474. ASSERT(CurrentTCB->tcb_timertype != NO_TIMER);
  1475. ASSERT(CurrentTCB->tcb_timerslot < TIMER_WHEEL_SIZE);
  1476. TryToCloseTCB(CurrentTCB, TCB_CLOSE_TIMEOUT,
  1477. TCBHandle);
  1478. continue;
  1479. }
  1480. }
  1481. }
  1482. //
  1483. // Check to see if we have to notify the
  1484. // automatic connection driver about this
  1485. // connection.
  1486. //
  1487. if (TCB_TIMER_FIRED_R(CurrentTCB, ACD_TIMER, j)) {
  1488. BOOLEAN fEnabled;
  1489. StopTCBTimerR(CurrentTCB, ACD_TIMER);
  1490. MakeTimerStateConsistent(CurrentTCB, j);
  1491. RecomputeTimerState(CurrentTCB);
  1492. ASSERT(CurrentTCB->tcb_timerslot < TIMER_WHEEL_SIZE);
  1493. if (CurrentTCB->tcb_timertype == NO_TIMER) {
  1494. RemoveFromTimerWheel(CurrentTCB);
  1495. } else {
  1496. Slot = COMPUTE_SLOT(CurrentTCB->tcb_timertime);
  1497. RemoveAndInsertIntoTimerWheel(CurrentTCB, Slot);
  1498. }
  1499. //
  1500. // Determine if we need to notify
  1501. // the automatic connection driver.
  1502. //
  1503. CTEGetLockAtDPC(&AcdDriverG.SpinLock);
  1504. fEnabled = AcdDriverG.fEnabled;
  1505. CTEFreeLockFromDPC(&AcdDriverG.SpinLock);
  1506. if (fEnabled)
  1507. TCPNoteNewConnection(CurrentTCB, TCBHandle);
  1508. else
  1509. CTEFreeLockFromDPC(&CurrentTCB->tcb_lock);
  1510. continue;
  1511. }
  1512. // Timer isn't running, or didn't fire.
  1513. MakeTimerStateConsistent(CurrentTCB, j);
  1514. ASSERT(CurrentTCB->tcb_timerslot < TIMER_WHEEL_SIZE);
  1515. RecomputeTimerState( CurrentTCB );
  1516. if (CurrentTCB->tcb_timertype == NO_TIMER) {
  1517. RemoveFromTimerWheel(CurrentTCB);
  1518. } else {
  1519. Slot = COMPUTE_SLOT(CurrentTCB->tcb_timertime);
  1520. RemoveAndInsertIntoTimerWheel(CurrentTCB, Slot);
  1521. }
  1522. CTEFreeLockFromDPC(&CurrentTCB->tcb_lock);
  1523. }
  1524. }
  1525. TimerWheel[i].tw_starttick = LocalTime + 1;
  1526. }
  1527. if (SynAttackProtect) {
  1528. ProcessSynTcbs(Processor);
  1529. }
  1530. // Check if it is about time to remove TCBs off TWQueue
  1531. if (Processor == 0) {
  1532. for (i = 0; i < NumTcbTablePartitions; i++) {
  1533. BOOLEAN Done = FALSE, firstime = TRUE;
  1534. TWTCB *CurrentTCB = NULL;
  1535. Queue *tmp;
  1536. CTEGetLockAtDPC(&pTWTCBTableLock[i]);
  1537. while (!Done) {
  1538. if (!EMPTYQ(&TWQueue[i])) {
  1539. PEEKQ(&TWQueue[i], CurrentTCB, TWTCB, twtcb_TWQueue);
  1540. CTEStructAssert(CurrentTCB, twtcb);
  1541. ASSERT(CurrentTCB->twtcb_flags & IN_TWQUEUE);
  1542. //Decrement its life time and the last TCB in the queue
  1543. //because this is a timer delta queue!
  1544. if (firstime) {
  1545. TWTCB *PrvTCB;
  1546. if (CurrentTCB->twtcb_rexmittimer > 0)
  1547. CurrentTCB->twtcb_rexmittimer--;
  1548. tmp = TWQueue[i].q_prev;
  1549. PrvTCB = STRUCT_OF(TWTCB, tmp, twtcb_TWQueue);
  1550. PrvTCB->twtcb_delta--;
  1551. firstime = FALSE;
  1552. }
  1553. } else {
  1554. Done = TRUE;
  1555. CurrentTCB = NULL;
  1556. }
  1557. if (CurrentTCB) {
  1558. // Check the rexmit timer.
  1559. if ((CurrentTCB->twtcb_rexmittimer <= 0)) {
  1560. // Timer fired close and remove this tcb
  1561. RemoveTWTCB(CurrentTCB, i);
  1562. numtwtimedout++;
  1563. FreeTWTCB(CurrentTCB);
  1564. } else {
  1565. Done = TRUE;
  1566. }
  1567. } else
  1568. break;
  1569. } //while
  1570. CTEFreeLockFromDPC(&pTWTCBTableLock[i]);
  1571. } //for
  1572. } //proc == 0
  1573. // See if we need to process the delay queues as part of deadman
  1574. // processing. We do this now because we want to restart the timer before
  1575. // processing the delay queues, in case that takes a while. If we make
  1576. // this check while the timer is running we'd have to lock, so we'll check
  1577. // and save the result now before we start the timer.
  1578. if (Processor == 0) {
  1579. if (DeadmanTicks <= LocalTime) {
  1580. ProcessDelayQ = TRUE;
  1581. DeadmanTicks = NUM_DEADMAN_TIME+LocalTime;
  1582. }
  1583. }
  1584. // Now check the pending free list. If it's not null, walk down the
  1585. // list and decrement the walk count. If the count goes below 2, pull it
  1586. // from the list. If the count goes to 0, free the TCB. If the count is
  1587. // at 1 it'll be freed by whoever called RemoveTCB.
  1588. if (Processor == 0) {
  1589. CTEGetLockAtDPC(&PendingFreeLock.Lock);
  1590. if (PendingFreeList != NULL) {
  1591. TCB *PrevTCB;
  1592. PrevTCB = STRUCT_OF(TCB, &PendingFreeList, tcb_delayq.q_next);
  1593. do {
  1594. CurrentTCB = (TCB *) PrevTCB->tcb_delayq.q_next;
  1595. CTEStructAssert(CurrentTCB, tcb);
  1596. CurrentTCB->tcb_walkcount--;
  1597. if (CurrentTCB->tcb_walkcount <= 0) {
  1598. *(TCB **) & PrevTCB->tcb_delayq.q_next =
  1599. (TCB *) CurrentTCB->tcb_delayq.q_next;
  1600. FreeTCB(CurrentTCB);
  1601. } else {
  1602. PrevTCB = CurrentTCB;
  1603. }
  1604. } while (PrevTCB->tcb_delayq.q_next != NULL);
  1605. }
  1606. if (PendingSynFreeList != NULL) {
  1607. SYNTCB *PrevTCB,*CurrentTCB;
  1608. //we use q_prev in link q so that QNEXT will still walk to the
  1609. //next syntcb in processsyntcb, while this tcb is on SynFreeLis.t
  1610. PrevTCB = STRUCT_OF(SYNTCB, &PendingSynFreeList, syntcb_link.q_prev);
  1611. do {
  1612. CurrentTCB = (SYNTCB *) PrevTCB->syntcb_link.q_prev;
  1613. CTEStructAssert(CurrentTCB, syntcb);
  1614. CurrentTCB->syntcb_walkcount--;
  1615. if (CurrentTCB->syntcb_walkcount <= 0) {
  1616. *(SYNTCB **) & PrevTCB->syntcb_link.q_prev =
  1617. (SYNTCB *) CurrentTCB->syntcb_link.q_prev;
  1618. FreeSynTCB(CurrentTCB);
  1619. } else {
  1620. PrevTCB = CurrentTCB;
  1621. }
  1622. } while (PrevTCB->syntcb_link.q_prev != NULL);
  1623. }
  1624. CTEFreeLockFromDPC(&PendingFreeLock.Lock);
  1625. // Do AddrCheckTable cleanup
  1626. if (AddrCheckTable) {
  1627. TCPAddrCheckElement *Temp;
  1628. CTEGetLockAtDPC(&AddrObjTableLock.Lock);
  1629. for (Temp = AddrCheckTable; Temp < AddrCheckTable + NTWMaxConnectCount; Temp++) {
  1630. if (Temp->TickCount > 0) {
  1631. if ((--(Temp->TickCount)) == 0) {
  1632. Temp->SourceAddress = 0;
  1633. }
  1634. }
  1635. }
  1636. CTEFreeLockFromDPC(&AddrObjTableLock.Lock);
  1637. }
  1638. }
  1639. CTEInterlockedAddUlong((PULONG)&TCBWalkCount, (ULONG)-1, &PendingFreeLock.Lock);
  1640. if ((Processor == 0) &&
  1641. TCPTIME_LTE((LastDelayQPartitionTime + DQ_PARTITION_TIME), TCPTime)) {
  1642. LastDelayQPartitionTime = TCPTime;
  1643. PartitionDelayQProcessing(TRUE);
  1644. ProcessDelayQ = TRUE;
  1645. }
  1646. if (ProcessDelayQ) {
  1647. ProcessTCBDelayQ(DISPATCH_LEVEL, TRUE);
  1648. } else if (Delayed) {
  1649. ProcessPerCpuTCBDelayQ(Processor, DISPATCH_LEVEL, NULL, NULL);
  1650. }
  1651. }
  1652. //* SetTCBMTU - Set TCB MTU values.
  1653. //
  1654. // A function called by TCBWalk to set the MTU values of all TCBs using
  1655. // a particular path.
  1656. //
  1657. // Input: CheckTCB - TCB to be checked.
  1658. // DestPtr - Ptr to destination address.
  1659. // SrcPtr - Ptr to source address.
  1660. // MTUPtr - Ptr to new MTU.
  1661. //
  1662. // Returns: TRUE.
  1663. //
  1664. uint
  1665. SetTCBMTU(TCB * CheckTCB, void *DestPtr, void *SrcPtr, void *MTUPtr)
  1666. {
  1667. IPAddr DestAddr = *(IPAddr *) DestPtr;
  1668. IPAddr SrcAddr = *(IPAddr *) SrcPtr;
  1669. CTELockHandle TCBHandle;
  1670. CTEStructAssert(CheckTCB, tcb);
  1671. CTEGetLock(&CheckTCB->tcb_lock, &TCBHandle);
  1672. if (IP_ADDR_EQUAL(CheckTCB->tcb_daddr, DestAddr) &&
  1673. IP_ADDR_EQUAL(CheckTCB->tcb_saddr, SrcAddr) &&
  1674. (CheckTCB->tcb_opt.ioi_flags & IP_FLAG_DF)) {
  1675. uint MTU = *(uint *)MTUPtr - CheckTCB->tcb_opt.ioi_optlength;
  1676. CheckTCB->tcb_mss = (ushort) MIN(MTU, (uint) CheckTCB->tcb_remmss);
  1677. ASSERT(CheckTCB->tcb_mss > 0);
  1678. ValidateMSS(CheckTCB);
  1679. //
  1680. // Reset the Congestion Window if necessary
  1681. //
  1682. if (CheckTCB->tcb_cwin < CheckTCB->tcb_mss) {
  1683. CheckTCB->tcb_cwin = CheckTCB->tcb_mss;
  1684. //
  1685. // Make sure the slow start threshold is at least
  1686. // 2 segments
  1687. //
  1688. if (CheckTCB->tcb_ssthresh < ((uint) CheckTCB->tcb_mss * 2)) {
  1689. CheckTCB->tcb_ssthresh = CheckTCB->tcb_mss * 2;
  1690. }
  1691. }
  1692. }
  1693. CTEFreeLock(&CheckTCB->tcb_lock, TCBHandle);
  1694. return TRUE;
  1695. }
  1696. //* DeleteTCBWithSrc - Delete tcbs with a particular src address.
  1697. //
  1698. // A function called by TCBWalk to delete all TCBs with a particular source
  1699. // address.
  1700. //
  1701. // Input: CheckTCB - TCB to be checked.
  1702. // AddrPtr - Ptr to address.
  1703. //
  1704. // Returns: FALSE if CheckTCB is to be deleted, TRUE otherwise.
  1705. //
  1706. uint
  1707. DeleteTCBWithSrc(TCB * CheckTCB, void *AddrPtr, void *Unused1, void *Unused3)
  1708. {
  1709. IPAddr Addr = *(IPAddr *) AddrPtr;
  1710. CTEStructAssert(CheckTCB, tcb);
  1711. if (IP_ADDR_EQUAL(CheckTCB->tcb_saddr, Addr))
  1712. return FALSE;
  1713. else
  1714. return TRUE;
  1715. }
  1716. //* TCBWalk - Walk the TCBs in the table, and call a function for each of them.
  1717. //
  1718. // Called when we need to repetively do something to each TCB in the table.
  1719. // We call the specified function with a pointer to the TCB and the input
  1720. // context for each TCB in the table. If the function returns FALSE, we
  1721. // delete the TCB.
  1722. //
  1723. // Input: CallRtn - Routine to be called.
  1724. // Context1 - Context to pass to CallRtn.
  1725. // Context2 - Second context to pass to call routine.
  1726. // Context3 - Third context to pass to call routine.
  1727. //
  1728. // Returns: Nothing.
  1729. //
  1730. void
  1731. TCBWalk(uint(*CallRtn) (struct TCB *, void *, void *, void *), void *Context1,
  1732. void *Context2, void *Context3)
  1733. {
  1734. uint i, j;
  1735. TCB *CurTCB;
  1736. CTELockHandle Handle, TCBHandle;
  1737. // Loop through each bucket in the table, going down the chain of
  1738. // TCBs on the bucket. For each one call CallRtn.
  1739. for (j = 0; j < NumTcbTablePartitions; j++) {
  1740. CTEGetLock(&pTCBTableLock[j], &Handle);
  1741. for (i = j * PerPartitionSize; i < (j + 1) * PerPartitionSize; i++) {
  1742. CurTCB = TCBTable[i];
  1743. // Walk down the chain on this bucket.
  1744. while (CurTCB != NULL) {
  1745. if (!(*CallRtn) (CurTCB, Context1, Context2, Context3)) {
  1746. // He failed the call. Notify the client and close the
  1747. // TCB.
  1748. CTEGetLock(&CurTCB->tcb_lock, &TCBHandle);
  1749. ASSERT(CurTCB->tcb_partition == j);
  1750. if (!CLOSING(CurTCB)) {
  1751. REFERENCE_TCB(CurTCB);
  1752. CTEFreeLock(&pTCBTableLock[j], TCBHandle);
  1753. TryToCloseTCB(CurTCB, TCB_CLOSE_ABORTED, Handle);
  1754. RemoveTCBFromConn(CurTCB);
  1755. if (CurTCB->tcb_state != TCB_TIME_WAIT)
  1756. NotifyOfDisc(CurTCB, NULL, TDI_CONNECTION_ABORTED,
  1757. NULL);
  1758. CTEGetLock(&CurTCB->tcb_lock, &TCBHandle);
  1759. DerefTCB(CurTCB, TCBHandle);
  1760. CTEGetLock(&pTCBTableLock[j], &Handle);
  1761. } else
  1762. CTEFreeLock(&CurTCB->tcb_lock, TCBHandle);
  1763. CurTCB = FindNextTCB(i, CurTCB);
  1764. } else {
  1765. CurTCB = CurTCB->tcb_next;
  1766. }
  1767. }
  1768. }
  1769. CTEFreeLock(&pTCBTableLock[j], Handle);
  1770. }
  1771. }
  1772. void
  1773. DerefSynTCB(SYNTCB * SynTCB, CTELockHandle TCBHandle)
  1774. {
  1775. ASSERT(SynTCB->syntcb_refcnt != 0);
  1776. if (--SynTCB->syntcb_refcnt == 0) {
  1777. CTEGetLockAtDPC(&PendingFreeLock.Lock);
  1778. if (TCBWalkCount) {
  1779. ASSERT(!(SynTCB->syntcb_flags & IN_SYNTCB_TABLE));
  1780. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,
  1781. "Freeing to synpendinglist %x\n",SynTCB));
  1782. //we use q_prev in link q so that QNEXT will still walk to the
  1783. //next syntcb in processsyntcb, while this tcb is on SynFreeLis.t
  1784. SynTCB->syntcb_walkcount = TCBWalkCount + 1;
  1785. *(SYNTCB **) &SynTCB->syntcb_link.q_prev = PendingSynFreeList;
  1786. PendingSynFreeList = SynTCB;
  1787. CTEFreeLockFromDPC(&PendingFreeLock.Lock);
  1788. CTEFreeLock(&SynTCB->syntcb_lock, TCBHandle);
  1789. } else {
  1790. CTEFreeLockFromDPC(&PendingFreeLock.Lock);
  1791. CTEFreeLock(&SynTCB->syntcb_lock, TCBHandle);
  1792. FreeSynTCB(SynTCB);
  1793. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"syntcb freed %x\n",SynTCB));
  1794. }
  1795. } else {
  1796. CTEFreeLock(&SynTCB->syntcb_lock, TCBHandle);
  1797. }
  1798. }
  1799. TCB *
  1800. RemoveAndInsertSynTCB(SYNTCB *SynTCB, CTELockHandle TCBHandle)
  1801. {
  1802. TCB *NewTCB;
  1803. LOGICAL Inserted;
  1804. NewTCB = AllocTCB();
  1805. KdPrintEx((DPFLTR_TCPIP_ID, DPFLTR_INFO_LEVEL,"reminsertsyn: %x %x\n",SynTCB,NewTCB));
  1806. if (NewTCB) {
  1807. // Initialize the full TCB to replace this SYN TCB.
  1808. NewTCB->tcb_dport = SynTCB->syntcb_dport;
  1809. NewTCB->tcb_sport = SynTCB->syntcb_sport;
  1810. NewTCB->tcb_daddr = SynTCB->syntcb_daddr;
  1811. NewTCB->tcb_saddr = SynTCB->syntcb_saddr;
  1812. NewTCB->tcb_rcvnext = SynTCB->syntcb_rcvnext;
  1813. NewTCB->tcb_senduna = SynTCB->syntcb_sendnext - 1;
  1814. NewTCB->tcb_sendmax = SynTCB->syntcb_sendnext;
  1815. NewTCB->tcb_sendnext = SynTCB->syntcb_sendnext;
  1816. NewTCB->tcb_sendwin = SynTCB->syntcb_sendwin;
  1817. NewTCB->tcb_defaultwin = SynTCB->syntcb_defaultwin;
  1818. NewTCB->tcb_phxsum = PHXSUM(SynTCB->syntcb_saddr, SynTCB->syntcb_daddr,
  1819. PROTOCOL_TCP, 0);
  1820. NewTCB->tcb_rtt = 0;
  1821. NewTCB->tcb_smrtt = 0;
  1822. NewTCB->tcb_delta = MS_TO_TICKS(6000);
  1823. NewTCB->tcb_rexmit = MS_TO_TICKS(3000);
  1824. NewTCB->tcb_mss = SynTCB->syntcb_mss;
  1825. NewTCB->tcb_remmss = SynTCB->syntcb_remmss;
  1826. NewTCB->tcb_rcvwin = SynTCB->syntcb_defaultwin;
  1827. NewTCB->tcb_rcvwinscale = SynTCB->syntcb_rcvwinscale;
  1828. NewTCB->tcb_sndwinscale = SynTCB->syntcb_sndwinscale;
  1829. NewTCB->tcb_tcpopts = SynTCB->syntcb_tcpopts;
  1830. NewTCB->tcb_state = TCB_SYN_RCVD;
  1831. NewTCB->tcb_connreq = NULL;
  1832. NewTCB->tcb_refcnt = 0;
  1833. REFERENCE_TCB(NewTCB);
  1834. NewTCB->tcb_fastchk |= TCP_FLAG_ACCEPT_PENDING;
  1835. NewTCB->tcb_flags |= (SynTCB->syntcb_flags & SYNTCB_SHARED_FLAGS);
  1836. NewTCB->tcb_tsrecent = SynTCB->syntcb_tsrecent;
  1837. NewTCB->tcb_tsupdatetime = SynTCB->syntcb_tsupdatetime;
  1838. NewTCB->tcb_rexmitcnt = 0;
  1839. ClassifyPacket(NewTCB);
  1840. (*LocalNetInfo.ipi_initopts) (&NewTCB->tcb_opt);
  1841. NewTCB->tcb_opt.ioi_ttl = SynTCB->syntcb_ttl;
  1842. CTEFreeLockFromDPC(&SynTCB->syntcb_lock);
  1843. Inserted = InsertTCB(NewTCB, FALSE);
  1844. CTEGetLockAtDPC(&NewTCB->tcb_lock);
  1845. if (!Inserted || CLOSING(NewTCB)) {
  1846. if (!CLOSING(NewTCB)) {
  1847. TryToCloseTCB(NewTCB, TCB_CLOSE_ABORTED, DISPATCH_LEVEL);
  1848. CTEGetLockAtDPC(&NewTCB->tcb_lock);
  1849. }
  1850. DerefTCB(NewTCB, DISPATCH_LEVEL);
  1851. NewTCB = NULL;
  1852. CTEGetLockAtDPC(&SynTCB->syntcb_lock);
  1853. } else {
  1854. // No deletion is pending on the TCB, so just drop its refcnt
  1855. // and return with its lock held.
  1856. DEREFERENCE_TCB(NewTCB);
  1857. // Start the timer on the TCB that just got created.
  1858. // The only timer that needs to be transfered across is the
  1859. // retransmit timer. The number of ticks remaining till the
  1860. // next retransmission of SYN+ACK on the SYN TCB is used
  1861. // to start the TCB timer.
  1862. CTEGetLockAtDPC(&SynTCB->syntcb_lock);
  1863. START_TCB_TIMER_R(NewTCB, RXMIT_TIMER,
  1864. (SynTCB->syntcb_rexmittimer < 2)
  1865. ? 2 : SynTCB->syntcb_rexmittimer);
  1866. }
  1867. } else {
  1868. // Could not convert it to a regular TCB, hence notify.
  1869. TcpInvokeCcb(TCP_CONN_SYN_RCVD, TCP_CONN_CLOSED,
  1870. &SynTCB->syntcb_addrbytes, 0);
  1871. DropHalfOpenTCB(SynTCB->syntcb_rexmitcnt);
  1872. }
  1873. // Drop the initial reference to the SYN TCB.
  1874. DerefSynTCB(SynTCB, TCBHandle);
  1875. return NewTCB;
  1876. }
  1877. //* FindSynTCB - Find a SynTCB in the syntcb table. Convert to
  1878. // full TCB if necessary and indicates what actions should
  1879. // be taken with the returned TCB
  1880. //
  1881. // Called when we need to find a SynTCB in the synTCB table.
  1882. // Note : No locks are held on entry. On exit tcb lock will be held
  1883. //
  1884. // Input: Src - Source IP address of TCB to be found.
  1885. // Dest - Dest. "" "" "" "" "" "" "".
  1886. // DestPort - Destination port of TCB to be found.
  1887. // SrcPort - Source port of TCB to be found.
  1888. // RcvInfo - Received segment information.
  1889. // Size - Size of payload in TCP segment.
  1890. // index - The index for the SynTCBTable.
  1891. // Output: Action - Action upon return of this function that
  1892. // should be performed. Flags are
  1893. // SYN_PKT_SEND_RST
  1894. // SYN_PKT_RST_RCVD
  1895. // SYN_PKT_DROP
  1896. // Flags are defined in tcb.h
  1897. //
  1898. // Returns: Pointer to synTCB found, or NULL if none.
  1899. //
  1900. TCB *
  1901. FindSynTCB(IPAddr Src, IPAddr Dest,
  1902. ushort DestPort, ushort SrcPort,
  1903. TCPRcvInfo RcvInfo, uint Size,
  1904. uint index,
  1905. PUCHAR Action)
  1906. {
  1907. ulong Partition;
  1908. SYNTCB *SynTCB;
  1909. Queue *Scan;
  1910. TCB * RcvTCB;
  1911. uchar rexmitCnt;
  1912. Partition = GET_PARTITION(index);
  1913. *Action = 0;
  1914. CTEGetLockAtDPC(&pSynTCBTableLock[Partition]);
  1915. for (Scan = QHEAD(&SYNTCBTable[index]);
  1916. Scan != QEND(&SYNTCBTable[index]);
  1917. Scan = QNEXT(Scan)) {
  1918. SynTCB = QSTRUCT(SYNTCB, Scan, syntcb_link);
  1919. CTEStructAssert(SynTCB, syntcb);
  1920. if (IP_ADDR_EQUAL(SynTCB->syntcb_daddr, Dest) &&
  1921. SynTCB->syntcb_dport == DestPort &&
  1922. IP_ADDR_EQUAL(SynTCB->syntcb_saddr, Src) &&
  1923. SynTCB->syntcb_sport == SrcPort) {
  1924. SeqNum SendUna = SynTCB->syntcb_sendnext - 1;
  1925. SeqNum SendMax = SynTCB->syntcb_sendnext;
  1926. CTEGetLockAtDPC(&SynTCB->syntcb_lock);
  1927. rexmitCnt = SynTCB->syntcb_rexmitcnt;
  1928. // 1st, we need to verify the sequence number.
  1929. // RcvWindow should be 0 here.
  1930. if (!SEQ_EQ(RcvInfo.tri_seq, SynTCB->syntcb_rcvnext)) {
  1931. CTEFreeLockFromDPC(&SynTCB->syntcb_lock);
  1932. CTEFreeLockFromDPC(&pSynTCBTableLock[Partition]);
  1933. // Normally, we should send an ACK back but we
  1934. // will wait for the retransmit timer to expire.
  1935. *Action = SYN_PKT_DROP;
  1936. return NULL;
  1937. }
  1938. // 2nd, we check for RST, if set, we terminate connection.
  1939. if (RcvInfo.tri_flags & TCP_FLAG_RST) {
  1940. *Action = SYN_PKT_RST_RCVD;
  1941. // 3rd, security and precedence check, does not apply
  1942. // 4th, check for SYN
  1943. } else if (RcvInfo.tri_flags & TCP_FLAG_SYN) {
  1944. *Action = SYN_PKT_SEND_RST;
  1945. // 5th, check for ACK
  1946. } else if (!(RcvInfo.tri_flags & TCP_FLAG_ACK)) {
  1947. // We return right here because in this case we
  1948. // actually do not want to change the SynTCB
  1949. CTEFreeLockFromDPC(&SynTCB->syntcb_lock);
  1950. CTEFreeLockFromDPC(&pSynTCBTableLock[Partition]);
  1951. *Action = SYN_PKT_DROP;
  1952. return NULL;
  1953. // 5th, continue to check for validity of ACK
  1954. } else if (SEQ_GTE(SendUna, RcvInfo.tri_ack) ||
  1955. SEQ_GT(RcvInfo.tri_ack, SendMax)) {
  1956. *Action = SYN_PKT_SEND_RST;
  1957. }
  1958. // At this point, if some action needs to be taken
  1959. // the SynTCB needs to be killed
  1960. if (*Action) {
  1961. SynTCB->syntcb_flags &= ~IN_SYNTCB_TABLE;
  1962. REMOVEQ(&SynTCB->syntcb_link);
  1963. CTEFreeLockFromDPC(&pSynTCBTableLock[Partition]);
  1964. TcpInvokeCcb(TCP_CONN_SYN_RCVD, TCP_CONN_CLOSED,
  1965. &SynTCB->syntcb_addrbytes, 0);
  1966. DropHalfOpenTCB(SynTCB->syntcb_rexmitcnt);
  1967. DerefSynTCB(SynTCB, DISPATCH_LEVEL);
  1968. return NULL;
  1969. }
  1970. // If we got here we know we have to convert the SynTCB to
  1971. // a full TCB
  1972. SynTCB->syntcb_flags &= ~IN_SYNTCB_TABLE;
  1973. REMOVEQ(&SynTCB->syntcb_link);
  1974. CTEFreeLockFromDPC(&pSynTCBTableLock[Partition]);
  1975. RcvTCB = RemoveAndInsertSynTCB(SynTCB, DISPATCH_LEVEL);
  1976. if (RcvTCB == NULL) {
  1977. // Could not allocate a TCB.
  1978. *Action = SYN_PKT_SEND_RST;
  1979. return NULL;
  1980. }
  1981. return RcvTCB;
  1982. } // end of if we found a matching SynTCB
  1983. } // end of for loop scanning for SynTCBs
  1984. CTEFreeLockFromDPC(&pSynTCBTableLock[Partition]);
  1985. // no matching TCB
  1986. return NULL;
  1987. }
  1988. //* FindTCB - Find a TCB in the tcb table.
  1989. //
  1990. // Called when we need to find a TCB in the TCB table. We take a quick
  1991. // look at the last TCB we found, and if it matches we return it, lock held. Otherwise
  1992. // we hash into the TCB table and look for it.
  1993. // Note : No locks are held on entry. On exit tcb lock will be held
  1994. //
  1995. // Input: Src - Source IP address of TCB to be found.
  1996. // Dest - Dest. "" "" "" "" "" "" ""
  1997. // DestPort - Destination port of TCB to be found.
  1998. // SrcPort - Source port of TCB to be found.
  1999. //
  2000. // Returns: Pointer to TCB found, or NULL if none.
  2001. //
  2002. TCB *
  2003. FindTCB(IPAddr Src, IPAddr Dest, ushort DestPort, ushort SrcPort,
  2004. CTELockHandle * Handle, BOOLEAN AtDispatch, uint * hash)
  2005. {
  2006. TCB *FoundTCB;
  2007. ulong index, Partition;
  2008. *hash = index = TCB_HASH(Dest, Src, DestPort, SrcPort);
  2009. Partition = GET_PARTITION(index);
  2010. if (AtDispatch) {
  2011. CTEGetLockAtDPC(&pTCBTableLock[Partition]);
  2012. } else {
  2013. CTEGetLock(&pTCBTableLock[Partition], Handle);
  2014. }
  2015. // Didn't find it in our 1 element cache.
  2016. FoundTCB = TCBTable[index];
  2017. while (FoundTCB != NULL) {
  2018. CTEStructAssert(FoundTCB, tcb);
  2019. if (IP_ADDR_EQUAL(FoundTCB->tcb_daddr, Dest) &&
  2020. FoundTCB->tcb_dport == DestPort &&
  2021. IP_ADDR_EQUAL(FoundTCB->tcb_saddr, Src) &&
  2022. FoundTCB->tcb_sport == SrcPort) {
  2023. // Found it. Update the cache for next time, and return.
  2024. //LastTCB = FoundTCB;
  2025. CTEGetLockAtDPC(&FoundTCB->tcb_lock);
  2026. CTEFreeLockFromDPC(&pTCBTableLock[Partition]);
  2027. return FoundTCB;
  2028. } else
  2029. FoundTCB = FoundTCB->tcb_next;
  2030. }
  2031. if (AtDispatch) {
  2032. CTEFreeLockFromDPC(&pTCBTableLock[Partition]);
  2033. } else {
  2034. CTEFreeLock(&pTCBTableLock[Partition], *Handle);
  2035. }
  2036. // no matching TCB
  2037. return NULL;
  2038. }
  2039. //* FindTCBTW - Find a TCB in the time wait tcb table.
  2040. //
  2041. // Called when we need to find a TCB in the TCB table. We take a quick
  2042. // look at the last TCB we found, and if it matches we return it. Otherwise
  2043. // we hash into the TCB table and look for it. We assume the TCB table lock
  2044. // is held when we are called.
  2045. //
  2046. // Input: Src - Source IP address of TCB to be found.
  2047. // Dest - Dest. "" "" "" "" "" "" ""
  2048. // DestPort - Destination port of TCB to be found.
  2049. // SrcPort - Source port of TCB to be found.
  2050. //
  2051. // Returns: Pointer to TCB found, or NULL if none.
  2052. //
  2053. TWTCB *
  2054. FindTCBTW(IPAddr Src, IPAddr Dest, ushort DestPort, ushort SrcPort, uint index)
  2055. {
  2056. TWTCB *FoundTCB;
  2057. Queue *Scan;
  2058. for (Scan = QHEAD(&TWTCBTable[index]);
  2059. Scan != QEND(&TWTCBTable[index]);
  2060. Scan = QNEXT(Scan)) {
  2061. FoundTCB = QSTRUCT(TWTCB, Scan, twtcb_link);
  2062. CTEStructAssert(FoundTCB, twtcb);
  2063. if (IP_ADDR_EQUAL(FoundTCB->twtcb_daddr, Dest) &&
  2064. FoundTCB->twtcb_dport == DestPort &&
  2065. IP_ADDR_EQUAL(FoundTCB->twtcb_saddr, Src) &&
  2066. FoundTCB->twtcb_sport == SrcPort) {
  2067. return FoundTCB;
  2068. }
  2069. }
  2070. // no matching TCB
  2071. return NULL;
  2072. }
  2073. void
  2074. InsertInTimewaitQueue(TWTCB *Twtcb, uint Partition)
  2075. {
  2076. Queue *PrevLink;
  2077. TWTCB *Prev;
  2078. CTEStructAssert(Twtcb, twtcb);
  2079. ASSERT(!(Twtcb->twtcb_flags & IN_TWQUEUE));
  2080. ENQUEUE(&TWQueue[Partition], &Twtcb->twtcb_TWQueue);
  2081. PrevLink = QPREV(&Twtcb->twtcb_TWQueue);
  2082. if (PrevLink != &TWQueue[Partition]) {
  2083. Prev = STRUCT_OF(TWTCB, PrevLink, twtcb_TWQueue);
  2084. // Compute this TCB's delta value from the using previous TCB's delta
  2085. // Note that prev tcb delta is decremented by timeout routine
  2086. // every tick
  2087. Twtcb->twtcb_rexmittimer = MAX_REXMIT_TO - Prev->twtcb_delta;
  2088. } else {
  2089. Twtcb->twtcb_rexmittimer = MAX_REXMIT_TO;
  2090. }
  2091. Twtcb->twtcb_delta = MAX_REXMIT_TO;
  2092. #if DBG
  2093. Twtcb->twtcb_flags |= IN_TWQUEUE;
  2094. #endif
  2095. }
  2096. void
  2097. RemoveFromTimewaitQueue(TWTCB *Twtcb, uint Partition)
  2098. {
  2099. Queue *NextLink, *PrevLink;
  2100. TWTCB *AdjacentTwTcb;
  2101. CTEStructAssert(Twtcb, twtcb);
  2102. ASSERT(Twtcb->twtcb_flags & IN_TWQUEUE);
  2103. // Update the delta queue elements. If this element is not the last one,
  2104. // update the retransmit ticks of the next element. Otherwise, if this is
  2105. // not the only element, update the delta ticks of the previous element.
  2106. NextLink = QNEXT(&Twtcb->twtcb_TWQueue);
  2107. PrevLink = QPREV(&Twtcb->twtcb_TWQueue);
  2108. if (NextLink != QEND(&TWQueue[Partition])) {
  2109. AdjacentTwTcb = STRUCT_OF(TWTCB, NextLink, twtcb_TWQueue);
  2110. AdjacentTwTcb->twtcb_rexmittimer += Twtcb->twtcb_rexmittimer;
  2111. } else if (PrevLink != &TWQueue[Partition]) {
  2112. AdjacentTwTcb = STRUCT_OF(TWTCB, PrevLink, twtcb_TWQueue);
  2113. AdjacentTwTcb->twtcb_delta = AdjacentTwTcb->twtcb_delta -
  2114. (MAX_REXMIT_TO - Twtcb->twtcb_delta);
  2115. }
  2116. REMOVEQ(&Twtcb->twtcb_TWQueue);
  2117. #if DBG
  2118. Twtcb->twtcb_flags &= ~IN_TWQUEUE;
  2119. #endif
  2120. }
  2121. //* RemoveAndInsert();
  2122. // This routine is called by graceful close routine when the TCB
  2123. // needs to be placed in TIM_WAIT state.
  2124. // The routine removes the TCB from normal table and inserts a small
  2125. // version of it
  2126. // in TW table at the same hash index as the previous one.
  2127. // Also, it queues the TWTCB in timer delta queue for time out
  2128. // processing
  2129. //
  2130. uint
  2131. RemoveAndInsert(TCB * TimWaitTCB)
  2132. {
  2133. uint TCBIndex;
  2134. CTELockHandle TableHandle;
  2135. TCB *PrevTCB;
  2136. TWTCB *TWTcb;
  2137. uint Partition = TimWaitTCB->tcb_partition;
  2138. Queue* Scan;
  2139. #if DBG
  2140. uint Found = FALSE;
  2141. #endif
  2142. CTEStructAssert(TimWaitTCB, tcb);
  2143. if (!(TimWaitTCB->tcb_flags & IN_TCB_TABLE)) {
  2144. CTELockHandle TcbHandle;
  2145. CTEGetLock(&TimWaitTCB->tcb_lock, &TcbHandle);
  2146. TryToCloseTCB(TimWaitTCB, TCB_CLOSE_ABORTED, TcbHandle);
  2147. CTEGetLock(&TimWaitTCB->tcb_lock, &TcbHandle);
  2148. DerefTCB(TimWaitTCB, TcbHandle);
  2149. return FALSE;
  2150. }
  2151. CTEGetLock(&pTCBTableLock[Partition], &TableHandle);
  2152. CTEGetLockAtDPC(&TimWaitTCB->tcb_lock);
  2153. TCBIndex = TCB_HASH(TimWaitTCB->tcb_daddr, TimWaitTCB->tcb_saddr,
  2154. TimWaitTCB->tcb_dport, TimWaitTCB->tcb_sport);
  2155. PrevTCB = STRUCT_OF(TCB, &TCBTable[TCBIndex], tcb_next);
  2156. do {
  2157. if (PrevTCB->tcb_next == TimWaitTCB) {
  2158. // Found him.
  2159. PrevTCB->tcb_next = TimWaitTCB->tcb_next;
  2160. #if DBG
  2161. Found = TRUE;
  2162. #endif
  2163. break;
  2164. }
  2165. PrevTCB = PrevTCB->tcb_next;
  2166. #if DBG
  2167. CTEStructAssert(PrevTCB, tcb);
  2168. #endif
  2169. } while (PrevTCB != NULL);
  2170. ASSERT(Found);
  2171. TimWaitTCB->tcb_flags &= ~IN_TCB_TABLE;
  2172. TimWaitTCB->tcb_pending |= FREE_PENDING;
  2173. //rce and opts are freed in dereftcb.
  2174. //at this point tcb is out of this tcbtable
  2175. //nobody should be holding on to this.
  2176. //we are free to close this tcb and
  2177. //move the state to a smaller twtcb after acquiring
  2178. //twtcbtable lock
  2179. //get a free twtcb
  2180. if ((TWTcb = AllocTWTCB(Partition)) == NULL) {
  2181. // Could not allocate Time-wait TCB; so, notify.
  2182. TcpInvokeCcb(TCP_CONN_TIME_WAIT, TCP_CONN_CLOSED,
  2183. &TimWaitTCB->tcb_addrbytes, 0);
  2184. DerefTCB(TimWaitTCB, DISPATCH_LEVEL);
  2185. CTEFreeLock(&pTCBTableLock[Partition], TableHandle);
  2186. return TRUE;
  2187. //possibaly we should queue this tcb on wait queue
  2188. //and service it when we get free twtcb
  2189. }
  2190. // Initialize twtcb
  2191. //
  2192. TWTcb->twtcb_daddr = TimWaitTCB->tcb_daddr;
  2193. TWTcb->twtcb_saddr = TimWaitTCB->tcb_saddr;
  2194. TWTcb->twtcb_dport = TimWaitTCB->tcb_dport;
  2195. TWTcb->twtcb_sport = TimWaitTCB->tcb_sport;
  2196. TWTcb->twtcb_rcvnext = TimWaitTCB->tcb_rcvnext;
  2197. TWTcb->twtcb_sendnext = TimWaitTCB->tcb_sendnext;
  2198. ASSERT(TimWaitTCB->tcb_sendnext == TimWaitTCB->tcb_senduna);
  2199. #if DBG
  2200. TWTcb->twtcb_flags = 0;
  2201. #endif
  2202. CTEGetLockAtDPC(&pTWTCBTableLock[Partition]);
  2203. // Free the parent tcb for this connection
  2204. DerefTCB(TimWaitTCB, DISPATCH_LEVEL);
  2205. // now insert this in to time wait table after locking
  2206. if (EMPTYQ(&TWTCBTable[TCBIndex])) {
  2207. //
  2208. // First item in this bucket.
  2209. //
  2210. PUSHQ(&TWTCBTable[TCBIndex], &TWTcb->twtcb_link);
  2211. } else {
  2212. //
  2213. // Insert the item in sorted order. The order is based
  2214. // on the address of the TWTCB. (In this case, comparison
  2215. // is made against the address of the twtcb_link member, but
  2216. // the same result is achieved.)
  2217. //
  2218. for (Scan = QHEAD(&TWTCBTable[TCBIndex]);
  2219. Scan != QEND(&TWTCBTable[TCBIndex]);
  2220. Scan = QNEXT(Scan)) {
  2221. if (Scan > &TWTcb->twtcb_link) {
  2222. TWTcb->twtcb_link.q_next = Scan;
  2223. TWTcb->twtcb_link.q_prev = Scan->q_prev;
  2224. Scan->q_prev->q_next = &TWTcb->twtcb_link;
  2225. Scan->q_prev = &TWTcb->twtcb_link;
  2226. break;
  2227. }
  2228. }
  2229. //
  2230. // If we made it to the end without inserting, insert it
  2231. // at the end.
  2232. //
  2233. if (Scan == QEND(&TWTCBTable[TCBIndex])) {
  2234. ENQUEUE(&TWTCBTable[TCBIndex], &TWTcb->twtcb_link);
  2235. }
  2236. }
  2237. //no need to hold on to tcbtablelock beyond this point
  2238. #if DBG
  2239. TWTcb->twtcb_flags |= IN_TWTCB_TABLE;
  2240. #endif
  2241. CTEFreeLockFromDPC(&pTCBTableLock[Partition]);
  2242. InsertInTimewaitQueue(TWTcb, Partition);
  2243. CTEFreeLock(&pTWTCBTableLock[Partition], TableHandle);
  2244. InterlockedIncrement((PLONG)&numtwqueue); //debug purpose
  2245. return TRUE;
  2246. }
  2247. //* RemoveTWTCB - Remove a TWTCB from the TWTCB table.
  2248. //
  2249. // Called when we need to remove a TCB in time-wait from the time wait TCB
  2250. // table. We assume the TWTCB table lock is held when we are called.
  2251. //
  2252. // Input: RemovedTCB - TWTCB to be removed.
  2253. //
  2254. void
  2255. RemoveTWTCB(TWTCB *RemovedTCB, uint Partition)
  2256. {
  2257. CTEStructAssert(RemovedTCB, twtcb);
  2258. ASSERT(RemovedTCB->twtcb_flags & IN_TWTCB_TABLE);
  2259. ASSERT(RemovedTCB->twtcb_flags & IN_TWQUEUE);
  2260. // The time-wait expired and we have to notify.
  2261. TcpInvokeCcb(TCP_CONN_TIME_WAIT, TCP_CONN_CLOSED,
  2262. &RemovedTCB->twtcb_addrbytes, 0);
  2263. REMOVEQ(&RemovedTCB->twtcb_link);
  2264. InterlockedDecrement((PLONG)&TStats.ts_numconns);
  2265. RemoveFromTimewaitQueue(RemovedTCB, Partition);
  2266. InterlockedDecrement((PLONG)&numtwqueue);
  2267. #if DBG
  2268. RemovedTCB->twtcb_flags &= ~IN_TWTCB_TABLE;
  2269. #endif
  2270. }
  2271. void
  2272. ReInsert2MSL(TWTCB *RemovedTCB)
  2273. {
  2274. uint Index, Partition;
  2275. CTEStructAssert(RemovedTCB, twtcb);
  2276. ASSERT(RemovedTCB->twtcb_flags & IN_TWQUEUE);
  2277. Index = TCB_HASH(RemovedTCB->twtcb_daddr, RemovedTCB->twtcb_saddr,
  2278. RemovedTCB->twtcb_dport, RemovedTCB->twtcb_sport);
  2279. Partition = GET_PARTITION(Index);
  2280. RemoveFromTimewaitQueue(RemovedTCB, Partition);
  2281. InsertInTimewaitQueue(RemovedTCB, Partition);
  2282. }
  2283. //* AssassinateTWTCB - Assassinate the time wait TCB, if possible.
  2284. //
  2285. // A TCB in time wait can be assasinated if (a) the new TCB being created is
  2286. // because of passive open and (b) the incoming sequence number on the SYN is
  2287. // greater or equal to the next expected sequence number on the connection.
  2288. // The sequence number to be used to send the outgoing SYN is derived from the
  2289. // next expected send sequence number. If these conditions are satisfied, the
  2290. // Time-wait TCB is removed and freed.
  2291. //
  2292. //
  2293. // Input: TwTcb - Time wait TCB to be replaced.
  2294. // RecvNext - Next Sequence number after the SYN's sequence.
  2295. // SendNext - [OUT] ISN to be used on the new connection.
  2296. // Partition - Partition to which the TCB belongs to.
  2297. //
  2298. // Returns: TRUE if the assassination was possible, FALSE otherwise.
  2299. //
  2300. __inline
  2301. BOOLEAN
  2302. AssassinateTWTCB(TWTCB *TwTcb, SeqNum RecvNext, SeqNum *SendNext,
  2303. uint Partition)
  2304. {
  2305. if (SEQ_GT(RecvNext, TwTcb->twtcb_rcvnext)) {
  2306. *SendNext= TwTcb->twtcb_sendnext + 128000;
  2307. RemoveTWTCB(TwTcb, Partition);
  2308. FreeTWTCB(TwTcb);
  2309. return TRUE;
  2310. }
  2311. return FALSE;
  2312. }
  2313. //* InsertSynTCB - Insert a SYNTCB in the tcb table.
  2314. //
  2315. // This routine inserts a SYNTCB in the SYNTCB table. No locks need to be held
  2316. // when this routine is called. We insert TCBs in ascending address order.
  2317. // Before inserting we make sure that the SYNTCB isn't already in the table.
  2318. //
  2319. // Input: NewTCB - SYNTCB to be inserted.
  2320. //
  2321. // Returns: TRUE if we inserted, false if we didn't.
  2322. //
  2323. uint
  2324. InsertSynTCB(SYNTCB * NewTCB, CTELockHandle *TableHandle)
  2325. {
  2326. uint TCBIndex;
  2327. TCB *CurrentTCB;
  2328. uint Partition;
  2329. Queue *Scan, *WhereToInsert;
  2330. ASSERT(NewTCB != NULL);
  2331. CTEStructAssert(NewTCB, syntcb);
  2332. TCBIndex = TCB_HASH(NewTCB->syntcb_daddr, NewTCB->syntcb_saddr,
  2333. NewTCB->syntcb_dport, NewTCB->syntcb_sport);
  2334. Partition = GET_PARTITION(TCBIndex);
  2335. CTEGetLock(&pTCBTableLock[Partition], TableHandle);
  2336. NewTCB->syntcb_partition = Partition;
  2337. // Begin by looking for duplicates of the new SYNTCB in the TCB table.
  2338. // If we find one, bail out.
  2339. CurrentTCB = TCBTable[TCBIndex];
  2340. while (CurrentTCB != NULL) {
  2341. if (IP_ADDR_EQUAL(CurrentTCB->tcb_daddr, NewTCB->syntcb_daddr) &&
  2342. IP_ADDR_EQUAL(CurrentTCB->tcb_saddr, NewTCB->syntcb_saddr) &&
  2343. (CurrentTCB->tcb_sport == NewTCB->syntcb_sport) &&
  2344. (CurrentTCB->tcb_dport == NewTCB->syntcb_dport)) {
  2345. CTEFreeLock(&pTCBTableLock[Partition], *TableHandle);
  2346. return FALSE;
  2347. } else {
  2348. CurrentTCB = CurrentTCB->tcb_next;
  2349. }
  2350. }
  2351. // Retain our lock on the TCB table, and look next for a duplicate
  2352. // in the TWTCB table.
  2353. CTEGetLockAtDPC(&pTWTCBTableLock[Partition]);
  2354. for (Scan = QHEAD(&TWTCBTable[TCBIndex]);
  2355. Scan != QEND(&TWTCBTable[TCBIndex]); Scan = QNEXT(Scan)) {
  2356. TWTCB* CurrentTWTCB = STRUCT_OF(TWTCB, Scan, twtcb_link);
  2357. if (IP_ADDR_EQUAL(CurrentTWTCB->twtcb_daddr, NewTCB->syntcb_daddr) &&
  2358. (CurrentTWTCB->twtcb_dport == NewTCB->syntcb_dport) &&
  2359. IP_ADDR_EQUAL(CurrentTWTCB->twtcb_saddr, NewTCB->syntcb_saddr) &&
  2360. (CurrentTWTCB->twtcb_sport == NewTCB->syntcb_sport)) {
  2361. if (AssassinateTWTCB(CurrentTWTCB, NewTCB->syntcb_rcvnext,
  2362. &NewTCB->syntcb_sendnext, Partition)) {
  2363. break;
  2364. } else {
  2365. CTEFreeLockFromDPC(&pTWTCBTableLock[Partition]);
  2366. CTEFreeLock(&pTCBTableLock[Partition], *TableHandle);
  2367. return FALSE;
  2368. }
  2369. }
  2370. }
  2371. CTEFreeLockFromDPC(&pTWTCBTableLock[Partition]);
  2372. // Finally, check for duplicates in the SYNTCB table, and at the same time
  2373. // find the insertion point for the new entry.
  2374. CTEGetLockAtDPC(&pSynTCBTableLock[Partition]);
  2375. CTEGetLockAtDPC(&NewTCB->syntcb_lock);
  2376. WhereToInsert = NULL;
  2377. for (Scan = QHEAD(&SYNTCBTable[TCBIndex]);
  2378. Scan != QEND(&SYNTCBTable[TCBIndex]); Scan = QNEXT(Scan)) {
  2379. SYNTCB *CurrentSynTCB = STRUCT_OF(SYNTCB, Scan, syntcb_link);
  2380. if (IP_ADDR_EQUAL(CurrentSynTCB->syntcb_daddr, NewTCB->syntcb_daddr) &&
  2381. (CurrentSynTCB->syntcb_dport == NewTCB->syntcb_dport) &&
  2382. IP_ADDR_EQUAL(CurrentSynTCB->syntcb_saddr, NewTCB->syntcb_saddr) &&
  2383. (CurrentSynTCB->syntcb_sport == NewTCB->syntcb_sport)) {
  2384. CTEFreeLockFromDPC(&NewTCB->syntcb_lock);
  2385. CTEFreeLockFromDPC(&pSynTCBTableLock[Partition]);
  2386. CTEFreeLock(&pTCBTableLock[Partition], *TableHandle);
  2387. return FALSE;
  2388. }
  2389. if (WhereToInsert == NULL && Scan > &NewTCB->syntcb_link) {
  2390. WhereToInsert = Scan;
  2391. }
  2392. }
  2393. if (WhereToInsert == NULL) {
  2394. WhereToInsert = Scan;
  2395. }
  2396. ENQUEUE(WhereToInsert, &NewTCB->syntcb_link);
  2397. NewTCB->syntcb_flags |= IN_SYNTCB_TABLE;
  2398. CTEFreeLockFromDPC(&pSynTCBTableLock[Partition]);
  2399. CTEFreeLockFromDPC(&pTCBTableLock[Partition]);
  2400. return TRUE;
  2401. }
  2402. //* InsertTCB - Insert a TCB in the tcb table.
  2403. //
  2404. // This routine inserts a TCB in the TCB table. No locks need to be held
  2405. // when this routine is called. We insert TCBs in ascending address order.
  2406. // Before inserting we make sure that the TCB isn't already in the table.
  2407. //
  2408. // Input: NewTCB - TCB to be inserted.
  2409. // ForceInsert - If there is a time wait TCB, it can be replaced.
  2410. //
  2411. // Returns: TRUE if we inserted, false if we didn't.
  2412. //
  2413. uint
  2414. InsertTCB(TCB * NewTCB, BOOLEAN ForceInsert)
  2415. {
  2416. uint TCBIndex;
  2417. CTELockHandle TableHandle;
  2418. TCB *PrevTCB, *CurrentTCB;
  2419. TCB *WhereToInsert;
  2420. uint Partition;
  2421. Queue *Scan;
  2422. uint EarlyInsertTime;
  2423. ASSERT(NewTCB != NULL);
  2424. CTEStructAssert(NewTCB, tcb);
  2425. TCBIndex = TCB_HASH(NewTCB->tcb_daddr, NewTCB->tcb_saddr,
  2426. NewTCB->tcb_dport, NewTCB->tcb_sport);
  2427. Partition = GET_PARTITION(TCBIndex);
  2428. CTEGetLock(&pTCBTableLock[Partition], &TableHandle);
  2429. CTEGetLockAtDPC(&NewTCB->tcb_lock);
  2430. NewTCB->tcb_partition = Partition;
  2431. // Look first for a duplicate in the SYNTCB table.
  2432. if (SynAttackProtect) {
  2433. CTEGetLockAtDPC(&pSynTCBTableLock[Partition]);
  2434. for (Scan = QHEAD(&SYNTCBTable[TCBIndex]);
  2435. Scan != QEND(&SYNTCBTable[TCBIndex]); Scan = QNEXT(Scan)) {
  2436. SYNTCB *CurrentSynTCB = STRUCT_OF(SYNTCB, Scan, syntcb_link);
  2437. if (IP_ADDR_EQUAL(CurrentSynTCB->syntcb_daddr, NewTCB->tcb_daddr) &&
  2438. (CurrentSynTCB->syntcb_dport == NewTCB->tcb_dport) &&
  2439. IP_ADDR_EQUAL(CurrentSynTCB->syntcb_saddr, NewTCB->tcb_saddr) &&
  2440. (CurrentSynTCB->syntcb_sport == NewTCB->tcb_sport)) {
  2441. CTEFreeLockFromDPC(&pSynTCBTableLock[Partition]);
  2442. CTEFreeLockFromDPC(&NewTCB->tcb_lock);
  2443. CTEFreeLock(&pTCBTableLock[Partition], TableHandle);
  2444. return FALSE;
  2445. }
  2446. }
  2447. CTEFreeLockFromDPC(&pSynTCBTableLock[Partition]);
  2448. }
  2449. // Next, look for a duplicate in the TWTCB table.
  2450. CTEGetLockAtDPC(&pTWTCBTableLock[Partition]);
  2451. for (Scan = QHEAD(&TWTCBTable[TCBIndex]);
  2452. Scan != QEND(&TWTCBTable[TCBIndex]); Scan = QNEXT(Scan)) {
  2453. TWTCB *CurrentTWTCB = STRUCT_OF(TWTCB, Scan, twtcb_link);
  2454. CTEStructAssert(CurrentTWTCB, twtcb);
  2455. if (IP_ADDR_EQUAL(CurrentTWTCB->twtcb_daddr, NewTCB->tcb_daddr) &&
  2456. (CurrentTWTCB->twtcb_dport == NewTCB->tcb_dport) &&
  2457. IP_ADDR_EQUAL(CurrentTWTCB->twtcb_saddr, NewTCB->tcb_saddr) &&
  2458. (CurrentTWTCB->twtcb_sport == NewTCB->tcb_sport)) {
  2459. if (ForceInsert &&
  2460. AssassinateTWTCB(CurrentTWTCB, NewTCB->tcb_rcvnext,
  2461. &NewTCB->tcb_sendnext, Partition)) {
  2462. break;
  2463. } else {
  2464. CTEFreeLockFromDPC(&pTWTCBTableLock[Partition]);
  2465. CTEFreeLockFromDPC(&NewTCB->tcb_lock);
  2466. CTEFreeLock(&pTCBTableLock[Partition], TableHandle);
  2467. return FALSE;
  2468. }
  2469. }
  2470. }
  2471. CTEFreeLockFromDPC(&pTWTCBTableLock[Partition]);
  2472. // Find the proper place in the table to insert him. While
  2473. // we're walking we'll check to see if a dupe already exists.
  2474. // When we find the right place to insert, we'll remember it, and
  2475. // keep walking looking for a duplicate.
  2476. PrevTCB = STRUCT_OF(TCB, &TCBTable[TCBIndex], tcb_next);
  2477. WhereToInsert = NULL;
  2478. while (PrevTCB->tcb_next != NULL) {
  2479. CurrentTCB = PrevTCB->tcb_next;
  2480. if (IP_ADDR_EQUAL(CurrentTCB->tcb_daddr, NewTCB->tcb_daddr) &&
  2481. IP_ADDR_EQUAL(CurrentTCB->tcb_saddr, NewTCB->tcb_saddr) &&
  2482. (CurrentTCB->tcb_sport == NewTCB->tcb_sport) &&
  2483. (CurrentTCB->tcb_dport == NewTCB->tcb_dport)) {
  2484. CTEFreeLockFromDPC(&NewTCB->tcb_lock);
  2485. CTEFreeLock(&pTCBTableLock[Partition], TableHandle);
  2486. return FALSE;
  2487. } else {
  2488. if (WhereToInsert == NULL && CurrentTCB > NewTCB) {
  2489. WhereToInsert = PrevTCB;
  2490. }
  2491. CTEStructAssert(PrevTCB->tcb_next, tcb);
  2492. PrevTCB = PrevTCB->tcb_next;
  2493. }
  2494. }
  2495. // there can be timed_wait tcb in the tw tcb table.
  2496. // look if there is a tcb with the same address.
  2497. // Get lock on TW table too.
  2498. if (WhereToInsert == NULL) {
  2499. WhereToInsert = PrevTCB;
  2500. }
  2501. NewTCB->tcb_next = WhereToInsert->tcb_next;
  2502. WhereToInsert->tcb_next = NewTCB;
  2503. NewTCB->tcb_flags |= IN_TCB_TABLE;
  2504. // Perform early insertion of the new TCB, since it's likely to have
  2505. // a timer scheduled right away in any case.
  2506. EarlyInsertTime = TCPTime + 2;
  2507. if (EarlyInsertTime == 0) {
  2508. EarlyInsertTime = 1;
  2509. }
  2510. if (NewTCB->tcb_timerslot == DUMMY_SLOT) {
  2511. NewTCB->tcb_timertime = EarlyInsertTime;
  2512. InsertIntoTimerWheel(NewTCB, COMPUTE_SLOT(EarlyInsertTime));
  2513. } else if ((TCPTIME_LT(EarlyInsertTime, NewTCB->tcb_timertime)) ||
  2514. (NewTCB->tcb_timertime == 0)) {
  2515. NewTCB->tcb_timertime = EarlyInsertTime;
  2516. RemoveAndInsertIntoTimerWheel(NewTCB, COMPUTE_SLOT(EarlyInsertTime));
  2517. }
  2518. CTEFreeLockFromDPC(&NewTCB->tcb_lock);
  2519. CTEFreeLock(&pTCBTableLock[Partition], TableHandle);
  2520. InterlockedIncrement((PLONG)&TStats.ts_numconns);
  2521. return TRUE;
  2522. }
  2523. //* RemoveTCB - Remove a TCB from the tcb table.
  2524. //
  2525. // Called when we need to remove a TCB from the TCB table. We assume the
  2526. // TCB table lock and the TCB lock are held when we are called. If the
  2527. // TCB isn't in the table we won't try to remove him.
  2528. //
  2529. // Input: RemovedTCB - TCB to be removed.
  2530. // PreviousState - Previous state of the TCB.
  2531. //
  2532. // Returns: TRUE if it's OK to free it, FALSE otherwise.
  2533. //
  2534. uint
  2535. RemoveTCB(TCB * RemovedTCB, uint PreviousState)
  2536. {
  2537. uint TCBIndex;
  2538. TCB *PrevTCB;
  2539. #if DBG
  2540. uint Found = FALSE;
  2541. #endif
  2542. CTEStructAssert(RemovedTCB, tcb);
  2543. if (RemovedTCB->tcb_timerslot != DUMMY_SLOT) {
  2544. ASSERT(RemovedTCB->tcb_timerslot < TIMER_WHEEL_SIZE);
  2545. RemoveFromTimerWheel(RemovedTCB);
  2546. }
  2547. if (RemovedTCB->tcb_flags & IN_TCB_TABLE) {
  2548. TcpInvokeCcb(CONN_STATE(PreviousState), TCP_CONN_CLOSED,
  2549. &RemovedTCB->tcb_addrbytes, 0);
  2550. TCBIndex = TCB_HASH(RemovedTCB->tcb_daddr, RemovedTCB->tcb_saddr,
  2551. RemovedTCB->tcb_dport, RemovedTCB->tcb_sport);
  2552. PrevTCB = STRUCT_OF(TCB, &TCBTable[TCBIndex], tcb_next);
  2553. do {
  2554. if (PrevTCB->tcb_next == RemovedTCB) {
  2555. // Found him.
  2556. PrevTCB->tcb_next = RemovedTCB->tcb_next;
  2557. RemovedTCB->tcb_flags &= ~IN_TCB_TABLE;
  2558. InterlockedDecrement((PLONG)&TStats.ts_numconns);
  2559. #if DBG
  2560. Found = TRUE;
  2561. #endif
  2562. break;
  2563. }
  2564. PrevTCB = PrevTCB->tcb_next;
  2565. #if DBG
  2566. if (PrevTCB != NULL)
  2567. CTEStructAssert(PrevTCB, tcb);
  2568. #endif
  2569. } while (PrevTCB != NULL);
  2570. ASSERT(Found);
  2571. }
  2572. CTEGetLockAtDPC(&PendingFreeLock.Lock);
  2573. if (TCBWalkCount != 0) {
  2574. #ifdef PENDING_FREE_DBG
  2575. if( RemovedTCB->tcb_flags & IN_TCB_TABLE )
  2576. DbgBreakPoint();
  2577. #endif
  2578. RemovedTCB->tcb_walkcount = TCBWalkCount + 1;
  2579. *(TCB **) & RemovedTCB->tcb_delayq.q_next = PendingFreeList;
  2580. PendingFreeList = RemovedTCB;
  2581. CTEFreeLockFromDPC(&PendingFreeLock.Lock);
  2582. return FALSE;
  2583. } else {
  2584. CTEFreeLockFromDPC(&PendingFreeLock.Lock);
  2585. return TRUE;
  2586. }
  2587. }
  2588. //* AllocTWTCB - Allocate a TCB.
  2589. //
  2590. // Called whenever we need to allocate a TWTCB. We try to pull one off the
  2591. // free list, or allocate one if we need one. We then initialize it, etc.
  2592. //
  2593. // Input: Nothing.
  2594. //
  2595. // Returns: Pointer to the new TCB, or NULL if we couldn't get one.
  2596. //
  2597. TWTCB *
  2598. AllocTWTCB(uint index)
  2599. {
  2600. TWTCB *NewTWTCB;
  2601. LOGICAL FromList;
  2602. // We use the reqeust pool, because its buffers are in the same size
  2603. // range as TWTCB. Further, it is a very active and efficient look
  2604. // aside list whereas when TWTCBs are on their own look aside list it
  2605. // is usually at a very small depth because TWTCBs are not allocated
  2606. // very frequently w.r.t. to the update period of the look aside list.
  2607. //
  2608. NewTWTCB = PplAllocate(TcpRequestPool, &FromList);
  2609. if (NewTWTCB) {
  2610. NdisZeroMemory(NewTWTCB, sizeof(TWTCB));
  2611. #if DBG
  2612. NewTWTCB->twtcb_sig = twtcb_signature;
  2613. #endif
  2614. }
  2615. return NewTWTCB;
  2616. }
  2617. //* AllocTCB - Allocate a TCB.
  2618. //
  2619. // Called whenever we need to allocate a TCB. We try to pull one off the
  2620. // free list, or allocate one if we need one. We then initialize it, etc.
  2621. //
  2622. // Input: Nothing.
  2623. //
  2624. // Returns: Pointer to the new TCB, or NULL if we couldn't get one.
  2625. //
  2626. TCB *
  2627. AllocTCB(VOID)
  2628. {
  2629. TCB *NewTCB;
  2630. LOGICAL FromList;
  2631. NewTCB = PplAllocate(TcbPool, &FromList);
  2632. if (NewTCB) {
  2633. NdisZeroMemory(NewTCB, sizeof(TCB));
  2634. #if DBG
  2635. NewTCB->tcb_sig = tcb_signature;
  2636. #endif
  2637. INITQ(&NewTCB->tcb_sendq);
  2638. // Initially we're not on the fast path because we're not established. Set
  2639. // the slowcount to one and set up the fastchk fields so we don't take the
  2640. // fast path. We start with the assumption that all types of offloads
  2641. // are permitted.
  2642. NewTCB->tcb_slowcount = 1;
  2643. NewTCB->tcb_fastchk = TCP_FLAG_ACK | TCP_FLAG_SLOW;
  2644. NewTCB->tcb_delackticks = DEL_ACK_TICKS;
  2645. NewTCB->tcb_allowedoffloads = TCP_IP_OFFLOAD_TYPES;
  2646. NewTCB->tcb_partition = 0;
  2647. CTEInitLock(&NewTCB->tcb_lock);
  2648. INITQ(&NewTCB->tcb_timerwheelq);
  2649. NewTCB->tcb_timerslot = DUMMY_SLOT;
  2650. NewTCB->tcb_timertime = 0;
  2651. NewTCB->tcb_timertype = NO_TIMER;
  2652. }
  2653. return NewTCB;
  2654. }
  2655. //* AllocSynTCB - Allocate a SYNTCB.
  2656. //
  2657. // Called whenever we need to allocate a synTCB. We try to pull one off the
  2658. // free list, or allocate one if we need one. We then initialize it, etc.
  2659. //
  2660. // Input: Nothing.
  2661. //
  2662. // Returns: Pointer to the new SYNTCB, or NULL if we couldn't get one.
  2663. //
  2664. SYNTCB *
  2665. AllocSynTCB(VOID)
  2666. {
  2667. SYNTCB *SynTCB;
  2668. LOGICAL FromList;
  2669. SynTCB = PplAllocate(SynTcbPool, &FromList);
  2670. if (SynTCB) {
  2671. NdisZeroMemory(SynTCB, sizeof(SYNTCB));
  2672. #if DBG
  2673. SynTCB->syntcb_sig = syntcb_signature;
  2674. #endif
  2675. CTEInitLock(&SynTCB->syntcb_lock);
  2676. }
  2677. return SynTCB;
  2678. }
  2679. //* FreeTCB - Free a TCB.
  2680. //
  2681. // Called whenever we need to free a TCB.
  2682. //
  2683. // Note: This routine may be called with the TCBTableLock held.
  2684. //
  2685. // Input: FreedTCB - TCB to be freed.
  2686. //
  2687. // Returns: Nothing.
  2688. //
  2689. VOID
  2690. FreeTCB(TCB * FreedTCB)
  2691. {
  2692. CTELockHandle Handle;
  2693. CTEStructAssert(FreedTCB, tcb);
  2694. if (FreedTCB->tcb_timerslot != DUMMY_SLOT) {
  2695. CTEGetLock(&FreedTCB->tcb_lock, &Handle);
  2696. // This TCB should not be touched in this stage at all..
  2697. ASSERT(FreedTCB->tcb_timerslot != DUMMY_SLOT);
  2698. // Even if it does, it has to be handled properly..
  2699. if (FreedTCB->tcb_timerslot != DUMMY_SLOT) {
  2700. ASSERT(FreedTCB->tcb_timerslot < TIMER_WHEEL_SIZE);
  2701. RemoveFromTimerWheel(FreedTCB);
  2702. }
  2703. CTEFreeLock(&FreedTCB->tcb_lock, Handle);
  2704. }
  2705. if (FreedTCB->tcb_SackBlock)
  2706. CTEFreeMem(FreedTCB->tcb_SackBlock);
  2707. if (FreedTCB->tcb_SackRcvd) {
  2708. SackListEntry *tmp, *next;
  2709. tmp = FreedTCB->tcb_SackRcvd;
  2710. while (tmp) {
  2711. next = tmp->next;
  2712. CTEFreeMem(tmp);
  2713. tmp = next;
  2714. }
  2715. }
  2716. PplFree(TcbPool, FreedTCB);
  2717. }
  2718. //* FreeSynTCB - Free a TCB.
  2719. //
  2720. // Called whenever we need to free a SynTCB.
  2721. //
  2722. // Note: This routine may be called with the SYNTCBTableLock held.
  2723. //
  2724. // Input: SynTCB - SynTCB to be freed.
  2725. //
  2726. // Returns: Nothing.
  2727. //
  2728. VOID
  2729. FreeSynTCB(SYNTCB * SynTCB)
  2730. {
  2731. CTEStructAssert(SynTCB, syntcb);
  2732. PplFree(SynTcbPool, SynTCB);
  2733. }
  2734. //* FreeTWTCB - Free a TWTCB.
  2735. //
  2736. // Called whenever we need to free a TWTCB.
  2737. //
  2738. // Note: This routine may be called with the TWTCBTableLock held.
  2739. //
  2740. // Input: FreedTCB - TCB to be freed.
  2741. //
  2742. // Returns: Nothing.
  2743. //
  2744. __inline
  2745. void
  2746. FreeTWTCB(TWTCB * FreedTWTCB)
  2747. {
  2748. PplFree(TcpRequestPool, FreedTWTCB);
  2749. }
  2750. NTSTATUS
  2751. GetTCBInfo(PTCP_FINDTCB_RESPONSE TCBInfo, IPAddr Dest, IPAddr Src,
  2752. ushort DestPort, ushort SrcPort)
  2753. {
  2754. TCB *FoundTCB;
  2755. CTELockHandle Handle, TwHandle;
  2756. BOOLEAN timedwait = FALSE;
  2757. uint Index, Partition;
  2758. FoundTCB = FindTCB(Src, Dest, DestPort, SrcPort, &Handle, FALSE, &Index);
  2759. Partition = GET_PARTITION(Index);
  2760. if (FoundTCB == NULL) {
  2761. CTEGetLock(&pTWTCBTableLock[Partition], &TwHandle);
  2762. FoundTCB = (TCB*)FindTCBTW(Src, Dest, DestPort, SrcPort, Index);
  2763. if (!FoundTCB) {
  2764. CTEFreeLock(&pTWTCBTableLock[Partition], TwHandle);
  2765. return STATUS_NOT_FOUND;
  2766. } else {
  2767. timedwait = TRUE;
  2768. }
  2769. } else {
  2770. TwHandle = Handle;
  2771. }
  2772. // okay we now have tcb locked.
  2773. // copy the fileds
  2774. TCBInfo->tcb_addr = (ULONG_PTR) FoundTCB;
  2775. if (!timedwait) {
  2776. TCBInfo->tcb_senduna = FoundTCB->tcb_senduna;
  2777. TCBInfo->tcb_sendnext = FoundTCB->tcb_sendnext;
  2778. TCBInfo->tcb_sendmax = FoundTCB->tcb_sendmax;
  2779. TCBInfo->tcb_sendwin = FoundTCB->tcb_sendwin;
  2780. TCBInfo->tcb_unacked = FoundTCB->tcb_unacked;
  2781. TCBInfo->tcb_maxwin = FoundTCB->tcb_maxwin;
  2782. TCBInfo->tcb_cwin = FoundTCB->tcb_cwin;
  2783. TCBInfo->tcb_mss = FoundTCB->tcb_mss;
  2784. TCBInfo->tcb_rtt = FoundTCB->tcb_rtt;
  2785. TCBInfo->tcb_smrtt = FoundTCB->tcb_smrtt;
  2786. TCBInfo->tcb_rexmitcnt = FoundTCB->tcb_rexmitcnt;
  2787. TCBInfo->tcb_rexmittimer = 0; // FoundTCB->tcb_rexmittimer;
  2788. TCBInfo->tcb_rexmit = FoundTCB->tcb_rexmit;
  2789. TCBInfo->tcb_retrans = TStats.ts_retranssegs;
  2790. TCBInfo->tcb_state = FoundTCB->tcb_state;
  2791. CTEFreeLock(&FoundTCB->tcb_lock, Handle);
  2792. } else {
  2793. //TCBInfo->tcb_state = ((TWTCB *)FoundTCB)->twtcb_state;
  2794. TCBInfo->tcb_state = TCB_TIME_WAIT;
  2795. CTEFreeLock(&pTWTCBTableLock[Partition], TwHandle);
  2796. }
  2797. return STATUS_SUCCESS;
  2798. }
  2799. #if REFERENCE_DEBUG
  2800. uint
  2801. TcpReferenceTCB(
  2802. IN TCB *RefTCB,
  2803. IN uchar *File,
  2804. IN uint Line
  2805. )
  2806. /*++
  2807. Routine Description:
  2808. Increases the reference count of a TCB and records a history of who
  2809. made the call to reference.
  2810. Arguments:
  2811. RefTCB - The TCB to reference.
  2812. File - The filename containing the calling fcn (output of the __FILE__ macro).
  2813. Line - The line number of the call to this fcn. (output of the __LINE__ macro).
  2814. Return Value:
  2815. The new reference count.
  2816. --*/
  2817. {
  2818. void *CallersCaller;
  2819. TCP_REFERENCE_HISTORY *RefHistory;
  2820. RefHistory = &RefTCB->tcb_refhistory[RefTCB->tcb_refhistory_index];
  2821. RefHistory->File = File;
  2822. RefHistory->Line = Line;
  2823. RtlGetCallersAddress(&RefHistory->Caller, &CallersCaller);
  2824. RefHistory->Count = ++RefTCB->tcb_refcnt;
  2825. RefTCB->tcb_refhistory_index = ++RefTCB->tcb_refhistory_index % MAX_REFERENCE_HISTORY;
  2826. return RefTCB->tcb_refcnt;
  2827. }
  2828. uint
  2829. TcpDereferenceTCB(
  2830. IN TCB *DerefTCB,
  2831. IN uchar *File,
  2832. IN uint Line
  2833. )
  2834. /*++
  2835. Routine Description:
  2836. Decreases the reference count of a TCB and records a history of who
  2837. made the call to dereference.
  2838. Arguments:
  2839. DerefTCB - The TCB to dereference.
  2840. File - The filename containing the calling fcn (output of the __FILE__ macro).
  2841. Line - The line number of the call to this fcn. (output of the __LINE__ macro).
  2842. Return Value:
  2843. The new reference count.
  2844. --*/
  2845. {
  2846. void *Caller;
  2847. TCP_REFERENCE_HISTORY *RefHistory;
  2848. RefHistory = &DerefTCB->tcb_refhistory[DerefTCB->tcb_refhistory_index];
  2849. RefHistory->File = File;
  2850. RefHistory->Line = Line;
  2851. // Because Dereference is usually called from DerefTCB, we are more
  2852. // interested in who called DerefTCB. So for dereference, we
  2853. // store the caller's caller in our history. We still retain a history
  2854. // of the actually call to this fcn via the file and line fields, so
  2855. // we are covered if the call did not come from DerefTCB.
  2856. //
  2857. RtlGetCallersAddress(&Caller, &RefHistory->Caller);
  2858. RefHistory->Count = --DerefTCB->tcb_refcnt;
  2859. DerefTCB->tcb_refhistory_index = ++DerefTCB->tcb_refhistory_index % MAX_REFERENCE_HISTORY;
  2860. return DerefTCB->tcb_refcnt;
  2861. }
  2862. #endif // REFERENCE_DEBUG
  2863. #pragma BEGIN_INIT
  2864. //* InitTCB - Initialize our TCB code.
  2865. //
  2866. // Called during init time to initialize our TCB code. We initialize
  2867. // the TCB table, etc, then return.
  2868. //
  2869. // Input: Nothing.
  2870. //
  2871. // Returns: TRUE if we did initialize, false if we didn't.
  2872. //
  2873. int
  2874. InitTCB(void)
  2875. {
  2876. uint i;
  2877. for (i = 0; i < TCB_TABLE_SIZE; i++)
  2878. TCBTable[i] = NULL;
  2879. CTEInitLock(&PendingFreeLock.Lock);
  2880. LastTimeoutTime = KeQueryInterruptTime();
  2881. #ifdef TIMER_TEST
  2882. TCPTime = 0xfffff000;
  2883. #else
  2884. TCPTime = 0;
  2885. #endif
  2886. TCBWalkCount = 0;
  2887. DeadmanTicks = NUM_DEADMAN_TIME;
  2888. #if MILLEN
  2889. Time_Proc = 1;
  2890. PerTimerSize = TCB_TABLE_SIZE;
  2891. #else // MILLEN
  2892. Time_Proc = KeNumberProcessors;
  2893. PerTimerSize = (TCB_TABLE_SIZE + Time_Proc) / Time_Proc;
  2894. #endif // !MILLEN
  2895. for (i = 0; i < Time_Proc; i++) {
  2896. CTEInitTimerEx(&TCBTimer[i]);
  2897. #if !MILLEN
  2898. KeSetTargetProcessorDpc(&(TCBTimer[i].t_dpc), (CCHAR) i);
  2899. #endif // !MILLEN
  2900. CTEStartTimerEx(&TCBTimer[i], MS_PER_TICK , TCBTimeout, NULL);
  2901. }
  2902. TcbPool = PplCreatePool(NULL, NULL, 0, sizeof(TCB), 'TPCT', 0);
  2903. if (!TcbPool)
  2904. {
  2905. return FALSE;
  2906. }
  2907. SynTcbPool = PplCreatePool(NULL, NULL, 0, sizeof(SYNTCB), 'YPCT', 0);
  2908. if (!SynTcbPool)
  2909. {
  2910. PplDestroyPool(TcbPool);
  2911. return FALSE;
  2912. }
  2913. return TRUE;
  2914. }
  2915. //* UnInitTCB - UnInitialize our TCB code.
  2916. //
  2917. // Called during init time if we're going to fail the init. We don't actually
  2918. // do anything here.
  2919. //
  2920. // Input: Nothing.
  2921. //
  2922. // Returns: Nothing.
  2923. //
  2924. void
  2925. UnInitTCB(void)
  2926. {
  2927. uint i;
  2928. for (i = 0; i < Time_Proc; i++) {
  2929. CTEStopTimer(&TCBTimer[i]);
  2930. }
  2931. }
  2932. #pragma END_INIT