]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
move lua scripts in resolver over to glorious luawrapper4, plus vamp up semantics
authorbert hubert <bert.hubert@netherlabs.nl>
Thu, 17 Dec 2015 10:34:11 +0000 (11:34 +0100)
committerbert hubert <bert.hubert@netherlabs.nl>
Thu, 17 Dec 2015 10:34:11 +0000 (11:34 +0100)
pdns/lua-recursor.cc
pdns/lua-recursor4.cc
pdns/lua-recursor4.hh
pdns/pdns_recursor.cc
pdns/syncres.cc
pdns/syncres.hh

index 56c02ca2169a4d4fc34d611d944b8e8e2c972e2c..5064dbc3033583aa4914c2c24d73446d49f766fe 100644 (file)
@@ -3,7 +3,7 @@
 #endif
 #include "lua-recursor.hh"
 // to avoid including all of syncres.hh
-int directResolve(const std::string& qname, const QType& qtype, int qclass, vector<DNSRecord>& ret);
+int directResolve(const DNSName& qname, const QType& qtype, int qclass, vector<DNSRecord>& ret);
 
 #if !defined(HAVE_LUA)
 
@@ -81,7 +81,7 @@ RecursorLua::RecursorLua(const std::string &fname)
   lua_setglobal(d_lua, "getregisteredname");
 }
 
-int followCNAMERecords(vector<DNSRecord>& ret, const QType& qtype)
+static int followCNAMERecords(vector<DNSRecord>& ret, const QType& qtype)
 {
   vector<DNSRecord> resolved;
   string target; // XXX DNSNAME PAIN
@@ -97,7 +97,7 @@ int followCNAMERecords(vector<DNSRecord>& ret, const QType& qtype)
   if(target[target.size()-1]!='.')
     target.append(1, '.');
 
-  int rcode=directResolve(target, qtype, 1, resolved); // 1 == class
+  int rcode=directResolve(DNSName(target), qtype, 1, resolved); // 1 == class
 
   for(const DNSRecord& rr :  resolved)
   {
@@ -108,9 +108,9 @@ int followCNAMERecords(vector<DNSRecord>& ret, const QType& qtype)
 }
 
 
-int getFakeAAAARecords(const std::string& qname, const std::string& prefix, vector<DNSRecord>& ret)
+static int getFakeAAAARecords(const std::string& qname, const std::string& prefix, vector<DNSRecord>& ret)
 {
-  int rcode=directResolve(qname, QType(QType::A), 1, ret);
+  int rcode=directResolve(DNSName(qname), QType(QType::A), 1, ret);
 
   ComboAddress prefixAddress(prefix);
 
@@ -129,7 +129,7 @@ int getFakeAAAARecords(const std::string& qname, const std::string& prefix, vect
   return rcode;
 }
 
-int getFakePTRRecords(const DNSName& qname, const std::string& prefix, vector<DNSRecord>& ret)
+static 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 */
@@ -148,7 +148,7 @@ int getFakePTRRecords(const DNSName& qname, const std::string& prefix, vector<DN
   newquery += "in-addr.arpa.";
 
 
-  int rcode = directResolve(newquery, QType(QType::PTR), 1, ret);
+  int rcode = directResolve(DNSName(newquery), QType(QType::PTR), 1, ret);
   for(DNSRecord& rr :  ret)
   {
     if(rr.d_type == QType::PTR && rr.d_place==DNSResourceRecord::ANSWER) {
index 2903fffded5d00fb290ef3ee1e1cf1c188e401a2..59b2dc17ecad50c46e539703194a27fc96058ff7 100644 (file)
 #undef L
 #include "ext/luawrapper/include/LuaContext.hpp"
 #include "logger.hh"
+#include "dnsparser.hh"
+#include "syncres.hh"
 
+namespace {
+  enum class PolicyDecision { PASS=-1, DROP=-2, TRUNCATE=-3 };
+}
+
+static int followCNAMERecords(vector<DNSRecord>& ret, const QType& qtype)
+{
+  vector<DNSRecord> resolved;
+  DNSName target;
+  for(const DNSRecord& rr :  ret) {
+    if(rr.d_type == QType::CNAME) {
+      target=getRR<CNAMERecordContent>(rr)->getTarget();
+      break;
+    }
+  }
+  if(target.empty())
+    return 0;
+  
+  int rcode=directResolve(target, qtype, 1, resolved); // 1 == class
+  
+  for(const DNSRecord& rr :  resolved) {
+    ret.push_back(rr);
+  }
+  return rcode;
+}
+
+static int getFakeAAAARecords(const DNSName& qname, const std::string& prefix, vector<DNSRecord>& ret)
+{
+  int rcode=directResolve(qname, QType(QType::A), 1, ret);
+
+  ComboAddress prefixAddress(prefix);
+
+  for(DNSRecord& rr :  ret)
+  {
+    if(rr.d_type == QType::A && rr.d_place==DNSResourceRecord::ANSWER) {
+      ComboAddress ipv4(getRR<ARecordContent>(rr)->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.d_content = std::make_shared<AAAARecordContent>(prefixAddress);
+      rr.d_type = QType::AAAA;
+    }
+  }
+  return rcode;
+}
+
+static 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 */
+  ret.clear();
+  vector<string> parts = qname.getRawLabels();
+
+  if(parts.size() < 8)
+    return -1;
+
+  string newquery;
+  for(int n = 0; n < 4; ++n) {
+    newquery +=
+      lexical_cast<string>(strtol(parts[n*2].c_str(), 0, 16) + 16*strtol(parts[n*2+1].c_str(), 0, 16));
+    newquery.append(1,'.');
+  }
+  newquery += "in-addr.arpa.";
+
+
+  int rcode = directResolve(DNSName(newquery), QType(QType::PTR), 1, ret);
+  for(DNSRecord& rr :  ret)
+  {
+    if(rr.d_type == QType::PTR && rr.d_place==DNSResourceRecord::ANSWER) {
+      rr.d_name = qname;
+    }
+  }
+  return rcode;
+
+}
+
+vector<pair<int, DNSRecord> > RecursorLua4::DNSQuestion::getRecords()
+{
+  vector<pair<int, DNSRecord> > ret;
+  int num=1;
+  for(const auto& r : records) {
+    ret.push_back({num++, r});
+  }
+  return ret;
+}
+void RecursorLua4::DNSQuestion::setRecords(const vector<pair<int, DNSRecord> >& recs)
+{
+  records.clear();
+  for(const auto& p : recs) {
+    records.push_back(p.second);
+    cout<<"Setting: "<<p.second.d_content->getZoneRepresentation()<<endl;
+  }
+}
+
+void RecursorLua4::DNSQuestion::addRecord(uint16_t type, const std::string& content, DNSResourceRecord::Place place, boost::optional<int> ttl)
+{
+  DNSRecord dr;
+  dr.d_name=qname;
+  dr.d_ttl=ttl.get_value_or(3600);
+  dr.d_type = type;
+  dr.d_place = place;
+  dr.d_content = shared_ptr<DNSRecordContent>(DNSRecordContent::mastermake(type, 1, content));
+  records.push_back(dr);
+}
+
+void RecursorLua4::DNSQuestion::addAnswer(uint16_t type, const std::string& content, boost::optional<int> ttl)
+{
+  addRecord(type, content, DNSResourceRecord::ANSWER, ttl);
+}
+  
 RecursorLua4::RecursorLua4(const std::string& fname)
 {
   d_lw = new LuaContext;
   d_lw->writeFunction("newDN", [](const std::string& dom){ return DNSName(dom); });  
   d_lw->registerFunction("isPartOf", &DNSName::isPartOf);  
-  d_lw->registerFunction("toString", &ComboAddress::toString);  
-  d_lw->registerFunction("toString", &DNSName::toString);    
+  //d_lw->registerFunction("toString", &ComboAddress::toString);  
+  d_lw->registerFunction<string(DNSName::*)()>("toString", [](const DNSName&dn ) { return dn.toString(); });
+  d_lw->registerMember("qname", &DNSQuestion::qname);
+  d_lw->registerMember("qtype", &DNSQuestion::qtype);
+  d_lw->registerMember("rcode", &DNSQuestion::rcode);
+  d_lw->registerMember("variable", &DNSQuestion::variable);
+  d_lw->registerMember("followupFunction", &DNSQuestion::followupFunction);
+  d_lw->registerMember("followupPrefix", &DNSQuestion::followupPrefix);
+  d_lw->registerMember("followupName", &DNSQuestion::followupName);
+  d_lw->registerMember("name", &DNSRecord::d_name);
+  d_lw->registerMember("type", &DNSRecord::d_type);
+  d_lw->registerMember("ttl", &DNSRecord::d_ttl);
+  
+  d_lw->registerFunction<string(DNSRecord::*)()>("getContent", [](const DNSRecord& dr) { return dr.d_content->getZoneRepresentation(); });
+
+
+  d_lw->registerFunction<void(DNSRecord::*)(const std::string&)>("changeContent", [](DNSRecord& dr, const std::string& newContent) { dr.d_content = shared_ptr<DNSRecordContent>(DNSRecordContent::mastermake(dr.d_type, 1, newContent)); });
+  d_lw->registerFunction("addAnswer", &DNSQuestion::addAnswer);
+  d_lw->registerFunction("getRecords", &DNSQuestion::getRecords);
+  d_lw->registerFunction("setRecords", &DNSQuestion::setRecords);
+
+  d_lw->writeFunction("newDS", []() { return SuffixMatchNode(); });
+  d_lw->registerFunction<void(SuffixMatchNode::*)(boost::variant<string,DNSName, vector<pair<unsigned int,string> > >)>("add",
+                                                                                  [](SuffixMatchNode&smn, const boost::variant<string,DNSName,vector<pair<unsigned int,string> > >& in)
+                                                                                  {
+                                                                                    try {
+                                                                                    if(auto s = boost::get<string>(&in)) {
+                                                                                      smn.add(DNSName(*s));
+                                                                                    }
+                                                                                    else if(auto v = boost::get<vector<pair<unsigned int, string> > >(&in)) {
+                                                                                      for(const auto& s : *v)
+                                                                                        smn.add(DNSName(s.second));
+                                                                                    }
+                                                                                    else
+                                                                                      smn.add(boost::get<DNSName>(in));
+                                                                                    }
+                                                                                    catch(std::exception& e) { cerr<<e.what()<<endl; }
+                                                                                  });
+  d_lw->registerFunction("check",(bool (SuffixMatchNode::*)(const DNSName&) const) &SuffixMatchNode::check);
+
+  
+  vector<pair<string,int>> pd{
+    {"PASS", (int)PolicyDecision::PASS}, {"DROP",  (int)PolicyDecision::DROP},
+    {"TRUNCATE", (int)PolicyDecision::TRUNCATE}
+  };
+
+  for(const auto& n : QType::names)
+    pd.push_back({n.first, n.second});
+  
 
-  vector<pair<string,int>> pd{{"PASS", PolicyDecision::PASS}, {"DROP",  PolicyDecision::DROP}, {"TRUNCATE", PolicyDecision::TRUNCATE}};
   d_lw->writeVariable("pdns", pd);            
   
   ifstream ifs(fname);
   if(!ifs) {
-    theL()<<"Unable to read configuration file from '"<<fname<<"': "<<strerror(errno)<<endl;
+    theL()<<Logger::Error<<"Unable to read configuration file from '"<<fname<<"': "<<strerror(errno)<<endl;
     return;
   }    
   d_lw->executeCode(ifs);
+
+  d_preresolve = d_lw->readVariable<boost::optional<luacall_t>>("preresolve").get_value_or(0);
+  d_nodata = d_lw->readVariable<boost::optional<luacall_t>>("nodata").get_value_or(0);
+  d_nxdomain = d_lw->readVariable<boost::optional<luacall_t>>("nxdomain").get_value_or(0);
+  d_postresolve = d_lw->readVariable<boost::optional<luacall_t>>("postresolve").get_value_or(0);
+  
+  //  d_ipfilter = d_lw->readVariable<boost::optional<ipfilter_t>>("ipfilter").get_value_or(0);
 }
 
 bool RecursorLua4::preresolve(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSRecord>& res, int& ret, bool* variable)
 {
-  const auto function = d_lw->readVariable<std::function<bool(const ComboAddress& remote, const ComboAddress& local, const DNSName& query, uint16_t)>>("preresolve");
-  if(!function)
+  return genhook(d_preresolve, remote, local, query, qtype, res, ret, variable);
+}
+
+bool RecursorLua4::nxdomain(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSRecord>& res, int& ret, bool* variable)
+{
+  return genhook(d_nxdomain, remote, local, query, qtype, res, ret, variable);
+}
+
+bool RecursorLua4::nodata(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSRecord>& res, int& ret, bool* variable)
+{
+  return genhook(d_nodata, remote, local, query, qtype, res, ret, variable);
+}
+
+bool RecursorLua4::postresolve(const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSRecord>& res, int& ret, bool* variable)
+{
+  return genhook(d_postresolve, remote, local, query, qtype, res, ret, variable);
+}
+
+bool RecursorLua4::preoutquery(const ComboAddress& ns, const ComboAddress& requestor, const DNSName& query, const QType& qtype, vector<DNSRecord>& res, int& ret)
+{
+  return genhook(d_postresolve, ns, requestor, query, qtype, res, ret, 0);
+}
+
+bool RecursorLua4::ipfilter(const ComboAddress& remote, const ComboAddress& local, const struct dnsheader& dh)
+{
+  if(d_ipfilter)
+    return d_ipfilter(remote, local);
+}
+
+bool RecursorLua4::genhook(luacall_t& func, const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSRecord>& res, int& ret, bool* variable)
+{
+  if(!func)
     return false;
-  ret = function(remote, local, query, qtype.getCode());
-  return true;
-}
\ No newline at end of file
+
+  auto dq = std::make_shared<DNSQuestion>();
+  dq->qname = query;
+  dq->qtype = qtype.getCode();
+  dq->local=local;
+  dq->remote=remote;
+  dq->records = res;
+
+  bool handled=func(dq);
+  if(variable) *variable = dq->variable; // could still be set to indicate this *name* is variable
+
+  if(handled) {
+    ret=dq->rcode;
+    
+    if(!dq->followupFunction.empty()) {
+      if(dq->followupFunction=="followCNAMERecords") {
+       ret = followCNAMERecords(dq->records, qtype);
+      }
+      else if(dq->followupFunction=="getFakeAAAARecords") {
+       ret=getFakeAAAARecords(dq->followupName, dq->followupPrefix, dq->records);
+      }
+      else if(dq->followupFunction=="getFakePTRRecords") {
+       ret=getFakePTRRecords(dq->followupName, dq->followupPrefix, dq->records);
+      }
+    }
+    res=dq->records;
+
+    
+
+  }
+
+
+  // see if they added followup work for us too
+  return handled;
+}
index 15ee5e07a880cae7a5d158620830bb905a22583e..f10032f670ae5e13cf1149d335e4eb5b4b8139ea 100644 (file)
@@ -2,15 +2,48 @@
 #include "iputils.hh"
 #include "dnsname.hh"
 #include "namespaces.hh"
+#include "dnsrecords.hh"
 
 class LuaContext;
-class RecursorLua4
+class RecursorLua4 : public boost::noncopyable
 {
 public:
   explicit RecursorLua4(const std::string& fname);
-  // ~RecursorLua();
+
   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, const struct dnsheader&);
+
 private:
+  struct DNSQuestion
+  {
+    DNSName qname;
+    uint16_t qtype;
+    ComboAddress local, remote;
+    int rcode{0};
+    // struct dnsheader, packet length would be great
+    vector<DNSRecord> records;
+    void addAnswer(uint16_t type, const std::string& content, boost::optional<int> ttl);
+    void addRecord(uint16_t type, const std::string& content, DNSResourceRecord::Place place, boost::optional<int> ttl);
+    vector<pair<int,DNSRecord> > getRecords();
+    void setRecords(const vector<pair<int,DNSRecord> >& records);
+    bool variable{false};
+    
+    string followupFunction;
+    string followupPrefix;
+    DNSName followupName;
+  };
+
+
   LuaContext* d_lw;
+  typedef std::function<bool(std::shared_ptr<DNSQuestion>)> luacall_t;
+  luacall_t d_preresolve, d_nxdomain, d_nodata, d_postresolve, d_preoutquery, d_postoutquery;
+  bool genhook(luacall_t& func, const ComboAddress& remote,const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSRecord>& res, int& ret, bool* variable);
+  typedef std::function<bool(const ComboAddress&, const ComboAddress&)> ipfilter_t;
+  ipfilter_t d_ipfilter;
 };
 
index ab7dd54a855245ebf3500ceb22559828a5ca7d09..df26a74a31401d153cd9cd7654a5f02d4b144818 100644 (file)
@@ -96,7 +96,7 @@ uint64_t g_latencyStatSize;
 bool g_logCommonErrors;
 bool g_anyToTcp;
 uint16_t g_udpTruncationThreshold, g_outgoingEDNSBufsize;
-__thread shared_ptr<RecursorLua>* t_pdl;
+__thread shared_ptr<RecursorLua4>* t_pdl;
 
 __thread addrringbuf_t* t_remotes, *t_servfailremotes, *t_largeanswerremotes;
 
@@ -596,7 +596,6 @@ catch(...)
 
 void startDoResolve(void *p)
 {
-  RecursorLua4 rl4("./recursor4.lua");
   DNSComboWriter* dc=(DNSComboWriter *)p;
   try {
     t_queryring->push_back(make_pair(dc->d_mdp.d_qname, dc->d_mdp.d_qtype));
@@ -717,7 +716,7 @@ void startDoResolve(void *p)
     }
 
 
-    if(/* !t_pdl->get() ||*/ !rl4.preresolve(dc->d_remote, local, dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res, &variableAnswer)) {
+    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);
       }
@@ -767,7 +766,7 @@ void startDoResolve(void *p)
        ret.push_back(spoofed);
        goto haveAnswer;
       }
-      
+
       if(t_pdl->get()) {
         if(res == RCode::NoError) {
                auto i=ret.cbegin();
@@ -776,11 +775,11 @@ void startDoResolve(void *p)
                           break;
                 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)
-               (*t_pdl)->nxdomain(dc->d_remote,local, dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res, &variableAnswer);
-       
+       }
+       else if(res == RCode::NXDomain)
+         (*t_pdl)->nxdomain(dc->d_remote,local, dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res, &variableAnswer);
        
+
        (*t_pdl)->postresolve(dc->d_remote,local, dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res, &variableAnswer);
       }
     }
@@ -1197,7 +1196,10 @@ string* doProcessUDPQuestion(const std::string& question, const ComboAddress& fr
   }
 
   if(t_pdl->get()) {
-    if((*t_pdl)->ipfilter(fromaddr, destaddr)) {
+    struct dnsheader dh;
+    memcpy(&dh, response.c_str(), sizeof(dh));
+    
+    if((*t_pdl)->ipfilter(fromaddr, destaddr, dh)) {
       if(!g_quiet)
        L<<Logger::Notice<<t_id<<" ["<<MT->getTid()<<"/"<<MT->numProcesses()<<"] DROPPED question from "<<fromaddr.toStringWithPort()<<" based on policy"<<endl;
       g_stats.policyDrops++;
@@ -1979,7 +1981,7 @@ string* doReloadLuaScript()
       return new string("unloaded\n");
     }
     else {
-      *t_pdl = shared_ptr<RecursorLua>(new RecursorLua(fname));
+      *t_pdl = shared_ptr<RecursorLua4>(new RecursorLua4(fname));
     }
   }
   catch(std::exception& e) {
@@ -2395,11 +2397,11 @@ try
 
   L<<Logger::Warning<<"Done priming cache with root hints"<<endl;
 
-  t_pdl = new shared_ptr<RecursorLua>();
+  t_pdl = new shared_ptr<RecursorLua4>();
 
   try {
     if(!::arg()["lua-dns-script"].empty()) {
-      *t_pdl = shared_ptr<RecursorLua>(new RecursorLua(::arg()["lua-dns-script"]));
+      *t_pdl = shared_ptr<RecursorLua4>(new RecursorLua4(::arg()["lua-dns-script"]));
       L<<Logger::Warning<<"Loaded 'lua' script from '"<<::arg()["lua-dns-script"]<<"'"<<endl;
     }
   }
index a974da6c76e86a800d5b7ded0fdfc0032604d95d..a5f0db976b48562e8899b555723d12815a0be033 100644 (file)
@@ -25,7 +25,7 @@
 #endif
 #include <boost/algorithm/string.hpp>
 
-#include "lua-recursor.hh"
+#include "lua-recursor4.hh"
 #include "utility.hh"
 #include "syncres.hh"
 #include <iostream>
@@ -1369,13 +1369,13 @@ int SyncRes::doResolveAt(set<DNSName> nameservers, DNSName auth, bool flawedNSSe
 
 
 // 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<DNSRecord>& ret)
+int directResolve(const DNSName& 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
+  int res = sr.beginResolve(qname, QType(qtype), qclass, ret); 
   
   return res;
 }
index 4612c274103990083a58109b29bdb4db2a99939d..2b18b02ea3359a10cc2de69ccc812dd6d77db240 100644 (file)
 #include <boost/tuple/tuple_comparison.hpp>
 #include "mtasker.hh"
 #include "iputils.hh"
+
 #include "filterpo.hh"
 
 void primeHints(void);
-class RecursorLua;
+class RecursorLua4;
 
 struct BothRecordsAndSignatures
 {
@@ -292,7 +293,7 @@ public:
     return d_trace.str();
   }
 
-  void setLuaEngine(shared_ptr<RecursorLua> pdl)
+  void setLuaEngine(shared_ptr<RecursorLua4> pdl)
   {
     d_pdl = pdl;
   }
@@ -474,7 +475,7 @@ private:
   vector<ComboAddress> getAddrs(const DNSName &qname, int depth, set<GetBestNSAnswer>& beenthere);
 private:
   ostringstream d_trace;
-  shared_ptr<RecursorLua> d_pdl;
+  shared_ptr<RecursorLua4> d_pdl;
   string d_prefix;
   bool d_cacheonly;
   bool d_nocache;