|
|
/*++
Copyright (c) 1998, Microsoft Corporation
Module Name:
dhcpio.c
Abstract:
This module contains code for the DHCP allocator's network I/O.
Author:
Abolade Gbadegesin (aboladeg) 5-Mar-1998
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
VOID DhcpReadCompletionRoutine( 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 DHCP server UDP port.
The message read is validated and processed, and if necessary, a reply is generated and sent to the 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; PDHCP_HEADER Headerp; PDHCP_INTERFACE Interfacep;
PROFILE("DhcpReadCompletionRoutine");
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 cases (a) we repost the buffer; in case (b) we do not.
//
Interfacep = (PDHCP_INTERFACE)Bufferp->Context;
//
// First look for an error code
//
if (ErrorCode) { NhTrace( TRACE_FLAG_IO, "DhcpReadCompletionRoutine: error %d for read-context %x", ErrorCode, Bufferp->Context ); //
// See if the interface is still active
//
ACQUIRE_LOCK(Interfacep); if (!DHCP_INTERFACE_ACTIVE(Interfacep)) { RELEASE_LOCK(Interfacep); NhReleaseBuffer(Bufferp); } else { RELEASE_LOCK(Interfacep); EnterCriticalSection(&DhcpInterfaceLock); if (!DHCP_REFERENCE_INTERFACE(Interfacep)) { NhReleaseBuffer(Bufferp); } else { //
// Repost the buffer for another read operation
//
Error = NhReadDatagramSocket( &DhcpComponentReference, Bufferp->Socket, Bufferp, DhcpReadCompletionRoutine, Bufferp->Context, Bufferp->Context2 ); if (Error) { ACQUIRE_LOCK(Interfacep); DhcpDeferReadInterface(Interfacep, Bufferp->Socket); RELEASE_LOCK(Interfacep); DHCP_DEREFERENCE_INTERFACE(Interfacep); NhWarningLog( IP_AUTO_DHCP_LOG_RECEIVE_FAILED, Error, "%I", NhQueryAddressSocket(Bufferp->Socket) ); NhReleaseBuffer(Bufferp); } } LeaveCriticalSection(&DhcpInterfaceLock); } break; }
//
// Now see if the interface is operational
//
ACQUIRE_LOCK(Interfacep); if (!DHCP_INTERFACE_ACTIVE(Interfacep)) { RELEASE_LOCK(Interfacep); NhReleaseBuffer(Bufferp); NhTrace( TRACE_FLAG_IO, "DhcpReadCompletionRoutine: interface %x inactive", Interfacep ); break; } RELEASE_LOCK(Interfacep);
//
// Now look at the message
//
Headerp = (PDHCP_HEADER)Bufferp->Buffer;
switch (Headerp->Operation) {
case BOOTP_OPERATION_REQUEST: { DhcpProcessMessage( Interfacep, Bufferp ); break; }
case BOOTP_OPERATION_REPLY: { InterlockedIncrement( reinterpret_cast<LPLONG>(&DhcpStatistics.MessagesIgnored) ); NhTrace( TRACE_FLAG_IO, "DhcpReadCompletionRoutine: ignoring BOOTPREPLY" ); //
// Repost the buffer for another read operation.
//
EnterCriticalSection(&DhcpInterfaceLock); if (!DHCP_REFERENCE_INTERFACE(Interfacep)) { LeaveCriticalSection(&DhcpInterfaceLock); NhReleaseBuffer(Bufferp); } else { LeaveCriticalSection(&DhcpInterfaceLock); Error = NhReadDatagramSocket( &DhcpComponentReference, Bufferp->Socket, Bufferp, DhcpReadCompletionRoutine, Bufferp->Context, Bufferp->Context2 ); if (Error) { ACQUIRE_LOCK(Interfacep); DhcpDeferReadInterface(Interfacep, Bufferp->Socket); RELEASE_LOCK(Interfacep); DHCP_DEREFERENCE_INTERFACE(Interfacep); NhWarningLog( IP_AUTO_DHCP_LOG_RECEIVE_FAILED, Error, "%I", NhQueryAddressSocket(Bufferp->Socket) ); NhReleaseBuffer(Bufferp); } } break; }
default: { InterlockedIncrement( reinterpret_cast<LPLONG>(&DhcpStatistics.MessagesIgnored) ) ; NhTrace( TRACE_FLAG_IO, "DhcpReadCompletionRoutine: ignoring invalid BOOTP operation %d", Headerp->Operation ); NhInformationLog( IP_AUTO_DHCP_LOG_INVALID_BOOTP_OPERATION, 0, "%d", Headerp->Operation ); //
// Repost the buffer for another read operation.
//
EnterCriticalSection(&DhcpInterfaceLock); if (!DHCP_REFERENCE_INTERFACE(Interfacep)) { LeaveCriticalSection(&DhcpInterfaceLock); NhReleaseBuffer(Bufferp); } else { LeaveCriticalSection(&DhcpInterfaceLock); Error = NhReadDatagramSocket( &DhcpComponentReference, Bufferp->Socket, Bufferp, DhcpReadCompletionRoutine, Bufferp->Context, Bufferp->Context2 ); if (Error) { ACQUIRE_LOCK(Interfacep); DhcpDeferReadInterface(Interfacep, Bufferp->Socket); RELEASE_LOCK(Interfacep); DHCP_DEREFERENCE_INTERFACE(Interfacep); NhWarningLog( IP_AUTO_DHCP_LOG_RECEIVE_FAILED, Error, "%I", NhQueryAddressSocket(Bufferp->Socket) ); NhReleaseBuffer(Bufferp); } } break; } }
} while(FALSE);
DHCP_DEREFERENCE_INTERFACE(Interfacep); DEREFERENCE_DHCP();
} // DhcpReadCompletionRoutine
VOID DhcpReadServerReplyCompletionRoutine( ULONG ErrorCode, ULONG BytesTransferred, PNH_BUFFER Bufferp )
/*++
Routine Description:
This routine is invoked upon completion of a receive-operation on a socket bound to the DHCP client port, when the component is attempting to detect the presence of a DHCP server.
Arguments:
ErrorCode - system-supplied status code
BytesTransferred - system-supplied byte count
Bufferp - send buffer
Return Value:
none.
Environment:
Runs in the context of an RTUTILS.DLL worker thread upon removal of an I/O completion packet. A reference to the component will have been made on our behalf by 'NhReadDatagramSocket'.
--*/
{ ULONG Address; ULONG Error; PDHCP_INTERFACE Interfacep;
PROFILE("DhcpReadServerReplyCompletionRoutine");
Interfacep = (PDHCP_INTERFACE)Bufferp->Context;
if (ErrorCode) { NhTrace( TRACE_FLAG_IO, "DhcpReadServerReplyCompletionRoutine: error %d receiving %s", ErrorCode, INET_NTOA(Bufferp->Context2) ); NhReleaseBuffer(Bufferp); DHCP_DEREFERENCE_INTERFACE(Interfacep); DEREFERENCE_DHCP(); return; }
ACQUIRE_LOCK(Interfacep); if (!DHCP_INTERFACE_ACTIVE(Interfacep)) { RELEASE_LOCK(Interfacep); NhReleaseBuffer(Bufferp); DHCP_DEREFERENCE_INTERFACE(Interfacep); DEREFERENCE_DHCP(); return; } RELEASE_LOCK(Interfacep);
//
// Inspect the message read
//
Address = NhQueryAddressSocket(Bufferp->Socket);
if (NhIsLocalAddress(Bufferp->ReadAddress.sin_addr.s_addr)) { NhTrace( TRACE_FLAG_IO, "DhcpReadServerReplyCompletionRoutine: ignoring, from self (%s)", INET_NTOA(Address) ); } else { CHAR LocalAddress[16];
lstrcpyA(LocalAddress, INET_NTOA(Address)); NhTrace( TRACE_FLAG_IO, "DhcpReadServerReplyCompletionRoutine: %s found, disabling %d (%s)", INET_NTOA(Bufferp->ReadAddress.sin_addr), Interfacep->Index, LocalAddress );
//
// We received this from another server.
// We'll need to disable this interface.
//
DhcpDisableInterface(Interfacep->Index); NhErrorLog( IP_AUTO_DHCP_LOG_DUPLICATE_SERVER, 0, "%I%I", Bufferp->ReadAddress.sin_addr.s_addr, Address ); NhReleaseBuffer(Bufferp); DHCP_DEREFERENCE_INTERFACE(Interfacep); DEREFERENCE_DHCP(); return; }
//
// We received it from ourselves.
// Look for another server.
//
Error = NhReadDatagramSocket( &DhcpComponentReference, Bufferp->Socket, Bufferp, DhcpReadServerReplyCompletionRoutine, Bufferp->Context, Bufferp->Context2 );
if (Error) { NhTrace( TRACE_FLAG_IO, "DhcpReadServerReplyCompletionRoutine: error %d reposting %s", ErrorCode, INET_NTOA(Bufferp->Context2) ); NhReleaseBuffer(Bufferp); NhWarningLog( IP_AUTO_DHCP_LOG_DETECTION_UNAVAILABLE, Error, "%I", Address ); DHCP_DEREFERENCE_INTERFACE(Interfacep); DEREFERENCE_DHCP(); return; }
DEREFERENCE_DHCP();
} // DhcpReadServerReplyCompletionRoutine
VOID DhcpWriteClientRequestCompletionRoutine( ULONG ErrorCode, ULONG BytesTransferred, PNH_BUFFER Bufferp )
/*++
Routine Description:
This routine is invoked upon completion of a send-operation on a socket bound to the DHCP client port, when the component is attempting to detect the presence of a DHCP server.
Arguments:
ErrorCode - system-supplied status code
BytesTransferred - system-supplied byte count
Bufferp - send buffer
Return Value:
none.
Environment:
Runs in the context of an RTUTILS.DLL worker thread upon removal of an I/O completion packet. A reference to the interface will have been made on our behalf by 'DhcpWriteClientRequestMessage'. A reference to the component will have been made on our behalf by 'NhWriteDatagramSocket'.
--*/
{ PDHCP_INTERFACE Interfacep; ULONG Error;
PROFILE("DhcpWriteClientRequestCompletionRoutine");
Interfacep = (PDHCP_INTERFACE)Bufferp->Context;
if (ErrorCode) { NhTrace( TRACE_FLAG_IO, "DhcpWriteClientRequestCompletionRoutine: error %d broadcast %s", ErrorCode, INET_NTOA(Bufferp->Context2) ); NhWarningLog( IP_AUTO_DHCP_LOG_DETECTION_UNAVAILABLE, ErrorCode, "%I", NhQueryAddressSocket(Bufferp->Socket) ); NhReleaseBuffer(Bufferp); DHCP_DEREFERENCE_INTERFACE(Interfacep); DEREFERENCE_DHCP(); return; }
ACQUIRE_LOCK(Interfacep); if (!DHCP_INTERFACE_ACTIVE(Interfacep)) { RELEASE_LOCK(Interfacep); NhReleaseBuffer(Bufferp); DHCP_DEREFERENCE_INTERFACE(Interfacep); DEREFERENCE_DHCP(); return; } RELEASE_LOCK(Interfacep);
//
// Reuse the send buffer to listen for a response from the server
//
Error = NhReadDatagramSocket( &DhcpComponentReference, Bufferp->Socket, Bufferp, DhcpReadServerReplyCompletionRoutine, Bufferp->Context, Bufferp->Context2 );
if (Error) { NhTrace( TRACE_FLAG_IO, "DhcpWriteClientRequestCompletionRoutine: error %d receiving %s", ErrorCode, INET_NTOA(Bufferp->Context2) ); NhWarningLog( IP_AUTO_DHCP_LOG_DETECTION_UNAVAILABLE, Error, "%I", NhQueryAddressSocket(Bufferp->Socket) ); NhReleaseBuffer(Bufferp); DHCP_DEREFERENCE_INTERFACE(Interfacep); DEREFERENCE_DHCP(); return; }
DEREFERENCE_DHCP();
} // DhcpWriteClientRequestCompletionRoutine
VOID DhcpWriteCompletionRoutine( 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 DHCP server UDP port.
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 interface will have been made on our behalf by the code which invoked 'NhWriteDatagramSocket'. A reference to the component will have been made on our behalf within 'NhWriteDatagramSocket'.
--*/
{ PDHCP_INTERFACE Interfacep;
PROFILE("DhcpWriteCompletionRoutine");
Interfacep = (PDHCP_INTERFACE)Bufferp->Context; DHCP_DEREFERENCE_INTERFACE(Interfacep); NhReleaseBuffer(Bufferp); DEREFERENCE_DHCP();
} // DhcpWriteCompletionRoutine
|