From e18dbde1d496ded10aa16a79ed516ce5940e3950 Mon Sep 17 00:00:00 2001 From: Bert Hubert Date: Sun, 5 Jun 2011 18:27:45 +0000 Subject: [PATCH] add Lua backend, add to tar.gz, .deb and rpm git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@2208 d19b8d6e-7fed-0310-83ef-9ca221ded41b --- build-scripts/rpm-build-instruction | 2 +- build-scripts/tar-gz-build-instruction | 2 +- configure.ac | 7 +- modules/luabackend/Makefile.am | 11 + modules/luabackend/OBJECTFILES | 1 + modules/luabackend/OBJECTLIBS | 1 + modules/luabackend/README | 137 ++++ modules/luabackend/dnssec.cc | 614 ++++++++++++++++++ modules/luabackend/lua_functions.cc | 320 +++++++++ modules/luabackend/lua_functions.hh | 8 + modules/luabackend/luabackend.cc | 56 ++ modules/luabackend/luabackend.hh | 229 +++++++ modules/luabackend/master.cc | 83 +++ modules/luabackend/minimal.cc | 237 +++++++ modules/luabackend/private.cc | 129 ++++ modules/luabackend/reload.cc | 184 ++++++ modules/luabackend/slave.cc | 288 ++++++++ modules/luabackend/supermaster.cc | 133 ++++ modules/luabackend/test/dnsperf | 1 + modules/luabackend/test/one | 2 + modules/luabackend/test/pdns | 4 + modules/luabackend/test/pdns.conf | 340 ++++++++++ modules/luabackend/test/pdns.pid | 1 + modules/luabackend/test/pdnssec | 1 + .../luabackend/test/powerdns-luabackend.lua | 112 ++++ 25 files changed, 2898 insertions(+), 5 deletions(-) create mode 100644 modules/luabackend/Makefile.am create mode 100644 modules/luabackend/OBJECTFILES create mode 100644 modules/luabackend/OBJECTLIBS create mode 100644 modules/luabackend/README create mode 100644 modules/luabackend/dnssec.cc create mode 100644 modules/luabackend/lua_functions.cc create mode 100644 modules/luabackend/lua_functions.hh create mode 100644 modules/luabackend/luabackend.cc create mode 100644 modules/luabackend/luabackend.hh create mode 100644 modules/luabackend/master.cc create mode 100644 modules/luabackend/minimal.cc create mode 100644 modules/luabackend/private.cc create mode 100644 modules/luabackend/reload.cc create mode 100644 modules/luabackend/slave.cc create mode 100644 modules/luabackend/supermaster.cc create mode 100755 modules/luabackend/test/dnsperf create mode 100644 modules/luabackend/test/one create mode 100755 modules/luabackend/test/pdns create mode 100644 modules/luabackend/test/pdns.conf create mode 100644 modules/luabackend/test/pdns.pid create mode 100755 modules/luabackend/test/pdnssec create mode 100644 modules/luabackend/test/powerdns-luabackend.lua diff --git a/build-scripts/rpm-build-instruction b/build-scripts/rpm-build-instruction index f3402c955..631f21fbb 100755 --- a/build-scripts/rpm-build-instruction +++ b/build-scripts/rpm-build-instruction @@ -1,7 +1,7 @@ #!/bin/sh #LIBS="-lkrb5 -lk5crypto -lpgport -lgssapi_krb5 -lkrb5support -lgssapi_krb5 -lcom_err -lnsl -lresolv" \ CC="ccache gcc" CXX="ccache g++" ./configure \ - --with-modules="mysql gmysql gpgsql gsqlite gsqlite3 pipe pdns geo" \ + --with-modules="mysql gmysql gpgsql gsqlite gsqlite3 pipe pdns geo lua" \ --with-dynmodules="" \ --enable-static-binaries \ --with-pgsql-lib=/opt/postgresql/lib --with-pgsql-includes=/opt/postgresql/include \ diff --git a/build-scripts/tar-gz-build-instruction b/build-scripts/tar-gz-build-instruction index 3deb39aef..e1435dc01 100755 --- a/build-scripts/tar-gz-build-instruction +++ b/build-scripts/tar-gz-build-instruction @@ -2,6 +2,6 @@ rm -f $(find . -name "*~") && ./bootstrap && ./configure \ --with-pgsql-lib=/opt/postgresql/lib --with-pgsql-includes=/opt/postgresql/include \ ---with-modules="mysql mydns gmysql mongodb gpgsql xdb pipe oracle pipe pdns db2 odbc ldap gsqlite gsqlite3 geo goracle opendbx godbc" \ +--with-modules="mysql mydns gmysql mongodb lua gpgsql xdb pipe oracle pipe pdns db2 odbc ldap gsqlite gsqlite3 geo goracle opendbx godbc" \ --with-dynmodules="" && make dist \ No newline at end of file diff --git a/configure.ac b/configure.ac index 66435d5c4..2e8e1f4c6 100644 --- a/configure.ac +++ b/configure.ac @@ -646,6 +646,7 @@ modules/geobackend/Makefile modules/opendbxbackend/Makefile \ modules/pipebackend/Makefile modules/oraclebackend/Makefile \ modules/xdbbackend/Makefile modules/godbcbackend/Makefile \ modules/odbcbackend/Makefile modules/mongodbbackend/Makefile \ -modules/gpgsqlbackend/Makefile modules/ldapbackend/Makefile -modules/gsqlitebackend/Makefile modules/gsqlite3backend/Makefile -modules/goraclebackend/Makefile modules/mydnsbackend/Makefile) +modules/gpgsqlbackend/Makefile modules/ldapbackend/Makefile \ +modules/gsqlitebackend/Makefile modules/gsqlite3backend/Makefile \ +modules/goraclebackend/Makefile modules/mydnsbackend/Makefile \ +modules/luabackend/Makefile ) diff --git a/modules/luabackend/Makefile.am b/modules/luabackend/Makefile.am new file mode 100644 index 000000000..406b80efe --- /dev/null +++ b/modules/luabackend/Makefile.am @@ -0,0 +1,11 @@ +AM_CPPFLAGS=@THREADFLAGS@ +EXTRA_DIST=OBJECTFILES OBJECTLIBS + +INCLUDES=-I/usr/include/lua5.1 +#INCLUDES=-I/usr/local/include/luajit-2.0 -DUSE_LUAJIT + +lib_LTLIBRARIES = libluabackend.la + +libluabackend_la_SOURCES=luabackend.cc luabackend.hh minimal.cc reload.cc lua_functions.cc master.cc private.cc slave.cc supermaster.cc dnssec.cc +libluabackend_la_LDFLAGS=-module -avoid-version -llua5.1 +#-lluajit-5.1 diff --git a/modules/luabackend/OBJECTFILES b/modules/luabackend/OBJECTFILES new file mode 100644 index 000000000..3c78d71d7 --- /dev/null +++ b/modules/luabackend/OBJECTFILES @@ -0,0 +1 @@ +luabackend.o minimal.o reload.o lua_functions.o master.o private.o slave.o supermaster.o dnssec.o \ No newline at end of file diff --git a/modules/luabackend/OBJECTLIBS b/modules/luabackend/OBJECTLIBS new file mode 100644 index 000000000..cab857527 --- /dev/null +++ b/modules/luabackend/OBJECTLIBS @@ -0,0 +1 @@ +-llua5.1 \ No newline at end of file diff --git a/modules/luabackend/README b/modules/luabackend/README new file mode 100644 index 000000000..fdbc5ab64 --- /dev/null +++ b/modules/luabackend/README @@ -0,0 +1,137 @@ +==================================== +This is the luabackend for PowerDNS! +==================================== + +This backend is just a "glue" between PowerDNS and your own Lua application. + +This does mean that you can not have a working setup that can serve you +dns-questions directly from start. What you need to do is to program your own +backend completly in Lua! Which database server to use etc is now up to you! + +What you have here is the possibility to make your own "dns-server" without the +knowledge of programming in c/c++. + +There is one thing that needs to be sad. Remember that each thread +PowerDNS launch of this backend is completly different so they cannot +share information between each other! + +You will need some kind of a database that can be shared for this. + +All the functionsname that PowerDNS except for a backend should be the same +in your Lua script, in lowercase. Also, the parameters should be in the same +order. Where there is a struture in c/c++ there is a table in the Lua backend. +This is also true for returnvalues. + + +============= +NEW FUNCTIONS +============= + +There is a couple of new functions for you to use in Lua: + +----------------------------------- +logger(log_facility, "your messages") +----------------------------------- + +All these log_facilities is availible: +log_all, log_ntlog, log_alert, log_critical, log_error, log_warning, log_notice, +log_info, log_debug, log_none + + +----------- +dnspacket() +----------- + +This will give you back three parameters with +remote_ip, remote_port and local_ip in that order. + +Can only be used for the functions list() and getsoa(). + + +------------------------ +getarg("your_parameter") +------------------------ + +Thisone tries to get the value of the name "lua-your_parameter" from the pdns.conf file. + + +------------------------ +mustdo("your_parameter") +------------------------ + +This is the same as getarg() but return a boolean instead of a string. + + +You also have all the different QTypes in a table called 'QTypes'. + + +==================== +WHAT HAS BEEN TESTED +==================== + +The only functionallity of the mininal functions except zone-transfer has +been tested. + +In the included powerdns-luabackend.lua file there is a example of how +this can be done. Note that this is more or less a static example since +there is no possiblity for each thread to know when something has changed. + +However, you run 'pdns_control reload' and it should reload the hole thing +from scratch. + + +=========================================== +WHAT YOU WILL FIND UNDER THE TEST DIRECTORY +=========================================== + +The script 'pdns' is used to test the server on the ip address '127.0.0.1' with +the port 5300. You should be able to run the following test with the included +'powerdns-luabackend.lua' file: + +$dig any www.test.com @127.0.0.1 -p5300 +multiline +; <<>> DiG 9.7.3 <<>> any www.test.com @127.0.0.1 -p5300 +multiline +;; global options: +cmd +;; Got answer: +;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 1001 +;; flags: qr aa rd; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0 +;; WARNING: recursion requested but not available + +;; QUESTION SECTION: +;www.test.com. IN ANY + +;; ANSWER SECTION: +www.test.com. 120 IN CNAME host.test.com. +host.test.com. 120 IN A 10.11.12.13 +host.test.com. 120 IN AAAA 1:2:3:4:5:6:7:8 + +;; Query time: 1 msec +;; SERVER: 127.0.0.1#5300(127.0.0.1) +;; WHEN: Thu Jun 2 22:19:56 2011 +;; MSG SIZE rcvd: 93 + + +============================= +OPTIONS IN THE CONFIGURE FILE +============================= + +The default values is: + +lua-filename = powerdns-luabackend.lua + +You can also override all the default functionsnames for the luafunctions if you want. +The prefix is lua-f_=mynewfunction. For example: + +lua-f_lookup = mynewfunction + +will call the function 'mynewfunction' for the lookup-routine. + +If you want your own configuration parameters you can have that too. +Just call the function getarg("my_parameter") and it will return the value +of 'lua-my_parameter'. For boolean you use the function mustdo("my_parameter"). + + + +You can send question about this backend to >dev/null first and if you don't get any +answer from that you can try to send them to me at fredan-pdns@fredan.org + +Fredrik Danerklint. \ No newline at end of file diff --git a/modules/luabackend/dnssec.cc b/modules/luabackend/dnssec.cc new file mode 100644 index 000000000..df93fda1a --- /dev/null +++ b/modules/luabackend/dnssec.cc @@ -0,0 +1,614 @@ +/* + Copyright (C) 2011 Fredrik Danerklint + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as published + by the Free Software Foundation + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + + +#include "luabackend.hh" + +#include "pdns/logger.hh" +#include "pdns/arguments.hh" + +/* + virtual bool updateDNSSECOrderAndAuth(uint32_t domain_id, const std::string& zonename, const std::string& qname, bool auth) + virtual bool updateDNSSECOrderAndAuthAbsolute(uint32_t domain_id, const std::string& qname, const std::string& ordername, bool auth) + virtual bool getBeforeAndAfterNamesAbsolute(uint32_t id, const std::string& qname, std::string& unhashed, std::string& before, std::string& after) + + virtual bool getDomainKeys(const string& name, unsigned int kind, std::vector& keys) + virtual bool removeDomainKey(const string& name, unsigned int id) + virtual int addDomainKey(const string& name, const KeyData& key) + virtual bool activateDomainKey(const string& name, unsigned int id) + virtual bool deactivateDomainKey(const string& name, unsigned int id) + + virtual bool getTSIGKey(const string& name, string* algorithm, string* content) { return false; } + + virtual bool setDomainMetadata(const string& name, const std::string& kind, std::vector& meta) + virtual bool getDomainMetadata(const string& name, const std::string& kind, std::vector& meta) + virtual void alsoNotifies(const string &domain, set *ips) + +*/ + +bool LUABackend::updateDNSSECOrderAndAuth(uint32_t domain_id, const std::string& zonename, const std::string& qname, bool auth) { + + if(f_lua_updatednssecorderandauth == 0) { + + if(logging) + L << Logger::Info << backend_name << "(updateDNSSECOrderAndAuth) domain_id: '" << domain_id << "' zonename: '" << zonename << "' qname: '" << qname << "' auth: '" << auth << "'" << endl; + + string ins=toLower(labelReverse(makeRelative(qname, zonename))); + return this->updateDNSSECOrderAndAuthAbsolute(domain_id, qname, ins, auth); + + } + + if(logging) + L << Logger::Info << backend_name << "(updateDNSSECOrderAndAuth) BEGIN domain_id: '" << domain_id << "' zonename: '" << zonename << "' qname: '" << qname << "' auth: '" << auth << "'" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_updatednssecorderandauth); + + lua_pushnumber(lua, domain_id); + lua_pushstring(lua, zonename.c_str()); + lua_pushstring(lua, qname.c_str()); + lua_pushboolean(lua, auth); + + if(lua_pcall(lua, 4, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + size_t returnedwhat = lua_type(lua, -1); + bool ok = false; + + if (returnedwhat == LUA_TBOOLEAN) + ok = lua_toboolean(lua, -1); + + lua_pop(lua, 1); + + if(logging) + L << Logger::Info << backend_name << "(updateDNSSECOrderAndAuth) END" << endl; + + return ok; +} + +bool LUABackend::updateDNSSECOrderAndAuthAbsolute(uint32_t domain_id, const std::string& qname, const std::string& ordername, bool auth) { + + if(f_lua_updatednssecorderandauthabsolute == 0) + return false; + + if(logging) + L << Logger::Info << backend_name << "(updateDNSSECOrderAndAuthAbsolute) BEGIN domain_id: '" << domain_id << "' qname: '" << qname << "' ordername: '" << ordername << "' auth: '" << auth << "'" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_updatednssecorderandauthabsolute); + + lua_pushnumber(lua, domain_id); + lua_pushstring(lua, qname.c_str()); + lua_pushstring(lua, ordername.c_str()); + lua_pushboolean(lua, auth); + + if(lua_pcall(lua, 4, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + size_t returnedwhat = lua_type(lua, -1); + bool ok = false; + + if (returnedwhat == LUA_TBOOLEAN) + ok = lua_toboolean(lua, -1); + + lua_pop(lua, 1); + + if(logging) + L << Logger::Info << backend_name << "(updateDNSSECOrderAndAuthAbsolute) END" << endl; + + return ok; +} + +bool LUABackend::getBeforeAndAfterNamesAbsolute(uint32_t id, const std::string& qname, std::string& unhashed, std::string& before, std::string& after) { + + if(f_lua_getbeforeandafternamesabsolute == 0) + return false; + + unhashed.clear(); + before.clear(); + after.clear(); + + if(logging) + L << Logger::Info << backend_name << "(getBeforeAndAfterNamesAbsolute) BEGIN id: '" << id << "' qname: '" << qname << "'" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_updatednssecorderandauthabsolute); + + lua_pushnumber(lua, id); + lua_pushstring(lua, qname.c_str()); + + if(lua_pcall(lua, 2, 3, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + size_t returnedwhat = lua_type(lua, -1); + bool ok = returnedwhat == LUA_TSTRING; + + if (!ok) { + if(logging) + L << Logger::Info << backend_name << "(getBeforeAndAfterNamesAbsolute) ERROR!" << endl; + + return false; + } + + //will this be correct since we are poping one at the time? + unhashed = lua_tostring(lua, -1); + lua_pop(lua, 1); + + returnedwhat = lua_type(lua, -1); + ok = (returnedwhat == LUA_TSTRING) && ok; + + before = lua_tostring(lua, -1); + lua_pop(lua, 1); + + returnedwhat = lua_type(lua, -1); + ok = (returnedwhat == LUA_TSTRING) && ok; + + after = lua_tostring(lua, -1); + lua_pop(lua, 1); + + if(logging) + L << Logger::Info << backend_name << "(getBeforeAndAfterNamesAbsolute) END unhashed: '" << unhashed << "' before: '" << before << "' after: '" << after << "' " << endl; + + return ok; +} + +bool LUABackend::updateDomainKey(const string& name, unsigned int &id, bool toowhat ) { + + if(f_lua_updatedomainkey == 0) + return false; + + if(logging) + L << Logger::Info << backend_name << "(updateDomainKey) BEGIN name: '" << name << "' id: '" << id << "' toowhat: '" << toowhat << "'" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_updatedomainkey); + + lua_pushstring(lua, name.c_str()); + lua_pushnumber(lua, id); + lua_pushboolean(lua, toowhat); + + if(lua_pcall(lua, 3, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + size_t returnedwhat = lua_type(lua, -1); + bool ok = false; + + if (returnedwhat == LUA_TBOOLEAN) + ok = lua_toboolean(lua, -1); + + lua_pop(lua, 1); + + if(logging) + L << Logger::Info << backend_name << "(updateDomainKey) END" << endl; + + return ok; +} + +bool LUABackend::activateDomainKey(const string& name, unsigned int id) { + + if(f_lua_activatedomainkey == 0) + return updateDomainKey(name, id, true); + + if(logging) + L << Logger::Info << backend_name << "(activateDomainKey) BEGIN name: '" << name << "' id: '" << id << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_activatedomainkey); + + lua_pushstring(lua, name.c_str()); + lua_pushnumber(lua, id); + + if(lua_pcall(lua, 2, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + size_t returnedwhat = lua_type(lua, -1); + bool ok = false; + + if (returnedwhat == LUA_TBOOLEAN) + ok = lua_toboolean(lua, -1); + + lua_pop(lua, 1); + + if(logging) + L << Logger::Info << backend_name << "(activateDomainKey) END" << endl; + + return ok; +} + +bool LUABackend::deactivateDomainKey(const string& name, unsigned int id) { + + if(f_lua_deactivatedomainkey == 0) + return updateDomainKey(name, id, false); + + if(logging) + L << Logger::Info << backend_name << "(deactivateDomainKey) BEGIN name: '" << name << "' id: '" << id << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_deactivatedomainkey); + + lua_pushstring(lua, name.c_str()); + lua_pushnumber(lua, id); + + if(lua_pcall(lua, 2, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + size_t returnedwhat = lua_type(lua, -1); + bool ok = false; + + if (returnedwhat == LUA_TBOOLEAN) + ok = lua_toboolean(lua, -1); + + lua_pop(lua, 1); + + if(logging) + L << Logger::Info << backend_name << "(deactivateDomainKey) END" << endl; + + return ok; +} + +bool LUABackend::removeDomainKey(const string& name, unsigned int id) { + + if(f_lua_removedomainkey == 0) + return false; + + if(logging) + L << Logger::Info << backend_name << "(removeDomainKey) BEGIN name: '" << name << "' id: '" << id << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_removedomainkey); + + lua_pushstring(lua, name.c_str()); + lua_pushnumber(lua, id); + + if(lua_pcall(lua, 2, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + size_t returnedwhat = lua_type(lua, -1); + bool ok = false; + + if (returnedwhat == LUA_TBOOLEAN) + ok = lua_toboolean(lua, -1); + + lua_pop(lua, 1); + + if(logging) + L << Logger::Info << backend_name << "(removeDomainKey) END" << endl; + + return ok; +} + +int LUABackend::addDomainKey(const string& name, const KeyData& key) { +// there is no logging function in pdnssec when running this routine? + +//key = id, flags, active, content + + if(f_lua_adddomainkey == 0) + return -1; + + if(logging) + //L << Logger::Info << backend_name << "(addDomainKey) BEGIN name: '" << name << "' id: '" << id << endl; + cerr << backend_name << "(addDomainKey) BEGIN name: '" << name << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_adddomainkey); + + lua_pushstring(lua, name.c_str()); + + lua_newtable(lua); + + lua_pushliteral(lua, "flags"); + lua_pushnumber(lua, key.flags); + lua_settable(lua, -3); + + lua_pushliteral(lua, "active"); + lua_pushboolean(lua, key.active); + lua_settable(lua, -3); + + lua_pushliteral(lua, "content"); + lua_pushstring(lua, key.content.c_str()); + lua_settable(lua, -3); + + if(lua_pcall(lua, 2, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return -1; + } + + size_t returnedwhat = lua_type(lua, -1); + int ok = -1; + + if (returnedwhat == LUA_TNUMBER) + ok = lua_tonumber(lua, -1); + + lua_pop(lua, 1); + + if(logging) + cerr << backend_name << "(addDomainKey) END" << endl; + + return ok; +} + +bool LUABackend::getDomainKeys(const string& name, unsigned int kind, std::vector& keys) { + //what is kind used for? + + if(f_lua_getdomainkeys == 0) + return false; + + if(logging) + L << Logger::Info << backend_name << "(getDomainKeys) BEGIN name: '" << name << "' kind: '" << kind << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_getdomainkeys); + + lua_pushstring(lua, name.c_str()); + lua_pushnumber(lua, kind); + + if(lua_pcall(lua, 2, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + size_t returnedwhat = lua_type(lua, -1); + + if (returnedwhat != LUA_TTABLE) { + lua_pop(lua, 1); + if(logging) + L << Logger::Info << backend_name << "(getDomainKeys) ERROR!" << endl; + + return false; + } + + lua_pushnil(lua); + + int key; + int j = 0; + + while (lua_next(lua, -2)) { + returnedwhat = lua_type(lua, -1); + if (returnedwhat == LUA_TTABLE) { + KeyData kd; + bool i,f,a,c = false; + + i = getValueFromTable(lua, "id", kd.id); + f = getValueFromTable(lua, "flags", kd.flags); + a = getValueFromTable(lua, "active", kd.active); + c = getValueFromTable(lua, "content", kd.content); + + if (i && f && a && c) { + j++; + keys.push_back(kd); + } + } + + lua_pop(lua,1); + key = lua_tonumber(lua, -1); + } + + if(logging) + L << Logger::Info << backend_name << "(getDomainKeys) END" << endl; + + return j > 0; +} + +bool LUABackend::getTSIGKey(const string& name, string* algorithm, string* content) { + + if(f_lua_gettsigkey == 0) + return false; + + if(logging) + L << Logger::Info << backend_name << "(getTSIGKey) BEGIN name: '" << name << "'" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_gettsigkey); + + lua_pushstring(lua, name.c_str()); + + if(lua_pcall(lua, 1, 2, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + if ( (lua_type(lua, -1) != LUA_TSTRING) && (lua_type(lua, -2) != LUA_TSTRING) ) { + lua_pop(lua, 2); + if(logging) + L << Logger::Info << backend_name << "(getTSIGKey) ERROR" << endl; + return false; + } + + string a,c = ""; + + a = lua_tostring(lua, -1); + lua_pop(lua, 1); + + c = lua_tostring(lua, -1); + lua_pop(lua, 1); + + *algorithm = a; + *content = c; + + if(logging) + L << Logger::Info << backend_name << "(getTSIGKey) END" << endl; + + return true; +} + +bool LUABackend::setDomainMetadata(const string& name, const std::string& kind, std::vector& meta) { + + if(f_lua_setdomainmetadata == 0) + return false; + + if(logging) + L << Logger::Info << backend_name << "(setDomainMetadata) BEGIN name: '" << name << "' kind: '" << kind << "'" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_setdomainmetadata); + + lua_pushstring(lua, name.c_str()); + lua_pushstring(lua, kind.c_str()); + + lua_newtable(lua); + std::vector::iterator i; + + int c = 0; + + for(i = meta.begin(); ic_str()); + lua_settable(lua, -3); + } + + if(lua_pcall(lua, 3, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + size_t returnedwhat = lua_type(lua, -1); + bool ok = false; + + if (returnedwhat == LUA_TBOOLEAN) + ok = lua_toboolean(lua, -1); + + lua_pop(lua, 1); + + if(logging) + L << Logger::Info << backend_name << "(setDomainMetadata) END" << endl; + + return ok; + +} + +bool LUABackend::getDomainMetadata(const string& name, const std::string& kind, std::vector& meta) { + if(f_lua_getdomainmetadata == 0) + return false; + + if(logging) + L << Logger::Info << backend_name << "(getDomainMetadata) BEGIN name: '" << name << "' kind: '" << kind << "'" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_getdomainmetadata); + + lua_pushstring(lua, name.c_str()); + lua_pushstring(lua, kind.c_str()); + + if(lua_pcall(lua, 2, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + lua_pushnil(lua); + + int key; + int j = 0; + size_t returnedwhat; + + while (lua_next(lua, -2)) { + returnedwhat = lua_type(lua, -1); + if (returnedwhat == LUA_TSTRING) { + j++; + meta.push_back(lua_tostring(lua, -1)); + } + + lua_pop(lua,1); + key = lua_tonumber(lua, -1); + } + + if(logging) + L << Logger::Info << backend_name << "(getDomainMetadata) END" << endl; + + return j > 0; + +} + +void LUABackend::alsoNotifies(const string &domain, set *ips) { + + if(f_lua_alsonotifies == 0) + return; + + if(logging) + L << Logger::Info << backend_name << "(alsonotifies) BEGIN domain: '" << domain << "'" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_alsonotifies); + + lua_pushstring(lua, domain.c_str()); + + if(lua_pcall(lua, 1, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return; + } + + lua_pushnil(lua); + + int key; + size_t returnedwhat; + + while (lua_next(lua, -2)) { + returnedwhat = lua_type(lua, -1); + if (returnedwhat == LUA_TSTRING) { + ips->insert(lua_tostring(lua, -1)); + } + + lua_pop(lua,1); + key = lua_tonumber(lua, -1); + } + + if(logging) + L << Logger::Info << backend_name << "(alsoNotifies) END" << endl; + + return; + +} diff --git a/modules/luabackend/lua_functions.cc b/modules/luabackend/lua_functions.cc new file mode 100644 index 000000000..b30c13f4d --- /dev/null +++ b/modules/luabackend/lua_functions.cc @@ -0,0 +1,320 @@ +/* + Copyright (C) 2011 Fredrik Danerklint + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as published + by the Free Software Foundation + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#define LUABACKEND_EXTERN_F_HH + +#include "luabackend.hh" + +#include "pdns/logger.hh" +#include "pdns/arguments.hh" +#include "pdns/dnspacket.hh" + +#include +#include +using namespace std; + +const luaL_Reg lualibs[] = { + {"", luaopen_base}, + {LUA_LOADLIBNAME, luaopen_package}, + {LUA_TABLIBNAME, luaopen_table}, + {LUA_IOLIBNAME, luaopen_io}, + {LUA_OSLIBNAME, luaopen_os}, + {LUA_STRLIBNAME, luaopen_string}, + {LUA_MATHLIBNAME, luaopen_math}, + {LUA_DBLIBNAME, luaopen_debug}, +// {LUA_COLIBNAME, luaopen_coroutine}, +#ifdef USE_LUAJIT + {"bit", luaopen_bit}, + {"jit", luaopen_jit}, +#endif + {NULL, NULL} +}; + +int my_lua_panic (lua_State *lua) { + lua_getfield(lua, LUA_REGISTRYINDEX, "__LUABACKEND"); + LUABackend* lb = (LUABackend*)lua_touserdata(lua, -1); + + assert(lua == lb->lua); + + stringstream e; + + e << lb->backend_name << "LUA PANIC! '" << lua_tostring(lua,-1) << "'" << endl; + + throw LUAException (e.str()); + + return 0; +} + +int l_arg_get (lua_State *lua) { + int i = lua_gettop(lua); + if (i < 1) + return 0; + + lua_getfield(lua, LUA_REGISTRYINDEX, "__LUABACKEND"); + LUABackend* lb = (LUABackend*)lua_touserdata(lua, -1); + + string a = lua_tostring(lua, 1); + + if (::arg().isEmpty(a)) + lua_pushnil(lua); + else + lua_pushstring(lua, lb->my_getArg(a).c_str()); + + return 1; +} + +int l_arg_mustdo (lua_State *lua) { + int i = lua_gettop(lua); + if (i < 1) + return 0; + + lua_getfield(lua, LUA_REGISTRYINDEX, "__LUABACKEND"); + LUABackend* lb = (LUABackend*)lua_touserdata(lua, -1); + + string a = lua_tostring(lua, 1); + + if (::arg().isEmpty(a)) + lua_pushnil(lua); + else + lua_pushboolean(lua, lb->my_mustDo(a)); + + return 1; +} + +int l_dnspacket (lua_State *lua) { + lua_getfield(lua, LUA_REGISTRYINDEX, "__LUABACKEND"); + LUABackend* lb = (LUABackend*)lua_touserdata(lua, -1); + + if (lb->dnspacket == NULL) { + lua_pushnil(lua); + + return 1; + } + + lua_pushstring(lua, lb->dnspacket->getRemote().c_str()); + lua_pushnumber(lua, lb->dnspacket->getRemotePort()); + lua_pushstring(lua, lb->dnspacket->getLocal().c_str()); + + return 3; +} + +int l_logger (lua_State *lua) { +// assert(lua == lb->lua); + + lua_getfield(lua, LUA_REGISTRYINDEX, "__LUABACKEND"); + LUABackend* lb = (LUABackend*)lua_touserdata(lua, -1); + + int i = lua_gettop(lua); + if (i < 1) + return 0; + + int log_level = 0; + stringstream s; + int j; + const char *ss; + + log_level = lua_tointeger(lua, 1); + + string space = ""; + + for(j=2; j<=i; j++) { + ss = lua_tostring(lua, j); + s << space << ss; + space = " "; + } + + L.log(lb->backend_name + s.str(), (Logger::Urgency) log_level); + + return 0; +} + +void register_lua_functions(lua_State *lua) { + lua_gc(lua, LUA_GCSTOP, 0); // stop collector during initialization + + const luaL_Reg *lib = lualibs; + for (; lib->func; lib++) { + lua_pushcfunction(lua, lib->func); + lua_pushstring(lua, lib->name); + lua_call(lua, 1, 0); + } + + lua_gc(lua, LUA_GCRESTART, 0); + + lua_pushinteger(lua, Logger::All); + lua_setglobal(lua, "log_all"); + + lua_pushinteger(lua, Logger::NTLog); + lua_setglobal(lua, "log_ntlog"); + + lua_pushinteger(lua, Logger::Alert); + lua_setglobal(lua, "log_alert"); + + lua_pushinteger(lua, Logger::Critical); + lua_setglobal(lua, "log_critical"); + + lua_pushinteger(lua, Logger::Error); + lua_setglobal(lua, "log_error"); + + lua_pushinteger(lua, Logger::Warning); + lua_setglobal(lua, "log_warning"); + + lua_pushinteger(lua, Logger::Notice); + lua_setglobal(lua, "log_notice"); + + lua_pushinteger(lua, Logger::Info); + lua_setglobal(lua, "log_info"); + + lua_pushinteger(lua, Logger::Debug); + lua_setglobal(lua, "log_debug"); + + lua_pushinteger(lua, Logger::None); + lua_setglobal(lua, "log_none"); + + lua_pushcfunction(lua, l_dnspacket); + lua_setglobal(lua, "dnspacket"); + + lua_pushcfunction(lua, l_logger); + lua_setglobal(lua, "logger"); + + lua_pushcfunction(lua, l_arg_get); + lua_setglobal(lua, "getarg"); + + lua_pushcfunction(lua, l_arg_mustdo); + lua_setglobal(lua, "mustdo"); + + lua_newtable(lua); + for(vector::const_iterator iter = QType::names.begin(); iter != QType::names.end(); ++iter) { + lua_pushnumber(lua, iter->second); + lua_setfield(lua, -2, iter->first.c_str()); + } + lua_pushnumber(lua, 3); + lua_setfield(lua, -2, "NXDOMAIN"); + lua_setglobal(lua, "QTypes"); +} + +bool LUABackend::getValueFromTable(lua_State *lua, const std::string& key, string& value) { + lua_pushstring(lua, key.c_str()); + lua_gettable(lua, -2); + + bool ret = false; + + if(!lua_isnil(lua, -1)) { + value = lua_tostring(lua, -1); + ret = true; + } + + lua_pop(lua, 1); + + return ret; +} + +bool LUABackend::getValueFromTable(lua_State *lua, uint32_t key, string& value) { + lua_pushnumber(lua, key); + lua_gettable(lua, -2); + + bool ret = false; + + if(!lua_isnil(lua, -1)) { + value = lua_tostring(lua, -1); + ret = true; + } + + lua_pop(lua, 1); + + return ret; +} + +bool LUABackend::getValueFromTable(lua_State *lua, const std::string& key, time_t& value) { + lua_pushstring(lua, key.c_str()); + lua_gettable(lua, -2); + + bool ret = false; + + if(!lua_isnil(lua, -1)) { + value = (time_t)lua_tonumber(lua, -1); + ret = true; + } + + lua_pop(lua, 1); + + return ret; +} + +bool LUABackend::getValueFromTable(lua_State *lua, const std::string& key, uint32_t& value) { + lua_pushstring(lua, key.c_str()); + lua_gettable(lua, -2); + + bool ret = false; + + if(!lua_isnil(lua, -1)) { + value = (uint32_t)lua_tonumber(lua, -1); + ret = true; + } + + lua_pop(lua, 1); + + return ret; +} + +bool LUABackend::getValueFromTable(lua_State *lua, const std::string& key, uint16_t& value) { + lua_pushstring(lua, key.c_str()); + lua_gettable(lua, -2); + + bool ret = false; + + if(!lua_isnil(lua, -1)) { + value = (uint16_t)lua_tonumber(lua, -1); + ret = true; + } + + lua_pop(lua, 1); + + return ret; +} + +bool LUABackend::getValueFromTable(lua_State *lua, const std::string& key, int& value) { + lua_pushstring(lua, key.c_str()); + lua_gettable(lua, -2); + + bool ret = false; + + if(!lua_isnil(lua, -1)) { + value = (int)lua_tonumber(lua, -1); + ret = true; + } + + lua_pop(lua, 1); + + return ret; +} + +bool LUABackend::getValueFromTable(lua_State *lua, const std::string& key, bool& value) { + lua_pushstring(lua, key.c_str()); + lua_gettable(lua, -2); + + bool ret = false; + + if(!lua_isnil(lua, -1)) { + value = lua_toboolean(lua, -1); + ret = true; + } + + lua_pop(lua, 1); + + return ret; +} + diff --git a/modules/luabackend/lua_functions.hh b/modules/luabackend/lua_functions.hh new file mode 100644 index 000000000..6d56980ab --- /dev/null +++ b/modules/luabackend/lua_functions.hh @@ -0,0 +1,8 @@ +#ifndef LUABACKEND_EXTERN_F_HH +#define LUABACKEND_EXTERN_F_HH + +//extern LUABackend* lb; +extern int my_lua_panic(lua_State* lua); +extern void register_lua_functions(lua_State* lua); + +#endif diff --git a/modules/luabackend/luabackend.cc b/modules/luabackend/luabackend.cc new file mode 100644 index 000000000..3e4bf3ddc --- /dev/null +++ b/modules/luabackend/luabackend.cc @@ -0,0 +1,56 @@ +/* + Copyright (C) 2011 Fredrik Danerklint + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as published + by the Free Software Foundation + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "luabackend.hh" +#include "pdns/logger.hh" + +/* SECOND PART */ + +class LUAFactory : public BackendFactory +{ +public: + LUAFactory() : BackendFactory("lua") {} + + void declareArguments(const string &suffix="") + { + + declare(suffix,"filename","Filename of the script for lua backend","powerdns-luabackend.lua"); + declare(suffix,"logging-query","Logging of the LUA Backend","no"); + + } + + DNSBackend *make(const string &suffix="") + { + return new LUABackend(suffix); + } + +}; + +/* THIRD PART */ + +class LUALoader +{ +public: + LUALoader() + { + BackendMakers().report(new LUAFactory); + + L< +using std::string; + +//#undef L + + + +class LUAException { +public: + LUAException(const string &ex) : what(ex){} + string what; +}; + +class LUABackend : public DNSBackend { + +public: + +// MINIMAL BACKEND + + LUABackend(const string &suffix=""); + ~LUABackend(); + bool list(const string &target, int domain_id); + void lookup(const QType &qtype, const string &qname, DNSPacket *p, int domain_id); + bool get(DNSResourceRecord &rr); + //! fills the soadata struct with the SOA details. Returns false if there is no SOA. + bool getSOA(const string &name, SOAData &soadata, DNSPacket *p=0); + + +// MASTER BACKEND + + void getUpdatedMasters(vector* domains); + void setNotifed(int id, u_int32_t serial); + + +// SLAVE BACKEND + + bool getDomainInfo(const string &domain, DomainInfo &di); + bool isMaster(const string &name, const string &ip); + void getUnfreshSlaveInfos(vector* domains); + void setFresh(int id); + + bool startTransaction(const string &qname, int id); + bool commitTransaction(); + bool abortTransaction(); + bool feedRecord(const DNSResourceRecord &rr); + + +// SUPERMASTER BACKEND + + bool superMasterBackend(const string &ip, const string &domain, const vector&nsset, string *account, DNSBackend **db); + bool createSlaveDomain(const string &ip, const string &domain, const string &account); + + +// DNSSEC BACKEND + + //! get a list of IP addresses that should also be notified for a domain + void alsoNotifies(const string &domain, set *ips); + bool getDomainMetadata(const string& name, const std::string& kind, std::vector& meta); + bool setDomainMetadata(const string& name, const std::string& kind, std::vector& meta); + + bool getDomainKeys(const string& name, unsigned int kind, std::vector& keys); + bool removeDomainKey(const string& name, unsigned int id); + bool activateDomainKey(const string& name, unsigned int id); + bool deactivateDomainKey(const string& name, unsigned int id); + bool getTSIGKey(const string& name, string* algorithm, string* content); + int addDomainKey(const string& name, const KeyData& key); + + bool getBeforeAndAfterNamesAbsolute(uint32_t id, const std::string& qname, std::string& unhashed, std::string& before, std::string& after); + bool updateDNSSECOrderAndAuthAbsolute(uint32_t domain_id, const std::string& qname, const std::string& ordername, bool auth); + bool updateDNSSECOrderAndAuth(uint32_t domain_id, const std::string& zonename, const std::string& qname, bool auth); + + +// OTHER + void reload(); + void rediscover(string* status=0); + + + string backend_name; + lua_State *lua; + DNSPacket *dnspacket; + + //private.cc + string my_getArg(string a); + bool my_mustDo(string a); + +private: + + pthread_t backend_pid; + unsigned int backend_count; + + int f_lua_exec_error; + + //mininal functions.... + int f_lua_list; + int f_lua_lookup; + int f_lua_get; + int f_lua_getsoa; + + //master functions.... + int f_lua_getupdatedmasters; + int f_lua_setnotifed; + + //slave functions.... + int f_lua_getdomaininfo; + int f_lua_ismaster; + int f_lua_getunfreshslaveinfos; + int f_lua_setfresh; + + int f_lua_starttransaction; + int f_lua_committransaction; + int f_lua_aborttransaction; + int f_lua_feedrecord; + + //supermaster functions.... + int f_lua_supermasterbackend; + int f_lua_createslavedomain; + + //rediscover + int f_lua_rediscover; + + //dnssec + int f_lua_alsonotifies; + int f_lua_getdomainmetadata; + int f_lua_setdomainmetadata; + + int f_lua_getdomainkeys; + int f_lua_removedomainkey; + int f_lua_activatedomainkey; + int f_lua_deactivatedomainkey; + int f_lua_updatedomainkey; + int f_lua_gettsigkey; + int f_lua_adddomainkey; + + int f_lua_getbeforeandafternamesabsolute; + int f_lua_updatednssecorderandauthabsolute; + int f_lua_updatednssecorderandauth; + + +// int my_lua_panic (lua_State *lua); + +// FUNCTIONS TO THIS BACKEND + bool getValueFromTable(lua_State *lua, const std::string& key, string& value); + bool getValueFromTable(lua_State *lua, uint32_t key, string& value); + bool getValueFromTable(lua_State *lua, const std::string& key, time_t& value); + bool getValueFromTable(lua_State *lua, const std::string& key, uint32_t& value); + bool getValueFromTable(lua_State *lua, const std::string& key, uint16_t& value); + bool getValueFromTable(lua_State *lua, const std::string& key, int& value); + bool getValueFromTable(lua_State *lua, const std::string& key, bool& value); + + //private.cc + bool domaininfo_from_table(DomainInfo *di); + void domains_from_table(vector* domains, const char *f_name); + void dnsrr_to_table(lua_State *lua, const DNSResourceRecord *rr); + + //reload.cc + void get_lua_function(lua_State *lua, const char *name, int *function); + + bool dnssec; + + bool logging; + + //dnssec.cc + bool updateDomainKey(const string& name, unsigned int &id, bool toowhat); + + +/* + //minimal.cc + bool content(DNSResourceRecord* rr); + + void getTheFreshOnes(vector* domains, string *type, string *f_name); + bool checkDomainInfo(const string *domain, mongo::BSONObj *mongo_r, string *f_name, string *mongo_q, DomainInfo *di, SOAData *soadata = NULL); + + + //crc32.cc + int generateCRC32(const string& my_string); + + string mongo_db; + string collection_domains; + string collection_records; + + string collection_domainmetadata; + string collection_cryptokeys; + string collection_tsigkeys; + + mongo::DBClientConnection m_db; + + auto_ptr cursor; + + string q_name; + +// long long unsigned int count; + mongo::Query mongo_query; + mongo::BSONObj mongo_record; + bool elements; + DNSResourceRecord rr_record; + string type; + mongo::BSONObjIterator* contents; + + + + unsigned int default_ttl; + + bool logging_cerr; + bool logging_content; + + bool checkindex; + + bool use_default_ttl; + + bool axfr_soa; + SOAData last_soadata; +*/ +}; + +#endif diff --git a/modules/luabackend/master.cc b/modules/luabackend/master.cc new file mode 100644 index 000000000..559e63f3e --- /dev/null +++ b/modules/luabackend/master.cc @@ -0,0 +1,83 @@ +/* + Copyright (C) 2011 Fredrik Danerklint + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as published + by the Free Software Foundation + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + + +#include "luabackend.hh" + +#include "pdns/logger.hh" +#include "pdns/arguments.hh" + +/* + virtual void getUpdatedMasters(vector* domains); + virtual void setNotifed(int id, u_int32_t serial); +*/ + +void LUABackend::getUpdatedMasters(vector* domains) { + + if (f_lua_getupdatedmasters == 0) + return; + + if (logging) + L << Logger::Info << backend_name << "(getUpdatedMasters) BEGIN" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_getupdatedmasters); + + if(lua_pcall(lua, 0, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return; + } + + size_t returnedwhat = lua_type(lua, -1); + if (returnedwhat != LUA_TTABLE) { + lua_pop(lua, 1 ); + return; + } + + domains_from_table(domains, "getUpdatedMasters"); + + if (logging) + L << Logger::Info << backend_name << "(getUpdatedMasters) END" << endl; +} + +void LUABackend::setNotifed(int id, u_int32_t serial) { + + if (f_lua_setnotifed == 0) + return; + + if (logging) + L << Logger::Info << backend_name << "(setNotifed) BEGIN" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_setnotifed); + + lua_pushnumber(lua, id); + lua_pushnumber(lua, serial); + + if(lua_pcall(lua, 2, 0, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return; + } + + if (logging) + L << Logger::Info << backend_name << "(setNotifed) END" << endl; +} + diff --git a/modules/luabackend/minimal.cc b/modules/luabackend/minimal.cc new file mode 100644 index 000000000..1bf9cfed2 --- /dev/null +++ b/modules/luabackend/minimal.cc @@ -0,0 +1,237 @@ +/* + Copyright (C) 2011 Fredrik Danerklint + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as published + by the Free Software Foundation + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "luabackend.hh" + +#include "pdns/logger.hh" +#include "pdns/arguments.hh" + +//#include "lua_functions.hh" + +/* FIRST PART */ + +LUABackend::LUABackend(const string &suffix) { + + setArgPrefix("lua"+suffix); + + try { + + if (pthread_equal(backend_pid, pthread_self())) { + backend_count++; + } else { + backend_count = 1; + backend_pid = pthread_self(); + } + +// lb = NULL; + lua = NULL; + dnspacket = NULL; + dnssec = false; + + reload(); + } + + catch(LUAException &e) { + L< 0) + soadata.ttl = soadata.default_ttl; + + if (soadata.ttl == 0) { + lua_pop(lua, 1 ); + return false; + } + + if (!getValueFromTable(lua, "nameserver", soadata.nameserver)) { + soadata.nameserver = arg()["default-soa-name"]; + if (soadata.nameserver.empty()) { + L<backend = NULL; + + if (!getValueFromTable(lua, "id", di->id)) + return false; + + if (!getValueFromTable(lua, "zone", di->zone)) + return false; + + if (!getValueFromTable(lua, "serial", di->serial)) + return false; + + getValueFromTable(lua, "notified_serial", di->notified_serial); + getValueFromTable(lua, "last_check", di->last_check); + + di->kind = DomainInfo::Native; + + string kind; + if (getValueFromTable(lua, "kind", kind)) { + + if (kind == "MASTER") + di->kind = DomainInfo::Master; + else if (kind == "SLAVE") + di->kind = DomainInfo::Slave; + } + + lua_pushstring(lua, "masters"); + lua_gettable(lua, -2); + + if(!lua_isnil(lua, -1)) { + lua_pushnil(lua); + const char *key, *value; + while (lua_next(lua, -2)) { + value = lua_tostring(lua, -1); + lua_pop(lua,1); + key = lua_tostring(lua, -1); + + di->masters.push_back(value); + } + } + + lua_pop(lua, 1); + + di->backend = this; + + return true; +} + +void LUABackend::domains_from_table(vector* domains, const char *f_name) { + lua_pushnil(lua); + + int k; + size_t returnedwhat; + + while (lua_next(lua, -2)) { + returnedwhat = lua_type(lua, -1); + if (returnedwhat == LUA_TTABLE) { + DomainInfo di; + + if (domaininfo_from_table(&di)) + domains->push_back(di); + } + + lua_pop(lua,1); + k = lua_tonumber(lua, -1); + } +} + + +void LUABackend::dnsrr_to_table(lua_State *lua, const DNSResourceRecord *rr) { + + lua_newtable(lua); + + lua_pushliteral(lua, "qtype"); + lua_pushstring(lua, rr->qtype.getName().c_str()); + lua_settable(lua, -3); + + lua_pushliteral(lua, "qclass"); + lua_pushnumber(lua, rr->qclass); + lua_settable(lua, -3); + + lua_pushliteral(lua, "priority"); + lua_pushnumber(lua, rr->priority); + lua_settable(lua, -3); + + lua_pushliteral(lua, "ttl"); + lua_pushnumber(lua, rr->ttl); + lua_settable(lua, -3); + + lua_pushliteral(lua, "auth"); + lua_pushboolean(lua, rr->auth); + lua_settable(lua, -3); + + lua_pushliteral(lua, "content"); + lua_pushstring(lua, rr->content.c_str()); + lua_settable(lua, -3); + +} \ No newline at end of file diff --git a/modules/luabackend/reload.cc b/modules/luabackend/reload.cc new file mode 100644 index 000000000..6e143aac0 --- /dev/null +++ b/modules/luabackend/reload.cc @@ -0,0 +1,184 @@ +/* + Copyright (C) 2011 Fredrik Danerklint + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as published + by the Free Software Foundation + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + + +#include "luabackend.hh" + +#include "pdns/logger.hh" +#include "pdns/arguments.hh" + +#include +#include +using namespace std; + +#include "lua_functions.hh" + +/* + virtual void reload(); + virtual void rediscover(string* status=0); +*/ + +void LUABackend::get_lua_function(lua_State *lua, const char *name, int *function) { + *function = 0; + + string f = "f_"; + f.append(name); + + string arg = ""; + if (!::arg().isEmpty(f)) + arg = getArg(f); + + lua_getglobal(lua, arg == "" ? name : arg.c_str()); + if (!lua_isnil(lua, -1)) { + lua_pushvalue(lua, -1); + *function = luaL_ref(lua, LUA_REGISTRYINDEX); + } +} + + +void LUABackend::reload() { + + backend_name.clear(); + +// backend_name = "[LUABackend: " + uitoa(backend_pid) + " (" + uitoa(backend_count) +")] "; + backend_name = "[LUABackend: (" + uitoa(backend_count) +")] "; + + if (lua) + lua_close(lua); + + logging = ::arg().mustDo("query-logging") || mustDo("logging-query"); + + lua = lua_open(); + + if (lua != NULL) { + lua_atpanic(lua, my_lua_panic); + + string filename = getArg("filename"); //"powerdns-luabackend.lua"; + + if (luaL_loadfile (lua, filename.c_str()) != 0) { + stringstream e; + e << backend_name << "Error loading the file '" << filename << "' : " << lua_tostring(lua,-1) << endl; + + lua_pop(lua, 1); + throw LUAException (e.str()); + } else { + + lua_pushlightuserdata(lua, (void*)this); + lua_setfield(lua, LUA_REGISTRYINDEX, "__LUABACKEND"); + + register_lua_functions(lua); + + if(lua_pcall(lua, 0, 0, 0)) { + stringstream e; + e << backend_name << "Error running the file '" << filename << "' : " << lua_tostring(lua,-1) << endl; + + lua_pop(lua, 1); + throw LUAException (e.str()); + + } else { + get_lua_function(lua, "exec_error", &f_lua_exec_error); + + //minimal functions.... + get_lua_function(lua, "list", &f_lua_list); + get_lua_function(lua, "lookup", &f_lua_lookup); + get_lua_function(lua, "get", &f_lua_get); + get_lua_function(lua, "getsoa", &f_lua_getsoa); + + if (f_lua_list == 0 || f_lua_lookup == 0 || f_lua_get == 0 || f_lua_getsoa == 0) { + throw LUAException (backend_name + "MINIMAL BACKEND: Missing requried function(s)!"); + } + + //master functions.... + get_lua_function(lua, "getupdatedmasters", &f_lua_getupdatedmasters); + get_lua_function(lua, "setnotifed", &f_lua_setnotifed); + + //slave functions.... + get_lua_function(lua, "getdomaininfo", &f_lua_getdomaininfo); + get_lua_function(lua, "ismaster", &f_lua_ismaster); + get_lua_function(lua, "getunfreshslaveinfos", &f_lua_getunfreshslaveinfos); + get_lua_function(lua, "setfresh", &f_lua_setfresh); + get_lua_function(lua, "starttransaction", &f_lua_starttransaction); + get_lua_function(lua, "committransaction", &f_lua_committransaction); + get_lua_function(lua, "aborttransaction", &f_lua_aborttransaction); + get_lua_function(lua, "feedrecord", &f_lua_feedrecord); + + //supermaster functions.... + get_lua_function(lua, "supermasterbackend", &f_lua_supermasterbackend); + get_lua_function(lua, "createslavedomain", &f_lua_createslavedomain); + + //rediscover + get_lua_function(lua, "rediscover", &f_lua_rediscover); + + //dnssec + get_lua_function(lua, "alsonotifies", &f_lua_alsonotifies); + get_lua_function(lua, "getdomainmetadata", &f_lua_getdomainmetadata); + get_lua_function(lua, "setdomainmetadata", &f_lua_setdomainmetadata); + + get_lua_function(lua, "getdomainkeys", &f_lua_getdomainkeys); + get_lua_function(lua, "removedomainkey", &f_lua_removedomainkey); + get_lua_function(lua, "activatedomainkey", &f_lua_activatedomainkey); + get_lua_function(lua, "deactivatedomainkey", &f_lua_deactivatedomainkey); + get_lua_function(lua, "updatedomainkey", &f_lua_updatedomainkey); + get_lua_function(lua, "adddomainkey", &f_lua_adddomainkey); + + get_lua_function(lua, "gettsigkey", &f_lua_gettsigkey); + + get_lua_function(lua, "getbeforeandafternamesabsolute", &f_lua_getbeforeandafternamesabsolute); + get_lua_function(lua, "updatednssecorderandauthabsolute", &f_lua_updatednssecorderandauthabsolute); + get_lua_function(lua, "updatednssecorderandauth", &f_lua_updatednssecorderandauth); // not needed... + + } + } + } else { + //a big kaboom here! + throw LUAException (backend_name + "LUA OPEN FAILED!"); + } +} + +void LUABackend::rediscover(string* status) { + if (logging) + L << Logger::Info << backend_name << "(rediscover) BEGIN" << endl; + + if (f_lua_rediscover == 0) + return; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_rediscover); + + if(lua_pcall(lua, 0, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return; + } + + size_t returnedwhat = lua_type(lua, -1); + if (returnedwhat != LUA_TSTRING) { + lua_pop(lua, 1 ); + return; + } + + string s = lua_tostring(lua, -1); + lua_pop(lua, 1 ); + *status = s; + + if (logging) + L << Logger::Info << backend_name << "(rediscover) END" << endl; + + return; +} + diff --git a/modules/luabackend/slave.cc b/modules/luabackend/slave.cc new file mode 100644 index 000000000..a77b64ec7 --- /dev/null +++ b/modules/luabackend/slave.cc @@ -0,0 +1,288 @@ +/* + Copyright (C) 2011 Fredrik Danerklint + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as published + by the Free Software Foundation + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + + +#include "luabackend.hh" + +#include "pdns/logger.hh" +#include "pdns/arguments.hh" + +/* + + virtual bool startTransaction(const string &qname, int id); + virtual bool commitTransaction(); + virtual bool abortTransaction(); + virtual bool feedRecord(const DNSResourceRecord &rr); + + virtual bool getDomainInfo(const string &domain, DomainInfo &di); + virtual bool isMaster(const string &name, const string &ip); + virtual void getUnfreshSlaveInfos(vector* domains); + virtual void setFresh(int id); +*/ + +bool LUABackend::startTransaction(const string &qname, int id) { + + if (f_lua_starttransaction == 0) + return false; + + if (logging) + L << Logger::Info << backend_name << "(startTransaction) BEGIN" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_starttransaction); + + lua_pushstring(lua, qname.c_str()); + lua_pushnumber(lua, id); + + if(lua_pcall(lua, 2, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + size_t returnedwhat = lua_type(lua, -1); + bool ok = false; + + if (returnedwhat == LUA_TBOOLEAN) + ok = lua_toboolean(lua, -1); + + lua_pop(lua, 1); + + if (logging) + L << Logger::Info << backend_name << "(startTransaction) END" << endl; + + return ok; +} + +bool LUABackend::commitTransaction() { + + if (f_lua_committransaction == 0) + return false; + + if (logging) + L << Logger::Info << backend_name << "(commitTransaction) BEGIN" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_committransaction); + + if(lua_pcall(lua, 0, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + size_t returnedwhat = lua_type(lua, -1); + bool ok = false; + + if (returnedwhat == LUA_TBOOLEAN) + ok = lua_toboolean(lua, -1); + + lua_pop(lua, 1); + + if (logging) + L << Logger::Info << backend_name << "(commitTransaction) END" << endl; + + return ok; +} + +bool LUABackend::abortTransaction() { + + if (f_lua_aborttransaction == 0) + return false; + + if (logging) + L << Logger::Info << backend_name << "(abortTransaction) BEGIN" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_aborttransaction); + + if(lua_pcall(lua, 0, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + size_t returnedwhat = lua_type(lua, -1); + bool ok = false; + + if (returnedwhat == LUA_TBOOLEAN) + ok = lua_toboolean(lua, -1); + + lua_pop(lua, 1); + + if (logging) + L << Logger::Info << backend_name << "(abortTransaction) END" << endl; + return ok; +} + +bool LUABackend::feedRecord(const DNSResourceRecord &rr) { + + if (f_lua_feedrecord == 0) + return false; + + if (logging) + L << Logger::Info << backend_name << "(feedRecord) BEGIN" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_feedrecord); + dnsrr_to_table(lua, &rr); + + if(lua_pcall(lua, 1, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + size_t returnedwhat = lua_type(lua, -1); + bool ok = false; + + if (returnedwhat == LUA_TBOOLEAN) + ok = lua_toboolean(lua, -1); + + lua_pop(lua, 1); + + if (logging) + L << Logger::Info << backend_name << "(feedRecord) END" << endl; + + return ok; +} + +void LUABackend::setFresh(int id) { + + if (f_lua_setfresh == 0) + return; + + if (logging) + L << Logger::Info << backend_name << "(setFresh) BEGIN" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_setfresh); + + lua_pushnumber(lua, id); + + if(lua_pcall(lua, 1, 0, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return; + } + + if (logging) + L << Logger::Info << backend_name << "(setFresh) END" << endl; + +} + +void LUABackend::getUnfreshSlaveInfos(vector* domains) { + + if (f_lua_getunfreshslaveinfos == 0) + return; + + if (logging) + L << Logger::Info << backend_name << "(getUnfreshSlaveInfos) BEGIN" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_getunfreshslaveinfos); + + if(lua_pcall(lua, 0, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return; + } + + size_t returnedwhat = lua_type(lua, -1); + if (returnedwhat != LUA_TTABLE) { + lua_pop(lua, 1 ); + return; + } + + domains_from_table(domains, "getUnfreshSlaveInfos"); + + if (logging) + L << Logger::Info << backend_name << "(getUnfreshSlaveInfos) END" << endl; + +} + +bool LUABackend::isMaster(const string &domain, const string &ip) { + + if (f_lua_ismaster == 0) + return false; + + if (logging) + L << Logger::Error << backend_name << "(isMaster) BEGIN" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_ismaster); + + lua_pushstring(lua, domain.c_str()); + lua_pushstring(lua, ip.c_str()); + + if(lua_pcall(lua, 2, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + size_t returnedwhat = lua_type(lua, -1); + bool ok = false; + + if (returnedwhat == LUA_TBOOLEAN) + ok = lua_toboolean(lua, -1); + + lua_pop(lua, 1); + + if (logging) + L << Logger::Info << backend_name << "(isMaster) END" << endl; + + return ok; +} + +bool LUABackend::getDomainInfo(const string &domain, DomainInfo &di) { + if (f_lua_getdomaininfo == 0) + return false; + + if (logging) + L << Logger::Info << backend_name << "(getDomainInfo) BEGIN" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_getdomaininfo); + + lua_pushstring(lua, domain.c_str()); + + if(lua_pcall(lua, 1, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + size_t returnedwhat = lua_type(lua, -1); + if (returnedwhat != LUA_TTABLE) { + lua_pop(lua, 1 ); + return false; + } + + if (logging) + L << Logger::Info << backend_name << "(getDomainInfo) END" << endl; + + return domaininfo_from_table(&di); +} diff --git a/modules/luabackend/supermaster.cc b/modules/luabackend/supermaster.cc new file mode 100644 index 000000000..fa6cc0d45 --- /dev/null +++ b/modules/luabackend/supermaster.cc @@ -0,0 +1,133 @@ +/* + Copyright (C) 2011 Fredrik Danerklint + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as published + by the Free Software Foundation + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + + +#include "luabackend.hh" + +#include "pdns/logger.hh" +#include "pdns/arguments.hh" + +/* + //! determine if ip is a supermaster or a domain + virtual bool superMasterBackend(const string &ip, const string &domain, const vector&nsset, string *account, DNSBackend **db) + + //! called by PowerDNS to create a slave record for a superMaster + virtual bool createSlaveDomain(const string &ip, const string &domain, const string &account) + +*/ + +bool LUABackend::superMasterBackend(const string &ip, const string &domain, const vector&nsset, string *account, DNSBackend **db) { + + if (f_lua_supermasterbackend == 0) + return false; + + if (logging) + L << Logger::Info << backend_name << "(superMasterBackend) BEGIN" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_supermasterbackend); + + lua_pushstring(lua, ip.c_str()); + lua_pushstring(lua, domain.c_str()); + + + lua_newtable(lua); + int c = 0; + for(vector::const_iterator i=nsset.begin();i!=nsset.end();++i) { + c++; + lua_pushnumber(lua, c); + + DNSResourceRecord rr; + + rr.qtype = i->qtype; + rr.qclass = i->qclass; + rr.priority = i->priority; + rr.ttl = i->ttl; + rr.auth = i->auth; + rr.content = i->content; + + dnsrr_to_table(lua, &rr); + lua_settable(lua, -3); + } + + if(lua_pcall(lua, 3, 2, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + size_t returnedwhat = lua_type(lua, -1); + bool ok = false; + + if (returnedwhat == LUA_TBOOLEAN) + ok = lua_toboolean(lua, -1); + + lua_pop(lua, 1); + + string a = ""; + returnedwhat = lua_type(lua, -1); + if (returnedwhat == LUA_TSTRING) + a = lua_tostring(lua, -1); + lua_pop(lua, 1); + + if (ok) { + *account = a; + *db = this; + } + + if (logging) + L << Logger::Info << backend_name << "(superMasterBackend) END" << endl; + + return ok; +} + +bool LUABackend::createSlaveDomain(const string &ip, const string &domain, const string &account) { + + if (f_lua_createslavedomain == 0) + return false; + + if (logging) + L << Logger::Info << backend_name << "(createSlaveDomain) BEGIN" << endl; + + lua_rawgeti(lua, LUA_REGISTRYINDEX, f_lua_createslavedomain); + + lua_pushstring(lua, ip.c_str()); + lua_pushstring(lua, domain.c_str()); + lua_pushstring(lua, account.c_str()); + + if(lua_pcall(lua, 3, 1, f_lua_exec_error) != 0) { + string e = backend_name + lua_tostring(lua, -1); + lua_pop(lua, 1); + + throw runtime_error(e); + return false; + } + + size_t returnedwhat = lua_type(lua, -1); + bool ok = false; + + if (returnedwhat == LUA_TBOOLEAN) + ok = lua_toboolean(lua, -1); + + lua_pop(lua, 1); + + if (logging) + L << Logger::Info << backend_name << "(createSlaveDomain) END" << endl; + + return ok; +} diff --git a/modules/luabackend/test/dnsperf b/modules/luabackend/test/dnsperf new file mode 100755 index 000000000..c4ba0e762 --- /dev/null +++ b/modules/luabackend/test/dnsperf @@ -0,0 +1 @@ +../../../../../src/dnsperf-src-1.0.1.0-1/dnsperf -d one -p5300 -H10 -T1 -l60 diff --git a/modules/luabackend/test/one b/modules/luabackend/test/one new file mode 100644 index 000000000..7d137ccf8 --- /dev/null +++ b/modules/luabackend/test/one @@ -0,0 +1,2 @@ +www.test.com ANY + diff --git a/modules/luabackend/test/pdns b/modules/luabackend/test/pdns new file mode 100755 index 000000000..95df2d0fe --- /dev/null +++ b/modules/luabackend/test/pdns @@ -0,0 +1,4 @@ +../../../pdns/pdns_server --daemon=no --local-port=5300 --socket-dir=./ \ +--no-shuffle --launch=lua \ +--fancy-records --send-root-referral --loglevel=9 \ +--config-dir=./ --cache-ttl=0 --negquery-cache-ttl=0 --query-cache-ttl=0 --recursive-cache-ttl=0 \ No newline at end of file diff --git a/modules/luabackend/test/pdns.conf b/modules/luabackend/test/pdns.conf new file mode 100644 index 000000000..5b035022f --- /dev/null +++ b/modules/luabackend/test/pdns.conf @@ -0,0 +1,340 @@ +# Autogenerated configuration file template +################################# +# allow-axfr-ips Allow zonetransfers only to these subnets +# +# allow-axfr-ips=0.0.0.0/0 + +################################# +# allow-recursion List of subnets that are allowed to recurse +# +# allow-recursion=0.0.0.0/0 + +################################# +# allow-recursion-override Set this so that local data fully overrides the recursor +# +# allow-recursion-override=no + +################################# +# cache-ttl Seconds to store packets in the PacketCache +# +# cache-ttl=20 + +################################# +# chroot If set, chroot to this directory for more security +# +# chroot= + +################################# +# config-dir Location of configuration directory (pdns.conf) +# +# config-dir=/usr/local/etc + +################################# +# config-name Name of this virtual configuration - will rename the binary image +# +# config-name= + +################################# +# control-console Debugging switch - don't use +# +# control-console=no + +################################# +# daemon Operate as a daemon +# +# daemon=no + +################################# +# default-soa-name name to insert in the SOA record if none set in the backend +# +# default-soa-name=a.misconfigured.powerdns.server + +################################# +# default-ttl Seconds a result is valid if not set otherwise +# +# default-ttl=3600 + +################################# +# disable-axfr Disable zonetransfers but do allow TCP queries +# +# disable-axfr=no + +################################# +# disable-tcp Do not listen to TCP queries +# +# disable-tcp=no + +################################# +# distributor-threads Default number of Distributor (backend) threads to start +# +distributor-threads=3 + +################################# +# do-ipv6-additional-processing Do AAAA additional processing +# +do-ipv6-additional-processing=yes + +################################# +# fancy-records Process URL and MBOXFW records +# +# fancy-records=no + +################################# +# guardian Run within a guardian process +# +# guardian=no + +################################# +# launch Which backends to launch and order to query them in +# +# launch= + +################################# +# lazy-recursion Only recurse if question cannot be answered locally +# +# lazy-recursion=yes + +################################# +# load-modules Load this module - supply absolute or relative path +# +# load-modules= + +################################# +# local-address Local IP addresses to which we bind +# +local-address=127.0.0.1 + +################################# +# local-ipv6 Local IP address to which we bind +# +local-ipv6=::1 + +################################# +# local-port The port on which we listen +# +# local-port=53 + +################################# +# log-dns-details If PDNS should log DNS non-erroneous details +# +# log-dns-details= + +################################# +# log-failed-updates If PDNS should log failed update requests +# +# log-failed-updates= + +################################# +# logfile Logfile to use (Windows only) +# +# logfile=pdns.log + +################################# +# logging-facility Log under a specific facility +# +# logging-facility= + +################################# +# loglevel Amount of logging. Higher is more. Do not set below 3 +# +# loglevel=4 + +################################# +# master Act as a master +# +# master=no + +################################# +# max-queue-length Maximum queuelength before considering situation lost +# +# max-queue-length=5000 + +################################# +# max-tcp-connections Maximum number of TCP connections +# +# max-tcp-connections=10 + +################################# +# module-dir Default directory for modules +# +# module-dir=/usr/local/lib + +################################# +# negquery-cache-ttl Seconds to store packets in the PacketCache +# +# negquery-cache-ttl=60 + +################################# +# no-shuffle Set this to prevent random shuffling of answers - for regression testing +# +# no-shuffle=off + +################################# +# out-of-zone-additional-processing Do out of zone additional processing +# +# out-of-zone-additional-processing=yes + +################################# +# pipebackend-abi-version Version of the pipe backend ABI +# +# pipebackend-abi-version=1 + +################################# +# query-cache-ttl Seconds to store packets in the PacketCache +# +# query-cache-ttl=20 + +################################# +# query-local-address Source IP address for sending queries +# +# query-local-address= + +################################# +# query-logging Hint backends that queries should be logged +# +# query-logging=no + +################################# +# queue-limit Maximum number of milliseconds to queue a query +# +# queue-limit=1500 + +################################# +# recursive-cache-ttl Seconds to store packets in the PacketCache +# +# recursive-cache-ttl=10 + +################################# +# recursor If recursion is desired, IP address of a recursing nameserver +# +# recursor=no + +################################# +# send-root-referral Send out old-fashioned root-referral instead of ServFail in case of no authority +# +# send-root-referral=no + +################################# +# setgid If set, change group id to this gid for more security +# +# setgid= + +################################# +# setuid If set, change user id to this uid for more security +# +# setuid= + +################################# +# skip-cname Do not perform CNAME indirection for each query +# +# skip-cname=no + +################################# +# slave Act as a slave +# +# slave=no + +################################# +# slave-cycle-interval Reschedule failed SOA serial checks once every .. seconds +# +# slave-cycle-interval=60 + +################################# +# smtpredirector Our smtpredir MX host +# +# smtpredirector=a.misconfigured.powerdns.smtp.server + +################################# +# soa-expire-default Default SOA expire +# +# soa-expire-default=604800 + +################################# +# soa-minimum-ttl Default SOA mininum ttl +# +# soa-minimum-ttl=3600 + +################################# +# soa-refresh-default Default SOA refresh +# +# soa-refresh-default=10800 + +################################# +# soa-retry-default Default SOA retry +# +# soa-retry-default=3600 + +################################# +# soa-serial-offset Make sure that no SOA serial is less than this number +# +# soa-serial-offset=0 + +################################# +# socket-dir Where the controlsocket will live +# +# socket-dir=/var/run + +################################# +# strict-rfc-axfrs Perform strictly rfc compliant axfrs (very slow) +# +# strict-rfc-axfrs=no + +################################# +# trusted-notification-proxy IP address of incoming notification proxy +# +# trusted-notification-proxy= + +################################# +# urlredirector Where we send hosts to that need to be url redirected +# +# urlredirector=127.0.0.1 + +################################# +# use-logfile Use a log file (Windows only) +# +# use-logfile=no + +################################# +# version-string PowerDNS version in packets - full, anonymous, powerdns or custom +# +# version-string=full + +################################# +# webserver Start a webserver for monitoring +# +# webserver=no + +################################# +# webserver-address IP Address of webserver to listen on +# +# webserver-address=127.0.0.1 + +################################# +# webserver-password Password required for accessing the webserver +# +# webserver-password= + +################################# +# webserver-port Port of webserver to listen on +# +# webserver-port=8081 + +################################# +# webserver-print-arguments If the webserver should print arguments +# +# webserver-print-arguments=no + +################################# +# wildcard-url Process URL and MBOXFW records +# +# wildcard-url=no + +################################# +# wildcards Honor wildcards in the database +# +# wildcards= + + +#query-logging=yes +launch=lua + diff --git a/modules/luabackend/test/pdns.pid b/modules/luabackend/test/pdns.pid new file mode 100644 index 000000000..479fd61e4 --- /dev/null +++ b/modules/luabackend/test/pdns.pid @@ -0,0 +1 @@ +6283 diff --git a/modules/luabackend/test/pdnssec b/modules/luabackend/test/pdnssec new file mode 100755 index 000000000..1d6a2b308 --- /dev/null +++ b/modules/luabackend/test/pdnssec @@ -0,0 +1 @@ +../../../pdns/pdnssec --config-dir=./ $@ diff --git a/modules/luabackend/test/powerdns-luabackend.lua b/modules/luabackend/test/powerdns-luabackend.lua new file mode 100644 index 000000000..6ee9d94f3 --- /dev/null +++ b/modules/luabackend/test/powerdns-luabackend.lua @@ -0,0 +1,112 @@ +--remember, this is just a test case to see that the minimal backend does work... + +local logger = logger +local pairs = pairs +local type = type + +local log_error = log_error +local dnspacket = dnspacket + + +local domains_id = {} +local domains_name = {} +local records = {} + + +domains_name["test.com"] = {domain_id = 11, name = "test.com", type = "NATIVE", soa = { hostmaster = "ahu.test.com", nameserver = "ns1.test.com", serial = 2005092501, refresh = 28800, retry = 7200, expire = 604800, default_ttl = 86400, ttl = 3600 } } +domains_id["11"] = domains_name["test.com"] + + +records["test.com"] = { + {domain_id = 11, name = "test.com", type = "NS", ttl = 120, content = "ns1.test.com"}, + {domain_id = 11, name = "test.com", type = "NS", ttl = 120, content = "ns2.test.com"}, +} +records["ns1.test.com"] = { + {domain_id = 11, name = "ns1.test.com", type = "A", ttl = 120, content = "10.11.12.14"}, + {domain_id = 11, name = "ns1.test.com", type = "AAAA", ttl = 120, content = "1:2:3:4:5:6:7:9"} +} +records["ns2.test.com"] = { + {domain_id = 11, name = "ns2.test.com", type = "A", ttl = 120, content = "10.11.12.15"}, + {domain_id = 11, name = "ns2.test.com", type = "AAAA", ttl = 120, content = "1:2:3:4:5:6:7:10"} +} + +records["www.test.com"] = { {domain_id = 11, name = "www.test.com", type = "CNAME", ttl = 120, content = "host.test.com"} } +records["host.test.com"] = { + {domain_id = 11, name = "host.test.com", type = "A", ttl = 120, content = "10.11.12.13"}, + {domain_id = 11, name = "host.test.com", type = "AAAA", ttl = 120, content = "1:2:3:4:5:6:7:8"} +} + + + +function list(target, domain_id) + logger(log_error, "(l_list)", "target:", target, " domain_id:", domain_id ) + + return false +end + +local size, c, r, n, nn, q_type, q_name, domainid +local remote_ip, remote_port, local_ip + +function lookup(qtype, qname, domain_id) +-- logger(log_error, "(l_lookup)", "qtype:", qtype, " qname:", qname, " domain_id:", domain_id ) + q_type = qtype + q_name = qname + domainid = domain_id + + r = records[q_name] + + c = 0 + size = 0 + + remote_ip, remote_port, local_ip = dnspacket() +-- logger(log_error, "(l_lookup) dnspacket", "remote:", remote_ip, " port:", remote_port, " local:", local_ip) + + if type(r) == "table" then + size = #r + end +-- logger(log_error, "(l_lookup)", "size:", size) +end + +function get() +-- logger(log_error, "(l_get) BEGIN") + + while c < size do + c = c + 1 + if (q_type == "ANY" or q_type == r[c]["type"]) then +-- for kk,vv in pairs(r[c]) do +-- logger(log_error, kk, type(vv), vv) +-- end + return r[c] + end + end + +-- logger(log_error, "(l_get) END") + return false +end + +local k,v,kk,vv + +function getsoa(name) +-- logger(log_error, "(l_getsoa) BEGIN", "name:", name) + + r = domains_name[name] + if type(r) == "table" then +-- logger(log_error, type(r), type(r["soa"])) + return r["soa"] + end + +-- logger(log_error, "(l_getsoa) END NOT FOUND") +end + +logger(log_error, "powerdns-luabackend starting up!") + + +for k,v in pairs(QTypes) do +-- logger(log_error, k, v) +end + +for k,v in pairs(records) do + for kk,vv in pairs(v) do +-- logger(log_error, kk, type(vv), vv["type"]) + end +end -- 2.49.0