]>
Commit | Line | Data |
---|---|---|
0ea9281e | 1 | /* |
12471842 PL |
2 | * This file is part of PowerDNS or dnsdist. |
3 | * Copyright -- PowerDNS.COM B.V. and its contributors | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of version 2 of the GNU General Public License as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * In addition, for the avoidance of any doubt, permission is granted to | |
10 | * link this program with OpenSSL and to (re)distribute the binaries | |
11 | * produced as the result of such linking. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
21 | */ | |
870a0fe4 AT |
22 | #ifdef HAVE_CONFIG_H |
23 | #include "config.h" | |
24 | #endif | |
b4ce8b4e BH |
25 | #include "pdns/dns.hh" |
26 | #include "pdns/dnsbackend.hh" | |
27 | #include "gsqlbackend.hh" | |
28 | #include "pdns/dnspacket.hh" | |
5c409fa2 | 29 | #include "pdns/pdnsexception.hh" |
b4ce8b4e BH |
30 | #include "pdns/logger.hh" |
31 | #include "pdns/arguments.hh" | |
f9cf6d92 KM |
32 | #include "pdns/base32.hh" |
33 | #include "pdns/dnssecinfra.hh" | |
f7df9b0f | 34 | #include <boost/algorithm/string.hpp> |
b4ce8b4e | 35 | #include <sstream> |
f7bcc763 | 36 | #include <boost/format.hpp> |
0f310932 | 37 | #include <boost/scoped_ptr.hpp> |
78bcb858 | 38 | |
63be3701 | 39 | #define ASSERT_ROW_COLUMNS(query, row, num) { if (row.size() != num) { throw PDNSException(std::string(query) + " returned wrong number of columns, expected " #num ", got " + std::to_string(row.size())); } } |
7c779a31 | 40 | |
0f310932 AT |
41 | GSQLBackend::GSQLBackend(const string &mode, const string &suffix) |
42 | { | |
43 | setArgPrefix(mode+suffix); | |
44 | d_db=0; | |
45 | d_logprefix="["+mode+"Backend"+suffix+"] "; | |
46 | ||
47 | try | |
48 | { | |
49 | d_dnssecQueries = mustDo("dnssec"); | |
50 | } | |
51 | catch (ArgException e) | |
52 | { | |
53 | d_dnssecQueries = false; | |
54 | } | |
55 | ||
56 | d_NoIdQuery=getArg("basic-query"); | |
57 | d_IdQuery=getArg("id-query"); | |
58 | d_ANYNoIdQuery=getArg("any-query"); | |
59 | d_ANYIdQuery=getArg("any-id-query"); | |
60 | ||
61 | d_listQuery=getArg("list-query"); | |
62 | d_listSubZoneQuery=getArg("list-subzone-query"); | |
63 | ||
0f310932 AT |
64 | d_InfoOfDomainsZoneQuery=getArg("info-zone-query"); |
65 | d_InfoOfAllSlaveDomainsQuery=getArg("info-all-slaves-query"); | |
66 | d_SuperMasterInfoQuery=getArg("supermaster-query"); | |
67 | d_GetSuperMasterIPs=getArg("supermaster-name-to-ips"); | |
68 | d_InsertZoneQuery=getArg("insert-zone-query"); | |
0f310932 | 69 | d_InsertRecordQuery=getArg("insert-record-query"); |
0f310932 AT |
70 | d_UpdateMasterOfZoneQuery=getArg("update-master-query"); |
71 | d_UpdateKindOfZoneQuery=getArg("update-kind-query"); | |
72 | d_UpdateSerialOfZoneQuery=getArg("update-serial-query"); | |
73 | d_UpdateLastCheckofZoneQuery=getArg("update-lastcheck-query"); | |
79532aa7 | 74 | d_UpdateAccountOfZoneQuery=getArg("update-account-query"); |
0f310932 AT |
75 | d_ZoneLastChangeQuery=getArg("zone-lastchange-query"); |
76 | d_InfoOfAllMasterDomainsQuery=getArg("info-all-master-query"); | |
77 | d_DeleteDomainQuery=getArg("delete-domain-query"); | |
78 | d_DeleteZoneQuery=getArg("delete-zone-query"); | |
79 | d_DeleteRRSetQuery=getArg("delete-rrset-query"); | |
80 | d_DeleteNamesQuery=getArg("delete-names-query"); | |
81 | d_getAllDomainsQuery=getArg("get-all-domains-query"); | |
82 | ||
09070ce7 PL |
83 | d_InsertEmptyNonTerminalOrderQuery=getArg("insert-empty-non-terminal-order-query"); |
84 | d_DeleteEmptyNonTerminalQuery = getArg("delete-empty-non-terminal-query"); | |
85 | d_RemoveEmptyNonTerminalsFromZoneQuery = getArg("remove-empty-non-terminals-from-zone-query"); | |
de43ec0f | 86 | |
0f310932 AT |
87 | d_ListCommentsQuery = getArg("list-comments-query"); |
88 | d_InsertCommentQuery = getArg("insert-comment-query"); | |
89 | d_DeleteCommentRRsetQuery = getArg("delete-comment-rrset-query"); | |
90 | d_DeleteCommentsQuery = getArg("delete-comments-query"); | |
91 | ||
0f310932 AT |
92 | d_firstOrderQuery = getArg("get-order-first-query"); |
93 | d_beforeOrderQuery = getArg("get-order-before-query"); | |
94 | d_afterOrderQuery = getArg("get-order-after-query"); | |
95 | d_lastOrderQuery = getArg("get-order-last-query"); | |
79de0a80 KM |
96 | |
97 | d_updateOrderNameAndAuthQuery = getArg("update-ordername-and-auth-query"); | |
98 | d_updateOrderNameAndAuthTypeQuery = getArg("update-ordername-and-auth-type-query"); | |
0f310932 | 99 | d_nullifyOrderNameAndUpdateAuthQuery = getArg("nullify-ordername-and-update-auth-query"); |
79de0a80 | 100 | d_nullifyOrderNameAndUpdateAuthTypeQuery = getArg("nullify-ordername-and-update-auth-type-query"); |
0f310932 AT |
101 | |
102 | d_AddDomainKeyQuery = getArg("add-domain-key-query"); | |
63de5311 | 103 | d_GetLastInsertedKeyIdQuery = getArg("get-last-inserted-key-id-query"); |
0f310932 AT |
104 | d_ListDomainKeysQuery = getArg("list-domain-keys-query"); |
105 | ||
106 | d_GetAllDomainMetadataQuery = getArg("get-all-domain-metadata-query"); | |
107 | d_GetDomainMetadataQuery = getArg("get-domain-metadata-query"); | |
108 | d_ClearDomainMetadataQuery = getArg("clear-domain-metadata-query"); | |
109 | d_ClearDomainAllMetadataQuery = getArg("clear-domain-all-metadata-query"); | |
110 | d_SetDomainMetadataQuery = getArg("set-domain-metadata-query"); | |
111 | ||
112 | d_ActivateDomainKeyQuery = getArg("activate-domain-key-query"); | |
113 | d_DeactivateDomainKeyQuery = getArg("deactivate-domain-key-query"); | |
114 | d_RemoveDomainKeyQuery = getArg("remove-domain-key-query"); | |
115 | d_ClearDomainAllKeysQuery = getArg("clear-domain-all-keys-query"); | |
116 | ||
117 | d_getTSIGKeyQuery = getArg("get-tsig-key-query"); | |
118 | d_setTSIGKeyQuery = getArg("set-tsig-key-query"); | |
119 | d_deleteTSIGKeyQuery = getArg("delete-tsig-key-query"); | |
120 | d_getTSIGKeysQuery = getArg("get-tsig-keys-query"); | |
121 | ||
474cacfa AT |
122 | d_SearchRecordsQuery = getArg("search-records-query"); |
123 | d_SearchCommentsQuery = getArg("search-comments-query"); | |
124 | ||
1750b440 | 125 | d_query_stmt = NULL; |
0f310932 AT |
126 | d_NoIdQuery_stmt = NULL; |
127 | d_IdQuery_stmt = NULL; | |
128 | d_ANYNoIdQuery_stmt = NULL; | |
129 | d_ANYIdQuery_stmt = NULL; | |
130 | d_listQuery_stmt = NULL; | |
131 | d_listSubZoneQuery_stmt = NULL; | |
0f310932 AT |
132 | d_InfoOfDomainsZoneQuery_stmt = NULL; |
133 | d_InfoOfAllSlaveDomainsQuery_stmt = NULL; | |
134 | d_SuperMasterInfoQuery_stmt = NULL; | |
135 | d_GetSuperMasterIPs_stmt = NULL; | |
136 | d_InsertZoneQuery_stmt = NULL; | |
0f310932 | 137 | d_InsertRecordQuery_stmt = NULL; |
09070ce7 | 138 | d_InsertEmptyNonTerminalOrderQuery_stmt = NULL; |
0f310932 AT |
139 | d_UpdateMasterOfZoneQuery_stmt = NULL; |
140 | d_UpdateKindOfZoneQuery_stmt = NULL; | |
141 | d_UpdateSerialOfZoneQuery_stmt = NULL; | |
142 | d_UpdateLastCheckofZoneQuery_stmt = NULL; | |
79532aa7 | 143 | d_UpdateAccountOfZoneQuery_stmt = NULL; |
0f310932 AT |
144 | d_InfoOfAllMasterDomainsQuery_stmt = NULL; |
145 | d_DeleteDomainQuery_stmt = NULL; | |
146 | d_DeleteZoneQuery_stmt = NULL; | |
147 | d_DeleteRRSetQuery_stmt = NULL; | |
148 | d_DeleteNamesQuery_stmt = NULL; | |
149 | d_ZoneLastChangeQuery_stmt = NULL; | |
150 | d_firstOrderQuery_stmt = NULL; | |
151 | d_beforeOrderQuery_stmt = NULL; | |
152 | d_afterOrderQuery_stmt = NULL; | |
153 | d_lastOrderQuery_stmt = NULL; | |
79de0a80 KM |
154 | d_updateOrderNameAndAuthQuery_stmt = NULL; |
155 | d_updateOrderNameAndAuthTypeQuery_stmt = NULL; | |
0f310932 | 156 | d_nullifyOrderNameAndUpdateAuthQuery_stmt = NULL; |
79de0a80 | 157 | d_nullifyOrderNameAndUpdateAuthTypeQuery_stmt = NULL; |
09070ce7 PL |
158 | d_RemoveEmptyNonTerminalsFromZoneQuery_stmt = NULL; |
159 | d_DeleteEmptyNonTerminalQuery_stmt = NULL; | |
0f310932 | 160 | d_AddDomainKeyQuery_stmt = NULL; |
63de5311 | 161 | d_GetLastInsertedKeyIdQuery_stmt = NULL; |
0f310932 AT |
162 | d_ListDomainKeysQuery_stmt = NULL; |
163 | d_GetAllDomainMetadataQuery_stmt = NULL; | |
164 | d_GetDomainMetadataQuery_stmt = NULL; | |
165 | d_ClearDomainMetadataQuery_stmt = NULL; | |
166 | d_ClearDomainAllMetadataQuery_stmt = NULL; | |
167 | d_SetDomainMetadataQuery_stmt = NULL; | |
168 | d_RemoveDomainKeyQuery_stmt = NULL; | |
169 | d_ActivateDomainKeyQuery_stmt = NULL; | |
170 | d_DeactivateDomainKeyQuery_stmt = NULL; | |
171 | d_ClearDomainAllKeysQuery_stmt = NULL; | |
172 | d_getTSIGKeyQuery_stmt = NULL; | |
173 | d_setTSIGKeyQuery_stmt = NULL; | |
174 | d_deleteTSIGKeyQuery_stmt = NULL; | |
175 | d_getTSIGKeysQuery_stmt = NULL; | |
176 | d_getAllDomainsQuery_stmt = NULL; | |
177 | d_ListCommentsQuery_stmt = NULL; | |
178 | d_InsertCommentQuery_stmt = NULL; | |
179 | d_DeleteCommentRRsetQuery_stmt = NULL; | |
180 | d_DeleteCommentsQuery_stmt = NULL; | |
474cacfa AT |
181 | d_SearchRecordsQuery_stmt = NULL; |
182 | d_SearchCommentsQuery_stmt = NULL; | |
d2dbd785 | 183 | } |
b4ce8b4e | 184 | |
092f210a | 185 | void GSQLBackend::setNotified(uint32_t domain_id, uint32_t serial) |
b4ce8b4e BH |
186 | { |
187 | try { | |
45d36933 RG |
188 | reconnectIfNeeded(); |
189 | ||
0f310932 AT |
190 | d_UpdateSerialOfZoneQuery_stmt-> |
191 | bind("serial", serial)-> | |
192 | bind("domain_id", domain_id)-> | |
193 | execute()-> | |
194 | reset(); | |
b4ce8b4e BH |
195 | } |
196 | catch(SSqlException &e) { | |
63be3701 | 197 | throw PDNSException("GSQLBackend unable to refresh domain_id "+itoa(domain_id)+": "+e.txtReason()); |
b4ce8b4e BH |
198 | } |
199 | } | |
200 | ||
092f210a | 201 | void GSQLBackend::setFresh(uint32_t domain_id) |
b4ce8b4e BH |
202 | { |
203 | try { | |
45d36933 RG |
204 | reconnectIfNeeded(); |
205 | ||
0f310932 AT |
206 | d_UpdateLastCheckofZoneQuery_stmt-> |
207 | bind("last_check", time(0))-> | |
208 | bind("domain_id", domain_id)-> | |
209 | execute()-> | |
210 | reset(); | |
b4ce8b4e BH |
211 | } |
212 | catch (SSqlException &e) { | |
63be3701 | 213 | throw PDNSException("GSQLBackend unable to refresh domain_id "+itoa(domain_id)+": "+e.txtReason()); |
b4ce8b4e BH |
214 | } |
215 | } | |
216 | ||
223d3559 | 217 | bool GSQLBackend::setMaster(const DNSName &domain, const string &ip) |
c02f13ef | 218 | { |
c02f13ef | 219 | try { |
45d36933 RG |
220 | reconnectIfNeeded(); |
221 | ||
0f310932 AT |
222 | d_UpdateMasterOfZoneQuery_stmt-> |
223 | bind("master", ip)-> | |
223d3559 | 224 | bind("domain", domain)-> |
0f310932 AT |
225 | execute()-> |
226 | reset(); | |
c02f13ef CH |
227 | } |
228 | catch (SSqlException &e) { | |
2042adf5 | 229 | throw PDNSException("GSQLBackend unable to set master of domain '"+domain.toLogString()+"': "+e.txtReason()); |
c02f13ef CH |
230 | } |
231 | return true; | |
232 | } | |
233 | ||
223d3559 | 234 | bool GSQLBackend::setKind(const DNSName &domain, const DomainInfo::DomainKind kind) |
c02f13ef | 235 | { |
c02f13ef | 236 | try { |
45d36933 RG |
237 | reconnectIfNeeded(); |
238 | ||
0f310932 AT |
239 | d_UpdateKindOfZoneQuery_stmt-> |
240 | bind("kind", toUpper(DomainInfo::getKindString(kind)))-> | |
223d3559 | 241 | bind("domain", domain)-> |
0f310932 AT |
242 | execute()-> |
243 | reset(); | |
c02f13ef CH |
244 | } |
245 | catch (SSqlException &e) { | |
2042adf5 | 246 | throw PDNSException("GSQLBackend unable to set kind of domain '"+domain.toLogString()+"': "+e.txtReason()); |
c02f13ef CH |
247 | } |
248 | return true; | |
249 | } | |
250 | ||
223d3559 | 251 | bool GSQLBackend::setAccount(const DNSName &domain, const string &account) |
79532aa7 CH |
252 | { |
253 | try { | |
45d36933 RG |
254 | reconnectIfNeeded(); |
255 | ||
79532aa7 CH |
256 | d_UpdateAccountOfZoneQuery_stmt-> |
257 | bind("account", account)-> | |
223d3559 | 258 | bind("domain", domain)-> |
79532aa7 CH |
259 | execute()-> |
260 | reset(); | |
261 | } | |
262 | catch (SSqlException &e) { | |
2042adf5 | 263 | throw PDNSException("GSQLBackend unable to set account of domain '"+domain.toLogString()+"': "+e.txtReason()); |
79532aa7 CH |
264 | } |
265 | return true; | |
266 | } | |
267 | ||
47bddbb7 | 268 | bool GSQLBackend::getDomainInfo(const DNSName &domain, DomainInfo &di, bool getSerial) |
b4ce8b4e | 269 | { |
85b8554f | 270 | /* fill DomainInfo from database info: |
8ffb7a9b | 271 | id,name,master IP(s),last_check,notified_serial,type,account */ |
b4ce8b4e | 272 | try { |
45d36933 RG |
273 | reconnectIfNeeded(); |
274 | ||
0f310932 | 275 | d_InfoOfDomainsZoneQuery_stmt-> |
8f126bc1 | 276 | bind("domain", domain)-> |
0f310932 AT |
277 | execute()-> |
278 | getResult(d_result)-> | |
279 | reset(); | |
b4ce8b4e BH |
280 | } |
281 | catch(SSqlException &e) { | |
63be3701 | 282 | throw PDNSException("GSQLBackend unable to retrieve information about a domain: "+e.txtReason()); |
b4ce8b4e BH |
283 | } |
284 | ||
285 | int numanswers=d_result.size(); | |
286 | if(!numanswers) | |
287 | return false; | |
7c779a31 AT |
288 | |
289 | ASSERT_ROW_COLUMNS("info-zone-query", d_result[0], 7); | |
290 | ||
955e760a | 291 | di.id=pdns_stou(d_result[0][0]); |
8408d2a6 KM |
292 | try { |
293 | di.zone=DNSName(d_result[0][1]); | |
294 | } catch (...) { | |
295 | return false; | |
296 | } | |
d622042f | 297 | vector<string> masters; |
298 | stringtok(masters, d_result[0][2], " ,\t"); | |
299 | for(const auto& m : masters) | |
300 | di.masters.emplace_back(m, 53); | |
955e760a AT |
301 | di.last_check=pdns_stou(d_result[0][3]); |
302 | di.notified_serial = pdns_stou(d_result[0][4]); | |
326a1978 | 303 | string type=d_result[0][5]; |
8ffb7a9b | 304 | di.account=d_result[0][6]; |
b4ce8b4e | 305 | di.backend=this; |
85b8554f CH |
306 | |
307 | di.serial = 0; | |
47bddbb7 KM |
308 | if(getSerial) { |
309 | try { | |
310 | SOAData sd; | |
311 | if(!getSOA(domain, sd)) | |
312 | g_log<<Logger::Notice<<"No serial for '"<<domain<<"' found - zone is missing?"<<endl; | |
313 | else | |
314 | di.serial = sd.serial; | |
315 | } | |
316 | catch(PDNSException &ae){ | |
317 | g_log<<Logger::Error<<"Error retrieving serial for '"<<domain<<"': "<<ae.reason<<endl; | |
318 | } | |
85b8554f CH |
319 | } |
320 | ||
76979e74 | 321 | di.kind = DomainInfo::stringToKind(type); |
85b8554f | 322 | |
b4ce8b4e BH |
323 | return true; |
324 | } | |
325 | ||
326 | void GSQLBackend::getUnfreshSlaveInfos(vector<DomainInfo> *unfreshDomains) | |
327 | { | |
328 | /* list all domains that need refreshing for which we are slave, and insert into SlaveDomain: | |
329 | id,name,master IP,serial */ | |
b4ce8b4e | 330 | try { |
45d36933 RG |
331 | reconnectIfNeeded(); |
332 | ||
0f310932 AT |
333 | d_InfoOfAllSlaveDomainsQuery_stmt-> |
334 | execute()-> | |
335 | getResult(d_result)-> | |
336 | reset(); | |
b4ce8b4e BH |
337 | } |
338 | catch (SSqlException &e) { | |
63be3701 | 339 | throw PDNSException("GSQLBackend unable to retrieve list of slave domains: "+e.txtReason()); |
b4ce8b4e BH |
340 | } |
341 | ||
e1602f7a | 342 | vector<DomainInfo> allSlaves; |
b4ce8b4e BH |
343 | int numanswers=d_result.size(); |
344 | for(int n=0;n<numanswers;++n) { // id,name,master,last_check | |
345 | DomainInfo sd; | |
7c779a31 | 346 | ASSERT_ROW_COLUMNS("info-all-slaves-query", d_result[n], 4); |
955e760a | 347 | sd.id=pdns_stou(d_result[n][0]); |
8408d2a6 KM |
348 | try { |
349 | sd.zone= DNSName(d_result[n][1]); | |
350 | } catch (...) { | |
351 | continue; | |
352 | } | |
d622042f | 353 | |
354 | vector<string> masters; | |
355 | stringtok(masters, d_result[n][2], ", \t"); | |
356 | for(const auto& m : masters) | |
357 | sd.masters.emplace_back(m, 53); | |
358 | ||
955e760a | 359 | sd.last_check=pdns_stou(d_result[n][3]); |
b4ce8b4e BH |
360 | sd.backend=this; |
361 | sd.kind=DomainInfo::Slave; | |
362 | allSlaves.push_back(sd); | |
363 | } | |
364 | ||
365 | for(vector<DomainInfo>::iterator i=allSlaves.begin();i!=allSlaves.end();++i) { | |
366 | SOAData sdata; | |
367 | sdata.serial=0; | |
368 | sdata.refresh=0; | |
369 | getSOA(i->zone,sdata); | |
370 | if((time_t)(i->last_check+sdata.refresh) < time(0)) { | |
371 | i->serial=sdata.serial; | |
372 | unfreshDomains->push_back(*i); | |
373 | } | |
374 | } | |
375 | } | |
376 | ||
377 | void GSQLBackend::getUpdatedMasters(vector<DomainInfo> *updatedDomains) | |
378 | { | |
379 | /* list all domains that need notifications for which we are master, and insert into updatedDomains | |
380 | id,name,master IP,serial */ | |
b4ce8b4e | 381 | try { |
45d36933 RG |
382 | reconnectIfNeeded(); |
383 | ||
0f310932 AT |
384 | d_InfoOfAllMasterDomainsQuery_stmt-> |
385 | execute()-> | |
386 | getResult(d_result)-> | |
387 | reset(); | |
b4ce8b4e BH |
388 | } |
389 | catch(SSqlException &e) { | |
63be3701 | 390 | throw PDNSException("GSQLBackend unable to retrieve list of master domains: "+e.txtReason()); |
b4ce8b4e BH |
391 | } |
392 | ||
e5b11b2f | 393 | vector<DomainInfo> allMasters; |
abcd36a1 CH |
394 | size_t numanswers=d_result.size(); |
395 | for(size_t n=0;n<numanswers;++n) { // id,name,master,last_check,notified_serial | |
b4ce8b4e | 396 | DomainInfo sd; |
30c9a6d9 | 397 | ASSERT_ROW_COLUMNS("info-all-master-query", d_result[n], 6); |
955e760a | 398 | sd.id=pdns_stou(d_result[n][0]); |
8408d2a6 KM |
399 | try { |
400 | sd.zone= DNSName(d_result[n][1]); | |
401 | } catch (...) { | |
402 | continue; | |
403 | } | |
955e760a AT |
404 | sd.last_check=pdns_stou(d_result[n][3]); |
405 | sd.notified_serial=pdns_stou(d_result[n][4]); | |
b4ce8b4e BH |
406 | sd.backend=this; |
407 | sd.kind=DomainInfo::Master; | |
408 | allMasters.push_back(sd); | |
409 | } | |
410 | ||
411 | for(vector<DomainInfo>::iterator i=allMasters.begin();i!=allMasters.end();++i) { | |
412 | SOAData sdata; | |
413 | sdata.serial=0; | |
414 | sdata.refresh=0; | |
415 | getSOA(i->zone,sdata); | |
416 | if(i->notified_serial!=sdata.serial) { | |
417 | i->serial=sdata.serial; | |
418 | updatedDomains->push_back(*i); | |
419 | } | |
420 | } | |
421 | } | |
422 | ||
96e63d77 | 423 | bool GSQLBackend::updateDNSSECOrderNameAndAuth(uint32_t domain_id, const DNSName& qname, const DNSName& ordername, bool auth, const uint16_t qtype) |
27045410 PD |
424 | { |
425 | if(!d_dnssecQueries) | |
426 | return false; | |
c2df797e | 427 | |
79de0a80 KM |
428 | if (!ordername.empty()) { |
429 | if (qtype == QType::ANY) { | |
430 | try { | |
45d36933 RG |
431 | reconnectIfNeeded(); |
432 | ||
79de0a80 | 433 | d_updateOrderNameAndAuthQuery_stmt-> |
96e63d77 | 434 | bind("ordername", ordername.labelReverse().toString(" ", false))-> |
79de0a80 KM |
435 | bind("auth", auth)-> |
436 | bind("domain_id", domain_id)-> | |
437 | bind("qname", qname)-> | |
438 | execute()-> | |
439 | reset(); | |
440 | } | |
441 | catch(SSqlException &e) { | |
63be3701 | 442 | throw PDNSException("GSQLBackend unable to update ordername and auth for domain_id "+itoa(domain_id)+": "+e.txtReason()); |
79de0a80 KM |
443 | } |
444 | } else { | |
445 | try { | |
45d36933 RG |
446 | reconnectIfNeeded(); |
447 | ||
79de0a80 | 448 | d_updateOrderNameAndAuthTypeQuery_stmt-> |
96e63d77 | 449 | bind("ordername", ordername.labelReverse().toString(" ", false))-> |
79de0a80 KM |
450 | bind("auth", auth)-> |
451 | bind("domain_id", domain_id)-> | |
452 | bind("qname", qname)-> | |
453 | bind("qtype", QType(qtype).getName())-> | |
454 | execute()-> | |
455 | reset(); | |
456 | } | |
457 | catch(SSqlException &e) { | |
63be3701 | 458 | throw PDNSException("GSQLBackend unable to update ordername and auth per type for domain_id "+itoa(domain_id)+": "+e.txtReason()); |
79de0a80 KM |
459 | } |
460 | } | |
461 | } else { | |
462 | if (qtype == QType::ANY) { | |
45d36933 RG |
463 | reconnectIfNeeded(); |
464 | ||
79de0a80 KM |
465 | try { |
466 | d_nullifyOrderNameAndUpdateAuthQuery_stmt-> | |
467 | bind("auth", auth)-> | |
468 | bind("domain_id", domain_id)-> | |
469 | bind("qname", qname)-> | |
470 | execute()-> | |
471 | reset(); | |
472 | } | |
473 | catch(SSqlException &e) { | |
63be3701 | 474 | throw PDNSException("GSQLBackend unable to nullify ordername and update auth for domain_id "+itoa(domain_id)+": "+e.txtReason()); |
79de0a80 KM |
475 | } |
476 | } else { | |
477 | try { | |
45d36933 RG |
478 | reconnectIfNeeded(); |
479 | ||
79de0a80 KM |
480 | d_nullifyOrderNameAndUpdateAuthTypeQuery_stmt-> |
481 | bind("auth", auth)-> | |
482 | bind("domain_id", domain_id)-> | |
483 | bind("qname", qname)-> | |
484 | bind("qtype", QType(qtype).getName())-> | |
485 | execute()-> | |
486 | reset(); | |
487 | } | |
488 | catch(SSqlException &e) { | |
63be3701 | 489 | throw PDNSException("GSQLBackend unable to nullify ordername and update auth per type for domain_id "+itoa(domain_id)+": "+e.txtReason()); |
79de0a80 KM |
490 | } |
491 | } | |
bb6dd39e | 492 | } |
27045410 PD |
493 | return true; |
494 | } | |
495 | ||
96e63d77 | 496 | bool GSQLBackend::updateEmptyNonTerminals(uint32_t domain_id, set<DNSName>& insert, set<DNSName>& erase, bool remove) |
b5baefaf | 497 | { |
b5baefaf | 498 | if(remove) { |
b5baefaf | 499 | try { |
45d36933 RG |
500 | reconnectIfNeeded(); |
501 | ||
09070ce7 | 502 | d_RemoveEmptyNonTerminalsFromZoneQuery_stmt-> |
0f310932 AT |
503 | bind("domain_id", domain_id)-> |
504 | execute()-> | |
505 | reset(); | |
b5baefaf PD |
506 | } |
507 | catch (SSqlException &e) { | |
63be3701 | 508 | throw PDNSException("GSQLBackend unable to delete empty non-terminal records from domain_id "+itoa(domain_id)+": "+e.txtReason()); |
b5baefaf PD |
509 | return false; |
510 | } | |
511 | } | |
512 | else | |
513 | { | |
424b92c6 | 514 | for(const auto& qname: erase) { |
b5baefaf | 515 | try { |
45d36933 RG |
516 | reconnectIfNeeded(); |
517 | ||
09070ce7 | 518 | d_DeleteEmptyNonTerminalQuery_stmt-> |
0f310932 AT |
519 | bind("domain_id", domain_id)-> |
520 | bind("qname", qname)-> | |
521 | execute()-> | |
522 | reset(); | |
b5baefaf PD |
523 | } |
524 | catch (SSqlException &e) { | |
2042adf5 | 525 | throw PDNSException("GSQLBackend unable to delete empty non-terminal rr '"+qname.toLogString()+"' from domain_id "+itoa(domain_id)+": "+e.txtReason()); |
b5baefaf PD |
526 | return false; |
527 | } | |
528 | } | |
529 | } | |
530 | ||
424b92c6 | 531 | for(const auto& qname: insert) { |
b5baefaf | 532 | try { |
45d36933 RG |
533 | reconnectIfNeeded(); |
534 | ||
09070ce7 | 535 | d_InsertEmptyNonTerminalOrderQuery_stmt-> |
0f310932 AT |
536 | bind("domain_id", domain_id)-> |
537 | bind("qname", qname)-> | |
09070ce7 PL |
538 | bindNull("ordername")-> |
539 | bind("auth", true)-> | |
0f310932 AT |
540 | execute()-> |
541 | reset(); | |
b5baefaf PD |
542 | } |
543 | catch (SSqlException &e) { | |
2042adf5 | 544 | throw PDNSException("GSQLBackend unable to insert empty non-terminal rr '"+qname.toLogString()+"' in domain_id "+itoa(domain_id)+": "+e.txtReason()); |
b5baefaf PD |
545 | return false; |
546 | } | |
547 | } | |
548 | ||
549 | return true; | |
550 | } | |
551 | ||
ece45ffb PD |
552 | bool GSQLBackend::doesDNSSEC() |
553 | { | |
554 | return d_dnssecQueries; | |
555 | } | |
556 | ||
29e0008a | 557 | bool GSQLBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const DNSName& qname, DNSName& unhashed, DNSName& before, DNSName& after) |
66dba9d7 | 558 | { |
28f1aab9 BH |
559 | if(!d_dnssecQueries) |
560 | return false; | |
8c1a6d6d | 561 | after.clear(); |
8c1a6d6d | 562 | |
0f310932 | 563 | SSqlStatement::row_t row; |
bb6dd39e | 564 | try { |
45d36933 RG |
565 | reconnectIfNeeded(); |
566 | ||
0f310932 | 567 | d_afterOrderQuery_stmt-> |
29e0008a | 568 | bind("ordername", qname.labelReverse().toString(" ", false))-> |
0f310932 AT |
569 | bind("domain_id", id)-> |
570 | execute(); | |
571 | while(d_afterOrderQuery_stmt->hasNextRow()) { | |
572 | d_afterOrderQuery_stmt->nextRow(row); | |
7c779a31 | 573 | ASSERT_ROW_COLUMNS("get-order-after-query", row, 1); |
637abecb KM |
574 | if(! row[0].empty()) { // Hack because NULL values are passed on as empty strings |
575 | after=DNSName(boost::replace_all_copy(row[0]," ",".")).labelReverse(); | |
576 | } | |
0f310932 AT |
577 | } |
578 | d_afterOrderQuery_stmt->reset(); | |
bb6dd39e PD |
579 | } |
580 | catch(SSqlException &e) { | |
63be3701 | 581 | throw PDNSException("GSQLBackend unable to find before/after (after) for domain_id "+itoa(id)+": "+e.txtReason()); |
bb6dd39e | 582 | } |
66dba9d7 | 583 | |
29e0008a | 584 | if(after.empty()) { |
bb6dd39e | 585 | try { |
45d36933 RG |
586 | reconnectIfNeeded(); |
587 | ||
0f310932 AT |
588 | d_firstOrderQuery_stmt-> |
589 | bind("domain_id", id)-> | |
590 | execute(); | |
591 | while(d_firstOrderQuery_stmt->hasNextRow()) { | |
592 | d_firstOrderQuery_stmt->nextRow(row); | |
7c779a31 | 593 | ASSERT_ROW_COLUMNS("get-order-first-query", row, 1); |
29e0008a | 594 | after=DNSName(boost::replace_all_copy(row[0]," ",".")).labelReverse(); |
0f310932 AT |
595 | } |
596 | d_firstOrderQuery_stmt->reset(); | |
bb6dd39e PD |
597 | } |
598 | catch(SSqlException &e) { | |
63be3701 | 599 | throw PDNSException("GSQLBackend unable to find before/after (first) for domain_id "+itoa(id)+": "+e.txtReason()); |
bb6dd39e | 600 | } |
c3c89361 BH |
601 | } |
602 | ||
8c1a6d6d KM |
603 | if (before.empty()) { |
604 | unhashed.clear(); | |
bc74a078 | 605 | |
8c1a6d6d | 606 | try { |
45d36933 RG |
607 | reconnectIfNeeded(); |
608 | ||
0f310932 | 609 | d_beforeOrderQuery_stmt-> |
29e0008a | 610 | bind("ordername", qname.labelReverse().toString(" ", false))-> |
0f310932 AT |
611 | bind("domain_id", id)-> |
612 | execute(); | |
613 | while(d_beforeOrderQuery_stmt->hasNextRow()) { | |
614 | d_beforeOrderQuery_stmt->nextRow(row); | |
7c779a31 | 615 | ASSERT_ROW_COLUMNS("get-order-before-query", row, 2); |
29e0008a | 616 | before=DNSName(boost::replace_all_copy(row[0]," ",".")).labelReverse(); |
8408d2a6 KM |
617 | try { |
618 | unhashed=DNSName(row[1]); | |
619 | } catch (...) { | |
620 | continue; | |
621 | } | |
0f310932 AT |
622 | } |
623 | d_beforeOrderQuery_stmt->reset(); | |
8c1a6d6d KM |
624 | } |
625 | catch(SSqlException &e) { | |
63be3701 | 626 | throw PDNSException("GSQLBackend unable to find before/after (before) for domain_id "+itoa(id)+": "+e.txtReason()); |
8c1a6d6d | 627 | } |
8c1a6d6d KM |
628 | |
629 | if(! unhashed.empty()) | |
630 | { | |
631 | // cerr<<"unhashed="<<unhashed<<",before="<<before<<", after="<<after<<endl; | |
632 | return true; | |
633 | } | |
634 | ||
8c1a6d6d | 635 | try { |
45d36933 RG |
636 | reconnectIfNeeded(); |
637 | ||
0f310932 AT |
638 | d_lastOrderQuery_stmt-> |
639 | bind("domain_id", id)-> | |
640 | execute(); | |
641 | while(d_lastOrderQuery_stmt->hasNextRow()) { | |
642 | d_lastOrderQuery_stmt->nextRow(row); | |
7c779a31 | 643 | ASSERT_ROW_COLUMNS("get-order-last-query", row, 2); |
29e0008a | 644 | before=DNSName(boost::replace_all_copy(row[0]," ",".")).labelReverse(); |
8408d2a6 KM |
645 | try { |
646 | unhashed=DNSName(row[1]); | |
647 | } catch (...) { | |
648 | continue; | |
649 | } | |
0f310932 AT |
650 | } |
651 | d_lastOrderQuery_stmt->reset(); | |
8c1a6d6d KM |
652 | } |
653 | catch(SSqlException &e) { | |
63be3701 | 654 | throw PDNSException("GSQLBackend unable to find before/after (last) for domain_id "+itoa(id)+": "+e.txtReason()); |
8c1a6d6d | 655 | } |
8c1a6d6d | 656 | } else { |
223d3559 | 657 | before=qname; |
66dba9d7 BH |
658 | } |
659 | ||
75943e62 | 660 | return true; |
66dba9d7 BH |
661 | } |
662 | ||
82cc0761 | 663 | bool GSQLBackend::addDomainKey(const DNSName& name, const KeyData& key, int64_t& id) |
c0273500 | 664 | { |
28f1aab9 | 665 | if(!d_dnssecQueries) |
82cc0761 | 666 | return false; |
c0273500 BH |
667 | |
668 | try { | |
45d36933 RG |
669 | reconnectIfNeeded(); |
670 | ||
0f310932 AT |
671 | d_AddDomainKeyQuery_stmt-> |
672 | bind("flags", key.flags)-> | |
673 | bind("active", key.active)-> | |
674 | bind("content", key.content)-> | |
8f126bc1 | 675 | bind("domain", name)-> |
0f310932 AT |
676 | execute()-> |
677 | reset(); | |
c0273500 BH |
678 | } |
679 | catch (SSqlException &e) { | |
63be3701 | 680 | throw PDNSException("GSQLBackend unable to store key: "+e.txtReason()); |
c0273500 | 681 | } |
63de5311 BZ |
682 | |
683 | try { | |
45d36933 RG |
684 | reconnectIfNeeded(); |
685 | ||
63de5311 | 686 | d_GetLastInsertedKeyIdQuery_stmt->execute(); |
82cc0761 BZ |
687 | if (!d_GetLastInsertedKeyIdQuery_stmt->hasNextRow()) { |
688 | id = -2; | |
689 | return true; | |
690 | } | |
63de5311 BZ |
691 | SSqlStatement::row_t row; |
692 | d_GetLastInsertedKeyIdQuery_stmt->nextRow(row); | |
7b82d9de | 693 | ASSERT_ROW_COLUMNS("get-last-inserted-key-id-query", row, 1); |
82cc0761 | 694 | id = std::stoi(row[0]); |
63de5311 | 695 | d_GetLastInsertedKeyIdQuery_stmt->reset(); |
82cc0761 | 696 | return true; |
63de5311 BZ |
697 | } |
698 | catch (SSqlException &e) { | |
82cc0761 BZ |
699 | id = -2; |
700 | return true; | |
63de5311 BZ |
701 | } |
702 | ||
82cc0761 | 703 | return false; |
c0273500 BH |
704 | } |
705 | ||
8f126bc1 | 706 | bool GSQLBackend::activateDomainKey(const DNSName& name, unsigned int id) |
4496f66f | 707 | { |
28f1aab9 BH |
708 | if(!d_dnssecQueries) |
709 | return false; | |
4496f66f BH |
710 | |
711 | try { | |
45d36933 RG |
712 | reconnectIfNeeded(); |
713 | ||
0f310932 | 714 | d_ActivateDomainKeyQuery_stmt-> |
8f126bc1 | 715 | bind("domain", name)-> |
0f310932 AT |
716 | bind("key_id", id)-> |
717 | execute()-> | |
718 | reset(); | |
4496f66f BH |
719 | } |
720 | catch (SSqlException &e) { | |
63be3701 | 721 | throw PDNSException("GSQLBackend unable to activate key: "+e.txtReason()); |
4496f66f BH |
722 | } |
723 | return true; | |
724 | } | |
725 | ||
8f126bc1 | 726 | bool GSQLBackend::deactivateDomainKey(const DNSName& name, unsigned int id) |
4496f66f | 727 | { |
28f1aab9 BH |
728 | if(!d_dnssecQueries) |
729 | return false; | |
4496f66f BH |
730 | |
731 | try { | |
45d36933 RG |
732 | reconnectIfNeeded(); |
733 | ||
0f310932 | 734 | d_DeactivateDomainKeyQuery_stmt-> |
8f126bc1 | 735 | bind("domain", name)-> |
0f310932 AT |
736 | bind("key_id", id)-> |
737 | execute()-> | |
738 | reset(); | |
4496f66f BH |
739 | } |
740 | catch (SSqlException &e) { | |
63be3701 | 741 | throw PDNSException("GSQLBackend unable to deactivate key: "+e.txtReason()); |
4496f66f BH |
742 | } |
743 | return true; | |
744 | } | |
745 | ||
8f126bc1 | 746 | bool GSQLBackend::removeDomainKey(const DNSName& name, unsigned int id) |
4496f66f | 747 | { |
28f1aab9 BH |
748 | if(!d_dnssecQueries) |
749 | return false; | |
4496f66f BH |
750 | |
751 | try { | |
45d36933 RG |
752 | reconnectIfNeeded(); |
753 | ||
0f310932 | 754 | d_RemoveDomainKeyQuery_stmt-> |
8f126bc1 | 755 | bind("domain", name)-> |
0f310932 AT |
756 | bind("key_id", id)-> |
757 | execute()-> | |
758 | reset(); | |
4496f66f BH |
759 | } |
760 | catch (SSqlException &e) { | |
63be3701 | 761 | throw PDNSException("GSQLBackend unable to remove key: "+e.txtReason()); |
4496f66f BH |
762 | } |
763 | return true; | |
764 | } | |
765 | ||
8f126bc1 | 766 | bool GSQLBackend::getTSIGKey(const DNSName& name, DNSName* algorithm, string* content) |
78bcb858 | 767 | { |
78bcb858 | 768 | try { |
45d36933 RG |
769 | reconnectIfNeeded(); |
770 | ||
0f310932 | 771 | d_getTSIGKeyQuery_stmt-> |
8f126bc1 | 772 | bind("key_name", name)-> |
0f310932 AT |
773 | execute(); |
774 | ||
775 | SSqlStatement::row_t row; | |
776 | ||
777 | content->clear(); | |
778 | while(d_getTSIGKeyQuery_stmt->hasNextRow()) { | |
779 | d_getTSIGKeyQuery_stmt->nextRow(row); | |
7c779a31 | 780 | ASSERT_ROW_COLUMNS("get-tsig-key-query", row, 2); |
8408d2a6 KM |
781 | try{ |
782 | if(algorithm->empty() || *algorithm==DNSName(row[0])) { | |
783 | *algorithm = DNSName(row[0]); | |
784 | *content = row[1]; | |
785 | } | |
786 | } catch (...) {} | |
0f310932 AT |
787 | } |
788 | ||
789 | d_getTSIGKeyQuery_stmt->reset(); | |
78bcb858 BH |
790 | } |
791 | catch (SSqlException &e) { | |
63be3701 | 792 | throw PDNSException("GSQLBackend unable to retrieve named TSIG key: "+e.txtReason()); |
78bcb858 | 793 | } |
4496f66f | 794 | |
78bcb858 BH |
795 | return !content->empty(); |
796 | } | |
4496f66f | 797 | |
8f126bc1 | 798 | bool GSQLBackend::setTSIGKey(const DNSName& name, const DNSName& algorithm, const string& content) |
9a72349d | 799 | { |
9a72349d | 800 | try { |
45d36933 RG |
801 | reconnectIfNeeded(); |
802 | ||
0f310932 | 803 | d_setTSIGKeyQuery_stmt-> |
8f126bc1 KM |
804 | bind("key_name", name)-> |
805 | bind("algorithm", algorithm)-> | |
0f310932 AT |
806 | bind("content", content)-> |
807 | execute()-> | |
808 | reset(); | |
9a72349d AT |
809 | } |
810 | catch (SSqlException &e) { | |
63be3701 | 811 | throw PDNSException("GSQLBackend unable to store named TSIG key: "+e.txtReason()); |
9a72349d AT |
812 | } |
813 | return true; | |
814 | } | |
815 | ||
8f126bc1 | 816 | bool GSQLBackend::deleteTSIGKey(const DNSName& name) |
9a72349d | 817 | { |
9a72349d | 818 | try { |
45d36933 RG |
819 | reconnectIfNeeded(); |
820 | ||
0f310932 | 821 | d_deleteTSIGKeyQuery_stmt-> |
8f126bc1 | 822 | bind("key_name", name)-> |
0f310932 AT |
823 | execute()-> |
824 | reset(); | |
9a72349d AT |
825 | } |
826 | catch (SSqlException &e) { | |
63be3701 | 827 | throw PDNSException("GSQLBackend unable to store named TSIG key: "+e.txtReason()); |
9a72349d AT |
828 | } |
829 | return true; | |
830 | } | |
831 | ||
832 | bool GSQLBackend::getTSIGKeys(std::vector< struct TSIGKey > &keys) | |
833 | { | |
9a72349d | 834 | try { |
45d36933 RG |
835 | reconnectIfNeeded(); |
836 | ||
0f310932 AT |
837 | d_getTSIGKeysQuery_stmt-> |
838 | execute(); | |
839 | ||
840 | SSqlStatement::row_t row; | |
841 | ||
842 | while(d_getTSIGKeysQuery_stmt->hasNextRow()) { | |
843 | d_getTSIGKeysQuery_stmt->nextRow(row); | |
7c779a31 | 844 | ASSERT_ROW_COLUMNS("get-tsig-keys-query", row, 3); |
0f310932 | 845 | struct TSIGKey key; |
8408d2a6 KM |
846 | try { |
847 | key.name = DNSName(row[0]); | |
848 | key.algorithm = DNSName(row[1]); | |
849 | } catch (...) { | |
850 | continue; | |
851 | } | |
0f310932 AT |
852 | key.key = row[2]; |
853 | keys.push_back(key); | |
854 | } | |
855 | ||
856 | d_getTSIGKeysQuery_stmt->reset(); | |
9a72349d AT |
857 | } |
858 | catch (SSqlException &e) { | |
63be3701 | 859 | throw PDNSException("GSQLBackend unable to retrieve TSIG keys: "+e.txtReason()); |
9a72349d AT |
860 | } |
861 | ||
9a72349d AT |
862 | return keys.empty(); |
863 | } | |
864 | ||
9c1c5d49 | 865 | bool GSQLBackend::getDomainKeys(const DNSName& name, std::vector<KeyData>& keys) |
c0273500 | 866 | { |
28f1aab9 BH |
867 | if(!d_dnssecQueries) |
868 | return false; | |
c0273500 BH |
869 | |
870 | try { | |
45d36933 RG |
871 | reconnectIfNeeded(); |
872 | ||
0f310932 | 873 | d_ListDomainKeysQuery_stmt-> |
8f126bc1 | 874 | bind("domain", name)-> |
0f310932 AT |
875 | execute(); |
876 | ||
877 | SSqlStatement::row_t row; | |
0f310932 AT |
878 | KeyData kd; |
879 | while(d_ListDomainKeysQuery_stmt->hasNextRow()) { | |
880 | d_ListDomainKeysQuery_stmt->nextRow(row); | |
7c779a31 | 881 | ASSERT_ROW_COLUMNS("list-domain-keys-query", row, 4); |
424b92c6 | 882 | //~ for(const auto& val: row) { |
0f310932 AT |
883 | //~ cerr<<"'"<<val<<"'"<<endl; |
884 | //~ } | |
955e760a AT |
885 | kd.id = pdns_stou(row[0]); |
886 | kd.flags = pdns_stou(row[1]); | |
887 | kd.active = row[2] == "1"; | |
0f310932 AT |
888 | kd.content = row[3]; |
889 | keys.push_back(kd); | |
890 | } | |
891 | ||
892 | d_ListDomainKeysQuery_stmt->reset(); | |
c0273500 BH |
893 | } |
894 | catch (SSqlException &e) { | |
63be3701 | 895 | throw PDNSException("GSQLBackend unable to list keys: "+e.txtReason()); |
c0273500 | 896 | } |
c0273500 BH |
897 | |
898 | return true; | |
899 | } | |
900 | ||
8f126bc1 | 901 | void GSQLBackend::alsoNotifies(const DNSName &domain, set<string> *ips) |
77151d0b | 902 | { |
77151d0b BH |
903 | vector<string> meta; |
904 | getDomainMetadata(domain, "ALSO-NOTIFY", meta); | |
424b92c6 | 905 | for(const auto& str: meta) { |
77151d0b BH |
906 | ips->insert(str); |
907 | } | |
908 | } | |
909 | ||
8f126bc1 | 910 | bool GSQLBackend::getAllDomainMetadata(const DNSName& name, std::map<std::string, std::vector<std::string> >& meta) |
df0cc941 | 911 | { |
df0cc941 | 912 | try { |
45d36933 RG |
913 | reconnectIfNeeded(); |
914 | ||
0f310932 | 915 | d_GetAllDomainMetadataQuery_stmt-> |
8f126bc1 | 916 | bind("domain", name)-> |
0f310932 AT |
917 | execute(); |
918 | ||
919 | SSqlStatement::row_t row; | |
920 | ||
921 | while(d_GetAllDomainMetadataQuery_stmt->hasNextRow()) { | |
922 | d_GetAllDomainMetadataQuery_stmt->nextRow(row); | |
7c779a31 AT |
923 | ASSERT_ROW_COLUMNS("get-all-domain-metadata-query", row, 2); |
924 | ||
0f310932 AT |
925 | if (!isDnssecDomainMetadata(row[0])) |
926 | meta[row[0]].push_back(row[1]); | |
927 | } | |
928 | ||
929 | d_GetAllDomainMetadataQuery_stmt->reset(); | |
df0cc941 AT |
930 | } |
931 | catch (SSqlException &e) { | |
63be3701 | 932 | throw PDNSException("GSQLBackend unable to list metadata: "+e.txtReason()); |
df0cc941 AT |
933 | } |
934 | ||
df0cc941 AT |
935 | return true; |
936 | } | |
937 | ||
938 | ||
8f126bc1 | 939 | bool GSQLBackend::getDomainMetadata(const DNSName& name, const std::string& kind, std::vector<std::string>& meta) |
c0273500 | 940 | { |
7166723e | 941 | if(!d_dnssecQueries && isDnssecDomainMetadata(kind)) |
28f1aab9 | 942 | return false; |
7166723e | 943 | |
c0273500 | 944 | try { |
45d36933 RG |
945 | reconnectIfNeeded(); |
946 | ||
0f310932 | 947 | d_GetDomainMetadataQuery_stmt-> |
8f126bc1 | 948 | bind("domain", name)-> |
0f310932 AT |
949 | bind("kind", kind)-> |
950 | execute(); | |
951 | ||
952 | SSqlStatement::row_t row; | |
953 | ||
954 | while(d_GetDomainMetadataQuery_stmt->hasNextRow()) { | |
955 | d_GetDomainMetadataQuery_stmt->nextRow(row); | |
7c779a31 | 956 | ASSERT_ROW_COLUMNS("get-domain-metadata-query", row, 1); |
0f310932 AT |
957 | meta.push_back(row[0]); |
958 | } | |
959 | ||
960 | d_GetDomainMetadataQuery_stmt->reset(); | |
c0273500 BH |
961 | } |
962 | catch (SSqlException &e) { | |
63be3701 | 963 | throw PDNSException("GSQLBackend unable to list metadata: "+e.txtReason()); |
c0273500 | 964 | } |
0f310932 | 965 | |
c0273500 BH |
966 | return true; |
967 | } | |
968 | ||
8f126bc1 | 969 | bool GSQLBackend::setDomainMetadata(const DNSName& name, const std::string& kind, const std::vector<std::string>& meta) |
c0273500 | 970 | { |
7166723e | 971 | if(!d_dnssecQueries && isDnssecDomainMetadata(kind)) |
28f1aab9 | 972 | return false; |
f7bcc763 | 973 | |
c0273500 | 974 | try { |
45d36933 RG |
975 | reconnectIfNeeded(); |
976 | ||
0f310932 | 977 | d_ClearDomainMetadataQuery_stmt-> |
8f126bc1 | 978 | bind("domain", name)-> |
0f310932 AT |
979 | bind("kind", kind)-> |
980 | execute()-> | |
981 | reset(); | |
1f93748d | 982 | if(!meta.empty()) { |
424b92c6 | 983 | for(const auto& value: meta) { |
0f310932 AT |
984 | d_SetDomainMetadataQuery_stmt-> |
985 | bind("kind", kind)-> | |
986 | bind("content", value)-> | |
8f126bc1 | 987 | bind("domain", name)-> |
0f310932 AT |
988 | execute()-> |
989 | reset(); | |
1f93748d AT |
990 | } |
991 | } | |
c0273500 BH |
992 | } |
993 | catch (SSqlException &e) { | |
63be3701 | 994 | throw PDNSException("GSQLBackend unable to store metadata key: "+e.txtReason()); |
c0273500 | 995 | } |
f7bcc763 | 996 | |
c0273500 BH |
997 | return true; |
998 | } | |
999 | ||
f1d06abf | 1000 | void GSQLBackend::lookup(const QType &qtype,const DNSName &qname, DNSPacket *pkt_p, int domain_id) |
b4ce8b4e | 1001 | { |
0f310932 | 1002 | try { |
45d36933 RG |
1003 | reconnectIfNeeded(); |
1004 | ||
0f310932 AT |
1005 | if(qtype.getCode()!=QType::ANY) { |
1006 | if(domain_id < 0) { | |
7c779a31 | 1007 | d_query_name = "basic-query"; |
a59a9c23 AT |
1008 | d_query_stmt = &d_NoIdQuery_stmt; |
1009 | (*d_query_stmt)-> | |
0f310932 | 1010 | bind("qtype", qtype.getName())-> |
8f126bc1 | 1011 | bind("qname", qname); |
0f310932 | 1012 | } else { |
7c779a31 | 1013 | d_query_name = "id-query"; |
a59a9c23 AT |
1014 | d_query_stmt = &d_IdQuery_stmt; |
1015 | (*d_query_stmt)-> | |
0f310932 | 1016 | bind("qtype", qtype.getName())-> |
f1d06abf | 1017 | bind("qname", qname)-> |
0f310932 AT |
1018 | bind("domain_id", domain_id); |
1019 | } | |
75f02b56 | 1020 | } else { |
0f310932 AT |
1021 | // qtype==ANY |
1022 | if(domain_id < 0) { | |
7c779a31 | 1023 | d_query_name = "any-query"; |
a59a9c23 AT |
1024 | d_query_stmt = &d_ANYNoIdQuery_stmt; |
1025 | (*d_query_stmt)-> | |
f1d06abf | 1026 | bind("qname", qname); |
0f310932 | 1027 | } else { |
7c779a31 | 1028 | d_query_name = "any-id-query"; |
a59a9c23 AT |
1029 | d_query_stmt = &d_ANYIdQuery_stmt; |
1030 | (*d_query_stmt)-> | |
f1d06abf | 1031 | bind("qname", qname)-> |
0f310932 AT |
1032 | bind("domain_id", domain_id); |
1033 | } | |
b4ce8b4e | 1034 | } |
b4ce8b4e | 1035 | |
a59a9c23 | 1036 | (*d_query_stmt)-> |
0f310932 | 1037 | execute(); |
b4ce8b4e BH |
1038 | } |
1039 | catch(SSqlException &e) { | |
63be3701 | 1040 | throw PDNSException("GSQLBackend lookup query:"+e.txtReason()); |
b4ce8b4e BH |
1041 | } |
1042 | ||
1043 | d_qname=qname; | |
b4ce8b4e | 1044 | } |
770e6a9c | 1045 | |
f1d06abf | 1046 | bool GSQLBackend::list(const DNSName &target, int domain_id, bool include_disabled) |
b4ce8b4e | 1047 | { |
e6a9dde5 | 1048 | DLOG(g_log<<"GSQLBackend constructing handle for list of domain id '"<<domain_id<<"'"<<endl); |
b4ce8b4e | 1049 | |
b4ce8b4e | 1050 | try { |
45d36933 RG |
1051 | reconnectIfNeeded(); |
1052 | ||
7c779a31 | 1053 | d_query_name = "list-query"; |
a59a9c23 AT |
1054 | d_query_stmt = &d_listQuery_stmt; |
1055 | (*d_query_stmt)-> | |
0f310932 AT |
1056 | bind("include_disabled", (int)include_disabled)-> |
1057 | bind("domain_id", domain_id)-> | |
1058 | execute(); | |
b4ce8b4e BH |
1059 | } |
1060 | catch(SSqlException &e) { | |
63be3701 | 1061 | throw PDNSException("GSQLBackend list query: "+e.txtReason()); |
b4ce8b4e BH |
1062 | } |
1063 | ||
79de0a80 | 1064 | d_qname.clear(); |
b4ce8b4e BH |
1065 | return true; |
1066 | } | |
1067 | ||
8f126bc1 | 1068 | bool GSQLBackend::listSubZone(const DNSName &zone, int domain_id) { |
182f7513 | 1069 | |
2042adf5 | 1070 | string wildzone = "%." + zone.makeLowerCase().toStringNoDot(); |
0f310932 | 1071 | |
6a323f63 | 1072 | try { |
45d36933 RG |
1073 | reconnectIfNeeded(); |
1074 | ||
7c779a31 | 1075 | d_query_name = "list-subzone-query"; |
a59a9c23 AT |
1076 | d_query_stmt = &d_listSubZoneQuery_stmt; |
1077 | (*d_query_stmt)-> | |
0f310932 AT |
1078 | bind("zone", zone)-> |
1079 | bind("wildzone", wildzone)-> | |
1080 | bind("domain_id", domain_id)-> | |
1081 | execute(); | |
6a323f63 RA |
1082 | } |
1083 | catch(SSqlException &e) { | |
63be3701 | 1084 | throw PDNSException("GSQLBackend listSubZone query: "+e.txtReason()); |
6a323f63 | 1085 | } |
79de0a80 | 1086 | d_qname.clear(); |
6a323f63 RA |
1087 | return true; |
1088 | } | |
1089 | ||
0f310932 AT |
1090 | bool GSQLBackend::get(DNSResourceRecord &r) |
1091 | { | |
e6a9dde5 | 1092 | // g_log << "GSQLBackend get() was called for "<<qtype.getName() << " record: "; |
0f310932 | 1093 | SSqlStatement::row_t row; |
8408d2a6 KM |
1094 | |
1095 | skiprow: | |
a59a9c23 | 1096 | if((*d_query_stmt)->hasNextRow()) { |
0f310932 | 1097 | try { |
a59a9c23 | 1098 | (*d_query_stmt)->nextRow(row); |
7c779a31 | 1099 | ASSERT_ROW_COLUMNS(d_query_name, row, 8); |
0f310932 | 1100 | } catch (SSqlException &e) { |
63be3701 | 1101 | throw PDNSException("GSQLBackend get: "+e.txtReason()); |
0f310932 | 1102 | } |
8408d2a6 KM |
1103 | try { |
1104 | extractRecord(row, r); | |
1105 | } catch (...) { | |
1106 | goto skiprow; | |
1107 | } | |
0f310932 AT |
1108 | return true; |
1109 | } | |
1110 | ||
1111 | try { | |
a59a9c23 | 1112 | (*d_query_stmt)->reset(); |
0f310932 | 1113 | } catch (SSqlException &e) { |
63be3701 | 1114 | throw PDNSException("GSQLBackend get: "+e.txtReason()); |
0f310932 AT |
1115 | } |
1116 | d_query_stmt = NULL; | |
1117 | return false; | |
1118 | } | |
6a323f63 | 1119 | |
223d3559 | 1120 | bool GSQLBackend::superMasterBackend(const string &ip, const DNSName &domain, const vector<DNSResourceRecord>&nsset, string *nameserver, string *account, DNSBackend **ddb) |
b4ce8b4e BH |
1121 | { |
1122 | // check if we know the ip/ns couple in the database | |
1123 | for(vector<DNSResourceRecord>::const_iterator i=nsset.begin();i!=nsset.end();++i) { | |
1124 | try { | |
45d36933 RG |
1125 | reconnectIfNeeded(); |
1126 | ||
0f310932 AT |
1127 | d_SuperMasterInfoQuery_stmt-> |
1128 | bind("ip", ip)-> | |
1129 | bind("nameserver", i->content)-> | |
1130 | execute()-> | |
1131 | getResult(d_result)-> | |
1132 | reset(); | |
b4ce8b4e BH |
1133 | } |
1134 | catch (SSqlException &e) { | |
63be3701 | 1135 | throw PDNSException("GSQLBackend unable to search for a domain: "+e.txtReason()); |
b4ce8b4e | 1136 | } |
b4ce8b4e | 1137 | if(!d_result.empty()) { |
0c55d038 | 1138 | ASSERT_ROW_COLUMNS("supermaster-query", d_result[0], 1); |
719f9024 | 1139 | *nameserver=i->content; |
b4ce8b4e BH |
1140 | *account=d_result[0][0]; |
1141 | *ddb=this; | |
1142 | return true; | |
1143 | } | |
1144 | } | |
1145 | return false; | |
1146 | } | |
1147 | ||
aa09fa3b | 1148 | bool GSQLBackend::createDomain(const DNSName &domain, const string &type, const string &masters, const string &account) |
487cf033 | 1149 | { |
487cf033 | 1150 | try { |
45d36933 RG |
1151 | reconnectIfNeeded(); |
1152 | ||
0f310932 | 1153 | d_InsertZoneQuery_stmt-> |
aa09fa3b | 1154 | bind("type", type)-> |
223d3559 | 1155 | bind("domain", domain)-> |
aa09fa3b PL |
1156 | bind("masters", masters)-> |
1157 | bind("account", account)-> | |
0f310932 AT |
1158 | execute()-> |
1159 | reset(); | |
487cf033 CH |
1160 | } |
1161 | catch(SSqlException &e) { | |
2042adf5 | 1162 | throw PDNSException("Database error trying to insert new domain '"+domain.toLogString()+"': "+ e.txtReason()); |
487cf033 CH |
1163 | } |
1164 | return true; | |
1165 | } | |
1166 | ||
223d3559 | 1167 | bool GSQLBackend::createSlaveDomain(const string &ip, const DNSName &domain, const string &nameserver, const string &account) |
b4ce8b4e | 1168 | { |
5805615b | 1169 | string name; |
719f9024 | 1170 | string masters(ip); |
b4ce8b4e | 1171 | try { |
719f9024 KM |
1172 | if (!nameserver.empty()) { |
1173 | // figure out all IP addresses for the master | |
45d36933 RG |
1174 | reconnectIfNeeded(); |
1175 | ||
0f310932 AT |
1176 | d_GetSuperMasterIPs_stmt-> |
1177 | bind("nameserver", nameserver)-> | |
1178 | bind("account", account)-> | |
1179 | execute()-> | |
1180 | getResult(d_result)-> | |
1181 | reset(); | |
5805615b | 1182 | if (!d_result.empty()) { |
d5ebcefe | 1183 | // collect all IP addresses |
5805615b | 1184 | vector<string> tmp; |
424b92c6 | 1185 | for(const auto& row: d_result) { |
dd930ede KM |
1186 | if (account == row[1]) |
1187 | tmp.push_back(row[0]); | |
5805615b | 1188 | } |
d5ebcefe | 1189 | // set them as domain's masters, comma separated |
719f9024 | 1190 | masters = boost::join(tmp, ", "); |
5805615b | 1191 | } |
719f9024 | 1192 | } |
aa09fa3b | 1193 | createDomain(domain, "SLAVE", masters, account); |
b4ce8b4e BH |
1194 | } |
1195 | catch(SSqlException &e) { | |
2042adf5 | 1196 | throw PDNSException("Database error trying to insert new slave domain '"+domain.toLogString()+"': "+ e.txtReason()); |
09d6667a CH |
1197 | } |
1198 | return true; | |
1199 | } | |
1200 | ||
223d3559 | 1201 | bool GSQLBackend::deleteDomain(const DNSName &domain) |
09d6667a | 1202 | { |
09d6667a CH |
1203 | DomainInfo di; |
1204 | if (!getDomainInfo(domain, di)) { | |
1205 | return false; | |
1206 | } | |
1207 | ||
09d6667a | 1208 | try { |
45d36933 RG |
1209 | reconnectIfNeeded(); |
1210 | ||
0f310932 AT |
1211 | d_DeleteZoneQuery_stmt-> |
1212 | bind("domain_id", di.id)-> | |
1213 | execute()-> | |
1214 | reset(); | |
1215 | d_ClearDomainAllMetadataQuery_stmt-> | |
223d3559 | 1216 | bind("domain", domain)-> |
0f310932 AT |
1217 | execute()-> |
1218 | reset(); | |
1219 | d_ClearDomainAllKeysQuery_stmt-> | |
223d3559 | 1220 | bind("domain", domain)-> |
0f310932 AT |
1221 | execute()-> |
1222 | reset(); | |
1223 | d_DeleteCommentsQuery_stmt-> | |
1224 | bind("domain_id", di.id)-> | |
1225 | execute()-> | |
1226 | reset(); | |
1227 | d_DeleteDomainQuery_stmt-> | |
223d3559 | 1228 | bind("domain", domain)-> |
0f310932 AT |
1229 | execute()-> |
1230 | reset(); | |
09d6667a CH |
1231 | } |
1232 | catch(SSqlException &e) { | |
2042adf5 | 1233 | throw PDNSException("Database error trying to delete domain '"+domain.toLogString()+"': "+ e.txtReason()); |
b4ce8b4e BH |
1234 | } |
1235 | return true; | |
1236 | } | |
1237 | ||
cea26350 | 1238 | void GSQLBackend::getAllDomains(vector<DomainInfo> *domains, bool include_disabled) |
1325e8a2 | 1239 | { |
e6a9dde5 | 1240 | DLOG(g_log<<"GSQLBackend retrieving all domains."<<endl); |
1325e8a2 PD |
1241 | |
1242 | try { | |
45d36933 RG |
1243 | reconnectIfNeeded(); |
1244 | ||
0f310932 AT |
1245 | d_getAllDomainsQuery_stmt-> |
1246 | bind("include_disabled", (int)include_disabled)-> | |
1247 | execute(); | |
1248 | ||
1249 | SSqlStatement::row_t row; | |
1250 | while (d_getAllDomainsQuery_stmt->hasNextRow()) { | |
1251 | d_getAllDomainsQuery_stmt->nextRow(row); | |
7c779a31 | 1252 | ASSERT_ROW_COLUMNS("get-all-domains-query", row, 8); |
0f310932 | 1253 | DomainInfo di; |
955e760a | 1254 | di.id = pdns_stou(row[0]); |
8408d2a6 KM |
1255 | try { |
1256 | di.zone = DNSName(row[1]); | |
1257 | } catch (...) { | |
1258 | continue; | |
1259 | } | |
0f310932 AT |
1260 | |
1261 | if (!row[4].empty()) { | |
d622042f | 1262 | vector<string> masters; |
1263 | stringtok(masters, row[4], " ,\t"); | |
1264 | for(const auto& m : masters) | |
1265 | di.masters.emplace_back(m, 53); | |
0f310932 | 1266 | } |
8ffb7a9b | 1267 | |
0f310932 AT |
1268 | SOAData sd; |
1269 | fillSOAData(row[2], sd); | |
1270 | di.serial = sd.serial; | |
955e760a AT |
1271 | di.notified_serial = pdns_stou(row[5]); |
1272 | di.last_check = pdns_stou(row[6]); | |
8ffb7a9b CH |
1273 | di.account = row[7]; |
1274 | ||
0f310932 AT |
1275 | if (pdns_iequals(row[3], "MASTER")) |
1276 | di.kind = DomainInfo::Master; | |
1277 | else if (pdns_iequals(row[3], "SLAVE")) | |
1278 | di.kind = DomainInfo::Slave; | |
1279 | else | |
1280 | di.kind = DomainInfo::Native; | |
1281 | ||
1282 | di.backend = this; | |
1283 | ||
1284 | domains->push_back(di); | |
1285 | } | |
1286 | d_getAllDomainsQuery_stmt->reset(); | |
1325e8a2 PD |
1287 | } |
1288 | catch (SSqlException &e) { | |
63be3701 | 1289 | throw PDNSException("Database error trying to retrieve all domains:" + e.txtReason()); |
1325e8a2 | 1290 | } |
b4ce8b4e BH |
1291 | } |
1292 | ||
8f126bc1 | 1293 | bool GSQLBackend::replaceRRSet(uint32_t domain_id, const DNSName& qname, const QType& qt, const vector<DNSResourceRecord>& rrset) |
8bbb6f36 | 1294 | { |
f374debc | 1295 | try { |
45d36933 RG |
1296 | reconnectIfNeeded(); |
1297 | ||
0f310932 AT |
1298 | if (qt != QType::ANY) { |
1299 | d_DeleteRRSetQuery_stmt-> | |
1300 | bind("domain_id", domain_id)-> | |
1301 | bind("qname", qname)-> | |
1302 | bind("qtype", qt.getName())-> | |
1303 | execute()-> | |
1304 | reset(); | |
1305 | } else { | |
1306 | d_DeleteNamesQuery_stmt-> | |
1307 | bind("domain_id", domain_id)-> | |
1308 | bind("qname", qname)-> | |
1309 | execute()-> | |
1310 | reset(); | |
1311 | } | |
f374debc KM |
1312 | } |
1313 | catch (SSqlException &e) { | |
63be3701 | 1314 | throw PDNSException("GSQLBackend unable to delete RRSet: "+e.txtReason()); |
f374debc KM |
1315 | } |
1316 | ||
6cc98ddf | 1317 | if (rrset.empty()) { |
f374debc | 1318 | try { |
45d36933 RG |
1319 | reconnectIfNeeded(); |
1320 | ||
0f310932 AT |
1321 | d_DeleteCommentRRsetQuery_stmt-> |
1322 | bind("domain_id", domain_id)-> | |
1323 | bind("qname", qname)-> | |
1324 | bind("qtype", qt.getName())-> | |
1325 | execute()-> | |
1326 | reset(); | |
f374debc KM |
1327 | } |
1328 | catch (SSqlException &e) { | |
63be3701 | 1329 | throw PDNSException("GSQLBackend unable to delete comment: "+e.txtReason()); |
f374debc | 1330 | } |
6cc98ddf | 1331 | } |
424b92c6 | 1332 | for(const auto& rr: rrset) { |
c9b43446 | 1333 | feedRecord(rr, DNSName()); |
8bbb6f36 BH |
1334 | } |
1335 | ||
1336 | return true; | |
1337 | } | |
1338 | ||
c9b43446 | 1339 | bool GSQLBackend::feedRecord(const DNSResourceRecord &r, const DNSName &ordername) |
b4ce8b4e | 1340 | { |
b9bafae0 KM |
1341 | int prio=0; |
1342 | string content(r.content); | |
0f310932 | 1343 | if (r.qtype == QType::MX || r.qtype == QType::SRV) { |
b9bafae0 | 1344 | string::size_type pos = content.find_first_not_of("0123456789"); |
955e760a AT |
1345 | if (pos != string::npos) { |
1346 | prio=pdns_stou(content.substr(0,pos)); | |
b9bafae0 | 1347 | boost::erase_head(content, pos); |
955e760a | 1348 | } |
b9bafae0 | 1349 | trim_left(content); |
0f310932 | 1350 | } |
f9cf6d92 | 1351 | |
b4ce8b4e | 1352 | try { |
45d36933 RG |
1353 | reconnectIfNeeded(); |
1354 | ||
08536840 PL |
1355 | d_InsertRecordQuery_stmt-> |
1356 | bind("content",content)-> | |
1357 | bind("ttl",r.ttl)-> | |
1358 | bind("priority",prio)-> | |
1359 | bind("qtype",r.qtype.getName())-> | |
1360 | bind("domain_id",r.domain_id)-> | |
1361 | bind("disabled",r.disabled)-> | |
f1c083f2 | 1362 | bind("qname",r.qname); |
08536840 | 1363 | |
c9b43446 KM |
1364 | if (!ordername.empty()) |
1365 | d_InsertRecordQuery_stmt->bind("ordername", ordername.labelReverse().makeLowerCase().toString(" ", false)); | |
0f310932 | 1366 | else |
c9b43446 | 1367 | d_InsertRecordQuery_stmt->bindNull("ordername"); |
08536840 PL |
1368 | |
1369 | if (d_dnssecQueries) | |
1370 | d_InsertRecordQuery_stmt->bind("auth", r.auth); | |
1371 | else | |
1372 | d_InsertRecordQuery_stmt->bind("auth", true); | |
1373 | ||
1374 | d_InsertRecordQuery_stmt-> | |
1375 | execute()-> | |
1376 | reset(); | |
b4ce8b4e BH |
1377 | } |
1378 | catch (SSqlException &e) { | |
63be3701 | 1379 | throw PDNSException("GSQLBackend unable to feed record: "+e.txtReason()); |
b4ce8b4e BH |
1380 | } |
1381 | return true; // XXX FIXME this API should not return 'true' I think -ahu | |
1382 | } | |
1383 | ||
223d3559 | 1384 | bool GSQLBackend::feedEnts(int domain_id, map<DNSName,bool>& nonterm) |
f9cf6d92 | 1385 | { |
424b92c6 | 1386 | for(const auto& nt: nonterm) { |
f9cf6d92 | 1387 | try { |
45d36933 RG |
1388 | reconnectIfNeeded(); |
1389 | ||
09070ce7 | 1390 | d_InsertEmptyNonTerminalOrderQuery_stmt-> |
0f310932 | 1391 | bind("domain_id",domain_id)-> |
223d3559 | 1392 | bind("qname", nt.first)-> |
09070ce7 | 1393 | bindNull("ordername")-> |
0f310932 AT |
1394 | bind("auth",(nt.second || !d_dnssecQueries))-> |
1395 | execute()-> | |
424b92c6 | 1396 | reset(); |
f9cf6d92 KM |
1397 | } |
1398 | catch (SSqlException &e) { | |
63be3701 | 1399 | throw PDNSException("GSQLBackend unable to feed empty non-terminal: "+e.txtReason()); |
f9cf6d92 KM |
1400 | } |
1401 | } | |
1402 | return true; | |
1403 | } | |
1404 | ||
28e2e78e | 1405 | bool GSQLBackend::feedEnts3(int domain_id, const DNSName &domain, map<DNSName,bool> &nonterm, const NSEC3PARAMRecordContent& ns3prc, bool narrow) |
f9cf6d92 KM |
1406 | { |
1407 | if(!d_dnssecQueries) | |
1408 | return false; | |
1409 | ||
0f310932 | 1410 | string ordername; |
e5c7239c | 1411 | |
424b92c6 | 1412 | for(const auto& nt: nonterm) { |
f9cf6d92 | 1413 | try { |
45d36933 RG |
1414 | reconnectIfNeeded(); |
1415 | ||
09070ce7 PL |
1416 | d_InsertEmptyNonTerminalOrderQuery_stmt-> |
1417 | bind("domain_id",domain_id)-> | |
1418 | bind("qname", nt.first); | |
1419 | if (narrow || !nt.second) { | |
1420 | d_InsertEmptyNonTerminalOrderQuery_stmt-> | |
1421 | bindNull("ordername"); | |
0f310932 | 1422 | } else { |
28e2e78e | 1423 | ordername=toBase32Hex(hashQNameWithSalt(ns3prc, nt.first)); |
09070ce7 PL |
1424 | d_InsertEmptyNonTerminalOrderQuery_stmt-> |
1425 | bind("ordername", ordername); | |
0f310932 | 1426 | } |
09070ce7 PL |
1427 | d_InsertEmptyNonTerminalOrderQuery_stmt-> |
1428 | bind("auth",nt.second)-> | |
1429 | execute()-> | |
1430 | reset(); | |
f9cf6d92 KM |
1431 | } |
1432 | catch (SSqlException &e) { | |
63be3701 | 1433 | throw PDNSException("GSQLBackend unable to feed empty non-terminal: "+e.txtReason()); |
f9cf6d92 KM |
1434 | } |
1435 | } | |
1436 | return true; | |
1437 | } | |
1438 | ||
223d3559 | 1439 | bool GSQLBackend::startTransaction(const DNSName &domain, int domain_id) |
b4ce8b4e BH |
1440 | { |
1441 | try { | |
45d36933 RG |
1442 | reconnectIfNeeded(); |
1443 | ||
0f310932 | 1444 | d_db->startTransaction(); |
bfa196c0 | 1445 | d_inTransaction = true; |
0f310932 AT |
1446 | if(domain_id >= 0) { |
1447 | d_DeleteZoneQuery_stmt-> | |
1448 | bind("domain_id", domain_id)-> | |
1449 | execute()-> | |
1450 | reset(); | |
1451 | } | |
b4ce8b4e BH |
1452 | } |
1453 | catch (SSqlException &e) { | |
bfa196c0 | 1454 | d_inTransaction = false; |
63be3701 | 1455 | throw PDNSException("Database failed to start transaction: "+e.txtReason()); |
b4ce8b4e BH |
1456 | } |
1457 | ||
1458 | return true; | |
1459 | } | |
1460 | ||
1461 | bool GSQLBackend::commitTransaction() | |
1462 | { | |
1463 | try { | |
0f310932 | 1464 | d_db->commit(); |
bfa196c0 | 1465 | d_inTransaction = false; |
b4ce8b4e BH |
1466 | } |
1467 | catch (SSqlException &e) { | |
bfa196c0 | 1468 | d_inTransaction = false; |
63be3701 | 1469 | throw PDNSException("Database failed to commit transaction: "+e.txtReason()); |
b4ce8b4e BH |
1470 | } |
1471 | return true; | |
1472 | } | |
1473 | ||
1474 | bool GSQLBackend::abortTransaction() | |
1475 | { | |
1476 | try { | |
0f310932 | 1477 | d_db->rollback(); |
bfa196c0 | 1478 | d_inTransaction = false; |
b4ce8b4e BH |
1479 | } |
1480 | catch(SSqlException &e) { | |
bfa196c0 | 1481 | d_inTransaction = false; |
63be3701 | 1482 | throw PDNSException("Database failed to abort transaction: "+string(e.txtReason())); |
b4ce8b4e BH |
1483 | } |
1484 | return true; | |
1485 | } | |
1486 | ||
f1013009 | 1487 | bool GSQLBackend::calculateSOASerial(const DNSName& domain, const SOAData& sd, uint32_t& serial) |
d07fc616 PD |
1488 | { |
1489 | if (d_ZoneLastChangeQuery.empty()) { | |
1490 | // query not set => fall back to default impl | |
1491 | return DNSBackend::calculateSOASerial(domain, sd, serial); | |
1492 | } | |
512eafef | 1493 | |
d07fc616 | 1494 | try { |
45d36933 RG |
1495 | reconnectIfNeeded(); |
1496 | ||
0f310932 AT |
1497 | d_ZoneLastChangeQuery_stmt-> |
1498 | bind("domain_id", sd.domain_id)-> | |
1499 | execute()-> | |
1500 | getResult(d_result)-> | |
1501 | reset(); | |
d07fc616 PD |
1502 | } |
1503 | catch (const SSqlException& e) { | |
e6a9dde5 | 1504 | //DLOG(g_log<<"GSQLBackend unable to calculate SOA serial: " << e.txtReason()<<endl); |
d07fc616 PD |
1505 | return false; |
1506 | } | |
0f310932 AT |
1507 | |
1508 | if (!d_result.empty()) { | |
7c779a31 | 1509 | ASSERT_ROW_COLUMNS("zone-lastchange-query", d_result[0], 1); |
955e760a | 1510 | serial = pdns_stou(d_result[0][0]); |
d07fc616 PD |
1511 | return true; |
1512 | } | |
1513 | ||
1514 | return false; | |
1515 | } | |
6cc98ddf CH |
1516 | |
1517 | bool GSQLBackend::listComments(const uint32_t domain_id) | |
1518 | { | |
6cc98ddf | 1519 | try { |
45d36933 RG |
1520 | reconnectIfNeeded(); |
1521 | ||
7c779a31 | 1522 | d_query_name = "list-comments-query"; |
a59a9c23 AT |
1523 | d_query_stmt = &d_ListCommentsQuery_stmt; |
1524 | (*d_query_stmt)-> | |
0f310932 AT |
1525 | bind("domain_id", domain_id)-> |
1526 | execute(); | |
6cc98ddf CH |
1527 | } |
1528 | catch(SSqlException &e) { | |
63be3701 | 1529 | throw PDNSException("GSQLBackend list comments query: "+e.txtReason()); |
6cc98ddf CH |
1530 | } |
1531 | ||
1532 | return true; | |
1533 | } | |
1534 | ||
1535 | bool GSQLBackend::getComment(Comment& comment) | |
1536 | { | |
0f310932 | 1537 | SSqlStatement::row_t row; |
6cc98ddf | 1538 | |
25dcc05f | 1539 | for(;;) { |
a59a9c23 | 1540 | if (!(*d_query_stmt)->hasNextRow()) { |
25dcc05f | 1541 | try { |
a59a9c23 | 1542 | (*d_query_stmt)->reset(); |
25dcc05f | 1543 | } catch(SSqlException &e) { |
63be3701 | 1544 | throw PDNSException("GSQLBackend comment get: "+e.txtReason()); |
25dcc05f CH |
1545 | } |
1546 | d_query_stmt = NULL; | |
1547 | return false; | |
1548 | } | |
1549 | ||
0f310932 | 1550 | try { |
a59a9c23 | 1551 | (*d_query_stmt)->nextRow(row); |
25dcc05f | 1552 | ASSERT_ROW_COLUMNS(d_query_name, row, 6); |
0f310932 | 1553 | } catch(SSqlException &e) { |
63be3701 | 1554 | throw PDNSException("GSQLBackend comment get: "+e.txtReason()); |
0f310932 | 1555 | } |
25dcc05f CH |
1556 | try { |
1557 | extractComment(row, comment); | |
1558 | } catch (...) { | |
1559 | continue; | |
1560 | } | |
1561 | return true; | |
0f310932 | 1562 | } |
6cc98ddf CH |
1563 | } |
1564 | ||
1565 | void GSQLBackend::feedComment(const Comment& comment) | |
1566 | { | |
6cc98ddf | 1567 | try { |
45d36933 RG |
1568 | reconnectIfNeeded(); |
1569 | ||
0f310932 AT |
1570 | d_InsertCommentQuery_stmt-> |
1571 | bind("domain_id",comment.domain_id)-> | |
25dcc05f | 1572 | bind("qname",comment.qname)-> |
0f310932 AT |
1573 | bind("qtype",comment.qtype.getName())-> |
1574 | bind("modified_at",comment.modified_at)-> | |
1575 | bind("account",comment.account)-> | |
1576 | bind("content",comment.content)-> | |
1577 | execute()-> | |
1578 | reset(); | |
6cc98ddf CH |
1579 | } |
1580 | catch (SSqlException &e) { | |
63be3701 | 1581 | throw PDNSException("GSQLBackend unable to feed comment: "+e.txtReason()); |
6cc98ddf CH |
1582 | } |
1583 | } | |
1584 | ||
8f126bc1 | 1585 | bool GSQLBackend::replaceComments(const uint32_t domain_id, const DNSName& qname, const QType& qt, const vector<Comment>& comments) |
6cc98ddf | 1586 | { |
f374debc | 1587 | try { |
45d36933 RG |
1588 | reconnectIfNeeded(); |
1589 | ||
0f310932 AT |
1590 | d_DeleteCommentRRsetQuery_stmt-> |
1591 | bind("domain_id",domain_id)-> | |
8f126bc1 | 1592 | bind("qname", qname)-> |
0f310932 AT |
1593 | bind("qtype",qt.getName())-> |
1594 | execute()-> | |
1595 | reset(); | |
f374debc KM |
1596 | } |
1597 | catch (SSqlException &e) { | |
63be3701 | 1598 | throw PDNSException("GSQLBackend unable to delete comment: "+e.txtReason()); |
f374debc | 1599 | } |
6cc98ddf | 1600 | |
424b92c6 | 1601 | for(const auto& comment: comments) { |
6cc98ddf CH |
1602 | feedComment(comment); |
1603 | } | |
1604 | ||
1605 | return true; | |
1606 | } | |
0f310932 | 1607 | |
f641c3b7 PD |
1608 | string GSQLBackend::directBackendCmd(const string &query) |
1609 | { | |
1610 | try { | |
1611 | ostringstream out; | |
1612 | ||
a59a9c23 | 1613 | auto stmt = d_db->prepare(query,0); |
f641c3b7 | 1614 | |
45d36933 RG |
1615 | reconnectIfNeeded(); |
1616 | ||
f641c3b7 PD |
1617 | stmt->execute(); |
1618 | ||
1619 | SSqlStatement::row_t row; | |
1620 | ||
1621 | while(stmt->hasNextRow()) { | |
1622 | stmt->nextRow(row); | |
424b92c6 | 1623 | for(const auto& col: row) |
f641c3b7 PD |
1624 | out<<"\'"<<col<<"\'\t"; |
1625 | out<<endl; | |
1626 | } | |
1627 | ||
1628 | return out.str(); | |
1629 | } | |
1630 | catch (SSqlException &e) { | |
63be3701 | 1631 | throw PDNSException("GSQLBackend unable to execute query: "+e.txtReason()); |
f641c3b7 PD |
1632 | } |
1633 | } | |
1634 | ||
474cacfa AT |
1635 | string GSQLBackend::pattern2SQLPattern(const string &pattern) |
1636 | { | |
1637 | string escaped_pattern = boost::replace_all_copy(pattern,"\\","\\\\"); | |
1638 | boost::replace_all(escaped_pattern,"_","\\_"); | |
1639 | boost::replace_all(escaped_pattern,"%","\\%"); | |
1640 | boost::replace_all(escaped_pattern,"*","%"); | |
1641 | boost::replace_all(escaped_pattern,"?","_"); | |
1642 | return escaped_pattern; | |
1643 | } | |
1644 | ||
1645 | bool GSQLBackend::searchRecords(const string &pattern, int maxResults, vector<DNSResourceRecord>& result) | |
1646 | { | |
25dcc05f | 1647 | d_qname.clear(); |
474cacfa AT |
1648 | try { |
1649 | string escaped_pattern = pattern2SQLPattern(pattern); | |
1650 | ||
45d36933 RG |
1651 | reconnectIfNeeded(); |
1652 | ||
474cacfa AT |
1653 | d_SearchRecordsQuery_stmt-> |
1654 | bind("value", escaped_pattern)-> | |
1655 | bind("value2", escaped_pattern)-> | |
1656 | bind("limit", maxResults)-> | |
1657 | execute(); | |
1658 | ||
1659 | while(d_SearchRecordsQuery_stmt->hasNextRow()) | |
1660 | { | |
1661 | SSqlStatement::row_t row; | |
1662 | DNSResourceRecord r; | |
1663 | d_SearchRecordsQuery_stmt->nextRow(row); | |
7c779a31 | 1664 | ASSERT_ROW_COLUMNS("search-records-query", row, 8); |
8408d2a6 KM |
1665 | try { |
1666 | extractRecord(row, r); | |
1667 | } catch (...) { | |
1668 | continue; | |
1669 | } | |
474cacfa AT |
1670 | result.push_back(r); |
1671 | } | |
1672 | ||
1673 | d_SearchRecordsQuery_stmt->reset(); | |
1674 | ||
1675 | return true; | |
1676 | } | |
1677 | catch (SSqlException &e) { | |
63be3701 | 1678 | throw PDNSException("GSQLBackend unable to execute query: "+e.txtReason()); |
474cacfa AT |
1679 | } |
1680 | ||
1681 | return false; | |
1682 | } | |
1683 | ||
1684 | bool GSQLBackend::searchComments(const string &pattern, int maxResults, vector<Comment>& result) | |
1685 | { | |
1686 | Comment c; | |
1687 | try { | |
1688 | string escaped_pattern = pattern2SQLPattern(pattern); | |
1689 | ||
45d36933 RG |
1690 | reconnectIfNeeded(); |
1691 | ||
474cacfa | 1692 | d_SearchCommentsQuery_stmt-> |
0ec0ee4f AT |
1693 | bind("value", escaped_pattern)-> |
1694 | bind("value2", escaped_pattern)-> | |
474cacfa AT |
1695 | bind("limit", maxResults)-> |
1696 | execute(); | |
1697 | ||
1698 | while(d_SearchCommentsQuery_stmt->hasNextRow()) { | |
1699 | SSqlStatement::row_t row; | |
1700 | d_SearchCommentsQuery_stmt->nextRow(row); | |
7c779a31 | 1701 | ASSERT_ROW_COLUMNS("search-comments-query", row, 6); |
474cacfa | 1702 | Comment comment; |
512ad04f | 1703 | extractComment(row, comment); |
474cacfa AT |
1704 | result.push_back(comment); |
1705 | } | |
1706 | ||
1707 | d_SearchRecordsQuery_stmt->reset(); | |
1708 | ||
1709 | return true; | |
1710 | } | |
1711 | catch (SSqlException &e) { | |
63be3701 | 1712 | throw PDNSException("GSQLBackend unable to execute query: "+e.txtReason()); |
474cacfa AT |
1713 | } |
1714 | ||
1715 | return false; | |
1716 | } | |
1717 | ||
1718 | void GSQLBackend::extractRecord(const SSqlStatement::row_t& row, DNSResourceRecord& r) | |
1719 | { | |
1720 | if (row[1].empty()) | |
1721 | r.ttl = ::arg().asNum( "default-ttl" ); | |
1722 | else | |
955e760a | 1723 | r.ttl=pdns_stou(row[1]); |
474cacfa AT |
1724 | if(!d_qname.empty()) |
1725 | r.qname=d_qname; | |
1726 | else | |
290a083d | 1727 | r.qname=DNSName(row[6]); |
2e9974be | 1728 | |
474cacfa AT |
1729 | r.qtype=row[3]; |
1730 | ||
e1f36dce | 1731 | if (r.qtype==QType::MX || r.qtype==QType::SRV) |
474cacfa | 1732 | r.content=row[2]+" "+row[0]; |
e1f36dce | 1733 | else |
474cacfa AT |
1734 | r.content=row[0]; |
1735 | ||
1736 | r.last_modified=0; | |
1737 | ||
1738 | if(d_dnssecQueries) | |
1739 | r.auth = !row[7].empty() && row[7][0]=='1'; | |
1740 | else | |
1741 | r.auth = 1; | |
1742 | ||
1743 | r.disabled = !row[5].empty() && row[5][0]=='1'; | |
1744 | ||
955e760a | 1745 | r.domain_id=pdns_stou(row[4]); |
474cacfa | 1746 | } |
f641c3b7 | 1747 | |
512ad04f AT |
1748 | void GSQLBackend::extractComment(const SSqlStatement::row_t& row, Comment& comment) |
1749 | { | |
25dcc05f CH |
1750 | comment.domain_id = pdns_stou(row[0]); |
1751 | comment.qname = DNSName(row[1]); | |
1752 | comment.qtype = row[2]; | |
1753 | comment.modified_at = pdns_stou(row[3]); | |
1754 | comment.account = row[4]; | |
1755 | comment.content = row[5]; | |
512ad04f AT |
1756 | } |
1757 | ||
0f310932 AT |
1758 | SSqlStatement::~SSqlStatement() { |
1759 | // make sure vtable won't break | |
1760 | } |