899 lines
19 KiB
C
899 lines
19 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1996-2000 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
update.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Domain Name System (DNS) Library
|
|||
|
|
|||
|
Update client routines.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Jim Gilroy (jamesg) October, 1996
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
User Mode - Win32
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
|
|||
|
#include "local.h"
|
|||
|
|
|||
|
//
|
|||
|
// Update Timeouts
|
|||
|
//
|
|||
|
// note, max is a little longer than might be expected as DNS server
|
|||
|
// may have to contact primary and wait for primary to do update (inc.
|
|||
|
// disk access) then response
|
|||
|
//
|
|||
|
|
|||
|
#define INITIAL_UPDATE_TIMEOUT (4) // 4 seconds
|
|||
|
#define MAX_UPDATE_TIMEOUT (60) // 60 seconds
|
|||
|
|
|||
|
|
|||
|
|
|||
|
PCHAR
|
|||
|
Dns_WriteNoDataUpdateRecordToMessage(
|
|||
|
IN PCHAR pch,
|
|||
|
IN PCHAR pchStop,
|
|||
|
IN WORD wClass,
|
|||
|
IN WORD wType
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
No data RR cases:
|
|||
|
|
|||
|
This includes prereqs and deletes except for specific record cases.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pch - ptr to next byte in packet buffer
|
|||
|
|
|||
|
pchStop - end of packet buffer
|
|||
|
|
|||
|
wClass - class
|
|||
|
|
|||
|
wType - desired RR type
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Ptr to next postion in buffer, if successful.
|
|||
|
NULL on error.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PDNS_WIRE_RECORD pdnsRR;
|
|||
|
|
|||
|
DNSDBG( WRITE, (
|
|||
|
"Writing update RR to packet buffer at %p.\n",
|
|||
|
pch ));
|
|||
|
|
|||
|
//
|
|||
|
// out of space
|
|||
|
//
|
|||
|
|
|||
|
pdnsRR = (PDNS_WIRE_RECORD) pch;
|
|||
|
pch += sizeof( DNS_WIRE_RECORD );
|
|||
|
if ( pch >= pchStop )
|
|||
|
{
|
|||
|
DNS_PRINT(( "ERROR out of space writing record to packet.\n" ));
|
|||
|
return( NULL );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// set type and class
|
|||
|
//
|
|||
|
|
|||
|
*(UNALIGNED WORD *) &pdnsRR->RecordType = htons( wType );
|
|||
|
*(UNALIGNED WORD *) &pdnsRR->RecordClass = htons( wClass );
|
|||
|
|
|||
|
//
|
|||
|
// TTL and datalength zero for all no data cases
|
|||
|
// - prereqs except specific record delete
|
|||
|
// - deletes except specific record delete
|
|||
|
//
|
|||
|
|
|||
|
*(UNALIGNED DWORD *) &pdnsRR->TimeToLive = 0;
|
|||
|
*(UNALIGNED WORD *) &pdnsRR->DataLength = 0;
|
|||
|
|
|||
|
return( pch );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
PCHAR
|
|||
|
Dns_WriteDataUpdateRecordToMessage(
|
|||
|
IN PCHAR pch,
|
|||
|
IN PCHAR pchStop,
|
|||
|
IN WORD wClass,
|
|||
|
IN WORD wType,
|
|||
|
IN DWORD dwTtl,
|
|||
|
IN WORD wDataLength
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
No data RR cases:
|
|||
|
|
|||
|
This includes prereqs and deletes except for specific record cases.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pch - ptr to next byte in packet buffer
|
|||
|
|
|||
|
pchStop - end of packet buffer
|
|||
|
|
|||
|
wClass - class
|
|||
|
|
|||
|
wType - desired RR type
|
|||
|
|
|||
|
dwTtl - time to live
|
|||
|
|
|||
|
wDataLength - data length
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Ptr to next postion in buffer, if successful.
|
|||
|
NULL on error.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PDNS_WIRE_RECORD pdnsRR;
|
|||
|
|
|||
|
DNSDBG( WRITE2, (
|
|||
|
"Writing RR to packet buffer at %p.\n",
|
|||
|
pch ));
|
|||
|
|
|||
|
//
|
|||
|
// out of space
|
|||
|
//
|
|||
|
|
|||
|
pdnsRR = (PDNS_WIRE_RECORD) pch;
|
|||
|
pch += sizeof( DNS_WIRE_RECORD );
|
|||
|
if ( pch + wDataLength >= pchStop )
|
|||
|
{
|
|||
|
DNS_PRINT(( "ERROR out of space writing record to packet.\n" ));
|
|||
|
return( NULL );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// set type and class
|
|||
|
//
|
|||
|
|
|||
|
*(UNALIGNED WORD *) &pdnsRR->RecordType = htons( wType );
|
|||
|
*(UNALIGNED WORD *) &pdnsRR->RecordClass = htons( wClass );
|
|||
|
|
|||
|
//
|
|||
|
// TTL and datalength zero for all no data cases
|
|||
|
// - prereqs except specific record delete
|
|||
|
// - deletes except specific record delete
|
|||
|
//
|
|||
|
|
|||
|
*(UNALIGNED DWORD *) &pdnsRR->TimeToLive = htonl( dwTtl );
|
|||
|
*(UNALIGNED WORD *) &pdnsRR->DataLength = htons( wDataLength );
|
|||
|
|
|||
|
return( pch );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Host update routines
|
|||
|
//
|
|||
|
|
|||
|
#if 0
|
|||
|
PDNS_MSG_BUF
|
|||
|
Dns_BuildHostUpdateMessage(
|
|||
|
IN OUT PDNS_MSG_BUF pMsg,
|
|||
|
IN LPSTR pszZone,
|
|||
|
IN LPSTR pszName,
|
|||
|
IN PIP_ARRAY aipAddresses,
|
|||
|
IN DWORD dwTtl
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Build server update message.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pMsg -- existing message buffer, to use; NULL to allocate new one
|
|||
|
|
|||
|
pszZone -- zone name for update
|
|||
|
|
|||
|
pszName -- full DNS hostname being updated
|
|||
|
|
|||
|
aipAddresses -- IP addresses to be updated
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful.
|
|||
|
Error status on failure.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PDNS_HEADER pdnsMsg;
|
|||
|
PCHAR pch;
|
|||
|
PCHAR pchstop;
|
|||
|
DWORD i;
|
|||
|
WORD nameOffset;
|
|||
|
|
|||
|
IF_DNSDBG( UPDATE )
|
|||
|
{
|
|||
|
DNS_PRINT((
|
|||
|
"Enter Dns_BuildHostUpdateMessage()\n"
|
|||
|
"\tpMsg = %p\n"
|
|||
|
"\tpszZone = %s\n"
|
|||
|
"\tpszName = %s\n"
|
|||
|
"\tdwTtl = %d\n",
|
|||
|
pMsg,
|
|||
|
pszZone,
|
|||
|
pszName,
|
|||
|
dwTtl ));
|
|||
|
DnsDbg_IpArray(
|
|||
|
"\tHost IP array\n",
|
|||
|
"host",
|
|||
|
aipAddresses );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// create message buffer
|
|||
|
//
|
|||
|
|
|||
|
if ( !pMsg )
|
|||
|
{
|
|||
|
DNS_PRINT(( "Allocating new UPDATE message buffer.\n" ));
|
|||
|
|
|||
|
pMsg = ALLOCATE_HEAP( DNS_UDP_ALLOC_LENGTH );
|
|||
|
if ( !pMsg )
|
|||
|
{
|
|||
|
return( NULL );
|
|||
|
}
|
|||
|
RtlZeroMemory(
|
|||
|
pMsg,
|
|||
|
DNS_UDP_ALLOC_LENGTH );
|
|||
|
|
|||
|
pMsg->BufferLength = DNS_UDP_MAX_PACKET_LENGTH;
|
|||
|
pMsg->pBufferEnd = (PCHAR)&pMsg->MessageHead + pMsg->BufferLength;
|
|||
|
|
|||
|
//
|
|||
|
// set default sockaddr info
|
|||
|
// - caller MUST choose remote IP address
|
|||
|
|
|||
|
pMsg->RemoteAddress.sin_family = AF_INET;
|
|||
|
pMsg->RemoteAddress.sin_port = NET_ORDER_DNS_PORT;
|
|||
|
pMsg->RemoteAddressLength = sizeof( SOCKADDR_IN );
|
|||
|
|
|||
|
// set header for update
|
|||
|
|
|||
|
pMsg->MessageHead.Opcode = DNS_OPCODE_UPDATE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// existing message, just verify
|
|||
|
//
|
|||
|
|
|||
|
ELSE_ASSERT( pMsg->MessageHead.Opcode == DNS_OPCODE_UPDATE );
|
|||
|
|
|||
|
//
|
|||
|
// reset current pointer after header
|
|||
|
// - note: send length is set based on this ptr
|
|||
|
//
|
|||
|
|
|||
|
pMsg->pCurrent = pMsg->MessageBody;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// build message
|
|||
|
//
|
|||
|
|
|||
|
pch = pMsg->pCurrent;
|
|||
|
pchstop = pMsg->pBufferEnd;
|
|||
|
|
|||
|
//
|
|||
|
// zone section
|
|||
|
//
|
|||
|
|
|||
|
pMsg->MessageHead.QuestionCount = 1;
|
|||
|
pch = Dns_WriteDottedNameToPacket(
|
|||
|
pch,
|
|||
|
pchstop,
|
|||
|
pszZone,
|
|||
|
NULL,
|
|||
|
0,
|
|||
|
FALSE );
|
|||
|
if ( !pch )
|
|||
|
{
|
|||
|
return( NULL );
|
|||
|
}
|
|||
|
*(UNALIGNED WORD *) pch = DNS_RTYPE_SOA;
|
|||
|
pch += sizeof(WORD);
|
|||
|
*(UNALIGNED WORD *) pch = DNS_RCLASS_INTERNET;
|
|||
|
pch += sizeof(WORD);
|
|||
|
|
|||
|
//
|
|||
|
// prerequisites -- no records
|
|||
|
//
|
|||
|
|
|||
|
pMsg->MessageHead.AnswerCount = 0;
|
|||
|
|
|||
|
//
|
|||
|
// update
|
|||
|
// - delete A records at name
|
|||
|
// - add new A records
|
|||
|
//
|
|||
|
|
|||
|
// save offset to host name for future writes
|
|||
|
|
|||
|
nameOffset = (WORD)(pch - (PCHAR) &pMsg->MessageHead);
|
|||
|
|
|||
|
pch = Dns_WriteDottedNameToPacket(
|
|||
|
pch,
|
|||
|
pchstop,
|
|||
|
pszName,
|
|||
|
pszZone,
|
|||
|
DNS_OFFSET_TO_QUESTION_NAME,
|
|||
|
FALSE );
|
|||
|
if ( !pch )
|
|||
|
{
|
|||
|
DNS_PRINT(( "ERROR writing dotted name to packet.\n" ));
|
|||
|
return( NULL );
|
|||
|
}
|
|||
|
pch = Dns_WriteNoDataUpdateRecordToMessage(
|
|||
|
pch,
|
|||
|
pchstop,
|
|||
|
DNS_CLASS_ALL, // delete all
|
|||
|
DNS_TYPE_A // A records
|
|||
|
);
|
|||
|
DNS_ASSERT( pch );
|
|||
|
|
|||
|
//
|
|||
|
// add A record for each address in array
|
|||
|
// - use offset for name
|
|||
|
// - write IP
|
|||
|
|
|||
|
for ( i=0; i<aipAddresses->AddrCount; i++ )
|
|||
|
{
|
|||
|
*(UNALIGNED WORD *) pch = htons( (WORD)(nameOffset|(WORD)0xC000) );
|
|||
|
pch += sizeof( WORD );
|
|||
|
pch = Dns_WriteDataUpdateRecordToMessage(
|
|||
|
pch,
|
|||
|
pchstop,
|
|||
|
DNS_CLASS_INTERNET,
|
|||
|
DNS_TYPE_A, // A records
|
|||
|
dwTtl,
|
|||
|
sizeof(IP_ADDRESS)
|
|||
|
);
|
|||
|
DNS_ASSERT( pch );
|
|||
|
*(UNALIGNED DWORD *) pch = aipAddresses->AddrArray[i];
|
|||
|
pch += sizeof(DWORD);
|
|||
|
}
|
|||
|
|
|||
|
// total update sections RRs
|
|||
|
// one delete RR, plus one for each new IP
|
|||
|
|
|||
|
pMsg->MessageHead.NameServerCount = (USHORT)(aipAddresses->AddrCount + 1);
|
|||
|
|
|||
|
//
|
|||
|
// additional section - no records
|
|||
|
//
|
|||
|
|
|||
|
pMsg->MessageHead.AdditionalCount = 0;
|
|||
|
|
|||
|
//
|
|||
|
// reset current ptr -- need for send routine
|
|||
|
//
|
|||
|
|
|||
|
pMsg->pCurrent = pch;
|
|||
|
|
|||
|
IF_DNSDBG( SEND )
|
|||
|
{
|
|||
|
DnsDbg_Message(
|
|||
|
"UPDATE packet built",
|
|||
|
pMsg );
|
|||
|
}
|
|||
|
return( pMsg );
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
|
|||
|
PDNS_RECORD
|
|||
|
Dns_HostUpdateRRSet(
|
|||
|
IN LPSTR pszHostName,
|
|||
|
IN PIP_ARRAY AddrArray,
|
|||
|
IN DWORD dwTtl
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Create records for host update:
|
|||
|
-- whack of all A records
|
|||
|
-- add of all A records in new set
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pszHostName -- host name, FULL FQDN
|
|||
|
|
|||
|
AddrArray -- new IPs of host
|
|||
|
|
|||
|
dwTtl -- TTL for records
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Ptr to record list.
|
|||
|
NULL on error.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DNS_RRSET rrset;
|
|||
|
PDNS_RECORD prr;
|
|||
|
DWORD i;
|
|||
|
|
|||
|
//
|
|||
|
// create whack
|
|||
|
//
|
|||
|
|
|||
|
prr = Dns_AllocateRecord( 0 );
|
|||
|
if ( ! prr )
|
|||
|
{
|
|||
|
return( NULL );
|
|||
|
}
|
|||
|
prr->pName = pszHostName;
|
|||
|
prr->wType = DNS_TYPE_A;
|
|||
|
prr->Flags.S.Section = DNSREC_UPDATE;
|
|||
|
prr->Flags.S.Delete = TRUE;
|
|||
|
|
|||
|
//
|
|||
|
// create update record for each address
|
|||
|
//
|
|||
|
|
|||
|
if ( !AddrArray )
|
|||
|
{
|
|||
|
return( prr );
|
|||
|
}
|
|||
|
DNS_RRSET_INIT( rrset );
|
|||
|
DNS_RRSET_ADD( rrset, prr );
|
|||
|
|
|||
|
for ( i=0; i<AddrArray->AddrCount; i++ )
|
|||
|
{
|
|||
|
prr = Dns_AllocateRecord( sizeof(DNS_A_DATA) );
|
|||
|
if ( ! prr )
|
|||
|
{
|
|||
|
Dns_RecordListFree( rrset.pFirstRR, FALSE );
|
|||
|
return( NULL );
|
|||
|
}
|
|||
|
prr->pName = pszHostName;
|
|||
|
prr->wType = DNS_TYPE_A;
|
|||
|
prr->Flags.S.Section = DNSREC_UPDATE;
|
|||
|
prr->dwTtl = dwTtl;
|
|||
|
prr->Data.A.IpAddress = AddrArray->AddrArray[i];
|
|||
|
|
|||
|
DNS_RRSET_ADD( rrset, prr );
|
|||
|
}
|
|||
|
|
|||
|
// return ptr to first record in list
|
|||
|
|
|||
|
return( rrset.pFirstRR );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// DCR: dead code, remove
|
|||
|
//
|
|||
|
DNS_STATUS
|
|||
|
Dns_UpdateHostAddrs(
|
|||
|
IN LPSTR pszName,
|
|||
|
IN PIP_ARRAY aipAddresses,
|
|||
|
IN PIP_ARRAY aipServers,
|
|||
|
IN DWORD dwTtl
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Updates client's A records registered with DNS server.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pszName -- name (FQDN) of client to update
|
|||
|
|
|||
|
aipAddresses -- counted array of new client IP addrs
|
|||
|
|
|||
|
aipServers -- counted array of DNS server IP addrs
|
|||
|
|
|||
|
dwTtl -- TTL for new A records
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful.
|
|||
|
Error status on failure.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PDNS_RECORD prr;
|
|||
|
DNS_STATUS status;
|
|||
|
|
|||
|
IF_DNSDBG( UPDATE )
|
|||
|
{
|
|||
|
DNS_PRINT((
|
|||
|
"Enter Dns_UpdateHostAddrs()\n"
|
|||
|
"\tpszName = %s\n"
|
|||
|
"\tdwTtl = %d\n",
|
|||
|
pszName,
|
|||
|
dwTtl ));
|
|||
|
DnsDbg_IpArray(
|
|||
|
"\tHost IP array\n",
|
|||
|
"\tHost",
|
|||
|
aipAddresses );
|
|||
|
DnsDbg_IpArray(
|
|||
|
"\tNS IP array\n",
|
|||
|
"\tNS",
|
|||
|
aipServers );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// never let anyone set a TTL longer than 1 hour
|
|||
|
//
|
|||
|
// DCR: define policy on what our clients should use for TTL
|
|||
|
// one hour is not bad
|
|||
|
// could key off type of address
|
|||
|
// RAS -- 15 minutes (as may be back up again quickly)
|
|||
|
// DHCP -- one hour (may move)
|
|||
|
// static -- one day (machines may be reconfigured)
|
|||
|
//
|
|||
|
|
|||
|
if ( dwTtl > 3600 )
|
|||
|
{
|
|||
|
dwTtl = 3600;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// build update RR set
|
|||
|
//
|
|||
|
|
|||
|
prr = Dns_HostUpdateRRSet(
|
|||
|
pszName,
|
|||
|
aipAddresses,
|
|||
|
dwTtl );
|
|||
|
if ( ! prr )
|
|||
|
{
|
|||
|
status = GetLastError();
|
|||
|
DNS_ASSERT( status == DNS_ERROR_NO_MEMORY );
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// do the update
|
|||
|
//
|
|||
|
|
|||
|
status = Dns_UpdateLib(
|
|||
|
prr,
|
|||
|
0, // no flags
|
|||
|
NULL, // no adapter list
|
|||
|
NULL, // use default credentials
|
|||
|
NULL // response not desired
|
|||
|
);
|
|||
|
|
|||
|
Dns_RecordListFree( prr, FALSE );
|
|||
|
|
|||
|
DNSDBG( UPDATE, (
|
|||
|
"Leave Dns_UpdateHostAddrs() status=%p %s\n",
|
|||
|
status,
|
|||
|
Dns_StatusString(status) ));
|
|||
|
|
|||
|
return( status );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DNS_STATUS
|
|||
|
Dns_UpdateLib(
|
|||
|
IN PDNS_RECORD pRecord,
|
|||
|
IN DWORD dwFlags,
|
|||
|
IN PDNS_NETINFO pNetworkInfo,
|
|||
|
IN HANDLE hCreds OPTIONAL,
|
|||
|
OUT PDNS_MSG_BUF * ppMsgRecv OPTIONAL
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Send DNS update.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pRecord -- list of records to send in update
|
|||
|
|
|||
|
dwFlags -- update flags; primarily security
|
|||
|
|
|||
|
pNetworkInfo -- adapter list with necessary info for update
|
|||
|
- zone name
|
|||
|
- primary name server name
|
|||
|
- primary name server IP
|
|||
|
|
|||
|
ppMsgRecv -- OPTIONAL addr to recv ptr to response message
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful.
|
|||
|
Error status on failure.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PDNS_MSG_BUF pmsgSend = NULL;
|
|||
|
PDNS_MSG_BUF pmsgRecv = NULL;
|
|||
|
DNS_STATUS status = NO_ERROR;
|
|||
|
WORD length;
|
|||
|
PIP_ARRAY parrayServers = NULL;
|
|||
|
LPSTR pszzone;
|
|||
|
LPSTR pszserverName;
|
|||
|
BOOL fsecure = FALSE;
|
|||
|
BOOL fswitchToTcp = FALSE;
|
|||
|
DNS_HEADER header;
|
|||
|
PCHAR pCreds=NULL;
|
|||
|
|
|||
|
DNSDBG( UPDATE, (
|
|||
|
"Dns_UpdateLib()\n"
|
|||
|
"\tflags = %p\n"
|
|||
|
"\tpRecord = %p\n"
|
|||
|
"\t\towner = %s\n",
|
|||
|
dwFlags,
|
|||
|
pRecord,
|
|||
|
pRecord ? pRecord->pName : NULL ));
|
|||
|
|
|||
|
//
|
|||
|
// if not a UPDATE compatibile adapter list -- no action
|
|||
|
//
|
|||
|
|
|||
|
if ( !IS_UPDATE_NETWORK_INFO(pNetworkInfo) )
|
|||
|
{
|
|||
|
return( ERROR_INVALID_PARAMETER );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// suck info from adapter list
|
|||
|
//
|
|||
|
|
|||
|
pszzone = pNetworkInfo->pSearchList->pszDomainOrZoneName;
|
|||
|
|
|||
|
parrayServers = Dns_ConvertNetworkInfoToIpArray( pNetworkInfo );
|
|||
|
|
|||
|
pszserverName = pNetworkInfo->aAdapterInfoList[0]->pszAdapterDomain;
|
|||
|
|
|||
|
DNS_ASSERT( pszzone && parrayServers );
|
|||
|
|
|||
|
//
|
|||
|
// build recv message buffer
|
|||
|
// - must be big enough for TCP
|
|||
|
//
|
|||
|
|
|||
|
pmsgRecv = Dns_AllocateMsgBuf( DNS_TCP_DEFAULT_PACKET_LENGTH );
|
|||
|
if ( !pmsgRecv )
|
|||
|
{
|
|||
|
status = DNS_ERROR_NO_MEMORY;
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// build update packet
|
|||
|
// note currently this function allocates TCP sized buffer if records
|
|||
|
// given; if this changes need to alloc TCP buffer here
|
|||
|
//
|
|||
|
|
|||
|
CLEAR_DNS_HEADER_FLAGS_AND_XID( &header );
|
|||
|
header.Opcode = DNS_OPCODE_UPDATE;
|
|||
|
|
|||
|
pmsgSend = Dns_BuildPacket(
|
|||
|
&header, // copy header
|
|||
|
TRUE, // ... but not header counts
|
|||
|
pszzone, // question zone\type SOA
|
|||
|
DNS_TYPE_SOA,
|
|||
|
pRecord,
|
|||
|
0, // no other flags
|
|||
|
TRUE // building an update packet
|
|||
|
);
|
|||
|
if ( !pmsgSend)
|
|||
|
{
|
|||
|
DNS_PRINT(( "ERROR: failed send buffer allocation.\n" ));
|
|||
|
status = DNS_ERROR_NO_MEMORY;
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// try non-secure first unless explicitly secure only
|
|||
|
//
|
|||
|
|
|||
|
fsecure = (dwFlags & DNS_UPDATE_SECURITY_ONLY);
|
|||
|
|
|||
|
if ( !fsecure )
|
|||
|
{
|
|||
|
status = Dns_SendAndRecv(
|
|||
|
pmsgSend,
|
|||
|
& pmsgRecv,
|
|||
|
NULL, // no response records
|
|||
|
dwFlags,
|
|||
|
parrayServers,
|
|||
|
pNetworkInfo );
|
|||
|
|
|||
|
if ( status == ERROR_SUCCESS )
|
|||
|
{
|
|||
|
status = Dns_MapRcodeToStatus( pmsgRecv->MessageHead.ResponseCode );
|
|||
|
}
|
|||
|
|
|||
|
if ( status != DNS_ERROR_RCODE_REFUSED ||
|
|||
|
dwFlags & DNS_UPDATE_SECURITY_OFF )
|
|||
|
{
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
DNSDBG( UPDATE, (
|
|||
|
"Failed unsecure update, switching to secure!\n"
|
|||
|
"\tcurrent time (ms) = %d\n",
|
|||
|
GetCurrentTime() ));
|
|||
|
fsecure = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// security
|
|||
|
// - must have server name
|
|||
|
// - must start package
|
|||
|
//
|
|||
|
|
|||
|
if ( fsecure )
|
|||
|
{
|
|||
|
if ( !pszserverName )
|
|||
|
{
|
|||
|
status = ERROR_INVALID_PARAMETER;
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
status = Dns_StartSecurity( FALSE );
|
|||
|
if ( status != ERROR_SUCCESS )
|
|||
|
{
|
|||
|
goto Cleanup;
|
|||
|
}
|
|||
|
|
|||
|
pCreds = Dns_GetApiContextCredentials(hCreds);
|
|||
|
|
|||
|
|
|||
|
status = Dns_DoSecureUpdate(
|
|||
|
pmsgSend,
|
|||
|
pmsgRecv,
|
|||
|
NULL,
|
|||
|
dwFlags,
|
|||
|
pNetworkInfo,
|
|||
|
parrayServers,
|
|||
|
pszserverName,
|
|||
|
pCreds, // initialized in DnsAcquireContextHandle
|
|||
|
NULL // default context name
|
|||
|
);
|
|||
|
if ( status == ERROR_SUCCESS )
|
|||
|
{
|
|||
|
status = Dns_MapRcodeToStatus( pmsgRecv->MessageHead.ResponseCode );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
Cleanup:
|
|||
|
|
|||
|
// free server array sucked from adapter list
|
|||
|
|
|||
|
if ( parrayServers )
|
|||
|
{
|
|||
|
FREE_HEAP( parrayServers );
|
|||
|
}
|
|||
|
|
|||
|
// return recv message buffer
|
|||
|
|
|||
|
if ( ppMsgRecv )
|
|||
|
{
|
|||
|
*ppMsgRecv = pmsgRecv;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
FREE_HEAP( pmsgRecv );
|
|||
|
}
|
|||
|
FREE_HEAP( pmsgSend);
|
|||
|
|
|||
|
DNSDBG( UPDATE, (
|
|||
|
"Dns_UpdateLib() completed, status = %p %s.\n",
|
|||
|
status,
|
|||
|
Dns_StatusString(status) ));
|
|||
|
|
|||
|
return( status );
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
DNS_STATUS
|
|||
|
Dns_UpdateLibEx(
|
|||
|
IN PDNS_RECORD pRecord,
|
|||
|
IN DWORD dwFlags,
|
|||
|
IN PDNS_NAME pszZone,
|
|||
|
IN PDNS_NAME pszServerName,
|
|||
|
IN PIP_ARRAY aipServers,
|
|||
|
IN HANDLE hCreds OPTIONAL,
|
|||
|
OUT PDNS_MSG_BUF * ppMsgRecv OPTIONAL
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Send DNS update.
|
|||
|
|
|||
|
This routine builds an UPDATE compatible pNetworkInfo from the
|
|||
|
information given. Then calls Dns_Update().
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pRecord -- list of records to send in update
|
|||
|
|
|||
|
pszZone -- zone name for update
|
|||
|
|
|||
|
pszServerName -- server name
|
|||
|
|
|||
|
aipServers -- DNS servers to send update to
|
|||
|
|
|||
|
hCreds -- Optional Credentials info
|
|||
|
|
|||
|
ppMsgRecv -- addr for ptr to recv buffer, if desired
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
ERROR_SUCCESS if successful.
|
|||
|
Error status on failure.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PDNS_NETINFO pNetworkInfo;
|
|||
|
DNS_STATUS status = NO_ERROR;
|
|||
|
|
|||
|
//
|
|||
|
// convert params into UPDATE compatible adapter list
|
|||
|
//
|
|||
|
|
|||
|
pNetworkInfo = Dns_CreateUpdateNetworkInfo(
|
|||
|
pszZone,
|
|||
|
pszServerName,
|
|||
|
aipServers,
|
|||
|
0 );
|
|||
|
|
|||
|
if ( !pNetworkInfo )
|
|||
|
{
|
|||
|
return( ERROR_INVALID_PARAMETER );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// call real update function
|
|||
|
//
|
|||
|
|
|||
|
status = Dns_UpdateLib(
|
|||
|
pRecord,
|
|||
|
dwFlags,
|
|||
|
pNetworkInfo,
|
|||
|
hCreds,
|
|||
|
ppMsgRecv );
|
|||
|
|
|||
|
Dns_FreeNetworkInfo( pNetworkInfo );
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// End update.c
|
|||
|
//
|