Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

975 lines
19 KiB

/*++
Copyright (c) 1997-2000 Microsoft Corporation
Module Name:
rrprint.c
Abstract:
Domain Name System (DNS) Library
Print resource record routines.
Author:
Jim Gilroy (jamesg) February, 1997
Revision History:
--*/
#include "local.h"
//
// Private prototypes
//
VOID
printBadDataLength(
IN PRINT_ROUTINE PrintRoutine,
IN OUT PPRINT_CONTEXT pContext,
IN PDNS_RECORD pRecord
);
VOID
ARecordPrint(
IN PRINT_ROUTINE PrintRoutine,
IN OUT PPRINT_CONTEXT pContext,
IN PDNS_RECORD pRecord
)
/*++
Routine Description:
Print A records.
Arguments:
PrintRoutine -- routine to print with
pRecord -- record to print
Return Value:
TRUE if record data equal
FALSE otherwise
--*/
{
WORD dataLength = pRecord->wDataLength;
if ( dataLength == sizeof(IP_ADDRESS) )
{
PrintRoutine(
pContext,
"\tIP address = %s\n",
IP_STRING(pRecord->Data.A.IpAddress) );
}
else if ( dataLength % sizeof(DNS_A_DATA) )
{
printBadDataLength( PrintRoutine, pContext, pRecord );
}
else // multiple records
{
PIP_ADDRESS pip = &pRecord->Data.A.IpAddress;
DnsPrint_Lock();
while ( dataLength )
{
PrintRoutine(
pContext,
"\tIP address = %s\n",
IP_STRING(*pip) );
dataLength -= sizeof(IP_ADDRESS);
pip++;
}
DnsPrint_Unlock();
}
}
VOID
PtrRecordPrint(
IN PRINT_ROUTINE PrintRoutine,
IN OUT PPRINT_CONTEXT pContext,
IN PDNS_RECORD pRecord
)
/*++
Routine Description:
Print PTR compatible record.
Includes: NS, PTR, CNAME, MB, MR, MG, MD, MF
Arguments:
PrintRoutine -- routine to print with
pRecord -- record to print
Return Value:
TRUE if record data equal
FALSE otherwise
--*/
{
PrintRoutine(
pContext,
"\tHostName = %s%S\n",
RECSTRING_UTF8( pRecord, pRecord->Data.PTR.pNameHost ),
RECSTRING_WIDE( pRecord, pRecord->Data.PTR.pNameHost )
);
}
VOID
MxRecordPrint(
IN PRINT_ROUTINE PrintRoutine,
IN OUT PPRINT_CONTEXT pContext,
IN PDNS_RECORD pRecord
)
/*++
Routine Description:
Print MX compatible record.
Includes: MX, RT, AFSDB
Arguments:
PrintRoutine -- routine to print with
pRecord -- record to print
Return Value:
TRUE if record data equal
FALSE otherwise
--*/
{
PrintRoutine(
pContext,
"\tPreference = %d\n"
"\tExchange = %s%S\n",
pRecord->Data.MX.wPreference,
RECSTRING_UTF8( pRecord, pRecord->Data.MX.pNameExchange ),
RECSTRING_WIDE( pRecord, pRecord->Data.MX.pNameExchange )
);
}
VOID
SoaRecordPrint(
IN PRINT_ROUTINE PrintRoutine,
IN OUT PPRINT_CONTEXT pContext,
IN PDNS_RECORD pRecord
)
/*++
Routine Description:
Print SOA record.
Arguments:
PrintRoutine -- routine to print with
pRecord -- record to print
Return Value:
TRUE if record data equal
FALSE otherwise
--*/
{
PrintRoutine(
pContext,
"\tPrimary = %s%S\n"
"\tAdmin = %s%S\n"
"\tSerial = %d\n"
"\tRefresh = %d\n"
"\tRetry = %d\n"
"\tExpire = %d\n"
"\tDefault TTL = %d\n",
RECSTRING_UTF8( pRecord, pRecord->Data.SOA.pNamePrimaryServer ),
RECSTRING_WIDE( pRecord, pRecord->Data.SOA.pNamePrimaryServer ),
RECSTRING_UTF8( pRecord, pRecord->Data.SOA.pNameAdministrator ),
RECSTRING_WIDE( pRecord, pRecord->Data.SOA.pNameAdministrator ),
pRecord->Data.SOA.dwSerialNo,
pRecord->Data.SOA.dwRefresh,
pRecord->Data.SOA.dwRetry,
pRecord->Data.SOA.dwExpire,
pRecord->Data.SOA.dwDefaultTtl );
}
VOID
MinfoRecordPrint(
IN PRINT_ROUTINE PrintRoutine,
IN OUT PPRINT_CONTEXT pContext,
IN PDNS_RECORD pRecord
)
/*++
Routine Description:
Print MINFO and RP records.
Arguments:
PrintRoutine -- routine to print with
pRecord -- record to print
Return Value:
TRUE if record data equal
FALSE otherwise
--*/
{
PrintRoutine(
pContext,
"\tMailbox = %s%S\n"
"\tErrorsMbox = %s%S\n",
RECSTRING_UTF8( pRecord, pRecord->Data.MINFO.pNameMailbox ),
RECSTRING_WIDE( pRecord, pRecord->Data.MINFO.pNameMailbox ),
RECSTRING_UTF8( pRecord, pRecord->Data.MINFO.pNameErrorsMailbox ),
RECSTRING_WIDE( pRecord, pRecord->Data.MINFO.pNameErrorsMailbox )
);
}
VOID
TxtRecordPrint(
IN PRINT_ROUTINE PrintRoutine,
IN OUT PPRINT_CONTEXT pContext,
IN PDNS_RECORD pRecord
)
/*++
Routine Description:
Print TXT compatible records.
Includes: TXT, X25, HINFO, ISDN
Arguments:
PrintRoutine -- routine to print with
pRecord -- record to print
Return Value:
TRUE if record data equal
FALSE otherwise
--*/
{
LPTSTR * ppstring;
INT i;
INT count;
count = pRecord->Data.TXT.dwStringCount;
ppstring = pRecord->Data.TXT.pStringArray;
DnsPrint_Lock();
PrintRoutine(
pContext,
"\tStringCount = %d\n",
count );
for( i=1; i<=count; i++ )
{
PrintRoutine(
pContext,
"\tString[%d] = %s%S\n",
i,
RECSTRING_UTF8( pRecord, *ppstring ),
RECSTRING_WIDE( pRecord, *ppstring )
);
ppstring++;
}
DnsPrint_Unlock();
}
VOID
AaaaRecordPrint(
IN PRINT_ROUTINE PrintRoutine,
IN OUT PPRINT_CONTEXT pContext,
IN PDNS_RECORD pRecord
)
/*++
Routine Description:
Print flat data records.
Includes AAAA type.
Arguments:
PrintRoutine -- routine to print with
pRecord -- record to print
Return Value:
TRUE if record data equal
FALSE otherwise
--*/
{
CHAR ip6String[ IP6_ADDRESS_STRING_LENGTH ];
Dns_Ip6AddressToString_A(
ip6String,
(PDNS_IP6_ADDRESS) &pRecord->Data.AAAA.Ip6Address );
PrintRoutine(
pContext,
"\tIP6 Address = %s\n",
ip6String );
}
VOID
SrvRecordPrint(
IN PRINT_ROUTINE PrintRoutine,
IN OUT PPRINT_CONTEXT pContext,
IN PDNS_RECORD pRecord
)
/*++
Routine Description:
Print SRV record.
Arguments:
PrintRoutine -- routine to print with
pRecord -- record to print
Return Value:
TRUE if record data equal
FALSE otherwise
--*/
{
PrintRoutine(
pContext,
"\tPriority = %d\n"
"\tWeight = %d\n"
"\tPort = %d\n"
"\tTarget Host = %s%S\n",
pRecord->Data.SRV.wPriority,
pRecord->Data.SRV.wWeight,
pRecord->Data.SRV.wPort,
RECSTRING_UTF8( pRecord, pRecord->Data.SRV.pNameTarget ),
RECSTRING_WIDE( pRecord, pRecord->Data.SRV.pNameTarget )
);
}
VOID
AtmaRecordPrint(
IN PRINT_ROUTINE PrintRoutine,
IN OUT PPRINT_CONTEXT pContext,
IN PDNS_RECORD pRecord
)
/*++
Routine Description:
Print ATMA record.
Arguments:
PrintRoutine -- routine to print with
pRecord -- record to print
Return Value:
TRUE if record data equal
FALSE otherwise
--*/
{
PrintRoutine(
pContext,
"\tAddress type = %d\n",
pRecord->Data.ATMA.AddressType );
if ( pRecord->Data.ATMA.Address &&
pRecord->Data.ATMA.AddressType == DNS_ATMA_FORMAT_E164 )
{
PrintRoutine(
pContext,
"\tAddress = %s\n",
pRecord->Data.ATMA.Address );
}
else if ( pRecord->Data.ATMA.Address )
{
DnsPrint_RawOctets(
PrintRoutine,
pContext,
"\tAddress = ",
"\t ", // no line header
pRecord->Data.ATMA.Address,
pRecord->wDataLength - 1
);
}
}
VOID
TsigRecordPrint(
IN PRINT_ROUTINE PrintRoutine,
IN OUT PPRINT_CONTEXT pContext,
IN PDNS_RECORD pRecord
)
/*++
Routine Description:
Print TSIG record.
Arguments:
PrintRoutine -- routine to print with
pRecord -- record to print
Return Value:
TRUE if record data equal
FALSE otherwise
--*/
{
DnsPrint_Lock();
if ( pRecord->Data.TSIG.bPacketPointers )
{
DnsPrint_PacketName(
PrintRoutine,
pContext,
"\tAlgorithm = ",
pRecord->Data.TSIG.pAlgorithmPacket,
NULL, // no packet context
NULL,
"\n" );
}
else
{
PrintRoutine(
pContext,
"\tAlgorithm = %s%S\n",
RECSTRING_UTF8( pRecord, pRecord->Data.TSIG.pNameAlgorithm ),
RECSTRING_WIDE( pRecord, pRecord->Data.TSIG.pNameAlgorithm )
);
}
PrintRoutine(
pContext,
"\tSigned Time = %I64u\n"
"\tFudge Time = %u\n"
"\tSig Length = %u\n"
"\tSig Ptr = %p\n"
"\tXid = %u\n"
"\tError = %u\n"
"\tOtherLength = %u\n"
"\tOther Ptr = %p\n",
pRecord->Data.TSIG.i64CreateTime,
pRecord->Data.TSIG.wFudgeTime,
pRecord->Data.TSIG.wSigLength,
pRecord->Data.TSIG.pSignature,
pRecord->Data.TSIG.wOriginalXid,
pRecord->Data.TSIG.wError,
pRecord->Data.TSIG.wOtherLength,
pRecord->Data.TSIG.pOtherData
);
if ( pRecord->Data.TSIG.pSignature )
{
DnsPrint_RawOctets(
PrintRoutine,
pContext,
"Signature:",
NULL, // no line header
pRecord->Data.TSIG.pSignature,
pRecord->Data.TSIG.wSigLength
);
}
if ( pRecord->Data.TSIG.pOtherData )
{
DnsPrint_RawOctets(
PrintRoutine,
pContext,
"Other Data:",
NULL, // no line header
pRecord->Data.TSIG.pOtherData,
pRecord->Data.TSIG.wOtherLength
);
}
DnsPrint_Unlock();
}
VOID
TkeyRecordPrint(
IN PRINT_ROUTINE PrintRoutine,
IN OUT PPRINT_CONTEXT pContext,
IN PDNS_RECORD pRecord
)
/*++
Routine Description:
Print TKEY record.
Arguments:
PrintRoutine -- routine to print with
pRecord -- record to print
Return Value:
TRUE if record data equal
FALSE otherwise
--*/
{
DnsPrint_Lock();
if ( pRecord->Data.TKEY.bPacketPointers )
{
DnsPrint_PacketName(
PrintRoutine,
pContext,
"\tAlgorithm = ",
pRecord->Data.TKEY.pAlgorithmPacket,
NULL, // no packet context
NULL,
"\n" );
}
else
{
PrintRoutine(
pContext,
"\tAlgorithm = %s%S\n",
RECSTRING_UTF8( pRecord, pRecord->Data.TKEY.pNameAlgorithm ),
RECSTRING_WIDE( pRecord, pRecord->Data.TKEY.pNameAlgorithm )
);
}
PrintRoutine(
pContext,
"\tCreate Time = %d\n"
"\tExpire Time = %d\n"
"\tMode = %d\n"
"\tError = %d\n"
"\tKey Length = %d\n"
"\tKey Ptr = %p\n"
"\tOtherLength = %d\n"
"\tOther Ptr = %p\n",
pRecord->Data.TKEY.dwCreateTime,
pRecord->Data.TKEY.dwExpireTime,
pRecord->Data.TKEY.wMode,
pRecord->Data.TKEY.wError,
pRecord->Data.TKEY.wKeyLength,
pRecord->Data.TKEY.pKey,
pRecord->Data.TKEY.wOtherLength,
pRecord->Data.TKEY.pOtherData
);
if ( pRecord->Data.TKEY.pKey )
{
DnsPrint_RawOctets(
PrintRoutine,
pContext,
"Key:",
NULL, // no line header
pRecord->Data.TKEY.pKey,
pRecord->Data.TKEY.wKeyLength
);
}
if ( pRecord->Data.TKEY.pOtherData )
{
DnsPrint_RawOctets(
PrintRoutine,
pContext,
"Other Data:",
NULL, // no line header
pRecord->Data.TKEY.pOtherData,
pRecord->Data.TKEY.wOtherLength
);
}
DnsPrint_Unlock();
}
//
// RR Print Dispatch Table
//
RR_PRINT_FUNCTION RRPrintTable[] =
{
NULL, // ZERO
ARecordPrint, // A
PtrRecordPrint, // NS
PtrRecordPrint, // MD
PtrRecordPrint, // MF
PtrRecordPrint, // CNAME
SoaRecordPrint, // SOA
PtrRecordPrint, // MB
PtrRecordPrint, // MG
PtrRecordPrint, // MR
NULL, // NULL
NULL, //WksRecordPrint, // WKS
PtrRecordPrint, // PTR
TxtRecordPrint, // HINFO
MinfoRecordPrint, // MINFO
MxRecordPrint, // MX
TxtRecordPrint, // TXT
MinfoRecordPrint, // RP
MxRecordPrint, // AFSDB
TxtRecordPrint, // X25
TxtRecordPrint, // ISDN
MxRecordPrint, // RT
NULL, // NSAP
NULL, // NSAPPTR
NULL, // SIG
NULL, // KEY
NULL, // PX
NULL, // GPOS
AaaaRecordPrint, // AAAA
NULL, // LOC
NULL, // NXT
NULL, // EID
NULL, // NIMLOC
SrvRecordPrint, // SRV
AtmaRecordPrint, // ATMA
NULL, // NAPTR
NULL, // KX
NULL, // CERT
NULL, // A6
NULL, // DNAME
NULL, // SINK
NULL, // OPT
NULL, // 42
NULL, // 43
NULL, // 44
NULL, // 45
NULL, // 46
NULL, // 47
NULL, // 48
//
// NOTE: last type indexed by type ID MUST be set
// as MAX_SELF_INDEXED_TYPE #define in record.h
// (see note above in record info table)
//
// Pseudo record types
//
TkeyRecordPrint, // TKEY
TsigRecordPrint, // TSIG
//
// MS only types
//
NULL, // WINS
NULL, // WINSR
};
//
// Generic print record functions
//
VOID
DnsPrint_Record(
IN PRINT_ROUTINE PrintRoutine,
IN OUT PPRINT_CONTEXT pContext,
IN LPSTR pszHeader,
IN PDNS_RECORD pRecord,
IN PDNS_RECORD pPreviousRecord OPTIONAL
)
/*++
Routine Description:
Print record.
Arguments:
PrintRoutine -- routine to print with
pszHeader -- header message
pRecord -- record to print
pPreviousRecord -- previous record in RR set (if any)
Return Value:
None.
--*/
{
WORD type = pRecord->wType;
WORD dataLength = pRecord->wDataLength;
WORD index;
DnsPrint_Lock();
if ( pszHeader )
{
PrintRoutine(
pContext,
pszHeader );
}
if ( !pRecord )
{
PrintRoutine(
pContext,
"ERROR: Null record ptr to print!\n" );
goto Unlock;
}
//
// print record info
//
// same as previous -- skip duplicated info
// must match
// - name ptr (or have no name)
// - type
// - flags (hence section)
if ( pPreviousRecord &&
(!pRecord->pName || pPreviousRecord->pName == pRecord->pName) &&
pPreviousRecord->wType == type &&
*(PWORD)&pPreviousRecord->Flags.DW == *(PWORD)&pRecord->Flags.DW )
{
PrintRoutine(
pContext,
" Next record in set:\n"
"\tPtr = %p, pNext = %p\n"
"\tTTL = %d\n"
"\tDataLength = %d\n",
pRecord,
pRecord->pNext,
pRecord->dwTtl,
dataLength );
}
//
// different from previous -- full print
//
else
{
PrintRoutine(
pContext,
" Record:\n"
"\tPtr = %p, pNext = %p\n"
"\tOwner = %s%S\n"
"\tType = %s (%d)\n"
"\tFlags = %hx\n"
"\t\tSection = %d\n"
"\t\tDelete = %d\n"
"\t\tCharSet = %d\n"
"\tTTL = %d\n"
"\tDataLength = %d\n",
pRecord,
pRecord->pNext,
RECSTRING_UTF8( pRecord, pRecord->pName ),
RECSTRING_WIDE( pRecord, pRecord->pName ),
Dns_RecordStringForType( type ),
type,
pRecord->Flags.DW,
pRecord->Flags.S.Section,
pRecord->Flags.S.Delete,
pRecord->Flags.S.CharSet,
pRecord->dwTtl,
dataLength );
}
//
// if no data -- done
//
if ( ! dataLength )
{
goto Unlock;
}
//
// print data
//
index = INDEX_FOR_TYPE( type );
DNS_ASSERT( index <= MAX_RECORD_TYPE_INDEX );
if ( index && RRPrintTable[ index ] )
{
RRPrintTable[ index ](
PrintRoutine,
pContext,
pRecord );
}
else if ( !index )
{
PrintRoutine(
pContext,
"\tUnknown type: can not print data\n" );
}
else
{
// DCR: should do raw bytes print
PrintRoutine(
pContext,
"\tNo print routine for this type\n" );
}
Unlock:
DnsPrint_Unlock();
}
VOID
printBadDataLength(
IN PRINT_ROUTINE PrintRoutine,
IN OUT PPRINT_CONTEXT pContext,
IN PDNS_RECORD pRecord
)
/*++
Routine Description:
Prints waring on bad data in record.
Arguments:
PrintRoutine -- routine to print with
pRecord -- record with bad data
Return Value:
None.
--*/
{
PrintRoutine(
pContext,
"\tERROR: Invalid record data length for this type.\n" );
}
VOID
DnsPrint_RecordSet(
IN PRINT_ROUTINE PrintRoutine,
IN OUT PPRINT_CONTEXT pContext,
IN LPSTR pszHeader,
IN PDNS_RECORD pRecord
)
/*++
Routine Description:
Print record set.
Arguments:
PrintRoutine -- routine to print with
pRecord -- record set to print
Return Value:
None
--*/
{
PDNS_RECORD pprevious;
DnsPrint_Lock();
if ( pszHeader )
{
PrintRoutine(
pContext,
pszHeader );
}
if ( !pRecord )
{
PrintRoutine(
pContext,
" No Records in list.\n" );
goto Unlock;
}
//
// print all records in set
//
pprevious = NULL;
while ( pRecord )
{
DnsPrint_Record(
PrintRoutine,
pContext,
NULL,
pRecord,
pprevious );
pprevious = pRecord;
pRecord = pRecord->pNext;
}
PrintRoutine(
pContext,
"\n" );
Unlock:
DnsPrint_Unlock();
}
//
// End rrprint.c
//