root/trunk/pdns/pdns/lua-pdns-recursor.cc @ 1472

Revision 1472, 6.0 KB (checked in by ahu, 3 years ago)

and the final bit of whitespace/tab cleanup

Line 
1#include "lua-pdns-recursor.hh"
2
3#if !defined(PDNS_ENABLE_LUA) && !defined(LIBDIR)
4
5// stub implementation
6
7PowerDNSLua::PowerDNSLua(const std::string& fname)
8{
9  throw runtime_error("Lua support disabled");
10}
11
12bool PowerDNSLua::nxdomain(const ComboAddress& remote,const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res)
13{
14  return false;
15}
16
17bool PowerDNSLua::preresolve(const ComboAddress& remote, const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res)
18{
19  return false;
20}
21
22PowerDNSLua::~PowerDNSLua()
23{
24
25}
26
27#else
28
29extern "C" {
30#undef L
31/* Include the Lua API header files. */
32#include <lua.h>
33#include <lauxlib.h>
34#include <lualib.h>
35}
36
37#include <stdlib.h>
38#include <stdio.h>
39#include <string>
40#include <vector>
41#include <stdexcept>
42#include "logger.hh"
43using namespace std;
44
45bool netmaskMatchTable(lua_State* lua, const std::string& ip)
46{
47  lua_pushnil(lua);  /* first key */
48  while (lua_next(lua, 2) != 0) {
49    string netmask=lua_tostring(lua, -1);
50    Netmask nm(netmask);
51    ComboAddress ca(ip);
52    lua_pop(lua, 1);
53   
54    if(nm.match(ip)) 
55      return true;
56  }
57  return false;
58}
59
60extern "C" {
61
62int netmaskMatchLua(lua_State *lua)
63{
64  bool result=false;
65  if(lua_gettop(lua) >= 2) {
66    string ip=lua_tostring(lua, 1);
67    if(lua_istable(lua, 2)) {
68      result = netmaskMatchTable(lua, ip);
69    }
70    else {
71      for(int n=2 ; n <= lua_gettop(lua); ++n) { 
72        string netmask=lua_tostring(lua, n);
73        Netmask nm(netmask);
74        ComboAddress ca(ip);
75       
76        result = nm.match(ip);
77        if(result)
78          break;
79      }
80    }
81  }
82 
83  lua_pushboolean(lua, result);
84  return 1;
85}
86
87int logLua(lua_State *lua)
88{
89  if(lua_gettop(lua) >= 1) {
90    string message=lua_tostring(lua, 1);
91    theL()<<Logger::Error<<"From Lua script: "<<message<<endl;
92  }
93  return 0;
94}
95}
96
97PowerDNSLua::PowerDNSLua(const std::string& fname)
98{
99  d_lua = lua_open();
100
101#ifndef LUA_VERSION_NUM
102  luaopen_base(d_lua);
103  luaopen_string(d_lua);
104
105  if(lua_dofile(d_lua,  fname.c_str())) 
106#else
107  luaL_openlibs(d_lua);
108  if(luaL_dofile(d_lua,  fname.c_str())) 
109#endif
110    throw runtime_error(string("Error loading LUA file '")+fname+"': "+ string(lua_isstring(d_lua, -1) ? lua_tostring(d_lua, -1) : "unknown error"));
111
112  lua_settop(d_lua, 0);
113 
114  lua_pushcfunction(d_lua, netmaskMatchLua);
115  lua_setglobal(d_lua, "matchnetmask");
116
117  lua_pushcfunction(d_lua, logLua);
118  lua_setglobal(d_lua, "pdnslog");
119
120  lua_newtable(d_lua);
121
122  for(vector<QType::namenum>::const_iterator iter = QType::names.begin(); iter != QType::names.end(); ++iter) {
123    lua_pushnumber(d_lua, iter->second);
124    lua_setfield(d_lua, -2, iter->first.c_str());
125  }
126  lua_pushnumber(d_lua, 3);
127  lua_setfield(d_lua, -2, "NXDOMAIN");
128  lua_setglobal(d_lua, "pdns");
129}
130
131bool PowerDNSLua::nxdomain(const ComboAddress& remote, const ComboAddress& local,const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res)
132{
133  return passthrough("nxdomain", remote, local, query, qtype, ret, res);
134}
135
136bool PowerDNSLua::preresolve(const ComboAddress& remote, const ComboAddress& local,const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res)
137{
138  return passthrough("preresolve", remote, local, query, qtype, ret, res);
139}
140
141bool PowerDNSLua::getFromTable(const std::string& key, std::string& value)
142{
143  lua_pushstring(d_lua, key.c_str()); // 4 is now '1'
144  lua_gettable(d_lua, -2);  // replace by the first entry of our table we hope
145
146  bool ret=false;
147  if(!lua_isnil(d_lua, -1)) {
148    value = lua_tostring(d_lua, -1);
149    ret=true;
150  }
151  lua_pop(d_lua, 1);
152  return ret;
153}
154
155
156bool PowerDNSLua::getFromTable(const std::string& key, uint32_t& value)
157{
158  lua_pushstring(d_lua, key.c_str()); // 4 is now '1'
159  lua_gettable(d_lua, -2);  // replace by the first entry of our table we hope
160
161  bool ret=false;
162  if(!lua_isnil(d_lua, -1)) {
163    value = (uint32_t)lua_tonumber(d_lua, -1);
164    ret=true;
165  }
166  lua_pop(d_lua, 1);
167  return ret;
168}
169
170
171bool PowerDNSLua::passthrough(const string& func, const ComboAddress& remote, const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res)
172{
173  lua_getglobal(d_lua,  func.c_str());
174  if(!lua_isfunction(d_lua, -1)) {
175    //  cerr<<"No such function '"<<func<<"'\n";
176    lua_pop(d_lua, 1);
177    return false;
178  }
179  /* the first argument */
180  lua_pushstring(d_lua,  remote.toString().c_str() );
181  lua_pushstring(d_lua,  local.toString().c_str() );
182  lua_pushstring(d_lua,  query.c_str() );
183  lua_pushnumber(d_lua,  qtype.getCode() );
184
185  if(lua_pcall(d_lua,  4, 2, 0)) { // error
186    string error=string("lua error in '"+func+"': ")+lua_tostring(d_lua, -1);
187    lua_pop(d_lua, 1);
188    throw runtime_error(error);
189    return false;
190  }
191  int newres = (int)lua_tonumber(d_lua, 1); // new rcode
192  if(newres < 0) {
193    //    cerr << "handler did not handle"<<endl;
194    lua_pop(d_lua, 2);
195    return false;
196  }
197  res=newres;
198
199  /* get the result */
200  DNSResourceRecord rr;
201  rr.qname = query;
202  rr.d_place = DNSResourceRecord::ANSWER;
203  rr.ttl = 3600;
204
205  ret.clear();
206
207  /*           1       2   3   4   */
208  /* stack:  boolean table key row */
209
210#ifndef LUA_VERSION_NUM
211  int tableLen = luaL_getn(d_lua, 2);
212#else
213  int tableLen = lua_objlen(d_lua, 2);
214#endif
215
216  for(int n=1; n < tableLen + 1; ++n) {
217    lua_pushnumber(d_lua, n);
218    lua_gettable(d_lua, 2);
219
220    uint32_t tmpnum;
221    if(!getFromTable("qtype", tmpnum)) 
222      rr.qtype=QType::A;
223    else
224      rr.qtype=tmpnum;
225
226    getFromTable("content", rr.content);
227    if(!getFromTable("ttl", rr.ttl))
228      rr.ttl=3600;
229
230    if(!getFromTable("qname", rr.qname))
231      rr.qname = query;
232
233    if(!getFromTable("place", tmpnum))
234      rr.d_place = DNSResourceRecord::ANSWER;
235    else
236      rr.d_place = (DNSResourceRecord::Place) tmpnum;
237
238    /* removes 'value'; keeps 'key' for next iteration */
239    lua_pop(d_lua, 1); // table
240
241    //    cerr<<"Adding content '"<<rr.content<<"' with place "<<(int)rr.d_place<<" \n";
242    ret.push_back(rr);
243  }
244
245  lua_pop(d_lua, 2);
246
247  return true;
248}
249
250PowerDNSLua::~PowerDNSLua()
251{
252  lua_close(d_lua);
253}
254#endif
Note: See TracBrowser for help on using the browser.