[-]
[+]
|
Changed |
pdns-3.2-allow-axfr-from.patch
|
@@ -1,5 +1,5 @@
---- pdns/backends/gsql/gsqlbackend.cc 2013-04-23 10:52:06.495487248 +0200
-+++ pdns/backends/gsql/gsqlbackend.cc 2013-04-23 10:58:18.797423413 +0200
+--- pdns/backends/gsql/gsqlbackend.cc 2013-05-03 10:28:03.153764623 +0200
++++ pdns/backends/gsql/gsqlbackend.cc 2013-05-03 10:29:36.217221341 +0200
@@ -284,6 +284,9 @@
d_removeEmptyNonTerminalsFromZoneQuery = getArg("remove-empty-non-terminals-from-zone-query");
d_insertEmptyNonTerminalQuery = getArg("insert-empty-non-terminal-query"+authswitch);
@@ -20,13 +20,13 @@
d_ClearDomainMetadataQuery = getArg("clear-domain-metadata-query");
d_SetDomainMetadataQuery = getArg("set-domain-metadata-query");
-@@ -637,7 +641,7 @@
+@@ -637,8 +641,8 @@
bool GSQLBackend::getDomainMetadata(const string& name, const std::string& kind, std::vector<std::string>& meta)
{
- if(!d_dnssecQueries)
- return false;
-+// if(!d_dnssecQueries)
-+// return false;
++ /* if(!d_dnssecQueries)
++ return false; */
char output[1024];
snprintf(output,sizeof(output)-1,d_GetDomainMetadataQuery.c_str(), sqlEscape(name).c_str(), sqlEscape(kind).c_str());
|
[-]
[+]
|
Changed |
pdns-3.2.tar.gz/pdns/backends/gsql/gsqlbackend.cc
^
|
@@ -284,9 +284,6 @@
d_removeEmptyNonTerminalsFromZoneQuery = getArg("remove-empty-non-terminals-from-zone-query");
d_insertEmptyNonTerminalQuery = getArg("insert-empty-non-terminal-query"+authswitch);
d_deleteEmptyNonTerminalQuery = getArg("delete-empty-non-terminal-query");
-
- // Define domainmetadata queries independent from dnssec functionality
- d_GetDomainMetadataQuery = getArg("get-domain-metadata-query");
if (d_dnssecQueries)
{
@@ -302,8 +299,7 @@
d_AddDomainKeyQuery = getArg("add-domain-key-query");
d_ListDomainKeysQuery = getArg("list-domain-keys-query");
- // Already defined outside of dnssec functionality
- // d_GetDomainMetadataQuery = getArg("get-domain-metadata-query");
+ d_GetDomainMetadataQuery = getArg("get-domain-metadata-query");
d_ClearDomainMetadataQuery = getArg("clear-domain-metadata-query");
d_SetDomainMetadataQuery = getArg("set-domain-metadata-query");
@@ -641,8 +637,8 @@
bool GSQLBackend::getDomainMetadata(const string& name, const std::string& kind, std::vector<std::string>& meta)
{
-// if(!d_dnssecQueries)
-// return false;
+ if(!d_dnssecQueries)
+ return false;
char output[1024];
snprintf(output,sizeof(output)-1,d_GetDomainMetadataQuery.c_str(), sqlEscape(name).c_str(), sqlEscape(kind).c_str());
|
[-]
[+]
|
Deleted |
pdns-3.2.tar.gz/pdns/backends/gsql/gsqlbackend.cc~
^
|
@@ -1,975 +0,0 @@
-/*
- PowerDNS Versatile Database Driven Nameserver
- Copyright (C) 2002-2011 PowerDNS.COM BV
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License version 2 as
- published by the Free Software Foundation
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-
-// $Id: gsqlbackend.cc 2979 2012-12-10 11:09:17Z peter $
-#ifdef WIN32
-# pragma warning ( disable: 4786 )
-#endif // WIN32
-
-#include <string>
-#include <map>
-
-#include "namespaces.hh"
-
-#include "pdns/dns.hh"
-#include "pdns/dnsbackend.hh"
-#include "gsqlbackend.hh"
-#include "pdns/dnspacket.hh"
-#include "pdns/ueberbackend.hh"
-#include "pdns/ahuexception.hh"
-#include "pdns/logger.hh"
-#include "pdns/arguments.hh"
-#include <boost/algorithm/string.hpp>
-#include <sstream>
-#include <boost/foreach.hpp>
-#include <boost/format.hpp>
-
-
-
-void GSQLBackend::setNotified(uint32_t domain_id, uint32_t serial)
-{
- char output[1024];
- snprintf(output,sizeof(output)-1,
- d_UpdateSerialOfZoneQuery.c_str(),
- serial, domain_id);
-
- try {
- d_db->doCommand(output);
- }
- catch(SSqlException &e) {
- throw AhuException("GSQLBackend unable to refresh domain_id "+itoa(domain_id)+": "+e.txtReason());
- }
-}
-
-void GSQLBackend::setFresh(uint32_t domain_id)
-{
- char output[1024];
- snprintf(output,sizeof(output)-1,d_UpdateLastCheckofZoneQuery.c_str(),
- time(0),
- domain_id);
-
- try {
- d_db->doCommand(output);
- }
- catch (SSqlException &e) {
- throw AhuException("GSQLBackend unable to refresh domain_id "+itoa(domain_id)+": "+e.txtReason());
- }
-}
-
-bool GSQLBackend::isMaster(const string &domain, const string &ip)
-{
- char output[1024];
- snprintf(output,sizeof(output)-1,
- d_MasterOfDomainsZoneQuery.c_str(),
- sqlEscape(domain).c_str());
- try {
- d_db->doQuery(output, d_result);
- }
- catch (SSqlException &e) {
- throw AhuException("GSQLBackend unable to retrieve list of master domains: "+e.txtReason());
- }
-
- if(d_result.empty())
- return 0;
-
- // we can have multiple masters separated by commas
- vector<string> masters;
- stringtok(masters, d_result[0][0], " ,\t");
- for(vector<string>::const_iterator iter=masters.begin(); iter != masters.end(); ++iter) {
- // we can also have masters with a port specified (which we ignore here)
- ServiceTuple st;
- parseService(*iter, st);
- if (!strcmp(ip.c_str(), st.host.c_str())) {
- return 1;
- }
- }
-
- // if no masters matched then this is not a master
- return 0;
-}
-
-bool GSQLBackend::getDomainInfo(const string &domain, DomainInfo &di)
-{
- /* list all domains that need refreshing for which we are slave, and insert into SlaveDomain:
- id,name,master IP,serial */
- char output[1024];
- snprintf(output,sizeof(output)-1,d_InfoOfDomainsZoneQuery.c_str(),
- sqlEscape(domain).c_str());
- try {
- d_db->doQuery(output,d_result);
- }
- catch(SSqlException &e) {
- throw AhuException("GSQLBackend unable to retrieve information about a domain: "+e.txtReason());
- }
-
- int numanswers=d_result.size();
- if(!numanswers)
- return false;
-
- di.id=atol(d_result[0][0].c_str());
- di.zone=d_result[0][1];
- stringtok(di.masters, d_result[0][2], " ,\t");
- di.last_check=atol(d_result[0][3].c_str());
- di.backend=this;
-
- string type=d_result[0][5];
- if(pdns_iequals(type,"SLAVE")) {
- di.serial=0;
- try {
- SOAData sd;
- if(!getSOA(domain,sd))
- L<<Logger::Notice<<"No serial for '"<<domain<<"' found - zone is missing?"<<endl;
- else
- di.serial=sd.serial;
- }
- catch(AhuException &ae){
- L<<Logger::Error<<"Error retrieving serial for '"<<domain<<"': "<<ae.reason<<endl;
- }
-
- di.kind=DomainInfo::Slave;
- }
- else if(pdns_iequals(type,"MASTER"))
- di.kind=DomainInfo::Master;
- else
- di.kind=DomainInfo::Native;
-
- return true;
-}
-
-void GSQLBackend::getUnfreshSlaveInfos(vector<DomainInfo> *unfreshDomains)
-{
- /* list all domains that need refreshing for which we are slave, and insert into SlaveDomain:
- id,name,master IP,serial */
- try {
- d_db->doQuery(d_InfoOfAllSlaveDomainsQuery, d_result);
- }
- catch (SSqlException &e) {
- throw AhuException("GSQLBackend unable to retrieve list of slave domains: "+e.txtReason());
- }
-
- vector<DomainInfo> allSlaves;
- int numanswers=d_result.size();
- for(int n=0;n<numanswers;++n) { // id,name,master,last_check
- DomainInfo sd;
- sd.id=atol(d_result[n][0].c_str());
- sd.zone=d_result[n][1];
- stringtok(sd.masters, d_result[n][2], ", \t");
- sd.last_check=atol(d_result[n][3].c_str());
- sd.backend=this;
- sd.kind=DomainInfo::Slave;
- allSlaves.push_back(sd);
- }
-
- for(vector<DomainInfo>::iterator i=allSlaves.begin();i!=allSlaves.end();++i) {
- SOAData sdata;
- sdata.serial=0;
- sdata.refresh=0;
- getSOA(i->zone,sdata);
- if((time_t)(i->last_check+sdata.refresh) < time(0)) {
- i->serial=sdata.serial;
- unfreshDomains->push_back(*i);
- }
- }
-}
-
-void GSQLBackend::getUpdatedMasters(vector<DomainInfo> *updatedDomains)
-{
- /* list all domains that need notifications for which we are master, and insert into updatedDomains
- id,name,master IP,serial */
- try {
- d_db->doQuery(d_InfoOfAllMasterDomainsQuery,d_result);
- }
- catch(SSqlException &e) {
- throw AhuException("GSQLBackend unable to retrieve list of master domains: "+e.txtReason());
- }
-
- vector<DomainInfo> allMasters;
- int numanswers=d_result.size();
- for(int n=0;n<numanswers;++n) { // id,name,master,last_check
- DomainInfo sd;
- sd.id=atol(d_result[n][0].c_str());
- sd.zone=d_result[n][1];
- sd.last_check=atol(d_result[n][3].c_str());
- sd.notified_serial=atoi(d_result[n][4].c_str());
- sd.backend=this;
- sd.kind=DomainInfo::Master;
- allMasters.push_back(sd);
- }
-
- for(vector<DomainInfo>::iterator i=allMasters.begin();i!=allMasters.end();++i) {
- SOAData sdata;
- sdata.serial=0;
- sdata.refresh=0;
- getSOA(i->zone,sdata);
- if(i->notified_serial!=sdata.serial) {
- i->serial=sdata.serial;
- updatedDomains->push_back(*i);
- }
- }
-}
-
-
-string GSQLBackend::sqlEscape(const string &name)
-{
- string a;
-
- for(string::const_iterator i=name.begin();i!=name.end();++i)
- if(*i=='\'' || *i=='\\'){
- a+='\\';
- a+=*i;
- }
- else
- a+=*i;
- return a;
-}
-
-
-GSQLBackend::GSQLBackend(const string &mode, const string &suffix)
-{
- setArgPrefix(mode+suffix);
- d_db=0;
- d_logprefix="["+mode+"Backend"+suffix+"] ";
-
- try
- {
- d_dnssecQueries = mustDo("dnssec");
- }
- catch (ArgException e)
- {
- d_dnssecQueries = false;
- }
-
- string authswitch = d_dnssecQueries ? "-auth" : "";
- d_noWildCardNoIDQuery=getArg("basic-query"+authswitch);
- d_noWildCardIDQuery=getArg("id-query"+authswitch);
- d_wildCardNoIDQuery=getArg("wildcard-query"+authswitch);
- d_wildCardIDQuery=getArg("wildcard-id-query"+authswitch);
-
- d_noWildCardANYNoIDQuery=getArg("any-query"+authswitch);
- d_noWildCardANYIDQuery=getArg("any-id-query"+authswitch);
- d_wildCardANYNoIDQuery=getArg("wildcard-any-query"+authswitch);
- d_wildCardANYIDQuery=getArg("wildcard-any-id-query"+authswitch);
-
- d_listQuery=getArg("list-query"+authswitch);
-
- d_MasterOfDomainsZoneQuery=getArg("master-zone-query");
- d_InfoOfDomainsZoneQuery=getArg("info-zone-query");
- d_InfoOfAllSlaveDomainsQuery=getArg("info-all-slaves-query");
- d_SuperMasterInfoQuery=getArg("supermaster-query");
- d_InsertSlaveZoneQuery=getArg("insert-slave-query");
- d_InsertRecordQuery=getArg("insert-record-query"+authswitch);
- d_UpdateSerialOfZoneQuery=getArg("update-serial-query");
- d_UpdateLastCheckofZoneQuery=getArg("update-lastcheck-query");
- d_ZoneLastChangeQuery=getArg("zone-lastchange-query");
- d_InfoOfAllMasterDomainsQuery=getArg("info-all-master-query");
- d_DeleteZoneQuery=getArg("delete-zone-query");
- d_DeleteRRSet=getArg("delete-rrset-query");
- d_getAllDomainsQuery=getArg("get-all-domains-query");
-
- d_removeEmptyNonTerminalsFromZoneQuery = getArg("remove-empty-non-terminals-from-zone-query");
- d_insertEmptyNonTerminalQuery = getArg("insert-empty-non-terminal-query"+authswitch);
- d_deleteEmptyNonTerminalQuery = getArg("delete-empty-non-terminal-query");
-
- // Define domainmetadata queries independent from dnssec functionality
- d_GetDomainMetadataQuery = getArg("get-domain-metadata-query");
-
- if (d_dnssecQueries)
- {
- d_firstOrderQuery = getArg("get-order-first-query");
- d_beforeOrderQuery = getArg("get-order-before-query");
- d_afterOrderQuery = getArg("get-order-after-query");
- d_lastOrderQuery = getArg("get-order-last-query");
- d_setOrderAuthQuery = getArg("set-order-and-auth-query");
- d_nullifyOrderNameAndUpdateAuthQuery = getArg("nullify-ordername-and-update-auth-query");
- d_nullifyOrderNameAndAuthQuery = getArg("nullify-ordername-and-auth-query");
- d_setAuthOnDsRecordQuery = getArg("set-auth-on-ds-record-query");
-
- d_AddDomainKeyQuery = getArg("add-domain-key-query");
- d_ListDomainKeysQuery = getArg("list-domain-keys-query");
-
- // Already defined outside of dnssec functionality
- // d_GetDomainMetadataQuery = getArg("get-domain-metadata-query");
- d_ClearDomainMetadataQuery = getArg("clear-domain-metadata-query");
- d_SetDomainMetadataQuery = getArg("set-domain-metadata-query");
-
- d_ActivateDomainKeyQuery = getArg("activate-domain-key-query");
- d_DeactivateDomainKeyQuery = getArg("deactivate-domain-key-query");
- d_RemoveDomainKeyQuery = getArg("remove-domain-key-query");
-
- d_getTSIGKeyQuery = getArg("get-tsig-key-query");
- }
-}
-
-bool GSQLBackend::updateDNSSECOrderAndAuth(uint32_t domain_id, const std::string& zonename, const std::string& qname, bool auth)
-{
- if(!d_dnssecQueries)
- return false;
- string ins=toLower(labelReverse(makeRelative(qname, zonename)));
- return this->updateDNSSECOrderAndAuthAbsolute(domain_id, qname, ins, auth);
-}
-
-bool GSQLBackend::updateDNSSECOrderAndAuthAbsolute(uint32_t domain_id, const std::string& qname, const std::string& ordername, bool auth)
-{
- if(!d_dnssecQueries)
- return false;
- char output[1024];
-
- snprintf(output, sizeof(output)-1, d_setOrderAuthQuery.c_str(), sqlEscape(ordername).c_str(), auth, sqlEscape(qname).c_str(), domain_id);
- try {
- d_db->doCommand(output);
- }
- catch(SSqlException &e) {
- throw AhuException("GSQLBackend unable to update ordername/auth for domain_id "+itoa(domain_id)+": "+e.txtReason());
- }
- return true;
-}
-
-bool GSQLBackend::nullifyDNSSECOrderNameAndUpdateAuth(uint32_t domain_id, const std::string& qname, bool auth)
-{
- if(!d_dnssecQueries)
- return false;
- char output[1024];
-
- snprintf(output, sizeof(output)-1, d_nullifyOrderNameAndUpdateAuthQuery.c_str(), auth, domain_id, sqlEscape(qname).c_str());
- try {
- d_db->doCommand(output);
- }
- catch(SSqlException &e) {
- throw AhuException("GSQLBackend unable to nullify ordername and update auth for domain_id "+itoa(domain_id)+": "+e.txtReason());
- }
- return true;
-}
-
-bool GSQLBackend::nullifyDNSSECOrderNameAndAuth(uint32_t domain_id, const std::string& qname, const std::string& type)
-{
- if(!d_dnssecQueries)
- return false;
- char output[1024];
-
- snprintf(output, sizeof(output)-1, d_nullifyOrderNameAndAuthQuery.c_str(), sqlEscape(qname).c_str(), sqlEscape(type).c_str(), domain_id);
- try {
- d_db->doCommand(output);
- }
- catch(SSqlException &e) {
- throw AhuException("GSQLBackend unable to nullify ordername/auth for domain_id "+itoa(domain_id)+": "+e.txtReason());
- }
- return true;
-}
-
-bool GSQLBackend::setDNSSECAuthOnDsRecord(uint32_t domain_id, const std::string& qname)
-{
- if(!d_dnssecQueries)
- return false;
- char output[1024];
-
- snprintf(output, sizeof(output)-1, d_setAuthOnDsRecordQuery.c_str(), domain_id, sqlEscape(qname).c_str());
- try {
- d_db->doCommand(output);
- }
- catch(SSqlException &e) {
- throw AhuException("GSQLBackend unable to set auth on DS record "+qname+" for domain_id "+itoa(domain_id)+": "+e.txtReason());
- }
- return true;
-}
-
-bool GSQLBackend::updateEmptyNonTerminals(uint32_t domain_id, const std::string& zonename, set<string>& insert, set<string>& erase, bool remove)
-{
- char output[1024];
-
- if(remove) {
- snprintf(output,sizeof(output)-1,d_removeEmptyNonTerminalsFromZoneQuery.c_str(), domain_id);
- try {
- d_db->doCommand(output);
- }
- catch (SSqlException &e) {
- throw AhuException("GSQLBackend unable to delete empty non-terminal records from domain_id "+itoa(domain_id)+": "+e.txtReason());
- return false;
- }
- }
- else
- {
- BOOST_FOREACH(const string qname, erase) {
- snprintf(output,sizeof(output)-1,d_deleteEmptyNonTerminalQuery.c_str(), domain_id, sqlEscape(qname).c_str());
- try {
- d_db->doCommand(output);
- }
- catch (SSqlException &e) {
- throw AhuException("GSQLBackend unable to delete empty non-terminal rr "+qname+" from domain_id "+itoa(domain_id)+": "+e.txtReason());
- return false;
- }
- }
- }
-
- BOOST_FOREACH(const string qname, insert) {
- snprintf(output,sizeof(output)-1,d_insertEmptyNonTerminalQuery.c_str(), domain_id, sqlEscape(qname).c_str());
- try {
- d_db->doCommand(output);
- }
- catch (SSqlException &e) {
- throw AhuException("GSQLBackend unable to insert empty non-terminal rr "+qname+" in domain_id "+itoa(domain_id)+": "+e.txtReason());
- return false;
- }
- }
-
- return true;
-}
-
-bool GSQLBackend::doesDNSSEC()
-{
- return d_dnssecQueries;
-}
-
-bool GSQLBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const std::string& qname, std::string& unhashed, std::string& before, std::string& after)
-{
- if(!d_dnssecQueries)
- return false;
- // cerr<<"gsql before/after called for id="<<id<<", qname='"<<qname<<"'"<<endl;
- unhashed.clear(); before.clear(); after.clear();
- string lcqname=toLower(qname);
-
- SSql::row_t row;
-
- char output[1024];
-
- snprintf(output, sizeof(output)-1, d_afterOrderQuery.c_str(), sqlEscape(lcqname).c_str(), id);
-
- try {
- d_db->doQuery(output);
- }
- catch(SSqlException &e) {
- throw AhuException("GSQLBackend unable to find before/after (after) for domain_id "+itoa(id)+": "+e.txtReason());
- }
-
- while(d_db->getRow(row)) {
- after=row[0];
- }
-
- if(after.empty() && !lcqname.empty()) {
- snprintf(output, sizeof(output)-1, d_firstOrderQuery.c_str(), id);
-
- try {
- d_db->doQuery(output);
- }
- catch(SSqlException &e) {
- throw AhuException("GSQLBackend unable to find before/after (first) for domain_id "+itoa(id)+": "+e.txtReason());
- }
- while(d_db->getRow(row)) {
- after=row[0];
- }
- }
-
- snprintf(output, sizeof(output)-1, d_beforeOrderQuery.c_str(), sqlEscape(lcqname).c_str(), id);
- try {
- d_db->doQuery(output);
- }
- catch(SSqlException &e) {
- throw AhuException("GSQLBackend unable to find before/after (before) for domain_id "+itoa(id)+": "+e.txtReason());
- }
- while(d_db->getRow(row)) {
- before=row[0];
- unhashed=row[1];
- }
-
- if(! unhashed.empty())
- {
- // cerr<<"unhashed="<<unhashed<<",before="<<before<<", after="<<after<<endl;
- return true;
- }
-
- snprintf(output, sizeof(output)-1, d_lastOrderQuery.c_str(), id);
- try {
- d_db->doQuery(output);
- }
- catch(SSqlException &e) {
- throw AhuException("GSQLBackend unable to find before/after (last) for domain_id "+itoa(id)+": "+e.txtReason());
- }
- while(d_db->getRow(row)) {
- before=row[0];
- unhashed=row[1];
- }
-
- return true;
-}
-
-int GSQLBackend::addDomainKey(const string& name, const KeyData& key)
-{
- if(!d_dnssecQueries)
- return -1;
- char output[16384];
- snprintf(output,sizeof(output)-1,d_AddDomainKeyQuery.c_str(),
- key.flags, (int)key.active, sqlEscape(key.content).c_str(), sqlEscape(toLower(name)).c_str());
-
- try {
- d_db->doCommand(output);
- }
- catch (SSqlException &e) {
- throw AhuException("GSQLBackend unable to store key: "+e.txtReason());
- }
- return 1; // XXX FIXME, no idea how to get the id
-}
-
-bool GSQLBackend::activateDomainKey(const string& name, unsigned int id)
-{
- if(!d_dnssecQueries)
- return false;
- char output[1024];
- snprintf(output,sizeof(output)-1,d_ActivateDomainKeyQuery.c_str(), sqlEscape(toLower(name)).c_str(), id);
-
- try {
- d_db->doCommand(output);
- }
- catch (SSqlException &e) {
- throw AhuException("GSQLBackend unable to activate key: "+e.txtReason());
- }
- return true;
-}
-
-bool GSQLBackend::deactivateDomainKey(const string& name, unsigned int id)
-{
- if(!d_dnssecQueries)
- return false;
- char output[1024];
- snprintf(output,sizeof(output)-1,d_DeactivateDomainKeyQuery.c_str(), sqlEscape(toLower(name)).c_str(), id);
-
- try {
- d_db->doCommand(output);
- }
- catch (SSqlException &e) {
- throw AhuException("GSQLBackend unable to deactivate key: "+e.txtReason());
- }
- return true;
-}
-
-bool GSQLBackend::removeDomainKey(const string& name, unsigned int id)
-{
- if(!d_dnssecQueries)
- return false;
- char output[1024];
- snprintf(output,sizeof(output)-1,d_RemoveDomainKeyQuery.c_str(), sqlEscape(toLower(name)).c_str(), id);
-
- try {
- d_db->doCommand(output);
- }
- catch (SSqlException &e) {
- throw AhuException("GSQLBackend unable to remove key: "+e.txtReason());
- }
- return true;
-}
-
-bool GSQLBackend::getTSIGKey(const string& name, string* algorithm, string* content)
-{
- if(!d_dnssecQueries)
- return false;
-
- char output[1024];
- snprintf(output,sizeof(output)-1,d_getTSIGKeyQuery.c_str(), sqlEscape(toLower(name)).c_str());
-
- try {
- d_db->doQuery(output);
- }
- catch (SSqlException &e) {
- throw AhuException("GSQLBackend unable to retrieve named TSIG key: "+e.txtReason());
- }
-
- SSql::row_t row;
-
- content->clear();
- while(d_db->getRow(row)) {
- *algorithm = row[0];
- *content=row[1];
- }
-
- return !content->empty();
-}
-
-bool GSQLBackend::getDomainKeys(const string& name, unsigned int kind, std::vector<KeyData>& keys)
-{
- if(!d_dnssecQueries)
- return false;
- char output[1024];
- snprintf(output,sizeof(output)-1,d_ListDomainKeysQuery.c_str(), sqlEscape(toLower(name)).c_str());
-
- try {
- d_db->doQuery(output);
- }
- catch (SSqlException &e) {
- throw AhuException("GSQLBackend unable to list keys: "+e.txtReason());
- }
-
- SSql::row_t row;
- // "select id, kind, active, content from domains, cryptokeys where domain_id=domains.id and name='%s'";
- KeyData kd;
- while(d_db->getRow(row)) {
- //~ BOOST_FOREACH(const std::string& val, row) {
- //~ cerr<<"'"<<val<<"'"<<endl;
- //~ }
- kd.id = atoi(row[0].c_str());
- kd.flags = atoi(row[1].c_str());
- kd.active = atoi(row[2].c_str());
- kd.content = row[3];
- keys.push_back(kd);
- }
-
- return true;
-}
-
-void GSQLBackend::alsoNotifies(const string &domain, set<string> *ips)
-{
- if(!d_dnssecQueries)
- return;
- vector<string> meta;
- getDomainMetadata(domain, "ALSO-NOTIFY", meta);
- BOOST_FOREACH(string& str, meta) {
- ips->insert(str);
- }
-}
-
-bool GSQLBackend::getDomainMetadata(const string& name, const std::string& kind, std::vector<std::string>& meta)
-{
-// if(!d_dnssecQueries)
-// return false;
- char output[1024];
- snprintf(output,sizeof(output)-1,d_GetDomainMetadataQuery.c_str(), sqlEscape(name).c_str(), sqlEscape(kind).c_str());
-
- try {
- d_db->doQuery(output);
- }
- catch (SSqlException &e) {
- throw AhuException("GSQLBackend unable to list metadata: "+e.txtReason());
- }
-
- SSql::row_t row;
-
- while(d_db->getRow(row)) {
- meta.push_back(row[0]);
- }
- return true;
-}
-
-bool GSQLBackend::setDomainMetadata(const string& name, const std::string& kind, const std::vector<std::string>& meta)
-{
- char output[16384];
- if(!d_dnssecQueries)
- return false;
-
- if(!meta.empty())
- snprintf(output,sizeof(output)-1,d_SetDomainMetadataQuery.c_str(),
- sqlEscape(kind).c_str(), sqlEscape(*meta.begin()).c_str(), sqlEscape(name).c_str());
-
- string clearQuery = (boost::format(d_ClearDomainMetadataQuery) % sqlEscape(name) % sqlEscape(kind)).str();
-
- try {
- d_db->doCommand(clearQuery);
- if(!meta.empty())
- d_db->doCommand(output);
- }
- catch (SSqlException &e) {
- throw AhuException("GSQLBackend unable to store metadata key: "+e.txtReason());
- }
-
- return true;
-}
-
-
-void GSQLBackend::lookup(const QType &qtype,const string &qname, DNSPacket *pkt_p, int domain_id)
-{
- string format;
- char output[1024];
-
- d_db->setLog(::arg().mustDo("query-logging"));
-
- string lcqname=toLower(qname);
-
- // lcqname=labelReverse(makeRelative(lcqname, "net"));
-
- if(qtype.getCode()!=QType::ANY) {
- // qtype qname domain_id
- if(domain_id<0) {
- if(qname[0]=='%')
- format=d_wildCardNoIDQuery;
- else
- format=d_noWildCardNoIDQuery;
-
- snprintf(output,sizeof(output)-1, format.c_str(),sqlEscape(qtype.getName()).c_str(), sqlEscape(lcqname).c_str());
- }
- else {
- if(qname[0]!='%')
- format=d_noWildCardIDQuery;
- else
- format=d_wildCardIDQuery;
- snprintf(output,sizeof(output)-1, format.c_str(),sqlEscape(qtype.getName()).c_str(),sqlEscape(lcqname).c_str(),domain_id);
- }
- }
- else {
- // qtype==ANY
- // qname domain_id
- if(domain_id<0) {
- if(qname[0]=='%')
- format=d_wildCardANYNoIDQuery;
- else
- format=d_noWildCardANYNoIDQuery;
-
- snprintf(output,sizeof(output)-1, format.c_str(),sqlEscape(lcqname).c_str());
- }
- else {
- if(qname[0]!='%')
- format=d_noWildCardANYIDQuery;
- else
- format=d_wildCardANYIDQuery;
- snprintf(output,sizeof(output)-1, format.c_str(),sqlEscape(lcqname).c_str(),domain_id);
- }
- }
-
- try {
- d_db->doQuery(output);
- }
- catch(SSqlException &e) {
- throw AhuException(e.txtReason());
- }
-
- d_qname=qname;
-
- d_qtype=qtype;
- d_count=0;
-}
-bool GSQLBackend::list(const string &target, int domain_id )
-{
- DLOG(L<<"GSQLBackend constructing handle for list of domain id '"<<domain_id<<"'"<<endl);
-
- char output[1024];
- snprintf(output,sizeof(output)-1,d_listQuery.c_str(),domain_id);
- try {
- d_db->doQuery(output);
- }
- catch(SSqlException &e) {
- throw AhuException("GSQLBackend list query: "+e.txtReason());
- }
-
- d_qname="";
- d_count=0;
- return true;
-}
-
-bool GSQLBackend::superMasterBackend(const string &ip, const string &domain, const vector<DNSResourceRecord>&nsset, string *account, DNSBackend **ddb)
-{
- string format;
- char output[1024];
- format = d_SuperMasterInfoQuery;
- // check if we know the ip/ns couple in the database
- for(vector<DNSResourceRecord>::const_iterator i=nsset.begin();i!=nsset.end();++i) {
- try {
- snprintf(output,sizeof(output)-1,format.c_str(),sqlEscape(ip).c_str(),sqlEscape(i->content).c_str());
- d_db->doQuery(output, d_result);
- }
- catch (SSqlException &e) {
- throw AhuException("GSQLBackend unable to search for a domain: "+e.txtReason());
- }
-
- if(!d_result.empty()) {
- *account=d_result[0][0];
- *ddb=this;
- return true;
- }
- }
- return false;
-}
-
-bool GSQLBackend::createSlaveDomain(const string &ip, const string &domain, const string &account)
-{
- string format;
- char output[1024];
- format = d_InsertSlaveZoneQuery;
- snprintf(output,sizeof(output)-1,format.c_str(),sqlEscape(domain).c_str(),sqlEscape(ip).c_str(),sqlEscape(account).c_str());
- try {
- d_db->doCommand(output);
- }
- catch(SSqlException &e) {
- throw AhuException("Database error trying to insert new slave '"+domain+"': "+ e.txtReason());
- }
- return true;
-}
-
-void GSQLBackend::getAllDomains(vector<DomainInfo> *domains)
-{
- DLOG(L<<"GSQLBackend retrieving all domains."<<endl);
-
- try {
- d_db->doQuery(d_getAllDomainsQuery.c_str());
- }
- catch (SSqlException &e) {
- throw AhuException("Database error trying to retrieve all domains:" + e.txtReason());
- }
-
- SSql::row_t row;
- while (d_db->getRow(row)) {
-
- DomainInfo di;
- di.id = atol(row[0].c_str());
- di.zone = row[1];
-
- if (!row[4].empty()) {
- stringtok(di.masters, row[4], " ,\t");
- }
- di.last_check=atol(row[6].c_str());
-
- SOAData sd;
- fillSOAData(row[2], sd);
- di.serial = sd.serial;
- if (!row[5].empty()) {
- di.notified_serial = atol(row[5].c_str());
- }
-
- if (pdns_iequals(row[3], "MASTER"))
- di.kind = DomainInfo::Master;
- else if (pdns_iequals(row[3], "SLAVE"))
- di.kind = DomainInfo::Slave;
- else
- di.kind = DomainInfo::Native;
-
- di.backend = this;
-
- domains->push_back(di);
- }
-}
-
-bool GSQLBackend::get(DNSResourceRecord &r)
-{
- // L << "GSQLBackend get() was called for "<<qtype.getName() << " record: ";
- SSql::row_t row;
- if(d_db->getRow(row)) {
- r.content=row[0];
- if (row[1].empty())
- r.ttl = ::arg().asNum( "default-ttl" );
- else
- r.ttl=atol(row[1].c_str());
- r.priority=atol(row[2].c_str());
- if(!d_qname.empty())
- r.qname=d_qname;
- else
- r.qname=row[5];
- r.qtype=row[3];
- r.last_modified=0;
-
- if(d_dnssecQueries)
- r.auth = !row[6].empty() && row[6][0]=='1';
- else
- r.auth = 1;
-
- r.domain_id=atoi(row[4].c_str());
- return true;
- }
-
- return false;
-}
-
-bool GSQLBackend::replaceRRSet(uint32_t domain_id, const string& qname, const QType& qt, const vector<DNSResourceRecord>& rrset)
-{
- string deleteQuery = (boost::format(d_DeleteRRSet) % domain_id % sqlEscape(qname) % sqlEscape(qt.getName())).str();
- d_db->doCommand(deleteQuery);
- BOOST_FOREACH(const DNSResourceRecord& rr, rrset) {
- feedRecord(rr);
- }
-
- return true;
-}
-
-bool GSQLBackend::feedRecord(const DNSResourceRecord &r)
-{
- string output;
- if(d_dnssecQueries) {
- output = (boost::format(d_InsertRecordQuery) % sqlEscape(r.content) % r.ttl % r.priority % sqlEscape(r.qtype.getName()) % r.domain_id % toLower(sqlEscape(r.qname)) % (int)r.auth).str();
- } else {
- output = (boost::format(d_InsertRecordQuery) % sqlEscape(r.content) % r.ttl % r.priority % sqlEscape(r.qtype.getName()) % r.domain_id % toLower(sqlEscape(r.qname))).str();
- }
-
- try {
- d_db->doCommand(output.c_str());
- }
- catch (SSqlException &e) {
- throw AhuException("GSQLBackend unable to feed record: "+e.txtReason());
- }
- return true; // XXX FIXME this API should not return 'true' I think -ahu
-}
-
-bool GSQLBackend::startTransaction(const string &domain, int domain_id)
-{
- char output[1024];
- if(domain_id >= 0)
- snprintf(output,sizeof(output)-1,d_DeleteZoneQuery.c_str(),domain_id);
- try {
- d_db->doCommand("begin");
- if(domain_id >= 0)
- d_db->doCommand(output);
- }
- catch (SSqlException &e) {
- throw AhuException("Database failed to start transaction: "+e.txtReason());
- }
-
- return true;
-}
-
-bool GSQLBackend::commitTransaction()
-{
- try {
- d_db->doCommand("commit");
- }
- catch (SSqlException &e) {
- throw AhuException("Database failed to commit transaction: "+e.txtReason());
- }
- return true;
-}
-
-bool GSQLBackend::abortTransaction()
-{
- try {
- d_db->doCommand("rollback");
- }
- catch(SSqlException &e) {
- throw AhuException("Database failed to abort transaction: "+string(e.txtReason()));
- }
- return true;
-}
-
-bool GSQLBackend::calculateSOASerial(const string& domain, const SOAData& sd, time_t& serial)
-{
- if (d_ZoneLastChangeQuery.empty()) {
- // query not set => fall back to default impl
- return DNSBackend::calculateSOASerial(domain, sd, serial);
- }
-
- char output[1024];
-
- snprintf(output, sizeof(output)-1,
- d_ZoneLastChangeQuery.c_str(),
- sd.domain_id);
-
- try {
- d_db->doQuery(output, d_result);
- }
- catch (const SSqlException& e) {
- //DLOG(L<<"GSQLBackend unable to calculate SOA serial: " << e.txtReason()<<endl);
- return false;
- }
-
- if (not d_result.empty()) {
- serial = atol(d_result[0][0].c_str());
- return true;
- }
-
- return false;
-}
|
[-]
[+]
|
Deleted |
pdns-3.2.tar.gz/pdns/tcpreceiver.cc~
^
|
@@ -1,958 +0,0 @@
-/*
- PowerDNS Versatile Database Driven Nameserver
- Copyright (C) 2002-2012 PowerDNS.COM BV
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License version 2
- as published by the Free Software Foundation
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-#include "packetcache.hh"
-#include "utility.hh"
-#include "dnssecinfra.hh"
-#include "dnsseckeeper.hh"
-#include <cstdio>
-#include "base32.hh"
-#include <cstring>
-#include <cstdlib>
-#include <sys/types.h>
-#include <iostream>
-#include <string>
-#include "tcpreceiver.hh"
-#include "sstuff.hh"
-#include <boost/foreach.hpp>
-#include <errno.h>
-#include <signal.h>
-#include "base64.hh"
-#include "ueberbackend.hh"
-#include "dnspacket.hh"
-#include "nameserver.hh"
-#include "distributor.hh"
-#include "lock.hh"
-#include "logger.hh"
-#include "arguments.hh"
-
-#include "packethandler.hh"
-#include "statbag.hh"
-#include "resolver.hh"
-#include "communicator.hh"
-#include "namespaces.hh"
-#include "signingpipe.hh"
-extern PacketCache PC;
-extern StatBag S;
-
-/**
-\file tcpreceiver.cc
-\brief This file implements the tcpreceiver that receives and answers questions over TCP/IP
-*/
-
-pthread_mutex_t TCPNameserver::s_plock = PTHREAD_MUTEX_INITIALIZER;
-Semaphore *TCPNameserver::d_connectionroom_sem;
-PacketHandler *TCPNameserver::s_P;
-int TCPNameserver::s_timeout;
-NetmaskGroup TCPNameserver::d_ng;
-
-void TCPNameserver::go()
-{
- L<<Logger::Error<<"Creating backend connection for TCP"<<endl;
- s_P=0;
- try {
- s_P=new PacketHandler;
- }
- catch(AhuException &ae) {
- L<<Logger::Error<<Logger::NTLog<<"TCP server is unable to launch backends - will try again when questions come in"<<endl;
- L<<Logger::Error<<"TCP server is unable to launch backends - will try again when questions come in: "<<ae.reason<<endl;
- }
- pthread_create(&d_tid, 0, launcher, static_cast<void *>(this));
-}
-
-void *TCPNameserver::launcher(void *data)
-{
- static_cast<TCPNameserver *>(data)->thread();
- return 0;
-}
-
-// throws AhuException if things didn't go according to plan, returns 0 if really 0 bytes were read
-int readnWithTimeout(int fd, void* buffer, unsigned int n, bool throwOnEOF=true)
-{
- unsigned int bytes=n;
- char *ptr = (char*)buffer;
- int ret;
- while(bytes) {
- ret=read(fd, ptr, bytes);
- if(ret < 0) {
- if(errno==EAGAIN) {
- ret=waitForData(fd, 5);
- if(ret < 0)
- throw NetworkError("Waiting for data read");
- if(!ret)
- throw NetworkError("Timeout reading data");
- continue;
- }
- else
- throw NetworkError("Reading data: "+stringerror());
- }
- if(!ret) {
- if(!throwOnEOF && n == bytes)
- return 0;
- else
- throw NetworkError("Did not fulfill read from TCP due to EOF");
- }
-
- ptr += ret;
- bytes -= ret;
- }
- return n;
-}
-
-// ditto
-void writenWithTimeout(int fd, const void *buffer, unsigned int n)
-{
- unsigned int bytes=n;
- const char *ptr = (char*)buffer;
- int ret;
- while(bytes) {
- ret=write(fd, ptr, bytes);
- if(ret < 0) {
- if(errno==EAGAIN) {
- ret=waitForRWData(fd, false, 5, 0);
- if(ret < 0)
- throw NetworkError("Waiting for data write");
- if(!ret)
- throw NetworkError("Timeout writing data");
- continue;
- }
- else
- throw NetworkError("Writing data: "+stringerror());
- }
- if(!ret) {
- throw NetworkError("Did not fulfill TCP write due to EOF");
- }
-
- ptr += ret;
- bytes -= ret;
- }
-}
-
-void connectWithTimeout(int fd, struct sockaddr* remote, size_t socklen)
-{
- int err;
- Utility::socklen_t len=sizeof(err);
-
-#ifndef WIN32
- if((err=connect(fd, remote, socklen))<0 && errno!=EINPROGRESS)
-#else
- if((err=connect(clisock, remote, socklen))<0 && WSAGetLastError() != WSAEWOULDBLOCK )
-#endif // WIN32
- throw NetworkError("connect: "+stringerror());
-
- if(!err)
- goto done;
-
- err=waitForRWData(fd, false, 5, 0);
- if(err == 0)
- throw NetworkError("Timeout connecting to remote");
- if(err < 0)
- throw NetworkError("Error connecting to remote");
-
- if(getsockopt(fd, SOL_SOCKET,SO_ERROR,(char *)&err,&len)<0)
- throw NetworkError("Error connecting to remote: "+stringerror()); // Solaris
-
- if(err)
- throw NetworkError("Error connecting to remote: "+string(strerror(err)));
-
- done:
- ;
-}
-
-void TCPNameserver::sendPacket(shared_ptr<DNSPacket> p, int outsock)
-{
- uint16_t len=htons(p->getString().length());
- string buffer((const char*)&len, 2);
- buffer.append(p->getString());
- writenWithTimeout(outsock, buffer.c_str(), buffer.length());
-}
-
-
-void TCPNameserver::getQuestion(int fd, char *mesg, int pktlen, const ComboAddress &remote)
-try
-{
- readnWithTimeout(fd, mesg, pktlen);
-}
-catch(NetworkError& ae) {
- throw NetworkError("Error reading DNS data from TCP client "+remote.toString()+": "+ae.what());
-}
-
-static void proxyQuestion(shared_ptr<DNSPacket> packet)
-{
- int sock=socket(AF_INET, SOCK_STREAM, 0);
-
- Utility::setCloseOnExec(sock);
- if(sock < 0)
- throw NetworkError("Error making TCP connection socket to recursor: "+stringerror());
-
- Utility::setNonBlocking(sock);
- ServiceTuple st;
- st.port=53;
- parseService(::arg()["recursor"],st);
-
- try {
- ComboAddress recursor(st.host, st.port);
- connectWithTimeout(sock, (struct sockaddr*)&recursor, recursor.getSocklen());
- const string &buffer=packet->getString();
-
- uint16_t len=htons(buffer.length()), slen;
-
- writenWithTimeout(sock, &len, 2);
- writenWithTimeout(sock, buffer.c_str(), buffer.length());
-
- readnWithTimeout(sock, &len, 2);
- len=ntohs(len);
-
- char answer[len];
- readnWithTimeout(sock, answer, len);
-
- slen=htons(len);
- writenWithTimeout(packet->getSocket(), &slen, 2);
-
- writenWithTimeout(packet->getSocket(), answer, len);
- }
- catch(NetworkError& ae) {
- close(sock);
- throw NetworkError("While proxying a question to recursor "+st.host+": " +ae.what());
- }
- close(sock);
- return;
-}
-
-void *TCPNameserver::doConnection(void *data)
-{
- shared_ptr<DNSPacket> packet;
- // Fix gcc-4.0 error (on AMD64)
- int fd=(int)(long)data; // gotta love C (generates a harmless warning on opteron)
- pthread_detach(pthread_self());
- Utility::setNonBlocking(fd);
- try {
- char mesg[512];
-
- DLOG(L<<"TCP Connection accepted on fd "<<fd<<endl);
- bool logDNSQueries= ::arg().mustDo("log-dns-queries");
- for(;;) {
- ComboAddress remote;
- socklen_t remotelen=sizeof(remote);
- if(getpeername(fd, (struct sockaddr *)&remote, &remotelen) < 0) {
- L<<Logger::Error<<"Received question from socket which had no remote address, dropping ("<<stringerror()<<")"<<endl;
- break;
- }
-
- uint16_t pktlen;
- if(!readnWithTimeout(fd, &pktlen, 2, false))
- break;
- else
- pktlen=ntohs(pktlen);
-
- if(pktlen>511) {
- L<<Logger::Error<<"Received an overly large question from "<<remote.toString()<<", dropping"<<endl;
- break;
- }
-
- getQuestion(fd, mesg, pktlen, remote);
- S.inc("tcp-queries");
-
- packet=shared_ptr<DNSPacket>(new DNSPacket);
- packet->setRemote(&remote);
- packet->d_tcp=true;
- packet->setSocket(fd);
- if(packet->parse(mesg, pktlen)<0)
- break;
-
- if(packet->qtype.getCode()==QType::AXFR || packet->qtype.getCode()==QType::IXFR ) {
- if(doAXFR(packet->qdomain, packet, fd))
- S.inc("tcp-answers");
- continue;
- }
-
- shared_ptr<DNSPacket> reply;
- shared_ptr<DNSPacket> cached= shared_ptr<DNSPacket>(new DNSPacket);
- if(logDNSQueries) {
- string remote;
- if(packet->hasEDNSSubnet())
- remote = packet->getRemote() + "<-" + packet->getRealRemote().toString();
- else
- remote = packet->getRemote();
- L << Logger::Notice<<"TCP Remote "<< remote <<" wants '" << packet->qdomain<<"|"<<packet->qtype.getName() <<
- "', do = " <<packet->d_dnssecOk <<", bufsize = "<< packet->getMaxReplyLen()<<": ";
- }
-
-
- if(!packet->d.rd && packet->couldBeCached() && PC.get(packet.get(), cached.get())) { // short circuit - does the PacketCache recognize this question?
- if(logDNSQueries)
- L<<"packetcache HIT"<<endl;
- cached->setRemote(&packet->d_remote);
- cached->d.id=packet->d.id;
- cached->d.rd=packet->d.rd; // copy in recursion desired bit
- cached->commitD(); // commit d to the packet inlined
-
- sendPacket(cached, fd); // presigned, don't do it again
- S.inc("tcp-answers");
- continue;
- }
- if(logDNSQueries)
- L<<"packetcache MISS"<<endl;
- {
- Lock l(&s_plock);
- if(!s_P) {
- L<<Logger::Error<<"TCP server is without backend connections, launching"<<endl;
- s_P=new PacketHandler;
- }
- bool shouldRecurse;
-
- reply=shared_ptr<DNSPacket>(s_P->questionOrRecurse(packet.get(), &shouldRecurse)); // we really need to ask the backend :-)
-
- if(shouldRecurse) {
- proxyQuestion(packet);
- continue;
- }
- }
-
- if(!reply) // unable to write an answer?
- break;
-
- S.inc("tcp-answers");
- sendPacket(reply, fd);
- }
- }
- catch(DBException &e) {
- Lock l(&s_plock);
- delete s_P;
- s_P = 0;
-
- L<<Logger::Error<<"TCP Connection Thread unable to answer a question because of a backend error, cycling"<<endl;
- }
- catch(AhuException &ae) {
- Lock l(&s_plock);
- delete s_P;
- s_P = 0; // on next call, backend will be recycled
- L<<Logger::Error<<"TCP nameserver had error, cycling backend: "<<ae.reason<<endl;
- }
- catch(NetworkError &e) {
- L<<Logger::Info<<"TCP Connection Thread died because of network error: "<<e.what()<<endl;
- }
-
- catch(std::exception &e) {
- L<<Logger::Error<<"TCP Connection Thread died because of STL error: "<<e.what()<<endl;
- }
- catch( ... )
- {
- L << Logger::Error << "TCP Connection Thread caught unknown exception." << endl;
- }
- d_connectionroom_sem->post();
- Utility::closesocket(fd);
-
- return 0;
-}
-
-
-// call this method with s_plock held!
-bool TCPNameserver::canDoAXFR(shared_ptr<DNSPacket> q)
-{
- if(::arg().mustDo("disable-axfr"))
- return false;
-
- if(q->d_havetsig) { // if you have one, it must be good
- TSIGRecordContent trc;
- string keyname, secret;
- if(!checkForCorrectTSIG(q.get(), s_P->getBackend(), &keyname, &secret, &trc))
- return false;
-
- DNSSECKeeper dk;
-
- if(!dk.TSIGGrantsAccess(q->qdomain, keyname, trc.d_algoName)) {
- L<<Logger::Error<<"AXFR '"<<q->qdomain<<"' denied: key with name '"<<keyname<<"' and algorithm '"<<trc.d_algoName<<"' does not grant access to zone"<<endl;
- return false;
- }
- else {
- L<<Logger::Warning<<"AXFR of domain '"<<q->qdomain<<"' allowed: TSIG signed request with authorized key '"<<keyname<<"' and algorithm '"<<trc.d_algoName<<"'"<<endl;
- return true;
- }
- }
-
- // cerr<<"checking allow-axfr-ips"<<endl;
- if(!(::arg()["allow-axfr-ips"].empty()) && d_ng.match( (ComboAddress *) &q->d_remote )) {
- L<<Logger::Warning<<"AXFR of domain '"<<q->qdomain<<"' allowed: client IP "<<q->getRemote()<<" is in allow-axfr-ips"<<endl;
- return true;
- }
-
- FindNS fns;
-
- // cerr<<"doing per-zone-axfr-acls"<<endl;
- SOAData sd;
- sd.db=(DNSBackend *)-1;
- if(s_P->getBackend()->getSOA(q->qdomain,sd)) {
- // cerr<<"got backend and SOA"<<endl;
- DNSBackend *B=sd.db;
- vector<string> acl;
- B->getDomainMetadata(q->qdomain, "ALLOW-AXFR-FROM", acl);
- for (vector<string>::const_iterator i = acl.begin(); i != acl.end(); ++i) {
- // cerr<<"matching against "<<*i<<endl;
- if(pdns_iequals(*i, "AUTO-NS")) {
- // cerr<<"AUTO-NS magic please!"<<endl;
-
- DNSResourceRecord rr;
- set<string> nsset;
-
- B->lookup(QType(QType::NS),q->qdomain);
- while(B->get(rr))
- nsset.insert(rr.content);
- for(set<string>::const_iterator j=nsset.begin();j!=nsset.end();++j) {
- vector<string> nsips=fns.lookup(*j, B);
- for(vector<string>::const_iterator k=nsips.begin();k!=nsips.end();++k) {
- // cerr<<"got "<<*k<<" from AUTO-NS"<<endl;
- if(*k == q->getRemote())
- {
- // cerr<<"got AUTO-NS hit"<<endl;
- L<<Logger::Warning<<"AXFR of domain '"<<q->qdomain<<"' allowed: client IP "<<q->getRemote()<<" is in NSset"<<endl;
- return true;
- }
- }
- }
- }
- else
- {
- Netmask nm = Netmask(*i);
- if(nm.match( (ComboAddress *) &q->d_remote ))
- {
- L<<Logger::Warning<<"AXFR of domain '"<<q->qdomain<<"' allowed: client IP "<<q->getRemote()<<" is in per-domain ACL"<<endl;
- // cerr<<"hit!"<<endl;
- return true;
- }
- }
- }
- }
-
- extern CommunicatorClass Communicator;
-
- if(Communicator.justNotified(q->qdomain, q->getRemote())) { // we just notified this ip
- L<<Logger::Warning<<"Approved AXFR of '"<<q->qdomain<<"' from recently notified slave "<<q->getRemote()<<endl;
- return true;
- }
-
- L<<Logger::Error<<"AXFR of domain '"<<q->qdomain<<"' denied: client IP "<<q->getRemote()<<" has no permission"<<endl;
- return false;
-}
-
-namespace {
- struct NSECXEntry
- {
- set<uint16_t> d_set;
- unsigned int d_ttl;
- };
-
- DNSResourceRecord makeDNSRRFromSOAData(const SOAData& sd)
- {
- DNSResourceRecord soa;
- soa.qname= sd.qname;
- soa.qtype=QType::SOA;
- soa.content=serializeSOAData(sd);
- soa.ttl=sd.ttl;
- soa.domain_id=sd.domain_id;
- soa.auth = true;
- soa.d_place=DNSResourceRecord::ANSWER;
- return soa;
- }
-
- shared_ptr<DNSPacket> getFreshAXFRPacket(shared_ptr<DNSPacket> q)
- {
- shared_ptr<DNSPacket> ret = shared_ptr<DNSPacket>(q->replyPacket());
- ret->setCompress(false);
- ret->d_dnssecOk=false; // RFC 5936, 2.2.5
- ret->d_tcp = true;
- return ret;
- }
-}
-
-
-/** do the actual zone transfer. Return 0 in case of error, 1 in case of success */
-int TCPNameserver::doAXFR(const string &target, shared_ptr<DNSPacket> q, int outsock)
-{
- bool noAXFRBecauseOfNSEC3Narrow=false;
- NSEC3PARAMRecordContent ns3pr;
- bool narrow;
- bool NSEC3Zone=false;
-
- DNSSECKeeper dk;
- dk.clearCaches(target);
- bool securedZone = dk.isSecuredZone(target);
- if(dk.getNSEC3PARAM(target, &ns3pr, &narrow)) {
- NSEC3Zone=true;
- if(narrow) {
- L<<Logger::Error<<"Not doing AXFR of an NSEC3 narrow zone.."<<endl;
- noAXFRBecauseOfNSEC3Narrow=true;
- }
- }
-
- shared_ptr<DNSPacket> outpacket= getFreshAXFRPacket(q);
- if(q->d_dnssecOk)
- outpacket->d_dnssecOk=true; // RFC 5936, 2.2.5 'SHOULD'
-
- if(noAXFRBecauseOfNSEC3Narrow) {
- L<<Logger::Error<<"AXFR of domain '"<<target<<"' denied to "<<q->getRemote()<<endl;
- outpacket->setRcode(RCode::Refused);
- // FIXME: should actually figure out if we are auth over a zone, and send out 9 if we aren't
- sendPacket(outpacket,outsock);
- return 0;
- }
-
- L<<Logger::Error<<"AXFR of domain '"<<target<<"' initiated by "<<q->getRemote()<<endl;
-
- SOAData sd;
- sd.db=(DNSBackend *)-1; // force uncached answer
- {
- Lock l(&s_plock);
- DLOG(L<<"Looking for SOA"<<endl); // find domain_id via SOA and list complete domain. No SOA, no AXFR
- if(!s_P) {
- L<<Logger::Error<<"TCP server is without backend connections in doAXFR, launching"<<endl;
- s_P=new PacketHandler;
- }
-
- if(!s_P->getBackend()->getSOA(target, sd) || !canDoAXFR(q)) {
- L<<Logger::Error<<"AXFR of domain '"<<target<<"' failed: not authoritative"<<endl;
- outpacket->setRcode(9); // 'NOTAUTH'
- sendPacket(outpacket,outsock);
- return 0;
- }
- }
-
- UeberBackend db;
- sd.db=(DNSBackend *)-1; // force uncached answer
- if(!db.getSOA(target, sd)) {
- L<<Logger::Error<<"AXFR of domain '"<<target<<"' failed: not authoritative in second instance"<<endl;
- outpacket->setRcode(9); // 'NOTAUTH'
- sendPacket(outpacket,outsock);
- return 0;
- }
-
- if(!sd.db || sd.db==(DNSBackend *)-1) {
- L<<Logger::Error<<"Error determining backend for domain '"<<target<<"' trying to serve an AXFR"<<endl;
- outpacket->setRcode(RCode::ServFail);
- sendPacket(outpacket,outsock);
- return 0;
- }
-
- TSIGRecordContent trc;
- string tsigkeyname, tsigsecret;
-
- q->getTSIGDetails(&trc, &tsigkeyname, 0);
-
- if(!tsigkeyname.empty()) {
- string tsig64, algorithm;
- Lock l(&s_plock);
- s_P->getBackend()->getTSIGKey(tsigkeyname, &algorithm, &tsig64);
- B64Decode(tsig64, tsigsecret);
- }
-
-
- UeberBackend signatureDB;
-
- // SOA *must* go out first, our signing pipe might reorder
- DLOG(L<<"Sending out SOA"<<endl);
- DNSResourceRecord soa = makeDNSRRFromSOAData(sd);
- outpacket->addRecord(soa);
- editSOA(dk, sd.qname, outpacket.get());
- if(securedZone) {
- set<string, CIStringCompare> authSet;
- authSet.insert(target);
- addRRSigs(dk, signatureDB, authSet, outpacket->getRRS());
- }
-
- if(!tsigkeyname.empty())
- outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac); // first answer is 'normal'
-
- sendPacket(outpacket, outsock);
-
- trc.d_mac = outpacket->d_trc.d_mac;
- outpacket = getFreshAXFRPacket(q);
-
- ChunkedSigningPipe csp(target, securedZone, "", ::arg().asNum("signing-threads"));
-
- typedef map<string, NSECXEntry> nsecxrepo_t;
- nsecxrepo_t nsecxrepo;
-
- // this is where the DNSKEYs go in
-
- DNSSECKeeper::keyset_t keys = dk.getKeys(target);
-
- DNSResourceRecord rr;
-
- rr.qname = target;
- rr.ttl = sd.default_ttl;
- rr.auth = 1; // please sign!
-
- BOOST_FOREACH(const DNSSECKeeper::keyset_t::value_type& value, keys) {
- rr.qtype = QType(QType::DNSKEY);
- rr.content = value.first.getDNSKEY().getZoneRepresentation();
- string keyname = NSEC3Zone ? hashQNameWithSalt(ns3pr.d_iterations, ns3pr.d_salt, rr.qname) : labelReverse(rr.qname);
- NSECXEntry& ne = nsecxrepo[keyname];
-
- ne.d_set.insert(rr.qtype.getCode());
- ne.d_ttl = sd.default_ttl;
- csp.submit(rr);
- }
-
- if(::arg().mustDo("experimental-direct-dnskey")) {
- sd.db->lookup(QType(QType::DNSKEY), target, NULL, sd.domain_id);
- while(sd.db->get(rr)) {
- rr.ttl = sd.default_ttl;
- csp.submit(rr);
- }
- }
-
- if(NSEC3Zone) { // now stuff in the NSEC3PARAM
- rr.qtype = QType(QType::NSEC3PARAM);
- ns3pr.d_flags = 0;
- rr.content = ns3pr.getZoneRepresentation();
- ns3pr.d_flags = 1;
- string keyname = hashQNameWithSalt(ns3pr.d_iterations, ns3pr.d_salt, rr.qname);
- NSECXEntry& ne = nsecxrepo[keyname];
-
- ne.d_set.insert(rr.qtype.getCode());
- csp.submit(rr);
- }
-
- // now start list zone
- if(!(sd.db->list(target, sd.domain_id))) {
- L<<Logger::Error<<"Backend signals error condition"<<endl;
- outpacket->setRcode(2); // 'SERVFAIL'
- sendPacket(outpacket,outsock);
- return 0;
- }
-
- /* now write all other records */
-
- string keyname;
- DTime dt;
- dt.set();
- int records=0;
- while(sd.db->get(rr)) {
- if (rr.qtype.getCode() == QType::RRSIG)
- continue;
-
- // only skip the DNSKEY if direct-dnskey is enabled, to avoid changing behaviour
- // when it is not enabled.
- if(::arg().mustDo("experimental-direct-dnskey") && rr.qtype.getCode() == QType::DNSKEY)
- continue;
-
- records++;
- if(securedZone && (rr.auth || (!NSEC3Zone && rr.qtype.getCode() == QType::NS) || rr.qtype.getCode() == QType::DS)) { // this is probably NSEC specific, NSEC3 is different
- if (NSEC3Zone || rr.qtype.getCode()) {
- keyname = NSEC3Zone ? hashQNameWithSalt(ns3pr.d_iterations, ns3pr.d_salt, rr.qname) : labelReverse(rr.qname);
- NSECXEntry& ne = nsecxrepo[keyname];
- ne.d_ttl = sd.default_ttl;
- if (rr.qtype.getCode()) {
- ne.d_set.insert(rr.qtype.getCode());
- }
- }
- }
-
- if (!rr.qtype.getCode())
- continue; // skip empty non-terminals
-
- if(rr.qtype.getCode() == QType::SOA)
- continue; // skip SOA - would indicate end of AXFR
-
- if(csp.submit(rr)) {
- for(;;) {
- outpacket->getRRS() = csp.getChunk();
- if(!outpacket->getRRS().empty()) {
- if(!tsigkeyname.empty())
- outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac, true);
- sendPacket(outpacket, outsock);
- trc.d_mac=outpacket->d_trc.d_mac;
- outpacket=getFreshAXFRPacket(q);
- }
- else
- break;
- }
- }
- }
- unsigned int udiff=dt.udiffNoReset();
- /*
- cerr<<"Starting NSEC: "<<csp.d_signed/(udiff/1000000.0)<<" sigs/s, "<<csp.d_signed<<" / "<<udiff/1000000.0<<endl;
- cerr<<"Outstanding: "<<csp.d_outstanding<<", "<<csp.d_queued - csp.d_signed << endl;
- cerr<<"Ready for consumption: "<<csp.getReady()<<endl;
- */
- if(securedZone) {
- if(NSEC3Zone) {
- for(nsecxrepo_t::const_iterator iter = nsecxrepo.begin(); iter != nsecxrepo.end(); ++iter) {
- NSEC3RecordContent n3rc;
- n3rc.d_set = iter->second.d_set;
- if (n3rc.d_set.size())
- n3rc.d_set.insert(QType::RRSIG);
- n3rc.d_salt=ns3pr.d_salt;
- n3rc.d_flags = ns3pr.d_flags;
- n3rc.d_iterations = ns3pr.d_iterations;
- n3rc.d_algorithm = 1; // SHA1, fixed in PowerDNS for now
- if(boost::next(iter) != nsecxrepo.end()) {
- n3rc.d_nexthash = boost::next(iter)->first;
- }
- else
- n3rc.d_nexthash=nsecxrepo.begin()->first;
-
- rr.qname = dotConcat(toLower(toBase32Hex(iter->first)), sd.qname);
-
- rr.ttl = sd.default_ttl;
- rr.content = n3rc.getZoneRepresentation();
- rr.qtype = QType::NSEC3;
- rr.d_place = DNSResourceRecord::ANSWER;
- rr.auth=true;
- if(csp.submit(rr)) {
- for(;;) {
- outpacket->getRRS() = csp.getChunk();
- if(!outpacket->getRRS().empty()) {
- if(!tsigkeyname.empty())
- outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac, true);
- sendPacket(outpacket, outsock);
- trc.d_mac=outpacket->d_trc.d_mac;
- outpacket=getFreshAXFRPacket(q);
- }
- else
- break;
- }
- }
- }
- }
- else for(nsecxrepo_t::const_iterator iter = nsecxrepo.begin(); iter != nsecxrepo.end(); ++iter) {
- NSECRecordContent nrc;
- nrc.d_set = iter->second.d_set;
- nrc.d_set.insert(QType::RRSIG);
- nrc.d_set.insert(QType::NSEC);
- if(boost::next(iter) != nsecxrepo.end()) {
- nrc.d_next = labelReverse(boost::next(iter)->first);
- }
- else
- nrc.d_next=labelReverse(nsecxrepo.begin()->first);
-
- rr.qname = labelReverse(iter->first);
-
- rr.ttl = sd.default_ttl;
- rr.content = nrc.getZoneRepresentation();
- rr.qtype = QType::NSEC;
- rr.d_place = DNSResourceRecord::ANSWER;
- rr.auth=true;
- if(csp.submit(rr)) {
- for(;;) {
- outpacket->getRRS() = csp.getChunk();
- if(!outpacket->getRRS().empty()) {
- if(!tsigkeyname.empty())
- outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac, true);
- sendPacket(outpacket, outsock);
- trc.d_mac=outpacket->d_trc.d_mac;
- outpacket=getFreshAXFRPacket(q);
- }
- else
- break;
- }
- }
- }
- }
- udiff=dt.udiffNoReset();
- /*
- cerr<<"Flushing pipe: "<<csp.d_signed/(udiff/1000000.0)<<" sigs/s, "<<csp.d_signed<<" / "<<udiff/1000000.0<<endl;
- cerr<<"Outstanding: "<<csp.d_outstanding<<", "<<csp.d_queued - csp.d_signed << endl;
- cerr<<"Ready for consumption: "<<csp.getReady()<<endl;
- * */
- for(;;) {
- outpacket->getRRS() = csp.getChunk(true); // flush the pipe
- if(!outpacket->getRRS().empty()) {
- if(!tsigkeyname.empty())
- outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac, true); // first answer is 'normal'
- sendPacket(outpacket, outsock);
- trc.d_mac=outpacket->d_trc.d_mac;
- outpacket=getFreshAXFRPacket(q);
- }
- else
- break;
- }
-
- udiff=dt.udiffNoReset();
- if(securedZone)
- L<<Logger::Info<<"Done signing: "<<csp.d_signed/(udiff/1000000.0)<<" sigs/s, "<<endl;
-
- DLOG(L<<"Done writing out records"<<endl);
- /* and terminate with yet again the SOA record */
- outpacket=getFreshAXFRPacket(q);
- outpacket->addRecord(soa);
- editSOA(dk, sd.qname, outpacket.get());
- if(!tsigkeyname.empty())
- outpacket->setTSIGDetails(trc, tsigkeyname, tsigsecret, trc.d_mac, true);
-
- sendPacket(outpacket, outsock);
-
- DLOG(L<<"last packet - close"<<endl);
- L<<Logger::Error<<"AXFR of domain '"<<target<<"' to "<<q->getRemote()<<" finished"<<endl;
-
- return 1;
-}
-
-TCPNameserver::~TCPNameserver()
-{
- delete d_connectionroom_sem;
-}
-
-TCPNameserver::TCPNameserver()
-{
-// sem_init(&d_connectionroom_sem,0,::arg().asNum("max-tcp-connections"));
- d_connectionroom_sem = new Semaphore( ::arg().asNum( "max-tcp-connections" ));
-
- s_timeout=10;
- vector<string>locals;
- stringtok(locals,::arg()["local-address"]," ,");
-
- vector<string>locals6;
- stringtok(locals6,::arg()["local-ipv6"]," ,");
-
- if(locals.empty() && locals6.empty())
- throw AhuException("No local address specified");
-
- vector<string> parts;
- stringtok( parts, ::arg()["allow-axfr-ips"], ", \t" ); // is this IP on the guestlist?
- for( vector<string>::const_iterator i = parts.begin(); i != parts.end(); ++i ) {
- d_ng.addMask( *i );
- }
-
-#ifndef WIN32
- signal(SIGPIPE,SIG_IGN);
-#endif // WIN32
-
- for(vector<string>::const_iterator laddr=locals.begin();laddr!=locals.end();++laddr) {
- int s=socket(AF_INET,SOCK_STREAM,0);
- Utility::setCloseOnExec(s);
-
- if(s<0)
- throw AhuException("Unable to acquire TCP socket: "+stringerror());
-
- ComboAddress local(*laddr, ::arg().asNum("local-port"));
-
- int tmp=1;
- if(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char*)&tmp,sizeof tmp)<0) {
- L<<Logger::Error<<"Setsockopt failed"<<endl;
- exit(1);
- }
-
- if(::bind(s, (sockaddr*)&local, local.getSocklen())<0) {
- L<<Logger::Error<<"binding to TCP socket: "<<strerror(errno)<<endl;
- throw AhuException("Unable to bind to TCP socket");
- }
-
- listen(s,128);
- L<<Logger::Error<<"TCP server bound to "<<local.toStringWithPort()<<endl;
- d_sockets.push_back(s);
- struct pollfd pfd;
- memset(&pfd, 0, sizeof(pfd));
- pfd.fd = s;
- pfd.events = POLLIN;
-
- d_prfds.push_back(pfd);
- }
-
-#if !WIN32 && HAVE_IPV6
- for(vector<string>::const_iterator laddr=locals6.begin();laddr!=locals6.end();++laddr) {
- int s=socket(AF_INET6,SOCK_STREAM,0);
- Utility::setCloseOnExec(s);
-
- if(s<0)
- throw AhuException("Unable to acquire TCPv6 socket: "+stringerror());
-
- ComboAddress local(*laddr, ::arg().asNum("local-port"));
-
- int tmp=1;
- if(setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char*)&tmp,sizeof tmp)<0) {
- L<<Logger::Error<<"Setsockopt failed"<<endl;
- exit(1);
- }
- if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &tmp, sizeof(tmp)) < 0) {
- L<<Logger::Error<<"Failed to set IPv6 socket to IPv6 only, continuing anyhow: "<<strerror(errno)<<endl;
- }
- if(bind(s, (const sockaddr*)&local, local.getSocklen())<0) {
- L<<Logger::Error<<"binding to TCP socket: "<<strerror(errno)<<endl;
- throw AhuException("Unable to bind to TCPv6 socket");
- }
-
- listen(s,128);
- L<<Logger::Error<<"TCPv6 server bound to "<<local.toStringWithPort()<<endl; // this gets %eth0 right
- d_sockets.push_back(s);
-
- struct pollfd pfd;
- memset(&pfd, 0, sizeof(pfd));
- pfd.fd = s;
- pfd.events = POLLIN;
-
- d_prfds.push_back(pfd);
- }
-#endif // WIN32
-}
-
-
-//! Start of TCP operations thread, we launch a new thread for each incoming TCP question
-void TCPNameserver::thread()
-{
- try {
- for(;;) {
- int fd;
- struct sockaddr_in remote;
- Utility::socklen_t addrlen=sizeof(remote);
-
- int ret=poll(&d_prfds[0], d_prfds.size(), -1); // blocks, forever if need be
- if(ret <= 0)
- continue;
-
- int sock=-1;
- BOOST_FOREACH(const struct pollfd& pfd, d_prfds) {
- if(pfd.revents == POLLIN) {
- sock = pfd.fd;
- addrlen=sizeof(remote);
-
- if((fd=accept(sock, (sockaddr*)&remote, &addrlen))<0) {
- L<<Logger::Error<<"TCP question accept error: "<<strerror(errno)<<endl;
-
- if(errno==EMFILE) {
- L<<Logger::Error<<Logger::NTLog<<"TCP handler out of filedescriptors, exiting, won't recover from this"<<endl;
- exit(1);
- }
- }
- else {
- pthread_t tid;
- d_connectionroom_sem->wait(); // blocks if no connections are available
-
- int room;
- d_connectionroom_sem->getValue( &room);
- if(room<1)
- L<<Logger::Warning<<Logger::NTLog<<"Limit of simultaneous TCP connections reached - raise max-tcp-connections"<<endl;
-
- if(pthread_create(&tid, 0, &doConnection, reinterpret_cast<void*>(fd))) {
- L<<Logger::Error<<"Error creating thread: "<<stringerror()<<endl;
- d_connectionroom_sem->post();
- }
- }
- }
- }
- }
- }
- catch(AhuException &AE) {
- L<<Logger::Error<<"TCP Nameserver thread dying because of fatal error: "<<AE.reason<<endl;
- }
- catch(...) {
- L<<Logger::Error<<"TCPNameserver dying because of an unexpected fatal error"<<endl;
- }
- exit(1); // take rest of server with us
-}
-
-
|