aboutsummaryrefslogtreecommitdiff
path: root/dns/powerdns-devel/files/patch-opendbx
diff options
context:
space:
mode:
Diffstat (limited to 'dns/powerdns-devel/files/patch-opendbx')
-rw-r--r--dns/powerdns-devel/files/patch-opendbx1038
1 files changed, 1038 insertions, 0 deletions
diff --git a/dns/powerdns-devel/files/patch-opendbx b/dns/powerdns-devel/files/patch-opendbx
new file mode 100644
index 000000000000..3f24a01e82b4
--- /dev/null
+++ b/dns/powerdns-devel/files/patch-opendbx
@@ -0,0 +1,1038 @@
+--- modules/opendbxbackend/odbxbackend.hh 2006-03-15 19:29:39.000000000 +0100
++++ modules/opendbxbackend/odbxbackend.hh 2006-09-03 11:34:13.000000000 +0200
+@@ -1,11 +1,10 @@
+ /*
+ * PowerDNS OpenDBX Backend
+- * Copyright (C) 2005 Norbert Sendetzky <norbert@linuxnetworks.de>
++ * Copyright (C) 2005-2006 Norbert Sendetzky <norbert@linuxnetworks.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * any later version.
++ * it under the terms of the GNU General Public License version 2
++ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+@@ -14,7 +13,7 @@
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+@@ -32,7 +31,6 @@
+ #include <pdns/arguments.hh>
+ #include <pdns/logger.hh>
+ #include <odbx.h>
+-#include "modules/ldapbackend/utils.hh"
+
+
+ #ifndef ODBXBACKEND_HH
+@@ -53,19 +51,23 @@
+
+ class OdbxBackend : public DNSBackend
+ {
++ enum QueryType { READ, WRITE };
++
+ string m_myname;
+ string m_qname;
+ int m_default_ttl;
+ bool m_qlog;
+- odbx_t* m_handle;
++ odbx_t* m_handle[2];
+ odbx_result_t* m_result;
+ char m_escbuf[BUFLEN];
+ char m_buffer[2*BUFLEN];
++ vector<string> m_hosts[2];
+
+- bool getRecord();
+- void execStmt( const char* stmt, unsigned long length, bool select );
+- void getDomainList( const string& query, vector<DomainInfo>* list, bool (*check_fcn)(u_int32_t,u_int32_t,SOAData*,DomainInfo*) );
+- string escape( const string& str );
++ string escape( const string& str, QueryType type );
++ bool connectTo( const vector<string>& host, QueryType type );
++ bool getDomainList( const string& query, vector<DomainInfo>* list, bool (*check_fcn)(u_int32_t,u_int32_t,SOAData*,DomainInfo*) );
++ bool execStmt( const char* stmt, unsigned long length, QueryType type );
++ bool getRecord( QueryType type );
+
+
+ public:
+@@ -107,37 +109,40 @@
+ void declareArguments( const string &suffix="" )
+ {
+ declare( suffix, "backend", "OpenDBX backend","mysql" );
+- declare( suffix, "host", "Name or address of one or more DBMS server","127.0.0.1" );
+- declare( suffix, "port", "Port the DBMS server is listening to","" );
++ declare( suffix, "host-read", "Name or address of one or more DBMS server to read from","127.0.0.1" );
++ declare( suffix, "host-write", "Name or address of one or more DBMS server used for updates","127.0.0.1" );
++ declare( suffix, "port", "Port the DBMS server are listening to","" );
+ declare( suffix, "database", "Database name containing the DNS records","powerdns" );
+ declare( suffix, "username","User for connecting to the DBMS","powerdns");
+ declare( suffix, "password","Password for connecting to the DBMS","");
+
+- declare( suffix, "sql-list", "AXFR query", "SELECT domain_id, name, type, ttl, prio, content FROM records WHERE domain_id=':id'" );
++ declare( suffix, "sql-list", "AXFR query", "SELECT domain_id, name, type, ttl, prio, content FROM records WHERE domain_id=:id" );
+
+ declare( suffix, "sql-lookup", "Lookup query","SELECT domain_id, name, type, ttl, prio, content FROM records WHERE name=':name'" );
+- declare( suffix, "sql-lookupid", "Lookup query with id","SELECT domain_id, name, type, ttl, prio, content FROM records WHERE domain_id=':id' AND name=':name'" );
++ declare( suffix, "sql-lookupid", "Lookup query with id","SELECT domain_id, name, type, ttl, prio, content FROM records WHERE domain_id=:id AND name=':name'" );
+ declare( suffix, "sql-lookuptype", "Lookup query with type","SELECT domain_id, name, type, ttl, prio, content FROM records WHERE name=':name' AND type=':type'" );
+- declare( suffix, "sql-lookuptypeid", "Lookup query with type and id","SELECT domain_id, name, type, ttl, prio, content FROM records WHERE domain_id=':id' AND name=':name' AND type=':type'" );
++ declare( suffix, "sql-lookuptypeid", "Lookup query with type and id","SELECT domain_id, name, type, ttl, prio, content FROM records WHERE domain_id=:id AND name=':name' AND type=':type'" );
+
+- declare( suffix, "sql-zonedelete","Delete all records for this zone","DELETE FROM records WHERE domain_id=':id'" );
+- declare( suffix, "sql-zoneinfo","Get domain info","SELECT d.id, d.name, d.type, d.master, d.last_check, r.content FROM domains AS d LEFT JOIN records AS r ON d.id=r.domain_id WHERE ( d.name=':name' AND r.type='SOA' ) OR ( d.name=':name' AND r.domain_id IS NULL )" );
++ declare( suffix, "sql-zonedelete","Delete all records for this zone","DELETE FROM records WHERE domain_id=:id" );
++ declare( suffix, "sql-zoneinfo","Get domain info","SELECT d.id, d.name, d.type, d.master, d.last_check, r.content FROM domains d LEFT JOIN records r ON ( d.id=r.domain_id AND r.type='SOA' ) WHERE d.name=':name' AND d.status='A'" );
+
+ declare( suffix, "sql-transactbegin", "Start transaction", "BEGIN" );
+ declare( suffix, "sql-transactend", "Finish transaction", "COMMIT" );
+ declare( suffix, "sql-transactabort", "Abort transaction", "ROLLBACK" );
+
+ declare( suffix, "sql-insert-slave","Add slave domain", "INSERT INTO domains ( name, type, master, account ) VALUES ( '%s', 'SLAVE', '%s', '%s' )" );
+- declare( suffix, "sql-insert-record","Feed record into table", "INSERT INTO records ( domain_id, name, type, ttl, prio, content ) VALUES ( '%d', '%s', '%s', '%d', '%d', '%s' )" );
++ declare( suffix, "sql-insert-record","Feed record into table", "INSERT INTO records ( domain_id, name, type, ttl, prio, content ) VALUES ( %d, '%s', '%s', %d, %d, '%s' )" );
+
+- declare( suffix, "sql-update-serial", "Set zone to notified", "UPDATE domains SET notified_serial='%d' WHERE id='%d'" );
+- declare( suffix, "sql-update-lastcheck", "Set time of last check", "UPDATE domains SET last_check='%d' WHERE id='%d'" );
++ declare( suffix, "sql-update-serial", "Set zone to notified", "UPDATE domains SET notified_serial=%d WHERE id=%d" );
++ declare( suffix, "sql-update-lastcheck", "Set time of last check", "UPDATE domains SET last_check=%d WHERE id=%d" );
+
+- declare( suffix, "sql-master", "Get master record for zone", "SELECT master FROM domains WHERE name=':name' AND type='SLAVE'" );
++ declare( suffix, "sql-master", "Get master record for zone", "SELECT master FROM domains WHERE name=':name' AND status='A' AND type='SLAVE'" );
+ declare( suffix, "sql-supermaster","Get supermaster info", "SELECT account FROM supermasters WHERE ip=':ip' AND nameserver=':ns'" );
+
+- declare( suffix, "sql-infoslaves", "Get all unfresh slaves", "SELECT d.id, d.name, d.master, d.notified_serial, d.last_check, r.change_date, r.content FROM domains AS d LEFT JOIN records AS r ON d.id=r.domain_id WHERE ( d.type='SLAVE' AND r.type='SOA' ) OR ( d.type='SLAVE' AND r.domain_id IS NULL )" );
+- declare( suffix, "sql-infomasters", "Get all updated masters", "SELECT d.id, d.name, d.master, d.notified_serial, d.last_check, r.change_date, r.content FROM domains AS d, records AS r WHERE d.type='MASTER' AND d.id=r.domain_id AND r.type='SOA'" );
++ declare( suffix, "sql-infoslaves", "Get all unfresh slaves", "SELECT d.id, d.name, d.master, d.notified_serial, d.last_check, r.change_date, r.content FROM domains d LEFT JOIN records r ON ( d.id=r.domain_id AND r.type='SOA' ) WHERE d.status='A' AND d.type='SLAVE'" );
++ declare( suffix, "sql-infomasters", "Get all updated masters", "SELECT d.id, d.name, d.master, d.notified_serial, d.last_check, r.change_date, r.content FROM domains d JOIN records r ON d.id=r.domain_id WHERE d.status='A' AND d.type='MASTER' AND r.type='SOA'" );
++
++ declare( suffix, "host", "depricated, use host-read and host-write instead","" );
+ }
+
+
+--- modules/opendbxbackend/odbxbackend.cc 2006-03-15 19:29:39.000000000 +0100
++++ modules/opendbxbackend/odbxbackend.cc 2006-06-17 11:39:04.000000000 +0200
+@@ -2,62 +2,80 @@
+
+
+
+-unsigned int odbx_host_index = 0;
++inline string& strbind( const string& search, const string& replace, string& subject )
++{
++ size_t pos = 0;
++
++ while( ( pos = subject.find( search, pos ) ) != string::npos )
++ {
++ subject.replace( pos, search.size(), replace );
++ pos += replace.size();
++ }
++
++ return subject;
++}
++
++
++
++inline string& toLowerByRef( string& str )
++{
++ for( unsigned int i = 0; i < str.length(); i++ )
++ {
++ str[i] = dns_tolower( str[i] );
++ }
++
++ return str;
++}
+
+
+
+ OdbxBackend::OdbxBackend( const string& suffix )
+ {
+- int err = -1;
+- unsigned int idx, i, h;
+ vector<string> hosts;
+
+
+ try
+ {
+ m_result = NULL;
++ m_handle[READ] = NULL;
++ m_handle[WRITE] = NULL;
+ m_myname = "[OpendbxBackend]";
+ m_default_ttl = arg().asNum( "default-ttl" );
+ m_qlog = arg().mustDo( "query-logging" );
+
+ setArgPrefix( "opendbx" + suffix );
+- stringtok( hosts, getArg( "host" ), ", " );
+
+- idx = odbx_host_index++ % hosts.size();
+-
+- for( i = 0; i < hosts.size(); i++ )
++ if( getArg( "host" ).size() > 0 )
+ {
+- h = ( idx + i ) % hosts.size();
+- if( !( err = odbx_init( &m_handle, getArg( "backend" ).c_str(), hosts[h].c_str(), getArg( "port" ).c_str() ) ) ) { break; }
++ L.log( m_myname + " WARNING: Using depricated opendbx-host parameter", Logger::Warning );
++ stringtok( m_hosts[READ], getArg( "host" ), ", " );
++ m_hosts[WRITE] = m_hosts[READ];
+ }
+-
+- if( err < 0 )
++ else
+ {
+- L.log( m_myname + " OdbxBackend: Unable to connect to server - " + string( odbx_error( m_handle, err ) ), Logger::Error );
+- throw( AhuException( "Fatal: odbx_init() failed" ) );
++ stringtok( m_hosts[READ], getArg( "host-read" ), ", " );
++ stringtok( m_hosts[WRITE], getArg( "host-write" ), ", " );
+ }
+
+- if( ( err = odbx_bind_simple( m_handle, getArg( "database" ).c_str(), getArg( "username" ).c_str(), getArg( "password" ).c_str() ) ) < 0 )
+- {
+- L.log( m_myname + " OdbxBackend: Unable to bind to database - " + string( odbx_error( m_handle, err ) ), Logger::Error );
+- throw( AhuException( "Fatal: odbx_bind_simple() failed" ) );
+- }
++ if( !connectTo( m_hosts[READ], READ ) ) { throw( AhuException( "Fatal: Connecting to server for reading failed" ) ); }
++ if( !connectTo( m_hosts[WRITE], WRITE ) ) { throw( AhuException( "Fatal: Connecting to server for writing failed" ) ); }
+ }
+ catch( exception& e )
+ {
+- L.log( m_myname + " OdbxBackend: Caught STL exception - " + e.what(), Logger::Error );
+- throw( DBException( "Fatal: STL exception" ) );
++ L.log( m_myname + " OdbxBackend(): Caught STL exception - " + e.what(), Logger::Error );
++ throw( AhuException( "Fatal: STL exception" ) );
+ }
+-
+- L.log( m_myname + " Connection succeeded", Logger::Notice );
+ }
+
+
+
+ OdbxBackend::~OdbxBackend()
+ {
+- odbx_unbind( m_handle );
+- odbx_finish( m_handle );
++ odbx_unbind( m_handle[WRITE] );
++ odbx_unbind( m_handle[READ] );
++
++ odbx_finish( m_handle[WRITE] );
++ odbx_finish( m_handle[READ] );
+ }
+
+
+@@ -65,17 +83,17 @@
+ bool OdbxBackend::getDomainInfo( const string& domain, DomainInfo& di )
+ {
+ const char* tmp;
+- string stmt;
+
+
+ try
+ {
+ DLOG( L.log( m_myname + " getDomainInfo()", Logger::Debug ) );
+
+- stmt = strbind( ":name", escape( toLower( domain ) ), getArg( "sql-zoneinfo" ) );
+- execStmt( stmt.c_str(), stmt.size(), true );
++ string stmt = getArg( "sql-zoneinfo" );
++ string& stmtref = strbind( ":name", escape( toLower( domain ), READ ), stmt );
+
+- if( !getRecord() ) { return false; }
++ if( !execStmt( stmtref.c_str(), stmtref.size(), READ ) ) { return false; }
++ if( !getRecord( READ ) ) { return false; }
+
+ do
+ {
+@@ -95,7 +113,7 @@
+
+ if( ( tmp = odbx_field_value( m_result, 1 ) ) != NULL )
+ {
+- di.zone = string( tmp );
++ di.zone = string( tmp, odbx_field_length( m_result, 1 ) );
+ }
+
+ if( ( tmp = odbx_field_value( m_result, 2 ) ) != NULL )
+@@ -112,7 +130,7 @@
+
+ if( ( tmp = odbx_field_value( m_result, 3 ) ) != NULL )
+ {
+- di.master = string( tmp );
++ di.master = string( tmp, odbx_field_length( m_result, 3 ) );
+ }
+
+ if( ( tmp = odbx_field_value( m_result, 5 ) ) != NULL )
+@@ -125,16 +143,16 @@
+ SOAData sd;
+
+ sd.serial = 0;
+- DNSPacket::fillSOAData( string( tmp ), sd );
++ DNSPacket::fillSOAData( string( tmp, odbx_field_length( m_result, 6 ) ), sd );
+ di.serial = sd.serial;
+ }
+ }
+- while( getRecord() );
++ while( getRecord( READ ) );
+ }
+ catch( exception& e )
+ {
+ L.log( m_myname + " getDomainInfo: Caught STL exception - " + e.what(), Logger::Error );
+- throw( DBException( "Error: STL exception" ) );
++ return false;
+ }
+
+ return true;
+@@ -144,11 +162,6 @@
+
+ bool OdbxBackend::list( const string& target, int zoneid )
+ {
+- string stmt;
+- size_t len;
+-
+-
+-
+ try
+ {
+ DLOG( L.log( m_myname + " list()", Logger::Debug ) );
+@@ -156,22 +169,29 @@
+ m_qname = "";
+ m_result = NULL;
+
+- len = snprintf( m_buffer, sizeof( m_buffer ) - 1, "%d", zoneid );
++ size_t len = snprintf( m_buffer, sizeof( m_buffer ) - 1, "%d", zoneid );
+
+- if( len < 0 || len > sizeof( m_buffer ) - 1 )
++ if( len < 0 )
+ {
+- L.log( m_myname + " list: Unable to convert zone id to string", Logger::Error );
+- throw( DBException( "Error: Libc error" ) );
++ L.log( m_myname + " list: Unable to convert zone id to string - format error", Logger::Error );
++ return false;
+ }
+
+- stmt = strbind( ":id", string( m_buffer, len ), getArg( "sql-list" ) );
++ if( len > sizeof( m_buffer ) - 1 )
++ {
++ L.log( m_myname + " list: Unable to convert zone id to string - insufficient buffer space", Logger::Error );
++ return false;
++ }
++
++ string stmt = getArg( "sql-list" );
++ string& stmtref = strbind( ":id", string( m_buffer, len ), stmt );
+
+- execStmt( stmt.c_str(), stmt.size(), true );
++ if( !execStmt( stmtref.c_str(), stmtref.size(), READ ) ) { return false; }
+ }
+ catch( exception& e )
+ {
+ L.log( m_myname + " list: Caught STL exception - " + e.what(), Logger::Error );
+- throw( DBException( "Error: STL exception" ) );
++ return false;
+ }
+
+ return true;
+@@ -181,23 +201,24 @@
+
+ void OdbxBackend::lookup( const QType& qtype, const string& qname, DNSPacket* dnspkt, int zoneid )
+ {
+- string stmt;
+-
+-
+ try
+ {
+ DLOG( L.log( m_myname + " lookup()", Logger::Debug ) );
+
++ string stmt;
++ string& stmtref = stmt;
++
+ m_result = NULL;
+ m_qname = qname;
+-
++
+ if( zoneid < 0 )
+ {
+ if( qtype.getCode() == QType::ANY )
+ {
+ stmt = getArg( "sql-lookup" );
+ } else {
+- stmt = strbind( ":type", qtype.getName(), getArg( "sql-lookuptype" ) );
++ stmt = getArg( "sql-lookuptype" );
++ stmtref = strbind( ":type", qtype.getName(), stmt );
+ }
+ }
+ else
+@@ -206,22 +227,34 @@
+ {
+ stmt = getArg( "sql-lookupid" );
+ } else {
+- stmt = strbind( ":type", qtype.getName(), getArg( "sql-lookuptypeid" ) );
++ stmt = getArg( "sql-lookuptypeid" );
++ stmtref = strbind( ":type", qtype.getName(), stmt );
+ }
+-
++
+ size_t len = snprintf( m_buffer, sizeof( m_buffer ) - 1, "%d", zoneid );
+
+- if( len < 0 || len > sizeof( m_buffer ) - 1 )
++ if( len < 0 )
+ {
+- L.log( m_myname + " lookup: Unable to convert zone id to string", Logger::Error );
++ L.log( m_myname + " lookup: Unable to convert zone id to string - format error", Logger::Error );
+ throw( DBException( "Error: Libc error" ) );
+ }
+
+- stmt = strbind( ":id", string( m_buffer, len ), stmt );
++ if( len > sizeof( m_buffer ) - 1 )
++ {
++ L.log( m_myname + " lookup: Unable to convert zone id to string - insufficient buffer space", Logger::Error );
++ throw( DBException( "Error: Libc error" ) );
++ }
++
++ stmtref = strbind( ":id", string( m_buffer, len ), stmtref );
+ }
+
+- stmt = strbind( ":name", escape( toLower( qname ) ), stmt );
+- execStmt( stmt.c_str(), stmt.size(), true );
++ string tmp = qname;
++ stmtref = strbind( ":name", escape( toLowerByRef( tmp ), READ ), stmtref );
++
++ if( !execStmt( stmtref.c_str(), stmtref.size(), READ ) )
++ {
++ throw( DBException( "Error: DB statement failed" ) );
++ }
+ }
+ catch( exception& e )
+ {
+@@ -241,7 +274,7 @@
+ {
+ DLOG( L.log( m_myname + " get()", Logger::Debug ) );
+
+- if( getRecord() )
++ if( getRecord( READ ) )
+ {
+ rr.content = "";
+ rr.priority = 0;
+@@ -257,7 +290,7 @@
+
+ if( m_qname.empty() && ( tmp = odbx_field_value( m_result, 1 ) ) != NULL )
+ {
+- rr.qname = string( tmp );
++ rr.qname = string( tmp, odbx_field_length( m_result, 1 ) );
+ }
+
+ if( ( tmp = odbx_field_value( m_result, 2 ) ) != NULL )
+@@ -277,7 +310,7 @@
+
+ if( ( tmp = odbx_field_value( m_result, 5 ) ) != NULL )
+ {
+- rr.content = string( tmp );
++ rr.content = string( tmp, odbx_field_length( m_result, 5 ) );
+ }
+
+ return true;
+@@ -286,7 +319,7 @@
+ catch( exception& e )
+ {
+ L.log( m_myname + " get: Caught STL exception - " + e.what(), Logger::Error );
+- throw( DBException( "Error: STL exception" ) );
++ return false;
+ }
+
+ return false;
+@@ -302,15 +335,30 @@
+ {
+ DLOG( L.log( m_myname + " setFresh()", Logger::Debug ) );
+
++ if( !m_handle[WRITE] && !connectTo( m_hosts[WRITE], WRITE ) )
++ {
++ L.log( m_myname + " setFresh: Master server is unreachable", Logger::Error );
++ throw( DBException( "Error: Server unreachable" ) );
++ }
++
+ len = snprintf( m_buffer, sizeof( m_buffer ) - 1, getArg( "sql-update-lastcheck" ).c_str(), time( 0 ), domain_id );
+
+- if( len < 0 || len > sizeof( m_buffer ) - 1 )
++ if( len < 0 )
++ {
++ L.log( m_myname + " setFresh: Unable to insert values into statement '" + getArg( "sql-update-lastcheck" ) + "' - format error", Logger::Error );
++ throw( DBException( "Error: Libc error" ) );
++ }
++
++ if( len > sizeof( m_buffer ) - 1 )
+ {
+- L.log( m_myname + " setFresh: Unable to insert values into statement '" + getArg( "sql-update-lastcheck" ) + "'", Logger::Error );
++ L.log( m_myname + " setFresh: Unable to insert values into statement '" + getArg( "sql-update-lastcheck" ) + "' - insufficient buffer space", Logger::Error );
+ throw( DBException( "Error: Libc error" ) );
+ }
+
+- execStmt( m_buffer, len, false );
++ if( !execStmt( m_buffer, len, WRITE ) )
++ {
++ throw( DBException( "Error: DB statement failed" ) );
++ }
+ }
+ catch ( exception& e )
+ {
+@@ -323,22 +371,34 @@
+
+ void OdbxBackend::setNotified( u_int32_t domain_id, u_int32_t serial )
+ {
+- size_t len;
+-
+-
+ try
+ {
+ DLOG( L.log( m_myname + " setNotified()", Logger::Debug ) );
+
+- len = snprintf( m_buffer, sizeof( m_buffer ) - 1, getArg( "sql-update-serial" ).c_str(), serial, domain_id );
++ if( !m_handle[WRITE] && !connectTo( m_hosts[WRITE], WRITE ) )
++ {
++ L.log( m_myname + " setFresh: Master server is unreachable", Logger::Error );
++ throw( DBException( "Error: Server unreachable" ) );
++ }
+
+- if( len < 0 || len > sizeof( m_buffer ) - 1 )
++ size_t len = snprintf( m_buffer, sizeof( m_buffer ) - 1, getArg( "sql-update-serial" ).c_str(), serial, domain_id );
++
++ if( len < 0 )
+ {
+- L.log( m_myname + " setNotified: Unable to insert values into statement '" + getArg( "sql-update-serial" ) + "'", Logger::Error );
++ L.log( m_myname + " setNotified: Unable to insert values into statement '" + getArg( "sql-update-serial" ) + "' - format error", Logger::Error );
+ throw( DBException( "Error: Libc error" ) );
+ }
+
+- execStmt( m_buffer, len, false );
++ if( len > sizeof( m_buffer ) - 1 )
++ {
++ L.log( m_myname + " setNotified: Unable to insert values into statement '" + getArg( "sql-update-serial" ) + "' - insufficient buffer space", Logger::Error );
++ throw( DBException( "Error: Libc error" ) );
++ }
++
++ if( !execStmt( m_buffer, len, WRITE ) )
++ {
++ throw( DBException( "Error: DB statement failed" ) );
++ }
+ }
+ catch ( exception& e )
+ {
+@@ -351,17 +411,15 @@
+
+ bool OdbxBackend::isMaster( const string& domain, const string& ip )
+ {
+- string stmt;
+-
+-
+ try
+ {
+ DLOG( L.log( m_myname + " isMaster()", Logger::Debug ) );
+
+- stmt = strbind( ":name", escape( toLower( domain ) ), getArg( "sql-master" ) );
+- execStmt( stmt.c_str(), stmt.size(), true );
++ string stmt = getArg( "sql-master" );
++ string& stmtref = strbind( ":name", escape( toLower( domain ), READ ), stmt );
+
+- if( !getRecord() ) { return false; }
++ if( !execStmt( stmtref.c_str(), stmtref.size(), READ ) ) { return false; }
++ if( !getRecord( READ ) ) { return false; }
+
+ do
+ {
+@@ -369,16 +427,17 @@
+ {
+ if( !strcmp( odbx_field_value( m_result, 0 ), ip.c_str() ) )
+ {
++ while( getRecord( READ ) );
+ return true;
+ }
+ }
+ }
+- while( getRecord() );
++ while( getRecord( READ ) );
+ }
+ catch ( exception& e )
+ {
+ L.log( m_myname + " isMaster: Caught STL exception - " + e.what(), Logger::Error );
+- throw( DBException( "Error: STL exception" ) );
++ return false;
+ }
+
+ return false;
+@@ -392,15 +451,17 @@
+ {
+ DLOG( L.log( m_myname + " getUnfreshSlaveInfos()", Logger::Debug ) );
+
+- if( unfresh != NULL )
++ if( unfresh == NULL )
+ {
+- getDomainList( getArg( "sql-infoslaves" ), unfresh, &checkSlave );
++ L.log( m_myname + " getUnfreshSlaveInfos: invalid parameter - NULL pointer", Logger::Error );
++ return;
+ }
++
++ getDomainList( getArg( "sql-infoslaves" ), unfresh, &checkSlave );
+ }
+ catch ( exception& e )
+ {
+ L.log( m_myname + " getUnfreshSlaveInfo: Caught STL exception - " + e.what(), Logger::Error );
+- throw( DBException( "Error: STL exception" ) );
+ }
+ }
+
+@@ -412,15 +473,17 @@
+ {
+ DLOG( L.log( m_myname + " getUpdatedMasters()", Logger::Debug ) );
+
+- if( updated != NULL )
++ if( updated == NULL )
+ {
+- getDomainList( getArg( "sql-infomasters" ), updated, &checkMaster );
++ L.log( m_myname + " getUpdatedMasters: invalid parameter - NULL pointer", Logger::Error );
++ return;
+ }
++
++ getDomainList( getArg( "sql-infomasters" ), updated, &checkMaster );
+ }
+ catch ( exception& e )
+ {
+ L.log( m_myname + " getUpdatedMasters: Caught STL exception - " + e.what(), Logger::Error );
+- throw( DBException( "Error: STL exception" ) );
+ }
+ }
+
+@@ -428,43 +491,41 @@
+
+ bool OdbxBackend::superMasterBackend( const string& ip, const string& domain, const vector<DNSResourceRecord>& set, string* account, DNSBackend** ddb )
+ {
+- string stmt;
+- vector<DNSResourceRecord>::const_iterator i;
+-
+-
+ try
+ {
+ DLOG( L.log( m_myname + " superMasterBackend()", Logger::Debug ) );
+
+ if( account != NULL && ddb != NULL )
+ {
++ vector<DNSResourceRecord>::const_iterator i;
++
+ for( i = set.begin(); i != set.end(); i++ )
+ {
+- stmt = strbind( ":ip", escape( ip ), getArg( "sql-supermaster" ) );
+- stmt = strbind( ":ns", escape( i->content ), stmt );
+-
+- execStmt( stmt.c_str(), stmt.size(), true );
++ string stmt = getArg( "sql-supermaster" );
++ string& stmtref = strbind( ":ip", escape( ip, READ ), stmt );
++ stmtref = strbind( ":ns", escape( i->content, READ ), stmtref );
+
+- if( !getRecord() ) { return false; }
++ if( !execStmt( stmtref.c_str(), stmtref.size(), READ ) ) { return false; }
+
+- do
++ if( getRecord( READ ) )
+ {
+ if( odbx_field_value( m_result, 0 ) != NULL )
+ {
+ *account = string( odbx_field_value( m_result, 0 ), odbx_field_length( m_result, 0 ) );
+ }
+- }
+- while( getRecord() );
+
+- *ddb=this;
+- return true;
++ while( getRecord( READ ) );
++
++ *ddb=this;
++ return true;
++ }
+ }
+ }
+ }
+ catch ( exception& e )
+ {
+ L.log( m_myname + " superMasterBackend: Caught STL exception - " + e.what(), Logger::Error );
+- throw( DBException( "Error: STL exception" ) );
++ return false;
+ }
+
+ return false;
+@@ -474,28 +535,38 @@
+
+ bool OdbxBackend::createSlaveDomain( const string& ip, const string& domain, const string& account )
+ {
+- size_t len;
+-
+-
+ try
+ {
+ DLOG( L.log( m_myname + " createSlaveDomain()", Logger::Debug ) );
+
+- len = snprintf( m_buffer, sizeof( m_buffer ) - 1, getArg( "sql-insert-slave" ).c_str(), escape( toLower( domain ) ).c_str(),
+- escape( ip ).c_str(), escape( account ).c_str() );
++ if( !m_handle[WRITE] && !connectTo( m_hosts[WRITE], WRITE ) )
++ {
++ L.log( m_myname + " createSlaveDomain: Master server is unreachable", Logger::Error );
++ return false;
++ }
+
+- if( len < 0 || len > sizeof( m_buffer ) - 1 )
++ string tmp = domain;
++ size_t len = snprintf( m_buffer, sizeof( m_buffer ) - 1, getArg( "sql-insert-slave" ).c_str(), escape( toLowerByRef( tmp ), WRITE ).c_str(),
++ escape( ip, WRITE ).c_str(), escape( account, WRITE ).c_str() );
++
++ if( len < 0 )
+ {
+- L.log( m_myname + " createSlaveDomain: Unable to insert values in statement '" + getArg( "sql-insert-slave" ) + "'", Logger::Error );
+- throw( DBException( "Error: Libc error" ) );
++ L.log( m_myname + " createSlaveDomain: Unable to insert values in statement '" + getArg( "sql-insert-slave" ) + "' - format error", Logger::Error );
++ return false;
++ }
++
++ if( len > sizeof( m_buffer ) - 1 )
++ {
++ L.log( m_myname + " createSlaveDomain: Unable to insert values in statement '" + getArg( "sql-insert-slave" ) + "' - insufficient buffer space", Logger::Error );
++ return false;
+ }
+
+- execStmt( m_buffer, len, false );
++ if( !execStmt( m_buffer, len, WRITE ) ) { return false; }
+ }
+ catch ( exception& e )
+ {
+ L.log( m_myname + " createSlaveDomain: Caught STL exception - " + e.what(), Logger::Error );
+- throw( DBException( "Error: STL exception" ) );
++ return false;
+ }
+
+ return true;
+@@ -505,28 +576,39 @@
+
+ bool OdbxBackend::feedRecord( const DNSResourceRecord& rr )
+ {
+- size_t len;
+-
+-
+ try
+ {
+ DLOG( L.log( m_myname + " feedRecord()", Logger::Debug ) );
+
+- len = snprintf( m_buffer, sizeof( m_buffer ) - 1, getArg( "sql-insert-record" ).c_str(), rr.domain_id,
+- escape( toLower( rr.qname ) ).c_str(), rr.qtype.getName().c_str(), rr.ttl, rr.priority, escape( rr.content ).c_str() );
++ if( !m_handle[WRITE] && !connectTo( m_hosts[WRITE], WRITE ) )
++ {
++ L.log( m_myname + " feedRecord: Master server is unreachable", Logger::Error );
++ return false;
++ }
+
+- if( len < 0 || len > sizeof( m_buffer ) - 1 )
++ string tmp = rr.qname;
++ size_t len = snprintf( m_buffer, sizeof( m_buffer ) - 1, getArg( "sql-insert-record" ).c_str(), rr.domain_id,
++ escape( toLowerByRef( tmp ), WRITE ).c_str(), rr.qtype.getName().c_str(), rr.ttl, rr.priority,
++ escape( rr.content, WRITE ).c_str() );
++
++ if( len < 0 )
+ {
+- L.log( m_myname + " feedRecord: Unable to insert values in statement '" + getArg( "sql-insert-record" ) + "'", Logger::Error );
+- throw( DBException( "Error: Libc error" ) );
++ L.log( m_myname + " feedRecord: Unable to insert values in statement '" + getArg( "sql-insert-record" ) + "' - format error", Logger::Error );
++ return false;
+ }
+
+- execStmt( m_buffer, len, false );
++ if( len > sizeof( m_buffer ) - 1 )
++ {
++ L.log( m_myname + " feedRecord: Unable to insert values in statement '" + getArg( "sql-insert-record" ) + "' - insufficient buffer space", Logger::Error );
++ return false;
++ }
++
++ if( !execStmt( m_buffer, len, WRITE ) ) { return false; }
+ }
+ catch ( exception& e )
+ {
+ L.log( m_myname + " feedRecord: Caught STL exception - " + e.what(), Logger::Error );
+- throw( DBException( "Error: STL exception" ) );
++ return false;
+ }
+
+ return true;
+@@ -536,33 +618,41 @@
+
+ bool OdbxBackend::startTransaction( const string& domain, int zoneid )
+ {
+- size_t len;
+- string stmt;
+-
+-
+ try
+ {
+ DLOG( L.log( m_myname + " startTransaction()", Logger::Debug ) );
+
+- stmt = getArg( "sql-transactbegin" );
+- execStmt( stmt.c_str(), stmt.size(), false );
++ if( !m_handle[WRITE] && !connectTo( m_hosts[WRITE], WRITE ) )
++ {
++ L.log( m_myname + " startTransaction: Master server is unreachable", Logger::Error );
++ return false;
++ }
+
+- len = snprintf( m_buffer, sizeof( m_buffer ) - 1, "%d", zoneid );
++ string& stmtref = const_cast<string&>( getArg( "sql-transactbegin" ) );
++ if( !execStmt( stmtref.c_str(), stmtref.size(), WRITE ) ) { return false; }
+
+- if( len < 0 || len > sizeof( m_buffer ) - 1 )
++ size_t len = snprintf( m_buffer, sizeof( m_buffer ) - 1, "%d", zoneid );
++
++ if( len < 0 )
+ {
+- L.log( m_myname + " lookup: Unable to convert zone id to string", Logger::Error );
+- throw( DBException( "Error: Libc error" ) );
++ L.log( m_myname + " startTransaction: Unable to convert zone id to string - format error", Logger::Error );
++ return false;
+ }
+
+- stmt = strbind( ":id", string( m_buffer, len ), getArg( "sql-zonedelete" ) );
++ if( len > sizeof( m_buffer ) - 1 )
++ {
++ L.log( m_myname + " startTransaction: Unable to convert zone id to string - insufficient buffer space", Logger::Error );
++ return false;
++ }
+
+- execStmt( stmt.c_str(), stmt.size(), false );
++ string stmt = getArg( "sql-zonedelete" );
++ stmtref = strbind( ":id", string( m_buffer, len ), stmt );
++ if( !execStmt( stmtref.c_str(), stmtref.size(), WRITE ) ) { return false; }
+ }
+ catch ( exception& e )
+ {
+ L.log( m_myname + " startTransaction: Caught STL exception - " + e.what(), Logger::Error );
+- throw( DBException( "Error: STL exception" ) );
++ return false;
+ }
+
+ return true;
+@@ -576,12 +666,19 @@
+ {
+ DLOG( L.log( m_myname + " commitTransaction()", Logger::Debug ) );
+
+- execStmt( getArg( "sql-transactend" ).c_str(), getArg( "sql-transactend" ).size(), false );
++ if( !m_handle[WRITE] && !connectTo( m_hosts[WRITE], WRITE ) )
++ {
++ L.log( m_myname + " commitTransaction: Master server is unreachable", Logger::Error );
++ return false;
++ }
++
++ const string& stmt = getArg( "sql-transactend" );
++ if( !execStmt( stmt.c_str(), stmt.size(), WRITE ) ) { return false; }
+ }
+ catch ( exception& e )
+ {
+ L.log( m_myname + " commitTransaction: Caught STL exception - " + e.what(), Logger::Error );
+- throw( DBException( "Error: STL exception" ) );
++ return false;
+ }
+
+ return true;
+@@ -595,12 +692,19 @@
+ {
+ DLOG( L.log( m_myname + " abortTransaction()", Logger::Debug ) );
+
+- execStmt( getArg( "sql-transactabort" ).c_str(), getArg( "sql-transabort" ).size(), false );
++ if( !m_handle[WRITE] && !connectTo( m_hosts[WRITE], WRITE ) )
++ {
++ L.log( m_myname + " abortTransaction: Master server is unreachable", Logger::Error );
++ return false;
++ }
++
++ const string& stmt = getArg( "sql-transactabort" );
++ if( !execStmt( stmt.c_str(), stmt.size(), WRITE ) ) { return false; }
+ }
+ catch ( exception& e )
+ {
+ L.log( m_myname + " abortTransaction: Caught STL exception - " + e.what(), Logger::Error );
+- throw( DBException( "Error: STL exception" ) );
++ return false;
+ }
+
+ return true;
+--- modules/opendbxbackend/odbxprivate.cc 2006-03-15 19:29:39.000000000 +0100
++++ modules/opendbxbackend/odbxprivate.cc 2006-09-02 01:02:36.000000000 +0200
+@@ -2,7 +2,50 @@
+
+
+
+-void OdbxBackend::execStmt( const char* stmt, unsigned long length, bool select )
++unsigned int odbx_host_index[2] = { 0, 0 };
++
++
++
++bool OdbxBackend::connectTo( const vector<string>& hosts, QueryType type )
++{
++ int err;
++ unsigned int h, i;
++ int idx = odbx_host_index[type]++ % hosts.size();
++
++
++ if( m_handle[type] )
++ {
++ odbx_unbind( m_handle[type] );
++ odbx_finish( m_handle[type] );
++ m_handle[type] = NULL;
++ }
++
++ for( i = 0; i < hosts.size(); i++ )
++ {
++ h = ( idx + i ) % hosts.size();
++
++ if( ( err = odbx_init( &(m_handle[type]), getArg( "backend" ).c_str(), hosts[h].c_str(), getArg( "port" ).c_str() ) ) == ODBX_ERR_SUCCESS )
++ {
++ if( ( err = odbx_bind_simple( m_handle[type], getArg( "database" ).c_str(), getArg( "username" ).c_str(), getArg( "password" ).c_str() ) ) == ODBX_ERR_SUCCESS )
++ {
++ L.log( m_myname + " Database connection (" + (type ? "write" : "read") + ") to '" + hosts[h] + "' succeeded", Logger::Notice );
++ return true;
++ }
++
++ L.log( m_myname + " Unable to bind to database on host " + hosts[h] + " - " + string( odbx_error( m_handle[type], err ) ), Logger::Error );
++ continue;
++ }
++
++ L.log( m_myname + " Unable to connect to server on host " + hosts[h] + " - " + string( odbx_error( m_handle[type], err ) ), Logger::Error );
++ }
++
++ m_handle[type] = NULL;
++ return false;
++}
++
++
++
++bool OdbxBackend::execStmt( const char* stmt, unsigned long length, QueryType type )
+ {
+ int err;
+
+@@ -11,18 +54,21 @@
+
+ if( m_qlog ) { L.log( m_myname + " Query: " + stmt, Logger::Info ); }
+
+- if( ( err = odbx_query( m_handle, stmt, length ) ) < 0 )
++ if( ( err = odbx_query( m_handle[type], stmt, length ) ) < 0 )
+ {
+- L.log( m_myname + " execStmt: Unable to execute query - " + string( odbx_error( m_handle, err ) ), Logger::Error );
+- throw( AhuException( "Error: odbx_query() failed" ) );
++ L.log( m_myname + " execStmt: Unable to execute query - " + string( odbx_error( m_handle[type], err ) ), Logger::Error );
++ connectTo( m_hosts[type], type );
++ return false;
+ }
+
+- if( !select ) { while( getRecord() ); }
++ if( type == WRITE ) { while( getRecord( type ) ); }
++
++ return true;
+ }
+
+
+
+-bool OdbxBackend::getRecord()
++bool OdbxBackend::getRecord( QueryType type )
+ {
+ int err = 3;
+
+@@ -31,13 +77,19 @@
+
+ do
+ {
++ if( err < 0 )
++ {
++ L.log( m_myname + " getRecord: Unable to get next result - " + string( odbx_error( m_handle[type], err ) ), Logger::Error );
++ throw( AhuException( "Error: odbx_result() failed" ) );
++ }
++
+ if( m_result != NULL )
+ {
+ if( err == 3 )
+ {
+ if( ( err = odbx_row_fetch( m_result ) ) < 0 )
+ {
+- L.log( m_myname + " getRecord: Unable to get next row - " + string( odbx_error( m_handle, err ) ), Logger::Error );
++ L.log( m_myname + " getRecord: Unable to get next row - " + string( odbx_error( m_handle[type], err ) ), Logger::Error );
+ throw( AhuException( "Error: odbx_row_fetch() failed" ) );
+ }
+
+@@ -72,13 +124,7 @@
+ m_result = NULL;
+ }
+ }
+- while( ( err = odbx_result( m_handle, &m_result, NULL, 0 ) ) > 0 );
+-
+- if( err < 0 )
+- {
+- L.log( m_myname + " getRecord: Unable to get next result - " + string( odbx_error( m_handle, err ) ), Logger::Error );
+- throw( AhuException( "Error: odbx_result() failed" ) );
+- }
++ while( ( err = odbx_result( m_handle[type], &m_result, NULL, 0 ) ) != 0 );
+
+ m_result = NULL;
+ return false;
+@@ -86,18 +132,18 @@
+
+
+
+-string OdbxBackend::escape( const string& str )
++string OdbxBackend::escape( const string& str, QueryType type )
+ {
+ int err;
+ unsigned long len = sizeof( m_escbuf );
+
+
+- DLOG( L.log( m_myname + " escape()", Logger::Debug ) );
++ DLOG( L.log( m_myname + " escape(string)", Logger::Debug ) );
+
+- if( ( err = odbx_escape( m_handle, str.c_str(), str.size(), m_escbuf, &len ) ) < 0 )
++ if( ( err = odbx_escape( m_handle[type], str.c_str(), str.size(), m_escbuf, &len ) ) < 0 )
+ {
+- L.log( m_myname + " escape: Unable to escape string - " + string( odbx_error( m_handle, err ) ), Logger::Error );
+- throw( AhuException( "Error: odbx_escape() failed" ) );
++ L.log( m_myname + " escape(string): Unable to escape string - " + string( odbx_error( m_handle[type], err ) ), Logger::Error );
++ throw( runtime_error( "odbx_escape() failed" ) );
+ }
+
+ return string( m_escbuf, len );
+@@ -105,7 +151,7 @@
+
+
+
+-void OdbxBackend::getDomainList( const string& stmt, vector<DomainInfo>* list, bool (*check_fcn)(u_int32_t,u_int32_t,SOAData*,DomainInfo*) )
++bool OdbxBackend::getDomainList( const string& stmt, vector<DomainInfo>* list, bool (*check_fcn)(u_int32_t,u_int32_t,SOAData*,DomainInfo*) )
+ {
+ const char* tmp;
+ u_int32_t nlast, nserial;
+@@ -115,9 +161,8 @@
+
+ DLOG( L.log( m_myname + " getDomainList()", Logger::Debug ) );
+
+- execStmt( stmt.c_str(), stmt.size(), true );
+-
+- if( !getRecord() ) { return; }
++ if( !execStmt( stmt.c_str(), stmt.size(), READ ) ) { return false; }
++ if( !getRecord( READ ) ) { return false; }
+
+ do
+ {
+@@ -128,7 +173,7 @@
+
+ if( ( tmp = odbx_field_value( m_result, 6 ) ) != NULL )
+ {
+- DNSPacket::fillSOAData( string( tmp ), sd );
++ DNSPacket::fillSOAData( string( tmp, odbx_field_length( m_result, 6 ) ), sd );
+ }
+
+ if( !sd.serial && ( tmp = odbx_field_value( m_result, 5 ) ) != NULL )
+@@ -171,7 +216,9 @@
+ list->push_back( di );
+ }
+ }
+- while( getRecord() );
++ while( getRecord( READ ) );
++
++ return true;
+ }
+
+