]>
Commit | Line | Data |
---|---|---|
a3814809 | 1 | /* |
12471842 PL |
2 | * This file is part of PowerDNS or dnsdist. |
3 | * Copyright -- PowerDNS.COM B.V. and its contributors | |
4 | * originally authored by Norbert Sendetzky | |
a3814809 | 5 | * |
12471842 PL |
6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of version 2 of the GNU General Public License as | |
8 | * published by the Free Software Foundation. | |
a3814809 | 9 | * |
12471842 PL |
10 | * In addition, for the avoidance of any doubt, permission is granted to |
11 | * link this program with OpenSSL and to (re)distribute the binaries | |
12 | * produced as the result of such linking. | |
a3814809 | 13 | * |
12471842 PL |
14 | * This program is distributed in the hope that it will be useful, |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | * GNU General Public License for more details. | |
a3814809 | 18 | * |
12471842 PL |
19 | * You should have received a copy of the GNU General Public License |
20 | * along with this program; if not, write to the Free Software | |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
a3814809 | 22 | */ |
870a0fe4 AT |
23 | #ifdef HAVE_CONFIG_H |
24 | #include "config.h" | |
25 | #endif | |
790e7c1b BH |
26 | #include "odbxbackend.hh" |
27 | ||
28 | ||
29 | ||
8e20e603 BH |
30 | inline string& strbind( const string& search, const string& replace, string& subject ) |
31 | { | |
e0ec6e79 | 32 | size_t pos = 0; |
8e20e603 | 33 | |
e0ec6e79 BH |
34 | while( ( pos = subject.find( search, pos ) ) != string::npos ) |
35 | { | |
36 | subject.replace( pos, search.size(), replace ); | |
37 | pos += replace.size(); | |
38 | } | |
8e20e603 | 39 | |
e0ec6e79 | 40 | return subject; |
8e20e603 BH |
41 | } |
42 | ||
43 | ||
44 | ||
790e7c1b BH |
45 | OdbxBackend::OdbxBackend( const string& suffix ) |
46 | { | |
e0ec6e79 BH |
47 | vector<string> hosts; |
48 | ||
49 | ||
50 | try | |
51 | { | |
52 | m_result = NULL; | |
53 | m_handle[READ] = NULL; | |
54 | m_handle[WRITE] = NULL; | |
55 | m_myname = "[OpendbxBackend]"; | |
56 | m_default_ttl = arg().asNum( "default-ttl" ); | |
57 | m_qlog = arg().mustDo( "query-logging" ); | |
58 | ||
59 | setArgPrefix( "opendbx" + suffix ); | |
60 | ||
61 | if( getArg( "host" ).size() > 0 ) | |
62 | { | |
e6a9dde5 | 63 | g_log.log( m_myname + " WARNING: Using deprecated opendbx-host parameter", Logger::Warning ); |
e0ec6e79 BH |
64 | stringtok( m_hosts[READ], getArg( "host" ), ", " ); |
65 | m_hosts[WRITE] = m_hosts[READ]; | |
66 | } | |
67 | else | |
68 | { | |
69 | stringtok( m_hosts[READ], getArg( "host-read" ), ", " ); | |
70 | stringtok( m_hosts[WRITE], getArg( "host-write" ), ", " ); | |
71 | } | |
72 | ||
3f81d239 | 73 | if( !connectTo( m_hosts[READ], READ ) ) { throw( PDNSException( "Fatal: Connecting to server for reading failed" ) ); } |
74 | if( !connectTo( m_hosts[WRITE], WRITE ) ) { throw( PDNSException( "Fatal: Connecting to server for writing failed" ) ); } | |
e0ec6e79 | 75 | } |
a2f4c096 | 76 | catch( std::exception& e ) |
e0ec6e79 | 77 | { |
e6a9dde5 | 78 | g_log.log( m_myname + " OdbxBackend(): Caught STL exception - " + e.what(), Logger::Error ); |
3f81d239 | 79 | throw( PDNSException( "Fatal: STL exception" ) ); |
e0ec6e79 | 80 | } |
790e7c1b BH |
81 | } |
82 | ||
83 | ||
84 | ||
85 | OdbxBackend::~OdbxBackend() | |
86 | { | |
e0ec6e79 BH |
87 | odbx_unbind( m_handle[WRITE] ); |
88 | odbx_unbind( m_handle[READ] ); | |
8e20e603 | 89 | |
e0ec6e79 BH |
90 | odbx_finish( m_handle[WRITE] ); |
91 | odbx_finish( m_handle[READ] ); | |
790e7c1b BH |
92 | } |
93 | ||
94 | ||
95 | ||
cf8c91f3 | 96 | bool OdbxBackend::getDomainInfo( const DNSName& domain, DomainInfo& di ) |
790e7c1b | 97 | { |
e0ec6e79 BH |
98 | const char* tmp; |
99 | ||
100 | ||
101 | try | |
102 | { | |
e6a9dde5 | 103 | DLOG( g_log.log( m_myname + " getDomainInfo()", Logger::Debug ) ); |
e0ec6e79 BH |
104 | |
105 | string stmt = getArg( "sql-zoneinfo" ); | |
cf8c91f3 | 106 | string& stmtref = strbind( ":name", escape( domain.makeLowerCase().toStringRootDot(), READ ), stmt ); |
e0ec6e79 BH |
107 | |
108 | if( !execStmt( stmtref.c_str(), stmtref.size(), READ ) ) { return false; } | |
109 | if( !getRecord( READ ) ) { return false; } | |
110 | ||
111 | do | |
112 | { | |
113 | di.id = 0; | |
df26024e | 114 | di.zone.clear(); |
e0ec6e79 BH |
115 | di.masters.clear(); |
116 | di.last_check = 0; | |
117 | di.notified_serial = 0; | |
118 | di.kind = DomainInfo::Native; | |
119 | di.backend = this; | |
120 | di.serial = 0; | |
121 | ||
122 | if( ( tmp = odbx_field_value( m_result, 6 ) ) != NULL ) | |
123 | { | |
124 | SOAData sd; | |
125 | ||
126 | sd.serial = 0; | |
127 | fillSOAData( string( tmp, odbx_field_length( m_result, 6 ) ), sd ); | |
128 | ||
129 | if( sd.serial == 0 && ( tmp = odbx_field_value( m_result, 5 ) ) != NULL ) | |
130 | { | |
131 | sd.serial = strtol( tmp, NULL, 10 ); | |
132 | } | |
133 | ||
134 | di.serial = sd.serial; | |
135 | } | |
136 | ||
137 | if( ( tmp = odbx_field_value( m_result, 4 ) ) != NULL ) | |
138 | { | |
139 | di.last_check = strtol( tmp, NULL, 10 ); | |
140 | } | |
141 | ||
142 | if( ( tmp = odbx_field_value( m_result, 3 ) ) != NULL ) | |
143 | { | |
144 | stringtok(di.masters, string( tmp, odbx_field_length( m_result, 3 ) ), ", \t"); | |
145 | } | |
146 | ||
147 | if( ( tmp = odbx_field_value( m_result, 2 ) ) != NULL ) | |
148 | { | |
149 | if( !strncmp( tmp, "SLAVE", 5 ) ) | |
150 | { | |
151 | di.kind = DomainInfo::Slave; | |
152 | } | |
153 | else if( !strncmp( tmp, "MASTER", 6 ) ) | |
154 | { | |
155 | di.kind = DomainInfo::Master; | |
156 | } | |
157 | } | |
158 | ||
159 | if( ( tmp = odbx_field_value( m_result, 1 ) ) != NULL ) | |
160 | { | |
cf8c91f3 | 161 | di.zone = DNSName(string( tmp, odbx_field_length( m_result, 1 ) )); |
e0ec6e79 BH |
162 | } |
163 | ||
164 | if( ( tmp = odbx_field_value( m_result, 0 ) ) != NULL ) | |
165 | { | |
166 | di.id = strtol( tmp, NULL, 10 ); | |
167 | } | |
168 | } | |
169 | while( getRecord( READ ) ); | |
170 | } | |
a2f4c096 | 171 | catch( std::exception& e ) |
e0ec6e79 | 172 | { |
e6a9dde5 | 173 | g_log.log( m_myname + " getDomainInfo: Caught STL std::exception - " + e.what(), Logger::Error ); |
e0ec6e79 BH |
174 | return false; |
175 | } | |
176 | ||
177 | return true; | |
e830c249 BH |
178 | } |
179 | ||
180 | ||
181 | ||
13f9e280 | 182 | bool OdbxBackend::getSOA( const DNSName& domain, SOAData& sd, bool unmodifiedSerial) |
e830c249 | 183 | { |
e0ec6e79 BH |
184 | const char* tmp; |
185 | ||
186 | ||
187 | try | |
188 | { | |
e6a9dde5 | 189 | DLOG( g_log.log( m_myname + " getSOA()", Logger::Debug ) ); |
e0ec6e79 BH |
190 | |
191 | string stmt = getArg( "sql-lookupsoa" ); | |
cf8c91f3 | 192 | string& stmtref = strbind( ":name", escape( domain.makeLowerCase().toStringRootDot(), READ ), stmt ); |
e0ec6e79 BH |
193 | |
194 | if( !execStmt( stmtref.c_str(), stmtref.size(), READ ) ) { return false; } | |
195 | if( !getRecord( READ ) ) { return false; } | |
196 | ||
197 | do | |
198 | { | |
01df0d92 | 199 | sd.qname = domain; |
e0ec6e79 BH |
200 | sd.serial = 0; |
201 | sd.ttl = m_default_ttl; | |
202 | ||
203 | if( ( tmp = odbx_field_value( m_result, 3 ) ) != NULL ) | |
204 | { | |
205 | fillSOAData( string( tmp, odbx_field_length( m_result, 3 ) ), sd ); | |
206 | } | |
207 | ||
208 | if( ( tmp = odbx_field_value( m_result, 2 ) ) != NULL ) | |
209 | { | |
210 | sd.ttl = strtoul( tmp, NULL, 10 ); | |
ed56a9d7 | 211 | } |
e0ec6e79 | 212 | |
13f9e280 | 213 | if( !unmodifiedSerial && sd.serial == 0 && ( tmp = odbx_field_value( m_result, 1 ) ) != NULL ) |
e0ec6e79 BH |
214 | { |
215 | sd.serial = strtol( tmp, NULL, 10 ); | |
216 | } | |
217 | ||
218 | if( ( tmp = odbx_field_value( m_result, 0 ) ) != NULL ) | |
219 | { | |
220 | sd.domain_id = strtol( tmp, NULL, 10 ); | |
221 | } | |
222 | ||
223 | if( sd.nameserver.empty() ) | |
224 | { | |
cf8c91f3 | 225 | sd.nameserver = DNSName(arg()["default-soa-name"]); |
e0ec6e79 BH |
226 | } |
227 | ||
228 | if( sd.hostmaster.empty() ) | |
229 | { | |
cf8c91f3 | 230 | sd.hostmaster = DNSName("hostmaster") + DNSName(domain); |
e0ec6e79 BH |
231 | } |
232 | ||
233 | sd.db = this; | |
234 | } | |
235 | while( getRecord( READ ) ); | |
236 | } | |
a2f4c096 | 237 | catch( std::exception& e ) |
e0ec6e79 | 238 | { |
e6a9dde5 | 239 | g_log.log( m_myname + " getSOA: Caught STL exception - " + e.what(), Logger::Error ); |
e0ec6e79 BH |
240 | return false; |
241 | } | |
242 | ||
243 | return true; | |
790e7c1b BH |
244 | } |
245 | ||
246 | ||
247 | ||
ed56a9d7 | 248 | bool OdbxBackend::list( const DNSName& target, int zoneid, bool include_disabled ) |
790e7c1b | 249 | { |
e0ec6e79 BH |
250 | try |
251 | { | |
e6a9dde5 | 252 | DLOG( g_log.log( m_myname + " list()", Logger::Debug ) ); |
e0ec6e79 | 253 | |
cf8c91f3 | 254 | m_qname.clear(); |
e0ec6e79 BH |
255 | m_result = NULL; |
256 | ||
90e286b7 | 257 | int len = snprintf( m_buffer, sizeof( m_buffer ) - 1, "%d", zoneid ); |
e0ec6e79 BH |
258 | |
259 | if( len < 0 ) | |
260 | { | |
e6a9dde5 | 261 | g_log.log( m_myname + " list: Unable to convert zone id to string - format error", Logger::Error ); |
e0ec6e79 BH |
262 | return false; |
263 | } | |
264 | ||
579c61f5 | 265 | if( len > static_cast<int>(sizeof( m_buffer )) - 1 ) |
e0ec6e79 | 266 | { |
e6a9dde5 | 267 | g_log.log( m_myname + " list: Unable to convert zone id to string - insufficient buffer space", Logger::Error ); |
e0ec6e79 BH |
268 | return false; |
269 | } | |
270 | ||
271 | string stmt = getArg( "sql-list" ); | |
272 | string& stmtref = strbind( ":id", string( m_buffer, len ), stmt ); | |
273 | ||
274 | if( !execStmt( stmtref.c_str(), stmtref.size(), READ ) ) { return false; } | |
275 | } | |
a2f4c096 | 276 | catch( std::exception& e ) |
e0ec6e79 | 277 | { |
e6a9dde5 | 278 | g_log.log( m_myname + " list: Caught STL exception - " + e.what(), Logger::Error ); |
e0ec6e79 BH |
279 | return false; |
280 | } | |
281 | ||
282 | return true; | |
790e7c1b BH |
283 | } |
284 | ||
285 | ||
286 | ||
ed56a9d7 | 287 | void OdbxBackend::lookup( const QType& qtype, const DNSName& qname, DNSPacket* dnspkt, int zoneid ) |
790e7c1b | 288 | { |
e0ec6e79 BH |
289 | try |
290 | { | |
e6a9dde5 | 291 | DLOG( g_log.log( m_myname + " lookup()", Logger::Debug ) ); |
e0ec6e79 BH |
292 | |
293 | string stmt; | |
294 | string& stmtref = stmt; | |
295 | ||
296 | m_result = NULL; | |
297 | m_qname = qname; | |
298 | ||
299 | if( zoneid < 0 ) | |
300 | { | |
301 | if( qtype.getCode() == QType::ANY ) | |
302 | { | |
303 | stmt = getArg( "sql-lookup" ); | |
304 | } else { | |
305 | stmt = getArg( "sql-lookuptype" ); | |
306 | stmtref = strbind( ":type", qtype.getName(), stmt ); | |
307 | } | |
308 | } | |
309 | else | |
310 | { | |
311 | if( qtype.getCode() == QType::ANY ) | |
312 | { | |
cf8c91f3 | 313 | stmt = getArg( "sql-lookupid" ); |
e0ec6e79 BH |
314 | } else { |
315 | stmt = getArg( "sql-lookuptypeid" ); | |
316 | stmtref = strbind( ":type", qtype.getName(), stmt ); | |
317 | } | |
318 | ||
90e286b7 | 319 | int len = snprintf( m_buffer, sizeof( m_buffer ) - 1, "%d", zoneid ); |
e0ec6e79 BH |
320 | |
321 | if( len < 0 ) | |
322 | { | |
e6a9dde5 | 323 | g_log.log( m_myname + " lookup: Unable to convert zone id to string - format error", Logger::Error ); |
e0ec6e79 BH |
324 | throw( DBException( "Error: Libc error" ) ); |
325 | } | |
326 | ||
579c61f5 | 327 | if( len > static_cast<int>(sizeof( m_buffer )) - 1 ) |
e0ec6e79 | 328 | { |
e6a9dde5 | 329 | g_log.log( m_myname + " lookup: Unable to convert zone id to string - insufficient buffer space", Logger::Error ); |
e0ec6e79 BH |
330 | throw( DBException( "Error: Libc error" ) ); |
331 | } | |
332 | ||
333 | stmtref = strbind( ":id", string( m_buffer, len ), stmtref ); | |
334 | } | |
335 | ||
cf8c91f3 | 336 | stmtref = strbind( ":name", escape( qname.makeLowerCase().toStringRootDot(), READ ), stmtref ); |
e0ec6e79 BH |
337 | |
338 | if( !execStmt( stmtref.c_str(), stmtref.size(), READ ) ) | |
339 | { | |
340 | throw( DBException( "Error: DB statement failed" ) ); | |
341 | } | |
342 | } | |
a2f4c096 | 343 | catch( std::exception& e ) |
e0ec6e79 | 344 | { |
e6a9dde5 | 345 | g_log.log( m_myname + " lookup: Caught STL exception - " + e.what(), Logger::Error ); |
e0ec6e79 BH |
346 | throw( DBException( "Error: STL exception" ) ); |
347 | } | |
790e7c1b BH |
348 | } |
349 | ||
350 | ||
351 | ||
352 | bool OdbxBackend::get( DNSResourceRecord& rr ) | |
353 | { | |
e0ec6e79 | 354 | const char* tmp; |
b9bafae0 | 355 | string priority; |
e0ec6e79 BH |
356 | |
357 | try | |
358 | { | |
e6a9dde5 | 359 | DLOG( g_log.log( m_myname + " get()", Logger::Debug ) ); |
e0ec6e79 BH |
360 | |
361 | if( getRecord( READ ) ) | |
362 | { | |
b9bafae0 | 363 | |
e0ec6e79 | 364 | rr.content = ""; |
e0ec6e79 BH |
365 | rr.domain_id = 0; |
366 | rr.last_modified = 0; | |
367 | rr.ttl = m_default_ttl; | |
368 | rr.qname = m_qname; | |
369 | ||
370 | if( ( tmp = odbx_field_value( m_result, 0 ) ) != NULL ) | |
371 | { | |
372 | rr.domain_id = strtol( tmp, NULL, 10 ); | |
373 | } | |
374 | ||
375 | if( m_qname.empty() && ( tmp = odbx_field_value( m_result, 1 ) ) != NULL ) | |
376 | { | |
cf8c91f3 | 377 | rr.qname = DNSName( string(tmp, odbx_field_length( m_result, 1 ) )); |
e0ec6e79 BH |
378 | } |
379 | ||
380 | if( ( tmp = odbx_field_value( m_result, 2 ) ) != NULL ) | |
381 | { | |
864e676f | 382 | rr.qtype = tmp; |
e0ec6e79 BH |
383 | } |
384 | ||
385 | if( ( tmp = odbx_field_value( m_result, 3 ) ) != NULL ) | |
386 | { | |
387 | rr.ttl = strtoul( tmp, NULL, 10 ); | |
388 | } | |
389 | ||
390 | if( ( tmp = odbx_field_value( m_result, 4 ) ) != NULL ) | |
391 | { | |
b9bafae0 | 392 | priority = string( tmp, odbx_field_length( m_result, 4 ) ); |
e0ec6e79 BH |
393 | } |
394 | ||
395 | if( ( tmp = odbx_field_value( m_result, 5 ) ) != NULL ) | |
396 | { | |
397 | rr.content = string( tmp, odbx_field_length( m_result, 5 ) ); | |
398 | } | |
399 | ||
b9bafae0 KM |
400 | if (rr.qtype==QType::MX || rr.qtype==QType::SRV) |
401 | rr.content = priority + " " + rr.content; | |
402 | ||
e0ec6e79 BH |
403 | return true; |
404 | } | |
405 | } | |
a2f4c096 | 406 | catch( std::exception& e ) |
e0ec6e79 | 407 | { |
e6a9dde5 | 408 | g_log.log( m_myname + " get: Caught STL exception - " + e.what(), Logger::Error ); |
e0ec6e79 BH |
409 | return false; |
410 | } | |
411 | ||
412 | return false; | |
790e7c1b BH |
413 | } |
414 | ||
415 | ||
e830c249 | 416 | void OdbxBackend::setFresh( uint32_t domain_id ) |
790e7c1b | 417 | { |
90e286b7 | 418 | int len; |
e0ec6e79 BH |
419 | |
420 | ||
421 | try | |
422 | { | |
e6a9dde5 | 423 | DLOG( g_log.log( m_myname + " setFresh()", Logger::Debug ) ); |
e0ec6e79 BH |
424 | |
425 | if( !m_handle[WRITE] && !connectTo( m_hosts[WRITE], WRITE ) ) | |
426 | { | |
e6a9dde5 | 427 | g_log.log( m_myname + " setFresh: Master server is unreachable", Logger::Error ); |
e0ec6e79 BH |
428 | throw( DBException( "Error: Server unreachable" ) ); |
429 | } | |
430 | ||
431 | len = snprintf( m_buffer, sizeof( m_buffer ) - 1, getArg( "sql-update-lastcheck" ).c_str(), time( 0 ), domain_id ); | |
432 | ||
433 | if( len < 0 ) | |
434 | { | |
e6a9dde5 | 435 | g_log.log( m_myname + " setFresh: Unable to insert values into statement '" + getArg( "sql-update-lastcheck" ) + "' - format error", Logger::Error ); |
e0ec6e79 BH |
436 | throw( DBException( "Error: Libc error" ) ); |
437 | } | |
438 | ||
579c61f5 | 439 | if( len > static_cast<int>(sizeof( m_buffer )) - 1 ) |
e0ec6e79 | 440 | { |
e6a9dde5 | 441 | g_log.log( m_myname + " setFresh: Unable to insert values into statement '" + getArg( "sql-update-lastcheck" ) + "' - insufficient buffer space", Logger::Error ); |
e0ec6e79 BH |
442 | throw( DBException( "Error: Libc error" ) ); |
443 | } | |
444 | ||
445 | if( !execStmt( m_buffer, len, WRITE ) ) | |
446 | { | |
447 | throw( DBException( "Error: DB statement failed" ) ); | |
448 | } | |
449 | } | |
a2f4c096 | 450 | catch ( std::exception& e ) |
e0ec6e79 | 451 | { |
e6a9dde5 | 452 | g_log.log( m_myname + " setFresh: Caught STL exception - " + e.what(), Logger::Error ); |
e0ec6e79 BH |
453 | throw( DBException( "Error: STL exception" ) ); |
454 | } | |
790e7c1b BH |
455 | } |
456 | ||
457 | ||
458 | ||
e830c249 | 459 | void OdbxBackend::setNotified( uint32_t domain_id, uint32_t serial ) |
790e7c1b | 460 | { |
e0ec6e79 BH |
461 | try |
462 | { | |
e6a9dde5 | 463 | DLOG( g_log.log( m_myname + " setNotified()", Logger::Debug ) ); |
e0ec6e79 BH |
464 | |
465 | if( !m_handle[WRITE] && !connectTo( m_hosts[WRITE], WRITE ) ) | |
466 | { | |
e6a9dde5 | 467 | g_log.log( m_myname + " setFresh: Master server is unreachable", Logger::Error ); |
e0ec6e79 BH |
468 | throw( DBException( "Error: Server unreachable" ) ); |
469 | } | |
470 | ||
90e286b7 | 471 | int len = snprintf( m_buffer, sizeof( m_buffer ) - 1, getArg( "sql-update-serial" ).c_str(), serial, domain_id ); |
e0ec6e79 BH |
472 | |
473 | if( len < 0 ) | |
474 | { | |
e6a9dde5 | 475 | g_log.log( m_myname + " setNotified: Unable to insert values into statement '" + getArg( "sql-update-serial" ) + "' - format error", Logger::Error ); |
e0ec6e79 BH |
476 | throw( DBException( "Error: Libc error" ) ); |
477 | } | |
478 | ||
579c61f5 | 479 | if( len > static_cast<int>(sizeof( m_buffer )) - 1 ) |
e0ec6e79 | 480 | { |
e6a9dde5 | 481 | g_log.log( m_myname + " setNotified: Unable to insert values into statement '" + getArg( "sql-update-serial" ) + "' - insufficient buffer space", Logger::Error ); |
e0ec6e79 BH |
482 | throw( DBException( "Error: Libc error" ) ); |
483 | } | |
484 | ||
485 | if( !execStmt( m_buffer, len, WRITE ) ) | |
486 | { | |
487 | throw( DBException( "Error: DB statement failed" ) ); | |
488 | } | |
489 | } | |
a2f4c096 | 490 | catch ( std::exception& e ) |
e0ec6e79 | 491 | { |
e6a9dde5 | 492 | g_log.log( m_myname + " setNotified: Caught STL exception - " + e.what(), Logger::Error ); |
e0ec6e79 BH |
493 | throw( DBException( "Error: STL exception" ) ); |
494 | } | |
790e7c1b BH |
495 | } |
496 | ||
497 | ||
498 | ||
cf8c91f3 | 499 | bool OdbxBackend::isMaster( const DNSName& domain, const string& ip ) |
790e7c1b | 500 | { |
e0ec6e79 BH |
501 | try |
502 | { | |
e6a9dde5 | 503 | DLOG( g_log.log( m_myname + " isMaster()", Logger::Debug ) ); |
e0ec6e79 BH |
504 | |
505 | string stmt = getArg( "sql-master" ); | |
cf8c91f3 | 506 | string& stmtref = strbind( ":name", escape( domain.makeLowerCase().toStringRootDot(), READ ), stmt ); |
e0ec6e79 BH |
507 | |
508 | if( !execStmt( stmtref.c_str(), stmtref.size(), READ ) ) { return false; } | |
509 | if( !getRecord( READ ) ) { return false; } | |
510 | ||
511 | do | |
512 | { | |
513 | if( odbx_field_value( m_result, 0 ) != NULL ) | |
514 | { | |
515 | if( !strcmp( odbx_field_value( m_result, 0 ), ip.c_str() ) ) | |
516 | { | |
517 | while( getRecord( READ ) ); | |
518 | return true; | |
519 | } | |
520 | } | |
521 | } | |
522 | while( getRecord( READ ) ); | |
523 | } | |
a2f4c096 | 524 | catch ( std::exception& e ) |
e0ec6e79 | 525 | { |
e6a9dde5 | 526 | g_log.log( m_myname + " isMaster: Caught STL exception - " + e.what(), Logger::Error ); |
e0ec6e79 BH |
527 | return false; |
528 | } | |
529 | ||
530 | return false; | |
790e7c1b BH |
531 | } |
532 | ||
533 | ||
534 | ||
535 | void OdbxBackend::getUnfreshSlaveInfos( vector<DomainInfo>* unfresh ) | |
536 | { | |
e0ec6e79 BH |
537 | try |
538 | { | |
e6a9dde5 | 539 | DLOG( g_log.log( m_myname + " getUnfreshSlaveInfos()", Logger::Debug ) ); |
e0ec6e79 BH |
540 | |
541 | if( unfresh == NULL ) | |
542 | { | |
e6a9dde5 | 543 | g_log.log( m_myname + " getUnfreshSlaveInfos: invalid parameter - NULL pointer", Logger::Error ); |
e0ec6e79 BH |
544 | return; |
545 | } | |
546 | ||
547 | getDomainList( getArg( "sql-infoslaves" ), unfresh, &checkSlave ); | |
548 | } | |
a2f4c096 | 549 | catch ( std::exception& e ) |
e0ec6e79 | 550 | { |
e6a9dde5 | 551 | g_log.log( m_myname + " getUnfreshSlaveInfo: Caught STL exception - " + e.what(), Logger::Error ); |
e0ec6e79 | 552 | } |
790e7c1b BH |
553 | } |
554 | ||
555 | ||
556 | ||
557 | void OdbxBackend::getUpdatedMasters( vector<DomainInfo>* updated ) | |
558 | { | |
e0ec6e79 BH |
559 | try |
560 | { | |
e6a9dde5 | 561 | DLOG( g_log.log( m_myname + " getUpdatedMasters()", Logger::Debug ) ); |
e0ec6e79 BH |
562 | |
563 | if( updated == NULL ) | |
564 | { | |
e6a9dde5 | 565 | g_log.log( m_myname + " getUpdatedMasters: invalid parameter - NULL pointer", Logger::Error ); |
e0ec6e79 BH |
566 | return; |
567 | } | |
568 | ||
569 | getDomainList( getArg( "sql-infomasters" ), updated, &checkMaster ); | |
570 | } | |
a2f4c096 | 571 | catch ( std::exception& e ) |
e0ec6e79 | 572 | { |
e6a9dde5 | 573 | g_log.log( m_myname + " getUpdatedMasters: Caught STL exception - " + e.what(), Logger::Error ); |
e0ec6e79 | 574 | } |
790e7c1b BH |
575 | } |
576 | ||
577 | ||
578 | ||
cf8c91f3 | 579 | bool OdbxBackend::superMasterBackend( const string& ip, const DNSName& domain, const vector<DNSResourceRecord>& set, string *nameserver, string* account, DNSBackend** ddb ) |
790e7c1b | 580 | { |
e0ec6e79 BH |
581 | try |
582 | { | |
e6a9dde5 | 583 | DLOG( g_log.log( m_myname + " superMasterBackend()", Logger::Debug ) ); |
e0ec6e79 BH |
584 | |
585 | if( account != NULL && ddb != NULL ) | |
586 | { | |
587 | vector<DNSResourceRecord>::const_iterator i; | |
588 | ||
589 | for( i = set.begin(); i != set.end(); i++ ) | |
590 | { | |
591 | string stmt = getArg( "sql-supermaster" ); | |
592 | string& stmtref = strbind( ":ip", escape( ip, READ ), stmt ); | |
593 | stmtref = strbind( ":ns", escape( i->content, READ ), stmtref ); | |
594 | ||
595 | if( !execStmt( stmtref.c_str(), stmtref.size(), READ ) ) { return false; } | |
596 | ||
597 | if( getRecord( READ ) ) | |
598 | { | |
599 | if( odbx_field_value( m_result, 0 ) != NULL ) | |
600 | { | |
601 | *account = string( odbx_field_value( m_result, 0 ), odbx_field_length( m_result, 0 ) ); | |
602 | } | |
603 | ||
604 | while( getRecord( READ ) ); | |
605 | ||
606 | *ddb=this; | |
607 | return true; | |
608 | } | |
609 | } | |
610 | } | |
611 | } | |
a2f4c096 | 612 | catch ( std::exception& e ) |
e0ec6e79 | 613 | { |
e6a9dde5 | 614 | g_log.log( m_myname + " superMasterBackend: Caught STL exception - " + e.what(), Logger::Error ); |
e0ec6e79 BH |
615 | return false; |
616 | } | |
617 | ||
618 | return false; | |
790e7c1b BH |
619 | } |
620 | ||
621 | ||
622 | ||
cf8c91f3 | 623 | bool OdbxBackend::createSlaveDomain( const string& ip, const DNSName& domain, const string &nameserver, const string& account ) |
790e7c1b | 624 | { |
e0ec6e79 BH |
625 | try |
626 | { | |
e6a9dde5 | 627 | DLOG( g_log.log( m_myname + " createSlaveDomain()", Logger::Debug ) ); |
e0ec6e79 BH |
628 | |
629 | if( !m_handle[WRITE] && !connectTo( m_hosts[WRITE], WRITE ) ) | |
630 | { | |
e6a9dde5 | 631 | g_log.log( m_myname + " createSlaveDomain: Master server is unreachable", Logger::Error ); |
e0ec6e79 BH |
632 | return false; |
633 | } | |
634 | ||
cf8c91f3 | 635 | int len = snprintf( m_buffer, sizeof( m_buffer ) - 1, getArg( "sql-insert-slave" ).c_str(), escape( domain.makeLowerCase().toStringRootDot(), WRITE ).c_str(), |
e0ec6e79 BH |
636 | escape( ip, WRITE ).c_str(), escape( account, WRITE ).c_str() ); |
637 | ||
638 | if( len < 0 ) | |
639 | { | |
e6a9dde5 | 640 | g_log.log( m_myname + " createSlaveDomain: Unable to insert values in statement '" + getArg( "sql-insert-slave" ) + "' - format error", Logger::Error ); |
e0ec6e79 BH |
641 | return false; |
642 | } | |
643 | ||
579c61f5 | 644 | if( len > static_cast<int>(sizeof( m_buffer )) - 1 ) |
e0ec6e79 | 645 | { |
e6a9dde5 | 646 | g_log.log( m_myname + " createSlaveDomain: Unable to insert values in statement '" + getArg( "sql-insert-slave" ) + "' - insufficient buffer space", Logger::Error ); |
e0ec6e79 BH |
647 | return false; |
648 | } | |
649 | ||
650 | if( !execStmt( m_buffer, len, WRITE ) ) { return false; } | |
651 | } | |
a2f4c096 | 652 | catch ( std::exception& e ) |
e0ec6e79 | 653 | { |
e6a9dde5 | 654 | g_log.log( m_myname + " createSlaveDomain: Caught STL exception - " + e.what(), Logger::Error ); |
e0ec6e79 BH |
655 | return false; |
656 | } | |
657 | ||
658 | return true; | |
790e7c1b BH |
659 | } |
660 | ||
661 | ||
662 | ||
d57d7155 | 663 | bool OdbxBackend::feedRecord( const DNSResourceRecord& rr, const DNSName& ordername ) |
790e7c1b | 664 | { |
e0ec6e79 BH |
665 | try |
666 | { | |
e6a9dde5 | 667 | DLOG( g_log.log( m_myname + " feedRecord()", Logger::Debug ) ); |
e0ec6e79 BH |
668 | |
669 | if( !m_handle[WRITE] && !connectTo( m_hosts[WRITE], WRITE ) ) | |
670 | { | |
e6a9dde5 | 671 | g_log.log( m_myname + " feedRecord: Master server is unreachable", Logger::Error ); |
e0ec6e79 BH |
672 | return false; |
673 | } | |
674 | ||
21df0d27 | 675 | unsigned int priority=0; |
b9bafae0 KM |
676 | string content(rr.content); |
677 | ||
678 | if(rr.qtype == QType::MX || rr.qtype == QType::SRV) { | |
21df0d27 | 679 | priority=pdns_stou(content); |
b9bafae0 KM |
680 | string::size_type pos = content.find_first_not_of("0123456789"); |
681 | if(pos != string::npos) | |
682 | boost::erase_head(content, pos); | |
683 | trim_left(content); | |
684 | } | |
685 | ||
90e286b7 | 686 | int len = snprintf( m_buffer, sizeof( m_buffer ) - 1, getArg( "sql-insert-record" ).c_str(), rr.domain_id, |
cf8c91f3 | 687 | escape( rr.qname.makeLowerCase().toStringRootDot(), WRITE ).c_str(), rr.qtype.getName().c_str(), rr.ttl, priority, |
b9bafae0 | 688 | escape( content, WRITE ).c_str() ); |
e0ec6e79 BH |
689 | |
690 | if( len < 0 ) | |
691 | { | |
e6a9dde5 | 692 | g_log.log( m_myname + " feedRecord: Unable to insert values in statement '" + getArg( "sql-insert-record" ) + "' - format error", Logger::Error ); |
e0ec6e79 BH |
693 | return false; |
694 | } | |
695 | ||
579c61f5 | 696 | if( len > static_cast<int>(sizeof( m_buffer )) - 1 ) |
e0ec6e79 | 697 | { |
e6a9dde5 | 698 | g_log.log( m_myname + " feedRecord: Unable to insert values in statement '" + getArg( "sql-insert-record" ) + "' - insufficient buffer space", Logger::Error ); |
e0ec6e79 BH |
699 | return false; |
700 | } | |
701 | ||
702 | if( !execStmt( m_buffer, len, WRITE ) ) { return false; } | |
703 | } | |
a2f4c096 | 704 | catch ( std::exception& e ) |
e0ec6e79 | 705 | { |
e6a9dde5 | 706 | g_log.log( m_myname + " feedRecord: Caught STL exception - " + e.what(), Logger::Error ); |
e0ec6e79 BH |
707 | return false; |
708 | } | |
709 | ||
710 | return true; | |
790e7c1b BH |
711 | } |
712 | ||
713 | ||
714 | ||
cf8c91f3 | 715 | bool OdbxBackend::startTransaction( const DNSName& domain, int zoneid ) |
790e7c1b | 716 | { |
e0ec6e79 BH |
717 | try |
718 | { | |
e6a9dde5 | 719 | DLOG( g_log.log( m_myname + " startTransaction()", Logger::Debug ) ); |
790e7c1b | 720 | |
e0ec6e79 BH |
721 | if( !m_handle[WRITE] && !connectTo( m_hosts[WRITE], WRITE ) ) |
722 | { | |
e6a9dde5 | 723 | g_log.log( m_myname + " startTransaction: Master server is unreachable", Logger::Error ); |
e0ec6e79 BH |
724 | return false; |
725 | } | |
8e20e603 | 726 | |
cf8c91f3 KM |
727 | string stmtref = getArg( "sql-transactbegin" ); |
728 | if( !execStmt( stmtref.c_str(), stmtref.size(), WRITE ) ) { return false; } | |
90e286b7 | 729 | int len = snprintf( m_buffer, sizeof( m_buffer ) - 1, "%d", zoneid ); |
e0ec6e79 BH |
730 | |
731 | if( len < 0 ) | |
732 | { | |
e6a9dde5 | 733 | g_log.log( m_myname + " startTransaction: Unable to convert zone id to string - format error", Logger::Error ); |
e0ec6e79 BH |
734 | return false; |
735 | } | |
736 | ||
579c61f5 | 737 | if( len > static_cast<int>(sizeof( m_buffer )) - 1 ) |
e0ec6e79 | 738 | { |
e6a9dde5 | 739 | g_log.log( m_myname + " startTransaction: Unable to convert zone id to string - insufficient buffer space", Logger::Error ); |
e0ec6e79 BH |
740 | return false; |
741 | } | |
742 | ||
340a213e | 743 | if(zoneid >= 0) { |
cf8c91f3 KM |
744 | string stmt = getArg( "sql-zonedelete" ); |
745 | stmtref = strbind( ":id", string( m_buffer, len ), stmt ); | |
746 | if( !execStmt( stmtref.c_str(), stmtref.size(), WRITE ) ) { return false; } | |
340a213e | 747 | } |
e0ec6e79 | 748 | } |
a2f4c096 | 749 | catch ( std::exception& e ) |
e0ec6e79 | 750 | { |
e6a9dde5 | 751 | g_log.log( m_myname + " startTransaction: Caught STL exception - " + e.what(), Logger::Error ); |
e0ec6e79 BH |
752 | return false; |
753 | } | |
754 | ||
755 | return true; | |
790e7c1b BH |
756 | } |
757 | ||
758 | ||
759 | ||
760 | bool OdbxBackend::commitTransaction() | |
761 | { | |
e0ec6e79 BH |
762 | try |
763 | { | |
e6a9dde5 | 764 | DLOG( g_log.log( m_myname + " commitTransaction()", Logger::Debug ) ); |
e0ec6e79 BH |
765 | |
766 | if( !m_handle[WRITE] && !connectTo( m_hosts[WRITE], WRITE ) ) | |
767 | { | |
e6a9dde5 | 768 | g_log.log( m_myname + " commitTransaction: Master server is unreachable", Logger::Error ); |
e0ec6e79 BH |
769 | return false; |
770 | } | |
771 | ||
772 | const string& stmt = getArg( "sql-transactend" ); | |
773 | if( !execStmt( stmt.c_str(), stmt.size(), WRITE ) ) { return false; } | |
774 | } | |
a2f4c096 | 775 | catch ( std::exception& e ) |
e0ec6e79 | 776 | { |
e6a9dde5 | 777 | g_log.log( m_myname + " commitTransaction: Caught STL exception - " + e.what(), Logger::Error ); |
e0ec6e79 BH |
778 | return false; |
779 | } | |
780 | ||
781 | return true; | |
790e7c1b BH |
782 | } |
783 | ||
784 | ||
785 | ||
786 | bool OdbxBackend::abortTransaction() | |
787 | { | |
e0ec6e79 BH |
788 | try |
789 | { | |
e6a9dde5 | 790 | DLOG( g_log.log( m_myname + " abortTransaction()", Logger::Debug ) ); |
e0ec6e79 BH |
791 | |
792 | if( !m_handle[WRITE] && !connectTo( m_hosts[WRITE], WRITE ) ) | |
793 | { | |
e6a9dde5 | 794 | g_log.log( m_myname + " abortTransaction: Master server is unreachable", Logger::Error ); |
e0ec6e79 BH |
795 | return false; |
796 | } | |
797 | ||
798 | const string& stmt = getArg( "sql-transactabort" ); | |
799 | if( !execStmt( stmt.c_str(), stmt.size(), WRITE ) ) { return false; } | |
800 | } | |
a2f4c096 | 801 | catch ( std::exception& e ) |
e0ec6e79 | 802 | { |
e6a9dde5 | 803 | g_log.log( m_myname + " abortTransaction: Caught STL exception - " + e.what(), Logger::Error ); |
e0ec6e79 BH |
804 | return false; |
805 | } | |
806 | ||
807 | return true; | |
790e7c1b | 808 | } |