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.

532 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. union {
  106. struct {
  107. ULONG Expected[NatMaximumPath];
  108. ULONG Base[NatMaximumPath];
  109. LONG Delta[NatMaximumPath];
  110. } TcpSeqNum;
  111. RTL_SPLAY_LINKS SourceSLink[NatMaximumPath];
  112. } u;
  113. // Maxmimum MSS value. Set to 0 if MSS adjustment is unnecessary.
  114. USHORT MaxMSS;
  115. IP_NAT_SESSION_MAPPING_STATISTICS Statistics;
  116. ULONG BytesForward; // interlocked-access only
  117. ULONG BytesReverse; // interlocked-access only
  118. ULONG PacketsForward; // interlocked-access only
  119. ULONG PacketsReverse; // interlocked-access only
  120. ULONG RejectsForward; // interlocked-access only
  121. ULONG RejectsReverse; // interlocked-access only
  122. } NAT_DYNAMIC_MAPPING, *PNAT_DYNAMIC_MAPPING;
  123. //
  124. // Definition of flags for NAT_DYNAMIC_MAPPING.Flags
  125. //
  126. // Set after a mapping has been deleted; when the last reference is released,
  127. // the mapping will be freed.
  128. //
  129. #define NAT_MAPPING_FLAG_DELETED 0x80000000
  130. #define NAT_MAPPING_DELETED(m) \
  131. ((m)->Flags & NAT_MAPPING_FLAG_DELETED)
  132. //
  133. // Set when an editor expires a mapping using 'NatEditorTimeoutSession'.
  134. //
  135. #define NAT_MAPPING_FLAG_EXPIRED 0x00000001
  136. #define NAT_MAPPING_EXPIRED(m) \
  137. ((m)->Flags & NAT_MAPPING_FLAG_EXPIRED)
  138. //
  139. // Set when the forward/reverse SYN for a TCP session is seen, respectively
  140. //
  141. #define NAT_MAPPING_FLAG_FWD_SYN 0x00000002
  142. #define NAT_MAPPING_FLAG_REV_SYN 0x00000004
  143. //
  144. // Set when the forward/reverse FIN for a TCP session is seen, respectively
  145. //
  146. #define NAT_MAPPING_FLAG_FWD_FIN 0x00000008
  147. #define NAT_MAPPING_FLAG_REV_FIN 0x00000010
  148. #define NAT_MAPPING_FIN(m) \
  149. (((m)->Flags & NAT_MAPPING_FLAG_FWD_FIN) && \
  150. ((m)->Flags & NAT_MAPPING_FLAG_REV_FIN))
  151. //
  152. // Set when an inbound mapping is created using a static address or port,
  153. // or because of a director or ticket.
  154. //
  155. #define NAT_MAPPING_FLAG_INBOUND 0x00000020
  156. #define NAT_MAPPING_INBOUND(m) \
  157. ((m)->Flags & NAT_MAPPING_FLAG_INBOUND)
  158. //
  159. // Set when a mapping is created by a director and is not subject to expiration.
  160. //
  161. #define NAT_MAPPING_FLAG_NO_TIMEOUT 0x00000040
  162. #define NAT_MAPPING_NO_TIMEOUT(m) \
  163. ((m)->Flags & NAT_MAPPING_FLAG_NO_TIMEOUT)
  164. //
  165. // Set when only forward packets are to be translated
  166. //
  167. #define NAT_MAPPING_FLAG_UNIDIRECTIONAL 0x00000080
  168. #define NAT_MAPPING_UNIDIRECTIONAL(m) \
  169. ((m)->Flags & NAT_MAPPING_FLAG_UNIDIRECTIONAL)
  170. //
  171. // Set when director-initiated dissociation should trigger deletion
  172. //
  173. #define NAT_MAPPING_FLAG_DELETE_ON_DISSOCIATE_DIRECTOR 0x00000100
  174. #define NAT_MAPPING_DELETE_ON_DISSOCIATE_DIRECTOR(m) \
  175. ((m)->Flags & NAT_MAPPING_FLAG_DELETE_ON_DISSOCIATE_DIRECTOR)
  176. //
  177. // Set on TCP mappings when the three-way handshake is complete
  178. //
  179. #define NAT_MAPPING_FLAG_TCP_OPEN 0x00000200
  180. #define NAT_MAPPING_TCP_OPEN(m) \
  181. ((m)->Flags & NAT_MAPPING_FLAG_TCP_OPEN)
  182. //
  183. // Set if the creation or deletion of this mapping should not
  184. // be logged
  185. //
  186. #define NAT_MAPPING_FLAG_DO_NOT_LOG 0x00000400
  187. #define NAT_MAPPING_DO_NOT_LOG(m) \
  188. ((m)->Flags & NAT_MAPPING_FLAG_DO_NOT_LOG)
  189. //
  190. // Set if the DF bit must be cleared for all packets that belong
  191. // to this mapping.
  192. //
  193. #define NAT_MAPPING_FLAG_CLEAR_DF_BIT 0x00000800
  194. #define NAT_MAPPING_CLEAR_DF_BIT(m) \
  195. ((m)->Flags & NAT_MAPPING_FLAG_CLEAR_DF_BIT)
  196. //
  197. // Mapping-key manipulation macros
  198. //
  199. #define MAKE_MAPPING_KEY(Key,Protocol,Address,Port) \
  200. ((Key) = \
  201. (Address) | \
  202. ((ULONG64)((Port) & 0xFFFF) << 32) | \
  203. ((ULONG64)((Protocol) & 0xFF) << 48))
  204. #define MAPPING_PROTOCOL(Key) ((UCHAR)(((Key) >> 48) & 0xFF))
  205. #define MAPPING_PORT(Key) ((USHORT)(((Key) >> 32) & 0xFFFF))
  206. #define MAPPING_ADDRESS(Key) ((ULONG)(Key))
  207. //
  208. // Resplay threshold; the mapping is resplayed every time its access-count
  209. // passes this value.
  210. //
  211. #define NAT_MAPPING_RESPLAY_THRESHOLD 5
  212. //
  213. // Defines the depth of the lookaside list for allocating dynamic mappings
  214. //
  215. #define MAPPING_LOOKASIDE_DEPTH 20
  216. //
  217. // Defines the threshold at which ad-hoc cleanup of expired mappings begins.
  218. //
  219. #define MAPPING_CLEANUP_THRESHOLD 1000
  220. //
  221. // Mapping allocation macros
  222. //
  223. #define ALLOCATE_MAPPING_BLOCK() \
  224. ExAllocateFromNPagedLookasideList(&MappingLookasideList)
  225. #define FREE_MAPPING_BLOCK(Block) \
  226. ExFreeToNPagedLookasideList(&MappingLookasideList,(Block))
  227. //
  228. // GLOBAL VARIABLE DECLARATIONS
  229. //
  230. extern ULONG ExpiredMappingCount;
  231. extern CACHE_ENTRY MappingCache[NatMaximumPath][CACHE_SIZE];
  232. extern ULONG MappingCount;
  233. extern LIST_ENTRY MappingList;
  234. extern KSPIN_LOCK MappingLock;
  235. extern NPAGED_LOOKASIDE_LIST MappingLookasideList;
  236. extern PNAT_DYNAMIC_MAPPING MappingTree[NatMaximumPath];
  237. //
  238. // MAPPING MANAGEMENT ROUTINES
  239. //
  240. PVOID
  241. NatAllocateFunction(
  242. POOL_TYPE PoolType,
  243. SIZE_T NumberOfBytes,
  244. ULONG Tag
  245. );
  246. VOID
  247. NatCleanupMapping(
  248. PNAT_DYNAMIC_MAPPING Mapping
  249. );
  250. NTSTATUS
  251. NatCreateMapping(
  252. ULONG Flags,
  253. ULONG64 DestinationKey[],
  254. ULONG64 SourceKey[],
  255. PNAT_INTERFACE Interfacep,
  256. PVOID InterfaceContext,
  257. USHORT MaxMSS,
  258. PNAT_DIRECTOR Director,
  259. PVOID DirectorContext,
  260. PNAT_DYNAMIC_MAPPING* InboundInsertionPoint,
  261. PNAT_DYNAMIC_MAPPING* OutboundInsertionPoint,
  262. PNAT_DYNAMIC_MAPPING* MappingCreated
  263. );
  264. NTSTATUS
  265. NatDeleteMapping(
  266. PNAT_DYNAMIC_MAPPING Mapping
  267. );
  268. //
  269. // BOOLEAN
  270. // NatDereferenceMapping(
  271. // PNAT_DYNAMIC_MAPPING Mapping
  272. // );
  273. //
  274. #define \
  275. NatDereferenceMapping( \
  276. _Mapping \
  277. ) \
  278. (InterlockedDecrement(&(_Mapping)->ReferenceCount) \
  279. ? TRUE \
  280. : (NatCleanupMapping(_Mapping), FALSE))
  281. //
  282. // VOID
  283. // NatExpireMapping(
  284. // PNAT_DYNAMIC_MAPPING Mapping
  285. // );
  286. //
  287. PNAT_DYNAMIC_MAPPING
  288. NatDestinationLookupForwardMapping(
  289. ULONG64 DestinationKey
  290. );
  291. PNAT_DYNAMIC_MAPPING
  292. NatDestinationLookupReverseMapping(
  293. ULONG64 DestinationKey
  294. );
  295. #define \
  296. NatExpireMapping( \
  297. _Mapping \
  298. ) \
  299. if (!NAT_MAPPING_EXPIRED(_Mapping)) { \
  300. (_Mapping)->Flags |= NAT_MAPPING_FLAG_EXPIRED; \
  301. InterlockedIncrement(&ExpiredMappingCount); \
  302. if (MappingCount > MAPPING_CLEANUP_THRESHOLD && \
  303. ExpiredMappingCount >= (MappingCount >> 2)) { \
  304. NatTriggerTimer(); \
  305. } \
  306. }
  307. VOID
  308. NatInitializeMappingManagement(
  309. VOID
  310. );
  311. PNAT_DYNAMIC_MAPPING
  312. NatInsertForwardMapping(
  313. PNAT_DYNAMIC_MAPPING Parent,
  314. PNAT_DYNAMIC_MAPPING Mapping
  315. );
  316. PNAT_DYNAMIC_MAPPING
  317. NatInsertReverseMapping(
  318. PNAT_DYNAMIC_MAPPING Parent,
  319. PNAT_DYNAMIC_MAPPING Mapping
  320. );
  321. PNAT_DYNAMIC_MAPPING
  322. NatSourceInsertForwardMapping(
  323. PNAT_DYNAMIC_MAPPING Parent,
  324. PNAT_DYNAMIC_MAPPING Mapping
  325. );
  326. PNAT_DYNAMIC_MAPPING
  327. NatSourceInsertReverseMapping(
  328. PNAT_DYNAMIC_MAPPING Parent,
  329. PNAT_DYNAMIC_MAPPING Mapping
  330. );
  331. NTSTATUS
  332. NatLookupAndQueryInformationMapping(
  333. UCHAR Protocol,
  334. ULONG DestinationAddress,
  335. USHORT DestinationPort,
  336. ULONG SourceAddress,
  337. USHORT SourcePort,
  338. OUT PVOID Information,
  339. ULONG InformationLength,
  340. NAT_SESSION_MAPPING_INFORMATION_CLASS InformationClass
  341. );
  342. PNAT_DYNAMIC_MAPPING
  343. NatLookupForwardMapping(
  344. ULONG64 DestinationKey,
  345. ULONG64 SourceKey,
  346. PNAT_DYNAMIC_MAPPING* InsertionPoint
  347. );
  348. PNAT_DYNAMIC_MAPPING
  349. NatLookupReverseMapping(
  350. ULONG64 DestinationKey,
  351. ULONG64 SourceKey,
  352. PNAT_DYNAMIC_MAPPING* InsertionPoint
  353. );
  354. VOID
  355. NatQueryInformationMapping(
  356. IN PNAT_DYNAMIC_MAPPING Mapping,
  357. OUT PUCHAR Protocol OPTIONAL,
  358. OUT PULONG PrivateAddress OPTIONAL,
  359. OUT PUSHORT PrivatePort OPTIONAL,
  360. OUT PULONG RemoteAddress OPTIONAL,
  361. OUT PUSHORT RemotePort OPTIONAL,
  362. OUT PULONG PublicAddress OPTIONAL,
  363. OUT PUSHORT PublicPort OPTIONAL,
  364. OUT PIP_NAT_SESSION_MAPPING_STATISTICS Statistics OPTIONAL
  365. );
  366. NTSTATUS
  367. NatQueryInterfaceMappingTable(
  368. IN PIP_NAT_ENUMERATE_SESSION_MAPPINGS InputBuffer,
  369. IN PIP_NAT_ENUMERATE_SESSION_MAPPINGS OutputBuffer,
  370. IN PULONG OutputBufferLength
  371. );
  372. NTSTATUS
  373. NatQueryMappingTable(
  374. IN PIP_NAT_ENUMERATE_SESSION_MAPPINGS InputBuffer,
  375. IN PIP_NAT_ENUMERATE_SESSION_MAPPINGS OutputBuffer,
  376. IN PULONG OutputBufferLength
  377. );
  378. //
  379. // BOOLEAN
  380. // NatReferenceMapping(
  381. // PNAT_DYNAMIC_MAPPING Mapping
  382. // );
  383. //
  384. #define \
  385. NatReferenceMapping( \
  386. _Mapping \
  387. ) \
  388. (NAT_MAPPING_DELETED(_Mapping) \
  389. ? FALSE \
  390. : (InterlockedIncrement(&(_Mapping)->ReferenceCount), TRUE))
  391. //
  392. // VOID
  393. // NatResplayMapping(
  394. // PNAT_DYNAMIC_MAPPING Mapping,
  395. // IP_NAT_PATH Path
  396. // );
  397. //
  398. #define \
  399. NatResplayMapping( \
  400. _Mapping, \
  401. _Path \
  402. ) \
  403. { \
  404. PRTL_SPLAY_LINKS _SLink; \
  405. KeAcquireSpinLockAtDpcLevel(&MappingLock); \
  406. if (!NAT_MAPPING_DELETED(_Mapping)) { \
  407. _SLink = RtlSplay(&(_Mapping)->SLink[_Path]); \
  408. MappingTree[_Path] = \
  409. CONTAINING_RECORD(_SLink, NAT_DYNAMIC_MAPPING, SLink[_Path]); \
  410. } \
  411. KeReleaseSpinLockFromDpcLevel(&MappingLock); \
  412. }
  413. VOID
  414. NatShutdownMappingManagement(
  415. VOID
  416. );
  417. PNAT_DYNAMIC_MAPPING
  418. NatSourceLookupForwardMapping(
  419. ULONG64 SourceKey,
  420. PNAT_DYNAMIC_MAPPING* InsertionPoint
  421. );
  422. PNAT_DYNAMIC_MAPPING
  423. NatSourceLookupReverseMapping(
  424. ULONG64 SourceKey,
  425. PNAT_DYNAMIC_MAPPING* InsertionPoint
  426. );
  427. //
  428. // VOID
  429. // NatTryToResplayMapping(
  430. // PNAT_DYNAMIC_MAPPING Mapping,
  431. // IP_NAT_PATH Path
  432. // );
  433. //
  434. #define \
  435. NatTryToResplayMapping( \
  436. _Mapping, \
  437. _Path \
  438. ) \
  439. if (InterlockedDecrement(&(_Mapping)->AccessCount[(_Path)]) == 0) { \
  440. NatResplayMapping((_Mapping), (_Path)); \
  441. InterlockedExchangeAdd( \
  442. &(_Mapping)->AccessCount[(_Path)], \
  443. NAT_MAPPING_RESPLAY_THRESHOLD \
  444. ); \
  445. }
  446. VOID
  447. NatUpdateStatisticsMapping(
  448. PNAT_DYNAMIC_MAPPING Mapping
  449. );
  450. #undef PNAT_INTERFACE
  451. #endif // _NAT_MAPPING_H_