]> granicus.if.org Git - pdns/commitdiff
the day you new that would be arriving: a Lua configuration file for Recursor. Also...
authorbert hubert <bert.hubert@netherlabs.nl>
Sun, 29 Nov 2015 10:51:00 +0000 (11:51 +0100)
committerbert hubert <bert.hubert@netherlabs.nl>
Sun, 29 Nov 2015 10:51:00 +0000 (11:51 +0100)
build-scripts/dist-recursor
pdns/Makefile-recursor
pdns/Makefile.am
pdns/pdns_recursor.cc
pdns/rec-lua-conf.cc [new file with mode: 0644]
pdns/sortlist.cc [new file with mode: 0644]
pdns/sortlist.hh [new file with mode: 0644]

index 5c2304308849c7251947f4acbe8422021cdf1133..42e398c1bc6a195ebe6796ef9d85f8b919dd7523 100755 (executable)
@@ -38,7 +38,7 @@ ws-recursor.hh ws-api.hh secpoll-recursor.hh \
 responsestats.hh webserver.hh dnsname.hh dnspacket.hh ednssubnet.hh \
 filterpo.hh rpzloader.hh ixfr.hh gss_context.hh resolver.hh dnssecinfra.hh \
 dnsseckeeper.hh statbag.hh ueberbackend.hh sha.hh dnsbackend.hh comment.hh \
-validate.hh validate-recursor.hh"
+validate.hh validate-recursor.hh sortlist.hh"
 
 CFILES="syncres.cc iputils.cc  misc.cc unix_utility.cc qtype.cc \
 logger.cc arguments.cc  lwres.cc pdns_recursor.cc lua-iputils.cc \
@@ -50,7 +50,8 @@ devpollmplexer.cc recpacketcache.cc dns.cc reczones.cc base32.cc nsecrecords.cc
 dnslabeltext.cc json.cc ws-recursor.cc ws-api.cc version.cc dns_random.cc \
 responsestats.cc webserver.cc rec-carbon.cc secpoll-recursor.cc dnsname.cc \
 filterpo.cc rpzloader.cc ixfr.cc dnssecinfra.cc gss_context.cc resolver.cc \
-ednssubnet.cc validate.cc validate-recursor.cc mbedtlssigners.cc"
+ednssubnet.cc validate.cc validate-recursor.cc mbedtlssigners.cc rec-lua-conf.cc \
+sortlist.cc"
 
 ./mkpubsuffixcc
 
@@ -81,6 +82,9 @@ cp -a ../ext/mbedtls/library/{aes.c,base64.c,md.c,md_wrap.c,md5.c,sha1.c,sha256.
 cp -a ../ext/mbedtls/library/{rsa.c,bignum.c,oid.c,asn1parse.c,ctr_drbg.c,entropy.c,entropy_poll.c,timing.c} $DIRNAME/ext/mbedtls/library
 
 cp -a ../ext/yahttp/ $DIRNAME/ext/yahttp
+
+mkdir -p $DIRNAME/ext/luawrapper/include
+cp ../ext/luawrapper/include/LuaContext.hpp $DIRNAME/ext/luawrapper/include
 echo '#include "../../../config.h"' > $DIRNAME/ext/yahttp/yahttp/yahttp-config.h
 mkdir $DIRNAME/rrd
 cp tools/rrd/{create,update,makegraphs,index.html} $DIRNAME/rrd
index 436a56e32dc430af97cc408ab562e3ace191701e..d32a8a80462609007d1e3a06e0a8d7ea14504796 100644 (file)
@@ -32,7 +32,8 @@ reczones.o base32.o nsecrecords.o json.o ws-recursor.o ws-api.o \
 version.o responsestats.o webserver.o ext/yahttp/yahttp/reqresp.o ext/yahttp/yahttp/router.o \
 rec-carbon.o secpoll-recursor.o lua-iputils.o iputils.o dnsname.o \
 rpzloader.o filterpo.o resolver.o ixfr.o dnssecinfra.o gss_context.o \
-ednssubnet.o validate.o validate-recursor.o mbedtlssigners.o
+ednssubnet.o validate.o validate-recursor.o mbedtlssigners.o \
+rec-lua-conf.o sortlist.o
 
 REC_CONTROL_OBJECTS=rec_channel.o rec_control.o arguments.o misc.o \
        unix_utility.o logger.o qtype.o dnslabeltext.o dnsname.o
index 315e84a42796b98ff05cdfbe9d3189b95f1e2510..7dcb6b5b399e54a93fe05609cec304d58c9aba7a 100644 (file)
@@ -1128,6 +1128,7 @@ pdns_recursor_SOURCES = \
        rec-carbon.cc \
        rec_channel.cc rec_channel.hh \
        rec_channel_rec.cc \
+       rec-lua-conf.cc \
        recpacketcache.cc recpacketcache.hh \
        recursor_cache.cc recursor_cache.hh \
        reczones.cc \
@@ -1139,6 +1140,7 @@ pdns_recursor_SOURCES = \
        secpoll-recursor.hh \
        selectmplexer.cc \
        sillyrecords.cc \
+       sortlist.cc sortlist.hh \
        statbag.cc \
        syncres.cc syncres.hh \
        unix_utility.cc \
index 8346d56693b19f97f72bac1615c816c56ccd981b..8c1e09d376423432c0df48e4a578ad2a9141083d 100644 (file)
@@ -23,6 +23,7 @@
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
+
 #include <netdb.h>
 #include <sys/stat.h>
 #include <unistd.h>
@@ -49,6 +50,8 @@
 #include "syncres.hh"
 #include <fcntl.h>
 #include <fstream>
+#include "sortlist.hh"
+extern SortList g_sortlist;
 #include "sstuff.hh"
 #include <boost/tuple/tuple.hpp>
 #include <boost/tuple/tuple_comparison.hpp>
@@ -81,7 +84,7 @@
 #include "statbag.hh"
 StatBag S;
 #endif
-
+void loadRecursorLuaConfig(const std::string& fname);
 __thread FDMultiplexer* t_fdm;
 __thread unsigned int t_id;
 unsigned int g_maxTCPPerClient;
@@ -816,6 +819,10 @@ void startDoResolve(void *p)
 
       if(ret.size()) {
         orderAndShuffle(ret);
+       if(auto sl = g_sortlist.getOrderCmp(dc->d_remote)) {
+         sort(ret.begin(), ret.end(), *sl);
+         variableAnswer=true;
+       }
         for(auto i=ret.cbegin(); i!=ret.cend(); ++i) {
           pw.startRecord(i->d_name, i->d_type, i->d_ttl, i->d_class, i->d_place);
           minTTL = min(minTTL, i->d_ttl);
@@ -2551,6 +2558,7 @@ int main(int argc, char **argv)
     ::arg().set("auth-zones", "Zones for which we have authoritative data, comma separated domain=file pairs ")="";
     ::arg().set("rpz-files", "RPZ files to load in order, domain or domain=policy pairs separated by commas")="";
     ::arg().set("rpz-masters", "RPZ master servers, address:name pairs separated by commas")="";
+    ::arg().set("lua-config-file", "More powerful configuration options")="";
 
     ::arg().set("forward-zones", "Zones for which we forward queries, comma separated domain=ip pairs")="";
     ::arg().set("forward-zones-recurse", "Zones for which we forward queries with recursion bit, comma separated domain=ip pairs")="";
@@ -2600,6 +2608,8 @@ int main(int argc, char **argv)
 
     ::arg().parse(argc,argv);
 
+    loadRecursorLuaConfig(::arg()["lua-config-file"]);
+
     ::arg().set("delegation-only")=toLower(::arg()["delegation-only"]);
 
     if(::arg().asNum("threads")==1)
diff --git a/pdns/rec-lua-conf.cc b/pdns/rec-lua-conf.cc
new file mode 100644 (file)
index 0000000..1dabe6e
--- /dev/null
@@ -0,0 +1,58 @@
+#include "ext/luawrapper/include/LuaContext.hpp"
+#include <fstream>
+#include "namespaces.hh"
+#include "logger.hh"
+#include "sortlist.hh"
+
+SortList g_sortlist;
+void loadRecursorLuaConfig(const std::string& fname)
+{
+  LuaContext Lua;
+  if(fname.empty())
+    return;
+  ifstream ifs(fname);
+  if(!ifs) {
+    theL()<<"Unable to read configuration file from '"<<fname<<"': "<<strerror(errno)<<endl;
+    return;
+  }
+  Lua.writeFunction("clearSortlist", []() { g_sortlist.clear(); });
+  
+  /* we can get: "1.2.3.4"
+                 {"1.2.3.4", "4.5.6.7"}
+                {"1.2.3.4", {"4.5.6.7", "8.9.10.11"}}
+  */
+
+  typedef vector<pair<int,boost::variant<string, vector<pair<int, string> > > > > argvec_t;
+  Lua.writeFunction("addSortList", 
+                   [](const std::string& formask_, 
+                      const boost::variant<string, argvec_t>& masks,
+                      boost::optional<int> order_) 
+                   {
+                     try {
+                       Netmask formask(formask_);
+                       int order = order_ ? (*order_) : g_sortlist.getMaxOrder(formask)+1;
+                       if(auto str = boost::get<string>(&masks)) 
+                         g_sortlist.addEntry(formask, Netmask(*str), order);
+                       else {
+       
+                         auto vec = boost::get<argvec_t>(&masks);
+                         for(const auto& e : *vec) {
+                           if(auto s = boost::get<string>(&e.second)) {
+                             g_sortlist.addEntry(formask, Netmask(*s), order);
+                           }
+                           else {
+                             const auto& v =boost::get<vector<pair<int, string> > >(e.second);
+                             for(const auto& e : v)
+                               g_sortlist.addEntry(formask, Netmask(e.second), order);
+                           }
+                           ++order;
+                         }
+                       }
+                     }
+                     catch(std::exception& e) {
+                       theL()<<Logger::Error<<"Error in addSortList: "<<e.what()<<endl;
+                     }
+                   });
+  Lua.executeCode(ifs);
+  
+}
diff --git a/pdns/sortlist.cc b/pdns/sortlist.cc
new file mode 100644 (file)
index 0000000..e5a0350
--- /dev/null
@@ -0,0 +1,89 @@
+#include "sortlist.hh"
+#include "dnsrecords.hh"
+
+void SortList::clear()
+{
+  d_sortlist.clear();
+}
+
+int SortList::getMaxOrder(const Netmask& formask) const
+{
+  int order=0;
+  
+  auto place = d_sortlist.lookup(formask);
+  if(place && place->first == formask) {
+    for(const auto& o : place->second.d_orders) 
+      order = std::max(order, o->second); // aki, shouldn't this be o.second?
+  }
+  
+  return order;
+}
+
+void SortList::addEntry(const Netmask& formask, const Netmask& valmask, int order)
+{
+  if(order < 0) {
+    order=getMaxOrder(formask);
+    ++order;
+  }
+  //  cout<<"Adding for netmask "<<formask.toString()<<" the order instruction that "<<valmask.toString()<<" is order "<<order<<endl;
+  d_sortlist[formask].d_orders[valmask]=order;
+}
+
+std::unique_ptr<SortListOrderCmp> SortList::getOrderCmp(const ComboAddress& who)
+{
+  if(!d_sortlist.match(who)) {
+    return std::unique_ptr<SortListOrderCmp>();
+  }
+  auto fnd = d_sortlist.lookup(who);
+  //  cerr<<"Returning sort order for "<<who.toString()<<", have "<<fnd->second.d_orders.size()<<" entries"<<endl;
+  return make_unique<SortListOrderCmp>(fnd->second);
+}
+
+bool SortListOrderCmp::operator()(const ComboAddress& a, const ComboAddress& b) const
+{
+  int aOrder=std::numeric_limits<int>::max();
+  int bOrder=aOrder;
+
+  if(d_slo.d_orders.match(a))
+    aOrder = d_slo.d_orders[a];
+  if(d_slo.d_orders.match(b))
+    bOrder = d_slo.d_orders[b];
+
+  return aOrder < bOrder;
+}
+
+static ComboAddress getAddr(const DNSRecord& dr)
+{
+  if(auto addr=getRR<ARecordContent>(dr)) {
+    return addr->getCA();
+  }
+  else
+    return getRR<AAAARecordContent>(dr)->getCA();
+}
+bool SortListOrderCmp::operator()(const DNSRecord& ar, const DNSRecord& br) const
+{
+  if(ar.d_type < br.d_type)
+    return true;
+  if(ar.d_type > br.d_type)
+    return false;
+
+  if(ar.d_type != QType::A && ar.d_type != QType::AAAA) 
+    return false;  // all other types are equal among themselves
+
+  int aOrder=std::numeric_limits<int>::max();
+  int bOrder=aOrder;
+
+  ComboAddress a=getAddr(ar), b=getAddr(br);
+  
+  if(d_slo.d_orders.match(a))
+    aOrder = d_slo.d_orders.lookup(a)->second;
+  else {
+    //    cout<<"Could not find anything for "<<a.toString()<<" in our orders!"<<endl;
+  }
+  if(d_slo.d_orders.match(b))
+    bOrder = d_slo.d_orders.lookup(b)->second;
+  else {
+    //    cout<<"Could not find anything for "<<b.toString()<<" in our orders!"<<endl;
+  }
+  return aOrder < bOrder;
+}
diff --git a/pdns/sortlist.hh b/pdns/sortlist.hh
new file mode 100644 (file)
index 0000000..afe67c1
--- /dev/null
@@ -0,0 +1,28 @@
+#pragma once
+#include "iputils.hh"
+#include "dnsrecords.hh"
+
+struct SortListOrder
+{
+  NetmaskTree<int> d_orders;
+};
+
+
+struct SortListOrderCmp
+{
+  SortListOrderCmp(SortListOrder slo) : d_slo(slo) {}
+  bool operator()(const ComboAddress& a, const ComboAddress& b) const;
+  bool operator()(const DNSRecord& a, const DNSRecord& b) const;
+  const SortListOrder d_slo;
+};
+
+class SortList {
+public:
+  void clear();
+  void addEntry(const Netmask& covers, const Netmask& answermask, int order=-1);
+  int getMaxOrder(const Netmask& formask) const;
+  std::unique_ptr<SortListOrderCmp> getOrderCmp(const ComboAddress& who);
+private:
+  
+  NetmaskTree<SortListOrder> d_sortlist;
+};