diff options
Diffstat (limited to 'dns/powerdns-devel/files/patch-opendbx')
-rw-r--r-- | dns/powerdns-devel/files/patch-opendbx | 1038 |
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; + } + + |