]> git.ipfire.org Git - thirdparty/pdns.git/blame - modules/oraclebackend/oraclebackend.cc
Logging: have a global g_log
[thirdparty/pdns.git] / modules / oraclebackend / oraclebackend.cc
CommitLineData
765f22c6 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 Maik Zumstrull
5 *
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.
765f22c6 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.
765f22c6 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.
18 *
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.
765f22c6 22 */
870a0fe4
AT
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
ae4e0030 26#include <string>
03fc70cf 27#include <stdexcept>
ae4e0030 28
917a9be8 29#include "pdns/namespaces.hh"
ae4e0030 30
765f22c6
BH
31#include "pdns/dns.hh"
32#include "pdns/dnsbackend.hh"
ae4e0030 33#include "oraclebackend.hh"
765f22c6
BH
34#include "pdns/logger.hh"
35#include "pdns/arguments.hh"
36#include "pdns/lock.hh"
ae4e0030
BH
37
38#include <oci.h>
39
765f22c6 40static const char *basicQueryKey = "PDNS_Basic_Query";
71301b6e 41static const char *basicQueryDefaultAuthSQL =
765f22c6
BH
42 "SELECT fqdn, ttl, type, content, zone_id, last_change, auth "
43 "FROM Records "
44 "WHERE type = :type AND fqdn = lower(:name)";
45
71301b6e
PD
46static const char *basicQueryDefaultSQL = "SELECT fqdn, ttl, type, content, zone_id, last_change "
47 "FROM Records "
48 "WHERE type = :type AND fqdn = lower(:name)";
49
765f22c6 50static const char *basicIdQueryKey = "PDNS_Basic_Id_Query";
71301b6e 51static const char *basicIdQueryDefaultAuthSQL =
765f22c6
BH
52 "SELECT fqdn, ttl, type, content, zone_id, last_change, auth "
53 "FROM Records "
54 "WHERE type = :type AND fqdn = lower(:name) AND zone_id = :zoneid";
55
71301b6e
PD
56static const char *basicIdQueryDefaultSQL =
57 "SELECT fqdn, ttl, type, content, zone_id, last_change "
58 "FROM Records "
59 "WHERE type = :type AND fqdn = lower(:name) AND zone_id = :zoneid";
60
765f22c6 61static const char *anyQueryKey = "PDNS_ANY_Query";
71301b6e 62static const char *anyQueryDefaultAuthSQL =
765f22c6
BH
63 "SELECT fqdn, ttl, type, content, zone_id, last_change, auth "
64 "FROM Records "
03fc70cf
BH
65 "WHERE fqdn = lower(:name)"
66 " AND type IS NOT NULL "
67 "ORDER BY type";
765f22c6 68
71301b6e
PD
69static const char *anyQueryDefaultSQL =
70 "SELECT fqdn, ttl, type, content, zone_id, last_change "
71 "FROM Records "
72 "WHERE fqdn = lower(:name)"
73 " AND type IS NOT NULL "
74 "ORDER BY type";
75
765f22c6 76static const char *anyIdQueryKey = "PDNS_ANY_Id_Query";
71301b6e 77static const char *anyIdQueryDefaultAuthSQL =
765f22c6
BH
78 "SELECT fqdn, ttl, type, content, zone_id, last_change, auth "
79 "FROM Records "
03fc70cf
BH
80 "WHERE fqdn = lower(:name)"
81 " AND zone_id = :zoneid"
82 " AND type IS NOT NULL "
83 "ORDER BY type";
765f22c6 84
71301b6e
PD
85static const char *anyIdQueryDefaultSQL =
86 "SELECT fqdn, ttl, type, content, zone_id, last_change "
87 "FROM Records "
88 "WHERE fqdn = lower(:name)"
89 " AND zone_id = :zoneid"
90 " AND type IS NOT NULL "
91 "ORDER BY type";
92
93
765f22c6 94static const char *listQueryKey = "PDNS_List_Query";
71301b6e 95static const char *listQueryDefaultAuthSQL =
765f22c6
BH
96 "SELECT fqdn, ttl, type, content, zone_id, last_change, auth "
97 "FROM Records "
03fc70cf
BH
98 "WHERE zone_id = :zoneid"
99 " AND type IS NOT NULL "
100 "ORDER BY fqdn, type";
765f22c6 101
71301b6e
PD
102static const char *listQueryDefaultSQL =
103 "SELECT fqdn, ttl, type, content, zone_id, last_change "
104 "FROM Records "
105 "WHERE zone_id = :zoneid"
106 " AND type IS NOT NULL "
107 "ORDER BY fqdn, type";
108
109
765f22c6
BH
110static const char *zoneInfoQueryKey = "PDNS_Zone_Info_Query";
111static const char *zoneInfoQueryDefaultSQL =
112 "SELECT id, name, type, last_check, serial, notified_serial "
113 "FROM Zones "
114 "WHERE name = lower(:name)";
115
116static const char *alsoNotifyQueryKey = "PDNS_Also_Notify_Query";
117static const char *alsoNotifyQueryDefaultSQL =
118 "SELECT an.hostaddr "
119 "FROM Zones z JOIN ZoneAlsoNotify an ON z.id = an.zone_id "
120 "WHERE z.name = lower(:name)";
121
765f22c6
BH
122static const char *zoneMastersQueryKey = "PDNS_Zone_Masters_Query";
123static const char *zoneMastersQueryDefaultSQL =
124 "SELECT master "
125 "FROM Zonemasters "
126 "WHERE zone_id = :zoneid";
127
128static const char *isZoneMasterQueryKey = "PDNS_Is_Zone_Master_Query";
129static const char *isZoneMasterQueryDefaultSQL =
130 "SELECT zm.master "
131 "FROM Zones z JOIN Zonemasters zm ON z.id = zm.zone_id "
132 "WHERE z.name = lower(:name) AND zm.master = :master";
133
134static const char *deleteZoneQueryKey = "PDNS_Delete_Zone_Query";
135static const char *deleteZoneQueryDefaultSQL =
136 "DELETE FROM Records WHERE zone_id = :zoneid";
137
138static const char *zoneSetLastCheckQueryKey = "PDNS_Zone_Set_Last_Check_Query";
139static const char *zoneSetLastCheckQueryDefaultSQL =
140 "UPDATE Zones SET last_check = :lastcheck WHERE id = :zoneid";
141
142static const char *zoneSetNotifiedSerialQueryKey = "PDNS_Zone_Set_NSerial_Query";
143static const char *zoneSetNotifiedSerialQueryDefaultSQL =
144 "UPDATE Zones SET notified_serial = :serial WHERE id = :zoneid";
145
146static const char *insertRecordQueryKey = "PDNS_Insert_Record_Query";
147static const char *insertRecordQueryDefaultSQL =
03fc70cf
BH
148 "INSERT INTO Records (id, fqdn, zone_id, ttl, type, content) "
149 "VALUES (records_id_seq.NEXTVAL, lower(:name), :zoneid, :ttl, :type, :content)";
150
151static const char *finalizeAXFRQueryKey = "PDNS_Finalize_AXFR";
152static const char *finalizeAXFRQueryDefaultSQL =
153 "DECLARE\n"
154 " zone_id INTEGER := :zoneid;\n"
155 "BEGIN\n"
156 " NULL;\n"
157 "END;";
765f22c6
BH
158
159static const char *unfreshZonesQueryKey = "PDNS_Unfresh_Zones_Query";
160static const char *unfreshZonesQueryDefaultSQL =
161 "SELECT z.id, z.name, z.last_check, z.serial, zm.master "
162 "FROM Zones z JOIN Zonemasters zm ON z.id = zm.zone_id "
163 "WHERE z.type = 'SLAVE' "
164 " AND (z.last_check IS NULL OR z.last_check + z.refresh < :ts)"
165 "ORDER BY z.id";
166
167static const char *updatedMastersQueryKey = "PDNS_Updated_Masters_Query";
168static const char *updatedMastersQueryDefaultSQL =
169 "SELECT id, name, serial, notified_serial "
170 "FROM Zones "
171 "WHERE type = 'MASTER' "
172 "AND (notified_serial IS NULL OR notified_serial < serial)";
173
174static const char *acceptSupernotificationQueryKey = "PDNS_Accept_Supernotification_Query";
175static const char *acceptSupernotificationQueryDefaultSQL =
176 "SELECT name "
177 "FROM Supermasters "
178 "WHERE ip = :ip AND nameserver = lower(:ns)";
179
180static const char *insertSlaveQueryKey = "PDNS_Insert_Slave_Query";
181static const char *insertSlaveQueryDefaultSQL =
182 "INSERT INTO Zones (id, name, type) "
183 "VALUES (zones_id_seq.NEXTVAL, lower(:zone), 'SLAVE') "
184 "RETURNING id INTO :zoneid";
185
186static const char *insertMasterQueryKey = "PDNS_Insert_Master_Query";
187static const char *insertMasterQueryDefaultSQL =
188 "INSERT INTO Zonemasters (zone_id, master) "
189 "VALUES (:zoneid, :ip)";
190
191static const char *prevNextNameQueryKey = "PDNS_Prev_Next_Name_Query";
192static const char *prevNextNameQueryDefaultSQL =
193 "BEGIN\n"
194 " get_canonical_prev_next(:zoneid, :name, :prev, :next);\n"
195 "END;";
196
197static const char *prevNextHashQueryKey = "PDNS_Prev_Next_Hash_Query";
198static const char *prevNextHashQueryDefaultSQL =
199 "BEGIN\n"
200 " get_hashed_prev_next(:zoneid, :hash, :unhashed, :prev, :next);\n"
201 "END;";
202
16534364
AT
203static const char *getAllZoneMetadataQueryKey = "PDNS_Get_All_Zone_Metadata";
204static const char *getAllZoneMetadataQueryDefaultSQL =
cdbf24f6 205 "SELECT md.meta_type, md.meta_content "
16534364 206 "FROM Zones z JOIN ZoneMetadata md ON z.id = md.zone_id "
cdbf24f6 207 "WHERE z.name = lower(:name) "
16534364
AT
208 "ORDER BY md.meta_ind";
209
765f22c6
BH
210static const char *getZoneMetadataQueryKey = "PDNS_Get_Zone_Metadata";
211static const char *getZoneMetadataQueryDefaultSQL =
212 "SELECT md.meta_content "
213 "FROM Zones z JOIN ZoneMetadata md ON z.id = md.zone_id "
214 "WHERE z.name = lower(:name) AND md.meta_type = :kind "
215 "ORDER BY md.meta_ind";
216
217static const char *delZoneMetadataQueryKey = "PDNS_Del_Zone_Metadata";
218static const char *delZoneMetadataQueryDefaultSQL =
219 "DELETE FROM ZoneMetadata md "
220 "WHERE zone_id = (SELECT id FROM Zones z WHERE z.name = lower(:name)) "
221 " AND md.meta_type = :kind";
222
223static const char *setZoneMetadataQueryKey = "PDNS_Set_Zone_Metadata";
224static const char *setZoneMetadataQueryDefaultSQL =
225 "INSERT INTO ZoneMetadata (zone_id, meta_type, meta_ind, meta_content) "
226 "VALUES ("
227 " (SELECT id FROM Zones WHERE name = lower(:name)),"
228 " :kind, :i, :content"
229 ")";
230
03fc70cf
BH
231static const char *getTSIGKeyQueryKey = "PDNS_Get_TSIG_Key";
232static const char *getTSIGKeyQueryDefaultSQL =
233 "SELECT algorithm, secret "
234 "FROM TSIGKeys "
235 "WHERE name = :name";
236
672d2e89
KM
237static const char *delTSIGKeyQueryKey = "PDNS_Del_TSIG_Key";
238static const char *delTSIGKeyQueryDefaultSQL =
239 "DELETE FROM TSIGKeys "
240 "WHERE name = :name";
241
242static const char *setTSIGKeyQueryKey = "PDNS_Set_TSIG_Key";
243static const char *setTSIGKeyQueryDefaultSQL =
47541c8a
KM
244 "INSERT INTO TSIGKeys (name, algorithm, secret) "
245 "VALUES (:name, :algorithm, :secret)";
672d2e89
KM
246
247static const char *getTSIGKeysQueryKey = "PDNS_Get_TSIG_Keys";
248static const char *getTSIGKeysQueryDefaultSQL =
249 "SELECT name, algorithm, secret "
250 "FROM TSIGKeys";
251
765f22c6
BH
252static const char *getZoneKeysQueryKey = "PDNS_Get_Zone_Keys";
253static const char *getZoneKeysQueryDefaultSQL =
254 "SELECT k.id, k.flags, k.active, k.keydata "
255 "FROM ZoneDNSKeys k JOIN Zones z ON z.id = k.zone_id "
256 "WHERE z.name = lower(:name)";
257
258static const char *delZoneKeyQueryKey = "PDNS_Del_Zone_Key";
259static const char *delZoneKeyQueryDefaultSQL =
260 "DELETE FROM ZoneDNSKeys WHERE id = :keyid";
261
262static const char *addZoneKeyQueryKey = "PDNS_Add_Zone_Key";
263static const char *addZoneKeyQueryDefaultSQL =
264 "INSERT INTO ZoneDNSKeys (id, zone_id, flags, active, keydata) "
265 "VALUES ("
266 " zonednskeys_id_seq.NEXTVAL,"
267 " (SELECT id FROM Zones WHERE name = lower(:name)),"
268 " :flags,"
269 " :active,"
270 " :content"
271 ") RETURNING id INTO :keyid";
272
273static const char *setZoneKeyStateQueryKey = "PDNS_Set_Zone_Key_State";
274static const char *setZoneKeyStateQueryDefaultSQL =
275 "UPDATE ZoneDNSKeys SET active = :active WHERE id = :keyid";
276
277
278static void
279string_to_cbuf (char *buf, const string& s, size_t bufsize)
ae4e0030 280{
03fc70cf
BH
281 if (s.size() >= bufsize) {
282 throw std::overflow_error("OracleBackend: string does not fit into char buffer");
765f22c6 283 }
765f22c6
BH
284 strncpy(buf, s.c_str(), bufsize);
285}
ae4e0030 286
e2b3f850
KM
287static void
288DNSName_to_cbuf (char *buf, const DNSName& n, size_t bufsize)
289{
290 string s = toLower(n.toStringNoDot());
291 if (s.size() >= bufsize) {
292 throw std::overflow_error("OracleBackend: DNSName does not fit into char buffer");
293 }
294 strncpy(buf, s.c_str(), bufsize);
295}
296
765f22c6
BH
297OracleBackend::OracleBackend (const string &suffix, OCIEnv *envh,
298 char *poolname)
299{
300 setArgPrefix(string("oracle") + suffix);
301 sword err;
302
303 // Initialize everything in a known state
03fc70cf
BH
304 oraenv = envh;
305 oraerr = NULL;
306 pooledSvcCtx = NULL;
307 masterAuthHandle = NULL;
308 masterSvcCtx = NULL;
765f22c6 309 curStmtHandle = NULL;
03fc70cf 310 openTransactionZoneID = -1;
765f22c6 311
71301b6e
PD
312 try
313 {
314 d_dnssecQueries = mustDo("dnssec");
315 }
316 catch (ArgException e)
317 {
318 d_dnssecQueries = false;
319 }
320
765f22c6
BH
321 // Process configuration options
322 string_to_cbuf(myServerName, getArg("nameserver-name"), sizeof(myServerName));
71301b6e
PD
323
324 if (d_dnssecQueries) {
325 basicQuerySQL = getArg("basic-query-auth");
326 basicIdQuerySQL = getArg("basic-id-query-auth");
327 anyQuerySQL = getArg("any-query-auth");
328 anyIdQuerySQL = getArg("any-id-query-auth");
329 listQuerySQL = getArg("list-query-auth");
330 } else {
331 basicQuerySQL = getArg("basic-query");
332 basicIdQuerySQL = getArg("basic-id-query");
333 anyQuerySQL = getArg("any-query");
334 anyIdQuerySQL = getArg("any-id-query");
335 listQuerySQL = getArg("list-query");
336 }
337
765f22c6
BH
338 zoneInfoQuerySQL = getArg("zone-info-query");
339 alsoNotifyQuerySQL = getArg("also-notify-query");
765f22c6
BH
340 zoneMastersQuerySQL = getArg("zone-masters-query");
341 isZoneMasterQuerySQL = getArg("is-zone-master-query");
342 deleteZoneQuerySQL = getArg("delete-zone-query");
343 zoneSetLastCheckQuerySQL = getArg("zone-set-last-check-query");
344 insertRecordQuerySQL = getArg("insert-record-query");
03fc70cf 345 finalizeAXFRQuerySQL = getArg("finalize-axfr-query");
765f22c6
BH
346 unfreshZonesQuerySQL = getArg("unfresh-zones-query");
347 updatedMastersQuerySQL = getArg("updated-masters-query");
348 acceptSupernotificationQuerySQL = getArg("accept-supernotification-query");
349 insertSlaveQuerySQL = getArg("insert-slave-query");
350 insertMasterQuerySQL = getArg("insert-master-query");
351 zoneSetNotifiedSerialQuerySQL = getArg("zone-set-notified-serial-query");
352 prevNextNameQuerySQL = getArg("prev-next-name-query");
353 prevNextHashQuerySQL = getArg("prev-next-hash-query");
cdbf24f6 354 getAllZoneMetadataQuerySQL = getArg("get-all-zone-metadata-query");
765f22c6
BH
355 getZoneMetadataQuerySQL = getArg("get-zone-metadata-query");
356 delZoneMetadataQuerySQL = getArg("del-zone-metadata-query");
357 setZoneMetadataQuerySQL = getArg("set-zone-metadata-query");
03fc70cf 358 getTSIGKeyQuerySQL = getArg("get-tsig-key-query");
672d2e89 359 delTSIGKeyQuerySQL = getArg("del-tsig-key-query");
911c3aa7 360 setTSIGKeyQuerySQL = getArg("set-tsig-key-query");
911c3aa7 361 getTSIGKeysQuerySQL = getArg("get-tsig-keys-query");
765f22c6
BH
362 getZoneKeysQuerySQL = getArg("get-zone-keys-query");
363 delZoneKeyQuerySQL = getArg("del-zone-key-query");
364 addZoneKeyQuerySQL = getArg("add-zone-key-query");
365 setZoneKeyStateQuerySQL = getArg("set-zone-key-state-query");
366
367 // Allocate an error handle
03fc70cf 368 err = OCIHandleAlloc(oraenv, (void**) &oraerr,
765f22c6
BH
369 OCI_HTYPE_ERROR, 0, NULL);
370 if (err == OCI_ERROR) {
371 throw OracleException("OCIHandleAlloc");
372 }
373
374 // Logon to the database
03fc70cf 375 err = OCISessionGet(oraenv, oraerr, &pooledSvcCtx, NULL, (OraText*) poolname, strlen(poolname), NULL, 0, NULL, NULL, NULL, OCI_SESSGET_SPOOL);
765f22c6
BH
376
377 if (err == OCI_ERROR) {
03fc70cf
BH
378 throw OracleException("Opening Oracle session", oraerr);
379 }
380}
381
382void
383OracleBackend::openMasterConnection ()
384{
385 sword err;
386
387 if (masterSvcCtx == NULL) {
388 err = OCIHandleAlloc(oraenv, (void**) &masterAuthHandle, OCI_HTYPE_AUTHINFO, 0, NULL);
389 if (err == OCI_ERROR) {
390 throw OracleException("openMasterConnection: allocating auth handle");
391 }
392
393 string database = getArg("master-database");
394 string username = getArg("master-username");
395 string password = getArg("master-password");
396
397 err = OCIAttrSet(masterAuthHandle, OCI_HTYPE_AUTHINFO, (void*)username.c_str(), username.size(), OCI_ATTR_USERNAME, oraerr);
398 if (err == OCI_ERROR) {
399 throw OracleException("openMasterConnection: setting username");
400 }
401
402 err = OCIAttrSet(masterAuthHandle, OCI_HTYPE_AUTHINFO, (void*)password.c_str(), password.size(), OCI_ATTR_PASSWORD, oraerr);
403 if (err == OCI_ERROR) {
404 throw OracleException("openMasterConnection: setting password");
405 }
406
407 err = OCISessionGet(oraenv, oraerr, &masterSvcCtx, masterAuthHandle,
408 (OraText*)database.c_str(), database.size(),
409 NULL, 0, NULL, NULL, NULL, OCI_SESSGET_STMTCACHE);
410 if (err == OCI_ERROR) {
411 throw OracleException("openMasterConnection OCISessionGet");
412 }
413 }
765f22c6 414}
ae4e0030 415
765f22c6
BH
416OracleBackend::~OracleBackend ()
417{
418 Cleanup();
419}
ae4e0030 420
765f22c6 421void
ea9586a4 422OracleBackend::lookup (const QType &qtype, const DNSName& qname,
765f22c6
BH
423 DNSPacket *p, int zoneId)
424{
03fc70cf
BH
425 sword rc;
426
765f22c6
BH
427 if (qtype.getCode() != QType::ANY) {
428 if (zoneId < 0) {
03fc70cf
BH
429 if (curStmtHandle != NULL) throw OracleException("Invalid state");
430 curStmtHandle = prepare_query(pooledSvcCtx, basicQuerySQL, basicQueryKey);
431 curStmtKey = basicQueryKey;
432 define_fwd_query(curStmtHandle);
433 bind_str_failokay(curStmtHandle, ":nsname", myServerName, sizeof(myServerName));
434 bind_str(curStmtHandle, ":name", mQueryName, sizeof(mQueryName));
435 bind_str(curStmtHandle, ":type", mQueryType, sizeof(mQueryType));
765f22c6 436 } else {
03fc70cf
BH
437 if (curStmtHandle != NULL) throw OracleException("Invalid state");
438 curStmtHandle = prepare_query(pooledSvcCtx, basicIdQuerySQL, basicIdQueryKey);
439 curStmtKey = basicIdQueryKey;
440 define_fwd_query(curStmtHandle);
441 bind_str_failokay(curStmtHandle, ":nsname", myServerName, sizeof(myServerName));
442 bind_str(curStmtHandle, ":name", mQueryName, sizeof(mQueryName));
443 bind_str(curStmtHandle, ":type", mQueryType, sizeof(mQueryType));
444 bind_int(curStmtHandle, ":zoneid", &mQueryZoneId);
765f22c6
BH
445 }
446 } else {
447 if (zoneId < 0) {
03fc70cf
BH
448 if (curStmtHandle != NULL) throw OracleException("Invalid state");
449 curStmtHandle = prepare_query(pooledSvcCtx, anyQuerySQL, anyQueryKey);
450 curStmtKey = anyQueryKey;
451 define_fwd_query(curStmtHandle);
452 bind_str_failokay(curStmtHandle, ":nsname", myServerName, sizeof(myServerName));
453 bind_str(curStmtHandle, ":name", mQueryName, sizeof(mQueryName));
765f22c6 454 } else {
03fc70cf
BH
455 if (curStmtHandle != NULL) throw OracleException("Invalid state");
456 curStmtHandle = prepare_query(pooledSvcCtx, anyIdQuerySQL, anyIdQueryKey);
457 curStmtKey = anyIdQueryKey;
458 define_fwd_query(curStmtHandle);
459 bind_str_failokay(curStmtHandle, ":nsname", myServerName, sizeof(myServerName));
460 bind_str(curStmtHandle, ":name", mQueryName, sizeof(mQueryName));
461 bind_int(curStmtHandle, ":zoneid", &mQueryZoneId);
765f22c6
BH
462 }
463 }
ae4e0030 464
e2b3f850 465 DNSName_to_cbuf(mQueryName, qname, sizeof(mQueryName));
765f22c6
BH
466 string_to_cbuf(mQueryType, qtype.getName(), sizeof(mQueryType));
467 mQueryZoneId = zoneId;
ae4e0030 468
03fc70cf
BH
469 rc = OCIStmtExecute(pooledSvcCtx, curStmtHandle, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
470
471 if (rc == OCI_ERROR) {
472 throw OracleException("Oracle Lookup", oraerr);
473 }
ae4e0030 474
03fc70cf
BH
475 if (rc == OCI_NO_DATA) {
476 release_query(curStmtHandle, curStmtKey);
477 curStmtHandle = NULL;
765f22c6
BH
478 }
479}
ae4e0030 480
765f22c6
BH
481bool
482OracleBackend::getBeforeAndAfterNames (
ea9586a4
AT
483 uint32_t zoneId, const DNSName& zone,
484 const DNSName& name, DNSName& before, DNSName& after)
765f22c6 485{
71301b6e
PD
486 if(!d_dnssecQueries)
487 return -1;
488
03fc70cf
BH
489 sword rc;
490 OCIStmt *stmt;
491
765f22c6
BH
492 (void)zone;
493
03fc70cf
BH
494 stmt = prepare_query(pooledSvcCtx, prevNextNameQuerySQL, prevNextNameQueryKey);
495 bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName));
496 bind_str(stmt, ":name", mQueryName, sizeof(mQueryName));
497 bind_str_ind(stmt, ":prev", mResultPrevName, sizeof(mResultPrevName), &mResultPrevNameInd);
498 bind_str_ind(stmt, ":next", mResultNextName, sizeof(mResultNextName), &mResultNextNameInd);
499 bind_uint32(stmt, ":zoneid", &zoneId);
e2b3f850 500 DNSName_to_cbuf(mQueryName, name, sizeof(mQueryName));
765f22c6
BH
501 mResultPrevNameInd = -1;
502 mResultNextNameInd = -1;
503
03fc70cf 504 rc = OCIStmtExecute(pooledSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
765f22c6 505
03fc70cf 506 if (rc == OCI_ERROR) {
765f22c6 507 throw OracleException(
03fc70cf 508 "Oracle getBeforeAndAfterNames", oraerr
765f22c6
BH
509 );
510 }
511
512 check_indicator(mResultPrevNameInd, false);
513 check_indicator(mResultNextNameInd, false);
514
e3de6828
KM
515 before = DNSName(mResultPrevName);
516 after = DNSName(mResultNextName);
765f22c6 517
03fc70cf 518 release_query(stmt, prevNextNameQueryKey);
765f22c6
BH
519 return true;
520}
521
522bool
523OracleBackend::getBeforeAndAfterNamesAbsolute(uint32_t zoneId,
ab0fbe56 524 const DNSName& name, DNSName& unhashed, DNSName& before, DNSName& after)
765f22c6 525{
71301b6e
PD
526 if(!d_dnssecQueries)
527 return -1;
528
03fc70cf
BH
529 sword rc;
530 OCIStmt *stmt;
531
532 stmt = prepare_query(pooledSvcCtx, prevNextHashQuerySQL, prevNextHashQueryKey);
533 bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName));
534 bind_str(stmt, ":hash", mQueryName, sizeof(mQueryName));
535 bind_str_ind(stmt, ":unhashed", mResultName, sizeof(mResultName), &mResultNameInd);
536 bind_str_ind(stmt, ":prev", mResultPrevName, sizeof(mResultPrevName), &mResultPrevNameInd);
537 bind_str_ind(stmt, ":next", mResultNextName, sizeof(mResultNextName), &mResultNextNameInd);
538 bind_uint32(stmt, ":zoneid", &zoneId);
ab0fbe56 539 string_to_cbuf(mQueryName, name.labelReverse().toString(" ", false)), sizeof(mQueryName));
765f22c6
BH
540 mResultNameInd = -1;
541 mResultPrevNameInd = -1;
542 mResultNextNameInd = -1;
543
03fc70cf 544 rc = OCIStmtExecute(pooledSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
765f22c6 545
03fc70cf 546 if (rc == OCI_ERROR) {
765f22c6 547 throw OracleException(
03fc70cf 548 "Oracle getBeforeAndAfterNamesAbsolute", oraerr
765f22c6
BH
549 );
550 }
551
03fc70cf 552 check_indicator(mResultNameInd, false);
765f22c6
BH
553 check_indicator(mResultPrevNameInd, false);
554 check_indicator(mResultNextNameInd, false);
555
e3de6828 556 unhashed = DNSName(mResultName);
ab0fbe56
KM
557 before = DNSName(boost::replace_all_copy(mResultPrevName," ",".")).labelReverse();
558 after = DNSName(boost::replace_all_copy(mResultNextName," ",".")).labelReverse();
765f22c6 559
03fc70cf 560 release_query(stmt, prevNextHashQueryKey);
765f22c6
BH
561 return true;
562}
563
564vector<string>
ea9586a4 565OracleBackend::getDomainMasters (const DNSName& domain, int zoneId)
765f22c6 566{
03fc70cf
BH
567 sword rc;
568 OCIStmt *stmt;
569
765f22c6
BH
570 (void)domain;
571
572 vector<string> masters;
573 char master[512];
574 sb2 master_ind;
575
03fc70cf
BH
576 openMasterConnection();
577
578 stmt = prepare_query(masterSvcCtx, zoneMastersQuerySQL, zoneMastersQueryKey);
579 bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName));
580 bind_int(stmt, ":zoneid", &mQueryZoneId);
765f22c6
BH
581
582 mQueryZoneId = zoneId;
03fc70cf 583 define_output_str(stmt, 1, &master_ind, master, sizeof(master));
765f22c6 584
03fc70cf 585 rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
765f22c6 586
03fc70cf
BH
587 if (rc == OCI_ERROR) {
588 throw OracleException("Oracle getDomainMasters", oraerr);
765f22c6
BH
589 }
590
03fc70cf 591 while (rc != OCI_NO_DATA) {
765f22c6
BH
592 check_indicator(master_ind, false);
593
594 masters.push_back(master);
595
03fc70cf 596 rc = OCIStmtFetch2(stmt, oraerr, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT);
765f22c6 597
03fc70cf 598 if (rc == OCI_ERROR) {
765f22c6 599 throw OracleException(
03fc70cf 600 "OracleBackend, fetching next zone master", oraerr
765f22c6
BH
601 );
602 }
603 }
604
03fc70cf 605 release_query(stmt, zoneMastersQueryKey);
765f22c6 606
765f22c6
BH
607 return masters;
608}
609
610bool
ea9586a4 611OracleBackend::isMaster (const DNSName& domain, const string &master)
765f22c6 612{
03fc70cf
BH
613 sword rc;
614 OCIStmt *stmt;
615
616 openMasterConnection();
617
618 stmt = prepare_query(masterSvcCtx, isZoneMasterQuerySQL, isZoneMasterQueryKey);
765f22c6 619
e2b3f850 620 DNSName_to_cbuf(mQueryZone, domain, sizeof(mQueryZone));
765f22c6
BH
621 string_to_cbuf(mQueryName, master, sizeof(mQueryName));
622
623 char res_master[512];
624 sb2 res_master_ind;
625
03fc70cf
BH
626 bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName));
627 bind_str(stmt, ":name", mQueryZone, sizeof(mQueryZone));
628 bind_str(stmt, ":master", mQueryName, sizeof(mQueryName));
629 define_output_str(stmt, 1, &res_master_ind, res_master, sizeof(res_master));
765f22c6 630
03fc70cf 631 rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
765f22c6 632
03fc70cf
BH
633 if (rc == OCI_ERROR) {
634 throw OracleException("Oracle isMaster", oraerr);
765f22c6
BH
635 }
636
03fc70cf
BH
637 release_query(stmt, isZoneMasterQueryKey);
638
639 if (rc != OCI_NO_DATA) {
765f22c6 640 check_indicator(res_master_ind, false);
765f22c6
BH
641 return true;
642 }
643
765f22c6
BH
644 return false;
645}
646
647bool
ea9586a4 648OracleBackend::getDomainInfo (const DNSName& domain, DomainInfo &di)
765f22c6 649{
03fc70cf
BH
650 sword rc;
651 OCIStmt *stmt;
652
765f22c6
BH
653 int zone_id;
654 sb2 zone_id_ind;
655 int last_check;
656 sb2 last_check_ind;
657 uint32_t serial;
658 sb2 serial_ind;
659 uint32_t notified_serial;
660 sb2 notified_serial_ind;
661
03fc70cf
BH
662 openMasterConnection();
663
664 stmt = prepare_query(masterSvcCtx, zoneInfoQuerySQL, zoneInfoQueryKey);
665 bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName));
666 define_output_int(stmt, 1, &zone_id_ind, &zone_id);
667 define_output_str(stmt, 2, &mResultNameInd, mResultName, sizeof(mResultName));
668 define_output_str(stmt, 3, &mResultTypeInd, mResultType, sizeof(mResultType));
669 define_output_int(stmt, 4, &last_check_ind, &last_check);
670 define_output_uint32(stmt, 5, &serial_ind, &serial);
671 define_output_uint32(stmt, 6, &notified_serial_ind, &notified_serial);
765f22c6 672
e2b3f850 673 DNSName_to_cbuf(mQueryZone, domain, sizeof(mQueryZone));
03fc70cf 674 bind_str(stmt, ":name", mQueryZone, sizeof(mQueryZone));
765f22c6 675
03fc70cf 676 rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
765f22c6 677
03fc70cf
BH
678 if (rc == OCI_ERROR) {
679 throw OracleException("Oracle getDomainInfo", oraerr);
765f22c6
BH
680 }
681
03fc70cf
BH
682 if (rc == OCI_NO_DATA) {
683 release_query(stmt, zoneInfoQueryKey);
765f22c6
BH
684 return false;
685 }
686
687 check_indicator(zone_id_ind, false);
688 check_indicator(mResultNameInd, false);
689 check_indicator(serial_ind, true);
690
03fc70cf 691 if (zone_id < 0) throw std::underflow_error("OracleBackend: Zone ID < 0 when writing into uint32_t");
765f22c6
BH
692
693 di.id = zone_id;
e3de6828 694 di.zone = DNSName(mResultName);
765f22c6
BH
695 di.serial = serial;
696 di.backend = this;
697
698 check_indicator(mResultTypeInd, false);
699 if (strcasecmp(mResultType, "NATIVE") == 0) {
700 di.kind = DomainInfo::Native;
701 } else if (strcasecmp(mResultType, "MASTER") == 0) {
702 di.kind = DomainInfo::Master;
703 check_indicator(notified_serial_ind, false);
704 di.notified_serial = notified_serial;
705 } else if (strcasecmp(mResultType, "SLAVE") == 0) {
706 di.kind = DomainInfo::Slave;
707 check_indicator(last_check_ind, true);
708 di.last_check = last_check;
e3de6828 709 di.masters = getDomainMasters(DNSName(mResultName), zone_id);
765f22c6
BH
710 } else {
711 throw OracleException("Unknown zone type in Oracle backend");
712 }
713
765f22c6
BH
714 di.kind = DomainInfo::Native;
715
03fc70cf 716 release_query(stmt, zoneInfoQueryKey);
765f22c6
BH
717 return true;
718}
719
ea9586a4 720void OracleBackend::alsoNotifies(const DNSName& domain, set<string> *addrs)
765f22c6 721{
03fc70cf
BH
722 sword rc;
723 OCIStmt *stmt;
724
765f22c6
BH
725 char hostaddr[512];
726 sb2 hostaddr_ind;
727
03fc70cf
BH
728 openMasterConnection();
729
730 stmt = prepare_query(masterSvcCtx, alsoNotifyQuerySQL, alsoNotifyQueryKey);
731 bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName));
732 bind_str(stmt, ":name", mQueryZone, sizeof(mQueryZone));
765f22c6 733
e2b3f850 734 DNSName_to_cbuf(mQueryZone, domain, sizeof(mQueryZone));
765f22c6 735
03fc70cf 736 define_output_str(stmt, 1, &hostaddr_ind, hostaddr, sizeof(hostaddr));
765f22c6 737
03fc70cf 738 rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
765f22c6 739
03fc70cf
BH
740 if (rc == OCI_ERROR) {
741 throw OracleException("Oracle alsoNotifies", oraerr);
765f22c6
BH
742 }
743
03fc70cf 744 while (rc != OCI_NO_DATA) {
765f22c6
BH
745 check_indicator(hostaddr_ind, false);
746
747 addrs->insert(hostaddr);
748
03fc70cf 749 rc = OCIStmtFetch2(stmt, oraerr, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT);
765f22c6 750
03fc70cf 751 if (rc == OCI_ERROR) {
765f22c6 752 throw OracleException(
03fc70cf 753 "OracleBackend alsoNotifies fetch", oraerr
765f22c6
BH
754 );
755 }
756 }
757
03fc70cf 758 release_query(stmt, alsoNotifyQueryKey);
765f22c6
BH
759}
760
765f22c6
BH
761void
762OracleBackend::getUnfreshSlaveInfos (vector<DomainInfo>* domains)
763{
03fc70cf
BH
764 sword rc;
765 OCIStmt *stmt;
766
765f22c6
BH
767 struct timeval now;
768 gettimeofday(&now, NULL);
769 mQueryTimestamp = now.tv_sec;
770
771 int last_check;
772 sb2 last_check_ind;
773 uint32_t serial;
774 sb2 serial_ind;
775 char master[512];
776 sb2 master_ind;
777
03fc70cf 778 openMasterConnection();
765f22c6 779
03fc70cf
BH
780 stmt = prepare_query(masterSvcCtx, unfreshZonesQuerySQL, unfreshZonesQueryKey);
781 bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName));
782 bind_int(stmt, ":ts", &mQueryTimestamp);
783 define_output_int(stmt, 1, &mResultZoneIdInd, &mResultZoneId);
784 define_output_str(stmt, 2, &mResultNameInd, mResultName, sizeof(mResultName));
785 define_output_int(stmt, 3, &last_check_ind, &last_check);
786 define_output_uint32(stmt, 4, &serial_ind, &serial);
787 define_output_str(stmt, 5, &master_ind, master, sizeof(master));
765f22c6 788
03fc70cf
BH
789 rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
790
791 if (rc == OCI_ERROR) {
792 throw OracleException("Oracle getUnfreshSlaveInfos", oraerr);
765f22c6
BH
793 }
794
03fc70cf 795 while (rc != OCI_NO_DATA) {
765f22c6
BH
796 check_indicator(mResultZoneIdInd, false);
797 check_indicator(mResultNameInd, false);
03fc70cf 798 check_indicator(serial_ind, true);
765f22c6
BH
799 check_indicator(last_check_ind, true);
800 int zoneId = mResultZoneId;
801
03fc70cf 802 if (mResultZoneId < 0) throw std::underflow_error("OracleBackend: Zone ID < 0 when writing into uint32_t");
765f22c6
BH
803
804 DomainInfo di;
805 di.id = mResultZoneId;
e3de6828 806 di.zone = DNSName(mResultName);
765f22c6
BH
807 di.last_check = last_check;
808 di.kind = DomainInfo::Slave;
809 di.backend = this;
03fc70cf
BH
810 if (serial_ind == 0) {
811 di.serial = serial;
812 }
765f22c6 813
03fc70cf 814 while (rc != OCI_NO_DATA && zoneId == mResultZoneId) {
765f22c6
BH
815 check_indicator(master_ind, false);
816 di.masters.push_back(master);
817
03fc70cf 818 rc = OCIStmtFetch2(stmt, oraerr, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT);
765f22c6 819
03fc70cf 820 if (rc == OCI_ERROR) {
765f22c6 821 throw OracleException(
03fc70cf 822 "OracleBackend, fetching next unfresh slave master", oraerr
765f22c6 823 );
ae4e0030
BH
824 }
825
765f22c6
BH
826 check_indicator(mResultZoneIdInd, false);
827 }
828
829 domains->push_back(di);
830 }
831
03fc70cf 832 release_query(stmt, unfreshZonesQueryKey);
765f22c6
BH
833}
834
835void
836OracleBackend::getUpdatedMasters (vector<DomainInfo>* domains)
837{
03fc70cf
BH
838 sword rc;
839 OCIStmt *stmt;
840
765f22c6
BH
841 uint32_t serial;
842 sb2 serial_ind;
843 uint32_t notified_serial;
844 sb2 notified_serial_ind;
845
03fc70cf
BH
846 openMasterConnection();
847
848 stmt = prepare_query(masterSvcCtx, updatedMastersQuerySQL, updatedMastersQueryKey);
849 bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName));
850 define_output_int(stmt, 1, &mResultZoneIdInd, &mResultZoneId);
851 define_output_str(stmt, 2, &mResultNameInd, mResultName, sizeof(mResultName));
852 define_output_uint32(stmt, 3, &serial_ind, &serial);
853 define_output_uint32(stmt, 4, &notified_serial_ind, &notified_serial);
765f22c6 854
03fc70cf 855 rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
765f22c6 856
03fc70cf
BH
857 if (rc == OCI_ERROR) {
858 throw OracleException("Oracle getUpdatedMasters", oraerr);
765f22c6
BH
859 }
860
03fc70cf 861 while (rc != OCI_NO_DATA) {
765f22c6
BH
862 check_indicator(mResultZoneIdInd, false);
863 check_indicator(mResultNameInd, false);
864 check_indicator(serial_ind, false);
865 check_indicator(notified_serial_ind, true);
866
03fc70cf 867 if (mResultZoneId < 0) throw std::underflow_error("OracleBackend: Zone ID < 0 when writing into uint32_t");
765f22c6
BH
868
869 DomainInfo di;
870 di.id = mResultZoneId;
e3de6828 871 di.zone = DNSName(mResultName);
765f22c6
BH
872 di.serial = serial;
873 di.notified_serial = notified_serial;
874 di.kind = DomainInfo::Master;
875 di.backend = this;
876
877 domains->push_back(di);
878
03fc70cf 879 rc = OCIStmtFetch2(stmt, oraerr, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT);
765f22c6 880
03fc70cf 881 if (rc == OCI_ERROR) {
765f22c6 882 throw OracleException(
03fc70cf 883 "OracleBackend, fetching next updated master", oraerr
765f22c6
BH
884 );
885 }
886 }
887
03fc70cf 888 release_query(stmt, updatedMastersQueryKey);
765f22c6
BH
889}
890
891void
892OracleBackend::setFresh (uint32_t zoneId)
893{
03fc70cf
BH
894 sword rc;
895 OCIStmt *stmt;
896
765f22c6
BH
897 mQueryZoneId = zoneId;
898
899 struct timeval now;
900 gettimeofday(&now, NULL);
901 mQueryTimestamp = now.tv_sec;
902
03fc70cf
BH
903 openMasterConnection();
904
905 rc = OCITransStart(masterSvcCtx, oraerr, 60, OCI_TRANS_NEW);
765f22c6 906
03fc70cf
BH
907 if (rc == OCI_ERROR) {
908 throw OracleException("Oracle setFresh BEGIN", oraerr);
765f22c6
BH
909 }
910
03fc70cf
BH
911 stmt = prepare_query(masterSvcCtx, zoneSetLastCheckQuerySQL, zoneSetLastCheckQueryKey);
912 bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName));
913 bind_int(stmt, ":zoneid", &mQueryZoneId);
914 bind_int(stmt, ":lastcheck", &mQueryTimestamp);
765f22c6 915
03fc70cf 916 rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
765f22c6 917
03fc70cf
BH
918 if (rc == OCI_ERROR) {
919 throw OracleException("Oracle setFresh", oraerr);
765f22c6
BH
920 }
921
03fc70cf 922 release_query(stmt, zoneSetLastCheckQueryKey);
765f22c6 923
03fc70cf 924 rc = OCITransCommit(masterSvcCtx, oraerr, OCI_DEFAULT);
765f22c6 925
03fc70cf
BH
926 if (rc) {
927 throw OracleException("Oracle setFresh COMMIT", oraerr);
765f22c6 928 }
765f22c6
BH
929}
930
931void
932OracleBackend::setNotified (uint32_t zoneId, uint32_t serial)
933{
03fc70cf
BH
934 sword rc;
935 OCIStmt *stmt;
765f22c6 936
03fc70cf 937 openMasterConnection();
765f22c6 938
03fc70cf
BH
939 rc = OCITransStart(masterSvcCtx, oraerr, 60, OCI_TRANS_NEW);
940
941 if (rc == OCI_ERROR) {
942 throw OracleException("Oracle setNotified BEGIN", oraerr);
943 }
765f22c6 944
03fc70cf
BH
945 stmt = prepare_query(masterSvcCtx, zoneSetNotifiedSerialQuerySQL, zoneSetNotifiedSerialQueryKey);
946 bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName));
947 bind_uint32(stmt, ":serial", &serial);
948 bind_uint32(stmt, ":zoneid", &zoneId);
765f22c6 949
03fc70cf 950 rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
765f22c6 951
03fc70cf
BH
952 if (rc == OCI_ERROR) {
953 throw OracleException("Oracle setNotified", oraerr);
765f22c6
BH
954 }
955
03fc70cf 956 release_query(stmt, zoneSetNotifiedSerialQueryKey);
765f22c6 957
03fc70cf 958 rc = OCITransCommit(masterSvcCtx, oraerr, OCI_DEFAULT);
765f22c6 959
03fc70cf
BH
960 if (rc) {
961 throw OracleException("Oracle setNotified COMMIT", oraerr);
765f22c6 962 }
765f22c6
BH
963}
964
965bool
ea9586a4 966OracleBackend::list (const DNSName& domain, int zoneId, bool include_disabled)
765f22c6 967{
03fc70cf
BH
968 sword rc;
969
765f22c6
BH
970 // This is only for backends that cannot lookup by zoneId,
971 // we can discard
972 (void)domain;
973
03fc70cf
BH
974 if (curStmtHandle != NULL) throw OracleException("Invalid state");
975 curStmtHandle = prepare_query(pooledSvcCtx, listQuerySQL, listQueryKey);
976 curStmtKey = listQueryKey;
977 define_fwd_query(curStmtHandle);
978 bind_str_failokay(curStmtHandle, ":nsname", myServerName, sizeof(myServerName));
979 bind_int(curStmtHandle, ":zoneid", &mQueryZoneId);
765f22c6
BH
980
981 mQueryZoneId = zoneId;
982
03fc70cf 983 rc = OCIStmtExecute(pooledSvcCtx, curStmtHandle, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
765f22c6 984
03fc70cf
BH
985 if (rc == OCI_ERROR) {
986 throw OracleException("Oracle List", oraerr);
765f22c6
BH
987 }
988
03fc70cf 989 if (rc == OCI_SUCCESS || rc == OCI_SUCCESS_WITH_INFO) {
765f22c6
BH
990 return true;
991 }
992
03fc70cf
BH
993 if (rc == OCI_NO_DATA) {
994 release_query(curStmtHandle, curStmtKey);
995 curStmtHandle = NULL;
996 }
997
765f22c6
BH
998 return false;
999}
1000
1001bool OracleBackend::get (DNSResourceRecord &rr)
1002{
03fc70cf
BH
1003 sword rc;
1004
1005 if (curStmtHandle == NULL) {
765f22c6
BH
1006 return false;
1007 }
1008
1009 check_indicator(mResultNameInd, false);
1010 check_indicator(mResultTTLInd, false);
c8cb5716
KM
1011 check_indicator(mResultTypeInd, true);
1012 check_indicator(mResultContentInd, true);
765f22c6
BH
1013 check_indicator(mResultZoneIdInd, false);
1014 check_indicator(mResultLastChangeInd, false);
71301b6e
PD
1015 if (d_dnssecQueries)
1016 check_indicator(mResultIsAuthInd, false);
765f22c6 1017
e3de6828 1018 rr.qname = DNSName(mResultName);
765f22c6
BH
1019 rr.ttl = mResultTTL;
1020 rr.qtype = mResultType;
22b8ff16 1021 rr.content = mResultContent;
765f22c6
BH
1022 rr.domain_id = mResultZoneId;
1023 rr.last_modified = mResultLastChange;
71301b6e
PD
1024 if (d_dnssecQueries)
1025 rr.auth = mResultIsAuth > 0;
1026 else
1027 rr.auth = 1;
765f22c6 1028
03fc70cf
BH
1029 rc = OCIStmtFetch2(curStmtHandle, oraerr, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT);
1030
1031 if (rc == OCI_ERROR) {
1032 throw OracleException("OracleBackend, fetching next row", oraerr);
1033 }
765f22c6 1034
03fc70cf
BH
1035 if (rc == OCI_NO_DATA) {
1036 release_query(curStmtHandle, curStmtKey);
1037 curStmtHandle = NULL;
765f22c6
BH
1038 }
1039
1040 return true;
1041}
1042
1043bool
ea9586a4 1044OracleBackend::startTransaction (const DNSName& domain, int zoneId)
765f22c6 1045{
03fc70cf
BH
1046 sword rc;
1047 OCIStmt *stmt;
1048
765f22c6
BH
1049 (void)domain;
1050
03fc70cf 1051 openMasterConnection();
765f22c6 1052
03fc70cf
BH
1053 rc = OCITransStart(masterSvcCtx, oraerr, 60, OCI_TRANS_NEW);
1054
1055 if (rc == OCI_ERROR) {
1056 throw OracleException("Oracle startTransaction", oraerr);
765f22c6
BH
1057 }
1058
1059 if (zoneId >= 0) {
03fc70cf
BH
1060 if (openTransactionZoneID >= 0) {
1061 throw OracleException("Attempt to start AXFR during AXFR");
1062 }
1063
1064 mQueryZoneId = openTransactionZoneID = zoneId;
765f22c6 1065
03fc70cf
BH
1066 stmt = prepare_query(masterSvcCtx, deleteZoneQuerySQL, deleteZoneQueryKey);
1067 bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName));
1068 bind_int(stmt, ":zoneid", &mQueryZoneId);
765f22c6 1069
03fc70cf 1070 rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
765f22c6 1071
03fc70cf
BH
1072 if (rc == OCI_ERROR) {
1073 throw OracleException("Oracle startTransaction deleteZone", oraerr);
765f22c6
BH
1074 }
1075
03fc70cf 1076 release_query(stmt, deleteZoneQueryKey);
765f22c6
BH
1077 }
1078
765f22c6
BH
1079 return true;
1080}
1081
1082bool
c9b43446 1083OracleBackend::feedRecord (const DNSResourceRecord &rr, const DNSName ordername)
765f22c6 1084{
03fc70cf
BH
1085 sword rc;
1086 OCIStmt *stmt;
765f22c6 1087
03fc70cf 1088 uint32_t ttl;
765f22c6 1089
03fc70cf
BH
1090 stmt = prepare_query(masterSvcCtx, insertRecordQuerySQL, insertRecordQueryKey);
1091 bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName));
1092 bind_int(stmt, ":zoneid", &mQueryZoneId);
1093 bind_str(stmt, ":name", mQueryName, sizeof(mQueryName));
1094 bind_str(stmt, ":type", mQueryType, sizeof(mQueryType));
1095 bind_uint32(stmt, ":ttl", &ttl);
b9bafae0 1096 bind_str(stmt, ":content", mQueryContent, sizeof(mQueryContent));
765f22c6
BH
1097
1098 mQueryZoneId = rr.domain_id;
e2b3f850 1099 DNSName_to_cbuf(mQueryName, rr.qname, sizeof(mQueryName));
765f22c6
BH
1100 ttl = rr.ttl;
1101 string_to_cbuf(mQueryType, rr.qtype.getName(), sizeof(mQueryType));
b9bafae0 1102 string_to_cbuf(mQueryContent, rr.content, sizeof(mQueryContent));
765f22c6 1103
03fc70cf 1104 rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
765f22c6 1105
03fc70cf
BH
1106 if (rc == OCI_ERROR) {
1107 throw OracleException("Oracle feedRecord", oraerr);
765f22c6
BH
1108 }
1109
03fc70cf
BH
1110 release_query(stmt, insertRecordQueryKey);
1111
765f22c6
BH
1112 return true;
1113}
1114
1115bool
1116OracleBackend::commitTransaction ()
1117{
03fc70cf
BH
1118 sword rc;
1119 OCIStmt *stmt;
765f22c6 1120
03fc70cf
BH
1121 if (openTransactionZoneID >= 0) {
1122 stmt = prepare_query(masterSvcCtx, finalizeAXFRQuerySQL, finalizeAXFRQueryKey);
1123 bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName));
1124 bind_int(stmt, ":zoneid", &openTransactionZoneID);
765f22c6 1125
03fc70cf
BH
1126 rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
1127
1128 if (rc == OCI_ERROR) {
1129 throw OracleException("Oracle commitTransaction finalizeAXFR", oraerr);
1130 }
1131
1132 release_query(stmt, finalizeAXFRQueryKey);
1133
1134 openTransactionZoneID = -1;
1135 }
1136
1137 rc = OCITransCommit(masterSvcCtx, oraerr, OCI_DEFAULT);
1138
1139 if (rc) {
1140 throw OracleException("Oracle commitTransaction", oraerr);
765f22c6
BH
1141 }
1142
765f22c6
BH
1143 return true;
1144}
1145
1146bool
1147OracleBackend::abortTransaction ()
1148{
1149 sword err;
1150
03fc70cf 1151 err = OCITransRollback(masterSvcCtx, oraerr, OCI_DEFAULT);
765f22c6
BH
1152
1153 if (err) {
03fc70cf 1154 throw OracleException("Oracle abortTransaction", oraerr);
765f22c6
BH
1155 }
1156
765f22c6
BH
1157 return true;
1158}
1159
1160bool
ea9586a4 1161OracleBackend::superMasterBackend (const string &ip, const DNSName& domain,
765f22c6 1162 const vector<DNSResourceRecord> &nsset,
719f9024
KM
1163 string *nameserver, string *account,
1164 DNSBackend **backend)
765f22c6 1165{
03fc70cf
BH
1166 sword rc;
1167 OCIStmt *stmt;
1168
1169 bool result = false;
1170
765f22c6
BH
1171 (void)domain;
1172
1173 string_to_cbuf(mQueryAddr, ip, sizeof(mQueryAddr));
1174
03fc70cf
BH
1175 openMasterConnection();
1176
1177 stmt = prepare_query(masterSvcCtx, acceptSupernotificationQuerySQL, acceptSupernotificationQueryKey);
1178 define_output_str(stmt, 1, &mResultNameInd, mResultName, sizeof(mResultName));
1179 bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName));
1180 bind_str(stmt, ":ns", mQueryName, sizeof(mQueryName));
1181 bind_str(stmt, ":ip", mQueryAddr, sizeof(mQueryAddr));
1182
1183 for (vector<DNSResourceRecord>::const_iterator i=nsset.begin(); i != nsset.end(); ++i) {
765f22c6
BH
1184 string_to_cbuf(mQueryName, i->content, sizeof(mQueryName));
1185
03fc70cf 1186 rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
765f22c6 1187
03fc70cf
BH
1188 if (rc == OCI_ERROR) {
1189 throw OracleException("Oracle superMasterBackend", oraerr);
765f22c6
BH
1190 }
1191
03fc70cf 1192 if (rc != OCI_NO_DATA) {
765f22c6
BH
1193 *account = mResultName;
1194 *backend = this;
03fc70cf
BH
1195 result = true;
1196 break;
765f22c6
BH
1197 }
1198 }
1199
03fc70cf 1200 release_query(stmt, acceptSupernotificationQueryKey);
765f22c6 1201
03fc70cf 1202 return result;
765f22c6
BH
1203}
1204
1205bool
ea9586a4 1206OracleBackend::createSlaveDomain(const string &ip, const DNSName& domain,
719f9024 1207 const string &nameserver, const string &account)
765f22c6 1208{
03fc70cf
BH
1209 sword rc;
1210 OCIStmt *insertSlaveQueryHandle;
1211 OCIStmt *insertMasterQueryHandle;
1212
e2b3f850 1213 DNSName_to_cbuf(mQueryZone, domain, sizeof(mQueryZone));
765f22c6 1214
03fc70cf 1215 openMasterConnection();
765f22c6 1216
03fc70cf
BH
1217 rc = OCITransStart(masterSvcCtx, oraerr, 60, OCI_TRANS_NEW);
1218
1219 if (rc == OCI_ERROR) {
1220 throw OracleException("Oracle createSlaveDomain BEGIN", oraerr);
765f22c6
BH
1221 }
1222
03fc70cf 1223 insertSlaveQueryHandle = prepare_query(masterSvcCtx, insertSlaveQuerySQL, insertSlaveQueryKey);
765f22c6
BH
1224 bind_str_failokay(insertSlaveQueryHandle, ":nsname", myServerName, sizeof(myServerName));
1225 bind_int(insertSlaveQueryHandle, ":zoneid", &mQueryZoneId);
03fc70cf 1226 bind_str(insertSlaveQueryHandle, ":zone", mQueryZone, sizeof(mQueryZone));
765f22c6 1227
03fc70cf 1228 insertMasterQueryHandle = prepare_query(masterSvcCtx, insertMasterQuerySQL, insertMasterQueryKey);
765f22c6
BH
1229 bind_str_failokay(insertMasterQueryHandle, ":nsname", myServerName, sizeof(myServerName));
1230 bind_int(insertMasterQueryHandle, ":zoneid", &mQueryZoneId);
03fc70cf 1231 bind_str(insertMasterQueryHandle, ":ip", mQueryAddr, sizeof(mQueryAddr));
765f22c6 1232
03fc70cf 1233 rc = OCIStmtExecute(masterSvcCtx, insertSlaveQueryHandle, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
765f22c6 1234
03fc70cf 1235 if (rc == OCI_ERROR) {
765f22c6 1236 throw OracleException(
03fc70cf 1237 "Oracle createSlaveDomain insertSlave", oraerr);
765f22c6
BH
1238 }
1239
1240 string_to_cbuf(mQueryAddr, ip, sizeof(mQueryAddr));
1241
03fc70cf 1242 rc = OCIStmtExecute(masterSvcCtx, insertMasterQueryHandle, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
765f22c6 1243
03fc70cf 1244 if (rc == OCI_ERROR) {
765f22c6 1245 throw OracleException(
03fc70cf 1246 "Oracle createSlaveDomain insertMaster", oraerr);
765f22c6
BH
1247 }
1248
1249 release_query(insertSlaveQueryHandle, insertSlaveQueryKey);
1250 release_query(insertMasterQueryHandle, insertMasterQueryKey);
1251
03fc70cf 1252 rc = OCITransCommit(masterSvcCtx, oraerr, OCI_DEFAULT);
765f22c6 1253
03fc70cf
BH
1254 if (rc) {
1255 throw OracleException("Oracle createSlaveDomain COMMIT", oraerr);
765f22c6
BH
1256 }
1257
765f22c6
BH
1258 return true;
1259}
1260
16534364 1261bool
ea9586a4 1262OracleBackend::getAllDomainMetadata (const DNSName& name, std::map<string, vector<string> >& meta)
16534364 1263{
16534364
AT
1264 DomainInfo di;
1265 if (getDomainInfo(name, di) == false) return false;
1266
1267 sword rc;
1268 OCIStmt *stmt;
1269
1270 stmt = prepare_query(pooledSvcCtx, getAllZoneMetadataQuerySQL, getAllZoneMetadataQueryKey);
1271 bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName));
1272 bind_str(stmt, ":name", mQueryName, sizeof(mQueryName));
cdbf24f6
KM
1273
1274 define_output_str(stmt, 1, &mResultTypeInd, mResultType, sizeof(mResultType));
1275 define_output_str(stmt, 2, &mResultContentInd, mResultContent, sizeof(mResultContent));
16534364 1276
e2b3f850 1277 DNSName_to_cbuf(mQueryName, name, sizeof(mQueryName));
16534364
AT
1278
1279 rc = OCIStmtExecute(pooledSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
1280
1281 while (rc != OCI_NO_DATA) {
1282 if (rc == OCI_ERROR) {
1283 throw OracleException("Oracle getAllDomainMetadata", oraerr);
1284 }
cdbf24f6 1285 check_indicator(mResultTypeInd, true);
16534364
AT
1286 check_indicator(mResultContentInd, true);
1287
cdbf24f6 1288 string kind = mResultType;
16534364 1289 string content = mResultContent;
ad34750d
KM
1290 if (!isDnssecDomainMetadata(content))
1291 meta[kind].push_back(content);
16534364
AT
1292
1293 rc = OCIStmtFetch2(stmt, oraerr, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT);
1294 }
1295
1296 release_query(stmt, getAllZoneMetadataQueryKey);
1297 return true;
1298}
1299
765f22c6 1300bool
ea9586a4 1301OracleBackend::getDomainMetadata (const DNSName& name, const string& kind,
765f22c6
BH
1302 vector<string>& meta)
1303{
ad34750d 1304 if(!d_dnssecQueries && isDnssecDomainMetadata(kind))
71301b6e
PD
1305 return -1;
1306 DomainInfo di;
1307 if (getDomainInfo(name, di) == false) return false;
1308
03fc70cf
BH
1309 sword rc;
1310 OCIStmt *stmt;
1311
1312 stmt = prepare_query(pooledSvcCtx, getZoneMetadataQuerySQL, getZoneMetadataQueryKey);
1313 bind_str_failokay(stmt, ":nsname", myServerName, sizeof(myServerName));
1314 bind_str(stmt, ":name", mQueryName, sizeof(mQueryName));
1315 bind_str(stmt, ":kind", mQueryType, sizeof(mQueryType));
1316 define_output_str(stmt, 1, &mResultContentInd, mResultContent, sizeof(mResultContent));
1317
e2b3f850 1318 DNSName_to_cbuf(mQueryName, name, sizeof(mQueryName));
765f22c6
BH
1319 string_to_cbuf(mQueryType, kind, sizeof(mQueryType));
1320
03fc70cf 1321 rc = OCIStmtExecute(pooledSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
765f22c6 1322
03fc70cf
BH
1323 while (rc != OCI_NO_DATA) {
1324 if (rc == OCI_ERROR) {
1325 throw OracleException("Oracle getDomainMetadata", oraerr);
765f22c6
BH
1326 }
1327
1328 check_indicator(mResultContentInd, true);
1329
1330 string content = mResultContent;
1331 meta.push_back(content);
1332
03fc70cf 1333 rc = OCIStmtFetch2(stmt, oraerr, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT);
765f22c6
BH
1334 }
1335
03fc70cf 1336 release_query(stmt, getZoneMetadataQueryKey);
765f22c6
BH
1337 return true;
1338}
1339
1340bool
ea9586a4 1341OracleBackend::setDomainMetadata(const DNSName& name, const string& kind,
765f22c6
BH
1342 const vector<string>& meta)
1343{
ad34750d 1344 if(!d_dnssecQueries && isDnssecDomainMetadata(kind))
71301b6e
PD
1345 return -1;
1346 DomainInfo di;
1347 if (getDomainInfo(name, di) == false) return false;
1348
03fc70cf
BH
1349 sword rc;
1350 OCIStmt *stmt;
1351
1352 openMasterConnection();
765f22c6 1353
03fc70cf
BH
1354 rc = OCITransStart(masterSvcCtx, oraerr, 60, OCI_TRANS_NEW);
1355
1356 if (rc == OCI_ERROR) {
1357 throw OracleException("Oracle setDomainMetadata BEGIN", oraerr);
765f22c6
BH
1358 }
1359
e2b3f850 1360 DNSName_to_cbuf(mQueryName, name, sizeof(mQueryName));
765f22c6
BH
1361 string_to_cbuf(mQueryType, kind, sizeof(mQueryType));
1362
03fc70cf
BH
1363 stmt = prepare_query(masterSvcCtx, delZoneMetadataQuerySQL, delZoneMetadataQueryKey);
1364 bind_str(stmt, ":name", mQueryName, sizeof(mQueryName));
1365 bind_str(stmt, ":kind", mQueryType, sizeof(mQueryType));
765f22c6 1366
03fc70cf 1367 rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
765f22c6 1368
03fc70cf
BH
1369 if (rc == OCI_ERROR) {
1370 throw OracleException("Oracle setDomainMetadata DELETE", oraerr);
765f22c6
BH
1371 }
1372
03fc70cf
BH
1373 release_query(stmt, delZoneMetadataQueryKey);
1374
1375 stmt = prepare_query(masterSvcCtx, setZoneMetadataQuerySQL, setZoneMetadataQueryKey);
765f22c6
BH
1376
1377 int i = 0;
1378
03fc70cf
BH
1379 bind_str(stmt, ":name", mQueryName, sizeof(mQueryName));
1380 bind_str(stmt, ":kind", mQueryType, sizeof(mQueryType));
1381 bind_int(stmt, ":i", &i);
1382 bind_str(stmt, ":content", mQueryContent, sizeof(mQueryContent));
765f22c6
BH
1383
1384 for (vector<string>::const_iterator it = meta.begin(); it != meta.end(); ++it) {
1385 string_to_cbuf(mQueryContent, *it, sizeof(mQueryContent));
03fc70cf
BH
1386 rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
1387 if (rc == OCI_ERROR) {
1388 throw OracleException("Oracle setDomainMetadata INSERT", oraerr);
765f22c6
BH
1389 }
1390 i++;
1391 }
1392
03fc70cf 1393 release_query(stmt, setZoneMetadataQueryKey);
765f22c6 1394
03fc70cf 1395 rc = OCITransCommit(masterSvcCtx, oraerr, OCI_DEFAULT);
765f22c6 1396
03fc70cf
BH
1397 if (rc == OCI_ERROR) {
1398 throw OracleException("Oracle setDomainMetadata COMMIT", oraerr);
765f22c6
BH
1399 }
1400
1401 return true;
ae4e0030
BH
1402}
1403
03fc70cf 1404bool
ea9586a4 1405OracleBackend::getTSIGKey (const DNSName& name, DNSName* algorithm, string* content)
03fc70cf
BH
1406{
1407 sword rc;
1408 OCIStmt *stmt;
1409
1410 stmt = prepare_query(pooledSvcCtx, getTSIGKeyQuerySQL, getTSIGKeyQueryKey);
e2b3f850 1411 DNSName_to_cbuf(mQueryName, name, sizeof(mQueryName));
5c15b4ca 1412 bind_str(stmt, ":name", mQueryName, sizeof(mQueryName));
bb134ac6 1413
03fc70cf
BH
1414 define_output_str(stmt, 1, &mResultTypeInd, mResultType, sizeof(mResultType));
1415 define_output_str(stmt, 2, &mResultContentInd, mResultContent, sizeof(mResultContent));
1416
1417 rc = OCIStmtExecute(pooledSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
1418
87168c90
KM
1419 content->clear();
1420 while (rc != OCI_NO_DATA) {
03fc70cf 1421
87168c90
KM
1422 if (rc == OCI_ERROR) {
1423 throw OracleException("Oracle getTSIGKey", oraerr);
1424 }
03fc70cf 1425
87168c90
KM
1426 check_indicator(mResultTypeInd, false);
1427 check_indicator(mResultContentInd, false);
03fc70cf 1428
e3de6828
KM
1429 if(algorithm->empty() || *algorithm==DNSName(mResultType)) {
1430 *algorithm = DNSName(mResultType);
87168c90
KM
1431 *content = mResultContent;
1432 }
1433
1434 rc = OCIStmtFetch2(stmt, oraerr, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT);
1435 }
03fc70cf
BH
1436
1437 release_query(stmt, getTSIGKeyQueryKey);
87168c90 1438 return !content->empty();
03fc70cf
BH
1439}
1440
911c3aa7 1441bool
ea9586a4 1442OracleBackend::delTSIGKey(const DNSName& name)
911c3aa7 1443{
f718b8c6
AT
1444 sword rc;
1445 OCIStmt *stmt;
1446
1447 openMasterConnection();
f718b8c6
AT
1448 rc = OCITransStart(masterSvcCtx, oraerr, 60, OCI_TRANS_NEW);
1449
672d2e89 1450 stmt = prepare_query(masterSvcCtx, delTSIGKeyQuerySQL, delTSIGKeyQueryKey);
e2b3f850 1451 DNSName_to_cbuf(mQueryName, name, sizeof(mQueryName));
47541c8a 1452
f718b8c6 1453 bind_str(stmt, ":name", mQueryName, sizeof(mQueryName));
47541c8a 1454
f718b8c6 1455 rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
f718b8c6 1456
911c3aa7 1457 if (rc == OCI_ERROR) {
672d2e89 1458 throw OracleException("Oracle delTSIGKey", oraerr);
911c3aa7
AT
1459 }
1460
1461 release_query(stmt, setTSIGKeyQueryKey);
f718b8c6
AT
1462
1463 rc = OCITransCommit(masterSvcCtx, oraerr, OCI_DEFAULT);
1464 if (rc == OCI_ERROR) {
672d2e89 1465 throw OracleException("Oracle delTSIGKey COMMIT", oraerr);
f718b8c6 1466 }
911c3aa7
AT
1467 return true;
1468}
1469
1470bool
ea9586a4 1471OracleBackend::setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content)
911c3aa7 1472{
f718b8c6
AT
1473 sword rc;
1474 OCIStmt *stmt;
1475
1476 openMasterConnection();
672d2e89 1477
f718b8c6
AT
1478 rc = OCITransStart(masterSvcCtx, oraerr, 60, OCI_TRANS_NEW);
1479
47541c8a
KM
1480 if (rc == OCI_ERROR) {
1481 throw OracleException("Oracle setTSIGKey BEGIN", oraerr);
1482 }
1483
672d2e89 1484 stmt = prepare_query(masterSvcCtx, delTSIGKeyQuerySQL, delTSIGKeyQueryKey);
e2b3f850 1485 DNSName_to_cbuf(mQueryName, name, sizeof(mQueryName));
47541c8a 1486
911c3aa7 1487 bind_str(stmt, ":name", mQueryName, sizeof(mQueryName));
672d2e89 1488
f718b8c6 1489 rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
47541c8a 1490
672d2e89 1491 if (rc == OCI_ERROR) {
47541c8a 1492 throw OracleException("Oracle setTSIGKey DELETE", oraerr);
672d2e89 1493 }
911c3aa7 1494
47541c8a 1495 release_query(stmt, delTSIGKeyQueryKey);
672d2e89
KM
1496
1497 stmt = prepare_query(masterSvcCtx, setTSIGKeyQuerySQL, setTSIGKeyQueryKey);
e2b3f850
KM
1498 DNSName_to_cbuf(mQueryName, name, sizeof(mQueryName));
1499 DNSName_to_cbuf(mQueryType, algorithm, sizeof(mQueryType));
672d2e89
KM
1500 string_to_cbuf(mQueryContent, content, sizeof(mQueryContent));
1501
1502 bind_str(stmt, ":name", mQueryName, sizeof(mQueryName));
1503 bind_str(stmt, ":algorithm", mQueryType, sizeof(mQueryType));
1504 bind_str(stmt, ":secret", mQueryContent, sizeof(mQueryContent));
1505
1506 rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
47541c8a 1507
911c3aa7 1508 if (rc == OCI_ERROR) {
47541c8a 1509 throw OracleException("Oracle setTSIGKey INSERT", oraerr);
911c3aa7
AT
1510 }
1511
1512 release_query(stmt, setTSIGKeyQueryKey);
f718b8c6
AT
1513
1514 rc = OCITransCommit(masterSvcCtx, oraerr, OCI_DEFAULT);
47541c8a 1515
f718b8c6 1516 if (rc == OCI_ERROR) {
672d2e89 1517 throw OracleException("Oracle setTSIGKey COMMIT", oraerr);
f718b8c6 1518 }
672d2e89 1519
911c3aa7
AT
1520 return true;
1521}
1522
1523bool
1524OracleBackend::getTSIGKeys(std::vector< struct TSIGKey > &keys)
1525{
911c3aa7
AT
1526 sword rc;
1527 OCIStmt *stmt;
1528
1529 stmt = prepare_query(pooledSvcCtx, getTSIGKeysQuerySQL, getTSIGKeysQueryKey);
672d2e89
KM
1530 define_output_str(stmt, 1, &mResultNameInd, mResultName, sizeof(mResultName));
1531 define_output_str(stmt, 2, &mResultTypeInd, mResultType, sizeof(mResultType));
1532 define_output_str(stmt, 3, &mResultContentInd, mResultContent, sizeof(mResultContent));
911c3aa7
AT
1533
1534 rc = OCIStmtExecute(pooledSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
1535
1536 while (rc != OCI_NO_DATA) {
1537 if (rc == OCI_ERROR) {
1538 throw OracleException("Oracle getDomainMetadata", oraerr);
1539 }
1540
1541 check_indicator(mResultNameInd, true);
1542 check_indicator(mResultTypeInd, true);
1543 check_indicator(mResultContentInd, true);
1544
1545 struct TSIGKey key;
1546
e3de6828
KM
1547 key.name = DNSName(mResultName);
1548 key.algorithm = DNSName(mResultType);
672d2e89 1549 key.key = mResultContent;
911c3aa7
AT
1550 keys.push_back(key);
1551
1552 rc = OCIStmtFetch2(stmt, oraerr, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT);
1553 }
1554
1555 release_query(stmt, getTSIGKeyQueryKey);
1556 return true;
1557}
1558
765f22c6 1559bool
9c1c5d49 1560OracleBackend::getDomainKeys (const DNSName& name, vector<KeyData>& keys)
765f22c6 1561{
71301b6e
PD
1562 if(!d_dnssecQueries)
1563 return -1;
1564 DomainInfo di;
1565 if (getDomainInfo(name, di) == false) return false;
1566
03fc70cf
BH
1567 sword rc;
1568 OCIStmt *stmt;
1569
1570 stmt = prepare_query(pooledSvcCtx, getZoneKeysQuerySQL, getZoneKeysQueryKey);
1571 bind_str(stmt, ":name", mQueryName, sizeof(mQueryName));
1572
e2b3f850 1573 DNSName_to_cbuf(mQueryName, name, sizeof(mQueryName));
765f22c6
BH
1574
1575 sb2 key_id_ind = 0;
1576 unsigned int key_id = 0;
1577 sb2 key_flags_ind = 0;
1578 uint16_t key_flags = 0;
1579 sb2 key_active_ind = 0;
1580 int key_active = 0;
765f22c6 1581
03fc70cf
BH
1582 define_output_uint(stmt, 1, &key_id_ind, &key_id);
1583 define_output_uint16(stmt, 2, &key_flags_ind, &key_flags);
1584 define_output_int(stmt, 3, &key_active_ind, &key_active);
1585 define_output_str(stmt, 4, &mResultContentInd, mResultContent, sizeof(mResultContent));
1586
1587 rc = OCIStmtExecute(pooledSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
765f22c6 1588
03fc70cf
BH
1589 while (rc != OCI_NO_DATA) {
1590 if (rc == OCI_ERROR) {
1591 throw OracleException("Oracle getDomainKeys", oraerr);
765f22c6
BH
1592 }
1593
1594 check_indicator(key_id_ind, false);
1595 check_indicator(key_flags_ind, false);
1596 check_indicator(key_active_ind, false);
1597 check_indicator(mResultContentInd, false);
1598
1599 KeyData kd;
1600 kd.id = key_id;
1601 kd.flags = key_flags;
1602 kd.active = key_active;
1603 kd.content = mResultContent;
1604 keys.push_back(kd);
1605
03fc70cf 1606 rc = OCIStmtFetch2(stmt, oraerr, 1, OCI_FETCH_NEXT, 0, OCI_DEFAULT);
765f22c6
BH
1607 }
1608
03fc70cf 1609 release_query(stmt, getZoneKeysQueryKey);
765f22c6
BH
1610 return true;
1611}
1612
1613bool
ea9586a4 1614OracleBackend::removeDomainKey (const DNSName& name, unsigned int id)
765f22c6 1615{
71301b6e
PD
1616 if(!d_dnssecQueries)
1617 return -1;
1618 DomainInfo di;
1619 if (getDomainInfo(name, di) == false) return false;
1620
03fc70cf
BH
1621 sword rc;
1622 OCIStmt *stmt;
1623
1624 openMasterConnection();
1625
1626 rc = OCITransStart(masterSvcCtx, oraerr, 60, OCI_TRANS_NEW);
765f22c6 1627
03fc70cf
BH
1628 if (rc == OCI_ERROR) {
1629 throw OracleException("Oracle removeDomainKey BEGIN", oraerr);
765f22c6
BH
1630 }
1631
03fc70cf
BH
1632 stmt = prepare_query(masterSvcCtx, delZoneKeyQuerySQL, delZoneKeyQueryKey);
1633 bind_uint(stmt, ":keyid", &id);
765f22c6 1634
03fc70cf 1635 rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
765f22c6 1636
03fc70cf
BH
1637 if (rc == OCI_ERROR) {
1638 throw OracleException("Oracle removeDomainKey DELETE", oraerr);
765f22c6
BH
1639 }
1640
03fc70cf 1641 release_query(stmt, delZoneKeyQueryKey);
765f22c6 1642
03fc70cf 1643 rc = OCITransCommit(masterSvcCtx, oraerr, OCI_DEFAULT);
765f22c6 1644
03fc70cf
BH
1645 if (rc == OCI_ERROR) {
1646 throw OracleException("Oracle removeDomainKey COMMIT", oraerr);
765f22c6
BH
1647 }
1648
1649 return true;
1650}
1651
82cc0761
BZ
1652bool
1653OracleBackend::addDomainKey (const DNSName& name, const KeyData& key, int64_t& id)
765f22c6 1654{
71301b6e 1655 if(!d_dnssecQueries)
82cc0761 1656 return false;
71301b6e
PD
1657 DomainInfo di;
1658 if (getDomainInfo(name, di) == false) return false;
1659
03fc70cf
BH
1660 sword rc;
1661 OCIStmt *stmt;
1662
765f22c6
BH
1663 int key_id = -1;
1664 uint16_t key_flags = key.flags;
1665 int key_active = key.active;
1666
03fc70cf
BH
1667 openMasterConnection();
1668
1669 rc = OCITransStart(masterSvcCtx, oraerr, 60, OCI_TRANS_NEW);
765f22c6 1670
03fc70cf
BH
1671 if (rc == OCI_ERROR) {
1672 throw OracleException("Oracle addDomainKey BEGIN", oraerr);
765f22c6
BH
1673 }
1674
e2b3f850 1675 DNSName_to_cbuf(mQueryName, name, sizeof(mQueryName));
765f22c6
BH
1676 string_to_cbuf(mQueryContent, key.content, sizeof(mQueryContent));
1677
03fc70cf 1678 stmt = prepare_query(masterSvcCtx, addZoneKeyQuerySQL, addZoneKeyQueryKey);
765f22c6 1679
03fc70cf
BH
1680 bind_int(stmt, ":keyid", &key_id);
1681 bind_str(stmt, ":name", mQueryName, sizeof(mQueryName));
1682 bind_uint16(stmt, ":flags", &key_flags);
1683 bind_int(stmt, ":active", &key_active);
1684 bind_str(stmt, ":content", mQueryContent, sizeof(mQueryContent));
765f22c6 1685
03fc70cf 1686 rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
765f22c6 1687
03fc70cf
BH
1688 if (rc == OCI_ERROR) {
1689 throw OracleException("Oracle addDomainKey INSERT", oraerr);
765f22c6
BH
1690 }
1691
03fc70cf 1692 release_query(stmt, addZoneKeyQueryKey);
765f22c6 1693
03fc70cf 1694 rc = OCITransCommit(masterSvcCtx, oraerr, OCI_DEFAULT);
765f22c6 1695
03fc70cf
BH
1696 if (rc == OCI_ERROR) {
1697 throw OracleException("Oracle addDomainKey COMMIT", oraerr);
765f22c6
BH
1698 }
1699
82cc0761
BZ
1700 id = key_id;
1701 return key_id >= 0;
765f22c6
BH
1702}
1703
1704bool
ea9586a4 1705OracleBackend::setDomainKeyState (const DNSName& name, unsigned int id, int active)
765f22c6 1706{
71301b6e
PD
1707 if(!d_dnssecQueries)
1708 return -1;
1709 DomainInfo di;
1710 if (getDomainInfo(name, di) == false) return false;
1711
03fc70cf
BH
1712 sword rc;
1713 OCIStmt *stmt;
1714
1715 openMasterConnection();
1716
1717 stmt = prepare_query(masterSvcCtx, setZoneKeyStateQuerySQL, setZoneKeyStateQueryKey);
1718 bind_uint(stmt, ":keyid", &id);
1719 bind_int(stmt, ":active", &active);
765f22c6 1720
03fc70cf 1721 rc = OCITransStart(masterSvcCtx, oraerr, 60, OCI_TRANS_NEW);
765f22c6 1722
03fc70cf
BH
1723 if (rc == OCI_ERROR) {
1724 throw OracleException("Oracle setDomainKeyState BEGIN", oraerr);
765f22c6
BH
1725 }
1726
03fc70cf 1727 rc = OCIStmtExecute(masterSvcCtx, stmt, oraerr, 1, 0, NULL, NULL, OCI_DEFAULT);
765f22c6 1728
03fc70cf
BH
1729 if (rc == OCI_ERROR) {
1730 throw OracleException("Oracle setDomainKeyState UPDATE", oraerr);
765f22c6
BH
1731 }
1732
03fc70cf 1733 rc = OCITransCommit(masterSvcCtx, oraerr, OCI_DEFAULT);
765f22c6 1734
03fc70cf
BH
1735 if (rc == OCI_ERROR) {
1736 throw OracleException("Oracle setDomainKeyState COMMIT", oraerr);
765f22c6
BH
1737 }
1738
03fc70cf 1739 release_query(stmt, setZoneKeyStateQueryKey);
765f22c6
BH
1740 return true;
1741}
1742
1743bool
ea9586a4 1744OracleBackend::activateDomainKey (const DNSName& name, unsigned int id)
765f22c6
BH
1745{
1746 return setDomainKeyState(name, id, 1);
1747}
1748
1749bool
ea9586a4 1750OracleBackend::deactivateDomainKey (const DNSName& name, unsigned int id)
765f22c6
BH
1751{
1752 return setDomainKeyState(name, id, 0);
1753}
1754
1755void
1756OracleBackend::Cleanup ()
1757{
1758 sword err;
1759
03fc70cf
BH
1760 if (masterSvcCtx != NULL) {
1761 err = OCITransRollback(masterSvcCtx, oraerr, OCI_DEFAULT);
765f22c6 1762 // No error check, we don't care if ROLLBACK failed
03fc70cf 1763 err = OCISessionRelease(masterSvcCtx, oraerr, NULL, 0, OCI_DEFAULT);
765f22c6 1764 if (err == OCI_ERROR) {
03fc70cf 1765 throw OracleException("Oracle cleanup, OCISessionRelease (master)", oraerr);
765f22c6 1766 }
03fc70cf
BH
1767 masterSvcCtx = NULL;
1768 OCIHandleFree(masterAuthHandle, OCI_HTYPE_AUTHINFO);
1769 masterAuthHandle = NULL;
765f22c6
BH
1770 }
1771
03fc70cf
BH
1772 if (pooledSvcCtx != NULL) {
1773 err = OCITransRollback(pooledSvcCtx, oraerr, OCI_DEFAULT);
1774 // No error check, we don't care if ROLLBACK failed
1775 err = OCISessionRelease(pooledSvcCtx, oraerr, NULL, 0, OCI_DEFAULT);
1776 if (err == OCI_ERROR) {
1777 throw OracleException("Oracle cleanup, OCISessionRelease (pooled)", oraerr);
1778 }
1779 pooledSvcCtx = NULL;
1780 }
1781
1782 if (oraerr != NULL) {
1783 OCIHandleFree(oraerr, OCI_HTYPE_ERROR);
1784 oraerr = NULL;
765f22c6
BH
1785 }
1786}
1787
1788OCIStmt*
03fc70cf 1789OracleBackend::prepare_query (OCISvcCtx *orasvc, string& code, const char *key)
765f22c6
BH
1790{
1791 sword err;
1792
1793 OCIStmt *handle = NULL;
1794
03fc70cf 1795 err = OCIStmtPrepare2(orasvc, &handle, oraerr, (OraText*) code.c_str(), code.length(), (OraText*) key, strlen(key), OCI_NTV_SYNTAX, OCI_DEFAULT);
765f22c6
BH
1796
1797 if (err == OCI_ERROR) {
03fc70cf 1798 throw OracleException("Preparing Oracle statement", oraerr);
765f22c6
BH
1799 }
1800
1801 return handle;
1802}
1803
1804void
1805OracleBackend::release_query (OCIStmt *stmt, const char *key)
1806{
1807 sword err;
1808
03fc70cf 1809 err = OCIStmtRelease(stmt, oraerr, (OraText*)key, strlen(key), OCI_DEFAULT);
765f22c6
BH
1810
1811 if (err == OCI_ERROR) {
03fc70cf 1812 throw OracleException("Releasing Oracle statement", oraerr);
765f22c6
BH
1813 }
1814}
1815
1816void
1817OracleBackend::define_output_str (OCIStmt *s, ub4 pos, sb2 *ind,
1818 char *buf, sb4 buflen)
1819{
1820 sword err;
1821 OCIDefine *handle = NULL;
1822
03fc70cf 1823 err = OCIDefineByPos(s, &handle, oraerr, pos, buf, buflen, SQLT_STR,
765f22c6
BH
1824 ind, NULL, NULL, OCI_DEFAULT);
1825
1826 if (err == OCI_ERROR) {
03fc70cf 1827 throw OracleException("Defining output for Oracle statement", oraerr);
765f22c6
BH
1828 }
1829}
1830
1831void
1832OracleBackend::define_output_int (OCIStmt *s, ub4 pos, sb2 *ind, int *buf)
1833{
1834 sword err;
1835 OCIDefine *handle = NULL;
1836
03fc70cf 1837 err = OCIDefineByPos(s, &handle, oraerr, pos, buf, sizeof(int),
765f22c6
BH
1838 SQLT_INT, ind, NULL, NULL, OCI_DEFAULT);
1839
1840 if (err == OCI_ERROR) {
03fc70cf 1841 throw OracleException("Defining output for Oracle statement", oraerr);
765f22c6
BH
1842 }
1843}
1844
1845void
1846OracleBackend::define_output_uint (OCIStmt *s, ub4 pos, sb2 *ind, unsigned int *buf)
1847{
1848 sword err;
1849 OCIDefine *handle = NULL;
1850
03fc70cf 1851 err = OCIDefineByPos(s, &handle, oraerr, pos, buf, sizeof(unsigned int),
765f22c6
BH
1852 SQLT_UIN, ind, NULL, NULL, OCI_DEFAULT);
1853
1854 if (err == OCI_ERROR) {
03fc70cf 1855 throw OracleException("Defining output for Oracle statement", oraerr);
765f22c6
BH
1856 }
1857}
1858
1859void
1860OracleBackend::define_output_uint16 (OCIStmt *s, ub4 pos, sb2 *ind,
1861 uint16_t *buf)
1862{
1863 sword err;
1864 OCIDefine *handle = NULL;
1865
03fc70cf 1866 err = OCIDefineByPos(s, &handle, oraerr, pos, buf, sizeof(uint16_t),
765f22c6
BH
1867 SQLT_UIN, ind, NULL, NULL, OCI_DEFAULT);
1868
1869 if (err == OCI_ERROR) {
03fc70cf 1870 throw OracleException("Defining output for Oracle statement", oraerr);
765f22c6
BH
1871 }
1872}
1873
1874void
1875OracleBackend::define_output_uint32 (OCIStmt *s, ub4 pos, sb2 *ind,
1876 uint32_t *buf)
1877{
1878 sword err;
1879 OCIDefine *handle = NULL;
1880
03fc70cf 1881 err = OCIDefineByPos(s, &handle, oraerr, pos, buf, sizeof(uint32_t),
765f22c6
BH
1882 SQLT_UIN, ind, NULL, NULL, OCI_DEFAULT);
1883
1884 if (err == OCI_ERROR) {
03fc70cf 1885 throw OracleException("Defining output for Oracle statement", oraerr);
765f22c6
BH
1886 }
1887}
1888
1889void
1890OracleBackend::check_indicator (sb2 ind, bool null_okay)
1891{
1892 if ((!null_okay) && (ind == -1)) {
1893 throw OracleException("Received NULL where a value was expected");
1894 }
1895
1896 if ((ind < -1) || (ind > 0)) {
1897 throw OracleException("Return value truncated");
1898 }
1899}
1900
1901void
1902OracleBackend::define_fwd_query (OCIStmt *s)
1903{
1904 const ub4 n = 100;
1905 sword err = OCIAttrSet(s, OCI_HTYPE_STMT, (void*) &n, sizeof(ub4),
03fc70cf 1906 OCI_ATTR_PREFETCH_ROWS, oraerr);
765f22c6
BH
1907
1908 if (err == OCI_ERROR) {
03fc70cf 1909 throw OracleException("Activating row prefetching", oraerr);
765f22c6
BH
1910 }
1911
1912 define_output_str(s, 1, &mResultNameInd,
1913 mResultName, sizeof(mResultName));
1914 define_output_uint32(s, 2, &mResultTTLInd, &mResultTTL);
1915 define_output_str(s, 3, &mResultTypeInd,
1916 mResultType, sizeof(mResultType));
1917 define_output_str(s, 4, &mResultContentInd,
1918 mResultContent, sizeof(mResultContent));
1919 define_output_int(s, 5, &mResultZoneIdInd, &mResultZoneId);
1920 define_output_int(s, 6, &mResultLastChangeInd, &mResultLastChange);
71301b6e
PD
1921 if (d_dnssecQueries)
1922 define_output_int(s, 7, &mResultIsAuthInd, &mResultIsAuth);
765f22c6
BH
1923}
1924
1925void
1926OracleBackend::bind_str (OCIStmt *s, const char *name, char *buf, sb4 buflen)
1927{
1928 sword err;
1929 OCIBind *handle = NULL;
1930
03fc70cf 1931 err = OCIBindByName(s, &handle, oraerr,
765f22c6
BH
1932 (OraText*) name, strlen(name),
1933 buf, buflen, SQLT_STR,
1934 NULL, NULL, NULL, 0, NULL,
1935 OCI_DEFAULT);
1936
1937 if (err == OCI_ERROR) {
03fc70cf
BH
1938 string msg;
1939 msg.append("Oracle bind_str (\"");
1940 msg.append(name);
1941 msg.append("\")");
1942 throw OracleException(msg, oraerr);
765f22c6
BH
1943 }
1944}
1945
1946void
1947OracleBackend::bind_str_failokay (OCIStmt *s, const char *name,
1948 char *buf, sb4 buflen)
1949{
1950 sword err;
1951 OCIBind *handle = NULL;
1952
03fc70cf 1953 err = OCIBindByName(s, &handle, oraerr,
765f22c6
BH
1954 (OraText*) name, strlen(name),
1955 buf, buflen, SQLT_STR,
1956 NULL, NULL, NULL, 0, NULL,
1957 OCI_DEFAULT);
1958
1959 (void)err;
1960}
1961
1962void
1963OracleBackend::bind_str_ind (OCIStmt *s, const char *name,
1964 char *buf, sb4 buflen, sb2 *ind)
1965{
1966 sword err;
1967 OCIBind *handle = NULL;
1968
03fc70cf 1969 err = OCIBindByName(s, &handle, oraerr,
765f22c6
BH
1970 (OraText*) name, strlen(name),
1971 buf, buflen, SQLT_STR,
1972 ind, NULL, NULL, 0, NULL,
1973 OCI_DEFAULT);
1974
1975 if (err == OCI_ERROR) {
03fc70cf
BH
1976 string msg;
1977 msg.append("Oracle bind_str_ind (\"");
1978 msg.append(name);
1979 msg.append("\")");
1980 throw OracleException(msg, oraerr);
765f22c6
BH
1981 }
1982}
1983
1984void
1985OracleBackend::bind_int (OCIStmt *s, const char *name, int *buf)
1986{
1987 sword err;
1988 OCIBind *handle = NULL;
1989
03fc70cf 1990 err = OCIBindByName(s, &handle, oraerr,
765f22c6
BH
1991 (OraText*) name, strlen(name),
1992 buf, sizeof(int), SQLT_INT,
1993 NULL, NULL, NULL, 0, NULL,
1994 OCI_DEFAULT);
1995
1996 if (err == OCI_ERROR) {
03fc70cf
BH
1997 string msg;
1998 msg.append("Oracle bind_int (\"");
1999 msg.append(name);
2000 msg.append("\")");
2001 throw OracleException(msg, oraerr);
765f22c6
BH
2002 }
2003}
2004
2005void
2006OracleBackend::bind_uint (OCIStmt *s, const char *name, unsigned int *buf)
2007{
2008 sword err;
2009 OCIBind *handle = NULL;
2010
03fc70cf 2011 err = OCIBindByName(s, &handle, oraerr,
765f22c6
BH
2012 (OraText*) name, strlen(name),
2013 buf, sizeof(unsigned int), SQLT_UIN,
2014 NULL, NULL, NULL, 0, NULL,
2015 OCI_DEFAULT);
2016
2017 if (err == OCI_ERROR) {
03fc70cf
BH
2018 string msg;
2019 msg.append("Oracle bind_uint (\"");
2020 msg.append(name);
2021 msg.append("\")");
2022 throw OracleException(msg, oraerr);
765f22c6
BH
2023 }
2024}
2025
2026void
2027OracleBackend::bind_uint16 (OCIStmt *s, const char *name, uint16_t *buf)
2028{
2029 sword err;
2030 OCIBind *handle = NULL;
2031
03fc70cf 2032 err = OCIBindByName(s, &handle, oraerr,
765f22c6
BH
2033 (OraText*) name, strlen(name),
2034 buf, sizeof(uint16_t), SQLT_UIN,
2035 NULL, NULL, NULL, 0, NULL,
2036 OCI_DEFAULT);
2037
2038 if (err == OCI_ERROR) {
03fc70cf
BH
2039 string msg;
2040 msg.append("Oracle bind_uint16 (\"");
2041 msg.append(name);
2042 msg.append("\")");
2043 throw OracleException(msg, oraerr);
765f22c6
BH
2044 }
2045}
2046
2047void
2048OracleBackend::bind_uint16_ind (OCIStmt *s, const char *name, uint16_t *buf,
2049 sb2 *ind)
2050{
2051 sword err;
2052 OCIBind *handle = NULL;
2053
03fc70cf 2054 err = OCIBindByName(s, &handle, oraerr,
765f22c6
BH
2055 (OraText*) name, strlen(name),
2056 buf, sizeof(uint16_t), SQLT_UIN,
2057 ind, NULL, NULL, 0, NULL,
2058 OCI_DEFAULT);
2059
2060 if (err == OCI_ERROR) {
03fc70cf
BH
2061 string msg;
2062 msg.append("Oracle bind_uint16_ind (\"");
2063 msg.append(name);
2064 msg.append("\")");
2065 throw OracleException(msg, oraerr);
765f22c6
BH
2066 }
2067}
2068
2069void
2070OracleBackend::bind_uint32 (OCIStmt *s, const char *name, uint32_t *buf)
2071{
2072 sword err;
2073 OCIBind *handle = NULL;
2074
03fc70cf 2075 err = OCIBindByName(s, &handle, oraerr,
765f22c6
BH
2076 (OraText*) name, strlen(name),
2077 buf, sizeof(uint32_t), SQLT_UIN,
2078 NULL, NULL, NULL, 0, NULL,
2079 OCI_DEFAULT);
2080
2081 if (err == OCI_ERROR) {
03fc70cf
BH
2082 string msg;
2083 msg.append("Oracle bind_uint32 (\"");
2084 msg.append(name);
2085 msg.append("\")");
2086 throw OracleException(msg, oraerr);
765f22c6
BH
2087 }
2088}
2089
2090
2091class OracleFactory : public BackendFactory
2092{
2093private:
2094 pthread_mutex_t factoryLock;
03fc70cf
BH
2095 OCIEnv *oraenv;
2096 OCIError *oraerr;
765f22c6
BH
2097 OCISPool *mSessionPoolHandle;
2098 text *mSessionPoolName;
2099 ub4 mSessionPoolNameLen;
2100
2101 void CreateSessionPool ()
2102 {
2103 sword err;
2104
2105 try {
92ba4415 2106 // set some environment variables
8ac0c064
PD
2107 setenv("ORACLE_HOME", arg()["oracle-home"].c_str(), 1);
2108 setenv("ORACLE_SID", arg()["oracle-sid"].c_str(), 1);
2109 setenv("NLS_LANG", arg()["oracle-nls-lang"].c_str(), 1);
2110
765f22c6 2111 // Initialize and create the environment
03fc70cf 2112 err = OCIEnvCreate(&oraenv, OCI_THREADED, NULL, NULL,
765f22c6
BH
2113 NULL, NULL, 0, NULL);
2114 if (err == OCI_ERROR) {
2115 throw OracleException("OCIEnvCreate");
ae4e0030 2116 }
765f22c6 2117 // Allocate an error handle
03fc70cf 2118 err = OCIHandleAlloc(oraenv, (void**) &oraerr,
765f22c6
BH
2119 OCI_HTYPE_ERROR, 0, NULL);
2120 if (err == OCI_ERROR) {
2121 throw OracleException("OCIHandleAlloc");
ae4e0030 2122 }
765f22c6 2123
03fc70cf
BH
2124 const char *dbname = arg()["oracle-pool-database"].c_str();
2125 const char *dbuser = arg()["oracle-pool-username"].c_str();
2126 const char *dbpass = arg()["oracle-pool-password"].c_str();
765f22c6
BH
2127
2128 ub4 sess_min = arg().asNum("oracle-session-min");
2129 ub4 sess_max = arg().asNum("oracle-session-max");
2130 ub4 sess_inc = arg().asNum("oracle-session-inc");
03fc70cf 2131 ub4 get_mode = OCI_SPOOL_ATTRVAL_NOWAIT;
765f22c6
BH
2132
2133 // Create a session pool
03fc70cf 2134 err = OCIHandleAlloc(oraenv, (void**) &mSessionPoolHandle,
765f22c6
BH
2135 OCI_HTYPE_SPOOL, 0, NULL);
2136 if (err == OCI_ERROR) {
2137 throw OracleException("OCIHandleAlloc");
ae4e0030 2138 }
03fc70cf 2139 err = OCISessionPoolCreate(oraenv, oraerr,
765f22c6
BH
2140 mSessionPoolHandle,
2141 (OraText **) &mSessionPoolName,
2142 &mSessionPoolNameLen,
2143 (OraText *) dbname, strlen(dbname),
2144 sess_min, sess_max, sess_inc,
2145 (OraText *) dbuser, strlen(dbuser),
2146 (OraText *) dbpass, strlen(dbpass),
2147 OCI_SPC_STMTCACHE | OCI_SPC_HOMOGENEOUS);
2148 if (err == OCI_ERROR) {
03fc70cf
BH
2149 throw OracleException("Creating Oracle session pool", oraerr);
2150 }
2151
2152 // Set session pool NOWAIT
2153 err = OCIAttrSet(mSessionPoolHandle, OCI_HTYPE_SPOOL, &get_mode, 0, OCI_ATTR_SPOOL_GETMODE, oraerr);
2154 if (err == OCI_ERROR) {
2155 throw OracleException("Setting session pool get mode", oraerr);
ae4e0030 2156 }
765f22c6 2157 } catch (OracleException &theException) {
e6a9dde5 2158 g_log << Logger::Critical << "OracleFactory: "
765f22c6
BH
2159 << theException.reason << endl;
2160 Cleanup();
2161 throw theException;
ae4e0030 2162 }
765f22c6
BH
2163 }
2164
2165 void Cleanup ()
2166 {
2167 sword err;
2168
2169 if (mSessionPoolHandle != NULL) {
2170 try {
03fc70cf 2171 err = OCISessionPoolDestroy(mSessionPoolHandle, oraerr,
765f22c6
BH
2172 OCI_SPD_FORCE);
2173 OCIHandleFree(mSessionPoolHandle, OCI_HTYPE_SPOOL);
2174 mSessionPoolHandle = NULL;
2175 if (err == OCI_ERROR) {
03fc70cf 2176 throw OracleException("OCISessionPoolDestroy", oraerr);
765f22c6
BH
2177 }
2178 } catch (OracleException &theException) {
e6a9dde5 2179 g_log << Logger::Error << "Failed to destroy Oracle session pool: "
765f22c6 2180 << theException.reason << endl;
ae4e0030 2181 }
765f22c6 2182 }
ae4e0030 2183
03fc70cf
BH
2184 if (oraerr != NULL) {
2185 OCIHandleFree(oraerr, OCI_HTYPE_ERROR);
2186 oraerr = NULL;
765f22c6
BH
2187 }
2188
03fc70cf
BH
2189 if (oraenv != NULL) {
2190 OCIHandleFree(oraenv, OCI_HTYPE_ENV);
2191 oraenv = NULL;
765f22c6
BH
2192 }
2193 }
2194
2195public:
2196
2197OracleFactory () : BackendFactory("oracle") {
2198 pthread_mutex_init(&factoryLock, NULL);
03fc70cf
BH
2199 oraenv = NULL;
2200 oraerr = NULL;
765f22c6
BH
2201 mSessionPoolHandle = NULL;
2202 mSessionPoolName = NULL;
2203 mSessionPoolNameLen = 0;
2204 }
2205
2206 ~OracleFactory () {
2207 Cleanup();
2208 pthread_mutex_destroy(&factoryLock);
2209 }
2210
2211 void declareArguments (const string & suffix = "") {
8ac0c064
PD
2212 declare(suffix,"home", "Oracle home path", "");
2213 declare(suffix,"sid", "Oracle sid", "XE");
2214 declare(suffix,"nls-lang", "Oracle language", "AMERICAN_AMERICA.AL32UTF8");
2215
03fc70cf
BH
2216 declare(suffix, "pool-database", "Database to connect to for the session pool", "powerdns");
2217 declare(suffix, "pool-username", "Username to connect as for the session pool", "powerdns");
2218 declare(suffix, "pool-password", "Password to connect with for the session pool", "");
2219 declare(suffix, "session-min", "Number of sessions to open at startup", "4");
2220 declare(suffix, "session-inc", "Number of sessions to open when growing", "2");
2221 declare(suffix, "session-max", "Max number of sessions to have open", "20");
2222 declare(suffix, "master-database", "Database to connect to for write access", "powerdns");
2223 declare(suffix, "master-username", "Username to connect as for write access", "powerdns");
2224 declare(suffix, "master-password", "Password to connect with for write access", "");
71301b6e 2225 declare(suffix, "dnssec", "Assume DNSSEC Schema is in place", "no");
765f22c6
BH
2226 declare(suffix, "nameserver-name", "", "");
2227
2228 declare(suffix, "basic-query", "", basicQueryDefaultSQL);
71301b6e 2229 declare(suffix, "basic-query-auth", "", basicQueryDefaultAuthSQL);
765f22c6 2230 declare(suffix, "basic-id-query", "", basicIdQueryDefaultSQL);
71301b6e 2231 declare(suffix, "basic-id-query-auth", "", basicIdQueryDefaultAuthSQL);
765f22c6 2232 declare(suffix, "any-query", "", anyQueryDefaultSQL);
71301b6e 2233 declare(suffix, "any-query-auth", "", anyQueryDefaultAuthSQL);
765f22c6 2234 declare(suffix, "any-id-query", "", anyIdQueryDefaultSQL);
71301b6e 2235 declare(suffix, "any-id-query-auth", "", anyIdQueryDefaultAuthSQL);
765f22c6 2236 declare(suffix, "list-query", "", listQueryDefaultSQL);
71301b6e 2237 declare(suffix, "list-query-auth", "", listQueryDefaultAuthSQL);
765f22c6
BH
2238 declare(suffix, "zone-info-query", "", zoneInfoQueryDefaultSQL);
2239 declare(suffix, "also-notify-query", "", alsoNotifyQueryDefaultSQL);
765f22c6
BH
2240 declare(suffix, "zone-masters-query", "", zoneMastersQueryDefaultSQL);
2241 declare(suffix, "is-zone-master-query", "", isZoneMasterQueryDefaultSQL);
2242 declare(suffix, "delete-zone-query", "", deleteZoneQueryDefaultSQL);
2243 declare(suffix, "zone-set-last-check-query", "", zoneSetLastCheckQueryDefaultSQL);
2244 declare(suffix, "zone-set-notified-serial-query", "", zoneSetNotifiedSerialQueryDefaultSQL);
2245 declare(suffix, "insert-record-query", "", insertRecordQueryDefaultSQL);
03fc70cf 2246 declare(suffix, "finalize-axfr-query", "", finalizeAXFRQueryDefaultSQL);
765f22c6
BH
2247 declare(suffix, "unfresh-zones-query", "", unfreshZonesQueryDefaultSQL);
2248 declare(suffix, "updated-masters-query", "", updatedMastersQueryDefaultSQL);
2249 declare(suffix, "accept-supernotification-query", "", acceptSupernotificationQueryDefaultSQL);
2250 declare(suffix, "insert-slave-query", "", insertSlaveQueryDefaultSQL);
2251 declare(suffix, "insert-master-query", "", insertMasterQueryDefaultSQL);
2252 declare(suffix, "prev-next-name-query", "", prevNextNameQueryDefaultSQL);
2253 declare(suffix, "prev-next-hash-query", "", prevNextHashQueryDefaultSQL);
2254
cdbf24f6 2255 declare(suffix, "get-all-zone-metadata-query", "", getAllZoneMetadataQueryDefaultSQL);
765f22c6
BH
2256 declare(suffix, "get-zone-metadata-query", "", getZoneMetadataQueryDefaultSQL);
2257 declare(suffix, "del-zone-metadata-query", "", delZoneMetadataQueryDefaultSQL);
2258 declare(suffix, "set-zone-metadata-query", "", setZoneMetadataQueryDefaultSQL);
2259
03fc70cf 2260 declare(suffix, "get-tsig-key-query", "", getTSIGKeyQueryDefaultSQL);
672d2e89 2261 declare(suffix, "del-tsig-key-query", "", delTSIGKeyQueryDefaultSQL);
911c3aa7 2262 declare(suffix, "set-tsig-key-query", "", setTSIGKeyQueryDefaultSQL);
911c3aa7 2263 declare(suffix, "get-tsig-keys-query", "", getTSIGKeysQueryDefaultSQL);
672d2e89 2264
765f22c6
BH
2265 declare(suffix, "get-zone-keys-query", "", getZoneKeysQueryDefaultSQL);
2266 declare(suffix, "del-zone-key-query", "", delZoneKeyQueryDefaultSQL);
2267 declare(suffix, "add-zone-key-query", "", addZoneKeyQueryDefaultSQL);
2268 declare(suffix, "set-zone-key-state-query", "", setZoneKeyStateQueryDefaultSQL);
2269 }
2270
2271 DNSBackend *make (const string & suffix = "") {
2272 {
2273 Lock l(&factoryLock);
03fc70cf 2274 if (oraenv == NULL) {
765f22c6 2275 CreateSessionPool();
ae4e0030 2276 }
765f22c6 2277 }
03fc70cf 2278 return new OracleBackend(suffix, oraenv,
765f22c6
BH
2279 (char *) mSessionPoolName);
2280 }
ae4e0030 2281
ae4e0030
BH
2282};
2283
2284
2285//! Magic class that is activated when the dynamic library is loaded
2286class OracleLoader
2287{
765f22c6
BH
2288public:
2289
2290 OracleLoader()
2291 {
2292 BackendMakers().report(new OracleFactory);
e6a9dde5 2293 g_log << Logger::Info << "[oraclebackend] This is the oracle backend version " VERSION
5e6a3d93
PL
2294#ifndef REPRODUCIBLE
2295 << " (" __DATE__ " " __TIME__ ")"
2296#endif
2297 << " reporting" << endl;
765f22c6
BH
2298 }
2299
ae4e0030 2300};
765f22c6 2301
ae4e0030 2302static OracleLoader loader;
765f22c6
BH
2303
2304/* vi: set sw=2 et : */