Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3072 lines
72 KiB

  1. /*++
  2. Copyright (c) 1996-2002 Microsoft Corporation
  3. Module Name:
  4. update.c
  5. Abstract:
  6. Domain Name System (DNS) API
  7. Update client routines.
  8. Author:
  9. Jim Gilroy (jamesg) October, 1996
  10. Revision History:
  11. --*/
  12. #include "local.h"
  13. #include "dnssec.h"
  14. //
  15. // Security flag check
  16. //
  17. #define UseSystemDefaultForSecurity(flag) \
  18. ( ((flag) & DNS_UPDATE_SECURITY_CHOICE_MASK) \
  19. == DNS_UPDATE_SECURITY_USE_DEFAULT )
  20. //
  21. // Local update flag
  22. // - must make sure this is in UPDATE_RESERVED space
  23. //
  24. #define DNS_UPDATE_LOCAL_COPY (0x00010000)
  25. //
  26. // DCR_DELETE: this is stupid
  27. //
  28. #define DNS_UNACCEPTABLE_UPDATE_OPTIONS \
  29. (~ \
  30. ( DNS_UPDATE_SECURITY_OFF | \
  31. DNS_UPDATE_CACHE_SECURITY_CONTEXT | \
  32. DNS_UPDATE_SECURITY_ON | \
  33. DNS_UPDATE_FORCE_SECURITY_NEGO | \
  34. DNS_UPDATE_TRY_ALL_MASTER_SERVERS | \
  35. DNS_UPDATE_REMOTE_SERVER | \
  36. DNS_UPDATE_LOCAL_COPY | \
  37. DNS_UPDATE_SECURITY_ONLY ))
  38. //
  39. // Update Timeouts
  40. //
  41. // note, max is a little longer than might be expected as DNS server
  42. // may have to contact primary and wait for primary to do update (inc.
  43. // disk access) then response
  44. //
  45. #define INITIAL_UPDATE_TIMEOUT (4) // 4 seconds
  46. #define MAX_UPDATE_TIMEOUT (60) // 60 seconds
  47. //
  48. // Private prototypes
  49. //
  50. DNS_STATUS
  51. Dns_DoSecureUpdate(
  52. IN PDNS_MSG_BUF pMsgSend,
  53. OUT PDNS_MSG_BUF pMsgRecv,
  54. IN OUT PHANDLE phContext,
  55. IN DWORD dwFlag,
  56. IN PDNS_NETINFO pNetworkInfo,
  57. IN PADDR_ARRAY pServerList,
  58. IN PWSTR pszNameServer,
  59. IN PCHAR pCreds,
  60. IN PCHAR pszContext
  61. );
  62. //
  63. // Update execution routines
  64. //
  65. VOID
  66. Update_SaveResults(
  67. IN OUT PUPDATE_BLOB pBlob,
  68. IN DWORD Status,
  69. IN DWORD Rcode,
  70. IN PDNS_ADDR pServerAddr
  71. )
  72. /*++
  73. Routine Description:
  74. Save update results.
  75. Arguments:
  76. pBlob -- update info blob
  77. Status -- update status
  78. Rcode -- returned RCODE
  79. ServerIp -- server attempted update at
  80. Return Value:
  81. ERROR_SUCCESS if successful.
  82. Error status on failure.
  83. --*/
  84. {
  85. PDNS_EXTRA_INFO pextra = (PDNS_EXTRA_INFO) pBlob->pExtraInfo;
  86. //
  87. // results - save to blob
  88. //
  89. pBlob->fSavedResults = TRUE;
  90. Util_SetBasicResults(
  91. & pBlob->Results,
  92. Status,
  93. Rcode,
  94. pServerAddr );
  95. //
  96. // find and set extra info result blob (if any)
  97. //
  98. ExtraInfo_SetBasicResults(
  99. pBlob->pExtraInfo,
  100. & pBlob->Results );
  101. //
  102. // backward compat update results
  103. //
  104. if ( pServerAddr )
  105. {
  106. pextra = ExtraInfo_FindInList(
  107. pBlob->pExtraInfo,
  108. DNS_EXINFO_ID_RESULTS_V1 );
  109. if ( pextra )
  110. {
  111. pextra->ResultsV1.Rcode = (WORD)Rcode;
  112. pextra->ResultsV1.Status = Status;
  113. if ( DnsAddr_IsIp4( pServerAddr ) )
  114. {
  115. pextra->ResultsV1.ServerIp4 = DnsAddr_GetIp4( pServerAddr );
  116. }
  117. else
  118. {
  119. DNS_ASSERT( DnsAddr_IsIp6( pServerAddr ) );
  120. DnsAddr_WriteIp6(
  121. & pextra->ResultsV1.ServerIp6,
  122. pServerAddr );
  123. }
  124. }
  125. }
  126. }
  127. DNS_STATUS
  128. Update_Send(
  129. IN OUT PUPDATE_BLOB pBlob
  130. )
  131. /*++
  132. Routine Description:
  133. Send DNS update.
  134. This is the core update send routine that does
  135. - packet build
  136. - send
  137. - secure fail over
  138. - result data (if required)
  139. This routine does NOT do FAZ or cache cleanup (see Update_FazSendFlush()).
  140. Arguments:
  141. pBlob -- update info blob
  142. Return Value:
  143. ERROR_SUCCESS if successful.
  144. Error status on failure.
  145. --*/
  146. {
  147. PDNS_MSG_BUF pmsgSend = NULL;
  148. PDNS_MSG_BUF pmsgRecv = NULL;
  149. DNS_STATUS status = NO_ERROR;
  150. WORD length;
  151. PWSTR pzone;
  152. PWSTR pserverName;
  153. PCHAR pcreds = NULL;
  154. BOOL fsecure = FALSE;
  155. BOOL fswitchToTcp = FALSE;
  156. DNS_HEADER header;
  157. BYTE rcode = 0;
  158. DNS_ADDR servAddr;
  159. PDNS_ADDR pservAddr = NULL;
  160. PADDR_ARRAY pserverArray = NULL;
  161. PDNS_NETINFO pnetInfo = NULL;
  162. PDNS_NETINFO pnetInfoLocal = NULL;
  163. SEND_BLOB sendBlob;
  164. DNSDBG( UPDATE, (
  165. "Update_Send( %p )\n",
  166. pBlob ));
  167. IF_DNSDBG( UPDATE )
  168. {
  169. DnsDbg_UpdateBlob( "Entering Update_Send", pBlob );
  170. }
  171. //
  172. // build netinfo if missing
  173. //
  174. pnetInfo = pBlob->pNetInfo;
  175. if ( !pnetInfo )
  176. {
  177. if ( pBlob->pServerList )
  178. {
  179. pnetInfoLocal = NetInfo_CreateForUpdate(
  180. pBlob->pszZone,
  181. pBlob->pszServerName,
  182. pBlob->pServerList,
  183. 0 );
  184. if ( !pnetInfoLocal )
  185. {
  186. status = ERROR_INVALID_PARAMETER;
  187. goto Cleanup;
  188. }
  189. }
  190. pnetInfo = pnetInfoLocal;
  191. }
  192. //
  193. // get info from netinfo
  194. // - must be update netinfo blob
  195. //
  196. if ( ! NetInfo_IsForUpdate(pnetInfo) )
  197. {
  198. status = ERROR_INVALID_PARAMETER;
  199. goto Cleanup;
  200. }
  201. pzone = NetInfo_UpdateZoneName( pnetInfo );
  202. pserverArray = NetInfo_ConvertToAddrArray(
  203. pnetInfo,
  204. NULL, // all adapters
  205. 0 // no addr family
  206. );
  207. pserverName = NetInfo_UpdateServerName( pnetInfo );
  208. if ( !pzone || !pserverArray )
  209. {
  210. status = ERROR_INVALID_PARAMETER;
  211. goto Cleanup;
  212. }
  213. //
  214. // build recv message buffer
  215. // - must be big enough for TCP
  216. //
  217. pmsgRecv = Dns_AllocateMsgBuf( DNS_TCP_DEFAULT_PACKET_LENGTH );
  218. if ( !pmsgRecv )
  219. {
  220. status = DNS_ERROR_NO_MEMORY;
  221. goto Cleanup;
  222. }
  223. //
  224. // build update packet
  225. // note currently this function allocates TCP sized buffer if records
  226. // given; if this changes need to alloc TCP buffer here
  227. //
  228. CLEAR_DNS_HEADER_FLAGS_AND_XID( &header );
  229. header.Opcode = DNS_OPCODE_UPDATE;
  230. pmsgSend = Dns_BuildPacket(
  231. &header, // copy header
  232. TRUE, // ... but not header counts
  233. (PDNS_NAME) pzone, // question zone\type SOA
  234. DNS_TYPE_SOA,
  235. pBlob->pRecords,
  236. DNSQUERY_UNICODE_NAME, // no other flags
  237. TRUE // building an update packet
  238. );
  239. if ( !pmsgSend )
  240. {
  241. DNS_PRINT(( "ERROR: failed send buffer allocation.\n" ));
  242. status = DNS_ERROR_NO_MEMORY;
  243. goto Cleanup;
  244. }
  245. //
  246. // init send blob
  247. //
  248. // note: do NOT set server array here as update
  249. // network info blob (from FAZ or built
  250. // from passed in array ourselves) takes precedence
  251. //
  252. RtlZeroMemory( &sendBlob, sizeof(sendBlob) );
  253. sendBlob.pSendMsg = pmsgSend;
  254. sendBlob.pNetInfo = pnetInfo;
  255. //sendBlob.pServerArray = pserverArray;
  256. sendBlob.Flags = pBlob->Flags;
  257. sendBlob.fSaveResponse = TRUE;
  258. sendBlob.Results.pMessage = pmsgRecv;
  259. sendBlob.pRecvMsgBuf = pmsgRecv;
  260. //
  261. // try non-secure first unless explicitly secure only
  262. //
  263. fsecure = (pBlob->Flags & DNS_UPDATE_SECURITY_ONLY);
  264. if ( !fsecure )
  265. {
  266. status = Send_AndRecv( &sendBlob );
  267. // QUESTION: is this adequate to preserve precon fail RCODEs
  268. // does Send_AndRecv() always give success to valid response
  269. if ( status == ERROR_SUCCESS )
  270. {
  271. rcode = pmsgRecv->MessageHead.ResponseCode;
  272. status = Dns_MapRcodeToStatus( rcode );
  273. }
  274. if ( status != DNS_ERROR_RCODE_REFUSED ||
  275. pBlob->Flags & DNS_UPDATE_SECURITY_OFF )
  276. {
  277. goto Cleanup;
  278. }
  279. DNSDBG( UPDATE, (
  280. "Failed unsecure update, switching to secure!\n"
  281. "\tcurrent time (ms) = %d\n",
  282. GetCurrentTime() ));
  283. fsecure = TRUE;
  284. }
  285. //
  286. // security
  287. // - must have server name
  288. // - must start package
  289. //
  290. if ( fsecure )
  291. {
  292. if ( !pserverName )
  293. {
  294. status = ERROR_INVALID_PARAMETER;
  295. goto Cleanup;
  296. }
  297. status = Dns_StartSecurity( FALSE );
  298. if ( status != ERROR_SUCCESS )
  299. {
  300. goto Cleanup;
  301. }
  302. //
  303. // DCR: hCreds doesn't return security context
  304. // - idea of something beyond just standard security
  305. // credentials was we'd been able to return the context
  306. // handle
  307. //
  308. // DCR_FIX0: Secure update needs to be non-IP4_ARRAY
  309. //
  310. pcreds = Dns_GetApiContextCredentials( pBlob->hCreds );
  311. status = Dns_DoSecureUpdate(
  312. pmsgSend,
  313. pmsgRecv,
  314. NULL,
  315. pBlob->Flags,
  316. pnetInfo,
  317. pserverArray,
  318. pserverName,
  319. pcreds, // initialized in DnsAcquireContextHandle
  320. NULL // default context name
  321. );
  322. if ( status == ERROR_SUCCESS )
  323. {
  324. rcode = pmsgRecv->MessageHead.ResponseCode;
  325. status = Dns_MapRcodeToStatus( rcode );
  326. }
  327. }
  328. Cleanup:
  329. //
  330. // result info
  331. //
  332. // DCR: note not perfect info on whether actually got to send
  333. //
  334. // DCR: could be a case with UDP where receive message is NOT
  335. // the message we sent to
  336. // would only occur if non-FAZ server array of multiple entries
  337. // and timeout on first
  338. //
  339. // FIX6: serverIP and rcode should be handled in send code
  340. //
  341. if ( pmsgSend && pmsgRecv )
  342. {
  343. pservAddr = &servAddr;
  344. DnsAddr_Copy( pservAddr, &pmsgSend->RemoteAddress );
  345. rcode = pmsgRecv->MessageHead.ResponseCode;
  346. #if 0
  347. if ( (rcode || status==NO_ERROR) && !pmsgRecv->fTcp )
  348. {
  349. DnsAddr_Copy( pservAddr, &pmsgRecv->RemoteAddress );
  350. }
  351. #endif
  352. }
  353. // save results
  354. Update_SaveResults(
  355. pBlob,
  356. status,
  357. rcode,
  358. pservAddr );
  359. // return recv message buffer
  360. if ( pBlob->fSaveRecvMsg )
  361. {
  362. pBlob->pMsgRecv = pmsgRecv;
  363. }
  364. else
  365. {
  366. FREE_HEAP( pmsgRecv );
  367. pBlob->pMsgRecv = NULL;
  368. }
  369. FREE_HEAP( pmsgSend);
  370. FREE_HEAP( pserverArray );
  371. NetInfo_Free( pnetInfoLocal );
  372. // winsock cleanup if we started
  373. GUI_MODE_SETUP_WS_CLEANUP( g_InNTSetupMode );
  374. DNSDBG( UPDATE, (
  375. "Leave Update_Send() => %d %s.\n\n",
  376. status,
  377. Dns_StatusString(status) ));
  378. return( status );
  379. }
  380. DNS_STATUS
  381. Update_FazSendFlush(
  382. IN OUT PUPDATE_BLOB pBlob
  383. )
  384. /*++
  385. Routine Description:
  386. Send DNS update.
  387. Arguments:
  388. pBlob -- update info blob
  389. Return Value:
  390. ERROR_SUCCESS if successful.
  391. Error status on failure.
  392. --*/
  393. {
  394. DNS_STATUS status;
  395. PDNS_NETINFO plocalNetworkInfo = NULL;
  396. PDNS_NETINFO pnetInfo = pBlob->pNetInfo;
  397. DNSDBG( TRACE, ( "Update_FazSendFlush( %p )\n", pBlob ));
  398. IF_DNSDBG( UPDATE )
  399. {
  400. DnsDbg_UpdateBlob( "Entering Update_FazSendFlush", pBlob );
  401. }
  402. //
  403. // read update config
  404. //
  405. Reg_RefreshUpdateConfig();
  406. //
  407. // need to build update adapter list from FAZ
  408. // - only pass on BYPASS_CACHE flag
  409. // - note FAZ will append DNS_QUERY_ALLOW_EMPTY_AUTH_RESP
  410. // flag yet DnsQuery() will fail on that flag without
  411. // BYPASS_CACHE also set
  412. //
  413. if ( ! NetInfo_IsForUpdate(pnetInfo) )
  414. {
  415. status = Faz_Private(
  416. pBlob->pRecords->pName,
  417. DNS_QUERY_BYPASS_CACHE,
  418. NULL, // no specified servers
  419. & plocalNetworkInfo );
  420. if ( status != ERROR_SUCCESS )
  421. {
  422. return( status );
  423. }
  424. pnetInfo = plocalNetworkInfo;
  425. pBlob->pNetInfo = pnetInfo;
  426. }
  427. //
  428. // call update send routine
  429. //
  430. status = Update_Send( pBlob );
  431. //
  432. // if updated name -- flush cache entry for name
  433. //
  434. if ( status == ERROR_SUCCESS )
  435. {
  436. DnsFlushResolverCacheEntry_W(
  437. pBlob->pRecords->pName );
  438. }
  439. //
  440. // if there was an error sending the update, flush the resolver
  441. // cache entry for the zone name to possibly pick up an alternate
  442. // DNS server for the next retry attempt of a similar update.
  443. //
  444. // DCR_QUESTION: is this the correct error code?
  445. // maybe ERROR_TIMED_OUT?
  446. //
  447. // DCR: update flushes don't make sense
  448. // 1) FAZ bypasses cache, so comment really isn't the problem
  449. // 2) ought to flush name itself anytime we can
  450. //
  451. if ( status == DNS_ERROR_RECORD_TIMED_OUT )
  452. {
  453. PWSTR pzoneName;
  454. if ( pnetInfo &&
  455. (pzoneName = NetInfo_UpdateZoneName( pnetInfo )) )
  456. {
  457. DnsFlushResolverCacheEntry_W( pzoneName );
  458. DnsFlushResolverCacheEntry_W( pBlob->pRecords->pName );
  459. }
  460. }
  461. // cleanup local adapter list if used
  462. if ( plocalNetworkInfo )
  463. {
  464. NetInfo_Free( plocalNetworkInfo );
  465. if ( pBlob->pNetInfo == plocalNetworkInfo )
  466. {
  467. pBlob->pNetInfo = NULL;
  468. }
  469. }
  470. DNSDBG( TRACE, (
  471. "Leave Update_FazSendFlush( %p ) => %d\n",
  472. pBlob,
  473. status ));
  474. return( status );
  475. }
  476. DNS_STATUS
  477. Update_MultiMaster(
  478. IN OUT PUPDATE_BLOB pBlob
  479. )
  480. /*++
  481. Routine Description:
  482. Do multi-master update.
  483. Arguments:
  484. pBlob -- update info blob
  485. note: IP4 array ignored, must be converted to DNS_ADDR higher.
  486. Return Value:
  487. ERROR_SUCCESS if successful.
  488. ErrorCode on failure.
  489. --*/
  490. {
  491. PDNS_NETINFO pnetInfo = NULL;
  492. PADDR_ARRAY pnsList = NULL;
  493. PADDR_ARRAY pbadServerList = NULL;
  494. PADDR_ARRAY plocalAddrs = NULL;
  495. DNS_STATUS status = DNS_ERROR_NO_DNS_SERVERS;
  496. DWORD iter;
  497. PDNS_ADDR pfailedAddr;
  498. BOOL fremoteUpdate = (pBlob->Flags & DNS_UPDATE_REMOTE_SERVER);
  499. DWORD savedStatus;
  500. BASIC_RESULTS savedRemoteResults;
  501. BASIC_RESULTS savedLocalResults;
  502. BOOL isLocal = FALSE;
  503. BOOL fdoneLocal = FALSE;
  504. BOOL fdoneRemote = FALSE;
  505. BOOL fdoneRemoteSuccess = FALSE;
  506. DNSDBG( UPDATE, (
  507. "\nUpdate_MultiMaster( %p )\n", pBlob ));
  508. IF_DNSDBG( UPDATE )
  509. {
  510. DnsDbg_UpdateBlob( "Entering Update_MultiMaster", pBlob );
  511. }
  512. DNS_ASSERT( !pBlob->fSaveRecvMsg );
  513. pBlob->fSaveRecvMsg = FALSE;
  514. //
  515. // read NS list for zone
  516. //
  517. pnsList = GetNameServersListForDomain(
  518. pBlob->pszZone,
  519. pBlob->pServerList );
  520. if ( !pnsList )
  521. {
  522. return status;
  523. }
  524. //
  525. // validate failed IP
  526. //
  527. pfailedAddr = &pBlob->FailedServer;
  528. if ( DnsAddr_IsEmpty(pfailedAddr) )
  529. {
  530. pfailedAddr = NULL;
  531. }
  532. if ( pfailedAddr &&
  533. pnsList->AddrCount == 1 &&
  534. DAddr_IsEqual(
  535. pfailedAddr,
  536. & pnsList->AddrArray[0] ) )
  537. {
  538. status = ERROR_TIMEOUT;
  539. goto Done;
  540. }
  541. //
  542. // create bad server list
  543. // - init with any previous failed DNS server
  544. //
  545. pbadServerList = DnsAddrArray_Create( pnsList->AddrCount + 1 );
  546. if ( !pbadServerList )
  547. {
  548. status = DNS_ERROR_NO_MEMORY;
  549. goto Done;
  550. }
  551. if ( pfailedAddr )
  552. {
  553. DnsAddrArray_AddAddr(
  554. pbadServerList,
  555. pfailedAddr,
  556. 0, // no family screen
  557. 0 // no dup screen
  558. );
  559. }
  560. //
  561. // get local IP list
  562. //
  563. if ( fremoteUpdate )
  564. {
  565. plocalAddrs = NetInfo_GetLocalAddrArray(
  566. pBlob->pNetInfo,
  567. NULL, // no specific adapter
  568. 0, // no specific family
  569. 0, // no flags
  570. FALSE // no force, should have recent copy
  571. );
  572. }
  573. //
  574. // init results
  575. //
  576. RtlZeroMemory( &savedRemoteResults, sizeof(savedRemoteResults) );
  577. RtlZeroMemory( &savedLocalResults, sizeof(savedLocalResults) );
  578. //
  579. // attempt update against each multi-master DNS server
  580. //
  581. // identify multi-master servers as those which return their themselves
  582. // as the authoritative server when do FAZ query
  583. //
  584. for ( iter = 0; iter < pnsList->AddrCount; iter++ )
  585. {
  586. PDNS_ADDR pservAddr = &pnsList->AddrArray[iter];
  587. PDNS_ADDR pfazAddr;
  588. ADDR_ARRAY ipArray;
  589. //
  590. // already attempted this server?
  591. //
  592. if ( AddrArray_ContainsAddr( pbadServerList, pservAddr ) )
  593. {
  594. DNSDBG( UPDATE, (
  595. "MultiMaster skip update to bad IP %s.\n",
  596. DNSADDR_STRING(pservAddr) ));
  597. continue;
  598. }
  599. //
  600. // if require remote, screen out local server
  601. //
  602. // note: currently updating both local and one remote
  603. // could do just remote
  604. //
  605. if ( fremoteUpdate )
  606. {
  607. isLocal = LocalIp_IsAddrLocal( pservAddr, plocalAddrs, NULL );
  608. if ( isLocal )
  609. {
  610. DNSDBG( UPDATE, (
  611. "MultiMaster local IP %s -- IsDns %d.\n",
  612. DNSADDR_STRING( pservAddr ),
  613. g_IsDnsServer ));
  614. if ( fdoneLocal )
  615. {
  616. DNSDBG( UPDATE, (
  617. "MultiMaster skip local IP %s after local.\n",
  618. DNSADDR_STRING( pservAddr ) ));
  619. continue;
  620. }
  621. }
  622. else if ( fdoneRemoteSuccess )
  623. {
  624. DNSDBG( UPDATE, (
  625. "MultiMaster skip remote IP %s after success remote.\n",
  626. DNSADDR_STRING( pservAddr ) ));
  627. continue;
  628. }
  629. }
  630. //
  631. // FAZ to get primary "seen" by this NS
  632. //
  633. DnsAddrArray_InitSingleWithAddr(
  634. & ipArray,
  635. pservAddr );
  636. DNSDBG( UPDATE, (
  637. "MultiMaster FAZ to %s.\n",
  638. DNSADDR_STRING( pservAddr ) ));
  639. status = DoQuickFAZ(
  640. &pnetInfo,
  641. pBlob->pszZone,
  642. &ipArray );
  643. if ( status != ERROR_SUCCESS )
  644. {
  645. DNSDBG( UPDATE, (
  646. "MultiMaster skip IP %s on FAZ failure => %d.\n",
  647. DNSADDR_STRING( pservAddr ),
  648. status ));
  649. continue;
  650. }
  651. DNS_ASSERT( pnetInfo->AdapterCount == 1 );
  652. DNS_ASSERT( pnetInfo->AdapterArray[0].pDnsAddrs );
  653. //
  654. // check FAZ result IP
  655. // - if different from server, use it
  656. // - but verify not in bad\previous list
  657. //
  658. pfazAddr = &pnetInfo->AdapterArray[0].pDnsAddrs->AddrArray[0];
  659. if ( !DnsAddr_IsEqual( pservAddr, pfazAddr, DNSADDR_MATCH_ADDR ) )
  660. {
  661. if ( DnsAddrArray_ContainsAddr(
  662. pbadServerList,
  663. pfazAddr,
  664. DNSADDR_MATCH_ADDR ) )
  665. {
  666. DNSDBG( UPDATE, (
  667. "MultiMaster skip FAZ result IP %s -- bad list.\n",
  668. DNSADDR_STRING( pservAddr ) ));
  669. NetInfo_Free( pnetInfo );
  670. pnetInfo = NULL;
  671. continue;
  672. }
  673. pservAddr = pfazAddr;
  674. }
  675. DNSDBG( UPDATE, (
  676. "MultiMaster update to %s.\n",
  677. DNSADDR_STRING( pservAddr ) ));
  678. pBlob->pNetInfo = pnetInfo;
  679. status = Update_FazSendFlush( pBlob );
  680. pBlob->pNetInfo = NULL;
  681. //
  682. // save results
  683. // - save local result (we assume there should only be one and
  684. // if more than one result should be the same)
  685. // - save best remote result; NO_ERROR tops, otherwise highest
  686. // error is best
  687. //
  688. if ( isLocal )
  689. {
  690. fdoneLocal = TRUE;
  691. RtlCopyMemory(
  692. &savedLocalResults,
  693. &pBlob->Results,
  694. sizeof( savedLocalResults ) );
  695. }
  696. else
  697. {
  698. BOOL fsaveResults = FALSE;
  699. if ( status == ERROR_SUCCESS )
  700. {
  701. fsaveResults = !fdoneRemoteSuccess;
  702. fdoneRemoteSuccess = TRUE;
  703. }
  704. else
  705. {
  706. fsaveResults = !fdoneRemoteSuccess &&
  707. status > savedRemoteResults.Status;
  708. }
  709. if ( fsaveResults )
  710. {
  711. fdoneRemote = TRUE;
  712. RtlCopyMemory(
  713. &savedRemoteResults,
  714. &pBlob->Results,
  715. sizeof( savedRemoteResults ) );
  716. }
  717. }
  718. //
  719. // check for continue
  720. // - timeouts
  721. // - all-master updates
  722. // - require remote server update (but we save success IP
  723. // and screen above)
  724. //
  725. // other cases stop once a single update completes
  726. //
  727. // DCR: continue multi-master-update until success?
  728. // DCR: not supporting some servers update-on others off
  729. // you can have case here where some servers are configured to
  730. // accept update and some are not
  731. if ( status == ERROR_TIMEOUT ||
  732. status == DNS_RCODE_SERVER_FAILURE )
  733. {
  734. }
  735. else if ( fremoteUpdate ||
  736. ( pBlob->Flags & DNS_UPDATE_TRY_ALL_MASTER_SERVERS ) )
  737. {
  738. }
  739. else
  740. {
  741. break;
  742. }
  743. // continue -- screen off this IP
  744. AddrArray_AddAddr(
  745. pbadServerList,
  746. pservAddr );
  747. // cleanup FAZ netinfo
  748. // - doing this last as FAZ IP is pointer into this struct
  749. NetInfo_Free( pnetInfo );
  750. pnetInfo = NULL;
  751. continue;
  752. }
  753. Done:
  754. //
  755. // set best results
  756. //
  757. {
  758. PBASIC_RESULTS presults = NULL;
  759. if ( fdoneRemote )
  760. {
  761. presults = &savedRemoteResults;
  762. }
  763. else if ( fdoneLocal )
  764. {
  765. presults = &savedLocalResults;
  766. }
  767. if ( presults )
  768. {
  769. Update_SaveResults(
  770. pBlob,
  771. presults->Status,
  772. presults->Rcode,
  773. &presults->ServerAddr );
  774. status = presults->Status;
  775. }
  776. }
  777. FREE_HEAP( pnsList );
  778. FREE_HEAP( pbadServerList );
  779. FREE_HEAP( plocalAddrs );
  780. NetInfo_Free( pnetInfo );
  781. return status;
  782. }
  783. DNS_STATUS
  784. Update_Private(
  785. IN OUT PUPDATE_BLOB pBlob
  786. )
  787. /*++
  788. Routine Description:
  789. Main private update routine.
  790. Do FAZ and determines
  791. - multi-homing
  792. - multi-master
  793. before handing over to next level.
  794. Arguments:
  795. pBlob -- update info blob
  796. Return Value:
  797. ERROR_SUCCESS if successful.
  798. ErrorCode on failure.
  799. --*/
  800. {
  801. DNS_STATUS status = NO_ERROR;
  802. PWSTR pzoneName;
  803. PWSTR pname;
  804. PADDR_ARRAY pserverList;
  805. PADDR_ARRAY pserverListCopy = NULL;
  806. PADDR_ARRAY poriginalServerList;
  807. PIP4_ARRAY pserv4List;
  808. PDNS_NETINFO pnetInfo = NULL;
  809. DWORD flags = pBlob->Flags;
  810. DNSDBG( UPDATE, (
  811. "Update_Private( blob=%p )\n",
  812. pBlob ));
  813. IF_DNSDBG( UPDATE )
  814. {
  815. DnsDbg_UpdateBlob( "Entering Update_Private", pBlob );
  816. }
  817. //
  818. // get record name
  819. //
  820. if ( !pBlob->pRecords )
  821. {
  822. status = ERROR_INVALID_PARAMETER;
  823. goto Done;
  824. }
  825. pname = pBlob->pRecords->pName;
  826. //
  827. // unpack to locals
  828. //
  829. pserverList = pBlob->pServerList;
  830. pserv4List = pBlob->pServ4List;
  831. poriginalServerList = pserverList;
  832. //
  833. // caller has particular server list
  834. // - convert IP4 list
  835. //
  836. pserverListCopy = Util_GetAddrArray(
  837. NULL,
  838. pserverList,
  839. pserv4List,
  840. pBlob->pExtraInfo );
  841. //
  842. // update with particular server list
  843. //
  844. if ( pserverListCopy )
  845. {
  846. //
  847. // FAZ to create update network info
  848. //
  849. status = DoQuickFAZ(
  850. &pnetInfo,
  851. pname,
  852. pserverListCopy );
  853. if ( status != ERROR_SUCCESS )
  854. {
  855. DnsAddrArray_Free( pserverListCopy );
  856. goto Done;
  857. }
  858. DNS_ASSERT( NetInfo_IsForUpdate(pnetInfo) );
  859. pzoneName = NetInfo_UpdateZoneName( pnetInfo );
  860. pBlob->pszZone = pzoneName;
  861. pBlob->pNetInfo = pnetInfo;
  862. //
  863. // update scale
  864. // - directly multimaster
  865. // OR
  866. // - single, but fail over to multi-master attempt if timeout
  867. //
  868. if ( flags & (DNS_UPDATE_TRY_ALL_MASTER_SERVERS | DNS_UPDATE_REMOTE_SERVER) )
  869. {
  870. pBlob->pServerList = pserverListCopy;
  871. status = Update_MultiMaster( pBlob );
  872. }
  873. else
  874. {
  875. status = Update_FazSendFlush( pBlob );
  876. if ( status == ERROR_TIMEOUT )
  877. {
  878. pBlob->pServerList = pserverListCopy;
  879. status = Update_MultiMaster( pBlob );
  880. }
  881. }
  882. // cleanup
  883. NetInfo_Free( pnetInfo );
  884. DnsAddrArray_Free( pserverListCopy );
  885. pBlob->pNetInfo = NULL;
  886. pBlob->pServerList = poriginalServerList;
  887. pBlob->pszZone = NULL;
  888. DnsAddr_Clear( &pBlob->FailedServer );
  889. goto Done;
  890. }
  891. //
  892. // server list unspecified
  893. // - use FAZ to figure it out
  894. //
  895. else
  896. {
  897. PADDR_ARRAY serverListArray[ UPDATE_ADAPTER_LIMIT ];
  898. PDNS_NETINFO networkInfoArray[ UPDATE_ADAPTER_LIMIT ];
  899. DWORD netCount = UPDATE_ADAPTER_LIMIT;
  900. DWORD iter;
  901. BOOL bsuccess = FALSE;
  902. //
  903. // build server list for update
  904. // - collapse adapters on same network into single adapter
  905. // - FAZ to find update servers
  906. // - collapse results from same network into single target
  907. //
  908. netCount = GetDnsServerListsForUpdate(
  909. serverListArray,
  910. netCount,
  911. pBlob->Flags
  912. );
  913. status = CollapseDnsServerListsForUpdate(
  914. serverListArray,
  915. networkInfoArray,
  916. & netCount,
  917. pname );
  918. DNS_ASSERT( netCount <= UPDATE_ADAPTER_LIMIT );
  919. if ( netCount == 0 )
  920. {
  921. if ( status == ERROR_SUCCESS )
  922. {
  923. status = DNS_ERROR_NO_DNS_SERVERS;
  924. }
  925. goto Done;
  926. }
  927. //
  928. // do update on all distinct (disjoint) networks
  929. //
  930. for ( iter = 0;
  931. iter < netCount;
  932. iter++ )
  933. {
  934. PADDR_ARRAY pdnsArray = serverListArray[ iter ];
  935. pnetInfo = networkInfoArray[ iter ];
  936. if ( !pnetInfo )
  937. {
  938. ASSERT( FALSE );
  939. FREE_HEAP( pdnsArray );
  940. continue;
  941. }
  942. DNS_ASSERT( NetInfo_IsForUpdate(pnetInfo) );
  943. pzoneName = NetInfo_UpdateZoneName( pnetInfo );
  944. pBlob->pszZone = pzoneName;
  945. pBlob->pNetInfo = pnetInfo;
  946. //
  947. // multimater update?
  948. // - if flag set
  949. // - or simple update (best net) times out
  950. //
  951. if ( flags & (DNS_UPDATE_TRY_ALL_MASTER_SERVERS | DNS_UPDATE_REMOTE_SERVER) )
  952. {
  953. pBlob->pServerList = pdnsArray;
  954. status = Update_MultiMaster( pBlob );
  955. }
  956. else
  957. {
  958. status = Update_FazSendFlush( pBlob );
  959. if ( status == ERROR_TIMEOUT )
  960. {
  961. pBlob->pServerList = pdnsArray;
  962. status = Update_MultiMaster( pBlob );
  963. }
  964. }
  965. // cleanup current network's info
  966. // reset blob
  967. NetInfo_Free( pnetInfo );
  968. FREE_HEAP( pdnsArray );
  969. pBlob->pNetInfo = NULL;
  970. pBlob->pServerList = NULL;
  971. pBlob->pszZone = NULL;
  972. DnsAddr_Clear( &pBlob->FailedServer );
  973. if ( status == NO_ERROR ||
  974. ( pBlob->fUpdateTestMode &&
  975. ( status == DNS_ERROR_RCODE_YXDOMAIN ||
  976. status == DNS_ERROR_RCODE_YXRRSET ||
  977. status == DNS_ERROR_RCODE_NXRRSET ) ) )
  978. {
  979. bsuccess = TRUE;
  980. }
  981. }
  982. //
  983. // successful update on any network counts as success
  984. //
  985. // DCR_QUESTION: not sure why don't just NO_ERROR all bsuccess,
  986. // only case would be this fUpdateTestMode thing above
  987. // on single network
  988. //
  989. if ( bsuccess )
  990. {
  991. if ( netCount != 1 )
  992. {
  993. status = NO_ERROR;
  994. }
  995. }
  996. }
  997. Done:
  998. //
  999. // force result blob setting for failure cases
  1000. //
  1001. if ( !pBlob->fSavedResults )
  1002. {
  1003. Update_SaveResults(
  1004. pBlob,
  1005. status,
  1006. 0,
  1007. NULL );
  1008. }
  1009. DNSDBG( TRACE, (
  1010. "Leaving Update_Private() => %d\n",
  1011. status ));
  1012. IF_DNSDBG( UPDATE )
  1013. {
  1014. DnsDbg_UpdateBlob( "Leaving Update_Private", pBlob );
  1015. }
  1016. return status;
  1017. }
  1018. //
  1019. // Update credentials
  1020. //
  1021. //
  1022. // Credentials are an optional future parameter to allow the caller
  1023. // to set the context handle to that of a given NT account. This
  1024. // structure will most likely be the following as defined in rpcdce.h:
  1025. //
  1026. // #define SEC_WINNT_AUTH_IDENTITY_ANSI 0x1
  1027. //
  1028. // typedef struct _SEC_WINNT_AUTH_IDENTITY_A {
  1029. // unsigned char __RPC_FAR *User;
  1030. // unsigned long UserLength;
  1031. // unsigned char __RPC_FAR *Domain;
  1032. // unsigned long DomainLength;
  1033. // unsigned char __RPC_FAR *Password;
  1034. // unsigned long PasswordLength;
  1035. // unsigned long Flags;
  1036. // } SEC_WINNT_AUTH_IDENTITY_A, *PSEC_WINNT_AUTH_IDENTITY_A;
  1037. //
  1038. // #define SEC_WINNT_AUTH_IDENTITY_UNICODE 0x2
  1039. //
  1040. // typedef struct _SEC_WINNT_AUTH_IDENTITY_W {
  1041. // unsigned short __RPC_FAR *User;
  1042. // unsigned long UserLength;
  1043. // unsigned short __RPC_FAR *Domain;
  1044. // unsigned long DomainLength;
  1045. // unsigned short __RPC_FAR *Password;
  1046. // unsigned long PasswordLength;
  1047. // unsigned long Flags;
  1048. // } SEC_WINNT_AUTH_IDENTITY_W, *PSEC_WINNT_AUTH_IDENTITY_W;
  1049. //
  1050. DNS_STATUS
  1051. WINAPI
  1052. DnsAcquireContextHandle_W(
  1053. IN DWORD CredentialFlags,
  1054. IN PVOID Credentials OPTIONAL,
  1055. OUT PHANDLE pContext
  1056. )
  1057. /*++
  1058. Routine Description:
  1059. Get credentials handle to security context for update.
  1060. The handle can for the default process credentials (user account or
  1061. system machine account) or for a specified set of credentials
  1062. identified by Credentials.
  1063. Arguments:
  1064. CredentialFlags -- flags
  1065. Credentials -- a PSEC_WINNT_AUTH_IDENTITY_W
  1066. (explicit definition skipped to avoid requiring rpcdec.h)
  1067. pContext -- addr to receive credentials handle
  1068. Return Value:
  1069. ERROR_SUCCESS if successful.
  1070. ErrorCode on failure.
  1071. --*/
  1072. {
  1073. if ( ! pContext )
  1074. {
  1075. return ERROR_INVALID_PARAMETER;
  1076. }
  1077. *pContext = Dns_CreateAPIContext(
  1078. CredentialFlags,
  1079. Credentials,
  1080. TRUE // unicode
  1081. );
  1082. if ( ! *pContext )
  1083. {
  1084. return DNS_ERROR_NO_MEMORY;
  1085. }
  1086. else
  1087. {
  1088. return NO_ERROR;
  1089. }
  1090. }
  1091. DNS_STATUS
  1092. WINAPI
  1093. DnsAcquireContextHandle_A(
  1094. IN DWORD CredentialFlags,
  1095. IN PVOID Credentials OPTIONAL,
  1096. OUT PHANDLE pContext
  1097. )
  1098. /*++
  1099. Routine Description:
  1100. Get credentials handle to security context for update.
  1101. The handle can for the default process credentials (user account or
  1102. system machine account) or for a specified set of credentials
  1103. identified by Credentials.
  1104. Arguments:
  1105. CredentialFlags -- flags
  1106. Credentials -- a PSEC_WINNT_AUTH_IDENTITY_A
  1107. (explicit definition skipped to avoid requiring rpcdec.h)
  1108. pContext -- addr to receive credentials handle
  1109. Return Value:
  1110. ERROR_SUCCESS if successful.
  1111. ErrorCode on failure.
  1112. --*/
  1113. {
  1114. if ( ! pContext )
  1115. {
  1116. return ERROR_INVALID_PARAMETER;
  1117. }
  1118. *pContext = Dns_CreateAPIContext(
  1119. CredentialFlags,
  1120. Credentials,
  1121. FALSE );
  1122. if ( ! *pContext )
  1123. {
  1124. return DNS_ERROR_NO_MEMORY;
  1125. }
  1126. else
  1127. {
  1128. return NO_ERROR;
  1129. }
  1130. }
  1131. VOID
  1132. WINAPI
  1133. DnsReleaseContextHandle(
  1134. IN HANDLE ContextHandle
  1135. )
  1136. /*++
  1137. Routine Description:
  1138. Frees context handle created by DnsAcquireContextHandle_X() routines.
  1139. Arguments:
  1140. ContextHandle - Handle to be closed.
  1141. Return Value:
  1142. None.
  1143. --*/
  1144. {
  1145. if ( ContextHandle )
  1146. {
  1147. //
  1148. // free any cached security context handles
  1149. //
  1150. // DCR_FIX0: should delete all contexts associated with this
  1151. // context (credentials handle) not all
  1152. //
  1153. // DCR: to be robust, user "ContextHandle" should be ref counted
  1154. // it should be set one on create; when in use, incremented
  1155. // then dec when done; then this Free could not collide with
  1156. // another thread's use
  1157. //
  1158. //Dns_TimeoutSecurityContextListEx( TRUE, ContextHandle );
  1159. Dns_TimeoutSecurityContextList( TRUE );
  1160. Dns_FreeAPIContext( ContextHandle );
  1161. }
  1162. }
  1163. //
  1164. // Utilities
  1165. //
  1166. DWORD
  1167. prepareUpdateRecordSet(
  1168. IN OUT PDNS_RECORD pRRSet,
  1169. IN BOOL fClearTtl,
  1170. IN BOOL fSetFlags,
  1171. IN WORD wFlags
  1172. )
  1173. /*++
  1174. Routine Description:
  1175. Validate and prepare record set for update.
  1176. - record set is single RR set
  1177. - sets record flags for update
  1178. Arguments:
  1179. pRRSet -- record set (always in unicode)
  1180. note: pRRSet is not touched (not OUT param)
  1181. IF fClearTtl AND fSetFlags are both FALSE
  1182. fClearTtl -- clear TTL in records; TRUE for delete set
  1183. fSetFlags -- set section and delete flags
  1184. wFlags -- flags field to set
  1185. (should contain desired section and delete flags)
  1186. Return Value:
  1187. ERROR_SUCCESS if successful.
  1188. ERROR_INVALID_PARAMETER if record set is not acceptable.
  1189. --*/
  1190. {
  1191. PDNS_RECORD prr;
  1192. PWSTR pname;
  1193. WORD type;
  1194. DNSDBG( TRACE, ( "prepareUpdateRecordSet()\n" ));
  1195. // validate
  1196. if ( !pRRSet )
  1197. {
  1198. return ERROR_INVALID_PARAMETER;
  1199. }
  1200. type = pRRSet->wType;
  1201. //
  1202. // note: could do an "update-type" check here, but that just
  1203. // A) burns unnecessary memory and cycles
  1204. // B) makes it harder to test bogus records sent in updates
  1205. // to the server
  1206. //
  1207. pname = pRRSet->pName;
  1208. if ( !pname )
  1209. {
  1210. return ERROR_INVALID_PARAMETER;
  1211. }
  1212. //
  1213. // check each RR in set
  1214. // - validate RR is in set
  1215. // - set RR flags
  1216. //
  1217. prr = pRRSet;
  1218. while ( prr )
  1219. {
  1220. if ( fSetFlags )
  1221. {
  1222. prr->Flags.S.Section = 0;
  1223. prr->Flags.S.Delete = 0;
  1224. prr->Flags.DW |= wFlags;
  1225. }
  1226. if ( fClearTtl )
  1227. {
  1228. prr->dwTtl = 0;
  1229. }
  1230. // check current RR in set
  1231. // - matches name and type
  1232. if ( prr != pRRSet )
  1233. {
  1234. if ( prr->wType != type ||
  1235. ! prr->pName ||
  1236. ! Dns_NameCompare_W( pname, prr->pName ) )
  1237. {
  1238. return ERROR_INVALID_PARAMETER;
  1239. }
  1240. }
  1241. prr = prr->pNext;
  1242. }
  1243. return ERROR_SUCCESS;
  1244. }
  1245. PDNS_RECORD
  1246. buildUpdateRecordSet(
  1247. IN OUT PDNS_RECORD pPrereqSet,
  1248. IN OUT PDNS_RECORD pAddSet,
  1249. IN OUT PDNS_RECORD pDeleteSet
  1250. )
  1251. /*++
  1252. Routine Description:
  1253. Build combined record list for update.
  1254. Combines prereq, delete and add records.
  1255. Note: records sets always in unicode.
  1256. Arguments:
  1257. pPrereqSet -- prerequisite records; note this does NOT
  1258. include delete preqs (see note below)
  1259. pAddSet -- records to add
  1260. pDeleteSet -- records to delete
  1261. Return Value:
  1262. Ptr to combined record list for update.
  1263. --*/
  1264. {
  1265. PDNS_RECORD plast = NULL;
  1266. PDNS_RECORD pfirst = NULL;
  1267. DNSDBG( TRACE, ( "buildUpdateRecordSet()\n" ));
  1268. //
  1269. // append prereq set
  1270. //
  1271. // DCR: doesn't handle delete prereqs
  1272. // this is fine because we roll our own, but if
  1273. // later expand the function, then need them
  1274. //
  1275. // note, I could add flag==PREREQ datalength==0
  1276. // test in prepareUpdateRecordSet() function, then
  1277. // set Delete flag; however, we'd still have the
  1278. // question of how to distinguish existence (class==ANY)
  1279. // prereq from delete (class==NONE) prereq -- without
  1280. // directly exposing the record Delete flag
  1281. //
  1282. if ( pPrereqSet )
  1283. {
  1284. plast = pPrereqSet;
  1285. pfirst = pPrereqSet;
  1286. prepareUpdateRecordSet(
  1287. pPrereqSet,
  1288. FALSE, // no TTL clear
  1289. TRUE, // set flags
  1290. DNSREC_PREREQ // prereq section
  1291. );
  1292. while ( plast->pNext )
  1293. {
  1294. plast = plast->pNext;
  1295. }
  1296. }
  1297. //
  1298. // append delete records
  1299. // do before Add records so that delete\add of same record
  1300. // leaves it in place
  1301. //
  1302. if ( pDeleteSet )
  1303. {
  1304. if ( !plast )
  1305. {
  1306. plast = pDeleteSet;
  1307. pfirst = pDeleteSet;
  1308. }
  1309. else
  1310. {
  1311. plast->pNext = pDeleteSet;
  1312. }
  1313. prepareUpdateRecordSet(
  1314. pDeleteSet,
  1315. TRUE, // clear TTL
  1316. TRUE, // set flags
  1317. DNSREC_UPDATE | DNSREC_DELETE // update section, delete bit
  1318. );
  1319. while ( plast->pNext )
  1320. {
  1321. plast = plast->pNext;
  1322. }
  1323. }
  1324. //
  1325. // append add records
  1326. //
  1327. if ( pAddSet )
  1328. {
  1329. if ( !plast )
  1330. {
  1331. plast = pAddSet;
  1332. pfirst = pAddSet;
  1333. }
  1334. else
  1335. {
  1336. plast->pNext = pAddSet;
  1337. }
  1338. prepareUpdateRecordSet(
  1339. pAddSet,
  1340. FALSE, // no TTL change
  1341. TRUE, // set flags
  1342. DNSREC_UPDATE // update section
  1343. );
  1344. }
  1345. return pfirst;
  1346. }
  1347. BOOL
  1348. IsPtrUpdate(
  1349. IN PDNS_RECORD pRecordList
  1350. )
  1351. /*++
  1352. Routine Description:
  1353. Check if update is PTR update.
  1354. Arguments:
  1355. pRecordList -- update record list
  1356. Return Value:
  1357. TRUE if PTR update.
  1358. FALSE otherwise.
  1359. --*/
  1360. {
  1361. PDNS_RECORD prr = pRecordList;
  1362. BOOL bptrUpdate = FALSE;
  1363. //
  1364. // find, then test first record in update section
  1365. //
  1366. while ( prr )
  1367. {
  1368. if ( prr->Flags.S.Section == DNSREC_UPDATE )
  1369. {
  1370. if ( prr->wType == DNS_TYPE_PTR )
  1371. {
  1372. bptrUpdate = TRUE;
  1373. }
  1374. break;
  1375. }
  1376. prr = prr->pNext;
  1377. }
  1378. return bptrUpdate;
  1379. }
  1380. //
  1381. // Replace functions
  1382. //
  1383. DNS_STATUS
  1384. WINAPI
  1385. replaceRecordSetPrivate(
  1386. IN PDNS_RECORD pReplaceSet,
  1387. IN DWORD Options,
  1388. IN HANDLE hCredentials, OPTIONAL
  1389. IN PIP4_ARRAY pServ4List, OPTIONAL
  1390. IN PVOID pExtraInfo,
  1391. IN DNS_CHARSET CharSet
  1392. )
  1393. /*++
  1394. Routine Description:
  1395. Replace record set routine handling all character sets.
  1396. Arguments:
  1397. pReplaceSet - replacement record set
  1398. Options - update options
  1399. pServerList - list of DNS servers to go to; if not given, machines
  1400. default servers are queried to find correct servers to send update to
  1401. hCredentials - handle to credentials to be used for update; optional,
  1402. if not given security credentials of this process are used in update
  1403. pReserved - ptr to blob
  1404. CharSet - character set of incoming records
  1405. Return Value:
  1406. ERROR_SUCCESS if update successful.
  1407. ErrorCode from server if server rejects update.
  1408. ERROR_INVALID_PARAMETER if bad param.
  1409. --*/
  1410. {
  1411. DNS_STATUS status;
  1412. PDNS_RECORD preplaceCopy = NULL;
  1413. PDNS_RECORD pupdateList = NULL;
  1414. BOOL btypeDelete;
  1415. DNS_RECORD rrNoCname;
  1416. DNS_RECORD rrDeleteType;
  1417. BOOL fcnameUpdate;
  1418. UPDATE_BLOB blob;
  1419. PDNS_ADDR_ARRAY pservArray = NULL;
  1420. DNSDBG( TRACE, (
  1421. "\n\nDnsReplaceRecordSet()\n"
  1422. "replaceRecordSetPrivate()\n"
  1423. "\tpReplaceSet = %p\n"
  1424. "\tOptions = %08x\n"
  1425. "\thCredentials = %p\n"
  1426. "\tpServ4List = %p\n"
  1427. "\tpExtra = %p\n"
  1428. "\tCharSet = %d\n",
  1429. pReplaceSet,
  1430. Options,
  1431. hCredentials,
  1432. pServ4List,
  1433. pExtraInfo,
  1434. CharSet
  1435. ));
  1436. //
  1437. // read update config
  1438. //
  1439. Reg_RefreshUpdateConfig();
  1440. //
  1441. // make local record set copy in unicode
  1442. //
  1443. if ( !pReplaceSet )
  1444. {
  1445. status = ERROR_INVALID_PARAMETER;
  1446. goto Cleanup;
  1447. }
  1448. preplaceCopy = Dns_RecordSetCopyEx(
  1449. pReplaceSet,
  1450. CharSet,
  1451. DnsCharSetUnicode );
  1452. if ( !preplaceCopy )
  1453. {
  1454. status = ERROR_INVALID_PARAMETER;
  1455. goto Cleanup;
  1456. }
  1457. //
  1458. // validate arguments
  1459. // - must have single RR set
  1460. // - mark them for update
  1461. //
  1462. status = prepareUpdateRecordSet(
  1463. preplaceCopy,
  1464. FALSE, // no TTL clear
  1465. TRUE, // set flags
  1466. DNSREC_UPDATE // flag as update
  1467. );
  1468. if ( status != ERROR_SUCCESS )
  1469. {
  1470. status = ERROR_INVALID_PARAMETER;
  1471. goto Cleanup;
  1472. }
  1473. //
  1474. // check if simple type delete
  1475. //
  1476. btypeDelete = ( preplaceCopy->wDataLength == 0 &&
  1477. preplaceCopy->pNext == NULL );
  1478. //
  1479. // set security for update
  1480. //
  1481. if ( UseSystemDefaultForSecurity( Options ) )
  1482. {
  1483. Options |= g_UpdateSecurityLevel;
  1484. }
  1485. if ( hCredentials )
  1486. {
  1487. Options |= DNS_UPDATE_CACHE_SECURITY_CONTEXT;
  1488. }
  1489. //
  1490. // type delete record
  1491. //
  1492. // if have replace records -- this goes in front
  1493. // if type delete -- then ONLY need this record
  1494. //
  1495. RtlZeroMemory( &rrDeleteType, sizeof(DNS_RECORD) );
  1496. rrDeleteType.pName = preplaceCopy->pName;
  1497. rrDeleteType.wType = preplaceCopy->wType;
  1498. rrDeleteType.wDataLength = 0;
  1499. rrDeleteType.Flags.DW = DNSREC_UPDATE | DNSREC_DELETE | DNSREC_UNICODE;
  1500. if ( btypeDelete )
  1501. {
  1502. rrDeleteType.pNext = NULL;
  1503. }
  1504. else
  1505. {
  1506. rrDeleteType.pNext = preplaceCopy;
  1507. }
  1508. pupdateList = &rrDeleteType;
  1509. //
  1510. // CNAME does not exist precondition record
  1511. // - for all updates EXCEPT CNAME
  1512. //
  1513. fcnameUpdate = ( preplaceCopy->wType == DNS_TYPE_CNAME );
  1514. if ( !fcnameUpdate )
  1515. {
  1516. RtlZeroMemory( &rrNoCname, sizeof(DNS_RECORD) );
  1517. rrNoCname.pName = preplaceCopy->pName;
  1518. rrNoCname.wType = DNS_TYPE_CNAME;
  1519. rrNoCname.wDataLength = 0;
  1520. rrNoCname.Flags.DW = DNSREC_PREREQ | DNSREC_NOEXIST | DNSREC_UNICODE;
  1521. rrNoCname.pNext = &rrDeleteType;
  1522. pupdateList = &rrNoCname;
  1523. }
  1524. //
  1525. // do the update
  1526. //
  1527. RtlZeroMemory( &blob, sizeof(blob) );
  1528. blob.pRecords = pupdateList;
  1529. blob.Flags = Options;
  1530. blob.pServ4List = pServ4List;
  1531. blob.pExtraInfo = pExtraInfo;
  1532. blob.hCreds = hCredentials;
  1533. status = Update_Private( &blob );
  1534. //
  1535. // CNAME collision test
  1536. //
  1537. // if replacing CNAME may have gotten silent ignore
  1538. // - first check if successfully replaced CNAME
  1539. // - if still not sure, check that no other records
  1540. // at name -- if NON-CNAME found then treat silent ignore
  1541. // as YXRRSET error
  1542. //
  1543. if ( fcnameUpdate &&
  1544. ! btypeDelete &&
  1545. status == NO_ERROR )
  1546. {
  1547. PDNS_RECORD pqueryRR = NULL;
  1548. BOOL fsuccess = FALSE;
  1549. //
  1550. // build addr array
  1551. //
  1552. pservArray = Util_GetAddrArray(
  1553. NULL, // no copy issue
  1554. NULL, // no addr array
  1555. pServ4List,
  1556. pExtraInfo );
  1557. // DCR: need to query update server list here to
  1558. // avoid intermediate caching
  1559. status = Query_Private(
  1560. preplaceCopy->pName,
  1561. DNS_TYPE_CNAME,
  1562. DNS_QUERY_BYPASS_CACHE,
  1563. pservArray,
  1564. & pqueryRR );
  1565. if ( status == NO_ERROR &&
  1566. Dns_RecordCompare(
  1567. preplaceCopy,
  1568. pqueryRR ) )
  1569. {
  1570. fsuccess = TRUE;
  1571. }
  1572. Dns_RecordListFree( pqueryRR );
  1573. if ( fsuccess )
  1574. {
  1575. goto Cleanup;
  1576. }
  1577. // query for any type at CNAME
  1578. // if found then assume we got a silent update
  1579. // success
  1580. status = Query_Private(
  1581. preplaceCopy->pName,
  1582. DNS_TYPE_ALL,
  1583. DNS_QUERY_BYPASS_CACHE,
  1584. pservArray,
  1585. & pqueryRR );
  1586. if ( status == ERROR_SUCCESS )
  1587. {
  1588. PDNS_RECORD prr = pqueryRR;
  1589. while ( prr )
  1590. {
  1591. if ( pReplaceSet->wType != prr->wType &&
  1592. Dns_NameCompare_W(
  1593. preplaceCopy->pName,
  1594. prr->pName ) )
  1595. {
  1596. status = DNS_ERROR_RCODE_YXRRSET;
  1597. break;
  1598. }
  1599. prr = prr->pNext;
  1600. }
  1601. }
  1602. else
  1603. {
  1604. status = ERROR_SUCCESS;
  1605. }
  1606. Dns_RecordListFree( pqueryRR );
  1607. }
  1608. Cleanup:
  1609. Dns_RecordListFree( preplaceCopy );
  1610. DnsAddrArray_Free( pservArray );
  1611. DNSDBG( TRACE, (
  1612. "Leave replaceRecordSetPrivate() = %d\n"
  1613. "Leave DnsReplaceRecordSet()\n\n\n",
  1614. status
  1615. ));
  1616. return status;
  1617. }
  1618. DNS_STATUS
  1619. WINAPI
  1620. DnsReplaceRecordSetUTF8(
  1621. IN PDNS_RECORD pReplaceSet,
  1622. IN DWORD Options,
  1623. IN HANDLE hCredentials OPTIONAL,
  1624. IN PIP4_ARRAY aipServers OPTIONAL,
  1625. IN PVOID pReserved
  1626. )
  1627. /*++
  1628. Routine Description:
  1629. Dynamic update routine to replace record set on DNS server.
  1630. Arguments:
  1631. pReplaceSet - new record set for name and type
  1632. Options - update options
  1633. pServerList - list of DNS servers to go to; if not given, machines
  1634. default servers are queried to find correct servers to send update to
  1635. hCredentials - handle to credentials to be used for update; optional,
  1636. if not given securit5y credentials of this process are used in update
  1637. pReserved - ptr to blob
  1638. Return Value:
  1639. None.
  1640. --*/
  1641. {
  1642. return replaceRecordSetPrivate(
  1643. pReplaceSet,
  1644. Options,
  1645. hCredentials,
  1646. aipServers,
  1647. pReserved,
  1648. DnsCharSetUtf8
  1649. );
  1650. }
  1651. DNS_STATUS
  1652. WINAPI
  1653. DnsReplaceRecordSetW(
  1654. IN PDNS_RECORD pReplaceSet,
  1655. IN DWORD Options,
  1656. IN HANDLE hCredentials OPTIONAL,
  1657. IN PIP4_ARRAY aipServers OPTIONAL,
  1658. IN PVOID pReserved
  1659. )
  1660. /*++
  1661. Routine Description:
  1662. Dynamic update routine to replace record set on DNS server.
  1663. Arguments:
  1664. pReplaceSet - new record set for name and type
  1665. Options - update options
  1666. pServerList - list of DNS servers to go to; if not given, machines
  1667. default servers are queried to find correct servers to send update to
  1668. hCredentials - handle to credentials to be used for update; optional,
  1669. if not given security credentials of this process are used in update
  1670. pReserved - ptr to blob
  1671. Return Value:
  1672. None.
  1673. --*/
  1674. {
  1675. return replaceRecordSetPrivate(
  1676. pReplaceSet,
  1677. Options,
  1678. hCredentials,
  1679. aipServers,
  1680. pReserved,
  1681. DnsCharSetUnicode
  1682. );
  1683. }
  1684. DNS_STATUS
  1685. WINAPI
  1686. DnsReplaceRecordSetA(
  1687. IN PDNS_RECORD pReplaceSet,
  1688. IN DWORD Options,
  1689. IN HANDLE hCredentials OPTIONAL,
  1690. IN PIP4_ARRAY aipServers OPTIONAL,
  1691. IN PVOID pReserved
  1692. )
  1693. /*++
  1694. Routine Description:
  1695. Dynamic update routine to replace record set on DNS server.
  1696. Arguments:
  1697. pReplaceSet - new record set for name and type
  1698. Options - update options
  1699. pServerList - list of DNS servers to go to; if not given, machines
  1700. default servers are queried to find correct servers to send update to
  1701. hCredentials - handle to credentials to be used for update; optional,
  1702. if not given security credentials of this process are used in update
  1703. pReserved - ptr to blob
  1704. Return Value:
  1705. None.
  1706. --*/
  1707. {
  1708. return replaceRecordSetPrivate(
  1709. pReplaceSet,
  1710. Options,
  1711. hCredentials,
  1712. aipServers,
  1713. pReserved,
  1714. DnsCharSetAnsi
  1715. );
  1716. }
  1717. //
  1718. // Modify functions
  1719. //
  1720. DNS_STATUS
  1721. WINAPI
  1722. modifyRecordsInSetPrivate(
  1723. IN PDNS_RECORD pAddRecords,
  1724. IN PDNS_RECORD pDeleteRecords,
  1725. IN DWORD Options,
  1726. IN HANDLE hCredentials, OPTIONAL
  1727. IN PADDR_ARRAY pServerList, OPTIONAL
  1728. IN PIP4_ARRAY pServ4List, OPTIONAL
  1729. IN PVOID pReserved,
  1730. IN DNS_CHARSET CharSet
  1731. )
  1732. /*++
  1733. Routine Description:
  1734. Dynamic update routine to replace record set on DNS server.
  1735. Arguments:
  1736. pAddRecords - records to register on server
  1737. pDeleteRecords - records to remove from server
  1738. Options - update options
  1739. pServerList - list of DNS servers to go to; if not given, machines
  1740. default servers are queried to find correct servers to send update to
  1741. hCredentials - handle to credentials to be used for update; optional,
  1742. if not given security credentials of this process are used in update
  1743. pReserved - ptr to blob
  1744. CharSet - character set of incoming records
  1745. Return Value:
  1746. ERROR_SUCCESS if update successful.
  1747. ErrorCode from server if server rejects update.
  1748. ERROR_INVALID_PARAMETER if bad param.
  1749. --*/
  1750. {
  1751. DNS_STATUS status;
  1752. PDNS_RECORD paddCopy = NULL;
  1753. PDNS_RECORD pdeleteCopy = NULL;
  1754. PDNS_RECORD pupdateSet = NULL;
  1755. UPDATE_BLOB blob;
  1756. DNSDBG( TRACE, (
  1757. "\n\nDns_ModifyRecordsInSet()\n"
  1758. "modifyRecordsInSetPrivate()\n"
  1759. "\tpAddSet = %p\n"
  1760. "\tpDeleteSet = %p\n"
  1761. "\tOptions = %08x\n"
  1762. "\thCredentials = %p\n"
  1763. "\tpServerList = %p\n"
  1764. "\tpServ4List = %p\n"
  1765. "\tCharSet = %d\n",
  1766. pAddRecords,
  1767. pDeleteRecords,
  1768. Options,
  1769. hCredentials,
  1770. pServerList,
  1771. pServ4List,
  1772. CharSet
  1773. ));
  1774. //
  1775. // read update config
  1776. //
  1777. Reg_RefreshUpdateConfig();
  1778. //
  1779. // make local copy in unicode
  1780. //
  1781. if ( pAddRecords )
  1782. {
  1783. paddCopy = Dns_RecordSetCopyEx(
  1784. pAddRecords,
  1785. CharSet,
  1786. DnsCharSetUnicode );
  1787. }
  1788. if ( pDeleteRecords )
  1789. {
  1790. pdeleteCopy = Dns_RecordSetCopyEx(
  1791. pDeleteRecords,
  1792. CharSet,
  1793. DnsCharSetUnicode );
  1794. }
  1795. //
  1796. // validate arguments
  1797. // - add and delete must be for single RR set
  1798. // and must be for same RR set
  1799. //
  1800. if ( !paddCopy && !pdeleteCopy )
  1801. {
  1802. return ERROR_INVALID_PARAMETER;
  1803. }
  1804. if ( paddCopy )
  1805. {
  1806. status = prepareUpdateRecordSet(
  1807. paddCopy,
  1808. FALSE, // no TTL clear
  1809. FALSE, // no flag clear
  1810. 0 // no flags to set
  1811. );
  1812. if ( status != ERROR_SUCCESS )
  1813. {
  1814. status = ERROR_INVALID_PARAMETER;
  1815. goto Cleanup;
  1816. }
  1817. }
  1818. if ( pdeleteCopy )
  1819. {
  1820. status = prepareUpdateRecordSet(
  1821. pdeleteCopy,
  1822. FALSE, // no TTL clear
  1823. FALSE, // no flag clear
  1824. 0 // no flags to set
  1825. );
  1826. if ( status != ERROR_SUCCESS )
  1827. {
  1828. status = ERROR_INVALID_PARAMETER;
  1829. goto Cleanup;
  1830. }
  1831. }
  1832. if ( paddCopy &&
  1833. pdeleteCopy &&
  1834. ! Dns_NameCompare_W( paddCopy->pName, pdeleteCopy->pName ) )
  1835. {
  1836. status = ERROR_INVALID_PARAMETER;
  1837. goto Cleanup;
  1838. }
  1839. //
  1840. // set security for update
  1841. //
  1842. if ( UseSystemDefaultForSecurity( Options ) )
  1843. {
  1844. Options |= g_UpdateSecurityLevel;
  1845. }
  1846. if ( hCredentials )
  1847. {
  1848. Options |= DNS_UPDATE_CACHE_SECURITY_CONTEXT;
  1849. }
  1850. //
  1851. // create update RRs
  1852. // - no prereqs
  1853. // - delete RRs set for delete
  1854. // - add RRs appended
  1855. //
  1856. pupdateSet = buildUpdateRecordSet(
  1857. NULL, // no precons
  1858. paddCopy,
  1859. pdeleteCopy );
  1860. //
  1861. // do the update
  1862. //
  1863. RtlZeroMemory( &blob, sizeof(blob) );
  1864. blob.pRecords = pupdateSet;
  1865. blob.Flags = Options;
  1866. blob.pServerList = pServerList;
  1867. blob.pServ4List = pServ4List;
  1868. blob.pExtraInfo = pReserved;
  1869. blob.hCreds = hCredentials;
  1870. status = Update_Private( &blob );
  1871. //
  1872. // cleanup local copy
  1873. //
  1874. Dns_RecordListFree( pupdateSet );
  1875. goto Exit;
  1876. Cleanup:
  1877. //
  1878. // cleanup copies on failure before combined list
  1879. //
  1880. Dns_RecordListFree( paddCopy );
  1881. Dns_RecordListFree( pdeleteCopy );
  1882. Exit:
  1883. DNSDBG( TRACE, (
  1884. "Leave modifyRecordsInSetPrivate() => %d\n"
  1885. "Leave Dns_ModifyRecordsInSet()\n\n\n",
  1886. status ));
  1887. return status;
  1888. }
  1889. DNS_STATUS
  1890. WINAPI
  1891. DnsModifyRecordsInSet_W(
  1892. IN PDNS_RECORD pAddRecords,
  1893. IN PDNS_RECORD pDeleteRecords,
  1894. IN DWORD Options,
  1895. IN HANDLE hCredentials, OPTIONAL
  1896. IN PIP4_ARRAY pServerList, OPTIONAL
  1897. IN PVOID pReserved
  1898. )
  1899. /*++
  1900. Routine Description:
  1901. Dynamic update routine to modify record set on DNS server.
  1902. Arguments:
  1903. pAddRecords - records to register on server
  1904. pDeleteRecords - records to remove from server
  1905. Options - update options
  1906. pServerList - list of DNS servers to go to; if not given, machines
  1907. default servers are queried to find correct servers to send update to
  1908. hCredentials - handle to credentials to be used for update; optional,
  1909. if not given security credentials of this process are used in update
  1910. pReserved - ptr to blob
  1911. Return Value:
  1912. ERROR_SUCCESS if update successful.
  1913. ErrorCode from server if server rejects update.
  1914. ERROR_INVALID_PARAMETER if bad param.
  1915. --*/
  1916. {
  1917. return modifyRecordsInSetPrivate(
  1918. pAddRecords,
  1919. pDeleteRecords,
  1920. Options,
  1921. hCredentials,
  1922. NULL, // no IP6 servers
  1923. pServerList,
  1924. pReserved,
  1925. DnsCharSetUnicode
  1926. );
  1927. }
  1928. DNS_STATUS
  1929. WINAPI
  1930. DnsModifyRecordsInSet_A(
  1931. IN PDNS_RECORD pAddRecords,
  1932. IN PDNS_RECORD pDeleteRecords,
  1933. IN DWORD Options,
  1934. IN HANDLE hCredentials, OPTIONAL
  1935. IN PIP4_ARRAY pServerList, OPTIONAL
  1936. IN PVOID pReserved
  1937. )
  1938. /*++
  1939. Routine Description:
  1940. Dynamic update routine to modify record set on DNS server.
  1941. Arguments:
  1942. pAddRecords - records to register on server
  1943. pDeleteRecords - records to remove from server
  1944. Options - update options
  1945. pServerList - list of DNS servers to go to; if not given, machines
  1946. default servers are queried to find correct servers to send update to
  1947. hCredentials - handle to credentials to be used for update; optional,
  1948. if not given security credentials of this process are used in update
  1949. pReserved - ptr to blob
  1950. Return Value:
  1951. ERROR_SUCCESS if update successful.
  1952. ErrorCode from server if server rejects update.
  1953. ERROR_INVALID_PARAMETER if bad param.
  1954. --*/
  1955. {
  1956. return modifyRecordsInSetPrivate(
  1957. pAddRecords,
  1958. pDeleteRecords,
  1959. Options,
  1960. hCredentials,
  1961. NULL, // no IP6 servers
  1962. pServerList,
  1963. pReserved,
  1964. DnsCharSetAnsi
  1965. );
  1966. }
  1967. DNS_STATUS
  1968. WINAPI
  1969. DnsModifyRecordsInSet_UTF8(
  1970. IN PDNS_RECORD pAddRecords,
  1971. IN PDNS_RECORD pDeleteRecords,
  1972. IN DWORD Options,
  1973. IN HANDLE hCredentials, OPTIONAL
  1974. IN PIP4_ARRAY pServerList, OPTIONAL
  1975. IN PVOID pReserved
  1976. )
  1977. /*++
  1978. Routine Description:
  1979. Dynamic update routine to modify record set on DNS server.
  1980. Arguments:
  1981. pAddRecords - records to register on server
  1982. pDeleteRecords - records to remove from server
  1983. Options - update options
  1984. pServerList - list of DNS servers to go to; if not given, machines
  1985. default servers are queried to find correct servers to send update to
  1986. hCredentials - handle to credentials to be used for update; optional,
  1987. if not given security credentials of this process are used in update
  1988. pReserved - ptr to blob
  1989. Return Value:
  1990. ERROR_SUCCESS if update successful.
  1991. ErrorCode from server if server rejects update.
  1992. ERROR_INVALID_PARAMETER if bad param.
  1993. --*/
  1994. {
  1995. return modifyRecordsInSetPrivate(
  1996. pAddRecords,
  1997. pDeleteRecords,
  1998. Options,
  1999. hCredentials,
  2000. NULL, // no IP6 servers
  2001. pServerList,
  2002. pReserved,
  2003. DnsCharSetUtf8
  2004. );
  2005. }
  2006. //
  2007. // Update test functions are called by system components
  2008. //
  2009. DNS_STATUS
  2010. WINAPI
  2011. DnsUpdateTest_UTF8(
  2012. IN HANDLE hCredentials OPTIONAL,
  2013. IN PCSTR pszName,
  2014. IN DWORD Flags,
  2015. IN PIP4_ARRAY pServerList OPTIONAL
  2016. )
  2017. /*++
  2018. Routine Description:
  2019. Dynamic DNS routine to test whether the caller can update the
  2020. records in the DNS domain name space for the given record name.
  2021. Arguments:
  2022. hCredentials - handle to credentials to be used for update.
  2023. pszName - the record set name that the caller wants to test.
  2024. Flags - the Dynamic DNS update options that the caller may wish to
  2025. use (see dnsapi.h).
  2026. pServerList - a specific list of servers to goto to figure out the
  2027. authoritative DNS server(s) for the given record set
  2028. domain zone name.
  2029. Return Value:
  2030. None.
  2031. --*/
  2032. {
  2033. PWSTR pnameWide = NULL;
  2034. DNS_STATUS status = NO_ERROR;
  2035. DNSDBG( TRACE, (
  2036. "\n\nDnsUpdateTest_UTF8( %s )\n",
  2037. pszName ));
  2038. if ( !pszName )
  2039. {
  2040. return ERROR_INVALID_PARAMETER;
  2041. }
  2042. pnameWide = Dns_NameCopyAllocate(
  2043. (PCHAR) pszName,
  2044. 0,
  2045. DnsCharSetUtf8,
  2046. DnsCharSetUnicode );
  2047. if ( !pnameWide )
  2048. {
  2049. return ERROR_INVALID_NAME;
  2050. }
  2051. status = DnsUpdateTest_W(
  2052. hCredentials,
  2053. (PCWSTR) pnameWide,
  2054. Flags,
  2055. pServerList );
  2056. FREE_HEAP( pnameWide );
  2057. return status;
  2058. }
  2059. DNS_STATUS
  2060. WINAPI
  2061. DnsUpdateTest_A(
  2062. IN HANDLE hCredentials OPTIONAL,
  2063. IN PCSTR pszName,
  2064. IN DWORD Flags,
  2065. IN PIP4_ARRAY pServerList OPTIONAL
  2066. )
  2067. /*++
  2068. Routine Description:
  2069. Dynamic DNS routine to test whether the caller can update the
  2070. records in the DNS domain name space for the given record name.
  2071. Arguments:
  2072. hCredentials - handle to credentials to be used for update.
  2073. pszName - the record set name that the caller wants to test.
  2074. Flags - the Dynamic DNS update options that the caller may wish to
  2075. use (see dnsapi.h).
  2076. pServerList - a specific list of servers to goto to figure out the
  2077. authoritative DNS server(s) for the given record set
  2078. domain zone name.
  2079. Return Value:
  2080. None.
  2081. --*/
  2082. {
  2083. PWSTR pnameWide = NULL;
  2084. DNS_STATUS status = NO_ERROR;
  2085. DNSDBG( TRACE, (
  2086. "\n\nDnsUpdateTest_UTF8( %s )\n",
  2087. pszName ));
  2088. if ( !pszName )
  2089. {
  2090. return ERROR_INVALID_PARAMETER;
  2091. }
  2092. pnameWide = Dns_NameCopyAllocate(
  2093. (PCHAR) pszName,
  2094. 0,
  2095. DnsCharSetUtf8,
  2096. DnsCharSetUnicode );
  2097. if ( !pnameWide )
  2098. {
  2099. return ERROR_INVALID_NAME;
  2100. }
  2101. status = DnsUpdateTest_W(
  2102. hCredentials,
  2103. (PCWSTR) pnameWide,
  2104. Flags,
  2105. pServerList );
  2106. FREE_HEAP( pnameWide );
  2107. return status;
  2108. }
  2109. DNS_STATUS
  2110. WINAPI
  2111. DnsUpdateTest_W(
  2112. IN HANDLE hCredentials OPTIONAL,
  2113. IN PCWSTR pszName,
  2114. IN DWORD Flags,
  2115. IN PIP4_ARRAY pServerList OPTIONAL
  2116. )
  2117. /*++
  2118. Routine Description:
  2119. Dynamic DNS routine to test whether the caller can update the
  2120. records in the DNS domain name space for the given record name.
  2121. Arguments:
  2122. hCredentials - handle to credentials to be used for update.
  2123. pszName - the record set name that the caller wants to test.
  2124. Flags - the Dynamic DNS update options that the caller may wish to
  2125. use (see dnsapi.h).
  2126. pServerList - a specific list of servers to goto to figure out the
  2127. authoritative DNS server(s) for the given record set
  2128. domain zone name.
  2129. Return Value:
  2130. None.
  2131. --*/
  2132. {
  2133. DNS_STATUS status = NO_ERROR;
  2134. DNS_RECORD record;
  2135. DWORD flags = Flags;
  2136. UPDATE_BLOB blob;
  2137. DNSDBG( TRACE, (
  2138. "\n\nDnsUpdateTest_W( %S )\n",
  2139. pszName ));
  2140. //
  2141. // validation
  2142. //
  2143. if ( flags & DNS_UNACCEPTABLE_UPDATE_OPTIONS )
  2144. {
  2145. status = ERROR_INVALID_PARAMETER;
  2146. goto Exit;
  2147. }
  2148. if ( !pszName )
  2149. {
  2150. status = ERROR_INVALID_PARAMETER;
  2151. goto Exit;
  2152. }
  2153. //
  2154. // read update config
  2155. //
  2156. Reg_RefreshUpdateConfig();
  2157. if ( UseSystemDefaultForSecurity( flags ) )
  2158. {
  2159. flags |= g_UpdateSecurityLevel;
  2160. }
  2161. if ( hCredentials )
  2162. {
  2163. flags |= DNS_UPDATE_CACHE_SECURITY_CONTEXT;
  2164. }
  2165. //
  2166. // build record
  2167. // - NOEXIST prerequisite
  2168. //
  2169. RtlZeroMemory( &record, sizeof(DNS_RECORD) );
  2170. record.pName = (PWSTR) pszName;
  2171. record.wType = DNS_TYPE_ANY;
  2172. record.wDataLength = 0;
  2173. record.Flags.DW = DNSREC_PREREQ | DNSREC_NOEXIST | DNSREC_UNICODE;
  2174. //
  2175. // do the prereq update
  2176. //
  2177. RtlZeroMemory( &blob, sizeof(blob) );
  2178. blob.pRecords = &record;
  2179. blob.Flags = flags;
  2180. blob.fUpdateTestMode = TRUE;
  2181. blob.pServ4List = pServerList;
  2182. blob.hCreds = hCredentials;
  2183. status = Update_Private( &blob );
  2184. Exit:
  2185. DNSDBG( TRACE, (
  2186. "Leave DnsUpdateTest_W() = %d\n\n\n",
  2187. status ));
  2188. return status;
  2189. }
  2190. //
  2191. // Old routines -- exported and used in dnsup.exe
  2192. //
  2193. // DCR: Work toward removing these old update functions.
  2194. //
  2195. DNS_STATUS
  2196. Dns_UpdateLib(
  2197. IN PDNS_RECORD pRecord,
  2198. IN DWORD dwFlags,
  2199. IN PDNS_NETINFO pNetworkInfo,
  2200. IN HANDLE hCreds OPTIONAL,
  2201. OUT PDNS_MSG_BUF * ppMsgRecv OPTIONAL
  2202. )
  2203. /*++
  2204. Routine Description:
  2205. Interface for dnsup.exe.
  2206. Arguments:
  2207. pRecord -- list of records to send in update
  2208. dwFlags -- update flags; primarily security
  2209. pNetworkInfo -- adapter list with necessary info for update
  2210. - zone name
  2211. - primary name server name
  2212. - primary name server IP
  2213. hCreds -- credentials handle returned from
  2214. ppMsgRecv -- OPTIONAL addr to recv ptr to response message
  2215. Return Value:
  2216. ERROR_SUCCESS if successful.
  2217. Error status on failure.
  2218. --*/
  2219. {
  2220. return ERROR_INVALID_PARAMETER;
  2221. #if 0
  2222. DNS_STATUS status;
  2223. UPDATE_BLOB blob;
  2224. DNSDBG( UPDATE, (
  2225. "Dns_UpdateLib()\n"
  2226. "\tflags = %08x\n"
  2227. "\tpRecord = %p\n"
  2228. "\t\towner = %S\n",
  2229. dwFlags,
  2230. pRecord,
  2231. pRecord ? pRecord->pName : NULL ));
  2232. //
  2233. // create blob
  2234. //
  2235. RtlZeroMemory( &blob, sizeof(blob) );
  2236. blob.pRecords = pRecord;
  2237. blob.Flags = dwFlags;
  2238. blob.pNetInfo = pNetworkInfo;
  2239. blob.hCreds = hCreds;
  2240. if ( ppMsgRecv )
  2241. {
  2242. blob.fSaveRecvMsg = TRUE;
  2243. }
  2244. status = Update_FazSendFlush( &blob );
  2245. if ( ppMsgRecv )
  2246. {
  2247. *ppMsgRecv = blob.pMsgRecv;
  2248. }
  2249. DNSDBG( UPDATE, (
  2250. "Leave Dns_UpdateLib() => %d %s.\n\n",
  2251. status,
  2252. Dns_StatusString(status) ));
  2253. return( status );
  2254. #endif
  2255. }
  2256. DNS_STATUS
  2257. Dns_UpdateLibEx(
  2258. IN PDNS_RECORD pRecord,
  2259. IN DWORD dwFlags,
  2260. IN PWSTR pszZone,
  2261. IN PWSTR pszServerName,
  2262. IN PIP4_ARRAY aipServers,
  2263. IN HANDLE hCreds OPTIONAL,
  2264. OUT PDNS_MSG_BUF * ppMsgRecv OPTIONAL
  2265. )
  2266. /*++
  2267. Routine Description:
  2268. Send DNS update.
  2269. This routine builds an UPDATE compatible pNetworkInfo from the
  2270. information given. Then calls Dns_Update().
  2271. Arguments:
  2272. pRecord -- list of records to send in update
  2273. pszZone -- zone name for update
  2274. pszServerName -- server name
  2275. aipServers -- DNS servers to send update to
  2276. hCreds -- Optional Credentials info
  2277. ppMsgRecv -- addr for ptr to recv buffer, if desired
  2278. Return Value:
  2279. ERROR_SUCCESS if successful.
  2280. Error status on failure.
  2281. --*/
  2282. {
  2283. return ERROR_INVALID_PARAMETER;
  2284. #if 0
  2285. PDNS_NETINFO pnetInfo;
  2286. DNS_STATUS status = NO_ERROR;
  2287. DNSDBG( UPDATE, ( "Dns_UpdateLibEx()\n" ));
  2288. //
  2289. // convert params into UPDATE compatible adapter list
  2290. //
  2291. pnetInfo = NetInfo_CreateForUpdateIp4(
  2292. pszZone,
  2293. pszServerName,
  2294. aipServers,
  2295. 0 );
  2296. if ( !pnetInfo )
  2297. {
  2298. return( ERROR_INVALID_PARAMETER );
  2299. }
  2300. //
  2301. // call real update function
  2302. //
  2303. status = Dns_UpdateLib(
  2304. pRecord,
  2305. dwFlags,
  2306. pnetInfo,
  2307. hCreds,
  2308. ppMsgRecv );
  2309. NetInfo_Free( pnetInfo );
  2310. DNSDBG( UPDATE, (
  2311. "Leave Dns_UpdateLibEx() => %d\n",
  2312. status ));
  2313. return status;
  2314. #endif
  2315. }
  2316. DNS_STATUS
  2317. DnsUpdate(
  2318. IN PDNS_RECORD pRecord,
  2319. IN DWORD dwFlags,
  2320. IN PDNS_NETINFO pNetworkInfo,
  2321. IN HANDLE hCreds, OPTIONAL
  2322. OUT PDNS_MSG_BUF * ppMsgRecv OPTIONAL
  2323. )
  2324. /*++
  2325. Routine Description:
  2326. Send DNS update.
  2327. Note if pNetworkInfo is not specified or not a valid UPDATE adapter list,
  2328. then a FindAuthoritativeZones (FAZ) query is done prior to the update.
  2329. Arguments:
  2330. pRecord -- list of records to send in update
  2331. dwFlags -- flags to update
  2332. pNetworkInfo -- DNS servers to send update to
  2333. ppMsgRecv -- addr for ptr to recv buffer, if desired
  2334. Return Value:
  2335. ERROR_SUCCESS if successful.
  2336. Error status on failure.
  2337. --*/
  2338. {
  2339. return ERROR_INVALID_PARAMETER;
  2340. #if 0
  2341. DNS_STATUS status;
  2342. PDNS_NETINFO plocalNetworkInfo = NULL;
  2343. UPDATE_BLOB blob;
  2344. DNSDBG( TRACE, ( "DnsUpdate()\n" ));
  2345. //
  2346. // create blob
  2347. //
  2348. RtlZeroMemory( &blob, sizeof(blob) );
  2349. blob.pRecords = pRecord;
  2350. blob.Flags = dwFlags;
  2351. blob.pNetInfo = pNetworkInfo;
  2352. blob.hCreds = hCreds;
  2353. if ( ppMsgRecv )
  2354. {
  2355. blob.fSaveRecvMsg = TRUE;
  2356. }
  2357. status = Update_FazSendFlush( &blob );
  2358. if ( ppMsgRecv )
  2359. {
  2360. *ppMsgRecv = blob.pMsgRecv;
  2361. }
  2362. DNSDBG( UPDATE, (
  2363. "Leave DnsUpdate() => %d\n",
  2364. status ));
  2365. return status;
  2366. #endif
  2367. }
  2368. //
  2369. // End update.c
  2370. //