if(!d_dnssecQueries)
return false;
char output[1024];
+
snprintf(output, sizeof(output)-1, d_nullifyOrderNameAndUpdateAuthQuery.c_str(), auth, domain_id, sqlEscape(qname).c_str());
try {
d_db->doCommand(output);
if(!d_dnssecQueries)
return false;
char output[1024];
+
snprintf(output, sizeof(output)-1, d_nullifyOrderNameAndAuthQuery.c_str(), sqlEscape(qname).c_str(), sqlEscape(type).c_str(), domain_id);
try {
d_db->doCommand(output);
bool GSQLBackend::replaceRRSet(uint32_t domain_id, const string& qname, const QType& qt, const vector<DNSResourceRecord>& rrset)
{
- string deleteQuery;
+ string deleteQuery;
string deleteRRSet;
if (qt != QType::ANY) {
deleteRRSet = "delete from records where domain_id = %d and name='%s' and type='%s'";
::arg().set("recursor","If recursion is desired, IP address of a recursing nameserver")="no";
::arg().set("allow-recursion","List of subnets that are allowed to recurse")="0.0.0.0/0";
::arg().set("pipebackend-abi-version","Version of the pipe backend ABI")="1";
+
::arg().set("udp-truncation-threshold", "Maximum UDP response size before we truncate")="1680";
::arg().set("disable-tcp","Do not listen to TCP queries")="no";
::arg().set("disable-axfr","Do not allow zone transfers")="no";
S.declare("rfc2136-refused", "RFC2136 packets that are refused.");
S.declare("rfc2136-changes", "RFC2136 changes to records in total.");
-
S.declare("servfail-packets","Number of times a server-failed packet was sent out");
S.declare("latency","Average number of microseconds needed to answer a question");
S.declare("timedout-packets","Number of packets which weren't answered within timeout set");
ar & d_place;
ar & auth;
}
-
+
bool operator==(const DNSResourceRecord& rhs);
bool operator<(const DNSResourceRecord &b) const
bool DNSPacket::s_doEDNSSubnetProcessing;
uint16_t DNSPacket::s_udpTruncationThreshold;
-
-DNSPacket::DNSPacket()
+
+DNSPacket::DNSPacket()
{
d_wrapped=false;
d_compress=true;
// For section 3.2.3, we do need content so we need to get it properly. But only for the correct Qclasses.
if (oc == Opcode::Update && dr.d_place == DNSRecord::Answer && dr.d_class != 1)
return new UnknownRecordContent(dr, pr);
-
+
uint16_t searchclass = (dr.d_type == QType::OPT) ? 1 : dr.d_class; // class is invalid for OPT
typemap_t::const_iterator i=getTypemap().find(make_pair(searchclass, dr.d_type));
{
string lcontent=toLower(content);
string rcontent=toLower(rhs.content);
-
+
string llabel=toLower(qname);
string rlabel=toLower(rhs.qname);
-
- return
+
+ return
tie(llabel, qtype, lcontent, ttl, priority) ==
tie(rlabel, rhs.qtype, rcontent, rhs.ttl, rhs.priority);
}
qname = p.d_label;
if(!qname.empty())
boost::erase_tail(qname, 1); // strip .
-
+
qtype = p.d_type;
ttl = p.d_ttl;
priority=0;
dw.xfrLabel(keyname, false);
dw.xfr16BitInt(0xff); // class
dw.xfr32BitInt(0); // TTL
- dw.xfrLabel(toLower(trc.d_algoName), false);
+ dw.xfrLabel(toLower(trc.d_algoName), false);
}
uint32_t now = trc.d_time;
<term>ALLOW-2136-FROM</term>
<listitem>
<para>
- This setting has the same function as described in the configuration options (See <xref linkend="rfc2136-configuration" />).
- Only one item is allowed per row, but multiple rows can be added.
+ This setting has the same function as described in the configuration options (See <xref linkend="rfc2136-configuration" />).
+ Only one item is allowed per row, but multiple rows can be added.
An example:
<programlisting>
sql> select id from domains where name='powerdnssec.org';
sql> insert into domainmetadata(domain_id, kind, content) values(5, ‘ALLOW-2136-FROM’,’10.0.0.0/8’);
sql> insert into domainmetadata(domain_id, kind, content) values(5, ‘ALLOW-2136-FROM’,’192.168.1.2/32’);
</programlisting>
-
+
This will allow 10.0.0.0/8 and 192.168.1.2/32 to send RFC2136 update messages for the powerdnssec.org domain.
</para>
</listitem>
5
sql> insert into domainmetadata (domain_id, kind, content) values (5, 'TSIG-ALLOW-2136', 'test');
</programlisting>
-
+
<para>An example of how to use a TSIG key with the <command>nsupdate</command> command:</para>
<programlisting>
-nsupdate <<!
+nsupdate <<!
server <ip> <port>
zone powerdnssec.org
update add test1.powerdnssec.org 3600 A 192.168.1.1
!
</programlisting>
<para>
- If a TSIG key is set for the domain, it is required to be used for the update.
+ If a TSIG key is set for the domain, it is required to be used for the update.
The TSIG is extra security on top of the <command>ALLOW-2136-FROM</command> setting.
If a TSIG key is set, the IP(-range) still needs to be allowed via <command>ALLOW-2136-FROM</command>.
</para>
5
sql> insert into domainmetadata(domain_id, kind, content) values(5, ‘FORWARD-2136’,’’);
</programlisting>
-
+
There is no content, the existance of the entry enables the forwarding.
This domain-specific setting is only useful when the configuration option <command>forward-2136</command> is set to 'no', as that will disable it globally.
Using the domainmetadata setting than allows you to enable it per domain.
<term>DEFAULT</term>
<listitem>
<para>
- Generate a soa serial of YYYYMMDD01. If the current serial is lower than the generated serial,
+ Generate a soa serial of YYYYMMDD01. If the current serial is lower than the generated serial,
use the generated serial. If the current serial is higher or equal to the generated serial, increase the
current serial by 1.
</para>
<term>SOA-EDIT-INCREASE</term>
<listitem>
<para>
- Change the serial to whatever SOA-EDIT would provide. If what SOA-EDIT provides is lower than the current serial,
+ Change the serial to whatever SOA-EDIT would provide. If what SOA-EDIT provides is lower than the current serial,
increase the current serial by 1.
</para>
</listitem>
-rw------- 1 root root 53 Aug 26 19:29 Kdhcpdupdate.+157+20493.key
-rw------- 1 root root 165 Aug 26 19:29 Kdhcpdupdate.+157+20493.private
-# cat Kdhcpdupdate.+157+20493.key
+# cat Kdhcpdupdate.+157+20493.key
dhcpdupdate. IN KEY 0 3 157 FYhvwsW1ZtFZqWzsMpqhbg==
</programlisting>
The important bits are the name of the key (<command>dhcpdupdate</command>) and the hash of the key (<command>FYhvwsW1ZtFZqWzsMpqhbg==</command>
ddns-rev-domainname "in-addr.arpa.";
zone powerdnssec.org {
- primary 127.0.0.1;
+ primary 127.0.0.1;
key dhcpdupdate;
}
<sect2 id="rfc2136-howto-powerdns"><title>Setting up PowerDNS</title>
<para>A number of small changes are needed to powerdns to make it accept dynamic updates from <command>dhcpd</command>.</para>
<para>
- Enabled RFC2136 (dynamic update) support functionality in PowerDNS by adding the following to the
+ Enabled RFC2136 (dynamic update) support functionality in PowerDNS by adding the following to the
PowerDNS configuration file (pdns.conf).
<programlisting>
experimental-rfc2136=yes
</orderedlist>
</para>
<para>
- We just told powerdns (via the configuration file) that we accept updates from nobody via the
+ We just told powerdns (via the configuration file) that we accept updates from nobody via the
<command>allow-2136-from</command> parameter. That's not very useful, so we're going to give permissions
per zone, via the domainmetadata table.
<programlisting>
<orderedlist>
<listitem><para>Add the 'dhcpdupdate' key to our PowerDNSinstallation</para></listitem>
<listitem><para>Associate the domains with the given TSIG key</para></listitem>
- </orderedlist>
+ </orderedlist>
</para>
<para>Restart PowerDNS and you should be ready to go!</para>
- </sect2>
+ </sect2>
</sect1>
-
+
<sect1 id="rfc2136-how-it-works"><title>How it works</title>
<para>This is a short description of how RFC2136 (update) messages are processed by PowerDNS.</para>
<para>
<orderedlist>
<listitem><para>
- The RFC2136 message is received. If it is TSIG signed, the TSIG is validated against the tsigkeys table.
+ The RFC2136 message is received. If it is TSIG signed, the TSIG is validated against the tsigkeys table.
If it is not valid, Refused is returned to the requestor.
</para></listitem>
<listitem><para>A check is performed on the zone to see if it is a valid zone. ServFail is returned when not valid.</para></listitem>
If the requestor (sender of the update message) does not match the values in <command>ALLOW-2136-FROM</command>, Refused is returned.
</para></listitem>
<listitem><para>
- If the message is TSIG signed, the TSIG keyname is compared with the TSIG keyname in domainmetadata. If they do not match, a Refused is send.
+ If the message is TSIG signed, the TSIG keyname is compared with the TSIG keyname in domainmetadata. If they do not match, a Refused is send.
The TSIG-ALLOW-2136 domainmetadata setting is used to find which key belongs to the domain.
</para></listitem>
<listitem><para>The backends are queried to find the backend for the given domain.</para></listitem>
</para></listitem>
<listitem><para>
Per record in the update message, a the prescan checks are performed. If the prescan fails, the corresponding RCode is returned.
- If the prescan for the record is correct, the actual update/delete/modify of the record is performed.
+ If the prescan for the record is correct, the actual update/delete/modify of the record is performed.
If the update fails (for whatever reason), ServFail is returned.
After changes to the records have been applied, the ordername and auth flag are set to make sure DNSSEC remains working.
The cache for that record is purged.
<sect1 id="rfc2136-backend"><title>RFC2136 support</title>
<para>
- To make your backend RFC2136 compatible, it needs to implement a number of new functions and functions already used for slave-operation.
+ To make your backend RFC2136 compatible, it needs to implement a number of new functions and functions already used for slave-operation.
The new functions are not RFC2136 specific and might be used for other update/remove functionality at a later stage.
<programlisting>
class DNSBackend {
</programlisting>
</para>
<para>
-
+
</para>
<para>
<variablelist>
<term>virtual bool startTransaction(const string &qname, int id);</term>
<listitem>
<para>
- See <xref linkend="rw-backends" />. Please note that this function now receives a negative number (-1), which indicates that
+ See <xref linkend="rw-backends" />. Please note that this function now receives a negative number (-1), which indicates that
the current zone data should NOT be deleted.
</para>
</listitem>
<term>virtual bool listSubZone(const string &name, int domain_id);</term>
<listitem>
<para>
- This method is needed for rectification of a zone after NS-records have been added. For DNSSEC, we need to know which records
+ This method is needed for rectification of a zone after NS-records have been added. For DNSSEC, we need to know which records
are below the currently added record.
<function>listSubZone()</function> is used like <function>list()</function> which means PowerDNS will call <function>get()</function>
after this method.
// First %s is 'sub.zone.com', second %s is '*.sub.zone.com'
select content,ttl,prio,type,domain_id,name from records where (name='%s' OR name like '%s') and domain_id=%d
</programlisting>
- The method is not only used when adding records, but also to correct ENT-records in powerdns. Make sure it returns every record in the tree
+ The method is not only used when adding records, but also to correct ENT-records in powerdns. Make sure it returns every record in the tree
below the given record.
</para>
</listitem>
<term>virtual bool replaceRRSet(uint32_t domain_id, const string& qname, const QType& qt, const vector<DNSResourceRecord>& rrset);</term>
<listitem>
<para>
- This method should remove all the records with <function>qname</function> of type <function>qt</function>. <function>qt</function>
- might also be ANY, which means all the records with that <function>qname</function> need to be removed.
- After removal, the records in <function>rrset</function> must be added to the zone. <function>rrset</function> can be empty in which case the method is used to remove a RRset.
+ This method should remove all the records with <function>qname</function> of type <function>qt</function>. <function>qt</function>
+ might also be ANY, which means all the records with that <function>qname</function> need to be removed.
+ After removal, the records in <function>rrset</function> must be added to the zone. <function>rrset</function> can be empty in which case the method is used to remove a RRset.
</para>
</listitem>
</varlistentry>
*d_statnumentries=d_map.size();
return delcount;
}
-
// called from ueberbackend
bool PacketCache::getEntry(const string &qname, const QType& qtype, CacheEntryType cet, string& value, int zoneID, bool meritsRecursion,
unsigned int maxReplyLen, bool dnssecOk, bool hasEDNS)
L<<Logger::Error<<"Received a TSIG signed message with a non-validating key"<<endl;
// RFC3007 describes that a non-secure message should be sending Refused for DNS Updates
if (p->d.opcode == Opcode::Update)
- r->setRcode(RCode::Refused);
- else
+ r->setRcode(RCode::Refused);
+ else
r->setRcode(RCode::NotAuth);
return r;
}
bool QType::isSupportedType() {
for(vector<namenum>::iterator pos=names.begin();pos<names.end();++pos)
- if(pos->second==code)
+ if(pos->second==code)
return true;
return false;
}
code == QType::MAILA ||
code == QType::MAILB ||
code == QType::TSIG ||
- code == QType::IXFR)
+ code == QType::IXFR)
return true;
return false;
}
-
uint16_t QType::getCode() const
{
return code;
static int chartocode(const char *p); //!< convert a character string to a code
// more solaris fun
-#undef DS
- enum typeenum {A=1,NS=2, CNAME=5, SOA=6, MR=9, PTR=12, HINFO=13, MX=15, TXT=16, RP=17, AFSDB=18, SIG=24, KEY=25, AAAA=28, LOC=29, SRV=33, NAPTR=35, KX=36,
+#undef DS
+ enum typeenum {A=1, NS=2, CNAME=5, SOA=6, MR=9, PTR=12, HINFO=13, MX=15, TXT=16, RP=17, AFSDB=18, SIG=24, KEY=25, AAAA=28, LOC=29, SRV=33, NAPTR=35, KX=36,
CERT=37, A6=38, OPT=41, DS=43, SSHFP=44, IPSECKEY=45, RRSIG=46, NSEC=47, DNSKEY=48, DHCID=49, NSEC3=50, NSEC3PARAM=51,
TLSA=52, SPF=99, EUI48=108, EUI64=109, TSIG=250, IXFR=251, AXFR=252, MAILB=253, MAILA=254, ANY=255, URL=256, MBOXFW=257, CURL=258, ADDR=259, DLV=32769} types;
- typedef pair<string,uint16_t> namenum;
+ typedef pair<string,uint16_t> namenum;
static vector<namenum> names;
inline bool operator==(const QType &comp) const {
init()
{
- qtype_insert("A",1);
- qtype_insert("NS",2);
- qtype_insert("CNAME",5);
- qtype_insert("SOA",6);
- qtype_insert("MR",9);
- qtype_insert("PTR",12);
- qtype_insert("HINFO",13);
- qtype_insert("MINFO",14);
- qtype_insert("MX",15);
- qtype_insert("TXT",16);
- qtype_insert("RP",17);
+ qtype_insert("A", 1);
+ qtype_insert("NS", 2);
+ qtype_insert("CNAME", 5);
+ qtype_insert("SOA", 6);
+ qtype_insert("MR", 9);
+ qtype_insert("PTR", 12);
+ qtype_insert("HINFO", 13);
+ qtype_insert("MINFO", 14);
+ qtype_insert("MX", 15);
+ qtype_insert("TXT", 16);
+ qtype_insert("RP", 17);
qtype_insert("AFSDB", 18);
qtype_insert("SIG", 24);
qtype_insert("KEY", 25);
qtype_insert("SPF", 99);
qtype_insert("EUI48", 108);
qtype_insert("EUI64", 109);
- qtype_insert("TSIG", 250);
+// qtype_insert("TSIG", 250);
qtype_insert("IXFR", 251);
qtype_insert("AXFR", 252);
qtype_insert("MAILB", 253);
throw ResolverException(string("resolver: received an answer to another question (")+mdp.d_qname+"!="+ origQname+".)");
}
- vector<DNSResourceRecord> ret;
+ vector<DNSResourceRecord> ret;
DNSResourceRecord rr;
- for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) {
+ for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) {
rr.qname = i->first.d_label;
if(!rr.qname.empty())
boost::erase_tail(rr.qname, 1); // strip .
rr.ttl = i->first.d_ttl;
rr.content = i->first.d_content->getZoneRepresentation();
rr.priority = 0;
-
+
uint16_t qtype=rr.qtype.getCode();
if(!rr.content.empty() && (qtype==QType::MX || qtype==QType::NS || qtype==QType::CNAME))
foundRecord=true;
}
- // Section 3.2.1
- if (rr->d_class == QClass::ANY && !foundRecord) {
- if (rr->d_type == QType::ANY)
+ // Section 3.2.1
+ if (rr->d_class == QClass::ANY && !foundRecord) {
+ if (rr->d_type == QType::ANY)
return RCode::NXDomain;
if (rr->d_type != QType::ANY)
return RCode::NXRRSet;
- }
+ }
// Section 3.2.2
if (rr->d_class == QClass::NONE && foundRecord) {
// Method implements section 3.4.1 of RFC2136
int PacketHandler::checkUpdatePrescan(const DNSRecord *rr) {
// The RFC stats that d_class != ZCLASS, but we only support the IN class.
- if (rr->d_class != QClass::IN && rr->d_class != QClass::NONE && rr->d_class != QClass::ANY)
+ if (rr->d_class != QClass::IN && rr->d_class != QClass::NONE && rr->d_class != QClass::ANY)
return RCode::FormErr;
QType qtype = QType(rr->d_type);
if (rr->d_class == QClass::ANY && rr->d_clen != 0)
return RCode::FormErr;
-
+
if (qtype.isMetadataType())
return RCode::FormErr;
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;
+ return 0;
}
if (!isPresigned && ((!::arg().mustDo("experimental-direct-dnskey") && rrType == QType::DNSKEY) || rrType == QType::RRSIG)) {
rrset.push_back(rec);
foundRecord = true;
}
-
+
if (foundRecord) {
if (rrType == QType::SOA) { // SOA updates require the serial to be higher than the current
SOAData sdOld, sdUpdate;
bool auth = rrset.front().auth;
if(*haveNSEC3) {
string hashed;
- if(! *narrow)
+ if(! *narrow)
hashed=toLower(toBase32Hex(hashQNameWithSalt(ns3pr->d_iterations, ns3pr->d_salt, rrLabel)));
if (*narrow)
if (pdns_iequals(di->zone, shorter))
break;
-
+
bool foundShorter = false;
di->backend->lookup(QType(QType::ANY), shorter);
while (di->backend->get(rec)) {
if(*haveNSEC3)
{
string hashed;
- if(! *narrow)
+ if(! *narrow)
hashed=toLower(toBase32Hex(hashQNameWithSalt(ns3pr->d_iterations, ns3pr->d_salt, rrLabel)));
-
+
if (*narrow)
di->backend->nullifyDNSSECOrderNameAndUpdateAuth(di->id, rrLabel, auth);
else
if(!auth)
{
- if (ns3pr->d_flags)
+ if (ns3pr->d_flags)
di->backend->nullifyDNSSECOrderNameAndAuth(di->id, rrLabel, "NS");
di->backend->nullifyDNSSECOrderNameAndAuth(di->id, rrLabel, "A");
di->backend->nullifyDNSSECOrderNameAndAuth(di->id, rrLabel, "AAAA");
// If we insert an NS, all the records below it become non auth - so, we're inserting a delegate.
- // Auth can only be false when the rrLabel is not the zone
+ // Auth can only be false when the rrLabel is not the zone
if (auth == false && rrType == QType::NS) {
DLOG(L<<msgPrefix<<"Going to fix auth flags below "<<rrLabel<<endl);
insnonterm.clear(); // No ENT's are needed below delegates (auth=0)
for(vector<string>::const_iterator qname=qnames.begin(); qname != qnames.end(); ++qname) {
if(*haveNSEC3) {
string hashed;
- if(! *narrow)
+ if(! *narrow)
hashed=toLower(toBase32Hex(hashQNameWithSalt(ns3pr->d_iterations, ns3pr->d_salt, *qname)));
-
+
if (*narrow)
di->backend->nullifyDNSSECOrderNameAndUpdateAuth(di->id, rrLabel, auth);
else
}
} // rr->d_class == QClass::IN
-
+
// Delete records - section 3.4.2.3 and 3.4.2.4 with the exception of the 'always leave 1 NS rule' as that's handled by
// 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<<"Deleting NSEC3PARAM from zone, resetting ordernames."<<endl;
+ L<<Logger::Notice<<msgPrefix<<"Deleting NSEC3PARAM from zone, resetting ordernames."<<endl;
if (rr->d_class == QClass::ANY)
d_dk.unsetNSEC3PARAM(rrLabel);
else if (rr->d_class == QClass::NONE) {
d_dk.unsetNSEC3PARAM(rrLabel);
else
return 0;
- } else
+ } else
return 0;
// We retrieve new values, other RR's in this update package might need it as well.
for (vector<string>::const_iterator changeRec=updateAuthFlag.begin(); changeRec!=updateAuthFlag.end(); ++changeRec) {
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);
}
else // NSEC
// if we delete b.c.d.e.test.com, we go up to d.e.test.com and then find b.d.e.test.com because that's below d.e.test.com.
// At that point we can stop deleting ENT's because the tree is in tact again.
di->backend->listSubZone(shorter, di->id);
-
+
while (di->backend->get(rec)) {
if (rec.qtype.getCode())
foundRealRR = true;
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, true);
}
uint16_t len=htons(forwardPacket.getString().length());
string buffer((const char*)&len, 2);
buffer.append(forwardPacket.getString());
- if(write(sock, buffer.c_str(), buffer.length()) < 0) {
+ if(write(sock, buffer.c_str(), buffer.length()) < 0) {
L<<Logger::Error<<msgPrefix<<"Unable to forward update message to "<<remote.toStringWithPort()<<", error:"<<stringerror()<<endl;
continue;
}
int PacketHandler::processUpdate(DNSPacket *p) {
if (! ::arg().mustDo("experimental-rfc2136"))
return RCode::Refused;
-
+
string msgPrefix="UPDATE (" + itoa(p->d.id) + ") from " + p->getRemote() + " for " + p->qdomain + ": ";
L<<Logger::Info<<msgPrefix<<"Processing started."<<endl;
// Check permissions - IP based
vector<string> allowedRanges;
B.getDomainMetadata(p->qdomain, "ALLOW-2136-FROM", allowedRanges);
- if (! ::arg()["allow-2136-from"].empty())
+ if (! ::arg()["allow-2136-from"].empty())
stringtok(allowedRanges, ::arg()["allow-2136-from"], ", \t" );
NetmaskGroup ng;
for(vector<string>::const_iterator i=allowedRanges.begin(); i != allowedRanges.end(); i++)
ng.addMask(*i);
-
+
if ( ! ng.match(&p->d_remote)) {
L<<Logger::Error<<msgPrefix<<"Remote not listed in allow-2136-from or domainmetadata. Sending REFUSED"<<endl;
return RCode::Refused;
B.getDomainMetadata(p->qdomain, "TSIG-ALLOW-2136", tsigKeys);
if (tsigKeys.size() > 0) {
bool validKey = false;
-
+
TSIGRecordContent trc;
string inputkey, message;
if (! p->getTSIGDetails(&trc, &inputkey, &message)) {
L<<Logger::Warning<<msgPrefix<<"TSIG is provided, but domain is not secured with TSIG. Processing continues"<<endl;
// RFC2136 uses the same DNS Header and Message as defined in RFC1035.
- // This means we can use the MOADNSParser to parse the incoming packet. The result is that we have some different
+ // This means we can use the MOADNSParser to parse the incoming packet. The result is that we have some different
// variable names during the use of our MOADNSParser.
MOADNSParser mdp(p->getString());
if (mdp.d_header.qdcount != 1) {
L<<Logger::Warning<<msgPrefix<<"Zone Count is not 1, sending FormErr"<<endl;
return RCode::FormErr;
- }
+ }
if (p->qtype.getCode() != QType::SOA) { // RFC2136 2.3 - ZTYPE must be SOA
L<<Logger::Warning<<msgPrefix<<"Query ZTYPE is not SOA, sending FormErr"<<endl;
if (di.kind == DomainInfo::Slave)
return forwardPacket(msgPrefix, p, &di);
- // Check if all the records provided are within the zone
+ // Check if all the records provided are within the zone
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, so it does not pass the endOn validation.
- if (! (rr->d_place == DNSRecord::Answer || rr->d_place == DNSRecord::Nameserver))
+ if (! (rr->d_place == DNSRecord::Answer || rr->d_place == DNSRecord::Nameserver))
continue;
string label = stripDot(rr->d_label);
return RCode::NotImp;
}
- // 3.2.1 and 3.2.2 - Prerequisite check
+ // 3.2.1 and 3.2.2 - Prerequisite check
for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i != mdp.d_answers.end(); ++i) {
const DNSRecord *rr = &i->first;
if (rr->d_place == DNSRecord::Answer) {
di.backend->abortTransaction();
return res;
}
- }
+ }
}
// 3.2.3 - Prerequisite check - this is outside of updatePrequisitesCheck because we check an RRSet and not the RR.
const DNSRecord *rr = &i->first;
if (rr->d_place == DNSRecord::Answer) {
// Last line of 3.2.3
- if (rr->d_class != QClass::IN && rr->d_class != QClass::NONE && rr->d_class != QClass::ANY)
+ if (rr->d_class != QClass::IN && rr->d_class != QClass::NONE && rr->d_class != QClass::ANY)
return RCode::FormErr;
if (rr->d_class == QClass::IN) {
foundRR++;
for(rrVector_t::iterator rrItem=vec->begin(); rrItem != vec->end(); ++rrItem) {
rrItem->ttl = rec.ttl; // The compare one line below also compares TTL, so we make them equal because TTL is not user within prerequisite checks.
- if (*rrItem == rec)
+ if (*rrItem == rec)
matchRR++;
}
}
bool updatedSerial=false;
NSEC3PARAMRecordContent ns3pr;
- bool narrow=false;
+ bool narrow=false;
bool haveNSEC3 = d_dk.getNSEC3PARAM(di.zone, &ns3pr, &narrow);
bool isPresigned = d_dk.isPresigned(di.zone);
L<<Logger::Error<<msgPrefix<<"Failed to commit updates!"<<endl;
return RCode::ServFail;
}
-
+
S.deposit("rfc2136-changes", changedRecords);
// Purge the records!
else
soa2Update.serial = newser;
}
-
+
newRec.content = serializeSOAData(soa2Update);
vector<DNSResourceRecord> rrset;
cleandig host-1.test.dyndns ANY
# check if the record exists, should result in an NXRRSET (section 3.2.1)
-# if the check fails, it will delete a record.
+# if the check fails, it will delete a record.
cleannsupdate <<!
server $nameserver $port
zone test.dyndns
cleannsupdate <<!
server $nameserver $port
zone test.dyndns
-prereq yxdomain host.test.dyndns
+prereq yxdomain host.test.dyndns
send
answer
!
This test checks section 3.2.1 and 3.2.3 of RFC2136, which is the prerequisite section.
-This test also checks to see what happens when a backend does NOT support RFC2136.
+This test also checks to see what happens when a backend does NOT support RFC2136.
This test performs a simple add and delete of a A and TXT record. This is typically with ISC's DHCPD does.
-The interesting thing is the case-sensativity, as hosts can have capital letters in them (it's how you configure the dhcpd's client machine).
+The interesting thing is the case-sensativity, as hosts can have capital letters in them (it's how you configure the dhcpd's client machine).
#!/bin/sh
#check if the cname exists
-cleandig cname3.test.dyndns CNAME hidesoadetails
+cleandig cname3.test.dyndns CNAME hidesoadetails
# add mx record
cleannsupdate <<!
!
# check if the record was deleted.
-cleandig cname3.test.dyndns CNAME hidesoadetails
+cleandig cname3.test.dyndns CNAME hidesoadetails
A test to see if RFC2136 add and delete record works properly on an MX record,
-this is interesting because the priority is stored seperately in powerdns and
+this is interesting because the priority is stored seperately in powerdns and
it is part of the RDATA.
#!/bin/sh
# check if add-delete.test.dyndns exists. It should not.
-cleandig abc.add-delete.test.dyndns ANY hidesoadetails
+cleandig abc.add-delete.test.dyndns ANY hidesoadetails
# add a record
cleannsupdate <<!
-This test tries to add a bogus record. It's an invalid record because not all the
+This test tries to add a bogus record. It's an invalid record because not all the
specifications have been met. (no type, etc). The test is using DNS::Update from perl
because nsupdate does not allow you to send bogus records.
my $res = Net::DNS::Resolver->new;
$res->nameservers($ARGV[0]);
$res->port($ARGV[1]);
-
+
my $reply = $res->send($update);
-
+
if ($reply) {
print "RCODE: ", $reply->header->rcode, "\n";
} else {
server $nameserver $port
zone test.dyndns
update add c.host.test.dyndns 3600 NS ns1.c.host.test.dyndns
-update add ns1.c.host.test.dyndns 3600 A 192.168.0.1
+update add ns1.c.host.test.dyndns 3600 A 192.168.0.1
send
answer
!
answer
!
-mysqldiff 3 "Check if we are back to normal"
+mysqldiff 3 "Check if we are back to normal"
cleandig a.host.test.dyndns ANY dnssec hidesoadetails
cleandig b.host.test.dyndns ANY dnssec hidesoadetails
update add ns1.delegate2.test.dyndns 3600 A 127.0.0.1
update add ns2.delegate2.test.dyndns 3600 A 127.0.0.1
update add delegate2.test.dyndns 3600 NS ns1.delegate2.test.dyndns
-update add delegate2.test.dyndns 3600 NS ns2.example.com
+update add delegate2.test.dyndns 3600 NS ns2.example.com
send
answer
!
cleandig delegate2.test.dyndns ANY
-mysqldiff 2 'Check delegate2 added correctly'
+mysqldiff 2 'Check delegate2 added correctly'
cleannsupdate <<!
server $nameserver $port
server $nameserver $port
zone test.dyndns
update delete ns1.delegate2.test.dyndns A
-update delete ns2.delegate2.test.dyndns A
+update delete ns2.delegate2.test.dyndns A
update delete ns1.delegate1.test.dyndns A
update delete ns2.delegate1.test.dyndns A
send
!
#check if it exists
-cleandig test.dyndns MX
+cleandig test.dyndns MX
# remove a MX record, with the wrong priority, so this should not match.
cleannsupdate <<!
cleannsupdate <<!
server $nameserver $port
zone test.dyndns
-update delete test.dyndns. 3600 NS ns1.test.dyndns.
-update delete test.dyndns. 3600 NS ns2.test.dyndns.
+update delete test.dyndns. 3600 NS ns1.test.dyndns.
+update delete test.dyndns. 3600 NS ns2.test.dyndns.
send
answer
!
cleannsupdate <<!
server $nameserver $port
zone test.dyndns
-update add test.dyndns. 3600 NS ns1.test.dyndns.
+update add test.dyndns. 3600 NS ns1.test.dyndns.
send
answer
!
-cleandig test.dyndns NS
+cleandig test.dyndns NS
#!/bin/sh
-
+
NSEC3=`cleandig test.dyndns NSEC3PARAM hidesoadetails dnssec`
echo $NSEC3
HAVENSEC3=`echo $NSEC3 | egrep 'IN[[:space:]]NSEC3PARAM' | wc -l`
#!/bin/bash
-
+
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
-mysqldiff
+mysqldiff
cleannsupdate <<!
server $nameserver $port
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
+In NSEC3-NARROW mode, we do add NSEC3PARAM's at the end, but these are then in non-narrow mode as we cannot
specify narrow mode in the NSEC3PARAM and the delete of the NSEC3PARAM also removed the narrow flag.
#!/bin/sh
-cleandig test.dyndns MX
+cleandig test.dyndns MX
cleannsupdate <<!
server $nameserver $port
-A test for RFC2136 which checks section 3.4.2.2 - Replacing a record.
+A test for RFC2136 which checks section 3.4.2.2 - Replacing a record.
In this test, we specifically use MX record, to see if the TTL changes of the MX record with the correct priority.
\ No newline at end of file
A test for RFC2136 which checks section 3.4.2.2 - Replacing a SOA record.
-This is special because we can 'set' the soa serial.
+This is special because we can 'set' the soa serial.
This test also does not use the hidesoaserial option because we want to compare that serial. It's also the reason why the test is run only once.
then
echo $testname >> skipped_tests
skipped=$[$skipped+1]
- else
+ else
$a/command > $a/real_result
expected=$a/expected_result
for extracontext in $extracontexts
for zone in $(grep zone named.conf | cut -f2 -d\")
do
- mv $zone.backup $zone
+ mv $zone.backup $zone
done
failed_tests=`wc -l failed_tests | cut -f 1 -d ' '`
if [ $failed_tests = 0 ];
then
- exit 0;
+ exit 0;
else
for t in `cat failed_tests`
do
echo $t
cat $t/diff
done
- exit 1;
+ exit 1;
fi