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.

2954 lines
99 KiB

  1. // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs)
  2. //
  3. // Copyright (c) 1985-2000 Microsoft Corporation
  4. //
  5. // This file is part of the Microsoft Research IPv6 Network Protocol Stack.
  6. // You should have received a copy of the Microsoft End-User License Agreement
  7. // for this software along with this release; see the file "license.txt".
  8. // If not, please see http://www.research.microsoft.com/msripv6/license.htm,
  9. // or write to Microsoft Research, One Microsoft Way, Redmond, WA 98052-6399.
  10. //
  11. // Abstract:
  12. //
  13. // Code for TCP connection management.
  14. //
  15. // This file contains the code handling TCP connection related requests,
  16. // such as connecting and disconnecting.
  17. //
  18. #include "oscfg.h"
  19. #include "ndis.h"
  20. #include "ip6imp.h"
  21. #include "ip6def.h"
  22. #include "tdi.h"
  23. #include "tdint.h"
  24. #include "tdistat.h"
  25. #include "queue.h"
  26. #include "transprt.h"
  27. #include "addr.h"
  28. #include "tcp.h"
  29. #include "tcb.h"
  30. #include "tcpconn.h"
  31. #include "tcpsend.h"
  32. #include "tcprcv.h"
  33. #include "tcpdeliv.h"
  34. #include "info.h"
  35. #include "tcpcfg.h"
  36. #include "route.h"
  37. #include "security.h"
  38. #include "tcpmd5.h"
  39. #include "md5.h"
  40. #include "crypto\rc4.h"
  41. SLIST_HEADER ConnReqFree; // Connection request free list.
  42. //
  43. // ISN globals.
  44. //
  45. #define ISN_KEY_SIZE 256 // 2048 bits.
  46. #define ISN_DEF_RAND_STORE_SIZE 256
  47. #define ISN_MIN_RAND_STORE_SIZE 1
  48. #define ISN_MAX_RAND_STORE_SIZE 16384
  49. typedef struct _ISN_RAND_STORE {
  50. MD5_CONTEXT Md5Context;
  51. ulong iBuf;
  52. ushort* pBuf;
  53. } ISN_RAND_STORE, *PISN_RAND_STORE;
  54. RC4_KEYSTRUCT ISNRC4Key;
  55. PISN_RAND_STORE ISNStore;
  56. uint ISNStoreSize = ISN_DEF_RAND_STORE_SIZE;
  57. uint ISNStoreMask;
  58. SeqNum ISNMonotonicPortion = 0;
  59. int ISNCredits;
  60. int ISNLastIsnUpdateTime;
  61. int ISNMaxCredits;
  62. extern PDRIVER_OBJECT TCPDriverObject;
  63. KSPIN_LOCK ConnReqFreeLock; // Lock to protect conn req free list.
  64. uint NumConnReq; // Current number of ConnReqs.
  65. uint MaxConnReq = 0xffffffff; // Maximum allowed number of ConnReqs.
  66. uint ConnPerBlock = MAX_CONN_PER_BLOCK;
  67. uint NextConnBlock = 0; // Cached index of next unfilled block.
  68. uint MaxAllocatedConnBlocks = 0; // Current number of blocks in the
  69. // ConnTable.
  70. TCPConnBlock **ConnTable = NULL; // The current connection table.
  71. KSPIN_LOCK ConnTableLock;
  72. extern KSPIN_LOCK AddrObjTableLock;
  73. extern KSPIN_LOCK TCBTableLock;
  74. extern void RemoveConnFromAO(AddrObj *AO, TCPConn *Conn);
  75. //
  76. // All of the init code can be discarded.
  77. //
  78. #ifdef ALLOC_PRAGMA
  79. int InitTCPConn(void);
  80. int InitISNGenerator(void);
  81. void UnloadISNGenerator(void);
  82. int GetRandBits();
  83. uint GetDeltaTime();
  84. #pragma alloc_text(INIT, InitTCPConn)
  85. #pragma alloc_text(INIT, InitISNGenerator)
  86. #pragma alloc_text(PAGE, UnloadISNGenerator)
  87. #endif // ALLOC_PRAGMA
  88. void CompleteConnReq(TCB *CmpltTCB, TDI_STATUS Status);
  89. //* UnloadISNGenerator - Unload the support for the ISN generator.
  90. //
  91. // Called when we are unloading the driver.
  92. //
  93. void // Returns: Nothing.
  94. UnloadISNGenerator(void)
  95. {
  96. CCHAR i;
  97. ASSERT(ISNStore);
  98. for (i = 0; i < KeNumberProcessors; i++) {
  99. if (ISNStore[i].pBuf != NULL) {
  100. ExFreePool(ISNStore[i].pBuf);
  101. ISNStore[i].pBuf = NULL;
  102. }
  103. }
  104. ExFreePool(ISNStore);
  105. ISNStore = NULL;
  106. }
  107. //* InitISNGenerator - Initialize the support for the ISN generator.
  108. //
  109. // Called when the driver is loaded. Get 2048 bits of randomness and
  110. // use them to create an RC4 key.
  111. //
  112. int //Returns: TRUE if successful.
  113. InitISNGenerator(void)
  114. {
  115. ULONG cBits = 0;
  116. ULONG i;
  117. ULONG cProcs = KeNumberProcessors;
  118. ULONG ISNRandomValue;
  119. unsigned char pBuf[ISN_KEY_SIZE];
  120. //
  121. // Start with the credits that would last for 1 tick.
  122. //
  123. ISNMaxCredits = ISNCredits = MAX_ISN_INCREMENTABLE_CONNECTIONS_PER_100MS;
  124. ISNLastIsnUpdateTime = (int)X100NSTOMS(KeQueryInterruptTime());
  125. if (!GetSystemRandomBits(pBuf, ISN_KEY_SIZE)) {
  126. return FALSE;
  127. }
  128. //
  129. // Generate the key control structure.
  130. //
  131. rc4_key(&ISNRC4Key, ISN_KEY_SIZE, pBuf);
  132. //
  133. // Initalialize the current sequence number to a random value.
  134. //
  135. rc4(&ISNRC4Key, sizeof(SeqNum), (uchar*)&ISNMonotonicPortion);
  136. //
  137. // Obtain a random value to be used along with the invariants to compute
  138. // the MD5 hash.
  139. //
  140. rc4(&ISNRC4Key, sizeof(ISNRandomValue), (uchar*)&ISNRandomValue);
  141. //
  142. // Round down the store size to power of 2. Verify in range.
  143. //
  144. while ((ISNStoreSize = ISNStoreSize >> 1) != 0) {
  145. cBits++;
  146. }
  147. ISNStoreSize = 1 << cBits;
  148. if (ISNStoreSize < ISN_MIN_RAND_STORE_SIZE ||
  149. ISNStoreSize > ISN_MAX_RAND_STORE_SIZE) {
  150. ISNStoreSize = ISN_DEF_RAND_STORE_SIZE;
  151. }
  152. //
  153. // The mask is store size - 1.
  154. //
  155. ISNStoreMask = ISNStoreSize - 1;
  156. //
  157. // Initialize the random ISN store. One array/index per processor.
  158. //
  159. ISNStore = ExAllocatePool(NonPagedPool, cProcs * sizeof(ISN_RAND_STORE));
  160. if (ISNStore == NULL) {
  161. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_RARE,
  162. "Tcpip: failed to allocate ISN rand store\n"));
  163. return FALSE;
  164. }
  165. RtlZeroMemory(ISNStore, sizeof(ISN_RAND_STORE) * cProcs);
  166. for (i = 0; i < cProcs; i++) {
  167. ISNStore[i].pBuf = ExAllocatePool(NonPagedPool,
  168. sizeof(ushort) * ISNStoreSize);
  169. if (ISNStore[i].pBuf == NULL) {
  170. goto error1;
  171. }
  172. rc4(&ISNRC4Key,
  173. sizeof(ushort) * ISNStoreSize,
  174. (uchar*)ISNStore[i].pBuf);
  175. //
  176. // Initialize structures required to call the MD5 transform.
  177. //
  178. MD5InitializeData(&ISNStore[i].Md5Context, ISNRandomValue);
  179. }
  180. return TRUE;
  181. error1:
  182. UnloadISNGenerator();
  183. return FALSE;
  184. }
  185. //* GetRandomISN - Gets a random Initial Sequence Number.
  186. //
  187. // Called when an Initial Sequence Number (ISN) is needed. Calls crypto
  188. // functions for random number generation.
  189. //
  190. void // Returns: Nothing.
  191. GetRandomISN(
  192. SeqNum *Seq, // Returned sequence number
  193. uchar *TcbInvariants) // Connection invariants
  194. {
  195. ulong randbits;
  196. ulong iProc;
  197. PMD5_CONTEXT Md5Context;
  198. //
  199. // Raise IRQL to DISPATCH so that we don't get swapped out while accessing
  200. // the processor specific array. Check to see if already at DISPATCH
  201. // before doing the work.
  202. //
  203. ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
  204. iProc = KeGetCurrentProcessorNumber();
  205. //
  206. // Add the random number only if the number of connections that can
  207. // increment the sequence number within this time period is non zero.
  208. // [Note: This could make the ISNCredits less than 0, but it is not a
  209. // problem].
  210. //
  211. if ((ISNCredits > 0) && (InterlockedDecrement((PLONG)&ISNCredits) > 0)) {
  212. randbits = GetRandBits();
  213. //
  214. // We want to add between 16K and 32K of random, so adjust. There are
  215. // 15 bits of randomness, just ensure that the high order bit is set
  216. // and we have >= 16K and <= (32K-1)::14bits of randomness.
  217. //
  218. randbits &= 0x7FFF;
  219. randbits |= 0x4000;
  220. } else {
  221. int Delta = GetDeltaTime();
  222. if (Delta > 0) {
  223. randbits = GetRandBits();
  224. //
  225. // We can add anywhere from 256 to 512 per ms.
  226. //
  227. randbits &= 0x1FF;
  228. randbits |= 0x100;
  229. randbits *= Delta;
  230. } else {
  231. randbits = 0;
  232. }
  233. }
  234. //
  235. // Update global CurISN. InterlockedExchangeAdd returns initial value
  236. // (not the added value).
  237. //
  238. *Seq = InterlockedExchangeAdd((PLONG)&ISNMonotonicPortion, randbits);
  239. //
  240. // Move the invariants from the connection.
  241. //
  242. Md5Context = &ISNStore[iProc].Md5Context;
  243. MD5InitializeScratch(Md5Context);
  244. RtlCopyMemory(Md5Context->Data, TcbInvariants, TCP_MD5_DATA_LENGTH);
  245. TransformMD5(Md5Context->Scratch, Md5Context->Data);
  246. //
  247. // Add the Invariant hash to the sequence number.
  248. //
  249. *Seq += (ULONG)(Md5Context->Scratch[0]);
  250. return;
  251. }
  252. //* GetRandBits
  253. //
  254. // Returns 16 random bits from the random number array generated using RC4.
  255. // When the store is exhausted, it will be replenished.
  256. //
  257. int // Returns: 16 bits of random data.
  258. GetRandBits()
  259. {
  260. ulong iStore;
  261. int randbits;
  262. ulong iProc = KeGetCurrentProcessorNumber();
  263. //
  264. // Get index into the random store. Mask performs mod operation.
  265. //
  266. iStore = ++ISNStore[iProc].iBuf & ISNStoreMask;
  267. ASSERT(iStore < ISNStoreSize);
  268. randbits = ISNStore[iProc].pBuf[iStore];
  269. if (iStore == 0) {
  270. rc4(&ISNRC4Key,
  271. sizeof(ushort) * ISNStoreSize,
  272. (uchar*) ISNStore[iProc].pBuf);
  273. }
  274. return randbits;
  275. }
  276. //* GetRandBits
  277. //
  278. // Tracks the time-based updates of ISN. It will return the time elapsed since
  279. // the last time this function was called. This would be used by the caller to
  280. // increment the ISN by an appropriate amount. Note that the maximum value
  281. // is function returns is 200 MS.
  282. //
  283. uint // Returns: Delta time in milli-seconds.
  284. GetDeltaTime()
  285. {
  286. //
  287. // If the time has changed since the ISN was updated last time, it
  288. // can be incremented now.
  289. //
  290. int PreviousUpdateTime, Delta;
  291. int CurrentUpdateTime = (int)X100NSTOMS(KeQueryInterruptTime());
  292. PreviousUpdateTime = InterlockedExchange((PLONG)&ISNLastIsnUpdateTime,
  293. CurrentUpdateTime);
  294. Delta = CurrentUpdateTime - PreviousUpdateTime;
  295. if (Delta > 0) {
  296. return MIN(Delta, 200);
  297. } else {
  298. return 0;
  299. }
  300. }
  301. //
  302. // Routines for handling conn refcount going to 0.
  303. //
  304. //* DummyDone - Called when nothing to do.
  305. //
  306. // Called with TCPConnBlock.cb_lock held.
  307. //
  308. void // Returns: Nothing.
  309. DummyDone(TCPConn *Conn, // Connection going to 0.
  310. KIRQL PreLockIrql) // IRQL prior to TCPConnBlock.cb_lock acquisition.
  311. {
  312. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, PreLockIrql);
  313. }
  314. //* DummyCmplt - Dummy close completion routine.
  315. void
  316. DummyCmplt(PVOID Dummy1, uint Dummy2, uint Dummy3)
  317. {
  318. UNREFERENCED_PARAMETER(Dummy1);
  319. UNREFERENCED_PARAMETER(Dummy2);
  320. UNREFERENCED_PARAMETER(Dummy3);
  321. }
  322. //* CloseDone - Called when we need to complete a close.
  323. //
  324. // Called with TCPConnBlock.cb_lock held.
  325. //
  326. void // Returns: Nothing.
  327. CloseDone(TCPConn *Conn, // Connection going to 0.
  328. KIRQL Irql0) // IRQL prior to TCPConnBlock.cb_lock acquisition.
  329. {
  330. RequestCompleteRoutine Rtn; // Completion routine.
  331. PVOID Context; // User context for completion routine.
  332. AddrObj *AO;
  333. KIRQL Irql1, Irql2;
  334. ASSERT(Conn->tc_flags & CONN_CLOSING);
  335. Rtn = Conn->tc_rtn;
  336. Context = Conn->tc_rtncontext;
  337. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, Irql0);
  338. KeAcquireSpinLock(&AddrObjTableLock, &Irql0);
  339. KeAcquireSpinLock(&Conn->tc_ConnBlock->cb_lock, &Irql1);
  340. if ((AO = Conn->tc_ao) != NULL) {
  341. CHECK_STRUCT(AO, ao);
  342. // It's associated.
  343. KeAcquireSpinLock(&AO->ao_lock, &Irql2);
  344. RemoveConnFromAO(AO, Conn);
  345. // We've pulled him from the AO, we can free the lock now.
  346. KeReleaseSpinLock(&AO->ao_lock, Irql2);
  347. }
  348. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, Irql1);
  349. KeReleaseSpinLock(&AddrObjTableLock, Irql0);
  350. ExFreePool(Conn);
  351. (*Rtn)(Context, TDI_SUCCESS, 0);
  352. }
  353. //* DisassocDone - Called when we need to complete a disassociate.
  354. //
  355. // Called with TCPConnBlock.cb_lock held.
  356. //
  357. void // Returns: Nothing.
  358. DisassocDone(TCPConn *Conn, // Connection going to 0.
  359. KIRQL Irql0) // IRQL prior to TCPConnBlock.cb_lock acquisition.
  360. {
  361. RequestCompleteRoutine Rtn; // Completion routine.
  362. PVOID Context; // User context for completion routine.
  363. AddrObj *AO;
  364. uint NeedClose = FALSE;
  365. KIRQL Irql1, Irql2;
  366. ASSERT(Conn->tc_flags & CONN_DISACC);
  367. ASSERT(!(Conn->tc_flags & CONN_CLOSING));
  368. ASSERT(Conn->tc_refcnt == 0);
  369. Rtn = Conn->tc_rtn;
  370. Context = Conn->tc_rtncontext;
  371. Conn->tc_refcnt = 1;
  372. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, Irql0);
  373. KeAcquireSpinLock(&AddrObjTableLock, &Irql0);
  374. KeAcquireSpinLock(&Conn->tc_ConnBlock->cb_lock, &Irql1);
  375. if (!(Conn->tc_flags & CONN_CLOSING)) {
  376. AO = Conn->tc_ao;
  377. if (AO != NULL) {
  378. KeAcquireSpinLock(&AO->ao_lock, &Irql2);
  379. RemoveConnFromAO(AO, Conn);
  380. KeReleaseSpinLock(&AO->ao_lock, Irql2);
  381. }
  382. ASSERT(Conn->tc_refcnt == 1);
  383. Conn->tc_flags &= ~CONN_DISACC;
  384. } else
  385. NeedClose = TRUE;
  386. Conn->tc_refcnt = 0;
  387. KeReleaseSpinLock(&AddrObjTableLock, Irql1);
  388. if (NeedClose) {
  389. CloseDone(Conn, Irql0);
  390. } else {
  391. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, Irql0);
  392. (*Rtn)(Context, TDI_SUCCESS, 0);
  393. }
  394. }
  395. //* FreeConnReq - Free a connection request structure.
  396. //
  397. // Called to free a connection request structure.
  398. //
  399. void // Returns: Nothing.
  400. FreeConnReq(
  401. TCPConnReq *FreedReq) // Connection request structure to be freed.
  402. {
  403. PSLIST_ENTRY BufferLink;
  404. CHECK_STRUCT(FreedReq, tcr);
  405. BufferLink = CONTAINING_RECORD(&(FreedReq->tcr_req.tr_q.q_next),
  406. SLIST_ENTRY, Next);
  407. ExInterlockedPushEntrySList(&ConnReqFree, BufferLink, &ConnReqFreeLock);
  408. }
  409. //* GetConnReq - Get a connection request structure.
  410. //
  411. // Called to get a connection request structure.
  412. //
  413. TCPConnReq * // Returns: Pointer to ConnReq structure, or NULL if none.
  414. GetConnReq(void) // Nothing.
  415. {
  416. TCPConnReq *Temp;
  417. PSLIST_ENTRY BufferLink;
  418. Queue *QueuePtr;
  419. TCPReq *ReqPtr;
  420. BufferLink = ExInterlockedPopEntrySList(&ConnReqFree, &ConnReqFreeLock);
  421. if (BufferLink != NULL) {
  422. QueuePtr = CONTAINING_RECORD(BufferLink, Queue, q_next);
  423. ReqPtr = CONTAINING_RECORD(QueuePtr, TCPReq, tr_q);
  424. Temp = CONTAINING_RECORD(ReqPtr, TCPConnReq, tcr_req);
  425. CHECK_STRUCT(Temp, tcr);
  426. } else {
  427. if (NumConnReq < MaxConnReq)
  428. Temp = ExAllocatePool(NonPagedPool, sizeof(TCPConnReq));
  429. else
  430. Temp = NULL;
  431. if (Temp != NULL) {
  432. ExInterlockedAddUlong((PULONG)&NumConnReq, 1, &ConnReqFreeLock);
  433. #if DBG
  434. Temp->tcr_req.tr_sig = tr_signature;
  435. Temp->tcr_sig = tcr_signature;
  436. #endif
  437. }
  438. }
  439. return Temp;
  440. }
  441. //* GetConnFromConnID - Get a Connection from a connection ID.
  442. //
  443. // Called to obtain a Connection pointer from a ConnID. We don't actually
  444. // check the connection pointer here, but we do bounds check the input ConnID
  445. // and make sure the instance fields match.
  446. // If successful, returns with TCPConnBlock.cb_lock held.
  447. //
  448. TCPConn * // Returns: Pointer to the TCPConn, or NULL.
  449. GetConnFromConnID(
  450. uint ConnID, // Connection ID to find a pointer for.
  451. KIRQL* Irql) // Receives IRQL prior to TCPConnBlock.cb_lock acquisition.
  452. {
  453. uint ConnIndex = CONN_INDEX(ConnID);
  454. uint ConnBlockId = CONN_BLOCKID(ConnID);
  455. TCPConn *MatchingConn = NULL;
  456. TCPConnBlock *ConnBlock;
  457. if (ConnIndex < MAX_CONN_PER_BLOCK && ConnBlockId < MaxAllocatedConnBlocks) {
  458. ConnBlock = ConnTable[ConnBlockId];
  459. if (ConnBlock) {
  460. MatchingConn = ConnBlock->cb_conn[ConnIndex];
  461. }
  462. if (MatchingConn != NULL) {
  463. KeAcquireSpinLock(&ConnBlock->cb_lock, Irql);
  464. //
  465. // Revalidate under lock that the conn is still in conn table.
  466. //
  467. MatchingConn = ConnBlock->cb_conn[ConnIndex];
  468. if (MatchingConn != NULL) {
  469. CHECK_STRUCT(MatchingConn, tc);
  470. if (MatchingConn->tc_inst != CONN_INST(ConnID)) {
  471. MatchingConn = NULL;
  472. KeReleaseSpinLock(&ConnBlock->cb_lock, *Irql);
  473. }
  474. } else {
  475. KeReleaseSpinLock(&ConnBlock->cb_lock, *Irql);
  476. }
  477. }
  478. } else
  479. MatchingConn = NULL;
  480. return MatchingConn;
  481. }
  482. //* GetConnID - Get a ConnTable slot.
  483. //
  484. // Called during OpenConnection to find a free slot in the ConnTable and
  485. // set it up with a connection.
  486. // If successful, returns with TCPConnBlock.cb_lock held.
  487. //
  488. uint // Returns: A ConnId to use.
  489. GetConnID(
  490. TCPConn *NewConn, // Connection to enter into slot.
  491. KIRQL *Irql0) // Receives IRQL prior to TCPConnBlock.cb_lock
  492. // acquisition.
  493. {
  494. uint CurrConnID = NewConn->tc_connid;
  495. uint i, j, BlockID, ConnIndex;
  496. //
  497. // If NewConn contains a valid ConnID and that location is unoccupied,
  498. // reuse it.
  499. //
  500. if (CurrConnID != INVALID_CONN_ID &&
  501. !NewConn->tc_ConnBlock->cb_conn[CONN_INDEX(CurrConnID)]) {
  502. KeAcquireSpinLock(&NewConn->tc_ConnBlock->cb_lock, Irql0);
  503. //
  504. // Reconfirm under lock that the location is unoccupied and, if so,
  505. // claim it.
  506. //
  507. if (!NewConn->tc_ConnBlock->cb_conn[CONN_INDEX(CurrConnID)]) {
  508. NewConn->tc_ConnBlock->cb_conn[CONN_INDEX(CurrConnID)] = NewConn;
  509. NewConn->tc_ConnBlock->cb_freecons--;
  510. NewConn->tc_inst = NewConn->tc_ConnBlock->cb_conninst++;
  511. NewConn->tc_connid = MAKE_CONN_ID(CONN_INDEX(CurrConnID),
  512. NewConn->tc_ConnBlock->cb_blockid,
  513. NewConn->tc_inst);
  514. return NewConn->tc_connid;
  515. }
  516. KeReleaseSpinLock(&NewConn->tc_ConnBlock->cb_lock, *Irql0);
  517. }
  518. //
  519. // NewConn's last spot is taken; search from the block from which
  520. // a ConnID was claimed most recently.
  521. //
  522. if (MaxAllocatedConnBlocks) {
  523. //
  524. // Capture the global counters without acquiring the lock.
  525. //
  526. uint TempMaxAllocatedConnBlocks = MaxAllocatedConnBlocks;
  527. uint TempNextConnBlock = NextConnBlock;
  528. for (i = 0; i < TempMaxAllocatedConnBlocks; i++) {
  529. BlockID = (TempNextConnBlock + i) % TempMaxAllocatedConnBlocks;
  530. if (!ConnTable[BlockID] || !ConnTable[BlockID]->cb_freecons) {
  531. continue;
  532. }
  533. //
  534. // Reconfirm under lock that the TCPConnBlock has free slots.
  535. //
  536. KeAcquireSpinLock(&ConnTable[BlockID]->cb_lock, Irql0);
  537. if (!ConnTable[BlockID]->cb_freecons) {
  538. KeReleaseSpinLock(&ConnTable[BlockID]->cb_lock, *Irql0);
  539. continue;
  540. }
  541. for (j = 0; j < MAX_CONN_PER_BLOCK; j++) {
  542. ConnIndex = (ConnTable[BlockID]->cb_nextfree + j) %
  543. MAX_CONN_PER_BLOCK;
  544. if (ConnTable[BlockID]->cb_conn[ConnIndex]) {
  545. continue;
  546. }
  547. //
  548. // Found the free slot; fill it in.
  549. //
  550. ConnTable[BlockID]->cb_conn[ConnIndex] = NewConn;
  551. ConnTable[BlockID]->cb_nextfree = ConnIndex + 1;
  552. ConnTable[BlockID]->cb_freecons--;
  553. if (!ConnTable[BlockID]->cb_freecons) {
  554. InterlockedCompareExchange((PLONG)&NextConnBlock,
  555. TempNextConnBlock,
  556. TempNextConnBlock + 1);
  557. }
  558. NewConn->tc_ConnBlock = ConnTable[BlockID];
  559. NewConn->tc_inst = ConnTable[BlockID]->cb_conninst++;
  560. NewConn->tc_connid = MAKE_CONN_ID(ConnIndex, BlockID,
  561. NewConn->tc_inst);
  562. return NewConn->tc_connid;
  563. }
  564. KeReleaseSpinLock(&ConnTable[BlockID]->cb_lock, *Irql0);
  565. }
  566. }
  567. //
  568. // The entire table is occupied; if we have room to grow,
  569. // allocate a new block.
  570. //
  571. KeAcquireSpinLock(&ConnTableLock, Irql0);
  572. if (MaxAllocatedConnBlocks < MaxConnBlocks) {
  573. TCPConnBlock* ConnBlock;
  574. BlockID = MaxAllocatedConnBlocks;
  575. ConnBlock = ExAllocatePool(NonPagedPool, sizeof(TCPConnBlock));
  576. if (ConnBlock) {
  577. RtlZeroMemory(ConnBlock, sizeof(TCPConnBlock));
  578. KeInitializeSpinLock(&ConnBlock->cb_lock);
  579. KeAcquireSpinLockAtDpcLevel(&ConnBlock->cb_lock);
  580. ConnBlock->cb_blockid = BlockID;
  581. ConnBlock->cb_freecons = MAX_CONN_PER_BLOCK - 1;
  582. ConnBlock->cb_nextfree = 1;
  583. ConnBlock->cb_conninst = 2;
  584. ConnBlock->cb_conn[0] = NewConn;
  585. NewConn->tc_ConnBlock = ConnBlock;
  586. NewConn->tc_inst = 1;
  587. NewConn->tc_connid = MAKE_CONN_ID(0, BlockID, NewConn->tc_inst);
  588. ConnTable[BlockID] = ConnBlock;
  589. InterlockedIncrement((PLONG)&MaxAllocatedConnBlocks);
  590. KeReleaseSpinLockFromDpcLevel(&ConnTableLock);
  591. return NewConn->tc_connid;
  592. }
  593. }
  594. KeReleaseSpinLock(&ConnTableLock, *Irql0);
  595. return INVALID_CONN_ID;
  596. }
  597. //* FreeConnID - Free a ConnTable slot.
  598. //
  599. // Called when we're done with a ConnID. We assume the caller holds the lock
  600. // on the TCPConnBlock when we are called.
  601. //
  602. void // Returns: Nothing.
  603. FreeConnID(
  604. TCPConn *Conn) // Conn to be freed.
  605. {
  606. uint ConnIndex = CONN_INDEX(Conn->tc_connid); // Index into conn table.
  607. uint BlockID = CONN_BLOCKID(Conn->tc_connid);
  608. TCPConnBlock* ConnBlock = Conn->tc_ConnBlock;
  609. ASSERT(ConnIndex < MAX_CONN_PER_BLOCK);
  610. ASSERT(BlockID < MaxAllocatedConnBlocks);
  611. ASSERT(ConnBlock->cb_conn[ConnIndex] != NULL);
  612. if (ConnBlock->cb_conn[ConnIndex]) {
  613. ConnBlock->cb_conn[ConnIndex] = NULL;
  614. ConnBlock->cb_freecons++;
  615. ConnBlock->cb_nextfree = ConnIndex;
  616. ASSERT(ConnBlock->cb_freecons <= MAX_CONN_PER_BLOCK);
  617. } else {
  618. ABORT();
  619. }
  620. }
  621. //* MapIPError - Map an IP error to a TDI error.
  622. //
  623. // Called to map an input IP error code to a TDI error code. If we can't,
  624. // we return the provided default.
  625. //
  626. TDI_STATUS // Returns: Mapped TDI error.
  627. MapIPError(
  628. IP_STATUS IPError, // Error code to be mapped.
  629. TDI_STATUS Default) // Default error code to return.
  630. {
  631. switch (IPError) {
  632. case IP_DEST_NO_ROUTE:
  633. return TDI_DEST_NET_UNREACH;
  634. case IP_DEST_ADDR_UNREACHABLE:
  635. return TDI_DEST_HOST_UNREACH;
  636. case IP_UNRECOGNIZED_NEXT_HEADER:
  637. return TDI_DEST_PROT_UNREACH;
  638. case IP_DEST_PORT_UNREACHABLE:
  639. return TDI_DEST_PORT_UNREACH;
  640. default:
  641. return Default;
  642. }
  643. }
  644. //* FinishRemoveTCBFromConn - Finish removing a TCB from a conn structure.
  645. //
  646. // Called when we have the locks we need and we just want to pull the
  647. // TCB off the connection.
  648. //
  649. void // Returns: Nothing.
  650. FinishRemoveTCBFromConn(
  651. TCB *RemovedTCB) // TCB to be removed.
  652. {
  653. TCPConn *Conn;
  654. AddrObj *AO;
  655. KIRQL Irql;
  656. TCPConnBlock *ConnBlock = NULL;
  657. if (((Conn = RemovedTCB->tcb_conn) != NULL) &&
  658. (Conn->tc_tcb == RemovedTCB)) {
  659. CHECK_STRUCT(Conn, tc);
  660. ConnBlock = Conn->tc_ConnBlock;
  661. KeAcquireSpinLock(&ConnBlock->cb_lock, &Irql);
  662. AO = Conn->tc_ao;
  663. if (AO != NULL) {
  664. KeAcquireSpinLockAtDpcLevel(&AO->ao_lock);
  665. if (AO_VALID(AO)) {
  666. KeAcquireSpinLockAtDpcLevel(&RemovedTCB->tcb_lock);
  667. // Need to double check this is still correct.
  668. if (Conn == RemovedTCB->tcb_conn) {
  669. // Everything still looks good.
  670. REMOVEQ(&Conn->tc_q);
  671. PUSHQ(&AO->ao_idleq, &Conn->tc_q);
  672. } else
  673. Conn = RemovedTCB->tcb_conn;
  674. } else {
  675. KeAcquireSpinLockAtDpcLevel(&RemovedTCB->tcb_lock);
  676. Conn = RemovedTCB->tcb_conn;
  677. }
  678. KeReleaseSpinLockFromDpcLevel(&AO->ao_lock);
  679. } else {
  680. KeAcquireSpinLockAtDpcLevel(&RemovedTCB->tcb_lock);
  681. Conn = RemovedTCB->tcb_conn;
  682. }
  683. if (Conn != NULL) {
  684. if (Conn->tc_tcb == RemovedTCB)
  685. Conn->tc_tcb = NULL;
  686. else
  687. ASSERT(Conn->tc_tcb == NULL);
  688. }
  689. KeReleaseSpinLockFromDpcLevel(&RemovedTCB->tcb_lock);
  690. KeReleaseSpinLock(&ConnBlock->cb_lock, Irql);
  691. }
  692. }
  693. //* RemoveTCBFromConn - Remove a TCB from a Conn structure.
  694. //
  695. // Called when we need to disassociate a TCB from a connection structure.
  696. // All we do is get the appropriate locks and call FinishRemoveTCBFromConn.
  697. //
  698. void // Returns: Nothing.
  699. RemoveTCBFromConn(
  700. TCB *RemovedTCB) // TCB to be removed.
  701. {
  702. CHECK_STRUCT(RemovedTCB, tcb);
  703. FinishRemoveTCBFromConn(RemovedTCB);
  704. }
  705. //* RemoveConnFromTCB - Remove a conn from a TCB.
  706. //
  707. // Called when we want to break the final association between a connection
  708. // and a TCB.
  709. //
  710. void // Returns: Nothing.
  711. RemoveConnFromTCB(
  712. TCB *RemoveTCB) // TCB to be removed.
  713. {
  714. ConnDoneRtn DoneRtn = NULL;
  715. KIRQL Irql = 0;
  716. TCPConn *Conn;
  717. if ((Conn = RemoveTCB->tcb_conn) != NULL) {
  718. KeAcquireSpinLock(&Conn->tc_ConnBlock->cb_lock, &Irql);
  719. KeAcquireSpinLockAtDpcLevel(&RemoveTCB->tcb_lock);
  720. CHECK_STRUCT(Conn, tc);
  721. if (--(Conn->tc_refcnt) == 0)
  722. DoneRtn = Conn->tc_donertn;
  723. RemoveTCB->tcb_conn = NULL;
  724. KeReleaseSpinLockFromDpcLevel(&RemoveTCB->tcb_lock);
  725. }
  726. if (DoneRtn != NULL)
  727. (*DoneRtn)(Conn, Irql);
  728. else if (Conn) {
  729. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, Irql);
  730. }
  731. }
  732. //* CloseTCB - Close a TCB.
  733. //
  734. // Called when we are done with a TCB, and want to free it. We'll remove
  735. // him from any tables that he's in, and destroy any outstanding requests.
  736. //
  737. void // Returns: Nothing.
  738. CloseTCB(
  739. TCB *ClosedTCB, // TCB to be closed.
  740. KIRQL OldIrql) // IRQL prior to acquiring TCB lock.
  741. {
  742. uchar OrigState = ClosedTCB->tcb_state;
  743. TDI_STATUS Status;
  744. uint OKToFree;
  745. CHECK_STRUCT(ClosedTCB, tcb);
  746. ASSERT(ClosedTCB->tcb_refcnt == 0);
  747. ASSERT(ClosedTCB->tcb_state != TCB_CLOSED);
  748. ASSERT(ClosedTCB->tcb_pending & DEL_PENDING);
  749. //
  750. // We'll check to make sure that our state isn't CLOSED. This should never
  751. // happen, since nobody should call TryToCloseTCB when the state is
  752. // closed, or take the reference count if we're closing. Nevertheless,
  753. // we'll double check as a safety measure.
  754. //
  755. if (ClosedTCB->tcb_state == TCB_CLOSED) {
  756. KeReleaseSpinLock(&ClosedTCB->tcb_lock, OldIrql);
  757. return;
  758. }
  759. //
  760. // Update SNMP counters. If we're in SYN-SENT or SYN-RCVD, this is a
  761. // failed connection attempt. If we're in ESTABLISED or CLOSE-WAIT,
  762. // treat this as an 'Established Reset' event.
  763. //
  764. if (ClosedTCB->tcb_state == TCB_SYN_SENT ||
  765. ClosedTCB->tcb_state == TCB_SYN_RCVD)
  766. TStats.ts_attemptfails++;
  767. else
  768. if (ClosedTCB->tcb_state == TCB_ESTAB ||
  769. ClosedTCB->tcb_state == TCB_CLOSE_WAIT) {
  770. TStats.ts_estabresets++;
  771. InterlockedDecrement((PLONG)&TStats.ts_currestab);
  772. ASSERT(*(int *)&TStats.ts_currestab >= 0);
  773. }
  774. ClosedTCB->tcb_state = TCB_CLOSED;
  775. KeReleaseSpinLockFromDpcLevel(&ClosedTCB->tcb_lock);
  776. //
  777. // Remove the TCB from it's associated TCPConn structure, if it has one.
  778. //
  779. FinishRemoveTCBFromConn(ClosedTCB);
  780. KeAcquireSpinLockAtDpcLevel(&TCBTableLock);
  781. KeAcquireSpinLockAtDpcLevel(&ClosedTCB->tcb_lock);
  782. OKToFree = RemoveTCB(ClosedTCB);
  783. //
  784. // He's been pulled from the appropriate places so nobody can find him.
  785. // Free the locks, and proceed to destroy any requests, etc.
  786. //
  787. KeReleaseSpinLockFromDpcLevel(&ClosedTCB->tcb_lock);
  788. KeReleaseSpinLock(&TCBTableLock, OldIrql);
  789. if ((SYNC_STATE(OrigState) || OrigState == TCB_SYN_RCVD) &&
  790. !GRACEFUL_CLOSED_STATE(OrigState)) {
  791. if (ClosedTCB->tcb_flags & NEED_RST)
  792. SendRSTFromTCB(ClosedTCB);
  793. }
  794. //
  795. // Release our references on our NTE and RCE.
  796. // We won't be sending anymore on this TCB.
  797. //
  798. if (ClosedTCB->tcb_nte != NULL)
  799. ReleaseNTE(ClosedTCB->tcb_nte);
  800. if (ClosedTCB->tcb_rce != NULL)
  801. ReleaseRCE(ClosedTCB->tcb_rce);
  802. if (ClosedTCB->tcb_closereason & TCB_CLOSE_RST)
  803. Status = TDI_CONNECTION_RESET;
  804. else if (ClosedTCB->tcb_closereason & TCB_CLOSE_ABORTED)
  805. Status = TDI_CONNECTION_ABORTED;
  806. else if (ClosedTCB->tcb_closereason & TCB_CLOSE_TIMEOUT)
  807. Status = MapIPError(ClosedTCB->tcb_error, TDI_TIMED_OUT);
  808. else if (ClosedTCB->tcb_closereason & TCB_CLOSE_REFUSED)
  809. Status = TDI_CONN_REFUSED;
  810. else if (ClosedTCB->tcb_closereason & TCB_CLOSE_UNREACH)
  811. Status = MapIPError(ClosedTCB->tcb_error, TDI_DEST_UNREACHABLE);
  812. else
  813. Status = TDI_SUCCESS;
  814. //
  815. // Now complete any outstanding requests on the TCB.
  816. //
  817. if (ClosedTCB->tcb_abortreq != NULL) {
  818. TCPAbortReq* AbortReq = ClosedTCB->tcb_abortreq;
  819. (*AbortReq->tar_rtn)(AbortReq->tar_context, TDI_SUCCESS, 0);
  820. }
  821. if (ClosedTCB->tcb_connreq != NULL) {
  822. TCPConnReq *ConnReq = ClosedTCB->tcb_connreq;
  823. CHECK_STRUCT(ConnReq, tcr);
  824. (*ConnReq->tcr_req.tr_rtn)(ConnReq->tcr_req.tr_context, Status, 0);
  825. FreeConnReq(ConnReq);
  826. }
  827. if (ClosedTCB->tcb_discwait != NULL) {
  828. TCPConnReq *ConnReq = ClosedTCB->tcb_discwait;
  829. CHECK_STRUCT(ConnReq, tcr);
  830. (*ConnReq->tcr_req.tr_rtn)(ConnReq->tcr_req.tr_context, Status, 0);
  831. FreeConnReq(ConnReq);
  832. }
  833. while (!EMPTYQ(&ClosedTCB->tcb_sendq)) {
  834. TCPReq *Req;
  835. TCPSendReq *SendReq;
  836. long Result;
  837. DEQUEUE(&ClosedTCB->tcb_sendq, Req, TCPReq, tr_q);
  838. CHECK_STRUCT(Req, tr);
  839. SendReq = (TCPSendReq *)Req;
  840. CHECK_STRUCT(SendReq, tsr);
  841. //
  842. // Set the status before dropping the ref count.
  843. //
  844. SendReq->tsr_req.tr_status = Status;
  845. //
  846. // Decrement the initial reference put on the buffer when it was
  847. // allocated. This reference would have been decremented if the
  848. // send had been acknowledged, but then the send would not still
  849. // be on the tcb_sendq.
  850. //
  851. Result = InterlockedDecrement(&(SendReq->tsr_refcnt));
  852. ASSERT(Result >= 0);
  853. if (Result <= 0) {
  854. // If we've sent directly from this send, NULL out the next
  855. // pointer for the last buffer in the chain.
  856. if (SendReq->tsr_lastbuf != NULL) {
  857. NDIS_BUFFER_LINKAGE(SendReq->tsr_lastbuf) = NULL;
  858. SendReq->tsr_lastbuf = NULL;
  859. }
  860. (*Req->tr_rtn)(Req->tr_context, Status, 0);
  861. FreeSendReq(SendReq);
  862. }
  863. }
  864. while (ClosedTCB->tcb_rcvhead != NULL) {
  865. TCPRcvReq *RcvReq;
  866. RcvReq = ClosedTCB->tcb_rcvhead;
  867. CHECK_STRUCT(RcvReq, trr);
  868. ClosedTCB->tcb_rcvhead = RcvReq->trr_next;
  869. (*RcvReq->trr_rtn)(RcvReq->trr_context, Status, 0);
  870. FreeRcvReq(RcvReq);
  871. }
  872. while (ClosedTCB->tcb_exprcv != NULL) {
  873. TCPRcvReq *RcvReq;
  874. RcvReq = ClosedTCB->tcb_exprcv;
  875. CHECK_STRUCT(RcvReq, trr);
  876. ClosedTCB->tcb_exprcv = RcvReq->trr_next;
  877. (*RcvReq->trr_rtn)(RcvReq->trr_context, Status, 0);
  878. FreeRcvReq(RcvReq);
  879. }
  880. if (ClosedTCB->tcb_pendhead != NULL)
  881. FreePacketChain(ClosedTCB->tcb_pendhead);
  882. if (ClosedTCB->tcb_urgpending != NULL)
  883. FreePacketChain(ClosedTCB->tcb_urgpending);
  884. while (ClosedTCB->tcb_raq != NULL) {
  885. TCPRAHdr *Hdr;
  886. Hdr = ClosedTCB->tcb_raq;
  887. CHECK_STRUCT(Hdr, trh);
  888. ClosedTCB->tcb_raq = Hdr->trh_next;
  889. if (Hdr->trh_buffer != NULL)
  890. FreePacketChain(Hdr->trh_buffer);
  891. ExFreePool(Hdr);
  892. }
  893. RemoveConnFromTCB(ClosedTCB);
  894. if (OKToFree) {
  895. FreeTCB(ClosedTCB);
  896. } else {
  897. KeAcquireSpinLock(&TCBTableLock, &OldIrql);
  898. ClosedTCB->tcb_walkcount--;
  899. if (ClosedTCB->tcb_walkcount == 0) {
  900. FreeTCB(ClosedTCB);
  901. }
  902. KeReleaseSpinLock(&TCBTableLock, OldIrql);
  903. }
  904. }
  905. //* TryToCloseTCB - Try to close a TCB.
  906. //
  907. // Called when we need to close a TCB, but don't know if we can.
  908. // If the reference count is 0, we'll call CloseTCB to deal with it.
  909. // Otherwise we'll set the DELETE_PENDING bit and deal with it when the
  910. // ref. count goes to 0. We assume the TCB is locked when we are called.
  911. //
  912. void // Returns: Nothing.
  913. TryToCloseTCB (
  914. TCB *ClosedTCB, // TCB to be closed.
  915. uchar Reason, // Reason we're closing.
  916. KIRQL PreLockIrql) // IRQL prior to acquiring the TCB lock.
  917. {
  918. CHECK_STRUCT(ClosedTCB, tcb);
  919. ASSERT(ClosedTCB->tcb_state != TCB_CLOSED);
  920. ClosedTCB->tcb_closereason |= Reason;
  921. if (ClosedTCB->tcb_pending & DEL_PENDING) {
  922. KeReleaseSpinLock(&ClosedTCB->tcb_lock, PreLockIrql);
  923. return;
  924. }
  925. ClosedTCB->tcb_pending |= DEL_PENDING;
  926. ClosedTCB->tcb_slowcount++;
  927. ClosedTCB->tcb_fastchk |= TCP_FLAG_SLOW;
  928. if (ClosedTCB->tcb_refcnt == 0)
  929. CloseTCB(ClosedTCB, PreLockIrql);
  930. else {
  931. KeReleaseSpinLock(&ClosedTCB->tcb_lock, PreLockIrql);
  932. }
  933. }
  934. //* DerefTCB - Dereference a TCB.
  935. //
  936. // Called when we're done with a TCB, and want to let exclusive user
  937. // have a shot. We dec. the refcount, and if it goes to zero and there
  938. // are pending actions, we'll perform one of the pending actions.
  939. //
  940. void // Returns: Nothing.
  941. DerefTCB(
  942. TCB *DoneTCB, // TCB to be dereffed.
  943. KIRQL PreLockIrql) // IRQL prior to acquiring the TCB lock.
  944. {
  945. ASSERT(DoneTCB->tcb_refcnt != 0);
  946. if (--DoneTCB->tcb_refcnt == 0) {
  947. if (DoneTCB->tcb_pending == 0) {
  948. KeReleaseSpinLock(&DoneTCB->tcb_lock, PreLockIrql);
  949. return;
  950. } else {
  951. if (DoneTCB->tcb_pending & RST_PENDING) {
  952. DoneTCB->tcb_refcnt++;
  953. NotifyOfDisc(DoneTCB, TDI_CONNECTION_RESET, &PreLockIrql);
  954. KeAcquireSpinLock(&DoneTCB->tcb_lock, &PreLockIrql);
  955. DerefTCB(DoneTCB, PreLockIrql);
  956. return;
  957. }
  958. if (DoneTCB->tcb_pending & DEL_PENDING)
  959. CloseTCB(DoneTCB, PreLockIrql);
  960. else
  961. DbgBreakPoint(); // Fatal condition.
  962. return;
  963. }
  964. }
  965. KeReleaseSpinLock(&DoneTCB->tcb_lock, PreLockIrql);
  966. return;
  967. }
  968. //* CalculateMSSForTCB - Update MSS, etc. after PMTU changes.
  969. //
  970. // Calculate our connection's MSS based on our PMTU, the sizes
  971. // of various headers, and the remote side's advertised MSS.
  972. // It's expected that this routine will be called whenever
  973. // our cached copy of the PMTU has been updated to a new value.
  974. //
  975. void
  976. CalculateMSSForTCB(
  977. TCB *ThisTCB) // The TCB we're running our calculations on.
  978. {
  979. uint PMTU;
  980. IPSecProc *IPSecToDo;
  981. uint TrailerLength = 0;
  982. uint IPSecBytes = 0;
  983. uint Dummy;
  984. ASSERT(ThisTCB->tcb_pmtu != 0); // Should be set before entering.
  985. ASSERT(ThisTCB->tcb_rce != NULL);
  986. //
  987. // First check that the PMTU size is reasonable. IP won't
  988. // let it get below minimum, but we have our own maximum since
  989. // currently TCP can only handle an MSS that fits in 16 bits.
  990. // TBD: If we add IPv6 Jumbogram support, we should also add LFN
  991. // TBD: support to TCP and change this to handle a larger MSS.
  992. //
  993. PMTU = ThisTCB->tcb_pmtu;
  994. if (PMTU > 65535) {
  995. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_RARE,
  996. "TCPSend: PMTU update value too large %u\n", PMTU));
  997. PMTU = 65535;
  998. }
  999. //
  1000. // Determine size of IPSec headers, if any.
  1001. //
  1002. IPSecToDo = OutboundSPLookup(&ThisTCB->tcb_saddr, &ThisTCB->tcb_daddr,
  1003. IP_PROTOCOL_TCP,
  1004. net_short(ThisTCB->tcb_sport),
  1005. net_short(ThisTCB->tcb_dport),
  1006. ThisTCB->tcb_rce->NTE->IF, &Dummy);
  1007. if (IPSecToDo != NULL) {
  1008. //
  1009. // Calculate the space needed for the IPSec headers.
  1010. //
  1011. IPSecBytes = IPSecBytesToInsert(IPSecToDo, &Dummy, &TrailerLength);
  1012. FreeIPSecToDo(IPSecToDo, IPSecToDo->BundleSize);
  1013. IPSecBytes += TrailerLength;
  1014. }
  1015. IF_TCPDBG(TCP_DEBUG_MSS) {
  1016. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_TCPDBG,
  1017. "CalculateMSSForTCB: IPSecBytes is %u\n", IPSecBytes));
  1018. }
  1019. //
  1020. // Subtract out the header sizes to yield the TCP MSS.
  1021. // If there is an ESP trailer on this connection, round down
  1022. // the MSS to allow the trailer to end on a 4-byte boundary.
  1023. //
  1024. PMTU -= sizeof(IPv6Header) + sizeof(TCPHeader) + IPSecBytes;
  1025. if (TrailerLength)
  1026. PMTU -= (PMTU & 3);
  1027. //
  1028. // Don't let MSS exceed what our peer advertised, regardless of how
  1029. // large the Path MTU is.
  1030. //
  1031. IF_TCPDBG(TCP_DEBUG_MSS) {
  1032. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_TCPDBG,
  1033. "CalculateMSSForTCB: Old MSS is %u ", ThisTCB->tcb_mss));
  1034. }
  1035. ThisTCB->tcb_mss = (ushort)MIN(PMTU, ThisTCB->tcb_remmss);
  1036. IF_TCPDBG(TCP_DEBUG_MSS) {
  1037. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_TCPDBG,
  1038. "New MSS is %u\n", ThisTCB->tcb_mss));
  1039. }
  1040. ASSERT(ThisTCB->tcb_mss != 0);
  1041. //
  1042. // We don't want our Congestion Window to be smaller than one maximum
  1043. // segment, so we may need to increase it when our MSS grows.
  1044. //
  1045. if (ThisTCB->tcb_cwin < ThisTCB->tcb_mss) {
  1046. ThisTCB->tcb_cwin = ThisTCB->tcb_mss;
  1047. //
  1048. // Make sure the slow start threshold is at
  1049. // least 2 segments.
  1050. //
  1051. if (ThisTCB->tcb_ssthresh < ((uint) ThisTCB->tcb_mss * 2)) {
  1052. ThisTCB->tcb_ssthresh = ThisTCB->tcb_mss * 2;
  1053. }
  1054. }
  1055. }
  1056. //** TdiOpenConnection - Open a connection.
  1057. //
  1058. // This is the TDI Open Connection entry point. We open a connection,
  1059. // and save the caller's connection context. A TCPConn structure is allocated
  1060. // here, but a TCB isn't allocated until the Connect or Listen is done.
  1061. //
  1062. TDI_STATUS // Returns: Status of attempt to open connection.
  1063. TdiOpenConnection(
  1064. PTDI_REQUEST Request, // This TDI request.
  1065. PVOID Context) // Connection context to be save for connection.
  1066. {
  1067. TCPConn *NewConn; // The newly opened connection.
  1068. KIRQL OldIrql; // Irql prior to acquiring TCPConnBlock lock.
  1069. uint ConnID; // New ConnID.
  1070. TDI_STATUS Status; // Status of this request.
  1071. NewConn = ExAllocatePool(NonPagedPool, sizeof(TCPConn));
  1072. if (NewConn != NULL) {
  1073. //
  1074. // We allocated a connection.
  1075. //
  1076. RtlZeroMemory(NewConn, sizeof(TCPConn));
  1077. #if DBG
  1078. NewConn->tc_sig = tc_signature;
  1079. #endif
  1080. NewConn->tc_tcb = NULL;
  1081. NewConn->tc_ao = NULL;
  1082. NewConn->tc_context = Context;
  1083. NewConn->tc_connid = INVALID_CONN_ID;
  1084. ConnID = GetConnID(NewConn, &OldIrql);
  1085. if (ConnID != INVALID_CONN_ID) {
  1086. //
  1087. // We successfully got a ConnID.
  1088. //
  1089. Request->Handle.ConnectionContext = (CONNECTION_CONTEXT)UIntToPtr(ConnID);
  1090. NewConn->tc_refcnt = 0;
  1091. NewConn->tc_flags = 0;
  1092. NewConn->tc_tcbflags = NAGLING | (BSDUrgent ? BSD_URGENT : 0);
  1093. if (DefaultRcvWin != 0) {
  1094. NewConn->tc_window = DefaultRcvWin;
  1095. NewConn->tc_flags |= CONN_WINSET;
  1096. } else
  1097. NewConn->tc_window = DEFAULT_RCV_WIN;
  1098. NewConn->tc_donertn = DummyDone;
  1099. NewConn->tc_owningpid = HandleToUlong(PsGetCurrentProcessId());
  1100. Status = TDI_SUCCESS;
  1101. KeReleaseSpinLock(&NewConn->tc_ConnBlock->cb_lock, OldIrql);
  1102. } else {
  1103. ExFreePool(NewConn);
  1104. Status = TDI_NO_RESOURCES;
  1105. }
  1106. return Status;
  1107. }
  1108. //
  1109. // Couldn't get a connection.
  1110. //
  1111. return TDI_NO_RESOURCES;
  1112. }
  1113. //* RemoveConnFromAO - Remove a connection from an AddrObj.
  1114. //
  1115. // A little utility routine to remove a connection from an AddrObj.
  1116. // We run down the connections on the AO, and when we find him we splice
  1117. // him out. We assume the caller holds the locks on the AddrObj and the
  1118. // TCPConnBlock lock.
  1119. //
  1120. void // Returns: Nothing.
  1121. RemoveConnFromAO(
  1122. AddrObj *AO, // AddrObj to remove from.
  1123. TCPConn *Conn) // Conn to remove.
  1124. {
  1125. CHECK_STRUCT(AO, ao);
  1126. CHECK_STRUCT(Conn, tc);
  1127. REMOVEQ(&Conn->tc_q);
  1128. Conn->tc_ao = NULL;
  1129. }
  1130. //* TdiCloseConnection - Close a connection.
  1131. //
  1132. // Called when the user is done with a connection, and wants to close it.
  1133. // We look the connection up in our table, and if we find it we'll remove
  1134. // the connection from the AddrObj it's associate with (if any). If there's
  1135. // a TCB associated with the connection we'll close it also.
  1136. //
  1137. // There are some interesting wrinkles related to closing while a TCB
  1138. // is still referencing the connection (i.e. tc_refcnt != 0) or while a
  1139. // disassociate address is in progress. See below for more details.
  1140. //
  1141. TDI_STATUS // Returns: Status of attempt to close.
  1142. TdiCloseConnection(
  1143. PTDI_REQUEST Request) // Request identifying connection to be closed.
  1144. {
  1145. uint ConnID = PtrToUlong(Request->Handle.ConnectionContext);
  1146. KIRQL Irql0;
  1147. TCPConn *Conn;
  1148. TDI_STATUS Status;
  1149. //
  1150. // We have the locks we need. Try to find a connection.
  1151. //
  1152. Conn = GetConnFromConnID(ConnID, &Irql0);
  1153. if (Conn != NULL) {
  1154. KIRQL Irql1;
  1155. TCB *ConnTCB;
  1156. //
  1157. // We found the connection. Free the ConnID and mark the connection
  1158. // as closing.
  1159. //
  1160. CHECK_STRUCT(Conn, tc);
  1161. FreeConnID(Conn);
  1162. Conn->tc_flags |= CONN_CLOSING;
  1163. //
  1164. // See if there's a TCB referencing this connection.
  1165. // If there is, we'll need to wait until he's done before closing him.
  1166. // We'll hurry the process along if we still have a pointer to him.
  1167. //
  1168. if (Conn->tc_refcnt != 0) {
  1169. RequestCompleteRoutine Rtn;
  1170. PVOID Context;
  1171. //
  1172. // A connection still references him. Save the current rtn stuff
  1173. // in case we are in the middle of disassociating him from an
  1174. // address, and store the caller's callback routine and our done
  1175. // routine.
  1176. //
  1177. Rtn = Conn->tc_rtn;
  1178. Context = Conn->tc_rtncontext;
  1179. Conn->tc_rtn = Request->RequestNotifyObject;
  1180. Conn->tc_rtncontext = Request->RequestContext;
  1181. Conn->tc_donertn = CloseDone;
  1182. //
  1183. // See if we're in the middle of disassociating him.
  1184. //
  1185. if (Conn->tc_flags & CONN_DISACC) {
  1186. //
  1187. // We are disassociating him. We'll free the conn table lock
  1188. // now and fail the disassociate request. Note that when
  1189. // we free the lock the refcount could go to zero. This is
  1190. // OK, because we've already stored the neccessary info. in
  1191. // the connection so the caller will get called back if it
  1192. // does. From this point out we return PENDING, so a callback
  1193. // is OK. We've marked him as closing, so the disassoc done
  1194. // routine will bail out if we've interrupted him. If the ref.
  1195. // count does go to zero, Conn->tc_tcb would have to be NULL,
  1196. // so in that case we'll just fall out of this routine.
  1197. //
  1198. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, Irql0);
  1199. (*Rtn)(Context, (uint) TDI_REQ_ABORTED, 0);
  1200. KeAcquireSpinLock(&Conn->tc_ConnBlock->cb_lock, &Irql0);
  1201. }
  1202. ConnTCB = Conn->tc_tcb;
  1203. if (ConnTCB != NULL) {
  1204. CHECK_STRUCT(ConnTCB, tcb);
  1205. //
  1206. // We have a TCB. Take the lock on him and get ready to
  1207. // close him.
  1208. //
  1209. KeAcquireSpinLock(&ConnTCB->tcb_lock, &Irql1);
  1210. if (ConnTCB->tcb_state != TCB_CLOSED) {
  1211. ConnTCB->tcb_flags |= NEED_RST;
  1212. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, Irql1);
  1213. if (!CLOSING(ConnTCB))
  1214. TryToCloseTCB(ConnTCB, TCB_CLOSE_ABORTED, Irql0);
  1215. else
  1216. KeReleaseSpinLock(&ConnTCB->tcb_lock, Irql0);
  1217. return TDI_PENDING;
  1218. } else {
  1219. //
  1220. // He's already closing. This should be harmless, but
  1221. // check this case.
  1222. //
  1223. KeReleaseSpinLock(&ConnTCB->tcb_lock, Irql1);
  1224. }
  1225. }
  1226. Status = TDI_PENDING;
  1227. } else {
  1228. //
  1229. // We have a connection that we can close. Finish the close.
  1230. //
  1231. Conn->tc_rtn = DummyCmplt;
  1232. CloseDone(Conn, Irql0);
  1233. return TDI_SUCCESS;
  1234. }
  1235. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, Irql0);
  1236. } else
  1237. Status = TDI_INVALID_CONNECTION;
  1238. //
  1239. // We're done with the connection. Go ahead and free him.
  1240. //
  1241. return Status;
  1242. }
  1243. //* TdiAssociateAddress - Associate an address with a connection.
  1244. //
  1245. // Called to associate an address with a connection. We do a minimal
  1246. // amount of sanity checking, and then put the connection on the AddrObj's
  1247. // list.
  1248. //
  1249. TDI_STATUS // Returns: Status of attempt to associate.
  1250. TdiAssociateAddress(
  1251. PTDI_REQUEST Request, // Structure for this request.
  1252. HANDLE AddrHandle) // Address handle to associate connection with.
  1253. {
  1254. KIRQL Irql0, Irql1; // One per lock nesting level.
  1255. AddrObj *AO;
  1256. uint ConnID = PtrToUlong(Request->Handle.ConnectionContext);
  1257. TCPConn *Conn;
  1258. TDI_STATUS Status;
  1259. AO = (AddrObj *)AddrHandle;
  1260. CHECK_STRUCT(AO, ao);
  1261. Conn = GetConnFromConnID(ConnID, &Irql0);
  1262. KeAcquireSpinLock(&AO->ao_lock, &Irql1);
  1263. if (!AO_VALID(AO)) {
  1264. KeReleaseSpinLock(&AO->ao_lock, Irql1);
  1265. if (Conn != NULL) {
  1266. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, Irql0);
  1267. }
  1268. return TDI_INVALID_PARAMETER;
  1269. }
  1270. if (Conn != NULL) {
  1271. CHECK_STRUCT(Conn, tc);
  1272. if (Conn->tc_ao != NULL) {
  1273. //
  1274. // It's already associated. Error out.
  1275. //
  1276. KdBreakPoint();
  1277. Status = TDI_ALREADY_ASSOCIATED;
  1278. } else {
  1279. Conn->tc_ao = AO;
  1280. ASSERT(Conn->tc_tcb == NULL);
  1281. PUSHQ(&AO->ao_idleq, &Conn->tc_q);
  1282. Status = TDI_SUCCESS;
  1283. }
  1284. KeReleaseSpinLock(&AO->ao_lock, Irql1);
  1285. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, Irql0);
  1286. return Status;
  1287. } else
  1288. Status = TDI_INVALID_CONNECTION;
  1289. KeReleaseSpinLock(&AO->ao_lock, Irql1);
  1290. return Status;
  1291. }
  1292. //* TdiDisAssociateAddress - Disassociate a connection from an address.
  1293. //
  1294. // The TDI entry point to disassociate a connection from an address. The
  1295. // connection must actually be associated and not connected to anything.
  1296. //
  1297. TDI_STATUS // Returns: Status of request.
  1298. TdiDisAssociateAddress(
  1299. PTDI_REQUEST Request) // Structure for this request.
  1300. {
  1301. uint ConnID = PtrToUlong(Request->Handle.ConnectionContext);
  1302. KIRQL Irql0, Irql1, Irql2; // One per lock nesting level.
  1303. TCPConn *Conn;
  1304. AddrObj *AO;
  1305. TDI_STATUS Status;
  1306. KeAcquireSpinLock(&AddrObjTableLock, &Irql0);
  1307. Conn = GetConnFromConnID(ConnID, &Irql1);
  1308. if (Conn != NULL) {
  1309. //
  1310. // The connection actually exists!
  1311. //
  1312. CHECK_STRUCT(Conn, tc);
  1313. AO = Conn->tc_ao;
  1314. if (AO != NULL) {
  1315. CHECK_STRUCT(AO, ao);
  1316. //
  1317. // And it's associated.
  1318. //
  1319. KeAcquireSpinLock(&AO->ao_lock, &Irql2);
  1320. //
  1321. // If there's no connection currently active, go ahead and remove
  1322. // him from the AddrObj. If a connection is active error the
  1323. // request out.
  1324. //
  1325. if (Conn->tc_tcb == NULL) {
  1326. if (Conn->tc_refcnt == 0) {
  1327. RemoveConnFromAO(AO, Conn);
  1328. Status = TDI_SUCCESS;
  1329. } else {
  1330. //
  1331. // He shouldn't be closing, or we couldn't have found him.
  1332. //
  1333. ASSERT(!(Conn->tc_flags & CONN_CLOSING));
  1334. Conn->tc_rtn = Request->RequestNotifyObject;
  1335. Conn->tc_rtncontext = Request->RequestContext;
  1336. Conn->tc_donertn = DisassocDone;
  1337. Conn->tc_flags |= CONN_DISACC;
  1338. Status = TDI_PENDING;
  1339. }
  1340. } else
  1341. Status = TDI_CONNECTION_ACTIVE;
  1342. KeReleaseSpinLock(&AO->ao_lock, Irql2);
  1343. } else
  1344. Status = TDI_NOT_ASSOCIATED;
  1345. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, Irql1);
  1346. } else
  1347. Status = TDI_INVALID_CONNECTION;
  1348. KeReleaseSpinLock(&AddrObjTableLock, Irql0);
  1349. return Status;
  1350. }
  1351. //* InitTCBFromConn - Initialize a TCB from information in a Connection.
  1352. //
  1353. // Called from Connect and Listen processing to initialize a new TCB from
  1354. // information in the connection. We assume the AddrObjTableLock and
  1355. // TCPConnBlock locks are held when we are called, or that the caller has some
  1356. // other way of making sure that the referenced AO doesn't go away in the
  1357. // middle of operation.
  1358. //
  1359. // Input: Conn - Connection to initialize from.
  1360. // NewTCB - TCB to be initialized.
  1361. // Addr - Remote addressing and option info for NewTCB.
  1362. // AOLocked - True if the called has the address object locked.
  1363. //
  1364. //
  1365. TDI_STATUS // Returns: TDI_STATUS of init attempt.
  1366. InitTCBFromConn(
  1367. TCPConn *Conn, // Connection to initialize from.
  1368. TCB *NewTCB, // TCB to be initialized.
  1369. PTDI_CONNECTION_INFORMATION Addr, // Remove addr info, etc. for NewTCB.
  1370. uint AOLocked) // True if caller has addr object lock.
  1371. {
  1372. KIRQL OldIrql;
  1373. CHECK_STRUCT(Conn, tc);
  1374. //
  1375. // We have a connection. Make sure it's associated with an address and
  1376. // doesn't already have a TCB attached.
  1377. //
  1378. if (Conn->tc_flags & CONN_INVALID)
  1379. return TDI_INVALID_CONNECTION;
  1380. if (Conn->tc_tcb == NULL) {
  1381. AddrObj *ConnAO;
  1382. ConnAO = Conn->tc_ao;
  1383. if (ConnAO != NULL) {
  1384. CHECK_STRUCT(ConnAO, ao);
  1385. if (!AOLocked) {
  1386. KeAcquireSpinLock(&ConnAO->ao_lock, &OldIrql);
  1387. }
  1388. if (!(NewTCB->tcb_flags & ACCEPT_PENDING)) {
  1389. //
  1390. // These fields are already initialized
  1391. // when ACCEPT_PENDING is on.
  1392. //
  1393. NewTCB->tcb_saddr = ConnAO->ao_addr;
  1394. NewTCB->tcb_sscope_id = ConnAO->ao_scope_id;
  1395. NewTCB->tcb_sport = ConnAO->ao_port;
  1396. NewTCB->tcb_defaultwin = Conn->tc_window;
  1397. NewTCB->tcb_rcvwin = Conn->tc_window;
  1398. }
  1399. NewTCB->tcb_rcvind = ConnAO->ao_rcv;
  1400. NewTCB->tcb_ricontext = ConnAO->ao_rcvcontext;
  1401. if (NewTCB->tcb_rcvind == NULL)
  1402. NewTCB->tcb_rcvhndlr = PendData;
  1403. else
  1404. NewTCB->tcb_rcvhndlr = IndicateData;
  1405. NewTCB->tcb_conncontext = Conn->tc_context;
  1406. NewTCB->tcb_flags |= Conn->tc_tcbflags;
  1407. if (Conn->tc_flags & CONN_WINSET)
  1408. NewTCB->tcb_flags |= WINDOW_SET;
  1409. if (NewTCB->tcb_flags & KEEPALIVE) {
  1410. NewTCB->tcb_alive = TCPTime;
  1411. NewTCB->tcb_kacount = 0;
  1412. }
  1413. NewTCB->tcb_hops = ConnAO->ao_ucast_hops;
  1414. if (!AOLocked) {
  1415. KeReleaseSpinLock(&ConnAO->ao_lock, OldIrql);
  1416. }
  1417. return TDI_SUCCESS;
  1418. } else
  1419. return TDI_NOT_ASSOCIATED;
  1420. } else
  1421. return TDI_CONNECTION_ACTIVE;
  1422. }
  1423. //* TdiConnect - Establish a connection.
  1424. //
  1425. // The TDI connection establishment routine. Called when the client wants to
  1426. // establish a connection, we validate his incoming parameters and kick
  1427. // things off by sending a SYN.
  1428. //
  1429. // Note: The format of the timeout (TO) parameter is system specific -
  1430. // we use a macro to convert to ticks.
  1431. //
  1432. TDI_STATUS // Returns: Status of attempt to connect.
  1433. TdiConnect(
  1434. PTDI_REQUEST Request, // This command request.
  1435. void *TO, // How long to wait for request.
  1436. PTDI_CONNECTION_INFORMATION RequestAddr, // Describes the destination.
  1437. PTDI_CONNECTION_INFORMATION ReturnAddr) // Where to return information.
  1438. {
  1439. TCPConnReq *ConnReq; // Connection request to use.
  1440. IPv6Addr DestAddr;
  1441. ulong DestScopeId;
  1442. ushort DestPort;
  1443. TCPConn *Conn;
  1444. TCB *NewTCB;
  1445. uint ConnID = PtrToUlong(Request->Handle.ConnectionContext);
  1446. KIRQL Irql0, Irql1, Irql2; // One per lock nesting level.
  1447. AddrObj *AO;
  1448. TDI_STATUS Status;
  1449. IP_STATUS IPStatus;
  1450. TCP_TIME *Timeout;
  1451. NetTableEntry *NTE;
  1452. NetTableEntryOrInterface *NTEorIF;
  1453. //
  1454. // First, get and validate the remote address.
  1455. //
  1456. if (RequestAddr == NULL || RequestAddr->RemoteAddress == NULL ||
  1457. !GetAddress((PTRANSPORT_ADDRESS)RequestAddr->RemoteAddress, &DestAddr,
  1458. &DestScopeId, &DestPort))
  1459. return TDI_BAD_ADDR;
  1460. //
  1461. // REVIEW: IPv4 performed other remote address sanity checks here.
  1462. // REVIEW: E.g., should we check that remote addr isn't multicast?
  1463. //
  1464. //
  1465. // REVIEW: I can't find an RFC which states 0 is not a valid port number.
  1466. //
  1467. if (DestPort == 0)
  1468. return TDI_BAD_ADDR;
  1469. //
  1470. // Get a connection request. If we can't, bail out now.
  1471. //
  1472. ConnReq = GetConnReq();
  1473. if (ConnReq == NULL)
  1474. return TDI_NO_RESOURCES;
  1475. //
  1476. // Get a TCB, assuming we'll need one.
  1477. //
  1478. NewTCB = AllocTCB();
  1479. if (NewTCB == NULL) {
  1480. // Couldn't get a TCB.
  1481. FreeConnReq(ConnReq);
  1482. return TDI_NO_RESOURCES;
  1483. }
  1484. Timeout = (TCP_TIME *)TO;
  1485. if (Timeout != NULL && !INFINITE_CONN_TO(*Timeout)) {
  1486. ulong Ticks = TCP_TIME_TO_TICKS(*Timeout);
  1487. if (Ticks > MAX_CONN_TO_TICKS)
  1488. Ticks = MAX_CONN_TO_TICKS;
  1489. else
  1490. Ticks++;
  1491. ConnReq->tcr_timeout = (ushort)Ticks;
  1492. } else
  1493. ConnReq->tcr_timeout = 0;
  1494. ConnReq->tcr_flags = 0;
  1495. ConnReq->tcr_conninfo = ReturnAddr;
  1496. ConnReq->tcr_addrinfo = NULL;
  1497. ConnReq->tcr_req.tr_rtn = Request->RequestNotifyObject;
  1498. ConnReq->tcr_req.tr_context = Request->RequestContext;
  1499. NewTCB->tcb_daddr = DestAddr;
  1500. NewTCB->tcb_dscope_id = DestScopeId;
  1501. NewTCB->tcb_dport = DestPort;
  1502. //
  1503. // Now find the real connection.
  1504. //
  1505. KeAcquireSpinLock(&AddrObjTableLock, &Irql0);
  1506. Conn = GetConnFromConnID(ConnID, &Irql1);
  1507. if (Conn != NULL) {
  1508. uint Inserted;
  1509. CHECK_STRUCT(Conn, tc);
  1510. //
  1511. // We found the connection. Check for an associated address object.
  1512. //
  1513. AO = Conn->tc_ao;
  1514. if (AO != NULL) {
  1515. KeAcquireSpinLock(&AO->ao_lock, &Irql2);
  1516. CHECK_STRUCT(AO, ao);
  1517. Status = InitTCBFromConn(Conn, NewTCB, RequestAddr, TRUE);
  1518. if (Status == TDI_SUCCESS) {
  1519. //
  1520. // We've initialized our TCB. Mark it that we initiated this
  1521. // connection (i.e. active open). Also, we're done with the
  1522. // AddrObjTable, so we can free it's lock.
  1523. //
  1524. NewTCB->tcb_flags |= ACTIVE_OPEN;
  1525. KeReleaseSpinLock(&AddrObjTableLock, Irql2);
  1526. //
  1527. // Initialize our routing state validation counter.
  1528. // We need to do this before acquiring an NTE or an RCE
  1529. // (to avoid missing any changes which may occur while
  1530. // we're in the process of acquiring them).
  1531. //
  1532. NewTCB->tcb_routing = RouteCacheValidationCounter;
  1533. //
  1534. // Determine NTE to send on (if user cares).
  1535. //
  1536. if (IsUnspecified(&NewTCB->tcb_saddr)) {
  1537. //
  1538. // Caller didn't specify a source address.
  1539. // Let the routing code pick one.
  1540. //
  1541. NTE = NULL;
  1542. NTEorIF = NULL;
  1543. } else {
  1544. //
  1545. // Our TCB has a specific source address. Determine
  1546. // which NTE corresponds to it and the scope id.
  1547. //
  1548. NTE = FindNetworkWithAddress(&NewTCB->tcb_saddr,
  1549. NewTCB->tcb_sscope_id);
  1550. if (NTE == NULL) {
  1551. //
  1552. // Bad source address. We don't have a network with
  1553. // the requested address. Error out.
  1554. //
  1555. // REVIEW: Will the AddrObj code even let this happen?
  1556. //
  1557. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_USER_ERROR,
  1558. "TdiConnect: Bad source address\n"));
  1559. KeReleaseSpinLock(&AO->ao_lock, Irql1);
  1560. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, Irql0);
  1561. Status = TDI_BAD_ADDR;
  1562. goto error;
  1563. }
  1564. NTEorIF = CastFromNTE(NTE);
  1565. }
  1566. //
  1567. // Get the route.
  1568. //
  1569. ASSERT(NewTCB->tcb_rce == NULL);
  1570. IPStatus = RouteToDestination(&DestAddr, DestScopeId,
  1571. NTEorIF, RTD_FLAG_NORMAL,
  1572. &NewTCB->tcb_rce);
  1573. if (IPStatus != IP_SUCCESS) {
  1574. //
  1575. // Failed to get a route to the destination. Error out.
  1576. //
  1577. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INTERNAL_ERROR,
  1578. "TdiConnect: Failed to get route to dest.\n"));
  1579. KeReleaseSpinLock(&AO->ao_lock, Irql1);
  1580. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, Irql0);
  1581. if ((IPStatus == IP_PARAMETER_PROBLEM) ||
  1582. (IPStatus == IP_BAD_ROUTE))
  1583. Status = TDI_BAD_ADDR;
  1584. else if (IPStatus == IP_NO_RESOURCES)
  1585. Status = TDI_NO_RESOURCES;
  1586. else
  1587. Status = TDI_DEST_UNREACHABLE;
  1588. goto error;
  1589. }
  1590. ASSERT(NewTCB->tcb_rce != NULL);
  1591. if (IsDisconnectedAndNotLoopbackRCE(NewTCB->tcb_rce)) {
  1592. //
  1593. // Fail new connection requests for TCBs with a
  1594. // disconnected outgoing interface, except when a
  1595. // loopback route is used.
  1596. //
  1597. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INTERNAL_ERROR,
  1598. "TdiConnect: Interface disconnected.\n"));
  1599. KeReleaseSpinLock(&AO->ao_lock, Irql1);
  1600. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, Irql0);
  1601. //
  1602. // Drop the reference on the route we obtained.
  1603. //
  1604. ReleaseRCE(NewTCB->tcb_rce);
  1605. Status = TDI_DEST_NET_UNREACH;
  1606. goto error;
  1607. }
  1608. //
  1609. // OK, we got a route. Enter the TCB into the connection
  1610. // and send a SYN.
  1611. //
  1612. KeAcquireSpinLock(&NewTCB->tcb_lock, &Irql2);
  1613. Conn->tc_tcb = NewTCB;
  1614. Conn->tc_refcnt++;
  1615. NewTCB->tcb_conn = Conn;
  1616. NewTCB->tcb_connid = Conn->tc_connid;
  1617. REMOVEQ(&Conn->tc_q);
  1618. ENQUEUE(&AO->ao_activeq, &Conn->tc_q);
  1619. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, Irql2);
  1620. KeReleaseSpinLock(&AO->ao_lock, Irql1);
  1621. //
  1622. // Initialize path-specific TCB settings, based on the RCE:
  1623. //
  1624. // If packets on the path will be looped back in software,
  1625. // don't use the Nagle algorithm for this TCB.
  1626. //
  1627. if (IsLoopbackRCE(NewTCB->tcb_rce)) {
  1628. NewTCB->tcb_flags &= ~NAGLING;
  1629. }
  1630. //
  1631. // Keep a reference for the NTE we're using.
  1632. // This prevents the NTE from going away should we release
  1633. // our RCE, and also makes for easy comparisons.
  1634. //
  1635. if (NTE == NULL) {
  1636. //
  1637. // We let the routing code pick the source NTE above.
  1638. // Remember this NTE and address for later use.
  1639. //
  1640. NewTCB->tcb_nte = NewTCB->tcb_rce->NTE;
  1641. AddRefNTE(NewTCB->tcb_nte);
  1642. NewTCB->tcb_saddr = NewTCB->tcb_nte->Address;
  1643. NewTCB->tcb_sscope_id =
  1644. DetermineScopeId(&NewTCB->tcb_saddr,
  1645. NewTCB->tcb_nte->IF);
  1646. } else {
  1647. //
  1648. // Remember the NTE we found above.
  1649. // We already hold a reference on it.
  1650. //
  1651. NewTCB->tcb_nte = NTE;
  1652. }
  1653. //
  1654. // Similarly, the routing code may have picked
  1655. // the destination scope id if it was left unspecified.
  1656. // REVIEW - getpeername will not return the new DestScopeId.
  1657. //
  1658. DestScopeId = DetermineScopeId(&NewTCB->tcb_daddr,
  1659. NewTCB->tcb_rce->NTE->IF);
  1660. ASSERT((NewTCB->tcb_dscope_id == DestScopeId) ||
  1661. (NewTCB->tcb_dscope_id == 0));
  1662. NewTCB->tcb_dscope_id = DestScopeId;
  1663. //
  1664. // Initialize our Maximum Segment Size (MSS).
  1665. // Cache our current Path Maximum Transmission Unit (PMTU)
  1666. // so that we'll know if it changes.
  1667. //
  1668. NewTCB->tcb_pmtu = GetEffectivePathMTUFromRCE(NewTCB->tcb_rce);
  1669. IF_TCPDBG(TCP_DEBUG_MSS) {
  1670. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_TCPDBG,
  1671. "TCP TdiConnect: PMTU from RCE is %d\n",
  1672. NewTCB->tcb_pmtu));
  1673. }
  1674. NewTCB->tcb_remmss = MAXUSHORT;
  1675. NewTCB->tcb_security = SecurityStateValidationCounter;
  1676. CalculateMSSForTCB(NewTCB);
  1677. // Now initialize our send state.
  1678. InitSendState(NewTCB);
  1679. NewTCB->tcb_refcnt = 1;
  1680. NewTCB->tcb_state = TCB_SYN_SENT;
  1681. TStats.ts_activeopens++;
  1682. // Need to put the ConnReq on the TCB now, in case the timer
  1683. // fires after we've inserted.
  1684. NewTCB->tcb_connreq = ConnReq;
  1685. KeReleaseSpinLock(&NewTCB->tcb_lock, Irql0);
  1686. Inserted = InsertTCB(NewTCB);
  1687. KeAcquireSpinLock(&NewTCB->tcb_lock, &Irql0);
  1688. if (!Inserted) {
  1689. // Insert failed. We must already have a connection. Pull
  1690. // the connreq from the TCB first, so we can return the
  1691. // correct error code for it.
  1692. NewTCB->tcb_connreq = NULL;
  1693. TryToCloseTCB(NewTCB, TCB_CLOSE_ABORTED, Irql0);
  1694. KeAcquireSpinLock(&NewTCB->tcb_lock, &Irql0);
  1695. DerefTCB(NewTCB, Irql0);
  1696. FreeConnReq(ConnReq);
  1697. return TDI_ADDR_IN_USE;
  1698. }
  1699. // If it's closing somehow, stop now. It can't have gone to
  1700. // closed, as we hold a reference on it. It could have gone
  1701. // to some other state (for example SYN-RCVD) so we need to
  1702. // check that now too.
  1703. if (!CLOSING(NewTCB) && NewTCB->tcb_state == TCB_SYN_SENT) {
  1704. SendSYN(NewTCB, Irql0);
  1705. KeAcquireSpinLock(&NewTCB->tcb_lock, &Irql0);
  1706. }
  1707. DerefTCB(NewTCB, Irql0);
  1708. return TDI_PENDING;
  1709. } else
  1710. KeReleaseSpinLock(&AO->ao_lock, Irql2);
  1711. } else
  1712. Status = TDI_NOT_ASSOCIATED;
  1713. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, Irql1);
  1714. } else
  1715. Status = TDI_INVALID_CONNECTION;
  1716. KeReleaseSpinLock(&AddrObjTableLock, Irql0);
  1717. error:
  1718. if (NTE != NULL)
  1719. ReleaseNTE(NTE);
  1720. FreeTCB(NewTCB);
  1721. FreeConnReq(ConnReq);
  1722. return Status;
  1723. }
  1724. //* TdiListen - Listen for a connection.
  1725. //
  1726. // The TDI listen handling routine. Called when the client wants to
  1727. // post a listen, we validate his incoming parameters, allocate a TCB
  1728. // and return.
  1729. //
  1730. TDI_STATUS // Returns: Status of attempt to connect.
  1731. TdiListen(
  1732. PTDI_REQUEST Request, // Structure for this request.
  1733. ushort Flags, // Listen flags for listen.
  1734. PTDI_CONNECTION_INFORMATION AcceptableAddr, // Acceptable remote addrs.
  1735. PTDI_CONNECTION_INFORMATION ConnectedAddr) // Where to return conn addr.
  1736. {
  1737. TCPConnReq *ConnReq; // Connection request to use.
  1738. IPv6Addr RemoteAddr; // Remote address to take conn. from.
  1739. ulong RemoteScopeId; // Scope identifier for remote addr (0 is none).
  1740. ushort RemotePort; // Acceptable remote port.
  1741. TCPConn *Conn; // Pointer to the Connection being listened upon.
  1742. TCB *NewTCB; // Pointer to the new TCB we'll use.
  1743. uint ConnID = PtrToUlong(Request->Handle.ConnectionContext);
  1744. KIRQL OldIrql; // Save IRQL value prior to taking lock.
  1745. TDI_STATUS Status;
  1746. //
  1747. // If we've been given remote addressing criteria, check it out.
  1748. //
  1749. if (AcceptableAddr != NULL && AcceptableAddr->RemoteAddress != NULL) {
  1750. if (!GetAddress((PTRANSPORT_ADDRESS)AcceptableAddr->RemoteAddress,
  1751. &RemoteAddr, &RemoteScopeId, &RemotePort))
  1752. return TDI_BAD_ADDR;
  1753. //
  1754. // REVIEW: IPv4 version did some other address sanity checks here.
  1755. // REVIEW: E.g., should we check that remote addr isn't multicast?
  1756. //
  1757. } else {
  1758. RemoteAddr = UnspecifiedAddr;
  1759. RemoteScopeId = 0;
  1760. RemotePort = 0;
  1761. }
  1762. //
  1763. // The remote address is valid. Get a ConnReq, and maybe a TCB.
  1764. //
  1765. ConnReq = GetConnReq();
  1766. if (ConnReq == NULL)
  1767. return TDI_NO_RESOURCES; // Couldn't get one.
  1768. //
  1769. // Now try to get a TCB.
  1770. //
  1771. NewTCB = AllocTCB();
  1772. if (NewTCB == NULL) {
  1773. //
  1774. // Couldn't get a TCB. Return an error.
  1775. //
  1776. FreeConnReq(ConnReq);
  1777. return TDI_NO_RESOURCES;
  1778. }
  1779. //
  1780. // We have the resources we need. Initialize them, and then check the
  1781. // state of the connection.
  1782. //
  1783. ConnReq->tcr_flags = Flags;
  1784. ConnReq->tcr_conninfo = ConnectedAddr;
  1785. ConnReq->tcr_addrinfo = NULL;
  1786. ConnReq->tcr_req.tr_rtn = Request->RequestNotifyObject;
  1787. ConnReq->tcr_req.tr_context = Request->RequestContext;
  1788. NewTCB->tcb_connreq = ConnReq;
  1789. NewTCB->tcb_daddr = RemoteAddr;
  1790. NewTCB->tcb_dscope_id = RemoteScopeId;
  1791. NewTCB->tcb_dport = RemotePort;
  1792. NewTCB->tcb_state = TCB_LISTEN;
  1793. //
  1794. // Now find the real connection. If we find it, we'll make sure it's
  1795. // associated.
  1796. //
  1797. Conn = GetConnFromConnID(ConnID, &OldIrql);
  1798. if (Conn != NULL) {
  1799. AddrObj *ConnAO;
  1800. CHECK_STRUCT(Conn, tc);
  1801. //
  1802. // We have a connection. Make sure it's associated with an address and
  1803. // doesn't already have a TCB attached.
  1804. //
  1805. ConnAO = Conn->tc_ao;
  1806. if (ConnAO != NULL) {
  1807. CHECK_STRUCT(ConnAO, ao);
  1808. KeAcquireSpinLockAtDpcLevel(&ConnAO->ao_lock);
  1809. if (AO_VALID(ConnAO)) {
  1810. Status = InitTCBFromConn(Conn, NewTCB, AcceptableAddr, TRUE);
  1811. } else {
  1812. Status = TDI_ADDR_INVALID;
  1813. }
  1814. if (Status == TDI_SUCCESS) {
  1815. //
  1816. // The initialization worked. Assign the new TCB to the
  1817. // connection, and return.
  1818. //
  1819. REMOVEQ(&Conn->tc_q);
  1820. PUSHQ(&ConnAO->ao_listenq, &Conn->tc_q);
  1821. Conn->tc_tcb = NewTCB;
  1822. NewTCB->tcb_conn = Conn;
  1823. NewTCB->tcb_connid = Conn->tc_connid;
  1824. Conn->tc_refcnt++;
  1825. ConnAO->ao_listencnt++;
  1826. KeReleaseSpinLockFromDpcLevel(&ConnAO->ao_lock);
  1827. Status = TDI_PENDING;
  1828. } else {
  1829. FreeTCB(NewTCB);
  1830. KeReleaseSpinLockFromDpcLevel(&ConnAO->ao_lock);
  1831. }
  1832. } else {
  1833. FreeTCB(NewTCB);
  1834. Status = TDI_NOT_ASSOCIATED;
  1835. }
  1836. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, OldIrql);
  1837. } else {
  1838. FreeTCB(NewTCB);
  1839. Status = TDI_INVALID_CONNECTION;
  1840. }
  1841. //
  1842. // We're all done.
  1843. //
  1844. if (Status != TDI_PENDING) {
  1845. FreeConnReq(ConnReq);
  1846. }
  1847. return Status;
  1848. }
  1849. //* InitRCE - Initialize an RCE.
  1850. //
  1851. // A utility routine to open an RCE and determine the maximum segment size
  1852. // for a connection. This function is called with the TCB lock held
  1853. // when transitioning out of the SYN_SENT or LISTEN states.
  1854. //
  1855. void // Returns: Nothing.
  1856. InitRCE(
  1857. TCB *NewTCB) // TCB for which an RCE is to be opened.
  1858. {
  1859. IP_STATUS Status;
  1860. //
  1861. // We are called when receiving an incoming connection attempt,
  1862. // so tcb_saddr will always be initialized.
  1863. //
  1864. ASSERT(! IsUnspecified(&NewTCB->tcb_saddr));
  1865. //
  1866. // If we don't already have an NTE for this connection, get one now.
  1867. //
  1868. if (NewTCB->tcb_nte == NULL) {
  1869. //
  1870. // Initialize our routing state validation counter.
  1871. // We need to do this before acquiring an NTE or an RCE
  1872. // (to avoid missing any changes which may occur while
  1873. // we're in the process of acquiring them).
  1874. //
  1875. NewTCB->tcb_routing = RouteCacheValidationCounter;
  1876. NewTCB->tcb_nte = FindNetworkWithAddress(&NewTCB->tcb_saddr,
  1877. NewTCB->tcb_sscope_id);
  1878. if (NewTCB->tcb_nte == NULL) {
  1879. //
  1880. // Failed to get an NTE corresponding to this source address.
  1881. //
  1882. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INTERNAL_ERROR,
  1883. "TCP InitRCE: Can't find the NTE for address?!?\n"));
  1884. goto ErrorReturn;
  1885. }
  1886. }
  1887. //
  1888. // Get the route.
  1889. //
  1890. ASSERT(NewTCB->tcb_rce == NULL);
  1891. Status = RouteToDestination(&NewTCB->tcb_daddr, NewTCB->tcb_dscope_id,
  1892. CastFromNTE(NewTCB->tcb_nte), RTD_FLAG_NORMAL,
  1893. &NewTCB->tcb_rce);
  1894. if (Status != IP_SUCCESS) {
  1895. //
  1896. // Failed to get a route to the destination.
  1897. //
  1898. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INTERNAL_ERROR,
  1899. "TCP InitRCE: Can't get a route?!?\n"));
  1900. ErrorReturn:
  1901. //
  1902. // Until we have a real route, use conservative values.
  1903. //
  1904. NewTCB->tcb_pmtu = IPv6_MINIMUM_MTU;
  1905. NewTCB->tcb_mss = (ushort)MIN(DEFAULT_MSS, NewTCB->tcb_remmss);
  1906. return;
  1907. }
  1908. //
  1909. // Initialize path-specific TCB settings, based on the RCE:
  1910. //
  1911. // If packets on the path will be looped back in software,
  1912. // don't use the Nagle algorithm for this TCB.
  1913. //
  1914. if (IsLoopbackRCE(NewTCB->tcb_rce)) {
  1915. NewTCB->tcb_flags &= ~NAGLING;
  1916. }
  1917. //
  1918. // Initialize the maximum segement size (MSS) for this connection.
  1919. // Cache our current Path Maximum Transmission Unit (PMTU)
  1920. // so that we'll know if it changes.
  1921. //
  1922. NewTCB->tcb_pmtu = GetEffectivePathMTUFromRCE(NewTCB->tcb_rce);
  1923. IF_TCPDBG(TCP_DEBUG_MSS) {
  1924. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_TCPDBG,
  1925. "TCP InitRCE: PMTU from RCE is %d\n", NewTCB->tcb_pmtu));
  1926. }
  1927. NewTCB->tcb_security = SecurityStateValidationCounter;
  1928. CalculateMSSForTCB(NewTCB);
  1929. }
  1930. //* AcceptConn - Accept a connection on a TCB.
  1931. //
  1932. // Called to accept a connection on a TCB, either from an incoming
  1933. // receive segment or via a user's accept. We initialize the RCE
  1934. // and the send state, and send out a SYN. We assume the TCB is locked
  1935. // and referenced when we get it.
  1936. //
  1937. void // Returns: Nothing.
  1938. AcceptConn(
  1939. TCB *AcceptTCB, // TCB to accept on.
  1940. KIRQL PreLockIrql) // IRQL prior to acquiring TCB lock.
  1941. {
  1942. CHECK_STRUCT(AcceptTCB, tcb);
  1943. ASSERT(AcceptTCB->tcb_refcnt != 0);
  1944. InitRCE(AcceptTCB);
  1945. InitSendState(AcceptTCB);
  1946. AdjustRcvWin(AcceptTCB);
  1947. SendSYN(AcceptTCB, PreLockIrql);
  1948. KeAcquireSpinLock(&AcceptTCB->tcb_lock, &PreLockIrql);
  1949. DerefTCB(AcceptTCB, PreLockIrql);
  1950. }
  1951. //* TdiAccept - Accept a connection.
  1952. //
  1953. // The TDI accept routine. Called when the client wants to
  1954. // accept a connection for which a listen had previously completed. We
  1955. // examine the state of the connection - it has to be in SYN-RCVD, with
  1956. // a TCB, with no pending connreq, etc.
  1957. //
  1958. TDI_STATUS // Returns: Status of attempt to connect.
  1959. TdiAccept(
  1960. PTDI_REQUEST Request, // Structure for this request.
  1961. PTDI_CONNECTION_INFORMATION AcceptInfo, // Info for this accept.
  1962. PTDI_CONNECTION_INFORMATION ConnectedInfo) // Where to return conn addr.
  1963. {
  1964. TCPConnReq *ConnReq; // ConnReq we'll use for this connection.
  1965. uint ConnID = PtrToUlong(Request->Handle.ConnectionContext);
  1966. TCPConn *Conn; // Connection being accepted upon.
  1967. TCB *AcceptTCB; // TCB for Conn.
  1968. KIRQL Irql0, Irql1; // One per lock nesting level.
  1969. TDI_STATUS Status;
  1970. //
  1971. // First, get the ConnReq we'll need.
  1972. //
  1973. ConnReq = GetConnReq();
  1974. if (ConnReq == NULL)
  1975. return TDI_NO_RESOURCES;
  1976. ConnReq->tcr_conninfo = ConnectedInfo;
  1977. ConnReq->tcr_addrinfo = NULL;
  1978. ConnReq->tcr_req.tr_rtn = Request->RequestNotifyObject;
  1979. ConnReq->tcr_req.tr_context = Request->RequestContext;
  1980. //
  1981. // Now look up the connection.
  1982. //
  1983. Conn = GetConnFromConnID(ConnID, &Irql0);
  1984. if (Conn != NULL) {
  1985. CHECK_STRUCT(Conn, tc);
  1986. //
  1987. // We have the connection. Make sure is has a TCB, and that the
  1988. // TCB is in the SYN-RCVD state, etc.
  1989. //
  1990. AcceptTCB = Conn->tc_tcb;
  1991. if (AcceptTCB != NULL) {
  1992. CHECK_STRUCT(AcceptTCB, tcb);
  1993. KeAcquireSpinLock(&AcceptTCB->tcb_lock, &Irql1);
  1994. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, Irql1);
  1995. if (!CLOSING(AcceptTCB) && AcceptTCB->tcb_state == TCB_SYN_RCVD) {
  1996. //
  1997. // State is valid. Make sure this TCB had a delayed accept on
  1998. // it, and that there is currently no connect request pending.
  1999. //
  2000. if (!(AcceptTCB->tcb_flags & CONN_ACCEPTED) &&
  2001. AcceptTCB->tcb_connreq == NULL) {
  2002. AcceptTCB->tcb_connreq = ConnReq;
  2003. AcceptTCB->tcb_flags |= CONN_ACCEPTED;
  2004. AcceptTCB->tcb_refcnt++;
  2005. //
  2006. // Everything's set. Accept the connection now.
  2007. //
  2008. AcceptConn(AcceptTCB, Irql0);
  2009. return TDI_PENDING;
  2010. }
  2011. }
  2012. KeReleaseSpinLock(&AcceptTCB->tcb_lock, Irql0);
  2013. Status = TDI_INVALID_CONNECTION;
  2014. goto error;
  2015. }
  2016. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, Irql0);
  2017. }
  2018. Status = TDI_INVALID_CONNECTION;
  2019. error:
  2020. FreeConnReq(ConnReq);
  2021. return Status;
  2022. }
  2023. //* TdiDisConnect - Disconnect a connection.
  2024. //
  2025. // The TDI disconnection routine. Called when the client wants to disconnect
  2026. // a connection. There are two types of disconnection we support, graceful
  2027. // and abortive. A graceful close will cause us to send a FIN and not complete
  2028. // the request until we get the ACK back. An abortive close causes us to send
  2029. // a RST. In that case we'll just get things going and return immediately.
  2030. //
  2031. // Note: The format of the Timeout (TO) is system specific - we use
  2032. // a macro to convert to ticks.
  2033. //
  2034. TDI_STATUS // Returns: Status of attempt to disconnect.
  2035. TdiDisconnect(
  2036. PTDI_REQUEST Request, // Structure for this request.
  2037. void *TO, // How long to wait.
  2038. ushort Flags, // Type of disconnect.
  2039. PTDI_CONNECTION_INFORMATION DiscConnInfo, // Ignored.
  2040. PTDI_CONNECTION_INFORMATION ReturnInfo, // Ignored.
  2041. TCPAbortReq *AbortReq) // Space for pending abort.
  2042. {
  2043. TCPConnReq *ConnReq; // Connection request to use.
  2044. TCPConn *Conn;
  2045. TCB *DiscTCB;
  2046. KIRQL Irql0, Irql1; // One per lock nesting level.
  2047. TDI_STATUS Status;
  2048. TCP_TIME *Timeout;
  2049. UNREFERENCED_PARAMETER(DiscConnInfo);
  2050. UNREFERENCED_PARAMETER(ReturnInfo);
  2051. Conn = GetConnFromConnID(PtrToUlong(Request->Handle.ConnectionContext),
  2052. &Irql0);
  2053. if (Conn != NULL) {
  2054. CHECK_STRUCT(Conn, tc);
  2055. DiscTCB = Conn->tc_tcb;
  2056. if (DiscTCB != NULL) {
  2057. CHECK_STRUCT(DiscTCB, tcb);
  2058. KeAcquireSpinLock(&DiscTCB->tcb_lock, &Irql1);
  2059. //
  2060. // We have the TCB. See what kind of disconnect this is.
  2061. //
  2062. if (Flags & TDI_DISCONNECT_ABORT) {
  2063. //
  2064. // This is an abortive disconnect. If we're not already
  2065. // closed or closing, blow the connection away.
  2066. //
  2067. if (DiscTCB->tcb_state != TCB_CLOSED) {
  2068. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, Irql1);
  2069. if (AbortReq != NULL) {
  2070. if (DiscTCB->tcb_abortreq == NULL) {
  2071. AbortReq->tar_rtn = Request->RequestNotifyObject;
  2072. AbortReq->tar_context = Request->RequestContext;
  2073. DiscTCB->tcb_abortreq = AbortReq;
  2074. Status = TDI_PENDING;
  2075. } else {
  2076. Status = TDI_SUCCESS;
  2077. }
  2078. } else {
  2079. Status = TDI_SUCCESS;
  2080. }
  2081. if (!CLOSING(DiscTCB)) {
  2082. DiscTCB->tcb_flags |= NEED_RST;
  2083. TryToCloseTCB(DiscTCB, TCB_CLOSE_ABORTED,
  2084. Irql0);
  2085. } else
  2086. KeReleaseSpinLock(&DiscTCB->tcb_lock, Irql0);
  2087. return Status;
  2088. } else {
  2089. //
  2090. // The TCB isn't connected.
  2091. //
  2092. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, Irql1);
  2093. KeReleaseSpinLock(&DiscTCB->tcb_lock, Irql0);
  2094. return TDI_INVALID_STATE;
  2095. }
  2096. } else {
  2097. //
  2098. // This is not an abortive close. For graceful close we'll
  2099. // need a ConnReq.
  2100. //
  2101. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, Irql1);
  2102. //
  2103. // Make sure we aren't in the middle of an abortive close.
  2104. //
  2105. if (CLOSING(DiscTCB)) {
  2106. KeReleaseSpinLock(&DiscTCB->tcb_lock, Irql0);
  2107. return TDI_INVALID_CONNECTION;
  2108. }
  2109. ConnReq = GetConnReq();
  2110. if (ConnReq != NULL) {
  2111. //
  2112. // Got the ConnReq. See if this is a DISCONNECT_WAIT
  2113. // primitive or not.
  2114. //
  2115. ConnReq->tcr_flags = 0;
  2116. ConnReq->tcr_conninfo = NULL;
  2117. ConnReq->tcr_addrinfo = NULL;
  2118. ConnReq->tcr_req.tr_rtn = Request->RequestNotifyObject;
  2119. ConnReq->tcr_req.tr_context = Request->RequestContext;
  2120. if (!(Flags & TDI_DISCONNECT_WAIT)) {
  2121. Timeout = (TCP_TIME *)TO;
  2122. if (Timeout != NULL && !INFINITE_CONN_TO(*Timeout)) {
  2123. ulong Ticks = TCP_TIME_TO_TICKS(*Timeout);
  2124. if (Ticks > MAX_CONN_TO_TICKS)
  2125. Ticks = MAX_CONN_TO_TICKS;
  2126. else
  2127. Ticks++;
  2128. ConnReq->tcr_timeout = (ushort)Ticks;
  2129. } else
  2130. ConnReq->tcr_timeout = 0;
  2131. //
  2132. // OK, we're just about set. We need to update
  2133. // the TCB state, and send the FIN.
  2134. //
  2135. if (DiscTCB->tcb_state == TCB_ESTAB) {
  2136. DiscTCB->tcb_state = TCB_FIN_WAIT1;
  2137. //
  2138. // Since we left established, we're off the fast
  2139. // receive path.
  2140. //
  2141. DiscTCB->tcb_slowcount++;
  2142. DiscTCB->tcb_fastchk |= TCP_FLAG_SLOW;
  2143. } else
  2144. if (DiscTCB->tcb_state == TCB_CLOSE_WAIT)
  2145. DiscTCB->tcb_state = TCB_LAST_ACK;
  2146. else {
  2147. KeReleaseSpinLock(&DiscTCB->tcb_lock, Irql0);
  2148. FreeConnReq(ConnReq);
  2149. return TDI_INVALID_STATE;
  2150. }
  2151. // Update SNMP info.
  2152. InterlockedDecrement((PLONG)&TStats.ts_currestab);
  2153. ASSERT(*(int *)&TStats.ts_currestab >= 0);
  2154. ASSERT(DiscTCB->tcb_connreq == NULL);
  2155. DiscTCB->tcb_connreq = ConnReq;
  2156. DiscTCB->tcb_flags |= FIN_NEEDED;
  2157. DiscTCB->tcb_refcnt++;
  2158. TCPSend(DiscTCB, Irql0);
  2159. return TDI_PENDING;
  2160. } else {
  2161. //
  2162. // This is a DISC_WAIT request.
  2163. //
  2164. ConnReq->tcr_timeout = 0;
  2165. if (DiscTCB->tcb_discwait == NULL) {
  2166. DiscTCB->tcb_discwait = ConnReq;
  2167. Status = TDI_PENDING;
  2168. } else {
  2169. FreeConnReq(ConnReq);
  2170. Status = TDI_INVALID_STATE;
  2171. }
  2172. KeReleaseSpinLock(&DiscTCB->tcb_lock, Irql0);
  2173. return Status;
  2174. }
  2175. } else {
  2176. //
  2177. // Couldn't get a ConnReq.
  2178. //
  2179. KeReleaseSpinLock(&DiscTCB->tcb_lock, Irql0);
  2180. return TDI_NO_RESOURCES;
  2181. }
  2182. }
  2183. } else
  2184. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, Irql0);
  2185. }
  2186. //
  2187. // No Conn, or no TCB on conn. Return an error.
  2188. //
  2189. return TDI_INVALID_CONNECTION;
  2190. }
  2191. //* OKToNotify - See if it's OK to notify about a DISC.
  2192. //
  2193. // A little utility function, called to see it it's OK to notify the client
  2194. // of an incoming FIN.
  2195. //
  2196. uint // Returns: TRUE if it's OK, False otherwise.
  2197. OKToNotify(
  2198. TCB *NotifyTCB) // TCB to check.
  2199. {
  2200. CHECK_STRUCT(NotifyTCB, tcb);
  2201. if (NotifyTCB->tcb_pendingcnt == 0 && NotifyTCB->tcb_urgcnt == 0 &&
  2202. NotifyTCB->tcb_rcvhead == NULL && NotifyTCB->tcb_exprcv == NULL)
  2203. return TRUE;
  2204. else
  2205. return FALSE;
  2206. }
  2207. //* NotifyOfDisc - Notify a client that a TCB is being disconnected.
  2208. //
  2209. // Called when we're disconnecting a TCB because we've received a FIN or
  2210. // RST from the remote peer, or because we're aborting for some reason.
  2211. // We'll complete a DISCONNECT_WAIT request if we have one, or try and
  2212. // issue an indication otherwise. This is only done if we're in a
  2213. // synchronized state and not in TIMED-WAIT.
  2214. //
  2215. // May be called with TCB lock held. Or not.
  2216. //
  2217. void // Returns: Nothing.
  2218. NotifyOfDisc(
  2219. TCB *DiscTCB, // TCB we're notifying.
  2220. TDI_STATUS Status, // Status code for notification.
  2221. PKIRQL IrqlPtr) // Indicates TCB is locked with given IRQL.
  2222. {
  2223. KIRQL Irql0, Irql1;
  2224. TCPConnReq *DiscReq;
  2225. TCPConn *Conn;
  2226. AddrObj *DiscAO;
  2227. PVOID ConnContext;
  2228. CHECK_STRUCT(DiscTCB, tcb);
  2229. ASSERT(DiscTCB->tcb_refcnt != 0);
  2230. //
  2231. // See if we already hold the TCB lock, grab it if not.
  2232. //
  2233. if (IrqlPtr != NULL) {
  2234. Irql0 = *IrqlPtr;
  2235. } else {
  2236. KeAcquireSpinLock(&DiscTCB->tcb_lock, &Irql0);
  2237. }
  2238. if (SYNC_STATE(DiscTCB->tcb_state) &&
  2239. !(DiscTCB->tcb_flags & DISC_NOTIFIED)) {
  2240. //
  2241. // We can't notify him if there's still data to be taken.
  2242. //
  2243. if (Status == TDI_GRACEFUL_DISC) {
  2244. if (!OKToNotify(DiscTCB)) {
  2245. DiscTCB->tcb_flags |= DISC_PENDING;
  2246. KeReleaseSpinLock(&DiscTCB->tcb_lock, Irql0);
  2247. return;
  2248. }
  2249. if (DiscTCB->tcb_pending & RST_PENDING) {
  2250. KeReleaseSpinLock(&DiscTCB->tcb_lock, Irql0);
  2251. return;
  2252. }
  2253. } else {
  2254. if (DiscTCB->tcb_flags & (IN_RCV_IND | IN_DELIV_URG)) {
  2255. DiscTCB->tcb_pending |= RST_PENDING;
  2256. KeReleaseSpinLock(&DiscTCB->tcb_lock, Irql0);
  2257. return;
  2258. }
  2259. DiscTCB->tcb_pending &= ~RST_PENDING;
  2260. }
  2261. DiscTCB->tcb_flags |= DISC_NOTIFIED;
  2262. DiscTCB->tcb_flags &= ~DISC_PENDING;
  2263. //
  2264. // We're in a state where a disconnect is meaningful, and we haven't
  2265. // already notified the client.
  2266. // See if we have a DISC-WAIT request pending.
  2267. //
  2268. if ((DiscReq = DiscTCB->tcb_discwait) != NULL) {
  2269. //
  2270. // We have a disconnect wait request. Complete it and we're done.
  2271. //
  2272. DiscTCB->tcb_discwait = NULL;
  2273. KeReleaseSpinLock(&DiscTCB->tcb_lock, Irql0);
  2274. (*DiscReq->tcr_req.tr_rtn)(DiscReq->tcr_req.tr_context, Status, 0);
  2275. FreeConnReq(DiscReq);
  2276. return;
  2277. }
  2278. //
  2279. // No DISC-WAIT. Find the AddrObj for the connection, and see if
  2280. // there is a disconnect handler registered.
  2281. //
  2282. ConnContext = DiscTCB->tcb_conncontext;
  2283. KeReleaseSpinLock(&DiscTCB->tcb_lock, Irql0);
  2284. KeAcquireSpinLock(&AddrObjTableLock, &Irql0);
  2285. if ((Conn = DiscTCB->tcb_conn) != NULL) {
  2286. CHECK_STRUCT(Conn, tc);
  2287. KeAcquireSpinLock(&Conn->tc_ConnBlock->cb_lock, &Irql1);
  2288. DiscAO = Conn->tc_ao;
  2289. if (DiscAO != NULL) {
  2290. KIRQL Irql2;
  2291. PDisconnectEvent DiscEvent;
  2292. PVOID DiscContext;
  2293. CHECK_STRUCT(DiscAO, ao);
  2294. KeAcquireSpinLock(&DiscAO->ao_lock, &Irql2);
  2295. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, Irql2);
  2296. KeReleaseSpinLock(&AddrObjTableLock, Irql1);
  2297. DiscEvent = DiscAO->ao_disconnect;
  2298. DiscContext = DiscAO->ao_disconncontext;
  2299. if (DiscEvent != NULL) {
  2300. REF_AO(DiscAO);
  2301. KeReleaseSpinLock(&DiscAO->ao_lock, Irql0);
  2302. IF_TCPDBG(TCP_DEBUG_CLOSE) {
  2303. KdPrintEx((DPFLTR_TCPIP6_ID, DPFLTR_INFO_TCPDBG,
  2304. "TCP: indicating %s disconnect\n",
  2305. (Status == TDI_GRACEFUL_DISC) ?
  2306. "graceful" : "abortive"));
  2307. }
  2308. (*DiscEvent)(DiscContext, ConnContext, 0, NULL, 0,
  2309. NULL, (Status == TDI_GRACEFUL_DISC) ?
  2310. TDI_DISCONNECT_RELEASE :
  2311. TDI_DISCONNECT_ABORT);
  2312. DELAY_DEREF_AO(DiscAO);
  2313. return;
  2314. } else {
  2315. KeReleaseSpinLock(&DiscAO->ao_lock, Irql0);
  2316. return;
  2317. }
  2318. }
  2319. KeReleaseSpinLock(&Conn->tc_ConnBlock->cb_lock, Irql1);
  2320. }
  2321. KeReleaseSpinLock(&AddrObjTableLock, Irql0);
  2322. return;
  2323. }
  2324. KeReleaseSpinLock(&DiscTCB->tcb_lock, Irql0);
  2325. }
  2326. //* GracefulClose - Complete the transition to a gracefully closed state.
  2327. //
  2328. // Called when we need to complete the transition to a gracefully closed
  2329. // state, either TIME_WAIT or CLOSED. This completion involves removing
  2330. // the TCB from it's associated connection (if it has one), notifying the
  2331. // upper layer client either via completing a request or calling a disc.
  2332. // notification handler, and actually doing the transition.
  2333. //
  2334. // The tricky part here is if we need to notify him (instead of completing
  2335. // a graceful disconnect request). We can't notify him if there is pending
  2336. // data on the connection, so in that case we have to pend the disconnect
  2337. // notification until we deliver the data.
  2338. //
  2339. void // Returns: Nothing.
  2340. GracefulClose(
  2341. TCB *CloseTCB, // TCB to transition.
  2342. uint ToTimeWait, // TRUE if we're going to TIME_WAIT, FALSE if
  2343. // we're going to close the TCB.
  2344. uint Notify, // TRUE if via notification, FALSE if via completing
  2345. // a disconnect request.
  2346. KIRQL PreLockIrql) // IRQL prior to acquiring TCB lock.
  2347. {
  2348. CHECK_STRUCT(CloseTCB, tcb);
  2349. ASSERT(CloseTCB->tcb_refcnt != 0);
  2350. //
  2351. // First, see if we need to notify the client of a FIN.
  2352. //
  2353. if (Notify) {
  2354. //
  2355. // We do need to notify him. See if it's OK to do so.
  2356. //
  2357. if (OKToNotify(CloseTCB)) {
  2358. //
  2359. // We can notify him. Change his state, pull him from the conn.,
  2360. // and notify him.
  2361. //
  2362. if (ToTimeWait) {
  2363. //
  2364. // Save the time we went into time wait, in case we need to
  2365. // scavenge.
  2366. //
  2367. CloseTCB->tcb_alive = SystemUpTime();
  2368. CloseTCB->tcb_state = TCB_TIME_WAIT;
  2369. KeReleaseSpinLock(&CloseTCB->tcb_lock, PreLockIrql);
  2370. } else {
  2371. //
  2372. // He's going to close. Mark him as closing with TryToCloseTCB
  2373. // (he won't actually close since we have a ref. on him). We
  2374. // do this so that anyone touching him after we free the
  2375. // lock will fail.
  2376. //
  2377. TryToCloseTCB(CloseTCB, TDI_SUCCESS, PreLockIrql);
  2378. }
  2379. RemoveTCBFromConn(CloseTCB);
  2380. NotifyOfDisc(CloseTCB, TDI_GRACEFUL_DISC, NULL);
  2381. } else {
  2382. //
  2383. // Can't notify him now. Set the appropriate flags, and return.
  2384. //
  2385. CloseTCB->tcb_flags |= (GC_PENDING |
  2386. (ToTimeWait ? TW_PENDING : 0));
  2387. DerefTCB(CloseTCB, PreLockIrql);
  2388. return;
  2389. }
  2390. } else {
  2391. //
  2392. // We're not notifying this guy, we just need to complete a conn. req.
  2393. // We need to check and see if he's been notified, and if not
  2394. // we'll complete the request and notify him later.
  2395. //
  2396. if (CloseTCB->tcb_flags & DISC_NOTIFIED) {
  2397. //
  2398. // He's been notified.
  2399. //
  2400. if (ToTimeWait) {
  2401. //
  2402. // Save the time we went into time wait, in case we need to
  2403. // scavenge.
  2404. //
  2405. CloseTCB->tcb_alive = SystemUpTime();
  2406. CloseTCB->tcb_state = TCB_TIME_WAIT;
  2407. KeReleaseSpinLock(&CloseTCB->tcb_lock, PreLockIrql);
  2408. } else {
  2409. //
  2410. // Mark him as closed. See comments above.
  2411. //
  2412. TryToCloseTCB(CloseTCB, TDI_SUCCESS, PreLockIrql);
  2413. }
  2414. RemoveTCBFromConn(CloseTCB);
  2415. KeAcquireSpinLock(&CloseTCB->tcb_lock, &PreLockIrql);
  2416. CompleteConnReq(CloseTCB, TDI_SUCCESS);
  2417. KeReleaseSpinLock(&CloseTCB->tcb_lock, PreLockIrql);
  2418. } else {
  2419. //
  2420. // He hasn't been notified. He should be pending already.
  2421. //
  2422. ASSERT(CloseTCB->tcb_flags & DISC_PENDING);
  2423. CloseTCB->tcb_flags |= (GC_PENDING |
  2424. (ToTimeWait ? TW_PENDING : 0));
  2425. CompleteConnReq(CloseTCB, TDI_SUCCESS);
  2426. DerefTCB(CloseTCB, PreLockIrql);
  2427. return;
  2428. }
  2429. }
  2430. //
  2431. // If we're going to TIME_WAIT, start the TIME_WAIT timer now.
  2432. // Otherwise close the TCB.
  2433. //
  2434. KeAcquireSpinLock(&CloseTCB->tcb_lock, &PreLockIrql);
  2435. if (!CLOSING(CloseTCB) && ToTimeWait) {
  2436. START_TCB_TIMER(CloseTCB->tcb_rexmittimer, MAX_REXMIT_TO);
  2437. KeReleaseSpinLock(&CloseTCB->tcb_lock, PreLockIrql);
  2438. RemoveConnFromTCB(CloseTCB);
  2439. KeAcquireSpinLock(&CloseTCB->tcb_lock, &PreLockIrql);
  2440. }
  2441. DerefTCB(CloseTCB, PreLockIrql);
  2442. }
  2443. #if 0 // REVIEW: Unused function?
  2444. //* ConnCheckPassed - Check to see if we have exceeded the connect limit.
  2445. //
  2446. // Called when a SYN is received to determine whether we will accept
  2447. // the incoming connection. If there is an empty slot or if the IP address
  2448. // is already in the table, we accept it.
  2449. //
  2450. int // Returns: TRUE is connect is accepted, FALSE if rejected.
  2451. ConnCheckPassed(
  2452. IPv6Addr *Src, // Source address of incoming connection.
  2453. ulong Prt) // Destination port of incoming connection.
  2454. {
  2455. UNREFERENCED_PARAMETER(Src);
  2456. UNREFERENCED_PARAMETER(Prt);
  2457. return TRUE;
  2458. }
  2459. #endif
  2460. void InitAddrChecks()
  2461. {
  2462. return;
  2463. }
  2464. //* EnumerateConnectionList - Enumerate Connection List database.
  2465. //
  2466. // This routine enumerates the contents of the connection limit database.
  2467. //
  2468. // Note: The comments found with this routine upon IPv6 port imply that
  2469. // there may have been code here once that actually did something.
  2470. // What's here now is a no-op.
  2471. //
  2472. void // Returns: Nothing.
  2473. EnumerateConnectionList(
  2474. uchar *Buffer, // Buffer to fill with connection list entries.
  2475. ulong BufferSize, // Size of Buffer in bytes.
  2476. ulong *EntriesReturned, // Where to put the number of entries returned.
  2477. ulong *EntriesAvailable) // Where to return number of avail conn. entries.
  2478. {
  2479. UNREFERENCED_PARAMETER(Buffer);
  2480. UNREFERENCED_PARAMETER(BufferSize);
  2481. *EntriesAvailable = 0;
  2482. *EntriesReturned = 0;
  2483. return;
  2484. }
  2485. #pragma BEGIN_INIT
  2486. //* InitTCPConn - Initialize TCP connection management code.
  2487. //
  2488. // Called during init time to initialize our TCP connection management.
  2489. //
  2490. int // Returns: TRUE.
  2491. InitTCPConn(
  2492. void) // Input: Nothing.
  2493. {
  2494. ExInitializeSListHead(&ConnReqFree);
  2495. KeInitializeSpinLock(&ConnReqFreeLock);
  2496. KeInitializeSpinLock(&ConnTableLock);
  2497. MaxAllocatedConnBlocks = 0;
  2498. ConnTable = ExAllocatePool(NonPagedPool,
  2499. MaxConnBlocks * sizeof(TCPConnBlock *));
  2500. if (ConnTable == NULL) {
  2501. return FALSE;
  2502. }
  2503. return TRUE;
  2504. }
  2505. #pragma END_INIT
  2506. //* UnloadTCPConn
  2507. //
  2508. // Cleanup and prepare for stack unload.
  2509. //
  2510. void
  2511. UnloadTCPConn(void)
  2512. {
  2513. PSLIST_ENTRY BufferLink;
  2514. KIRQL OldIrql;
  2515. TCPConnBlock **OldTable;
  2516. while ((BufferLink = ExInterlockedPopEntrySList(&ConnReqFree,
  2517. &ConnReqFreeLock))
  2518. != NULL) {
  2519. Queue *QueuePtr = CONTAINING_RECORD(BufferLink, Queue, q_next);
  2520. TCPReq *Req = CONTAINING_RECORD(QueuePtr, TCPReq, tr_q);
  2521. TCPConnReq *ConnReq = CONTAINING_RECORD(Req, TCPConnReq, tcr_req);
  2522. CHECK_STRUCT(ConnReq, tcr);
  2523. ExFreePool(ConnReq);
  2524. }
  2525. KeAcquireSpinLock(&ConnTableLock, &OldIrql);
  2526. OldTable = ConnTable;
  2527. ConnTable = NULL;
  2528. KeReleaseSpinLock(&ConnTableLock, OldIrql);
  2529. if (OldTable != NULL) {
  2530. uint i;
  2531. for (i = 0; i < MaxAllocatedConnBlocks; i++) {
  2532. ExFreePool(OldTable[i]);
  2533. }
  2534. ExFreePool(OldTable);
  2535. }
  2536. }