mirror of https://github.com/tongzx/nt5src
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.
354 lines
7.3 KiB
354 lines
7.3 KiB
/*++
|
|
|
|
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
|
|
//
|