arguments.o lwres.o pdns_recursor.o recursor_cache.o dnsparser.o \
dnswriter.o dnsrecords.o rcpgenerator.o base64.o zoneparser-tng.o \
rec_channel.o rec_channel_rec.o malloc.o selectmplexer.o sillyrecords.o \
-dns_random.o aescrypt.o aeskey.o aes_modes.o aestab.o
-
+dns_random.o aescrypt.o aeskey.o aes_modes.o aestab.o lua-pdns-recursor.o
REC_CONTROL_OBJECTS=rec_channel.o rec_control.o arguments.o
# OS specific instructions
-include sysdeps/$(shell uname).inc
+ifeq ($(LUA), 1)
+ LUALIBS=-llua5.1
+ CXXFLAGS+=-I/usr/include/lua5.1 -DPDNS_ENABLE_LUA
+endif
+
+
ifeq ($(STATIC),semi)
- STATICFLAGS=-Wl,-Bstatic -lstdc++ -lgcc -Wl,-Bdynamic -static-libgcc -lm -lc
+ STATICFLAGS=-Wl,-Bstatic -lstdc++ $(LUALIBS) -lgcc -Wl,-Bdynamic -static-libgcc -lm -lc
LINKCC=$(CC)
-endif
-ifeq ($(STATIC),full)
- STATICFLAGS=-lstdc++ -lm -static
+elseifeq ($(STATIC),full)
+ STATICFLAGS=-lstdc++ -lm $(LUALIBS) -static
LINKCC=$(CC)
+else
+ LDFLAGS += $(LUALIBS)
endif
+
LDFLAGS += $(PROFILEFLAGS) $(STATICFLAGS)
message:
#include "lua-pdns-recursor.hh"
+
+#ifdef PDNS_ENABLE_LUA
+#define PDNS_DO_LUA
+#endif
+
+#ifdef LIBDIR
+#define PDNS_DO_LUA
+#endif
+
+#if !defined(PDNS_DO_LUA) && !defined(LIBDIR)
+
+// stub implementation
+
+PowerDNSLua::PowerDNSLua(const std::string& fname)
+{
+ throw runtime_error("Lua support disabled");
+}
+
+bool PowerDNSLua::nxdomain(const ComboAddress& remote, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res)
+{
+ return false;
+}
+
+bool PowerDNSLua::prequery(const ComboAddress& remote, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res)
+{
+ return false;
+}
+
+PowerDNSLua::~PowerDNSLua()
+{
+
+}
+
+#else
+
extern "C" {
#undef L
/* Include the Lua API header files. */
{
d_lua = lua_open();
luaopen_base(d_lua);
+ luaopen_string(d_lua);
+
lua_settop(d_lua, 0);
if(luaL_dofile(d_lua, fname.c_str()))
throw runtime_error(string("Error loading LUA file '")+fname+"': "+ string(lua_isstring(d_lua, -1) ? lua_tostring(d_lua, -1) : "unknown error"));
rr.qtype = QType((int)(lua_tonumber(d_lua, -1)));
lua_pop(d_lua, 1);
-
- lua_pushnumber(d_lua, 2); // 4 is now '1'
+ lua_pushnumber(d_lua, 2); // 4 is now '2'
lua_gettable(d_lua, 3); // replace by the second entry of our table we hope
-
rr.content= lua_tostring(d_lua, -1);
- lua_pop(d_lua, 2); // content + table
+ lua_pop(d_lua, 1); // content
+
+ lua_pushnumber(d_lua, 3); // 4 is now '3'
+ lua_gettable(d_lua, 3); // replace by the second entry of our table we hope
+ rr.ttl = (uint32_t)lua_tonumber(d_lua, -1);
+ lua_pop(d_lua, 1); // content
+
+
+ lua_pop(d_lua, 1); // table
// cerr<<"Adding content '"<<rr.content<<"'\n";
ret.push_back(rr);
PowerDNSLua::~PowerDNSLua()
{
- cerr<<"Destructor called"<<endl;
- /* Remember to destroy the Lua State */
lua_close(d_lua);
- cerr<<"Done destroying"<<endl;
-}
-
-/*
-int main()
-{
- PowerDNSLua pdl;
- pdl.nxdomain(ComboAddress("127.0.0.1"), "ds9a.nl", QType(QType::A));
}
-*/
+#endif
#include "iputils.hh"
#include "mplexer.hh"
#include "config.h"
+#include "lua-pdns-recursor.hh"
#ifndef RECURSOR
#include "statbag.hh"
FDMultiplexer* g_fdm;
unsigned int g_maxTCPPerClient;
bool g_logCommonErrors;
+shared_ptr<PowerDNSLua> g_pdl;
using namespace boost;
#ifdef __FreeBSD__ // see cvstrac ticket #26
if(!dc->d_mdp.d_header.rd)
sr.setCacheOnly();
- int res=sr.beginResolve(dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), dc->d_mdp.d_qclass, ret);
+ 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))
+ 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(res<0) {
pw.getHeader()->rcode=RCode::ServFail;
}
}
+string doReloadLuaScript(vector<string>::const_iterator begin, vector<string>::const_iterator end)
+{
+ string fname=::arg()["lua-dns-script"];
+ try {
+ if(begin==end) {
+ if(!fname.empty())
+ g_pdl = shared_ptr<PowerDNSLua>(new PowerDNSLua(fname));
+ else
+ throw runtime_error("Asked to relead lua scripts, but no name passed and no default ('lua-dns-script') defined");
+ }
+ else {
+ fname=*begin;
+ if(fname.empty()) {
+ g_pdl.reset();
+ L<<Logger::Error<<"Unloaded current lua script"<<endl;
+ return "unloaded current lua script\n";
+ }
+ else
+ g_pdl = shared_ptr<PowerDNSLua>(new PowerDNSLua(fname));
+ }
+ }
+ catch(exception& e) {
+ L<<Logger::Error<<"Retaining current script, error from '"<<fname<<"': "<< e.what() <<endl;
+ return string("Retaining current script, error from '"+fname+"': "+string(e.what())+"\n");
+ }
+ L<<Logger::Warning<<"(Re)loaded lua script from '"<<fname<<"'"<<endl;
+ return "ok - loaded script from '"+fname+"'\n";
+}
+
void seedRandom(const string& source);
int serviceMain(int argc, char*argv[])
}
parseAuthAndForwards();
+
+ try {
+ if(!::arg()["lua-dns-script"].empty()) {
+ g_pdl = shared_ptr<PowerDNSLua>(new PowerDNSLua(::arg()["lua-dns-script"]));
+ L<<Logger::Warning<<"Loaded 'lua' script from '"<<::arg()["lua-dns-script"]<<"'"<<endl;
+ }
+
+ }
+ catch(exception &e) {
+ L<<Logger::Error<<"Failed to load 'lua' script from '"<<::arg()["lua-dns-script"]<<"': "<<e.what()<<endl;
+ exit(99);
+ }
+
g_stats.remotes.resize(::arg().asNum("remotes-ringbuffer-entries"));
if(!g_stats.remotes.empty())
// HTimer mtimer("main");
// mtimer.start();
+
g_stats.startupTime=time(0);
reportBasicTypes();
::arg().set("export-etc-hosts", "If we should serve up contents from /etc/hosts")="off";
::arg().set("serve-rfc1918", "If we should be authoritative for RFC 1918 private IP space")="";
::arg().set("auth-can-lower-ttl", "If we follow RFC 2181 to the letter, an authoritative server can lower the TTL of NS records")="off";
+ ::arg().set("lua-dns-script", "Filename containing an optional 'lua' script that will be used to modify dns answers")="";
::arg().setSwitch( "ignore-rd-bit", "Assume each packet requires recursion, for compatability" )= "off";
::arg().setCmd("help","Provide a helpful message");
if(cmd=="wipe-cache")
return doWipeCache(begin, end);
+ if(cmd=="reload-lua-script")
+ return doReloadLuaScript(begin, end);
+
+ if(cmd=="unload-lua-script") {
+ vector<string> empty;
+ empty.push_back(string());
+ return doReloadLuaScript(empty.begin(), empty.end());
+ }
+
+
if(cmd=="top-remotes")
return doTopRemotes();
}
};
+string doReloadLuaScript(vector<string>::const_iterator begin, vector<string>::const_iterator end);
+
extern RecursorStats g_stats;