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.

1212 lines
25 KiB

  1. /*++
  2. Copyright (c) 1997 Microsoft Corporation
  3. Module Name:
  4. entry.c
  5. Abstract:
  6. This module contains the entry-code for the IP Network Address Translator.
  7. Author:
  8. Abolade Gbadegesin (t-abolag) 11-July-1997
  9. Revision History:
  10. William Ingle (billi) 12-May-2001 NULL security descriptor check
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. //
  15. // GLOBAL DATA DEFINITIONS
  16. //
  17. COMPONENT_REFERENCE ComponentReference;
  18. //
  19. // Win32 device-name
  20. //
  21. WCHAR ExternalName[] = L"\\DosDevices\\IPNAT";
  22. //
  23. // Device- and file-object for the IP driver
  24. //
  25. extern PDEVICE_OBJECT IpDeviceObject = NULL;
  26. extern PFILE_OBJECT IpFileObject = NULL;
  27. extern HANDLE TcpDeviceHandle = NULL;
  28. //
  29. // Device-object for the NAT driver
  30. //
  31. extern PDEVICE_OBJECT NatDeviceObject = NULL;
  32. //
  33. // Registry parameters key name
  34. //
  35. WCHAR ParametersName[] = L"Parameters";
  36. //
  37. // Name of value holding reserved ports
  38. //
  39. WCHAR ReservedPortsName[] = L"ReservedPorts";
  40. //
  41. // Start and end of reserved-port range
  42. //
  43. USHORT ReservedPortsLowerRange = DEFAULT_START_PORT;
  44. USHORT ReservedPortsUpperRange = DEFAULT_END_PORT;
  45. //
  46. // Device- and file-object for the TCP driver
  47. //
  48. extern PDEVICE_OBJECT TcpDeviceObject = NULL;
  49. extern PFILE_OBJECT TcpFileObject = NULL;
  50. //
  51. // Registry path for the driver's parameters
  52. //
  53. const WCHAR IpNatParametersPath[] =
  54. L"\\Registry\\Machine\\System\\CurrentControlSet\\Services"
  55. L"\\IpNat\\Parameters";
  56. //
  57. // Timeout interval for TCP session mappings
  58. //
  59. ULONG TcpTimeoutSeconds = DEFAULT_TCP_TIMEOUT;
  60. //
  61. // Bitmap of enabled tracing message classes
  62. //
  63. ULONG TraceClassesEnabled = 0;
  64. //
  65. // Registry trace-class value name
  66. //
  67. WCHAR TraceClassesEnabledName[] = L"TraceClassesEnabled";
  68. //
  69. // Timeout interval for UDP and other message-oriented session mappings
  70. //
  71. ULONG UdpTimeoutSeconds = DEFAULT_UDP_TIMEOUT;
  72. #if NAT_WMI
  73. //
  74. // Copy of our registry path for WMI use.
  75. //
  76. UNICODE_STRING NatRegistryPath;
  77. #endif
  78. //
  79. // Name of value for allowing inbound non-unicast
  80. //
  81. WCHAR AllowInboundNonUnicastTrafficName[] = L"AllowInboundNonUnicastTraffic";
  82. //
  83. // If true, non-unicast traffic will not be dropped
  84. // when recevied on a firewalled interface.
  85. //
  86. BOOLEAN AllowInboundNonUnicastTraffic = FALSE;
  87. //
  88. // FUNCTION PROTOTYPES (alphabetically)
  89. //
  90. NTSTATUS
  91. DriverEntry(
  92. IN PDRIVER_OBJECT DriverObject,
  93. IN PUNICODE_STRING RegistryPath
  94. );
  95. NTSTATUS
  96. NatAdjustSecurityDescriptor(
  97. VOID
  98. );
  99. VOID
  100. NatCleanupDriver(
  101. VOID
  102. );
  103. VOID
  104. NatCreateExternalNaming(
  105. IN PUNICODE_STRING DeviceString
  106. );
  107. VOID
  108. NatDeleteExternalNaming(
  109. VOID
  110. );
  111. NTSTATUS
  112. NatInitializeDriver(
  113. VOID
  114. );
  115. NTSTATUS
  116. NatSetFirewallHook(
  117. BOOLEAN Install
  118. );
  119. VOID
  120. NatUnloadDriver(
  121. IN PDRIVER_OBJECT DriverObject
  122. );
  123. #ifdef ALLOC_PRAGMA
  124. #pragma alloc_text(INIT, DriverEntry)
  125. #pragma alloc_text(INIT, NatAdjustSecurityDescriptor)
  126. #pragma alloc_text(PAGE, NatCreateExternalNaming)
  127. #pragma alloc_text(PAGE, NatDeleteExternalNaming)
  128. #endif
  129. NTSTATUS
  130. DriverEntry(
  131. IN PDRIVER_OBJECT DriverObject,
  132. IN PUNICODE_STRING RegistryPath
  133. )
  134. /*++
  135. Routine Description:
  136. Performs driver-initialization for NAT.
  137. Arguments:
  138. Return Value:
  139. STATUS_SUCCESS if initialization succeeded, error code otherwise.
  140. --*/
  141. {
  142. WCHAR DeviceName[] = DD_IP_NAT_DEVICE_NAME;
  143. UNICODE_STRING DeviceString;
  144. LONG i;
  145. OBJECT_ATTRIBUTES ObjectAttributes;
  146. HANDLE ParametersKey;
  147. HANDLE ServiceKey;
  148. NTSTATUS status;
  149. UNICODE_STRING String;
  150. PAGED_CODE();
  151. CALLTRACE(("DriverEntry\n"));
  152. #if DBG
  153. //
  154. // Open the registry key
  155. //
  156. InitializeObjectAttributes(
  157. &ObjectAttributes,
  158. RegistryPath,
  159. OBJ_CASE_INSENSITIVE,
  160. NULL,
  161. NULL
  162. );
  163. status = ZwOpenKey(&ServiceKey, KEY_READ, &ObjectAttributes);
  164. if (NT_SUCCESS(status)) {
  165. RtlInitUnicodeString(&String, ParametersName);
  166. InitializeObjectAttributes(
  167. &ObjectAttributes,
  168. &String,
  169. OBJ_CASE_INSENSITIVE,
  170. ServiceKey,
  171. NULL
  172. );
  173. status = ZwOpenKey(&ParametersKey, KEY_READ, &ObjectAttributes);
  174. ZwClose(ServiceKey);
  175. if (NT_SUCCESS(status)) {
  176. UCHAR Buffer[32];
  177. ULONG BytesRead;
  178. PKEY_VALUE_PARTIAL_INFORMATION Value;
  179. RtlInitUnicodeString(&String, TraceClassesEnabledName);
  180. status =
  181. ZwQueryValueKey(
  182. ParametersKey,
  183. &String,
  184. KeyValuePartialInformation,
  185. (PKEY_VALUE_PARTIAL_INFORMATION)Buffer,
  186. sizeof(Buffer),
  187. &BytesRead
  188. );
  189. ZwClose(ParametersKey);
  190. if (NT_SUCCESS(status) &&
  191. ((PKEY_VALUE_PARTIAL_INFORMATION)Buffer)->Type == REG_DWORD) {
  192. TraceClassesEnabled =
  193. *(PULONG)((PKEY_VALUE_PARTIAL_INFORMATION)Buffer)->Data;
  194. }
  195. }
  196. }
  197. #endif
  198. #if NAT_WMI
  199. //
  200. // Record our registry path for WMI use
  201. //
  202. NatRegistryPath.Length = 0;
  203. NatRegistryPath.MaximumLength
  204. = RegistryPath->MaximumLength + sizeof( UNICODE_NULL );
  205. NatRegistryPath.Buffer = ExAllocatePoolWithTag(
  206. PagedPool,
  207. NatRegistryPath.MaximumLength,
  208. NAT_TAG_WMI
  209. );
  210. if( NatRegistryPath.Buffer )
  211. {
  212. RtlCopyUnicodeString( &NatRegistryPath, RegistryPath );
  213. }
  214. else
  215. {
  216. ERROR(("NAT: Unable to allocate string for RegistryPath\n"));
  217. return STATUS_NO_MEMORY;
  218. }
  219. #endif
  220. //
  221. // Create the device's object.
  222. //
  223. RtlInitUnicodeString(&DeviceString, DeviceName);
  224. status =
  225. IoCreateDevice(
  226. DriverObject,
  227. 0,
  228. &DeviceString,
  229. FILE_DEVICE_NETWORK,
  230. FILE_DEVICE_SECURE_OPEN,
  231. FALSE,
  232. &NatDeviceObject
  233. );
  234. if (!NT_SUCCESS(status)) {
  235. ERROR(("IoCreateDevice failed (0x%08X)\n", status));
  236. return status;
  237. }
  238. //
  239. // Adjust the security descriptor on the device object.
  240. //
  241. status = NatAdjustSecurityDescriptor();
  242. if (!NT_SUCCESS(status)) {
  243. ERROR(("NatAdjustSecurityDescriptor failed (0x%08x)\n", status));
  244. return status;
  245. }
  246. //
  247. // Initialize file-object tracking items
  248. //
  249. KeInitializeSpinLock(&NatFileObjectLock);
  250. NatOwnerProcessId = NULL;
  251. NatFileObjectCount = 0;
  252. //
  253. // Setup the driver object
  254. //
  255. DriverObject->DriverUnload = NatUnloadDriver;
  256. DriverObject->FastIoDispatch = &NatFastIoDispatch;
  257. DriverObject->DriverStartIo = NULL;
  258. for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++) {
  259. DriverObject->MajorFunction[i] = NatDispatch;
  260. }
  261. //
  262. // Create a Win32-accessible device object
  263. //
  264. NatCreateExternalNaming(&DeviceString);
  265. //
  266. // Initialize the driver's structures
  267. //
  268. status = NatInitializeDriver();
  269. return status;
  270. } // DriverEntry
  271. NTSTATUS
  272. NatAdjustSecurityDescriptor(
  273. VOID
  274. )
  275. /*++
  276. Routine Description:
  277. Modifies the security descriptor on the NAT's device object so
  278. that only SYSTEM has any permissions.
  279. Arguments:
  280. none.
  281. Return Value:
  282. NTSTATUS - success/error code.
  283. --*/
  284. {
  285. PACE_HEADER AceHeader;
  286. PSID AceSid;
  287. PACL Dacl;
  288. BOOLEAN DaclDefaulted;
  289. BOOLEAN DaclPresent;
  290. DWORD i;
  291. BOOLEAN MemoryAllocated;
  292. PSECURITY_DESCRIPTOR NatSD = NULL;
  293. PACL NewDacl = NULL;
  294. SECURITY_DESCRIPTOR NewSD;
  295. SECURITY_INFORMATION SecurityInformation;
  296. ULONG Size;
  297. NTSTATUS status;
  298. do
  299. {
  300. //
  301. // Get our original security descriptor
  302. //
  303. status =
  304. ObGetObjectSecurity(
  305. NatDeviceObject,
  306. &NatSD,
  307. &MemoryAllocated
  308. );
  309. // ObGetObjectSecurity can return a NULL security descriptor
  310. // even with NT_SUCCESS status code
  311. if (!NT_SUCCESS(status) || (NULL==NatSD)) {
  312. break;
  313. }
  314. //
  315. // Obtain the Dacl from the security descriptor
  316. //
  317. status =
  318. RtlGetDaclSecurityDescriptor(
  319. NatSD,
  320. &DaclPresent,
  321. &Dacl,
  322. &DaclDefaulted
  323. );
  324. if (!NT_SUCCESS(status)) {
  325. break;
  326. }
  327. ASSERT(FALSE != DaclPresent);
  328. //
  329. // Make a copy of the Dacl so that we can modify it.
  330. //
  331. NewDacl =
  332. ExAllocatePoolWithTag(
  333. PagedPool,
  334. Dacl->AclSize,
  335. NAT_TAG_SD
  336. );
  337. if (NULL == NewDacl) {
  338. status = STATUS_NO_MEMORY;
  339. break;
  340. }
  341. RtlCopyMemory(NewDacl, Dacl, Dacl->AclSize);
  342. //
  343. // Loop through the DACL, removing any access allowed
  344. // entries that aren't for SYSTEM
  345. //
  346. for (i = 0; i < NewDacl->AceCount; i++) {
  347. status = RtlGetAce(NewDacl, i, &AceHeader);
  348. if (NT_SUCCESS(status)) {
  349. if (ACCESS_ALLOWED_ACE_TYPE == AceHeader->AceType) {
  350. AceSid = (PSID) &((ACCESS_ALLOWED_ACE*)AceHeader)->SidStart;
  351. if (!RtlEqualSid(AceSid, SeExports->SeLocalSystemSid)) {
  352. status = RtlDeleteAce(NewDacl, i);
  353. if (NT_SUCCESS(status)) {
  354. i -= 1;
  355. }
  356. }
  357. }
  358. }
  359. }
  360. ASSERT(NewDacl->AceCount > 0);
  361. //
  362. // Create a new security descriptor to hold the new Dacl.
  363. //
  364. status =
  365. RtlCreateSecurityDescriptor(
  366. &NewSD,
  367. SECURITY_DESCRIPTOR_REVISION
  368. );
  369. if (!NT_SUCCESS(status)) {
  370. break;
  371. }
  372. //
  373. // Place the new Dacl into the new SD
  374. //
  375. status =
  376. RtlSetDaclSecurityDescriptor(
  377. &NewSD,
  378. TRUE,
  379. NewDacl,
  380. FALSE
  381. );
  382. if (!NT_SUCCESS(status)) {
  383. break;
  384. }
  385. //
  386. // Set the new SD into our device object. Only the Dacl from the
  387. // SD will be set.
  388. //
  389. SecurityInformation = DACL_SECURITY_INFORMATION;
  390. status =
  391. ObSetSecurityObjectByPointer(
  392. NatDeviceObject,
  393. SecurityInformation,
  394. &NewSD
  395. );
  396. } while (FALSE);
  397. if (NULL != NatSD) {
  398. ObReleaseObjectSecurity(NatSD, MemoryAllocated);
  399. }
  400. if (NULL != NewDacl) {
  401. ExFreePool(NewDacl);
  402. }
  403. return status;
  404. } // NatAdjustSecurityDescriptor
  405. VOID
  406. NatCleanupDriver(
  407. VOID
  408. )
  409. /*++
  410. Routine Description:
  411. This routine is invoked when the last reference to the NAT driver
  412. is released.
  413. Arguments:
  414. none.
  415. Return Value:
  416. none.
  417. --*/
  418. {
  419. CALLTRACE(("NatCleanupDriver\n"));
  420. } // NatCleanupDriver
  421. VOID
  422. NatCreateExternalNaming(
  423. IN PUNICODE_STRING DeviceString
  424. )
  425. /*++
  426. Routine Description:
  427. Creates a symbolic-link to the NAT's device-object so
  428. the NAT can be opened by a user-mode process.
  429. Arguments:
  430. DeviceString - Unicode name of the NAT's device-object.
  431. Return Value:
  432. none.
  433. --*/
  434. {
  435. UNICODE_STRING symLinkString;
  436. PAGED_CODE();
  437. RtlInitUnicodeString(&symLinkString, ExternalName);
  438. IoCreateSymbolicLink(&symLinkString, DeviceString);
  439. } // NatCreateExternalNaming
  440. VOID
  441. NatDeleteExternalNaming(
  442. VOID
  443. )
  444. /*++
  445. Routine Description:
  446. Deletes the Win32 symbolic-link to the NAT's device-object
  447. Arguments:
  448. Return Value:
  449. none.
  450. --*/
  451. {
  452. UNICODE_STRING symLinkString;
  453. PAGED_CODE();
  454. RtlInitUnicodeString(&symLinkString, ExternalName);
  455. IoDeleteSymbolicLink(&symLinkString);
  456. } // NatDeleteExternalNaming
  457. NTSTATUS
  458. NatInitializeDriver(
  459. VOID
  460. )
  461. /*++
  462. Routine Description:
  463. Performs initialization of the driver's structures.
  464. Arguments:
  465. none.
  466. Return Value:
  467. NTSTATUS - success/error code.
  468. --*/
  469. {
  470. OBJECT_ATTRIBUTES ObjectAttributes;
  471. HANDLE ParametersKey;
  472. NTSTATUS status;
  473. NTSTATUS status2;
  474. UNICODE_STRING UnicodeString;
  475. IO_STATUS_BLOCK IoStatus;
  476. CALLTRACE(("NatInitializeDriver\n"));
  477. //
  478. // Set up global synchronization objects
  479. //
  480. InitializeComponentReference(&ComponentReference, NatCleanupDriver);
  481. //
  482. // Obtain the IP and TCP driver device-objects
  483. //
  484. RtlInitUnicodeString(&UnicodeString, DD_IP_DEVICE_NAME);
  485. status =
  486. IoGetDeviceObjectPointer(
  487. &UnicodeString,
  488. SYNCHRONIZE|GENERIC_READ|GENERIC_WRITE,
  489. &IpFileObject,
  490. &IpDeviceObject
  491. );
  492. if (!NT_SUCCESS(status)) {
  493. ERROR(("NatInitializeDriver: error %X getting IP object\n", status));
  494. return status;
  495. }
  496. RtlInitUnicodeString(&UnicodeString, DD_TCP_DEVICE_NAME);
  497. status =
  498. IoGetDeviceObjectPointer(
  499. &UnicodeString,
  500. SYNCHRONIZE|GENERIC_READ|GENERIC_WRITE,
  501. &TcpFileObject,
  502. &TcpDeviceObject
  503. );
  504. if (!NT_SUCCESS(status)) {
  505. ERROR(("NatInitializeDriver: error %X getting TCP object\n", status));
  506. return status;
  507. }
  508. //
  509. // Open Tcp Kernel Device
  510. //
  511. InitializeObjectAttributes(
  512. &ObjectAttributes,
  513. &UnicodeString,
  514. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
  515. NULL,
  516. NULL);
  517. status =
  518. ZwCreateFile(
  519. &TcpDeviceHandle,
  520. GENERIC_READ,
  521. &ObjectAttributes,
  522. &IoStatus,
  523. NULL,
  524. FILE_ATTRIBUTE_NORMAL,
  525. FILE_SHARE_READ | FILE_SHARE_WRITE,
  526. FILE_OPEN_IF,
  527. 0,
  528. NULL,
  529. 0);
  530. if ( !NT_SUCCESS(status) )
  531. {
  532. ERROR(("ZwCreateFile failed (0x%08X)\n", status));
  533. }
  534. ObReferenceObject(IpDeviceObject);
  535. ObReferenceObject(TcpDeviceObject);
  536. //
  537. // Initialize all object-modules
  538. //
  539. NatInitializeTimerManagement();
  540. NatInitializeMappingManagement();
  541. NatInitializeDirectorManagement();
  542. NatInitializeEditorManagement();
  543. NatInitializeRedirectManagement();
  544. NatInitializeDynamicTicketManagement();
  545. NatInitializeIcmpManagement();
  546. NatInitializeRawIpManagement();
  547. NatInitializeInterfaceManagement();
  548. #if 0
  549. status = NatInitializeAddressManagement();
  550. if (!NT_SUCCESS(status)) { return status; }
  551. #endif
  552. NatInitializePacketManagement();
  553. NatInitializeNotificationManagement();
  554. #if NAT_WMI
  555. NatInitializeWMI();
  556. #endif
  557. //
  558. // Initialize NAT-provided editors.
  559. //
  560. status = NatInitializePptpManagement();
  561. if (!NT_SUCCESS(status)) { return status; }
  562. //
  563. // Commence translation of packets, and start the periodic timer.
  564. //
  565. status = NatInitiateTranslation();
  566. //
  567. // Read optional registry settings.
  568. // The user may customize the range of ports used by modifying
  569. // the reserved-ports setting in the registry.
  570. // We now check to see if there is such a value,
  571. // and if so, we use it as our reserved-port range.
  572. //
  573. // The user may also specify that inbound non-unicast traffic
  574. // is allowed on a firewalled interface.
  575. //
  576. //
  577. // N.B. Failures here are not returned to the caller.
  578. //
  579. RtlInitUnicodeString(&UnicodeString, IpNatParametersPath);
  580. InitializeObjectAttributes(
  581. &ObjectAttributes,
  582. &UnicodeString,
  583. OBJ_CASE_INSENSITIVE,
  584. NULL,
  585. NULL
  586. );
  587. status2 = ZwOpenKey(&ParametersKey, KEY_READ, &ObjectAttributes);
  588. if (NT_SUCCESS(status2)) {
  589. UCHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION)];
  590. ULONG EndPort;
  591. PWCHAR p;
  592. ULONG StartPort;
  593. PKEY_VALUE_PARTIAL_INFORMATION Value = NULL;
  594. ULONG ValueLength;
  595. //
  596. // First check for allowed non-unicast traffic.
  597. //
  598. RtlInitUnicodeString(
  599. &UnicodeString,
  600. AllowInboundNonUnicastTrafficName
  601. );
  602. status2 =
  603. ZwQueryValueKey(
  604. ParametersKey,
  605. &UnicodeString,
  606. KeyValuePartialInformation,
  607. (PKEY_VALUE_PARTIAL_INFORMATION)Buffer,
  608. sizeof(Buffer),
  609. &ValueLength
  610. );
  611. if (NT_SUCCESS(status2)
  612. && REG_DWORD == ((PKEY_VALUE_PARTIAL_INFORMATION)Buffer)->Type) {
  613. AllowInboundNonUnicastTraffic =
  614. 1 == *((PULONG)((PKEY_VALUE_PARTIAL_INFORMATION)Buffer)->Data);
  615. }
  616. //
  617. // Check for reserved ports
  618. //
  619. do {
  620. RtlInitUnicodeString(&UnicodeString, ReservedPortsName);
  621. status2 =
  622. ZwQueryValueKey(
  623. ParametersKey,
  624. &UnicodeString,
  625. KeyValuePartialInformation,
  626. (PKEY_VALUE_PARTIAL_INFORMATION)Buffer,
  627. sizeof(Buffer),
  628. &ValueLength
  629. );
  630. if (status2 != STATUS_BUFFER_OVERFLOW) { break; }
  631. Value =
  632. (PKEY_VALUE_PARTIAL_INFORMATION)
  633. ExAllocatePoolWithTag(
  634. PagedPool, ValueLength, NAT_TAG_RANGE_ARRAY
  635. );
  636. if (!Value) { break; }
  637. status2 =
  638. ZwQueryValueKey(
  639. ParametersKey,
  640. &UnicodeString,
  641. KeyValuePartialInformation,
  642. (PKEY_VALUE_PARTIAL_INFORMATION)Value,
  643. ValueLength,
  644. &ValueLength
  645. );
  646. if (!NT_SUCCESS(status2)) { break; }
  647. //
  648. // The value should be in the format "xxx-yyy\0\0";
  649. // read the first number
  650. //
  651. p = (PWCHAR)Value->Data;
  652. RtlInitUnicodeString(&UnicodeString, p);
  653. status2 = RtlUnicodeStringToInteger(&UnicodeString, 10, &StartPort);
  654. if (!NT_SUCCESS(status2)) { break; }
  655. //
  656. // Advance past '-'
  657. //
  658. while (*p && *p != L'-') { ++p; }
  659. if (*p != L'-') { break; } else { ++p; }
  660. //
  661. // Read second number
  662. //
  663. RtlInitUnicodeString(&UnicodeString, p);
  664. status2 = RtlUnicodeStringToInteger(&UnicodeString, 10, &EndPort);
  665. if (!NT_SUCCESS(status2)) { break; }
  666. //
  667. // Validate the resulting range
  668. //
  669. if (StartPort > 0 &&
  670. StartPort < 65535 &&
  671. EndPort > 0 &&
  672. EndPort < 65535 &&
  673. StartPort <= EndPort
  674. ) {
  675. ReservedPortsLowerRange = NTOHS((USHORT)StartPort);
  676. ReservedPortsUpperRange = NTOHS((USHORT)EndPort);
  677. }
  678. } while(FALSE);
  679. if (Value) { ExFreePool(Value); }
  680. ZwClose(ParametersKey);
  681. }
  682. return status;
  683. } // NatInitializeDriver
  684. NTSTATUS
  685. NatInitiateTranslation(
  686. VOID
  687. )
  688. /*++
  689. Routine Description:
  690. This routine is invoked on creation of the first interface,
  691. to launch the periodic timer and install the firewall hook.
  692. Arguments:
  693. none.
  694. Return Value:
  695. STATUS_SUCCESS if successful, error code otherwise.
  696. --*/
  697. {
  698. CALLTRACE(("NatInitiateTranslation\n"));
  699. //
  700. // Launch the timer
  701. //
  702. NatStartTimer();
  703. //
  704. // Install 'NatTranslate' as the firewall hook
  705. //
  706. return NatSetFirewallHook(TRUE);
  707. } // NatInitiateTranslation
  708. NTSTATUS
  709. NatSetFirewallHook(
  710. BOOLEAN Install
  711. )
  712. /*++
  713. Routine Description:
  714. This routine is called to set (Install==TRUE) or clear (Install==FALSE) the
  715. value of the firewall-callout function pointer in the IP driver.
  716. Arguments:
  717. Install - indicates whether to install or remove the hook.
  718. Return Value:
  719. NTSTATUS - indicates success/failure
  720. Environment:
  721. The routine assumes the caller is executing at PASSIVE_LEVEL.
  722. --*/
  723. {
  724. IP_SET_FIREWALL_HOOK_INFO HookInfo;
  725. IO_STATUS_BLOCK IoStatus;
  726. PIRP Irp;
  727. TCP_RESERVE_PORT_RANGE PortRange;
  728. KEVENT LocalEvent;
  729. NTSTATUS status;
  730. CALLTRACE(("NatSetFirewallHook\n"));
  731. //
  732. // Register (or deregister) as a firewall
  733. //
  734. HookInfo.FirewallPtr = (IPPacketFirewallPtr)NatTranslatePacket;
  735. HookInfo.Priority = 1;
  736. HookInfo.Add = Install;
  737. KeInitializeEvent(&LocalEvent, SynchronizationEvent, FALSE);
  738. Irp =
  739. IoBuildDeviceIoControlRequest(
  740. IOCTL_IP_SET_FIREWALL_HOOK,
  741. IpDeviceObject,
  742. (PVOID)&HookInfo,
  743. sizeof(HookInfo),
  744. NULL,
  745. 0,
  746. FALSE,
  747. &LocalEvent,
  748. &IoStatus
  749. );
  750. if (!Irp) {
  751. ERROR(("NatSetFirewallHook: IoBuildDeviceIoControlRequest=0\n"));
  752. return STATUS_UNSUCCESSFUL;
  753. }
  754. status = IoCallDriver(IpDeviceObject, Irp);
  755. if (status == STATUS_PENDING) {
  756. KeWaitForSingleObject(&LocalEvent, Executive, KernelMode, FALSE, NULL);
  757. status = IoStatus.Status;
  758. }
  759. if (!NT_SUCCESS(status)) {
  760. ERROR(("NatSetFirewallHook: IpSetFirewallHook=0x%08X\n", status));
  761. return status;
  762. }
  763. if (ReservedPortsLowerRange != DEFAULT_START_PORT ||
  764. ReservedPortsUpperRange != DEFAULT_END_PORT
  765. ) {
  766. return STATUS_SUCCESS;
  767. }
  768. //
  769. // Reserve (or unreserve) our port-range
  770. //
  771. // N.B. The IOCTL expects host-order numbers and we store the range
  772. // in network order, so do a swap before reserving the ports.
  773. //
  774. PortRange.LowerRange = NTOHS(DEFAULT_START_PORT);
  775. PortRange.UpperRange = NTOHS(DEFAULT_END_PORT);
  776. Irp =
  777. IoBuildDeviceIoControlRequest(
  778. Install
  779. ? IOCTL_TCP_RESERVE_PORT_RANGE
  780. : IOCTL_TCP_UNRESERVE_PORT_RANGE,
  781. TcpDeviceObject,
  782. (PVOID)&PortRange,
  783. sizeof(PortRange),
  784. NULL,
  785. 0,
  786. FALSE,
  787. &LocalEvent,
  788. &IoStatus
  789. );
  790. if (!Irp) {
  791. ERROR(("NatSetFirewallHook: IoBuildDeviceIoControlRequest(2)=0\n"));
  792. return STATUS_UNSUCCESSFUL;
  793. }
  794. status = IoCallDriver(TcpDeviceObject, Irp);
  795. if (status == STATUS_PENDING) {
  796. KeWaitForSingleObject(&LocalEvent, Executive, KernelMode, FALSE, NULL);
  797. status = IoStatus.Status;
  798. }
  799. if (!NT_SUCCESS(status)) {
  800. ERROR(("NatSetFirewallHook: Tcp(Un)ReservePortRange=0x%08X\n", status));
  801. }
  802. return status;
  803. } // NatSetFirewallHook
  804. VOID
  805. NatTerminateTranslation(
  806. VOID
  807. )
  808. /*++
  809. Routine Description:
  810. On cleanup of the last interface, this routine is invoked
  811. to stop the periodic timer and de-install the firewall hook.
  812. Arguments:
  813. none.
  814. Return Value:
  815. none.
  816. --*/
  817. {
  818. CALLTRACE(("NatTerminateTranslation\n"));
  819. NatSetFirewallHook(FALSE);
  820. } // NatTerminateTranslation
  821. VOID
  822. NatUnloadDriver(
  823. IN PDRIVER_OBJECT DriverObject
  824. )
  825. /*++
  826. Routine Description:
  827. Performs cleanup for the NAT.
  828. Arguments:
  829. DriverObject - reference to the NAT's driver-object
  830. Return Value:
  831. --*/
  832. {
  833. PNAT_EDITOR Editor;
  834. PLIST_ENTRY List;
  835. CALLTRACE(("NatUnloadDriver\n"));
  836. //
  837. // Stop translation and clear the periodic timer
  838. //
  839. NatTerminateTranslation();
  840. //
  841. // Stop the route-change-notification in our packet-management and
  842. // address-management modules.
  843. // This forces completion of the route-change and address-change IRPs,
  844. // which in turn releases component-references which would otherwise not
  845. // drop until a route-change and address-change occurred.
  846. //
  847. NatShutdownNotificationManagement();
  848. NatShutdownPacketManagement();
  849. #if 0
  850. NatShutdownAddressManagement();
  851. #endif
  852. //
  853. // Drop our self-reference and wait for all activity to cease.
  854. //
  855. ReleaseInitialComponentReference(&ComponentReference, TRUE);
  856. //
  857. // Tear down our Win32-namespace symbolic link
  858. //
  859. NatDeleteExternalNaming();
  860. //
  861. // Delete the NAT's device object
  862. //
  863. IoDeleteDevice(DriverObject->DeviceObject);
  864. //
  865. // Shutdown object modules
  866. //
  867. #if NAT_WMI
  868. NatShutdownWMI();
  869. if( NatRegistryPath.Buffer )
  870. {
  871. ExFreePool( NatRegistryPath.Buffer );
  872. RtlInitUnicodeString( &NatRegistryPath, NULL );
  873. }
  874. #endif
  875. NatShutdownPptpManagement();
  876. NatShutdownTimerManagement();
  877. NatShutdownMappingManagement();
  878. NatShutdownEditorManagement();
  879. NatShutdownDirectorManagement();
  880. NatShutdownDynamicTicketManagement();
  881. NatShutdownRawIpManagement();
  882. NatShutdownIcmpManagement();
  883. NatShutdownInterfaceManagement();
  884. //
  885. // Release references to the IP and TCP driver objects
  886. //
  887. ObDereferenceObject((PVOID)IpFileObject);
  888. ObDereferenceObject(IpDeviceObject);
  889. ObDereferenceObject((PVOID)TcpFileObject);
  890. ObDereferenceObject(TcpDeviceObject);
  891. if (TcpDeviceHandle) {
  892. ZwClose(TcpDeviceHandle);
  893. TcpDeviceHandle = NULL;
  894. }
  895. DeleteComponentReference(&ComponentReference);
  896. } // NatUnloadDriver