]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/rec-lua-conf.cc
minicurl: correct comment
[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
b9fa43e0
OM
148#ifdef HAVE_FSTRM
149typedef std::unordered_map<std::string, boost::variant<bool, uint64_t, std::string, std::vector<std::pair<int,std::string> > > > frameStreamOptions_t;
150
151static void parseFrameStreamOptions(boost::optional<frameStreamOptions_t> vars, FrameStreamExportConfig& config)
152{
153 if (!vars) {
154 return;
155 }
573f4ff0
OM
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 }
b9fa43e0
OM
182}
183#endif /* HAVE_FSTRM */
184
e6ec15bf 185void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& delayedThreads)
3e61e7f7 186{
f3c18728 187 LuaConfigItems lci;
188
3e61e7f7 189 LuaContext Lua;
190 if(fname.empty())
191 return;
192 ifstream ifs(fname);
0f5785a6
PL
193 if(!ifs)
194 throw PDNSException("Cannot open file '"+fname+"': "+strerror(errno));
195
63341e8d
RG
196 auto luaconfsLocal = g_luaconfs.getLocal();
197 lci.generation = luaconfsLocal->generation + 1;
198
c2cc36d8
CH
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
f3c18728 214 Lua.writeFunction("clearSortlist", [&lci]() { lci.sortlist.clear(); });
3e61e7f7 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
ad42489c 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
d122dac0 231 Lua.writeFunction("rpzFile", [&lci](const string& filename, boost::optional<rpzOptions_t> options) {
ad42489c 232 try {
563bbdca 233 boost::optional<DNSFilterEngine::Policy> defpol;
d122dac0 234 bool defpolOverrideLocal = true;
563bbdca 235 std::string polName("rpzFile");
6b972d59 236 std::shared_ptr<DNSFilterEngine::Zone> zone = std::make_shared<DNSFilterEngine::Zone>();
563bbdca
RG
237 uint32_t maxTTL = std::numeric_limits<uint32_t>::max();
238 if(options) {
239 auto& have = *options;
8f618901 240 size_t zoneSizeHint = 0;
d122dac0 241 parseRPZParameters(have, polName, defpol, defpolOverrideLocal, maxTTL, zoneSizeHint);
8f618901 242 if (zoneSizeHint > 0) {
6b972d59 243 zone->reserve(zoneSizeHint);
a2d0450e 244 }
563bbdca 245 }
e6a9dde5 246 g_log<<Logger::Warning<<"Loading RPZ from file '"<<filename<<"'"<<endl;
6b972d59 247 zone->setName(polName);
d122dac0 248 loadRPZFromFile(filename, zone, defpol, defpolOverrideLocal, maxTTL);
6b972d59 249 lci.dfe.addZone(zone);
e6a9dde5 250 g_log<<Logger::Warning<<"Done loading RPZ from file '"<<filename<<"'"<<endl;
ad42489c 251 }
6791663c 252 catch(const std::exception& e) {
e6a9dde5 253 g_log<<Logger::Error<<"Unable to load RPZ zone from '"<<filename<<"': "<<e.what()<<endl;
ad42489c 254 }
255 });
256
d122dac0 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) {
209955c7 258
259 boost::optional<DNSFilterEngine::Policy> defpol;
d122dac0 260 bool defpolOverrideLocal = true;
209955c7 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;
ea448a77 265 uint16_t axfrTimeout = 20;
209955c7 266 uint32_t maxTTL = std::numeric_limits<uint32_t>::max();
267 ComboAddress localAddress;
5f311886
RG
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
209955c7 278 size_t zoneIdx;
23f886c0 279 std::string dumpFile;
a66c5cfa 280 std::shared_ptr<SOARecordContent> sr = nullptr;
209955c7 281
ad42489c 282 try {
a66c5cfa 283 std::string seedFile;
6b972d59 284 std::string polName(zoneName);
a66c5cfa
RG
285
286 if (options) {
563bbdca 287 auto& have = *options;
8f618901 288 size_t zoneSizeHint = 0;
d122dac0 289 parseRPZParameters(have, polName, defpol, defpolOverrideLocal, maxTTL, zoneSizeHint);
8f618901 290 if (zoneSizeHint > 0) {
6b972d59 291 zone->reserve(zoneSizeHint);
a2d0450e 292 }
a66c5cfa 293
563bbdca 294 if(have.count("tsigname")) {
d122dac0
RG
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))
98c9ec39 298 throw std::runtime_error("TSIG secret is not valid Base-64 encoded");
299 }
a66c5cfa 300
98c9ec39 301 if(have.count("refresh")) {
d122dac0 302 refresh = boost::get<uint32_t>(have["refresh"]);
98c9ec39 303 }
a66c5cfa 304
db8f9152 305 if(have.count("maxReceivedMBytes")) {
d122dac0 306 maxReceivedXFRMBytes = static_cast<size_t>(boost::get<uint32_t>(have["maxReceivedMBytes"]));
db8f9152 307 }
a66c5cfa 308
f6a8f7d7 309 if(have.count("localAddress")) {
d122dac0 310 localAddress = ComboAddress(boost::get<string>(have["localAddress"]));
f6a8f7d7 311 }
a66c5cfa 312
ea448a77 313 if(have.count("axfrTimeout")) {
d122dac0 314 axfrTimeout = static_cast<uint16_t>(boost::get<uint32_t>(have["axfrTimeout"]));
ea448a77 315 }
a66c5cfa
RG
316
317 if(have.count("seedFile")) {
d122dac0 318 seedFile = boost::get<std::string>(have["seedFile"]);
a66c5cfa 319 }
23f886c0
RG
320
321 if(have.count("dumpFile")) {
d122dac0 322 dumpFile = boost::get<std::string>(have["dumpFile"]);
23f886c0 323 }
563bbdca 324 }
a66c5cfa 325
5f311886
RG
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 }
6791663c
RG
333 }
334
a66c5cfa
RG
335 DNSName domain(zoneName);
336 zone->setDomain(domain);
6b972d59 337 zone->setName(polName);
6791663c 338 zone->setRefresh(refresh);
209955c7 339 zoneIdx = lci.dfe.addZone(zone);
a66c5cfa
RG
340
341 if (!seedFile.empty()) {
23f886c0
RG
342 g_log<<Logger::Info<<"Pre-loading RPZ zone "<<zoneName<<" from seed file '"<<seedFile<<"'"<<endl;
343 try {
d122dac0 344 sr = loadRPZFromFile(seedFile, zone, defpol, defpolOverrideLocal, maxTTL);
a66c5cfa 345
23f886c0
RG
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;
a66c5cfa
RG
356 }
357 }
ad42489c 358 }
6791663c 359 catch(const std::exception& e) {
e6a9dde5 360 g_log<<Logger::Error<<"Problem configuring 'rpzMaster': "<<e.what()<<endl;
209955c7 361 exit(1); // FIXME proper exit code?
ad42489c 362 }
6791663c 363 catch(const PDNSException& e) {
e6a9dde5 364 g_log<<Logger::Error<<"Problem configuring 'rpzMaster': "<<e.reason<<endl;
209955c7 365 exit(1); // FIXME proper exit code?
ad42489c 366 }
367
d122dac0 368 delayedThreads.rpzMasterThreads.push_back(std::make_tuple(masters, defpol, defpolOverrideLocal, maxTTL, zoneIdx, tt, maxReceivedXFRMBytes, localAddress, axfrTimeout, sr, dumpFile));
ad42489c 369 });
370
3e61e7f7 371 typedef vector<pair<int,boost::variant<string, vector<pair<int, string> > > > > argvec_t;
372 Lua.writeFunction("addSortList",
f3c18728 373 [&lci](const std::string& formask_,
3e61e7f7 374 const boost::variant<string, argvec_t>& masks,
375 boost::optional<int> order_)
376 {
377 try {
378 Netmask formask(formask_);
f3c18728 379 int order = order_ ? (*order_) : lci.sortlist.getMaxOrder(formask)+1;
3e61e7f7 380 if(auto str = boost::get<string>(&masks))
f3c18728 381 lci.sortlist.addEntry(formask, Netmask(*str), order);
3e61e7f7 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)) {
f3c18728 387 lci.sortlist.addEntry(formask, Netmask(*s), order);
3e61e7f7 388 }
389 else {
390 const auto& v =boost::get<vector<pair<int, string> > >(e.second);
dd079764
RG
391 for(const auto& entry : v)
392 lci.sortlist.addEntry(formask, Netmask(entry.second), order);
3e61e7f7 393 }
394 ++order;
395 }
396 }
397 }
398 catch(std::exception& e) {
e6a9dde5 399 g_log<<Logger::Error<<"Error in addSortList: "<<e.what()<<endl;
3e61e7f7 400 }
401 });
2ac8ae89 402
190e0d9a
PL
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);
32122aab 406 auto ds = std::dynamic_pointer_cast<DSRecordContent>(DSRecordContent::make(what));
190e0d9a
PL
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 */
2ac8ae89 419 Lua.writeFunction("addDS", [&lci](const std::string& who, const std::string& what) {
e48c6b8a 420 warnIfDNSSECDisabled("Warning: adding Trust Anchor for DNSSEC (addDS), but dnssec is set to 'off'!");
190e0d9a 421 g_log<<Logger::Warning<<"addDS is deprecated and will be removed in the future, switch to addTA"<<endl;
52ad9eea 422 DNSName zone(who);
32122aab 423 auto ds = std::dynamic_pointer_cast<DSRecordContent>(DSRecordContent::make(what));
64a4a928 424 lci.dsAnchors[zone].insert(*ds);
52ad9eea 425 });
2ac8ae89 426
190e0d9a 427 /* Remove in 4.3 */
2ac8ae89 428 Lua.writeFunction("clearDS", [&lci](boost::optional<string> who) {
190e0d9a 429 g_log<<Logger::Warning<<"clearDS is deprecated and will be removed in the future, switch to clearTA"<<endl;
e48c6b8a 430 warnIfDNSSECDisabled("Warning: removing Trust Anchor for DNSSEC (clearDS), but dnssec is set to 'off'!");
2ac8ae89 431 if(who)
432 lci.dsAnchors.erase(DNSName(*who));
433 else
434 lci.dsAnchors.clear();
435 });
436
1bd49828 437 Lua.writeFunction("addNTA", [&lci](const std::string& who, const boost::optional<std::string> why) {
e48c6b8a 438 warnIfDNSSECDisabled("Warning: adding Negative Trust Anchor for DNSSEC (addNTA), but dnssec is set to 'off'!");
1bd49828
PL
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) {
e48c6b8a 446 warnIfDNSSECDisabled("Warning: removing Negative Trust Anchor for DNSSEC (clearNTA), but dnssec is set to 'off'!");
1bd49828
PL
447 if(who)
448 lci.negAnchors.erase(DNSName(*who));
449 else
450 lci.negAnchors.clear();
451 });
452
e4ae55e5
PL
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);
8f29eeaa 457 }
e4ae55e5
PL
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);
8f29eeaa
PL
462 });
463
aa7929a3 464#if HAVE_PROTOBUF
f1c7929a
RG
465 Lua.writeFunction("setProtobufMasks", [&lci](const uint8_t maskV4, uint8_t maskV6) {
466 lci.protobufMaskV4 = maskV4;
467 lci.protobufMaskV6 = maskV6;
468 });
469
b773359c 470 Lua.writeFunction("protobufServer", [&lci](boost::variant<const std::string, const std::unordered_map<int, std::string>> servers, boost::optional<protobufOptions_t> vars) {
63341e8d 471 if (!lci.protobufExportConfig.enabled) {
b773359c 472
63341e8d 473 lci.protobufExportConfig.enabled = true;
b773359c
RG
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 }
aa7929a3
RG
496 }
497 else {
b773359c 498 g_log<<Logger::Error<<"Only one protobufServer() directive can be configured, we already have "<<lci.protobufExportConfig.servers.at(0).toString()<<endl;
aa7929a3 499 }
4898a348
RG
500 });
501
b773359c
RG
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 }
aa7929a3 528 }
b773359c
RG
529 else {
530 g_log<<Logger::Error<<"Only one outgoingProtobufServer() directive can be configured, we already have "<<lci.outgoingProtobufExportConfig.servers.at(0).toString()<<endl;
aa7929a3
RG
531 }
532 });
533#endif
534
b9fa43e0
OM
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
ad42489c 569 try {
570 Lua.executeCode(ifs);
571 g_luaconfs.setState(lci);
572 }
2ac8ae89 573 catch(const LuaContext::ExecutionErrorException& e) {
e6a9dde5 574 g_log<<Logger::Error<<"Unable to load Lua script from '"+fname+"': ";
2ac8ae89 575 try {
576 std::rethrow_if_nested(e);
dd079764
RG
577 } catch(const std::exception& exp) {
578 // exp is the exception that was thrown from inside the lambda
e6a9dde5 579 g_log << exp.what() << std::endl;
2ac8ae89 580 }
dd079764
RG
581 catch(const PDNSException& exp) {
582 // exp is the exception that was thrown from inside the lambda
e6a9dde5 583 g_log << exp.reason << std::endl;
2ac8ae89 584 }
585 throw;
586
587 }
ad42489c 588 catch(std::exception& err) {
e6a9dde5 589 g_log<<Logger::Error<<"Unable to load Lua script from '"+fname+"': "<<err.what()<<endl;
2ac8ae89 590 throw;
ad42489c 591 }
592
3e61e7f7 593}
6a99b9a4 594
e6ec15bf
RG
595void startLuaConfigDelayedThreads(const luaConfigDelayedThreads& delayedThreads, uint64_t generation)
596{
597 for (const auto& rpzMaster : delayedThreads.rpzMasterThreads) {
598 try {
d122dac0 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);
e6ec15bf
RG
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}