]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
expose 'iputils' module to Lua code, allowing for native IP(v6) address processing...
authorbert hubert <bert.hubert@netherlabs.nl>
Mon, 5 Jan 2015 12:24:55 +0000 (13:24 +0100)
committerbert hubert <bert.hubert@netherlabs.nl>
Mon, 5 Jan 2015 12:24:55 +0000 (13:24 +0100)
pdns/Makefile.am
pdns/lua-iputils.cc [new file with mode: 0644]
pdns/lua-pdns.cc
pdns/lua-pdns.hh
pdns/lua-recursor.cc

index eef73aa9281e3ce29dffeb1521505d748ba4aaee..5464997864abc5dd2a6ac93c6dd3960235d2f1dc 100644 (file)
@@ -137,7 +137,7 @@ pdns_server_SOURCES = \
        lock.hh \
        logger.cc logger.hh \
        lua-auth.cc lua-auth.hh \
-       lua-pdns.cc \
+       lua-pdns.cc lua-iputils.cc \
        mastercommunicator.cc \
        md5.hh \
        misc.cc misc.hh \
@@ -360,6 +360,10 @@ zone2json_SOURCES = \
 zone2json_LDFLAGS = $(THREADFLAGS)
 zone2json_LDADD = $(POLARSSL_LIBS)
 
+# pkglib_LTLIBRARIES = iputils.la
+# iputils_la_SOURCES = lua-iputils.cc 
+# iputils_la_LDFLAGS= -module -avoid-version
+
 zone2ldap_SOURCES = \
        arguments.cc \
        base32.cc \
@@ -885,7 +889,7 @@ pdns_recursor_SOURCES = \
        htimer.cc htimer.hh \
        json.cc json.hh \
        logger.cc \
-       lua-pdns.cc lua-pdns.hh \
+       lua-pdns.cc lua-pdns.hh lua-iputils.cc \
        lua-recursor.cc lua-recursor.hh \
        lwres.cc lwres.hh \
        misc.cc \
diff --git a/pdns/lua-iputils.cc b/pdns/lua-iputils.cc
new file mode 100644 (file)
index 0000000..89b8f15
--- /dev/null
@@ -0,0 +1,345 @@
+extern "C" {
+#include <lua.h>
+#include <lauxlib.h>
+}
+#include <iostream>
+#include "iputils.hh"
+#include <string>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <netdb.h>
+       
+using namespace std;
+#undef L
+
+#if !defined LUA_VERSION_NUM || LUA_VERSION_NUM==501
+/*
+** Adapted from Lua 5.2.0
+*/
+static void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
+  luaL_checkstack(L, nup+1, "too many upvalues");
+  for (; l->name != NULL; l++) {  /* fill the table with given functions */
+    int i;
+    lua_pushstring(L, l->name);
+    for (i = 0; i < nup; i++)  /* copy upvalues to the top */
+      lua_pushvalue(L, -(nup+1));
+    lua_pushcclosure(L, l->func, nup);  /* closure with those upvalues */
+    lua_settable(L, -(nup + 3));
+  }
+  lua_pop(L, nup);  /* remove upvalues */
+}
+#endif
+
+
+/////////////////////////////////
+
+static int l_new_ca(lua_State* L)
+{
+  ComboAddress* ca=(ComboAddress*)lua_newuserdata(L, sizeof(ComboAddress)); 
+  memset(ca, 0, sizeof(ComboAddress));
+  *ca=ComboAddress(luaL_checkstring(L, 1));
+  luaL_getmetatable(L, "iputils.ca");
+  lua_setmetatable(L, -2);
+  return 1;
+}
+
+static int l_ca_tostring(lua_State* L)
+{
+  ComboAddress* ca = (ComboAddress*)luaL_checkudata(L, 1, "iputils.ca");
+  
+  string ret=ca->toString();
+  lua_pushstring(L, ret.c_str());
+  return 1;
+}
+
+static int l_ca_tostringWithPort(lua_State* L)
+{
+  ComboAddress* ca = (ComboAddress*)luaL_checkudata(L, 1, "iputils.ca");
+  
+  string ret=ca->toStringWithPort();
+  lua_pushstring(L, ret.c_str());
+  return 1;
+}
+
+static int l_ca_equal(lua_State* L)
+{
+  ComboAddress* ca1 = (ComboAddress*)luaL_checkudata(L, 1, "iputils.ca");
+  ComboAddress* ca2 = (ComboAddress*)luaL_checkudata(L, 2, "iputils.ca");
+  lua_pushboolean(L, *ca1==*ca2);
+  return 1;
+}
+
+static const struct luaL_Reg iputils_ca_methods[]={
+    {"tostring", l_ca_tostring},
+    {"__tostring", l_ca_tostring},
+    {"__eq", l_ca_equal},
+    {"tostringwithport", l_ca_tostringWithPort},
+    {NULL, NULL}
+};
+
+
+/////////////////////////////
+
+static int l_ipset_index(lua_State* L)
+{
+  set<ComboAddress>*ourset = (set<ComboAddress>*)luaL_checkudata(L, 1, "iputils.ipset");
+  ComboAddress* ca1 = (ComboAddress*)luaL_checkudata(L, 2, "iputils.ca");
+  if(ourset->count(*ca1)) {
+    lua_pushboolean(L, 1);
+    return 1;
+  }
+  
+  return 0;
+}
+
+static int l_ipset_newindex(lua_State* L)
+{
+  set<ComboAddress>*ourset = (set<ComboAddress>*)luaL_checkudata(L, 1, "iputils.ipset");
+  ComboAddress* ca1 = (ComboAddress*)luaL_checkudata(L, 2, "iputils.ca");
+  ourset->insert(*ca1);
+  return 0;
+}
+
+static int l_newipset(lua_State* L)
+{
+  new(lua_newuserdata(L, sizeof(set<ComboAddress>))) set<ComboAddress>();
+  luaL_getmetatable(L, "iputils.ipset");
+  lua_setmetatable(L, -2);
+  return 1;
+}
+
+static int l_ipset_gc(lua_State* L)
+{
+  set<ComboAddress>*ourset = (set<ComboAddress>*)luaL_checkudata(L, 1, "iputils.ipset");
+  ourset->~set<ComboAddress>();
+  return 0;
+}
+
+static const struct luaL_Reg ipset_methods[]={
+    {"__index", l_ipset_index},
+    {"__newindex", l_ipset_newindex},
+    {"__gc", l_ipset_gc},
+    {NULL, NULL}
+};
+
+////////////////////////////////////////////////////
+
+
+static int l_netmask_tostring(lua_State* L)
+{
+  Netmask* nm = (Netmask*)luaL_checkudata(L, 1, "iputils.netmask");
+  string ret=nm->toString();
+  lua_pushstring(L, ret.c_str());
+  return 1;
+}
+
+static int l_new_netmask(lua_State* L)
+{
+  /*Netmask* nm=*/ new(lua_newuserdata(L, sizeof(Netmask))) Netmask(luaL_checkstring(L, 1));
+  luaL_getmetatable(L, "iputils.netmask");
+  lua_setmetatable(L, -2);
+  return 1;
+}
+
+static int l_netmask_match(lua_State* L)
+{
+  Netmask* nm=(Netmask*)luaL_checkudata(L, 1, "iputils.netmask");
+  ComboAddress* ca1 = (ComboAddress*)luaL_checkudata(L, 2, "iputils.ca");
+  lua_pushboolean(L, nm->match(*ca1));
+  return 1;
+}
+
+static int l_netmask_gc(lua_State* L)
+{
+  Netmask* nm = (Netmask*)luaL_checkudata(L, 1, "iputils.netmask");
+  nm->~Netmask();
+  return 0;
+}
+
+static const struct luaL_Reg iputils_netmask_methods[]={
+    {"__tostring", l_netmask_tostring},
+    {"match", l_netmask_match},
+    {"__gc", l_netmask_gc},
+    {NULL, NULL}
+};
+
+
+//////////////////////
+
+static int l_nmgroup_tostring(lua_State* L)
+{
+  NetmaskGroup* nmg = (NetmaskGroup*)luaL_checkudata(L, 1, "iputils.nmgroup");
+  
+  string ret=nmg->toString();
+  lua_pushstring(L, ret.c_str());
+  return 1;
+}
+
+static int l_new_nmgroup(lua_State* L)
+{
+  /*NetmaskGroup*nmg= */ new(lua_newuserdata(L, sizeof(NetmaskGroup))) NetmaskGroup();
+  luaL_getmetatable(L, "iputils.nmgroup");
+  lua_setmetatable(L, -2);
+  return 1;
+}
+
+static int l_nmgroup_match(lua_State* L)
+{
+  NetmaskGroup* nm=(NetmaskGroup*)luaL_checkudata(L, 1, "iputils.nmgroup");
+  ComboAddress* ca1 = (ComboAddress*)luaL_checkudata(L, 2, "iputils.ca");
+  lua_pushboolean(L, nm->match(*ca1));
+  return 1;
+}
+
+static int l_nmgroup_add(lua_State* L)
+{
+  NetmaskGroup* nm=(NetmaskGroup*)luaL_checkudata(L, 1, "iputils.nmgroup");
+  nm->addMask(luaL_checkstring(L, 2));
+  return 0;
+}
+
+
+static int l_nmgroup_gc(lua_State* L)
+{
+  NetmaskGroup* nm = (NetmaskGroup*)luaL_checkudata(L, 1, "iputils.nmgroup");
+  nm->~NetmaskGroup();
+  return 0;
+}
+
+static const struct luaL_Reg iputils_nmgroup_methods[]={
+    {"__tostring", l_nmgroup_tostring},
+    {"match", l_nmgroup_match},
+    {"add", l_nmgroup_add},
+    {"__gc", l_nmgroup_gc},
+    {NULL, NULL}
+};
+
+////////////
+
+static const struct luaL_Reg iputils[]={
+    {"newca", l_new_ca},
+    {"newipset", l_newipset},
+    {"newnm", l_new_netmask},
+    {"newnmgroup", l_new_nmgroup},
+    {NULL, NULL}
+};
+
+
+extern "C" int luaopen_iputils(lua_State* L)
+{
+  luaL_newmetatable(L, "iputils.ca");
+  lua_pushvalue(L, -1);
+  lua_setfield(L, -2, "__index");
+  luaL_setfuncs(L, iputils_ca_methods, 0);
+
+  luaL_newmetatable(L, "iputils.ipset");
+  lua_pushvalue(L, -1);
+  lua_setfield(L, -2, "__index");
+  luaL_setfuncs(L, ipset_methods, 0);
+
+  luaL_newmetatable(L, "iputils.netmask");
+  lua_pushvalue(L, -1);
+  lua_setfield(L, -2, "__index");
+  luaL_setfuncs(L, iputils_netmask_methods, 0);
+
+  luaL_newmetatable(L, "iputils.nmgroup");
+  lua_pushvalue(L, -1);
+  lua_setfield(L, -2, "__index");
+  luaL_setfuncs(L, iputils_nmgroup_methods, 0);
+
+#if LUA_VERSION_NUM < 502
+  luaL_register(L, "iputils", iputils);
+#else
+  luaL_newlib(L, iputils);
+#endif
+  return 1;
+}
+
+#if 0
+int makeIPv6sockaddr(const std::string& addr, struct sockaddr_in6* ret)
+{
+  if(addr.empty())
+    return -1;
+  string ourAddr(addr);
+  int port = -1;
+  if(addr[0]=='[') { // [::]:53 style address
+    string::size_type pos = addr.find(']');
+    if(pos == string::npos || pos + 2 > addr.size() || addr[pos+1]!=':')
+      return -1;
+    ourAddr.assign(addr.c_str() + 1, pos-1);
+    port = atoi(addr.c_str()+pos+2);  
+  }
+  ret->sin6_scope_id=0;
+  ret->sin6_family=AF_INET6;
+  if(inet_pton(AF_INET6, ourAddr.c_str(), (void*)&ret->sin6_addr) != 1) {
+    struct addrinfo* res;
+    struct addrinfo hints;
+    memset(&hints, 0, sizeof(hints));
+    
+    hints.ai_family = AF_INET6;
+    hints.ai_flags = AI_NUMERICHOST;
+    
+    int error;
+    if((error=getaddrinfo(ourAddr.c_str(), 0, &hints, &res))) { // this is correct
+      return -1;
+    }
+  
+    memcpy(ret, res->ai_addr, res->ai_addrlen);
+    freeaddrinfo(res);
+  }
+
+  if(port >= 0)
+    ret->sin6_port = htons(port);
+
+  return 0;
+}
+
+int makeIPv4sockaddr(const std::string& str, struct sockaddr_in* ret)
+{
+  if(str.empty()) {
+    return -1;
+  }
+  struct in_addr inp;
+  
+  string::size_type pos = str.find(':');
+  if(pos == string::npos) { // no port specified, not touching the port
+    if(inet_aton(str.c_str(), &inp)) {
+      ret->sin_addr.s_addr=inp.s_addr;
+      return 0;
+    }
+    return -1;
+  }
+  if(!*(str.c_str() + pos + 1)) // trailing :
+    return -1; 
+    
+  char *eptr = (char*)str.c_str() + str.size();
+  int port = strtol(str.c_str() + pos + 1, &eptr, 10);
+  if(*eptr)
+    return -1;
+  
+  ret->sin_port = htons(port);
+  if(inet_aton(str.substr(0, pos).c_str(), &inp)) {
+    ret->sin_addr.s_addr=inp.s_addr;
+    return 0;
+  }
+  return -1;
+}
+
+
+pair<string, string> splitField(const string& inp, char sepa)
+{
+  pair<string, string> ret;
+  string::size_type cpos=inp.find(sepa);
+  if(cpos==string::npos)
+    ret.first=inp;
+  else {
+    ret.first=inp.substr(0, cpos);
+    ret.second=inp.substr(cpos+1);
+  }
+  return ret;
+}
+
+#endif
index 25e9348b8b6cbcce6221479fde2fc699dc4ad3b3..4dbde69c2a935528b27feaac232eb611bf93ebef 100644 (file)
@@ -278,6 +278,13 @@ PowerDNSLua::PowerDNSLua(const std::string& fname)
 {
   d_lua = luaL_newstate();
 
+  // create module iputils & load it
+#if LUA_VERSION_NUM < 502
+  luaopen_iputils(d_lua);
+#else
+  luaL_requiref(d_lua, "iputils", luaopen_iputils, 1);
+#endif
+
   lua_pushcfunction(d_lua, netmaskMatchLua);
   lua_setglobal(d_lua, "matchnetmask");
 
index 934d02aacb63061713a99dd9fa94a45ce7491edf..bdc0ed42cca551fbbdbf685020d7b07b068cf330 100644 (file)
@@ -37,4 +37,5 @@ void popResourceRecordsTable(lua_State *lua, const string &query, vector<DNSReso
 void pushSyslogSecurityLevelTable(lua_State *lua);
 int getLuaTableLength(lua_State* lua, int depth);
 void luaStackDump (lua_State *L);
+extern "C" int luaopen_iputils(lua_State*);
 #endif
index 4ac6bdd99b1d0ead334a9d07f2645913b3d81ddd..76c1760d54ae1ff0ba11f563c7702d85a03e7b3f 100644 (file)
@@ -169,7 +169,15 @@ bool RecursorLua::passthrough(const string& func, const ComboAddress& remote, co
   
   d_local = local; 
   /* the first argument */
-  lua_pushstring(d_lua,  remote.toString().c_str() );
+  if(strcmp(func.c_str(),"prequery"))
+    lua_pushstring(d_lua,  remote.toString().c_str() );
+  else {
+    ComboAddress* ca=(ComboAddress*)lua_newuserdata(d_lua, sizeof(ComboAddress)); 
+    *ca=remote;
+    luaL_getmetatable(d_lua, "iputils.ca");
+    lua_setmetatable(d_lua, -2);
+  }
+
   lua_pushstring(d_lua,  query.c_str() );
   lua_pushnumber(d_lua,  qtype.getCode() );