]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
parse whole config before daemonize now, which means we can complain to the operator
authorbert hubert <bert.hubert@netherlabs.nl>
Thu, 5 Mar 2015 11:54:12 +0000 (12:54 +0100)
committerbert hubert <bert.hubert@netherlabs.nl>
Thu, 5 Mar 2015 11:54:12 +0000 (12:54 +0100)
fix traffic ending up in pools where it did not belong

pdns/dnsdist-lua.cc
pdns/dnsdist.cc
pdns/dnsdist.hh
pdns/dnsdistconf.lua

index d2220ece4d1cc6f2c29f9bd52720b424f797c128..c036e8f50a1e72dea7aceee4fa3f1fde01b70f34 100644 (file)
@@ -7,25 +7,39 @@
 
 using std::thread;
 
-void setupLua(bool client)
+static vector<std::function<void(void)>>* g_launchWork;
+
+vector<std::function<void(void)>> setupLua(bool client)
 {
+  g_launchWork= new vector<std::function<void(void)>>();
   g_lua.writeFunction("newServer", 
-                     [](boost::variant<string,std::unordered_map<std::string, std::string>> pvars, boost::optional<int> qps)
+                     [client](boost::variant<string,std::unordered_map<std::string, std::string>> pvars, boost::optional<int> qps)
                      { 
+                       if(client) {
+                         return shared_ptr<DownstreamState>();
+                       }
                        if(auto address = boost::get<string>(&pvars)) {
                          auto ret=std::make_shared<DownstreamState>(ComboAddress(*address, 53));
-                         ret->tid = move(thread(responderThread, ret));
+
                          if(qps) {
                            ret->qps=QPSLimiter(*qps, *qps);
                          }
                          g_dstates.push_back(ret);
+
+                         if(g_launchWork) {
+                           g_launchWork->push_back([ret]() {
+                               ret->tid = move(thread(responderThread, ret));
+                             });
+                         }
+                         else {
+                           ret->tid = move(thread(responderThread, ret));
+                         }
+
                          return ret;
                        }
                        auto vars=boost::get<std::unordered_map<std::string, std::string>>(pvars);
                        auto ret=std::make_shared<DownstreamState>(ComboAddress(vars["address"], 53));
-
-                       ret->tid = move(thread(responderThread, ret));
-
+                       
                        if(vars.count("qps")) {
                          ret->qps=QPSLimiter(boost::lexical_cast<int>(vars["qps"]),boost::lexical_cast<int>(vars["qps"]));
                        }
@@ -42,6 +56,14 @@ void setupLua(bool client)
                          ret->weight=boost::lexical_cast<int>(vars["weight"]);
                        }
 
+                       if(g_launchWork) {
+                         g_launchWork->push_back([ret]() {
+                             ret->tid = move(thread(responderThread, ret));
+                           });
+                       }
+                       else {
+                         ret->tid = move(thread(responderThread, ret));
+                       }
 
                        g_dstates.push_back(ret);
                        std::stable_sort(g_dstates.begin(), g_dstates.end(), [](const decltype(ret)& a, const decltype(ret)& b) {
@@ -86,6 +108,18 @@ void setupLua(bool client)
   g_lua.writeFunction("addACL", [](const std::string& domain) {
       g_ACL.addMask(domain);
     });
+
+  g_lua.writeFunction("addLocal", [client](const std::string& addr) {
+      if(client)
+       return;
+      try {
+       ComboAddress loc(addr, 53);
+       g_locals.push_back(loc);
+      }
+      catch(std::exception& e) {
+       g_outputBuffer="Error: "+string(e.what())+"\n";
+      }
+    });
   g_lua.writeFunction("setACL", [](const vector<pair<int, string>>& parts) {
     NetmaskGroup nmg;
     for(const auto& p : parts) {
@@ -285,11 +319,6 @@ void setupLua(bool client)
       dh.qr=v;
     });
 
-  std::ifstream ifs(g_vm["config"].as<string>());
-  if(!ifs) 
-    warnlog("Unable to read configuration from '%s'", g_vm["config"].as<string>());
-  else
-    infolog("Read configuration from '%s'", g_vm["config"].as<string>());
 
   g_lua.registerFunction("tostring", &ComboAddress::toString);
 
@@ -314,8 +343,15 @@ void setupLua(bool client)
        SSetsockopt(sock, SOL_SOCKET, SO_REUSEADDR, 1);
        SBind(sock, local);
        SListen(sock, 5);
-       thread t(controlThread, sock, local);
-       t.detach();
+       auto launch=[sock, local]() {
+           thread t(controlThread, sock, local);
+           t.detach();
+       };
+       if(g_launchWork) 
+         g_launchWork->push_back(launch);
+       else
+         launch();
+           
       }
       catch(std::exception& e) {
        errlog("Unable to bind to control socket on %s: %s", local.toStringWithPort(), e.what());
@@ -487,6 +523,12 @@ void setupLua(bool client)
        string encrypted = sodEncryptSym(testmsg, g_key, sn);
        string decrypted = sodDecryptSym(encrypted, g_key, sn2);
        
+       sn.increment();
+       sn2.increment();
+
+       encrypted = sodEncryptSym(testmsg, g_key, sn);
+       decrypted = sodDecryptSym(encrypted, g_key, sn2);
+
        if(testmsg == decrypted)
         g_outputBuffer="Everything is ok!\n";
        else
@@ -498,6 +540,15 @@ void setupLua(bool client)
      }});
 
   
+  std::ifstream ifs(g_vm["config"].as<string>());
+  if(!ifs) 
+    warnlog("Unable to read configuration from '%s'", g_vm["config"].as<string>());
+  else
+    infolog("Read configuration from '%s'", g_vm["config"].as<string>());
 
   g_lua.executeCode(ifs);
+  auto ret=*g_launchWork;
+  delete g_launchWork;
+  g_launchWork=0;
+  return ret;
 }
index 07d7560f5897be6457bbce199f911718680177a2..9e2610381bde9d5a8a2e16c4195cf659b6fe6b1e 100644 (file)
    We neglect to do recvfromto() on 0.0.0.0
    Receiver is currently singlethreaded (not that bad actually)
    We can't compile w/o crypto
-   our naming is as inconsistent as only ahu can make it
    lack of help()
    we offer now way to log from Lua
-   our startup fails *after* fork on most cases, which is not overly helpful
 */
 
 ArgvMap& arg()
@@ -72,7 +70,7 @@ uint16_t g_maxOutstanding;
 bool g_console;
 NetmaskGroup g_ACL;
 string g_outputBuffer;
-
+vector<ComboAddress> g_locals;
 
 /* UDP: the grand design. Per socket we listen on for incoming queries there is one thread.
    Then we have a bunch of connected sockets for talking to downstream servers. 
@@ -268,12 +266,9 @@ ComboAddress g_serverControl{"127.0.0.1:5199"};
 
 servers_t getDownstreamCandidates(const std::string& pool)
 {
-  if(pool.empty())
-    return g_dstates;
-  
   servers_t ret;
   for(auto& s : g_dstates) 
-    if(s->pools.count(pool))
+    if((pool.empty() && s->pools.empty()) || s->pools.count(pool))
       ret.push_back(s);
   
   return ret;
@@ -800,6 +795,22 @@ void doClient(ComboAddress server)
   writen2(fd, (const char*)ours.value, sizeof(ours.value));
   readn2(fd, (char*)theirs.value, sizeof(theirs.value));
 
+  if(g_vm.count("command")) {
+    auto command = g_vm["command"].as<string>();
+    string response;
+    string msg=sodEncryptSym(command, g_key, ours);
+    putMsgLen(fd, msg.length());
+    writen2(fd, msg);
+    uint16_t len;
+    getMsgLen(fd, &len);
+    char resp[len];
+    readn2(fd, resp, len);
+    msg.assign(resp, len);
+    msg=sodDecryptSym(msg, g_key, theirs);
+    cout<<msg<<endl;
+    return; 
+  }
+
   set<string> dupper;
   {
     ifstream history(".history");
@@ -917,6 +928,7 @@ try
     ("help,h", "produce help message")
     ("config", po::value<string>()->default_value("/etc/dnsdist.conf"), "Filename with our configuration")
     ("client", "be a client")
+    ("command,c", po::value<string>(), "Execute this command on a running dnsdist")
     ("daemon", po::value<bool>()->default_value(true), "run in background")
     ("local", po::value<vector<string> >(), "Listen on which addresses")
     ("max-outstanding", po::value<uint16_t>()->default_value(65535), "maximum outstanding queries per downstream")
@@ -947,11 +959,36 @@ try
   g_policy = leastOutstandingPol;
 
 
-  if(g_vm.count("client")) {
+  if(g_vm.count("client") || g_vm.count("command")) {
     setupLua(true);
     doClient(g_serverControl);
     exit(EXIT_SUCCESS);
   }
+
+  auto todo=setupLua(false);
+
+  if(g_vm.count("local")) {
+    g_locals.clear();
+    for(auto loc : g_vm["local"].as<vector<string> >())
+      g_locals.push_back(ComboAddress(loc, 53));
+  }
+  
+  if(g_locals.empty())
+    g_locals.push_back(ComboAddress("0.0.0.0", 53));
+  
+
+  vector<ClientState*> toLaunch;
+  for(const auto& local : g_locals) {
+    ClientState* cs = new ClientState;
+    cs->local= local;
+    cs->udpFD = SSocket(cs->local.sin4.sin_family, SOCK_DGRAM, 0);
+    if(cs->local.sin4.sin_family == AF_INET6) {
+      SSetsockopt(cs->udpFD, IPPROTO_IPV6, IPV6_V6ONLY, 1);
+    }
+    SBind(cs->udpFD, cs->local);    
+    toLaunch.push_back(cs);
+  }
+
   if(g_vm["daemon"].as<bool>())  {
     g_console=false;
     daemonize();
@@ -960,10 +997,13 @@ try
     vinfolog("Running in the foreground");
   }
 
+  for(auto& t : todo)
+    t();
+
   for(auto& addr : {"127.0.0.0/8", "10.0.0.0/8", "100.64.0.0/10", "169.254.0.0/16", "192.168.0.0/16", "172.16.0.0/12", "::1/128", "fc00::/7", "fe80::/10"})
     g_ACL.addMask(addr);
 
-  setupLua(false);
+
   if(g_vm.count("remotes")) {
     for(const auto& address : g_vm["remotes"].as<vector<string>>()) {
       auto ret=std::make_shared<DownstreamState>(ComboAddress(address, 53));
@@ -980,28 +1020,15 @@ try
     }
   }
 
-  vector<string> locals;
-  if(g_vm.count("local"))
-    locals = g_vm["local"].as<vector<string> >();
-  else
-    locals.push_back("::");
-
-  for(const string& local : locals) {
-    ClientState* cs = new ClientState;
-    cs->local= ComboAddress(local, 53);
-    cs->udpFD = SSocket(cs->local.sin4.sin_family, SOCK_DGRAM, 0);
-    if(cs->local.sin4.sin_family == AF_INET6) {
-      SSetsockopt(cs->udpFD, IPPROTO_IPV6, IPV6_V6ONLY, 1);
-    }
-    SBind(cs->udpFD, cs->local);    
 
+  for(auto& cs : toLaunch) {
     thread t1(udpClientThread, cs);
     t1.detach();
   }
 
-  for(const string& local : locals) {
+  for(const auto& local : g_locals) {
     ClientState* cs = new ClientState;
-    cs->local= ComboAddress(local, 53);
+    cs->local= local;
 
     cs->tcpFD = SSocket(cs->local.sin4.sin_family, SOCK_STREAM, 0);
 
index 7f410a0c934a9d6c0a1fc908fcf2441da52078d5..cd09f42e61333103f333ea69341f52c56a188d23 100644 (file)
@@ -200,7 +200,7 @@ extern LuaContext g_lua;
 extern ServerPolicy g_policy;
 extern servers_t g_dstates;
 extern std::string g_outputBuffer;
-
+extern std::vector<ComboAddress> g_locals;
 struct dnsheader;
 std::shared_ptr<DownstreamState> firstAvailable(const servers_t& servers, const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh);
 std::shared_ptr<DownstreamState> leastOutstanding(const servers_t& servers, const ComboAddress& remote, const DNSName& qname, uint16_t qtype, dnsheader* dh);
@@ -213,7 +213,8 @@ extern SuffixMatchNode g_suffixMatchNodeFilter;
 extern ComboAddress g_serverControl;
 void controlThread(int fd, ComboAddress local);
 extern NetmaskGroup g_ACL;
-void setupLua(bool client);
+
+vector<std::function<void(void)>> setupLua(bool client);
 extern std::string g_key;
 namespace po = boost::program_options;
 extern po::variables_map g_vm;
index 100f2de8584d0ced8d7ef72516539927c232c5ae..d77986e2f5b447f0989e79b0c530da3572a5a2b8 100644 (file)
@@ -1,4 +1,5 @@
 controlSocket("0.0.0.0")
+addLocal("0.0.0.0:5200")
 setKey("MXNeLFWHUe4363BBKrY06cAsH8NWNb+Se2eXU5+Bb74=")
 
 -- define the good servers