diff options
Diffstat (limited to 'source3/libaddns/dnsresponse.c')
-rw-r--r-- | source3/libaddns/dnsresponse.c | 589 |
1 files changed, 589 insertions, 0 deletions
diff --git a/source3/libaddns/dnsresponse.c b/source3/libaddns/dnsresponse.c new file mode 100644 index 0000000000..65a8853049 --- /dev/null +++ b/source3/libaddns/dnsresponse.c @@ -0,0 +1,589 @@ +/* + Linux DNS client library implementation + + Copyright (C) 2006 Krishna Ganugapati <krishnag@centeris.com> + Copyright (C) 2006 Gerald Carter <jerry@samba.org> + + ** 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 DNSStdAllocateResponse( DNS_RESPONSE ** ppDNSResponse ) +{ + int32 dwError = 0; + DNS_RESPONSE *pDNSResponse = NULL; + + dwError = + DNSAllocateMemory( sizeof( DNS_RESPONSE ), + ( void ** ) &pDNSResponse ); + BAIL_ON_ERROR( dwError ); + + *ppDNSResponse = pDNSResponse; + + return dwError; + + error: + + *ppDNSResponse = NULL; + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +static int32 DNSStdUnmarshallQuestionSection( HANDLE hReceiveBuffer, + int16 wQuestions, + DNS_QUESTION_RECORD * + **pppDNSQuestionRecords ) +{ + int32 dwError = 0; + int32 i = 0; + int32 dwRead = 0; + DNS_QUESTION_RECORD *pDNSQuestionRecord = NULL; + DNS_QUESTION_RECORD **ppDNSQuestionRecords = NULL; + int16 wnQueryClass = 0; + int16 wnQueryType = 0; + + + dwError = + DNSAllocateMemory( wQuestions * + sizeof( DNS_QUESTION_RECORD * ), + ( void ** ) &ppDNSQuestionRecords ); + BAIL_ON_ERROR( dwError ); + + for ( i = 0; i < wQuestions; i++ ) { + + dwError = + DNSAllocateMemory( sizeof( DNS_QUESTION_RECORD ), + ( void ** ) &pDNSQuestionRecord ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSUnmarshallDomainName( hReceiveBuffer, + &pDNSQuestionRecord-> + pDomainName ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSUnmarshallBuffer( hReceiveBuffer, + ( uint8 * ) & wnQueryType, + ( int32 ) sizeof( int16 ), + &dwRead ); + BAIL_ON_ERROR( dwError ); + pDNSQuestionRecord->wQueryType = ntohs( wnQueryType ); + + dwError = + DNSUnmarshallBuffer( hReceiveBuffer, + ( uint8 * ) & wnQueryClass, + ( int32 ) sizeof( int16 ), + &dwRead ); + BAIL_ON_ERROR( dwError ); + pDNSQuestionRecord->wQueryClass = ntohs( wnQueryClass ); + + *( ppDNSQuestionRecords + i ) = pDNSQuestionRecord; + } + + *pppDNSQuestionRecords = ppDNSQuestionRecords; + return dwError; + + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +static int32 DNSStdUnmarshallAnswerSection( HANDLE hReceiveBuffer, + int16 wAnswers, + DNS_RR_RECORD * **pppDNSAnswerRRRecords ) +{ + int32 dwError = 0; + int32 i = 0; + DNS_RR_RECORD *pDNSRRRecord = NULL; + DNS_RR_RECORD **ppDNSAnswerRRRecords = NULL; + DNS_RR_HEADER RRHeader = { 0 }; + DNS_RR_HEADER *pRRHeader = &RRHeader; + uint8 *pRData = NULL; + int32 dwRead = 0; + + dwError = DNSAllocateMemory( wAnswers * sizeof( DNS_RR_RECORD * ), + ( void ** ) &ppDNSAnswerRRRecords ); + BAIL_ON_ERROR( dwError ); + + for ( i = 0; i < wAnswers; i++ ) { + + memset( pRRHeader, 0, sizeof( DNS_RR_HEADER ) ); + dwError = DNSUnmarshallRRHeader( hReceiveBuffer, pRRHeader ); + BAIL_ON_ERROR( dwError ); + + + dwError = + DNSUnmarshallRData( hReceiveBuffer, + pRRHeader->wRDataSize, &pRData, + &dwRead ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSAllocateMemory( sizeof( DNS_RR_RECORD ), + ( void ** ) &pDNSRRRecord ); + BAIL_ON_ERROR( dwError ); + + memcpy( &pDNSRRRecord->RRHeader, pRRHeader, + sizeof( DNS_RR_HEADER ) ); + pDNSRRRecord->pRData = pRData; + + *( ppDNSAnswerRRRecords + i ) = pDNSRRRecord; + } + + *pppDNSAnswerRRRecords = ppDNSAnswerRRRecords; + + return dwError; + + error: + + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +static int32 DNSStdUnmarshallAuthoritySection( HANDLE hReceiveBuffer, + int16 wAuthoritys, + DNS_RR_RECORD * **pppDNSAuthorityRRRecords ) +{ + int32 dwError = 0; + int32 i = 0; + DNS_RR_RECORD *pDNSRRRecord = NULL; + DNS_RR_RECORD **ppDNSAuthorityRRRecords = NULL; + DNS_RR_HEADER RRHeader = { 0 }; + DNS_RR_HEADER *pRRHeader = &RRHeader; + uint8 *pRData = NULL; + int32 dwRead = 0; + + dwError = DNSAllocateMemory( wAuthoritys * sizeof( DNS_RR_RECORD * ), + ( void ** ) &ppDNSAuthorityRRRecords ); + BAIL_ON_ERROR( dwError ); + + for ( i = 0; i < wAuthoritys; i++ ) { + + memset( pRRHeader, 0, sizeof( DNS_RR_HEADER ) ); + dwError = DNSUnmarshallRRHeader( hReceiveBuffer, pRRHeader ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSUnmarshallRData( hReceiveBuffer, + pRRHeader->wRDataSize, &pRData, + &dwRead ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSAllocateMemory( sizeof( DNS_RR_RECORD ), + ( void ** ) &pDNSRRRecord ); + BAIL_ON_ERROR( dwError ); + + memcpy( &pDNSRRRecord->RRHeader, pRRHeader, + sizeof( DNS_RR_HEADER ) ); + pDNSRRRecord->pRData = pRData; + + *( ppDNSAuthorityRRRecords + i ) = pDNSRRRecord; + } + + *pppDNSAuthorityRRRecords = ppDNSAuthorityRRRecords; + + return dwError; + + error: + + return dwError; + +} + +/********************************************************************* +*********************************************************************/ + +static int32 DNSStdUnmarshallAdditionalSection( HANDLE hReceiveBuffer, + int16 wAdditionals, + DNS_RR_RECORD * + **pppDNSAdditionalsRRRecords ) +{ + int32 dwError = 0; + int32 i = 0; + DNS_RR_RECORD *pDNSRRRecord = NULL; + DNS_RR_RECORD **ppDNSAdditionalRRRecords = NULL; + DNS_RR_HEADER RRHeader = { 0 }; + DNS_RR_HEADER *pRRHeader = &RRHeader; + uint8 *pRData = NULL; + int32 dwRead = 0; + + dwError = DNSAllocateMemory( wAdditionals * sizeof( DNS_RR_RECORD * ), + ( void ** ) &ppDNSAdditionalRRRecords ); + BAIL_ON_ERROR( dwError ); + + for ( i = 0; i < wAdditionals; i++ ) { + + memset( pRRHeader, 0, sizeof( DNS_RR_HEADER ) ); + dwError = DNSUnmarshallRRHeader( hReceiveBuffer, pRRHeader ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSUnmarshallRData( hReceiveBuffer, + pRRHeader->wRDataSize, &pRData, + &dwRead ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSAllocateMemory( sizeof( DNS_RR_RECORD ), + ( void ** ) &pDNSRRRecord ); + BAIL_ON_ERROR( dwError ); + + memcpy( &pDNSRRRecord->RRHeader, pRRHeader, + sizeof( DNS_RR_HEADER ) ); + pDNSRRRecord->pRData = pRData; + + + *( ppDNSAdditionalRRRecords + i ) = pDNSRRRecord; + } + + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSStdReceiveStdResponse( HANDLE hDNSHandle, DNS_RESPONSE ** ppDNSResponse ) +{ + DNS_RESPONSE *pDNSResponse = NULL; + int32 dwError = 0; + int16 wnIdentification, wIdentification = 0; + int16 wnParameter, wParameter = 0; + int16 wnQuestions, wQuestions = 0; + int16 wnAnswers, wAnswers = 0; + int16 wnAdditionals, wAdditionals = 0; + int16 wnAuthoritys, wAuthoritys = 0; + int32 dwRead = 0; + DNS_RR_RECORD **ppDNSAnswerRecords = NULL; + DNS_RR_RECORD **ppDNSAdditionalRecords = NULL; + DNS_RR_RECORD **ppDNSAuthorityRecords = NULL; + DNS_QUESTION_RECORD **ppDNSQuestionRecords = NULL; + HANDLE hRecvBuffer = ( HANDLE ) NULL; + + dwError = DNSCreateReceiveBuffer( &hRecvBuffer ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSReceiveBufferContext( hDNSHandle, hRecvBuffer, &dwRead ); + BAIL_ON_ERROR( dwError ); + +#if 0 + dwError = DNSDumpRecvBufferContext( hRecvBuffer ); + BAIL_ON_ERROR( dwError ); +#endif + + dwError = + DNSUnmarshallBuffer( hRecvBuffer, + ( uint8 * ) & wnIdentification, + sizeof( int16 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + wIdentification = ntohs( wnIdentification ); + + dwError = + DNSUnmarshallBuffer( hRecvBuffer, ( uint8 * ) & wnParameter, + sizeof( int16 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + wParameter = ntohs( wnParameter ); + + + dwError = + DNSUnmarshallBuffer( hRecvBuffer, ( uint8 * ) & wnQuestions, + sizeof( int16 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + wQuestions = ntohs( wnQuestions ); + + + dwError = + DNSUnmarshallBuffer( hRecvBuffer, ( uint8 * ) & wnAnswers, + sizeof( int16 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + wAnswers = ntohs( wnAnswers ); + + + dwError = + DNSUnmarshallBuffer( hRecvBuffer, ( uint8 * ) & wnAuthoritys, + sizeof( int16 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + wAuthoritys = ntohs( wnAuthoritys ); + + dwError = + DNSUnmarshallBuffer( hRecvBuffer, ( uint8 * ) & wnAdditionals, + sizeof( int16 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + wAdditionals = ntohs( wnAdditionals ); + + + if ( wQuestions ) { + dwError = + DNSStdUnmarshallQuestionSection( hRecvBuffer, + wQuestions, + &ppDNSQuestionRecords ); + BAIL_ON_ERROR( dwError ); + } + + if ( wAnswers ) { + dwError = + DNSStdUnmarshallAnswerSection( hRecvBuffer, wAnswers, + &ppDNSAnswerRecords ); + BAIL_ON_ERROR( dwError ); + } + + if ( wAuthoritys ) { + dwError = + DNSStdUnmarshallAuthoritySection( hRecvBuffer, + wAuthoritys, + &ppDNSAuthorityRecords ); + BAIL_ON_ERROR( dwError ); + } + + if ( wAdditionals ) { + dwError = + DNSStdUnmarshallAdditionalSection( hRecvBuffer, + wAdditionals, + &ppDNSAdditionalRecords ); + BAIL_ON_ERROR( dwError ); + } + + dwError = DNSStdAllocateResponse( &pDNSResponse ); + BAIL_ON_ERROR( dwError ); + + pDNSResponse->wIdentification = wIdentification; + pDNSResponse->wParameter = wParameter; + pDNSResponse->wQuestions = wQuestions; + pDNSResponse->wAnswers = wAnswers; + pDNSResponse->wAuthoritys = wAuthoritys; + pDNSResponse->wAdditionals = wAdditionals; + + pDNSResponse->ppQuestionRRSet = ppDNSQuestionRecords; + pDNSResponse->ppAnswerRRSet = ppDNSAnswerRecords; + pDNSResponse->ppAuthorityRRSet = ppDNSAuthorityRecords; + pDNSResponse->ppAdditionalRRSet = ppDNSAdditionalRecords; + + *ppDNSResponse = pDNSResponse; + + + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSUnmarshallDomainName( HANDLE hRecvBuffer, DNS_DOMAIN_NAME ** ppDomainName ) +{ + int32 dwError = 0; + DNS_DOMAIN_LABEL *pLabel = NULL; + DNS_DOMAIN_LABEL *pLabelList = NULL; + DNS_DOMAIN_NAME *pDomainName = NULL; + char *pszLabel = NULL; + char szLabel[65]; + uint8 uLen = 0; + int32 dwRead = 0; + uint8 uLen1, uLen2 = 0; + int16 wnOffset, wOffset = 0; + + dwError = + DNSUnmarshallBuffer( hRecvBuffer, &uLen1, sizeof( char ), + &dwRead ); + BAIL_ON_ERROR( dwError ); + if ( uLen1 & 0xC0 ) { + + uLen1 |= 0x3F; + dwError = + DNSUnmarshallBuffer( hRecvBuffer, &uLen2, + sizeof( char ), &dwRead ); + BAIL_ON_ERROR( dwError ); + + memcpy( ( uint8 * ) & wnOffset, &uLen1, sizeof( char ) ); + memcpy( ( uint8 * ) & wnOffset + 1, &uLen2, sizeof( char ) ); + wOffset = ntohs( wnOffset ); + + dwError = + DNSUnmarshallDomainNameAtOffset( hRecvBuffer, wOffset, + &pDomainName ); + BAIL_ON_ERROR( dwError ); + *ppDomainName = pDomainName; + + return dwError; + + } else { + + dwError = DNSReceiveBufferMoveBackIndex( hRecvBuffer, 1 ); + BAIL_ON_ERROR( dwError ); + + while ( 1 ) { + + + dwError = + DNSUnmarshallBuffer( hRecvBuffer, &uLen, + sizeof( char ), + &dwRead ); + BAIL_ON_ERROR( dwError ); + if ( uLen == 0 ) { + break; + } + + memset( szLabel, 0, 65 ); + dwError = + DNSUnmarshallBuffer( hRecvBuffer, + ( uint8 * ) szLabel, + uLen, &dwRead ); + + dwError = DNSAllocateString( szLabel, &pszLabel ); + BAIL_ON_ERROR( dwError ); + + dwError = + DNSAllocateMemory( sizeof( DNS_DOMAIN_LABEL ), + ( void ** ) &pLabel ); + BAIL_ON_ERROR( dwError ); + + pLabel->pszLabel = pszLabel; + dwError = + DNSAppendLabel( pLabelList, pLabel, + &pLabelList ); + BAIL_ON_ERROR( dwError ); + } + + } + + dwError = + DNSAllocateMemory( sizeof( DNS_DOMAIN_NAME ), + ( void ** ) &pDomainName ); + BAIL_ON_ERROR( dwError ); + pDomainName->pLabelList = pLabelList; + + *ppDomainName = pDomainName; + + return dwError; + + error: + + *ppDomainName = NULL; + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSUnmarshallRRHeader( HANDLE hRecvBuffer, DNS_RR_HEADER * pRRHeader ) +{ + int32 dwError = 0; + int32 dwRead = 0; + int16 wnType = 0; + int16 wnClass = 0; + int16 wnRDataSize = 0; + int32 dwnTTL = 0; + + dwError = + DNSUnmarshallDomainName( hRecvBuffer, + &pRRHeader->pDomainName ); + BAIL_ON_ERROR( dwError ); + + + dwError = + DNSUnmarshallBuffer( hRecvBuffer, ( uint8 * ) & wnType, + sizeof( int16 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + pRRHeader->wType = ntohs( wnType ); + + + dwError = + DNSUnmarshallBuffer( hRecvBuffer, ( uint8 * ) & wnClass, + sizeof( int16 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + pRRHeader->wClass = ntohs( wnClass ); + + dwError = + DNSUnmarshallBuffer( hRecvBuffer, ( uint8 * ) & dwnTTL, + sizeof( int32 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + pRRHeader->dwTTL = ntohl( dwnTTL ); + + dwError = + DNSUnmarshallBuffer( hRecvBuffer, ( uint8 * ) & wnRDataSize, + sizeof( int16 ), &dwRead ); + BAIL_ON_ERROR( dwError ); + pRRHeader->wRDataSize = htons( wnRDataSize ); + + error: + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSUnmarshallRData( HANDLE hRecvBuffer, + int32 dwSize, uint8 ** ppRData, int32 * pdwRead ) +{ + int32 dwError = 0; + uint8 *pMemory = NULL; + + dwError = DNSAllocateMemory( dwSize, ( void ** ) &pMemory ); + BAIL_ON_ERROR( dwError ); + dwError = + DNSUnmarshallBuffer( hRecvBuffer, ( uint8 * ) pMemory, dwSize, + pdwRead ); + BAIL_ON_ERROR( dwError ); + + *ppRData = pMemory; + + return dwError; + + error: + + if ( pMemory ) { + DNSFreeMemory( pMemory ); + } + + *ppRData = NULL; + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSUpdateGetResponseCode( DNS_UPDATE_RESPONSE * pDNSUpdateResponse, + int32 * pdwResponseCode ) +{ + int32 dwError = 0; + + *pdwResponseCode = + MapDNSResponseCodes( pDNSUpdateResponse->wParameter ); + + return dwError; +} + |