/* 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; }