diff options
Diffstat (limited to 'source3/libaddns/dnsutils.c')
-rw-r--r-- | source3/libaddns/dnsutils.c | 596 |
1 files changed, 596 insertions, 0 deletions
diff --git a/source3/libaddns/dnsutils.c b/source3/libaddns/dnsutils.c new file mode 100644 index 0000000000..6071d35d53 --- /dev/null +++ b/source3/libaddns/dnsutils.c @@ -0,0 +1,596 @@ +/* + 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" +#include <ctype.h> + +#define TRUE 1 +#define FALSE 0 + +#define STATE_BEGIN 0 +#define STATE_LABEL 1 +#define STATE_FINISH 2 + +#define TOKEN_LABEL 1 +#define TOKEN_SEPARATOR 2 +#define TOKEN_EOS 3 + +/********************************************************************* +*********************************************************************/ + +static int32 getToken( char *pszString, char *pszToken, int32 * pdwToken, + int32 * pdwPosition ) +{ + int32 dwError = 0; + char c = 0; + int32 dwToken = 0; + int32 i = 0; + int32 dwState = 0; + int32 dwPosition = 0; + + dwPosition = *pdwPosition; + dwState = STATE_BEGIN; + while ( dwState != STATE_FINISH ) { + c = pszString[dwPosition]; + if ( c == '\0' ) { + if ( dwState == STATE_LABEL ) { + dwToken = TOKEN_LABEL; + dwState = STATE_FINISH; + continue; + } else if ( dwState == STATE_BEGIN ) { + dwToken = TOKEN_EOS; + dwState = STATE_FINISH; + continue; + } + } else if ( isalnum( c ) || c == '-' ) { + pszToken[i++] = c; + dwPosition++; + dwState = STATE_LABEL; + continue; + } else if ( c == '.' ) { + if ( dwState == STATE_LABEL ) { + dwToken = TOKEN_LABEL; + dwState = STATE_FINISH; + continue; + } else if ( dwState == STATE_BEGIN ) { + dwToken = TOKEN_SEPARATOR; + dwPosition++; + dwState = STATE_FINISH; + continue; + } + } else { + if ( dwState == STATE_LABEL ) { + dwToken = TOKEN_LABEL; + dwState = STATE_FINISH; + } else if ( dwState == 0 ) { + dwError = ERROR_INVALID_PARAMETER; + dwState = STATE_FINISH; + } + } + } + *pdwPosition = dwPosition; + *pdwToken = dwToken; + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +static int32 DNSMakeLabel( char *szLabel, DNS_DOMAIN_LABEL ** ppLabel ) +{ + DNS_DOMAIN_LABEL *pLabel = NULL; + char *pszLabel = NULL; + int32 dwError = 0; + + dwError = + DNSAllocateMemory( sizeof( DNS_DOMAIN_LABEL ), + ( void ** ) &pLabel ); + BAIL_ON_ERROR( dwError ); + + dwError = DNSAllocateString( szLabel, &pszLabel ); + BAIL_ON_ERROR( dwError ); + + pLabel->pszLabel = pszLabel; + pLabel->dwLength = ( int32 ) strlen( pszLabel ); + *ppLabel = pLabel; + return dwError; + + error: + + if ( pLabel ) { + DNSFreeMemory( pLabel ); + } + *ppLabel = NULL; + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +static void DNSFreeLabel( DNS_DOMAIN_LABEL * pLabel ) +{ + if ( pLabel ) { + DNSFreeMemory( pLabel ); + } + return; +} + +/********************************************************************* +*********************************************************************/ + +void DNSFreeLabelList(DNS_DOMAIN_LABEL *pLabelList) +{ + DNS_DOMAIN_LABEL *pTemp = NULL; + while(pLabelList) { + pTemp = pLabelList; + pLabelList = pLabelList->pNext; + DNSFreeLabel(pTemp); + } + + return; +} + +/********************************************************************* +*********************************************************************/ + +void DNSFreeDomainName(DNS_DOMAIN_NAME *pDomainName) +{ + DNSFreeLabelList(pDomainName->pLabelList); + DNSFreeMemory(pDomainName); + + return; +} + +/********************************************************************* +*********************************************************************/ + +static int32 LabelList( char *pszString, int32 * pdwPosition, DNS_DOMAIN_LABEL ** ppList ) +{ + int32 dwError = 0; + DNS_DOMAIN_LABEL *pList = NULL; + DNS_DOMAIN_LABEL *pLabel = NULL; + int32 dwToken = 0; + char szToken[64]; + + memset( szToken, 0, 64 ); + dwError = getToken( pszString, szToken, &dwToken, pdwPosition ); + BAIL_ON_ERROR( dwError ); + if ( dwToken != TOKEN_LABEL ) { + dwError = ERROR_INVALID_PARAMETER; + BAIL_ON_ERROR( dwError ); + } + + dwError = DNSMakeLabel( szToken, &pLabel ); + BAIL_ON_ERROR( dwError ); + + memset( szToken, 0, 64 ); + dwError = getToken( pszString, szToken, &dwToken, pdwPosition ); + BAIL_ON_ERROR( dwError ); + if ( dwToken == TOKEN_EOS ) { + *ppList = pLabel; + return dwError; + } else if ( dwToken == TOKEN_SEPARATOR ) { + dwError = LabelList( pszString, pdwPosition, &pList ); + BAIL_ON_ERROR( dwError ); + + pLabel->pNext = pList; + *ppList = pLabel; + } + + return dwError; + + error: + if ( pLabel ) { + DNSFreeLabel( pLabel ); + } + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +static int32 DNSGetDomainNameOffset( uint8 * pBuffer ) +{ + uint8 uLen = 0; + uint8 uLen1; + int32 dwOffset = 0; + + uLen1 = *pBuffer; + if ( uLen1 & 0xC0 ) { + dwOffset += 2; + + } else { + + while ( 1 ) { + + uLen = *pBuffer; + pBuffer++; + dwOffset++; + if ( uLen == 0 ) { + break; + } + dwOffset += uLen; + pBuffer += uLen; + } + } + return ( dwOffset ); +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSGenerateIdentifier( int16 * pwIdentifier ) +{ + int32 dwError = 0; + + *pwIdentifier = random( ); + + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSGetDomainNameLength( DNS_DOMAIN_NAME * pDomainName, int32 * pdwLength ) +{ + int32 dwError = 0; + int32 dwLength = 0; + DNS_DOMAIN_LABEL *pDomainLabel = NULL; + + if ( !pDomainName ) { + dwError = ERROR_INVALID_PARAMETER; + BAIL_ON_ERROR( dwError ); + } + pDomainLabel = pDomainName->pLabelList; + + while ( pDomainLabel ) { + dwLength += pDomainLabel->dwLength; + dwLength += 1; + pDomainLabel = pDomainLabel->pNext; + } + dwLength += 1; + *pdwLength = dwLength; + + return dwError; + error: + + *pdwLength = 0; + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSCopyDomainName( uint8 * pBuffer, + DNS_DOMAIN_NAME * pDomainName, int32 * pdwCopied ) +{ + int32 dwError = 0; + DNS_DOMAIN_LABEL *pDomainLabel = NULL; + uint8 uChar = 0; + int32 dwCopied = 0; + + if ( !pDomainName ) { + dwError = ERROR_INVALID_PARAMETER; + BAIL_ON_ERROR( dwError ); + } + + pDomainLabel = pDomainName->pLabelList; + while ( pDomainLabel ) { + uChar = ( uint8 ) pDomainLabel->dwLength; + memcpy( pBuffer + dwCopied, &uChar, sizeof( uint8 ) ); + dwCopied += sizeof( uint8 ); + memcpy( pBuffer + dwCopied, pDomainLabel->pszLabel, + pDomainLabel->dwLength ); + dwCopied += pDomainLabel->dwLength; + pDomainLabel = pDomainLabel->pNext; + } + uChar = 0; + memcpy( pBuffer + dwCopied, &uChar, sizeof( uint8 ) ); + dwCopied += sizeof( uint8 ); + + *pdwCopied = dwCopied; + return dwError; + + error: + *pdwCopied = 0; + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSGenerateKeyName( char **ppszKeyName ) +{ + int32 dwError = 0; + char *pszKeyName = NULL; + char szTemp[256]; + char szBuffer[256]; + unsigned char uuid[16]; + + memset( szTemp, 0, 256 ); + memset( szBuffer, 0, 256 ); + memset( uuid, 0, 16 ); + + uuid_generate( uuid ); + + uuid_unparse( uuid, szBuffer ); + + strcpy( szTemp, szBuffer ); + dwError = DNSAllocateString( szTemp, &pszKeyName ); + BAIL_ON_ERROR( dwError ); + + *ppszKeyName = pszKeyName; + + return dwError; + + error: + + *ppszKeyName = NULL; + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSDomainNameFromString( char *pszDomainName, + DNS_DOMAIN_NAME ** ppDomainName ) +{ + int32 dwError = 0; + int32 dwPosition = 0; + DNS_DOMAIN_NAME *pDomainName = NULL; + DNS_DOMAIN_LABEL *pLabelList = NULL; + + if ( !pszDomainName || !*pszDomainName ) { + dwError = ERROR_INVALID_PARAMETER; + return dwError; + } + + dwError = LabelList( pszDomainName, &dwPosition, &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: + + if ( pLabelList ) { + DNSFreeLabelList( pLabelList ); + } + *ppDomainName = NULL; + + return dwError; +} + + +/********************************************************************* +*********************************************************************/ + +int32 DNSAppendLabel( DNS_DOMAIN_LABEL * pLabelList, + DNS_DOMAIN_LABEL * pLabel, + DNS_DOMAIN_LABEL ** ppNewLabelList ) +{ + DNS_DOMAIN_LABEL **ppLabelList = NULL; + int32 dwError = 0; + + if ( pLabelList == NULL ) { + *ppNewLabelList = pLabel; + return dwError; + } + + ppLabelList = &pLabelList; + + while ( ( *ppLabelList )->pNext ) { + ppLabelList = &( ( *ppLabelList )->pNext ); + } + + ( *ppLabelList )->pNext = pLabel; + *ppNewLabelList = pLabelList; + return dwError; +} + +/********************************************************************* +*********************************************************************/ + +int32 GetLastError( ) +{ + return ( errno ); +} + +/********************************************************************* +*********************************************************************/ + +int32 WSAGetLastError( void ) +{ + return ( errno ); +} + +/********************************************************************* +*********************************************************************/ + +void DNSRecordGenerateOffsets( DNS_RR_RECORD * pDNSRecord ) +{ + int32 dwOffset = 0; + uint8 *pRData = NULL; + int16 wKeySize, wnKeySize = 0; + + pRData = pDNSRecord->pRData; + switch ( pDNSRecord->RRHeader.wType ) { + case QTYPE_TKEY: + pDNSRecord->Offsets.TKey.wAlgorithmOffset = + ( int16 ) dwOffset; + dwOffset += DNSGetDomainNameOffset( pRData ); + pDNSRecord->Offsets.TKey.wInceptionOffset = + ( int16 ) dwOffset; + dwOffset += sizeof( int32 ); + pDNSRecord->Offsets.TKey.wExpirationOffset = + ( int16 ) dwOffset; + dwOffset += sizeof( int32 ); + pDNSRecord->Offsets.TKey.wModeOffset = ( int16 ) dwOffset; + dwOffset += sizeof( int16 ); + pDNSRecord->Offsets.TKey.wErrorOffset = ( int16 ) dwOffset; + dwOffset += sizeof( int16 ); + pDNSRecord->Offsets.TKey.wKeySizeOffset = ( int16 ) dwOffset; + dwOffset += sizeof( int16 ); + pDNSRecord->Offsets.TKey.wKeyDataOffset = ( int16 ) dwOffset; + + memcpy( &wnKeySize, + pRData + pDNSRecord->Offsets.TKey.wKeySizeOffset, + sizeof( int16 ) ); + wKeySize = ntohs( wnKeySize ); + + dwOffset += wKeySize; + pDNSRecord->Offsets.TKey.wOtherSizeOffset = + ( int16 ) dwOffset; + dwOffset += sizeof( int16 ); + pDNSRecord->Offsets.TKey.wOtherDataOffset = + ( int16 ) dwOffset; + break; + + case QTYPE_TSIG: + break; + } + return; +} + +/********************************************************************* +*********************************************************************/ + +int32 MapDNSResponseCodes( int16 wResponseCode ) +{ + int16 wnResponseCode = 0; + uint8 *pByte = NULL; + + wnResponseCode = htons( wResponseCode ); + pByte = ( uint8 * ) & wnResponseCode; + +#if 0 + printf( "Byte 0 - %.2x\n", pByte[0] ); + printf( "Byte 1 - %.2x\n", pByte[1] ); +#endif + /* Bit 3, 2, 1, 0 of Byte 2 represent the RCode */ + + return ( ( int32 ) pByte[1] ); +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSAllocateMemory(int32 dwSize, void * * ppMemory) +{ + + int32 dwError = 0; + void * pMemory = NULL; + + pMemory = malloc(dwSize); + if (!pMemory){ + dwError = ERROR_OUTOFMEMORY; + *ppMemory = NULL; + }else { + memset(pMemory,0, dwSize); + *ppMemory = pMemory; + } + return (dwError); +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSReallocMemory(void * pMemory, void * * ppNewMemory, int32 dwSize) +{ + int32 dwError = 0; + void * pNewMemory = NULL; + + if (pMemory == NULL) { + pNewMemory = malloc(dwSize); + memset(pNewMemory, 0, dwSize); + }else { + pNewMemory = realloc(pMemory, dwSize); + } + if (!pNewMemory){ + dwError = ERROR_OUTOFMEMORY; + *ppNewMemory = NULL; + }else { + *ppNewMemory = pNewMemory; + } + + return(dwError); +} + +/********************************************************************* +*********************************************************************/ + +void DNSFreeMemory( void * pMemory ) +{ + free(pMemory); + return; +} + +/********************************************************************* +*********************************************************************/ + +int32 DNSAllocateString(char *pszInputString, char **ppszOutputString) +{ + int32 dwError = 0; + int32 dwLen = 0; + char * pszOutputString = NULL; + + if (!pszInputString || !*pszInputString){ + dwError = ERROR_INVALID_PARAMETER; + BAIL_ON_ERROR(dwError); + } + dwLen = (int32)strlen(pszInputString); + dwError = DNSAllocateMemory(dwLen+1, (void * *)&pszOutputString); + BAIL_ON_ERROR(dwError); + + strcpy(pszOutputString, pszInputString); + + *ppszOutputString = pszOutputString; + + return(dwError); +error: + *ppszOutputString = pszOutputString; + return(dwError); +} + +/********************************************************************* +*********************************************************************/ + +void DNSFreeString(char * pszString) +{ + return; +} + + + |