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.
1092 lines
22 KiB
1092 lines
22 KiB
/*++
|
|
|
|
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
|
|
//
|
|
|
|
typedef BOOL (* RR_COMPARE_FUNCTION)(
|
|
PDNS_RECORD,
|
|
PDNS_RECORD );
|
|
|
|
//extern RR_COMPARE_FUNCTION RRCompareTable[];
|
|
|
|
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 ( ppDiff2 )
|
|
{
|
|
*ppDiff2 = NULL;
|
|
}
|
|
if ( ppDiff1 )
|
|
{
|
|
*ppDiff1 = NULL;
|
|
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:
|
|
|
|
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
|
|
//
|
|
|
|
|
|
|
|
BOOL
|
|
WINAPI
|
|
Dns_DeleteRecordFromList(
|
|
IN OUT PDNS_RECORD * ppRRList,
|
|
IN PDNS_RECORD pRRDelete
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Delete matching record from record list.
|
|
|
|
Arguments:
|
|
|
|
ppRRList -- addr of record list ptr
|
|
note that in case FIRST record in list is deleted, ppRRList
|
|
is set with ptr to new first record in the list (possibly NULL)
|
|
|
|
pRRDelete -- record to delete
|
|
|
|
Return Value:
|
|
|
|
TRUE if record found in list and deleted.
|
|
FALSE if no match.
|
|
|
|
--*/
|
|
{
|
|
PDNS_RECORD prr;
|
|
PDNS_RECORD pprev;
|
|
|
|
DNSDBG( TRACE, (
|
|
"Dns_DeleteRecordFromList( %p, %p )\n",
|
|
ppRRList,
|
|
pRRDelete ));
|
|
|
|
|
|
//
|
|
// loop through list
|
|
//
|
|
// note, startup works as pNext is first field in DNS_RECORD
|
|
// so access to pNext is simply dereference of the record ptr
|
|
// -- same operation as deref of list address to get first record;
|
|
// this allows us to have pprev pointer starting at ppRRList, and
|
|
// eliminates special code for handling delete of first record
|
|
//
|
|
|
|
prr = (PDNS_RECORD) ppRRList;
|
|
|
|
while ( pprev = prr,
|
|
prr = prr->pNext )
|
|
{
|
|
if ( Dns_RecordCompare(
|
|
prr,
|
|
pRRDelete ) )
|
|
{
|
|
pprev->pNext = prr->pNext;
|
|
|
|
Dns_RecordFree( prr );
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
|