mirror of https://github.com/tongzx/nt5src
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
6567 lines
151 KiB
/*++
|
|
|
|
Copyright (c) 1995-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
DnsCmd.c
|
|
|
|
Abstract:
|
|
|
|
Command line management for DNS Server.
|
|
|
|
Author:
|
|
|
|
Jim Gilroy (jamesg) September 1995
|
|
|
|
Revision History:
|
|
|
|
Jing Chen (t-jingc) June 1998
|
|
Jim Gilroy (jamesg) September 1998 cleanup
|
|
|
|
--*/
|
|
|
|
|
|
#include "dnsclip.h"
|
|
#include "dnsc_wmi.h"
|
|
|
|
#include <string.h> // strtoul()
|
|
#include <time.h>
|
|
|
|
|
|
#define DNSCMD_UNICODE 1 // unicode argv interface
|
|
|
|
|
|
//
|
|
// Static IP array counts
|
|
// values beyond any reasonable value anyone would send
|
|
//
|
|
|
|
#define MAX_IP_PROPERTY_COUNT (200)
|
|
|
|
|
|
//
|
|
// Globals -- allow these to be viewable in processing functions
|
|
//
|
|
|
|
LPSTR pszServerName = NULL;
|
|
LPWSTR pwszServerName = NULL;
|
|
|
|
LPSTR pszCommandName = NULL;
|
|
|
|
extern DWORD g_dwViewFlag;
|
|
|
|
BOOL g_UseWmi = FALSE;
|
|
|
|
|
|
//
|
|
// Printing
|
|
//
|
|
|
|
#define dnscmd_PrintRoutine ((PRINT_ROUTINE) fprintf)
|
|
|
|
#define dnscmd_PrintContext ((PPRINT_CONTEXT) stdout)
|
|
|
|
|
|
//
|
|
// Command table setup
|
|
//
|
|
|
|
typedef DNS_STATUS (* COMMAND_FUNCTION)( DWORD argc, CHAR** argv);
|
|
|
|
typedef struct _COMMAND_INFO
|
|
{
|
|
LPSTR pszCommandName;
|
|
COMMAND_FUNCTION pCommandFunction;
|
|
LPSTR pComments;
|
|
}
|
|
COMMAND_INFO, *LPCOMMAND_INFO;
|
|
|
|
//
|
|
// Command table
|
|
//
|
|
|
|
extern COMMAND_INFO GlobalCommandInfo[];
|
|
|
|
//
|
|
// Dummy Argc to command function to indicate help requested
|
|
//
|
|
|
|
#define NEED_HELP_ARGC (MAXDWORD)
|
|
|
|
|
|
|
|
//
|
|
// Private utilites
|
|
//
|
|
|
|
COMMAND_FUNCTION
|
|
getCommandFunction(
|
|
IN LPSTR pszCommandName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get function corresponding to command name.
|
|
|
|
Arguments:
|
|
|
|
pszCommandName -- command string
|
|
|
|
Return Value:
|
|
|
|
Ptr to command function corresponding to command name.
|
|
NULL if unrecognized command.
|
|
|
|
--*/
|
|
{
|
|
DWORD i;
|
|
|
|
//
|
|
// find command in list matching string
|
|
//
|
|
|
|
i = 0;
|
|
while( GlobalCommandInfo[i].pszCommandName )
|
|
{
|
|
if( _stricmp(
|
|
pszCommandName,
|
|
GlobalCommandInfo[i].pszCommandName ) == 0 )
|
|
{
|
|
return( GlobalCommandInfo[i].pCommandFunction );
|
|
}
|
|
i++;
|
|
}
|
|
return( NULL );
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
printCommands(
|
|
VOID
|
|
)
|
|
{
|
|
DWORD i = 0;
|
|
|
|
//
|
|
// display commands
|
|
// but stop display at "command barrier" (NULL function)
|
|
// commands below are duplicates or hidden
|
|
//
|
|
|
|
while( GlobalCommandInfo[i].pszCommandName &&
|
|
GlobalCommandInfo[i].pCommandFunction )
|
|
{
|
|
printf( " %-26s -- %s\n",
|
|
GlobalCommandInfo[i].pszCommandName,
|
|
GlobalCommandInfo[i].pComments );
|
|
i++;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
LPSTR
|
|
getCommandName(
|
|
IN LPSTR pszCmd
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get command name.
|
|
|
|
Remove "/" from begining of command.
|
|
|
|
Arguments:
|
|
|
|
pszCmd -- command string
|
|
|
|
Return Value:
|
|
|
|
Ptr to command string (with no leading "/")
|
|
NULL if not a command.
|
|
|
|
--*/
|
|
{
|
|
if ( pszCmd && ( pszCmd[ 0 ] == '/' || pszCmd[ 0 ] == '-' ) )
|
|
{
|
|
return pszCmd + 1;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
getUserConfirmation(
|
|
IN LPSTR pszString
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get user's confirmation on a command.
|
|
|
|
Arguments:
|
|
|
|
pszString -- configmation string
|
|
|
|
Return Value:
|
|
|
|
TRUE if confirmed.
|
|
FALSE if cancelled.
|
|
|
|
--*/
|
|
{
|
|
int ch;
|
|
|
|
printf( "Are you sure you want to %s? (y/n) ", pszString );
|
|
|
|
if ( ( (ch=getchar()) != EOF ) &&
|
|
( (ch == 'y') || (ch == 'Y') ) )
|
|
{
|
|
printf("\n");
|
|
return( TRUE );
|
|
}
|
|
else
|
|
{
|
|
printf("\nCommand cancelled!\n");
|
|
return( FALSE );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
convertDwordParameterUnknownBase(
|
|
IN LPSTR pszParam
|
|
)
|
|
{
|
|
INT base = 10;
|
|
|
|
if ( *pszParam > '9' || (*pszParam == '0' && *(pszParam+1) > '9') )
|
|
{
|
|
// hex conversion
|
|
base = 16;
|
|
}
|
|
return strtoul(
|
|
pszParam,
|
|
NULL,
|
|
base );
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
readIpAddressArray(
|
|
OUT PIP_ADDRESS pAddrArray,
|
|
IN DWORD ArraySize,
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv,
|
|
IN BOOL fInaddrNoneAllowed
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read IP array.
|
|
|
|
Arguments:
|
|
|
|
pIpArray -- IP array buffer
|
|
|
|
ArraySize -- IPs array can handle
|
|
|
|
Argc -- remaining Argc
|
|
|
|
Argv -- remaining Argv
|
|
|
|
fInaddrNoneAllowed -- if TRUE, 255.255.255.255 is a valid input
|
|
|
|
Return Value:
|
|
|
|
Count of IP in array.
|
|
|
|
--*/
|
|
{
|
|
DWORD count = 0;
|
|
IP_ADDRESS ip;
|
|
|
|
while ( Argc && count < ArraySize )
|
|
{
|
|
ip = inet_addr( Argv[0] );
|
|
|
|
//
|
|
// Allow INADDR_NONE if that address really was specified
|
|
// and it is allowed as a valid input.
|
|
//
|
|
|
|
if ( ip == INADDR_NONE &&
|
|
( !fInaddrNoneAllowed ||
|
|
strcmp( Argv[ 0 ], "255.255.255.255" ) != 0 ) )
|
|
{
|
|
break;
|
|
}
|
|
|
|
pAddrArray[ count ] = ip;
|
|
count++;
|
|
|
|
Argc--;
|
|
Argv++;
|
|
}
|
|
|
|
return( count );
|
|
}
|
|
|
|
|
|
|
|
INT
|
|
ReadArgsIntoDnsTypeArray(
|
|
OUT PWORD pTypeArray,
|
|
IN INT ArraySize,
|
|
IN INT Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read list of DNS type strings into a WORD array, one type value
|
|
per word. The DNS types can be in numeric form or alpha form.
|
|
e.g. "6" or "SOA"
|
|
|
|
If the types are in alpha form, type strings that cannot be interpreted
|
|
are not added to the array.
|
|
|
|
DEVNOTE: This is for setting the NoRoundRobin type list, which I have
|
|
not yet implemented via RPC.
|
|
|
|
Arguments:
|
|
|
|
pIpArray -- IP array buffer
|
|
|
|
ArraySize -- IPs array can handle
|
|
|
|
Argc -- number of arguments
|
|
|
|
Argv -- pointer to arguments
|
|
|
|
Return Value:
|
|
|
|
Number of types successfully processed into array.
|
|
|
|
--*/
|
|
{
|
|
INT typeIdx;
|
|
|
|
for ( typeIdx = 0; Argc && typeIdx < ArraySize; --Argc, ++Argv )
|
|
{
|
|
if ( isdigit( *Argv[ 0 ] ) )
|
|
{
|
|
pTypeArray[ typeIdx++ ] = ( WORD ) atoi( *Argv );
|
|
}
|
|
else
|
|
{
|
|
WORD wType;
|
|
|
|
wType = Dns_RecordTypeForName(
|
|
*Argv,
|
|
0 ); // null-terminated
|
|
if ( wType != 0 )
|
|
{
|
|
pTypeArray[ typeIdx++ ] = wType;
|
|
}
|
|
}
|
|
}
|
|
|
|
return typeIdx;
|
|
} // ReadArgsIntoDnsTypeArray
|
|
|
|
|
|
|
|
DWORD
|
|
parseZoneTypeString(
|
|
IN LPSTR pszZoneType,
|
|
OUT BOOL * pfDsIntegrated
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get command name.
|
|
|
|
Remove "/" from beggining of command.
|
|
NULL if error (no "/")
|
|
|
|
Arguments:
|
|
|
|
pszZoneType -- zone type string, e.g. "Secondary" or "2"
|
|
|
|
pfDsIntegrated -- does type indicate zone should be DS integrated?
|
|
|
|
Return Value:
|
|
|
|
DNS_ZONE_TYPE_XXX constant matching zone type or -1 if the type
|
|
cannot be matched.
|
|
|
|
--*/
|
|
{
|
|
DWORD zoneType = -1;
|
|
|
|
ASSERT( pfDsIntegrated && pszZoneType );
|
|
|
|
*pfDsIntegrated = FALSE;
|
|
|
|
if ( *pszZoneType == '//' )
|
|
{
|
|
++pszZoneType;
|
|
}
|
|
|
|
if ( !_stricmp( pszZoneType, "Primary" ) ||
|
|
!_stricmp( pszZoneType, "1" ) )
|
|
{
|
|
zoneType = DNS_ZONE_TYPE_PRIMARY;
|
|
}
|
|
else if ( !_stricmp( pszZoneType, "DsPrimary" ) )
|
|
{
|
|
zoneType = DNS_ZONE_TYPE_PRIMARY;
|
|
*pfDsIntegrated = TRUE;
|
|
}
|
|
else if ( !_stricmp( pszZoneType, "Secondary" ) ||
|
|
!_stricmp( pszZoneType, "2" ) )
|
|
{
|
|
zoneType = DNS_ZONE_TYPE_SECONDARY;
|
|
}
|
|
else if ( !_stricmp( pszZoneType, "Stub" ) ||
|
|
!_stricmp( pszZoneType, "3" ) )
|
|
{
|
|
zoneType = DNS_ZONE_TYPE_STUB;
|
|
}
|
|
else if ( !_stricmp( pszZoneType, "DsStub" ) )
|
|
{
|
|
zoneType = DNS_ZONE_TYPE_STUB;
|
|
*pfDsIntegrated = TRUE;
|
|
}
|
|
else if ( !_stricmp( pszZoneType, "Forwarder" ) ||
|
|
!_stricmp( pszZoneType, "4" ) )
|
|
{
|
|
zoneType = DNS_ZONE_TYPE_FORWARDER;
|
|
}
|
|
else if ( !_stricmp( pszZoneType, "DsForwarder" ) )
|
|
{
|
|
zoneType = DNS_ZONE_TYPE_FORWARDER;
|
|
*pfDsIntegrated = TRUE;
|
|
}
|
|
|
|
return zoneType;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
parseDpSpecifier(
|
|
IN LPSTR pszDpName,
|
|
OUT DWORD * pdwDpFlag, OPTIONAL
|
|
OUT LPSTR * ppszCustomDpName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Parses a directory partition name. Valid specifiers:
|
|
|
|
/DomainDefault
|
|
/ForestDefault
|
|
/Legacy
|
|
|
|
Anything that does not start with "/" is assumed to be the
|
|
name of a custom DP.
|
|
|
|
If pdwDpFlag is non-NULL, then for a built-in partition
|
|
ppszCustomDpName will be NULL and the appropriate DWORD flag
|
|
value will be set at pdwDpFlag. If pdwDpFlag is NULL, then
|
|
for built-in partitions ppszCustomDpName will be pointed to
|
|
a static string such as DNS_DP_LEGACY_STR.
|
|
|
|
Arguments:
|
|
|
|
pszDpName - name to be parsed - must be NULL-terminated
|
|
|
|
pdwDpFlag - flag if DP is builtin, zero if custom
|
|
|
|
ppszCustomDpName - set to ptr within pszDpName for customer
|
|
|
|
Return Value:
|
|
|
|
FALSE if the specifier does not appear to be valid (e.g. is empty).
|
|
|
|
--*/
|
|
{
|
|
BOOL rc = TRUE;
|
|
|
|
static const LPSTR pszStaticLegacy = DNS_DP_LEGACY_STR;
|
|
static const LPSTR pszStaticDomain = DNS_DP_DOMAIN_STR;
|
|
static const LPSTR pszStaticForest = DNS_DP_FOREST_STR;
|
|
|
|
if ( !ppszCustomDpName || !pszDpName || !*pszDpName )
|
|
{
|
|
rc = FALSE;
|
|
}
|
|
else
|
|
{
|
|
if ( pdwDpFlag )
|
|
{
|
|
*pdwDpFlag = 0;
|
|
}
|
|
*ppszCustomDpName = NULL;
|
|
|
|
if ( *pszDpName == '/' || strncmp( pszDpName, "..", 2 ) == 0 )
|
|
{
|
|
// Skip over preamble character(s).
|
|
++pszDpName;
|
|
if ( *pszDpName == '.' )
|
|
{
|
|
++pszDpName;
|
|
}
|
|
|
|
if ( toupper( *pszDpName ) == 'F' )
|
|
{
|
|
if ( pdwDpFlag )
|
|
*pdwDpFlag |= DNS_DP_FOREST_DEFAULT;
|
|
else
|
|
*ppszCustomDpName = pszStaticForest;
|
|
}
|
|
else if ( toupper( *pszDpName ) == 'D' )
|
|
{
|
|
if ( pdwDpFlag )
|
|
*pdwDpFlag |= DNS_DP_DOMAIN_DEFAULT;
|
|
else
|
|
*ppszCustomDpName = pszStaticDomain;
|
|
|
|
}
|
|
else if ( toupper( *pszDpName ) == 'L' )
|
|
{
|
|
if ( pdwDpFlag )
|
|
*pdwDpFlag |= DNS_DP_LEGACY;
|
|
else
|
|
*ppszCustomDpName = pszStaticLegacy;
|
|
}
|
|
else
|
|
{
|
|
rc = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*ppszCustomDpName = pszDpName;
|
|
}
|
|
}
|
|
return rc;
|
|
} // parseDpSpecifier
|
|
|
|
|
|
|
|
DWORD
|
|
readIpArray(
|
|
OUT PIP_ARRAY pIpArray,
|
|
IN DWORD ArraySize,
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read IP array.
|
|
|
|
Wrapper around readIpAddressArray, to build IP_ARRAY structure.
|
|
|
|
Arguments:
|
|
|
|
pIpArray -- IP array to write into
|
|
|
|
ArraySize -- IPs array can handle
|
|
|
|
Argc -- remaining Argc
|
|
|
|
Argv -- remaining Argv
|
|
|
|
Return Value:
|
|
|
|
Count of IP in array.
|
|
|
|
--*/
|
|
{
|
|
DWORD count;
|
|
|
|
count = readIpAddressArray(
|
|
pIpArray->AddrArray,
|
|
ArraySize,
|
|
Argc,
|
|
Argv,
|
|
FALSE );
|
|
|
|
pIpArray->AddrCount = count;
|
|
|
|
return( count );
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
readZoneAndDomainName(
|
|
IN LPSTR * Argv,
|
|
OUT LPSTR * ppZoneName,
|
|
OUT LPSTR * ppNodeName,
|
|
OUT PBOOL pbAllocatedNode,
|
|
OUT LPSTR * ppZoneArg, OPTIONAL
|
|
OUT LPSTR * ppNodeArg OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Read zone and domain name.
|
|
Build node FQDN if required.
|
|
|
|
Arguments:
|
|
|
|
Argv -- argv with zone and node names
|
|
|
|
ppZoneName -- addr to receive ptr to zone name
|
|
|
|
ppNodeName -- addr to receive ptr to node name
|
|
|
|
pbAllocatedNode -- ptr to bool set TRUE if allocate node name
|
|
|
|
ppZoneArg -- addr to receive ptr to zone argument
|
|
|
|
ppNodeArg -- addr to receive ptr to node argument
|
|
|
|
Return Value:
|
|
|
|
TRUE -- if in authoritative zone
|
|
FALSE -- if cache or root hints
|
|
|
|
--*/
|
|
{
|
|
LPSTR pzoneName;
|
|
LPSTR pnodeName;
|
|
LPSTR pzoneArg;
|
|
LPSTR pnodeArg;
|
|
BOOL ballocated = FALSE;
|
|
BOOL bauthZone = TRUE;
|
|
|
|
//
|
|
// read zone name
|
|
// - special case RootHints and Cache
|
|
// setting zone to special string
|
|
//
|
|
|
|
pzoneName = pzoneArg = *Argv;
|
|
if ( *pzoneArg == '/' )
|
|
{
|
|
if ( _stricmp( pzoneArg, "/RootHints" ) == 0 )
|
|
{
|
|
pzoneName = DNS_ZONE_ROOT_HINTS;
|
|
bauthZone = FALSE;
|
|
}
|
|
else if ( _stricmp( pzoneArg, "/Cache" ) == 0 )
|
|
{
|
|
pzoneName = DNS_ZONE_CACHE;
|
|
bauthZone = FALSE;
|
|
}
|
|
}
|
|
else if ( *pzoneArg == '.' )
|
|
{
|
|
if ( _stricmp( pzoneArg, "..RootHints" ) == 0 )
|
|
{
|
|
pzoneName = DNS_ZONE_ROOT_HINTS;
|
|
bauthZone = FALSE;
|
|
}
|
|
else if ( _stricmp( pzoneArg, "..Cache" ) == 0 )
|
|
{
|
|
pzoneName = DNS_ZONE_CACHE;
|
|
bauthZone = FALSE;
|
|
}
|
|
}
|
|
Argv++;
|
|
|
|
//
|
|
// Node name
|
|
// - for zones, accept file format and append zone name
|
|
// - root hints or cache must be FQDN
|
|
//
|
|
|
|
pnodeArg = *Argv;
|
|
|
|
if ( bauthZone )
|
|
{
|
|
if ( strcmp( pnodeArg, "@" ) == 0 )
|
|
{
|
|
pnodeName = pzoneName;
|
|
}
|
|
else if ( Dns_IsNameFQDN( pnodeArg ) )
|
|
{
|
|
// input pnodeName is FQDN, with a trailing dot
|
|
pnodeName = pnodeArg;
|
|
}
|
|
else
|
|
{
|
|
//append zone name to the end of pnodeName
|
|
pnodeName = malloc( 2 + strlen(pzoneName) + strlen(pnodeArg) );
|
|
if ( pnodeName )
|
|
{
|
|
strcpy ( pnodeName, pnodeArg );
|
|
strcat ( pnodeName, "." );
|
|
strcat ( pnodeName, pzoneName );
|
|
ballocated = TRUE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pnodeName = *Argv;
|
|
}
|
|
|
|
//
|
|
// set out params
|
|
//
|
|
|
|
if ( ppZoneName )
|
|
{
|
|
*ppZoneName = pzoneName;
|
|
}
|
|
if ( ppNodeName )
|
|
{
|
|
*ppNodeName = pnodeName;
|
|
}
|
|
if ( pbAllocatedNode )
|
|
{
|
|
*pbAllocatedNode = ballocated;
|
|
}
|
|
if ( ppZoneArg )
|
|
{
|
|
*ppZoneArg = pzoneArg;
|
|
}
|
|
if ( ppNodeArg )
|
|
{
|
|
*ppNodeArg = pnodeArg;
|
|
}
|
|
|
|
return( bauthZone );
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
getServerVersion(
|
|
IN LPWSTR pwszServerName,
|
|
IN BOOL fPrintVersion,
|
|
OUT PDWORD pdwMajorVersion, OPTIONAL
|
|
OUT PDWORD pdwMinorVersion, OPTIONAL
|
|
OUT PDWORD pdwBuildNum OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Query server for version information.
|
|
|
|
Arguments:
|
|
|
|
pwszServerName -- name of DNS server
|
|
fPrintVersion -- if TRUE this function will print one-line server version
|
|
pdwMajorVersion -- ptr to DWORD to receive major version or NULL
|
|
pdwMinorVersion -- ptr to DWORD to receive minor version or NULL
|
|
pdwBuildNum -- ptr to DWORD to receive build number or NULL
|
|
|
|
Return Value:
|
|
|
|
Status code.
|
|
--*/
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
DWORD dataType;
|
|
PDNS_RPC_SERVER_INFO pServerInfo = NULL;
|
|
DWORD dwMajorVersion = 0;
|
|
DWORD dwMinorVersion = 0;
|
|
DWORD dwBuildNum = 0;
|
|
|
|
//
|
|
// Retrieve server info.
|
|
//
|
|
|
|
status = DnssrvQuery(
|
|
pwszServerName,
|
|
NULL, // zone
|
|
DNSSRV_QUERY_SERVER_INFO,
|
|
&dataType,
|
|
&pServerInfo );
|
|
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
goto Done;
|
|
}
|
|
|
|
if ( !pServerInfo || dataType != DNSSRV_TYPEID_SERVER_INFO )
|
|
{
|
|
status = ERROR_NOT_FOUND;
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Parse version.
|
|
//
|
|
|
|
dwMajorVersion = pServerInfo->dwVersion & 0x000000FF;
|
|
dwMinorVersion = ( pServerInfo->dwVersion & 0x0000FF00 ) >> 8;
|
|
dwBuildNum = pServerInfo->dwVersion >>16;
|
|
|
|
//
|
|
// Optionally print version.
|
|
//
|
|
|
|
if ( fPrintVersion )
|
|
{
|
|
printf( "DNS server %S version is %d.%d.%d\n",
|
|
pwszServerName,
|
|
dwMajorVersion,
|
|
dwMinorVersion,
|
|
dwBuildNum );
|
|
}
|
|
|
|
//
|
|
// Store version numbers to output destinations.
|
|
//
|
|
|
|
Done:
|
|
|
|
if ( pdwMajorVersion )
|
|
{
|
|
*pdwMajorVersion = dwMajorVersion;
|
|
}
|
|
if ( pdwMinorVersion )
|
|
{
|
|
*pdwMinorVersion = dwMinorVersion;
|
|
}
|
|
if ( pdwBuildNum )
|
|
{
|
|
*pdwBuildNum = dwBuildNum;
|
|
}
|
|
|
|
return status;
|
|
} // getServerVersion
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
processCacheSizeQuery(
|
|
LPWSTR pwszServerName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Query server and print current cache usage.
|
|
|
|
Arguments:
|
|
|
|
pwszServerName -- name of DNS server
|
|
|
|
Return Value:
|
|
|
|
Status code.
|
|
--*/
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
PDNS_RPC_BUFFER pStatBuff = NULL;
|
|
PDNSSRV_MEMORY_STATS pMemStats = NULL;
|
|
PDNSSRV_STAT pStat;
|
|
PCHAR pch;
|
|
PCHAR pchstop;
|
|
|
|
//
|
|
// Print server version
|
|
//
|
|
|
|
getServerVersion(
|
|
pwszServerName,
|
|
TRUE,
|
|
NULL, NULL, NULL );
|
|
|
|
//
|
|
// Retrieve statistics from server.
|
|
//
|
|
|
|
status = DnssrvGetStatistics(
|
|
pwszServerName,
|
|
DNSSRV_STATID_MEMORY,
|
|
&pStatBuff );
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
goto Done;
|
|
}
|
|
if ( !pStatBuff )
|
|
{
|
|
printf( "Error: statistics buffer missing\n" );
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Loop through returned stats to find memory stats.
|
|
//
|
|
|
|
pch = pStatBuff->Buffer;
|
|
pchstop = pch + pStatBuff->dwLength;
|
|
while ( pch < pchstop )
|
|
{
|
|
pStat = ( PDNSSRV_STAT ) pch;
|
|
pch = ( PCHAR ) GET_NEXT_STAT_IN_BUFFER( pStat );
|
|
if ( pch > pchstop )
|
|
{
|
|
printf( "Error: invalid stats buffer\n" );
|
|
goto Done;
|
|
}
|
|
|
|
// printf( "Found stat ID %08X\n", pStat->Header.StatId );
|
|
|
|
if ( pStat->Header.StatId == DNSSRV_STATID_MEMORY )
|
|
{
|
|
pMemStats = ( PDNSSRV_MEMORY_STATS ) pStat;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( pMemStats == NULL )
|
|
{
|
|
printf( "Error: unable to retrieve memory statistics\n" );
|
|
status = ERROR_NOT_SUPPORTED;
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// Print results.
|
|
//
|
|
|
|
printf( "Cache usage for server %S is %d bytes:\n"
|
|
" Nodes: %d (%d bytes)\n"
|
|
" RRs: %d (%d bytes)\n",
|
|
pwszServerName,
|
|
pMemStats->MemTags[ MEMTAG_NODE_CACHE ].Memory +
|
|
pMemStats->MemTags[ MEMTAG_RECORD_CACHE ].Memory,
|
|
pMemStats->MemTags[ MEMTAG_NODE_CACHE ].Alloc -
|
|
pMemStats->MemTags[ MEMTAG_NODE_CACHE ].Free,
|
|
pMemStats->MemTags[ MEMTAG_NODE_CACHE ].Memory,
|
|
pMemStats->MemTags[ MEMTAG_RECORD_CACHE ].Alloc -
|
|
pMemStats->MemTags[ MEMTAG_RECORD_CACHE ].Free,
|
|
pMemStats->MemTags[ MEMTAG_RECORD_CACHE ].Memory);
|
|
|
|
Done:
|
|
|
|
return status;
|
|
} // processCacheSizeQuery
|
|
|
|
|
|
//
|
|
// Prototypes for forward references.
|
|
//
|
|
|
|
DNS_STATUS
|
|
ProcessDisplayAllZoneRecords(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
);
|
|
|
|
|
|
|
|
//
|
|
// DnsCmd entry point
|
|
//
|
|
|
|
#if DNSCMD_UNICODE
|
|
INT __cdecl
|
|
wmain(
|
|
IN int argc,
|
|
IN PWSTR * Argv
|
|
)
|
|
#else
|
|
INT __cdecl
|
|
main(
|
|
IN int argc,
|
|
IN char ** argv
|
|
)
|
|
#endif
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
DnsCmd program entry point.
|
|
|
|
Executes specified command corresponding to a DNS Server API
|
|
call, using the specified server name.
|
|
|
|
Arguments:
|
|
|
|
argc -- arg count
|
|
|
|
argv -- argument list
|
|
argv[1] -- DNS ServerName
|
|
argv[2] -- Command to execute
|
|
argv[3...] -- arguments to command
|
|
|
|
Return Value:
|
|
|
|
Return from the desired command. Usually a pass through of the return
|
|
code from DNS API call.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
COMMAND_FUNCTION pcommandFunc;
|
|
DWORD commandArgc;
|
|
LPSTR * commandArgv;
|
|
LPSTR parg1;
|
|
WSADATA wsadata;
|
|
|
|
#ifdef DNSCMD_UNICODE
|
|
char ** argv = NULL;
|
|
int i;
|
|
#endif
|
|
|
|
//
|
|
// initialize debug
|
|
//
|
|
|
|
DnssrvInitializeDebug();
|
|
|
|
//
|
|
// Initialize Winsock in case we want to call any Winsock functions.
|
|
//
|
|
|
|
WSAStartup( MAKEWORD( 2, 0 ), &wsadata );
|
|
|
|
#if DNSCMD_UNICODE
|
|
|
|
//
|
|
// Convert Unicode arguments to UTF8.
|
|
//
|
|
|
|
argv = ALLOCATE_HEAP( ( argc + 1 ) * sizeof( PCHAR ) );
|
|
|
|
for ( i = 0; i < argc; ++i )
|
|
{
|
|
argv[ i ] = Dns_NameCopyAllocate(
|
|
( PCHAR ) Argv[ i ],
|
|
0, // no given length (use strlen)
|
|
DnsCharSetUnicode,
|
|
DnsCharSetUtf8 );
|
|
}
|
|
argv[ i ] = NULL;
|
|
#endif
|
|
|
|
//
|
|
// DnsCmd <ServerName> [/WMI] <Command> [<Command Parameters>]
|
|
//
|
|
// Skip EXE name parameter.
|
|
//
|
|
|
|
if ( argc < 2 )
|
|
{
|
|
goto Help;
|
|
}
|
|
--argc;
|
|
++argv;
|
|
|
|
//
|
|
// DNS server IP address/name parameter
|
|
//
|
|
|
|
pszServerName = argv[ 0 ];
|
|
if ( *pszServerName == '/' )
|
|
{
|
|
pszServerName = ".";
|
|
}
|
|
else
|
|
{
|
|
argc--;
|
|
argv++;
|
|
}
|
|
|
|
pwszServerName = Dns_NameCopyAllocate(
|
|
pszServerName,
|
|
0, // no given length (use strlen)
|
|
DnsCharSetUtf8,
|
|
DnsCharSetUnicode );
|
|
|
|
//
|
|
// Check for optional WMI parameter.
|
|
//
|
|
|
|
if ( argc && argv[ 0 ] && _stricmp( argv[ 0 ], "/WMI" ) == 0 )
|
|
{
|
|
g_UseWmi = TRUE;
|
|
--argc;
|
|
++argv;
|
|
if ( argc < 1 )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
status = DnscmdWmi_Initialize( pwszServerName );
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"Fatal error 0x%08X during WMI initialization to server \"%S\"\n",
|
|
status,
|
|
pwszServerName );
|
|
goto Done;
|
|
}
|
|
printf(
|
|
"Opened WMI connection to server \"%S\"\n\n",
|
|
pwszServerName );
|
|
}
|
|
|
|
//
|
|
// next parameter is command name, retrieve associated function
|
|
//
|
|
|
|
if ( argc == 0 )
|
|
{
|
|
status = ERROR_SUCCESS;
|
|
goto Help;
|
|
}
|
|
pszCommandName = argv[0];
|
|
pcommandFunc = getCommandFunction( pszCommandName );
|
|
if( !pcommandFunc )
|
|
{
|
|
if ( _stricmp( pszCommandName, "/?" ) == 0 ||
|
|
_stricmp( pszCommandName, "/help" ) == 0 )
|
|
{
|
|
status = ERROR_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
status = ERROR_INVALID_PARAMETER;
|
|
printf(
|
|
"Unknown Command \"%s\" Specified -- type DnsCmd -?.\n",
|
|
pszCommandName );
|
|
}
|
|
goto Help;
|
|
}
|
|
|
|
//
|
|
// set argc, argv for rest of parameters
|
|
//
|
|
|
|
commandArgc = (DWORD)(argc - 1);
|
|
commandArgv = &argv[1];
|
|
|
|
//
|
|
// test for help request on specific command
|
|
// - if found, dispatch with Argc=0, to force help
|
|
//
|
|
|
|
if ( commandArgc > 0 )
|
|
{
|
|
parg1 = commandArgv[0];
|
|
if ( *parg1 == '?' ||
|
|
_stricmp( parg1, "/?" ) == 0 ||
|
|
_stricmp( parg1, "/help" ) == 0 )
|
|
{
|
|
commandArgc = NEED_HELP_ARGC;
|
|
}
|
|
}
|
|
|
|
//
|
|
// dispatch to processor for this command
|
|
//
|
|
|
|
status = pcommandFunc( commandArgc, commandArgv );
|
|
|
|
Dns_EndDebug();
|
|
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
printf( "\nCommand failed: %s %ld (%08lx)\n",
|
|
Dns_StatusString( status ),
|
|
status, status );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Do not output success message for commands where the output
|
|
// may be piped to file for a specific use (e.g. zone file output).
|
|
|
|
if ( pcommandFunc != ProcessDisplayAllZoneRecords )
|
|
{
|
|
printf( "Command completed successfully.\n" );
|
|
}
|
|
}
|
|
|
|
|
|
goto Done;
|
|
|
|
//
|
|
// Output help text.
|
|
//
|
|
|
|
Help:
|
|
|
|
printf(
|
|
"\nUsage: DnsCmd <ServerName> <Command> [<Command Parameters>]\n\n"
|
|
"<ServerName>:\n"
|
|
" . -- local machine using LPC\n"
|
|
" IP address -- RPC over TCP/IP\n"
|
|
" DNS name -- RPC over TCP/IP\n"
|
|
" other server name -- RPC over named pipes\n\n"
|
|
"<Command>:\n" );
|
|
|
|
printCommands();
|
|
|
|
printf(
|
|
"\n<Command Parameters>:\n"
|
|
" DnsCmd <CommandName> /? -- For help info on specific Command\n" );
|
|
|
|
//
|
|
// Cleanup and return.
|
|
//
|
|
|
|
Done:
|
|
|
|
if ( g_UseWmi )
|
|
{
|
|
DnscmdWmi_Free();
|
|
}
|
|
|
|
WSACleanup();
|
|
|
|
return( status );
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
// Command Functions
|
|
//
|
|
|
|
|
|
//
|
|
// Info Query -- for Server or Zone
|
|
//
|
|
|
|
DNS_STATUS
|
|
ProcessInfo(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
DWORD typeid;
|
|
PVOID pdata;
|
|
LPCSTR pszQueryName;
|
|
|
|
//
|
|
// /Info [<PropertyName>]
|
|
//
|
|
// get specific property to query -- if given
|
|
// if not specific query, default to ZONE_INFO
|
|
//
|
|
|
|
if ( Argc == 0 )
|
|
{
|
|
pszQueryName = DNSSRV_QUERY_SERVER_INFO;
|
|
}
|
|
else if ( Argc == 1 )
|
|
{
|
|
//
|
|
// Allow property name to be bare or preceded by command char.
|
|
//
|
|
|
|
pszQueryName = getCommandName( Argv[0] );
|
|
if ( !pszQueryName )
|
|
{
|
|
pszQueryName = Argv[ 0 ];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
//
|
|
// Handle meta-queries: queries that involve client-side parsing
|
|
//
|
|
|
|
if ( _stricmp( pszQueryName, "CacheSize" ) == 0 )
|
|
{
|
|
status = processCacheSizeQuery( pwszServerName );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// query, print result on success
|
|
//
|
|
|
|
if ( g_UseWmi )
|
|
{
|
|
status = DnscmdWmi_ProcessDnssrvQuery(
|
|
NULL, // zone
|
|
pszQueryName );
|
|
}
|
|
else
|
|
{
|
|
status = DnssrvQuery(
|
|
pwszServerName,
|
|
NULL, // no zone
|
|
pszQueryName, // query name
|
|
& typeid,
|
|
& pdata );
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf( "Query result:\n" );
|
|
DnsPrint_RpcUnion(
|
|
dnscmd_PrintRoutine,
|
|
dnscmd_PrintContext,
|
|
NULL,
|
|
typeid,
|
|
pdata );
|
|
}
|
|
}
|
|
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"Info query failed.\n"
|
|
" Status = %d (0x%08lx)\n",
|
|
status, status );
|
|
}
|
|
}
|
|
|
|
return( status );
|
|
|
|
Help:
|
|
printf(
|
|
"Usage: DnsCmd <Server> /Info [<Property>]\n"
|
|
" <Property> -- server property to view\n"
|
|
" Examples:\n"
|
|
" BootMethod\n"
|
|
" RpcProtocol\n"
|
|
" LogLevel\n"
|
|
" EventlogLevel\n"
|
|
" NoRecursion\n"
|
|
" ForwardDelegations\n"
|
|
" ForwardingTimeout\n"
|
|
" IsSlave\n"
|
|
" SecureResponses\n"
|
|
" RecursionRetry\n"
|
|
" RecursionTimeout\n"
|
|
" " DNS_REGKEY_ADDITIONAL_RECURSION_TIMEOUT "\n"
|
|
" MaxCacheTtl\n"
|
|
" MaxNegativeCacheTtl\n"
|
|
" RoundRobin\n"
|
|
" LocalNetPriority\n"
|
|
" AddressAnswerLimit\n"
|
|
" BindSecondaries\n"
|
|
" WriteAuthorityNs\n"
|
|
" NameCheckFlag\n"
|
|
" StrictFileParsing\n"
|
|
" UpdateOptions\n"
|
|
" DisableAutoReverseZones\n"
|
|
" SendPort\n"
|
|
" NoTcp\n"
|
|
" XfrConnectTimeout\n"
|
|
" DsPollingInterval\n"
|
|
" ScavengingInterval\n"
|
|
" DefaultAgingState\n"
|
|
" DefaultNoRefreshInterval\n"
|
|
" DefaultRefreshInterval\n"
|
|
);
|
|
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
ProcessZoneInfo(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
DWORD typeid;
|
|
PVOID pdata;
|
|
LPCSTR pqueryName;
|
|
|
|
//
|
|
// /ZoneInfo <ZoneName> [<PropertyName>]
|
|
//
|
|
// get specific query -- if given
|
|
// if not specific query, default to ZONE_INFO
|
|
//
|
|
|
|
if ( Argc == 1 )
|
|
{
|
|
pqueryName = DNSSRV_QUERY_ZONE_INFO;
|
|
}
|
|
else if ( Argc == 2 )
|
|
{
|
|
pqueryName = getCommandName( Argv[1] );
|
|
if ( !pqueryName )
|
|
{
|
|
pqueryName = Argv[1];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
//
|
|
// query, print result on success
|
|
//
|
|
|
|
if ( g_UseWmi )
|
|
{
|
|
status = DnscmdWmi_ProcessZoneInfo(
|
|
Argv[ 0 ] );
|
|
}
|
|
else
|
|
{
|
|
status = DnssrvQuery(
|
|
pwszServerName,
|
|
Argv[0], // zone name
|
|
pqueryName, // query name
|
|
&typeid,
|
|
&pdata );
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf( "Zone query result:\n" );
|
|
DnsPrint_RpcUnion(
|
|
dnscmd_PrintRoutine,
|
|
dnscmd_PrintContext,
|
|
NULL,
|
|
typeid,
|
|
pdata );
|
|
}
|
|
else
|
|
{
|
|
printf(
|
|
"Zone Info query failed.\n"
|
|
" Status = %d (0x%08lx)\n",
|
|
status, status );
|
|
}
|
|
}
|
|
return( status );
|
|
|
|
Help:
|
|
printf(
|
|
"Usage: DnsCmd <Server> /ZoneInfo <ZoneName> [<Property>]\n"
|
|
" <Property> -- zone property to view\n"
|
|
" Examples:\n"
|
|
" AllowUpdate\n"
|
|
" DsIntegrated\n"
|
|
" Aging\n"
|
|
" RefreshInterval\n"
|
|
" NoRefreshInterval\n" );
|
|
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Simple server operations
|
|
//
|
|
|
|
DNS_STATUS
|
|
ProcessSimpleServerOperation(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
LPSTR cmd;
|
|
|
|
//
|
|
// <Simple Server Command> no parameters
|
|
// Commands:
|
|
// - DebugBreak
|
|
// - ClearDebugLog
|
|
// - Restart
|
|
// - DisplayCache
|
|
// - Reload
|
|
//
|
|
|
|
if ( Argc != 0 )
|
|
{
|
|
printf( "Usage: DnsCmd <ServerName> /%s\n", pszCommandName );
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
if ( g_UseWmi )
|
|
{
|
|
status = DnscmdWmi_ProcessDnssrvOperation(
|
|
NULL,
|
|
getCommandName( pszCommandName ),
|
|
DNSSRV_TYPEID_NULL,
|
|
( PVOID ) NULL );
|
|
}
|
|
else
|
|
{
|
|
status = DnssrvOperation(
|
|
pwszServerName,
|
|
NULL,
|
|
getCommandName( pszCommandName ),
|
|
DNSSRV_TYPEID_NULL,
|
|
NULL );
|
|
}
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"%s completed successfully.\n",
|
|
pszServerName );
|
|
}
|
|
else
|
|
{
|
|
printf(
|
|
"%s failed: status = %d (0x%08lx).\n",
|
|
pszServerName,
|
|
status, status );
|
|
}
|
|
return( status );
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
ProcessStatistics(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
DWORD statid = DNSSRV_STATID_ALL; // default to all
|
|
PDNS_RPC_BUFFER pstatsBuf = NULL;
|
|
LPSTR cmd;
|
|
|
|
//
|
|
// Statistics [/<StatId> | /Clear]
|
|
//
|
|
|
|
if ( Argc > 1 )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
//
|
|
// if command -- execute command
|
|
// /Clear is only supported command
|
|
//
|
|
//
|
|
|
|
cmd = getCommandName( Argv[0] );
|
|
if ( cmd )
|
|
{
|
|
if ( !_stricmp(cmd, "Clear" ) )
|
|
{
|
|
status = DnssrvOperation(
|
|
pwszServerName,
|
|
NULL,
|
|
"ClearStatistics",
|
|
DNSSRV_TYPEID_NULL,
|
|
NULL );
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf("DNS Server %S statistics cleared.\n", pwszServerName );
|
|
}
|
|
return( status );
|
|
}
|
|
goto Help;
|
|
}
|
|
|
|
//
|
|
// view statistics
|
|
// - if specific statid given, read it
|
|
|
|
if ( Argc > 0 )
|
|
{
|
|
statid = strtoul(
|
|
Argv[0],
|
|
NULL,
|
|
16 );
|
|
if ( statid == 0 )
|
|
{
|
|
statid = (-1);
|
|
}
|
|
}
|
|
|
|
if ( g_UseWmi )
|
|
{
|
|
status = DnscmdWmi_GetStatistics(
|
|
statid );
|
|
}
|
|
else
|
|
{
|
|
status = DnssrvGetStatistics(
|
|
pwszServerName,
|
|
statid,
|
|
& pstatsBuf );
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf( "DNS Server %S statistics:\n", pwszServerName );
|
|
DnsPrint_RpcStatsBuffer(
|
|
dnscmd_PrintRoutine,
|
|
dnscmd_PrintContext,
|
|
NULL,
|
|
pstatsBuf );
|
|
}
|
|
}
|
|
|
|
return( status );
|
|
|
|
Help:
|
|
printf(
|
|
"Usage: DnsCmd <ServerName> /Statistics [/<StatId> | /Clear]\n"
|
|
" <StatId> -- ID of particular stat desired. (ALL is the default)\n"
|
|
" %08lx -- Time \n"
|
|
" %08lx -- Query \n"
|
|
" %08lx -- Query2 \n"
|
|
" %08lx -- Recurse \n"
|
|
" %08lx -- Master \n"
|
|
" %08lx -- Secondary \n"
|
|
" %08lx -- Wins \n"
|
|
" %08lx -- Wire Update\n"
|
|
" %08lx -- Internal Update\n"
|
|
" %08lx -- SkwanSec \n"
|
|
" %08lx -- Ds \n"
|
|
" %08lx -- Memory \n"
|
|
" %08lx -- PacketMem \n"
|
|
" %08lx -- Dbase \n"
|
|
" %08lx -- Records \n"
|
|
" Deprecated stats:\n"
|
|
" %08lx -- Memory-NT5 \n"
|
|
" %08lx -- NbstatMem \n"
|
|
" /Clear -- clear statistics data\n",
|
|
DNSSRV_STATID_TIME,
|
|
DNSSRV_STATID_QUERY,
|
|
DNSSRV_STATID_QUERY2,
|
|
DNSSRV_STATID_RECURSE,
|
|
DNSSRV_STATID_MASTER,
|
|
DNSSRV_STATID_SECONDARY,
|
|
DNSSRV_STATID_WINS,
|
|
DNSSRV_STATID_WIRE_UPDATE,
|
|
DNSSRV_STATID_NONWIRE_UPDATE,
|
|
DNSSRV_STATID_MEMORY,
|
|
DNSSRV_STATID_SKWANSEC,
|
|
DNSSRV_STATID_DS,
|
|
DNSSRV_STATID_PACKET,
|
|
DNSSRV_STATID_DBASE,
|
|
DNSSRV_STATID_RECORD,
|
|
|
|
DNSSRV_STATID_MEMORY,
|
|
DNSSRV_STATID_NBSTAT
|
|
);
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
//
|
|
// Update server data file(s)
|
|
// for one zone, when <zonename> specified
|
|
// all files: no <zonename> specified
|
|
//
|
|
|
|
DNS_STATUS
|
|
ProcessWriteBackFiles(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
LPSTR zonename = NULL;
|
|
LPSTR cmd;
|
|
|
|
//
|
|
// WriteBackFiles [ZoneName]
|
|
//
|
|
|
|
if ( Argc > 1 )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
if ( Argc == 0 )
|
|
{
|
|
cmd = "WriteDirtyZones";
|
|
}
|
|
else
|
|
{
|
|
zonename = Argv[0];
|
|
cmd = "WriteBackFile";
|
|
}
|
|
|
|
status = DnssrvOperation(
|
|
pwszServerName, //server
|
|
zonename, //zone
|
|
cmd, //cmd
|
|
DNSSRV_TYPEID_NULL,
|
|
(PVOID) NULL );
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"Sever data file(s) updated. \n"
|
|
);
|
|
}
|
|
return( status );
|
|
|
|
Help:
|
|
|
|
printf(
|
|
"Usage: DnsCmd <ServerName> /WriteBackFiles [<ZoneName>]\n"
|
|
" <ZoneName> -- FQDN of a zone whose datafile to be written back\n"
|
|
" Default: write back datafile for all dirty zones\n"
|
|
);
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
#if 0
|
|
|
|
//
|
|
// Server query
|
|
//
|
|
|
|
DNS_STATUS
|
|
ProcessQueryServer(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
DWORD typeid;
|
|
PVOID pdata;
|
|
|
|
//
|
|
// QueryServer <QueryName>
|
|
//
|
|
|
|
if ( Argc != 1 )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
status = DnssrvQuery(
|
|
pwszServerName,
|
|
NULL,
|
|
Argv[0],
|
|
& typeid,
|
|
& pdata );
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"Server %s query result:\n",
|
|
Argv[0]
|
|
);
|
|
DnsPrint_RpcUnion(
|
|
dnscmd_PrintRoutine,
|
|
dnscmd_PrintContext,
|
|
NULL,
|
|
typeid,
|
|
pdata );
|
|
}
|
|
else
|
|
{
|
|
printf(
|
|
"QueryServer failed.\n"
|
|
" Status = %d (0x%08lx)\n",
|
|
status, status );
|
|
}
|
|
return( status );
|
|
|
|
Help:
|
|
printf(
|
|
"Usage: DnsCmd <Server> QueryServer <PropertyName>\n"
|
|
" <PropertyName> examples:\n"
|
|
" ServerInfo\n"
|
|
" Statistics\n"
|
|
" BootMethod\n"
|
|
" ListenAddresses\n"
|
|
" SendPort\n"
|
|
" RpcProtocol\n"
|
|
" NoRecursion\n"
|
|
" RecursionRetry\n"
|
|
" RecursionTimeout\n"
|
|
" " DNS_REGKEY_ADDITIONAL_RECURSION_TIMEOUT "\n"
|
|
" Forwarders\n"
|
|
" ForwardingTimeout\n"
|
|
" IsSlave\n"
|
|
" MaxCacheTtl\n"
|
|
" MaxNegativeCacheTtl\n"
|
|
" DisableAutoReverseZones\n"
|
|
" CleanupInterval\n"
|
|
" AllowUpdate\n"
|
|
" RoundRobin\n"
|
|
" AddressAnswerLimit\n"
|
|
" BindSecondaries\n"
|
|
" WriteAuthority\n"
|
|
" StrictFileParsing\n"
|
|
);
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
DWORD
|
|
ReadIPAddr(LPSTR ipAddrStr)
|
|
{
|
|
DWORD ipaddr=0;
|
|
int n,count=0,base=1;
|
|
|
|
while(count<4)
|
|
{
|
|
n = strtoul(ipAddrStr,&ipAddrStr,10);
|
|
if( (n>255) || ((count<3) && (ipAddrStr[0]!='.')) ) return(-1);
|
|
else ipAddrStr++;
|
|
ipaddr += base*n;
|
|
base*=256;
|
|
count++;
|
|
}
|
|
return(ipaddr);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
ProcessRecordAdd(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
PDNS_RECORD prr;
|
|
PDNS_RPC_RECORD prrRpc;
|
|
LPSTR pzoneName;
|
|
LPSTR pnodeName;
|
|
BOOL ballocatedNode;
|
|
LPSTR pzoneArg;
|
|
WORD wType;
|
|
DWORD ttl = 0;
|
|
DWORD ttlFlag = 0;
|
|
CHAR buf[33];
|
|
DWORD baging = 0;
|
|
DWORD bopenAcl = 0;
|
|
|
|
|
|
//
|
|
// RecordAdd <Zone> <Node> [/AgeOn | /AgeOff] [/AdminAcl] [<TTL>] <RRType> <RRData>
|
|
//
|
|
|
|
if ( Argc < 4 || Argc == NEED_HELP_ARGC )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
//
|
|
// read zone and domain name
|
|
//
|
|
|
|
readZoneAndDomainName(
|
|
Argv,
|
|
& pzoneName,
|
|
& pnodeName,
|
|
& ballocatedNode,
|
|
& pzoneArg,
|
|
NULL );
|
|
|
|
Argv++;
|
|
Argc--;
|
|
Argv++;
|
|
Argc--;
|
|
|
|
//
|
|
// Aging ON\OFF
|
|
//
|
|
|
|
if ( Argc )
|
|
{
|
|
if ( _stricmp( *Argv, "/Aging" ) == 0 ||
|
|
_stricmp( *Argv, "/AgeOn" ) == 0 )
|
|
{
|
|
baging = 1;
|
|
Argv++;
|
|
Argc--;
|
|
}
|
|
#if 0
|
|
else if ( _stricmp( *Argv, "/AgeOff" ) == 0 )
|
|
{
|
|
baging = 0;
|
|
Argv++;
|
|
Argc--;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if ( Argc && _stricmp( *Argv, "/OpenAcl" ) == 0 )
|
|
{
|
|
bopenAcl = TRUE;
|
|
Argv++;
|
|
Argc--;
|
|
}
|
|
|
|
//
|
|
// TTL -- optional
|
|
// - use default if none given
|
|
//
|
|
|
|
ttl = strtoul(
|
|
*Argv,
|
|
NULL,
|
|
10 );
|
|
|
|
if ( ttl == 0 && strcmp(*Argv, "0") != 0 )
|
|
{
|
|
ttlFlag = DNS_RPC_RECORD_FLAG_DEFAULT_TTL;
|
|
}
|
|
else // read TTL
|
|
{
|
|
Argv++;
|
|
Argc--;
|
|
if ( Argc < 1 )
|
|
{
|
|
goto Help;
|
|
}
|
|
}
|
|
|
|
//
|
|
// record type
|
|
//
|
|
|
|
wType = Dns_RecordTypeForName( *Argv, 0 );
|
|
if ( !wType )
|
|
{
|
|
printf( "Invalid RRType: <%s>!\n", *Argv );
|
|
goto Help;
|
|
}
|
|
Argv++;
|
|
Argc--;
|
|
|
|
//
|
|
// build DNS_RECORD
|
|
// - if no record data, then type delete
|
|
// - otherwise build record
|
|
//
|
|
|
|
if ( !Argc )
|
|
{
|
|
prrRpc = ALLOCATE_HEAP( SIZEOF_DNS_RPC_RECORD_HEADER );
|
|
if ( !prrRpc )
|
|
{
|
|
printf( "Not enough memory!\n" );
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
prrRpc->wDataLength = 0;
|
|
prrRpc->wType = wType;
|
|
}
|
|
|
|
else
|
|
{
|
|
prr = Dns_RecordBuild_A(
|
|
NULL, // ptr to RRSet
|
|
pnodeName, // nameOwner
|
|
wType, // RR type in WORD
|
|
FALSE, // ! S.Delete
|
|
0, // S.section
|
|
Argc, // count of strings
|
|
Argv // strings to fill into RR
|
|
);
|
|
if ( ! prr )
|
|
{
|
|
printf( "\nInvalid Data!\n" );
|
|
goto Help;
|
|
}
|
|
|
|
// convert DNS_RECORD to RPC buffer
|
|
|
|
prrRpc = DnsConvertRecordToRpcBuffer( prr );
|
|
if ( ! prrRpc )
|
|
{
|
|
#if DBG
|
|
printf("DnsConvertRecordToRpcBuffer() failed\n");
|
|
#endif
|
|
status = GetLastError();
|
|
goto Help;
|
|
}
|
|
// prr and prrRpc freed by process termination
|
|
}
|
|
|
|
//
|
|
// set TTL and flags for the RR
|
|
//
|
|
|
|
prrRpc->dwTtlSeconds = ttl;
|
|
prrRpc->dwFlags = ttlFlag;
|
|
|
|
if ( baging )
|
|
{
|
|
prrRpc->dwFlags |= DNS_RPC_RECORD_FLAG_AGING_ON;
|
|
}
|
|
if ( bopenAcl )
|
|
{
|
|
prrRpc->dwFlags |= DNS_RPC_FLAG_OPEN_ACL;
|
|
}
|
|
|
|
if ( g_UseWmi )
|
|
{
|
|
status = DnscmdWmi_ProcessRecordAdd(
|
|
pzoneName,
|
|
pnodeName,
|
|
prrRpc,
|
|
Argc,
|
|
Argv );
|
|
}
|
|
else
|
|
{
|
|
status = DnssrvUpdateRecord(
|
|
pwszServerName, // server
|
|
pzoneName, // zone
|
|
pnodeName, // node
|
|
prrRpc, // RR to add
|
|
NULL );
|
|
}
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"Add %s Record for %s at %s\n",
|
|
*(Argv - 1), // RR type
|
|
pnodeName, // owner name
|
|
pzoneArg ); // zone name
|
|
}
|
|
|
|
// free node name if allocated
|
|
|
|
if ( ballocatedNode )
|
|
{
|
|
free( pnodeName );
|
|
}
|
|
|
|
return( status );
|
|
|
|
Help:
|
|
printf(
|
|
"Usage: DnsCmd <ServerName> /RecordAdd <Zone> <NodeName> [/Aging] [/OpenAcl]\n"
|
|
" [<Ttl>] <RRType> <RRData>\n\n"
|
|
" <RRType> <RRData>\n"
|
|
" A <IPAddress>\n"
|
|
" NS,CNAME,MB,MD <HostName|DomainName>\n"
|
|
" PTR,MF,MG,MR <HostName|DomainName>\n"
|
|
" MX,RT,AFSDB <Preference> <ServerName>\n"
|
|
" SRV <Priority> <Weight> <Port> <HostName>\n"
|
|
" SOA <PrimaryServer> <AdminEmail> <Serial#>\n"
|
|
" <Refresh> <Retry> <Expire> <MinTTL>\n"
|
|
" AAAA <Ipv6Address>\n"
|
|
" TXT <String> [<String>]\n"
|
|
" X25,HINFO,ISDN <String> [<String>]\n"
|
|
" MINFO,RP <MailboxName> <ErrMailboxName>\n"
|
|
" WKS <Protocol> <IPAddress> <Service> [<Service>]..]\n"
|
|
" KEY <Flags> <KeyProtocol> <CryptoAlgorithm> <Base64Data>\n"
|
|
" SIG <TypeCovered> <CryptoAlgorithm> <LabelCount>\n"
|
|
" <OriginalTTL> <SigExpiration> <SigInception>\n"
|
|
" <KeyTag> <Signer's Name> <Base64Data>\n"
|
|
" NXT <NextName> <Type> [<Type>...]\n"
|
|
" WINS <MapFlag> <LookupTimeout>\n"
|
|
" <CacheTimeout> <IPAddress> [<IPAddress>]\n"
|
|
" WINSR <MapFlag> <LookupTimeout>\n"
|
|
" <CacheTimeout> <RstDomainName>\n"
|
|
" <Zone> -- <ZoneName> | /RootHints\n"
|
|
" <ZoneName> -- FQDN of a zone\n"
|
|
" <NodeName> -- name of node to which a record will be added\n"
|
|
" - FQDN of a node (name with a '.' at the end) OR\n"
|
|
" - node name relative to the ZoneName OR\n"
|
|
" - \"@\" for zone root node OR\n"
|
|
" - service name for SRV only (e.g. _ftp._tcp)\n"
|
|
" <Ttl> -- TTL for the RR (Default: TTL defined in SOA)\n"
|
|
" <HostName> -- FQDN of a host\n"
|
|
" <IPAddress> -- e.g. 255.255.255.255\n"
|
|
" <ipv6Address> -- e.g. 1:2:3:4:5:6:7:8\n"
|
|
" <Protocol> -- UDP | TCP \n"
|
|
" <Service> -- e.g. domain, smtp\n"
|
|
" <TypeCovered> -- type of the RRset signed by this SIG\n"
|
|
" <CryptoAlgorithm> -- 1=RSA/MD5, 2=Diffie-Hellman, 3=DSA\n"
|
|
" <SigExpiration> -- yyyymmddhhmmss - GMT\n"
|
|
" <SigInception> -- yyyymmddhhmmss - GMT\n"
|
|
" <KeyTag> -- used to discriminate between multiple SIGs\n"
|
|
" <Signer's Name> -- domain name of signer\n"
|
|
" <KeyProtocol> -- 1=TLS, 2=email, 3=DNSSEC, 4=IPSEC\n"
|
|
" <Base64Data> -- KEY or SIG binary data in base64 notation\n"
|
|
" <NextName> -- domain name of next RRSet in zone\n"
|
|
);
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
ProcessRecordDelete(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Delete record(s) from node in zone.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
PDNS_RECORD prr;
|
|
PDNS_RPC_RECORD prrRpc = NULL;
|
|
LPSTR pzoneName = NULL;
|
|
LPSTR pnodeName = NULL;
|
|
BOOL ballocatedNode = FALSE;
|
|
LPSTR pzoneArg;
|
|
LPSTR psztypeArg = NULL;
|
|
WORD wType;
|
|
DWORD ttl = 0;
|
|
DWORD ttlFlag = 0;
|
|
CHAR buf[33];
|
|
BOOL fconfirm = TRUE;
|
|
|
|
//
|
|
// RecordDelete <Zone> <Node> <RRType> [<RRData>] [/f]
|
|
//
|
|
|
|
if ( Argc < 3 || Argc == NEED_HELP_ARGC )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
//
|
|
// Check for "force" (no-confirm) flag
|
|
//
|
|
|
|
if ( !_stricmp( Argv[Argc-1], "/f" ) )
|
|
{
|
|
fconfirm = FALSE;
|
|
Argc--;
|
|
}
|
|
if ( Argc < 3 )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
//
|
|
// read zone and domain name
|
|
//
|
|
|
|
readZoneAndDomainName(
|
|
Argv,
|
|
& pzoneName,
|
|
& pnodeName,
|
|
& ballocatedNode,
|
|
& pzoneArg,
|
|
NULL );
|
|
|
|
Argv++;
|
|
Argc--;
|
|
Argv++;
|
|
Argc--;
|
|
|
|
//
|
|
// TTL -- optional
|
|
// - use default if none given
|
|
//
|
|
|
|
ttl = strtoul(
|
|
*Argv,
|
|
NULL,
|
|
10 );
|
|
|
|
if ( ttl == 0 && strcmp(*Argv, "0") != 0 )
|
|
{
|
|
ttlFlag = DNS_RPC_RECORD_FLAG_DEFAULT_TTL;
|
|
}
|
|
else // read TTL
|
|
{
|
|
Argv++;
|
|
Argc--;
|
|
if ( Argc < 1 )
|
|
{
|
|
goto Help;
|
|
}
|
|
}
|
|
|
|
//
|
|
// record type
|
|
//
|
|
|
|
psztypeArg = *Argv;
|
|
|
|
wType = Dns_RecordTypeForName(
|
|
psztypeArg,
|
|
0 // null terminated
|
|
);
|
|
if ( !wType )
|
|
{
|
|
printf( "Invalid RRType: <%s>!\n", *Argv );
|
|
goto Help;
|
|
}
|
|
Argv++;
|
|
Argc--;
|
|
|
|
//
|
|
// build DNS_RECORD
|
|
// - if no record data, then type delete
|
|
// - otherwise build record
|
|
//
|
|
|
|
if ( Argc )
|
|
{
|
|
prr = Dns_RecordBuild_A(
|
|
NULL, // ptr to RRSet
|
|
pnodeName, // nameOwner
|
|
wType, // RR type in WORD
|
|
FALSE, // ! S.Delete
|
|
0, // S.section
|
|
Argc, // count of strings
|
|
Argv // strings to fill into RR
|
|
);
|
|
if ( ! prr )
|
|
{
|
|
printf( "\nInvalid Data!\n" );
|
|
goto Help;
|
|
}
|
|
|
|
// convert DNS_RECORD to RPC buffer
|
|
|
|
prrRpc = DnsConvertRecordToRpcBuffer( prr );
|
|
if ( ! prrRpc )
|
|
{
|
|
#if DBG
|
|
printf("DnsConvertRecordToRpcBuffer()faild\n");
|
|
#endif
|
|
status = GetLastError();
|
|
goto Help;
|
|
}
|
|
// prr and prrRpc freed by process termination
|
|
// set TTL for the RR
|
|
|
|
prrRpc->dwTtlSeconds = ttl;
|
|
prrRpc->dwFlags = ttlFlag;
|
|
}
|
|
|
|
//
|
|
// ask user for confirmation
|
|
//
|
|
|
|
if ( fconfirm )
|
|
{
|
|
if ( !getUserConfirmation( "delete record" ) )
|
|
{
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
}
|
|
|
|
//
|
|
// delete
|
|
// - if record do full update
|
|
// - if type do type delete
|
|
//
|
|
|
|
if ( prrRpc )
|
|
{
|
|
status = DnssrvUpdateRecord(
|
|
pwszServerName, // server
|
|
pzoneName, // zone
|
|
pnodeName, // node
|
|
NULL, // no add
|
|
prrRpc // RR to delete
|
|
);
|
|
}
|
|
else
|
|
{
|
|
status = DnssrvDeleteRecordSet(
|
|
pwszServerName, // server
|
|
pzoneName, // zone
|
|
pnodeName, // node
|
|
wType
|
|
);
|
|
}
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"Deleted %s record(s) at %s\n",
|
|
psztypeArg,
|
|
pzoneArg );
|
|
}
|
|
|
|
// free node name if allocated
|
|
|
|
if ( ballocatedNode && pnodeName )
|
|
{
|
|
free( pnodeName );
|
|
}
|
|
|
|
return( status );
|
|
|
|
Help:
|
|
printf(
|
|
"Usage: DnsCmd <ServerName> /RecordDelete <Zone> <NodeName>\n"
|
|
" <RRType> <RRData> [/f]\n\n"
|
|
" <Zone> -- FQDN of a zone of /RootHints or /Cache\n"
|
|
" <NodeName> -- name of node from which a record will be deleted\n"
|
|
" - \"@\" for zone root OR\n"
|
|
" - FQDN of a node (DNS name with a '.' at the end) OR\n"
|
|
" - single label for name relative to zone root ) OR\n"
|
|
" - service name for SRV only (e.g. _ftp._tcp)\n"
|
|
" <RRType>: <RRData>:\n"
|
|
" A <IP Address>\n"
|
|
" SRV <Priority> <Weight> <Port> <HostName>\n"
|
|
" AAAA <IPv6 Address>\n"
|
|
" MX <Preference> <ServerName>\n"
|
|
" NS,CNAME,PTR <HostName>\n"
|
|
" For help on how to specify the <RRData> for other record\n"
|
|
" types see \"DnsCmd /RecordAdd /?\"\n"
|
|
" If <RRData> is not specified deletes all records with of specified type\n"
|
|
" /f -- Execute without asking for confirmation\n\n" );
|
|
|
|
// free node name if allocated
|
|
|
|
if ( ballocatedNode )
|
|
{
|
|
free( pnodeName );
|
|
}
|
|
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
ProcessNodeDelete(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Delete record(s) from node in zone.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
LPSTR pzoneName;
|
|
LPSTR pnodeName;
|
|
BOOL ballocatedNode = FALSE;
|
|
LPSTR pzoneArg;
|
|
DWORD iarg;
|
|
BOOL bsubtree = FALSE;
|
|
BOOL bnoConfirm = FALSE;
|
|
|
|
//
|
|
// /DeleteNode <Zone> <NodeName> [/Tree] [/f]
|
|
//
|
|
|
|
if ( Argc < 2 || Argc > 4 )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
// read options
|
|
|
|
iarg = 3;
|
|
while ( iarg <= Argc )
|
|
{
|
|
if ( !_stricmp(Argv[iarg-1], "/Tree") )
|
|
{
|
|
bsubtree = 1;
|
|
}
|
|
else if ( !_stricmp(Argv[iarg-1], "/f") )
|
|
{
|
|
bnoConfirm = 1;
|
|
}
|
|
else
|
|
{
|
|
goto Help;
|
|
}
|
|
iarg ++;
|
|
}
|
|
|
|
//
|
|
// if confirmation option, get user confirmation
|
|
// - if denied, bail
|
|
//
|
|
|
|
if ( !bnoConfirm )
|
|
{
|
|
PCHAR pmessage = "delete node";
|
|
|
|
if ( bsubtree )
|
|
{
|
|
pmessage = "delete node's subtree";
|
|
}
|
|
if ( !getUserConfirmation( pmessage ) )
|
|
{
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
}
|
|
|
|
//
|
|
// read zone and domain name
|
|
//
|
|
|
|
readZoneAndDomainName(
|
|
Argv,
|
|
& pzoneName,
|
|
& pnodeName,
|
|
& ballocatedNode,
|
|
& pzoneArg,
|
|
NULL );
|
|
|
|
//
|
|
// delete
|
|
//
|
|
|
|
status = DnssrvDeleteNode(
|
|
pwszServerName,
|
|
pzoneName,
|
|
pnodeName,
|
|
bsubtree
|
|
);
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"DNS Server %S deleted node at %s:\n"
|
|
" Status = %d (0x%08lx)\n",
|
|
pwszServerName,
|
|
pnodeName,
|
|
status, status );
|
|
}
|
|
|
|
// free node name if allocated
|
|
|
|
if ( ballocatedNode )
|
|
{
|
|
free( pnodeName );
|
|
}
|
|
|
|
return( status );
|
|
|
|
Help:
|
|
printf(
|
|
"Usage: DnsCmd <ServerName> /NodeDelete "
|
|
"<Zone> <NodeName> [/Tree] [/f]\n"
|
|
" <Zone> -- <ZoneName> | /RootHints | /Cache\n"
|
|
" <ZoneName> -- FQDN of a zone\n"
|
|
" <NodeName> -- FQDN of a node (with a '.' at the end) OR\n"
|
|
" node name relative to the ZoneName\n"
|
|
" /Tree -- must be provided, when deleting a subdomain;\n"
|
|
" (Not to delete sub tree is the default)\n"
|
|
" /f -- execute without asking for confirmation\n"
|
|
);
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
ProcessAgeAllRecords(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Delete record(s) from node in zone.
|
|
|
|
--*/
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
LPSTR pzoneName;
|
|
LPSTR pnodeName;
|
|
BOOL ballocatedNode = FALSE;
|
|
LPSTR pzoneArg;
|
|
DWORD iarg;
|
|
BOOL bsubtree = FALSE;
|
|
BOOL bnoConfirm = FALSE;
|
|
|
|
//
|
|
// /AgeAllRecords <Zone> [<NodeName>] [/f] [Tree]
|
|
//
|
|
|
|
if ( Argc < 1 || Argc > 4 )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
//
|
|
// read options
|
|
// - iarg left at FIRST option parsed
|
|
// so we can determine if "node" option exists
|
|
//
|
|
|
|
iarg = Argc;
|
|
while ( iarg > 1 )
|
|
{
|
|
if ( !_stricmp(Argv[iarg-1], "/Tree") )
|
|
{
|
|
bsubtree = 1;
|
|
}
|
|
else if ( !_stricmp(Argv[iarg-1], "/f") )
|
|
{
|
|
bnoConfirm = 1;
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
iarg--;
|
|
}
|
|
|
|
//
|
|
// read zone and optionally, domain name
|
|
//
|
|
|
|
if ( iarg > 1 )
|
|
{
|
|
readZoneAndDomainName(
|
|
Argv,
|
|
& pzoneName,
|
|
& pnodeName,
|
|
& ballocatedNode,
|
|
& pzoneArg,
|
|
NULL );
|
|
}
|
|
else
|
|
{
|
|
pzoneArg = pzoneName = Argv[0];
|
|
pnodeName = NULL;
|
|
}
|
|
|
|
//
|
|
// if confirmation option, get user confirmation
|
|
// - if denied, bail
|
|
//
|
|
|
|
if ( !bnoConfirm )
|
|
{
|
|
PCHAR pmessage = "force aging on node";
|
|
|
|
if ( bsubtree )
|
|
{
|
|
if ( pnodeName )
|
|
{
|
|
pmessage = "force aging on node's subtree";
|
|
}
|
|
else
|
|
{
|
|
pmessage = "force aging on entire zone";
|
|
}
|
|
}
|
|
if ( !getUserConfirmation( pmessage ) )
|
|
{
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
}
|
|
|
|
//
|
|
// force aging
|
|
//
|
|
|
|
status = DnssrvForceAging(
|
|
pwszServerName,
|
|
pzoneName,
|
|
pnodeName,
|
|
bsubtree
|
|
);
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"DNS Server %S forced aging on records %s %s of zone %s:\n"
|
|
" Status = %d (0x%08lx)\n",
|
|
pwszServerName,
|
|
bsubtree ? "in subtree" : "at",
|
|
pnodeName ? pnodeName : "root",
|
|
pzoneArg,
|
|
status, status );
|
|
}
|
|
|
|
// free node name if allocated
|
|
|
|
if ( ballocatedNode )
|
|
{
|
|
free( pnodeName );
|
|
}
|
|
|
|
return( status );
|
|
|
|
Help:
|
|
printf(
|
|
"Usage: DnsCmd <ServerName> /AgeAllRecords <ZoneName> [<NodeName>] [/Tree] [/f]\n"
|
|
" <Zone> -- <ZoneName>\n"
|
|
" <ZoneName> -- FQDN of a zone\n"
|
|
" <NodeName> -- name or node or subtree in which to enable aging\n"
|
|
" - \"@\" for zone root OR\n"
|
|
" - FQDN of a node (name with a '.' at the end) OR\n"
|
|
" - single label for name relative to zone root\n"
|
|
" /Tree -- force aging on entire subtree of node\n"
|
|
" or entire zone if node not given\n"
|
|
" /f -- execute without asking for confirmation\n"
|
|
);
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Server configuration API
|
|
//
|
|
|
|
DNS_STATUS
|
|
ProcessResetProperty(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
LPSTR pszZone = NULL;
|
|
LPSTR pszProperty = NULL;
|
|
BOOL fAllZones = FALSE;
|
|
|
|
//
|
|
// Config [Zone] <PropertyName> <Value>
|
|
// Note: if there is no valid, pass 0 for DWORDs or NULL for
|
|
// other types. This allows you to clear values, such as the
|
|
// LogFilterIPList.
|
|
//
|
|
|
|
if ( Argc < 1 || Argc == NEED_HELP_ARGC )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
//
|
|
// The first arg is the zone name unless it starts with a
|
|
// slash, which means the zone name was omitted.
|
|
//
|
|
|
|
if ( *Argv[ 0 ] != '/' )
|
|
{
|
|
pszZone = Argv[ 0 ];
|
|
--Argc;
|
|
++Argv;
|
|
}
|
|
|
|
//
|
|
// Property name - starts with a slash.
|
|
//
|
|
|
|
pszProperty = getCommandName( Argv[ 0 ] );
|
|
if ( !pszProperty )
|
|
{
|
|
goto Help;
|
|
}
|
|
--Argc;
|
|
++Argv;
|
|
|
|
//
|
|
// Trap apply to all zone operation.
|
|
//
|
|
|
|
if ( pszZone &&
|
|
_stricmp( pszZone, "_ApplyAllZones_" ) == 0 )
|
|
{
|
|
pszZone = NULL;
|
|
fAllZones = TRUE;
|
|
}
|
|
|
|
//
|
|
// Do a strcmp to decide if this is a string or DWORD property.
|
|
// As more string properties are added we should probably use a
|
|
// table instead of a bunch of stricmps.
|
|
//
|
|
|
|
if ( _stricmp( pszProperty, DNS_REGKEY_LOG_FILE_PATH ) == 0 ||
|
|
_stricmp( pszProperty, DNS_REGKEY_ZONE_BREAK_ON_NAME_UPDATE ) == 0 )
|
|
{
|
|
//
|
|
// This property is a string value.
|
|
//
|
|
|
|
LPWSTR pwszPropertyValue = NULL;
|
|
|
|
if ( Argc && Argv[ 0 ] )
|
|
{
|
|
pwszPropertyValue = Dns_StringCopyAllocate(
|
|
Argv[ 0 ],
|
|
0,
|
|
DnsCharSetUtf8,
|
|
DnsCharSetUnicode );
|
|
}
|
|
|
|
if ( g_UseWmi )
|
|
{
|
|
status = DnscmdWmi_ResetProperty(
|
|
pszZone,
|
|
pszProperty,
|
|
VT_BSTR,
|
|
( PVOID ) pwszPropertyValue );
|
|
}
|
|
else
|
|
{
|
|
status = DnssrvResetStringProperty(
|
|
pwszServerName,
|
|
pszZone,
|
|
pszProperty,
|
|
pwszPropertyValue,
|
|
fAllZones ? DNSSRV_OP_PARAM_APPLY_ALL_ZONES : 0 );
|
|
}
|
|
|
|
FREE_HEAP( pwszPropertyValue );
|
|
}
|
|
else if ( _stricmp( pszProperty, DNS_REGKEY_LISTEN_ADDRESSES ) == 0 ||
|
|
_stricmp( pszProperty, DNS_REGKEY_LOG_IP_FILTER_LIST ) == 0 ||
|
|
_stricmp( pszProperty, DNS_REGKEY_FORWARDERS ) == 0 ||
|
|
_stricmp( pszProperty, DNS_REGKEY_ZONE_ALLOW_AUTONS ) == 0 ||
|
|
_stricmp( pszProperty, DNS_REGKEY_ZONE_MASTERS ) == 0 ||
|
|
_stricmp( pszProperty, DNS_REGKEY_ZONE_LOCAL_MASTERS ) == 0 ||
|
|
_stricmp( pszProperty, DNS_REGKEY_ZONE_SCAVENGE_SERVERS ) == 0 ||
|
|
_stricmp( pszProperty, DNS_REGKEY_BREAK_ON_UPDATE_FROM ) == 0 ||
|
|
_stricmp( pszProperty, DNS_REGKEY_BREAK_ON_RECV_FROM ) == 0 )
|
|
|
|
{
|
|
//
|
|
// This property is an IP list value.
|
|
//
|
|
|
|
DWORD ipCount;
|
|
IP_ADDRESS ipAddressArray[ MAX_IP_PROPERTY_COUNT ];
|
|
PIP_ARRAY pipArray = NULL;
|
|
|
|
if ( Argc )
|
|
{
|
|
BOOL fInaddrNoneAllowed =
|
|
_stricmp( pszProperty, DNS_REGKEY_BREAK_ON_UPDATE_FROM ) == 0 ||
|
|
_stricmp( pszProperty, DNS_REGKEY_BREAK_ON_RECV_FROM ) == 0;
|
|
|
|
ipCount = readIpAddressArray(
|
|
ipAddressArray,
|
|
MAX_IP_PROPERTY_COUNT,
|
|
Argc,
|
|
Argv,
|
|
fInaddrNoneAllowed );
|
|
if ( ipCount < 1 )
|
|
{
|
|
goto Help;
|
|
}
|
|
Argc -= ipCount;
|
|
Argv += ipCount;
|
|
|
|
pipArray = Dns_BuildIpArray( ipCount, ipAddressArray );
|
|
}
|
|
|
|
if ( g_UseWmi )
|
|
{
|
|
status = DnscmdWmi_ResetProperty(
|
|
pszZone,
|
|
pszProperty,
|
|
PRIVATE_VT_IPARRAY,
|
|
( PVOID ) pipArray );
|
|
}
|
|
else
|
|
{
|
|
status = DnssrvResetIPListProperty(
|
|
pwszServerName,
|
|
pszZone,
|
|
pszProperty,
|
|
pipArray,
|
|
fAllZones ? DNSSRV_OP_PARAM_APPLY_ALL_ZONES : 0 );
|
|
}
|
|
|
|
FREE_HEAP( pipArray );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// This property is a DWORD value.
|
|
//
|
|
|
|
DWORD value = Argc ?
|
|
convertDwordParameterUnknownBase( Argv[ 0 ] ) :
|
|
0;
|
|
|
|
if ( fAllZones )
|
|
{
|
|
value |= DNSSRV_OP_PARAM_APPLY_ALL_ZONES;
|
|
}
|
|
|
|
if ( g_UseWmi )
|
|
{
|
|
status = DnscmdWmi_ResetProperty(
|
|
pszZone,
|
|
pszProperty,
|
|
VT_I4,
|
|
( PVOID ) ( DWORD_PTR ) value );
|
|
}
|
|
else
|
|
{
|
|
status = DnssrvResetDwordProperty(
|
|
pwszServerName,
|
|
pszZone,
|
|
pszProperty,
|
|
value );
|
|
}
|
|
}
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"Registry property %s successfully reset.\n",
|
|
pszProperty );
|
|
}
|
|
else
|
|
{
|
|
printf(
|
|
"DNS Server failed to reset registry property.\n"
|
|
" Status = %d (0x%08lx)\n",
|
|
status, status );
|
|
}
|
|
return( status );
|
|
|
|
Help:
|
|
|
|
printf(
|
|
"Usage: DnsCmd <ServerName> /Config "
|
|
"[<ZoneName>|..AllZones] <Property> <Value>\n"
|
|
" Server <Property>:\n"
|
|
" /RpcProtocol\n"
|
|
" /LogLevel\n"
|
|
" /" DNS_REGKEY_LOG_FILE_PATH " <Log file name>\n"
|
|
" /" DNS_REGKEY_LOG_IP_FILTER_LIST " <IP list>\n"
|
|
" /" DNS_REGKEY_LOG_FILE_MAX_SIZE "\n"
|
|
" /EventlogLevel\n"
|
|
" /NoRecursion\n"
|
|
" /" DNS_REGKEY_BOOT_METHOD "\n"
|
|
" /ForwardDelegations\n"
|
|
" /ForwardingTimeout\n"
|
|
" /IsSlave\n"
|
|
" /SecureResponses\n"
|
|
" /RecursionRetry\n"
|
|
" /RecursionTimeout\n"
|
|
" /MaxCacheTtl\n"
|
|
" /" DNS_REGKEY_MAX_CACHE_SIZE "\n"
|
|
" /MaxNegativeCacheTtl\n"
|
|
" /RoundRobin\n"
|
|
" /LocalNetPriority\n"
|
|
" /AddressAnswerLimit\n"
|
|
" /BindSecondaries\n"
|
|
" /WriteAuthorityNs\n"
|
|
" /NameCheckFlag\n"
|
|
" /StrictFileParsing\n"
|
|
" /UpdateOptions\n"
|
|
" /DisableAutoReverseZones\n"
|
|
" /SendPort\n"
|
|
" /NoTcp\n"
|
|
" /XfrConnectTimeout\n"
|
|
" /DsPollingInterval\n"
|
|
" /DsTombstoneInterval\n"
|
|
" /ScavengingInterval\n"
|
|
" /DefaultAgingState\n"
|
|
" /DefaultNoRefreshInterval\n"
|
|
" /DefaultRefreshInterval\n"
|
|
" /" DNS_REGKEY_ENABLE_DNSSEC "\n"
|
|
" /" DNS_REGKEY_ENABLE_EDNS "\n"
|
|
" /" DNS_REGKEY_EDNS_CACHE_TIMEOUT "\n"
|
|
" /" DNS_REGKEY_DISABLE_AUTONS "\n"
|
|
" Zone <Property>:\n"
|
|
" /SecureSecondaries\n"
|
|
" /AllowUpdate <Value>\n"
|
|
" <Value> -- 0: no updates; 1: unsecure updates; 2: secure updates only\n"
|
|
" /Aging\n"
|
|
" /RefreshInterval <Value>\n"
|
|
" /NoRefreshInterval <Value>\n"
|
|
" /" DNS_REGKEY_ZONE_FWD_TIMEOUT " <Value>\n"
|
|
" /" DNS_REGKEY_ZONE_FWD_SLAVE " <Value>\n"
|
|
" /" DNS_REGKEY_ZONE_ALLOW_AUTONS " <IP List>\n"
|
|
" <Value>: New property value. Use 0x prefix to indicate hex value.\n"
|
|
" Note some server and zone DWORD properties must be reset as\n"
|
|
" part of a more complex operation.\n"
|
|
" Use zone \"..AllZones\" to apply operation to all zones.\n"
|
|
" See dnscmd help for more information.\n"
|
|
);
|
|
return( ERROR_SUCCESS );
|
|
} // ProcessResetProperty
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
ProcessResetForwarders(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
#define MAX_FORWARD_COUNT (50)
|
|
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
DWORD iArg = 0;
|
|
DWORD fSlave = FALSE;
|
|
DWORD dwTimeout = DNS_DEFAULT_FORWARD_TIMEOUT;
|
|
DWORD cForwarders = 0;
|
|
IP_ADDRESS aipForwarders[ MAX_FORWARD_COUNT ];
|
|
LPSTR cmd;
|
|
|
|
//
|
|
// ResetForwarders [<ForwarderIP>] ...] [/Slave|/NoSlave] [/TimeOut <time>]
|
|
//
|
|
|
|
if ( Argc == NEED_HELP_ARGC )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
// read forwarder ipAddresses:
|
|
|
|
while ( ( iArg < Argc ) &&
|
|
( !getCommandName(Argv[iArg]) ) )
|
|
{
|
|
if ( iArg < MAX_FORWARD_COUNT )
|
|
{
|
|
aipForwarders[iArg] = inet_addr( Argv[iArg] );
|
|
}
|
|
iArg++;
|
|
}
|
|
|
|
cForwarders = iArg;
|
|
|
|
//
|
|
// Optional commands
|
|
//
|
|
|
|
while ( iArg < Argc )
|
|
{
|
|
cmd = getCommandName( Argv[iArg] );
|
|
|
|
if ( cmd )
|
|
{
|
|
if ( !_stricmp(cmd, "Slave") )
|
|
{
|
|
fSlave = TRUE;
|
|
}
|
|
else if ( !_stricmp(cmd, "NoSlave") )
|
|
{
|
|
fSlave = FALSE;
|
|
}
|
|
else if ( !_stricmp(cmd, "TimeOut") )
|
|
{
|
|
if ( ++iArg >= Argc )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
dwTimeout = strtoul(
|
|
Argv[iArg],
|
|
NULL,
|
|
10 );
|
|
}
|
|
else
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
iArg ++;
|
|
}
|
|
else
|
|
{
|
|
goto Help;
|
|
}
|
|
}
|
|
|
|
if ( g_UseWmi )
|
|
{
|
|
status = DnscmdWmi_ProcessResetForwarders(
|
|
cForwarders,
|
|
aipForwarders,
|
|
dwTimeout,
|
|
fSlave );
|
|
}
|
|
else
|
|
{
|
|
status = DnssrvResetForwarders(
|
|
pwszServerName,
|
|
cForwarders,
|
|
aipForwarders,
|
|
dwTimeout,
|
|
fSlave );
|
|
}
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf( "Forwarders reset successfully.\n" );
|
|
}
|
|
else
|
|
{
|
|
printf(
|
|
"DNS Server failed to reset forwarders.\n"
|
|
" Status = %d (0x%08lx)\n",
|
|
status, status );
|
|
}
|
|
|
|
return( status );
|
|
|
|
Help:
|
|
|
|
printf( "Usage: DnsCmd <ServerName> /ResetForwarders "
|
|
"[<IPAddress>] ...] [ /[No]Slave ] [/TimeOut <Time>]\n"
|
|
" <IPAddress> -- where to forward unsolvable DNS queries\n"
|
|
" /Slave -- operate as slave server\n"
|
|
" /NoSlave -- not as slave server (default)\n"
|
|
" No forwarders is the default.\n"
|
|
" Default timeout is %d sec\n",
|
|
DNS_DEFAULT_FORWARD_TIMEOUT );
|
|
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
ProcessResetListenAddresses(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
DWORD iArg;
|
|
DWORD cListenAddresses = 0;
|
|
IP_ADDRESS aipListenAddresses[ 10 ];
|
|
|
|
//
|
|
// ResetListenAddresses <IPAddress> ...
|
|
//
|
|
|
|
//Help:
|
|
|
|
if ( Argc == NEED_HELP_ARGC )
|
|
{
|
|
goto Help;
|
|
}
|
|
if ( Argc > 0 &&
|
|
getCommandName(Argv[0]) )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
|
|
// read listen addresses
|
|
|
|
cListenAddresses = Argc;
|
|
|
|
for ( iArg=0; iArg<cListenAddresses; iArg++)
|
|
{
|
|
aipListenAddresses[iArg] = inet_addr( Argv[iArg] );
|
|
}
|
|
|
|
status = DnssrvResetServerListenAddresses(
|
|
pwszServerName,
|
|
cListenAddresses,
|
|
aipListenAddresses );
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf( "ListenAddresses reset successful.\n" );
|
|
}
|
|
else
|
|
{
|
|
printf(
|
|
"DNS Server failed to reset listen addressess.\n"
|
|
" Status = %d (0x%08lx)\n",
|
|
status, status );
|
|
}
|
|
|
|
return( status );
|
|
|
|
Help:
|
|
|
|
printf( "Usage: DnsCmd <ServerName> /ResetListenAddresses [<ListenAddress>] ...]\n"
|
|
" <ListenAddress> -- an IP address belonging to the DNS server\n"
|
|
" Default: listen to all server IP Address(es) for DNS requests\n\n" );
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Zone Queries
|
|
//
|
|
|
|
DNS_STATUS
|
|
ProcessEnumZones(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
DWORD filter = 0;
|
|
DWORD zoneCount;
|
|
WORD iArg = 0;
|
|
PDNS_RPC_ZONE_LIST pZoneList = NULL;
|
|
LPSTR cmd;
|
|
|
|
//
|
|
// EnumZones [<Filter1>] [<Filter2>]
|
|
//
|
|
|
|
// get filters:
|
|
|
|
while ( iArg < Argc )
|
|
{
|
|
cmd = getCommandName( Argv[iArg] );
|
|
|
|
if ( !cmd )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
if ( !_stricmp( cmd, "Primary" ) )
|
|
{
|
|
filter |= ZONE_REQUEST_PRIMARY;
|
|
}
|
|
else if ( !_stricmp( cmd, "Secondary" ) )
|
|
{
|
|
filter |= ZONE_REQUEST_SECONDARY;
|
|
}
|
|
else if ( !_stricmp( cmd, "Forwarder" ) )
|
|
{
|
|
filter |= ZONE_REQUEST_FORWARDER;
|
|
}
|
|
else if ( !_stricmp( cmd, "Stub" ) )
|
|
{
|
|
filter |= ZONE_REQUEST_STUB;
|
|
}
|
|
else if ( !_stricmp( cmd, "Cache" ) )
|
|
{
|
|
filter |= ZONE_REQUEST_CACHE;
|
|
}
|
|
else if ( !_stricmp( cmd, "Auto-Created" ) )
|
|
{
|
|
filter |= ZONE_REQUEST_AUTO;
|
|
}
|
|
else if ( !_stricmp( cmd, "Forward" ) )
|
|
{
|
|
filter |= ZONE_REQUEST_FORWARD;
|
|
}
|
|
else if ( !_stricmp( cmd, "Reverse" ) )
|
|
{
|
|
filter |= ZONE_REQUEST_REVERSE;
|
|
}
|
|
else if ( !_stricmp( cmd, "Ds" ) )
|
|
{
|
|
filter |= ZONE_REQUEST_DS;
|
|
}
|
|
else if ( !_stricmp( cmd, "NonDs" ) )
|
|
{
|
|
filter |= ZONE_REQUEST_NON_DS;
|
|
}
|
|
else
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
iArg ++;
|
|
}
|
|
|
|
// special case NO filter
|
|
|
|
if ( filter == 0 )
|
|
{
|
|
filter = ZONE_REQUEST_ALL_ZONES_AND_CACHE;
|
|
}
|
|
|
|
|
|
if ( g_UseWmi )
|
|
{
|
|
status = DnscmdWmi_ProcessEnumZones(
|
|
filter );
|
|
}
|
|
else
|
|
{
|
|
status = DnssrvEnumZones(
|
|
pwszServerName,
|
|
filter,
|
|
NULL,
|
|
&pZoneList );
|
|
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"DnssrvEnumZones() failed.\n"
|
|
" Status = %d (0x%08lx)\n",
|
|
status, status );
|
|
goto Cleanup;
|
|
}
|
|
else
|
|
{
|
|
DnsPrint_RpcZoneList(
|
|
dnscmd_PrintRoutine,
|
|
dnscmd_PrintContext,
|
|
"Enumerated zone list:\n",
|
|
pZoneList );
|
|
}
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
//
|
|
// deallocate zone list
|
|
//
|
|
|
|
DnssrvFreeZoneList( pZoneList );
|
|
return( status );
|
|
|
|
Help:
|
|
printf( "Usage: DnsCmd <ServerName> /EnumZones [<Filter1>] [<Filter2>]\n"
|
|
" <Filter1>: (All is the default)\n"
|
|
" /Primary\n"
|
|
" /Secondary\n"
|
|
" /Forwarder\n"
|
|
" /Stub\n"
|
|
" /Cache\n"
|
|
" /Auto-Created\n"
|
|
" <Filter2>: (All is the default)\n"
|
|
" /Forward\n"
|
|
" /Reverse\n"
|
|
" Output:\n"
|
|
" Type:\n"
|
|
" Pri - primary zone\n"
|
|
" Sec - secondary zone\n"
|
|
" Stub - stub zone\n"
|
|
" Frwdr - forwarder zone\n"
|
|
" Storage:\n"
|
|
" File - zone is stored in a file\n"
|
|
" AD-Forest - zone is stored in the forest Active Directory DNS partition\n"
|
|
" AD-Domain - zone is stored in the domain Active Directory DNS partition\n"
|
|
" AD-Legacy - zone is stored in the W2K-compatible DNS partition\n"
|
|
" Properties:\n"
|
|
" Update - DNS dynamic updates are allowed\n"
|
|
" Secure - DNS dynamic updates are allowed only if they are secure\n"
|
|
" Rev - zone is a reverse lookup zone\n"
|
|
" Auto - zone was auto-created by the DNS server\n"
|
|
" Aging - aging is enabled for this zone\n"
|
|
" Down - zone is currently shutdown\n"
|
|
" Paused - zone is currently paused\n"
|
|
);
|
|
return( ERROR_SUCCESS );
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Create a new zone
|
|
//
|
|
|
|
DNS_STATUS
|
|
ProcessZoneAdd(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
LPSTR pzoneName;
|
|
DWORD zoneType = DNS_ZONE_TYPE_PRIMARY;
|
|
DWORD countMasters = 0;
|
|
IP_ADDRESS masterArray[ MAX_IP_PROPERTY_COUNT ];
|
|
DWORD floadExisting = FALSE;
|
|
LPSTR pszAllocatedDataFile = NULL;
|
|
LPSTR pszDataFile = NULL;
|
|
LPSTR pszEmailAdminName = NULL; // pass NULL by default
|
|
LPSTR cmd;
|
|
BOOL fDsIntegrated;
|
|
|
|
DWORD dwTimeout = 0; // for forwarder zones only
|
|
BOOL fSlave = FALSE; // for forwarder zones only
|
|
|
|
BOOL fInDirPart = FALSE;
|
|
DWORD dpFlag = 0; // directory partition flag for builtin
|
|
LPSTR pszDpFqdn = NULL; // directory partition FQDN for custom
|
|
|
|
//
|
|
// CreateZone
|
|
//
|
|
|
|
if ( Argc < 2 ||
|
|
Argc == NEED_HELP_ARGC ||
|
|
getCommandName(Argv[0]) )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
// set zone name
|
|
|
|
pzoneName = Argv[0];
|
|
Argv++;
|
|
Argc--;
|
|
|
|
//
|
|
// zone type
|
|
// - Primary
|
|
// - Secondary, then read master IP array
|
|
// - DsPrimary
|
|
//
|
|
|
|
cmd = getCommandName( Argv[0] );
|
|
if ( !cmd )
|
|
{
|
|
goto Help;
|
|
}
|
|
Argv++;
|
|
Argc--;
|
|
|
|
zoneType = parseZoneTypeString( cmd, &fDsIntegrated );
|
|
|
|
if ( zoneType == -1 )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
// JJW: should I set floadExisting for all DsIntegrated zones?
|
|
if ( zoneType == DNS_ZONE_TYPE_PRIMARY && fDsIntegrated )
|
|
{
|
|
floadExisting = TRUE;
|
|
}
|
|
else if ( zoneType == DNS_ZONE_TYPE_SECONDARY ||
|
|
zoneType == DNS_ZONE_TYPE_STUB ||
|
|
zoneType == DNS_ZONE_TYPE_FORWARDER )
|
|
{
|
|
// get master IP list
|
|
|
|
countMasters = readIpAddressArray(
|
|
masterArray,
|
|
MAX_IP_PROPERTY_COUNT,
|
|
Argc,
|
|
Argv,
|
|
FALSE );
|
|
if ( countMasters < 1 )
|
|
{
|
|
goto Help;
|
|
}
|
|
Argc -= countMasters;
|
|
Argv += countMasters;
|
|
}
|
|
|
|
//
|
|
// options
|
|
// - file name (default to load existing file)
|
|
// - admin email name
|
|
// - DS overwrite options
|
|
//
|
|
|
|
while ( Argc )
|
|
{
|
|
cmd = getCommandName( *Argv );
|
|
if ( !cmd )
|
|
{
|
|
goto Help;
|
|
}
|
|
Argc--;
|
|
Argv++;
|
|
|
|
if ( !_stricmp( cmd, "file" ) )
|
|
{
|
|
if ( Argc <= 0 || zoneType == DNS_ZONE_TYPE_FORWARDER )
|
|
{
|
|
goto Help;
|
|
}
|
|
pszDataFile = *Argv;
|
|
Argc--;
|
|
Argv++;
|
|
}
|
|
else if ( !_stricmp(cmd, "a") )
|
|
{
|
|
if ( Argc <= 0 )
|
|
{
|
|
goto Help;
|
|
}
|
|
pszEmailAdminName = *Argv;
|
|
Argc--;
|
|
Argv++;
|
|
}
|
|
else if ( !_stricmp(cmd, "load") )
|
|
{
|
|
floadExisting = TRUE;
|
|
}
|
|
else if ( !_stricmp(cmd, "timeout") &&
|
|
zoneType == DNS_ZONE_TYPE_FORWARDER )
|
|
{
|
|
dwTimeout = strtoul( *( Argv++ ), NULL, 10 );
|
|
Argc--;
|
|
}
|
|
else if ( !_stricmp(cmd, "slave") &&
|
|
zoneType == DNS_ZONE_TYPE_FORWARDER )
|
|
{
|
|
fSlave = TRUE;
|
|
}
|
|
else if ( ( !_stricmp(cmd, "dp" ) ||
|
|
!_stricmp(cmd, "DirectoryPartition" ) ) &&
|
|
fDsIntegrated )
|
|
|
|
{
|
|
//
|
|
// Directory partition for zone. Check to see if a builtin DP
|
|
// is requested, if so set flag, Otherwise DP argument must
|
|
// be the FQDN of a custom DP.
|
|
//
|
|
|
|
if ( !parseDpSpecifier( *Argv, &dpFlag, &pszDpFqdn ) )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
fInDirPart = TRUE;
|
|
Argc--;
|
|
Argv++;
|
|
}
|
|
else
|
|
{
|
|
goto Help;
|
|
}
|
|
}
|
|
|
|
//
|
|
// If no file name for file-backed, set up default.
|
|
//
|
|
|
|
if ( zoneType == DNS_ZONE_TYPE_PRIMARY &&
|
|
!pszDataFile &&
|
|
!fDsIntegrated )
|
|
{
|
|
pszAllocatedDataFile = MIDL_user_allocate( strlen( pzoneName ) + 20 );
|
|
strcpy( pszAllocatedDataFile, pzoneName );
|
|
strcat( pszAllocatedDataFile, ".dns" );
|
|
pszDataFile = pszAllocatedDataFile;
|
|
}
|
|
|
|
//
|
|
// Let there be zone!
|
|
//
|
|
|
|
if ( fInDirPart )
|
|
{
|
|
status = DnssrvCreateZoneInDirectoryPartition(
|
|
pwszServerName,
|
|
pzoneName,
|
|
zoneType,
|
|
pszEmailAdminName,
|
|
countMasters,
|
|
masterArray,
|
|
floadExisting,
|
|
dwTimeout,
|
|
fSlave,
|
|
dpFlag,
|
|
pszDpFqdn );
|
|
}
|
|
else
|
|
{
|
|
status = DnssrvCreateZone(
|
|
pwszServerName,
|
|
pzoneName,
|
|
zoneType,
|
|
pszEmailAdminName,
|
|
countMasters,
|
|
masterArray,
|
|
floadExisting,
|
|
fDsIntegrated,
|
|
pszDataFile,
|
|
dwTimeout,
|
|
fSlave );
|
|
}
|
|
|
|
if ( pszAllocatedDataFile )
|
|
{
|
|
MIDL_user_free( pszAllocatedDataFile );
|
|
pszAllocatedDataFile = NULL;
|
|
}
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"DNS Server %S created zone %s:\n",
|
|
pwszServerName,
|
|
pzoneName );
|
|
}
|
|
return( status );
|
|
|
|
Help:
|
|
|
|
printf(
|
|
"Usage: DnsCmd <ServerName> /ZoneAdd <ZoneName> <ZoneType> [<Options>]\n"
|
|
" <ZoneName> -- FQDN of zone\n"
|
|
" <ZoneType>:\n"
|
|
" /DsPrimary [/dp <FQDN>]\n"
|
|
" -- DS integrated primary zone\n"
|
|
" /Primary /file <filename>\n"
|
|
" -- standard file backed primary; MUST include filename.\n"
|
|
" /Secondary <MasterIPaddress> [<MasterIPaddress>] ..] [/file <filename>]\n"
|
|
" -- standard secondary, MUST include at least one master IP;\n"
|
|
" filename is optional.\n"
|
|
" /Stub <MasterIPaddress> [<MasterIPaddress>] ..] [/file <filename>]\n"
|
|
" -- stub secondary, only replicates NS info from primary server\n"
|
|
" /DsStub -- as /Stub but DS integrated - use same options\n"
|
|
" /Forwarder <MasterIPaddress> [<MasterIPaddress>] ..] [/Timeout <Time>]\n"
|
|
" [/Slave]\n"
|
|
" -- forwarder zone, queries for names in zone forwarded to masters\n"
|
|
" /DsForwarder -- as /Forwarder but DS integrated - use same options\n"
|
|
" <Options>:\n"
|
|
" [/file <filename>] -- filename, invalid for DS integrated zones\n"
|
|
" [/load] -- load existing file; if not specified,\n"
|
|
" non-DS primary creates default zone records\n"
|
|
" [/a <AdminName>] -- zone admin email name; primary zones only\n"
|
|
" [/DP <FQDN>] -- fully qualified domain name of directory partition\n"
|
|
" where zone should be stored; or use one of:\n"
|
|
" /DP /domain - domain directory partition\n"
|
|
" /DP /forest - forest directory partition\n"
|
|
" /DP /legacy - legacy directory partition\n"
|
|
);
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
ProcessZoneDelete(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
LPSTR cmd;
|
|
BOOL fconfirm = TRUE;
|
|
DWORD iArg;
|
|
LPSTR pszOperation;
|
|
|
|
|
|
//
|
|
// ZoneDelete <ZoneName> [/DsDel] [/f]
|
|
//
|
|
|
|
if ( Argc < 1 ||
|
|
Argc == NEED_HELP_ARGC ||
|
|
( getCommandName( Argv[0] ) ) )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
pszOperation = DNSSRV_OP_ZONE_DELETE;
|
|
|
|
// read options
|
|
|
|
iArg = 1;
|
|
while ( iArg < Argc )
|
|
{
|
|
if ( !(cmd = getCommandName(Argv[iArg]) ) )
|
|
{
|
|
goto Help;
|
|
}
|
|
if ( !_stricmp( cmd, "f" ) )
|
|
{
|
|
// execute without confirmation:
|
|
fconfirm = FALSE;
|
|
}
|
|
else if ( !_stricmp( cmd, "DsDel" ) )
|
|
{
|
|
// delete zone from DS:
|
|
pszOperation = DNSSRV_OP_ZONE_DELETE_FROM_DS;
|
|
}
|
|
else
|
|
{
|
|
goto Help;
|
|
}
|
|
iArg ++;
|
|
}
|
|
|
|
//
|
|
// get user confirmation
|
|
//
|
|
|
|
if ( fconfirm )
|
|
{
|
|
if ( !getUserConfirmation( pszOperation ) )
|
|
{
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
}
|
|
|
|
if ( g_UseWmi )
|
|
{
|
|
status = DnscmdWmi_ProcessDnssrvOperation(
|
|
Argv[ 0 ], // zone name
|
|
pszOperation, // delete or delete from DS
|
|
DNSSRV_TYPEID_NULL, // no data
|
|
( PVOID ) NULL );
|
|
}
|
|
else
|
|
{
|
|
status = DnssrvOperation(
|
|
pwszServerName,
|
|
Argv[ 0 ], // zone name
|
|
pszOperation, // delete or delete from DS
|
|
DNSSRV_TYPEID_NULL, // no data
|
|
( PVOID ) NULL );
|
|
}
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"DNS Server %S deleted zone %s:\n"
|
|
" Status = %d (0x%08lx)\n",
|
|
pwszServerName,
|
|
Argv[0],
|
|
status, status );
|
|
}
|
|
return( status );
|
|
|
|
Help:
|
|
printf(
|
|
"Usage: DnsCmd <ServerName> /ZoneDelete <ZoneName> [/DsDel] [/f]\n"
|
|
" /DsDel -- Delete Zone from DS\n"
|
|
" /f -- Execute without asking for confirmation\n"
|
|
" Default: delete zone from DNS sever, but NOT from DS\n" );
|
|
return( ERROR_SUCCESS );
|
|
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
ProcessZonePause(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
|
|
//
|
|
// ZonePause <ZoneName>
|
|
//
|
|
|
|
//Help:
|
|
|
|
if ( Argc != 1 ||
|
|
getCommandName( Argv[0] ) )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
status = DnssrvPauseZone(
|
|
pwszServerName,
|
|
Argv[0] // zone name
|
|
);
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"DNS Server %S paused zone %s:\n"
|
|
" Status = %d (0x%08lx)\n",
|
|
pwszServerName,
|
|
Argv[0],
|
|
status, status );
|
|
}
|
|
return( status );
|
|
|
|
Help:
|
|
|
|
printf( "Usage: DnsCmd <ServerName> /ZonePause <ZoneName>\n" );
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
ProcessZoneResume(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
|
|
//
|
|
// ResumeZone <ZoneName>
|
|
//
|
|
|
|
if ( Argc != 1 ||
|
|
getCommandName( Argv[0] ) )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
status = DnssrvResumeZone(
|
|
pwszServerName,
|
|
Argv[0] // zone name
|
|
);
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"DNS Server %S resumed use of zone %s:\n"
|
|
" Status = %d (0x%08lx)\n",
|
|
pwszServerName,
|
|
Argv[0],
|
|
status, status );
|
|
}
|
|
return( status );
|
|
|
|
Help:
|
|
|
|
printf( "Usage: DnsCmd <ServerName> /ZoneResume <ZoneName>\n" );
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
ProcessZoneReload(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
|
|
//
|
|
// ReloadZone <ZoneName>
|
|
//
|
|
|
|
if ( Argc != 1 ||
|
|
getCommandName( Argv[0] ) )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
status = DnssrvOperation(
|
|
pwszServerName,
|
|
Argv[0], // zone name
|
|
DNSSRV_OP_ZONE_RELOAD, // operation
|
|
DNSSRV_TYPEID_NULL, // no data
|
|
(PVOID) NULL
|
|
);
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"DNS Server %S reloaded zone %s:\n"
|
|
" Status = %d (0x%08lx)\n",
|
|
pwszServerName,
|
|
Argv[0],
|
|
status, status );
|
|
}
|
|
return( status );
|
|
|
|
Help:
|
|
|
|
printf( "Usage: DnsCmd <ServerName> /ZoneReload <ZoneName>\n" );
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
ProcessZoneWriteBack(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
|
|
//
|
|
// ZoneWriteBack <ZoneName>
|
|
//
|
|
|
|
if ( Argc != 1 ||
|
|
getCommandName( Argv[0] ) )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
status = DnssrvOperation(
|
|
pwszServerName,
|
|
Argv[0], // zone name
|
|
DNSSRV_OP_ZONE_WRITE_BACK_FILE, // operation
|
|
DNSSRV_TYPEID_NULL, // no data
|
|
(PVOID) NULL
|
|
);
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"DNS Server %S wrote back zone %s:\n"
|
|
" Status = %d (0x%08lx)\n",
|
|
pwszServerName,
|
|
Argv[0],
|
|
status, status );
|
|
}
|
|
return( status );
|
|
|
|
Help:
|
|
|
|
printf( "Usage: DnsCmd <ServerName> /ZoneWriteBack <ZoneName>\n" );
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
ProcessZoneRefresh(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
|
|
//
|
|
// ZoneRefresh <ZoneName>
|
|
//
|
|
|
|
if ( Argc != 1 || getCommandName( Argv[0] ) )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
status = DnssrvOperation(
|
|
pwszServerName,
|
|
Argv[0], // zone name
|
|
DNSSRV_OP_ZONE_REFRESH, // operation
|
|
DNSSRV_TYPEID_NULL, // no data
|
|
(PVOID) NULL
|
|
);
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"DNS Server %S forced refresh of zone %s:\n"
|
|
" Status = %d (0x%08lx)\n",
|
|
pwszServerName,
|
|
Argv[0],
|
|
status, status );
|
|
}
|
|
return( status );
|
|
|
|
Help:
|
|
|
|
printf( "Usage: DnsCmd <ServerName> /ZoneRefresh <ZoneName>\n" );
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
ProcessZoneUpdateFromDs(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
|
|
//
|
|
// ZoneUpdateFromDs <ZoneName>
|
|
//
|
|
|
|
if ( Argc != 1 || getCommandName( Argv[0] ) )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
status = DnssrvOperation(
|
|
pwszServerName,
|
|
Argv[0],
|
|
DNSSRV_OP_ZONE_UPDATE_FROM_DS,
|
|
DNSSRV_TYPEID_NULL,
|
|
(PVOID) NULL );
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"DNS Server %S update zone %s.\n"
|
|
" Status = %d (0x%08lx)\n",
|
|
pwszServerName,
|
|
Argv[0],
|
|
status, status );
|
|
}
|
|
return( status );
|
|
|
|
Help:
|
|
|
|
printf(
|
|
"Usage: DnsCmd <ServerName> /ZoneUpdateFromDs <ZoneName>\n" );
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Zone property reset functions
|
|
//
|
|
|
|
DNS_STATUS
|
|
ProcessZoneResetType(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
LPSTR pzoneName;
|
|
DWORD zoneType = DNS_ZONE_TYPE_PRIMARY; // default
|
|
DWORD countMasters = 0;
|
|
IP_ADDRESS masterArray[ MAX_IP_PROPERTY_COUNT ];
|
|
DWORD fDsIntegrated;
|
|
DWORD loadOptions = TRUE; // load existing
|
|
LPSTR pszDataFile = NULL;
|
|
DWORD iArg = 0;
|
|
LPSTR cmd;
|
|
|
|
//
|
|
// ZoneResetType <ZoneName> <Property> [<options>]
|
|
//
|
|
|
|
if ( Argc < 2 ||
|
|
Argc == NEED_HELP_ARGC ||
|
|
getCommandName(Argv[0]) )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
// get zone name
|
|
|
|
pzoneName = Argv[0];
|
|
Argv++;
|
|
Argc--;
|
|
|
|
// get zone type:
|
|
|
|
cmd = getCommandName( Argv[0] );
|
|
if ( !cmd )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
zoneType = parseZoneTypeString( cmd, &fDsIntegrated );
|
|
|
|
if ( zoneType == -1 )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
if ( zoneType == DNS_ZONE_TYPE_SECONDARY ||
|
|
zoneType == DNS_ZONE_TYPE_STUB ||
|
|
zoneType == DNS_ZONE_TYPE_FORWARDER )
|
|
{
|
|
// get master IP list
|
|
|
|
countMasters = readIpAddressArray(
|
|
masterArray,
|
|
MAX_IP_PROPERTY_COUNT,
|
|
Argc-1,
|
|
Argv+1,
|
|
FALSE );
|
|
if ( countMasters < 1 )
|
|
{
|
|
goto Help;
|
|
}
|
|
Argv += countMasters;
|
|
Argc -= countMasters;
|
|
}
|
|
|
|
Argv++;
|
|
Argc--;
|
|
|
|
//
|
|
// options
|
|
//
|
|
|
|
iArg = 0;
|
|
|
|
while ( iArg < Argc )
|
|
{
|
|
cmd = getCommandName( Argv[iArg] );
|
|
if ( !cmd )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
if ( !_stricmp(cmd, "file") )
|
|
{
|
|
if ( ++iArg >= Argc )
|
|
{
|
|
goto Help;
|
|
}
|
|
pszDataFile = Argv[iArg];
|
|
}
|
|
else if ( !_stricmp(cmd, "OverWrite_Mem") )
|
|
{
|
|
loadOptions |= DNS_ZONE_LOAD_OVERWRITE_MEMORY;
|
|
}
|
|
else if ( !_stricmp(cmd, "OverWrite_Ds") )
|
|
{
|
|
loadOptions |= DNS_ZONE_LOAD_OVERWRITE_DS;
|
|
}
|
|
else
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
iArg++;
|
|
}
|
|
|
|
//
|
|
// reset type
|
|
//
|
|
|
|
status = DnssrvResetZoneTypeEx(
|
|
pwszServerName,
|
|
pzoneName,
|
|
zoneType,
|
|
countMasters,
|
|
masterArray,
|
|
loadOptions,
|
|
fDsIntegrated,
|
|
pszDataFile );
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"DNS Server %S reset type of zone %s:\n",
|
|
pwszServerName,
|
|
pzoneName );
|
|
}
|
|
return( status );
|
|
|
|
Help:
|
|
|
|
printf(
|
|
"Usage: DnsCmd <ServerName> /ZoneResetType <ZoneName> <Property> [<Options>]\n"
|
|
" <ZoneName> -- FQDN of zone\n"
|
|
" <Property>:\n"
|
|
" /Primary /file <filename>\n"
|
|
" /Secondary <MasterIPaddress> [<MasterIPaddress>] [/file <filename>]\n"
|
|
" /Stub <MasterIPaddress> [<MasterIPaddress>] [/file <filename>]\n"
|
|
" /DsStub <MasterIPaddress> [<MasterIPaddress>]\n"
|
|
" /Forwarder <MasterIPaddress> [<MasterIPaddress>] [/file <filename>]\n"
|
|
" /DsPrimary -- DS integrated zone\n"
|
|
" <Options>:\n"
|
|
" /OverWrite_Mem -- overwrite DNS by data in DS\n"
|
|
" /OverWrite_Ds -- overwrite DS by data in DNS\n"
|
|
);
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Zone rename
|
|
//
|
|
|
|
DNS_STATUS
|
|
ProcessZoneRename(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
LPSTR pszCurrentZoneName = NULL;
|
|
LPSTR pszNewZoneName = NULL;
|
|
LPSTR pszNewFileName = NULL;
|
|
LPSTR cmd;
|
|
|
|
//
|
|
// ZoneRename <ZoneName> <Property> [<options>]
|
|
//
|
|
|
|
if ( Argc < 2 ||
|
|
Argc == NEED_HELP_ARGC ||
|
|
getCommandName( Argv[ 0 ] ) )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
// get current and new zone names
|
|
|
|
pszCurrentZoneName = Argv[0];
|
|
Argv++;
|
|
Argc--;
|
|
pszNewZoneName = Argv[0];
|
|
Argv++;
|
|
Argc--;
|
|
|
|
// optionally get file name
|
|
|
|
if ( Argc > 0 )
|
|
{
|
|
cmd = getCommandName( *Argv );
|
|
Argc--;
|
|
Argv++;
|
|
if ( cmd && !_stricmp( cmd, "file" ) )
|
|
{
|
|
if ( Argc <= 0 )
|
|
{
|
|
goto Help;
|
|
}
|
|
pszNewFileName = *Argv;
|
|
Argc--;
|
|
Argv++;
|
|
}
|
|
}
|
|
|
|
status = DnssrvRenameZone(
|
|
pwszServerName,
|
|
pszCurrentZoneName,
|
|
pszNewZoneName,
|
|
pszNewFileName );
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"DNS Server %S renamed zone\n %s to\n %s\n",
|
|
pwszServerName,
|
|
pszCurrentZoneName,
|
|
pszNewZoneName );
|
|
}
|
|
return( status );
|
|
|
|
Help:
|
|
|
|
printf(
|
|
"Usage: DnsCmd <ServerName> /ZoneRename <CurrentZoneName> <NewZoneName>\n"
|
|
);
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
//
|
|
// Zone export
|
|
//
|
|
|
|
DNS_STATUS
|
|
ProcessZoneExport(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
LPSTR pszzoneName = NULL;
|
|
LPSTR pszzoneExportFile = NULL;
|
|
LPSTR cmd;
|
|
|
|
//
|
|
// ZoneExport <ZoneName> ZoneExportFile
|
|
//
|
|
|
|
if ( Argc != 2 || Argc == NEED_HELP_ARGC )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
// Get zone name argument and output file argument.
|
|
|
|
pszzoneName = Argv[ 0 ];
|
|
Argv++;
|
|
Argc--;
|
|
if ( _stricmp( pszzoneName, "/Cache" ) == 0 )
|
|
{
|
|
pszzoneName = DNS_ZONE_CACHE;
|
|
}
|
|
pszzoneExportFile = Argv[ 0 ];
|
|
Argv++;
|
|
Argc--;
|
|
|
|
status = DnssrvExportZone(
|
|
pwszServerName,
|
|
pszzoneName,
|
|
pszzoneExportFile );
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
//
|
|
// If we are executing this command on the local server, try and
|
|
// get the real value of the windir environment variable to make
|
|
// the output as helpful as possible. Otherwise just print %windir%
|
|
// as literal text. Note: fServerIsRemote is not 100% accurate - if
|
|
// you type in the name of the local machine as the server, for
|
|
// example. But since it is only used to tailor the output message
|
|
// slightly this is acceptable.
|
|
//
|
|
|
|
BOOL fServerIsRemote = wcscmp( pwszServerName, L"." ) != 0;
|
|
char * pszWinDir = "%windir%";
|
|
|
|
if ( !fServerIsRemote )
|
|
{
|
|
char * pszRealWinDir = getenv( "windir" );
|
|
|
|
if ( pszRealWinDir )
|
|
{
|
|
pszWinDir = pszRealWinDir;
|
|
}
|
|
}
|
|
|
|
printf(
|
|
"DNS Server %S exported zone\n"
|
|
" %s to file %s\\system32\\dns\\%s%s\n",
|
|
pwszServerName,
|
|
pszzoneName,
|
|
pszWinDir,
|
|
pszzoneExportFile,
|
|
fServerIsRemote ? " on the DNS server" : "" );
|
|
}
|
|
return status;
|
|
|
|
Help:
|
|
|
|
printf(
|
|
"Usage: DnsCmd <ServerName> /ZoneExport <ZoneName> <ZoneExportFile>\n"
|
|
" <ZoneName> -- FQDN of zone to export\n"
|
|
" /Cache to export cache\n" );
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
|
|
//
|
|
// Move zone to another directory partition
|
|
//
|
|
|
|
DNS_STATUS
|
|
ProcessZoneChangeDirectoryPartition(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
LPSTR pszzoneName = NULL;
|
|
DWORD dwdpFlag = 0; // directory partition flag for built-in
|
|
LPSTR pszdpFqdn = NULL; // directory partition FQDN for custom
|
|
|
|
//
|
|
// ZoneChangeDP ZoneName NewPartitionName
|
|
//
|
|
|
|
if ( Argc != 2 || Argc == NEED_HELP_ARGC )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
pszzoneName = Argv[ 0 ];
|
|
Argv++;
|
|
Argc--;
|
|
|
|
if ( !parseDpSpecifier( *Argv, NULL, &pszdpFqdn ) )
|
|
{
|
|
goto Help;
|
|
}
|
|
Argv++;
|
|
Argc--;
|
|
|
|
status = DnssrvChangeZoneDirectoryPartition(
|
|
pwszServerName,
|
|
pszzoneName,
|
|
pszdpFqdn );
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"DNS Server %S moved zone %s to new directory partition\n",
|
|
pwszServerName,
|
|
pszzoneName );
|
|
}
|
|
return status;
|
|
|
|
Help:
|
|
|
|
printf(
|
|
"Usage: DnsCmd <ServerName> /ZoneChangeDirectoryPartition <ZoneName> <NewPartitionName>\n"
|
|
" <ZoneName> -- FQDN of zone to move to new partition\n"
|
|
" <NewPartition> -- FQDN of new directory partition or one of:\n"
|
|
" /domain - domain directory partition\n"
|
|
" /forest - forest directory partition\n"
|
|
" /legacy - legacy directory partition\n" );
|
|
return ERROR_SUCCESS;
|
|
} // ProcessZoneChangeDirectoryPartition
|
|
|
|
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
ProcessZoneResetSecondaries(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
DWORD fsecureSecondaries = MAXDWORD;
|
|
DWORD fnotifyLevel = MAXDWORD;
|
|
DWORD countSecondaries = 0;
|
|
DWORD countNotify = 0;
|
|
IP_ADDRESS secondaries[ MAX_IP_PROPERTY_COUNT ];
|
|
IP_ADDRESS notifyList[ MAX_IP_PROPERTY_COUNT ];
|
|
PIP_ADDRESS array;
|
|
LPSTR pzoneName;
|
|
LPSTR cmd;
|
|
DWORD count;
|
|
|
|
//
|
|
// ZoneResetSecondaries <ZoneName> [<SecureFlag>] [<NotifyFlag>] [<NotifyIPAddress>] ...]
|
|
//
|
|
|
|
if ( Argc < 1 ||
|
|
Argc == NEED_HELP_ARGC ||
|
|
getCommandName(Argv[0]) )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
// zone name
|
|
|
|
pzoneName = Argv[0];
|
|
|
|
Argc--;
|
|
Argv++;
|
|
|
|
// read security and notify flags
|
|
|
|
while ( Argc )
|
|
{
|
|
cmd = getCommandName( Argv[0] );
|
|
if ( cmd )
|
|
{
|
|
// security cases
|
|
|
|
if ( !_stricmp(cmd, "NoXfr") )
|
|
{
|
|
fsecureSecondaries = ZONE_SECSECURE_NO_XFR;
|
|
}
|
|
else if ( !_stricmp(cmd, "SecureNs") )
|
|
{
|
|
fsecureSecondaries = ZONE_SECSECURE_NS_ONLY;
|
|
}
|
|
else if ( !_stricmp(cmd, "SecureList") )
|
|
{
|
|
fsecureSecondaries = ZONE_SECSECURE_LIST;
|
|
}
|
|
else if ( !_stricmp(cmd, "NonSecure") )
|
|
{
|
|
fsecureSecondaries = ZONE_SECSECURE_NO_SECURITY;
|
|
}
|
|
|
|
// notify cases
|
|
|
|
else if ( !_stricmp(cmd, "NoNotify") )
|
|
{
|
|
fnotifyLevel = ZONE_NOTIFY_OFF;
|
|
}
|
|
else if ( !_stricmp(cmd, "Notify") )
|
|
{
|
|
fnotifyLevel = ZONE_NOTIFY_ALL;
|
|
}
|
|
else if ( !_stricmp(cmd, "NotifyList") )
|
|
{
|
|
fnotifyLevel = ZONE_NOTIFY_LIST_ONLY;
|
|
}
|
|
else
|
|
{
|
|
goto Help;
|
|
}
|
|
Argc--;
|
|
Argv++;
|
|
continue;
|
|
}
|
|
|
|
// get IP list
|
|
// - secondary IP before <Notify> flag
|
|
// - notify IP list after
|
|
|
|
array = secondaries;
|
|
if ( fnotifyLevel != MAXDWORD )
|
|
{
|
|
array = notifyList;
|
|
}
|
|
count = 0;
|
|
|
|
while ( Argc )
|
|
{
|
|
IP_ADDRESS ip;
|
|
|
|
cmd = getCommandName( Argv[0] );
|
|
if ( cmd )
|
|
{
|
|
break; // no more IP
|
|
}
|
|
|
|
ip = inet_addr( Argv[0] );
|
|
if ( ip == -1 )
|
|
{
|
|
goto Help;
|
|
}
|
|
array[ count ] = ip;
|
|
count++;
|
|
|
|
Argc--;
|
|
Argv++;
|
|
}
|
|
|
|
if ( fnotifyLevel == MAXDWORD )
|
|
{
|
|
countSecondaries = count;
|
|
}
|
|
else
|
|
{
|
|
countNotify = count;
|
|
}
|
|
}
|
|
|
|
//
|
|
// default flags
|
|
// - do intelligent thing if lists are given
|
|
// otherwise default to open zone with notify
|
|
//
|
|
|
|
if ( countSecondaries )
|
|
{
|
|
fsecureSecondaries = ZONE_SECSECURE_LIST;
|
|
}
|
|
else if ( fsecureSecondaries == MAXDWORD )
|
|
{
|
|
fsecureSecondaries = ZONE_SECSECURE_NO_SECURITY;
|
|
}
|
|
|
|
if ( countNotify )
|
|
{
|
|
fnotifyLevel = ZONE_NOTIFY_LIST_ONLY;
|
|
}
|
|
else if ( fnotifyLevel == MAXDWORD )
|
|
{
|
|
fnotifyLevel = ZONE_NOTIFY_ALL;
|
|
}
|
|
|
|
//
|
|
// reset secondaries on server
|
|
//
|
|
|
|
if ( g_UseWmi )
|
|
{
|
|
status = DnscmdWmi_ProcessResetZoneSecondaries(
|
|
pzoneName,
|
|
fsecureSecondaries,
|
|
countSecondaries,
|
|
secondaries,
|
|
fnotifyLevel,
|
|
countNotify,
|
|
notifyList );
|
|
}
|
|
else
|
|
{
|
|
status = DnssrvResetZoneSecondaries(
|
|
pwszServerName,
|
|
pzoneName,
|
|
fsecureSecondaries,
|
|
countSecondaries,
|
|
secondaries,
|
|
fnotifyLevel,
|
|
countNotify,
|
|
notifyList );
|
|
}
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"Zone %s reset notify list successful.\n",
|
|
pzoneName );
|
|
}
|
|
return( status );
|
|
|
|
Help:
|
|
|
|
printf(
|
|
"Usage: DnsCmd <ServerName> /ZoneResetSecondaries <ZoneName> \n"
|
|
" [<Security>] [<SecondaryIPAddress>] ...]\n"
|
|
" [<Notify>] [<NotifyIPAddress>] ...]\n"
|
|
" <Security>:\n"
|
|
" /NoXfr -- no zone transfer\n"
|
|
" /NonSecure -- transfer to any IP (default)\n"
|
|
" /SecureNs -- transfer only to NS for zone\n"
|
|
" /SecureList -- transfer only to NS in secondary list; must\n"
|
|
" then provide secondary IP list\n"
|
|
" <Notify>:\n"
|
|
" /NoNotify -- turn off notify\n"
|
|
" /Notify -- notify (default); notifies all secondaries in list and \n"
|
|
" for non-DS primary notifies all NS servers for zone\n"
|
|
" /NotifyList -- notify only notify list IPs;\n"
|
|
" must then provide notify IP list\n" );
|
|
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
ProcessZoneResetScavengeServers(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
IP_ADDRESS serverArray[ MAX_IP_PROPERTY_COUNT + 1 ];
|
|
DWORD serverCount;
|
|
LPSTR pzoneName;
|
|
|
|
//
|
|
// ZoneSetScavengeServers <ZoneName> <ServerIPAddress>
|
|
//
|
|
|
|
if ( Argc < 1 || getCommandName(Argv[0]) )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
// zone name
|
|
|
|
pzoneName = Argv[0];
|
|
|
|
Argc--;
|
|
Argv++;
|
|
|
|
// get server IP list
|
|
|
|
serverCount = readIpArray(
|
|
(PIP_ARRAY) serverArray,
|
|
MAX_IP_PROPERTY_COUNT,
|
|
Argc,
|
|
Argv );
|
|
|
|
if ( serverCount != Argc )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
DnsPrint_IpArray(
|
|
dnscmd_PrintRoutine,
|
|
dnscmd_PrintContext,
|
|
"New scavenge servers:",
|
|
"server",
|
|
(PIP_ARRAY) serverArray
|
|
);
|
|
|
|
//
|
|
// reset scavenging servers
|
|
// - if NO addresses given, send NULL to enable all servers to
|
|
// scavenge zone
|
|
//
|
|
|
|
status = DnssrvOperation(
|
|
pwszServerName,
|
|
pzoneName,
|
|
DNS_REGKEY_ZONE_SCAVENGE_SERVERS,
|
|
DNSSRV_TYPEID_IPARRAY,
|
|
serverCount
|
|
? (PIP_ARRAY) serverArray
|
|
: NULL
|
|
);
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"Reset scavenging servers on zone %s successfully.\n",
|
|
pzoneName );
|
|
}
|
|
else
|
|
{
|
|
printf(
|
|
"Error, failed reset of scavenge servers on zone %s.\n"
|
|
" Status = %d\n",
|
|
pzoneName,
|
|
status );
|
|
}
|
|
return( status );
|
|
|
|
Help:
|
|
|
|
printf(
|
|
"Usage: DnsCmd <ServerName> /ZoneResetScavengeServers <ZoneName> [<Server IPs>]\n"
|
|
" <Server IPs> -- list of one or more IP addresses of servers to scavenge\n"
|
|
" this zone; if no addresses given ALL servers hosting this zone\n"
|
|
" will be allowed to scavenge the zone.\n"
|
|
);
|
|
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
ProcessZoneResetMasters(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
IP_ADDRESS serverArray[ MAX_IP_PROPERTY_COUNT+1 ];
|
|
DWORD serverCount;
|
|
LPSTR pzoneName;
|
|
LPSTR psz;
|
|
BOOL fLocalMasters = FALSE;
|
|
|
|
//
|
|
// ZoneResetMasters <ZoneName> [/Local] <MasterIPAddress>
|
|
//
|
|
// Local tells the server to set the local master list for DS integrated
|
|
// stub zones.
|
|
//
|
|
|
|
if ( Argc < 1 || getCommandName(Argv[0]) )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
// zone name
|
|
|
|
pzoneName = Argv[0];
|
|
|
|
Argc--;
|
|
Argv++;
|
|
|
|
// local flag
|
|
|
|
psz = getCommandName( Argv[ 0 ] );
|
|
if ( psz )
|
|
{
|
|
if ( _stricmp( psz, "Local" ) == 0 )
|
|
{
|
|
fLocalMasters = TRUE;
|
|
}
|
|
else
|
|
{
|
|
goto Help; // Unknown option
|
|
}
|
|
Argc--;
|
|
Argv++;
|
|
}
|
|
|
|
// get server IP list - an empty IP list is permissable
|
|
|
|
serverCount = readIpArray(
|
|
(PIP_ARRAY) serverArray,
|
|
MAX_IP_PROPERTY_COUNT,
|
|
Argc,
|
|
Argv );
|
|
|
|
if ( serverCount != Argc )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
//
|
|
// reset masters
|
|
//
|
|
|
|
if ( g_UseWmi )
|
|
{
|
|
status = DnscmdWmi_ProcessDnssrvOperation(
|
|
pzoneName,
|
|
fLocalMasters ?
|
|
DNS_REGKEY_ZONE_LOCAL_MASTERS :
|
|
DNS_REGKEY_ZONE_MASTERS,
|
|
DNSSRV_TYPEID_IPARRAY,
|
|
( PIP_ARRAY ) serverArray );
|
|
}
|
|
else
|
|
{
|
|
status = DnssrvOperation(
|
|
pwszServerName,
|
|
pzoneName,
|
|
fLocalMasters ?
|
|
DNS_REGKEY_ZONE_LOCAL_MASTERS :
|
|
DNS_REGKEY_ZONE_MASTERS,
|
|
DNSSRV_TYPEID_IPARRAY,
|
|
( PIP_ARRAY ) serverArray );
|
|
}
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"Reset master servers for zone %s successfully.\n",
|
|
pzoneName );
|
|
}
|
|
else
|
|
{
|
|
printf(
|
|
"Error failed reset of master servers for zone %s.\n"
|
|
" Status = %d\n",
|
|
pzoneName,
|
|
status );
|
|
}
|
|
return( status );
|
|
|
|
Help:
|
|
|
|
printf(
|
|
"Usage: DnsCmd <ServerName> /ZoneResetMasters <ZoneName> [/Local] [<Server IPs>]\n"
|
|
" /Local -- Set the local master list for DS integrated zones.\n"
|
|
" <Server IPs> -- List of one or more IP addresses of master servers for\n"
|
|
" this zone. Masters may include the primary or other secondaries\n"
|
|
" for the zone, but should not make the replication graph cyclic.\n"
|
|
);
|
|
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
DNS_STATUS
|
|
ProcessResetZoneType(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
DWORD dwZoneType;
|
|
IP_ADDRESS ipMaster = 0;
|
|
|
|
//
|
|
// ResetZoneType <ZoneName> <ZoneType> [MasterIp]
|
|
//
|
|
|
|
if( Argc < 2 || Argc > 3 )
|
|
{
|
|
printf( "Usage: dnscmd <Server> ResetZoneType <ZoneName> <ZoneType> [MasterIp]\n" );
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
// get zone type
|
|
|
|
dwZoneType = strtoul(
|
|
Argv[1],
|
|
NULL,
|
|
10 );
|
|
|
|
// get master IP
|
|
|
|
if ( Argc == 3 )
|
|
{
|
|
ipMaster = inet_addr( Argv[2] );
|
|
}
|
|
|
|
status = DnssrvResetZoneType(
|
|
pwszServerName,
|
|
Argv[0],
|
|
dwZoneType,
|
|
(ipMaster ? 1 : 0),
|
|
&ipMaster );
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"DNS Server %S reset zone type to %d:\n",
|
|
pwszServerName,
|
|
dwZoneType );
|
|
}
|
|
else
|
|
{
|
|
printf(
|
|
"DNS Server %S failed to reset zone type.\n"
|
|
" Status = %d (0x%08lx)\n",
|
|
pwszServerName,
|
|
status, status );
|
|
}
|
|
return( status );
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
ProcessResetZoneDatabase(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
DWORD fuseDatabase;
|
|
PCHAR pszfileName = NULL;
|
|
|
|
//
|
|
// ResetZoneDatabase <ZoneName> <DsIntegrated> <FileName>
|
|
//
|
|
|
|
if( Argc < 2 || Argc > 3 )
|
|
{
|
|
printf(
|
|
"Usage: dnscmd <Server> ResetZoneDatabase <ZoneName> <fDsIntegrated> <FileName>" );
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
// get database flag
|
|
|
|
fuseDatabase = strtoul(
|
|
Argv[1],
|
|
NULL,
|
|
10 );
|
|
|
|
// get file name
|
|
|
|
if ( Argc == 3 )
|
|
{
|
|
pszfileName = Argv[2];
|
|
}
|
|
|
|
status = DnssrvResetZoneDatabase(
|
|
pwszServerName,
|
|
Argv[0],
|
|
fuseDatabase,
|
|
pszfileName );
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"DNS Server %S reset zone %s database to %s:\n",
|
|
pwszServerName,
|
|
Argv[0],
|
|
fuseDatabase ? "use DS" : pszfileName
|
|
);
|
|
}
|
|
else
|
|
{
|
|
printf(
|
|
"DNS Server %S failed to reset zone database.\n"
|
|
" Status = %d (0x%08lx)\n",
|
|
pwszServerName,
|
|
status, status );
|
|
}
|
|
return( status );
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
//
|
|
// Record viewing commands
|
|
//
|
|
|
|
DNS_STATUS
|
|
ProcessEnumRecords(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
LPSTR pzoneName;
|
|
LPSTR pnodeName;
|
|
BOOL ballocatedNode;
|
|
LPSTR pstartChild = NULL;
|
|
WORD type = DNS_TYPE_ALL;
|
|
DWORD flag = 0;
|
|
DWORD authFlag = 0;
|
|
DWORD bufferLength;
|
|
PBYTE pbuffer;
|
|
LPSTR pszcmd;
|
|
PDNS_RPC_NAME plastName;
|
|
BOOL bcontinue = FALSE;
|
|
BOOL bdetail = FALSE;
|
|
CHAR nextChildName[ DNS_MAX_NAME_BUFFER_LENGTH ];
|
|
|
|
//
|
|
// EnumRecords
|
|
//
|
|
|
|
if ( Argc < 2 || Argc == NEED_HELP_ARGC )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
//
|
|
// read zone and domain name
|
|
//
|
|
|
|
readZoneAndDomainName(
|
|
Argv,
|
|
& pzoneName,
|
|
& pnodeName,
|
|
& ballocatedNode,
|
|
NULL,
|
|
NULL );
|
|
|
|
Argv++;
|
|
Argc--;
|
|
Argv++;
|
|
Argc--;
|
|
|
|
//
|
|
// commands
|
|
//
|
|
// on authority level flags, build separate from final flag
|
|
// so we can determine if authority screen was set, otherwise
|
|
// flag will be set to view all data
|
|
|
|
while ( (LONG)Argc > 0 )
|
|
{
|
|
pszcmd = getCommandName( *Argv );
|
|
if ( !pszcmd )
|
|
{
|
|
goto Help;
|
|
}
|
|
else if ( !_stricmp(pszcmd, "Continue") )
|
|
{
|
|
bcontinue = TRUE;
|
|
}
|
|
else if ( !_stricmp(pszcmd, "Detail") )
|
|
{
|
|
bdetail = TRUE;
|
|
}
|
|
else if ( !_stricmp(pszcmd, "Authority") )
|
|
{
|
|
authFlag |= DNS_RPC_VIEW_AUTHORITY_DATA;
|
|
}
|
|
else if ( !_stricmp(pszcmd, "Glue") )
|
|
{
|
|
authFlag |= DNS_RPC_VIEW_GLUE_DATA;
|
|
}
|
|
else if ( !_stricmp(pszcmd, "Additional") )
|
|
{
|
|
flag |= DNS_RPC_VIEW_ADDITIONAL_DATA;
|
|
}
|
|
else if ( !_stricmp(pszcmd, "Node") )
|
|
{
|
|
flag |= DNS_RPC_VIEW_NO_CHILDREN;
|
|
}
|
|
else if ( !_stricmp(pszcmd, "Root") )
|
|
{
|
|
flag |= DNS_RPC_VIEW_NO_CHILDREN;
|
|
}
|
|
else if ( !_stricmp(pszcmd, "Child") )
|
|
{
|
|
flag |= DNS_RPC_VIEW_ONLY_CHILDREN;
|
|
}
|
|
else if ( !_stricmp(pszcmd, "Type") )
|
|
{
|
|
Argv++;
|
|
Argc--;
|
|
if ( (INT)Argc <= 0 )
|
|
{
|
|
goto Help;
|
|
}
|
|
type = Dns_RecordTypeForName( *Argv, 0 );
|
|
if ( type == 0 )
|
|
{
|
|
type = DNS_TYPE_ALL;
|
|
}
|
|
}
|
|
else if ( !_stricmp(pszcmd, "StartChild") ||
|
|
!_stricmp(pszcmd, "StartPoint") )
|
|
{
|
|
Argv++;
|
|
Argc--;
|
|
if ( ! Argc )
|
|
{
|
|
goto Help;
|
|
}
|
|
pstartChild = *Argv;
|
|
}
|
|
else // unknown command
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
Argc--;
|
|
Argv++;
|
|
}
|
|
|
|
// if no flag entered, view all data
|
|
|
|
if ( authFlag == 0 )
|
|
{
|
|
authFlag = DNS_RPC_VIEW_ALL_DATA;
|
|
}
|
|
flag |= authFlag;
|
|
|
|
|
|
//
|
|
// enumerate records
|
|
// - call in loop to handle error more data case
|
|
//
|
|
|
|
if ( g_UseWmi )
|
|
{
|
|
status = DnscmdWmi_ProcessEnumRecords(
|
|
pzoneName,
|
|
pnodeName,
|
|
bdetail,
|
|
flag );
|
|
}
|
|
else
|
|
{
|
|
while ( 1 )
|
|
{
|
|
status = DnssrvEnumRecords(
|
|
pwszServerName,
|
|
pzoneName,
|
|
pnodeName,
|
|
pstartChild,
|
|
type,
|
|
flag,
|
|
NULL,
|
|
NULL,
|
|
& bufferLength,
|
|
& pbuffer );
|
|
|
|
if ( status == ERROR_SUCCESS ||
|
|
status == ERROR_MORE_DATA )
|
|
{
|
|
plastName = DnsPrint_RpcRecordsInBuffer(
|
|
dnscmd_PrintRoutine,
|
|
dnscmd_PrintContext,
|
|
"Returned records:\n",
|
|
bdetail,
|
|
bufferLength,
|
|
pbuffer );
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
break;
|
|
}
|
|
|
|
// more records to enumerate
|
|
|
|
if ( !plastName )
|
|
{
|
|
break;
|
|
}
|
|
DnssrvCopyRpcNameToBuffer(
|
|
nextChildName,
|
|
plastName );
|
|
|
|
if ( bcontinue )
|
|
{
|
|
pstartChild = nextChildName;
|
|
|
|
DNSDBG( ANY, (
|
|
"Continuing enum at %s\n",
|
|
pstartChild ));
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
printf(
|
|
"More records remain to be enumerated!\n"
|
|
"\n"
|
|
"To enumerate ALL reissue the command with the \"/Continue\" option.\n"
|
|
" OR\n"
|
|
"To enumerate remaining records serially, reissue the command \n"
|
|
"with \"/StartChild %s\" option.\n",
|
|
nextChildName );
|
|
|
|
status = ERROR_SUCCESS;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf(
|
|
"DNS Server failed to enumerate records for node %s.\n"
|
|
" Status = %d (0x%08lx)\n",
|
|
pnodeName,
|
|
status, status );
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return( status );
|
|
|
|
|
|
Help:
|
|
printf( "Usage: DnsCmd <ServerName> /EnumRecords <ZoneName> <NodeName> "
|
|
"[<DataOptions>] [<ViewOptions>]\n"
|
|
" <ZoneName> -- FQDN of zone node to enumerate\n"
|
|
" /RootHints for roots-hints enumeration\n"
|
|
" /Cache for cache enumeration\n"
|
|
" <NodeName> -- name of node whose records will be enumerated\n"
|
|
" - \"@\" for zone root OR\n"
|
|
" - FQDN of a node (name with a '.' at the end) OR\n"
|
|
" - node name relative to the <ZoneName>\n"
|
|
" <DataOptions>: (All data is the default)\n"
|
|
" /Type <RRType> -- enumerate RRs of specific type\n"
|
|
" <RRType> is standard type name; eg. A, NS, SOA, ...\n"
|
|
" /Authority -- include authoritative data\n"
|
|
" /Glue -- include glue data\n"
|
|
" /Additional -- include additional data when enumerating\n"
|
|
" /Node -- only enumerate RRs of the given node\n"
|
|
" /Child -- only enumerate RRs of children of the given node\n"
|
|
" /StartChild <ChildName> -- child name, after which to start enumeration\n"
|
|
" <ViewOptions>:\n"
|
|
" /Continue -- on full buffer condition, continue enum until end of records\n"
|
|
" default is to retrieve only first buffer of data\n"
|
|
" /Detail -- print detailed record node information\n"
|
|
" default is view of records similar to zone file\n\n" );
|
|
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
typedef struct
|
|
{
|
|
LONG ilNodes;
|
|
LONG ilRecords;
|
|
int ilRecurseDepth;
|
|
int ilMaxRecurseDepth;
|
|
} DISP_ZONE_STATS, * PDISP_ZONE_STATS;
|
|
|
|
|
|
PDNS_RPC_NAME
|
|
DNS_API_FUNCTION
|
|
ProcessDisplayAllZoneRecords_Guts(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pPrintContext,
|
|
IN LPSTR pszHeader,
|
|
IN LPSTR pZoneName,
|
|
IN LPSTR pNodeName,
|
|
IN WORD wType,
|
|
IN DWORD dwFlags,
|
|
IN BOOL fDetail,
|
|
IN PDISP_ZONE_STATS pStats
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The guts of the dump cache functionality.
|
|
|
|
Arguments:
|
|
|
|
PrintRoutine -- printf like routine to print with
|
|
|
|
pszHeader -- header string - will only be output if there is at least
|
|
one record in the result (empty or placeholder nodes don't count)
|
|
|
|
fDetail -- if TRUE print detailed record info
|
|
|
|
dwBufferLength -- buffer length
|
|
|
|
abBuffer -- ptr to RPC buffer
|
|
|
|
Return Value:
|
|
|
|
Ptr to last RPC node name in buffer.
|
|
NULL on error.
|
|
|
|
--*/
|
|
{
|
|
PBYTE pcurrent;
|
|
PBYTE pstop;
|
|
PDNS_RPC_NAME plastName = NULL;
|
|
INT recordCount;
|
|
PCHAR precordHeader;
|
|
DNS_STATUS status;
|
|
PBYTE pbuffer = NULL;
|
|
DWORD dwbufferSize = 0;
|
|
CHAR nextChildName[ DNS_MAX_NAME_BUFFER_LENGTH ];
|
|
LPSTR pstartChild = NULL;
|
|
BOOL fdisplayedHeader = FALSE;
|
|
|
|
if ( pStats )
|
|
{
|
|
if ( ++pStats->ilRecurseDepth > pStats->ilMaxRecurseDepth )
|
|
{
|
|
pStats->ilMaxRecurseDepth = pStats->ilRecurseDepth;
|
|
}
|
|
// printf( "GUTS: depth %d: %s\n", pStats->ilRecurseDepth, pNodeName );
|
|
}
|
|
|
|
while ( 1 )
|
|
{
|
|
if ( pbuffer )
|
|
{
|
|
MIDL_user_free( pbuffer );
|
|
pbuffer = NULL;
|
|
}
|
|
|
|
status = DnssrvEnumRecords(
|
|
pwszServerName,
|
|
pZoneName,
|
|
pNodeName,
|
|
pstartChild,
|
|
wType,
|
|
dwFlags,
|
|
NULL,
|
|
NULL,
|
|
&dwbufferSize,
|
|
&pbuffer );
|
|
|
|
if ( status == ERROR_SUCCESS || status == ERROR_MORE_DATA )
|
|
{
|
|
DnsPrint_Lock();
|
|
|
|
if ( !pbuffer )
|
|
{
|
|
PrintRoutine( pPrintContext, "NULL record buffer ptr.\n" );
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// find stop byte
|
|
//
|
|
|
|
ASSERT( DNS_IS_DWORD_ALIGNED( pbuffer ) );
|
|
|
|
pstop = pbuffer + dwbufferSize;
|
|
pcurrent = pbuffer;
|
|
|
|
//
|
|
// loop until out of nodes
|
|
//
|
|
|
|
while ( pcurrent < pstop )
|
|
{
|
|
PDNS_RPC_NODE pcurrNode = ( PDNS_RPC_NODE ) pcurrent;
|
|
CHAR szchildNodeName[ DNS_MAX_NAME_BUFFER_LENGTH ] = "";
|
|
|
|
//
|
|
// print owner node
|
|
// - if NOT printing detail and no records
|
|
// (essentially domain nodes) then no node print
|
|
//
|
|
|
|
plastName = &pcurrNode->dnsNodeName;
|
|
|
|
recordCount = pcurrNode->wRecordCount;
|
|
|
|
if ( pStats )
|
|
{
|
|
++pStats->ilNodes;
|
|
pStats->ilRecords += recordCount;
|
|
}
|
|
|
|
// Display header before printing the first record.
|
|
if ( recordCount && !fdisplayedHeader )
|
|
{
|
|
PrintRoutine( pPrintContext, ( pszHeader ? pszHeader : "" ) );
|
|
fdisplayedHeader = TRUE;
|
|
}
|
|
|
|
|
|
if ( fDetail )
|
|
{
|
|
DnsPrint_RpcNode(
|
|
PrintRoutine, pPrintContext,
|
|
NULL,
|
|
(PDNS_RPC_NODE)pcurrent );
|
|
if ( recordCount == 0 )
|
|
{
|
|
PrintRoutine( pPrintContext, "\n" );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( recordCount != 0 )
|
|
{
|
|
DnsPrint_RpcName(
|
|
PrintRoutine, pPrintContext,
|
|
NULL,
|
|
plastName,
|
|
NULL );
|
|
}
|
|
}
|
|
|
|
if ( pcurrNode->dwFlags & DNS_RPC_FLAG_NODE_STICKY )
|
|
{
|
|
//
|
|
// Set up child node name before we start iterating
|
|
// records at this name.
|
|
//
|
|
|
|
memcpy(
|
|
szchildNodeName,
|
|
pcurrNode->dnsNodeName.achName,
|
|
pcurrNode->dnsNodeName.cchNameLength );
|
|
szchildNodeName[ pcurrNode->dnsNodeName.cchNameLength ] = '.';
|
|
szchildNodeName[ pcurrNode->dnsNodeName.cchNameLength + 1 ] = '\0';
|
|
if ( strcmp( pNodeName, "@" ) != 0 )
|
|
{
|
|
strcat( szchildNodeName, pNodeName );
|
|
}
|
|
if ( szchildNodeName[ strlen( szchildNodeName ) - 1 ] == '.' )
|
|
{
|
|
szchildNodeName[ strlen( szchildNodeName ) - 1 ] = '\0';
|
|
}
|
|
}
|
|
|
|
pcurrent += pcurrNode->wLength;
|
|
pcurrent = DNS_NEXT_DWORD_PTR(pcurrent);
|
|
|
|
//
|
|
// Print all records at this node.
|
|
//
|
|
|
|
precordHeader = "";
|
|
|
|
while( recordCount-- )
|
|
{
|
|
if ( pcurrent >= pstop )
|
|
{
|
|
PrintRoutine( pPrintContext,
|
|
"ERROR: Bogus buffer at %p\n"
|
|
" Expect record at %p past buffer end at %p\n"
|
|
" with %d records remaining.\n",
|
|
pbuffer,
|
|
(PDNS_RPC_RECORD) pcurrent,
|
|
pstop,
|
|
recordCount+1 );
|
|
|
|
ASSERT( FALSE );
|
|
break;
|
|
}
|
|
|
|
DnsPrint_RpcRecord(
|
|
PrintRoutine, pPrintContext,
|
|
precordHeader,
|
|
fDetail,
|
|
(PDNS_RPC_RECORD)pcurrent );
|
|
|
|
precordHeader = "\t\t";
|
|
|
|
pcurrent += ((PDNS_RPC_RECORD)pcurrent)->wDataLength
|
|
+ SIZEOF_DNS_RPC_RECORD_HEADER;
|
|
|
|
pcurrent = DNS_NEXT_DWORD_PTR(pcurrent);
|
|
}
|
|
|
|
//
|
|
// Recurse on this node if it has children.
|
|
//
|
|
|
|
if ( *szchildNodeName )
|
|
{
|
|
CHAR szheader[ DNS_MAX_NAME_BUFFER_LENGTH + 100 ] = "";
|
|
|
|
sprintf( szheader, "$ORIGIN %s\n", szchildNodeName );
|
|
|
|
ProcessDisplayAllZoneRecords_Guts(
|
|
PrintRoutine,
|
|
pPrintContext,
|
|
szheader,
|
|
pZoneName,
|
|
szchildNodeName,
|
|
wType,
|
|
dwFlags,
|
|
fDetail,
|
|
pStats );
|
|
}
|
|
}
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
break;
|
|
}
|
|
|
|
// more records to enumerate
|
|
|
|
if ( !plastName )
|
|
{
|
|
break;
|
|
}
|
|
DnssrvCopyRpcNameToBuffer(
|
|
nextChildName,
|
|
plastName );
|
|
|
|
pstartChild = nextChildName;
|
|
|
|
DNSDBG( ANY, (
|
|
"Continuing enum at %s\n",
|
|
pstartChild ));
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
printf(
|
|
"DNS Server failed to enumerate records for node %s.\n"
|
|
" Status = %s %d (0x%08lx)\n",
|
|
pNodeName,
|
|
Dns_StatusString( status ),
|
|
status, status );
|
|
}
|
|
break;
|
|
}
|
|
if ( pbuffer )
|
|
{
|
|
MIDL_user_free( pbuffer );
|
|
}
|
|
|
|
Done:
|
|
|
|
DnsPrint_Unlock();
|
|
|
|
if ( pStats )
|
|
{
|
|
--pStats->ilRecurseDepth;
|
|
}
|
|
|
|
return plastName;
|
|
} // ProcessDisplayAllZoneRecords_Guts
|
|
|
|
|
|
DNS_STATUS
|
|
ProcessDisplayAllZoneRecords(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
LPSTR pszcmd;
|
|
LPSTR pszzoneName = NULL;
|
|
BOOL bdetail = FALSE;
|
|
time_t now;
|
|
CHAR sznow[ 30 ];
|
|
CHAR szheader[ 256 ];
|
|
size_t len;
|
|
WCHAR wszserverName[ DNS_MAX_NAME_BUFFER_LENGTH ] = L"";
|
|
PWSTR pwszserverDisplayName = pwszServerName;
|
|
DISP_ZONE_STATS displayZoneStats = { 0 };
|
|
|
|
//
|
|
// /ZonePrint [ZoneName] /Detail
|
|
//
|
|
|
|
if ( Argc > 3 || Argc == NEED_HELP_ARGC )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
//
|
|
// Parse arguments.
|
|
//
|
|
|
|
while ( Argc )
|
|
{
|
|
pszcmd = getCommandName( *Argv );
|
|
if ( !pszcmd && !pszzoneName )
|
|
{
|
|
pszzoneName = *Argv;
|
|
}
|
|
else if ( _strnicmp( pszcmd, "D", 1 ) == 0 )
|
|
{
|
|
bdetail = TRUE;
|
|
}
|
|
else
|
|
{
|
|
goto Help;
|
|
}
|
|
Argv++;
|
|
Argc--;
|
|
}
|
|
if ( !pszzoneName )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
// Get time string.
|
|
|
|
time( &now );
|
|
strcpy( sznow, asctime( gmtime( &now ) ) );
|
|
len = strlen( sznow ) - 1;
|
|
if ( sznow[ len ] == '\n' )
|
|
{
|
|
sznow[ len ] = '\0';
|
|
}
|
|
|
|
// Get local hostname string.
|
|
|
|
if ( wcscmp( pwszServerName, L"." ) == 0 )
|
|
{
|
|
DWORD bufsize = sizeof( wszserverName ) /
|
|
sizeof( wszserverName[ 0 ] );
|
|
|
|
if ( GetComputerNameExW(
|
|
ComputerNamePhysicalDnsFullyQualified,
|
|
wszserverName,
|
|
&bufsize ) )
|
|
{
|
|
pwszserverDisplayName = wszserverName;
|
|
}
|
|
}
|
|
|
|
sprintf(
|
|
szheader,
|
|
";\n"
|
|
"; Zone: %s\n"
|
|
"; Server: %S\n"
|
|
"; Time: %s UTC\n"
|
|
";\n",
|
|
pszzoneName,
|
|
pwszserverDisplayName,
|
|
sznow );
|
|
|
|
if ( ProcessDisplayAllZoneRecords_Guts(
|
|
dnscmd_PrintRoutine,
|
|
dnscmd_PrintContext,
|
|
szheader,
|
|
pszzoneName,
|
|
"@",
|
|
DNS_TYPE_ALL,
|
|
DNS_RPC_VIEW_ALL_DATA,
|
|
bdetail,
|
|
&displayZoneStats ) )
|
|
{
|
|
dnscmd_PrintRoutine(
|
|
dnscmd_PrintContext,
|
|
";\n"
|
|
"; Finished zone iteration: %lu nodes, %lu records in %d seconds\n"
|
|
";\n",
|
|
displayZoneStats.ilNodes,
|
|
displayZoneStats.ilRecords,
|
|
time( NULL ) - now );
|
|
}
|
|
|
|
return status;
|
|
|
|
Help:
|
|
printf(
|
|
"Usage: DnsCmd <ServerName> /ZonePrint [<ZoneName>] [/Detail]\n"
|
|
" <ZoneName> -- name of the zone (use ..Cache for DNS server cache)\n"
|
|
" /Detail -- explicit RPC node contents\n" );
|
|
return ERROR_SUCCESS;
|
|
} // ProcessDisplayAllZoneRecords
|
|
|
|
|
|
|
|
#if 0
|
|
DNS_STATUS
|
|
ProcessEnumRecordsEx(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
LPSTR pszNodeName;
|
|
LPSTR pszStartChild = NULL;
|
|
WORD type = DNS_TYPE_ALL;
|
|
DWORD dwFlag = 0;
|
|
PDNS_NODE pnodeFirst = NULL;
|
|
PDNS_NODE pnodeLast;
|
|
|
|
//
|
|
// EnumNodeRecords
|
|
//
|
|
|
|
if( Argc < 1 || Argc > 4 )
|
|
{
|
|
printf( "Usage: dnscmd <ServerName> EnumRecordsEx <NodeName> "
|
|
" [<dwFlag>] [<wType>] [<ChildStartName>]\n"
|
|
" <NodeName> -- FQDN of node to enumerate\n"
|
|
" <dwFlag> -- enumeration flags; default is enumeration of \n"
|
|
" all records (cached, authoritative, root hint data) at node\n"
|
|
" and enumeration of node and any leaf children\n"
|
|
" Flag is combination of these values:\n"
|
|
" AUTHORITY_DATA = %08lx\n"
|
|
" CACHE_DATA = %08lx\n"
|
|
" ROOT_HINT_DATA = %08lx\n"
|
|
" ADDITIONAL_DATA = %08lx\n"
|
|
" ALL_DATA = %08lx\n"
|
|
" NO_CHILDREN = %08lx\n"
|
|
" ONLY_CHILDREN = %08lx\n"
|
|
" <wType> -- type name to enumerate; default is ALL types\n"
|
|
" <ChildStartName> -- child name to restart enumeration at\n",
|
|
DNS_RPC_VIEW_AUTHORITY_DATA ,
|
|
DNS_RPC_VIEW_CACHE_DATA ,
|
|
DNS_RPC_VIEW_ROOT_HINT_DATA ,
|
|
DNS_RPC_VIEW_ADDITIONAL_DATA ,
|
|
DNS_RPC_VIEW_ALL_DATA ,
|
|
DNS_RPC_VIEW_NO_CHILDREN ,
|
|
DNS_RPC_VIEW_ONLY_CHILDREN
|
|
);
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
// set node name
|
|
|
|
pszNodeName = Argv[0];
|
|
|
|
// set view options
|
|
|
|
if ( Argc >= 2 )
|
|
{
|
|
dwFlag = strtoul(
|
|
Argv[1],
|
|
NULL,
|
|
16 );
|
|
}
|
|
|
|
// set the type
|
|
|
|
if ( Argc >= 3 )
|
|
{
|
|
type = Dns_RecordTypeForName( Argv[2], 0 );
|
|
if ( type == 0 )
|
|
{
|
|
type = DNS_TYPE_ALL;
|
|
}
|
|
}
|
|
|
|
// set child name
|
|
|
|
if ( Argc >= 4 )
|
|
{
|
|
pszStartChild = Argv[3];
|
|
}
|
|
|
|
status = DnssrvEnumRecordsEx(
|
|
pwszServerName,
|
|
NULL,
|
|
pszNodeName,
|
|
pszStartChild,
|
|
type,
|
|
dwFlag,
|
|
NULL,
|
|
NULL,
|
|
& pnodeFirst,
|
|
& pnodeLast );
|
|
|
|
if ( status == ERROR_SUCCESS || status == ERROR_MORE_DATA )
|
|
{
|
|
DnsPrint_NodeList(
|
|
dnscmd_PrintRoutine,
|
|
dnscmd_PrintContext,
|
|
"Returned node list: ",
|
|
pnodeFirst,
|
|
TRUE // print records
|
|
);
|
|
}
|
|
else
|
|
{
|
|
printf(
|
|
"DNS Server failed to enumerate records for node %s.\n"
|
|
" Status = %d (0x%08lx)\n",
|
|
pszNodeName,
|
|
status, status );
|
|
}
|
|
|
|
DnssrvFreeNodeList(
|
|
pnodeFirst,
|
|
TRUE // free records also
|
|
);
|
|
|
|
return( status );
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
ProcessSbsRegister(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
IP_ADDRESS hostIp;
|
|
DWORD ttl;
|
|
|
|
//
|
|
// SbsRegister
|
|
//
|
|
|
|
if ( Argc < 2 || Argc == NEED_HELP_ARGC )
|
|
{
|
|
goto Usage;
|
|
}
|
|
|
|
// client host IP
|
|
|
|
hostIp = inet_addr( Argv[3] );
|
|
if ( hostIp == (-1) )
|
|
{
|
|
goto Usage;
|
|
}
|
|
|
|
// record TTL
|
|
|
|
ttl = strtoul(
|
|
Argv[3],
|
|
NULL,
|
|
10 );
|
|
|
|
status = DnssrvSbsAddClientToIspZone(
|
|
pwszServerName,
|
|
Argv[0],
|
|
Argv[1],
|
|
Argv[2],
|
|
hostIp,
|
|
ttl );
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"DNS Server %S registered SAM records for client %s:\n",
|
|
pwszServerName,
|
|
Argv[1] );
|
|
}
|
|
else
|
|
{
|
|
printf(
|
|
"DNS Server %S failed to register SAM records for %s.\n"
|
|
" Status = %d (0x%08lx)\n",
|
|
pwszServerName,
|
|
Argv[1],
|
|
status, status );
|
|
}
|
|
return( status );
|
|
|
|
Usage:
|
|
|
|
printf(
|
|
"Usage: dnscmd <Server> /SbsRegister <IspZoneName> <Client> <ClientHost> <HostIP> <TTL>\n"
|
|
" <Server> -- server name (DNS, netBIOS or IP)\n"
|
|
" <IspZoneName> -- full DNS name of ISP's zone\n"
|
|
" <Client> -- client name (not FQDN)\n"
|
|
" <ClientHost> -- client host name (not FQDN)\n"
|
|
" <HostIP> -- client host IP\n"
|
|
" <Ttl> -- TTL for records\n"
|
|
"\n" );
|
|
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
ProcessSbsDeleteRecord(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
WORD type;
|
|
IP_ADDRESS hostIp = 0;
|
|
LPSTR pszdata = NULL;
|
|
|
|
//
|
|
// SbsRegister
|
|
//
|
|
|
|
if ( Argc < 5 || Argc == NEED_HELP_ARGC )
|
|
{
|
|
goto Usage;
|
|
}
|
|
|
|
// type to delete
|
|
|
|
type = Dns_RecordTypeForName( Argv[3], 0 );
|
|
if ( type == 0 )
|
|
{
|
|
goto Usage;
|
|
}
|
|
|
|
// if A record, then data will be IP address, otherwise it is DNS name
|
|
|
|
if ( type == DNS_TYPE_A )
|
|
{
|
|
hostIp = inet_addr( Argv[4] );
|
|
if ( hostIp == (-1) )
|
|
{
|
|
goto Usage;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pszdata = Argv[4];
|
|
}
|
|
|
|
status = DnssrvSbsDeleteRecord(
|
|
pwszServerName,
|
|
Argv[0],
|
|
Argv[1],
|
|
Argv[2],
|
|
type,
|
|
pszdata,
|
|
hostIp );
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"DNS Server %S deleted SAM record at %s in client domain %s:\n",
|
|
pwszServerName,
|
|
Argv[2],
|
|
Argv[1] );
|
|
}
|
|
else
|
|
{
|
|
printf(
|
|
"DNS Server %S failed to delete SAM record at %s in domain %s.\n"
|
|
" Status = %d (0x%08lx)\n",
|
|
pwszServerName,
|
|
Argv[2],
|
|
Argv[1],
|
|
status, status );
|
|
}
|
|
return( status );
|
|
|
|
Usage:
|
|
|
|
printf(
|
|
"Usage: DnsCmd <Server> /SbsDeleteA <ZoneName> <Domain> <Host> <Type> <Data>\n"
|
|
" <Server> -- server name (DNS, netBIOS or IP)\n"
|
|
" <ZoneName> -- full DNS name of ISP's zone\n"
|
|
" <Client> -- client name (not FQDN)\n"
|
|
" <Host> -- client host name (not FQDN)\n"
|
|
" <Type> -- record type (ex. A, NS, CNAME)\n"
|
|
" <HostIP> -- client host IP\n"
|
|
"\n" );
|
|
|
|
return( ERROR_SUCCESS );
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Directory partition operations
|
|
//
|
|
|
|
DNS_STATUS
|
|
ProcessEnumDirectoryPartitions(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
PDNS_RPC_DP_LIST pDpList = NULL;
|
|
LPSTR pszcmd;
|
|
BOOL bcustomOnly = FALSE;
|
|
|
|
//
|
|
// Command format: /EnumDirectoryPartitions [filter strings]
|
|
//
|
|
//
|
|
//
|
|
|
|
if ( Argc > 1 || Argc == NEED_HELP_ARGC )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
if ( Argc == 1 )
|
|
{
|
|
pszcmd = getCommandName( *Argv );
|
|
if ( _strnicmp( pszcmd, "Cust",4 ) == 0 )
|
|
{
|
|
bcustomOnly = TRUE;
|
|
}
|
|
Argv++;
|
|
Argc--;
|
|
}
|
|
|
|
status = DnssrvEnumDirectoryPartitions(
|
|
pwszServerName,
|
|
0, // filter
|
|
&pDpList );
|
|
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"DnssrvEnumDirectoryPartitions() failed.\n"
|
|
" Status = %d (0x%08lx)\n",
|
|
status, status );
|
|
goto Cleanup;
|
|
}
|
|
else
|
|
{
|
|
DnsPrint_RpcDpList(
|
|
dnscmd_PrintRoutine,
|
|
dnscmd_PrintContext,
|
|
"Enumerated directory partition list:\n",
|
|
pDpList );
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
//
|
|
// deallocate zone list
|
|
//
|
|
|
|
DnssrvFreeDirectoryPartitionList( pDpList );
|
|
return status;
|
|
|
|
Help:
|
|
|
|
printf( "Usage: DnsCmd <ServerName> /EnumDirectoryPartitions [/Custom]\n" );
|
|
return status;
|
|
} // ProcessEnumDirectoryPartitions
|
|
|
|
|
|
DNS_STATUS
|
|
ProcessDirectoryPartitionInfo(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
PDNS_RPC_DP_INFO pDpInfo = NULL;
|
|
BOOL bdetail = FALSE;
|
|
LPSTR pszfqdn;
|
|
LPSTR pszcmd;
|
|
|
|
//
|
|
// Command format: /DirectoryPartitionInfo fqdn [/Detail]
|
|
//
|
|
// Currently no arguments.
|
|
//
|
|
|
|
if ( Argc == 0 )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
pszfqdn = *Argv;
|
|
Argv++;
|
|
Argc--;
|
|
|
|
if ( Argc == 1 )
|
|
{
|
|
pszcmd = getCommandName( *Argv );
|
|
if ( _stricmp( pszcmd, "Detail" ) == 0 )
|
|
{
|
|
bdetail = TRUE;
|
|
}
|
|
Argv++;
|
|
Argc--;
|
|
}
|
|
|
|
status = DnssrvDirectoryPartitionInfo(
|
|
pwszServerName,
|
|
pszfqdn,
|
|
&pDpInfo );
|
|
|
|
if ( status != ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"DnssrvDirectoryPartitionInfo() failed.\n"
|
|
" Status = %d (0x%08lx)\n",
|
|
status, status );
|
|
goto Cleanup;
|
|
}
|
|
else
|
|
{
|
|
DnsPrint_RpcDpInfo(
|
|
dnscmd_PrintRoutine,
|
|
dnscmd_PrintContext,
|
|
"Directory partition info:",
|
|
pDpInfo,
|
|
!bdetail );
|
|
}
|
|
|
|
Cleanup:
|
|
|
|
DnssrvFreeDirectoryPartitionInfo( pDpInfo );
|
|
return status;
|
|
|
|
Help:
|
|
|
|
printf( "Usage: DnsCmd <ServerName> /DirectoryPartitionInfo <FQDN of partition> [/Detail]\n" );
|
|
return status;
|
|
} // ProcessDirectoryPartitionInfo
|
|
|
|
|
|
DNS_STATUS
|
|
ProcessCreateDirectoryPartition(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
LPSTR pszDpFqdn;
|
|
|
|
//
|
|
// Command format: /CreateDirectoryPartition DP-FQDN [/Create]
|
|
//
|
|
|
|
if ( Argc != 1 )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
pszDpFqdn = Argv[ 0 ];
|
|
|
|
status = DnssrvEnlistDirectoryPartition(
|
|
pwszServerName,
|
|
DNS_DP_OP_CREATE,
|
|
pszDpFqdn );
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"DNS Server %S created directory partition: %s\n",
|
|
pwszServerName,
|
|
pszDpFqdn );
|
|
}
|
|
else
|
|
{
|
|
printf(
|
|
"DnssrvEnlistDirectoryPartition( create, %s ) failed.\n"
|
|
" Status = %d (0x%08lx)\n",
|
|
pszDpFqdn,
|
|
status, status );
|
|
}
|
|
|
|
return status;
|
|
|
|
Help:
|
|
|
|
printf( "Usage: DnsCmd <ServerName> /CreateDirectoryPartition <FQDN of partition>\n" );
|
|
return status;
|
|
} // ProcessCreateDirectoryPartition
|
|
|
|
|
|
DNS_STATUS
|
|
ProcessDeleteDirectoryPartition(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
LPSTR pszDpFqdn;
|
|
|
|
//
|
|
// Command format: /DeleteDirectoryPartition DP-FQDN [/Create]
|
|
//
|
|
|
|
if ( Argc != 1 )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
pszDpFqdn = Argv[ 0 ];
|
|
|
|
status = DnssrvEnlistDirectoryPartition(
|
|
pwszServerName,
|
|
DNS_DP_OP_DELETE,
|
|
pszDpFqdn );
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"DNS Server %S deleted directory partition: %s\n",
|
|
pwszServerName,
|
|
pszDpFqdn );
|
|
}
|
|
else
|
|
{
|
|
printf(
|
|
"DnssrvEnlistDirectoryPartition( delete, %s ) failed.\n"
|
|
" Status = %d (0x%08lx)\n",
|
|
pszDpFqdn,
|
|
status, status );
|
|
}
|
|
|
|
return status;
|
|
|
|
Help:
|
|
|
|
printf( "Usage: DnsCmd <ServerName> /DeleteDirectoryPartition <FQDN of partition>\n" );
|
|
return status;
|
|
} // ProcessDeleteDirectoryPartition
|
|
|
|
|
|
DNS_STATUS
|
|
ProcessEnlistDirectoryPartition(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
LPSTR pszDpFqdn;
|
|
|
|
//
|
|
// Command format: /EnlistDirectoryPartition DP-FQDN [/Create]
|
|
//
|
|
|
|
if ( Argc != 1 )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
pszDpFqdn = Argv[ 0 ];
|
|
|
|
status = DnssrvEnlistDirectoryPartition(
|
|
pwszServerName,
|
|
DNS_DP_OP_ENLIST,
|
|
pszDpFqdn );
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"DNS Server %S enlisted directory partition: %s\n",
|
|
pwszServerName,
|
|
pszDpFqdn );
|
|
}
|
|
else
|
|
{
|
|
printf(
|
|
"DnssrvEnlistDirectoryPartition( enlist, %s ) failed.\n"
|
|
" Status = %d (0x%08lx)\n",
|
|
pszDpFqdn,
|
|
status, status );
|
|
}
|
|
|
|
return status;
|
|
|
|
Help:
|
|
|
|
printf( "Usage: DnsCmd <ServerName> /EnlistDirectoryPartition <FQDN of partition>\n" );
|
|
return status;
|
|
} // ProcessEnlistDirectoryPartition
|
|
|
|
|
|
DNS_STATUS
|
|
ProcessUnenlistDirectoryPartition(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
LPSTR pszDpFqdn;
|
|
|
|
//
|
|
// Command format: /UnenlistDirectoryPartition DP-FQDN [/Create]
|
|
//
|
|
|
|
if ( Argc != 1 )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
pszDpFqdn = Argv[ 0 ];
|
|
|
|
status = DnssrvEnlistDirectoryPartition(
|
|
pwszServerName,
|
|
DNS_DP_OP_UNENLIST,
|
|
pszDpFqdn );
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"DNS Server %S unenlisted directory partition: %s\n",
|
|
pwszServerName,
|
|
pszDpFqdn );
|
|
}
|
|
else
|
|
{
|
|
printf(
|
|
"DnssrvEnlistDirectoryPartition( unenlist, %s ) failed.\n"
|
|
" Status = %d (0x%08lx)\n",
|
|
pszDpFqdn,
|
|
status, status );
|
|
}
|
|
|
|
return status;
|
|
|
|
Help:
|
|
|
|
printf( "Usage: DnsCmd <ServerName> /UnenlistDirectoryPartition <FQDN of partition>\n" );
|
|
return status;
|
|
} // ProcessUnenlistDirectoryPartition
|
|
|
|
|
|
|
|
DNS_STATUS
|
|
ProcessCreateBuiltinDirectoryPartitions(
|
|
IN DWORD Argc,
|
|
IN LPSTR * Argv
|
|
)
|
|
{
|
|
DNS_STATUS status = ERROR_SUCCESS;
|
|
DWORD dwopcode = DNS_DP_OP_CREATE_DOMAIN;
|
|
PCHAR psz;
|
|
|
|
//
|
|
// Command format: /CreateBuiltinDPs [/Forest | /AllDomains]
|
|
//
|
|
// No argument - create domain DP
|
|
// /Forest - create forest DP
|
|
// /AllDomains - create domain DPs for all domains in forest
|
|
//
|
|
|
|
if ( Argc > 1 || Argc == NEED_HELP_ARGC )
|
|
{
|
|
goto Help;
|
|
}
|
|
|
|
if ( ( psz = getCommandName( Argv[ 0 ] ) ) != NULL )
|
|
{
|
|
if ( _strnicmp( psz, "All", 3 ) == 0 )
|
|
{
|
|
dwopcode = DNS_DP_OP_CREATE_ALL_DOMAINS;
|
|
}
|
|
else if ( _strnicmp( psz, "For", 3 ) == 0 )
|
|
{
|
|
dwopcode = DNS_DP_OP_CREATE_FOREST;
|
|
}
|
|
}
|
|
|
|
status = DnssrvEnlistDirectoryPartition(
|
|
pwszServerName,
|
|
dwopcode,
|
|
NULL );
|
|
|
|
if ( status == ERROR_SUCCESS )
|
|
{
|
|
printf(
|
|
"DNS Server %S completed operation successfully\n",
|
|
pwszServerName );
|
|
}
|
|
else
|
|
{
|
|
printf(
|
|
"DnssrvEnlistDirectoryPartition failed.\n"
|
|
" Status = %d (0x%08lx)\n",
|
|
status, status );
|
|
}
|
|
|
|
return status;
|
|
|
|
Help:
|
|
|
|
printf(
|
|
"Usage: DnsCmd <ServerName> /CreateBuiltinDirectoryPartitions [<Option>]\n"
|
|
" With no argument creates the built-in DNS directory partition for the domain.\n"
|
|
" /Forest -- create built-in DNS directory partition for the forest\n"
|
|
" /AllDomains -- create built-in DNS partitions for all domains in the forest\n" );
|
|
return status;
|
|
} // ProcessCreateBuiltinDirectoryPartitions
|
|
|
|
|
|
|
|
//
|
|
// Command table
|
|
// Have this down here so no need for private protos on dispatch functions.
|
|
//
|
|
// DEVNOTE: all this needs internationalization
|
|
//
|
|
|
|
COMMAND_INFO GlobalCommandInfo[] =
|
|
{
|
|
// Zone + Server operations
|
|
|
|
// Server and Zone Operations
|
|
|
|
{ "/Info",
|
|
ProcessInfo,
|
|
"Get server information"
|
|
},
|
|
{ "/Config",
|
|
ProcessResetProperty,
|
|
"Reset server or zone configuration"
|
|
},
|
|
{ "/EnumZones",
|
|
ProcessEnumZones,
|
|
"Enumerate zones"
|
|
},
|
|
|
|
// Server Operations
|
|
|
|
{ "/Statistics",
|
|
ProcessStatistics,
|
|
"Query/clear server statistics data"
|
|
},
|
|
{ "/ClearCache",
|
|
ProcessSimpleServerOperation,
|
|
"Clear DNS server cache"
|
|
},
|
|
{ "/WriteBackFiles",
|
|
ProcessWriteBackFiles,
|
|
"Write back all zone or root-hint datafile(s)"
|
|
},
|
|
{ "/StartScavenging",
|
|
ProcessSimpleServerOperation,
|
|
"Initiates server scavenging"
|
|
},
|
|
|
|
// Server Property Reset
|
|
|
|
{ "/ResetListenAddresses",
|
|
ProcessResetListenAddresses,
|
|
"Set server IP address(es) to serve DNS requests"
|
|
},
|
|
{ "/ResetForwarders",
|
|
ProcessResetForwarders,
|
|
"Set DNS servers to forward recursive queries to"
|
|
},
|
|
|
|
// Zone Operations
|
|
|
|
{ "/ZoneInfo",
|
|
ProcessZoneInfo,
|
|
"View zone information"
|
|
},
|
|
{ "/ZoneAdd",
|
|
ProcessZoneAdd,
|
|
"Create a new zone on the DNS server"
|
|
},
|
|
{ "/ZoneDelete",
|
|
ProcessZoneDelete,
|
|
"Delete a zone from DNS server or DS"
|
|
},
|
|
{ "/ZonePause",
|
|
ProcessZonePause,
|
|
"Pause a zone"
|
|
},
|
|
{ "/ZoneResume",
|
|
ProcessZoneResume,
|
|
"Resume a zone"
|
|
},
|
|
{ "/ZoneReload",
|
|
ProcessZoneReload,
|
|
"Reload zone from its database (file or DS)"
|
|
},
|
|
{ "/ZoneWriteBack",
|
|
ProcessZoneWriteBack,
|
|
"Write back zone to file"
|
|
},
|
|
{ "/ZoneRefresh",
|
|
ProcessZoneRefresh,
|
|
"Force refresh of secondary zone from master"
|
|
},
|
|
{ "/ZoneUpdateFromDs",
|
|
ProcessZoneUpdateFromDs,
|
|
"Update a DS integrated zone by data from DS"
|
|
},
|
|
{ "/ZonePrint",
|
|
ProcessDisplayAllZoneRecords,
|
|
"Display all records in the zone"
|
|
},
|
|
|
|
// Zone Property Reset
|
|
|
|
{ "/ZoneResetType",
|
|
ProcessZoneResetType,
|
|
"Change zone type"
|
|
},
|
|
{ "/ZoneResetSecondaries",
|
|
ProcessZoneResetSecondaries,
|
|
"Reset secondary\\notify information for a zone"
|
|
},
|
|
{ "/ZoneResetScavengeServers",
|
|
ProcessZoneResetScavengeServers,
|
|
"Reset scavenging servers for a zone"
|
|
},
|
|
{ "/ZoneResetMasters",
|
|
ProcessZoneResetMasters,
|
|
"Reset secondary zone's master servers"
|
|
},
|
|
#if 0
|
|
{ "/ZoneRename",
|
|
ProcessZoneRename,
|
|
"Rename a zone"
|
|
},
|
|
#endif
|
|
{ "/ZoneExport",
|
|
ProcessZoneExport,
|
|
"Export a zone to file"
|
|
},
|
|
#if 0
|
|
{ "/ZoneResetAging",
|
|
ProcessZoneResetAging,
|
|
"Reset aging\scavenging information for a zone"
|
|
},
|
|
#endif
|
|
{ "/ZoneChangeDirectoryPartition",
|
|
ProcessZoneChangeDirectoryPartition,
|
|
"Move a zone to another directory partition"
|
|
},
|
|
|
|
// Record Operations
|
|
|
|
{ "/EnumRecords",
|
|
ProcessEnumRecords,
|
|
"Enumerate records at a name"
|
|
},
|
|
{ "/RecordAdd",
|
|
ProcessRecordAdd,
|
|
"Create a record in zone or RootHints"
|
|
},
|
|
{ "/RecordDelete",
|
|
ProcessRecordDelete,
|
|
"Delete a record from zone, RootHints or cache"
|
|
},
|
|
{ "/NodeDelete",
|
|
ProcessNodeDelete,
|
|
"Delete all records at a name"
|
|
},
|
|
{ "/AgeAllRecords",
|
|
ProcessAgeAllRecords,
|
|
"Force aging on node(s) in zone"
|
|
},
|
|
|
|
// Directory partitions
|
|
|
|
{
|
|
"/EnumDirectoryPartitions",
|
|
ProcessEnumDirectoryPartitions,
|
|
"Enumerate directory partitions"
|
|
},
|
|
{
|
|
"/DirectoryPartitionInfo",
|
|
ProcessDirectoryPartitionInfo,
|
|
"Get info on a directory partition"
|
|
},
|
|
{
|
|
"/CreateDirectoryPartition",
|
|
ProcessCreateDirectoryPartition,
|
|
"Create a directory partition"
|
|
},
|
|
{
|
|
"/DeleteDirectoryPartition",
|
|
ProcessDeleteDirectoryPartition,
|
|
"Delete a directory partition"
|
|
},
|
|
{
|
|
"/EnlistDirectoryPartition",
|
|
ProcessEnlistDirectoryPartition,
|
|
"Add DNS server to partition replication scope"
|
|
},
|
|
{
|
|
"/UnenlistDirectoryPartition",
|
|
ProcessUnenlistDirectoryPartition,
|
|
"Remove DNS server from replication scope"
|
|
},
|
|
#if DBG
|
|
{ "/CreateBuiltinDirectoryPartitions",
|
|
ProcessCreateBuiltinDirectoryPartitions,
|
|
"Create built-in partitions"
|
|
},
|
|
#endif
|
|
|
|
|
|
// END displayed commands
|
|
// commands below here are duplicate names of above or
|
|
// hidden commands
|
|
|
|
{ "***StopDisplayMarker***",
|
|
NULL,
|
|
NULL
|
|
},
|
|
|
|
// Hidden
|
|
|
|
{ "/Restart",
|
|
ProcessSimpleServerOperation,
|
|
"Restart DNS server"
|
|
},
|
|
|
|
// Debug only
|
|
|
|
{ "/DebugBreak",
|
|
ProcessSimpleServerOperation,
|
|
"Server debug break (internal)"
|
|
},
|
|
{ "/ClearDebugLog",
|
|
ProcessSimpleServerOperation,
|
|
"Clear server debug log (internal)"
|
|
},
|
|
{ "/RootBreak",
|
|
ProcessSimpleServerOperation,
|
|
"Root break (internal)"
|
|
},
|
|
|
|
// Duplicate command names
|
|
|
|
{ "/ResetRegistry",
|
|
ProcessResetProperty,
|
|
"Reset server or zone configuration"
|
|
},
|
|
{ "/ZoneResetNotify",
|
|
ProcessZoneResetSecondaries,
|
|
"Reset secondary\notify information for a zone"
|
|
},
|
|
{ "/DeleteNode",
|
|
ProcessNodeDelete,
|
|
"Delete all records at a name"
|
|
},
|
|
{ "/WriteBackFiles",
|
|
ProcessWriteBackFiles,
|
|
"Write back all zone or root-hint datafile(s)"
|
|
},
|
|
|
|
// SAM test
|
|
|
|
{ "/SbsRegister",
|
|
ProcessSbsRegister,
|
|
"SBS Registration"
|
|
},
|
|
{ "/SbsDeleteRecord",
|
|
ProcessSbsDeleteRecord,
|
|
"SBS Record Delete"
|
|
},
|
|
|
|
// Directory partitions
|
|
|
|
{ "/EnumDPs",
|
|
ProcessEnumDirectoryPartitions,
|
|
"Enumerate directory partitions"
|
|
},
|
|
{
|
|
"/DPInfo",
|
|
ProcessDirectoryPartitionInfo,
|
|
"Get info on a directory partition"
|
|
},
|
|
{
|
|
"/CreateDP",
|
|
ProcessCreateDirectoryPartition,
|
|
"Create a directory partition"
|
|
},
|
|
{
|
|
"/DeleteDP",
|
|
ProcessDeleteDirectoryPartition,
|
|
"Delete a directory partition"
|
|
},
|
|
{
|
|
"/EnlistDP",
|
|
ProcessEnlistDirectoryPartition,
|
|
"Add DNS server to partition replication scope"
|
|
},
|
|
{
|
|
"/UnenlistDP",
|
|
ProcessUnenlistDirectoryPartition,
|
|
"Remove DNS server from replication scope"
|
|
},
|
|
{ "/ZoneChangeDP",
|
|
ProcessZoneChangeDirectoryPartition,
|
|
"Move the zone to another directory partition"
|
|
},
|
|
{ "/CreateBuiltinDirectoryPartitions",
|
|
ProcessCreateBuiltinDirectoryPartitions,
|
|
"Create built-in partitions using admin's credentials"
|
|
},
|
|
{ "/CreateBuiltinDPs",
|
|
ProcessCreateBuiltinDirectoryPartitions,
|
|
"Create built-in partitions using admin's credentials"
|
|
},
|
|
|
|
{ NULL, NULL, "" },
|
|
};
|
|
|
|
|
|
//
|
|
// End dnscmd.c
|
|
//
|
|
|