]>
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 | 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 | ||
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 | ||
d122dac0 | 54 | typedef std::unordered_map<std::string, boost::variant<bool, uint32_t, std::string > > rpzOptions_t; |
6a99b9a4 | 55 | |
d122dac0 | 56 | static 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 | 88 | typedef std::unordered_map<std::string, boost::variant<bool, uint64_t, std::string, std::vector<std::pair<int,std::string> > > > protobufOptions_t; |
f1c7929a RG |
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 | } | |
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 |
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 | } | |
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 | 185 | void 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 |
595 | void 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 | } |