1671 lines
45 KiB
C
1671 lines
45 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1997-2001 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
dynreg.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Domain Name System (DNS) API
|
|||
|
|
|||
|
Dynamic registration implementation
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Ram Viswanathan (ramv) March 27 1997
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "local.h"
|
|||
|
|
|||
|
#define ENABLE_DEBUG_LOGGING 0
|
|||
|
|
|||
|
#include "logit.h"
|
|||
|
|
|||
|
|
|||
|
HANDLE hQuitEvent = NULL;
|
|||
|
HANDLE hSem = NULL;
|
|||
|
HANDLE handle[2] = { NULL, NULL} ;
|
|||
|
HANDLE hConsumerThread = NULL;
|
|||
|
BOOL g_fStopNotify = FALSE;
|
|||
|
PDYNDNSQUEUE g_pdnsQueue = NULL;
|
|||
|
PDYNDNSQUEUE g_pTimedOutQueue = NULL;
|
|||
|
DWORD g_dwQCount = 0;
|
|||
|
DWORD g_MainQueueCount = 0;
|
|||
|
|
|||
|
|
|||
|
#define MAX_QLEN 0xFFFF
|
|||
|
#define MAX_RETRIES 0x3
|
|||
|
|
|||
|
#define DNS_MAX_DHCP_SERVER_REGISTRATION_QUEUE_SIZE 250 // Arbitrary?
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Credentials for updates
|
|||
|
//
|
|||
|
|
|||
|
PSEC_WINNT_AUTH_IDENTITY_W g_pIdentityCreds = NULL;
|
|||
|
|
|||
|
//CredHandle g_CredHandle;
|
|||
|
|
|||
|
HANDLE g_UpdateCredContext = NULL;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Queue allocations in dnslib heap
|
|||
|
//
|
|||
|
|
|||
|
#define QUEUE_ALLOC_HEAP(Size) Dns_Alloc(Size)
|
|||
|
#define QUEUE_ALLOC_HEAP_ZERO(Size) Dns_AllocZero(Size)
|
|||
|
#define QUEUE_FREE_HEAP(pMem) Dns_Free(pMem)
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// local helper functions
|
|||
|
//
|
|||
|
|
|||
|
DNS_STATUS
|
|||
|
DynDnsRegisterEntries(
|
|||
|
VOID
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
DNS_STATUS
|
|||
|
DynDnsAddForward(
|
|||
|
IN OUT REGISTER_HOST_ENTRY HostAddr,
|
|||
|
IN LPWSTR pszName,
|
|||
|
IN DWORD dwTTL,
|
|||
|
IN PIP_ARRAY DnsServerList
|
|||
|
)
|
|||
|
{
|
|||
|
DNS_STATUS status = 0;
|
|||
|
DNS_RECORD record;
|
|||
|
|
|||
|
DYNREG_F1( "Inside function DynDnsAddForward" );
|
|||
|
|
|||
|
RtlZeroMemory( &record, sizeof(DNS_RECORD) );
|
|||
|
|
|||
|
record.pName = (PCHAR)pszName;
|
|||
|
record.wType = DNS_TYPE_A;
|
|||
|
record.dwTtl = dwTTL;
|
|||
|
record.wDataLength = sizeof(record.Data.A);
|
|||
|
record.Data.A.IpAddress = HostAddr.Addr.ipAddr;
|
|||
|
|
|||
|
DYNREG_F1( "DynDnsAddForward - Calling DnsReplaceRecordSet_W for A record:" );
|
|||
|
DYNREG_F2( " Name: %S", record.pName );
|
|||
|
DYNREG_F2( " Address: 0x%x", record.Data.A.IpAddress );
|
|||
|
|
|||
|
status = DnsReplaceRecordSetW(
|
|||
|
& record,
|
|||
|
DNS_UPDATE_CACHE_SECURITY_CONTEXT,
|
|||
|
NULL, // no security context
|
|||
|
(PIP4_ARRAY) DnsServerList,
|
|||
|
NULL // reserved
|
|||
|
);
|
|||
|
|
|||
|
DYNREG_F2( "DynDnsAddForward - DnsReplaceRecordSet returned status: 0%x", status );
|
|||
|
|
|||
|
return( status );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DNS_STATUS
|
|||
|
DynDnsDeleteForwards(
|
|||
|
IN PDNS_RECORD pDnsList,
|
|||
|
IN IP_ADDRESS ipAddr,
|
|||
|
IN PIP_ARRAY DnsServerList
|
|||
|
)
|
|||
|
{
|
|||
|
DNS_STATUS status = 0;
|
|||
|
PDNS_RECORD prr;
|
|||
|
DNS_RECORD record;
|
|||
|
|
|||
|
DYNREG_F1( "Inside function DynDnsDeleteForwards" );
|
|||
|
|
|||
|
//
|
|||
|
// the list pointed to by pDnsList is a set of PTR records.
|
|||
|
//
|
|||
|
|
|||
|
RtlZeroMemory( &record, sizeof(DNS_RECORD) );
|
|||
|
|
|||
|
prr = pDnsList;
|
|||
|
|
|||
|
for ( prr = pDnsList;
|
|||
|
prr;
|
|||
|
prr = prr->pNext )
|
|||
|
{
|
|||
|
if ( prr->wType != DNS_TYPE_PTR )
|
|||
|
{
|
|||
|
//
|
|||
|
// should not happen
|
|||
|
//
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// As far as the DHCP server is concerned, when timeout happens
|
|||
|
// or when client releases an address, It can update the
|
|||
|
// address lookup to clean up turds left over by say, a roaming
|
|||
|
// laptop
|
|||
|
//
|
|||
|
|
|||
|
record.pName = prr->Data.Ptr.pNameHost;
|
|||
|
record.wType = DNS_TYPE_A;
|
|||
|
record.wDataLength = sizeof(DNS_A_DATA);
|
|||
|
record.Data.A.IpAddress = ipAddr ;
|
|||
|
|
|||
|
//
|
|||
|
// make the appropriate call and return the first failed error
|
|||
|
//
|
|||
|
|
|||
|
DYNREG_F1( "DynDnsDeleteForwards - Calling ModifyRecords(Remove) for A record:" );
|
|||
|
DYNREG_F2( " Name: %S", record.pName );
|
|||
|
DYNREG_F2( " Address: 0x%x", record.Data.A.IpAddress );
|
|||
|
|
|||
|
status = DnsModifyRecordsInSet_W(
|
|||
|
NULL, // no add records
|
|||
|
& record, // delete record
|
|||
|
DNS_UPDATE_CACHE_SECURITY_CONTEXT,
|
|||
|
NULL, // no security context
|
|||
|
(PIP4_ARRAY) DnsServerList, // DNS servers
|
|||
|
NULL // reserved
|
|||
|
);
|
|||
|
|
|||
|
if ( status != ERROR_SUCCESS )
|
|||
|
{
|
|||
|
//
|
|||
|
// DCR_QUESTION: do we really want to stop on failure?
|
|||
|
break;
|
|||
|
}
|
|||
|
DYNREG_F2( "DynDnsDeleteForwards - ModifyRecords(Remove) returned status: 0%x", status );
|
|||
|
}
|
|||
|
|
|||
|
return( status );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DNS_STATUS
|
|||
|
DynDnsAddEntry(
|
|||
|
REGISTER_HOST_ENTRY HostAddr,
|
|||
|
LPWSTR pszName,
|
|||
|
DWORD dwRegisteredTTL,
|
|||
|
BOOL fDoForward,
|
|||
|
PDWORD pdwFwdErrCode,
|
|||
|
PIP_ARRAY DnsServerList
|
|||
|
)
|
|||
|
{
|
|||
|
DNS_STATUS status = 0;
|
|||
|
DWORD returnCode = 0;
|
|||
|
DNS_RECORD record;
|
|||
|
WCHAR reverseNameBuf[DNS_MAX_REVERSE_NAME_BUFFER_LENGTH];
|
|||
|
DWORD cch;
|
|||
|
|
|||
|
DYNREG_F1( "Inside function DynDnsAddEntry" );
|
|||
|
|
|||
|
*pdwFwdErrCode = 0;
|
|||
|
|
|||
|
if ( !(HostAddr.dwOptions & REGISTER_HOST_PTR) )
|
|||
|
{
|
|||
|
status = ERROR_INVALID_PARAMETER;
|
|||
|
goto Exit;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// create reverse lookup name for IP address
|
|||
|
//
|
|||
|
|
|||
|
Dns_Ip4AddressToReverseName_W(
|
|||
|
reverseNameBuf,
|
|||
|
HostAddr.Addr.ipAddr );
|
|||
|
|
|||
|
|
|||
|
if ( fDoForward )
|
|||
|
{
|
|||
|
DYNREG_F1( "DynDnsAddEntry - Calling DynDnsAddForward" );
|
|||
|
|
|||
|
//
|
|||
|
// we simply make a best case effort to do the forward add
|
|||
|
// if it fails, we simply ignore
|
|||
|
//
|
|||
|
|
|||
|
returnCode = DynDnsAddForward(
|
|||
|
HostAddr,
|
|||
|
pszName,
|
|||
|
dwRegisteredTTL,
|
|||
|
DnsServerList );
|
|||
|
|
|||
|
DYNREG_F2( "DynDnsAddEntry - DynDnsAddForward returned: 0%x",
|
|||
|
returnCode );
|
|||
|
|
|||
|
*pdwFwdErrCode = returnCode;
|
|||
|
}
|
|||
|
|
|||
|
RtlZeroMemory( &record, sizeof(DNS_RECORD) );
|
|||
|
|
|||
|
record.pName = (PDNS_NAME) reverseNameBuf;
|
|||
|
record.dwTtl = dwRegisteredTTL;
|
|||
|
record.wType = DNS_TYPE_PTR;
|
|||
|
record.Data.Ptr.pNameHost = (PDNS_NAME)pszName;
|
|||
|
record.wDataLength = sizeof(record.Data.Ptr.pNameHost);
|
|||
|
|
|||
|
DYNREG_F1( "DynDnsAddEntry - Calling DnsAddRecords_W for PTR record:" );
|
|||
|
DYNREG_F2( " Name: %S", record.pName );
|
|||
|
DYNREG_F2( " Ptr: %S", record.Data.Ptr.pNameHost );
|
|||
|
|
|||
|
status = DnsModifyRecordsInSet_W(
|
|||
|
& record, // add record
|
|||
|
NULL, // no delete records
|
|||
|
DNS_UPDATE_CACHE_SECURITY_CONTEXT,
|
|||
|
NULL, // no context handle
|
|||
|
(PIP4_ARRAY) DnsServerList, // DNS servers
|
|||
|
NULL // reserved
|
|||
|
);
|
|||
|
|
|||
|
DYNREG_F2( "DynDnsAddEntry - DnsAddRecords_W returned status: 0%x", status );
|
|||
|
|
|||
|
Exit:
|
|||
|
|
|||
|
return( status );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DNS_STATUS
|
|||
|
DynDnsDeleteEntry(
|
|||
|
REGISTER_HOST_ENTRY HostAddr,
|
|||
|
LPWSTR pszName,
|
|||
|
BOOL fDoForward,
|
|||
|
PDWORD pdwFwdErrCode,
|
|||
|
PIP_ARRAY DnsServerList
|
|||
|
)
|
|||
|
{
|
|||
|
//
|
|||
|
// Brief Synopsis of functionality:
|
|||
|
// On DoForward try deleting the forward mapping. Ignore failure
|
|||
|
// Then try deleting the PTR record. If that fails
|
|||
|
// because server is down, try again, if it fails because the
|
|||
|
// operation was refused, then dont retry
|
|||
|
//
|
|||
|
|
|||
|
DWORD status = 0;
|
|||
|
DWORD returnCode = 0;
|
|||
|
DNS_RECORD recordPtr;
|
|||
|
DNS_RECORD recordA;
|
|||
|
WCHAR reverseNameBuf[DNS_MAX_REVERSE_NAME_BUFFER_LENGTH] ;
|
|||
|
INT i;
|
|||
|
INT cch;
|
|||
|
PDNS_RECORD precord = NULL;
|
|||
|
|
|||
|
DYNREG_F1( "Inside function DynDnsDeleteEntry" );
|
|||
|
|
|||
|
*pdwFwdErrCode = 0;
|
|||
|
|
|||
|
//
|
|||
|
// build reverse lookup name for IP
|
|||
|
//
|
|||
|
|
|||
|
Dns_Ip4AddressToReverseName_W(
|
|||
|
reverseNameBuf,
|
|||
|
HostAddr.Addr.ipAddr);
|
|||
|
|
|||
|
|
|||
|
if ( fDoForward )
|
|||
|
{
|
|||
|
if ( pszName && *pszName )
|
|||
|
{
|
|||
|
//
|
|||
|
// we delete a specific forward. not all forwards as we do
|
|||
|
// when we do a query
|
|||
|
//
|
|||
|
|
|||
|
RtlZeroMemory( &recordA, sizeof(DNS_RECORD) );
|
|||
|
|
|||
|
recordA.pName = (PDNS_NAME) pszName;
|
|||
|
recordA.wType = DNS_TYPE_A;
|
|||
|
recordA.wDataLength = sizeof(DNS_A_DATA);
|
|||
|
recordA.Data.A.IpAddress = HostAddr.Addr.ipAddr;
|
|||
|
|
|||
|
DYNREG_F1( "DynDnsDeleteEntry - Calling ModifyRecords(Remove) for A record:" );
|
|||
|
DYNREG_F2( " Name: %S", recordA.pName );
|
|||
|
DYNREG_F2( " Address: 0x%x", recordA.Data.A.IpAddress );
|
|||
|
|
|||
|
//
|
|||
|
// make the appropriate call
|
|||
|
//
|
|||
|
|
|||
|
returnCode = DnsModifyRecordsInSet_W(
|
|||
|
NULL, // no add records
|
|||
|
&recordA, // delete record
|
|||
|
DNS_UPDATE_CACHE_SECURITY_CONTEXT,
|
|||
|
NULL, // no security context
|
|||
|
(PIP4_ARRAY) DnsServerList, // DNS servers
|
|||
|
NULL // reserved
|
|||
|
);
|
|||
|
|
|||
|
DYNREG_F2( "DynDnsDeleteEntry - ModifyRecords(Remove) returned status: 0%x", returnCode );
|
|||
|
|
|||
|
*pdwFwdErrCode = returnCode;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
DYNREG_F1( "DynDnsDeleteEntry - Name not specified, going to query for PTR" );
|
|||
|
|
|||
|
//
|
|||
|
//name not specified
|
|||
|
//
|
|||
|
status = DnsQuery_W(
|
|||
|
reverseNameBuf,
|
|||
|
DNS_TYPE_PTR,
|
|||
|
DNS_QUERY_BYPASS_CACHE,
|
|||
|
DnsServerList,
|
|||
|
&precord,
|
|||
|
NULL );
|
|||
|
|
|||
|
DYNREG_F2( "DynDnsDeleteEntry - DnsQuery_W returned status: 0%x", status );
|
|||
|
|
|||
|
switch ( status )
|
|||
|
{
|
|||
|
case DNS_ERROR_RCODE_NO_ERROR:
|
|||
|
|
|||
|
DYNREG_F1( "DynDnsDeleteEntry - Calling DynDnsDeleteForwards" );
|
|||
|
|
|||
|
returnCode = DynDnsDeleteForwards(
|
|||
|
precord,
|
|||
|
HostAddr.Addr.ipAddr,
|
|||
|
DnsServerList );
|
|||
|
|
|||
|
DYNREG_F2( "DynDnsDeleteEntry - DynDnsDeleteForwards returned status: 0%x", returnCode );
|
|||
|
|
|||
|
*pdwFwdErrCode = returnCode;
|
|||
|
|
|||
|
#if 0
|
|||
|
switch ( returnCode )
|
|||
|
{
|
|||
|
case DNS_ERROR_RCODE_NO_ERROR:
|
|||
|
//
|
|||
|
// we succeeded, break out
|
|||
|
//
|
|||
|
break;
|
|||
|
|
|||
|
case DNS_ERROR_RCODE_REFUSED:
|
|||
|
//
|
|||
|
// nothing can be done
|
|||
|
//
|
|||
|
break;
|
|||
|
|
|||
|
case DNS_ERROR_RCODE_SERVER_FAILURE:
|
|||
|
case DNS_ERROR_TRY_AGAIN_LATER:
|
|||
|
case ERROR_TIMEOUT:
|
|||
|
//
|
|||
|
// need to retry this again
|
|||
|
//
|
|||
|
// goto Exit; // if uncommented will force retry
|
|||
|
break;
|
|||
|
|
|||
|
case DNS_ERROR_RCODE_NOT_IMPLEMENTED:
|
|||
|
default:
|
|||
|
//
|
|||
|
// query itself failed. Nothing can be done
|
|||
|
//
|
|||
|
break;
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
//
|
|||
|
// caller takes care of each situation in turn
|
|||
|
// PTR record cannot be queried for and hence
|
|||
|
// cant be deleted
|
|||
|
//
|
|||
|
goto Exit;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// delete PTR Record
|
|||
|
//
|
|||
|
|
|||
|
if ( pszName && *pszName )
|
|||
|
{
|
|||
|
//
|
|||
|
// name is known
|
|||
|
//
|
|||
|
|
|||
|
RtlZeroMemory( &recordPtr, sizeof(DNS_RECORD) );
|
|||
|
|
|||
|
recordPtr.pName = (PDNS_NAME) reverseNameBuf;
|
|||
|
recordPtr.wType = DNS_TYPE_PTR;
|
|||
|
recordPtr.wDataLength = sizeof(DNS_PTR_DATA);
|
|||
|
recordPtr.Data.Ptr.pNameHost = (PDNS_NAME) pszName;
|
|||
|
|
|||
|
DYNREG_F1( "DynDnsDeleteEntry - Calling ModifyRecords(Remove) for PTR record:" );
|
|||
|
DYNREG_F2( " Name: %S", recordPtr.pName );
|
|||
|
DYNREG_F2( " PTR : 0%x", recordPtr.Data.Ptr.pNameHost );
|
|||
|
|
|||
|
status = DnsModifyRecordsInSet_W(
|
|||
|
NULL, // no add records
|
|||
|
&recordPtr, // delete record
|
|||
|
DNS_UPDATE_CACHE_SECURITY_CONTEXT,
|
|||
|
NULL, // no security context
|
|||
|
(PIP4_ARRAY) DnsServerList, // DNS servers
|
|||
|
NULL // reserved
|
|||
|
);
|
|||
|
|
|||
|
DYNREG_F2( "DynDnsDeleteEntry - ModifyRecords(Remove) returned status: 0%x", status );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
DYNREG_F1( "DynDnsDeleteEntry - Calling ModifyRecords(Remove) for PTR record:" );
|
|||
|
|
|||
|
if ( fDoForward && precord )
|
|||
|
{
|
|||
|
//
|
|||
|
// remove record from the earlier query that you made
|
|||
|
//
|
|||
|
|
|||
|
status = DnsModifyRecordsInSet_W(
|
|||
|
NULL, // no add records
|
|||
|
precord, // delete record from query
|
|||
|
DNS_UPDATE_CACHE_SECURITY_CONTEXT,
|
|||
|
NULL, // no security context
|
|||
|
(PIP4_ARRAY) DnsServerList,
|
|||
|
NULL // reserved
|
|||
|
);
|
|||
|
|
|||
|
DYNREG_F2( "DynDnsDeleteEntry - ModifyRecords(Remove) returned status: 0%x", status );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
//
|
|||
|
// name is NOT known
|
|||
|
//
|
|||
|
// remove ALL records of PTR type
|
|||
|
// - zero datalength indicates type delete
|
|||
|
//
|
|||
|
|
|||
|
RtlZeroMemory( &recordPtr, sizeof(DNS_RECORD) );
|
|||
|
|
|||
|
recordPtr.pName = (PDNS_NAME) reverseNameBuf;
|
|||
|
recordPtr.wType = DNS_TYPE_PTR;
|
|||
|
recordPtr.Data.Ptr.pNameHost = (PDNS_NAME) NULL;
|
|||
|
|
|||
|
DYNREG_F1( "DynDnsDeleteEntry - Calling ModifyRecords(Remove) for ANY PTR records:" );
|
|||
|
DYNREG_F2( " Name: %S", recordPtr.pName );
|
|||
|
DYNREG_F2( " PTR : 0%x", recordPtr.Data.Ptr.pNameHost );
|
|||
|
|
|||
|
status = DnsModifyRecordsInSet_W(
|
|||
|
NULL, // no add records
|
|||
|
&recordPtr, // delete record
|
|||
|
DNS_UPDATE_CACHE_SECURITY_CONTEXT,
|
|||
|
NULL, // no security context
|
|||
|
(PIP4_ARRAY) DnsServerList,
|
|||
|
NULL // reserved
|
|||
|
);
|
|||
|
|
|||
|
DYNREG_F2( "DynDnsDeleteEntry - ModifyRecords(Remove) returned status: 0%x", status );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Exit:
|
|||
|
|
|||
|
if ( precord )
|
|||
|
{
|
|||
|
// DCR: need to fix this in Win2K
|
|||
|
//
|
|||
|
//QUEUE_FREE_HEAP( precord );
|
|||
|
|
|||
|
DnsRecordListFree(
|
|||
|
precord,
|
|||
|
DnsFreeRecordListDeep );
|
|||
|
}
|
|||
|
|
|||
|
return( status );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DNS_STATUS
|
|||
|
DynDnsRegisterEntries(
|
|||
|
VOID
|
|||
|
)
|
|||
|
|
|||
|
/*
|
|||
|
DynDnsRegisterEntries()
|
|||
|
|
|||
|
This is the thread that dequeues the appropriate parameters
|
|||
|
from the main queue and starts acting upon it. This is where
|
|||
|
the bulk of the work gets done. Note that this function
|
|||
|
gets called in an endless loop
|
|||
|
|
|||
|
Briefly, this is what the function does.
|
|||
|
|
|||
|
a) Find PTR corresponding to the Host Addr passed in.
|
|||
|
b) If this is the same as the Address name passed in, then leave as is,
|
|||
|
Otherwise delete and add new PTR record.
|
|||
|
c) Follow forward and delete if possible from the forward's
|
|||
|
dns server.
|
|||
|
d) If DoForward then do what the client would've done in an NT5.0 case,
|
|||
|
i.e. Try to write a new forward lookup.
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
No arguments
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
is 0 if Success. and (DWORD)-1 if failure.
|
|||
|
|
|||
|
*/
|
|||
|
|
|||
|
{
|
|||
|
/*
|
|||
|
cases to be considered here.
|
|||
|
|
|||
|
DYNDNS_ADD_ENTRY:
|
|||
|
First query for the lookup
|
|||
|
For each of the PTR records that come back, you need to check
|
|||
|
against the one you are asked to register. If there is a match,
|
|||
|
exit with success. If not add this entry for the PTR
|
|||
|
|
|||
|
if downlevel, then we need to add this entry to forward A record
|
|||
|
as well.
|
|||
|
|
|||
|
DYNDNS_DELETE_ENTRY
|
|||
|
Delete the entry that corresponds to the pair that you have specified
|
|||
|
here. If it does not exist then do nothing about it.
|
|||
|
|
|||
|
If downlevel here, then go to the A record correspond to this and
|
|||
|
delete the forward entry as well.
|
|||
|
|
|||
|
*/
|
|||
|
|
|||
|
DWORD status, dwWaitResult;
|
|||
|
PQELEMENT pQElement = NULL;
|
|||
|
LPWSTR pszName = NULL;
|
|||
|
BOOL fDoForward;
|
|||
|
PQELEMENT pBackDependency = NULL;
|
|||
|
REGISTER_HOST_ENTRY HostAddr ;
|
|||
|
DWORD dwOperation;
|
|||
|
DWORD dwCurrTime;
|
|||
|
DWORD dwTTL;
|
|||
|
DWORD dwWaitTime = INFINITE;
|
|||
|
DWORD dwFwdAddErrCode = 0;
|
|||
|
DHCP_CALLBACK_FN pfnDhcpCallBack = NULL;
|
|||
|
PVOID pvData = NULL;
|
|||
|
|
|||
|
DYNREG_F1( "Inside function DynDnsRegisterEntries" );
|
|||
|
|
|||
|
//
|
|||
|
// call back function
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// check to see if there is any item in the timed out queue
|
|||
|
// that has the timer gone out and so you can start processing
|
|||
|
// that element right away
|
|||
|
//
|
|||
|
|
|||
|
dwCurrTime = Dns_GetCurrentTimeInSeconds();
|
|||
|
|
|||
|
if ( g_pTimedOutQueue &&
|
|||
|
g_pTimedOutQueue->pHead &&
|
|||
|
(dwCurrTime > g_pTimedOutQueue->pHead->dwRetryTime) )
|
|||
|
{
|
|||
|
//
|
|||
|
// dequeue an element from the timed out queue and process it
|
|||
|
//
|
|||
|
DYNREG_F1( "DynDnsRegisterEntries - Dequeue element from timed out list" );
|
|||
|
|
|||
|
pQElement = Dequeue( g_pTimedOutQueue );
|
|||
|
|
|||
|
if ( !pQElement )
|
|||
|
{
|
|||
|
status = ERROR_SUCCESS;
|
|||
|
goto Exit;
|
|||
|
}
|
|||
|
|
|||
|
pfnDhcpCallBack = pQElement->pfnDhcpCallBack;
|
|||
|
pvData = pQElement->pvData;
|
|||
|
|
|||
|
//
|
|||
|
// now determine if we have processed this element way too many
|
|||
|
// times
|
|||
|
//
|
|||
|
|
|||
|
if ( pQElement->dwRetryCount >= MAX_RETRIES )
|
|||
|
{
|
|||
|
DYNREG_F1( "DynDnsRegisterEntries - Element has failed too many times, calling DHCP callback function" );
|
|||
|
if (pQElement->fDoForwardOnly)
|
|||
|
{
|
|||
|
if ( pfnDhcpCallBack )
|
|||
|
(*pfnDhcpCallBack)(DNSDHCP_FWD_FAILED, pvData);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if ( pfnDhcpCallBack )
|
|||
|
(*pfnDhcpCallBack)(DNSDHCP_FAILURE, pvData);
|
|||
|
}
|
|||
|
|
|||
|
if ( pQElement->pszName )
|
|||
|
QUEUE_FREE_HEAP( pQElement->pszName );
|
|||
|
|
|||
|
QUEUE_FREE_HEAP( pQElement );
|
|||
|
status = ERROR_SUCCESS;
|
|||
|
goto Exit;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
DWORD dwRetryTime = GetEarliestRetryTime (g_pTimedOutQueue);
|
|||
|
|
|||
|
DYNREG_F1( "DynDnsRegisterEntries - No element in timed out queue." );
|
|||
|
DYNREG_F1( " Going to wait for next element." );
|
|||
|
|
|||
|
dwWaitTime = dwRetryTime != (DWORD)-1 ?
|
|||
|
(dwRetryTime > dwCurrTime? (dwRetryTime - dwCurrTime) *1000: 0)
|
|||
|
: INFINITE;
|
|||
|
|
|||
|
dwWaitResult = WaitForMultipleObjects ( 2,
|
|||
|
handle,
|
|||
|
FALSE,
|
|||
|
dwWaitTime );
|
|||
|
|
|||
|
switch ( dwWaitResult )
|
|||
|
{
|
|||
|
case WAIT_OBJECT_0:
|
|||
|
//
|
|||
|
// quit event, return and let caller take care
|
|||
|
//
|
|||
|
return(0);
|
|||
|
|
|||
|
case WAIT_OBJECT_0 + 1 :
|
|||
|
//
|
|||
|
// dequeue an element from the main queue and process
|
|||
|
//
|
|||
|
pQElement = Dequeue(g_pdnsQueue);
|
|||
|
|
|||
|
if (!pQElement)
|
|||
|
{
|
|||
|
//
|
|||
|
// should not happen, assert failure and return error
|
|||
|
//
|
|||
|
status = NO_ERROR; // Note: This actually does happen
|
|||
|
// because when Ram adds a new
|
|||
|
// entry, he may put it in the
|
|||
|
// timed out queue instead of the
|
|||
|
// g_pdnsQueue when there is a related
|
|||
|
// item pending a retry time. Assert
|
|||
|
// removed and error code changed to
|
|||
|
// to success by GlennC - 3/6/98.
|
|||
|
goto Exit;
|
|||
|
}
|
|||
|
|
|||
|
EnterCriticalSection(&g_QueueCS);
|
|||
|
g_MainQueueCount--;
|
|||
|
LeaveCriticalSection(&g_QueueCS);
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case WAIT_TIMEOUT:
|
|||
|
//
|
|||
|
// Let us exit the function this time around. We will catch the
|
|||
|
// timed out element the next time around
|
|||
|
//
|
|||
|
return ERROR_SUCCESS;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// safe to make a call since you are not dependent on anyone
|
|||
|
//
|
|||
|
|
|||
|
DYNREG_F1( "DynDnsRegisterEntries - Got an element to process!" );
|
|||
|
|
|||
|
pszName = pQElement->pszName;
|
|||
|
fDoForward = pQElement->fDoForward;
|
|||
|
HostAddr = pQElement->HostAddr;
|
|||
|
dwOperation = pQElement->dwOperation;
|
|||
|
dwTTL = pQElement->dwTTL;
|
|||
|
pfnDhcpCallBack = pQElement->pfnDhcpCallBack;
|
|||
|
pvData = pQElement->pvData;
|
|||
|
|
|||
|
if ( dwOperation == DYNDNS_ADD_ENTRY )
|
|||
|
{
|
|||
|
//
|
|||
|
// make the appropriate API call to add an entry
|
|||
|
//
|
|||
|
|
|||
|
if (pQElement->fDoForwardOnly )
|
|||
|
{
|
|||
|
DYNREG_F1( "DynDnsRegisterEntries - Calling DynDnsAddForward" );
|
|||
|
status = DynDnsAddForward ( HostAddr,
|
|||
|
pszName,
|
|||
|
dwTTL,
|
|||
|
pQElement->DnsServerList );
|
|||
|
DYNREG_F2( "DynDnsRegisterEntries - DynDnsAddForward returned status: 0%x", status );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
DYNREG_F1( "DynDnsRegisterEntries - Calling DynDnsAddEntry" );
|
|||
|
status = DynDnsAddEntry( HostAddr,
|
|||
|
pszName,
|
|||
|
dwTTL,
|
|||
|
fDoForward,
|
|||
|
&dwFwdAddErrCode,
|
|||
|
pQElement->DnsServerList );
|
|||
|
DYNREG_F2( "DynDnsRegisterEntries - DynDnsAddEntry returned status: 0%x", status );
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
//
|
|||
|
// make the appropriate call to delete here
|
|||
|
//
|
|||
|
|
|||
|
if ( pQElement->fDoForwardOnly )
|
|||
|
{
|
|||
|
DNS_RECORD record;
|
|||
|
|
|||
|
RtlZeroMemory( &record, sizeof(DNS_RECORD) );
|
|||
|
|
|||
|
record.pName = (PCHAR)pszName;
|
|||
|
record.wType = DNS_TYPE_A;
|
|||
|
record.wDataLength = sizeof(DNS_A_DATA);
|
|||
|
record.Data.A.IpAddress = HostAddr.Addr.ipAddr ;
|
|||
|
|
|||
|
status = DNS_ERROR_RCODE_NO_ERROR;
|
|||
|
|
|||
|
DYNREG_F1( "DynDnsRegisterEntries - Calling ModifyRecords(Remove)" );
|
|||
|
|
|||
|
dwFwdAddErrCode = DnsModifyRecordsInSet_W(
|
|||
|
NULL, // no add records
|
|||
|
& record, // delete record
|
|||
|
DNS_UPDATE_CACHE_SECURITY_CONTEXT,
|
|||
|
NULL, // no security context
|
|||
|
(PIP4_ARRAY) pQElement->DnsServerList,
|
|||
|
NULL // reserved
|
|||
|
);
|
|||
|
|
|||
|
DYNREG_F2( "DynDnsRegisterEntries - ModifyRecords(Remove) returned status: 0%x", dwFwdAddErrCode );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
DYNREG_F1( "DynDnsRegisterEntries - Calling DynDnsDeleteEntry" );
|
|||
|
status = DynDnsDeleteEntry( HostAddr,
|
|||
|
pszName,
|
|||
|
fDoForward,
|
|||
|
&dwFwdAddErrCode,
|
|||
|
pQElement->DnsServerList );
|
|||
|
DYNREG_F2( "DynDnsRegisterEntries - DynDnsDeleteEntry returned status: 0%x", status );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (status == DNS_ERROR_RCODE_NO_ERROR &&
|
|||
|
dwFwdAddErrCode == DNS_ERROR_RCODE_NO_ERROR )
|
|||
|
{
|
|||
|
if ( pfnDhcpCallBack )
|
|||
|
(*pfnDhcpCallBack) (DNSDHCP_SUCCESS, pvData);
|
|||
|
|
|||
|
if ( pQElement )
|
|||
|
{
|
|||
|
if ( pQElement->pszName )
|
|||
|
QUEUE_FREE_HEAP( pQElement->pszName );
|
|||
|
|
|||
|
QUEUE_FREE_HEAP( pQElement );
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
else if ( status == DNS_ERROR_RCODE_NO_ERROR &&
|
|||
|
dwFwdAddErrCode != DNS_ERROR_RCODE_NO_ERROR )
|
|||
|
{
|
|||
|
//
|
|||
|
// adding reverse succeeded but adding forward failed
|
|||
|
//
|
|||
|
|
|||
|
DWORD dwCurrTime = Dns_GetCurrentTimeInSeconds();
|
|||
|
|
|||
|
pQElement->fDoForwardOnly = TRUE;
|
|||
|
|
|||
|
if ( pQElement->dwRetryCount >= MAX_RETRIES )
|
|||
|
{
|
|||
|
//
|
|||
|
// clean up pQElement and stop retrying
|
|||
|
//
|
|||
|
if ( pfnDhcpCallBack )
|
|||
|
(*pfnDhcpCallBack)(DNSDHCP_FWD_FAILED, pvData);
|
|||
|
|
|||
|
if ( pQElement->pszName )
|
|||
|
QUEUE_FREE_HEAP( pQElement->pszName );
|
|||
|
|
|||
|
QUEUE_FREE_HEAP( pQElement );
|
|||
|
|
|||
|
status = ERROR_SUCCESS;
|
|||
|
goto Exit;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// we may need to retry this guy later
|
|||
|
//
|
|||
|
|
|||
|
switch ( dwFwdAddErrCode )
|
|||
|
{
|
|||
|
case DNS_ERROR_RCODE_SERVER_FAILURE:
|
|||
|
|
|||
|
status = AddToTimedOutQueue(
|
|||
|
pQElement,
|
|||
|
g_pTimedOutQueue,
|
|||
|
dwCurrTime + RETRY_TIME_SERVER_FAILURE );
|
|||
|
break;
|
|||
|
|
|||
|
case DNS_ERROR_TRY_AGAIN_LATER:
|
|||
|
|
|||
|
status = AddToTimedOutQueue(
|
|||
|
pQElement,
|
|||
|
g_pTimedOutQueue,
|
|||
|
dwCurrTime + RETRY_TIME_TRY_AGAIN_LATER );
|
|||
|
break;
|
|||
|
|
|||
|
case ERROR_TIMEOUT:
|
|||
|
|
|||
|
status = AddToTimedOutQueue(
|
|||
|
pQElement,
|
|||
|
g_pTimedOutQueue,
|
|||
|
dwCurrTime + RETRY_TIME_TIMEOUT );
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
|
|||
|
//
|
|||
|
// different kind of error on attempting to add forward.
|
|||
|
// like connection refused etc.
|
|||
|
// call the callback to indicate that you failed on
|
|||
|
// forward only
|
|||
|
|
|||
|
if ( pQElement )
|
|||
|
{
|
|||
|
if ( pQElement->pszName )
|
|||
|
QUEUE_FREE_HEAP( pQElement->pszName );
|
|||
|
|
|||
|
QUEUE_FREE_HEAP( pQElement );
|
|||
|
}
|
|||
|
|
|||
|
if ( pfnDhcpCallBack )
|
|||
|
(*pfnDhcpCallBack)(DNSDHCP_FWD_FAILED, pvData);
|
|||
|
}
|
|||
|
}
|
|||
|
else if ( status != DNS_ERROR_RCODE_NO_ERROR &&
|
|||
|
dwFwdAddErrCode == DNS_ERROR_RCODE_NO_ERROR )
|
|||
|
{
|
|||
|
//
|
|||
|
// adding forward succeeded but adding reverse failed
|
|||
|
//
|
|||
|
|
|||
|
DWORD dwCurrTime = Dns_GetCurrentTimeInSeconds();
|
|||
|
|
|||
|
pQElement->fDoForwardOnly = FALSE;
|
|||
|
pQElement->fDoForward = FALSE;
|
|||
|
|
|||
|
if ( pQElement->dwRetryCount >= MAX_RETRIES )
|
|||
|
{
|
|||
|
//
|
|||
|
// clean up pQElement and stop retrying
|
|||
|
//
|
|||
|
if ( pfnDhcpCallBack )
|
|||
|
(*pfnDhcpCallBack)(DNSDHCP_FAILURE, pvData);
|
|||
|
|
|||
|
if ( pQElement->pszName )
|
|||
|
QUEUE_FREE_HEAP( pQElement->pszName );
|
|||
|
|
|||
|
QUEUE_FREE_HEAP( pQElement );
|
|||
|
|
|||
|
status = ERROR_SUCCESS;
|
|||
|
goto Exit;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// we may need to retry this guy later
|
|||
|
//
|
|||
|
|
|||
|
switch ( status )
|
|||
|
{
|
|||
|
case DNS_ERROR_RCODE_SERVER_FAILURE:
|
|||
|
|
|||
|
status = AddToTimedOutQueue(
|
|||
|
pQElement,
|
|||
|
g_pTimedOutQueue,
|
|||
|
dwCurrTime + RETRY_TIME_SERVER_FAILURE );
|
|||
|
break;
|
|||
|
|
|||
|
case DNS_ERROR_TRY_AGAIN_LATER:
|
|||
|
|
|||
|
status = AddToTimedOutQueue(
|
|||
|
pQElement,
|
|||
|
g_pTimedOutQueue,
|
|||
|
dwCurrTime + RETRY_TIME_TRY_AGAIN_LATER );
|
|||
|
break;
|
|||
|
|
|||
|
case ERROR_TIMEOUT:
|
|||
|
|
|||
|
status = AddToTimedOutQueue(
|
|||
|
pQElement,
|
|||
|
g_pTimedOutQueue,
|
|||
|
dwCurrTime + RETRY_TIME_TIMEOUT );
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
|
|||
|
//
|
|||
|
// different kind of error on attempting to add forward.
|
|||
|
// like connection refused etc.
|
|||
|
// call the callback to indicate that you at least succeeded
|
|||
|
// with the forward registration
|
|||
|
|
|||
|
if ( pQElement )
|
|||
|
{
|
|||
|
if ( pQElement->pszName )
|
|||
|
QUEUE_FREE_HEAP( pQElement->pszName );
|
|||
|
|
|||
|
QUEUE_FREE_HEAP( pQElement );
|
|||
|
}
|
|||
|
|
|||
|
if ( pfnDhcpCallBack )
|
|||
|
(*pfnDhcpCallBack)(DNSDHCP_FAILURE, pvData);
|
|||
|
}
|
|||
|
}
|
|||
|
else if (status == DNS_ERROR_RCODE_SERVER_FAILURE ||
|
|||
|
status == DNS_ERROR_TRY_AGAIN_LATER ||
|
|||
|
status == ERROR_TIMEOUT )
|
|||
|
{
|
|||
|
//
|
|||
|
// we need to retry this guy later
|
|||
|
//
|
|||
|
DWORD dwCurrTime = Dns_GetCurrentTimeInSeconds();
|
|||
|
|
|||
|
switch (status)
|
|||
|
{
|
|||
|
case DNS_ERROR_RCODE_SERVER_FAILURE:
|
|||
|
|
|||
|
status = AddToTimedOutQueue(
|
|||
|
pQElement,
|
|||
|
g_pTimedOutQueue,
|
|||
|
dwCurrTime + RETRY_TIME_SERVER_FAILURE );
|
|||
|
break;
|
|||
|
|
|||
|
case DNS_ERROR_TRY_AGAIN_LATER:
|
|||
|
|
|||
|
status = AddToTimedOutQueue(
|
|||
|
pQElement,
|
|||
|
g_pTimedOutQueue,
|
|||
|
dwCurrTime + RETRY_TIME_TRY_AGAIN_LATER );
|
|||
|
break;
|
|||
|
|
|||
|
case ERROR_TIMEOUT:
|
|||
|
|
|||
|
status = AddToTimedOutQueue(
|
|||
|
pQElement,
|
|||
|
g_pTimedOutQueue,
|
|||
|
dwCurrTime + RETRY_TIME_TIMEOUT );
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
//
|
|||
|
// a different kind of error, really nothing can be done
|
|||
|
// free memory and get the hell out
|
|||
|
// call the callback to say that registration failed
|
|||
|
//
|
|||
|
|
|||
|
if ( pQElement )
|
|||
|
{
|
|||
|
if ( pQElement->pszName )
|
|||
|
QUEUE_FREE_HEAP( pQElement->pszName );
|
|||
|
|
|||
|
QUEUE_FREE_HEAP( pQElement );
|
|||
|
}
|
|||
|
|
|||
|
if ( pfnDhcpCallBack )
|
|||
|
(*pfnDhcpCallBack)(DNSDHCP_FAILURE, pvData);
|
|||
|
}
|
|||
|
|
|||
|
Exit:
|
|||
|
|
|||
|
return( status);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Main registration thread
|
|||
|
//
|
|||
|
|
|||
|
VOID
|
|||
|
DynDnsConsumerThread(
|
|||
|
VOID
|
|||
|
)
|
|||
|
{
|
|||
|
DWORD dwRetval;
|
|||
|
|
|||
|
DYNREG_F1( "Inside function DynDnsConsumerThread" );
|
|||
|
|
|||
|
while ( ! g_fStopNotify )
|
|||
|
{
|
|||
|
dwRetval = DynDnsRegisterEntries();
|
|||
|
|
|||
|
if ( !dwRetval )
|
|||
|
{
|
|||
|
//
|
|||
|
// Ram note: get Munil/Ramesh to implement call back function
|
|||
|
//
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// you have been asked to exit
|
|||
|
//
|
|||
|
|
|||
|
FreeQueue( g_pdnsQueue );
|
|||
|
g_pdnsQueue = NULL;
|
|||
|
|
|||
|
EnterCriticalSection(&g_QueueCS);
|
|||
|
g_MainQueueCount = 0;
|
|||
|
LeaveCriticalSection(&g_QueueCS);
|
|||
|
|
|||
|
FreeQueue( g_pTimedOutQueue );
|
|||
|
g_pTimedOutQueue = NULL;
|
|||
|
ExitThread(0); // This sets the handle in the waitforsingleobject for
|
|||
|
|
|||
|
//
|
|||
|
// the termination function
|
|||
|
//
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Init\Cleanup routines
|
|||
|
//
|
|||
|
|
|||
|
VOID
|
|||
|
CommonDynRegCleanup(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Common cleanup between failed init and terminate.
|
|||
|
|
|||
|
Function exists just to kill off common code.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
//
|
|||
|
// common cleanup
|
|||
|
// - semaphore
|
|||
|
// - event
|
|||
|
// - security credential info
|
|||
|
|
|||
|
if ( hSem )
|
|||
|
{
|
|||
|
CloseHandle( hSem );
|
|||
|
hSem = NULL;
|
|||
|
}
|
|||
|
|
|||
|
if ( hQuitEvent )
|
|||
|
{
|
|||
|
CloseHandle( hQuitEvent );
|
|||
|
hQuitEvent = NULL;
|
|||
|
}
|
|||
|
|
|||
|
if ( g_pIdentityCreds )
|
|||
|
{
|
|||
|
Dns_FreeAuthIdentityCredentials( g_pIdentityCreds );
|
|||
|
g_pIdentityCreds = NULL;
|
|||
|
}
|
|||
|
|
|||
|
if ( g_UpdateCredContext )
|
|||
|
{
|
|||
|
DnsReleaseContextHandle( g_UpdateCredContext );
|
|||
|
g_UpdateCredContext = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DNS_STATUS
|
|||
|
WINAPI
|
|||
|
DnsDhcpSrvRegisterInitialize(
|
|||
|
IN PDNS_CREDENTIALS pCredentials
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Initialize DHCP server DNS registration.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pCredentials -- credentials to do registrations under (if any)
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
DNS or Win32 error code.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
INT i;
|
|||
|
DWORD threadId;
|
|||
|
DNS_STATUS status;
|
|||
|
|
|||
|
//
|
|||
|
// init globals
|
|||
|
// - also init debug logging
|
|||
|
//
|
|||
|
|
|||
|
DYNREG_INIT();
|
|||
|
|
|||
|
DNS_ASSERT(!hQuitEvent && !hSem);
|
|||
|
|
|||
|
g_fStopNotify = FALSE;
|
|||
|
|
|||
|
if ( !( hQuitEvent = CreateEvent( NULL, TRUE, FALSE, NULL ) ) )
|
|||
|
{
|
|||
|
status = GetLastError();
|
|||
|
goto Exit;
|
|||
|
}
|
|||
|
|
|||
|
if ( ! ( hSem = CreateSemaphore( NULL, 0, MAX_QLEN, NULL ) ) )
|
|||
|
{
|
|||
|
status = GetLastError();
|
|||
|
goto Exit;
|
|||
|
}
|
|||
|
|
|||
|
handle[0]= hQuitEvent;
|
|||
|
handle[1]= hSem;
|
|||
|
|
|||
|
Dns_InitializeSecondsTimer();
|
|||
|
|
|||
|
status = InitializeQueues( &g_pdnsQueue, &g_pTimedOutQueue );
|
|||
|
if ( status != NO_ERROR )
|
|||
|
{
|
|||
|
g_pdnsQueue = NULL;
|
|||
|
g_pTimedOutQueue = NULL;
|
|||
|
goto Exit;
|
|||
|
}
|
|||
|
|
|||
|
EnterCriticalSection(&g_QueueCS);
|
|||
|
g_MainQueueCount = 0;
|
|||
|
LeaveCriticalSection(&g_QueueCS);
|
|||
|
|
|||
|
//
|
|||
|
// have creds?
|
|||
|
// - create global credentials
|
|||
|
// - acquire a valid SSPI handle using these creds
|
|||
|
//
|
|||
|
// DCR: global cred handle not MT safe
|
|||
|
// here we are in the DHCP server process and don't have
|
|||
|
// any reason to use another update context; but if
|
|||
|
// shared with some other service this breaks
|
|||
|
//
|
|||
|
// fix should be to have separate
|
|||
|
// - creds
|
|||
|
// - cred handle
|
|||
|
// that is kept here (not cached) and pushed down
|
|||
|
// on each update call
|
|||
|
//
|
|||
|
|
|||
|
if ( pCredentials )
|
|||
|
{
|
|||
|
DNS_ASSERT( g_pIdentityCreds == NULL );
|
|||
|
|
|||
|
g_pIdentityCreds = Dns_AllocateCredentials(
|
|||
|
pCredentials->pUserName,
|
|||
|
pCredentials->pDomain,
|
|||
|
pCredentials->pPassword );
|
|||
|
if ( !g_pIdentityCreds )
|
|||
|
{
|
|||
|
status = DNS_ERROR_NO_MEMORY;
|
|||
|
goto Exit;
|
|||
|
}
|
|||
|
|
|||
|
// DCR: this won't work if creds will expire
|
|||
|
// but it seems like they autorefresh
|
|||
|
|
|||
|
status = Dns_StartSecurity(
|
|||
|
FALSE // not process attach
|
|||
|
);
|
|||
|
if ( status != NO_ERROR )
|
|||
|
{
|
|||
|
status = ERROR_CANNOT_IMPERSONATE;
|
|||
|
goto Exit;
|
|||
|
}
|
|||
|
|
|||
|
status = Dns_RefreshSSpiCredentialsHandle(
|
|||
|
FALSE, // client
|
|||
|
(PCHAR) g_pIdentityCreds // creds
|
|||
|
);
|
|||
|
if ( status != NO_ERROR )
|
|||
|
{
|
|||
|
status = ERROR_CANNOT_IMPERSONATE;
|
|||
|
goto Exit;
|
|||
|
}
|
|||
|
#if 0
|
|||
|
DNS_ASSERT( g_UpdateCredContext == NULL );
|
|||
|
|
|||
|
status = DnsAcquireContextHandle_W(
|
|||
|
0, // flags
|
|||
|
g_pIdentityCreds, // creds
|
|||
|
& g_UpdateCredContext // set handle
|
|||
|
);
|
|||
|
if ( status != NO_ERROR )
|
|||
|
{
|
|||
|
goto Exit;
|
|||
|
}
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// fire up registration thread
|
|||
|
// - pass creds as start param
|
|||
|
// - if thread start fails, free creds
|
|||
|
//
|
|||
|
|
|||
|
hConsumerThread = CreateThread(
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
(LPTHREAD_START_ROUTINE)DynDnsConsumerThread,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
&threadId );
|
|||
|
|
|||
|
if ( hConsumerThread == NULL )
|
|||
|
{
|
|||
|
status = GetLastError();
|
|||
|
goto Exit;
|
|||
|
}
|
|||
|
|
|||
|
Exit:
|
|||
|
|
|||
|
//
|
|||
|
// if failed, clean up globals
|
|||
|
//
|
|||
|
|
|||
|
if ( status != NO_ERROR &&
|
|||
|
status != ERROR_CANNOT_IMPERSONATE )
|
|||
|
{
|
|||
|
if ( g_pdnsQueue )
|
|||
|
{
|
|||
|
FreeQueue( g_pdnsQueue );
|
|||
|
g_pdnsQueue = NULL;
|
|||
|
}
|
|||
|
|
|||
|
if ( g_pTimedOutQueue )
|
|||
|
{
|
|||
|
FreeQueue(g_pTimedOutQueue);
|
|||
|
g_pTimedOutQueue = NULL;
|
|||
|
}
|
|||
|
|
|||
|
EnterCriticalSection(&g_QueueCS);
|
|||
|
g_MainQueueCount = 0;
|
|||
|
LeaveCriticalSection(&g_QueueCS);
|
|||
|
|
|||
|
// global cleanup
|
|||
|
// - shared between failure case here and term function
|
|||
|
|
|||
|
CommonDynRegCleanup();
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
DNS_STATUS
|
|||
|
WINAPI
|
|||
|
DnsDhcpSrvRegisterInit(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Backward compatibility stub to above function.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
DNS or Win32 error code.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
return DnsDhcpSrvRegisterInitialize( NULL );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DNS_STATUS
|
|||
|
WINAPI
|
|||
|
DnsDhcpSrvRegisterTerm(
|
|||
|
VOID
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Initialization routine each process should call exactly on exit after
|
|||
|
using DnsDhcpSrvRegisterHostAddrs. This will signal to us that if our
|
|||
|
thread is still trying to talk to a server, we'll stop trying.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
DNS or Win32 error code.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
BOOL fRet;
|
|||
|
DWORD dwRetval = ERROR_SUCCESS;
|
|||
|
DWORD dwWaitResult;
|
|||
|
|
|||
|
DYNREG_F1( "Inside function DnsDhcpSrvRegisterTerm" );
|
|||
|
|
|||
|
//
|
|||
|
// Need to notify Consumer Thread that he is getting thrown
|
|||
|
// out and clean up after him. Send an event after him
|
|||
|
//
|
|||
|
|
|||
|
g_fStopNotify = TRUE;
|
|||
|
|
|||
|
fRet = SetEvent( hQuitEvent );
|
|||
|
|
|||
|
dwWaitResult = WaitForSingleObject( hConsumerThread, INFINITE );
|
|||
|
|
|||
|
switch (dwWaitResult)
|
|||
|
{
|
|||
|
case WAIT_OBJECT_0:
|
|||
|
//
|
|||
|
// client thread terminated
|
|||
|
//
|
|||
|
CloseHandle(hConsumerThread);
|
|||
|
hConsumerThread = NULL;
|
|||
|
break;
|
|||
|
|
|||
|
case WAIT_TIMEOUT:
|
|||
|
if ( hConsumerThread )
|
|||
|
{
|
|||
|
//
|
|||
|
// Why hasn't this thread stopped?
|
|||
|
//
|
|||
|
DYNREG_F1( "DNSAPI: DHCP Server DNS registration thread won't stop!" );
|
|||
|
DNS_ASSERT( FALSE );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// cleanup globals
|
|||
|
// - event
|
|||
|
// - semaphore
|
|||
|
// - update security cred info
|
|||
|
//
|
|||
|
|
|||
|
CommonDynRegCleanup();
|
|||
|
|
|||
|
//
|
|||
|
// Blow away any cached security context handles
|
|||
|
//
|
|||
|
// DCR: security context dump is not multi-service safe
|
|||
|
// should have this cleanup just the context's associated
|
|||
|
// with DHCP server service;
|
|||
|
// either need some key or use cred handle
|
|||
|
//
|
|||
|
|
|||
|
Dns_TimeoutSecurityContextList( TRUE );
|
|||
|
|
|||
|
return dwRetval;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DNS_STATUS
|
|||
|
WINAPI
|
|||
|
DnsDhcpSrvRegisterHostName(
|
|||
|
IN REGISTER_HOST_ENTRY HostAddr,
|
|||
|
IN PWSTR pwsName,
|
|||
|
IN DWORD dwTTL,
|
|||
|
IN DWORD dwFlags, // An entry you want to blow away
|
|||
|
IN DHCP_CALLBACK_FN pfnDhcpCallBack,
|
|||
|
IN PVOID pvData,
|
|||
|
IN PIP_ADDRESS pipDnsServerList,
|
|||
|
IN DWORD dwDnsServerCount
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
DnsDhcpSrvRegisterHostName()
|
|||
|
|
|||
|
The main DHCP registration thread calls this function each time a
|
|||
|
registration needs to be done.
|
|||
|
|
|||
|
Brief Synopsis of the working of this function
|
|||
|
|
|||
|
This function creates a queue object of the type given in queue.c
|
|||
|
and enqueues the appropriate object after grabbing hold of the
|
|||
|
critical section.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
HostAddr --- The Host Addr you wish to register
|
|||
|
pszName --- The Host Name to be associated with the address
|
|||
|
dwTTL --- Time to Live.
|
|||
|
dwOperation -- The following flags are valid
|
|||
|
|
|||
|
DYNDNS_DELETE_ENTRY -- Delete the entry being referred to.
|
|||
|
DYNDNS_ADD_ENTRY -- Register the new entry.
|
|||
|
DYNDNS_REG_FORWARD -- Register the forward as well
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
is 0 if Success. and (DWORD)-1 if failure.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PQELEMENT pQElement = NULL;
|
|||
|
DWORD status = ERROR_SUCCESS;
|
|||
|
BOOL fSem = FALSE;
|
|||
|
BOOL fRegForward = dwFlags & DYNDNS_REG_FORWARD ? TRUE: FALSE ;
|
|||
|
|
|||
|
DYNREG_F1( "Inside function DnsDhcpSrvRegisterHostName_W" );
|
|||
|
|
|||
|
// RAMNOTE: parameter checking on queuing
|
|||
|
|
|||
|
if ( g_fStopNotify ||
|
|||
|
! g_pTimedOutQueue ||
|
|||
|
! g_pdnsQueue )
|
|||
|
{
|
|||
|
DYNREG_F1( "g_fStopNotify || ! g_pTimedOutQueue || ! g_pdnsQueue" );
|
|||
|
DYNREG_F1( "DnsDhcpSrvRegisterHostName_W - Returning ERROR_INVALID_PARAMETER" );
|
|||
|
return ERROR_INVALID_PARAMETER;
|
|||
|
}
|
|||
|
|
|||
|
if ( !(dwFlags & DYNDNS_DELETE_ENTRY) && ( !pwsName || !*pwsName ) )
|
|||
|
{
|
|||
|
DYNREG_F1( "!(dwFlags & DYNDNS_DELETE_ENTRY) && ( !pwsName || !*pwsName )" );
|
|||
|
DYNREG_F1( "DnsDhcpSrvRegisterHostName_W - Returning ERROR_INVALID_PARAMETER" );
|
|||
|
//
|
|||
|
// Null parameter for name can be specified only when operation
|
|||
|
// is to do a delete
|
|||
|
//
|
|||
|
return ERROR_INVALID_PARAMETER;
|
|||
|
}
|
|||
|
|
|||
|
if ( ! (dwFlags & DYNDNS_ADD_ENTRY || dwFlags & DYNDNS_DELETE_ENTRY ) )
|
|||
|
{
|
|||
|
DYNREG_F1( "! (dwFlags & DYNDNS_ADD_ENTRY || dwFlags & DYNDNS_DELETE_ENTRY )" );
|
|||
|
DYNREG_F1( "DnsDhcpSrvRegisterHostName_W - Returning ERROR_INVALID_PARAMETER" );
|
|||
|
return ERROR_INVALID_PARAMETER;
|
|||
|
}
|
|||
|
|
|||
|
if ( (dwFlags & DYNDNS_DELETE_ENTRY) && (dwFlags & DYNDNS_ADD_ENTRY) )
|
|||
|
{
|
|||
|
DYNREG_F1( "(dwFlags & DYNDNS_DELETE_ENTRY) && (dwFlags & DYNDNS_ADD_ENTRY)" );
|
|||
|
DYNREG_F1( "DnsDhcpSrvRegisterHostName_W - Returning ERROR_INVALID_PARAMETER" );
|
|||
|
//
|
|||
|
// you cant ask me to both add and delete an entry
|
|||
|
//
|
|||
|
return ERROR_INVALID_PARAMETER;
|
|||
|
}
|
|||
|
|
|||
|
if ( ! (HostAddr.dwOptions & REGISTER_HOST_PTR) )
|
|||
|
{
|
|||
|
DYNREG_F1( "! (HostAddr.dwOptions & REGISTER_HOST_PTR)" );
|
|||
|
DYNREG_F1( "DnsDhcpSrvRegisterHostName_W - Returning ERROR_INVALID_PARAMETER" );
|
|||
|
return ERROR_INVALID_PARAMETER;
|
|||
|
}
|
|||
|
|
|||
|
if ( g_MainQueueCount > DNS_MAX_DHCP_SERVER_REGISTRATION_QUEUE_SIZE )
|
|||
|
{
|
|||
|
return DNS_ERROR_TRY_AGAIN_LATER;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// create a queue element.
|
|||
|
//
|
|||
|
|
|||
|
pQElement = (PQELEMENT) QUEUE_ALLOC_HEAP_ZERO(sizeof(QELEMENT) );
|
|||
|
|
|||
|
if ( !pQElement )
|
|||
|
{
|
|||
|
DYNREG_F1( "DnsDhcpSrvRegisterHostName_W - Failed to create element!" );
|
|||
|
status = DNS_ERROR_NO_MEMORY;
|
|||
|
goto Exit;
|
|||
|
}
|
|||
|
|
|||
|
memcpy(&(pQElement->HostAddr), &HostAddr, sizeof(REGISTER_HOST_ENTRY));
|
|||
|
|
|||
|
pQElement->pszName = NULL;
|
|||
|
|
|||
|
if ( pwsName )
|
|||
|
{
|
|||
|
pQElement->pszName = (LPWSTR) QUEUE_ALLOC_HEAP_ZERO(wcslen(pwsName)*2+ 2 );
|
|||
|
|
|||
|
if ( !pQElement->pszName )
|
|||
|
{
|
|||
|
DYNREG_F1( "DnsDhcpSrvRegisterHostName_W - Failed to allocate name buffer!" );
|
|||
|
status = DNS_ERROR_NO_MEMORY;
|
|||
|
goto Exit;
|
|||
|
}
|
|||
|
|
|||
|
wcscpy(pQElement->pszName, pwsName);
|
|||
|
}
|
|||
|
|
|||
|
if ( dwDnsServerCount )
|
|||
|
{
|
|||
|
pQElement->DnsServerList = Dns_BuildIpArray( dwDnsServerCount,
|
|||
|
pipDnsServerList );
|
|||
|
|
|||
|
if ( !pQElement->DnsServerList )
|
|||
|
{
|
|||
|
status = DNS_ERROR_NO_MEMORY;
|
|||
|
goto Exit;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
pQElement->dwTTL = dwTTL;
|
|||
|
pQElement->fDoForward = fRegForward;
|
|||
|
|
|||
|
//
|
|||
|
// callback function
|
|||
|
//
|
|||
|
|
|||
|
pQElement->pfnDhcpCallBack = pfnDhcpCallBack;
|
|||
|
pQElement->pvData = pvData; // parameter to callback function
|
|||
|
|
|||
|
if (dwFlags & DYNDNS_ADD_ENTRY)
|
|||
|
pQElement->dwOperation = DYNDNS_ADD_ENTRY;
|
|||
|
else
|
|||
|
pQElement->dwOperation = DYNDNS_DELETE_ENTRY;
|
|||
|
|
|||
|
//
|
|||
|
// Set all the other fields to NULLs
|
|||
|
//
|
|||
|
|
|||
|
pQElement->dwRetryTime = 0;
|
|||
|
pQElement->pFLink = NULL;
|
|||
|
pQElement->pBLink = NULL;
|
|||
|
pQElement ->fDoForwardOnly = FALSE;
|
|||
|
|
|||
|
//
|
|||
|
// put this element in the queue
|
|||
|
//
|
|||
|
|
|||
|
DYNREG_F1( "DnsDhcpSrvRegisterHostName_W - Put queue element in list" );
|
|||
|
|
|||
|
status = Enqueue ( pQElement, g_pdnsQueue, g_pTimedOutQueue);
|
|||
|
|
|||
|
//
|
|||
|
// FYI: Count of main queue elements is incremented inside Enqueue()
|
|||
|
//
|
|||
|
|
|||
|
if (status)
|
|||
|
{
|
|||
|
DYNREG_F1( "DnsDhcpSrvRegisterHostName_W - Failed to queue element in list!" );
|
|||
|
goto Exit;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Signal the semaphore the consumer may be waiting on
|
|||
|
//
|
|||
|
|
|||
|
fSem = ReleaseSemaphore( hSem,
|
|||
|
1,
|
|||
|
&g_dwQCount );
|
|||
|
|
|||
|
if ( !fSem )
|
|||
|
{
|
|||
|
DNS_ASSERT( fSem ); // assert and say that something weird happened
|
|||
|
}
|
|||
|
|
|||
|
return(status);
|
|||
|
|
|||
|
Exit:
|
|||
|
|
|||
|
if ( status )
|
|||
|
{
|
|||
|
//
|
|||
|
// something failed. Free all alloc'd memory
|
|||
|
//
|
|||
|
|
|||
|
if ( pQElement )
|
|||
|
{
|
|||
|
if ( pQElement->pszName )
|
|||
|
QUEUE_FREE_HEAP( pQElement->pszName );
|
|||
|
|
|||
|
QUEUE_FREE_HEAP( pQElement );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return( status );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// End dynreg.c
|
|||
|
//
|