[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