]>
Commit | Line | Data |
---|---|---|
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 | 19 | GlobalStateHolder<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 | ||
34 | LuaConfigItems::LuaConfigItems() | |
35 | { | |
03bf7abb | 36 | DNSName root("."); // don't use g_rootdnsname here, it might not exist yet |
f2234140 PL |
37 | for (const auto &dsRecord : rootDSs) { |
38 | auto ds=unique_ptr<DSRecordContent>(dynamic_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 | ||
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 | ||
6a99b9a4 | 54 | |
8f618901 RG |
55 | static void parseRPZParameters(const std::unordered_map<string,boost::variant<uint32_t, string> >& have, std::string& polName, boost::optional<DNSFilterEngine::Policy>& defpol, uint32_t& maxTTL, size_t& zoneSizeHint) |
56 | { | |
57 | if(have.count("policyName")) { | |
58 | polName = boost::get<std::string>(constGet(have, "policyName")); | |
59 | } | |
60 | if(have.count("defpol")) { | |
61 | defpol=DNSFilterEngine::Policy(); | |
62 | defpol->d_kind = (DNSFilterEngine::PolicyKind)boost::get<uint32_t>(constGet(have, "defpol")); | |
63 | defpol->d_name = std::make_shared<std::string>(polName); | |
64 | if(defpol->d_kind == DNSFilterEngine::PolicyKind::Custom) { | |
65 | defpol->d_custom= | |
8f618901 RG |
66 | DNSRecordContent::mastermake(QType::CNAME, 1, |
67 | boost::get<string>(constGet(have,"defcontent")) | |
6177a176 | 68 | ); |
8f618901 RG |
69 | |
70 | if(have.count("defttl")) | |
71 | defpol->d_ttl = static_cast<int32_t>(boost::get<uint32_t>(constGet(have, "defttl"))); | |
72 | else | |
73 | defpol->d_ttl = -1; // get it from the zone | |
74 | } | |
75 | } | |
76 | if(have.count("maxTTL")) { | |
77 | maxTTL = boost::get<uint32_t>(constGet(have, "maxTTL")); | |
78 | } | |
79 | if(have.count("zoneSizeHint")) { | |
80 | zoneSizeHint = static_cast<size_t>(boost::get<uint32_t>(constGet(have, "zoneSizeHint"))); | |
81 | } | |
82 | } | |
83 | ||
f1c7929a RG |
84 | typedef std::unordered_map<std::string, boost::variant<bool, uint64_t, std::string> > protobufOptions_t; |
85 | ||
86 | static void parseProtobufOptions(boost::optional<protobufOptions_t> vars, ProtobufExportConfig& config) | |
87 | { | |
88 | if (!vars) { | |
89 | return; | |
90 | } | |
91 | ||
92 | if (vars->count("timeout")) { | |
93 | config.timeout = boost::get<uint64_t>((*vars)["timeout"]); | |
94 | } | |
95 | ||
96 | if (vars->count("maxQueuedEntries")) { | |
97 | config.maxQueuedEntries = boost::get<uint64_t>((*vars)["maxQueuedEntries"]); | |
98 | } | |
99 | ||
100 | if (vars->count("reconnectWaitTime")) { | |
101 | config.reconnectWaitTime = boost::get<uint64_t>((*vars)["reconnectWaitTime"]); | |
102 | } | |
103 | ||
104 | if (vars->count("asyncConnect")) { | |
105 | config.asyncConnect = boost::get<bool>((*vars)["asyncConnect"]); | |
106 | } | |
107 | ||
108 | if (vars->count("taggedOnly")) { | |
109 | config.taggedOnly = boost::get<bool>((*vars)["taggedOnly"]); | |
110 | } | |
111 | ||
112 | if (vars->count("logQueries")) { | |
113 | config.logQueries = boost::get<bool>((*vars)["logQueries"]); | |
114 | } | |
115 | ||
116 | if (vars->count("logResponses")) { | |
117 | config.logResponses = boost::get<bool>((*vars)["logResponses"]); | |
118 | } | |
119 | } | |
120 | ||
e6ec15bf | 121 | void loadRecursorLuaConfig(const std::string& fname, luaConfigDelayedThreads& delayedThreads) |
3e61e7f7 | 122 | { |
f3c18728 | 123 | LuaConfigItems lci; |
124 | ||
3e61e7f7 | 125 | LuaContext Lua; |
126 | if(fname.empty()) | |
127 | return; | |
128 | ifstream ifs(fname); | |
0f5785a6 PL |
129 | if(!ifs) |
130 | throw PDNSException("Cannot open file '"+fname+"': "+strerror(errno)); | |
131 | ||
63341e8d RG |
132 | auto luaconfsLocal = g_luaconfs.getLocal(); |
133 | lci.generation = luaconfsLocal->generation + 1; | |
134 | ||
f3c18728 | 135 | Lua.writeFunction("clearSortlist", [&lci]() { lci.sortlist.clear(); }); |
3e61e7f7 | 136 | |
137 | /* we can get: "1.2.3.4" | |
138 | {"1.2.3.4", "4.5.6.7"} | |
139 | {"1.2.3.4", {"4.5.6.7", "8.9.10.11"}} | |
140 | */ | |
141 | ||
ad42489c | 142 | map<string,DNSFilterEngine::PolicyKind> pmap{ |
143 | {"NoAction", DNSFilterEngine::PolicyKind::NoAction}, | |
144 | {"Drop", DNSFilterEngine::PolicyKind::Drop}, | |
145 | {"NXDOMAIN", DNSFilterEngine::PolicyKind::NXDOMAIN}, | |
146 | {"NODATA", DNSFilterEngine::PolicyKind::NODATA}, | |
147 | {"Truncate", DNSFilterEngine::PolicyKind::Truncate}, | |
148 | {"Custom", DNSFilterEngine::PolicyKind::Custom} | |
149 | }; | |
150 | Lua.writeVariable("Policy", pmap); | |
151 | ||
8f618901 | 152 | Lua.writeFunction("rpzFile", [&lci](const string& filename, const boost::optional<std::unordered_map<string,boost::variant<uint32_t, string>>>& options) { |
ad42489c | 153 | try { |
563bbdca RG |
154 | boost::optional<DNSFilterEngine::Policy> defpol; |
155 | std::string polName("rpzFile"); | |
6b972d59 | 156 | std::shared_ptr<DNSFilterEngine::Zone> zone = std::make_shared<DNSFilterEngine::Zone>(); |
563bbdca RG |
157 | uint32_t maxTTL = std::numeric_limits<uint32_t>::max(); |
158 | if(options) { | |
159 | auto& have = *options; | |
8f618901 RG |
160 | size_t zoneSizeHint = 0; |
161 | parseRPZParameters(have, polName, defpol, maxTTL, zoneSizeHint); | |
162 | if (zoneSizeHint > 0) { | |
6b972d59 | 163 | zone->reserve(zoneSizeHint); |
a2d0450e | 164 | } |
563bbdca | 165 | } |
e6a9dde5 | 166 | g_log<<Logger::Warning<<"Loading RPZ from file '"<<filename<<"'"<<endl; |
6b972d59 RG |
167 | zone->setName(polName); |
168 | loadRPZFromFile(filename, zone, defpol, maxTTL); | |
169 | lci.dfe.addZone(zone); | |
e6a9dde5 | 170 | g_log<<Logger::Warning<<"Done loading RPZ from file '"<<filename<<"'"<<endl; |
ad42489c | 171 | } |
6791663c | 172 | catch(const std::exception& e) { |
e6a9dde5 | 173 | g_log<<Logger::Error<<"Unable to load RPZ zone from '"<<filename<<"': "<<e.what()<<endl; |
ad42489c | 174 | } |
175 | }); | |
176 | ||
e6ec15bf | 177 | Lua.writeFunction("rpzMaster", [&lci, &delayedThreads](const boost::variant<string, std::vector<std::pair<int, string> > >& masters_, const string& zoneName, const boost::optional<std::unordered_map<string,boost::variant<uint32_t, string>>>& options) { |
209955c7 | 178 | |
179 | boost::optional<DNSFilterEngine::Policy> defpol; | |
180 | std::shared_ptr<DNSFilterEngine::Zone> zone = std::make_shared<DNSFilterEngine::Zone>(); | |
181 | TSIGTriplet tt; | |
182 | uint32_t refresh=0; | |
183 | size_t maxReceivedXFRMBytes = 0; | |
ea448a77 | 184 | uint16_t axfrTimeout = 20; |
209955c7 | 185 | uint32_t maxTTL = std::numeric_limits<uint32_t>::max(); |
186 | ComboAddress localAddress; | |
5f311886 RG |
187 | std::vector<ComboAddress> masters; |
188 | if (masters_.type() == typeid(string)) { | |
189 | masters.push_back(ComboAddress(boost::get<std::string>(masters_), 53)); | |
190 | } | |
191 | else { | |
192 | for (const auto& master : boost::get<std::vector<std::pair<int, std::string>>>(masters_)) { | |
193 | masters.push_back(ComboAddress(master.second, 53)); | |
194 | } | |
195 | } | |
196 | ||
209955c7 | 197 | size_t zoneIdx; |
23f886c0 | 198 | std::string dumpFile; |
a66c5cfa | 199 | std::shared_ptr<SOARecordContent> sr = nullptr; |
209955c7 | 200 | |
ad42489c | 201 | try { |
a66c5cfa | 202 | std::string seedFile; |
6b972d59 | 203 | std::string polName(zoneName); |
a66c5cfa RG |
204 | |
205 | if (options) { | |
563bbdca | 206 | auto& have = *options; |
8f618901 RG |
207 | size_t zoneSizeHint = 0; |
208 | parseRPZParameters(have, polName, defpol, maxTTL, zoneSizeHint); | |
209 | if (zoneSizeHint > 0) { | |
6b972d59 | 210 | zone->reserve(zoneSizeHint); |
a2d0450e | 211 | } |
a66c5cfa | 212 | |
563bbdca | 213 | if(have.count("tsigname")) { |
98c9ec39 | 214 | tt.name=DNSName(toLower(boost::get<string>(constGet(have, "tsigname")))); |
215 | tt.algo=DNSName(toLower(boost::get<string>(constGet(have, "tsigalgo")))); | |
216 | if(B64Decode(boost::get<string>(constGet(have, "tsigsecret")), tt.secret)) | |
217 | throw std::runtime_error("TSIG secret is not valid Base-64 encoded"); | |
218 | } | |
a66c5cfa | 219 | |
98c9ec39 | 220 | if(have.count("refresh")) { |
8f618901 | 221 | refresh = boost::get<uint32_t>(constGet(have,"refresh")); |
98c9ec39 | 222 | } |
a66c5cfa | 223 | |
db8f9152 | 224 | if(have.count("maxReceivedMBytes")) { |
8f618901 | 225 | maxReceivedXFRMBytes = static_cast<size_t>(boost::get<uint32_t>(constGet(have,"maxReceivedMBytes"))); |
db8f9152 | 226 | } |
a66c5cfa | 227 | |
f6a8f7d7 PL |
228 | if(have.count("localAddress")) { |
229 | localAddress = ComboAddress(boost::get<string>(constGet(have,"localAddress"))); | |
230 | } | |
a66c5cfa | 231 | |
ea448a77 PL |
232 | if(have.count("axfrTimeout")) { |
233 | axfrTimeout = static_cast<uint16_t>(boost::get<uint32_t>(constGet(have, "axfrTimeout"))); | |
234 | } | |
a66c5cfa RG |
235 | |
236 | if(have.count("seedFile")) { | |
237 | seedFile = boost::get<std::string>(constGet(have, "seedFile")); | |
238 | } | |
23f886c0 RG |
239 | |
240 | if(have.count("dumpFile")) { | |
241 | dumpFile = boost::get<std::string>(constGet(have, "dumpFile")); | |
242 | } | |
563bbdca | 243 | } |
a66c5cfa | 244 | |
5f311886 RG |
245 | if (localAddress != ComboAddress()) { |
246 | // We were passed a localAddress, check if its AF matches the masters' | |
247 | for (const auto& master : masters) { | |
248 | if (localAddress.sin4.sin_family != master.sin4.sin_family) { | |
249 | throw PDNSException("Master address("+master.toString()+") is not of the same Address Family as the local address ("+localAddress.toString()+")."); | |
250 | } | |
251 | } | |
6791663c RG |
252 | } |
253 | ||
a66c5cfa RG |
254 | DNSName domain(zoneName); |
255 | zone->setDomain(domain); | |
6b972d59 | 256 | zone->setName(polName); |
6791663c | 257 | zone->setRefresh(refresh); |
209955c7 | 258 | zoneIdx = lci.dfe.addZone(zone); |
a66c5cfa RG |
259 | |
260 | if (!seedFile.empty()) { | |
23f886c0 RG |
261 | g_log<<Logger::Info<<"Pre-loading RPZ zone "<<zoneName<<" from seed file '"<<seedFile<<"'"<<endl; |
262 | try { | |
263 | sr = loadRPZFromFile(seedFile, zone, defpol, maxTTL); | |
a66c5cfa | 264 | |
23f886c0 RG |
265 | if (zone->getDomain() != domain) { |
266 | throw PDNSException("The RPZ zone " + zoneName + " loaded from the seed file (" + zone->getDomain().toString() + ") does not match the one passed in parameter (" + domain.toString() + ")"); | |
267 | } | |
268 | ||
269 | if (sr == nullptr) { | |
270 | throw PDNSException("The RPZ zone " + zoneName + " loaded from the seed file (" + zone->getDomain().toString() + ") has no SOA record"); | |
271 | } | |
272 | } | |
273 | catch(const std::exception& e) { | |
274 | g_log<<Logger::Warning<<"Unable to pre-load RPZ zone "<<zoneName<<" from seed file '"<<seedFile<<"': "<<e.what()<<endl; | |
a66c5cfa RG |
275 | } |
276 | } | |
ad42489c | 277 | } |
6791663c | 278 | catch(const std::exception& e) { |
e6a9dde5 | 279 | g_log<<Logger::Error<<"Problem configuring 'rpzMaster': "<<e.what()<<endl; |
209955c7 | 280 | exit(1); // FIXME proper exit code? |
ad42489c | 281 | } |
6791663c | 282 | catch(const PDNSException& e) { |
e6a9dde5 | 283 | g_log<<Logger::Error<<"Problem configuring 'rpzMaster': "<<e.reason<<endl; |
209955c7 | 284 | exit(1); // FIXME proper exit code? |
ad42489c | 285 | } |
286 | ||
e6ec15bf | 287 | delayedThreads.rpzMasterThreads.push_back(std::make_tuple(masters, defpol, maxTTL, zoneIdx, tt, maxReceivedXFRMBytes, localAddress, axfrTimeout, sr, dumpFile)); |
ad42489c | 288 | }); |
289 | ||
3e61e7f7 | 290 | typedef vector<pair<int,boost::variant<string, vector<pair<int, string> > > > > argvec_t; |
291 | Lua.writeFunction("addSortList", | |
f3c18728 | 292 | [&lci](const std::string& formask_, |
3e61e7f7 | 293 | const boost::variant<string, argvec_t>& masks, |
294 | boost::optional<int> order_) | |
295 | { | |
296 | try { | |
297 | Netmask formask(formask_); | |
f3c18728 | 298 | int order = order_ ? (*order_) : lci.sortlist.getMaxOrder(formask)+1; |
3e61e7f7 | 299 | if(auto str = boost::get<string>(&masks)) |
f3c18728 | 300 | lci.sortlist.addEntry(formask, Netmask(*str), order); |
3e61e7f7 | 301 | else { |
302 | ||
303 | auto vec = boost::get<argvec_t>(&masks); | |
304 | for(const auto& e : *vec) { | |
305 | if(auto s = boost::get<string>(&e.second)) { | |
f3c18728 | 306 | lci.sortlist.addEntry(formask, Netmask(*s), order); |
3e61e7f7 | 307 | } |
308 | else { | |
309 | const auto& v =boost::get<vector<pair<int, string> > >(e.second); | |
dd079764 RG |
310 | for(const auto& entry : v) |
311 | lci.sortlist.addEntry(formask, Netmask(entry.second), order); | |
3e61e7f7 | 312 | } |
313 | ++order; | |
314 | } | |
315 | } | |
316 | } | |
317 | catch(std::exception& e) { | |
e6a9dde5 | 318 | g_log<<Logger::Error<<"Error in addSortList: "<<e.what()<<endl; |
3e61e7f7 | 319 | } |
320 | }); | |
2ac8ae89 | 321 | |
322 | Lua.writeFunction("addDS", [&lci](const std::string& who, const std::string& what) { | |
e48c6b8a | 323 | warnIfDNSSECDisabled("Warning: adding Trust Anchor for DNSSEC (addDS), but dnssec is set to 'off'!"); |
52ad9eea | 324 | DNSName zone(who); |
52ad9eea | 325 | auto ds = unique_ptr<DSRecordContent>(dynamic_cast<DSRecordContent*>(DSRecordContent::make(what))); |
64a4a928 | 326 | lci.dsAnchors[zone].insert(*ds); |
52ad9eea | 327 | }); |
2ac8ae89 | 328 | |
329 | Lua.writeFunction("clearDS", [&lci](boost::optional<string> who) { | |
e48c6b8a | 330 | warnIfDNSSECDisabled("Warning: removing Trust Anchor for DNSSEC (clearDS), but dnssec is set to 'off'!"); |
2ac8ae89 | 331 | if(who) |
332 | lci.dsAnchors.erase(DNSName(*who)); | |
333 | else | |
334 | lci.dsAnchors.clear(); | |
335 | }); | |
336 | ||
1bd49828 | 337 | Lua.writeFunction("addNTA", [&lci](const std::string& who, const boost::optional<std::string> why) { |
e48c6b8a | 338 | warnIfDNSSECDisabled("Warning: adding Negative Trust Anchor for DNSSEC (addNTA), but dnssec is set to 'off'!"); |
1bd49828 PL |
339 | if(why) |
340 | lci.negAnchors[DNSName(who)] = static_cast<string>(*why); | |
341 | else | |
342 | lci.negAnchors[DNSName(who)] = ""; | |
343 | }); | |
344 | ||
345 | Lua.writeFunction("clearNTA", [&lci](boost::optional<string> who) { | |
e48c6b8a | 346 | warnIfDNSSECDisabled("Warning: removing Negative Trust Anchor for DNSSEC (clearNTA), but dnssec is set to 'off'!"); |
1bd49828 PL |
347 | if(who) |
348 | lci.negAnchors.erase(DNSName(*who)); | |
349 | else | |
350 | lci.negAnchors.clear(); | |
351 | }); | |
352 | ||
aa7929a3 | 353 | #if HAVE_PROTOBUF |
f1c7929a RG |
354 | Lua.writeFunction("setProtobufMasks", [&lci](const uint8_t maskV4, uint8_t maskV6) { |
355 | lci.protobufMaskV4 = maskV4; | |
356 | lci.protobufMaskV6 = maskV6; | |
357 | }); | |
358 | ||
359 | Lua.writeFunction("protobufServer", [&lci](const string& server_, boost::optional<protobufOptions_t> vars) { | |
aa7929a3 | 360 | try { |
63341e8d | 361 | if (!lci.protobufExportConfig.enabled) { |
63341e8d | 362 | lci.protobufExportConfig.enabled = true; |
f1c7929a RG |
363 | lci.protobufExportConfig.server = ComboAddress(server_); |
364 | parseProtobufOptions(vars, lci.protobufExportConfig); | |
aa7929a3 RG |
365 | } |
366 | else { | |
63341e8d | 367 | g_log<<Logger::Error<<"Only one protobuf server can be configured, we already have "<<lci.protobufExportConfig.server.toString()<<endl; |
aa7929a3 RG |
368 | } |
369 | } | |
4898a348 | 370 | catch(std::exception& e) { |
e6a9dde5 | 371 | g_log<<Logger::Error<<"Error while starting protobuf logger to '"<<server_<<": "<<e.what()<<endl; |
4898a348 RG |
372 | } |
373 | catch(PDNSException& e) { | |
e6a9dde5 | 374 | g_log<<Logger::Error<<"Error while starting protobuf logger to '"<<server_<<": "<<e.reason<<endl; |
4898a348 RG |
375 | } |
376 | }); | |
377 | ||
f1c7929a | 378 | Lua.writeFunction("outgoingProtobufServer", [&lci](const string& server_, boost::optional<protobufOptions_t> vars) { |
4898a348 | 379 | try { |
63341e8d | 380 | if (!lci.outgoingProtobufExportConfig.enabled) { |
63341e8d | 381 | lci.outgoingProtobufExportConfig.enabled = true; |
f1c7929a RG |
382 | lci.protobufExportConfig.server = ComboAddress(server_); |
383 | parseProtobufOptions(vars, lci.protobufExportConfig); | |
4898a348 RG |
384 | } |
385 | else { | |
63341e8d | 386 | g_log<<Logger::Error<<"Only one protobuf server can be configured, we already have "<<lci.outgoingProtobufExportConfig.server.toString()<<endl; |
4898a348 RG |
387 | } |
388 | } | |
aa7929a3 | 389 | catch(std::exception& e) { |
e6a9dde5 | 390 | g_log<<Logger::Error<<"Error while starting protobuf logger to '"<<server_<<": "<<e.what()<<endl; |
aa7929a3 RG |
391 | } |
392 | catch(PDNSException& e) { | |
e6a9dde5 | 393 | g_log<<Logger::Error<<"Error while starting protobuf logger to '"<<server_<<": "<<e.reason<<endl; |
aa7929a3 RG |
394 | } |
395 | }); | |
396 | #endif | |
397 | ||
ad42489c | 398 | try { |
399 | Lua.executeCode(ifs); | |
400 | g_luaconfs.setState(lci); | |
401 | } | |
2ac8ae89 | 402 | catch(const LuaContext::ExecutionErrorException& e) { |
e6a9dde5 | 403 | g_log<<Logger::Error<<"Unable to load Lua script from '"+fname+"': "; |
2ac8ae89 | 404 | try { |
405 | std::rethrow_if_nested(e); | |
dd079764 RG |
406 | } catch(const std::exception& exp) { |
407 | // exp is the exception that was thrown from inside the lambda | |
e6a9dde5 | 408 | g_log << exp.what() << std::endl; |
2ac8ae89 | 409 | } |
dd079764 RG |
410 | catch(const PDNSException& exp) { |
411 | // exp is the exception that was thrown from inside the lambda | |
e6a9dde5 | 412 | g_log << exp.reason << std::endl; |
2ac8ae89 | 413 | } |
414 | throw; | |
415 | ||
416 | } | |
ad42489c | 417 | catch(std::exception& err) { |
e6a9dde5 | 418 | g_log<<Logger::Error<<"Unable to load Lua script from '"+fname+"': "<<err.what()<<endl; |
2ac8ae89 | 419 | throw; |
ad42489c | 420 | } |
421 | ||
3e61e7f7 | 422 | } |
6a99b9a4 | 423 | |
e6ec15bf RG |
424 | void startLuaConfigDelayedThreads(const luaConfigDelayedThreads& delayedThreads, uint64_t generation) |
425 | { | |
426 | for (const auto& rpzMaster : delayedThreads.rpzMasterThreads) { | |
427 | try { | |
428 | 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) * 1024 * 1024, std::get<6>(rpzMaster), std::get<7>(rpzMaster), std::get<8>(rpzMaster), std::get<9>(rpzMaster), generation); | |
429 | t.detach(); | |
430 | } | |
431 | catch(const std::exception& e) { | |
432 | g_log<<Logger::Error<<"Problem starting RPZIXFRTracker thread: "<<e.what()<<endl; | |
433 | exit(1); // FIXME proper exit code? | |
434 | } | |
435 | catch(const PDNSException& e) { | |
436 | g_log<<Logger::Error<<"Problem starting RPZIXFRTracker thread: "<<e.reason<<endl; | |
437 | exit(1); // FIXME proper exit code? | |
438 | } | |
439 | } | |
440 | } |