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"]));
}
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) {
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) {
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);
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());
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
}});
+ 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;
}
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()
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.
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;
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");
("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")
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();
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));
}
}
- 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);
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);
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;
controlSocket("0.0.0.0")
+addLocal("0.0.0.0:5200")
setKey("MXNeLFWHUe4363BBKrY06cAsH8NWNb+Se2eXU5+Bb74=")
-- define the good servers