]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
interim commit that goes with https://gist.github.com/ahupowerdns/1e8bfbba95a277a4fac...
authorbert hubert <bert.hubert@netherlabs.nl>
Mon, 31 Oct 2016 23:06:43 +0000 (00:06 +0100)
committerbert hubert <bert.hubert@netherlabs.nl>
Sun, 19 Nov 2017 19:48:19 +0000 (20:48 +0100)
pdns/dnsrecords.cc
pdns/dnsrecords.hh
pdns/lua-auth4.cc
pdns/lua-auth4.hh
pdns/packethandler.cc

index fbd05a83563f938797d900d28c8f438a1a63be22..2feebc990a6771b98c7b507d18123d610433c925 100644 (file)
@@ -141,7 +141,7 @@ boilerplate_conv(DNAME, QType::DNAME, conv.xfrName(d_content));
 boilerplate_conv(MR, QType::MR, conv.xfrName(d_alias, true));
 boilerplate_conv(MINFO, QType::MINFO, conv.xfrName(d_rmailbx, true); conv.xfrName(d_emailbx, true));
 boilerplate_conv(TXT, QType::TXT, conv.xfrText(d_text, true));
-boilerplate_conv(LUA, QType::LUA, conv.xfrText(d_code, true));
+boilerplate_conv(LUA, QType::LUA, conv.xfrType(d_type); conv.xfrText(d_code, true));
 boilerplate_conv(ENT, 0, );
 boilerplate_conv(SPF, 99, conv.xfrText(d_text, true));
 boilerplate_conv(HINFO, QType::HINFO,  conv.xfrText(d_cpu);   conv.xfrText(d_host));
index fbaff717da5ef2e1cd6aedcd49006af1b264adf6..8e9ec7b0160fa194f620c39adb8e568fbbe96f6c 100644 (file)
@@ -190,6 +190,7 @@ class LUARecordContent : public DNSRecordContent
 public:
   includeboilerplate(LUA)
 
+  uint16_t d_type;
   string d_code;
 };
 
index 56d05389bc4575f9668cd8a212ce7cede8151725..e7912080c52c9557330a5527bc2bd70a44197167 100644 (file)
@@ -6,6 +6,8 @@
 #include "namespaces.hh"
 #include "ednssubnet.hh"
 #include <unordered_set>
+#include "sstuff.hh"
+#include <thread>
 
 #if !defined(HAVE_LUA)
 
@@ -283,8 +285,50 @@ bool AuthLua4::updatePolicy(const DNSName &qname, QType qtype, const DNSName &zo
 AuthLua4::~AuthLua4() { }
 
 
+class IsUpOracle
+{
+public:
+  bool isUp(const ComboAddress& remote);
+  
+  
+private:
+  void checkThread(const ComboAddress& rem) {
+    d_statuses[rem].second=false;
+    for(;;) {
+      try {
+        Socket s(rem.sin4.sin_family, SOCK_STREAM);
+        s.setNonBlocking();
+        s.connect(rem, 1);
+        if(!d_statuses[rem].second)
+          cout<<"Declaring "<<rem.toStringWithPort()<<" UP!"<<endl;
+        d_statuses[rem].second=true;
+      }
+      catch(NetworkError& ne) {
+        if(d_statuses[rem].second)
+          cout<<"Failed to connect to "<<rem.toStringWithPort()<<", setting DOWN"<<endl;
+        d_statuses[rem].second=false;
+      }
+      sleep(1);
+    }
+  }
+  map<ComboAddress, pair<std::thread*, bool>> d_statuses;
+};
+
+bool IsUpOracle::isUp(const ComboAddress& remote)
+{
+  auto iter = d_statuses.find(remote);
+  if(iter == d_statuses.end()) {
+    cout<<"First ever query for "<<remote.toStringWithPort()<<", launching checker"<<endl;
+    std::thread* checker = new std::thread(&IsUpOracle::checkThread, this, remote);
+    d_statuses[remote]={checker, false};
+    return false;
+  }
+  return iter->second.second;
+}
+
+IsUpOracle g_up;
 
-std::vector<shared_ptr<DNSRecordContent>> luaSynth(const std::string& code, uint16_t qtype) 
+std::vector<shared_ptr<DNSRecordContent>> luaSynth(const std::string& code, const DNSName& query, const ComboAddress& who, uint16_t qtype) 
 {
   std::vector<shared_ptr<DNSRecordContent>> ret;
   cout<<"Code: "<<code<<endl;
@@ -292,7 +336,52 @@ std::vector<shared_ptr<DNSRecordContent>> luaSynth(const std::string& code, uint
   strip.resize(strip.size()-1);
   
   LuaContext lua;
-  ret.push_back(std::shared_ptr<DNSRecordContent>(DNSRecordContent::mastermake(qtype, 1, lua.executeCode<string>("return "+strip))));
+  lua.writeVariable("qname", query.toString());
+  lua.writeVariable("who", who.toString());
+
+  lua.writeFunction("ifportup", [](int port, const vector<pair<int, string> >& ips) {
+      vector<ComboAddress> candidates;
+      for(const auto& i : ips) {
+        ComboAddress rem(i.second, port);
+        if(g_up.isUp(rem))
+          candidates.push_back(rem);
+      }
+      cout<<"Have "<<candidates.size()<<" candidate IP addresses: ";
+      for(const auto& c : candidates)
+        cout<<c.toString()<<" ";
+      cout<<endl;
+      if(candidates.empty()) {
+        cout<<"Picking a random one, everything is down. Should return all of them"<<endl;
+        return ips[random() % ips.size()].second;
+      }
+      return candidates[random() % candidates.size()].toString();
+    });
+  
+  lua.writeFunction("pickRandom", [](const vector<pair<int, string> >& ips) {
+      return ips[random()%ips.size()].second;
+    });
+
+  // wrandom({ {100, '1.2.3.4'}, {50, '5.4.3.2'}, {1, '192.168.1.0'}})"
+
+  lua.writeFunction("wrandom", [](std::unordered_map<int, std::unordered_map<int, string> > ips) {
+      int sum=0;
+      vector<pair<int, string> > pick;
+      for(auto& i : ips) {
+        sum += atoi(i.second[1].c_str());
+        pick.push_back({sum, i.second[2]});
+      }
+      int r = random() % sum;
+      auto p = upper_bound(pick.begin(), pick.end(),r, [](int r, const decltype(pick)::value_type& a) { return  r < a.first;});
+      return p->second;
+      
+    });
+
+  
+  string content=lua.executeCode<string>(strip);
+  if(qtype==QType::TXT)
+    content = '"'+content+'"';
+  
+  ret.push_back(std::shared_ptr<DNSRecordContent>(DNSRecordContent::mastermake(qtype, 1, content )));
 
   return ret;
 }
index fcdd545f80afcf042a7b4c7126ea696e32511be4..e7aec2fb1333e61d4f8c53fbd9741b5944b94f4a 100644 (file)
@@ -42,4 +42,4 @@ private:
   luacall_update_policy_t d_update_policy;
   luacall_axfr_filter_t d_axfr_filter;
 };
-std::vector<shared_ptr<DNSRecordContent>> luaSynth(const std::string& code, uint16_t qtype);
+std::vector<shared_ptr<DNSRecordContent>> luaSynth(const std::string& code, const DNSName& qname, const ComboAddress& who, uint16_t qtype);
index e50247d2578247264ba46a02e092409b5245cf20..0ba3e64a2d6339551c5efa8e7d2306ff30807568 100644 (file)
@@ -1284,10 +1284,12 @@ DNSPacket *PacketHandler::doQuestion(DNSPacket *p)
     
     while(B.get(rr)) {
       if(rr.dr.d_type == QType::LUA) {
-        cerr<<"We got LUA: "<<endl;
-        auto recvec=luaSynth(getRR<LUARecordContent>(rr.dr)->d_code, p->qtype.getCode());
+        auto rec=getRR<LUARecordContent>(rr.dr);
+        if(rec->d_type != p->qtype.getCode())
+          continue;
+        
+        auto recvec=luaSynth(rec->d_code, target, p->getRemote(), p->qtype.getCode());
         if(!recvec.empty()) {
-          cerr<<"We got answers from Lua"<<endl;
           for(const auto& r : recvec) {
             rr.dr.d_type = p->qtype.getCode();
             rr.dr.d_content = r;