throw runtime_error("Lua support disabled");
}
-bool PowerDNSLua::nxdomain(const ComboAddress& remote,const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res)
+bool PowerDNSLua::nxdomain(const ComboAddress& remote,const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
{
return false;
}
-bool PowerDNSLua::preresolve(const ComboAddress& remote, const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res)
+bool PowerDNSLua::preresolve(const ComboAddress& remote, const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
{
return false;
}
return 1;
}
+// called by lua to indicate that this answer is 'variable' and should not be cached
+int setVariableLua(lua_State* lua)
+{
+ lua_getfield(lua, LUA_REGISTRYINDEX, "__PowerDNSLua");
+ PowerDNSLua* pl = (PowerDNSLua*)lua_touserdata(lua, -1);
+ pl->setVariable();
+ return 0;
+}
+
int logLua(lua_State *lua)
{
if(lua_gettop(lua) >= 1) {
lua_pushcfunction(d_lua, logLua);
lua_setglobal(d_lua, "pdnslog");
+ lua_pushcfunction(d_lua, setVariableLua);
+ lua_setglobal(d_lua, "setvariable");
+
+
lua_pushcfunction(d_lua, getLocalAddressLua);
lua_setglobal(d_lua, "getlocaladdress");
lua_setfield(d_lua, LUA_REGISTRYINDEX, "__PowerDNSLua");
}
-bool PowerDNSLua::nxdomain(const ComboAddress& remote, const ComboAddress& local,const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res)
+bool PowerDNSLua::nxdomain(const ComboAddress& remote, const ComboAddress& local,const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
{
- return passthrough("nxdomain", remote, local, query, qtype, ret, res);
+ return passthrough("nxdomain", remote, local, query, qtype, ret, res, variable);
}
-bool PowerDNSLua::preresolve(const ComboAddress& remote, const ComboAddress& local,const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res)
+bool PowerDNSLua::preresolve(const ComboAddress& remote, const ComboAddress& local,const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable)
{
- return passthrough("preresolve", remote, local, query, qtype, ret, res);
+ return passthrough("preresolve", remote, local, query, qtype, ret, res, variable);
}
bool PowerDNSLua::getFromTable(const std::string& key, std::string& value)
}
-bool PowerDNSLua::passthrough(const string& func, const ComboAddress& remote, const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res)
+bool PowerDNSLua::passthrough(const string& func, const ComboAddress& remote, const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret,
+ int& res, bool* variable)
{
+ d_variable = false;
lua_getglobal(d_lua, func.c_str());
if(!lua_isfunction(d_lua, -1)) {
// cerr<<"No such function '"<<func<<"'\n";
return false;
}
- d_local = local;
+ d_local = local;
/* the first argument */
lua_pushstring(d_lua, remote.toString().c_str() );
lua_pushstring(d_lua, query.c_str() );
throw runtime_error(error);
return false;
}
+
+ *variable |= d_variable;
+
int newres = (int)lua_tonumber(d_lua, 1); // new rcode
if(newres < 0) {
// cerr << "handler did not handle"<<endl;
explicit PowerDNSLua(const std::string& fname);
~PowerDNSLua();
void reload();
- bool preresolve(const ComboAddress& remote,const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret);
- bool nxdomain(const ComboAddress& remote, const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret);
+ bool preresolve(const ComboAddress& remote,const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret, bool* variable);
+ bool nxdomain(const ComboAddress& remote, const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& res, int& ret, bool* variable);
ComboAddress getLocal()
{
return d_local;
}
+
+ void setVariable()
+ {
+ d_variable=true;
+ }
+
private:
lua_State* d_lua;
- bool passthrough(const string& func, const ComboAddress& remote,const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res);
+ bool passthrough(const string& func, const ComboAddress& remote,const ComboAddress& local, const string& query, const QType& qtype, vector<DNSResourceRecord>& ret, int& res, bool* variable);
bool getFromTable(const std::string& key, std::string& value);
bool getFromTable(const std::string& key, uint32_t& value);
bool d_failed;
-
+ bool d_variable;
ComboAddress d_local;
};
int res;
- if(!t_pdl->get() || !(*t_pdl)->preresolve(dc->d_remote, g_listenSocketsAddresses[dc->d_socket], dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res)) {
+ bool variableAnswer = false;
+ if(!t_pdl->get() || !(*t_pdl)->preresolve(dc->d_remote, g_listenSocketsAddresses[dc->d_socket], dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res, &variableAnswer)) {
res = sr.beginResolve(dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), dc->d_mdp.d_qclass, ret);
if(t_pdl->get()) {
if(res == RCode::NXDomain)
- (*t_pdl)->nxdomain(dc->d_remote, g_listenSocketsAddresses[dc->d_socket], dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res);
+ (*t_pdl)->nxdomain(dc->d_remote, g_listenSocketsAddresses[dc->d_socket], dc->d_mdp.d_qname, QType(dc->d_mdp.d_qtype), ret, res, &variableAnswer);
}
}
+
uint32_t minTTL=numeric_limits<uint32_t>::max();
if(res<0) {
pw.getHeader()->rcode=RCode::ServFail;
sendit:;
if(!dc->d_tcp) {
sendto(dc->d_socket, (const char*)&*packet.begin(), packet.size(), 0, (struct sockaddr *)(&dc->d_remote), dc->d_remote.getSocklen());
- if(!SyncRes::s_nopacketcache) {
+ if(!SyncRes::s_nopacketcache && !variableAnswer ) {
t_packetCache->insertResponsePacket(string((const char*)&*packet.begin(), packet.size()), g_now.tv_sec,
min(minTTL,
- pw.getHeader()->rcode == RCode::ServFail ? SyncRes::s_packetcacheservfailttl : SyncRes::s_packetcachettl
- )
+ (pw.getHeader()->rcode == RCode::ServFail) ? SyncRes::s_packetcacheservfailttl : SyncRes::s_packetcachettl
+ )
);
}
}
}
g_stats.unexpectedCount++; // if we made it here, it really is an unexpected answer
if(g_logCommonErrors)
- L<<Logger::Warning<<"Discarding unexpected packet from "<<fromaddr.toString()<<": "<<pident.domain<<", "<<pident.type<<endl;
+ L<<Logger::Warning<<"Discarding unexpected packet from "<<fromaddr.toStringWithPort()<<": "<<pident.domain<<", "<<pident.type<<endl;
}
else if(fd >= 0) {
t_udpclientsocks->returnSocket(fd);