WindowsXP-SP1/ds/dns/dnslib/rrsort.c
2020-09-30 16:53:49 +02:00

355 lines
7.7 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1997-2000 Microsoft Corporation
Module Name:
rrsort.c
Abstract:
Domain Name System (DNS) Library
Copy resource record routines.
Author:
Glenn Curtis (glennc) December, 1997
Revision History:
Jim Gilroy (jamesg) March 2000 -- prioritize fix ups
--*/
#include "local.h"
BOOL
Dns_CompareIpAddresses(
IN IP_ADDRESS addr1,
IN IP_ADDRESS addr2,
IN IP_ADDRESS subnetMask
)
{
if ( subnetMask == INADDR_NONE ||
subnetMask == INADDR_ANY )
{
if ( ((LPBYTE)&addr1)[0] == ((LPBYTE)&addr2)[0] )
{
if ( ((LPBYTE)&addr1)[1] == ((LPBYTE)&addr2)[1] )
{
if ( ((LPBYTE)&addr1)[2] == ((LPBYTE)&addr2)[2] )
return TRUE;
}
}
}
else
{
IP_ADDRESS MaskedAddr1 = addr1 & subnetMask;
IP_ADDRESS MaskedAddr2 = addr2 & subnetMask;
if ( ( addr1 & subnetMask ) == ( addr2 & subnetMask ) )
return TRUE;
}
return FALSE;
}
PDNS_RECORD
Dns_PrioritizeSingleRecordSet(
IN OUT PDNS_RECORD pRecordSet,
IN PDNS_ADDR_INFO aAddressInfo,
IN DWORD cAddressInfo
)
/*++
Routine Description:
Prioritize records in record set.
Note: REQUIRES single record set.
Caller should use Dns_PrioritizeRecordList() for multiple lists.
Arguments:
pRecordSet -- record set to prioritize
aAddressInfo -- local address info to prioritize against
cAddressInfo -- count of address info structs
Return Value:
Ptr to prioritized set.
Set is NOT new, but is same set as pRecordSet, with records shuffled.
--*/
{
PDNS_RECORD prr;
PDNS_RECORD pprevRR;
PDNS_RECORD prrUnmatched;
DWORD iter;
DNS_LIST listPrioritized;
//
// DCR_FIX: this whole routine is bogus
// - it lets you do no intermediate ranking
// it's binary and in order of IPs in list
//
// need
// - knowledge of fast\slow interfaces (WAN for example)
// then
// - do best match on each RR in turn (rank it)
// - then arrange in rank order
//
//
// verify A records
//
// DCR_ENHANCE: prioritize A6 records
//
if ( !pRecordSet || pRecordSet->wType != DNS_TYPE_A )
{
return( pRecordSet );
}
// init prioritized list
DNS_LIST_STRUCT_INIT( listPrioritized );
//
// loop through IP addresses to finding best matches
//
prrUnmatched = pRecordSet;
for ( iter = 0; iter < cAddressInfo; iter++ )
{
pprevRR = NULL;
prr = prrUnmatched;
//
// loop through all RRs in set
//
while ( prr )
{
// NOTE: no RR set check, we assume caller passes in single
// record set, so we don't have to call detach twice
ASSERT( prr->wType == DNS_TYPE_A );
if ( Dns_CompareIpAddresses(
aAddressInfo[iter].IpAddr,
prr->Data.A.IpAddress,
aAddressInfo[iter].SubnetMask ) )
{
// found a match
// - cut from old list
// - add to new list
PDNS_RECORD pnext = prr->pNext;
prr->pNext = NULL;
DNS_LIST_STRUCT_ADD( listPrioritized, prr );
// fix up old list
if ( pprevRR )
{
pprevRR->pNext = pnext;
}
else
{
prrUnmatched = pnext;
}
prr = pnext;
}
else
{
pprevRR = prr;
prr = prr->pNext;
}
}
}
//
// get matched list -- quick return if nothing matched
//
prr = (PDNS_RECORD) listPrioritized.pFirst;
if ( !prr )
{
return( prrUnmatched );
}
//
// matched -- make sure first record has name
// - copy the name from the original first record
//
if ( !prr->pName || !FLAG_FreeOwner(prr) )
{
PBYTE pnameCopy = NULL;
pnameCopy = Dns_NameCopyAllocate(
pRecordSet->pName,
0, // length unknown
RECORD_CHARSET( prr ),
RECORD_CHARSET( prr )
);
if ( pnameCopy )
{
prr->pName = pnameCopy;
FLAG_FreeOwner( prr ) = TRUE;
}
// DCR_FIX0: alloc failure leaves blank name
// best idea is
// - do single RR set
// - just grab (move) name from original first RR
// only check is must be external name
}
//
// tack unmatched records on end
//
DNS_LIST_STRUCT_ADD( listPrioritized, prrUnmatched );
//
// return prioritized list
//
return prr;
}
PDNS_RECORD
Dns_PrioritizeRecordSet(
IN OUT PDNS_RECORD pRecordList,
IN PDNS_ADDR_INFO aAddressInfo,
IN DWORD cAddressInfo
)
/*++
Routine Description:
Prioritize records in record list.
Record list may contain multiple record sets.
Note, currently only prioritize A records, but may
later do A6 also.
Arguments:
pRecordList -- record list to prioritize
aAddressInfo -- local address info to prioritize against
cAddressInfo -- count of address info structs
Return Value:
Ptr to prioritized list.
List is NOT new, but is same list as pRecordList, with records shuffled.
--*/
{
DNS_LIST listPrioritized;
PDNS_RECORD prr;
PDNS_RECORD prrNextSet;
if ( cAddressInfo == 0 ||
! pRecordList )
{
return pRecordList;
}
// init prioritized list
DNS_LIST_STRUCT_INIT( listPrioritized );
//
// loop through all record sets prioritizing
// - whack off each RR set in turn
// - prioritize it (if possible)
// - pour it back into full list
//
//
prr = pRecordList;
while ( prr )
{
prrNextSet = Dns_RecordSetDetach( prr );
prr = Dns_PrioritizeSingleRecordSet(
prr,
aAddressInfo,
cAddressInfo );
while ( prr )
{
register PDNS_RECORD pnextRR;
pnextRR = prr->pNext;
DNS_LIST_STRUCT_ADD( listPrioritized, prr );
prr = pnextRR;
}
prr = prrNextSet;
}
return (PDNS_RECORD) listPrioritized.pFirst;
}
PDNS_RECORD
Dns_PrioritizeRecordSetEx(
IN OUT PDNS_RECORD pRecordList,
IN PDNS_ADDR_ARRAY pAddrArray
)
/*++
Routine Description:
Prioritize records in record list.
Record list may contain multiple record sets.
Note, currently only prioritize A records, but may
later do A6 also.
Arguments:
pRecordList -- record list to prioritize
pAddrArray -- addr info array
Return Value:
Ptr to prioritized list.
List is NOT new, but is same list as pRecordList, with records shuffled.
--*/
{
return Dns_PrioritizeRecordSet(
pRecordList,
pAddrArray->AddrArray,
pAddrArray->AddrCount );
}
//
// End rrsort.c
//