/*++ Copyright (c) 1995-2000 Microsoft Corporation Module Name: print.c Abstract: Domain Name System (DNS) Server RPC Library Print routines for RPC types Author: Jim Gilroy (jamesg) September 1995 Revision History: --*/ #include "dnsclip.h" #include #define DNS_NOT_APPLICABLE "N/A" #define DNS_NOT_APPLICABLE_W L"N/A" #define DNS_NOT_PERFORMED "not since restart" // // Winsock version: copied from socket.c // #ifndef DNS_WINSOCK2 #define DNS_WINSOCK_VERSION (0x0101) // Winsock 1.1 #else // Winsock2 #define DNS_WINSOCK_VERSION (0x0002) // Winsock 2.0 #endif // // Tagged memory stat strings // // NT5 shipped version // LPSTR MemTagStringsNT5[] = { MEMTAG_NAME_NONE , MEMTAG_NAME_RECORD , MEMTAG_NAME_NODE , MEMTAG_NAME_NAME , MEMTAG_NAME_ZONE , MEMTAG_NAME_UPDATE , MEMTAG_NAME_TIMEOUT , MEMTAG_NAME_STUFF , MEMTAG_NAME_NODEHASH , MEMTAG_NAME_DS_DN , MEMTAG_NAME_DS_MOD , MEMTAG_NAME_DS_RECORD , MEMTAG_NAME_NODE_COPY , MEMTAG_NAME_PACKET_UDP , MEMTAG_NAME_PACKET_TCP , MEMTAG_NAME_DNSLIB , MEMTAG_NAME_TABLE , MEMTAG_NAME_SOCKET , MEMTAG_NAME_CONNECTION , MEMTAG_NAME_REGISTRY , MEMTAG_NAME_RPC , MEMTAG_NAME_NBSTAT , MEMTAG_NAME_FILEBUF , MEMTAG_NAME_DS_OTHER , MEMTAG_NAME_THREAD , MEMTAG_NAME_UPDATE_LIST , MEMTAG_NAME_SAFE , NULL, // safety NULL, NULL, NULL }; // NT5 SP1 version LPSTR MemTagStrings[] = { MEMTAG_NAME_NONE , MEMTAG_NAME_PACKET_UDP , MEMTAG_NAME_PACKET_TCP , MEMTAG_NAME_NAME , MEMTAG_NAME_ZONE , MEMTAG_NAME_UPDATE , MEMTAG_NAME_UPDATE_LIST , MEMTAG_NAME_TIMEOUT , MEMTAG_NAME_NODEHASH , MEMTAG_NAME_DS_DN , MEMTAG_NAME_DS_MOD , // 10 MEMTAG_NAME_DS_RECORD , MEMTAG_NAME_DS_OTHER , MEMTAG_NAME_THREAD , MEMTAG_NAME_NBSTAT , MEMTAG_NAME_DNSLIB , MEMTAG_NAME_TABLE , MEMTAG_NAME_SOCKET , MEMTAG_NAME_CONNECTION , MEMTAG_NAME_REGISTRY , MEMTAG_NAME_RPC , // 20 MEMTAG_NAME_STUFF , MEMTAG_NAME_FILEBUF , MEMTAG_NAME_REMOTE , MEMTAG_NAME_SAFE , MEMTAG_NAME_RECORD , MEMTAG_NAME_RECORD_FILE , MEMTAG_NAME_RECORD_DS , MEMTAG_NAME_RECORD_AXFR , MEMTAG_NAME_RECORD_IXFR , MEMTAG_NAME_RECORD_DYNUP , // 30 MEMTAG_NAME_RECORD_ADMIN , MEMTAG_NAME_RECORD_AUTO , MEMTAG_NAME_RECORD_CACHE , MEMTAG_NAME_RECORD_NOEXIST , MEMTAG_NAME_RECORD_WINS , MEMTAG_NAME_RECORD_WINSPTR , MEMTAG_NAME_RECORD_COPY , MEMTAG_NAME_NODE , MEMTAG_NAME_NODE_FILE , MEMTAG_NAME_NODE_DS , // 40 MEMTAG_NAME_NODE_AXFR , MEMTAG_NAME_NODE_IXFR , MEMTAG_NAME_NODE_DYNUP , MEMTAG_NAME_NODE_ADMIN , MEMTAG_NAME_NODE_AUTO , MEMTAG_NAME_NODE_CACHE , MEMTAG_NAME_NODE_NOEXIST , MEMTAG_NAME_NODE_WINS , MEMTAG_NAME_NODE_WINSPTR , MEMTAG_NAME_NODE_COPY , NULL, // safety NULL, NULL, NULL }; VOID Dns_SystemHourToSystemTime( IN DWORD dwHourTime, IN OUT PSYSTEMTIME pSystemTime ) /*++ Routine Description: Converts system time in hours to SYSTEMTIME format. Arguments: dwHourTime -- system time in hours (hours since 1601) pSystemTime -- ptr to SYSTEMTIME to set Return Value: None --*/ { #define FILE_TIME_INTERVALS_IN_HOUR (36000000000) LONGLONG fileTime; fileTime = (LONGLONG)dwHourTime * FILE_TIME_INTERVALS_IN_HOUR; FileTimeToSystemTime( (PFILETIME)&fileTime, pSystemTime ); } // // Print server info // VOID DnsPrint_RpcServerInfo( IN PRINT_ROUTINE PrintRoutine, IN OUT PPRINT_CONTEXT pPrintContext, IN LPSTR pszHeader, IN PDNS_RPC_SERVER_INFO pServerInfo ) { char szTime[ 80 ] = DNS_NOT_PERFORMED; DnsPrint_Lock(); if ( pszHeader ) { PrintRoutine( pPrintContext, pszHeader ); } if ( ! pServerInfo ) { PrintRoutine( pPrintContext, "NULL server info ptr.\n" ); } else { int majorVer = pServerInfo->dwVersion & 0x000000FF; int minorVer = ( pServerInfo->dwVersion & 0x0000FF00 ) >> 8; int buildNum = pServerInfo->dwVersion >> 16; PrintRoutine( pPrintContext, "Server info\n" "\tserver name = %s\n", pServerInfo->pszServerName ); // // Sanitize build number for older versions where build number is wacked. // if ( buildNum < 1 || buildNum > 5000 ) { PrintRoutine( pPrintContext, "\tversion = %08lX (%d.%d)\n", pServerInfo->dwVersion, majorVer, minorVer ); } else { PrintRoutine( pPrintContext, "\tversion = %08lX (%d.%d build %d)\n", pServerInfo->dwVersion, majorVer, minorVer, buildNum ); } PrintRoutine( pPrintContext, "\tDS container = %S\n" "\tforest name = %s\n" "\tdomain name = %s\n", pServerInfo->pszDsContainer ? pServerInfo->pszDsContainer : DNS_NOT_APPLICABLE_W, pServerInfo->pszForestName ? pServerInfo->pszForestName : DNS_NOT_APPLICABLE, pServerInfo->pszDomainName ? pServerInfo->pszDomainName : DNS_NOT_APPLICABLE ); PrintRoutine( pPrintContext, "\tbuiltin domain partition = %s\n" "\tbuiltin forest partition = %s\n", pServerInfo->pszDomainDirectoryPartition ? pServerInfo->pszDomainDirectoryPartition : DNS_NOT_APPLICABLE, pServerInfo->pszForestDirectoryPartition ? pServerInfo->pszForestDirectoryPartition : DNS_NOT_APPLICABLE ); #if DBG PrintRoutine( pPrintContext, "\tAD forest behavior ver = %2d (appears in DEBUG output only)\n" "\tAD domain behavior ver = %2d (appears in DEBUG output only)\n" "\tAD DSA behavior ver = %2d (appears in DEBUG output only)\n", pServerInfo->dwAdForestVersion, pServerInfo->dwAdDomainVersion, pServerInfo->dwAdDsaVersion ); #endif if ( pServerInfo->dwLastScavengeTime ) { time_t t = pServerInfo->dwLastScavengeTime; strcpy( szTime, ctime( &t ) ); szTime[ strlen( szTime ) - 1 ] = '\0'; } PrintRoutine( pPrintContext, "\tlast scavenge cycle = %s (%d)\n", szTime, pServerInfo->dwLastScavengeTime ); PrintRoutine( pPrintContext, " Configuration:\n" "\tdwLogLevel = %p\n" "\tdwDebugLevel = %p\n" "\tdwRpcProtocol = %p\n" "\tdwNameCheckFlag = %p\n" "\tcAddressAnswerLimit = %d\n" "\tdwRecursionRetry = %d\n" "\tdwRecursionTimeout = %d\n" "\tdwDsPollingInterval = %d\n", pServerInfo->dwLogLevel, pServerInfo->dwDebugLevel, pServerInfo->dwRpcProtocol, pServerInfo->dwNameCheckFlag, pServerInfo->cAddressAnswerLimit, pServerInfo->dwRecursionRetry, pServerInfo->dwRecursionTimeout, pServerInfo->dwDsPollingInterval ); PrintRoutine( pPrintContext, " Configuration Flags:\n" "\tfBootMethod = %d\n" "\tfAdminConfigured = %d\n" "\tfAllowUpdate = %d\n" "\tfDsAvailable = %d\n" "\tfAutoReverseZones = %d\n" "\tfAutoCacheUpdate = %d\n" "\tfSlave = %d\n" "\tfNoRecursion = %d\n" "\tfRoundRobin = %d\n" "\tfStrictFileParsing = %d\n" "\tfLooseWildcarding = %d\n" "\tfBindSecondaries = %d\n" "\tfWriteAuthorityNs = %d\n" "\tfLocalNetPriority = %d\n", pServerInfo->fBootMethod, pServerInfo->fAdminConfigured, pServerInfo->fAllowUpdate, pServerInfo->fDsAvailable, pServerInfo->fAutoReverseZones, pServerInfo->fAutoCacheUpdate, pServerInfo->fSlave, pServerInfo->fNoRecursion, pServerInfo->fRoundRobin, pServerInfo->fStrictFileParsing, pServerInfo->fLooseWildcarding, pServerInfo->fBindSecondaries, pServerInfo->fWriteAuthorityNs, pServerInfo->fLocalNetPriority ); PrintRoutine( pPrintContext, " Aging Configuration:\n" "\tScavengingInterval = %d\n" "\tDefaultAgingState = %d\n" "\tDefaultRefreshInterval = %d\n" "\tDefaultNoRefreshInterval = %d\n", pServerInfo->dwScavengingInterval, pServerInfo->fDefaultAgingState, pServerInfo->dwDefaultRefreshInterval, pServerInfo->dwDefaultNoRefreshInterval ); DnsPrint_IpArray( PrintRoutine, pPrintContext, " ServerAddresses:\n", "\tAddr", pServerInfo->aipServerAddrs ); DnsPrint_IpArray( PrintRoutine, pPrintContext, " ListenAddresses:\n", "\tAddr", pServerInfo->aipListenAddrs ); DnsPrint_IpArray( PrintRoutine, pPrintContext, " Forwarders:\n", "\tAddr", pServerInfo->aipForwarders ); PrintRoutine( pPrintContext, "\tforward timeout = %d\n" "\tslave = %d\n", pServerInfo->dwForwardTimeout, pServerInfo->fSlave ); } DnsPrint_Unlock(); } // // Print zone Zone debug utilities // PSTR truncateStringA( PSTR pszSource, PSTR pszDest, int iDestLength ) { if ( pszSource ) { int len = strlen( pszSource ); if ( len < iDestLength ) { strcpy( pszDest, pszSource ); } else { strncpy( pszDest, pszSource, iDestLength - 4 ); strcpy( pszDest + iDestLength - 4, "..." ); } } else { *pszDest = '\0'; } return pszDest; } PWSTR truncateStringW( PWSTR pwszSource, PWSTR pwszDest, int iDestLength ) { if ( pwszSource ) { int len = wcslen( pwszSource ); if ( len < iDestLength ) { wcscpy( pwszDest, pwszSource ); } else { wcsncpy( pwszDest, pwszSource, iDestLength - 4 ); wcscpy( pwszDest + iDestLength - 4, L"..." ); pwszDest[ iDestLength - 1 ] = '\0'; } } else { *pwszDest = L'\0'; } return pwszDest; } #define DNS_DPDISP_REAL_CUSTOM_NAME 0x0001 #define DNS_DPDISP_BLANK_STRING_FOR_LEGACY 0x0002 LPSTR partitionDisplayName( IN DWORD dwPartitionFlags, IN LPSTR pszPartitionFqdn, IN DWORD dwNameBuffLen, OUT LPSTR pszNameBuff, IN DWORD dwFlags ) /*++ Routine Description: Formats directory partition for display. If the flags indicate that the partition is a built-in partition, the name will be substituted for a descriptive string. Arguments: dwPartitionFlags -- DP flags from the DNS server pszPartitionFqdn -- FQDN of the partition dwNameBuffLen -- length of the output name buffer pszNameBuff -- pointer to the output name buffer dwFlags - use DNS_DPDISP_XXX constants Return Value: Pointer to pszNameBuff --*/ { // // Substitute name if this is a built-in partition. // if ( dwPartitionFlags & DNS_DP_DOMAIN_DEFAULT ) { pszPartitionFqdn = "AD-Domain"; } else if ( dwPartitionFlags & DNS_DP_FOREST_DEFAULT ) { pszPartitionFqdn = "AD-Forest"; } else if ( dwPartitionFlags & DNS_DP_LEGACY || !pszPartitionFqdn ) { pszPartitionFqdn = ( dwFlags & DNS_DPDISP_BLANK_STRING_FOR_LEGACY ) ? "" : "AD-Legacy"; } else if ( !( dwFlags & DNS_DPDISP_REAL_CUSTOM_NAME ) ) { pszPartitionFqdn = "AD-Custom"; } truncateStringA( pszPartitionFqdn, pszNameBuff, dwNameBuffLen ); return pszNameBuff; } // partitionDisplayName LPSTR zoneTypeString( IN DWORD dwZoneType, IN DWORD dwOutBuffLen, OUT LPSTR pszOutBuff ) /*++ Routine Description: Convert DWORD zone type into display string. Arguments: dwZoneType -- zone type dwOutBuffLen -- length of the output name buffer pszOutBuff -- pointer to the output name buffer Return Value: Pointer to pszOutBuff --*/ { PSTR pszZoneType = NULL; CHAR szBuff[ 10 ]; switch ( dwZoneType ) { case DNS_ZONE_TYPE_CACHE: pszZoneType = "Cache"; break; case DNS_ZONE_TYPE_PRIMARY: pszZoneType = "Primary"; break; case DNS_ZONE_TYPE_SECONDARY: pszZoneType = "Secondary"; break; case DNS_ZONE_TYPE_STUB: pszZoneType = "Stub"; break; case DNS_ZONE_TYPE_FORWARDER: pszZoneType = "Forwarder"; break; default: _itoa( dwZoneType, szBuff, 10 ); pszZoneType = szBuff; break; } truncateStringA( pszZoneType, pszOutBuff, dwOutBuffLen ); return pszOutBuff; } // zoneTypeString VOID DnsPrint_RpcZone( IN PRINT_ROUTINE PrintRoutine, IN OUT PPRINT_CONTEXT pPrintContext, IN LPSTR pszHeader, IN PDNS_RPC_ZONE pZone ) { if ( ! pZone ) { PrintRoutine( pPrintContext, "%sNULL zone info ptr.\n", ( pszHeader ? pszHeader : "" ) ); } else { CHAR szpartition[ 15 ]; CHAR sztype[ 10 ]; // print zone per line if ( pszHeader && *pszHeader ) { PrintRoutine( pPrintContext, "%s\n", pszHeader ? pszHeader : "" ); } PrintRoutine( pPrintContext, " %-30S", pZone->pszZoneName ); if ( pZone->Flags.DsIntegrated ) { partitionDisplayName( pZone->dwDpFlags, pZone->pszDpFqdn, sizeof( szpartition ), szpartition, 0 ); } else { strcpy( szpartition, "File" ); } PrintRoutine( pPrintContext, " %-9s %-14s %s%s%s%s%s\n", zoneTypeString( pZone->ZoneType, sizeof( sztype ), sztype ), szpartition, pZone->Flags.Update == 2 ? "Secure " : ( pZone->Flags.Update == 1 ? "Update " : "" ), pZone->Flags.Reverse ? "Rev " : "", pZone->Flags.AutoCreated ? "Auto " : "", pZone->Flags.Aging ? "Aging " : "", pZone->Flags.Paused ? "Paused " : "", pZone->Flags.Shutdown ? "Down " : "" ); } } VOID DNS_API_FUNCTION DnsPrint_RpcZoneList( IN PRINT_ROUTINE PrintRoutine, IN OUT PPRINT_CONTEXT pPrintContext, IN LPSTR pszHeader, IN PDNS_RPC_ZONE_LIST pZoneList ) { DWORD i; DnsPrint_Lock(); if ( pszHeader ) { PrintRoutine( pPrintContext, "%s\n", pszHeader ); } if ( !pZoneList ) { PrintRoutine( pPrintContext, "NULL zone list pointer.\n" ); } else { PrintRoutine( pPrintContext, "\tZone count = %d\n\n", pZoneList->dwZoneCount ); PrintRoutine( pPrintContext, " Zone name Type Storage Properties\n\n" ); if ( pZoneList->dwZoneCount ) { DnsPrint_RpcZone( PrintRoutine, pPrintContext, NULL, // print default header pZoneList->ZoneArray[0] ); } for ( i=1; idwZoneCount; i++ ) { DnsPrint_RpcZone( PrintRoutine, pPrintContext, NULL, // print default header pZoneList->ZoneArray[i] ); } PrintRoutine( pPrintContext, "\n" ); } DnsPrint_Unlock(); } // // Directory parition debug utilities // VOID DnsPrint_RpcDpEnum( IN PRINT_ROUTINE PrintRoutine, IN OUT PPRINT_CONTEXT pPrintContext, IN LPSTR pszHeader, IN PDNS_RPC_DP_ENUM pDp ) { DnsPrint_Lock(); if ( !pDp ) { PrintRoutine( pPrintContext, "NULL DP enum ptr\n" ); } else { PrintRoutine( pPrintContext, " %-40s %s%s%s%s%s%s\n", pDp->pszDpFqdn, pDp->dwFlags & DNS_DP_ENLISTED ? "Enlisted " : "Not-Enlisted ", pDp->dwFlags & DNS_DP_DELETED ? "Deleted " : "", pDp->dwFlags & DNS_DP_AUTOCREATED ? "Auto " : "", pDp->dwFlags & DNS_DP_LEGACY ? "Legacy " : "", pDp->dwFlags & DNS_DP_DOMAIN_DEFAULT ? "Domain " : "", pDp->dwFlags & DNS_DP_FOREST_DEFAULT ? "Forest " : "" ); } DnsPrint_Unlock(); } // DnsPrint_RpcDpEnum VOID DnsPrint_RpcDpInfo( IN PRINT_ROUTINE PrintRoutine, IN OUT PPRINT_CONTEXT pPrintContext, IN LPSTR pszHeader, IN PDNS_RPC_DP_INFO pDp, IN BOOL fTruncateLongStrings ) { DnsPrint_Lock(); if ( !pDp ) { PrintRoutine( pPrintContext, "%sNULL DP info ptr.\n", ( pszHeader ? pszHeader : "" ) ); } else { WCHAR wsz[ 80 ]; PrintRoutine( pPrintContext, "%s\n" " DNS root: %s\n" " Flags: 0x%X %s%s%s%s%s%s\n" " Zone count: %d\n" " DP head: %S\n" " Crossref: ", pszHeader ? pszHeader : "", pDp->pszDpFqdn, pDp->dwFlags, pDp->dwFlags & DNS_DP_ENLISTED ? "Enlisted " : "Not-Enlisted ", pDp->dwFlags & DNS_DP_DELETED ? "Deleted " : "", pDp->dwFlags & DNS_DP_AUTOCREATED ? "Auto " : "", pDp->dwFlags & DNS_DP_LEGACY ? "Legacy " : "", pDp->dwFlags & DNS_DP_DOMAIN_DEFAULT ? "Domain " : "", pDp->dwFlags & DNS_DP_FOREST_DEFAULT ? "Forest " : "", pDp->dwZoneCount, pDp->pszDpDn, pDp->pszCrDn ); if ( fTruncateLongStrings ) { truncateStringW( pDp->pszCrDn, wsz, 64 ); PrintRoutine( pPrintContext, "%S", wsz ); } else { PrintRoutine( pPrintContext, "%S", pDp->pszCrDn ); } PrintRoutine( pPrintContext, "\n Replicas: %d\n", pDp->dwReplicaCount ); if ( pDp->dwReplicaCount && pDp->ReplicaArray ) { DWORD i; for ( i = 0; i < pDp->dwReplicaCount && pDp->ReplicaArray[ i ]; ++i ) { if ( fTruncateLongStrings ) { truncateStringW( pDp->ReplicaArray[ i ]->pszReplicaDn, wsz, 74 ); PrintRoutine( pPrintContext, " %S\n", wsz ); } else { PrintRoutine( pPrintContext, " %S\n", pDp->ReplicaArray[ i ]->pszReplicaDn ? pDp->ReplicaArray[ i ]->pszReplicaDn : L"NULL" ); } } } } DnsPrint_Unlock(); } // DnsPrint_RpcDpInfo VOID DNS_API_FUNCTION DnsPrint_RpcDpList( IN PRINT_ROUTINE PrintRoutine, IN OUT PPRINT_CONTEXT pPrintContext, IN LPSTR pszHeader, IN PDNS_RPC_DP_LIST pDpList ) { DWORD i; DnsPrint_Lock(); if ( pszHeader ) { PrintRoutine( pPrintContext, "%s\n", pszHeader ); } if ( !pDpList ) { PrintRoutine( pPrintContext, "NULL directory partition list pointer.\n" ); } else { PrintRoutine( pPrintContext, "\tDirectory partition count = %d\n\n", pDpList->dwDpCount ); for ( i = 0; i < pDpList->dwDpCount && pDpList->DpArray[ i ]; ++i ) { DnsPrint_RpcDpEnum( PrintRoutine, pPrintContext, NULL, // print default header pDpList->DpArray[ i ] ); } PrintRoutine( pPrintContext, "\n" ); } DnsPrint_Unlock(); } // DnsPrint_RpcDpList VOID DnsPrint_RpcZoneInfo( IN PRINT_ROUTINE PrintRoutine, IN OUT PPRINT_CONTEXT pPrintContext, IN LPSTR pszHeader, IN PDNS_RPC_ZONE_INFO pZoneInfo ) { CHAR szdpName[ 300 ]; // don't want truncation DnsPrint_Lock(); PrintRoutine( pPrintContext, (pszHeader ? pszHeader : "") ); if ( ! pZoneInfo ) { PrintRoutine( pPrintContext, "NULL zone info ptr.\n" ); } else { PrintRoutine( pPrintContext, "Zone info:\n" "\tptr = %p\n" "\tzone name = %s\n" "\tzone type = %d\n" "\tupdate = %d\n" "\tDS integrated = %d\n" "\tdata file = %s\n" "\tusing WINS = %d\n" "\tusing Nbstat = %d\n" "\taging = %d\n" "\t refresh interval = %lu\n" "\t no refresh = %lu\n" "\t scavenge available = %lu\n", pZoneInfo, pZoneInfo->pszZoneName, pZoneInfo->dwZoneType, pZoneInfo->fAllowUpdate, pZoneInfo->fUseDatabase, pZoneInfo->pszDataFile, pZoneInfo->fUseWins, pZoneInfo->fUseNbstat, pZoneInfo->fAging, pZoneInfo->dwRefreshInterval, pZoneInfo->dwNoRefreshInterval, pZoneInfo->dwAvailForScavengeTime ); DnsPrint_IpArray( PrintRoutine, pPrintContext, "\tZone Masters\n", "\tMaster", pZoneInfo->aipMasters ); if ( pZoneInfo->dwZoneType == DNS_ZONE_TYPE_STUB ) { DnsPrint_IpArray( PrintRoutine, pPrintContext, "\tZone Local Masters\n", "\tLocal Master", pZoneInfo->aipLocalMasters ); } DnsPrint_IpArray( PrintRoutine, pPrintContext, "\tZone Secondaries\n", "\tSecondary", pZoneInfo->aipSecondaries ); PrintRoutine( pPrintContext, "\tsecure secs = %d\n", pZoneInfo->fSecureSecondaries ); if ( pZoneInfo->fUseDatabase ) { PrintRoutine( pPrintContext, "\tdirectory partition = %s flags %08X\n", partitionDisplayName( pZoneInfo->dwDpFlags, pZoneInfo->pszDpFqdn, sizeof( szdpName ), szdpName, DNS_DPDISP_REAL_CUSTOM_NAME ), pZoneInfo->dwDpFlags ); } if ( pZoneInfo->aipScavengeServers ) { DnsPrint_IpArray( PrintRoutine, pPrintContext, "\tScavenge Servers\n", "\tServer", pZoneInfo->aipScavengeServers ); } if ( pZoneInfo->dwZoneType == DNS_ZONE_TYPE_FORWARDER ) { PrintRoutine( pPrintContext, "\tforwarder timeout = %d\n" "\tforwarder slave = %d\n", pZoneInfo->dwForwarderTimeout, pZoneInfo->fForwarderSlave ); } if ( pZoneInfo->dwZoneType == DNS_ZONE_TYPE_SECONDARY || pZoneInfo->dwZoneType == DNS_ZONE_TYPE_STUB ) { char szTime1[ 60 ] = DNS_NOT_PERFORMED; char szTime2[ 60 ] = DNS_NOT_PERFORMED; if ( pZoneInfo->dwLastSuccessfulXfr ) { time_t t = pZoneInfo->dwLastSuccessfulXfr; strcpy( szTime1, ctime( &t ) ); szTime1[ strlen( szTime1 ) - 1 ] = '\0'; } if ( pZoneInfo->dwLastSuccessfulSoaCheck ) { time_t t = pZoneInfo->dwLastSuccessfulSoaCheck; strcpy( szTime2, ctime( &t ) ); szTime2[ strlen( szTime2 ) - 1 ] = '\0'; } PrintRoutine( pPrintContext, "\tlast successful xfr = %s (%d)\n" "\tlast SOA check = %s (%d)\n", szTime1, pZoneInfo->dwLastSuccessfulXfr, szTime2, pZoneInfo->dwLastSuccessfulSoaCheck ); } } DnsPrint_Unlock(); } VOID DnsPrint_RpcZoneInfoList( IN PRINT_ROUTINE PrintRoutine, IN OUT PPRINT_CONTEXT pPrintContext, IN LPSTR pszHeader, IN DWORD dwZoneCount, IN PDNS_RPC_ZONE_INFO apZoneInfo[] ) { DWORD i; DnsPrint_Lock(); PrintRoutine( pPrintContext, (pszHeader ? pszHeader : "") ); PrintRoutine( pPrintContext, "Zone Count = %d\n", dwZoneCount ); if ( dwZoneCount != 0 && apZoneInfo != NULL ) { for (i=0; icchNameLength; strncpy( pResult, pName->achName, length ); pResult[ length ] = 0; } VOID DnsPrint_RpcName( IN PRINT_ROUTINE PrintRoutine, IN OUT PPRINT_CONTEXT pPrintContext, IN LPSTR pszHeader, IN PDNS_RPC_NAME pName, IN LPSTR pszTrailer ) /*++ Routine Description: Prints RPC name. Arguments: PrintRoutine -- printf like routine to print with pszHeader -- header string pName -- RPC name pszTrailer -- trailer string Return Value: None --*/ { // // print name to given length // DnsPrint_Lock(); if ( !pszHeader ) { pszHeader = ""; } if ( !pszTrailer ) { pszTrailer = ""; } if ( ! pName ) { PrintRoutine( pPrintContext, "%s" "(NULL DNS name ptr)" "%s", pszHeader, pszTrailer ); } else { #if 0 PrintRoutine( pPrintContext, "%s" "(%d) %.*s" "%s", pszHeader, pName->cchNameLength, pName->cchNameLength, pName->achName, pszTrailer ); #endif if ( pName->cchNameLength > 0 ) { PrintRoutine( pPrintContext, "%s" "%.*s" "%s", pszHeader, pName->cchNameLength, pName->achName, pszTrailer ); } else // use "@ for empty node name { PrintRoutine( pPrintContext, "%s" "%@" "%s", pszHeader, pszTrailer ); } } DnsPrint_Unlock(); } VOID DnsPrint_RpcNode( IN PRINT_ROUTINE PrintRoutine, IN OUT PPRINT_CONTEXT pPrintContext, IN LPSTR pszHeader, IN PDNS_RPC_NODE pNode ) /*++ Routine Description: Prints RPC node. Arguments: PrintRoutine -- printf like routine to print with pszHeader -- header string pNode -- RPC node to print Return Value: None --*/ { DnsPrint_Lock(); PrintRoutine( pPrintContext, (pszHeader ? pszHeader : "RPC Node:") ); if ( ! pNode ) { PrintRoutine( pPrintContext, "NULL RPC node ptr.\n" ); } else { PrintRoutine( pPrintContext, "\n" "\tptr = %p\n" "\twLength = %d\n" "\twRecordCount = %d\n" "\tdwChildCount = %d\n" "\tdwFlags = %p\n", pNode, pNode->wLength, pNode->wRecordCount, pNode->dwChildCount, pNode->dwFlags ); DnsPrint_RpcName( PrintRoutine, pPrintContext, "\tNode Name = ", & pNode->dnsNodeName, "\n" ); } DnsPrint_Unlock(); } VOID DnsPrint_RpcRecord( IN PRINT_ROUTINE PrintRoutine, IN OUT PPRINT_CONTEXT pPrintContext, IN LPSTR pszHeader, IN BOOL fDetail, IN PDNS_FLAT_RECORD pRecord ) /*++ Routine Description: Prints RPC record. Arguments: PrintRoutine -- printf like routine to print with pszHeader -- header string fDetail -- if TRUE print detailed record info pRecord -- RPC record to print Return Value: None --*/ { PCHAR ptypeString; PDNS_RPC_RECORD_DATA pdata; WORD type; WORD dataLength; SYSTEMTIME sysTime; CHAR szBuff[ 5000 ]; DnsPrint_Lock(); PrintRoutine( pPrintContext, (pszHeader ? pszHeader : "" ) ); if ( ! pRecord ) { PrintRoutine( pPrintContext, "NULL record ptr.\n" ); goto Done; } // // record fixed fields // type = pRecord->wType; ptypeString = Dns_RecordStringForType( type ); if ( !ptypeString ) { ptypeString = "UNKNOWN"; } pdata = &pRecord->Data; dataLength = pRecord->wDataLength; if ( fDetail ) { Dns_SystemHourToSystemTime( pRecord->dwTimeStamp, &sysTime ); PrintRoutine( pPrintContext, " %s Record info:\n" "\tptr = %p\n" "\twType = %s (%u)\n" "\twDataLength = %u\n" "\tdwFlags = %lx\n" "\trank = %x\n" "\tdwSerial = %p\n" "\tdwTtlSeconds = %u\n" "\tdwTimeStamp = %lu ([%2d:%2d:%2d] [%2d/%2d/%2d])\n", ptypeString, pRecord, ptypeString, type, pRecord->wDataLength, pRecord->dwFlags, (UCHAR)(pRecord->dwFlags & DNS_RPC_FLAG_RANK), pRecord->dwSerial, pRecord->dwTtlSeconds, pRecord->dwTimeStamp, sysTime.wHour, sysTime.wMinute, sysTime.wSecond, sysTime.wMonth, sysTime.wDay, sysTime.wYear ); } // // print record type and data // - as single line data where possible if ( !fDetail ) { if ( pRecord->dwTimeStamp ) { PrintRoutine( pPrintContext, " [Aging:%lu]", pRecord->dwTimeStamp ); } PrintRoutine( pPrintContext, " %lu", pRecord->dwTtlSeconds ); } PrintRoutine( pPrintContext, " %s\t", ptypeString ); // // print type data // switch ( type ) { case DNS_TYPE_A: PrintRoutine( pPrintContext, "%d.%d.%d.%d\n", * ( (PUCHAR) &(pdata->A) + 0 ), * ( (PUCHAR) &(pdata->A) + 1 ), * ( (PUCHAR) &(pdata->A) + 2 ), * ( (PUCHAR) &(pdata->A) + 3 ) ); break; case DNS_TYPE_PTR: case DNS_TYPE_NS: case DNS_TYPE_CNAME: case DNS_TYPE_MD: case DNS_TYPE_MB: case DNS_TYPE_MF: case DNS_TYPE_MG: case DNS_TYPE_MR: // // these RRs contain single indirection // DnsPrint_RpcName( PrintRoutine, pPrintContext, NULL, & pdata->NS.nameNode, "\n" ); break; case DNS_TYPE_MX: case DNS_TYPE_RT: case DNS_TYPE_AFSDB: // // these RR contain // - one preference value // - one domain name // PrintRoutine( pPrintContext, "%d ", pdata->MX.wPreference ); DnsPrint_RpcName( PrintRoutine, pPrintContext, NULL, & pdata->MX.nameExchange, "\n" ); break; case DNS_TYPE_SOA: if ( fDetail ) { DnsPrint_RpcName( PrintRoutine, pPrintContext, "\n\tPrimaryNameServer: ", & pdata->SOA.namePrimaryServer, "\n" ); // responsible party name, immediately follows primary server name DnsPrint_RpcName( PrintRoutine, pPrintContext, "\tResponsibleParty: ", (PDNS_RPC_NAME) (pdata->SOA.namePrimaryServer.achName + pdata->SOA.namePrimaryServer.cchNameLength), "\n" ); PrintRoutine( pPrintContext, "\tSerialNo = %lu\n" "\tRefresh = %lu\n" "\tRetry = %lu\n" "\tExpire = %lu\n" "\tMinimumTTL = %lu\n", pdata->SOA.dwSerialNo, pdata->SOA.dwRefresh, pdata->SOA.dwRetry, pdata->SOA.dwExpire, pdata->SOA.dwMinimumTtl ); break; } else { DnsPrint_RpcName( PrintRoutine, pPrintContext, NULL, & pdata->SOA.namePrimaryServer, NULL ); // responsible party name, immediately follows primary server name DnsPrint_RpcName( PrintRoutine, pPrintContext, " ", (PDNS_RPC_NAME) (pdata->SOA.namePrimaryServer.achName + pdata->SOA.namePrimaryServer.cchNameLength), NULL ); PrintRoutine( pPrintContext, " %lu" " %lu" " %lu" " %lu" " %lu\n", pdata->SOA.dwSerialNo, pdata->SOA.dwRefresh, pdata->SOA.dwRetry, pdata->SOA.dwExpire, pdata->SOA.dwMinimumTtl ); break; } case DNS_TYPE_AAAA: { CHAR ip6String[ IPV6_ADDRESS_STRING_LENGTH+1 ]; Dns_Ip6AddressToString_A( ip6String, &pdata->AAAA.ipv6Address ); PrintRoutine( pPrintContext, "%s\n", ip6String ); } break; case DNS_TYPE_HINFO: case DNS_TYPE_ISDN: case DNS_TYPE_X25: case DNS_TYPE_TEXT: { // // all these are simply text string(s) // // TXT strings will be printed one per line // PCHAR pch = (PCHAR) &pdata->TXT.stringData; PCHAR pchStop = pch + dataLength; UCHAR cch; while ( pch < pchStop ) { cch = (UCHAR) *pch++; if ( type == DNS_TYPE_TEXT ) { PrintRoutine( pPrintContext, "\t%.*s\n", cch, pch ); } else { PrintRoutine( pPrintContext, "\"%.*s\" ", cch, pch ); } pch += cch; } if ( type != DNS_TYPE_TEXT ) { PrintRoutine( pPrintContext,"\n"); } ASSERT( pch == pchStop ); break; } case DNS_TYPE_MINFO: case DNS_TYPE_RP: // // these RRs contain two domain names // DnsPrint_RpcName( PrintRoutine, pPrintContext, NULL, & pdata->MINFO.nameMailBox, NULL ); // errors to mailbox name, immediately follows mail box DnsPrint_RpcName( PrintRoutine, pPrintContext, " ", (PDNS_RPC_NAME) ( pdata->MINFO.nameMailBox.achName + pdata->MINFO.nameMailBox.cchNameLength ), "\n" ); break; case DNS_TYPE_WKS: { INT i; if ( fDetail ) { PrintRoutine( pPrintContext, "WKS: Address %d.%d.%d.%d\n" "\tProtocol %d\n" "\tBitmask\n", * ( (PUCHAR) &(pdata->WKS.ipAddress) + 0 ), * ( (PUCHAR) &(pdata->WKS.ipAddress) + 1 ), * ( (PUCHAR) &(pdata->WKS.ipAddress) + 2 ), * ( (PUCHAR) &(pdata->WKS.ipAddress) + 3 ), pdata->WKS.chProtocol ); for ( i = 0; i < (INT)( dataLength - sizeof( pdata->WKS.ipAddress ) - sizeof( pdata->WKS.chProtocol ) ); i++ ) { PrintRoutine( pPrintContext, "\t\tbyte[%d] = %x\n", i, (UCHAR) pdata->WKS.bBitMask[i] ); } break; } else { DNS_STATUS status; struct protoent * pProtoent; WSADATA wsaData; PrintRoutine( pPrintContext, "%d.%d.%d.%d ", * ( (PUCHAR) &(pdata->WKS.ipAddress) + 0 ), * ( (PUCHAR) &(pdata->WKS.ipAddress) + 1 ), * ( (PUCHAR) &(pdata->WKS.ipAddress) + 2 ), * ( (PUCHAR) &(pdata->WKS.ipAddress) + 3 ) ); // // get protocol number: // // start winsock: status = WSAStartup( DNS_WINSOCK_VERSION, &wsaData ); if ( status == SOCKET_ERROR ) { status = WSAGetLastError(); SetLastError( status ); PrintRoutine( pPrintContext, "ERROR: WSAGetLastError()\n" ); ASSERT(FALSE); } pProtoent = getprotobynumber( pdata->WKS.chProtocol ); if ( ! pProtoent || pProtoent->p_proto >= MAXUCHAR ) { status = WSAGetLastError(); SetLastError( status ); PrintRoutine( pPrintContext, "ERROR: getprotobyname()\n" ); ASSERT(FALSE); } PrintRoutine( pPrintContext, "%s\t", pProtoent->p_name ); //bBitMask[0] : string length, not printed: for ( i = 1; i < (INT)( dataLength - sizeof( pdata->WKS.ipAddress ) - sizeof( pdata->WKS.chProtocol ) ); i++ ) { PrintRoutine( pPrintContext, "%c", (UCHAR) pdata->WKS.bBitMask[i] ); } PrintRoutine( pPrintContext,"\n"); break; } } case DNS_TYPE_NULL: { INT i; for ( i = 0; i < dataLength; i++ ) { // print one DWORD per line if ( !(i%16) ) { PrintRoutine( pPrintContext, "\n\t" ); } PrintRoutine( pPrintContext, "%02x ", (UCHAR) pdata->Null.bData[i] ); } PrintRoutine( pPrintContext, "\n" ); break; } case DNS_TYPE_SRV: // // SRV // PrintRoutine( pPrintContext, "%d %d %d ", pdata->SRV.wPriority, pdata->SRV.wWeight, pdata->SRV.wPort ); DnsPrint_RpcName( PrintRoutine, pPrintContext, NULL, & pdata->SRV.nameTarget, "\n" ); break; case DNS_TYPE_WINS: { DWORD i; CHAR flagName[ WINS_FLAG_MAX_LENGTH ]; // // WINS // - scope/domain mapping flag // - WINS server list // Dns_WinsRecordFlagString( pdata->WINS.dwMappingFlag, flagName ); PrintRoutine( pPrintContext, "%s %d %d ", flagName, //pdata->WINS.dwMappingFlag, pdata->WINS.dwLookupTimeout, pdata->WINS.dwCacheTimeout ); if ( fDetail ) { PrintRoutine( pPrintContext, " WINS Servers:\n" ); } for( i=0; iWINS.cWinsServerCount; i++ ) { PrintRoutine( pPrintContext, "%d.%d.%d.%d%c", * ( (PUCHAR) &(pdata->WINS.aipWinsServers[i]) + 0 ), * ( (PUCHAR) &(pdata->WINS.aipWinsServers[i]) + 1 ), * ( (PUCHAR) &(pdata->WINS.aipWinsServers[i]) + 2 ), * ( (PUCHAR) &(pdata->WINS.aipWinsServers[i]) + 3 ), fDetail ? '\n' : ' ' ); } if ( !fDetail ) { PrintRoutine( pPrintContext, "\n" ); } break; } case DNS_TYPE_NBSTAT: { CHAR flagName[ WINS_FLAG_MAX_LENGTH ]; // // NBSTAT // - scope/domain mapping flag // - optionally a result domain // Dns_WinsRecordFlagString( pdata->WINS.dwMappingFlag, flagName ); PrintRoutine( pPrintContext, "%s %d %d ", flagName, //pdata->WINS.dwMappingFlag, pdata->NBSTAT.dwLookupTimeout, pdata->NBSTAT.dwCacheTimeout ); if ( dataLength > sizeof(pdata->NBSTAT.dwMappingFlag) ) { DnsPrint_RpcName( PrintRoutine, pPrintContext, NULL, & pdata->NBSTAT.nameResultDomain, "\n" ); } break; } case DNS_TYPE_KEY: { int keyLength = dataLength - SIZEOF_KEY_FIXED_DATA; PrintRoutine( pPrintContext, "0x%04X %d %d ", ( int ) pdata->KEY.wFlags, ( int ) pdata->KEY.chProtocol, ( int ) pdata->KEY.chAlgorithm ); if ( keyLength > 0 && keyLength < sizeof( szBuff ) / 2 ) { PCHAR p = Dns_SecurityKeyToBase64String( ( PBYTE ) pdata + SIZEOF_KEY_FIXED_DATA, keyLength, szBuff ); if ( p ) { *p = '\0'; // NULL terminate key string } PrintRoutine( pPrintContext, szBuff ); } else { PrintRoutine( pPrintContext, "KEY = %d bytes", keyLength ); } PrintRoutine( pPrintContext, "\n" ); break; } case DNS_TYPE_SIG: { CHAR szSigExp[ 30 ]; CHAR szSigInc[ 30 ]; INT sigOffset = SIZEOF_SIG_FIXED_DATA + pdata->SIG.nameSigner.cchNameLength + sizeof( pdata->SIG.nameSigner.cchNameLength ); INT sigLength = dataLength - sigOffset; ptypeString = Dns_RecordStringForType( pdata->SIG.wTypeCovered ); if ( !ptypeString ) { ptypeString = "UNKNOWN-TYPE"; } PrintRoutine( pPrintContext, "%s %d %d %d %s %s %d ", ptypeString, ( int ) pdata->SIG.chAlgorithm, ( int ) pdata->SIG.chLabelCount, ( int ) pdata->SIG.dwOriginalTtl, Dns_SigTimeString( pdata->SIG.dwSigExpiration, szSigExp ), Dns_SigTimeString( pdata->SIG.dwSigInception, szSigInc ), ( int ) pdata->SIG.wKeyTag ); DnsPrint_RpcName( PrintRoutine, pPrintContext, NULL, &pdata->SIG.nameSigner, " " ); if ( sigLength > 0 && sigLength < sizeof( szBuff ) / 2 ) { PCHAR p = Dns_SecurityKeyToBase64String( ( PBYTE ) pdata + sigOffset, sigLength, szBuff ); if ( p ) { *p = '\0'; // NULL terminate key string } PrintRoutine( pPrintContext, szBuff ); } else { PrintRoutine( pPrintContext, "SIG = %d bytes", sigLength ); } PrintRoutine( pPrintContext, "\n" ); break; } case DNS_TYPE_NXT: { INT typeIdx; DnsPrint_RpcName( PrintRoutine, pPrintContext, NULL, ( PDNS_RPC_NAME ) ( ( PBYTE ) &pdata->NXT + ( pdata->NXT.wNumTypeWords + 1 ) * sizeof( WORD ) ), NULL ); for ( typeIdx = 0; typeIdx < pdata->NXT.wNumTypeWords; ++typeIdx ) { ptypeString = Dns_RecordStringForType( pdata->NXT.wTypeWords[ typeIdx ] ); if ( !ptypeString ) { ptypeString = "UNKNOWN-TYPE"; } PrintRoutine( pPrintContext, " %s", ptypeString ); } PrintRoutine( pPrintContext, "\n" ); break; } default: PrintRoutine( pPrintContext, "Unknown resource record type (%d) at %p.\n", type, pRecord ); break; } Done: DnsPrint_Unlock(); } PDNS_RPC_NAME DNS_API_FUNCTION DnsPrint_RpcRecordsInBuffer( IN PRINT_ROUTINE PrintRoutine, IN OUT PPRINT_CONTEXT pPrintContext, IN LPSTR pszHeader, IN BOOL fDetail, IN DWORD dwBufferLength, IN BYTE abBuffer[] ) /*++ Routine Description: Prints RPC buffer. Arguments: PrintRoutine -- printf like routine to print with pszHeader -- header string 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; DnsPrint_Lock(); PrintRoutine( pPrintContext, (pszHeader ? pszHeader : "") ); if ( !abBuffer ) { PrintRoutine( pPrintContext, "NULL record buffer ptr.\n" ); goto Done; } #if 0 else { PrintRoutine( pPrintContext, "Record buffer of length %d at %p:\n", dwBufferLength, abBuffer ); } #endif // // find stop byte // ASSERT( DNS_IS_DWORD_ALIGNED(abBuffer) ); pstop = abBuffer + dwBufferLength; pcurrent = abBuffer; // // loop until out of nodes // while ( pcurrent < pstop ) { // // print owner node // - if NOT printing detail and no records // (essentially domain nodes) then no node print // plastName = &((PDNS_RPC_NODE)pcurrent)->dnsNodeName; recordCount = ((PDNS_RPC_NODE)pcurrent)->wRecordCount; if ( fDetail ) { DnsPrint_RpcNode( PrintRoutine, pPrintContext, NULL, (PDNS_RPC_NODE)pcurrent ); if ( recordCount == 0 ) { PrintRoutine( pPrintContext,"\n"); } } else { #ifndef DBG if ( recordCount != 0 ) #endif { DnsPrint_RpcName( PrintRoutine, pPrintContext, NULL, plastName, NULL ); #ifdef DBG if ( recordCount == 0 ) { PrintRoutine( pPrintContext, "\t\t(node)\n" ); } #endif } } pcurrent += ((PDNS_RPC_NODE)pcurrent)->wLength; pcurrent = DNS_NEXT_DWORD_PTR(pcurrent); // // for each node, print all records in list // if ( !recordCount ) { continue; } precordHeader = ""; while( recordCount-- ) { if ( pcurrent >= pstop ) { PrintRoutine( pPrintContext, "ERROR: Bogus buffer at %p\n" "\tExpect record at %p past buffer end at %p\n" "\twith %d records remaining.\n", abBuffer, (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); } } Done: DnsPrint_Unlock(); return( plastName ); } VOID DNS_API_FUNCTION DnsPrint_Node( IN PRINT_ROUTINE PrintRoutine, IN OUT PPRINT_CONTEXT pPrintContext, IN LPSTR pszHeader, IN PDNS_NODE pNode, IN BOOLEAN fPrintRecords ) { DnsPrint_Lock(); PrintRoutine( pPrintContext, (pszHeader ? pszHeader : "") ); if ( !pNode ) { PrintRoutine( pPrintContext, " NULL DNS node ptr.\n" ); goto Unlock; } else { PrintRoutine( pPrintContext, "%s\n" "\tName = %s%S\n" "\tPtr = %p, pNext = %p\n" "\tFlags = %p\n" "\tRec ptr = %p\n", pszHeader ? "" : "DNS node", (LPSTR) (pNode->Flags.S.Unicode ? "" : (PSTR) pNode->pName), (LPWSTR) (pNode->Flags.S.Unicode ? pNode->pName : L""), pNode, pNode->pNext, pNode->Flags.W, pNode->pRecord ); } // // if desired print record list // if ( pNode->pRecord && fPrintRecords ) { DnsPrint_RecordSet( PrintRoutine, pPrintContext, "\trecords:\n", pNode->pRecord ); } Unlock: DnsPrint_Unlock(); } VOID DNS_API_FUNCTION DnsPrint_NodeList( IN PRINT_ROUTINE PrintRoutine, IN OUT PPRINT_CONTEXT pPrintContext, IN LPSTR pszHeader, IN PDNS_NODE pNode, IN BOOLEAN fPrintRecords ) { DnsPrint_Lock(); PrintRoutine( pPrintContext, (pszHeader ? pszHeader : "") ); if ( !pNode ) { PrintRoutine( pPrintContext, " NULL node list pointer.\n" ); } else { do { DnsPrint_Node( PrintRoutine, pPrintContext, NULL, pNode, fPrintRecords ); } while ( pNode = pNode->pNext ); } DnsPrint_Unlock(); } // // RPC Type union printing // VOID DnsPrint_RpcIpArrayPlusParameters( IN PRINT_ROUTINE PrintRoutine, IN OUT PPRINT_CONTEXT pPrintContext, IN LPSTR pszHeader, IN LPSTR pszStructureName, IN LPSTR pszParam1Name, IN DWORD dwParam1, IN LPSTR pszParam2Name, IN DWORD dwParam2, IN LPSTR pszIpArrayHeader, IN PIP_ARRAY pIpArray ) /*++ Routine Description: Print info that contains up to two params and IP_ARRAY. This is kludgy, but there are several RPC types that contain an IP array and some flags. This does the right thing for all those cases. Arguments: pszParam1Name -- name of parameter; pszParam2Name -- name of parameter; serves as flag as to whether param2 is printed pszIpArrayHeader -- name of IP array, passed to DnsPrint_IpArray as header; should be full header line ex. "\tMasters:\n" Return Value: None. --*/ { if ( !pszHeader ) { pszHeader = ""; } DnsPrint_Lock(); PrintRoutine( pPrintContext, "%s%s\n" "\t%s = %d (%p)\n", pszHeader, pszStructureName, pszParam1Name, dwParam1, dwParam1 ); if ( pszParam2Name ) { PrintRoutine( pPrintContext, "\t%s = %d (%p)\n", pszParam2Name, dwParam2, dwParam2 ); } DnsPrint_IpArray( PrintRoutine, pPrintContext, pszIpArrayHeader, "\t\t", pIpArray ); DnsPrint_Unlock(); } VOID DnsPrint_RpcUnion( IN PRINT_ROUTINE PrintRoutine, IN OUT PPRINT_CONTEXT pPrintContext, IN LPSTR pszHeader, IN DWORD dwTypeId, IN PVOID pData ) { if ( !pszHeader ) { pszHeader = ""; } if ( !pData && dwTypeId != DNSSRV_TYPEID_NULL && dwTypeId != DNSSRV_TYPEID_DWORD ) { PrintRoutine( pPrintContext, "%sNull RPC data ptr of type %d.\n", pszHeader, dwTypeId ); return; } switch ( dwTypeId ) { case DNSSRV_TYPEID_NULL: PrintRoutine( pPrintContext, "%sPointer: %p\n", pszHeader, pData ); break; case DNSSRV_TYPEID_DWORD: PrintRoutine( pPrintContext, "%sDword: %d (%p)\n", pszHeader, (DWORD)(UINT_PTR)pData, pData ); break; case DNSSRV_TYPEID_LPSTR: PrintRoutine( pPrintContext, "%sString: %s\n", pszHeader, (LPSTR)pData ); break; case DNSSRV_TYPEID_LPWSTR: PrintRoutine( pPrintContext, "%sWideString: %S\n", pszHeader, (LPWSTR)pData ); break; case DNSSRV_TYPEID_IPARRAY: DnsPrint_IpArray( PrintRoutine, pPrintContext, pszHeader, NULL, (PIP_ARRAY) pData ); break; case DNSSRV_TYPEID_BUFFER: PrintRoutine( pPrintContext, "%sBuffer: length = %d, data ptr = %p\n", pszHeader, ((PDNS_RPC_BUFFER) pData)->dwLength, ((PDNS_RPC_BUFFER) pData)->Buffer ); break; case DNSSRV_TYPEID_SERVER_INFO: DnsPrint_RpcServerInfo( PrintRoutine, pPrintContext, pszHeader, (PDNS_RPC_SERVER_INFO) pData ); break; case DNSSRV_TYPEID_STATS: DnsPrint_RpcSingleStat( PrintRoutine, pPrintContext, pszHeader, (PDNSSRV_STAT) pData ); break; case DNSSRV_TYPEID_ZONE: PrintRoutine( pPrintContext, "%s\n", pszHeader); DnsPrint_RpcZone( PrintRoutine, pPrintContext, NULL, //print default header (PDNS_RPC_ZONE) pData ); break; case DNSSRV_TYPEID_FORWARDERS: DnsPrint_RpcIpArrayPlusParameters( PrintRoutine, pPrintContext, pszHeader, "Forwarders Info:", "Slave", ((PDNS_RPC_FORWARDERS)pData)->fSlave, "Timeout", ((PDNS_RPC_FORWARDERS)pData)->dwForwardTimeout, "\tForwarders:\n", ((PDNS_RPC_FORWARDERS)pData)->aipForwarders ); break; case DNSSRV_TYPEID_ZONE_INFO: DnsPrint_RpcZoneInfo( PrintRoutine, pPrintContext, pszHeader, (PDNS_RPC_ZONE_INFO) pData ); break; case DNSSRV_TYPEID_ZONE_SECONDARIES: DnsPrint_RpcIpArrayPlusParameters( PrintRoutine, pPrintContext, pszHeader, "Zone Secondary Info:", "Secure Secondaries", ((PDNS_RPC_ZONE_SECONDARIES)pData)->fSecureSecondaries, NULL, 0, "\tSecondaries:\n", ((PDNS_RPC_ZONE_SECONDARIES)pData)->aipSecondaries ); break; case DNSSRV_TYPEID_ZONE_TYPE_RESET: DnsPrint_RpcIpArrayPlusParameters( PrintRoutine, pPrintContext, pszHeader, "Zone Type Reset Info:", "ZoneType", ((PDNS_RPC_ZONE_TYPE_RESET)pData)->dwZoneType, NULL, 0, "\tMasters:\n", ((PDNS_RPC_ZONE_TYPE_RESET)pData)->aipMasters ); break; case DNSSRV_TYPEID_ZONE_DATABASE: PrintRoutine( pPrintContext, "%sZone Dbase Info:\n" "\tDS Integrated = %d\n" "\tFile Name = %s\n", pszHeader, ((PDNS_RPC_ZONE_DATABASE)pData)->fDsIntegrated, ((PDNS_RPC_ZONE_DATABASE)pData)->pszFileName ); break; case DNSSRV_TYPEID_ZONE_CREATE: PrintRoutine( pPrintContext, "%sZone Create Info:\n" "\tZone Name = %s\n" "\tType = %d\n" "\tAllow Update = %d\n" "\tDS Integrated = %d\n" "\tFile Name = %s\n" "\tLoad Existing = %d\n" "\tFlags = 0x%08X\n" "\tAdmin Name = %s\n" "\tDirPart Flags = 0x%08X\n" "\tDirPart FQDN = %s\n", pszHeader, ((PDNS_RPC_ZONE_CREATE_INFO)pData)->pszZoneName, ((PDNS_RPC_ZONE_CREATE_INFO)pData)->dwZoneType, ((PDNS_RPC_ZONE_CREATE_INFO)pData)->fAllowUpdate, ((PDNS_RPC_ZONE_CREATE_INFO)pData)->fDsIntegrated, ((PDNS_RPC_ZONE_CREATE_INFO)pData)->pszDataFile, ((PDNS_RPC_ZONE_CREATE_INFO)pData)->fLoadExisting, ((PDNS_RPC_ZONE_CREATE_INFO)pData)->dwFlags, ((PDNS_RPC_ZONE_CREATE_INFO)pData)->pszAdmin, ((PDNS_RPC_ZONE_CREATE_INFO)pData)->dwDpFlags, ((PDNS_RPC_ZONE_CREATE_INFO)pData)->pszDpFqdn ); break; case DNSSRV_TYPEID_NAME_AND_PARAM: PrintRoutine( pPrintContext, "%sName and Parameter:\n" "\tParam = %d (%p)\n" "\tName = %s\n", pszHeader, ((PDNS_RPC_NAME_AND_PARAM)pData)->dwParam, ((PDNS_RPC_NAME_AND_PARAM)pData)->dwParam, ((PDNS_RPC_NAME_AND_PARAM)pData)->pszNodeName ); break; case DNSSRV_TYPEID_ZONE_LIST: DnsPrint_RpcZoneList( PrintRoutine, pPrintContext, NULL, (PDNS_RPC_ZONE_LIST)pData ); break; default: PrintRoutine( pPrintContext, "%s\n" "WARNING: Unknown RPC structure typeid = %d at %p\n", pszHeader, dwTypeId, pData ); break; } } // // Stat validity table. // // Contains match of stat ID and lengths as of this build of RPC client. // typedef struct StatsValidityTableEntry { DWORD Id; WORD wLength; }; struct StatsValidityTableEntry StatsValidityTable[] = { DNSSRV_STATID_TIME, sizeof(DNSSRV_TIME_STATS), DNSSRV_STATID_QUERY, sizeof(DNSSRV_QUERY_STATS), DNSSRV_STATID_QUERY2, sizeof(DNSSRV_QUERY2_STATS), DNSSRV_STATID_RECURSE, sizeof(DNSSRV_RECURSE_STATS), DNSSRV_STATID_MASTER, sizeof(DNSSRV_MASTER_STATS), DNSSRV_STATID_SECONDARY, sizeof(DNSSRV_SECONDARY_STATS), DNSSRV_STATID_WINS, sizeof(DNSSRV_WINS_STATS), DNSSRV_STATID_NBSTAT, sizeof(DNSSRV_NBSTAT_STATS), DNSSRV_STATID_WIRE_UPDATE, sizeof(DNSSRV_UPDATE_STATS), DNSSRV_STATID_NONWIRE_UPDATE, sizeof(DNSSRV_UPDATE_STATS), DNSSRV_STATID_SKWANSEC, sizeof(DNSSRV_SKWANSEC_STATS), DNSSRV_STATID_DS, sizeof(DNSSRV_DS_STATS), DNSSRV_STATID_MEMORY, sizeof(DNSSRV_MEMORY_STATS), DNSSRV_STATID_PACKET, sizeof(DNSSRV_PACKET_STATS), DNSSRV_STATID_DBASE, sizeof(DNSSRV_DBASE_STATS), DNSSRV_STATID_RECORD, sizeof(DNSSRV_RECORD_STATS), DNSSRV_STATID_TIMEOUT, sizeof(DNSSRV_TIMEOUT_STATS), DNSSRV_STATID_ERRORS, sizeof(DNSSRV_ERROR_STATS), DNSSRV_STATID_CACHE, sizeof(DNSSRV_CACHE_STATS), DNSSRV_STATID_PRIVATE, sizeof(DNSSRV_PRIVATE_STATS), 0, 0, // termination }; DNS_STATUS DNS_API_FUNCTION DnssrvValidityCheckStatistic( IN PDNSSRV_STAT pStat ) /*++ Routine Description: Validity check stat struct received from server. Arguments: pStat -- ptr to stat buffer Return Value: ERROR_SUCCESS if valid. DNS_ERROR_INVALID_TYPE if unknown stat id. ERROR_INVALID_DATA if invalid data. --*/ { DWORD i; DWORD id; // // find stat ID in table, and verify length match // i = 0; while ( id = StatsValidityTable[i].Id ) { if ( pStat->Header.StatId == id ) { if ( pStat->Header.wLength == StatsValidityTable[i].wLength - sizeof(DNSSRV_STAT_HEADER) ) { return( ERROR_SUCCESS ); } return( ERROR_INVALID_DATA ); } i++; } return( DNS_ERROR_INVALID_TYPE ); } // // Stat printing. // VOID DnsPrint_RpcStatRaw( IN PRINT_ROUTINE PrintRoutine, IN OUT PPRINT_CONTEXT pPrintContext, IN LPSTR pszHeader, IN PDNSSRV_STAT pStat, IN DNS_STATUS Status ) /*++ Routine Description: Debug print flat stat structure. Arguments: PrintRoutine -- printf like print routine to use pszHeader -- header message to print pStat -- ptr to stat buffer Status -- status result of validity check; if not ERROR_SUCCESS, appropriate error message is printed Return Value: None. --*/ { PDWORD pdword; INT i; PCHAR pstatEnd; DnsPrint_Lock(); if ( pszHeader ) { PrintRoutine( pPrintContext, pszHeader ); } // // validity check stat // if ( Status != ERROR_SUCCESS ) { if ( Status == DNS_ERROR_INVALID_TYPE ) { PrintRoutine( pPrintContext, "Stat ID = %p, is not valid for version of the DNS RPC client.\n", pStat->Header.StatId ); } else if ( Status == ERROR_INVALID_DATA ) { PrintRoutine( pPrintContext, "Stat data length %d is invalid for stat ID = %p\n", pStat->Header.wLength, pStat->Header.StatId ); } PrintRoutine( pPrintContext, "WARNING: DNS RPC client must match version of server for statistics\n" "\tprinting to be formatted appropriately.\n" "Update this tool or the DNS server as necessary to match versions.\n" ); } // // print stat buffer raw // PrintRoutine( pPrintContext, "Stat ID %p:\n", pStat->Header.StatId ); pdword = (PDWORD) pStat->Buffer; pstatEnd = pStat->Header.wLength + (PCHAR)pdword; i = 0; while ( (PCHAR)pdword < pstatEnd ) { PrintRoutine( pPrintContext, " stat[%d] = %10lu\n", i, *pdword ); pdword++; i++; } DnsPrint_Unlock(); } VOID DnsPrint_RpcStatsBuffer( IN PRINT_ROUTINE PrintRoutine, IN OUT PPRINT_CONTEXT pPrintContext, IN LPSTR pszHeader, IN PDNS_RPC_BUFFER pBuffer ) /*++ Routine Description: Debug print stats buffer. Arguments: pBuffer -- buffer containing stats to print Return Value: None. --*/ { PDNSSRV_STAT pstat; PCHAR pch; PCHAR pchstop; DnsPrint_Lock(); if ( pszHeader ) { PrintRoutine( pPrintContext, pszHeader ); } pch = pBuffer->Buffer; pchstop = pch + pBuffer->dwLength; while ( pch < pchstop ) { pstat = (PDNSSRV_STAT) pch; pch = (PCHAR) GET_NEXT_STAT_IN_BUFFER( pstat ); if ( pch > pchstop ) { PrintRoutine( pPrintContext, "ERROR: invalid stats buffer!!!\n" ); break; } DnsPrint_RpcSingleStat( PrintRoutine, pPrintContext, NULL, pstat ); } PrintRoutine( pPrintContext, "\n\n" ); DnsPrint_Unlock(); } VOID printStatTypeArray( IN PRINT_ROUTINE PrintRoutine, IN OUT PPRINT_CONTEXT pPrintContext, IN LPSTR pszHeader, IN PDWORD pArray ) /*++ Routine Description: Debug print stats type array. Arguments: Return Value: None. --*/ { register DWORD i; PrintRoutine( pPrintContext, "%s\n", pszHeader ); // // print counts for all types // - skip mixed and unknown bins until end // for ( i=0; iHeader.StatId ) { case DNSSRV_STATID_TIME: { PDNSSRV_TIME_STATS pstat = (PDNSSRV_TIME_STATS)pStat; SYSTEMTIME localTime; CHAR szdate[30]; CHAR sztime[20]; SystemTimeToTzSpecificLocalTime( NULL, // use local time (PSYSTEMTIME) & pstat->ServerStartTime, & localTime ); GetDateFormat( LOCALE_SYSTEM_DEFAULT, LOCALE_NOUSEROVERRIDE, // (PSYSTEMTIME) &pstat->ServerStartTime, & localTime, NULL, szdate, 30 ); GetTimeFormat( LOCALE_SYSTEM_DEFAULT, LOCALE_NOUSEROVERRIDE, // (PSYSTEMTIME) &pstat->ServerStartTime, & localTime, NULL, sztime, 20 ); PrintRoutine( pPrintContext, "\n" "DNS Server Time Statistics\n" "--------------------------\n" "Server start time %s %s\n" "Seconds since start %10lu\n", szdate, sztime, pstat->SecondsSinceServerStart ); SystemTimeToTzSpecificLocalTime( NULL, // use local time (PSYSTEMTIME) & pstat->LastClearTime, & localTime ); GetDateFormat( LOCALE_SYSTEM_DEFAULT, LOCALE_NOUSEROVERRIDE, // (PSYSTEMTIME) &pstat->LastClearTime, & localTime, NULL, szdate, 30 ); GetTimeFormat( LOCALE_SYSTEM_DEFAULT, LOCALE_NOUSEROVERRIDE, // (PSYSTEMTIME) &pstat->LastClearTime, & localTime, NULL, sztime, 20 ); PrintRoutine( pPrintContext, "Stats last cleared %s %s\n" "Seconds since clear %10lu\n", szdate, sztime, pstat->SecondsSinceLastClear ); break; } case DNSSRV_STATID_QUERY: { PDNSSRV_QUERY_STATS pstat = (PDNSSRV_QUERY_STATS)pStat; PrintRoutine( pPrintContext, "\n" "Queries and Responses:\n" "----------------------\n" "Total:\n" " Queries Received = %10lu\n" " Responses Sent = %10lu\n" "UDP:\n" " Queries Recvd = %10lu\n" " Responses Sent = %10lu\n" " Queries Sent = %10lu\n" " Responses Recvd = %10lu\n" "TCP:\n" " Client Connects = %10lu\n" " Queries Recvd = %10lu\n" " Responses Sent = %10lu\n" " Queries Sent = %10lu\n" " Responses Recvd = %10lu\n", pstat->UdpQueries + pstat->TcpQueries, pstat->UdpResponses + pstat->TcpResponses, pstat->UdpQueries, pstat->UdpResponses, pstat->UdpQueriesSent, pstat->UdpResponsesReceived, pstat->TcpClientConnections, pstat->TcpQueries, pstat->TcpResponses, pstat->TcpQueriesSent, pstat->TcpResponsesReceived ); break; } case DNSSRV_STATID_QUERY2: { PDNSSRV_QUERY2_STATS pstat = (PDNSSRV_QUERY2_STATS)pStat; PrintRoutine( pPrintContext, "\n" "Queries:\n" "--------\n" "Total = %10lu\n" " Notify = %10lu\n" " Update = %10lu\n" " TKeyNego = %10lu\n" " Standard = %10lu\n" " A = %10lu\n" " NS = %10lu\n" " SOA = %10lu\n" " MX = %10lu\n" " PTR = %10lu\n" " SRV = %10lu\n" " ALL = %10lu\n" " IXFR = %10lu\n" " AXFR = %10lu\n" " OTHER = %10lu\n", pstat->TotalQueries, pstat->Notify, pstat->Update, pstat->TKeyNego, pstat->Standard, pstat->TypeA, pstat->TypeNs, pstat->TypeSoa, pstat->TypeMx, pstat->TypePtr, pstat->TypeSrv, pstat->TypeAll, pstat->TypeIxfr, pstat->TypeAxfr, pstat->TypeOther ); break; } case DNSSRV_STATID_RECURSE: { PDNSSRV_RECURSE_STATS pstat = (PDNSSRV_RECURSE_STATS)pStat; PrintRoutine( pPrintContext, "\n" "Recursion:\n" "----------\n" "Query:\n" " Queries Recursed = %10lu\n" " Original Questions = %10lu\n" " Additional Question = %10lu\n" " Total Questions = %10lu\n" " Retries = %10lu\n" " Total Passes = %10lu\n" " ToForwarders = %10lu\n" " Sends = %10lu\n", pstat->QueriesRecursed, pstat->OriginalQuestionRecursed, pstat->AdditionalRecursed, pstat->TotalQuestionsRecursed, pstat->Retries, pstat->LookupPasses, pstat->Forwards, pstat->Sends ); PrintRoutine( pPrintContext, "\n" "Response:\n" " TotalResponses = %10lu\n" " Unmatched = %10lu\n" " Mismatched = %10lu\n" " FromForwarder = %10lu\n" " Authoritative = %10lu\n" " NotAuthoritative = %10lu\n" " Answer = %10lu\n" " Empty = %10lu\n" " NameError = %10lu\n" " Rcode = %10lu\n" " Delegation = %10lu\n" " NonZoneData = %10lu\n" " Unsecure = %10lu\n" " BadPacket = %10lu\n" "Process Response:\n" " Forward Response = %10lu\n" " Continue Recursion = %10lu\n" " Continue Lookup = %10lu\n" " Next Lookup = %10lu\n", pstat->Responses, pstat->ResponseUnmatched, pstat->ResponseMismatched, pstat->ResponseFromForwarder, pstat->ResponseAuthoritative, pstat->ResponseNotAuth, pstat->ResponseAnswer, pstat->ResponseEmpty, pstat->ResponseNameError, pstat->ResponseRcode, pstat->ResponseDelegation, pstat->ResponseNonZoneData, pstat->ResponseUnsecure, pstat->ResponseBadPacket, pstat->SendResponseDirect, pstat->ContinueCurrentRecursion, pstat->ContinueCurrentLookup, pstat->ContinueNextLookup ); PrintRoutine( pPrintContext, "\n" "Timeouts:\n" " Send Timeouts = %10lu\n" " Final Queued = %10lu\n" " Final Expired = %10lu\n" "\n" "Failures:\n" " Recurse Failures = %10lu\n" " Into Authority = %10lu\n" " Previous Zone = %10lu\n" " Retry Limit = %10lu\n" " Partial (HaveAnswer) = %10lu\n" " Cache Update = %10lu\n" " Server Failure Resp = %10lu\n" " Total Failures = %10lu\n", pstat->PacketTimeout, pstat->FinalTimeoutQueued, pstat->FinalTimeoutExpired, pstat->RecursePassFailure, pstat->FailureReachAuthority, pstat->FailureReachPreviousResponse, pstat->FailureRetryCount, pstat->PartialFailure, pstat->CacheUpdateFailure, pstat->ServerFailure, pstat->Failures ); PrintRoutine( pPrintContext, "\n" "TCP Recursion:\n" " Try = %10lu\n" " Query = %10lu\n" " Response = %10lu\n" " Disconnects = %10lu\n" "\n" "Cache Update Queries:\n" " Query = %10lu\n" " Response = %10lu\n" " Retry = %10lu\n" " Free = %10lu\n" " Root NS Query = %10lu\n" " Root NS Response = %10lu\n" " Suspended Query = %10lu\n" " Resume Suspended = %10lu\n" "\n", pstat->TcpTry, pstat->TcpQuery, pstat->TcpResponse, pstat->TcpDisconnect, pstat->CacheUpdateAlloc, pstat->CacheUpdateResponse, pstat->CacheUpdateRetry, pstat->CacheUpdateFree, pstat->RootNsQuery, pstat->RootNsResponse, pstat->SuspendedQuery, pstat->ResumeSuspendedQuery ); PrintRoutine( pPrintContext, "\n" "Other:\n" " Discarded duplicates = %10lu\n" "\n", pstat->DiscardedDuplicateQueries ); break; } case DNSSRV_STATID_MASTER: { PDNSSRV_MASTER_STATS pstat = (PDNSSRV_MASTER_STATS)pStat; PrintRoutine( pPrintContext, "\n" "Master Stats:\n" "-------------\n" "Notifies Sent = %10lu\n" "\n" "Requests = %10lu\n" " NameError = %10lu\n" " FormError = %10lu\n" " Refused = %10lu\n" " AxfrLimit = %10lu\n" " Security = %10lu\n" " Shutdown = %10lu\n" " ZoneLocked = %10lu\n" " ServerFailure = %10lu\n" " Failure = %10lu\n" " Success = %10lu\n" "\n" "AXFR Request = %10lu\n" " Success = %10lu\n" " In IXFR = %10lu\n" "\n" "IXFR Request = %10lu\n" " Success Update = %10lu\n" " UDP Request = %10lu\n" " Success = %10lu\n" " Force TCP = %10lu\n" " Force Full = %10lu\n" " TCP Request = %10lu\n" " Success = %10lu\n" " Do Full = %10lu\n" "\n", pstat->NotifySent, pstat->Request, pstat->NameError, pstat->FormError, pstat->Refused, pstat->AxfrLimit, pstat->RefuseSecurity, pstat->RefuseShutdown, pstat->RefuseZoneLocked, pstat->RefuseServerFailure, pstat->Failure, (pstat->AxfrSuccess + pstat->IxfrUpdateSuccess), pstat->AxfrRequest, pstat->AxfrSuccess, pstat->IxfrAxfr, pstat->IxfrRequest, pstat->IxfrUpdateSuccess, pstat->IxfrUdpRequest, pstat->IxfrUdpSuccess, pstat->IxfrUdpForceTcp, pstat->IxfrUdpForceAxfr, pstat->IxfrTcpRequest, pstat->IxfrTcpSuccess, pstat->IxfrAxfr ); break; } case DNSSRV_STATID_SECONDARY: { PDNSSRV_SECONDARY_STATS pstat = (PDNSSRV_SECONDARY_STATS)pStat; PrintRoutine( pPrintContext, "\n" "Secondary Stats:\n" "----------------\n" "NOTIFY:\n" " Received = %10lu\n" " Invalid = %10lu\n" " Primary = %10lu\n" " No Version = %10lu\n" " New Version = %10lu\n" " Current Version = %10lu\n" " Old Version = %10lu\n" " Master Unknown = %10lu\n" "\n" "SOA Query:\n" " Request = %10lu\n" " Response = %10lu\n" " Invalid = %10lu\n" " NameError = %10lu\n" "\n" "AXFR:\n" " AXFR Request = %10lu\n" " AXFR in IXFR = %10lu\n" " Response = %10lu\n" " Success = %10lu\n" " Refused = %10lu\n" " Invalid = %10lu\n" "\n" "Stub zone AXFR:\n" " Stub AXFR Request = %10lu\n" " Response = %10lu\n" " Success = %10lu\n" " Refused = %10lu\n" " Invalid = %10lu\n" "\n" "IXFR UDP:\n" " Request = %10lu\n" " Response = %10lu\n" " Success = %10lu\n" " UseTcp = %10lu\n" " UseAxfr = %10lu\n" " New Primary = %10lu\n" " Refused = %10lu\n" " Wrong Server = %10lu\n" " FormError = %10lu\n" " Invalid = %10lu\n" "\n" "IXFR TCP:\n" " Request = %10lu\n" " Response = %10lu\n" " Success = %10lu\n" " AXFR = %10lu\n" " FormError = %10lu\n" " Refused = %10lu\n" " Invalid = %10lu\n" "\n", pstat->NotifyReceived, pstat->NotifyInvalid, pstat->NotifyPrimary, pstat->NotifyNoVersion, pstat->NotifyNewVersion, pstat->NotifyCurrentVersion, pstat->NotifyOldVersion, pstat->NotifyMasterUnknown, pstat->SoaRequest, pstat->SoaResponse, pstat->SoaResponseInvalid, pstat->SoaResponseNameError, pstat->AxfrRequest, pstat->IxfrTcpAxfr, pstat->AxfrResponse, pstat->AxfrSuccess, pstat->AxfrRefused, pstat->AxfrInvalid, pstat->StubAxfrRequest, pstat->StubAxfrResponse, pstat->StubAxfrSuccess, pstat->StubAxfrRefused, pstat->StubAxfrInvalid, pstat->IxfrUdpRequest, pstat->IxfrUdpResponse, pstat->IxfrUdpSuccess, pstat->IxfrUdpUseTcp, pstat->IxfrUdpUseAxfr, pstat->IxfrUdpNewPrimary, pstat->IxfrUdpRefused, pstat->IxfrUdpWrongServer, pstat->IxfrUdpFormerr, pstat->IxfrUdpInvalid, pstat->IxfrTcpRequest, pstat->IxfrTcpResponse, pstat->IxfrTcpSuccess, pstat->IxfrTcpAxfr, pstat->IxfrTcpFormerr, pstat->IxfrTcpRefused, pstat->IxfrTcpInvalid ); break; } case DNSSRV_STATID_WINS: { PDNSSRV_WINS_STATS pstat = (PDNSSRV_WINS_STATS)pStat; PrintRoutine( pPrintContext, "\n" "WINS Referrals:\n" "---------------\n" "Forward:\n" " Lookups = %10lu\n" " Responses = %10lu\n" "Reverse:\n" " Lookups = %10lu\n" " Responses = %10lu\n", pstat->WinsLookups, pstat->WinsResponses, pstat->WinsReverseLookups, pstat->WinsReverseResponses ); break; } case DNSSRV_STATID_NBSTAT: { PDNSSRV_NBSTAT_STATS pstat = (PDNSSRV_NBSTAT_STATS)pStat; PrintRoutine( pPrintContext, "\n" "Nbstat Memory Usage:\n" "--------------------\n" "Nbstat Buffers:\n" " Alloc = %10lu\n" " Free = %10lu\n" " NetAllocs = %10lu\n" " Memory = %10lu\n" " Used = %10lu\n" " Returned = %10lu\n" " InUse = %10lu\n" " InFreeList = %10lu\n" "\n", pstat->NbstatAlloc, pstat->NbstatFree, pstat->NbstatNetAllocs, pstat->NbstatMemory, pstat->NbstatUsed, pstat->NbstatReturn, pstat->NbstatInUse, pstat->NbstatInFreeList ); break; } case DNSSRV_STATID_WIRE_UPDATE: case DNSSRV_STATID_NONWIRE_UPDATE: { PDNSSRV_UPDATE_STATS pstat = (PDNSSRV_UPDATE_STATS)pStat; PrintRoutine( pPrintContext, "\n" "%s:\n" "--------------------------\n" "Updates Received = %10lu\n" " Forwarded = %10lu\n" " Empty (PreCon Only) = %10lu\n" " NoOps (Dups) = %10lu\n" " Rejected = %10lu\n" " Completed = %10lu\n" " Timed Out = %10lu\n" " In Queue = %10lu\n" "\n" "Updates Rejected = %10lu\n" " FormError = %10lu\n" " NameError = %10lu\n" " NotImpl = %10lu (Non-Update Zone)\n" " Refused = %10lu\n" " NonSecure Packet = %10lu\n" " AccessDenied = %10lu\n" " YxDomain = %10lu\n" " YxRRSet = %10lu\n" " NxRRSet = %10lu\n" " NotAuth = %10lu\n" " NotZone = %10lu\n" "\n" #if 0 // unused counters "Update Collisions = %10lu\n" " Read = %10lu\n" " Write = %10lu\n" " In LDAP = %10lu\n" "\n" #endif "Queue\n" " Queued = %10lu\n" " Retried = %10lu\n" " Timeout = %10lu\n" " In Queue = %10lu\n" "\n" "Secure Update\n" " Success = %10lu\n" " Continue = %10lu\n" " Failure = %10lu\n" " DS Write Failure = %10lu\n" "\n" "Update Forwarding\n" " Forwards = %10lu\n" " TCP Forwards = %10lu\n" " Responses = %10lu\n" " Timed Out = %10lu\n" " In Queue = %10lu\n" "\n", pStat->Header.StatId == DNSSRV_STATID_WIRE_UPDATE ? "Packet Dynamic Update" : "Internal Dynamic Update", pstat->Received, pstat->Forwards, pstat->Empty, pstat->NoOps, pstat->Rejected, pstat->Completed, pstat->Timeout, pstat->InQueue, pstat->Rejected, pstat->FormErr, pstat->NxDomain, pstat->NotImpl, pstat->Refused, pstat->RefusedNonSecure, pstat->RefusedAccessDenied, pstat->YxDomain, pstat->YxRrset, pstat->NxRrset, pstat->NotAuth, pstat->NotZone, #if 0 // unused counters pstat->Collisions, pstat->CollisionsRead, pstat->CollisionsWrite, pstat->CollisionsDsWrite, #endif pstat->Queued, pstat->Retry, pstat->Timeout, pstat->InQueue, pstat->SecureSuccess, pstat->SecureContinue, pstat->SecureFailure, pstat->SecureDsWriteFailure, pstat->Forwards, pstat->TcpForwards, pstat->ForwardResponses, pstat->ForwardTimeouts, pstat->ForwardInQueue ); printStatTypeArray( PrintRoutine, pPrintContext, "Update Types:", pstat->UpdateType ); break; } case DNSSRV_STATID_DS: { PDNSSRV_DS_STATS pstat = (PDNSSRV_DS_STATS)pStat; PrintRoutine( pPrintContext, "\n" "DS Integration:\n" "---------------\n" "DS Reads:\n" " Nodes Read Total = %10lu\n" " Records Read Total = %10lu\n" " Nodes Loaded = %10lu\n" " Records Loaded = %10lu\n" "\n" " Update Searches = %10lu\n" " Update Nodes Read = %10lu\n" " Update Records Read = %10lu\n" "\n" "DS Writes:\n" " Nodes Added = %10lu\n" " Nodes Modified = %10lu\n" " Nodes Tombstoned = %10lu\n" " Nodes Final Delete = %10lu\n" " Node Write Suppressed = %10lu\n" " RR Sets Added = %10lu\n" " RR Sets Replaced = %10lu\n" " Serial Writes = %10lu\n" "\n" " Update Lists = %10lu\n" " Update Nodes = %10lu\n" " Suppressed = %10lu\n" " Writes = %10lu\n" " Tombstones = %10lu\n" " Write causes:\n" " Record Change = %10lu\n" " Aging Refresh = %10lu\n" " Aging On = %10lu\n" " Aging Off = %10lu\n" " Write sources:\n" " Packet = %10lu\n" " Precon Only = %10lu\n" " Admin = %10lu\n" " Auto Config = %10lu\n" " Scavenge = %10lu\n", pstat->DsTotalNodesRead, pstat->DsTotalRecordsRead, pstat->DsNodesLoaded, pstat->DsRecordsLoaded, pstat->DsUpdateSearches, pstat->DsUpdateNodesRead, pstat->DsUpdateRecordsRead, pstat->DsNodesAdded, pstat->DsNodesModified, pstat->DsNodesTombstoned, pstat->DsNodesDeleted, pstat->DsWriteSuppressed, pstat->DsRecordsAdded, pstat->DsRecordsReplaced, pstat->DsSerialWrites, pstat->UpdateLists, pstat->UpdateNodes, pstat->UpdateSuppressed, pstat->UpdateWrites, pstat->UpdateTombstones, pstat->UpdateRecordChange, pstat->UpdateAgingRefresh, pstat->UpdateAgingOn, pstat->UpdateAgingOff, pstat->UpdatePacket, pstat->UpdatePacketPrecon, pstat->UpdateAdmin, pstat->UpdateAutoConfig, pstat->UpdateScavenge ); PrintRoutine( pPrintContext, "\n" "Tombstones:\n" " Written = %10lu\n" " Read = %10lu\n" " Deleted = %10lu\n" "\n" "Write Performance:\n" " Total = %10lu\n" " Total Time = %10lu\n" " Average = %10lu\n" " < 10ms = %10lu\n" " < 100ms = %10lu\n" " < 1s = %10lu\n" " < 10s = %10lu\n" " < 100s = %10lu\n" " > 100s = %10lu\n" " Max = %10lu\n" "Search Performance:\n" " Total (ms) = %10lu\n" "\n" "Failures:\n" " FailedDeleteDsEntries = %10lu\n" " FailedReadRecords = %10lu\n" " FailedLdapModify = %10lu\n" " FailedLdapAdd = %10lu\n" "\n" "Polling:\n" " PollingPassesWithErrors = %10lu\n" "\n", pstat->DsNodesTombstoned, pstat->DsTombstonesRead, pstat->DsNodesDeleted, pstat->LdapTimedWrites, pstat->LdapWriteTimeTotal, pstat->LdapWriteAverage, pstat->LdapWriteBucket0, pstat->LdapWriteBucket1, pstat->LdapWriteBucket2, pstat->LdapWriteBucket3, pstat->LdapWriteBucket4, pstat->LdapWriteBucket5, pstat->LdapWriteMax, pstat->LdapSearchTime, pstat->FailedDeleteDsEntries, pstat->FailedReadRecords, pstat->FailedLdapModify, pstat->FailedLdapAdd, pstat->PollingPassesWithDsErrors ); printStatTypeArray( PrintRoutine, pPrintContext, "DS Write Types:", pstat->DsWriteType ); break; } case DNSSRV_STATID_SKWANSEC: { PDNSSRV_SKWANSEC_STATS pstat = (PDNSSRV_SKWANSEC_STATS)pStat; PrintRoutine( pPrintContext, "\n" "SkwanSec Stats:\n" "---------------\n" "\n" "Security Context:\n" " Create = %10lu\n" " Free = %10lu\n" " Timeout = %10lu\n" " Queue Length = %10lu\n" " Queued = %10lu\n" " In Nego = %10lu\n" " Nego Complete = %10lu\n" " DeQueued = %10lu\n" "\n" "Security Packet Contexts:\n" " Alloc = %10lu\n" " Free = %10lu\n" "\n" "TKEY:\n" " Invalid = %10lu\n" " BadTime = %10lu\n" "\n" "TSIG:\n" " Formerr = %10lu\n" " Echo = %10lu\n" " BadKey = %10lu\n" " Verify Success = %10lu\n" " Verify Failed = %10lu\n" "\n", pstat->SecContextCreate, pstat->SecContextFree, pstat->SecContextTimeout, pstat->SecContextQueueLength, pstat->SecContextQueue, pstat->SecContextQueueInNego, pstat->SecContextQueueNegoComplete, pstat->SecContextDequeue, pstat->SecPackAlloc, pstat->SecPackFree, pstat->SecTkeyInvalid, pstat->SecTkeyBadTime, pstat->SecTsigFormerr, pstat->SecTsigEcho, pstat->SecTsigBadKey, pstat->SecTsigVerifySuccess, pstat->SecTsigVerifyFailed ); break; } case DNSSRV_STATID_MEMORY: { PDNSSRV_MEMORY_STATS pstat = (PDNSSRV_MEMORY_STATS) pStat; DWORD i; LPSTR * pnameArray; DWORD count; pnameArray = MemTagStrings; count = MEMTAG_COUNT; PrintRoutine( pPrintContext, "\n" "Memory Stats:\n" "-------------\n" "Memory:\n" " Total Memory = %10lu\n" " Alloc Count = %10lu\n" " Free Count = %10lu\n" "\n" "Standard Allocs:\n" " Used = %10lu\n" " Returned = %10lu\n" " InUse = %10lu\n" " Memory = %10lu\n" "\n" "Standard To Heap:\n" " Alloc = %10lu\n" " Free = %10lu\n" " InUse = %10lu\n" " Memory = %10lu\n" "\n" "Standard Blocks:\n" " Alloc = %10lu\n" " Used = %10lu\n" " Returned = %10lu\n" " InUse = %10lu\n" " FreeList = %10lu\n" " FreeList Memory = %10lu\n" " Total Memory = %10lu\n" "\n" "Tagged Allocations:\n", pstat->Memory, pstat->Alloc, pstat->Free, pstat->StdUsed, pstat->StdReturn, pstat->StdInUse, pstat->StdMemory, pstat->StdToHeapAlloc, pstat->StdToHeapFree, pstat->StdToHeapInUse, pstat->StdToHeapMemory, pstat->StdBlockAlloc, pstat->StdBlockUsed, pstat->StdBlockReturn, pstat->StdBlockInUse, pstat->StdBlockFreeList, pstat->StdBlockFreeListMemory, pstat->StdBlockMemory ); for ( i=0; iMemTags[ i ].Alloc, pstat->MemTags[ i ].Free, pstat->MemTags[ i ].Alloc - pstat->MemTags[i].Free, pstat->MemTags[ i ].Memory ); } break; } case DNSSRV_STATID_DBASE: { PDNSSRV_DBASE_STATS pstat = (PDNSSRV_DBASE_STATS)pStat; PrintRoutine( pPrintContext, "\n" "Database Nodes:\n" "---------------\n" "Nodes:\n" " Used = %10lu\n" " Returned = %10lu\n" " InUse = %10lu\n" " Memory = %10lu\n" "\n", pstat->NodeUsed, pstat->NodeReturn, pstat->NodeInUse, pstat->NodeMemory ); break; } case DNSSRV_STATID_RECORD: { PDNSSRV_RECORD_STATS pstat = (PDNSSRV_RECORD_STATS)pStat; PrintRoutine( pPrintContext, "\n" "Records:\n" "--------\n" "Flow:\n" " Used = %10lu\n" " Returned = %10lu\n" " InUse = %10lu\n" " SlowFree Queued = %10lu\n" " SlowFree Completed = %10lu\n" " Memory = %10lu\n" "\n" "Caching:\n" " Total = %10lu\n" " Timeouts = %10lu\n" " In Use = %10lu\n" "\n", pstat->Used, pstat->Return, pstat->InUse, pstat->SlowFreeQueued, pstat->SlowFreeFinished, pstat->Memory, pstat->CacheTotal, pstat->CacheTimeouts, pstat->CacheCurrent ); break; } case DNSSRV_STATID_PACKET: { PDNSSRV_PACKET_STATS pstat = (PDNSSRV_PACKET_STATS)pStat; PrintRoutine( pPrintContext, "\n" "Packet Memory Usage:\n" "--------------------\n" "UDP Messages:\n" " Alloc = %10lu\n" " Free = %10lu\n" " NetAllocs = %10lu\n" " Memory = %10lu\n" " Used = %10lu\n" " Returned = %10lu\n" " InUse = %10lu\n" " InFreeList = %10lu\n", pstat->UdpAlloc, pstat->UdpFree, pstat->UdpNetAllocs, pstat->UdpMemory, pstat->UdpUsed, pstat->UdpReturn, pstat->UdpInUse, pstat->UdpInFreeList ); // // NS List stats added after Whistler beta 2. // PrintRoutine( pPrintContext, " NsListUsed = %10lu\n" " NsListReturned = %10lu\n" " NsListInUse = %10lu\n", pstat->UdpPacketsForNsListUsed, pstat->UdpPacketsForNsListReturned, pstat->UdpPacketsForNsListInUse ); PrintRoutine( pPrintContext, "\n" "TCP Messages:\n" " Alloc = %10lu\n" " Realloc = %10lu\n" " Free = %10lu\n" " NetAllocs = %10lu\n" " Memory = %10lu\n" "\n" "Recursion Messages:\n" " Used = %10lu\n" " Returned = %10lu\n" "\n", pstat->TcpAlloc, pstat->TcpRealloc, pstat->TcpFree, pstat->TcpNetAllocs, pstat->TcpMemory, pstat->RecursePacketUsed, pstat->RecursePacketReturn ); break; } case DNSSRV_STATID_TIMEOUT: { PDNSSRV_TIMEOUT_STATS pstat = (PDNSSRV_TIMEOUT_STATS)pStat; PrintRoutine( pPrintContext, "\n" "Timeout:\n" "--------\n" "Nodes Queued\n" " Total = %10lu\n" " Direct = %10lu\n" " FromReference = %10lu\n" " FromChildDelete = %10lu\n" " Dup Already Queued = %10lu\n" "Nodes Checked\n" " Total = %10lu\n" " RecentAccess = %10lu\n" " ActiveRecord = %10lu\n" " CanNotDelete = %10lu\n" " Deleted = %10lu\n" "TimeoutBlocks\n" " Created = %10lu\n" " Deleted = %10lu\n" "Delayed Frees\n" " Queued = %10lu\n" " WithFunction = %10lu\n" " Executed = %10lu\n" " WithFunction = %10lu\n", pstat->SetTotal, pstat->SetDirect, pstat->SetFromDereference, pstat->SetFromChildDelete, pstat->AlreadyInSystem, pstat->Checks, pstat->RecentAccess, pstat->ActiveRecord, pstat->CanNotDelete, pstat->Deleted, pstat->ArrayBlocksCreated, pstat->ArrayBlocksDeleted, pstat->DelayedFreesQueued, pstat->DelayedFreesQueuedWithFunction, pstat->DelayedFreesExecuted, pstat->DelayedFreesExecutedWithFunction ); break; } case DNSSRV_STATID_ERRORS: { PDNSSRV_ERROR_STATS pstat = (PDNSSRV_ERROR_STATS)pStat; PrintRoutine( pPrintContext, "\n" "Error Stats:\n" "--------------\n" "\n" " NoError = %10lu\n" " FormError = %10lu\n" " ServFail = %10lu\n" " NxDomain = %10lu\n" " NotImpl = %10lu\n" " Refused = %10lu\n" " YxDomain = %10lu\n" " YxRRSet = %10lu\n" " NxRRSet = %10lu\n" " NotAuth = %10lu\n" " NotZone = %10lu\n" " Max = %10lu\n" " BadSig = %10lu\n" " BadKey = %10lu\n" " BadTime = %10lu\n" " UnknownError = %10lu\n" "\n", pstat->NoError, pstat->FormError, pstat->ServFail, pstat->NxDomain, pstat->NotImpl, pstat->Refused, pstat->YxDomain, pstat->YxRRSet, pstat->NxRRSet, pstat->NotAuth, pstat->NotZone, pstat->Max, pstat->BadSig, pstat->BadKey, pstat->BadTime, pstat->UnknownError ); break; } case DNSSRV_STATID_CACHE: { PDNSSRV_CACHE_STATS pstat = ( PDNSSRV_CACHE_STATS ) pStat; PrintRoutine( pPrintContext, "\n" "Cache Stats:\n" "------------\n" " Checks where cache exceeded limit = %10lu\n" " Successful cache enforcement passes = %10lu\n" " Failed cache enforcement passes = %10lu\n" " Passes that required aggressive free = %10lu\n" " Passes where nothing was freed = %10lu\n\n", pstat->CacheExceededLimitChecks, pstat->SuccessfulFreePasses, pstat->FailedFreePasses, pstat->PassesRequiringAggressiveFree, pstat->PassesWithNoFrees ); break; } case DNSSRV_STATID_PRIVATE: { PDNSSRV_PRIVATE_STATS pstat = (PDNSSRV_PRIVATE_STATS)pStat; PrintRoutine( pPrintContext, "\n" "Private Stats:\n" "--------------\n" "\n" "Record Sources:\n" " RR File = %10lu\n" " RR File Free = %10lu\n" " RR DS = %10lu\n" " RR DS Free = %10lu\n" " RR Admin = %10lu\n" " RR Admin Free = %10lu\n" " RR DynUp = %10lu\n" " RR DynUp Free = %10lu\n" " RR Axfr = %10lu\n" " RR Axfr Free = %10lu\n" " RR Ixfr = %10lu\n" " RR Ixfr Free = %10lu\n" " RR Copy = %10lu\n" " RR Copy Free = %10lu\n" " RR Cache = %10lu\n" " RR Cache Free = %10lu\n" #if 0 " RR NoExist = %10lu\n" " RR NoExist Free = %10lu\n" " RR Wins = %10lu\n" " RR Wins Free = %10lu\n" " RR WinsPtr = %10lu\n" " RR WinsPtr Free = %10lu\n" " RR Auto = %10lu\n" " RR Auto Free = %10lu\n" " RR Unknown = %10lu\n" " RR Unknown Free = %10lu\n" #endif "\n" "UDP Sockets:\n" " PnP Socket Delete = %10lu\n" " Recvfrom Failure = %10lu\n" " ConnResets = %10lu\n" " ConnReset Overflow = %10lu\n" " GQCS Failure = %10lu\n" " GQCS Failure wCntxt = %10lu\n" " GQCS ConnReset = %10lu\n" " Indicate Recv Fail = %10lu\n" " Restart Recv Pass = %10lu\n" "\n" "TCP Connections:\n" " ConnectAttempt = %10lu\n" " ConnectFailure = %10lu\n" " Connect = %10lu\n" " Query = %10lu\n" " Disconnect = %10lu\n" "\n" "SkwanSec Hacks:\n" " Verified Old Sig = %10lu\n" " Failed Old Sig = %10lu\n" " Big TimeSkew Bypass = %10lu\n" "\n", pstat->RecordFile, pstat->RecordFileFree, pstat->RecordDs, pstat->RecordDsFree, pstat->RecordAdmin, pstat->RecordAdminFree, pstat->RecordDynUp, pstat->RecordDynUpFree, pstat->RecordAxfr, pstat->RecordAxfrFree, pstat->RecordIxfr, pstat->RecordIxfrFree, pstat->RecordCopy, pstat->RecordCopyFree, pstat->RecordCache, pstat->RecordCacheFree, #if 0 pstat->RecordNoExist, pstat->RecordNoExistFree, pstat->RecordWins, pstat->RecordWinsFree, pstat->RecordWinsPtr, pstat->RecordWinsPtrFree, pstat->RecordAuto, pstat->RecordAutoFree, pstat->RecordUnknown, pstat->RecordUnknownFree, #endif pstat->UdpSocketPnpDelete, pstat->UdpRecvFailure, pstat->UdpConnResets, pstat->UdpConnResetRetryOverflow, pstat->UdpGQCSFailure, pstat->UdpGQCSFailureWithContext, pstat->UdpGQCSConnReset, pstat->UdpIndicateRecvFailures, pstat->UdpRestartRecvOnSockets, pstat->TcpConnectAttempt, pstat->TcpConnectFailure, pstat->TcpConnect, pstat->TcpQuery, pstat->TcpDisconnect, pstat->SecTsigVerifyOldSig, pstat->SecTsigVerifyOldFailed, pstat->SecBigTimeSkewBypass ); break; } default: DnsPrint_RpcStatRaw( PrintRoutine, pPrintContext, NULL, pStat, DNS_ERROR_INVALID_TYPE ); break; } // end switch DnsPrint_Unlock(); } // // End of print.c //