885 lines
18 KiB
C
885 lines
18 KiB
C
/*++
|
||
|
||
Copyright (c) 2000-2001 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
ops.c
|
||
|
||
Abstract:
|
||
|
||
DNS Resolver Service.
|
||
|
||
Remote APIs to resolver service.
|
||
|
||
Author:
|
||
|
||
Jim Gilroy (jamesg) November 2000
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
|
||
#include "local.h"
|
||
|
||
|
||
//
|
||
// Max number to enum at a time
|
||
//
|
||
|
||
#define MAX_CACHE_ENUM_COUNT (500)
|
||
|
||
|
||
|
||
|
||
//
|
||
// Enum operations
|
||
//
|
||
// Tag is DWORD with
|
||
// - high word the hash bucket index
|
||
// - low word the entry count
|
||
//
|
||
|
||
#define MakeEnumTag(h,e) MAKEDWORD( (WORD)e, (WORD)h )
|
||
|
||
#define HashBucketFromEnumTag(t) HIWORD(t)
|
||
#define EntryIndexFromEnumTag(t) LOWORD(t)
|
||
|
||
#define GetRpcRecords(p,t,pi) (NULL)
|
||
#define AllocRpcName( s ) Dns_StringCopyAllocate_W( (s), 0 )
|
||
|
||
|
||
|
||
|
||
DNS_STATUS
|
||
R_ResolverEnumCache(
|
||
IN DNS_RPC_HANDLE Handle,
|
||
IN PDNS_CACHE_ENUM_REQUEST pRequest,
|
||
OUT PDNS_CACHE_ENUM * ppEnum
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Enumerate entries in cache.
|
||
|
||
Arguments:
|
||
|
||
RpcHandle -- RPC handle
|
||
|
||
pRequest -- ptr to Enum request
|
||
|
||
ppEnum -- addr to recv pointer to enumeration
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS if successful.
|
||
ErrorCode on failure to enum.
|
||
|
||
--*/
|
||
{
|
||
DNS_STATUS status = ERROR_SUCCESS;
|
||
PDNS_CACHE_ENUM penum = NULL;
|
||
BOOL flocked = FALSE;
|
||
DWORD count = 0;
|
||
DWORD maxCount = 0;
|
||
DWORD entryCount = 0;
|
||
DWORD entryStart;
|
||
WORD typeRequest = 0;
|
||
DWORD hashStart;
|
||
DWORD ihash;
|
||
PDNS_RECORD prr;
|
||
PDNS_CACHE_ENTRY prpcEntry;
|
||
|
||
|
||
DNSDBG( RPC, ( "\nR_ResolverEnumCache\n" ));
|
||
DNSLOG_F1( "Resolver - R_ResolverEnumCache" );
|
||
|
||
if ( !ppEnum || !pRequest )
|
||
{
|
||
return ERROR_INVALID_PARAMETER;
|
||
}
|
||
*ppEnum = NULL;
|
||
|
||
if ( ClientThreadNotAllowedAccess() )
|
||
{
|
||
status = ERROR_ACCESS_DENIED;
|
||
goto Done;
|
||
}
|
||
|
||
//
|
||
// allocate desired space
|
||
//
|
||
|
||
maxCount = pRequest->MaxCount;
|
||
if ( maxCount > MAX_CACHE_ENUM_COUNT )
|
||
{
|
||
maxCount = MAX_CACHE_ENUM_COUNT;
|
||
}
|
||
|
||
penum = (PDNS_CACHE_ENUM)
|
||
RPC_HEAP_ALLOC_ZERO(
|
||
sizeof(DNS_CACHE_ENUM) +
|
||
(maxCount * sizeof(DNS_CACHE_ENTRY)) );
|
||
if ( !penum )
|
||
{
|
||
status = DNS_ERROR_NO_MEMORY;
|
||
goto Done;
|
||
}
|
||
|
||
//
|
||
// read entries starting from EnumTag
|
||
//
|
||
|
||
LOCK_CACHE();
|
||
flocked = TRUE;
|
||
count = 0;
|
||
typeRequest = pRequest->Type;
|
||
|
||
hashStart = HashBucketFromEnumTag( pRequest->EnumTag );
|
||
entryStart = EntryIndexFromEnumTag( pRequest->EnumTag );
|
||
|
||
//
|
||
// enum next DCR: issue of CNAME here?
|
||
//
|
||
|
||
for ( ihash = hashStart; ihash < g_HashTableSize; ihash++ )
|
||
{
|
||
PCACHE_ENTRY pentry = g_HashTable[ihash];
|
||
entryCount = 0;
|
||
|
||
while ( pentry )
|
||
{
|
||
DWORD index = 0;
|
||
|
||
// skip any entries in previous enum
|
||
|
||
if ( ihash == hashStart &&
|
||
entryCount < entryStart )
|
||
{
|
||
pentry = pentry->pNext;
|
||
entryCount++;
|
||
continue;
|
||
}
|
||
|
||
// write enum entries matching criteria
|
||
|
||
while( count < maxCount )
|
||
{
|
||
prr = GetRpcRecords(
|
||
pentry,
|
||
typeRequest,
|
||
& index );
|
||
if ( !prr )
|
||
{
|
||
break;
|
||
}
|
||
|
||
prpcEntry = &penum->EntryArray[count];
|
||
|
||
prpcEntry->pName = AllocRpcName( pentry->pName );
|
||
prpcEntry->wType = typeRequest;
|
||
count++;
|
||
}
|
||
|
||
pentry = pentry->pNext;
|
||
entryCount++;
|
||
}
|
||
}
|
||
|
||
//
|
||
// set return params
|
||
// if exhaust cache -- success
|
||
// if more data, set termination tag to restart
|
||
//
|
||
|
||
penum->TotalCount = g_EntryCount;
|
||
penum->EnumCount = count;
|
||
penum->EnumTagStart = pRequest->EnumTag;
|
||
|
||
if ( ihash == g_HashTableSize )
|
||
{
|
||
status = ERROR_SUCCESS;
|
||
}
|
||
else
|
||
{
|
||
status = ERROR_MORE_DATA;
|
||
penum->EnumTagStop = (DWORD) MAKELONG( entryCount, ihash );
|
||
}
|
||
|
||
*ppEnum = penum;
|
||
|
||
Done:
|
||
|
||
UNLOCK_CACHE();
|
||
|
||
DNSDBG( RPC, (
|
||
"Leave R_ResolverEnumCache()\n"
|
||
"\tstatus = %d\n"
|
||
"\ttotal count = %d\n"
|
||
"\ttag start = %p\n"
|
||
"\ttag end = %p\n"
|
||
"\tcount = %d\n\n",
|
||
status,
|
||
penum->TotalCount,
|
||
penum->EnumTagStart,
|
||
penum->EnumTagStop,
|
||
penum->EnumCount ));
|
||
|
||
return( status );
|
||
}
|
||
|
||
|
||
|
||
//
|
||
// Cache operations
|
||
//
|
||
|
||
DNS_STATUS
|
||
R_ResolverFlushCache(
|
||
IN DNS_RPC_HANDLE Handle
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Flush resolver cache.
|
||
|
||
Arguments:
|
||
|
||
Handle -- RPC handle
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS if successful.
|
||
ERROR_ACCESS_DENIED if unable to flush.
|
||
|
||
--*/
|
||
{
|
||
DNSDBG( RPC, ( "\nR_ResolverFlushCache\n" ));
|
||
|
||
//
|
||
// DCR: flush should have security
|
||
//
|
||
|
||
if ( ClientThreadNotAllowedAccess() )
|
||
{
|
||
DNSLOG_F1( "R_ResolverFlushCache - ERROR_ACCESS_DENIED" );
|
||
return ERROR_ACCESS_DENIED;
|
||
}
|
||
|
||
//
|
||
// flush cache
|
||
//
|
||
|
||
Cache_Flush();
|
||
|
||
DNSDBG( RPC, ( "Leave R_ResolverFlushCache\n\n" ));
|
||
return ERROR_SUCCESS;
|
||
}
|
||
|
||
|
||
|
||
DNS_STATUS
|
||
R_ResolverFlushCacheEntry(
|
||
IN DNS_RPC_HANDLE Handle,
|
||
IN PWSTR pwsName,
|
||
IN WORD wType
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Flush data from resolver cache.
|
||
|
||
Arguments:
|
||
|
||
Handle -- RPC handle
|
||
|
||
pwsName -- name to flush (if NULL flush entire cache)
|
||
|
||
wType -- type to flush; if zero, flush entire entry for name
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS if successful.
|
||
ERROR_ACCESS_DENIED if unable to flush.
|
||
|
||
--*/
|
||
{
|
||
DNSLOG_F1( "R_ResolverFlushCacheEntry" );
|
||
DNSLOG_F2( " Name : %S", pwsName );
|
||
DNSLOG_F2( " Type : %d", wType );
|
||
|
||
DNSDBG( RPC, (
|
||
"R_ResolverFlushCacheEntry\n"
|
||
"\tName = %p %S\n"
|
||
"\tType = %d\n",
|
||
pwsName, pwsName,
|
||
wType ));
|
||
|
||
if ( !pwsName )
|
||
{
|
||
return ERROR_INVALID_PARAMETER;
|
||
}
|
||
|
||
//
|
||
// two levels
|
||
// 1) - no type => flush the whole name entry
|
||
// 2) - name and type => flush on particular RR set
|
||
//
|
||
|
||
Cache_FlushRecords(
|
||
pwsName,
|
||
wType
|
||
? FLUSH_LEVEL_NORMAL
|
||
: FLUSH_LEVEL_WIRE,
|
||
wType
|
||
);
|
||
|
||
DNSDBG( RPC, ( "Leave R_ResolverFlushCacheEntry\n\n" ));
|
||
|
||
return ERROR_SUCCESS;
|
||
}
|
||
|
||
|
||
|
||
//
|
||
// Query API utilities
|
||
//
|
||
|
||
DNS_STATUS
|
||
ResolverQuery(
|
||
IN OUT PQUERY_BLOB pBlob
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Make the query to DNS server.
|
||
|
||
Arguments:
|
||
|
||
pBlob -- query blob
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS if successful response.
|
||
DNS_INFO_NO_RECORDS on no records for type response.
|
||
DNS_ERROR_RCODE_NAME_ERROR on name error.
|
||
DNS_ERROR_INVALID_NAME on bad name.
|
||
None
|
||
|
||
--*/
|
||
{
|
||
DNS_STATUS status = ERROR_SUCCESS;
|
||
PDNS_NETINFO pnetInfo = NULL;
|
||
BOOL fadapterTimedOut = FALSE;
|
||
DNS_STATUS statusNetFailure = ERROR_SUCCESS;
|
||
|
||
|
||
DNSDBG( TRACE, (
|
||
"ResolverQuery( %S, type=%d, f=%08x )\n",
|
||
pBlob->pNameOrig,
|
||
pBlob->wType,
|
||
pBlob->Flags ));
|
||
|
||
//
|
||
// skip query -- timeouts -- entirely if net down
|
||
//
|
||
|
||
if ( IsKnownNetFailure() )
|
||
{
|
||
status = GetLastError();
|
||
DNSLOG_F2(
|
||
"Not going query since there is a known net failure: 0x%.8X",
|
||
status );
|
||
DNSDBG( ANY, (
|
||
"WARNING: known net failure %d, suppressing queries!\n",
|
||
status ));
|
||
return status;
|
||
}
|
||
|
||
//
|
||
// get valid network info
|
||
//
|
||
|
||
pnetInfo = GrabNetworkInfo();
|
||
if ( ! pnetInfo )
|
||
{
|
||
DNSDBG( ANY, ( "ERROR: GrabNetworkInfo() failed!\n" ));
|
||
return DNS_ERROR_NO_DNS_SERVERS;
|
||
}
|
||
pBlob->pNetworkInfo = pnetInfo;
|
||
|
||
//
|
||
// cluster filtering setup
|
||
//
|
||
|
||
if ( g_IsServer )
|
||
{
|
||
pBlob->pfnIsClusterIp = IsClusterAddress;
|
||
}
|
||
|
||
//
|
||
// query
|
||
// includes
|
||
// - local name check
|
||
// - wire query
|
||
//
|
||
|
||
status = Query_Main( pBlob );
|
||
|
||
statusNetFailure = pBlob->NetFailureStatus;
|
||
|
||
#if 0
|
||
//
|
||
// DCR: missing catching intermediate failures
|
||
//
|
||
|
||
//
|
||
// reset server priorities on failures
|
||
// do here to avoid washing out info in retry with new name
|
||
//
|
||
|
||
if ( status != ERROR_SUCCESS &&
|
||
pnetInfo->ReturnFlags & DNS_FLAG_RESET_SERVER_PRIORITY )
|
||
{
|
||
if ( g_AdapterTimeoutCacheTime &&
|
||
Dns_DisableTimedOutAdapters( pnetInfo ) )
|
||
{
|
||
fadapterTimedOut = TRUE;
|
||
SetKnownTimedOutAdapter();
|
||
}
|
||
}
|
||
#endif
|
||
|
||
|
||
//
|
||
// success
|
||
// - drop message popup count
|
||
//
|
||
|
||
if ( status == ERROR_SUCCESS )
|
||
{
|
||
#if 0
|
||
// don't see any point in locking for this crap
|
||
// as long as don't decrement anywhere, and even
|
||
// then success reset should make it ok
|
||
LOCK_NET_FAILURE();
|
||
if ( g_MessagePopupStrikes > 0 )
|
||
g_MessagePopupStrikes--;
|
||
UNLOCK_NET_FAILURE();
|
||
#endif
|
||
g_MessagePopupStrikes = 0;
|
||
}
|
||
|
||
//
|
||
// network failure condition
|
||
// - anything but ERROR_TIMEOUT is net failure
|
||
//
|
||
// timeout error indicates possible net down condition
|
||
// - ping DNS servers
|
||
// if down shutdown queries for short interval; this
|
||
// eliminates long timeouts in boot up during netdown
|
||
// condition
|
||
//
|
||
// DCR: this is stupid -- ping especially
|
||
//
|
||
// should just keep a count, if count rises back off;
|
||
// why we should do useless query (ping) is beyond me
|
||
// rather than just doing another query; only advantage
|
||
// of ping is that it should succeed immediately
|
||
//
|
||
// furthermore any tracking for this that we do do should
|
||
// be in single routine saving the network info
|
||
//
|
||
|
||
else if ( statusNetFailure )
|
||
{
|
||
if ( statusNetFailure == ERROR_TIMEOUT )
|
||
{
|
||
#if 0
|
||
DWORD iter;
|
||
BOOL fping = FALSE;
|
||
PDNS_ADAPTER padapter;
|
||
|
||
for ( iter = 0; iter < pnetInfo->cAdapterCount; iter++ )
|
||
{
|
||
padapter = pnetInfo->AdapterArray[iter];
|
||
|
||
if ( padapter &&
|
||
g_NetFailureCacheTime &&
|
||
Dns_PingAdapterServers( padapter ) )
|
||
{
|
||
fping = TRUE;
|
||
break;
|
||
}
|
||
}
|
||
if ( !fping )
|
||
{
|
||
SetKnownNetFailure( status );
|
||
}
|
||
#endif
|
||
}
|
||
else
|
||
{
|
||
SetKnownNetFailure( status );
|
||
}
|
||
}
|
||
|
||
//
|
||
// save change in adapter priority
|
||
//
|
||
|
||
if ( pnetInfo->ReturnFlags & RUN_FLAG_RESET_SERVER_PRIORITY )
|
||
{
|
||
UpdateNetworkInfo( pnetInfo );
|
||
}
|
||
else
|
||
{
|
||
NetInfo_Free( pnetInfo );
|
||
}
|
||
pBlob->pNetworkInfo = NULL;
|
||
|
||
DNSDBG( QUERY, (
|
||
"Leave ResolverQuery() => %d\n",
|
||
status ));
|
||
|
||
IF_DNSDBG( QUERY )
|
||
{
|
||
DnsDbg_QueryBlob(
|
||
"Blob leaving ResolverQuery()",
|
||
pBlob );
|
||
}
|
||
return status;
|
||
}
|
||
|
||
|
||
|
||
//
|
||
// Query API
|
||
//
|
||
|
||
#ifdef DNS_TRY_ASYNC
|
||
VOID
|
||
R_ResolverQueryAsync(
|
||
IN PRPC_ASYNC_STATE AsyncHandle,
|
||
IN DNS_RPC_HANDLE Handle,
|
||
IN OUT PRPC_QUERY_BLOB pBlob
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Query the resolver.
|
||
|
||
Arguments:
|
||
|
||
pBlob -- ptr to query info and results buffer
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS if successful.
|
||
ErrorCode (including DNS RCODE) on failure.
|
||
|
||
--*/
|
||
{
|
||
DNS_STATUS status = ERROR_SUCCESS;
|
||
PDNS_RECORD prr = NULL;
|
||
PDNS_RECORD prrQuery = NULL;
|
||
PDNS_RECORD presultRR = NULL;
|
||
PCACHE_ENTRY pentry = NULL;
|
||
BOOL locked = FALSE;
|
||
BOOL fcacheNegativeResponse = FALSE;
|
||
CHAR nameUtf8[ DNS_MAX_NAME_BUFFER_LENGTH+1 ];
|
||
DWORD nameBufLength = DNS_MAX_NAME_BUFFER_LENGTH;
|
||
|
||
// DCR_CLEANUP: make local
|
||
// quickie define to old args
|
||
PWSTR pwsName = pBlob->pName;
|
||
WORD Type = pBlob->wType;
|
||
DWORD Flags = pBlob->Flags;
|
||
|
||
|
||
DNSLOG_F1( "R_ResolverQuery" );
|
||
DNSLOG_F1( " Arguments:" );
|
||
DNSLOG_F2( " Name : %S", pwsName );
|
||
DNSLOG_F2( " Type : %d", Type );
|
||
DNSLOG_F2( " Flags : 0x%x", Flags );
|
||
|
||
DNSDBG( RPC, (
|
||
"\nR_ResolverQuery( %S, t=%d, f=%08x )\n",
|
||
pwsName,
|
||
Type,
|
||
Flags ));
|
||
|
||
|
||
//
|
||
// cacheable response
|
||
//
|
||
|
||
Done:
|
||
|
||
//
|
||
// put results in blob
|
||
//
|
||
|
||
pBlob->pRecords = presultRR;
|
||
pBlob->Status = status;
|
||
|
||
DNSLOG_F3(
|
||
"R_ResolverQuery - status : 0x%.8X\n\t%s",
|
||
status,
|
||
Dns_StatusString( status ) );
|
||
DNSLOG_F1( "" );
|
||
|
||
DNSDBG( RPC, (
|
||
"Leave R_ResolverQuery( %S, t=%d, f=%08x )\n\n",
|
||
pwsName,
|
||
Type,
|
||
Flags ));
|
||
}
|
||
#endif
|
||
|
||
|
||
|
||
BOOL
|
||
ResolverCacheQueryCallback(
|
||
IN OUT PQUERY_BLOB pBlob
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Check cache for name.
|
||
|
||
This is callback to check appended names.
|
||
|
||
Arguments:
|
||
|
||
pBlob -- query blob
|
||
|
||
Return Value:
|
||
|
||
TRUE if name and type found.
|
||
FALSE otherwise.
|
||
|
||
--*/
|
||
{
|
||
//
|
||
// check cache for name and type
|
||
//
|
||
|
||
if ( SKIP_CACHE_LOOKUP(pBlob->Flags) )
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// copy name back to unicode
|
||
//
|
||
|
||
if ( ! Dns_NameCopyWireToUnicode(
|
||
pBlob->NameBufferWide,
|
||
pBlob->pNameWire ) )
|
||
{
|
||
DNSDBG( ANY, (
|
||
"Invalid name %s.\n",
|
||
pBlob->pNameWire ));
|
||
DNS_ASSERT( FALSE );
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// lookup in cache
|
||
//
|
||
|
||
return Cache_GetRecordsForRpc(
|
||
& pBlob->pRecords,
|
||
& pBlob->Status,
|
||
pBlob->NameBufferWide,
|
||
pBlob->wType,
|
||
pBlob->Flags
|
||
);
|
||
}
|
||
|
||
|
||
|
||
DNS_STATUS
|
||
R_ResolverQuery(
|
||
IN DNS_RPC_HANDLE Handle,
|
||
IN PWSTR pwsName,
|
||
IN WORD wType,
|
||
IN DWORD Flags,
|
||
OUT PDNS_RECORD * ppResultRecords
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Simple query to resolver.
|
||
|
||
Arguments:
|
||
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS if query successful.
|
||
ErrorCode on failure.
|
||
|
||
--*/
|
||
{
|
||
DNS_STATUS status = ERROR_SUCCESS;
|
||
PDNS_RECORD prrReturn = NULL;
|
||
QUERY_BLOB blob;
|
||
|
||
|
||
DNSLOG_F1( "DNS Caching Resolver Service - R_ResolverQuery" );
|
||
DNSLOG_F1( " Arguments:" );
|
||
DNSLOG_F2( " Name : %S", pwsName );
|
||
DNSLOG_F2( " Type : %d", wType );
|
||
DNSLOG_F2( " Flags : 0x%x", Flags );
|
||
|
||
DNSDBG( RPC, (
|
||
"\nR_ResolverQuery( %S, t=%d, f=%08x )\n",
|
||
pwsName,
|
||
wType,
|
||
Flags ));
|
||
|
||
if ( !ppResultRecords )
|
||
{
|
||
return ERROR_INVALID_PARAMETER;
|
||
}
|
||
|
||
if ( ClientThreadNotAllowedAccess() )
|
||
{
|
||
DNSLOG_F1( "R_ResolverQuery - ERROR_ACCESS_DENIED" );
|
||
status = ERROR_ACCESS_DENIED;
|
||
goto Done;
|
||
}
|
||
|
||
//
|
||
// check cache for name and type
|
||
//
|
||
// DCR: functionalize to take QUERY_BLOB
|
||
//
|
||
|
||
if ( !(Flags & DNS_QUERY_BYPASS_CACHE) )
|
||
{
|
||
if ( Cache_GetRecordsForRpc(
|
||
& prrReturn,
|
||
& status,
|
||
pwsName,
|
||
wType,
|
||
Flags ) )
|
||
{
|
||
goto Done;
|
||
}
|
||
}
|
||
|
||
//
|
||
// setup query blob
|
||
//
|
||
|
||
RtlZeroMemory(
|
||
& blob,
|
||
sizeof(blob) );
|
||
|
||
blob.pNameOrig = pwsName;
|
||
blob.wType = wType;
|
||
blob.Flags = Flags | DNSQUERY_UNICODE_OUT;
|
||
|
||
// callbacks
|
||
// - address info func for prioritize
|
||
// - cache query for intermediate names
|
||
|
||
blob.pfnGetAddrArray = GetLocalAddrArray;
|
||
blob.pfnQueryCache = ResolverCacheQueryCallback;
|
||
|
||
//
|
||
// do query
|
||
// - local lookup
|
||
// - then wire query
|
||
//
|
||
|
||
status = ResolverQuery( &blob );
|
||
|
||
if ( status != ERROR_SUCCESS &&
|
||
status != DNS_ERROR_RCODE_NAME_ERROR &&
|
||
status != DNS_INFO_NO_RECORDS )
|
||
{
|
||
goto Done;
|
||
}
|
||
prrReturn = blob.pRecords;
|
||
|
||
//
|
||
// local results
|
||
// - not cached
|
||
// but note that still going through Cache_QueryResponse()
|
||
// to get proper RPC preparation
|
||
|
||
#if 0
|
||
if ( blob.pLocalRecords )
|
||
{
|
||
}
|
||
#endif
|
||
|
||
//
|
||
// cache results
|
||
// - don't cache local lookup records
|
||
//
|
||
// DCR: should have simple "CacheResults" flag
|
||
//
|
||
// note: even local records are going through here
|
||
// now to clean them up for RPC; they are not
|
||
// cached
|
||
//
|
||
|
||
status = Cache_QueryResponse( &blob );
|
||
prrReturn = blob.pRecords;
|
||
|
||
|
||
Done:
|
||
|
||
// dump any unused query records
|
||
|
||
if ( prrReturn && status != ERROR_SUCCESS )
|
||
{
|
||
Dns_RecordListFree( prrReturn );
|
||
prrReturn = NULL;
|
||
}
|
||
|
||
// set out pointer
|
||
|
||
*ppResultRecords = prrReturn;
|
||
|
||
DNSLOG_F3(
|
||
" R_ResolverQuery - Returning status : 0x%.8X\n\t%s",
|
||
status,
|
||
Dns_StatusString(status) );
|
||
DNSLOG_F1( "" );
|
||
|
||
IF_DNSDBG( RPC )
|
||
{
|
||
DnsDbg_RecordSet(
|
||
"R_ResolverQuery Result List:",
|
||
prrReturn );
|
||
}
|
||
DNSDBG( RPC, (
|
||
"Leave R_ResolverQuery( %S, t=%d, f=%08x )\n\n"
|
||
"\tstatus = %d\n\n",
|
||
pwsName,
|
||
wType,
|
||
Flags,
|
||
status ));
|
||
|
||
return status;
|
||
}
|
||
|
||
//
|
||
// End ops.c
|
||
//
|
||
|