dnstcpbench \
dnswasher \
dumresp \
+ kvresp \
notify \
nproxy \
nsec3dig \
unix_utility.cc \
qtype.cc
+kvresp_SOURCES = \
+ dnslabeltext.cc dnsname.cc dnsname.hh \
+ kvresp.cc \
+ logger.cc \
+ misc.cc misc.hh \
+ statbag.cc \
+ unix_utility.cc \
+ qtype.cc
saxfr_SOURCES = \
base32.cc \
if(len < 0)
unixDie("recvfrom");
cout<<"Had packet: "<<string(buffer, len)<<endl;
- /*
if(dh->qr)
continue;
dh->qr=1;
dh->ad=0;
- */
if(sendto(s.getHandle(), buffer, len, 0, (struct sockaddr*)&rem, socklen) < 0)
unixDie("sendto");
--- /dev/null
+
+--[[
+This implements a two-step domain filtering solution where the status of an IP address
+and a domain name need to be looked up.
+To do so, we use the udpQuestionResponse answers which generically allows us to do asynchronous
+lookups via UDP.
+Such lookups can be slow, they won't block PowerDNS while we wait for them.
+
+To benefit from this hook, return: "udpQueryResponse", UDP-server, data
+from preresolve (or other hooks).
+The 'data' third return value should be a table with the query in there, plus the callback
+that needs to be called once the data is in.
+
+We'll add more parameters, like 'timeout' and perhaps 'protocol' as we improve this feature
+over time.
+--]]
+
+function preresolve ( remoteip, domain, qtype )
+ print ("preresolve handler called for: "..remoteip.. ", local: ".. getlocaladdress()..", ".. domain..", ".. qtype)
+ return "udpQueryResponse", "127.0.0.1:5555", {query="IP "..remoteip, callback="getipdetails"}
+end
+
+function getipdetails(remoteip, domain, qtype, data)
+ print("In getipdetails, got ".. data.response.. " from '"..remoteip.."', for '"..remoteip.."'")
+ data.ipstatus=data.response
+ data.query="DOMAIN "..domain
+ data.callback="getdomaindetails"
+ return "udpQueryResponse", "127.0.0.1:5555", data
+end
+
+function getdomaindetails(remoteip, domain, qtype, data)
+ print("In getipdetails, got ".. data.response.. " from '"..remoteip.."', for '"..domain.."'")
+ print("So status of domain is "..data.response.." and status of IP is "..data.ipstatus)
+ if(data.ipstatus=="1" and data.response=="1")
+ then
+ print("IP wants filtering and domain is of the filtered kind")
+ return 0,{{qtype=pdns.CNAME, content="www.blocked.com", ttl=3602},
+ {qname="www.webserver.com", qtype=pdns.A, content="1.2.3.4", ttl=3602}}
+ else
+ return pdns.PASS, {}
+ end
+end
+
+
+
--- /dev/null
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "iputils.hh"
+#include "sstuff.hh"
+#include "statbag.hh"
+
+StatBag S;
+
+int main(int argc, char** argv)
+try
+{
+ if(argc != 3) {
+ cerr<<"Syntax: dumresp local-address local-port"<<endl;
+ exit(EXIT_FAILURE);
+ }
+
+ ComboAddress local(argv[1], atoi(argv[2]));
+ Socket s(local.sin4.sin_family, SOCK_DGRAM);
+
+ s.bind(local);
+ cout<<"Bound to "<<local.toStringWithPort()<<endl;
+
+ char buffer[1500];
+
+ int len;
+ ComboAddress rem=local;
+ socklen_t socklen = rem.getSocklen();
+ for(;;) {
+ len=recvfrom(s.getHandle(), buffer, sizeof(buffer), 0, (struct sockaddr*)&rem, &socklen);
+ if(len < 0)
+ unixDie("recvfrom");
+ string query(buffer, len);
+ cout<<"Had packet: "<<query<<endl;
+ vector<string> parts;
+ stringtok(parts, query);
+ if(parts.size()<2)
+ continue;
+ string response;
+ if(parts[0]=="DOMAIN")
+ response= (parts[1].find("xxx") != string::npos) ? "1" : "0";
+ else if(parts[0]=="IP")
+ response= (parts[1]=="127.0.0.1") ? "1" : "0";
+ else
+ response= "???";
+
+ cout<<"Our reply: "<<response<<endl;
+ if(sendto(s.getHandle(), response.c_str(), response.length(), 0, (struct sockaddr*)&rem, socklen) < 0)
+ unixDie("sendto");
+ }
+}
+catch(std::exception& e)
+{
+ cerr<<"Fatal error: "<<e.what()<<endl;
+ exit(EXIT_FAILURE);
+}
return newres != -1;
}
-static bool getFromTable(lua_State *lua, const std::string &key, lua_CFunction& value)
-{
- lua_pushstring(lua, key.c_str()); // 4 is now '1'
- lua_gettable(lua, -2); // replace by the first entry of our table we hope
-
- bool ret=false;
-
- if(lua_isfunction(lua, -1)) {
- value = lua_tocfunction(lua, -1);
- ret=true;
- }
- lua_pop(lua, 1);
- return ret;
-}
-
-
bool RecursorLua::passthrough(const string& func, const ComboAddress& remote, const ComboAddress& local, const DNSName& query, const QType& qtype, vector<DNSRecord>& ret,
int& res, bool* variable)
{
throw runtime_error(error);
return false;
}
-
+ loop:;
if(variable)
*variable |= d_variable;
string tocall = lua_tostring(d_lua,1);
lua_remove(d_lua, 1); // the name
ret.clear();
- cerr<<"tocall: "<<tocall<<endl;
- if(tocall == "udpQuestionResponse") {
-
+ if(tocall == "udpQueryResponse") {
string dest = lua_tostring(d_lua,1);
- cerr<<"dest: "<<dest<<endl;
string uquery;
getFromTable("query", uquery);
- lua_CFunction callback=0;
- cout<<"callback get:"<<::getFromTable(d_lua, "callback", callback)<<endl;
- cout<<"callback value: "<<(void*)callback<<endl;
- cerr<<"query: "<<query<<endl;
- // string followup = lua_tostring(d_lua, 3);
- // cerr<<"followup: "<<dest<<endl;
- lua_pop(d_lua, 3);
-
- string answer = udpQuestionResponse(ComboAddress(dest), uquery);
- cerr<<"Back in lua-recursor, got: '"<<answer<<"'"<<endl;
- lua_pushcfunction(d_lua, callback);
+ string callback;
+ getFromTable("callback", callback);
+
+ lua_remove(d_lua, -2);
+
+ // XXX THIS IS PLAIN WRONG - WE LEAVE STUFF ON THE LUA STACK AND EXPECT IT TO STILL BE HERE WHEN WE GET BACK!
+ string answer = GenUDPQueryResponse(ComboAddress(dest), uquery);
+
+ lua_getglobal(d_lua, callback.c_str());
+
lua_pushstring(d_lua, remote.toString().c_str() );
lua_pushstring(d_lua, query.toString().c_str() );
lua_pushnumber(d_lua, qtype.getCode() );
- lua_pushstring(d_lua, answer.c_str() );
- cerr<<"Going to call"<<endl;
+
+ lua_pushvalue(d_lua, -5);
+ lua_remove(d_lua, -6);
+
+ lua_pushstring(d_lua, answer.c_str());
+ lua_setfield(d_lua, -2, "response");
+
if(lua_pcall(d_lua, 4, 3, 0)) { // NOTE! Means we always get 3 stack entries back, no matter what our lua hook returned!
string error=string("lua error in '"+func+"' while callback for '"+query.toString()+"|"+qtype.getName()+": ")+lua_tostring(d_lua, -1);
lua_pop(d_lua, 1);
throw runtime_error(error);
return false;
}
- cerr<<"We called!"<<endl;
+ goto loop;
}
else if(tocall == "getFakeAAAARecords") {
string luaprefix = lua_tostring(d_lua, 2);
#include "dns.hh"
#include "iputils.hh"
#include "lua-pdns.hh"
-string udpQuestionResponse(const ComboAddress& dest, const string& query);
+string GenUDPQueryResponse(const ComboAddress& dest, const string& query);
class RecursorLua : public PowerDNSLua
{
public:
return ret;
}
-void handleUDPQueryResponse(int fd, FDMultiplexer::funcparam_t& var)
+void handleGenUDPQueryResponse(int fd, FDMultiplexer::funcparam_t& var)
{
- cerr<<"In handle UDPQueryResponse"<<endl;
- PacketID* pident=any_cast<PacketID>(&var);
+ PacketID pident=*any_cast<PacketID>(&var);
char resp[512];
int ret=recv(fd, resp, sizeof(resp), 0);
t_fdm->removeReadFD(fd);
if(ret >= 0) {
string data(resp, ret);
- cerr<<"Reporting what we got ('"<<data<<"')"<<endl;
- cerr<<"Reporting returned: "<<MT->sendEvent(*pident, &data)<<endl;
+ MT->sendEvent(pident, &data);
}
else {
- cerr<<"Had some kind of error: "<<ret<<endl;
+ string empty;
+ MT->sendEvent(pident, &empty);
+ // cerr<<"Had some kind of error: "<<ret<<", "<<strerror(errno)<<endl;
}
}
-string udpQuestionResponse(const ComboAddress& dest, const string& query)
+string GenUDPQueryResponse(const ComboAddress& dest, const string& query)
{
- cerr<<"In udpQuestionResponse"<<endl;
Socket s(dest.sin4.sin_family, SOCK_DGRAM);
s.setNonBlocking();
ComboAddress local = getQueryLocalAddress(dest.sin4.sin_family, 0);
s.bind(local);
s.connect(dest);
- cerr<<"here, query="<<query<<endl;
s.send(query);
PacketID pident;
pident.sock=&s;
pident.type=0;
- t_fdm->addReadFD(s.getHandle(), handleUDPQueryResponse, pident);
+ t_fdm->addReadFD(s.getHandle(), handleGenUDPQueryResponse, pident);
string data;
- cerr<<"Entering waitEvent in udpQuestionResponse"<<endl;
+
int ret=MT->waitEvent(pident,&data, g_networkTimeoutMsec);
- cerr<<"Got back: "<<data<<endl;
+
if(!ret || ret==-1) { // timeout
- cerr<<"Got back some kind of error, ret="<<ret<<endl;
t_fdm->removeReadFD(s.getHandle());
}
else if(data.empty()) {// error, EOF or other
-
+ // we could special case this
return data;
}
-
return data;
}
-
vector<ComboAddress> g_localQueryAddresses4, g_localQueryAddresses6;
const ComboAddress g_local4("0.0.0.0"), g_local6("::");