]> granicus.if.org Git - pdns/commitdiff
apply remotebackend service pack 1, by Aki Tuomi. Closes #597
authorPeter van Dijk <peter.van.dijk@netherlabs.nl>
Thu, 25 Oct 2012 08:00:45 +0000 (08:00 +0000)
committerPeter van Dijk <peter.van.dijk@netherlabs.nl>
Thu, 25 Oct 2012 08:00:45 +0000 (08:00 +0000)
git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@2824 d19b8d6e-7fed-0310-83ef-9ca221ded41b

68 files changed:
modules/remotebackend/httpconnector.cc
modules/remotebackend/pipeconnector.cc
modules/remotebackend/regression-tests/00dnssec-grabkeys/command [new file with mode: 0755]
modules/remotebackend/regression-tests/00dnssec-grabkeys/description [new file with mode: 0644]
modules/remotebackend/regression-tests/00dnssec-grabkeys/expected_result [new file with mode: 0644]
modules/remotebackend/regression-tests/apex-test/command [new file with mode: 0755]
modules/remotebackend/regression-tests/apex-test/description [new file with mode: 0644]
modules/remotebackend/regression-tests/apex-test/expected_result [new file with mode: 0644]
modules/remotebackend/regression-tests/backend.rb
modules/remotebackend/regression-tests/basic-a-dnssec/command [new file with mode: 0755]
modules/remotebackend/regression-tests/basic-a-dnssec/description [new file with mode: 0644]
modules/remotebackend/regression-tests/basic-a-dnssec/expected_result [new file with mode: 0644]
modules/remotebackend/regression-tests/basic-a-dnssec/skip.nodnssec [new file with mode: 0644]
modules/remotebackend/regression-tests/basic-aaaa-resolution/command [new file with mode: 0755]
modules/remotebackend/regression-tests/basic-aaaa-resolution/description [new file with mode: 0644]
modules/remotebackend/regression-tests/basic-aaaa-resolution/expected_result [new file with mode: 0644]
modules/remotebackend/regression-tests/basic-aaaa-resolution/tmp.rb [new file with mode: 0644]
modules/remotebackend/regression-tests/dnsbackend.rb
modules/remotebackend/regression-tests/dnssec-keys/command [new file with mode: 0755]
modules/remotebackend/regression-tests/dnssec-keys/description [new file with mode: 0644]
modules/remotebackend/regression-tests/dnssec-keys/expected_result [new file with mode: 0644]
modules/remotebackend/regression-tests/dnssec-keys/skip.nodnssec [new file with mode: 0644]
modules/remotebackend/regression-tests/example.com.ksk [new file with mode: 0644]
modules/remotebackend/regression-tests/example.com.zsk.1 [new file with mode: 0644]
modules/remotebackend/regression-tests/example.com.zsk.2 [new file with mode: 0644]
modules/remotebackend/regression-tests/http-backend.rb
modules/remotebackend/regression-tests/list-all-records/command [new file with mode: 0755]
modules/remotebackend/regression-tests/list-all-records/description [new file with mode: 0644]
modules/remotebackend/regression-tests/list-all-records/expected_result [new file with mode: 0644]
modules/remotebackend/regression-tests/long-txt-resolution/command [new file with mode: 0755]
modules/remotebackend/regression-tests/long-txt-resolution/description [new file with mode: 0644]
modules/remotebackend/regression-tests/long-txt-resolution/expected_result [new file with mode: 0644]
modules/remotebackend/regression-tests/long-txt-resolution/tmp.rb [new file with mode: 0644]
modules/remotebackend/regression-tests/ns-at-delegation/command [new file with mode: 0755]
modules/remotebackend/regression-tests/ns-at-delegation/description [new file with mode: 0644]
modules/remotebackend/regression-tests/ns-at-delegation/expected_result [new file with mode: 0644]
modules/remotebackend/regression-tests/nsec-middle/command [new file with mode: 0755]
modules/remotebackend/regression-tests/nsec-middle/description [new file with mode: 0644]
modules/remotebackend/regression-tests/nsec-middle/expected_result [new file with mode: 0644]
modules/remotebackend/regression-tests/nsec-middle/expected_result.narrow [new file with mode: 0644]
modules/remotebackend/regression-tests/nsec-middle/expected_result.nsec3 [new file with mode: 0644]
modules/remotebackend/regression-tests/nsec-middle/skip.nodnssec [new file with mode: 0644]
modules/remotebackend/regression-tests/nsec-sibling-test/command [new file with mode: 0755]
modules/remotebackend/regression-tests/nsec-sibling-test/description [new file with mode: 0644]
modules/remotebackend/regression-tests/nsec-sibling-test/expected_result [new file with mode: 0644]
modules/remotebackend/regression-tests/nsec-sibling-test/expected_result.narrow [new file with mode: 0644]
modules/remotebackend/regression-tests/nsec-sibling-test/expected_result.nsec3 [new file with mode: 0644]
modules/remotebackend/regression-tests/nsec-sibling-test/skip.nodnssec [new file with mode: 0644]
modules/remotebackend/regression-tests/nsec-wraparound-begin/command [new file with mode: 0755]
modules/remotebackend/regression-tests/nsec-wraparound-begin/description [new file with mode: 0644]
modules/remotebackend/regression-tests/nsec-wraparound-begin/expected_result [new file with mode: 0644]
modules/remotebackend/regression-tests/nsec-wraparound-begin/expected_result.nsec3 [new file with mode: 0644]
modules/remotebackend/regression-tests/nsec-wraparound-begin/skip.nodnssec [new file with mode: 0644]
modules/remotebackend/regression-tests/nsec-wraparound-end/command [new file with mode: 0755]
modules/remotebackend/regression-tests/nsec-wraparound-end/description [new file with mode: 0644]
modules/remotebackend/regression-tests/nsec-wraparound-end/expected_result [new file with mode: 0644]
modules/remotebackend/regression-tests/nsec-wraparound-end/expected_result.nsec3 [new file with mode: 0644]
modules/remotebackend/regression-tests/nsec-wraparound-end/skip.nodnssec [new file with mode: 0644]
modules/remotebackend/regression-tests/pipe-backend.rb
modules/remotebackend/regression-tests/test-schema.sql
modules/remotebackend/regression-tests/up.example.com.ksk [new file with mode: 0644]
modules/remotebackend/regression-tests/up.example.com.zsk.1 [new file with mode: 0644]
modules/remotebackend/regression-tests/up.example.com.zsk.2 [new file with mode: 0644]
modules/remotebackend/remotebackend.cc
modules/remotebackend/remotebackend.hh
modules/remotebackend/test_backend.rb [deleted file]
modules/remotebackend/unixconnector.cc
regression-tests/start-test-stop

index 2433efbe8d6c0d971841cdf3036767e56fdaafde..c5aae9f079d1bda4a30de31998b6e1f5d214d406 100644 (file)
@@ -57,8 +57,12 @@ void HTTPConnector::requestbuilder(const std::string &method, const Json::Value
 
     ss << "/" << method;
 
-    // add the url components, if found, in following order 
-
+    // add the url components, if found, in following order.
+    // id must be first due to the fact that the qname/name can be empty
+    if ((param = parameters.get("id", Json::Value())).isNull() == false) {
+       json2string(param, sparam);
+       ss << "/" << sparam;
+    }
     if ((param = parameters.get("zonename", Json::Value())).isNull() == false) {
        json2string(param, sparam);
        ss << "/" << sparam;
@@ -83,11 +87,6 @@ void HTTPConnector::requestbuilder(const std::string &method, const Json::Value
        ss << "/" << sparam;
     }
 
-    if ((param = parameters.get("id", Json::Value())).isNull() == false) {
-       json2string(param, sparam);
-       ss << "/" << sparam;
-    }
-
     // finally add suffix
     ss << d_url_suffix;
     curl_easy_setopt(d_c, CURLOPT_URL, ss.str().c_str());
@@ -102,7 +101,7 @@ void HTTPConnector::requestbuilder(const std::string &method, const Json::Value
         // create post with keydata
         std::stringstream ss2;
         param = parameters["key"]; 
-        ss2 << "flags" << param["flags"].asUInt() << "&active" << (param["active"].asBool() ? 1 : 0) << "&content=";
+        ss2 << "flags=" << param["flags"].asUInt() << "&active=" << (param["active"].asBool() ? 1 : 0) << "&content=";
         tmpstr = curl_easy_escape(d_c, param["content"].asCString(), 0);
         ss2 << tmpstr;
         sparam = ss2.str();
index 13a97c5f9f386ecb3652509cd83ea77cbc28ea04..133e36e42503b35dcc1d6bee4e66c7cac41661e2 100644 (file)
@@ -1,6 +1,10 @@
 #include "remotebackend.hh"
 
 PipeConnector::PipeConnector(std::map<std::string,std::string> options) {
+  if (options.count("command") == 0) {
+    L<<Logger::Error<<"Cannot find 'command' option in connection string"<<endl;
+    throw new AhuException();
+  }
   this->command = options.find("command")->second;
   this->options = options;
   this->coproc = NULL;
diff --git a/modules/remotebackend/regression-tests/00dnssec-grabkeys/command b/modules/remotebackend/regression-tests/00dnssec-grabkeys/command
new file mode 100755 (executable)
index 0000000..0d984d3
--- /dev/null
@@ -0,0 +1,16 @@
+#!/bin/sh -e
+set pipefail
+rm -f trustedkeys
+rm -f unbound-host.conf
+for zone in example.com 
+do
+       drill -p $port -o rd -D dnskey $zone @$nameserver | grep -v '^;' | grep -v AwEAAarTiHhPgvD28WCN8UBXcEcf8f >> trustedkeys
+       echo "stub-zone:" >> unbound-host.conf
+       echo "  name: $zone" >> unbound-host.conf
+       echo "  stub-addr: $nameserver@$port" >> unbound-host.conf
+       echo "" >> unbound-host.conf
+done
+
+echo "server:" >> unbound-host.conf
+echo "  do-not-query-address: 192.168.0.0/16" >> unbound-host.conf
+echo '  trust-anchor-file: "trustedkeys"' >> unbound-host.conf
diff --git a/modules/remotebackend/regression-tests/00dnssec-grabkeys/description b/modules/remotebackend/regression-tests/00dnssec-grabkeys/description
new file mode 100644 (file)
index 0000000..4315650
--- /dev/null
@@ -0,0 +1 @@
+Grab DNSKEY records for validation testing.
diff --git a/modules/remotebackend/regression-tests/00dnssec-grabkeys/expected_result b/modules/remotebackend/regression-tests/00dnssec-grabkeys/expected_result
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/modules/remotebackend/regression-tests/apex-test/command b/modules/remotebackend/regression-tests/apex-test/command
new file mode 100755 (executable)
index 0000000..f8868dd
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+cleandig up.example.com NS
diff --git a/modules/remotebackend/regression-tests/apex-test/description b/modules/remotebackend/regression-tests/apex-test/description
new file mode 100644 (file)
index 0000000..a735cbf
--- /dev/null
@@ -0,0 +1 @@
+Verify that up.example.com NS records come out right
diff --git a/modules/remotebackend/regression-tests/apex-test/expected_result b/modules/remotebackend/regression-tests/apex-test/expected_result
new file mode 100644 (file)
index 0000000..11c99e7
--- /dev/null
@@ -0,0 +1,6 @@
+0      up.example.com. IN      NS      120     ns1.example.com.
+0      up.example.com. IN      NS      120     ns2.example.com.
+2      ns1.example.com.        IN      A       120     192.168.2.2
+2      ns2.example.com.        IN      A       120     192.168.2.3
+Rcode: 0, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='up.example.com.', qtype=NS
index c7c882c957103efdd31af2e97851835b7af67b4c..8f859418094fb44ad43cfa0dd3860058ccd89adf 100755 (executable)
@@ -8,34 +8,62 @@ def rr(qname, qtype, content, ttl, priority = 0, auth = 1, domain_id = -1)
 end
 
 class Handler
-   attr :db
    def initialize(dbpath)
-     @db = SQLite3::Database.new dbpath
+     @dbpath = dbpath
+   end
+
+   def db
+      d = SQLite3::Database.new @dbpath
+      if block_given?
+        d.transaction
+        begin
+           yield d
+        rescue
+           d.rollback
+           return
+         end
+         d.commit
+      else
+         d
+      end
    end
 
    def do_initialize(*args)
      return true, "Test bench initialized"
    end
 
+   def getbeforename(qname, id)
+        before = db.get_first_value("SELECT ordername FROM records WHERE ordername < ? AND domain_id = ? ORDER BY ordername DESC", qname, id)
+        if (before.nil?) 
+           before = db.get_first_value("SELECT ordername FROM records WHERE domain_id = ? ORDER by ordername DESC LIMIT 1", id)
+        end
+        before
+   end
+
+  def getaftername(qname, id)
+        after = db.get_first_value("SELECT ordername FROM records WHERE ordername > ? AND domain_id = ? ORDER BY ordername", qname, id)
+        if (after.nil?)
+           after = db.get_first_value("SELECT ordername FROM records WHERE domain_id = ? ORDER by ordername LIMIT 1", id)
+        end
+        after
+   end
+
+
    def do_getbeforeandafternamesabsolute(args)
-        before = @db.get_first_value("SELECT ordername FROM records WHERE ordername < ? AND domain_id = ?", args["qname"], args["id"])
-        after = @db.get_first_value("SELECT ordername FROM records WHERE ordername > ? AND domain_id = ?", args["qname"], args["id"])
-        return [{:before => before, :after => after, :unhashed => args["qname"]}, nil]
+        args["qname"] = "" if args["qname"].nil?
+        return [{:before => getbeforename(args["qname"],args["id"]), :after => getaftername(args["qname"],args["id"]), :unhashed => args["qname"]}, nil]
    end
 
    def do_getbeforeandafternames(args)
-        before = @db.get_first_value("SELECT ordername FROM records WHERE ordername < ? AND domain_id = ?", args["qname"], args["id"])
-        after = @db.get_first_value("SELECT ordername FROM records WHERE ordername > ? AND domain_id = ?", args["qname"], args["id"])
-        return [{:before => before, :after => after, :unhashed => args["qname"]}, nil]
+        args["qname"] = "" if args["qname"].nil?
+        return [{:before => getbeforename(args["qname"],args["id"]), :after => getaftername(args["qname"],args["id"]), :unhashed => args["qname"]}, nil]
    end
 
    def do_getdomainkeys(args)
        ret = []
-       @db.execute("SELECT flags,active,content FROM domains JOIN cryptokeys ON domains.id = cryptokeys.domain_id WHERE domains.name = ?", args["name"]) do |row|
-          ret << {:flags => row[0].to_i, :active => !(row[1].to_i.zero?), :content => row[2]}
+       db.execute("SELECT cryptokeys.id,flags,active,content FROM domains JOIN cryptokeys ON domains.id = cryptokeys.domain_id WHERE domains.name = ?", [args["name"]]) do |row|
+          ret << {:id => row[0].to_i, :flags => row[1].to_i, :active => !(row[2].to_i.zero?), :content => row[3]}
        end 
-
        return false if ret.empty?
        return [ret,nil]
    end
@@ -45,13 +73,25 @@ class Handler
      loop do
         begin
           sargs = {}
-          if (args["qtype"] == "ANY")
-             sql = "SELECT domain_id,name,type,content,ttl,prio,auth FROM records WHERE name = :qname"
-             sargs["qname"] = args["qname"]
+          if (args["zone-id"].to_i > 0)
+             sargs["domain_id"] = args["zone-id"].to_i
+             if (args["qtype"] == "ANY")
+                sql = "SELECT domain_id,name,type,content,ttl,prio,auth FROM records WHERE name = :qname AND domain_id = :domain_id"
+                sargs["qname"] = args["qname"]
+             else
+                sql = "SELECT domain_id,name,type,content,ttl,prio,auth FROM records WHERE name = :qname AND type = :qtype AND domain_id = :domain_id"
+                sargs["qname"] = args["qname"]
+                sargs["qtype"] = args["qtype"]
+             end
           else
-             sql = "SELECT domain_id,name,type,content,ttl,prio,auth FROM records WHERE name = :qname AND type = :qtype"
-             sargs["qname"] = args["qname"]
-             sargs["qtype"] = args["qtype"]
+             if (args["qtype"] == "ANY")
+                sql = "SELECT domain_id,name,type,content,ttl,prio,auth FROM records WHERE name = :qname"
+                sargs["qname"] = args["qname"]
+             else
+                sql = "SELECT domain_id,name,type,content,ttl,prio,auth FROM records WHERE name = :qname AND type = :qtype"
+                sargs["qname"] = args["qname"]
+                sargs["qtype"] = args["qtype"]
+             end  
           end
           db.execute(sql, sargs) do |row|
             ret << rr(row[1], row[2], row[3], row[4], row[5], row[6], row[0])
@@ -64,9 +104,21 @@ class Handler
      return false unless ret.size > 0
      return [ret,nil]
    end
+  
+   def do_getdomaininfo(args) 
+     ret = {}
+     sql = "SELECT name,content FROM records WHERE name = :name AND type = 'SOA'"
+     db.execute(sql, args) do |row|
+       ret[:zone] = row[0]
+       ret[:serial] = row[1].split(' ')[2].to_i
+       ret[:kind] = "native"
+     end
+     return [ret,nil] if ret.has_key?(:zone)
+     return false
+   end
+
    def do_list(args)
-     target = args["target"]
+     target = args["zonename"]
      ret = []
      loop do
         begin
@@ -77,6 +129,7 @@ class Handler
           end
         rescue Exception => e
           e.backtrace
+          return false, [e.message]
         end
         break
      end
@@ -84,11 +137,63 @@ class Handler
      return [ret,nil]
    end
 
+   def do_adddomainkey(args)
+     d_id = db.get_first_value("SELECT id FROM domains WHERE name = ?", args["name"])
+     return false if d_id.nil?
+     sql = "INSERT INTO cryptokeys (domain_id, flags, active, content) VALUES(?,?,?,?)"
+     active = args["key"]["active"]
+     if (active) 
+        active = 1
+     else
+        active = 0
+     end
+     db do |tx|
+        tx.execute(sql, [d_id, args["key"]["flags"].to_i, active, args["key"]["content"]])
+     end
+     return db.get_first_value("SELECT last_insert_rowid()").to_i
+   end
+
+   def do_deactivatedomainkey(args)
+     d_id = db.get_first_value("SELECT id FROM domains WHERE name = ?", args["name"])
+     return false if d_id.nil?
+     db do |tx|
+       tx.execute("UPDATE cryptokeys SET active = 0 WHERE domain_id = ? AND id = ?", [d_id, args["id"]])  
+     end
+     return true
+   end
+
+   def do_activatedomainkey(args)
+     d_id = db.get_first_value("SELECT id FROM domains WHERE name = ?", args["name"])
+     return false if d_id.nil?
+     db do |tx|
+       db.execute("UPDATE cryptokeys SET active = 1 WHERE domain_id = ? AND id = ?", [d_id, args["id"]])
+     end
+     return true
+   end
+
    def do_getdomainmetadata(args) 
-       return false
+       ret = []
+        sql = "SELECT content FROM domainmetadata JOIN domains WHERE name = :name AND kind = :kind"
+        sargs = {:name => args["name"], :kind => args["kind"]}
+        db.execute(sql,sargs) do |row|
+          ret << row[0]
+        end
+        return false unless ret.size > 0
+        return [ret,nil]
    end
 
    def do_setdomainmetadata(args)
-       return false
+        d_id = db.get_first_value("SELECT id FROM domains WHERE name = ?", args["name"])
+        return false if d_id.nil?
+        db do |tx|
+           sql = "DELETE FROM domainmetadata WHERE domain_id = ?"
+           tx.execute(sql, [d_id]) 
+           break if args["value"].nil?
+           sql = "INSERT INTO domainmetadata (domain_id,kind,content) VALUES(?,?,?)"
+           args["value"].each do |value|
+             tx.execute(sql,[d_id, args["kind"], value])
+           end
+        end
+       return true
    end
 end
diff --git a/modules/remotebackend/regression-tests/basic-a-dnssec/command b/modules/remotebackend/regression-tests/basic-a-dnssec/command
new file mode 100755 (executable)
index 0000000..6d157fc
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+cleandig outpost.example.com A dnssec
diff --git a/modules/remotebackend/regression-tests/basic-a-dnssec/description b/modules/remotebackend/regression-tests/basic-a-dnssec/description
new file mode 100644 (file)
index 0000000..6cd423e
--- /dev/null
@@ -0,0 +1 @@
+Basic DNSSEC test
diff --git a/modules/remotebackend/regression-tests/basic-a-dnssec/expected_result b/modules/remotebackend/regression-tests/basic-a-dnssec/expected_result
new file mode 100644 (file)
index 0000000..76c3fec
--- /dev/null
@@ -0,0 +1,5 @@
+0      outpost.example.com.    IN      A       120     192.168.2.1
+0      outpost.example.com.    IN      RRSIG   120     A 8 3 120 [expiry] [inception] [keytag] example.com. ...
+2      .       IN      OPT     32768   
+Rcode: 0, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='outpost.example.com.', qtype=A
diff --git a/modules/remotebackend/regression-tests/basic-a-dnssec/skip.nodnssec b/modules/remotebackend/regression-tests/basic-a-dnssec/skip.nodnssec
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/modules/remotebackend/regression-tests/basic-aaaa-resolution/command b/modules/remotebackend/regression-tests/basic-aaaa-resolution/command
new file mode 100755 (executable)
index 0000000..4a6e523
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+cleandig outpost.example.com AAAA 
+
diff --git a/modules/remotebackend/regression-tests/basic-aaaa-resolution/description b/modules/remotebackend/regression-tests/basic-aaaa-resolution/description
new file mode 100644 (file)
index 0000000..2bfe713
--- /dev/null
@@ -0,0 +1,2 @@
+This test tries to resolve a straight AAAA record that is directly available in
+the database backend.
diff --git a/modules/remotebackend/regression-tests/basic-aaaa-resolution/expected_result b/modules/remotebackend/regression-tests/basic-aaaa-resolution/expected_result
new file mode 100644 (file)
index 0000000..1155d21
--- /dev/null
@@ -0,0 +1,3 @@
+0      outpost.example.com.    IN      AAAA    120     fe80::1
+Rcode: 0, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='outpost.example.com.', qtype=AAAA
diff --git a/modules/remotebackend/regression-tests/basic-aaaa-resolution/tmp.rb b/modules/remotebackend/regression-tests/basic-aaaa-resolution/tmp.rb
new file mode 100644 (file)
index 0000000..3cbe477
--- /dev/null
@@ -0,0 +1,46 @@
+qname = "node-b.dyn.example.com"
+
+def to32(number)
+   number.to_s(32).tr "0123456789abcdefghijklmnopqrstuv", "ybndrfg8ejkmcpqxot1uwisza345h769"
+end
+
+def from32(str)
+   str.tr("ybndrfg8ejkmcpqxot1uwisza345h769", "0123456789abcdefghijklmnopqrstuv").to_i(32)
+end
+
+def rr(qname, qtype, content, ttl, priority = 0, auth = 1)
+   {:qname => qname, :qtype => qtype, :content => content, :ttl => ttl, :priority => priority, :auth => auth}
+end
+
+def send_result(*params)
+
+end
+
+def main(qname,qtype)
+   if qname[/\.?dyn.example.com$/]
+    if qname == "dyn.example.com"
+      ret = []
+      if (qtype != "SOA")
+         ret << rr(qname, "NS", "ns1.example.com",300)
+         ret << rr(qname, "NS", "ns2.example.com",300)
+         ret << rr(qname, "NS", "ns3.example.com",300)
+      end
+      ret << rr(qname,"SOA","ns1.example.com hostmaster.example.com #{Time.now.strftime("%Y%m%d%H")} 28800 7200 1209600 300",300)
+      return send_result ret
+    elsif qtype == "ANY" or qtype == "AAAA"
+      name = qname.match(/^node-(.*)\.dyn.example.com$/)[1]
+      if name.empty?
+        return send_result false
+      end
+#      if name.size < 16
+#        pad = 15-name.size
+#        (1..pad).each do |i| name = "y#{name}" end
+#      end
+      puts from32(name)
+      return send_result [rr(qname, "AAAA", "", 300)]
+    end
+   end
+   send_result false
+end
+
+main qname,"AAAA"
index 427446f1d6b3997a19e120b36b450e16d2162881..f896b683a439bbf270363f5f563d4a36da67340d 100644 (file)
@@ -1,28 +1,60 @@
 require 'json'
+require 'thread'
 
 class DNSBackendHandler < WEBrick::HTTPServlet::AbstractServlet
    def initialize(server, dnsbackend)
      @dnsbackend = dnsbackend
+     @semaphore = Mutex.new
+     @f = File.open("/tmp/tmp.txt","a")
+   end
+
+   def parse_url(url)
+     url = url.split('/')
+     method = url.shift.downcase
+
+     # do some determining based on method names
+     args = case method
+     when "lookup"
+         {
+          "qname" => url.shift,
+          "qtype" => url.shift,
+         }
+     when "list"
+        {
+          "zonename" => url.shift
+        }
+     when "getbeforeandafternamesabsolute", "getbeforeandafternames"
+        {
+           "id" => url.shift.to_i,
+           "qname" => url.shift 
+        }
+     when "getdomainmetadata", "setdomainmetadata", "getdomainkeys"
+        {
+            "name" => url.shift,
+            "kind" => url.shift
+        }
+     when "removedomainkey", "activatedomainkey", "deactivatedomainkey"
+        {
+             "id" => url.shift,
+             "name" => url.shift
+        } 
+     when "adddomainkey", "gettsigkey", "getdomaininfo"
+        {
+             "name" => url.shift
+        }
+     end
+
+     [method, args]
    end
 
    def do_GET(req,res)
      tmp = req.path[/dns\/(.*)/,1]
      return 400, "Bad request" if (tmp.nil?)
-     tmp = tmp.split("/")
-     method = "do_#{tmp.shift}".downcase
-     args = {}
-
-     if tmp.size > 0 
-       args["qname"] = tmp[0]
-       args["name"] = tmp[0]
-       args["target"] = tmp.shift
-     end
-     if tmp.size > 0
-       args["kind"] = tmp[0]
-       args["qtype"] = tmp[0]
-       args["id"] = tmp.shift
-     end
 
+     method, args = parse_url(tmp)
+
+     method = "do_#{method}"
+    
      # get more arguments
      req.each do |k,v|
         attr = k[/X-RemoteBackend-(.*)/,1]
@@ -31,25 +63,39 @@ class DNSBackendHandler < WEBrick::HTTPServlet::AbstractServlet
         end
      end
 
-     if @dnsbackend.respond_to?(method.to_sym)
-       result, log = @dnsbackend.send(method.to_sym, args)
-        body = {:result => result, :log => log}
-        res.status = 200
-        res["Content-Type"] = "application/javascript; charset=utf-8"
-        res.body = body.to_json
-     else
-        res.status = 404
-        res["Content-Type"] = "application/javascript; charset=utf-8"
-        res.body = ({:result => false, :log => ["Method not found"]}).to_json
+     args = args.merge req.query
+
+     if method == "do_adddomainkey"
+        args["key"] = {
+           "flags" => args.delete("flags").to_i,
+           "active" => args.delete("active").to_i,
+           "content" => args.delete("content")
+        }
+     end
+
+     @f.puts method
+     @f.puts args
+
+     @semaphore.synchronize do
+       if @dnsbackend.respond_to?(method.to_sym)
+          result, log = @dnsbackend.send(method.to_sym, args)
+          body = {:result => result, :log => log}
+          res.status = 200
+          res["Content-Type"] = "application/javascript; charset=utf-8"
+          res.body = body.to_json
+        else
+          res.status = 404
+          res["Content-Type"] = "application/javascript; charset=utf-8"
+          res.body = ({:result => false, :log => ["Method not found"]}).to_json
+        end
      end
    end
 
    def do_DELETE(req,res)
+     do_GET(req,res)
    end
    
    def do_POST(req,res)
-     req.continue
-
-     # get method name and args
+     do_GET(req,res)
    end 
 end
diff --git a/modules/remotebackend/regression-tests/dnssec-keys/command b/modules/remotebackend/regression-tests/dnssec-keys/command
new file mode 100755 (executable)
index 0000000..50dd9f3
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+cleandig example.com DNSKEY 
diff --git a/modules/remotebackend/regression-tests/dnssec-keys/description b/modules/remotebackend/regression-tests/dnssec-keys/description
new file mode 100644 (file)
index 0000000..ba38d23
--- /dev/null
@@ -0,0 +1 @@
+Check that pdns can read keys from backend
diff --git a/modules/remotebackend/regression-tests/dnssec-keys/expected_result b/modules/remotebackend/regression-tests/dnssec-keys/expected_result
new file mode 100644 (file)
index 0000000..5bff4c2
--- /dev/null
@@ -0,0 +1,4 @@
+0      example.com.    IN      DNSKEY  120     256 3 8 ...
+0      example.com.    IN      DNSKEY  120     257 3 8 ...
+Rcode: 0, RD: 0, QR: 1, TC: 1, AA: 1, opcode: 0
+Reply to question for qname='example.com.', qtype=DNSKEY
diff --git a/modules/remotebackend/regression-tests/dnssec-keys/skip.nodnssec b/modules/remotebackend/regression-tests/dnssec-keys/skip.nodnssec
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/modules/remotebackend/regression-tests/example.com.ksk b/modules/remotebackend/regression-tests/example.com.ksk
new file mode 100644 (file)
index 0000000..f8740a5
--- /dev/null
@@ -0,0 +1,11 @@
+Private-key-format: v1.2
+Algorithm: 8 (RSASHA256)
+Modulus: 50uFCCyl8CcSdUqOVHpbx38cL4yzRR4IULwnzMqjGkAQCZ/aMKJ6XzO1LUU/QIobJ5uO3r5GkLWAkW1ne+xEtuuj5CUuAG2lBifciNOVfrljmtuPRU1QahhzL48cZdiGjUvhcSKAo8ftwzH3NMLVzURZxT0C+JWvC18sZHs2w20+HVIZbZzCqwuTDpAsqPklxjflSZQRHrB3OI07hMRoWbAi2bIvjI6BgVUsMIUyNymfLPIROEMVj1fqQcygfzwAZcFWZSGU3Isxz8O4JTizGvaJ1E4Yh/QkHP1MMc6Kggbbd+KyYt1UfXLUFMDraiNFl8oNbOoJDdtA4oRX1bN8EQ==
+PublicExponent: AQAB
+PrivateExponent: Lsygh8Vk9AEr4nCp+NzjKiwFe3eIJHGNtCxGD1FnDB4vQItIHjQZ955iR90tjbUEBpEaqOYuKASZlZNh73igdLScLkL5mluVGvhAzqylIIWJamGHjTm2DimRUOuvjsnve7KBVJ9rEPiYmrjG8LWFhimQ0nBkZAEBcJcax+AIdiUHgR7SkyRIeuitZCbNiiJ7s2dkdN2JBxhEsZi+q13vDjGy1Ifu1M5nXXPjHsj3aoorSwmnOsR3AwSgC8nydL0OxNo2Fm54qdZC2EftX6KVaRYi3UWJd1lNt6wgBO6w2iDdLteg70P3XuzWyZe0CxHqG956LMQqvKSr59o5j2tYeQ==
+Prime1: +DWjjc/Z+u8UiLDBjDFNmM2wzEPoIAFkq86dj+n427jd72hFlAeuO2K6AgXekXSB7TA3JeBGKLyXzCoLN9C4wKLCMAcZs3uOmA43xEgL+cufKfFgKmrrq/mX0y34B17jtt6fL+oSYHuoryN9WxBeNfpz94lb9xE6cptoUopiJJ0=
+Prime2: 7o35Ayz2OhYeUkDsJCQ7Q38Vv5qdB8u8BXLYzEH3/fLiOViaHPUfg+jQ9TzEc3XCgQ212LI3yqwWsQ6nMnB+X9H1czW9OW9LJC9cS0mayIxdbYIa1HzUyYzCSiZfEFwzNXBPkfnmYjHqAPzCsAuBmrH9z3oo7c1rHcltrL84SQU=
+Exponent1: D1W5ChzqWb+FpEBPZOry4Vrr7mLPp5KOdrLoNyj8cA7G33Cww8mJsS+TUGaubowlLtNIxPVLQF8OfdWnJcamc3hayP7XTqh2kdxnA6Bz5PX4mm3IRDag4toj0C9J4KKzLOwqJ5qtkfpx3IgzyXmEaI9VtNhuryAIXWZOlrLoB10=
+Exponent2: zQxjmgMvskYI0hLT50ztU9sMyqEPkP/iIZzSFOAvVa1MHpa2AWYBLNUVp3YQNl5mTZ+HSzgFFMROzOoXdReUyLAkFl9+wruTDwtWfbBKx08/jz1h6ntSO9wttKa+18Uojyp2erce/BCDX03j2oZJZLrRu2D5hU4oYHYfO3kx3DE=
+Coefficient: 1lIUp+1hdC3zOULOkFpMqXFKp4QTkRLxffMnvH5jvfTaofGwYAFSFKIj289OQrmjJ0HXMJNEQ5vK0pW7K4newD1fefPYI3zyRE4zzew3hWlsGFgTqAsqEqk/gpPOMKJ0fWXJoFN4N5+3SOKYUthyRQHpxPI4IXKsL6Ckygf7Ydg=
+
diff --git a/modules/remotebackend/regression-tests/example.com.zsk.1 b/modules/remotebackend/regression-tests/example.com.zsk.1
new file mode 100644 (file)
index 0000000..bd7d3f2
--- /dev/null
@@ -0,0 +1,11 @@
+Private-key-format: v1.2
+Algorithm: 8 (RSASHA256)
+Modulus: yIrPfzxbh4ndcbY/Kv0pp5/wVDBkrNaPOJMRKmASPFP8tbBSsvk49ARQEdrTGtPg0tMdUCX1nPZPIVmJsrD2/xGcpW0A+CAOB4H7Akz+nHlhkgPtErM6zPktxoQXBVUWKkcddJjEO5gAgXHN3Y/Ji6fDmtiRTjFUPyNYrBzf7zc=
+PublicExponent: AQAB
+PrivateExponent: Aiff2CXNdBUK0NydLDiheIBTJIyKoIMD8h8+mX6D46shddCJ6wubzZ+4PqDkEQ9DBPEpCQIHdGL/ccPVI5scZJerFbEdZP12n+0ZRoAkhbuhgTYlUQh253y8w+CIOipgIMo9WAM66/F6Y8KBpPp2qq7OJHbbKGhEQMKrx/dsHeE=
+Prime1: 7MnlWpyUSc5vKcnZjo4Qj3OC+VQXiC3vXFSWFY3xF5dKc0tIbaznTwH+KQ35gFZ6ZBVPkHQP/v6VPv6t5V5h1w==
+Prime2: 2NATZQeCOwtPCuahak8pM2166PmTI84zUYmRWINf957KniyP44eM068HOm5RZeF7MwdnzrOV+tx3l3tftb/xoQ==
+Exponent1: hj40RHnO7EUX6sYgDFzocJuZXodZTABW2q6t5Axz6d8A+3pr1poXDUjg8h+VGzhr7P/T+t6CDxwAOxWiOw6WQw==
+Exponent2: ke78HvR+498oxN2XqEbAJK18HXRfZapVQHyoKDvFTJbFKtIzx6JlV9ZntxyqDTlIA4DojmiyergKhxuzwFICAQ==
+Coefficient: m0leC8nHk+4zytiraipFK2/WRzmDw9+pHLqWpCKnXkWSVCdbhw1tyNfS4WDKL8iBXcV774WL0oR/naOwU72IpA==
+
diff --git a/modules/remotebackend/regression-tests/example.com.zsk.2 b/modules/remotebackend/regression-tests/example.com.zsk.2
new file mode 100644 (file)
index 0000000..e74a199
--- /dev/null
@@ -0,0 +1,11 @@
+Private-key-format: v1.2
+Algorithm: 8 (RSASHA256)
+Modulus: r+vmQll38ndQqNSCx9eqRBUbSOLcH4PZFX824sGhY2NSQChqt1G4ZfndzRwgjXMUwiE7GkkqU2Vbt/g4iP67V/+MYecMV9YHkCRnEzb47nBXvs9JCf8AHMCnma567GQjPECh4HevPE9wmcOfpy/u7UN1oHKSKRWuZJadUwcjbp8=
+PublicExponent: AQAB
+PrivateExponent: CYC93UtVnOM6wrFJZ+qA9+Yx+p5yk0CSi0Q7c+/6EVMuABQ5gNyTuu0j65lU3X81bwUk2wHPx6smfgoVDRAW5jjO4jgIFV6nE4inzk5YQKycQSL8YG3Nm9GciLFya1KUXs81sHsQpkvK7MNaSbvkaHZQ6iv16bZ4t73Wascwa/E=
+Prime1: 6a165cIC0nNsGlTW/s2jRu7idq5+U203iE1HzSIddmWgx5KIKE/s3I+pwfmXYRUmq+4H9ASd/Yot1lSYW98szw==
+Prime2: wLoCPKxxnuxDx6/9IKOYz8t9ZNLY74iCeQ85koqvTctkFmB9jpOUHTU9BhecaFY2euP9CuHV7z3PLtCoO8s1MQ==
+Exponent1: CuzJaiR/7UboLvL4ekEy+QYCIHpX/Z6FkiHK0ZRevEJUGgCHzRqvgEBXN3Jr2WYbwL4IMShmGoxzSCn8VY9BkQ==
+Exponent2: LDR9/tyu0vzuLwc20B22FzNdd5rFF2wAQTQ0yF/3Baj5NAi9w84l0u07KgKQZX4g0N8qUyypnU5YDyzc6ZoagQ==
+Coefficient: 6S0vhIQITWzqfQSLj+wwRzs6qCvJckHb1+SD1XpwYjSgMTEUlZhf96m8WiaE1/fIt4Zl2PC3fF7YIBoFLln22w==
+
index a0e0529b5aa5e0d0070d58e9135dd98ceddd39d9..8a49989dc61cba48946a8934273f2975a3f24b33 100755 (executable)
@@ -5,10 +5,17 @@ require "webrick"
 require "../modules/remotebackend/regression-tests/dnsbackend"
 require "../modules/remotebackend/regression-tests/backend"
 
-server = WEBrick::HTTPServer.new :Port => 62434
+server = WEBrick::HTTPServer.new(
+       Port: 62434,
+       BindAddress: "localhost",
+#      Logger: WEBrick::Log.new("remotebackend-server.log"),
+       AccessLog: [ [ File.open("remotebackend-access.log", "w"), WEBrick::AccessLog::COMBINED_LOG_FORMAT ] ] 
+)
 
 be = Handler.new("../modules/remotebackend/regression-tests/remote.sqlite3") 
-
 server.mount "/dns", DNSBackendHandler, be
+
 trap('INT') { server.stop }
+trap('TERM') { server.stop }
+
 server.start
diff --git a/modules/remotebackend/regression-tests/list-all-records/command b/modules/remotebackend/regression-tests/list-all-records/command
new file mode 100755 (executable)
index 0000000..bf5680d
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+dig example.com AXFR @$nameserver -p $port | grep "IN" | egrep -v "(NSEC|RRSIG|DNSKEY)" | LC_ALL=C sort
diff --git a/modules/remotebackend/regression-tests/list-all-records/description b/modules/remotebackend/regression-tests/list-all-records/description
new file mode 100644 (file)
index 0000000..2106ef6
--- /dev/null
@@ -0,0 +1 @@
+Makes sure listing works
diff --git a/modules/remotebackend/regression-tests/list-all-records/expected_result b/modules/remotebackend/regression-tests/list-all-records/expected_result
new file mode 100644 (file)
index 0000000..f9d0649
--- /dev/null
@@ -0,0 +1,14 @@
+example.com.           120     IN      NS      ns1.example.com.
+example.com.           120     IN      NS      ns2.example.com.
+example.com.           120     IN      SOA     ns1.example.com. hostmaster.example.com. 2000010101 28800 7200 1209600 120
+example.com.           120     IN      SOA     ns1.example.com. hostmaster.example.com. 2000010101 28800 7200 1209600 120
+ns1.example.com.       120     IN      A       192.168.2.2
+ns2.example.com.       120     IN      A       192.168.2.3
+outpost.example.com.   120     IN      A       192.168.2.1
+outpost.example.com.   120     IN      AAAA    fe80::1
+up.example.com.                120     IN      DS      38674 8 1 50EA84825288D03BF9DDDA0B0B5F8964C6FBAFA8
+up.example.com.                120     IN      DS      38674 8 2 BF31EF7AEA46F2ADCA7A61FBB0629FB5C24116DF0F22EC0115DBC7EB DDDEE04E
+up.example.com.                120     IN      DS      38674 8 3 6ED18DCEABA6D2547F2FC82BA3801FDC919DB51B0E44BAA261B887C8 24DD9A2D
+up.example.com.                120     IN      NS      ns1.example.com.
+up.example.com.                120     IN      NS      ns2.example.com.
+www.example.com.       120     IN      A       192.168.2.255
diff --git a/modules/remotebackend/regression-tests/long-txt-resolution/command b/modules/remotebackend/regression-tests/long-txt-resolution/command
new file mode 100755 (executable)
index 0000000..3fdd4be
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+cleandig jump.up.example.com TXT
+
diff --git a/modules/remotebackend/regression-tests/long-txt-resolution/description b/modules/remotebackend/regression-tests/long-txt-resolution/description
new file mode 100644 (file)
index 0000000..bd43c63
--- /dev/null
@@ -0,0 +1 @@
+Check that long TXT comes out clean
diff --git a/modules/remotebackend/regression-tests/long-txt-resolution/expected_result b/modules/remotebackend/regression-tests/long-txt-resolution/expected_result
new file mode 100644 (file)
index 0000000..7ae60e6
--- /dev/null
@@ -0,0 +1,3 @@
+0      jump.up.example.com.    IN      TXT     120     "a very very long indeed text string that should pass out clean and proper thru the entire chain of powerdns processing"
+Rcode: 0, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='jump.up.example.com.', qtype=TXT
diff --git a/modules/remotebackend/regression-tests/long-txt-resolution/tmp.rb b/modules/remotebackend/regression-tests/long-txt-resolution/tmp.rb
new file mode 100644 (file)
index 0000000..3cbe477
--- /dev/null
@@ -0,0 +1,46 @@
+qname = "node-b.dyn.example.com"
+
+def to32(number)
+   number.to_s(32).tr "0123456789abcdefghijklmnopqrstuv", "ybndrfg8ejkmcpqxot1uwisza345h769"
+end
+
+def from32(str)
+   str.tr("ybndrfg8ejkmcpqxot1uwisza345h769", "0123456789abcdefghijklmnopqrstuv").to_i(32)
+end
+
+def rr(qname, qtype, content, ttl, priority = 0, auth = 1)
+   {:qname => qname, :qtype => qtype, :content => content, :ttl => ttl, :priority => priority, :auth => auth}
+end
+
+def send_result(*params)
+
+end
+
+def main(qname,qtype)
+   if qname[/\.?dyn.example.com$/]
+    if qname == "dyn.example.com"
+      ret = []
+      if (qtype != "SOA")
+         ret << rr(qname, "NS", "ns1.example.com",300)
+         ret << rr(qname, "NS", "ns2.example.com",300)
+         ret << rr(qname, "NS", "ns3.example.com",300)
+      end
+      ret << rr(qname,"SOA","ns1.example.com hostmaster.example.com #{Time.now.strftime("%Y%m%d%H")} 28800 7200 1209600 300",300)
+      return send_result ret
+    elsif qtype == "ANY" or qtype == "AAAA"
+      name = qname.match(/^node-(.*)\.dyn.example.com$/)[1]
+      if name.empty?
+        return send_result false
+      end
+#      if name.size < 16
+#        pad = 15-name.size
+#        (1..pad).each do |i| name = "y#{name}" end
+#      end
+      puts from32(name)
+      return send_result [rr(qname, "AAAA", "", 300)]
+    end
+   end
+   send_result false
+end
+
+main qname,"AAAA"
diff --git a/modules/remotebackend/regression-tests/ns-at-delegation/command b/modules/remotebackend/regression-tests/ns-at-delegation/command
new file mode 100755 (executable)
index 0000000..f8868dd
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+cleandig up.example.com NS
diff --git a/modules/remotebackend/regression-tests/ns-at-delegation/description b/modules/remotebackend/regression-tests/ns-at-delegation/description
new file mode 100644 (file)
index 0000000..d7492c8
--- /dev/null
@@ -0,0 +1 @@
+Verify that asking for NS at a delegation point returns a referral.
diff --git a/modules/remotebackend/regression-tests/ns-at-delegation/expected_result b/modules/remotebackend/regression-tests/ns-at-delegation/expected_result
new file mode 100644 (file)
index 0000000..11c99e7
--- /dev/null
@@ -0,0 +1,6 @@
+0      up.example.com. IN      NS      120     ns1.example.com.
+0      up.example.com. IN      NS      120     ns2.example.com.
+2      ns1.example.com.        IN      A       120     192.168.2.2
+2      ns2.example.com.        IN      A       120     192.168.2.3
+Rcode: 0, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='up.example.com.', qtype=NS
diff --git a/modules/remotebackend/regression-tests/nsec-middle/command b/modules/remotebackend/regression-tests/nsec-middle/command
new file mode 100755 (executable)
index 0000000..9745b8b
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+cleandig outerpost.example.com A dnssec
+
diff --git a/modules/remotebackend/regression-tests/nsec-middle/description b/modules/remotebackend/regression-tests/nsec-middle/description
new file mode 100644 (file)
index 0000000..f129195
--- /dev/null
@@ -0,0 +1,2 @@
+This test verifies that an NXDOMAIN in the middle of a zone
+generates a correct NSEC(3).
diff --git a/modules/remotebackend/regression-tests/nsec-middle/expected_result b/modules/remotebackend/regression-tests/nsec-middle/expected_result
new file mode 100644 (file)
index 0000000..86441a9
--- /dev/null
@@ -0,0 +1,9 @@
+1      example.com.    IN      NSEC    120     ns1.example.com. NS SOA RRSIG NSEC DNSKEY
+1      example.com.    IN      RRSIG   120     NSEC 8 2 120 [expiry] [inception] [keytag] example.com. ...
+1      example.com.    IN      RRSIG   120     SOA 8 2 120 [expiry] [inception] [keytag] example.com. ...
+1      example.com.    IN      SOA     120     ns1.example.com. hostmaster.example.com. 2000010101 28800 7200 1209600 120
+1      ns2.example.com.        IN      NSEC    120     outpost.example.com. A RRSIG NSEC
+1      ns2.example.com.        IN      RRSIG   120     NSEC 8 3 120 [expiry] [inception] [keytag] example.com. ...
+2      .       IN      OPT     32768   
+Rcode: 3, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='outerpost.example.com.', qtype=A
diff --git a/modules/remotebackend/regression-tests/nsec-middle/expected_result.narrow b/modules/remotebackend/regression-tests/nsec-middle/expected_result.narrow
new file mode 100644 (file)
index 0000000..65a5f89
--- /dev/null
@@ -0,0 +1,7 @@
+1      example.com.    IN      NSEC    120     outpost.example.com. NS SOA RRSIG NSEC DNSKEY
+1      example.com.    IN      RRSIG   120     NSEC 8 2 120 [expiry] [inception] [keytag] example.com. ...
+1      example.com.    IN      RRSIG   120     SOA 8 2 120 [expiry] [inception] [keytag] example.com. ...
+1      example.com.    IN      SOA     120     ns1.example.com. hostmaster.example.com. 2000010101 28800 7200 1209600 120
+2      .       IN      OPT     32768   
+Rcode: 3, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='outerpost.example.com.', qtype=A
diff --git a/modules/remotebackend/regression-tests/nsec-middle/expected_result.nsec3 b/modules/remotebackend/regression-tests/nsec-middle/expected_result.nsec3
new file mode 100644 (file)
index 0000000..65a5f89
--- /dev/null
@@ -0,0 +1,7 @@
+1      example.com.    IN      NSEC    120     outpost.example.com. NS SOA RRSIG NSEC DNSKEY
+1      example.com.    IN      RRSIG   120     NSEC 8 2 120 [expiry] [inception] [keytag] example.com. ...
+1      example.com.    IN      RRSIG   120     SOA 8 2 120 [expiry] [inception] [keytag] example.com. ...
+1      example.com.    IN      SOA     120     ns1.example.com. hostmaster.example.com. 2000010101 28800 7200 1209600 120
+2      .       IN      OPT     32768   
+Rcode: 3, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='outerpost.example.com.', qtype=A
diff --git a/modules/remotebackend/regression-tests/nsec-middle/skip.nodnssec b/modules/remotebackend/regression-tests/nsec-middle/skip.nodnssec
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/modules/remotebackend/regression-tests/nsec-sibling-test/command b/modules/remotebackend/regression-tests/nsec-sibling-test/command
new file mode 100755 (executable)
index 0000000..7cb2d94
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+cleandig jump.up.example.com A dnssec
diff --git a/modules/remotebackend/regression-tests/nsec-sibling-test/description b/modules/remotebackend/regression-tests/nsec-sibling-test/description
new file mode 100644 (file)
index 0000000..3da7d7b
--- /dev/null
@@ -0,0 +1 @@
+Tests that DS delegation comes out right
diff --git a/modules/remotebackend/regression-tests/nsec-sibling-test/expected_result b/modules/remotebackend/regression-tests/nsec-sibling-test/expected_result
new file mode 100644 (file)
index 0000000..018dacf
--- /dev/null
@@ -0,0 +1,6 @@
+0      jump.up.example.com.    IN      A       120     192.168.3.1
+0      jump.up.example.com.    IN      RRSIG   120     A 8 4 120 [expiry] [inception] [keytag] up.example.com. ...
+0      jump.up.example.com.    IN      RRSIG   120     A 8 4 120 [expiry] [inception] [keytag] up.example.com. ...
+2      .       IN      OPT     32768   
+Rcode: 0, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='jump.up.example.com.', qtype=A
diff --git a/modules/remotebackend/regression-tests/nsec-sibling-test/expected_result.narrow b/modules/remotebackend/regression-tests/nsec-sibling-test/expected_result.narrow
new file mode 100644 (file)
index 0000000..018dacf
--- /dev/null
@@ -0,0 +1,6 @@
+0      jump.up.example.com.    IN      A       120     192.168.3.1
+0      jump.up.example.com.    IN      RRSIG   120     A 8 4 120 [expiry] [inception] [keytag] up.example.com. ...
+0      jump.up.example.com.    IN      RRSIG   120     A 8 4 120 [expiry] [inception] [keytag] up.example.com. ...
+2      .       IN      OPT     32768   
+Rcode: 0, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='jump.up.example.com.', qtype=A
diff --git a/modules/remotebackend/regression-tests/nsec-sibling-test/expected_result.nsec3 b/modules/remotebackend/regression-tests/nsec-sibling-test/expected_result.nsec3
new file mode 100644 (file)
index 0000000..018dacf
--- /dev/null
@@ -0,0 +1,6 @@
+0      jump.up.example.com.    IN      A       120     192.168.3.1
+0      jump.up.example.com.    IN      RRSIG   120     A 8 4 120 [expiry] [inception] [keytag] up.example.com. ...
+0      jump.up.example.com.    IN      RRSIG   120     A 8 4 120 [expiry] [inception] [keytag] up.example.com. ...
+2      .       IN      OPT     32768   
+Rcode: 0, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='jump.up.example.com.', qtype=A
diff --git a/modules/remotebackend/regression-tests/nsec-sibling-test/skip.nodnssec b/modules/remotebackend/regression-tests/nsec-sibling-test/skip.nodnssec
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/modules/remotebackend/regression-tests/nsec-wraparound-begin/command b/modules/remotebackend/regression-tests/nsec-wraparound-begin/command
new file mode 100755 (executable)
index 0000000..c2e9055
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+cleandig a.example.com A dnssec
+
diff --git a/modules/remotebackend/regression-tests/nsec-wraparound-begin/description b/modules/remotebackend/regression-tests/nsec-wraparound-begin/description
new file mode 100644 (file)
index 0000000..55df335
--- /dev/null
@@ -0,0 +1,2 @@
+This test verifies that NXDOMAINS beyond the last record of a zone
+generate a correct wraparound NSEC.
diff --git a/modules/remotebackend/regression-tests/nsec-wraparound-begin/expected_result b/modules/remotebackend/regression-tests/nsec-wraparound-begin/expected_result
new file mode 100644 (file)
index 0000000..89c9aa9
--- /dev/null
@@ -0,0 +1,7 @@
+1      example.com.    IN      NSEC    120     ns1.example.com. NS SOA RRSIG NSEC DNSKEY
+1      example.com.    IN      RRSIG   120     NSEC 8 2 120 [expiry] [inception] [keytag] example.com. ...
+1      example.com.    IN      RRSIG   120     SOA 8 2 120 [expiry] [inception] [keytag] example.com. ...
+1      example.com.    IN      SOA     120     ns1.example.com. hostmaster.example.com. 2000010101 28800 7200 1209600 120
+2      .       IN      OPT     32768   
+Rcode: 3, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='a.example.com.', qtype=A
diff --git a/modules/remotebackend/regression-tests/nsec-wraparound-begin/expected_result.nsec3 b/modules/remotebackend/regression-tests/nsec-wraparound-begin/expected_result.nsec3
new file mode 100644 (file)
index 0000000..a20b545
--- /dev/null
@@ -0,0 +1,11 @@
+1      9f8hti7cc7oqnqjv84klnp89glqrss3r.example.com.   IN      NSEC3   86400   1 1 1 abcd 9FDAOFPLLN0FQFU9DP274GOU59QFHSLD A RRSIG
+1      9f8hti7cc7oqnqjv84klnp89glqrss3r.example.com.   IN      RRSIG   86400   NSEC3 8 3 86400 [expiry] [inception] [keytag] example.com. ...
+1      example.com.    IN      RRSIG   86400   SOA 8 2 100000 [expiry] [inception] [keytag] example.com. ...
+1      example.com.    IN      SOA     86400   ns1.example.com. ahu.example.com. 2000081501 28800 7200 604800 86400
+1      gnk5kv3h2h1h8ge405j6093608ukp3i5.example.com.   IN      NSEC3   86400   1 1 1 abcd GNO4LESKG6U7HKEJ9UL71SF1HD7F1P96 A RRSIG
+1      gnk5kv3h2h1h8ge405j6093608ukp3i5.example.com.   IN      RRSIG   86400   NSEC3 8 3 86400 [expiry] [inception] [keytag] example.com. ...
+1      vtnq6ocn2vkuiv3nju14oqtaen2mt5sk.example.com.   IN      NSEC3   86400   1 1 1 abcd VTP9NUQBEH436S7J0K8TI2A32MMKCUUL NS SOA MX RRSIG DNSKEY NSEC3PARAM
+1      vtnq6ocn2vkuiv3nju14oqtaen2mt5sk.example.com.   IN      RRSIG   86400   NSEC3 8 3 86400 [expiry] [inception] [keytag] example.com. ...
+2      .       IN      OPT     32768   
+Rcode: 3, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='zzz.example.com.', qtype=A
diff --git a/modules/remotebackend/regression-tests/nsec-wraparound-begin/skip.nodnssec b/modules/remotebackend/regression-tests/nsec-wraparound-begin/skip.nodnssec
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/modules/remotebackend/regression-tests/nsec-wraparound-end/command b/modules/remotebackend/regression-tests/nsec-wraparound-end/command
new file mode 100755 (executable)
index 0000000..7af813e
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+cleandig zzz.example.com A dnssec
+
diff --git a/modules/remotebackend/regression-tests/nsec-wraparound-end/description b/modules/remotebackend/regression-tests/nsec-wraparound-end/description
new file mode 100644 (file)
index 0000000..55df335
--- /dev/null
@@ -0,0 +1,2 @@
+This test verifies that NXDOMAINS beyond the last record of a zone
+generate a correct wraparound NSEC.
diff --git a/modules/remotebackend/regression-tests/nsec-wraparound-end/expected_result b/modules/remotebackend/regression-tests/nsec-wraparound-end/expected_result
new file mode 100644 (file)
index 0000000..f0dd6f4
--- /dev/null
@@ -0,0 +1,9 @@
+1      example.com.    IN      NSEC    120     ns1.example.com. NS SOA RRSIG NSEC DNSKEY
+1      example.com.    IN      RRSIG   120     NSEC 8 2 120 [expiry] [inception] [keytag] example.com. ...
+1      example.com.    IN      RRSIG   120     SOA 8 2 120 [expiry] [inception] [keytag] example.com. ...
+1      example.com.    IN      SOA     120     ns1.example.com. hostmaster.example.com. 2000010101 28800 7200 1209600 120
+1      www.example.com.        IN      NSEC    120     example.com. A RRSIG NSEC
+1      www.example.com.        IN      RRSIG   120     NSEC 8 3 120 [expiry] [inception] [keytag] example.com. ...
+2      .       IN      OPT     32768   
+Rcode: 3, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='zzz.example.com.', qtype=A
diff --git a/modules/remotebackend/regression-tests/nsec-wraparound-end/expected_result.nsec3 b/modules/remotebackend/regression-tests/nsec-wraparound-end/expected_result.nsec3
new file mode 100644 (file)
index 0000000..a20b545
--- /dev/null
@@ -0,0 +1,11 @@
+1      9f8hti7cc7oqnqjv84klnp89glqrss3r.example.com.   IN      NSEC3   86400   1 1 1 abcd 9FDAOFPLLN0FQFU9DP274GOU59QFHSLD A RRSIG
+1      9f8hti7cc7oqnqjv84klnp89glqrss3r.example.com.   IN      RRSIG   86400   NSEC3 8 3 86400 [expiry] [inception] [keytag] example.com. ...
+1      example.com.    IN      RRSIG   86400   SOA 8 2 100000 [expiry] [inception] [keytag] example.com. ...
+1      example.com.    IN      SOA     86400   ns1.example.com. ahu.example.com. 2000081501 28800 7200 604800 86400
+1      gnk5kv3h2h1h8ge405j6093608ukp3i5.example.com.   IN      NSEC3   86400   1 1 1 abcd GNO4LESKG6U7HKEJ9UL71SF1HD7F1P96 A RRSIG
+1      gnk5kv3h2h1h8ge405j6093608ukp3i5.example.com.   IN      RRSIG   86400   NSEC3 8 3 86400 [expiry] [inception] [keytag] example.com. ...
+1      vtnq6ocn2vkuiv3nju14oqtaen2mt5sk.example.com.   IN      NSEC3   86400   1 1 1 abcd VTP9NUQBEH436S7J0K8TI2A32MMKCUUL NS SOA MX RRSIG DNSKEY NSEC3PARAM
+1      vtnq6ocn2vkuiv3nju14oqtaen2mt5sk.example.com.   IN      RRSIG   86400   NSEC3 8 3 86400 [expiry] [inception] [keytag] example.com. ...
+2      .       IN      OPT     32768   
+Rcode: 3, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='zzz.example.com.', qtype=A
diff --git a/modules/remotebackend/regression-tests/nsec-wraparound-end/skip.nodnssec b/modules/remotebackend/regression-tests/nsec-wraparound-end/skip.nodnssec
new file mode 100644 (file)
index 0000000..e69de29
index 0e4125f87e0ef16bf5e74ae13eea9dbc79fceb9e..a71c519b9e7532c25e0fb0b5d43f92afcae35a84 100755 (executable)
@@ -5,9 +5,12 @@ require '../modules/remotebackend/regression-tests/backend'
 
 h = Handler.new("../modules/remotebackend/regression-tests/remote.sqlite3")
 
+f = File.open "/tmp/tmp.txt","a"
+
 STDOUT.sync = true
 begin 
   STDIN.each_line do |line|
+    f.puts line
     # expect json
     input = {}
     line = line.strip
@@ -25,8 +28,9 @@ begin
          res, log = h.send(method)
       end
       puts ({:result => res, :log => log}).to_json
+      f.puts ({:result => res, :log => log}).to_json
     rescue JSON::ParserError
-      send_failure "Cannot parse input #{line}"
+      puts ({:result => false, :log => "Cannot parse input #{line}"}).to_json
       next
     end
   end
index ba64010f9052f91cacf0166add84a126d89a530c..dbc2e8a5e57c97efaacf0fb06ea10cc34e32f4a4 100644 (file)
@@ -20,12 +20,15 @@ CREATE TABLE records (
   content         VARCHAR(65535) DEFAULT NULL,
   ttl             INTEGER DEFAULT NULL,
   prio            INTEGER DEFAULT NULL,
-  change_date     INTEGER DEFAULT NULL
+  change_date     INTEGER DEFAULT NULL,
+  ordername       VARCHAR(255) DEFAULT NULL,
+  auth            BOOL DEFAULT 0
 );
               
 CREATE INDEX rec_name_index ON records(name);
 CREATE INDEX nametype_index ON records(name,type);
 CREATE INDEX domain_id ON records(domain_id);
+create index orderindex on records(ordername);
 
 create table supermasters (
   ip          VARCHAR(25) NOT NULL, 
@@ -33,10 +36,6 @@ create table supermasters (
   account     VARCHAR(40) DEFAULT NULL
 );
 
-alter table records add ordername      VARCHAR(255);
-alter table records add auth bool;
-create index orderindex on records(ordername);
-
 create table domainmetadata (
  id         INTEGER PRIMARY KEY,
  domain_id       INT NOT NULL,
@@ -64,11 +63,27 @@ create table tsigkeys (
 );
 
 create unique index namealgoindex on tsigkeys(name, algorithm);
-insert into domains (name,type) VALUES('delegated.dnssec-parent.com','NATIVE');
-insert into domains (name,type) VALUES('dnssec-parent.com','NATIVE');
+
 insert into domains (name,type) VALUES('example.com','NATIVE');
-insert into domains (name,type) VALUES('minimal.com','NATIVE');
-insert into domains (name,type) VALUES('test.com','NATIVE');
-insert into domains (name,type) VALUES('wtest.com','NATIVE');
+insert into domains (name,type) VALUES('up.example.com','NATIVE');
+
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "example.com", "SOA", "120", "ns1.example.com hostmaster.example.com 2000010101 28800 7200 1209600 120", "", 1 FROM domains WHERE name = "example.com"; 
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "example.com", "NS", "120", "ns1.example.com", "", 1 FROM domains WHERE name = "example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "example.com", "NS", "120", "ns2.example.com", "", 1 FROM domains WHERE name = "example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "outpost.example.com", "A", "120", "192.168.2.1", "outpost", 1 FROM domains WHERE name = "example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "outpost.example.com", "AAAA", "120", "fe80::1", "outpost", 1 FROM domains WHERE name = "example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "www.example.com", "A", "120", "192.168.2.255", "www", 1 FROM domains WHERE name = "example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "up.example.com", "NS", "120", "ns1.example.com", "up", 0 FROM domains WHERE name = "example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "up.example.com", "NS", "120", "ns2.example.com", "up", 0 FROM domains WHERE name = "example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "ns1.example.com", "A", "120", "192.168.2.2", "ns1", 1 FROM domains WHERE name = "example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "ns2.example.com", "A", "120", "192.168.2.3", "ns2", 1 FROM domains WHERE name = "example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "up.example.com", "DS", "120", "38674 8 1 50ea84825288d03bf9ddda0b0b5f8964c6fbafa8", "up", 1 FROM domains WHERE name = "example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "up.example.com", "DS", "120", "38674 8 2 bf31ef7aea46f2adca7a61fbb0629fb5c24116df0f22ec0115dbc7ebdddee04e", "up", 1 FROM domains WHERE name = "example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "up.example.com", "DS", "120", "38674 8 3 6ed18dceaba6d2547f2fc82ba3801fdc919db51b0e44baa261b887c824dd9a2d", "up", 1 FROM domains WHERE name = "example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "up.example.com", "SOA", "120", "ns1.example.com hostmaster.example.com 2000010101 28800 7200 1209600 120", "", 1 FROM domains WHERE name = "up.example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "up.example.com", "NS", "120", "ns1.example.com", "", 1 FROM domains WHERE name = "up.example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "up.example.com", "NS", "120", "ns2.example.com", "", 1 FROM domains WHERE name = "up.example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "jump.up.example.com", "A", "120", "192.168.3.1", "jump", 1 FROM domains WHERE name = "up.example.com";
+insert into records (domain_id, name, type, ttl, content, ordername, auth) select id as domain_id, "jump.up.example.com", "TXT", "120", "a very very long indeed text string that should pass out clean and proper thru the entire chain of powerdns processing", "jump", 1 FROM domains WHERE name = "up.example.com";
 
 commit;
diff --git a/modules/remotebackend/regression-tests/up.example.com.ksk b/modules/remotebackend/regression-tests/up.example.com.ksk
new file mode 100644 (file)
index 0000000..9198617
--- /dev/null
@@ -0,0 +1,11 @@
+Private-key-format: v1.2
+Algorithm: 8 (RSASHA256)
+Modulus: uJPhQJzTPtwYCo/e9p+bIVB+JqSm79/3dcAdbrl5hMC4GFpdsqNbrhgzxrnic5Te0Kgt5ewWm9uXirq9eYFHmOmdwYKvbEjeEpBo2/HhDCRtRpuTHYsfqsJqbNAR5j0cMmjYq9UicZmrBR0rg8nqfZIMuTSAhAyTKd96ntA4Q1MS/XKd6tzeaeRjBAm263toW22C+c7A233NH3Q+DQIBul0vO9gKMRcdDGTmrjJleHzYRWGETZx9/OJwhroV4XH3z3gs0pBIEbGM4vKzrN3ER9lfQ/hn9ZSo6ksjawOY4NleVO4PofM8PlF0Hjg4Qzjqow2IgyL0Y3kVbSWpx7caNw==
+PublicExponent: AQAB
+PrivateExponent: COSdg1ULAiOG+2gX857La3BK/UzZlJ0gRlaA4VQJlgSjDULtWMbXvl+ai9MEJVJHs5rAYcX3B0z61DHphyOPcfKiwy9EvHbjHD0Q9rS36+alZs2AHRN8hxtIfWc/aLrXbPMlEI8uuNwQ8I7wCP1/Hf9RCNHBKQH7sfzIFhBgmMqG63bVhaFI3Dae3R8mbRPurNCQqqpQRnY6QCo+MT4oCcPtUhknNdrMfiXk1OIlKXQy5fcF1CcKM9SseL2OQ6BSR5zmzvuPtr214F0Nsx3jl9zw9Dq29fDEQRuxmITJNeXeBkTc0S87CVIc9wX4Xke9S4t0cYEcIFaFLAf5nDk5gQ==
+Prime1: 4Ff95nOa40oewS0KgKvbPTd9ZT7bqXBqvUNYV4t+oAtsA01qikrg13FlEDOgGn65LpWPia3WAOj3x+RNKqSs2lDn1DcRiY5QIVUtvGYicJfoNW9XAZC8qb6shhzxdQto8s0g8Q2M+i6vFNG+buAY/1h0FopNRIvMSC+rpFDl06c=
+Prime2: 0p9pWeanOBmnB00B6GYXNJ04xK0FysGnRdLLSJ1wd++9SxggVy7i3fLBVMtW6RIKho1alu/vnPNRkOk3ns1TliNfgVk2E+BF/9lJoXQaD7PKT62tRSH+7dSluW/MmakFNrlQeAylFsFSFepdbXYODWaOzyl7qNmZziLKksbRlvE=
+Exponent1: Uo9POt3UZEzEoKaotM2J8y9WkEnfoK1kOp5sBlupj9BkQZrd2GLR97cdUCcPhnCYSZJ0rmAw30jc1s0nsMfFbNpVVn2lkI+04W9tU2XqyrC8nd2JkWPoajdnWjuQiFhYmPHwa4VnGjLP78N4Z2lFCcNNhXYEFXO1C+OvMNssmQU=
+Exponent2: YG+69f3E/MvKDW61++maoG2IS40JRN/MLg0pJLNphpDPdC20yRZfq831tVRxE8A974OTQd7UMGG8LASMgfpzViAWH4xwVUNv6YhczT7ym9PvQvI7jpbVOaIOy0wkOwsHpxnMfVsUz8luQziO1IqkPoCBzNqqkxIm+Ro29GNyHZE=
+Coefficient: CEAJV5fxzzRBxE5Sjwk1cCycIRc4knBywzI0+SKiwGjnieCuJY3VDU0c9kkXfJPL6CydhQg7w4d/uOzKv4UY74Pt3a7JgfhSmRpl9pEGS3vytcc5rRl/VYN9a+S6iUU2YbpWziQZt6tujA+WuvXmr5RsgvqnFYAwYYGav1cogMc=
+
diff --git a/modules/remotebackend/regression-tests/up.example.com.zsk.1 b/modules/remotebackend/regression-tests/up.example.com.zsk.1
new file mode 100644 (file)
index 0000000..bb32fb5
--- /dev/null
@@ -0,0 +1,11 @@
+Private-key-format: v1.2
+Algorithm: 8 (RSASHA256)
+Modulus: 5rFrlB6aOKdmqATnpW42XOwbvmRFD2Bj7hprkZ5sx1UX9ZqRsml0ZUuPvzpXZlxDdOYbrJVR7OJXy/KTGSEaKtdBIE1sGqTqSmGuAjf1eKCDY3AQoLau/kVo+3f2TWhnKalm7PKWaHxJFgw6/fpMHipQPlEvpiqEnk0z1ioWKhk=
+PublicExponent: AQAB
+PrivateExponent: Agt7ZDgjjqeAi9zj7xiLlPtxy9hTMA2fF86g+qI1yCGLYWhcl2vYYIfQ2crVrf5Y3w8lb9GbWjcaZ0rP6NEyjGovtM+RjykBeSxlu4zaH2vuW+6MH8Ed6kpLMXAqewFf7mxodsom3RllXAA2ZLspZYdvO7QDageN7e6NWy1+FUE=
+Prime1: 57E4mG4RAqoyetlXPZaKhb9X/GASccIXv0zfH7I/KUpaySSUfzcxojIOkoAFb2Ur8YDemE3f6coXraVx+qXbYQ==
+Prime2: /uVcsoQDurkOJ0kH/4vLvooU98J9ozGKg0CyBMrUQBhhSkr/o4W8obNoLHlMGeJYWeSAs5QonMamlLS9V+dBuQ==
+Exponent1: G4TJHBG2o4JjjIPUANSoj0oywR8IEcrj1yziM3mQVu8l6U4W9SUxF/qqEGx0OM7jcUPFLIHTXolKVq2X5BVfAQ==
+Exponent2: m9uRX9KbGSyYe+sLCfXoAj0abxisjAH56SHA+G8xc3O04aGUSN+4pMM3uqH8p4MgdO7kx2mbn6lUKG+Pq1VLeQ==
+Coefficient: S1bcDTTRVPoGEv9Zun57TL654I+XO9HHCneacZYAyJC5jI1GDbbVQmfXknuuvoh9Z4YsFRoh0zANy9cHjusk2Q==
+
diff --git a/modules/remotebackend/regression-tests/up.example.com.zsk.2 b/modules/remotebackend/regression-tests/up.example.com.zsk.2
new file mode 100644 (file)
index 0000000..e3eca70
--- /dev/null
@@ -0,0 +1,11 @@
+Private-key-format: v1.2
+Algorithm: 8 (RSASHA256)
+Modulus: wJQvmbajlCnSj5XsqgxC7kWpslPSMFjkt1Rn2zuriyup/WeQAGxcPwCVVCq0pGrEqAP0hRnxpe8hhWLVJSpRiaaSqISBbZ+ebCqcTXo7C3d10XyKxBE5qxBePjJz3CvK0ellmbocC+QkeZSxBSRXjMAlFwsTroanoFhOtvjizS0=
+PublicExponent: AQAB
+PrivateExponent: JIGS2nFAZhxdgYGauQuU/oUvK5JvNGINjWFPRMR1eu7ejR5+Mk5YWEscg7WKw+ZHfFAvoLGv2NRRhu8a165DgV8fd5m38P20PpxqqzP2z8K6YANv2CkxsvvIBSwOUmkB/HqL6/Nhy4xTlKCcQxpm1gq5+XM1hXFmrEtzLgMqBVE=
+Prime1: /mXttF4hg/BDGHqaAAaZ5J8EFvoPRZIpFz6UU/5v8Kxx2se/FH6GCyEEdIebaNvB0gyZsC7lf4yIOCx9jx2EVQ==
+Prime2: wcqb8PZpsgxtSLYifXM0iZgs5k4LH8AwrrRjnGKkGPycxbbZb2qLddqwdP01YRCxkAnq4g9f/V33ozBm7Ms9eQ==
+Exponent1: zm1xPAmh0ojUOPnLGrhAigYKcIaKe96FH0p1W867kKStYmTxBTVBmag6EEC1d5nSpZn537++FAi5xDM90zKVXQ==
+Exponent2: XbEcJaqsvTU+3MmZ8TbyrpdRFeOjgy1DHCQAiMoz9hSjov9dLn2/gTJC37zPwub0QeRZmAPA79kvcclj6ZX1WQ==
+Coefficient: Z19qS5JSev5auSgG4UdNqqd4t5MlxdRaiigOPOzkipYxFCJGmscgU6aZ6OsjjpTCOaqd9voEgEVIW5CKHAtBUQ==
+
index 29d7a50b6758e73c2a95f13572795125938b6eaa..0cb9c28b61a3010b61737a57c920804b9b5adf35 100644 (file)
@@ -352,6 +352,10 @@ bool RemoteBackend::deactivateDomainKey(const string& name, unsigned int id) {
    return answer.asBool();
 }
 
+bool RemoteBackend::doesDNSSEC() {
+   return d_dnssec;
+}
+
 bool RemoteBackend::getTSIGKey(const std::string& name, std::string* algorithm, std::string* content) {
    Json::Value query,answer;
    query["method"] = "getTSIGKey";
@@ -369,6 +373,45 @@ bool RemoteBackend::getTSIGKey(const std::string& name, std::string* algorithm,
    return true;
 }
 
+bool RemoteBackend::getDomainInfo(const string &domain, DomainInfo &di) {
+   Json::Value query,answer;
+   std::string kind;
+   query["method"] = "getDomainInfo";
+   query["parameters"] = Json::Value();
+   query["parameters"]["name"] = domain;
+
+   if (connector->send(query) == false || connector->recv(answer) == false)
+     return false;
+
+   // make sure we got zone & kind
+   if (!answer.isMember("zone")) {
+      L<<Logger::Error<<kBackendId<<"Missing zone in getDomainInfo return value"<<endl;
+      throw new AhuException();
+   }
+   // parse return value. we need at least zone,serial,kind
+   di.id = answer.get("id", Json::Value(-1)).asInt();
+   di.zone = answer["zone"].asString();
+   if (answer.isMember("masters") && answer["masters"].isArray()) {
+     Json::Value value = answer["masters"];
+     for(Json::Value::iterator i = value.begin(); i != value.end(); i++) {
+        di.masters.push_back((*i).asString());
+     }
+   }
+   di.notified_serial = -1;
+   di.serial = answer.get("serial", Json::Value(0)).asInt();
+   di.last_check = 0;
+   kind = answer.get("kind", Json::Value("native")).asString();
+   if (kind == "master") {
+      di.kind = DomainInfo::Master;
+   } else if (kind == "slave") {
+      di.kind = DomainInfo::Slave;
+   } else {
+      di.kind = DomainInfo::Native;
+   }
+   di.backend = this;
+   return true;
+}
+
 DNSBackend *RemoteBackend::maker()
 {
    try {
index a2ed9b87f3a8b64c398e046dba772c5da89e3176..9836422d3630b3470e54f2213ebf8529717288b3 100644 (file)
@@ -30,6 +30,14 @@ class UnixsocketConnector: public Connector {
     virtual ~UnixsocketConnector();
     virtual int send_message(const Json::Value &input);
     virtual int recv_message(Json::Value &output);
+  private:
+    ssize_t read(std::string &data);
+    ssize_t write(const std::string &data);
+    void reconnect();
+    std::map<std::string,std::string> options;
+    int fd;
+    std::string path;
+    bool connected;
 };
 
 class HTTPConnector: public Connector {
@@ -88,6 +96,8 @@ class RemoteBackend : public DNSBackend
   virtual int addDomainKey(const string& name, const KeyData& key);
   virtual bool activateDomainKey(const string& name, unsigned int id);
   virtual bool deactivateDomainKey(const string& name, unsigned int id);
+  virtual bool getDomainInfo(const string&, DomainInfo&);
+  virtual bool doesDNSSEC();
 
   static DNSBackend *maker();
 
diff --git a/modules/remotebackend/test_backend.rb b/modules/remotebackend/test_backend.rb
deleted file mode 100755 (executable)
index 424c765..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-#!/usr/bin/ruby
-
-require 'json'
-
-prefix = "2001:06e8:0500:0000"
-
-# domain keys
-
-$domain_keys = [
- {
-  :id => 8,
-  :flags => 257,
-  :active => true,
-  :content => "Private-key-format: v1.2
-Algorithm: 8 (RSASHA256)
-Modulus: nFfl3jgFE+KET9PFPVmRCVmGZ+o+Stnqq7AZPAmhSYf96BPqK3t22vKHJhmVla+td94if2XUSggRUDz8YSeIybVNDTCmhF4xNyhAYAeh+HxJQU7CL8jQLs0b86Hd/Ua/s2pmSFSX4vzoAg+1lucLT3AiGYWjrvciFFpWnMyYftqcfTy3Vu/TMA9Kr7tr75CsJ2mzu1rywHsvOErCY8xH6dGd2LCY9ozuOwsgAlou+rOF5W71UPIuomM9QcIdVD2nq8+aHSsKeWk8gabLEsKU0SFFutO/R41lYXiUaFv+zY7r7NmP+d0Wmr0rgnzq2vlV0USQhlDPAsPSVstAuMrjgw==
-PublicExponent: AQAB
-PrivateExponent: kSdnrMbKe7dqfcpDG9WMgYp6BS88A5/a2F2ysv+Ds+Q9cAENXTpPn2yNDd4+sd3pgcmYsjsS6deTr9/YFRXw9bKBKLI80JFdZhKng5hMvYqnBGQmt/Dz4/RE87PVLNIC4/mrFE4Bn2vStnRTu3WY/wURXf3YkgI+IdXsfQTsBNloLiRoVV1QmB4kkHtRXsr02dg4kMhaXA13kT7lsrquCvGoxP++keVJ88AaQA8si30/E+CSgrbCHThUXeL6ErYz6myI5O2RJqodlcEQeXYi2cNkzQJnO3yjXcaSJy2u3tVNE2wXCXf1pwHXyTA4YT1qMbMIABq9TiVW8Q2Kg4sN
-Prime1: wrNo1cyyL/LpO+Das2EQzMbX0ctdy0OPvg3kWZqt2ZEwJjcVe1Vav5ZzSWKQWuT0IytUst7qdTE7lKpWWKDAbxJ4IMcMiMN2iQqE9V/dhIJluIrshupQzdhnXR46MfbazkDuvMTM1Fk4ZOgm3lrJoRvl6EOxl7e9veTwCjKqrA8=
-Prime2: zZDvTPq/Ea7aKa+CNmP7oOYxpvE1fpPV8MRjQ+IMi8VIDHpE72NoSSVoVuSL7fgl7qAFlbJMEtQGIlqUFQkC0sbI6ddb1/Ane+xhH4aPaljtIJQs0GlM/ECz30qZCreyHqaVzXlk9ZrN7HlnIOQ//DV3lCsS8EE1djeQxFThrU0=
-Exponent1: S9uW1uX/7sqXsKq0yvrgjshSQf0YOB/Em2nSNE8duQzmU51Wk0z4JHk7xbXPRHq73A//2gkcFDjwW8XaCoHnN99cSnkDGy38uvwMPYXySrR7aWFHMnGMtgbAjvk990WUjpOh8I5Et99jJ32D11JMCKdT9iCZyuDd3mSaWX7QHGU=
-Exponent2: hiaslG8a3B5gz01zS62KHCG9i3XkdDtkJeDz6uwNRfW0JDhy3krgVsPryLETxHPpxUV2/49A6BSoACledC/SQN1rZnedv1lBWzUS2PEGjN+FuHoamNPvYruS5wiWwZDJ1AjgwBwVz9Z7xnQf4i4yt5Po+q/1hwb3LbPrbMT8Fg0=
-Coefficient: zZDvTPq/Ea7aKa+CNmP7oOYxpvE1fpPV8MRjQ+IMi8VIDHpE72NoSSVoVuSL7fgl7qAFlbJMEtQGIlqUFQkC0sbI6ddb1/Ane+xhH4aPaljtIJQs0GlM/ECz30qZCreyHqaVzXlk9ZrN7HlnIOQ//DV3lCsS8EE1djeQxFThrU0="
- },
- {
-   :id => 9,
-   :flags => 256,
-   :active => true,
-   :content => "Private-key-format: v1.2
-Algorithm: 8 (RSASHA256)
-Modulus: 0fcOKzIHcE5K3B3zwu0iAm4Z/cRBH9JX0mMhl9h58i0C8QEK3fK+425MEI/q4P7qGkwB9hJ9TefC5ny3b+F2iSIDTqcrMoRr6/lJO2YH7MyeuAv1T5HMsC7DoCkdaq0xuoOkOtKaVz5/FwSFmCIlCNeboFX3Fq4kCoWsa1m63AE=
-PublicExponent: AQAB
-PrivateExponent: BWc0q6LlcxvorEJvD/CXQ/W+YHvo6x84GFdpuWUeOj+zSC1tMKn7BJJFjdWOR0z4DEYxdLokFFmm99R0ygHE0ZWh7WS1OX5AzqoFczeC0BDLvoAYu6XMvwlYp78ffqlI2qv4ohfew5TYzWCugxIufFsC55i2FoworGBLSFUloaM=
-Prime1: +aIMyvDUAzL/JZDHsPLnawLhy7sfZB4BbtARAYxZ6HSE9MAnFKbQhXQ9yRdGLSZEhe8g5b9tXBvxT8TPIGhwcw==
-Prime2: 11H/gYNtYkloQuRcL2xd3ElxosgncgFvXKY0y4sGyJuEhHJfttaxXCmNfVN9fg5lX18kfxCv4s8rqI+M+rZouw==
-Exponent1: SmrNp34NpfqA52D2tsBizproVwSsgfsT8EXkm/KMJuj9bb0OqXBlPzN868Kdb/41dTvpMbRUVJ4b3OzN1lpsEw==
-Exponent2: zPRiTzd48SuKsNGJ5iIynbLTFe2LjntLM1eJvY2SYXWXCDOOZA2sOVvcMEU+mLS/Ta7UoJaTtUMZ/ZLW0Pa8bQ==
-Coefficient: 11H/gYNtYkloQuRcL2xd3ElxosgncgFvXKY0y4sGyJuEhHJfttaxXCmNfVN9fg5lX18kfxCv4s8rqI+M+rZouw=="
- },
- {
-   :id => 10,
-   :flags => 256,
-   :active => false,
-   :content => "Private-key-format: v1.2
-Algorithm: 8 (RSASHA256)
-Modulus: rzJLZNmV+xQLkYWT3PytSYDeE8SovXi9+WCp9MVkWcSj1BgrBbugregqsSQLvz+rGsgc2nK3kqygDhypRMExmd2TRHeIrtcLHZ3nq+mmL/GfE0K6KWS2FJx06ol7v9xG8esLe+TUSAENo2xFR0BFmkiJN+R5hq06Rb0Y7OMSBs8=
-PublicExponent: AQAB
-PrivateExponent: FwH6jMABG6bCQ4DQrlDbS6/felEf/TdXcOHqRU7houMEG4fLqUZpZO1Rzfmh4U0x4fktxjJn5pyXrcLDKAMHHv+DjtPSC4B+49HFOZEHl/522VYw6NyJ+Firk41hbFxIStSFYh47qxKyAwbI/LuyTJE0Au8D+4dl8oFwfh0x+aE=
-Prime1: 0sDZukxVtL4zI9JPvEdBUAXLu4I98GS7xhxiLNeb+iF2+Vvw06igV7+CccMldz/r3gqr9y+NdAloErFvkieLRQ==
-Prime2: 1M822AT25uYwdKiiYuBPQlUIKVuP1paa8y4rh+uDuoHpm9E29hwHr2uLXESOO5YxB0oc8yauNOdH+HGTg8GhAw==
-Exponent1: IOq2Fv7tM/mxCxtCEOogLVt6YqMJAY76NQsh2lciqYKojnHpv2VLBemHejU8mM+HC3snOMhYk5MUijbkcjNy8Q==
-Exponent2: V0LUkUWP3GQ9MEjJtVOXDHMDkrnZxDsjNF4VOXmoHT0SBnOGXupleFfX4DC4RdSzK/MG5elRe53ulAA2Zctq8w==
-Coefficient: 1M822AT25uYwdKiiYuBPQlUIKVuP1paa8y4rh+uDuoHpm9E29hwHr2uLXESOO5YxB0oc8yauNOdH+HGTg8GhAw=="
- }
-]
-
-def to32(number) 
-   number.to_s(32).tr "0123456789abcdefghijklmnopqrstuv", "ybndrfg8ejkmcpqxot1uwisza345h769"
-end
-
-def from32(str)
-   str.tr("0123456789abcdefghijklmnopqrstuv", "ybndrfg8ejkmcpqxot1uwisza345h769").to_i(32)
-end
-
-def rr(qname, qtype, content, ttl, priority = 0, auth = 1)
-   {:qname => qname, :qtype => qtype, :content => content, :ttl => ttl, :priority => priority, :auth => auth}
-end
-
-def send_result(result, log = nil)
-  out = {:result => result}
-  if log.class != Array
-    log = [log]
-  end
-  out[:log] = log unless log.nil?
-  print out.to_json
-  print "\n"
-end
-
-def send_failure(msg)
-  send_result false, [msg]
-end
-
-class Handler
-   attr :prefix, :plen, :suffix, :domain
-   
-   def initialize(prefix)
-     @prefix = prefix
-   end
-
-   def do_initialize(*args)
-     # precalculate some things
-     tmp = self.prefix.gsub(/[^0-9a-f]/,'')
-     @plen = tmp.size
-     @suffix = tmp.split(//).reverse.join('.')+".ip6.arpa"
-     @domain = "dyn.example.com"
-     send_result true, "Autorev v6 backend initialized"
-   end
-
-   def do_getbeforeandafternamesabsolute(args)
-     qname = args["qname"]
-     # assume prefix
-     name = qname.gsub(/ /,'')
-     nlen = 32-self.plen
-
-     name_a = nil
-     name_b = nil
-     unhashed = nil
-
-     if name == ''
-         name_a = sprintf("%0#{nlen}x",0).split(//).join(' ')
-     elsif name.size < nlen
-         name_a = sprintf("%0#{nlen}x",0).split(//).join(' ')
-     else 
-        unhashed = sprintf("%0#{nlen}x",name.to_i(16)).split(//).join(' ')
-        if (name.to_i(16) > 0)
-           name_b = sprintf("%0#{nlen}x",(name.to_i(16)-1)).split(//).join ' '
-        end
-        unless (name[/[^f]/].nil?)
-           name_a = sprintf("%0#{nlen}x",(name.to_i(16)+1)).split(//).join ' '
-        end
-     end
-     send_result ({:before => name_b, :after => name_a, :unhashed => unhashed})
-   end
-
-   def do_getbeforeandafternames(args)
-      self.do_getbeforeandafternamesabsolute(args)
-   end
-
-   def do_getdomainkeys(args)
-      if args["name"] == self.suffix
-         send_result $domain_keys
-      else
-         send_result false
-      end
-   end
-
-   def do_lookup(args)
-     qtype = args["qtype"]
-     qname = args["qname"]
-
-     if qname[/.ip6.arpa$/]
-      if qname == self.suffix
-        ret = []
-        if (qtype != "SOA")
-           ret << rr(qname, "NS", "ns1.example.com",300)
-           ret << rr(qname, "NS", "ns2.example.com",300)
-           ret << rr(qname, "NS", "ns3.example.com",300)      
-        end
-        ret << rr(qname,"SOA","ns1.example.com hostmaster.example.com #{Time.now.strftime("%Y%m%d%H")} 28800 7200 1209600 300",300)
-        return send_result ret
-      elsif qtype == "ANY" or qtype == "PTR"
-        # assume suffix
-        name = qname.gsub(self.suffix,"").split(".").reverse.join("")
-        if name.empty? or name.size != 32-plen
-          return send_result false
-        end
-       name = to32(name.to_i(16))
-        return send_result [rr(qname, "PTR", "node-#{name}.#{self.domain}", 300)]
-      end
-     end
-     send_result false
-   end
-   def do_getdomainmetadata(args) 
-      name = args["name"]
-      kind = args["kind"]
-      send_result false
-   end
-end
-
-h = Handler.new(prefix)
-
-STDOUT.sync = true
-begin 
-  STDIN.each_line do |line|
-    # expect json
-    input = {}
-    line = line.strip
-    next if line.empty?
-    begin
-      input = JSON.parse(line)
-      method = "do_#{input["method"].downcase}"
-      args = input["parameters"]
-
-      if h.respond_to?(method.to_sym) == false
-         res = false
-         send_result res, nil
-      elsif args.size > 0
-         h.send(method,args)
-      else
-         h.send(method)
-      end
-    rescue JSON::ParserError
-      send_failure "Cannot parse input #{line}"
-      next
-    end
-  end
-rescue SystemExit, Interrupt
-end
index a1216e0aebf7aaaf42d6852e6ff5a00c9ecb1a0f..8f7d14d2c4a330bdb6480498a0562aaa6f162348 100644 (file)
 #define UNIX_PATH_MAX 108
 #endif
 
-
-// Singleton class to maintain client connection
-// via single unix socket connection
-static int n_unix_socket_connection;
-static pthread_mutex_t unix_build_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t unix_mutex = PTHREAD_MUTEX_INITIALIZER;
-class UnixsocketConnection {
-  public:
-    UnixsocketConnection(const std::string &path)
-    {
-      this->path = path;
-      connected = false;
-    };
-
-    ~UnixsocketConnection() {
-      L<<Logger::Info<<"closing socket connection"<<endl;
-      close(fd);
-    };
-
-    ssize_t read(std::string &data) { 
-        ssize_t nread;
-        char buf[1500] = {0};
-        Lock scoped_lock(&unix_mutex); 
-
-        reconnect();
-        if (!connected) return -1;
-        nread = ::read(this->fd, buf, sizeof buf); 
-        // just try again later...
-        if (nread==-1 && errno == EAGAIN) return 0;
-
-        if (nread==-1) {
-           connected = false;
-           close(fd);
-           return -1;
-        }
-
-        data.append(buf, nread);
-        return nread;
-    };
-
-    ssize_t write(const std::string &data) { 
-        ssize_t nwrite, nbuf;
-        char buf[1500];
-        Lock scoped_lock(&unix_mutex); 
-
-        reconnect();
-        if (!connected) return -1;
-        nbuf = data.copy(buf, sizeof buf); // copy data and write
-        nwrite = ::write(fd, buf, nbuf);
-        if (nwrite == -1) {
-          connected = false;
-          close(fd);
-          return -1;
-        }
-        return nwrite;
-    };
-
-  private:
-    int fd;
-    bool connected;
-    std::string path;
-
-    void reconnect() {
-       struct sockaddr_un sock;
-       struct timeval tv;
-       fd_set rd;
-
-       if (connected) return; // no point reconnecting if connected...
-       connected = true;
-
-       L<<Logger::Info<<"Reconnecting to backend" << std::endl;
-       fd = socket(AF_UNIX, SOCK_STREAM, 0);
-       if (fd < 0) {
-          connected = false;
-          L<<Logger::Error<<"Cannot create socket: " << strerror(errno) << std::endl;;
-          return;
-       }
-       sock.sun_family = AF_UNIX;
-       memset(sock.sun_path, 0, UNIX_PATH_MAX);
-       path.copy(sock.sun_path, UNIX_PATH_MAX, 0);
-       fcntl(fd, F_SETFL, O_NONBLOCK, &fd);
-       
-       while(connect(fd, reinterpret_cast<struct sockaddr*>(&sock), sizeof sock)==-1 && (errno == EINPROGRESS)) {
-        tv.tv_sec = 0;
-         tv.tv_usec = 500;
-         FD_ZERO(&rd);
-         FD_SET(fd, &rd);
-         select(fd+1,&rd,NULL,NULL,&tv); // wait a moment
-       };
-       if (errno != EISCONN && errno != 0) {
-          L<<Logger::Error<<"Cannot connect to socket: " << strerror(errno) << std::endl;
-          close(fd);
-          connected = false;
-          return;
-       }
-    };
-};
-
-static UnixsocketConnection *unix_socket_connection;
-
 UnixsocketConnector::UnixsocketConnector(std::map<std::string,std::string> options) {
-     Lock scoped_lock(&unix_build_mutex);
-
-     if (unix_socket_connection == NULL) {
-       Json::Value init,res;
-       unix_socket_connection = new UnixsocketConnection(options.find("path")->second);
-       n_unix_socket_connection = 1;
-       init["method"] = "initialize";
-       init["parameters"] = Json::Value();
-       for(std::map<std::string,std::string>::iterator i = options.begin(); i != options.end(); i++)
-         init["parameters"][i->first] = i->second;
-       this->send(init);
-       if (this->recv(res) == false)
-          L<<Logger::Warning << "Failed to initialize backend" << std::endl;
-     } else {
-       n_unix_socket_connection++;
-     }
+   if (options.count("path") == 0) {
+     L<<Logger::Error<<"Cannot find 'path' option in connection string"<<endl;
+     throw new AhuException();
+   } 
+   this->path = options.find("path")->second;
+   this->options = options;
+   this->connected = false;
 }
 
 UnixsocketConnector::~UnixsocketConnector() {
-     Lock scoped_lock(&unix_build_mutex);
-     n_unix_socket_connection--;
-     if (n_unix_socket_connection == 0) {
-       delete unix_socket_connection;
-       unix_socket_connection = NULL;
-     }
+   if (this->connected) {
+      L<<Logger::Info<<"closing socket connection"<<endl;
+      close(fd);
+   }
 }
 
 int UnixsocketConnector::send_message(const Json::Value &input) {
@@ -143,12 +31,9 @@ int UnixsocketConnector::send_message(const Json::Value &input) {
         Json::FastWriter writer;
         int rv;
         data = writer.write(input);
-        //i make sure we got nothing waiting there.
-        std::string temp;
-        while(unix_socket_connection->read(temp)>0) { temp = ""; }
-        rv = unix_socket_connection->write(data);
+        rv = this->write(data);
         if (rv == -1)
-            throw AhuException("Failed to write to socket");
+          return -1;
         return rv;
 }
 
@@ -164,9 +49,11 @@ int UnixsocketConnector::recv_message(Json::Value &output) {
  
         while(time(NULL) - t0 < 2) { // 2 second timeout 
           std::string temp;
-          rv = unix_socket_connection->read(temp);
+          temp.clear();
+
+          rv = this->read(temp);
           if (rv == -1) 
-            throw AhuException("Failed to read from socket");
+            return -1;
 
           if (rv>0) {
             nread += rv;
@@ -179,3 +66,97 @@ int UnixsocketConnector::recv_message(Json::Value &output) {
 
         return -1;
 }
+
+ssize_t UnixsocketConnector::read(std::string &data) {
+    ssize_t nread;
+    char buf[1500] = {0};
+
+    reconnect();
+    if (!connected) return -1;
+    nread = ::read(this->fd, buf, sizeof buf);
+
+    // just try again later...
+    if (nread==-1 && errno == EAGAIN) return 0;
+
+    if (nread==-1) {
+       connected = false;
+       close(fd);
+       return -1;
+    }
+
+    data.append(buf, nread);
+    return nread;
+}
+
+ssize_t UnixsocketConnector::write(const std::string &data) {
+    ssize_t nwrite, nbuf;
+    size_t pos;
+    char buf[1500];
+
+    reconnect();
+    if (!connected) return -1;
+    pos = 0;
+    nwrite = 0;
+    while(pos < data.size()) {
+      nbuf = data.copy(buf, sizeof buf, pos); // copy data and write
+      nwrite = ::write(fd, buf, nbuf);
+      pos = pos + sizeof(buf);
+      if (nwrite == -1) {
+        connected = false;
+        close(fd);
+        return -1;
+      }
+    }
+    return nwrite;
+}
+
+void UnixsocketConnector::reconnect() {
+   struct sockaddr_un sock;
+   struct timeval tv;
+   fd_set rd;
+   Json::Value init,res;
+
+   if (connected) return; // no point reconnecting if connected...
+   connected = true;
+
+   L<<Logger::Info<<"Reconnecting to backend" << std::endl;
+   fd = socket(AF_UNIX, SOCK_STREAM, 0);
+   if (fd < 0) {
+      connected = false;
+      L<<Logger::Error<<"Cannot create socket: " << strerror(errno) << std::endl;;
+      return;
+   }
+   sock.sun_family = AF_UNIX;
+   memset(sock.sun_path, 0, UNIX_PATH_MAX);
+   path.copy(sock.sun_path, UNIX_PATH_MAX, 0);
+   fcntl(fd, F_SETFL, O_NONBLOCK, &fd);
+
+   while(connect(fd, reinterpret_cast<struct sockaddr*>(&sock), sizeof sock)==-1 && (errno == EINPROGRESS)) {
+     tv.tv_sec = 0;
+     tv.tv_usec = 500;
+     FD_ZERO(&rd);
+     FD_SET(fd, &rd);
+     select(fd+1,&rd,NULL,NULL,&tv); // wait a moment
+   }
+
+   if (errno != EISCONN && errno != 0) {
+      L<<Logger::Error<<"Cannot connect to socket: " << strerror(errno) << std::endl;
+      close(fd);
+      connected = false;
+      return;
+   }
+   // send initialize
+
+   init["method"] = "initialize";
+   init["parameters"] = Json::Value();
+   for(std::map<std::string,std::string>::iterator i = options.begin(); i != options.end(); i++)
+      init["parameters"][i->first] = i->second;
+
+   this->send_message(init);
+   if (this->recv_message(res) == false) {
+      L<<Logger::Warning << "Failed to initialize backend" << std::endl;
+      close(fd);
+      this->connected = false;
+   }
+}
+
index 8aa880d7926a5318a91825a533ec2744eeba0687..59048527ec419f364b014d729abc0991ac89d3a3 100755 (executable)
@@ -32,7 +32,7 @@ testsdir=.
 if [ "$port" = help ] || [ "$context" = help ]
 then
        set +x
-       cat << '__EOF__'
+       grep -v '^#' << '__EOF__'
 
 Usage: ./start-test-stop <port> [<context>] [wait]
 
@@ -45,6 +45,8 @@ opendbx-sqlite3
 tinydns
 remotebackend-pipe remotebackend-unix remotebackend-http 
 remotebackend-pipe-dnssec remotebackend-unix-dnssec remotebackend-http-dnssec
+#remotebackend-pipe-nsec3 remotebackend-unix-nsec3 remotebackend-http-nsec3
+#remotebackend-pipe-nsec3-narrow remotebackend-unix-nsec3-narrow remotebackend-http-nsec3-narrow
 
 add -presigned to any gmysql test (except narrow) to test 
 presigned operation
@@ -355,20 +357,26 @@ __EOF__
                remotebackend-*)
                        remotetype=$(echo $context | cut -d- -f 2)
                        remotesec=$(echo $context | cut -d- -f 3)
+                       narrow=$(echo $context | cut -d- -f 4)
+                        testsdir=../modules/remotebackend/regression-tests/
 
                        case $remotetype in
                        http)
                                connstr="http:url=http://localhost:62434/dns"
-                               ../modules/remotebackend/regression-tests/http-backend.rb &
+                               rm -f remotebackend-server.log
+                               rm -f remotebackend-access.log
+                               $testsdir/http-backend.rb &
                                echo $! > pdns-remotebackend.pid
+                               # make sure it runs before continuing
+                               sleep 2
                                ;;
                        unix)
                                connstr="unix:path=/tmp/remote.socket"
-                               socat unix-listen:/tmp/remote.socket exec:../modules/remotebackend/regression-tests/pipe-backend.rb &
+                               socat unix-listen:/tmp/remote.socket,fork exec:$testsdir/unix-backend.rb &
                                echo $! > pdns-remotebackend.pid
                                ;;
                        pipe)
-                               connstr="pipe:command=../modules/remotebackend/regression-tests/pipe-backend.rb"
+                               connstr="pipe:command=$testsdir/pipe-backend.rb"
                                ;;
                        *)
                                echo "Invalid usage"
@@ -376,24 +384,66 @@ __EOF__
                                ;;
                        esac
 
-                       if [ "$remotesec" = "dnssec" ]; then
-                               remote_add_param="--remote-dnssec=yes"
+                       skipreasons="nodnssec"
+
+                       if [ "$remotesec" = "nsec3" ]; then
+                               remotedosec="yes"
+                               if [ "$narrow" = "narrow" ]; then
+                                       extracontexts="dnssec nsec3 narrow"
+                                       skipreasons="narrow nsec3"
+                               else 
+                                       extracontexts="dnssec nsec3"
+                                       skipreasons="nsec3"
+                               fi
+                               remote_add_param="--remote-dnssec=yes"
+                        else 
+                               if [ "$remotesec" = "dnssec" ]; then
+                                       remotedosec="yes"
+                                       remote_add_param="--remote-dnssec=yes"
+                                       extracontexts="dnssec"
+                                       skipreasons="nonsec3 nonarrow"
+                               fi
                        fi
 
+                       # generate pdns.conf for pdnssec
+                       cat > pdns-remote.conf <<EOF
+launch=remote
+remote-connection-string=$connstr
+EOF
+
                        $RUNWRAPPER ../pdns/pdns_server --daemon=no --local-port=$port --socket-dir=./ \
                                --no-shuffle --launch=remote \
                                --query-logging --loglevel=9 --cache-ttl=0 --no-config \
                                --send-root-referral \
                                --remote-connection-string="$connstr" $remote_add_param &
                         
-                       if [ "$remotesec" = "dnssec" ]
-                       then
-                               extracontexts="dnssec"
-                       else
-                               skipreasons="nodnssec"
-                       fi
+                       echo "Setting up test database..."
+                       # setup test database
+                       rm -f $testsdir/remote.sqlite3
+                       sqlite3 $testsdir/remote.sqlite3 < $testsdir/test-schema.sql
+                       chmod 0666 $testsdir/remote.sqlite3
+                       if [ "$remotedosec" = "yes" ]; then
+                                echo "remote-dnssec=yes" >> pdns-remote.conf
+                                ../pdns/pdnssec --config-dir=. --config-name=remote import-zone-key example.com $testsdir/example.com.ksk ksk
+                                ../pdns/pdnssec --config-dir=. --config-name=remote import-zone-key example.com $testsdir/example.com.zsk.1 zsk
+                                ../pdns/pdnssec --config-dir=. --config-name=remote import-zone-key example.com $testsdir/example.com.zsk.2 zsk
+                                ../pdns/pdnssec --config-dir=. --config-name=remote activate-zone-key example.com 1
+                                ../pdns/pdnssec --config-dir=. --config-name=remote activate-zone-key example.com 2
+                                ../pdns/pdnssec --config-dir=. --config-name=remote deactivate-zone-key example.com 3
+
+                                ../pdns/pdnssec --config-dir=. --config-name=remote import-zone-key up.example.com $testsdir/up.example.com.ksk ksk
+                                ../pdns/pdnssec --config-dir=. --config-name=remote import-zone-key up.example.com $testsdir/up.example.com.zsk.1 zsk
+                                ../pdns/pdnssec --config-dir=. --config-name=remote import-zone-key up.example.com $testsdir/up.example.com.zsk.2 zsk
+                                ../pdns/pdnssec --config-dir=. --config-name=remote activate-zone-key example.com 4
+                                ../pdns/pdnssec --config-dir=. --config-name=remote activate-zone-key example.com 5
+                                ../pdns/pdnssec --config-dir=. --config-name=remote deactivate-zone-key example.com 6
+
+                               if [ "$remotesec" = "nsec3" ]; then
+                                       ../pdns/pdnssec --config-dir=. --config-name=remote set-nsec3 example.com
+                                        ../pdns/pdnssec --config-dir=. --config-name=remote set-nsec3 up.example.com
+                               fi
 
-                       testsdir=../modules/remotebackend/regression-tests/
+                       fi
 
                        ;;
                *)