static int ldp_addRecords(lua_State *L) {
DNSPacket *p=ldp_checkDNSPacket(L);
- vector<DNSResourceRecord> rrs;
+ vector<DNSRecord> rrs;
popResourceRecordsTable(L, DNSName("BOGUS"), rrs);
- BOOST_FOREACH(DNSResourceRecord rr, rrs) {
- p->addRecord(rr);
+ BOOST_FOREACH(const DNSRecord& dr, rrs) {
+ p->addRecord(DNSResourceRecord(dr));
}
return 0;
}
#include <stdexcept>
#include "logger.hh"
#include "namespaces.hh"
+#include "dnsparser.hh"
bool netmaskMatchTable(lua_State* lua, const std::string& ip)
{
return ret;
}
-void pushResourceRecordsTable(lua_State* lua, const vector<DNSResourceRecord>& records)
+void pushResourceRecordsTable(lua_State* lua, const vector<DNSRecord>& records)
{
// make a table of tables
lua_newtable(lua);
int pos=0;
- BOOST_FOREACH(const DNSResourceRecord& rr, records)
+ for(const auto& rr: records)
{
// row number, used by 'lua_settable' below
lua_pushnumber(lua, ++pos);
// "row" table
lua_newtable(lua);
- lua_pushstring(lua, rr.qname.toString().c_str());
+ lua_pushstring(lua, rr.d_name.toString().c_str());
lua_setfield(lua, -2, "qname"); // pushes value at the top of the stack to the table immediately below that (-1 = top, -2 is below)
- lua_pushstring(lua, rr.content.c_str());
+ lua_pushstring(lua, rr.d_content->getZoneRepresentation().c_str());
lua_setfield(lua, -2, "content");
- lua_pushnumber(lua, rr.qtype.getCode());
+ lua_pushnumber(lua, rr.d_type);
lua_setfield(lua, -2, "qtype");
- lua_pushnumber(lua, rr.ttl);
+ lua_pushnumber(lua, rr.d_ttl);
lua_setfield(lua, -2, "ttl");
lua_pushnumber(lua, rr.d_place);
lua_setfield(lua, -2, "place");
- lua_pushnumber(lua, rr.qclass);
+ lua_pushnumber(lua, rr.d_class);
lua_setfield(lua, -2, "qclass");
lua_settable(lua, -3); // pushes the table we just built into the master table at position pushed above
}
// expects a table at offset 2, and, importantly DOES NOT POP IT from the stack - only the contents
-void popResourceRecordsTable(lua_State *lua, const DNSName &query, vector<DNSResourceRecord>& ret)
+void popResourceRecordsTable(lua_State *lua, const DNSName &query, vector<DNSRecord>& ret)
{
/* get the result */
- DNSResourceRecord rr;
- rr.qname = query;
- rr.d_place = DNSResourceRecord::ANSWER;
- rr.ttl = 3600;
+ DNSRecord rr;
+ rr.d_name = query;
+ rr.d_place = DNSRecord::Answer;
+ rr.d_ttl = 3600;
int tableLen = getLuaTableLength(lua, 2);
uint32_t tmpnum=0;
if(!getFromTable(lua, "qtype", tmpnum))
- rr.qtype=QType::A;
+ rr.d_type=QType::A;
else
- rr.qtype=tmpnum;
+ rr.d_type=tmpnum;
- getFromTable(lua, "content", rr.content);
- if(!getFromTable(lua, "ttl", rr.ttl))
- rr.ttl=3600;
+ if(!getFromTable(lua, "qclass", tmpnum))
+ rr.d_class = QClass::IN;
+ else {
+ rr.d_class = tmpnum;
+ }
+
+
+ string content;
+ getFromTable(lua, "content", content);
+ rr.d_content=shared_ptr<DNSRecordContent>(DNSRecordContent::mastermake(rr.d_type, rr.d_class, content));
- string qname = rr.qname.toString();
+ if(!getFromTable(lua, "ttl", rr.d_ttl))
+ rr.d_ttl=3600;
+
+ string qname = rr.d_name.toString();
if(!getFromTable(lua, "qname", qname))
- rr.qname = query;
+ rr.d_name = query;
if(!getFromTable(lua, "place", tmpnum))
- rr.d_place = DNSResourceRecord::ANSWER;
+ rr.d_place = DNSRecord::Answer;
else {
- rr.d_place = (DNSResourceRecord::Place) tmpnum;
- if(rr.d_place > DNSResourceRecord::ADDITIONAL)
- rr.d_place = DNSResourceRecord::ADDITIONAL;
+ rr.d_place = (DNSRecord::Place) tmpnum;
+ if(rr.d_place > DNSRecord::Additional)
+ rr.d_place = DNSRecord::Additional;
}
- if(!getFromTable(lua, "qclass", tmpnum))
- rr.qclass = QClass::IN;
- else {
- rr.qclass = tmpnum;
- }
/* removes 'value'; keeps 'key' for next iteration */
lua_pop(lua, 1); // table
};
// enum for policy decisions, used by both auth and recursor. Not all values supported everywhere.
namespace PolicyDecision { enum returnTypes { PASS=-1, DROP=-2, TRUNCATE=-3 }; };
-void pushResourceRecordsTable(lua_State* lua, const vector<DNSResourceRecord>& records);
-void popResourceRecordsTable(lua_State *lua, const DNSName &query, vector<DNSResourceRecord>& ret);
+void pushResourceRecordsTable(lua_State* lua, const vector<DNSRecord>& records);
+void popResourceRecordsTable(lua_State *lua, const DNSName &query, vector<DNSRecord>& ret);
void pushSyslogSecurityLevelTable(lua_State *lua);
int getLuaTableLength(lua_State* lua, int depth);
void luaStackDump (lua_State *L);
#endif
#include "lua-recursor.hh"
// to avoid including all of syncres.hh
-int directResolve(const std::string& qname, const QType& qtype, int qclass, vector<DNSResourceRecord>& ret);
+int directResolve(const std::string& qname, const QType& qtype, int qclass, vector<DNSRecord>& ret);
#if !defined(HAVE_LUA)
// empty
}
-bool RecursorLua::nxdomain(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
+bool RecursorLua::nxdomain(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSRecord>& ret, int& res, bool* variable)
{
return false;
}
-bool RecursorLua::nodata(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
+bool RecursorLua::nodata(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSRecord>& ret, int& res, bool* variable)
{
return false;
}
-bool RecursorLua::postresolve(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
+bool RecursorLua::postresolve(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSRecord>& ret, int& res, bool* variable)
{
return false;
}
-bool RecursorLua::preresolve(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
+bool RecursorLua::preresolve(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSRecord>& ret, int& res, bool* variable)
{
return false;
}
-bool RecursorLua::preoutquery(const ComboAddress& remote, const ComboAddress& local,const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res)
+bool RecursorLua::preoutquery(const ComboAddress& remote, const ComboAddress& local,const DNSName& query, const QType& qtype, vector<DNSRecord>& ret, int& res)
{
return false;
}
#include <stdexcept>
#include <boost/foreach.hpp>
#include "logger.hh"
+#include "dnsparser.hh"
#include "namespaces.hh"
#include "rec_channel.hh"
+#include "dnsrecords.hh"
static int getRegisteredNameLua(lua_State *L) {
const char *name = luaL_checkstring(L, 1);
lua_setglobal(d_lua, "getregisteredname");
}
-int followCNAMERecords(vector<DNSResourceRecord>& ret, const QType& qtype)
+int followCNAMERecords(vector<DNSRecord>& ret, const QType& qtype)
{
- vector<DNSResourceRecord> resolved;
- string target;
- BOOST_FOREACH(DNSResourceRecord& rr, ret) {
- if(rr.qtype.getCode() == QType::CNAME) {
- target=rr.content;
+ vector<DNSRecord> resolved;
+ string target; // XXX DNSNAME PAIN
+ BOOST_FOREACH(DNSRecord& rr, ret) {
+ if(rr.d_type == QType::CNAME) {
+ target=std::dynamic_pointer_cast<CNAMERecordContent>(rr.d_content)->getTarget().toString();
break;
}
}
int rcode=directResolve(target, qtype, 1, resolved); // 1 == class
- BOOST_FOREACH(const DNSResourceRecord& rr, resolved)
+ BOOST_FOREACH(const DNSRecord& rr, resolved)
{
ret.push_back(rr);
}
}
-int getFakeAAAARecords(const std::string& qname, const std::string& prefix, vector<DNSResourceRecord>& ret)
+int getFakeAAAARecords(const std::string& qname, const std::string& prefix, vector<DNSRecord>& ret)
{
int rcode=directResolve(qname, QType(QType::A), 1, ret);
ComboAddress prefixAddress(prefix);
- BOOST_FOREACH(DNSResourceRecord& rr, ret)
+ BOOST_FOREACH(DNSRecord& rr, ret)
{
- if(rr.qtype.getCode() == QType::A && rr.d_place==DNSResourceRecord::ANSWER) {
- ComboAddress ipv4(rr.content);
+ if(rr.d_type == QType::A && rr.d_place==DNSRecord::Answer) {
+ ComboAddress ipv4(std::dynamic_pointer_cast<ARecordContent>(rr.d_content)->getCA());
uint32_t tmp;
memcpy((void*)&tmp, &ipv4.sin4.sin_addr.s_addr, 4);
// tmp=htonl(tmp);
memcpy(((char*)&prefixAddress.sin6.sin6_addr.s6_addr)+12, &tmp, 4);
- rr.content = prefixAddress.toString();
- rr.qtype = QType(QType::AAAA);
+ rr.d_content = std::make_shared<AAAARecordContent>(prefixAddress);
+ rr.d_type = QType::AAAA;
}
}
return rcode;
}
-int getFakePTRRecords(const DNSName& qname, const std::string& prefix, vector<DNSResourceRecord>& ret)
+int getFakePTRRecords(const DNSName& qname, const std::string& prefix, vector<DNSRecord>& ret)
{
/* qname has a reverse ordered IPv6 address, need to extract the underlying IPv4 address from it
and turn it into an IPv4 in-addr.arpa query */
int rcode = directResolve(newquery, QType(QType::PTR), 1, ret);
- BOOST_FOREACH(DNSResourceRecord& rr, ret)
+ BOOST_FOREACH(DNSRecord& rr, ret)
{
- if(rr.qtype.getCode() == QType::PTR && rr.d_place==DNSResourceRecord::ANSWER) {
- rr.qname = qname;
+ if(rr.d_type == QType::PTR && rr.d_place==DNSRecord::Answer) {
+ rr.d_name = qname;
}
}
return rcode;
}
-bool RecursorLua::nxdomain(const ComboAddress& remote, const ComboAddress& local,const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
+bool RecursorLua::nxdomain(const ComboAddress& remote, const ComboAddress& local,const DNSName& query, const QType& qtype, vector<DNSRecord>& ret, int& res, bool* variable)
{
if(d_nofuncs.nxdomain)
return false;
return passthrough("nxdomain", remote, local, query, qtype, ret, res, variable);
}
-bool RecursorLua::preresolve(const ComboAddress& remote, const ComboAddress& local,const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
+bool RecursorLua::preresolve(const ComboAddress& remote, const ComboAddress& local,const DNSName& query, const QType& qtype, vector<DNSRecord>& ret, int& res, bool* variable)
{
if(d_nofuncs.preresolve)
return false;
return passthrough("preresolve", remote, local, query, qtype, ret, res, variable);
}
-bool RecursorLua::nodata(const ComboAddress& remote, const ComboAddress& local,const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
+bool RecursorLua::nodata(const ComboAddress& remote, const ComboAddress& local,const DNSName& query, const QType& qtype, vector<DNSRecord>& ret, int& res, bool* variable)
{
if(d_nofuncs.nodata)
return false;
return passthrough("nodata", remote, local, query, qtype, ret, res, variable);
}
-bool RecursorLua::postresolve(const ComboAddress& remote, const ComboAddress& local,const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
+bool RecursorLua::postresolve(const ComboAddress& remote, const ComboAddress& local,const DNSName& query, const QType& qtype, vector<DNSRecord>& ret, int& res, bool* variable)
{
if(d_nofuncs.postresolve)
return false;
return passthrough("postresolve", remote, local, query, qtype, ret, res, variable);
}
-bool RecursorLua::preoutquery(const ComboAddress& ns, const ComboAddress& requestor, const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res)
+bool RecursorLua::preoutquery(const ComboAddress& ns, const ComboAddress& requestor, const DNSName& query, const QType& qtype, vector<DNSRecord>& ret, int& res)
{
if(d_nofuncs.preoutquery)
return false;
}
-bool RecursorLua::passthrough(const string& func, const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& ret,
+bool RecursorLua::passthrough(const string& func, const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSRecord>& ret,
int& res, bool* variable)
{
d_variable = false;
public:
explicit RecursorLua(const std::string& fname);
// ~RecursorLua();
- bool preresolve(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret, bool* variable);
- bool nxdomain(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret, bool* variable);
- bool nodata(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret, bool* variable);
- bool postresolve(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret, bool* variable);
- bool preoutquery(const ComboAddress& ns, const ComboAddress& requestor, const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret);
+ bool preresolve(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSRecord>& res, int& ret, bool* variable);
+ bool nxdomain(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSRecord>& res, int& ret, bool* variable);
+ bool nodata(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSRecord>& res, int& ret, bool* variable);
+ bool postresolve(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSRecord>& res, int& ret, bool* variable);
+ bool preoutquery(const ComboAddress& ns, const ComboAddress& requestor, const DNSName& query, const QType& qtype, vector<DNSRecord>& res, int& ret);
bool ipfilter(const ComboAddress& remote, const ComboAddress& local);
private:
- bool passthrough(const string& func, const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable);
+ bool passthrough(const string& func, const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSRecord>& ret, int& res, bool* variable);
struct NoFuncs
{
if(ret <= 0) // includes 'timeout'
return ret;
- lwr->d_result.clear();
+ lwr->d_records.clear();
try {
lwr->d_tcbit=0;
MOADNSParser mdp((const char*)buf.get(), len);
return 1; // this is "success", the error is set in lwr->d_rcode
}
- if(!pdns_iequals(domain, mdp.d_qname)) {
+ if(domain != mdp.d_qname) {
if(!mdp.d_qname.empty() && domain.toString().find((char)0) == string::npos /* ugly */) {// embedded nulls are too noisy, plus empty domains are too
L<<Logger::Notice<<"Packet purporting to come from remote server "<<ip.toString()<<" contained wrong answer: '" << domain << "' != '" << mdp.d_qname << "'" << endl;
}
// unexpected count has already been done @ pdns_recursor.cc
goto out;
}
-
- lwr->d_records = mdp.d_answers;
+
+ for(const auto& a : mdp.d_answers)
+ lwr->d_records.push_back(a.first);
EDNSOpts edo;
if(EDNS0Level > 0 && getEDNSOpts(mdp, &edo)) {
return -1;
}
-vector<DNSResourceRecord>& LWResult::getResult()
-{
- if(d_result.empty()) {
- for(auto i=d_records.cbegin(); i != d_records.cend(); ++i) {
- DNSResourceRecord rr(i->first);
- d_result.push_back(rr);
- }
- }
- return d_result;
-}
{
public:
LWResult() : d_usec(0) {}
- typedef vector<DNSResourceRecord> res_t;
- res_t& getResult();
- vector<pair<DNSRecord, uint16_t>> d_records;
+ vector<DNSRecord> d_records;
int d_rcode;
bool d_aabit, d_tcbit;
uint32_t d_usec;
bool d_haveEDNS;
-
- vector<DNSResourceRecord> d_result;
};
int asyncresolve(const ComboAddress& ip, const DNSName& domain, int type, bool doTCP, bool sendRDQuery, int EDNS0Level, struct timeval* now, LWResult* res);
#include <sys/types.h>
#include <boost/algorithm/string.hpp>
#include "iputils.hh"
-
+#include "dnsparser.hh"
bool g_singleThreaded;
// we don't shuffle the rest
}
-static bool comparePlace(DNSResourceRecord a, DNSResourceRecord b)
+
+// shuffle, maintaining some semblance of order
+void shuffle(vector<DNSRecord>& rrs)
{
- return (a.d_place < b.d_place);
+ vector<DNSRecord>::iterator first, second;
+ for(first=rrs.begin();first!=rrs.end();++first)
+ if(first->d_place==DNSRecord::Answer && first->d_type != QType::CNAME) // CNAME must come first
+ break;
+ for(second=first;second!=rrs.end();++second)
+ if(second->d_place!=DNSRecord::Answer)
+ break;
+
+ if(second-first>1)
+ random_shuffle(first,second);
+
+ // now shuffle the additional records
+ for(first=second;first!=rrs.end();++first)
+ if(first->d_place==DNSRecord::Additional && first->d_type != QType::CNAME) // CNAME must come first
+ break;
+ for(second=first; second!=rrs.end(); ++second)
+ if(second->d_place!=DNSRecord::Additional)
+ break;
+
+ if(second-first>1)
+ random_shuffle(first,second);
+
+ // we don't shuffle the rest
}
// make sure rrs is sorted in d_place order to avoid surprises later
// then shuffle the parts that desire shuffling
-void orderAndShuffle(vector<DNSResourceRecord>& rrs)
+void orderAndShuffle(vector<DNSRecord>& rrs)
{
- std::stable_sort(rrs.begin(), rrs.end(), comparePlace);
+ std::stable_sort(rrs.begin(), rrs.end(), [](const DNSRecord&a, const DNSRecord& b) {
+ return a.d_place < b.d_place;
+ });
shuffle(rrs);
}
}
string makeHexDump(const string& str);
+void shuffle(vector<DNSRecord>& rrs);
void shuffle(vector<DNSResourceRecord>& rrs);
-void orderAndShuffle(vector<DNSResourceRecord>& rrs);
+void orderAndShuffle(vector<DNSRecord>& rrs);
void normalizeTV(struct timeval& tv);
const struct timeval operator+(const struct timeval& lhs, const struct timeval& rhs);
return true;
}
-// FIXME400 remove this, it's just here to move faster while we DNSName the things
-inline bool pdns_iequals(const DNSName& a, const DNSName& b) __attribute__((pure));
-inline bool pdns_iequals(const DNSName& a, const DNSName& b)
-{
- return a==b;
-}
-
inline bool pdns_iequals_ch(const char a, const char b) __attribute__((pure));
inline bool pdns_iequals_ch(const char a, const char b)
{
do {
unhashed=next;
}
- while( next.chopOff() && !pdns_iequals(next, closest));
+ while( next.chopOff() && !(next==closest));
hashed=hashQNameWithSalt(ns3rc, unhashed);
DLOG(L<<"2 hash: "<<toBase32Hex(hashed)<<" "<<unhashed<<endl);
return;
addNSECX(p, r, target, DNSName(), sd.qname, 5);
- if(pdns_iequals(sd.qname, p->qdomain)) {
+ if(sd.qname == p->qdomain) {
addDNSKEY(p, r, sd);
addNSEC3PARAM(p, r, sd);
}
if(!retargetcount) r->qdomainzone=sd.qname;
-
- if(pdns_iequals(sd.qname, p->qdomain)) {
+ if(sd.qname==p->qdomain) {
if(p->qtype.getCode() == QType::DNSKEY)
{
if(addDNSKEY(p, r, sd))
}
}
- if(p->qtype.getCode() == QType::SOA && pdns_iequals(sd.qname, p->qdomain)) {
+ if(p->qtype.getCode() == QType::SOA && sd.qname==p->qdomain) {
rr.qname=sd.qname;
rr.qtype=QType::SOA;
rr.content=serializeSOAData(sd);
if((p->qtype.getCode() == QType::ANY || rr.qtype == p->qtype) && rr.auth)
weDone=1;
// the line below fakes 'unauth NS' for delegations for non-DNSSEC backends.
- if((rr.qtype == p->qtype && !rr.auth) || (rr.qtype.getCode() == QType::NS && (!rr.auth || !pdns_iequals(sd.qname, rr.qname))))
+ if((rr.qtype == p->qtype && !rr.auth) || (rr.qtype.getCode() == QType::NS && (!rr.auth || !(sd.qname==rr.qname))))
weHaveUnauth=1;
if(rr.qtype.getCode() == QType::CNAME && p->qtype.getCode() != QType::CNAME)
}
/* Add in SOA if required */
- if( pdns_iequals( target, sd.qname ) ) {
+ if(target==sd.qname) {
rr.qtype = QType::SOA;
rr.content = serializeSOAData(sd);
rr.qname = sd.qname;
}
ComboAddress local;
listenSocketsAddresses_t::const_iterator lociter;
- vector<DNSResourceRecord> ret;
+ vector<DNSRecord> ret;
vector<uint8_t> packet;
DNSPacketWriter pw(packet, dc->d_mdp.d_qname, dc->d_mdp.d_qtype, dc->d_mdp.d_qclass);
}
// if there is a RecursorLua active, and it 'took' the query in preResolve, we don't launch beginResolve
+
if(!t_pdl->get() || !(*t_pdl)->preresolve(dc->d_remote, local, dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res, &variableAnswer)) {
try {
res = sr.beginResolve(dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), dc->d_mdp.d_qclass, ret);
if(t_pdl->get()) {
if(res == RCode::NoError) {
- vector<DNSResourceRecord>::const_iterator i;
- for(i=ret.begin(); i!=ret.end(); ++i)
- if(i->qtype.getCode() == dc->d_mdp.d_qtype && i->d_place == DNSResourceRecord::ANSWER)
+ auto i=ret.cbegin();
+ for(; i!= ret.cend(); ++i)
+ if(i->d_type == dc->d_mdp.d_qtype && i->d_place == DNSRecord::Answer)
break;
- if(i == ret.end())
+ if(i == ret.cend())
(*t_pdl)->nodata(dc->d_remote,local, dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res, &variableAnswer);
}
else if(res == RCode::NXDomain)
else {
pw.getHeader()->rcode=res;
-
if(ret.size()) {
orderAndShuffle(ret);
- for(vector<DNSResourceRecord>::const_iterator i=ret.begin(); i!=ret.end(); ++i) {
- pw.startRecord(i->qname, i->qtype.getCode(), i->ttl, i->qclass, (DNSPacketWriter::Place)i->d_place);
- minTTL = min(minTTL, i->ttl);
- if(i->qtype.getCode() == QType::A) { // blast out A record w/o doing whole dnswriter thing
- uint32_t ip=0;
- IpToU32(i->content, &ip);
- pw.xfr32BitInt(htonl(ip));
- } else {
- shared_ptr<DNSRecordContent> drc(DNSRecordContent::mastermake(i->qtype.getCode(), i->qclass, i->content));
- drc->toPacket(pw);
- }
+ for(auto i=ret.cbegin(); i!=ret.cend(); ++i) {
+ pw.startRecord(i->d_name, i->d_type, i->d_ttl, i->d_class, (DNSPacketWriter::Place)i->d_place);
+ minTTL = min(minTTL, i->d_ttl);
+ i->d_content->toPacket(pw);
if(pw.size() > maxanswersize) {
pw.rollback();
- if(i->d_place==DNSResourceRecord::ANSWER) // only truncate if we actually omitted parts of the answer
+ if(i->d_place==DNSRecord::Answer) // only truncate if we actually omitted parts of the answer
{
pw.getHeader()->tc=1;
pw.truncate();
if(now.tv_sec - last_rootupdate > 7200) {
SyncRes sr(now);
sr.setDoEDNS0(true);
- vector<DNSResourceRecord> ret;
+ vector<DNSRecord> ret;
sr.setNoCache();
int res=-1;
// we do a full scan for outstanding queries on unexpected answers. not too bad since we only accept them on the right port number, which is hard enough to guess
for(MT_t::waiters_t::iterator mthread=MT->d_waiters.begin(); mthread!=MT->d_waiters.end(); ++mthread) {
if(pident.fd==mthread->key.fd && mthread->key.remote==pident.remote && mthread->key.type == pident.type &&
- pdns_iequals(pident.domain, mthread->key.domain)) {
+ pident.domain == mthread->key.domain) {
mthread->key.nearMisses++;
}
int serviceMain(int argc, char*argv[])
{
L.setName(s_programname);
-
L.setLoglevel((Logger::Urgency)(6)); // info and up
if(!::arg()["logging-facility"].empty()) {
#include "recursor_cache.hh"
#include "misc.hh"
#include <iostream>
-
#include "dnsrecords.hh"
#include "arguments.hh"
#include "syncres.hh"
#include "recursor_cache.hh"
#include "cachecleaner.hh"
-
-#include "namespaces.hh"
#include "namespaces.hh"
-
-DNSResourceRecord String2DNSRR(const DNSName& qname, const QType& qt, const string& serial, uint32_t ttd)
-{
- DNSResourceRecord rr;
- rr.ttl=ttd;
- rr.qtype=qt;
- rr.qname=qname;
-
- if(rr.qtype.getCode()==QType::A && serial.size()==4) {
- uint32_t ip;
- memcpy((char*)&ip, serial.c_str(), 4);
- rr.content=U32ToIP(ntohl(ip));
- }
- else if(rr.qtype.getCode()==QType::AAAA && serial.size()==16) {
- ComboAddress tmp;
- memset(&tmp, 0, sizeof(tmp));
- tmp.sin4.sin_family=AF_INET6;
- memcpy(tmp.sin6.sin6_addr.s6_addr, serial.c_str(), 16);
- rr.content=tmp.toString();
- }
- else if(rr.qtype.getCode()==QType::CNAME || rr.qtype.getCode()==QType::NS || rr.qtype.getCode()==QType::PTR) {
- unsigned int frompos=0;
- unsigned char labellen;
-
- while((labellen=serial.at(frompos++))) {
- if((labellen & 0xc0) == 0xc0) {
- string encoded=qname.toDNSString();
- uint16_t offset=256*(labellen & ~0xc0) + (unsigned int)serial.at(frompos++) - sizeof(dnsheader)-5;
-
- simpleExpandTo(encoded, offset, rr.content);
- // cerr<<"Oops, fallback, content so far: '"<<rr.content<<"', offset: "<<offset<<", '"<<qname<<"', "<<qt.getName()<<"\n";
- break;
- }
- rr.content.append(serial.c_str()+frompos, labellen);
- frompos+=labellen;
- rr.content.append(1,'.');
- }
- if(rr.content.empty())
- rr.content=".";
- }
- else {
- shared_ptr<DNSRecordContent> regen=DNSRecordContent::unserialize(qname, qt.getCode(), serial);
- rr.content=regen->getZoneRepresentation();
- }
- rr.content.reserve(0);
- // rr.qname.reserve(0);
- return rr;
-}
-
-// returns the RDATA for rr - might be compressed!
-string DNSRR2String(const DNSResourceRecord& rr)
-{
- uint16_t type=rr.qtype.getCode();
-
- if(type==QType::A) {
- uint32_t ip;
- IpToU32(rr.content, &ip);
- return string((char*)&ip, 4);
- }
- else if(type==QType::AAAA) {
- ComboAddress ca(rr.content);
- return string((char*)&ca.sin6.sin6_addr.s6_addr, 16);
- }
- else if(type==QType::NS || type==QType::CNAME)
- return simpleCompress(rr.content, rr.qname.toString());
- else {
- string ret;
- shared_ptr<DNSRecordContent> drc(DNSRecordContent::mastermake(type, 1, rr.content));
- ret=drc->serialize(rr.qname);
- // cerr<<"stored '"<<rr.qname<<" '"<<rr.qtype.getName()<<"' '"<<rr.content<<"' as "<<ret.size()<<" bytes"<<endl;
- return ret;
- }
-}
-
unsigned int MemRecursorCache::size()
{
return (unsigned int)d_cache.size();
for(cache_t::const_iterator i=d_cache.begin(); i!=d_cache.end(); ++i) {
ret+=sizeof(struct CacheEntry);
ret+=(unsigned int)i->d_qname.toString().length();
- for(vector<StoredRecord>::const_iterator j=i->d_records.begin(); j!= i->d_records.end(); ++j)
- ret+=j->size();
+ for(auto j=i->d_records.begin(); j!= i->d_records.end(); ++j)
+ ret+= sizeof(*j); // XXX WRONG we don't know the stored size! j->size();
}
return ret;
}
-int MemRecursorCache::get(time_t now, const DNSName &qname, const QType& qt, set<DNSResourceRecord>* res, vector<std::shared_ptr<RRSIGRecordContent>>* signatures)
+int MemRecursorCache::get(time_t now, const DNSName &qname, const QType& qt, vector<DNSRecord>* res, vector<std::shared_ptr<RRSIGRecordContent>>* signatures)
{
unsigned int ttd=0;
- // cerr<<"looking up "<< qname+"|"+qt.getName()<<"\n";
+ // cerr<<"looking up "<< qname<<"|"+qt.getName()<<"\n";
- if(!d_cachecachevalid || !pdns_iequals(d_cachedqname, qname)) {
+ if(!d_cachecachevalid || d_cachedqname!= qname) {
// cerr<<"had cache cache miss"<<endl;
d_cachedqname=qname;
d_cachecache=d_cache.equal_range(tie(qname));
d_cachecachevalid=true;
}
-// else cerr<<"had cache cache hit!"<<endl;
+ // else cerr<<"had cache cache hit!"<<endl;
if(res)
res->clear();
if(d_cachecache.first!=d_cachecache.second) {
for(cache_t::const_iterator i=d_cachecache.first; i != d_cachecache.second; ++i)
- if(i->d_qtype == qt.getCode() || qt.getCode()==QType::ANY ||
- (qt.getCode()==QType::ADDR && (i->d_qtype == QType::A || i->d_qtype == QType::AAAA) )
+ if(i->d_ttd > now && (i->d_qtype == qt.getCode() || qt.getCode()==QType::ANY ||
+ (qt.getCode()==QType::ADDR && (i->d_qtype == QType::A || i->d_qtype == QType::AAAA) ) )
) {
- for(vector<StoredRecord>::const_iterator k=i->d_records.begin(); k != i->d_records.end(); ++k) {
- if(k->d_ttd < 1000000000 || k->d_ttd > (uint32_t) now) { // FIXME what does the 100000000 number mean?
- ttd=k->d_ttd;
- if(res) {
- DNSResourceRecord rr=String2DNSRR(qname, QType(i->d_qtype), k->d_string, ttd);
- res->insert(rr);
- }
- }
- }
+
+ ttd = i->d_ttd;
+ for(auto k=i->d_records.begin(); k != i->d_records.end(); ++k) {
+ if(res) {
+ DNSRecord dr;
+ dr.d_name = qname;
+ dr.d_type = i->d_qtype;
+ dr.d_class = 1;
+ dr.d_content = *k;
+ dr.d_ttl = i->d_ttd;
+ dr.d_place = DNSRecord::Answer;
+ res->push_back(dr);
+ }
+ }
+
if(signatures) // if you do an ANY lookup you are hosed XXXX
*signatures=i->d_signatures;
if(res) {
-bool MemRecursorCache::attemptToRefreshNSTTL(const QType& qt, const set<DNSResourceRecord>& content, const CacheEntry& stored)
+bool MemRecursorCache::attemptToRefreshNSTTL(const QType& qt, const vector<DNSRecord>& content, const CacheEntry& stored)
{
if(!stored.d_auth) {
//~ cerr<<"feel free to scribble non-auth data!"<<endl;
if(stored.d_records.empty())
return false;
- if(stored.d_records.begin()->d_ttd > content.begin()->ttl) {
+ if(stored.d_ttd > content.begin()->d_ttl) {
//~ cerr<<"attempt to LOWER TTL - fine by us"<<endl;
return false;
}
return true;
}
-/* the code below is rather tricky - it basically replaces the stuff cached for qname by content, but it is special
- cased for when inserting identical records with only differing ttls, in which case the entry is not
- touched, but only given a new ttd */
-void MemRecursorCache::replace(time_t now, const DNSName &qname, const QType& qt, const set<DNSResourceRecord>& content, const vector<shared_ptr<RRSIGRecordContent>>& signatures, bool auth)
+void MemRecursorCache::replace(time_t now, const DNSName &qname, const QType& qt, const vector<DNSRecord>& content, const vector<shared_ptr<RRSIGRecordContent>>& signatures, bool auth)
{
d_cachecachevalid=false;
boost::tuple<DNSName, uint16_t> key=boost::make_tuple(qname, qt.getCode());
cache_t::iterator stored=d_cache.find(key);
uint32_t maxTTD=UINT_MAX;
- bool isNew=false;
if(stored == d_cache.end()) {
- stored=d_cache.insert(CacheEntry(key,vector<StoredRecord>(), auth)).first;
- isNew=true;
+ stored=d_cache.insert(CacheEntry(key,CacheEntry::records_t(), auth)).first;
}
- pair<vector<StoredRecord>::iterator, vector<StoredRecord>::iterator> range;
-
- StoredRecord dr;
+
CacheEntry ce=*stored;
+ ce.d_qtype=qt.getCode();
ce.d_signatures=signatures;
- //~ cerr<<"asked to store "<< qname+"|"+qt.getName()<<" -> '"<<content.begin()->content<<"', isnew="<<isNew<<", auth="<<auth<<", ce.auth="<<ce.d_auth<<"\n";
- if(qt.getCode()==QType::SOA || qt.getCode()==QType::CNAME) { // you can only have one (1) each of these
- // cerr<<"\tCleaning out existing store because of SOA and CNAME\n";
- ce.d_records.clear();
- }
+ // cerr<<"asked to store "<< qname<<"|"+qt.getName()<<" -> '"<<content.begin()->d_content->getZoneRepresentation()<<"', auth="<<auth<<", ce.auth="<<ce.d_auth<<"\n";
+
+ ce.d_records.clear();
if(!auth && ce.d_auth) { // unauth data came in, we have some auth data, but is it fresh?
- vector<StoredRecord>::iterator j;
- for(j = ce.d_records.begin() ; j != ce.d_records.end(); ++j)
- if((time_t)j->d_ttd > now)
- break;
- if(j != ce.d_records.end()) { // we still have valid data, ignore unauth data
+ if(ce.d_ttd > now) { // we still have valid data, ignore unauth data
// cerr<<"\tStill hold valid auth data, and the new data is unauth, return\n";
return;
}
}
// limit TTL of auth->auth NSset update if needed, except for root
- if(ce.d_auth && auth && qt.getCode()==QType::NS && !(qname == DNSName("."))) {
+ if(ce.d_auth && auth && qt.getCode()==QType::NS && !(qname == DNSName())) {
// cerr<<"\tLimiting TTL of auth->auth NS set replace"<<endl;
- vector<StoredRecord>::iterator j;
- for(j = ce.d_records.begin() ; j != ce.d_records.end(); ++j) {
- maxTTD=min(maxTTD, j->d_ttd);
- }
+ maxTTD = ce.d_ttd;
}
// make sure that we CAN refresh the root
- if(auth && ((qname == DNSName(".")) || !attemptToRefreshNSTTL(qt, content, ce) ) ) {
+ if(auth && ((qname == DNSName()) || !attemptToRefreshNSTTL(qt, content, ce) ) ) {
// cerr<<"\tGot auth data, and it was not refresh attempt of an unchanged NS set, nuking storage"<<endl;
ce.d_records.clear(); // clear non-auth data
ce.d_auth = true;
- isNew=true; // data should be sorted again
}
// else cerr<<"\tNot nuking"<<endl;
- // make sure we don't accidentally merge old and new unauth data
- if(!auth && !ce.d_auth) {
- ce.d_records.clear();
- isNew=true;
- }
// cerr<<"\tHave "<<content.size()<<" records to store\n";
- for(set<DNSResourceRecord>::const_iterator i=content.begin(); i != content.end(); ++i) {
+ for(auto i=content.cbegin(); i != content.cend(); ++i) {
// cerr<<"To store: "<<i->content<<" with ttl/ttd "<<i->ttl<<endl;
- dr.d_ttd=min(maxTTD, i->ttl);
- dr.d_string=DNSRR2String(*i);
+ ce.d_ttd=min(maxTTD, i->d_ttl); // XXX this does weird things if TTLs differ in the set
+ ce.d_records.push_back(i->d_content);
- if(isNew)
- ce.d_records.push_back(dr);
+ /*
else {
range=equal_range(ce.d_records.begin(), ce.d_records.end(), dr);
if(range.first != range.second) {
// cerr<<"\t\tMay need to modify TTL of stored record\n";
for(vector<StoredRecord>::iterator j=range.first ; j!=range.second; ++j) {
- /* see http://mailman.powerdns.com/pipermail/pdns-users/2006-May/003413.html */
+ // see http://mailman.powerdns.com/pipermail/pdns-users/2006-May/003413.html
if(j->d_ttd > (unsigned int) now && i->ttl > j->d_ttd && qt.getCode()==QType::NS && auth) { // don't allow auth servers to *raise* TTL of an NS record
//~ cerr<<"\t\tNot doing so, trying to raise TTL NS\n";
continue;
//~ cerr<<"\t\tThere was no exact copy of this record, so adding & sorting\n";
ce.d_records.push_back(dr);
sort(ce.d_records.begin(), ce.d_records.end());
- }
+ }
}
+ */
}
- if(isNew) {
- // cerr<<"\tSorting (because of isNew)\n";
- sort(ce.d_records.begin(), ce.d_records.end());
- }
-
- if(ce.d_records.capacity() != ce.d_records.size())
- vector<StoredRecord>(ce.d_records).swap(ce.d_records);
-
d_cache.replace(stored, ce);
}
CacheEntry ce = *iter;
- if(ce.d_records.size()==1) {
- maxTTD=ce.d_records.begin()->d_ttd;
- }
- else { // find the LATEST ttd
- for(vector<StoredRecord>::const_iterator i=ce.d_records.begin(); i != ce.d_records.end(); ++i)
- maxTTD=max(maxTTD, i->d_ttd);
- }
+ maxTTD=ce.d_ttd;
int32_t maxTTL = maxTTD - now;
if(maxTTL < 0)
uint32_t newTTD = now + newTTL;
- for(vector<StoredRecord>::iterator j = ce.d_records.begin() ; j != ce.d_records.end(); ++j) {
- if(j->d_ttd>newTTD) // do never renew expired or older TTLs
- j->d_ttd = newTTD;
- }
+
+ if(ce.d_ttd > newTTD) // do never renew expired or older TTLs
+ ce.d_ttd = newTTD;
+
d_cache.replace(iter, ce);
return true;
uint64_t count=0;
time_t now=time(0);
for(sequence_t::const_iterator i=sidx.begin(); i != sidx.end(); ++i) {
- for(vector<StoredRecord>::const_iterator j=i->d_records.begin(); j != i->d_records.end(); ++j) {
+ for(auto j=i->d_records.cbegin(); j != i->d_records.cend(); ++j) {
count++;
try {
- DNSResourceRecord rr=String2DNSRR(i->d_qname, QType(i->d_qtype), j->d_string, j->d_ttd - now);
- fprintf(fp, "%s %d IN %s %s\n", rr.qname.toString().c_str(), rr.ttl, rr.qtype.getName().c_str(), rr.content.c_str());
+ fprintf(fp, "%s %d IN %s %s\n", i->d_qname.toString().c_str(), (int32_t)(i->d_ttd - now), DNSRecordContent::NumberToType(i->d_qtype).c_str(), (*j)->getZoneRepresentation().c_str());
}
catch(...) {
fprintf(fp, "; error printing '%s'\n", i->d_qname.toString().c_str());
}
unsigned int size();
unsigned int bytes();
- int get(time_t, const DNSName &qname, const QType& qt, set<DNSResourceRecord>* res, vector<std::shared_ptr<RRSIGRecordContent>>* signatures=0);
+ int get(time_t, const DNSName &qname, const QType& qt, vector<DNSRecord>* res, vector<std::shared_ptr<RRSIGRecordContent>>* signatures=0);
- int getDirect(time_t now, const char* qname, const QType& qt, uint32_t ttd[10], char* data[10], uint16_t len[10]);
- void replace(time_t, const DNSName &qname, const QType& qt, const set<DNSResourceRecord>& content, const vector<shared_ptr<RRSIGRecordContent>>& signatures, bool auth);
+ void replace(time_t, const DNSName &qname, const QType& qt, const vector<DNSRecord>& content, const vector<shared_ptr<RRSIGRecordContent>>& signatures, bool auth);
void doPrune(void);
void doSlash(int perc);
uint64_t doDump(int fd);
uint64_t cacheHits, cacheMisses;
private:
- struct StoredRecord
- {
- mutable uint32_t d_ttd;
- string d_string;
-
- bool operator<(const StoredRecord& rhs) const
- {
- return d_string < rhs.d_string;
- }
-
- unsigned int size() const
- {
- return sizeof(*this) + d_string.size();
- }
-
- };
struct CacheEntry
{
- CacheEntry(const boost::tuple<DNSName, uint16_t>& key, const vector<StoredRecord>& records, bool auth) :
- d_qname(key.get<0>()), d_qtype(key.get<1>()), d_auth(auth), d_records(records)
+ CacheEntry(const boost::tuple<DNSName, uint16_t>& key, const vector<shared_ptr<DNSRecordContent>>& records, bool auth) :
+ d_qname(key.get<0>()), d_qtype(key.get<1>()), d_auth(auth), d_records(records), d_ttd(0)
{}
- typedef vector<StoredRecord> records_t;
+ typedef vector<std::shared_ptr<DNSRecordContent>> records_t;
vector<std::shared_ptr<RRSIGRecordContent>> d_signatures;
uint32_t getTTD() const
{
- if(d_records.size()==1)
- return d_records.begin()->d_ttd;
-
- uint32_t earliest=std::numeric_limits<uint32_t>::max();
- for(records_t::const_iterator i=d_records.begin(); i != d_records.end(); ++i)
- earliest=min(earliest, i->d_ttd);
- return earliest;
+ return d_ttd;
}
DNSName d_qname;
uint16_t d_qtype;
bool d_auth;
records_t d_records;
+ uint32_t d_ttd;
};
typedef multi_index_container<
pair<cache_t::iterator, cache_t::iterator> d_cachecache;
DNSName d_cachedqname;
bool d_cachecachevalid;
- bool attemptToRefreshNSTTL(const QType& qt, const set<DNSResourceRecord>& content, const CacheEntry& stored);
+ bool attemptToRefreshNSTTL(const QType& qt, const vector<DNSRecord>& content, const CacheEntry& stored);
};
-string DNSRR2String(const DNSResourceRecord& rr);
-DNSResourceRecord String2DNSRR(const DNSName& qname, const QType& qt, const string& serial, uint32_t ttd);
-
#endif
void primeHints(void)
{
// prime root cache
- set<DNSResourceRecord>nsset;
+ vector<DNSRecord> nsset;
if(!t_RC)
t_RC = new MemRecursorCache();
"2001:503:c27::2:30", "2001:7fd::1", "2001:500:3::42", "2001:dc3::35"
};
- DNSResourceRecord arr, aaaarr, nsrr;
- arr.qtype=QType::A;
- aaaarr.qtype=QType::AAAA;
- nsrr.qtype=QType::NS;
- arr.ttl=aaaarr.ttl=nsrr.ttl=time(0)+3600000;
+ DNSRecord arr, aaaarr, nsrr;
+ arr.d_type=QType::A;
+ aaaarr.d_type=QType::AAAA;
+ nsrr.d_type=QType::NS;
+ arr.d_ttl=aaaarr.d_ttl=nsrr.d_ttl=time(0)+3600000;
for(char c='a';c<='m';++c) {
static char templ[40];
strncpy(templ,"a.root-servers.net.", sizeof(templ) - 1);
*templ=c;
- aaaarr.qname=arr.qname=DNSName(templ);
- nsrr.content=templ;
- arr.content=ips[c-'a'];
- set<DNSResourceRecord> aset;
- aset.insert(arr);
+ aaaarr.d_name=arr.d_name=DNSName(templ);
+ nsrr.d_content=std::make_shared<NSRecordContent>(DNSName(templ));
+ arr.d_content=std::make_shared<ARecordContent>(ComboAddress(ips[c-'a']));
+ vector<DNSRecord> aset;
+ aset.push_back(arr);
t_RC->replace(time(0), DNSName(templ), QType(QType::A), aset, vector<std::shared_ptr<RRSIGRecordContent>>(), true); // auth, nuke it all
if (ip6s[c-'a'] != NULL) {
- aaaarr.content=ip6s[c-'a'];
+ aaaarr.d_content=std::make_shared<AAAARecordContent>(ComboAddress(ip6s[c-'a']));
- set<DNSResourceRecord> aaaaset;
- aaaaset.insert(aaaarr);
+ vector<DNSRecord> aaaaset;
+ aaaaset.push_back(aaaarr);
t_RC->replace(time(0), DNSName(templ), QType(QType::AAAA), aaaaset, vector<std::shared_ptr<RRSIGRecordContent>>(), true);
}
- nsset.insert(nsrr);
+ nsset.push_back(nsrr);
}
}
else {
while(zpt.get(rr)) {
rr.ttl+=time(0);
if(rr.qtype.getCode()==QType::A) {
- set<DNSResourceRecord> aset;
- aset.insert(rr);
+ vector<DNSRecord> aset;
+ aset.push_back(DNSRecord(rr));
t_RC->replace(time(0), rr.qname, QType(QType::A), aset, vector<std::shared_ptr<RRSIGRecordContent>>(), true); // auth, etc see above
} else if(rr.qtype.getCode()==QType::AAAA) {
- set<DNSResourceRecord> aaaaset;
- aaaaset.insert(rr);
+ vector<DNSRecord> aaaaset;
+ aaaaset.push_back(DNSRecord(rr));
t_RC->replace(time(0), rr.qname, QType(QType::AAAA), aaaaset, vector<std::shared_ptr<RRSIGRecordContent>>(), true);
} else if(rr.qtype.getCode()==QType::NS) {
rr.content=toLower(rr.content);
- nsset.insert(rr);
+ nsset.push_back(DNSRecord(rr));
}
}
}
SyncRes::AuthDomain ad;
ad.d_rdForward=false;
- DNSResourceRecord rr;
- rr.qname=hostname;
- rr.d_place=DNSResourceRecord::ANSWER;
- rr.ttl=86400;
- rr.qtype=QType::SOA;
- rr.content="localhost. root 1 604800 86400 2419200 604800";
+ DNSRecord dr;
+ dr.d_name=hostname;
+ dr.d_place=DNSRecord::Answer;
+ dr.d_ttl=86400;
+ dr.d_type=QType::SOA;
+ dr.d_class = 1;
+ dr.d_content = std::shared_ptr<DNSRecordContent>(DNSRecordContent::mastermake(QType::SOA, 1, "localhost. root 1 604800 86400 2419200 604800"));
- ad.d_records.insert(rr);
+ ad.d_records.insert(dr);
- rr.qtype=QType::NS;
- rr.content="localhost.";
+ dr.d_type=QType::NS;
+ dr.d_content=std::make_shared<NSRecordContent>("localhost.");
- ad.d_records.insert(rr);
+ ad.d_records.insert(dr);
- rr.qtype=QType::A;
- rr.content=ip;
- ad.d_records.insert(rr);
+ dr.d_type=QType::A;
+ dr.d_content= std::shared_ptr<DNSRecordContent>(DNSRecordContent::mastermake(QType::A, 1, ip));
+ ad.d_records.insert(dr);
- if(newMap->count(rr.qname)) {
- L<<Logger::Warning<<"Hosts file will not overwrite zone '"<<rr.qname<<"' already loaded"<<endl;
+ if(newMap->count(dr.d_name)) {
+ L<<Logger::Warning<<"Hosts file will not overwrite zone '"<<dr.d_name<<"' already loaded"<<endl;
}
else {
- L<<Logger::Warning<<"Inserting forward zone '"<<rr.qname<<"' based on hosts file"<<endl;
- (*newMap)[rr.qname]=ad;
+ L<<Logger::Warning<<"Inserting forward zone '"<<dr.d_name<<"' based on hosts file"<<endl;
+ (*newMap)[dr.d_name]=ad;
}
}
SyncRes::AuthDomain ad;
ad.d_rdForward=false;
- DNSResourceRecord rr;
+ DNSRecord dr;
for(int n=ipparts.size()-1; n>=0 ; --n) {
- rr.qname.appendRawLabel(ipparts[n]);
+ dr.d_name.appendRawLabel(ipparts[n]);
}
- rr.qname.appendRawLabel("in-addr");
- rr.qname.appendRawLabel("arpa");
-
- rr.d_place=DNSResourceRecord::ANSWER;
- rr.ttl=86400;
- rr.qtype=QType::SOA;
- rr.content="localhost. root. 1 604800 86400 2419200 604800";
+ dr.d_name.appendRawLabel("in-addr");
+ dr.d_name.appendRawLabel("arpa");
+ dr.d_class = 1;
+ dr.d_place=DNSRecord::Answer;
+ dr.d_ttl=86400;
+ dr.d_type=QType::SOA;
+ dr.d_content=std::shared_ptr<DNSRecordContent>(DNSRecordContent::mastermake(QType::SOA, 1, "localhost. root 1 604800 86400 2419200 604800"));
- ad.d_records.insert(rr);
+ ad.d_records.insert(dr);
- rr.qtype=QType::NS;
- rr.content="localhost.";
+ dr.d_type=QType::NS;
+ dr.d_content=std::make_shared<NSRecordContent>(DNSName("localhost."));
- ad.d_records.insert(rr);
- rr.qtype=QType::PTR;
+ ad.d_records.insert(dr);
+ dr.d_type=QType::PTR;
if(ipparts.size()==4) // otherwise this is a partial zone
for(unsigned int n=1; n < parts.size(); ++n) {
- rr.content=DNSName(parts[n]).toString();
- ad.d_records.insert(rr);
+ dr.d_content=std::shared_ptr<DNSRecordContent>(DNSRecordContent::mastermake(QType::PTR, 1, DNSName(parts[n]).toString())); // XXX FIXME DNSNAME PAIN CAN THIS BE RIGHT?
+ ad.d_records.insert(dr);
}
- if(newMap->count(rr.qname)) {
- L<<Logger::Warning<<"Will not overwrite zone '"<<rr.qname<<"' already loaded"<<endl;
+ if(newMap->count(dr.d_name)) {
+ L<<Logger::Warning<<"Will not overwrite zone '"<<dr.d_name<<"' already loaded"<<endl;
}
else {
if(ipparts.size()==4)
- L<<Logger::Warning<<"Inserting reverse zone '"<<rr.qname<<"' based on hosts file"<<endl;
- (*newMap)[rr.qname]=ad;
+ L<<Logger::Warning<<"Inserting reverse zone '"<<dr.d_name<<"' based on hosts file"<<endl;
+ (*newMap)[dr.d_name]=ad;
}
}
for(SyncRes::domainmap_t::const_iterator i = t_sstorage->domainmap->begin(); i != t_sstorage->domainmap->end(); ++i) {
for(SyncRes::AuthDomain::records_t::const_iterator j = i->second.d_records.begin(); j != i->second.d_records.end(); ++j)
- broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, j->qname));
+ broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, j->d_name));
}
string configname=::arg()["config-dir"]+"/recursor.conf";
// purge again - new zones need to blank out the cache
for(SyncRes::domainmap_t::const_iterator i = newDomainMap->begin(); i != newDomainMap->end(); ++i) {
for(SyncRes::AuthDomain::records_t::const_iterator j = i->second.d_records.begin(); j != i->second.d_records.end(); ++j)
- broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, j->qname));
+ broadcastAccFunction<uint64_t>(boost::bind(pleaseWipeCache, j->d_name));
}
// this is pretty blunt
L<<Logger::Error<<"Parsing authoritative data for zone '"<<headers.first<<"' from file '"<<headers.second<<"'"<<endl;
ZoneParserTNG zpt(headers.second, DNSName(headers.first));
DNSResourceRecord rr;
+ DNSRecord dr;
while(zpt.get(rr)) {
try {
- string tmp=DNSRR2String(rr);
- rr=String2DNSRR(rr.qname, rr.qtype, tmp, rr.ttl);
+ dr=DNSRecord(rr);
+ dr.d_place=DNSRecord::Answer;
}
catch(std::exception &e) {
delete newMap;
throw PDNSException("Error parsing record '"+rr.qname.toString()+"' of type "+rr.qtype.getName()+" in zone '"+headers.first+"' from file '"+headers.second+"'");
}
- ad.d_records.insert(rr);
+ ad.d_records.insert(dr);
}
}
else {
gettimeofday(&now, 0);
SyncRes sr(now);
sr.d_doDNSSEC=true;
- vector<DNSResourceRecord> ret;
+ vector<DNSRecord> ret;
string version = "recursor-" +string(PACKAGEVERSION);
string qstring(version.substr(0, 63)+ ".security-status."+::arg()["security-poll-suffix"]);
DNSName query(qstring);
int res=sr.beginResolve(query, QType(QType::TXT), 1, ret);
if(!res && !ret.empty()) {
- string content=ret.begin()->content;
+ string content=ret.begin()->d_content->getZoneRepresentation();
if(!content.empty() && content[0]=='"' && content[content.size()-1]=='"') {
content=content.substr(1, content.length()-2);
}
} else if (optOutFlag != (ns3rc.d_flags & 1))
throw PDNSException("Zones with a mixture of Opt-Out NSEC3 RRs and non-Opt-Out NSEC3 RRs are not supported.");
optOutFlag = ns3rc.d_flags & 1;
- if (ns3rc.d_set.count(QType::NS) && !pdns_iequals(rr.qname, domain))
+ if (ns3rc.d_set.count(QType::NS) && !(rr.qname==domain))
secured.insert(DNSName(toLower(makeRelative(rr.qname.toString(), domain.toString())))); // XXX DNSName pain
continue;
}
break;
}
case QType::NS: {
- if(!pdns_iequals(rr.qname, domain))
+ if(rr.qname!=domain)
nsset.insert(rr.qname);
break;
}
if(nsset.count(shorter) && rr.qtype.getCode() != QType::DS)
rr.auth=false;
- if (pdns_iequals(shorter, domain)) // stop at apex
+ if (shorter==domain) // stop at apex
break;
}while(shorter.chopOff());
void operator()() const
{
vector<uint8_t> packet;
- DNSPacketWriter pw(packet, "outpost.ds9a.nl", QType::A);
+ DNSPacketWriter pw(packet, DNSName("outpost.ds9a.nl"), QType::A);
for(int records = 0; records < d_records; records++) {
- pw.startRecord("outpost.ds9a.nl", QType::A);
+ pw.startRecord(DNSName("outpost.ds9a.nl"), QType::A);
ARecordContent arc("1.2.3.4");
arc.toPacket(pw);
}
void operator()() const
{
vector<uint8_t> packet;
- DNSPacketWriter pw(packet, "outpost.ds9a.nl", QType::A);
+ DNSPacketWriter pw(packet, DNSName("outpost.ds9a.nl"), QType::A);
ARecordContent arc("1.2.3.4");
- string name("outpost.ds9a.nl");
+ DNSName name("outpost.ds9a.nl");
for(int records = 0; records < d_records; records++) {
pw.startRecord(name, QType::A);
void operator()() const
{
vector<uint8_t> packet;
- DNSPacketWriter pw(packet, "outpost.ds9a.nl", QType::TXT);
+ DNSPacketWriter pw(packet, DNSName("outpost.ds9a.nl"), QType::TXT);
for(int records = 0; records < d_records; records++) {
- pw.startRecord("outpost.ds9a.nl", QType::TXT);
+ pw.startRecord(DNSName("outpost.ds9a.nl"), QType::TXT);
TXTRecordContent arc("\"een leuk verhaaltje in een TXT\"");
arc.toPacket(pw);
}
void operator()() const
{
vector<uint8_t> packet;
- DNSPacketWriter pw(packet, "outpost.ds9a.nl", d_type);
+ DNSPacketWriter pw(packet, DNSName("outpost.ds9a.nl"), d_type);
for(int records = 0; records < d_records; records++) {
- pw.startRecord("outpost.ds9a.nl", d_type);
+ pw.startRecord(DNSName("outpost.ds9a.nl"), d_type);
DNSRecordContent*drc = DNSRecordContent::mastermake(d_type, 1,
d_content);
drc->toPacket(pw);
void operator()() const
{
vector<uint8_t> packet;
- DNSPacketWriter pw(packet, "outpost.ds9a.nl", QType::AAAA);
+ DNSPacketWriter pw(packet, DNSName("outpost.ds9a.nl"), QType::AAAA);
for(int records = 0; records < d_records; records++) {
- pw.startRecord("outpost.ds9a.nl", QType::AAAA);
+ pw.startRecord(DNSName("outpost.ds9a.nl"), QType::AAAA);
DNSRecordContent*drc = DNSRecordContent::mastermake(QType::AAAA, 1, "fe80::21d:92ff:fe6d:8441");
drc->toPacket(pw);
delete drc;
void operator()() const
{
vector<uint8_t> packet;
- DNSPacketWriter pw(packet, "outpost.ds9a.nl", QType::SOA);
+ DNSPacketWriter pw(packet, DNSName("outpost.ds9a.nl"), QType::SOA);
for(int records = 0; records < d_records; records++) {
- pw.startRecord("outpost.ds9a.nl", QType::SOA);
+ pw.startRecord(DNSName("outpost.ds9a.nl"), QType::SOA);
DNSRecordContent*drc = DNSRecordContent::mastermake(QType::SOA, 1, "a0.org.afilias-nst.info. noc.afilias-nst.info. 2008758137 1800 900 604800 86400");
drc->toPacket(pw);
delete drc;
vector<uint8_t> makeEmptyQuery()
{
vector<uint8_t> packet;
- DNSPacketWriter pw(packet, "outpost.ds9a.nl", QType::SOA);
+ DNSPacketWriter pw(packet, DNSName("outpost.ds9a.nl"), QType::SOA);
return packet;
}
vector<uint8_t> makeRootReferral()
{
vector<uint8_t> packet;
- DNSPacketWriter pw(packet, "outpost.ds9a.nl", QType::SOA);
+ DNSPacketWriter pw(packet, DNSName("outpost.ds9a.nl"), QType::SOA);
// nobody reads what we output, but it appears to be the magic that shuts some nameservers up
static const char*ips[]={"198.41.0.4", "192.228.79.201", "192.33.4.12", "199.7.91.13", "192.203.230.10", "192.5.5.241", "192.112.36.4", "128.63.2.53",
for(char c='a';c<='m';++c) {
*templ=c;
- pw.startRecord(".", QType::NS, 3600, 1, DNSPacketWriter::AUTHORITY);
+ pw.startRecord(DNSName(), QType::NS, 3600, 1, DNSPacketWriter::AUTHORITY);
DNSRecordContent* drc = DNSRecordContent::mastermake(QType::NS, 1, templ);
drc->toPacket(pw);
delete drc;
for(char c='a';c<='m';++c) {
*templ=c;
- pw.startRecord(".", QType::A, 3600, 1, DNSPacketWriter::ADDITIONAL);
+ pw.startRecord(DNSName(), QType::A, 3600, 1, DNSPacketWriter::ADDITIONAL);
DNSRecordContent* drc = DNSRecordContent::mastermake(QType::A, 1, ips[c-'a']);
drc->toPacket(pw);
delete drc;
vector<uint8_t> makeTypicalReferral()
{
vector<uint8_t> packet;
- DNSPacketWriter pw(packet, "outpost.ds9a.nl", QType::A);
+ DNSPacketWriter pw(packet, DNSName("outpost.ds9a.nl"), QType::A);
- pw.startRecord("ds9a.nl", QType::NS, 3600, 1, DNSPacketWriter::AUTHORITY);
+ pw.startRecord(DNSName("ds9a.nl"), QType::NS, 3600, 1, DNSPacketWriter::AUTHORITY);
DNSRecordContent* drc = DNSRecordContent::mastermake(QType::NS, 1, "ns1.ds9a.nl");
drc->toPacket(pw);
delete drc;
- pw.startRecord("ds9a.nl", QType::NS, 3600, 1, DNSPacketWriter::AUTHORITY);
+ pw.startRecord(DNSName("ds9a.nl"), QType::NS, 3600, 1, DNSPacketWriter::AUTHORITY);
drc = DNSRecordContent::mastermake(QType::NS, 1, "ns2.ds9a.nl");
drc->toPacket(pw);
delete drc;
- pw.startRecord("ns1.ds9a.nl", QType::A, 3600, 1, DNSPacketWriter::ADDITIONAL);
+ pw.startRecord(DNSName("ns1.ds9a.nl"), QType::A, 3600, 1, DNSPacketWriter::ADDITIONAL);
drc = DNSRecordContent::mastermake(QType::A, 1, "1.2.3.4");
drc->toPacket(pw);
delete drc;
- pw.startRecord("ns2.ds9a.nl", QType::A, 3600, 1, DNSPacketWriter::ADDITIONAL);
+ pw.startRecord(DNSName("ns2.ds9a.nl"), QType::A, 3600, 1, DNSPacketWriter::ADDITIONAL);
drc = DNSRecordContent::mastermake(QType::A, 1, "4.3.2.1");
drc->toPacket(pw);
delete drc;
for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) {
DNSResourceRecord rr;
rr.qtype=i->first.d_type;
- rr.qname=i->first.d_label;
+ rr.qname=i->first.d_name;
rr.ttl=i->first.d_ttl;
rr.content=i->first.d_content->getZoneRepresentation(); // this should be the serialised form
try
{
reportAllTypes();
+
doRun(NOPTest());
doRun(IEqualsTest());
}
/** everything begins here - this is the entry point just after receiving a packet */
-int SyncRes::beginResolve(const DNSName &qname, const QType &qtype, uint16_t qclass, vector<DNSResourceRecord>&ret)
+int SyncRes::beginResolve(const DNSName &qname, const QType &qtype, uint16_t qclass, vector<DNSRecord>&ret)
{
s_queries++;
if( (qtype.getCode()==QType::PTR && qname==arpa) ||
(qtype.getCode()==QType::A && qname==localhost)) {
ret.clear();
- DNSResourceRecord rr;
- rr.qname=qname;
- rr.qtype=qtype;
- rr.qclass=QClass::IN;
- rr.ttl=86400;
+ DNSRecord dr;
+ dr.d_name=qname;
+ dr.d_place = DNSRecord::Answer;
+ dr.d_type=qtype.getCode();
+ dr.d_class=QClass::IN;
+ dr.d_ttl=86400;
if(qtype.getCode()==QType::PTR)
- rr.content="localhost.";
+ dr.d_content=shared_ptr<DNSRecordContent>(DNSRecordContent::mastermake(QType::PTR, 1, "localhost."));
else
- rr.content="127.0.0.1";
- ret.push_back(rr);
+ dr.d_content=shared_ptr<DNSRecordContent>(DNSRecordContent::mastermake(QType::A, 1, "127.0.0.1"));
+ ret.push_back(dr);
return 0;
}
(qname==versionbind || qname==idserver || qname==versionpdns )
) {
ret.clear();
- DNSResourceRecord rr;
- rr.qname=qname;
- rr.qtype=qtype;
- rr.qclass=qclass;
- rr.ttl=86400;
+ DNSRecord dr;
+ dr.d_name=qname;
+ dr.d_type=qtype.getCode();
+ dr.d_class=qclass;
+ dr.d_ttl=86400;
+ dr.d_place = DNSRecord::Answer;
if(qname==versionbind || qname==versionpdns)
- rr.content="\""+::arg()["version-string"]+"\"";
+ dr.d_content=shared_ptr<DNSRecordContent>(DNSRecordContent::mastermake(QType::TXT, 3, "\""+::arg()["version-string"]+"\""));
else
- rr.content="\""+s_serverID+"\"";
- ret.push_back(rr);
+ dr.d_content=shared_ptr<DNSRecordContent>(DNSRecordContent::mastermake(QType::TXT, 3, "\""+s_serverID+"\""));
+
+ ret.push_back(dr);
return 0;
}
}
//! This is the 'out of band resolver', in other words, the authoritative server
-bool SyncRes::doOOBResolve(const DNSName &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int& res)
+bool SyncRes::doOOBResolve(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, int depth, int& res)
{
string prefix;
if(doLog()) {
bool somedata=false;
for(ziter=range.first; ziter!=range.second; ++ziter) {
somedata=true;
- if(qtype.getCode()==QType::ANY || ziter->qtype==qtype || ziter->qtype.getCode()==QType::CNAME) // let rest of nameserver do the legwork on this one
+ if(qtype.getCode()==QType::ANY || ziter->d_type==qtype.getCode() || ziter->d_type==QType::CNAME) // let rest of nameserver do the legwork on this one
ret.push_back(*ziter);
}
if(!ret.empty()) {
}
if(somedata) {
LOG(prefix<<qname.toString()<<": found record in '"<<authdomain.toString()<<"', but nothing of the right type, sending SOA"<<endl);
- ziter=iter->second.d_records.find(boost::make_tuple(authdomain, QType(QType::SOA)));
+ ziter=iter->second.d_records.find(boost::make_tuple(authdomain, QType::SOA));
if(ziter!=iter->second.d_records.end()) {
- DNSResourceRecord rr=*ziter;
- rr.d_place=DNSResourceRecord::AUTHORITY;
- ret.push_back(rr);
+ DNSRecord dr=*ziter;
+ dr.d_place=DNSRecord::Nameserver;
+ ret.push_back(dr);
}
else
LOG(prefix<<qname.toString()<<": can't find SOA record '"<<authdomain.toString()<<"' in our zone!"<<endl);
LOG(prefix<<qname.toString()<<": nothing found so far in '"<<authdomain.toString()<<"', trying wildcards"<<endl);
DNSName wcarddomain(qname);
- while(!pdns_iequals(wcarddomain, iter->first) && wcarddomain.chopOff()) {
+ while(wcarddomain != iter->first && wcarddomain.chopOff()) {
LOG(prefix<<qname.toString()<<": trying '*."+wcarddomain.toString()+"' in "<<authdomain.toString()<<endl);
range=iter->second.d_records.equal_range(boost::make_tuple(DNSName("*")+wcarddomain));
if(range.first==range.second)
continue;
for(ziter=range.first; ziter!=range.second; ++ziter) {
- DNSResourceRecord rr=*ziter;
- if(rr.qtype == qtype || qtype.getCode() == QType::ANY) {
- rr.qname = qname;
- rr.d_place=DNSResourceRecord::ANSWER;
- ret.push_back(rr);
+ DNSRecord dr=*ziter;
+ if(dr.d_type == qtype.getCode() || qtype.getCode() == QType::ANY) {
+ dr.d_name = qname;
+ dr.d_place=DNSRecord::Answer;
+ ret.push_back(dr);
}
}
LOG(prefix<<qname.toString()<<": in '"<<authdomain.toString()<<"', had wildcard match on '*."+wcarddomain.toString()+"'"<<endl);
DNSName nsdomain(qname);
- while(nsdomain.chopOff() && !pdns_iequals(nsdomain, iter->first)) {
- range=iter->second.d_records.equal_range(boost::make_tuple(nsdomain,QType(QType::NS)));
+ while(nsdomain.chopOff() && nsdomain != iter->first) {
+ range=iter->second.d_records.equal_range(boost::make_tuple(nsdomain,QType::NS));
if(range.first==range.second)
continue;
for(ziter=range.first; ziter!=range.second; ++ziter) {
- DNSResourceRecord rr=*ziter;
- rr.d_place=DNSResourceRecord::AUTHORITY;
- ret.push_back(rr);
+ DNSRecord dr=*ziter;
+ dr.d_place=DNSRecord::Nameserver;
+ ret.push_back(dr);
}
}
if(ret.empty()) {
LOG(prefix<<qname.toString()<<": no NS match in zone '"<<authdomain.toString()<<"' either, handing out SOA"<<endl);
- ziter=iter->second.d_records.find(boost::make_tuple(authdomain, QType(QType::SOA)));
+ ziter=iter->second.d_records.find(boost::make_tuple(authdomain, QType::SOA));
if(ziter!=iter->second.d_records.end()) {
- DNSResourceRecord rr=*ziter;
- rr.d_place=DNSResourceRecord::AUTHORITY;
- ret.push_back(rr);
+ DNSRecord dr=*ziter;
+ dr.d_place=DNSRecord::Nameserver;
+ ret.push_back(dr);
}
- else
+ else {
LOG(prefix<<qname.toString()<<": can't find SOA record '"<<authdomain.toString()<<"' in our zone!"<<endl);
+ }
res=RCode::NXDomain;
}
else
int ret;
for(int tries = 0; tries < 3; ++tries) {
- cerr<<"Remote '"<<ip.toString()<<"' currently in mode "<<mode<<endl;
+ // cerr<<"Remote '"<<ip.toString()<<"' currently in mode "<<mode<<endl;
if(mode==EDNSStatus::UNKNOWN || mode==EDNSStatus::EDNSOK || mode==EDNSStatus::EDNSIGNORANT)
EDNSLevel = 1;
ret=asyncresolve(ip, domain, type, doTCP, sendRDQuery, EDNSLevel, now, res);
if(ret == 0 || ret < 0) {
- cerr<< (ret < 0 ? "Transport error" : "Timeout")<<" for query to "<<ip.toString()<<" for '"<<domain.toString()<<"' (ret="<<ret<<"), no change in mode"<<endl;
+ // cerr<< (ret < 0 ? "Transport error" : "Timeout")<<" for query to "<<ip.toString()<<" for '"<<domain.toString()<<"' (ret="<<ret<<"), no change in mode"<<endl;
return ret;
}
else if(mode==EDNSStatus::UNKNOWN || mode==EDNSStatus::EDNSOK || mode == EDNSStatus::EDNSIGNORANT ) {
if(res->d_rcode == RCode::FormErr || res->d_rcode == RCode::NotImp) {
- cerr<<"Downgrading to NOEDNS because of "<<RCode::to_s(res->d_rcode)<<" for query to "<<ip.toString()<<" for '"<<domain.toString()<<"'"<<endl;
+ // cerr<<"Downgrading to NOEDNS because of "<<RCode::to_s(res->d_rcode)<<" for query to "<<ip.toString()<<" for '"<<domain.toString()<<"'"<<endl;
mode = EDNSStatus::NOEDNS;
continue;
}
else if(!res->d_haveEDNS) {
if(mode != EDNSStatus::EDNSIGNORANT) {
mode = EDNSStatus::EDNSIGNORANT;
- cerr<<"We find that "<<ip.toString()<<" is an EDNS-ignorer for '"<<domain.toString()<<"', moving to mode 3"<<endl;
+ // cerr<<"We find that "<<ip.toString()<<" is an EDNS-ignorer for '"<<domain.toString()<<"', moving to mode 3"<<endl;
}
}
else {
mode = EDNSStatus::EDNSOK;
- cerr<<"We find that "<<ip.toString()<<" is EDNS OK!"<<endl;
+ // cerr<<"We find that "<<ip.toString()<<" is EDNS OK!"<<endl;
}
}
if(oldmode != mode)
ednsstatus->modeSetAt=d_now.tv_sec;
- cerr<<"Result: ret="<<ret<<", EDNS-level: "<<EDNSLevel<<", haveEDNS: "<<res->d_haveEDNS<<", new mode: "<<mode<<endl;
+ // cerr<<"Result: ret="<<ret<<", EDNS-level: "<<EDNSLevel<<", haveEDNS: "<<res->d_haveEDNS<<", new mode: "<<mode<<endl;
return ret;
}
return ret;
}
-int SyncRes::doResolve(const DNSName &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, set<GetBestNSAnswer>& beenthere)
+int SyncRes::doResolve(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, int depth, set<GetBestNSAnswer>& beenthere)
{
string prefix;
if(doLog()) {
// filter out the good stuff from lwr.result()
for(const auto& rec : lwr.d_records) {
- if((DNSResourceRecord::Place)rec.first.d_place == DNSResourceRecord::ANSWER)
- ret.push_back(DNSResourceRecord(rec.first));
+ if(rec.d_place == DNSRecord::Answer)
+ ret.push_back(rec);
}
return res;
}
return 0;
LOG(prefix<<qname.toString()<<": failed (res="<<res<<")"<<endl);
+ ;
return res<0 ? RCode::ServFail : res;
}
*/
vector<ComboAddress> SyncRes::getAddrs(const DNSName &qname, int depth, set<GetBestNSAnswer>& beenthere)
{
- typedef vector<DNSResourceRecord> res_t;
+ typedef vector<DNSRecord> res_t;
res_t res;
typedef vector<ComboAddress> ret_t;
if(!doResolve(qname, type, res,depth+1, beenthere) && !res.empty()) { // this consults cache, OR goes out
for(res_t::const_iterator i=res.begin(); i!= res.end(); ++i) {
- if(i->qtype.getCode()==QType::A || i->qtype.getCode()==QType::AAAA) {
- ret.push_back(ComboAddress(i->content, 53));
+ if(i->d_type == QType::A || i->d_type == QType::AAAA) {
+ if(auto rec = std::dynamic_pointer_cast<ARecordContent>(i->d_content))
+ ret.push_back(rec->getCA(53));
+ else if(auto rec = std::dynamic_pointer_cast<AAAARecordContent>(i->d_content))
+ ret.push_back(rec->getCA(53));
done=true;
}
}
}
if(done) {
if(j==1 && s_doIPv6) { // we got an A record, see if we have some AAAA lying around
- set<DNSResourceRecord> cset;
+ vector<DNSRecord> cset;
if(t_RC->get(d_now.tv_sec, qname, QType(QType::AAAA), &cset) > 0) {
- for(set<DNSResourceRecord>::const_iterator k=cset.begin();k!=cset.end();++k) {
- if(k->ttl > (unsigned int)d_now.tv_sec ) {
- ret.push_back(ComboAddress(k->content, 53));
+ for(auto k=cset.cbegin();k!=cset.cend();++k) {
+ if(k->d_ttl > (unsigned int)d_now.tv_sec ) {
+ ComboAddress ca=std::dynamic_pointer_cast<AAAARecordContent>(k->d_content)->getCA(53);
+ ret.push_back(ca);
}
}
}
return ret;
}
-void SyncRes::getBestNSFromCache(const DNSName &qname, const QType& qtype, set<DNSResourceRecord>&bestns, bool* flawedNSSet, int depth, set<GetBestNSAnswer>& beenthere)
+void SyncRes::getBestNSFromCache(const DNSName &qname, const QType& qtype, vector<DNSRecord>& bestns, bool* flawedNSSet, int depth, set<GetBestNSAnswer>& beenthere)
{
string prefix;
DNSName subdomain(qname);
do {
brokeloop=false;
LOG(prefix<<qname.toString()<<": Checking if we have NS in cache for '"<<subdomain.toString()<<"'"<<endl);
- set<DNSResourceRecord> ns;
+ vector<DNSRecord> ns;
*flawedNSSet = false;
if(t_RC->get(d_now.tv_sec, subdomain, QType(QType::NS), &ns) > 0) {
- for(set<DNSResourceRecord>::const_iterator k=ns.begin();k!=ns.end();++k) {
- if(k->ttl > (unsigned int)d_now.tv_sec ) {
- set<DNSResourceRecord> aset;
+ for(auto k=ns.cbegin();k!=ns.cend(); ++k) {
+ if(k->d_ttl > (unsigned int)d_now.tv_sec ) {
+ vector<DNSRecord> aset;
- DNSResourceRecord rr=*k;
- rr.content=k->content;
- if(!DNSName(rr.content).isPartOf(subdomain) || t_RC->get(d_now.tv_sec, DNSName(rr.content), s_doIPv6 ? QType(QType::ADDR) : QType(QType::A),
+ const DNSRecord& dr=*k;
+ auto nrr = std::dynamic_pointer_cast<NSRecordContent>(dr.d_content);
+ if(!nrr->getNS().isPartOf(subdomain) || t_RC->get(d_now.tv_sec, nrr->getNS(), s_doIPv6 ? QType(QType::ADDR) : QType(QType::A),
doLog() ? &aset : 0) > 5) {
- bestns.insert(rr);
- LOG(prefix<<qname.toString()<<": NS (with ip, or non-glue) in cache for '"<<subdomain.toString()<<"' -> '"<<rr.content<<"'"<<endl);
- LOG(prefix<<qname.toString()<<": within bailiwick: "<<DNSName(rr.content).isPartOf(subdomain) /* ugh */);
+ bestns.push_back(dr);
+ LOG(prefix<<qname.toString()<<": NS (with ip, or non-glue) in cache for '"<<subdomain.toString()<<"' -> '"<<nrr->getNS()<<"'"<<endl);
+ LOG(prefix<<qname.toString()<<": within bailiwick: "<< nrr->getNS().isPartOf(subdomain));
if(!aset.empty()) {
- LOG(", in cache, ttl="<<(unsigned int)(((time_t)aset.begin()->ttl- d_now.tv_sec ))<<endl);
+ LOG(", in cache, ttl="<<(unsigned int)(((time_t)aset.begin()->d_ttl- d_now.tv_sec ))<<endl);
}
else {
LOG(", not in cache / did not look at cache"<<endl);
}
else {
*flawedNSSet=true;
- LOG(prefix<<qname.toString()<<": NS in cache for '"<<subdomain.toString()<<"', but needs glue ("<<k->content<<") which we miss or is expired"<<endl);
+ LOG(prefix<<qname<<": NS in cache for '"<<subdomain<<"', but needs glue ("<<nrr->getNS()<<") which we miss or is expired"<<endl);
}
}
}
GetBestNSAnswer answer;
answer.qname=qname;
answer.qtype=qtype.getCode();
- BOOST_FOREACH(const DNSResourceRecord& rr, bestns)
- answer.bestns.insert(make_pair(rr.qname, rr.content));
+ for(const auto& dr : bestns)
+ answer.bestns.insert(make_pair(dr.d_name, dr.d_content->getZoneRepresentation()));
+ // XXX we are passing a DNSName through a string here!
if(beenthere.count(answer)) {
brokeloop=true;
LOG(prefix<<qname.toString()<<": We have NS in cache for '"<<subdomain.toString()<<"' but part of LOOP (already seen "<<answer.qname.toString()<<")! Trying less specific NS"<<endl);
+ ;
if(doLog())
for( set<GetBestNSAnswer>::const_iterator j=beenthere.begin();j!=beenthere.end();++j) {
bool neo = !(*j< answer || answer<*j);
}
}
LOG(prefix<<qname.toString()<<": no valid/useful NS in cache for '"<<subdomain.toString()<<"'"<<endl);
+ ;
if(subdomain.isRoot() && !brokeloop) {
primeHints();
LOG(prefix<<qname.toString()<<": reprimed the root"<<endl);
else {
for(vector<ComboAddress>::const_iterator server=iter->second.d_servers.begin(); server != iter->second.d_servers.end(); ++server)
// nsset.insert((iter->second.d_rdForward ? "+" : "-") + server->toStringWithPort()); // add a '+' if the rd bit should be set
- // XXX this doesn't work, nsset can't contain a port number, or a plus etc!
+ // XXX this doesn't work, nsset can't contain a port number, or a plus etc! DNSNAME PAIN
abort();
}
return authdomain;
}
- set<DNSResourceRecord> bestns;
+ vector<DNSRecord> bestns;
getBestNSFromCache(subdomain, qtype, bestns, flawedNSSet, depth, beenthere);
- for(set<DNSResourceRecord>::const_iterator k=bestns.begin();k!=bestns.end();++k) {
- nsset.insert(DNSName(k->content));
- if(k==bestns.begin())
- subdomain=k->qname;
+ for(auto k=bestns.cbegin() ; k != bestns.cend(); ++k) {
+ nsset.insert(std::dynamic_pointer_cast<NSRecordContent>(k->d_content)->getNS());
+ if(k==bestns.cbegin())
+ subdomain=k->d_name;
}
return subdomain;
}
-bool SyncRes::doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res)
+bool SyncRes::doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector<DNSRecord>& ret, int depth, int &res)
{
string prefix;
if(doLog()) {
}
LOG(prefix<<qname.toString()<<": Looking for CNAME cache hit of '"<<(qname.toString()+"|CNAME")<<"'"<<endl);
- set<DNSResourceRecord> cset;
+ vector<DNSRecord> cset;
if(t_RC->get(d_now.tv_sec, qname,QType(QType::CNAME),&cset) > 0) {
- for(set<DNSResourceRecord>::const_iterator j=cset.begin();j!=cset.end();++j) {
- if(j->ttl>(unsigned int) d_now.tv_sec) {
- LOG(prefix<<qname.toString()<<": Found cache CNAME hit for '"<< (qname.toString()+"|CNAME") <<"' to '"<<j->content<<"'"<<endl);
- DNSResourceRecord rr=*j;
- rr.ttl-=d_now.tv_sec;
- ret.push_back(rr);
+ for(auto j=cset.cbegin() ; j != cset.cend() ; ++j) {
+ if(j->d_ttl>(unsigned int) d_now.tv_sec) {
+ LOG(prefix<<qname.toString()<<": Found cache CNAME hit for '"<< (qname.toString()+"|CNAME") <<"' to '"<<j->d_content->getZoneRepresentation()<<"'"<<endl);
+ DNSRecord dr=*j;
+ dr.d_ttl-=d_now.tv_sec;
+ ret.push_back(dr);
if(!(qtype==QType(QType::CNAME))) { // perhaps they really wanted a CNAME!
set<GetBestNSAnswer>beenthere;
- res=doResolve(DNSName(j->content), qtype, ret, depth+1, beenthere);
+ res=doResolve(std::dynamic_pointer_cast<CNAMERecordContent>(j->d_content)->getTarget(), qtype, ret, depth+1, beenthere);
}
else
res=0;
return ret;
}
-bool SyncRes::doCacheCheck(const DNSName &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res)
+
+bool SyncRes::doCacheCheck(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, int depth, int &res)
{
bool giveNegative=false;
}
}
}
- set<DNSResourceRecord> cset;
+ vector<DNSRecord> cset;
bool found=false, expired=false;
vector<std::shared_ptr<RRSIGRecordContent>> signatures;
uint32_t ttl=0;
if(t_RC->get(d_now.tv_sec, sqname, sqt, &cset, d_doDNSSEC ? &signatures : 0) > 0) {
LOG(prefix<<sqname.toString()<<": Found cache hit for "<<sqt.getName()<<": ");
- for(set<DNSResourceRecord>::const_iterator j=cset.begin();j!=cset.end();++j) {
- LOG(j->content);
- if(j->ttl>(unsigned int) d_now.tv_sec) {
- DNSResourceRecord rr=*j;
- ttl=rr.ttl-=d_now.tv_sec;
+ for(auto j=cset.cbegin() ; j != cset.cend() ; ++j) {
+ LOG(j->d_content->getZoneRepresentation());
+ if(j->d_ttl>(unsigned int) d_now.tv_sec) {
+ DNSRecord dr=*j;
+ ttl = (dr.d_ttl-=d_now.tv_sec);
if(giveNegative) {
- rr.d_place=DNSResourceRecord::AUTHORITY;
- rr.ttl=sttl;
+ dr.d_place=DNSRecord::Nameserver;
+ dr.d_ttl=sttl;
}
- ret.push_back(rr);
- LOG("[ttl="<<rr.ttl<<"] ");
+ ret.push_back(dr);
+ LOG("[ttl="<<dr.d_ttl<<"] ");
found=true;
}
else {
}
for(const auto& signature : signatures) {
- DNSResourceRecord rr;
- rr.qtype=QType(QType::RRSIG);
- rr.qname=sqname;
- rr.ttl=ttl;
- rr.content=signature->getZoneRepresentation();
- rr.d_place=DNSResourceRecord::ANSWER;
-
- ret.push_back(rr);
+ DNSRecord dr;
+ dr.d_type=QType::RRSIG;
+ dr.d_name=sqname;
+ dr.d_ttl=ttl;
+ dr.d_content=signature;
+ dr.d_place=DNSRecord::Answer;
+ dr.d_class=1;
+ ret.push_back(dr);
}
LOG(endl);
if(doLog()) {
LOG(prefix<<"Nameservers: ");
- for(vector<DNSName>::const_iterator i=rnameservers.begin();i!=rnameservers.end();++i) {
+ for(vector<DNSName>::const_iterator i=rnameservers.begin();i!=rnameservers.end();++i) {
if(i!=rnameservers.begin()) {
LOG(", ");
if(!((i-rnameservers.begin())%3)) {
/** returns -1 in case of no results, rcode otherwise */
int SyncRes::doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType &qtype,
- vector<DNSResourceRecord>&ret,
+ vector<DNSRecord>&ret,
int depth, set<GetBestNSAnswer>&beenthere)
{
string prefix;
LOG(prefix<<qname.toString()<<": Failed to resolve via any of the "<<(unsigned int)rnameservers.size()<<" offered NS at level '"<<auth.toString()<<"'"<<endl);
if(auth!=DNSName() && flawedNSSet) {
LOG(prefix<<qname.toString()<<": Ageing nameservers for level '"<<auth.toString()<<"', next query might succeed"<<endl);
+
if(t_RC->doAgeCache(d_now.tv_sec, auth, QType::NS, 10))
g_stats.nsSetInvalidations++;
}
return -1;
}
// this line needs to identify the 'self-resolving' behaviour, but we get it wrong now
- if(pdns_iequals(qname, *tns) && qtype.getCode()==QType::A && rnameservers.size() > (unsigned)(1+1*s_doIPv6)) {
+ if(qname == *tns && qtype.getCode()==QType::A && rnameservers.size() > (unsigned)(1+1*s_doIPv6)) {
LOG(prefix<<qname.toString()<<": Not using NS to resolve itself! ("<<(1+tns-rnameservers.begin())<<"/"<<rnameservers.size()<<")"<<endl);
continue;
}
LWResult lwr;
if(tns->empty()) {
LOG(prefix<<qname.toString()<<": Domain is out-of-band"<<endl);
- doOOBResolve(qname, qtype, lwr.d_result, depth, lwr.d_rcode);
+ doOOBResolve(qname, qtype, lwr.d_records, depth, lwr.d_rcode);
lwr.d_tcbit=false;
lwr.d_aabit=true;
}
else {
LOG(prefix<<qname.toString()<<": Trying to resolve NS '"<<tns->toString()<< "' ("<<1+tns-rnameservers.begin()<<"/"<<(unsigned int)rnameservers.size()<<")"<<endl);
+ ;
if(!isCanonical(*tns)) {
LOG(prefix<<qname.toString()<<": Domain has hardcoded nameserver(s)"<<endl);
if(s_maxtotusec && d_totUsec > s_maxtotusec)
throw ImmediateServFailException("Too much time waiting for "+qname.toString()+"|"+qtype.getName()+", timeouts: "+boost::lexical_cast<string>(d_timeouts) +", throttles: "+boost::lexical_cast<string>(d_throttledqueries) + ", queries: "+lexical_cast<string>(d_outqueries)+", "+lexical_cast<string>(d_totUsec/1000)+"msec");
- if(d_pdl && d_pdl->preoutquery(*remoteIP, d_requestor, qname, qtype, lwr.d_result, resolveret)) {
+ if(d_pdl && d_pdl->preoutquery(*remoteIP, d_requestor, qname, qtype, lwr.d_records, resolveret)) {
LOG(prefix<<qname.toString()<<": query handled by Lua"<<endl);
}
else
LOG(prefix<<qname.toString()<<": truncated bit set, over TCP?"<<endl);
return RCode::ServFail;
}
- LOG(prefix<<qname.toString()<<": Got "<<(unsigned int)lwr.d_result.size()<<" answers from "<<tns->toString()<<" ("<< remoteIP->toString() <<"), rcode="<<lwr.d_rcode<<" ("<<RCode::to_s(lwr.d_rcode)<<"), aa="<<lwr.d_aabit<<", in "<<lwr.d_usec/1000<<"ms"<<endl);
+ LOG(prefix<<qname.toString()<<": Got "<<(unsigned int)lwr.d_records.size()<<" answers from "<<tns->toString()<<" ("<< remoteIP->toString() <<"), rcode="<<lwr.d_rcode<<" ("<<RCode::to_s(lwr.d_rcode)<<"), aa="<<lwr.d_aabit<<", in "<<lwr.d_usec/1000<<"ms"<<endl);
/* // for you IPv6 fanatics :-)
if(remoteIP->sin4.sin_family==AF_INET6)
if(s_minimumTTL) {
for(auto& rec : lwr.d_records) {
- rec.first.d_ttl = max(rec.first.d_ttl, s_minimumTTL);
+ rec.d_ttl = max(rec.d_ttl, s_minimumTTL);
}
}
struct CachePair
{
- set<DNSResourceRecord> records;
+ vector<DNSRecord> records;
vector<shared_ptr<RRSIGRecordContent>> signatures;
};
typedef map<pair<DNSName, QType>, CachePair, TCacheComp > tcache_t;
if(d_doDNSSEC) {
for(const auto& rec : lwr.d_records) {
- if(rec.first.d_type == QType::RRSIG) {
- auto rrsig = std::dynamic_pointer_cast<RRSIGRecordContent>(rec.first.d_content);
- cerr<<"Got an RRSIG for "<<DNSRecordContent::NumberToType(rrsig->d_type)<<" with name '"<<rec.first.d_name<<"'"<<endl;
- tcache[make_pair(rec.first.d_name, QType(rrsig->d_type))].signatures.push_back(rrsig);
+ if(rec.d_type == QType::RRSIG) {
+ auto rrsig = std::dynamic_pointer_cast<RRSIGRecordContent>(rec.d_content);
+ // cerr<<"Got an RRSIG for "<<DNSRecordContent::NumberToType(rrsig->d_type)<<" with name '"<<rec.d_name<<"'"<<endl;
+ tcache[make_pair(rec.d_name, QType(rrsig->d_type))].signatures.push_back(rrsig);
}
}
}
// reap all answers from this packet that are acceptable
- for(LWResult::res_t::iterator i=lwr.getResult().begin();i != lwr.getResult().end();++i) {
- if(i->qtype.getCode() == QType::OPT) {
- LOG(prefix<<qname.toString()<<": skipping OPT answer '"<<i->qname.toString()<<"' from '"<<auth.toString()<<"' nameservers" <<endl);
+ for(auto& rec : lwr.d_records) {
+ if(rec.d_type == QType::OPT) {
+ LOG(prefix<<qname.toString()<<": skipping OPT answer '"<<rec.d_name<<"' from '"<<auth.toString()<<"' nameservers" <<endl);
continue;
}
- LOG(prefix<<qname.toString()<<": accept answer '"<<i->qname.toString()<<"|"<<i->qtype.getName()<<"|"<<i->content<<"' from '"<<auth.toString()<<"' nameservers? ");
- if(i->qtype.getCode()==QType::ANY) {
+ LOG(prefix<<qname.toString()<<": accept answer '"<<rec.d_name<<"|"<<DNSRecordContent::NumberToType(rec.d_type)<<"|"<<rec.d_content->getZoneRepresentation()<<"' from '"<<auth.toString()<<"' nameservers? "<<(int)rec.d_place<<" ");
+ if(rec.d_type == QType::ANY) {
LOG("NO! - we don't accept 'ANY' data"<<endl);
continue;
}
// Check if we are authoritative for a zone in this answer
if (!t_sstorage->domainmap->empty()) {
- DNSName tmp_qname(i->qname);
+ DNSName tmp_qname(rec.d_name);
auto auth_domain_iter=getBestAuthZone(&tmp_qname);
if(auth_domain_iter!=t_sstorage->domainmap->end()) {
if (auth_domain_iter->first != auth) {
}
- if(i->qname.isPartOf(auth)) {
- if(lwr.d_aabit && lwr.d_rcode==RCode::NoError && i->d_place==DNSResourceRecord::ANSWER && ::arg().contains("delegation-only",auth.toString() /* ugh */)) {
+ if(rec.d_name.isPartOf(auth)) {
+ if(lwr.d_aabit && lwr.d_rcode==RCode::NoError && rec.d_place==DNSRecord::Answer && ::arg().contains("delegation-only",auth.toString() /* ugh */)) {
LOG("NO! Is from delegation-only zone"<<endl);
s_nodelegated++;
return RCode::NXDomain;
}
- else if(i->qtype.getCode() == QType::RRSIG) {
+ else if(rec.d_type == QType::RRSIG) {
LOG("RRSIG - separate"<<endl);
}
else {
LOG("YES!"<<endl);
- i->ttl=min(s_maxcachettl, i->ttl);
+ rec.d_ttl=min(s_maxcachettl, rec.d_ttl);
- DNSResourceRecord rr=*i;
- rr.d_place=DNSResourceRecord::ANSWER;
+ DNSRecord dr(rec);
+ dr.d_place=DNSRecord::Answer;
- rr.ttl += d_now.tv_sec;
+ dr.d_ttl += d_now.tv_sec;
- if(rr.qtype.getCode() == QType::NS) // people fiddle with the case
- rr.content=toLower(rr.content); // this must stay! (the cache can't be case-insensitive on the RHS of records)
- tcache[make_pair(i->qname,i->qtype)].records.insert(rr);
+ tcache[make_pair(rec.d_name,QType(rec.d_type))].records.push_back(dr);
}
}
else
if(i->second.records.size() > 1) { // need to group the ttl to be the minimum of the RRSET (RFC 2181, 5.2)
uint32_t lowestTTL=std::numeric_limits<uint32_t>::max();
for(auto& record : i->second.records)
- lowestTTL=min(lowestTTL, record.ttl);
+ lowestTTL=min(lowestTTL, record.d_ttl);
for(auto& record : i->second.records)
- *const_cast<uint32_t*>(&record.ttl)=lowestTTL;
+ *const_cast<uint32_t*>(&record.d_ttl)=lowestTTL; // boom
}
- cout<<"Have "<<i->second.records.size()<<" records and "<<i->second.signatures.size()<<" signatures for "<<i->first.first.toString();
- cout<<'|'<<DNSRecordContent::NumberToType(i->first.second.getCode())<<endl;
+ // cout<<"Have "<<i->second.records.size()<<" records and "<<i->second.signatures.size()<<" signatures for "<<i->first.first.toString();
+ // cout<<'|'<<DNSRecordContent::NumberToType(i->first.second.getCode())<<endl;
t_RC->replace(d_now.tv_sec, i->first.first, i->first.second, i->second.records, i->second.signatures, lwr.d_aabit);
}
set<DNSName> nsset;
DNSName newauth, soaname;
DNSName newtarget;
- for(LWResult::res_t::iterator i=lwr.getResult().begin();i!=lwr.getResult().end();++i) {
- if(i->d_place==DNSResourceRecord::AUTHORITY && i->qtype.getCode()==QType::SOA &&
- lwr.d_rcode==RCode::NXDomain && dottedEndsOn(qname,i->qname) && dottedEndsOn(i->qname, auth)) {
- LOG(prefix<<qname.toString()<<": got negative caching indication for name '"<<qname.toString()+"' (accept="<<dottedEndsOn(i->qname, auth)<<"), newtarget='"<<newtarget.toString()<<"'"<<endl);
+ for(auto& rec : lwr.d_records) {
+ if(rec.d_place==DNSRecord::Nameserver && rec.d_type==QType::SOA &&
+ lwr.d_rcode==RCode::NXDomain && dottedEndsOn(qname,rec.d_name) && dottedEndsOn(rec.d_name, auth)) {
+ LOG(prefix<<qname.toString()<<": got negative caching indication for name '"<<qname.toString()+"' (accept="<<dottedEndsOn(rec.d_name, auth)<<"), newtarget='"<<newtarget.toString()<<"'"<<endl);
- i->ttl = min(i->ttl, s_maxnegttl);
+ rec.d_ttl = min(rec.d_ttl, s_maxnegttl);
if(!newtarget.length()) // only add a SOA if we're not going anywhere after this
- ret.push_back(*i);
+ ret.push_back(rec);
NegCacheEntry ne;
- ne.d_qname=i->qname;
+ ne.d_qname=rec.d_name;
- ne.d_ttd=d_now.tv_sec + i->ttl;
+ ne.d_ttd=d_now.tv_sec + rec.d_ttl;
ne.d_name=qname;
ne.d_qtype=QType(0); // this encodes 'whole record'
negindic=true;
}
- else if(i->d_place==DNSResourceRecord::ANSWER && pdns_iequals(i->qname, qname) && i->qtype.getCode()==QType::CNAME && (!(qtype==QType(QType::CNAME)))) {
- ret.push_back(*i);
- newtarget=DNSName(i->content);
+ else if(rec.d_place==DNSRecord::Answer && rec.d_name == qname && rec.d_type==QType::CNAME && (!(qtype==QType(QType::CNAME)))) {
+ ret.push_back(rec);
+ newtarget=DNSName(rec.d_content->getZoneRepresentation());
}
- else if(d_doDNSSEC && (i->qtype==QType::RRSIG || i->qtype==QType::NSEC || i->qtype==QType::NSEC3) && i->d_place==DNSResourceRecord::ANSWER){
- ret.push_back(*i); // enjoy your DNSSEC
+ else if(d_doDNSSEC && (rec.d_type==QType::RRSIG || rec.d_type==QType::NSEC || rec.d_type==QType::NSEC3) && rec.d_place==DNSRecord::Answer){
+ ret.push_back(rec); // enjoy your DNSSEC
}
// for ANY answers we *must* have an authoritative answer, unless we are forwarding recursively
- else if(i->d_place==DNSResourceRecord::ANSWER && pdns_iequals(i->qname, qname) &&
+ else if(rec.d_place==DNSRecord::Answer && rec.d_name == qname &&
(
- i->qtype==qtype || (lwr.d_aabit && (qtype==QType(QType::ANY) || magicAddrMatch(qtype, i->qtype) ) ) || sendRDQuery
+ rec.d_type==qtype.getCode() || (lwr.d_aabit && (qtype==QType(QType::ANY) || magicAddrMatch(qtype, QType(rec.d_type)) ) ) || sendRDQuery
)
)
{
- LOG(prefix<<qname.toString()<<": answer is in: resolved to '"<< i->content<<"|"<<i->qtype.getName()<<"'"<<endl);
+ LOG(prefix<<qname.toString()<<": answer is in: resolved to '"<< rec.d_content->getZoneRepresentation()<<"|"<<DNSRecordContent::NumberToType(rec.d_type)<<"'"<<endl);
done=true;
- ret.push_back(*i);
+ ret.push_back(rec);
}
- else if(i->d_place==DNSResourceRecord::AUTHORITY && qname.isPartOf(i->qname) && i->qtype.getCode()==QType::NS) {
- if(moreSpecificThan(i->qname,auth)) {
- newauth=i->qname;
- LOG(prefix<<qname.toString()<<": got NS record '"<<i->qname.toString()<<"' -> '"<<i->content<<"'"<<endl);
+ else if(rec.d_place==DNSRecord::Nameserver && qname.isPartOf(rec.d_name) && rec.d_type==QType::NS) {
+ if(moreSpecificThan(rec.d_name,auth)) {
+ newauth=rec.d_name;
+ LOG(prefix<<qname.toString()<<": got NS record '"<<rec.d_name.toString()<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"'"<<endl);
realreferral=true;
}
- else
- LOG(prefix<<qname.toString()<<": got upwards/level NS record '"<<i->qname.toString()<<"' -> '"<<i->content<<"', had '"<<auth.toString()<<"'"<<endl);
- nsset.insert(DNSName(i->content));
+ else {
+ LOG(prefix<<qname.toString()<<": got upwards/level NS record '"<<rec.d_name.toString()<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"', had '"<<auth.toString()<<"'"<<endl);
+ }
+ nsset.insert(DNSName(rec.d_content->getZoneRepresentation()));
}
- else if(i->d_place==DNSResourceRecord::AUTHORITY && dottedEndsOn(qname,i->qname) && i->qtype.getCode()==QType::DS) {
- LOG(prefix<<qname.toString()<<": got DS record '"<<i->qname.toString()<<"' -> '"<<i->content<<"'"<<endl);
+ else if(rec.d_place==DNSRecord::Nameserver && dottedEndsOn(qname,rec.d_name) && rec.d_type==QType::DS) {
+ LOG(prefix<<qname.toString()<<": got DS record '"<<rec.d_name.toString()<<"' -> '"<<rec.d_content->getZoneRepresentation()<<"'"<<endl);
sawDS=true;
}
- else if(!done && i->d_place==DNSResourceRecord::AUTHORITY && dottedEndsOn(qname,i->qname) && i->qtype.getCode()==QType::SOA &&
+ else if(!done && rec.d_place==DNSRecord::Nameserver && dottedEndsOn(qname,rec.d_name) && rec.d_type==QType::SOA &&
lwr.d_rcode==RCode::NoError) {
LOG(prefix<<qname.toString()<<": got negative caching indication for '"<< (qname.toString()+"|"+qtype.getName()+"'") <<endl);
LOG(prefix<<qname.toString()<<": Hang on! Got a redirect to '"<<newtarget.toString()<<"' already"<<endl);
}
else {
- i-> ttl = min(s_maxnegttl, i->ttl);
- ret.push_back(*i);
+ rec.d_ttl = min(s_maxnegttl, rec.d_ttl);
+ ret.push_back(rec);
NegCacheEntry ne;
- ne.d_qname=i->qname;
- ne.d_ttd=d_now.tv_sec + i->ttl;
+ ne.d_qname=rec.d_name;
+ ne.d_ttd=d_now.tv_sec + rec.d_ttl;
ne.d_name=qname;
ne.d_qtype=qtype;
if(qtype.getCode()) { // prevents us from blacking out a whole domain
return 0;
}
if(!newtarget.empty()) {
- if(pdns_iequals(newtarget,qname)) {
+ if(newtarget == qname) {
LOG(prefix<<qname.toString()<<": status=got a CNAME referral to self, returning SERVFAIL"<<endl);
return RCode::ServFail;
}
LOG(prefix<<qname.toString()<<": status=did not resolve, got "<<(unsigned int)nsset.size()<<" NS, looping to them"<<endl);
if(sawDS) {
t_sstorage->dnssecmap[newauth]=true;
- for(const auto& e : t_sstorage->dnssecmap)
+ /* for(const auto& e : t_sstorage->dnssecmap)
cout<<e.first.toString()<<' ';
- cout<<endl;
+ cout<<endl;*/
}
auth=newauth;
nameservers=nsset;
// used by PowerDNSLua - note that this neglects to add the packet count & statistics back to pdns_ercursor.cc
-int directResolve(const std::string& qname, const QType& qtype, int qclass, vector<DNSResourceRecord>& ret)
+int directResolve(const std::string& qname, const QType& qtype, int qclass, vector<DNSRecord>& ret)
{
struct timeval now;
gettimeofday(&now, 0);
SyncRes sr(now);
-
int res = sr.beginResolve(DNSName(qname), QType(qtype), qclass, ret); // DNSName conversion XXX
+
return res;
}
explicit SyncRes(const struct timeval& now);
- int beginResolve(const DNSName &qname, const QType &qtype, uint16_t qclass, vector<DNSResourceRecord>&ret);
+ int beginResolve(const DNSName &qname, const QType &qtype, uint16_t qclass, vector<DNSRecord>&ret);
void setId(int id)
{
if(doLog())
vector<ComboAddress> d_servers;
bool d_rdForward;
typedef multi_index_container <
- DNSResourceRecord,
+ DNSRecord,
indexed_by <
ordered_non_unique<
- composite_key< DNSResourceRecord,
- member<DNSResourceRecord, DNSName, &DNSResourceRecord::qname>,
- member<DNSResourceRecord, QType, &DNSResourceRecord::qtype>
+ composite_key< DNSRecord,
+ member<DNSRecord, DNSName, &DNSRecord::d_name>,
+ member<DNSRecord, uint16_t, &DNSRecord::d_type>
>,
- composite_key_compare<std::less<DNSName>, std::less<QType> >
+ composite_key_compare<std::less<DNSName>, std::less<uint16_t> >
>
>
> records_t;
private:
struct GetBestNSAnswer;
- int doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType &qtype, vector<DNSResourceRecord>&ret,
+ int doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSet, const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret,
int depth, set<GetBestNSAnswer>&beenthere);
- int doResolve(const DNSName &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, set<GetBestNSAnswer>& beenthere);
- bool doOOBResolve(const DNSName &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res);
+ int doResolve(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, int depth, set<GetBestNSAnswer>& beenthere);
+ bool doOOBResolve(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, int depth, int &res);
domainmap_t::const_iterator getBestAuthZone(DNSName* qname);
- bool doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res);
- bool doCacheCheck(const DNSName &qname, const QType &qtype, vector<DNSResourceRecord>&ret, int depth, int &res);
- void getBestNSFromCache(const DNSName &qname, const QType &qtype, set<DNSResourceRecord>&bestns, bool* flawedNSSet, int depth, set<GetBestNSAnswer>& beenthere);
+ bool doCNAMECacheCheck(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, int depth, int &res);
+ bool doCacheCheck(const DNSName &qname, const QType &qtype, vector<DNSRecord>&ret, int depth, int &res);
+ void getBestNSFromCache(const DNSName &qname, const QType &qtype, vector<DNSRecord>&bestns, bool* flawedNSSet, int depth, set<GetBestNSAnswer>& beenthere);
DNSName getBestNSNamesFromCache(const DNSName &qname, const QType &qtype, set<DNSName>& nsset, bool* flawedNSSet, int depth, set<GetBestNSAnswer>&beenthere);
inline vector<DNSName> shuffleInSpeedOrder(set<DNSName> &nameservers, const string &prefix);
void broadcastFunction(const pipefunc_t& func, bool skipSelf = false);
void distributeAsyncFunction(const std::string& question, const pipefunc_t& func);
-int directResolve(const DNSName& qname, const QType& qtype, int qclass, vector<DNSResourceRecord>& ret);
+int directResolve(const DNSName& qname, const QType& qtype, int qclass, vector<DNSRecord>& ret);
template<class T> T broadcastAccFunction(const boost::function<T*()>& func, bool skipSelf=false);
if (rectify) {
if (rr.qtype.getCode()) {
qnames.insert(rr.qname);
- if(rr.qtype.getCode() == QType::NS && !pdns_iequals(rr.qname, target))
+ if(rr.qtype.getCode() == QType::NS && rr.qname!=target)
nsset.insert(rr.qname);
} else {
// remove existing ents
// set auth
BOOST_FOREACH(DNSResourceRecord &rr, rrs) {
rr.auth=true;
- if (rr.qtype.getCode() != QType::NS || !pdns_iequals(rr.qname, target)) {
+ if (rr.qtype.getCode() != QType::NS || rr.qname!=target) {
DNSName shorter(rr.qname);
do {
- if (pdns_iequals(shorter, target)) // apex is always auth
+ if (shorter==target) // apex is always auth
continue;
- if(nsset.count(shorter) && !(pdns_iequals(rr.qname, shorter) && rr.qtype.getCode() == QType::DS))
+ if(nsset.count(shorter) && !(rr.qname==shorter && rr.qtype.getCode() == QType::DS))
rr.auth=false;
} while(shorter.chopOff());
} else
map<DNSName,bool> nonterm;
BOOST_FOREACH(DNSResourceRecord &rr, rrs) {
DNSName shorter(rr.qname);
- while(!pdns_iequals(shorter, target) && shorter.chopOff()) {
+ while(shorter != target && shorter.chopOff()) {
if(!qnames.count(shorter)) {
if(!(maxent)) {
L<<Logger::Warning<<"Zone '"<<target<<"' has too many empty non terminals."<<endl;
typedef enum { zone, wire } case_type_enum_t;
-
BOOST_AUTO_TEST_CASE(test_record_types) {
// tuple contains <type, user value, zone representation, line value, broken>
typedef boost::tuple<const QType::typeenum, const std::string, const std::string, const std::string, bool> case_t;
}
else if (changetype == "REPLACE") {
// we only validate for REPLACE, as DELETE can be used to "fix" out of zone records.
- if (!qname.isPartOf(zonename) && !pdns_iequals(qname, zonename))
+ if (!qname.isPartOf(zonename) && qname != zonename)
throw ApiException("RRset "+qname.toString()+" IN "+qtype.getName()+": Name is out of zone");
new_records.clear();
if (rr.qname != qname || rr.qtype != qtype)
throw ApiException("Record "+rr.qname.toString()+"/"+rr.qtype.getName()+" "+rr.content+": Record wrongly bundled with RRset " + qname.toString() + "/" + qtype.getName());
- if (rr.qtype.getCode() == QType::SOA && pdns_iequals(rr.qname, zonename)) {
+ if (rr.qtype.getCode() == QType::SOA && rr.qname==zonename) {
soa_edit_done = increaseSOARecord(rr, soa_edit_api_kind, soa_edit_kind);
}
}
Value records;
records.SetArray();
- BOOST_FOREACH(const SyncRes::AuthDomain::records_t::value_type& rr, zone.d_records) {
+ BOOST_FOREACH(const SyncRes::AuthDomain::records_t::value_type& dr, zone.d_records) {
Value object;
object.SetObject();
- Value jname(rr.qname.toString().c_str(), doc.GetAllocator()); // copy
+ Value jname(dr.d_name.toString().c_str(), doc.GetAllocator()); // copy
object.AddMember("name", jname, doc.GetAllocator());
- Value jtype(rr.qtype.getName().c_str(), doc.GetAllocator()); // copy
+ Value jtype(DNSRecordContent::NumberToType(dr.d_type).c_str(), doc.GetAllocator()); // copy
object.AddMember("type", jtype, doc.GetAllocator());
- object.AddMember("ttl", rr.ttl, doc.GetAllocator());
- Value jcontent(rr.content.c_str(), doc.GetAllocator()); // copy
+ object.AddMember("ttl", dr.d_ttl, doc.GetAllocator());
+ Value jcontent(dr.d_content->getZoneRepresentation().c_str(), doc.GetAllocator()); // copy
object.AddMember("content", jcontent, doc.GetAllocator());
records.PushBack(object, doc.GetAllocator());
}
const SyncRes::AuthDomain& zone = val.second;
BOOST_FOREACH(const SyncRes::AuthDomain::records_t::value_type& rr, zone.d_records) {
- if (pdns_ci_find(rr.qname.toString(), q) == string::npos && pdns_ci_find(rr.content, q) == string::npos)
+ if (pdns_ci_find(rr.d_name.toString(), q) == string::npos && pdns_ci_find(rr.d_content->getZoneRepresentation(), q) == string::npos)
continue;
Value object;
object.AddMember("zone_id", jzoneId, doc.GetAllocator());
Value jzoneName(val.first.toString().c_str(), doc.GetAllocator()); // copy
object.AddMember("zone_name", jzoneName, doc.GetAllocator());
- Value jname(rr.qname.toString().c_str(), doc.GetAllocator()); // copy
+ Value jname(rr.d_name.toString().c_str(), doc.GetAllocator()); // copy
object.AddMember("name", jname, doc.GetAllocator());
- Value jcontent(rr.content.c_str(), doc.GetAllocator()); // copy
+ Value jcontent(rr.d_content->getZoneRepresentation().c_str(), doc.GetAllocator()); // copy
object.AddMember("content", jcontent, doc.GetAllocator());
doc.PushBack(object, doc.GetAllocator());