Source code of Windows XP (NT5)
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.

512 lines
14 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. mapping.h
  5. Abstract:
  6. This file contains declarations for the management of dynamic mappings.
  7. This includes the relevant data structures as well as the routines for
  8. manipulating the structures.
  9. Author:
  10. Abolade Gbadegesin (t-abolag) 11-July-1997
  11. Revision History:
  12. --*/
  13. #ifndef _NAT_MAPPING_H_
  14. #define _NAT_MAPPING_H_
  15. //
  16. // Forward declaration of structure defined elsewhere
  17. //
  18. struct _NAT_INTERFACE;
  19. #define PNAT_INTERFACE struct _NAT_INTERFACE*
  20. typedef enum _NAT_SESSION_MAPPING_INFORMATION_CLASS {
  21. NatKeySessionMappingInformation,
  22. NatStatisticsSessionMappingInformation,
  23. #if _WIN32_WINNT > 0x0500
  24. NatKeySessionMappingExInformation,
  25. #endif
  26. NatMaximumSessionMappingInformation
  27. } NAT_SESSION_MAPPING_INFORMATION_CLASS,
  28. *PNAT_SESSION_MAPPING_INFORMATION_CLASS;
  29. //
  30. // Structure: NAT_DYNAMIC_MAPPING
  31. //
  32. // This structure holds information about a specific active session.
  33. // Each instance is held on the global mapping-list as well as
  34. // on the global mapping-trees for forward and reverse access.
  35. //
  36. // Each mapping stores four keys which are address/protocol/port combinations:
  37. // forward source and destination keys (the original session-endpoints),
  38. // and reverse source and destination keys (the translated endpoints).
  39. //
  40. // Each time a packet is translated using a mapping, the 'LastAccessTime'
  41. // is set to the number of ticks since system-start (KeQueryTickCount).
  42. // This value is used by our timer routine to eliminate expired mappings.
  43. //
  44. // Synchronization of access to mappings is similar to that of interfaces,
  45. // editors, and directors:
  46. //
  47. // We use a reference count to ensure the existence of a mapping,
  48. // and a spin-lock to ensure its consistency.
  49. //
  50. // The fields of a mapping are only consistent while the spinlock is held
  51. // (with the exception of fields such as 'PrivateKey' which are read-only)
  52. //
  53. // The spinlock can only be acquired if
  54. // (a) the reference-count has been incremented, or
  55. // (b) the mapping-list lock is already held.
  56. //
  57. // If the mapping is for an edited, directed, or interface's session,
  58. // it also lives on its editor's, director's or interface's list of mappings.
  59. // The following holds true of all three lists (i.e. for 'Editor' write
  60. // 'Director' or 'Interface' as appropriate):
  61. //
  62. // As described in 'EDITOR.H', the cached fields 'Editor*' are protected
  63. // by the global 'EditorMappingLock'. Hence,
  64. //
  65. // (a) to read the 'Editor' or 'EditorContext' for a mapping,
  66. // or to traverse the 'EditorLink' field, 'EditorLock' must be held
  67. // and the editor referenced. Note that the attempt to reference
  68. // the editor will fail if the editor has been marked for deletion.
  69. //
  70. // (b) to modify the 'Editor' or 'EditorContext' or to add or
  71. // remove a mapping from its editor's list of mappings by changing
  72. // the 'EditorLink' field, both 'EditorLock' and 'EditorMappingLock'
  73. // must be acquired, in that order.
  74. //
  75. // Acquisition of 'EditorLock' ensures that the cached editor will not be
  76. // deleted while being referenced, and acquisition of 'EditorMappingLock'
  77. // ensures that no changes are being made to the list.
  78. //
  79. // N.B. On the rare occasions when 'MappingLock' must be held at the same time
  80. // as one of 'InterfaceLock', 'EditorLock', and 'DirectorLock', 'MappingLock'
  81. // must always be acquired first.
  82. //
  83. typedef struct _NAT_DYNAMIC_MAPPING {
  84. LIST_ENTRY Link;
  85. RTL_SPLAY_LINKS SLink[NatMaximumPath];
  86. ULONG64 DestinationKey[NatMaximumPath]; // read-only
  87. ULONG64 SourceKey[NatMaximumPath]; // read-only
  88. LONG64 LastAccessTime;
  89. KSPIN_LOCK Lock;
  90. ULONG ReferenceCount;
  91. ULONG AccessCount[NatMaximumPath]; // interlocked-access only
  92. PNAT_TRANSLATE_ROUTINE TranslateRoutine[NatMaximumPath]; // read-only
  93. PNAT_INTERFACE Interfacep;
  94. PVOID InterfaceContext;
  95. LIST_ENTRY InterfaceLink;
  96. PNAT_EDITOR Editor;
  97. PVOID EditorContext;
  98. LIST_ENTRY EditorLink;
  99. PNAT_DIRECTOR Director;
  100. PVOID DirectorContext;
  101. LIST_ENTRY DirectorLink;
  102. ULONG Flags;
  103. ULONG IpChecksumDelta[NatMaximumPath];
  104. ULONG ProtocolChecksumDelta[NatMaximumPath];
  105. ULONG TcpSeqNumExpected[NatMaximumPath];
  106. ULONG TcpSeqNumBase[NatMaximumPath];
  107. LONG TcpSeqNumDelta[NatMaximumPath];
  108. // Maxmimum MSS value. Set to 0 if MSS adjustment is unnecessary.
  109. USHORT MaxMSS;
  110. IP_NAT_SESSION_MAPPING_STATISTICS Statistics;
  111. ULONG BytesForward; // interlocked-access only
  112. ULONG BytesReverse; // interlocked-access only
  113. ULONG PacketsForward; // interlocked-access only
  114. ULONG PacketsReverse; // interlocked-access only
  115. ULONG RejectsForward; // interlocked-access only
  116. ULONG RejectsReverse; // interlocked-access only
  117. } NAT_DYNAMIC_MAPPING, *PNAT_DYNAMIC_MAPPING;
  118. //
  119. // Definition of flags for NAT_DYNAMIC_MAPPING.Flags
  120. //
  121. // Set after a mapping has been deleted; when the last reference is released,
  122. // the mapping will be freed.
  123. //
  124. #define NAT_MAPPING_FLAG_DELETED 0x80000000
  125. #define NAT_MAPPING_DELETED(m) \
  126. ((m)->Flags & NAT_MAPPING_FLAG_DELETED)
  127. //
  128. // Set when an editor expires a mapping using 'NatEditorTimeoutSession'.
  129. //
  130. #define NAT_MAPPING_FLAG_EXPIRED 0x00000001
  131. #define NAT_MAPPING_EXPIRED(m) \
  132. ((m)->Flags & NAT_MAPPING_FLAG_EXPIRED)
  133. //
  134. // Set when the forward/reverse SYN for a TCP session is seen, respectively
  135. //
  136. #define NAT_MAPPING_FLAG_FWD_SYN 0x00000002
  137. #define NAT_MAPPING_FLAG_REV_SYN 0x00000004
  138. //
  139. // Set when the forward/reverse FIN for a TCP session is seen, respectively
  140. //
  141. #define NAT_MAPPING_FLAG_FWD_FIN 0x00000008
  142. #define NAT_MAPPING_FLAG_REV_FIN 0x00000010
  143. #define NAT_MAPPING_FIN(m) \
  144. (((m)->Flags & NAT_MAPPING_FLAG_FWD_FIN) && \
  145. ((m)->Flags & NAT_MAPPING_FLAG_REV_FIN))
  146. //
  147. // Set when an inbound mapping is created using a static address or port,
  148. // or because of a director or ticket.
  149. //
  150. #define NAT_MAPPING_FLAG_INBOUND 0x00000020
  151. #define NAT_MAPPING_INBOUND(m) \
  152. ((m)->Flags & NAT_MAPPING_FLAG_INBOUND)
  153. //
  154. // Set when a mapping is created by a director and is not subject to expiration.
  155. //
  156. #define NAT_MAPPING_FLAG_NO_TIMEOUT 0x00000040
  157. #define NAT_MAPPING_NO_TIMEOUT(m) \
  158. ((m)->Flags & NAT_MAPPING_FLAG_NO_TIMEOUT)
  159. //
  160. // Set when only forward packets are to be translated
  161. //
  162. #define NAT_MAPPING_FLAG_UNIDIRECTIONAL 0x00000080
  163. #define NAT_MAPPING_UNIDIRECTIONAL(m) \
  164. ((m)->Flags & NAT_MAPPING_FLAG_UNIDIRECTIONAL)
  165. //
  166. // Set when director-initiated dissociation should trigger deletion
  167. //
  168. #define NAT_MAPPING_FLAG_DELETE_ON_DISSOCIATE_DIRECTOR 0x00000100
  169. #define NAT_MAPPING_DELETE_ON_DISSOCIATE_DIRECTOR(m) \
  170. ((m)->Flags & NAT_MAPPING_FLAG_DELETE_ON_DISSOCIATE_DIRECTOR)
  171. //
  172. // Set on TCP mappings when the three-way handshake is complete
  173. //
  174. #define NAT_MAPPING_FLAG_TCP_OPEN 0x00000200
  175. #define NAT_MAPPING_TCP_OPEN(m) \
  176. ((m)->Flags & NAT_MAPPING_FLAG_TCP_OPEN)
  177. //
  178. // Set if the creation or deletion of this mapping should not
  179. // be logged
  180. //
  181. #define NAT_MAPPING_FLAG_DO_NOT_LOG 0x00000400
  182. #define NAT_MAPPING_DO_NOT_LOG(m) \
  183. ((m)->Flags & NAT_MAPPING_FLAG_DO_NOT_LOG)
  184. //
  185. // Set if the DF bit must be cleared for all packets that belong
  186. // to this mapping.
  187. //
  188. #define NAT_MAPPING_FLAG_CLEAR_DF_BIT 0x00000800
  189. #define NAT_MAPPING_CLEAR_DF_BIT(m) \
  190. ((m)->Flags & NAT_MAPPING_FLAG_CLEAR_DF_BIT)
  191. //
  192. // Mapping-key manipulation macros
  193. //
  194. #define MAKE_MAPPING_KEY(Key,Protocol,Address,Port) \
  195. ((Key) = \
  196. (Address) | \
  197. ((ULONG64)((Port) & 0xFFFF) << 32) | \
  198. ((ULONG64)((Protocol) & 0xFF) << 48))
  199. #define MAPPING_PROTOCOL(Key) ((UCHAR)(((Key) >> 48) & 0xFF))
  200. #define MAPPING_PORT(Key) ((USHORT)(((Key) >> 32) & 0xFFFF))
  201. #define MAPPING_ADDRESS(Key) ((ULONG)(Key))
  202. //
  203. // Resplay threshold; the mapping is resplayed every time its access-count
  204. // passes this value.
  205. //
  206. #define NAT_MAPPING_RESPLAY_THRESHOLD 5
  207. //
  208. // Defines the depth of the lookaside list for allocating dynamic mappings
  209. //
  210. #define MAPPING_LOOKASIDE_DEPTH 20
  211. //
  212. // Defines the threshold at which ad-hoc cleanup of expired mappings begins.
  213. //
  214. #define MAPPING_CLEANUP_THRESHOLD 1000
  215. //
  216. // Mapping allocation macros
  217. //
  218. #define ALLOCATE_MAPPING_BLOCK() \
  219. ExAllocateFromNPagedLookasideList(&MappingLookasideList)
  220. #define FREE_MAPPING_BLOCK(Block) \
  221. ExFreeToNPagedLookasideList(&MappingLookasideList,(Block))
  222. //
  223. // GLOBAL VARIABLE DECLARATIONS
  224. //
  225. extern ULONG ExpiredMappingCount;
  226. extern CACHE_ENTRY MappingCache[NatMaximumPath][CACHE_SIZE];
  227. extern ULONG MappingCount;
  228. extern LIST_ENTRY MappingList;
  229. extern KSPIN_LOCK MappingLock;
  230. extern NPAGED_LOOKASIDE_LIST MappingLookasideList;
  231. extern PNAT_DYNAMIC_MAPPING MappingTree[NatMaximumPath];
  232. //
  233. // MAPPING MANAGEMENT ROUTINES
  234. //
  235. PVOID
  236. NatAllocateFunction(
  237. POOL_TYPE PoolType,
  238. SIZE_T NumberOfBytes,
  239. ULONG Tag
  240. );
  241. VOID
  242. NatCleanupMapping(
  243. PNAT_DYNAMIC_MAPPING Mapping
  244. );
  245. NTSTATUS
  246. NatCreateMapping(
  247. ULONG Flags,
  248. ULONG64 DestinationKey[],
  249. ULONG64 SourceKey[],
  250. PNAT_INTERFACE Interfacep,
  251. PVOID InterfaceContext,
  252. USHORT MaxMSS,
  253. PNAT_DIRECTOR Director,
  254. PVOID DirectorContext,
  255. PNAT_DYNAMIC_MAPPING* InboundInsertionPoint,
  256. PNAT_DYNAMIC_MAPPING* OutboundInsertionPoint,
  257. PNAT_DYNAMIC_MAPPING* MappingCreated
  258. );
  259. NTSTATUS
  260. NatDeleteMapping(
  261. PNAT_DYNAMIC_MAPPING Mapping
  262. );
  263. //
  264. // BOOLEAN
  265. // NatDereferenceMapping(
  266. // PNAT_DYNAMIC_MAPPING Mapping
  267. // );
  268. //
  269. #define \
  270. NatDereferenceMapping( \
  271. _Mapping \
  272. ) \
  273. (InterlockedDecrement(&(_Mapping)->ReferenceCount) \
  274. ? TRUE \
  275. : (NatCleanupMapping(_Mapping), FALSE))
  276. //
  277. // VOID
  278. // NatExpireMapping(
  279. // PNAT_DYNAMIC_MAPPING Mapping
  280. // );
  281. //
  282. PNAT_DYNAMIC_MAPPING
  283. NatDestinationLookupForwardMapping(
  284. ULONG64 DestinationKey
  285. );
  286. PNAT_DYNAMIC_MAPPING
  287. NatDestinationLookupReverseMapping(
  288. ULONG64 DestinationKey
  289. );
  290. #define \
  291. NatExpireMapping( \
  292. _Mapping \
  293. ) \
  294. if (!NAT_MAPPING_EXPIRED(_Mapping)) { \
  295. (_Mapping)->Flags |= NAT_MAPPING_FLAG_EXPIRED; \
  296. InterlockedIncrement(&ExpiredMappingCount); \
  297. if (MappingCount > MAPPING_CLEANUP_THRESHOLD && \
  298. ExpiredMappingCount >= (MappingCount >> 2)) { \
  299. NatTriggerTimer(); \
  300. } \
  301. }
  302. VOID
  303. NatInitializeMappingManagement(
  304. VOID
  305. );
  306. PNAT_DYNAMIC_MAPPING
  307. NatInsertForwardMapping(
  308. PNAT_DYNAMIC_MAPPING Parent,
  309. PNAT_DYNAMIC_MAPPING Mapping
  310. );
  311. PNAT_DYNAMIC_MAPPING
  312. NatInsertReverseMapping(
  313. PNAT_DYNAMIC_MAPPING Parent,
  314. PNAT_DYNAMIC_MAPPING Mapping
  315. );
  316. NTSTATUS
  317. NatLookupAndQueryInformationMapping(
  318. UCHAR Protocol,
  319. ULONG DestinationAddress,
  320. USHORT DestinationPort,
  321. ULONG SourceAddress,
  322. USHORT SourcePort,
  323. OUT PVOID Information,
  324. ULONG InformationLength,
  325. NAT_SESSION_MAPPING_INFORMATION_CLASS InformationClass
  326. );
  327. PNAT_DYNAMIC_MAPPING
  328. NatLookupForwardMapping(
  329. ULONG64 DestinationKey,
  330. ULONG64 SourceKey,
  331. PNAT_DYNAMIC_MAPPING* InsertionPoint
  332. );
  333. PNAT_DYNAMIC_MAPPING
  334. NatLookupReverseMapping(
  335. ULONG64 DestinationKey,
  336. ULONG64 SourceKey,
  337. PNAT_DYNAMIC_MAPPING* InsertionPoint
  338. );
  339. VOID
  340. NatQueryInformationMapping(
  341. IN PNAT_DYNAMIC_MAPPING Mapping,
  342. OUT PUCHAR Protocol OPTIONAL,
  343. OUT PULONG PrivateAddress OPTIONAL,
  344. OUT PUSHORT PrivatePort OPTIONAL,
  345. OUT PULONG RemoteAddress OPTIONAL,
  346. OUT PUSHORT RemotePort OPTIONAL,
  347. OUT PULONG PublicAddress OPTIONAL,
  348. OUT PUSHORT PublicPort OPTIONAL,
  349. OUT PIP_NAT_SESSION_MAPPING_STATISTICS Statistics OPTIONAL
  350. );
  351. NTSTATUS
  352. NatQueryInterfaceMappingTable(
  353. IN PIP_NAT_ENUMERATE_SESSION_MAPPINGS InputBuffer,
  354. IN PIP_NAT_ENUMERATE_SESSION_MAPPINGS OutputBuffer,
  355. IN PULONG OutputBufferLength
  356. );
  357. NTSTATUS
  358. NatQueryMappingTable(
  359. IN PIP_NAT_ENUMERATE_SESSION_MAPPINGS InputBuffer,
  360. IN PIP_NAT_ENUMERATE_SESSION_MAPPINGS OutputBuffer,
  361. IN PULONG OutputBufferLength
  362. );
  363. //
  364. // BOOLEAN
  365. // NatReferenceMapping(
  366. // PNAT_DYNAMIC_MAPPING Mapping
  367. // );
  368. //
  369. #define \
  370. NatReferenceMapping( \
  371. _Mapping \
  372. ) \
  373. (NAT_MAPPING_DELETED(_Mapping) \
  374. ? FALSE \
  375. : (InterlockedIncrement(&(_Mapping)->ReferenceCount), TRUE))
  376. //
  377. // VOID
  378. // NatResplayMapping(
  379. // PNAT_DYNAMIC_MAPPING Mapping,
  380. // IP_NAT_PATH Path
  381. // );
  382. //
  383. #define \
  384. NatResplayMapping( \
  385. _Mapping, \
  386. _Path \
  387. ) \
  388. { \
  389. PRTL_SPLAY_LINKS _SLink; \
  390. KeAcquireSpinLockAtDpcLevel(&MappingLock); \
  391. if (!NAT_MAPPING_DELETED(_Mapping)) { \
  392. _SLink = RtlSplay(&(_Mapping)->SLink[_Path]); \
  393. MappingTree[_Path] = \
  394. CONTAINING_RECORD(_SLink, NAT_DYNAMIC_MAPPING, SLink[_Path]); \
  395. } \
  396. KeReleaseSpinLockFromDpcLevel(&MappingLock); \
  397. }
  398. VOID
  399. NatShutdownMappingManagement(
  400. VOID
  401. );
  402. PNAT_DYNAMIC_MAPPING
  403. NatSourceLookupForwardMapping(
  404. ULONG64 SourceKey
  405. );
  406. PNAT_DYNAMIC_MAPPING
  407. NatSourceLookupReverseMapping(
  408. ULONG64 SourceKey
  409. );
  410. //
  411. // VOID
  412. // NatTryToResplayMapping(
  413. // PNAT_DYNAMIC_MAPPING Mapping,
  414. // IP_NAT_PATH Path
  415. // );
  416. //
  417. #define \
  418. NatTryToResplayMapping( \
  419. _Mapping, \
  420. _Path \
  421. ) \
  422. if (InterlockedDecrement(&(_Mapping)->AccessCount[(_Path)]) == 0) { \
  423. NatResplayMapping((_Mapping), (_Path)); \
  424. InterlockedExchangeAdd( \
  425. &(_Mapping)->AccessCount[(_Path)], \
  426. NAT_MAPPING_RESPLAY_THRESHOLD \
  427. ); \
  428. }
  429. VOID
  430. NatUpdateStatisticsMapping(
  431. PNAT_DYNAMIC_MAPPING Mapping
  432. );
  433. #undef PNAT_INTERFACE
  434. #endif // _NAT_MAPPING_H_