Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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