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.

308 lines
7.8 KiB

  1. /*++
  2. Copyright (c) 1997-2001 Microsoft Corporation
  3. Module Name:
  4. NsConn.h
  5. Abstract:
  6. Declarations for IpSec NAT shim connection entry management
  7. Author:
  8. Jonathan Burstein (jonburs) 10-July-2001
  9. Environment:
  10. Kernel mode
  11. Revision History:
  12. --*/
  13. #pragma once
  14. //
  15. // Structure: _NS_CONNECTION_ENTRY
  16. //
  17. // This structure holds information about a specific active session.
  18. // Each instance is held on the global connection list as well as
  19. // on the global connection trees for inbound and outbound access.
  20. //
  21. // Each connection entry contains 5 pieces of identifying information:
  22. // 1) the address key (local and remote IP addresses)
  23. // 2) the protocol for the connection (TCP or UDP)
  24. // 3) the IpSec context
  25. // 4) the inbound (original) port key
  26. // 5) the outbound (translated) port key
  27. //
  28. // Each time a packet is processed for a connection, the 'l64AccessOrExpiryTime'
  29. // is set to the number of ticks since system-start (KeQueryTickCount).
  30. // This value is used by our timer routine to eliminate expired connections.
  31. //
  32. // For TCP connections, 'l64AccessOrExpiryTime' will no longer be updated once
  33. // FINs are seen in both direction. This is necessary for the timer routine
  34. // to correctly evaluate whether or not the connection has left the time_wait
  35. // state, and thus to prevent premature port reuse.
  36. //
  37. // Synchronization rules:
  38. //
  39. // We use a reference count to ensure the existence of a connection entry,
  40. // and a spin-lock to ensure its consistency.
  41. //
  42. // The fields of a connection entry are only consistent while the spinlock is
  43. // held (with the exception of fields such as 'ul64AddressKey' which are
  44. // read-only and fields such as 'ulReferenceCount' that are interlocked-access
  45. // only.)
  46. //
  47. // The spinlock can only be acquired if
  48. // (a) the reference-count has been incremented, or
  49. // (b) the connection list lock is already held.
  50. //
  51. typedef struct _NS_CONNECTION_ENTRY
  52. {
  53. LIST_ENTRY Link;
  54. RTL_SPLAY_LINKS SLink[NsMaximumDirection];
  55. KSPIN_LOCK Lock;
  56. ULONG ulReferenceCount; // interlocked-access only
  57. ULONG ulFlags;
  58. ULONG64 ul64AddressKey; // read-only
  59. ULONG ulPortKey[NsMaximumDirection]; // read-only
  60. PVOID pvIpSecContext; // read-only
  61. UCHAR ucProtocol; // read-only
  62. LONG64 l64AccessOrExpiryTime;
  63. ULONG ulAccessCount[NsMaximumDirection]; // interlocked-access only
  64. ULONG ulProtocolChecksumDelta[NsMaximumDirection];
  65. PNS_PACKET_ROUTINE PacketRoutine[NsMaximumDirection]; // read-only
  66. } NS_CONNECTION_ENTRY, *PNS_CONNECTION_ENTRY;
  67. //
  68. // Set after a connection entry has been deleted; when the last
  69. // reference is released the entry will be freed
  70. //
  71. #define NS_CONNECTION_FLAG_DELETED 0x80000000
  72. #define NS_CONNECTION_DELETED(c) \
  73. ((c)->ulFlags & NS_CONNECTION_FLAG_DELETED)
  74. //
  75. // Set when a connection entry is expired
  76. //
  77. #define NS_CONNECTION_FLAG_EXPIRED 0x00000001
  78. #define NS_CONNECTION_EXPIRED(c) \
  79. ((c)->ulFlags & NS_CONNECTION_FLAG_EXPIRED)
  80. //
  81. // Set when inbound / outbound FIN for a TCP session is seen
  82. //
  83. #define NS_CONNECTION_FLAG_OB_FIN 0x00000002
  84. #define NS_CONNECTION_FLAG_IB_FIN 0x00000004
  85. #define NS_CONNECTION_FIN(c) \
  86. (((c)->ulFlags & NS_CONNECTION_FLAG_OB_FIN) \
  87. && ((c)->ulFlags & NS_CONNECTION_FLAG_IB_FIN))
  88. //
  89. // Connection entry key manipulation macros
  90. //
  91. #define MAKE_ADDRESS_KEY(Key, ulLocalAddress, ulRemoteAddress) \
  92. ((Key) = ((ULONG64)(ulLocalAddress) << 32) | (ulRemoteAddress))
  93. #define CONNECTION_LOCAL_ADDRESS(ul64AddressKey) \
  94. ((ULONG)(((ul64AddressKey) >> 32) & 0xFFFFFFFF))
  95. #define CONNECTION_REMOTE_ADDRESS(ul64AddressKey) \
  96. ((ULONG)((ul64AddressKey)))
  97. #define MAKE_PORT_KEY(Key, usLocalPort, usRemotePort) \
  98. ((Key) = ((ULONG)(usLocalPort & 0xFFFF) << 16) | (usRemotePort & 0xFFFF))
  99. #define CONNECTION_LOCAL_PORT(ulPortKey) \
  100. ((USHORT)(((ulPortKey) >> 16) & 0xFFFF))
  101. #define CONNECTION_REMOTE_PORT(ulPortKey) \
  102. ((USHORT)(ulPortKey))
  103. //
  104. // Resplay threshold; the entry is resplayed every time its access-count
  105. // passes this value.
  106. //
  107. #define NS_CONNECTION_RESPLAY_THRESHOLD 5
  108. //
  109. // Defines the depth of the lookaside list for allocating connection entries
  110. //
  111. #define NS_CONNECTION_LOOKASIDE_DEPTH 20
  112. //
  113. // Connection entry allocation macros
  114. //
  115. #define ALLOCATE_CONNECTION_BLOCK() \
  116. ExAllocateFromNPagedLookasideList(&NsConnectionLookasideList)
  117. #define FREE_CONNECTION_BLOCK(Block) \
  118. ExFreeToNPagedLookasideList(&NsConnectionLookasideList,(Block))
  119. //
  120. // Port range boundaries
  121. //
  122. #define NS_SOURCE_PORT_BASE 6000
  123. #define NS_SOURCE_PORT_END 65534
  124. //
  125. // GLOBAL VARIABLE DECLARATIONS
  126. //
  127. extern CACHE_ENTRY NsConnectionCache[CACHE_SIZE];
  128. extern ULONG NsConnectionCount;
  129. extern LIST_ENTRY NsConnectionList;
  130. extern KSPIN_LOCK NsConnectionLock;
  131. extern NPAGED_LOOKASIDE_LIST NsConnectionLookasideList;
  132. extern PNS_CONNECTION_ENTRY NsConnectionTree[NsMaximumDirection];
  133. extern USHORT NsNextSourcePort;
  134. //
  135. // Function Prototypes
  136. //
  137. NTSTATUS
  138. NsAllocateSourcePort(
  139. ULONG64 ul64AddressKey,
  140. ULONG ulPortKey,
  141. UCHAR ucProtocol,
  142. BOOLEAN fPortConflicts,
  143. PNS_CONNECTION_ENTRY *ppOutboundInsertionPoint,
  144. PULONG pulTranslatedPortKey
  145. );
  146. VOID
  147. NsCleanupConnectionEntry(
  148. PNS_CONNECTION_ENTRY pEntry
  149. );
  150. NTSTATUS
  151. NsCreateConnectionEntry(
  152. ULONG64 ul64AddressKey,
  153. ULONG ulInboundPortKey,
  154. ULONG ulOutboundPortKey,
  155. UCHAR ucProtocol,
  156. PVOID pvIpSecContext,
  157. PNS_CONNECTION_ENTRY pInboundInsertionPoint,
  158. PNS_CONNECTION_ENTRY pOutboundInsertionPoint,
  159. PNS_CONNECTION_ENTRY *ppNewEntry
  160. );
  161. NTSTATUS
  162. NsDeleteConnectionEntry(
  163. PNS_CONNECTION_ENTRY pEntry
  164. );
  165. __forceinline
  166. VOID
  167. NsDereferenceConnectionEntry(
  168. PNS_CONNECTION_ENTRY pEntry
  169. )
  170. {
  171. if (0 == InterlockedDecrement(&pEntry->ulReferenceCount))
  172. {
  173. NsCleanupConnectionEntry(pEntry);
  174. }
  175. }
  176. NTSTATUS
  177. NsInitializeConnectionManagement(
  178. VOID
  179. );
  180. PNS_CONNECTION_ENTRY
  181. NsLookupInboundConnectionEntry(
  182. ULONG64 ul64AddressKey,
  183. ULONG ulPortKey,
  184. UCHAR ucProtocol,
  185. PVOID pvIpSecContext,
  186. BOOLEAN *pfPortConflicts OPTIONAL,
  187. PNS_CONNECTION_ENTRY *ppInsertionPoint OPTIONAL
  188. );
  189. PNS_CONNECTION_ENTRY
  190. NsLookupOutboundConnectionEntry(
  191. ULONG64 ul64AddressKey,
  192. ULONG ulPortKey,
  193. UCHAR ucProtocol,
  194. PNS_CONNECTION_ENTRY *ppInsertionPoint OPTIONAL
  195. );
  196. __forceinline
  197. BOOLEAN
  198. NsReferenceConnectionEntry(
  199. PNS_CONNECTION_ENTRY pEntry
  200. )
  201. {
  202. if (NS_CONNECTION_DELETED(pEntry))
  203. {
  204. return FALSE;
  205. }
  206. else
  207. {
  208. InterlockedIncrement(&pEntry->ulReferenceCount);
  209. return TRUE;
  210. }
  211. }
  212. __forceinline
  213. VOID
  214. NsResplayConnectionEntry(
  215. PNS_CONNECTION_ENTRY pEntry,
  216. IPSEC_NATSHIM_DIRECTION Direction
  217. )
  218. {
  219. PRTL_SPLAY_LINKS SLink;
  220. KeAcquireSpinLockAtDpcLevel(&NsConnectionLock);
  221. if (!NS_CONNECTION_DELETED(pEntry))
  222. {
  223. SLink = RtlSplay(&pEntry->SLink[Direction]);
  224. NsConnectionTree[Direction] =
  225. CONTAINING_RECORD(SLink, NS_CONNECTION_ENTRY, SLink[Direction]);
  226. }
  227. KeReleaseSpinLockFromDpcLevel(&NsConnectionLock);
  228. }
  229. VOID
  230. NsShutdownConnectionManagement(
  231. VOID
  232. );
  233. __forceinline
  234. VOID
  235. NsTryToResplayConnectionEntry(
  236. PNS_CONNECTION_ENTRY pEntry,
  237. IPSEC_NATSHIM_DIRECTION Direction
  238. )
  239. {
  240. if (0 == InterlockedDecrement(&pEntry->ulAccessCount[Direction]))
  241. {
  242. NsResplayConnectionEntry(pEntry, Direction);
  243. InterlockedExchangeAdd(
  244. &pEntry->ulAccessCount[Direction],
  245. NS_CONNECTION_RESPLAY_THRESHOLD
  246. );
  247. }
  248. }