]> granicus.if.org Git - pdns/commitdiff
lua scripts can now indicate that a query has a 'variable' answer, which means that...
authorBert Hubert <bert.hubert@netherlabs.nl>
Sun, 13 Jun 2010 21:10:32 +0000 (21:10 +0000)
committerBert Hubert <bert.hubert@netherlabs.nl>
Sun, 13 Jun 2010 21:10:32 +0000 (21:10 +0000)
use 'setvariable()' from the lua hooks to indicate this.

git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@1636 d19b8d6e-7fed-0310-83ef-9ca221ded41b

pdns/lua-pdns-recursor.cc
pdns/lua-pdns-recursor.hh
pdns/pdns_recursor.cc
pdns/powerdns-example-script.lua

index 0c0b2befe8807f2046d70055142c1d8d1045f4c7..78230e76985c13d0a1065a3675cd69b8823def05 100644 (file)
@@ -9,12 +9,12 @@ PowerDNSLua::PowerDNSLua(const std::string& fname)
   throw runtime_error("Lua support disabled");
 }
 
-bool PowerDNSLua::nxdomain(const ComboAddress& remote,const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res)
+bool PowerDNSLua::nxdomain(const ComboAddress& remote,const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
 {
   return false;
 }
 
-bool PowerDNSLua::preresolve(const ComboAddress& remote, const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res)
+bool PowerDNSLua::preresolve(const ComboAddress& remote, const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
 {
   return false;
 }
@@ -93,6 +93,15 @@ int getLocalAddressLua(lua_State* lua)
   return 1;
 }
 
+// called by lua to indicate that this answer is 'variable' and should not be cached
+int setVariableLua(lua_State* lua)
+{
+  lua_getfield(lua, LUA_REGISTRYINDEX, "__PowerDNSLua"); 
+  PowerDNSLua* pl = (PowerDNSLua*)lua_touserdata(lua, -1);
+  pl->setVariable();
+  return 0;
+}
+
 int logLua(lua_State *lua)
 {
   if(lua_gettop(lua) >= 1) {
@@ -126,6 +135,10 @@ PowerDNSLua::PowerDNSLua(const std::string& fname)
   lua_pushcfunction(d_lua, logLua);
   lua_setglobal(d_lua, "pdnslog");
 
+  lua_pushcfunction(d_lua, setVariableLua);
+  lua_setglobal(d_lua, "setvariable");
+
+
   lua_pushcfunction(d_lua, getLocalAddressLua);
   lua_setglobal(d_lua, "getlocaladdress");
 
@@ -143,14 +156,14 @@ PowerDNSLua::PowerDNSLua(const std::string& fname)
   lua_setfield(d_lua, LUA_REGISTRYINDEX, "__PowerDNSLua");
 }
 
-bool PowerDNSLua::nxdomain(const ComboAddress& remote, const ComboAddress& local,const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res)
+bool PowerDNSLua::nxdomain(const ComboAddress& remote, const ComboAddress& local,const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
 {
-  return passthrough("nxdomain", remote, local, query, qtype, ret, res);
+  return passthrough("nxdomain", remote, local, query, qtype, ret, res, variable);
 }
 
-bool PowerDNSLua::preresolve(const ComboAddress& remote, const ComboAddress& local,const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res)
+bool PowerDNSLua::preresolve(const ComboAddress& remote, const ComboAddress& local,const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
 {
-  return passthrough("preresolve", remote, local, query, qtype, ret, res);
+  return passthrough("preresolve", remote, local, query, qtype, ret, res, variable);
 }
 
 bool PowerDNSLua::getFromTable(const std::string& key, std::string& value)
@@ -183,8 +196,10 @@ bool PowerDNSLua::getFromTable(const std::string& key, uint32_t& value)
 }
 
 
-bool PowerDNSLua::passthrough(const string& func, const ComboAddress& remote, const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res)
+bool PowerDNSLua::passthrough(const string& func, const ComboAddress& remote, const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, 
+  int& res, bool* variable)
 {
+  d_variable = false;
   lua_getglobal(d_lua,  func.c_str());
   if(!lua_isfunction(d_lua, -1)) {
     //  cerr<<"No such function '"<<func<<"'\n";
@@ -192,7 +207,7 @@ bool PowerDNSLua::passthrough(const string& func, const ComboAddress& remote, co
     return false;
   }
   
-  d_local = local;
+  d_local = local; 
   /* the first argument */
   lua_pushstring(d_lua,  remote.toString().c_str() );
   lua_pushstring(d_lua,  query.c_str() );
@@ -204,6 +219,9 @@ bool PowerDNSLua::passthrough(const string& func, const ComboAddress& remote, co
     throw runtime_error(error);
     return false;
   }
+  
+  *variable |= d_variable;
+  
   int newres = (int)lua_tonumber(d_lua, 1); // new rcode
   if(newres < 0) {
     //    cerr << "handler did not handle"<<endl;
index d03abcc80969db05a4c50bd695133c41099b65ac..d88f73871f5d12ec479cffd7a96e01a7f8013c61 100644 (file)
@@ -11,20 +11,26 @@ public:
   explicit PowerDNSLua(const std::string& fname);
   ~PowerDNSLua();
   void reload();
-  bool preresolve(const ComboAddress& remote,const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret);
-  bool nxdomain(const ComboAddress& remote, const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret);
+  bool preresolve(const ComboAddress& remote,const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret, bool* variable);
+  bool nxdomain(const ComboAddress& remote, const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret, bool* variable);
   
   ComboAddress getLocal()
   {
     return d_local;
   }
+
+  void setVariable()
+  {
+    d_variable=true;
+  }
+
 private:
   lua_State* d_lua;
-  bool passthrough(const string& func, const ComboAddress& remote,const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res);
+  bool passthrough(const string& func, const ComboAddress& remote,const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable);
   bool getFromTable(const std::string& key, std::string& value);
   bool getFromTable(const std::string& key, uint32_t& value);
   bool d_failed;
-  
+  bool d_variable;  
   ComboAddress d_local;
 };
 
index 8e0ad23b5457429c12bad31dfb24ea77e5d1dd89..3460ac0f799f51e8a9bc470ab98594f7cf46865d 100644 (file)
@@ -511,14 +511,16 @@ void startDoResolve(void *p)
 
     int res;
 
-    if(!t_pdl->get() || !(*t_pdl)->preresolve(dc->d_remote, g_listenSocketsAddresses[dc->d_socket], dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res)) {
+    bool variableAnswer = false;
+    if(!t_pdl->get() || !(*t_pdl)->preresolve(dc->d_remote, g_listenSocketsAddresses[dc->d_socket], dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res, &variableAnswer)) {
        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::NXDomain)
-          (*t_pdl)->nxdomain(dc->d_remote, g_listenSocketsAddresses[dc->d_socket], dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res);
+          (*t_pdl)->nxdomain(dc->d_remote, g_listenSocketsAddresses[dc->d_socket], dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res, &variableAnswer);
       }
     }
+    
     uint32_t minTTL=numeric_limits<uint32_t>::max();
     if(res<0) {
       pw.getHeader()->rcode=RCode::ServFail;
@@ -557,11 +559,11 @@ void startDoResolve(void *p)
   sendit:;
     if(!dc->d_tcp) {
       sendto(dc->d_socket, (const char*)&*packet.begin(), packet.size(), 0, (struct sockaddr *)(&dc->d_remote), dc->d_remote.getSocklen());
-      if(!SyncRes::s_nopacketcache) {
+      if(!SyncRes::s_nopacketcache && !variableAnswer ) {
         t_packetCache->insertResponsePacket(string((const char*)&*packet.begin(), packet.size()), g_now.tv_sec, 
                                           min(minTTL, 
-                                              pw.getHeader()->rcode == RCode::ServFail ? SyncRes::s_packetcacheservfailttl : SyncRes::s_packetcachettl
-                                              )
+                                              (pw.getHeader()->rcode == RCode::ServFail) ? SyncRes::s_packetcacheservfailttl : SyncRes::s_packetcachettl
+                                              ) 
                                          );
       }
     }
@@ -1412,7 +1414,7 @@ void handleUDPServerResponse(int fd, FDMultiplexer::funcparam_t& var)
       }
       g_stats.unexpectedCount++; // if we made it here, it really is an unexpected answer
       if(g_logCommonErrors)
-        L<<Logger::Warning<<"Discarding unexpected packet from "<<fromaddr.toString()<<": "<<pident.domain<<", "<<pident.type<<endl;
+        L<<Logger::Warning<<"Discarding unexpected packet from "<<fromaddr.toStringWithPort()<<": "<<pident.domain<<", "<<pident.type<<endl;
     }
     else if(fd >= 0) {
       t_udpclientsocks->returnSocket(fd);
index b722e884c4ccab41ad7c280621389b175408807b..21fb7930158ebdcd234d9cec66413e2fec8a75f9 100644 (file)
@@ -1,6 +1,14 @@
 function preresolve ( remoteip, domain, qtype )
        print ("prequery handler called for: ", remoteip, getlocaladdress(), domain, qtype)
        pdnslog("a test message.. received query from "..remoteip.." on "..getlocaladdress());
+
+       if domain == "www.donotcache.org."
+       then
+               print("making sure www.donotcache.org will never end up in the cache")
+               setvariable()
+               return -1, {}
+       end
+
        if domain == "www.powerdns.org." 
        then
                ret={}