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.

6599 lines
162 KiB

  1. /*++
  2. Copyright (c) 1995-2000 Microsoft Corporation
  3. Module Name:
  4. DnsCmd.c
  5. Abstract:
  6. Command line management for DNS Server.
  7. Author:
  8. Jim Gilroy (jamesg) September 1995
  9. Revision History:
  10. Jing Chen (t-jingc) June 1998
  11. Jim Gilroy (jamesg) September 1998 cleanup
  12. --*/
  13. #include "dnsclip.h"
  14. #include "dnsc_wmi.h"
  15. #include <string.h> // strtoul()
  16. #include <time.h>
  17. #include <locale.h>
  18. #define DNSCMD_UNICODE 1 // unicode argv interface
  19. extern PWSTR
  20. getUnicodeForUtf8(
  21. IN PSTR pUtf8
  22. );
  23. extern PWSTR
  24. utf8ToUnicode(
  25. IN PSTR pszInputStr,
  26. IN DWORD dwInputLength
  27. );
  28. //
  29. // Static IP array counts
  30. // values beyond any reasonable value anyone would send
  31. //
  32. #define MAX_IP_PROPERTY_COUNT (200)
  33. //
  34. // Globals -- allow these to be viewable in processing functions
  35. //
  36. LPSTR pszServerName = NULL;
  37. LPWSTR pwszServerName = NULL;
  38. LPSTR pszCommandName = NULL;
  39. extern DWORD g_dwViewFlag;
  40. BOOL g_UseWmi = FALSE;
  41. //
  42. // Printing
  43. //
  44. #define dnscmd_PrintRoutine ((PRINT_ROUTINE) fprintf)
  45. #define dnscmd_PrintContext ((PPRINT_CONTEXT) stdout)
  46. //
  47. // Command table setup
  48. //
  49. typedef DNS_STATUS ( * COMMAND_FUNCTION )(
  50. DWORD argc,
  51. PSTR * argv,
  52. PWSTR * unicodeArgv );
  53. typedef struct _COMMAND_INFO
  54. {
  55. LPSTR pszCommandName;
  56. COMMAND_FUNCTION pCommandFunction;
  57. LPSTR pComments;
  58. }
  59. COMMAND_INFO, *LPCOMMAND_INFO;
  60. //
  61. // Command table
  62. //
  63. extern COMMAND_INFO GlobalCommandInfo[];
  64. //
  65. // Dummy Argc to command function to indicate help requested
  66. //
  67. #define NEED_HELP_ARGC (MAXDWORD)
  68. //
  69. // Private utilites
  70. //
  71. COMMAND_FUNCTION
  72. getCommandFunction(
  73. IN LPSTR pszCommandName
  74. )
  75. /*++
  76. Routine Description:
  77. Get function corresponding to command name.
  78. Arguments:
  79. pszCommandName -- command string
  80. Return Value:
  81. Ptr to command function corresponding to command name.
  82. NULL if unrecognized command.
  83. --*/
  84. {
  85. DWORD i;
  86. //
  87. // find command in list matching string
  88. //
  89. i = 0;
  90. while( GlobalCommandInfo[i].pszCommandName )
  91. {
  92. if( _stricmp(
  93. pszCommandName,
  94. GlobalCommandInfo[i].pszCommandName ) == 0 )
  95. {
  96. return( GlobalCommandInfo[i].pCommandFunction );
  97. }
  98. i++;
  99. }
  100. return NULL;
  101. }
  102. VOID
  103. printCommands(
  104. VOID
  105. )
  106. {
  107. DWORD i = 0;
  108. //
  109. // display commands
  110. // but stop display at "command barrier" (NULL function)
  111. // commands below are duplicates or hidden
  112. //
  113. while( GlobalCommandInfo[i].pszCommandName &&
  114. GlobalCommandInfo[i].pCommandFunction )
  115. {
  116. printf( " %-26s -- %s\n",
  117. GlobalCommandInfo[i].pszCommandName,
  118. GlobalCommandInfo[i].pComments );
  119. i++;
  120. }
  121. }
  122. LPSTR
  123. getCommandName(
  124. IN LPSTR pszCmd
  125. )
  126. /*++
  127. Routine Description:
  128. Get command name.
  129. Remove "/" from begining of command.
  130. Arguments:
  131. pszCmd -- command string
  132. Return Value:
  133. Ptr to command string (with no leading "/")
  134. NULL if not a command.
  135. --*/
  136. {
  137. if ( pszCmd && ( pszCmd[ 0 ] == '/' || pszCmd[ 0 ] == '-' ) )
  138. {
  139. return pszCmd + 1;
  140. }
  141. return NULL;
  142. }
  143. BOOL
  144. getUserConfirmation(
  145. IN LPSTR pszString
  146. )
  147. /*++
  148. Routine Description:
  149. Get user's confirmation on a command.
  150. Arguments:
  151. pszString -- configmation string
  152. Return Value:
  153. TRUE if confirmed.
  154. FALSE if cancelled.
  155. --*/
  156. {
  157. int ch;
  158. printf( "Are you sure you want to %s? (y/n) ", pszString );
  159. if ( ( (ch=getchar()) != EOF ) &&
  160. ( (ch == 'y') || (ch == 'Y') ) )
  161. {
  162. printf("\n");
  163. return( TRUE );
  164. }
  165. else
  166. {
  167. printf("\nCommand cancelled!\n");
  168. return( FALSE );
  169. }
  170. }
  171. DWORD
  172. convertDwordParameterUnknownBase(
  173. IN LPSTR pszParam
  174. )
  175. {
  176. INT base = 10;
  177. if ( *pszParam > '9' || (*pszParam == '0' && *(pszParam+1) > '9') )
  178. {
  179. // hex conversion
  180. base = 16;
  181. }
  182. return strtoul(
  183. pszParam,
  184. NULL,
  185. base );
  186. }
  187. DWORD
  188. readIpAddressArray(
  189. OUT PIP_ADDRESS pAddrArray,
  190. IN DWORD ArraySize,
  191. IN DWORD Argc,
  192. IN LPSTR * Argv,
  193. IN BOOL fInaddrNoneAllowed
  194. )
  195. /*++
  196. Routine Description:
  197. Read IP array.
  198. Arguments:
  199. pIpArray -- IP array buffer
  200. ArraySize -- IPs array can handle
  201. Argc -- remaining Argc
  202. Argv -- remaining Argv
  203. fInaddrNoneAllowed -- if TRUE, 255.255.255.255 is a valid input
  204. Return Value:
  205. Count of IP in array.
  206. --*/
  207. {
  208. DWORD count = 0;
  209. IP_ADDRESS ip;
  210. while ( Argc && count < ArraySize )
  211. {
  212. ip = inet_addr( Argv[0] );
  213. //
  214. // Allow INADDR_NONE if that address really was specified
  215. // and it is allowed as a valid input.
  216. //
  217. if ( ip == INADDR_NONE &&
  218. ( !fInaddrNoneAllowed ||
  219. strcmp( Argv[ 0 ], "255.255.255.255" ) != 0 ) )
  220. {
  221. break;
  222. }
  223. pAddrArray[ count ] = ip;
  224. count++;
  225. Argc--;
  226. Argv++;
  227. }
  228. return count;
  229. }
  230. INT
  231. ReadArgsIntoDnsTypeArray(
  232. OUT PWORD pTypeArray,
  233. IN INT ArraySize,
  234. IN INT Argc,
  235. IN LPSTR * Argv
  236. )
  237. /*++
  238. Routine Description:
  239. Read list of DNS type strings into a WORD array, one type value
  240. per word. The DNS types can be in numeric form or alpha form.
  241. e.g. "6" or "SOA"
  242. If the types are in alpha form, type strings that cannot be interpreted
  243. are not added to the array.
  244. DEVNOTE: This is for setting the NoRoundRobin type list, which I have
  245. not yet implemented via RPC.
  246. Arguments:
  247. pIpArray -- IP array buffer
  248. ArraySize -- IPs array can handle
  249. Argc -- number of arguments
  250. Argv -- pointer to arguments
  251. Return Value:
  252. Number of types successfully processed into array.
  253. --*/
  254. {
  255. INT typeIdx;
  256. for ( typeIdx = 0; Argc && typeIdx < ArraySize; --Argc, ++Argv )
  257. {
  258. if ( isdigit( *Argv[ 0 ] ) )
  259. {
  260. pTypeArray[ typeIdx++ ] = ( WORD ) atoi( *Argv );
  261. }
  262. else
  263. {
  264. WORD wType;
  265. wType = Dns_RecordTypeForName(
  266. *Argv,
  267. 0 ); // null-terminated
  268. if ( wType != 0 )
  269. {
  270. pTypeArray[ typeIdx++ ] = wType;
  271. }
  272. }
  273. }
  274. return typeIdx;
  275. } // ReadArgsIntoDnsTypeArray
  276. DWORD
  277. parseZoneTypeString(
  278. IN LPSTR pszZoneType,
  279. OUT BOOL * pfDsIntegrated
  280. )
  281. /*++
  282. Routine Description:
  283. Get command name.
  284. Remove "/" from beggining of command.
  285. NULL if error (no "/")
  286. Arguments:
  287. pszZoneType -- zone type string, e.g. "Secondary" or "2"
  288. pfDsIntegrated -- does type indicate zone should be DS integrated?
  289. Return Value:
  290. DNS_ZONE_TYPE_XXX constant matching zone type or -1 if the type
  291. cannot be matched.
  292. --*/
  293. {
  294. DWORD zoneType = -1;
  295. ASSERT( pfDsIntegrated && pszZoneType );
  296. *pfDsIntegrated = FALSE;
  297. if ( *pszZoneType == '//' )
  298. {
  299. ++pszZoneType;
  300. }
  301. if ( !_stricmp( pszZoneType, "Primary" ) ||
  302. !_stricmp( pszZoneType, "1" ) )
  303. {
  304. zoneType = DNS_ZONE_TYPE_PRIMARY;
  305. }
  306. else if ( !_stricmp( pszZoneType, "DsPrimary" ) )
  307. {
  308. zoneType = DNS_ZONE_TYPE_PRIMARY;
  309. *pfDsIntegrated = TRUE;
  310. }
  311. else if ( !_stricmp( pszZoneType, "Secondary" ) ||
  312. !_stricmp( pszZoneType, "2" ) )
  313. {
  314. zoneType = DNS_ZONE_TYPE_SECONDARY;
  315. }
  316. else if ( !_stricmp( pszZoneType, "Stub" ) ||
  317. !_stricmp( pszZoneType, "3" ) )
  318. {
  319. zoneType = DNS_ZONE_TYPE_STUB;
  320. }
  321. else if ( !_stricmp( pszZoneType, "DsStub" ) )
  322. {
  323. zoneType = DNS_ZONE_TYPE_STUB;
  324. *pfDsIntegrated = TRUE;
  325. }
  326. else if ( !_stricmp( pszZoneType, "Forwarder" ) ||
  327. !_stricmp( pszZoneType, "4" ) )
  328. {
  329. zoneType = DNS_ZONE_TYPE_FORWARDER;
  330. }
  331. else if ( !_stricmp( pszZoneType, "DsForwarder" ) )
  332. {
  333. zoneType = DNS_ZONE_TYPE_FORWARDER;
  334. *pfDsIntegrated = TRUE;
  335. }
  336. return zoneType;
  337. }
  338. BOOL
  339. parseDpSpecifier(
  340. IN LPSTR pszDpName,
  341. OUT DWORD * pdwDpFlag, OPTIONAL
  342. OUT LPSTR * ppszCustomDpName
  343. )
  344. /*++
  345. Routine Description:
  346. Parses a directory partition name. Valid specifiers:
  347. /DomainDefault
  348. /ForestDefault
  349. /Legacy
  350. Anything that does not start with "/" is assumed to be the
  351. name of a custom DP.
  352. If pdwDpFlag is non-NULL, then for a built-in partition
  353. ppszCustomDpName will be NULL and the appropriate DWORD flag
  354. value will be set at pdwDpFlag. If pdwDpFlag is NULL, then
  355. for built-in partitions ppszCustomDpName will be pointed to
  356. a static string such as DNS_DP_LEGACY_STR.
  357. Arguments:
  358. pszDpName - name to be parsed - must be NULL-terminated
  359. pdwDpFlag - flag if DP is builtin, zero if custom
  360. ppszCustomDpName - set to ptr within pszDpName for customer
  361. Return Value:
  362. FALSE if the specifier does not appear to be valid (e.g. is empty).
  363. --*/
  364. {
  365. BOOL rc = TRUE;
  366. static const LPSTR pszStaticLegacy = DNS_DP_LEGACY_STR;
  367. static const LPSTR pszStaticDomain = DNS_DP_DOMAIN_STR;
  368. static const LPSTR pszStaticForest = DNS_DP_FOREST_STR;
  369. if ( !ppszCustomDpName || !pszDpName || !*pszDpName )
  370. {
  371. rc = FALSE;
  372. }
  373. else
  374. {
  375. if ( pdwDpFlag )
  376. {
  377. *pdwDpFlag = 0;
  378. }
  379. *ppszCustomDpName = NULL;
  380. if ( *pszDpName == '/' || strncmp( pszDpName, "..", 2 ) == 0 )
  381. {
  382. // Skip over preamble character(s).
  383. ++pszDpName;
  384. if ( *pszDpName == '.' )
  385. {
  386. ++pszDpName;
  387. }
  388. if ( toupper( *pszDpName ) == 'F' )
  389. {
  390. if ( pdwDpFlag )
  391. *pdwDpFlag |= DNS_DP_FOREST_DEFAULT;
  392. else
  393. *ppszCustomDpName = pszStaticForest;
  394. }
  395. else if ( toupper( *pszDpName ) == 'D' )
  396. {
  397. if ( pdwDpFlag )
  398. *pdwDpFlag |= DNS_DP_DOMAIN_DEFAULT;
  399. else
  400. *ppszCustomDpName = pszStaticDomain;
  401. }
  402. else if ( toupper( *pszDpName ) == 'L' )
  403. {
  404. if ( pdwDpFlag )
  405. *pdwDpFlag |= DNS_DP_LEGACY;
  406. else
  407. *ppszCustomDpName = pszStaticLegacy;
  408. }
  409. else
  410. {
  411. rc = FALSE;
  412. }
  413. }
  414. else
  415. {
  416. *ppszCustomDpName = pszDpName;
  417. }
  418. }
  419. return rc;
  420. } // parseDpSpecifier
  421. DWORD
  422. readIpArray(
  423. OUT PIP_ARRAY pIpArray,
  424. IN DWORD ArraySize,
  425. IN DWORD Argc,
  426. IN LPSTR * Argv
  427. )
  428. /*++
  429. Routine Description:
  430. Read IP array.
  431. Wrapper around readIpAddressArray, to build IP_ARRAY structure.
  432. Arguments:
  433. pIpArray -- IP array to write into
  434. ArraySize -- IPs array can handle
  435. Argc -- remaining Argc
  436. Argv -- remaining Argv
  437. Return Value:
  438. Count of IP in array.
  439. --*/
  440. {
  441. DWORD count;
  442. count = readIpAddressArray(
  443. pIpArray->AddrArray,
  444. ArraySize,
  445. Argc,
  446. Argv,
  447. FALSE );
  448. pIpArray->AddrCount = count;
  449. return count;
  450. }
  451. BOOL
  452. readZoneAndDomainName(
  453. IN LPSTR * Argv,
  454. OUT LPSTR * ppZoneName,
  455. OUT LPSTR * ppNodeName,
  456. OUT PBOOL pbAllocatedNode,
  457. OUT LPSTR * ppZoneArg, OPTIONAL
  458. OUT LPSTR * ppNodeArg OPTIONAL
  459. )
  460. /*++
  461. Routine Description:
  462. Read zone and domain name.
  463. Build node FQDN if required.
  464. Arguments:
  465. Argv -- argv with zone and node names
  466. ppZoneName -- addr to receive ptr to zone name
  467. ppNodeName -- addr to receive ptr to node name
  468. pbAllocatedNode -- ptr to bool set TRUE if allocate node name
  469. ppZoneArg -- addr to receive ptr to zone argument
  470. ppNodeArg -- addr to receive ptr to node argument
  471. Return Value:
  472. TRUE -- if in authoritative zone
  473. FALSE -- if cache or root hints
  474. --*/
  475. {
  476. LPSTR pzoneName;
  477. LPSTR pnodeName;
  478. LPSTR pzoneArg;
  479. LPSTR pnodeArg;
  480. BOOL ballocated = FALSE;
  481. BOOL bauthZone = TRUE;
  482. //
  483. // read zone name
  484. // - special case RootHints and Cache
  485. // setting zone to special string
  486. //
  487. pzoneName = pzoneArg = *Argv;
  488. if ( *pzoneArg == '/' )
  489. {
  490. if ( _stricmp( pzoneArg, "/RootHints" ) == 0 )
  491. {
  492. pzoneName = DNS_ZONE_ROOT_HINTS_A;
  493. bauthZone = FALSE;
  494. }
  495. else if ( _stricmp( pzoneArg, "/Cache" ) == 0 )
  496. {
  497. pzoneName = DNS_ZONE_CACHE_A;
  498. bauthZone = FALSE;
  499. }
  500. }
  501. else if ( *pzoneArg == '.' )
  502. {
  503. if ( _stricmp( pzoneArg, "..RootHints" ) == 0 )
  504. {
  505. pzoneName = DNS_ZONE_ROOT_HINTS_A;
  506. bauthZone = FALSE;
  507. }
  508. else if ( _stricmp( pzoneArg, "..Cache" ) == 0 )
  509. {
  510. pzoneName = DNS_ZONE_CACHE_A;
  511. bauthZone = FALSE;
  512. }
  513. }
  514. Argv++;
  515. //
  516. // Node name
  517. // - for zones, accept file format and append zone name
  518. // - root hints or cache must be FQDN
  519. //
  520. pnodeArg = *Argv;
  521. if ( bauthZone )
  522. {
  523. if ( strcmp( pnodeArg, "@" ) == 0 )
  524. {
  525. pnodeName = pzoneName;
  526. }
  527. else if ( Dns_IsNameFQDN( pnodeArg ) )
  528. {
  529. // input pnodeName is FQDN, with a trailing dot
  530. pnodeName = pnodeArg;
  531. }
  532. else
  533. {
  534. //append zone name to the end of pnodeName
  535. pnodeName = malloc( 2 + strlen(pzoneName) + strlen(pnodeArg) );
  536. if ( pnodeName )
  537. {
  538. strcpy ( pnodeName, pnodeArg );
  539. strcat ( pnodeName, "." );
  540. strcat ( pnodeName, pzoneName );
  541. ballocated = TRUE;
  542. }
  543. }
  544. }
  545. else
  546. {
  547. pnodeName = *Argv;
  548. }
  549. //
  550. // set out params
  551. //
  552. if ( ppZoneName )
  553. {
  554. *ppZoneName = pzoneName;
  555. }
  556. if ( ppNodeName )
  557. {
  558. *ppNodeName = pnodeName;
  559. }
  560. if ( pbAllocatedNode )
  561. {
  562. *pbAllocatedNode = ballocated;
  563. }
  564. if ( ppZoneArg )
  565. {
  566. *ppZoneArg = pzoneArg;
  567. }
  568. if ( ppNodeArg )
  569. {
  570. *ppNodeArg = pnodeArg;
  571. }
  572. return bauthZone;
  573. }
  574. DNS_STATUS
  575. getServerVersion(
  576. IN LPWSTR pwszServerName,
  577. IN BOOL fPrintVersion,
  578. OUT PDWORD pdwMajorVersion, OPTIONAL
  579. OUT PDWORD pdwMinorVersion, OPTIONAL
  580. OUT PDWORD pdwBuildNum, OPTIONAL
  581. OUT PDWORD pdwDomainVersion
  582. )
  583. /*++
  584. Routine Description:
  585. Query server for version information.
  586. Arguments:
  587. pwszServerName -- name of DNS server
  588. fPrintVersion -- if TRUE this function will print one-line server version
  589. pdwMajorVersion -- ptr to DWORD to receive major version or NULL
  590. pdwMinorVersion -- ptr to DWORD to receive minor version or NULL
  591. pdwBuildNum -- ptr to DWORD to receive build number or NULL
  592. pdwDomainVersion -- ptr to DWORD to receive domain behavior version or NULL
  593. Return Value:
  594. Status code.
  595. --*/
  596. {
  597. DNS_STATUS status = ERROR_SUCCESS;
  598. DWORD dataType;
  599. PDNS_RPC_SERVER_INFO pServerInfo = NULL;
  600. DWORD dwMajorVersion = 0;
  601. DWORD dwMinorVersion = 0;
  602. DWORD dwBuildNum = 0;
  603. DWORD dwDomainVersion = 0;
  604. //
  605. // Retrieve server info.
  606. //
  607. status = DnssrvQuery(
  608. pwszServerName,
  609. NULL, // zone
  610. DNSSRV_QUERY_SERVER_INFO,
  611. &dataType,
  612. &pServerInfo );
  613. if ( status != ERROR_SUCCESS )
  614. {
  615. goto Done;
  616. }
  617. if ( !pServerInfo || dataType != DNSSRV_TYPEID_SERVER_INFO )
  618. {
  619. status = ERROR_NOT_FOUND;
  620. goto Done;
  621. }
  622. //
  623. // Parse version.
  624. //
  625. dwMajorVersion = pServerInfo->dwVersion & 0x000000FF;
  626. dwMinorVersion = ( pServerInfo->dwVersion & 0x0000FF00 ) >> 8;
  627. dwBuildNum = pServerInfo->dwVersion >> 16;
  628. dwDomainVersion = pServerInfo->dwDsDomainVersion;
  629. //
  630. // Optionally print version.
  631. //
  632. if ( fPrintVersion )
  633. {
  634. printf( "DNS server %S version is %d.%d.%d",
  635. pwszServerName,
  636. dwMajorVersion,
  637. dwMinorVersion,
  638. dwBuildNum );
  639. #if DBG
  640. printf( ", domain version is %d",
  641. dwDomainVersion );
  642. #endif
  643. printf( "\n\n" );
  644. }
  645. //
  646. // Store version numbers to output destinations.
  647. //
  648. Done:
  649. if ( pdwMajorVersion )
  650. {
  651. *pdwMajorVersion = dwMajorVersion;
  652. }
  653. if ( pdwMinorVersion )
  654. {
  655. *pdwMinorVersion = dwMinorVersion;
  656. }
  657. if ( pdwBuildNum )
  658. {
  659. *pdwBuildNum = dwBuildNum;
  660. }
  661. if ( pdwDomainVersion )
  662. {
  663. *pdwDomainVersion = dwDomainVersion;
  664. }
  665. return status;
  666. } // getServerVersion
  667. DNS_STATUS
  668. processCacheSizeQuery(
  669. LPWSTR pwszServerName
  670. )
  671. /*++
  672. Routine Description:
  673. Query server and print current cache usage.
  674. Arguments:
  675. pwszServerName -- name of DNS server
  676. Return Value:
  677. Status code.
  678. --*/
  679. {
  680. DNS_STATUS status = ERROR_SUCCESS;
  681. PDNS_RPC_BUFFER pStatBuff = NULL;
  682. PDNSSRV_MEMORY_STATS pMemStats = NULL;
  683. PDNSSRV_STAT pStat;
  684. PCHAR pch;
  685. PCHAR pchstop;
  686. //
  687. // Print server version
  688. //
  689. getServerVersion(
  690. pwszServerName,
  691. TRUE,
  692. NULL, NULL, NULL, NULL );
  693. //
  694. // Retrieve statistics from server.
  695. //
  696. status = DnssrvGetStatistics(
  697. pwszServerName,
  698. DNSSRV_STATID_MEMORY,
  699. &pStatBuff );
  700. if ( status != ERROR_SUCCESS )
  701. {
  702. goto Done;
  703. }
  704. if ( !pStatBuff )
  705. {
  706. printf( "Error: statistics buffer missing\n" );
  707. goto Done;
  708. }
  709. //
  710. // Loop through returned stats to find memory stats.
  711. //
  712. pch = pStatBuff->Buffer;
  713. pchstop = pch + pStatBuff->dwLength;
  714. while ( pch < pchstop )
  715. {
  716. pStat = ( PDNSSRV_STAT ) pch;
  717. pch = ( PCHAR ) GET_NEXT_STAT_IN_BUFFER( pStat );
  718. if ( pch > pchstop )
  719. {
  720. printf( "Error: invalid stats buffer\n" );
  721. goto Done;
  722. }
  723. // printf( "Found stat ID %08X\n", pStat->Header.StatId );
  724. if ( pStat->Header.StatId == DNSSRV_STATID_MEMORY )
  725. {
  726. pMemStats = ( PDNSSRV_MEMORY_STATS ) pStat;
  727. break;
  728. }
  729. }
  730. if ( pMemStats == NULL )
  731. {
  732. printf( "Error: unable to retrieve memory statistics\n" );
  733. status = ERROR_NOT_SUPPORTED;
  734. goto Done;
  735. }
  736. //
  737. // Print results.
  738. //
  739. printf( "Cache usage for server %S is %d bytes:\n"
  740. " Nodes: %d (%d bytes)\n"
  741. " RRs: %d (%d bytes)\n",
  742. pwszServerName,
  743. pMemStats->MemTags[ MEMTAG_NODE_CACHE ].Memory +
  744. pMemStats->MemTags[ MEMTAG_RECORD_CACHE ].Memory,
  745. pMemStats->MemTags[ MEMTAG_NODE_CACHE ].Alloc -
  746. pMemStats->MemTags[ MEMTAG_NODE_CACHE ].Free,
  747. pMemStats->MemTags[ MEMTAG_NODE_CACHE ].Memory,
  748. pMemStats->MemTags[ MEMTAG_RECORD_CACHE ].Alloc -
  749. pMemStats->MemTags[ MEMTAG_RECORD_CACHE ].Free,
  750. pMemStats->MemTags[ MEMTAG_RECORD_CACHE ].Memory);
  751. Done:
  752. return status;
  753. } // processCacheSizeQuery
  754. //
  755. // Prototypes for forward references.
  756. //
  757. DNS_STATUS
  758. ProcessDisplayAllZoneRecords(
  759. IN DWORD Argc,
  760. IN LPSTR * Argv,
  761. IN LPWSTR * UnicodeArgv
  762. );
  763. //
  764. // DnsCmd entry point
  765. //
  766. INT
  767. __cdecl
  768. wmain(
  769. IN int argc,
  770. IN PWSTR * Argv
  771. )
  772. /*++
  773. Routine Description:
  774. DnsCmd program entry point.
  775. Executes specified command corresponding to a DNS Server API
  776. call, using the specified server name.
  777. Arguments:
  778. argc -- arg count
  779. argv -- argument list
  780. argv[1] -- DNS ServerName
  781. argv[2] -- Command to execute
  782. argv[3...] -- arguments to command
  783. Return Value:
  784. Return from the desired command. Usually a pass through of the return
  785. code from DNS API call.
  786. --*/
  787. {
  788. DNS_STATUS status = ERROR_SUCCESS;
  789. COMMAND_FUNCTION pcommandFunc;
  790. DWORD commandArgc;
  791. LPSTR * commandArgv;
  792. LPSTR parg1;
  793. WSADATA wsadata;
  794. PSTR * argv = NULL;
  795. PWSTR * unicodeArgv = Argv;
  796. int i;
  797. UINT codepage;
  798. char achCodepage[12] = ".OCP";
  799. //
  800. // Initialize localization stuff - so that printf() of non-US characters
  801. // will work properly. I stole this code from dcdiag.
  802. //
  803. if ( codepage = GetConsoleOutputCP() )
  804. {
  805. sprintf( achCodepage, ".%u", codepage );
  806. setlocale( LC_ALL, achCodepage );
  807. }
  808. else
  809. {
  810. //
  811. // We do this because LC_ALL sets the LC_CTYPE as well, and we're
  812. // not supposed to do that, say the experts if we're setting the
  813. // locale to ".OCP".
  814. //
  815. setlocale( LC_COLLATE, achCodepage ); // sets the sort order
  816. setlocale( LC_MONETARY, achCodepage ); // sets the currency formatting rules
  817. setlocale( LC_NUMERIC, achCodepage ); // sets the formatting of numerals
  818. setlocale( LC_TIME, achCodepage ); // defines the date/time formatting
  819. }
  820. //
  821. // Initialize debug logging.
  822. //
  823. DnssrvInitializeDebug();
  824. //
  825. // Initialize Winsock in case we want to call any Winsock functions.
  826. //
  827. WSAStartup( MAKEWORD( 2, 0 ), &wsadata );
  828. //
  829. // Convert Unicode arguments to UTF8.
  830. //
  831. argv = ALLOCATE_HEAP( ( argc + 1 ) * sizeof( PCHAR ) );
  832. for ( i = 0; i < argc; ++i )
  833. {
  834. argv[ i ] = Dns_NameCopyAllocate(
  835. ( PCHAR ) Argv[ i ],
  836. 0, // no given length (use strlen)
  837. DnsCharSetUnicode,
  838. DnsCharSetUtf8 );
  839. }
  840. argv[ i ] = NULL;
  841. //
  842. // DnsCmd <ServerName> [/WMI] <Command> [<Command Parameters>]
  843. //
  844. // Skip EXE name parameter.
  845. //
  846. if ( argc < 2 )
  847. {
  848. goto Help;
  849. }
  850. --argc;
  851. ++argv;
  852. ++unicodeArgv;
  853. //
  854. // DNS server IP address/name parameter
  855. //
  856. pszServerName = argv[ 0 ];
  857. if ( *pszServerName == '/' )
  858. {
  859. pszServerName = ".";
  860. }
  861. else
  862. {
  863. argc--;
  864. argv++;
  865. unicodeArgv++;
  866. }
  867. pwszServerName = Dns_NameCopyAllocate(
  868. pszServerName,
  869. 0, // no given length (use strlen)
  870. DnsCharSetUtf8,
  871. DnsCharSetUnicode );
  872. //
  873. // Check for optional WMI parameter.
  874. //
  875. if ( argc && argv[ 0 ] && _stricmp( argv[ 0 ], "/WMI" ) == 0 )
  876. {
  877. g_UseWmi = TRUE;
  878. --argc;
  879. ++argv;
  880. ++unicodeArgv;
  881. if ( argc < 1 )
  882. {
  883. goto Help;
  884. }
  885. status = DnscmdWmi_Initialize( pwszServerName );
  886. if ( status != ERROR_SUCCESS )
  887. {
  888. printf(
  889. "Fatal error 0x%08X during WMI initialization to server \"%S\"\n",
  890. status,
  891. pwszServerName );
  892. goto Done;
  893. }
  894. printf(
  895. "Opened WMI connection to server \"%S\"\n\n",
  896. pwszServerName );
  897. }
  898. //
  899. // next parameter is command name, retrieve associated function
  900. //
  901. if ( argc == 0 )
  902. {
  903. status = ERROR_SUCCESS;
  904. goto Help;
  905. }
  906. pszCommandName = argv[0];
  907. pcommandFunc = getCommandFunction( pszCommandName );
  908. if( !pcommandFunc )
  909. {
  910. if ( _stricmp( pszCommandName, "/?" ) == 0 ||
  911. _stricmp( pszCommandName, "/help" ) == 0 )
  912. {
  913. status = ERROR_SUCCESS;
  914. }
  915. else
  916. {
  917. status = ERROR_INVALID_PARAMETER;
  918. printf(
  919. "Unknown Command \"%s\" Specified -- type DnsCmd -?.\n",
  920. pszCommandName );
  921. }
  922. goto Help;
  923. }
  924. //
  925. // set argc, argv for rest of parameters
  926. //
  927. commandArgc = (DWORD)(argc - 1);
  928. commandArgv = &argv[1];
  929. //
  930. // test for help request on specific command
  931. // - if found, dispatch with Argc=0, to force help
  932. //
  933. if ( commandArgc > 0 )
  934. {
  935. parg1 = commandArgv[0];
  936. if ( *parg1 == '?' ||
  937. _stricmp( parg1, "/?" ) == 0 ||
  938. _stricmp( parg1, "/help" ) == 0 )
  939. {
  940. commandArgc = NEED_HELP_ARGC;
  941. }
  942. }
  943. //
  944. // dispatch to processor for this command
  945. //
  946. status = pcommandFunc( commandArgc, commandArgv, &unicodeArgv[ 1 ] );
  947. Dns_EndDebug();
  948. if ( commandArgc != NEED_HELP_ARGC && status != ERROR_SUCCESS )
  949. {
  950. printf( "\nCommand failed: %s %ld (%08lx)\n",
  951. Dns_StatusString( status ),
  952. status, status );
  953. if ( status == ERROR_INVALID_PARAMETER )
  954. {
  955. printf( "\nCheck the required arguments and format of your command.\n" );
  956. }
  957. }
  958. else
  959. {
  960. //
  961. // Do not output success message for commands where the output
  962. // may be piped to file for a specific use (e.g. zone file output).
  963. if ( pcommandFunc != ProcessDisplayAllZoneRecords &&
  964. commandArgc != NEED_HELP_ARGC )
  965. {
  966. printf( "Command completed successfully.\n" );
  967. }
  968. }
  969. goto Done;
  970. //
  971. // Output help text.
  972. //
  973. Help:
  974. printf(
  975. "\nUsage: DnsCmd <ServerName> <Command> [<Command Parameters>]\n\n"
  976. "<ServerName>:\n"
  977. " IP address or host name -- remote or local DNS server\n"
  978. " . -- DNS server on local machine\n"
  979. "<Command>:\n" );
  980. printCommands();
  981. printf(
  982. "\n<Command Parameters>:\n"
  983. " DnsCmd <CommandName> /? -- For help info on specific Command\n" );
  984. //
  985. // Cleanup and return.
  986. //
  987. Done:
  988. if ( g_UseWmi )
  989. {
  990. DnscmdWmi_Free();
  991. }
  992. WSACleanup();
  993. return status;
  994. }
  995. //
  996. // Command Functions
  997. //
  998. //
  999. // Info Query -- for Server or Zone
  1000. //
  1001. DNS_STATUS
  1002. ProcessInfo(
  1003. IN DWORD Argc,
  1004. IN LPSTR * Argv,
  1005. IN LPWSTR * UnicodeArgv
  1006. )
  1007. {
  1008. DNS_STATUS status = ERROR_SUCCESS;
  1009. DWORD typeid;
  1010. PVOID pdata;
  1011. LPCSTR pszQueryName;
  1012. //
  1013. // /Info [<PropertyName>]
  1014. //
  1015. // get specific property to query -- if given
  1016. // if not specific query, default to ZONE_INFO
  1017. //
  1018. if ( Argc == 0 )
  1019. {
  1020. pszQueryName = DNSSRV_QUERY_SERVER_INFO;
  1021. }
  1022. else if ( Argc == 1 )
  1023. {
  1024. //
  1025. // Allow property name to be bare or preceded by command char.
  1026. //
  1027. pszQueryName = getCommandName( Argv[0] );
  1028. if ( !pszQueryName )
  1029. {
  1030. pszQueryName = Argv[ 0 ];
  1031. }
  1032. }
  1033. else
  1034. {
  1035. goto Help;
  1036. }
  1037. //
  1038. // Handle meta-queries: queries that involve client-side parsing
  1039. //
  1040. if ( _stricmp( pszQueryName, "CacheSize" ) == 0 )
  1041. {
  1042. status = processCacheSizeQuery( pwszServerName );
  1043. }
  1044. else
  1045. {
  1046. //
  1047. // query, print result on success
  1048. //
  1049. if ( g_UseWmi )
  1050. {
  1051. status = DnscmdWmi_ProcessDnssrvQuery(
  1052. NULL, // zone
  1053. pszQueryName );
  1054. }
  1055. else
  1056. {
  1057. status = DnssrvQuery(
  1058. pwszServerName,
  1059. NULL, // no zone
  1060. pszQueryName, // query name
  1061. & typeid,
  1062. & pdata );
  1063. if ( status == ERROR_SUCCESS )
  1064. {
  1065. printf( "Query result:\n" );
  1066. DnsPrint_RpcUnion(
  1067. dnscmd_PrintRoutine,
  1068. dnscmd_PrintContext,
  1069. NULL,
  1070. typeid,
  1071. pdata );
  1072. }
  1073. }
  1074. if ( status != ERROR_SUCCESS )
  1075. {
  1076. printf(
  1077. "Info query failed\n"
  1078. " status = %d (0x%08lx)\n",
  1079. status, status );
  1080. }
  1081. }
  1082. return status;
  1083. Help:
  1084. printf(
  1085. "Usage: DnsCmd <Server> /Info [<Property>]\n"
  1086. " <Property> -- server property to view\n"
  1087. " Examples:\n"
  1088. " BootMethod\n"
  1089. " RpcProtocol\n"
  1090. " LogLevel\n"
  1091. " EventlogLevel\n"
  1092. " NoRecursion\n"
  1093. " ForwardDelegations\n"
  1094. " ForwardingTimeout\n"
  1095. " IsSlave\n"
  1096. " SecureResponses\n"
  1097. " RecursionRetry\n"
  1098. " RecursionTimeout\n"
  1099. " " DNS_REGKEY_ADDITIONAL_RECURSION_TIMEOUT "\n"
  1100. " MaxCacheTtl\n"
  1101. " MaxNegativeCacheTtl\n"
  1102. " RoundRobin\n"
  1103. " LocalNetPriority\n"
  1104. " AddressAnswerLimit\n"
  1105. " BindSecondaries\n"
  1106. " WriteAuthorityNs\n"
  1107. " NameCheckFlag\n"
  1108. " StrictFileParsing\n"
  1109. " UpdateOptions\n"
  1110. " DisableAutoReverseZones\n"
  1111. " SendPort\n"
  1112. " NoTcp\n"
  1113. " XfrConnectTimeout\n"
  1114. " DsPollingInterval\n"
  1115. " ScavengingInterval\n"
  1116. " DefaultAgingState\n"
  1117. " DefaultNoRefreshInterval\n"
  1118. " DefaultRefreshInterval\n" );
  1119. return ERROR_INVALID_PARAMETER;
  1120. }
  1121. DNS_STATUS
  1122. ProcessZoneInfo(
  1123. IN DWORD Argc,
  1124. IN LPSTR * Argv,
  1125. IN LPWSTR * UnicodeArgv
  1126. )
  1127. {
  1128. DNS_STATUS status = ERROR_SUCCESS;
  1129. DWORD typeid;
  1130. PVOID pdata;
  1131. LPCSTR pqueryName;
  1132. //
  1133. // /ZoneInfo <ZoneName> [<PropertyName>]
  1134. //
  1135. // get specific query -- if given
  1136. // if not specific query, default to ZONE_INFO
  1137. //
  1138. if ( Argc == 1 )
  1139. {
  1140. pqueryName = DNSSRV_QUERY_ZONE_INFO;
  1141. }
  1142. else if ( Argc == 2 )
  1143. {
  1144. pqueryName = getCommandName( Argv[1] );
  1145. if ( !pqueryName )
  1146. {
  1147. pqueryName = Argv[1];
  1148. }
  1149. }
  1150. else
  1151. {
  1152. goto Help;
  1153. }
  1154. //
  1155. // query, print result on success
  1156. //
  1157. if ( g_UseWmi )
  1158. {
  1159. status = DnscmdWmi_ProcessZoneInfo(
  1160. Argv[ 0 ] );
  1161. }
  1162. else
  1163. {
  1164. status = DnssrvQuery(
  1165. pwszServerName,
  1166. Argv[0], // zone name
  1167. pqueryName, // query name
  1168. &typeid,
  1169. &pdata );
  1170. if ( status == ERROR_SUCCESS )
  1171. {
  1172. printf( "Zone query result:\n" );
  1173. DnsPrint_RpcUnion(
  1174. dnscmd_PrintRoutine,
  1175. dnscmd_PrintContext,
  1176. NULL,
  1177. typeid,
  1178. pdata );
  1179. }
  1180. else
  1181. {
  1182. printf(
  1183. "Zone info query failed\n"
  1184. " status = %d (0x%08lx)\n",
  1185. status, status );
  1186. }
  1187. }
  1188. return status;
  1189. Help:
  1190. printf(
  1191. "Usage: DnsCmd <Server> /ZoneInfo <ZoneName> [<Property>]\n"
  1192. " <Property> -- zone property to view\n"
  1193. " Examples:\n"
  1194. " AllowUpdate\n"
  1195. " DsIntegrated\n"
  1196. " Aging\n"
  1197. " RefreshInterval\n"
  1198. " NoRefreshInterval\n" );
  1199. return ERROR_INVALID_PARAMETER;
  1200. }
  1201. //
  1202. // Simple server operations
  1203. //
  1204. DNS_STATUS
  1205. ProcessSimpleServerOperation(
  1206. IN DWORD Argc,
  1207. IN LPSTR * Argv,
  1208. IN LPWSTR * UnicodeArgv
  1209. )
  1210. {
  1211. DNS_STATUS status = ERROR_SUCCESS;
  1212. LPSTR cmd;
  1213. //
  1214. // <Simple Server Command> no parameters
  1215. // Commands:
  1216. // - DebugBreak
  1217. // - ClearDebugLog
  1218. // - Restart
  1219. // - DisplayCache
  1220. // - Reload
  1221. //
  1222. if ( Argc != 0 )
  1223. {
  1224. printf( "Usage: DnsCmd <ServerName> %s%s\n",
  1225. ( pszCommandName && *pszCommandName != '/' ) ? "/" : "",
  1226. pszCommandName );
  1227. return ERROR_INVALID_PARAMETER;
  1228. }
  1229. if ( g_UseWmi )
  1230. {
  1231. status = DnscmdWmi_ProcessDnssrvOperation(
  1232. NULL,
  1233. getCommandName( pszCommandName ),
  1234. DNSSRV_TYPEID_NULL,
  1235. ( PVOID ) NULL );
  1236. }
  1237. else
  1238. {
  1239. status = DnssrvOperation(
  1240. pwszServerName,
  1241. NULL,
  1242. getCommandName( pszCommandName ),
  1243. DNSSRV_TYPEID_NULL,
  1244. NULL );
  1245. }
  1246. if ( status == ERROR_SUCCESS )
  1247. {
  1248. printf(
  1249. "%s completed successfully.\n",
  1250. pszServerName );
  1251. }
  1252. else
  1253. {
  1254. printf(
  1255. "%s failed: status = %d (0x%08lx).\n",
  1256. pszServerName,
  1257. status, status );
  1258. }
  1259. return status;
  1260. }
  1261. DNS_STATUS
  1262. ProcessAutoConfigure(
  1263. IN DWORD Argc,
  1264. IN LPSTR * Argv,
  1265. IN LPWSTR * UnicodeArgv
  1266. )
  1267. {
  1268. DNS_STATUS status = ERROR_SUCCESS;
  1269. LPSTR cmd;
  1270. DWORD iarg = 0;
  1271. DWORD dwflag = 0;
  1272. while ( iarg < Argc )
  1273. {
  1274. cmd = getCommandName( Argv[ iarg ] );
  1275. if ( cmd )
  1276. {
  1277. if ( !_strnicmp( cmd, "For", 3 ) )
  1278. {
  1279. dwflag |= DNS_RPC_AUTOCONFIG_FORWARDERS;
  1280. }
  1281. else if ( !_strnicmp( cmd, "Roo", 3 ) )
  1282. {
  1283. dwflag |= DNS_RPC_AUTOCONFIG_ROOTHINTS;
  1284. }
  1285. else if ( !_strnicmp( cmd, "Sel", 3 ) )
  1286. {
  1287. dwflag |= DNS_RPC_AUTOCONFIG_SELFPOINTCLIENT;
  1288. }
  1289. else
  1290. {
  1291. goto Help;
  1292. }
  1293. ++iarg;
  1294. }
  1295. else
  1296. {
  1297. goto Help;
  1298. }
  1299. }
  1300. if ( !dwflag )
  1301. {
  1302. dwflag = DNS_RPC_AUTOCONFIG_SELFPOINTCLIENT |
  1303. DNS_RPC_AUTOCONFIG_ROOTHINTS |
  1304. DNS_RPC_AUTOCONFIG_FORWARDERS;
  1305. }
  1306. status = DnssrvOperation(
  1307. pwszServerName,
  1308. NULL,
  1309. DNSSRV_OP_AUTO_CONFIGURE,
  1310. DNSSRV_TYPEID_DWORD,
  1311. ( PVOID ) ( DWORD_PTR ) dwflag );
  1312. if ( status == ERROR_SUCCESS )
  1313. {
  1314. printf(
  1315. "%s completed successfully.\n",
  1316. pszServerName );
  1317. }
  1318. else
  1319. {
  1320. printf(
  1321. "%s failed: status = %d (0x%08lx).\n",
  1322. pszServerName,
  1323. status, status );
  1324. }
  1325. return status;
  1326. Help:
  1327. printf(
  1328. "Usage: DnsCmd <ServerName> /" DNSSRV_OP_AUTO_CONFIGURE " [Options]\n"
  1329. " Configures DNS server and client using the current DNS client settings\n"
  1330. " Options can be on or more of:\n"
  1331. " /Forwarders -- configure DNS server with forwarders\n"
  1332. " /RootHints -- configure DNS server with root hints\n"
  1333. " /SelfPoint -- configure DNS client to point to local DNS server\n"
  1334. " If no options are specified, default is all options\n" );
  1335. return ERROR_INVALID_PARAMETER;
  1336. } // ProcessAutoConfigure
  1337. DNS_STATUS
  1338. ProcessStatistics(
  1339. IN DWORD Argc,
  1340. IN LPSTR * Argv,
  1341. IN LPWSTR * UnicodeArgv
  1342. )
  1343. {
  1344. DNS_STATUS status = ERROR_SUCCESS;
  1345. DWORD statid = DNSSRV_STATID_ALL; // default to all
  1346. PDNS_RPC_BUFFER pstatsBuf = NULL;
  1347. LPSTR cmd;
  1348. //
  1349. // Statistics [/<StatId> | /Clear]
  1350. //
  1351. if ( Argc > 1 )
  1352. {
  1353. goto Help;
  1354. }
  1355. //
  1356. // if command -- execute command
  1357. // /Clear is only supported command
  1358. //
  1359. //
  1360. cmd = getCommandName( Argv[0] );
  1361. if ( cmd )
  1362. {
  1363. if ( !_stricmp(cmd, "Clear" ) )
  1364. {
  1365. status = DnssrvOperation(
  1366. pwszServerName,
  1367. NULL,
  1368. "ClearStatistics",
  1369. DNSSRV_TYPEID_NULL,
  1370. NULL );
  1371. if ( status == ERROR_SUCCESS )
  1372. {
  1373. printf("DNS Server %S statistics cleared.\n", pwszServerName );
  1374. }
  1375. return status;
  1376. }
  1377. goto Help;
  1378. }
  1379. //
  1380. // view statistics
  1381. // - if specific statid given, read it
  1382. if ( Argc > 0 )
  1383. {
  1384. statid = strtoul(
  1385. Argv[0],
  1386. NULL,
  1387. 16 );
  1388. if ( statid == 0 )
  1389. {
  1390. statid = (-1);
  1391. }
  1392. }
  1393. if ( g_UseWmi )
  1394. {
  1395. status = DnscmdWmi_GetStatistics(
  1396. statid );
  1397. }
  1398. else
  1399. {
  1400. status = DnssrvGetStatistics(
  1401. pwszServerName,
  1402. statid,
  1403. & pstatsBuf );
  1404. if ( status == ERROR_SUCCESS )
  1405. {
  1406. printf( "DNS Server %S statistics:\n", pwszServerName );
  1407. DnsPrint_RpcStatsBuffer(
  1408. dnscmd_PrintRoutine,
  1409. dnscmd_PrintContext,
  1410. NULL,
  1411. pstatsBuf );
  1412. }
  1413. }
  1414. return status;
  1415. Help:
  1416. printf(
  1417. "Usage: DnsCmd <ServerName> /Statistics [<StatId> | /Clear]\n"
  1418. " <StatId> -- ID of particular stat desired. (ALL is the default)\n"
  1419. " %08lx -- Time \n"
  1420. " %08lx -- Query \n"
  1421. " %08lx -- Query2 \n"
  1422. " %08lx -- Recurse \n"
  1423. " %08lx -- Master \n"
  1424. " %08lx -- Secondary \n"
  1425. " %08lx -- Wins \n"
  1426. " %08lx -- Wire Update\n"
  1427. " %08lx -- Security \n"
  1428. " %08lx -- Ds \n"
  1429. " %08lx -- Internal Update\n"
  1430. " %08lx -- Memory \n"
  1431. " %08lx -- Dbase \n"
  1432. " %08lx -- Records \n"
  1433. " %08lx -- PacketMem \n"
  1434. " /Clear -- clear statistics data\n",
  1435. DNSSRV_STATID_TIME,
  1436. DNSSRV_STATID_QUERY,
  1437. DNSSRV_STATID_QUERY2,
  1438. DNSSRV_STATID_RECURSE,
  1439. DNSSRV_STATID_MASTER,
  1440. DNSSRV_STATID_SECONDARY,
  1441. DNSSRV_STATID_WINS,
  1442. DNSSRV_STATID_WIRE_UPDATE,
  1443. DNSSRV_STATID_SKWANSEC,
  1444. DNSSRV_STATID_DS,
  1445. DNSSRV_STATID_NONWIRE_UPDATE,
  1446. DNSSRV_STATID_MEMORY,
  1447. DNSSRV_STATID_DBASE,
  1448. DNSSRV_STATID_RECORD,
  1449. DNSSRV_STATID_PACKET );
  1450. return ERROR_INVALID_PARAMETER;
  1451. }
  1452. //
  1453. // Update server data file(s)
  1454. // for one zone, when <zonename> specified
  1455. // all files: no <zonename> specified
  1456. //
  1457. DNS_STATUS
  1458. ProcessWriteBackFiles(
  1459. IN DWORD Argc,
  1460. IN LPSTR * Argv,
  1461. IN LPWSTR * UnicodeArgv
  1462. )
  1463. {
  1464. DNS_STATUS status = ERROR_SUCCESS;
  1465. LPSTR zonename = NULL;
  1466. LPSTR cmd;
  1467. //
  1468. // WriteBackFiles [ZoneName]
  1469. //
  1470. if ( Argc > 1 )
  1471. {
  1472. goto Help;
  1473. }
  1474. if ( Argc == 0 )
  1475. {
  1476. cmd = "WriteDirtyZones";
  1477. }
  1478. else
  1479. {
  1480. zonename = Argv[0];
  1481. cmd = "WriteBackFile";
  1482. }
  1483. status = DnssrvOperation(
  1484. pwszServerName, //server
  1485. zonename, //zone
  1486. cmd, //cmd
  1487. DNSSRV_TYPEID_NULL,
  1488. (PVOID) NULL );
  1489. if ( status == ERROR_SUCCESS )
  1490. {
  1491. printf(
  1492. "Sever data file(s) updated. \n"
  1493. );
  1494. }
  1495. return status;
  1496. Help:
  1497. printf(
  1498. "Usage: DnsCmd <ServerName> /WriteBackFiles [<ZoneName>]\n"
  1499. " <ZoneName> -- FQDN of a zone whose datafile to be written back\n"
  1500. " Default: write back datafile for all dirty zones\n"
  1501. );
  1502. return ERROR_INVALID_PARAMETER;
  1503. }
  1504. DNS_STATUS
  1505. ProcessRecordAdd(
  1506. IN DWORD Argc,
  1507. IN LPSTR * Argv,
  1508. IN LPWSTR * UnicodeArgv
  1509. )
  1510. {
  1511. DNS_STATUS status = ERROR_SUCCESS;
  1512. PDNS_RECORD prr;
  1513. PDNS_RPC_RECORD prrRpc;
  1514. LPSTR pzoneName;
  1515. LPSTR pnodeName;
  1516. BOOL ballocatedNode;
  1517. LPSTR pzoneArg;
  1518. WORD wType;
  1519. DWORD ttl = 0;
  1520. DWORD ttlFlag = 0;
  1521. CHAR buf[33];
  1522. DWORD baging = 0;
  1523. DWORD bopenAcl = 0;
  1524. //
  1525. // RecordAdd <Zone> <Node> [/AgeOn | /AgeOff] [/AdminAcl] [<TTL>] <RRType> <RRData>
  1526. //
  1527. if ( Argc < 4 || Argc == NEED_HELP_ARGC )
  1528. {
  1529. goto Help;
  1530. }
  1531. //
  1532. // read zone and domain name
  1533. //
  1534. readZoneAndDomainName(
  1535. Argv,
  1536. & pzoneName,
  1537. & pnodeName,
  1538. & ballocatedNode,
  1539. & pzoneArg,
  1540. NULL );
  1541. Argv++;
  1542. Argc--;
  1543. Argv++;
  1544. Argc--;
  1545. //
  1546. // Aging ON\OFF
  1547. //
  1548. if ( Argc )
  1549. {
  1550. if ( _stricmp( *Argv, "/Aging" ) == 0 ||
  1551. _stricmp( *Argv, "/AgeOn" ) == 0 )
  1552. {
  1553. baging = 1;
  1554. Argv++;
  1555. Argc--;
  1556. }
  1557. #if 0
  1558. else if ( _stricmp( *Argv, "/AgeOff" ) == 0 )
  1559. {
  1560. baging = 0;
  1561. Argv++;
  1562. Argc--;
  1563. }
  1564. #endif
  1565. }
  1566. if ( Argc && _stricmp( *Argv, "/OpenAcl" ) == 0 )
  1567. {
  1568. bopenAcl = TRUE;
  1569. Argv++;
  1570. Argc--;
  1571. }
  1572. //
  1573. // TTL -- optional
  1574. // - use default if none given
  1575. //
  1576. ttl = strtoul(
  1577. *Argv,
  1578. NULL,
  1579. 10 );
  1580. if ( ttl == 0 && strcmp(*Argv, "0") != 0 )
  1581. {
  1582. ttlFlag = DNS_RPC_RECORD_FLAG_DEFAULT_TTL;
  1583. }
  1584. else // read TTL
  1585. {
  1586. Argv++;
  1587. Argc--;
  1588. if ( Argc < 1 )
  1589. {
  1590. goto Help;
  1591. }
  1592. }
  1593. //
  1594. // record type
  1595. //
  1596. wType = Dns_RecordTypeForName( *Argv, 0 );
  1597. if ( !wType )
  1598. {
  1599. printf( "Invalid RRType: <%s>!\n", *Argv );
  1600. goto Help;
  1601. }
  1602. Argv++;
  1603. Argc--;
  1604. //
  1605. // build DNS_RECORD
  1606. // - if no record data, then type delete
  1607. // - otherwise build record
  1608. //
  1609. if ( !Argc )
  1610. {
  1611. prrRpc = ALLOCATE_HEAP( SIZEOF_DNS_RPC_RECORD_HEADER );
  1612. if ( !prrRpc )
  1613. {
  1614. printf( "Not enough memory!\n" );
  1615. return ERROR_SUCCESS;
  1616. }
  1617. prrRpc->wDataLength = 0;
  1618. prrRpc->wType = wType;
  1619. }
  1620. else
  1621. {
  1622. prr = Dns_RecordBuild_A(
  1623. NULL, // ptr to RRSet
  1624. pnodeName, // nameOwner
  1625. wType, // RR type in WORD
  1626. FALSE, // ! S.Delete
  1627. 0, // S.section
  1628. Argc, // count of strings
  1629. Argv // strings to fill into RR
  1630. );
  1631. if ( ! prr )
  1632. {
  1633. printf( "\nInvalid Data!\n" );
  1634. goto Help;
  1635. }
  1636. // convert DNS_RECORD to RPC buffer
  1637. prrRpc = DnsConvertRecordToRpcBuffer( prr );
  1638. if ( ! prrRpc )
  1639. {
  1640. #if DBG
  1641. printf("DnsConvertRecordToRpcBuffer() failed\n");
  1642. #endif
  1643. status = GetLastError();
  1644. goto Help;
  1645. }
  1646. // prr and prrRpc freed by process termination
  1647. }
  1648. //
  1649. // set TTL and flags for the RR
  1650. //
  1651. prrRpc->dwTtlSeconds = ttl;
  1652. prrRpc->dwFlags = ttlFlag;
  1653. if ( baging )
  1654. {
  1655. prrRpc->dwFlags |= DNS_RPC_RECORD_FLAG_AGING_ON;
  1656. }
  1657. if ( bopenAcl )
  1658. {
  1659. prrRpc->dwFlags |= DNS_RPC_FLAG_OPEN_ACL;
  1660. }
  1661. if ( g_UseWmi )
  1662. {
  1663. status = DnscmdWmi_ProcessRecordAdd(
  1664. pzoneName,
  1665. pnodeName,
  1666. prrRpc,
  1667. Argc,
  1668. Argv );
  1669. }
  1670. else
  1671. {
  1672. status = DnssrvUpdateRecord(
  1673. pwszServerName, // server
  1674. pzoneName, // zone
  1675. pnodeName, // node
  1676. prrRpc, // RR to add
  1677. NULL );
  1678. }
  1679. if ( status == ERROR_SUCCESS )
  1680. {
  1681. PWSTR pwsznode = getUnicodeForUtf8( pnodeName );
  1682. PWSTR pwszzone = getUnicodeForUtf8( pzoneArg );
  1683. printf(
  1684. "Add %s Record for %S at %S\n",
  1685. *( Argv - 1 ), // RR type
  1686. pwsznode, // owner name
  1687. pwszzone ); // zone name
  1688. FREE_HEAP( pwsznode );
  1689. FREE_HEAP( pwszzone );
  1690. }
  1691. // free node name if allocated
  1692. if ( ballocatedNode )
  1693. {
  1694. free( pnodeName );
  1695. }
  1696. return status;
  1697. Help:
  1698. printf(
  1699. "Usage: DnsCmd <ServerName> /RecordAdd <Zone> <NodeName> [/Aging] [/OpenAcl]\n"
  1700. " [<Ttl>] <RRType> <RRData>\n\n"
  1701. " <RRType> <RRData>\n"
  1702. " A <IPAddress>\n"
  1703. " NS,CNAME,MB,MD <HostName|DomainName>\n"
  1704. " PTR,MF,MG,MR <HostName|DomainName>\n"
  1705. " MX,RT,AFSDB <Preference> <ServerName>\n"
  1706. " SRV <Priority> <Weight> <Port> <HostName>\n"
  1707. " SOA <PrimaryServer> <AdminEmail> <Serial#>\n"
  1708. " <Refresh> <Retry> <Expire> <MinTTL>\n"
  1709. " AAAA <Ipv6Address>\n"
  1710. " TXT <String> [<String>]\n"
  1711. " X25,HINFO,ISDN <String> [<String>]\n"
  1712. " MINFO,RP <MailboxName> <ErrMailboxName>\n"
  1713. " WKS <Protocol> <IPAddress> <Service> [<Service>]..]\n"
  1714. " KEY <Flags> <KeyProtocol> <CryptoAlgorithm> <Base64Data>\n"
  1715. " SIG <TypeCovered> <CryptoAlgorithm> <LabelCount>\n"
  1716. " <OriginalTTL> <SigExpiration> <SigInception>\n"
  1717. " <KeyTag> <Signer's Name> <Base64Data>\n"
  1718. " NXT <NextName> <Type> [<Type>...]\n"
  1719. " WINS <MapFlag> <LookupTimeout>\n"
  1720. " <CacheTimeout> <IPAddress> [<IPAddress>]\n"
  1721. " WINSR <MapFlag> <LookupTimeout>\n"
  1722. " <CacheTimeout> <RstDomainName>\n"
  1723. " <Zone> -- <ZoneName> | /RootHints\n"
  1724. " <ZoneName> -- FQDN of a zone\n"
  1725. " <NodeName> -- name of node for which a record will be added\n"
  1726. " - FQDN of a node (name with a '.' at the end) OR\n"
  1727. " - node name relative to the ZoneName OR\n"
  1728. " - \"@\" for zone root node OR\n"
  1729. " - service name for SRV only (e.g. _ftp._tcp)\n"
  1730. " <Ttl> -- TTL for the RR (Default: TTL defined in SOA)\n"
  1731. " <HostName> -- FQDN of a host\n"
  1732. " <IPAddress> -- e.g. 255.255.255.255\n"
  1733. " <ipv6Address> -- e.g. 1:2:3:4:5:6:7:8\n"
  1734. " <Protocol> -- UDP | TCP \n"
  1735. " <Service> -- e.g. domain, smtp\n"
  1736. " <TypeCovered> -- type of the RRset signed by this SIG\n"
  1737. " <CryptoAlgorithm> -- 1=RSA/MD5, 2=Diffie-Hellman, 3=DSA\n"
  1738. " <SigExpiration> -- yyyymmddhhmmss - GMT\n"
  1739. " <SigInception> -- yyyymmddhhmmss - GMT\n"
  1740. " <KeyTag> -- used to discriminate between multiple SIGs\n"
  1741. " <Signer's Name> -- domain name of signer\n"
  1742. " <KeyProtocol> -- 1=TLS, 2=email, 3=DNSSEC, 4=IPSEC\n"
  1743. " <Base64Data> -- KEY or SIG binary data in base64 notation\n"
  1744. " <NextName> -- domain name of next RRSet in zone\n" );
  1745. return ERROR_INVALID_PARAMETER;
  1746. }
  1747. DNS_STATUS
  1748. ProcessRecordDelete(
  1749. IN DWORD Argc,
  1750. IN LPSTR * Argv,
  1751. IN LPWSTR * UnicodeArgv
  1752. )
  1753. /*++
  1754. Routine Description:
  1755. Delete record(s) from node in zone.
  1756. --*/
  1757. {
  1758. DNS_STATUS status = ERROR_SUCCESS;
  1759. PDNS_RECORD prr;
  1760. PDNS_RPC_RECORD prrRpc = NULL;
  1761. LPSTR pzoneName = NULL;
  1762. LPSTR pnodeName = NULL;
  1763. BOOL ballocatedNode = FALSE;
  1764. LPSTR pzoneArg;
  1765. LPSTR psztypeArg = NULL;
  1766. WORD wType;
  1767. DWORD ttl = 0;
  1768. DWORD ttlFlag = 0;
  1769. CHAR buf[33];
  1770. BOOL fconfirm = TRUE;
  1771. //
  1772. // RecordDelete <Zone> <Node> <RRType> [<RRData>] [/f]
  1773. //
  1774. if ( Argc < 3 || Argc == NEED_HELP_ARGC )
  1775. {
  1776. goto Help;
  1777. }
  1778. //
  1779. // Check for "force" (no-confirm) flag
  1780. //
  1781. if ( !_stricmp( Argv[Argc-1], "/f" ) )
  1782. {
  1783. fconfirm = FALSE;
  1784. Argc--;
  1785. }
  1786. if ( Argc < 3 )
  1787. {
  1788. goto Help;
  1789. }
  1790. //
  1791. // read zone and domain name
  1792. //
  1793. readZoneAndDomainName(
  1794. Argv,
  1795. & pzoneName,
  1796. & pnodeName,
  1797. & ballocatedNode,
  1798. & pzoneArg,
  1799. NULL );
  1800. Argv++;
  1801. Argc--;
  1802. Argv++;
  1803. Argc--;
  1804. //
  1805. // TTL -- optional
  1806. // - use default if none given
  1807. //
  1808. ttl = strtoul(
  1809. *Argv,
  1810. NULL,
  1811. 10 );
  1812. if ( ttl == 0 && strcmp(*Argv, "0") != 0 )
  1813. {
  1814. ttlFlag = DNS_RPC_RECORD_FLAG_DEFAULT_TTL;
  1815. }
  1816. else // read TTL
  1817. {
  1818. Argv++;
  1819. Argc--;
  1820. if ( Argc < 1 )
  1821. {
  1822. goto Help;
  1823. }
  1824. }
  1825. //
  1826. // record type
  1827. //
  1828. psztypeArg = *Argv;
  1829. wType = Dns_RecordTypeForName(
  1830. psztypeArg,
  1831. 0 // null terminated
  1832. );
  1833. if ( !wType )
  1834. {
  1835. printf( "Invalid RRType: <%s>!\n", *Argv );
  1836. goto Help;
  1837. }
  1838. Argv++;
  1839. Argc--;
  1840. //
  1841. // build DNS_RECORD
  1842. // - if no record data, then type delete
  1843. // - otherwise build record
  1844. //
  1845. if ( Argc )
  1846. {
  1847. prr = Dns_RecordBuild_A(
  1848. NULL, // ptr to RRSet
  1849. pnodeName, // nameOwner
  1850. wType, // RR type in WORD
  1851. FALSE, // ! S.Delete
  1852. 0, // S.section
  1853. Argc, // count of strings
  1854. Argv // strings to fill into RR
  1855. );
  1856. if ( ! prr )
  1857. {
  1858. printf( "\nInvalid Data!\n" );
  1859. goto Help;
  1860. }
  1861. // convert DNS_RECORD to RPC buffer
  1862. prrRpc = DnsConvertRecordToRpcBuffer( prr );
  1863. if ( ! prrRpc )
  1864. {
  1865. #if DBG
  1866. printf("DnsConvertRecordToRpcBuffer()faild\n");
  1867. #endif
  1868. status = GetLastError();
  1869. goto Help;
  1870. }
  1871. // prr and prrRpc freed by process termination
  1872. // set TTL for the RR
  1873. prrRpc->dwTtlSeconds = ttl;
  1874. prrRpc->dwFlags = ttlFlag;
  1875. }
  1876. //
  1877. // ask user for confirmation
  1878. //
  1879. if ( fconfirm )
  1880. {
  1881. if ( !getUserConfirmation( "delete record" ) )
  1882. {
  1883. return ERROR_SUCCESS;
  1884. }
  1885. }
  1886. //
  1887. // delete
  1888. // - if record do full update
  1889. // - if type do type delete
  1890. //
  1891. if ( prrRpc )
  1892. {
  1893. status = DnssrvUpdateRecord(
  1894. pwszServerName, // server
  1895. pzoneName, // zone
  1896. pnodeName, // node
  1897. NULL, // no add
  1898. prrRpc // RR to delete
  1899. );
  1900. }
  1901. else
  1902. {
  1903. status = DnssrvDeleteRecordSet(
  1904. pwszServerName, // server
  1905. pzoneName, // zone
  1906. pnodeName, // node
  1907. wType
  1908. );
  1909. }
  1910. if ( status == ERROR_SUCCESS )
  1911. {
  1912. printf(
  1913. "Deleted %s record(s) at %s\n",
  1914. psztypeArg,
  1915. pzoneArg );
  1916. }
  1917. // free node name if allocated
  1918. if ( ballocatedNode && pnodeName )
  1919. {
  1920. free( pnodeName );
  1921. }
  1922. return status;
  1923. Help:
  1924. printf(
  1925. "Usage: DnsCmd <ServerName> /RecordDelete <Zone> <NodeName>\n"
  1926. " <RRType> <RRData> [/f]\n\n"
  1927. " <Zone> -- FQDN of a zone of /RootHints or /Cache\n"
  1928. " <NodeName> -- name of node from which a record will be deleted\n"
  1929. " - \"@\" for zone root OR\n"
  1930. " - FQDN of a node (DNS name with a '.' at the end) OR\n"
  1931. " - single label for name relative to zone root ) OR\n"
  1932. " - service name for SRV only (e.g. _ftp._tcp)\n"
  1933. " <RRType>: <RRData>:\n"
  1934. " A <IP Address>\n"
  1935. " SRV <Priority> <Weight> <Port> <HostName>\n"
  1936. " AAAA <IPv6 Address>\n"
  1937. " MX <Preference> <ServerName>\n"
  1938. " NS,CNAME,PTR <HostName>\n"
  1939. " For help on how to specify the <RRData> for other record\n"
  1940. " types see \"DnsCmd /RecordAdd /?\"\n"
  1941. " If <RRData> is not specified deletes all records with of specified type\n"
  1942. " /f -- Execute without asking for confirmation\n\n" );
  1943. // free node name if allocated
  1944. if ( ballocatedNode )
  1945. {
  1946. free( pnodeName );
  1947. }
  1948. return ERROR_INVALID_PARAMETER;
  1949. }
  1950. DNS_STATUS
  1951. ProcessNodeDelete(
  1952. IN DWORD Argc,
  1953. IN LPSTR * Argv,
  1954. IN LPWSTR * UnicodeArgv
  1955. )
  1956. /*++
  1957. Routine Description:
  1958. Delete record(s) from node in zone.
  1959. --*/
  1960. {
  1961. DNS_STATUS status = ERROR_SUCCESS;
  1962. LPSTR pzoneName;
  1963. LPSTR pnodeName;
  1964. BOOL ballocatedNode = FALSE;
  1965. LPSTR pzoneArg;
  1966. DWORD iarg;
  1967. BOOL bsubtree = FALSE;
  1968. BOOL bnoConfirm = FALSE;
  1969. //
  1970. // /DeleteNode <Zone> <NodeName> [/Tree] [/f]
  1971. //
  1972. if ( Argc < 2 || Argc > 4 )
  1973. {
  1974. goto Help;
  1975. }
  1976. // read options
  1977. iarg = 3;
  1978. while ( iarg <= Argc )
  1979. {
  1980. if ( !_stricmp(Argv[iarg-1], "/Tree") )
  1981. {
  1982. bsubtree = 1;
  1983. }
  1984. else if ( !_stricmp(Argv[iarg-1], "/f") )
  1985. {
  1986. bnoConfirm = 1;
  1987. }
  1988. else
  1989. {
  1990. goto Help;
  1991. }
  1992. iarg ++;
  1993. }
  1994. //
  1995. // if confirmation option, get user confirmation
  1996. // - if denied, bail
  1997. //
  1998. if ( !bnoConfirm )
  1999. {
  2000. PCHAR pmessage = "delete node";
  2001. if ( bsubtree )
  2002. {
  2003. pmessage = "delete node's subtree";
  2004. }
  2005. if ( !getUserConfirmation( pmessage ) )
  2006. {
  2007. return ERROR_SUCCESS;
  2008. }
  2009. }
  2010. //
  2011. // read zone and domain name
  2012. //
  2013. readZoneAndDomainName(
  2014. Argv,
  2015. & pzoneName,
  2016. & pnodeName,
  2017. & ballocatedNode,
  2018. & pzoneArg,
  2019. NULL );
  2020. //
  2021. // delete
  2022. //
  2023. status = DnssrvDeleteNode(
  2024. pwszServerName,
  2025. pzoneName,
  2026. pnodeName,
  2027. bsubtree );
  2028. if ( status == ERROR_SUCCESS )
  2029. {
  2030. LPWSTR pwsznodeName = utf8ToUnicode( pnodeName, 0 );
  2031. printf(
  2032. "DNS Server %S deleted node at %S:\n"
  2033. " Status = %d (0x%08lx)\n",
  2034. pwszServerName,
  2035. pwsznodeName,
  2036. status, status );
  2037. FREE_HEAP( pwsznodeName );
  2038. }
  2039. // free node name if allocated
  2040. if ( ballocatedNode )
  2041. {
  2042. free( pnodeName );
  2043. }
  2044. return status;
  2045. Help:
  2046. printf(
  2047. "Usage: DnsCmd <ServerName> /NodeDelete "
  2048. "<Zone> <NodeName> [/Tree] [/f]\n"
  2049. " <Zone> -- <ZoneName> | /RootHints | /Cache\n"
  2050. " <ZoneName> -- FQDN of a zone\n"
  2051. " <NodeName> -- FQDN of a node (with a '.' at the end) OR\n"
  2052. " node name relative to the ZoneName\n"
  2053. " /Tree -- must be provided, when deleting a subdomain;\n"
  2054. " (Not to delete sub tree is the default)\n"
  2055. " /f -- execute without asking for confirmation\n" );
  2056. return ERROR_INVALID_PARAMETER;
  2057. }
  2058. DNS_STATUS
  2059. ProcessAgeAllRecords(
  2060. IN DWORD Argc,
  2061. IN LPSTR * Argv,
  2062. IN LPWSTR * UnicodeArgv
  2063. )
  2064. /*++
  2065. Routine Description:
  2066. Delete record(s) from node in zone.
  2067. --*/
  2068. {
  2069. DNS_STATUS status = ERROR_SUCCESS;
  2070. LPSTR pszzoneName;
  2071. LPWSTR pwszzoneName;
  2072. LPSTR pnodeName;
  2073. BOOL ballocatedNode = FALSE;
  2074. LPSTR pzoneArg;
  2075. DWORD iarg;
  2076. BOOL bsubtree = FALSE;
  2077. BOOL bnoConfirm = FALSE;
  2078. //
  2079. // /AgeAllRecords <Zone> [<NodeName>] [/f] [Tree]
  2080. //
  2081. if ( Argc < 1 || Argc > 4 )
  2082. {
  2083. goto Help;
  2084. }
  2085. //
  2086. // read options
  2087. // - iarg left at FIRST option parsed
  2088. // so we can determine if "node" option exists
  2089. //
  2090. iarg = Argc;
  2091. while ( iarg > 1 )
  2092. {
  2093. if ( !_stricmp(Argv[iarg-1], "/Tree") )
  2094. {
  2095. bsubtree = 1;
  2096. }
  2097. else if ( !_stricmp(Argv[iarg-1], "/f") )
  2098. {
  2099. bnoConfirm = 1;
  2100. }
  2101. else
  2102. {
  2103. break;
  2104. }
  2105. iarg--;
  2106. }
  2107. //
  2108. // read zone and optionally, domain name
  2109. //
  2110. if ( iarg > 1 )
  2111. {
  2112. readZoneAndDomainName(
  2113. Argv,
  2114. &pszzoneName,
  2115. &pnodeName,
  2116. &ballocatedNode,
  2117. &pzoneArg,
  2118. NULL );
  2119. }
  2120. else
  2121. {
  2122. pzoneArg = pszzoneName = Argv[ 0 ];
  2123. pnodeName = NULL;
  2124. }
  2125. pwszzoneName = UnicodeArgv[ 0 ];
  2126. //
  2127. // if confirmation option, get user confirmation
  2128. // - if denied, bail
  2129. //
  2130. if ( !bnoConfirm )
  2131. {
  2132. PCHAR pmessage = "force aging on node";
  2133. if ( bsubtree )
  2134. {
  2135. if ( pnodeName )
  2136. {
  2137. pmessage = "force aging on node's subtree";
  2138. }
  2139. else
  2140. {
  2141. pmessage = "force aging on entire zone";
  2142. }
  2143. }
  2144. if ( !getUserConfirmation( pmessage ) )
  2145. {
  2146. return ERROR_SUCCESS;
  2147. }
  2148. }
  2149. //
  2150. // force aging
  2151. //
  2152. status = DnssrvForceAging(
  2153. pwszServerName,
  2154. pszzoneName,
  2155. pnodeName,
  2156. bsubtree );
  2157. if ( status == ERROR_SUCCESS )
  2158. {
  2159. printf(
  2160. "DNS Server %S forced aging on records %s %s of zone %S:\n"
  2161. " Status = %d (0x%08lx)\n",
  2162. pwszServerName,
  2163. bsubtree ? "in subtree" : "at",
  2164. pnodeName ? pnodeName : "root",
  2165. pwszzoneName,
  2166. status, status );
  2167. }
  2168. // free node name if allocated
  2169. if ( ballocatedNode )
  2170. {
  2171. free( pnodeName );
  2172. }
  2173. return status;
  2174. Help:
  2175. printf(
  2176. "Usage: DnsCmd <ServerName> /AgeAllRecords <ZoneName> [<NodeName>] [/Tree] [/f]\n"
  2177. " <Zone> -- <ZoneName>\n"
  2178. " <ZoneName> -- FQDN of a zone\n"
  2179. " <NodeName> -- name or node or subtree in which to enable aging\n"
  2180. " - \"@\" for zone root OR\n"
  2181. " - FQDN of a node (name with a '.' at the end) OR\n"
  2182. " - single label for name relative to zone root\n"
  2183. " /Tree -- force aging on entire subtree of node\n"
  2184. " or entire zone if node not given\n"
  2185. " /f -- execute without asking for confirmation\n" );
  2186. return ERROR_INVALID_PARAMETER;
  2187. }
  2188. //
  2189. // Server configuration API
  2190. //
  2191. DNS_STATUS
  2192. ProcessResetProperty(
  2193. IN DWORD Argc,
  2194. IN LPSTR * Argv,
  2195. IN LPWSTR * UnicodeArgv
  2196. )
  2197. {
  2198. DNS_STATUS status = ERROR_SUCCESS;
  2199. LPSTR pszZone = NULL;
  2200. LPSTR pszProperty = NULL;
  2201. BOOL fAllZones = FALSE;
  2202. //
  2203. // Config [Zone] <PropertyName> <Value>
  2204. // Note: if there is no valid, pass 0 for DWORDs or NULL for
  2205. // other types. This allows you to clear values, such as the
  2206. // LogFilterIPList.
  2207. //
  2208. if ( Argc < 1 || Argc == NEED_HELP_ARGC )
  2209. {
  2210. goto Help;
  2211. }
  2212. //
  2213. // The first arg is the zone name unless it starts with a
  2214. // slash, which means the zone name was omitted.
  2215. //
  2216. if ( *Argv[ 0 ] != '/' )
  2217. {
  2218. pszZone = Argv[ 0 ];
  2219. --Argc;
  2220. ++Argv;
  2221. }
  2222. //
  2223. // Property name - starts with a slash.
  2224. //
  2225. pszProperty = getCommandName( Argv[ 0 ] );
  2226. if ( !pszProperty )
  2227. {
  2228. goto Help;
  2229. }
  2230. --Argc;
  2231. ++Argv;
  2232. //
  2233. // Trap apply to all zone operation.
  2234. //
  2235. if ( pszZone &&
  2236. _stricmp( pszZone, "_ApplyAllZones_" ) == 0 )
  2237. {
  2238. pszZone = NULL;
  2239. fAllZones = TRUE;
  2240. }
  2241. //
  2242. // Do a strcmp to decide if this is a string or DWORD property.
  2243. // As more string properties are added we should probably use a
  2244. // table instead of a bunch of stricmps.
  2245. //
  2246. if ( _stricmp( pszProperty, DNS_REGKEY_LOG_FILE_PATH ) == 0 ||
  2247. _stricmp( pszProperty, DNS_REGKEY_ZONE_BREAK_ON_NAME_UPDATE ) == 0 ||
  2248. _stricmp( pszProperty, DNS_REGKEY_SERVER_PLUGIN ) == 0 )
  2249. {
  2250. //
  2251. // This property is a string value.
  2252. //
  2253. LPWSTR pwszPropertyValue = NULL;
  2254. if ( Argc && Argv[ 0 ] )
  2255. {
  2256. pwszPropertyValue = Dns_StringCopyAllocate(
  2257. Argv[ 0 ],
  2258. 0,
  2259. DnsCharSetUtf8,
  2260. DnsCharSetUnicode );
  2261. }
  2262. if ( g_UseWmi )
  2263. {
  2264. status = DnscmdWmi_ResetProperty(
  2265. pszZone,
  2266. pszProperty,
  2267. VT_BSTR,
  2268. ( PVOID ) pwszPropertyValue );
  2269. }
  2270. else
  2271. {
  2272. status = DnssrvResetStringProperty(
  2273. pwszServerName,
  2274. pszZone,
  2275. pszProperty,
  2276. pwszPropertyValue,
  2277. fAllZones ? DNSSRV_OP_PARAM_APPLY_ALL_ZONES : 0 );
  2278. }
  2279. FREE_HEAP( pwszPropertyValue );
  2280. }
  2281. else if ( _stricmp( pszProperty, DNS_REGKEY_LISTEN_ADDRESSES ) == 0 ||
  2282. _stricmp( pszProperty, DNS_REGKEY_LOG_IP_FILTER_LIST ) == 0 ||
  2283. _stricmp( pszProperty, DNS_REGKEY_FORWARDERS ) == 0 ||
  2284. _stricmp( pszProperty, DNS_REGKEY_ZONE_ALLOW_AUTONS ) == 0 ||
  2285. _stricmp( pszProperty, DNS_REGKEY_ZONE_MASTERS ) == 0 ||
  2286. _stricmp( pszProperty, DNS_REGKEY_ZONE_LOCAL_MASTERS ) == 0 ||
  2287. _stricmp( pszProperty, DNS_REGKEY_ZONE_SCAVENGE_SERVERS ) == 0 ||
  2288. _stricmp( pszProperty, DNS_REGKEY_BREAK_ON_UPDATE_FROM ) == 0 ||
  2289. _stricmp( pszProperty, DNS_REGKEY_BREAK_ON_RECV_FROM ) == 0 )
  2290. {
  2291. //
  2292. // This property is an IP list value.
  2293. //
  2294. DWORD ipCount;
  2295. IP_ADDRESS ipAddressArray[ MAX_IP_PROPERTY_COUNT ];
  2296. PIP_ARRAY pipArray = NULL;
  2297. if ( Argc )
  2298. {
  2299. BOOL fInaddrNoneAllowed =
  2300. _stricmp( pszProperty, DNS_REGKEY_BREAK_ON_UPDATE_FROM ) == 0 ||
  2301. _stricmp( pszProperty, DNS_REGKEY_BREAK_ON_RECV_FROM ) == 0;
  2302. ipCount = readIpAddressArray(
  2303. ipAddressArray,
  2304. MAX_IP_PROPERTY_COUNT,
  2305. Argc,
  2306. Argv,
  2307. fInaddrNoneAllowed );
  2308. if ( ipCount < 1 )
  2309. {
  2310. goto Help;
  2311. }
  2312. Argc -= ipCount;
  2313. Argv += ipCount;
  2314. pipArray = Dns_BuildIpArray( ipCount, ipAddressArray );
  2315. }
  2316. if ( g_UseWmi )
  2317. {
  2318. status = DnscmdWmi_ResetProperty(
  2319. pszZone,
  2320. pszProperty,
  2321. PRIVATE_VT_IPARRAY,
  2322. ( PVOID ) pipArray );
  2323. }
  2324. else
  2325. {
  2326. status = DnssrvResetIPListProperty(
  2327. pwszServerName,
  2328. pszZone,
  2329. pszProperty,
  2330. pipArray,
  2331. fAllZones ? DNSSRV_OP_PARAM_APPLY_ALL_ZONES : 0 );
  2332. }
  2333. FREE_HEAP( pipArray );
  2334. }
  2335. else
  2336. {
  2337. //
  2338. // This property is a DWORD value.
  2339. //
  2340. DWORD value = Argc ?
  2341. convertDwordParameterUnknownBase( Argv[ 0 ] ) :
  2342. 0;
  2343. if ( fAllZones )
  2344. {
  2345. value |= DNSSRV_OP_PARAM_APPLY_ALL_ZONES;
  2346. }
  2347. if ( g_UseWmi )
  2348. {
  2349. status = DnscmdWmi_ResetProperty(
  2350. pszZone,
  2351. pszProperty,
  2352. VT_I4,
  2353. ( PVOID ) ( DWORD_PTR ) value );
  2354. }
  2355. else
  2356. {
  2357. status = DnssrvResetDwordProperty(
  2358. pwszServerName,
  2359. pszZone,
  2360. pszProperty,
  2361. value );
  2362. }
  2363. }
  2364. if ( status == ERROR_SUCCESS )
  2365. {
  2366. printf(
  2367. "Registry property %s successfully reset.\n",
  2368. pszProperty );
  2369. }
  2370. else
  2371. {
  2372. printf(
  2373. "DNS Server failed to reset registry property.\n"
  2374. " Status = %d (0x%08lx)\n",
  2375. status, status );
  2376. }
  2377. return status;
  2378. Help:
  2379. // Note: removing ..AllZones from help. It doesn't work that well
  2380. // and it's not a very good model anyways. But leave it in place in
  2381. // case anyone actually wants to use it.
  2382. printf(
  2383. "Usage: DnsCmd <ServerName> /Config "
  2384. "<ZoneName> <Property> <Value>\n"
  2385. " Server <Property>:\n"
  2386. " /RpcProtocol\n"
  2387. " /LogLevel\n"
  2388. " /" DNS_REGKEY_LOG_FILE_PATH " <Log file name>\n"
  2389. " /" DNS_REGKEY_LOG_IP_FILTER_LIST " <IP list>\n"
  2390. " /" DNS_REGKEY_LOG_FILE_MAX_SIZE "\n"
  2391. " /EventlogLevel\n"
  2392. " /NoRecursion\n"
  2393. " /" DNS_REGKEY_BOOT_METHOD "\n"
  2394. " /ForwardDelegations\n"
  2395. " /ForwardingTimeout\n"
  2396. " /IsSlave\n"
  2397. " /SecureResponses\n"
  2398. " /RecursionRetry\n"
  2399. " /RecursionTimeout\n"
  2400. " /MaxCacheTtl\n"
  2401. " /" DNS_REGKEY_MAX_CACHE_SIZE "\n"
  2402. " /MaxNegativeCacheTtl\n"
  2403. " /RoundRobin\n"
  2404. " /LocalNetPriority\n"
  2405. " /AddressAnswerLimit\n"
  2406. " /BindSecondaries\n"
  2407. " /WriteAuthorityNs\n"
  2408. " /NameCheckFlag\n"
  2409. " /StrictFileParsing\n"
  2410. " /UpdateOptions\n"
  2411. " /DisableAutoReverseZones\n"
  2412. " /SendPort\n"
  2413. " /NoTcp\n"
  2414. " /XfrConnectTimeout\n"
  2415. " /DsPollingInterval\n"
  2416. " /DsTombstoneInterval\n"
  2417. " /ScavengingInterval\n"
  2418. " /DefaultAgingState\n"
  2419. " /DefaultNoRefreshInterval\n"
  2420. " /DefaultRefreshInterval\n"
  2421. " /" DNS_REGKEY_ENABLE_DNSSEC "\n"
  2422. " /" DNS_REGKEY_ENABLE_EDNS "\n"
  2423. " /" DNS_REGKEY_EDNS_CACHE_TIMEOUT "\n"
  2424. " /" DNS_REGKEY_DISABLE_AUTONS "\n"
  2425. " Zone <Property>:\n"
  2426. " /SecureSecondaries\n"
  2427. " /AllowUpdate <Value>\n"
  2428. " <Value> -- 0: no updates; 1: unsecure updates; 2: secure updates only\n"
  2429. " /Aging\n"
  2430. " /RefreshInterval <Value>\n"
  2431. " /NoRefreshInterval <Value>\n"
  2432. " /" DNS_REGKEY_ZONE_FWD_TIMEOUT " <Value>\n"
  2433. " /" DNS_REGKEY_ZONE_FWD_SLAVE " <Value>\n"
  2434. " /" DNS_REGKEY_ZONE_ALLOW_AUTONS " <IP List>\n"
  2435. " <Value>: New property value. Use 0x prefix to indicate hex value.\n"
  2436. " Note some server and zone DWORD properties must be reset as\n"
  2437. " part of a more complex operation.\n" );
  2438. return ERROR_INVALID_PARAMETER;
  2439. } // ProcessResetProperty
  2440. DNS_STATUS
  2441. ProcessResetForwarders(
  2442. IN DWORD Argc,
  2443. IN LPSTR * Argv,
  2444. IN LPWSTR * UnicodeArgv
  2445. )
  2446. {
  2447. #define MAX_FORWARD_COUNT (50)
  2448. DNS_STATUS status = ERROR_SUCCESS;
  2449. DWORD iArg = 0;
  2450. DWORD fSlave = FALSE;
  2451. DWORD dwTimeout = DNS_DEFAULT_FORWARD_TIMEOUT;
  2452. DWORD cForwarders = 0;
  2453. IP_ADDRESS aipForwarders[ MAX_FORWARD_COUNT ];
  2454. LPSTR cmd;
  2455. //
  2456. // ResetForwarders [<ForwarderIP>] ...] [/Slave|/NoSlave] [/TimeOut <time>]
  2457. //
  2458. if ( Argc == NEED_HELP_ARGC )
  2459. {
  2460. goto Help;
  2461. }
  2462. // read forwarder ipAddresses:
  2463. while ( ( iArg < Argc ) &&
  2464. ( !getCommandName(Argv[iArg]) ) )
  2465. {
  2466. if ( iArg < MAX_FORWARD_COUNT )
  2467. {
  2468. aipForwarders[iArg] = inet_addr( Argv[iArg] );
  2469. }
  2470. iArg++;
  2471. }
  2472. cForwarders = iArg;
  2473. //
  2474. // Optional commands
  2475. //
  2476. while ( iArg < Argc )
  2477. {
  2478. cmd = getCommandName( Argv[iArg] );
  2479. if ( cmd )
  2480. {
  2481. if ( !_stricmp(cmd, "Slave") )
  2482. {
  2483. fSlave = TRUE;
  2484. }
  2485. else if ( !_stricmp(cmd, "NoSlave") )
  2486. {
  2487. fSlave = FALSE;
  2488. }
  2489. else if ( !_stricmp(cmd, "TimeOut") )
  2490. {
  2491. if ( ++iArg >= Argc )
  2492. {
  2493. goto Help;
  2494. }
  2495. dwTimeout = strtoul(
  2496. Argv[iArg],
  2497. NULL,
  2498. 10 );
  2499. }
  2500. else
  2501. {
  2502. goto Help;
  2503. }
  2504. iArg ++;
  2505. }
  2506. else
  2507. {
  2508. goto Help;
  2509. }
  2510. }
  2511. if ( g_UseWmi )
  2512. {
  2513. status = DnscmdWmi_ProcessResetForwarders(
  2514. cForwarders,
  2515. aipForwarders,
  2516. dwTimeout,
  2517. fSlave );
  2518. }
  2519. else
  2520. {
  2521. status = DnssrvResetForwarders(
  2522. pwszServerName,
  2523. cForwarders,
  2524. aipForwarders,
  2525. dwTimeout,
  2526. fSlave );
  2527. }
  2528. if ( status == ERROR_SUCCESS )
  2529. {
  2530. printf( "Forwarders reset successfully.\n" );
  2531. }
  2532. else
  2533. {
  2534. printf(
  2535. "DNS Server failed to reset forwarders.\n"
  2536. " Status = %d (0x%08lx)\n",
  2537. status, status );
  2538. }
  2539. return status;
  2540. Help:
  2541. printf( "Usage: DnsCmd <ServerName> /ResetForwarders "
  2542. "[<IPAddress>] ...] [ /[No]Slave ] [/TimeOut <Time>]\n"
  2543. " <IPAddress> -- where to forward unsolvable DNS queries\n"
  2544. " /Slave -- operate as slave server\n"
  2545. " /NoSlave -- not as slave server (default)\n"
  2546. " No forwarders is the default.\n"
  2547. " Default timeout is %d sec\n",
  2548. DNS_DEFAULT_FORWARD_TIMEOUT );
  2549. return ERROR_INVALID_PARAMETER;
  2550. }
  2551. DNS_STATUS
  2552. ProcessResetListenAddresses(
  2553. IN DWORD Argc,
  2554. IN LPSTR * Argv,
  2555. IN LPWSTR * UnicodeArgv
  2556. )
  2557. {
  2558. DNS_STATUS status = ERROR_SUCCESS;
  2559. DWORD iArg;
  2560. DWORD cListenAddresses = 0;
  2561. IP_ADDRESS aipListenAddresses[ 10 ];
  2562. //
  2563. // ResetListenAddresses <IPAddress> ...
  2564. //
  2565. //Help:
  2566. if ( Argc == NEED_HELP_ARGC )
  2567. {
  2568. goto Help;
  2569. }
  2570. if ( Argc > 0 &&
  2571. getCommandName(Argv[0]) )
  2572. {
  2573. goto Help;
  2574. }
  2575. // read listen addresses
  2576. cListenAddresses = Argc;
  2577. for ( iArg=0; iArg<cListenAddresses; iArg++)
  2578. {
  2579. aipListenAddresses[iArg] = inet_addr( Argv[iArg] );
  2580. }
  2581. status = DnssrvResetServerListenAddresses(
  2582. pwszServerName,
  2583. cListenAddresses,
  2584. aipListenAddresses );
  2585. if ( status == ERROR_SUCCESS )
  2586. {
  2587. printf( "ListenAddresses reset successful.\n" );
  2588. }
  2589. else
  2590. {
  2591. printf(
  2592. "DNS Server failed to reset listen addressess.\n"
  2593. " Status = %d (0x%08lx)\n",
  2594. status, status );
  2595. }
  2596. return status;
  2597. Help:
  2598. printf( "Usage: DnsCmd <ServerName> /ResetListenAddresses [<ListenAddress>] ...]\n"
  2599. " <ListenAddress> -- an IP address belonging to the DNS server\n"
  2600. " Default: listen to all server IP Address(es) for DNS requests\n\n" );
  2601. return ERROR_INVALID_PARAMETER;
  2602. }
  2603. //
  2604. // Zone Queries
  2605. //
  2606. DNS_STATUS
  2607. ProcessEnumZones(
  2608. IN DWORD Argc,
  2609. IN LPSTR * Argv,
  2610. IN LPWSTR * UnicodeArgv
  2611. )
  2612. {
  2613. DNS_STATUS status = ERROR_SUCCESS;
  2614. DWORD filter = 0;
  2615. DWORD zoneCount;
  2616. DWORD iArg = 0;
  2617. PDNS_RPC_ZONE_LIST pZoneList = NULL;
  2618. LPSTR cmd;
  2619. LPSTR pszpartition = NULL;
  2620. //
  2621. // EnumZones [<Filter1>] [<Filter2>]
  2622. //
  2623. // get filters:
  2624. while ( iArg < Argc )
  2625. {
  2626. cmd = getCommandName( Argv[iArg] );
  2627. if ( !cmd )
  2628. {
  2629. goto Help;
  2630. }
  2631. if ( !_stricmp( cmd, "Primary" ) )
  2632. {
  2633. filter |= ZONE_REQUEST_PRIMARY;
  2634. }
  2635. else if ( !_stricmp( cmd, "Secondary" ) )
  2636. {
  2637. filter |= ZONE_REQUEST_SECONDARY;
  2638. }
  2639. else if ( !_stricmp( cmd, "Forwarder" ) )
  2640. {
  2641. filter |= ZONE_REQUEST_FORWARDER;
  2642. }
  2643. else if ( !_stricmp( cmd, "Stub" ) )
  2644. {
  2645. filter |= ZONE_REQUEST_STUB;
  2646. }
  2647. else if ( !_stricmp( cmd, "Cache" ) )
  2648. {
  2649. filter |= ZONE_REQUEST_CACHE;
  2650. }
  2651. else if ( !_stricmp( cmd, "Auto-Created" ) || !_stricmp( cmd, "Auto" ) )
  2652. {
  2653. filter |= ZONE_REQUEST_AUTO;
  2654. }
  2655. else if ( !_stricmp( cmd, "Forward" ) )
  2656. {
  2657. filter |= ZONE_REQUEST_FORWARD;
  2658. }
  2659. else if ( !_stricmp( cmd, "Reverse" ) )
  2660. {
  2661. filter |= ZONE_REQUEST_REVERSE;
  2662. }
  2663. else if ( !_stricmp( cmd, "Ds" ) )
  2664. {
  2665. filter |= ZONE_REQUEST_DS;
  2666. }
  2667. else if ( !_stricmp( cmd, "NonDs" ) || !_stricmp( cmd, "File" ) )
  2668. {
  2669. filter |= ZONE_REQUEST_NON_DS;
  2670. }
  2671. else if ( !_stricmp( cmd, "DomainDirectoryPartition" ) ||
  2672. !_stricmp( cmd, "DomainDp" ) )
  2673. {
  2674. filter |= ZONE_REQUEST_DOMAIN_DP;
  2675. }
  2676. else if ( !_stricmp( cmd, "ForestDirectoryPartition" ) ||
  2677. !_stricmp( cmd, "ForestDp" ) )
  2678. {
  2679. filter |= ZONE_REQUEST_FOREST_DP;
  2680. }
  2681. else if ( !_stricmp( cmd, "CustomDirectoryPartition" ) ||
  2682. !_stricmp( cmd, "CustomDp" ) )
  2683. {
  2684. filter |= ZONE_REQUEST_CUSTOM_DP;
  2685. }
  2686. else if ( !_stricmp( cmd, "LegacyDirectoryPartition" ) ||
  2687. !_stricmp( cmd, "LegacyDp" ) )
  2688. {
  2689. filter |= ZONE_REQUEST_LEGACY_DP;
  2690. }
  2691. else if ( !_stricmp( cmd, "Dp" ) ||
  2692. !_stricmp( cmd, "DirectoryPartition" ) )
  2693. {
  2694. if ( iArg + 1 >= Argc ||
  2695. !Argv[ iArg + 1 ] ||
  2696. getCommandName( Argv[ iArg + 1 ] ) != NULL )
  2697. {
  2698. goto Help;
  2699. }
  2700. pszpartition = Argv[ ++iArg ];
  2701. }
  2702. else
  2703. {
  2704. goto Help;
  2705. }
  2706. ++iArg;
  2707. }
  2708. // special case NO filter
  2709. if ( filter == 0 )
  2710. {
  2711. filter = ZONE_REQUEST_ALL_ZONES_AND_CACHE;
  2712. }
  2713. if ( g_UseWmi )
  2714. {
  2715. status = DnscmdWmi_ProcessEnumZones(
  2716. filter );
  2717. }
  2718. else
  2719. {
  2720. status = DnssrvEnumZonesEx(
  2721. pwszServerName,
  2722. filter, // DWORD filter
  2723. pszpartition, // directory partition FQDN
  2724. NULL, // query string (not implemented)
  2725. NULL, // last zone
  2726. &pZoneList );
  2727. if ( status != ERROR_SUCCESS )
  2728. {
  2729. printf(
  2730. "Zone enumeration failed\n"
  2731. " status = %d (0x%08lx)\n",
  2732. status, status );
  2733. goto Cleanup;
  2734. }
  2735. else
  2736. {
  2737. DnsPrint_RpcZoneList(
  2738. dnscmd_PrintRoutine,
  2739. dnscmd_PrintContext,
  2740. "Enumerated zone list:\n",
  2741. pZoneList );
  2742. }
  2743. }
  2744. Cleanup:
  2745. //
  2746. // deallocate zone list
  2747. //
  2748. DnssrvFreeZoneList( pZoneList );
  2749. return status;
  2750. Help:
  2751. printf( "Usage: DnsCmd <ServerName> /EnumZones [<Filter1> <Filter2> ...]\n"
  2752. " Filters:\n"
  2753. " /Primary - primary zones\n"
  2754. " /Secondary - secondary zones\n"
  2755. " /Forwarder - conditional forwarding zones\n"
  2756. " /Stub - stub zones\n"
  2757. " /Cache - the cache zone\n"
  2758. " /Auto-Created - auto-created zones\n"
  2759. " /Forward - forward lookup zones\n"
  2760. " /Reverse - reverse lookup zones\n"
  2761. " /Ds - DS-integrated zones\n"
  2762. " /File - file-backed zones\n"
  2763. " /DomainDirectoryPartition - zones in domain directory partition\n"
  2764. " /ForestDirectoryPartition - zones in forest directory partition\n"
  2765. " /CustomDirectoryPartition - zones in any custom directory partition\n"
  2766. " /LegacyDirectoryPartition - zones in the legacy partition\n"
  2767. " /DirectoryPartition - zones in partition specified by next arg\n"
  2768. " Output:\n"
  2769. " Storage:\n"
  2770. " File - zone is stored in a file\n"
  2771. " AD-Forest - zone is stored in the forest Active Directory DNS partition\n"
  2772. " AD-Domain - zone is stored in the domain Active Directory DNS partition\n"
  2773. " AD-Legacy - zone is stored in the W2K-compatible DNS partition\n"
  2774. " Properties:\n"
  2775. " Update - zone accepts DNS dynamic updates\n"
  2776. " Secure - zone accepts secure DNS dynamic updates\n"
  2777. " Rev - zone is a reverse lookup zone\n"
  2778. " Auto - zone was auto-created by the DNS server\n"
  2779. " Aging - aging is enabled for this zone\n"
  2780. " Down - zone is currently shutdown\n"
  2781. " Paused - zone is currently paused\n" );
  2782. return ERROR_INVALID_PARAMETER;
  2783. }
  2784. //
  2785. // Create a new zone
  2786. //
  2787. DNS_STATUS
  2788. ProcessZoneAdd(
  2789. IN DWORD Argc,
  2790. IN LPSTR * Argv,
  2791. IN LPWSTR * UnicodeArgv
  2792. )
  2793. {
  2794. DNS_STATUS status = ERROR_SUCCESS;
  2795. LPSTR pzoneName;
  2796. DWORD zoneType = DNS_ZONE_TYPE_PRIMARY;
  2797. DWORD countMasters = 0;
  2798. IP_ADDRESS masterArray[ MAX_IP_PROPERTY_COUNT ];
  2799. DWORD floadExisting = FALSE;
  2800. LPSTR pszAllocatedDataFile = NULL;
  2801. LPSTR pszDataFile = NULL;
  2802. LPSTR pszEmailAdminName = NULL; // pass NULL by default
  2803. LPSTR cmd;
  2804. BOOL fDsIntegrated;
  2805. BOOL fdpSpecified = FALSE;
  2806. DWORD dwTimeout = 0; // for forwarder zones only
  2807. BOOL fSlave = FALSE; // for forwarder zones only
  2808. BOOL fInDirPart = FALSE;
  2809. DWORD dpFlag = 0; // directory partition flag for builtin
  2810. LPSTR pszDpFqdn = NULL; // directory partition FQDN for custom
  2811. #if DBG
  2812. DWORD dwdcPromo = 0;
  2813. #endif
  2814. PWSTR pwszzoneName = NULL;
  2815. //
  2816. // CreateZone
  2817. //
  2818. if ( Argc < 2 ||
  2819. Argc == NEED_HELP_ARGC ||
  2820. getCommandName(Argv[0]) )
  2821. {
  2822. goto Help;
  2823. }
  2824. // set zone name
  2825. pzoneName = Argv[0];
  2826. Argv++;
  2827. Argc--;
  2828. //
  2829. // zone type
  2830. // - Primary
  2831. // - Secondary, then read master IP array
  2832. // - DsPrimary
  2833. //
  2834. cmd = getCommandName( Argv[0] );
  2835. if ( !cmd )
  2836. {
  2837. goto Help;
  2838. }
  2839. Argv++;
  2840. Argc--;
  2841. zoneType = parseZoneTypeString( cmd, &fDsIntegrated );
  2842. if ( zoneType == -1 )
  2843. {
  2844. goto Help;
  2845. }
  2846. // JJW: should I set floadExisting for all DsIntegrated zones?
  2847. if ( zoneType == DNS_ZONE_TYPE_PRIMARY && fDsIntegrated )
  2848. {
  2849. floadExisting = TRUE;
  2850. }
  2851. else if ( zoneType == DNS_ZONE_TYPE_SECONDARY ||
  2852. zoneType == DNS_ZONE_TYPE_STUB ||
  2853. zoneType == DNS_ZONE_TYPE_FORWARDER )
  2854. {
  2855. // get master IP list
  2856. countMasters = readIpAddressArray(
  2857. masterArray,
  2858. MAX_IP_PROPERTY_COUNT,
  2859. Argc,
  2860. Argv,
  2861. FALSE );
  2862. if ( countMasters < 1 )
  2863. {
  2864. goto Help;
  2865. }
  2866. Argc -= countMasters;
  2867. Argv += countMasters;
  2868. }
  2869. //
  2870. // options
  2871. // - file name (default to load existing file)
  2872. // - admin email name
  2873. // - DS overwrite options
  2874. //
  2875. while ( Argc )
  2876. {
  2877. cmd = getCommandName( *Argv );
  2878. if ( !cmd )
  2879. {
  2880. goto Help;
  2881. }
  2882. Argc--;
  2883. Argv++;
  2884. if ( !_stricmp( cmd, "file" ) )
  2885. {
  2886. if ( Argc <= 0 || zoneType == DNS_ZONE_TYPE_FORWARDER )
  2887. {
  2888. goto Help;
  2889. }
  2890. pszDataFile = *Argv;
  2891. Argc--;
  2892. Argv++;
  2893. }
  2894. else if ( !_stricmp(cmd, "a") )
  2895. {
  2896. if ( Argc <= 0 )
  2897. {
  2898. goto Help;
  2899. }
  2900. pszEmailAdminName = *Argv;
  2901. Argc--;
  2902. Argv++;
  2903. }
  2904. else if ( !_stricmp(cmd, "load") )
  2905. {
  2906. floadExisting = TRUE;
  2907. }
  2908. else if ( !_stricmp(cmd, "timeout") &&
  2909. zoneType == DNS_ZONE_TYPE_FORWARDER )
  2910. {
  2911. dwTimeout = strtoul( *( Argv++ ), NULL, 10 );
  2912. Argc--;
  2913. }
  2914. else if ( !_stricmp(cmd, "slave") &&
  2915. zoneType == DNS_ZONE_TYPE_FORWARDER )
  2916. {
  2917. fSlave = TRUE;
  2918. }
  2919. else if ( ( !_stricmp(cmd, "dp" ) ||
  2920. !_stricmp(cmd, "DirectoryPartition" ) ) &&
  2921. fDsIntegrated )
  2922. {
  2923. //
  2924. // Directory partition for zone. Check to see if a builtin DP
  2925. // is requested, if so set flag, Otherwise DP argument must
  2926. // be the FQDN of a custom DP.
  2927. //
  2928. if ( !parseDpSpecifier( *Argv, &dpFlag, &pszDpFqdn ) )
  2929. {
  2930. goto Help;
  2931. }
  2932. fdpSpecified = TRUE;
  2933. fInDirPart = TRUE;
  2934. Argc--;
  2935. Argv++;
  2936. }
  2937. #if DBG
  2938. else if ( !_stricmp( cmd, "dcpromo" ) )
  2939. {
  2940. //
  2941. // DCPROMO argument is debug only (for test)
  2942. // Argument following should be /forest or /domain.
  2943. //
  2944. if ( _strnicmp( *Argv, "/d", 2 ) == 0 )
  2945. {
  2946. dwdcPromo = DNS_ZONE_CREATE_FOR_DCPROMO;
  2947. }
  2948. else if ( _strnicmp( *Argv, "/f", 2 ) == 0 )
  2949. {
  2950. dwdcPromo = DNS_ZONE_CREATE_FOR_DCPROMO_FOREST;
  2951. }
  2952. else
  2953. {
  2954. goto Help;
  2955. }
  2956. Argc--;
  2957. Argv++;
  2958. }
  2959. #endif
  2960. else
  2961. {
  2962. goto Help;
  2963. }
  2964. }
  2965. //
  2966. // If no file name for file-backed, set up default.
  2967. //
  2968. if ( zoneType == DNS_ZONE_TYPE_PRIMARY &&
  2969. !pszDataFile &&
  2970. !fDsIntegrated )
  2971. {
  2972. pszAllocatedDataFile = MIDL_user_allocate( strlen( pzoneName ) + 20 );
  2973. strcpy( pszAllocatedDataFile, pzoneName );
  2974. strcat( pszAllocatedDataFile, ".dns" );
  2975. pszDataFile = pszAllocatedDataFile;
  2976. }
  2977. //
  2978. // For DS integrated zones, if no DP is specified then we need to
  2979. // select the best DP: legacy or built-in domain DP.
  2980. //
  2981. // By default stub and forwarder zones are always created in the
  2982. // domain NDNC if no target NDNC was specified.
  2983. //
  2984. else if ( fDsIntegrated && !fdpSpecified )
  2985. {
  2986. DWORD dwdomainVersion = 0;
  2987. status = getServerVersion(
  2988. pwszServerName,
  2989. TRUE,
  2990. NULL,
  2991. NULL,
  2992. NULL,
  2993. &dwdomainVersion );
  2994. if ( status == ERROR_SUCCESS &&
  2995. dwdomainVersion >= DS_BEHAVIOR_WIN2003 ||
  2996. zoneType == DNS_ZONE_TYPE_FORWARDER ||
  2997. zoneType == DNS_ZONE_TYPE_STUB )
  2998. {
  2999. dpFlag = DNS_DP_DOMAIN_DEFAULT;
  3000. pszDpFqdn = NULL;
  3001. fInDirPart = TRUE;
  3002. printf( "Creating zone in built-in domain directory partition...\n" );
  3003. }
  3004. status = ERROR_SUCCESS;
  3005. }
  3006. //
  3007. // Let there be zone!
  3008. //
  3009. #if DBG
  3010. if ( dwdcPromo )
  3011. {
  3012. printf( "Creating dcpromo zone with dcpromo flag 0x%08X\n", dwdcPromo );
  3013. status = DnssrvCreateZoneForDcPromoEx(
  3014. pwszServerName,
  3015. pzoneName,
  3016. pszDataFile,
  3017. dwdcPromo );
  3018. }
  3019. else
  3020. #endif
  3021. if ( fInDirPart )
  3022. {
  3023. status = DnssrvCreateZoneInDirectoryPartition(
  3024. pwszServerName,
  3025. pzoneName,
  3026. zoneType,
  3027. pszEmailAdminName,
  3028. countMasters,
  3029. masterArray,
  3030. floadExisting,
  3031. dwTimeout,
  3032. fSlave,
  3033. dpFlag,
  3034. pszDpFqdn );
  3035. }
  3036. else
  3037. {
  3038. status = DnssrvCreateZone(
  3039. pwszServerName,
  3040. pzoneName,
  3041. zoneType,
  3042. pszEmailAdminName,
  3043. countMasters,
  3044. masterArray,
  3045. floadExisting,
  3046. fDsIntegrated,
  3047. pszDataFile,
  3048. dwTimeout,
  3049. fSlave );
  3050. }
  3051. if ( pszAllocatedDataFile )
  3052. {
  3053. MIDL_user_free( pszAllocatedDataFile );
  3054. pszAllocatedDataFile = NULL;
  3055. }
  3056. if ( status == ERROR_SUCCESS )
  3057. {
  3058. pwszzoneName = getUnicodeForUtf8( pzoneName );
  3059. printf(
  3060. "DNS Server %S created zone %S:\n",
  3061. pwszServerName,
  3062. pwszzoneName );
  3063. FREE_HEAP( pwszzoneName );
  3064. }
  3065. return status;
  3066. Help:
  3067. printf(
  3068. "Usage: DnsCmd <ServerName> /ZoneAdd <ZoneName> <ZoneType> [<Options>]\n"
  3069. " <ZoneName> -- FQDN of zone\n"
  3070. " <ZoneType>:\n"
  3071. " /DsPrimary [/dp <FQDN>]\n"
  3072. " -- DS integrated primary zone\n"
  3073. " /Primary /file <filename>\n"
  3074. " -- standard file backed primary; MUST include filename.\n"
  3075. " /Secondary <MasterIPaddress> [<MasterIPaddress>] ..] [/file <filename>]\n"
  3076. " -- standard secondary, MUST include at least one master IP;\n"
  3077. " filename is optional.\n"
  3078. " /Stub <MasterIPaddress> [<MasterIPaddress>] ..] [/file <filename>]\n"
  3079. " -- stub secondary, only replicates NS info from primary server\n"
  3080. " /DsStub -- as /Stub but DS integrated - use same options\n"
  3081. " /Forwarder <MasterIPaddress> [<MasterIPaddress>] ..] [/Timeout <Time>]\n"
  3082. " [/Slave]\n"
  3083. " -- forwarder zone, queries for names in zone forwarded to masters\n"
  3084. " /DsForwarder -- as /Forwarder but DS integrated - use same options\n"
  3085. " <Options>:\n"
  3086. " [/file <filename>] -- filename, invalid for DS integrated zones\n"
  3087. " [/load] -- load existing file; if not specified,\n"
  3088. " non-DS primary creates default zone records\n"
  3089. " [/a <AdminName>] -- zone admin email name; primary zones only\n"
  3090. " [/DP <FQDN>] -- fully qualified domain name of directory partition\n"
  3091. " where zone should be stored; or use one of:\n"
  3092. " /DP /domain - domain directory partition\n"
  3093. " /DP /forest - forest directory partition\n"
  3094. " /DP /legacy - legacy directory partition\n" );
  3095. return ERROR_INVALID_PARAMETER;
  3096. }
  3097. DNS_STATUS
  3098. ProcessZoneDelete(
  3099. IN DWORD Argc,
  3100. IN LPSTR * Argv,
  3101. IN LPWSTR * UnicodeArgv
  3102. )
  3103. {
  3104. DNS_STATUS status = ERROR_SUCCESS;
  3105. LPSTR cmd;
  3106. BOOL fconfirm = TRUE;
  3107. DWORD iArg;
  3108. LPSTR pszOperation;
  3109. //
  3110. // ZoneDelete <ZoneName> [/DsDel] [/f]
  3111. //
  3112. if ( Argc < 1 ||
  3113. Argc == NEED_HELP_ARGC ||
  3114. ( getCommandName( Argv[0] ) ) )
  3115. {
  3116. goto Help;
  3117. }
  3118. pszOperation = DNSSRV_OP_ZONE_DELETE;
  3119. // read options
  3120. iArg = 1;
  3121. while ( iArg < Argc )
  3122. {
  3123. if ( !(cmd = getCommandName(Argv[iArg]) ) )
  3124. {
  3125. goto Help;
  3126. }
  3127. if ( !_stricmp( cmd, "f" ) )
  3128. {
  3129. // execute without confirmation:
  3130. fconfirm = FALSE;
  3131. }
  3132. else if ( !_stricmp( cmd, "DsDel" ) )
  3133. {
  3134. // delete zone from DS:
  3135. pszOperation = DNSSRV_OP_ZONE_DELETE_FROM_DS;
  3136. }
  3137. else
  3138. {
  3139. goto Help;
  3140. }
  3141. iArg ++;
  3142. }
  3143. //
  3144. // get user confirmation
  3145. //
  3146. if ( fconfirm )
  3147. {
  3148. if ( !getUserConfirmation( pszOperation ) )
  3149. {
  3150. return ERROR_SUCCESS;
  3151. }
  3152. }
  3153. if ( g_UseWmi )
  3154. {
  3155. status = DnscmdWmi_ProcessDnssrvOperation(
  3156. Argv[ 0 ], // zone name
  3157. pszOperation, // delete or delete from DS
  3158. DNSSRV_TYPEID_NULL, // no data
  3159. ( PVOID ) NULL );
  3160. }
  3161. else
  3162. {
  3163. status = DnssrvOperation(
  3164. pwszServerName,
  3165. Argv[ 0 ], // zone name
  3166. pszOperation, // delete or delete from DS
  3167. DNSSRV_TYPEID_NULL, // no data
  3168. ( PVOID ) NULL );
  3169. }
  3170. if ( status == ERROR_SUCCESS )
  3171. {
  3172. printf(
  3173. "DNS Server %S deleted zone %S:\n"
  3174. " Status = %d (0x%08lx)\n",
  3175. pwszServerName,
  3176. UnicodeArgv[0],
  3177. status, status );
  3178. }
  3179. return status;
  3180. Help:
  3181. printf(
  3182. "Usage: DnsCmd <ServerName> /ZoneDelete <ZoneName> [/DsDel] [/f]\n"
  3183. " /DsDel -- Delete Zone from DS\n"
  3184. " /f -- Execute without asking for confirmation\n"
  3185. " Default: delete zone from DNS sever, but NOT from DS\n" );
  3186. return ERROR_INVALID_PARAMETER;
  3187. }
  3188. DNS_STATUS
  3189. ProcessZonePause(
  3190. IN DWORD Argc,
  3191. IN LPSTR * Argv,
  3192. IN LPWSTR * UnicodeArgv
  3193. )
  3194. {
  3195. DNS_STATUS status = ERROR_SUCCESS;
  3196. //
  3197. // ZonePause <ZoneName>
  3198. //
  3199. //Help:
  3200. if ( Argc != 1 ||
  3201. getCommandName( Argv[0] ) )
  3202. {
  3203. goto Help;
  3204. }
  3205. status = DnssrvPauseZone(
  3206. pwszServerName,
  3207. Argv[0] // zone name
  3208. );
  3209. if ( status == ERROR_SUCCESS )
  3210. {
  3211. printf(
  3212. "DNS Server %S paused zone %S:\n"
  3213. " Status = %d (0x%08lx)\n",
  3214. pwszServerName,
  3215. UnicodeArgv[0],
  3216. status, status );
  3217. }
  3218. return status;
  3219. Help:
  3220. printf( "Usage: DnsCmd <ServerName> /ZonePause <ZoneName>\n" );
  3221. return ERROR_INVALID_PARAMETER;
  3222. }
  3223. DNS_STATUS
  3224. ProcessZoneResume(
  3225. IN DWORD Argc,
  3226. IN LPSTR * Argv,
  3227. IN LPWSTR * UnicodeArgv
  3228. )
  3229. {
  3230. DNS_STATUS status = ERROR_SUCCESS;
  3231. //
  3232. // ResumeZone <ZoneName>
  3233. //
  3234. if ( Argc != 1 ||
  3235. getCommandName( Argv[0] ) )
  3236. {
  3237. goto Help;
  3238. }
  3239. status = DnssrvResumeZone(
  3240. pwszServerName,
  3241. Argv[0] // zone name
  3242. );
  3243. if ( status == ERROR_SUCCESS )
  3244. {
  3245. printf(
  3246. "DNS Server %S resumed use of zone %S:\n"
  3247. " Status = %d (0x%08lx)\n",
  3248. pwszServerName,
  3249. UnicodeArgv[0],
  3250. status, status );
  3251. }
  3252. return status;
  3253. Help:
  3254. printf( "Usage: DnsCmd <ServerName> /ZoneResume <ZoneName>\n" );
  3255. return ERROR_INVALID_PARAMETER;
  3256. }
  3257. DNS_STATUS
  3258. ProcessZoneReload(
  3259. IN DWORD Argc,
  3260. IN LPSTR * Argv,
  3261. IN LPWSTR * UnicodeArgv
  3262. )
  3263. {
  3264. DNS_STATUS status = ERROR_SUCCESS;
  3265. //
  3266. // ReloadZone <ZoneName>
  3267. //
  3268. if ( Argc != 1 ||
  3269. getCommandName( Argv[0] ) )
  3270. {
  3271. goto Help;
  3272. }
  3273. status = DnssrvOperation(
  3274. pwszServerName,
  3275. Argv[0], // zone name
  3276. DNSSRV_OP_ZONE_RELOAD, // operation
  3277. DNSSRV_TYPEID_NULL, // no data
  3278. (PVOID) NULL
  3279. );
  3280. if ( status == ERROR_SUCCESS )
  3281. {
  3282. printf(
  3283. "DNS Server %S reloaded zone %S:\n"
  3284. " Status = %d (0x%08lx)\n",
  3285. pwszServerName,
  3286. UnicodeArgv[0],
  3287. status, status );
  3288. }
  3289. return status;
  3290. Help:
  3291. printf( "Usage: DnsCmd <ServerName> /ZoneReload <ZoneName>\n" );
  3292. return ERROR_INVALID_PARAMETER;
  3293. }
  3294. DNS_STATUS
  3295. ProcessZoneWriteBack(
  3296. IN DWORD Argc,
  3297. IN LPSTR * Argv,
  3298. IN LPWSTR * UnicodeArgv
  3299. )
  3300. {
  3301. DNS_STATUS status = ERROR_SUCCESS;
  3302. //
  3303. // ZoneWriteBack <ZoneName>
  3304. //
  3305. if ( Argc != 1 ||
  3306. getCommandName( Argv[0] ) )
  3307. {
  3308. goto Help;
  3309. }
  3310. status = DnssrvOperation(
  3311. pwszServerName,
  3312. Argv[0], // zone name
  3313. DNSSRV_OP_ZONE_WRITE_BACK_FILE, // operation
  3314. DNSSRV_TYPEID_NULL, // no data
  3315. (PVOID) NULL
  3316. );
  3317. if ( status == ERROR_SUCCESS )
  3318. {
  3319. printf(
  3320. "DNS Server %S wrote back zone %S:\n"
  3321. " Status = %d (0x%08lx)\n",
  3322. pwszServerName,
  3323. UnicodeArgv[0],
  3324. status, status );
  3325. }
  3326. return status;
  3327. Help:
  3328. printf( "Usage: DnsCmd <ServerName> /ZoneWriteBack <ZoneName>\n" );
  3329. return ERROR_INVALID_PARAMETER;
  3330. }
  3331. DNS_STATUS
  3332. ProcessZoneRefresh(
  3333. IN DWORD Argc,
  3334. IN LPSTR * Argv,
  3335. IN LPWSTR * UnicodeArgv
  3336. )
  3337. {
  3338. DNS_STATUS status = ERROR_SUCCESS;
  3339. //
  3340. // ZoneRefresh <ZoneName>
  3341. //
  3342. if ( Argc != 1 || getCommandName( Argv[0] ) )
  3343. {
  3344. goto Help;
  3345. }
  3346. status = DnssrvOperation(
  3347. pwszServerName,
  3348. Argv[0], // zone name
  3349. DNSSRV_OP_ZONE_REFRESH, // operation
  3350. DNSSRV_TYPEID_NULL, // no data
  3351. (PVOID) NULL
  3352. );
  3353. if ( status == ERROR_SUCCESS )
  3354. {
  3355. printf(
  3356. "DNS Server %S forced refresh of zone %S:\n"
  3357. " Status = %d (0x%08lx)\n",
  3358. pwszServerName,
  3359. UnicodeArgv[0],
  3360. status, status );
  3361. }
  3362. return status;
  3363. Help:
  3364. printf( "Usage: DnsCmd <ServerName> /ZoneRefresh <ZoneName>\n" );
  3365. return ERROR_INVALID_PARAMETER;
  3366. }
  3367. DNS_STATUS
  3368. ProcessZoneUpdateFromDs(
  3369. IN DWORD Argc,
  3370. IN LPSTR * Argv,
  3371. IN LPWSTR * UnicodeArgv
  3372. )
  3373. {
  3374. DNS_STATUS status = ERROR_SUCCESS;
  3375. //
  3376. // ZoneUpdateFromDs <ZoneName>
  3377. //
  3378. if ( Argc != 1 || getCommandName( Argv[0] ) )
  3379. {
  3380. goto Help;
  3381. }
  3382. status = DnssrvOperation(
  3383. pwszServerName,
  3384. Argv[0],
  3385. DNSSRV_OP_ZONE_UPDATE_FROM_DS,
  3386. DNSSRV_TYPEID_NULL,
  3387. (PVOID) NULL );
  3388. if ( status == ERROR_SUCCESS )
  3389. {
  3390. printf(
  3391. "DNS Server %S update zone %S\n"
  3392. " Status = %d (0x%08lx)\n",
  3393. pwszServerName,
  3394. UnicodeArgv[0],
  3395. status, status );
  3396. }
  3397. return status;
  3398. Help:
  3399. printf( "Usage: DnsCmd <ServerName> /ZoneUpdateFromDs <ZoneName>\n" );
  3400. return ERROR_INVALID_PARAMETER;
  3401. }
  3402. //
  3403. // Zone property reset functions
  3404. //
  3405. DNS_STATUS
  3406. ProcessZoneResetType(
  3407. IN DWORD Argc,
  3408. IN LPSTR * Argv,
  3409. IN LPWSTR * UnicodeArgv
  3410. )
  3411. {
  3412. DNS_STATUS status = ERROR_SUCCESS;
  3413. LPSTR pszzoneName;
  3414. LPWSTR pwszzoneName;
  3415. DWORD zoneType = DNS_ZONE_TYPE_PRIMARY; // default
  3416. DWORD countMasters = 0;
  3417. IP_ADDRESS masterArray[ MAX_IP_PROPERTY_COUNT ];
  3418. DWORD fDsIntegrated;
  3419. DWORD loadOptions = TRUE; // load existing
  3420. LPSTR pszDataFile = NULL;
  3421. LPSTR pszDpFqdn = NULL;
  3422. DWORD dpFlag = 0;
  3423. DWORD iArg = 0;
  3424. LPSTR cmd;
  3425. //
  3426. // ZoneResetType <ZoneName> <Property> [<options>]
  3427. //
  3428. if ( Argc < 2 ||
  3429. Argc == NEED_HELP_ARGC ||
  3430. getCommandName(Argv[0]) )
  3431. {
  3432. goto Help;
  3433. }
  3434. // get zone name
  3435. pszzoneName = Argv[ 0 ];
  3436. pwszzoneName = UnicodeArgv[ 0 ];
  3437. Argv++;
  3438. Argc--;
  3439. // get zone type:
  3440. cmd = getCommandName( Argv[0] );
  3441. if ( !cmd )
  3442. {
  3443. goto Help;
  3444. }
  3445. zoneType = parseZoneTypeString( cmd, &fDsIntegrated );
  3446. if ( zoneType == -1 )
  3447. {
  3448. goto Help;
  3449. }
  3450. if ( zoneType == DNS_ZONE_TYPE_SECONDARY ||
  3451. zoneType == DNS_ZONE_TYPE_STUB ||
  3452. zoneType == DNS_ZONE_TYPE_FORWARDER )
  3453. {
  3454. // get master IP list
  3455. countMasters = readIpAddressArray(
  3456. masterArray,
  3457. MAX_IP_PROPERTY_COUNT,
  3458. Argc-1,
  3459. Argv+1,
  3460. FALSE );
  3461. if ( countMasters < 1 )
  3462. {
  3463. goto Help;
  3464. }
  3465. Argv += countMasters;
  3466. Argc -= countMasters;
  3467. }
  3468. Argv++;
  3469. Argc--;
  3470. //
  3471. // options
  3472. //
  3473. iArg = 0;
  3474. while ( iArg < Argc )
  3475. {
  3476. cmd = getCommandName( Argv[iArg] );
  3477. if ( !cmd )
  3478. {
  3479. goto Help;
  3480. }
  3481. if ( !_stricmp(cmd, "file") )
  3482. {
  3483. if ( ++iArg >= Argc )
  3484. {
  3485. goto Help;
  3486. }
  3487. pszDataFile = Argv[ iArg ];
  3488. }
  3489. else if ( !_stricmp( cmd, "OverWrite_Mem" ) )
  3490. {
  3491. loadOptions |= DNS_ZONE_LOAD_OVERWRITE_MEMORY;
  3492. }
  3493. else if ( !_stricmp( cmd, "OverWrite_Ds" ) )
  3494. {
  3495. loadOptions |= DNS_ZONE_LOAD_OVERWRITE_DS;
  3496. }
  3497. else if ( _stricmp( cmd, "Dp" ) == 0 ||
  3498. _stricmp( cmd, "DirectoryPartition" ) == 0 )
  3499. {
  3500. if ( ++iArg >= Argc )
  3501. {
  3502. goto Help;
  3503. }
  3504. if ( !parseDpSpecifier( Argv[ iArg ], &dpFlag, &pszDpFqdn ) )
  3505. {
  3506. goto Help;
  3507. }
  3508. }
  3509. else
  3510. {
  3511. goto Help;
  3512. }
  3513. iArg++;
  3514. }
  3515. //
  3516. // reset type
  3517. //
  3518. status = DnssrvResetZoneTypeEx(
  3519. pwszServerName,
  3520. pszzoneName,
  3521. zoneType,
  3522. countMasters,
  3523. masterArray,
  3524. loadOptions,
  3525. fDsIntegrated,
  3526. pszDataFile,
  3527. dpFlag,
  3528. pszDpFqdn );
  3529. if ( status == ERROR_SUCCESS )
  3530. {
  3531. printf(
  3532. "DNS Server %S reset type of zone %S:\n",
  3533. pwszServerName,
  3534. pwszzoneName );
  3535. }
  3536. return status;
  3537. Help:
  3538. printf(
  3539. "Usage: DnsCmd <ServerName> /ZoneResetType <ZoneName> <Property> [<Options>]\n"
  3540. " <ZoneName> -- FQDN of zone\n"
  3541. " <Property>:\n"
  3542. " /DsPrimary\n"
  3543. " /Primary /file <filename>\n"
  3544. " /Secondary <MasterIPaddress> [<MasterIPaddress>] [/file <filename>]\n"
  3545. " /Stub <MasterIPaddress> [<MasterIPaddress>] [/file <filename>]\n"
  3546. " /DsStub <MasterIPaddress> [<MasterIPaddress>]\n"
  3547. " /Forwarder <MasterIPaddress> [<MasterIPaddress>] [/file <filename>]\n"
  3548. " /DsForwarder <MasterIPaddress> [<MasterIPaddress>] [/file <filename>]\n"
  3549. " <Options>:\n"
  3550. " /OverWrite_Mem -- overwrite DNS by data in DS\n"
  3551. " /OverWrite_Ds -- overwrite DS by data in DNS\n"
  3552. " /DirectoryPartition <FQDN> -- store the new zone in the directory\n"
  3553. " partition specified by the next argument\n" );
  3554. return ERROR_INVALID_PARAMETER;
  3555. }
  3556. //
  3557. // Zone rename
  3558. //
  3559. DNS_STATUS
  3560. ProcessZoneRename(
  3561. IN DWORD Argc,
  3562. IN LPSTR * Argv,
  3563. IN LPWSTR * UnicodeArgv
  3564. )
  3565. {
  3566. DNS_STATUS status = ERROR_SUCCESS;
  3567. LPSTR pszCurrentZoneName = NULL;
  3568. LPWSTR pwszCurrentZoneName = NULL;
  3569. LPSTR pszNewZoneName = NULL;
  3570. LPWSTR pwszNewZoneName = NULL;
  3571. LPSTR pszNewFileName = NULL;
  3572. LPSTR cmd;
  3573. //
  3574. // ZoneRename <ZoneName> <Property> [<options>]
  3575. //
  3576. if ( Argc < 2 ||
  3577. Argc == NEED_HELP_ARGC ||
  3578. getCommandName( Argv[ 0 ] ) )
  3579. {
  3580. goto Help;
  3581. }
  3582. // get current and new zone names
  3583. pszCurrentZoneName = Argv[ 0 ];
  3584. pwszCurrentZoneName = UnicodeArgv[ 0 ];
  3585. Argv++;
  3586. UnicodeArgv++;
  3587. Argc--;
  3588. pwszNewZoneName = UnicodeArgv[ 0 ];
  3589. Argv++;
  3590. UnicodeArgv++;
  3591. Argc--;
  3592. // optionally get file name
  3593. if ( Argc > 0 )
  3594. {
  3595. cmd = getCommandName( *Argv );
  3596. Argc--;
  3597. Argv++;
  3598. if ( cmd && !_stricmp( cmd, "file" ) )
  3599. {
  3600. if ( Argc <= 0 )
  3601. {
  3602. goto Help;
  3603. }
  3604. pszNewFileName = *Argv;
  3605. Argc--;
  3606. Argv++;
  3607. }
  3608. }
  3609. status = DnssrvRenameZone(
  3610. pwszServerName,
  3611. pszCurrentZoneName,
  3612. pszNewZoneName,
  3613. pszNewFileName );
  3614. if ( status == ERROR_SUCCESS )
  3615. {
  3616. printf(
  3617. "DNS Server %S renamed zone\n %S to\n %S\n",
  3618. pwszServerName,
  3619. pwszCurrentZoneName,
  3620. pwszNewZoneName );
  3621. }
  3622. return status;
  3623. Help:
  3624. printf(
  3625. "Usage: DnsCmd <ServerName> /ZoneRename <CurrentZoneName> <NewZoneName>\n" );
  3626. return ERROR_INVALID_PARAMETER;
  3627. }
  3628. //
  3629. // Zone export
  3630. //
  3631. DNS_STATUS
  3632. ProcessZoneExport(
  3633. IN DWORD Argc,
  3634. IN LPSTR * Argv,
  3635. IN LPWSTR * UnicodeArgv
  3636. )
  3637. {
  3638. DNS_STATUS status = ERROR_SUCCESS;
  3639. LPSTR pszzoneName = NULL;
  3640. LPWSTR pwszzoneName = NULL;
  3641. LPSTR pszzoneExportFile = NULL;
  3642. LPSTR cmd;
  3643. //
  3644. // ZoneExport <ZoneName> ZoneExportFile
  3645. //
  3646. if ( Argc != 2 || Argc == NEED_HELP_ARGC )
  3647. {
  3648. goto Help;
  3649. }
  3650. // Get zone name argument and output file argument.
  3651. pszzoneName = Argv[ 0 ];
  3652. pwszzoneName = UnicodeArgv[ 0 ];
  3653. Argv++;
  3654. Argc--;
  3655. if ( _stricmp( pszzoneName, "/Cache" ) == 0 )
  3656. {
  3657. pszzoneName = DNS_ZONE_CACHE;
  3658. }
  3659. pszzoneExportFile = Argv[ 0 ];
  3660. Argv++;
  3661. Argc--;
  3662. status = DnssrvExportZone(
  3663. pwszServerName,
  3664. pszzoneName,
  3665. pszzoneExportFile );
  3666. if ( status == ERROR_SUCCESS )
  3667. {
  3668. //
  3669. // If we are executing this command on the local server, try and
  3670. // get the real value of the windir environment variable to make
  3671. // the output as helpful as possible. Otherwise just print %windir%
  3672. // as literal text. Note: fServerIsRemote is not 100% accurate - if
  3673. // you type in the name of the local machine as the server, for
  3674. // example. But since it is only used to tailor the output message
  3675. // slightly this is acceptable.
  3676. //
  3677. BOOL fServerIsRemote = wcscmp( pwszServerName, L"." ) != 0;
  3678. char * pszWinDir = "%windir%";
  3679. if ( !fServerIsRemote )
  3680. {
  3681. char * pszRealWinDir = getenv( "windir" );
  3682. if ( pszRealWinDir )
  3683. {
  3684. pszWinDir = pszRealWinDir;
  3685. }
  3686. }
  3687. printf(
  3688. "DNS Server %S exported zone\n"
  3689. " %S to file %s\\system32\\dns\\%s%s\n",
  3690. pwszServerName,
  3691. pwszzoneName,
  3692. pszWinDir,
  3693. pszzoneExportFile,
  3694. fServerIsRemote ? " on the DNS server" : "" );
  3695. }
  3696. return status;
  3697. Help:
  3698. printf(
  3699. "Usage: DnsCmd <ServerName> /ZoneExport <ZoneName> <ZoneExportFile>\n"
  3700. " <ZoneName> -- FQDN of zone to export\n"
  3701. " /Cache to export cache\n" );
  3702. return ERROR_INVALID_PARAMETER;
  3703. }
  3704. //
  3705. // Move zone to another directory partition
  3706. //
  3707. DNS_STATUS
  3708. ProcessZoneChangeDirectoryPartition(
  3709. IN DWORD Argc,
  3710. IN LPSTR * Argv,
  3711. IN LPWSTR * UnicodeArgv
  3712. )
  3713. {
  3714. DNS_STATUS status = ERROR_SUCCESS;
  3715. LPSTR pszzoneName = NULL;
  3716. LPWSTR pwszzoneName = NULL;
  3717. DWORD dwdpFlag = 0; // directory partition flag for built-in
  3718. LPSTR pszdpFqdn = NULL; // directory partition FQDN for custom
  3719. //
  3720. // ZoneChangeDP ZoneName NewPartitionName
  3721. //
  3722. if ( Argc != 2 || Argc == NEED_HELP_ARGC )
  3723. {
  3724. goto Help;
  3725. }
  3726. pszzoneName = Argv[ 0 ];
  3727. pwszzoneName = UnicodeArgv[ 0 ];
  3728. Argv++;
  3729. Argc--;
  3730. if ( !parseDpSpecifier( *Argv, NULL, &pszdpFqdn ) )
  3731. {
  3732. goto Help;
  3733. }
  3734. Argv++;
  3735. Argc--;
  3736. status = DnssrvChangeZoneDirectoryPartition(
  3737. pwszServerName,
  3738. pszzoneName,
  3739. pszdpFqdn );
  3740. if ( status == ERROR_SUCCESS )
  3741. {
  3742. printf(
  3743. "DNS Server %S moved zone %S to new directory partition\n",
  3744. pwszServerName,
  3745. pwszzoneName );
  3746. }
  3747. return status;
  3748. Help:
  3749. printf(
  3750. "Usage: DnsCmd <ServerName> /ZoneChangeDirectoryPartition <ZoneName> <NewPartitionName>\n"
  3751. " <ZoneName> -- FQDN of zone to move to new partition\n"
  3752. " <NewPartition> -- FQDN of new directory partition or one of:\n"
  3753. " /domain - domain directory partition\n"
  3754. " /forest - forest directory partition\n"
  3755. " /legacy - legacy directory partition\n" );
  3756. return ERROR_INVALID_PARAMETER;
  3757. } // ProcessZoneChangeDirectoryPartition
  3758. DNS_STATUS
  3759. ProcessZoneResetSecondaries(
  3760. IN DWORD Argc,
  3761. IN LPSTR * Argv,
  3762. IN LPWSTR * UnicodeArgv
  3763. )
  3764. {
  3765. DNS_STATUS status = ERROR_SUCCESS;
  3766. DWORD fsecureSecondaries = MAXDWORD;
  3767. DWORD fnotifyLevel = MAXDWORD;
  3768. DWORD countSecondaries = 0;
  3769. DWORD countNotify = 0;
  3770. IP_ADDRESS secondaries[ MAX_IP_PROPERTY_COUNT ];
  3771. IP_ADDRESS notifyList[ MAX_IP_PROPERTY_COUNT ];
  3772. PIP_ADDRESS array;
  3773. LPSTR pszzoneName;
  3774. LPWSTR pwszzoneName;
  3775. LPSTR cmd;
  3776. DWORD count;
  3777. //
  3778. // ZoneResetSecondaries <ZoneName> [<SecureFlag>] [<NotifyFlag>] [<NotifyIPAddress>] ...]
  3779. //
  3780. if ( Argc < 1 ||
  3781. Argc == NEED_HELP_ARGC ||
  3782. getCommandName( Argv[ 0 ] ) )
  3783. {
  3784. goto Help;
  3785. }
  3786. // zone name
  3787. pszzoneName = Argv[ 0 ];
  3788. pwszzoneName = UnicodeArgv[ 0 ];
  3789. Argc--;
  3790. Argv++;
  3791. // read security and notify flags
  3792. while ( Argc )
  3793. {
  3794. cmd = getCommandName( Argv[ 0 ] );
  3795. if ( cmd )
  3796. {
  3797. // security cases
  3798. if ( !_stricmp(cmd, "NoXfr") )
  3799. {
  3800. fsecureSecondaries = ZONE_SECSECURE_NO_XFR;
  3801. }
  3802. else if ( !_stricmp(cmd, "SecureNs") )
  3803. {
  3804. fsecureSecondaries = ZONE_SECSECURE_NS_ONLY;
  3805. }
  3806. else if ( !_stricmp(cmd, "SecureList") )
  3807. {
  3808. fsecureSecondaries = ZONE_SECSECURE_LIST;
  3809. }
  3810. else if ( !_stricmp(cmd, "NonSecure") )
  3811. {
  3812. fsecureSecondaries = ZONE_SECSECURE_NO_SECURITY;
  3813. }
  3814. // notify cases
  3815. else if ( !_stricmp(cmd, "NoNotify") )
  3816. {
  3817. fnotifyLevel = ZONE_NOTIFY_OFF;
  3818. }
  3819. else if ( !_stricmp(cmd, "Notify") )
  3820. {
  3821. fnotifyLevel = ZONE_NOTIFY_ALL;
  3822. }
  3823. else if ( !_stricmp(cmd, "NotifyList") )
  3824. {
  3825. fnotifyLevel = ZONE_NOTIFY_LIST_ONLY;
  3826. }
  3827. else
  3828. {
  3829. goto Help;
  3830. }
  3831. Argc--;
  3832. Argv++;
  3833. continue;
  3834. }
  3835. // get IP list
  3836. // - secondary IP before <Notify> flag
  3837. // - notify IP list after
  3838. array = secondaries;
  3839. if ( fnotifyLevel != MAXDWORD )
  3840. {
  3841. array = notifyList;
  3842. }
  3843. count = 0;
  3844. while ( Argc )
  3845. {
  3846. IP_ADDRESS ip;
  3847. cmd = getCommandName( Argv[0] );
  3848. if ( cmd )
  3849. {
  3850. break; // no more IP
  3851. }
  3852. ip = inet_addr( Argv[0] );
  3853. if ( ip == -1 )
  3854. {
  3855. goto Help;
  3856. }
  3857. array[ count ] = ip;
  3858. count++;
  3859. Argc--;
  3860. Argv++;
  3861. }
  3862. if ( fnotifyLevel == MAXDWORD )
  3863. {
  3864. countSecondaries = count;
  3865. }
  3866. else
  3867. {
  3868. countNotify = count;
  3869. }
  3870. }
  3871. //
  3872. // default flags
  3873. // - do intelligent thing if lists are given
  3874. // otherwise default to open zone with notify
  3875. //
  3876. if ( countSecondaries )
  3877. {
  3878. fsecureSecondaries = ZONE_SECSECURE_LIST;
  3879. }
  3880. else if ( fsecureSecondaries == MAXDWORD )
  3881. {
  3882. fsecureSecondaries = ZONE_SECSECURE_NO_SECURITY;
  3883. }
  3884. if ( countNotify )
  3885. {
  3886. fnotifyLevel = ZONE_NOTIFY_LIST_ONLY;
  3887. }
  3888. else if ( fnotifyLevel == MAXDWORD )
  3889. {
  3890. fnotifyLevel = ZONE_NOTIFY_ALL;
  3891. }
  3892. //
  3893. // reset secondaries on server
  3894. //
  3895. if ( g_UseWmi )
  3896. {
  3897. status = DnscmdWmi_ProcessResetZoneSecondaries(
  3898. pszzoneName,
  3899. fsecureSecondaries,
  3900. countSecondaries,
  3901. secondaries,
  3902. fnotifyLevel,
  3903. countNotify,
  3904. notifyList );
  3905. }
  3906. else
  3907. {
  3908. status = DnssrvResetZoneSecondaries(
  3909. pwszServerName,
  3910. pszzoneName,
  3911. fsecureSecondaries,
  3912. countSecondaries,
  3913. secondaries,
  3914. fnotifyLevel,
  3915. countNotify,
  3916. notifyList );
  3917. }
  3918. if ( status == ERROR_SUCCESS )
  3919. {
  3920. printf(
  3921. "Zone %S reset notify list successful\n",
  3922. pwszzoneName );
  3923. }
  3924. return status;
  3925. Help:
  3926. printf(
  3927. "Usage: DnsCmd <ServerName> /ZoneResetSecondaries <ZoneName> \n"
  3928. " [<Security>] [<SecondaryIPAddress>] ...]\n"
  3929. " [<Notify>] [<NotifyIPAddress>] ...]\n"
  3930. " <Security>:\n"
  3931. " /NoXfr -- no zone transfer\n"
  3932. " /NonSecure -- transfer to any IP (default)\n"
  3933. " /SecureNs -- transfer only to NS for zone\n"
  3934. " /SecureList -- transfer only to NS in secondary list; must\n"
  3935. " then provide secondary IP list\n"
  3936. " <Notify>:\n"
  3937. " /NoNotify -- turn off notify\n"
  3938. " /Notify -- notify (default); notifies all secondaries in list and \n"
  3939. " for non-DS primary notifies all NS servers for zone\n"
  3940. " /NotifyList -- notify only notify list IPs;\n"
  3941. " must then provide notify IP list\n" );
  3942. return ERROR_INVALID_PARAMETER;
  3943. }
  3944. DNS_STATUS
  3945. ProcessZoneResetScavengeServers(
  3946. IN DWORD Argc,
  3947. IN LPSTR * Argv,
  3948. IN LPWSTR * UnicodeArgv
  3949. )
  3950. {
  3951. DNS_STATUS status = ERROR_SUCCESS;
  3952. IP_ADDRESS serverArray[ MAX_IP_PROPERTY_COUNT + 1 ];
  3953. DWORD serverCount;
  3954. LPSTR pszzoneName;
  3955. LPWSTR pwszzoneName;
  3956. //
  3957. // ZoneSetScavengeServers <ZoneName> <ServerIPAddress>
  3958. //
  3959. if ( Argc < 1 || getCommandName(Argv[0]) )
  3960. {
  3961. goto Help;
  3962. }
  3963. // zone name
  3964. pszzoneName = Argv[ 0 ];
  3965. pwszzoneName = UnicodeArgv[ 0 ];
  3966. Argc--;
  3967. Argv++;
  3968. // get server IP list
  3969. serverCount = readIpArray(
  3970. (PIP_ARRAY) serverArray,
  3971. MAX_IP_PROPERTY_COUNT,
  3972. Argc,
  3973. Argv );
  3974. if ( serverCount != Argc )
  3975. {
  3976. goto Help;
  3977. }
  3978. DnsPrint_Ip4Array(
  3979. dnscmd_PrintRoutine,
  3980. dnscmd_PrintContext,
  3981. "New scavenge servers:",
  3982. "server",
  3983. ( PIP_ARRAY ) serverArray );
  3984. //
  3985. // reset scavenging servers
  3986. // - if NO addresses given, send NULL to enable all servers to
  3987. // scavenge zone
  3988. //
  3989. status = DnssrvOperation(
  3990. pwszServerName,
  3991. pszzoneName,
  3992. DNS_REGKEY_ZONE_SCAVENGE_SERVERS,
  3993. DNSSRV_TYPEID_IPARRAY,
  3994. serverCount
  3995. ? (PIP_ARRAY) serverArray
  3996. : NULL );
  3997. if ( status == ERROR_SUCCESS )
  3998. {
  3999. printf(
  4000. "Reset scavenging servers on zone %S successfully.\n",
  4001. pwszzoneName );
  4002. }
  4003. else
  4004. {
  4005. printf(
  4006. "Error, failed reset of scavenge servers on zone %S.\n"
  4007. " Status = %d\n",
  4008. pwszzoneName,
  4009. status );
  4010. }
  4011. return status;
  4012. Help:
  4013. printf(
  4014. "Usage: DnsCmd <ServerName> /ZoneResetScavengeServers <ZoneName> [<Server IPs>]\n"
  4015. " <Server IPs> -- list of one or more IP addresses of servers to scavenge\n"
  4016. " this zone; if no addresses given ALL servers hosting this zone\n"
  4017. " will be allowed to scavenge the zone.\n" );
  4018. return ERROR_INVALID_PARAMETER;
  4019. }
  4020. DNS_STATUS
  4021. ProcessZoneResetMasters(
  4022. IN DWORD Argc,
  4023. IN LPSTR * Argv,
  4024. IN LPWSTR * UnicodeArgv
  4025. )
  4026. {
  4027. DNS_STATUS status = ERROR_SUCCESS;
  4028. IP_ADDRESS serverArray[ MAX_IP_PROPERTY_COUNT+1 ];
  4029. DWORD serverCount;
  4030. LPSTR pszzoneName;
  4031. LPWSTR pwszzoneName;
  4032. LPSTR psz;
  4033. BOOL fLocalMasters = FALSE;
  4034. //
  4035. // ZoneResetMasters <ZoneName> [/Local] <MasterIPAddress>
  4036. //
  4037. // Local tells the server to set the local master list for DS integrated
  4038. // stub zones.
  4039. //
  4040. if ( Argc < 1 || getCommandName(Argv[0]) )
  4041. {
  4042. goto Help;
  4043. }
  4044. // zone name
  4045. pszzoneName = Argv[ 0 ];
  4046. pwszzoneName = UnicodeArgv[ 0 ];
  4047. Argc--;
  4048. Argv++;
  4049. // local flag
  4050. psz = getCommandName( Argv[ 0 ] );
  4051. if ( psz )
  4052. {
  4053. if ( _stricmp( psz, "Local" ) == 0 )
  4054. {
  4055. fLocalMasters = TRUE;
  4056. }
  4057. else
  4058. {
  4059. goto Help; // Unknown option
  4060. }
  4061. Argc--;
  4062. Argv++;
  4063. }
  4064. // get server IP list - an empty IP list is permissable
  4065. serverCount = readIpArray(
  4066. ( PIP_ARRAY ) serverArray,
  4067. MAX_IP_PROPERTY_COUNT,
  4068. Argc,
  4069. Argv );
  4070. if ( serverCount != Argc )
  4071. {
  4072. goto Help;
  4073. }
  4074. //
  4075. // reset masters
  4076. //
  4077. if ( g_UseWmi )
  4078. {
  4079. status = DnscmdWmi_ProcessDnssrvOperation(
  4080. pszzoneName,
  4081. fLocalMasters ?
  4082. DNS_REGKEY_ZONE_LOCAL_MASTERS :
  4083. DNS_REGKEY_ZONE_MASTERS,
  4084. DNSSRV_TYPEID_IPARRAY,
  4085. ( PIP_ARRAY ) serverArray );
  4086. }
  4087. else
  4088. {
  4089. status = DnssrvOperation(
  4090. pwszServerName,
  4091. pszzoneName,
  4092. fLocalMasters ?
  4093. DNS_REGKEY_ZONE_LOCAL_MASTERS :
  4094. DNS_REGKEY_ZONE_MASTERS,
  4095. DNSSRV_TYPEID_IPARRAY,
  4096. ( PIP_ARRAY ) serverArray );
  4097. }
  4098. if ( status == ERROR_SUCCESS )
  4099. {
  4100. printf(
  4101. "Reset master servers for zone %S successfully.\n",
  4102. pwszzoneName );
  4103. }
  4104. else
  4105. {
  4106. printf(
  4107. "Error failed reset of master servers for zone %S.\n"
  4108. " Status = %d\n",
  4109. pwszzoneName ,
  4110. status );
  4111. }
  4112. return status;
  4113. Help:
  4114. printf(
  4115. "Usage: DnsCmd <ServerName> /ZoneResetMasters <ZoneName> [/Local] [<Server IPs>]\n"
  4116. " /Local -- Set the local master list for DS integrated zones.\n"
  4117. " <Server IPs> -- List of one or more IP addresses of master servers for\n"
  4118. " this zone. Masters may include the primary or other secondaries\n"
  4119. " for the zone, but should not make the replication graph cyclic.\n" );
  4120. return ERROR_INVALID_PARAMETER;
  4121. }
  4122. //
  4123. // Record viewing commands
  4124. //
  4125. DNS_STATUS
  4126. ProcessEnumRecords(
  4127. IN DWORD Argc,
  4128. IN LPSTR * Argv,
  4129. IN LPWSTR * UnicodeArgv
  4130. )
  4131. {
  4132. DNS_STATUS status = ERROR_SUCCESS;
  4133. LPSTR pzoneName;
  4134. LPSTR pnodeName;
  4135. BOOL ballocatedNode;
  4136. LPSTR pstartChild = NULL;
  4137. WORD type = DNS_TYPE_ALL;
  4138. DWORD flag = 0;
  4139. DWORD authFlag = 0;
  4140. DWORD bufferLength;
  4141. PBYTE pbuffer;
  4142. LPSTR pszcmd;
  4143. PDNS_RPC_NAME plastName;
  4144. BOOL bcontinue = FALSE;
  4145. BOOL bdetail = FALSE;
  4146. CHAR nextChildName[ DNS_MAX_NAME_BUFFER_LENGTH ];
  4147. //
  4148. // EnumRecords
  4149. //
  4150. if ( Argc < 2 || Argc == NEED_HELP_ARGC )
  4151. {
  4152. goto Help;
  4153. }
  4154. //
  4155. // read zone and domain name
  4156. //
  4157. readZoneAndDomainName(
  4158. Argv,
  4159. & pzoneName,
  4160. & pnodeName,
  4161. & ballocatedNode,
  4162. NULL,
  4163. NULL );
  4164. Argv++;
  4165. Argc--;
  4166. Argv++;
  4167. Argc--;
  4168. //
  4169. // commands
  4170. //
  4171. // on authority level flags, build separate from final flag
  4172. // so we can determine if authority screen was set, otherwise
  4173. // flag will be set to view all data
  4174. while ( (LONG)Argc > 0 )
  4175. {
  4176. pszcmd = getCommandName( *Argv );
  4177. if ( !pszcmd )
  4178. {
  4179. goto Help;
  4180. }
  4181. else if ( !_stricmp(pszcmd, "Continue") )
  4182. {
  4183. bcontinue = TRUE;
  4184. }
  4185. else if ( !_stricmp(pszcmd, "Detail") )
  4186. {
  4187. bdetail = TRUE;
  4188. }
  4189. else if ( !_stricmp(pszcmd, "Authority") )
  4190. {
  4191. authFlag |= DNS_RPC_VIEW_AUTHORITY_DATA;
  4192. }
  4193. else if ( !_stricmp(pszcmd, "Glue") )
  4194. {
  4195. authFlag |= DNS_RPC_VIEW_GLUE_DATA;
  4196. }
  4197. else if ( !_stricmp(pszcmd, "Additional") )
  4198. {
  4199. flag |= DNS_RPC_VIEW_ADDITIONAL_DATA;
  4200. }
  4201. else if ( !_stricmp(pszcmd, "Node") )
  4202. {
  4203. flag |= DNS_RPC_VIEW_NO_CHILDREN;
  4204. }
  4205. else if ( !_stricmp(pszcmd, "Root") )
  4206. {
  4207. flag |= DNS_RPC_VIEW_NO_CHILDREN;
  4208. }
  4209. else if ( !_stricmp(pszcmd, "Child") )
  4210. {
  4211. flag |= DNS_RPC_VIEW_ONLY_CHILDREN;
  4212. }
  4213. else if ( !_stricmp(pszcmd, "Type") )
  4214. {
  4215. Argv++;
  4216. Argc--;
  4217. if ( (INT)Argc <= 0 )
  4218. {
  4219. goto Help;
  4220. }
  4221. type = Dns_RecordTypeForName( *Argv, 0 );
  4222. if ( type == 0 )
  4223. {
  4224. type = DNS_TYPE_ALL;
  4225. }
  4226. }
  4227. else if ( !_stricmp(pszcmd, "StartChild") ||
  4228. !_stricmp(pszcmd, "StartPoint") )
  4229. {
  4230. Argv++;
  4231. Argc--;
  4232. if ( ! Argc )
  4233. {
  4234. goto Help;
  4235. }
  4236. pstartChild = *Argv;
  4237. }
  4238. else // unknown command
  4239. {
  4240. goto Help;
  4241. }
  4242. Argc--;
  4243. Argv++;
  4244. }
  4245. // if no flag entered, view all data
  4246. if ( authFlag == 0 )
  4247. {
  4248. authFlag = DNS_RPC_VIEW_ALL_DATA;
  4249. }
  4250. flag |= authFlag;
  4251. //
  4252. // enumerate records
  4253. // - call in loop to handle error more data case
  4254. //
  4255. if ( g_UseWmi )
  4256. {
  4257. status = DnscmdWmi_ProcessEnumRecords(
  4258. pzoneName,
  4259. pnodeName,
  4260. bdetail,
  4261. flag );
  4262. }
  4263. else
  4264. {
  4265. while ( 1 )
  4266. {
  4267. status = DnssrvEnumRecords(
  4268. pwszServerName,
  4269. pzoneName,
  4270. pnodeName,
  4271. pstartChild,
  4272. type,
  4273. flag,
  4274. NULL,
  4275. NULL,
  4276. & bufferLength,
  4277. & pbuffer );
  4278. if ( status == ERROR_SUCCESS ||
  4279. status == ERROR_MORE_DATA )
  4280. {
  4281. plastName = DnsPrint_RpcRecordsInBuffer(
  4282. dnscmd_PrintRoutine,
  4283. dnscmd_PrintContext,
  4284. "Returned records:\n",
  4285. bdetail,
  4286. bufferLength,
  4287. pbuffer );
  4288. if ( status == ERROR_SUCCESS )
  4289. {
  4290. break;
  4291. }
  4292. // more records to enumerate
  4293. if ( !plastName )
  4294. {
  4295. break;
  4296. }
  4297. DnssrvCopyRpcNameToBuffer(
  4298. nextChildName,
  4299. plastName );
  4300. if ( bcontinue )
  4301. {
  4302. pstartChild = nextChildName;
  4303. DNSDBG( ANY, (
  4304. "Continuing enum at %s\n",
  4305. pstartChild ));
  4306. continue;
  4307. }
  4308. else
  4309. {
  4310. printf(
  4311. "More records remain to be enumerated!\n"
  4312. "\n"
  4313. "To enumerate ALL reissue the command with the \"/Continue\" option.\n"
  4314. " OR\n"
  4315. "To enumerate remaining records serially, reissue the command \n"
  4316. "with \"/StartChild %s\" option.\n",
  4317. nextChildName );
  4318. status = ERROR_SUCCESS;
  4319. break;
  4320. }
  4321. }
  4322. else
  4323. {
  4324. printf(
  4325. "DNS Server failed to enumerate records for node %s.\n"
  4326. " Status = %d (0x%08lx)\n",
  4327. pnodeName,
  4328. status, status );
  4329. }
  4330. break;
  4331. }
  4332. }
  4333. return status;
  4334. Help:
  4335. printf( "Usage: DnsCmd <ServerName> /EnumRecords <ZoneName> <NodeName> "
  4336. "[<DataOptions>] [<ViewOptions>]\n"
  4337. " <ZoneName> -- FQDN of zone node to enumerate\n"
  4338. " /RootHints for roots-hints enumeration\n"
  4339. " /Cache for cache enumeration\n"
  4340. " <NodeName> -- name of node whose records will be enumerated\n"
  4341. " - \"@\" for zone root OR\n"
  4342. " - FQDN of a node (name with a '.' at the end) OR\n"
  4343. " - node name relative to the <ZoneName>\n"
  4344. " <DataOptions>: (All data is the default)\n"
  4345. " /Type <RRType> -- enumerate RRs of specific type\n"
  4346. " <RRType> is standard type name; eg. A, NS, SOA, ...\n"
  4347. " /Authority -- include authoritative data\n"
  4348. " /Glue -- include glue data\n"
  4349. " /Additional -- include additional data when enumerating\n"
  4350. " /Node -- only enumerate RRs of the given node\n"
  4351. " /Child -- only enumerate RRs of children of the given node\n"
  4352. " /StartChild <ChildName> -- child name, after which to start enumeration\n"
  4353. " <ViewOptions>:\n"
  4354. " /Continue -- on full buffer condition, continue enum until end of records\n"
  4355. " default is to retrieve only first buffer of data\n"
  4356. " /Detail -- print detailed record node information\n"
  4357. " default is view of records similar to zone file\n\n" );
  4358. return ERROR_INVALID_PARAMETER;
  4359. }
  4360. typedef struct
  4361. {
  4362. LONG ilNodes;
  4363. LONG ilRecords;
  4364. int ilRecurseDepth;
  4365. int ilMaxRecurseDepth;
  4366. } DISP_ZONE_STATS, * PDISP_ZONE_STATS;
  4367. PDNS_RPC_NAME
  4368. DNS_API_FUNCTION
  4369. ProcessDisplayAllZoneRecords_Guts(
  4370. IN PRINT_ROUTINE PrintRoutine,
  4371. IN OUT PPRINT_CONTEXT pPrintContext,
  4372. IN LPSTR pZoneName,
  4373. IN LPSTR pNodeName,
  4374. IN WORD wType,
  4375. IN DWORD dwFlags,
  4376. IN BOOL fDetail,
  4377. IN PDISP_ZONE_STATS pStats
  4378. )
  4379. /*++
  4380. Routine Description:
  4381. The guts of the dump cache functionality.
  4382. Arguments:
  4383. PrintRoutine -- printf like routine to print with
  4384. fDetail -- if TRUE print detailed record info
  4385. dwBufferLength -- buffer length
  4386. abBuffer -- ptr to RPC buffer
  4387. Return Value:
  4388. Ptr to last RPC node name in buffer.
  4389. NULL on error.
  4390. --*/
  4391. {
  4392. PBYTE pcurrent;
  4393. PBYTE pstop;
  4394. PDNS_RPC_NAME plastName = NULL;
  4395. INT recordCount;
  4396. PCHAR precordHeader;
  4397. DNS_STATUS status;
  4398. PBYTE pbuffer = NULL;
  4399. DWORD dwbufferSize = 0;
  4400. CHAR nextChildName[ DNS_MAX_NAME_BUFFER_LENGTH ];
  4401. LPSTR pstartChild = NULL;
  4402. BOOL fdisplayedHeader = FALSE;
  4403. if ( pStats )
  4404. {
  4405. if ( ++pStats->ilRecurseDepth > pStats->ilMaxRecurseDepth )
  4406. {
  4407. pStats->ilMaxRecurseDepth = pStats->ilRecurseDepth;
  4408. }
  4409. // printf( "GUTS: depth %d: %s\n", pStats->ilRecurseDepth, pNodeName );
  4410. }
  4411. while ( 1 )
  4412. {
  4413. if ( pbuffer )
  4414. {
  4415. MIDL_user_free( pbuffer );
  4416. pbuffer = NULL;
  4417. }
  4418. status = DnssrvEnumRecords(
  4419. pwszServerName,
  4420. pZoneName,
  4421. pNodeName,
  4422. pstartChild,
  4423. wType,
  4424. dwFlags,
  4425. NULL,
  4426. NULL,
  4427. &dwbufferSize,
  4428. &pbuffer );
  4429. if ( status == ERROR_SUCCESS || status == ERROR_MORE_DATA )
  4430. {
  4431. DnsPrint_Lock();
  4432. if ( !pbuffer )
  4433. {
  4434. PrintRoutine( pPrintContext, "NULL record buffer ptr.\n" );
  4435. goto Done;
  4436. }
  4437. //
  4438. // find stop byte
  4439. //
  4440. ASSERT( DNS_IS_DWORD_ALIGNED( pbuffer ) );
  4441. pstop = pbuffer + dwbufferSize;
  4442. pcurrent = pbuffer;
  4443. //
  4444. // loop until out of nodes
  4445. //
  4446. while ( pcurrent < pstop )
  4447. {
  4448. PDNS_RPC_NODE pcurrNode = ( PDNS_RPC_NODE ) pcurrent;
  4449. CHAR szchildNodeName[ DNS_MAX_NAME_BUFFER_LENGTH ] = "";
  4450. //
  4451. // print owner node
  4452. // - if NOT printing detail and no records
  4453. // (essentially domain nodes) then no node print
  4454. //
  4455. plastName = &pcurrNode->dnsNodeName;
  4456. recordCount = pcurrNode->wRecordCount;
  4457. if ( pStats )
  4458. {
  4459. ++pStats->ilNodes;
  4460. pStats->ilRecords += recordCount;
  4461. }
  4462. if ( fDetail )
  4463. {
  4464. DnsPrint_RpcNode(
  4465. PrintRoutine, pPrintContext,
  4466. NULL,
  4467. (PDNS_RPC_NODE)pcurrent );
  4468. if ( recordCount == 0 )
  4469. {
  4470. PrintRoutine( pPrintContext, "\n" );
  4471. }
  4472. }
  4473. else if ( recordCount != 0 )
  4474. {
  4475. BOOL outputLastName = FALSE;
  4476. if ( plastName && plastName->cchNameLength )
  4477. {
  4478. DnsPrint_RpcName(
  4479. PrintRoutine, pPrintContext,
  4480. NULL,
  4481. plastName,
  4482. NULL );
  4483. outputLastName = TRUE;
  4484. }
  4485. if ( pNodeName &&
  4486. ( *pNodeName != '@' || !outputLastName ) )
  4487. {
  4488. PWSTR pwsznodeName = getUnicodeForUtf8( pNodeName );
  4489. PrintRoutine(
  4490. pPrintContext,
  4491. "%s%S",
  4492. outputLastName ? "." : "",
  4493. pwsznodeName );
  4494. FREE_HEAP( pwsznodeName );
  4495. }
  4496. }
  4497. if ( pcurrNode->dwFlags & DNS_RPC_FLAG_NODE_STICKY )
  4498. {
  4499. //
  4500. // Set up child node name before we start iterating
  4501. // records at this name.
  4502. //
  4503. memcpy(
  4504. szchildNodeName,
  4505. pcurrNode->dnsNodeName.achName,
  4506. pcurrNode->dnsNodeName.cchNameLength );
  4507. szchildNodeName[ pcurrNode->dnsNodeName.cchNameLength ] = '.';
  4508. szchildNodeName[ pcurrNode->dnsNodeName.cchNameLength + 1 ] = '\0';
  4509. if ( strcmp( pNodeName, "@" ) != 0 )
  4510. {
  4511. strcat( szchildNodeName, pNodeName );
  4512. }
  4513. if ( szchildNodeName[ strlen( szchildNodeName ) - 1 ] == '.' )
  4514. {
  4515. szchildNodeName[ strlen( szchildNodeName ) - 1 ] = '\0';
  4516. }
  4517. }
  4518. pcurrent += pcurrNode->wLength;
  4519. pcurrent = DNS_NEXT_DWORD_PTR(pcurrent);
  4520. //
  4521. // Print all records at this node.
  4522. //
  4523. precordHeader = "";
  4524. while( recordCount-- )
  4525. {
  4526. if ( pcurrent >= pstop )
  4527. {
  4528. PrintRoutine( pPrintContext,
  4529. "ERROR: Bogus buffer at %p\n"
  4530. " Expect record at %p past buffer end at %p\n"
  4531. " with %d records remaining.\n",
  4532. pbuffer,
  4533. (PDNS_RPC_RECORD) pcurrent,
  4534. pstop,
  4535. recordCount+1 );
  4536. ASSERT( FALSE );
  4537. break;
  4538. }
  4539. DnsPrint_RpcRecord(
  4540. PrintRoutine, pPrintContext,
  4541. precordHeader,
  4542. fDetail,
  4543. (PDNS_RPC_RECORD)pcurrent );
  4544. precordHeader = "\t\t";
  4545. pcurrent += ((PDNS_RPC_RECORD)pcurrent)->wDataLength
  4546. + SIZEOF_DNS_RPC_RECORD_HEADER;
  4547. pcurrent = DNS_NEXT_DWORD_PTR(pcurrent);
  4548. }
  4549. //
  4550. // Recurse on this node if it has children. If the caller's
  4551. // header argument is NULL or is a comment assume we're at
  4552. // the root of the zone.
  4553. //
  4554. if ( *szchildNodeName )
  4555. {
  4556. ProcessDisplayAllZoneRecords_Guts(
  4557. PrintRoutine,
  4558. pPrintContext,
  4559. pZoneName,
  4560. szchildNodeName,
  4561. wType,
  4562. dwFlags,
  4563. fDetail,
  4564. pStats );
  4565. }
  4566. }
  4567. if ( status == ERROR_SUCCESS )
  4568. {
  4569. break;
  4570. }
  4571. // more records to enumerate
  4572. if ( !plastName )
  4573. {
  4574. break;
  4575. }
  4576. DnssrvCopyRpcNameToBuffer(
  4577. nextChildName,
  4578. plastName );
  4579. pstartChild = nextChildName;
  4580. DNSDBG( ANY, (
  4581. "Continuing enum at %s\n",
  4582. pstartChild ));
  4583. continue;
  4584. }
  4585. else
  4586. {
  4587. printf(
  4588. "DNS Server failed to enumerate records for node %s.\n"
  4589. " Status = %s %d (0x%08lx)\n",
  4590. pNodeName,
  4591. Dns_StatusString( status ),
  4592. status, status );
  4593. }
  4594. break;
  4595. }
  4596. if ( pbuffer )
  4597. {
  4598. MIDL_user_free( pbuffer );
  4599. }
  4600. Done:
  4601. DnsPrint_Unlock();
  4602. if ( pStats )
  4603. {
  4604. --pStats->ilRecurseDepth;
  4605. }
  4606. return plastName;
  4607. } // ProcessDisplayAllZoneRecords_Guts
  4608. DNS_STATUS
  4609. ProcessDisplayAllZoneRecords(
  4610. IN DWORD Argc,
  4611. IN LPSTR * Argv,
  4612. IN LPWSTR * UnicodeArgv
  4613. )
  4614. {
  4615. DNS_STATUS status = ERROR_SUCCESS;
  4616. LPSTR pszcmd;
  4617. LPSTR pszzoneName = NULL;
  4618. BOOL bdetail = FALSE;
  4619. time_t now;
  4620. CHAR sznow[ 30 ];
  4621. size_t len;
  4622. WCHAR wszserverName[ DNS_MAX_NAME_BUFFER_LENGTH ] = L"";
  4623. PWSTR pwszserverDisplayName = pwszServerName;
  4624. DISP_ZONE_STATS displayZoneStats = { 0 };
  4625. PWSTR pwszzonename;
  4626. //
  4627. // /ZonePrint [ZoneName] /Detail
  4628. //
  4629. if ( Argc > 3 || Argc == NEED_HELP_ARGC )
  4630. {
  4631. goto Help;
  4632. }
  4633. //
  4634. // Parse arguments.
  4635. //
  4636. while ( Argc )
  4637. {
  4638. pszcmd = getCommandName( *Argv );
  4639. if ( !pszcmd && !pszzoneName )
  4640. {
  4641. pszzoneName = *Argv;
  4642. }
  4643. else if ( _strnicmp( pszcmd, "D", 1 ) == 0 )
  4644. {
  4645. bdetail = TRUE;
  4646. }
  4647. else
  4648. {
  4649. goto Help;
  4650. }
  4651. Argv++;
  4652. Argc--;
  4653. }
  4654. if ( !pszzoneName )
  4655. {
  4656. goto Help;
  4657. }
  4658. // Get time string.
  4659. time( &now );
  4660. strcpy( sznow, asctime( gmtime( &now ) ) );
  4661. len = strlen( sznow ) - 1;
  4662. if ( sznow[ len ] == '\n' )
  4663. {
  4664. sznow[ len ] = '\0';
  4665. }
  4666. // Get local hostname string.
  4667. if ( wcscmp( pwszServerName, L"." ) == 0 )
  4668. {
  4669. DWORD bufsize = sizeof( wszserverName ) /
  4670. sizeof( wszserverName[ 0 ] );
  4671. if ( GetComputerNameExW(
  4672. ComputerNamePhysicalDnsFullyQualified,
  4673. wszserverName,
  4674. &bufsize ) )
  4675. {
  4676. pwszserverDisplayName = wszserverName;
  4677. }
  4678. }
  4679. pwszzonename = getUnicodeForUtf8( pszzoneName );
  4680. dnscmd_PrintRoutine(
  4681. dnscmd_PrintContext,
  4682. ";\n"
  4683. "; Zone: %S\n"
  4684. "; Server: %S\n"
  4685. "; Time: %s UTC\n"
  4686. ";\n",
  4687. pwszzonename,
  4688. pwszserverDisplayName,
  4689. sznow );
  4690. FREE_HEAP( pwszzonename );
  4691. if ( ProcessDisplayAllZoneRecords_Guts(
  4692. dnscmd_PrintRoutine,
  4693. dnscmd_PrintContext,
  4694. pszzoneName,
  4695. "@",
  4696. DNS_TYPE_ALL,
  4697. DNS_RPC_VIEW_ALL_DATA,
  4698. bdetail,
  4699. &displayZoneStats ) )
  4700. {
  4701. dnscmd_PrintRoutine(
  4702. dnscmd_PrintContext,
  4703. ";\n"
  4704. "; Finished zone: %lu nodes and %lu records in %d seconds\n"
  4705. ";\n",
  4706. displayZoneStats.ilNodes,
  4707. displayZoneStats.ilRecords,
  4708. time( NULL ) - now );
  4709. }
  4710. return status;
  4711. Help:
  4712. printf(
  4713. "Usage: DnsCmd <ServerName> /ZonePrint [<ZoneName>] [/Detail]\n"
  4714. " <ZoneName> -- name of the zone (use ..Cache for DNS server cache)\n"
  4715. " /Detail -- explicit RPC node contents\n" );
  4716. return ERROR_INVALID_PARAMETER;
  4717. } // ProcessDisplayAllZoneRecords
  4718. DNS_STATUS
  4719. ProcessSbsRegister(
  4720. IN DWORD Argc,
  4721. IN LPSTR * Argv,
  4722. IN LPWSTR * UnicodeArgv
  4723. )
  4724. {
  4725. DNS_STATUS status = ERROR_SUCCESS;
  4726. IP_ADDRESS hostIp;
  4727. DWORD ttl;
  4728. //
  4729. // SbsRegister
  4730. //
  4731. if ( Argc < 2 || Argc == NEED_HELP_ARGC )
  4732. {
  4733. goto Usage;
  4734. }
  4735. // client host IP
  4736. hostIp = inet_addr( Argv[3] );
  4737. if ( hostIp == (-1) )
  4738. {
  4739. goto Usage;
  4740. }
  4741. // record TTL
  4742. ttl = strtoul(
  4743. Argv[3],
  4744. NULL,
  4745. 10 );
  4746. status = DnssrvSbsAddClientToIspZone(
  4747. pwszServerName,
  4748. Argv[0],
  4749. Argv[1],
  4750. Argv[2],
  4751. hostIp,
  4752. ttl );
  4753. if ( status == ERROR_SUCCESS )
  4754. {
  4755. printf(
  4756. "DNS Server %S registered SAM records for client %s:\n",
  4757. pwszServerName,
  4758. Argv[1] );
  4759. }
  4760. else
  4761. {
  4762. printf(
  4763. "DNS Server %S failed to register SAM records for %s.\n"
  4764. " Status = %d (0x%08lx)\n",
  4765. pwszServerName,
  4766. Argv[1],
  4767. status, status );
  4768. }
  4769. return status;
  4770. Usage:
  4771. printf(
  4772. "Usage: dnscmd <Server> /SbsRegister <IspZoneName> <Client> <ClientHost> <HostIP> <TTL>\n"
  4773. " <Server> -- server name (DNS, netBIOS or IP)\n"
  4774. " <IspZoneName> -- full DNS name of ISP's zone\n"
  4775. " <Client> -- client name (not FQDN)\n"
  4776. " <ClientHost> -- client host name (not FQDN)\n"
  4777. " <HostIP> -- client host IP\n"
  4778. " <Ttl> -- TTL for records\n"
  4779. "\n" );
  4780. return ERROR_INVALID_PARAMETER;
  4781. }
  4782. DNS_STATUS
  4783. ProcessSbsDeleteRecord(
  4784. IN DWORD Argc,
  4785. IN LPSTR * Argv,
  4786. IN LPWSTR * UnicodeArgv
  4787. )
  4788. {
  4789. DNS_STATUS status = ERROR_SUCCESS;
  4790. WORD type;
  4791. IP_ADDRESS hostIp = 0;
  4792. LPSTR pszdata = NULL;
  4793. //
  4794. // SbsRegister
  4795. //
  4796. if ( Argc < 5 || Argc == NEED_HELP_ARGC )
  4797. {
  4798. goto Usage;
  4799. }
  4800. // type to delete
  4801. type = Dns_RecordTypeForName( Argv[3], 0 );
  4802. if ( type == 0 )
  4803. {
  4804. goto Usage;
  4805. }
  4806. // if A record, then data will be IP address, otherwise it is DNS name
  4807. if ( type == DNS_TYPE_A )
  4808. {
  4809. hostIp = inet_addr( Argv[4] );
  4810. if ( hostIp == (-1) )
  4811. {
  4812. goto Usage;
  4813. }
  4814. }
  4815. else
  4816. {
  4817. pszdata = Argv[4];
  4818. }
  4819. status = DnssrvSbsDeleteRecord(
  4820. pwszServerName,
  4821. Argv[0],
  4822. Argv[1],
  4823. Argv[2],
  4824. type,
  4825. pszdata,
  4826. hostIp );
  4827. if ( status == ERROR_SUCCESS )
  4828. {
  4829. printf(
  4830. "DNS Server %S deleted SAM record at %s in client domain %s:\n",
  4831. pwszServerName,
  4832. Argv[2],
  4833. Argv[1] );
  4834. }
  4835. else
  4836. {
  4837. printf(
  4838. "DNS Server %S failed to delete SAM record at %s in domain %s.\n"
  4839. " Status = %d (0x%08lx)\n",
  4840. pwszServerName,
  4841. Argv[2],
  4842. Argv[1],
  4843. status, status );
  4844. }
  4845. return status;
  4846. Usage:
  4847. printf(
  4848. "Usage: DnsCmd <Server> /SbsDeleteA <ZoneName> <Domain> <Host> <Type> <Data>\n"
  4849. " <Server> -- server name (DNS, netBIOS or IP)\n"
  4850. " <ZoneName> -- full DNS name of ISP's zone\n"
  4851. " <Client> -- client name (not FQDN)\n"
  4852. " <Host> -- client host name (not FQDN)\n"
  4853. " <Type> -- record type (ex. A, NS, CNAME)\n"
  4854. " <HostIP> -- client host IP\n"
  4855. "\n" );
  4856. return ERROR_INVALID_PARAMETER;
  4857. }
  4858. //
  4859. // Directory partition operations
  4860. //
  4861. DNS_STATUS
  4862. ProcessEnumDirectoryPartitions(
  4863. IN DWORD Argc,
  4864. IN LPSTR * Argv,
  4865. IN LPWSTR * UnicodeArgv
  4866. )
  4867. {
  4868. DNS_STATUS status = ERROR_SUCCESS;
  4869. PDNS_RPC_DP_LIST pdpList = NULL;
  4870. LPSTR pszcmd;
  4871. DWORD dwfilter = 0;
  4872. //
  4873. // Command format: /EnumDirectoryPartitions [filter strings]
  4874. //
  4875. //
  4876. //
  4877. if ( Argc > 1 || Argc == NEED_HELP_ARGC )
  4878. {
  4879. goto Help;
  4880. }
  4881. if ( Argc == 1 )
  4882. {
  4883. pszcmd = getCommandName( *Argv );
  4884. if ( pszcmd && _strnicmp( pszcmd, "Cust", 4 ) == 0 )
  4885. {
  4886. dwfilter |= DNS_ENUMDPS_CUSTOMONLY;
  4887. }
  4888. Argv++;
  4889. Argc--;
  4890. }
  4891. status = DnssrvEnumDirectoryPartitions(
  4892. pwszServerName,
  4893. dwfilter,
  4894. &pdpList );
  4895. if ( status != ERROR_SUCCESS )
  4896. {
  4897. printf(
  4898. "Directory partition enumeration failed\n"
  4899. " status = %d (0x%08lx)\n",
  4900. status, status );
  4901. goto Cleanup;
  4902. }
  4903. else
  4904. {
  4905. DnsPrint_RpcDpList(
  4906. dnscmd_PrintRoutine,
  4907. dnscmd_PrintContext,
  4908. "Enumerated directory partition list:\n",
  4909. pdpList );
  4910. }
  4911. Cleanup:
  4912. //
  4913. // deallocate zone list
  4914. //
  4915. DnssrvFreeDirectoryPartitionList( pdpList );
  4916. return status;
  4917. Help:
  4918. printf( "Usage: DnsCmd <ServerName> /EnumDirectoryPartitions [/Custom]\n" );
  4919. return ERROR_INVALID_PARAMETER;
  4920. } // ProcessEnumDirectoryPartitions
  4921. DNS_STATUS
  4922. ProcessDirectoryPartitionInfo(
  4923. IN DWORD Argc,
  4924. IN LPSTR * Argv,
  4925. IN LPWSTR * UnicodeArgv
  4926. )
  4927. {
  4928. DNS_STATUS status = ERROR_SUCCESS;
  4929. PDNS_RPC_DP_INFO pDpInfo = NULL;
  4930. BOOL bdetail = FALSE;
  4931. LPSTR pszfqdn;
  4932. LPSTR pszcmd;
  4933. //
  4934. // Command format: /DirectoryPartitionInfo fqdn [/Detail]
  4935. //
  4936. // Currently no arguments.
  4937. //
  4938. if ( Argc <= 0 || Argc > 2 || Argc == NEED_HELP_ARGC )
  4939. {
  4940. goto Help;
  4941. }
  4942. pszfqdn = *Argv;
  4943. Argv++;
  4944. Argc--;
  4945. if ( Argc == 1 )
  4946. {
  4947. pszcmd = getCommandName( *Argv );
  4948. if ( pszcmd && _stricmp( pszcmd, "Detail" ) == 0 )
  4949. {
  4950. bdetail = TRUE;
  4951. }
  4952. Argv++;
  4953. Argc--;
  4954. }
  4955. status = DnssrvDirectoryPartitionInfo(
  4956. pwszServerName,
  4957. pszfqdn,
  4958. &pDpInfo );
  4959. if ( status != ERROR_SUCCESS )
  4960. {
  4961. printf(
  4962. "Directory partition info query failed\n"
  4963. " status = %d (0x%08lx)\n",
  4964. status, status );
  4965. goto Cleanup;
  4966. }
  4967. else
  4968. {
  4969. DnsPrint_RpcDpInfo(
  4970. dnscmd_PrintRoutine,
  4971. dnscmd_PrintContext,
  4972. "Directory partition info:",
  4973. pDpInfo,
  4974. !bdetail );
  4975. }
  4976. Cleanup:
  4977. DnssrvFreeDirectoryPartitionInfo( pDpInfo );
  4978. return status;
  4979. Help:
  4980. printf( "Usage: DnsCmd <ServerName> /DirectoryPartitionInfo <FQDN of partition> [/Detail]\n" );
  4981. return ERROR_INVALID_PARAMETER;
  4982. } // ProcessDirectoryPartitionInfo
  4983. DNS_STATUS
  4984. ProcessCreateDirectoryPartition(
  4985. IN DWORD Argc,
  4986. IN LPSTR * Argv,
  4987. IN LPWSTR * UnicodeArgv
  4988. )
  4989. {
  4990. DNS_STATUS status = ERROR_SUCCESS;
  4991. PSTR pszDpFqdn;
  4992. PWSTR pwszDpFqdn;
  4993. //
  4994. // Command format: /CreateDirectoryPartition DP-FQDN [/Create]
  4995. //
  4996. if ( Argc != 1 )
  4997. {
  4998. goto Help;
  4999. }
  5000. pszDpFqdn = Argv[ 0 ];
  5001. //
  5002. // Make sure FQDN argument is not a command switch.
  5003. //
  5004. if ( !pszDpFqdn || pszDpFqdn[ 0 ] == '/' )
  5005. {
  5006. return ERROR_INVALID_PARAMETER;
  5007. }
  5008. //
  5009. // Perform the operation.
  5010. //
  5011. status = DnssrvEnlistDirectoryPartition(
  5012. pwszServerName,
  5013. DNS_DP_OP_CREATE,
  5014. pszDpFqdn );
  5015. pwszDpFqdn = getUnicodeForUtf8( pszDpFqdn );
  5016. if ( status == ERROR_SUCCESS )
  5017. {
  5018. printf(
  5019. "DNS Server %S created directory partition: %S\n",
  5020. pwszServerName,
  5021. pwszDpFqdn );
  5022. }
  5023. else
  5024. {
  5025. wprintf(
  5026. L"Create directory partition failed: %s\n"
  5027. L" status = %d (0x%08lx)\n",
  5028. pwszDpFqdn,
  5029. status, status );
  5030. }
  5031. FREE_HEAP( pwszDpFqdn );
  5032. return status;
  5033. Help:
  5034. printf( "Usage: DnsCmd <ServerName> /CreateDirectoryPartition <FQDN of partition>\n" );
  5035. return ERROR_INVALID_PARAMETER;
  5036. } // ProcessCreateDirectoryPartition
  5037. DNS_STATUS
  5038. ProcessDeleteDirectoryPartition(
  5039. IN DWORD Argc,
  5040. IN LPSTR * Argv,
  5041. IN LPWSTR * UnicodeArgv
  5042. )
  5043. {
  5044. DNS_STATUS status = ERROR_SUCCESS;
  5045. LPSTR pszDpFqdn;
  5046. LPWSTR pwszDpFqdn;
  5047. //
  5048. // Command format: /DeleteDirectoryPartition DP-FQDN [/Create]
  5049. //
  5050. if ( Argc != 1 )
  5051. {
  5052. goto Help;
  5053. }
  5054. pszDpFqdn = Argv[ 0 ];
  5055. pwszDpFqdn = UnicodeArgv[ 0 ];
  5056. status = DnssrvEnlistDirectoryPartition(
  5057. pwszServerName,
  5058. DNS_DP_OP_DELETE,
  5059. pszDpFqdn );
  5060. if ( status == ERROR_SUCCESS )
  5061. {
  5062. printf(
  5063. "DNS Server %S deleted directory partition: %S\n",
  5064. pwszServerName,
  5065. pwszDpFqdn );
  5066. }
  5067. else
  5068. {
  5069. printf(
  5070. "Delete directory partition failed: %S\n"
  5071. " status = %d (0x%08lx)\n",
  5072. pwszDpFqdn,
  5073. status, status );
  5074. }
  5075. return status;
  5076. Help:
  5077. printf( "Usage: DnsCmd <ServerName> /DeleteDirectoryPartition <FQDN of partition>\n" );
  5078. return ERROR_INVALID_PARAMETER;
  5079. } // ProcessDeleteDirectoryPartition
  5080. DNS_STATUS
  5081. ProcessEnlistDirectoryPartition(
  5082. IN DWORD Argc,
  5083. IN LPSTR * Argv,
  5084. IN LPWSTR * UnicodeArgv
  5085. )
  5086. {
  5087. DNS_STATUS status = ERROR_SUCCESS;
  5088. LPSTR pszDpFqdn;
  5089. LPWSTR pwszDpFqdn;
  5090. //
  5091. // Command format: /EnlistDirectoryPartition DP-FQDN [/Create]
  5092. //
  5093. if ( Argc != 1 )
  5094. {
  5095. goto Help;
  5096. }
  5097. pszDpFqdn = Argv[ 0 ];
  5098. pwszDpFqdn = UnicodeArgv[ 0 ];
  5099. status = DnssrvEnlistDirectoryPartition(
  5100. pwszServerName,
  5101. DNS_DP_OP_ENLIST,
  5102. pszDpFqdn );
  5103. if ( status == ERROR_SUCCESS )
  5104. {
  5105. printf(
  5106. "DNS Server %S enlisted directory partition: %S\n",
  5107. pwszServerName,
  5108. pwszDpFqdn );
  5109. }
  5110. else
  5111. {
  5112. printf(
  5113. "Enlist directory partition failed: %S\n"
  5114. " status = %d (0x%08lX)\n",
  5115. pwszDpFqdn,
  5116. status, status );
  5117. }
  5118. return status;
  5119. Help:
  5120. printf( "Usage: DnsCmd <ServerName> /EnlistDirectoryPartition <FQDN of partition>\n" );
  5121. return ERROR_INVALID_PARAMETER;
  5122. } // ProcessEnlistDirectoryPartition
  5123. DNS_STATUS
  5124. ProcessUnenlistDirectoryPartition(
  5125. IN DWORD Argc,
  5126. IN LPSTR * Argv,
  5127. IN LPWSTR * UnicodeArgv
  5128. )
  5129. {
  5130. DNS_STATUS status = ERROR_SUCCESS;
  5131. LPSTR pszDpFqdn;
  5132. LPWSTR pwszDpFqdn;
  5133. //
  5134. // Command format: /UnenlistDirectoryPartition DP-FQDN [/Create]
  5135. //
  5136. if ( Argc != 1 )
  5137. {
  5138. goto Help;
  5139. }
  5140. pszDpFqdn = Argv[ 0 ];
  5141. pwszDpFqdn = UnicodeArgv[ 0 ];
  5142. status = DnssrvEnlistDirectoryPartition(
  5143. pwszServerName,
  5144. DNS_DP_OP_UNENLIST,
  5145. pszDpFqdn );
  5146. if ( status == ERROR_SUCCESS )
  5147. {
  5148. printf(
  5149. "DNS Server %S unenlisted directory partition: %S\n",
  5150. pwszServerName,
  5151. pwszDpFqdn );
  5152. }
  5153. else
  5154. {
  5155. printf(
  5156. "Unenlist directory partition failed: %S\n"
  5157. " status = %d (0x%08lX)\n",
  5158. pwszDpFqdn,
  5159. status, status );
  5160. }
  5161. return status;
  5162. Help:
  5163. printf( "Usage: DnsCmd <ServerName> /UnenlistDirectoryPartition <FQDN of partition>\n" );
  5164. return ERROR_INVALID_PARAMETER;
  5165. } // ProcessUnenlistDirectoryPartition
  5166. DNS_STATUS
  5167. ProcessCreateBuiltinDirectoryPartitions(
  5168. IN DWORD Argc,
  5169. IN LPSTR * Argv,
  5170. IN LPWSTR * UnicodeArgv
  5171. )
  5172. {
  5173. DNS_STATUS status = ERROR_SUCCESS;
  5174. DWORD dwopcode = 0xFFFFFFFF;
  5175. PCHAR psz;
  5176. //
  5177. // Command format: /CreateBuiltinDPs [/Domain | /Forest | /AllDomains]
  5178. //
  5179. // /Domain - create domain DP
  5180. // /Forest - create forest DP
  5181. // /AllDomains - create domain DPs for all domains in forest
  5182. //
  5183. if ( Argc != 1 || Argc == NEED_HELP_ARGC )
  5184. {
  5185. goto Help;
  5186. }
  5187. if ( ( psz = getCommandName( Argv[ 0 ] ) ) != NULL )
  5188. {
  5189. if ( _strnicmp( psz, "All", 3 ) == 0 )
  5190. {
  5191. dwopcode = DNS_DP_OP_CREATE_ALL_DOMAINS;
  5192. }
  5193. else if ( _strnicmp( psz, "For", 3 ) == 0 )
  5194. {
  5195. dwopcode = DNS_DP_OP_CREATE_FOREST;
  5196. }
  5197. else if ( _strnicmp( psz, "Dom", 3 ) == 0 )
  5198. {
  5199. dwopcode = DNS_DP_OP_CREATE_DOMAIN;
  5200. }
  5201. else
  5202. {
  5203. goto Help;
  5204. }
  5205. }
  5206. status = DnssrvEnlistDirectoryPartition(
  5207. pwszServerName,
  5208. dwopcode,
  5209. NULL );
  5210. if ( status == ERROR_SUCCESS )
  5211. {
  5212. printf(
  5213. "DNS Server %S completed operation successfully\n",
  5214. pwszServerName );
  5215. }
  5216. else
  5217. {
  5218. printf(
  5219. "Create built-in directory partitions failed\n"
  5220. " status = %d (0x%08lx)\n",
  5221. status, status );
  5222. }
  5223. return status;
  5224. Help:
  5225. printf(
  5226. "Usage: DnsCmd <ServerName> /CreateBuiltinDirectoryPartitions <Option>\n"
  5227. " Option must be one of:\n"
  5228. " /Domain -- Creates the built-in domain-wide DNS directory partition for\n"
  5229. " the Active Directory domain where the DNS server specified by\n"
  5230. " ServerName is located.\n"
  5231. " /Forest -- Creates the built-in forest-wide DNS directory partition for\n"
  5232. " the Active Directory forest where the DNS server specified by\n"
  5233. " ServerName is located.\n"
  5234. " /AllDomains -- Creates the built-in domain-wide DNS directory partitions\n"
  5235. " on a DNS server in each domain in the Active Directory forest where\n"
  5236. " the user running this command is logged on. The ServerName argument\n"
  5237. " is ignored for this operation.\n" );
  5238. return ERROR_INVALID_PARAMETER;
  5239. } // ProcessCreateBuiltinDirectoryPartitions
  5240. //
  5241. // Command table
  5242. // Have this down here so no need for private protos on dispatch functions.
  5243. //
  5244. // DEVNOTE: all this needs internationalization
  5245. //
  5246. COMMAND_INFO GlobalCommandInfo[] =
  5247. {
  5248. // Zone + Server operations
  5249. // Server and Zone Operations
  5250. { "/Info",
  5251. ProcessInfo,
  5252. "Get server information"
  5253. },
  5254. { "/Config",
  5255. ProcessResetProperty,
  5256. "Reset server or zone configuration"
  5257. },
  5258. { "/EnumZones",
  5259. ProcessEnumZones,
  5260. "Enumerate zones"
  5261. },
  5262. // Server Operations
  5263. { "/Statistics",
  5264. ProcessStatistics,
  5265. "Query/clear server statistics data"
  5266. },
  5267. { "/ClearCache",
  5268. ProcessSimpleServerOperation,
  5269. "Clear DNS server cache"
  5270. },
  5271. { "/WriteBackFiles",
  5272. ProcessWriteBackFiles,
  5273. "Write back all zone or root-hint datafile(s)"
  5274. },
  5275. { "/StartScavenging",
  5276. ProcessSimpleServerOperation,
  5277. "Initiates server scavenging"
  5278. },
  5279. // Server Property Reset
  5280. { "/ResetListenAddresses",
  5281. ProcessResetListenAddresses,
  5282. "Set server IP address(es) to serve DNS requests"
  5283. },
  5284. { "/ResetForwarders",
  5285. ProcessResetForwarders,
  5286. "Set DNS servers to forward recursive queries to"
  5287. },
  5288. // Zone Operations
  5289. { "/ZoneInfo",
  5290. ProcessZoneInfo,
  5291. "View zone information"
  5292. },
  5293. { "/ZoneAdd",
  5294. ProcessZoneAdd,
  5295. "Create a new zone on the DNS server"
  5296. },
  5297. { "/ZoneDelete",
  5298. ProcessZoneDelete,
  5299. "Delete a zone from DNS server or DS"
  5300. },
  5301. { "/ZonePause",
  5302. ProcessZonePause,
  5303. "Pause a zone"
  5304. },
  5305. { "/ZoneResume",
  5306. ProcessZoneResume,
  5307. "Resume a zone"
  5308. },
  5309. { "/ZoneReload",
  5310. ProcessZoneReload,
  5311. "Reload zone from its database (file or DS)"
  5312. },
  5313. { "/ZoneWriteBack",
  5314. ProcessZoneWriteBack,
  5315. "Write back zone to file"
  5316. },
  5317. { "/ZoneRefresh",
  5318. ProcessZoneRefresh,
  5319. "Force refresh of secondary zone from master"
  5320. },
  5321. { "/ZoneUpdateFromDs",
  5322. ProcessZoneUpdateFromDs,
  5323. "Update a DS integrated zone by data from DS"
  5324. },
  5325. { "/ZonePrint",
  5326. ProcessDisplayAllZoneRecords,
  5327. "Display all records in the zone"
  5328. },
  5329. // Zone Property Reset
  5330. { "/ZoneResetType",
  5331. ProcessZoneResetType,
  5332. "Change zone type"
  5333. },
  5334. { "/ZoneResetSecondaries",
  5335. ProcessZoneResetSecondaries,
  5336. "Reset secondary\\notify information for a zone"
  5337. },
  5338. { "/ZoneResetScavengeServers",
  5339. ProcessZoneResetScavengeServers,
  5340. "Reset scavenging servers for a zone"
  5341. },
  5342. { "/ZoneResetMasters",
  5343. ProcessZoneResetMasters,
  5344. "Reset secondary zone's master servers"
  5345. },
  5346. #if 0
  5347. { "/ZoneRename",
  5348. ProcessZoneRename,
  5349. "Rename a zone"
  5350. },
  5351. #endif
  5352. { "/ZoneExport",
  5353. ProcessZoneExport,
  5354. "Export a zone to file"
  5355. },
  5356. #if 0
  5357. { "/ZoneResetAging",
  5358. ProcessZoneResetAging,
  5359. "Reset aging\scavenging information for a zone"
  5360. },
  5361. #endif
  5362. { "/ZoneChangeDirectoryPartition",
  5363. ProcessZoneChangeDirectoryPartition,
  5364. "Move a zone to another directory partition"
  5365. },
  5366. // Record Operations
  5367. { "/EnumRecords",
  5368. ProcessEnumRecords,
  5369. "Enumerate records at a name"
  5370. },
  5371. { "/RecordAdd",
  5372. ProcessRecordAdd,
  5373. "Create a record in zone or RootHints"
  5374. },
  5375. { "/RecordDelete",
  5376. ProcessRecordDelete,
  5377. "Delete a record from zone, RootHints or cache"
  5378. },
  5379. { "/NodeDelete",
  5380. ProcessNodeDelete,
  5381. "Delete all records at a name"
  5382. },
  5383. { "/AgeAllRecords",
  5384. ProcessAgeAllRecords,
  5385. "Force aging on node(s) in zone"
  5386. },
  5387. // Directory partitions
  5388. {
  5389. "/EnumDirectoryPartitions",
  5390. ProcessEnumDirectoryPartitions,
  5391. "Enumerate directory partitions"
  5392. },
  5393. {
  5394. "/DirectoryPartitionInfo",
  5395. ProcessDirectoryPartitionInfo,
  5396. "Get info on a directory partition"
  5397. },
  5398. {
  5399. "/CreateDirectoryPartition",
  5400. ProcessCreateDirectoryPartition,
  5401. "Create a directory partition"
  5402. },
  5403. {
  5404. "/DeleteDirectoryPartition",
  5405. ProcessDeleteDirectoryPartition,
  5406. "Delete a directory partition"
  5407. },
  5408. {
  5409. "/EnlistDirectoryPartition",
  5410. ProcessEnlistDirectoryPartition,
  5411. "Add DNS server to partition replication scope"
  5412. },
  5413. {
  5414. "/UnenlistDirectoryPartition",
  5415. ProcessUnenlistDirectoryPartition,
  5416. "Remove DNS server from replication scope"
  5417. },
  5418. { "/CreateBuiltinDirectoryPartitions",
  5419. ProcessCreateBuiltinDirectoryPartitions,
  5420. "Create built-in partitions"
  5421. },
  5422. // END displayed commands
  5423. // commands below here are duplicate names of above or
  5424. // hidden commands
  5425. { "***StopDisplayMarker***",
  5426. NULL,
  5427. NULL
  5428. },
  5429. // Hidden
  5430. { "/Restart",
  5431. ProcessSimpleServerOperation,
  5432. "Restart DNS server"
  5433. },
  5434. { "/" DNSSRV_OP_AUTO_CONFIGURE,
  5435. ProcessAutoConfigure,
  5436. "Prime root hints, forwarder, and point resolver at local server"
  5437. },
  5438. // Debug only
  5439. { "/DebugBreak",
  5440. ProcessSimpleServerOperation,
  5441. "Server debug break (internal)"
  5442. },
  5443. { "/ClearDebugLog",
  5444. ProcessSimpleServerOperation,
  5445. "Clear server debug log (internal)"
  5446. },
  5447. { "/RootBreak",
  5448. ProcessSimpleServerOperation,
  5449. "Root break (internal)"
  5450. },
  5451. // Duplicate command names
  5452. { "/ResetRegistry",
  5453. ProcessResetProperty,
  5454. "Reset server or zone configuration"
  5455. },
  5456. { "/ZoneResetNotify",
  5457. ProcessZoneResetSecondaries,
  5458. "Reset secondary\notify information for a zone"
  5459. },
  5460. { "/DeleteNode",
  5461. ProcessNodeDelete,
  5462. "Delete all records at a name"
  5463. },
  5464. { "/WriteBackFiles",
  5465. ProcessWriteBackFiles,
  5466. "Write back all zone or root-hint datafiles"
  5467. },
  5468. // SAM test
  5469. { "/SbsRegister",
  5470. ProcessSbsRegister,
  5471. "SBS Registration"
  5472. },
  5473. { "/SbsDeleteRecord",
  5474. ProcessSbsDeleteRecord,
  5475. "SBS Record Delete"
  5476. },
  5477. // Directory partitions
  5478. { "/EnumDPs",
  5479. ProcessEnumDirectoryPartitions,
  5480. "Enumerate directory partitions"
  5481. },
  5482. {
  5483. "/DPInfo",
  5484. ProcessDirectoryPartitionInfo,
  5485. "Get info on a directory partition"
  5486. },
  5487. {
  5488. "/CreateDP",
  5489. ProcessCreateDirectoryPartition,
  5490. "Create a directory partition"
  5491. },
  5492. {
  5493. "/DeleteDP",
  5494. ProcessDeleteDirectoryPartition,
  5495. "Delete a directory partition"
  5496. },
  5497. {
  5498. "/EnlistDP",
  5499. ProcessEnlistDirectoryPartition,
  5500. "Add DNS server to partition replication scope"
  5501. },
  5502. {
  5503. "/UnenlistDP",
  5504. ProcessUnenlistDirectoryPartition,
  5505. "Remove DNS server from replication scope"
  5506. },
  5507. { "/ZoneChangeDP",
  5508. ProcessZoneChangeDirectoryPartition,
  5509. "Move zone to another directory partition"
  5510. },
  5511. { "/CreateBuiltinDirectoryPartitions",
  5512. ProcessCreateBuiltinDirectoryPartitions,
  5513. "Create built-in partitions using admin's credentials"
  5514. },
  5515. { "/CreateBuiltinDPs",
  5516. ProcessCreateBuiltinDirectoryPartitions,
  5517. "Create built-in partitions using admin's credentials"
  5518. },
  5519. { NULL, NULL, "" },
  5520. };
  5521. //
  5522. // End dnscmd.c
  5523. //