]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Add correct handling of DNSSEC records in rfc2136
authorRuben d'Arco <cyclops@prof-x.net>
Thu, 7 Mar 2013 14:42:00 +0000 (15:42 +0100)
committermind04 <mind04@monshouwer.org>
Fri, 12 Jul 2013 15:26:18 +0000 (17:26 +0200)
Ignore NSEC or NSEC3 records, as they are never stored in the records table.
Allow adding/removing/updating of NSEC3PARAM's
Also updated start-test-stop to remove *_tests files before starting, as we might have one left from
a previous test.

pdns/nsecrecords.cc
pdns/packethandler.hh
pdns/rfc2136handler.cc
regression-tests/1dyndns-update-nsec3params/command [new file with mode: 0755]
regression-tests/1dyndns-update-nsec3params/description [new file with mode: 0644]
regression-tests/1dyndns-update-nsec3params/expected_result [new file with mode: 0755]
regression-tests/1dyndns-update-nsec3params/expected_result.nsec3 [new file with mode: 0755]
regression-tests/1dyndns-update-nsec3params/skip.narrow [new file with mode: 0644]
regression-tests/1dyndns-update-nsec3params/skip.nodnssec [new file with mode: 0644]
regression-tests/start-test-stop

index 15fccdc4f6f89340324b9db7af90e5a35d0b31a0..24911da6adbd2b1b0d87f489f787a94a6aa22ac0 100644 (file)
@@ -246,6 +246,7 @@ string NSEC3RecordContent::getZoneRepresentation() const
 void NSEC3PARAMRecordContent::report(void)
 {
   regist(1, 51, &make, &make, "NSEC3PARAM");
+  regist(254, 51, &make, &make, "NSEC3PARAM");
 }
 
 DNSRecordContent* NSEC3PARAMRecordContent::make(const string& content)
index 2ac2a19cda99d73ae9917d01f4b88bde3c4d21fd..80c3c944320db4feb1b1423c6516cbeb06e28b19 100755 (executable)
@@ -87,7 +87,7 @@ private:
   void emitNSEC3(const NSEC3PARAMRecordContent &ns3rc, const SOAData& sd, const std::string& unhashed, const std::string& begin, const std::string& end, const std::string& toNSEC3, DNSPacket *r, int mode);
   int processUpdate(DNSPacket *p);
   int forwardPacket(const string &msgPrefix, DNSPacket *p, DomainInfo *di);
-  uint16_t performUpdate(const string &msgPrefix, const DNSRecord *rr, DomainInfo *di, bool narrow, bool haveNSEC3, const NSEC3PARAMRecordContent *ns3pr, bool *updatedSerial);
+  uint16_t performUpdate(const string &msgPrefix, const DNSRecord *rr, DomainInfo *di, bool isPresigned, bool* narrow, bool* haveNSEC3, NSEC3PARAMRecordContent *ns3pr, bool *updatedSerial);
   int checkUpdatePrescan(const DNSRecord *rr);
   int checkUpdatePrerequisites(const DNSRecord *rr, DomainInfo *di);
   void increaseSerial(const string &msgPrefix, const DomainInfo *di, bool haveNSEC3, bool narrow, const NSEC3PARAMRecordContent *ns3pr);
index d024a704b71d7c9b90a956a199950b2a3e720f00..1ea49ca97a8011e14ba716d7fa391dbc44ee82aa 100755 (executable)
@@ -85,31 +85,67 @@ int PacketHandler::checkUpdatePrescan(const DNSRecord *rr) {
 
 
 // Implements section 3.4.2 of RFC2136
-uint16_t PacketHandler::performUpdate(const string &msgPrefix, const DNSRecord *rr, DomainInfo *di, bool narrow, bool haveNSEC3, const NSEC3PARAMRecordContent *ns3pr, bool *updatedSerial) {
+uint16_t PacketHandler::performUpdate(const string &msgPrefix, const DNSRecord *rr, DomainInfo *di, bool isPresigned, bool* narrow, bool* haveNSEC3, NSEC3PARAMRecordContent *ns3pr, bool *updatedSerial) {
+  string rrLabel = stripDot(rr->d_label);
+  rrLabel = toLower(rrLabel);
+  QType rrType = QType(rr->d_type);
+
+
+  if (rrType == QType::NSEC || rrType == QType::NSEC3) {
+    L<<Logger::Warning<<msgPrefix<<"Trying to add/update/delete "<<rrLabel<<"|"<<rrType.getName()<<". These are generated records, ignoring!"<<endl;
+    return 0;    
+  }
+
+  if (!isPresigned && (rrType == QType::RRSIG || rrType == QType::DNSKEY) ) {
+    L<<Logger::Warning<<msgPrefix<<"Trying to add/update/delete "<<rrLabel<<"|"<<rrType.getName()<<" in non-presigned zone, ignoring!"<<endl;
+    return 0;
+  }
+
+  if (rrType == QType::NSEC3PARAM && rrLabel != di->zone) {
+    L<<Logger::Warning<<msgPrefix<<"Trying to add/update/delete "<<rrLabel<<"|NSEC3PARAM, NSEC3PARAM must be at zone apex, ignoring!"<<endl;
+    return 0;
+  }
+
+  
   uint16_t changedRecords = 0;
   DNSResourceRecord rec;
   vector<DNSResourceRecord> rrset, recordsToDelete;
   set<string> delnonterm, insnonterm; // used to (at the end) fix ENT records.
 
-  string rrLabel = stripDot(rr->d_label);
-  rrLabel = toLower(rrLabel);
-  QType rrType = QType(rr->d_type);
 
   if (rr->d_class == QClass::IN) { // 3.4.2.2 QClass::IN means insert or update
     DLOG(L<<msgPrefix<<"Add/Update record (QClass == IN) "<<rrLabel<<"|"<<rrType.getName()<<endl);
 
+    if (rrType == QType::NSEC3PARAM) {
+      L<<Logger::Notice<<msgPrefix<<"Setting NSEC3PARAM for zone, resetting ordernames."<<endl;  
+      NSEC3PARAMRecordContent nsec3param(rr->d_content->getZoneRepresentation(), di->zone);
+      d_dk.setNSEC3PARAM(di->zone, nsec3param, (*narrow));
+      *haveNSEC3 = d_dk.getNSEC3PARAM(di->zone, ns3pr, narrow);
+      di->backend->list(di->zone, di->id);
+      vector<DNSResourceRecord> rrs;
+      while (di->backend->get(rec)) {
+        rrs.push_back(rec);
+      }
+      for (vector<DNSResourceRecord>::const_iterator i = rrs.begin(); i != rrs.end(); i++) {
+        if (*narrow) {
+          di->backend->nullifyDNSSECOrderNameAndUpdateAuth(di->id, i->qname, i->auth);
+        } else {
+          string hashed=toLower(toBase32Hex(hashQNameWithSalt(ns3pr->d_iterations, ns3pr->d_salt, i->qname)));
+          di->backend->updateDNSSECOrderAndAuthAbsolute(di->id, i->qname, hashed, i->auth);
+        }
+      }
+      return 1;
+    }
+
     bool foundRecord = false;
     di->backend->lookup(rrType, rrLabel);
     while (di->backend->get(rec)) {
-        rrset.push_back(rec);
-        foundRecord = true;
+      rrset.push_back(rec);
+      foundRecord = true;
     }
-
     
     if (foundRecord) {
-
-      // SOA updates require the serial to be updated.
-      if (rrType == QType::SOA) {
+      if (rrType == QType::SOA) { // SOA updates require the serial to be higher than the current
         SOAData sdOld, sdUpdate;
         DNSResourceRecord *oldRec = &rrset.front();
         fillSOAData(oldRec->content, sdOld);
@@ -154,9 +190,9 @@ uint16_t PacketHandler::performUpdate(const string &msgPrefix, const DNSRecord *
       // ReplaceRRSet dumps our ordername and auth flag, so we need to correct it.
       // We can take the auth flag from the first RR in the set, as the name is different, so should the auth be.
       bool auth = rrset.front().auth;
-      if(haveNSEC3) {
+      if(*haveNSEC3) {
         string hashed;
-        if(!narrow) 
+        if(! *narrow) 
           hashed=toLower(toBase32Hex(hashQNameWithSalt(ns3pr->d_iterations, ns3pr->d_salt, rrLabel)));
         
         di->backend->updateDNSSECOrderAndAuthAbsolute(di->id, rrLabel, hashed, auth);
@@ -210,10 +246,10 @@ uint16_t PacketHandler::performUpdate(const string &msgPrefix, const DNSRecord *
         } while(chopOff(shorter));
       }
 
-      if(haveNSEC3)
+      if(*haveNSEC3)
       {
         string hashed;
-        if(!narrow) 
+        if(! *narrow) 
           hashed=toLower(toBase32Hex(hashQNameWithSalt(ns3pr->d_iterations, ns3pr->d_salt, rrLabel)));
         
         di->backend->updateDNSSECOrderAndAuthAbsolute(di->id, rrLabel, hashed, auth);
@@ -246,9 +282,9 @@ uint16_t PacketHandler::performUpdate(const string &msgPrefix, const DNSRecord *
             qnames.push_back(rec.qname);
         }
         for(vector<string>::const_iterator qname=qnames.begin(); qname != qnames.end(); ++qname) {
-          if(haveNSEC3)  {
+          if(*haveNSEC3)  {
             string hashed;
-            if(!narrow) 
+            if(! *narrow) 
               hashed=toLower(toBase32Hex(hashQNameWithSalt(ns3pr->d_iterations, ns3pr->d_salt, *qname)));
         
             di->backend->updateDNSSECOrderAndAuthAbsolute(di->id, *qname, hashed, auth);
@@ -269,6 +305,33 @@ uint16_t PacketHandler::performUpdate(const string &msgPrefix, const DNSRecord *
   // the code that calls this performUpdate().
   if ((rr->d_class == QClass::ANY || rr->d_class == QClass::NONE) && rrType != QType::SOA) { // never delete a SOA.
     DLOG(L<<msgPrefix<<"Deleting records: "<<rrLabel<<"; QClasse:"<<rr->d_class<<"; rrType: "<<rrType.getName()<<endl);
+
+    if (rrType == QType::NSEC3PARAM) {
+      L<<Logger::Notice<<msgPrefix<<"Removing NSEC3PARAM from zone, resetting ordernames."<<endl;  
+      if (rr->d_class == QClass::ANY)
+        d_dk.unsetNSEC3PARAM(rrLabel);
+      else if (rr->d_class == QClass::NONE) {
+        NSEC3PARAMRecordContent nsec3rr(rr->d_content->getZoneRepresentation(), di->zone);
+       if (ns3pr->getZoneRepresentation() == nsec3rr.getZoneRepresentation())
+          d_dk.unsetNSEC3PARAM(rrLabel);
+        else
+          return 0;
+      } else 
+        return 0;
+
+      *haveNSEC3 = d_dk.getNSEC3PARAM(di->zone, ns3pr, narrow);
+      di->backend->list(di->zone, di->id);
+      vector<DNSResourceRecord> rrs;
+      while (di->backend->get(rec)) {
+        rrs.push_back(rec);
+      }
+      for (vector<DNSResourceRecord>::const_iterator i = rrs.begin(); i != rrs.end(); i++) {
+        di->backend->updateDNSSECOrderAndAuth(di->id, di->zone, i->qname, i->auth);
+      }
+      return 1;
+    }
+
+
     di->backend->lookup(rrType, rrLabel);
     while(di->backend->get(rec)) {
       if (rr->d_class == QClass::ANY) { // 3.4.2.3
@@ -299,9 +362,9 @@ uint16_t PacketHandler::performUpdate(const string &msgPrefix, const DNSRecord *
             changeAuth.push_back(rec.qname);
         }
         for (vector<string>::const_iterator changeRec=changeAuth.begin(); changeRec!=changeAuth.end(); ++changeRec) {
-          if(haveNSEC3)  {
+          if(*haveNSEC3)  {
             string hashed;
-            if(!narrow) 
+            if(! *narrow) 
               hashed=toLower(toBase32Hex(hashQNameWithSalt(ns3pr->d_iterations, ns3pr->d_salt, *changeRec)));
         
             di->backend->updateDNSSECOrderAndAuthAbsolute(di->id, *changeRec, hashed, true);
@@ -340,6 +403,7 @@ uint16_t PacketHandler::performUpdate(const string &msgPrefix, const DNSRecord *
           // a.b.d.e.test.com
           // if we delete a.b.c.d.e.test.com, we go up to d.e.test.com and then find a.b.d.e.test.com
           // At that point we can stop deleting ENT's because the tree is in tact again.
+          //TODO: I think we do not need listSubZone() here, as we're moving up the tree with the chopOff(); i consider the listSubZone query more expensive and a lookup would be better.
           di->backend->listSubZone(shorter, di->id);
           while (di->backend->get(rec)) {
             if (rec.qtype.getCode())
@@ -361,10 +425,10 @@ uint16_t PacketHandler::performUpdate(const string &msgPrefix, const DNSRecord *
     di->backend->updateEmptyNonTerminals(di->id, di->zone, insnonterm, delnonterm, false);
     for (set<string>::const_iterator i=insnonterm.begin(); i!=insnonterm.end(); i++) {
       string hashed;
-      if(haveNSEC3)
+      if(*haveNSEC3)
       {
         string hashed;
-        if(!narrow) 
+        if(! *narrow) 
           hashed=toLower(toBase32Hex(hashQNameWithSalt(ns3pr->d_iterations, ns3pr->d_salt, *i)));
         di->backend->updateDNSSECOrderAndAuthAbsolute(di->id, *i, hashed, false);
       }
@@ -384,6 +448,7 @@ int PacketHandler::forwardPacket(const string &msgPrefix, DNSPacket *p, DomainIn
   }
 
   for(vector<string>::const_iterator master=di->masters.begin(); master != di->masters.end(); master++) {
+    L<<Logger::Notice<<msgPrefix<<"Forwarding packet to master "<<*master<<endl;
     ComboAddress remote;
     try {
       remote = ComboAddress(*master, 53);
@@ -549,7 +614,7 @@ int PacketHandler::processUpdate(DNSPacket *p) {
   for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i != mdp.d_answers.end(); ++i) {
     const DNSRecord *rr = &i->first;
     // Skip this check for other field types (like the TSIG -  which is in the additional section)
-    // For a TSIG, the label is the dnskey.
+    // For a TSIG, the label is the dnskey, so it does not pass the endOn validation.
     if (! (rr->d_place == DNSRecord::Answer || rr->d_place == DNSRecord::Nameserver)) 
       continue;
 
@@ -561,9 +626,10 @@ int PacketHandler::processUpdate(DNSPacket *p) {
     }
   }
 
-  Lock l(&s_rfc2136lock);
+
+  Lock l(&s_rfc2136lock); //TODO: i think this lock can be per zone, not for everything
   L<<Logger::Info<<msgPrefix<<"starting transaction."<<endl;
-  if (!di.backend->startTransaction(p->qdomain, -1)) { // Not giving the domain_id means that we do not delete the records.
+  if (!di.backend->startTransaction(p->qdomain, -1)) { // Not giving the domain_id means that we do not delete the existing records.
     L<<Logger::Error<<msgPrefix<<"Backend for domain "<<p->qdomain<<" does not support transaction. Can't do Update packet."<<endl;
     return RCode::NotImp;
   }
@@ -649,8 +715,9 @@ int PacketHandler::processUpdate(DNSPacket *p) {
 
     bool updatedSerial=false;
     NSEC3PARAMRecordContent ns3pr;
-    bool narrow; 
+    bool narrow=false
     bool haveNSEC3 = d_dk.getNSEC3PARAM(di.zone, &ns3pr, &narrow);
+    bool isPresigned = d_dk.isPresigned(di.zone);
 
     // We get all the before/after fields before doing anything to the db.
     // We can't do this inside performUpdate() because when we remove a delegate, the before/after result is different to what it should be
@@ -677,7 +744,7 @@ int PacketHandler::processUpdate(DNSPacket *p) {
         if (rr->d_class == QClass::NONE  && rr->d_type == QType::NS && stripDot(rr->d_label) == di.zone)
           nsRRtoDelete.push_back(rr);
         else
-          changedRecords += performUpdate(msgPrefix, rr, &di, narrow, haveNSEC3, &ns3pr, &updatedSerial);
+          changedRecords += performUpdate(msgPrefix, rr, &di, isPresigned, &narrow, &haveNSEC3, &ns3pr, &updatedSerial);
       }
     }
     if (nsRRtoDelete.size()) {
@@ -691,7 +758,7 @@ int PacketHandler::processUpdate(DNSPacket *p) {
         for (vector<DNSResourceRecord>::iterator inZone=nsRRInZone.begin(); inZone != nsRRInZone.end(); inZone++) {
           for (vector<const DNSRecord *>::iterator rr=nsRRtoDelete.begin(); rr != nsRRtoDelete.end(); rr++) {
             if (inZone->getZoneRepresentation() == (*rr)->d_content->getZoneRepresentation())
-              changedRecords += performUpdate(msgPrefix, *rr, &di, narrow, haveNSEC3, &ns3pr, &updatedSerial);
+              changedRecords += performUpdate(msgPrefix, *rr, &di, isPresigned, &narrow, &haveNSEC3, &ns3pr, &updatedSerial);
           }
         }
       }
@@ -815,7 +882,7 @@ void PacketHandler::increaseSerial(const string &msgPrefix, const DomainInfo *di
   vector<DNSResourceRecord> rrset;
   rrset.push_back(newRec);
   di->backend->replaceRRSet(di->id, newRec.qname, newRec.qtype, rrset);
-  L<<Logger::Error<<msgPrefix<<"Increasing SOA serial ("<<oldSerial<<" -> "<<soa2Update.serial<<")"<<endl;
+  L<<Logger::Notice<<msgPrefix<<"Increasing SOA serial ("<<oldSerial<<" -> "<<soa2Update.serial<<")"<<endl;
 
   //Correct ordername + auth flag
   if(haveNSEC3) {
diff --git a/regression-tests/1dyndns-update-nsec3params/command b/regression-tests/1dyndns-update-nsec3params/command
new file mode 100755 (executable)
index 0000000..e62d4bd
--- /dev/null
@@ -0,0 +1,43 @@
+#!/bin/sh
+       
+NSEC3=`cleandig test.dyndns NSEC3PARAM hidesoadetails dnssec`
+echo $NSEC3
+HAVENSEC3=`echo $NSEC3 | egrep 'IN[[:space:]]NSEC3PARAM' | wc -l`
+
+cleandig b.host.test.dyndns A hidesoadetails dnssec
+
+cleannsupdate <<!
+server $nameserver $port
+zone test.dyndns
+update add test.dyndns. 3600 NSEC3PARAM 1 1 10 DCBE
+send
+answer
+!
+
+cleandig test.dyndns NSEC3PARAM hidesoadetails dnssec
+cleandig b.host.test.dyndns A hidesoadetails dnssec
+
+cleannsupdate <<!
+server $nameserver $port
+zone test.dyndns
+update DELETE test.dyndns. NSEC3PARAM
+send
+answer
+!
+
+cleandig test.dyndns NSEC3PARAM hidesoadetails dnssec
+cleandig b.host.test.dyndns A hidesoadetails dnssec
+
+if [ $HAVENSEC3 != 0 ]
+then
+       cleannsupdate <<!
+       server $nameserver $port
+       zone test.dyndns
+       update add test.dyndns. 3600 NSEC3PARAM 1 1 1 abcd
+       send
+       answer
+!
+
+       cleandig test.dyndns NSEC3PARAM hidesoadetails dnssec
+       cleandig b.host.test.dyndns A hidesoadetails dnssec
+fi
diff --git a/regression-tests/1dyndns-update-nsec3params/description b/regression-tests/1dyndns-update-nsec3params/description
new file mode 100644 (file)
index 0000000..34e272f
--- /dev/null
@@ -0,0 +1,4 @@
+We allow to add/remove the NSEC3PARAM record, this test confirms that everything is working correctly.
+The test operates a bit different when in NSEC mode, as we don't add a NSEC3PARAM at the end.
+In NSEC3-NARROW mode, we do add NSEC3PARAM's at the end, but these are then in non-narrow mode as we cannot 
+specify that and the delete of the NSEC3PARAM also removed the narrow flag.
diff --git a/regression-tests/1dyndns-update-nsec3params/expected_result b/regression-tests/1dyndns-update-nsec3params/expected_result
new file mode 100755 (executable)
index 0000000..c8a3b58
--- /dev/null
@@ -0,0 +1,52 @@
+1 test.dyndns. IN NSEC 86400 cname1.test.dyndns. NS SOA MX RRSIG NSEC DNSKEY 1 test.dyndns. IN RRSIG 3600 SOA 8 2 3600 [expiry] [inception] [keytag] test.dyndns. ... 1 test.dyndns. IN RRSIG 86400 NSEC 8 2 86400 [expiry] [inception] [keytag] test.dyndns. ... 1 test.dyndns. IN SOA 3600 ns1.test.dyndns. ahu.example.dyndns. [serial] 28800 7200 604800 86400 2 . IN OPT 32768 Rcode: 0, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0 Reply to question for qname='test.dyndns.', qtype=NSEC3PARAM
+1      a.host.test.dyndns.     IN      NSEC    86400   e.host.test.dyndns. A RRSIG NSEC
+1      a.host.test.dyndns.     IN      RRSIG   86400   NSEC 8 4 86400 [expiry] [inception] [keytag] test.dyndns. ...
+1      test.dyndns.    IN      NSEC    86400   cname1.test.dyndns. NS SOA MX RRSIG NSEC DNSKEY
+1      test.dyndns.    IN      RRSIG   3600    SOA 8 2 3600 [expiry] [inception] [keytag] test.dyndns. ...
+1      test.dyndns.    IN      RRSIG   86400   NSEC 8 2 86400 [expiry] [inception] [keytag] test.dyndns. ...
+1      test.dyndns.    IN      SOA     3600    ns1.test.dyndns. ahu.example.dyndns. [serial] 28800 7200 604800 86400
+2      .       IN      OPT     32768   
+Rcode: 3, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='b.host.test.dyndns.', qtype=A
+Answer:
+;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id: [id]
+;; flags: qr aa; ZONE: 1, PREREQ: 0, UPDATE: 0, ADDITIONAL: 0
+;; ZONE SECTION:
+;test.dyndns.                  IN      SOA
+
+0      test.dyndns.    IN      NSEC3PARAM      86400   1 0 10 dcbe
+0      test.dyndns.    IN      RRSIG   86400   NSEC3PARAM 8 2 86400 [expiry] [inception] [keytag] test.dyndns. ...
+2      .       IN      OPT     32768   
+Rcode: 0, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='test.dyndns.', qtype=NSEC3PARAM
+1      ac2jl1kik929tr9i5rfcmbucm547n51a.test.dyndns.   IN      NSEC3   86400   1 1 10 dcbe EE295AK1NDT9O0RLL1A4RPPB4NAOV4QM
+1      ac2jl1kik929tr9i5rfcmbucm547n51a.test.dyndns.   IN      RRSIG   86400   NSEC3 8 3 86400 [expiry] [inception] [keytag] test.dyndns. ...
+1      test.dyndns.    IN      RRSIG   3600    SOA 8 2 3600 [expiry] [inception] [keytag] test.dyndns. ...
+1      test.dyndns.    IN      SOA     3600    ns1.test.dyndns. ahu.example.dyndns. [serial] 28800 7200 604800 86400
+1      uba3qp1vffon9pq2r07e7ldrnh5mg90v.test.dyndns.   IN      NSEC3   86400   1 1 10 dcbe 4KLD1OCH52V50U3NG1HM8R7960VRSVOM A RRSIG
+1      uba3qp1vffon9pq2r07e7ldrnh5mg90v.test.dyndns.   IN      RRSIG   86400   NSEC3 8 3 86400 [expiry] [inception] [keytag] test.dyndns. ...
+2      .       IN      OPT     32768   
+Rcode: 3, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='b.host.test.dyndns.', qtype=A
+Answer:
+;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id: [id]
+;; flags: qr aa; ZONE: 1, PREREQ: 0, UPDATE: 0, ADDITIONAL: 0
+;; ZONE SECTION:
+;test.dyndns.                  IN      SOA
+
+1      test.dyndns.    IN      NSEC    86400   cname1.test.dyndns. NS SOA MX RRSIG NSEC DNSKEY
+1      test.dyndns.    IN      RRSIG   3600    SOA 8 2 3600 [expiry] [inception] [keytag] test.dyndns. ...
+1      test.dyndns.    IN      RRSIG   86400   NSEC 8 2 86400 [expiry] [inception] [keytag] test.dyndns. ...
+1      test.dyndns.    IN      SOA     3600    ns1.test.dyndns. ahu.example.dyndns. [serial] 28800 7200 604800 86400
+2      .       IN      OPT     32768   
+Rcode: 0, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='test.dyndns.', qtype=NSEC3PARAM
+1      a.host.test.dyndns.     IN      NSEC    86400   e.host.test.dyndns. A RRSIG NSEC
+1      a.host.test.dyndns.     IN      RRSIG   86400   NSEC 8 4 86400 [expiry] [inception] [keytag] test.dyndns. ...
+1      test.dyndns.    IN      NSEC    86400   cname1.test.dyndns. NS SOA MX RRSIG NSEC DNSKEY
+1      test.dyndns.    IN      RRSIG   3600    SOA 8 2 3600 [expiry] [inception] [keytag] test.dyndns. ...
+1      test.dyndns.    IN      RRSIG   86400   NSEC 8 2 86400 [expiry] [inception] [keytag] test.dyndns. ...
+1      test.dyndns.    IN      SOA     3600    ns1.test.dyndns. ahu.example.dyndns. [serial] 28800 7200 604800 86400
+2      .       IN      OPT     32768   
+Rcode: 3, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='b.host.test.dyndns.', qtype=A
diff --git a/regression-tests/1dyndns-update-nsec3params/expected_result.nsec3 b/regression-tests/1dyndns-update-nsec3params/expected_result.nsec3
new file mode 100755 (executable)
index 0000000..b160060
--- /dev/null
@@ -0,0 +1,76 @@
+0 test.dyndns. IN NSEC3PARAM 86400 1 0 1 abcd 0 test.dyndns. IN RRSIG 86400 NSEC3PARAM 8 2 86400 [expiry] [inception] [keytag] test.dyndns. ... 2 . IN OPT 32768 Rcode: 0, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0 Reply to question for qname='test.dyndns.', qtype=NSEC3PARAM
+1      4i84rosksbmegcqfnkf6n6ci093h7rq4.test.dyndns.   IN      NSEC3   86400   1 1 1 abcd 8PQJV4B3M0LCFMVAE0HP394LC154L1I7 CNAME RRSIG
+1      4i84rosksbmegcqfnkf6n6ci093h7rq4.test.dyndns.   IN      RRSIG   86400   NSEC3 8 3 86400 [expiry] [inception] [keytag] test.dyndns. ...
+1      8ti9tgh8d81frr5vr4o1o5bvko42v9dq.test.dyndns.   IN      NSEC3   86400   1 1 1 abcd DSA3TI9NU3APDSVL3F63QLVAKV555SR6 A RRSIG
+1      8ti9tgh8d81frr5vr4o1o5bvko42v9dq.test.dyndns.   IN      RRSIG   86400   NSEC3 8 3 86400 [expiry] [inception] [keytag] test.dyndns. ...
+1      lmrsadk2bb62qpruaules5i5ap06cp55.test.dyndns.   IN      NSEC3   86400   1 1 1 abcd LRESBBP3LV8BLGJ9FSGTDMM4Q7VJ3D6J
+1      lmrsadk2bb62qpruaules5i5ap06cp55.test.dyndns.   IN      RRSIG   86400   NSEC3 8 3 86400 [expiry] [inception] [keytag] test.dyndns. ...
+1      test.dyndns.    IN      RRSIG   3600    SOA 8 2 3600 [expiry] [inception] [keytag] test.dyndns. ...
+1      test.dyndns.    IN      SOA     3600    ns1.test.dyndns. ahu.example.dyndns. [serial] 28800 7200 604800 86400
+2      .       IN      OPT     32768   
+Rcode: 3, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='b.host.test.dyndns.', qtype=A
+Answer:
+;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id: [id]
+;; flags: qr aa; ZONE: 1, PREREQ: 0, UPDATE: 0, ADDITIONAL: 0
+;; ZONE SECTION:
+;test.dyndns.                  IN      SOA
+
+0      test.dyndns.    IN      NSEC3PARAM      86400   1 0 10 dcbe
+0      test.dyndns.    IN      RRSIG   86400   NSEC3PARAM 8 2 86400 [expiry] [inception] [keytag] test.dyndns. ...
+2      .       IN      OPT     32768   
+Rcode: 0, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='test.dyndns.', qtype=NSEC3PARAM
+1      ac2jl1kik929tr9i5rfcmbucm547n51a.test.dyndns.   IN      NSEC3   86400   1 1 10 dcbe EE295AK1NDT9O0RLL1A4RPPB4NAOV4QM
+1      ac2jl1kik929tr9i5rfcmbucm547n51a.test.dyndns.   IN      RRSIG   86400   NSEC3 8 3 86400 [expiry] [inception] [keytag] test.dyndns. ...
+1      test.dyndns.    IN      RRSIG   3600    SOA 8 2 3600 [expiry] [inception] [keytag] test.dyndns. ...
+1      test.dyndns.    IN      SOA     3600    ns1.test.dyndns. ahu.example.dyndns. [serial] 28800 7200 604800 86400
+1      uba3qp1vffon9pq2r07e7ldrnh5mg90v.test.dyndns.   IN      NSEC3   86400   1 1 10 dcbe 4KLD1OCH52V50U3NG1HM8R7960VRSVOM A RRSIG
+1      uba3qp1vffon9pq2r07e7ldrnh5mg90v.test.dyndns.   IN      RRSIG   86400   NSEC3 8 3 86400 [expiry] [inception] [keytag] test.dyndns. ...
+2      .       IN      OPT     32768   
+Rcode: 3, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='b.host.test.dyndns.', qtype=A
+Answer:
+;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id: [id]
+;; flags: qr aa; ZONE: 1, PREREQ: 0, UPDATE: 0, ADDITIONAL: 0
+;; ZONE SECTION:
+;test.dyndns.                  IN      SOA
+
+1      test.dyndns.    IN      NSEC    86400   cname1.test.dyndns. NS SOA MX RRSIG NSEC DNSKEY
+1      test.dyndns.    IN      RRSIG   3600    SOA 8 2 3600 [expiry] [inception] [keytag] test.dyndns. ...
+1      test.dyndns.    IN      RRSIG   86400   NSEC 8 2 86400 [expiry] [inception] [keytag] test.dyndns. ...
+1      test.dyndns.    IN      SOA     3600    ns1.test.dyndns. ahu.example.dyndns. [serial] 28800 7200 604800 86400
+2      .       IN      OPT     32768   
+Rcode: 0, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='test.dyndns.', qtype=NSEC3PARAM
+1      a.host.test.dyndns.     IN      NSEC    86400   e.host.test.dyndns. A RRSIG NSEC
+1      a.host.test.dyndns.     IN      RRSIG   86400   NSEC 8 4 86400 [expiry] [inception] [keytag] test.dyndns. ...
+1      test.dyndns.    IN      NSEC    86400   cname1.test.dyndns. NS SOA MX RRSIG NSEC DNSKEY
+1      test.dyndns.    IN      RRSIG   3600    SOA 8 2 3600 [expiry] [inception] [keytag] test.dyndns. ...
+1      test.dyndns.    IN      RRSIG   86400   NSEC 8 2 86400 [expiry] [inception] [keytag] test.dyndns. ...
+1      test.dyndns.    IN      SOA     3600    ns1.test.dyndns. ahu.example.dyndns. [serial] 28800 7200 604800 86400
+2      .       IN      OPT     32768   
+Rcode: 3, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='b.host.test.dyndns.', qtype=A
+Answer:
+;; ->>HEADER<<- opcode: UPDATE, status: NOERROR, id: [id]
+;; flags: qr aa; ZONE: 1, PREREQ: 0, UPDATE: 0, ADDITIONAL: 0
+;; ZONE SECTION:
+;test.dyndns.                  IN      SOA
+
+0      test.dyndns.    IN      NSEC3PARAM      86400   1 0 1 abcd
+0      test.dyndns.    IN      RRSIG   86400   NSEC3PARAM 8 2 86400 [expiry] [inception] [keytag] test.dyndns. ...
+2      .       IN      OPT     32768   
+Rcode: 0, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='test.dyndns.', qtype=NSEC3PARAM
+1      4i84rosksbmegcqfnkf6n6ci093h7rq4.test.dyndns.   IN      NSEC3   86400   1 1 1 abcd 8PQJV4B3M0LCFMVAE0HP394LC154L1I7 CNAME RRSIG
+1      4i84rosksbmegcqfnkf6n6ci093h7rq4.test.dyndns.   IN      RRSIG   86400   NSEC3 8 3 86400 [expiry] [inception] [keytag] test.dyndns. ...
+1      8ti9tgh8d81frr5vr4o1o5bvko42v9dq.test.dyndns.   IN      NSEC3   86400   1 1 1 abcd DSA3TI9NU3APDSVL3F63QLVAKV555SR6 A RRSIG
+1      8ti9tgh8d81frr5vr4o1o5bvko42v9dq.test.dyndns.   IN      RRSIG   86400   NSEC3 8 3 86400 [expiry] [inception] [keytag] test.dyndns. ...
+1      lmrsadk2bb62qpruaules5i5ap06cp55.test.dyndns.   IN      NSEC3   86400   1 1 1 abcd LRESBBP3LV8BLGJ9FSGTDMM4Q7VJ3D6J
+1      lmrsadk2bb62qpruaules5i5ap06cp55.test.dyndns.   IN      RRSIG   86400   NSEC3 8 3 86400 [expiry] [inception] [keytag] test.dyndns. ...
+1      test.dyndns.    IN      RRSIG   3600    SOA 8 2 3600 [expiry] [inception] [keytag] test.dyndns. ...
+1      test.dyndns.    IN      SOA     3600    ns1.test.dyndns. ahu.example.dyndns. [serial] 28800 7200 604800 86400
+2      .       IN      OPT     32768   
+Rcode: 3, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='b.host.test.dyndns.', qtype=A
diff --git a/regression-tests/1dyndns-update-nsec3params/skip.narrow b/regression-tests/1dyndns-update-nsec3params/skip.narrow
new file mode 100644 (file)
index 0000000..0f73e79
--- /dev/null
@@ -0,0 +1,2 @@
+This test is skipped in narrow mode as we cannot set narrow via nsec3param.
+So, this test could impact other tests, as after this test has run, narrow mode would be off.
diff --git a/regression-tests/1dyndns-update-nsec3params/skip.nodnssec b/regression-tests/1dyndns-update-nsec3params/skip.nodnssec
new file mode 100644 (file)
index 0000000..e69de29
index c77a1684be84e7420e1b40ff1d0f9751f6322ebc..de7cd82da0570daccd9451ec14b57ded261cfd0d 100755 (executable)
@@ -99,6 +99,7 @@ do
 done
 
 rm -f pdns*.pid
+rm -f *_tests
 
 presigned=no
 
@@ -721,5 +722,10 @@ if [ $failed_tests = 0 ];
 then
         exit 0;
 else
+       for t in `cat failed_tests`
+       do
+               echo $t
+               cat $t/diff
+       done
         exit 1;
 fi