]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
prequery -> preresolve, make records arrive in the correct order, make nxdomain only...
authorBert Hubert <bert.hubert@netherlabs.nl>
Sat, 14 Jun 2008 21:11:33 +0000 (21:11 +0000)
committerBert Hubert <bert.hubert@netherlabs.nl>
Sat, 14 Jun 2008 21:11:33 +0000 (21:11 +0000)
git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@1200 d19b8d6e-7fed-0310-83ef-9ca221ded41b

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

index e90d3245b604f712c0d73409a8a09cbdd0fe5263..4ac648f81c1b8831eda9cb40073fd7152b431607 100644 (file)
@@ -8167,8 +8167,9 @@ Feb 10 14:16:03 stats: 125784 questions, 13971 cache entries, 309 negative entri
       <sect2>
        <title>Configuring Lua scripts</title>
        <para>
-         In order to load scripts, the PowerDNS Recursor must have 'lua' support built in. The packages distributed from the PowerDNS website have this language
-         enabled, other distributions may differ.
+         In order to load scripts, the PowerDNS Recursor must have Lua support built in. The packages distributed from the PowerDNS website have this language
+         enabled, other distributions may differ. To compile with Lua support, use: <literal>LUA=1 make</literal> or <literal>LUA=1 gmake</literal>
+         as the case may be. Paths to the Lua include files and binaries may be found near the top of the <filename>Makefile</filename>.
        </para>
        <para>
          If lua support is available, a script can be configured either via the configuration file, or at runtime via the <command>rec_control</command> tool.
@@ -8187,11 +8188,11 @@ Feb 10 14:16:03 stats: 125784 questions, 13971 cache entries, 309 negative entri
       </sect2>
       <sect2><title>Writing Lua PowerDNS Recursor scripts</title>
        <para>
-         Once a script is loaded, PowerDNS looks for two functions: <function>prequery</function> and <function>nxdomain</function>. Either or both of these
+         Once a script is loaded, PowerDNS looks for two functions: <function>preresolve</function> and <function>nxdomain</function>. Either or both of these
          can be absent, in which case the corresponding functionality is disabled.
        </para>
        <para>
-         <function>prequery</function> is called before any DNS resolution is attempted, and if this function indicates it, it can supply a direct answer to the 
+         <function>preresolve</function> is called before any DNS resolution is attempted, and if this function indicates it, it can supply a direct answer to the 
          DNS query, overriding the internet. This is useful to combat botnets, or to disable domains unacceptable to an organization for whatever reason.
        </para>
        <para>
@@ -8216,17 +8217,14 @@ function nxdomain ( ip, domain, qtype )
 
   ret={}
   if qtype ~= 1 then return -1, ret end  --  only A records
-  if not string.gmatch(domain, "^www.") then return -1, ret end  -- only things that start with www.
+  if not string.find(domain, "^www.") then return -1, ret end  -- only things that start with www.
   if not matchnetmask(ip, "10.0.0.0/8")  then return -1, ret end -- only interfere with local queries
-  ret[0]={qtype=1, content="127.1.2.3"}    -- add IN A 127.1.2.3
-  ret[1]={qtype=1, content="127.3.2.1"}    -- add IN A 127.3.2.1
-  return 0, ret                 -- return true, plus records
+  ret[1]={qtype=1, content="127.1.2.3"}    -- add IN A 127.1.2.3
+  ret[2]={qtype=1, content="127.3.2.1"}    -- add IN A 127.3.2.1
+  return 0, ret                 -- return no error, plus records
 end
          </screen>
        </para>
-       <para>
-         For Lua 5.0, use <function>string.find</function> instead of <function>string.gmatch</function>.
-       </para>
        <para>
          <warning>
            <para>
@@ -8286,12 +8284,22 @@ end
              <listitem>
                <para>
                  Time to live of a record. Defaults to 3600. Be sure not to specify differing TTLs within answers with an identical qname. While this
-                 can be encoded in DNS, results may be undesired.
+                 will be encoded in DNS, actual results may be undesired.
                </para>
              </listitem>
            </varlistentry>
          </variablelist>
        </para>
+       <para>
+         <warning>
+           <para>
+             The result table must have indexes that start at 1! Otherwise the first or confusingly the last entry of the table will
+             be ignored. A useful technique is to return data using: 
+             <literal>return 0, {{qtype=1, content="1.2.3.4"}, {qtype=1, content="4.3.2.1"}}</literal> as this will get the numbering
+             right automatically.
+           </para>
+         </warning>
+       </para>
       </sect2>
     </sect1>
     <sect1 id="recursor-design-and-engineering">
index 0be22a8a3453af5b84ae2dfff0476fa53ce24479..74fb4416a0f63df2900a7f7b265866fd1f84a842 100644 (file)
@@ -84,9 +84,9 @@ bool PowerDNSLua::nxdomain(const ComboAddress& remote, const string& query, cons
   return passthrough("nxdomain", remote, query, qtype, ret, res);
 }
 
-bool PowerDNSLua::prequery(const ComboAddress& remote, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res)
+bool PowerDNSLua::preresolve(const ComboAddress& remote, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res)
 {
-  return passthrough("prequery", remote, query, qtype, ret, res);
+  return passthrough("preresolve", remote, query, qtype, ret, res);
 }
 
 bool PowerDNSLua::getFromTable(const std::string& key, std::string& value)
@@ -138,12 +138,13 @@ bool PowerDNSLua::passthrough(const string& func, const ComboAddress& remote, co
     throw runtime_error(error);
     return false;
   }
-  res = (int)lua_tonumber(d_lua, 1); // new rcode
-  if(res < 0) {
+  int newres = (int)lua_tonumber(d_lua, 1); // new rcode
+  if(newres < 0) {
     //    cerr << "handler did not handle"<<endl;
     lua_pop(d_lua, 2);
     return false;
   }
+  res=newres;
 
   /* get the result */
   DNSResourceRecord rr;
@@ -156,8 +157,15 @@ bool PowerDNSLua::passthrough(const string& func, const ComboAddress& remote, co
   /*           1       2   3   4   */
   /* stack:  boolean table key row */
 
-  lua_pushnil(d_lua);  /* first key */
-  while (lua_next(d_lua, 2) != 0) {
+#ifndef LUA_VERSION_NUM
+  int tableLen = luaL_getn(d_lua, 2);
+#else
+  int tableLen = lua_objlen(d_lua, 2);
+#endif
+
+  for(int n=1; n < tableLen + 1; ++n) {
+    lua_pushnumber(d_lua, n);
+    lua_gettable(d_lua, 2);
 
     uint32_t tmpnum;
     if(!getFromTable("qtype", tmpnum)) 
@@ -180,7 +188,7 @@ bool PowerDNSLua::passthrough(const string& func, const ComboAddress& remote, co
     /* removes 'value'; keeps 'key' for next iteration */
     lua_pop(d_lua, 1); // table
 
-    //    cerr<<"Adding content '"<<rr.content<<"'\n";
+    //    cerr<<"Adding content '"<<rr.content<<"' with place "<<(int)rr.d_place<<" \n";
     ret.push_back(rr);
   }
 
index 4b2309ad5bafd9c7cfb50258d242fcf331fe0f63..1be6880315d084b662f6d1664cdd9820c6e8dfd2 100644 (file)
@@ -11,7 +11,7 @@ public:
   explicit PowerDNSLua(const std::string& fname);
   ~PowerDNSLua();
   void reload();
-  bool prequery(const ComboAddress& remote, const string& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret);
+  bool preresolve(const ComboAddress& remote, const string& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret);
   bool nxdomain(const ComboAddress& remote, const string& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret);
 private:
   lua_State* d_lua;
index e8f26042b3292a444214cf6c7fc8444db7dc52fb..95122e14f14efee085a97e895e9e81dec322f335 100644 (file)
@@ -538,11 +538,12 @@ void startDoResolve(void *p)
 
     int res;
 
-    if(!g_pdl.get() || !g_pdl->prequery(dc->d_remote, dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res)) {
+    if(!g_pdl.get() || !g_pdl->preresolve(dc->d_remote, dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res)) {
        res = sr.beginResolve(dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), dc->d_mdp.d_qclass, ret);
 
-       if(g_pdl.get() && (res < 0 || res == RCode::NXDomain || res == RCode::ServFail)) {
-        g_pdl->nxdomain(dc->d_remote, dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res);
+       if(g_pdl.get()) {
+        if(res == RCode::NXDomain)
+          g_pdl->nxdomain(dc->d_remote, dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res);
        }
     }
 
index dcbe5f4560f72e911e2962dff34d71c589d7c2ce..1a60065eb615938958e033c4b90438d3731258d7 100644 (file)
@@ -1,37 +1,43 @@
-function prequery ( ip, domain, qtype )
+function preresolve ( ip, domain, qtype )
        print ("prequery handler called for: ", ip, domain, qtype)
-       ret = {}
-       
---     ret[1]= {1, "10.11.12.13", 3601};
---     ret[2]= {1, "11.12.13.14", 3601};
+
        if domain == "www.ds9c.nl." 
        then
-               ret[0]= {qtype=1, content="9.8.7.6", ttl=3601}
-               ret[1]= {qtype=1, content="1.2.3.4", ttl=3601}
+               ret={}
+               ret[1]= {qtype=1, content="9.8.7.6", ttl=3601}
+               ret[2]= {qtype=1, content="1.2.3.4", ttl=3601}
                print "dealing!"
                return 0, ret
        elseif domain == "www.baddomain.com."
        then
-               print "dealing - nx"
-               return 3, ret
+               print "dealing - faking nx"
+               return 3, {}
+       elseif domain == "echo."
+       then
+               print "dealing with echo!"
+               return 0, {{qtype=1, content=ip}}
+       elseif domain == "echo6."
+       then
+               print "dealing with echo6!"
+               return 0, {{qtype=28, content=ip}}
        else
                print "not dealing!"
-               return -1, ret
+               return -1, {}
        end
 end
 
 function nxdomain ( ip, domain, qtype )
        print ("nxhandler called for: ", ip, domain, qtype)
-       ret={}
-       if qtype ~= 1 then return false, ret end  --  only A records
---     if not string.match(domain, "^www.") then return false, ret end  -- only things that start with www.
+       if qtype ~= 1 then return -1, {} end  --  only A records
+       if not string.find(domain, "^www.") then return -1, {} end  -- only things that start with www.
        
        if matchnetmask(ip, "127.0.0.1/8")
        then 
                print "dealing"
-               ret[0]={qtype="5", content="www.webserver.com", ttl=3602}
-               ret[1]={qname="www.webserver.com", qtype="1", content="1.2.3.4", ttl=3602}
-               ret[2]={qname="webserver.com", qtype="2", content="ns1.webserver.com", place=2}
+               ret={}
+               ret[1]={qtype="5", content="www.webserver.com", ttl=3602}
+               ret[2]={qname="www.webserver.com", qtype="1", content="1.2.3.4", ttl=3602}
+               ret[3]={qname="webserver.com", qtype="2", content="ns1.webserver.com", place=2}
 --             ret[1]={15, "25 ds9a.nl", 3602}
                return 0, ret
        else