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.

1992 lines
56 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. xlate.h
  5. Abstract:
  6. This file contains the code for the translation-routines used for
  7. mappings.
  8. The forward routines have the exact same logic as the reverse routines.
  9. However, for reasons of efficiency the two are separate routines,
  10. to avoid the cost of indexing on 'NAT_PATH' for every packet
  11. processed.
  12. To avoid duplicating the code, then, this header file consolidates the code
  13. in one location. This file is included twice in XLATE.C, and before each
  14. inclusion, either 'XLATE_FORWARD' or 'XLATE_REVERSE' is defined.
  15. This causes the compiler to generate the code for separate functions,
  16. as desired, while avoiding the unpleasantness of code-duplication.
  17. The translation routines are as follows:
  18. NatTranslate?Tcp - no editor for either direction
  19. NatTranslate?Udp - no editor for either direction
  20. NatTranslate?TcpEdit - an editor for at least one direction
  21. NatTranslate?UdpEdit - an editor for the given direction
  22. NatTranslate?TcpResize - a resizing editor for at least one direction
  23. Each routine is invoked from 'NatTranslatePacket' at dispatch level
  24. with no locks held and with a reference acquired for the mapping.
  25. Author:
  26. Abolade Gbadegesin (t-abolag) July-30-1997
  27. Revision History:
  28. Abolade Gbadegesin (aboladeg) July-15-1997
  29. Reworked to deal with a global splay-tree of mappings, rather than
  30. a per-interface splay-tree.
  31. --*/
  32. #ifndef XLATE_CODE // Just provide declarations.
  33. //
  34. // Structure: NAT_CACHED_ROUTE
  35. //
  36. // This structure holds information for a cached route.
  37. //
  38. typedef struct _NAT_CACHED_ROUTE {
  39. ULONG DestinationAddress;
  40. ULONG Index;
  41. } NAT_CACHED_ROUTE, *PNAT_CACHED_ROUTE;
  42. //
  43. // Structure: NAT_XLATE_CONTEXT
  44. //
  45. // This structure holds context-information for a packet as it is passed thru
  46. // the translation code. This context is passed to the translation routines,
  47. // and handed to 'NatEditorEditSession' when it is invoked by an editor to
  48. // make changes to the packet.
  49. //
  50. // Included are the original IP header, the checksum-delta to be updated if
  51. // an editor makes any changes to the packet, and the TCP sequence number delta
  52. // to be set if an editor resizes a TCP segment.
  53. //
  54. typedef struct _NAT_XLATE_CONTEXT {
  55. IPRcvBuf* RecvBuffer;
  56. PIP_HEADER Header;
  57. PUCHAR DestinationType;
  58. ULONG SourceAddress;
  59. ULONG DestinationAddress;
  60. IPRcvBuf* ProtocolRecvBuffer;
  61. PUCHAR ProtocolHeader;
  62. ULONG ProtocolDataOffset;
  63. ULONG Flags;
  64. PULONG ChecksumDelta;
  65. LONG TcpSeqNumDelta;
  66. BOOLEAN ChecksumOffloaded;
  67. } NAT_XLATE_CONTEXT, *PNAT_XLATE_CONTEXT;
  68. //
  69. // Definitions of flags for the field NAT_XLATE_CONTEXT.Flags
  70. //
  71. #define NAT_XLATE_FLAG_EDITED 0x00000001
  72. #define NAT_XLATE_EDITED(h) ((h)->Flags & NAT_XLATE_FLAG_EDITED)
  73. #define NAT_XLATE_FLAG_LOOPBACK 0x00000002
  74. #define NAT_XLATE_LOOPBACK(h) ((h)->Flags & NAT_XLATE_FLAG_LOOPBACK)
  75. #if NAT_WMI
  76. #define NAT_XLATE_FLAG_LOGGED 0x00000004
  77. #define NAT_XLATE_LOGGED(h) ((h)->Flags & NAT_XLATE_FLAG_LOGGED)
  78. #endif
  79. //
  80. // Inline routine to initialize a translation context
  81. // given appropriate arguments.
  82. //
  83. #define \
  84. NAT_BUILD_XLATE_CONTEXT( \
  85. _Context, \
  86. _Header, \
  87. _DestinationType, \
  88. _RecvBuffer, \
  89. _SourceAddress, \
  90. _DestinationAddress \
  91. ) \
  92. (_Context)->Header = (PIP_HEADER)_Header; \
  93. (_Context)->DestinationType = _DestinationType; \
  94. (_Context)->RecvBuffer = (_RecvBuffer); \
  95. (_Context)->SourceAddress = _SourceAddress; \
  96. (_Context)->DestinationAddress = _DestinationAddress; \
  97. (_Context)->ChecksumOffloaded = \
  98. ((_RecvBuffer)->ipr_flags & IPR_FLAG_CHECKSUM_OFFLOAD) \
  99. == IPR_FLAG_CHECKSUM_OFFLOAD; \
  100. if ((_RecvBuffer)->ipr_size == (ULONG)IP_DATA_OFFSET(_Header)) {\
  101. if ((_Context)->ProtocolRecvBuffer = (_RecvBuffer)->ipr_next) { \
  102. (_Context)->ProtocolHeader = (_RecvBuffer)->ipr_next->ipr_buffer; \
  103. } \
  104. } \
  105. else if (IP_DATA_OFFSET(_Header) < (_RecvBuffer)->ipr_size) { \
  106. (_Context)->ProtocolRecvBuffer = (_RecvBuffer); \
  107. (_Context)->ProtocolHeader = \
  108. (_RecvBuffer)->ipr_buffer + IP_DATA_OFFSET(_Header); \
  109. } else { \
  110. (_Context)->ProtocolRecvBuffer = NULL; \
  111. (_Context)->ProtocolHeader = NULL; \
  112. } \
  113. if ((_Context)->ProtocolHeader) { \
  114. UINT ProtocolHeaderSize = 0; \
  115. UINT HeaderSize = \
  116. (_Context)->ProtocolRecvBuffer->ipr_size \
  117. - (UINT) ((_Context)->ProtocolHeader \
  118. - (_Context)->ProtocolRecvBuffer->ipr_buffer); \
  119. switch ((_Context)->Header->Protocol) { \
  120. case NAT_PROTOCOL_TCP: { \
  121. ProtocolHeaderSize = sizeof(TCP_HEADER); \
  122. break; \
  123. } \
  124. case NAT_PROTOCOL_UDP: { \
  125. ProtocolHeaderSize = sizeof(UDP_HEADER); \
  126. break; \
  127. } \
  128. case NAT_PROTOCOL_ICMP: { \
  129. ProtocolHeaderSize = \
  130. FIELD_OFFSET(ICMP_HEADER, EncapsulatedIpHeader); \
  131. break; \
  132. } \
  133. case NAT_PROTOCOL_PPTP: { \
  134. ProtocolHeaderSize = sizeof(GRE_HEADER); \
  135. break; \
  136. } \
  137. } \
  138. if (HeaderSize < ProtocolHeaderSize) { \
  139. (_Context)->ProtocolRecvBuffer = NULL; \
  140. (_Context)->ProtocolHeader = NULL; \
  141. } \
  142. }
  143. //
  144. // Checksum manipulation macros
  145. //
  146. //
  147. // Fold carry-bits of a checksum into the low-order word
  148. //
  149. #define CHECKSUM_FOLD(xsum) \
  150. (xsum) = (USHORT)(xsum) + ((xsum) >> 16); \
  151. (xsum) += ((xsum) >> 16)
  152. //
  153. // Sum the words of a 32-bit value into a checksum
  154. //
  155. #define CHECKSUM_LONG(xsum,l) \
  156. (xsum) += (USHORT)(l) + (USHORT)((l) >> 16)
  157. //
  158. // Transfer a checksum to or from the negated format sent on the network
  159. //
  160. #define CHECKSUM_XFER(dst,src) \
  161. (dst) = (USHORT)~(src)
  162. //
  163. // Update the checksum field 'x' using standard variables 'Checksum' and
  164. // 'ChecksumDelta'
  165. //
  166. #define CHECKSUM_UPDATE(x) \
  167. CHECKSUM_XFER(Checksum, (x)); \
  168. Checksum += ChecksumDelta; \
  169. CHECKSUM_FOLD(Checksum); \
  170. CHECKSUM_XFER((x), Checksum)
  171. //
  172. // Checksum computation routines (inlined)
  173. //
  174. __forceinline
  175. VOID
  176. NatComputeIpChecksum(
  177. PIP_HEADER IpHeader
  178. )
  179. /*++
  180. Routine Description:
  181. Computes the IP Checksum for a packet, and places that checksum
  182. into the packet header.
  183. Arguments:
  184. IpHeader - pointer to the IP header for which the checksum is to
  185. be computed. The checksum field of this header will be modified.
  186. Return Value:
  187. None.
  188. --*/
  189. {
  190. ULONG IpChecksum;
  191. IpHeader->Checksum = 0;
  192. IpChecksum =
  193. tcpxsum(
  194. 0,
  195. (PUCHAR)IpHeader,
  196. IP_DATA_OFFSET(IpHeader)
  197. );
  198. CHECKSUM_FOLD(IpChecksum);
  199. CHECKSUM_XFER(IpHeader->Checksum, IpChecksum);
  200. } // NatComputeIpChecksum
  201. __forceinline
  202. VOID
  203. NatComputeTcpChecksum(
  204. PIP_HEADER IpHeader,
  205. PTCP_HEADER TcpHeader,
  206. IPRcvBuf *TcpRcvBuffer
  207. )
  208. /*++
  209. Routine Description:
  210. Computes the TCP checksum for a packet, and places that checksum
  211. into the TCP header.
  212. Arguments:
  213. IpHeader - pointer to the IP header for the packet.
  214. TcpHeader - pointer to the TCP for the packet. The checksum field
  215. in this header will be modified.
  216. TcpRcvBuffer - the IPRcvBuf containing the TCP header.
  217. Return Value:
  218. None.
  219. --*/
  220. {
  221. ULONG TcpChecksum;
  222. IPRcvBuf* Temp;
  223. TcpChecksum = NTOHS(IpHeader->TotalLength);
  224. TcpChecksum -= IP_DATA_OFFSET(IpHeader);
  225. TcpChecksum = NTOHS(TcpChecksum);
  226. CHECKSUM_LONG(TcpChecksum, IpHeader->SourceAddress);
  227. CHECKSUM_LONG(TcpChecksum, IpHeader->DestinationAddress);
  228. TcpChecksum += (NAT_PROTOCOL_TCP << 8);
  229. TcpHeader->Checksum = 0;
  230. TcpChecksum +=
  231. tcpxsum(
  232. 0,
  233. (PUCHAR)TcpHeader,
  234. TcpRcvBuffer->ipr_size -
  235. (ULONG)((PUCHAR)TcpHeader - TcpRcvBuffer->ipr_buffer)
  236. );
  237. for (Temp = TcpRcvBuffer->ipr_next;
  238. Temp;
  239. Temp = Temp->ipr_next
  240. ) {
  241. TcpChecksum +=
  242. tcpxsum(
  243. 0,
  244. Temp->ipr_buffer,
  245. Temp->ipr_size
  246. );
  247. }
  248. CHECKSUM_FOLD(TcpChecksum);
  249. CHECKSUM_XFER(TcpHeader->Checksum, TcpChecksum);
  250. } // NatComputeTcpChecksum
  251. __forceinline
  252. VOID
  253. NatComputeUdpChecksum(
  254. PIP_HEADER IpHeader,
  255. PUDP_HEADER UdpHeader,
  256. IPRcvBuf *UdpRcvBuffer
  257. )
  258. /*++
  259. Routine Description:
  260. Computes the UDP checksum for a packet, and places that checksum
  261. into the UDP header.
  262. Arguments:
  263. IpHeader - pointer to the IP header for the packet.
  264. UdpHeader - pointer to the UDP for the packet. The checksum field
  265. in this header will be modified.
  266. UdpRcvBuffer - the IPRcvBuf containing the UDP header.
  267. Return Value:
  268. None.
  269. --*/
  270. {
  271. ULONG UdpChecksum;
  272. IPRcvBuf* Temp;
  273. UdpChecksum = UdpHeader->Length;
  274. CHECKSUM_LONG(UdpChecksum, IpHeader->SourceAddress);
  275. CHECKSUM_LONG(UdpChecksum, IpHeader->DestinationAddress);
  276. UdpChecksum += (NAT_PROTOCOL_UDP << 8);
  277. UdpHeader->Checksum = 0;
  278. UdpChecksum +=
  279. tcpxsum(
  280. 0,
  281. (PUCHAR)UdpHeader,
  282. UdpRcvBuffer->ipr_size -
  283. (ULONG)((PUCHAR)UdpHeader - UdpRcvBuffer->ipr_buffer)
  284. );
  285. for (Temp = UdpRcvBuffer->ipr_next;
  286. Temp;
  287. Temp = Temp->ipr_next
  288. ) {
  289. UdpChecksum +=
  290. tcpxsum(
  291. 0,
  292. Temp->ipr_buffer,
  293. Temp->ipr_size
  294. );
  295. }
  296. CHECKSUM_FOLD(UdpChecksum);
  297. CHECKSUM_XFER(UdpHeader->Checksum, UdpChecksum);
  298. } // NatComputeUdpChecksum
  299. //
  300. // Forward declarations of structures defined elsewhere.
  301. //
  302. struct _NAT_INTERFACE;
  303. #define PNAT_INTERFACE struct _NAT_INTERFACE*
  304. struct _NAT_DYNAMIC_MAPPING;
  305. #define PNAT_DYNAMIC_MAPPING struct _NAT_DYNAMIC_MAPPING*
  306. //
  307. // Functional signature macro
  308. //
  309. #define XLATE_ROUTINE(Name) \
  310. FORWARD_ACTION \
  311. Name( \
  312. PNAT_DYNAMIC_MAPPING Mapping, \
  313. PNAT_XLATE_CONTEXT Contextp, \
  314. IPRcvBuf** InReceiveBuffer, \
  315. IPRcvBuf** OutReceiveBuffer \
  316. );
  317. //
  318. // Prototype: PNAT_TRANSLATE_ROUTINE
  319. //
  320. // This is the prototype for the routines which handle translation for
  321. // different classes of sessions. Each mapping's 'TranslateRoutine' field
  322. // is initialized with a pointer to such a routine.
  323. //
  324. // This allows us to take advantage of our foreknowledge about sessions.
  325. // For instance, a TCP connection which has no editor registered will never
  326. // have to take the editor-lock, and can skip the check for an editor.
  327. // Similarly, a TCP connection whose editor never resizes a packet does not
  328. // need to ever adjust sequence numbers.
  329. //
  330. typedef XLATE_ROUTINE((FASTCALL*PNAT_TRANSLATE_ROUTINE))
  331. XLATE_ROUTINE(FASTCALL NatTranslateForwardTcp)
  332. XLATE_ROUTINE(FASTCALL NatTranslateReverseTcp)
  333. XLATE_ROUTINE(FASTCALL NatTranslateForwardUdp)
  334. XLATE_ROUTINE(FASTCALL NatTranslateReverseUdp)
  335. XLATE_ROUTINE(FASTCALL NatTranslateForwardTcpEdit)
  336. XLATE_ROUTINE(FASTCALL NatTranslateReverseTcpEdit)
  337. XLATE_ROUTINE(FASTCALL NatTranslateForwardUdpEdit)
  338. XLATE_ROUTINE(FASTCALL NatTranslateReverseUdpEdit)
  339. XLATE_ROUTINE(FASTCALL NatTranslateForwardTcpResize)
  340. XLATE_ROUTINE(FASTCALL NatTranslateReverseTcpResize)
  341. //
  342. // NatTranslate?Null is used for firewall-only mappings (i.e., mappings that
  343. // don't perform any actual translation). These routines never have to modify
  344. // any of the packet data; they only update the bookkeeping...
  345. //
  346. XLATE_ROUTINE(FASTCALL NatTranslateForwardTcpNull)
  347. XLATE_ROUTINE(FASTCALL NatTranslateReverseTcpNull)
  348. XLATE_ROUTINE(FASTCALL NatTranslateForwardUdpNull)
  349. XLATE_ROUTINE(FASTCALL NatTranslateReverseUdpNull)
  350. //
  351. // Functional signature macro
  352. //
  353. #define XLATE_IP_ROUTINE(Name) \
  354. FORWARD_ACTION \
  355. Name( \
  356. PNAT_INTERFACE Interfacep OPTIONAL, \
  357. IP_NAT_DIRECTION Direction, \
  358. PNAT_XLATE_CONTEXT Contextp, \
  359. IPRcvBuf** InRecvBuffer, \
  360. IPRcvBuf** OutRecvBuffer \
  361. );
  362. //
  363. // Prototype: PNAT_IP_TRANSLATE_ROUTINE
  364. //
  365. // This is the prototype for the routines which handle translation for
  366. // protocols other than TCP and UDP, i.e. for IP-layer protocols.
  367. //
  368. // All such routines are responsible for updating the IP header checksum,
  369. // and updating 'InRecvBuffer' and 'OutRecvBuffer' in the event of any change
  370. // to the packet being processed.
  371. //
  372. typedef XLATE_IP_ROUTINE((*PNAT_IP_TRANSLATE_ROUTINE))
  373. //
  374. // Prototype: Nat?TCPStateCheck
  375. //
  376. // These routines are used in FW mode to protect against various forms of
  377. // constructed packets (e.g., SYN/FIN).
  378. //
  379. void
  380. FASTCALL
  381. NatAdjustMSSOption(
  382. PNAT_XLATE_CONTEXT Contextp,
  383. USHORT maxMSS
  384. );
  385. FORWARD_ACTION
  386. NatForwardTcpStateCheck(
  387. PNAT_DYNAMIC_MAPPING pMapping,
  388. PTCP_HEADER pTcpHeader
  389. );
  390. FORWARD_ACTION
  391. NatReverseTcpStateCheck(
  392. PNAT_DYNAMIC_MAPPING pMapping,
  393. PTCP_HEADER pTcpHeader
  394. );
  395. #undef PNAT_INTERFACE
  396. #undef PNAT_DYNAMIC_MAPPING
  397. PNAT_IP_TRANSLATE_ROUTINE TranslateRoutineTable[256];
  398. //
  399. // FUNCTION PROTOTYPES
  400. //
  401. VOID
  402. NatInitializePacketManagement(
  403. VOID
  404. );
  405. VOID
  406. NatShutdownPacketManagement(
  407. VOID
  408. );
  409. FORWARD_ACTION
  410. NatTranslatePacket(
  411. IPRcvBuf** InReceiveBuffer,
  412. ULONG ReceiveAdapterIndex,
  413. PULONG SendAdapterIndex,
  414. PUCHAR DestinationType,
  415. PVOID Unused,
  416. ULONG UnusedLength,
  417. IPRcvBuf** OutReceiveBuffer
  418. );
  419. #else // XLATE_CODE
  420. //
  421. // Produce code for the protocol-layer translation routines.
  422. // Produce forward-routines if 'XLATE_FORWARD' is defined,
  423. // and reverse routines otherwise.
  424. //
  425. #ifdef XLATE_FORWARD
  426. #define XLATE_POSITIVE NatForwardPath
  427. #define XLATE_NEGATIVE NatReversePath
  428. #define NAT_TRANSLATE_TCP NatTranslateForwardTcp
  429. #define NAT_TRANSLATE_UDP NatTranslateForwardUdp
  430. #define NAT_TRANSLATE_TCP_EDIT NatTranslateForwardTcpEdit
  431. #define NAT_TRANSLATE_UDP_EDIT NatTranslateForwardUdpEdit
  432. #define NAT_TRANSLATE_TCP_RESIZE NatTranslateForwardTcpResize
  433. #define NAT_TRANSLATE_TCP_NULL NatTranslateForwardTcpNull
  434. #define NAT_TRANSLATE_UDP_NULL NatTranslateForwardUdpNull
  435. #define NAT_TRANSLATE_SYN NAT_MAPPING_FLAG_FWD_SYN
  436. #define NAT_TRANSLATE_FIN NAT_MAPPING_FLAG_FWD_FIN
  437. #define NAT_TRANSLATE_TCP_STATE_CHECK NatForwardTcpStateCheck
  438. #define DATA_HANDLER ForwardDataHandler
  439. #define BYTE_COUNT BytesForward
  440. #define PACKET_COUNT PacketsForward
  441. #define REJECT_COUNT RejectsForward
  442. #define NAT_TRANSLATE_HEADER() \
  443. Contextp->Header->DestinationAddress = \
  444. MAPPING_ADDRESS(Mapping->SourceKey[NatReversePath]); \
  445. ((PUSHORT)Contextp->ProtocolHeader)[1] = \
  446. MAPPING_PORT(Mapping->SourceKey[NatReversePath]); \
  447. Contextp->Header->SourceAddress = \
  448. MAPPING_ADDRESS(Mapping->DestinationKey[NatReversePath]); \
  449. ((PUSHORT)Contextp->ProtocolHeader)[0] = \
  450. MAPPING_PORT(Mapping->DestinationKey[NatReversePath])
  451. #define NAT_DROP_IF_UNIDIRECTIONAL()
  452. #else
  453. #define XLATE_POSITIVE NatReversePath
  454. #define XLATE_NEGATIVE NatForwardPath
  455. #define NAT_TRANSLATE_TCP NatTranslateReverseTcp
  456. #define NAT_TRANSLATE_UDP NatTranslateReverseUdp
  457. #define NAT_TRANSLATE_TCP_EDIT NatTranslateReverseTcpEdit
  458. #define NAT_TRANSLATE_UDP_EDIT NatTranslateReverseUdpEdit
  459. #define NAT_TRANSLATE_TCP_RESIZE NatTranslateReverseTcpResize
  460. #define NAT_TRANSLATE_TCP_NULL NatTranslateReverseTcpNull
  461. #define NAT_TRANSLATE_UDP_NULL NatTranslateReverseUdpNull
  462. #define NAT_TRANSLATE_SYN NAT_MAPPING_FLAG_REV_SYN
  463. #define NAT_TRANSLATE_FIN NAT_MAPPING_FLAG_REV_FIN
  464. #define NAT_TRANSLATE_TCP_STATE_CHECK NatReverseTcpStateCheck
  465. #define DATA_HANDLER ReverseDataHandler
  466. #define BYTE_COUNT BytesReverse
  467. #define PACKET_COUNT PacketsReverse
  468. #define REJECT_COUNT RejectsReverse
  469. #define NAT_TRANSLATE_HEADER() \
  470. Contextp->Header->DestinationAddress = \
  471. MAPPING_ADDRESS(Mapping->SourceKey[NatForwardPath]); \
  472. ((PUSHORT)Contextp->ProtocolHeader)[1] = \
  473. MAPPING_PORT(Mapping->SourceKey[NatForwardPath]); \
  474. Contextp->Header->SourceAddress = \
  475. MAPPING_ADDRESS(Mapping->DestinationKey[NatForwardPath]); \
  476. ((PUSHORT)Contextp->ProtocolHeader)[0] = \
  477. MAPPING_PORT(Mapping->DestinationKey[NatForwardPath])
  478. #define NAT_DROP_IF_UNIDIRECTIONAL() \
  479. if (NAT_MAPPING_UNIDIRECTIONAL(Mapping)) { return DROP; }
  480. #endif
  481. FORWARD_ACTION
  482. FASTCALL
  483. NAT_TRANSLATE_TCP(
  484. PNAT_DYNAMIC_MAPPING Mapping,
  485. PNAT_XLATE_CONTEXT Contextp,
  486. IPRcvBuf** InReceiveBuffer,
  487. IPRcvBuf** OutReceiveBuffer
  488. )
  489. {
  490. ULONG IpChecksumDelta;
  491. PIP_HEADER IpHeader = Contextp->Header;
  492. ULONG ProtocolChecksumDelta;
  493. PRTL_SPLAY_LINKS SLink;
  494. PTCP_HEADER TcpHeader = (PTCP_HEADER)Contextp->ProtocolHeader;
  495. //
  496. // We know we will make changes to the buffer-chain,
  497. // so move the head of the list to 'OutReceiveBuffer'.
  498. //
  499. *OutReceiveBuffer = *InReceiveBuffer; *InReceiveBuffer = NULL;
  500. //
  501. // Update the IP and protocol headers with the translated address/port
  502. //
  503. NAT_TRANSLATE_HEADER();
  504. if (!Contextp->ChecksumOffloaded) {
  505. //
  506. // Now add the checksum-delta incurred by changes to the IP header
  507. //
  508. CHECKSUM_XFER(IpChecksumDelta, IpHeader->Checksum);
  509. CHECKSUM_XFER(
  510. ProtocolChecksumDelta,
  511. ((PTCP_HEADER)Contextp->ProtocolHeader)->Checksum
  512. );
  513. IpChecksumDelta += Mapping->IpChecksumDelta[XLATE_POSITIVE];
  514. CHECKSUM_FOLD(IpChecksumDelta);
  515. CHECKSUM_XFER(IpHeader->Checksum, IpChecksumDelta);
  516. ProtocolChecksumDelta += Mapping->ProtocolChecksumDelta[XLATE_POSITIVE];
  517. CHECKSUM_FOLD(ProtocolChecksumDelta);
  518. CHECKSUM_XFER(
  519. ((PTCP_HEADER)Contextp->ProtocolHeader)->Checksum,
  520. ProtocolChecksumDelta
  521. );
  522. } else {
  523. //
  524. // Compute the IP and TCP checksums
  525. //
  526. NatComputeIpChecksum(IpHeader);
  527. NatComputeTcpChecksum(
  528. IpHeader,
  529. (PTCP_HEADER)Contextp->ProtocolHeader,
  530. Contextp->ProtocolRecvBuffer
  531. );
  532. }
  533. if (NAT_MAPPING_CLEAR_DF_BIT(Mapping) &&
  534. (IpHeader->OffsetAndFlags & IP_DF_FLAG)) {
  535. //
  536. // Clear the DF bit from this packet and adjust the IP
  537. // checksum accordingly.
  538. //
  539. IpHeader->OffsetAndFlags &= ~IP_DF_FLAG;
  540. CHECKSUM_XFER(IpChecksumDelta, IpHeader->Checksum);
  541. IpChecksumDelta += ~IP_DF_FLAG;
  542. CHECKSUM_FOLD(IpChecksumDelta);
  543. CHECKSUM_XFER(IpHeader->Checksum, IpChecksumDelta);
  544. }
  545. //
  546. // Check if need to adjust MSS options in TCP SYNs
  547. //
  548. if (TCP_FLAG(TcpHeader, SYN) && (Mapping->MaxMSS > 0)) {
  549. NatAdjustMSSOption(Contextp, Mapping->MaxMSS);
  550. }
  551. KeAcquireSpinLockAtDpcLevel(&Mapping->Lock);
  552. //
  553. // Perform state validation for inbound mappings.
  554. //
  555. if (NAT_MAPPING_INBOUND(Mapping)
  556. && DROP == NAT_TRANSLATE_TCP_STATE_CHECK(
  557. Mapping,
  558. TcpHeader
  559. )) {
  560. KeReleaseSpinLockFromDpcLevel(&Mapping->Lock);
  561. return DROP;
  562. } else if (TCP_FLAG(TcpHeader, SYN)) {
  563. //
  564. // Record that we've seen a SYN in this direction
  565. //
  566. Mapping->Flags |= NAT_TRANSLATE_SYN;
  567. }
  568. //
  569. // Now we need to update the connection state for the sender
  570. // based on the flags in the packet:
  571. //
  572. // When a RST is seen, we close both ends of the connection.
  573. // As each FIN is seen, we mark the mapping appropriately.
  574. // When both FINs have been seen, we mark the mapping for deletion.
  575. //
  576. if (TCP_FLAG(((PTCP_HEADER)Contextp->ProtocolHeader), RST)) {
  577. NatExpireMapping(Mapping);
  578. }
  579. else
  580. if (TCP_FLAG(((PTCP_HEADER)Contextp->ProtocolHeader), FIN)) {
  581. Mapping->Flags |= NAT_TRANSLATE_FIN;
  582. if (NAT_MAPPING_FIN(Mapping)) {
  583. NatExpireMapping(Mapping);
  584. }
  585. }
  586. //
  587. // Update the mapping's timestamp and statistics
  588. //
  589. KeQueryTickCount((PLARGE_INTEGER)&Mapping->LastAccessTime);
  590. KeReleaseSpinLockFromDpcLevel(&Mapping->Lock);
  591. InterlockedExchangeAdd(
  592. &Mapping->BYTE_COUNT,
  593. NTOHS(IpHeader->TotalLength) -
  594. IP_DATA_OFFSET(IpHeader) -
  595. TCP_DATA_OFFSET(((PTCP_HEADER)Contextp->ProtocolHeader))
  596. );
  597. InterlockedIncrement(&Mapping->PACKET_COUNT);
  598. //
  599. // Resplay the mapping (periodically), and indicate the change
  600. // by invalidating 'DestinationType'
  601. //
  602. NatTryToResplayMapping(Mapping, XLATE_POSITIVE);
  603. *Contextp->DestinationType = DEST_INVALID;
  604. return FORWARD;
  605. } // NAT_TRANSLATE_TCP
  606. FORWARD_ACTION
  607. FASTCALL
  608. NAT_TRANSLATE_UDP(
  609. PNAT_DYNAMIC_MAPPING Mapping,
  610. PNAT_XLATE_CONTEXT Contextp,
  611. IPRcvBuf** InReceiveBuffer,
  612. IPRcvBuf** OutReceiveBuffer
  613. )
  614. {
  615. ULONG IpChecksumDelta;
  616. PIP_HEADER IpHeader = Contextp->Header;
  617. ULONG ProtocolChecksumDelta;
  618. PRTL_SPLAY_LINKS SLink;
  619. PUDP_HEADER UdpHeader = (PUDP_HEADER)Contextp->ProtocolHeader;
  620. BOOLEAN UpdateXsum;
  621. //
  622. // We know we will make changes to the buffer-chain,
  623. // so move the head of the list to 'OutReceiveBuffer'.
  624. //
  625. *OutReceiveBuffer = *InReceiveBuffer; *InReceiveBuffer = NULL;
  626. //
  627. // Unidirectional flows require that reverse packets be dropped;
  628. // This is primarily to support H.323 proxy.
  629. //
  630. NAT_DROP_IF_UNIDIRECTIONAL();
  631. //
  632. // We have to handle the fact that the UDP checksum is optional;
  633. // if the checksum in the header is zero, then no checksum was sent
  634. // and we will make no changes to the field.
  635. //
  636. CHECKSUM_XFER(IpChecksumDelta, IpHeader->Checksum);
  637. if (!UdpHeader->Checksum) {
  638. UpdateXsum = FALSE;
  639. }
  640. else {
  641. UpdateXsum = TRUE;
  642. CHECKSUM_XFER(ProtocolChecksumDelta, UdpHeader->Checksum);
  643. }
  644. //
  645. // Update the IP and protocol headers with the translated address/port
  646. //
  647. NAT_TRANSLATE_HEADER();
  648. if (!Contextp->ChecksumOffloaded) {
  649. //
  650. // Update the checksums
  651. //
  652. IpChecksumDelta += Mapping->IpChecksumDelta[XLATE_POSITIVE];
  653. CHECKSUM_FOLD(IpChecksumDelta);
  654. CHECKSUM_XFER(IpHeader->Checksum, IpChecksumDelta);
  655. if (UpdateXsum) {
  656. ProtocolChecksumDelta += Mapping->ProtocolChecksumDelta[XLATE_POSITIVE];
  657. CHECKSUM_FOLD(ProtocolChecksumDelta);
  658. CHECKSUM_XFER(UdpHeader->Checksum, ProtocolChecksumDelta);
  659. }
  660. } else {
  661. //
  662. // Compute the IP and (optionally) UDP checksums
  663. //
  664. NatComputeIpChecksum(IpHeader);
  665. if (UpdateXsum) {
  666. NatComputeUdpChecksum(
  667. IpHeader,
  668. (PUDP_HEADER)Contextp->ProtocolHeader,
  669. Contextp->ProtocolRecvBuffer
  670. );
  671. }
  672. }
  673. if (NAT_MAPPING_CLEAR_DF_BIT(Mapping) &&
  674. (IpHeader->OffsetAndFlags & IP_DF_FLAG)) {
  675. //
  676. // Clear the DF bit from this packet and adjust the IP
  677. // checksum accordingly.
  678. //
  679. IpHeader->OffsetAndFlags &= ~IP_DF_FLAG;
  680. CHECKSUM_XFER(IpChecksumDelta, IpHeader->Checksum);
  681. IpChecksumDelta += ~IP_DF_FLAG;
  682. CHECKSUM_FOLD(IpChecksumDelta);
  683. CHECKSUM_XFER(IpHeader->Checksum, IpChecksumDelta);
  684. }
  685. //
  686. // Update the mapping's statistics and timestamp
  687. //
  688. KeAcquireSpinLockAtDpcLevel(&Mapping->Lock);
  689. KeQueryTickCount((PLARGE_INTEGER)&Mapping->LastAccessTime);
  690. KeReleaseSpinLockFromDpcLevel(&Mapping->Lock);
  691. InterlockedExchangeAdd(
  692. &Mapping->BYTE_COUNT,
  693. NTOHS(IpHeader->TotalLength) -
  694. IP_DATA_OFFSET(IpHeader) -
  695. sizeof(UDP_HEADER)
  696. );
  697. InterlockedIncrement(&Mapping->PACKET_COUNT);
  698. //
  699. // Resplay the mapping (periodically), and indicate the change
  700. // by invalidating 'DestinationType'
  701. //
  702. NatTryToResplayMapping(Mapping, XLATE_POSITIVE);
  703. *Contextp->DestinationType = DEST_INVALID;
  704. return FORWARD;
  705. } // NAT_TRANSLATE_UDP
  706. FORWARD_ACTION
  707. FASTCALL
  708. NAT_TRANSLATE_TCP_EDIT(
  709. PNAT_DYNAMIC_MAPPING Mapping,
  710. PNAT_XLATE_CONTEXT Contextp,
  711. IPRcvBuf** InReceiveBuffer,
  712. IPRcvBuf** OutReceiveBuffer
  713. )
  714. {
  715. PNAT_EDITOR Editor;
  716. PVOID EditorContext;
  717. PNAT_INTERFACE Interfacep;
  718. ULONG IpChecksumDelta;
  719. PIP_HEADER IpHeader = Contextp->Header;
  720. BOOLEAN IsReset;
  721. ULONG ProtocolChecksumDelta;
  722. PRTL_SPLAY_LINKS SLink;
  723. NTSTATUS status;
  724. PTCP_HEADER TcpHeader = (PTCP_HEADER)Contextp->ProtocolHeader;
  725. //
  726. // We know we will make changes to the buffer-chain,
  727. // so move the head of the list to 'OutReceiveBuffer'.
  728. //
  729. *OutReceiveBuffer = *InReceiveBuffer; *InReceiveBuffer = NULL;
  730. CHECKSUM_XFER(IpChecksumDelta, IpHeader->Checksum);
  731. CHECKSUM_XFER(ProtocolChecksumDelta, TcpHeader->Checksum);
  732. IsReset = !!TCP_FLAG(TcpHeader, RST);
  733. //
  734. // Call the editor for this session, if there is one.
  735. // Note that the mapping's cached pointers to the editor and interface
  736. // are referenced within the appropriate lock before being used.
  737. // See the synchronization rules governing 'Mapping->Editor*'
  738. // and 'Mapping->Interface*' in 'MAPPING.H' for the logic behind
  739. // the operations below.
  740. //
  741. KeAcquireSpinLockAtDpcLevel(&EditorLock);
  742. if (!(Editor = Mapping->Editor) ||
  743. !Editor->DATA_HANDLER ||
  744. !NatReferenceEditor(Editor)) {
  745. KeReleaseSpinLockFromDpcLevel(&EditorLock);
  746. }
  747. else {
  748. EditorContext = Mapping->EditorContext;
  749. KeReleaseSpinLockFromDpcLevel(&EditorLock);
  750. //
  751. // Set up context fields for the editor
  752. //
  753. Contextp->ProtocolDataOffset =
  754. (ULONG)((PUCHAR)TcpHeader -
  755. (PUCHAR)Contextp->ProtocolRecvBuffer->ipr_buffer) +
  756. TCP_DATA_OFFSET(TcpHeader);
  757. Contextp->ChecksumDelta = &ProtocolChecksumDelta;
  758. //
  759. // Invoke the editor's receive handler
  760. // if this is not a TCP RST segment.
  761. //
  762. if (!IsReset) {
  763. //
  764. // The editor-helper functions require that
  765. // 'Interfacep', 'Editor' and 'Mapping' be referenced
  766. // but not locked.
  767. //
  768. KeAcquireSpinLockAtDpcLevel(&InterfaceLock);
  769. if (!(Interfacep = Mapping->Interfacep) ||
  770. !NatReferenceInterface(Interfacep)
  771. ) {
  772. KeReleaseSpinLockFromDpcLevel(&InterfaceLock);
  773. }
  774. else {
  775. KeReleaseSpinLockFromDpcLevel(&InterfaceLock);
  776. status =
  777. Editor->DATA_HANDLER(
  778. Interfacep,
  779. (PVOID)Mapping,
  780. (PVOID)Contextp,
  781. Editor->Context,
  782. EditorContext,
  783. (PVOID)Contextp->ProtocolRecvBuffer,
  784. Contextp->ProtocolDataOffset
  785. );
  786. NatDereferenceInterface(Interfacep);
  787. if (!NT_SUCCESS(status)) {
  788. NatDereferenceEditor(Editor);
  789. InterlockedIncrement(&Mapping->REJECT_COUNT);
  790. return DROP;
  791. }
  792. //
  793. // Reset the fields formerly retrieved from the context,
  794. // which may now point to memory that has been freed.
  795. // (see 'NatHelperEditSession').
  796. //
  797. IpHeader = Contextp->Header;
  798. TcpHeader = (PTCP_HEADER)Contextp->ProtocolHeader;
  799. }
  800. }
  801. }
  802. //
  803. // Update the IP and protocol headers with the translated address/port
  804. //
  805. NAT_TRANSLATE_HEADER();
  806. //
  807. // Now add the checksum-delta incurred by changes to the IP header
  808. //
  809. KeAcquireSpinLockAtDpcLevel(&Mapping->Lock);
  810. //
  811. // Perform state validation for inbound mappings.
  812. //
  813. if (NAT_MAPPING_INBOUND(Mapping)
  814. && DROP == NAT_TRANSLATE_TCP_STATE_CHECK(
  815. Mapping,
  816. TcpHeader
  817. )) {
  818. KeReleaseSpinLockFromDpcLevel(&Mapping->Lock);
  819. return DROP;
  820. } else if (TCP_FLAG(TcpHeader, SYN)) {
  821. //
  822. // Record that we've seen a SYN in this direction
  823. //
  824. Mapping->Flags |= NAT_TRANSLATE_SYN;
  825. }
  826. if (!Contextp->ChecksumOffloaded) {
  827. IpChecksumDelta += Mapping->IpChecksumDelta[XLATE_POSITIVE];
  828. CHECKSUM_FOLD(IpChecksumDelta);
  829. CHECKSUM_XFER(IpHeader->Checksum, IpChecksumDelta);
  830. if (!NAT_XLATE_EDITED(Contextp)) {
  831. ProtocolChecksumDelta += Mapping->ProtocolChecksumDelta[XLATE_POSITIVE];
  832. CHECKSUM_FOLD(ProtocolChecksumDelta);
  833. CHECKSUM_XFER(TcpHeader->Checksum, ProtocolChecksumDelta);
  834. } else {
  835. //
  836. // NatEditorEditSession was called on the packet;
  837. // Completely recompute the TCP checksum.
  838. //
  839. NatComputeTcpChecksum(
  840. IpHeader,
  841. (PTCP_HEADER)Contextp->ProtocolHeader,
  842. Contextp->ProtocolRecvBuffer
  843. );
  844. }
  845. } else {
  846. //
  847. // Compute the IP and TCP checksums
  848. //
  849. NatComputeIpChecksum(IpHeader);
  850. NatComputeTcpChecksum(
  851. IpHeader,
  852. (PTCP_HEADER)Contextp->ProtocolHeader,
  853. Contextp->ProtocolRecvBuffer
  854. );
  855. }
  856. if (NAT_MAPPING_CLEAR_DF_BIT(Mapping) &&
  857. (IpHeader->OffsetAndFlags & IP_DF_FLAG)) {
  858. //
  859. // Clear the DF bit from this packet and adjust the IP
  860. // checksum accordingly.
  861. //
  862. IpHeader->OffsetAndFlags &= ~IP_DF_FLAG;
  863. CHECKSUM_XFER(IpChecksumDelta, IpHeader->Checksum);
  864. IpChecksumDelta += ~IP_DF_FLAG;
  865. CHECKSUM_FOLD(IpChecksumDelta);
  866. CHECKSUM_XFER(IpHeader->Checksum, IpChecksumDelta);
  867. }
  868. //
  869. // Check if need to adjust MSS options in TCP SYNs
  870. //
  871. if (TCP_FLAG(TcpHeader, SYN) && (Mapping->MaxMSS > 0)) {
  872. NatAdjustMSSOption(Contextp, Mapping->MaxMSS);
  873. }
  874. //
  875. // Now we need to update the connection state for the sender
  876. // based on the flags in the packet:
  877. //
  878. // When a RST is seen, we close both ends of the connection.
  879. // As each FIN is seen, we mark the mapping appropriately.
  880. // When both FINs have been seen, we mark the mapping for deletion.
  881. //
  882. if (IsReset) {
  883. NatExpireMapping(Mapping);
  884. }
  885. else
  886. if (TCP_FLAG(TcpHeader, FIN)) {
  887. Mapping->Flags |= NAT_TRANSLATE_FIN;
  888. if (NAT_MAPPING_FIN(Mapping)) {
  889. NatExpireMapping(Mapping);
  890. }
  891. }
  892. //
  893. // Update the mapping's statistics and timestamp
  894. //
  895. KeQueryTickCount((PLARGE_INTEGER)&Mapping->LastAccessTime);
  896. KeReleaseSpinLockFromDpcLevel(&Mapping->Lock);
  897. InterlockedExchangeAdd(
  898. &Mapping->BYTE_COUNT,
  899. NTOHS(IpHeader->TotalLength) -
  900. IP_DATA_OFFSET(IpHeader) -
  901. TCP_DATA_OFFSET(TcpHeader)
  902. );
  903. InterlockedIncrement(&Mapping->PACKET_COUNT);
  904. //
  905. // Resplay the mapping (periodically), and indicate the change
  906. // by invalidating 'DestinationType'
  907. //
  908. NatTryToResplayMapping(Mapping, XLATE_POSITIVE);
  909. *Contextp->DestinationType = DEST_INVALID;
  910. return FORWARD;
  911. } // NAT_TRANSLATE_TCP_EDIT
  912. FORWARD_ACTION
  913. FASTCALL
  914. NAT_TRANSLATE_UDP_EDIT(
  915. PNAT_DYNAMIC_MAPPING Mapping,
  916. PNAT_XLATE_CONTEXT Contextp,
  917. IPRcvBuf** InReceiveBuffer,
  918. IPRcvBuf** OutReceiveBuffer
  919. )
  920. {
  921. PNAT_EDITOR Editor;
  922. PVOID EditorContext;
  923. PNAT_INTERFACE Interfacep;
  924. ULONG IpChecksumDelta;
  925. PIP_HEADER IpHeader = Contextp->Header;
  926. BOOLEAN IsReset;
  927. ULONG ProtocolChecksumDelta;
  928. PRTL_SPLAY_LINKS SLink;
  929. NTSTATUS status;
  930. BOOLEAN UpdateXsum;
  931. PUDP_HEADER UdpHeader = (PUDP_HEADER)Contextp->ProtocolHeader;
  932. //
  933. // We know we will make changes to the buffer-chain,
  934. // so move the head of the list to 'OutReceiveBuffer'.
  935. //
  936. *OutReceiveBuffer = *InReceiveBuffer; *InReceiveBuffer = NULL;
  937. //
  938. // We have to handle the fact that the UDP checksum is optional;
  939. // if the checksum in the header is zero, then no checksum was sent
  940. // and we will make no changes to the field.
  941. //
  942. CHECKSUM_XFER(IpChecksumDelta, IpHeader->Checksum);
  943. if (!UdpHeader->Checksum) {
  944. UpdateXsum = FALSE;
  945. }
  946. else {
  947. UpdateXsum = TRUE;
  948. CHECKSUM_XFER(ProtocolChecksumDelta, UdpHeader->Checksum);
  949. }
  950. //
  951. // Call the editor for this session, if there is one.
  952. // Note that the mapping's cached pointers to the editor and interface
  953. // are referenced within the appropriate lock before being used.
  954. // See the synchronization rules governing 'Mapping->Editor*'
  955. // and 'Mapping->Interface*' in 'MAPPING.H' for the logic behind
  956. // the operations below.
  957. //
  958. KeAcquireSpinLockAtDpcLevel(&EditorLock);
  959. if (!(Editor = Mapping->Editor) ||
  960. !Editor->DATA_HANDLER ||
  961. !NatReferenceEditor(Editor)) {
  962. KeReleaseSpinLockFromDpcLevel(&EditorLock);
  963. }
  964. else {
  965. EditorContext = Mapping->EditorContext;
  966. KeReleaseSpinLockFromDpcLevel(&EditorLock);
  967. //
  968. // Set up the context fields to be used for editing
  969. //
  970. Contextp->ProtocolDataOffset =
  971. (ULONG)((PUCHAR)UdpHeader -
  972. Contextp->ProtocolRecvBuffer->ipr_buffer) +
  973. sizeof(UDP_HEADER);
  974. Contextp->ChecksumDelta = UpdateXsum ? &ProtocolChecksumDelta : NULL;
  975. //
  976. // Invoke the editor's receive handler
  977. //
  978. // The editor-helper functions require that
  979. // 'Interfacep', 'Editor' and 'Mapping' be referenced
  980. // but not locked.
  981. //
  982. KeAcquireSpinLockAtDpcLevel(&InterfaceLock);
  983. if (!(Interfacep = Mapping->Interfacep) ||
  984. !NatReferenceInterface(Interfacep)
  985. ) {
  986. KeReleaseSpinLockFromDpcLevel(&InterfaceLock);
  987. }
  988. else {
  989. KeReleaseSpinLockFromDpcLevel(&InterfaceLock);
  990. status =
  991. Editor->DATA_HANDLER(
  992. Interfacep,
  993. (PVOID)Mapping,
  994. (PVOID)Contextp,
  995. Editor->Context,
  996. EditorContext,
  997. (PVOID)Contextp->ProtocolRecvBuffer,
  998. Contextp->ProtocolDataOffset
  999. );
  1000. NatDereferenceInterface(Interfacep);
  1001. if (!NT_SUCCESS(status)) {
  1002. NatDereferenceEditor(Editor);
  1003. InterlockedIncrement(&Mapping->REJECT_COUNT);
  1004. return DROP;
  1005. }
  1006. //
  1007. // Reset the fields formerly retrieved from the context,
  1008. // which may now point to memory that has been freed.
  1009. // (see 'NatHelperEditSession').
  1010. //
  1011. IpHeader = Contextp->Header;
  1012. UdpHeader = (PUDP_HEADER)Contextp->ProtocolHeader;
  1013. }
  1014. NatDereferenceEditor(Editor);
  1015. }
  1016. //
  1017. // Update the IP and protocol headers with the translated address/port
  1018. //
  1019. NAT_TRANSLATE_HEADER();
  1020. if (!Contextp->ChecksumOffloaded) {
  1021. //
  1022. // Update the checksums
  1023. //
  1024. IpChecksumDelta += Mapping->IpChecksumDelta[XLATE_POSITIVE];
  1025. CHECKSUM_FOLD(IpChecksumDelta);
  1026. CHECKSUM_XFER(IpHeader->Checksum, IpChecksumDelta);
  1027. if (UpdateXsum) {
  1028. if (!NAT_XLATE_EDITED(Contextp)) {
  1029. ProtocolChecksumDelta +=
  1030. Mapping->ProtocolChecksumDelta[XLATE_POSITIVE];
  1031. CHECKSUM_FOLD(ProtocolChecksumDelta);
  1032. CHECKSUM_XFER(UdpHeader->Checksum, ProtocolChecksumDelta);
  1033. }
  1034. else {
  1035. //
  1036. // NatEditorEditSession was called on the packet;
  1037. // Completely recompute the UDP checksum.
  1038. //
  1039. NatComputeUdpChecksum(
  1040. IpHeader,
  1041. (PUDP_HEADER)Contextp->ProtocolHeader,
  1042. Contextp->ProtocolRecvBuffer
  1043. );
  1044. }
  1045. }
  1046. } else {
  1047. //
  1048. // Compute the IP and (optionally) UDP checksums
  1049. //
  1050. NatComputeIpChecksum(IpHeader);
  1051. if (UpdateXsum) {
  1052. NatComputeUdpChecksum(
  1053. IpHeader,
  1054. (PUDP_HEADER)Contextp->ProtocolHeader,
  1055. Contextp->ProtocolRecvBuffer
  1056. );
  1057. }
  1058. }
  1059. if (NAT_MAPPING_CLEAR_DF_BIT(Mapping) &&
  1060. (IpHeader->OffsetAndFlags & IP_DF_FLAG)) {
  1061. //
  1062. // Clear the DF bit from this packet and adjust the IP
  1063. // checksum accordingly.
  1064. //
  1065. IpHeader->OffsetAndFlags &= ~IP_DF_FLAG;
  1066. CHECKSUM_XFER(IpChecksumDelta, IpHeader->Checksum);
  1067. IpChecksumDelta += ~IP_DF_FLAG;
  1068. CHECKSUM_FOLD(IpChecksumDelta);
  1069. CHECKSUM_XFER(IpHeader->Checksum, IpChecksumDelta);
  1070. }
  1071. //
  1072. // Update the mapping's statistics and timestamp
  1073. //
  1074. KeAcquireSpinLockAtDpcLevel(&Mapping->Lock);
  1075. KeQueryTickCount((PLARGE_INTEGER)&Mapping->LastAccessTime);
  1076. KeReleaseSpinLockFromDpcLevel(&Mapping->Lock);
  1077. InterlockedExchangeAdd(
  1078. &Mapping->BYTE_COUNT,
  1079. NTOHS(IpHeader->TotalLength) -
  1080. IP_DATA_OFFSET(IpHeader) -
  1081. sizeof(UDP_HEADER)
  1082. );
  1083. InterlockedIncrement(&Mapping->PACKET_COUNT);
  1084. //
  1085. // Resplay the mapping (periodically), and indicate the change
  1086. // by invalidating 'DestinationType'
  1087. //
  1088. NatTryToResplayMapping(Mapping, XLATE_POSITIVE);
  1089. *Contextp->DestinationType = DEST_INVALID;
  1090. return FORWARD;
  1091. } // NAT_TRANSLATE_UDP_EDIT
  1092. FORWARD_ACTION
  1093. FASTCALL
  1094. NAT_TRANSLATE_TCP_RESIZE(
  1095. PNAT_DYNAMIC_MAPPING Mapping,
  1096. PNAT_XLATE_CONTEXT Contextp,
  1097. IPRcvBuf** InReceiveBuffer,
  1098. IPRcvBuf** OutReceiveBuffer
  1099. )
  1100. {
  1101. PNAT_EDITOR Editor;
  1102. PVOID EditorContext;
  1103. PNAT_INTERFACE Interfacep;
  1104. ULONG IpChecksumDelta;
  1105. PIP_HEADER IpHeader = Contextp->Header;
  1106. BOOLEAN IsResend;
  1107. BOOLEAN IsReset;
  1108. BOOLEAN IsSyn;
  1109. ULONG ProtocolChecksumDelta;
  1110. PRTL_SPLAY_LINKS SLink;
  1111. NTSTATUS status;
  1112. PTCP_HEADER TcpHeader = (PTCP_HEADER)Contextp->ProtocolHeader;
  1113. //
  1114. // We know we will make changes to the buffer-chain,
  1115. // so move the head of the list to 'OutReceiveBuffer'.
  1116. //
  1117. *OutReceiveBuffer = *InReceiveBuffer; *InReceiveBuffer = NULL;
  1118. CHECKSUM_XFER(IpChecksumDelta, IpHeader->Checksum);
  1119. CHECKSUM_XFER(ProtocolChecksumDelta, TcpHeader->Checksum);
  1120. IsResend = FALSE;
  1121. IsReset = !!TCP_FLAG(TcpHeader, RST);
  1122. IsSyn = !!TCP_FLAG(TcpHeader, SYN);
  1123. //
  1124. // Set up context fields for the editor
  1125. //
  1126. Contextp->ProtocolDataOffset =
  1127. (ULONG)((PUCHAR)TcpHeader -
  1128. Contextp->ProtocolRecvBuffer->ipr_buffer) +
  1129. TCP_DATA_OFFSET(TcpHeader);
  1130. Contextp->ChecksumDelta = &ProtocolChecksumDelta;
  1131. Contextp->TcpSeqNumDelta = 0;
  1132. //
  1133. // Call the editor for this session, if there is one.
  1134. // Note that the mapping's cached pointers to the editor and interface
  1135. // are referenced within the appropriate lock before being used.
  1136. // See the synchronization rules governing 'Mapping->Editor*'
  1137. // and 'Mapping->Interface*' in 'MAPPING.H' for the logic behind
  1138. // the operations below.
  1139. //
  1140. KeAcquireSpinLockAtDpcLevel(&EditorLock);
  1141. if (!(Editor = Mapping->Editor) ||
  1142. !NatReferenceEditor(Editor)) {
  1143. KeReleaseSpinLockFromDpcLevel(&EditorLock);
  1144. }
  1145. else {
  1146. EditorContext = Mapping->EditorContext;
  1147. KeReleaseSpinLockFromDpcLevel(&EditorLock);
  1148. //
  1149. // On a SYN packet, just record the sequence number
  1150. // On a RST packet, the sequence number is ignored
  1151. // On other packets, make sure the packet is in sequence.
  1152. // If the packet is a retransmission, we try to apply
  1153. // the sequence number delta. If the packet is too old
  1154. // (i.e. we don't have the delta which would apply to it)
  1155. // then we drop the packet.
  1156. //
  1157. // N.B. With resized TCP sessions the checksum-delta may change,
  1158. // and so we only touch it under cover of the mapping's lock.
  1159. //
  1160. KeAcquireSpinLockAtDpcLevel(&Mapping->Lock);
  1161. //
  1162. // Perform state validation for inbound mappings.
  1163. //
  1164. if (NAT_MAPPING_INBOUND(Mapping)
  1165. && DROP == NAT_TRANSLATE_TCP_STATE_CHECK(
  1166. Mapping,
  1167. TcpHeader
  1168. )) {
  1169. KeReleaseSpinLockFromDpcLevel(&Mapping->Lock);
  1170. return DROP;
  1171. } else if (IsSyn) {
  1172. //
  1173. // Record that we've seen a SYN in this direction
  1174. //
  1175. Mapping->Flags |= NAT_TRANSLATE_SYN;
  1176. }
  1177. if (IsSyn || !(Mapping->Flags & NAT_TRANSLATE_SYN)) {
  1178. //
  1179. // First packet for this direction;
  1180. // just record the sequence number as if it were expected.
  1181. //
  1182. Mapping->TcpSeqNumBase[XLATE_POSITIVE] =
  1183. TcpHeader->SequenceNumber;
  1184. Mapping->TcpSeqNumExpected[XLATE_POSITIVE] =
  1185. RtlUlongByteSwap(
  1186. RtlUlongByteSwap(TcpHeader->SequenceNumber) + 1
  1187. );
  1188. }
  1189. else
  1190. if (TcpHeader->SequenceNumber ==
  1191. Mapping->TcpSeqNumExpected[XLATE_POSITIVE] || IsReset
  1192. ) {
  1193. //
  1194. // The packet is in sequence, which is the most common case,
  1195. // or the segment has the reset bit set.
  1196. // No action is required.
  1197. //
  1198. }
  1199. else {
  1200. ULONG Sn =
  1201. RtlUlongByteSwap(TcpHeader->SequenceNumber);
  1202. ULONG SnE =
  1203. RtlUlongByteSwap(Mapping->TcpSeqNumExpected[XLATE_POSITIVE]);
  1204. ULONG Base =
  1205. RtlUlongByteSwap(Mapping->TcpSeqNumBase[XLATE_POSITIVE]);
  1206. //
  1207. // The packet is out of sequence.
  1208. // See if the current delta applies to it,
  1209. // i.e. if it is a retransmission of a packet
  1210. // which appears *after* the sequence number at which
  1211. // the current delta was computed.
  1212. // N.B. When comparing sequence numbers, account for wraparound
  1213. // by adding half the sequence-number space.
  1214. //
  1215. if ((Sn < SnE || (Sn + MAXLONG) < (SnE + MAXLONG)) &&
  1216. (Sn >= Base || (Sn + MAXLONG) > (Base + MAXLONG))
  1217. ) {
  1218. //
  1219. // The packet is a retransmission, and our delta applies.
  1220. //
  1221. IsResend = TRUE;
  1222. TRACE(
  1223. XLATE, ("NatTranslate: retransmission %u, expected %u\n",
  1224. Sn, SnE
  1225. ));
  1226. }
  1227. else {
  1228. //
  1229. // The packet is an old retransmission or it is out-of-order.
  1230. // We have no choice but to drop it.
  1231. //
  1232. KeReleaseSpinLockFromDpcLevel(&Mapping->Lock);
  1233. NatDereferenceEditor(Editor);
  1234. TRACE(
  1235. XLATE, ("NatTranslate: out-of-order %u, expected %u\n",
  1236. Sn, SnE
  1237. ));
  1238. InterlockedIncrement(&Mapping->REJECT_COUNT);
  1239. return DROP;
  1240. }
  1241. }
  1242. if (!IsResend) {
  1243. //
  1244. // Compute the next expected sequence number
  1245. //
  1246. Mapping->TcpSeqNumExpected[XLATE_POSITIVE] =
  1247. RtlUlongByteSwap(Mapping->TcpSeqNumExpected[XLATE_POSITIVE]) +
  1248. NTOHS(IpHeader->TotalLength) -
  1249. IP_DATA_OFFSET(IpHeader) -
  1250. TCP_DATA_OFFSET(TcpHeader);
  1251. Mapping->TcpSeqNumExpected[XLATE_POSITIVE] =
  1252. RtlUlongByteSwap(Mapping->TcpSeqNumExpected[XLATE_POSITIVE]);
  1253. }
  1254. KeReleaseSpinLockFromDpcLevel(&Mapping->Lock);
  1255. //
  1256. // Invoke the editor's receive handler
  1257. // if this is not a TCP SYN or RST segment.
  1258. //
  1259. if (!IsSyn && !IsReset) {
  1260. if (Editor->DATA_HANDLER) {
  1261. //
  1262. // The editor-helper functions require that
  1263. // 'Interfacep', 'Editor' and 'Mapping' be referenced
  1264. // but not locked.
  1265. //
  1266. KeAcquireSpinLockAtDpcLevel(&InterfaceLock);
  1267. if (!(Interfacep = Mapping->Interfacep) ||
  1268. !NatReferenceInterface(Interfacep)
  1269. ) {
  1270. KeReleaseSpinLockFromDpcLevel(&InterfaceLock);
  1271. }
  1272. else {
  1273. KeReleaseSpinLockFromDpcLevel(&InterfaceLock);
  1274. status =
  1275. Editor->DATA_HANDLER(
  1276. Interfacep,
  1277. (PVOID)Mapping,
  1278. (PVOID)Contextp,
  1279. Editor->Context,
  1280. EditorContext,
  1281. (PVOID)Contextp->ProtocolRecvBuffer,
  1282. Contextp->ProtocolDataOffset
  1283. );
  1284. NatDereferenceInterface(Interfacep);
  1285. if (!NT_SUCCESS(status)) {
  1286. NatDereferenceEditor(Editor);
  1287. InterlockedIncrement(&Mapping->REJECT_COUNT);
  1288. return DROP;
  1289. }
  1290. //
  1291. // Reset the fields formerly retrieved from the context,
  1292. // which may now point to memory that has been freed.
  1293. // (see 'NatHelperEditSession').
  1294. //
  1295. IpHeader = Contextp->Header;
  1296. TcpHeader = (PTCP_HEADER)Contextp->ProtocolHeader;
  1297. //
  1298. // We can't allow editors to edit retransmitted packets,
  1299. // since they wouldn't be able to guarantee that they make
  1300. // exactly the same changes to the retransmission as they
  1301. // made to the original.
  1302. //
  1303. if (IsResend && NAT_XLATE_EDITED(Contextp)) {
  1304. NatDereferenceEditor(Editor);
  1305. InterlockedIncrement(&Mapping->REJECT_COUNT);
  1306. return DROP;
  1307. }
  1308. }
  1309. }
  1310. }
  1311. NatDereferenceEditor(Editor);
  1312. }
  1313. if (!IsReset) {
  1314. //
  1315. // The editor is done doing the things that it does,
  1316. // including changing the packet size, possibly,
  1317. // so now adjust the TCP header's sequence number if necessary.
  1318. // Again the exclusion is RST segments.
  1319. //
  1320. KeAcquireSpinLockAtDpcLevel(&Mapping->Lock);
  1321. //
  1322. // If necessary, apply a delta value to the sequence number
  1323. // in the header of the TCP segment.
  1324. //
  1325. if (Mapping->TcpSeqNumDelta[XLATE_POSITIVE]) {
  1326. //
  1327. // Update the checksum (see RFC1624):
  1328. //
  1329. // Take out ones-complement sum of old sequence number
  1330. //
  1331. CHECKSUM_LONG(ProtocolChecksumDelta, ~TcpHeader->SequenceNumber);
  1332. //
  1333. // Store new sequence number
  1334. //
  1335. TcpHeader->SequenceNumber =
  1336. RtlUlongByteSwap(TcpHeader->SequenceNumber) +
  1337. Mapping->TcpSeqNumDelta[XLATE_POSITIVE];
  1338. TcpHeader->SequenceNumber =
  1339. RtlUlongByteSwap(TcpHeader->SequenceNumber);
  1340. //
  1341. // Add in new sequence number
  1342. //
  1343. CHECKSUM_LONG(ProtocolChecksumDelta, TcpHeader->SequenceNumber);
  1344. }
  1345. //
  1346. // The editor may have just modified the packet-size.
  1347. // Pick up any sequence-number delta it set for us,
  1348. // and update the basis of the new sequence-number delta
  1349. // in the sequence-number space
  1350. //
  1351. if (Contextp->TcpSeqNumDelta) {
  1352. Mapping->TcpSeqNumBase[XLATE_POSITIVE] =
  1353. Mapping->TcpSeqNumExpected[XLATE_POSITIVE];
  1354. Mapping->TcpSeqNumDelta[XLATE_POSITIVE] +=
  1355. Contextp->TcpSeqNumDelta;
  1356. }
  1357. //
  1358. // Adjust the ACK numbers
  1359. //
  1360. if (!TCP_FLAG(TcpHeader, ACK)) {
  1361. KeReleaseSpinLockFromDpcLevel(&Mapping->Lock);
  1362. }
  1363. else {
  1364. if (!Mapping->TcpSeqNumDelta[XLATE_NEGATIVE]) {
  1365. KeReleaseSpinLockFromDpcLevel(&Mapping->Lock);
  1366. }
  1367. else {
  1368. //
  1369. // Update the checksum (see RFC 1624)
  1370. //
  1371. // Take old ACK number out of checksum
  1372. //
  1373. CHECKSUM_LONG(ProtocolChecksumDelta, ~TcpHeader->AckNumber);
  1374. //
  1375. // Store new ACK number (note we *subtract* the delta)
  1376. //
  1377. TcpHeader->AckNumber =
  1378. RtlUlongByteSwap(TcpHeader->AckNumber) -
  1379. Mapping->TcpSeqNumDelta[XLATE_NEGATIVE];
  1380. KeReleaseSpinLockFromDpcLevel(&Mapping->Lock);
  1381. TcpHeader->AckNumber = RtlUlongByteSwap(TcpHeader->AckNumber);
  1382. //
  1383. // Add new ACK number to checksum
  1384. //
  1385. CHECKSUM_LONG(ProtocolChecksumDelta, TcpHeader->AckNumber);
  1386. }
  1387. }
  1388. }
  1389. //
  1390. // Update the IP and protocol headers with the translated address/port
  1391. //
  1392. NAT_TRANSLATE_HEADER();
  1393. //
  1394. // Now add the checksum-delta incurred by changes to the IP header
  1395. //
  1396. KeAcquireSpinLockAtDpcLevel(&Mapping->Lock);
  1397. if (!Contextp->ChecksumOffloaded) {
  1398. IpChecksumDelta += Mapping->IpChecksumDelta[XLATE_POSITIVE];
  1399. CHECKSUM_FOLD(IpChecksumDelta);
  1400. CHECKSUM_XFER(IpHeader->Checksum, IpChecksumDelta);
  1401. if (!NAT_XLATE_EDITED(Contextp)) {
  1402. ProtocolChecksumDelta += Mapping->ProtocolChecksumDelta[XLATE_POSITIVE];
  1403. CHECKSUM_FOLD(ProtocolChecksumDelta);
  1404. CHECKSUM_XFER(TcpHeader->Checksum, ProtocolChecksumDelta);
  1405. }
  1406. else {
  1407. //
  1408. // NatEditorEditSession was called on the packet;
  1409. // Completely recompute the TCP checksum.
  1410. //
  1411. NatComputeTcpChecksum(
  1412. IpHeader,
  1413. (PTCP_HEADER)Contextp->ProtocolHeader,
  1414. Contextp->ProtocolRecvBuffer
  1415. );
  1416. }
  1417. } else {
  1418. //
  1419. // Compute the IP and TCP checksums
  1420. //
  1421. NatComputeIpChecksum(IpHeader);
  1422. NatComputeTcpChecksum(
  1423. IpHeader,
  1424. (PTCP_HEADER)Contextp->ProtocolHeader,
  1425. Contextp->ProtocolRecvBuffer
  1426. );
  1427. }
  1428. if (NAT_MAPPING_CLEAR_DF_BIT(Mapping) &&
  1429. (IpHeader->OffsetAndFlags & IP_DF_FLAG)) {
  1430. //
  1431. // Clear the DF bit from this packet and adjust the IP
  1432. // checksum accordingly.
  1433. //
  1434. IpHeader->OffsetAndFlags &= ~IP_DF_FLAG;
  1435. CHECKSUM_XFER(IpChecksumDelta, IpHeader->Checksum);
  1436. IpChecksumDelta += ~IP_DF_FLAG;
  1437. CHECKSUM_FOLD(IpChecksumDelta);
  1438. CHECKSUM_XFER(IpHeader->Checksum, IpChecksumDelta);
  1439. }
  1440. //
  1441. // Check if need to adjust MSS options in TCP SYNs
  1442. //
  1443. if (TCP_FLAG(TcpHeader, SYN) && (Mapping->MaxMSS > 0)) {
  1444. NatAdjustMSSOption(Contextp, Mapping->MaxMSS);
  1445. }
  1446. //
  1447. // Now we need to update the connection state for the sender
  1448. // based on the flags in the packet:
  1449. //
  1450. // When a RST is seen, we close both ends of the connection.
  1451. // As each FIN is seen, we mark the mapping appropriately.
  1452. // When both FINs have been seen, we mark the mapping for deletion.
  1453. //
  1454. if (IsReset) {
  1455. NatExpireMapping(Mapping);
  1456. }
  1457. else
  1458. if (TCP_FLAG(TcpHeader, FIN)) {
  1459. Mapping->Flags |= NAT_TRANSLATE_FIN;
  1460. if (NAT_MAPPING_FIN(Mapping)) {
  1461. NatExpireMapping(Mapping);
  1462. }
  1463. }
  1464. //
  1465. // Update the mapping's statistics and timestamp
  1466. //
  1467. KeQueryTickCount((PLARGE_INTEGER)&Mapping->LastAccessTime);
  1468. KeReleaseSpinLockFromDpcLevel(&Mapping->Lock);
  1469. InterlockedExchangeAdd(
  1470. &Mapping->BYTE_COUNT,
  1471. NTOHS(IpHeader->TotalLength) -
  1472. IP_DATA_OFFSET(IpHeader) -
  1473. TCP_DATA_OFFSET(TcpHeader)
  1474. );
  1475. InterlockedIncrement(&Mapping->PACKET_COUNT);
  1476. //
  1477. // Resplay the mapping (periodically), and indicate the change
  1478. // by invalidating 'DestinationType'
  1479. //
  1480. NatTryToResplayMapping(Mapping, XLATE_POSITIVE);
  1481. *Contextp->DestinationType = DEST_INVALID;
  1482. return FORWARD;
  1483. } // NAT_TRANSLATE_TCP_RESIZE
  1484. FORWARD_ACTION
  1485. FASTCALL
  1486. NAT_TRANSLATE_TCP_NULL(
  1487. PNAT_DYNAMIC_MAPPING Mapping,
  1488. PNAT_XLATE_CONTEXT Contextp,
  1489. IPRcvBuf** InReceiveBuffer,
  1490. IPRcvBuf** OutReceiveBuffer
  1491. )
  1492. {
  1493. PIP_HEADER IpHeader = Contextp->Header;
  1494. KeAcquireSpinLockAtDpcLevel(&Mapping->Lock);
  1495. //
  1496. // Perform state validation for inbound mappings.
  1497. //
  1498. if (NAT_MAPPING_INBOUND(Mapping)
  1499. && DROP == NAT_TRANSLATE_TCP_STATE_CHECK(
  1500. Mapping,
  1501. ((PTCP_HEADER)Contextp->ProtocolHeader)
  1502. )) {
  1503. KeReleaseSpinLockFromDpcLevel(&Mapping->Lock);
  1504. return DROP;
  1505. } else if (TCP_FLAG(((PTCP_HEADER)Contextp->ProtocolHeader), SYN)) {
  1506. //
  1507. // Record that we've seen a SYN in this direction
  1508. //
  1509. Mapping->Flags |= NAT_TRANSLATE_SYN;
  1510. }
  1511. //
  1512. // Now we need to update the connection state for the sender
  1513. // based on the flags in the packet:
  1514. //
  1515. // When a RST is seen, we close both ends of the connection.
  1516. // As each FIN is seen, we mark the mapping appropriately.
  1517. // When both FINs have been seen, we mark the mapping for deletion.
  1518. //
  1519. if (TCP_FLAG(((PTCP_HEADER)Contextp->ProtocolHeader), RST)) {
  1520. NatExpireMapping(Mapping);
  1521. }
  1522. else
  1523. if (TCP_FLAG(((PTCP_HEADER)Contextp->ProtocolHeader), FIN)) {
  1524. Mapping->Flags |= NAT_TRANSLATE_FIN;
  1525. if (NAT_MAPPING_FIN(Mapping)) {
  1526. NatExpireMapping(Mapping);
  1527. }
  1528. }
  1529. //
  1530. // Update the mapping's timestamp and statistics
  1531. //
  1532. KeQueryTickCount((PLARGE_INTEGER)&Mapping->LastAccessTime);
  1533. KeReleaseSpinLockFromDpcLevel(&Mapping->Lock);
  1534. InterlockedExchangeAdd(
  1535. &Mapping->BYTE_COUNT,
  1536. NTOHS(IpHeader->TotalLength) -
  1537. IP_DATA_OFFSET(IpHeader) -
  1538. TCP_DATA_OFFSET(((PTCP_HEADER)Contextp->ProtocolHeader))
  1539. );
  1540. InterlockedIncrement(&Mapping->PACKET_COUNT);
  1541. //
  1542. // Resplay the mapping (periodically).
  1543. //
  1544. NatTryToResplayMapping(Mapping, XLATE_POSITIVE);
  1545. return FORWARD;
  1546. } // NAT_TRANSLATE_TCP_NULL
  1547. FORWARD_ACTION
  1548. FASTCALL
  1549. NAT_TRANSLATE_UDP_NULL(
  1550. PNAT_DYNAMIC_MAPPING Mapping,
  1551. PNAT_XLATE_CONTEXT Contextp,
  1552. IPRcvBuf** InReceiveBuffer,
  1553. IPRcvBuf** OutReceiveBuffer
  1554. )
  1555. {
  1556. PIP_HEADER IpHeader = Contextp->Header;
  1557. PUDP_HEADER UdpHeader = (PUDP_HEADER)Contextp->ProtocolHeader;
  1558. //
  1559. // Unidirectional flows require that reverse packets be dropped;
  1560. // This is primarily to support H.323 proxy.
  1561. //
  1562. NAT_DROP_IF_UNIDIRECTIONAL();
  1563. //
  1564. // Update the mapping's statistics and timestamp
  1565. //
  1566. KeAcquireSpinLockAtDpcLevel(&Mapping->Lock);
  1567. KeQueryTickCount((PLARGE_INTEGER)&Mapping->LastAccessTime);
  1568. KeReleaseSpinLockFromDpcLevel(&Mapping->Lock);
  1569. InterlockedExchangeAdd(
  1570. &Mapping->BYTE_COUNT,
  1571. NTOHS(IpHeader->TotalLength) -
  1572. IP_DATA_OFFSET(IpHeader) -
  1573. sizeof(UDP_HEADER)
  1574. );
  1575. InterlockedIncrement(&Mapping->PACKET_COUNT);
  1576. //
  1577. // Resplay the mapping (periodically).
  1578. //
  1579. NatTryToResplayMapping(Mapping, XLATE_POSITIVE);
  1580. return FORWARD;
  1581. } // NAT_TRANSLATE_UDP_NULL
  1582. #undef XLATE_FORWARD
  1583. #undef XLATE_REVERSE
  1584. #undef XLATE_POSITIVE
  1585. #undef XLATE_NEGATIVE
  1586. #undef NAT_TRANSLATE_TCP
  1587. #undef NAT_TRANSLATE_UDP
  1588. #undef NAT_TRANSLATE_TCP_EDIT
  1589. #undef NAT_TRANSLATE_UDP_EDIT
  1590. #undef NAT_TRANSLATE_TCP_RESIZE
  1591. #undef NAT_TRANSLATE_TCP_NULL
  1592. #undef NAT_TRANSLATE_UDP_NULL
  1593. #undef NAT_TRANSLATE_SYN
  1594. #undef NAT_TRANSLATE_FIN
  1595. #undef NAT_TRANSLATE_TCP_STATE_CHECK
  1596. #undef DATA_HANDLER
  1597. #undef BYTE_COUNT
  1598. #undef PACKET_COUNT
  1599. #undef REJECT_COUNT
  1600. #undef NAT_TRANSLATE_HEADER
  1601. #undef NAT_DROP_IF_UNIDIRECTIONAL
  1602. #endif // XLATE_CODE