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.

6407 lines
158 KiB

  1. /*++
  2. Copyright (c) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. asyncreg.c
  5. Abstract:
  6. Domain Name System (DNS) API
  7. Client IP/PTR dynamic update.
  8. Author:
  9. Glenn Curtis (GlennC) Feb-16-1998
  10. Revision History:
  11. Jim Gilroy (jamesg) May\June 2001
  12. - eliminate duplicate code
  13. - simplify lines
  14. - PTR reg only if forward successful
  15. - alternate names
  16. --*/
  17. #include "local.h"
  18. #include <netevent.h>
  19. #define ENABLE_DEBUG_LOGGING 1
  20. #include "logit.h"
  21. //
  22. // Flags for debugging for this module
  23. //
  24. #define DNS_DBG_DHCP DNS_DBG_UPDATE
  25. #define DNS_DBG_DHCP2 DNS_DBG_UPDATE2
  26. //
  27. // Registry values
  28. //
  29. #define ADAPTER_NAME_CLASS "AdapterNameClass"
  30. #define REGISTERED_ADDRS "RegisteredAddresses"
  31. #define REGISTERED_ADDRS_COUNT "RegisteredAddressCount"
  32. #define REGISTERED_NAME "RegisteredName"
  33. //
  34. // DCR_CLEANUP: tag these definitions to avoid collision
  35. // with registry.h defs
  36. //
  37. #define REGISTERED_HOST_NAME "HostName"
  38. #define REGISTERED_HOST_NAME_W L"HostName"
  39. #define REGISTERED_DOMAIN_NAME "DomainName"
  40. #define REGISTERED_DOMAIN_NAME_W L"DomainName"
  41. #define SENT_UPDATE_TO_IP "SentUpdateToIp"
  42. #define SENT_PRI_UPDATE_TO_IP "SentPriUpdateToIp"
  43. #define REGISTERED_TTL "RegisteredTTL"
  44. #define FLAGS "RegisteredFlags"
  45. #define REGISTERED_SINCE_BOOT "RegisteredSinceBoot"
  46. #define DNS_SERVER_ADDRS "DNSServerAddresses"
  47. #define DNS_SERVER_ADDRS_COUNT "DNSServerAddressCount"
  48. #define DEFAULT_REG_LOCATION "System\\CurrentControlSet\\Services\\Tcpip\\Parameters\\DNSRegisteredAdapters"
  49. #define DEFAULT_REG_LOCATION_WIN95 "System\\CurrentControlSet\\Services\\VxD\\MSTCP\\Parameters\\DNSRegisteredAdapters"
  50. #define NT_INTERFACE_REG_LOCATION "System\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\"
  51. #define TCPIP_REG_LOCATION "System\\CurrentControlSet\\Services\\Tcpip\\Parameters"
  52. #define DYN_DNS_ROOT_CLASS "DynDRootClass"
  53. #define BOOT_TIME "BootTime"
  54. #define DHCPVER_WIN95 2
  55. #define DHCPVER_WINNT 1
  56. #define DHCPVER_UNINIT 0
  57. #define FIRST_RETRY_INTERVAL 5*60 // 5 minutes
  58. #define SECOND_RETRY_INTERVAL 10*60 // 10 minutes
  59. #define FAILED_RETRY_INTERVAL 60*60 // 1 hour
  60. #define ASYNC_INIT_CALLED() (g_dwVersion != DHCPVER_UNINIT)
  61. #define CLEAR_ASYNC_INIT() g_dwVersion = DHCPVER_UNINIT ;
  62. //
  63. // Registry state flags
  64. //
  65. #define REGISTERED_FORWARD 0x00000001
  66. #define REGISTERED_PRIMARY 0x00000002
  67. #define REGISTERED_POINTER 0x00000004
  68. //
  69. // Update type
  70. //
  71. // Multiple types of updates for a given entry.
  72. // These identify which type (which name) being updated.
  73. //
  74. typedef enum _UpType
  75. {
  76. UPTYPE_PRIMARY = 1,
  77. UPTYPE_DOMAIN,
  78. UPTYPE_ALTERNATE,
  79. UPTYPE_PTR
  80. }
  81. UPTYPE, *PUPTYPE;
  82. #define IS_UPTYPE_PRIMARY(UpType) ((UpType)==UPTYPE_PRIMARY)
  83. #define IS_UPTYPE_DOMAIN(UpType) ((UpType)==UPTYPE_DOMAIN)
  84. #define IS_UPTYPE_ALTERNATE(UpType) ((UpType)==UPTYPE_ALTERNATE)
  85. #define IS_UPTYPE_PTR(UpType) ((UpType)==UPTYPE_PTR)
  86. //
  87. // On unjoin, deregistration wait no more than two minutes
  88. // to clean up -- then just get outta Dodge
  89. //
  90. #if DBG
  91. #define REMOVE_REGISTRATION_WAIT_LIMIT (0xffffffff)
  92. #else
  93. #define REMOVE_REGISTRATION_WAIT_LIMIT (120000) // 2 minutes in ms
  94. #endif
  95. //
  96. // definition of client list element
  97. //
  98. #define DNS_SIG_TOP 0x123aa321
  99. #define DNS_SIG_BOTTOM 0x321bb123
  100. typedef struct _DnsUpdateEntry
  101. {
  102. LIST_ENTRY List;
  103. DWORD SignatureTop;
  104. PSTR AdapterName;
  105. PSTR HostName;
  106. PSTR PrimaryDomainName;
  107. PSTR DomainName;
  108. PSTR AlternateNames;
  109. DWORD AlternateIndex;
  110. DWORD HostAddrCount;
  111. PREGISTER_HOST_ENTRY HostAddrs;
  112. PIP_ARRAY DnsServerList;
  113. IP_ADDRESS SentUpdateToIp;
  114. IP_ADDRESS SentPriUpdateToIp;
  115. DWORD TTL;
  116. DWORD Flags;
  117. BOOL fNewElement;
  118. BOOL fFromRegistry;
  119. BOOL fRemove;
  120. BOOL fRegisteredPRI;
  121. BOOL fRegisteredFWD;
  122. BOOL fRegisteredALT;
  123. BOOL fRegisteredPTR;
  124. BOOL fDisableErrorLogging;
  125. DWORD RetryCount;
  126. DWORD RetryTime;
  127. PREGISTER_HOST_STATUS pRegisterStatus;
  128. DWORD SignatureBottom;
  129. }
  130. UPDATE_ENTRY, *PUPDATE_ENTRY;
  131. //
  132. // globals
  133. //
  134. //
  135. // the behavior of the system at boot differs from when it is not at
  136. // boot. At boot time we collect a bunch of requests and register them
  137. // in one shot. One thread does this. After boot, we register them
  138. // as requests come in, one at a time.
  139. //
  140. BOOL g_fAtBoot = TRUE;
  141. BOOL g_fPurgeRegistrations = FALSE;
  142. BOOL g_fPurgeRegistrationsInitiated = FALSE;
  143. BOOL g_fRegistrationThreadRunning = FALSE;
  144. BOOL g_fNoMoreDDNSUpdates = FALSE;
  145. BOOL g_fShutdown = FALSE;
  146. DWORD g_dwTime = 0; // To determine boot time or not
  147. //
  148. // The following global is used to eliminate multiple calls to GetVersion()
  149. //
  150. DWORD g_dwVersion = DHCPVER_UNINIT; // is 1 for winnt and 2 for win95
  151. LIST_ENTRY g_RegistrationList;
  152. HANDLE g_hStopEvent = NULL;
  153. HANDLE g_hThreadDeadEvent = NULL;
  154. HANDLE g_hNewItemEvent = NULL;
  155. HANDLE g_hRegistrationThread = NULL;
  156. BOOL g_fQuit = FALSE;
  157. HKEY g_hKey = NULL;
  158. DWORD g_dwBootTime = 60;
  159. //
  160. // Private heap
  161. //
  162. #define INITIAL_DDNS_HEAP (16*1024)
  163. HANDLE g_DDNSHeap;
  164. #define PHEAP_ALLOC_ZERO( s ) HeapAlloc( g_DDNSHeap, HEAP_ZERO_MEMORY, (s) )
  165. #define PHEAP_ALLOC( s ) HeapAlloc( g_DDNSHeap, HEAP_ZERO_MEMORY, (s) )
  166. #define PHEAP_FREE( p ) HeapFree( g_DDNSHeap, 0, (p) )
  167. //
  168. // Private protos
  169. //
  170. DNS_STATUS
  171. AllocateUpdateEntry(
  172. IN PSTR AdapterName,
  173. IN PSTR HostName,
  174. IN PSTR DomainName,
  175. IN PSTR PrimaryDomainName,
  176. IN PSTR AlternateNames,
  177. IN DWORD HostAddrCount,
  178. IN PREGISTER_HOST_ENTRY HostAddrs,
  179. IN DWORD DnsServerCount,
  180. IN PIP_ADDRESS DnsServerList,
  181. IN IP_ADDRESS SentUpdateToIp,
  182. IN IP_ADDRESS SentPriUpdateToIp,
  183. IN DWORD TTL,
  184. IN DWORD Flags,
  185. IN DWORD RetryCount,
  186. IN DWORD RetryTime,
  187. IN PREGISTER_HOST_STATUS RegisterStatus,
  188. OUT PUPDATE_ENTRY * ppUpdateEntry
  189. );
  190. VOID
  191. FreeUpdateEntry(
  192. IN OUT PUPDATE_ENTRY pUpdateEntry
  193. );
  194. VOID
  195. FreeUpdateEntryList(
  196. IN PLIST_ENTRY pUpdateEntry
  197. );
  198. DWORD
  199. WINAPI
  200. RegistrationThread(
  201. VOID
  202. );
  203. VOID
  204. WriteUpdateEntryToRegistry(
  205. IN PUPDATE_ENTRY pUpdateEntry
  206. );
  207. PUPDATE_ENTRY
  208. ReadUpdateEntryFromRegistry(
  209. IN PSTR pszAdapterName
  210. );
  211. VOID
  212. MarkAdapterAsPendingUpdate(
  213. IN PSTR pAdapterName
  214. );
  215. DWORD
  216. GetNextUpdateEntryFromList(
  217. OUT PUPDATE_ENTRY * ppUpdateEntry,
  218. OUT PDWORD pdwWaitTime
  219. );
  220. VOID
  221. ProcessUpdateEntry(
  222. IN OUT PUPDATE_ENTRY pUpdateEntry,
  223. IN BOOL fPurgeMode
  224. );
  225. DNS_STATUS
  226. ModifyAdapterRegistration(
  227. IN OUT PUPDATE_ENTRY pUpdateEntry,
  228. IN OUT PUPDATE_ENTRY pRegistryEntry,
  229. IN PDNS_RECORD pUpdateRecord,
  230. IN PDNS_RECORD pRegRecord,
  231. IN BOOL fPrimaryDomain
  232. );
  233. VOID
  234. ResetAdaptersInRegistry(
  235. VOID
  236. );
  237. VOID
  238. DeregisterUnusedAdapterInRegistry(
  239. IN BOOL fPurgeMode
  240. );
  241. PDNS_RECORD
  242. GetPreviousRegistrationInformation(
  243. IN PUPDATE_ENTRY pUpdateEntry,
  244. IN BOOL fPrimaryDomain,
  245. OUT PIP_ADDRESS pServerIp
  246. );
  247. PDNS_RECORD
  248. CreateDnsRecordSetUnion(
  249. IN PDNS_RECORD pSet1,
  250. IN PDNS_RECORD pSet2
  251. );
  252. #if 1 // DBG
  253. VOID
  254. LogHostEntries(
  255. IN DWORD dwHostAddrCount,
  256. IN PREGISTER_HOST_ENTRY pHostAddrs
  257. );
  258. #define DNSLOG_HOST_ENTRYS( a, b ) LogHostEntries( a, b )
  259. #else
  260. #define DNSLOG_HOST_ENTRYS( a, b )
  261. #endif
  262. #if 1 // DBG
  263. VOID
  264. LogPipAddress(
  265. IN DWORD dwServerListCount,
  266. IN PIP_ADDRESS pServers
  267. );
  268. #define DNSLOG_PIP_ADDRESS( a, b ) LogPipAddress( a, b )
  269. #else
  270. #define DNSLOG_PIP_ADDRESS( a, b )
  271. #endif
  272. #if 1 // DBG
  273. VOID
  274. LogPipArray(
  275. IN PIP_ARRAY pServers
  276. );
  277. #define DNSLOG_PIP_ARRAY( a ) LogPipArray( a )
  278. #else
  279. #define DNSLOG_PIP_ARRAY( a )
  280. #endif
  281. DNS_STATUS
  282. alertOrStartRegistrationThread(
  283. VOID
  284. );
  285. VOID
  286. registerUpdateStatus(
  287. IN OUT PREGISTER_HOST_STATUS pRegStatus,
  288. IN DNS_STATUS Status
  289. );
  290. VOID
  291. enqueueUpdate(
  292. IN OUT PUPDATE_ENTRY pUpdate
  293. );
  294. VOID
  295. enqueueUpdateMaybe(
  296. IN OUT PUPDATE_ENTRY pUpdate
  297. );
  298. PLIST_ENTRY
  299. dequeueAndCleanupUpdate(
  300. IN OUT PLIST_ENTRY pUpdateEntry
  301. );
  302. BOOL
  303. searchForOldUpdateEntriesAndCleanUp(
  304. IN PSTR pszAdapterName,
  305. IN PUPDATE_ENTRY pUpdateEntry OPTIONAL,
  306. IN BOOL fLookInRegistry
  307. );
  308. BOOL
  309. compareUpdateEntries(
  310. IN PUPDATE_ENTRY pUdapteEntry1,
  311. IN PUPDATE_ENTRY pUpdateEntry2
  312. );
  313. BOOL
  314. compareHostEntryAddrs(
  315. IN PREGISTER_HOST_ENTRY Addrs1,
  316. IN PREGISTER_HOST_ENTRY Addrs2,
  317. IN DWORD Count
  318. );
  319. BOOL
  320. compareServerLists(
  321. IN PIP_ARRAY List1,
  322. IN PIP_ARRAY List2
  323. );
  324. DWORD
  325. GetRegistryValue(
  326. HKEY KeyHandle,
  327. PSTR ValueName,
  328. DWORD ValueType,
  329. LPBYTE BufferPtr
  330. );
  331. //
  332. // Jim routines
  333. //
  334. VOID
  335. LogRegistration(
  336. IN PUPDATE_ENTRY pUpdateEntry,
  337. IN DNS_STATUS Status,
  338. IN DWORD UpType,
  339. IN BOOL fDeregister,
  340. IN IP4_ADDRESS DnsIp,
  341. IN IP4_ADDRESS UpdateIp
  342. );
  343. VOID
  344. AsyncLogUpdateEntry(
  345. IN PSTR pszHeader,
  346. IN PUPDATE_ENTRY pEntry
  347. );
  348. #define ASYNCREG_UPDATE_ENTRY(h,p) AsyncLogUpdateEntry(h,p)
  349. VOID
  350. DnsPrint_UpdateEntry(
  351. IN PRINT_ROUTINE PrintRoutine,
  352. IN PPRINT_CONTEXT PrintContext,
  353. IN PSTR pszHeader,
  354. IN PUPDATE_ENTRY pUpdateEntry
  355. );
  356. #if DBG
  357. #define DnsDbg_UpdateEntry(h,p) DnsPrint_UpdateEntry(DnsPR,NULL,h,p)
  358. #else
  359. #define DnsDbg_UpdateEntry(h,p)
  360. #endif
  361. PDNS_RECORD
  362. CreateForwardRecords(
  363. IN PUPDATE_ENTRY pUpdateEntry,
  364. IN BOOL fUsePrimaryName
  365. );
  366. PDNS_RECORD
  367. CreatePtrRecord(
  368. IN PSTR pszHostName,
  369. IN PSTR pszDomainName,
  370. IN IP4_ADDRESS Ip4Addr,
  371. IN DWORD Ttl
  372. );
  373. VOID
  374. UpdatePtrRecords(
  375. IN OUT PUPDATE_ENTRY pUpdateEntry,
  376. IN BOOL fAdd
  377. );
  378. VOID
  379. SetUpdateStatus(
  380. IN OUT PUPDATE_ENTRY pUpdateEntry,
  381. IN DNS_STATUS Status,
  382. IN BOOL fPrimary
  383. );
  384. //
  385. // Public functions
  386. //
  387. DNS_STATUS
  388. WINAPI
  389. DnsAsyncRegisterInit(
  390. IN PSTR pszRootRegKey
  391. )
  392. /*++
  393. Routine Description:
  394. Initialize asynchronous DNS registration.
  395. Process must call (one time) before calling DnsAsyncRegisterHostAddrs.
  396. Arguments:
  397. None.
  398. Return Value:
  399. DNS or Win32 error code.
  400. --*/
  401. {
  402. DWORD Status = ERROR_SUCCESS;
  403. DWORD disposition;
  404. DWORD disallowUpdate;
  405. //
  406. // Initialize debug logging funtion
  407. //
  408. ASYNCREG_INIT();
  409. ASYNCREG_F1( "Inside function DnsAsyncRegisterInit" );
  410. ASYNCREG_TIME();
  411. ASYNCREG_F2( " pszRootRegKey value set to %s", pszRootRegKey );
  412. //
  413. // g_dwVersion is only set once and this function must be called exactly
  414. // once until the corresponding TERM is called.
  415. //
  416. if ( ASYNC_INIT_CALLED() )
  417. {
  418. //
  419. // we are calling this more than once!
  420. //
  421. DNS_ASSERT(FALSE) ;
  422. return ERROR_INTERNAL_ERROR ;
  423. }
  424. else
  425. {
  426. DWORD sysVersion;
  427. if ( g_fRegistrationThreadRunning )
  428. {
  429. //
  430. // we encountered a previous problem while trying to stop
  431. // the registration thread, do not allow any further update
  432. // operations for this process!
  433. //
  434. DNS_ASSERT(FALSE) ;
  435. return ERROR_INTERNAL_ERROR ;
  436. }
  437. sysVersion = GetVersion();
  438. if ( sysVersion < 0x80000000 )
  439. {
  440. g_dwVersion = DHCPVER_WINNT;
  441. }
  442. else
  443. {
  444. g_dwVersion = DHCPVER_WIN95;
  445. }
  446. }
  447. //
  448. // if not supplied, use default
  449. //
  450. if ( !pszRootRegKey )
  451. {
  452. if ( g_dwVersion == DHCPVER_WINNT )
  453. {
  454. pszRootRegKey = DEFAULT_REG_LOCATION ;
  455. }
  456. else if ( g_dwVersion == DHCPVER_WIN95 )
  457. {
  458. pszRootRegKey = DEFAULT_REG_LOCATION_WIN95 ;
  459. }
  460. else
  461. {
  462. // we did not set g_dwVersion
  463. DNS_ASSERT(FALSE) ;
  464. pszRootRegKey = DEFAULT_REG_LOCATION ;
  465. }
  466. }
  467. //
  468. // Create private heap
  469. //
  470. g_DDNSHeap = HeapCreate( 0, INITIAL_DDNS_HEAP, 0 );
  471. if ( g_DDNSHeap == NULL )
  472. {
  473. g_DDNSHeap = GetProcessHeap();
  474. if ( g_DDNSHeap == NULL )
  475. {
  476. ASYNCREG_F1( "ERROR: DnsAsyncRegisterInit function failed to create heap" );
  477. Status = DNS_ERROR_NO_MEMORY;
  478. goto ErrorExit;
  479. }
  480. }
  481. //
  482. // get registration configuration info
  483. // - just insure we have the latest copy
  484. //
  485. // DCR_FIX: when available get latest copy from resolver
  486. // does not need to be done on init, may be done on call
  487. //
  488. Reg_ReadGlobalsEx( 0, NULL );
  489. //
  490. // Open the registry location used to store this info
  491. //
  492. // Note that Win95 does not support WideCharacter types
  493. // The result is that we are forced to use RegCreateKeyExA for
  494. // both
  495. //
  496. Status = RegCreateKeyExA(
  497. HKEY_LOCAL_MACHINE,
  498. pszRootRegKey,
  499. 0, // reserved
  500. DYN_DNS_ROOT_CLASS,
  501. REG_OPTION_NON_VOLATILE, // options
  502. KEY_READ | KEY_WRITE, // desired access
  503. NULL,
  504. &g_hKey,
  505. &disposition
  506. );
  507. if ( Status != NO_ERROR )
  508. {
  509. goto ErrorExit;
  510. }
  511. if ( !( g_hStopEvent = CreateEvent( NULL, TRUE, FALSE, NULL ) ) )
  512. {
  513. Status = GetLastError();
  514. goto ErrorExit;
  515. }
  516. if ( !( g_hThreadDeadEvent = CreateEvent( NULL, TRUE, FALSE, NULL ) ) )
  517. {
  518. Status = GetLastError();
  519. goto ErrorExit;
  520. }
  521. if ( !( g_hNewItemEvent = CreateEvent( NULL, TRUE, FALSE, NULL ) ) )
  522. {
  523. Status = GetLastError();
  524. goto ErrorExit;
  525. }
  526. EnterCriticalSection( &g_RegistrationListCS );
  527. InitializeListHead( &g_RegistrationList );
  528. LeaveCriticalSection( &g_RegistrationListCS );
  529. //
  530. // the following call is needed for determining if we are still in
  531. // boot time or not
  532. //
  533. g_dwTime = Dns_GetCurrentTimeInSeconds();
  534. g_fQuit = FALSE;
  535. g_fAtBoot = TRUE;
  536. g_fPurgeRegistrations = FALSE;
  537. g_fPurgeRegistrationsInitiated = FALSE;
  538. g_fNoMoreDDNSUpdates = FALSE;
  539. ResetAdaptersInRegistry();
  540. return NO_ERROR;
  541. ErrorExit:
  542. if ( g_DDNSHeap &&
  543. g_DDNSHeap != GetProcessHeap() )
  544. {
  545. HeapDestroy( g_DDNSHeap );
  546. g_DDNSHeap = NULL;
  547. }
  548. if ( g_hStopEvent )
  549. {
  550. CloseHandle(g_hStopEvent);
  551. g_hStopEvent = NULL;
  552. }
  553. if ( g_hThreadDeadEvent )
  554. {
  555. CloseHandle(g_hThreadDeadEvent);
  556. g_hThreadDeadEvent = NULL;
  557. }
  558. if ( g_hNewItemEvent )
  559. {
  560. CloseHandle(g_hNewItemEvent);
  561. g_hNewItemEvent = NULL;
  562. }
  563. if ( g_hKey )
  564. {
  565. RegCloseKey( g_hKey );
  566. g_hKey = NULL;
  567. }
  568. CLEAR_ASYNC_INIT(); // reset this so we are no longer in use
  569. return(Status);
  570. }
  571. DNS_STATUS
  572. WINAPI
  573. DnsAsyncRegisterTerm(
  574. VOID
  575. )
  576. /*++
  577. Routine Description:
  578. Stop DNS registration. Shutdown DNS registration thread.
  579. Initialization routine each process should call exactly on exit after
  580. using DnsAsyncRegisterHostAddrs. This will signal to us that if our
  581. thread is still trying to talk to a server, we'll stop trying.
  582. Arguments:
  583. None.
  584. Return Value:
  585. DNS or Win32 error code.
  586. --*/
  587. {
  588. DWORD waitResult;
  589. ASYNCREG_F1( "Inside function DnsAsyncRegisterTerm" );
  590. ASYNCREG_TIME();
  591. ASYNCREG_F1( "" );
  592. if ( ASYNC_INIT_CALLED() )
  593. {
  594. if ( g_hStopEvent &&
  595. g_fRegistrationThreadRunning )
  596. {
  597. SetEvent(g_hStopEvent);
  598. waitResult = WaitForSingleObject( g_hThreadDeadEvent,
  599. INFINITE );
  600. switch ( waitResult )
  601. {
  602. case WAIT_OBJECT_0 :
  603. ASYNCREG_F1( "DNSAPI.DLL: Registration thread signaled it was finished" );
  604. ASYNCREG_F1( "" );
  605. break;
  606. case WAIT_TIMEOUT :
  607. ASYNCREG_F1( "DNSAPI.DLL: Registration thread won't stop! " );
  608. ASYNCREG_F1( "" );
  609. DNS_ASSERT( FALSE );
  610. break;
  611. }
  612. if ( g_fRegistrationThreadRunning )
  613. {
  614. ASYNCREG_F1( "DNSAPI.DLL: Registration thread wasn't stopped! " );
  615. ASYNCREG_F1( "" );
  616. DNS_ASSERT(FALSE) ;
  617. CLEAR_ASYNC_INIT(); // reset this so we are no longer in use
  618. return ERROR_INTERNAL_ERROR ;
  619. }
  620. }
  621. EnterCriticalSection( &g_RegistrationThreadCS );
  622. //
  623. // Close the thread handles if they aren't already.
  624. //
  625. if ( g_hRegistrationThread )
  626. {
  627. CloseHandle( g_hRegistrationThread );
  628. g_hRegistrationThread = NULL;
  629. }
  630. if ( g_hStopEvent )
  631. {
  632. CloseHandle(g_hStopEvent);
  633. g_hStopEvent = NULL;
  634. }
  635. if ( g_hThreadDeadEvent )
  636. {
  637. CloseHandle(g_hThreadDeadEvent);
  638. g_hThreadDeadEvent = NULL;
  639. }
  640. if ( g_hNewItemEvent )
  641. {
  642. CloseHandle(g_hNewItemEvent);
  643. g_hNewItemEvent = NULL;
  644. }
  645. g_fQuit = TRUE;
  646. if ( g_hKey )
  647. {
  648. RegCloseKey(g_hKey);
  649. g_hKey = NULL;
  650. }
  651. LeaveCriticalSection( &g_RegistrationThreadCS );
  652. Dns_TimeoutSecurityContextList( TRUE );
  653. CLEAR_ASYNC_INIT(); // reset this so we are no longer in use
  654. if ( g_DDNSHeap &&
  655. g_DDNSHeap != GetProcessHeap() )
  656. {
  657. HeapDestroy( g_DDNSHeap );
  658. g_DDNSHeap = NULL;
  659. }
  660. return NO_ERROR;
  661. }
  662. else
  663. {
  664. //
  665. // This is being called more than once! Or the Init function has
  666. // not yet been called!
  667. //
  668. DNS_ASSERT(FALSE) ;
  669. return ERROR_INTERNAL_ERROR ;
  670. }
  671. }
  672. DNS_STATUS
  673. WINAPI
  674. DnsRemoveRegistrations(
  675. VOID
  676. )
  677. /*++
  678. Routine Description:
  679. Remove DNS host registrations for this machine.
  680. This will be called by DHCP client on domain unjoin. Removes DNS
  681. registrations for the box, then terminates the registration thread
  682. to disable further registrations.
  683. Registrations can only be reenabled by calling DnsAsyncRegisterInit()
  684. again.
  685. Arguments:
  686. None.
  687. Return Value:
  688. ERROR_SUCCESS if successful.
  689. ErrorCode on failure.
  690. --*/
  691. {
  692. PLIST_ENTRY pListEntry;
  693. PLIST_ENTRY pTopOfList;
  694. ASYNCREG_F1( "Inside function DnsRemoveRegistrations" );
  695. ASYNCREG_TIME();
  696. DNSDBG( TRACE, ( "DnsRemoveRegistrations()\n" ));
  697. DNS_ASSERT(ASYNC_INIT_CALLED()); // make sure init was called
  698. if ( !ASYNC_INIT_CALLED() )
  699. {
  700. ASYNCREG_F1( "DnsAsyncRemoveRegistrations returning ERROR_SERVICE_NOT_ACTIVE" );
  701. ASYNCREG_F1( "This is an error in DHCP client code, it forgot to call DnsAsyncRegisterInit()" );
  702. return ERROR_SERVICE_NOT_ACTIVE;
  703. }
  704. //
  705. // Set a global flag to disable any further adapter registration calls
  706. //
  707. g_fNoMoreDDNSUpdates = TRUE;
  708. //
  709. // Get the Registration list lock
  710. //
  711. EnterCriticalSection( &g_RegistrationListCS );
  712. //
  713. // Mark any and all adapter registration information in the registry
  714. // as non-registered. These will be later interpreted as non-existant
  715. // and deregistered by the RegistrationThread.
  716. //
  717. ResetAdaptersInRegistry();
  718. //
  719. // Walk the list of pending update entries and clear out the
  720. // non-neccessary updates.
  721. //
  722. pTopOfList = &g_RegistrationList;
  723. pListEntry = pTopOfList->Flink;
  724. while ( pListEntry != pTopOfList )
  725. {
  726. if ( ((PUPDATE_ENTRY) pListEntry)->SignatureTop !=
  727. DNS_SIG_TOP ||
  728. ((PUPDATE_ENTRY) pListEntry)->SignatureBottom !=
  729. DNS_SIG_BOTTOM )
  730. {
  731. //
  732. // Someone trashed our registration list!
  733. //
  734. DNS_ASSERT( FALSE );
  735. //
  736. // We'll reset it and try to move on . . .
  737. //
  738. InitializeListHead( &g_RegistrationList );
  739. pTopOfList = &g_RegistrationList;
  740. pListEntry = pTopOfList->Flink;
  741. continue;
  742. }
  743. if ( !((PUPDATE_ENTRY) pListEntry)->fRemove )
  744. {
  745. //
  746. // There is an update entry in the registration list
  747. // that has not yet been processed. Since it is an
  748. // add update, we'll blow it away.
  749. //
  750. pListEntry = dequeueAndCleanupUpdate( pListEntry );
  751. continue;
  752. }
  753. else
  754. {
  755. ((PUPDATE_ENTRY) pListEntry)->fNewElement = TRUE;
  756. ((PUPDATE_ENTRY) pListEntry)->fRegisteredFWD = FALSE;
  757. ((PUPDATE_ENTRY) pListEntry)->fRegisteredPRI = FALSE;
  758. ((PUPDATE_ENTRY) pListEntry)->fRegisteredPTR = FALSE;
  759. ((PUPDATE_ENTRY) pListEntry)->fDisableErrorLogging = FALSE;
  760. ((PUPDATE_ENTRY) pListEntry)->RetryCount = 2;
  761. ((PUPDATE_ENTRY) pListEntry)->RetryTime =
  762. Dns_GetCurrentTimeInSeconds();
  763. pListEntry = pListEntry->Flink;
  764. }
  765. }
  766. LeaveCriticalSection( &g_RegistrationListCS );
  767. g_fPurgeRegistrations = TRUE;
  768. //
  769. // start async registration thread if not started
  770. //
  771. alertOrStartRegistrationThread();
  772. //
  773. // wait for async registration thread to terminate
  774. //
  775. // however we'll bag it after a few minutes -- a robustness check
  776. // to avoid long hang; Generally the machine will be rebooted
  777. // so failure to cleanup the list and terminate is not critical;
  778. // Registrations will have to be cleaned up by admin action or
  779. // aging on the DNS server
  780. //
  781. #if DBG
  782. {
  783. DWORD waitResult;
  784. waitResult = WaitForSingleObject(
  785. g_hThreadDeadEvent,
  786. REMOVE_REGISTRATION_WAIT_LIMIT );
  787. if ( waitResult != WAIT_OBJECT_0 )
  788. {
  789. ASYNCREG_F1(
  790. "ERROR: RemoveRegistration() wait expired before async thread\n"
  791. "\ttermination!\n" );
  792. }
  793. }
  794. #else
  795. WaitForSingleObject( g_hThreadDeadEvent, REMOVE_REGISTRATION_WAIT_LIMIT );
  796. #endif
  797. return NO_ERROR;
  798. }
  799. DNS_STATUS
  800. WINAPI
  801. privateAsyncRegisterHostAddrs(
  802. IN PSTR pszAdapterName,
  803. IN PSTR pszHostName,
  804. IN PREGISTER_HOST_ENTRY pHostAddrs,
  805. IN DWORD dwHostAddrCount,
  806. IN PIP4_ADDRESS pipDnsServerList,
  807. IN DWORD dwDnsServerCount,
  808. IN PSTR pszDomainName,
  809. IN PREGISTER_HOST_STATUS pRegisterStatus,
  810. IN DWORD dwTTL,
  811. IN DWORD dwFlags
  812. )
  813. /*++
  814. Routine Description:
  815. Registers host address with DNS server.
  816. This is called by DHCP client to register a particular IP.
  817. This is the working UTF8 version of the
  818. DnsAsyncRegisterHostAddrs() unicode routine actually called by
  819. the DHCP client.
  820. Arguments:
  821. Return Value:
  822. ERROR_SUCCESS if successful.
  823. Error code on failure.
  824. --*/
  825. {
  826. DWORD status = NO_ERROR;
  827. PUPDATE_ENTRY pupEntry = NULL;
  828. PSTR padapterDN = NULL;
  829. PSTR pprimaryDN = NULL;
  830. REG_UPDATE_INFO updateInfo;
  831. BOOL fcleanupUpdateInfo = FALSE;
  832. ASYNCREG_F1( "Inside function privateDnsAsyncRegisterHostAddrs, parameters are:" );
  833. ASYNCREG_F2( " pszAdapterName : %s", pszAdapterName );
  834. ASYNCREG_F2( " pszHostName : %s", pszHostName );
  835. ASYNCREG_F2( " dwHostAddrCount : %d", dwHostAddrCount );
  836. DNSLOG_HOST_ENTRYS( dwHostAddrCount, pHostAddrs );
  837. ASYNCREG_F2( " dwDnsServerCount : %d", dwDnsServerCount );
  838. if ( dwDnsServerCount && pipDnsServerList )
  839. {
  840. DNSLOG_PIP_ADDRESS( dwDnsServerCount, pipDnsServerList );
  841. }
  842. ASYNCREG_F2( " pszDomainName : %s", pszDomainName );
  843. ASYNCREG_F2( " dwTTL : %d", dwTTL );
  844. ASYNCREG_F2( " dwFlags : %d", dwFlags );
  845. ASYNCREG_F1( "" );
  846. ASYNCREG_TIME();
  847. DNSDBG( TRACE, (
  848. "privateAsyncRegisterHostAddrs()\n"
  849. "\tadapter name = %s\n"
  850. "\thost name = %s\n"
  851. "\tadapter domain = %s\n"
  852. "\tpHostAddrs = %p\n"
  853. "\tAddrCount = %d\n"
  854. "\tpDNSServers = %p\n"
  855. "\tServerCount = %d\n"
  856. "\tFlags = %08x\n",
  857. pszAdapterName,
  858. pszHostName,
  859. pszDomainName,
  860. pHostAddrs,
  861. dwHostAddrCount,
  862. pipDnsServerList,
  863. dwDnsServerCount,
  864. dwTTL ));
  865. //
  866. // first things first, need to inform underlying code that something
  867. // has changed in the list of net adapters. Glenn is going to be called
  868. // now so that he can re read the registry (or do any appropriate query)
  869. // to now note the changed state.
  870. //
  871. if ( !(dwFlags & DYNDNS_DEL_ENTRY) )
  872. {
  873. DnsNotifyResolver( 0, NULL );
  874. }
  875. DNS_ASSERT(ASYNC_INIT_CALLED()); // make sure init was called
  876. if ( !ASYNC_INIT_CALLED() )
  877. {
  878. DNSDBG( ANY, (
  879. "ERROR: AsyncRegisterHostAddrs called before Init routine!!!\n" ));
  880. status = ERROR_SERVICE_NOT_ACTIVE;
  881. goto Exit;
  882. }
  883. if ( g_fNoMoreDDNSUpdates )
  884. {
  885. DNSDBG( ANY, (
  886. "ERROR: AsyncRegisterHostAddrs called after RemoveRegistrations()!!!\n" ));
  887. status = ERROR_SERVICE_NOT_ACTIVE;
  888. goto Exit;
  889. }
  890. //
  891. // Validate parameters
  892. //
  893. if ( !pszAdapterName || !(*pszAdapterName) )
  894. {
  895. DNSDBG( ANY, ( "ERROR: RegisterHostAddrs invalid adaptername!\n" ));
  896. status = ERROR_INVALID_PARAMETER;
  897. goto Exit;
  898. }
  899. if ( ( !pszHostName || !(*pszHostName) ) &&
  900. !( dwFlags & DYNDNS_DEL_ENTRY ) )
  901. {
  902. DNSDBG( ANY, ( "ERROR: RegisterHostAddrs invalid hostname!\n" ));
  903. status = ERROR_INVALID_PARAMETER;
  904. goto Exit;
  905. }
  906. if ( dwHostAddrCount && !pHostAddrs )
  907. {
  908. DNSDBG( ANY, ( "ERROR: RegisterHostAddrs invalid host addresses!\n" ));
  909. status = ERROR_INVALID_PARAMETER;
  910. goto Exit;
  911. }
  912. //
  913. // get adapter update configuration
  914. //
  915. status = Reg_ReadUpdateInfo(
  916. pszAdapterName,
  917. & updateInfo );
  918. if ( status != ERROR_SUCCESS )
  919. {
  920. DNSDBG( INIT, (
  921. "Update registry read failure %d\n",
  922. status ));
  923. goto Exit;
  924. }
  925. fcleanupUpdateInfo = TRUE;
  926. //
  927. // skip WAN, if not doing WAN by policy
  928. //
  929. if ( (dwFlags & DYNDNS_REG_RAS) && !g_RegisterWanAdapters )
  930. {
  931. ASYNCREG_F1( "privateAsyncRegisterHostAddrs returning NO_ERROR, because WAN adapter registrations are disabled" );
  932. goto NoActionExit;
  933. }
  934. //
  935. // policy DNS servers, override passed in list
  936. //
  937. if ( updateInfo.pDnsServerArray )
  938. {
  939. pipDnsServerList = updateInfo.pDnsServerArray->AddrArray;
  940. dwDnsServerCount = updateInfo.pDnsServerArray->AddrCount;
  941. }
  942. //
  943. // must have DNS servers to update adapter
  944. // - don't update IP on one interface starting with DNS servers
  945. // from another
  946. //
  947. if ( dwDnsServerCount && !pipDnsServerList )
  948. {
  949. ASYNCREG_F1( "privateAsyncRegisterHostAddrs returning ERROR_INVALID_PARAMETER" );
  950. ASYNCREG_F1( "ERROR_INVALID_PARAMETER reason 4" );
  951. status = ERROR_INVALID_PARAMETER;
  952. goto Exit;
  953. }
  954. if ( ! dwDnsServerCount &&
  955. ! (dwFlags & DYNDNS_DEL_ENTRY) )
  956. {
  957. ASYNCREG_F1( "privateAsyncRegisterHostAddrs returning NO_ERROR, because adapter does not have any DNS servers configured" );
  958. status = ERROR_INVALID_PARAMETER;
  959. goto Exit;
  960. }
  961. //
  962. // no update on adpater => delete outstanding updates
  963. // note, we do before delete check below for event check
  964. //
  965. if ( !updateInfo.fRegistrationEnabled )
  966. {
  967. ASYNCREG_F1( "privateAsyncRegisterHostAddrs returning NO_ERROR, because adapter is disabled" );
  968. if ( pRegisterStatus )
  969. {
  970. pRegisterStatus->dwStatus = NO_ERROR;
  971. SetEvent( pRegisterStatus->hDoneEvent );
  972. }
  973. if ( searchForOldUpdateEntriesAndCleanUp(
  974. pszAdapterName,
  975. NULL,
  976. TRUE ) )
  977. {
  978. goto CheckThread;
  979. }
  980. status = NO_ERROR;
  981. goto Exit;
  982. //goto NoActionExit;
  983. }
  984. //
  985. // delete update -- cleanup and delete
  986. // - delete outstanding update in list
  987. // - cleanup registry
  988. // - do delete
  989. //
  990. if ( dwFlags & DYNDNS_DEL_ENTRY )
  991. {
  992. if ( searchForOldUpdateEntriesAndCleanUp(
  993. pszAdapterName,
  994. NULL,
  995. TRUE ) )
  996. {
  997. goto CheckThread;
  998. }
  999. }
  1000. //
  1001. // limit IP registration count
  1002. // if doing registration and no addresses -- bail
  1003. //
  1004. if ( updateInfo.RegistrationMaxAddressCount < dwHostAddrCount )
  1005. {
  1006. dwHostAddrCount = updateInfo.RegistrationMaxAddressCount;
  1007. ASYNCREG_F2(
  1008. "Restricting adapter registration to the first %d addresses",
  1009. dwHostAddrCount );
  1010. }
  1011. if ( dwHostAddrCount == 0 )
  1012. {
  1013. ASYNCREG_F1( "privateAsyncRegisterHostAddrs returning NO_ERROR" );
  1014. ASYNCREG_F1( "We are done, there are no addresses to register in DNS" );
  1015. goto NoActionExit;
  1016. }
  1017. //
  1018. // no\empty host name or zero IP => bogus
  1019. //
  1020. if ( !pszHostName ||
  1021. !(*pszHostName) ||
  1022. ( dwHostAddrCount && ( pHostAddrs[0].Addr.ipAddr == 0 ) ) )
  1023. {
  1024. ASYNCREG_F1( "privateAsyncRegisterHostAddrs returning ERROR_INVALID_PARAMETER" );
  1025. ASYNCREG_F1( "ERROR_INVALID_PARAMETER reason 5" );
  1026. status = ERROR_INVALID_PARAMETER;
  1027. goto Exit;
  1028. }
  1029. //
  1030. // determine domain names to update
  1031. // - get PDN
  1032. // - adapter name
  1033. // - none if adapter name registration off
  1034. // - else check policy override
  1035. // - else name passed in
  1036. // - but treat empty as NULL
  1037. //
  1038. pprimaryDN = updateInfo.pszPrimaryDomainName;
  1039. if ( updateInfo.fRegisterAdapterName )
  1040. {
  1041. if ( updateInfo.pszAdapterDomainName )
  1042. {
  1043. padapterDN = updateInfo.pszAdapterDomainName;
  1044. }
  1045. else
  1046. {
  1047. padapterDN = pszDomainName;
  1048. }
  1049. if ( padapterDN &&
  1050. !(*padapterDN) )
  1051. {
  1052. padapterDN = NULL;
  1053. }
  1054. }
  1055. //
  1056. // no domains => nothing to register, we're done
  1057. //
  1058. if ( !padapterDN &&
  1059. !pprimaryDN )
  1060. {
  1061. ASYNCREG_F1( "privateAsyncRegisterHostAddrs returning ERROR_SUCCESS" );
  1062. ASYNCREG_F1( "no adapter name and no PDN" );
  1063. goto NoActionExit;
  1064. }
  1065. // if adapter name same as PDN -- just one update
  1066. if ( pprimaryDN &&
  1067. padapterDN &&
  1068. Dns_NameCompare_UTF8( pprimaryDN, padapterDN ) )
  1069. {
  1070. padapterDN = NULL;
  1071. }
  1072. // build update
  1073. status = AllocateUpdateEntry(
  1074. pszAdapterName,
  1075. pszHostName,
  1076. padapterDN,
  1077. pprimaryDN,
  1078. updateInfo.pmszAlternateNames,
  1079. dwHostAddrCount,
  1080. pHostAddrs,
  1081. dwDnsServerCount,
  1082. pipDnsServerList,
  1083. 0, // No particular server IP at this time
  1084. 0, // No particular server IP at this time
  1085. (dwTTL == 0xffffffff || dwTTL == 0)
  1086. ? g_RegistrationTtl
  1087. : dwTTL,
  1088. dwFlags,
  1089. 0,
  1090. Dns_GetCurrentTimeInSeconds(),
  1091. pRegisterStatus,
  1092. &pupEntry );
  1093. if ( status != NO_ERROR )
  1094. {
  1095. goto Exit;
  1096. }
  1097. //
  1098. // More WAN adapter hacks . . .
  1099. // If DDNS is not disabled for WAN adapters, then the default
  1100. // behavior for logging update events is disabled on these type
  1101. // adapters. There is a registry key that can turn on the logging
  1102. // of WAN adapter updates if such a user is interested. We configure
  1103. // those settings here.
  1104. //
  1105. if ( dwFlags & DYNDNS_REG_RAS )
  1106. {
  1107. //pupEntry->fDisableErrorLogging = !g_EnableWanDynamicUpdateEventLog;
  1108. pupEntry->fDisableErrorLogging = TRUE;
  1109. }
  1110. //
  1111. // When adding an entry to the registration list, first walk the
  1112. // list to look for any other updates for the same adapter.
  1113. // If there is already an add update in the list, blow it away.
  1114. // If there is already a delete update in the list with the same
  1115. // information, blow it away.
  1116. //
  1117. // Then put update into registration list.
  1118. //
  1119. searchForOldUpdateEntriesAndCleanUp(
  1120. pupEntry->AdapterName,
  1121. pupEntry,
  1122. FALSE );
  1123. //
  1124. // Since we are about to queue up an update entry for a given
  1125. // adapter, we need to mark any possible previous registration
  1126. // information that could be in the registry as pending. This
  1127. // marking will prevent the old data from being incorrectly
  1128. // queued as a disabled adapter if any errors are encountered
  1129. // on the update attempts. i.e failed update attempts on a given
  1130. // adapter should not be regarded as a disabled adapter that needs
  1131. // to have it's stale records cleaned up.
  1132. //
  1133. MarkAdapterAsPendingUpdate( pszAdapterName );
  1134. EnterCriticalSection( &g_RegistrationListCS );
  1135. InsertTailList( &g_RegistrationList, (PLIST_ENTRY) pupEntry );
  1136. LeaveCriticalSection( &g_RegistrationListCS );
  1137. CheckThread:
  1138. //
  1139. // DCR: do we need cleanup if thread is dead?
  1140. //
  1141. alertOrStartRegistrationThread();
  1142. status = NO_ERROR;
  1143. goto Exit;
  1144. NoActionExit:
  1145. //
  1146. // exit for no-action no-error exit
  1147. //
  1148. DNSDBG( UPDATE, (
  1149. "privateAsyncRegisterHostAddrs()\n"
  1150. "\tno-update no-error exit\n" ));
  1151. status = NO_ERROR;
  1152. if ( pRegisterStatus )
  1153. {
  1154. pRegisterStatus->dwStatus = NO_ERROR;
  1155. SetEvent( pRegisterStatus->hDoneEvent );
  1156. }
  1157. Exit:
  1158. //
  1159. // cleanup allocated update info
  1160. //
  1161. if ( fcleanupUpdateInfo )
  1162. {
  1163. Reg_FreeUpdateInfo(
  1164. &updateInfo,
  1165. FALSE // no free struct, it's on stack
  1166. );
  1167. }
  1168. DNSDBG( UPDATE, (
  1169. "Leaving privateAsyncRegisterHostAddrs()\n"
  1170. "\tstatus = %d\n",
  1171. status ));
  1172. return( status );
  1173. }
  1174. DNS_STATUS
  1175. WINAPI
  1176. DnsAsyncRegisterHostAddrs(
  1177. IN PWSTR pwsAdapterName,
  1178. IN PWSTR pwsHostName,
  1179. IN PREGISTER_HOST_ENTRY pHostAddrs,
  1180. IN DWORD dwHostAddrCount,
  1181. IN PIP_ADDRESS pipDnsServerList,
  1182. IN DWORD dwDnsServerCount,
  1183. IN PWSTR pwsDomainName,
  1184. IN PREGISTER_HOST_STATUS pRegisterStatus,
  1185. IN DWORD dwTTL,
  1186. IN DWORD dwFlags
  1187. )
  1188. /*++
  1189. Routine Description:
  1190. Registers host address with DNS server.
  1191. This is called by DHCP client to register a particular IP.
  1192. Arguments:
  1193. Return Value:
  1194. ERROR_SUCCESS if successful.
  1195. Error code on failure.
  1196. --*/
  1197. {
  1198. CHAR adapterName[2*MAX_PATH];
  1199. CHAR hostName[ DNS_MAX_LABEL_BUFFER_LENGTH ];
  1200. CHAR domainName[ DNS_MAX_NAME_BUFFER_LENGTH ];
  1201. PSTR padapterName = NULL;
  1202. PSTR phostName = NULL;
  1203. PSTR pdomainName = NULL;
  1204. DNSDBG( TRACE, (
  1205. "DnsAsyncRegisterHostAddrs()\n"
  1206. "\tadapter name = %S\n"
  1207. "\thost name = %S\n"
  1208. "\tadapter domain = %S\n"
  1209. "\tpHostAddrs = %p\n",
  1210. pwsAdapterName,
  1211. pwsHostName,
  1212. pwsDomainName,
  1213. pHostAddrs
  1214. ));
  1215. //
  1216. // convert unicode strings to UTF8
  1217. //
  1218. if ( pwsAdapterName )
  1219. {
  1220. Dns_NameCopy(
  1221. adapterName,
  1222. NULL,
  1223. (PCHAR) pwsAdapterName,
  1224. 0,
  1225. DnsCharSetUnicode,
  1226. DnsCharSetUtf8 );
  1227. padapterName = adapterName;
  1228. }
  1229. if ( pwsHostName )
  1230. {
  1231. Dns_NameCopy(
  1232. hostName,
  1233. NULL,
  1234. (PCHAR) pwsHostName,
  1235. 0,
  1236. DnsCharSetUnicode,
  1237. DnsCharSetUtf8 );
  1238. phostName = hostName;
  1239. }
  1240. if ( pwsDomainName )
  1241. {
  1242. Dns_NameCopy(
  1243. domainName,
  1244. NULL,
  1245. (PCHAR) pwsDomainName,
  1246. 0,
  1247. DnsCharSetUnicode,
  1248. DnsCharSetUtf8 );
  1249. pdomainName = domainName;
  1250. }
  1251. return privateAsyncRegisterHostAddrs(
  1252. padapterName,
  1253. phostName,
  1254. pHostAddrs,
  1255. dwHostAddrCount,
  1256. pipDnsServerList,
  1257. dwDnsServerCount,
  1258. pdomainName,
  1259. pRegisterStatus,
  1260. dwTTL,
  1261. dwFlags );
  1262. }
  1263. //
  1264. // Async registration utilities
  1265. //
  1266. PSTR
  1267. CreateNarrowStringCopy(
  1268. IN PSTR pString
  1269. )
  1270. {
  1271. PSTR pnew = NULL;
  1272. if ( pString )
  1273. {
  1274. pnew = HeapAlloc(
  1275. g_DDNSHeap,
  1276. 0,
  1277. strlen(pString) + 1 );
  1278. if ( pnew )
  1279. {
  1280. strcpy( pnew, pString );
  1281. }
  1282. }
  1283. return pnew;
  1284. }
  1285. VOID
  1286. PrivateHeapFree(
  1287. IN PVOID pVal
  1288. )
  1289. {
  1290. if ( pVal )
  1291. {
  1292. HeapFree(
  1293. g_DDNSHeap,
  1294. 0,
  1295. pVal );
  1296. }
  1297. }
  1298. DNS_STATUS
  1299. AllocateUpdateEntry(
  1300. IN PSTR AdapterName,
  1301. IN PSTR HostName,
  1302. IN PSTR DomainName,
  1303. IN PSTR PrimaryDomainName,
  1304. IN PSTR AlternateNames,
  1305. IN DWORD HostAddrCount,
  1306. IN PREGISTER_HOST_ENTRY HostAddrs,
  1307. IN DWORD DnsServerCount,
  1308. IN PIP_ADDRESS DnsServerList,
  1309. IN IP_ADDRESS SentUpdateToIp,
  1310. IN IP_ADDRESS SentPriUpdateToIp,
  1311. IN DWORD TTL,
  1312. IN DWORD Flags,
  1313. IN DWORD RetryCount,
  1314. IN DWORD RetryTime,
  1315. IN PREGISTER_HOST_STATUS Registerstatus,
  1316. OUT PUPDATE_ENTRY * ppUpdateEntry
  1317. )
  1318. /*++
  1319. Routine Description:
  1320. Create update info blob.
  1321. Arguments:
  1322. Return Value:
  1323. ERROR_SUCCESS if successful.
  1324. Error code on failure.
  1325. --*/
  1326. {
  1327. PUPDATE_ENTRY pupEntry = NULL;
  1328. DWORD status = ERROR_SUCCESS;
  1329. PSTR ptempDomain = DomainName;
  1330. PSTR ptempPrimaryDomain = PrimaryDomainName;
  1331. if ( ptempDomain && !(*ptempDomain) )
  1332. {
  1333. ptempDomain = NULL;
  1334. }
  1335. if ( ptempPrimaryDomain && !(*ptempPrimaryDomain) )
  1336. {
  1337. ptempPrimaryDomain = NULL;
  1338. }
  1339. if ( AdapterName && !(*AdapterName) )
  1340. {
  1341. AdapterName = NULL;
  1342. }
  1343. if ( HostName && !(*HostName) )
  1344. {
  1345. HostName = NULL;
  1346. }
  1347. DNSDBG( TRACE, ( "AllocateUpdateEntry()\n" ));
  1348. DNSDBG( DHCP, (
  1349. "AllocateUpdateEntry()\n"
  1350. "\tAdapterName = %s\n"
  1351. "\tHostName = %s\n"
  1352. "\tPrimaryDomain = %s\n"
  1353. "\tAdapterDomain = %s\n"
  1354. "\tAlternateNames = %s\n"
  1355. "\tHostAddrCount = %d\n"
  1356. "\tpHostAddrs = %p\n"
  1357. "\tTTL = %d\n"
  1358. "\tFlags = %08x\n"
  1359. "\tHostAddrCount = %d\n"
  1360. "\tTime = %d\n",
  1361. AdapterName,
  1362. HostName,
  1363. PrimaryDomainName,
  1364. DomainName,
  1365. AlternateNames,
  1366. HostAddrCount,
  1367. HostAddrs,
  1368. TTL,
  1369. Flags,
  1370. RetryTime
  1371. ));
  1372. if ( !AdapterName ||
  1373. !HostName ||
  1374. !HostAddrCount )
  1375. {
  1376. ASYNCREG_F1( "AllocateUpdateEntry returing error : ERROR_INVALID_PARAMETER" );
  1377. ASYNCREG_F1( "" );
  1378. status = ERROR_INVALID_PARAMETER;
  1379. goto Exit;
  1380. }
  1381. pupEntry = PHEAP_ALLOC_ZERO( sizeof(UPDATE_ENTRY) );
  1382. if ( !pupEntry )
  1383. {
  1384. status = DNS_ERROR_NO_MEMORY;
  1385. goto Exit;
  1386. }
  1387. InitializeListHead( &(pupEntry->List) );
  1388. pupEntry->SignatureTop = DNS_SIG_TOP;
  1389. pupEntry->SignatureBottom = DNS_SIG_BOTTOM;
  1390. //
  1391. // copy strings
  1392. //
  1393. pupEntry->AdapterName = CreateNarrowStringCopy( AdapterName );
  1394. if ( !pupEntry->AdapterName )
  1395. {
  1396. status = DNS_ERROR_NO_MEMORY;
  1397. goto Exit;
  1398. }
  1399. if ( HostName )
  1400. {
  1401. pupEntry->HostName = CreateNarrowStringCopy( HostName );
  1402. if ( !pupEntry->HostName )
  1403. {
  1404. status = DNS_ERROR_NO_MEMORY;
  1405. goto Exit;
  1406. }
  1407. }
  1408. if ( ptempDomain )
  1409. {
  1410. pupEntry->DomainName = CreateNarrowStringCopy( ptempDomain );
  1411. if ( !pupEntry->DomainName )
  1412. {
  1413. status = DNS_ERROR_NO_MEMORY;
  1414. goto Exit;
  1415. }
  1416. }
  1417. if ( ptempPrimaryDomain )
  1418. {
  1419. pupEntry->PrimaryDomainName = CreateNarrowStringCopy( ptempPrimaryDomain );
  1420. if ( !pupEntry->PrimaryDomainName )
  1421. {
  1422. status = DNS_ERROR_NO_MEMORY;
  1423. goto Exit;
  1424. }
  1425. }
  1426. if ( AlternateNames )
  1427. {
  1428. pupEntry->AlternateNames = MultiSz_Copy_A( AlternateNames );
  1429. if ( !pupEntry->AlternateNames )
  1430. {
  1431. status = DNS_ERROR_NO_MEMORY;
  1432. goto Exit;
  1433. }
  1434. }
  1435. if ( HostAddrCount )
  1436. {
  1437. pupEntry->HostAddrs = PHEAP_ALLOC( sizeof(REGISTER_HOST_ENTRY) * HostAddrCount );
  1438. if ( !pupEntry->HostAddrs )
  1439. {
  1440. status = DNS_ERROR_NO_MEMORY;
  1441. goto Exit;
  1442. }
  1443. memcpy(
  1444. pupEntry->HostAddrs,
  1445. HostAddrs,
  1446. sizeof(REGISTER_HOST_ENTRY) * HostAddrCount );
  1447. }
  1448. pupEntry->HostAddrCount = HostAddrCount;
  1449. if ( DnsServerCount )
  1450. {
  1451. pupEntry->DnsServerList = Dns_BuildIpArray( DnsServerCount,
  1452. DnsServerList );
  1453. if ( !pupEntry->DnsServerList )
  1454. {
  1455. status = DNS_ERROR_NO_MEMORY;
  1456. goto Exit;
  1457. }
  1458. }
  1459. pupEntry->SentUpdateToIp = SentUpdateToIp;
  1460. pupEntry->SentPriUpdateToIp = SentPriUpdateToIp;
  1461. pupEntry->pRegisterStatus = Registerstatus;
  1462. pupEntry->TTL = TTL;
  1463. pupEntry->Flags = Flags;
  1464. pupEntry->fRemove = Flags & DYNDNS_DEL_ENTRY ? TRUE : FALSE;
  1465. pupEntry->fNewElement = TRUE;
  1466. pupEntry->RetryCount = RetryCount;
  1467. pupEntry->RetryTime = RetryTime;
  1468. Exit:
  1469. if ( status!=ERROR_SUCCESS && pupEntry )
  1470. {
  1471. FreeUpdateEntry( pupEntry );
  1472. pupEntry = NULL;
  1473. }
  1474. *ppUpdateEntry = pupEntry;
  1475. return (status);
  1476. }
  1477. VOID
  1478. FreeUpdateEntry(
  1479. IN OUT PUPDATE_ENTRY pUpdateEntry
  1480. )
  1481. /*++
  1482. Routine Description:
  1483. Free update blob entry.
  1484. Arguments:
  1485. pUpdateEntry -- update entry blob to free
  1486. Return Value:
  1487. None
  1488. --*/
  1489. {
  1490. DNSDBG( TRACE, (
  1491. "FreeUpdateEntry( %p )\n",
  1492. pUpdateEntry ));
  1493. //
  1494. // deep free the update entry
  1495. //
  1496. if ( pUpdateEntry )
  1497. {
  1498. PrivateHeapFree( pUpdateEntry->AdapterName );
  1499. PrivateHeapFree( pUpdateEntry->HostName );
  1500. PrivateHeapFree( pUpdateEntry->DomainName );
  1501. PrivateHeapFree( pUpdateEntry->PrimaryDomainName );
  1502. PrivateHeapFree( pUpdateEntry->AlternateNames );
  1503. PrivateHeapFree( pUpdateEntry->HostAddrs );
  1504. // note that server list is created by Dns_BuildIpArray()
  1505. // (uses dnslib heap) so must free by Dns_Free()
  1506. Dns_Free( pUpdateEntry->DnsServerList );
  1507. PrivateHeapFree( pUpdateEntry );
  1508. }
  1509. }
  1510. VOID
  1511. FreeUpdateEntryList(
  1512. IN OUT PLIST_ENTRY pUpdateEntry
  1513. )
  1514. /*++
  1515. Routine Description:
  1516. Free all updates in update list.
  1517. Arguments:
  1518. pUpdateEntry -- update list head
  1519. Return Value:
  1520. None
  1521. --*/
  1522. {
  1523. PLIST_ENTRY pentry = NULL;
  1524. DNSDBG( TRACE, (
  1525. "FreeUpdateEntryList( %p )\n",
  1526. pUpdateEntry ));
  1527. while ( !IsListEmpty( pUpdateEntry ) )
  1528. {
  1529. pentry = RemoveHeadList( pUpdateEntry );
  1530. if ( pentry )
  1531. {
  1532. FreeUpdateEntry( (PUPDATE_ENTRY) pentry );
  1533. }
  1534. }
  1535. }
  1536. DWORD
  1537. WINAPI
  1538. RegistrationThread(
  1539. VOID
  1540. )
  1541. /*++
  1542. Routine Description:
  1543. Asynchronous registration thread.
  1544. This thread does actual updates, and stays alive until they are
  1545. completed, allowing registration API calls to return.
  1546. This thread is created at boot time as soon as the first register
  1547. request comes in. The thread simply waits for a certain amount of time
  1548. given by boot time or be signaled by DnsAsyncRegisterHostEntries.
  1549. This function collects all the requests and does the appropriate
  1550. aggregation of requests and sends off the modify/add/delete commands
  1551. to the DNS Server. When the call is successful, it makes a note of
  1552. this in the registry
  1553. Arguments:
  1554. None
  1555. Return Value:
  1556. ERROR_SUCCESS if successful.
  1557. ErrorCode on failure.
  1558. --*/
  1559. {
  1560. DWORD waitResult;
  1561. PUPDATE_ENTRY pupEntry = NULL;
  1562. HANDLE handle[2];
  1563. DWORD status = NO_ERROR;
  1564. DWORD dwWaitTime = g_dwBootTime;
  1565. DWORD rcode = 0;
  1566. if ( !g_hKey )
  1567. {
  1568. return(ERROR_INVALID_PARAMETER);
  1569. }
  1570. //
  1571. // Note that this thread is running by setting a global flag
  1572. //
  1573. g_fRegistrationThreadRunning = TRUE;
  1574. //
  1575. // for use at a subsequent WFMO
  1576. //
  1577. handle[0] = g_hStopEvent;
  1578. handle[1] = g_hNewItemEvent;
  1579. //
  1580. // Check to see this thread is at boot time or not.
  1581. // At boot time we simply wait for BOOT_TIME, otherwise move on.
  1582. // The global g_fAtBoot is not protected by critical section because
  1583. // only one thread accesses it at any time.
  1584. //
  1585. if ( !g_fAtBoot || g_fPurgeRegistrations )
  1586. {
  1587. dwWaitTime = 0;
  1588. }
  1589. dwWaitTime *= 1000;
  1590. waitResult = WaitForSingleObject( g_hStopEvent,
  1591. dwWaitTime );
  1592. switch( waitResult )
  1593. {
  1594. case WAIT_OBJECT_0 :
  1595. //
  1596. // kill event
  1597. //
  1598. goto CleanUpAndDie;
  1599. case WAIT_TIMEOUT :
  1600. //
  1601. // Means we can start processing the elements in the queue now
  1602. //
  1603. break;
  1604. }
  1605. //
  1606. // loop through update list, doing any update
  1607. // - do new updates
  1608. // - do retries that have reached retry time
  1609. // - when list empty, terminate thread
  1610. //
  1611. while ( 1 )
  1612. {
  1613. // if empty list and not-booting or purging
  1614. // => get out
  1615. EnterCriticalSection( &g_RegistrationListCS );
  1616. if ( IsListEmpty( &g_RegistrationList ) &&
  1617. ! g_fAtBoot &&
  1618. ! g_fPurgeRegistrations )
  1619. {
  1620. LeaveCriticalSection( &g_RegistrationListCS );
  1621. break;
  1622. }
  1623. //
  1624. // get "updateable" update from list (if any)
  1625. // 0 -- new update, or retry update ready
  1626. // 1 -- retry update, not yet ready
  1627. // -1 -- list empty
  1628. //
  1629. rcode = GetNextUpdateEntryFromList( &pupEntry,
  1630. &dwWaitTime );
  1631. if ( &g_RegistrationList == (PLIST_ENTRY) pupEntry )
  1632. {
  1633. DNS_ASSERT(&g_RegistrationList != (PLIST_ENTRY) pupEntry);
  1634. LeaveCriticalSection( &g_RegistrationListCS );
  1635. goto CleanUpAndDie;
  1636. }
  1637. LeaveCriticalSection( &g_RegistrationListCS );
  1638. //
  1639. // rcode==0 -- new update in list
  1640. //
  1641. // DCR_QUESTION: not clear that this terminates updates in the
  1642. // purging updates case
  1643. //
  1644. if ( rcode == 0 )
  1645. {
  1646. //
  1647. // See if we have been signaled to stop running . . .
  1648. //
  1649. waitResult = WaitForMultipleObjects(
  1650. 2,
  1651. handle,
  1652. FALSE,
  1653. 1 ); // a very small wait
  1654. switch( waitResult )
  1655. {
  1656. case WAIT_OBJECT_0 :
  1657. //
  1658. // kill event
  1659. //
  1660. FreeUpdateEntry( pupEntry );
  1661. goto CleanUpAndDie;
  1662. default :
  1663. //
  1664. // Keep going, process next item in registration list
  1665. //
  1666. break;
  1667. }
  1668. ProcessUpdateEntry( pupEntry, g_fPurgeRegistrations );
  1669. continue;
  1670. }
  1671. //
  1672. // rcode==1 -- update needs retry
  1673. //
  1674. else if ( rcode == 1 &&
  1675. ! g_fAtBoot &&
  1676. ! g_fPurgeRegistrations )
  1677. {
  1678. waitResult = WaitForMultipleObjects(
  1679. 2,
  1680. handle,
  1681. FALSE,
  1682. dwWaitTime );
  1683. switch( waitResult )
  1684. {
  1685. case WAIT_OBJECT_0 :
  1686. //
  1687. // kill event
  1688. //
  1689. goto CleanUpAndDie;
  1690. case WAIT_OBJECT_0 + 1 :
  1691. //
  1692. // new item has been added to registration list
  1693. //
  1694. break;
  1695. case WAIT_TIMEOUT :
  1696. //
  1697. // process next item in registration list
  1698. //
  1699. break;
  1700. }
  1701. continue;
  1702. }
  1703. //
  1704. // rcode == (-1) -- list empty
  1705. // OR
  1706. // rcode == (1) -- reties, not booting or purging
  1707. //
  1708. else
  1709. {
  1710. if ( !g_fAtBoot && !g_fPurgeRegistrations )
  1711. {
  1712. goto CleanUpAndDie;
  1713. }
  1714. if ( g_fPurgeRegistrationsInitiated )
  1715. {
  1716. goto CleanUpAndDie;
  1717. }
  1718. if ( g_fPurgeRegistrations )
  1719. {
  1720. ResetAdaptersInRegistry();
  1721. }
  1722. //
  1723. // Remove any adapter configurations from the registry
  1724. // that were not processed. Do this by attempting to
  1725. // remove the related DNS records from the DNS server(s).
  1726. //
  1727. DeregisterUnusedAdapterInRegistry( g_fPurgeRegistrations );
  1728. if ( g_fPurgeRegistrations )
  1729. {
  1730. g_fPurgeRegistrationsInitiated = TRUE;
  1731. }
  1732. g_fAtBoot = FALSE;
  1733. continue;
  1734. }
  1735. }
  1736. CleanUpAndDie :
  1737. ASYNCREG_F1( "RegistrationThread - terminating" );
  1738. ASYNCREG_F1( "" );
  1739. EnterCriticalSection( &g_RegistrationThreadCS );
  1740. EnterCriticalSection( &g_RegistrationListCS );
  1741. g_fQuit = TRUE;
  1742. g_fAtBoot = FALSE;
  1743. g_fPurgeRegistrations = FALSE;
  1744. g_fPurgeRegistrationsInitiated = FALSE;
  1745. //
  1746. // Blow away the registration list
  1747. //
  1748. FreeUpdateEntryList( &g_RegistrationList );
  1749. InitializeListHead( &g_RegistrationList );
  1750. LeaveCriticalSection( &g_RegistrationListCS );
  1751. //
  1752. // Blow away any cached security handles
  1753. //
  1754. Dns_TimeoutSecurityContextList( TRUE );
  1755. //
  1756. // Close the thread handle.
  1757. //
  1758. if ( g_hRegistrationThread )
  1759. {
  1760. CloseHandle( g_hRegistrationThread );
  1761. g_hRegistrationThread = NULL;
  1762. }
  1763. //
  1764. // Note that this thread is NOT running by setting a global flag
  1765. //
  1766. g_fRegistrationThreadRunning = FALSE;
  1767. //
  1768. // Now signal that we've finished
  1769. //
  1770. ASYNCREG_F1( "RegistrationThread - Signaling ThreadDeadEvent" );
  1771. ASYNCREG_F1( "" );
  1772. // clear purge incase of later restart
  1773. //g_fPurgeRegistrations = FALSE;
  1774. // currently must go through Init routine which clears this flag
  1775. SetEvent( g_hThreadDeadEvent );
  1776. LeaveCriticalSection( &g_RegistrationThreadCS );
  1777. ASYNCREG_F1( "RegistrationThread - Finished" );
  1778. ASYNCREG_F1( "" );
  1779. return NO_ERROR;
  1780. }
  1781. VOID
  1782. WriteUpdateEntryToRegistry(
  1783. IN PUPDATE_ENTRY pUpdateEntry
  1784. )
  1785. {
  1786. HKEY hAdapterKey = NULL;
  1787. DWORD disposition;
  1788. DWORD status = ERROR_SUCCESS;
  1789. DWORD dwRegistered = 0;
  1790. DWORD dwFlags = 0;
  1791. WCHAR uName[ DNS_MAX_NAME_BUFFER_LENGTH ];
  1792. ASYNCREG_UPDATE_ENTRY(
  1793. "Inside function WriteUpdateEntryToRegistry",
  1794. pUpdateEntry );
  1795. DNSDBG( TRACE, (
  1796. "WriteUpdateEntryToRegistry( %p )\n",
  1797. pUpdateEntry ));
  1798. //
  1799. // write only add update
  1800. //
  1801. // remove's should not be non-volatile as don't know anything
  1802. // about state when come back up
  1803. //
  1804. if ( !pUpdateEntry->fRemove )
  1805. {
  1806. if ( pUpdateEntry->fRegisteredFWD )
  1807. {
  1808. dwFlags |= REGISTERED_FORWARD;
  1809. }
  1810. if ( pUpdateEntry->fRegisteredPRI )
  1811. {
  1812. dwFlags |= REGISTERED_PRIMARY;
  1813. }
  1814. if ( pUpdateEntry->fRegisteredPTR )
  1815. {
  1816. dwFlags |= REGISTERED_POINTER;
  1817. }
  1818. if ( dwFlags )
  1819. {
  1820. dwRegistered = 1;
  1821. }
  1822. status = RegCreateKeyExA ( g_hKey,
  1823. pUpdateEntry->AdapterName,
  1824. 0,
  1825. ADAPTER_NAME_CLASS,
  1826. REG_OPTION_NON_VOLATILE, // options
  1827. KEY_READ | KEY_WRITE, // desired access
  1828. NULL,
  1829. &hAdapterKey,
  1830. &disposition );
  1831. if ( status )
  1832. {
  1833. goto Exit;
  1834. }
  1835. Dns_Utf8ToUnicode( pUpdateEntry->HostName,
  1836. strlen( pUpdateEntry->HostName ),
  1837. uName,
  1838. 256 );
  1839. status = RegSetValueExW( hAdapterKey,
  1840. REGISTERED_HOST_NAME_W,
  1841. 0,
  1842. REG_SZ,
  1843. (LPBYTE)uName,
  1844. ( wcslen( uName )
  1845. + 1 ) * sizeof(WCHAR) );
  1846. if ( status )
  1847. {
  1848. goto Exit;
  1849. }
  1850. if ( pUpdateEntry->DomainName &&
  1851. pUpdateEntry->fRegisteredFWD )
  1852. {
  1853. Dns_Utf8ToUnicode( pUpdateEntry->DomainName,
  1854. strlen( pUpdateEntry->DomainName ),
  1855. uName,
  1856. 256 );
  1857. status = RegSetValueExW( hAdapterKey,
  1858. REGISTERED_DOMAIN_NAME_W,
  1859. 0,
  1860. REG_SZ,
  1861. (LPBYTE)uName,
  1862. ( wcslen( uName )
  1863. + 1 ) * sizeof(WCHAR) );
  1864. if ( status )
  1865. {
  1866. goto Exit;
  1867. }
  1868. }
  1869. else
  1870. {
  1871. status = RegSetValueExA( hAdapterKey,
  1872. REGISTERED_DOMAIN_NAME,
  1873. 0,
  1874. REG_SZ,
  1875. (LPBYTE)"",
  1876. ( strlen( "" )
  1877. + 1 ) * sizeof(CHAR) );
  1878. if ( status )
  1879. {
  1880. goto Exit;
  1881. }
  1882. }
  1883. if ( pUpdateEntry->PrimaryDomainName &&
  1884. pUpdateEntry->fRegisteredPRI )
  1885. {
  1886. Dns_Utf8ToUnicode( pUpdateEntry->PrimaryDomainName,
  1887. strlen( pUpdateEntry->PrimaryDomainName ),
  1888. uName,
  1889. 256 );
  1890. status = RegSetValueExW( hAdapterKey,
  1891. PRIMARY_DOMAIN_NAME,
  1892. 0,
  1893. REG_SZ,
  1894. (LPBYTE)uName,
  1895. ( wcslen( uName )
  1896. + 1 ) * sizeof(WCHAR) );
  1897. if ( status )
  1898. {
  1899. goto Exit;
  1900. }
  1901. }
  1902. else
  1903. {
  1904. status = RegSetValueExA( hAdapterKey,
  1905. PRIMARY_DOMAIN_NAME_A,
  1906. 0,
  1907. REG_SZ,
  1908. (LPBYTE)"",
  1909. ( strlen( "" )
  1910. + 1 ) * sizeof(CHAR) );
  1911. if ( status )
  1912. {
  1913. goto Exit;
  1914. }
  1915. }
  1916. RegSetValueExA( hAdapterKey,
  1917. SENT_UPDATE_TO_IP,
  1918. 0,
  1919. REG_DWORD,
  1920. (LPBYTE)&pUpdateEntry->SentUpdateToIp,
  1921. sizeof(DWORD) );
  1922. RegSetValueExA( hAdapterKey,
  1923. SENT_PRI_UPDATE_TO_IP,
  1924. 0,
  1925. REG_DWORD,
  1926. (LPBYTE)&pUpdateEntry->SentPriUpdateToIp,
  1927. sizeof(DWORD) );
  1928. RegSetValueExA( hAdapterKey,
  1929. REGISTERED_TTL,
  1930. 0,
  1931. REG_DWORD,
  1932. (LPBYTE)&pUpdateEntry->TTL,
  1933. sizeof(DWORD) );
  1934. RegSetValueExA( hAdapterKey,
  1935. FLAGS,
  1936. 0,
  1937. REG_DWORD,
  1938. (LPBYTE)&dwFlags,
  1939. sizeof(DWORD) );
  1940. //
  1941. // ignore error on the last two. Non critical
  1942. //
  1943. status = RegSetValueExA( hAdapterKey,
  1944. REGISTERED_ADDRS,
  1945. 0,
  1946. REG_BINARY,
  1947. (LPBYTE) pUpdateEntry->HostAddrs,
  1948. pUpdateEntry->HostAddrCount *
  1949. sizeof(REGISTER_HOST_ENTRY) );
  1950. if ( status )
  1951. {
  1952. goto Exit;
  1953. }
  1954. status = RegSetValueExA( hAdapterKey,
  1955. REGISTERED_ADDRS_COUNT,
  1956. 0,
  1957. REG_DWORD,
  1958. (LPBYTE)&pUpdateEntry->HostAddrCount,
  1959. sizeof(DWORD) );
  1960. if ( status )
  1961. {
  1962. goto Exit;
  1963. }
  1964. status = RegSetValueExA( hAdapterKey,
  1965. REGISTERED_SINCE_BOOT,
  1966. 0,
  1967. REG_DWORD,
  1968. (LPBYTE)&dwRegistered,
  1969. sizeof(DWORD) );
  1970. if ( status )
  1971. {
  1972. goto Exit;
  1973. }
  1974. if ( pUpdateEntry->DnsServerList )
  1975. {
  1976. status = RegSetValueExA( hAdapterKey,
  1977. DNS_SERVER_ADDRS,
  1978. 0,
  1979. REG_BINARY,
  1980. (LPBYTE) pUpdateEntry ->
  1981. DnsServerList ->
  1982. AddrArray,
  1983. pUpdateEntry ->
  1984. DnsServerList ->
  1985. AddrCount *
  1986. sizeof(IP_ADDRESS) );
  1987. if ( status )
  1988. {
  1989. goto Exit;
  1990. }
  1991. status = RegSetValueExA( hAdapterKey,
  1992. DNS_SERVER_ADDRS_COUNT,
  1993. 0,
  1994. REG_DWORD,
  1995. (LPBYTE) &pUpdateEntry ->
  1996. DnsServerList ->
  1997. AddrCount,
  1998. sizeof(DWORD) );
  1999. if ( status )
  2000. {
  2001. goto Exit;
  2002. }
  2003. }
  2004. else
  2005. {
  2006. DWORD count = 0;
  2007. status = RegSetValueExA( hAdapterKey,
  2008. DNS_SERVER_ADDRS_COUNT,
  2009. 0,
  2010. REG_DWORD,
  2011. (LPBYTE) &count,
  2012. sizeof(DWORD) );
  2013. if ( status )
  2014. {
  2015. goto Exit;
  2016. }
  2017. status = RegSetValueExA( hAdapterKey,
  2018. DNS_SERVER_ADDRS,
  2019. 0,
  2020. REG_BINARY,
  2021. (LPBYTE) NULL,
  2022. 0 );
  2023. if ( status )
  2024. {
  2025. goto Exit;
  2026. }
  2027. }
  2028. RegCloseKey( hAdapterKey );
  2029. return;
  2030. }
  2031. Exit:
  2032. //
  2033. // remove or failure -- kill adapter key
  2034. //
  2035. RegDeleteKey( g_hKey, pUpdateEntry->AdapterName );
  2036. if ( hAdapterKey )
  2037. {
  2038. RegCloseKey( hAdapterKey );
  2039. }
  2040. }
  2041. PUPDATE_ENTRY
  2042. ReadUpdateEntryFromRegistry(
  2043. IN PSTR AdapterName
  2044. )
  2045. {
  2046. PREGISTER_HOST_ENTRY pHostAddrs = NULL;
  2047. PUPDATE_ENTRY pupEntry = NULL;
  2048. DWORD status = NO_ERROR;
  2049. PSTR pregHostName = NULL;
  2050. PSTR pregDomain = NULL;
  2051. PSTR pregPrimary = NULL;
  2052. IP_ADDRESS ipSentUpdateTo = 0;
  2053. IP_ADDRESS ipSentPriUpdateTo = 0;
  2054. DWORD dwTTL = 0;
  2055. DWORD dwFlags = 0;
  2056. DWORD dwHostAddrCount = 0;
  2057. DWORD dwServerAddrCount = 0;
  2058. PIP_ADDRESS pServerList = NULL;
  2059. PSTR pdomain;
  2060. PSTR pprimary;
  2061. HKEY hAdapterKey = NULL;
  2062. DWORD dwType;
  2063. DWORD dwBytesRead = MAX_PATH -1;
  2064. DWORD dwBufferSize = 2048;
  2065. BOOL fRegFWD = FALSE;
  2066. BOOL fRegPRI = FALSE;
  2067. BOOL fRegPTR = FALSE;
  2068. DNSDBG( TRACE, (
  2069. "ReadUpdateEntryFromRegistry( %s )\n",
  2070. AdapterName ));
  2071. //
  2072. // implementation note
  2073. //
  2074. // two different heaps here
  2075. // - g_DDNSHeap specific for this module
  2076. // - general DnsApi heap which all the stuff which is
  2077. // allocated by GetRegistryValue() is using
  2078. //
  2079. // GetRegistryValue() uses ALLOCATE_HEAP() (general dnsapi heap)
  2080. // so all the stuff it creates must be freed by FREE_HEAP()
  2081. //
  2082. pHostAddrs = (PREGISTER_HOST_ENTRY) PHEAP_ALLOC( dwBufferSize );
  2083. if ( !pHostAddrs )
  2084. {
  2085. goto Exit;
  2086. }
  2087. pServerList = (PIP_ADDRESS) PHEAP_ALLOC( dwBufferSize );
  2088. if ( !pServerList )
  2089. {
  2090. goto Exit;
  2091. }
  2092. status = RegOpenKeyEx(
  2093. g_hKey,
  2094. AdapterName,
  2095. 0,
  2096. KEY_ALL_ACCESS,
  2097. &hAdapterKey );
  2098. if ( status )
  2099. {
  2100. hAdapterKey = NULL;
  2101. goto Exit;
  2102. }
  2103. //
  2104. // read each value in turn
  2105. //
  2106. // note that registry flags are not the API flags but the
  2107. // flags denoting successful registration
  2108. status = GetRegistryValue(
  2109. hAdapterKey,
  2110. FLAGS,
  2111. REG_DWORD,
  2112. (PBYTE)&dwFlags );
  2113. if ( status )
  2114. {
  2115. goto Exit;
  2116. }
  2117. fRegPRI = !!( dwFlags & REGISTERED_PRIMARY );
  2118. fRegFWD = !!( dwFlags & REGISTERED_FORWARD );
  2119. fRegPTR = !!( dwFlags & REGISTERED_POINTER );
  2120. status = GetRegistryValue(
  2121. hAdapterKey,
  2122. REGISTERED_HOST_NAME,
  2123. REG_SZ,
  2124. (PBYTE)&pregHostName );
  2125. if ( status )
  2126. {
  2127. goto Exit;
  2128. }
  2129. if ( fRegPRI )
  2130. {
  2131. status = GetRegistryValue(
  2132. hAdapterKey,
  2133. PRIMARY_DOMAIN_NAME_A,
  2134. REG_SZ,
  2135. (LPBYTE)&pregPrimary );
  2136. if ( status )
  2137. {
  2138. goto Exit;
  2139. }
  2140. }
  2141. if ( fRegFWD )
  2142. {
  2143. status = GetRegistryValue(
  2144. hAdapterKey,
  2145. REGISTERED_DOMAIN_NAME,
  2146. REG_SZ,
  2147. (LPBYTE)&pregDomain );
  2148. if ( status )
  2149. {
  2150. goto Exit;
  2151. }
  2152. }
  2153. status = GetRegistryValue(
  2154. hAdapterKey,
  2155. SENT_UPDATE_TO_IP,
  2156. REG_DWORD,
  2157. (LPBYTE)&ipSentUpdateTo );
  2158. if ( status )
  2159. {
  2160. goto Exit;
  2161. }
  2162. status = GetRegistryValue(
  2163. hAdapterKey,
  2164. SENT_PRI_UPDATE_TO_IP,
  2165. REG_DWORD,
  2166. (LPBYTE)&ipSentPriUpdateTo );
  2167. if ( status )
  2168. {
  2169. goto Exit;
  2170. }
  2171. status = GetRegistryValue(
  2172. hAdapterKey,
  2173. REGISTERED_TTL,
  2174. REG_DWORD,
  2175. (LPBYTE)&dwTTL );
  2176. if ( status )
  2177. {
  2178. goto Exit;
  2179. }
  2180. status = GetRegistryValue(
  2181. hAdapterKey,
  2182. REGISTERED_ADDRS_COUNT,
  2183. REG_DWORD,
  2184. (LPBYTE)&dwHostAddrCount );
  2185. if ( status )
  2186. {
  2187. goto Exit;
  2188. }
  2189. dwBytesRead = dwBufferSize;
  2190. status = RegQueryValueEx(
  2191. hAdapterKey,
  2192. REGISTERED_ADDRS,
  2193. 0,
  2194. &dwType,
  2195. (LPBYTE)pHostAddrs,
  2196. &dwBytesRead );
  2197. if( status == ERROR_MORE_DATA )
  2198. {
  2199. PrivateHeapFree( pHostAddrs );
  2200. pHostAddrs = (PREGISTER_HOST_ENTRY) PHEAP_ALLOC( dwBytesRead );
  2201. if ( !pHostAddrs )
  2202. {
  2203. goto Exit;
  2204. }
  2205. status = RegQueryValueEx(
  2206. hAdapterKey,
  2207. REGISTERED_ADDRS,
  2208. 0,
  2209. &dwType,
  2210. (LPBYTE)pHostAddrs,
  2211. &dwBytesRead );
  2212. }
  2213. if ( status )
  2214. {
  2215. goto Exit;
  2216. }
  2217. if ( dwBytesRead/sizeof(REGISTER_HOST_ENTRY) < dwHostAddrCount )
  2218. {
  2219. goto Exit;
  2220. }
  2221. status = GetRegistryValue(
  2222. hAdapterKey,
  2223. DNS_SERVER_ADDRS_COUNT,
  2224. REG_DWORD,
  2225. (LPBYTE)&dwServerAddrCount );
  2226. if ( status )
  2227. {
  2228. dwServerAddrCount = 0;
  2229. }
  2230. if ( dwServerAddrCount )
  2231. {
  2232. dwBytesRead = dwBufferSize;
  2233. status = RegQueryValueEx(
  2234. hAdapterKey,
  2235. DNS_SERVER_ADDRS,
  2236. 0,
  2237. &dwType,
  2238. (LPBYTE)pServerList,
  2239. &dwBytesRead );
  2240. if ( status == ERROR_MORE_DATA )
  2241. {
  2242. PHEAP_FREE( pServerList );
  2243. pServerList = (PIP_ADDRESS) PHEAP_ALLOC( dwBytesRead );
  2244. if ( !pServerList )
  2245. {
  2246. goto Exit;
  2247. }
  2248. status = RegQueryValueEx(
  2249. hAdapterKey,
  2250. DNS_SERVER_ADDRS,
  2251. 0,
  2252. &dwType,
  2253. (LPBYTE)pServerList,
  2254. &dwBytesRead );
  2255. }
  2256. if ( status )
  2257. {
  2258. goto Exit;
  2259. }
  2260. if ( dwBytesRead/sizeof(IP_ADDRESS) < dwServerAddrCount )
  2261. {
  2262. goto Exit;
  2263. }
  2264. }
  2265. else
  2266. {
  2267. pServerList = NULL;
  2268. }
  2269. //
  2270. // validate domain names non-empty
  2271. //
  2272. pdomain = pregDomain;
  2273. if ( pdomain &&
  2274. strlen( pdomain ) == 0 )
  2275. {
  2276. pdomain = NULL;
  2277. }
  2278. pprimary = pregPrimary;
  2279. if ( pprimary &&
  2280. strlen( pprimary ) == 0 )
  2281. {
  2282. pprimary = NULL;
  2283. }
  2284. status = AllocateUpdateEntry(
  2285. AdapterName,
  2286. pregHostName,
  2287. pdomain,
  2288. pprimary,
  2289. NULL, // no alternate names
  2290. dwHostAddrCount,
  2291. pHostAddrs,
  2292. dwServerAddrCount,
  2293. pServerList,
  2294. ipSentUpdateTo,
  2295. ipSentPriUpdateTo,
  2296. dwTTL,
  2297. ( fRegPTR ) ? DYNDNS_REG_PTR : 0,
  2298. 0,
  2299. Dns_GetCurrentTimeInSeconds(),
  2300. NULL,
  2301. &pupEntry );
  2302. if ( status )
  2303. {
  2304. DNS_ASSERT( pupEntry == NULL );
  2305. pupEntry = NULL;
  2306. goto Exit;
  2307. }
  2308. pupEntry->fFromRegistry = TRUE;
  2309. pupEntry->fRegisteredFWD = fRegFWD;
  2310. pupEntry->fRegisteredPRI = fRegPRI;
  2311. pupEntry->fRegisteredPTR = fRegPTR;
  2312. Exit:
  2313. //
  2314. // cleanup
  2315. // - close registry
  2316. // - dump local data
  2317. //
  2318. if ( hAdapterKey )
  2319. {
  2320. RegCloseKey( hAdapterKey );
  2321. }
  2322. PrivateHeapFree( pHostAddrs );
  2323. PrivateHeapFree( pServerList );
  2324. FREE_HEAP( pregHostName );
  2325. FREE_HEAP( pregDomain );
  2326. FREE_HEAP( pregPrimary );
  2327. // set return value
  2328. ASYNCREG_UPDATE_ENTRY(
  2329. "Leaving ReadUpdateEntryFromRegistry:",
  2330. pupEntry );
  2331. IF_DNSDBG( TRACE )
  2332. {
  2333. DnsDbg_UpdateEntry(
  2334. "Leave ReadUpdateEntryFromRegistry():",
  2335. pupEntry );
  2336. }
  2337. return pupEntry;
  2338. }
  2339. VOID
  2340. MarkAdapterAsPendingUpdate(
  2341. IN PSTR AdapterName
  2342. )
  2343. {
  2344. DWORD status = NO_ERROR;
  2345. DWORD dwRegistered = 1;
  2346. HKEY hAdapterKey = NULL;
  2347. DNSDBG( TRACE, (
  2348. "MarkAdapterAsPendingUpdate( %s )\n",
  2349. AdapterName ));
  2350. status = RegOpenKeyEx(
  2351. g_hKey,
  2352. AdapterName,
  2353. 0,
  2354. KEY_ALL_ACCESS,
  2355. &hAdapterKey );
  2356. if ( status )
  2357. {
  2358. return;
  2359. }
  2360. RegSetValueExA(
  2361. hAdapterKey,
  2362. REGISTERED_SINCE_BOOT,
  2363. 0,
  2364. REG_DWORD,
  2365. (LPBYTE) &dwRegistered,
  2366. sizeof(DWORD) );
  2367. RegCloseKey( hAdapterKey );
  2368. }
  2369. DWORD
  2370. GetNextUpdateEntryFromList(
  2371. OUT PUPDATE_ENTRY * ppUpdateEntry,
  2372. OUT PDWORD pdwWaitTime
  2373. )
  2374. /*++
  2375. Routine Description:
  2376. Dequeue update entry from update list.
  2377. //
  2378. // If a new entry is found, set ppUpdateEntry to point
  2379. // to it and return 0 (prefering deletes over adds).
  2380. //
  2381. // If there are only retry entries in the list, and one or more
  2382. // have reached their retry time interval, then set ppUpdateEntry
  2383. // to point to the one with the least retry time and return 0.
  2384. //
  2385. // If there are only retry entries in the list, but none have
  2386. // yet reached there retry time interval then set pdwWaitTime to
  2387. // the time remaining to wait for the entry with the least retry
  2388. // interval and return 1 (WAIT)
  2389. //
  2390. // If there are no more records in list, return (-1)
  2391. //
  2392. Arguments:
  2393. Return Value:
  2394. (0) -- returning entry in ppUpdateEntry
  2395. - new entry if found
  2396. - retry which is past its retry time
  2397. (1) -- list has only retries which have NOT reached retry time
  2398. - set pdwWaitTime to remaining time to first retry
  2399. (-1) -- list is empty
  2400. --*/
  2401. {
  2402. PLIST_ENTRY pentry;
  2403. PLIST_ENTRY plistHead;
  2404. PLIST_ENTRY pleastWaitEntry = NULL;
  2405. DWORD minWaitTime = 0xffffffff;
  2406. INT waitTime;
  2407. ASYNCREG_F1( "Inside function GetNextUpdateEntryFromList" );
  2408. DNSDBG( TRACE, ( "GetNextUpdateEntryFromList()" ));
  2409. if ( IsListEmpty( &g_RegistrationList ) )
  2410. {
  2411. *ppUpdateEntry = NULL;
  2412. *pdwWaitTime = 0;
  2413. ASYNCREG_F1( "GetNextUpdateEntryFromList - returning (NO_MORE_RECORDS)" );
  2414. ASYNCREG_F1( "" );
  2415. return(-1);
  2416. }
  2417. //
  2418. // Loop through list looking for a new delete related update entry.
  2419. // If so, remove it from list and return it.
  2420. //
  2421. plistHead = &g_RegistrationList;
  2422. pentry = plistHead->Flink;
  2423. while ( pentry != plistHead )
  2424. {
  2425. if ( ((PUPDATE_ENTRY) pentry)->fRemove &&
  2426. ((PUPDATE_ENTRY) pentry)->fNewElement )
  2427. {
  2428. RemoveEntryList( pentry );
  2429. *ppUpdateEntry = (PUPDATE_ENTRY) pentry;
  2430. *pdwWaitTime = 0;
  2431. ASYNCREG_F1( "GetNextUpdateEntryFromList - returning new remove entry (SUCCESS)" );
  2432. ASYNCREG_F1( "" );
  2433. return 0;
  2434. }
  2435. else
  2436. {
  2437. pentry = pentry->Flink;
  2438. }
  2439. }
  2440. //
  2441. // Now loop through list looking for any new update.
  2442. // If so, remove it from list and return it.
  2443. //
  2444. plistHead = &g_RegistrationList;
  2445. pentry = plistHead->Flink;
  2446. while ( pentry != plistHead )
  2447. {
  2448. if ( ((PUPDATE_ENTRY) pentry)->fNewElement )
  2449. {
  2450. RemoveEntryList( pentry );
  2451. *ppUpdateEntry = (PUPDATE_ENTRY) pentry;
  2452. *pdwWaitTime = 0;
  2453. ASYNCREG_F1( "GetNextUpdateEntryFromList - returning new entry (SUCCESS)" );
  2454. ASYNCREG_F1( "" );
  2455. return 0;
  2456. }
  2457. else
  2458. {
  2459. pentry = pentry->Flink;
  2460. }
  2461. }
  2462. //
  2463. // There are no new update entries to process, now need to
  2464. // loop through list looking for the next possible update to
  2465. // wait on. If wait time has expired return it, otherwise
  2466. // set pdwWaitTime to time remaining and return 1.
  2467. //
  2468. plistHead = &g_RegistrationList;
  2469. pentry = plistHead->Flink;
  2470. while ( pentry != plistHead )
  2471. {
  2472. if ( ((PUPDATE_ENTRY) pentry)->RetryTime <
  2473. minWaitTime )
  2474. {
  2475. minWaitTime = ((PUPDATE_ENTRY) pentry)->RetryTime;
  2476. pleastWaitEntry = pentry;
  2477. }
  2478. pentry = pentry->Flink;
  2479. }
  2480. waitTime = (INT) ( minWaitTime - Dns_GetCurrentTimeInSeconds() );
  2481. if ( waitTime > 0 )
  2482. {
  2483. waitTime *= 1000;
  2484. *ppUpdateEntry = NULL;
  2485. *pdwWaitTime = (DWORD) waitTime;
  2486. ASYNCREG_F1( "GetNextUpdateEntryFromList - returning (WAIT)" );
  2487. ASYNCREG_F1( "" );
  2488. return 1;
  2489. }
  2490. else
  2491. {
  2492. RemoveEntryList( pleastWaitEntry );
  2493. *ppUpdateEntry = (PUPDATE_ENTRY) pleastWaitEntry;
  2494. *pdwWaitTime = 0;
  2495. ASYNCREG_F1( "GetNextUpdateEntryFromList - returning wait entry (SUCCESS)" );
  2496. ASYNCREG_F1( "" );
  2497. return 0;
  2498. }
  2499. }
  2500. //
  2501. // Update entry processing
  2502. //
  2503. DNS_STATUS
  2504. DoRemoveUpdate(
  2505. IN OUT PUPDATE_ENTRY pRemoveEntry,
  2506. IN OUT PDNS_RECORD pRemoveRecord,
  2507. IN UPTYPE UpType
  2508. )
  2509. /*++
  2510. Routine Description:
  2511. Do a remove update.
  2512. Helper routine for DoUpdate().
  2513. Routine simply avoids duplicate code as this is called
  2514. with both registry entry and with update entry.
  2515. Arguments:
  2516. pRemoveEntry -- entry to remove, from update or registry
  2517. pRemoveRecord -- record to remove
  2518. fPrimary -- TRUE for primary update; FALSE otherwise
  2519. Return Value:
  2520. DNS or Win32 error code.
  2521. --*/
  2522. {
  2523. DNS_STATUS status = NO_ERROR;
  2524. DNSDBG( TRACE, (
  2525. "DoRemoveUpdate( %p, %p, %d )\n",
  2526. pRemoveEntry,
  2527. pRemoveRecord,
  2528. UpType
  2529. ));
  2530. //
  2531. // try remove
  2532. // - don't track failure, this is a one shot deal before
  2533. // adapter goes down
  2534. //
  2535. status = DnsModifyRecordsInSet_UTF8(
  2536. NULL, // no add records
  2537. pRemoveRecord, // delete records
  2538. DNS_UPDATE_CACHE_SECURITY_CONTEXT,
  2539. NULL, // no context handle
  2540. (PIP4_ARRAY) pRemoveEntry->DnsServerList,
  2541. NULL // reserved
  2542. );
  2543. SetUpdateStatus(
  2544. pRemoveEntry,
  2545. status,
  2546. UpType );
  2547. if ( IS_UPTYPE_PRIMARY(UpType) )
  2548. {
  2549. LogRegistration(
  2550. pRemoveEntry,
  2551. status,
  2552. UpType,
  2553. TRUE, // deregistration
  2554. 0, // default server IP
  2555. 0 // default update IP
  2556. );
  2557. }
  2558. #if 0
  2559. // doing entire update entry PTR dereg at once
  2560. // in ProcessUpdate() once done
  2561. //
  2562. // deregister the PTR records
  2563. //
  2564. if ( (pRemoveEntry->Flags & DYNDNS_REG_PTR) &&
  2565. g_RegisterReverseLookup )
  2566. {
  2567. UpdatePtrRecords(
  2568. pRemoveEntry,
  2569. FALSE // remove records
  2570. );
  2571. }
  2572. #endif
  2573. return status;
  2574. }
  2575. DNS_STATUS
  2576. ModifyAdapterRegistration(
  2577. IN PUPDATE_ENTRY pUpdateEntry,
  2578. IN PUPDATE_ENTRY pRegistryEntry,
  2579. IN PDNS_RECORD pUpdateRecord,
  2580. IN PDNS_RECORD pRegRecord,
  2581. IN BOOL fPrimaryDomain
  2582. )
  2583. {
  2584. DNS_STATUS status = NO_ERROR;
  2585. PDNS_RECORD potherRecords = NULL;
  2586. PDNS_RECORD pNewUpdateRecord = NULL;
  2587. PDNS_RECORD pNewRegRecord = NULL;
  2588. IP_ADDRESS serverIp = 0;
  2589. DNSDBG( TRACE, (
  2590. "ModifyAdapterRegistration()\n"
  2591. "\tpUpdateEntry = %p\n"
  2592. "\tpUpdateRecords = %p\n"
  2593. "\tpRegistryEntry = %p\n"
  2594. "\tpRegistryRecords = %p\n"
  2595. "\tfPrimary = %d\n",
  2596. pUpdateEntry,
  2597. pRegistryEntry,
  2598. pUpdateRecord,
  2599. pRegRecord,
  2600. fPrimaryDomain ));
  2601. //
  2602. // multi-adapter registration test
  2603. //
  2604. // check other adapters for registrations on the same name
  2605. // if found, include in updates
  2606. //
  2607. potherRecords = GetPreviousRegistrationInformation(
  2608. pUpdateEntry,
  2609. fPrimaryDomain,
  2610. &serverIp );
  2611. if ( potherRecords )
  2612. {
  2613. IP_ARRAY ipArray;
  2614. DNSDBG( DHCP, (
  2615. "Have registry update data for other adapters!\n"
  2616. "\tCreating combined update record sets.\n" ));
  2617. ipArray.AddrCount = 1;
  2618. ipArray.AddrArray[0] = serverIp;
  2619. pNewUpdateRecord = CreateDnsRecordSetUnion(
  2620. pUpdateRecord,
  2621. potherRecords );
  2622. if ( pRegRecord
  2623. &&
  2624. Dns_NameCompare_UTF8(
  2625. pRegRecord->pName,
  2626. pUpdateRecord->pName )
  2627. &&
  2628. CompareMultiAdapterSOAQueries(
  2629. pUpdateRecord->pName,
  2630. pUpdateEntry->DnsServerList,
  2631. pRegistryEntry->DnsServerList ) )
  2632. {
  2633. pNewRegRecord = CreateDnsRecordSetUnion(
  2634. pRegRecord,
  2635. potherRecords );
  2636. }
  2637. else
  2638. {
  2639. if ( pRegRecord )
  2640. {
  2641. //
  2642. // The record found in the registry for this adapter
  2643. // is stale and should be deleted. Otherwise we set the
  2644. // current list of records to only that of potherRecords.
  2645. //
  2646. ASYNCREG_F1( "DoUpdateForPrimaryName - Found stale registry entry:" );
  2647. ASYNCREG_F2( " Name : %s", pRegRecord->pName );
  2648. ASYNCREG_F1( " Address :" );
  2649. DNSLOG_PIP_ADDRESS( 1, &(pRegRecord->Data.A.IpAddress) );
  2650. ASYNCREG_F1( "" );
  2651. ASYNCREG_F1( " Calling DnsRemoveRecords_UTF8 to get rid of it" );
  2652. status = DnsModifyRecordsInSet_UTF8(
  2653. NULL, // no add records
  2654. pRegRecord, // delete records
  2655. DNS_UPDATE_CACHE_SECURITY_CONTEXT,
  2656. NULL, // no context handle
  2657. (PIP4_ARRAY) pRegistryEntry->DnsServerList,
  2658. NULL // reserved
  2659. );
  2660. ASYNCREG_F3( " DnsRemoveRecords_UTF8 returned: 0x%x\n\t%s",
  2661. status,
  2662. Dns_StatusString( status ) );
  2663. }
  2664. pNewRegRecord = potherRecords;
  2665. potherRecords = NULL;
  2666. }
  2667. if ( !pNewUpdateRecord || !pNewRegRecord )
  2668. {
  2669. DNSDBG( ANY, (
  2670. "ERROR: failed to build combined record set for update!\n" ));
  2671. status = DNS_ERROR_NO_MEMORY;
  2672. goto Exit;
  2673. }
  2674. ASYNCREG_F1( "ModifyAdapterRegistration - Calling DnsModifyRecordSet_UTF8" );
  2675. ASYNCREG_F1( " (current update + previous records)" );
  2676. if ( serverIp )
  2677. {
  2678. //
  2679. // DCR: just do replace from the start
  2680. //
  2681. ASYNCREG_F1( " (sending update to specific server)" );
  2682. DNSLOG_PIP_ARRAY( &ipArray );
  2683. status = DnsModifyRecordSet_UTF8(
  2684. NULL, // no creds
  2685. pNewRegRecord, // previous set
  2686. pNewUpdateRecord, // new set
  2687. DNS_UPDATE_CACHE_SECURITY_CONTEXT,
  2688. &ipArray );
  2689. ASYNCREG_F3( " DnsModifyRecordSet_UTF8 returned: 0x%x\n\t%s",
  2690. status,
  2691. Dns_StatusString( status ) );
  2692. if ( status == DNS_ERROR_RCODE_SERVER_FAILURE ||
  2693. status == ERROR_TIMEOUT )
  2694. {
  2695. goto SendUpdate1;
  2696. }
  2697. if ( status == DNS_ERROR_NOT_UNIQUE &&
  2698. g_RegistrationOverwritesInConflict )
  2699. {
  2700. ASYNCREG_F1( "ModifyAdapterRegistration - Calling DnsReplaceRecordSet_UTF8" );
  2701. ASYNCREG_F1( " (current update + previous records)" );
  2702. status = DnsReplaceRecordSetUTF8(
  2703. pNewUpdateRecord, // replace set
  2704. DNS_UPDATE_CACHE_SECURITY_CONTEXT,
  2705. NULL, // no security context
  2706. (PIP4_ARRAY) &ipArray, // DNS servers
  2707. NULL // reserved
  2708. );
  2709. ASYNCREG_F3( " DnsReplaceRecordSet_UTF8 returned: 0x%x\n\t%s",
  2710. status,
  2711. Dns_StatusString( status ) );
  2712. }
  2713. }
  2714. else
  2715. {
  2716. SendUpdate1 :
  2717. ASYNCREG_F1( " (sending update to adapter server list)" );
  2718. DNSLOG_PIP_ARRAY( pUpdateEntry->DnsServerList );
  2719. status = DnsModifyRecordSet_UTF8(
  2720. NULL, // no creds
  2721. pNewRegRecord, // previous set
  2722. pNewUpdateRecord, // new set
  2723. DNS_UPDATE_CACHE_SECURITY_CONTEXT,
  2724. pUpdateEntry->DnsServerList
  2725. );
  2726. ASYNCREG_F3( " DnsModifyRecordSet_UTF8 returned: 0x%x\n\t%s",
  2727. status,
  2728. Dns_StatusString( status ) );
  2729. if ( status == DNS_ERROR_NOT_UNIQUE &&
  2730. g_RegistrationOverwritesInConflict )
  2731. {
  2732. ASYNCREG_F1( "ModifyAdapterRegistration - Calling DnsReplaceRecordSet_UTF8" );
  2733. ASYNCREG_F1( " (current update + previous records)" );
  2734. status = DnsReplaceRecordSetUTF8(
  2735. pNewUpdateRecord, // replace set
  2736. DNS_UPDATE_CACHE_SECURITY_CONTEXT,
  2737. NULL, // no security context
  2738. (PIP4_ARRAY) pUpdateEntry->DnsServerList,
  2739. NULL // reserved
  2740. );
  2741. ASYNCREG_F3( " DnsReplaceRecordSet_UTF8 returned: 0x%x\n\t%s",
  2742. status,
  2743. Dns_StatusString( status ) );
  2744. }
  2745. }
  2746. }
  2747. else
  2748. {
  2749. if ( pRegRecord
  2750. &&
  2751. Dns_NameCompare_UTF8(
  2752. pRegRecord->pName,
  2753. pUpdateRecord->pName )
  2754. &&
  2755. CompareMultiAdapterSOAQueries(
  2756. pUpdateRecord->pName,
  2757. pUpdateEntry->DnsServerList,
  2758. pRegistryEntry->DnsServerList ) )
  2759. {
  2760. ASYNCREG_F1( "ModifyAdapterRegistration - Calling DnsModifyRecordSet_UTF8" );
  2761. ASYNCREG_F1( " (current update record only)" );
  2762. status = DnsModifyRecordSet_UTF8(
  2763. NULL, // no creds
  2764. pRegRecord, // previous set
  2765. pUpdateRecord, // new set
  2766. DNS_UPDATE_CACHE_SECURITY_CONTEXT,
  2767. pUpdateEntry->DnsServerList );
  2768. ASYNCREG_F3( " DnsModifyRecordSet_UTF8 returned: 0x%x\n\t%s",
  2769. status,
  2770. Dns_StatusString( status ) );
  2771. }
  2772. else
  2773. {
  2774. if ( pRegRecord )
  2775. {
  2776. //
  2777. // The record found in the registry for this adapter
  2778. // is stale and should be deleted. Otherwise we set the
  2779. // current list of records to only that of potherRecords.
  2780. //
  2781. ASYNCREG_F1( "DoUpdateForPrimaryName - Found stale registry entry:" );
  2782. ASYNCREG_F2( " Name : %s", pRegRecord->pName );
  2783. ASYNCREG_F1( " Address :" );
  2784. DNSLOG_PIP_ADDRESS( 1, &(pRegRecord->Data.A.IpAddress) );
  2785. ASYNCREG_F1( "" );
  2786. ASYNCREG_F1( " Calling DnsRemoveRecords_UTF8 to get rid of it" );
  2787. status = DnsModifyRecordsInSet_UTF8(
  2788. NULL, // no add records
  2789. pRegRecord, // delete records
  2790. DNS_UPDATE_CACHE_SECURITY_CONTEXT,
  2791. NULL, // no context handle
  2792. pRegistryEntry->DnsServerList,
  2793. NULL // reserved
  2794. );
  2795. ASYNCREG_F3( " DnsRemoveRecords_UTF8 returned: 0x%x\n\t%s",
  2796. status,
  2797. Dns_StatusString( status ) );
  2798. }
  2799. ASYNCREG_F1( "ModifyAdapterRegistration - Calling DnsAddRecordSet_UTF8" );
  2800. status = DnsAddRecordSet_UTF8(
  2801. NULL, // no creds
  2802. pUpdateRecord,
  2803. DNS_UPDATE_CACHE_SECURITY_CONTEXT,
  2804. pUpdateEntry->DnsServerList );
  2805. ASYNCREG_F3( " DnsAddRecordSet_UTF8 returned: 0x%x\n\t%s",
  2806. status,
  2807. Dns_StatusString( status ) );
  2808. }
  2809. if ( status == DNS_ERROR_NOT_UNIQUE &&
  2810. g_RegistrationOverwritesInConflict )
  2811. {
  2812. ASYNCREG_F1( "ModifyAdapterRegistration - Calling DnsReplaceRecordSet_UTF8" );
  2813. ASYNCREG_F1( " (current update record only)" );
  2814. status = DnsReplaceRecordSetUTF8(
  2815. pUpdateRecord, // replace set
  2816. DNS_UPDATE_CACHE_SECURITY_CONTEXT,
  2817. NULL, // no security context
  2818. (PIP4_ARRAY) pUpdateEntry->DnsServerList,
  2819. NULL // reserved
  2820. );
  2821. ASYNCREG_F3( " DnsReplaceRecordSet_UTF8 returned: 0x%x\n\t%s",
  2822. status,
  2823. Dns_StatusString( status ) );
  2824. }
  2825. }
  2826. Exit:
  2827. Dns_RecordListFree( potherRecords );
  2828. Dns_RecordListFree( pNewUpdateRecord );
  2829. Dns_RecordListFree( pNewRegRecord );
  2830. return status;
  2831. }
  2832. DNS_STATUS
  2833. DoModifyUpdate(
  2834. IN OUT PUPDATE_ENTRY pUpdateEntry,
  2835. IN OUT PDNS_RECORD pUpdateRecord,
  2836. IN PUPDATE_ENTRY pRegistryEntry, OPTIONAL
  2837. IN OUT PDNS_RECORD pRegRecord, OPTIONAL
  2838. IN UPTYPE UpType
  2839. )
  2840. /*++
  2841. Routine Description:
  2842. Standard modify registration.
  2843. Helper routine for DoUpdate().
  2844. This handles modify for typical non-remove case.
  2845. - Forward records updated
  2846. - Old PTR removed if new address.
  2847. - New PTR added (or name modified).
  2848. Arguments:
  2849. pUpdateEntry -- update entry
  2850. pUpdateRecord -- records for update
  2851. pRegistryEntry -- registry entry
  2852. pRegRecord -- records from registry entry
  2853. fPrimary -- TRUE if update for primary domain name
  2854. FALSE for adapter domain name
  2855. Return Value:
  2856. DNS or Win32 error code.
  2857. --*/
  2858. {
  2859. DNS_STATUS status = NO_ERROR;
  2860. IP4_ADDRESS ip = 0;
  2861. BOOL fregistered = FALSE;
  2862. DNSDBG( TRACE, (
  2863. "DoModifyUpdate()\n"
  2864. "\tUpdateEntry = %p\n"
  2865. "\tUpType = %d\n",
  2866. pUpdateEntry,
  2867. UpType ));
  2868. DNS_ASSERT( pUpdateEntry != NULL );
  2869. DNS_ASSERT( pUpdateRecord != NULL );
  2870. //
  2871. // do forward registration modify
  2872. //
  2873. status = ModifyAdapterRegistration(
  2874. pUpdateEntry, // add
  2875. pRegistryEntry, // remove
  2876. pUpdateRecord,
  2877. pRegRecord,
  2878. IS_UPTYPE_PRIMARY(UpType)
  2879. );
  2880. //
  2881. // save success info
  2882. //
  2883. SetUpdateStatus(
  2884. pUpdateEntry,
  2885. status,
  2886. UpType );
  2887. //
  2888. // PTR records
  2889. //
  2890. // deregister previous PTR registration
  2891. // - registry entry indicates previous registration
  2892. // - not the same address as current (otherwise it's an update)
  2893. //
  2894. // note: adding new registration takes place in DoUpdate() once
  2895. // ALL forward updates are complete
  2896. //
  2897. if ( g_RegisterReverseLookup )
  2898. {
  2899. if ( pRegistryEntry &&
  2900. (pRegistryEntry->Flags & DYNDNS_REG_PTR) &&
  2901. !compareUpdateEntries( pRegistryEntry, pUpdateEntry ) )
  2902. {
  2903. UpdatePtrRecords(
  2904. pRegistryEntry,
  2905. FALSE // remove previous PTR
  2906. );
  2907. }
  2908. }
  2909. //
  2910. // Log registration status in EventLog
  2911. //
  2912. if ( pUpdateEntry->RetryCount == 2 ||
  2913. status == DNS_ERROR_RCODE_NOT_IMPLEMENTED ||
  2914. status == DNS_ERROR_RCODE_REFUSED )
  2915. {
  2916. LogRegistration(
  2917. pUpdateEntry,
  2918. status,
  2919. UpType,
  2920. FALSE, // registration
  2921. 0, // default server IP
  2922. 0 // default update IP
  2923. );
  2924. }
  2925. DNSDBG( TRACE, (
  2926. "Leave DoModifyUpdate() => %d\n",
  2927. status ));
  2928. return status;
  2929. }
  2930. DNS_STATUS
  2931. DoUpdate(
  2932. IN OUT PUPDATE_ENTRY pRegistryEntry OPTIONAL,
  2933. IN OUT PUPDATE_ENTRY pUpdateEntry,
  2934. IN UPTYPE UpType
  2935. )
  2936. /*++
  2937. Routine Description:
  2938. Do update for a particular name.
  2939. Helper routine for ProcessUpdate().
  2940. Handles one name, called separately for AdapaterDomainName and
  2941. PrimaryDomainName.
  2942. Arguments:
  2943. pUpdateEntry -- update entry
  2944. pRegistryEntry -- registry entry
  2945. fPrimary -- TRUE if update for primary domain name
  2946. FALSE for adapter domain name
  2947. Return Value:
  2948. DNS or Win32 error code.
  2949. --*/
  2950. {
  2951. PDNS_RECORD prrRegistry = NULL;
  2952. PDNS_RECORD prrUpdate = NULL;
  2953. DNS_STATUS status = NO_ERROR;
  2954. ASYNCREG_UPDATE_ENTRY(
  2955. "DoUpdate() -- UpdateEntry:",
  2956. pUpdateEntry );
  2957. ASYNCREG_UPDATE_ENTRY(
  2958. "DoUpdate() -- RegistryEntry:",
  2959. pRegistryEntry );
  2960. IF_DNSDBG( TRACE )
  2961. {
  2962. DnsDbg_UpdateEntry(
  2963. "DoUpdate() -- UpdateEntry:",
  2964. pUpdateEntry );
  2965. DnsDbg_UpdateEntry(
  2966. "DoUpdate() -- RegistryEntry:",
  2967. pRegistryEntry );
  2968. }
  2969. DNS_ASSERT( pUpdateEntry != NULL );
  2970. //
  2971. // build records from update entrys
  2972. //
  2973. prrUpdate = CreateForwardRecords(
  2974. pUpdateEntry,
  2975. UpType
  2976. );
  2977. if ( ! prrUpdate )
  2978. {
  2979. DNSDBG( TRACE, (
  2980. "No forward records created for update entry (%p) for update type %d!",
  2981. pUpdateEntry,
  2982. UpType ));
  2983. return NO_ERROR;
  2984. }
  2985. if ( pRegistryEntry )
  2986. {
  2987. prrRegistry = CreateForwardRecords(
  2988. pRegistryEntry,
  2989. UpType
  2990. );
  2991. DNS_ASSERT( !IS_UPTYPE_ALTERNATE(UpType) || prrRegistry==NULL );
  2992. }
  2993. //
  2994. // remove?
  2995. // - remove previous registry entry if exists
  2996. // - remove update entry
  2997. //
  2998. if ( pUpdateEntry->fRemove )
  2999. {
  3000. if ( prrRegistry )
  3001. {
  3002. // we don't lookup registry entries on fRemove updates, so i
  3003. // don't see how we'd get here
  3004. DNS_ASSERT( FALSE );
  3005. DoRemoveUpdate(
  3006. pRegistryEntry,
  3007. prrRegistry,
  3008. UpType );
  3009. }
  3010. status = DoRemoveUpdate(
  3011. pUpdateEntry,
  3012. prrUpdate,
  3013. UpType );
  3014. }
  3015. //
  3016. // add\modify registration
  3017. //
  3018. else
  3019. {
  3020. status = DoModifyUpdate(
  3021. pUpdateEntry,
  3022. prrUpdate,
  3023. pRegistryEntry,
  3024. prrRegistry,
  3025. UpType
  3026. );
  3027. }
  3028. //
  3029. // cleanup records
  3030. //
  3031. Dns_RecordListFree( prrRegistry );
  3032. Dns_RecordListFree( prrUpdate );
  3033. return status;
  3034. }
  3035. BOOL
  3036. IsQuickRetryError(
  3037. IN DNS_STATUS Status
  3038. )
  3039. {
  3040. return( Status != NO_ERROR
  3041. &&
  3042. ( Status == DNS_ERROR_RCODE_REFUSED ||
  3043. Status == DNS_ERROR_RCODE_SERVER_FAILURE ||
  3044. Status == DNS_ERROR_TRY_AGAIN_LATER ||
  3045. Status == DNS_ERROR_NO_DNS_SERVERS ||
  3046. Status == WSAECONNREFUSED ||
  3047. Status == WSAETIMEDOUT ||
  3048. Status == ERROR_TIMEOUT ) );
  3049. }
  3050. VOID
  3051. ProcessUpdateEntry(
  3052. IN OUT PUPDATE_ENTRY pUpdateEntry,
  3053. IN BOOL fPurgeMode
  3054. )
  3055. /*++
  3056. Routine Description:
  3057. Main routine processing an update.
  3058. Arguments:
  3059. pUpdateEntry -- update entry to execute
  3060. note: this routine frees pUpdateEntry when complete
  3061. fPurgeMode -- TRUE if purging update queue
  3062. Return Value:
  3063. DNS or Win32 error code.
  3064. --*/
  3065. {
  3066. DNS_STATUS status;
  3067. DNS_STATUS statusPri = NO_ERROR;
  3068. DNS_STATUS statusAdp = NO_ERROR;
  3069. DNS_STATUS statusAlt = NO_ERROR;
  3070. PUPDATE_ENTRY pregEntry = NULL;
  3071. DWORD retryInterval;
  3072. DNSDBG( TRACE, (
  3073. "ProcessUpdateEntry( %p, purge=%d )\n",
  3074. pUpdateEntry,
  3075. fPurgeMode ));
  3076. IF_DNSDBG( TRACE )
  3077. {
  3078. DnsDbg_UpdateEntry(
  3079. "Enter ProcessUpdateEntry():",
  3080. pUpdateEntry );
  3081. }
  3082. //
  3083. // add (not remove)
  3084. //
  3085. if ( !pUpdateEntry->fRemove )
  3086. {
  3087. // no adds during purge mode
  3088. if ( fPurgeMode )
  3089. {
  3090. goto Cleanup;
  3091. }
  3092. //
  3093. // get any prior update info from registry
  3094. //
  3095. // if hostname change, then delete on prior update
  3096. //
  3097. pregEntry = ReadUpdateEntryFromRegistry( pUpdateEntry->AdapterName );
  3098. if ( pregEntry )
  3099. {
  3100. if ( ! Dns_NameCompare_UTF8(
  3101. pregEntry->HostName,
  3102. pUpdateEntry->HostName ) )
  3103. {
  3104. DNSDBG( TRACE, (
  3105. "Prior registry data with non-matching hostname!\n"
  3106. "\tqueuing delete for prior data and doing standard add.\n" ));
  3107. //
  3108. // Create delete update entry for registry information and
  3109. // add to registration list. Clear registry in the mean time.
  3110. //
  3111. pregEntry->fRemove = TRUE;
  3112. pregEntry->Flags |= DYNDNS_DEL_ENTRY;
  3113. pregEntry->fRegisteredFWD = FALSE;
  3114. pregEntry->fRegisteredPRI = FALSE;
  3115. pregEntry->fRegisteredPTR = FALSE;
  3116. if ( fPurgeMode )
  3117. {
  3118. pregEntry->RetryCount = 2;
  3119. pregEntry->RetryTime = Dns_GetCurrentTimeInSeconds();
  3120. }
  3121. //
  3122. // Clear registry key for adapter
  3123. //
  3124. WriteUpdateEntryToRegistry( pregEntry );
  3125. //
  3126. // Put update in registration list
  3127. // - clear registry entry PTR so not used below
  3128. //
  3129. enqueueUpdate( pregEntry );
  3130. pregEntry = NULL;
  3131. // fall through to do standard add update with no prior data
  3132. }
  3133. }
  3134. }
  3135. //
  3136. // do updates
  3137. // - primary
  3138. // - adapter domain
  3139. // - alternate name
  3140. //
  3141. if ( ! pUpdateEntry->fRegisteredFWD )
  3142. {
  3143. statusAdp = DoUpdate(
  3144. pregEntry,
  3145. pUpdateEntry,
  3146. UPTYPE_DOMAIN
  3147. );
  3148. }
  3149. if ( ! pUpdateEntry->fRegisteredPRI )
  3150. {
  3151. statusPri = DoUpdate(
  3152. pregEntry,
  3153. pUpdateEntry,
  3154. UPTYPE_PRIMARY // primary update
  3155. );
  3156. }
  3157. if ( ! pUpdateEntry->fRegisteredALT )
  3158. {
  3159. PSTR pname = pUpdateEntry->AlternateNames;
  3160. DNS_STATUS statusTmp;
  3161. DWORD count = 0;
  3162. //
  3163. // update each alternate name in MULTISZ
  3164. // - must set index in update blob to use correct name in
  3165. // record building
  3166. // - any failure fails ALT names
  3167. //
  3168. statusAlt = NO_ERROR;
  3169. while ( pname )
  3170. {
  3171. pUpdateEntry->AlternateIndex = count++;
  3172. DNSDBG( DHCP, (
  3173. "Update with alternate name %s\n"
  3174. "\tindex = %d\n",
  3175. pname,
  3176. count-1 ));
  3177. statusTmp = DoUpdate(
  3178. NULL, // not saving alternate info in registry
  3179. // pregEntry,
  3180. pUpdateEntry,
  3181. UPTYPE_ALTERNATE
  3182. );
  3183. if ( statusTmp != NO_ERROR )
  3184. {
  3185. statusAlt = statusTmp;
  3186. }
  3187. pname = MultiSz_NextString_A( pname );
  3188. }
  3189. pUpdateEntry->fRegisteredALT = (statusAlt == NO_ERROR);
  3190. }
  3191. //
  3192. // update PTRs once forward done
  3193. //
  3194. // doing this outside DoUpdate() because will ONLY do PTRs
  3195. // for forwards that succeed, so want all forward updates
  3196. // completed first; but this also helps in that it combines
  3197. // the reverse updates
  3198. //
  3199. if (( pUpdateEntry->Flags & DYNDNS_REG_PTR) && g_RegisterReverseLookup)
  3200. {
  3201. UpdatePtrRecords(
  3202. pUpdateEntry,
  3203. !pUpdateEntry->fRemove // add update
  3204. );
  3205. }
  3206. //
  3207. // write completed update info to registry
  3208. //
  3209. if ( !pUpdateEntry->fRemove )
  3210. {
  3211. WriteUpdateEntryToRegistry( pUpdateEntry );
  3212. }
  3213. //
  3214. // setup retry on failure
  3215. //
  3216. if ( statusPri != NO_ERROR )
  3217. {
  3218. status = statusPri;
  3219. goto ErrorRetry;
  3220. }
  3221. else if ( statusAdp != NO_ERROR )
  3222. {
  3223. status = statusAdp;
  3224. goto ErrorRetry;
  3225. }
  3226. else if ( statusAlt != NO_ERROR )
  3227. {
  3228. status = statusAlt;
  3229. goto ErrorRetry;
  3230. }
  3231. //
  3232. // successful update
  3233. // - signal update event (if given)
  3234. // - cleanup if remove or purging
  3235. // - requeue if add
  3236. //
  3237. if ( pUpdateEntry->pRegisterStatus )
  3238. {
  3239. registerUpdateStatus( pUpdateEntry->pRegisterStatus, ERROR_SUCCESS );
  3240. }
  3241. if ( pUpdateEntry->fRemove || fPurgeMode || g_fPurgeRegistrations )
  3242. {
  3243. DNSDBG( TRACE, (
  3244. "Leaving ProcessUpdate() => successful remove\\purge.\n" ));
  3245. goto Cleanup;
  3246. }
  3247. else
  3248. {
  3249. pUpdateEntry->fNewElement = FALSE;
  3250. pUpdateEntry->fRegisteredFWD = FALSE;
  3251. pUpdateEntry->fRegisteredPRI = FALSE;
  3252. pUpdateEntry->fRegisteredPTR = FALSE;
  3253. pUpdateEntry->RetryCount = 0;
  3254. pUpdateEntry->fDisableErrorLogging = TRUE;
  3255. pUpdateEntry->RetryTime = Dns_GetCurrentTimeInSeconds() +
  3256. g_RegistrationRefreshInterval;
  3257. if ( pUpdateEntry->pRegisterStatus )
  3258. {
  3259. pUpdateEntry->pRegisterStatus = NULL;
  3260. }
  3261. enqueueUpdate( pUpdateEntry );
  3262. DNSDBG( TRACE, (
  3263. "Leaving ProcessUpdate( %p ) => successful => requeued.\n",
  3264. pUpdateEntry ));
  3265. pUpdateEntry = NULL;
  3266. goto Cleanup;
  3267. }
  3268. ErrorRetry:
  3269. // failures during purge mode are not retried
  3270. // just free entry and bail
  3271. if ( fPurgeMode || g_fPurgeRegistrations )
  3272. {
  3273. DNSDBG( TRACE, (
  3274. "Leaving ProcessUpdate() => failed purging.\n" ));
  3275. goto Cleanup;
  3276. }
  3277. //
  3278. // set retry time
  3279. //
  3280. // less than two retries and more transient errors
  3281. // => short retry
  3282. //
  3283. // third failure or longer term error code
  3284. // => push retry back to an hour
  3285. //
  3286. if ( pUpdateEntry->RetryCount < 2
  3287. &&
  3288. ( IsQuickRetryError(statusAdp) ||
  3289. IsQuickRetryError(statusPri) ||
  3290. IsQuickRetryError(statusAlt) ) )
  3291. {
  3292. pUpdateEntry->RetryCount++;
  3293. retryInterval = (pUpdateEntry->RetryCount == 1)
  3294. ? FIRST_RETRY_INTERVAL
  3295. : SECOND_RETRY_INTERVAL;
  3296. }
  3297. else
  3298. {
  3299. retryInterval = FAILED_RETRY_INTERVAL;
  3300. pUpdateEntry->RetryCount = 0;
  3301. pUpdateEntry->fDisableErrorLogging = TRUE;
  3302. if ( pUpdateEntry->pRegisterStatus )
  3303. {
  3304. registerUpdateStatus( pUpdateEntry->pRegisterStatus, status );
  3305. pUpdateEntry->pRegisterStatus = NULL;
  3306. }
  3307. }
  3308. pUpdateEntry->fNewElement = FALSE;
  3309. pUpdateEntry->RetryTime = Dns_GetCurrentTimeInSeconds() + retryInterval;
  3310. //
  3311. // requeue
  3312. // - entry dumped if another update for adapter already queued
  3313. //
  3314. enqueueUpdateMaybe( pUpdateEntry );
  3315. DNSDBG( TRACE, (
  3316. "Leaving ProcessUpdate( %p ) => failed => requeued.\n",
  3317. pUpdateEntry ));
  3318. pUpdateEntry = NULL;
  3319. Cleanup:
  3320. //
  3321. // cleanup
  3322. // - registry entry
  3323. // - update entry if not requeued
  3324. //
  3325. FreeUpdateEntry( pregEntry );
  3326. FreeUpdateEntry( pUpdateEntry );
  3327. }
  3328. VOID
  3329. ResetAdaptersInRegistry(
  3330. VOID
  3331. )
  3332. {
  3333. DWORD retVal = NO_ERROR;
  3334. DWORD status = NO_ERROR;
  3335. CHAR szName[ MAX_PATH ];
  3336. HKEY hAdapterKey = NULL;
  3337. DWORD dwType;
  3338. INT index;
  3339. DWORD dwBytesRead = MAX_PATH -1;
  3340. DWORD dwRegistered = 0;
  3341. ASYNCREG_F1( "Inside function ResetAdaptersInRegistry" );
  3342. ASYNCREG_F1( "" );
  3343. index = 0;
  3344. while ( !retVal )
  3345. {
  3346. dwBytesRead = MAX_PATH - 1;
  3347. retVal = RegEnumKeyEx ( g_hKey,
  3348. index,
  3349. szName,
  3350. &dwBytesRead,
  3351. NULL,
  3352. NULL,
  3353. NULL,
  3354. NULL );
  3355. if ( retVal )
  3356. {
  3357. goto Exit;
  3358. }
  3359. status = RegOpenKeyEx( g_hKey,
  3360. szName,
  3361. 0,
  3362. KEY_ALL_ACCESS,
  3363. &hAdapterKey );
  3364. if ( status )
  3365. {
  3366. goto Exit;
  3367. }
  3368. //
  3369. // Found an adapter in the registry, set registered since
  3370. // boot to FALSE.
  3371. //
  3372. status = RegSetValueExA( hAdapterKey,
  3373. REGISTERED_SINCE_BOOT,
  3374. 0,
  3375. REG_DWORD,
  3376. (LPBYTE)&dwRegistered, // 0 - False
  3377. sizeof(DWORD) );
  3378. if ( status )
  3379. {
  3380. goto Exit;
  3381. }
  3382. RegCloseKey( hAdapterKey );
  3383. hAdapterKey = NULL;
  3384. index++;
  3385. }
  3386. Exit :
  3387. if ( hAdapterKey )
  3388. {
  3389. RegCloseKey( hAdapterKey );
  3390. }
  3391. }
  3392. VOID
  3393. DeregisterUnusedAdapterInRegistry(
  3394. IN BOOL fPurgeMode
  3395. )
  3396. {
  3397. DWORD retVal = NO_ERROR;
  3398. DWORD status = NO_ERROR;
  3399. CHAR szName[MAX_PATH];
  3400. HKEY hAdapterKey = NULL;
  3401. INT index;
  3402. DWORD dwBytesRead = MAX_PATH -1;
  3403. DWORD dwRegistered = 0;
  3404. PUPDATE_ENTRY pregEntry = NULL;
  3405. ASYNCREG_F1( "Inside function DeregisterUnusedAdapterInRegistry" );
  3406. ASYNCREG_F1( "" );
  3407. index = 0;
  3408. while ( !retVal )
  3409. {
  3410. dwBytesRead = MAX_PATH - 1;
  3411. retVal = RegEnumKeyEx ( g_hKey,
  3412. index,
  3413. szName,
  3414. &dwBytesRead,
  3415. NULL,
  3416. NULL,
  3417. NULL,
  3418. NULL );
  3419. if ( retVal != ERROR_SUCCESS )
  3420. {
  3421. goto Exit;
  3422. }
  3423. status = RegOpenKeyEx( g_hKey,
  3424. szName,
  3425. 0,
  3426. KEY_ALL_ACCESS,
  3427. &hAdapterKey );
  3428. if ( status != ERROR_SUCCESS )
  3429. {
  3430. goto Exit;
  3431. }
  3432. //
  3433. // Found an adapter in the registry, read registered since
  3434. // boot value to see if FALSE.
  3435. //
  3436. status = GetRegistryValue( hAdapterKey,
  3437. REGISTERED_SINCE_BOOT,
  3438. REG_DWORD,
  3439. (LPBYTE)&dwRegistered );
  3440. RegCloseKey( hAdapterKey );
  3441. hAdapterKey = NULL;
  3442. if ( status != ERROR_SUCCESS )
  3443. {
  3444. goto Exit;
  3445. }
  3446. if ( dwRegistered == 0 &&
  3447. (pregEntry = ReadUpdateEntryFromRegistry( szName )) )
  3448. {
  3449. if ( pregEntry->fRegisteredFWD ||
  3450. pregEntry->fRegisteredPRI ||
  3451. pregEntry->fRegisteredPTR )
  3452. {
  3453. ASYNCREG_F2( "Found unused adapter: %s", szName );
  3454. ASYNCREG_F1( "Removing entry from registry and adding" );
  3455. ASYNCREG_F1( "delete entry to registration list" );
  3456. //
  3457. // This adapter has not been configured since boot time,
  3458. // create delete update entry for registry information
  3459. // and add to registration list. Clear registry in the
  3460. // mean time.
  3461. //
  3462. pregEntry->fRemove = TRUE;
  3463. pregEntry->Flags |= DYNDNS_DEL_ENTRY;
  3464. pregEntry->fRegisteredFWD = FALSE;
  3465. pregEntry->fRegisteredPRI = FALSE;
  3466. pregEntry->fRegisteredPTR = FALSE;
  3467. if ( fPurgeMode )
  3468. {
  3469. pregEntry->RetryCount = 2;
  3470. pregEntry->RetryTime = Dns_GetCurrentTimeInSeconds();
  3471. }
  3472. //
  3473. // Clear registry key for adapter
  3474. //
  3475. WriteUpdateEntryToRegistry( pregEntry );
  3476. index--;
  3477. //
  3478. // Put update in registration list
  3479. //
  3480. enqueueUpdate( pregEntry );
  3481. PulseEvent( g_hNewItemEvent );
  3482. }
  3483. else
  3484. {
  3485. ASYNCREG_F2( "Found unused adapter: %s", szName );
  3486. ASYNCREG_F1( "This adapter is still pending an update, ignoring . . ." );
  3487. //
  3488. // We are only just starting to try to update this entry.
  3489. // Do not queue up a delete for it since the entry shows
  3490. // that no records have been registered anyhow.
  3491. //
  3492. FreeUpdateEntry( pregEntry );
  3493. pregEntry = NULL;
  3494. }
  3495. }
  3496. index++;
  3497. }
  3498. Exit :
  3499. if ( hAdapterKey )
  3500. {
  3501. RegCloseKey( hAdapterKey );
  3502. }
  3503. }
  3504. PDNS_RECORD
  3505. GetPreviousRegistrationInformation(
  3506. IN PUPDATE_ENTRY pUpdateEntry,
  3507. IN BOOL fPrimaryDomain,
  3508. OUT PIP_ADDRESS pServerIp
  3509. )
  3510. {
  3511. DWORD retVal = NO_ERROR;
  3512. DWORD status = NO_ERROR;
  3513. CHAR szName[MAX_PATH];
  3514. INT index;
  3515. DWORD dwBytesRead = MAX_PATH -1;
  3516. DWORD dwRegistered = 0;
  3517. PUPDATE_ENTRY pregEntry = NULL;
  3518. PDNS_RECORD precords = NULL;
  3519. PSTR pdomain;
  3520. DNSDBG( TRACE, (
  3521. "GetPreviousRegistrationInformation( %p )\n",
  3522. pUpdateEntry ));
  3523. //
  3524. // determine desired domain name to use
  3525. //
  3526. if ( fPrimaryDomain )
  3527. {
  3528. pdomain = pUpdateEntry->PrimaryDomainName;
  3529. }
  3530. else
  3531. {
  3532. pdomain = pUpdateEntry->DomainName;
  3533. }
  3534. if ( !pdomain )
  3535. {
  3536. goto Exit;
  3537. }
  3538. index = 0;
  3539. while ( !retVal )
  3540. {
  3541. dwBytesRead = MAX_PATH - 1;
  3542. retVal = RegEnumKeyEx(
  3543. g_hKey,
  3544. index,
  3545. szName,
  3546. &dwBytesRead,
  3547. NULL,
  3548. NULL,
  3549. NULL,
  3550. NULL );
  3551. if ( retVal )
  3552. {
  3553. goto Exit;
  3554. }
  3555. //
  3556. // Skip past registry information for the given adapter name
  3557. //
  3558. if ( !_stricmp( szName, pUpdateEntry->AdapterName ) )
  3559. {
  3560. index++;
  3561. continue;
  3562. }
  3563. //
  3564. // Found an adapter in the registry
  3565. //
  3566. pregEntry = ReadUpdateEntryFromRegistry( szName );
  3567. if ( pregEntry )
  3568. {
  3569. //
  3570. // See if registered entry is related to update entry
  3571. // ( same HostName and DomainName )
  3572. //
  3573. if ( Dns_NameCompare_UTF8(
  3574. pregEntry->HostName,
  3575. pUpdateEntry->HostName )
  3576. &&
  3577. ( Dns_NameCompare_UTF8(
  3578. pregEntry->DomainName,
  3579. pdomain )
  3580. ||
  3581. Dns_NameCompare_UTF8(
  3582. pregEntry->PrimaryDomainName,
  3583. pdomain ) ) )
  3584. {
  3585. BOOL fUsePrimary = TRUE;
  3586. if ( Dns_NameCompare_UTF8(
  3587. pregEntry->DomainName,
  3588. pdomain ) )
  3589. {
  3590. fUsePrimary = FALSE;
  3591. }
  3592. //
  3593. // PHASE 1 - COMPARE SOAS FROM REGISTRY AND UPDATE ENTRIES
  3594. // IF SAME, ADD TO LIST. ELSE, TOSS.
  3595. //
  3596. // PHASE 2 - COMPARE NS RECORDS FROM BOTH ENTRIES
  3597. // IF SAME ZONE AND SERVER, ADD TO LIST. ELSE, TOSS.
  3598. //
  3599. // PHASE 3 - COMPARE NS RECORDS FROM BOTH ENTRIES
  3600. // IF SAME ZONE AND THERE IS AN INTERSECTION OF
  3601. // SERVERS, ADD TO LIST. ELSE, TOSS.
  3602. // NOTE: FOR THIS PHASE, THERE HAD BETTER BE ALL
  3603. // SOAS RETURNED TO TEST INTERSECTION?
  3604. //
  3605. if ( CompareMultiAdapterSOAQueries(
  3606. pdomain,
  3607. pUpdateEntry->DnsServerList,
  3608. pregEntry->DnsServerList ) )
  3609. {
  3610. PDNS_RECORD prr;
  3611. //
  3612. // Convert registered entry to a PDNS_RECORD and
  3613. // add to current list
  3614. //
  3615. prr = CreateForwardRecords(
  3616. pregEntry,
  3617. fUsePrimary );
  3618. if ( prr )
  3619. {
  3620. precords = Dns_RecordListAppend(
  3621. precords,
  3622. prr );
  3623. if ( pServerIp &&
  3624. *pServerIp == 0 &&
  3625. pUpdateEntry->RetryCount == 0 &&
  3626. pregEntry->SentUpdateToIp )
  3627. {
  3628. *pServerIp = pregEntry->SentUpdateToIp;
  3629. }
  3630. }
  3631. }
  3632. }
  3633. FreeUpdateEntry( pregEntry );
  3634. pregEntry = NULL;
  3635. }
  3636. index++;
  3637. }
  3638. Exit:
  3639. DNSDBG( TRACE, (
  3640. "Leave GetPreviousRegistrationInformation()\n"
  3641. "\tprevious records = %p\n",
  3642. precords ));
  3643. return( precords );
  3644. }
  3645. PDNS_RECORD
  3646. CreateDnsRecordSetUnion(
  3647. IN PDNS_RECORD pSet1,
  3648. IN PDNS_RECORD pSet2
  3649. )
  3650. {
  3651. PDNS_RECORD pSet1Copy = NULL;
  3652. PDNS_RECORD pSet2Copy = NULL;
  3653. pSet1Copy = Dns_RecordSetCopyEx(
  3654. pSet1,
  3655. DnsCharSetUtf8,
  3656. DnsCharSetUtf8 );
  3657. if ( !pSet1Copy )
  3658. {
  3659. return NULL;
  3660. }
  3661. pSet2Copy = Dns_RecordSetCopyEx(
  3662. pSet2,
  3663. DnsCharSetUtf8,
  3664. DnsCharSetUtf8 );
  3665. if ( !pSet2Copy )
  3666. {
  3667. Dns_RecordListFree( pSet1Copy );
  3668. return NULL;
  3669. }
  3670. return Dns_RecordListAppend( pSet1Copy, pSet2Copy );
  3671. }
  3672. //
  3673. // Logging
  3674. //
  3675. #if 1 // DBG
  3676. VOID
  3677. LogHostEntries(
  3678. IN DWORD dwHostAddrCount,
  3679. IN PREGISTER_HOST_ENTRY pHostAddrs
  3680. )
  3681. {
  3682. DWORD iter;
  3683. for ( iter = 0; iter < dwHostAddrCount; iter++ )
  3684. {
  3685. ASYNCREG_F3( " HostAddrs[%d].dwOptions : 0x%x",
  3686. iter,
  3687. pHostAddrs[iter].dwOptions );
  3688. if ( pHostAddrs->dwOptions & REGISTER_HOST_A )
  3689. {
  3690. ASYNCREG_F6( " HostAddrs[%d].Addr.ipAddr : %d.%d.%d.%d",
  3691. iter,
  3692. ((BYTE *) &pHostAddrs[iter].Addr.ipAddr)[0],
  3693. ((BYTE *) &pHostAddrs[iter].Addr.ipAddr)[1],
  3694. ((BYTE *) &pHostAddrs[iter].Addr.ipAddr)[2],
  3695. ((BYTE *) &pHostAddrs[iter].Addr.ipAddr)[3] );
  3696. }
  3697. else if ( pHostAddrs->dwOptions & REGISTER_HOST_AAAA )
  3698. {
  3699. ASYNCREG_F6( " HostAddrs[%d].Addr.ipV6Addr : %d.%d.%d.%d",
  3700. iter,
  3701. ((DWORD *) &pHostAddrs[iter].Addr.ipV6Addr)[0],
  3702. ((DWORD *) &pHostAddrs[iter].Addr.ipV6Addr)[1],
  3703. ((DWORD *) &pHostAddrs[iter].Addr.ipV6Addr)[2],
  3704. ((DWORD *) &pHostAddrs[iter].Addr.ipV6Addr)[3] );
  3705. }
  3706. else
  3707. {
  3708. ASYNCREG_F1( "ERROR: HostAddrs[%d].Addr UNKNOWN ADDRESS TYPE!" );
  3709. }
  3710. }
  3711. }
  3712. #endif
  3713. #if 1 // DBG
  3714. VOID
  3715. LogPipAddress(
  3716. IN DWORD dwServerListCount,
  3717. IN PIP_ADDRESS pServers
  3718. )
  3719. {
  3720. DWORD iter;
  3721. for ( iter = 0; iter < dwServerListCount; iter++ )
  3722. {
  3723. ASYNCREG_F6( " Server [%d] : %d.%d.%d.%d",
  3724. iter,
  3725. ((BYTE *) &pServers[iter])[0],
  3726. ((BYTE *) &pServers[iter])[1],
  3727. ((BYTE *) &pServers[iter])[2],
  3728. ((BYTE *) &pServers[iter])[3] );
  3729. }
  3730. }
  3731. #endif
  3732. #if 1 // DBG
  3733. VOID
  3734. LogPipArray(
  3735. IN PIP_ARRAY pServers
  3736. )
  3737. {
  3738. DWORD count;
  3739. DWORD iter;
  3740. if ( pServers )
  3741. {
  3742. count = pServers->AddrCount;
  3743. }
  3744. else
  3745. {
  3746. return;
  3747. }
  3748. for ( iter = 0; iter < count; iter++ )
  3749. {
  3750. ASYNCREG_F6( " Server [%d] : %d.%d.%d.%d",
  3751. iter,
  3752. ((BYTE *) &pServers->AddrArray[iter])[0],
  3753. ((BYTE *) &pServers->AddrArray[iter])[1],
  3754. ((BYTE *) &pServers->AddrArray[iter])[2],
  3755. ((BYTE *) &pServers->AddrArray[iter])[3] );
  3756. }
  3757. }
  3758. #endif
  3759. DNS_STATUS
  3760. alertOrStartRegistrationThread(
  3761. VOID
  3762. )
  3763. /*++
  3764. Routine Description:
  3765. Alerts registration thread of new update, starting thread if necessary.
  3766. This is called in registration\deregistration functions to ensure
  3767. thread has been started.
  3768. Arguments:
  3769. None
  3770. Return Value:
  3771. ERROR_SUCCESS if successful.
  3772. Error code on failure.
  3773. --*/
  3774. {
  3775. DWORD threadId;
  3776. DNS_STATUS Status;
  3777. ASYNCREG_F1( "Inside alertOrStartRegistrationThread()\n" );
  3778. //
  3779. // must lock to avoid multiple async start
  3780. //
  3781. // DCR_PERF: use a single general CS for init protect issues
  3782. // simply check
  3783. // - done => bail
  3784. // - not done => dumb wait (sleep, check)
  3785. //
  3786. EnterCriticalSection( &g_RegistrationThreadCS );
  3787. if ( g_hRegistrationThread )
  3788. {
  3789. LeaveCriticalSection( &g_RegistrationThreadCS );
  3790. PulseEvent( g_hNewItemEvent );
  3791. return( ERROR_SUCCESS );
  3792. }
  3793. //
  3794. // if not started, fire it up
  3795. //
  3796. Status = ERROR_SUCCESS;
  3797. g_fQuit = FALSE;
  3798. g_fShutdown = FALSE;
  3799. ResetEvent( g_hStopEvent );
  3800. ResetEvent( g_hThreadDeadEvent );
  3801. g_hRegistrationThread = CreateThread(
  3802. NULL,
  3803. 0,
  3804. (LPTHREAD_START_ROUTINE)
  3805. RegistrationThread,
  3806. NULL,
  3807. 0,
  3808. & threadId );
  3809. if ( ! g_hRegistrationThread )
  3810. {
  3811. Status = GetLastError();
  3812. }
  3813. LeaveCriticalSection( &g_RegistrationThreadCS );
  3814. return( Status );
  3815. }
  3816. VOID
  3817. registerUpdateStatus(
  3818. IN OUT PREGISTER_HOST_STATUS pRegstatus,
  3819. IN DNS_STATUS Status
  3820. )
  3821. /*++
  3822. Routine Description:
  3823. Set Status and signal completion.
  3824. Arguments:
  3825. pRegstatus -- registration Status block to indicate
  3826. Status -- Status to indicate
  3827. Return Value:
  3828. None
  3829. --*/
  3830. {
  3831. // test for existence and event
  3832. if ( !pRegstatus || !pRegstatus->hDoneEvent )
  3833. {
  3834. return;
  3835. }
  3836. // set return Status
  3837. // signal event
  3838. pRegstatus->dwStatus = Status;
  3839. SetEvent( pRegstatus->hDoneEvent );
  3840. }
  3841. VOID
  3842. enqueueUpdate(
  3843. IN OUT PUPDATE_ENTRY pUpdate
  3844. )
  3845. /*++
  3846. Routine Description:
  3847. Queue update on registration queue.
  3848. Arguments:
  3849. pUpdate -- update completed
  3850. Return Value:
  3851. None
  3852. --*/
  3853. {
  3854. EnterCriticalSection( &g_RegistrationListCS );
  3855. InsertTailList( &g_RegistrationList, (PLIST_ENTRY)pUpdate );
  3856. LeaveCriticalSection( &g_RegistrationListCS );
  3857. }
  3858. VOID
  3859. enqueueUpdateMaybe(
  3860. IN OUT PUPDATE_ENTRY pUpdate
  3861. )
  3862. /*++
  3863. Routine Description:
  3864. Queue update on registration queue, only if there does not exist
  3865. any updates in the queue already for the given adapter.
  3866. Arguments:
  3867. pUpdate -- update completed
  3868. Return Value:
  3869. None
  3870. --*/
  3871. {
  3872. PLIST_ENTRY plistHead;
  3873. PLIST_ENTRY pentry;
  3874. BOOL fAdd = TRUE;
  3875. EnterCriticalSection( &g_RegistrationListCS );
  3876. plistHead = &g_RegistrationList;
  3877. pentry = plistHead->Flink;
  3878. while ( pentry != plistHead )
  3879. {
  3880. if ( !_stricmp( ((PUPDATE_ENTRY) pentry)->AdapterName,
  3881. pUpdate->AdapterName ) )
  3882. {
  3883. fAdd = FALSE;
  3884. break;
  3885. }
  3886. pentry = pentry->Flink;
  3887. }
  3888. if ( fAdd )
  3889. {
  3890. InsertTailList( &g_RegistrationList, (PLIST_ENTRY)pUpdate );
  3891. }
  3892. else
  3893. {
  3894. FreeUpdateEntry( pUpdate );
  3895. }
  3896. LeaveCriticalSection( &g_RegistrationListCS );
  3897. }
  3898. PLIST_ENTRY
  3899. dequeueAndCleanupUpdate(
  3900. IN OUT PLIST_ENTRY pUpdateEntry
  3901. )
  3902. /*++
  3903. Routine Description:
  3904. Dequeue and free update.
  3905. Includes any registration Status setting.
  3906. Arguments:
  3907. pUpdateEntry -- pUpdateEntry
  3908. Return Value:
  3909. Ptr to next update in queue.
  3910. --*/
  3911. {
  3912. PLIST_ENTRY pnext = pUpdateEntry->Flink;
  3913. RemoveEntryList( pUpdateEntry );
  3914. if ( ((PUPDATE_ENTRY)pUpdateEntry)->pRegisterStatus )
  3915. {
  3916. registerUpdateStatus(
  3917. ((PUPDATE_ENTRY)pUpdateEntry)->pRegisterStatus,
  3918. ERROR_SUCCESS );
  3919. }
  3920. FreeUpdateEntry( (PUPDATE_ENTRY) pUpdateEntry );
  3921. return( pnext );
  3922. }
  3923. BOOL
  3924. searchForOldUpdateEntriesAndCleanUp(
  3925. IN PSTR pszAdapterName,
  3926. IN PUPDATE_ENTRY pUpdateEntry, OPTIONAL
  3927. IN BOOL fLookInRegistry
  3928. )
  3929. /*++
  3930. Routine Description:
  3931. Searches registry for any previous registrations for a given adapter
  3932. name and queues up a delete update entry for it. Then walks the update
  3933. registration list to remove any add updates for the given adapter.
  3934. Arguments:
  3935. pszAdapterName -- name of adapters that is going away (disabled for
  3936. DDNS or now removed).
  3937. Return Value:
  3938. Flag to indicate whether a delete update has been queued up ready to
  3939. be processed.
  3940. --*/
  3941. {
  3942. PUPDATE_ENTRY pregEntry = NULL;
  3943. BOOL fReturn = FALSE;
  3944. PLIST_ENTRY plistHead;
  3945. PLIST_ENTRY pentry;
  3946. //
  3947. // See if this adapter has been previously registered
  3948. //
  3949. if ( fLookInRegistry &&
  3950. (pregEntry = ReadUpdateEntryFromRegistry( pszAdapterName )) )
  3951. {
  3952. pregEntry->fRemove = TRUE;
  3953. pregEntry->Flags |= DYNDNS_DEL_ENTRY;
  3954. pregEntry->fRegisteredFWD = FALSE;
  3955. pregEntry->fRegisteredPRI = FALSE;
  3956. pregEntry->fRegisteredPTR = FALSE;
  3957. //
  3958. // Clear registry key for adapter
  3959. //
  3960. WriteUpdateEntryToRegistry( pregEntry );
  3961. //
  3962. // Put update in registration list
  3963. //
  3964. enqueueUpdate( pregEntry );
  3965. fReturn = TRUE; // We have queued a delete update to process.
  3966. }
  3967. //
  3968. // Now walk the pending update list looking for updates that should
  3969. // be removed for the given adapter name.
  3970. //
  3971. EnterCriticalSection( &g_RegistrationListCS );
  3972. plistHead = &g_RegistrationList;
  3973. pentry = plistHead->Flink;
  3974. while ( pentry != plistHead )
  3975. {
  3976. if ( !_stricmp( ((PUPDATE_ENTRY) pentry)->AdapterName,
  3977. pszAdapterName ) &&
  3978. !((PUPDATE_ENTRY) pentry)->fRemove )
  3979. {
  3980. //
  3981. // There is an update entry in the registration list
  3982. // that has the same adapter name. We need to get rid of
  3983. // this entry since the adapter is being deleted.
  3984. //
  3985. if ( pUpdateEntry &&
  3986. compareUpdateEntries( (PUPDATE_ENTRY) pentry,
  3987. pUpdateEntry ) )
  3988. {
  3989. //
  3990. // The adapter entry in the queue is the same as the
  3991. // one being being processed. i.e. All of the adapter
  3992. // information seems to be the same and we must have
  3993. // just been called to refresh the adapter info in DNS.
  3994. // Since they are the same, if we have previously tried
  3995. // an update with these settings and failed and have
  3996. // already logged an event, then there is no reason to
  3997. // repeat the error event in the retries to follow
  3998. // on the new pUpdateEntry. That said, we'll copy over
  3999. // the flag from the queued update to the new one . . .
  4000. //
  4001. pUpdateEntry->fDisableErrorLogging =
  4002. ((PUPDATE_ENTRY) pentry)->fDisableErrorLogging;
  4003. }
  4004. pentry = dequeueAndCleanupUpdate( pentry );
  4005. continue;
  4006. }
  4007. else if ( !_stricmp( ((PUPDATE_ENTRY) pentry)->AdapterName,
  4008. pszAdapterName ) )
  4009. {
  4010. if ( !fLookInRegistry &&
  4011. pUpdateEntry &&
  4012. compareUpdateEntries( (PUPDATE_ENTRY) pentry,
  4013. pUpdateEntry ) )
  4014. {
  4015. //
  4016. // There is a delete update entry in the registration list
  4017. // that has the same adapter data. Get rid of this delete
  4018. // entry since the adapter is being updated again.
  4019. //
  4020. pentry = dequeueAndCleanupUpdate( pentry );
  4021. continue;
  4022. }
  4023. else
  4024. {
  4025. //
  4026. // There is a delete update entry in the registration list for
  4027. // the same adapter that contains different data, have the
  4028. // delete update set to new with a retry count of 2.
  4029. //
  4030. ((PUPDATE_ENTRY) pentry)->fNewElement = TRUE;
  4031. ((PUPDATE_ENTRY) pentry)->fRegisteredFWD = FALSE;
  4032. ((PUPDATE_ENTRY) pentry)->fRegisteredPRI = FALSE;
  4033. ((PUPDATE_ENTRY) pentry)->fRegisteredPTR = FALSE;
  4034. ((PUPDATE_ENTRY) pentry)->fDisableErrorLogging = FALSE;
  4035. ((PUPDATE_ENTRY) pentry)->RetryCount = 2;
  4036. ((PUPDATE_ENTRY) pentry)->RetryTime =
  4037. Dns_GetCurrentTimeInSeconds();
  4038. pentry = pentry->Flink;
  4039. }
  4040. }
  4041. else
  4042. {
  4043. pentry = pentry->Flink;
  4044. }
  4045. }
  4046. LeaveCriticalSection( &g_RegistrationListCS );
  4047. return fReturn;
  4048. }
  4049. BOOL
  4050. compareHostEntryAddrs(
  4051. IN PREGISTER_HOST_ENTRY Addrs1,
  4052. IN PREGISTER_HOST_ENTRY Addrs2,
  4053. IN DWORD Count
  4054. )
  4055. {
  4056. DWORD iter;
  4057. for ( iter = 0; iter < Count; iter++ )
  4058. {
  4059. if ( ( Addrs1[iter].dwOptions & REGISTER_HOST_A ) &&
  4060. ( Addrs2[iter].dwOptions & REGISTER_HOST_A ) )
  4061. {
  4062. if ( memcmp( &Addrs1[iter].Addr.ipAddr,
  4063. &Addrs2[iter].Addr.ipAddr,
  4064. sizeof( IP_ADDRESS ) ) )
  4065. {
  4066. return FALSE;
  4067. }
  4068. }
  4069. else if ( ( Addrs1[iter].dwOptions & REGISTER_HOST_AAAA ) &&
  4070. ( Addrs2[iter].dwOptions & REGISTER_HOST_AAAA ) )
  4071. {
  4072. if ( memcmp( &Addrs1[iter].Addr.ipV6Addr,
  4073. &Addrs2[iter].Addr.ipV6Addr,
  4074. sizeof( IP6_ADDRESS ) ) )
  4075. {
  4076. return FALSE;
  4077. }
  4078. }
  4079. else
  4080. {
  4081. return FALSE;
  4082. }
  4083. }
  4084. return TRUE;
  4085. }
  4086. //
  4087. // Routines for update entry comparison
  4088. //
  4089. BOOL
  4090. compareServerLists(
  4091. IN PIP_ARRAY List1,
  4092. IN PIP_ARRAY List2
  4093. )
  4094. {
  4095. if ( List1 && List2 )
  4096. {
  4097. if ( List1->AddrCount != List2->AddrCount )
  4098. {
  4099. return FALSE;
  4100. }
  4101. if ( memcmp( List1->AddrArray,
  4102. List2->AddrArray,
  4103. sizeof( IP_ADDRESS ) * List1->AddrCount ) )
  4104. {
  4105. return FALSE;
  4106. }
  4107. }
  4108. return TRUE;
  4109. }
  4110. BOOL
  4111. compareUpdateEntries(
  4112. IN PUPDATE_ENTRY pUpdateEntry1,
  4113. IN PUPDATE_ENTRY pUpdateEntry2
  4114. )
  4115. /*++
  4116. Routine Description:
  4117. Compares to update entries to see if they are describing the same
  4118. adapter configuration settings. Tests the domain names, the IP
  4119. address(es), host names, and the DNS server lists.
  4120. Arguments:
  4121. pUdapteEntry1 - one of the update entries to compare against the other.
  4122. pUdapteEntry2 - one of the update entries to compare against the other.
  4123. Return Value:
  4124. Flag to indicate whether a the two updates are the same.
  4125. --*/
  4126. {
  4127. if ( !pUpdateEntry1 || !pUpdateEntry2 )
  4128. {
  4129. return FALSE;
  4130. }
  4131. if ( ( pUpdateEntry1->HostName || pUpdateEntry2->HostName ) &&
  4132. !Dns_NameCompare_UTF8( pUpdateEntry1->HostName,
  4133. pUpdateEntry2->HostName ) )
  4134. {
  4135. return FALSE;
  4136. }
  4137. if ( ( pUpdateEntry1->DomainName || pUpdateEntry2->DomainName ) &&
  4138. !Dns_NameCompare_UTF8( pUpdateEntry1->DomainName,
  4139. pUpdateEntry2->DomainName ) )
  4140. {
  4141. return FALSE;
  4142. }
  4143. if ( ( pUpdateEntry1->PrimaryDomainName || pUpdateEntry2->PrimaryDomainName )
  4144. &&
  4145. ! Dns_NameCompare_UTF8(
  4146. pUpdateEntry1->PrimaryDomainName,
  4147. pUpdateEntry2->PrimaryDomainName ) )
  4148. {
  4149. return FALSE;
  4150. }
  4151. if ( pUpdateEntry1->HostAddrCount != pUpdateEntry2->HostAddrCount ||
  4152. ! compareHostEntryAddrs(
  4153. pUpdateEntry1->HostAddrs,
  4154. pUpdateEntry2->HostAddrs,
  4155. pUpdateEntry1->HostAddrCount ) )
  4156. {
  4157. return FALSE;
  4158. }
  4159. if ( pUpdateEntry1->DnsServerList &&
  4160. pUpdateEntry2->DnsServerList &&
  4161. ! compareServerLists(
  4162. pUpdateEntry1->DnsServerList,
  4163. pUpdateEntry2->DnsServerList ) )
  4164. {
  4165. return FALSE;
  4166. }
  4167. return TRUE;
  4168. }
  4169. //
  4170. // Glenn's old registry function
  4171. //
  4172. // No longer in use anywhere else but still used in these
  4173. // registration (dynreg and asyncreg) modules.
  4174. //
  4175. DWORD
  4176. GetRegistryValue(
  4177. HKEY KeyHandle,
  4178. PSTR ValueName,
  4179. DWORD ValueType,
  4180. PBYTE BufferPtr
  4181. )
  4182. /*++
  4183. Routine Description:
  4184. This function retrieves the value of the specified value field. This
  4185. function allocates memory for variable length fields such as REG_SZ.
  4186. For REG_DWORD data type, it copies the field value directly into
  4187. BufferPtr. If fIsWin9X is NOT set, all string types are read as
  4188. UNICODE (W) and then converted to UTF8 format. Currently it can
  4189. handle only the following fields :
  4190. REG_DWORD,
  4191. REG_SZ,
  4192. REG_MULTI_SZ,
  4193. REG_EXPAND_SZ
  4194. REG_BINARY
  4195. Arguments:
  4196. KeyHandle : handle of the key whose value field is retrieved.
  4197. ValueName : name of the value field.
  4198. ValueType : Expected type of the value field.
  4199. BufferPtr : Pointer to DWORD location where a DWORD datatype value
  4200. is returned or a buffer pointer for REG_SZ or REG_BINARY
  4201. datatype value is returned.
  4202. Return Value:
  4203. Registry Errors.
  4204. --*/
  4205. {
  4206. DWORD Error;
  4207. DWORD LocalValueType;
  4208. DWORD ValueSize;
  4209. PBYTE DataBuffer = NULL;
  4210. PBYTE AllotedBuffer = NULL;
  4211. PWSTR ValueNameW = NULL;
  4212. //
  4213. // DCR_PERF: heap buffer for name is stupid (MAX_PATH covers it)
  4214. //
  4215. DWORD Length = ( strlen( ValueName ) + 1 ) * sizeof( WCHAR );
  4216. ValueNameW = ALLOCATE_HEAP( Length );
  4217. if ( !ValueNameW )
  4218. {
  4219. return DNS_ERROR_NO_MEMORY;
  4220. }
  4221. Dns_Utf8ToUnicode( ValueName,
  4222. strlen( ValueName ),
  4223. ValueNameW,
  4224. Length );
  4225. //
  4226. // Query DataType and BufferSize.
  4227. //
  4228. Error = RegQueryValueExW( KeyHandle,
  4229. ValueNameW,
  4230. 0,
  4231. &LocalValueType,
  4232. NULL,
  4233. &ValueSize );
  4234. if ( Error != ERROR_SUCCESS )
  4235. {
  4236. FREE_HEAP( ValueNameW );
  4237. return(Error);
  4238. }
  4239. switch( ValueType )
  4240. {
  4241. case REG_DWORD:
  4242. DataBuffer = BufferPtr;
  4243. break;
  4244. case REG_SZ:
  4245. case REG_MULTI_SZ:
  4246. case REG_EXPAND_SZ:
  4247. case REG_BINARY:
  4248. if ( ValueSize == 0 )
  4249. {
  4250. //
  4251. // if string not found in the registry,
  4252. // allocate space for null string.
  4253. //
  4254. ValueSize = sizeof(WCHAR);
  4255. }
  4256. AllotedBuffer = DataBuffer = ALLOCATE_HEAP( ValueSize );
  4257. if ( DataBuffer == NULL )
  4258. {
  4259. return( DNS_ERROR_NO_MEMORY );
  4260. }
  4261. break;
  4262. default:
  4263. FREE_HEAP( ValueNameW );
  4264. return( ERROR_INVALID_PARAMETER );
  4265. }
  4266. //
  4267. // retrieve data.
  4268. //
  4269. Error = RegQueryValueExW( KeyHandle,
  4270. ValueNameW,
  4271. 0,
  4272. &LocalValueType,
  4273. DataBuffer,
  4274. &ValueSize );
  4275. FREE_HEAP( ValueNameW );
  4276. if ( Error != ERROR_SUCCESS )
  4277. {
  4278. if ( AllotedBuffer )
  4279. {
  4280. FREE_HEAP( AllotedBuffer );
  4281. }
  4282. *(DWORD *)BufferPtr = 0;
  4283. return(Error);
  4284. }
  4285. switch( ValueType )
  4286. {
  4287. case REG_BINARY:
  4288. if ( ValueSize == 0 )
  4289. {
  4290. //
  4291. // if string no found in the registry,
  4292. // return null string.
  4293. //
  4294. *(LPWSTR)DataBuffer = '\0';
  4295. }
  4296. *(LPBYTE *)BufferPtr = DataBuffer;
  4297. break;
  4298. case REG_SZ:
  4299. case REG_EXPAND_SZ:
  4300. case REG_MULTI_SZ:
  4301. if ( ValueSize == 0 )
  4302. {
  4303. //
  4304. // if string no found in the registry,
  4305. // return null string.
  4306. //
  4307. *(LPWSTR)DataBuffer = '\0';
  4308. }
  4309. {
  4310. LPBYTE Utf8Buffer = ALLOCATE_HEAP( ValueSize * 2 );
  4311. if ( Utf8Buffer == NULL )
  4312. {
  4313. return( DNS_ERROR_NO_MEMORY );
  4314. }
  4315. if ( !Dns_UnicodeToUtf8( (LPWSTR) DataBuffer,
  4316. ValueSize / sizeof(WCHAR),
  4317. Utf8Buffer,
  4318. ValueSize * 2 ) )
  4319. {
  4320. FREE_HEAP( DataBuffer );
  4321. return ERROR_INVALID_PARAMETER;
  4322. }
  4323. FREE_HEAP( DataBuffer );
  4324. *(LPBYTE *)BufferPtr = Utf8Buffer;
  4325. }
  4326. break;
  4327. default:
  4328. break;
  4329. }
  4330. return( Error );
  4331. }
  4332. //
  4333. // Jim Utils
  4334. //
  4335. PDNS_RECORD
  4336. CreatePtrRecord(
  4337. IN PSTR pszHostName,
  4338. IN PSTR pszDomainName,
  4339. IN IP4_ADDRESS Ip4Addr,
  4340. IN DWORD Ttl
  4341. )
  4342. /*++
  4343. Routine Description:
  4344. Create PTR record for update from IP and host and domain names.
  4345. Arguments:
  4346. Return Value:
  4347. PTR record to use in update.
  4348. --*/
  4349. {
  4350. IP_UNION ipUnion;
  4351. DNSDBG( TRACE, (
  4352. "CreatePtrRecord( %s, %s, %s )\n",
  4353. pszHostName,
  4354. pszDomainName,
  4355. IP_STRING( Ip4Addr ) ));
  4356. IPUNION_SET_IP4( &ipUnion, Ip4Addr );
  4357. return Dns_CreatePtrRecordExEx(
  4358. & ipUnion,
  4359. pszHostName,
  4360. pszDomainName,
  4361. Ttl,
  4362. DnsCharSetUtf8, // from UTF8
  4363. DnsCharSetUtf8 // to UTF8
  4364. );
  4365. }
  4366. VOID
  4367. UpdatePtrRecords(
  4368. IN OUT PUPDATE_ENTRY pUpdateEntry,
  4369. IN BOOL fAdd
  4370. )
  4371. /*++
  4372. Routine Description:
  4373. Register PTR records for an update entry.
  4374. Arguments:
  4375. pUpdateEntry -- update being processed
  4376. fAdd -- TRUE for add; FALSE for delete
  4377. Return Value:
  4378. PTR record to use in update.
  4379. --*/
  4380. {
  4381. DWORD iter;
  4382. PDNS_RECORD prr = NULL;
  4383. DNS_STATUS status = NO_ERROR;
  4384. IP_ADDRESS ipServer;
  4385. DNS_RRSET rrset;
  4386. PSTR pdomain = NULL;
  4387. PSTR pprimary = NULL;
  4388. DWORD ttl = pUpdateEntry->TTL;
  4389. PSTR phostname = pUpdateEntry->HostName;
  4390. DNSDBG( TRACE, (
  4391. "UpdatePtrRecords( %p, fAdd=%d )\n",
  4392. pUpdateEntry,
  4393. fAdd ));
  4394. IF_DNSDBG( TRACE )
  4395. {
  4396. DnsDbg_UpdateEntry(
  4397. "Entering UpdatePtrRecords:",
  4398. pUpdateEntry );
  4399. }
  4400. //
  4401. // make sure we have update to do
  4402. // only do ADD updates if forward registrations were
  4403. // successful
  4404. //
  4405. pdomain = pUpdateEntry->DomainName;
  4406. pprimary = pUpdateEntry->PrimaryDomainName;
  4407. if ( fAdd )
  4408. {
  4409. if ( !pUpdateEntry->fRegisteredFWD )
  4410. {
  4411. pdomain = NULL;
  4412. }
  4413. if ( !pUpdateEntry->fRegisteredPRI )
  4414. {
  4415. pprimary = NULL;
  4416. }
  4417. }
  4418. if ( !pdomain && !pprimary )
  4419. {
  4420. DNSDBG( TRACE, (
  4421. "UpdatePtrRecords() => no forward registrations"
  4422. "-- skipping PTR update.\n" ));
  4423. return;
  4424. }
  4425. //
  4426. // build PTR (or set) for each IP in update entry
  4427. //
  4428. for ( iter = 0; iter < pUpdateEntry->HostAddrCount; iter++ )
  4429. {
  4430. IP4_ADDRESS ip = pUpdateEntry->HostAddrs[iter].Addr.ipAddr;
  4431. if ( ip == 0 || ip == DNS_NET_ORDER_LOOPBACK )
  4432. {
  4433. DNS_ASSERT( FALSE );
  4434. continue;
  4435. }
  4436. //
  4437. // build update PTR set
  4438. // - primary name
  4439. // - adapter name
  4440. //
  4441. DNS_RRSET_INIT( rrset );
  4442. if ( pprimary )
  4443. {
  4444. prr = CreatePtrRecord(
  4445. phostname,
  4446. pprimary,
  4447. ip,
  4448. ttl );
  4449. if ( prr )
  4450. {
  4451. DNS_RRSET_ADD( rrset, prr );
  4452. }
  4453. }
  4454. if ( pdomain )
  4455. {
  4456. prr = CreatePtrRecord(
  4457. phostname,
  4458. pdomain,
  4459. ip,
  4460. ttl );
  4461. if ( prr )
  4462. {
  4463. DNS_RRSET_ADD( rrset, prr );
  4464. }
  4465. }
  4466. prr = rrset.pFirstRR;
  4467. if ( !prr )
  4468. {
  4469. continue;
  4470. }
  4471. //
  4472. // do update
  4473. //
  4474. // for ADD => replace, we own the IP address now
  4475. // for REMOVE => modify, as another update might have already
  4476. // written correct info
  4477. //
  4478. if ( fAdd )
  4479. {
  4480. status = DnsReplaceRecordSetUTF8(
  4481. prr, // update set
  4482. DNS_UPDATE_CACHE_SECURITY_CONTEXT,
  4483. NULL, // no security context
  4484. (PIP4_ARRAY) pUpdateEntry->DnsServerList,
  4485. NULL // reserved
  4486. );
  4487. }
  4488. else
  4489. {
  4490. status = DnsModifyRecordsInSet_UTF8(
  4491. NULL, // no add records
  4492. prr, // delete records
  4493. DNS_UPDATE_CACHE_SECURITY_CONTEXT,
  4494. NULL, // no context handle
  4495. pUpdateEntry->DnsServerList,
  4496. NULL // reserved
  4497. );
  4498. }
  4499. DNSDBG( TRACE, (
  4500. "%s on PTRs for IP %s => %d (%s)\n",
  4501. fAdd
  4502. ? "Replace"
  4503. : "Modify (remove)",
  4504. IP_STRING(ip),
  4505. status,
  4506. Dns_StatusString(status) ));
  4507. ipServer = 0;
  4508. if ( status == NO_ERROR ||
  4509. // status == DNS_ERROR_RCODE_SERVER_FAILURE ||
  4510. status == DNS_ERROR_RCODE_NOT_IMPLEMENTED ||
  4511. status == DNS_ERROR_RCODE_REFUSED ||
  4512. status == DNS_ERROR_RCODE_YXRRSET ||
  4513. status == DNS_ERROR_RCODE_NXRRSET )
  4514. {
  4515. ipServer = DnsGetLastServerUpdateIP();
  4516. }
  4517. if ( !fAdd ||
  4518. pUpdateEntry->RetryCount == 2 )
  4519. {
  4520. LogRegistration(
  4521. pUpdateEntry,
  4522. status,
  4523. UPTYPE_PTR,
  4524. !fAdd,
  4525. ipServer,
  4526. ip );
  4527. }
  4528. // note successful PTR registrations (adds)
  4529. if ( fAdd && status==NO_ERROR )
  4530. {
  4531. pUpdateEntry->fRegisteredPTR = TRUE;
  4532. }
  4533. Dns_RecordListFree( prr );
  4534. }
  4535. DNSDBG( TRACE, (
  4536. "Leave UpdatePtrRecords()\n" ));
  4537. }
  4538. PDNS_RECORD
  4539. CreateForwardRecords(
  4540. IN PUPDATE_ENTRY pUpdateEntry,
  4541. IN UPTYPE UpType
  4542. )
  4543. /*++
  4544. Routine Description:
  4545. Create A records for update.
  4546. Arguments:
  4547. pUpdateEntry -- update entry
  4548. UpType -- update type
  4549. UPTYPE_DOMAIN
  4550. UPTYPE_PRIMARY
  4551. UPTYPE_ALTERNATE
  4552. Return Value:
  4553. Ptr to list of A records.
  4554. --*/
  4555. {
  4556. PDNS_RECORD prr = NULL;
  4557. PSTR pname;
  4558. DWORD iter;
  4559. CHAR nameBuffer[ DNS_MAX_NAME_BUFFER_LENGTH ];
  4560. DNS_RRSET rrset;
  4561. DNSDBG( TRACE, (
  4562. "CreateForwardRecords( %p, %d )\n",
  4563. pUpdateEntry,
  4564. UpType ));
  4565. //
  4566. // build FQDN
  4567. //
  4568. // for alternate name, go to name for desired index
  4569. //
  4570. if ( IS_UPTYPE_ALTERNATE(UpType) )
  4571. {
  4572. DWORD count = pUpdateEntry->AlternateIndex;
  4573. pname = pUpdateEntry->AlternateNames;
  4574. while ( count-- )
  4575. {
  4576. pname = MultiSz_NextString_A( pname );
  4577. if ( !pname )
  4578. {
  4579. DNSDBG( ANY, (
  4580. "ERROR: Alternate count %d does NOT exist in name!\n",
  4581. pUpdateEntry->AlternateIndex ));
  4582. DNS_ASSERT( FALSE );
  4583. return NULL;
  4584. }
  4585. }
  4586. DNSDBG( DHCP, (
  4587. "Create records with alternate name %s\n",
  4588. pname ));
  4589. }
  4590. else
  4591. {
  4592. PSTR pdomain = pUpdateEntry->DomainName;
  4593. if ( IS_UPTYPE_PRIMARY(UpType) )
  4594. {
  4595. pdomain = pUpdateEntry->PrimaryDomainName;
  4596. }
  4597. if ( !pdomain || !pUpdateEntry->HostName )
  4598. {
  4599. return NULL;
  4600. }
  4601. if ( !Dns_NameAppend_A(
  4602. nameBuffer,
  4603. DNS_MAX_NAME_BUFFER_LENGTH,
  4604. pUpdateEntry->HostName,
  4605. pdomain ) )
  4606. {
  4607. return NULL;
  4608. }
  4609. pname = nameBuffer;
  4610. }
  4611. //
  4612. // create records for name
  4613. //
  4614. DNS_RRSET_INIT( rrset );
  4615. for ( iter = 0; iter < pUpdateEntry->HostAddrCount; iter++ )
  4616. {
  4617. if ( !(pUpdateEntry->HostAddrs[iter].dwOptions & REGISTER_HOST_A) )
  4618. {
  4619. continue;
  4620. }
  4621. prr = Dns_CreateARecord(
  4622. pname,
  4623. pUpdateEntry->HostAddrs[iter].Addr.ipAddr,
  4624. pUpdateEntry->TTL,
  4625. DnsCharSetUtf8,
  4626. DnsCharSetUtf8 );
  4627. if ( !prr )
  4628. {
  4629. SetLastError( DNS_ERROR_NO_MEMORY );
  4630. Dns_RecordListFree( rrset.pFirstRR );
  4631. return NULL;
  4632. }
  4633. DNS_RRSET_ADD( rrset, prr );
  4634. }
  4635. DNSDBG( TRACE, (
  4636. "Leave CreateForwardRecords() => %p\n",
  4637. rrset.pFirstRR ));
  4638. return rrset.pFirstRR;
  4639. }
  4640. VOID
  4641. SetUpdateStatus(
  4642. IN OUT PUPDATE_ENTRY pUpdateEntry,
  4643. IN DNS_STATUS Status,
  4644. IN UPTYPE UpType
  4645. )
  4646. /*++
  4647. Routine Description:
  4648. Set update Status info in update entry.
  4649. Arguments:
  4650. pUpdateEntry -- entry to set Status in
  4651. Status -- result of update
  4652. fPrimary -- TRUE if update was for primary name; FALSE otherwise
  4653. Return Value:
  4654. None
  4655. --*/
  4656. {
  4657. IP4_ADDRESS ipServer = 0;
  4658. BOOL fregistered = FALSE;
  4659. DNSDBG( TRACE, ( "SetUpdateStatus()\n" ));
  4660. DNS_ASSERT( pUpdateEntry != NULL );
  4661. fregistered = ( Status == NO_ERROR );
  4662. ipServer = DnsGetLastServerUpdateIP();
  4663. if ( IS_UPTYPE_PRIMARY(UpType) )
  4664. {
  4665. pUpdateEntry->SentPriUpdateToIp = ipServer;
  4666. pUpdateEntry->fRegisteredPRI = fregistered;
  4667. }
  4668. else if ( IS_UPTYPE_DOMAIN(UpType) )
  4669. {
  4670. pUpdateEntry->SentUpdateToIp = ipServer;
  4671. pUpdateEntry->fRegisteredFWD = fregistered;
  4672. }
  4673. }
  4674. VOID
  4675. DnsPrint_UpdateEntry(
  4676. IN PRINT_ROUTINE PrintRoutine,
  4677. IN OUT PPRINT_CONTEXT pContext,
  4678. IN PSTR pszHeader,
  4679. IN PUPDATE_ENTRY pEntry
  4680. )
  4681. /*++
  4682. Routine Description:
  4683. Print update entry.
  4684. Arguments:
  4685. PrintRoutine - routine to print with
  4686. pszHeader - header
  4687. pEntry - ptr to update entry
  4688. Return Value:
  4689. None.
  4690. --*/
  4691. {
  4692. DWORD i;
  4693. if ( !pszHeader )
  4694. {
  4695. pszHeader = "Update Entry:";
  4696. }
  4697. if ( !pEntry )
  4698. {
  4699. PrintRoutine(
  4700. pContext,
  4701. "%s %s\r\n",
  4702. pszHeader,
  4703. "NULL Update Entry ptr." );
  4704. return;
  4705. }
  4706. // print the struct
  4707. PrintRoutine(
  4708. pContext,
  4709. "%s\r\n"
  4710. "\tPtr = %p\n"
  4711. "\tSignatureTop = %08x\n"
  4712. "\tAdapterName = %s\n"
  4713. "\tHostName = %s\n"
  4714. "\tDomainName = %s\n"
  4715. "\tPrimaryDomainName = %s\n"
  4716. "\tAlternateName = %s\n"
  4717. "\tAlternateIndex = %d\n"
  4718. "\tHostAddrCount = %d\n"
  4719. "\tHostAddrs = %p\n"
  4720. "\tDnsServerList = %p\n"
  4721. "\tSentUpdateToIp = %s\n"
  4722. "\tSentPriUpdateToIp = %s\n"
  4723. "\tTTL = %d\n"
  4724. "\tFlags = %08x\n"
  4725. "\tfNewElement = %d\n"
  4726. "\tfFromRegistry = %d\n"
  4727. "\tfRemove = %d\n"
  4728. "\tfRegisteredFWD = %d\n"
  4729. "\tfRegisteredPRI = %d\n"
  4730. "\tfRegisteredPTR = %d\n"
  4731. "\tfDisableLogging = %d\n"
  4732. "\tRetryCount = %d\n"
  4733. "\tRetryTime = %d\n"
  4734. "\tpRegisterStatus = %p\n"
  4735. "\tSignatureBottom = %08x\n",
  4736. pszHeader,
  4737. pEntry,
  4738. pEntry->SignatureTop,
  4739. pEntry->AdapterName,
  4740. pEntry->HostName,
  4741. pEntry->DomainName,
  4742. pEntry->PrimaryDomainName,
  4743. pEntry->AlternateNames,
  4744. pEntry->AlternateIndex,
  4745. pEntry->HostAddrCount,
  4746. pEntry->HostAddrs,
  4747. pEntry->DnsServerList,
  4748. IP_STRING( pEntry->SentUpdateToIp ),
  4749. IP_STRING( pEntry->SentPriUpdateToIp ),
  4750. pEntry->TTL,
  4751. pEntry->Flags,
  4752. pEntry->fNewElement,
  4753. pEntry->fFromRegistry,
  4754. pEntry->fRemove,
  4755. pEntry->fRegisteredFWD,
  4756. pEntry->fRegisteredPRI,
  4757. pEntry->fRegisteredPTR,
  4758. pEntry->fDisableErrorLogging,
  4759. pEntry->RetryCount,
  4760. pEntry->RetryTime,
  4761. pEntry->pRegisterStatus,
  4762. pEntry->SignatureBottom
  4763. );
  4764. }
  4765. VOID
  4766. AsyncLogUpdateEntry(
  4767. IN PSTR pszHeader,
  4768. IN PUPDATE_ENTRY pEntry
  4769. )
  4770. {
  4771. if ( !pEntry )
  4772. {
  4773. return;
  4774. }
  4775. ASYNCREG_F2( " %s", pszHeader );
  4776. ASYNCREG_F1( " Update Entry" );
  4777. ASYNCREG_F1( " ______________________________________________________" );
  4778. ASYNCREG_F2( " AdapterName : %s", pEntry->AdapterName );
  4779. ASYNCREG_F2( " HostName : %s", pEntry->HostName );
  4780. ASYNCREG_F2( " DomainName : %s", pEntry->DomainName );
  4781. ASYNCREG_F2( " PrimaryDomainName : %s", pEntry->PrimaryDomainName );
  4782. ASYNCREG_F2( " HostAddrCount : %d", pEntry->HostAddrCount );
  4783. DNSLOG_HOST_ENTRYS( pEntry->HostAddrCount,
  4784. pEntry->HostAddrs );
  4785. if ( pEntry->DnsServerList )
  4786. {
  4787. DNSLOG_PIP_ARRAY( pEntry->DnsServerList );
  4788. }
  4789. ASYNCREG_F2( " TTL : %d", pEntry->TTL );
  4790. ASYNCREG_F2( " Flags : %d", pEntry->Flags );
  4791. ASYNCREG_F2( " fNewElement : %d", pEntry->fNewElement );
  4792. ASYNCREG_F2( " fRemove : %d", pEntry->fRemove );
  4793. ASYNCREG_F2( " fRegisteredFWD : %d", pEntry->fRegisteredFWD );
  4794. ASYNCREG_F2( " fRegisteredPRI : %d", pEntry->fRegisteredPRI );
  4795. ASYNCREG_F2( " fRegisteredPTR : %d", pEntry->fRegisteredPTR );
  4796. ASYNCREG_F2( " RetryCount : %d", pEntry->RetryCount );
  4797. ASYNCREG_F2( " RetryTime : %d", pEntry->RetryTime );
  4798. ASYNCREG_F1( "" );
  4799. }
  4800. //
  4801. // Logging
  4802. //
  4803. DWORD RegistrationEventArray[6][6] =
  4804. {
  4805. EVENT_DNSAPI_REGISTRATION_FAILED_TIMEOUT,
  4806. EVENT_DNSAPI_REGISTRATION_FAILED_SERVERFAIL,
  4807. EVENT_DNSAPI_REGISTRATION_FAILED_NOTSUPP,
  4808. EVENT_DNSAPI_REGISTRATION_FAILED_REFUSED,
  4809. EVENT_DNSAPI_REGISTRATION_FAILED_SECURITY,
  4810. EVENT_DNSAPI_REGISTRATION_FAILED_OTHER,
  4811. EVENT_DNSAPI_DEREGISTRATION_FAILED_TIMEOUT,
  4812. EVENT_DNSAPI_DEREGISTRATION_FAILED_SERVERFAIL,
  4813. EVENT_DNSAPI_DEREGISTRATION_FAILED_NOTSUPP,
  4814. EVENT_DNSAPI_DEREGISTRATION_FAILED_REFUSED,
  4815. EVENT_DNSAPI_DEREGISTRATION_FAILED_SECURITY,
  4816. EVENT_DNSAPI_DEREGISTRATION_FAILED_OTHER,
  4817. EVENT_DNSAPI_REGISTRATION_FAILED_NOTSUPP_PRIMARY_DN,
  4818. EVENT_DNSAPI_REGISTRATION_FAILED_REFUSED_PRIMARY_DN,
  4819. EVENT_DNSAPI_REGISTRATION_FAILED_TIMEOUT_PRIMARY_DN,
  4820. EVENT_DNSAPI_REGISTRATION_FAILED_SERVERFAIL_PRIMARY_DN,
  4821. EVENT_DNSAPI_REGISTRATION_FAILED_SECURITY_PRIMARY_DN,
  4822. EVENT_DNSAPI_REGISTRATION_FAILED_OTHER_PRIMARY_DN,
  4823. EVENT_DNSAPI_DEREGISTRATION_FAILED_NOTSUPP_PRIMARY_DN,
  4824. EVENT_DNSAPI_DEREGISTRATION_FAILED_REFUSED_PRIMARY_DN,
  4825. EVENT_DNSAPI_DEREGISTRATION_FAILED_TIMEOUT_PRIMARY_DN,
  4826. EVENT_DNSAPI_DEREGISTRATION_FAILED_SERVERFAIL_PRIMARY_DN,
  4827. EVENT_DNSAPI_DEREGISTRATION_FAILED_SECURITY_PRIMARY_DN,
  4828. EVENT_DNSAPI_DEREGISTRATION_FAILED_OTHER_PRIMARY_DN,
  4829. EVENT_DNSAPI_PTR_REGISTRATION_FAILED_TIMEOUT,
  4830. EVENT_DNSAPI_PTR_REGISTRATION_FAILED_SERVERFAIL,
  4831. EVENT_DNSAPI_PTR_REGISTRATION_FAILED_NOTSUPP,
  4832. EVENT_DNSAPI_PTR_REGISTRATION_FAILED_REFUSED,
  4833. EVENT_DNSAPI_PTR_REGISTRATION_FAILED_SECURITY,
  4834. EVENT_DNSAPI_PTR_REGISTRATION_FAILED_OTHER,
  4835. EVENT_DNSAPI_PTR_DEREGISTRATION_FAILED_TIMEOUT,
  4836. EVENT_DNSAPI_PTR_DEREGISTRATION_FAILED_SERVERFAIL,
  4837. EVENT_DNSAPI_PTR_DEREGISTRATION_FAILED_NOTSUPP,
  4838. EVENT_DNSAPI_PTR_DEREGISTRATION_FAILED_REFUSED,
  4839. EVENT_DNSAPI_PTR_DEREGISTRATION_FAILED_SECURITY,
  4840. EVENT_DNSAPI_PTR_DEREGISTRATION_FAILED_OTHER
  4841. };
  4842. //
  4843. // Map update status to index into table
  4844. //
  4845. // This is the outside -- fast varying -- index
  4846. //
  4847. #define EVENTINDEX_TIMEOUT (0)
  4848. #define EVENTINDEX_SERVFAIL (1)
  4849. #define EVENTINDEX_NOTSUPP (2)
  4850. #define EVENTINDEX_REFUSED (3)
  4851. #define EVENTINDEX_SECURITY (4)
  4852. #define EVENTINDEX_OTHER (5)
  4853. //
  4854. // Map adapter, primary, PTR registration into index into table
  4855. //
  4856. // This index +0 for reg, +1 for dereg gives inside index into
  4857. // event table.
  4858. //
  4859. #define EVENTINDEX_ADAPTER (0)
  4860. #define EVENTINDEX_PRIMARY (2)
  4861. #define EVENTINDEX_PTR (4)
  4862. DWORD
  4863. GetUpdateEventId(
  4864. IN DNS_STATUS Status,
  4865. IN UPTYPE UpType,
  4866. IN BOOL fDeregister,
  4867. OUT PDWORD pdwLevel
  4868. )
  4869. /*++
  4870. Routine Description:
  4871. Get event ID.
  4872. Arguments:
  4873. Status -- status from update call
  4874. fDeregister -- TRUE if deregistration, FALSE for registration
  4875. fPtr -- TRUE if PTR, FALSE for forward
  4876. fPrimary -- TRUE for primary domain name
  4877. Return Value:
  4878. Event Id.
  4879. Zero if no event.
  4880. --*/
  4881. {
  4882. DWORD level = EVENTLOG_WARNING_TYPE;
  4883. DWORD statusIndex;
  4884. DWORD typeIndex;
  4885. //
  4886. // find status code
  4887. //
  4888. switch ( Status )
  4889. {
  4890. case NO_ERROR :
  4891. // success logging in disabled
  4892. return 0;
  4893. case ERROR_TIMEOUT:
  4894. statusIndex = EVENTINDEX_TIMEOUT;
  4895. break;
  4896. case DNS_ERROR_RCODE_SERVER_FAILURE:
  4897. statusIndex = EVENTINDEX_SERVFAIL;
  4898. break;
  4899. case DNS_ERROR_RCODE_NOT_IMPLEMENTED:
  4900. // NOT_IMPL means no update on DNS server, not a client
  4901. // specific problem so informational level
  4902. statusIndex = EVENTINDEX_NOTSUPP;
  4903. level = EVENTLOG_INFORMATION_TYPE;
  4904. break;
  4905. case DNS_ERROR_RCODE_REFUSED:
  4906. statusIndex = EVENTINDEX_REFUSED;
  4907. break;
  4908. case DNS_ERROR_RCODE_BADSIG:
  4909. case DNS_ERROR_RCODE_BADKEY:
  4910. case DNS_ERROR_RCODE_BADTIME:
  4911. statusIndex = EVENTINDEX_SECURITY;
  4912. break;
  4913. default:
  4914. statusIndex = EVENTINDEX_OTHER;
  4915. break;
  4916. }
  4917. //
  4918. // determine interior index for type of update
  4919. // - all PTR logging is at informational level
  4920. // - dereg events are one group behind registration events
  4921. // in table; just inc index
  4922. if ( IS_UPTYPE_PTR(UpType) )
  4923. {
  4924. typeIndex = EVENTINDEX_PTR;
  4925. }
  4926. else if ( IS_UPTYPE_PRIMARY(UpType) )
  4927. {
  4928. typeIndex = EVENTINDEX_PRIMARY;
  4929. }
  4930. else
  4931. {
  4932. typeIndex = EVENTINDEX_ADAPTER;
  4933. }
  4934. if ( fDeregister )
  4935. {
  4936. typeIndex++;
  4937. }
  4938. //
  4939. // get event from table
  4940. //
  4941. *pdwLevel = level;
  4942. return RegistrationEventArray[ typeIndex ][ statusIndex ];
  4943. }
  4944. VOID
  4945. LogRegistration(
  4946. IN PUPDATE_ENTRY pUpdateEntry,
  4947. IN DNS_STATUS Status,
  4948. IN DWORD UpType,
  4949. IN BOOL fDeregister,
  4950. IN IP4_ADDRESS DnsIp,
  4951. IN IP4_ADDRESS UpdateIp
  4952. )
  4953. /*++
  4954. Routine Description:
  4955. Log register\deregister failure.
  4956. Arguments:
  4957. pUpdateEntry -- update entry being executed
  4958. Status -- status from update call
  4959. Type -- UPTYPE (PRIMARY, ADAPTER, PTR)
  4960. fDeregister -- TRUE if deregistration, FALSE for registration
  4961. DnsIp -- DNS server IP that failed update
  4962. UpdateIp -- IP we tried to update
  4963. Return Value:
  4964. None
  4965. --*/
  4966. {
  4967. PSTR insertStrings[ 7 ];
  4968. CHAR serverIpBuffer[ IP4_ADDRESS_STRING_BUFFER_LENGTH ];
  4969. CHAR serverListBuffer[ (IP4_ADDRESS_STRING_BUFFER_LENGTH+2)*9 ];
  4970. CHAR ipListBuffer[ (IP4_ADDRESS_STRING_BUFFER_LENGTH+2)*9 ];
  4971. CHAR hostnameBuffer[ DNS_MAX_NAME_BUFFER_LENGTH ];
  4972. CHAR domainBuffer[ DNS_MAX_NAME_BUFFER_LENGTH*2 ];
  4973. CHAR errorCodeBuffer[ 25 ];
  4974. DWORD iter;
  4975. IP4_ADDRESS ip;
  4976. PSTR pname;
  4977. DWORD eventId;
  4978. DWORD level;
  4979. DNSDBG( TRACE, (
  4980. "LogRegistration()\n"
  4981. "\tpEntry = %p\n"
  4982. "\tStatus = %d\n"
  4983. "\tUpType = %d\n"
  4984. "\tfDereg = %d\n"
  4985. "\tDNS IP = %s\n"
  4986. "\tUpdate IP = %s\n",
  4987. pUpdateEntry,
  4988. Status,
  4989. UpType,
  4990. fDeregister,
  4991. IP_STRING( DnsIp ),
  4992. IP_STRING( UpdateIp ) ));
  4993. //
  4994. // not logging?
  4995. // - no success logging
  4996. // - disabled
  4997. // - on DNS server (which registers itself)
  4998. //
  4999. if ( Status == NO_ERROR ||
  5000. pUpdateEntry->fDisableErrorLogging ||
  5001. g_IsDnsServer )
  5002. {
  5003. return;
  5004. }
  5005. //
  5006. // adapter name
  5007. //
  5008. insertStrings[0] = pUpdateEntry->AdapterName;
  5009. //
  5010. // hostname
  5011. //
  5012. Dns_NameCopy(
  5013. (PCHAR) hostnameBuffer,
  5014. NULL,
  5015. pUpdateEntry->HostName,
  5016. 0,
  5017. DnsCharSetUtf8,
  5018. DnsCharSetAnsi );
  5019. insertStrings[1] = hostnameBuffer;
  5020. //
  5021. // domain name
  5022. // - name depends on type
  5023. // - if no name, no logging
  5024. if ( IS_UPTYPE_PTR(UpType) )
  5025. {
  5026. pname = pUpdateEntry->PrimaryDomainName;
  5027. if ( !pname )
  5028. {
  5029. pname = pUpdateEntry->DomainName;
  5030. }
  5031. }
  5032. else if ( IS_UPTYPE_PRIMARY(UpType) )
  5033. {
  5034. pname = pUpdateEntry->PrimaryDomainName;
  5035. }
  5036. else
  5037. {
  5038. pname = pUpdateEntry->DomainName;
  5039. }
  5040. if ( !pname )
  5041. {
  5042. return;
  5043. }
  5044. Dns_NameCopy(
  5045. (PCHAR) domainBuffer,
  5046. NULL,
  5047. pname,
  5048. 0,
  5049. DnsCharSetUtf8,
  5050. DnsCharSetAnsi );
  5051. insertStrings[2] = domainBuffer;
  5052. //
  5053. // DNS server list
  5054. // - layout comma separated, four per line, limit 8
  5055. {
  5056. PCHAR pch = serverListBuffer;
  5057. DWORD count = 0;
  5058. *pch = 0;
  5059. if ( pUpdateEntry->DnsServerList )
  5060. {
  5061. count = pUpdateEntry->DnsServerList->AddrCount;
  5062. }
  5063. for ( iter=0; iter < count; iter++ )
  5064. {
  5065. if ( iter == 0 )
  5066. {
  5067. strcpy( pch, "\t" );
  5068. pch++;
  5069. }
  5070. else
  5071. {
  5072. *pch++ = ',';
  5073. *pch++ = ' ';
  5074. if ( iter == 4 )
  5075. {
  5076. strcpy( pch, "\r\n\t" );
  5077. pch += 3;
  5078. }
  5079. else if ( iter > 8 )
  5080. {
  5081. strcpy( pch, "..." );
  5082. break;
  5083. }
  5084. }
  5085. pch = Dns_Ip4AddressToString_A(
  5086. pch,
  5087. & pUpdateEntry->DnsServerList->AddrArray[iter]
  5088. );
  5089. }
  5090. if ( pch == serverListBuffer )
  5091. {
  5092. strcpy( serverListBuffer, "\t<?>" );
  5093. }
  5094. insertStrings[3] = serverListBuffer;
  5095. }
  5096. //
  5097. // DNS server IP
  5098. //
  5099. ip = DnsIp;
  5100. if ( ip == 0 )
  5101. {
  5102. if ( IS_UPTYPE_PRIMARY(UpType) )
  5103. {
  5104. ip = pUpdateEntry->SentPriUpdateToIp;
  5105. }
  5106. else
  5107. {
  5108. ip = pUpdateEntry->SentUpdateToIp;
  5109. }
  5110. }
  5111. if ( ip )
  5112. {
  5113. sprintf(
  5114. serverIpBuffer,
  5115. "%d.%d.%d.%d",
  5116. (ip & 0xff),
  5117. ((ip>8) & 0xff),
  5118. ((ip>16) & 0xff),
  5119. ((ip>24) & 0xff) );
  5120. }
  5121. else
  5122. {
  5123. strcpy( serverIpBuffer, "<?>" );
  5124. }
  5125. insertStrings[4] = serverIpBuffer;
  5126. //
  5127. // Update IP
  5128. // - passed in (for PTR)
  5129. // - OR get IP list from update entry
  5130. // - layout comma separated, four per line, limit 8
  5131. //
  5132. ip = UpdateIp;
  5133. if ( ip )
  5134. {
  5135. sprintf(
  5136. ipListBuffer,
  5137. "%d.%d.%d.%d",
  5138. (ip & 0xff),
  5139. ((ip>8) & 0xff),
  5140. ((ip>16) & 0xff),
  5141. ((ip>24) & 0xff) );
  5142. }
  5143. else
  5144. {
  5145. DWORD count = pUpdateEntry->HostAddrCount;
  5146. PCHAR pch = ipListBuffer;
  5147. *pch = 0;
  5148. for ( iter=0; iter < count; iter++ )
  5149. {
  5150. if ( iter > 0 )
  5151. {
  5152. *pch++ = ',';
  5153. *pch++ = ' ';
  5154. if ( iter == 4 )
  5155. {
  5156. strcpy( pch, "\r\n\t" );
  5157. pch += 3;
  5158. }
  5159. else if ( iter > 8 )
  5160. {
  5161. strcpy( pch, "..." );
  5162. break;
  5163. }
  5164. }
  5165. pch = Dns_Ip4AddressToString_A(
  5166. pch,
  5167. & pUpdateEntry->HostAddrs[iter].Addr.ipAddr );
  5168. }
  5169. if ( pch == ipListBuffer )
  5170. {
  5171. strcpy( ipListBuffer, "<?>" );
  5172. }
  5173. }
  5174. insertStrings[5] = ipListBuffer;
  5175. // terminate insert string array
  5176. insertStrings[6] = NULL;
  5177. //
  5178. // get event ID for type of update and update status
  5179. //
  5180. eventId = GetUpdateEventId(
  5181. Status,
  5182. UpType,
  5183. fDeregister,
  5184. & level );
  5185. if ( !eventId )
  5186. {
  5187. DNS_ASSERT( FALSE );
  5188. return;
  5189. }
  5190. //
  5191. // log the event
  5192. //
  5193. DNSDBG( TRACE, (
  5194. "Logging registration event:\n"
  5195. "\tid = %d\n"
  5196. "\tlevel = %d\n"
  5197. "\tstatus = %d\n"
  5198. "\tfor uptype = %d\n",
  5199. eventId,
  5200. level,
  5201. Status,
  5202. UpType ));
  5203. DnsLogEvent(
  5204. eventId,
  5205. (WORD) level,
  5206. 7,
  5207. insertStrings,
  5208. Status );
  5209. }
  5210. //
  5211. // End asyncreg.c
  5212. //