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