]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
implement CNAME following when requested from Lua.
authorbert hubert <bert.hubert@netherlabs.nl>
Thu, 20 Mar 2014 11:38:25 +0000 (12:38 +0100)
committerbert hubert <bert.hubert@netherlabs.nl>
Thu, 20 Mar 2014 11:38:25 +0000 (12:38 +0100)
pdns/lua-pdns.cc
pdns/lua-pdns.hh
pdns/lua-recursor.cc
pdns/powerdns-example-script.lua

index 41e96e42b9c3052649afa06be5a5574173b152e7..25e9348b8b6cbcce6221479fde2fc699dc4ad3b3 100644 (file)
@@ -161,6 +161,7 @@ int getLuaTableLength(lua_State* lua, int depth)
 #endif
 }
 
+// expects a table at offset 2, and, importantly DOES NOT POP IT from the stack - only the contents
 void popResourceRecordsTable(lua_State *lua, const string &query, vector<DNSResourceRecord>& ret)
 {
   /* get the result */
@@ -169,10 +170,7 @@ void popResourceRecordsTable(lua_State *lua, const string &query, vector<DNSReso
   rr.d_place = DNSResourceRecord::ANSWER;
   rr.ttl = 3600;
 
-//  cerr<<"Lua stacksize "<<lua_gettop(lua)<<endl;
-
   int tableLen = getLuaTableLength(lua, 2);
-//  cerr<<"Got back "<<tableLen<< " answers from Lua"<<endl;
 
   for(int n=1; n < tableLen + 1; ++n) {
     lua_pushnumber(lua, n);
@@ -278,7 +276,6 @@ int logLua(lua_State *lua)
 
 PowerDNSLua::PowerDNSLua(const std::string& fname)
 {
-
   d_lua = luaL_newstate();
 
   lua_pushcfunction(d_lua, netmaskMatchLua);
@@ -353,4 +350,36 @@ PowerDNSLua::~PowerDNSLua()
 {
   lua_close(d_lua);
 }
+
+#if 0
+void luaStackDump (lua_State *L) {
+  int i;
+  int top = lua_gettop(L);
+  for (i = 1; i <= top; i++) {  /* repeat for each level */
+    int t = lua_type(L, i);
+    switch (t) {
+      
+    case LUA_TSTRING:  /* strings */
+      printf("`%s'", lua_tostring(L, i));
+      break;
+      
+    case LUA_TBOOLEAN:  /* booleans */
+      printf(lua_toboolean(L, i) ? "true" : "false");
+      break;
+      
+    case LUA_TNUMBER:  /* numbers */
+      printf("%g", lua_tonumber(L, i));
+      break;
+      
+    default:  /* other values */
+      printf("%s", lua_typename(L, t));
+      break;
+      
+    }
+    printf("  ");  /* put a separator */
+  }
+  printf("\n");  /* end the listing */
+}
+#endif 
+
 #endif
index eb85ac9f0f167ca41b34b9915841b31ebe42b3f3..934d02aacb63061713a99dd9fa94a45ce7491edf 100644 (file)
@@ -36,4 +36,5 @@ void pushResourceRecordsTable(lua_State* lua, const vector<DNSResourceRecord>& r
 void popResourceRecordsTable(lua_State *lua, const string &query, vector<DNSResourceRecord>& ret);
 void pushSyslogSecurityLevelTable(lua_State *lua);
 int getLuaTableLength(lua_State* lua, int depth);
+void luaStackDump (lua_State *L);
 #endif
index cfda9ea7fda98ac6aa2501c09060bb11fe8b7766..4ac6bdd99b1d0ead334a9d07f2645913b3d81ddd 100644 (file)
@@ -58,6 +58,32 @@ RecursorLua::RecursorLua(const std::string &fname)
   // empty
 }
 
+int followCNAMERecords(vector<DNSResourceRecord>& ret, const QType& qtype)
+{
+  vector<DNSResourceRecord> resolved;
+  string target;
+  BOOST_FOREACH(DNSResourceRecord& rr, ret) {
+    if(rr.qtype.getCode() == QType::CNAME) {
+      target=rr.content;
+      break;
+    }
+  }
+  if(target.empty()) 
+    return 0;
+  
+  if(target[target.size()-1]!='.')
+    target.append(1, '.');
+
+  int rcode=directResolve(target, qtype, 1, resolved); // 1 == class
+
+  BOOST_FOREACH(const DNSResourceRecord& rr, resolved)
+  {    
+    ret.push_back(rr);
+  }
+  return rcode;
+
+}
+
 int getFakeAAAARecords(const std::string& qname, const std::string& prefix, vector<DNSResourceRecord>& ret)
 {
   int rcode=directResolve(qname, QType(QType::A), 1, ret);
@@ -158,26 +184,37 @@ bool RecursorLua::passthrough(const string& func, const ComboAddress& remote, co
     extraParameter+=2;
   }
 
-  if(lua_pcall(d_lua,  3 + extraParameter, 3, 0)) { 
+  if(lua_pcall(d_lua,  3 + extraParameter, 3, 0)) {   // NOTE! Means we always get 3 stack entries back!
     string error=string("lua error in '"+func+"' while processing query for '"+query+"|"+qtype.getName()+": ")+lua_tostring(d_lua, -1);
     lua_pop(d_lua, 1);
     throw runtime_error(error);
     return false;
   }
-  
+
   *variable |= d_variable;
     
   if(!lua_isnumber(d_lua, 1)) {
     string tocall = lua_tostring(d_lua,1);
-    string luaqname = lua_tostring(d_lua,2);
-    string luaprefix = lua_tostring(d_lua, 3);
-    lua_pop(d_lua, 3);
-    // cerr<<"should call '"<<tocall<<"' to finish off"<<endl;
+    lua_remove(d_lua, 1); // the name
     ret.clear();
-    if(tocall == "getFakeAAAARecords")
+    if(tocall == "getFakeAAAARecords") {
+      string luaprefix = lua_tostring(d_lua, 2);
+      string luaqname = lua_tostring(d_lua,1);
+      lua_pop(d_lua, 2);
       res = getFakeAAAARecords(luaqname, luaprefix, ret);
-    else if(tocall == "getFakePTRRecords")
+    }
+    else if(tocall == "getFakePTRRecords") {
+      string luaprefix = lua_tostring(d_lua, 2);
+      string luaqname = lua_tostring(d_lua,1);
+      lua_pop(d_lua, 2);
       res = getFakePTRRecords(luaqname, luaprefix, ret);
+    }
+    else if(tocall == "followCNAMERecords") {
+      popResourceRecordsTable(d_lua, query, ret);
+      lua_pop(d_lua, 2); 
+      res = followCNAMERecords(ret, qtype);
+    }
+
     return true;
     // returned a followup 
   }
@@ -195,10 +232,8 @@ bool RecursorLua::passthrough(const string& func, const ComboAddress& remote, co
   /*           1       2   3   4   */
   /* stack:  boolean table key row */
 
-  popResourceRecordsTable(d_lua, query, ret);
-
+  popResourceRecordsTable(d_lua, query, ret); // doesn't actually pop the table itself!
   lua_pop(d_lua, 3);
-
   return true;
 }
 
index d336acf66380579cab2ea408835cea210a40bf02..b67971ae9558e9893f9555f6754fea97bdf2837e 100644 (file)
@@ -14,6 +14,12 @@ function preresolve ( remoteip, domain, qtype )
                return "getFakePTRRecords", domain, "fe80::21b::77ff:0:0"
        end
 
+       if domain == "www.followme.com."
+       then
+               print ("Need to CNAME www.followme.com to www.powerdns.com")
+               return "followCNAMERecords", 0, {{qtype=pdns.CNAME, content="www.powerdns.com"}}
+       end
+
        if domain == "www.donotanswer.org."
        then
                print("we won't answer a query for donotanswer.org")