]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/rec-lua-conf.cc
minicurl: correct comment
[thirdparty/pdns.git] / pdns / rec-lua-conf.cc
1 #include "config.h"
2 #include "ext/luawrapper/include/LuaContext.hpp"
3
4 #include <fstream>
5 #include <thread>
6 #include "namespaces.hh"
7 #include "logger.hh"
8 #include "rec-lua-conf.hh"
9 #include "sortlist.hh"
10 #include "filterpo.hh"
11 #include "syncres.hh"
12 #include "rpzloader.hh"
13 #include "base64.hh"
14 #include "remote_logger.hh"
15 #include "validate.hh"
16 #include "validate-recursor.hh"
17 #include "root-dnssec.hh"
18
19 GlobalStateHolder<LuaConfigItems> g_luaconfs;
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
34 LuaConfigItems::LuaConfigItems()
35 {
36 DNSName root("."); // don't use g_rootdnsname here, it might not exist yet
37 for (const auto &dsRecord : rootDSs) {
38 auto ds=std::dynamic_pointer_cast<DSRecordContent>(DSRecordContent::make(dsRecord));
39 dsAnchors[root].insert(*ds);
40 }
41 }
42
43 /* DID YOU READ THE STORY ABOVE? */
44
45 template <typename C>
46 typename 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
54 typedef std::unordered_map<std::string, boost::variant<bool, uint32_t, std::string > > rpzOptions_t;
55
56 static void parseRPZParameters(rpzOptions_t& have, std::string& polName, boost::optional<DNSFilterEngine::Policy>& defpol, bool& defpolOverrideLocal, uint32_t& maxTTL, size_t& zoneSizeHint)
57 {
58 if(have.count("policyName")) {
59 polName = boost::get<std::string>(have["policyName"]);
60 }
61 if(have.count("defpol")) {
62 defpol=DNSFilterEngine::Policy();
63 defpol->d_kind = (DNSFilterEngine::PolicyKind)boost::get<uint32_t>(have["defpol"]);
64 defpol->d_name = std::make_shared<std::string>(polName);
65 if(defpol->d_kind == DNSFilterEngine::PolicyKind::Custom) {
66 defpol->d_custom.push_back(DNSRecordContent::mastermake(QType::CNAME, QClass::IN,
67 boost::get<string>(have["defcontent"])));
68
69 if(have.count("defttl"))
70 defpol->d_ttl = static_cast<int32_t>(boost::get<uint32_t>(have["defttl"]));
71 else
72 defpol->d_ttl = -1; // get it from the zone
73 }
74
75 if (have.count("defpolOverrideLocalData")) {
76 defpolOverrideLocal = boost::get<bool>(have["defpolOverrideLocalData"]);
77 }
78 }
79 if(have.count("maxTTL")) {
80 maxTTL = boost::get<uint32_t>(have["maxTTL"]);
81 }
82 if(have.count("zoneSizeHint")) {
83 zoneSizeHint = static_cast<size_t>(boost::get<uint32_t>(have["zoneSizeHint"]));
84 }
85 }
86
87 #if HAVE_PROTOBUF
88 typedef std::unordered_map<std::string, boost::variant<bool, uint64_t, std::string, std::vector<std::pair<int,std::string> > > > protobufOptions_t;
89
90 static 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 }
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 }
145 }
146 #endif /* HAVE_PROTOBUF */
147
148 #ifdef HAVE_FSTRM
149 typedef std::unordered_map<std::string, boost::variant<bool, uint64_t, std::string, std::vector<std::pair<int,std::string> > > > frameStreamOptions_t;
150
151 static void parseFrameStreamOptions(boost::optional<frameStreamOptions_t> vars, FrameStreamExportConfig& config)
152 {
153 if (!vars) {
154 return;
155 }
156
157 if (vars->count("logQueries")) {
158 config.logQueries = boost::get<bool>((*vars)["logQueries"]);
159 }
160 if (vars->count("logResponses")) {
161 config.logResponses = boost::get<bool>((*vars)["logResponses"]);
162 }
163
164 if (vars->count("bufferHint")) {
165 config.bufferHint = boost::get<uint64_t>((*vars)["bufferHint"]);
166 }
167 if (vars->count("flushTimeout")) {
168 config.flushTimeout = boost::get<uint64_t>((*vars)["flushTimeout"]);
169 }
170 if (vars->count("inputQueueSize")) {
171 config.inputQueueSize = boost::get<uint64_t>((*vars)["inputQueueSize"]);
172 }
173 if (vars->count("outputQueueSize")) {
174 config.outputQueueSize = boost::get<uint64_t>((*vars)["outputQueueSize"]);
175 }
176 if (vars->count("queueNotifyThreshold")) {
177 config.queueNotifyThreshold = boost::get<uint64_t>((*vars)["queueNotifyThreshold"]);
178 }
179 if (vars->count("reopenInterval")) {
180 config.reopenInterval = boost::get<uint64_t>((*vars)["reopenInterval"]);
181 }
182 }
183 #endif /* HAVE_FSTRM */
184
185 void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& delayedThreads)
186 {
187 LuaConfigItems lci;
188
189 LuaContext Lua;
190 if(fname.empty())
191 return;
192 ifstream ifs(fname);
193 if(!ifs)
194 throw PDNSException("Cannot open file '"+fname+"': "+strerror(errno));
195
196 auto luaconfsLocal = g_luaconfs.getLocal();
197 lci.generation = luaconfsLocal->generation + 1;
198
199 // pdnslog here is compatible with pdnslog in lua-base4.cc.
200 Lua.writeFunction("pdnslog", [](const std::string& msg, boost::optional<int> loglevel) { g_log << (Logger::Urgency)loglevel.get_value_or(Logger::Warning) << msg<<endl; });
201 std::unordered_map<string, std::unordered_map<string, int>> pdns_table;
202 pdns_table["loglevels"] = std::unordered_map<string, int>{
203 {"Alert", LOG_ALERT},
204 {"Critical", LOG_CRIT},
205 {"Debug", LOG_DEBUG},
206 {"Emergency", LOG_EMERG},
207 {"Info", LOG_INFO},
208 {"Notice", LOG_NOTICE},
209 {"Warning", LOG_WARNING},
210 {"Error", LOG_ERR}
211 };
212 Lua.writeVariable("pdns", pdns_table);
213
214 Lua.writeFunction("clearSortlist", [&lci]() { lci.sortlist.clear(); });
215
216 /* we can get: "1.2.3.4"
217 {"1.2.3.4", "4.5.6.7"}
218 {"1.2.3.4", {"4.5.6.7", "8.9.10.11"}}
219 */
220
221 map<string,DNSFilterEngine::PolicyKind> pmap{
222 {"NoAction", DNSFilterEngine::PolicyKind::NoAction},
223 {"Drop", DNSFilterEngine::PolicyKind::Drop},
224 {"NXDOMAIN", DNSFilterEngine::PolicyKind::NXDOMAIN},
225 {"NODATA", DNSFilterEngine::PolicyKind::NODATA},
226 {"Truncate", DNSFilterEngine::PolicyKind::Truncate},
227 {"Custom", DNSFilterEngine::PolicyKind::Custom}
228 };
229 Lua.writeVariable("Policy", pmap);
230
231 Lua.writeFunction("rpzFile", [&lci](const string& filename, boost::optional<rpzOptions_t> options) {
232 try {
233 boost::optional<DNSFilterEngine::Policy> defpol;
234 bool defpolOverrideLocal = true;
235 std::string polName("rpzFile");
236 std::shared_ptr<DNSFilterEngine::Zone> zone = std::make_shared<DNSFilterEngine::Zone>();
237 uint32_t maxTTL = std::numeric_limits<uint32_t>::max();
238 if(options) {
239 auto& have = *options;
240 size_t zoneSizeHint = 0;
241 parseRPZParameters(have, polName, defpol, defpolOverrideLocal, maxTTL, zoneSizeHint);
242 if (zoneSizeHint > 0) {
243 zone->reserve(zoneSizeHint);
244 }
245 }
246 g_log<<Logger::Warning<<"Loading RPZ from file '"<<filename<<"'"<<endl;
247 zone->setName(polName);
248 loadRPZFromFile(filename, zone, defpol, defpolOverrideLocal, maxTTL);
249 lci.dfe.addZone(zone);
250 g_log<<Logger::Warning<<"Done loading RPZ from file '"<<filename<<"'"<<endl;
251 }
252 catch(const std::exception& e) {
253 g_log<<Logger::Error<<"Unable to load RPZ zone from '"<<filename<<"': "<<e.what()<<endl;
254 }
255 });
256
257 Lua.writeFunction("rpzMaster", [&lci, &delayedThreads](const boost::variant<string, std::vector<std::pair<int, string> > >& masters_, const string& zoneName, boost::optional<rpzOptions_t> options) {
258
259 boost::optional<DNSFilterEngine::Policy> defpol;
260 bool defpolOverrideLocal = true;
261 std::shared_ptr<DNSFilterEngine::Zone> zone = std::make_shared<DNSFilterEngine::Zone>();
262 TSIGTriplet tt;
263 uint32_t refresh=0;
264 size_t maxReceivedXFRMBytes = 0;
265 uint16_t axfrTimeout = 20;
266 uint32_t maxTTL = std::numeric_limits<uint32_t>::max();
267 ComboAddress localAddress;
268 std::vector<ComboAddress> masters;
269 if (masters_.type() == typeid(string)) {
270 masters.push_back(ComboAddress(boost::get<std::string>(masters_), 53));
271 }
272 else {
273 for (const auto& master : boost::get<std::vector<std::pair<int, std::string>>>(masters_)) {
274 masters.push_back(ComboAddress(master.second, 53));
275 }
276 }
277
278 size_t zoneIdx;
279 std::string dumpFile;
280 std::shared_ptr<SOARecordContent> sr = nullptr;
281
282 try {
283 std::string seedFile;
284 std::string polName(zoneName);
285
286 if (options) {
287 auto& have = *options;
288 size_t zoneSizeHint = 0;
289 parseRPZParameters(have, polName, defpol, defpolOverrideLocal, maxTTL, zoneSizeHint);
290 if (zoneSizeHint > 0) {
291 zone->reserve(zoneSizeHint);
292 }
293
294 if(have.count("tsigname")) {
295 tt.name=DNSName(toLower(boost::get<string>(have["tsigname"])));
296 tt.algo=DNSName(toLower(boost::get<string>(have[ "tsigalgo"])));
297 if(B64Decode(boost::get<string>(have[ "tsigsecret"]), tt.secret))
298 throw std::runtime_error("TSIG secret is not valid Base-64 encoded");
299 }
300
301 if(have.count("refresh")) {
302 refresh = boost::get<uint32_t>(have["refresh"]);
303 }
304
305 if(have.count("maxReceivedMBytes")) {
306 maxReceivedXFRMBytes = static_cast<size_t>(boost::get<uint32_t>(have["maxReceivedMBytes"]));
307 }
308
309 if(have.count("localAddress")) {
310 localAddress = ComboAddress(boost::get<string>(have["localAddress"]));
311 }
312
313 if(have.count("axfrTimeout")) {
314 axfrTimeout = static_cast<uint16_t>(boost::get<uint32_t>(have["axfrTimeout"]));
315 }
316
317 if(have.count("seedFile")) {
318 seedFile = boost::get<std::string>(have["seedFile"]);
319 }
320
321 if(have.count("dumpFile")) {
322 dumpFile = boost::get<std::string>(have["dumpFile"]);
323 }
324 }
325
326 if (localAddress != ComboAddress()) {
327 // We were passed a localAddress, check if its AF matches the masters'
328 for (const auto& master : masters) {
329 if (localAddress.sin4.sin_family != master.sin4.sin_family) {
330 throw PDNSException("Master address("+master.toString()+") is not of the same Address Family as the local address ("+localAddress.toString()+").");
331 }
332 }
333 }
334
335 DNSName domain(zoneName);
336 zone->setDomain(domain);
337 zone->setName(polName);
338 zone->setRefresh(refresh);
339 zoneIdx = lci.dfe.addZone(zone);
340
341 if (!seedFile.empty()) {
342 g_log<<Logger::Info<<"Pre-loading RPZ zone "<<zoneName<<" from seed file '"<<seedFile<<"'"<<endl;
343 try {
344 sr = loadRPZFromFile(seedFile, zone, defpol, defpolOverrideLocal, maxTTL);
345
346 if (zone->getDomain() != domain) {
347 throw PDNSException("The RPZ zone " + zoneName + " loaded from the seed file (" + zone->getDomain().toString() + ") does not match the one passed in parameter (" + domain.toString() + ")");
348 }
349
350 if (sr == nullptr) {
351 throw PDNSException("The RPZ zone " + zoneName + " loaded from the seed file (" + zone->getDomain().toString() + ") has no SOA record");
352 }
353 }
354 catch(const std::exception& e) {
355 g_log<<Logger::Warning<<"Unable to pre-load RPZ zone "<<zoneName<<" from seed file '"<<seedFile<<"': "<<e.what()<<endl;
356 }
357 }
358 }
359 catch(const std::exception& e) {
360 g_log<<Logger::Error<<"Problem configuring 'rpzMaster': "<<e.what()<<endl;
361 exit(1); // FIXME proper exit code?
362 }
363 catch(const PDNSException& e) {
364 g_log<<Logger::Error<<"Problem configuring 'rpzMaster': "<<e.reason<<endl;
365 exit(1); // FIXME proper exit code?
366 }
367
368 delayedThreads.rpzMasterThreads.push_back(std::make_tuple(masters, defpol, defpolOverrideLocal, maxTTL, zoneIdx, tt, maxReceivedXFRMBytes, localAddress, axfrTimeout, sr, dumpFile));
369 });
370
371 typedef vector<pair<int,boost::variant<string, vector<pair<int, string> > > > > argvec_t;
372 Lua.writeFunction("addSortList",
373 [&lci](const std::string& formask_,
374 const boost::variant<string, argvec_t>& masks,
375 boost::optional<int> order_)
376 {
377 try {
378 Netmask formask(formask_);
379 int order = order_ ? (*order_) : lci.sortlist.getMaxOrder(formask)+1;
380 if(auto str = boost::get<string>(&masks))
381 lci.sortlist.addEntry(formask, Netmask(*str), order);
382 else {
383
384 auto vec = boost::get<argvec_t>(&masks);
385 for(const auto& e : *vec) {
386 if(auto s = boost::get<string>(&e.second)) {
387 lci.sortlist.addEntry(formask, Netmask(*s), order);
388 }
389 else {
390 const auto& v =boost::get<vector<pair<int, string> > >(e.second);
391 for(const auto& entry : v)
392 lci.sortlist.addEntry(formask, Netmask(entry.second), order);
393 }
394 ++order;
395 }
396 }
397 }
398 catch(std::exception& e) {
399 g_log<<Logger::Error<<"Error in addSortList: "<<e.what()<<endl;
400 }
401 });
402
403 Lua.writeFunction("addTA", [&lci](const std::string& who, const std::string& what) {
404 warnIfDNSSECDisabled("Warning: adding Trust Anchor for DNSSEC (addTA), but dnssec is set to 'off'!");
405 DNSName zone(who);
406 auto ds = std::dynamic_pointer_cast<DSRecordContent>(DSRecordContent::make(what));
407 lci.dsAnchors[zone].insert(*ds);
408 });
409
410 Lua.writeFunction("clearTA", [&lci](boost::optional<string> who) {
411 warnIfDNSSECDisabled("Warning: removing Trust Anchor for DNSSEC (clearTA), but dnssec is set to 'off'!");
412 if(who)
413 lci.dsAnchors.erase(DNSName(*who));
414 else
415 lci.dsAnchors.clear();
416 });
417
418 /* Remove in 4.3 */
419 Lua.writeFunction("addDS", [&lci](const std::string& who, const std::string& what) {
420 warnIfDNSSECDisabled("Warning: adding Trust Anchor for DNSSEC (addDS), but dnssec is set to 'off'!");
421 g_log<<Logger::Warning<<"addDS is deprecated and will be removed in the future, switch to addTA"<<endl;
422 DNSName zone(who);
423 auto ds = std::dynamic_pointer_cast<DSRecordContent>(DSRecordContent::make(what));
424 lci.dsAnchors[zone].insert(*ds);
425 });
426
427 /* Remove in 4.3 */
428 Lua.writeFunction("clearDS", [&lci](boost::optional<string> who) {
429 g_log<<Logger::Warning<<"clearDS is deprecated and will be removed in the future, switch to clearTA"<<endl;
430 warnIfDNSSECDisabled("Warning: removing Trust Anchor for DNSSEC (clearDS), but dnssec is set to 'off'!");
431 if(who)
432 lci.dsAnchors.erase(DNSName(*who));
433 else
434 lci.dsAnchors.clear();
435 });
436
437 Lua.writeFunction("addNTA", [&lci](const std::string& who, const boost::optional<std::string> why) {
438 warnIfDNSSECDisabled("Warning: adding Negative Trust Anchor for DNSSEC (addNTA), but dnssec is set to 'off'!");
439 if(why)
440 lci.negAnchors[DNSName(who)] = static_cast<string>(*why);
441 else
442 lci.negAnchors[DNSName(who)] = "";
443 });
444
445 Lua.writeFunction("clearNTA", [&lci](boost::optional<string> who) {
446 warnIfDNSSECDisabled("Warning: removing Negative Trust Anchor for DNSSEC (clearNTA), but dnssec is set to 'off'!");
447 if(who)
448 lci.negAnchors.erase(DNSName(*who));
449 else
450 lci.negAnchors.clear();
451 });
452
453 Lua.writeFunction("readTrustAnchorsFromFile", [&lci](const std::string& fname, const boost::optional<uint32_t> interval) {
454 uint32_t realInterval = 24;
455 if (interval) {
456 realInterval = static_cast<uint32_t>(*interval);
457 }
458 warnIfDNSSECDisabled("Warning: reading Trust Anchors from file (readTrustAnchorsFromFile), but dnssec is set to 'off'!");
459 lci.trustAnchorFileInfo.fname = fname;
460 lci.trustAnchorFileInfo.interval = realInterval;
461 updateTrustAnchorsFromFile(fname, lci.dsAnchors);
462 });
463
464 #if HAVE_PROTOBUF
465 Lua.writeFunction("setProtobufMasks", [&lci](const uint8_t maskV4, uint8_t maskV6) {
466 lci.protobufMaskV4 = maskV4;
467 lci.protobufMaskV6 = maskV6;
468 });
469
470 Lua.writeFunction("protobufServer", [&lci](boost::variant<const std::string, const std::unordered_map<int, std::string>> servers, boost::optional<protobufOptions_t> vars) {
471 if (!lci.protobufExportConfig.enabled) {
472
473 lci.protobufExportConfig.enabled = true;
474
475 try {
476 if (servers.type() == typeid(std::string)) {
477 auto server = boost::get<const std::string>(servers);
478
479 lci.protobufExportConfig.servers.emplace_back(server);
480 }
481 else {
482 auto serversMap = boost::get<const std::unordered_map<int,std::string>>(servers);
483 for (const auto& serverPair : serversMap) {
484 lci.protobufExportConfig.servers.emplace_back(serverPair.second);
485 }
486 }
487
488 parseProtobufOptions(vars, lci.protobufExportConfig);
489 }
490 catch(std::exception& e) {
491 g_log<<Logger::Error<<"Error while adding protobuf logger: "<<e.what()<<endl;
492 }
493 catch(PDNSException& e) {
494 g_log<<Logger::Error<<"Error while adding protobuf logger: "<<e.reason<<endl;
495 }
496 }
497 else {
498 g_log<<Logger::Error<<"Only one protobufServer() directive can be configured, we already have "<<lci.protobufExportConfig.servers.at(0).toString()<<endl;
499 }
500 });
501
502 Lua.writeFunction("outgoingProtobufServer", [&lci](boost::variant<const std::string, const std::unordered_map<int, std::string>> servers, boost::optional<protobufOptions_t> vars) {
503 if (!lci.outgoingProtobufExportConfig.enabled) {
504
505 lci.outgoingProtobufExportConfig.enabled = true;
506
507 try {
508 if (servers.type() == typeid(std::string)) {
509 auto server = boost::get<const std::string>(servers);
510
511 lci.outgoingProtobufExportConfig.servers.emplace_back(server);
512 }
513 else {
514 auto serversMap = boost::get<const std::unordered_map<int,std::string>>(servers);
515 for (const auto& serverPair : serversMap) {
516 lci.outgoingProtobufExportConfig.servers.emplace_back(serverPair.second);
517 }
518 }
519
520 parseProtobufOptions(vars, lci.outgoingProtobufExportConfig);
521 }
522 catch(std::exception& e) {
523 g_log<<Logger::Error<<"Error while starting outgoing protobuf logger: "<<e.what()<<endl;
524 }
525 catch(PDNSException& e) {
526 g_log<<Logger::Error<<"Error while starting outgoing protobuf logger: "<<e.reason<<endl;
527 }
528 }
529 else {
530 g_log<<Logger::Error<<"Only one outgoingProtobufServer() directive can be configured, we already have "<<lci.outgoingProtobufExportConfig.servers.at(0).toString()<<endl;
531 }
532 });
533 #endif
534
535 #ifdef HAVE_FSTRM
536 Lua.writeFunction("dnstapFrameStreamServer", [&lci](boost::variant<const std::string, const std::unordered_map<int, std::string>> servers, boost::optional<frameStreamOptions_t> vars) {
537 if (!lci.frameStreamExportConfig.enabled) {
538
539 lci.frameStreamExportConfig.enabled = true;
540
541 try {
542 if (servers.type() == typeid(std::string)) {
543 auto server = boost::get<const std::string>(servers);
544
545 lci.frameStreamExportConfig.servers.emplace_back(server);
546 }
547 else {
548 auto serversMap = boost::get<const std::unordered_map<int,std::string>>(servers);
549 for (const auto& serverPair : serversMap) {
550 lci.frameStreamExportConfig.servers.emplace_back(serverPair.second);
551 }
552 }
553
554 parseFrameStreamOptions(vars, lci.frameStreamExportConfig);
555 }
556 catch(std::exception& e) {
557 g_log<<Logger::Error<<"Error while starting dnstap framestream logger: "<<e.what()<<endl;
558 }
559 catch(PDNSException& e) {
560 g_log<<Logger::Error<<"Error while starting dnstap framestream logger: "<<e.reason<<endl;
561 }
562 }
563 else {
564 g_log<<Logger::Error<<"Only one dnstapFrameStreamServer() directive can be configured, we already have "<<lci.frameStreamExportConfig.servers.at(0).toString()<<endl;
565 }
566 });
567 #endif /* HAVE_FSTRM */
568
569 try {
570 Lua.executeCode(ifs);
571 g_luaconfs.setState(lci);
572 }
573 catch(const LuaContext::ExecutionErrorException& e) {
574 g_log<<Logger::Error<<"Unable to load Lua script from '"+fname+"': ";
575 try {
576 std::rethrow_if_nested(e);
577 } catch(const std::exception& exp) {
578 // exp is the exception that was thrown from inside the lambda
579 g_log << exp.what() << std::endl;
580 }
581 catch(const PDNSException& exp) {
582 // exp is the exception that was thrown from inside the lambda
583 g_log << exp.reason << std::endl;
584 }
585 throw;
586
587 }
588 catch(std::exception& err) {
589 g_log<<Logger::Error<<"Unable to load Lua script from '"+fname+"': "<<err.what()<<endl;
590 throw;
591 }
592
593 }
594
595 void startLuaConfigDelayedThreads(const luaConfigDelayedThreads& delayedThreads, uint64_t generation)
596 {
597 for (const auto& rpzMaster : delayedThreads.rpzMasterThreads) {
598 try {
599 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);
600 t.detach();
601 }
602 catch(const std::exception& e) {
603 g_log<<Logger::Error<<"Problem starting RPZIXFRTracker thread: "<<e.what()<<endl;
604 exit(1); // FIXME proper exit code?
605 }
606 catch(const PDNSException& e) {
607 g_log<<Logger::Error<<"Problem starting RPZIXFRTracker thread: "<<e.reason<<endl;
608 exit(1); // FIXME proper exit code?
609 }
610 }
611 }