1
#include "odbxbackend.hh"
5
unsigned int odbx_host_index = 0;
9
OdbxBackend::OdbxBackend( const string& suffix )
12
unsigned int idx, i, h;
19
m_myname = "[OpendbxBackend]";
20
m_default_ttl = arg().asNum( "default-ttl" );
21
m_qlog = arg().mustDo( "query-logging" );
23
setArgPrefix( "opendbx" + suffix );
24
stringtok( hosts, getArg( "host" ), ", " );
26
idx = odbx_host_index++ % hosts.size();
28
for( i = 0; i < hosts.size(); i++ )
30
h = ( idx + i ) % hosts.size();
31
if( !( err = odbx_init( &m_handle, getArg( "backend" ).c_str(), hosts[h].c_str(), getArg( "port" ).c_str() ) ) ) { break; }
36
L.log( m_myname + " OdbxBackend: Unable to connect to server - " + string( odbx_error( m_handle, err ) ), Logger::Error );
37
throw( AhuException( "Fatal: odbx_init() failed" ) );
40
if( ( err = odbx_bind_simple( m_handle, getArg( "database" ).c_str(), getArg( "username" ).c_str(), getArg( "password" ).c_str() ) ) < 0 )
42
L.log( m_myname + " OdbxBackend: Unable to bind to database - " + string( odbx_error( m_handle, err ) ), Logger::Error );
43
throw( AhuException( "Fatal: odbx_bind_simple() failed" ) );
48
L.log( m_myname + " OdbxBackend: Caught STL exception - " + e.what(), Logger::Error );
49
throw( DBException( "Fatal: STL exception" ) );
52
L.log( m_myname + " Connection succeeded", Logger::Notice );
57
OdbxBackend::~OdbxBackend()
59
odbx_unbind( m_handle );
60
odbx_finish( m_handle );
65
bool OdbxBackend::getDomainInfo( const string& domain, DomainInfo& di )
73
DLOG( L.log( m_myname + " getDomainInfo()", Logger::Debug ) );
75
stmt = strbind( ":name", escape( toLower( domain ) ), getArg( "sql-zoneinfo" ) );
76
execStmt( stmt.c_str(), stmt.size(), true );
78
if( !getRecord() ) { return false; }
86
di.notified_serial = 0;
87
di.kind = DomainInfo::Native;
91
if( ( tmp = odbx_field_value( m_result, 0 ) ) != NULL )
93
di.id = strtol( tmp, NULL, 10 );
96
if( ( tmp = odbx_field_value( m_result, 1 ) ) != NULL )
98
di.zone = string( tmp );
101
if( ( tmp = odbx_field_value( m_result, 2 ) ) != NULL )
103
if( !strncmp( tmp, "SLAVE", 5 ) )
105
di.kind = DomainInfo::Slave;
107
else if( !strncmp( tmp, "MASTER", 6 ) )
109
di.kind = DomainInfo::Master;
113
if( ( tmp = odbx_field_value( m_result, 3 ) ) != NULL )
115
di.master = string( tmp );
118
if( ( tmp = odbx_field_value( m_result, 5 ) ) != NULL )
120
di.last_check = strtol( tmp, NULL, 10 );
123
if( ( tmp = odbx_field_value( m_result, 6 ) ) != NULL )
128
DNSPacket::fillSOAData( string( tmp ), sd );
129
di.serial = sd.serial;
132
while( getRecord() );
134
catch( exception& e )
136
L.log( m_myname + " getDomainInfo: Caught STL exception - " + e.what(), Logger::Error );
137
throw( DBException( "Error: STL exception" ) );
145
bool OdbxBackend::list( const string& target, int zoneid )
154
DLOG( L.log( m_myname + " list()", Logger::Debug ) );
159
len = snprintf( m_buffer, sizeof( m_buffer ) - 1, "%d", zoneid );
161
if( len < 0 || len > sizeof( m_buffer ) - 1 )
163
L.log( m_myname + " list: Unable to convert zone id to string", Logger::Error );
164
throw( DBException( "Error: Libc error" ) );
167
stmt = strbind( ":id", string( m_buffer, len ), getArg( "sql-list" ) );
169
execStmt( stmt.c_str(), stmt.size(), true );
171
catch( exception& e )
173
L.log( m_myname + " list: Caught STL exception - " + e.what(), Logger::Error );
174
throw( DBException( "Error: STL exception" ) );
182
void OdbxBackend::lookup( const QType& qtype, const string& qname, DNSPacket* dnspkt, int zoneid )
189
DLOG( L.log( m_myname + " lookup()", Logger::Debug ) );
196
if( qtype.getCode() == QType::ANY )
198
stmt = getArg( "sql-lookup" );
200
stmt = strbind( ":type", qtype.getName(), getArg( "sql-lookuptype" ) );
205
if( qtype.getCode() == QType::ANY )
207
stmt = getArg( "sql-lookupid" );
209
stmt = strbind( ":type", qtype.getName(), getArg( "sql-lookuptypeid" ) );
212
size_t len = snprintf( m_buffer, sizeof( m_buffer ) - 1, "%d", zoneid );
214
if( len < 0 || len > sizeof( m_buffer ) - 1 )
216
L.log( m_myname + " lookup: Unable to convert zone id to string", Logger::Error );
217
throw( DBException( "Error: Libc error" ) );
220
stmt = strbind( ":id", string( m_buffer, len ), stmt );
223
stmt = strbind( ":name", escape( toLower( qname ) ), stmt );
224
execStmt( stmt.c_str(), stmt.size(), true );
226
catch( exception& e )
228
L.log( m_myname + " lookup: Caught STL exception - " + e.what(), Logger::Error );
229
throw( DBException( "Error: STL exception" ) );
235
bool OdbxBackend::get( DNSResourceRecord& rr )
242
DLOG( L.log( m_myname + " get()", Logger::Debug ) );
249
rr.last_modified = 0;
250
rr.ttl = m_default_ttl;
253
if( ( tmp = odbx_field_value( m_result, 0 ) ) != NULL )
255
rr.domain_id = strtol( tmp, NULL, 10 );
258
if( m_qname.empty() && ( tmp = odbx_field_value( m_result, 1 ) ) != NULL )
260
rr.qname = string( tmp );
263
if( ( tmp = odbx_field_value( m_result, 2 ) ) != NULL )
265
rr.qtype = QType( tmp );
268
if( ( tmp = odbx_field_value( m_result, 3 ) ) != NULL )
270
rr.ttl = strtoul( tmp, NULL, 10 );
273
if( ( tmp = odbx_field_value( m_result, 4 ) ) != NULL )
275
rr.priority = (u_int16_t) strtoul( tmp, NULL, 10 );
278
if( ( tmp = odbx_field_value( m_result, 5 ) ) != NULL )
280
rr.content = string( tmp );
286
catch( exception& e )
288
L.log( m_myname + " get: Caught STL exception - " + e.what(), Logger::Error );
289
throw( DBException( "Error: STL exception" ) );
296
void OdbxBackend::setFresh( u_int32_t domain_id )
303
DLOG( L.log( m_myname + " setFresh()", Logger::Debug ) );
305
len = snprintf( m_buffer, sizeof( m_buffer ) - 1, getArg( "sql-update-lastcheck" ).c_str(), time( 0 ), domain_id );
307
if( len < 0 || len > sizeof( m_buffer ) - 1 )
309
L.log( m_myname + " setFresh: Unable to insert values into statement '" + getArg( "sql-update-lastcheck" ) + "'", Logger::Error );
310
throw( DBException( "Error: Libc error" ) );
313
execStmt( m_buffer, len, false );
315
catch ( exception& e )
317
L.log( m_myname + " setFresh: Caught STL exception - " + e.what(), Logger::Error );
318
throw( DBException( "Error: STL exception" ) );
324
void OdbxBackend::setNotified( u_int32_t domain_id, u_int32_t serial )
331
DLOG( L.log( m_myname + " setNotified()", Logger::Debug ) );
333
len = snprintf( m_buffer, sizeof( m_buffer ) - 1, getArg( "sql-update-serial" ).c_str(), serial, domain_id );
335
if( len < 0 || len > sizeof( m_buffer ) - 1 )
337
L.log( m_myname + " setNotified: Unable to insert values into statement '" + getArg( "sql-update-serial" ) + "'", Logger::Error );
338
throw( DBException( "Error: Libc error" ) );
341
execStmt( m_buffer, len, false );
343
catch ( exception& e )
345
L.log( m_myname + " setNotified: Caught STL exception - " + e.what(), Logger::Error );
346
throw( DBException( "Error: STL exception" ) );
352
bool OdbxBackend::isMaster( const string& domain, const string& ip )
359
DLOG( L.log( m_myname + " isMaster()", Logger::Debug ) );
361
stmt = strbind( ":name", escape( toLower( domain ) ), getArg( "sql-master" ) );
362
execStmt( stmt.c_str(), stmt.size(), true );
364
if( !getRecord() ) { return false; }
368
if( odbx_field_value( m_result, 0 ) != NULL )
370
if( !strcmp( odbx_field_value( m_result, 0 ), ip.c_str() ) )
376
while( getRecord() );
378
catch ( exception& e )
380
L.log( m_myname + " isMaster: Caught STL exception - " + e.what(), Logger::Error );
381
throw( DBException( "Error: STL exception" ) );
389
void OdbxBackend::getUnfreshSlaveInfos( vector<DomainInfo>* unfresh )
393
DLOG( L.log( m_myname + " getUnfreshSlaveInfos()", Logger::Debug ) );
395
if( unfresh != NULL )
397
getDomainList( getArg( "sql-infoslaves" ), unfresh, &checkSlave );
400
catch ( exception& e )
402
L.log( m_myname + " getUnfreshSlaveInfo: Caught STL exception - " + e.what(), Logger::Error );
403
throw( DBException( "Error: STL exception" ) );
409
void OdbxBackend::getUpdatedMasters( vector<DomainInfo>* updated )
413
DLOG( L.log( m_myname + " getUpdatedMasters()", Logger::Debug ) );
415
if( updated != NULL )
417
getDomainList( getArg( "sql-infomasters" ), updated, &checkMaster );
420
catch ( exception& e )
422
L.log( m_myname + " getUpdatedMasters: Caught STL exception - " + e.what(), Logger::Error );
423
throw( DBException( "Error: STL exception" ) );
429
bool OdbxBackend::superMasterBackend( const string& ip, const string& domain, const vector<DNSResourceRecord>& set, string* account, DNSBackend** ddb )
432
vector<DNSResourceRecord>::const_iterator i;
437
DLOG( L.log( m_myname + " superMasterBackend()", Logger::Debug ) );
439
if( account != NULL && ddb != NULL )
441
for( i = set.begin(); i != set.end(); i++ )
443
stmt = strbind( ":ip", escape( ip ), getArg( "sql-supermaster" ) );
444
stmt = strbind( ":ns", escape( i->content ), stmt );
446
execStmt( stmt.c_str(), stmt.size(), true );
448
if( !getRecord() ) { return false; }
452
if( odbx_field_value( m_result, 0 ) != NULL )
454
*account = string( odbx_field_value( m_result, 0 ), odbx_field_length( m_result, 0 ) );
457
while( getRecord() );
464
catch ( exception& e )
466
L.log( m_myname + " superMasterBackend: Caught STL exception - " + e.what(), Logger::Error );
467
throw( DBException( "Error: STL exception" ) );
475
bool OdbxBackend::createSlaveDomain( const string& ip, const string& domain, const string& account )
482
DLOG( L.log( m_myname + " createSlaveDomain()", Logger::Debug ) );
484
len = snprintf( m_buffer, sizeof( m_buffer ) - 1, getArg( "sql-insert-slave" ).c_str(), escape( toLower( domain ) ).c_str(),
485
escape( ip ).c_str(), escape( account ).c_str() );
487
if( len < 0 || len > sizeof( m_buffer ) - 1 )
489
L.log( m_myname + " createSlaveDomain: Unable to insert values in statement '" + getArg( "sql-insert-slave" ) + "'", Logger::Error );
490
throw( DBException( "Error: Libc error" ) );
493
execStmt( m_buffer, len, false );
495
catch ( exception& e )
497
L.log( m_myname + " createSlaveDomain: Caught STL exception - " + e.what(), Logger::Error );
498
throw( DBException( "Error: STL exception" ) );
506
bool OdbxBackend::feedRecord( const DNSResourceRecord& rr )
513
DLOG( L.log( m_myname + " feedRecord()", Logger::Debug ) );
515
len = snprintf( m_buffer, sizeof( m_buffer ) - 1, getArg( "sql-insert-record" ).c_str(), rr.domain_id,
516
escape( toLower( rr.qname ) ).c_str(), rr.qtype.getName().c_str(), rr.ttl, rr.priority, escape( rr.content ).c_str() );
518
if( len < 0 || len > sizeof( m_buffer ) - 1 )
520
L.log( m_myname + " feedRecord: Unable to insert values in statement '" + getArg( "sql-insert-record" ) + "'", Logger::Error );
521
throw( DBException( "Error: Libc error" ) );
524
execStmt( m_buffer, len, false );
526
catch ( exception& e )
528
L.log( m_myname + " feedRecord: Caught STL exception - " + e.what(), Logger::Error );
529
throw( DBException( "Error: STL exception" ) );
537
bool OdbxBackend::startTransaction( const string& domain, int zoneid )
545
DLOG( L.log( m_myname + " startTransaction()", Logger::Debug ) );
547
stmt = getArg( "sql-transactbegin" );
548
execStmt( stmt.c_str(), stmt.size(), false );
550
len = snprintf( m_buffer, sizeof( m_buffer ) - 1, "%d", zoneid );
552
if( len < 0 || len > sizeof( m_buffer ) - 1 )
554
L.log( m_myname + " lookup: Unable to convert zone id to string", Logger::Error );
555
throw( DBException( "Error: Libc error" ) );
558
stmt = strbind( ":id", string( m_buffer, len ), getArg( "sql-zonedelete" ) );
560
execStmt( stmt.c_str(), stmt.size(), false );
562
catch ( exception& e )
564
L.log( m_myname + " startTransaction: Caught STL exception - " + e.what(), Logger::Error );
565
throw( DBException( "Error: STL exception" ) );
573
bool OdbxBackend::commitTransaction()
577
DLOG( L.log( m_myname + " commitTransaction()", Logger::Debug ) );
579
execStmt( getArg( "sql-transactend" ).c_str(), getArg( "sql-transactend" ).size(), false );
581
catch ( exception& e )
583
L.log( m_myname + " commitTransaction: Caught STL exception - " + e.what(), Logger::Error );
584
throw( DBException( "Error: STL exception" ) );
592
bool OdbxBackend::abortTransaction()
596
DLOG( L.log( m_myname + " abortTransaction()", Logger::Debug ) );
598
execStmt( getArg( "sql-transactabort" ).c_str(), getArg( "sql-transabort" ).size(), false );
600
catch ( exception& e )
602
L.log( m_myname + " abortTransaction: Caught STL exception - " + e.what(), Logger::Error );
603
throw( DBException( "Error: STL exception" ) );