1013 lines
19 KiB
C
1013 lines
19 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1997-2000 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
rrcomp.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Domain Name System (DNS) Library
|
|||
|
|
|||
|
Compare resource record routines.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Jim Gilroy (jamesg) February, 1997
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
|
|||
|
#include "local.h"
|
|||
|
#include "locale.h" // for setlocale stuff for Win9x
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Type specific RR compare routine prototypes
|
|||
|
//
|
|||
|
|
|||
|
BOOL
|
|||
|
ARecordCompare(
|
|||
|
IN PDNS_RECORD pRR1,
|
|||
|
IN PDNS_RECORD pRR2
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Compare A records.
|
|||
|
|
|||
|
All these routines assume:
|
|||
|
- type compare complete
|
|||
|
- datalength compare completed
|
|||
|
- NO unicode
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pRR1 - first record
|
|||
|
|
|||
|
pRR2 -- second record
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if record data equal
|
|||
|
FALSE otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
return( pRR1->Data.A.IpAddress == pRR2->Data.A.IpAddress );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
PtrRecordCompare(
|
|||
|
IN PDNS_RECORD pRR1,
|
|||
|
IN PDNS_RECORD pRR2
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Compare PTR compatible record.
|
|||
|
Includes: NS, PTR, CNAME, MB, MR, MG, MD, MF
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pRR1 - first record
|
|||
|
|
|||
|
pRR2 -- second record
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if record data equal
|
|||
|
FALSE otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
return Dns_NameComparePrivate(
|
|||
|
(LPSTR) pRR1->Data.PTR.pNameHost,
|
|||
|
(LPSTR) pRR2->Data.PTR.pNameHost,
|
|||
|
RECORD_CHARSET(pRR1) );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
MxRecordCompare(
|
|||
|
IN PDNS_RECORD pRR1,
|
|||
|
IN PDNS_RECORD pRR2
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Compare MX compatible record.
|
|||
|
Includes: MX, RT, AFSDB
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pRR1 - first record
|
|||
|
|
|||
|
pRR2 -- second record
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if record data equal
|
|||
|
FALSE otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
// verify preference match first
|
|||
|
|
|||
|
if ( pRR1->Data.MX.wPreference != pRR2->Data.MX.wPreference )
|
|||
|
{
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
|
|||
|
// then result is name comparison
|
|||
|
|
|||
|
return Dns_NameComparePrivate(
|
|||
|
(LPSTR) pRR1->Data.MX.pNameExchange,
|
|||
|
(LPSTR) pRR2->Data.MX.pNameExchange,
|
|||
|
RECORD_CHARSET(pRR1) );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
SoaRecordCompare(
|
|||
|
IN PDNS_RECORD pRR1,
|
|||
|
IN PDNS_RECORD pRR2
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Compare SOA record.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pRR1 - first record
|
|||
|
|
|||
|
pRR2 -- second record
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if record data equal
|
|||
|
FALSE otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
// verify integer data match first
|
|||
|
|
|||
|
if ( memcmp( & pRR1->Data.SOA.dwSerialNo,
|
|||
|
& pRR2->Data.SOA.dwSerialNo,
|
|||
|
SIZEOF_SOA_FIXED_DATA ) )
|
|||
|
{
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
|
|||
|
// match check names
|
|||
|
// - primary name server
|
|||
|
// - admin email name
|
|||
|
|
|||
|
if ( ! Dns_NameComparePrivate(
|
|||
|
(LPSTR) pRR1->Data.SOA.pNamePrimaryServer,
|
|||
|
(LPSTR) pRR2->Data.SOA.pNamePrimaryServer,
|
|||
|
RECORD_CHARSET(pRR1) ) )
|
|||
|
{
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
|
|||
|
return Dns_NameComparePrivate(
|
|||
|
(LPSTR) pRR1->Data.SOA.pNameAdministrator,
|
|||
|
(LPSTR) pRR2->Data.SOA.pNameAdministrator,
|
|||
|
RECORD_CHARSET(pRR1) );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
MinfoRecordCompare(
|
|||
|
IN PDNS_RECORD pRR1,
|
|||
|
IN PDNS_RECORD pRR2
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Compare MINFO and RP records.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pRR1 -- first record
|
|||
|
|
|||
|
pRR2 -- second record
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if record data equal
|
|||
|
FALSE otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
if ( ! Dns_NameComparePrivate(
|
|||
|
(LPSTR) pRR1->Data.MINFO.pNameMailbox,
|
|||
|
(LPSTR) pRR2->Data.MINFO.pNameMailbox,
|
|||
|
RECORD_CHARSET(pRR1) ) )
|
|||
|
{
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
|
|||
|
return Dns_NameComparePrivate(
|
|||
|
(LPSTR) pRR1->Data.MINFO.pNameErrorsMailbox,
|
|||
|
(LPSTR) pRR2->Data.MINFO.pNameErrorsMailbox,
|
|||
|
RECORD_CHARSET(pRR1) );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
TxtRecordCompare(
|
|||
|
IN PDNS_RECORD pRR1,
|
|||
|
IN PDNS_RECORD pRR2
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Compare TXT compatible records.
|
|||
|
Includes: TXT, X25, HINFO, ISDN
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pRR1 -- first record
|
|||
|
|
|||
|
pRR2 -- second record
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if record data equal
|
|||
|
FALSE otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD count;
|
|||
|
PCHAR * pstring1;
|
|||
|
PCHAR * pstring2;
|
|||
|
|
|||
|
//
|
|||
|
// compare every string
|
|||
|
// since string order DOES matter
|
|||
|
// - find string count
|
|||
|
// - compare each (case-sensitive)
|
|||
|
//
|
|||
|
|
|||
|
count = pRR1->Data.TXT.dwStringCount;
|
|||
|
if ( count != pRR2->Data.TXT.dwStringCount )
|
|||
|
{
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
|
|||
|
pstring1 = (PCHAR *) pRR1->Data.TXT.pStringArray;
|
|||
|
pstring2 = (PCHAR *) pRR2->Data.TXT.pStringArray;
|
|||
|
|
|||
|
while ( count-- )
|
|||
|
{
|
|||
|
if ( IS_UNICODE_RECORD(pRR1) )
|
|||
|
{
|
|||
|
if ( wcscmp( (LPWSTR)*pstring1++, (LPWSTR)*pstring2++ ) != 0 )
|
|||
|
{
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if ( strcmp( *pstring1++, *pstring2++ ) != 0 )
|
|||
|
{
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return( TRUE );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
FlatRecordCompare(
|
|||
|
IN PDNS_RECORD pRR1,
|
|||
|
IN PDNS_RECORD pRR2
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Compare flat data records.
|
|||
|
Includes AAAA type.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pRR1 -- first record
|
|||
|
|
|||
|
pRR2 -- second record
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if record data equal
|
|||
|
FALSE otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
if ( pRR1->wDataLength != pRR2->wDataLength )
|
|||
|
{
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
return( !memcmp( & pRR1->Data,
|
|||
|
& pRR2->Data,
|
|||
|
pRR1->wDataLength ) );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
SrvRecordCompare(
|
|||
|
IN PDNS_RECORD pRR1,
|
|||
|
IN PDNS_RECORD pRR2
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Compare SRV record.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pRR1 -- first record
|
|||
|
|
|||
|
pRR2 -- second record
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if record data equal
|
|||
|
FALSE otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
// verify integer data match first
|
|||
|
|
|||
|
if ( memcmp( & pRR1->Data.SRV.wPriority,
|
|||
|
& pRR2->Data.SRV.wPriority,
|
|||
|
SIZEOF_SRV_FIXED_DATA ) )
|
|||
|
{
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
|
|||
|
// then result is compare on target host
|
|||
|
|
|||
|
return Dns_NameComparePrivate(
|
|||
|
(LPSTR) pRR1->Data.SRV.pNameTarget,
|
|||
|
(LPSTR) pRR2->Data.SRV.pNameTarget,
|
|||
|
RECORD_CHARSET(pRR1) );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
AtmaRecordCompare(
|
|||
|
IN PDNS_RECORD pRR1,
|
|||
|
IN PDNS_RECORD pRR2
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Compare ATMA record.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pRR1 -- first record
|
|||
|
|
|||
|
pRR2 -- second record
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if record data equal
|
|||
|
FALSE otherwise
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
WORD length = pRR1->wDataLength;
|
|||
|
|
|||
|
if ( length > pRR2->wDataLength )
|
|||
|
{
|
|||
|
length = pRR2->wDataLength;
|
|||
|
}
|
|||
|
|
|||
|
// verify integer data match first
|
|||
|
|
|||
|
if ( pRR1->Data.ATMA.AddressType != pRR2->Data.ATMA.AddressType )
|
|||
|
{
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
|
|||
|
if ( memcmp(
|
|||
|
pRR1->Data.ATMA.Address,
|
|||
|
pRR2->Data.ATMA.Address,
|
|||
|
length ) != 0 )
|
|||
|
{
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
|
|||
|
return( TRUE );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// RR compare routines jump table
|
|||
|
//
|
|||
|
|
|||
|
RR_COMPARE_FUNCTION RRCompareTable[] =
|
|||
|
{
|
|||
|
NULL, // ZERO
|
|||
|
ARecordCompare, // A
|
|||
|
PtrRecordCompare, // NS
|
|||
|
PtrRecordCompare, // MD
|
|||
|
PtrRecordCompare, // MF
|
|||
|
PtrRecordCompare, // CNAME
|
|||
|
SoaRecordCompare, // SOA
|
|||
|
PtrRecordCompare, // MB
|
|||
|
PtrRecordCompare, // MG
|
|||
|
PtrRecordCompare, // MR
|
|||
|
NULL, // NULL
|
|||
|
NULL, //WksRecordCompare, // WKS
|
|||
|
PtrRecordCompare, // PTR
|
|||
|
TxtRecordCompare, // HINFO
|
|||
|
MinfoRecordCompare, // MINFO
|
|||
|
MxRecordCompare, // MX
|
|||
|
TxtRecordCompare, // TXT
|
|||
|
MinfoRecordCompare, // RP
|
|||
|
MxRecordCompare, // AFSDB
|
|||
|
TxtRecordCompare, // X25
|
|||
|
TxtRecordCompare, // ISDN
|
|||
|
MxRecordCompare, // RT
|
|||
|
NULL, // NSAP
|
|||
|
NULL, // NSAPPTR
|
|||
|
NULL, // SIG
|
|||
|
NULL, // KEY
|
|||
|
NULL, // PX
|
|||
|
NULL, // GPOS
|
|||
|
FlatRecordCompare, // AAAA
|
|||
|
NULL, // LOC
|
|||
|
NULL, // NXT
|
|||
|
NULL, // EID
|
|||
|
NULL, // NIMLOC
|
|||
|
SrvRecordCompare, // SRV
|
|||
|
AtmaRecordCompare, // 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
|
|||
|
//
|
|||
|
|
|||
|
NULL, // TKEY
|
|||
|
NULL, // TSIG
|
|||
|
|
|||
|
//
|
|||
|
// MS only types
|
|||
|
//
|
|||
|
|
|||
|
FlatRecordCompare, // WINS
|
|||
|
NULL, // WINSR
|
|||
|
};
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
WINAPI
|
|||
|
Dns_RecordCompare(
|
|||
|
IN PDNS_RECORD pRecord1,
|
|||
|
IN PDNS_RECORD pRecord2
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Compare two records.
|
|||
|
|
|||
|
Record compare ignores TTL and flags and section information.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pRecord1 -- first record
|
|||
|
|
|||
|
pRecord2 -- second record
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if records equal.
|
|||
|
FALSE otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
BOOL fresult;
|
|||
|
WORD type = pRecord1->wType;
|
|||
|
WORD index;
|
|||
|
|
|||
|
IF_DNSDBG( UPDATE )
|
|||
|
{
|
|||
|
DNS_PRINT((
|
|||
|
"Dns_RecordCompare()\n"
|
|||
|
"\tfirst = %p\n"
|
|||
|
"\tfirst = %p\n",
|
|||
|
pRecord1,
|
|||
|
pRecord2 ));
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// verify that both records have same character set
|
|||
|
//
|
|||
|
|
|||
|
if ( RECORD_CHARSET(pRecord1) != RECORD_CHARSET(pRecord2) )
|
|||
|
{
|
|||
|
DNS_PRINT(( "ERROR: comparing records with non-matching character sets!\n" ));
|
|||
|
|
|||
|
//
|
|||
|
// If they are different and one of them is undefined, just use
|
|||
|
// the defined char set of the other for each.
|
|||
|
//
|
|||
|
|
|||
|
if ( !RECORD_CHARSET(pRecord1) && RECORD_CHARSET(pRecord2) )
|
|||
|
{
|
|||
|
RECORD_CHARSET(pRecord1) = RECORD_CHARSET(pRecord2);
|
|||
|
}
|
|||
|
|
|||
|
if ( !RECORD_CHARSET(pRecord2) && RECORD_CHARSET(pRecord1) )
|
|||
|
{
|
|||
|
RECORD_CHARSET(pRecord2) = RECORD_CHARSET(pRecord1);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// compare type
|
|||
|
//
|
|||
|
|
|||
|
if ( type != pRecord2->wType )
|
|||
|
{
|
|||
|
DNSDBG( UPDATE, (
|
|||
|
"record compare failed -- type mismatch\n" ));
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// compare names
|
|||
|
//
|
|||
|
|
|||
|
if ( ! Dns_NameComparePrivate(
|
|||
|
pRecord1->pName,
|
|||
|
pRecord2->pName,
|
|||
|
RECORD_CHARSET( pRecord1 )
|
|||
|
) )
|
|||
|
{
|
|||
|
DNSDBG( UPDATE, (
|
|||
|
"record compare failed -- owner name mismatch\n" ));
|
|||
|
return( FALSE );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// compare data
|
|||
|
//
|
|||
|
|
|||
|
index = INDEX_FOR_TYPE( type );
|
|||
|
DNS_ASSERT( index <= MAX_RECORD_TYPE_INDEX );
|
|||
|
|
|||
|
if ( !index || !RRCompareTable[ index ] )
|
|||
|
{
|
|||
|
fresult = FlatRecordCompare( pRecord1, pRecord2 );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
fresult = RRCompareTable[ index ](
|
|||
|
pRecord1,
|
|||
|
pRecord2 );
|
|||
|
}
|
|||
|
|
|||
|
IF_DNSDBG( UPDATE )
|
|||
|
{
|
|||
|
DNS_PRINT((
|
|||
|
"Dns_RecordCompare(%p, %p) returns = %d.\n",
|
|||
|
pRecord1,
|
|||
|
pRecord2,
|
|||
|
fresult ));
|
|||
|
}
|
|||
|
return( fresult );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DNS_STATUS
|
|||
|
buildUnmatchedRecordSet(
|
|||
|
OUT PDNS_RECORD * ppDiffRR,
|
|||
|
IN OUT PDNS_RECORD pRR
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Build new list of difference records.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
ppDiffRR - address to recieve PTR to new set
|
|||
|
|
|||
|
pRR - incoming RR set; matched records marked wReserved TRUE
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful.
|
|||
|
Error code on failure.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PDNS_RECORD pcur;
|
|||
|
PDNS_RECORD pnew;
|
|||
|
DNS_RRSET rrset;
|
|||
|
|
|||
|
// init comparison rrset
|
|||
|
|
|||
|
DNS_RRSET_INIT( rrset );
|
|||
|
|
|||
|
//
|
|||
|
// loop through RR set, add records to either match or diff sets
|
|||
|
//
|
|||
|
|
|||
|
pcur = pRR;
|
|||
|
|
|||
|
while ( pcur )
|
|||
|
{
|
|||
|
if ( ! IS_RR_MATCHED(pcur) )
|
|||
|
{
|
|||
|
// make copy of record
|
|||
|
|
|||
|
pnew = Dns_RecordCopyEx(
|
|||
|
pcur,
|
|||
|
RECORD_CHARSET(pcur),
|
|||
|
RECORD_CHARSET(pcur)
|
|||
|
);
|
|||
|
if ( !pnew )
|
|||
|
{
|
|||
|
// DCR_FIX1: last error not set on all Dns_RecordCopy() failures
|
|||
|
// Charlie Wickham was getting some random win32 error
|
|||
|
//
|
|||
|
// DNS_STATUS status = GetLastError();
|
|||
|
|
|||
|
// assume unable to copy because of invalid data
|
|||
|
|
|||
|
DNS_PRINT((
|
|||
|
"ERROR: unable to copy record at %p\n"
|
|||
|
"\thence unable to build diff of set at %p\n",
|
|||
|
pcur,
|
|||
|
pRR ));
|
|||
|
Dns_RecordListFree( rrset.pFirstRR );
|
|||
|
*ppDiffRR = NULL;
|
|||
|
|
|||
|
//return( status ? status : ERROR_INVALID_DATA );
|
|||
|
return( ERROR_INVALID_DATA );
|
|||
|
}
|
|||
|
DNS_RRSET_ADD( rrset, pnew );
|
|||
|
}
|
|||
|
pcur = pcur->pNext;
|
|||
|
}
|
|||
|
|
|||
|
*ppDiffRR = rrset.pFirstRR;
|
|||
|
return( ERROR_SUCCESS );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DWORD
|
|||
|
isUnmatchedRecordInSet(
|
|||
|
IN PDNS_RECORD pRR
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Check if unmatched record in set.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pRR - incoming RR set; matched records marked wReserved TRUE
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Count of all unmatched records in set.
|
|||
|
Zero if all records matched.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PDNS_RECORD pcur;
|
|||
|
DWORD countUnmatched = 0;
|
|||
|
|
|||
|
//
|
|||
|
// loop through RR set check for unmatched records
|
|||
|
//
|
|||
|
|
|||
|
pcur = pRR;
|
|||
|
|
|||
|
while ( pcur )
|
|||
|
{
|
|||
|
if ( ! IS_RR_MATCHED(pcur) )
|
|||
|
{
|
|||
|
countUnmatched++;
|
|||
|
}
|
|||
|
pcur = pcur->pNext;
|
|||
|
}
|
|||
|
|
|||
|
return( countUnmatched );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DNS_SET_COMPARE_RESULT
|
|||
|
WINAPI
|
|||
|
Dns_RecordSetCompareEx(
|
|||
|
IN OUT PDNS_RECORD pRR1,
|
|||
|
IN OUT PDNS_RECORD pRR2,
|
|||
|
OUT PDNS_RECORD * ppDiff1, OPTIONAL
|
|||
|
OUT PDNS_RECORD * ppDiff2 OPTIONAL
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Compare two records.
|
|||
|
|
|||
|
Record compare ignores TTL and flags and section information.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pRR1 - first incoming RR set
|
|||
|
pRR2 - second incoming RR set
|
|||
|
|
|||
|
ppDiff1 - addr to receive ptr to unmatched records from first set
|
|||
|
ppDiff2 - addr to receive ptr to unmatched records from second set
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Result indicating relationship -- or error on allocation error:
|
|||
|
DnsSetCompareError
|
|||
|
DnsSetCompareIdentical
|
|||
|
DnsSetCompareNoOverlap
|
|||
|
DnsSetCompareOneSubsetOfTwo
|
|||
|
DnsSetCompareTwoSubsetOfOne
|
|||
|
DnsSetCompareIntersection
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PDNS_RECORD pcur1;
|
|||
|
PDNS_RECORD pcur2;
|
|||
|
DWORD count1 = 0;
|
|||
|
DWORD count2 = 0;
|
|||
|
DNS_STATUS status;
|
|||
|
DWORD unmatched1;
|
|||
|
DWORD unmatched2;
|
|||
|
DNS_SET_COMPARE_RESULT result;
|
|||
|
|
|||
|
//
|
|||
|
// init RR sets for compare
|
|||
|
// - clear reserved field used as matched flag in compare
|
|||
|
//
|
|||
|
|
|||
|
pcur1 = pRR1;
|
|||
|
while ( pcur1 )
|
|||
|
{
|
|||
|
CLEAR_RR_MATCHED(pcur1);
|
|||
|
pcur1 = pcur1->pNext;
|
|||
|
count1++;
|
|||
|
}
|
|||
|
pcur1 = pRR2;
|
|||
|
while ( pcur1 )
|
|||
|
{
|
|||
|
CLEAR_RR_MATCHED(pcur1);
|
|||
|
pcur1 = pcur1->pNext;
|
|||
|
count2++;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// loop through set 1
|
|||
|
// attempt match of each record to all records in set 2
|
|||
|
// except those already matched
|
|||
|
|
|||
|
pcur1 = pRR1;
|
|||
|
|
|||
|
while ( pcur1 )
|
|||
|
{
|
|||
|
pcur2 = pRR2;
|
|||
|
while ( pcur2 )
|
|||
|
{
|
|||
|
if ( !IS_RR_MATCHED(pcur2) && Dns_RecordCompare( pcur1, pcur2 ) )
|
|||
|
{
|
|||
|
SET_RR_MATCHED(pcur1);
|
|||
|
SET_RR_MATCHED(pcur2);
|
|||
|
}
|
|||
|
pcur2 = pcur2->pNext;
|
|||
|
}
|
|||
|
pcur1 = pcur1->pNext;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// get diff record lists, return
|
|||
|
// - if no diffs, then have match
|
|||
|
//
|
|||
|
// tedious, but do all this error handling because it is easy for
|
|||
|
// user to pass in bad records that may fail copy routines, need
|
|||
|
// way to easily report info, even if only for debugging apps calling in
|
|||
|
//
|
|||
|
|
|||
|
if ( ppDiff1 )
|
|||
|
{
|
|||
|
status = buildUnmatchedRecordSet( ppDiff1, pRR1 );
|
|||
|
if ( status != ERROR_SUCCESS )
|
|||
|
{
|
|||
|
goto Failed;
|
|||
|
}
|
|||
|
}
|
|||
|
if ( ppDiff2 )
|
|||
|
{
|
|||
|
status = buildUnmatchedRecordSet( ppDiff2, pRR2 );
|
|||
|
if ( status != ERROR_SUCCESS )
|
|||
|
{
|
|||
|
if ( ppDiff1 && *ppDiff1 )
|
|||
|
{
|
|||
|
Dns_RecordListFree( *ppDiff1 );
|
|||
|
}
|
|||
|
goto Failed;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// determine relationship between sets
|
|||
|
//
|
|||
|
// impl note: the only better way i could see doing this
|
|||
|
// is to map relationships directly to bit flags
|
|||
|
// however, our enum type doesn't map to bit flags, so
|
|||
|
// then would have to run mapping table to map flags to enum
|
|||
|
//
|
|||
|
// note, we do compare so that NULL lists comes out the first
|
|||
|
// as no-overlap rather than as subset
|
|||
|
//
|
|||
|
|
|||
|
unmatched1 = isUnmatchedRecordInSet( pRR1 );
|
|||
|
unmatched2 = isUnmatchedRecordInSet( pRR2 );
|
|||
|
|
|||
|
if ( unmatched1 == count1 )
|
|||
|
{
|
|||
|
ASSERT( unmatched2 == count2 );
|
|||
|
result = DnsSetCompareNoOverlap;
|
|||
|
}
|
|||
|
else if ( unmatched1 == 0 )
|
|||
|
{
|
|||
|
if ( unmatched2 == 0 )
|
|||
|
{
|
|||
|
result = DnsSetCompareIdentical;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
ASSERT( unmatched2 != count2 );
|
|||
|
result = DnsSetCompareOneSubsetOfTwo;
|
|||
|
}
|
|||
|
}
|
|||
|
else if ( unmatched2 == 0 )
|
|||
|
{
|
|||
|
result = DnsSetCompareTwoSubsetOfOne;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
ASSERT( unmatched2 != count2 );
|
|||
|
result = DnsSetCompareIntersection;
|
|||
|
}
|
|||
|
return( result );
|
|||
|
|
|||
|
|
|||
|
Failed:
|
|||
|
|
|||
|
*ppDiff1 = *ppDiff2 = NULL;
|
|||
|
SetLastError( status );
|
|||
|
return( DnsSetCompareError );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
WINAPI
|
|||
|
Dns_RecordSetCompare(
|
|||
|
IN OUT PDNS_RECORD pRR1,
|
|||
|
IN OUT PDNS_RECORD pRR2,
|
|||
|
OUT PDNS_RECORD * ppDiff1, OPTIONAL
|
|||
|
OUT PDNS_RECORD * ppDiff2 OPTIONAL
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Compare two records.
|
|||
|
|
|||
|
Record compare ignores TTL and flags and section information.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pRR1 - first incoming RR set
|
|||
|
pRR2 - second incoming RR set
|
|||
|
|
|||
|
ppDiff1 - addr to receive ptr to unmatched records from first set
|
|||
|
ppDiff2 - addr to receive ptr to unmatched records from second set
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if record sets equal.
|
|||
|
FALSE otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DNS_SET_COMPARE_RESULT result;
|
|||
|
|
|||
|
result = Dns_RecordSetCompareEx(
|
|||
|
pRR1,
|
|||
|
pRR2,
|
|||
|
ppDiff1,
|
|||
|
ppDiff2 );
|
|||
|
|
|||
|
return( result == DnsSetCompareIdentical );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
WINAPI
|
|||
|
Dns_RecordSetCompareForIntersection(
|
|||
|
IN OUT PDNS_RECORD pRR1,
|
|||
|
IN OUT PDNS_RECORD pRR2
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Compare two record sets for intersection.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pRR1 - first incoming RR set
|
|||
|
pRR2 - second incoming RR set
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE if record sets intersect.
|
|||
|
FALSE otherwise.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DNS_SET_COMPARE_RESULT result;
|
|||
|
|
|||
|
result = Dns_RecordSetCompareEx(
|
|||
|
pRR1,
|
|||
|
pRR2,
|
|||
|
NULL,
|
|||
|
NULL );
|
|||
|
|
|||
|
return( result == DnsSetCompareIdentical ||
|
|||
|
result == DnsSetCompareIntersection ||
|
|||
|
result == DnsSetCompareOneSubsetOfTwo ||
|
|||
|
result == DnsSetCompareTwoSubsetOfOne );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// End rrcomp.c
|
|||
|
//
|
|||
|
|
|||
|
|