/* 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" /********************************************************************* *********************************************************************/ int32 DNSCreateDeleteRecord( char *szHost, int16 wClass, int16 wType, DNS_RR_RECORD ** ppDNSRecord ) { int32 dwError = 0; DNS_RR_RECORD *pDNSRRRecord = NULL; DNS_DOMAIN_NAME *pDomainName = NULL; dwError = DNSDomainNameFromString( szHost, &pDomainName ); BAIL_ON_ERROR( dwError ); dwError = DNSAllocateMemory( sizeof( DNS_RR_RECORD ), ( void * ) &pDNSRRRecord ); BAIL_ON_ERROR( dwError ); pDNSRRRecord->RRHeader.dwTTL = 0; pDNSRRRecord->RRHeader.wClass = wClass; pDNSRRRecord->RRHeader.wType = wType; pDNSRRRecord->RRHeader.pDomainName = pDomainName; pDNSRRRecord->RRHeader.wRDataSize = 0; *ppDNSRecord = pDNSRRRecord; return dwError; error: if ( pDomainName ) { DNSFreeDomainName( pDomainName ); } if ( pDNSRRRecord ) { DNSFreeMemory( pDNSRRRecord ); } *ppDNSRecord = NULL; return dwError; } /********************************************************************* *********************************************************************/ int32 DNSCreateARecord( char *szHost, int16 wClass, int16 wType, int32 dwIP, DNS_RR_RECORD ** ppDNSRecord ) { int32 dwError = 0; DNS_RR_RECORD *pDNSRRRecord = NULL; DNS_DOMAIN_NAME *pDomainName = NULL; uint8 *pRData = NULL; int32 dwnIP = 0; dwError = DNSDomainNameFromString( szHost, &pDomainName ); BAIL_ON_ERROR( dwError ); dwError = DNSAllocateMemory( sizeof( DNS_RR_RECORD ), ( void * ) &pDNSRRRecord ); BAIL_ON_ERROR( dwError ); pDNSRRRecord->RRHeader.wType = wType; pDNSRRRecord->RRHeader.pDomainName = pDomainName; pDNSRRRecord->RRHeader.wClass = wClass; pDNSRRRecord->RRHeader.wRDataSize = 0; pDNSRRRecord->RRHeader.dwTTL = 0; if ( wClass != DNS_CLASS_ANY ) { pDNSRRRecord->RRHeader.dwTTL = DNS_ONE_DAY_IN_SECS; pDNSRRRecord->RRHeader.wRDataSize = sizeof( int32 ); dwError = DNSAllocateMemory( sizeof( int32 ), ( void * ) &pRData ); dwnIP = htonl( dwIP ); memcpy( pRData, &dwnIP, sizeof( int32 ) ); pDNSRRRecord->pRData = pRData; } *ppDNSRecord = pDNSRRRecord; return dwError; error: if ( pDomainName ) { DNSFreeDomainName( pDomainName ); } if ( pDNSRRRecord ) { DNSFreeMemory( pDNSRRRecord ); } if ( pDNSRRRecord ) { DNSFreeMemory( pRData ); } *ppDNSRecord = NULL; return dwError; } /********************************************************************* *********************************************************************/ int32 DNSCreateTKeyRecord( char *szKeyName, uint8 * pKeyData, int16 wKeySize, DNS_RR_RECORD ** ppDNSRecord ) { int32 dwError = 0; DNS_RR_RECORD *pDNSRecord = NULL; DNS_DOMAIN_NAME *pAlgorithmName = NULL; DNS_DOMAIN_NAME *pDomainName = NULL; time_t t; int32 dwRDataSize = 0; int32 dwnInception, dwInception = 0; int32 dwnExpiration, dwExpiration = 0; int16 wnMode, wMode = 0; int16 wnError, wError = 0; int16 wnKeySize = 0; int16 wnOtherSize, wOtherSize = 0; int32 dwAlgorithmLen = 0; int32 dwCopied = 0; int32 dwOffset = 0; uint8 *pRData = NULL; char szTemp[20]; dwError = DNSAllocateMemory( sizeof( DNS_RR_RECORD ), ( void * ) &pDNSRecord ); BAIL_ON_ERROR( dwError ); dwError = DNSDomainNameFromString( szKeyName, &pDomainName ); BAIL_ON_ERROR( dwError ); strncpy( szTemp, "gss.microsoft.com", sizeof( szTemp ) ); dwError = DNSDomainNameFromString( szTemp, &pAlgorithmName ); BAIL_ON_ERROR( dwError ); pDNSRecord->RRHeader.dwTTL = 0; pDNSRecord->RRHeader.pDomainName = pDomainName; pDNSRecord->RRHeader.wClass = DNS_CLASS_ANY; pDNSRecord->RRHeader.wType = QTYPE_TKEY; time( &t ); dwExpiration = ( int32 ) t + DNS_ONE_DAY_IN_SECS; dwInception = ( int32 ) t; wError = 0; wMode = 3; dwError = DNSGetDomainNameLength( pAlgorithmName, &dwAlgorithmLen ); BAIL_ON_ERROR( dwError ); dwRDataSize = dwAlgorithmLen + sizeof( dwExpiration ) + sizeof( dwInception ) + sizeof( wError ) + sizeof( wMode ) + +sizeof( wError ) + sizeof( wKeySize ) + wKeySize + sizeof( wOtherSize ) + wOtherSize; dwError = DNSAllocateMemory( dwRDataSize, ( void * ) &pRData ); BAIL_ON_ERROR( dwError ); dwnInception = htonl( dwInception ); dwnExpiration = htonl( dwExpiration ); wnMode = htons( wMode ); wnError = htons( wError ); wnKeySize = htons( wKeySize ); wnOtherSize = htons( wOtherSize ); dwError = DNSCopyDomainName( pRData, pAlgorithmName, &dwCopied ); BAIL_ON_ERROR( dwError ); dwOffset += dwCopied; memcpy( pRData + dwOffset, &dwnInception, sizeof( int32 ) ); dwOffset += sizeof( int32 ); memcpy( pRData + dwOffset, &dwnExpiration, sizeof( int32 ) ); dwOffset += sizeof( int32 ); memcpy( pRData + dwOffset, &wnMode, sizeof( int16 ) ); dwOffset += sizeof( int16 ); memcpy( pRData + dwOffset, &wnError, sizeof( int16 ) ); dwOffset += sizeof( int16 ); memcpy( pRData + dwOffset, &wnKeySize, sizeof( int16 ) ); dwOffset += sizeof( int16 ); memcpy( pRData + dwOffset, pKeyData, wKeySize ); dwOffset += wKeySize; memcpy( pRData + dwOffset, &wnOtherSize, sizeof( int16 ) ); dwOffset += sizeof( int16 ); pDNSRecord->RRHeader.wRDataSize = ( int16 ) dwRDataSize; pDNSRecord->pRData = pRData; *ppDNSRecord = pDNSRecord; return dwError; error: if ( pDNSRecord ) { DNSFreeMemory( pDNSRecord ); } if ( pDomainName ) { DNSFreeDomainName( pDomainName ); } if ( pAlgorithmName ) { DNSFreeDomainName( pAlgorithmName ); } *ppDNSRecord = NULL; return dwError; } /********************************************************************* *********************************************************************/ int32 DNSCreateTSIGRecord( char *szKeyName, int32 dwTimeSigned, int16 wFudge, int16 wOriginalID, uint8 * pMac, int16 wMacSize, DNS_RR_RECORD ** ppDNSRecord ) { int32 dwError = 0; DNS_RR_RECORD *pDNSRecord = NULL; DNS_DOMAIN_NAME *pAlgorithmName = NULL; DNS_DOMAIN_NAME *pDomainName = NULL; time_t t; int32 dwRDataSize = 0; int16 wnFudge = 0; int16 wnError = 0, wError = 0; int16 wnMacSize = 0; int16 wnOriginalID = 0; int16 wnOtherLen = 0, wOtherLen = 0; int32 dwAlgorithmLen = 0; int32 dwCopied = 0; int32 dwOffset = 0; uint8 *pRData = NULL; int32 dwnTimeSigned = 0; int16 wnTimePrefix = 0; int16 wTimePrefix = 0; char szTemp[20]; dwError = DNSAllocateMemory( sizeof( DNS_RR_RECORD ), ( void * ) &pDNSRecord ); BAIL_ON_ERROR( dwError ); dwError = DNSDomainNameFromString( szKeyName, &pDomainName ); BAIL_ON_ERROR( dwError ); strncpy( szTemp, "gss.microsoft.com", sizeof( szTemp ) ); dwError = DNSDomainNameFromString( szTemp, &pAlgorithmName ); BAIL_ON_ERROR( dwError ); pDNSRecord->RRHeader.dwTTL = 0; pDNSRecord->RRHeader.pDomainName = pDomainName; pDNSRecord->RRHeader.wClass = DNS_CLASS_ANY; pDNSRecord->RRHeader.wType = QTYPE_TSIG; /* This needs to be a 48bit value - 6 octets. */ time( &t ); dwError = DNSGetDomainNameLength( pAlgorithmName, &dwAlgorithmLen ); BAIL_ON_ERROR( dwError ); dwRDataSize = dwAlgorithmLen + 6 + sizeof( wFudge ) + sizeof( wMacSize ) + wMacSize + sizeof( wOriginalID ) + sizeof( wError ) + sizeof( wOtherLen ); dwError = DNSAllocateMemory( dwRDataSize, ( void * ) &pRData ); BAIL_ON_ERROR( dwError ); /* Convert t to 48 bit network order */ wnTimePrefix = htons( wTimePrefix ); dwnTimeSigned = htonl( dwTimeSigned ); wnFudge = htons( wFudge ); wnMacSize = htons( wMacSize ); wnOriginalID = htons( wOriginalID ); wnError = htons( wError ); wnOtherLen = htons( wOtherLen ); dwError = DNSCopyDomainName( pRData, pAlgorithmName, &dwCopied ); BAIL_ON_ERROR( dwError ); dwOffset += dwCopied; memcpy( pRData + dwOffset, &wnTimePrefix, sizeof( int16 ) ); dwOffset += sizeof( int16 ); memcpy( pRData + dwOffset, &dwnTimeSigned, sizeof( int32 ) ); dwOffset += sizeof( int32 ); memcpy( pRData + dwOffset, &wnFudge, sizeof( int16 ) ); dwOffset += sizeof( int16 ); memcpy( pRData + dwOffset, &wnMacSize, sizeof( int16 ) ); dwOffset += sizeof( int16 ); memcpy( pRData + dwOffset, pMac, wMacSize ); dwOffset += wMacSize; memcpy( pRData + dwOffset, &wnOriginalID, sizeof( int16 ) ); dwOffset += sizeof( int16 ); memcpy( pRData + dwOffset, &wnError, sizeof( int16 ) ); dwOffset += sizeof( int16 ); memcpy( pRData + dwOffset, &wnOtherLen, sizeof( int16 ) ); dwOffset += sizeof( int16 ); pDNSRecord->RRHeader.wRDataSize = ( int16 ) dwRDataSize; pDNSRecord->pRData = pRData; *ppDNSRecord = pDNSRecord; return dwError; error: if ( pDNSRecord ) { DNSFreeMemory( pDNSRecord ); } if ( pDomainName ) { DNSFreeDomainName( pDomainName ); } if ( pAlgorithmName ) { DNSFreeDomainName( pAlgorithmName ); } *ppDNSRecord = NULL; return dwError; } /********************************************************************* *********************************************************************/ int32 DNSCreateQuestionRecord( char *pszQName, int16 wQType, int16 wQClass, DNS_QUESTION_RECORD ** ppDNSQuestionRecord ) { int32 dwError = 0; DNS_QUESTION_RECORD *pDNSQuestionRecord = NULL; DNS_DOMAIN_NAME *pDomainName = NULL; dwError = DNSDomainNameFromString( pszQName, &pDomainName ); BAIL_ON_ERROR( dwError ); dwError = DNSAllocateMemory( sizeof( DNS_QUESTION_RECORD ), ( void * ) &pDNSQuestionRecord ); BAIL_ON_ERROR( dwError ); pDNSQuestionRecord->pDomainName = pDomainName; pDNSQuestionRecord->wQueryClass = wQClass; pDNSQuestionRecord->wQueryType = wQType; *ppDNSQuestionRecord = pDNSQuestionRecord; return dwError; error: if ( pDomainName ) { DNSFreeDomainName( pDomainName ); } if ( pDNSQuestionRecord ) { DNSFreeMemory( pDNSQuestionRecord ); } *ppDNSQuestionRecord = NULL; return dwError; } /********************************************************************* *********************************************************************/ int32 DNSCreateZoneRecord( const char *pszZName, DNS_ZONE_RECORD ** ppDNSZoneRecord ) { int32 dwError = 0; DNS_ZONE_RECORD *pDNSZoneRecord = NULL; DNS_DOMAIN_NAME *pDomainName = NULL; dwError = DNSDomainNameFromString( pszZName, &pDomainName ); BAIL_ON_ERROR( dwError ); dwError = DNSAllocateMemory( sizeof( DNS_ZONE_RECORD ), ( void * ) &pDNSZoneRecord ); BAIL_ON_ERROR( dwError ); pDNSZoneRecord->pDomainName = pDomainName; pDNSZoneRecord->wZoneClass = DNS_CLASS_IN; pDNSZoneRecord->wZoneType = QTYPE_SOA; *ppDNSZoneRecord = pDNSZoneRecord; return dwError; error: if ( pDomainName ) { DNSFreeDomainName( pDomainName ); } if ( pDNSZoneRecord ) { DNSFreeMemory( pDNSZoneRecord ); } *ppDNSZoneRecord = NULL; return dwError; } int32 DNSFreeZoneRecord( DNS_ZONE_RECORD * pDNSZoneRecord ) { int32 dwError = 0; return dwError; } /********************************************************************* *********************************************************************/ int32 DNSCreateNameInUseRecord( char *pszName, int32 qtype, struct in_addr * ip, DNS_RR_RECORD * *ppDNSRRRecord ) { int32 dwError = 0; DNS_RR_RECORD *pDNSRRRecord = NULL; DNS_DOMAIN_NAME *pDomainName = NULL; dwError = DNSDomainNameFromString( pszName, &pDomainName ); BAIL_ON_ERROR( dwError ); dwError = DNSAllocateMemory( sizeof( DNS_RR_RECORD ), ( void * ) &pDNSRRRecord ); BAIL_ON_ERROR( dwError ); pDNSRRRecord->RRHeader.pDomainName = pDomainName; pDNSRRRecord->RRHeader.dwTTL = 0; pDNSRRRecord->RRHeader.wType = qtype; if ( !ip ) { pDNSRRRecord->RRHeader.wClass = DNS_CLASS_ANY; pDNSRRRecord->RRHeader.wRDataSize = 0; } else { pDNSRRRecord->RRHeader.wClass = DNS_CLASS_IN; pDNSRRRecord->RRHeader.wRDataSize = 4; dwError = DNSAllocateMemory( 4, ( void * ) &pDNSRRRecord-> pRData ); BAIL_ON_ERROR( dwError ); memcpy( pDNSRRRecord->pRData, &ip->s_addr, 4 ); } *ppDNSRRRecord = pDNSRRRecord; return dwError; error: if ( pDomainName ) { DNSFreeDomainName( pDomainName ); } if ( pDNSRRRecord ) { DNSFreeMemory( pDNSRRRecord ); } *ppDNSRRRecord = NULL; return dwError; } /********************************************************************* *********************************************************************/ int32 DNSCreateNameNotInUseRecord( char *pszName, int32 qtype, DNS_RR_RECORD * *ppDNSRRRecord ) { int32 dwError = 0; DNS_RR_RECORD *pDNSRRRecord = NULL; DNS_DOMAIN_NAME *pDomainName = NULL; dwError = DNSDomainNameFromString( pszName, &pDomainName ); BAIL_ON_ERROR( dwError ); dwError = DNSAllocateMemory( sizeof( DNS_RR_RECORD ), ( void * ) &pDNSRRRecord ); BAIL_ON_ERROR( dwError ); pDNSRRRecord->RRHeader.pDomainName = pDomainName; pDNSRRRecord->RRHeader.wClass = DNS_CLASS_NONE; pDNSRRRecord->RRHeader.wType = qtype; pDNSRRRecord->RRHeader.dwTTL = 0; pDNSRRRecord->RRHeader.wRDataSize = 0; *ppDNSRRRecord = pDNSRRRecord; return dwError; error: if ( pDomainName ) { DNSFreeDomainName( pDomainName ); } if ( pDNSRRRecord ) { DNSFreeMemory( pDNSRRRecord ); } *ppDNSRRRecord = NULL; return dwError; }