From 5693e6c599a586b1bb19eea375c6b1e22526031c Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 24 Aug 2006 15:43:32 +0000 Subject: r17798: Beginnings of a standalone libaddns library released under the LGPL. Original code by Krishna Ganugapati . Additional work by me. It's still got some warts, but non-secure updates do currently work. There are at least four things left to really clean up. 1. Change the memory management to use talloc() rather than malloc() and cleanup the leaks. 2. Fix the error code reporting (see initial changes to dnserr.h) 3. Fix the secure updates 4. Define a public interface in addns.h 5. Move the code in libads/dns.c into the libaddns/ directory (and under the LGPL). A few notes: * Enable the new code by compiling with --with-dnsupdate * Also adds the command 'net ads dns register' * Requires -luuid (included in the e2fsprogs-devel package). * Has only been tested on Linux platforms so there may be portability issues. (This used to be commit 36f04674aeefd93c5a0408b8967dcd48b86fdbc1) --- source3/libaddns/dnsrequest.c | 478 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 478 insertions(+) create mode 100644 source3/libaddns/dnsrequest.c (limited to 'source3/libaddns/dnsrequest.c') diff --git a/source3/libaddns/dnsrequest.c b/source3/libaddns/dnsrequest.c new file mode 100644 index 0000000000..3dd402981f --- /dev/null +++ b/source3/libaddns/dnsrequest.c @@ -0,0 +1,478 @@ +/* + Linux DNS client library implementation + Copyright (C) 2006 Krishna Ganugapati + Copyright (C) 2006 Gerald Carter + + ** NOTE! The following LGPL license applies to the libaddns + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA +*/ + +#include "dns.h" + +/********************************************************************* +*********************************************************************/ + +static int32 DNSStdMarshallQuestionSection( HANDLE hSendBuffer, + DNS_QUESTION_RECORD ** ppDNSQuestionRecords, + int16 wQuestions ) +{ + int32 dwError = 0; + int32 i = 0; + int32 dwRead = 0; + DNS_QUESTION_RECORD *pDNSQuestionRecord = NULL; + int16 wnQueryType = 0; + int16 wnQueryClass = 0; + + for ( i = 0; i < wQuestions; i++ ) { + + pDNSQuestionRecord = *( ppDNSQuestionRecords + i ); + dwError = + DNSMarshallDomainName( hSendBuffer, + pDNSQuestionRecord-> + pDomainName ); + BAIL_ON_ERROR( dwError ); + + wnQueryType = htons( pDNSQuestionRecord->wQueryType ); + dwError = + DNSMarshallBuffer( hSendBuffer, + ( uint8 * ) & wnQueryType, + ( int32 ) sizeof( int16 ), + &dwRead ); + BAIL_ON_ERROR( dwError ); + + wnQueryClass = htons( pDNSQuestionRecord->wQueryClass ); + dwError = + DNSMarshallBuffer( hSendBuffer, + ( uint8 * ) & wnQueryClass, + ( int32 ) sizeof( int16 ), + &dwRead ); + BAIL_ON_ERROR( dwError ); + + pDNSQuestionRecord++; + } + + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +static int32 DNSStdMarshallAnswerSection( HANDLE hSendBuffer, + DNS_RR_RECORD ** ppDNSAnswerRRRecords, + int16 wAnswers ) +{ + int32 dwError = 0; + int32 i = 0; + DNS_RR_RECORD *pDNSAnswerRRRecord = NULL; + + + for ( i = 0; i < wAnswers; i++ ) { + + pDNSAnswerRRRecord = *( ppDNSAnswerRRRecords + i ); + + dwError = + DNSMarshallRRHeader( hSendBuffer, + pDNSAnswerRRRecord ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSMarshallRData( hSendBuffer, pDNSAnswerRRRecord ); + BAIL_ON_ERROR( dwError ); + + pDNSAnswerRRRecord++; + + } + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +static int32 DNSStdMarshallAuthoritySection( HANDLE hSendBuffer, + DNS_RR_RECORD ** ppDNSAuthorityRRRecords, + int16 wAuthoritys ) +{ + int32 dwError = 0; + int32 i = 0; + + DNS_RR_RECORD *pDNSAuthorityRRRecord = NULL; + + for ( i = 0; i < wAuthoritys; i++ ) { + + pDNSAuthorityRRRecord = *( ppDNSAuthorityRRRecords + i ); + + dwError = + DNSMarshallRRHeader( hSendBuffer, + pDNSAuthorityRRRecord ); + + dwError = DNSMarshallRData( hSendBuffer, + pDNSAuthorityRRRecord ); + BAIL_ON_ERROR( dwError ); + + } + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +static int32 DNSStdMarshallAdditionalSection( HANDLE hSendBuffer, + DNS_RR_RECORD ** ppDNSAdditionalsRRRecords, + int16 wAdditionals ) +{ + int32 dwError = 0; + int32 i = 0; + DNS_RR_RECORD *pDNSAdditionalRRRecord = NULL; + + for ( i = 0; i < wAdditionals; i++ ) { + + pDNSAdditionalRRRecord = *( ppDNSAdditionalsRRRecords + i ); + + dwError = + DNSMarshallRRHeader( hSendBuffer, + pDNSAdditionalRRRecord ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSMarshallRData( hSendBuffer, + pDNSAdditionalRRRecord ); + BAIL_ON_ERROR( dwError ); + + } + + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +static int32 DNSBuildRequestMessage( DNS_REQUEST * pDNSRequest, HANDLE * phSendBuffer ) +{ + int32 dwError = 0; + char DNSMessageHeader[12]; + int16 wnIdentification = 0; + int16 wnParameter = 0; + int16 wnQuestions = 0; + int16 wnAnswers = 0; + int16 wnAuthoritys = 0; + int16 wnAdditionals = 0; + int32 dwRead = 0; + HANDLE hSendBuffer = ( HANDLE ) NULL; + + dwError = DNSCreateSendBuffer( &hSendBuffer ); + BAIL_ON_ERROR( dwError ); + + wnIdentification = htons( pDNSRequest->wIdentification ); + memcpy( DNSMessageHeader, ( char * ) &wnIdentification, 2 ); + + wnParameter = htons( pDNSRequest->wParameter ); + memcpy( DNSMessageHeader + 2, ( char * ) &wnParameter, 2 ); + + wnQuestions = htons( pDNSRequest->wQuestions ); + memcpy( DNSMessageHeader + 4, ( char * ) &wnQuestions, 2 ); + + wnAnswers = htons( pDNSRequest->wAnswers ); + memcpy( DNSMessageHeader + 6, ( char * ) &wnAnswers, 2 ); + + wnAuthoritys = htons( pDNSRequest->wAuthoritys ); + memcpy( DNSMessageHeader + 8, ( char * ) &wnAuthoritys, 2 ); + + wnAdditionals = htons( pDNSRequest->wAdditionals ); + memcpy( DNSMessageHeader + 10, ( char * ) &wnAdditionals, 2 ); + + dwError = + DNSMarshallBuffer( hSendBuffer, ( uint8 * ) DNSMessageHeader, + 12, &dwRead ); + BAIL_ON_ERROR( dwError ); + + if ( pDNSRequest->wQuestions ) { + dwError = + DNSStdMarshallQuestionSection( hSendBuffer, + pDNSRequest-> + ppQuestionRRSet, + pDNSRequest-> + wQuestions ); + BAIL_ON_ERROR( dwError ); + } + + if ( pDNSRequest->wAnswers ) { + dwError = + DNSStdMarshallAnswerSection( hSendBuffer, + pDNSRequest-> + ppAnswerRRSet, + pDNSRequest->wAnswers ); + BAIL_ON_ERROR( dwError ); + } + + if ( pDNSRequest->wAuthoritys ) { + dwError = + DNSStdMarshallAuthoritySection( hSendBuffer, + pDNSRequest-> + ppAuthorityRRSet, + pDNSRequest-> + wAuthoritys ); + BAIL_ON_ERROR( dwError ); + } + + if ( pDNSRequest->wAdditionals ) { + dwError = + DNSStdMarshallAdditionalSection( hSendBuffer, + pDNSRequest-> + ppAdditionalRRSet, + pDNSRequest-> + wAdditionals ); + BAIL_ON_ERROR( dwError ); + } +#if 0 + DNSDumpSendBufferContext( hSendBuffer ); +#endif + *phSendBuffer = hSendBuffer; + + return dwError; + + error: + + if ( hSendBuffer ) { + DNSFreeSendBufferContext( hSendBuffer ); + } + + *phSendBuffer = ( HANDLE ) NULL; + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSStdSendStdRequest2( HANDLE hDNSServer, DNS_REQUEST * pDNSRequest ) +{ + int32 dwError = 0; + int32 dwBytesSent = 0; + HANDLE hSendBuffer = ( HANDLE ) NULL; + + dwError = DNSBuildRequestMessage( pDNSRequest, &hSendBuffer ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSSendBufferContext( hDNSServer, hSendBuffer, &dwBytesSent ); + BAIL_ON_ERROR( dwError ); + + error: + + if ( hSendBuffer ) { + DNSFreeSendBufferContext( hSendBuffer ); + } + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSMarshallDomainName( HANDLE hSendBuffer, DNS_DOMAIN_NAME * pDomainName ) +{ + int32 dwError = 0; + DNS_DOMAIN_LABEL *pTemp = NULL; + int32 dwLen = 0; + int32 dwSent = 0; + char uEndChar = 0; + + pTemp = pDomainName->pLabelList; + while ( pTemp ) { + dwLen = ( int32 ) strlen( pTemp->pszLabel ); + dwError = + DNSMarshallBuffer( hSendBuffer, ( uint8 * ) & dwLen, + sizeof( char ), &dwSent ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSMarshallBuffer( hSendBuffer, + ( uint8 * ) pTemp->pszLabel, dwLen, + &dwSent ); + BAIL_ON_ERROR( dwError ); + pTemp = pTemp->pNext; + } + DNSMarshallBuffer( hSendBuffer, ( uint8 * ) & uEndChar, + sizeof( char ), &dwSent ); + + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSMarshallRRHeader( HANDLE hSendBuffer, DNS_RR_RECORD * pDNSRecord ) +{ + int32 dwError = 0; + int32 dwRead = 0; + int16 wnType = 0; + int16 wnClass = 0; + int16 wnRDataSize = 0; + int32 dwnTTL = 0; + + dwError = + DNSMarshallDomainName( hSendBuffer, + pDNSRecord->RRHeader.pDomainName ); + BAIL_ON_ERROR( dwError ); + + wnType = htons( pDNSRecord->RRHeader.wType ); + dwError = + DNSMarshallBuffer( hSendBuffer, ( uint8 * ) & wnType, + sizeof( int16 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + + wnClass = htons( pDNSRecord->RRHeader.wClass ); + dwError = + DNSMarshallBuffer( hSendBuffer, ( uint8 * ) & wnClass, + sizeof( int16 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + + dwnTTL = htonl( pDNSRecord->RRHeader.dwTTL ); + dwError = + DNSMarshallBuffer( hSendBuffer, ( uint8 * ) & dwnTTL, + sizeof( int32 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + + wnRDataSize = htons( pDNSRecord->RRHeader.wRDataSize ); + dwError = + DNSMarshallBuffer( hSendBuffer, ( uint8 * ) & wnRDataSize, + sizeof( int16 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSMarshallRData( HANDLE hSendBuffer, DNS_RR_RECORD * pDNSRecord ) +{ + int32 dwError = 0; + int32 dwWritten = 0; + + dwError = + DNSMarshallBuffer( hSendBuffer, pDNSRecord->pRData, + pDNSRecord->RRHeader.wRDataSize, + &dwWritten ); + BAIL_ON_ERROR( dwError ); + + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSStdAddQuestionSection( DNS_REQUEST * pDNSRequest, + DNS_QUESTION_RECORD * pDNSQuestion ) +{ + int32 dwNumQuestions = 0; + int32 dwError = 0; + + dwNumQuestions = pDNSRequest->wQuestions; + + dwError = DNSReallocMemory( ( uint8 * ) pDNSRequest->ppQuestionRRSet, + ( void ** ) &pDNSRequest->ppQuestionRRSet, + ( dwNumQuestions + + 1 ) * sizeof( DNS_QUESTION_RECORD * ) + ); + BAIL_ON_ERROR( dwError ); + + *( pDNSRequest->ppQuestionRRSet + dwNumQuestions ) = pDNSQuestion; + + pDNSRequest->wQuestions += 1; + + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSStdAddAdditionalSection( DNS_REQUEST * pDNSRequest, + DNS_RR_RECORD * pDNSRecord ) +{ + int32 dwNumAdditionals = 0; + int32 dwError = 0; + + dwNumAdditionals = pDNSRequest->wAdditionals; + dwError = DNSReallocMemory( pDNSRequest->ppAdditionalRRSet, + ( void ** ) &pDNSRequest-> + ppAdditionalRRSet, + ( dwNumAdditionals + + 1 ) * sizeof( DNS_RR_RECORD * ) ); + BAIL_ON_ERROR( dwError ); + + *( pDNSRequest->ppAdditionalRRSet + dwNumAdditionals ) = pDNSRecord; + + pDNSRequest->wAdditionals += 1; + + error: + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSStdCreateStdRequest( DNS_REQUEST ** ppDNSRequest ) +{ + int32 dwError = 0; + DNS_REQUEST *pDNSRequest = NULL; + +#if 0 + int16 wRecursionDesired = RECURSION_DESIRED; + int16 wParameter = QR_QUERY; + int16 wOpcode = OPCODE_QUERY; +#endif + dwError = + DNSAllocateMemory( sizeof( DNS_REQUEST ), + ( void ** ) &pDNSRequest ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSGenerateIdentifier( &pDNSRequest->wIdentification ); + BAIL_ON_ERROR( dwError ); + +/* + wOpcode <<= 1; + wRecursionDesired <<= 7; + wParameter |= wOpcode; + wParameter |= wRecursionDesired; +*/ + pDNSRequest->wParameter = 0x00; + + *ppDNSRequest = pDNSRequest; + + return dwError; + + error: + + *ppDNSRequest = NULL; + return dwError; +} -- cgit