]>
git.ipfire.org Git - thirdparty/pdns.git/blob - modules/opendbxbackend/odbxprivate.cc
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 #include "odbxbackend.hh"
29 unsigned int odbx_host_index
[2] = { 0, 0 };
33 bool OdbxBackend::connectTo( const vector
<string
>& hosts
, QueryType type
)
37 int idx
= odbx_host_index
[type
]++ % hosts
.size();
40 if( m_handle
[type
] != NULL
)
42 odbx_unbind( m_handle
[type
] );
43 odbx_finish( m_handle
[type
] );
44 m_handle
[type
] = NULL
;
47 if( type
== WRITE
&& getArg( "backend" ) == "sqlite" )
49 L
.log( m_myname
+ " Using same SQLite connection for reading and writing to '" + hosts
[odbx_host_index
[READ
]] + "'", Logger::Notice
);
50 m_handle
[WRITE
] = m_handle
[READ
];
54 for( i
= 0; i
< hosts
.size(); i
++ )
56 h
= ( idx
+ i
) % hosts
.size();
58 if( ( err
= odbx_init( &(m_handle
[type
]), getArg( "backend" ).c_str(), hosts
[h
].c_str(), getArg( "port" ).c_str() ) ) == ODBX_ERR_SUCCESS
)
60 if( ( err
= odbx_bind( m_handle
[type
], getArg( "database" ).c_str(), getArg( "username" ).c_str(), getArg( "password" ).c_str(), ODBX_BIND_SIMPLE
) ) == ODBX_ERR_SUCCESS
)
62 L
.log( m_myname
+ " Database connection (" + (type
? "write" : "read") + ") to '" + hosts
[h
] + "' succeeded", Logger::Notice
);
66 L
.log( m_myname
+ " Unable to bind to database on host " + hosts
[h
] + " - " + string( odbx_error( m_handle
[type
], err
) ), Logger::Error
);
70 L
.log( m_myname
+ " Unable to connect to server on host " + hosts
[h
] + " - " + string( odbx_error( m_handle
[type
], err
) ), Logger::Error
);
73 m_handle
[type
] = NULL
;
79 bool OdbxBackend::execStmt( const char* stmt
, unsigned long length
, QueryType type
)
84 DLOG( L
.log( m_myname
+ " execStmt()", Logger::Debug
) );
86 if( m_qlog
) { L
.log( m_myname
+ " Query: " + stmt
, Logger::Info
); }
88 if( ( err
= odbx_query( m_handle
[type
], stmt
, length
) ) < 0 )
90 L
.log( m_myname
+ " execStmt: Unable to execute query - " + string( odbx_error( m_handle
[type
], err
) ), Logger::Error
);
92 if( err
!= -ODBX_ERR_PARAM
&& odbx_error_type( m_handle
[type
], err
) > 0 ) { return false; } // ODBX_ERR_PARAM workaround
93 if( !connectTo( m_hosts
[type
], type
) ) { return false; }
94 if( odbx_query( m_handle
[type
], stmt
, length
) < 0 ) { return false; }
97 if( type
== WRITE
) { while( getRecord( type
) ); }
104 bool OdbxBackend::getRecord( QueryType type
)
109 DLOG( L
.log( m_myname
+ " getRecord()", Logger::Debug
) );
115 L
.log( m_myname
+ " getRecord: Unable to get next result - " + string( odbx_error( m_handle
[type
], err
) ), Logger::Error
);
116 throw( PDNSException( "Error: odbx_result() failed" ) );
119 if( m_result
!= NULL
)
123 if( ( err
= odbx_row_fetch( m_result
) ) < 0 )
125 L
.log( m_myname
+ " getRecord: Unable to get next row - " + string( odbx_error( m_handle
[type
], err
) ), Logger::Error
);
126 throw( PDNSException( "Error: odbx_row_fetch() failed" ) );
135 for( i
= 0; i
< odbx_column_count( m_result
); i
++ )
137 fields
+= string( odbx_column_name( m_result
, i
) );
139 if( odbx_field_value( m_result
, i
) != NULL
)
141 fields
+= "=" + string( odbx_field_value( m_result
, i
) ) + ", ";
149 L
.log( m_myname
+ " Values: " + fields
, Logger::Error
);
156 odbx_result_free( m_result
);
160 while( ( err
= odbx_result( m_handle
[type
], &m_result
, NULL
, 0 ) ) != 0 );
168 string
OdbxBackend::escape( const string
& str
, QueryType type
)
171 unsigned long len
= sizeof( m_escbuf
);
174 DLOG( L
.log( m_myname
+ " escape(string)", Logger::Debug
) );
176 if( ( err
= odbx_escape( m_handle
[type
], str
.c_str(), str
.size(), m_escbuf
, &len
) ) < 0 )
178 L
.log( m_myname
+ " escape(string): Unable to escape string - " + string( odbx_error( m_handle
[type
], err
) ), Logger::Error
);
180 if( err
!= -ODBX_ERR_PARAM
&& odbx_error_type( m_handle
[type
], err
) > 0 ) { throw( runtime_error( "odbx_escape() failed" ) ); } // ODBX_ERR_PARAM workaround
181 if( !connectTo( m_hosts
[type
], type
) ) { throw( runtime_error( "odbx_escape() failed" ) ); }
182 if( odbx_escape( m_handle
[type
], str
.c_str(), str
.size(), m_escbuf
, &len
) < 0 ) { throw( runtime_error( "odbx_escape() failed" ) ); }
185 return string( m_escbuf
, len
);
190 bool OdbxBackend::getDomainList( const string
& stmt
, vector
<DomainInfo
>* list
, bool (*check_fcn
)(uint32_t,uint32_t,SOAData
*,DomainInfo
*) )
193 uint32_t nlast
, nserial
;
197 DLOG( L
.log( m_myname
+ " getDomainList()", Logger::Debug
) );
199 if( !execStmt( stmt
.c_str(), stmt
.size(), READ
) ) { return false; }
200 if( !getRecord( READ
) ) { return false; }
210 if( ( tmp
= odbx_field_value( m_result
, 6 ) ) != NULL
)
212 fillSOAData( string( tmp
, odbx_field_length( m_result
, 6 ) ), sd
);
215 if( !sd
.serial
&& ( tmp
= odbx_field_value( m_result
, 5 ) ) != NULL
)
217 sd
.serial
= strtol( tmp
, NULL
, 10 );
220 if( ( tmp
= odbx_field_value( m_result
, 4 ) ) != NULL
)
222 nserial
= strtol( tmp
, NULL
, 10 );
225 if( ( tmp
= odbx_field_value( m_result
, 3 ) ) != NULL
)
227 nlast
= strtol( tmp
, NULL
, 10 );
230 if( (*check_fcn
)( nlast
, nserial
, &sd
, &di
) )
232 if( ( tmp
= odbx_field_value( m_result
, 2 ) ) != NULL
)
234 stringtok(di
.masters
, string( tmp
, odbx_field_length( m_result
, 2 )), ", \t" );
237 if( ( tmp
= odbx_field_value( m_result
, 1 ) ) != NULL
)
239 di
.zone
= DNSName( string(tmp
, odbx_field_length( m_result
, 1 )) );
242 if( ( tmp
= odbx_field_value( m_result
, 0 ) ) != NULL
)
244 di
.id
= strtol( tmp
, NULL
, 10 );
247 di
.last_check
= nlast
;
248 di
.notified_serial
= nserial
;
249 di
.serial
= sd
.serial
;
252 list
->push_back( di
);
255 while( getRecord( READ
) );
262 bool checkSlave( uint32_t nlast
, uint32_t nserial
, SOAData
* sd
, DomainInfo
* di
)
264 if( nlast
+ sd
->refresh
< (uint32_t) time( 0 ) )
266 di
->kind
= DomainInfo::Slave
;
275 bool checkMaster( uint32_t nlast
, uint32_t nserial
, SOAData
* sd
, DomainInfo
* di
)
277 if( nserial
!= sd
->serial
)
279 di
->kind
= DomainInfo::Master
;