declare(suffix,"get-order-after-query","DNSSEC Ordering Query, after", "select min(ordername) from records where ordername > '%s' and domain_id=%d and ordername is not null");
declare(suffix,"get-order-last-query","DNSSEC Ordering Query, last", "select ordername, name from records where ordername != '' and domain_id=%d and ordername is not null order by 1 desc limit 1");
declare(suffix,"set-order-and-auth-query", "DNSSEC set ordering query", "update records set ordername='%s',auth=%d where name='%s' and domain_id='%d'");
- declare(suffix,"nullify-ordername-and-auth-query", "DNSSEC nullify ordername query", "update records set ordername=NULL,auth=0 where name='%s' and type='%s' and domain_id='%d'");
+ declare(suffix,"nullify-ordername-query", "DNSSEC nullify ordername query", "update records set ordername=NULL where domain_id='%d' and name='%s' and type is null");
+ declare(suffix,"nullify-ordername-and-auth-query", "DNSSEC nullify ordername and auth query", "update records set ordername=NULL,auth=0 where name='%s' and type='%s' and domain_id='%d'");
+ declare(suffix,"remove-empty-non-terminals-from-zone-query", "remove all empty non-terminals from zone", "delete from records where domain_id='%d' and type is null");
+ declare(suffix,"insert-empty-non-terminal-query", "insert empty non-terminal in zone", "insert into records (domain_id,name,type,auth) values ('%d','%s',null,'1')");
+ declare(suffix,"delete-empty-non-terminal-query", "delete empty non-terminal from zone", "delete from records where domain_id='%d' and name='%s' and type is null");
declare(suffix,"update-serial-query","", "update domains set notified_serial=%d where id=%d");
declare(suffix,"update-lastcheck-query","", "update domains set last_check=%d where id=%d");
declare(suffix,"get-order-last-query","DNSSEC Ordering Query, last", "select ordername, name from records where ordername != '' and domain_id=%d and ordername is not null order by 1 using ~>~ limit 1");
declare(suffix,"set-order-and-auth-query", "DNSSEC set ordering query", "update records set ordername=E'%s',auth=(%d = 1) where name=E'%s' and domain_id='%d'");
- declare(suffix,"nullify-ordername-and-auth-query", "DNSSEC nullify ordername query", "update records set ordername=NULL,auth=false where name=E'%s' and type=E'%s' and domain_id='%d'");
+ declare(suffix,"nullify-ordername-query", "DNSSEC nullify ordername query", "update records set ordername=NULL where domain_id='%d' and name='%s' and type is null");
+ declare(suffix,"nullify-ordername-and-auth-query", "DNSSEC nullify ordername and auth query", "update records set ordername=NULL,auth=false where name=E'%s' and type=E'%s' and domain_id='%d'");
+ declare(suffix,"remove-empty-non-terminals-from-zone-query", "remove all empty non-terminals from zone", "delete from records where domain_id='%d' and type is null");
+ declare(suffix,"insert-empty-non-terminal-query", "insert empty non-terminal in zone", "insert into records (domain_id,name,type,auth) values ('%d','%s',null,true)");
+ declare(suffix,"delete-empty-non-terminal-query", "delete empty non-terminal from zone", "delete from records where domain_id='%d' and name='%s' and type is null");
declare(suffix,"update-serial-query","", "update domains set notified_serial=%d where id=%d");
declare(suffix,"update-lastcheck-query","", "update domains set last_check=%d where id=%d");
declare(suffix,"get-order-last-query","DNSSEC Ordering Query, last", "select ordername, name from records where ordername != '' and domain_id=%d and ordername is not null order by 1 desc limit 1");
declare(suffix,"set-order-and-auth-query", "DNSSEC set ordering query", "update records set ordername='%s',auth=%d where name='%s' and domain_id='%d'");
- declare(suffix,"nullify-ordername-and-auth-query", "DNSSEC nullify ordername query", "update records set ordername=NULL,auth=0 where name='%s' and type='%s' and domain_id='%d'");
+ declare(suffix,"nullify-ordername-query", "DNSSEC nullify ordername query", "update records set ordername=NULL where domain_id='%d' and name='%s' and type is null");
+ declare(suffix,"nullify-ordername-and-auth-query", "DNSSEC nullify ordername and auth query", "update records set ordername=NULL,auth=0 where name='%s' and type='%s' and domain_id='%d'");
+ declare(suffix,"remove-empty-non-terminals-from-zone-query", "remove all empty non-terminals from zone", "delete from records where domain_id='%d' and type is null");
+ declare(suffix,"insert-empty-non-terminal-query", "insert empty non-terminal in zone", "insert into records (domain_id,name,type,auth) values ('%d','%s',null,'1')");
+ declare(suffix,"delete-empty-non-terminal-query", "delete empty non-terminal from zone", "delete from records where domain_id='%d' and name='%s' and type is null");
declare( suffix, "master-zone-query", "Data", "select master from domains where name='%s' and type='SLAVE'");
:_underscore.test.com:16:\030underscores\040are\040terrible:3600
+blah.test.com:192.168.6.1:3600
&blah.test.com::blah.test.com.:3600
++b.c.test.com:5.6.7.8:3600
++\052.a.b.c.test.com:8.7.6.5:3600
+counter.test.com:1.1.1.5:3600
:_double._tcp.dc.test.com:33:\000\000\000d\001\205\007server1\004test\003com\000:3600
:_double._tcp.dc.test.com:33:\000\001\000d\001\205\007server1\004test\003com\000:3600
bdr.qtype=qtype.getCode();
bdr.content=content;
bdr.nsec3hash = hashed;
+
+ if (!qtype.getCode()) // Set auth on empty non-terminals
+ bdr.auth=true;
if(bdr.qtype == QType::MX || bdr.qtype == QType::SRV) {
prio=atoi(bdr.content.c_str());
}
}
+void Bind2Backend::doEmptyNonTerminals(shared_ptr<State> stage, int id, bool nsec3zone, NSEC3PARAMRecordContent ns3pr)
+{
+ BB2DomainInfo bb2 = stage->id_zone_map[id];
+
+ bool doent=true;
+ set<string> qnames, nonterm;
+ string qname, shorter, hashed;
+
+ uint32_t maxent = ::arg().asNum("max-ent-entries");
+
+ BOOST_FOREACH(const Bind2DNSRecord& bdr, *bb2.d_records)
+ if (bdr.auth)
+ qnames.insert(labelReverse(bdr.qname));
+
+ BOOST_FOREACH(const string& qname, qnames)
+ {
+ shorter=qname;
+
+ while(chopOff(shorter))
+ {
+ if(!qnames.count(shorter) && !nonterm.count(shorter))
+ {
+ if(!(maxent))
+ {
+ L<<Logger::Error<<"Zone '"<<bb2.d_name<<"' has too many empty non terminals."<<endl;
+ doent=false;
+ break;
+ }
+ nonterm.insert(shorter);
+ --maxent;
+ }
+ }
+ if(!doent)
+ return;
+ }
+
+ DNSResourceRecord rr;
+ rr.qtype="0";
+ rr.content="";
+ rr.ttl=0;
+ rr.priority=0;
+ BOOST_FOREACH(const string& qname, nonterm)
+ {
+ rr.qname=qname+"."+bb2.d_name+".";
+ if(nsec3zone)
+ hashed=toLower(toBase32Hex(hashQNameWithSalt(ns3pr.d_iterations, ns3pr.d_salt, rr.qname)));
+ insert(stage, id, rr.qname, rr.qtype, rr.content, rr.ttl, rr.priority, hashed);
+ }
+}
+
void Bind2Backend::loadConfig(string* status)
{
// Interference with createSlaveDomain()
// sort(staging->id_zone_map[bbd->d_id].d_records->begin(), staging->id_zone_map[bbd->d_id].d_records->end());
- shared_ptr<recordstorage_t > records=staging->id_zone_map[bbd->d_id].d_records;
- fixupAuth(records);
+ fixupAuth(staging->id_zone_map[bbd->d_id].d_records);
+ doEmptyNonTerminals(staging, bbd->d_id, nsec3zone, ns3pr);
staging->id_zone_map[bbd->d_id].setCtime();
staging->id_zone_map[bbd->d_id].d_loaded=true;
// cerr<<"Sorting done"<<endl;
fixupAuth(staging->id_zone_map[bbd->d_id].d_records);
+ doEmptyNonTerminals(staging, bbd->d_id, nsec3zone, ns3pr);
staging->id_zone_map[bbd->d_id].setCtime();
s_state->id_zone_map[bbd->d_id]=staging->id_zone_map[bbd->d_id]; // move over
//cout<<"starting lower bound for: '"<<domain<<"'"<<endl;
- recordstorage_t::const_iterator iter = bbd.d_records->lower_bound(domain);
+ recordstorage_t::const_iterator iter = bbd.d_records->upper_bound(domain);
- while(iter == bbd.d_records->end() || (iter->qname) > domain || (!(iter->auth) && !(iter->qtype == QType::NS)))
+ while(iter == bbd.d_records->end() || (iter->qname) > domain || (!(iter->auth) && (!(iter->qtype == QType::NS))) || (!(iter->qtype)))
iter--;
before=iter->qname;
//cerr<<"\tFound: '"<<(iter->qname)<<"' (nsec3hash='"<<(iter->nsec3hash)<<"')"<<endl;
// this iteration is theoretically unnecessary - glue always sorts right behind a delegation
// so we will never get here. But let's do it anyway.
- while(!(iter->auth) && !(iter->qtype == QType::NS))
+ while((!(iter->auth) && (!(iter->qtype == QType::NS))) || (!(iter->qtype)))
{
iter++;
if(iter == bbd.d_records->end())
static string DLListRejectsHandler(const vector<string>&parts, Utility::pid_t ppid);
static string DLReloadNowHandler(const vector<string>&parts, Utility::pid_t ppid);
static void fixupAuth(shared_ptr<recordstorage_t> records);
+ static void doEmptyNonTerminals(shared_ptr<State> stage, int id, bool nsec3zone, NSEC3PARAMRecordContent ns3pr);
void loadConfig(string *status=0);
static void nukeZoneRecords(BB2DomainInfo *bbd);
};
d_afterOrderQuery = getArg("get-order-after-query");
d_lastOrderQuery = getArg("get-order-last-query");
d_setOrderAuthQuery = getArg("set-order-and-auth-query");
+ d_nullifyOrderNameQuery = getArg("nullify-ordername-query");
d_nullifyOrderNameAndAuthQuery = getArg("nullify-ordername-and-auth-query");
+ d_removeEmptyNonTerminalsFromZoneQuery = getArg("remove-empty-non-terminals-from-zone-query");
+ d_insertEmptyNonTerminalQuery = getArg("insert-empty-non-terminal-query");
+ d_deleteEmptyNonTerminalQuery = getArg("delete-empty-non-terminal-query");
d_AddDomainKeyQuery = getArg("add-domain-key-query");
d_ListDomainKeysQuery = getArg("list-domain-keys-query");
return true;
}
+bool GSQLBackend::nullifyDNSSECOrderName(uint32_t domain_id, const std::string& qname)
+{
+ if(!d_dnssecQueries)
+ return false;
+ char output[1024];
+
+ snprintf(output, sizeof(output)-1, d_nullifyOrderNameQuery.c_str(), domain_id, sqlEscape(qname).c_str());
+ d_db->doCommand(output);
+ return true;
+}
+
bool GSQLBackend::nullifyDNSSECOrderNameAndAuth(uint32_t domain_id, const std::string& qname, const std::string& type)
{
if(!d_dnssecQueries)
return true;
}
+bool GSQLBackend::updateEmptyNonTerminals(uint32_t domain_id, const std::string& zonename, set<string>& insert, set<string>& erase, bool remove)
+{
+ if(!d_dnssecQueries)
+ return false;
+ char output[1024];
+
+ if(remove) {
+ snprintf(output,sizeof(output)-1,d_removeEmptyNonTerminalsFromZoneQuery.c_str(), domain_id);
+ try {
+ d_db->doCommand(output);
+ }
+ catch (SSqlException &e) {
+ throw AhuException("GSQLBackend unable to delete empty non-terminal records from domain_id "+itoa(domain_id)+": "+e.txtReason());
+ return false;
+ }
+ }
+ else
+ {
+ BOOST_FOREACH(const string qname, erase) {
+ snprintf(output,sizeof(output)-1,d_deleteEmptyNonTerminalQuery.c_str(), domain_id, sqlEscape(qname).c_str());
+ try {
+ d_db->doCommand(output);
+ }
+ catch (SSqlException &e) {
+ throw AhuException("GSQLBackend unable to delete empty non-terminal rr "+qname+" from domain_id "+itoa(domain_id)+": "+e.txtReason());
+ return false;
+ }
+ }
+ }
+
+ BOOST_FOREACH(const string qname, insert) {
+ snprintf(output,sizeof(output)-1,d_insertEmptyNonTerminalQuery.c_str(), domain_id, sqlEscape(qname).c_str());
+ try {
+ d_db->doCommand(output);
+ }
+ catch (SSqlException &e) {
+ throw AhuException("GSQLBackend unable to insert empty non-terminal rr "+qname+" in domain_id "+itoa(domain_id)+": "+e.txtReason());
+ return false;
+ }
+ }
+
+ return true;
+}
+
bool GSQLBackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const std::string& qname, std::string& unhashed, std::string& before, std::string& after)
{
if(!d_dnssecQueries)
virtual bool getBeforeAndAfterNamesAbsolute(uint32_t id, const std::string& qname, std::string& unhashed, std::string& before, std::string& after);
bool updateDNSSECOrderAndAuth(uint32_t domain_id, const std::string& zonename, const std::string& qname, bool auth);
virtual bool updateDNSSECOrderAndAuthAbsolute(uint32_t domain_id, const std::string& qname, const std::string& ordername, bool auth);
+ virtual bool nullifyDNSSECOrderName(uint32_t domain_id, const std::string& qname);
virtual bool nullifyDNSSECOrderNameAndAuth(uint32_t domain_id, const std::string& qname, const std::string& type);
+ virtual bool updateEmptyNonTerminals(uint32_t domain_id, const std::string& zonename, set<string>& insert ,set<string>& erase, bool remove);
virtual bool calculateSOASerial(const string& domain, const SOAData& sd, time_t& serial);
string d_afterOrderQuery;
string d_lastOrderQuery;
string d_setOrderAuthQuery;
+ string d_nullifyOrderNameQuery;
string d_nullifyOrderNameAndAuthQuery;
+ string d_removeEmptyNonTerminalsFromZoneQuery;
+ string d_insertEmptyNonTerminalQuery;
+ string d_deleteEmptyNonTerminalQuery;
string d_AddDomainKeyQuery;
string d_ListDomainKeysQuery;
#include <botan/rsa.h>
#include <botan/pubkey.h>
#include <botan/look_pk.h>
-#include <botan/numthry.h>
#include "dnssecinfra.hh"
using namespace Botan;
#if BOTAN_VERSION_CODE < BOTAN_VERSION_CODE_FOR(1,9,0)
BigInt d1 = d_key->get_d() % (d_key->get_p() - 1);
BigInt d2 = d_key->get_d() % (d_key->get_q() - 1);
- BigInt c = inverse_mod(d_key->get_q(), d_key->get_p());
#else
BigInt d1 = d_key->get_d1();
BigInt d2 = d_key->get_d2();
- BigInt c = d_key->get_c();
#endif
storvect.push_back(make_pair("Exponent1", asRaw(d1)));
storvect.push_back(make_pair("Exponent2", asRaw(d2)));
- storvect.push_back(make_pair("Coefficient", asRaw(c)));
+ storvect.push_back(make_pair("Coefficient", asRaw(d_key->get_q())));
return storvect;
}
::arg().set("setgid","If set, change group id to this gid for more security")="";
::arg().set("max-cache-entries", "Maximum number of cache entries")="1000000";
+ ::arg().set("max-ent-entries", "Maximum number of empty non-terminals in a zone")="100000";
::arg().set("entropy-source", "If set, read entropy from this file")="/dev/urandom";
::arg().set("lua-prequery-script", "Lua script with prequery handler")="";
return false;
}
+ virtual bool updateEmptyNonTerminals(uint32_t domain_id, const std::string& zonename, set<string>& insert, set<string>& erase, bool remove)
+ {
+ return false;
+ }
+
+ virtual bool nullifyDNSSECOrderName(uint32_t domain_id, const std::string& qname)
+ {
+ return false;
+ }
+
virtual bool nullifyDNSSECOrderNameAndAuth(uint32_t domain_id, const std::string& qname, const std::string& type)
{
return false;
res[0] = static_cast<unsigned char>(window);
res[1] = static_cast<unsigned char>(len);
- tmp.assign(res, res+len+2);
- pw.xfrBlob(tmp);
+
+ if (len) {
+ tmp.assign(res, res+len+2);
+ pw.xfrBlob(tmp);
+ }
}
NSEC3RecordContent::DNSRecordContent* NSEC3RecordContent::make(const DNSRecord &dr, PacketReader& pr)
DNSResourceRecord rr;
B.lookup(QType(QType::ANY), begin);
while(B.get(rr)) {
- if(rr.domain_id == sd.domain_id && (rr.qtype.getCode() == QType::NS || rr.auth))
+ if(rr.domain_id == sd.domain_id && (rr.qtype.getCode() == QType::NS || rr.auth))
nrc.d_set.insert(rr.qtype.getCode());
}
nrc.d_next=end;
- rr.ttl = sd.default_ttl;
-
rr.qname=begin;
- // we can leave ttl untouched, either it is the default, or it is what we retrieved above
+ rr.ttl = sd.default_ttl;
rr.qtype=QType::NSEC;
rr.content=nrc.getZoneRepresentation();
rr.d_place = (mode == 5 ) ? DNSResourceRecord::ANSWER: DNSResourceRecord::AUTHORITY;
{
// cerr<<"We should emit NSEC3 '"<<toLower(toBase32Hex(begin))<<"' - ('"<<toNSEC3<<"') - '"<<toLower(toBase32Hex(end))<<"' (unhashed: '"<<unhashed<<"')"<<endl;
NSEC3RecordContent n3rc;
- n3rc.d_set.insert(QType::RRSIG);
n3rc.d_salt=ns3prc.d_salt;
n3rc.d_flags = ns3prc.d_flags;
n3rc.d_iterations = ns3prc.d_iterations;
n3rc.d_algorithm = 1; // SHA1, fixed in PowerDNS for now
- DNSResourceRecord nsec3rr, rr;
- B.lookup(QType(QType::ANY), unhashed);
- while(B.get(rr)) {
- n3rc.d_set.insert(rr.qtype.getCode());
- }
+ DNSResourceRecord rr;
+ if(!unhashed.empty()) {
+ B.lookup(QType(QType::ANY), unhashed);
+ while(B.get(rr)) {
+ if(rr.domain_id == sd.domain_id && rr.qtype.getCode()) // skip out of zone data and empty non-terminals
+ n3rc.d_set.insert(rr.qtype.getCode());
+ }
- if(unhashed == sd.qname) {
- n3rc.d_set.insert(QType::NSEC3PARAM);
- n3rc.d_set.insert(QType::DNSKEY);
+ if(unhashed == sd.qname) {
+ n3rc.d_set.insert(QType::NSEC3PARAM);
+ n3rc.d_set.insert(QType::DNSKEY);
+ }
}
+
+ if (n3rc.d_set.size())
+ n3rc.d_set.insert(QType::RRSIG);
n3rc.d_nexthash=end;
- rr.ttl = sd.default_ttl;
rr.qname=dotConcat(toLower(toBase32Hex(begin)), sd.qname);
-
+ rr.ttl = sd.default_ttl;
rr.qtype=QType::NSEC3;
rr.content=n3rc.getZoneRepresentation();
-
rr.d_place = (mode == 5 ) ? DNSResourceRecord::ANSWER: DNSResourceRecord::AUTHORITY;
rr.auth = true;
+
r->addRecord(rr);
}
/*
mode 0 = No Data Responses, QTYPE is not DS
- mode 1 = No Data Responses, QTYPE is DS (can we do this already?)
+ mode 1 = No Data Responses, QTYPE is DS
mode 2 = Wildcard No Data Responses
mode 3 = Wildcard Answer Responses
mode 4 = Name Error Responses
if(narrow) { // nsec3-narrow
ret=true;
before=hashed;
- if(decrement)
+ if(decrement) {
decrementHash(before);
+ unhashed.clear();
+ }
after=hashed;
incrementHash(after);
}
string before,after;
//cerr<<"Calling getBeforeandAfter!"<<endl;
+
if (mode == 2) {
+ // wildcard NO-DATA
sd.db->getBeforeAndAfterNames(sd.domain_id, auth, p->qdomain, before, after);
+ emitNSEC(before, after, target, sd, r, mode);
+ sd.db->getBeforeAndAfterNames(sd.domain_id, auth, target, before, after);
}
else {
sd.db->getBeforeAndAfterNames(sd.domain_id, auth, target, before, after);
}
- // cerr<<"Done calling, before='"<<before<<"', after='"<<after<<"'"<<endl;
-
- // this stuff is wrong (but it appears to work)
+ emitNSEC(before, after, target, sd, r, mode);
- if(mode == 0 || mode == 1 || mode == 5)
- emitNSEC(target, after, target, sd, r, mode);
-
- if(mode == 2 || mode == 4) {
- emitNSEC(before, after, target, sd, r, mode);
-
- if (mode == 2) {
- sd.db->getBeforeAndAfterNames(sd.domain_id, auth, target, before, after);
- emitNSEC(target, after, auth, sd, r, mode);
- }
- else {
+ if (mode == 4) {
// this one does wildcard denial, if applicable
sd.db->getBeforeAndAfterNames(sd.domain_id, auth, auth, before, after);
emitNSEC(auth, after, auth, sd, r, mode);
- }
}
- if(mode == 3)
- emitNSEC(before, after, target, sd, r, mode);
-
return;
}
}
}
else if(weDone) {
+ bool haveRecords = false;
BOOST_FOREACH(rr, rrset) {
- if((p->qtype.getCode() == QType::ANY || rr.qtype == p->qtype) && rr.auth)
+ if((p->qtype.getCode() == QType::ANY || rr.qtype == p->qtype) && rr.qtype.getCode() && rr.auth) {
r->addRecord(rr);
+ haveRecords = true;
+ }
}
- if(p->qtype.getCode() == QType::ANY) {
- completeANYRecords(p, r, sd, target);
+ if (haveRecords) {
+ if(p->qtype.getCode() == QType::ANY)
+ completeANYRecords(p, r, sd, target);
}
+ else
+ makeNOError(p, r, rr.qname, sd, 0);
goto sendit;
}
#
# max-cache-entries=1000000
+#################################
+# max-ent-entries Maximum number of empty non-terminals in a zone
+#
+# max-ent-entries=100000
+
#################################
# max-queue-length Maximum queuelength before considering situation lost
#
cleanSlashes(configname);
::arg().laxFile(configname.c_str());
+ ::arg().set("max-ent-entries", "Maximum number of empty non-terminals in a zone")="100000";
::arg().set("module-dir","Default directory for modules")=LIBDIR;
BackendMakers().launch(::arg()["launch"]); // vrooooom!
::arg().laxFile(configname.c_str());
return;
}
sd.db->list(zone, sd.domain_id);
- DNSResourceRecord rr;
- set<string> qnames, nsset, dsnames;
+ DNSResourceRecord rr;
+ set<string> qnames, nsset, dsnames, nonterm, insnonterm, delnonterm;
+ bool doent=true;
while(sd.db->get(rr)) {
- qnames.insert(rr.qname);
- if(rr.qtype.getCode() == QType::NS && !pdns_iequals(rr.qname, zone))
- nsset.insert(rr.qname);
- if(rr.qtype.getCode() == QType::DS)
- dsnames.insert(rr.qname);
+ if (rr.qtype.getCode())
+ {
+ qnames.insert(rr.qname);
+ if(rr.qtype.getCode() == QType::NS && !pdns_iequals(rr.qname, zone))
+ nsset.insert(rr.qname);
+ if(rr.qtype.getCode() == QType::DS)
+ dsnames.insert(rr.qname);
+ }
+ else
+ if(doent)
+ delnonterm.insert(rr.qname);
}
NSEC3PARAMRecordContent ns3pr;
bool narrow;
bool haveNSEC3=dk.getNSEC3PARAM(zone, &ns3pr, &narrow);
- string hashed;
if(!haveNSEC3)
cerr<<"Adding NSEC ordering information"<<endl;
else if(!narrow)
if(doTransaction)
sd.db->startTransaction("", -1);
+
+ bool realrr=true;
+ string hashed;
+
+ uint32_t maxent = ::arg().asNum("max-ent-entries");
+
+ dononterm:;
BOOST_FOREACH(const string& qname, qnames)
{
- string shorter(qname);
bool auth=true;
+ string shorter(qname);
- do {
- if(nsset.count(shorter)) {
- auth=false;
- break;
- }
- }while(chopOff(shorter));
+ if(realrr) {
+ do {
+ if(nsset.count(shorter)) {
+ auth=false;
+ break;
+ }
+ } while(chopOff(shorter));
- if(dsnames.count(qname))
- auth=true;
+ if(dsnames.count(qname))
+ auth=true;
+ }
if(haveNSEC3)
{
cerr<<"'"<<qname<<"' -> '"<< hashed <<"'"<<endl;
}
sd.db->updateDNSSECOrderAndAuthAbsolute(sd.domain_id, qname, hashed, auth);
- if(!auth || dsnames.count(qname))
+ if((!auth || dsnames.count(qname)) && realrr)
{
sd.db->nullifyDNSSECOrderNameAndAuth(sd.domain_id, qname, "NS");
sd.db->nullifyDNSSECOrderNameAndAuth(sd.domain_id, qname, "A");
}
else // NSEC
{
- sd.db->updateDNSSECOrderAndAuth(sd.domain_id, zone, qname, auth);
- if(!auth || dsnames.count(qname))
+ if(realrr)
{
- sd.db->nullifyDNSSECOrderNameAndAuth(sd.domain_id, qname, "A");
- sd.db->nullifyDNSSECOrderNameAndAuth(sd.domain_id, qname, "AAAA");
+ sd.db->updateDNSSECOrderAndAuth(sd.domain_id, zone, qname, auth);
+ if(!auth || dsnames.count(qname))
+ {
+ sd.db->nullifyDNSSECOrderNameAndAuth(sd.domain_id, qname, "A");
+ sd.db->nullifyDNSSECOrderNameAndAuth(sd.domain_id, qname, "AAAA");
+ }
+ }
+ else
+ {
+ sd.db->nullifyDNSSECOrderName(sd.domain_id, qname);
+ }
+ }
+
+ if(auth && realrr && doent)
+ {
+ shorter=qname;
+ while(!pdns_iequals(shorter, zone) && chopOff(shorter))
+ {
+ if(!qnames.count(shorter) && !nonterm.count(shorter))
+ {
+ if(!(maxent))
+ {
+ cerr<<"Zone '"<<zone<<"' has too many empty non terminals."<<endl;
+ insnonterm.clear();
+ delnonterm.clear();
+ doent=false;
+ break;
+ }
+ nonterm.insert(shorter);
+ if (!delnonterm.count(shorter))
+ insnonterm.insert(shorter);
+ else
+ delnonterm.erase(shorter);
+ --maxent;
+ }
}
}
}
+
+ if(realrr)
+ {
+ //cerr<<"Total: "<<nonterm.size()<<" Insert: "<<insnonterm.size()<<" Delete: "<<delnonterm.size()<<endl;
+ if(!insnonterm.empty() || !delnonterm.empty() || !doent)
+ {
+ sd.db->updateEmptyNonTerminals(sd.domain_id, zone, insnonterm, delnonterm, !doent);
+ }
+ if(doent)
+ {
+ realrr=false;
+ qnames=nonterm;
+ goto dononterm;
+ }
+ }
+
if(doTransaction)
sd.db->commitTransaction();
}
domain_id=di.id;
Resolver::res_t recs;
- set<string> nsset, qnames, dsnames;
+ set<string> nsset, qnames, dsnames, nonterm, delnonterm;
ComboAddress raddr(remote, 53);
dnssecZone = gotPresigned = true;
continue;
}
-
+
if(!endsOn(i->qname, domain)) {
L<<Logger::Error<<"Remote "<<remote<<" tried to sneak in out-of-zone data '"<<i->qname<<"'|"<<i->qtype.getName()<<" during AXFR of zone '"<<domain<<"', ignoring"<<endl;
continue;
}
- if(i->qtype.getCode() == QType::NS && !pdns_iequals(i->qname, domain))
- nsset.insert(i->qname);
- if(i->qtype.getCode() != QType::RRSIG) // this excludes us hashing RRSIGs for NSEC(3)
- qnames.insert(i->qname);
- if(i->qtype.getCode() == QType::DS)
- dsnames.insert(i->qname);
-
i->domain_id=domain_id;
#if 0
if(i->qtype.getCode()>=60000)
}
else {
di.backend->feedRecord(*i);
+ if(i->qtype.getCode() == QType::NS && !pdns_iequals(i->qname, domain))
+ nsset.insert(i->qname);
+ if(i->qtype.getCode() != QType::RRSIG) // this excludes us hashing RRSIGs for NSEC(3)
+ qnames.insert(i->qname);
+ if(i->qtype.getCode() == QType::DS)
+ dsnames.insert(i->qname);
}
}
}
haveNSEC3 = false;
}
+ bool doent=true;
+ bool realrr=true;
string hashed;
+
+ uint32_t maxent = ::arg().asNum("max-ent-entries");
+
+ dononterm:;
BOOST_FOREACH(const string& qname, qnames)
{
- string shorter(qname);
bool auth=true;
- do {
- if(nsset.count(shorter)) {
- auth=false;
- break;
- }
- }while(chopOff(shorter));
-
- if(dsnames.count(qname))
- auth=true;
+ string shorter(qname);
+
+ if(realrr) {
+ do {
+ if(nsset.count(shorter)) {
+ auth=false;
+ break;
+ }
+ }while(chopOff(shorter));
+
+ if(dsnames.count(qname))
+ auth=true;
+ }
if(dnssecZone && haveNSEC3)
{
hashed=toLower(toBase32Hex(hashQNameWithSalt(ns3pr.d_iterations, ns3pr.d_salt, qname)));
}
di.backend->updateDNSSECOrderAndAuthAbsolute(domain_id, qname, hashed, auth); // this should always be done
- if(!auth || dsnames.count(qname))
+ if((!auth || dsnames.count(qname)) && realrr)
{
di.backend->nullifyDNSSECOrderNameAndAuth(domain_id, qname, "NS");
di.backend->nullifyDNSSECOrderNameAndAuth(domain_id, qname, "A");
}
else // NSEC
{
- di.backend->updateDNSSECOrderAndAuth(domain_id, domain, qname, auth);
- if(!auth || dsnames.count(qname))
+ if(realrr)
{
- di.backend->nullifyDNSSECOrderNameAndAuth(domain_id, qname, "A");
- di.backend->nullifyDNSSECOrderNameAndAuth(domain_id, qname, "AAAA");
+ di.backend->updateDNSSECOrderAndAuth(domain_id, domain, qname, auth);
+ if(!auth || dsnames.count(qname))
+ {
+ di.backend->nullifyDNSSECOrderNameAndAuth(domain_id, qname, "A");
+ di.backend->nullifyDNSSECOrderNameAndAuth(domain_id, qname, "AAAA");
+ }
+ }
+ }
+
+ if(auth && realrr && doent)
+ {
+ shorter=qname;
+ while(!pdns_iequals(shorter, domain) && chopOff(shorter))
+ {
+ if(!qnames.count(shorter) && !nonterm.count(shorter))
+ {
+ if(!(maxent))
+ {
+ L<<Logger::Error<<"AXFR zone "<<domain<<" has too many empty non terminals."<<endl;
+ nonterm.empty();
+ doent=false;
+ break;
+ }
+ nonterm.insert(shorter);
+ --maxent;
+ }
}
}
}
+
+ if(!nonterm.empty() && realrr && doent)
+ {
+ if(di.backend->updateEmptyNonTerminals(domain_id, domain, nonterm, delnonterm, false))
+ {
+ realrr=false;
+ qnames=nonterm;
+ goto dononterm;
+ }
+ }
+
di.backend->commitTransaction();
di.backend->setFresh(domain_id);
PC.purge(domain+"$");
continue;
records++;
if(securedZone && (rr.auth || (!NSEC3Zone && rr.qtype.getCode() == QType::NS) || rr.qtype.getCode() == QType::DS)) { // this is probably NSEC specific, NSEC3 is different
- keyname = NSEC3Zone ? hashQNameWithSalt(ns3pr.d_iterations, ns3pr.d_salt, rr.qname) : labelReverse(rr.qname);
- NSECXEntry& ne = nsecxrepo[keyname];
- ne.d_set.insert(rr.qtype.getCode());
- ne.d_ttl = sd.default_ttl;
+ if (NSEC3Zone || rr.qtype.getCode()) {
+ keyname = NSEC3Zone ? hashQNameWithSalt(ns3pr.d_iterations, ns3pr.d_salt, rr.qname) : labelReverse(rr.qname);
+ NSECXEntry& ne = nsecxrepo[keyname];
+ ne.d_ttl = sd.default_ttl;
+ if (rr.qtype.getCode()) {
+ ne.d_set.insert(rr.qtype.getCode());
+ }
+ }
}
+
+ if (!rr.qtype.getCode())
+ continue; // skip empty non-terminals
+
if(rr.qtype.getCode() == QType::SOA)
continue; // skip SOA - would indicate end of AXFR
for(nsecxrepo_t::const_iterator iter = nsecxrepo.begin(); iter != nsecxrepo.end(); ++iter) {
NSEC3RecordContent n3rc;
n3rc.d_set = iter->second.d_set;
- n3rc.d_set.insert(QType::RRSIG);
+ if (n3rc.d_set.size())
+ n3rc.d_set.insert(QType::RRSIG);
n3rc.d_salt=ns3pr.d_salt;
n3rc.d_flags = ns3pr.d_flags;
n3rc.d_iterations = ns3pr.d_iterations;
rr.qname = dotConcat(toLower(toBase32Hex(iter->first)), sd.qname);
- rr.ttl = iter->second.d_ttl;
+ rr.ttl = sd.default_ttl;
rr.content = n3rc.getZoneRepresentation();
rr.qtype = QType::NSEC3;
rr.d_place = DNSResourceRecord::ANSWER;
rr.qname = labelReverse(iter->first);
- rr.ttl = iter->second.d_ttl;
+ rr.ttl = sd.default_ttl;
rr.content = nrc.getZoneRepresentation();
rr.qtype = QType::NSEC;
rr.d_place = DNSResourceRecord::ANSWER;
b6d1c64a890e3f3ce40970724a12eb0b ../regression-tests/example.com
-bb578fbd58265c977dc83a52bde80928 ../regression-tests/test.com
+451fb64d4a6b33b63124556d789ac3d0 ../regression-tests/test.com
7d726bc367bf5e6ee5f1689994c6b6d4 ../regression-tests/wtest.com
a0670eef8fba3e16908057af8de2c2f2 ../regression-tests/dnssec-parent.com
42dd3a56c7d268e75836371878819ec4 ../regression-tests/delegated.dnssec-parent.com
24514dc104b22206daeb973ff9303545 ../regression-tests/minimal.com
-61490253e7b3a9ac1e0be2214c16cfa0 ../modules/tinydnsbackend/data.cdb
+f1e5a8ab3243ad2c47b29d06f22bdeaf ../modules/tinydnsbackend/data.cdb
0 www.something.wtest.com. IN A 3600 4.3.2.1
0 www.something.wtest.com. IN RRSIG 3600 A 8 3 3600 [expiry] [inception] [keytag] wtest.com. ...
-1 7q60llva2bt9ucubvn553q9s2pf8ho38.wtest.com. IN NSEC3 86400 1 1 1 abcd 7Q60LLVA2BT9UCUBVN553Q9S2PF8HO3A RRSIG
+1 7q60llva2bt9ucubvn553q9s2pf8ho38.wtest.com. IN NSEC3 86400 1 1 1 abcd 7Q60LLVA2BT9UCUBVN553Q9S2PF8HO3A
1 7q60llva2bt9ucubvn553q9s2pf8ho38.wtest.com. IN RRSIG 86400 NSEC3 8 3 86400 [expiry] [inception] [keytag] wtest.com. ...
2 . IN OPT 32768
Rcode: 0, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
#!/bin/sh
+if [ ! -f $testname/use.drill ]
+then
../pdns/sdig $nameserver $port $1 $2 $3 | LC_ALL=C sort
+fi
../pdns/nsec3dig $nameserver $port $1 $2 > $testname/nsec3dig.out 2>&1
drill -a -p $port -o rd -D -S -k trustedkeys $1 $2 @$nameserver > $testname/drillchase.out 2>&1
echo RETVAL: $? >> $testname/drillchase.out
unbound-host -v -C unbound-host.conf -t $2 $1 > $testname/unbound-host.out 2>&1
echo RETVAL: $? >> $testname/unbound-host.out
fi
+if [ -f $testname/use.drill ]
+then
+ cat $testname/drill.out
+fi
grep -i bogus $testname/*.out
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 t67rqvqprigd7rtb5fah6c3o7g9th3iv.example.com. IN NSEC3 86400 1 1 1 abcd T67RQVQPRIGD7RTB5FAH6C3O7G9TH3J1 NS RRSIG
+1 t67rqvqprigd7rtb5fah6c3o7g9th3iv.example.com. IN NSEC3 86400 1 1 1 abcd T67RQVQPRIGD7RTB5FAH6C3O7G9TH3J1
1 t67rqvqprigd7rtb5fah6c3o7g9th3iv.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 VTNQ6OCN2VKUIV3NJU14OQTAEN2MT5SL NS SOA MX RRSIG DNSKEY NSEC3PARAM
1 vtnq6ocn2vkuiv3nju14oqtaen2mt5sk.example.com. IN RRSIG 86400 NSEC3 8 3 86400 [expiry] [inception] [keytag] example.com. ...
-1 be6iqh4fjrtdhacqk7g3iq96qcvf2qoi.dnssec-parent.com. IN NSEC3 86400 1 1 1 abcd BE6IQH4FJRTDHACQK7G3IQ96QCVF2QOK A NS SOA RRSIG
+1 be6iqh4fjrtdhacqk7g3iq96qcvf2qoi.dnssec-parent.com. IN NSEC3 86400 1 1 1 abcd BE6IQH4FJRTDHACQK7G3IQ96QCVF2QOK
1 be6iqh4fjrtdhacqk7g3iq96qcvf2qoi.dnssec-parent.com. IN RRSIG 86400 NSEC3 8 3 86400 [expiry] [inception] [keytag] dnssec-parent.com. ...
1 dnssec-parent.com. IN RRSIG 3600 SOA 8 2 3600 [expiry] [inception] [keytag] dnssec-parent.com. ...
1 dnssec-parent.com. IN SOA 3600 ns1.dnssec-parent.com. ahu.example.com. 2005092501 28800 7200 604800 86400
-1 t67rqvqprigd7rtb5fah6c3o7g9th3iv.example.com. IN NSEC3 86400 1 1 1 abcd T67RQVQPRIGD7RTB5FAH6C3O7G9TH3J1 NS RRSIG
+1 t67rqvqprigd7rtb5fah6c3o7g9th3iv.example.com. IN NSEC3 86400 1 1 1 abcd T67RQVQPRIGD7RTB5FAH6C3O7G9TH3J1
1 usa.example.com. IN NS 120 usa-ns1.usa.example.com.
1 usa.example.com. IN NS 120 usa-ns2.usa.example.com.
1 vtnq6ocn2vkuiv3nju14oqtaen2mt5sk.example.com. IN NSEC3 86400 1 1 1 abcd VTNQ6OCN2VKUIV3NJU14OQTAEN2MT5SL NS SOA MX RRSIG DNSKEY NSEC3PARAM
--- /dev/null
+#!/bin/sh
+cleandig c.test.com ANY dnssec
--- /dev/null
+Check if the empty non-terminal exists (ANY query)
--- /dev/null
+1 blah.test.com. IN NSEC 86400 b.c.test.com. NS RRSIG NSEC
+1 blah.test.com. IN RRSIG 86400 NSEC 8 3 86400 [expiry] [inception] [keytag] test.com. ...
+1 test.com. IN RRSIG 3600 SOA 8 2 3600 [expiry] [inception] [keytag] test.com. ...
+1 test.com. IN SOA 3600 ns1.test.com. ahu.example.com. 2005092501 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='c.test.com.', qtype=ANY
--- /dev/null
+1 s6g5shc1jvovl5fl9e943adlonqln7g4.test.com. IN NSEC3 86400 1 1 1 abcd S6G5SHC1JVOVL5FL9E943ADLONQLN7G5
+1 s6g5shc1jvovl5fl9e943adlonqln7g4.test.com. IN RRSIG 86400 NSEC3 8 3 86400 [expiry] [inception] [keytag] test.com. ...
+1 test.com. IN RRSIG 3600 SOA 8 2 3600 [expiry] [inception] [keytag] test.com. ...
+1 test.com. IN SOA 3600 ns1.test.com. ahu.example.com. 2005092501 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='c.test.com.', qtype=ANY
--- /dev/null
+1 s6g5shc1jvovl5fl9e943adlonqln7g4.test.com. IN NSEC3 86400 1 1 1 abcd SA5VVPQN1COEJGJ3HBKFEKDNII8KKSQA
+1 s6g5shc1jvovl5fl9e943adlonqln7g4.test.com. IN RRSIG 86400 NSEC3 8 3 86400 [expiry] [inception] [keytag] test.com. ...
+1 test.com. IN RRSIG 3600 SOA 8 2 3600 [expiry] [inception] [keytag] test.com. ...
+1 test.com. IN SOA 3600 ns1.test.com. ahu.example.com. 2005092501 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='c.test.com.', qtype=ANY
--- /dev/null
+#!/bin/sh
+USEDRILL=1 cleandig test.com AXFR dnssec | grep -P 'IN\tNSEC' | LC_ALL=C sort
--- /dev/null
+Are all NSECx records present in the AXFR output (including empty non-terminals)
--- /dev/null
+*.a.b.c.test.com. 86400 IN NSEC counter.test.com. A RRSIG NSEC
+*.test.test.com. 86400 IN NSEC sub.test.test.com. CNAME RRSIG NSEC
+_double._tcp.dc.test.com. 86400 IN NSEC _ldap._tcp.dc.test.com. SRV RRSIG NSEC
+_ldap._tcp.dc.test.com. 86400 IN NSEC enum.test.com. SRV RRSIG NSEC
+_underscore.test.com. 86400 IN NSEC blah.test.com. TXT RRSIG NSEC
+b.c.test.com. 86400 IN NSEC *.a.b.c.test.com. A RRSIG NSEC
+blah.test.com. 86400 IN NSEC b.c.test.com. NS RRSIG NSEC
+counter.test.com. 86400 IN NSEC _double._tcp.dc.test.com. A RRSIG NSEC
+enum.test.com. 86400 IN NSEC server1.test.com. NAPTR RRSIG NSEC
+server1.test.com. 86400 IN NSEC *.test.test.com. A RP RRSIG NSEC
+sub.test.test.com. 86400 IN NSEC www.test.test.com. NS RRSIG NSEC
+test.com. 86400 IN NSEC _underscore.test.com. NS SOA MX RRSIG NSEC DNSKEY
+very-long-txt.test.com. 86400 IN NSEC within-server.test.com. TXT RRSIG NSEC
+within-server.test.com. 86400 IN NSEC www.test.com. CNAME RRSIG NSEC
+www.test.com. 86400 IN NSEC test.com. CNAME RRSIG NSEC
+www.test.test.com. 86400 IN NSEC very-long-txt.test.com. A RRSIG NSEC
--- /dev/null
+2eu2gulbu53h9uvhfalshpbo2a83t6l2.test.com. 86400 IN NSEC3 1 1 1 abcd 79u3das6ucctns1br3tvd8qkanni351l NS SOA MX RRSIG DNSKEY NSEC3PARAM
+79u3das6ucctns1br3tvd8qkanni351l.test.com. 86400 IN NSEC3 1 1 1 abcd 7mmura8h40be5n4koan7rnmkursamh99
+7mmura8h40be5n4koan7rnmkursamh99.test.com. 86400 IN NSEC3 1 1 1 abcd 88f1bqrb2iscvfel2sqqcksvflnekap6
+88f1bqrb2iscvfel2sqqcksvflnekap6.test.com. 86400 IN NSEC3 1 1 1 abcd a5labagjjevr86gh0hf3jg7nufhga5ar CNAME RRSIG
+a5labagjjevr86gh0hf3jg7nufhga5ar.test.com. 86400 IN NSEC3 1 1 1 abcd aovp95mr44hqefrqus6nomsd944bm3vb A RRSIG
+aovp95mr44hqefrqus6nomsd944bm3vb.test.com. 86400 IN NSEC3 1 1 1 abcd b022o9dksaj737fh77e7kqqtj3om56ki A RRSIG
+b022o9dksaj737fh77e7kqqtj3om56ki.test.com. 86400 IN NSEC3 1 1 1 abcd dafc69cv5n2tfcf6ovbvtv94drgmqjo5
+dafc69cv5n2tfcf6ovbvtv94drgmqjo5.test.com. 86400 IN NSEC3 1 1 1 abcd eban51bjgugorb20unp5peec7s5d2eka TXT RRSIG
+eban51bjgugorb20unp5peec7s5d2eka.test.com. 86400 IN NSEC3 1 1 1 abcd h5855rvon2aasm8qv1nk49i1b2mkbejp SRV RRSIG
+h5855rvon2aasm8qv1nk49i1b2mkbejp.test.com. 86400 IN NSEC3 1 1 1 abcd iai9hin25meh689r5v5gtifk8om5di0e A RRSIG
+iai9hin25meh689r5v5gtifk8om5di0e.test.com. 86400 IN NSEC3 1 1 1 abcd igf4m7otecach14p0a6ingi7dbuas5b2 A RRSIG
+igf4m7otecach14p0a6ingi7dbuas5b2.test.com. 86400 IN NSEC3 1 1 1 abcd o1l0fb73hi3qp4a3fnqjsleanlc883i3 A RP RRSIG
+o1l0fb73hi3qp4a3fnqjsleanlc883i3.test.com. 86400 IN NSEC3 1 1 1 abcd plud9qqecuril62gcfp8br44i7eoq7c9 TXT RRSIG
+plud9qqecuril62gcfp8br44i7eoq7c9.test.com. 86400 IN NSEC3 1 1 1 abcd qd81ag9inqts1ocs7api0pji94k27btr SRV RRSIG
+qd81ag9inqts1ocs7api0pji94k27btr.test.com. 86400 IN NSEC3 1 1 1 abcd s6g5shc1jvovl5fl9e943adlonqln7g4 CNAME RRSIG
+s6g5shc1jvovl5fl9e943adlonqln7g4.test.com. 86400 IN NSEC3 1 1 1 abcd sa5vvpqn1coejgj3hbkfekdnii8kksqa
+sa5vvpqn1coejgj3hbkfekdnii8kksqa.test.com. 86400 IN NSEC3 1 1 1 abcd sra2sm4pl136bultass7qqnlblipe8am NAPTR RRSIG
+sra2sm4pl136bultass7qqnlblipe8am.test.com. 86400 IN NSEC3 1 1 1 abcd vlvujatanof6feajoesti9kq4s0crst3 CNAME RRSIG
+test.com. 86400 IN NSEC3PARAM 1 0 1 abcd
+vlvujatanof6feajoesti9kq4s0crst3.test.com. 86400 IN NSEC3 1 1 1 abcd 2eu2gulbu53h9uvhfalshpbo2a83t6l2
--- /dev/null
+#!/bin/sh
+cleandig b.c.test.com TXT dnssec
--- /dev/null
+Check NSECx records if a record is enclosed (above and below) in empty-non-terminals.
--- /dev/null
+1 b.c.test.com. IN NSEC 86400 *.a.b.c.test.com. A RRSIG NSEC
+1 b.c.test.com. IN RRSIG 86400 NSEC 8 4 86400 [expiry] [inception] [keytag] test.com. ...
+1 test.com. IN RRSIG 3600 SOA 8 2 3600 [expiry] [inception] [keytag] test.com. ...
+1 test.com. IN SOA 3600 ns1.test.com. ahu.example.com. 2005092501 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='b.c.test.com.', qtype=TXT
--- /dev/null
+1 a5labagjjevr86gh0hf3jg7nufhga5ar.test.com. IN NSEC3 86400 1 1 1 abcd A5LABAGJJEVR86GH0HF3JG7NUFHGA5AS A RRSIG
+1 a5labagjjevr86gh0hf3jg7nufhga5ar.test.com. IN RRSIG 86400 NSEC3 8 3 86400 [expiry] [inception] [keytag] test.com. ...
+1 test.com. IN RRSIG 3600 SOA 8 2 3600 [expiry] [inception] [keytag] test.com. ...
+1 test.com. IN SOA 3600 ns1.test.com. ahu.example.com. 2005092501 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='b.c.test.com.', qtype=TXT
--- /dev/null
+1 a5labagjjevr86gh0hf3jg7nufhga5ar.test.com. IN NSEC3 86400 1 1 1 abcd AOVP95MR44HQEFRQUS6NOMSD944BM3VB A RRSIG
+1 a5labagjjevr86gh0hf3jg7nufhga5ar.test.com. IN RRSIG 86400 NSEC3 8 3 86400 [expiry] [inception] [keytag] test.com. ...
+1 test.com. IN RRSIG 3600 SOA 8 2 3600 [expiry] [inception] [keytag] test.com. ...
+1 test.com. IN SOA 3600 ns1.test.com. ahu.example.com. 2005092501 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='b.c.test.com.', qtype=TXT
--- /dev/null
+#!/bin/sh
+cleandig c.test.com SOA dnssec
--- /dev/null
+Check if the empty non-terminal exists (SOA query)
--- /dev/null
+1 blah.test.com. IN NSEC 86400 b.c.test.com. NS RRSIG NSEC
+1 blah.test.com. IN RRSIG 86400 NSEC 8 3 86400 [expiry] [inception] [keytag] test.com. ...
+1 test.com. IN RRSIG 3600 SOA 8 2 3600 [expiry] [inception] [keytag] test.com. ...
+1 test.com. IN SOA 3600 ns1.test.com. ahu.example.com. 2005092501 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='c.test.com.', qtype=SOA
--- /dev/null
+1 s6g5shc1jvovl5fl9e943adlonqln7g4.test.com. IN NSEC3 86400 1 1 1 abcd S6G5SHC1JVOVL5FL9E943ADLONQLN7G5
+1 s6g5shc1jvovl5fl9e943adlonqln7g4.test.com. IN RRSIG 86400 NSEC3 8 3 86400 [expiry] [inception] [keytag] test.com. ...
+1 test.com. IN RRSIG 3600 SOA 8 2 3600 [expiry] [inception] [keytag] test.com. ...
+1 test.com. IN SOA 3600 ns1.test.com. ahu.example.com. 2005092501 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='c.test.com.', qtype=SOA
--- /dev/null
+1 s6g5shc1jvovl5fl9e943adlonqln7g4.test.com. IN NSEC3 86400 1 1 1 abcd SA5VVPQN1COEJGJ3HBKFEKDNII8KKSQA
+1 s6g5shc1jvovl5fl9e943adlonqln7g4.test.com. IN RRSIG 86400 NSEC3 8 3 86400 [expiry] [inception] [keytag] test.com. ...
+1 test.com. IN RRSIG 3600 SOA 8 2 3600 [expiry] [inception] [keytag] test.com. ...
+1 test.com. IN SOA 3600 ns1.test.com. ahu.example.com. 2005092501 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='c.test.com.', qtype=SOA
--- /dev/null
+#!/bin/sh
+cleandig something.a.b.c.test.com A dnssec
--- /dev/null
+Check RRSIG label count if there are empty non-terminals involved
--- /dev/null
+0 something.a.b.c.test.com. IN A 3600 8.7.6.5
+0 something.a.b.c.test.com. IN RRSIG 3600 A 8 5 3600 [expiry] [inception] [keytag] test.com. ...
+1 *.a.b.c.test.com. IN NSEC 86400 counter.test.com. A RRSIG NSEC
+1 *.a.b.c.test.com. IN RRSIG 86400 NSEC 8 5 86400 [expiry] [inception] [keytag] test.com. ...
+2 . IN OPT 32768
+Rcode: 0, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='something.a.b.c.test.com.', qtype=A
--- /dev/null
+0 something.a.b.c.test.com. IN A 3600 8.7.6.5
+0 something.a.b.c.test.com. IN RRSIG 3600 A 8 5 3600 [expiry] [inception] [keytag] test.com. ...
+1 qjeirdhb04ir4vbs5pbbhbue69dlq9nr.test.com. IN NSEC3 86400 1 1 1 abcd QJEIRDHB04IR4VBS5PBBHBUE69DLQ9NT
+1 qjeirdhb04ir4vbs5pbbhbue69dlq9nr.test.com. IN RRSIG 86400 NSEC3 8 3 86400 [expiry] [inception] [keytag] test.com. ...
+2 . IN OPT 32768
+Rcode: 0, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='something.a.b.c.test.com.', qtype=A
--- /dev/null
+0 something.a.b.c.test.com. IN A 3600 8.7.6.5
+0 something.a.b.c.test.com. IN RRSIG 3600 A 8 5 3600 [expiry] [inception] [keytag] test.com. ...
+1 qd81ag9inqts1ocs7api0pji94k27btr.test.com. IN NSEC3 86400 1 1 1 abcd S6G5SHC1JVOVL5FL9E943ADLONQLN7G4 CNAME RRSIG
+1 qd81ag9inqts1ocs7api0pji94k27btr.test.com. IN RRSIG 86400 NSEC3 8 3 86400 [expiry] [inception] [keytag] test.com. ...
+2 . IN OPT 32768
+Rcode: 0, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
+Reply to question for qname='something.a.b.c.test.com.', qtype=A
--- /dev/null
+#!/bin/sh
+cleandig c.test.com A dnssec
--- /dev/null
+Check if the empty non-terminal exists (A query)
--- /dev/null
+1 blah.test.com. IN NSEC 86400 b.c.test.com. NS RRSIG NSEC
+1 blah.test.com. IN RRSIG 86400 NSEC 8 3 86400 [expiry] [inception] [keytag] test.com. ...
+1 test.com. IN RRSIG 3600 SOA 8 2 3600 [expiry] [inception] [keytag] test.com. ...
+1 test.com. IN SOA 3600 ns1.test.com. ahu.example.com. 2005092501 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='c.test.com.', qtype=A
--- /dev/null
+1 s6g5shc1jvovl5fl9e943adlonqln7g4.test.com. IN NSEC3 86400 1 1 1 abcd S6G5SHC1JVOVL5FL9E943ADLONQLN7G5
+1 s6g5shc1jvovl5fl9e943adlonqln7g4.test.com. IN RRSIG 86400 NSEC3 8 3 86400 [expiry] [inception] [keytag] test.com. ...
+1 test.com. IN RRSIG 3600 SOA 8 2 3600 [expiry] [inception] [keytag] test.com. ...
+1 test.com. IN SOA 3600 ns1.test.com. ahu.example.com. 2005092501 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='c.test.com.', qtype=A
--- /dev/null
+1 s6g5shc1jvovl5fl9e943adlonqln7g4.test.com. IN NSEC3 86400 1 1 1 abcd SA5VVPQN1COEJGJ3HBKFEKDNII8KKSQA
+1 s6g5shc1jvovl5fl9e943adlonqln7g4.test.com. IN RRSIG 86400 NSEC3 8 3 86400 [expiry] [inception] [keytag] test.com. ...
+1 test.com. IN RRSIG 3600 SOA 8 2 3600 [expiry] [inception] [keytag] test.com. ...
+1 test.com. IN SOA 3600 ns1.test.com. ahu.example.com. 2005092501 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='c.test.com.', qtype=A
0 www.a.b.c.d.e.something.wtest.com. IN A 3600 4.3.2.1
0 www.a.b.c.d.e.something.wtest.com. IN RRSIG 3600 A 8 3 3600 [expiry] [inception] [keytag] wtest.com. ...
-1 pqgjjrj5si55uc1208gt1hp1k217fhqu.wtest.com. IN NSEC3 86400 1 1 1 abcd PQGJJRJ5SI55UC1208GT1HP1K217FHR0 RRSIG
+1 pqgjjrj5si55uc1208gt1hp1k217fhqu.wtest.com. IN NSEC3 86400 1 1 1 abcd PQGJJRJ5SI55UC1208GT1HP1K217FHR0
1 pqgjjrj5si55uc1208gt1hp1k217fhqu.wtest.com. IN RRSIG 86400 NSEC3 8 3 86400 [expiry] [inception] [keytag] wtest.com. ...
2 . IN OPT 32768
Rcode: 0, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
0 www.a.b.c.d.e.wtest.com. IN A 3600 6.7.8.9
0 www.a.b.c.d.e.wtest.com. IN RRSIG 3600 A 8 7 3600 [expiry] [inception] [keytag] wtest.com. ...
-1 pet5iqbgccga60p2n38nmuanrk50papg.wtest.com. IN NSEC3 86400 1 1 1 abcd PET5IQBGCCGA60P2N38NMUANRK50PAPI RRSIG
+1 pet5iqbgccga60p2n38nmuanrk50papg.wtest.com. IN NSEC3 86400 1 1 1 abcd PET5IQBGCCGA60P2N38NMUANRK50PAPI
1 pet5iqbgccga60p2n38nmuanrk50papg.wtest.com. IN RRSIG 86400 NSEC3 8 3 86400 [expiry] [inception] [keytag] wtest.com. ...
2 . IN OPT 32768
Rcode: 0, RD: 0, QR: 1, TC: 0, AA: 1, opcode: 0
1 09lo11rs63u9b3d538a86ijvqcqt9312.minimal.com. IN NSEC3 86400 1 1 1 abcd 09LO11RS63U9B3D538A86IJVQCQT9313 NS SOA RRSIG DNSKEY NSEC3PARAM
-1 8hki26qt36v6qs8cll4e4nvjit38uhap.minimal.com. IN NSEC3 86400 1 1 1 abcd 8HKI26QT36V6QS8CLL4E4NVJIT38UHAR RRSIG
-1 9oadfe8c55evko75kb06spdl23p4fmrh.minimal.com. IN NSEC3 86400 1 1 1 abcd 9OADFE8C55EVKO75KB06SPDL23P4FMRJ RRSIG
+1 8hki26qt36v6qs8cll4e4nvjit38uhap.minimal.com. IN NSEC3 86400 1 1 1 abcd 8HKI26QT36V6QS8CLL4E4NVJIT38UHAR
+1 9oadfe8c55evko75kb06spdl23p4fmrh.minimal.com. IN NSEC3 86400 1 1 1 abcd 9OADFE8C55EVKO75KB06SPDL23P4FMRJ
1 blah.test.com. IN NS 3600 blah.test.com.
-1 blah.test.com. IN NSEC 86400 counter.test.com. NS RRSIG NSEC
+1 blah.test.com. IN NSEC 86400 b.c.test.com. NS RRSIG NSEC
1 blah.test.com. IN RRSIG 86400 NSEC 8 3 86400 [expiry] [inception] [keytag] test.com. ...
2 . IN OPT 32768
2 blah.test.com. IN A 3600 192.168.6.1
1 2eu2gulbu53h9uvhfalshpbo2a83t6l2.test.com. IN NSEC3 86400 1 1 1 abcd 2EU2GULBU53H9UVHFALSHPBO2A83T6L3 NS SOA MX RRSIG DNSKEY NSEC3PARAM
1 2eu2gulbu53h9uvhfalshpbo2a83t6l2.test.com. IN RRSIG 86400 NSEC3 8 3 86400 [expiry] [inception] [keytag] test.com. ...
1 blah.test.com. IN NS 3600 blah.test.com.
-1 s96h2qicbt8d9i5aa43kp8sjjresq4ka.test.com. IN NSEC3 86400 1 1 1 abcd S96H2QICBT8D9I5AA43KP8SJJRESQ4KC A NS RRSIG
+1 s96h2qicbt8d9i5aa43kp8sjjresq4ka.test.com. IN NSEC3 86400 1 1 1 abcd S96H2QICBT8D9I5AA43KP8SJJRESQ4KC
1 s96h2qicbt8d9i5aa43kp8sjjresq4ka.test.com. IN RRSIG 86400 NSEC3 8 3 86400 [expiry] [inception] [keytag] test.com. ...
2 . IN OPT 32768
2 blah.test.com. IN A 3600 192.168.6.1
-1 2eu2gulbu53h9uvhfalshpbo2a83t6l2.test.com. IN NSEC3 86400 1 1 1 abcd 88F1BQRB2ISCVFEL2SQQCKSVFLNEKAP6 NS SOA MX RRSIG DNSKEY NSEC3PARAM
+1 2eu2gulbu53h9uvhfalshpbo2a83t6l2.test.com. IN NSEC3 86400 1 1 1 abcd 79U3DAS6UCCTNS1BR3TVD8QKANNI351L NS SOA MX RRSIG DNSKEY NSEC3PARAM
1 2eu2gulbu53h9uvhfalshpbo2a83t6l2.test.com. IN RRSIG 86400 NSEC3 8 3 86400 [expiry] [inception] [keytag] test.com. ...
1 blah.test.com. IN NS 3600 blah.test.com.
-1 qd81ag9inqts1ocs7api0pji94k27btr.test.com. IN NSEC3 86400 1 1 1 abcd SA5VVPQN1COEJGJ3HBKFEKDNII8KKSQA CNAME RRSIG
-1 qd81ag9inqts1ocs7api0pji94k27btr.test.com. IN RRSIG 86400 NSEC3 8 3 86400 [expiry] [inception] [keytag] test.com. ...
+1 s6g5shc1jvovl5fl9e943adlonqln7g4.test.com. IN NSEC3 86400 1 1 1 abcd SA5VVPQN1COEJGJ3HBKFEKDNII8KKSQA
+1 s6g5shc1jvovl5fl9e943adlonqln7g4.test.com. IN RRSIG 86400 NSEC3 8 3 86400 [expiry] [inception] [keytag] test.com. ...
2 . IN OPT 32768
2 blah.test.com. IN A 3600 192.168.6.1
Rcode: 0, RD: 0, QR: 1, TC: 0, AA: 0, opcode: 0
-1 9fag9508oqu3m22qac0u5eqgg45v8cf0.example.com. IN NSEC3 86400 1 1 1 abcd 9FAG9508OQU3M22QAC0U5EQGG45V8CF2 RRSIG
+1 9fag9508oqu3m22qac0u5eqgg45v8cf0.example.com. IN NSEC3 86400 1 1 1 abcd 9FAG9508OQU3M22QAC0U5EQGG45V8CF2
1 9fag9508oqu3m22qac0u5eqgg45v8cf0.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 kt3ll2fgp7p2s71mk7frk5igi8pc8gl1.example.com. IN NSEC3 86400 1 1 1 abcd KT3LL2FGP7P2S71MK7FRK5IGI8PC8GL3 RRSIG
+1 kt3ll2fgp7p2s71mk7frk5igi8pc8gl1.example.com. IN NSEC3 86400 1 1 1 abcd KT3LL2FGP7P2S71MK7FRK5IGI8PC8GL3
1 kt3ll2fgp7p2s71mk7frk5igi8pc8gl1.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 VTNQ6OCN2VKUIV3NJU14OQTAEN2MT5SL NS SOA MX RRSIG DNSKEY NSEC3PARAM
1 vtnq6ocn2vkuiv3nju14oqtaen2mt5sk.example.com. IN RRSIG 86400 NSEC3 8 3 86400 [expiry] [inception] [keytag] example.com. ...
-1 9fag9508oqu3m22qac0u5eqgg45v8cf0.example.com. IN NSEC3 86400 1 1 1 abcd 9FAG9508OQU3M22QAC0U5EQGG45V8CF2 RRSIG
+1 9fag9508oqu3m22qac0u5eqgg45v8cf0.example.com. IN NSEC3 86400 1 1 1 abcd 9FAG9508OQU3M22QAC0U5EQGG45V8CF2
1 9fag9508oqu3m22qac0u5eqgg45v8cf0.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 sthvu2kihc96kc1tu8v3curr8og5dghn.example.com. IN NSEC3 86400 1 1 1 abcd STHVU2KIHC96KC1TU8V3CURR8OG5DGHP RRSIG
+1 sthvu2kihc96kc1tu8v3curr8og5dghn.example.com. IN NSEC3 86400 1 1 1 abcd STHVU2KIHC96KC1TU8V3CURR8OG5DGHP
1 sthvu2kihc96kc1tu8v3curr8og5dghn.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 VTNQ6OCN2VKUIV3NJU14OQTAEN2MT5SL NS SOA MX RRSIG DNSKEY NSEC3PARAM
1 vtnq6ocn2vkuiv3nju14oqtaen2mt5sk.example.com. IN RRSIG 86400 NSEC3 8 3 86400 [expiry] [inception] [keytag] example.com. ...
-1 368r0s1q794jmkdrcpf6f85v316hd9ak.wtest.com. IN NSEC3 86400 1 1 1 abcd 368R0S1Q794JMKDRCPF6F85V316HD9AM RRSIG
+1 368r0s1q794jmkdrcpf6f85v316hd9ak.wtest.com. IN NSEC3 86400 1 1 1 abcd 368R0S1Q794JMKDRCPF6F85V316HD9AM
1 368r0s1q794jmkdrcpf6f85v316hd9ak.wtest.com. IN RRSIG 86400 NSEC3 8 3 86400 [expiry] [inception] [keytag] wtest.com. ...
1 54njs65s8u96tkffrft6l7j1t1556vik.wtest.com. IN NSEC3 86400 1 1 1 abcd 54NJS65S8U96TKFFRFT6L7J1T1556VIL TXT RRSIG
1 54njs65s8u96tkffrft6l7j1t1556vik.wtest.com. IN RRSIG 86400 NSEC3 8 3 86400 [expiry] [inception] [keytag] wtest.com. ...
1 5uvgfm2vjcje09svs7lfb22i1uuqjf98.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 sdgbafmjek5v4t8c89q9u0n03qmcslor.example.com. IN NSEC3 86400 1 1 1 abcd SDGBAFMJEK5V4T8C89Q9U0N03QMCSLOT RRSIG
+1 sdgbafmjek5v4t8c89q9u0n03qmcslor.example.com. IN NSEC3 86400 1 1 1 abcd SDGBAFMJEK5V4T8C89Q9U0N03QMCSLOT
1 sdgbafmjek5v4t8c89q9u0n03qmcslor.example.com. IN RRSIG 86400 NSEC3 8 3 86400 [expiry] [inception] [keytag] example.com. ...
-1 tsdp8hajlfgr90cv4ib634g1m25nc5up.example.com. IN NSEC3 86400 1 1 1 abcd TSDP8HAJLFGR90CV4IB634G1M25NC5UR RRSIG
+1 tsdp8hajlfgr90cv4ib634g1m25nc5up.example.com. IN NSEC3 86400 1 1 1 abcd TSDP8HAJLFGR90CV4IB634G1M25NC5UR
1 tsdp8hajlfgr90cv4ib634g1m25nc5up.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
1 5uvgfm2vjcje09svs7lfb22i1uuqjf98.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 k6ta8mhi455hk3jskn0b2st81j6fa1l0.example.com. IN NSEC3 86400 1 1 1 abcd K6TA8MHI455HK3JSKN0B2ST81J6FA1L2 RRSIG
+1 k6ta8mhi455hk3jskn0b2st81j6fa1l0.example.com. IN NSEC3 86400 1 1 1 abcd K6TA8MHI455HK3JSKN0B2ST81J6FA1L2
1 k6ta8mhi455hk3jskn0b2st81j6fa1l0.example.com. IN RRSIG 86400 NSEC3 8 3 86400 [expiry] [inception] [keytag] example.com. ...
-1 tsdp8hajlfgr90cv4ib634g1m25nc5up.example.com. IN NSEC3 86400 1 1 1 abcd TSDP8HAJLFGR90CV4IB634G1M25NC5UR RRSIG
+1 tsdp8hajlfgr90cv4ib634g1m25nc5up.example.com. IN NSEC3 86400 1 1 1 abcd TSDP8HAJLFGR90CV4IB634G1M25NC5UR
1 tsdp8hajlfgr90cv4ib634g1m25nc5up.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
read l
fi
kill $(cat pdns*.pid)
-rm pdns*.pid
\ No newline at end of file
+rm pdns*.pid
very-long-txt IN TXT "A very long TXT record! boy you won't believe how long. A very long TXT record! boy you won't believe how long. A very long TXT record! boy you won't believe how long. A very long TXT record! boy you won't believe how long. A very long TXT record! boy you won't believe how long!"
within-server IN CNAME outpost.example.com.
_underscore IN TXT "underscores are terrible"
+b.c IN A 5.6.7.8
+*.a.b.c IN A 8.7.6.5
-1 9fag9508oqu3m22qac0u5eqgg45v8cf0.example.com. IN NSEC3 86400 1 1 1 abcd 9FAG9508OQU3M22QAC0U5EQGG45V8CF2 RRSIG
+1 9fag9508oqu3m22qac0u5eqgg45v8cf0.example.com. IN NSEC3 86400 1 1 1 abcd 9FAG9508OQU3M22QAC0U5EQGG45V8CF2
1 9fag9508oqu3m22qac0u5eqgg45v8cf0.example.com. IN RRSIG 86400 NSEC3 8 3 86400 [expiry] [inception] [keytag] example.com. ...
-1 ectnliqstqsjnnrpuhjj5h0j3c3odkk3.example.com. IN NSEC3 86400 1 1 1 abcd ECTNLIQSTQSJNNRPUHJJ5H0J3C3ODKK5 RRSIG
+1 ectnliqstqsjnnrpuhjj5h0j3c3odkk3.example.com. IN NSEC3 86400 1 1 1 abcd ECTNLIQSTQSJNNRPUHJJ5H0J3C3ODKK5
1 ectnliqstqsjnnrpuhjj5h0j3c3odkk3.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 2eu2gulbu53h9uvhfalshpbo2a83t6l2.test.com. IN NSEC3 86400 1 1 1 abcd 2EU2GULBU53H9UVHFALSHPBO2A83T6L3 NS SOA MX RRSIG DNSKEY NSEC3PARAM
-1 npce7etkesd3umcst08psfape1cnno5o.test.com. IN NSEC3 86400 1 1 1 abcd NPCE7ETKESD3UMCST08PSFAPE1CNNO5Q RRSIG
-1 nqf0papl2qmp38upr87f930kmebc0o0n.test.com. IN NSEC3 86400 1 1 1 abcd NQF0PAPL2QMP38UPR87F930KMEBC0O0P RRSIG
+1 npce7etkesd3umcst08psfape1cnno5o.test.com. IN NSEC3 86400 1 1 1 abcd NPCE7ETKESD3UMCST08PSFAPE1CNNO5Q
+1 nqf0papl2qmp38upr87f930kmebc0o0n.test.com. IN NSEC3 86400 1 1 1 abcd NQF0PAPL2QMP38UPR87F930KMEBC0O0P
-1 2eu2gulbu53h9uvhfalshpbo2a83t6l2.test.com. IN NSEC3 86400 1 1 1 abcd 88F1BQRB2ISCVFEL2SQQCKSVFLNEKAP6 NS SOA MX RRSIG DNSKEY NSEC3PARAM
+1 2eu2gulbu53h9uvhfalshpbo2a83t6l2.test.com. IN NSEC3 86400 1 1 1 abcd 79U3DAS6UCCTNS1BR3TVD8QKANNI351L NS SOA MX RRSIG DNSKEY NSEC3PARAM
1 igf4m7otecach14p0a6ingi7dbuas5b2.test.com. IN NSEC3 86400 1 1 1 abcd O1L0FB73HI3QP4A3FNQJSLEANLC883I3 A RP RRSIG