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.

1546 lines
28 KiB

  1. /*++
  2. Copyright (c) 2000-2000 Microsoft Corporation
  3. Module Name:
  4. ip.c
  5. Abstract:
  6. DNS Resolver Service.
  7. IP list and change notification.
  8. Author:
  9. Jim Gilroy (jamesg) November 2000
  10. Revision History:
  11. --*/
  12. #include "local.h"
  13. #include "iphlpapi.h"
  14. //
  15. // IP notify thread globals
  16. //
  17. HANDLE g_IpNotifyThread;
  18. DWORD g_IpNotifyThreadId;
  19. HANDLE g_IpNotifyEvent;
  20. HANDLE g_IpNotifyHandle;
  21. OVERLAPPED g_IpNotifyOverlapped;
  22. //
  23. // IP Address list values
  24. //
  25. PDNS_ADDR_ARRAY g_LocalAddrArray;
  26. PIP_ARRAY g_ClusterIpArray;
  27. IP_ADDRESS g_OldClusterIp;
  28. //
  29. // Cluster record TTLs -- use max TTL
  30. //
  31. #define CLUSTER_RECORD_TTL (g_MaxCacheTtl)
  32. //
  33. // Shutdown\close locking
  34. //
  35. // Since GQCS and GetOverlappedResult() don't directly wait
  36. // on StopEvent, we need to be able to close notification handle
  37. // and port in two different threads.
  38. //
  39. // Note: this should probably be some general CS that is
  40. // overloaded to do service control stuff.
  41. // I'm not using the server control CS because it's not clear
  42. // that the functions it does in dnsrslvr.c even need locking.
  43. //
  44. #define LOCK_IP_NOTIFY_HANDLE() EnterCriticalSection( &NetworkFailureCritSec )
  45. #define UNLOCK_IP_NOTIFY_HANDLE() LeaveCriticalSection( &NetworkFailureCritSec )
  46. CRITICAL_SECTION g_IpListCS;
  47. #define LOCK_IP_LIST() EnterCriticalSection( &g_IpListCS );
  48. #define UNLOCK_IP_LIST() LeaveCriticalSection( &g_IpListCS );
  49. //
  50. // Cluster Tag
  51. //
  52. #define CLUSTER_TAG 0xd734453d
  53. VOID
  54. CloseIpNotifyHandle(
  55. VOID
  56. )
  57. /*++
  58. Routine Description:
  59. Close IP notify handle.
  60. Wrapping up code since this close must be MT
  61. safe and is done in several places.
  62. Arguments:
  63. None
  64. Return Value:
  65. None
  66. --*/
  67. {
  68. LOCK_IP_NOTIFY_HANDLE();
  69. if ( g_IpNotifyHandle )
  70. {
  71. //CloseHandle( g_IpNotifyHandle );
  72. PostQueuedCompletionStatus(
  73. g_IpNotifyHandle,
  74. 0, // no bytes
  75. 0, // no key
  76. & g_IpNotifyOverlapped );
  77. g_IpNotifyHandle = NULL;
  78. }
  79. UNLOCK_IP_NOTIFY_HANDLE();
  80. }
  81. DNS_STATUS
  82. IpNotifyThread(
  83. IN LPVOID pvDummy
  84. )
  85. /*++
  86. Routine Description:
  87. IP notification thread.
  88. Arguments:
  89. pvDummy -- unused
  90. Return Value:
  91. NO_ERROR on normal service shutdown
  92. Win32 error on abnormal termination
  93. --*/
  94. {
  95. DNS_STATUS status;
  96. DWORD bytesRecvd;
  97. BOOL fstartedNotify;
  98. BOOL fhaveIpChange = FALSE;
  99. BOOL fsleep = FALSE;
  100. HANDLE notifyHandle;
  101. DNSDBG( INIT, ( "\nStart IpNotifyThread.\n" ));
  102. g_IpNotifyHandle = NULL;
  103. //
  104. // wait in loop on notifications
  105. //
  106. while ( !g_StopFlag )
  107. {
  108. //
  109. // spin protect
  110. // - if error in previous NotifyAddrChange or
  111. // GetOverlappedResult do short sleep to avoid
  112. // chance of hard spin
  113. //
  114. if ( fsleep )
  115. {
  116. WaitForSingleObject(
  117. g_hStopEvent,
  118. 60000 );
  119. fsleep = FALSE;
  120. continue;
  121. }
  122. //
  123. // start notification
  124. //
  125. // do this before checking result as we want notification
  126. // down BEFORE we read so we don't leave window where
  127. // IP change is not picked up
  128. //
  129. RtlZeroMemory(
  130. &g_IpNotifyOverlapped,
  131. sizeof(OVERLAPPED) );
  132. if ( g_IpNotifyEvent )
  133. {
  134. g_IpNotifyOverlapped.hEvent = g_IpNotifyEvent;
  135. ResetEvent( g_IpNotifyEvent );
  136. }
  137. notifyHandle = 0;
  138. fstartedNotify = FALSE;
  139. status = NotifyAddrChange(
  140. & notifyHandle,
  141. & g_IpNotifyOverlapped );
  142. if ( status == ERROR_IO_PENDING )
  143. {
  144. DNSDBG( INIT, (
  145. "NotifyAddrChange()\n"
  146. "\tstatus = %d\n"
  147. "\thandle = %d\n"
  148. "\toverlapped event = %d\n",
  149. status,
  150. notifyHandle,
  151. g_IpNotifyOverlapped.hEvent ));
  152. g_IpNotifyHandle = notifyHandle;
  153. fstartedNotify = TRUE;
  154. }
  155. else
  156. {
  157. DNSDBG( ANY, (
  158. "NotifyAddrChange() FAILED\n"
  159. "\tstatus = %d\n"
  160. "\thandle = %d\n"
  161. "\toverlapped event = %d\n",
  162. status,
  163. notifyHandle,
  164. g_IpNotifyOverlapped.hEvent ));
  165. fsleep = TRUE;
  166. }
  167. if ( g_StopFlag )
  168. {
  169. goto Done;
  170. }
  171. //
  172. // previous notification -- refresh data
  173. //
  174. // FlushCache currently include local IP list
  175. // sleep keeps us from spinning in this loop
  176. //
  177. // DCR: better spin protection;
  178. // if hit X times then sleep longer?
  179. //
  180. if ( fhaveIpChange )
  181. {
  182. DNSDBG( ANY, ( "\nIP notification, flushing cache and restarting.\n" ));
  183. HandleConfigChange(
  184. "IP-notification",
  185. TRUE // flush cache
  186. );
  187. fhaveIpChange = FALSE;
  188. }
  189. //
  190. // starting --
  191. // clear list to force rebuild of IP list AFTER starting notify
  192. // so we can know that we don't miss any changes;
  193. // need this on startup, but also to protect against any
  194. // NotifyAddrChange failues
  195. //
  196. else if ( fstartedNotify )
  197. {
  198. ClearLocalAddrArray();
  199. }
  200. //
  201. // anti-spin protection
  202. // - 15 second sleep between any notifications
  203. //
  204. WaitForSingleObject(
  205. g_hStopEvent,
  206. 15000 );
  207. if ( g_StopFlag )
  208. {
  209. goto Done;
  210. }
  211. //
  212. // wait on notification
  213. // - save notification result
  214. // - sleep on error, but never if notification
  215. //
  216. if ( fstartedNotify )
  217. {
  218. fhaveIpChange = GetOverlappedResult(
  219. g_IpNotifyHandle,
  220. & g_IpNotifyOverlapped,
  221. & bytesRecvd,
  222. TRUE // wait
  223. );
  224. fsleep = !fhaveIpChange;
  225. status = NO_ERROR;
  226. if ( !fhaveIpChange )
  227. {
  228. status = GetLastError();
  229. }
  230. DNSDBG( ANY, (
  231. "GetOverlappedResult() => %d.\n"
  232. "\t\tstatus = %d\n",
  233. fhaveIpChange,
  234. status ));
  235. }
  236. }
  237. Done:
  238. DNSDBG( ANY, ( "Stop IP Notify thread on service shutdown.\n" ));
  239. CloseIpNotifyHandle();
  240. return( status );
  241. }
  242. VOID
  243. ZeroInitIpListGlobals(
  244. VOID
  245. )
  246. /*++
  247. Routine Description:
  248. Zero-init IP globals just for failure protection.
  249. The reason to have this is there is some interaction with
  250. the cache from the notify thread. To avoid that being a
  251. problem we start the cache first.
  252. But just for safety we should at least zero init these
  253. globals first to protect us from cache touching them.
  254. Arguments:
  255. Return Value:
  256. NO_ERROR on normal service shutdown
  257. Win32 error on abnormal termination
  258. --*/
  259. {
  260. //
  261. // clear out globals to smoothly handle failure cases
  262. //
  263. g_LocalAddrArray = NULL;
  264. g_ClusterIpArray = NULL;
  265. g_OldClusterIp = 0;
  266. g_IpNotifyThread = NULL;
  267. g_IpNotifyThreadId = 0;
  268. g_IpNotifyEvent = NULL;
  269. g_IpNotifyHandle = NULL;
  270. }
  271. DNS_STATUS
  272. InitIpListAndNotification(
  273. VOID
  274. )
  275. /*++
  276. Routine Description:
  277. Start IP notification thread.
  278. Arguments:
  279. None
  280. Globals:
  281. Initializes IP list and notify thread globals.
  282. Return Value:
  283. NO_ERROR on normal service shutdown
  284. Win32 error on abnormal termination
  285. --*/
  286. {
  287. DNS_STATUS status = NO_ERROR;
  288. DNSDBG( TRACE, ( "InitIpListAndNotification()\n" ));
  289. //
  290. // CS for IP list access
  291. //
  292. InitializeCriticalSection( &g_IpListCS );
  293. //
  294. // create event for overlapped I/O
  295. //
  296. g_IpNotifyEvent = CreateEvent(
  297. NULL, // no security descriptor
  298. TRUE, // manual reset event
  299. FALSE, // start not signalled
  300. NULL // no name
  301. );
  302. if ( !g_IpNotifyEvent )
  303. {
  304. status = GetLastError();
  305. DNSDBG( ANY, ( "\nFAILED IpNotifyEvent create.\n" ));
  306. goto Done;
  307. }
  308. //
  309. // fire up IP notify thread
  310. //
  311. g_IpNotifyThread = CreateThread(
  312. NULL,
  313. 0,
  314. (LPTHREAD_START_ROUTINE) IpNotifyThread,
  315. NULL,
  316. 0,
  317. & g_IpNotifyThreadId
  318. );
  319. if ( !g_IpNotifyThread )
  320. {
  321. status = GetLastError();
  322. DNSDBG( ANY, (
  323. "FAILED to create IP notify thread = %d\n",
  324. status ));
  325. }
  326. Done:
  327. // not currently stopping on init failure
  328. return( ERROR_SUCCESS );
  329. }
  330. VOID
  331. ShutdownIpListAndNotify(
  332. VOID
  333. )
  334. /*++
  335. Routine Description:
  336. Stop IP notify thread.
  337. Note: currently this is blocking call, we'll wait until
  338. thread shuts down.
  339. Arguments:
  340. None.
  341. Return Value:
  342. None.
  343. --*/
  344. {
  345. DNSDBG( TRACE, ( "ShutdownIpListAndNotify()\n" ));
  346. //
  347. // MUST be stopping
  348. // - if not thread won't wake
  349. //
  350. ASSERT( g_StopFlag );
  351. g_StopFlag = TRUE;
  352. //
  353. // close IP notify handles -- waking thread if still running
  354. //
  355. if ( g_IpNotifyEvent )
  356. {
  357. SetEvent( g_IpNotifyEvent );
  358. }
  359. CloseIpNotifyHandle();
  360. //
  361. // wait for thread to stop
  362. //
  363. ThreadShutdownWait( g_IpNotifyThread );
  364. g_IpNotifyThread = NULL;
  365. //
  366. // cleanup IP lists
  367. //
  368. if ( g_LocalAddrArray )
  369. {
  370. GENERAL_HEAP_FREE( g_LocalAddrArray );
  371. g_LocalAddrArray = NULL;
  372. }
  373. if ( g_ClusterIpArray )
  374. {
  375. GENERAL_HEAP_FREE( g_ClusterIpArray );
  376. g_ClusterIpArray = NULL;
  377. g_OldClusterIp = 0;
  378. }
  379. //
  380. // close event
  381. //
  382. CloseHandle( g_IpNotifyEvent );
  383. g_IpNotifyEvent = NULL;
  384. //
  385. // kill off CS
  386. //
  387. DeleteCriticalSection( &g_IpListCS );
  388. }
  389. //
  390. // IP list routines
  391. //
  392. DWORD
  393. SizeForAddrArray(
  394. IN DWORD AddrCount
  395. )
  396. /*++
  397. Routine Description:
  398. Determine size for addr array of given count.
  399. Arguments:
  400. AddrCount -- count of addresses
  401. Return Value:
  402. Size in bytes required for addr array.
  403. --*/
  404. {
  405. return sizeof(DNS_ADDR_ARRAY) + (AddrCount * sizeof(DNS_ADDR_INFO));
  406. }
  407. PDNS_ADDR_ARRAY
  408. CopyAddrArray(
  409. IN PDNS_ADDR_ARRAY pAddrArray
  410. )
  411. /*++
  412. Routine Description:
  413. Create copy of address info array.
  414. Arguments:
  415. pAddrArray -- ptr to addr info array to copy
  416. Return Value:
  417. Ptr to new addr array.
  418. --*/
  419. {
  420. PDNS_ADDR_ARRAY pnew;
  421. DWORD size;
  422. DNSDBG( TRACE, ( "CopyAddrArray()\n" ));
  423. //
  424. // alloc memory and copy
  425. //
  426. size = SizeForAddrArray( pAddrArray->AddrCount );
  427. pnew = (PDNS_ADDR_ARRAY) GENERAL_HEAP_ALLOC( size );
  428. if ( pnew )
  429. {
  430. RtlCopyMemory(
  431. pnew,
  432. pAddrArray,
  433. size
  434. );
  435. }
  436. return pnew;
  437. }
  438. VOID
  439. ClearLocalAddrArray(
  440. VOID
  441. )
  442. /*++
  443. Routine Description:
  444. Clear the IP list data.
  445. Arguments:
  446. None.
  447. Globals:
  448. Updates IP list globals.
  449. Return Value:
  450. None.
  451. --*/
  452. {
  453. PDNS_ADDR_ARRAY poldArray;
  454. DNSDBG( TRACE, ( "ClearLocalAddrArray()\n" ));
  455. //
  456. // clear new list
  457. //
  458. // must go through lock even if no list, in case another
  459. // thread started building new list before our call
  460. //
  461. LOCK_IP_LIST();
  462. poldArray = g_LocalAddrArray;
  463. g_LocalAddrArray = NULL;
  464. UNLOCK_IP_LIST();
  465. // free old list
  466. if ( poldArray )
  467. {
  468. GENERAL_HEAP_FREE( poldArray );
  469. }
  470. }
  471. PDNS_ADDR_ARRAY
  472. GetLocalAddrArray(
  473. VOID
  474. )
  475. /*++
  476. Routine Description:
  477. Get copy of local IP address info list.
  478. Note: caller must free list.
  479. //
  480. // DCR: just direct return of counted array
  481. // - include IPv6
  482. //
  483. Arguments:
  484. None
  485. Globals:
  486. May update IP list globals.
  487. Return Value:
  488. Ptr to local addr info array. Caller must free.
  489. NULL on allocation failure.
  490. --*/
  491. {
  492. PDNS_ADDR_ARRAY pnew = NULL;
  493. DWORD size;
  494. DNSDBG( TRACE, ( "GetLocalAddrArray()\n" ));
  495. LOCK_IP_LIST();
  496. //
  497. // if no current list -- try to get one
  498. //
  499. if ( !g_LocalAddrArray )
  500. {
  501. g_LocalAddrArray = DnsGetLocalAddrArrayDirect();
  502. if ( !g_LocalAddrArray )
  503. {
  504. goto Unlock;
  505. }
  506. IF_DNSDBG( INIT )
  507. {
  508. DnsDbg_DnsAddrArray(
  509. "New IP address info:",
  510. g_LocalAddrArray
  511. );
  512. }
  513. }
  514. //
  515. // alloc memory and copy
  516. //
  517. pnew = CopyAddrArray( g_LocalAddrArray );
  518. Unlock:
  519. UNLOCK_IP_LIST();
  520. return pnew;
  521. }
  522. VOID
  523. RegisterClusterIp4Address(
  524. IN IP_ADDRESS ClusterIp,
  525. IN BOOL fAdd
  526. )
  527. /*++
  528. Routine Description:
  529. Register IP4 cluster IP.
  530. Arguments:
  531. ClusterIp -- IP of cluster
  532. fAdd -- TRUE if adding cluster IP, FALSE if deleting
  533. Return Value:
  534. None
  535. --*/
  536. {
  537. DNSLOG_F1( "RegisterClusterIp4Address" );
  538. DNSDBG( RPC, (
  539. "RegisterClusterIp4Address\n"
  540. "\tClusterIp = %s\n"
  541. "\tfAdd = %d\n",
  542. IP_STRING( ClusterIp ),
  543. fAdd ));
  544. LOCK_IP_LIST();
  545. //
  546. // adding, add to exclusion list
  547. //
  548. if ( fAdd )
  549. {
  550. // put IP in cluster array
  551. // - if array is full (or nonexistant), allocate bigger one
  552. // and slap IP in again
  553. if ( ! Dns_AddIpToIpArray(
  554. g_ClusterIpArray,
  555. ClusterIp ) )
  556. {
  557. g_ClusterIpArray = Dns_CopyAndExpandIpArray(
  558. g_ClusterIpArray,
  559. 25, // expand by 20 slots
  560. TRUE // delete existing copy
  561. );
  562. Dns_AddIpToIpArray(
  563. g_ClusterIpArray,
  564. ClusterIp );
  565. }
  566. }
  567. //
  568. // deleting remove from exclusion list
  569. // - but save old cluster IP as global until we are
  570. // sure it is gone
  571. //
  572. else
  573. {
  574. g_OldClusterIp = ClusterIp;
  575. if ( !g_ClusterIpArray )
  576. {
  577. goto Refresh;
  578. }
  579. Dns_ClearIpFromIpArray(
  580. g_ClusterIpArray,
  581. ClusterIp );
  582. }
  583. Refresh:
  584. // no need to clear local array
  585. //
  586. // IP help gives us notification of cluster IP change; since
  587. // cluster calls us after making change, we've probably already
  588. // been notified and done reread; since we don't keep a global
  589. // filtered list there's no need to dump it
  590. //
  591. // ClearLocalAddrArray();
  592. IF_DNSDBG( INIT )
  593. {
  594. DnsDbg_IpArray(
  595. "Cluster Exclusion Array:",
  596. NULL,
  597. g_ClusterIpArray
  598. );
  599. DnsDbg_Printf(
  600. "Old Cluster IP = %s\n",
  601. IP_STRING( g_OldClusterIp ) );
  602. }
  603. UNLOCK_IP_LIST();
  604. }
  605. DWORD
  606. RemoveClusterIpFromAddrArray(
  607. IN OUT PDNS_ADDR_ARRAY pAddrArray
  608. )
  609. /*++
  610. Routine Description:
  611. Screen cluster addresses from IP list.
  612. Note, assumes caller has network info locked.
  613. Arguments:
  614. pAddrArray -- array with unscreened address info
  615. AddrCount -- count of addresses
  616. Return Value:
  617. Count after screening
  618. --*/
  619. {
  620. DWORD loadIndex = 0;
  621. DWORD testIndex;
  622. IP_ADDRESS ip;
  623. BOOL fexclusion = FALSE;
  624. BOOL fexcludeOldCluster = FALSE;
  625. DNSDBG( TRACE, (
  626. "RemoveClusterIpFromAddrArray()\n" ));
  627. //
  628. // screen IP address list for cluster IPs
  629. //
  630. // note, we do a push down here because we want to maintain order
  631. // or remaining IP addresses
  632. //
  633. // note, we could have this function do a copy from source to
  634. // destination, so we aren't copying twice in this case;
  635. // i don't see this as a big win
  636. //
  637. for ( testIndex = 0;
  638. testIndex < pAddrArray->AddrCount;
  639. testIndex++ )
  640. {
  641. ip = pAddrArray->AddrArray[testIndex].IpAddr;
  642. if ( ip == g_OldClusterIp )
  643. {
  644. DNSDBG( INIT, (
  645. "Screened old cluster IP %s from local list.\n",
  646. IP_STRING(ip) ));
  647. fexclusion = TRUE;
  648. fexcludeOldCluster = TRUE;
  649. continue;
  650. }
  651. if ( Dns_IsAddressInIpArray( g_ClusterIpArray, ip ) )
  652. {
  653. DNSDBG( INIT, (
  654. "Screened cluster IP %s from local list.\n",
  655. IP_STRING(ip) ));
  656. fexclusion = TRUE;
  657. continue;
  658. }
  659. // once have exclusion must push down addresses
  660. if ( fexclusion )
  661. {
  662. RtlCopyMemory(
  663. & pAddrArray->AddrArray[loadIndex],
  664. & pAddrArray->AddrArray[testIndex],
  665. sizeof(DNS_ADDR_INFO)
  666. );
  667. }
  668. loadIndex++;
  669. }
  670. pAddrArray->AddrCount = loadIndex;
  671. // clear old cluster IP, if no longer in local list
  672. // - keep excluding until it doesn't show up anymore
  673. // if it shows up after that then it is legitimate address
  674. if ( !fexcludeOldCluster )
  675. {
  676. g_OldClusterIp = 0;
  677. }
  678. return( loadIndex );
  679. }
  680. PDNS_ADDR_ARRAY
  681. GetLocalAddrArrayFiltered(
  682. VOID
  683. )
  684. /*++
  685. Routine Description:
  686. Get filtered addr info array.
  687. Arguments:
  688. None.
  689. Globals:
  690. May update IP list globals.
  691. Return Value:
  692. Ptr to local addr info array. Caller must free.
  693. NULL on allocation failure.
  694. --*/
  695. {
  696. PDNS_ADDR_ARRAY pnew = NULL;
  697. DWORD count;
  698. DNSDBG( TRACE, ( "GetLocalAddrArrayFiltered()\n" ));
  699. LOCK_IP_LIST();
  700. //
  701. // create cluster filtered list
  702. //
  703. // - created copy of full list
  704. // - screen out cluster IPs
  705. // - note NET lock protects use of cluster list also
  706. //
  707. // note: if filter alloc fails, treats as no filtering avail
  708. //
  709. pnew = GetLocalAddrArray();
  710. if ( !pnew )
  711. {
  712. goto Unlock;
  713. }
  714. RemoveClusterIpFromAddrArray( pnew );
  715. Unlock:
  716. UNLOCK_IP_LIST();
  717. IF_DNSDBG( INIT )
  718. {
  719. DnsDbg_DnsAddrArray(
  720. "Filtered IP address info:",
  721. pnew
  722. );
  723. }
  724. return pnew;
  725. }
  726. //
  727. // Remote IP list routines
  728. //
  729. VOID
  730. R_ResolverGetLocalAddrInfoArray(
  731. IN DNS_RPC_HANDLE Reserved,
  732. OUT PDNS_ADDR_ARRAY * ppAddrArray,
  733. IN ENVAR_DWORD_INFO FilterInfo
  734. )
  735. /*++
  736. Routine Description:
  737. Get local IP address list from resolver.
  738. Arguments:
  739. Reserved -- RPC handle
  740. ppIpAddrList -- addr to recv ptr to array
  741. FilterInfo -- FilterClusterIp environment variable info
  742. Return Value:
  743. Count of IP addresses returned
  744. --*/
  745. {
  746. PDNS_ADDR_ARRAY preturnList = NULL;
  747. DNSLOG_F1( "R_ResolverGetLocalAddrInfoArray()" );
  748. DNSDBG( RPC, ( "R_ResolverGetLocalAddrInfoArray()\n" ));
  749. //
  750. // validate
  751. //
  752. if ( !ppAddrArray )
  753. {
  754. return; // ERROR_INVALID_PARAMETER;
  755. }
  756. if ( ClientThreadNotAllowedAccess() )
  757. {
  758. DNSLOG_F1( "R_ResolverGetLocalAddrInfoArray() - ERROR_ACCESS_DENIED" );
  759. goto Done;
  760. }
  761. //
  762. // determine if need to filter
  763. //
  764. // default is don't filter unless environment variable is
  765. // explicitly set
  766. //
  767. if ( FilterInfo.fFound && FilterInfo.Value )
  768. {
  769. preturnList = GetLocalAddrArrayFiltered();
  770. }
  771. else
  772. {
  773. preturnList = GetLocalAddrArray();
  774. }
  775. Done:
  776. *ppAddrArray = preturnList;
  777. DNSDBG( RPC, ( "Leave R_ResolverGetLocalAddrInfoArray()\n" ));
  778. }
  779. VOID
  780. R_ResolverRegisterClusterIp(
  781. IN DNS_RPC_HANDLE Handle,
  782. IN IP_ADDRESS ClusterIp,
  783. IN DWORD Tag,
  784. IN BOOL fAdd
  785. )
  786. /*++
  787. Routine Description:
  788. Make the query to remote DNS server.
  789. Arguments:
  790. Handle -- RPC handle
  791. ClusterIp -- IP of cluster
  792. fAdd -- TRUE if adding cluster IP, FALSE if deleting
  793. Return Value:
  794. None
  795. --*/
  796. {
  797. DNSLOG_F1( "R_ResolverRegisterClusterIp" );
  798. DNSDBG( RPC, (
  799. "R_ResolverRegisterClusterIp\n"
  800. "\tClusterIp = %s\n"
  801. "\tfAdd = %d\n",
  802. IP_STRING( ClusterIp ),
  803. fAdd ));
  804. //
  805. // DCR: should have security
  806. //
  807. if ( ClientThreadNotAllowedAccess() )
  808. {
  809. DNSLOG_F1( "R_ResolverFlushCache - ERROR_ACCESS_DENIED" );
  810. return;
  811. }
  812. if ( Tag != CLUSTER_TAG )
  813. {
  814. return;
  815. }
  816. RegisterClusterIp4Address(
  817. ClusterIp,
  818. fAdd );
  819. }
  820. //
  821. // Cluster IP manipulation.
  822. //
  823. #if 0
  824. BOOL
  825. Resolver_IsClusterIpCallback(
  826. IN PIP_UNION pIpUnion,
  827. IN BOOL fCopyName,
  828. OUT PWCHAR * ppName
  829. )
  830. /*++
  831. Routine Description:
  832. Detect cluster address.
  833. Arguments:
  834. pIpUnion -- address to test
  835. fCopyName -- want the name back
  836. ppName -- addr to recv ptr to name
  837. Return Value:
  838. TRUE if cluster IP
  839. FALSE if regular IP
  840. --*/
  841. {
  842. IP4_ADDRESS ip;
  843. DNSDBG( TRACE, (
  844. "Resolver_IsClusterIpCallback()\n" ));
  845. //
  846. // no IP6 support yet
  847. //
  848. *ppName = NULL;
  849. //
  850. // DCR: keep cluster as combo IP list with ptr to cluster name
  851. //
  852. if ( pIpUnion->IsIp6 )
  853. {
  854. return FALSE;
  855. }
  856. ip = pIpUnion.Ip4;
  857. if ( ip == g_OldClusterIp )
  858. {
  859. DNSDBG( INIT, (
  860. "IP is old cluster IP %s.\n",
  861. IP_STRING(ip) ));
  862. return TRUE;
  863. }
  864. LOCK_IP_LIST();
  865. fresult = Dns_IsAddressInIpArray( g_ClusterIpArray, ip );
  866. UNLOCK_IP_LIST();
  867. if ( fresult )
  868. {
  869. DNSDBG( INIT, (
  870. "IP is current cluster IP %s.\n",
  871. IP_STRING(ip) ));
  872. return TRUE;
  873. }
  874. // not cluster IP
  875. return FALSE;
  876. }
  877. #endif
  878. //
  879. // Cluster filtering callback routines
  880. //
  881. BOOL
  882. IsClusterIp4Addr(
  883. IN IP4_ADDRESS IpAddr
  884. )
  885. /*++
  886. Routine Description:
  887. Check if cluster address.
  888. Arguments:
  889. IpAddr -- IP4 address
  890. Return Value:
  891. TRUE if cluster IP.
  892. FALSE otherwise.
  893. --*/
  894. {
  895. DNSDBG( TRACE, (
  896. "IsClusterIp4Addr( %08x )\n", IpAddr ));
  897. if ( Dns_IsAddressInIpArray( g_ClusterIpArray, IpAddr ) )
  898. {
  899. DNSDBG( INIT, (
  900. "IP %s is cluster address.\n",
  901. IP_STRING(IpAddr) ));
  902. return TRUE;
  903. }
  904. return FALSE;
  905. }
  906. BOOL
  907. IsClusterAddress(
  908. IN OUT PQUERY_BLOB pBlob,
  909. IN PIP_UNION pIpUnion
  910. )
  911. /*++
  912. Routine Description:
  913. Cluster filtering callback.
  914. Arguments:
  915. Return Value:
  916. TRUE if cluster IP.
  917. FALSE otherwise.
  918. --*/
  919. {
  920. IP4_ADDRESS ip4;
  921. DNSDBG( TRACE, (
  922. "IsClusterAddress( %p, %p )\n",
  923. pBlob,
  924. pIpUnion ));
  925. if ( !g_ClusterIpArray )
  926. {
  927. return FALSE;
  928. }
  929. //
  930. // determine if cluster address
  931. //
  932. // DCR: create cluster IP records
  933. // - match cluster name and create forward record
  934. // - match IP and create reverse record to cluster name
  935. //
  936. if ( IPUNION_IS_IP4(pIpUnion) )
  937. {
  938. BOOL fresult;
  939. IP4_ADDRESS ip4;
  940. ip4 = IPUNION_GET_IP4( pIpUnion );
  941. LOCK_IP_LIST();
  942. fresult = Dns_IsAddressInIpArray( g_ClusterIpArray, ip4 );
  943. UNLOCK_IP_LIST();
  944. return fresult;
  945. }
  946. // DCR: no IP6 cluster support yet
  947. return FALSE;
  948. }
  949. DNS_STATUS
  950. R_ResolverRegisterCluster(
  951. IN DNS_RPC_HANDLE Handle,
  952. IN DWORD Tag,
  953. IN PWSTR pwsName,
  954. IN PRPC_IP_UNION pIpUnion,
  955. IN DWORD Flag
  956. )
  957. /*++
  958. Routine Description:
  959. Make the query to remote DNS server.
  960. Arguments:
  961. Handle -- RPC handle
  962. Tag -- RPC API tag
  963. pwsName -- name of cluster
  964. pIpUnion -- IP union
  965. Flag -- registration flag
  966. DNS_CLUSTER_ADD
  967. DNS_CLUSTER_DELETE_NAME
  968. DNS_CLUSTER_DELETE_IP
  969. Return Value:
  970. None
  971. --*/
  972. {
  973. PDNS_RECORD prrAddr = NULL;
  974. PDNS_RECORD prrPtr = NULL;
  975. WORD wtype;
  976. PIP_UNION pip = (PIP_UNION) pIpUnion;
  977. DNS_STATUS status;
  978. BOOL fadd;
  979. DNSLOG_F1( "R_ResolverRegisterCluster" );
  980. ASSERT( sizeof(IP_UNION) == sizeof(RPC_IP_UNION) );
  981. DNSDBG( RPC, (
  982. "R_ResolverRegisterCluster()\n"
  983. "\tpName = %s\n"
  984. "\tpIpUnion = %p\n"
  985. "\tFlag = %08x\n",
  986. pwsName,
  987. pip,
  988. Flag ));
  989. //
  990. // DCR: should have security
  991. //
  992. if ( ClientThreadNotAllowedAccess() )
  993. {
  994. DNSLOG_F1( "R_ResolverRegisterClusterIp - ERROR_ACCESS_DENIED" );
  995. return ERROR_ACCESS_DENIED;
  996. }
  997. if ( Tag != CLUSTER_TAG )
  998. {
  999. return ERROR_ACCESS_DENIED;
  1000. }
  1001. //
  1002. // get type
  1003. //
  1004. wtype = DNS_TYPE_A;
  1005. if ( IPUNION_IS_IP6(pip) )
  1006. {
  1007. wtype = DNS_TYPE_AAAA;
  1008. }
  1009. fadd = (Flag == DNS_CLUSTER_ADD);
  1010. //
  1011. // cluster add -- cache cluster records
  1012. // - forward and reverse
  1013. //
  1014. if ( !pwsName )
  1015. {
  1016. DNSDBG( ANY, ( "WARNING: no cluster name given!\n" ));
  1017. goto AddrList;
  1018. }
  1019. //
  1020. // build records
  1021. // - address and corresponding PTR
  1022. //
  1023. prrAddr = Dns_CreateForwardRecord(
  1024. pwsName,
  1025. pip,
  1026. CLUSTER_RECORD_TTL,
  1027. DnsCharSetUnicode,
  1028. DnsCharSetUnicode );
  1029. if ( !prrAddr )
  1030. {
  1031. status = GetLastError();
  1032. if ( status == ERROR_SUCCESS )
  1033. {
  1034. status = ERROR_INVALID_DATA;
  1035. }
  1036. return status;
  1037. }
  1038. SET_RR_CLUSTER( prrAddr );
  1039. prrPtr = Dns_CreatePtrRecordEx(
  1040. pip,
  1041. pwsName,
  1042. CLUSTER_RECORD_TTL,
  1043. DnsCharSetUnicode,
  1044. DnsCharSetUnicode );
  1045. if ( prrPtr )
  1046. {
  1047. SET_RR_CLUSTER( prrPtr );
  1048. }
  1049. //
  1050. // add records to cache
  1051. //
  1052. if ( Flag == DNS_CLUSTER_ADD )
  1053. {
  1054. Cache_RecordSetAtomic(
  1055. NULL, // record name
  1056. 0, // record type
  1057. prrAddr );
  1058. if ( prrPtr )
  1059. {
  1060. Cache_RecordSetAtomic(
  1061. NULL, // record name
  1062. 0, // record type
  1063. prrPtr );
  1064. }
  1065. prrAddr = NULL;
  1066. prrPtr = NULL;
  1067. }
  1068. //
  1069. // if delete cluster, flush cache entries for name\type
  1070. //
  1071. // DCR: don't have way to STRONG flush a name and type
  1072. // assume cluster name goes away wholesale
  1073. //
  1074. // DCR: need delete of cluster PTR record
  1075. // must be name specific
  1076. //
  1077. // DCR: build reverse name independently so whack works
  1078. // even without cluster name
  1079. //
  1080. else if ( Flag == DNS_CLUSTER_DELETE_NAME )
  1081. {
  1082. Cache_FlushRecords(
  1083. pwsName,
  1084. FLUSH_LEVEL_STRONG,
  1085. 0 );
  1086. // delete record matching PTR
  1087. }
  1088. else if ( Flag == DNS_CLUSTER_DELETE_IP )
  1089. {
  1090. Cache_FlushRecords(
  1091. pwsName,
  1092. FLUSH_LEVEL_STRONG,
  1093. 0 );
  1094. Cache_FlushRecords(
  1095. prrPtr->pName,
  1096. FLUSH_LEVEL_STRONG,
  1097. 0 );
  1098. }
  1099. //
  1100. // IP4 address list backcompat processing
  1101. //
  1102. // note: could use sockaddr to IP6 routine here
  1103. // if want list of IP6 addrs; if build combined
  1104. // type then should have conversion routine
  1105. //
  1106. // my take here is that IP6 cluster addresses won't show
  1107. // up period
  1108. //
  1109. AddrList:
  1110. if ( wtype == DNS_TYPE_A )
  1111. {
  1112. IP4_ADDRESS ip4 = IPUNION_GET_IP4(pip);
  1113. if ( !fadd &&
  1114. Flag != DNS_CLUSTER_DELETE_IP )
  1115. {
  1116. goto Done;
  1117. }
  1118. RegisterClusterIp4Address(
  1119. ip4,
  1120. fadd );
  1121. }
  1122. Done:
  1123. // cleanup uncached records
  1124. Dns_RecordFree( prrAddr );
  1125. Dns_RecordFree( prrPtr );
  1126. return ERROR_SUCCESS;
  1127. }
  1128. //
  1129. // End ip.c
  1130. //