|
|
/*++
Copyright (c) 1996-2001 Microsoft Corporation
Module Name:
rrlist.c
Abstract:
Domain Name System (DNS) Library
Record list manipulation.
Author:
Jim Gilroy (jamesg) January, 1997
Environment:
User Mode - Win32
Revision History:
--*/
#include "local.h"
PDNS_RECORD Dns_RecordSetDetach( IN OUT PDNS_RECORD pRR ) /*++
Routine Description:
Detach first RR set from the rest of the list.
Arguments:
pRR - incoming record set
Return Value:
Ptr to first record of next RR set. NULL if at end of list.
--*/ { PDNS_RECORD prr = pRR; PDNS_RECORD pback; // previous RR in set
WORD type; // first RR set type
DWORD section; // section of first RR set
if ( !prr ) { return( NULL ); }
//
// loop until find start of new RR set
// - new type or
// - new section or
// - new name
// note that NULL name is automatically considered
// previous name
//
type = prr->wType; section = prr->Flags.S.Section; pback = prr;
while ( prr = pback->pNext ) { if ( prr->wType == type && prr->Flags.S.Section == section && ( prr->pName == NULL || Dns_NameComparePrivate( prr->pName, pback->pName, pback->Flags.S.CharSet ) ) ) { pback = prr; continue; }
// should not be detaching nameless record
// - fixup for robustness
if ( !prr->pName ) { ASSERT( prr->pName ); prr->pName = Dns_NameCopyAllocate( pRR->pName, 0, // length unknown
pRR->Flags.S.CharSet, prr->Flags.S.CharSet ); SET_FREE_OWNER( prr ); } break; }
// have following RR set, NULL terminate first set
if ( prr ) { pback->pNext = NULL; } return( prr ); }
PDNS_RECORD WINAPI Dns_RecordListAppend( IN OUT PDNS_RECORD pHeadList, IN PDNS_RECORD pTailList ) /*++
Routine Description:
Append record list onto another.
Arguments:
pHeadList -- record list to be head
pTailList -- record list to append to pHeadList
Return Value:
Ptr to first record of combined RR set. - pHeadList UNLESS pHeadList is NULL, then it is pTailList.
--*/ { PDNS_RECORD prr = pHeadList;
if ( !prr ) { return pTailList; }
// find end of first list and append second list
while ( prr->pNext ) { prr = prr->pNext; }
// should be appending new set (with new name)
// or matching previous set
DNS_ASSERT( !pTailList || pTailList->pName || (pTailList->wType == prr->wType && pTailList->Flags.S.Section == prr->Flags.S.Section) );
prr->pNext = pTailList;
return pHeadList; }
DWORD Dns_RecordListCount( IN PDNS_RECORD pRRList, IN WORD wType ) /*++
Routine Description:
Count records in list.
Arguments:
pRRList - incoming record set
Return Value:
Count of records of given type in list.
--*/ { DWORD count = 0;
//
// loop counting all records that match
// - either direct match
// - or if matching type is ALL
//
while ( pRRList ) { if ( pRRList->wType == wType || wType == DNS_TYPE_ALL ) { count++; }
pRRList = pRRList->pNext; }
return( count ); }
DWORD Dns_RecordListGetMinimumTtl( IN PDNS_RECORD pRRList ) /*++
Routine Description:
Get minimum TTL of record list
Arguments:
pRRList - incoming record set
Return Value:
Minimum TTL of records in list.
--*/ { PDNS_RECORD prr = pRRList; DWORD minTtl = MAXDWORD;
DNSDBG( TRACE, ( "Dns_RecordListGetMinimumTtl( %p )\n", pRRList ));
//
// loop through list build minimum TTL
//
while ( prr ) { if ( prr->dwTtl < minTtl ) { minTtl = prr->dwTtl; } prr = prr->pNext; }
return minTtl; }
//
// Record screening
//
BOOL Dns_ScreenRecord( IN PDNS_RECORD pRR, IN DWORD ScreenFlag ) /*++
Routine Description:
Screen a record.
Arguments:
pRR - incoming record
ScreenFlag - screeing flag
Return Value:
TRUE if passes screening. FALSE if record fails screen.
--*/ { BOOL fsave = TRUE;
DNSDBG( TRACE, ( "Dns_ScreenRecord( %p, %08x )\n", pRR, ScreenFlag ));
// section screening
if ( ScreenFlag & SCREEN_OUT_SECTION ) { if ( IS_ANSWER_RR(pRR) ) { fsave = !(ScreenFlag & SCREEN_OUT_ANSWER); } else if ( IS_AUTHORITY_RR(pRR) ) { fsave = !(ScreenFlag & SCREEN_OUT_AUTHORITY); } else if ( IS_ADDITIONAL_RR(pRR) ) { fsave = !(ScreenFlag & SCREEN_OUT_ADDITIONAL); } if ( !fsave ) { return FALSE; } }
// type screening
if ( ScreenFlag & SCREEN_OUT_NON_RPC ) { fsave = Dns_IsRpcRecordType( pRR->wType ); }
return fsave; }
PDNS_RECORD Dns_RecordListScreen( IN PDNS_RECORD pRR, IN DWORD ScreenFlag ) /*++
Routine Description:
Screen records from record set.
Arguments:
pRR - incoming record set
ScreenFlag - flag with record screening parameters
Return Value:
Ptr to new record set, if successful. NULL on error.
--*/ { PDNS_RECORD prr; PDNS_RECORD pnext; DNS_RRSET rrset;
DNSDBG( TRACE, ( "Dns_RecordListScreen( %p, %08x )\n", pRR, ScreenFlag ));
// init copy rrset
DNS_RRSET_INIT( rrset );
//
// loop through RR list
//
pnext = pRR;
while ( pnext ) { prr = pnext; pnext = prr->pNext;
//
// screen
// - reappend record passing screen
// - delete record failing screen
//
if ( Dns_ScreenRecord( prr, ScreenFlag ) ) { prr->pNext = NULL; DNS_RRSET_ADD( rrset, prr ); continue; } else { Dns_RecordFree( prr ); } }
return( rrset.pFirstRR ); }
//
// End rrlist.c
//
|