root/trunk/pdns/modules/opendbxbackend/odbxbackend.cc @ 973

Revision 973, 13.4 KB (checked in by ahu, 6 years ago)

fillSOAData is no longer part of DNSPacket, update modules

Line 
1#include "odbxbackend.hh"
2
3
4
5unsigned int odbx_host_index = 0;
6
7
8
9OdbxBackend::OdbxBackend( const string& suffix )
10{
11        int err = -1;
12        unsigned int  idx, i, h;
13        vector<string> hosts;
14
15
16        try
17        {
18                m_result = NULL;
19                m_myname = "[OpendbxBackend]";
20                m_default_ttl = arg().asNum( "default-ttl" );
21                m_qlog = arg().mustDo( "query-logging" );
22
23                setArgPrefix( "opendbx" + suffix );
24                stringtok( hosts, getArg( "host" ), ", " );
25
26                idx = odbx_host_index++ % hosts.size();
27
28                for( i = 0; i < hosts.size(); i++ )
29                {
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; }
32                }
33
34                if( err < 0 )
35                {
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" ) );
38                }
39
40                if( ( err = odbx_bind_simple( m_handle, getArg( "database" ).c_str(), getArg( "username" ).c_str(), getArg( "password" ).c_str() ) ) < 0 )
41                {
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" ) );
44                }
45        }
46        catch( exception& e )
47        {
48                L.log( m_myname + " OdbxBackend: Caught STL exception - " + e.what(),  Logger::Error );
49                throw( DBException( "Fatal: STL exception" ) );
50        }
51
52        L.log( m_myname + " Connection succeeded", Logger::Notice );
53}
54
55
56
57OdbxBackend::~OdbxBackend()
58{
59        odbx_unbind( m_handle );
60        odbx_finish( m_handle );
61}
62
63
64
65bool OdbxBackend::getDomainInfo( const string& domain, DomainInfo& di )
66{
67        const char* tmp;
68        string stmt;
69
70
71        try
72        {
73                DLOG( L.log( m_myname + " getDomainInfo()", Logger::Debug ) );
74
75                stmt = strbind( ":name", escape( toLower( domain ) ), getArg( "sql-zoneinfo" ) );
76                execStmt( stmt.c_str(), stmt.size(), true );
77
78                if( !getRecord() ) { return false; }
79
80                do
81                {
82                        di.id = 0;
83                        di.zone = "";
84                        di.master = "";
85                        di.last_check = 0;
86                        di.notified_serial = 0;
87                        di.kind = DomainInfo::Native;
88                        di.backend = this;
89                        di.serial = 0;
90
91                        if( ( tmp = odbx_field_value( m_result, 0 ) ) != NULL )
92                        {
93                                di.id = strtol( tmp, NULL, 10 );
94                        }
95
96                        if( ( tmp = odbx_field_value( m_result, 1 ) ) != NULL )
97                        {
98                                di.zone = string( tmp );
99                        }
100
101                        if( ( tmp = odbx_field_value( m_result, 2 ) ) != NULL )
102                        {
103                                if( !strncmp( tmp, "SLAVE", 5 ) )
104                                {
105                                        di.kind = DomainInfo::Slave;
106                                }
107                                else if( !strncmp( tmp, "MASTER", 6 ) )
108                                {
109                                        di.kind = DomainInfo::Master;
110                                }
111                        }
112
113                        if( ( tmp = odbx_field_value( m_result, 3 ) ) != NULL )
114                        {
115                                di.master = string( tmp );
116                        }
117
118                        if( ( tmp = odbx_field_value( m_result, 5 ) ) != NULL )
119                        {
120                                di.last_check = strtol( tmp, NULL, 10 );
121                        }
122
123                        if( ( tmp = odbx_field_value( m_result, 6 ) ) != NULL )
124                        {
125                                SOAData sd;
126
127                                sd.serial = 0;
128                                fillSOAData( string( tmp ), sd );
129                                di.serial = sd.serial;
130                        }
131                }
132                while( getRecord() );
133        }
134        catch( exception& e )
135        {
136                L.log( m_myname + " getDomainInfo: Caught STL exception - " + e.what(),  Logger::Error );
137                throw( DBException( "Error: STL exception" ) );
138        }
139
140        return true;
141}
142
143
144
145bool OdbxBackend::list( const string& target, int zoneid )
146{
147        string stmt;
148        size_t len;
149
150
151
152        try
153        {
154                DLOG( L.log( m_myname + " list()", Logger::Debug ) );
155
156                m_qname = "";
157                m_result = NULL;
158
159                len = snprintf( m_buffer, sizeof( m_buffer ) - 1, "%d", zoneid );
160
161                if( len < 0 || len > sizeof( m_buffer ) - 1 )
162                {
163                        L.log( m_myname + " list: Unable to convert zone id to string",  Logger::Error );
164                        throw( DBException( "Error: Libc error" ) );
165                }
166
167                stmt = strbind( ":id", string( m_buffer, len ), getArg( "sql-list" ) );
168
169                execStmt( stmt.c_str(), stmt.size(), true );
170        }
171        catch( exception& e )
172        {
173                L.log( m_myname + " list: Caught STL exception - " + e.what(),  Logger::Error );
174                throw( DBException( "Error: STL exception" ) );
175        }
176
177        return true;
178}
179
180
181
182void OdbxBackend::lookup( const QType& qtype, const string& qname, DNSPacket* dnspkt, int zoneid )
183{
184        string stmt;
185
186
187        try
188        {
189                DLOG( L.log( m_myname + " lookup()", Logger::Debug ) );
190
191                m_result = NULL;
192                m_qname = qname;
193               
194                if( zoneid < 0 )
195                {
196                        if( qtype.getCode() == QType::ANY )
197                        {
198                                stmt = getArg( "sql-lookup" );
199                        } else {
200                                stmt = strbind( ":type", qtype.getName(), getArg( "sql-lookuptype" ) );
201                        }
202                }
203                else
204                {
205                        if( qtype.getCode() == QType::ANY )
206                        {
207                                stmt = getArg( "sql-lookupid" );
208                        } else {
209                                stmt = strbind( ":type", qtype.getName(), getArg( "sql-lookuptypeid" ) );
210                        }
211                       
212                        size_t len = snprintf( m_buffer, sizeof( m_buffer ) - 1, "%d", zoneid );
213
214                        if( len < 0 || len > sizeof( m_buffer ) - 1 )
215                        {
216                                L.log( m_myname + " lookup: Unable to convert zone id to string",  Logger::Error );
217                                throw( DBException( "Error: Libc error" ) );
218                        }
219
220                        stmt = strbind( ":id", string( m_buffer, len ), stmt );
221                }
222
223                stmt = strbind( ":name", escape( toLower( qname ) ), stmt );
224                execStmt( stmt.c_str(), stmt.size(), true );
225        }
226        catch( exception& e )
227        {
228                L.log( m_myname + " lookup: Caught STL exception - " + e.what(),  Logger::Error );
229                throw( DBException( "Error: STL exception" ) );
230        }
231}
232
233
234
235bool OdbxBackend::get( DNSResourceRecord& rr )
236{
237        const char* tmp;
238
239
240        try
241        {
242                DLOG( L.log( m_myname + " get()", Logger::Debug ) );
243
244                if( getRecord() )
245                {
246                        rr.content = "";
247                        rr.priority = 0;
248                        rr.domain_id = 0;
249                        rr.last_modified = 0;
250                        rr.ttl = m_default_ttl;
251                        rr.qname = m_qname;
252
253                        if( ( tmp = odbx_field_value( m_result, 0 ) ) != NULL )
254                        {
255                                rr.domain_id = strtol( tmp, NULL, 10 );
256                        }
257
258                        if( m_qname.empty() && ( tmp = odbx_field_value( m_result, 1 ) ) != NULL )
259                        {
260                                rr.qname = string( tmp );
261                        }
262
263                        if( ( tmp = odbx_field_value( m_result, 2 ) ) != NULL )
264                        {
265                                rr.qtype = QType( tmp );
266                        }
267
268                        if( ( tmp = odbx_field_value( m_result, 3 ) ) != NULL )
269                        {
270                                rr.ttl = strtoul( tmp, NULL, 10 );
271                        }
272
273                        if( ( tmp = odbx_field_value( m_result, 4 ) ) != NULL )
274                        {
275                                rr.priority = (u_int16_t) strtoul( tmp, NULL, 10 );
276                        }
277
278                        if( ( tmp = odbx_field_value( m_result, 5 ) ) != NULL )
279                        {
280                                rr.content = string( tmp );
281                        }
282
283                        return true;
284                }
285        }
286        catch( exception& e )
287        {
288                L.log( m_myname + " get: Caught STL exception - " + e.what(),  Logger::Error );
289                throw( DBException( "Error: STL exception" ) );
290        }
291
292        return false;
293}
294
295
296void OdbxBackend::setFresh( u_int32_t domain_id )
297{
298        size_t len;
299
300
301        try
302        {
303                DLOG( L.log( m_myname + " setFresh()", Logger::Debug ) );
304
305                len = snprintf( m_buffer, sizeof( m_buffer ) - 1, getArg( "sql-update-lastcheck" ).c_str(), time( 0 ), domain_id );
306
307                if( len < 0 || len > sizeof( m_buffer ) - 1 )
308                {
309                        L.log( m_myname + " setFresh: Unable to insert values into statement '" + getArg( "sql-update-lastcheck" ) + "'",  Logger::Error );
310                        throw( DBException( "Error: Libc error" ) );
311                }
312
313                execStmt( m_buffer, len, false );
314        }
315        catch ( exception& e )
316        {
317                L.log( m_myname + " setFresh: Caught STL exception - " + e.what(),  Logger::Error );
318                throw( DBException( "Error: STL exception" ) );
319        }
320}
321
322
323
324void OdbxBackend::setNotified( u_int32_t domain_id, u_int32_t serial )
325{
326        size_t len;
327
328
329        try
330        {
331                DLOG( L.log( m_myname + " setNotified()", Logger::Debug ) );
332
333                len = snprintf( m_buffer, sizeof( m_buffer ) - 1, getArg( "sql-update-serial" ).c_str(), serial, domain_id );
334
335                if( len < 0 || len > sizeof( m_buffer ) - 1 )
336                {
337                        L.log( m_myname + " setNotified: Unable to insert values into statement '" + getArg( "sql-update-serial" ) + "'",  Logger::Error );
338                        throw( DBException( "Error: Libc error" ) );
339                }
340
341                execStmt( m_buffer, len, false );
342        }
343        catch ( exception& e )
344        {
345                L.log( m_myname + " setNotified: Caught STL exception - " + e.what(),  Logger::Error );
346                throw( DBException( "Error: STL exception" ) );
347        }
348}
349
350
351
352bool OdbxBackend::isMaster( const string& domain, const string& ip )
353{
354        string stmt;
355
356
357        try
358        {
359                DLOG( L.log( m_myname + " isMaster()", Logger::Debug ) );
360
361                stmt = strbind( ":name", escape( toLower( domain ) ), getArg( "sql-master" ) );
362                execStmt( stmt.c_str(), stmt.size(), true );
363
364                if( !getRecord() ) { return false; }
365
366                do
367                {
368                        if( odbx_field_value( m_result, 0 ) != NULL )
369                        {
370                                if( !strcmp( odbx_field_value( m_result, 0 ), ip.c_str() ) )
371                                {
372                                        return true;
373                                }
374                        }
375                }
376                while( getRecord() );
377        }
378        catch ( exception& e )
379        {
380                L.log( m_myname + " isMaster: Caught STL exception - " + e.what(),  Logger::Error );
381                throw( DBException( "Error: STL exception" ) );
382        }
383
384        return false;
385}
386
387
388
389void OdbxBackend::getUnfreshSlaveInfos( vector<DomainInfo>* unfresh )
390{
391        try
392        {
393                DLOG( L.log( m_myname + " getUnfreshSlaveInfos()", Logger::Debug ) );
394
395                if( unfresh != NULL )
396                {
397                        getDomainList( getArg( "sql-infoslaves" ), unfresh, &checkSlave );
398                }
399        }
400        catch ( exception& e )
401        {
402                L.log( m_myname + " getUnfreshSlaveInfo: Caught STL exception - " + e.what(),  Logger::Error );
403                throw( DBException( "Error: STL exception" ) );
404        }
405}
406
407
408
409void OdbxBackend::getUpdatedMasters( vector<DomainInfo>* updated )
410{
411        try
412        {
413                DLOG( L.log( m_myname + " getUpdatedMasters()", Logger::Debug ) );
414
415                if( updated != NULL )
416                {
417                        getDomainList( getArg( "sql-infomasters" ), updated, &checkMaster );
418                }
419        }
420        catch ( exception& e )
421        {
422                L.log( m_myname + " getUpdatedMasters: Caught STL exception - " + e.what(),  Logger::Error );
423                throw( DBException( "Error: STL exception" ) );
424        }
425}
426
427
428
429bool OdbxBackend::superMasterBackend( const string& ip, const string& domain, const vector<DNSResourceRecord>& set, string* account, DNSBackend** ddb )
430{
431        string stmt;
432        vector<DNSResourceRecord>::const_iterator i;
433
434
435        try
436        {
437                DLOG( L.log( m_myname + " superMasterBackend()", Logger::Debug ) );
438
439                if( account != NULL && ddb != NULL )
440                {
441                        for( i = set.begin(); i != set.end(); i++ )
442                        {
443                                stmt = strbind( ":ip", escape( ip ), getArg( "sql-supermaster" ) );
444                                stmt = strbind( ":ns", escape( i->content ), stmt );
445
446                                execStmt( stmt.c_str(), stmt.size(), true );
447
448                                if( !getRecord() ) { return false; }
449
450                                do
451                                {
452                                        if( odbx_field_value( m_result, 0 ) != NULL )
453                                        {
454                                                *account = string( odbx_field_value( m_result, 0 ), odbx_field_length( m_result, 0 ) );
455                                        }
456                                }
457                                while( getRecord() );
458
459                                *ddb=this;
460                                return true;
461                        }
462                }
463        }
464        catch ( exception& e )
465        {
466                L.log( m_myname + " superMasterBackend: Caught STL exception - " + e.what(),  Logger::Error );
467                throw( DBException( "Error: STL exception" ) );
468        }
469
470        return false;
471}
472
473
474
475bool OdbxBackend::createSlaveDomain( const string& ip, const string& domain, const string& account )
476{
477        size_t len;
478
479
480        try
481        {
482                DLOG( L.log( m_myname + " createSlaveDomain()", Logger::Debug ) );
483
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() );
486
487                if( len < 0 || len > sizeof( m_buffer ) - 1 )
488                {
489                        L.log( m_myname + " createSlaveDomain: Unable to insert values in statement '" + getArg( "sql-insert-slave" ) + "'",  Logger::Error );
490                        throw( DBException( "Error: Libc error" ) );
491                }
492
493                execStmt( m_buffer, len, false );
494        }
495        catch ( exception& e )
496        {
497                L.log( m_myname + " createSlaveDomain: Caught STL exception - " + e.what(),  Logger::Error );
498                throw( DBException( "Error: STL exception" ) );
499        }
500
501        return true;
502}
503
504
505
506bool OdbxBackend::feedRecord( const DNSResourceRecord& rr )
507{
508        size_t len;
509
510
511        try
512        {
513                DLOG( L.log( m_myname + " feedRecord()", Logger::Debug ) );
514
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() );
517
518                if( len < 0 || len > sizeof( m_buffer ) - 1 )
519                {
520                        L.log( m_myname + " feedRecord: Unable to insert values in statement '" + getArg( "sql-insert-record" ) + "'",  Logger::Error );
521                        throw( DBException( "Error: Libc error" ) );
522                }
523
524                execStmt( m_buffer, len, false );
525        }
526        catch ( exception& e )
527        {
528                L.log( m_myname + " feedRecord: Caught STL exception - " + e.what(),  Logger::Error );
529                throw( DBException( "Error: STL exception" ) );
530        }
531
532        return true;
533}
534
535
536
537bool OdbxBackend::startTransaction( const string& domain, int zoneid )
538{
539        size_t len;
540        string stmt;
541
542
543        try
544        {
545                DLOG( L.log( m_myname + " startTransaction()", Logger::Debug ) );
546
547                stmt = getArg( "sql-transactbegin" );
548                execStmt( stmt.c_str(), stmt.size(), false );
549
550                len = snprintf( m_buffer, sizeof( m_buffer ) - 1, "%d", zoneid );
551
552                if( len < 0 || len > sizeof( m_buffer ) - 1 )
553                {
554                        L.log( m_myname + " lookup: Unable to convert zone id to string",  Logger::Error );
555                        throw( DBException( "Error: Libc error" ) );
556                }
557
558                stmt = strbind( ":id", string( m_buffer, len ), getArg( "sql-zonedelete" ) );
559
560                execStmt( stmt.c_str(), stmt.size(), false );
561        }
562        catch ( exception& e )
563        {
564                L.log( m_myname + " startTransaction: Caught STL exception - " + e.what(),  Logger::Error );
565                throw( DBException( "Error: STL exception" ) );
566        }
567
568        return true;
569}
570
571
572
573bool OdbxBackend::commitTransaction()
574{
575        try
576        {
577                DLOG( L.log( m_myname + " commitTransaction()", Logger::Debug ) );
578
579                execStmt( getArg( "sql-transactend" ).c_str(), getArg( "sql-transactend" ).size(), false );
580        }
581        catch ( exception& e )
582        {
583                L.log( m_myname + " commitTransaction: Caught STL exception - " + e.what(),  Logger::Error );
584                throw( DBException( "Error: STL exception" ) );
585        }
586
587        return true;
588}
589
590
591
592bool OdbxBackend::abortTransaction()
593{
594        try
595        {
596                DLOG( L.log( m_myname + " abortTransaction()", Logger::Debug ) );
597
598                execStmt( getArg( "sql-transactabort" ).c_str(), getArg( "sql-transabort" ).size(), false );
599        }
600        catch ( exception& e )
601        {
602                L.log( m_myname + " abortTransaction: Caught STL exception - " + e.what(),  Logger::Error );
603                throw( DBException( "Error: STL exception" ) );
604        }
605
606        return true;
607}
Note: See TracBrowser for help on using the browser.