]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/rec-lua-conf.cc
WIP code for dnstap of cache misses
[thirdparty/pdns.git] / pdns / rec-lua-conf.cc
CommitLineData
6a99b9a4 1#include "config.h"
3e61e7f7 2#include "ext/luawrapper/include/LuaContext.hpp"
6a99b9a4 3
3e61e7f7 4#include <fstream>
ad42489c 5#include <thread>
3e61e7f7 6#include "namespaces.hh"
7#include "logger.hh"
f3c18728 8#include "rec-lua-conf.hh"
3e61e7f7 9#include "sortlist.hh"
ad42489c 10#include "filterpo.hh"
11#include "syncres.hh"
12#include "rpzloader.hh"
98c9ec39 13#include "base64.hh"
aa7929a3 14#include "remote_logger.hh"
52ad9eea 15#include "validate.hh"
e48c6b8a 16#include "validate-recursor.hh"
f2234140 17#include "root-dnssec.hh"
3e61e7f7 18
12ce523e 19GlobalStateHolder<LuaConfigItems> g_luaconfs;
f3c18728 20
21/* SO HOW DOES THIS WORK! AND PLEASE PAY ATTENTION!
22 This function can be called at any time. It is expected to overwrite all the contents
23 of LuaConfigItems, which is held in a GlobalStateHolder for RCU properties.
24
25 This function can be called again at a later date, so you must make sure that anything you
26 allow to be configured from here lives in g_luaconfs AND NOWHERE ELSE.
27
28 If someone loads an empty Lua file, the default LuaConfigItems struct MUST MAKE SENSE.
29
30 To make this easy on you, here is a LuaConfigItems constructor where you
31 can set sane defaults:
32*/
33
34LuaConfigItems::LuaConfigItems()
35{
03bf7abb 36 DNSName root("."); // don't use g_rootdnsname here, it might not exist yet
f2234140 37 for (const auto &dsRecord : rootDSs) {
32122aab 38 auto ds=std::dynamic_pointer_cast<DSRecordContent>(DSRecordContent::make(dsRecord));
03bf7abb 39 dsAnchors[root].insert(*ds);
f2234140 40 }
f3c18728 41}
42
ad42489c 43/* DID YOU READ THE STORY ABOVE? */
44
45template <typename C>
46typename C::value_type::second_type constGet(const C& c, const std::string& name)
47{
48 auto iter = c.find(name);
49 if(iter == c.end())
50 return 0;
51 return iter->second;
52}
53
d122dac0 54typedef std::unordered_map<std::string, boost::variant<bool, uint32_t, std::string > > rpzOptions_t;
6a99b9a4 55
d122dac0 56static void parseRPZParameters(rpzOptions_t& have, std::string& polName, boost::optional<DNSFilterEngine::Policy>& defpol, bool& defpolOverrideLocal, uint32_t& maxTTL, size_t& zoneSizeHint)
8f618901
RG
57{
58 if(have.count("policyName")) {
d122dac0 59 polName = boost::get<std::string>(have["policyName"]);
8f618901
RG
60 }
61 if(have.count("defpol")) {
62 defpol=DNSFilterEngine::Policy();
d122dac0 63 defpol->d_kind = (DNSFilterEngine::PolicyKind)boost::get<uint32_t>(have["defpol"]);
8f618901
RG
64 defpol->d_name = std::make_shared<std::string>(polName);
65 if(defpol->d_kind == DNSFilterEngine::PolicyKind::Custom) {
6da513b2 66 defpol->d_custom.push_back(DNSRecordContent::mastermake(QType::CNAME, QClass::IN,
d122dac0 67 boost::get<string>(have["defcontent"])));
8f618901
RG
68
69 if(have.count("defttl"))
d122dac0 70 defpol->d_ttl = static_cast<int32_t>(boost::get<uint32_t>(have["defttl"]));
8f618901
RG
71 else
72 defpol->d_ttl = -1; // get it from the zone
73 }
d122dac0
RG
74
75 if (have.count("defpolOverrideLocalData")) {
76 defpolOverrideLocal = boost::get<bool>(have["defpolOverrideLocalData"]);
77 }
8f618901
RG
78 }
79 if(have.count("maxTTL")) {
d122dac0 80 maxTTL = boost::get<uint32_t>(have["maxTTL"]);
8f618901
RG
81 }
82 if(have.count("zoneSizeHint")) {
d122dac0 83 zoneSizeHint = static_cast<size_t>(boost::get<uint32_t>(have["zoneSizeHint"]));
8f618901
RG
84 }
85}
86
abbf4bba 87#if HAVE_PROTOBUF
0bd2e252 88typedef std::unordered_map<std::string, boost::variant<bool, uint64_t, std::string, std::vector<std::pair<int,std::string> > > > protobufOptions_t;
f1c7929a
RG
89
90static void parseProtobufOptions(boost::optional<protobufOptions_t> vars, ProtobufExportConfig& config)
91{
92 if (!vars) {
93 return;
94 }
95
96 if (vars->count("timeout")) {
97 config.timeout = boost::get<uint64_t>((*vars)["timeout"]);
98 }
99
100 if (vars->count("maxQueuedEntries")) {
101 config.maxQueuedEntries = boost::get<uint64_t>((*vars)["maxQueuedEntries"]);
102 }
103
104 if (vars->count("reconnectWaitTime")) {
105 config.reconnectWaitTime = boost::get<uint64_t>((*vars)["reconnectWaitTime"]);
106 }
107
108 if (vars->count("asyncConnect")) {
109 config.asyncConnect = boost::get<bool>((*vars)["asyncConnect"]);
110 }
111
112 if (vars->count("taggedOnly")) {
113 config.taggedOnly = boost::get<bool>((*vars)["taggedOnly"]);
114 }
115
116 if (vars->count("logQueries")) {
117 config.logQueries = boost::get<bool>((*vars)["logQueries"]);
118 }
119
120 if (vars->count("logResponses")) {
121 config.logResponses = boost::get<bool>((*vars)["logResponses"]);
122 }
0bd2e252
RG
123
124 if (vars->count("exportTypes")) {
125 config.exportTypes.clear();
126
127 auto types = boost::get<std::vector<std::pair<int, std::string>>>((*vars)["exportTypes"]);
128 for (const auto& pair : types) {
129 const auto type = pair.second;
130 bool found = false;
131
132 for (const auto& entry : QType::names) {
133 if (entry.first == type) {
134 found = true;
135 config.exportTypes.insert(entry.second);
136 break;
137 }
138 }
139
140 if (!found) {
141 throw std::runtime_error("Unknown QType '" + type + "' in protobuf's export types");
142 }
143 }
144 }
f1c7929a 145}
abbf4bba 146#endif /* HAVE_PROTOBUF */
f1c7929a 147
e6ec15bf 148void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& delayedThreads)
3e61e7f7 149{
f3c18728 150 LuaConfigItems lci;
151
3e61e7f7 152 LuaContext Lua;
153 if(fname.empty())
154 return;
155 ifstream ifs(fname);
0f5785a6
PL
156 if(!ifs)
157 throw PDNSException("Cannot open file '"+fname+"': "+strerror(errno));
158
63341e8d
RG
159 auto luaconfsLocal = g_luaconfs.getLocal();
160 lci.generation = luaconfsLocal->generation + 1;
161
c2cc36d8
CH
162 // pdnslog here is compatible with pdnslog in lua-base4.cc.
163 Lua.writeFunction("pdnslog", [](const std::string& msg, boost::optional<int> loglevel) { g_log << (Logger::Urgency)loglevel.get_value_or(Logger::Warning) << msg<<endl; });
164 std::unordered_map<string, std::unordered_map<string, int>> pdns_table;
165 pdns_table["loglevels"] = std::unordered_map<string, int>{
166 {"Alert", LOG_ALERT},
167 {"Critical", LOG_CRIT},
168 {"Debug", LOG_DEBUG},
169 {"Emergency", LOG_EMERG},
170 {"Info", LOG_INFO},
171 {"Notice", LOG_NOTICE},
172 {"Warning", LOG_WARNING},
173 {"Error", LOG_ERR}
174 };
175 Lua.writeVariable("pdns", pdns_table);
176
f3c18728 177 Lua.writeFunction("clearSortlist", [&lci]() { lci.sortlist.clear(); });
3e61e7f7 178
179 /* we can get: "1.2.3.4"
180 {"1.2.3.4", "4.5.6.7"}
181 {"1.2.3.4", {"4.5.6.7", "8.9.10.11"}}
182 */
183
ad42489c 184 map<string,DNSFilterEngine::PolicyKind> pmap{
185 {"NoAction", DNSFilterEngine::PolicyKind::NoAction},
186 {"Drop", DNSFilterEngine::PolicyKind::Drop},
187 {"NXDOMAIN", DNSFilterEngine::PolicyKind::NXDOMAIN},
188 {"NODATA", DNSFilterEngine::PolicyKind::NODATA},
189 {"Truncate", DNSFilterEngine::PolicyKind::Truncate},
190 {"Custom", DNSFilterEngine::PolicyKind::Custom}
191 };
192 Lua.writeVariable("Policy", pmap);
193
d122dac0 194 Lua.writeFunction("rpzFile", [&lci](const string& filename, boost::optional<rpzOptions_t> options) {
ad42489c 195 try {
563bbdca 196 boost::optional<DNSFilterEngine::Policy> defpol;
d122dac0 197 bool defpolOverrideLocal = true;
563bbdca 198 std::string polName("rpzFile");
6b972d59 199 std::shared_ptr<DNSFilterEngine::Zone> zone = std::make_shared<DNSFilterEngine::Zone>();
563bbdca
RG
200 uint32_t maxTTL = std::numeric_limits<uint32_t>::max();
201 if(options) {
202 auto& have = *options;
8f618901 203 size_t zoneSizeHint = 0;
d122dac0 204 parseRPZParameters(have, polName, defpol, defpolOverrideLocal, maxTTL, zoneSizeHint);
8f618901 205 if (zoneSizeHint > 0) {
6b972d59 206 zone->reserve(zoneSizeHint);
a2d0450e 207 }
563bbdca 208 }
e6a9dde5 209 g_log<<Logger::Warning<<"Loading RPZ from file '"<<filename<<"'"<<endl;
6b972d59 210 zone->setName(polName);
d122dac0 211 loadRPZFromFile(filename, zone, defpol, defpolOverrideLocal, maxTTL);
6b972d59 212 lci.dfe.addZone(zone);
e6a9dde5 213 g_log<<Logger::Warning<<"Done loading RPZ from file '"<<filename<<"'"<<endl;
ad42489c 214 }
6791663c 215 catch(const std::exception& e) {
e6a9dde5 216 g_log<<Logger::Error<<"Unable to load RPZ zone from '"<<filename<<"': "<<e.what()<<endl;
ad42489c 217 }
218 });
219
d122dac0 220 Lua.writeFunction("rpzMaster", [&lci, &delayedThreads](const boost::variant<string, std::vector<std::pair<int, string> > >& masters_, const string& zoneName, boost::optional<rpzOptions_t> options) {
209955c7 221
222 boost::optional<DNSFilterEngine::Policy> defpol;
d122dac0 223 bool defpolOverrideLocal = true;
209955c7 224 std::shared_ptr<DNSFilterEngine::Zone> zone = std::make_shared<DNSFilterEngine::Zone>();
225 TSIGTriplet tt;
226 uint32_t refresh=0;
227 size_t maxReceivedXFRMBytes = 0;
ea448a77 228 uint16_t axfrTimeout = 20;
209955c7 229 uint32_t maxTTL = std::numeric_limits<uint32_t>::max();
230 ComboAddress localAddress;
5f311886
RG
231 std::vector<ComboAddress> masters;
232 if (masters_.type() == typeid(string)) {
233 masters.push_back(ComboAddress(boost::get<std::string>(masters_), 53));
234 }
235 else {
236 for (const auto& master : boost::get<std::vector<std::pair<int, std::string>>>(masters_)) {
237 masters.push_back(ComboAddress(master.second, 53));
238 }
239 }
240
209955c7 241 size_t zoneIdx;
23f886c0 242 std::string dumpFile;
a66c5cfa 243 std::shared_ptr<SOARecordContent> sr = nullptr;
209955c7 244
ad42489c 245 try {
a66c5cfa 246 std::string seedFile;
6b972d59 247 std::string polName(zoneName);
a66c5cfa
RG
248
249 if (options) {
563bbdca 250 auto& have = *options;
8f618901 251 size_t zoneSizeHint = 0;
d122dac0 252 parseRPZParameters(have, polName, defpol, defpolOverrideLocal, maxTTL, zoneSizeHint);
8f618901 253 if (zoneSizeHint > 0) {
6b972d59 254 zone->reserve(zoneSizeHint);
a2d0450e 255 }
a66c5cfa 256
563bbdca 257 if(have.count("tsigname")) {
d122dac0
RG
258 tt.name=DNSName(toLower(boost::get<string>(have["tsigname"])));
259 tt.algo=DNSName(toLower(boost::get<string>(have[ "tsigalgo"])));
260 if(B64Decode(boost::get<string>(have[ "tsigsecret"]), tt.secret))
98c9ec39 261 throw std::runtime_error("TSIG secret is not valid Base-64 encoded");
262 }
a66c5cfa 263
98c9ec39 264 if(have.count("refresh")) {
d122dac0 265 refresh = boost::get<uint32_t>(have["refresh"]);
98c9ec39 266 }
a66c5cfa 267
db8f9152 268 if(have.count("maxReceivedMBytes")) {
d122dac0 269 maxReceivedXFRMBytes = static_cast<size_t>(boost::get<uint32_t>(have["maxReceivedMBytes"]));
db8f9152 270 }
a66c5cfa 271
f6a8f7d7 272 if(have.count("localAddress")) {
d122dac0 273 localAddress = ComboAddress(boost::get<string>(have["localAddress"]));
f6a8f7d7 274 }
a66c5cfa 275
ea448a77 276 if(have.count("axfrTimeout")) {
d122dac0 277 axfrTimeout = static_cast<uint16_t>(boost::get<uint32_t>(have["axfrTimeout"]));
ea448a77 278 }
a66c5cfa
RG
279
280 if(have.count("seedFile")) {
d122dac0 281 seedFile = boost::get<std::string>(have["seedFile"]);
a66c5cfa 282 }
23f886c0
RG
283
284 if(have.count("dumpFile")) {
d122dac0 285 dumpFile = boost::get<std::string>(have["dumpFile"]);
23f886c0 286 }
563bbdca 287 }
a66c5cfa 288
5f311886
RG
289 if (localAddress != ComboAddress()) {
290 // We were passed a localAddress, check if its AF matches the masters'
291 for (const auto& master : masters) {
292 if (localAddress.sin4.sin_family != master.sin4.sin_family) {
293 throw PDNSException("Master address("+master.toString()+") is not of the same Address Family as the local address ("+localAddress.toString()+").");
294 }
295 }
6791663c
RG
296 }
297
a66c5cfa
RG
298 DNSName domain(zoneName);
299 zone->setDomain(domain);
6b972d59 300 zone->setName(polName);
6791663c 301 zone->setRefresh(refresh);
209955c7 302 zoneIdx = lci.dfe.addZone(zone);
a66c5cfa
RG
303
304 if (!seedFile.empty()) {
23f886c0
RG
305 g_log<<Logger::Info<<"Pre-loading RPZ zone "<<zoneName<<" from seed file '"<<seedFile<<"'"<<endl;
306 try {
d122dac0 307 sr = loadRPZFromFile(seedFile, zone, defpol, defpolOverrideLocal, maxTTL);
a66c5cfa 308
23f886c0
RG
309 if (zone->getDomain() != domain) {
310 throw PDNSException("The RPZ zone " + zoneName + " loaded from the seed file (" + zone->getDomain().toString() + ") does not match the one passed in parameter (" + domain.toString() + ")");
311 }
312
313 if (sr == nullptr) {
314 throw PDNSException("The RPZ zone " + zoneName + " loaded from the seed file (" + zone->getDomain().toString() + ") has no SOA record");
315 }
316 }
317 catch(const std::exception& e) {
318 g_log<<Logger::Warning<<"Unable to pre-load RPZ zone "<<zoneName<<" from seed file '"<<seedFile<<"': "<<e.what()<<endl;
a66c5cfa
RG
319 }
320 }
ad42489c 321 }
6791663c 322 catch(const std::exception& e) {
e6a9dde5 323 g_log<<Logger::Error<<"Problem configuring 'rpzMaster': "<<e.what()<<endl;
209955c7 324 exit(1); // FIXME proper exit code?
ad42489c 325 }
6791663c 326 catch(const PDNSException& e) {
e6a9dde5 327 g_log<<Logger::Error<<"Problem configuring 'rpzMaster': "<<e.reason<<endl;
209955c7 328 exit(1); // FIXME proper exit code?
ad42489c 329 }
330
d122dac0 331 delayedThreads.rpzMasterThreads.push_back(std::make_tuple(masters, defpol, defpolOverrideLocal, maxTTL, zoneIdx, tt, maxReceivedXFRMBytes, localAddress, axfrTimeout, sr, dumpFile));
ad42489c 332 });
333
3e61e7f7 334 typedef vector<pair<int,boost::variant<string, vector<pair<int, string> > > > > argvec_t;
335 Lua.writeFunction("addSortList",
f3c18728 336 [&lci](const std::string& formask_,
3e61e7f7 337 const boost::variant<string, argvec_t>& masks,
338 boost::optional<int> order_)
339 {
340 try {
341 Netmask formask(formask_);
f3c18728 342 int order = order_ ? (*order_) : lci.sortlist.getMaxOrder(formask)+1;
3e61e7f7 343 if(auto str = boost::get<string>(&masks))
f3c18728 344 lci.sortlist.addEntry(formask, Netmask(*str), order);
3e61e7f7 345 else {
346
347 auto vec = boost::get<argvec_t>(&masks);
348 for(const auto& e : *vec) {
349 if(auto s = boost::get<string>(&e.second)) {
f3c18728 350 lci.sortlist.addEntry(formask, Netmask(*s), order);
3e61e7f7 351 }
352 else {
353 const auto& v =boost::get<vector<pair<int, string> > >(e.second);
dd079764
RG
354 for(const auto& entry : v)
355 lci.sortlist.addEntry(formask, Netmask(entry.second), order);
3e61e7f7 356 }
357 ++order;
358 }
359 }
360 }
361 catch(std::exception& e) {
e6a9dde5 362 g_log<<Logger::Error<<"Error in addSortList: "<<e.what()<<endl;
3e61e7f7 363 }
364 });
2ac8ae89 365
190e0d9a
PL
366 Lua.writeFunction("addTA", [&lci](const std::string& who, const std::string& what) {
367 warnIfDNSSECDisabled("Warning: adding Trust Anchor for DNSSEC (addTA), but dnssec is set to 'off'!");
368 DNSName zone(who);
32122aab 369 auto ds = std::dynamic_pointer_cast<DSRecordContent>(DSRecordContent::make(what));
190e0d9a
PL
370 lci.dsAnchors[zone].insert(*ds);
371 });
372
373 Lua.writeFunction("clearTA", [&lci](boost::optional<string> who) {
374 warnIfDNSSECDisabled("Warning: removing Trust Anchor for DNSSEC (clearTA), but dnssec is set to 'off'!");
375 if(who)
376 lci.dsAnchors.erase(DNSName(*who));
377 else
378 lci.dsAnchors.clear();
379 });
380
381 /* Remove in 4.3 */
2ac8ae89 382 Lua.writeFunction("addDS", [&lci](const std::string& who, const std::string& what) {
e48c6b8a 383 warnIfDNSSECDisabled("Warning: adding Trust Anchor for DNSSEC (addDS), but dnssec is set to 'off'!");
190e0d9a 384 g_log<<Logger::Warning<<"addDS is deprecated and will be removed in the future, switch to addTA"<<endl;
52ad9eea 385 DNSName zone(who);
32122aab 386 auto ds = std::dynamic_pointer_cast<DSRecordContent>(DSRecordContent::make(what));
64a4a928 387 lci.dsAnchors[zone].insert(*ds);
52ad9eea 388 });
2ac8ae89 389
190e0d9a 390 /* Remove in 4.3 */
2ac8ae89 391 Lua.writeFunction("clearDS", [&lci](boost::optional<string> who) {
190e0d9a 392 g_log<<Logger::Warning<<"clearDS is deprecated and will be removed in the future, switch to clearTA"<<endl;
e48c6b8a 393 warnIfDNSSECDisabled("Warning: removing Trust Anchor for DNSSEC (clearDS), but dnssec is set to 'off'!");
2ac8ae89 394 if(who)
395 lci.dsAnchors.erase(DNSName(*who));
396 else
397 lci.dsAnchors.clear();
398 });
399
1bd49828 400 Lua.writeFunction("addNTA", [&lci](const std::string& who, const boost::optional<std::string> why) {
e48c6b8a 401 warnIfDNSSECDisabled("Warning: adding Negative Trust Anchor for DNSSEC (addNTA), but dnssec is set to 'off'!");
1bd49828
PL
402 if(why)
403 lci.negAnchors[DNSName(who)] = static_cast<string>(*why);
404 else
405 lci.negAnchors[DNSName(who)] = "";
406 });
407
408 Lua.writeFunction("clearNTA", [&lci](boost::optional<string> who) {
e48c6b8a 409 warnIfDNSSECDisabled("Warning: removing Negative Trust Anchor for DNSSEC (clearNTA), but dnssec is set to 'off'!");
1bd49828
PL
410 if(who)
411 lci.negAnchors.erase(DNSName(*who));
412 else
413 lci.negAnchors.clear();
414 });
415
e4ae55e5
PL
416 Lua.writeFunction("readTrustAnchorsFromFile", [&lci](const std::string& fname, const boost::optional<uint32_t> interval) {
417 uint32_t realInterval = 24;
418 if (interval) {
419 realInterval = static_cast<uint32_t>(*interval);
8f29eeaa 420 }
e4ae55e5
PL
421 warnIfDNSSECDisabled("Warning: reading Trust Anchors from file (readTrustAnchorsFromFile), but dnssec is set to 'off'!");
422 lci.trustAnchorFileInfo.fname = fname;
423 lci.trustAnchorFileInfo.interval = realInterval;
424 updateTrustAnchorsFromFile(fname, lci.dsAnchors);
8f29eeaa
PL
425 });
426
aa7929a3 427#if HAVE_PROTOBUF
f1c7929a
RG
428 Lua.writeFunction("setProtobufMasks", [&lci](const uint8_t maskV4, uint8_t maskV6) {
429 lci.protobufMaskV4 = maskV4;
430 lci.protobufMaskV6 = maskV6;
431 });
432
b773359c 433 Lua.writeFunction("protobufServer", [&lci](boost::variant<const std::string, const std::unordered_map<int, std::string>> servers, boost::optional<protobufOptions_t> vars) {
63341e8d 434 if (!lci.protobufExportConfig.enabled) {
b773359c 435
63341e8d 436 lci.protobufExportConfig.enabled = true;
b773359c
RG
437
438 try {
439 if (servers.type() == typeid(std::string)) {
440 auto server = boost::get<const std::string>(servers);
441
442 lci.protobufExportConfig.servers.emplace_back(server);
443 }
444 else {
445 auto serversMap = boost::get<const std::unordered_map<int,std::string>>(servers);
446 for (const auto& serverPair : serversMap) {
447 lci.protobufExportConfig.servers.emplace_back(serverPair.second);
448 }
449 }
450
451 parseProtobufOptions(vars, lci.protobufExportConfig);
452 }
453 catch(std::exception& e) {
454 g_log<<Logger::Error<<"Error while adding protobuf logger: "<<e.what()<<endl;
455 }
456 catch(PDNSException& e) {
457 g_log<<Logger::Error<<"Error while adding protobuf logger: "<<e.reason<<endl;
458 }
aa7929a3
RG
459 }
460 else {
b773359c 461 g_log<<Logger::Error<<"Only one protobufServer() directive can be configured, we already have "<<lci.protobufExportConfig.servers.at(0).toString()<<endl;
aa7929a3 462 }
4898a348
RG
463 });
464
b773359c
RG
465 Lua.writeFunction("outgoingProtobufServer", [&lci](boost::variant<const std::string, const std::unordered_map<int, std::string>> servers, boost::optional<protobufOptions_t> vars) {
466 if (!lci.outgoingProtobufExportConfig.enabled) {
467
468 lci.outgoingProtobufExportConfig.enabled = true;
469
470 try {
471 if (servers.type() == typeid(std::string)) {
472 auto server = boost::get<const std::string>(servers);
473
474 lci.outgoingProtobufExportConfig.servers.emplace_back(server);
475 }
476 else {
477 auto serversMap = boost::get<const std::unordered_map<int,std::string>>(servers);
478 for (const auto& serverPair : serversMap) {
479 lci.outgoingProtobufExportConfig.servers.emplace_back(serverPair.second);
480 }
481 }
482
483 parseProtobufOptions(vars, lci.outgoingProtobufExportConfig);
484 }
485 catch(std::exception& e) {
486 g_log<<Logger::Error<<"Error while starting outgoing protobuf logger: "<<e.what()<<endl;
487 }
488 catch(PDNSException& e) {
489 g_log<<Logger::Error<<"Error while starting outgoing protobuf logger: "<<e.reason<<endl;
490 }
aa7929a3 491 }
b773359c
RG
492 else {
493 g_log<<Logger::Error<<"Only one outgoingProtobufServer() directive can be configured, we already have "<<lci.outgoingProtobufExportConfig.servers.at(0).toString()<<endl;
aa7929a3
RG
494 }
495 });
496#endif
497
ad42489c 498 try {
499 Lua.executeCode(ifs);
500 g_luaconfs.setState(lci);
501 }
2ac8ae89 502 catch(const LuaContext::ExecutionErrorException& e) {
e6a9dde5 503 g_log<<Logger::Error<<"Unable to load Lua script from '"+fname+"': ";
2ac8ae89 504 try {
505 std::rethrow_if_nested(e);
dd079764
RG
506 } catch(const std::exception& exp) {
507 // exp is the exception that was thrown from inside the lambda
e6a9dde5 508 g_log << exp.what() << std::endl;
2ac8ae89 509 }
dd079764
RG
510 catch(const PDNSException& exp) {
511 // exp is the exception that was thrown from inside the lambda
e6a9dde5 512 g_log << exp.reason << std::endl;
2ac8ae89 513 }
514 throw;
515
516 }
ad42489c 517 catch(std::exception& err) {
e6a9dde5 518 g_log<<Logger::Error<<"Unable to load Lua script from '"+fname+"': "<<err.what()<<endl;
2ac8ae89 519 throw;
ad42489c 520 }
521
3e61e7f7 522}
6a99b9a4 523
e6ec15bf
RG
524void startLuaConfigDelayedThreads(const luaConfigDelayedThreads& delayedThreads, uint64_t generation)
525{
526 for (const auto& rpzMaster : delayedThreads.rpzMasterThreads) {
527 try {
d122dac0 528 std::thread t(RPZIXFRTracker, std::get<0>(rpzMaster), std::get<1>(rpzMaster), std::get<2>(rpzMaster), std::get<3>(rpzMaster), std::get<4>(rpzMaster), std::get<5>(rpzMaster), std::get<6>(rpzMaster) * 1024 * 1024, std::get<7>(rpzMaster), std::get<8>(rpzMaster), std::get<9>(rpzMaster), std::get<10>(rpzMaster), generation);
e6ec15bf
RG
529 t.detach();
530 }
531 catch(const std::exception& e) {
532 g_log<<Logger::Error<<"Problem starting RPZIXFRTracker thread: "<<e.what()<<endl;
533 exit(1); // FIXME proper exit code?
534 }
535 catch(const PDNSException& e) {
536 g_log<<Logger::Error<<"Problem starting RPZIXFRTracker thread: "<<e.reason<<endl;
537 exit(1); // FIXME proper exit code?
538 }
539 }
540}