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.
6692 lines
147 KiB
6692 lines
147 KiB
/*++
|
|
|
|
Copyright (c) 1997-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
print.c
|
|
|
|
Abstract:
|
|
|
|
Domain Name System (DNS) Library
|
|
|
|
Print routines.
|
|
|
|
Author:
|
|
|
|
Jim Gilroy (jamesg) February 8, 1997
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "local.h"
|
|
#include "svcguid.h" // RnR guids
|
|
#include "..\dnsapi\dnsapip.h" // Private query stuff
|
|
#include "..\resolver\idl\resrpc.h" // Resolver interface structs
|
|
|
|
|
|
//
|
|
// Print globals
|
|
//
|
|
|
|
CRITICAL_SECTION DnsAtomicPrintCs;
|
|
PCRITICAL_SECTION pDnsAtomicPrintCs = NULL;
|
|
|
|
//
|
|
// Empty string for simple switching of UTF-8/Unicode print
|
|
// (macros in dnslib.h)
|
|
//
|
|
|
|
DWORD DnsEmptyString = 0;
|
|
|
|
|
|
//
|
|
// Indenting
|
|
//
|
|
// Serve up as many indenting tabs as indent level indicates
|
|
//
|
|
|
|
CHAR IndentString[] = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
|
|
|
|
#define INDENT_STRING( level ) (IndentString + (sizeof(IndentString) - 1 - (level)))
|
|
|
|
|
|
|
|
//
|
|
// Print Locking
|
|
//
|
|
// Unless caller initilizes print locking by supplying lock,
|
|
// print locking is disabled.
|
|
//
|
|
|
|
VOID
|
|
DnsPrint_InitLocking(
|
|
IN PCRITICAL_SECTION pLock
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Setup DNS printing to use a lock.
|
|
|
|
Can use already initialized lock from caller, or will
|
|
create default lock.
|
|
|
|
Arguments:
|
|
|
|
pLock - ptr to CS to use as lock; if NULL, create one
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
if ( pLock )
|
|
{
|
|
pDnsAtomicPrintCs = pLock;
|
|
}
|
|
else if ( !pDnsAtomicPrintCs )
|
|
{
|
|
InitializeCriticalSection( &DnsAtomicPrintCs );
|
|
pDnsAtomicPrintCs = &DnsAtomicPrintCs;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_Lock(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Lock to get atomic DNS print.
|
|
|
|
--*/
|
|
{
|
|
if ( pDnsAtomicPrintCs )
|
|
{
|
|
EnterCriticalSection( pDnsAtomicPrintCs );
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
DnsPrint_Unlock(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Unlock to debug print.
|
|
|
|
--*/
|
|
{
|
|
if ( pDnsAtomicPrintCs )
|
|
{
|
|
LeaveCriticalSection( pDnsAtomicPrintCs );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Print routines for general types and structures
|
|
//
|
|
|
|
VOID
|
|
DnsPrint_String(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader OPTIONAL,
|
|
IN PSTR pszString,
|
|
IN BOOL fUnicode,
|
|
IN PSTR pszTrailer OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print DNS string given in either Unicode or UTF-8 format.
|
|
|
|
--*/
|
|
{
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "";
|
|
}
|
|
if ( !pszTrailer )
|
|
{
|
|
pszTrailer = "";
|
|
}
|
|
|
|
if ( ! pszString )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s(NULL DNS string ptr)%s",
|
|
pszHeader,
|
|
pszTrailer );
|
|
}
|
|
else if (fUnicode)
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s%S%s",
|
|
pszHeader,
|
|
(PWSTR ) pszString,
|
|
pszTrailer );
|
|
}
|
|
else
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s%s%s",
|
|
pszHeader,
|
|
(PSTR ) pszString,
|
|
pszTrailer );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_StringCharSet(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader OPTIONAL,
|
|
IN PSTR pszString,
|
|
IN DNS_CHARSET CharSet,
|
|
IN PSTR pszTrailer OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print string of given CHARSET.
|
|
|
|
--*/
|
|
{
|
|
DnsPrint_String(
|
|
PrintRoutine,
|
|
pContext,
|
|
pszHeader,
|
|
pszString,
|
|
(CharSet == DnsCharSetUnicode),
|
|
pszTrailer );
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_UnicodeStringBytes(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PWCHAR pUnicode,
|
|
IN DWORD Length
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print chars (WORDs) of unicode string.
|
|
|
|
--*/
|
|
{
|
|
DWORD i;
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\r\n"
|
|
"\twide string %S\r\n"
|
|
"\tlength %d\r\n"
|
|
"\tbytes ",
|
|
pszHeader,
|
|
pUnicode,
|
|
Length );
|
|
|
|
for ( i=0; i<Length; i++ )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%04hx ",
|
|
pUnicode[i] );
|
|
}
|
|
printf( "\r\n" );
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_Utf8StringBytes(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PCHAR pUtf8,
|
|
IN DWORD Length
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print bytes of UTF8 string.
|
|
|
|
--*/
|
|
{
|
|
DWORD i;
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\r\n"
|
|
"\tUTF8 string %s\r\n"
|
|
"\tlength %d\r\n"
|
|
"\tbytes ",
|
|
pszHeader,
|
|
pUtf8,
|
|
Length );
|
|
|
|
for ( i=0; i<Length; i++ )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%02x ",
|
|
(UCHAR) pUtf8[i] );
|
|
}
|
|
printf( "\r\n" );
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_StringArray(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PSTR * StringArray,
|
|
IN DWORD Count, OPTIONAL
|
|
IN BOOL fUnicode
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print string array.
|
|
|
|
--*/
|
|
{
|
|
DWORD i = 0;
|
|
PCHAR pstr;
|
|
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "StringArray:";
|
|
}
|
|
if ( !StringArray )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s NULL pointer!\r\n",
|
|
pszHeader );
|
|
}
|
|
|
|
DnsPrint_Lock();
|
|
|
|
if ( Count )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s Count = %d\r\n",
|
|
pszHeader,
|
|
Count );
|
|
}
|
|
else
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\r\n",
|
|
pszHeader );
|
|
}
|
|
|
|
//
|
|
// print args
|
|
// - stop at Count (if given)
|
|
// OR
|
|
// - on NULL arg (if no count given)
|
|
//
|
|
|
|
while ( (!Count || i < Count) )
|
|
{
|
|
pstr = StringArray[i++];
|
|
if ( !pstr && !Count )
|
|
{
|
|
break;
|
|
}
|
|
PrintRoutine(
|
|
pContext,
|
|
(fUnicode) ? "\t%S\r\n" : "\t%s\r\n",
|
|
pstr );
|
|
}
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_Argv(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN CHAR ** Argv,
|
|
IN DWORD Argc, OPTIONAL
|
|
IN BOOL fUnicode
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print Argv array.
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// this is just special case of string print
|
|
//
|
|
|
|
DnsPrint_StringArray(
|
|
PrintRoutine,
|
|
pContext,
|
|
pszHeader
|
|
? pszHeader
|
|
: "Argv:",
|
|
Argv,
|
|
Argc,
|
|
fUnicode );
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_DwordArray(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PSTR pszName,
|
|
IN DWORD dwCount,
|
|
IN PDWORD adwArray
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print DWORD array.
|
|
|
|
--*/
|
|
{
|
|
DWORD i;
|
|
|
|
DnsPrint_Lock();
|
|
|
|
if ( pszHeader )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
pszHeader );
|
|
}
|
|
|
|
if ( !pszName )
|
|
{
|
|
pszName = "DWORD";
|
|
}
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s Array Count = %d\r\n",
|
|
pszName,
|
|
dwCount );
|
|
|
|
for( i=0; i<dwCount; i++ )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"\t%s[%d] => 0x%p (%d)\r\n",
|
|
pszName,
|
|
i,
|
|
adwArray[i],
|
|
adwArray[i] );
|
|
}
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_Ip4AddressArray(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PSTR pszName,
|
|
IN DWORD dwIpAddrCount,
|
|
IN PIP4_ADDRESS pIpAddrs
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print IP address array.
|
|
|
|
--*/
|
|
{
|
|
DWORD i;
|
|
|
|
DnsPrint_Lock();
|
|
|
|
if ( !pszName )
|
|
{
|
|
pszName = "IP Addr";
|
|
}
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s Addr Count = %d\r\n",
|
|
pszHeader ? pszHeader : "",
|
|
dwIpAddrCount );
|
|
|
|
if ( dwIpAddrCount != 0 && pIpAddrs != NULL )
|
|
{
|
|
// print array with count
|
|
// use character print so works even if NOT DWORD aligned
|
|
|
|
for( i=0; i<dwIpAddrCount; i++ )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"\t%s[%d] => %d.%d.%d.%d\r\n",
|
|
pszName,
|
|
i,
|
|
* ( (PUCHAR) &pIpAddrs[i] + 0 ),
|
|
* ( (PUCHAR) &pIpAddrs[i] + 1 ),
|
|
* ( (PUCHAR) &pIpAddrs[i] + 2 ),
|
|
* ( (PUCHAR) &pIpAddrs[i] + 3 ) );
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
// this spins if printing zero length IP_ARRAY struct
|
|
|
|
else if ( pIpAddrs != NULL )
|
|
{
|
|
// print NULL terminated array (ex. hostents IPs)
|
|
|
|
i = 0;
|
|
while ( pIpAddrs[i] )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"\t%s[%d] => %s\r\n",
|
|
pszName,
|
|
i,
|
|
inet_ntoa( *(struct in_addr *) &pIpAddrs[i] ) );
|
|
}
|
|
}
|
|
#endif
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_Ip4Array(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PSTR pszName,
|
|
IN PIP4_ARRAY pIpArray
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print IP address array struct
|
|
|
|
Just pass through to more generic print routine.
|
|
|
|
--*/
|
|
{
|
|
// protect against NULL case
|
|
|
|
if ( !pIpArray )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\tNULL IP Array.\r\n",
|
|
pszHeader ? pszHeader : "" );
|
|
}
|
|
|
|
// call uncoupled IP array routine
|
|
|
|
else
|
|
{
|
|
DnsPrint_Ip4AddressArray(
|
|
PrintRoutine,
|
|
pContext,
|
|
pszHeader,
|
|
pszName,
|
|
pIpArray->AddrCount,
|
|
pIpArray->AddrArray );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_Ip6Address(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PIP6_ADDRESS pIp6Addr,
|
|
IN PSTR pszTrailer
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print IP6 address.
|
|
|
|
Arguments:
|
|
|
|
PrintRoutine -- print routine to call
|
|
|
|
pContext -- first argument to print routine
|
|
|
|
pszHeader -- header to print
|
|
NOTE: unlike other print routines this routine
|
|
requires header to contain newline,tab, etc if
|
|
multiline print is desired; the reason is to allow
|
|
use of this routine for single line print
|
|
|
|
pIp6Address -- ptr to IP6 address to print
|
|
|
|
pszTrailer -- trailer to print
|
|
NOTE: again this routine is designed to allow single
|
|
line print; if newline required after print, send
|
|
newline in trailer
|
|
|
|
Return Value:
|
|
|
|
Ptr to next location in buffer (the terminating NULL).
|
|
|
|
--*/
|
|
{
|
|
CHAR buffer[ IP6_ADDRESS_STRING_BUFFER_LENGTH ];
|
|
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "IP6 Addr: ";
|
|
}
|
|
if ( !pszTrailer )
|
|
{
|
|
pszTrailer = "\r\n";
|
|
}
|
|
|
|
if ( !pIp6Addr )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s NULL IP6 address ptr.%s",
|
|
pszHeader,
|
|
pszTrailer );
|
|
return;
|
|
}
|
|
|
|
// convert IP6 address to string
|
|
|
|
Dns_Ip6AddressToString_A(
|
|
buffer,
|
|
pIp6Addr );
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s%s%s",
|
|
pszHeader,
|
|
buffer,
|
|
pszTrailer );
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_Ip6Array(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PSTR pszName,
|
|
IN PIP6_ARRAY pIpArray
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print IP address array struct
|
|
|
|
Just pass through to more generic print routine.
|
|
|
|
--*/
|
|
{
|
|
DWORD i;
|
|
CHAR buffer[ IP6_ADDRESS_STRING_BUFFER_LENGTH ];
|
|
|
|
if ( !pszName )
|
|
{
|
|
pszName = "IP";
|
|
}
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "IP Array";
|
|
}
|
|
|
|
// protect against NULL case
|
|
|
|
if ( !pIpArray )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s \tNULL IP Array.\n",
|
|
pszHeader );
|
|
return;
|
|
}
|
|
|
|
DnsPrint_Lock();
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\n"
|
|
"\tPtr = %p\n"
|
|
"\tMaxCount = %d\n"
|
|
"\tAddrCount = %d\n",
|
|
pszHeader,
|
|
pIpArray,
|
|
pIpArray->MaxCount,
|
|
pIpArray->AddrCount );
|
|
|
|
for( i=0; i<pIpArray->AddrCount; i++ )
|
|
{
|
|
// convert IP6 address to string
|
|
|
|
Dns_Ip6AddressToString_A(
|
|
buffer,
|
|
& pIpArray->AddrArray[i] );
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"\t%s[%d] => %s\n",
|
|
pszName,
|
|
i,
|
|
buffer );
|
|
}
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Print routines for DNS types and structures
|
|
//
|
|
|
|
VOID
|
|
DnsPrint_DnsAddrLine(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PDNS_ADDR pAddr,
|
|
IN PSTR pszTrailer
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print DNS_ADDR
|
|
|
|
Arguments:
|
|
|
|
PrintRoutine -- print routine to call
|
|
|
|
pContext -- first argument to print routine
|
|
|
|
pszHeader -- header to print
|
|
NOTE: unlike other print routines this routine
|
|
requires header to contain newline,tab, etc if
|
|
multiline print is desired; the reason is to allow
|
|
use of this routine for single line print
|
|
|
|
pDnsAddr -- ptr to addr to print
|
|
|
|
pszTrailer -- trailer to print
|
|
NOTE: again this routine is designed to allow single
|
|
line print; if newline required after print, send
|
|
newline in trailer
|
|
|
|
Return Value:
|
|
|
|
Ptr to next location in buffer (the terminating NULL).
|
|
|
|
--*/
|
|
{
|
|
CHAR buffer[ DNS_ADDR_STRING_BUFFER_LENGTH ];
|
|
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "DnsAddr: ";
|
|
}
|
|
if ( !pszTrailer )
|
|
{
|
|
pszTrailer = "\r\n";
|
|
}
|
|
|
|
if ( !pAddr )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s NULL DNS_ADDR ptr.%s",
|
|
pszHeader,
|
|
pszTrailer );
|
|
return;
|
|
}
|
|
|
|
// convert DNS_ADDR to string
|
|
|
|
DnsAddr_WriteStructString_A( buffer, pAddr );
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s%s%s",
|
|
pszHeader,
|
|
buffer,
|
|
pszTrailer );
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_DnsAddr(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN DWORD Indent,
|
|
IN PDNS_ADDR pSab
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print sockaddr blob structure and length used in call.
|
|
|
|
--*/
|
|
{
|
|
PSTR pindent = INDENT_STRING( Indent );
|
|
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "Sockaddr Blob:";
|
|
}
|
|
|
|
if ( !pSab )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s%s\tNULL SockaddrBlob passed to print.\r\n",
|
|
pindent,
|
|
pszHeader );
|
|
return;
|
|
}
|
|
|
|
DnsPrint_Lock();
|
|
|
|
DnsPrint_Sockaddr(
|
|
PrintRoutine,
|
|
pContext,
|
|
pszHeader,
|
|
Indent,
|
|
& pSab->Sockaddr,
|
|
pSab->SockaddrLength
|
|
);
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\tsockaddr len = %d\n"
|
|
"%s\tprefix len = %d\n"
|
|
"%s\tflags = %08x\n"
|
|
"%s\tstatus = %d\n"
|
|
"%s\tpriority = %d\n",
|
|
pindent, pSab->SockaddrLength,
|
|
pindent, pSab->SubnetLength,
|
|
pindent, pSab->Flags,
|
|
pindent, pSab->Status,
|
|
pindent, pSab->Priority );
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_DnsAddrArray(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PSTR pszName,
|
|
IN PDNS_ADDR_ARRAY pArray
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print IP address array struct
|
|
|
|
Just pass through to more generic print routine.
|
|
|
|
--*/
|
|
{
|
|
DWORD i;
|
|
CHAR buffer[ DNS_ADDR_STRING_BUFFER_LENGTH ];
|
|
|
|
if ( !pszName )
|
|
{
|
|
pszName = "Addr";
|
|
}
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "IP Array";
|
|
}
|
|
|
|
// protect against NULL case
|
|
|
|
if ( !pArray )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s \tNULL IP Array.\n",
|
|
pszHeader );
|
|
return;
|
|
}
|
|
|
|
DnsPrint_Lock();
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\n"
|
|
"\tPtr = %p\n"
|
|
"\tMaxCount = %d\n"
|
|
"\tAddrCount = %d\n",
|
|
pszHeader,
|
|
pArray,
|
|
pArray->MaxCount,
|
|
pArray->AddrCount );
|
|
|
|
for( i=0; i<pArray->AddrCount; i++ )
|
|
{
|
|
// convert DNS_ADDR to string
|
|
|
|
DnsAddr_WriteStructString_A(
|
|
buffer,
|
|
& pArray->AddrArray[i] );
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"\t%s[%d] => %s\n",
|
|
pszName,
|
|
i,
|
|
buffer );
|
|
}
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// DNS message stuff
|
|
//
|
|
|
|
INT
|
|
Dns_WritePacketNameToBuffer(
|
|
OUT PCHAR pBuffer,
|
|
OUT PCHAR * ppBufferOut,
|
|
IN PBYTE pMsgName,
|
|
IN PDNS_HEADER pMsgHead, OPTIONAL
|
|
IN PBYTE pMsgEnd OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write packet name into buffer.
|
|
|
|
Arguments:
|
|
|
|
pBuffer - buffer to print to, MUST be twice DNS_MAX_NAME_LENGTH
|
|
to avoid overflows on bad packets
|
|
|
|
ppBufferOut - ptr to terminating NULL in buffer conversion, this
|
|
is position at which additional printing to buffer
|
|
could resume
|
|
|
|
pMsgName - ptr to name in packet to print
|
|
|
|
pMsgHead - ptr to DNS message; need for offsetting, if not given
|
|
names are not printed past first offset
|
|
|
|
pMsgEnd - ptr to end of message, specifically byte immediately after
|
|
message
|
|
|
|
Return Value:
|
|
|
|
Count of bytes in packet name occupied.
|
|
This offset from pMsgName is the next field in the packet.
|
|
|
|
Zero return indicates error in message name.
|
|
|
|
--*/
|
|
{
|
|
register PUCHAR pchbuf;
|
|
register PUCHAR pchmsg;
|
|
register UCHAR cch;
|
|
PCHAR pbufStop;
|
|
PCHAR pnextLabel;
|
|
UCHAR compressionType;
|
|
WORD offset;
|
|
PCHAR pbyteAfterFirstOffset = NULL;
|
|
|
|
//
|
|
// no message end specified?
|
|
// make it max ptr so we can do single test for ptr validity
|
|
// rather than testing for pMsgEnd existence first
|
|
//
|
|
|
|
if ( !pMsgEnd )
|
|
{
|
|
pMsgEnd = (PVOID)(INT_PTR)(-1);
|
|
}
|
|
|
|
//
|
|
// loop until copy as printable name, or hit compression or name error
|
|
//
|
|
// buffer must be twice max label length
|
|
// - allow extra chars for label length byte and compression printing
|
|
// - but stop printing when within a label of end as label (or error
|
|
// message) is copied in one blob without end check
|
|
//
|
|
|
|
pchbuf = pBuffer;
|
|
pbufStop = pchbuf + 2*DNS_MAX_NAME_LENGTH - DNS_MAX_LABEL_LENGTH - 10;
|
|
pchmsg = pMsgName;
|
|
|
|
while ( 1 )
|
|
{
|
|
// bounds checking to survive bad packet
|
|
//
|
|
// DEVNOTE: note this is not strictly a bad packet (could be just a
|
|
// heck of a lot of labels) and we could
|
|
// a) let packet processing proceed without printing
|
|
// or
|
|
// b) require buffer that could contain max legal DNS name
|
|
// but not worth the effort
|
|
|
|
if ( pchbuf >= pbufStop )
|
|
{
|
|
pchbuf += sprintf(
|
|
pchbuf,
|
|
"[ERROR name exceeds safe print buffer length]\r\n" );
|
|
pchmsg = pMsgName;
|
|
break;
|
|
}
|
|
|
|
cch = (UCHAR) *pchmsg++;
|
|
compressionType = cch & 0xC0;
|
|
|
|
DNSDBG( OFF, (
|
|
"byte = (%d) (0x%02x)\r\n"
|
|
"compress flag = (%d) (0x%02x)\r\n",
|
|
cch, cch,
|
|
compressionType, compressionType ));
|
|
|
|
//
|
|
// normal length byte
|
|
// - write length field
|
|
// - copy label to print buffer
|
|
//
|
|
|
|
if ( compressionType == 0 )
|
|
{
|
|
pchbuf += sprintf( pchbuf, "(%d)", (INT)cch );
|
|
|
|
// terminate at root name
|
|
|
|
if ( ! cch )
|
|
{
|
|
break;
|
|
}
|
|
|
|
// check that within packet
|
|
|
|
pnextLabel = pchmsg + cch;
|
|
if ( pnextLabel >= pMsgEnd )
|
|
{
|
|
pchbuf += sprintf(
|
|
pchbuf,
|
|
"[ERROR length byte: 0x%02X at %p leads outside message]\r\n",
|
|
cch,
|
|
pchmsg );
|
|
|
|
// force zero byte return
|
|
|
|
pchmsg = pMsgName;
|
|
break;
|
|
}
|
|
|
|
// copy label to output string
|
|
|
|
memcpy(
|
|
pchbuf,
|
|
pchmsg,
|
|
cch );
|
|
|
|
pchbuf += cch;
|
|
pchmsg = pnextLabel;
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// valid compression
|
|
//
|
|
|
|
else if ( compressionType == (UCHAR)0xC0 )
|
|
{
|
|
// check that compression word not straddling message end
|
|
|
|
if ( pchmsg >= pMsgEnd )
|
|
{
|
|
pchbuf += sprintf(
|
|
pchbuf,
|
|
"[ERROR compression word at %p is outside message]\r\n",
|
|
pchmsg );
|
|
|
|
// force zero byte return
|
|
|
|
pchmsg = pMsgName;
|
|
break;
|
|
}
|
|
|
|
// calculate offset
|
|
|
|
offset = cch; // high byte
|
|
offset <<= 8;
|
|
offset |= *pchmsg++; // low byte
|
|
|
|
pchbuf += sprintf(
|
|
pchbuf,
|
|
"[%04hX]",
|
|
offset );
|
|
|
|
if ( pMsgHead )
|
|
{
|
|
//
|
|
// on first compression, save ptr to byte immediately after
|
|
// name, so can calculate next byte
|
|
//
|
|
// save ptr to next byte in mess, to calculate actual length
|
|
// name takes up in packet
|
|
//
|
|
|
|
if ( ! pbyteAfterFirstOffset )
|
|
{
|
|
pbyteAfterFirstOffset = pchmsg;
|
|
}
|
|
|
|
//
|
|
// jump to offset for continuation of name
|
|
// - clear two highest bits to get length
|
|
//
|
|
|
|
offset = offset ^ 0xC000;
|
|
DNS_ASSERT( (offset & 0xC000) == 0 );
|
|
|
|
pnextLabel = (PCHAR)pMsgHead + offset;
|
|
if ( pnextLabel >= pchmsg - sizeof(WORD) )
|
|
{
|
|
pchbuf += sprintf(
|
|
pchbuf,
|
|
"[ERROR offset at %p to higher byte in packet %p]\r\n",
|
|
pchmsg - sizeof(WORD),
|
|
pnextLabel );
|
|
break;
|
|
}
|
|
pchmsg = pnextLabel;
|
|
continue;
|
|
}
|
|
|
|
// if no ptr to message head, can not continue at offset
|
|
// NULL terminate previous label
|
|
|
|
else
|
|
{
|
|
*pchbuf++ = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// invalid compression
|
|
// - force zero byte return to indicate error
|
|
|
|
else
|
|
{
|
|
pchbuf += sprintf(
|
|
pchbuf,
|
|
"[ERROR length byte: 0x%02X]",
|
|
cch );
|
|
pchmsg = pMsgName;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// return ptr to next position in output buffer
|
|
//
|
|
|
|
if ( ppBufferOut )
|
|
{
|
|
*ppBufferOut = pchbuf;
|
|
}
|
|
|
|
//
|
|
// return number of bytes read from message
|
|
//
|
|
|
|
if ( pbyteAfterFirstOffset )
|
|
{
|
|
pchmsg = pbyteAfterFirstOffset;
|
|
}
|
|
return (INT)( pchmsg - pMsgName );
|
|
}
|
|
|
|
|
|
|
|
INT
|
|
DnsPrint_PacketName(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader, OPTIONAL
|
|
IN PBYTE pMsgName,
|
|
IN PDNS_HEADER pMsgHead, OPTIONAL
|
|
IN PBYTE pMsgEnd, OPTIONAL
|
|
IN PSTR pszTrailer OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print DNS name given in packet format.
|
|
|
|
Arguments:
|
|
|
|
PrintRoutine - routine to print with
|
|
|
|
pszHeader - header to print
|
|
|
|
pMsgHead - ptr to DNS message; need for offsetting, if not given
|
|
names are not printed past first offset
|
|
|
|
pMsgName - ptr to name in packet to print
|
|
|
|
pMsgEnd - ptr to end of message; OPTIONAL, but needed to protect
|
|
against AV accessing bad packet names
|
|
|
|
pszTrailer - trailer to print after name
|
|
|
|
Return Value:
|
|
|
|
Count of bytes in packet name occupied.
|
|
This offset from pMsgName is the next field in the packet.
|
|
|
|
Zero return indicates error in message name.
|
|
|
|
--*/
|
|
{
|
|
INT countNameBytes;
|
|
|
|
// name buffer, allow space for full name, plus parens on length
|
|
// fields plus several compression flags
|
|
|
|
CHAR PrintName[ 2*DNS_MAX_NAME_LENGTH ];
|
|
|
|
|
|
if ( ! pMsgName )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s(NULL packet name ptr)%s\r\n",
|
|
pszHeader ? pszHeader : "",
|
|
pszTrailer ? pszTrailer : ""
|
|
);
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// build packet name into buffer, then print
|
|
//
|
|
|
|
countNameBytes = Dns_WritePacketNameToBuffer(
|
|
PrintName,
|
|
NULL,
|
|
pMsgName,
|
|
pMsgHead,
|
|
pMsgEnd
|
|
);
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s%s%s",
|
|
pszHeader ? pszHeader : "",
|
|
PrintName,
|
|
pszTrailer ? pszTrailer : ""
|
|
);
|
|
|
|
return( countNameBytes );
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_Message(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PDNS_MSG_BUF pMsg
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print DNS message buffer.
|
|
Includes context information as well as actual DNS message.
|
|
|
|
--*/
|
|
{
|
|
PDNS_HEADER pmsgHeader;
|
|
PCHAR pchRecord;
|
|
PBYTE pmsgEnd;
|
|
INT i;
|
|
INT isection;
|
|
INT cchName;
|
|
WORD wLength;
|
|
WORD wOffset;
|
|
WORD wXid;
|
|
WORD wQuestionCount;
|
|
WORD wAnswerCount;
|
|
WORD wNameServerCount;
|
|
WORD wAdditionalCount;
|
|
WORD countSectionRR;
|
|
BOOL fFlipped = FALSE;
|
|
|
|
DnsPrint_Lock();
|
|
|
|
if ( pszHeader )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\r\n",
|
|
pszHeader );
|
|
}
|
|
|
|
// get message info
|
|
//
|
|
// note: length may not be correctly set while building message,
|
|
// so make pmsgEnd greater of given length and pCurrent ptr
|
|
// but allow for case where set back to pre-OPT length
|
|
//
|
|
|
|
wLength = pMsg->MessageLength;
|
|
pmsgHeader = &pMsg->MessageHead;
|
|
pmsgEnd = ((PBYTE)pmsgHeader) + wLength;
|
|
|
|
if ( pmsgEnd < pMsg->pCurrent &&
|
|
pmsgEnd != pMsg->pPreOptEnd )
|
|
{
|
|
pmsgEnd = pMsg->pCurrent;
|
|
}
|
|
|
|
//
|
|
// print header info
|
|
//
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s %s info at %p\r\n"
|
|
" Socket = %d 4=%d 6=%d\r\n"
|
|
" Remote addr %s\r\n"
|
|
" fam = %d\n"
|
|
" port = %d\n"
|
|
" len = %d\n"
|
|
" Buf length = 0x%04x\r\n"
|
|
" Msg length = 0x%04x\r\n"
|
|
" Message:\r\n",
|
|
( pMsg->fTcp
|
|
? "TCP"
|
|
: "UDP" ),
|
|
( pmsgHeader->IsResponse
|
|
? "response"
|
|
: "question" ),
|
|
pMsg,
|
|
pMsg->Socket,
|
|
pMsg->Socket4,
|
|
pMsg->Socket6,
|
|
MSG_REMOTE_IPADDR_STRING( pMsg ),
|
|
MSG_REMOTE_FAMILY( pMsg ),
|
|
MSG_REMOTE_IP_PORT( pMsg ),
|
|
pMsg->RemoteAddress.SockaddrLength,
|
|
pMsg->BufferLength,
|
|
wLength
|
|
);
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
" XID 0x%04hx\r\n"
|
|
" Flags 0x%04hx\r\n"
|
|
" QR 0x%lx (%s)\r\n"
|
|
" OPCODE 0x%lx (%s)\r\n"
|
|
" AA 0x%lx\r\n"
|
|
" TC 0x%lx\r\n"
|
|
" RD 0x%lx\r\n"
|
|
" RA 0x%lx\r\n"
|
|
" Z 0x%lx\r\n"
|
|
" RCODE 0x%lx (%s)\r\n"
|
|
" QCOUNT 0x%hx\r\n"
|
|
" ACOUNT 0x%hx\r\n"
|
|
" NSCOUNT 0x%hx\r\n"
|
|
" ARCOUNT 0x%hx\r\n",
|
|
|
|
pmsgHeader->Xid,
|
|
ntohs((*((PWORD)pmsgHeader + 1))),
|
|
|
|
pmsgHeader->IsResponse,
|
|
(pmsgHeader->IsResponse ? "response" : "question"),
|
|
pmsgHeader->Opcode,
|
|
Dns_OpcodeString( pmsgHeader->Opcode ),
|
|
pmsgHeader->Authoritative,
|
|
pmsgHeader->Truncation,
|
|
pmsgHeader->RecursionDesired,
|
|
pmsgHeader->RecursionAvailable,
|
|
pmsgHeader->Reserved,
|
|
pmsgHeader->ResponseCode,
|
|
Dns_ResponseCodeString( pmsgHeader->ResponseCode ),
|
|
|
|
pmsgHeader->QuestionCount,
|
|
pmsgHeader->AnswerCount,
|
|
pmsgHeader->NameServerCount,
|
|
pmsgHeader->AdditionalCount );
|
|
|
|
//
|
|
// determine if byte flipped and get correct count
|
|
//
|
|
|
|
wXid = pmsgHeader->Xid;
|
|
wQuestionCount = pmsgHeader->QuestionCount;
|
|
wAnswerCount = pmsgHeader->AnswerCount;
|
|
wNameServerCount = pmsgHeader->NameServerCount;
|
|
wAdditionalCount = pmsgHeader->AdditionalCount;
|
|
|
|
if ( wQuestionCount )
|
|
{
|
|
fFlipped = wQuestionCount & 0xff00;
|
|
}
|
|
else if ( wNameServerCount )
|
|
{
|
|
fFlipped = wNameServerCount & 0xff00;
|
|
}
|
|
if ( fFlipped )
|
|
{
|
|
wXid = ntohs( wXid );
|
|
wQuestionCount = ntohs( wQuestionCount );
|
|
wAnswerCount = ntohs( wAnswerCount );
|
|
wNameServerCount = ntohs( wNameServerCount );
|
|
wAdditionalCount = ntohs( wAdditionalCount );
|
|
}
|
|
|
|
//
|
|
// catch record flipping problems -- all are flipped or none at all
|
|
// and no record count should be > 256 EXCEPT answer count
|
|
// during FAST zone transfer
|
|
//
|
|
|
|
DNS_ASSERT( ! (wQuestionCount & 0xff00) );
|
|
DNS_ASSERT( ! (wNameServerCount & 0xff00) );
|
|
DNS_ASSERT( ! (wAdditionalCount & 0xff00) );
|
|
|
|
#if 0
|
|
//
|
|
// stop here if WINS response -- don't have parsing ready
|
|
//
|
|
|
|
if ( pmsgHeader->IsResponse && IS_WINS_XID(wXid) )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
" WINS Response packet.\r\n\r\n" );
|
|
goto Unlock;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// print questions and resource records
|
|
//
|
|
|
|
pchRecord = (PCHAR)(pmsgHeader + 1);
|
|
|
|
for ( isection=0; isection<4; isection++)
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
" %s Section:\r\n",
|
|
Dns_SectionNameString( isection, pmsgHeader->Opcode ) );
|
|
|
|
if ( isection==0 )
|
|
{
|
|
countSectionRR = wQuestionCount;
|
|
}
|
|
else if ( isection==1 )
|
|
{
|
|
countSectionRR = wAnswerCount;
|
|
}
|
|
else if ( isection==2 )
|
|
{
|
|
countSectionRR = wNameServerCount;
|
|
}
|
|
else if ( isection==3 )
|
|
{
|
|
countSectionRR = wAdditionalCount;
|
|
}
|
|
|
|
for ( i=0; i < countSectionRR; i++ )
|
|
{
|
|
//
|
|
// verify not overrunning length
|
|
// - check against pCurrent as well as message length
|
|
// so can print packets while being built
|
|
//
|
|
|
|
wOffset = (WORD)(pchRecord - (PCHAR)pmsgHeader);
|
|
if ( wOffset >= wLength
|
|
&&
|
|
pchRecord >= pMsg->pCurrent )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"ERROR: BOGUS PACKET:\r\n"
|
|
"\tFollowing RR (offset %d) past packet length (%d).\r\n",
|
|
wOffset,
|
|
wLength
|
|
);
|
|
goto Unlock;
|
|
}
|
|
|
|
//
|
|
// print RR name
|
|
//
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
" Name Offset = 0x%04x\r\n",
|
|
wOffset
|
|
);
|
|
|
|
cchName = DnsPrint_PacketName(
|
|
PrintRoutine,
|
|
pContext,
|
|
" Name \"",
|
|
pchRecord,
|
|
pmsgHeader,
|
|
pmsgEnd,
|
|
"\"\r\n" );
|
|
if ( ! cchName )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"ERROR: Invalid name length, stop packet print\r\n" );
|
|
DNS_ASSERT( FALSE );
|
|
break;
|
|
}
|
|
pchRecord += cchName;
|
|
|
|
// print question or resource record
|
|
|
|
if ( isection == 0 )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
" QTYPE %d\r\n"
|
|
" QCLASS %d\r\n",
|
|
FlipUnalignedWord( pchRecord ),
|
|
FlipUnalignedWord( pchRecord + sizeof(WORD) )
|
|
);
|
|
pchRecord += sizeof( DNS_WIRE_QUESTION );
|
|
}
|
|
else
|
|
{
|
|
pchRecord += DnsPrint_PacketRecord(
|
|
PrintRoutine,
|
|
pContext,
|
|
NULL,
|
|
(PDNS_WIRE_RECORD) pchRecord,
|
|
pmsgHeader,
|
|
pmsgEnd
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
// check that at proper end of packet
|
|
|
|
wOffset = (WORD)(pchRecord - (PCHAR)pmsgHeader);
|
|
if ( pchRecord < pMsg->pCurrent || wOffset < wLength )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"WARNING: message continues beyond these records\r\n"
|
|
"\tpch = %p, pCurrent = %p, %d bytes\r\n"
|
|
"\toffset = %d, msg length = %d, %d bytes\r\n",
|
|
pchRecord,
|
|
pMsg->pCurrent,
|
|
pMsg->pCurrent - pchRecord,
|
|
wOffset,
|
|
wLength,
|
|
wLength - wOffset );
|
|
}
|
|
PrintRoutine(
|
|
pContext,
|
|
" Message length = %04x\n\r\n",
|
|
wOffset );
|
|
|
|
Unlock:
|
|
DnsPrint_Unlock();
|
|
|
|
|
|
} // DnsPrint_Message
|
|
|
|
|
|
|
|
INT
|
|
DnsPrint_PacketRecord(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PDNS_WIRE_RECORD pMsgRR,
|
|
IN PDNS_HEADER pMsgHead, OPTIONAL
|
|
IN PBYTE pMsgEnd OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print RR in packet format.
|
|
|
|
Arguments:
|
|
|
|
pszHeader - Header message/name for RR.
|
|
|
|
pMsgRR - resource record to print
|
|
|
|
pMsgHead - ptr to DNS message; need for offsetting, if not given
|
|
names are not printed past first offset
|
|
|
|
pMsgEnd - ptr to end of message, specifically byte immediately after
|
|
message
|
|
|
|
Return Value:
|
|
|
|
Number of bytes in record.
|
|
|
|
--*/
|
|
{
|
|
PCHAR pdata = (PCHAR)(pMsgRR + 1);
|
|
PCHAR pdataStop;
|
|
WORD dlen = FlipUnalignedWord( &pMsgRR->DataLength );
|
|
WORD type;
|
|
PCHAR pRRString;
|
|
|
|
DnsPrint_Lock();
|
|
|
|
//
|
|
// print RR fixed fields
|
|
//
|
|
|
|
type = FlipUnalignedWord( &pMsgRR->RecordType );
|
|
pRRString = Dns_RecordStringForType( type );
|
|
|
|
if ( pszHeader )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\r\n",
|
|
pszHeader );
|
|
}
|
|
PrintRoutine(
|
|
pContext,
|
|
" TYPE %s (%u)\r\n"
|
|
" CLASS %u\r\n"
|
|
" TTL %lu\r\n"
|
|
" DLEN %u\r\n"
|
|
" DATA ",
|
|
pRRString,
|
|
type,
|
|
FlipUnalignedWord( &pMsgRR->RecordClass ),
|
|
FlipUnalignedDword( &pMsgRR->TimeToLive ),
|
|
dlen );
|
|
|
|
//
|
|
// update records may not have data
|
|
//
|
|
|
|
if ( dlen == 0 )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"(none)\r\n" );
|
|
goto Done;
|
|
}
|
|
|
|
// stop byte after RR data
|
|
|
|
pdataStop = pdata + dlen;
|
|
if ( pMsgEnd < pdataStop )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"ERROR: record at %p extends past end of packet!\n"
|
|
"\tpmsg = %p\n"
|
|
"\tpmsgEnd = %p\n"
|
|
"\trecord end = %p\n",
|
|
pMsgRR,
|
|
pMsgHead,
|
|
pMsgEnd,
|
|
pdataStop );
|
|
goto Done;
|
|
}
|
|
|
|
//
|
|
// print RR data
|
|
//
|
|
|
|
switch ( type )
|
|
{
|
|
|
|
case DNS_TYPE_A:
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%d.%d.%d.%d\r\n",
|
|
* (PUCHAR)( pdata + 0 ),
|
|
* (PUCHAR)( pdata + 1 ),
|
|
* (PUCHAR)( pdata + 2 ),
|
|
* (PUCHAR)( pdata + 3 )
|
|
);
|
|
break;
|
|
|
|
case DNS_TYPE_AAAA:
|
|
{
|
|
IP6_ADDRESS ip6;
|
|
|
|
RtlCopyMemory(
|
|
&ip6,
|
|
pdata,
|
|
sizeof(ip6) );
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n",
|
|
ip6.IP6Word[0],
|
|
ip6.IP6Word[1],
|
|
ip6.IP6Word[2],
|
|
ip6.IP6Word[3],
|
|
ip6.IP6Word[4],
|
|
ip6.IP6Word[5],
|
|
ip6.IP6Word[6],
|
|
ip6.IP6Word[7]
|
|
);
|
|
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 domain name
|
|
//
|
|
|
|
DnsPrint_PacketName(
|
|
PrintRoutine,
|
|
pContext,
|
|
NULL,
|
|
pdata,
|
|
pMsgHead,
|
|
pMsgEnd,
|
|
"\r\n" );
|
|
break;
|
|
|
|
case DNS_TYPE_MX:
|
|
case DNS_TYPE_RT:
|
|
case DNS_TYPE_AFSDB:
|
|
|
|
//
|
|
// these RR contain
|
|
// - one preference value
|
|
// - one domain name
|
|
//
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%d ",
|
|
FlipUnalignedWord( pdata )
|
|
);
|
|
DnsPrint_PacketName(
|
|
PrintRoutine,
|
|
pContext,
|
|
NULL,
|
|
pdata + sizeof(WORD),
|
|
pMsgHead,
|
|
pMsgEnd,
|
|
"\r\n" );
|
|
break;
|
|
|
|
case DNS_TYPE_SOA:
|
|
|
|
pdata += DnsPrint_PacketName(
|
|
PrintRoutine,
|
|
pContext,
|
|
"\r\n\t\tPrimaryServer: ",
|
|
pdata,
|
|
pMsgHead,
|
|
pMsgEnd,
|
|
NULL );
|
|
pdata += DnsPrint_PacketName(
|
|
PrintRoutine,
|
|
pContext,
|
|
"\r\n\t\tAdministrator: ",
|
|
pdata,
|
|
pMsgHead,
|
|
pMsgEnd,
|
|
"\r\n" );
|
|
PrintRoutine(
|
|
pContext,
|
|
"\t\tSerialNo = %d\r\n"
|
|
"\t\tRefresh = %d\r\n"
|
|
"\t\tRetry = %d\r\n"
|
|
"\t\tExpire = %d\r\n"
|
|
"\t\tMinimumTTL = %d\r\n",
|
|
FlipUnalignedDword( pdata ),
|
|
FlipUnalignedDword( (PDWORD)pdata+1 ),
|
|
FlipUnalignedDword( (PDWORD)pdata+2 ),
|
|
FlipUnalignedDword( (PDWORD)pdata+3 ),
|
|
FlipUnalignedDword( (PDWORD)pdata+4 )
|
|
);
|
|
break;
|
|
|
|
case DNS_TYPE_MINFO:
|
|
case DNS_TYPE_RP:
|
|
|
|
//
|
|
// these RRs contain two domain names
|
|
//
|
|
|
|
pdata += DnsPrint_PacketName(
|
|
PrintRoutine,
|
|
pContext,
|
|
NULL,
|
|
pdata,
|
|
pMsgHead,
|
|
pMsgEnd,
|
|
NULL );
|
|
DnsPrint_PacketName(
|
|
PrintRoutine,
|
|
pContext,
|
|
" ",
|
|
pdata,
|
|
pMsgHead,
|
|
pMsgEnd,
|
|
"\r\n" );
|
|
break;
|
|
|
|
case DNS_TYPE_TEXT:
|
|
case DNS_TYPE_HINFO:
|
|
case DNS_TYPE_ISDN:
|
|
case DNS_TYPE_X25:
|
|
{
|
|
//
|
|
// all these are simply text string(s)
|
|
//
|
|
|
|
PCHAR pch = pdata;
|
|
PCHAR pchStop = pch + dlen;
|
|
UCHAR cch;
|
|
|
|
while ( pch < pchStop )
|
|
{
|
|
cch = (UCHAR) *pch++;
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"\t%.*s\r\n",
|
|
cch,
|
|
pch );
|
|
|
|
pch += cch;
|
|
}
|
|
if ( pch != pchStop )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"ERROR: Bad RR. "
|
|
"Text strings do not add to RR length.\r\n" );
|
|
}
|
|
break;
|
|
}
|
|
|
|
case DNS_TYPE_WKS:
|
|
{
|
|
INT i;
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"WKS: Address %d.%d.%d.%d\r\n"
|
|
"\t\tProtocol %d\r\n"
|
|
"\t\tBitmask\r\n",
|
|
* (PUCHAR)( pdata + 0 ),
|
|
* (PUCHAR)( pdata + 1 ),
|
|
* (PUCHAR)( pdata + 2 ),
|
|
* (PUCHAR)( pdata + 3 ),
|
|
* (PUCHAR)( pdata + 4 ) );
|
|
|
|
pdata += SIZEOF_WKS_FIXED_DATA;
|
|
|
|
for ( i=0; i < (INT)(dlen-SIZEOF_WKS_FIXED_DATA); i++ )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"\t\t\tbyte[%d] = %x\r\n",
|
|
i,
|
|
(UCHAR) pdata[i] );
|
|
}
|
|
break;
|
|
}
|
|
|
|
case DNS_TYPE_NULL:
|
|
|
|
DnsPrint_RawOctets(
|
|
PrintRoutine,
|
|
pContext,
|
|
NULL,
|
|
"\t\t",
|
|
pdata,
|
|
dlen );
|
|
break;
|
|
|
|
case DNS_TYPE_SRV:
|
|
|
|
// SRV <priority> <weight> <port> <target host>
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"\t\tPriority = %d\r\n"
|
|
"\t\tWeight = %d\r\n"
|
|
"\t\tPort = %d\r\n",
|
|
FlipUnalignedWord( pdata ),
|
|
FlipUnalignedWord( (PWORD)pdata+1 ),
|
|
FlipUnalignedWord( (PWORD)pdata+2 )
|
|
);
|
|
DnsPrint_PacketName(
|
|
PrintRoutine,
|
|
pContext,
|
|
"\t\tTarget host ",
|
|
pdata + 3*sizeof(WORD),
|
|
pMsgHead,
|
|
pMsgEnd,
|
|
"\r\n" );
|
|
break;
|
|
|
|
case DNS_TYPE_OPT:
|
|
|
|
//
|
|
// OPT
|
|
// - RR class is buffer size
|
|
// - RR TTL contains
|
|
// <extended RCODE> low byte
|
|
// <version> second byte
|
|
// <flags-zero> high word
|
|
//
|
|
|
|
{
|
|
BYTE version;
|
|
BYTE extendedRcode;
|
|
DWORD fullRcode = 0;
|
|
WORD flags;
|
|
|
|
extendedRcode = *( (PBYTE) &pMsgRR->TimeToLive );
|
|
version = *( (PBYTE) &pMsgRR->TimeToLive + 1 );
|
|
flags = *( (PWORD) &pMsgRR->TimeToLive + 1 );
|
|
|
|
if ( pMsgHead->ResponseCode )
|
|
{
|
|
fullRcode = ((DWORD)extendedRcode << 4) +
|
|
(DWORD)pMsgHead->ResponseCode;
|
|
}
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"\t\tBuffer Size = %d\r\n"
|
|
"\t\tRcode Ext = %d (%x)\r\n"
|
|
"\t\tRcode Full = %d\r\n"
|
|
"\t\tVersion = %d\r\n"
|
|
"\t\tFlags = %x\r\n",
|
|
FlipUnalignedWord( &pMsgRR->RecordClass ),
|
|
extendedRcode, extendedRcode,
|
|
fullRcode,
|
|
version,
|
|
flags );
|
|
}
|
|
break;
|
|
|
|
case DNS_TYPE_TKEY:
|
|
{
|
|
DWORD beginTime;
|
|
DWORD expireTime;
|
|
WORD keyLength;
|
|
WORD mode;
|
|
WORD extRcode;
|
|
WORD otherLength;
|
|
|
|
otherLength = (WORD)DnsPrint_PacketName(
|
|
PrintRoutine,
|
|
pContext,
|
|
"\r\n\t\tAlgorithm: ",
|
|
pdata,
|
|
pMsgHead,
|
|
pMsgEnd,
|
|
NULL );
|
|
if ( !otherLength )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"Invalid algorithm name in TKEY RR!\r\n" );
|
|
}
|
|
pdata += otherLength;
|
|
|
|
beginTime = InlineFlipUnalignedDword( pdata );
|
|
pdata += sizeof(DWORD);
|
|
expireTime = InlineFlipUnalignedDword( pdata );
|
|
pdata += sizeof(DWORD);
|
|
|
|
mode = InlineFlipUnalignedWord( pdata );
|
|
pdata += sizeof(WORD);
|
|
extRcode = InlineFlipUnalignedWord( pdata );
|
|
pdata += sizeof(WORD);
|
|
keyLength = InlineFlipUnalignedWord( pdata );
|
|
pdata += sizeof(WORD);
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"\r\n"
|
|
"\t\tCreate time = %d\r\n"
|
|
"\t\tExpire time = %d\r\n"
|
|
"\t\tMode = %d\r\n"
|
|
"\t\tExtended RCODE = %d\r\n"
|
|
"\t\tKey Length = %d\r\n",
|
|
beginTime,
|
|
expireTime,
|
|
mode,
|
|
extRcode,
|
|
keyLength );
|
|
|
|
if ( pdata + keyLength > pdataStop )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"Invalid key length: exceeds record data!\r\n" );
|
|
break;
|
|
}
|
|
DnsPrint_RawOctets(
|
|
PrintRoutine,
|
|
pContext,
|
|
"\t\tKey:",
|
|
"\t\t ", // line header
|
|
pdata,
|
|
keyLength );
|
|
|
|
pdata += keyLength;
|
|
if ( pdata + sizeof(WORD) > pdataStop )
|
|
{
|
|
break;
|
|
}
|
|
otherLength = InlineFlipUnalignedWord( pdata );
|
|
pdata += sizeof(WORD);
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"\r\n"
|
|
"\t\tOther Length = %d\r\n",
|
|
otherLength );
|
|
|
|
if ( pdata + otherLength > pdataStop )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"Invalid other data length: exceeds record data!\r\n" );
|
|
break;
|
|
}
|
|
DnsPrint_RawOctets(
|
|
PrintRoutine,
|
|
pContext,
|
|
"\t\tOther Data:",
|
|
"\t\t ", // line header
|
|
pdata,
|
|
otherLength );
|
|
break;
|
|
}
|
|
|
|
case DNS_TYPE_TSIG:
|
|
{
|
|
ULONGLONG signTime;
|
|
WORD fudgeTime;
|
|
WORD sigLength;
|
|
WORD extRcode;
|
|
WORD wOriginalId;
|
|
WORD otherLength;
|
|
|
|
otherLength = (WORD) DnsPrint_PacketName(
|
|
PrintRoutine,
|
|
pContext,
|
|
"\r\n\t\tAlgorithm: ",
|
|
pdata,
|
|
pMsgHead,
|
|
pMsgEnd,
|
|
NULL );
|
|
if ( !otherLength )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"Invalid algorithm name in TSIG RR!\r\n" );
|
|
}
|
|
pdata += otherLength;
|
|
|
|
signTime = InlineFlipUnaligned48Bits( pdata );
|
|
pdata += sizeof(DWORD) + sizeof(WORD);
|
|
|
|
fudgeTime = InlineFlipUnalignedWord( pdata );
|
|
pdata += sizeof(WORD);
|
|
|
|
sigLength = InlineFlipUnalignedWord( pdata );
|
|
pdata += sizeof(WORD);
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"\r\n"
|
|
"\t\tSigned time = %I64u\r\n"
|
|
"\t\tFudge time = %u\r\n"
|
|
"\t\tSig Length = %u\r\n",
|
|
signTime,
|
|
fudgeTime,
|
|
sigLength );
|
|
|
|
if ( pdata + sigLength > pdataStop )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"Invalid signature length: exceeds record data!\r\n" );
|
|
break;
|
|
}
|
|
DnsPrint_RawOctets(
|
|
PrintRoutine,
|
|
pContext,
|
|
"\t\tSignature:",
|
|
"\t\t ", // line header
|
|
pdata,
|
|
sigLength );
|
|
|
|
pdata += sigLength;
|
|
if ( pdata + sizeof(DWORD) > pdataStop )
|
|
{
|
|
break;
|
|
}
|
|
wOriginalId = InlineFlipUnalignedWord( pdata );
|
|
pdata += sizeof(WORD);
|
|
|
|
extRcode = InlineFlipUnalignedWord( pdata );
|
|
pdata += sizeof(WORD);
|
|
|
|
otherLength = InlineFlipUnalignedWord( pdata );
|
|
pdata += sizeof(WORD);
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"\r\n"
|
|
"\t\tOriginal XID = %x\r\n"
|
|
"\t\tExtended RCODE = %u\r\n"
|
|
"\t\tOther Length = %u\r\n",
|
|
wOriginalId,
|
|
extRcode,
|
|
otherLength );
|
|
|
|
if ( pdata + otherLength > pdataStop )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"Invalid other data length: exceeds record data!\r\n" );
|
|
break;
|
|
}
|
|
DnsPrint_RawOctets(
|
|
PrintRoutine,
|
|
pContext,
|
|
"\t\tOther Data:",
|
|
"\t\t ", // line header
|
|
pdata,
|
|
otherLength );
|
|
break;
|
|
}
|
|
|
|
case DNS_TYPE_WINS:
|
|
{
|
|
DWORD i;
|
|
DWORD winsFlags;
|
|
DWORD lookupTimeout;
|
|
DWORD cacheTimeout;
|
|
DWORD winsCount;
|
|
CHAR flagString[ WINS_FLAG_MAX_LENGTH ];
|
|
|
|
//
|
|
// WINS
|
|
// - scope/domain mapping flag
|
|
// - lookup timeout
|
|
// - cache timeout
|
|
// - WINS server count
|
|
// - WINS server list
|
|
//
|
|
|
|
winsFlags = FlipUnalignedDword( pdata );
|
|
pdata += sizeof(DWORD);
|
|
lookupTimeout = FlipUnalignedDword( pdata );
|
|
pdata += sizeof(DWORD);
|
|
cacheTimeout = FlipUnalignedDword( pdata );
|
|
pdata += sizeof(DWORD);
|
|
winsCount = FlipUnalignedDword( pdata );
|
|
pdata += sizeof(DWORD);
|
|
|
|
Dns_WinsRecordFlagString(
|
|
winsFlags,
|
|
flagString );
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"\r\n"
|
|
"\t\tWINS flags = %s (%08x)\r\n"
|
|
"\t\tLookup timeout = %d\r\n"
|
|
"\t\tCaching TTL = %d\r\n",
|
|
flagString,
|
|
winsFlags,
|
|
lookupTimeout,
|
|
cacheTimeout );
|
|
|
|
if ( pdata + (winsCount * SIZEOF_IP4_ADDRESS) > pdataStop )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"ERROR: WINS server count leads beyond record data length!\n"
|
|
"\tpmsg = %p\n"
|
|
"\tpmsgEnd = %p\n"
|
|
"\tpRR = %p\n"
|
|
"\trecord data end = %p\n"
|
|
"\twins count = %d\n"
|
|
"\tend of wins IPs = %p\n",
|
|
pMsgHead,
|
|
pMsgEnd,
|
|
pMsgRR,
|
|
pdataStop,
|
|
winsCount,
|
|
pdata + (winsCount * SIZEOF_IP4_ADDRESS)
|
|
);
|
|
goto Done;
|
|
}
|
|
|
|
DnsPrint_Ip4AddressArray(
|
|
PrintRoutine,
|
|
pContext,
|
|
NULL,
|
|
"\tWINS",
|
|
winsCount,
|
|
(PIP4_ADDRESS) pdata );
|
|
break;
|
|
}
|
|
|
|
case DNS_TYPE_WINSR:
|
|
{
|
|
DWORD winsFlags;
|
|
DWORD lookupTimeout;
|
|
DWORD cacheTimeout;
|
|
CHAR flagString[ WINS_FLAG_MAX_LENGTH ];
|
|
|
|
//
|
|
// NBSTAT
|
|
// - scope/domain mapping flag
|
|
// - lookup timeout
|
|
// - cache timeout
|
|
// - result domain -- optional
|
|
//
|
|
|
|
winsFlags = FlipUnalignedDword( pdata );
|
|
pdata += sizeof(DWORD);
|
|
lookupTimeout = FlipUnalignedDword( pdata );
|
|
pdata += sizeof(DWORD);
|
|
cacheTimeout = FlipUnalignedDword( pdata );
|
|
pdata += sizeof(DWORD);
|
|
|
|
Dns_WinsRecordFlagString(
|
|
winsFlags,
|
|
flagString );
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"\r\n"
|
|
"\t\tWINS-R flags = %s (%08x)\r\n"
|
|
"\t\tLookup timeout = %d\r\n"
|
|
"\t\tCaching TTL = %d\r\n",
|
|
flagString,
|
|
winsFlags,
|
|
lookupTimeout,
|
|
cacheTimeout );
|
|
|
|
DnsPrint_PacketName(
|
|
PrintRoutine,
|
|
pContext,
|
|
"\t\tResult domain = ",
|
|
pdata,
|
|
pMsgHead,
|
|
pMsgEnd,
|
|
"\r\n" );
|
|
break;
|
|
}
|
|
|
|
case DNS_TYPE_KEY:
|
|
{
|
|
WORD flags;
|
|
BYTE protocol;
|
|
BYTE algorithm;
|
|
INT keyLength;
|
|
CHAR szKeyFlags[ 100 ];
|
|
|
|
keyLength = dlen - SIZEOF_KEY_FIXED_DATA;
|
|
|
|
flags = FlipUnalignedWord( pdata );
|
|
pdata += sizeof( WORD );
|
|
protocol = * ( PBYTE ) pdata;
|
|
++pdata;
|
|
algorithm = * ( PBYTE ) pdata;
|
|
++pdata;
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"\r\n"
|
|
"\t\tKEY flags = 0x%04x %s\r\n"
|
|
"\t\tKEY protocol = %s (%d)\r\n"
|
|
"\t\tKEY algorithm = %s (%d)\r\n",
|
|
(INT) flags,
|
|
Dns_KeyFlagString( szKeyFlags, flags ),
|
|
Dns_GetKeyProtocolString( protocol ),
|
|
(INT) protocol,
|
|
Dns_GetDnssecAlgorithmString( algorithm ),
|
|
(INT) algorithm );
|
|
|
|
DnsPrint_RawOctets(
|
|
PrintRoutine,
|
|
pContext,
|
|
"\t\tPublic key:",
|
|
"\t\t ", // line header
|
|
pdata,
|
|
keyLength );
|
|
break;
|
|
}
|
|
|
|
case DNS_TYPE_SIG:
|
|
{
|
|
WORD typeCovered;
|
|
BYTE algorithm;
|
|
BYTE labelCount;
|
|
DWORD originalTTL;
|
|
DWORD sigInception;
|
|
DWORD sigExpiration;
|
|
WORD keyTag;
|
|
CHAR szSigInception[ 100 ];
|
|
CHAR szSigExpiration[ 100 ];
|
|
INT sigLength;
|
|
|
|
typeCovered = FlipUnalignedWord( pdata );
|
|
pdata += sizeof( WORD );
|
|
algorithm = * ( PBYTE ) pdata;
|
|
++pdata;
|
|
labelCount = * ( PBYTE ) pdata;
|
|
++pdata;
|
|
originalTTL = FlipUnalignedDword( pdata );
|
|
pdata += sizeof( DWORD );
|
|
sigExpiration = FlipUnalignedDword( pdata );
|
|
pdata += sizeof( DWORD );
|
|
sigInception = FlipUnalignedDword( pdata );
|
|
pdata += sizeof( DWORD );
|
|
keyTag = FlipUnalignedWord( pdata );
|
|
pdata += sizeof( WORD );
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"\r\n"
|
|
"\t\tSIG type covered = %s\r\n"
|
|
"\t\tSIG algorithm = %s (%d)\r\n"
|
|
"\t\tSIG label count = %d\r\n"
|
|
"\t\tSIG original TTL = %d\r\n"
|
|
"\t\tSIG expiration = %s\r\n"
|
|
"\t\tSIG inception = %s\r\n"
|
|
"\t\tSIG key tag = %d\r\n",
|
|
Dns_RecordStringForType( typeCovered ),
|
|
Dns_GetDnssecAlgorithmString( ( BYTE ) algorithm ),
|
|
( INT ) algorithm,
|
|
( INT ) labelCount,
|
|
( INT ) originalTTL,
|
|
Dns_SigTimeString( sigExpiration, szSigExpiration ),
|
|
Dns_SigTimeString( sigInception, szSigInception ),
|
|
( INT ) keyTag );
|
|
|
|
pdata += DnsPrint_PacketName(
|
|
PrintRoutine,
|
|
pContext,
|
|
"\t\tSIG signer's name = ",
|
|
pdata,
|
|
pMsgHead,
|
|
pMsgEnd,
|
|
"\r\n" );
|
|
|
|
sigLength = ( INT ) ( pdataStop - pdata );
|
|
|
|
DnsPrint_RawOctets(
|
|
PrintRoutine,
|
|
pContext,
|
|
"\t\tSignature:",
|
|
"\t\t ", // line header
|
|
pdata,
|
|
sigLength );
|
|
break;
|
|
}
|
|
|
|
case DNS_TYPE_NXT:
|
|
{
|
|
INT bitmapLength;
|
|
INT byteIdx;
|
|
INT bitIdx;
|
|
|
|
pdata += DnsPrint_PacketName(
|
|
PrintRoutine,
|
|
pContext,
|
|
"\r\n\t\tNXT next name = ",
|
|
pdata,
|
|
pMsgHead,
|
|
pMsgEnd,
|
|
"\r\n" );
|
|
|
|
bitmapLength = ( INT ) ( pdataStop - pdata );
|
|
|
|
PrintRoutine( pContext, "\t\tNXT types covered = " );
|
|
|
|
for ( byteIdx = 0; byteIdx < bitmapLength; ++byteIdx )
|
|
{
|
|
for ( bitIdx = ( byteIdx ? 0 : 1 ); bitIdx < 8; ++bitIdx )
|
|
{
|
|
PCHAR pszType;
|
|
|
|
if ( !( pdata[ byteIdx ] & ( 1 << bitIdx ) ) )
|
|
{
|
|
continue; // Bit value is zero - do not write string.
|
|
}
|
|
pszType = Dns_RecordStringForType( byteIdx * 8 + bitIdx );
|
|
if ( !pszType )
|
|
{
|
|
ASSERT( FALSE );
|
|
continue; // This type has no string - do not write.
|
|
}
|
|
PrintRoutine( pContext, "%s ", pszType );
|
|
}
|
|
}
|
|
|
|
PrintRoutine( pContext, "\r\n" );
|
|
break;
|
|
}
|
|
|
|
default:
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"Unknown resource record type %d at %p.\r\n",
|
|
type,
|
|
pMsgRR );
|
|
|
|
DnsPrint_RawOctets(
|
|
PrintRoutine,
|
|
pContext,
|
|
NULL,
|
|
"\t\t",
|
|
pdata,
|
|
dlen );
|
|
break;
|
|
}
|
|
|
|
Done:
|
|
|
|
DnsPrint_Unlock();
|
|
|
|
return( sizeof(DNS_WIRE_RECORD) + dlen );
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Print related utilities
|
|
//
|
|
|
|
INT
|
|
Dns_WriteFormattedSystemTimeToBuffer(
|
|
OUT PCHAR pBuffer,
|
|
IN PSYSTEMTIME pSystemTime
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Write SYSTEMTIME structure to buffer.
|
|
|
|
Arguments:
|
|
|
|
pBuffer -- buffer to write into, assumed to have at least 50
|
|
bytes available
|
|
|
|
pSystemTime -- system time to convert; assumed to be local, no
|
|
time zone conversion is done
|
|
|
|
Return Value:
|
|
|
|
Bytes in formatted string.
|
|
|
|
--*/
|
|
{
|
|
PCHAR pend = pBuffer + 60;
|
|
PCHAR pstart = pBuffer;
|
|
INT count;
|
|
|
|
pBuffer += GetDateFormat(
|
|
LOCALE_SYSTEM_DEFAULT,
|
|
LOCALE_NOUSEROVERRIDE,
|
|
(PSYSTEMTIME) pSystemTime,
|
|
NULL,
|
|
pBuffer,
|
|
(int)(pend - pBuffer) );
|
|
|
|
// Replace NULL from GetDateFormat with a space.
|
|
|
|
*( pBuffer - 1 ) = ' ';
|
|
|
|
pBuffer += GetTimeFormat(
|
|
LOCALE_SYSTEM_DEFAULT,
|
|
LOCALE_NOUSEROVERRIDE,
|
|
(PSYSTEMTIME) pSystemTime,
|
|
NULL,
|
|
pBuffer,
|
|
(int)(pend - pBuffer) );
|
|
|
|
if ( pBuffer <= pstart+1 )
|
|
{
|
|
return( 0 );
|
|
}
|
|
return (INT)( pBuffer - pstart );
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Response code print
|
|
//
|
|
|
|
#define DNS_RCODE_UNKNOWN (DNS_RCODE_BADTIME + 1)
|
|
|
|
PCHAR ResponseCodeStringTable[] =
|
|
{
|
|
"NOERROR",
|
|
"FORMERR",
|
|
"SERVFAIL",
|
|
"NXDOMAIN",
|
|
"NOTIMP",
|
|
"REFUSED",
|
|
"YXDOMAIN",
|
|
"YXRRSET",
|
|
"NXRRSET",
|
|
"NOTAUTH",
|
|
"NOTZONE",
|
|
"11 - unknown\r\n",
|
|
"12 - unknown\r\n",
|
|
"13 - unknown\r\n",
|
|
"14 - unknown\r\n",
|
|
"15 - unknown\r\n",
|
|
|
|
// DNS RCODEs stop at 15 -- these extended errors are available for security
|
|
|
|
"BADSIG",
|
|
"BADKEY",
|
|
"BADTIME",
|
|
"UNKNOWN"
|
|
};
|
|
|
|
|
|
PCHAR
|
|
Dns_ResponseCodeString(
|
|
IN INT ResponseCode
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get string corresponding to a response code.
|
|
|
|
Arguments:
|
|
|
|
ResponseCode - response code
|
|
|
|
Return Value:
|
|
|
|
Ptr to string for code.
|
|
|
|
--*/
|
|
{
|
|
if ( ResponseCode > DNS_RCODE_UNKNOWN )
|
|
{
|
|
ResponseCode = DNS_RCODE_UNKNOWN;
|
|
}
|
|
return( ResponseCodeStringTable[ ResponseCode ] );
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// More detailed RCODE strings
|
|
//
|
|
|
|
PCHAR ResponseCodeExplanationStringTable[] =
|
|
{
|
|
"NOERROR: no error",
|
|
"FORMERR: format error",
|
|
"SERVFAIL: server failure",
|
|
"NXDOMAIN: name error",
|
|
"NOTIMP: not implemented",
|
|
"REFUSED",
|
|
"YXDOMAIN: name exists that should not",
|
|
"YXRRSET: RR set exists that should not",
|
|
"NXRRSET: required RR set does not exist",
|
|
"NOTAUTH: not authoritative",
|
|
"NOTZONE: name not in zone",
|
|
"11 - unknown",
|
|
"12 - unknown",
|
|
"13 - unknown",
|
|
"14 - unknown",
|
|
"15 - unknown",
|
|
|
|
// DNS RCODEs stop at 15 -- these extended errors are available for security
|
|
|
|
"BADSIG: bad signature",
|
|
"BADKEY: bad signature",
|
|
"BADTIME: invalid or expired time on signature or key",
|
|
"UNKNOWN"
|
|
};
|
|
|
|
|
|
PCHAR
|
|
Dns_ResponseCodeExplanationString(
|
|
IN INT ResponseCode
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get string corresponding to a response code.
|
|
Basically for use by packet debug routine above.
|
|
|
|
Arguments:
|
|
|
|
ResponseCode - response code
|
|
|
|
Return Value:
|
|
|
|
Ptr to string for code.
|
|
|
|
--*/
|
|
{
|
|
if ( ResponseCode > DNS_RCODE_UNKNOWN )
|
|
{
|
|
ResponseCode = DNS_RCODE_UNKNOWN;
|
|
}
|
|
return( ResponseCodeExplanationStringTable[ ResponseCode ] );
|
|
}
|
|
|
|
|
|
|
|
PCHAR
|
|
Dns_KeyFlagString(
|
|
IN OUT PCHAR pszBuff,
|
|
IN WORD Flags
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Formats a human-readable string based on the flags value
|
|
(DNSSEC KEY RR flags). See RFC2535 section 3.2.1.
|
|
|
|
Arguments:
|
|
|
|
pszBuff - buffer to dump string into should be min 100 chars
|
|
|
|
flags - flag value to generate string for
|
|
|
|
Return Value:
|
|
|
|
pszBuff
|
|
|
|
--*/
|
|
{
|
|
BOOL fZoneKey = FALSE;
|
|
|
|
*pszBuff = '\0';
|
|
|
|
// "type" bits
|
|
|
|
if ( ( Flags & 0xC000 ) == 0xC000 )
|
|
{
|
|
strcat( pszBuff, "NOKEY " );
|
|
}
|
|
else if ( ( Flags & 0xC000 ) == 0x8000 )
|
|
{
|
|
strcat( pszBuff, "NOAUTH " );
|
|
}
|
|
else if ( ( Flags & 0xC000 ) == 0x4000 )
|
|
{
|
|
strcat( pszBuff, "NOCONF " );
|
|
}
|
|
else
|
|
{
|
|
strcat( pszBuff, "NOAUTH NOCONF " );
|
|
}
|
|
|
|
// extended bit
|
|
|
|
if ( Flags & 0x1000 )
|
|
{
|
|
strcat( pszBuff, "EXTEND " );
|
|
}
|
|
|
|
// name type bits
|
|
|
|
if ( ( Flags & 0x0300 ) == 0x0300 )
|
|
{
|
|
strcat( pszBuff, "RESNT " ); // reserved name type
|
|
}
|
|
else if ( ( Flags & 0x0200 ) == 0x0100 )
|
|
{
|
|
strcat( pszBuff, "ENTITY " );
|
|
}
|
|
else if ( ( Flags & 0x0100 ) == 0x4000 )
|
|
{
|
|
strcat( pszBuff, "ZONE " );
|
|
fZoneKey = TRUE;
|
|
}
|
|
else
|
|
{
|
|
strcat( pszBuff, "USER " );
|
|
}
|
|
|
|
// signatory bits
|
|
|
|
if ( fZoneKey )
|
|
{
|
|
strcat( pszBuff, ( Flags & 0x0008 ) ? "MODEA " : "MODEB " );
|
|
if ( Flags & 0x0004 )
|
|
{
|
|
strcat( pszBuff, "STRONG " );
|
|
}
|
|
if ( Flags & 0x0002 )
|
|
{
|
|
strcat( pszBuff, "UNIQ " );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( Flags & 0x0008 )
|
|
{
|
|
strcat( pszBuff, "ZCTRL " );
|
|
}
|
|
if ( Flags & 0x0004 )
|
|
{
|
|
strcat( pszBuff, "STRONG " );
|
|
}
|
|
if ( Flags & 0x0002 )
|
|
{
|
|
strcat( pszBuff, "UNIQ " );
|
|
}
|
|
}
|
|
|
|
return pszBuff;
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Opcode print
|
|
//
|
|
|
|
PCHAR OpcodeStringTable[] =
|
|
{
|
|
"QUERY",
|
|
"IQUERY",
|
|
"SRV_STATUS",
|
|
"UNKNOWN",
|
|
"NOTIFY",
|
|
"UPDATE",
|
|
"UNKNOWN?"
|
|
};
|
|
|
|
CHAR OpcodeCharacterTable[] =
|
|
{
|
|
'Q',
|
|
'I',
|
|
'S',
|
|
'K',
|
|
'N',
|
|
'U',
|
|
'?'
|
|
};
|
|
|
|
#define DNS_OPCODE_UNSPEC (DNS_OPCODE_UPDATE + 1)
|
|
|
|
|
|
PCHAR
|
|
Dns_OpcodeString(
|
|
IN INT Opcode
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get string corresponding to a response code.
|
|
|
|
Arguments:
|
|
|
|
Opcode - response code
|
|
|
|
Return Value:
|
|
|
|
Ptr to string for code.
|
|
|
|
--*/
|
|
{
|
|
if ( Opcode > DNS_OPCODE_UNSPEC )
|
|
{
|
|
Opcode = DNS_OPCODE_UNSPEC;
|
|
}
|
|
return( OpcodeStringTable[ Opcode ] );
|
|
}
|
|
|
|
|
|
|
|
CHAR
|
|
Dns_OpcodeCharacter(
|
|
IN INT Opcode
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get string corresponding to an opcode.
|
|
|
|
Arguments:
|
|
|
|
Opcode - response code
|
|
|
|
Return Value:
|
|
|
|
Ptr to string for code.
|
|
|
|
--*/
|
|
{
|
|
if ( Opcode > DNS_OPCODE_UNSPEC )
|
|
{
|
|
Opcode = DNS_OPCODE_UNSPEC;
|
|
}
|
|
return( OpcodeCharacterTable[ Opcode ] );
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Section names
|
|
//
|
|
// With update get a new set of section names.
|
|
// Provide single interface to putting a name on them.
|
|
//
|
|
|
|
PSTR SectionNameArray[5] =
|
|
{
|
|
"Question",
|
|
"Answer",
|
|
"Authority",
|
|
"Additional",
|
|
"ERROR: Invalid Section"
|
|
};
|
|
|
|
PSTR UpdateSectionNameArray[5] =
|
|
{
|
|
"Zone",
|
|
"Prerequisite",
|
|
"Update",
|
|
"Additional",
|
|
"ERROR: Invalid Section"
|
|
};
|
|
|
|
PCHAR
|
|
Dns_SectionNameString(
|
|
IN INT iSection,
|
|
IN INT iOpcode
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get string corresponding to name of RR section id.
|
|
For use by packet debug routine above.
|
|
|
|
Arguments:
|
|
|
|
iSection - section id (0-3 for Question-Additional)
|
|
|
|
iOpcode - opcode
|
|
|
|
Return Value:
|
|
|
|
Ptr to string for section name.
|
|
|
|
--*/
|
|
{
|
|
if ( iSection >= 4 )
|
|
{
|
|
iSection = 4;
|
|
}
|
|
|
|
if ( iOpcode == DNS_OPCODE_UPDATE )
|
|
{
|
|
return( UpdateSectionNameArray[iSection] );
|
|
}
|
|
else
|
|
{
|
|
return( SectionNameArray[iSection] );
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
DnsPrint_MessageNoContext(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PDNS_HEADER pMsgHead,
|
|
IN WORD wLength OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print DNS message buffer.
|
|
Includes context information as well as actual DNS message.
|
|
|
|
--*/
|
|
{
|
|
PCHAR pchRecord;
|
|
PBYTE pmsgEnd;
|
|
INT i;
|
|
INT isection;
|
|
INT cchName;
|
|
WORD wOffset;
|
|
WORD wXid;
|
|
WORD wQuestionCount;
|
|
WORD wAnswerCount;
|
|
WORD wNameServerCount;
|
|
WORD wAdditionalCount;
|
|
WORD countSectionRR;
|
|
BOOL fFlipped = FALSE;
|
|
|
|
//
|
|
// processing limits
|
|
// - if length given set stop limit
|
|
// - if length not given set wLength so checks against
|
|
// length overrun always fail (are ok)
|
|
//
|
|
|
|
if ( wLength )
|
|
{
|
|
pmsgEnd = ((PBYTE)pMsgHead) + wLength;
|
|
}
|
|
else
|
|
{
|
|
wLength = MAXWORD;
|
|
pmsgEnd = NULL;
|
|
}
|
|
|
|
|
|
DnsPrint_Lock();
|
|
|
|
if ( pszHeader )
|
|
{
|
|
PrintRoutine( pContext, "%s\r\n", pszHeader );
|
|
}
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"DNS message header at %p\r\n",
|
|
pMsgHead );
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
" XID 0x%04hx\r\n"
|
|
" Flags 0x%04hx\r\n"
|
|
" QR 0x%lx (%s)\r\n"
|
|
" OPCODE 0x%lx (%s)\r\n"
|
|
" AA 0x%lx\r\n"
|
|
" TC 0x%lx\r\n"
|
|
" RD 0x%lx\r\n"
|
|
" RA 0x%lx\r\n"
|
|
" Z 0x%lx\r\n"
|
|
" RCODE 0x%lx (%s)\r\n"
|
|
" QCOUNT 0x%hx\r\n"
|
|
" ACOUNT 0x%hx\r\n"
|
|
" NSCOUNT 0x%hx\r\n"
|
|
" ARCOUNT 0x%hx\r\n",
|
|
|
|
pMsgHead->Xid,
|
|
ntohs((*((PWORD)pMsgHead + 1))),
|
|
|
|
pMsgHead->IsResponse,
|
|
(pMsgHead->IsResponse ? "response" : "question"),
|
|
pMsgHead->Opcode,
|
|
Dns_OpcodeString( pMsgHead->Opcode ),
|
|
pMsgHead->Authoritative,
|
|
pMsgHead->Truncation,
|
|
pMsgHead->RecursionDesired,
|
|
pMsgHead->RecursionAvailable,
|
|
pMsgHead->Reserved,
|
|
pMsgHead->ResponseCode,
|
|
Dns_ResponseCodeString( pMsgHead->ResponseCode ),
|
|
|
|
pMsgHead->QuestionCount,
|
|
pMsgHead->AnswerCount,
|
|
pMsgHead->NameServerCount,
|
|
pMsgHead->AdditionalCount );
|
|
|
|
//
|
|
// determine if byte flipped and get correct count
|
|
//
|
|
|
|
wXid = pMsgHead->Xid;
|
|
wQuestionCount = pMsgHead->QuestionCount;
|
|
wAnswerCount = pMsgHead->AnswerCount;
|
|
wNameServerCount = pMsgHead->NameServerCount;
|
|
wAdditionalCount = pMsgHead->AdditionalCount;
|
|
|
|
if ( wQuestionCount )
|
|
{
|
|
fFlipped = wQuestionCount & 0xff00;
|
|
}
|
|
else if ( wNameServerCount )
|
|
{
|
|
fFlipped = wNameServerCount & 0xff00;
|
|
}
|
|
if ( fFlipped )
|
|
{
|
|
wXid = ntohs( wXid );
|
|
wQuestionCount = ntohs( wQuestionCount );
|
|
wAnswerCount = ntohs( wAnswerCount );
|
|
wNameServerCount = ntohs( wNameServerCount );
|
|
wAdditionalCount = ntohs( wAdditionalCount );
|
|
}
|
|
|
|
//
|
|
// catch record flipping problems -- all are flipped or none at all
|
|
// and no record count should be > 256 EXCEPT answer count
|
|
// during FAST zone transfer
|
|
//
|
|
|
|
DNS_ASSERT( ! (wQuestionCount & 0xff00) );
|
|
DNS_ASSERT( ! (wNameServerCount & 0xff00) );
|
|
DNS_ASSERT( ! (wAdditionalCount & 0xff00) );
|
|
|
|
#if 0
|
|
//
|
|
// stop here if WINS response -- don't have parsing ready
|
|
//
|
|
|
|
if ( pMsgHead->IsResponse && IS_WINS_XID(wXid) )
|
|
{
|
|
PrintRoutine( pContext, " WINS Response packet.\r\n\r\n" );
|
|
goto Unlock;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// print questions and resource records
|
|
//
|
|
|
|
pchRecord = (PCHAR)(pMsgHead + 1);
|
|
|
|
for ( isection=0; isection<4; isection++)
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
" %s Section:\r\n",
|
|
Dns_SectionNameString( isection, pMsgHead->Opcode ) );
|
|
|
|
if ( isection==0 )
|
|
{
|
|
countSectionRR = wQuestionCount;
|
|
}
|
|
else if ( isection==1 )
|
|
{
|
|
countSectionRR = wAnswerCount;
|
|
}
|
|
else if ( isection==2 )
|
|
{
|
|
countSectionRR = wNameServerCount;
|
|
}
|
|
else if ( isection==3 )
|
|
{
|
|
countSectionRR = wAdditionalCount;
|
|
}
|
|
|
|
for ( i=0; i < countSectionRR; i++ )
|
|
{
|
|
//
|
|
// verify not overrunning length
|
|
// - check against pCurrent as well as message length
|
|
// so can print packets while being built
|
|
//
|
|
|
|
wOffset = (WORD)(pchRecord - (PCHAR)pMsgHead);
|
|
|
|
if ( wOffset >= wLength )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"ERROR: BOGUS PACKET:\r\n"
|
|
"\tFollowing RR (offset %d) past packet length (%d).\r\n",
|
|
wOffset,
|
|
wLength
|
|
);
|
|
goto Unlock;
|
|
}
|
|
|
|
//
|
|
// print RR name
|
|
//
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
" Name Offset = 0x%04x\r\n",
|
|
wOffset
|
|
);
|
|
|
|
cchName = DnsPrint_PacketName(
|
|
PrintRoutine,
|
|
pContext,
|
|
" Name \"",
|
|
pchRecord,
|
|
pMsgHead,
|
|
pmsgEnd,
|
|
"\"\r\n" );
|
|
if ( !cchName )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"ERROR: Invalid name length, stop packet print\r\n" );
|
|
DNS_ASSERT( FALSE );
|
|
break;
|
|
}
|
|
pchRecord += cchName;
|
|
|
|
// print question or resource record
|
|
|
|
if ( isection == 0 )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
" QTYPE %d\r\n"
|
|
" QCLASS %d\r\n",
|
|
FlipUnalignedWord( pchRecord ),
|
|
FlipUnalignedWord( pchRecord + sizeof(WORD) )
|
|
);
|
|
pchRecord += sizeof( DNS_WIRE_QUESTION );
|
|
}
|
|
else
|
|
{
|
|
pchRecord += DnsPrint_PacketRecord(
|
|
PrintRoutine,
|
|
pContext,
|
|
NULL,
|
|
(PDNS_WIRE_RECORD) pchRecord,
|
|
pMsgHead,
|
|
pmsgEnd
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
// check that at proper end of packet
|
|
|
|
wOffset = (WORD)(pchRecord - (PCHAR)pMsgHead);
|
|
PrintRoutine(
|
|
pContext,
|
|
" Message length = %04x\r\n\r\n",
|
|
wOffset );
|
|
|
|
// print warning if given message length and did not end up
|
|
// at end of message
|
|
// note: pmsgEnd test in case passed wLength==0, in which case
|
|
// wLength set to MAXDWORD above
|
|
|
|
if ( pmsgEnd && wOffset < wLength )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"WARNING: message continues beyond these records\r\n"
|
|
"\tpch = %p\r\n"
|
|
"\toffset = %d, msg length = %d, %d bytes\r\n",
|
|
pchRecord,
|
|
wOffset,
|
|
wLength,
|
|
wLength - wOffset );
|
|
|
|
DnsPrint_RawOctets(
|
|
PrintRoutine,
|
|
pContext,
|
|
"Remaining bytes:",
|
|
NULL,
|
|
pchRecord,
|
|
(wLength - wOffset) );
|
|
}
|
|
|
|
Unlock:
|
|
DnsPrint_Unlock();
|
|
|
|
|
|
} // DnsPrint_MessageNoContext
|
|
|
|
|
|
|
|
DWORD
|
|
DnsStringPrint_Guid(
|
|
OUT PCHAR pBuffer,
|
|
IN PGUID pGuid
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print GUID to buffer.
|
|
|
|
Arguments:
|
|
|
|
pBuffer - buffer to print to
|
|
buffer must be big enough for GUID string
|
|
GUID_STRING_BUFFER_LENGTH covers it
|
|
|
|
pGuid - GUID to print
|
|
|
|
Return Value:
|
|
|
|
Count of bytes printed to string.
|
|
|
|
--*/
|
|
{
|
|
if ( !pGuid )
|
|
{
|
|
*pBuffer = 0;
|
|
return 0;
|
|
}
|
|
|
|
return sprintf(
|
|
pBuffer,
|
|
"%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x",
|
|
pGuid->Data1,
|
|
pGuid->Data2,
|
|
pGuid->Data3,
|
|
*(PWORD) &pGuid->Data4[0],
|
|
pGuid->Data4[2],
|
|
pGuid->Data4[3],
|
|
pGuid->Data4[4],
|
|
pGuid->Data4[5],
|
|
pGuid->Data4[6],
|
|
pGuid->Data4[7] );
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_Guid(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PGUID pGuid
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print GUID
|
|
|
|
Arguments:
|
|
|
|
pszHeader - Header message/name for RR.
|
|
|
|
pGuid -- ptr to GUID to print
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
CHAR guidBuffer[ GUID_STRING_BUFFER_LENGTH ];
|
|
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "Guid";
|
|
}
|
|
if ( !pGuid )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s: NULL GUID pointer!\r\n",
|
|
pszHeader );
|
|
}
|
|
|
|
// convert GUID to string
|
|
|
|
DnsStringPrint_Guid(
|
|
guidBuffer,
|
|
pGuid );
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s: (%p) %s\r\n",
|
|
pszHeader,
|
|
pGuid,
|
|
guidBuffer );
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
DnsStringPrint_RawOctets(
|
|
OUT PCHAR pBuffer,
|
|
IN PCHAR pchData,
|
|
IN DWORD dwLength,
|
|
IN PSTR pszLineHeader,
|
|
IN DWORD dwLineLength
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print raw octect data to sting
|
|
|
|
Arguments:
|
|
|
|
pBuffer - buffer to print to
|
|
|
|
pchData - data to print
|
|
|
|
dwLength - length of data to print
|
|
|
|
pszLineHeader - header on each line.
|
|
|
|
dwLineLength - number of bytes to print on line; default is
|
|
|
|
Return Value:
|
|
|
|
Count of bytes printed to string.
|
|
|
|
--*/
|
|
{
|
|
INT i;
|
|
INT lineCount = 0;
|
|
PCHAR pch = pBuffer;
|
|
|
|
*pch = 0;
|
|
|
|
//
|
|
// catch NULL pointer
|
|
// - return is null terminated
|
|
// - but indicate no bytes written
|
|
//
|
|
|
|
if ( !pchData )
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// write each byte in hex
|
|
// - if dwLineLength set break into lines with count
|
|
// or optional header
|
|
//
|
|
|
|
for ( i = 0; i < (INT)dwLength; i++ )
|
|
{
|
|
if ( dwLineLength && (i % dwLineLength) == 0 )
|
|
{
|
|
if ( pszLineHeader )
|
|
{
|
|
pch += sprintf( pch, "\r\n%s", pszLineHeader );
|
|
}
|
|
else
|
|
{
|
|
pch += sprintf( pch, "\r\n%3d> ", i );
|
|
}
|
|
lineCount++;
|
|
}
|
|
|
|
pch += sprintf( pch, "%02x ", (UCHAR)pchData[i] );
|
|
}
|
|
|
|
return( (DWORD)(pch - pBuffer) );
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_RawBinary(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PSTR pszLineHeader,
|
|
IN PCHAR pchData,
|
|
IN DWORD dwLength,
|
|
IN DWORD PrintSize
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print raw data.
|
|
|
|
Arguments:
|
|
|
|
pszHeader - Header message/name for RR.
|
|
|
|
pszLineHeader - Header on each line.
|
|
|
|
pchData - data to print
|
|
|
|
dwLength - length of data to print
|
|
|
|
PrintSize - size to print in
|
|
size(QWORD)
|
|
size(DWORD)
|
|
size(WORD)
|
|
defaults to bytes
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
DWORD i;
|
|
DWORD lineCount = 0;
|
|
CHAR buf[ 2000 ];
|
|
PCHAR pch = buf;
|
|
PCHAR pbyte;
|
|
PCHAR pend;
|
|
|
|
DnsPrint_Lock();
|
|
|
|
if ( pszHeader )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s",
|
|
pszHeader );
|
|
}
|
|
|
|
buf[0] = 0;
|
|
|
|
//
|
|
// print bytes
|
|
// - write 16 bytes a line
|
|
// - buffer up 10 lines for speed
|
|
//
|
|
// note: we'll write a partial (<16 byte) line the first
|
|
// time if data is unaligned with PrintSize, then we'll
|
|
// write at 16 a pop
|
|
//
|
|
|
|
if ( PrintSize == 0 )
|
|
{
|
|
PrintSize = 1;
|
|
}
|
|
|
|
i = 0;
|
|
pch = buf;
|
|
pend = (PBYTE)pchData + dwLength;
|
|
|
|
while ( i < dwLength )
|
|
{
|
|
DWORD lineBytes = (i%16);
|
|
|
|
if ( lineBytes==0 || lineBytes > (16-PrintSize) )
|
|
{
|
|
if ( lineCount > 10 )
|
|
{
|
|
PrintRoutine( pContext, buf );
|
|
lineCount = 0;
|
|
pch = buf;
|
|
}
|
|
|
|
if ( pszLineHeader )
|
|
{
|
|
pch += sprintf( pch, "\r\n%s", pszLineHeader );
|
|
}
|
|
else
|
|
{
|
|
pch += sprintf( pch, "\r\n\t%3d> ", i );
|
|
}
|
|
lineCount++;
|
|
|
|
//if ( i >= 128 && dlen > 256 )
|
|
//{
|
|
// PrintRoutine( pContext, "skipping remaining bytes ...\r\n" ));
|
|
//}
|
|
}
|
|
|
|
pbyte = &pchData[i];
|
|
|
|
if ( PrintSize == sizeof(QWORD) &&
|
|
POINTER_IS_ALIGNED( pbyte, ALIGN_QUAD ) &&
|
|
pbyte + sizeof(QWORD) <= pend )
|
|
{
|
|
pch += sprintf( pch, "%I64x ", *(PQWORD)pbyte );
|
|
i += sizeof(QWORD);
|
|
}
|
|
else if ( PrintSize == sizeof(DWORD) &&
|
|
POINTER_IS_ALIGNED( pbyte, ALIGN_DWORD ) &&
|
|
pbyte + sizeof(DWORD) <= pend )
|
|
{
|
|
pch += sprintf( pch, "%08x ", *(PDWORD)pbyte );
|
|
i += sizeof(DWORD);
|
|
}
|
|
else if ( PrintSize == sizeof(WORD) &&
|
|
POINTER_IS_ALIGNED( pbyte, ALIGN_WORD ) &&
|
|
pbyte + sizeof(WORD) <= pend )
|
|
{
|
|
pch += sprintf( pch, "%04x ", *(PWORD)pbyte );
|
|
i += sizeof(WORD);
|
|
}
|
|
else // default to byte print
|
|
{
|
|
pch += sprintf( pch, "%02x ", *pbyte );
|
|
i++;
|
|
}
|
|
}
|
|
|
|
// print remaining bytes in buffer
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\r\n",
|
|
buf );
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_RawOctets(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PSTR pszLineHeader,
|
|
IN PCHAR pchData,
|
|
IN DWORD dwLength
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print raw octect data.
|
|
|
|
Arguments:
|
|
|
|
pszHeader - Header message/name for RR.
|
|
|
|
pszLineHeader - Header on each line.
|
|
|
|
pchData - data to print
|
|
|
|
dwLength - length of data to print
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
INT i;
|
|
INT lineCount = 0;
|
|
CHAR buf[ 2000 ];
|
|
PCHAR pch = buf;
|
|
|
|
DnsPrint_Lock();
|
|
|
|
if ( pszHeader )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s",
|
|
pszHeader );
|
|
}
|
|
|
|
buf[0] = 0;
|
|
|
|
// buffer every 20 lines for speed
|
|
|
|
for ( i = 0; i < (INT)dwLength; i++ )
|
|
{
|
|
if ( !(i%16) )
|
|
{
|
|
if ( lineCount > 10 )
|
|
{
|
|
PrintRoutine( pContext, buf );
|
|
lineCount = 0;
|
|
pch = buf;
|
|
}
|
|
|
|
if ( pszLineHeader )
|
|
{
|
|
pch += sprintf( pch, "\r\n%s", pszLineHeader );
|
|
}
|
|
else
|
|
{
|
|
pch += sprintf( pch, "\r\n%3d> ", i );
|
|
}
|
|
lineCount++;
|
|
|
|
//if ( i >= 128 && dlen > 256 )
|
|
//{
|
|
// PrintRoutine( pContext, "skipping remaining bytes ...\r\n" ));
|
|
//}
|
|
}
|
|
|
|
pch += sprintf( pch, "%02x ", (UCHAR)pchData[i] );
|
|
}
|
|
|
|
// print remaining bytes in buffer
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\r\n",
|
|
buf );
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_ParsedRecord(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PDNS_PARSED_RR pParsedRR
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print parsed RR structure.
|
|
|
|
Arguments:
|
|
|
|
pszHeader - Header message/name for RR.
|
|
|
|
pParsedRR - parsed RR to print
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "Parsed RR:";
|
|
}
|
|
|
|
if ( !pParsedRR )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s %s\r\n",
|
|
pszHeader,
|
|
"NULL ParsedRR ptr." );
|
|
return;
|
|
}
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\r\n"
|
|
"\tpchName = %p\r\n"
|
|
"\tpchRR = %p\r\n"
|
|
"\tpchData = %p\r\n"
|
|
"\tpchNextRR = %p\r\n"
|
|
"\twType = %d\r\n"
|
|
"\twClass = %d\r\n"
|
|
"\tTTL = %d\r\n"
|
|
"\twDataLength = %d\r\n",
|
|
pszHeader,
|
|
pParsedRR->pchName,
|
|
pParsedRR->pchRR,
|
|
pParsedRR->pchData,
|
|
pParsedRR->pchNextRR,
|
|
pParsedRR->Type,
|
|
pParsedRR->Class,
|
|
pParsedRR->Ttl,
|
|
pParsedRR->DataLength
|
|
);
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Winsock RnR structures
|
|
//
|
|
|
|
VOID
|
|
DnsPrint_FdSet(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN struct fd_set * pfd_set
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print sockets in FD_SET.
|
|
|
|
--*/
|
|
{
|
|
INT count;
|
|
INT i;
|
|
|
|
DNS_ASSERT( pfd_set );
|
|
|
|
count = (INT) pfd_set->fd_count;
|
|
|
|
DnsPrint_Lock();
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s (count = %d)\r\n",
|
|
pszHeader ? pszHeader : "FD_SET:",
|
|
count );
|
|
|
|
for (i=0; i<count; i++)
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"\tsocket[%d] = %d\r\n",
|
|
i,
|
|
pfd_set->fd_array[i] );
|
|
}
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_Sockaddr(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN DWORD Indent,
|
|
IN PSOCKADDR pSockaddr,
|
|
IN INT iSockaddrLength
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print sockaddr structure and length used in call.
|
|
|
|
--*/
|
|
{
|
|
PSTR pindent = INDENT_STRING( Indent );
|
|
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "Sockaddr:";
|
|
}
|
|
|
|
if ( !pSockaddr )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s%s\tNULL Sockaddr passed to print.\r\n",
|
|
pindent,
|
|
pszHeader );
|
|
return;
|
|
}
|
|
|
|
DnsPrint_Lock();
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s%s\r\n"
|
|
"%s\tpointer = %p\r\n"
|
|
"%s\tlength = %d\r\n"
|
|
"%s\tsa_family = %d\r\n",
|
|
pindent, pszHeader,
|
|
pindent, pSockaddr,
|
|
pindent, iSockaddrLength,
|
|
pindent, pSockaddr->sa_family
|
|
);
|
|
|
|
switch ( pSockaddr->sa_family )
|
|
{
|
|
|
|
case AF_INET:
|
|
{
|
|
PSOCKADDR_IN psin = (PSOCKADDR_IN) pSockaddr;
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\tsin_port = %04x\r\n"
|
|
"%s\tsin_addr = %s (%08x)\r\n"
|
|
"%s\tsin_zero = %08x %08x\r\n",
|
|
pindent, psin->sin_port,
|
|
pindent, inet_ntoa( psin->sin_addr ),
|
|
psin->sin_addr.s_addr,
|
|
pindent, *(PDWORD) &psin->sin_zero[0],
|
|
*(PDWORD) &psin->sin_zero[4]
|
|
);
|
|
break;
|
|
}
|
|
|
|
case AF_INET6:
|
|
{
|
|
PSOCKADDR_IN6 psin = (PSOCKADDR_IN6) pSockaddr;
|
|
|
|
CHAR buffer[ IP6_ADDRESS_STRING_BUFFER_LENGTH ];
|
|
|
|
Dns_Ip6AddressToString_A(
|
|
buffer,
|
|
(PIP6_ADDRESS) &psin->sin6_addr );
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\tsin6_port = %04x\r\n"
|
|
"%s\tsin6_flowinfo = %08x\r\n"
|
|
"%s\tsin6_addr = %s\r\n"
|
|
"%s\tsin6_scope_id = %08x\r\n",
|
|
pindent, psin->sin6_port,
|
|
pindent, psin->sin6_flowinfo,
|
|
pindent, buffer,
|
|
pindent, psin->sin6_scope_id
|
|
);
|
|
break;
|
|
}
|
|
|
|
default:
|
|
|
|
// print unknown in WORDs
|
|
// limit print as this is probably a busted sockaddr due to bug
|
|
{
|
|
DnsPrint_RawBinary(
|
|
PrintRoutine,
|
|
pContext,
|
|
"\tdata: ",
|
|
pindent, // line header
|
|
pSockaddr->sa_data,
|
|
iSockaddrLength < 100
|
|
? iSockaddrLength
|
|
: 100,
|
|
sizeof(WORD)
|
|
);
|
|
break;
|
|
}
|
|
}
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_AddrInfoEx(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN DWORD Indent,
|
|
IN PADDRINFO pAddrInfo,
|
|
IN BOOL fUnicode
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print ADDRINFO structure.
|
|
|
|
--*/
|
|
{
|
|
PSTR pindent = INDENT_STRING( Indent );
|
|
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "AddrInfo:";
|
|
}
|
|
|
|
if ( !pAddrInfo )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s%s NULL AddrInfo.\n",
|
|
pindent,
|
|
pszHeader );
|
|
return;
|
|
}
|
|
|
|
DnsPrint_Lock();
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s%s\n"
|
|
"%s\tPtr = %p\n"
|
|
"%s\tNext Ptr = %p\n"
|
|
"%s\tFlags = %08x\n"
|
|
"%s\tFamily = %d\n"
|
|
"%s\tSockType = %d\n"
|
|
"%s\tProtocol = %d\n"
|
|
"%s\tAddrLength = %d\n"
|
|
"%s\tName = %s%S\n",
|
|
pindent, pszHeader,
|
|
pindent, pAddrInfo,
|
|
pindent, pAddrInfo->ai_next,
|
|
pindent, pAddrInfo->ai_flags,
|
|
pindent, pAddrInfo->ai_family,
|
|
pindent, pAddrInfo->ai_socktype,
|
|
pindent, pAddrInfo->ai_protocol,
|
|
pindent, pAddrInfo->ai_addrlen,
|
|
pindent,
|
|
(fUnicode) ? "" : pAddrInfo->ai_canonname,
|
|
(fUnicode) ? pAddrInfo->ai_canonname : ""
|
|
);
|
|
|
|
DnsPrint_Sockaddr(
|
|
PrintRoutine,
|
|
pContext,
|
|
NULL,
|
|
Indent + 1,
|
|
pAddrInfo->ai_addr,
|
|
pAddrInfo->ai_addrlen );
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_AddrInfoListEx(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN DWORD Indent,
|
|
IN PADDRINFO pAddrInfo,
|
|
IN BOOL fUnicode
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print ADDRINFO structure.
|
|
|
|
--*/
|
|
{
|
|
PADDRINFO paddr = pAddrInfo;
|
|
PSTR pindent = INDENT_STRING( Indent );
|
|
|
|
//
|
|
// list header
|
|
//
|
|
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "AddrInfo List:";
|
|
}
|
|
|
|
if ( !paddr )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s%s NULL AddrInfo List.\r\n",
|
|
pindent,
|
|
pszHeader );
|
|
return;
|
|
}
|
|
|
|
DnsPrint_Lock();
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s%s\n",
|
|
pindent, pszHeader
|
|
);
|
|
|
|
//
|
|
// print each ADDRINFO in list
|
|
//
|
|
|
|
while ( paddr )
|
|
{
|
|
DnsPrint_AddrInfoEx(
|
|
PrintRoutine,
|
|
pContext,
|
|
NULL,
|
|
Indent,
|
|
paddr,
|
|
fUnicode );
|
|
|
|
paddr = paddr->ai_next;
|
|
}
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"End of AddrInfo list\n\n"
|
|
);
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_SocketAddress(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN DWORD Indent,
|
|
IN PSOCKET_ADDRESS pSocketAddress
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print SOCKET_ADDRESS structure.
|
|
|
|
--*/
|
|
{
|
|
PSTR pindent = INDENT_STRING( Indent );
|
|
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "SocketAddress:";
|
|
}
|
|
|
|
if ( !pSocketAddress )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s%s NULL SocketAddress.\r\n",
|
|
pindent,
|
|
pszHeader );
|
|
return;
|
|
}
|
|
|
|
DnsPrint_Lock();
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s%s\n"
|
|
"%s\tpSockaddr = %p\r\n"
|
|
"%s\tiSockaddrLength = %d\r\n",
|
|
pindent, pszHeader,
|
|
pindent, pSocketAddress->lpSockaddr,
|
|
pindent, pSocketAddress->iSockaddrLength );
|
|
|
|
DnsPrint_Sockaddr(
|
|
PrintRoutine,
|
|
pContext,
|
|
NULL,
|
|
Indent,
|
|
pSocketAddress->lpSockaddr,
|
|
pSocketAddress->iSockaddrLength );
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_CsAddr(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN DWORD Indent,
|
|
IN PCSADDR_INFO pCsAddr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print CSADDR_INFO structure.
|
|
|
|
Arguments:
|
|
|
|
PrintRoutine - routine to print with
|
|
|
|
pParam - ptr to print context
|
|
|
|
pszHeader - header
|
|
|
|
Indent - indent count, for formatting CSADDR inside larger struct
|
|
|
|
pCsAddr - ptr to CSADDRINFO to print
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PSTR pindent = INDENT_STRING( Indent );
|
|
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "CSAddrInfo:";
|
|
}
|
|
|
|
if ( !pCsAddr )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s%s \tNULL CSADDR_INFO ptr.\r\n",
|
|
pindent, pszHeader
|
|
);
|
|
return;
|
|
}
|
|
|
|
// print the struct
|
|
|
|
DnsPrint_Lock();
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s%s\r\n"
|
|
"%s\tPtr = %p\n"
|
|
"%s\tSocketType = %d\n"
|
|
"%s\tProtocol = %d\n",
|
|
pindent, pszHeader,
|
|
pindent, pCsAddr,
|
|
pindent, pCsAddr->iSocketType,
|
|
pindent, pCsAddr->iProtocol
|
|
);
|
|
|
|
DnsPrint_SocketAddress(
|
|
PrintRoutine,
|
|
pContext,
|
|
"LocalAddress:",
|
|
Indent,
|
|
& pCsAddr->LocalAddr
|
|
);
|
|
|
|
DnsPrint_SocketAddress(
|
|
PrintRoutine,
|
|
pContext,
|
|
"RemoteAddress:",
|
|
Indent,
|
|
& pCsAddr->RemoteAddr
|
|
);
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_AfProtocolsArray(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PAFPROTOCOLS pProtocolArray,
|
|
IN DWORD ProtocolCount
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print AFPROTOCOLS array.
|
|
|
|
Arguments:
|
|
|
|
PrintRoutine - routine to print with
|
|
|
|
pszHeader - header
|
|
|
|
pProtocolArray - protocols array
|
|
|
|
ProtocolCount - array count
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
DWORD i;
|
|
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "AFPROTOCOLS Array:";
|
|
}
|
|
|
|
// print
|
|
// - array + count
|
|
// - each protocol element
|
|
|
|
DnsPrint_Lock();
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\r\n"
|
|
"\tProtocol Array = %p\r\n"
|
|
"\tProtocol Count = %d\r\n",
|
|
pszHeader,
|
|
pProtocolArray,
|
|
ProtocolCount );
|
|
|
|
if ( pProtocolArray )
|
|
{
|
|
for ( i=0; i<ProtocolCount; i++ )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"\t\tfamily = %d; proto = %d\r\n",
|
|
pProtocolArray[i].iAddressFamily,
|
|
pProtocolArray[i].iProtocol );
|
|
}
|
|
}
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_WsaQuerySet(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN LPWSAQUERYSET pQuerySet,
|
|
IN BOOL fUnicode
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print WSAQUERYSET structure.
|
|
|
|
Arguments:
|
|
|
|
PrintRoutine - routine to print with
|
|
|
|
pszHeader - header
|
|
|
|
pQuerySet - ptr to WSAQUERYSET to print
|
|
|
|
fUnicode - TRUE if WSAQUERYSET is wide (WSAQUERYSETW)
|
|
FALSE if ANSI
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
CHAR serviceGuidBuffer[ GUID_STRING_BUFFER_LENGTH ];
|
|
CHAR nameSpaceGuidBuffer[ GUID_STRING_BUFFER_LENGTH ];
|
|
DWORD i;
|
|
|
|
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "WSAQuerySet:";
|
|
}
|
|
|
|
if ( !pQuerySet )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s NULL QuerySet ptr\r\n",
|
|
pszHeader );
|
|
return;
|
|
}
|
|
|
|
// convert GUIDs to strings
|
|
|
|
DnsStringPrint_Guid(
|
|
serviceGuidBuffer,
|
|
pQuerySet->lpServiceClassId
|
|
);
|
|
DnsStringPrint_Guid(
|
|
nameSpaceGuidBuffer,
|
|
pQuerySet->lpNSProviderId
|
|
);
|
|
|
|
// print the struct
|
|
|
|
DnsPrint_Lock();
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\r\n"
|
|
"\tSize = %d\r\n"
|
|
"\tServiceInstanceName = %S%s\r\n"
|
|
"\tService GUID = (%p) %s\r\n"
|
|
"\tWSA version = %p %x %d\r\n"
|
|
"\tComment = %S%s\r\n"
|
|
"\tName Space = %d %s\r\n"
|
|
"\tName Space GUID = (%p) %s\r\n"
|
|
"\tContext = %S%s\r\n"
|
|
"\tNumberOfProtocols = %d\r\n"
|
|
"\tProtocol Array = %p\r\n"
|
|
"\tQueryString = %S%s\r\n"
|
|
"\tCS Addr Count = %d\r\n"
|
|
"\tCS Addr Array = %p\r\n"
|
|
"\tOutput Flags = %08x\r\n"
|
|
"\tpBlob = %p\r\n",
|
|
|
|
pszHeader,
|
|
pQuerySet->dwSize,
|
|
DNSSTRING_WIDE( fUnicode, pQuerySet->lpszServiceInstanceName ),
|
|
DNSSTRING_ANSI( fUnicode, pQuerySet->lpszServiceInstanceName ),
|
|
pQuerySet->lpServiceClassId,
|
|
serviceGuidBuffer,
|
|
pQuerySet->lpVersion,
|
|
( pQuerySet->lpVersion ) ? pQuerySet->lpVersion->dwVersion : 0,
|
|
( pQuerySet->lpVersion ) ? pQuerySet->lpVersion->ecHow : 0,
|
|
|
|
DNSSTRING_WIDE( fUnicode, pQuerySet->lpszComment ),
|
|
DNSSTRING_ANSI( fUnicode, pQuerySet->lpszComment ),
|
|
pQuerySet->dwNameSpace,
|
|
Dns_GetRnrNameSpaceIdString( pQuerySet->dwNameSpace ),
|
|
pQuerySet->lpNSProviderId,
|
|
nameSpaceGuidBuffer,
|
|
DNSSTRING_WIDE( fUnicode, pQuerySet->lpszContext ),
|
|
DNSSTRING_ANSI( fUnicode, pQuerySet->lpszContext ),
|
|
|
|
pQuerySet->dwNumberOfProtocols,
|
|
pQuerySet->lpafpProtocols,
|
|
DNSSTRING_WIDE( fUnicode, pQuerySet->lpszQueryString ),
|
|
DNSSTRING_ANSI( fUnicode, pQuerySet->lpszQueryString ),
|
|
|
|
pQuerySet->dwNumberOfCsAddrs,
|
|
pQuerySet->lpcsaBuffer,
|
|
pQuerySet->dwOutputFlags,
|
|
pQuerySet->lpBlob
|
|
);
|
|
|
|
// print address-family\protocols array
|
|
|
|
if ( pQuerySet->lpafpProtocols )
|
|
{
|
|
DnsPrint_AfProtocolsArray(
|
|
PrintRoutine,
|
|
pContext,
|
|
"\tAFPROTOCOLS Array:",
|
|
pQuerySet->lpafpProtocols,
|
|
pQuerySet->dwNumberOfProtocols );
|
|
}
|
|
|
|
// print CSADDR_INFO array
|
|
|
|
if ( pQuerySet->dwNumberOfCsAddrs &&
|
|
pQuerySet->lpcsaBuffer )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"--- CS_ADDR array:\r\n" );
|
|
|
|
for ( i=0; i<pQuerySet->dwNumberOfCsAddrs; i++ )
|
|
{
|
|
DnsPrint_CsAddr(
|
|
PrintRoutine,
|
|
pContext,
|
|
NULL,
|
|
1, // indent one level
|
|
& pQuerySet->lpcsaBuffer[i] );
|
|
}
|
|
}
|
|
|
|
// print blob (the hostent)
|
|
|
|
//
|
|
// DCR_FIX0: need some sort of test for blob type?
|
|
// - most blobs are hostent, but some are servent
|
|
//
|
|
|
|
if ( pQuerySet->lpBlob )
|
|
{
|
|
GUID ianaGuid = SVCID_INET_SERVICEBYNAME;
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"--- BLOB:\n"
|
|
"\tcbSize = %d\r\n"
|
|
"\tpBlobData = %p\r\n",
|
|
pQuerySet->lpBlob->cbSize,
|
|
pQuerySet->lpBlob->pBlobData
|
|
);
|
|
|
|
// note: can't print blob as hostent
|
|
// 1) may not be hostent
|
|
// 2) is passed with offsets rather than pointers
|
|
|
|
DnsPrint_RawBinary(
|
|
PrintRoutine,
|
|
pContext,
|
|
NULL,
|
|
"\t\t",
|
|
pQuerySet->lpBlob->pBlobData,
|
|
pQuerySet->lpBlob->cbSize,
|
|
sizeof(DWORD)
|
|
);
|
|
}
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_WsaNsClassInfo(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PWSANSCLASSINFO pInfo,
|
|
IN BOOL fUnicode
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print WSACLASSINFO structure.
|
|
|
|
Arguments:
|
|
|
|
PrintRoutine - routine to print with
|
|
|
|
pszHeader - header
|
|
|
|
pInfo - ptr to WSACLASSINFO to print
|
|
|
|
fUnicode - TRUE if WSACLASSINFO is wide (WSACLASSINFOW)
|
|
FALSE if ANSI
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "WSANsClassInfo:";
|
|
}
|
|
|
|
if ( !pInfo )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s NULL NsClassInfo ptr\r\n",
|
|
pszHeader );
|
|
return;
|
|
}
|
|
|
|
// print the struct
|
|
|
|
DnsPrint_Lock();
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\r\n"
|
|
"\tPtr = %d\r\n"
|
|
"\tName = %S%s\r\n"
|
|
"\tName Space = %d\r\n"
|
|
"\tValue Type = %d\r\n"
|
|
"\tValue Size = %d\r\n"
|
|
"\tpValue = %p\r\n",
|
|
pszHeader,
|
|
pInfo,
|
|
DNSSTRING_WIDE( fUnicode, pInfo->lpszName ),
|
|
DNSSTRING_ANSI( fUnicode, pInfo->lpszName ),
|
|
pInfo->dwNameSpace,
|
|
pInfo->dwValueType,
|
|
pInfo->dwValueSize,
|
|
pInfo->lpValue
|
|
);
|
|
|
|
if ( pInfo->lpValue )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"--- Value:\r\n"
|
|
);
|
|
|
|
DnsPrint_RawBinary(
|
|
PrintRoutine,
|
|
pContext,
|
|
NULL,
|
|
"\t\t",
|
|
pInfo->lpValue,
|
|
pInfo->dwValueSize,
|
|
sizeof(BYTE) // print in bytes
|
|
);
|
|
}
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_WsaServiceClassInfo(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN LPWSASERVICECLASSINFO pInfo,
|
|
IN BOOL fUnicode
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print WSASERVICECLASSINFO structure.
|
|
|
|
Arguments:
|
|
|
|
PrintRoutine - routine to print with
|
|
|
|
pszHeader - header
|
|
|
|
pInfo - ptr to WSASERVICECLASSINFO to print
|
|
|
|
fUnicode - TRUE if WSASERVICECLASSINFO is wide (WSASERVICECLASSINFOW)
|
|
FALSE if ANSI
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
CHAR serviceClassGuidBuffer[ GUID_STRING_BUFFER_LENGTH ];
|
|
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "WSAServiceClassInfo:";
|
|
}
|
|
|
|
if ( !pInfo )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s NULL ServiceClassInfo ptr\r\n",
|
|
pszHeader );
|
|
return;
|
|
}
|
|
|
|
// convert GUID to strings
|
|
|
|
DnsStringPrint_Guid(
|
|
serviceClassGuidBuffer,
|
|
pInfo->lpServiceClassId
|
|
);
|
|
|
|
// print the struct
|
|
|
|
DnsPrint_Lock();
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\r\n"
|
|
"\tPtr = %p\r\n"
|
|
"\tClass GUID = (%p) %s\r\n"
|
|
"\tClassName = %S%s\r\n"
|
|
"\tClass Info Count = %d\r\n"
|
|
"\tClass Info Array = %p\r\n",
|
|
pszHeader,
|
|
pInfo,
|
|
serviceClassGuidBuffer,
|
|
DNSSTRING_WIDE( fUnicode, pInfo->lpszServiceClassName ),
|
|
DNSSTRING_ANSI( fUnicode, pInfo->lpszServiceClassName ),
|
|
pInfo->dwCount,
|
|
pInfo->lpClassInfos
|
|
);
|
|
|
|
if ( pInfo->lpClassInfos )
|
|
{
|
|
DWORD i;
|
|
|
|
for ( i=0; i<pInfo->dwCount; i++ )
|
|
{
|
|
DnsPrint_WsaNsClassInfo(
|
|
PrintRoutine,
|
|
pContext,
|
|
NULL, // default header
|
|
& pInfo->lpClassInfos[i],
|
|
fUnicode
|
|
);
|
|
}
|
|
}
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_Hostent(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PHOSTENT pHostent,
|
|
IN BOOL fUnicode
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print hostent structure.
|
|
|
|
Arguments:
|
|
|
|
PrintRoutine - routine to print with
|
|
|
|
pszHeader - header
|
|
|
|
pHostent - ptr to hostent
|
|
|
|
fUnicode - TRUE if hostent is unicode
|
|
FALSE if ANSI
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "Hostent:";
|
|
}
|
|
|
|
if ( !pHostent )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s %s\r\n",
|
|
pszHeader,
|
|
"NULL Hostent ptr." );
|
|
return;
|
|
}
|
|
|
|
// print the struct
|
|
|
|
DnsPrint_Lock();
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\r\n"
|
|
"\th_name = %p %S%s\n"
|
|
"\th_aliases = %p\n"
|
|
"\th_addrtype = %d\n"
|
|
"\th_length = %d\n"
|
|
"\th_addrlist = %p\n",
|
|
pszHeader,
|
|
pHostent->h_name,
|
|
DNSSTRING_WIDE( fUnicode, pHostent->h_name ),
|
|
DNSSTRING_ANSI( fUnicode, pHostent->h_name ),
|
|
pHostent->h_aliases,
|
|
pHostent->h_addrtype,
|
|
pHostent->h_length,
|
|
pHostent->h_addr_list
|
|
);
|
|
|
|
// print the aliases
|
|
|
|
if ( pHostent->h_aliases )
|
|
{
|
|
PSTR * paliasArray = pHostent->h_aliases;
|
|
PSTR palias;
|
|
|
|
while ( palias = *paliasArray++ )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"\tAlias = (%p) %S%s\n",
|
|
palias,
|
|
DNSSTRING_WIDE( fUnicode, palias ),
|
|
DNSSTRING_ANSI( fUnicode, palias ) );
|
|
}
|
|
}
|
|
|
|
// print the addresses
|
|
|
|
if ( pHostent->h_addr_list )
|
|
{
|
|
PCHAR * ppaddr = pHostent->h_addr_list;
|
|
PCHAR pip;
|
|
INT i = 0;
|
|
INT family = pHostent->h_addrtype;
|
|
INT addrLength = pHostent->h_length;
|
|
CHAR stringBuf[ IP6_ADDRESS_STRING_BUFFER_LENGTH ];
|
|
|
|
while ( pip = ppaddr[i] )
|
|
{
|
|
DWORD bufLength = IP6_ADDRESS_STRING_BUFFER_LENGTH;
|
|
|
|
Dns_AddressToString_A(
|
|
stringBuf,
|
|
& bufLength,
|
|
pip,
|
|
addrLength,
|
|
family );
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"\tAddr[%d] = %s \t(ptr=%p)\n",
|
|
i,
|
|
stringBuf,
|
|
pip );
|
|
i++;
|
|
}
|
|
}
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// IP help types (iptypes.h)
|
|
//
|
|
|
|
VOID
|
|
DnsPrint_IpAdapterAddress(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PVOID pAddr,
|
|
IN BOOL fUnicast,
|
|
IN BOOL fPrintList
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print IP_ADAPTER_XXX_ADDRESS structures
|
|
|
|
This prints:
|
|
PIP_ADAPTER_UNICAST_ADDRESS
|
|
PIP_ADAPTER_ANYCAST_ADDRESS
|
|
PIP_ADAPTER_MULTICAST_ADDRESS
|
|
PIP_ADAPTER_DNS_SERVER_ADDRESS
|
|
|
|
fUnicast --
|
|
TRUE for UNICAST,
|
|
FALSE for all other types which are identical.
|
|
|
|
fPrintList --
|
|
TRUE to print all addresses.
|
|
FALSE to print just this address.
|
|
|
|
--*/
|
|
{
|
|
PIP_ADAPTER_UNICAST_ADDRESS paddr = (PIP_ADAPTER_UNICAST_ADDRESS) pAddr;
|
|
DWORD count = 0;
|
|
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "IpAdapterAddress:";
|
|
}
|
|
|
|
if ( !paddr )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\tNULL IpAdapterAddress passed to print.\n",
|
|
pszHeader );
|
|
return;
|
|
}
|
|
|
|
DnsPrint_Lock();
|
|
|
|
if ( fPrintList )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s List:\n",
|
|
pszHeader );
|
|
}
|
|
|
|
while ( paddr )
|
|
{
|
|
if ( fPrintList )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s [%d]:\n",
|
|
pszHeader,
|
|
count );
|
|
}
|
|
else
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\n",
|
|
pszHeader );
|
|
}
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"\tPointer = %p\n"
|
|
"\tLength = %d\n"
|
|
"\tFlags = %08x\n"
|
|
"\tpNext = %p\n",
|
|
paddr,
|
|
paddr->Length,
|
|
paddr->Flags,
|
|
paddr->Next
|
|
);
|
|
|
|
DnsPrint_SocketAddress(
|
|
PrintRoutine,
|
|
pContext,
|
|
"\tSocketAddress:",
|
|
1, // indent
|
|
& paddr->Address
|
|
);
|
|
|
|
if ( fUnicast )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"\tPrefixOrigin = %d\n"
|
|
"\tSuffixOrigin = %d\n"
|
|
"\tDadState = %d\n"
|
|
"\tValidLifetime = %u\n"
|
|
"\tPrefLifetime = %u\n"
|
|
"\tLeaseLifetime = %u\n",
|
|
paddr->PrefixOrigin,
|
|
paddr->SuffixOrigin,
|
|
paddr->DadState,
|
|
paddr->ValidLifetime,
|
|
paddr->PreferredLifetime,
|
|
paddr->LeaseLifetime
|
|
);
|
|
}
|
|
|
|
// print next in list (if desired)
|
|
// - hard stop at 50 addresses
|
|
|
|
paddr = paddr->Next;
|
|
if ( !fPrintList || count > 50 )
|
|
{
|
|
break;
|
|
}
|
|
count++;
|
|
}
|
|
|
|
if ( fPrintList )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"End of %s List\n",
|
|
pszHeader );
|
|
}
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_IpAdapterList(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PIP_ADAPTER_ADDRESSES pAdapt,
|
|
IN BOOL fPrintAddrs,
|
|
IN BOOL fPrintList
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print IP_ADAPTER_ADDRESSES structure
|
|
|
|
Arguments:
|
|
|
|
fPrintAddressLists -- TRUE to print address list subfields.
|
|
|
|
fPrintList --
|
|
TRUE to print list of adapters,
|
|
FALSE to print just this adapter
|
|
|
|
--*/
|
|
{
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "IpAdapter:";
|
|
}
|
|
|
|
if ( !pAdapt )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\tNULL IpAdapter passed to print.\n",
|
|
pszHeader );
|
|
return;
|
|
}
|
|
|
|
DnsPrint_Lock();
|
|
|
|
if ( fPrintList )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s List:\n",
|
|
pszHeader );
|
|
}
|
|
|
|
while ( pAdapt )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\n"
|
|
"\tPointer = %p\n"
|
|
"\tLength = %d\n"
|
|
"\tIfIndex = %d\n"
|
|
"\tpNext = %p\n"
|
|
"\tAdapterName = %s\n"
|
|
"\tUnicastList = %p\n"
|
|
"\tAnycastList = %p\n"
|
|
"\tMulticastList = %p\n"
|
|
"\tDnsServerList = %p\n"
|
|
"\tDnsSuffix = %S\n"
|
|
"\tDescription = %S\n"
|
|
"\tFriendlyName = %S\n"
|
|
"\tPhysicalAddr Ptr = %p\n"
|
|
"\tPhysicalLength = %d\n"
|
|
"\tFlags = %d\n"
|
|
"\tMtu = %d\n"
|
|
"\tIfType = %d\n"
|
|
"\tOperStatus = %d\n"
|
|
"\tIfIndex6 = %d\n",
|
|
pszHeader,
|
|
pAdapt,
|
|
pAdapt->Length,
|
|
pAdapt->IfIndex,
|
|
pAdapt->Next,
|
|
pAdapt->AdapterName,
|
|
pAdapt->FirstUnicastAddress,
|
|
pAdapt->FirstAnycastAddress,
|
|
pAdapt->FirstMulticastAddress,
|
|
pAdapt->FirstDnsServerAddress,
|
|
pAdapt->DnsSuffix,
|
|
pAdapt->Description,
|
|
pAdapt->FriendlyName,
|
|
pAdapt->PhysicalAddress,
|
|
pAdapt->PhysicalAddressLength,
|
|
pAdapt->Flags,
|
|
pAdapt->Mtu,
|
|
pAdapt->IfType,
|
|
(INT) pAdapt->OperStatus,
|
|
pAdapt->Ipv6IfIndex );
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"\tZoneIndices = %d inf=%d lnk=%d sub=%d adm=%d site=%d %d %d\n"
|
|
"\t %d %d %d %d %d %d %d %d\n",
|
|
pAdapt->ZoneIndices[0],
|
|
pAdapt->ZoneIndices[1],
|
|
pAdapt->ZoneIndices[2],
|
|
pAdapt->ZoneIndices[3],
|
|
pAdapt->ZoneIndices[4],
|
|
pAdapt->ZoneIndices[5],
|
|
pAdapt->ZoneIndices[6],
|
|
pAdapt->ZoneIndices[7],
|
|
pAdapt->ZoneIndices[8],
|
|
pAdapt->ZoneIndices[9],
|
|
pAdapt->ZoneIndices[10],
|
|
pAdapt->ZoneIndices[11],
|
|
pAdapt->ZoneIndices[12],
|
|
pAdapt->ZoneIndices[13],
|
|
pAdapt->ZoneIndices[14],
|
|
pAdapt->ZoneIndices[15] );
|
|
|
|
DnsPrint_RawBinary(
|
|
PrintRoutine,
|
|
pContext,
|
|
NULL, // no header
|
|
"\tPhysical Address", // line header
|
|
pAdapt->PhysicalAddress,
|
|
pAdapt->PhysicalAddressLength,
|
|
0 // no alignment, write in bytes
|
|
);
|
|
|
|
if ( fPrintAddrs )
|
|
{
|
|
if ( pAdapt->FirstUnicastAddress )
|
|
{
|
|
DnsPrint_IpAdapterAddress(
|
|
PrintRoutine,
|
|
pContext,
|
|
"Adapter Unicast Addrs",
|
|
pAdapt->FirstUnicastAddress,
|
|
TRUE, // unicast
|
|
TRUE // print list
|
|
);
|
|
}
|
|
if ( pAdapt->FirstAnycastAddress )
|
|
{
|
|
DnsPrint_IpAdapterAddress(
|
|
PrintRoutine,
|
|
pContext,
|
|
"Adapter Anycast Addrs",
|
|
pAdapt->FirstAnycastAddress,
|
|
FALSE, // not unicast
|
|
TRUE // print list
|
|
);
|
|
}
|
|
if ( pAdapt->FirstMulticastAddress )
|
|
{
|
|
DnsPrint_IpAdapterAddress(
|
|
PrintRoutine,
|
|
pContext,
|
|
"Adapter Multicast Addrs",
|
|
pAdapt->FirstMulticastAddress,
|
|
FALSE, // not unicast
|
|
TRUE // print list
|
|
);
|
|
}
|
|
if ( pAdapt->FirstDnsServerAddress )
|
|
{
|
|
DnsPrint_IpAdapterAddress(
|
|
PrintRoutine,
|
|
pContext,
|
|
"Adapter DnsServer Addrs",
|
|
pAdapt->FirstDnsServerAddress,
|
|
FALSE, // not unicast
|
|
TRUE // print list
|
|
);
|
|
}
|
|
}
|
|
|
|
// get next
|
|
|
|
pAdapt = pAdapt->Next;
|
|
if ( !fPrintList )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"End of %s%s\n"
|
|
"\n",
|
|
pszHeader,
|
|
fPrintList ? " List" : "" );
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Query print routines
|
|
//
|
|
|
|
VOID
|
|
DnsPrint_QueryBlob(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PQUERY_BLOB pBlob
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print query blob.
|
|
|
|
Arguments:
|
|
|
|
PrintRoutine - routine to print with
|
|
|
|
pContext - print context
|
|
|
|
pszHeader - header
|
|
|
|
pBlob - query info
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
DWORD i;
|
|
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "Query Blob:";
|
|
}
|
|
|
|
if ( !pBlob )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s %s\n",
|
|
pszHeader,
|
|
"NULL Query Blob ptr." );
|
|
return;
|
|
}
|
|
|
|
// print the struct
|
|
|
|
DnsPrint_Lock();
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"\tname orig %S\n"
|
|
"\tname query %S\n"
|
|
"\ttype %d\n"
|
|
"\tflags %08x\n"
|
|
|
|
"\tname length %d\n"
|
|
"\tname attributes %08x\n"
|
|
"\tquery count %d\n"
|
|
"\tname flags %08x\n"
|
|
"\tfappendedName %d\n"
|
|
|
|
"\tstatus %d\n"
|
|
"\trcode %d\n"
|
|
"\tnetfail status %d\n"
|
|
"\tcache negative %d\n"
|
|
"\tno ip local %d\n"
|
|
"\trecords %p\n"
|
|
"\tlocal records %p\n"
|
|
|
|
"\tnetwork info %p\n"
|
|
"\tserver list %p\n"
|
|
"\tserver4 list %p\n"
|
|
"\tpmsg %p\n"
|
|
"\tevent %p\n",
|
|
|
|
pBlob->pNameOrig,
|
|
pBlob->pNameQuery,
|
|
pBlob->wType,
|
|
pBlob->Flags,
|
|
|
|
pBlob->NameLength,
|
|
pBlob->NameAttributes,
|
|
pBlob->QueryCount,
|
|
pBlob->NameFlags,
|
|
pBlob->fAppendedName,
|
|
|
|
pBlob->Status,
|
|
pBlob->Rcode,
|
|
pBlob->NetFailureStatus,
|
|
pBlob->fCacheNegative,
|
|
pBlob->fNoIpLocal,
|
|
pBlob->pRecords,
|
|
pBlob->pLocalRecords,
|
|
|
|
pBlob->pNetInfo,
|
|
pBlob->pServerList,
|
|
pBlob->pServerList4,
|
|
pBlob->pRecvMsg,
|
|
pBlob->hEvent
|
|
);
|
|
|
|
// DCR_FIX0: cleanup when results in use
|
|
|
|
DnsPrint_RecordSet(
|
|
PrintRoutine,
|
|
pContext,
|
|
"Records:\n",
|
|
pBlob->pRecords );
|
|
|
|
// DCR_FIX0: use results when ready
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_QueryResults(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PDNS_RESULTS pResults
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print query results.
|
|
|
|
Arguments:
|
|
|
|
PrintRoutine - routine to print with
|
|
|
|
pContext - print context
|
|
|
|
pszHeader - header
|
|
|
|
pResults - results info
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
DWORD i;
|
|
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "Results:";
|
|
}
|
|
|
|
if ( !pResults )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s %s\n",
|
|
pszHeader,
|
|
"NULL Results ptr." );
|
|
return;
|
|
}
|
|
|
|
// print the struct
|
|
|
|
DnsPrint_Lock();
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"\tstatus %d\n"
|
|
"\trcode %d\n"
|
|
"\tserver %s\n"
|
|
"\tpanswer %p\n"
|
|
"\tpalias %p\n"
|
|
"\tpauthority %p\n"
|
|
"\tpadditional %p\n"
|
|
"\tpsig %p\n"
|
|
"\tpmsg %p\n",
|
|
pResults->Status,
|
|
pResults->Rcode,
|
|
IP4_STRING( pResults->ServerAddr ),
|
|
pResults->pAnswerRecords,
|
|
pResults->pAliasRecords,
|
|
pResults->pAuthorityRecords,
|
|
pResults->pAdditionalRecords,
|
|
pResults->pSigRecords,
|
|
pResults->pMessage
|
|
);
|
|
|
|
DnsPrint_RecordSet(
|
|
PrintRoutine,
|
|
pContext,
|
|
"\tAnswer records:\n",
|
|
pResults->pAnswerRecords );
|
|
|
|
DnsPrint_RecordSet(
|
|
PrintRoutine,
|
|
pContext,
|
|
"\tAlias records:\n",
|
|
pResults->pAliasRecords );
|
|
|
|
DnsPrint_RecordSet(
|
|
PrintRoutine,
|
|
pContext,
|
|
"\tAuthority records:\n",
|
|
pResults->pAuthorityRecords );
|
|
|
|
DnsPrint_RecordSet(
|
|
PrintRoutine,
|
|
pContext,
|
|
"\tAdditional records:\n",
|
|
pResults->pAdditionalRecords );
|
|
|
|
DnsPrint_RecordSet(
|
|
PrintRoutine,
|
|
pContext,
|
|
"\tSignature records:\n",
|
|
pResults->pSigRecords );
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_ParsedMessage(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PDNS_PARSED_MESSAGE pParsed
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print parsed message.
|
|
|
|
Arguments:
|
|
|
|
PrintRoutine - routine to print with
|
|
|
|
pContext - print context
|
|
|
|
pszHeader - header
|
|
|
|
pResults - query info
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
DWORD i;
|
|
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "Parsed Message:";
|
|
}
|
|
|
|
if ( !pParsed )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s %s\n",
|
|
pszHeader,
|
|
"NULL Parsed Message ptr." );
|
|
return;
|
|
}
|
|
|
|
// print the struct
|
|
|
|
DnsPrint_Lock();
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"\tstatus %d (%08x)\n"
|
|
"\tchar set %d\n",
|
|
pParsed->Status, pParsed->Status,
|
|
pParsed->CharSet
|
|
);
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"\tquestion:\n"
|
|
"\t\tname %S%s\n"
|
|
"\t\ttype %d\n"
|
|
"\t\tclass %d\n",
|
|
PRINT_STRING_WIDE_CHARSET( pParsed->pQuestionName, pParsed->CharSet ),
|
|
PRINT_STRING_ANSI_CHARSET( pParsed->pQuestionName, pParsed->CharSet ),
|
|
pParsed->QuestionType,
|
|
pParsed->QuestionClass
|
|
);
|
|
|
|
DnsPrint_RecordSet(
|
|
PrintRoutine,
|
|
pContext,
|
|
"Answer records:\n",
|
|
pParsed->pAnswerRecords );
|
|
|
|
DnsPrint_RecordSet(
|
|
PrintRoutine,
|
|
pContext,
|
|
"Alias records:\n",
|
|
pParsed->pAliasRecords );
|
|
|
|
DnsPrint_RecordSet(
|
|
PrintRoutine,
|
|
pContext,
|
|
"Authority records:\n",
|
|
pParsed->pAuthorityRecords );
|
|
|
|
DnsPrint_RecordSet(
|
|
PrintRoutine,
|
|
pContext,
|
|
"Additional records:\n",
|
|
pParsed->pAdditionalRecords );
|
|
|
|
DnsPrint_RecordSet(
|
|
PrintRoutine,
|
|
pContext,
|
|
"Signature records:\n",
|
|
pParsed->pSigRecords );
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_QueryInfo(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PDNS_QUERY_INFO pQueryInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print query info
|
|
|
|
Arguments:
|
|
|
|
PrintRoutine - routine to print with
|
|
|
|
pContext - print context
|
|
|
|
pszHeader - header
|
|
|
|
pQueryInfo - query info
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
DWORD i;
|
|
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "Query Info:";
|
|
}
|
|
|
|
if ( !pQueryInfo )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s %s\n",
|
|
pszHeader,
|
|
"NULL Query Info ptr." );
|
|
return;
|
|
}
|
|
|
|
// print the struct
|
|
|
|
DnsPrint_Lock();
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\n"
|
|
"\tpointer %p\n"
|
|
"\tstatus %d (%08x)\n"
|
|
"\tchar set %d\n"
|
|
"\tname %S%s\n"
|
|
"\tname resv. %s\n"
|
|
"\ttype %d\n"
|
|
"\trcode %d\n"
|
|
"\tflags %08x\n"
|
|
|
|
"\tpanswer %p\n"
|
|
"\tpalias %p\n"
|
|
"\tpauthority %p\n"
|
|
"\tpadditional %p\n"
|
|
//"\tpsig %p\n"
|
|
|
|
"\tevent %p\n"
|
|
"\tserver list %p\n"
|
|
"\tserver4 list %p\n"
|
|
"\tpmsg %p\n",
|
|
|
|
pszHeader,
|
|
pQueryInfo,
|
|
pQueryInfo->Status, pQueryInfo->Status,
|
|
pQueryInfo->CharSet,
|
|
PRINT_STRING_WIDE_CHARSET( pQueryInfo->pName, pQueryInfo->CharSet ),
|
|
PRINT_STRING_ANSI_CHARSET( pQueryInfo->pName, pQueryInfo->CharSet ),
|
|
pQueryInfo->pReservedName,
|
|
pQueryInfo->Type,
|
|
pQueryInfo->Rcode,
|
|
pQueryInfo->Flags,
|
|
|
|
pQueryInfo->pAnswerRecords,
|
|
pQueryInfo->pAliasRecords,
|
|
pQueryInfo->pAuthorityRecords,
|
|
pQueryInfo->pAdditionalRecords,
|
|
//pQueryInfo->pSigRecords,
|
|
|
|
pQueryInfo->hEvent,
|
|
pQueryInfo->pServerList,
|
|
pQueryInfo->pServerListIp4,
|
|
pQueryInfo->pMessage
|
|
);
|
|
|
|
DnsPrint_RecordSet(
|
|
PrintRoutine,
|
|
pContext,
|
|
"Answer records:\n",
|
|
pQueryInfo->pAnswerRecords );
|
|
|
|
DnsPrint_RecordSet(
|
|
PrintRoutine,
|
|
pContext,
|
|
"Alias records:\n",
|
|
pQueryInfo->pAliasRecords );
|
|
|
|
DnsPrint_RecordSet(
|
|
PrintRoutine,
|
|
pContext,
|
|
"Authority records:\n",
|
|
pQueryInfo->pAuthorityRecords );
|
|
|
|
DnsPrint_RecordSet(
|
|
PrintRoutine,
|
|
pContext,
|
|
"Additional records:\n",
|
|
pQueryInfo->pAdditionalRecords );
|
|
|
|
//DnsPrint_RecordSet(
|
|
// "Signature records:\n",
|
|
// pQueryInfo->pSigRecords );
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_EnvarInfo(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PENVAR_DWORD_INFO pEnvar
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print envar data
|
|
|
|
Arguments:
|
|
|
|
PrintRoutine - routine to print with
|
|
|
|
pContext - print context
|
|
|
|
pszHeader -- header to print with
|
|
|
|
pEnvar -- ptr to envar info
|
|
|
|
Return Value:
|
|
|
|
ERROR_SUCCESS if successful.
|
|
ErrorCode on failure.
|
|
|
|
--*/
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\n"
|
|
"\tId = %d\n"
|
|
"\tValue = %p\n"
|
|
"\tfFound = %d\n",
|
|
pszHeader ? pszHeader : "Envar Info:",
|
|
pEnvar->Id,
|
|
pEnvar->Value,
|
|
pEnvar->fFound
|
|
);
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Network info print routines.
|
|
//
|
|
|
|
VOID
|
|
DnsPrint_NetworkInfo(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pPrintContext,
|
|
IN LPSTR pszHeader,
|
|
IN PDNS_NETINFO pNetworkInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Prints and validates network info structure.
|
|
Should also touch all the memory and AV when bogus.
|
|
|
|
Arguments:
|
|
|
|
pNetworkInfo -- network info to print
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
DWORD i;
|
|
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "NetworkInfo:";
|
|
}
|
|
if ( !pNetworkInfo )
|
|
{
|
|
PrintRoutine(
|
|
pPrintContext,
|
|
"%s NULL NetworkInfo.\n",
|
|
pszHeader );
|
|
return;
|
|
}
|
|
|
|
DnsPrint_Lock();
|
|
|
|
PrintRoutine(
|
|
pPrintContext,
|
|
"%s\n"
|
|
"\tpointer = %p\n"
|
|
"\tpszHostName = %S\n"
|
|
"\tpszDomainName = %S\n"
|
|
"\tpSearchList = %p\n"
|
|
"\tTimeStamp = %d\n"
|
|
"\tTag = %d\n"
|
|
"\tInfoFlags = %08x\n"
|
|
"\tReturnFlags = %08x\n"
|
|
"\tAdapterIndex = %d\n"
|
|
"\tAdapterCount = %d\n"
|
|
"\tAdapterArraySize = %d\n",
|
|
pszHeader,
|
|
pNetworkInfo,
|
|
pNetworkInfo->pszHostName,
|
|
pNetworkInfo->pszDomainName,
|
|
pNetworkInfo->pSearchList,
|
|
pNetworkInfo->TimeStamp,
|
|
pNetworkInfo->Tag,
|
|
pNetworkInfo->InfoFlags,
|
|
pNetworkInfo->ReturnFlags,
|
|
pNetworkInfo->AdapterIndex,
|
|
pNetworkInfo->AdapterCount,
|
|
pNetworkInfo->MaxAdapterCount );
|
|
|
|
// print search list
|
|
|
|
DnsPrint_SearchList(
|
|
PrintRoutine,
|
|
pPrintContext,
|
|
"Search List: ",
|
|
pNetworkInfo->pSearchList );
|
|
|
|
// print server lists
|
|
|
|
for ( i=0; i < pNetworkInfo->AdapterCount; i++ )
|
|
{
|
|
CHAR header[60];
|
|
|
|
sprintf( header, "AdapterInfo[%d]:", i );
|
|
|
|
DnsPrint_AdapterInfo(
|
|
PrintRoutine,
|
|
pPrintContext,
|
|
header,
|
|
NetInfo_GetAdapterByIndex( pNetworkInfo, i ) );
|
|
}
|
|
PrintRoutine(
|
|
pPrintContext,
|
|
"\n" );
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_AdapterInfo(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pPrintContext,
|
|
IN LPSTR pszHeader,
|
|
IN PDNS_ADAPTER pAdapter
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Prints and validates DNS adapter info.
|
|
Should also touch all the memory and AV when bogus.
|
|
|
|
Arguments:
|
|
|
|
pAdapter -- DNS adapter to print
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
DWORD i;
|
|
PDNS_ADDR_ARRAY pserverArray;
|
|
CHAR buffer[ DNS_ADDR_STRING_BUFFER_LENGTH ];
|
|
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "Adapter Info:";
|
|
}
|
|
if ( !pAdapter )
|
|
{
|
|
PrintRoutine(
|
|
pPrintContext,
|
|
"%s NULL Adapter info.\n",
|
|
pszHeader );
|
|
return;
|
|
}
|
|
|
|
DnsPrint_Lock();
|
|
|
|
PrintRoutine(
|
|
pPrintContext,
|
|
"%s\n"
|
|
"\tpointer = %p\n"
|
|
"\tGuid Name = %S\n"
|
|
"\tDomain = %S\n"
|
|
"\tLocalAddrs = %p\n"
|
|
"\tDnsAddrs = %p\n"
|
|
"\tInterfaceIndex = %d\n"
|
|
"\tInterfaceIndex6 = %d\n"
|
|
"\tInfoFlags = %08x\n"
|
|
"\tStatus = %d\n"
|
|
"\tRunFlags = %08x\n"
|
|
"\tSite = %d\n",
|
|
pszHeader,
|
|
pAdapter,
|
|
pAdapter->pszAdapterGuidName,
|
|
pAdapter->pszAdapterDomain,
|
|
pAdapter->pLocalAddrs,
|
|
pAdapter->pDnsAddrs,
|
|
pAdapter->InterfaceIndex,
|
|
pAdapter->InterfaceIndex6,
|
|
pAdapter->InfoFlags,
|
|
pAdapter->Status,
|
|
pAdapter->RunFlags,
|
|
pAdapter->Site );
|
|
|
|
// DNS server info
|
|
|
|
pserverArray = pAdapter->pDnsAddrs;
|
|
if ( pserverArray )
|
|
{
|
|
for ( i=0; i < pserverArray->AddrCount; i++ )
|
|
{
|
|
PDNS_ADDR pserver = &pserverArray->AddrArray[i];
|
|
|
|
DnsAddr_WriteStructString_A(
|
|
buffer,
|
|
pserver );
|
|
|
|
PrintRoutine(
|
|
pPrintContext,
|
|
"\tDNS Server [%d]:\n"
|
|
"\t\tAddress = %s\n"
|
|
"\t\tPriority = %d\n"
|
|
"\t\tFlags = %08x\n"
|
|
"\t\tStatus = %u\n",
|
|
i,
|
|
buffer,
|
|
pserver->Priority,
|
|
pserver->Flags,
|
|
pserver->Status
|
|
);
|
|
}
|
|
}
|
|
|
|
// IP address info
|
|
|
|
if ( pAdapter->pLocalAddrs )
|
|
{
|
|
DnsPrint_DnsAddrArray(
|
|
PrintRoutine,
|
|
pPrintContext,
|
|
"\tLocal Addrs",
|
|
"\tAddr",
|
|
pAdapter->pLocalAddrs );
|
|
}
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_SearchList(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pPrintContext,
|
|
IN LPSTR pszHeader,
|
|
IN PSEARCH_LIST pSearchList
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Prints and validates DNS search list.
|
|
Should also touch all the memory and AV when bogus.
|
|
|
|
Arguments:
|
|
|
|
pSearchList -- search list to print
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
DWORD i;
|
|
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "DNS Search List:";
|
|
}
|
|
|
|
if ( ! pSearchList )
|
|
{
|
|
PrintRoutine(
|
|
pPrintContext,
|
|
"%s NULL search list.\n",
|
|
pszHeader );
|
|
return;
|
|
}
|
|
|
|
DnsPrint_Lock();
|
|
|
|
PrintRoutine(
|
|
pPrintContext,
|
|
"%s\n"
|
|
"\tpointer = %p\n"
|
|
"\tNameCount = %d\n"
|
|
"\tMaxNameCount = %d\n"
|
|
"\tCurrentIndex = %d\n"
|
|
"\tSearchListNames:\n",
|
|
pszHeader,
|
|
pSearchList,
|
|
pSearchList->NameCount,
|
|
pSearchList->MaxNameCount,
|
|
pSearchList->CurrentNameIndex
|
|
);
|
|
|
|
for ( i=0; i < pSearchList->NameCount; i++ )
|
|
{
|
|
PrintRoutine(
|
|
pPrintContext,
|
|
"\t\t%S (Flags: %08x)\n",
|
|
pSearchList->SearchNameArray[i].pszName,
|
|
pSearchList->SearchNameArray[i].Flags );
|
|
}
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_HostentBlob(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PHOSTENT_BLOB pBlob
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print hostent structure.
|
|
|
|
Arguments:
|
|
|
|
PrintRoutine - routine to print with
|
|
|
|
pszHeader - header
|
|
|
|
pBlob - ptr to hostent blob
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
DWORD i;
|
|
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "Hostent Blob:";
|
|
}
|
|
|
|
if ( !pBlob )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s %s\n",
|
|
pszHeader,
|
|
"NULL Hostent blob ptr." );
|
|
return;
|
|
}
|
|
|
|
// print the struct
|
|
|
|
DnsPrint_Lock();
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\n"
|
|
"\tPtr = %p\n"
|
|
"\tpHostent = %p\n"
|
|
"\tfAllocatedBlob = %d\n"
|
|
"\tfAllocatedBuf = %d\n"
|
|
"\tpBuffer = %p\n"
|
|
"\tBufferLength = %d\n"
|
|
"\tAvailLength = %d\n"
|
|
"\tpAvailBuffer = %p\n"
|
|
"\tpCurrent = %p\n"
|
|
"\tBytesLeft = %d\n"
|
|
"\tMaxAliasCount = %d\n"
|
|
"\tAliasCount = %d\n"
|
|
"\tMaxAddrCount = %d\n"
|
|
"\tAddrCount = %d\n"
|
|
"\tfWroteName = %d\n"
|
|
"\tfUnicode = %d\n"
|
|
"\tCharSet = %d\n",
|
|
pszHeader,
|
|
pBlob,
|
|
pBlob->pHostent,
|
|
pBlob->fAllocatedBlob,
|
|
pBlob->fAllocatedBuf,
|
|
pBlob->pBuffer,
|
|
pBlob->BufferLength,
|
|
pBlob->AvailLength,
|
|
pBlob->pAvailBuffer,
|
|
pBlob->pCurrent,
|
|
pBlob->BytesLeft,
|
|
pBlob->MaxAliasCount,
|
|
pBlob->AliasCount,
|
|
pBlob->MaxAddrCount,
|
|
pBlob->AddrCount,
|
|
pBlob->fWroteName,
|
|
pBlob->fUnicode,
|
|
pBlob->CharSet
|
|
);
|
|
|
|
// print the hostent
|
|
|
|
if ( pBlob->pHostent )
|
|
{
|
|
DnsPrint_Hostent(
|
|
PrintRoutine,
|
|
pContext,
|
|
NULL,
|
|
pBlob->pHostent,
|
|
pBlob->fUnicode
|
|
);
|
|
}
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_SaBlob(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PSABLOB pBlob
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print sockaddr blob structure.
|
|
|
|
Arguments:
|
|
|
|
PrintRoutine - routine to print with
|
|
|
|
pszHeader - header
|
|
|
|
pBlob - ptr to hostent blob
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
DWORD i;
|
|
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "SockaddrBlob:";
|
|
}
|
|
|
|
if ( !pBlob )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s %s\n",
|
|
pszHeader,
|
|
"NULL SockaddrBlob ptr." );
|
|
return;
|
|
}
|
|
|
|
// print the struct
|
|
|
|
DnsPrint_Lock();
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\n"
|
|
"\tPtr = %p\n"
|
|
"\tpName = %S\n"
|
|
"\tpHostent = %p\n"
|
|
"\tAliasCount = %d\n",
|
|
pszHeader,
|
|
pBlob,
|
|
pBlob->pName,
|
|
pBlob->pHostent,
|
|
pBlob->AliasCount
|
|
);
|
|
|
|
// print the aliases
|
|
|
|
for ( i=0; i<pBlob->AliasCount; i++ )
|
|
{
|
|
PWSTR palias = pBlob->AliasArray[i];
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"\tAlias = (%p) %S\n",
|
|
palias,
|
|
palias );
|
|
}
|
|
|
|
// print the addresses
|
|
|
|
DnsPrint_DnsAddrArray(
|
|
PrintRoutine,
|
|
pContext,
|
|
"\tSockaddrs:",
|
|
"\t\tAddr",
|
|
pBlob->pAddrArray );
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
// Update info print routines
|
|
//
|
|
|
|
VOID
|
|
DnsPrint_UpdateBlob(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PUPDATE_BLOB pBlob
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print update blob.
|
|
|
|
Arguments:
|
|
|
|
PrintRoutine - routine to print with
|
|
|
|
pContext - print context
|
|
|
|
pszHeader - header
|
|
|
|
pBlob - update info
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
DWORD i;
|
|
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "Update Blob:";
|
|
}
|
|
|
|
if ( !pBlob )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s %s\n",
|
|
pszHeader,
|
|
"NULL Update Blob ptr." );
|
|
return;
|
|
}
|
|
|
|
// print the struct
|
|
|
|
DnsPrint_Lock();
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\n"
|
|
"\tBlob ptr %p\n"
|
|
"\tpRecords %p\n"
|
|
"\tFlags %08x\n"
|
|
"\ttest mode %d\n"
|
|
"\tsave msg %d\n"
|
|
"\thCreds %p\n"
|
|
"\tpExtraInfo %p\n"
|
|
"\tpNetInfo %p\n"
|
|
"\tpszZone %s\n"
|
|
"\tpszServerName %s\n"
|
|
"\tserver list %p\n"
|
|
"\tserver4 list %p\n"
|
|
"\tpRecvMsg %p\n",
|
|
|
|
pszHeader,
|
|
pBlob,
|
|
pBlob->pRecords,
|
|
pBlob->Flags,
|
|
pBlob->fUpdateTestMode,
|
|
pBlob->fSaveRecvMsg,
|
|
pBlob->hCreds,
|
|
pBlob->pExtraInfo,
|
|
pBlob->pNetInfo,
|
|
pBlob->pszZone,
|
|
pBlob->pszServerName,
|
|
pBlob->pServerList,
|
|
pBlob->pServ4List,
|
|
pBlob->pMsgRecv
|
|
);
|
|
|
|
DnsPrint_RecordSet(
|
|
PrintRoutine,
|
|
pContext,
|
|
"\tUpdate Records:\n",
|
|
pBlob->pRecords );
|
|
|
|
if ( pBlob->pServerList )
|
|
{
|
|
DnsPrint_DnsAddrArray(
|
|
PrintRoutine,
|
|
pContext,
|
|
"Server List",
|
|
NULL,
|
|
pBlob->pServerList );
|
|
}
|
|
if ( pBlob->pServ4List )
|
|
{
|
|
DnsPrint_Ip4Array(
|
|
PrintRoutine,
|
|
pContext,
|
|
"Server4 List",
|
|
NULL,
|
|
pBlob->pServ4List );
|
|
}
|
|
|
|
if ( !DnsAddr_IsEmpty( &pBlob->FailedServer ) )
|
|
{
|
|
DnsPrint_DnsAddrLine(
|
|
PrintRoutine,
|
|
pContext,
|
|
"Failed Server Addr",
|
|
& pBlob->FailedServer,
|
|
NULL );
|
|
}
|
|
|
|
#if 1
|
|
if ( pBlob->pExtraInfo )
|
|
{
|
|
DnsPrint_ExtraInfo(
|
|
PrintRoutine,
|
|
pContext,
|
|
NULL,
|
|
pBlob->pExtraInfo );
|
|
}
|
|
#endif
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_ExtraInfo(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PDNS_EXTRA_INFO pInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print update extra info.
|
|
|
|
Arguments:
|
|
|
|
PrintRoutine - routine to print with
|
|
|
|
pContext - print context
|
|
|
|
pszHeader - header
|
|
|
|
pInfo - extra info
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "Update Extra Info:";
|
|
}
|
|
|
|
if ( !pInfo )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s %s\n",
|
|
pszHeader,
|
|
"NULL Update Extra Info ptr." );
|
|
return;
|
|
}
|
|
|
|
// print the struct(s)
|
|
|
|
DnsPrint_Lock();
|
|
|
|
while ( pInfo )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\n"
|
|
"\tinfo ptr %p\n"
|
|
"\tnext ptr %p\n"
|
|
"\tid %d\n",
|
|
pszHeader,
|
|
pInfo,
|
|
pInfo->pNext,
|
|
pInfo->Id
|
|
);
|
|
|
|
switch ( pInfo->Id )
|
|
{
|
|
case DNS_EXINFO_ID_RESULTS_V1:
|
|
|
|
// print the struct
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"\tstatus %d\n"
|
|
"\trcode %d\n"
|
|
"\tserver IP %08x %s\n",
|
|
pInfo->ResultsV1.Status,
|
|
pInfo->ResultsV1.Rcode,
|
|
pInfo->ResultsV1.ServerIp4,
|
|
IP4_STRING( pInfo->ResultsV1.ServerIp4 )
|
|
);
|
|
break;
|
|
|
|
case DNS_EXINFO_ID_RESULTS_BASIC:
|
|
|
|
DnsPrint_ResultsBasic(
|
|
PrintRoutine,
|
|
pContext,
|
|
NULL,
|
|
(PBASIC_RESULTS) & pInfo->ResultsBasic
|
|
);
|
|
break;
|
|
|
|
case DNS_EXINFO_ID_SERVER_LIST:
|
|
|
|
DnsPrint_DnsAddrArray(
|
|
PrintRoutine,
|
|
pContext,
|
|
"ServerList:",
|
|
NULL,
|
|
pInfo->pServerList
|
|
);
|
|
break;
|
|
|
|
case DNS_EXINFO_ID_SERVER_LIST_IP4:
|
|
|
|
DnsPrint_Ip4Array(
|
|
PrintRoutine,
|
|
pContext,
|
|
"ServerList IP4:",
|
|
NULL,
|
|
pInfo->pServerList4
|
|
);
|
|
break;
|
|
|
|
default:
|
|
|
|
// verify this is results blob
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"\tUnknown update info ID = %d\n",
|
|
pInfo->Id );
|
|
break;
|
|
}
|
|
|
|
pInfo = pInfo->pNext;
|
|
}
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
#if 0
|
|
VOID
|
|
DnsPrint_UpdateResults(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PDNS_UPDATE_RESULT_INFO pResults
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print update results.
|
|
|
|
Arguments:
|
|
|
|
PrintRoutine - routine to print with
|
|
|
|
pContext - print context
|
|
|
|
pszHeader - header
|
|
|
|
pResults - results info
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "Update Results:";
|
|
}
|
|
|
|
if ( !pResults )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s %s\n",
|
|
pszHeader,
|
|
"NULL Update Results ptr." );
|
|
return;
|
|
}
|
|
|
|
// verify this is results blob
|
|
|
|
if ( pResults->Id != DNS_UPDATE_INFO_ID_RESULT_INFO )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s ptr=%p is NOT valid update results id=%d\n",
|
|
pszHeader,
|
|
pResults,
|
|
pResults->Id );
|
|
return;
|
|
}
|
|
|
|
// print the struct
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\n"
|
|
"\tresults ptr %p\n"
|
|
"\tstatus %d\n"
|
|
"\trcode %d\n"
|
|
"\tserver IP %08x %s\n",
|
|
pszHeader,
|
|
pResults,
|
|
pResults->Status,
|
|
pResults->Rcode,
|
|
pResults->ServerIp,
|
|
IP4_STRING( pResults->ServerIp ),
|
|
);
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_ResultsBasic(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PBASIC_RESULTS pResults
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print query results.
|
|
|
|
Arguments:
|
|
|
|
PrintRoutine - routine to print with
|
|
|
|
pContext - print context
|
|
|
|
pszHeader - header
|
|
|
|
pResults - results info
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
DWORD i;
|
|
CHAR addrString[DNS_ADDR_STRING_BUFFER_LENGTH];
|
|
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "Results:";
|
|
}
|
|
|
|
if ( !pResults )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s %s\n",
|
|
pszHeader,
|
|
"NULL Results ptr." );
|
|
return;
|
|
}
|
|
|
|
// print the struct
|
|
|
|
DnsAddr_WriteStructString_A(
|
|
addrString,
|
|
& pResults->ServerAddr );
|
|
|
|
DnsPrint_Lock();
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"\tStatus %d\n"
|
|
"\tRcode %d\n"
|
|
"\tServer %s\n",
|
|
pResults->Status,
|
|
pResults->Rcode,
|
|
addrString
|
|
);
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
DnsPrint_ResultBlob(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PRESULT_BLOB pResults
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print query results.
|
|
|
|
Arguments:
|
|
|
|
PrintRoutine - routine to print with
|
|
|
|
pContext - print context
|
|
|
|
pszHeader - header
|
|
|
|
pResults - results info
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
DWORD i;
|
|
CHAR addrString[DNS_ADDR_STRING_BUFFER_LENGTH];
|
|
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "Results:";
|
|
}
|
|
|
|
if ( !pResults )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s %s\n",
|
|
pszHeader,
|
|
"NULL Results ptr." );
|
|
return;
|
|
}
|
|
|
|
// print the struct
|
|
|
|
DnsAddr_WriteStructString_A(
|
|
addrString,
|
|
& pResults->ServerAddr );
|
|
|
|
DnsPrint_Lock();
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"\tStatus %d\n"
|
|
"\tRcode %d\n"
|
|
"\tfHaveResponse %d\n"
|
|
"\tServer %s\n"
|
|
"\tpRecords %p\n"
|
|
"\tpMessage %p\n",
|
|
pResults->Status,
|
|
pResults->Rcode,
|
|
pResults->fHaveResponse,
|
|
addrString,
|
|
pResults->pRecords,
|
|
pResults->pMessage
|
|
);
|
|
|
|
if ( pResults->pRecords )
|
|
{
|
|
DnsPrint_RecordSet(
|
|
PrintRoutine,
|
|
pContext,
|
|
"\tRecords:\n",
|
|
pResults->pRecords );
|
|
}
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
|
|
VOID
|
|
DnsPrint_SendBlob(
|
|
IN PRINT_ROUTINE PrintRoutine,
|
|
IN OUT PPRINT_CONTEXT pContext,
|
|
IN PSTR pszHeader,
|
|
IN PSEND_BLOB pBlob
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Print update blob.
|
|
|
|
Arguments:
|
|
|
|
PrintRoutine - routine to print with
|
|
|
|
pContext - print context
|
|
|
|
pszHeader - header
|
|
|
|
pBlob - send blob
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
DWORD i;
|
|
|
|
if ( !pszHeader )
|
|
{
|
|
pszHeader = "Send Blob:";
|
|
}
|
|
|
|
if ( !pBlob )
|
|
{
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s %s\n",
|
|
pszHeader,
|
|
"NULL Send Blob ptr." );
|
|
return;
|
|
}
|
|
|
|
// print the struct
|
|
|
|
DnsPrint_Lock();
|
|
|
|
PrintRoutine(
|
|
pContext,
|
|
"%s\n"
|
|
"\tBlob ptr %p\n"
|
|
"\tpNetInfo %p\n"
|
|
"\tpServerArray %p\n"
|
|
"\tpServ4Array %p\n"
|
|
"\tpSendMsg %p\n"
|
|
"\tFlags %08x\n"
|
|
"\tfSaveRecvMsg %d\n"
|
|
"\tfSaveRecords %d\n",
|
|
pszHeader,
|
|
pBlob,
|
|
pBlob->pNetInfo,
|
|
pBlob->pServerList,
|
|
pBlob->pServ4List,
|
|
pBlob->pSendMsg,
|
|
pBlob->Flags,
|
|
pBlob->fSaveResponse,
|
|
pBlob->fSaveRecords
|
|
);
|
|
|
|
if ( pBlob->pServerList )
|
|
{
|
|
DnsPrint_DnsAddrArray(
|
|
PrintRoutine,
|
|
pContext,
|
|
"Server List",
|
|
NULL,
|
|
pBlob->pServerList );
|
|
}
|
|
if ( pBlob->pServ4List )
|
|
{
|
|
DnsPrint_Ip4Array(
|
|
PrintRoutine,
|
|
pContext,
|
|
"Server IP4 List",
|
|
NULL,
|
|
pBlob->pServ4List );
|
|
}
|
|
|
|
DnsPrint_ResultBlob(
|
|
PrintRoutine,
|
|
pContext,
|
|
"\tSend Results:\n",
|
|
&pBlob->Results );
|
|
|
|
DnsPrint_Unlock();
|
|
}
|
|
|
|
//
|
|
// End of print.c
|
|
//
|
|
|
|
|