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.

1215 lines
26 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. //
  28. // Device-object for the NAT driver
  29. //
  30. extern PDEVICE_OBJECT NatDeviceObject = NULL;
  31. //
  32. // Registry parameters key name
  33. //
  34. WCHAR ParametersName[] = L"Parameters";
  35. //
  36. // Name of value holding reserved ports
  37. //
  38. WCHAR ReservedPortsName[] = L"ReservedPorts";
  39. //
  40. // Start and end of reserved-port range
  41. //
  42. USHORT ReservedPortsLowerRange = DEFAULT_START_PORT;
  43. USHORT ReservedPortsUpperRange = DEFAULT_END_PORT;
  44. //
  45. // Device- and file-object for the TCP driver
  46. //
  47. extern PDEVICE_OBJECT TcpDeviceObject = NULL;
  48. extern PFILE_OBJECT TcpFileObject = NULL;
  49. extern HANDLE TcpDeviceHandle = 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. // N.B. Failures here are not returned to the caller.
  577. //
  578. RtlInitUnicodeString(&UnicodeString, IpNatParametersPath);
  579. InitializeObjectAttributes(
  580. &ObjectAttributes,
  581. &UnicodeString,
  582. OBJ_CASE_INSENSITIVE,
  583. NULL,
  584. NULL
  585. );
  586. status2 = ZwOpenKey(&ParametersKey, KEY_READ, &ObjectAttributes);
  587. if (NT_SUCCESS(status2)) {
  588. UCHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION)];
  589. ULONG EndPort;
  590. PWCHAR p;
  591. ULONG StartPort;
  592. PKEY_VALUE_PARTIAL_INFORMATION Value = NULL;
  593. ULONG ValueLength;
  594. //
  595. // First check for allowed non-unicast traffic.
  596. //
  597. RtlInitUnicodeString(
  598. &UnicodeString,
  599. AllowInboundNonUnicastTrafficName
  600. );
  601. status2 =
  602. ZwQueryValueKey(
  603. ParametersKey,
  604. &UnicodeString,
  605. KeyValuePartialInformation,
  606. (PKEY_VALUE_PARTIAL_INFORMATION)Buffer,
  607. sizeof(Buffer),
  608. &ValueLength
  609. );
  610. if (NT_SUCCESS(status2)
  611. && REG_DWORD == ((PKEY_VALUE_PARTIAL_INFORMATION)Buffer)->Type) {
  612. AllowInboundNonUnicastTraffic =
  613. 1 == *((PULONG)((PKEY_VALUE_PARTIAL_INFORMATION)Buffer)->Data);
  614. }
  615. //
  616. // Check for reserved ports
  617. //
  618. do {
  619. RtlInitUnicodeString(&UnicodeString, ReservedPortsName);
  620. status2 =
  621. ZwQueryValueKey(
  622. ParametersKey,
  623. &UnicodeString,
  624. KeyValuePartialInformation,
  625. (PKEY_VALUE_PARTIAL_INFORMATION)Buffer,
  626. sizeof(Buffer),
  627. &ValueLength
  628. );
  629. if (status2 != STATUS_BUFFER_OVERFLOW) { break; }
  630. Value =
  631. (PKEY_VALUE_PARTIAL_INFORMATION)
  632. ExAllocatePoolWithTag(
  633. PagedPool, ValueLength, NAT_TAG_RANGE_ARRAY
  634. );
  635. if (!Value) { break; }
  636. status2 =
  637. ZwQueryValueKey(
  638. ParametersKey,
  639. &UnicodeString,
  640. KeyValuePartialInformation,
  641. (PKEY_VALUE_PARTIAL_INFORMATION)Value,
  642. ValueLength,
  643. &ValueLength
  644. );
  645. if (!NT_SUCCESS(status2)
  646. || REG_SZ != Value->Type
  647. || L'\0' != *(PWCHAR) (Value->Data + (Value->DataLength - sizeof(WCHAR)))) {
  648. break;
  649. }
  650. //
  651. // The value should be in the format "xxx-yyy\0\0";
  652. // read the first number
  653. //
  654. p = (PWCHAR)Value->Data;
  655. RtlInitUnicodeString(&UnicodeString, p);
  656. status2 = RtlUnicodeStringToInteger(&UnicodeString, 10, &StartPort);
  657. if (!NT_SUCCESS(status2)) { break; }
  658. //
  659. // Advance past '-'
  660. //
  661. while (*p && *p != L'-') { ++p; }
  662. if (*p != L'-') { break; } else { ++p; }
  663. //
  664. // Read second number
  665. //
  666. RtlInitUnicodeString(&UnicodeString, p);
  667. status2 = RtlUnicodeStringToInteger(&UnicodeString, 10, &EndPort);
  668. if (!NT_SUCCESS(status2)) { break; }
  669. //
  670. // Validate the resulting range
  671. //
  672. if (StartPort > 0 &&
  673. StartPort < 65535 &&
  674. EndPort > 0 &&
  675. EndPort < 65535 &&
  676. StartPort <= EndPort
  677. ) {
  678. ReservedPortsLowerRange = NTOHS((USHORT)StartPort);
  679. ReservedPortsUpperRange = NTOHS((USHORT)EndPort);
  680. }
  681. } while(FALSE);
  682. if (Value) { ExFreePool(Value); }
  683. ZwClose(ParametersKey);
  684. }
  685. return status;
  686. } // NatInitializeDriver
  687. NTSTATUS
  688. NatInitiateTranslation(
  689. VOID
  690. )
  691. /*++
  692. Routine Description:
  693. This routine is invoked on creation of the first interface,
  694. to launch the periodic timer and install the firewall hook.
  695. Arguments:
  696. none.
  697. Return Value:
  698. STATUS_SUCCESS if successful, error code otherwise.
  699. --*/
  700. {
  701. CALLTRACE(("NatInitiateTranslation\n"));
  702. //
  703. // Launch the timer
  704. //
  705. NatStartTimer();
  706. //
  707. // Install 'NatTranslate' as the firewall hook
  708. //
  709. return NatSetFirewallHook(TRUE);
  710. } // NatInitiateTranslation
  711. NTSTATUS
  712. NatSetFirewallHook(
  713. BOOLEAN Install
  714. )
  715. /*++
  716. Routine Description:
  717. This routine is called to set (Install==TRUE) or clear (Install==FALSE) the
  718. value of the firewall-callout function pointer in the IP driver.
  719. Arguments:
  720. Install - indicates whether to install or remove the hook.
  721. Return Value:
  722. NTSTATUS - indicates success/failure
  723. Environment:
  724. The routine assumes the caller is executing at PASSIVE_LEVEL.
  725. --*/
  726. {
  727. IP_SET_FIREWALL_HOOK_INFO HookInfo;
  728. IO_STATUS_BLOCK IoStatus;
  729. PIRP Irp;
  730. TCP_RESERVE_PORT_RANGE PortRange;
  731. KEVENT LocalEvent;
  732. NTSTATUS status;
  733. CALLTRACE(("NatSetFirewallHook\n"));
  734. //
  735. // Register (or deregister) as a firewall
  736. //
  737. HookInfo.FirewallPtr = (IPPacketFirewallPtr)NatTranslatePacket;
  738. HookInfo.Priority = 1;
  739. HookInfo.Add = Install;
  740. KeInitializeEvent(&LocalEvent, SynchronizationEvent, FALSE);
  741. Irp =
  742. IoBuildDeviceIoControlRequest(
  743. IOCTL_IP_SET_FIREWALL_HOOK,
  744. IpDeviceObject,
  745. (PVOID)&HookInfo,
  746. sizeof(HookInfo),
  747. NULL,
  748. 0,
  749. FALSE,
  750. &LocalEvent,
  751. &IoStatus
  752. );
  753. if (!Irp) {
  754. ERROR(("NatSetFirewallHook: IoBuildDeviceIoControlRequest=0\n"));
  755. return STATUS_UNSUCCESSFUL;
  756. }
  757. status = IoCallDriver(IpDeviceObject, Irp);
  758. if (status == STATUS_PENDING) {
  759. KeWaitForSingleObject(&LocalEvent, Executive, KernelMode, FALSE, NULL);
  760. KeResetEvent(&LocalEvent);
  761. status = IoStatus.Status;
  762. }
  763. if (!NT_SUCCESS(status)) {
  764. ERROR(("NatSetFirewallHook: IpSetFirewallHook=0x%08X\n", status));
  765. return status;
  766. }
  767. if (ReservedPortsLowerRange != DEFAULT_START_PORT ||
  768. ReservedPortsUpperRange != DEFAULT_END_PORT
  769. ) {
  770. return STATUS_SUCCESS;
  771. }
  772. //
  773. // Reserve (or unreserve) our port-range
  774. //
  775. // N.B. The IOCTL expects host-order numbers and we store the range
  776. // in network order, so do a swap before reserving the ports.
  777. //
  778. PortRange.LowerRange = NTOHS(DEFAULT_START_PORT);
  779. PortRange.UpperRange = NTOHS(DEFAULT_END_PORT);
  780. Irp =
  781. IoBuildDeviceIoControlRequest(
  782. Install
  783. ? IOCTL_TCP_RESERVE_PORT_RANGE
  784. : IOCTL_TCP_UNRESERVE_PORT_RANGE,
  785. TcpDeviceObject,
  786. (PVOID)&PortRange,
  787. sizeof(PortRange),
  788. NULL,
  789. 0,
  790. FALSE,
  791. &LocalEvent,
  792. &IoStatus
  793. );
  794. if (!Irp) {
  795. ERROR(("NatSetFirewallHook: IoBuildDeviceIoControlRequest(2)=0\n"));
  796. return STATUS_UNSUCCESSFUL;
  797. }
  798. status = IoCallDriver(TcpDeviceObject, Irp);
  799. if (status == STATUS_PENDING) {
  800. KeWaitForSingleObject(&LocalEvent, Executive, KernelMode, FALSE, NULL);
  801. status = IoStatus.Status;
  802. }
  803. if (!NT_SUCCESS(status)) {
  804. ERROR(("NatSetFirewallHook: Tcp(Un)ReservePortRange=0x%08X\n", status));
  805. }
  806. return status;
  807. } // NatSetFirewallHook
  808. VOID
  809. NatTerminateTranslation(
  810. VOID
  811. )
  812. /*++
  813. Routine Description:
  814. On cleanup of the last interface, this routine is invoked
  815. to stop the periodic timer and de-install the firewall hook.
  816. Arguments:
  817. none.
  818. Return Value:
  819. none.
  820. --*/
  821. {
  822. CALLTRACE(("NatTerminateTranslation\n"));
  823. NatSetFirewallHook(FALSE);
  824. } // NatTerminateTranslation
  825. VOID
  826. NatUnloadDriver(
  827. IN PDRIVER_OBJECT DriverObject
  828. )
  829. /*++
  830. Routine Description:
  831. Performs cleanup for the NAT.
  832. Arguments:
  833. DriverObject - reference to the NAT's driver-object
  834. Return Value:
  835. --*/
  836. {
  837. PNAT_EDITOR Editor;
  838. PLIST_ENTRY List;
  839. CALLTRACE(("NatUnloadDriver\n"));
  840. //
  841. // Stop translation and clear the periodic timer
  842. //
  843. NatTerminateTranslation();
  844. //
  845. // Stop the route-change-notification in our packet-management and
  846. // address-management modules.
  847. // This forces completion of the route-change and address-change IRPs,
  848. // which in turn releases component-references which would otherwise not
  849. // drop until a route-change and address-change occurred.
  850. //
  851. NatShutdownNotificationManagement();
  852. NatShutdownPacketManagement();
  853. #if 0
  854. NatShutdownAddressManagement();
  855. #endif
  856. //
  857. // Drop our self-reference and wait for all activity to cease.
  858. //
  859. ReleaseInitialComponentReference(&ComponentReference, TRUE);
  860. //
  861. // Tear down our Win32-namespace symbolic link
  862. //
  863. NatDeleteExternalNaming();
  864. //
  865. // Delete the NAT's device object
  866. //
  867. IoDeleteDevice(DriverObject->DeviceObject);
  868. //
  869. // Shutdown object modules
  870. //
  871. #if NAT_WMI
  872. NatShutdownWMI();
  873. if( NatRegistryPath.Buffer )
  874. {
  875. ExFreePool( NatRegistryPath.Buffer );
  876. RtlInitUnicodeString( &NatRegistryPath, NULL );
  877. }
  878. #endif
  879. NatShutdownPptpManagement();
  880. NatShutdownTimerManagement();
  881. NatShutdownMappingManagement();
  882. NatShutdownEditorManagement();
  883. NatShutdownDirectorManagement();
  884. NatShutdownDynamicTicketManagement();
  885. NatShutdownRawIpManagement();
  886. NatShutdownIcmpManagement();
  887. NatShutdownInterfaceManagement();
  888. //
  889. // Release references to the IP and TCP driver objects
  890. //
  891. ObDereferenceObject((PVOID)IpFileObject);
  892. ObDereferenceObject(IpDeviceObject);
  893. ObDereferenceObject((PVOID)TcpFileObject);
  894. ObDereferenceObject(TcpDeviceObject);
  895. if (TcpDeviceHandle) {
  896. ZwClose(TcpDeviceHandle);
  897. TcpDeviceHandle = NULL;
  898. }
  899. DeleteComponentReference(&ComponentReference);
  900. } // NatUnloadDriver