[Pdns-dev] [PATCH 3/3] Strict mode for generic SQL backends

Peter Collingbourne peter at pcc.me.uk
Mon Nov 17 22:42:58 CET 2008


This patch implements a strict mode for the gsql backend in a similar
style to the strict mode of the ldap backend, i.e. PTR records are
autogenerated from existing A and AAAA records.  Includes documentation
for the new feature.
---
 modules/gmysqlbackend/gmysqlbackend.cc     |    3 ++
 modules/godbcbackend/godbcbackend.cc       |    3 ++
 modules/goraclebackend/goraclebackend.cc   |    3 ++
 modules/gpgsqlbackend/gpgsqlbackend.cc     |    3 ++
 modules/gsqlite3backend/gsqlite3backend.cc |    3 ++
 modules/gsqlitebackend/gsqlitebackend.cc   |    3 ++
 pdns/backends/gsql/gsqlbackend.cc          |   37 ++++++++++++++++++++++++++++
 pdns/backends/gsql/gsqlbackend.hh          |    4 +++
 pdns/docs/pdns.sgml                        |   33 ++++++++++++++++++++++---
 9 files changed, 88 insertions(+), 4 deletions(-)

diff --git a/modules/gmysqlbackend/gmysqlbackend.cc b/modules/gmysqlbackend/gmysqlbackend.cc
index 17c758e..69d7466 100644
--- a/modules/gmysqlbackend/gmysqlbackend.cc
+++ b/modules/gmysqlbackend/gmysqlbackend.cc
@@ -50,6 +50,7 @@ public:
     declare(suffix,"port","Database backend port to connect to","0");
     declare(suffix,"socket","Pdns backend socket to connect to","");
     declare(suffix,"password","Pdns backend password to connect with","");
+    declare(suffix,"method","Pdns backend search method (simple or strict)", "simple");
 
     declare(suffix,"basic-query","Basic query","select content,ttl,prio,type,domain_id,name from records where type='%s' and name='%s'");
     declare(suffix,"id-query","Basic with ID query","select content,ttl,prio,type,domain_id,name from records where type='%s' and name='%s' and domain_id=%d");
@@ -61,6 +62,8 @@ public:
     declare(suffix,"wildcard-any-query","Wildcard ANY query","select content,ttl,prio,type,domain_id,name from records where name like '%s'");
     declare(suffix,"wildcard-any-id-query","Wildcard ANY with ID query","select content,ttl,prio,type,domain_id,name from records where name like '%s' and domain_id='%d'");
 
+    declare(suffix, "reverse-query","Reverse lookup query", "select name,ttl,prio,'PTR',0,content from records where type='%s' and content='%s'");
+
     declare(suffix,"list-query","AXFR query", "select content,ttl,prio,type,domain_id,name from records where domain_id='%d'");
     declare(suffix,"master-zone-query","Data", "select master from domains where name='%s' and type='SLAVE'");
 
diff --git a/modules/godbcbackend/godbcbackend.cc b/modules/godbcbackend/godbcbackend.cc
index 7eb30b1..b96ed10 100644
--- a/modules/godbcbackend/godbcbackend.cc
+++ b/modules/godbcbackend/godbcbackend.cc
@@ -49,6 +49,7 @@ public:
     declare( suffix, "datasource", "Datasource (DSN) to use","PowerDNS");
     declare( suffix, "username", "User to connect as","powerdns");
     declare( suffix, "password", "Password to connect with","");
+    declare( suffix, "method", "Pdns backend search method (simple or strict)","simple");
 
     declare( suffix, "basic-query", "Basic query","select content,ttl,prio,type,domain_id,name from records where type='%s' and name='%s'");
     declare( suffix, "id-query", "Basic with ID query","select content,ttl,prio,type,domain_id,name from records where type='%s' and name='%s' and domain_id=%d");
@@ -60,6 +61,8 @@ public:
     declare( suffix, "wildcard-any-query", "Wildcard ANY query","select content,ttl,prio,type,domain_id,name from records where name like '%s'");
     declare( suffix, "wildcard-any-id-query", "Wildcard ANY with ID query","select content,ttl,prio,type,domain_id,name from records where name like '%s' and domain_id='%d'");
 
+    declare( suffix, "reverse-query", "Reverse lookup query", "select name,ttl,prio,'PTR',0,content from records where type='%s' and content='%s'");
+
     declare( suffix, "list-query", "AXFR query", "select content,ttl,prio,type,domain_id,name from records where domain_id='%d'");
     declare( suffix, "master-zone-query", "Data", "select master from domains where name='%s' and type='SLAVE'");
 
diff --git a/modules/goraclebackend/goraclebackend.cc b/modules/goraclebackend/goraclebackend.cc
index b0a20ed..2aa0e6c 100644
--- a/modules/goraclebackend/goraclebackend.cc
+++ b/modules/goraclebackend/goraclebackend.cc
@@ -44,6 +44,7 @@ public:
     declare(suffix,"tnsname","Generic Oracle backend TNSNAME to connect to","powerdns");
     declare(suffix,"user","Database backend user to connect as","powerdns");
     declare(suffix,"password","Pdns backend password to connect with","");
+    declare(suffix,"method","Pdns backend search method (simple or strict)", "simple");
 
     declare(suffix,"basic-query","Basic query","select content,ttl,prio,type,domain_id,name from records where type='%s' and name='%s'");
     declare(suffix,"id-query","Basic with ID query","select content,ttl,prio,type,domain_id,name from records where type='%s' and name='%s' and domain_id=%d");
@@ -55,6 +56,8 @@ public:
     declare(suffix,"wildcard-any-query","Wildcard ANY query","select content,ttl,prio,type,domain_id,name from records where name like '%s'");
     declare(suffix,"wildcard-any-id-query","Wildcard ANY with ID query","select content,ttl,prio,type,domain_id,name from records where name like '%s' and domain_id='%d'");
 
+    declare(suffix, "reverse-query","Reverse lookup query", "select name,ttl,prio,'PTR',0,content from records where type='%s' and content='%s'");
+
     declare(suffix,"list-query","AXFR query", "select content,ttl,prio,type,domain_id,name from records where domain_id='%d'");
     declare(suffix,"master-zone-query","Data", "select master from domains where name='%s' and type='SLAVE'");
 
diff --git a/modules/gpgsqlbackend/gpgsqlbackend.cc b/modules/gpgsqlbackend/gpgsqlbackend.cc
index 1aaebca..0e45da6 100644
--- a/modules/gpgsqlbackend/gpgsqlbackend.cc
+++ b/modules/gpgsqlbackend/gpgsqlbackend.cc
@@ -50,6 +50,7 @@ public:
     declare(suffix,"port","Database backend port to connect to","");
     declare(suffix,"socket","Pdns backend socket to connect to","");
     declare(suffix,"password","Pdns backend password to connect with","");
+    declare(suffix,"method","Pdns backend search method (simple or strict)", "simple");
 
     declare(suffix,"basic-query","Basic query","select content,ttl,prio,type,domain_id,name from records where type='%s' and name='%s'");
     declare(suffix,"id-query","Basic with ID query","select content,ttl,prio,type,domain_id,name from records where type='%s' and name='%s' and domain_id=%d");
@@ -61,6 +62,8 @@ public:
     declare(suffix,"wildcard-any-query","Wildcard ANY query","select content,ttl,prio,type,domain_id,name from records where name like '%s'");
     declare(suffix,"wildcard-any-id-query","Wildcard ANY with ID query","select content,ttl,prio,type,domain_id,name from records where name like '%s' and domain_id='%d'");
 
+    declare(suffix, "reverse-query","Reverse lookup query", "select name,ttl,prio,'PTR',0,content from records where type='%s' and content='%s'");
+
     declare(suffix,"list-query","AXFR query", "select content,ttl,prio,type,domain_id,name from records where domain_id='%d'");
     declare(suffix,"master-zone-query","Data", "select master from domains where name='%s' and type='SLAVE'");
 
diff --git a/modules/gsqlite3backend/gsqlite3backend.cc b/modules/gsqlite3backend/gsqlite3backend.cc
index df69131..5254c3e 100644
--- a/modules/gsqlite3backend/gsqlite3backend.cc
+++ b/modules/gsqlite3backend/gsqlite3backend.cc
@@ -51,6 +51,7 @@ public:
   void declareArguments( const std::string & suffix = "" )
   {
     declare( suffix, "database", "Filename of the SQLite3 database", "powerdns.sqlite" );
+    declare( suffix, "method", "Pdns backend search method (simple or strict)", "simple");
     
     declare( suffix, "basic-query", "Basic query","select content,ttl,prio,type,domain_id,name from records where type='%s' and name='%s'");
     declare( suffix, "id-query", "Basic with ID query","select content,ttl,prio,type,domain_id,name from records where type='%s' and name='%s' and domain_id=%d");
@@ -62,6 +63,8 @@ public:
     declare( suffix, "wildcard-any-query", "Wildcard ANY query","select content,ttl,prio,type,domain_id,name from records where name like '%s'");
     declare( suffix, "wildcard-any-id-query", "Wildcard ANY with ID query","select content,ttl,prio,type,domain_id,name from records where name like '%s' and domain_id=%d");
 
+    declare( suffix, "reverse-query", "Reverse lookup query", "select name,ttl,prio,'PTR',0,content from records where type='%s' and content='%s'");
+
     declare( suffix, "list-query", "AXFR query", "select content,ttl,prio,type,domain_id,name from records where domain_id=%d");
     declare( suffix, "master-zone-query", "Data", "select master from domains where name='%s' and type='SLAVE'");
 
diff --git a/modules/gsqlitebackend/gsqlitebackend.cc b/modules/gsqlitebackend/gsqlitebackend.cc
index 709316f..1e7afba 100644
--- a/modules/gsqlitebackend/gsqlitebackend.cc
+++ b/modules/gsqlitebackend/gsqlitebackend.cc
@@ -51,6 +51,7 @@ public:
   void declareArguments( const std::string & suffix = "" )
   {
     declare( suffix, "database", "Filename of the SQLite database", "powerdns.sqlite" );
+    declare( suffix, "method", "Pdns backend search method (simple or strict)", "simple");
     
     declare( suffix, "basic-query", "Basic query","select content,ttl,prio,type,domain_id,name from records where type='%s' and name='%s'");
     declare( suffix, "id-query", "Basic with ID query","select content,ttl,prio,type,domain_id,name from records where type='%s' and name='%s' and domain_id=%d");
@@ -62,6 +63,8 @@ public:
     declare( suffix, "wildcard-any-query", "Wildcard ANY query","select content,ttl,prio,type,domain_id,name from records where name like '%s'");
     declare( suffix, "wildcard-any-id-query", "Wildcard ANY with ID query","select content,ttl,prio,type,domain_id,name from records where name like '%s' and domain_id=%d");
 
+    declare( suffix, "reverse-query", "Reverse lookup query", "select name,ttl,prio,'PTR',0,content from records where type='%s' and content='%s'");
+
     declare( suffix, "list-query", "AXFR query", "select content,ttl,prio,type,domain_id,name from records where domain_id=%d");
     declare( suffix, "master-zone-query", "Data", "select master from domains where name='%s' and type='SLAVE'");
 
diff --git a/pdns/backends/gsql/gsqlbackend.cc b/pdns/backends/gsql/gsqlbackend.cc
index b0f0c5d..07a6af2 100644
--- a/pdns/backends/gsql/gsqlbackend.cc
+++ b/pdns/backends/gsql/gsqlbackend.cc
@@ -216,6 +216,7 @@ GSQLBackend::GSQLBackend(const string &mode, const string &suffix)
   setArgPrefix(mode+suffix);
   d_db=0;
   d_logprefix="["+mode+"Backend"+suffix+"] ";
+  d_methodStrict=(getArg("method")=="strict");
 		  
   d_noWildCardNoIDQuery=getArg("basic-query");
   d_noWildCardIDQuery=getArg("id-query");
@@ -227,6 +228,8 @@ GSQLBackend::GSQLBackend(const string &mode, const string &suffix)
   d_wildCardANYNoIDQuery=getArg("wildcard-any-query");
   d_wildCardANYIDQuery=getArg("wildcard-any-id-query");
   
+  d_reverseQuery=getArg("reverse-query");
+  
   d_listQuery=getArg("list-query");
 
   d_MasterOfDomainsZoneQuery=getArg("master-zone-query");
@@ -250,6 +253,7 @@ void GSQLBackend::lookup(const QType &qtype,const string &qname, DNSPacket *pkt_
   d_db->setLog(::arg().mustDo("query-logging"));
 
   string lcqname=toLower(qname);
+  int len = lcqname.length();
   
   if(qtype.getCode()!=QType::ANY) {
     // qtype qname domain_id
@@ -297,6 +301,22 @@ void GSQLBackend::lookup(const QType &qtype,const string &qname, DNSPacket *pkt_
     throw AhuException(e.txtReason());
   }
 
+  if(d_methodStrict && (qtype.getCode()==QType::PTR || qtype.getCode()==QType::ANY)) {
+    vector<string> parts;
+    string ip;
+    stringtok(parts, lcqname, ".");
+
+    if(len > 13 && lcqname.substr(len-13, 13)==".in-addr.arpa" && ptr2ip4(parts, ip)) {
+      snprintf(output,sizeof(output)-1, d_reverseQuery.c_str(), "A", ip.c_str());
+      d_extraQueries.push_back(output);
+    }
+    else if(len > 9 && lcqname.substr(len-9, 9)==".ip6.arpa" && parts.size() == 34) {
+      ip = ptr2ip6(parts);
+      snprintf(output,sizeof(output)-1, d_reverseQuery.c_str(), "AAAA", sqlEscape(ip).c_str());
+      d_extraQueries.push_back(output);
+    }
+  }
+
   d_qname=qname;
 
   d_qtype=qtype;
@@ -306,6 +326,12 @@ bool GSQLBackend::list(const string &target, int domain_id )
 {
   DLOG(L<<"GSQLBackend constructing handle for list of domain id'"<<domain_id<<"'"<<endl);
 
+  if(d_methodStrict && (target.size() > 13 && target.substr(target.size()-13, 13) == ".in-addr.arpa" ||
+                        target.size() > 9 && target.substr(target.size()-9, 9) == ".ip6.arpa")) {
+    L << Logger::Warning << "Request for reverse zone AXFR, but this is not supported in strict mode" << endl;
+    return false;   // AXFR isn't supported in strict mode. Use simple mode and additional PTR records
+  }
+
   char output[1024];
   snprintf(output,sizeof(output)-1,d_listQuery.c_str(),domain_id);
   try {
@@ -381,6 +407,17 @@ bool GSQLBackend::get(DNSResourceRecord &r)
     r.domain_id=atoi(row[4].c_str());
     return true;
   }
+  else if (!d_extraQueries.empty()) {
+    string& query = d_extraQueries.front();
+    try {
+      d_db->doQuery(query);
+    }
+    catch(SSqlException &e) {
+      throw AhuException(e.txtReason());
+    }
+    d_extraQueries.pop_front();
+    return get(r);
+  }
   
   return false;
 }
diff --git a/pdns/backends/gsql/gsqlbackend.hh b/pdns/backends/gsql/gsqlbackend.hh
index d56fd33..3c38105 100644
--- a/pdns/backends/gsql/gsqlbackend.hh
+++ b/pdns/backends/gsql/gsqlbackend.hh
@@ -1,5 +1,6 @@
 #include <string>
 #include <map>
+#include <list>
 #include "ssql.hh"
 
 using namespace std;
@@ -44,6 +45,8 @@ private:
   int d_count;
   SSql *d_db;
   SSql::result_t d_result;
+  bool d_methodStrict;
+  std::list<string> d_extraQueries;
 
   string d_wildCardNoIDQuery;
   string d_noWildCardNoIDQuery;
@@ -53,6 +56,7 @@ private:
   string d_noWildCardANYNoIDQuery;
   string d_noWildCardANYIDQuery;
   string d_wildCardANYIDQuery;
+  string d_reverseQuery;
   string d_listQuery;
   string d_logprefix;
   
diff --git a/pdns/docs/pdns.sgml b/pdns/docs/pdns.sgml
index 180b0ba..fb3855d 100644
--- a/pdns/docs/pdns.sgml
+++ b/pdns/docs/pdns.sgml
@@ -7144,6 +7144,7 @@ CREATE TABLE records (
 
 CREATE INDEX rec_name_index ON records(name);
 CREATE INDEX nametype_index ON records(name,type);
+CREATE INDEX content_index ON records(content); -- only necessary for strict mode
 CREATE INDEX domain_id ON records(domain_id);
 
 create table supermasters (
@@ -11254,6 +11255,7 @@ CREATE TABLE records (
 
 CREATE INDEX rec_name_index ON records(name);
 CREATE INDEX nametype_index ON records(name,type);
+CREATE INDEX content_index ON records(content); -- only necessary for strict mode
 CREATE INDEX domain_id ON records(domain_id);
 
 create table supermasters (
@@ -11316,6 +11318,7 @@ CREATE TABLE records (
 
 CREATE INDEX rec_name_index ON records(name);
 CREATE INDEX nametype_index ON records(name,type);
+CREATE INDEX content_index ON records(content); -- only necessary for strict mode
 CREATE INDEX domain_id ON records(domain_id);
 
 create table supermasters (
@@ -11376,6 +11379,7 @@ CREATE TABLE records (
 );
 
 create index RECORDS$NAME on RECORDS (NAME);
+create index RECORDS$CONTENT on RECORDS (CONTENT); -- only necessary for strict mode
 create sequence RECORDS_ID_SEQUENCE;
 
 create table supermasters (
@@ -11408,9 +11412,9 @@ insert into domains (id,name,type) values (domains_id_sequence.nextval,'netherla
 
       <sect2><title>Basic functionality</title>
 	<para>
-	  4 queries are needed for regular lookups, 4 for 'fancy records' which are disabled by default and 1 is needed for zone transfers.
+	  5 queries are needed for regular lookups, 4 for 'fancy records' which are disabled by default and 1 is needed for zone transfers.
 	</para>
-	<para>The 4+4 regular queries must return the following 6 fields, in this exact order:
+	<para>The 5+4 regular queries must return the following 6 fields, in this exact order:
 	  <variablelist>
 	    <varlistentry>
 	      <term>content</term>
@@ -11467,8 +11471,8 @@ insert into domains (id,name,type) values (domains_id_sequence.nextval,'netherla
 	  Please note that the names of the fields are not relevant, but the order is!
 	</para>
 	<para>
-	  As said earlier, there are 8 SQL queries for regular lookups. To configure them, set 'gmysql-basic-query' or 'gpgsql-basic-query', depending on your
-	  choice of backend. If so called 'MBOXFW' fancy records are not used, four queries remain:
+	  As said earlier, there are 9 SQL queries for regular lookups. To configure them, set 'gmysql-basic-query' or 'gpgsql-basic-query', depending on your
+	  choice of backend. If so called 'MBOXFW' fancy records are not used, five queries remain:
 	  <variablelist>
 	    <varlistentry>
 	      <term>basic-query</term>
@@ -11511,6 +11515,16 @@ insert into domains (id,name,type) values (domains_id_sequence.nextval,'netherla
 		</para>
 	      </listitem>
 	    </varlistentry>
+	    <varlistentry>
+	      <term>reverse-query</term>
+	      <listitem>
+		<para>
+		  For doing PTR queries in strict mode.
+		  Default: <command>select name,ttl,prio,'PTR',0,content from records where type='%s' and content='%s'</command>
+		  First %s is replaced by the record type (A or AAAA depending on query namespace), the second by the IP address being looked up.
+		</para>
+	      </listitem>
+	    </varlistentry>
 	  </variablelist>
 	</para>
 	<para>
@@ -11759,6 +11773,16 @@ insert into domains (id,name,type) values (domains_id_sequence.nextval,'netherla
                 </para>
               </listitem>
             </varlistentry>
+            <varlistentry>
+              <term>backend-method</term>
+              <listitem>
+                <para>
+                  Database lookup method.  May be 'simple' or 'strict'.  Default is simple mode.  In strict mode, PTR records are
+                  generated automatically using existing A and AAAA records.  Using 'strict', you won't be able to do zone transfers
+                  for reverse zones.
+                </para>
+              </listitem>
+            </varlistentry>
           </variablelist>
 	</para>
       </sect2>
@@ -12103,6 +12127,7 @@ insert into Records (id,ZoneId, name,type,content,TimeToLive,Priority) select RE
               
             CREATE INDEX rec_name_index ON records(name);
             CREATE INDEX nametype_index ON records(name,type);
+            CREATE INDEX content_index ON records(content); -- only necessary for strict mode
             CREATE INDEX domain_id ON records(domain_id);
 
             create table supermasters (
-- 
1.5.6.5


-- 
Peter
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 197 bytes
Desc: Digital signature
Url : http://mailman.powerdns.com/pipermail/pdns-dev/attachments/20081117/f5111ce9/attachment-0001.bin


More information about the Pdns-dev mailing list