/*++ 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