|
|
/*++
Copyright (c) 1998, Microsoft Corporation
Module Name:
dnsio.c
Abstract:
This module contains code for the DNS allocator's network I/O completion routines.
Author:
Abolade Gbadegesin (aboladeg) 9-Mar-1998
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
#include "dnsmsg.h"
VOID DnsReadCompletionRoutine( ULONG ErrorCode, ULONG BytesTransferred, PNH_BUFFER Bufferp )
/*++
Routine Description:
This routine is invoked upon completion of a read operation on a datagram socket bound to the DNS server UDP port.
The message read is validated and processed; the processing may involve creating a query-record and forwarding the query to a server, or matching a response to an existing query-record and forwarding the response to the appropriate client.
Arguments:
ErrorCode - Win32 status code for the I/O operation
BytesTransferred - number of bytes in 'Bufferp'
Bufferp - holds data read from the datagram socket
Return Value:
none.
Environment:
Runs in the context of an RTUTILS.DLL worker-thread which has just dequeued an I/O completion packet from the common I/O completion port with which our datagram sockets are associated. A reference to the component will have been made on our behalf by 'NhReadDatagramSocket'.
--*/
{ ULONG Error; PDNS_HEADER Headerp; PDNS_INTERFACE Interfacep;
PROFILE("DnsReadCompletionRoutine");
do {
//
// There are two cases where we don't process the message;
// (a) the I/O operation failed
// (b) the interface is no longer active
// In case (a), we repost the buffer; in case (b), we do not.
//
Interfacep = (PDNS_INTERFACE)Bufferp->Context;
//
// First look for an error code
//
if (ErrorCode) {
NhTrace( TRACE_FLAG_IO, "DnsReadCompletionRoutine: error %d for read-context %x", ErrorCode, Bufferp->Context );
//
// See if the interface is still active
//
ACQUIRE_LOCK(Interfacep); if (!DNS_INTERFACE_ACTIVE(Interfacep)) { RELEASE_LOCK(Interfacep); NhReleaseBuffer(Bufferp); } else { RELEASE_LOCK(Interfacep); EnterCriticalSection(&DnsInterfaceLock); if (!DNS_REFERENCE_INTERFACE(Interfacep)) { LeaveCriticalSection(&DnsInterfaceLock); NhReleaseBuffer(Bufferp); } else { LeaveCriticalSection(&DnsInterfaceLock); //
// Repost the buffer for another read operation
//
do { Error = NhReadDatagramSocket( &DnsComponentReference, Bufferp->Socket, Bufferp, DnsReadCompletionRoutine, Bufferp->Context, Bufferp->Context2 ); //
// A connection-reset error indicates that our last
// *send* could not be delivered at its destination.
// We could hardly care less; so issue the read again,
// immediately.
//
} while (Error == WSAECONNRESET); if (Error) { ACQUIRE_LOCK(Interfacep); DnsDeferReadInterface(Interfacep, Bufferp->Socket); RELEASE_LOCK(Interfacep); DNS_DEREFERENCE_INTERFACE(Interfacep); NhWarningLog( IP_DNS_PROXY_LOG_RECEIVE_FAILED, Error, "%I", NhQueryAddressSocket(Bufferp->Socket) ); NhReleaseBuffer(Bufferp); } } }
break; }
//
// Now see if the interface is operational
//
ACQUIRE_LOCK(Interfacep); if (!DNS_INTERFACE_ACTIVE(Interfacep)) { RELEASE_LOCK(Interfacep); NhReleaseBuffer(Bufferp); NhTrace( TRACE_FLAG_IO, "DnsReadCompletionRoutine: interface %d inactive", Interfacep->Index ); break; } RELEASE_LOCK(Interfacep);
//
// Now look at the message
//
Headerp = (PDNS_HEADER)Bufferp->Buffer;
if (Headerp->IsResponse == DNS_MESSAGE_QUERY) { DnsProcessQueryMessage( Interfacep, Bufferp ); } else { DnsProcessResponseMessage( Interfacep, Bufferp ); }
} while(FALSE);
DNS_DEREFERENCE_INTERFACE(Interfacep); DEREFERENCE_DNS();
} // DnsReadCompletionRoutine
VOID DnsWriteCompletionRoutine( ULONG ErrorCode, ULONG BytesTransferred, PNH_BUFFER Bufferp )
/*++
Routine Description:
This routine is invoked upon completion of a write-operation on a datagram socket bound to the DNS server UDP port.
The write-context for all writes is a 'DNS_QUERY'. Our handling is dependent on whether the message written was a query or a response.
Upon completion of a query, we may need to do a resend if there was an error. Upon completion of a response, we delete the query-record.
Arguments:
ErrorCode - Win32 status code for the I/O operation
BytesTransferred - number of bytes in 'Bufferp'
Bufferp - holds data read from the datagram socket
Return Value:
none.
Environment:
Runs in the context of an RTUTILS.DLL worker-thread which has just dequeued an I/O completion packet from the common I/O completion port with which our datagram sockets are associated. A reference to the component will have been made on our behalf by 'NhReadDatagramSocket'.
--*/
{ ULONG Error; PDNS_HEADER Headerp; PDNS_INTERFACE Interfacep; USHORT QueryId; PDNS_QUERY Queryp; PULONG Server;
PROFILE("DnsWriteCompletionRoutine");
Interfacep = (PDNS_INTERFACE)Bufferp->Context; QueryId = (USHORT)Bufferp->Context2; Headerp = (PDNS_HEADER)Bufferp->Buffer;
ACQUIRE_LOCK(Interfacep);
//
// Obtain the query associated with the send.
//
Queryp = DnsMapResponseToQuery(Interfacep, QueryId);
if (Headerp->IsResponse == DNS_MESSAGE_RESPONSE) {
if (ErrorCode) {
//
// An error occurred sending the message to the client
//
NhTrace( TRACE_FLAG_DNS, "DnsWriteCompletionRoutine: error %d response %d interface %d", ErrorCode, Queryp ? Queryp->QueryId : -1, Interfacep->Index ); NhWarningLog( IP_DNS_PROXY_LOG_RESPONSE_FAILED, ErrorCode, "%I", NhQueryAddressSocket(Bufferp->Socket) );
} else if (Queryp && Headerp->ResponseCode == DNS_RCODE_NOERROR) {
//
// We're done with this query since it succeeded; remove it.
//
NhTrace( TRACE_FLAG_DNS, "DnsWriteCompletionRoutine: removing query %d interface %d", Queryp->QueryId, Interfacep->Index );
DnsDeleteQuery(Interfacep, Queryp); } } else {
if (!ErrorCode) { //
// No errors, so just return.
//
NhTrace( TRACE_FLAG_DNS, "DnsWriteCompletionRoutine: sent query %d interface %d", Queryp ? Queryp->QueryId : -1, Interfacep->Index ); } else { //
// The query just went out and it failed.
//
NhTrace( TRACE_FLAG_DNS, "DnsWriteCompletionRoutine: error %d for query %d interface %d", ErrorCode, Queryp ? Queryp->QueryId : -1, Interfacep->Index ); NhWarningLog( IP_DNS_PROXY_LOG_QUERY_FAILED, ErrorCode, "%I%I%I", Queryp ? Queryp->SourceAddress : -1, Bufferp->WriteAddress.sin_addr.s_addr, NhQueryAddressSocket(Bufferp->Socket) ); } }
RELEASE_LOCK(Interfacep); DNS_DEREFERENCE_INTERFACE(Interfacep); NhReleaseBuffer(Bufferp); DEREFERENCE_DNS();
} // DnsWriteCompletionRoutine
|