|
|
/*++
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
//
|