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.

3485 lines
100 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. xlate.c
  5. Abstract:
  6. This module contains the code for translation of IP datagrams.
  7. 'NatTranslatePacket' is the routine directly invoked by TCPIP.SYS
  8. for every locally-received and locally-generated packet.
  9. Also included here is the cache of routes used to optimize forwarding.
  10. Author:
  11. Abolade Gbadegesin (t-abolag) 16-July-1997
  12. Revision History:
  13. Abolade Gbadegesin (aboladeg) 15-Apr-1998
  14. Added route-lookup cache; first stable version of multiple-client
  15. firewall hook.
  16. --*/
  17. #include "precomp.h"
  18. #pragma hdrstop
  19. //
  20. // GLOBAL DATA DECLARATIONS
  21. //
  22. //
  23. // Index of TCP/IP loopback interface
  24. //
  25. ULONG LoopbackIndex;
  26. //
  27. // Cache of routing-information
  28. //
  29. CACHE_ENTRY RouteCache[CACHE_SIZE];
  30. //
  31. // I/O request packet for notification of changes to the IP routing table.
  32. //
  33. PIRP RouteCacheIrp;
  34. //
  35. // Spin-lock controlling access to all route-cache information
  36. //
  37. KSPIN_LOCK RouteCacheLock;
  38. //
  39. // Array of entries corresponding to locations in 'RouteCache'
  40. //
  41. NAT_CACHED_ROUTE RouteCacheTable[CACHE_SIZE];
  42. //
  43. // Array of translation routines, indexed by IP protocol
  44. //
  45. PNAT_IP_TRANSLATE_ROUTINE TranslateRoutineTable[256];
  46. //
  47. // CONSTANTS
  48. //
  49. //
  50. // The boundary for UDP loose source matching. A mapping must
  51. // have private port greater than this to allow another session
  52. // to be created by a UDP packet that matches only the public
  53. // endpoint.
  54. //
  55. #define NAT_XLATE_UDP_LSM_LOW_PORT 1024
  56. //
  57. // FORWARD DECLARATIONS
  58. //
  59. NTSTATUS
  60. NatpDirectPacket(
  61. ULONG ReceiveIndex,
  62. ULONG SendIndex,
  63. PNAT_XLATE_CONTEXT Contextp,
  64. IPRcvBuf** InReceiveBuffer,
  65. IPRcvBuf** OutReceiveBuffer,
  66. FORWARD_ACTION* ForwardAction
  67. );
  68. FORWARD_ACTION
  69. NatpForwardPacket(
  70. ULONG ReceiveIndex,
  71. ULONG SendIndex,
  72. PNAT_XLATE_CONTEXT Contextp,
  73. PNAT_IP_TRANSLATE_ROUTINE TranslateRoutine,
  74. IPRcvBuf** InReceiveBuffer,
  75. IPRcvBuf** OutReceiveBuffer
  76. );
  77. BOOLEAN
  78. FASTCALL
  79. NatpIsUnicastPacket(
  80. ULONG Address
  81. );
  82. FORWARD_ACTION
  83. NatpReceiveNonUnicastPacket(
  84. ULONG Index,
  85. PNAT_XLATE_CONTEXT Contextp
  86. );
  87. FORWARD_ACTION
  88. NatpReceivePacket(
  89. ULONG Index,
  90. PNAT_XLATE_CONTEXT Contextp,
  91. PNAT_IP_TRANSLATE_ROUTINE TranslateRoutine,
  92. IPRcvBuf** InReceiveBuffer,
  93. IPRcvBuf** OutReceiveBuffer
  94. );
  95. NTSTATUS
  96. NatpRouteChangeCompletionRoutine(
  97. PDEVICE_OBJECT DeviceObject,
  98. PIRP Irp,
  99. PVOID Context
  100. );
  101. ULONG
  102. FASTCALL
  103. NatpRoutePacket(
  104. ULONG DestinationAddress,
  105. PNAT_XLATE_CONTEXT Contextp OPTIONAL,
  106. PNTSTATUS Status
  107. );
  108. FORWARD_ACTION
  109. NatpSendNonUnicastPacket(
  110. ULONG Index,
  111. PNAT_XLATE_CONTEXT Contextp
  112. );
  113. FORWARD_ACTION
  114. NatpSendPacket(
  115. ULONG Index,
  116. PNAT_XLATE_CONTEXT Contextp,
  117. PNAT_IP_TRANSLATE_ROUTINE TranslateRoutine,
  118. IPRcvBuf** InReceiveBuffer,
  119. IPRcvBuf** OutReceiveBuffer
  120. );
  121. FORWARD_ACTION
  122. NatpTranslateLocalTraffic(
  123. PNAT_INTERFACE Interfacep OPTIONAL,
  124. IP_NAT_DIRECTION Direction,
  125. PNAT_XLATE_CONTEXT Contextp,
  126. IPRcvBuf** InRecvBuffer,
  127. IPRcvBuf** OutRecvBuffer
  128. );
  129. FORWARD_ACTION
  130. NatForwardTcpStateCheck(
  131. PNAT_DYNAMIC_MAPPING pMapping,
  132. PTCP_HEADER pTcpHeader
  133. )
  134. /*++
  135. Routine Description:
  136. This routine validates that packets for a TCP active open are valid:
  137. -- only SYN at first
  138. -- after the SYN/ACK, either only SYN (SYN/ACK lost) or only ACK
  139. -- after the ACK of SYN/ACK (connection open), no SYN
  140. Arguments:
  141. pMapping -- the mapping this packet belongs to
  142. pTcpHeader -- the TCP header of the packet
  143. Return Value:
  144. FORWARD_ACTION - indicates whether to 'FORWARD' or 'DROP' the packet.
  145. Environment:
  146. Invoked with pMapping->Lock held by the caller
  147. --*/
  148. {
  149. USHORT Flags = TCP_ALL_FLAGS(pTcpHeader);
  150. if (NAT_MAPPING_TCP_OPEN(pMapping)) {
  151. //
  152. // Connection open -- SYN not allowed
  153. //
  154. return (Flags & TCP_FLAG_SYN) ? DROP : FORWARD;
  155. } else if( pMapping->Flags & NAT_MAPPING_FLAG_REV_SYN ) {
  156. ASSERT( pMapping->Flags & NAT_MAPPING_FLAG_FWD_SYN );
  157. if ((Flags & TCP_FLAG_ACK) && !(Flags & TCP_FLAG_SYN)) {
  158. //
  159. // This is the ACK of the SYN/ACK -- connection now open
  160. //
  161. pMapping->Flags |= NAT_MAPPING_FLAG_TCP_OPEN;
  162. } else if (TCP_FLAG_SYN != Flags
  163. && TCP_FLAG_RST != Flags
  164. && (TCP_FLAG_ACK | TCP_FLAG_RST) != Flags) {
  165. //
  166. // It's not an ACK of the SYN/ACK, it's not a RST (or ACK/RST),
  167. // and it's not a retransmittal of the SYN (possible
  168. // in this state, though rare) -- drop.
  169. //
  170. return DROP;
  171. }
  172. } else {
  173. //
  174. // We've yet to receive a SYN/ACK -- this packet can have only a SYN
  175. //
  176. if (TCP_FLAG_SYN != Flags) {
  177. return DROP;
  178. }
  179. pMapping->Flags |= NAT_MAPPING_FLAG_FWD_SYN;
  180. }
  181. return FORWARD;
  182. }
  183. VOID
  184. NatInitializePacketManagement(
  185. VOID
  186. )
  187. /*++
  188. Routine Description:
  189. This routine is invoked to initialize the packet-management module.
  190. Arguments:
  191. none.
  192. Return Value:
  193. none.
  194. Environment:
  195. Invoked at passive level.
  196. --*/
  197. {
  198. ULONG Length;
  199. IPRouteLookupData RouteLookupData;
  200. NTSTATUS status;
  201. PAGED_CODE();
  202. CALLTRACE(("NatInitializePacketManagement\n"));
  203. //
  204. // Initialize our route-cache and set up the table of translation-routines
  205. // indexed by IP protocol numbers.
  206. //
  207. InitializeCache(RouteCache);
  208. RouteCacheIrp = NULL;
  209. KeInitializeSpinLock(&RouteCacheLock);
  210. RtlZeroMemory(RouteCacheTable, sizeof(RouteCacheTable));
  211. RtlZeroMemory(TranslateRoutineTable, sizeof(TranslateRoutineTable));
  212. TranslateRoutineTable[NAT_PROTOCOL_ICMP] = NatTranslateIcmp;
  213. TranslateRoutineTable[NAT_PROTOCOL_PPTP] = NatTranslatePptp;
  214. TranslateRoutineTable[NAT_PROTOCOL_IP6IN4] = NatpTranslateLocalTraffic;
  215. TranslateRoutineTable[NAT_PROTOCOL_IPSEC_ESP] = NatpTranslateLocalTraffic;
  216. TranslateRoutineTable[NAT_PROTOCOL_IPSEC_AH] = NatpTranslateLocalTraffic;
  217. TranslateRoutineTable[NAT_PROTOCOL_TCP] =
  218. (PNAT_IP_TRANSLATE_ROUTINE)NatTranslatePacket;
  219. TranslateRoutineTable[NAT_PROTOCOL_UDP] =
  220. (PNAT_IP_TRANSLATE_ROUTINE)NatTranslatePacket;
  221. //
  222. // Retrieve the index of the loopback interface, which we will use
  223. // to detect and ignore loopback packets in 'NatTranslatePacket' below.
  224. //
  225. RouteLookupData.Version = 0;
  226. RouteLookupData.SrcAdd = 0;
  227. RouteLookupData.DestAdd = 0x0100007f;
  228. Length = sizeof(LoopbackIndex);
  229. status =
  230. LookupRouteInformation(
  231. &RouteLookupData,
  232. NULL,
  233. IPRouteOutgoingFirewallContext,
  234. &LoopbackIndex,
  235. &Length
  236. );
  237. if (!NT_SUCCESS(status)) {
  238. LoopbackIndex = INVALID_IF_INDEX;
  239. } else {
  240. TRACE(
  241. XLATE, (
  242. "NatInitializePacketManagement: Loopback=%d\n", LoopbackIndex
  243. ));
  244. }
  245. //
  246. // Obtain a reference to the module on the completion routine's behalf,
  247. // set up the IRP which will be used to request route-change notification,
  248. // and issue the first route-change notification request.
  249. //
  250. if (!REFERENCE_NAT()) { return; }
  251. RouteCacheIrp =
  252. IoBuildDeviceIoControlRequest(
  253. IOCTL_IP_RTCHANGE_NOTIFY_REQUEST,
  254. IpDeviceObject,
  255. NULL,
  256. 0,
  257. NULL,
  258. 0,
  259. FALSE,
  260. NULL,
  261. NULL
  262. );
  263. if (!RouteCacheIrp) {
  264. ERROR((
  265. "NatInitializePacketManagement: IoBuildDeviceIoControlRequest==0\n"
  266. ));
  267. DEREFERENCE_NAT();
  268. } else {
  269. IoSetCompletionRoutine(
  270. RouteCacheIrp,
  271. NatpRouteChangeCompletionRoutine,
  272. NULL,
  273. TRUE,
  274. TRUE,
  275. TRUE
  276. );
  277. status = IoCallDriver(IpDeviceObject, RouteCacheIrp);
  278. if (!NT_SUCCESS(status)) {
  279. ERROR(("NatInitializePacketManagement: IoCallDriver=%x\n", status));
  280. }
  281. }
  282. } // NatInitializePacketManagement
  283. NTSTATUS
  284. NatpDirectPacket(
  285. ULONG ReceiveIndex,
  286. ULONG SendIndex,
  287. PNAT_XLATE_CONTEXT Contextp,
  288. IPRcvBuf** InReceiveBuffer,
  289. IPRcvBuf** OutReceiveBuffer,
  290. FORWARD_ACTION* ForwardAction
  291. )
  292. /*++
  293. Routine Description:
  294. This routine is invoked to process packets which might be subject
  295. to control by a director.
  296. Arguments:
  297. ReceiveIndex - the interface on which the packet was received,
  298. for locally received packets
  299. SendIndex - the interface on which the packet is to be sent,
  300. for non-locally destined packets
  301. Contextp - contains context information about the packet
  302. InReceiveBuffer - points to the packet's buffer chain
  303. OutReceiveBuffer - receives the packet buffer chain if translation occurs
  304. ForwardAction - contains the action to take on the packet,
  305. if a director applies.
  306. Return Value:
  307. STATUS_SUCCESS if the packet was directed elsewhere, STATUS_UNSUCCESSFUL
  308. otherwise.
  309. --*/
  310. {
  311. ULONG64 DestinationKey[NatMaximumPath];
  312. USHORT DestinationPort;
  313. PNAT_DIRECTOR Director;
  314. IP_NAT_DIRECTOR_QUERY DirectorQuery;
  315. PNAT_DYNAMIC_MAPPING Mapping;
  316. ULONG MappingFlags;
  317. UCHAR Protocol;
  318. PNAT_DIRECTOR RedirectDirector;
  319. ULONG64 SourceKey[NatMaximumPath];
  320. USHORT SourcePort;
  321. NTSTATUS status;
  322. PNAT_INTERFACE Interfacep = NULL;
  323. USHORT MaxMSS = 0;
  324. TRACE(PER_PACKET, ("NatpDirectPacket\n"));
  325. Protocol = Contextp->Header->Protocol;
  326. if (Protocol == NAT_PROTOCOL_TCP || Protocol == NAT_PROTOCOL_UDP) {
  327. SourcePort = ((PUSHORT)Contextp->ProtocolHeader)[0];
  328. DestinationPort = ((PUSHORT)Contextp->ProtocolHeader)[1];
  329. } else {
  330. SourcePort = 0;
  331. DestinationPort = 0;
  332. }
  333. //
  334. // Choose a director to examine the packet.
  335. // If any redirects exist, we first allow the redirect-director
  336. // to look at the packet. Otherwise, we look for a specific director.
  337. // Prepare for any eventuality by retrieving and referencing
  338. // both the redirect-director (if any) and the specific director (if any).
  339. //
  340. if (!RedirectCount) {
  341. Director = NatLookupAndReferenceDirector(Protocol, DestinationPort);
  342. RedirectDirector = NULL;
  343. } else {
  344. Director = NatLookupAndReferenceDirector(Protocol, DestinationPort);
  345. RedirectDirector =
  346. (PNAT_DIRECTOR)RedirectRegisterDirector.DirectorHandle;
  347. if (!NatReferenceDirector(RedirectDirector)) {
  348. RedirectDirector = NULL;
  349. }
  350. }
  351. if (!Director && !RedirectDirector) { return STATUS_UNSUCCESSFUL; }
  352. DirectorQuery.ReceiveIndex = ReceiveIndex;
  353. DirectorQuery.SendIndex = SendIndex;
  354. DirectorQuery.Protocol = Protocol;
  355. DirectorQuery.DestinationAddress = Contextp->DestinationAddress;
  356. DirectorQuery.DestinationPort = DestinationPort;
  357. DirectorQuery.SourceAddress = Contextp->SourceAddress;
  358. DirectorQuery.SourcePort = SourcePort;
  359. if (Contextp->Flags & NAT_XLATE_FLAG_LOOPBACK) {
  360. DirectorQuery.Flags = IP_NAT_DIRECTOR_QUERY_FLAG_LOOPBACK;
  361. } else {
  362. DirectorQuery.Flags = 0;
  363. }
  364. //
  365. // Consult a director to get a private address/port
  366. // to which the incoming session should be directed:
  367. //
  368. // If there is a redirect director, try that first.
  369. // If that succeeds, release the specific director (if any)
  370. // and retain the redirect director in 'Director'.
  371. // Otherwise, release the redirect director,
  372. // and try the specific director next, if any.
  373. // Otherwise, try the specific director right away.
  374. //
  375. if (RedirectDirector) {
  376. DirectorQuery.DirectorContext = RedirectDirector->Context;
  377. status = RedirectDirector->QueryHandler(&DirectorQuery);
  378. if (NT_SUCCESS(status)) {
  379. if (Director) { NatDereferenceDirector(Director); }
  380. Director = RedirectDirector;
  381. } else {
  382. NatDereferenceDirector(RedirectDirector);
  383. if (Director && Director != RedirectDirector) {
  384. DirectorQuery.DirectorContext = Director->Context;
  385. if (Contextp->Flags & NAT_XLATE_FLAG_LOOPBACK) {
  386. DirectorQuery.Flags = IP_NAT_DIRECTOR_QUERY_FLAG_LOOPBACK;
  387. } else {
  388. DirectorQuery.Flags = 0;
  389. }
  390. status = Director->QueryHandler(&DirectorQuery);
  391. }
  392. }
  393. } else {
  394. DirectorQuery.DirectorContext = Director->Context;
  395. status = Director->QueryHandler(&DirectorQuery);
  396. }
  397. if (!NT_SUCCESS(status)) {
  398. if (Director) { NatDereferenceDirector(Director); }
  399. return STATUS_UNSUCCESSFUL;
  400. }
  401. //
  402. // Either the primary director or the redirect-director
  403. // has told us what to do with the session; see now if it should be dropped
  404. // or directed.
  405. //
  406. if (DirectorQuery.Flags & IP_NAT_DIRECTOR_QUERY_FLAG_DROP) {
  407. NatDereferenceDirector(Director);
  408. *ForwardAction = DROP;
  409. return STATUS_SUCCESS;
  410. } else if (Protocol != NAT_PROTOCOL_TCP && Protocol != NAT_PROTOCOL_UDP) {
  411. ULONG Checksum;
  412. ULONG ChecksumDelta = 0;
  413. NatDereferenceDirector(Director);
  414. //
  415. // Translate the packet as instructed by the director.
  416. // N.B. The director must specify both the destination and source
  417. // addresses.
  418. //
  419. CHECKSUM_LONG(ChecksumDelta, ~Contextp->Header->DestinationAddress);
  420. CHECKSUM_LONG(ChecksumDelta, ~Contextp->Header->SourceAddress);
  421. Contextp->Header->DestinationAddress =
  422. DirectorQuery.NewDestinationAddress;
  423. Contextp->Header->SourceAddress =
  424. DirectorQuery.NewSourceAddress;
  425. CHECKSUM_LONG(ChecksumDelta, Contextp->Header->DestinationAddress);
  426. CHECKSUM_LONG(ChecksumDelta, Contextp->Header->SourceAddress);
  427. CHECKSUM_UPDATE(Contextp->Header->Checksum);
  428. *ForwardAction = FORWARD;
  429. return STATUS_SUCCESS;
  430. }
  431. TRACE(
  432. XLATE, (
  433. "NatpDirectPacket: directed %d.%d.%d.%d/%d:%d.%d.%d.%d/%d to %d.%d.%d.%d/%d:%d.%d.%d.%d/%d\n",
  434. ADDRESS_BYTES(DirectorQuery.DestinationAddress),
  435. NTOHS(DirectorQuery.DestinationPort),
  436. ADDRESS_BYTES(DirectorQuery.SourceAddress),
  437. NTOHS(DirectorQuery.SourcePort),
  438. ADDRESS_BYTES(DirectorQuery.NewDestinationAddress),
  439. NTOHS(DirectorQuery.NewDestinationPort),
  440. ADDRESS_BYTES(DirectorQuery.NewSourceAddress),
  441. NTOHS(DirectorQuery.NewSourcePort)
  442. ));
  443. MAKE_MAPPING_KEY(
  444. SourceKey[NatForwardPath],
  445. Protocol,
  446. Contextp->SourceAddress,
  447. SourcePort
  448. );
  449. MAKE_MAPPING_KEY(
  450. DestinationKey[NatForwardPath],
  451. Protocol,
  452. Contextp->DestinationAddress,
  453. DestinationPort
  454. );
  455. MAKE_MAPPING_KEY(
  456. SourceKey[NatReversePath],
  457. Protocol,
  458. DirectorQuery.NewDestinationAddress,
  459. DirectorQuery.NewDestinationPort
  460. );
  461. MAKE_MAPPING_KEY(
  462. DestinationKey[NatReversePath],
  463. Protocol,
  464. DirectorQuery.NewSourceAddress,
  465. DirectorQuery.NewSourcePort
  466. );
  467. //
  468. // A director requested that a mapping be established for a session.
  469. // Create a mapping using the director's private endpoint.
  470. //
  471. MappingFlags =
  472. NAT_MAPPING_FLAG_INBOUND |
  473. NAT_MAPPING_FLAG_DO_NOT_LOG |
  474. ((DirectorQuery.Flags &
  475. IP_NAT_DIRECTOR_QUERY_FLAG_NO_TIMEOUT)
  476. ? NAT_MAPPING_FLAG_NO_TIMEOUT : 0) |
  477. ((DirectorQuery.Flags &
  478. IP_NAT_DIRECTOR_QUERY_FLAG_UNIDIRECTIONAL)
  479. ? NAT_MAPPING_FLAG_UNIDIRECTIONAL : 0) |
  480. ((DirectorQuery.Flags &
  481. IP_NAT_DIRECTOR_QUERY_FLAG_DELETE_ON_DISSOCIATE)
  482. ? NAT_MAPPING_FLAG_DELETE_ON_DISSOCIATE_DIRECTOR : 0);
  483. #ifdef NAT_WMI
  484. //
  485. // Determine if this mapping should be logged. We only want to log
  486. // mappings that are crossing a boundary or firewalled interface.
  487. // Furthermore, we only want to perform those checks if connection
  488. // logging is actually enabled.
  489. //
  490. if (NatWmiEnabledEvents[NAT_WMI_CONNECTION_CREATION_EVENT]) {
  491. BOOLEAN LogConnection = FALSE;
  492. KeAcquireSpinLockAtDpcLevel(&InterfaceLock);
  493. if (NatLookupCachedInterface(ReceiveIndex, Interfacep)) {
  494. LogConnection =
  495. NAT_INTERFACE_BOUNDARY(Interfacep)
  496. || NAT_INTERFACE_FW(Interfacep);
  497. }
  498. if (!LogConnection
  499. && NatLookupCachedInterface(SendIndex, Interfacep)) {
  500. if (NAT_INTERFACE_BOUNDARY(Interfacep)
  501. || NAT_INTERFACE_FW(Interfacep)) {
  502. //
  503. // This isn't an inbound connection
  504. //
  505. MappingFlags &= ~NAT_MAPPING_FLAG_INBOUND;
  506. LogConnection = TRUE;
  507. }
  508. }
  509. KeReleaseSpinLockFromDpcLevel(&InterfaceLock);
  510. if (LogConnection) {
  511. MappingFlags &= ~NAT_MAPPING_FLAG_DO_NOT_LOG;
  512. }
  513. }
  514. #endif
  515. //
  516. // Record maximum MSS value in case it needs to be set in the mapping.
  517. //
  518. KeAcquireSpinLockAtDpcLevel(&InterfaceLock);
  519. if (NatLookupCachedInterface(SendIndex, Interfacep) && NAT_INTERFACE_BOUNDARY(Interfacep)) {
  520. MaxMSS = MAX_MSSOPTION(Interfacep->MTU);
  521. } else if (NatLookupCachedInterface(ReceiveIndex, Interfacep) &&
  522. NAT_INTERFACE_BOUNDARY(Interfacep)) {
  523. MaxMSS = MAX_MSSOPTION(Interfacep->MTU);
  524. }
  525. KeReleaseSpinLockFromDpcLevel(&InterfaceLock);
  526. KeAcquireSpinLockAtDpcLevel(&MappingLock);
  527. status =
  528. NatCreateMapping(
  529. MappingFlags,
  530. DestinationKey,
  531. SourceKey,
  532. NULL,
  533. NULL,
  534. MaxMSS,
  535. Director,
  536. DirectorQuery.DirectorSessionContext,
  537. NULL,
  538. NULL,
  539. &Mapping
  540. );
  541. KeReleaseSpinLockFromDpcLevel(&MappingLock);
  542. if (!NT_SUCCESS(status)) {
  543. TRACE(XLATE, ("NatpDirectPacket: mapping not created\n"));
  544. NatDereferenceDirector(Director);
  545. return STATUS_UNSUCCESSFUL;
  546. }
  547. NatDereferenceDirector(Director);
  548. //
  549. // Perform the actual translation.
  550. // This replaces the destination endpoint
  551. // with whatever the director provided as a destination.
  552. //
  553. *ForwardAction =
  554. Mapping->TranslateRoutine[NatForwardPath](
  555. Mapping,
  556. Contextp,
  557. InReceiveBuffer,
  558. OutReceiveBuffer
  559. );
  560. NatDereferenceMapping(Mapping);
  561. return STATUS_SUCCESS;
  562. } // NatpDirectPacket
  563. FORWARD_ACTION
  564. NatpForwardPacket(
  565. ULONG ReceiveIndex,
  566. ULONG SendIndex,
  567. PNAT_XLATE_CONTEXT Contextp,
  568. PNAT_IP_TRANSLATE_ROUTINE TranslateRoutine,
  569. IPRcvBuf** InReceiveBuffer,
  570. IPRcvBuf** OutReceiveBuffer
  571. )
  572. /*++
  573. Routine Description:
  574. This routine is invoked to process packets to be forwarded.
  575. Such packets are not locally-destined, and hence we care about them
  576. only if the outgoing interface is a NAT boundary interface, in which case
  577. the packets must be automatically translated using a public IP address.
  578. In the process, a mapping is created so that translation of the packet's
  579. successors is handled in the fast path in 'NatTranslatePacket'.
  580. Arguments:
  581. ReceiveIndex - the interface on which the packet was received
  582. SendIndex - the interface on which the packet is to be forwarded
  583. Contextp - contains context information about the packet
  584. TranslateRoutine - points to the routine which performs translation
  585. InReceiveBuffer - points to the packet buffer chain
  586. OutReceiveBuffer - receives the packet buffer chain if translation occurs
  587. Return Value:
  588. FORWARD_ACTION - indicates whether to 'FORWARD' or 'DROP' the packet.
  589. --*/
  590. {
  591. FORWARD_ACTION act;
  592. PNAT_USED_ADDRESS Addressp;
  593. ULONG64 DestinationKey[NatMaximumPath];
  594. USHORT DestinationPort;
  595. PNAT_DYNAMIC_MAPPING InsertionPoint;
  596. PNAT_INTERFACE Interfacep;
  597. PNAT_DYNAMIC_MAPPING Mapping;
  598. USHORT PortAcquired;
  599. UCHAR Protocol;
  600. ULONG PublicAddress;
  601. PNAT_INTERFACE ReceiveInterface;
  602. ULONG ReverseSourceAddress;
  603. ULONG64 SourceKey[NatMaximumPath];
  604. USHORT SourcePort;
  605. PNAT_USED_ADDRESS StaticAddressp;
  606. NTSTATUS status;
  607. ULONG i;
  608. USHORT MaxMSS = 0;
  609. TRACE(PER_PACKET, ("NatpForwardPacket\n"));
  610. //
  611. // Look up the sending and receiving interfaces, and set the default action
  612. // in 'act'. If the sending interface is a boundary interface,
  613. // then if we are unable to translate for any reason, the packet must be
  614. // dropped since it contains a private address.
  615. // Otherwise, we allow the stack to see the packet even if we cannot
  616. // translate it.
  617. //
  618. KeAcquireSpinLockAtDpcLevel(&InterfaceLock);
  619. if (!NatLookupCachedInterface(SendIndex, Interfacep)) {
  620. act = FORWARD;
  621. //
  622. // We need to see if this packet was received on a firewalled
  623. // interface, and, if so, drop the packet.
  624. //
  625. if (NatLookupCachedInterface(ReceiveIndex, ReceiveInterface)
  626. && NAT_INTERFACE_FW(ReceiveInterface)) {
  627. act = DROP;
  628. }
  629. } else {
  630. if (!NatLookupCachedInterface(ReceiveIndex, ReceiveInterface)) {
  631. //
  632. // The receiving interface has not been added.
  633. // This packet will not be translated, and should furthermore
  634. // be dropped if the outgoing interface is a boundary or
  635. // firewalled interface.
  636. // This prevents unauthorized access to the remote network.
  637. //
  638. act =
  639. (NAT_INTERFACE_BOUNDARY(Interfacep)
  640. || NAT_INTERFACE_FW(Interfacep))
  641. ? DROP
  642. : FORWARD;
  643. Interfacep = NULL;
  644. } else if (NAT_INTERFACE_BOUNDARY(ReceiveInterface)) {
  645. KeReleaseSpinLockFromDpcLevel(&InterfaceLock);
  646. //
  647. // Treat this packet like a received packet.
  648. // This case may occur when we have an address pool and someone
  649. // on the public network sends a packet to an address in the pool.
  650. // The destination will be non-local, as for a transit packet,
  651. // (hence the invocation of 'NatpForwardPacket') when actually
  652. // the packet should be treated as a receipt
  653. // (via 'NatpReceivePacket').
  654. //
  655. return
  656. NatpReceivePacket(
  657. ReceiveIndex,
  658. Contextp,
  659. TranslateRoutine,
  660. InReceiveBuffer,
  661. OutReceiveBuffer
  662. );
  663. } else if (NAT_INTERFACE_FW(ReceiveInterface)) {
  664. //
  665. // We've received a packet on a non-translating firewalled
  666. // interface that is not directly addressed to us.
  667. //
  668. Interfacep = NULL;
  669. act = DROP;
  670. } else if (NAT_INTERFACE_BOUNDARY(Interfacep)) {
  671. //
  672. // The outgoing interface is a boundary interface,
  673. // and the receiving interface is permitted access.
  674. // If translation fails, the packet must be dropped.
  675. //
  676. NatReferenceInterface(Interfacep);
  677. act = DROP;
  678. } else if (NAT_INTERFACE_FW(Interfacep)) {
  679. //
  680. // The outgoing interface is a non-boundary firewalled
  681. // interface; transit traffic is not permitted through
  682. // such an interface.
  683. //
  684. Interfacep = NULL;
  685. act = DROP;
  686. } else {
  687. //
  688. // The outgoing interface is not a boundary or firewalled
  689. // interface.
  690. //
  691. Interfacep = NULL;
  692. act = FORWARD;
  693. }
  694. }
  695. KeReleaseSpinLockFromDpcLevel(&InterfaceLock);
  696. if (!Interfacep) { return act; }
  697. if ((PVOID)TranslateRoutine == (PVOID)NatTranslatePacket) {
  698. //
  699. // This is either a TCP or a UDP packet.
  700. //
  701. Protocol = Contextp->Header->Protocol;
  702. SourcePort = ((PUSHORT)Contextp->ProtocolHeader)[0];
  703. DestinationPort = ((PUSHORT)Contextp->ProtocolHeader)[1];
  704. MAKE_MAPPING_KEY(
  705. SourceKey[NatForwardPath],
  706. Protocol,
  707. Contextp->SourceAddress,
  708. SourcePort
  709. );
  710. MAKE_MAPPING_KEY(
  711. DestinationKey[NatForwardPath],
  712. Protocol,
  713. Contextp->DestinationAddress,
  714. DestinationPort
  715. );
  716. //
  717. // We now generate an outbound mapping and translate the packet.
  718. //
  719. // First, acquire an endpoint for the mapping;
  720. // note that this must be done with the interface's lock held,
  721. // since it involves consulting the interface's address-pool.
  722. //
  723. KeAcquireSpinLockAtDpcLevel(&MappingLock);
  724. KeAcquireSpinLockAtDpcLevel(&Interfacep->Lock);
  725. status =
  726. NatAcquireEndpointFromAddressPool(
  727. Interfacep,
  728. SourceKey[NatForwardPath],
  729. DestinationKey[NatForwardPath],
  730. 0,
  731. MAPPING_PORT(SourceKey[NatForwardPath]),
  732. TRUE,
  733. &Addressp,
  734. &PortAcquired
  735. );
  736. if (!NT_SUCCESS(status)) {
  737. KeReleaseSpinLockFromDpcLevel(&Interfacep->Lock);
  738. KeReleaseSpinLockFromDpcLevel(&MappingLock);
  739. ExInterlockedAddLargeStatistic(
  740. (PLARGE_INTEGER)&Interfacep->Statistics.RejectsForward, 1
  741. );
  742. NatDereferenceInterface(Interfacep);
  743. return DROP;
  744. }
  745. PublicAddress = Addressp->PublicAddress;
  746. //
  747. // Next, if there are static mappings for the interface,
  748. // handle the special case where a client A behind the NAT
  749. // is attempting to send to another client B behind the NAT,
  750. // using the *statically-mapped* address for B.
  751. // We detect this case by looking for a static address mapping
  752. // from 'Contextp->DestinationAddress' to a private address.
  753. //
  754. if (Interfacep->NoStaticMappingExists) {
  755. KeReleaseSpinLockFromDpcLevel(&Interfacep->Lock);
  756. ReverseSourceAddress = Contextp->DestinationAddress;
  757. } else {
  758. StaticAddressp =
  759. NatLookupStaticAddressPoolEntry(
  760. Interfacep,
  761. Contextp->DestinationAddress,
  762. FALSE
  763. );
  764. if (StaticAddressp) {
  765. ReverseSourceAddress = StaticAddressp->PrivateAddress;
  766. } else {
  767. ReverseSourceAddress = Contextp->DestinationAddress;
  768. }
  769. KeReleaseSpinLockFromDpcLevel(&Interfacep->Lock);
  770. }
  771. MAKE_MAPPING_KEY(
  772. SourceKey[NatReversePath],
  773. Protocol,
  774. ReverseSourceAddress,
  775. DestinationPort
  776. );
  777. MAKE_MAPPING_KEY(
  778. DestinationKey[NatReversePath],
  779. Protocol,
  780. PublicAddress,
  781. PortAcquired
  782. );
  783. //
  784. // Set Maximum MSS value on the mapping of the sending interface.
  785. //
  786. if (NAT_INTERFACE_BOUNDARY(Interfacep)) {
  787. MaxMSS = MAX_MSSOPTION(Interfacep->MTU);
  788. }
  789. //
  790. // Allocate a mapping.
  791. //
  792. status =
  793. NatCreateMapping(
  794. 0,
  795. DestinationKey,
  796. SourceKey,
  797. Interfacep,
  798. (PVOID)Addressp,
  799. MaxMSS,
  800. NULL,
  801. NULL,
  802. NULL,
  803. NULL,
  804. &Mapping
  805. );
  806. KeReleaseSpinLockFromDpcLevel(&MappingLock);
  807. if (!NT_SUCCESS(status)) {
  808. ExInterlockedAddLargeStatistic(
  809. (PLARGE_INTEGER)&Interfacep->Statistics.RejectsForward, 1
  810. );
  811. NatDereferenceInterface(Interfacep);
  812. return DROP;
  813. }
  814. //
  815. // Activate any applicable dynamic tickets
  816. //
  817. if (DynamicTicketCount) {
  818. NatLookupAndApplyDynamicTicket(
  819. Protocol,
  820. DestinationPort,
  821. Interfacep,
  822. PublicAddress,
  823. Contextp->SourceAddress
  824. );
  825. }
  826. //
  827. // Perform the actual translation
  828. //
  829. act =
  830. Mapping->TranslateRoutine[NatForwardPath](
  831. Mapping,
  832. Contextp,
  833. InReceiveBuffer,
  834. OutReceiveBuffer
  835. );
  836. NatDereferenceMapping(Mapping);
  837. NatDereferenceInterface(Interfacep);
  838. return act;
  839. } // TranslateRoutine != NatTranslatePacket
  840. //
  841. // The packet is neither a TCP nor a UDP packet.
  842. // Only translate if the outgoing interface is a boundary interface.
  843. //
  844. // N.B. The translation routine must be invoked with a reference made
  845. // to the boundary interface, and without holding the mapping lock.
  846. //
  847. if (TranslateRoutine) {
  848. act =
  849. TranslateRoutine(
  850. Interfacep,
  851. NatOutboundDirection,
  852. Contextp,
  853. InReceiveBuffer,
  854. OutReceiveBuffer
  855. );
  856. }
  857. NatDereferenceInterface(Interfacep);
  858. return act;
  859. } // NatpForwardPacket
  860. void
  861. FASTCALL
  862. NatAdjustMSSOption(
  863. PNAT_XLATE_CONTEXT Contextp,
  864. USHORT MaxMSS
  865. )
  866. /*++
  867. Routine Description:
  868. This routine lowers MSS option in a TCP SYN packet if that MSS value is too large
  869. for the outgoing link. It also updates the TCP checksum accordingly.
  870. It assumes that IP and TCP checksums have been computed so it has to be called after
  871. the translation route completes.
  872. TCP options follow the general format of one byte type, one byte length, zero or more
  873. data indicated by the length field. The exception to this general format are one byte
  874. NOP and ENDOFOPTION option types.
  875. Arguments:
  876. Contextp - contains context information about the packet
  877. MaxMSS - the maximum MSS value on the sending interface which is equal to the
  878. interface MTU minus IP and TCP fixed header size
  879. Return Value:
  880. --*/
  881. {
  882. USHORT tempMSS;
  883. PTCP_HEADER TcpHeader = (PTCP_HEADER)Contextp->ProtocolHeader;
  884. PUCHAR OptionsPtr = (PUCHAR)(TcpHeader + 1);
  885. PUCHAR OptionsEnd = NULL, TcpBufEnd = NULL;
  886. ULONG tcpChecksumDelta;
  887. UNALIGNED MSSOption *MSSPtr = NULL;
  888. CALLTRACE(("NatpAdjustMSSOption\n"));
  889. //
  890. // Only TCP SYN has MSS options.
  891. //
  892. ASSERT(TCP_FLAG(TcpHeader, SYN) && MaxMSS > 0);
  893. //
  894. // Do some bound checking
  895. //
  896. TcpBufEnd = Contextp->ProtocolRecvBuffer->ipr_buffer + Contextp->ProtocolRecvBuffer->ipr_size;
  897. if ((TcpBufEnd - (PUCHAR)TcpHeader) >= TCP_DATA_OFFSET( TcpHeader )) {
  898. OptionsEnd = (PUCHAR)TcpHeader + TCP_DATA_OFFSET( TcpHeader );
  899. }
  900. else {
  901. return;
  902. }
  903. //
  904. // MSS option is not the first option so it is necessary to do a complete parsing.
  905. //
  906. while (OptionsPtr < OptionsEnd) {
  907. switch (*OptionsPtr) {
  908. case TCP_OPTION_ENDOFOPTIONS:
  909. return;
  910. case TCP_OPTION_NOP:
  911. OptionsPtr++;
  912. break;
  913. case TCP_OPTION_MSS:
  914. MSSPtr = (UNALIGNED MSSOption *)OptionsPtr;
  915. //
  916. // Found malformed MSS option so quit and do nothing.
  917. //
  918. if (MSS_OPTION_SIZE > (OptionsEnd - OptionsPtr) ||
  919. MSS_OPTION_SIZE != MSSPtr->OptionLen) {
  920. return;
  921. }
  922. tempMSS = MSSPtr->MSSValue;
  923. //
  924. // if the current MSS option is smaller than sndMTU - (IP Header + TCP header),
  925. // nothing needs to be done.
  926. //
  927. if (RtlUshortByteSwap( tempMSS ) <= MaxMSS) {
  928. OptionsPtr += MSS_OPTION_SIZE;
  929. break;
  930. }
  931. //
  932. // Adjust the MSS option.
  933. //
  934. MSSPtr->MSSValue = RtlUshortByteSwap( MaxMSS );
  935. //
  936. // Update the TCP check sum. It assumes that this routine is always called
  937. // after translation so that even in the case of off-loading both IP and TCP
  938. // checksums are already calculated.
  939. //
  940. CHECKSUM_XFER(tcpChecksumDelta, TcpHeader->Checksum);
  941. //
  942. // Check to see if the MSS option starts at 16 bit boundary. If not then need
  943. // to byte swap the 16-bit MSS value when updating the check sum.
  944. //
  945. if (0 == (OptionsPtr - (PUCHAR)TcpHeader) % 2) {
  946. tcpChecksumDelta += (USHORT)~tempMSS;
  947. tcpChecksumDelta += MSSPtr->MSSValue;
  948. } else {
  949. //
  950. // The MSS option does not sit on a 16 bit boundary, so the packets is like this:
  951. // [MSS Option Size][MSS' high byte][MSS' low byte][one byte pointed by OptionPtr]
  952. // Use these two 16-bit fields to update the checksum.
  953. //
  954. tcpChecksumDelta += (USHORT)~((USHORT)((tempMSS & 0xFF00) >> 8) | (MSS_OPTION_SIZE << 8));
  955. tcpChecksumDelta += (USHORT)((MSSPtr->MSSValue & 0xFF00) >> 8) | (MSS_OPTION_SIZE << 8);
  956. tcpChecksumDelta += (USHORT)~((USHORT)((tempMSS & 0xFF) <<8) | (USHORT)*OptionsPtr);
  957. tcpChecksumDelta += (USHORT)((MSSPtr->MSSValue & 0xFF) <<8) | (USHORT)*OptionsPtr;
  958. }
  959. CHECKSUM_FOLD(tcpChecksumDelta);
  960. CHECKSUM_XFER(TcpHeader->Checksum, tcpChecksumDelta);
  961. OptionsPtr += MSS_OPTION_SIZE;
  962. TRACE(
  963. XLATE,
  964. ("NatpAdjustMSSOption: Adjusted TCP MSS Option from %d to %d\n",
  965. RtlUshortByteSwap( tempMSS ),
  966. MaxMSS));
  967. break;
  968. case TCP_OPTION_WSCALE:
  969. //
  970. // Found malformed WS options so quit and do nothing.
  971. //
  972. if (WS_OPTION_SIZE > OptionsPtr - OptionsEnd || WS_OPTION_SIZE != OptionsPtr[1]) {
  973. return;
  974. }
  975. OptionsPtr += WS_OPTION_SIZE;
  976. break;
  977. case TCP_OPTION_TIMESTAMPS:
  978. //
  979. // Found malformed Time Stamp options so quit and do nothing.
  980. //
  981. if (TS_OPTION_SIZE > OptionsPtr - OptionsEnd || TS_OPTION_SIZE != OptionsPtr[1]) {
  982. return;
  983. }
  984. OptionsPtr += TS_OPTION_SIZE;
  985. break;
  986. case TCP_OPTION_SACK_PERMITTED:
  987. //
  988. // Found malformed Sack Permitted options so quit and do nothing.
  989. //
  990. if (SP_OPTION_SIZE > OptionsPtr - OptionsEnd || SP_OPTION_SIZE != OptionsPtr[1]) {
  991. return;
  992. }
  993. OptionsPtr += SP_OPTION_SIZE;
  994. break;
  995. default:
  996. //
  997. // unknown option. Check to see if it has a valid length field.
  998. //
  999. if (OptionsEnd > OptionsPtr + 1) {
  1000. // Found malformed unknown options so quit and do nothing.
  1001. if (OptionsPtr[1] < 2 || OptionsPtr[1] > OptionsEnd - OptionsPtr)
  1002. return;
  1003. OptionsPtr += OptionsPtr[1];
  1004. } else {
  1005. return;
  1006. }
  1007. break;
  1008. } // switch
  1009. } // while
  1010. }
  1011. BOOLEAN
  1012. FASTCALL
  1013. NatpIsUnicastPacket(
  1014. ULONG Address
  1015. )
  1016. /*++
  1017. Routine Description:
  1018. This routine is called to determine whether or not a packet is a unicast
  1019. packet, based on its address.
  1020. Arguments:
  1021. Address - the destination address of the packet
  1022. Return Value:
  1023. BOOLEAN - TRUE if the packet appears to be a unicast, FALSE otherwise.
  1024. --*/
  1025. {
  1026. //
  1027. // See if the packet is multicast or all-ones broadcast
  1028. //
  1029. if (ADDRESS_CLASS_D(Address) || ADDRESS_CLASS_E(Address)) {
  1030. return FALSE;
  1031. }
  1032. //
  1033. // See if the address is a network-class directed broadcast
  1034. //
  1035. if ((Address | ~GET_CLASS_MASK(Address)) == Address) {
  1036. return FALSE;
  1037. }
  1038. return TRUE;
  1039. }
  1040. FORWARD_ACTION
  1041. NatpReceiveNonUnicastPacket(
  1042. ULONG Index,
  1043. PNAT_XLATE_CONTEXT Contextp
  1044. )
  1045. /*++
  1046. Routine Description:
  1047. This routine is invoked to process locally destined non-unicast packets.
  1048. If the packet was received on a firewalled interface, it will be dropped
  1049. unless an exemption exists.
  1050. Arguments:
  1051. Index - index of the interface on which the packet was received
  1052. Contextp - the context for this packet
  1053. Return Value:
  1054. FORWARD_ACTION - indicates whether to 'FORWARD' or 'DROP' the packet.
  1055. --*/
  1056. {
  1057. FORWARD_ACTION act;
  1058. USHORT DestinationPort;
  1059. PNAT_INTERFACE Interfacep;
  1060. KIRQL Irql;
  1061. USHORT SourcePort;
  1062. PNAT_TICKET Ticketp;
  1063. UCHAR Type;
  1064. TRACE(PER_PACKET, ("NatpReceiveNonUnicastPacket\n"));
  1065. KeAcquireSpinLock(&InterfaceLock, &Irql);
  1066. if (!NatLookupCachedInterface(Index, Interfacep)
  1067. || !NAT_INTERFACE_FW(Interfacep)) {
  1068. //
  1069. // The packet was not received on a firewalled interface
  1070. //
  1071. KeReleaseSpinLock(&InterfaceLock, Irql);
  1072. act = FORWARD;
  1073. } else {
  1074. NatReferenceInterface(Interfacep);
  1075. KeReleaseSpinLockFromDpcLevel(&InterfaceLock);
  1076. //
  1077. // This packet was received on a firealled interface. Drop it,
  1078. // unless:
  1079. // * it appears to be a DHCP response packet
  1080. // * it's a UDP packet, and there exist a firewall port mapping
  1081. // (i.e., one that does not change the destination address
  1082. // or port) for the destination port
  1083. // * it's an IGMP packet
  1084. // * it's a permitted ICMP type
  1085. //
  1086. act = DROP;
  1087. switch (Contextp->Header->Protocol) {
  1088. case NAT_PROTOCOL_ICMP: {
  1089. Type = ((PICMP_HEADER)Contextp->ProtocolHeader)->Type;
  1090. switch (Type) {
  1091. case ICMP_ECHO_REQUEST:
  1092. case ICMP_TIMESTAMP_REQUEST:
  1093. case ICMP_ROUTER_REQUEST:
  1094. case ICMP_MASK_REQUEST: {
  1095. //
  1096. // These types are allowed in based on the interface's
  1097. // configuration.
  1098. //
  1099. if (NAT_INTERFACE_ALLOW_ICMP(Interfacep, Type)) {
  1100. act = FORWARD;
  1101. }
  1102. break;
  1103. }
  1104. //
  1105. // Any other inbound ICMP type is always dropped.
  1106. //
  1107. }
  1108. break;
  1109. }
  1110. case NAT_PROTOCOL_IGMP: {
  1111. act = FORWARD;
  1112. break;
  1113. }
  1114. case NAT_PROTOCOL_UDP: {
  1115. SourcePort = ((PUSHORT)Contextp->ProtocolHeader)[0];
  1116. DestinationPort = ((PUSHORT)Contextp->ProtocolHeader)[1];
  1117. if (NTOHS(DHCP_SERVER_PORT) == SourcePort
  1118. && NTOHS(DHCP_CLIENT_PORT) == DestinationPort) {
  1119. act = FORWARD;
  1120. } else {
  1121. KeAcquireSpinLockAtDpcLevel(&Interfacep->Lock);
  1122. Ticketp =
  1123. NatLookupFirewallTicket(
  1124. Interfacep,
  1125. NAT_PROTOCOL_UDP,
  1126. DestinationPort
  1127. );
  1128. if (NULL != Ticketp) {
  1129. act = FORWARD;
  1130. }
  1131. KeReleaseSpinLockFromDpcLevel(&Interfacep->Lock);
  1132. }
  1133. break;
  1134. }
  1135. }
  1136. NatDereferenceInterface(Interfacep);
  1137. KeLowerIrql(Irql);
  1138. }
  1139. return act;
  1140. } // NatpReceiveNonUnicastPacket
  1141. FORWARD_ACTION
  1142. NatpReceivePacket(
  1143. ULONG Index,
  1144. PNAT_XLATE_CONTEXT Contextp,
  1145. PNAT_IP_TRANSLATE_ROUTINE TranslateRoutine,
  1146. IPRcvBuf** InReceiveBuffer,
  1147. IPRcvBuf** OutReceiveBuffer
  1148. )
  1149. /*++
  1150. Routine Description:
  1151. This routine is invoked to process locally destined packets.
  1152. All initial automatic translation of such packets occurs here,
  1153. based on destination of the packet, which may be a local IP address
  1154. or an IP address from the pool assigned to a boundary interface.
  1155. In the process, a mapping is created so that translation of the packet's
  1156. successors is handled in the fast path in 'NatTranslatePacket'.
  1157. Arguments:
  1158. Index - index of the interface on which the packet was received
  1159. DestinationType - receives 'DEST_INVALID' if destination changed
  1160. TranslateRoutine - points to the routine which performs translation
  1161. InReceiveBuffer - points to the packet buffer chain
  1162. OutReceiveBuffer - receives the packet buffer chain if translation occurs
  1163. Return Value:
  1164. FORWARD_ACTION - indicates whether to 'FORWARD' or 'DROP' the packet.
  1165. --*/
  1166. {
  1167. FORWARD_ACTION act;
  1168. PNAT_USED_ADDRESS Addressp;
  1169. ULONG64 DestinationKey[NatMaximumPath];
  1170. USHORT DestinationPort;
  1171. ULONG i;
  1172. PNAT_INTERFACE Interfacep;
  1173. PLIST_ENTRY Link;
  1174. PNAT_DYNAMIC_MAPPING Mapping;
  1175. ULONG NewDestinationAddress;
  1176. USHORT NewDestinationPort;
  1177. UCHAR Protocol;
  1178. ULONG64 SourceKey[NatMaximumPath];
  1179. USHORT SourcePort;
  1180. NTSTATUS status;
  1181. BOOLEAN TicketProcessingOnly;
  1182. USHORT MaxMSS = 0;
  1183. TRACE(PER_PACKET, ("NatpReceivePacket\n"));
  1184. //
  1185. // Look up the receiving interface.
  1186. // If the receiving interface is a boundary interface,
  1187. // then if we are unable to translate for any reason, the packet must be
  1188. // dropped as a matter of policy, unless it is locally-destined.
  1189. // Otherwise, we allow the stack to see the packet even if we cannot
  1190. // translate it.
  1191. //
  1192. KeAcquireSpinLockAtDpcLevel(&InterfaceLock);
  1193. if (!NatLookupCachedInterface(Index, Interfacep)) {
  1194. act = FORWARD;
  1195. } else {
  1196. if (!NAT_INTERFACE_BOUNDARY(Interfacep)
  1197. && !NAT_INTERFACE_FW(Interfacep)) {
  1198. Interfacep = NULL;
  1199. act = FORWARD;
  1200. } else {
  1201. NatReferenceInterface(Interfacep);
  1202. if(NAT_INTERFACE_FW(Interfacep)) {
  1203. act = DROP;
  1204. } else {
  1205. //
  1206. // See if the packet is locally-destined
  1207. //
  1208. if (Interfacep->AddressArray[0].Address ==
  1209. Contextp->DestinationAddress) {
  1210. act = FORWARD;
  1211. } else {
  1212. act = DROP;
  1213. for (i = 1; i < Interfacep->AddressCount; i++) {
  1214. if (Interfacep->AddressArray[i].Address ==
  1215. Contextp->DestinationAddress) {
  1216. //
  1217. // The packet's destination-address is local.
  1218. //
  1219. act = FORWARD;
  1220. break;
  1221. }
  1222. }
  1223. }
  1224. }
  1225. //
  1226. // Set MaxMSS for the receiving interface so that SYN/ACK's MSS option might
  1227. // be adjusted if necessary.
  1228. //
  1229. if (NAT_INTERFACE_BOUNDARY(Interfacep)) {
  1230. MaxMSS = MAX_MSSOPTION(Interfacep->MTU);
  1231. }
  1232. }
  1233. }
  1234. KeReleaseSpinLockFromDpcLevel(&InterfaceLock);
  1235. if ((PVOID)TranslateRoutine == (PVOID)NatTranslatePacket) {
  1236. //
  1237. // If we don't recognize the receiving interface, return right away,
  1238. // unless someone has created a ticket somewhere. In the latter case,
  1239. // the packet to which the ticket must be applied may be received
  1240. // on a different interface than the interface to which the ticket
  1241. // is attached. (This may happen with one-way cable-modems or other
  1242. // asymmetric routes.) We catch that case here by using the ticket's
  1243. // interface for translation.
  1244. //
  1245. if (!Interfacep && !TicketCount) { return act; }
  1246. //
  1247. // This is either a TCP or a UDP packet.
  1248. //
  1249. Protocol = Contextp->Header->Protocol;
  1250. SourcePort = ((PUSHORT)Contextp->ProtocolHeader)[0];
  1251. DestinationPort = ((PUSHORT)Contextp->ProtocolHeader)[1];
  1252. //
  1253. // We allow the packet through if one of the following is true:
  1254. // (a) a ticket exists for the packet (e.g. a static port mapping)
  1255. // (b) a static address mapping exists for the packet's destination
  1256. // (c) this appears to be a DHCP unicast response:
  1257. // -- UDP
  1258. // -- source port 67
  1259. // -- destination port 68
  1260. // (d) this is a UDP packet that is destined for the local endpoint
  1261. // of some other mapping ("loose source matching")
  1262. //
  1263. MAKE_MAPPING_KEY(
  1264. SourceKey[NatForwardPath],
  1265. Protocol,
  1266. Contextp->SourceAddress,
  1267. SourcePort
  1268. );
  1269. MAKE_MAPPING_KEY(
  1270. DestinationKey[NatForwardPath],
  1271. Protocol,
  1272. Contextp->DestinationAddress,
  1273. DestinationPort
  1274. );
  1275. if (Interfacep) {
  1276. TicketProcessingOnly = FALSE;
  1277. } else {
  1278. //
  1279. // We only reach this point if a ticket exists and we want to check
  1280. // if it applies to this packet even though this packet was not
  1281. // received on this interface. We now scan the interface list
  1282. // (again) to see if we can find one which has this ticket.
  1283. //
  1284. KeAcquireSpinLockAtDpcLevel(&InterfaceLock);
  1285. for (Link = InterfaceList.Flink; Link != &InterfaceList;
  1286. Link = Link->Flink) {
  1287. Interfacep = CONTAINING_RECORD(Link, NAT_INTERFACE, Link);
  1288. if (NAT_INTERFACE_DELETED(Interfacep) ||
  1289. IsListEmpty(&Interfacep->TicketList)) {
  1290. Interfacep = NULL;
  1291. continue;
  1292. }
  1293. KeAcquireSpinLockAtDpcLevel(&Interfacep->Lock);
  1294. if (NatLookupTicket(
  1295. Interfacep,
  1296. DestinationKey[NatForwardPath],
  1297. SourceKey[NatForwardPath],
  1298. NULL
  1299. )) {
  1300. //
  1301. // This interface has a ticket for the packet;
  1302. // make a reference to it and end the search.
  1303. //
  1304. KeReleaseSpinLockFromDpcLevel(&Interfacep->Lock);
  1305. NatReferenceInterface(Interfacep);
  1306. break;
  1307. }
  1308. KeReleaseSpinLockFromDpcLevel(&Interfacep->Lock);
  1309. Interfacep = NULL;
  1310. }
  1311. KeReleaseSpinLockFromDpcLevel(&InterfaceLock);
  1312. if (!Interfacep) { return act; }
  1313. TicketProcessingOnly = TRUE;
  1314. }
  1315. Mapping = NULL;
  1316. do {
  1317. //
  1318. // First see if we can quickly determine that this packet won't
  1319. // meet any of the allow in criteria.
  1320. //
  1321. if (!TicketCount
  1322. && Interfacep->NoStaticMappingExists
  1323. && NAT_PROTOCOL_UDP != Protocol
  1324. ) {
  1325. //
  1326. // There's no way for this packet to meet any of the criteria
  1327. // that would allow it in:
  1328. // a) no tickets exist
  1329. // b) no static mappings exist for this interface
  1330. // c) it's not a UDP packet, and thus cannot be a unicast DHCP
  1331. // response. nor will it match a local UDP session endpoint
  1332. //
  1333. NatDereferenceInterface(Interfacep);
  1334. return act;
  1335. }
  1336. //
  1337. // See if a ticket exists which applies to this session.
  1338. //
  1339. KeAcquireSpinLockAtDpcLevel(&Interfacep->Lock);
  1340. if (!IsListEmpty(&Interfacep->TicketList)) {
  1341. status =
  1342. NatLookupAndRemoveTicket(
  1343. Interfacep,
  1344. DestinationKey[NatForwardPath],
  1345. SourceKey[NatForwardPath],
  1346. &Addressp,
  1347. &NewDestinationAddress,
  1348. &NewDestinationPort
  1349. );
  1350. if (NT_SUCCESS(status)) {
  1351. KeReleaseSpinLockFromDpcLevel(&Interfacep->Lock);
  1352. //
  1353. // A ticket was found. Create a mapping for it.
  1354. //
  1355. TRACE(
  1356. XLATE, (
  1357. "NatpReceivePacket: using ticket to %d.%d.%d.%d/%d\n",
  1358. ADDRESS_BYTES(NewDestinationAddress),
  1359. NTOHS(NewDestinationPort)
  1360. ));
  1361. MAKE_MAPPING_KEY(
  1362. SourceKey[NatReversePath],
  1363. Protocol,
  1364. NewDestinationAddress,
  1365. NewDestinationPort
  1366. );
  1367. MAKE_MAPPING_KEY(
  1368. DestinationKey[NatReversePath],
  1369. Protocol,
  1370. Contextp->SourceAddress,
  1371. SourcePort
  1372. );
  1373. KeAcquireSpinLockAtDpcLevel(&MappingLock);
  1374. status =
  1375. NatCreateMapping(
  1376. NAT_MAPPING_FLAG_INBOUND,
  1377. DestinationKey,
  1378. SourceKey,
  1379. Interfacep,
  1380. Addressp,
  1381. MaxMSS,
  1382. NULL,
  1383. NULL,
  1384. NULL,
  1385. NULL,
  1386. &Mapping
  1387. );
  1388. KeReleaseSpinLockFromDpcLevel(&MappingLock);
  1389. if (!NT_SUCCESS(status)) {
  1390. NatDereferenceInterface(Interfacep);
  1391. return act;
  1392. }
  1393. //
  1394. // We have a mapping now in 'Mapping';
  1395. // Drop to the translation code below.
  1396. //
  1397. TicketProcessingOnly = FALSE;
  1398. break;
  1399. }
  1400. //
  1401. // No ticket, or failure creating mapping.
  1402. // Try other possibilities.
  1403. //
  1404. } // !IsListEmpty(TicketList)
  1405. //
  1406. // If we only reached this point because of a ticket,
  1407. // stop here, since the packet was not really received on
  1408. // 'Interfacep'.
  1409. //
  1410. if (TicketProcessingOnly) {
  1411. KeReleaseSpinLockFromDpcLevel(&Interfacep->Lock);
  1412. NatDereferenceInterface(Interfacep);
  1413. return act;
  1414. }
  1415. //
  1416. // Since this is an inbound packet, we now look for
  1417. // a static-address mapping which allows inbound sessions.
  1418. //
  1419. if ((Addressp =
  1420. NatLookupStaticAddressPoolEntry(
  1421. Interfacep,
  1422. Contextp->DestinationAddress,
  1423. TRUE
  1424. ))
  1425. && NatReferenceAddressPoolEntry(Addressp)) {
  1426. KeReleaseSpinLockFromDpcLevel(&Interfacep->Lock);
  1427. TRACE(
  1428. XLATE, (
  1429. "NatpReceivePacket: using static address to %d.%d.%d.%d/%d\n",
  1430. ADDRESS_BYTES(Addressp->PrivateAddress),
  1431. NTOHS(DestinationPort)
  1432. ));
  1433. MAKE_MAPPING_KEY(
  1434. SourceKey[NatReversePath],
  1435. Protocol,
  1436. Addressp->PrivateAddress,
  1437. DestinationPort
  1438. );
  1439. MAKE_MAPPING_KEY(
  1440. DestinationKey[NatReversePath],
  1441. Protocol,
  1442. Contextp->SourceAddress,
  1443. SourcePort
  1444. );
  1445. //
  1446. // We will allow the packet through if we can reserve
  1447. // its destination port, i.e. if no existing session
  1448. // from the same remote endpoint is using that destination.
  1449. // Initialize a new dynamic mapping for the packet,
  1450. // and note that this will fail if such a duplicate exists.
  1451. //
  1452. KeAcquireSpinLockAtDpcLevel(&MappingLock);
  1453. status =
  1454. NatCreateMapping(
  1455. NAT_MAPPING_FLAG_INBOUND,
  1456. DestinationKey,
  1457. SourceKey,
  1458. Interfacep,
  1459. Addressp,
  1460. MaxMSS,
  1461. NULL,
  1462. NULL,
  1463. NULL,
  1464. NULL,
  1465. &Mapping
  1466. );
  1467. KeReleaseSpinLockFromDpcLevel(&MappingLock);
  1468. if (!NT_SUCCESS(status)) {
  1469. NatDereferenceInterface(Interfacep);
  1470. return act;
  1471. }
  1472. //
  1473. // On reaching here, we will have created a mapping
  1474. // from a static address mapping.
  1475. //
  1476. break;
  1477. }
  1478. //
  1479. // If this is a UDP packet, see if its destination matches
  1480. // the public endpoint of an already existing mapping (i.e.,
  1481. // perform a mapping lookup ignoring the packet's source
  1482. // address and port).
  1483. //
  1484. if (NAT_PROTOCOL_UDP == Protocol) {
  1485. ULONG PrivateAddress;
  1486. USHORT PrivatePort;
  1487. KeReleaseSpinLockFromDpcLevel(&Interfacep->Lock);
  1488. KeAcquireSpinLockAtDpcLevel(&MappingLock);
  1489. //
  1490. // First search for a forward path (sessions that
  1491. // were originally outbound) match.
  1492. //
  1493. Mapping =
  1494. NatDestinationLookupForwardMapping(
  1495. DestinationKey[NatForwardPath]
  1496. );
  1497. if (NULL == Mapping) {
  1498. //
  1499. // No forward path match was found; attempt to
  1500. // locate a reverse path (sessions that were
  1501. // originally inbound) match.
  1502. //
  1503. Mapping =
  1504. NatDestinationLookupReverseMapping(
  1505. DestinationKey[NatForwardPath]
  1506. );
  1507. }
  1508. if (NULL != Mapping) {
  1509. IP_NAT_PATH Path;
  1510. //
  1511. // Determine the private address and port
  1512. //
  1513. Path =
  1514. NAT_MAPPING_INBOUND(Mapping)
  1515. ? NatReversePath
  1516. : NatForwardPath;
  1517. PrivateAddress = MAPPING_ADDRESS(Mapping->SourceKey[Path]);
  1518. PrivatePort = MAPPING_PORT(Mapping->SourceKey[Path]);
  1519. }
  1520. KeReleaseSpinLockFromDpcLevel(&MappingLock);
  1521. if (NULL != Mapping
  1522. && NTOHS(PrivatePort) > NAT_XLATE_UDP_LSM_LOW_PORT) {
  1523. //
  1524. // A partial-match mapping exists, and the private port
  1525. // is within the allowed rage. Get the address
  1526. // object for the private endpoint
  1527. //
  1528. KeAcquireSpinLockAtDpcLevel(&Interfacep->Lock);
  1529. status =
  1530. NatAcquireFromAddressPool(
  1531. Interfacep,
  1532. PrivateAddress,
  1533. MAPPING_ADDRESS(DestinationKey[NatForwardPath]),
  1534. &Addressp
  1535. );
  1536. KeReleaseSpinLockFromDpcLevel(&Interfacep->Lock);
  1537. if (NT_SUCCESS(status)) {
  1538. //
  1539. // Create the new mapping.
  1540. //
  1541. TRACE(
  1542. XLATE, (
  1543. "NatpReceivePacket: UDP LSM to %d.%d.%d.%d/%d\n",
  1544. ADDRESS_BYTES(PrivateAddress),
  1545. NTOHS(PrivatePort)
  1546. ));
  1547. MAKE_MAPPING_KEY(
  1548. SourceKey[NatReversePath],
  1549. Protocol,
  1550. PrivateAddress,
  1551. PrivatePort
  1552. );
  1553. MAKE_MAPPING_KEY(
  1554. DestinationKey[NatReversePath],
  1555. Protocol,
  1556. Contextp->SourceAddress,
  1557. SourcePort
  1558. );
  1559. KeAcquireSpinLockAtDpcLevel(&MappingLock);
  1560. status =
  1561. NatCreateMapping(
  1562. NAT_MAPPING_FLAG_INBOUND,
  1563. DestinationKey,
  1564. SourceKey,
  1565. Interfacep,
  1566. Addressp,
  1567. 0,
  1568. NULL,
  1569. NULL,
  1570. NULL,
  1571. NULL,
  1572. &Mapping
  1573. );
  1574. KeReleaseSpinLockFromDpcLevel(&MappingLock);
  1575. if (!NT_SUCCESS(status)) {
  1576. NatDereferenceInterface(Interfacep);
  1577. return act;
  1578. }
  1579. //
  1580. // On reaching here, we will have created a mapping
  1581. // due to a loose UDP source match.
  1582. //
  1583. break;
  1584. }
  1585. }
  1586. //
  1587. // The code below assumes that this lock is held.
  1588. //
  1589. KeAcquireSpinLockAtDpcLevel(&Interfacep->Lock);
  1590. }
  1591. //
  1592. // Check if this is may be a DHCP response packet. If the
  1593. // request that elicited this response was broadcast we
  1594. // won't have a corresponding mapping to allow the packet
  1595. // in; dropping the packet, though, will cause connectivity
  1596. // problems.
  1597. //
  1598. if (NAT_PROTOCOL_UDP == Protocol
  1599. && NTOHS(DHCP_SERVER_PORT) == SourcePort
  1600. && NTOHS(DHCP_CLIENT_PORT) == DestinationPort
  1601. && NAT_INTERFACE_FW(Interfacep)) {
  1602. //
  1603. // What appears to be a unicast DHCP response was received
  1604. // on a firewalled interface. We need to always let such
  1605. // packets through to prevent an interruption in network
  1606. // connectivity.
  1607. //
  1608. act = FORWARD;
  1609. }
  1610. //
  1611. // This packet doesn't meet any criteria that allow for
  1612. // the creation of a mapping. Return the default action.
  1613. //
  1614. KeReleaseSpinLockFromDpcLevel(&Interfacep->Lock);
  1615. NatDereferenceInterface(Interfacep);
  1616. return act;
  1617. } while (FALSE); // !Mapping
  1618. if (Interfacep) { NatDereferenceInterface(Interfacep); }
  1619. //
  1620. // Somewhere above a mapping was found or created.
  1621. // Translate the packet using that mapping
  1622. //
  1623. act =
  1624. Mapping->TranslateRoutine[NatForwardPath](
  1625. Mapping,
  1626. Contextp,
  1627. InReceiveBuffer,
  1628. OutReceiveBuffer
  1629. );
  1630. //
  1631. // Release our reference on the mapping and the interface
  1632. //
  1633. NatDereferenceMapping(Mapping);
  1634. return act;
  1635. } // TranslateRoutine != NatTranslatePacket
  1636. //
  1637. // This is neither a TCP nor a UDP packet.
  1638. // If it is coming in on a boundary interface, translate it;
  1639. // otherwise let it pass through unscathed.
  1640. //
  1641. // N.B. The translation routine must be invoked with a reference made
  1642. // to the boundary interface, and without holding the mapping lock.
  1643. //
  1644. if (TranslateRoutine) {
  1645. act =
  1646. TranslateRoutine(
  1647. Interfacep,
  1648. NatInboundDirection,
  1649. Contextp,
  1650. InReceiveBuffer,
  1651. OutReceiveBuffer
  1652. );
  1653. }
  1654. if (Interfacep) { NatDereferenceInterface(Interfacep); }
  1655. return act;
  1656. } // NatpReceivePacket
  1657. NTSTATUS
  1658. NatpRouteChangeCompletionRoutine(
  1659. PDEVICE_OBJECT DeviceObject,
  1660. PIRP Irp,
  1661. PVOID Context
  1662. )
  1663. /*++
  1664. Routine Description:
  1665. This routine is invoked by the I/O manager upon completion of
  1666. a route-change-notification request. It invalidates our route-cache and,
  1667. unless shutdown is in progress, re-issues the route-change-notification
  1668. request.
  1669. Arguments:
  1670. DeviceObject - the device object of the IP driver
  1671. Irp - the completed I/O request packet
  1672. Context - unused
  1673. Return Value:
  1674. STATUS_MORE_PROCESSING_REQUIRED - indication that the IRP should be freed.
  1675. --*/
  1676. {
  1677. PIO_STACK_LOCATION IrpSp;
  1678. KIRQL Irql;
  1679. NTSTATUS status;
  1680. CALLTRACE(("NatpRouteChangeCompletionRoutine\n"));
  1681. //
  1682. // Invalidate the entire route-cache.
  1683. //
  1684. KeAcquireSpinLock(&RouteCacheLock, &Irql);
  1685. InitializeCache(RouteCache);
  1686. //
  1687. // If we cannot re-reference the module, relinquish the IRP.
  1688. //
  1689. if (!RouteCacheIrp || !REFERENCE_NAT()) {
  1690. KeReleaseSpinLock(&RouteCacheLock, Irql);
  1691. DEREFERENCE_NAT_AND_RETURN(STATUS_SUCCESS);
  1692. }
  1693. Irp->Cancel = FALSE;
  1694. KeReleaseSpinLock(&RouteCacheLock, Irql);
  1695. //
  1696. // Reinitialize the IRP structure and submit it again
  1697. // for further notification.
  1698. //
  1699. Irp->IoStatus.Status = 0;
  1700. Irp->IoStatus.Information = 0;
  1701. Irp->AssociatedIrp.SystemBuffer = NULL;
  1702. IoSetCompletionRoutine(
  1703. Irp,
  1704. NatpRouteChangeCompletionRoutine,
  1705. NULL,
  1706. TRUE,
  1707. TRUE,
  1708. TRUE
  1709. );
  1710. IrpSp = IoGetNextIrpStackLocation(Irp);
  1711. IrpSp->MajorFunction = IRP_MJ_DEVICE_CONTROL;
  1712. IrpSp->Parameters.DeviceIoControl.IoControlCode =
  1713. IOCTL_IP_RTCHANGE_NOTIFY_REQUEST;
  1714. IrpSp->Parameters.DeviceIoControl.InputBufferLength = 0;
  1715. IrpSp->Parameters.DeviceIoControl.OutputBufferLength = 0;
  1716. status = IoCallDriver(IpDeviceObject, Irp);
  1717. if (!NT_SUCCESS(status)) {
  1718. ERROR(("NatpRouteChangeWorkerRoutine: IoCallDriver=0x%08X\n", status));
  1719. }
  1720. DEREFERENCE_NAT_AND_RETURN(STATUS_MORE_PROCESSING_REQUIRED);
  1721. } // NatpRouteChangeCompletionRoutine
  1722. ULONG
  1723. FASTCALL
  1724. NatpRoutePacket(
  1725. ULONG DestinationAddress,
  1726. PNAT_XLATE_CONTEXT Contextp,
  1727. PNTSTATUS Status
  1728. )
  1729. /*++
  1730. Routine Description:
  1731. This routine is invoked to determine the index of the outgoing adapter
  1732. for a given source/destination pair.
  1733. It attempts to retrieve the required information from our route-table
  1734. cache, and if unsuccessful consults the IP routing tables.
  1735. Arguments:
  1736. DestinationAddress - the destination address for the packet
  1737. Contextp - optionally supplies the context of the packet on whose
  1738. behalf a route-lookup is being requested. If demand-dial were required
  1739. in order to forward the packet, this data would be needed in order
  1740. for demand-dial filters to function correctly.
  1741. Status - receives the status of the lookup in the event of a failure
  1742. Return Value:
  1743. ULONG - the index of the outgoing interface, or INVALID_IF_INDEX if none.
  1744. --*/
  1745. {
  1746. PUCHAR Buffer;
  1747. ULONG BufferLength;
  1748. PNAT_CACHED_ROUTE CachedRoute;
  1749. ULONG Index;
  1750. KIRQL Irql;
  1751. ULONG Length;
  1752. IPRouteLookupData RouteLookupData;
  1753. TRACE(PER_PACKET, ("NatpRoutePacket\n"));
  1754. //
  1755. // Probe the cache for the destination IP address specified.
  1756. //
  1757. KeAcquireSpinLock(&RouteCacheLock, &Irql);
  1758. if ((CachedRoute = ProbeCache(RouteCache, DestinationAddress)) &&
  1759. CachedRoute->DestinationAddress == DestinationAddress) {
  1760. Index = CachedRoute->Index;
  1761. KeReleaseSpinLock(&RouteCacheLock, Irql);
  1762. TRACE(PER_PACKET, ("NatpRoutePacket: cache hit\n"));
  1763. return Index;
  1764. }
  1765. KeReleaseSpinLockFromDpcLevel(&RouteCacheLock);
  1766. //
  1767. // The cache did not have the value requested,
  1768. // so consult the TCP/IP driver directly.
  1769. //
  1770. RouteLookupData.Version = 0;
  1771. RouteLookupData.DestAdd = DestinationAddress;
  1772. if (Contextp) {
  1773. RouteLookupData.SrcAdd = Contextp->SourceAddress;
  1774. RouteLookupData.Info[0] = (Contextp->Header)->Protocol;
  1775. if (NAT_PROTOCOL_TCP == RouteLookupData.Info[0]) {
  1776. Buffer = Contextp->ProtocolHeader;
  1777. BufferLength = sizeof(TCP_HEADER);
  1778. } else if (NAT_PROTOCOL_UDP == RouteLookupData.Info[0]) {
  1779. Buffer = Contextp->ProtocolHeader;
  1780. BufferLength = sizeof(UDP_HEADER);
  1781. } else if (NAT_PROTOCOL_ICMP == RouteLookupData.Info[0]) {
  1782. Buffer = Contextp->ProtocolHeader;
  1783. BufferLength = sizeof(ICMP_HEADER);
  1784. } else {
  1785. Buffer = Contextp->RecvBuffer->ipr_buffer;
  1786. BufferLength = Contextp->RecvBuffer->ipr_size;
  1787. }
  1788. } else {
  1789. RouteLookupData.SrcAdd = 0;
  1790. Buffer = NULL;
  1791. BufferLength = 0;
  1792. }
  1793. Length = sizeof(Index);
  1794. *Status =
  1795. LookupRouteInformationWithBuffer(
  1796. &RouteLookupData,
  1797. Buffer,
  1798. BufferLength,
  1799. NULL,
  1800. IPRouteOutgoingFirewallContext,
  1801. &Index,
  1802. &Length
  1803. );
  1804. if (!NT_SUCCESS(*Status) || *Status == STATUS_PENDING) {
  1805. KeLowerIrql(Irql);
  1806. return INVALID_IF_INDEX;
  1807. }
  1808. //
  1809. // Update the cache with the entry retrieved,
  1810. // assuming we've had enough misses to warrant
  1811. // replacement of the cache-index's current contents.
  1812. //
  1813. KeAcquireSpinLockAtDpcLevel(&RouteCacheLock);
  1814. CachedRoute = &RouteCacheTable[CACHE_INDEX(DestinationAddress)];
  1815. if (UpdateCache(RouteCache, DestinationAddress, CachedRoute)) {
  1816. CachedRoute->DestinationAddress = DestinationAddress;
  1817. CachedRoute->Index = Index;
  1818. }
  1819. KeReleaseSpinLock(&RouteCacheLock, Irql);
  1820. return Index;
  1821. } // NatpRoutePacket
  1822. FORWARD_ACTION
  1823. NatpSendNonUnicastPacket(
  1824. ULONG Index,
  1825. PNAT_XLATE_CONTEXT Contextp
  1826. )
  1827. /*++
  1828. Routine Description:
  1829. This routine is invoked to process locally sent non-unicast packets.
  1830. If the packet is to be sent on a firewalled interface it must have a valid
  1831. source address for that interface.
  1832. Arguments:
  1833. Index - index of the interface on which the packet is to be sent
  1834. Contextp - the context for this packet
  1835. Return Value:
  1836. FORWARD_ACTION - indicates whether to 'FORWARD' or 'DROP' the packet.
  1837. --*/
  1838. {
  1839. FORWARD_ACTION act;
  1840. PNAT_INTERFACE Interfacep;
  1841. ULONG i;
  1842. KIRQL Irql;
  1843. TRACE(PER_PACKET, ("NatpSendNonUnicastPacket\n"));
  1844. KeAcquireSpinLock(&InterfaceLock, &Irql);
  1845. if (!NatLookupCachedInterface(Index, Interfacep)
  1846. || !NAT_INTERFACE_FW(Interfacep)) {
  1847. //
  1848. // The packet is not to be sent on a firewalled interface
  1849. //
  1850. KeReleaseSpinLock(&InterfaceLock, Irql);
  1851. act = FORWARD;
  1852. } else {
  1853. NatReferenceInterface(Interfacep);
  1854. KeReleaseSpinLock(&InterfaceLock, Irql);
  1855. //
  1856. // Make sure the packet has a valid source address
  1857. //
  1858. act = DROP;
  1859. if (Interfacep->AddressArray[0].Address == Contextp->SourceAddress) {
  1860. act = FORWARD;
  1861. } else {
  1862. for (i = 1; i < Interfacep->AddressCount; i++) {
  1863. if (Contextp->SourceAddress ==
  1864. Interfacep->AddressArray[i].Address) {
  1865. act = FORWARD;
  1866. break;
  1867. }
  1868. }
  1869. }
  1870. if (DROP == act
  1871. && 0 == Contextp->SourceAddress
  1872. && NAT_PROTOCOL_UDP == Contextp->Header->Protocol
  1873. && NTOHS(DHCP_CLIENT_PORT) ==
  1874. ((PUDP_HEADER)Contextp->ProtocolHeader)->SourcePort
  1875. && NTOHS(DHCP_SERVER_PORT) ==
  1876. ((PUDP_HEADER)Contextp->ProtocolHeader)->DestinationPort) {
  1877. //
  1878. // This appears to be a DHCP request sent from an adapter that
  1879. // has a non-DHCP allocated address (e.g., an autonet address). In
  1880. // this situation the DHCP client will use a source address of
  1881. // 0.0.0.0. These packets should always be forwarded.
  1882. //
  1883. act = FORWARD;
  1884. }
  1885. NatDereferenceInterface(Interfacep);
  1886. }
  1887. return act;
  1888. } // NatpSendNonUnicastPacket
  1889. FORWARD_ACTION
  1890. NatpSendPacket(
  1891. ULONG Index,
  1892. PNAT_XLATE_CONTEXT Contextp,
  1893. PNAT_IP_TRANSLATE_ROUTINE TranslateRoutine,
  1894. IPRcvBuf** InReceiveBuffer,
  1895. IPRcvBuf** OutReceiveBuffer
  1896. )
  1897. /*++
  1898. Routine Description:
  1899. This routine is invoked to process locally generated packets.
  1900. Most locally-generated packets do not require translation at all.
  1901. The exceptions arise with applications that bind to a private IP address
  1902. but then send packets to the public network, as well as with certain
  1903. applications (PPTP, ICMP) which must be forced through the translation
  1904. path to ensure that certain fields are unique for all sessions sharing
  1905. the public IP address(es). (E.g. the PPTP GRE call-identifier.)
  1906. Arguments:
  1907. Index - the interface on which the packet is to be sent
  1908. DestinationType - receives 'DEST_INVALID' if destination changed
  1909. TranslateRoutine - points to the routine which performs translation
  1910. InReceiveBuffer - points to the packet buffer chain
  1911. OutReceiveBuffer - receives the packet buffer chain if translation occurs
  1912. Return Value:
  1913. FORWARD_ACTION - indicates whether to 'FORWARD' or 'DROP' the packet.
  1914. --*/
  1915. {
  1916. FORWARD_ACTION act;
  1917. PNAT_USED_ADDRESS Addressp;
  1918. ULONG64 DestinationKey[NatMaximumPath];
  1919. USHORT DestinationPort;
  1920. ULONG i;
  1921. PNAT_DYNAMIC_MAPPING InsertionPoint;
  1922. PNAT_INTERFACE Interfacep;
  1923. KIRQL Irql;
  1924. PNAT_DYNAMIC_MAPPING Mapping;
  1925. USHORT PortAcquired;
  1926. UCHAR Protocol;
  1927. ULONG64 SourceKey[NatMaximumPath];
  1928. USHORT SourcePort;
  1929. NTSTATUS status;
  1930. TRACE(PER_PACKET, ("NatpSendPacket\n"));
  1931. //
  1932. // Look up the sending interface, and set the default action
  1933. // in 'act'. If the packet's source address is not on the sending interface,
  1934. // then we must translate it like any other outbound packet.
  1935. // Otherwise, we may let the packet through unchanged, so long as
  1936. // there is no mapping for it created by a director.
  1937. // N.B. We record the original IRQL since local-sends are not guaranteed
  1938. // to be passed to us at dispatch level.
  1939. //
  1940. KeAcquireSpinLock(&InterfaceLock, &Irql);
  1941. if (!NatLookupCachedInterface(Index, Interfacep) ||
  1942. (!NAT_INTERFACE_BOUNDARY(Interfacep)
  1943. && !NAT_INTERFACE_FW(Interfacep))) {
  1944. //
  1945. // This packet is not being sent on a boundary or firewalled interface,
  1946. // so we won't normally translate it.
  1947. //
  1948. // However, a special case arises when a local MTU mismatch results in
  1949. // the forwarder generating an ICMP path MTU error message.
  1950. // The forwarder generates the error based on the *translated* packet
  1951. // which has the public IP address as its source, and so the error
  1952. // ends up being sent on the loopback interface to the local machine.
  1953. // When we see an ICMP message on the loopback interface, give the
  1954. // ICMP translator a chance to modify it *if there are any mappings*.
  1955. //
  1956. if (LoopbackIndex == Index &&
  1957. TranslateRoutine == NatTranslateIcmp &&
  1958. MappingCount) {
  1959. KeReleaseSpinLockFromDpcLevel(&InterfaceLock);
  1960. act =
  1961. NatTranslateIcmp(
  1962. NULL,
  1963. NatInboundDirection,
  1964. Contextp,
  1965. InReceiveBuffer,
  1966. OutReceiveBuffer
  1967. );
  1968. KeLowerIrql(Irql);
  1969. return act;
  1970. } else {
  1971. KeReleaseSpinLock(&InterfaceLock, Irql);
  1972. return FORWARD;
  1973. }
  1974. }
  1975. NatReferenceInterface(Interfacep);
  1976. KeReleaseSpinLockFromDpcLevel(&InterfaceLock);
  1977. Protocol = Contextp->Header->Protocol;
  1978. if (Interfacep->AddressArray[0].Address == Contextp->SourceAddress) {
  1979. act = FORWARD;
  1980. } else {
  1981. //
  1982. // The outgoing interface is a boundary interface.
  1983. // This means that if the packet's source-address is the address
  1984. // of an interface other than 'Interfacep', it is a private address,
  1985. // and we'll need to discard the packet if it cannot be translated.
  1986. // Therefore, see whether the packet's source-address is public.
  1987. //
  1988. act = DROP;
  1989. for (i = 1; i < Interfacep->AddressCount; i++) {
  1990. if (Contextp->SourceAddress ==
  1991. Interfacep->AddressArray[i].Address) {
  1992. //
  1993. // The packet's source-address is public,
  1994. // so the packet will be allowed to go out untranslated.
  1995. //
  1996. act = FORWARD;
  1997. break;
  1998. }
  1999. }
  2000. }
  2001. //
  2002. // If the packet's source-address is not private, we can avoid
  2003. // translating it unless
  2004. // (a) it's an ICMP packet
  2005. // (b) it's a PPTP data packet
  2006. // (c) it's a PPTP control-session packet.
  2007. // (d) the interface is in FW mode -- need to generate a mapping so
  2008. // that inbound packets for this connection won't be dropped
  2009. //
  2010. if (act == FORWARD &&
  2011. !NAT_INTERFACE_FW(Interfacep) &&
  2012. Protocol != NAT_PROTOCOL_ICMP &&
  2013. Protocol != NAT_PROTOCOL_PPTP &&
  2014. (Protocol != NAT_PROTOCOL_TCP ||
  2015. ((PUSHORT)Contextp->ProtocolHeader)[1] != NTOHS(PPTP_CONTROL_PORT))) {
  2016. KeLowerIrql(Irql);
  2017. NatDereferenceInterface(Interfacep);
  2018. return FORWARD;
  2019. }
  2020. //
  2021. // The packet may require some form of translation.
  2022. //
  2023. if ((PVOID)TranslateRoutine == (PVOID)NatTranslatePacket) {
  2024. SourcePort = ((PUSHORT)Contextp->ProtocolHeader)[0];
  2025. DestinationPort = ((PUSHORT)Contextp->ProtocolHeader)[1];
  2026. //
  2027. // The packet is either TCP or UDP.
  2028. // Generate a mapping for the packet's session.
  2029. //
  2030. MAKE_MAPPING_KEY(
  2031. SourceKey[NatForwardPath],
  2032. Protocol,
  2033. Contextp->SourceAddress,
  2034. SourcePort
  2035. );
  2036. MAKE_MAPPING_KEY(
  2037. DestinationKey[NatForwardPath],
  2038. Protocol,
  2039. Contextp->DestinationAddress,
  2040. DestinationPort
  2041. );
  2042. //
  2043. // Acquire an endpoint for the mapping. If the interface
  2044. // is in FW mode and act == FORWARD, however, we only
  2045. // want to get the address structure corresponding to the
  2046. // source address of the packet
  2047. //
  2048. KeAcquireSpinLockAtDpcLevel(&MappingLock);
  2049. KeAcquireSpinLockAtDpcLevel(&Interfacep->Lock);
  2050. if(act != FORWARD || !NAT_INTERFACE_FW(Interfacep)) {
  2051. status =
  2052. NatAcquireEndpointFromAddressPool(
  2053. Interfacep,
  2054. SourceKey[NatForwardPath],
  2055. DestinationKey[NatForwardPath],
  2056. 0,
  2057. MAPPING_PORT(SourceKey[NatForwardPath]),
  2058. TRUE,
  2059. &Addressp,
  2060. &PortAcquired
  2061. );
  2062. } else {
  2063. PortAcquired = SourcePort;
  2064. status =
  2065. NatAcquireFromAddressPool(
  2066. Interfacep,
  2067. Contextp->SourceAddress,
  2068. Contextp->SourceAddress,
  2069. &Addressp
  2070. );
  2071. }
  2072. KeReleaseSpinLockFromDpcLevel(&Interfacep->Lock);
  2073. if (!NT_SUCCESS(status)) {
  2074. KeReleaseSpinLock(&MappingLock, Irql);
  2075. ExInterlockedAddLargeStatistic(
  2076. (PLARGE_INTEGER)&Interfacep->Statistics.RejectsForward, 1
  2077. );
  2078. NatDereferenceInterface(Interfacep);
  2079. return DROP;
  2080. }
  2081. MAKE_MAPPING_KEY(
  2082. SourceKey[NatReversePath],
  2083. Protocol,
  2084. Contextp->DestinationAddress,
  2085. DestinationPort
  2086. );
  2087. MAKE_MAPPING_KEY(
  2088. DestinationKey[NatReversePath],
  2089. Protocol,
  2090. Addressp->PublicAddress,
  2091. PortAcquired
  2092. );
  2093. //
  2094. // Allocate a mapping.
  2095. //
  2096. status =
  2097. NatCreateMapping(
  2098. 0,
  2099. DestinationKey,
  2100. SourceKey,
  2101. Interfacep,
  2102. (PVOID)Addressp,
  2103. 0,
  2104. NULL,
  2105. NULL,
  2106. NULL,
  2107. NULL,
  2108. &Mapping
  2109. );
  2110. KeReleaseSpinLockFromDpcLevel(&MappingLock);
  2111. if (!NT_SUCCESS(status)) {
  2112. KeLowerIrql(Irql);
  2113. ExInterlockedAddLargeStatistic(
  2114. (PLARGE_INTEGER)&Interfacep->Statistics.RejectsForward, 1
  2115. );
  2116. NatDereferenceInterface(Interfacep);
  2117. return DROP;
  2118. }
  2119. //
  2120. // Activate any applicable dynamic tickets
  2121. //
  2122. if (DynamicTicketCount) {
  2123. NatLookupAndApplyDynamicTicket(
  2124. Protocol,
  2125. DestinationPort,
  2126. Interfacep,
  2127. Addressp->PublicAddress,
  2128. Contextp->SourceAddress
  2129. );
  2130. }
  2131. //
  2132. // Perform the actual translation
  2133. // This replaces the source endpoint with a globally-valid
  2134. // endpoint.
  2135. //
  2136. act =
  2137. Mapping->TranslateRoutine[NatForwardPath](
  2138. Mapping,
  2139. Contextp,
  2140. InReceiveBuffer,
  2141. OutReceiveBuffer
  2142. );
  2143. //
  2144. // Release our reference on the mapping and the interface
  2145. //
  2146. KeLowerIrql(Irql);
  2147. NatDereferenceMapping(Mapping);
  2148. NatDereferenceInterface(Interfacep);
  2149. return act;
  2150. } // TranslateRoutine != NatTranslatePacket
  2151. //
  2152. // Perform ICMP/PPTP translation.
  2153. //
  2154. // N.B. The translation routine must be invoked with a reference made
  2155. // to the boundary interface, and without holding the mapping lock.
  2156. //
  2157. if (TranslateRoutine) {
  2158. act =
  2159. TranslateRoutine(
  2160. Interfacep,
  2161. NatOutboundDirection,
  2162. Contextp,
  2163. InReceiveBuffer,
  2164. OutReceiveBuffer
  2165. );
  2166. }
  2167. KeLowerIrql(Irql);
  2168. NatDereferenceInterface(Interfacep);
  2169. return act;
  2170. } // NatpSendPacket
  2171. FORWARD_ACTION
  2172. NatpTranslateLocalTraffic(
  2173. PNAT_INTERFACE Interfacep OPTIONAL,
  2174. IP_NAT_DIRECTION Direction,
  2175. PNAT_XLATE_CONTEXT Contextp,
  2176. IPRcvBuf** InRecvBuffer,
  2177. IPRcvBuf** OutRecvBuffer
  2178. )
  2179. /*++
  2180. Routine Description:
  2181. This routine will forward unmodified traffic that is either:
  2182. * received by the local machine
  2183. * sent by the local machine
  2184. Arguments:
  2185. Interfacep - the boundary interface over which to translate, or NULL
  2186. if the packet is inbound and the receiving interface has not been
  2187. added to the NAT.
  2188. Direction - the direction in which the packet is traveling
  2189. Contextp - initialized with context-information for the packet
  2190. InRecvBuffer - input buffer-chain
  2191. OutRecvBuffer - receives modified buffer-chain.
  2192. Return Value:
  2193. FORWARD_ACTION - indicates action to take on packet.
  2194. Environment:
  2195. Invoked with a reference made to 'Interfacep' by the caller.
  2196. --*/
  2197. {
  2198. FORWARD_ACTION act;
  2199. ULONG i;
  2200. TRACE(PER_PACKET, ("NatpTranslateLocalTraffic\n"));
  2201. if (NatInboundDirection == Direction) {
  2202. //
  2203. // Inbound traffic must be directed to the local machine, and thus
  2204. // is always forwarded.
  2205. //
  2206. act = FORWARD;
  2207. } else {
  2208. //
  2209. // This is an outgoing packet. We only allow packets that have the
  2210. // same source address as the interface that they are being sent
  2211. // on. This prevents a packet from the private network from being
  2212. // sent to the public network.
  2213. //
  2214. if (Interfacep->AddressArray[0].Address == Contextp->SourceAddress) {
  2215. act = FORWARD;
  2216. } else {
  2217. act = DROP;
  2218. for (i = 1; i < Interfacep->AddressCount; i++) {
  2219. if (Contextp->SourceAddress ==
  2220. Interfacep->AddressArray[i].Address) {
  2221. //
  2222. // The packet's source-address is valid,
  2223. // so the packet will be allowed to go out.
  2224. //
  2225. act = FORWARD;
  2226. break;
  2227. }
  2228. }
  2229. }
  2230. }
  2231. return act;
  2232. } // NatpTranslateLocalTraffic
  2233. FORWARD_ACTION
  2234. NatReverseTcpStateCheck(
  2235. PNAT_DYNAMIC_MAPPING pMapping,
  2236. PTCP_HEADER pTcpHeader
  2237. )
  2238. /*++
  2239. Routine Description:
  2240. This routine validates that packets for a TCP passive open are valid:
  2241. -- only SYN/ACK (or RST) at first
  2242. -- no SYN after connection is opened (ACK of SYN/ACK)
  2243. Arguments:
  2244. pMapping -- the mapping this packet belongs to
  2245. pTcpHeader -- the TCP header of the packet
  2246. Return Value:
  2247. FORWARD_ACTION - indicates whether to 'FORWARD' or 'DROP' the packet.
  2248. Environment:
  2249. Invoked with pMapping->Lock held by the caller
  2250. --*/
  2251. {
  2252. USHORT Flags = TCP_ALL_FLAGS(pTcpHeader);
  2253. if (NAT_MAPPING_TCP_OPEN(pMapping)) {
  2254. //
  2255. // Connection open -- SYN not allowed
  2256. //
  2257. return (Flags & TCP_FLAG_SYN) ? DROP : FORWARD;
  2258. } else {
  2259. ASSERT(pMapping->Flags & NAT_MAPPING_FLAG_FWD_SYN);
  2260. //
  2261. // SYN received, can only send SYN/ACK, RST, or ACK/RST
  2262. //
  2263. if (Flags == (TCP_FLAG_SYN | TCP_FLAG_ACK)) {
  2264. pMapping->Flags |= NAT_MAPPING_FLAG_REV_SYN;
  2265. } else if (Flags != TCP_FLAG_RST
  2266. && Flags != (TCP_FLAG_ACK | TCP_FLAG_RST)) {
  2267. return DROP;
  2268. }
  2269. }
  2270. return FORWARD;
  2271. }
  2272. VOID
  2273. NatShutdownPacketManagement(
  2274. VOID
  2275. )
  2276. /*++
  2277. Routine Description:
  2278. This routine is invoked to shutdown the packet-management module.
  2279. Arguments:
  2280. none.
  2281. Return Value:
  2282. none.
  2283. Environment:
  2284. Invoked at passive level.
  2285. --*/
  2286. {
  2287. KIRQL Irql;
  2288. CALLTRACE(("NatShutdownPacketManagement\n"));
  2289. KeAcquireSpinLock(&RouteCacheLock, &Irql);
  2290. if (RouteCacheIrp) {
  2291. PIRP Irp = RouteCacheIrp;
  2292. RouteCacheIrp = NULL;
  2293. KeReleaseSpinLock(&RouteCacheLock, Irql);
  2294. IoCancelIrp(Irp);
  2295. KeAcquireSpinLock(&RouteCacheLock, &Irql);
  2296. }
  2297. KeReleaseSpinLock(&RouteCacheLock, Irql);
  2298. } // NatShutdownPacketManagement
  2299. FORWARD_ACTION
  2300. NatTranslatePacket(
  2301. IPRcvBuf** InReceiveBuffer,
  2302. ULONG ReceiveIndex,
  2303. PULONG SendIndex,
  2304. PUCHAR DestinationType,
  2305. PVOID Unused,
  2306. ULONG UnusedLength,
  2307. IPRcvBuf** OutReceiveBuffer
  2308. )
  2309. /*++
  2310. Routine Description:
  2311. This routine is invoked to translate a packet just received or a packet
  2312. about to be transmitted. This is the entrypoint into the NAT from TCP/IP,
  2313. invoked for every locally-received and locally-generated IP packet,
  2314. including loopback and transit packets. It is therefore critical
  2315. that a decision be made on each packet as early as possible.
  2316. Arguments:
  2317. InReceiveBuffer - points to the packet buffer chain
  2318. ReceiveIndex - index of the adapter on which the packet arrived
  2319. SendIndex - index of the adapter on which the packet is to be sent
  2320. DestinationType - indicates type of packet (broadcast/multicast/unicast)
  2321. Unused - unused
  2322. UnusedLength - unused
  2323. OutReceiveBuffer - receives packet buffer chain if translation occurs.
  2324. Return Value:
  2325. FORWARD_ACTION - indicates whether to 'FORWARD' or 'DROP' the packet.
  2326. --*/
  2327. {
  2328. FORWARD_ACTION act;
  2329. NAT_XLATE_CONTEXT Context;
  2330. ULONG64 DestinationKey;
  2331. PIP_HEADER IpHeader;
  2332. KIRQL Irql;
  2333. ULONG Length;
  2334. USHORT TcpFlags;
  2335. PNAT_DYNAMIC_MAPPING Mapping;
  2336. IPRouteLookupData RouteLookupData;
  2337. ULONG64 SourceKey;
  2338. NTSTATUS status;
  2339. PNAT_IP_TRANSLATE_ROUTINE TranslateRoutine;
  2340. TRACE(
  2341. PER_PACKET, (
  2342. "NatTranslatePacket(r=%d,s=%d,t=%d)\n",
  2343. ReceiveIndex,
  2344. *SendIndex,
  2345. *DestinationType
  2346. ));
  2347. //
  2348. // See if the packet is a unicast, and if not, return immediately.
  2349. //
  2350. if (IS_BCAST_DEST(*DestinationType)) {
  2351. //
  2352. // Double-check the dest-type flag,
  2353. // which will appear to be set if the dest-type has been invalidated.
  2354. // If the dest-type has been invalidated, we'll need to guess
  2355. // whether the packet is a unicast.
  2356. //
  2357. if (*DestinationType != DEST_INVALID ||
  2358. !NatpIsUnicastPacket(
  2359. ((PIP_HEADER)(*InReceiveBuffer)->ipr_buffer)->DestinationAddress
  2360. )) {
  2361. //
  2362. // We process non-unicast packets if
  2363. // * It is locally-destined or locally-sent
  2364. // * There is at least one firewalled interface
  2365. // * AllowInboundNonUnicastTraffic is FALSE
  2366. //
  2367. if (!AllowInboundNonUnicastTraffic
  2368. && FirewalledInterfaceCount > 0
  2369. && (LOCAL_IF_INDEX == *SendIndex
  2370. || LOCAL_IF_INDEX == ReceiveIndex)) {
  2371. //
  2372. // Build the context for this packet and, if successful, call
  2373. // the non-unicast processing routine.
  2374. //
  2375. IpHeader = (PIP_HEADER)(*InReceiveBuffer)->ipr_buffer;
  2376. NAT_BUILD_XLATE_CONTEXT(
  2377. &Context,
  2378. IpHeader,
  2379. DestinationType,
  2380. *InReceiveBuffer,
  2381. IpHeader->SourceAddress,
  2382. IpHeader->DestinationAddress
  2383. );
  2384. if (!Context.ProtocolRecvBuffer) { return DROP; }
  2385. if (LOCAL_IF_INDEX == *SendIndex) {
  2386. act = NatpReceiveNonUnicastPacket(ReceiveIndex, &Context);
  2387. } else {
  2388. act = NatpSendNonUnicastPacket(*SendIndex, &Context);
  2389. }
  2390. #if NAT_WMI
  2391. if (DROP == act) {
  2392. NatLogDroppedPacket(&Context);
  2393. }
  2394. #endif
  2395. return act;
  2396. } else {
  2397. TRACE(PER_PACKET, ("NatTranslatePacket: non-unicast ignored\n"));
  2398. return FORWARD;
  2399. }
  2400. }
  2401. //
  2402. // We guessed the packet is a unicast; process it below.
  2403. //
  2404. }
  2405. //
  2406. // This is a unicast packet;
  2407. // Determine which translation routine should handle it,
  2408. // based on the packet's IP-layer protocol number.
  2409. //
  2410. // N.B. This determination is made with *one* access to the table
  2411. // of translation routines. Interlocked changes may be made to this table
  2412. // as the global configuration changes, so we must read from it
  2413. // using a single access.
  2414. //
  2415. IpHeader = (PIP_HEADER)(*InReceiveBuffer)->ipr_buffer;
  2416. TranslateRoutine = TranslateRoutineTable[IpHeader->Protocol];
  2417. //
  2418. // Return quickly if we have nothing to do, that is,
  2419. // if this is a TCP/UDP packet but there are no interfaces,
  2420. // no registered directors, and no mappings.
  2421. //
  2422. if ((PVOID)TranslateRoutine == (PVOID)NatTranslatePacket &&
  2423. !InterfaceCount &&
  2424. !DirectorCount &&
  2425. !MappingCount) {
  2426. return FORWARD;
  2427. }
  2428. //
  2429. // Prepare to translate the packet by building a translation context
  2430. // that encapsulates all the information we'll be using in the remainder
  2431. // of the translation path. If this fails, the packet must be malformed
  2432. // in some way, and we return control right away.
  2433. //
  2434. NAT_BUILD_XLATE_CONTEXT(
  2435. &Context,
  2436. IpHeader,
  2437. DestinationType,
  2438. *InReceiveBuffer,
  2439. IpHeader->SourceAddress,
  2440. IpHeader->DestinationAddress
  2441. );
  2442. if (!Context.ProtocolRecvBuffer) { return DROP; }
  2443. //
  2444. // The packet is a loopback, so return control right away unless there is
  2445. // at least one director. Loopback packets are never translated unless a
  2446. // director specifically asks us to do so. One director that might request
  2447. // a loopback translation is the redirect-director.
  2448. // (See 'REDIRECT.C' and the flag 'IP_NAT_REDIRECT_FLAG_LOOPBACK'.)
  2449. //
  2450. if (LoopbackIndex != INVALID_IF_INDEX &&
  2451. ((ReceiveIndex == LOCAL_IF_INDEX && *SendIndex == LoopbackIndex) ||
  2452. (*SendIndex == LOCAL_IF_INDEX && ReceiveIndex == LoopbackIndex))) {
  2453. if (!DirectorCount && TranslateRoutine != NatTranslateIcmp) {
  2454. TRACE(
  2455. PER_PACKET, (
  2456. "NatTranslatePacket: ignoring loopback (r=%d,s=%d,t=%d)\n",
  2457. ReceiveIndex,
  2458. *SendIndex,
  2459. *DestinationType
  2460. ));
  2461. return FORWARD;
  2462. }
  2463. Context.Flags = NAT_XLATE_FLAG_LOOPBACK;
  2464. } else {
  2465. Context.Flags = 0;
  2466. }
  2467. //
  2468. // Now we are at the fast-path for translation of TCP/UDP session packets.
  2469. // From here on we need to execute at dispatch IRQL, so raise the IRQL
  2470. // in case we were entered at passive IRQL (e.g. during a local send).
  2471. // We then perform a mapping lookup and attempt to use that to translate
  2472. // this packet.
  2473. //
  2474. if ((PVOID)TranslateRoutine != (PVOID)NatTranslatePacket || !MappingCount) {
  2475. KeRaiseIrql(DISPATCH_LEVEL, &Irql);
  2476. } else {
  2477. //
  2478. // If this is a TCP packet, check for invalid TCP flags combinations:
  2479. // * no flag bit sets
  2480. // * none of SYN, ACK, or RST are set
  2481. // * RST w/ anything except ACK
  2482. // * SYN w/ anything except ACK
  2483. //
  2484. // These checks need to happen before searching the mapping trees to
  2485. // prevents certain classes of denial of service attacks (e.g.,
  2486. // 'stream.c').
  2487. //
  2488. if (NAT_PROTOCOL_TCP == IpHeader->Protocol) {
  2489. TcpFlags = TCP_ALL_FLAGS((PTCP_HEADER)Context.ProtocolHeader);
  2490. if (!TcpFlags
  2491. || !(TcpFlags & (TCP_FLAG_SYN | TCP_FLAG_ACK | TCP_FLAG_RST))
  2492. || ((TcpFlags & TCP_FLAG_RST)
  2493. && (TcpFlags & ~(TCP_FLAG_RST | TCP_FLAG_ACK)))
  2494. || ((TcpFlags & TCP_FLAG_SYN)
  2495. && (TcpFlags & ~(TCP_FLAG_SYN | TCP_FLAG_ACK)))) {
  2496. #if NAT_WMI
  2497. NatLogDroppedPacket(&Context);
  2498. #endif
  2499. return DROP;
  2500. }
  2501. }
  2502. //
  2503. // Build a mapping lookup key
  2504. //
  2505. MAKE_MAPPING_KEY(
  2506. DestinationKey,
  2507. IpHeader->Protocol,
  2508. Context.DestinationAddress,
  2509. ((PUSHORT)Context.ProtocolHeader)[1]
  2510. );
  2511. MAKE_MAPPING_KEY(
  2512. SourceKey,
  2513. IpHeader->Protocol,
  2514. Context.SourceAddress,
  2515. ((PUSHORT)Context.ProtocolHeader)[0]
  2516. );
  2517. //
  2518. // Look for a mapping, and translate if found.
  2519. //
  2520. // N.B. We expect to receive more data than we send,
  2521. // and so we first look for a reverse mapping (i.e., incoming).
  2522. //
  2523. KeAcquireSpinLock(&MappingLock, &Irql);
  2524. if (Mapping =
  2525. NatLookupReverseMapping(
  2526. DestinationKey,
  2527. SourceKey,
  2528. NULL
  2529. )) {
  2530. NatReferenceMapping(Mapping);
  2531. KeReleaseSpinLockFromDpcLevel(&MappingLock);
  2532. *SendIndex = INVALID_IF_INDEX;
  2533. act =
  2534. Mapping->TranslateRoutine[NatReversePath](
  2535. Mapping,
  2536. &Context,
  2537. InReceiveBuffer,
  2538. OutReceiveBuffer
  2539. );
  2540. NatDereferenceMapping(Mapping);
  2541. KeLowerIrql(Irql);
  2542. #if NAT_WMI
  2543. if (DROP == act) {
  2544. NatLogDroppedPacket(&Context);
  2545. }
  2546. #endif
  2547. return act;
  2548. } else if (Mapping =
  2549. NatLookupForwardMapping(
  2550. DestinationKey,
  2551. SourceKey,
  2552. NULL
  2553. )) {
  2554. NatReferenceMapping(Mapping);
  2555. KeReleaseSpinLockFromDpcLevel(&MappingLock);
  2556. *SendIndex = INVALID_IF_INDEX;
  2557. act =
  2558. Mapping->TranslateRoutine[NatForwardPath](
  2559. Mapping,
  2560. &Context,
  2561. InReceiveBuffer,
  2562. OutReceiveBuffer
  2563. );
  2564. NatDereferenceMapping(Mapping);
  2565. KeLowerIrql(Irql);
  2566. #if NAT_WMI
  2567. if (DROP == act) {
  2568. NatLogDroppedPacket(&Context);
  2569. }
  2570. #endif
  2571. return act;
  2572. }
  2573. KeReleaseSpinLockFromDpcLevel(&MappingLock);
  2574. //
  2575. // No mapping was found; go through the process of establishing one.
  2576. //
  2577. }
  2578. //
  2579. // The packet could not be dispensed with in the fast path,
  2580. // so now we enter the second stage of processing.
  2581. // We will first look for a director who knows what to do with the packet,
  2582. // then we will attempt to automatically translate the packet,
  2583. // if it will cross a boundary interface.
  2584. //
  2585. // N.B. If we have neither local interfaces nor installed directors,
  2586. // we know we will make no changes, so return quickly.
  2587. //
  2588. if (!InterfaceCount && !DirectorCount) {
  2589. KeLowerIrql(Irql);
  2590. return FORWARD;
  2591. }
  2592. //
  2593. // Look first of all for a director.
  2594. // If no director is found, or if the director found supplies no mapping,
  2595. // proceed to the automatic-translation code, which is performed
  2596. // for packets which cross boundary interfaces. Note, therefore,
  2597. // that we never do automatic translation for loopback packets.
  2598. //
  2599. if (DirectorCount) {
  2600. status =
  2601. NatpDirectPacket(
  2602. ReceiveIndex,
  2603. *SendIndex,
  2604. &Context,
  2605. InReceiveBuffer,
  2606. OutReceiveBuffer,
  2607. &act
  2608. );
  2609. if (NT_SUCCESS(status)) {
  2610. KeLowerIrql(Irql);
  2611. #if NAT_WMI
  2612. if (DROP == act) {
  2613. NatLogDroppedPacket(&Context);
  2614. }
  2615. #endif
  2616. return act;
  2617. }
  2618. }
  2619. KeLowerIrql(Irql);
  2620. if (!InterfaceCount ||
  2621. ((Context.Flags & NAT_XLATE_FLAG_LOOPBACK) &&
  2622. !(*SendIndex == LoopbackIndex &&
  2623. TranslateRoutine == NatTranslateIcmp &&
  2624. MappingCount))) {
  2625. return FORWARD;
  2626. }
  2627. //
  2628. // Now decide whether the packet should be automatically translated.
  2629. // We classify the packet as local-send, local-receive, or transit.
  2630. // The action taken depends on which of the three cases is applicable:
  2631. //
  2632. // Locally-sent packets are not translated, with a few exceptions
  2633. // (see 'NatpSendPacket').
  2634. //
  2635. // Locally-received packets are translated if they match the inbound-path
  2636. // of a previously established mapping, or if they match a configured
  2637. // static port-mapping, or a static address-mapping with inbound sessions
  2638. // enabled.
  2639. //
  2640. // Transit packets are translated if their outgoing interface
  2641. // is a boundary interface; transit packets whose incoming interface
  2642. // is a boundary interface are dropped.
  2643. //
  2644. if (ReceiveIndex != LOCAL_IF_INDEX) {
  2645. //
  2646. // The packet is either a locally-destined packet or a transit packet.
  2647. //
  2648. if (*SendIndex == LOCAL_IF_INDEX) {
  2649. //
  2650. // The packet is locally destined.
  2651. // We assume this will happen mostly when packets are received
  2652. // from the public network, and since we expect more incoming
  2653. // packets than outgoing ones, this is our fast path.
  2654. //
  2655. act =
  2656. NatpReceivePacket(
  2657. ReceiveIndex,
  2658. &Context,
  2659. TranslateRoutine,
  2660. InReceiveBuffer,
  2661. OutReceiveBuffer
  2662. );
  2663. #if NAT_WMI
  2664. if (DROP == act) {
  2665. NatLogDroppedPacket(&Context);
  2666. }
  2667. #endif
  2668. return act;
  2669. }
  2670. //
  2671. // The packet is a transit packet.
  2672. // This will happen when packets are sent to the public network
  2673. // from a private client. Since we expect fewer outgoing packets
  2674. // than incoming ones, this will be hit less often.
  2675. //
  2676. // Unfortunately, it requires a route-lookup.
  2677. // To mitigate this unpleasantness, we use a cache of routes.
  2678. // In cases where there are a few high-volume connections,
  2679. // this will be a big win since we won't have to go through
  2680. // IP's routing table lock to retrieve the outgoing interface.
  2681. //
  2682. *SendIndex =
  2683. NatpRoutePacket(
  2684. Context.DestinationAddress,
  2685. &Context,
  2686. &status
  2687. );
  2688. //
  2689. // If we can't route the packet, neither can IP; drop it early.
  2690. //
  2691. if (*SendIndex == INVALID_IF_INDEX) {
  2692. TRACE(XLATE, ("NatTranslatePacket: dropping unroutable packet\n"));
  2693. if (status != STATUS_PENDING) {
  2694. NatSendRoutingFailureNotification(
  2695. Context.DestinationAddress,
  2696. Context.SourceAddress
  2697. );
  2698. }
  2699. #if NAT_WMI
  2700. NatLogDroppedPacket(&Context);
  2701. #endif
  2702. return DROP;
  2703. }
  2704. act =
  2705. NatpForwardPacket(
  2706. ReceiveIndex,
  2707. *SendIndex,
  2708. &Context,
  2709. TranslateRoutine,
  2710. InReceiveBuffer,
  2711. OutReceiveBuffer
  2712. );
  2713. #if NAT_WMI
  2714. if (DROP == act) {
  2715. NatLogDroppedPacket(&Context);
  2716. }
  2717. #endif
  2718. return act;
  2719. }
  2720. //
  2721. // The packet is an outgoing locally-generated packet.
  2722. //
  2723. if (*SendIndex != INVALID_IF_INDEX) {
  2724. act =
  2725. NatpSendPacket(
  2726. *SendIndex,
  2727. &Context,
  2728. TranslateRoutine,
  2729. InReceiveBuffer,
  2730. OutReceiveBuffer
  2731. );
  2732. #if NAT_WMI
  2733. if (DROP == act) {
  2734. NatLogDroppedPacket(&Context);
  2735. }
  2736. #endif
  2737. return act;
  2738. }
  2739. //
  2740. // 'SendIndex' has been invalidated.
  2741. // Use a route-lookup to get the sending adapter index.
  2742. //
  2743. *SendIndex = NatpRoutePacket(Context.DestinationAddress, NULL, &status);
  2744. //
  2745. // Drop unroutable packets early.
  2746. //
  2747. if (*SendIndex == INVALID_IF_INDEX) {
  2748. TRACE(XLATE, ("NatTranslatePacket: dropping unroutable packet\n"));
  2749. if (status != STATUS_PENDING) {
  2750. NatSendRoutingFailureNotification(
  2751. Context.DestinationAddress,
  2752. Context.SourceAddress
  2753. );
  2754. }
  2755. #if NAT_WMI
  2756. NatLogDroppedPacket(&Context);
  2757. #endif
  2758. return DROP;
  2759. }
  2760. act =
  2761. NatpSendPacket(
  2762. *SendIndex,
  2763. &Context,
  2764. TranslateRoutine,
  2765. InReceiveBuffer,
  2766. OutReceiveBuffer
  2767. );
  2768. #if NAT_WMI
  2769. if (DROP == act) {
  2770. NatLogDroppedPacket(&Context);
  2771. }
  2772. #endif
  2773. return act;
  2774. } // NatTranslatePacket
  2775. //
  2776. // Now include the code for the translation routines;
  2777. // See XLATE.H for more details.
  2778. //
  2779. #define XLATE_CODE
  2780. #define XLATE_FORWARD
  2781. #include "xlate.h"
  2782. #undef XLATE_FORWARD
  2783. #define XLATE_REVERSE
  2784. #include "xlate.h"
  2785. #undef XLATE_REVERSE