This commits adds a lot of files and code to implement rfc2136. The code was taken from a different branch and only added again.
There are still things missing.
Primary changes:
- Add rfc2136 methods to rfc2136handler.cc file and include file in build
- Add constructor for DNSResourceRecord to take a DNSRecord
- Add setContent and getZoneRepresentation to DNSResourceRecord for easy compare and set of content
This removes the need to consantly check if it's an MX record, etc.
- Add compare operator to DNSResourceRecord to easily compare DNSResourceRecords
- Move SOA-EDIT calculation/changes to seperate method for re-use in rfc2136 code
- Move rfc1982LessThan to misc.hh for reuse
- Added code to handle update packets in questionOrRecurse
dnsseckeeper.hh dnssecinfra.hh base32.hh dns.cc dnssecsigner.cc polarrsakeyinfra.cc \
md5.hh signingpipe.cc signingpipe.hh dnslabeltext.cc lua-pdns.cc lua-auth.cc lua-auth.hh serialtweaker.cc \
ednssubnet.cc ednssubnet.hh cachecleaner.hh json.cc json.hh \
-version.hh version.cc
+version.hh version.cc rfc2136handler.cc
#
pdns_server_LDFLAGS=@moduleobjects@ @modulelibs@ @DYNLINKFLAGS@ @LIBDL@ @THREADFLAGS@ $(BOOST_SERIALIZATION_LDFLAGS) -rdynamic
{
public:
DNSResourceRecord() : qclass(1), priority(0), signttl(0), last_modified(0), d_place(ANSWER), auth(1), scopeMask(0) {};
+ DNSResourceRecord(const struct DNSRecord&);
~DNSResourceRecord(){};
+ void setContent(const string& content);
+ string getZoneRepresentation();
+
// data
QType qtype; //!< qtype of this record, ie A, CNAME, MX etc
ar & d_place;
ar & auth;
}
+
+ bool operator==(const DNSResourceRecord& rhs);
bool operator<(const DNSResourceRecord &b) const
{
#include "dnsrecords.hh"
#include <boost/foreach.hpp>
+void DNSResourceRecord::setContent(const string &cont) {
+ content = cont;
+ if(!content.empty() && (qtype==QType::MX || qtype==QType::NS || qtype==QType::CNAME))
+ boost::erase_tail(content, 1);
+
+ if(qtype.getCode() == QType::MX) {
+ vector<string> parts;
+ stringtok(parts, content);
+ priority = atoi(parts[0].c_str());
+ if(parts.size() > 1)
+ content=parts[1];
+ else
+ content=".";
+ } else if(qtype.getCode() == QType::SRV) {
+ priority = atoi(content.c_str());
+ vector<pair<string::size_type, string::size_type> > fields;
+ vstringtok(fields, content, " ");
+ if(fields.size()==4) {
+ content=string(content.c_str() + fields[1].first, fields[3].second - fields[1].first);
+ content=stripDot(content);
+ }
+ }
+}
+
+string DNSResourceRecord::getZoneRepresentation() {
+ ostringstream ret;
+ switch(qtype.getCode()) {
+ case QType::SRV:
+ case QType::MX:
+ ret<<priority;
+ ret<<" "<<content<<".";
+ break;
+ case QType::CNAME:
+ case QType::NS:
+ ret<<content<<".";
+ break;
+ default:
+ ret<<content;
+ break;
+ }
+ return ret.str();
+}
+
+bool DNSResourceRecord::operator==(const DNSResourceRecord& rhs)
+{
+ string lcontent=toLower(content);
+ string rcontent=toLower(rhs.content);
+
+ string llabel=toLower(qname);
+ string rlabel=toLower(rhs.qname);
+
+ return
+ tie(llabel, qtype, lcontent, ttl, priority) ==
+ tie(rlabel, rhs.qtype, rcontent, rhs.ttl, rhs.priority);
+}
+
+
+
+DNSResourceRecord::DNSResourceRecord(const DNSRecord &p) {
+ auth=true;
+ qname = p.d_label;
+ if(!qname.empty())
+ boost::erase_tail(qname, 1); // strip .
+
+ qtype = p.d_type;
+ ttl = p.d_ttl;
+ priority=0;
+ setContent(p.d_content->getZoneRepresentation());
+}
+
+
boilerplate_conv(A, ns_t_a, conv.xfrIP(d_ip));
ARecordContent::ARecordContent(uint32_t ip) : DNSRecordContent(ns_t_a)
class DNSPacket;
uint32_t localtime_format_YYYYMMDDSS(time_t t, uint32_t seq);
bool editSOA(DNSSECKeeper& dk, const string& qname, DNSPacket* dp);
-uint32_t calculateEditSoa(SOAData sd, const string& kind);
+uint32_t calculateEditSOA(SOAData sd, const string& kind);
#endif
}
}
+template<typename T> bool rfc1982LessThan(T a, T b)
+{
+ return ((signed)(a - b)) < 0;
+}
+
// fills container with ranges, so {posbegin,posend}
template <typename Container>
void
r=p->replyPacket(); // generate an empty reply packet
if(d_logDNSDetails)
L<<Logger::Error<<"Received a TSIG signed message with a non-validating key"<<endl;
- r->setRcode(RCode::NotAuth);
+ // 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::NotAuth);
return r;
}
p->setTSIGDetails(trc, keyname, secret, trc.d_mac); // this will get copied by replyPacket()
}
if(p->d.opcode) { // non-zero opcode (again thanks RA!)
if(p->d.opcode==Opcode::Update) {
- if(::arg().mustDo("log-failed-updates"))
- L<<Logger::Notice<<"Received an UPDATE opcode from "<<p->getRemote()<<" for "<<p->qdomain<<", sending NOTIMP"<<endl;
- r->setRcode(RCode::NotImp); // notimp;
- return r;
+ //S.inc("rfc2136-queries");
+ int res=processUpdate(p);
+ //if (res == RCode::Refused)
+ // S.inc("rfc2136-refused");
+ //else if (res != RCode::ServFail)
+ // S.inc("rfc2136-answers");
+ r->setRcode(res);
+ r->setOpcode(Opcode::Update);
+ return r;
}
else if(p->d.opcode==Opcode::Notify) {
int res=processNotify(p);
void addNSEC3(DNSPacket *p, DNSPacket* r, const string &target, const string &wildcard, const std::string& auth, const NSEC3PARAMRecordContent& nsec3param, bool narrow, int mode);
void emitNSEC(const std::string& before, const std::string& after, const std::string& toNSEC, const SOAData& sd, DNSPacket *r, int mode);
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);
+ uint16_t performUpdate(const string &msgPrefix, const DNSRecord *rr, DomainInfo *di, bool narrow, bool haveNSEC3, const NSEC3PARAMRecordContent *ns3pr, bool *updatedSerial);
+ int checkUpdatePrescan(const DNSRecord *rr);
+ int checkUpdatePrerequisites(const DNSRecord *rr, DomainInfo *di);
+ void increaseSerial(const string &msgPrefix, const DomainInfo& di);
void synthesiseRRSIGs(DNSPacket* p, DNSPacket* r);
void makeNXDomain(DNSPacket* p, DNSPacket* r, const std::string& target, const std::string& wildcard, SOAData& sd);
#include <boost/scoped_ptr.hpp>
using boost::scoped_ptr;
-template<typename T> bool rfc1982LessThan(T a, T b)
-{
- return ((signed)(a - b)) < 0;
-}
void CommunicatorClass::addSuckRequest(const string &domain, const string &master)
{