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.

1528 lines
31 KiB

  1. /*++
  2. Copyright (c) 1998, Microsoft Corporation
  3. Module Name:
  4. rmdns.c
  5. Abstract:
  6. This module contains routines for the DNS allocator module's interface
  7. to the IP router-manager. (See ROUTPROT.H for details).
  8. Author:
  9. Abolade Gbadegesin (aboladeg) 4-Mar-1998
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. #define DNS_SERVICE_NAME TEXT("DNS")
  15. COMPONENT_REFERENCE DnsComponentReference;
  16. PIP_DNS_PROXY_GLOBAL_INFO DnsGlobalInfo = NULL;
  17. CRITICAL_SECTION DnsGlobalInfoLock;
  18. SOCKET DnsGlobalSocket = INVALID_SOCKET;
  19. HANDLE DnsNotificationEvent;
  20. ULONG DnsProtocolStopped = 0;
  21. const MPR_ROUTING_CHARACTERISTICS DnsRoutingCharacteristics =
  22. {
  23. MS_ROUTER_VERSION,
  24. MS_IP_DNS_PROXY,
  25. RF_ROUTING|RF_ADD_ALL_INTERFACES,
  26. DnsRmStartProtocol,
  27. DnsRmStartComplete,
  28. DnsRmStopProtocol,
  29. DnsRmGetGlobalInfo,
  30. DnsRmSetGlobalInfo,
  31. NULL,
  32. NULL,
  33. DnsRmAddInterface,
  34. DnsRmDeleteInterface,
  35. DnsRmInterfaceStatus,
  36. DnsRmGetInterfaceInfo,
  37. DnsRmSetInterfaceInfo,
  38. DnsRmGetEventMessage,
  39. NULL,
  40. NULL,
  41. NULL,
  42. NULL,
  43. NULL,
  44. DnsRmMibCreate,
  45. DnsRmMibDelete,
  46. DnsRmMibGet,
  47. DnsRmMibSet,
  48. DnsRmMibGetFirst,
  49. DnsRmMibGetNext,
  50. NULL,
  51. NULL
  52. };
  53. IP_DNS_PROXY_STATISTICS DnsStatistics;
  54. SUPPORT_FUNCTIONS DnsSupportFunctions;
  55. VOID
  56. DnsCleanupModule(
  57. VOID
  58. )
  59. /*++
  60. Routine Description:
  61. This routine is invoked to cleanup the DNS module.
  62. Arguments:
  63. none.
  64. Return Value:
  65. none.
  66. Environment:
  67. Invoked from within a 'DllMain' routine on 'DLL_PROCESS_DETACH'.
  68. --*/
  69. {
  70. DnsShutdownInterfaceManagement();
  71. DnsShutdownTableManagement();
  72. DnsShutdownFileManagement();
  73. DeleteCriticalSection(&DnsGlobalInfoLock);
  74. DeleteComponentReference(&DnsComponentReference);
  75. } // DnsCleanupModule
  76. VOID
  77. DnsCleanupProtocol(
  78. VOID
  79. )
  80. /*++
  81. Routine Description:
  82. This routine is invoked to cleanup the DNS protocol-component
  83. after a 'StopProtocol'. It runs when the last reference to the
  84. DHCP component is released. (See 'COMPREF.H').
  85. Arguments:
  86. none.
  87. Return Value:
  88. none.
  89. Environment:
  90. Invoked from within an arbitrary context with no locks held.
  91. --*/
  92. {
  93. DNS_PROXY_TYPE Type;
  94. PROFILE("DnsCleanupProtocol");
  95. if (DnsServerList[DnsProxyDns]) {
  96. NH_FREE(DnsServerList[DnsProxyDns]);
  97. DnsServerList[DnsProxyDns] = NULL;
  98. }
  99. if (DnsServerList[DnsProxyWins]) {
  100. NH_FREE(DnsServerList[DnsProxyWins]);
  101. DnsServerList[DnsProxyWins] = NULL;
  102. }
  103. if (DnsICSDomainSuffix)
  104. {
  105. NH_FREE(DnsICSDomainSuffix);
  106. DnsICSDomainSuffix = NULL;
  107. }
  108. if (DnsGlobalInfo) { NH_FREE(DnsGlobalInfo); DnsGlobalInfo = NULL; }
  109. InterlockedExchange(reinterpret_cast<LPLONG>(&DnsProtocolStopped), 1);
  110. SetEvent(DnsNotificationEvent);
  111. ResetComponentReference(&DnsComponentReference);
  112. NhStopEventLog();
  113. } // DnsCleanupProtocol
  114. BOOLEAN
  115. DnsInitializeModule(
  116. VOID
  117. )
  118. /*++
  119. Routine Description:
  120. This routine is invoked to initialize the DNS module.
  121. Arguments:
  122. none.
  123. Return Value:
  124. BOOLEAN - TRUE if initialization succeeded, FALSE otherwise
  125. Environment:
  126. Invoked in the context of a 'DllMain' routine on 'DLL_PROCESS_ATTACH'.
  127. --*/
  128. {
  129. if (InitializeComponentReference(
  130. &DnsComponentReference, DnsCleanupProtocol
  131. )) {
  132. return FALSE;
  133. }
  134. __try {
  135. InitializeCriticalSection(&DnsGlobalInfoLock);
  136. }
  137. __except(EXCEPTION_EXECUTE_HANDLER) {
  138. DeleteComponentReference(&DnsComponentReference);
  139. return FALSE;
  140. }
  141. if (DnsInitializeFileManagement()) {
  142. DeleteCriticalSection(&DnsGlobalInfoLock);
  143. DeleteComponentReference(&DnsComponentReference);
  144. return FALSE;
  145. }
  146. if (DnsInitializeTableManagement()) {
  147. DnsShutdownFileManagement();
  148. DeleteCriticalSection(&DnsGlobalInfoLock);
  149. DeleteComponentReference(&DnsComponentReference);
  150. return FALSE;
  151. }
  152. if (DnsInitializeInterfaceManagement()) {
  153. DnsShutdownTableManagement();
  154. DnsShutdownFileManagement();
  155. DeleteCriticalSection(&DnsGlobalInfoLock);
  156. DeleteComponentReference(&DnsComponentReference);
  157. return FALSE;
  158. }
  159. return TRUE;
  160. } // DnsInitializeModule
  161. BOOLEAN
  162. DnsIsDnsEnabled(
  163. VOID
  164. )
  165. /*++
  166. Routine Description:
  167. This routine is invoked to determine whether the DNS proxy is enabled.
  168. It checks the global info which, if found, indicates that the protocol
  169. is enabled.
  170. Note that the global info critical section is always initialized in the
  171. 'DllMain' routine, which is why this routine works if the DNS proxy
  172. is not even installed.
  173. Arguments:
  174. none.
  175. Return Value:
  176. BOOLEAN - TRUE if DNS proxy is enabled, FALSE otherwise.
  177. Environment:
  178. Invoked from an arbitrary context.
  179. --*/
  180. {
  181. PROFILE("DnsIsDnsEnabled");
  182. if (!REFERENCE_DNS()) { return FALSE; }
  183. EnterCriticalSection(&DnsGlobalInfoLock);
  184. if (!DnsGlobalInfo ||
  185. !(DnsGlobalInfo->Flags & IP_DNS_PROXY_FLAG_ENABLE_DNS)) {
  186. LeaveCriticalSection(&DnsGlobalInfoLock);
  187. DEREFERENCE_DNS_AND_RETURN(FALSE);
  188. }
  189. LeaveCriticalSection(&DnsGlobalInfoLock);
  190. DEREFERENCE_DNS_AND_RETURN(TRUE);
  191. } // DnsIsDnsEnabled
  192. BOOLEAN
  193. DnsIsWinsEnabled(
  194. VOID
  195. )
  196. /*++
  197. Routine Description:
  198. This routine is invoked to determine whether the WINS proxy is enabled.
  199. It checks the global info which, if found, indicates that the protocol
  200. is enabled.
  201. Note that the global info critical section is always initialized in the
  202. 'DllMain' routine, which is why this routine works if the DNS proxy
  203. is not even installed.
  204. Arguments:
  205. none.
  206. Return Value:
  207. BOOLEAN - TRUE if WINS proxy is enabled, FALSE otherwise.
  208. Environment:
  209. Invoked from an arbitrary context.
  210. --*/
  211. {
  212. PROFILE("DnsIsWinsEnabled");
  213. return FALSE;
  214. } // DnsIsWinsEnabled
  215. BOOL IsServiceRunning(LPCTSTR pSvcName)
  216. {
  217. BOOL bRet = FALSE;
  218. SERVICE_STATUS Status;
  219. SC_HANDLE hService, hScm;
  220. hScm = OpenSCManager(NULL, NULL, GENERIC_READ);
  221. if (hScm) {
  222. hService = OpenService(hScm, pSvcName, SERVICE_QUERY_STATUS);
  223. if (hService) {
  224. ZeroMemory(&Status, sizeof(Status));
  225. if (QueryServiceStatus(hService, &Status) &&
  226. (SERVICE_STOPPED != Status.dwCurrentState &&
  227. SERVICE_STOP_PENDING != Status.dwCurrentState)) {
  228. bRet = TRUE;
  229. }
  230. CloseServiceHandle(hService);
  231. }
  232. CloseServiceHandle(hScm);
  233. }
  234. return bRet;
  235. }
  236. ULONG
  237. APIENTRY
  238. DnsRmStartProtocol(
  239. HANDLE NotificationEvent,
  240. PSUPPORT_FUNCTIONS SupportFunctions,
  241. PVOID GlobalInfo,
  242. ULONG StructureVersion,
  243. ULONG StructureSize,
  244. ULONG StructureCount
  245. )
  246. /*++
  247. Routine Description:
  248. This routine is invoked to indicate the component's operation should begin.
  249. Arguments:
  250. NotificationEvent - event on which we notify the router-manager
  251. about asynchronous occurrences
  252. SupportFunctions - functions for initiating router-related operations
  253. GlobalInfo - configuration for the component
  254. Return Value:
  255. ULONG - Win32 status code.
  256. Environment:
  257. The routine runs in the context of an IP router-manager thread.
  258. --*/
  259. {
  260. ULONG Error = NO_ERROR;
  261. SOCKET GlobalSocket;
  262. ULONG Size;
  263. NTSTATUS status;
  264. PROFILE("DnsRmStartProtocol");
  265. REFERENCE_DNS_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
  266. if (!GlobalInfo) { DEREFERENCE_DNS_AND_RETURN(ERROR_INVALID_PARAMETER); }
  267. NhStartEventLog();
  268. do {
  269. //
  270. // Copy the global configuration
  271. //
  272. EnterCriticalSection(&DnsGlobalInfoLock);
  273. Size = sizeof(*DnsGlobalInfo);
  274. DnsGlobalInfo =
  275. reinterpret_cast<PIP_DNS_PROXY_GLOBAL_INFO>(NH_ALLOCATE(Size));
  276. if (!DnsGlobalInfo) {
  277. LeaveCriticalSection(&DnsGlobalInfoLock);
  278. NhTrace(
  279. TRACE_FLAG_INIT,
  280. "DnsRmStartProtocol: cannot allocate global info"
  281. );
  282. NhErrorLog(
  283. IP_DNS_PROXY_LOG_ALLOCATION_FAILED,
  284. 0,
  285. "%d",
  286. Size
  287. );
  288. Error = ERROR_NOT_ENOUGH_MEMORY;
  289. break;
  290. }
  291. CopyMemory(DnsGlobalInfo, GlobalInfo, Size);
  292. //
  293. // If a full DNS server is running on this machine
  294. // then we need to start DNS Proxy in Disabled mode.
  295. // If and when the full DNS server is stopped it will reenable the
  296. // Proxy DNS.
  297. //
  298. if (IsServiceRunning(DNS_SERVICE_NAME)) {
  299. DnsGlobalInfo->Flags &= ~IP_DNS_PROXY_FLAG_ENABLE_DNS;
  300. }
  301. //
  302. // Save the notification event
  303. //
  304. DnsNotificationEvent = NotificationEvent;
  305. //
  306. // Save the support functions
  307. //
  308. if (!SupportFunctions) {
  309. ZeroMemory(&DnsSupportFunctions, sizeof(DnsSupportFunctions));
  310. }
  311. else {
  312. CopyMemory(
  313. &DnsSupportFunctions,
  314. SupportFunctions,
  315. sizeof(*SupportFunctions)
  316. );
  317. }
  318. //
  319. // Query for ICS domain suffix string
  320. //
  321. DnsQueryICSDomainSuffix();
  322. //
  323. // Build the server list
  324. //
  325. DnsQueryServerList();
  326. //
  327. // Create the global query-socket
  328. //
  329. Error = NhCreateDatagramSocket(0, 0, &GlobalSocket);
  330. if (Error == NO_ERROR) {
  331. InterlockedExchangePointer(
  332. (PVOID*)&DnsGlobalSocket,
  333. (PVOID)GlobalSocket
  334. );
  335. }
  336. else {
  337. NhTrace(
  338. TRACE_FLAG_DNS,
  339. "DnsRmStartProtocol: error %d creating global socket", Error
  340. );
  341. Error = NO_ERROR;
  342. }
  343. LeaveCriticalSection(&DnsGlobalInfoLock);
  344. //
  345. // load entries from the hosts.ics file (if present)
  346. //
  347. LoadHostsIcsFile(TRUE);
  348. InterlockedExchange(reinterpret_cast<LPLONG>(&DnsProtocolStopped), 0);
  349. } while (FALSE);
  350. if (NO_ERROR != Error) {
  351. NhStopEventLog();
  352. }
  353. DEREFERENCE_DNS_AND_RETURN(Error);
  354. } // DnsRmStartProtocol
  355. ULONG
  356. APIENTRY
  357. DnsRmStartComplete(
  358. VOID
  359. )
  360. /*++
  361. Routine Description:
  362. This routine is invoked when the router has finished adding the initial
  363. configuration
  364. Arguments:
  365. none.
  366. Return Value:
  367. ULONG - Win32 status code
  368. Environment:
  369. The routine runs in the context of an IP router-manager thread.
  370. --*/
  371. {
  372. return NO_ERROR;
  373. } // DnsRmStartComplete
  374. ULONG
  375. APIENTRY
  376. DnsRmStopProtocol(
  377. VOID
  378. )
  379. /*++
  380. Routine Description:
  381. This routine is invoked to stop the protocol.
  382. Arguments:
  383. none.
  384. Return Value:
  385. ULONG - Win32 status code
  386. Environment:
  387. The routine runs in the context of an IP router-manager thread.
  388. --*/
  389. {
  390. SOCKET GlobalSocket;
  391. PROFILE("DnsRmStopProtocol");
  392. //
  393. // Reference the module to make sure it's running
  394. //
  395. REFERENCE_DNS_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
  396. //
  397. // Save any entries present in our tables
  398. //
  399. SaveHostsIcsFile(TRUE);
  400. //
  401. // Empty the dns tables to save memory space
  402. //
  403. DnsEmptyTables();
  404. EnterCriticalSection(&DnsGlobalInfoLock);
  405. if (DnsNotifyChangeKeyWaitHandle) {
  406. RtlDeregisterWait(DnsNotifyChangeKeyWaitHandle);
  407. DnsNotifyChangeKeyWaitHandle = NULL;
  408. }
  409. if (DnsNotifyChangeKeyEvent) {
  410. NtClose(DnsNotifyChangeKeyEvent);
  411. DnsNotifyChangeKeyEvent = NULL;
  412. DnsNotifyChangeKeyCallbackRoutine(NULL, FALSE);
  413. }
  414. if (DnsTcpipInterfacesKey) {
  415. NtClose(DnsTcpipInterfacesKey);
  416. DnsTcpipInterfacesKey = NULL;
  417. }
  418. if (DnsNotifyChangeAddressWaitHandle) {
  419. RtlDeregisterWait(DnsNotifyChangeAddressWaitHandle);
  420. DnsNotifyChangeAddressWaitHandle = NULL;
  421. }
  422. if (DnsNotifyChangeAddressEvent) {
  423. if (CancelIPChangeNotify(&DnsNotifyChangeAddressOverlapped)) {
  424. if (WAIT_OBJECT_0 !=
  425. WaitForSingleObject(DnsNotifyChangeAddressEvent, INFINITE)) {
  426. NhTrace(
  427. TRACE_FLAG_DNS,
  428. "DnsRmStopProtocol: error %d while waiting on "
  429. "DnsNotifyChangeAddressEvent",
  430. GetLastError()
  431. );
  432. }
  433. }
  434. NtClose(DnsNotifyChangeAddressEvent);
  435. DnsNotifyChangeAddressEvent = NULL;
  436. DnsNotifyChangeAddressCallbackRoutine(NULL, FALSE);
  437. }
  438. //
  439. // ICSDomain
  440. //
  441. if (DnsNotifyChangeKeyICSDomainWaitHandle) {
  442. RtlDeregisterWait(DnsNotifyChangeKeyICSDomainWaitHandle);
  443. DnsNotifyChangeKeyICSDomainWaitHandle = NULL;
  444. }
  445. if (DnsNotifyChangeKeyICSDomainEvent) {
  446. NtClose(DnsNotifyChangeKeyICSDomainEvent);
  447. DnsNotifyChangeKeyICSDomainEvent = NULL;
  448. DnsNotifyChangeKeyICSDomainCallbackRoutine(NULL, FALSE);
  449. }
  450. if (DnsTcpipParametersKey) {
  451. NtClose(DnsTcpipParametersKey);
  452. DnsTcpipParametersKey = NULL;
  453. }
  454. LeaveCriticalSection(&DnsGlobalInfoLock);
  455. GlobalSocket =
  456. (SOCKET)InterlockedExchangePointer(
  457. (PVOID*)&DnsGlobalSocket,
  458. (PVOID)INVALID_SOCKET
  459. );
  460. NhDeleteDatagramSocket(GlobalSocket);
  461. //
  462. // Drop the initial reference to cause a cleanup
  463. //
  464. ReleaseInitialComponentReference(&DnsComponentReference);
  465. return DEREFERENCE_DNS() ? NO_ERROR : ERROR_PROTOCOL_STOP_PENDING;
  466. } // DnsRmStopProtocol
  467. ULONG
  468. APIENTRY
  469. DnsRmAddInterface(
  470. PWCHAR Name,
  471. ULONG Index,
  472. NET_INTERFACE_TYPE Type,
  473. ULONG MediaType,
  474. USHORT AccessType,
  475. USHORT ConnectionType,
  476. PVOID InterfaceInfo,
  477. ULONG StructureVersion,
  478. ULONG StructureSize,
  479. ULONG StructureCount
  480. )
  481. /*++
  482. Routine Description:
  483. This routine is invoked to add an interface to the component.
  484. Arguments:
  485. Name - the name of the interface (unused)
  486. Index - the index of the interface
  487. Type - the type of the interface
  488. InterfaceInfo - the configuration information for the interface
  489. Return Value:
  490. ULONG - Win32 status code.
  491. Environment:
  492. The routine runs in the context of an IP router-manager thread.
  493. --*/
  494. {
  495. ULONG Error;
  496. PROFILE("DnsRmAddInterface");
  497. REFERENCE_DNS_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
  498. Error =
  499. DnsCreateInterface(
  500. Index,
  501. Type,
  502. (PIP_DNS_PROXY_INTERFACE_INFO)InterfaceInfo,
  503. NULL
  504. );
  505. DEREFERENCE_DNS_AND_RETURN(Error);
  506. } // DnsRmAddInterface
  507. ULONG
  508. APIENTRY
  509. DnsRmDeleteInterface(
  510. ULONG Index
  511. )
  512. /*++
  513. Routine Description:
  514. This routine is invoked to delete an interface from the component.
  515. Arguments:
  516. Index - the index of the interface
  517. Return Value:
  518. ULONG - Win32 status code
  519. Environment:
  520. The routine runs in the context of an IP router-manager thread.
  521. --*/
  522. {
  523. ULONG Error;
  524. PROFILE("DnsRmDeleteInterface");
  525. REFERENCE_DNS_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
  526. Error =
  527. DnsDeleteInterface(
  528. Index
  529. );
  530. DEREFERENCE_DNS_AND_RETURN(Error);
  531. } // DnsRmDeleteInterface
  532. ULONG
  533. APIENTRY
  534. DnsRmGetEventMessage(
  535. OUT ROUTING_PROTOCOL_EVENTS* Event,
  536. OUT MESSAGE* Result
  537. )
  538. /*++
  539. Routine Description:
  540. This routine is invoked to retrieve an event message from the component.
  541. The only event message we generate is the 'ROUTER_STOPPED' message.
  542. Arguments:
  543. Event - receives the generated event
  544. Result - receives the associated result
  545. Return Value:
  546. ULONG - Win32 status code.
  547. --*/
  548. {
  549. PROFILE("DnsRmGetEventMessage");
  550. if (InterlockedExchange(reinterpret_cast<LPLONG>(&DnsProtocolStopped), 0)) {
  551. *Event = ROUTER_STOPPED;
  552. return NO_ERROR;
  553. }
  554. return ERROR_NO_MORE_ITEMS;
  555. } // DnsRmGetEventMessage
  556. ULONG
  557. APIENTRY
  558. DnsRmGetInterfaceInfo(
  559. ULONG Index,
  560. PVOID InterfaceInfo,
  561. IN OUT PULONG InterfaceInfoSize,
  562. IN OUT PULONG StructureVersion,
  563. IN OUT PULONG StructureSize,
  564. IN OUT PULONG StructureCount
  565. )
  566. /*++
  567. Routine Description:
  568. This routine is invoked to retrieve the component's per-interface
  569. configuration.
  570. Arguments:
  571. Index - the index of the interface to be queried
  572. InterfaceInfo - receives the query results
  573. InterfaceInfoSize - receives the amount of data retrieved
  574. Return Value:
  575. ULONG - Win32 status code.
  576. --*/
  577. {
  578. ULONG Error;
  579. PROFILE("DnsRmGetInterfaceInfo");
  580. REFERENCE_DNS_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
  581. Error =
  582. DnsQueryInterface(
  583. Index,
  584. (PIP_DNS_PROXY_INTERFACE_INFO)InterfaceInfo,
  585. InterfaceInfoSize
  586. );
  587. *StructureSize = *InterfaceInfoSize;
  588. if (StructureCount) {*StructureCount = 1;}
  589. DEREFERENCE_DNS_AND_RETURN(Error);
  590. } // DnsRmGetInterfaceInfo
  591. ULONG
  592. APIENTRY
  593. DnsRmSetInterfaceInfo(
  594. ULONG Index,
  595. PVOID InterfaceInfo,
  596. ULONG StructureVersion,
  597. ULONG StructureSize,
  598. ULONG StructureCount
  599. )
  600. /*++
  601. Routine Description:
  602. This routine is invoked to change the component's per-interface
  603. configuration.
  604. Arguments:
  605. Index - the index of the interface to be updated
  606. InterfaceInfo - supplies the new configuration
  607. Return Value:
  608. ULONG - Win32 status code.
  609. --*/
  610. {
  611. ULONG Error;
  612. PROFILE("DnsRmSetInterfaceInfo");
  613. REFERENCE_DNS_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
  614. Error =
  615. DnsConfigureInterface(
  616. Index,
  617. (PIP_DNS_PROXY_INTERFACE_INFO)InterfaceInfo
  618. );
  619. DEREFERENCE_DNS_AND_RETURN(Error);
  620. } // DnsRmSetInterfaceInfo
  621. ULONG
  622. APIENTRY
  623. DnsRmInterfaceStatus(
  624. ULONG Index,
  625. BOOL InterfaceActive,
  626. ULONG StatusType,
  627. PVOID StatusInfo
  628. )
  629. /*++
  630. Routine Description:
  631. This routine is invoked to bind/unbind, enable/disable an interface
  632. Arguments:
  633. Index - the interface to be bound
  634. InterfaceActive - whether the interface is active
  635. StatusType - type of status being changed (bind or enabled)
  636. StatusInfo - Info pertaining to the state being changed
  637. Return Value:
  638. ULONG - Win32 Status code
  639. Environment:
  640. The routine runs in the context of an IP router-manager thread.
  641. --*/
  642. {
  643. ULONG Error = NO_ERROR;
  644. switch(StatusType) {
  645. case RIS_INTERFACE_ADDRESS_CHANGE: {
  646. PIP_ADAPTER_BINDING_INFO BindInfo =
  647. (PIP_ADAPTER_BINDING_INFO)StatusInfo;
  648. if (BindInfo->AddressCount) {
  649. Error = DnsRmBindInterface(Index, StatusInfo);
  650. } else {
  651. Error = DnsRmUnbindInterface(Index);
  652. }
  653. break;
  654. }
  655. case RIS_INTERFACE_ENABLED: {
  656. Error = DnsRmEnableInterface(Index);
  657. break;
  658. }
  659. case RIS_INTERFACE_DISABLED: {
  660. Error = DnsRmDisableInterface(Index);
  661. break;
  662. }
  663. }
  664. return Error;
  665. } // DnsRmInterfaceStatus
  666. ULONG
  667. DnsRmBindInterface(
  668. ULONG Index,
  669. PVOID BindingInfo
  670. )
  671. /*++
  672. Routine Description:
  673. This routine is invoked to bind an interface to its IP address(es).
  674. Arguments:
  675. Index - the interface to be bound
  676. BindingInfo - the addressing information
  677. Return Value:
  678. ULONG - Win32 status code.
  679. Environment:
  680. The routine runs in the context of an IP router-manager thread.
  681. --*/
  682. {
  683. ULONG Error;
  684. PROFILE("DnsRmBindInterface");
  685. REFERENCE_DNS_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
  686. Error =
  687. DnsBindInterface(
  688. Index,
  689. (PIP_ADAPTER_BINDING_INFO)BindingInfo
  690. );
  691. DEREFERENCE_DNS_AND_RETURN(Error);
  692. } // DnsRmBindInterface
  693. ULONG
  694. DnsRmUnbindInterface(
  695. ULONG Index
  696. )
  697. /*++
  698. Routine Description:
  699. This routine is invoked to unbind an interface from its IP address(es).
  700. Arguments:
  701. Index - the interface to be unbound
  702. Return Value:
  703. ULONG - Win32 status code.
  704. Environment:
  705. The routine runs in the context of an IP router-manager thread.
  706. --*/
  707. {
  708. ULONG Error;
  709. PROFILE("DnsRmUnbindInterface");
  710. REFERENCE_DNS_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
  711. Error =
  712. DnsUnbindInterface(
  713. Index
  714. );
  715. DEREFERENCE_DNS_AND_RETURN(Error);
  716. } // DnsRmUnbindInterface
  717. ULONG
  718. DnsRmEnableInterface(
  719. ULONG Index
  720. )
  721. /*++
  722. Routine Description:
  723. This routine is invoked to enable operation on an interface.
  724. Arguments:
  725. Index - the interface to be enabled.
  726. Return Value:
  727. ULONG - Win32 status code.
  728. Environment:
  729. The routine runs in the context of an IP router-manager thread.
  730. --*/
  731. {
  732. ULONG Error;
  733. PROFILE("DnsRmEnableInterface");
  734. REFERENCE_DNS_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
  735. Error =
  736. DnsEnableInterface(
  737. Index
  738. );
  739. DEREFERENCE_DNS_AND_RETURN(Error);
  740. } // DnsRmEnableInterface
  741. ULONG
  742. DnsRmDisableInterface(
  743. ULONG Index
  744. )
  745. /*++
  746. Routine Description:
  747. This routine is invoked to disable operation on an interface.
  748. Arguments:
  749. Index - the interface to be disabled.
  750. Return Value:
  751. ULONG - Win32 status code.
  752. Environment:
  753. The routine runs in the context of an IP router-manager thread.
  754. --*/
  755. {
  756. ULONG Error;
  757. PROFILE("DnsRmDisableInterface");
  758. REFERENCE_DNS_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
  759. Error =
  760. DnsDisableInterface(
  761. Index
  762. );
  763. DEREFERENCE_DNS_AND_RETURN(Error);
  764. } // DnsRmDisableInterface
  765. ULONG
  766. DnsEnableSuffixQuery(
  767. VOID
  768. )
  769. /*++
  770. Routine Description:
  771. This routine is invoked to reenable the suffix watch.
  772. Arguments:
  773. None.
  774. Return Value:
  775. ULONG - Win32 status code.
  776. Environment:
  777. The routine runs in the context of an IP router-manager thread.
  778. --*/
  779. {
  780. ULONG Error = NO_ERROR;
  781. PROFILE("DnsEnableSuffixQuery");
  782. //
  783. // enable ICSDomain key watch
  784. //
  785. REFERENCE_DNS_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
  786. EnterCriticalSection(&DnsGlobalInfoLock);
  787. DnsQueryICSDomainSuffix();
  788. LeaveCriticalSection(&DnsGlobalInfoLock);
  789. DEREFERENCE_DNS_AND_RETURN(Error);
  790. } // DnsEnableSuffixQuery
  791. ULONG
  792. DnsDisableSuffixQuery(
  793. VOID
  794. )
  795. /*++
  796. Routine Description:
  797. This routine is invoked to disable the suffix watch.
  798. Arguments:
  799. None.
  800. Return Value:
  801. ULONG - Win32 status code.
  802. Environment:
  803. The routine runs in the context of an IP router-manager thread.
  804. --*/
  805. {
  806. ULONG Error = NO_ERROR;
  807. PROFILE("DnsDisableSuffixQuery");
  808. //
  809. // disable ICSDomain key watch for the period we are disabled
  810. //
  811. REFERENCE_DNS_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
  812. EnterCriticalSection(&DnsGlobalInfoLock);
  813. if (DnsNotifyChangeKeyICSDomainWaitHandle) {
  814. RtlDeregisterWait(DnsNotifyChangeKeyICSDomainWaitHandle);
  815. DnsNotifyChangeKeyICSDomainWaitHandle = NULL;
  816. }
  817. if (DnsNotifyChangeKeyICSDomainEvent) {
  818. NtClose(DnsNotifyChangeKeyICSDomainEvent);
  819. DnsNotifyChangeKeyICSDomainEvent = NULL;
  820. DnsNotifyChangeKeyICSDomainCallbackRoutine(NULL, FALSE);
  821. }
  822. if (DnsTcpipParametersKey) {
  823. NtClose(DnsTcpipParametersKey);
  824. DnsTcpipParametersKey = NULL;
  825. }
  826. if (DnsICSDomainSuffix)
  827. {
  828. NH_FREE(DnsICSDomainSuffix);
  829. DnsICSDomainSuffix = NULL;
  830. }
  831. LeaveCriticalSection(&DnsGlobalInfoLock);
  832. DEREFERENCE_DNS_AND_RETURN(Error);
  833. } // DnsDisableSuffixQuery
  834. ULONG
  835. APIENTRY
  836. DnsRmGetGlobalInfo(
  837. PVOID GlobalInfo,
  838. IN OUT PULONG GlobalInfoSize,
  839. IN OUT PULONG StructureVersion,
  840. IN OUT PULONG StructureSize,
  841. IN OUT PULONG StructureCount
  842. )
  843. /*++
  844. Routine Description:
  845. This routine is invoked to retrieve the configuration for the component.
  846. Arguments:
  847. GlobalInfo - receives the configuration
  848. GlobalInfoSize - receives the size of the configuration
  849. Return Value:
  850. ULONG - Win32 status code
  851. Environment:
  852. The routine runs in the context of an IP router-manager thread.
  853. --*/
  854. {
  855. ULONG Size;
  856. PROFILE("DnsRmGetGlobalInfo");
  857. REFERENCE_DNS_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
  858. if (!GlobalInfoSize || (*GlobalInfoSize && !GlobalInfo)) {
  859. DEREFERENCE_DNS_AND_RETURN(ERROR_INVALID_PARAMETER);
  860. }
  861. EnterCriticalSection(&DnsGlobalInfoLock);
  862. Size = sizeof(*DnsGlobalInfo);
  863. if (*GlobalInfoSize < Size) {
  864. LeaveCriticalSection(&DnsGlobalInfoLock);
  865. *StructureSize = *GlobalInfoSize = Size;
  866. if (StructureCount) {*StructureCount = 1;}
  867. DEREFERENCE_DNS_AND_RETURN(ERROR_INSUFFICIENT_BUFFER);
  868. }
  869. CopyMemory(GlobalInfo, DnsGlobalInfo, Size);
  870. LeaveCriticalSection(&DnsGlobalInfoLock);
  871. *StructureSize = *GlobalInfoSize = Size;
  872. if (StructureCount) {*StructureCount = 1;}
  873. DEREFERENCE_DNS_AND_RETURN(NO_ERROR);
  874. } // DnsRmGetGlobalInfo
  875. ULONG
  876. APIENTRY
  877. DnsRmSetGlobalInfo(
  878. PVOID GlobalInfo,
  879. ULONG StructureVersion,
  880. ULONG StructureSize,
  881. ULONG StructureCount
  882. )
  883. /*++
  884. Routine Description:
  885. This routine is invoked to change the configuration for the component.
  886. Arguments:
  887. GlobalInfo - the new configuration
  888. Return Value:
  889. ULONG - Win32 status code
  890. Environment:
  891. The routine runs in the context of an IP router-manager thread.
  892. --*/
  893. {
  894. ULONG OldFlags;
  895. ULONG NewFlags;
  896. PIP_DNS_PROXY_GLOBAL_INFO NewInfo;
  897. ULONG Size;
  898. PROFILE("DnsRmSetGlobalInfo");
  899. REFERENCE_DNS_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
  900. if (!GlobalInfo) { DEREFERENCE_DNS_AND_RETURN(ERROR_INVALID_PARAMETER); }
  901. Size = sizeof(*DnsGlobalInfo);
  902. NewInfo = reinterpret_cast<PIP_DNS_PROXY_GLOBAL_INFO>(NH_ALLOCATE(Size));
  903. if (!NewInfo) {
  904. NhTrace(
  905. TRACE_FLAG_INIT,
  906. "DnsRmSetGlobalInfo: error reallocating global info"
  907. );
  908. NhErrorLog(
  909. IP_DNS_PROXY_LOG_ALLOCATION_FAILED,
  910. 0,
  911. "%d",
  912. Size
  913. );
  914. DEREFERENCE_DNS_AND_RETURN(ERROR_NOT_ENOUGH_MEMORY);
  915. }
  916. CopyMemory(NewInfo, GlobalInfo, Size);
  917. //
  918. // If a full DNS server is running on this machine
  919. // then we need to keep DNS Proxy in the Disabled mode.
  920. // If and when the full DNS server is stopped it will reenable the
  921. // Proxy DNS.
  922. if (IsServiceRunning(DNS_SERVICE_NAME)) {
  923. NewInfo->Flags &= ~IP_DNS_PROXY_FLAG_ENABLE_DNS;
  924. }
  925. EnterCriticalSection(&DnsGlobalInfoLock);
  926. OldFlags = DnsGlobalInfo->Flags;
  927. NH_FREE(DnsGlobalInfo);
  928. DnsGlobalInfo = NewInfo;
  929. NewFlags = DnsGlobalInfo->Flags;
  930. LeaveCriticalSection(&DnsGlobalInfoLock);
  931. //
  932. // See if the enabled state of either DNS or WINS proxy changed.
  933. // If so, we need to deactivate and reactivate all interfaces
  934. //
  935. if ((NewFlags & IP_DNS_PROXY_FLAG_ENABLE_DNS)
  936. != (OldFlags & IP_DNS_PROXY_FLAG_ENABLE_DNS)) {
  937. DnsReactivateEveryInterface();
  938. }
  939. DEREFERENCE_DNS_AND_RETURN(NO_ERROR);
  940. } // DnsRmSetGlobalInfo
  941. ULONG
  942. APIENTRY
  943. DnsRmMibCreate(
  944. ULONG InputDataSize,
  945. PVOID InputData
  946. )
  947. {
  948. return ERROR_NOT_SUPPORTED;
  949. }
  950. ULONG
  951. APIENTRY
  952. DnsRmMibDelete(
  953. ULONG InputDataSize,
  954. PVOID InputData
  955. )
  956. {
  957. return ERROR_NOT_SUPPORTED;
  958. }
  959. ULONG
  960. APIENTRY
  961. DnsRmMibGet(
  962. ULONG InputDataSize,
  963. PVOID InputData,
  964. OUT PULONG OutputDataSize,
  965. OUT PVOID OutputData
  966. )
  967. /*++
  968. Routine Description:
  969. The DNS proxy only exposes one item to the MIB; its statistics.
  970. Arguments:
  971. InputDataSize - the MIB query data size
  972. InputData - specifies the MIB object to be retrieved
  973. OutputDataSize - the MIB response data size
  974. OutputData - receives the MIB object retrieved
  975. Return Value:
  976. ULONG - Win32 status code.
  977. --*/
  978. {
  979. ULONG Error;
  980. PIP_DNS_PROXY_MIB_QUERY Oidp;
  981. PROFILE("DnsRmMibGet");
  982. REFERENCE_DNS_OR_RETURN(ERROR_CAN_NOT_COMPLETE);
  983. if (InputDataSize < sizeof(*Oidp) || !InputData || !OutputDataSize) {
  984. Error = ERROR_INVALID_PARAMETER;
  985. }
  986. else {
  987. Oidp = (PIP_DNS_PROXY_MIB_QUERY)InputData;
  988. switch(Oidp->Oid) {
  989. case IP_DNS_PROXY_STATISTICS_OID: {
  990. if (*OutputDataSize < sizeof(*Oidp) + sizeof(DnsStatistics)) {
  991. *OutputDataSize = sizeof(*Oidp) + sizeof(DnsStatistics);
  992. Error = ERROR_INSUFFICIENT_BUFFER;
  993. }
  994. else if (!OutputData) {
  995. Error = ERROR_INVALID_PARAMETER;
  996. }
  997. else {
  998. *OutputDataSize = sizeof(*Oidp) + sizeof(DnsStatistics);
  999. Oidp = (PIP_DNS_PROXY_MIB_QUERY)OutputData;
  1000. Oidp->Oid = IP_DNS_PROXY_STATISTICS_OID;
  1001. CopyMemory(
  1002. Oidp->Data,
  1003. &DnsStatistics,
  1004. sizeof(DnsStatistics)
  1005. );
  1006. Error = NO_ERROR;
  1007. }
  1008. break;
  1009. }
  1010. default: {
  1011. NhTrace(
  1012. TRACE_FLAG_DNS,
  1013. "DnsRmMibGet: oid %d invalid",
  1014. Oidp->Oid
  1015. );
  1016. Error = ERROR_INVALID_PARAMETER;
  1017. break;
  1018. }
  1019. }
  1020. }
  1021. DEREFERENCE_DNS_AND_RETURN(Error);
  1022. }
  1023. ULONG
  1024. APIENTRY
  1025. DnsRmMibSet(
  1026. ULONG InputDataSize,
  1027. PVOID InputData
  1028. )
  1029. {
  1030. return ERROR_NOT_SUPPORTED;
  1031. }
  1032. ULONG
  1033. APIENTRY
  1034. DnsRmMibGetFirst(
  1035. ULONG InputDataSize,
  1036. PVOID InputData,
  1037. OUT PULONG OutputDataSize,
  1038. OUT PVOID OutputData
  1039. )
  1040. {
  1041. return ERROR_NOT_SUPPORTED;
  1042. }
  1043. ULONG
  1044. APIENTRY
  1045. DnsRmMibGetNext(
  1046. ULONG InputDataSize,
  1047. PVOID InputData,
  1048. OUT PULONG OutputDataSize,
  1049. OUT PVOID OutputData
  1050. )
  1051. {
  1052. return ERROR_NOT_SUPPORTED;
  1053. }