windows-nt/Source/XPSP1/NT/ds/dns/server/client/nt4api.c

1259 lines
28 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1995 Microsoft Corporation
Module Name:
nt4api.c
Abstract:
Domain Name System (DNS) Server -- Admin Client API
DNS NT4 API that are not direct calls to RPC stubs.
Author:
Jim Gilroy (jamesg) 14-Oct-1995
Environment:
User Mode - Win32
Revision History:
--*/
#include "dnsclip.h"
VOID
DNS_API_FUNCTION
Dns4_FreeZoneInfo(
IN OUT PDNS4_ZONE_INFO pZoneInfo
)
/*++
Routine Description:
Deep free of DNS4_ZONE_INFO structure.
Arguments:
pZoneInfo -- ptr to zone info to free
Return Value:
None
--*/
{
if ( !pZoneInfo )
{
return;
}
//
// free substructures
// - name string
// - data file string
// - secondary IP array
// - WINS server array
//
if ( pZoneInfo->pszZoneName )
{
MIDL_user_free( pZoneInfo->pszZoneName );
}
if ( pZoneInfo->pszDataFile )
{
MIDL_user_free( pZoneInfo->pszDataFile );
}
if ( pZoneInfo->aipMasters )
{
MIDL_user_free( pZoneInfo->aipMasters );
}
if ( pZoneInfo->aipSecondaries )
{
MIDL_user_free( pZoneInfo->aipSecondaries );
}
//
// free DNS4_ZONE_INFO struct itself
//
MIDL_user_free( pZoneInfo );
}
DNS_STATUS
DNS_API_FUNCTION
Dns4_ResetZoneMaster(
IN LPCSTR Server,
IN DNS_HANDLE hZone,
IN IP_ADDRESS ipMaster
)
/*++
Routine Description:
Reset one zone master
--*/
{
IP_ADDRESS ipBuf = ipMaster;
return Dns4_ResetZoneMasters(
Server,
hZone,
1,
& ipBuf );
}
DNS_STATUS
DNS_API_FUNCTION
Dns4_EnumZoneInfo(
IN LPCSTR Server,
OUT PDWORD pdwZoneCount,
IN DWORD dwArrayCount,
IN OUT PDNS4_ZONE_INFO apZones[]
)
/*++
Routine Description:
Get zone info for all zones on server.
Arguments:
Server -- server name
pdwZoneCount -- addr to recv number of zones on server
dwArrayCount -- size of zone info ptr array
apZones -- array to be filled with zone info ptrs
Return Value:
None
--*/
{
DNS_STATUS status;
PDNS_HANDLE ahZones;
INT i;
DWORD zoneCount = 0;
IF_DNSDBG( STUB )
{
DNS_PRINT((
"Enter DnsEnumZoneInfo()\n"
"\tServer = %s\n"
"\tpdwZoneCount = %p\n"
"\tdwArrayCount = %d\n"
"\tapZones = %p\n",
Server,
pdwZoneCount,
dwArrayCount,
apZones ));
DnsDbg_DwordArray(
"Zone array",
NULL,
dwArrayCount,
(PDWORD)apZones );
}
//
// allocate space
// - allocate for as many entries as caller is allowing zones
// zones
ahZones = (PDNS_HANDLE) MIDL_user_allocate(
dwArrayCount * sizeof(DNS_HANDLE) );
if ( !ahZones )
{
return( DNS_ERROR_NO_MEMORY );
}
IF_DNSDBG( STUB )
{
DNS_PRINT((
"Allocated zone HANDLE block at %p for up to %d zones\n",
ahZones,
dwArrayCount ));
DnsDbg_DwordArray(
"Zone handle array",
NULL,
dwArrayCount,
ahZones );
}
//
// get zone handles
//
status = Dns4_EnumZoneHandles(
Server,
& zoneCount,
dwArrayCount,
ahZones
);
IF_DNSDBG( STUB )
{
DNS_PRINT((
"Under call to DnsEnumZoneHandles() completed.\n"
"\tstatus = %d (%p)\n"
"\tzone count = %d\n",
status, status,
zoneCount ));
DnsDbg_DwordArray(
"Zone handle array",
NULL,
(zoneCount < dwArrayCount) ? zoneCount+1 : dwArrayCount,
ahZones );
}
*pdwZoneCount = zoneCount;
if ( status != ERROR_SUCCESS )
{
return( status );
}
//
// get info for each zone
//
for( i=0; i<(INT)zoneCount; i++ )
{
apZones[i] = NULL;
status = Dns4_GetZoneInfo(
Server,
ahZones[i],
& apZones[i] );
if ( status != ERROR_SUCCESS )
{
goto cleanup;
}
}
IF_DNSDBG( STUB )
{
Dns4_Dbg_RpcZoneInfoList(
"Leaving DnsEnumZoneInfo() ",
*pdwZoneCount,
apZones );
}
cleanup:
IF_DNSDBG( STUB )
{
if ( status != ERROR_SUCCESS )
{
DNS_PRINT((
"Leaving DnsEnumZoneInfo(), status = %d\n",
status ));
}
}
MIDL_user_free( ahZones );
return( status );
}
//
// NT4 type print
//
VOID
Dns4_Print_RpcServerInfo(
IN PRINT_ROUTINE PrintRoutine,
IN LPSTR pszHeader,
IN PDNS4_RPC_SERVER_INFO pServerInfo
)
{
DnsPrint_Lock();
if ( pszHeader )
{
PrintRoutine( pszHeader );
}
if ( ! pServerInfo )
{
PrintRoutine( "NULL server info ptr.\n" );
}
else
{
PrintRoutine(
"Server info:\n"
"\tptr = %p\n"
"\tversion = %p\n"
"\tboot registry = %d\n",
pServerInfo,
pServerInfo->dwVersion,
pServerInfo->fBootRegistry );
DnsPrint_IpArray(
PrintRoutine,
NULL,
"\tServerAddresses:\n",
"\tAddr",
pServerInfo->aipServerAddrs );
DnsPrint_IpArray(
PrintRoutine,
NULL,
"\tListenAddresses:\n",
"\tAddr",
pServerInfo->aipListenAddrs );
DnsPrint_IpArray(
PrintRoutine,
NULL,
"\tForwarders:\n",
"\tAddr",
pServerInfo->aipForwarders );
PrintRoutine(
"\tforward timeout = %d\n"
"\tslave = %d\n",
pServerInfo->dwForwardTimeout,
pServerInfo->fSlave );
}
DnsPrint_Unlock();
}
VOID
Dns4_Print_RpcStatistics(
IN PRINT_ROUTINE PrintRoutine,
IN LPSTR pszHeader,
IN PDNS4_STATISTICS pStatistics
)
/*++
Routine Description:
Debug print statistics.
Arguments:
None.
Return Value:
None.
--*/
{
CHAR szdate[30];
CHAR sztime[20];
DnsPrint_Lock();
if ( pszHeader )
{
PrintRoutine( pszHeader );
}
GetDateFormat(
LOCALE_SYSTEM_DEFAULT,
LOCALE_NOUSEROVERRIDE,
(PSYSTEMTIME) &pStatistics->ServerStartTime,
NULL,
szdate,
30 );
GetTimeFormat(
LOCALE_SYSTEM_DEFAULT,
LOCALE_NOUSEROVERRIDE,
(PSYSTEMTIME) &pStatistics->ServerStartTime,
NULL,
sztime,
20 );
PrintRoutine(
"\n"
"DNS Statistics\n"
"--------------\n"
"\tServer start time %s %s\n",
szdate,
sztime );
GetDateFormat(
LOCALE_SYSTEM_DEFAULT,
LOCALE_NOUSEROVERRIDE,
(PSYSTEMTIME) &pStatistics->LastClearTime,
NULL,
szdate,
30 );
GetTimeFormat(
LOCALE_SYSTEM_DEFAULT,
LOCALE_NOUSEROVERRIDE,
(PSYSTEMTIME) &pStatistics->LastClearTime,
NULL,
sztime,
20 );
PrintRoutine(
"\tStats last cleared %s %s\n"
"\tSeconds since clear %d\n",
szdate,
sztime,
pStatistics->SecondsSinceLastClear
);
//
// query and response counts
//
PrintRoutine(
"\n"
"Queries and Responses:\n"
"----------------------\n"
"Total:\n"
"\tQueries Received = %d\n"
"\tResponses Sent = %d\n"
"UDP:\n"
"\tQueries Recvd = %d\n"
"\tResponses Sent = %d\n"
"\tQueries Sent = %d\n"
"\tResponses Recvd = %d\n"
"TCP:\n"
"\tClient Connects = %d\n"
"\tQueries Recvd = %d\n"
"\tResponses Sent = %d\n"
"\tQueries Sent = %d\n"
"\tResponses Recvd = %d\n",
pStatistics->UdpQueries + pStatistics->TcpQueries,
pStatistics->UdpResponses + pStatistics->TcpResponses,
pStatistics->UdpQueries,
pStatistics->UdpResponses,
pStatistics->UdpQueriesSent,
pStatistics->UdpResponsesReceived,
pStatistics->TcpClientConnections,
pStatistics->TcpQueries,
pStatistics->TcpResponses,
pStatistics->TcpQueriesSent,
pStatistics->TcpResponsesReceived
);
PrintRoutine(
"\n"
"Recursion:\n"
"----------\n"
"\tPackets = %d\n"
"\tLookups = %d\n"
"\tQuestions = %d\n"
"\tPasses = %d\n"
"\tForwards = %d\n"
"\tSends = %d\n"
"\tResponses = %d\n"
"\tTimeouts = %d\n"
"\tFailures = %d\n"
"\tIncomplete = %d\n",
pStatistics->RecursePacketUsed,
pStatistics->RecurseLookups,
pStatistics->RecurseQuestions,
pStatistics->RecursePasses,
pStatistics->RecurseForwards,
pStatistics->RecurseLookups,
pStatistics->RecurseResponses,
pStatistics->RecurseTimeouts,
pStatistics->RecurseFailures,
pStatistics->RecursePartialFailures
);
PrintRoutine(
"TCP Recursion:\n"
"\tTry = %d\n"
"\tQuery = %d\n"
"\tResponse = %d\n"
"Root Query:\n"
"\tQuery = %d\n"
"\tResponse = %d\n",
pStatistics->RecurseTcpTry,
pStatistics->RecurseTcpQuery,
pStatistics->RecurseTcpResponse,
pStatistics->RecurseRootQuery,
pStatistics->RecurseRootResponse
);
PrintRoutine(
"\n"
"WINS Referrals:\n"
"---------------\n"
"Forward:\n"
"\tLookups = %d\n"
"\tResponses = %d\n"
"Reverse:\n"
"\tLookups = %d\n"
"\tResponses = %d\n",
pStatistics->WinsLookups,
pStatistics->WinsResponses,
pStatistics->WinsReverseLookups,
pStatistics->WinsReverseResponses
);
PrintRoutine(
"\n"
"Secondary Zone Transfer:\n"
"------------------------\n"
"SOA Queries = %d\n"
"SOA Responses = %d\n"
"Notifies Recvd = %d\n"
"AXFR Requests = %d\n"
"AXFR Rejected = %d\n"
"AXFR Failed = %d\n"
"AXFR Successful = %d\n",
pStatistics->SecSoaQueries,
pStatistics->SecSoaResponses,
pStatistics->SecNotifyReceived,
pStatistics->SecAxfrRequested,
pStatistics->SecAxfrRejected,
pStatistics->SecAxfrFailed,
pStatistics->SecAxfrSuccessful
);
PrintRoutine(
"\n"
"Master Zone Transfer:\n"
"---------------------\n"
"Notifies Sent = %d\n"
"AXFR Requests Recvd = %d\n"
"AXFR Invalid Requests = %d\n"
"AXFR Denied (Security) = %d\n"
"AXFR Refused = %d\n"
"AXFR Failed = %d\n"
"AXFR Successful = %d\n",
pStatistics->MasterNotifySent,
pStatistics->MasterAxfrReceived,
pStatistics->MasterAxfrInvalid,
pStatistics->MasterAxfrDenied,
pStatistics->MasterAxfrRefused,
pStatistics->MasterAxfrFailed,
pStatistics->MasterAxfrSuccessful
);
//
// Database stats
//
PrintRoutine(
"\n"
"Database:\n"
"---------\n"
"Nodes\n"
" InUse = %d\n"
" Memory = %d\n"
"Records\n"
" InUse = %d\n"
" Memory = %d\n"
"Database Total\n"
" Memory = %d\n",
pStatistics->NodeInUse,
pStatistics->NodeMemory,
pStatistics->RecordInUse,
pStatistics->RecordMemory,
pStatistics->DatabaseMemory
);
PrintRoutine(
"\n"
"RR Caching:\n"
"\tTotal = %d\n"
"\tCurrent = %d\n"
"\tTimeouts = %d\n",
pStatistics->CacheRRTotal,
pStatistics->CacheRRCurrent,
pStatistics->CacheRRTimeouts
);
PrintRoutine(
"\n"
"Domain Nodes:\n"
"\tAlloc = %d\n"
"\tFree = %d\n"
"\tNetAllocs = %d\n"
"\tMemory = %d\n"
"\n"
"\tUsed = %d\n"
"\tReturned = %d\n"
"\tInUse = %d\n"
"\n"
"\tStd Alloc = %d\n"
"\tStd Used = %d\n"
"\tStd Return = %d\n"
"\tInFreeList = %d\n",
pStatistics->NodeAlloc,
pStatistics->NodeFree,
pStatistics->NodeNetAllocs,
pStatistics->NodeMemory,
pStatistics->NodeUsed,
pStatistics->NodeReturn,
pStatistics->NodeInUse,
pStatistics->NodeStdAlloc,
pStatistics->NodeStdUsed,
pStatistics->NodeStdReturn,
pStatistics->NodeInFreeList
);
PrintRoutine(
"\n"
"Records:\n"
"\tAlloc = %d\n"
"\tFree = %d\n"
"\tNetAllocs = %d\n"
"\tMemory = %d\n"
"\n"
"\tUsed = %d\n"
"\tReturned = %d\n"
"\tInUse = %d\n"
"\n"
"\tStd Alloc = %d\n"
"\tStd Used = %d\n"
"\tStd Return = %d\n"
"\tInFreeList = %d\n",
pStatistics->RecordAlloc,
pStatistics->RecordFree,
pStatistics->RecordNetAllocs,
pStatistics->RecordMemory,
pStatistics->RecordUsed,
pStatistics->RecordReturn,
pStatistics->RecordInUse,
pStatistics->RecordStdAlloc,
pStatistics->RecordStdUsed,
pStatistics->RecordStdReturn,
pStatistics->RecordInFreeList
);
PrintRoutine(
"\n"
"Packet Memory Usage:\n"
"--------------------\n"
"UDP Messages:\n"
"\tAlloc = %d\n"
"\tFree = %d\n"
"\tNetAllocs = %d\n"
"\tMemory = %d\n"
"\tUsed = %d\n"
"\tReturned = %d\n"
"\tInUse = %d\n"
"\tInFreeList = %d\n"
"\n",
pStatistics->UdpAlloc,
pStatistics->UdpFree,
pStatistics->UdpNetAllocs,
pStatistics->UdpMemory,
pStatistics->UdpUsed,
pStatistics->UdpReturn,
pStatistics->UdpInUse,
pStatistics->UdpInFreeList
);
PrintRoutine(
"TCP Messages:\n"
"\tAlloc = %d\n"
"\tRealloc = %d\n"
"\tFree = %d\n"
"\tNetAllocs = %d\n"
"\tMemory = %d\n"
"\n",
pStatistics->TcpAlloc,
pStatistics->TcpRealloc,
pStatistics->TcpFree,
pStatistics->TcpNetAllocs,
pStatistics->TcpMemory
);
PrintRoutine(
"Recursion Messages:\n"
"\tUsed = %d\n"
"\tReturned = %d\n"
"\n",
pStatistics->RecursePacketUsed,
pStatistics->RecursePacketReturn
);
PrintRoutine(
"\n"
"Nbstat Memory Usage:\n"
"--------------------\n"
"Nbstat Buffers:\n"
"\tAlloc = %d\n"
"\tFree = %d\n"
"\tNetAllocs = %d\n"
"\tMemory = %d\n"
"\tUsed = %d\n"
"\tReturned = %d\n"
"\tInUse = %d\n"
"\tInFreeList = %d\n"
"\n",
pStatistics->NbstatAlloc,
pStatistics->NbstatFree,
pStatistics->NbstatNetAllocs,
pStatistics->NbstatMemory,
pStatistics->NbstatUsed,
pStatistics->NbstatReturn,
pStatistics->NbstatInUse,
pStatistics->NbstatInFreeList
);
DnsPrint_Unlock();
}
VOID
Dns4_Print_RpcZoneHandleList(
IN PRINT_ROUTINE PrintRoutine,
IN LPSTR pszHeader,
IN DWORD dwZoneCount,
IN DNS_HANDLE ahZones[]
)
{
DWORD i;
DnsPrint_Lock();
if ( pszHeader )
{
PrintRoutine( pszHeader );
}
PrintRoutine( "Zone Count = %d\n", dwZoneCount );
if ( dwZoneCount != 0 && ahZones != NULL )
{
for( i=0; i<dwZoneCount; i++ )
{
PrintRoutine( "\thZones[%d] => %p\n", i, ahZones[i] );
}
}
}
VOID
Dns4_Print_RpcZoneInfo(
IN PRINT_ROUTINE PrintRoutine,
IN LPSTR pszHeader,
IN PDNS4_ZONE_INFO pZoneInfo
)
{
DnsPrint_Lock();
PrintRoutine( (pszHeader ? pszHeader : "") );
if ( ! pZoneInfo )
{
PrintRoutine( "NULL zone info ptr.\n" );
}
else
{
PrintRoutine(
"Zone info:\n"
"\tptr = %p\n"
"\thZone = %p\n"
"\tzone name = %s\n"
"\tzone type = %d\n"
"\tusing dbase = %d\n"
"\tdata file = %s\n"
"\tusing WINS = %d\n"
"\tusing Nbstat = %d\n",
pZoneInfo,
pZoneInfo->hZone,
pZoneInfo->pszZoneName,
pZoneInfo->dwZoneType,
pZoneInfo->fUseDatabase,
pZoneInfo->pszDataFile,
pZoneInfo->fUseWins,
pZoneInfo->fUseNbstat
);
DnsPrint_IpArray(
PrintRoutine,
NULL,
"\tZones Masters\n",
"\tMaster",
pZoneInfo->aipMasters );
DnsPrint_IpArray(
PrintRoutine,
NULL,
"\tZone Secondaries\n",
"\tSecondary",
pZoneInfo->aipSecondaries );
PrintRoutine(
"\tsecure secs = %d\n",
pZoneInfo->fSecureSecondaries
);
}
DnsPrint_Unlock();
}
VOID
Dns4_Print_RpcZoneInfoList(
IN PRINT_ROUTINE PrintRoutine,
IN LPSTR pszHeader,
IN DWORD dwZoneCount,
IN PDNS4_ZONE_INFO apZoneInfo[]
)
{
DWORD i;
DnsPrint_Lock();
PrintRoutine( (pszHeader ? pszHeader : "") );
PrintRoutine( "Zone Count = %d\n", dwZoneCount );
if ( dwZoneCount != 0 && apZoneInfo != NULL )
{
for (i=0; i<dwZoneCount; i++)
{
PrintRoutine( "\n[%d]", i );
Dns4_Print_RpcZoneInfo(
PrintRoutine,
NULL,
apZoneInfo[i] );
}
}
DnsPrint_Unlock();
}
VOID
Dns4_Print_RpcRecord(
IN PRINT_ROUTINE PrintRoutine,
IN LPSTR pszHeader,
IN PDNS4_RPC_RECORD pRecord
)
{
PCHAR pRecordString;
PDNS4_RPC_RECORD pnt4Record;
WORD type;
DnsPrint_Lock();
PrintRoutine( (pszHeader ? pszHeader : "" ) );
if ( ! pRecord )
{
PrintRoutine( "NULL record ptr.\n" );
goto Done;
}
//
// record fixed fields
//
type = pRecord->wType;
pRecordString = Dns_RecordStringForType( type );
if ( !pRecordString )
{
pRecordString = "UNKNOWN";
}
PrintRoutine(
" %s Record (NT4):\n"
"\tptr = %p\n"
"\thRecord = %p\n"
"\twLength = %u\n"
"\twDataLength = %u\n"
"\twType = %s (%u)\n"
"\twClass = %u\n"
"\tdwFlags = %lx\n"
"\tdwTtlSeconds = %u\n",
pRecordString,
pRecord,
pRecord->hRecord,
pRecord->wRecordLength,
pRecord->wDataLength,
pRecordString,
type,
pRecord->wClass,
pRecord->dwFlags,
pRecord->dwTtlSeconds
);
//
// print record type and data
// - as single line data where possible
PrintRoutine(
" %s ",
pRecordString );
switch ( type )
{
case DNS_TYPE_A:
PrintRoutine(
"%d.%d.%d.%d\n",
* ( (PUCHAR) &(pRecord->Data.A) + 0 ),
* ( (PUCHAR) &(pRecord->Data.A) + 1 ),
* ( (PUCHAR) &(pRecord->Data.A) + 2 ),
* ( (PUCHAR) &(pRecord->Data.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,
NULL,
& pRecord->Data.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(
"%d ",
pRecord->Data.MX.wPreference
);
DnsPrint_RpcName(
PrintRoutine,
NULL,
& pRecord->Data.MX.nameExchange,
"\n" );
break;
case DNS_TYPE_SOA:
DnsPrint_RpcName(
PrintRoutine,
"\n\tPrimaryNameServer: ",
& pRecord->Data.SOA.namePrimaryServer,
"\n" );
// responsible party name, immediately follows primary server name
DnsPrint_RpcName(
PrintRoutine,
"\tResponsibleParty: ",
(PDNS_RPC_NAME)
(pRecord->Data.SOA.namePrimaryServer.achName
+ pRecord->Data.SOA.namePrimaryServer.cchNameLength),
"\n" );
PrintRoutine(
"\tSerialNo = %lu\n"
"\tRefresh = %lu\n"
"\tRetry = %lu\n"
"\tExpire = %lu\n"
"\tMinimumTTL = %lu\n",
pRecord->Data.SOA.dwSerialNo,
pRecord->Data.SOA.dwRefresh,
pRecord->Data.SOA.dwRetry,
pRecord->Data.SOA.dwExpire,
pRecord->Data.SOA.dwMinimumTtl );
break;
case DNS_TYPE_MINFO:
case DNS_TYPE_RP:
//
// these RRs contain two domain names
//
DnsPrint_RpcName(
PrintRoutine,
"\n\tMailBox: ",
& pRecord->Data.MINFO.nameMailBox,
NULL );
// errors to mailbox name, immediately follows mail box
DnsPrint_RpcName(
PrintRoutine,
"\tErrorsToMailbox: ",
(PDNS_RPC_NAME)
( pRecord->Data.MINFO.nameMailBox.achName
+ pRecord->Data.MINFO.nameMailBox.cchNameLength ),
"\n" );
break;
case DNS_TYPE_AAAA:
case DNS_TYPE_HINFO:
case DNS_TYPE_ISDN:
case DNS_TYPE_X25:
case DNS_TYPE_TEXT:
{
//
// all these are simply text string(s)
//
PCHAR pch = (PCHAR) &pRecord->Data.TXT.stringData;
PCHAR pchStop = pch + pRecord->wDataLength;
UCHAR cch;
while ( pch < pchStop )
{
cch = (UCHAR) *pch++;
PrintRoutine(
"\t%.*s\n",
cch,
pch );
pch += cch;
}
ASSERT( pch == pchStop );
break;
}
case DNS_TYPE_WKS:
{
INT i;
PrintRoutine(
"WKS: Address %d.%d.%d.%d\n"
"\tProtocol %d\n"
"\tBitmask\n",
* ( (PUCHAR) &(pRecord->Data.WKS.ipAddress) + 0 ),
* ( (PUCHAR) &(pRecord->Data.WKS.ipAddress) + 1 ),
* ( (PUCHAR) &(pRecord->Data.WKS.ipAddress) + 2 ),
* ( (PUCHAR) &(pRecord->Data.WKS.ipAddress) + 3 ),
pRecord->Data.WKS.chProtocol
);
for ( i = 0;
i < (INT)( pRecord->wDataLength
- sizeof( pRecord->Data.WKS.ipAddress )
- sizeof( pRecord->Data.WKS.chProtocol ) );
i++ )
{
PrintRoutine(
"\t\tbyte[%d] = %x\n",
i,
(UCHAR) pRecord->Data.WKS.bBitMask[i] );
}
break;
}
case DNS_TYPE_NULL:
{
INT i;
for ( i = 0; i < pRecord->wDataLength; i++ )
{
// print one DWORD per line
if ( !(i%16) )
{
PrintRoutine( "\n\t" );
}
PrintRoutine(
"%02x ",
(UCHAR) pRecord->Data.Null.bData[i] );
}
PrintRoutine( "\n" );
break;
}
case DNS_TYPE_SRV:
//
// SRV <priority> <weight> <port> <target host>
//
PrintRoutine(
"%d %d %d ",
pRecord->Data.SRV.wPriority,
pRecord->Data.SRV.wWeight,
pRecord->Data.SRV.wPort
);
DnsPrint_RpcName(
PrintRoutine,
NULL,
& pRecord->Data.SRV.nameTarget,
"\n" );
break;
case DNS_TYPE_WINS:
{
DWORD i;
//
// WINS
// - scope/domain mapping flag
// - WINS server list
//
PrintRoutine( "%08lx\n", pRecord->Data.WINS.dwMappingFlag );
#if 0
//
// DEVNOTE: WINS mapping strings
// JJW: this is probably an obsolete B*GB*G
//
"%s\t",
Dns_WinsMappingFlagString( pRecord->Data.WINS.dwMappingFlag )
#endif
for( i=0; i<pRecord->Data.WINS.cWinsServerCount; i++ )
{
PrintRoutine(
"%d.%d.%d.%d\n",
* ( (PUCHAR) &(pRecord->Data.WINS.aipWinsServers[i]) + 0 ),
* ( (PUCHAR) &(pRecord->Data.WINS.aipWinsServers[i]) + 1 ),
* ( (PUCHAR) &(pRecord->Data.WINS.aipWinsServers[i]) + 2 ),
* ( (PUCHAR) &(pRecord->Data.WINS.aipWinsServers[i]) + 3 )
);
}
break;
}
case DNS_TYPE_NBSTAT:
//
// NBSTAT
// - scope/domain mapping flag
// - optionally a result domain
//
PrintRoutine( "%08lx\n", pRecord->Data.NBSTAT.dwMappingFlag );
if ( pRecord->wDataLength > sizeof(pRecord->Data.NBSTAT.dwMappingFlag) )
{
DnsPrint_RpcName(
PrintRoutine,
NULL,
& pRecord->Data.NBSTAT.nameResultDomain,
"\n" );
}
break;
default:
PrintRoutine(
"Unknown resource record type (%d) at %p.\n",
pRecord->wType,
pRecord );
break;
}
Done:
DnsPrint_Unlock();
}
VOID
DNS_API_FUNCTION
Dns4_Print_RpcRecordsInBuffer(
IN PRINT_ROUTINE PrintRoutine,
IN LPSTR pszHeader,
IN DWORD dwBufferLength,
IN BYTE abBuffer[]
)
{
PBYTE pbCurrent;
PBYTE pbStop;
INT cRecordCount;
DnsPrint_Lock();
PrintRoutine( (pszHeader ? pszHeader : "") );
if ( !abBuffer )
{
PrintRoutine( "NULL record buffer ptr.\n" );
goto Done;
}
else
{
PrintRoutine(
"Record buffer of length %d at %p:\n",
dwBufferLength,
abBuffer );
}
//
// find stop byte
//
ASSERT( DNS_IS_DWORD_ALIGNED(abBuffer) );
pbStop = abBuffer + dwBufferLength;
pbCurrent = abBuffer;
//
// loop until out of nodes
//
while( pbCurrent < pbStop )
{
//
// print owner node
// determine record count
// find first record
//
DnsPrint_RpcNode(
PrintRoutine,
NULL,
(PDNS_RPC_NODE)pbCurrent );
cRecordCount = ((PDNS_RPC_NODE)pbCurrent)->wRecordCount;
pbCurrent += ((PDNS_RPC_NODE)pbCurrent)->wLength;
pbCurrent = DNS_NEXT_DWORD_PTR(pbCurrent);
//
// for each node, print all records in list
//
while( cRecordCount-- )
{
if ( pbCurrent >= pbStop )
{
PrintRoutine(
"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) pbCurrent,
pbStop,
cRecordCount+1 );
ASSERT( FALSE );
break;
}
Dns4_Print_RpcRecord(
PrintRoutine,
"",
(PDNS4_RPC_RECORD) pbCurrent );
pbCurrent += ((PDNS4_RPC_RECORD)pbCurrent)->wDataLength
+ SIZEOF_DNS4_RPC_RECORD_HEADER;
pbCurrent = DNS_NEXT_DWORD_PTR(pbCurrent);
}
}
Done:
DnsPrint_Unlock();
}
//
// End of nt4api.c
//