Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2621 lines
64 KiB

  1. /*++
  2. Copyright (c) 1998, Microsoft Corporation
  3. Module Name:
  4. natio.h
  5. Abstract:
  6. This module contains declarations for the NAT's I/O interface
  7. to the kernel-mode driver.
  8. Author:
  9. Abolade Gbadegesin (aboladeg) 10-Mar-1998
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. #include <ras.h>
  15. #include <rasuip.h>
  16. #include <raserror.h>
  17. //
  18. // PRIVATE GLOBAL VARIABLES
  19. //
  20. HANDLE NatFileHandle;
  21. LIST_ENTRY NatInterfaceList;
  22. //
  23. // Controls access to 'NatFileHandle' and 'NatInterfaceList'.
  24. //
  25. CRITICAL_SECTION NatInterfaceLock;
  26. //
  27. // FORWARD DECLARATIONS
  28. //
  29. VOID
  30. NatpDisableLoadDriverPrivilege(
  31. PBOOLEAN WasEnabled
  32. );
  33. BOOLEAN
  34. NatpEnableLoadDriverPrivilege(
  35. PBOOLEAN WasEnabled
  36. );
  37. PNAT_INTERFACE
  38. NatpLookupInterface(
  39. ULONG Index,
  40. OUT PLIST_ENTRY* InsertionPoint OPTIONAL
  41. );
  42. ULONG
  43. NatExpandWildcardMappings(
  44. IN PIP_NAT_INTERFACE_INFO InInfo,
  45. IN PIP_ADAPTER_BINDING_INFO BindingInfo,
  46. OUT PIP_NAT_INTERFACE_INFO *ExpandedInfo
  47. );
  48. ULONG
  49. NatBindInterface(
  50. ULONG Index,
  51. PNAT_INTERFACE Interfacep OPTIONAL,
  52. PIP_ADAPTER_BINDING_INFO BindingInfo,
  53. ULONG AdapterIndex
  54. )
  55. /*++
  56. Routine Description:
  57. This routine is invoked to bind the NAT to an interface.
  58. Arguments:
  59. Index - the interface to be bound
  60. Interfacep - optionally supplies the interface-structure to be bound
  61. (See 'NATCONN.C' which passes in a static interface-structure).
  62. BindingInfo - the interface's address-information
  63. AdapterIndex - optionally specifies the interface's TCP/IP adapter index.
  64. This is set only for home-router interfaces.
  65. Return Value:
  66. ULONG - Win32 status code.
  67. --*/
  68. {
  69. PIP_NAT_CREATE_INTERFACE CreateInterface;
  70. ULONG Error;
  71. IO_STATUS_BLOCK IoStatus;
  72. ULONG Size;
  73. NTSTATUS status;
  74. HANDLE WaitEvent;
  75. PIP_NAT_INTERFACE_INFO ExpandedInfo = NULL;
  76. ULONG ExpandedSize;
  77. PROFILE("NatBindInterface");
  78. Error = NO_ERROR;
  79. //
  80. // Look up the interface to be bound
  81. //
  82. EnterCriticalSection(&NatInterfaceLock);
  83. if (!Interfacep && !(Interfacep = NatpLookupInterface(Index, NULL))) {
  84. LeaveCriticalSection(&NatInterfaceLock);
  85. NhTrace(
  86. TRACE_FLAG_NAT,
  87. "NatBindInterface: interface %d not found",
  88. Index
  89. );
  90. return ERROR_NO_SUCH_INTERFACE;
  91. }
  92. //
  93. // Make sure the interface isn't already bound
  94. //
  95. if (NAT_INTERFACE_BOUND(Interfacep)) {
  96. LeaveCriticalSection(&NatInterfaceLock);
  97. NhTrace(
  98. TRACE_FLAG_NAT,
  99. "NatBindInterface: interface %d is already bound",
  100. Index
  101. );
  102. return ERROR_ADDRESS_ALREADY_ASSOCIATED;
  103. }
  104. //
  105. // Allocate the bind-structure
  106. //
  107. Size =
  108. sizeof(IP_NAT_CREATE_INTERFACE) +
  109. SIZEOF_IP_BINDING(BindingInfo->AddressCount);
  110. CreateInterface = reinterpret_cast<PIP_NAT_CREATE_INTERFACE>(
  111. NH_ALLOCATE(Size));
  112. if (!CreateInterface) {
  113. LeaveCriticalSection(&NatInterfaceLock);
  114. NhTrace(
  115. TRACE_FLAG_NAT,
  116. "NatBindInterface: allocation failed for interface %d binding",
  117. Index
  118. );
  119. NhErrorLog(
  120. IP_NAT_LOG_ALLOCATION_FAILED,
  121. 0,
  122. "%d",
  123. Size
  124. );
  125. return ERROR_NOT_ENOUGH_MEMORY;
  126. }
  127. Interfacep->AdapterIndex =
  128. (AdapterIndex != (ULONG)-1)
  129. ? AdapterIndex
  130. : NhMapInterfaceToAdapter(Interfacep->Index);
  131. if (Interfacep->AdapterIndex == (ULONG)-1) {
  132. LeaveCriticalSection(&NatInterfaceLock);
  133. NhTrace(
  134. TRACE_FLAG_NAT,
  135. "NatBindInterface: NhMapInterfaceToAdapter failed for %d",
  136. Index
  137. );
  138. return ERROR_INVALID_INDEX;
  139. }
  140. CreateInterface->Index = Interfacep->AdapterIndex;
  141. CopyMemory(
  142. CreateInterface->BindingInfo,
  143. BindingInfo,
  144. SIZEOF_IP_BINDING(BindingInfo->AddressCount)
  145. );
  146. WaitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  147. if (WaitEvent == NULL) {
  148. LeaveCriticalSection(&NatInterfaceLock);
  149. NhTrace(
  150. TRACE_FLAG_NAT,
  151. "NatBindInterface: CreateEvent failed [%d] for interface %d",
  152. GetLastError(),
  153. Index
  154. );
  155. return ERROR_NOT_ENOUGH_MEMORY;
  156. }
  157. //
  158. // Install the interface
  159. //
  160. status =
  161. NtDeviceIoControlFile(
  162. NatFileHandle,
  163. WaitEvent,
  164. NULL,
  165. NULL,
  166. &IoStatus,
  167. IOCTL_IP_NAT_CREATE_INTERFACE,
  168. (PVOID)CreateInterface,
  169. Size,
  170. NULL,
  171. 0
  172. );
  173. if (status == STATUS_PENDING) {
  174. WaitForSingleObject(WaitEvent, INFINITE);
  175. status = IoStatus.Status;
  176. }
  177. NH_FREE(CreateInterface);
  178. if (!NT_SUCCESS(status)) {
  179. CloseHandle(WaitEvent);
  180. LeaveCriticalSection(&NatInterfaceLock);
  181. NhTrace(
  182. TRACE_FLAG_NAT,
  183. "NatBindInterface: status %08x binding interface %d",
  184. status,
  185. Index
  186. );
  187. Error = RtlNtStatusToDosError(status);
  188. NhErrorLog(
  189. IP_NAT_LOG_IOCTL_FAILED,
  190. Error,
  191. ""
  192. );
  193. return Error;
  194. }
  195. //
  196. // If a mapping with
  197. // public ip address = 0
  198. // private ip address = 127.0.0.1
  199. // exists, expand that mapping to one mapping for each of the ipaddresses
  200. // bound to the interface.
  201. //
  202. Error = NatExpandWildcardMappings(
  203. Interfacep->Info,
  204. BindingInfo,
  205. &ExpandedInfo);
  206. if ( Error != NO_ERROR ) {
  207. ULONG AdapterIndex = Interfacep->AdapterIndex;
  208. LeaveCriticalSection(&NatInterfaceLock);
  209. NhTrace(
  210. TRACE_FLAG_NAT,
  211. "NatBindInterface: Failed to expand wildcard mappings. Error %d",
  212. Error
  213. );
  214. NhErrorLog(
  215. IP_NAT_LOG_EXPANSION_FAILED,
  216. Error,
  217. ""
  218. );
  219. status =
  220. NtDeviceIoControlFile(
  221. NatFileHandle,
  222. WaitEvent,
  223. NULL,
  224. NULL,
  225. &IoStatus,
  226. IOCTL_IP_NAT_DELETE_INTERFACE,
  227. (PVOID)&AdapterIndex,
  228. sizeof(ULONG),
  229. NULL,
  230. 0
  231. );
  232. if (status == STATUS_PENDING) {
  233. WaitForSingleObject(WaitEvent, INFINITE);
  234. status = IoStatus.Status;
  235. }
  236. CloseHandle(WaitEvent);
  237. return Error;
  238. }
  239. //
  240. // Now set its configuration
  241. //
  242. ExpandedInfo->Index = Interfacep->AdapterIndex;
  243. ExpandedSize =
  244. FIELD_OFFSET(IP_NAT_INTERFACE_INFO, Header) +
  245. ExpandedInfo->Header.Size;
  246. status =
  247. NtDeviceIoControlFile(
  248. NatFileHandle,
  249. WaitEvent,
  250. NULL,
  251. NULL,
  252. &IoStatus,
  253. IOCTL_IP_NAT_SET_INTERFACE_INFO,
  254. (PVOID)ExpandedInfo,
  255. ExpandedSize,
  256. NULL,
  257. 0
  258. );
  259. if (status == STATUS_PENDING) {
  260. WaitForSingleObject(WaitEvent, INFINITE);
  261. status = IoStatus.Status;
  262. }
  263. //
  264. // If new Interface Info was allocated, free it
  265. //
  266. if ( ExpandedInfo != Interfacep->Info ) {
  267. NH_FREE(ExpandedInfo);
  268. ExpandedInfo = NULL;
  269. }
  270. if (!NT_SUCCESS(status)) {
  271. ULONG AdapterIndex = Interfacep->AdapterIndex;
  272. LeaveCriticalSection(&NatInterfaceLock);
  273. NhTrace(
  274. TRACE_FLAG_NAT,
  275. "NatBindInterface: status %08x setting info for interface %d (%d)",
  276. status,
  277. Index,
  278. AdapterIndex
  279. );
  280. Error = RtlNtStatusToDosError(status);
  281. NhErrorLog(
  282. IP_NAT_LOG_IOCTL_FAILED,
  283. Error,
  284. ""
  285. );
  286. status =
  287. NtDeviceIoControlFile(
  288. NatFileHandle,
  289. WaitEvent,
  290. NULL,
  291. NULL,
  292. &IoStatus,
  293. IOCTL_IP_NAT_DELETE_INTERFACE,
  294. (PVOID)&AdapterIndex,
  295. sizeof(ULONG),
  296. NULL,
  297. 0
  298. );
  299. if (status == STATUS_PENDING) {
  300. WaitForSingleObject(WaitEvent, INFINITE);
  301. status = IoStatus.Status;
  302. }
  303. CloseHandle(WaitEvent);
  304. return Error;
  305. }
  306. Interfacep->Flags |= NAT_INTERFACE_FLAG_BOUND;
  307. if (Interfacep->Type == ROUTER_IF_TYPE_DEDICATED) {
  308. NatUpdateProxyArp(Interfacep, TRUE);
  309. }
  310. CloseHandle(WaitEvent);
  311. LeaveCriticalSection(&NatInterfaceLock);
  312. return Error;
  313. } // NatBindInterface
  314. ULONG
  315. NatConfigureDriver(
  316. PIP_NAT_GLOBAL_INFO GlobalInfo
  317. )
  318. /*++
  319. Routine Description:
  320. This routine is called to update the configuration for the NAT driver.
  321. Arguments:
  322. GlobalInfo - the new configuration for the NAT.
  323. Return Value:
  324. ULONG - Win32 status code.
  325. --*/
  326. {
  327. ULONG Error = NO_ERROR;
  328. IO_STATUS_BLOCK IoStatus;
  329. NTSTATUS status;
  330. HANDLE WaitEvent;
  331. PROFILE("NatConfigureDriver");
  332. WaitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  333. if (WaitEvent == NULL) {
  334. NhTrace(
  335. TRACE_FLAG_NAT,
  336. "NatConfigureDriver: CreateEvent failed [%d]",
  337. GetLastError()
  338. );
  339. return ERROR_NOT_ENOUGH_MEMORY;
  340. }
  341. //
  342. // Attempt to configure the driver
  343. //
  344. EnterCriticalSection(&NatInterfaceLock);
  345. status =
  346. NtDeviceIoControlFile(
  347. NatFileHandle,
  348. WaitEvent,
  349. NULL,
  350. NULL,
  351. &IoStatus,
  352. IOCTL_IP_NAT_SET_GLOBAL_INFO,
  353. (PVOID)GlobalInfo,
  354. FIELD_OFFSET(IP_NAT_GLOBAL_INFO, Header) + GlobalInfo->Header.Size,
  355. NULL,
  356. 0
  357. );
  358. if (status == STATUS_PENDING) {
  359. WaitForSingleObject(WaitEvent, INFINITE);
  360. status = IoStatus.Status;
  361. }
  362. LeaveCriticalSection(&NatInterfaceLock);
  363. if (!NT_SUCCESS(status)) {
  364. NhTrace(
  365. TRACE_FLAG_NAT,
  366. "NatConfigureDriver: status %08x setting global info",
  367. status
  368. );
  369. Error = RtlNtStatusToDosError(status);
  370. NhErrorLog(
  371. IP_NAT_LOG_IOCTL_FAILED,
  372. Error,
  373. ""
  374. );
  375. }
  376. CloseHandle(WaitEvent);
  377. return Error;
  378. } // NatConfigureDriver
  379. ULONG
  380. NatConfigureInterface(
  381. ULONG Index,
  382. PIP_NAT_INTERFACE_INFO InterfaceInfo
  383. )
  384. /*++
  385. Routine Description:
  386. This routine is invoked to set the configuration for a NAT interface.
  387. Arguments:
  388. Index - the interface to be configured
  389. InterfaceInfo - the configuration for the interface
  390. Return Value:
  391. ULONG - Win32 status code.
  392. --*/
  393. {
  394. ULONG Error = NO_ERROR;
  395. PIP_NAT_INTERFACE_INFO Info;
  396. PNAT_INTERFACE Interfacep;
  397. IO_STATUS_BLOCK IoStatus;
  398. ULONG Size;
  399. NTSTATUS status;
  400. PROFILE("NatConfigureInterface");
  401. if (!InterfaceInfo) {
  402. NhTrace(
  403. TRACE_FLAG_NAT,
  404. "NatConfigureInterface: no interface info for %d",
  405. Index
  406. );
  407. return ERROR_INVALID_PARAMETER;
  408. }
  409. //
  410. // Make a copy of the information
  411. //
  412. Size =
  413. FIELD_OFFSET(IP_NAT_INTERFACE_INFO, Header) +
  414. InterfaceInfo->Header.Size;
  415. Info = (PIP_NAT_INTERFACE_INFO)NH_ALLOCATE(Size);
  416. if (!Info) {
  417. NhTrace(
  418. TRACE_FLAG_NAT,
  419. "NatConfigureInterface: error allocating copy of configuration"
  420. );
  421. NhErrorLog(
  422. IP_NAT_LOG_ALLOCATION_FAILED,
  423. 0,
  424. "%d",
  425. Size
  426. );
  427. return ERROR_NOT_ENOUGH_MEMORY;
  428. }
  429. CopyMemory(
  430. Info,
  431. InterfaceInfo,
  432. Size
  433. );
  434. //
  435. // Look up the interface to be configured
  436. //
  437. EnterCriticalSection(&NatInterfaceLock);
  438. if (!(Interfacep = NatpLookupInterface(Index, NULL))) {
  439. LeaveCriticalSection(&NatInterfaceLock);
  440. NhTrace(
  441. TRACE_FLAG_NAT,
  442. "NatConfigureInterface: interface %d not found",
  443. Index
  444. );
  445. NH_FREE(Info);
  446. return ERROR_NO_SUCH_INTERFACE;
  447. }
  448. //
  449. // See if the configuration changed
  450. //
  451. if ((Size ==
  452. FIELD_OFFSET(IP_NAT_INTERFACE_INFO, Header) +
  453. Interfacep->Info->Header.Size) &&
  454. memcmp(InterfaceInfo, Interfacep->Info, Size) == 0
  455. ) {
  456. LeaveCriticalSection(&NatInterfaceLock);
  457. NhTrace(
  458. TRACE_FLAG_NAT,
  459. "NatConfigureInterface: no change to interface %d configuration",
  460. Index
  461. );
  462. NH_FREE(Info);
  463. return NO_ERROR;
  464. }
  465. //
  466. // See if the interface is bound;
  467. // if so we need to update the kernel-mode driver's configuration.
  468. //
  469. if (!NAT_INTERFACE_BOUND(Interfacep)) {
  470. status = STATUS_SUCCESS;
  471. } else {
  472. HANDLE WaitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  473. if (WaitEvent != NULL) {
  474. DWORD ExpandedSize = 0;
  475. PIP_ADAPTER_BINDING_INFO BindingInfo;
  476. PIP_NAT_INTERFACE_INFO ExpandedInfo = NULL;
  477. //
  478. // If both, address and port translation are disabled,
  479. // and a mapping with
  480. // public ip address = 0
  481. // private ip address = 127.0.0.1
  482. // exists, expand that mapping to one mapping for each of
  483. // the ipaddresses bound to the interface.
  484. //
  485. BindingInfo = NhQueryBindingInformation(Interfacep->AdapterIndex);
  486. if ( BindingInfo == NULL ) {
  487. LeaveCriticalSection(&NatInterfaceLock);
  488. NhTrace(
  489. TRACE_FLAG_NAT,
  490. "NatConfigureInterface: Failed to Query Binding "
  491. "Information. Error %d",
  492. Error
  493. );
  494. NhErrorLog(
  495. IP_NAT_LOG_EXPANSION_FAILED,
  496. Error,
  497. ""
  498. );
  499. NH_FREE(Info);
  500. return Error;
  501. }
  502. Error = NatExpandWildcardMappings(
  503. Info,
  504. BindingInfo,
  505. &ExpandedInfo
  506. );
  507. if ( Error != NO_ERROR ) {
  508. LeaveCriticalSection(&NatInterfaceLock);
  509. NhTrace(
  510. TRACE_FLAG_NAT,
  511. "NatConfigureInterface: Failed to expand wildcard "
  512. "mappings. Error %d",
  513. Error
  514. );
  515. NhErrorLog(
  516. IP_NAT_LOG_EXPANSION_FAILED,
  517. Error,
  518. ""
  519. );
  520. NH_FREE(Info);
  521. NH_FREE(BindingInfo);
  522. return Error;
  523. }
  524. NH_FREE(BindingInfo);
  525. BindingInfo = NULL;
  526. ExpandedInfo->Index = Info->Index = Interfacep->AdapterIndex;
  527. ExpandedSize = FIELD_OFFSET(IP_NAT_INTERFACE_INFO, Header) +
  528. ExpandedInfo->Header.Size;
  529. //
  530. // Attempt to configure the interface
  531. //
  532. status =
  533. NtDeviceIoControlFile(
  534. NatFileHandle,
  535. WaitEvent,
  536. NULL,
  537. NULL,
  538. &IoStatus,
  539. IOCTL_IP_NAT_SET_INTERFACE_INFO,
  540. (PVOID)ExpandedInfo,
  541. ExpandedSize,
  542. NULL,
  543. 0
  544. );
  545. if (status == STATUS_PENDING) {
  546. WaitForSingleObject(WaitEvent, INFINITE);
  547. status = IoStatus.Status;
  548. }
  549. CloseHandle(WaitEvent);
  550. //
  551. // If new Interface Info was allocated during the call to
  552. // NatExpandWildcardMappings, free it
  553. //
  554. if ( ExpandedInfo != Info ) {
  555. NH_FREE(ExpandedInfo);
  556. ExpandedInfo = NULL;
  557. }
  558. } else {
  559. status = STATUS_UNSUCCESSFUL;
  560. NhTrace(
  561. TRACE_FLAG_NAT,
  562. "NatConfigureInterface: CreateEvent failed [%d]",
  563. GetLastError()
  564. );
  565. }
  566. }
  567. if (!NT_SUCCESS(status)) {
  568. NH_FREE(Info);
  569. NhTrace(
  570. TRACE_FLAG_NAT,
  571. "NatConfigureInterface: status %08x setting interface info",
  572. status
  573. );
  574. Error = RtlNtStatusToDosError(status);
  575. NhErrorLog(
  576. IP_NAT_LOG_IOCTL_FAILED,
  577. Error,
  578. ""
  579. );
  580. } else {
  581. Error = NO_ERROR;
  582. //
  583. // Update proxy ARP entries for LAN interfaces
  584. //
  585. if (NAT_INTERFACE_BOUND(Interfacep) &&
  586. Interfacep->Type == ROUTER_IF_TYPE_DEDICATED
  587. ) {
  588. NatUpdateProxyArp(Interfacep, FALSE);
  589. }
  590. if (Interfacep->Info) { NH_FREE(Interfacep->Info); }
  591. Interfacep->Info = Info;
  592. if (NAT_INTERFACE_BOUND(Interfacep) &&
  593. Interfacep->Type == ROUTER_IF_TYPE_DEDICATED
  594. ) {
  595. NatUpdateProxyArp(Interfacep, TRUE);
  596. }
  597. }
  598. LeaveCriticalSection(&NatInterfaceLock);
  599. if (NT_SUCCESS(status)) {
  600. if (InterfaceInfo->Flags & IP_NAT_INTERFACE_FLAGS_BOUNDARY) {
  601. NhSignalNatInterface(
  602. Index,
  603. TRUE
  604. );
  605. } else {
  606. NhSignalNatInterface(
  607. Index,
  608. FALSE
  609. );
  610. }
  611. }
  612. return Error;
  613. } // NatConfigureInterface
  614. ULONG
  615. NatCreateInterface(
  616. ULONG Index,
  617. NET_INTERFACE_TYPE Type,
  618. PIP_NAT_INTERFACE_INFO InterfaceInfo
  619. )
  620. /*++
  621. Routine Description:
  622. This routine is invoked to create an interface with the NAT driver.
  623. Arguments:
  624. Index - the index of the new interface
  625. InterfaceInfo - the configuration for the new interface
  626. Return Value:
  627. ULONG - Win32 status code.
  628. --*/
  629. {
  630. ULONG Error;
  631. PIP_NAT_INTERFACE_INFO Info;
  632. PLIST_ENTRY InsertionPoint;
  633. PNAT_INTERFACE Interfacep;
  634. IO_STATUS_BLOCK IoStatus;
  635. ULONG Size;
  636. NTSTATUS status;
  637. ROUTER_INTERFACE_TYPE IfType;
  638. PROFILE("NatCreateInterface");
  639. if (!InterfaceInfo) {
  640. NhTrace(
  641. TRACE_FLAG_NAT,
  642. "NatCreateInterface: no interface info for %d",
  643. Index
  644. );
  645. return ERROR_INVALID_PARAMETER;
  646. }
  647. //
  648. // Check for the interface in our table
  649. //
  650. EnterCriticalSection(&NatInterfaceLock);
  651. if (NatpLookupInterface(Index, &InsertionPoint)) {
  652. LeaveCriticalSection(&NatInterfaceLock);
  653. NhTrace(
  654. TRACE_FLAG_NAT,
  655. "NatCreateInterface: interface %d already exists",
  656. Index
  657. );
  658. return ERROR_INTERFACE_ALREADY_EXISTS;
  659. }
  660. //
  661. // Allocate a new interface
  662. //
  663. Interfacep =
  664. reinterpret_cast<PNAT_INTERFACE>(NH_ALLOCATE(sizeof(NAT_INTERFACE)));
  665. if (!Interfacep) {
  666. LeaveCriticalSection(&NatInterfaceLock);
  667. NhTrace(
  668. TRACE_FLAG_NAT,
  669. "NatCreateInterface: error allocating interface"
  670. );
  671. NhErrorLog(
  672. IP_NAT_LOG_ALLOCATION_FAILED,
  673. 0,
  674. "%d",
  675. sizeof(NAT_INTERFACE)
  676. );
  677. return ERROR_NOT_ENOUGH_MEMORY;
  678. }
  679. //
  680. // Make a copy of the information
  681. //
  682. Size =
  683. FIELD_OFFSET(IP_NAT_INTERFACE_INFO, Header) +
  684. InterfaceInfo->Header.Size;
  685. Info = (PIP_NAT_INTERFACE_INFO)NH_ALLOCATE(Size);
  686. if (!Info) {
  687. LeaveCriticalSection(&NatInterfaceLock);
  688. NH_FREE(Interfacep);
  689. NhTrace(
  690. TRACE_FLAG_NAT,
  691. "NatCreateInterface: error allocating copy of configuration"
  692. );
  693. return ERROR_NOT_ENOUGH_MEMORY;
  694. }
  695. CopyMemory(
  696. Info,
  697. InterfaceInfo,
  698. Size
  699. );
  700. //
  701. // Initialize the new interface
  702. //
  703. ZeroMemory(Interfacep, sizeof(*Interfacep));
  704. Interfacep->Index = Index;
  705. Interfacep->AdapterIndex = (ULONG)-1;
  706. Interfacep->Type = IfType =
  707. ((Type == PERMANENT)
  708. ? ROUTER_IF_TYPE_DEDICATED
  709. : ROUTER_IF_TYPE_FULL_ROUTER);
  710. Interfacep->Info = Info;
  711. InsertTailList(InsertionPoint, &Interfacep->Link);
  712. LeaveCriticalSection(&NatInterfaceLock);
  713. if (InterfaceInfo->Flags & IP_NAT_INTERFACE_FLAGS_BOUNDARY) {
  714. NhSignalNatInterface(
  715. Index,
  716. TRUE
  717. );
  718. } else {
  719. NhSignalNatInterface(
  720. Index,
  721. FALSE
  722. );
  723. }
  724. return NO_ERROR;
  725. } // NatCreateInterface
  726. ULONG
  727. NatCreateTicket(
  728. ULONG InterfaceIndex,
  729. UCHAR Protocol,
  730. USHORT PublicPort,
  731. ULONG PublicAddress,
  732. USHORT PrivatePort,
  733. ULONG PrivateAddress
  734. )
  735. /*++
  736. Routine Description:
  737. This routine is invoked to add a ticket (static port mapping)
  738. to an interface.
  739. Arguments:
  740. InterfaceIndex - the interface to which to add the ticket
  741. Protocol, PublicPort, PublicAddress, PrivatePort, PrivateAddress -
  742. describes the ticket to be created
  743. Return Value:
  744. ULONG - Win32 status code.
  745. --*/
  746. {
  747. IP_NAT_CREATE_TICKET CreateTicket;
  748. ULONG Error;
  749. IO_STATUS_BLOCK IoStatus;
  750. NTSTATUS status;
  751. HANDLE WaitEvent;
  752. PROFILE("NatCreateTicket");
  753. WaitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  754. if (WaitEvent == NULL) {
  755. NhTrace(
  756. TRACE_FLAG_NAT,
  757. "NatCreateTicket: CreateEvent failed [%d]",
  758. GetLastError()
  759. );
  760. return ERROR_NOT_ENOUGH_MEMORY;
  761. }
  762. CreateTicket.InterfaceIndex = InterfaceIndex;
  763. CreateTicket.PortMapping.Protocol = Protocol;
  764. CreateTicket.PortMapping.PublicPort = PublicPort;
  765. CreateTicket.PortMapping.PublicAddress = PublicAddress;
  766. CreateTicket.PortMapping.PrivatePort = PrivatePort;
  767. CreateTicket.PortMapping.PrivateAddress = PrivateAddress;
  768. EnterCriticalSection(&NatInterfaceLock);
  769. status =
  770. NtDeviceIoControlFile(
  771. NatFileHandle,
  772. WaitEvent,
  773. NULL,
  774. NULL,
  775. &IoStatus,
  776. IOCTL_IP_NAT_CREATE_TICKET,
  777. (PVOID)&CreateTicket,
  778. sizeof(CreateTicket),
  779. NULL,
  780. 0
  781. );
  782. LeaveCriticalSection(&NatInterfaceLock);
  783. if (status == STATUS_PENDING) {
  784. WaitForSingleObject(WaitEvent, INFINITE);
  785. status = IoStatus.Status;
  786. }
  787. if (NT_SUCCESS(status)) {
  788. Error = NO_ERROR;
  789. } else {
  790. Error = RtlNtStatusToDosError(status);
  791. NhTrace(
  792. TRACE_FLAG_NAT,
  793. "NatCreateTicket: Ioctl = %d",
  794. Error
  795. );
  796. }
  797. CloseHandle(WaitEvent);
  798. return Error;
  799. } // NatCreateTicket
  800. ULONG
  801. NatDeleteInterface(
  802. ULONG Index
  803. )
  804. /*++
  805. Routine Description:
  806. This routine is invoked to remove an interface from the NAT.
  807. Arguments:
  808. Index - the interface to be removed
  809. Return Value:
  810. ULONG - Win32 status code.
  811. --*/
  812. {
  813. ULONG Error;
  814. PNAT_INTERFACE Interfacep;
  815. IO_STATUS_BLOCK IoStatus;
  816. NTSTATUS status;
  817. HANDLE WaitEvent;
  818. PROFILE("NatDeleteInterface");
  819. WaitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  820. if (WaitEvent == NULL) {
  821. NhTrace(
  822. TRACE_FLAG_NAT,
  823. "NatDeleteInterface: CreateEvent failed [%d]",
  824. GetLastError()
  825. );
  826. return ERROR_NOT_ENOUGH_MEMORY;
  827. }
  828. //
  829. // Retrieve the interface to be deleted.
  830. //
  831. EnterCriticalSection(&NatInterfaceLock);
  832. if (!(Interfacep = NatpLookupInterface(Index, NULL))) {
  833. LeaveCriticalSection(&NatInterfaceLock);
  834. CloseHandle(WaitEvent);
  835. NhTrace(
  836. TRACE_FLAG_NAT,
  837. "NatDeleteInterface: interface %d not found",
  838. Index
  839. );
  840. return ERROR_NO_SUCH_INTERFACE;
  841. }
  842. Error = NO_ERROR;
  843. if (NAT_INTERFACE_BOUND(Interfacep)) {
  844. //
  845. // Delete the interface from the kernel-mode driver
  846. //
  847. status =
  848. NtDeviceIoControlFile(
  849. NatFileHandle,
  850. WaitEvent,
  851. NULL,
  852. NULL,
  853. &IoStatus,
  854. IOCTL_IP_NAT_DELETE_INTERFACE,
  855. (PVOID)&Interfacep->AdapterIndex,
  856. sizeof(ULONG),
  857. NULL,
  858. 0
  859. );
  860. if (status == STATUS_PENDING) {
  861. WaitForSingleObject(WaitEvent, INFINITE);
  862. status = IoStatus.Status;
  863. }
  864. if (NT_SUCCESS(status)) {
  865. Error = NO_ERROR;
  866. } else {
  867. Error = RtlNtStatusToDosError(status);
  868. NhErrorLog(
  869. IP_NAT_LOG_IOCTL_FAILED,
  870. Error,
  871. ""
  872. );
  873. }
  874. }
  875. CloseHandle(WaitEvent);
  876. //
  877. // Remove the interface from our list
  878. //
  879. RemoveEntryList(&Interfacep->Link);
  880. if (Interfacep->Info) {
  881. NH_FREE(Interfacep->Info);
  882. }
  883. NH_FREE(Interfacep);
  884. LeaveCriticalSection(&NatInterfaceLock);
  885. NhSignalNatInterface(
  886. Index,
  887. FALSE
  888. );
  889. return Error;
  890. } // NatDeleteInterface
  891. ULONG
  892. NatDeleteTicket(
  893. ULONG InterfaceIndex,
  894. UCHAR Protocol,
  895. USHORT PublicPort,
  896. ULONG PublicAddress,
  897. USHORT PrivatePort,
  898. ULONG PrivateAddress
  899. )
  900. /*++
  901. Routine Description:
  902. This routine is invoked to remove a ticket (static port mapping)
  903. from an interface.
  904. Arguments:
  905. InterfaceIndex - the interface from which to remove the ticket
  906. Protocol, PublicPort, PublicAddress, PrivatePort, PrivateAddress -
  907. describes the ticket to be deleted
  908. Return Value:
  909. ULONG - Win32 status code.
  910. --*/
  911. {
  912. IP_NAT_CREATE_TICKET DeleteTicket;
  913. ULONG Error;
  914. IO_STATUS_BLOCK IoStatus;
  915. NTSTATUS status;
  916. HANDLE WaitEvent;
  917. PROFILE("NatDeleteTicket");
  918. WaitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  919. if (WaitEvent == NULL) {
  920. NhTrace(
  921. TRACE_FLAG_NAT,
  922. "NatDeleteTicket: CreateEvent failed [%d]",
  923. GetLastError()
  924. );
  925. return ERROR_NOT_ENOUGH_MEMORY;
  926. }
  927. DeleteTicket.InterfaceIndex = InterfaceIndex;
  928. DeleteTicket.PortMapping.Protocol = Protocol;
  929. DeleteTicket.PortMapping.PublicPort = PublicPort;
  930. DeleteTicket.PortMapping.PublicAddress = PublicAddress;
  931. DeleteTicket.PortMapping.PrivatePort = PrivatePort;
  932. DeleteTicket.PortMapping.PrivateAddress = PrivateAddress;
  933. EnterCriticalSection(&NatInterfaceLock);
  934. status =
  935. NtDeviceIoControlFile(
  936. NatFileHandle,
  937. WaitEvent,
  938. NULL,
  939. NULL,
  940. &IoStatus,
  941. IOCTL_IP_NAT_DELETE_TICKET,
  942. (PVOID)&DeleteTicket,
  943. sizeof(DeleteTicket),
  944. NULL,
  945. 0
  946. );
  947. LeaveCriticalSection(&NatInterfaceLock);
  948. if (status == STATUS_PENDING) {
  949. WaitForSingleObject(WaitEvent, INFINITE);
  950. status = IoStatus.Status;
  951. }
  952. if (NT_SUCCESS(status)) {
  953. Error = NO_ERROR;
  954. } else {
  955. Error = RtlNtStatusToDosError(status);
  956. NhTrace(
  957. TRACE_FLAG_NAT,
  958. "NatDeleteTicket: Ioctl = %d",
  959. Error
  960. );
  961. }
  962. CloseHandle(WaitEvent);
  963. return Error;
  964. } // NatDeleteTicket
  965. ULONG
  966. NatGetInterfaceCharacteristics(
  967. ULONG Index
  968. )
  969. /*++
  970. Routine Description:
  971. This routine is invoked to determine whether the given interface:
  972. 1) Is a NAT boundary interface
  973. 2) Is a NAT private interface
  974. 3) Has the firewall enabled
  975. Note that this routine may be invoked even when the NAT
  976. is neither installed nor running; it operates as expected,
  977. since the interface list and lock are always initialized in 'DllMain'.
  978. Arguments:
  979. Index - the interface in question
  980. IsNatInterface - optionally set to TRUE if the given index
  981. is at all a NAT interface.
  982. Return Value:
  983. BOOLEAN - TRUE if the interface is a NAT boundary interface,
  984. FALSE otherwise.
  985. --*/
  986. {
  987. ULONG Result = 0;
  988. PNAT_INTERFACE Interfacep;
  989. PROFILE("NatGetInterfaceCharacteristics");
  990. EnterCriticalSection(&NatInterfaceLock);
  991. if (!(Interfacep = NatpLookupInterface(Index, NULL))) {
  992. LeaveCriticalSection(&NatInterfaceLock);
  993. return Result;
  994. }
  995. if (Interfacep->Info &&
  996. (Interfacep->Info->Flags & IP_NAT_INTERFACE_FLAGS_FW)) {
  997. Result = NAT_IF_CHAR_FW;
  998. }
  999. if (Interfacep->Info &&
  1000. (Interfacep->Info->Flags & IP_NAT_INTERFACE_FLAGS_BOUNDARY)) {
  1001. Result |= NAT_IF_CHAR_BOUNDARY;
  1002. } else if (!NAT_IFC_FW(Result)) {
  1003. //
  1004. // As the interface isn't public and isn't firewalled, it must
  1005. // be a private interface (or we wouldn't have a record of it).
  1006. //
  1007. Result |= NAT_IF_CHAR_PRIVATE;
  1008. }
  1009. LeaveCriticalSection(&NatInterfaceLock);
  1010. return Result;
  1011. } // NatGetInterfaceCharacteristics
  1012. VOID
  1013. NatInstallApplicationSettings(
  1014. VOID
  1015. )
  1016. /*++
  1017. Routine Description:
  1018. This routine is invoked to update the application settings
  1019. (i.e., dynamic tickets) stored with the kernel-mode translation module.
  1020. Arguments:
  1021. none
  1022. Return Value:
  1023. none.
  1024. --*/
  1025. {
  1026. PNAT_APP_ENTRY pAppEntry;
  1027. ULONG Count;
  1028. PIP_NAT_CREATE_DYNAMIC_TICKET CreateTicket;
  1029. IO_STATUS_BLOCK IoStatus;
  1030. ULONG Length;
  1031. PLIST_ENTRY Link;
  1032. NTSTATUS status;
  1033. HANDLE WaitEvent;
  1034. PROFILE("NatInstallApplicationSettings");
  1035. //
  1036. // Install a dynamic ticket for each entry in the applications list
  1037. //
  1038. EnterCriticalSection(&NatInterfaceLock);
  1039. EnterCriticalSection(&NhLock);
  1040. WaitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  1041. if (WaitEvent == NULL) {
  1042. LeaveCriticalSection(&NhLock);
  1043. LeaveCriticalSection(&NatInterfaceLock);
  1044. NhTrace(
  1045. TRACE_FLAG_NAT,
  1046. "NatInstallSharedAccessSettings: CreateEvent failed [%d]",
  1047. GetLastError()
  1048. );
  1049. return;
  1050. }
  1051. for (Link = NhApplicationSettingsList.Flink;
  1052. Link != &NhApplicationSettingsList;
  1053. Link = Link->Flink)
  1054. {
  1055. //
  1056. // Each 'application' has a list of 'responses' which specify
  1057. // the ports on which response-sessions are expected.
  1058. // Enumerate the responses and allocate a ticket-structure
  1059. // large enough to hold the list as an array.
  1060. //
  1061. pAppEntry = CONTAINING_RECORD(Link, NAT_APP_ENTRY, Link);
  1062. Length =
  1063. pAppEntry->ResponseCount * sizeof(CreateTicket->ResponseArray[0]) +
  1064. FIELD_OFFSET(IP_NAT_CREATE_DYNAMIC_TICKET, ResponseArray);
  1065. if (!(CreateTicket =
  1066. reinterpret_cast<PIP_NAT_CREATE_DYNAMIC_TICKET>(
  1067. NH_ALLOCATE(Length)
  1068. )))
  1069. { break; }
  1070. //
  1071. // Fill in the ticket structure from the application entry
  1072. // and its list of response-entries.
  1073. //
  1074. CreateTicket->Protocol = pAppEntry->Protocol;
  1075. CreateTicket->Port = pAppEntry->Port;
  1076. CreateTicket->ResponseCount = pAppEntry->ResponseCount;
  1077. for (Count = 0; Count < pAppEntry->ResponseCount; Count++)
  1078. {
  1079. CreateTicket->ResponseArray[Count].Protocol =
  1080. pAppEntry->ResponseArray[Count].ucIPProtocol;
  1081. CreateTicket->ResponseArray[Count].StartPort =
  1082. pAppEntry->ResponseArray[Count].usStartPort;
  1083. CreateTicket->ResponseArray[Count].EndPort =
  1084. pAppEntry->ResponseArray[Count].usEndPort;
  1085. }
  1086. //
  1087. // Install the dynamic ticket for this application, and continue.
  1088. //
  1089. status = NtDeviceIoControlFile(
  1090. NatFileHandle,
  1091. WaitEvent,
  1092. NULL,
  1093. NULL,
  1094. &IoStatus,
  1095. IOCTL_IP_NAT_CREATE_DYNAMIC_TICKET,
  1096. (PVOID)CreateTicket,
  1097. Length,
  1098. NULL,
  1099. 0
  1100. );
  1101. if (status == STATUS_PENDING) {
  1102. WaitForSingleObject(WaitEvent, INFINITE);
  1103. status = IoStatus.Status;
  1104. }
  1105. NH_FREE(CreateTicket);
  1106. }
  1107. LeaveCriticalSection(&NhLock);
  1108. LeaveCriticalSection(&NatInterfaceLock);
  1109. CloseHandle(WaitEvent);
  1110. } // NatInstallApplicationSettings
  1111. BOOLEAN
  1112. NatIsBoundaryInterface(
  1113. ULONG Index,
  1114. PBOOLEAN IsNatInterface OPTIONAL
  1115. )
  1116. /*++
  1117. Routine Description:
  1118. This routine is invoked to determine whether the given interface
  1119. has the NAT enabled and is marked as a boundary interface.
  1120. Note that this routine may be invoked even when the NAT
  1121. is neither installed nor running; it operates as expected,
  1122. since the interface list and lock are always initialized in 'DllMain'.
  1123. Arguments:
  1124. Index - the interface in question
  1125. IsNatInterface - optionally set to TRUE if the given index
  1126. is at all a NAT interface.
  1127. Return Value:
  1128. BOOLEAN - TRUE if the interface is a NAT boundary interface,
  1129. FALSE otherwise.
  1130. --*/
  1131. {
  1132. PNAT_INTERFACE Interfacep;
  1133. PROFILE("NatIsBoundaryInterface");
  1134. EnterCriticalSection(&NatInterfaceLock);
  1135. if (!(Interfacep = NatpLookupInterface(Index, NULL))) {
  1136. LeaveCriticalSection(&NatInterfaceLock);
  1137. if (IsNatInterface) { *IsNatInterface = FALSE; }
  1138. return FALSE;
  1139. }
  1140. if (IsNatInterface) { *IsNatInterface = TRUE; }
  1141. if (Interfacep->Info &&
  1142. (Interfacep->Info->Flags & IP_NAT_INTERFACE_FLAGS_BOUNDARY)) {
  1143. LeaveCriticalSection(&NatInterfaceLock);
  1144. return TRUE;
  1145. }
  1146. LeaveCriticalSection(&NatInterfaceLock);
  1147. return FALSE;
  1148. } // NatIsBoundaryInterface
  1149. PNAT_INTERFACE
  1150. NatpLookupInterface(
  1151. ULONG Index,
  1152. OUT PLIST_ENTRY* InsertionPoint OPTIONAL
  1153. )
  1154. /*++
  1155. Routine Description:
  1156. This routine is called to retrieve an interface given its index.
  1157. Arguments:
  1158. Index - the index of the interface to be retrieved
  1159. InsertionPoint - if the interface is not found, optionally receives
  1160. the point where the interface would be inserted in the interface list
  1161. Return Value:
  1162. PNAT_INTERFACE - the interface, if found; otherwise, NULL.
  1163. Environment:
  1164. Invoked internally from an arbitrary context, with 'NatInterfaceLock'
  1165. held by caller.
  1166. --*/
  1167. {
  1168. PNAT_INTERFACE Interfacep;
  1169. PLIST_ENTRY Link;
  1170. PROFILE("NatpLookupInterface");
  1171. for (Link = NatInterfaceList.Flink; Link != &NatInterfaceList;
  1172. Link = Link->Flink) {
  1173. Interfacep = CONTAINING_RECORD(Link, NAT_INTERFACE, Link);
  1174. if (Index > Interfacep->Index) {
  1175. continue;
  1176. } else if (Index < Interfacep->Index) {
  1177. break;
  1178. }
  1179. return Interfacep;
  1180. }
  1181. if (InsertionPoint) { *InsertionPoint = Link; }
  1182. return NULL;
  1183. } // NatpLookupInterface
  1184. ULONG
  1185. NatQueryInterface(
  1186. ULONG Index,
  1187. PIP_NAT_INTERFACE_INFO InterfaceInfo,
  1188. PULONG InterfaceInfoSize
  1189. )
  1190. /*++
  1191. Routine Description:
  1192. This routine is invoked to retrieve the information for a NAT interface.
  1193. Arguments:
  1194. Index - the interface whose information is to be queried
  1195. InterfaceInfo - receives the information
  1196. InterfaceInfoSize - receives the information size
  1197. Return Value:
  1198. ULONG - Win32 status code.
  1199. --*/
  1200. {
  1201. ULONG Error;
  1202. PNAT_INTERFACE Interfacep;
  1203. ULONG Size;
  1204. PROFILE("NatQueryInterface");
  1205. //
  1206. // Look up the interface to be queried
  1207. //
  1208. EnterCriticalSection(&NatInterfaceLock);
  1209. if (!(Interfacep = NatpLookupInterface(Index, NULL))) {
  1210. LeaveCriticalSection(&NatInterfaceLock);
  1211. NhTrace(
  1212. TRACE_FLAG_NAT,
  1213. "NatQueryInterface: interface %d not found",
  1214. Index
  1215. );
  1216. return ERROR_NO_SUCH_INTERFACE;
  1217. }
  1218. //
  1219. // Compute the required size
  1220. //
  1221. Size =
  1222. FIELD_OFFSET(IP_NAT_INTERFACE_INFO, Header) +
  1223. Interfacep->Info->Header.Size;
  1224. if (Size >= *InterfaceInfoSize) {
  1225. *InterfaceInfoSize = Size;
  1226. Error = ERROR_INSUFFICIENT_BUFFER;
  1227. } else {
  1228. *InterfaceInfoSize = Size;
  1229. CopyMemory(
  1230. InterfaceInfo,
  1231. Interfacep->Info,
  1232. Size
  1233. );
  1234. Error = NO_ERROR;
  1235. }
  1236. LeaveCriticalSection(&NatInterfaceLock);
  1237. return Error;
  1238. } // NatQueryInterface
  1239. ULONG
  1240. NatQueryInterfaceMappingTable(
  1241. ULONG Index,
  1242. PIP_NAT_ENUMERATE_SESSION_MAPPINGS EnumerateTable,
  1243. PULONG EnumerateTableSize
  1244. )
  1245. /*++
  1246. Routine Description:
  1247. This routine is invoked to retrieve the session mappings for an interface.
  1248. Arguments:
  1249. EnumerateTable - receives the enumerated mappings
  1250. EnumerateTableSize - indicates the size of 'EnumerateTable'
  1251. Return Value:
  1252. ULONG - Win32 error code.
  1253. --*/
  1254. {
  1255. IP_NAT_ENUMERATE_SESSION_MAPPINGS Enumerate;
  1256. PNAT_INTERFACE Interfacep;
  1257. IO_STATUS_BLOCK IoStatus;
  1258. ULONG RequiredSize;
  1259. NTSTATUS status;
  1260. HANDLE WaitEvent;
  1261. PROFILE("NatQueryInterfaceMappingTable");
  1262. EnterCriticalSection(&NatInterfaceLock);
  1263. if (!(Interfacep = NatpLookupInterface(Index, NULL))) {
  1264. LeaveCriticalSection(&NatInterfaceLock);
  1265. NhTrace(
  1266. TRACE_FLAG_NAT,
  1267. "NatQueryInterfaceMappingTable: interface %d not found",
  1268. Index
  1269. );
  1270. return ERROR_NO_SUCH_INTERFACE;
  1271. }
  1272. if (!NAT_INTERFACE_BOUND(Interfacep)) {
  1273. //
  1274. // The interface is not bound, so there aren't any mappings.
  1275. // Indicate zero mappings in the caller's request-buffer.
  1276. //
  1277. LeaveCriticalSection(&NatInterfaceLock);
  1278. RequiredSize =
  1279. FIELD_OFFSET(IP_NAT_ENUMERATE_SESSION_MAPPINGS, EnumerateTable[0]);
  1280. if (*EnumerateTableSize < RequiredSize) {
  1281. *EnumerateTableSize = RequiredSize;
  1282. return ERROR_INSUFFICIENT_BUFFER;
  1283. }
  1284. EnumerateTable->Index = Index;
  1285. EnumerateTable->EnumerateContext[0] = 0;
  1286. EnumerateTable->EnumerateCount = 0;
  1287. *EnumerateTableSize = RequiredSize;
  1288. return NO_ERROR;
  1289. }
  1290. WaitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  1291. if (WaitEvent == NULL) {
  1292. LeaveCriticalSection(&NatInterfaceLock);
  1293. NhTrace(
  1294. TRACE_FLAG_NAT,
  1295. "NatQueryInterfaceMappingTable: CreateEvent failed [%d]",
  1296. GetLastError()
  1297. );
  1298. return ERROR_NOT_ENOUGH_MEMORY;
  1299. }
  1300. //
  1301. // Determine the amount of space required
  1302. //
  1303. Enumerate.Index = Interfacep->AdapterIndex;
  1304. Enumerate.EnumerateCount = 0;
  1305. Enumerate.EnumerateContext[0] = 0;
  1306. status =
  1307. NtDeviceIoControlFile(
  1308. NatFileHandle,
  1309. WaitEvent,
  1310. NULL,
  1311. NULL,
  1312. &IoStatus,
  1313. IOCTL_IP_NAT_GET_INTERFACE_MAPPING_TABLE,
  1314. (PVOID)&Enumerate,
  1315. sizeof(Enumerate),
  1316. (PVOID)&Enumerate,
  1317. sizeof(Enumerate)
  1318. );
  1319. if (status == STATUS_PENDING) {
  1320. WaitForSingleObject(WaitEvent, INFINITE);
  1321. status = IoStatus.Status;
  1322. }
  1323. if (!NT_SUCCESS(status)) {
  1324. CloseHandle(WaitEvent);
  1325. LeaveCriticalSection(&NatInterfaceLock);
  1326. *EnumerateTableSize = 0;
  1327. return RtlNtStatusToDosError(status);
  1328. }
  1329. RequiredSize =
  1330. FIELD_OFFSET(IP_NAT_ENUMERATE_SESSION_MAPPINGS, EnumerateTable[0]) +
  1331. Enumerate.EnumerateTotalHint * sizeof(IP_NAT_SESSION_MAPPING);
  1332. //
  1333. // If the caller doesn't have enough space for all these mappings, fail
  1334. //
  1335. if (*EnumerateTableSize < RequiredSize) {
  1336. CloseHandle(WaitEvent);
  1337. LeaveCriticalSection(&NatInterfaceLock);
  1338. *EnumerateTableSize = RequiredSize + 5 * sizeof(IP_NAT_SESSION_MAPPING);
  1339. return ERROR_INSUFFICIENT_BUFFER;
  1340. }
  1341. //
  1342. // Attempt to read the mappings
  1343. //
  1344. Enumerate.Index = Interfacep->AdapterIndex;
  1345. Enumerate.EnumerateCount = 0;
  1346. Enumerate.EnumerateContext[0] = 0;
  1347. status =
  1348. NtDeviceIoControlFile(
  1349. NatFileHandle,
  1350. WaitEvent,
  1351. NULL,
  1352. NULL,
  1353. &IoStatus,
  1354. IOCTL_IP_NAT_GET_INTERFACE_MAPPING_TABLE,
  1355. (PVOID)&Enumerate,
  1356. sizeof(Enumerate),
  1357. (PVOID)EnumerateTable,
  1358. *EnumerateTableSize
  1359. );
  1360. if (status == STATUS_PENDING) {
  1361. WaitForSingleObject(WaitEvent, INFINITE);
  1362. status = IoStatus.Status;
  1363. }
  1364. CloseHandle(WaitEvent);
  1365. LeaveCriticalSection(&NatInterfaceLock);
  1366. EnumerateTable->Index = Index;
  1367. *EnumerateTableSize =
  1368. FIELD_OFFSET(IP_NAT_ENUMERATE_SESSION_MAPPINGS, EnumerateTable[0]) +
  1369. EnumerateTable->EnumerateCount * sizeof(IP_NAT_SESSION_MAPPING);
  1370. return NT_SUCCESS(status) ? NO_ERROR : RtlNtStatusToDosError(status);
  1371. } // NatQueryInterfaceMappingTable
  1372. ULONG
  1373. NatQueryMappingTable(
  1374. PIP_NAT_ENUMERATE_SESSION_MAPPINGS EnumerateTable,
  1375. PULONG EnumerateTableSize
  1376. )
  1377. /*++
  1378. Routine Description:
  1379. This routine is invoked to retrieve the session mappings for an interface.
  1380. Arguments:
  1381. EnumerateTable - receives the enumerated mappings
  1382. EnumerateTableSize - indicates the size of 'EnumerateTable'
  1383. Return Value:
  1384. ULONG - Win32 error code.
  1385. --*/
  1386. {
  1387. IP_NAT_ENUMERATE_SESSION_MAPPINGS Enumerate;
  1388. IO_STATUS_BLOCK IoStatus;
  1389. ULONG RequiredSize;
  1390. NTSTATUS status;
  1391. HANDLE WaitEvent;
  1392. PROFILE("NatQueryMappingTable");
  1393. WaitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  1394. if (WaitEvent == NULL) {
  1395. NhTrace(
  1396. TRACE_FLAG_NAT,
  1397. "NatQueryMappingTable: CreateEvent failed [%d]",
  1398. GetLastError()
  1399. );
  1400. return ERROR_NOT_ENOUGH_MEMORY;
  1401. }
  1402. EnterCriticalSection(&NatInterfaceLock);
  1403. //
  1404. // Determine the amount of space required
  1405. //
  1406. Enumerate.EnumerateCount = 0;
  1407. Enumerate.EnumerateContext[0] = 0;
  1408. status =
  1409. NtDeviceIoControlFile(
  1410. NatFileHandle,
  1411. WaitEvent,
  1412. NULL,
  1413. NULL,
  1414. &IoStatus,
  1415. IOCTL_IP_NAT_GET_MAPPING_TABLE,
  1416. (PVOID)&Enumerate,
  1417. sizeof(Enumerate),
  1418. (PVOID)&Enumerate,
  1419. sizeof(Enumerate)
  1420. );
  1421. if (status == STATUS_PENDING) {
  1422. WaitForSingleObject(WaitEvent, INFINITE);
  1423. status = IoStatus.Status;
  1424. }
  1425. if (!NT_SUCCESS(status)) {
  1426. LeaveCriticalSection(&NatInterfaceLock);
  1427. CloseHandle(WaitEvent);
  1428. *EnumerateTableSize = 0;
  1429. return RtlNtStatusToDosError(status);
  1430. }
  1431. RequiredSize =
  1432. FIELD_OFFSET(IP_NAT_ENUMERATE_SESSION_MAPPINGS, EnumerateTable[0]) +
  1433. Enumerate.EnumerateTotalHint * sizeof(IP_NAT_SESSION_MAPPING);
  1434. //
  1435. // If the caller doesn't have enough space for all these mappings, fail
  1436. //
  1437. if (*EnumerateTableSize < RequiredSize) {
  1438. LeaveCriticalSection(&NatInterfaceLock);
  1439. CloseHandle(WaitEvent);
  1440. *EnumerateTableSize = RequiredSize + 5 * sizeof(IP_NAT_SESSION_MAPPING);
  1441. return ERROR_INSUFFICIENT_BUFFER;
  1442. }
  1443. //
  1444. // Attempt to read the mappings
  1445. //
  1446. Enumerate.EnumerateCount = 0;
  1447. Enumerate.EnumerateContext[0] = 0;
  1448. status =
  1449. NtDeviceIoControlFile(
  1450. NatFileHandle,
  1451. WaitEvent,
  1452. NULL,
  1453. NULL,
  1454. &IoStatus,
  1455. IOCTL_IP_NAT_GET_MAPPING_TABLE,
  1456. (PVOID)&Enumerate,
  1457. sizeof(Enumerate),
  1458. (PVOID)EnumerateTable,
  1459. *EnumerateTableSize
  1460. );
  1461. if (status == STATUS_PENDING) {
  1462. WaitForSingleObject(WaitEvent, INFINITE);
  1463. status = IoStatus.Status;
  1464. }
  1465. CloseHandle(WaitEvent);
  1466. LeaveCriticalSection(&NatInterfaceLock);
  1467. EnumerateTable->Index = (ULONG)-1;
  1468. *EnumerateTableSize =
  1469. FIELD_OFFSET(IP_NAT_ENUMERATE_SESSION_MAPPINGS, EnumerateTable[0]) +
  1470. EnumerateTable->EnumerateCount * sizeof(IP_NAT_SESSION_MAPPING);
  1471. return NT_SUCCESS(status) ? NO_ERROR : RtlNtStatusToDosError(status);
  1472. } // NatQueryMappingTable
  1473. ULONG
  1474. NatQueryStatisticsInterface(
  1475. ULONG Index,
  1476. PIP_NAT_INTERFACE_STATISTICS InterfaceStatistics,
  1477. PULONG InterfaceStatisticsSize
  1478. )
  1479. /*++
  1480. Routine Description:
  1481. This routine is invoked to retrieve the statistics for a NAT interface.
  1482. Arguments:
  1483. Index - the index of the interface whose statistics are to be retrieved
  1484. Return Value:
  1485. ULONG - Win32 error code.
  1486. --*/
  1487. {
  1488. PNAT_INTERFACE Interfacep;
  1489. IO_STATUS_BLOCK IoStatus;
  1490. NTSTATUS status;
  1491. HANDLE WaitEvent;
  1492. PROFILE("NatQueryStatisticsInterface");
  1493. //
  1494. // Look up the interface to be queried
  1495. //
  1496. EnterCriticalSection(&NatInterfaceLock);
  1497. if (!(Interfacep = NatpLookupInterface(Index, NULL))) {
  1498. LeaveCriticalSection(&NatInterfaceLock);
  1499. NhTrace(
  1500. TRACE_FLAG_NAT,
  1501. "NatQueryStatisticsInterface: interface %d not found",
  1502. Index
  1503. );
  1504. return ERROR_NO_SUCH_INTERFACE;
  1505. }
  1506. //
  1507. // If the interface is not bound, supply zero statistics.
  1508. //
  1509. if (!NAT_INTERFACE_BOUND(Interfacep)) {
  1510. LeaveCriticalSection(&NatInterfaceLock);
  1511. if (*InterfaceStatisticsSize < sizeof(IP_NAT_INTERFACE_STATISTICS)) {
  1512. *InterfaceStatisticsSize = sizeof(IP_NAT_INTERFACE_STATISTICS);
  1513. return ERROR_INSUFFICIENT_BUFFER;
  1514. }
  1515. *InterfaceStatisticsSize = sizeof(IP_NAT_INTERFACE_STATISTICS);
  1516. ZeroMemory(InterfaceStatistics, sizeof(IP_NAT_INTERFACE_STATISTICS));
  1517. return NO_ERROR;
  1518. }
  1519. WaitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  1520. if (WaitEvent == NULL) {
  1521. LeaveCriticalSection(&NatInterfaceLock);
  1522. NhTrace(
  1523. TRACE_FLAG_NAT,
  1524. "NatQueryStatisticsInterface: CreateEvent failed [%d]",
  1525. GetLastError()
  1526. );
  1527. return ERROR_NOT_ENOUGH_MEMORY;
  1528. }
  1529. //
  1530. // Attempt to read the statistics for the interface
  1531. //
  1532. status =
  1533. NtDeviceIoControlFile(
  1534. NatFileHandle,
  1535. WaitEvent,
  1536. NULL,
  1537. NULL,
  1538. &IoStatus,
  1539. IOCTL_IP_NAT_GET_INTERFACE_STATISTICS,
  1540. (PVOID)&Interfacep->AdapterIndex,
  1541. sizeof(ULONG),
  1542. (PVOID)InterfaceStatistics,
  1543. *InterfaceStatisticsSize
  1544. );
  1545. if (status == STATUS_PENDING) {
  1546. WaitForSingleObject(WaitEvent, INFINITE);
  1547. status = IoStatus.Status;
  1548. }
  1549. CloseHandle(WaitEvent);
  1550. LeaveCriticalSection(&NatInterfaceLock);
  1551. if (NT_SUCCESS(status) && IoStatus.Information > *InterfaceStatisticsSize) {
  1552. *InterfaceStatisticsSize = (ULONG)IoStatus.Information;
  1553. return ERROR_INSUFFICIENT_BUFFER;
  1554. }
  1555. *InterfaceStatisticsSize = (ULONG)IoStatus.Information;
  1556. return NT_SUCCESS(status) ? NO_ERROR : RtlNtStatusToDosError(status);
  1557. } // NatQueryStatisticsInterface
  1558. VOID
  1559. NatRemoveApplicationSettings(
  1560. VOID
  1561. )
  1562. /*++
  1563. Routine Description:
  1564. This routine is invoked to remove the advanced application settings (i.e.,
  1565. dynamic tickets), and supply the settings to the kernel-mode translation
  1566. module.
  1567. Arguments:
  1568. none.
  1569. Return Value:
  1570. none.
  1571. --*/
  1572. {
  1573. PNAT_APP_ENTRY pAppEntry;
  1574. IP_NAT_DELETE_DYNAMIC_TICKET DeleteTicket;
  1575. IO_STATUS_BLOCK IoStatus;
  1576. PLIST_ENTRY Link;
  1577. NTSTATUS status;
  1578. HANDLE WaitEvent;
  1579. PROFILE("NatRemoveApplicationSettings");
  1580. //
  1581. // Each 'application' entry in the shared access settings
  1582. // corresponds to a dynamic ticket for the kernel-mode translator.
  1583. // We begin by removing the dynamic tickets for the old settings, if any,
  1584. // and then we free the old settings in preparation for reloading.
  1585. //
  1586. WaitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  1587. if (WaitEvent == NULL) {
  1588. NhTrace(
  1589. TRACE_FLAG_NAT,
  1590. "NatRemoveSharedAccessSettings: CreateEvent failed [%d]",
  1591. GetLastError()
  1592. );
  1593. return;
  1594. }
  1595. EnterCriticalSection(&NatInterfaceLock);
  1596. EnterCriticalSection(&NhLock);
  1597. for (Link = NhApplicationSettingsList.Flink;
  1598. Link != &NhApplicationSettingsList;
  1599. Link = Link->Flink)
  1600. {
  1601. pAppEntry = CONTAINING_RECORD(Link, NAT_APP_ENTRY, Link);
  1602. DeleteTicket.Protocol = pAppEntry->Protocol;
  1603. DeleteTicket.Port = pAppEntry->Port;
  1604. status =
  1605. NtDeviceIoControlFile(
  1606. NatFileHandle,
  1607. WaitEvent,
  1608. NULL,
  1609. NULL,
  1610. &IoStatus,
  1611. IOCTL_IP_NAT_DELETE_DYNAMIC_TICKET,
  1612. (PVOID)&DeleteTicket,
  1613. sizeof(DeleteTicket),
  1614. NULL,
  1615. 0
  1616. );
  1617. if (status == STATUS_PENDING) {
  1618. WaitForSingleObject(WaitEvent, INFINITE);
  1619. status = IoStatus.Status;
  1620. }
  1621. }
  1622. LeaveCriticalSection(&NhLock);
  1623. LeaveCriticalSection(&NatInterfaceLock);
  1624. CloseHandle(WaitEvent);
  1625. } // NatRemoveSharedAccessSettings
  1626. ULONG
  1627. NatUnbindInterface(
  1628. ULONG Index,
  1629. PNAT_INTERFACE Interfacep
  1630. )
  1631. /*++
  1632. Routine Description:
  1633. This routine is invoked to remove a binding from the NAT.
  1634. Arguments:
  1635. Index - the interface to be unbound
  1636. Interfacep - optionally supplies the interface-structure to be unbound
  1637. (See 'NATCONN.C' which passes in a static interface-structure).
  1638. Return Value:
  1639. ULONG - Win32 status code.
  1640. --*/
  1641. {
  1642. ULONG Error;
  1643. IO_STATUS_BLOCK IoStatus;
  1644. NTSTATUS status;
  1645. HANDLE WaitEvent;
  1646. PROFILE("NatUnbindInterface");
  1647. WaitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  1648. if (WaitEvent == NULL) {
  1649. NhTrace(
  1650. TRACE_FLAG_NAT,
  1651. "NatUnbindInterface: CreateEvent failed [%d]",
  1652. GetLastError()
  1653. );
  1654. return ERROR_NOT_ENOUGH_MEMORY;
  1655. }
  1656. //
  1657. // Retrieve the interface to be unbound.
  1658. //
  1659. EnterCriticalSection(&NatInterfaceLock);
  1660. if (!Interfacep && !(Interfacep = NatpLookupInterface(Index, NULL))) {
  1661. LeaveCriticalSection(&NatInterfaceLock);
  1662. NhTrace(
  1663. TRACE_FLAG_NAT,
  1664. "NatUnbindInterface: interface %d not found",
  1665. Index
  1666. );
  1667. return ERROR_NO_SUCH_INTERFACE;
  1668. }
  1669. //
  1670. // Make sure the interface is not already unbound
  1671. //
  1672. if (!NAT_INTERFACE_BOUND(Interfacep)) {
  1673. LeaveCriticalSection(&NatInterfaceLock);
  1674. NhTrace(
  1675. TRACE_FLAG_NAT,
  1676. "NatUnbindInterface: interface %d already unbound",
  1677. Index
  1678. );
  1679. return ERROR_ADDRESS_NOT_ASSOCIATED;
  1680. }
  1681. Interfacep->Flags &= ~NAT_INTERFACE_FLAG_BOUND;
  1682. if (Interfacep->Type == ROUTER_IF_TYPE_DEDICATED) {
  1683. NatUpdateProxyArp(Interfacep, FALSE);
  1684. }
  1685. //
  1686. // Remove the interface from the kernel-mode driver
  1687. //
  1688. status =
  1689. NtDeviceIoControlFile(
  1690. NatFileHandle,
  1691. WaitEvent,
  1692. NULL,
  1693. NULL,
  1694. &IoStatus,
  1695. IOCTL_IP_NAT_DELETE_INTERFACE,
  1696. (PVOID)&Interfacep->AdapterIndex,
  1697. sizeof(ULONG),
  1698. NULL,
  1699. 0
  1700. );
  1701. if (status == STATUS_PENDING) {
  1702. WaitForSingleObject(WaitEvent, INFINITE);
  1703. status = IoStatus.Status;
  1704. }
  1705. LeaveCriticalSection(&NatInterfaceLock);
  1706. CloseHandle(WaitEvent);
  1707. Error = NT_SUCCESS(status) ? NO_ERROR : RtlNtStatusToDosError(status);
  1708. if (Error) {
  1709. NhErrorLog(
  1710. IP_NAT_LOG_IOCTL_FAILED,
  1711. Error,
  1712. ""
  1713. );
  1714. }
  1715. return Error;
  1716. } // NatUnbindInterface
  1717. ULONG
  1718. NatLookupPortMappingAdapter(
  1719. ULONG AdapterIndex,
  1720. UCHAR Protocol,
  1721. ULONG PublicAddress,
  1722. USHORT PublicPort,
  1723. PIP_NAT_PORT_MAPPING PortMappingp
  1724. )
  1725. /*++
  1726. Routine Description:
  1727. This routine is invoked to find a mapping that matches the given adapter,
  1728. protocol, public address and public port number. The routine tries to
  1729. match both port and address mapping.
  1730. Arguments:
  1731. AdapterIndex - the adapter to be looked up
  1732. Protocol - protocol used to match a mapping
  1733. PublicAddress - public address used to match a mapping
  1734. PublicPort - public port number used to match a mapping
  1735. PortMappingp - pointer to a caller-supplied storage to save the mapping if
  1736. found
  1737. Return Value:
  1738. ULONG - Win32 status code.
  1739. --*/
  1740. {
  1741. IP_NAT_CREATE_TICKET LookupTicket;
  1742. ULONG Error;
  1743. IO_STATUS_BLOCK IoStatus;
  1744. NTSTATUS status;
  1745. HANDLE WaitEvent;
  1746. PROFILE("NatLookupPortMappingAdapter");
  1747. Error = NO_ERROR;
  1748. WaitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  1749. if (WaitEvent == NULL) {
  1750. NhTrace(
  1751. TRACE_FLAG_NAT,
  1752. "NatLookupPortMappingAdapter:"
  1753. " CreateEvent failed [%d] for adapter %d",
  1754. GetLastError(),
  1755. AdapterIndex
  1756. );
  1757. return ERROR_NOT_ENOUGH_MEMORY;
  1758. }
  1759. LookupTicket.InterfaceIndex = AdapterIndex;
  1760. LookupTicket.PortMapping.Protocol = Protocol;
  1761. LookupTicket.PortMapping.PublicPort = PublicPort;
  1762. LookupTicket.PortMapping.PublicAddress = PublicAddress;
  1763. LookupTicket.PortMapping.PrivatePort = 0;
  1764. LookupTicket.PortMapping.PrivateAddress = 0;
  1765. status =
  1766. NtDeviceIoControlFile(
  1767. NatFileHandle,
  1768. WaitEvent,
  1769. NULL,
  1770. NULL,
  1771. &IoStatus,
  1772. IOCTL_IP_NAT_LOOKUP_TICKET,
  1773. (PVOID)&LookupTicket,
  1774. sizeof(LookupTicket),
  1775. (PVOID)PortMappingp,
  1776. sizeof(*PortMappingp)
  1777. );
  1778. if (status == STATUS_PENDING) {
  1779. WaitForSingleObject(WaitEvent, INFINITE);
  1780. status = IoStatus.Status;
  1781. }
  1782. if (!NT_SUCCESS(status)) {
  1783. NhTrace(
  1784. TRACE_FLAG_NAT,
  1785. "NatLookupPortMappingAdapter:"
  1786. " status %08x getting info for adapter %d",
  1787. status,
  1788. AdapterIndex
  1789. );
  1790. Error = RtlNtStatusToDosError(status);
  1791. }
  1792. CloseHandle(WaitEvent);
  1793. return Error;
  1794. }
  1795. ULONG
  1796. NatExpandWildcardMappings(
  1797. IN PIP_NAT_INTERFACE_INFO InInfo,
  1798. IN PIP_ADAPTER_BINDING_INFO BindingInfo,
  1799. OUT PIP_NAT_INTERFACE_INFO *ExpandedInfo
  1800. )
  1801. /*++
  1802. Routine Description:
  1803. This routine is invoked to expand any wildcard(address) mappings, into one
  1804. mapping per ipaddress bound to the interface
  1805. Assumes that information pointed to by InInfo and BindingInfo does not
  1806. change during the duration of this function
  1807. Arguments:
  1808. InInfo - Pointer to the set of mappings to be expanded
  1809. ExpandedInfo - On successful completion, ExpandedInfo contains a pointer
  1810. to the expanded set of mappings.
  1811. If there were mappings that needed expansion, the function
  1812. will allocate the memory for this new set of
  1813. mappings.
  1814. If no expansion is required, ExpandedInfo will point to the
  1815. same location as InInfo.
  1816. Return Value:
  1817. ULONG - Win32 status code.
  1818. If there are no wildcard mappings, it returns ERROR_EXTENDED_ERROR
  1819. In case of success: NO_ERROR is returned
  1820. --*/
  1821. {
  1822. ULONG Error;
  1823. ULONG Size;
  1824. DWORD j, k;
  1825. DWORD MappingSize;
  1826. DWORD CountOldMappings, CountNewMappings, CountWildcardMappings;
  1827. DWORD tempCount;
  1828. PIP_NAT_PORT_MAPPING OldMappings = NULL;
  1829. PIP_NAT_PORT_MAPPING NewMappings = NULL;
  1830. PIP_NAT_INTERFACE_INFO NewInterfaceInfo = NULL;
  1831. PRTR_INFO_BLOCK_HEADER NewHeader = NULL;
  1832. Error = NO_ERROR;
  1833. //
  1834. // If a mapping with
  1835. // public ip address = 0
  1836. // private ip address = 127.0.0.1
  1837. // exists, expand that mapping to one mapping for each of the ipaddresses
  1838. // bound to the interface.
  1839. //
  1840. NewInterfaceInfo = InInfo;
  1841. do {
  1842. //
  1843. // We don't do any expansion in case of a private interface
  1844. //
  1845. if ( InInfo->Flags == 0 ) {
  1846. break;
  1847. }
  1848. //
  1849. // If no port mappings exist, break out
  1850. //
  1851. Error = MprInfoBlockFind(
  1852. (LPVOID)&(InInfo->Header),
  1853. IP_NAT_PORT_MAPPING_TYPE,
  1854. &MappingSize,
  1855. &CountOldMappings,
  1856. (LPBYTE *)&OldMappings);
  1857. if ( Error != NO_ERROR ) {
  1858. if ( Error == ERROR_NOT_FOUND ) {
  1859. Error = NO_ERROR;
  1860. }
  1861. break;
  1862. }
  1863. //
  1864. // Count how many mappings need to be expanded
  1865. //
  1866. CountWildcardMappings = 0;
  1867. for ( j = 0; j < CountOldMappings; j++ ) {
  1868. if ( IS_WILDCARD_MAPPING(&(OldMappings[j])) ) {
  1869. CountWildcardMappings++;
  1870. }
  1871. }
  1872. //
  1873. // If there are no wildcard mappings
  1874. // return ERROR_EXTENDED_ERROR
  1875. //
  1876. if ( CountWildcardMappings == 0 ) {
  1877. break;
  1878. }
  1879. //
  1880. // allocate memory to hold the new set of mappings
  1881. // Number of new mappings will be
  1882. //
  1883. // ( (OldMappings - WildcardMappings) +
  1884. // (WildcardMappings * "no of bound ipaddresses") )
  1885. //
  1886. CountNewMappings =
  1887. (CountOldMappings +
  1888. (CountWildcardMappings * (BindingInfo->AddressCount-1)));
  1889. Size = CountNewMappings * MappingSize;
  1890. NewMappings = (PIP_NAT_PORT_MAPPING)NH_ALLOCATE(Size);
  1891. if ( NewMappings == NULL ) {
  1892. NhTrace(
  1893. TRACE_FLAG_NAT,
  1894. "Failed to allocate buffer for expanded mappings. Size: %d",
  1895. Size
  1896. );
  1897. NhErrorLog(
  1898. IP_NAT_LOG_ALLOCATION_FAILED,
  1899. 0,
  1900. "%d",
  1901. Size
  1902. );
  1903. //
  1904. // If we can't get the buffer, forget about expanding the mappings
  1905. // and go on with life.
  1906. //
  1907. Error = ERROR_NOT_ENOUGH_MEMORY;
  1908. break;
  1909. }
  1910. tempCount = 0;
  1911. for ( j = 0; j < CountOldMappings; j++ ) {
  1912. if (IS_WILDCARD_MAPPING(&(OldMappings[j]))) {
  1913. for ( k = 0; k < BindingInfo->AddressCount; k++ ) {
  1914. CopyMemory(&(NewMappings[tempCount]), &(OldMappings[j]),
  1915. sizeof(IP_NAT_PORT_MAPPING));
  1916. NewMappings[tempCount].PublicAddress =
  1917. NewMappings[tempCount].PrivateAddress = BindingInfo->Address[k].Address;
  1918. tempCount++;
  1919. }
  1920. }
  1921. else {
  1922. CopyMemory(&(NewMappings[tempCount]), &(OldMappings[j]),
  1923. sizeof(IP_NAT_PORT_MAPPING));
  1924. tempCount++;
  1925. }
  1926. }
  1927. if ( tempCount != CountNewMappings ) {
  1928. NhTrace(
  1929. TRACE_FLAG_NAT,
  1930. "NatExpandWildcardMappings: Unexpected number of expanded "
  1931. "mappings: %d. Expected: %d",
  1932. tempCount,
  1933. CountNewMappings
  1934. );
  1935. Error = ERROR_INVALID_DATA;
  1936. break;
  1937. }
  1938. #if DBG
  1939. {
  1940. char publicAddress[128];
  1941. char privateAddress[128];
  1942. NhTrace(
  1943. TRACE_FLAG_NAT,
  1944. "NatExpandWildcardMappings: Expanded set of "
  1945. "mappings. Total: %d\r\n",
  1946. CountNewMappings
  1947. );
  1948. for ( j = 0; j < CountNewMappings; j++ ) {
  1949. _snprintf(
  1950. publicAddress,
  1951. 127,
  1952. INET_NTOA(NewMappings[j].PublicAddress)
  1953. );
  1954. _snprintf(
  1955. privateAddress,
  1956. 127,
  1957. INET_NTOA(NewMappings[j].PrivateAddress)
  1958. );
  1959. NhTrace(
  1960. TRACE_FLAG_NAT,
  1961. "\tProto: %u, PubPort: %hu, PubAdd: %s, "
  1962. "PrivPort: %hu, PrivAdd: %s\r\n",
  1963. NewMappings[j].Protocol & 0xFF,
  1964. ntohs(NewMappings[j].PublicPort),
  1965. publicAddress,
  1966. ntohs(NewMappings[j].PrivatePort),
  1967. privateAddress
  1968. );
  1969. }
  1970. }
  1971. #endif
  1972. //
  1973. // Now create the new header
  1974. //
  1975. Error =
  1976. MprInfoBlockSet(
  1977. &(InInfo->Header),
  1978. IP_NAT_PORT_MAPPING_TYPE,
  1979. sizeof(IP_NAT_PORT_MAPPING),
  1980. CountNewMappings,
  1981. (LPBYTE)NewMappings,
  1982. (LPVOID *)&NewHeader);
  1983. if ( Error != NO_ERROR ) {
  1984. NhTrace(
  1985. TRACE_FLAG_NAT,
  1986. "MprInfoBlockSet failed with error: %d",
  1987. Error
  1988. );
  1989. break;
  1990. }
  1991. //
  1992. // Allocate space for a new IP_NAT_INTERFACE_INFO struct.
  1993. //
  1994. Size = FIELD_OFFSET(IP_NAT_INTERFACE_INFO, Header) + NewHeader->Size;
  1995. NewInterfaceInfo = (PIP_NAT_INTERFACE_INFO)NH_ALLOCATE(Size);
  1996. if ( NewInterfaceInfo == NULL ) {
  1997. NhTrace(
  1998. TRACE_FLAG_NAT,
  1999. "Failed to allocate buffer for new NatInterfaceInfo. Size: %d",
  2000. Size
  2001. );
  2002. NhErrorLog(
  2003. IP_NAT_LOG_ALLOCATION_FAILED,
  2004. 0,
  2005. "%d",
  2006. Size
  2007. );
  2008. //
  2009. // If we can't get the buffer, forget about fixing the mappings
  2010. // and go on with life.
  2011. //
  2012. Error = ERROR_NOT_ENOUGH_MEMORY;
  2013. break;
  2014. }
  2015. //
  2016. // Copy the old IP_NAT_INFTERFACE_INFO. Leave out the old header
  2017. //
  2018. CopyMemory(
  2019. NewInterfaceInfo,
  2020. InInfo,
  2021. FIELD_OFFSET(IP_NAT_INTERFACE_INFO, Header));
  2022. //
  2023. // Now copy the new header
  2024. //
  2025. CopyMemory(
  2026. ((BYTE *)NewInterfaceInfo +
  2027. FIELD_OFFSET(IP_NAT_INTERFACE_INFO, Header)),
  2028. NewHeader,
  2029. NewHeader->Size);
  2030. } while (FALSE);
  2031. if ( NewMappings ) { NH_FREE(NewMappings); }
  2032. if ( NewHeader ) { NH_FREE(NewHeader); }
  2033. if ( Error == NO_ERROR ) {
  2034. *ExpandedInfo = NewInterfaceInfo;
  2035. }
  2036. else {
  2037. if ( NewInterfaceInfo && NewInterfaceInfo != InInfo ) {
  2038. NH_FREE(NewInterfaceInfo);
  2039. }
  2040. }
  2041. return Error;
  2042. } // NatExpandWildcardMappings