• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PowerDNS / pdns / 15920880335

26 Jun 2025 03:30PM UTC coverage: 61.923% (-3.7%) from 65.652%
15920880335

push

github

web-flow
Merge pull request #15669 from miodvallat/serial_keyer

Increase zone serial number after zone key operations

38311 of 91850 branches covered (41.71%)

Branch coverage included in aggregate %.

27 of 29 new or added lines in 1 file covered. (93.1%)

6308 existing lines in 78 files now uncovered.

120482 of 164587 relevant lines covered (73.2%)

5965233.22 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.96
/pdns/recursordist/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 "lua-base4.hh"
9
#include "rec-lua-conf.hh"
10
#include "sortlist.hh"
11
#include "filterpo.hh"
12
#include "syncres.hh"
13
#include "rpzloader.hh"
14
#include "base64.hh"
15
#include "remote_logger.hh"
16
#include "validate.hh"
17
#include "validate-recursor.hh"
18
#include "root-dnssec.hh"
19
#include "rec-system-resolve.hh"
20

21
GlobalStateHolder<LuaConfigItems> g_luaconfs;
22

23
/* SO HOW DOES THIS WORK! AND PLEASE PAY ATTENTION!
24
   This function can be called at any time. It is expected to overwrite all the contents
25
   of LuaConfigItems, which is held in a GlobalStateHolder for RCU properties.
26

27
   This function can be called again at a later date, so you must make sure that anything you
28
   allow to be configured from here lives in g_luaconfs AND NOWHERE ELSE.
29

30
   If someone loads an empty Lua file, the default LuaConfigItems struct MUST MAKE SENSE.
31

32
   To make this easy on you, here is a LuaConfigItems constructor where you
33
   can set sane defaults:
34
*/
35

36
LuaConfigItems::LuaConfigItems()
37
{
105✔
38
  DNSName root("."); // don't use g_rootdnsname here, it might not exist yet
105✔
39
  for (const auto& dsRecord : rootDSs) {
210✔
40
    auto dsRecContent = std::dynamic_pointer_cast<DSRecordContent>(DSRecordContent::make(dsRecord));
210✔
41
    dsAnchors[root].emplace(*dsRecContent);
210✔
42
  }
210✔
43
}
105✔
44

45
/* DID YOU READ THE STORY ABOVE? */
46

47
bool operator==(const ProtobufExportConfig& configA, const ProtobufExportConfig& configB)
UNCOV
48
{
×
49
  // clang-format off
UNCOV
50
  return configA.exportTypes          == configB.exportTypes       &&
×
UNCOV
51
         configA.servers              == configB.servers           &&
×
UNCOV
52
         configA.maxQueuedEntries     == configB.maxQueuedEntries  &&
×
UNCOV
53
         configA.timeout              == configB.timeout           &&
×
UNCOV
54
         configA.reconnectWaitTime    == configB.reconnectWaitTime &&
×
UNCOV
55
         configA.asyncConnect         == configB.asyncConnect      &&
×
UNCOV
56
         configA.enabled              == configB.enabled           &&
×
UNCOV
57
         configA.logQueries           == configB.logQueries        &&
×
UNCOV
58
         configA.logResponses         == configB.logResponses      &&
×
UNCOV
59
         configA.taggedOnly           == configB.taggedOnly        &&
×
UNCOV
60
         configA.logMappedFrom        == configB.logMappedFrom;
×
61
  // clang-format on
UNCOV
62
}
×
63

64
bool operator!=(const ProtobufExportConfig& configA, const ProtobufExportConfig& configB)
UNCOV
65
{
×
UNCOV
66
  return !(configA == configB);
×
UNCOV
67
}
×
68

69
bool operator==(const FrameStreamExportConfig& configA, const FrameStreamExportConfig& configB)
UNCOV
70
{
×
71
  // clang-format off
UNCOV
72
  return configA.enabled              == configB.enabled              &&
×
UNCOV
73
         configA.logQueries           == configB.logQueries           &&
×
UNCOV
74
         configA.logResponses         == configB.logResponses         &&
×
UNCOV
75
         configA.logNODs              == configB.logNODs              &&
×
UNCOV
76
         configA.logUDRs              == configB.logUDRs              &&
×
UNCOV
77
         configA.bufferHint           == configB.bufferHint           &&
×
UNCOV
78
         configA.flushTimeout         == configB.flushTimeout         &&
×
UNCOV
79
         configA.inputQueueSize       == configB.inputQueueSize       &&
×
UNCOV
80
         configA.outputQueueSize      == configB.outputQueueSize      &&
×
UNCOV
81
         configA.queueNotifyThreshold == configB.queueNotifyThreshold &&
×
UNCOV
82
         configA.reopenInterval       == configB.reopenInterval       &&
×
UNCOV
83
         configA.servers              == configB.servers;
×
84
  // clang-format on
UNCOV
85
}
×
86

87
bool operator!=(const FrameStreamExportConfig& configA, const FrameStreamExportConfig& configB)
UNCOV
88
{
×
UNCOV
89
  return !(configA == configB);
×
UNCOV
90
}
×
91

92
template <typename C>
93
typename C::value_type::second_type constGet(const C& c, const std::string& name)
94
{
95
  auto iter = c.find(name);
96
  if (iter == c.end())
97
    return 0;
98
  return iter->second;
99
}
100

101
typedef std::unordered_map<std::string, boost::variant<bool, uint32_t, std::string, std::vector<std::pair<int, std::string>>>> rpzOptions_t;
102

103
static void parseRPZParameters(const rpzOptions_t& have, RPZTrackerParams& params)
UNCOV
104
{
×
UNCOV
105
  if (have.count("policyName") != 0) {
×
UNCOV
106
    params.polName = boost::get<std::string>(have.at("policyName"));
×
UNCOV
107
  }
×
UNCOV
108
  if (have.count("defpol") != 0) {
×
UNCOV
109
    params.defpol = DNSFilterEngine::Policy();
×
UNCOV
110
    params.defpol->d_kind = (DNSFilterEngine::PolicyKind)boost::get<uint32_t>(have.at("defpol"));
×
UNCOV
111
    params.defpol->setName(params.polName);
×
UNCOV
112
    if (params.defpol->d_kind == DNSFilterEngine::PolicyKind::Custom) {
×
113
      params.defcontent = boost::get<string>(have.at("defcontent"));
×
114
      if (!params.defpol->d_custom) {
×
115
        params.defpol->d_custom = make_unique<DNSFilterEngine::Policy::CustomData>();
×
116
      }
×
117
      params.defpol->d_custom->push_back(DNSRecordContent::make(QType::CNAME, QClass::IN,
×
118
                                                                params.defcontent));
×
119

120
      if (have.count("defttl") != 0) {
×
121
        params.defpol->d_ttl = static_cast<int32_t>(boost::get<uint32_t>(have.at("defttl")));
×
122
      }
×
123
      else {
×
124
        params.defpol->d_ttl = -1; // get it from the zone
×
125
      }
×
126
    }
×
127

UNCOV
128
    if (have.count("defpolOverrideLocalData") != 0) {
×
UNCOV
129
      params.defpolOverrideLocal = boost::get<bool>(have.at("defpolOverrideLocalData"));
×
UNCOV
130
    }
×
UNCOV
131
  }
×
UNCOV
132
  if (have.count("maxTTL") != 0) {
×
133
    params.maxTTL = boost::get<uint32_t>(have.at("maxTTL"));
×
134
  }
×
UNCOV
135
  if (have.count("zoneSizeHint") != 0) {
×
136
    params.zoneXFRParams.zoneSizeHint = static_cast<size_t>(boost::get<uint32_t>(have.at("zoneSizeHint")));
×
137
  }
×
UNCOV
138
  if (have.count("tags") != 0) {
×
UNCOV
139
    const auto& tagsTable = boost::get<std::vector<std::pair<int, std::string>>>(have.at("tags"));
×
UNCOV
140
    std::unordered_set<std::string> tags;
×
UNCOV
141
    for (const auto& tag : tagsTable) {
×
UNCOV
142
      tags.insert(tag.second);
×
UNCOV
143
      params.tags.insert(tag.second);
×
UNCOV
144
    }
×
UNCOV
145
  }
×
UNCOV
146
  if (have.count("overridesGettag") != 0) {
×
147
    params.defpolOverrideLocal = boost::get<bool>(have.at("overridesGettag"));
×
148
  }
×
UNCOV
149
  if (have.count("extendedErrorCode") != 0) {
×
UNCOV
150
    auto code = boost::get<uint32_t>(have.at("extendedErrorCode"));
×
UNCOV
151
    if (code > std::numeric_limits<uint16_t>::max()) {
×
152
      throw std::runtime_error("Invalid extendedErrorCode value " + std::to_string(code) + " in RPZ configuration");
×
153
    }
×
UNCOV
154
    params.extendedErrorCode = code;
×
UNCOV
155
    if (have.count("extendedErrorExtra") != 0) {
×
UNCOV
156
      params.extendedErrorExtra = boost::get<std::string>(have.at("extendedErrorExtra"));
×
UNCOV
157
    }
×
UNCOV
158
  }
×
UNCOV
159
  if (have.count("includeSOA") != 0) {
×
UNCOV
160
    params.includeSOA = boost::get<bool>(have.at("includeSOA"));
×
UNCOV
161
  }
×
UNCOV
162
  if (have.count("ignoreDuplicates") != 0) {
×
163
    params.ignoreDuplicates = boost::get<bool>(have.at("ignoreDuplicates"));
×
164
  }
×
UNCOV
165
}
×
166

167
typedef std::unordered_map<std::string, boost::variant<bool, uint64_t, std::string, std::vector<std::pair<int, std::string>>>> protobufOptions_t;
168

169
static void parseProtobufOptions(const boost::optional<protobufOptions_t>& vars, ProtobufExportConfig& config)
UNCOV
170
{
×
UNCOV
171
  if (!vars) {
×
UNCOV
172
    return;
×
UNCOV
173
  }
×
UNCOV
174
  const auto& have = *vars;
×
175

UNCOV
176
  if (have.count("timeout") != 0) {
×
177
    config.timeout = boost::get<uint64_t>(have.at("timeout"));
×
178
  }
×
179

UNCOV
180
  if (have.count("maxQueuedEntries") != 0) {
×
181
    config.maxQueuedEntries = boost::get<uint64_t>(have.at("maxQueuedEntries"));
×
182
  }
×
183

UNCOV
184
  if (have.count("reconnectWaitTime") != 0) {
×
185
    config.reconnectWaitTime = boost::get<uint64_t>(have.at("reconnectWaitTime"));
×
186
  }
×
187

UNCOV
188
  if (have.count("asyncConnect") != 0) {
×
189
    config.asyncConnect = boost::get<bool>(have.at("asyncConnect"));
×
190
  }
×
191

UNCOV
192
  if (have.count("taggedOnly") != 0) {
×
UNCOV
193
    config.taggedOnly = boost::get<bool>(have.at("taggedOnly"));
×
UNCOV
194
  }
×
195

UNCOV
196
  if (have.count("logQueries") != 0) {
×
UNCOV
197
    config.logQueries = boost::get<bool>(have.at("logQueries"));
×
UNCOV
198
  }
×
199

UNCOV
200
  if (have.count("logResponses") != 0) {
×
UNCOV
201
    config.logResponses = boost::get<bool>(have.at("logResponses"));
×
UNCOV
202
  }
×
203

UNCOV
204
  if (have.count("logMappedFrom") != 0) {
×
UNCOV
205
    config.logMappedFrom = boost::get<bool>(have.at("logMappedFrom"));
×
UNCOV
206
  }
×
207

UNCOV
208
  if (have.count("exportTypes") != 0) {
×
UNCOV
209
    config.exportTypes.clear();
×
210

UNCOV
211
    auto types = boost::get<std::vector<std::pair<int, std::string>>>(have.at("exportTypes"));
×
UNCOV
212
    for (const auto& pair : types) {
×
UNCOV
213
      const auto& type = pair.second;
×
214

UNCOV
215
      QType qtype;
×
UNCOV
216
      try {
×
UNCOV
217
        qtype = std::stoul(type);
×
UNCOV
218
      }
×
UNCOV
219
      catch (const std::exception& ex) {
×
UNCOV
220
        qtype = QType::chartocode(type.c_str());
×
UNCOV
221
        if (qtype == 0) {
×
222
          throw std::runtime_error("Unknown QType '" + type + "' in protobuf's export types");
×
223
        }
×
UNCOV
224
      }
×
UNCOV
225
      config.exportTypes.insert(qtype);
×
UNCOV
226
    }
×
UNCOV
227
  }
×
UNCOV
228
}
×
229

230
#ifdef HAVE_FSTRM
231
typedef std::unordered_map<std::string, boost::variant<bool, uint64_t, std::string, std::vector<std::pair<int, std::string>>>> frameStreamOptions_t;
232

233
static void parseFrameStreamOptions(const boost::optional<frameStreamOptions_t>& vars, FrameStreamExportConfig& config)
UNCOV
234
{
×
UNCOV
235
  if (!vars) {
×
UNCOV
236
    return;
×
UNCOV
237
  }
×
UNCOV
238
  const auto& have = *vars;
×
239

UNCOV
240
  if (have.count("logQueries") != 0) {
×
UNCOV
241
    config.logQueries = boost::get<bool>(have.at("logQueries"));
×
UNCOV
242
  }
×
UNCOV
243
  if (have.count("logResponses") != 0) {
×
244
    config.logResponses = boost::get<bool>(have.at("logResponses"));
×
245
  }
×
UNCOV
246
  if (have.count("logNODs") != 0) {
×
UNCOV
247
    config.logNODs = boost::get<bool>(have.at("logNODs"));
×
UNCOV
248
  }
×
UNCOV
249
  if (have.count("logUDRs") != 0) {
×
UNCOV
250
    config.logUDRs = boost::get<bool>(have.at("logUDRs"));
×
UNCOV
251
  }
×
252

UNCOV
253
  if (have.count("bufferHint") != 0) {
×
254
    config.bufferHint = boost::get<uint64_t>(have.at("bufferHint"));
×
255
  }
×
UNCOV
256
  if (have.count("flushTimeout") != 0) {
×
257
    config.flushTimeout = boost::get<uint64_t>(have.at("flushTimeout"));
×
258
  }
×
UNCOV
259
  if (have.count("inputQueueSize") != 0) {
×
260
    config.inputQueueSize = boost::get<uint64_t>(have.at("inputQueueSize"));
×
261
  }
×
UNCOV
262
  if (have.count("outputQueueSize") != 0) {
×
263
    config.outputQueueSize = boost::get<uint64_t>(have.at("outputQueueSize"));
×
264
  }
×
UNCOV
265
  if (have.count("queueNotifyThreshold") != 0) {
×
266
    config.queueNotifyThreshold = boost::get<uint64_t>(have.at("queueNotifyThreshold"));
×
267
  }
×
UNCOV
268
  if (have.count("reopenInterval") != 0) {
×
269
    config.reopenInterval = boost::get<uint64_t>(have.at("reopenInterval"));
×
270
  }
×
UNCOV
271
}
×
272
#endif /* HAVE_FSTRM */
273

274
static void rpzPrimary(LuaConfigItems& lci, const boost::variant<string, std::vector<std::pair<int, string>>>& primaries_, const string& zoneName, const boost::optional<rpzOptions_t>& options)
UNCOV
275
{
×
UNCOV
276
  RPZTrackerParams params;
×
UNCOV
277
  params.zoneXFRParams.name = zoneName;
×
UNCOV
278
  params.polName = zoneName;
×
279

UNCOV
280
  std::shared_ptr<DNSFilterEngine::Zone> zone = std::make_shared<DNSFilterEngine::Zone>();
×
UNCOV
281
  if (primaries_.type() == typeid(string)) {
×
282
    params.zoneXFRParams.primaries.emplace_back(boost::get<std::string>(primaries_));
×
283
  }
×
UNCOV
284
  else {
×
UNCOV
285
    for (const auto& primary : boost::get<std::vector<std::pair<int, std::string>>>(primaries_)) {
×
UNCOV
286
      params.zoneXFRParams.primaries.emplace_back(primary.second);
×
UNCOV
287
    }
×
UNCOV
288
  }
×
289

UNCOV
290
  try {
×
UNCOV
291
    if (options) {
×
UNCOV
292
      auto& have = *options;
×
UNCOV
293
      parseRPZParameters(have, params);
×
294

UNCOV
295
      if (have.count("tsigname") != 0) {
×
296
        params.zoneXFRParams.tsigtriplet.name = DNSName(toLower(boost::get<string>(have.at("tsigname"))));
×
297
        params.zoneXFRParams.tsigtriplet.algo = DNSName(toLower(boost::get<string>(have.at("tsigalgo"))));
×
298
        if (B64Decode(boost::get<string>(have.at("tsigsecret")), params.zoneXFRParams.tsigtriplet.secret) != 0) {
×
299
          throw std::runtime_error("TSIG secret is not valid Base-64 encoded");
×
300
        }
×
301
      }
×
UNCOV
302
      if (have.count("refresh") != 0) {
×
UNCOV
303
        params.zoneXFRParams.refreshFromConf = boost::get<uint32_t>(have.at("refresh"));
×
UNCOV
304
        if (params.zoneXFRParams.refreshFromConf == 0) {
×
305
          SLOG(g_log << Logger::Warning << "rpzPrimary refresh value of 0 ignored" << endl,
×
306
               lci.d_slog->info(Logr::Warning, "rpzPrimary refresh value of 0 ignored"));
×
307
        }
×
UNCOV
308
      }
×
309

UNCOV
310
      if (have.count("maxReceivedMBytes") != 0) {
×
311
        params.zoneXFRParams.maxReceivedMBytes = static_cast<size_t>(boost::get<uint32_t>(have.at("maxReceivedMBytes")));
×
312
      }
×
313

UNCOV
314
      if (have.count("localAddress") != 0) {
×
315
        params.zoneXFRParams.localAddress = ComboAddress(boost::get<string>(have.at("localAddress")));
×
316
      }
×
317

UNCOV
318
      if (have.count("axfrTimeout") != 0) {
×
319
        params.zoneXFRParams.xfrTimeout = static_cast<uint16_t>(boost::get<uint32_t>(have.at("axfrTimeout")));
×
320
      }
×
321

UNCOV
322
      if (have.count("seedFile") != 0) {
×
323
        params.seedFileName = boost::get<std::string>(have.at("seedFile"));
×
324
      }
×
325

UNCOV
326
      if (have.count("dumpFile") != 0) {
×
UNCOV
327
        params.dumpZoneFileName = boost::get<std::string>(have.at("dumpFile"));
×
UNCOV
328
      }
×
UNCOV
329
    }
×
330

UNCOV
331
    if (params.zoneXFRParams.localAddress != ComboAddress()) {
×
332
      // We were passed a localAddress, check if its AF matches the primaries'
333
      for (const auto& nameOrIP : params.zoneXFRParams.primaries) {
×
334
        auto primary = pdns::fromNameOrIP(nameOrIP, 53, lci.d_slog);
×
335
        if (params.zoneXFRParams.localAddress.sin4.sin_family != primary.sin4.sin_family) {
×
336
          throw PDNSException("Primary address(" + primary.toString() + ") is not of the same Address Family as the local address (" + params.zoneXFRParams.localAddress.toString() + ").");
×
337
        }
×
338
      }
×
339
    }
×
UNCOV
340
    lci.rpzs.emplace_back(params);
×
UNCOV
341
  }
×
UNCOV
342
  catch (const std::exception& e) {
×
343
    SLOG(g_log << Logger::Error << "Problem configuring 'rpzPrimary': " << e.what() << endl,
×
344
         lci.d_slog->error(Logr::Error, e.what(), "Exception configuring 'rpzPrimary'", "exception", Logging::Loggable("std::exception")));
×
345
  }
×
UNCOV
346
  catch (const PDNSException& e) {
×
347
    SLOG(g_log << Logger::Error << "Problem configuring 'rpzPrimary': " << e.reason << endl,
×
348
         lci.d_slog->error(Logr::Error, e.reason, "Exception configuring 'rpzPrimary'", Logging::Loggable("PDNSException")));
×
349
  }
×
UNCOV
350
}
×
351

352
// A wrapper class that loads the standard Lua defintions into the context, so that we can use things like pdns.A
353
class RecLuaConfigContext : public BaseLua4
354
{
355
public:
356
  RecLuaConfigContext() :
357
    BaseLua4("")
UNCOV
358
  {
×
UNCOV
359
    prepareContext();
×
UNCOV
360
  }
×
361
  void postPrepareContext() override
UNCOV
362
  {
×
363
    // clang-format off
UNCOV
364
    d_pd.push_back({"AdditionalMode", in_t{
×
UNCOV
365
          {"Ignore", static_cast<int>(AdditionalMode::Ignore)},
×
UNCOV
366
          {"CacheOnly", static_cast<int>(AdditionalMode::CacheOnly)},
×
UNCOV
367
          {"CacheOnlyRequireAuth", static_cast<int>(AdditionalMode::CacheOnlyRequireAuth)},
×
UNCOV
368
          {"ResolveImmediately", static_cast<int>(AdditionalMode::ResolveImmediately)},
×
UNCOV
369
          {"ResolveDeferred", static_cast<int>(AdditionalMode::ResolveDeferred)}
×
UNCOV
370
        }});
×
UNCOV
371
  }
×
372
  void postLoad() override
373
  {
×
374
  }
×
375
  LuaContext* operator->()
UNCOV
376
  {
×
UNCOV
377
    return d_lw.get();
×
UNCOV
378
  }
×
379
};
380

381
void loadRecursorLuaConfig(const std::string& fname, ProxyMapping& proxyMapping, LuaConfigItems& newLuaConfig) // NOLINT(readability-function-cognitive-complexity)
UNCOV
382
{
×
UNCOV
383
  LuaConfigItems lci;
×
UNCOV
384
  if (g_slog) {
×
UNCOV
385
    lci.d_slog = g_slog->withName("luaconfig");
×
UNCOV
386
  }
×
387

UNCOV
388
  RecLuaConfigContext Lua;
×
389

UNCOV
390
  if (fname.empty())
×
391
    return;
×
UNCOV
392
  ifstream ifs(fname);
×
UNCOV
393
  if (!ifs)
×
394
    throw PDNSException("Cannot open file '" + fname + "': " + stringerror());
×
395

UNCOV
396
  auto luaconfsLocal = g_luaconfs.getLocal();
×
UNCOV
397
  lci.generation = luaconfsLocal->generation + 1;
×
398

UNCOV
399
  Lua->writeFunction("clearSortlist", [&lci]() { lci.sortlist.clear(); });
×
400

401
  /* we can get: "1.2.3.4"
402
                 {"1.2.3.4", "4.5.6.7"}
403
                 {"1.2.3.4", {"4.5.6.7", "8.9.10.11"}}
404
  */
405

UNCOV
406
  map<string, DNSFilterEngine::PolicyKind> pmap{
×
UNCOV
407
    {"NoAction", DNSFilterEngine::PolicyKind::NoAction},
×
UNCOV
408
    {"Drop", DNSFilterEngine::PolicyKind::Drop},
×
UNCOV
409
    {"NXDOMAIN", DNSFilterEngine::PolicyKind::NXDOMAIN},
×
UNCOV
410
    {"NODATA", DNSFilterEngine::PolicyKind::NODATA},
×
UNCOV
411
    {"Truncate", DNSFilterEngine::PolicyKind::Truncate},
×
UNCOV
412
    {"Custom", DNSFilterEngine::PolicyKind::Custom}};
×
UNCOV
413
  Lua->writeVariable("Policy", pmap);
×
414

UNCOV
415
  Lua->writeFunction("rpzFile", [&lci](const string& filename, boost::optional<rpzOptions_t> options) {
×
UNCOV
416
    RPZTrackerParams params;
×
UNCOV
417
    params.zoneXFRParams.name = filename;
×
UNCOV
418
    params.polName = "rpzFile";
×
UNCOV
419
    if (options) {
×
UNCOV
420
      parseRPZParameters(*options, params);
×
UNCOV
421
    }
×
UNCOV
422
    lci.rpzs.emplace_back(params);
×
UNCOV
423
  });
×
424

UNCOV
425
  Lua->writeFunction("rpzMaster", [&lci](const boost::variant<string, std::vector<std::pair<int, string>>>& primaries_, const string& zoneName, const boost::optional<rpzOptions_t>& options) {
×
UNCOV
426
    SLOG(g_log << Logger::Warning << "'rpzMaster' is deprecated and will be removed in a future release, use 'rpzPrimary' instead" << endl,
×
UNCOV
427
         lci.d_slog->info(Logr::Warning, "'rpzMaster' is deprecated and will be removed in a future release, use 'rpzPrimary' instead"));
×
UNCOV
428
    rpzPrimary(lci, primaries_, zoneName, options);
×
UNCOV
429
  });
×
UNCOV
430
  Lua->writeFunction("rpzPrimary", [&lci](const boost::variant<string, std::vector<std::pair<int, string>>>& primaries_, const string& zoneName, const boost::optional<rpzOptions_t>& options) {
×
431
    rpzPrimary(lci, primaries_, zoneName, options);
×
432
  });
×
433

UNCOV
434
  typedef std::unordered_map<std::string, boost::variant<uint32_t, std::string>> zoneToCacheOptions_t;
×
435

UNCOV
436
  Lua->writeFunction("zoneToCache", [&lci](const string& zoneName, const string& method, const boost::variant<string, std::vector<std::pair<int, string>>>& srcs, boost::optional<zoneToCacheOptions_t> options) {
×
437
    try {
×
438
      RecZoneToCache::Config conf;
×
439
      DNSName validZoneName(zoneName);
×
440
      conf.d_zone = zoneName;
×
441
      const set<string> methods = {"axfr", "url", "file"};
×
442
      if (methods.count(method) == 0) {
×
443
        throw std::runtime_error("unknwon method '" + method + "'");
×
444
      }
×
445
      conf.d_method = method;
×
446
      if (srcs.type() == typeid(std::string)) {
×
447
        conf.d_sources.push_back(boost::get<std::string>(srcs));
×
448
      }
×
449
      else {
×
450
        for (const auto& src : boost::get<std::vector<std::pair<int, std::string>>>(srcs)) {
×
451
          conf.d_sources.push_back(src.second);
×
452
        }
×
453
      }
×
454
      if (conf.d_sources.size() == 0) {
×
455
        throw std::runtime_error("at least one source required");
×
456
      }
×
457
      if (options) {
×
458
        auto& have = *options;
×
459
        if (have.count("timeout")) {
×
460
          conf.d_timeout = boost::get<uint32_t>(have.at("timeout"));
×
461
        }
×
462
        if (have.count("tsigname")) {
×
463
          conf.d_tt.name = DNSName(toLower(boost::get<string>(have.at("tsigname"))));
×
464
          conf.d_tt.algo = DNSName(toLower(boost::get<string>(have.at("tsigalgo"))));
×
465
          if (B64Decode(boost::get<string>(have.at("tsigsecret")), conf.d_tt.secret)) {
×
466
            throw std::runtime_error("TSIG secret is not valid Base-64 encoded");
×
467
          }
×
468
        }
×
469
        if (have.count("maxReceivedMBytes")) {
×
470
          conf.d_maxReceivedBytes = static_cast<size_t>(boost::get<uint32_t>(have.at("maxReceivedMBytes")));
×
471
          conf.d_maxReceivedBytes *= 1024 * 1024;
×
472
        }
×
473
        if (have.count("localAddress")) {
×
474
          conf.d_local = ComboAddress(boost::get<string>(have.at("localAddress")));
×
475
        }
×
476
        if (have.count("refreshPeriod")) {
×
477
          conf.d_refreshPeriod = boost::get<uint32_t>(have.at("refreshPeriod"));
×
478
        }
×
479
        if (have.count("retryOnErrorPeriod")) {
×
480
          conf.d_retryOnError = boost::get<uint32_t>(have.at("retryOnErrorPeriod"));
×
481
        }
×
482
        const map<string, pdns::ZoneMD::Config> nameToVal = {
×
483
          {"ignore", pdns::ZoneMD::Config::Ignore},
×
484
          {"validate", pdns::ZoneMD::Config::Validate},
×
485
          {"require", pdns::ZoneMD::Config::Require},
×
486
        };
×
487
        if (have.count("zonemd")) {
×
488
          string zonemdValidation = boost::get<string>(have.at("zonemd"));
×
489
          auto it = nameToVal.find(zonemdValidation);
×
490
          if (it == nameToVal.end()) {
×
491
            throw std::runtime_error(zonemdValidation + " is not a valid value for `zonemd`");
×
492
          }
×
493
          else {
×
494
            conf.d_zonemd = it->second;
×
495
          }
×
496
        }
×
497
        if (have.count("dnssec")) {
×
498
          string dnssec = boost::get<string>(have.at("dnssec"));
×
499
          auto it = nameToVal.find(dnssec);
×
500
          if (it == nameToVal.end()) {
×
501
            throw std::runtime_error(dnssec + " is not a valid value for `dnssec`");
×
502
          }
×
503
          else {
×
504
            conf.d_dnssec = it->second;
×
505
          }
×
506
        }
×
507
      }
×
508

509
      lci.ztcConfigs[validZoneName] = std::move(conf);
×
510
    }
×
511
    catch (const std::exception& e) {
×
512
      SLOG(g_log << Logger::Error << "Problem configuring zoneToCache for zone '" << zoneName << "': " << e.what() << endl,
×
513
           lci.d_slog->error(Logr::Error, e.what(), "Problem configuring zoneToCache", "zone", Logging::Loggable(zoneName),
×
514
                             "exception", Logging::Loggable("std::exception")));
×
515
    }
×
516
  });
×
517

UNCOV
518
  typedef vector<pair<int, boost::variant<string, vector<pair<int, string>>>>> argvec_t;
×
UNCOV
519
  Lua->writeFunction("addSortList",
×
UNCOV
520
                     [&lci](const std::string& formask_,
×
UNCOV
521
                            const boost::variant<string, argvec_t>& masks,
×
UNCOV
522
                            boost::optional<int> order_) {
×
UNCOV
523
                       try {
×
UNCOV
524
                         Netmask formask(formask_);
×
UNCOV
525
                         int order = order_ ? (*order_) : lci.sortlist.getMaxOrder(formask) + 1;
×
UNCOV
526
                         if (auto str = boost::get<string>(&masks))
×
527
                           lci.sortlist.addEntry(formask, Netmask(*str), order);
×
UNCOV
528
                         else {
×
529

UNCOV
530
                           auto vec = boost::get<argvec_t>(&masks);
×
UNCOV
531
                           for (const auto& e : *vec) {
×
UNCOV
532
                             if (auto s = boost::get<string>(&e.second)) {
×
UNCOV
533
                               lci.sortlist.addEntry(formask, Netmask(*s), order);
×
UNCOV
534
                             }
×
UNCOV
535
                             else {
×
UNCOV
536
                               const auto& v = boost::get<vector<pair<int, string>>>(e.second);
×
UNCOV
537
                               for (const auto& entry : v)
×
UNCOV
538
                                 lci.sortlist.addEntry(formask, Netmask(entry.second), order);
×
UNCOV
539
                             }
×
UNCOV
540
                             ++order;
×
UNCOV
541
                           }
×
UNCOV
542
                         }
×
UNCOV
543
                       }
×
UNCOV
544
                       catch (std::exception& e) {
×
545
                         SLOG(g_log << Logger::Error << "Error in addSortList: " << e.what() << endl,
×
546
                              lci.d_slog->error(Logr::Error, e.what(), "Error in addSortList", "exception",  Logging::Loggable("std::exception")));
×
547
                       }
×
UNCOV
548
                     });
×
549

UNCOV
550
  Lua->writeFunction("addTA", [&lci](const std::string& who, const std::string& what) {
×
UNCOV
551
    DNSName zone(who);
×
UNCOV
552
    auto ds = std::dynamic_pointer_cast<DSRecordContent>(DSRecordContent::make(what));
×
UNCOV
553
    lci.dsAnchors[zone].insert(*ds);
×
UNCOV
554
  });
×
555

UNCOV
556
  Lua->writeFunction("clearTA", [&lci](boost::optional<string> who) {
×
UNCOV
557
    if (who)
×
558
      lci.dsAnchors.erase(DNSName(*who));
×
UNCOV
559
    else
×
UNCOV
560
      lci.dsAnchors.clear();
×
UNCOV
561
  });
×
562

563
  /* Remove in 4.3 */
UNCOV
564
  Lua->writeFunction("addDS", [&lci](const std::string& who, const std::string& what) {
×
UNCOV
565
    SLOG(g_log << Logger::Warning << "addDS is deprecated and will be removed in the future, switch to addTA" << endl,
×
UNCOV
566
         lci.d_slog->info(Logr::Warning, "addDS is deprecated and will be removed in the future, switch to addTA"));
×
UNCOV
567
    DNSName zone(who);
×
UNCOV
568
    auto ds = std::dynamic_pointer_cast<DSRecordContent>(DSRecordContent::make(what));
×
UNCOV
569
    lci.dsAnchors[zone].insert(*ds);
×
UNCOV
570
  });
×
571

572
  /* Remove in 4.3 */
UNCOV
573
  Lua->writeFunction("clearDS", [&lci](boost::optional<string> who) {
×
UNCOV
574
    SLOG(g_log << Logger::Warning << "clearDS is deprecated and will be removed in the future, switch to clearTA" << endl,
×
UNCOV
575
         lci.d_slog->info(Logr::Warning, "clearDS is deprecated and will be removed in the future, switch to clearTA"));
×
UNCOV
576
    if (who)
×
UNCOV
577
      lci.dsAnchors.erase(DNSName(*who));
×
578
    else
×
579
      lci.dsAnchors.clear();
×
UNCOV
580
  });
×
581

UNCOV
582
  Lua->writeFunction("addNTA", [&lci](const std::string& who, const boost::optional<std::string> why) {
×
UNCOV
583
    if (why)
×
UNCOV
584
      lci.negAnchors[DNSName(who)] = static_cast<string>(*why);
×
UNCOV
585
    else
×
UNCOV
586
      lci.negAnchors[DNSName(who)] = "";
×
UNCOV
587
  });
×
588

UNCOV
589
  Lua->writeFunction("clearNTA", [&lci](boost::optional<string> who) {
×
590
    if (who)
×
591
      lci.negAnchors.erase(DNSName(*who));
×
592
    else
×
593
      lci.negAnchors.clear();
×
594
  });
×
595

UNCOV
596
  Lua->writeFunction("readTrustAnchorsFromFile", [&lci](const std::string& fnamearg, const boost::optional<uint32_t> interval) {
×
UNCOV
597
    uint32_t realInterval = 24;
×
UNCOV
598
    if (interval) {
×
599
      realInterval = static_cast<uint32_t>(*interval);
×
600
    }
×
UNCOV
601
    lci.trustAnchorFileInfo.fname = fnamearg;
×
UNCOV
602
    lci.trustAnchorFileInfo.interval = realInterval;
×
UNCOV
603
  });
×
604

UNCOV
605
  Lua->writeFunction("setProtobufMasks", [&lci](const uint8_t maskV4, uint8_t maskV6) {
×
UNCOV
606
    lci.protobufMaskV4 = maskV4;
×
UNCOV
607
    lci.protobufMaskV6 = maskV6;
×
UNCOV
608
  });
×
609

UNCOV
610
  Lua->writeFunction("protobufServer", [&lci](boost::variant<const std::string, const std::unordered_map<int, std::string>> servers, boost::optional<protobufOptions_t> vars) {
×
UNCOV
611
    if (!lci.protobufExportConfig.enabled) {
×
612

UNCOV
613
      lci.protobufExportConfig.enabled = true;
×
614

UNCOV
615
      try {
×
UNCOV
616
        if (servers.type() == typeid(std::string)) {
×
617
          auto server = boost::get<const std::string>(servers);
×
618

619
          lci.protobufExportConfig.servers.emplace_back(server);
×
620
        }
×
UNCOV
621
        else {
×
UNCOV
622
          auto serversMap = boost::get<const std::unordered_map<int, std::string>>(servers);
×
UNCOV
623
          for (const auto& serverPair : serversMap) {
×
UNCOV
624
            lci.protobufExportConfig.servers.emplace_back(serverPair.second);
×
UNCOV
625
          }
×
UNCOV
626
        }
×
627

UNCOV
628
        parseProtobufOptions(vars, lci.protobufExportConfig);
×
UNCOV
629
      }
×
UNCOV
630
      catch (std::exception& e) {
×
631
        SLOG(g_log << Logger::Error << "Error while adding protobuf logger: " << e.what() << endl,
×
632
             lci.d_slog->error(Logr::Error, e.what(), "Exception while adding protobuf logger", "exception", Logging::Loggable("std::exception")));
×
633
      }
×
UNCOV
634
      catch (PDNSException& e) {
×
635
        SLOG(g_log << Logger::Error << "Error while adding protobuf logger: " << e.reason << endl,
×
636
             lci.d_slog->error(Logr::Error, e.reason, "Exception while adding protobuf logger", "exception", Logging::Loggable("PDNSException")));
×
637
      }
×
UNCOV
638
    }
×
639
    else {
×
640
      SLOG(g_log << Logger::Error << "Only one protobufServer() directive can be configured, we already have " << lci.protobufExportConfig.servers.at(0).toString() << endl,
×
641
           lci.d_slog->info(Logr::Error, "Only one protobufServer() directive can be configured", "existing", Logging::Loggable(lci.protobufExportConfig.servers.at(0).toString())));
×
642
    }
×
UNCOV
643
  });
×
644

UNCOV
645
  Lua->writeFunction("outgoingProtobufServer", [&lci](boost::variant<const std::string, const std::unordered_map<int, std::string>> servers, boost::optional<protobufOptions_t> vars) {
×
UNCOV
646
    if (!lci.outgoingProtobufExportConfig.enabled) {
×
647

UNCOV
648
      lci.outgoingProtobufExportConfig.enabled = true;
×
649

UNCOV
650
      try {
×
UNCOV
651
        if (servers.type() == typeid(std::string)) {
×
652
          auto server = boost::get<const std::string>(servers);
×
653

654
          lci.outgoingProtobufExportConfig.servers.emplace_back(server);
×
655
        }
×
UNCOV
656
        else {
×
UNCOV
657
          auto serversMap = boost::get<const std::unordered_map<int, std::string>>(servers);
×
UNCOV
658
          for (const auto& serverPair : serversMap) {
×
UNCOV
659
            lci.outgoingProtobufExportConfig.servers.emplace_back(serverPair.second);
×
UNCOV
660
          }
×
UNCOV
661
        }
×
662

UNCOV
663
        parseProtobufOptions(vars, lci.outgoingProtobufExportConfig);
×
UNCOV
664
      }
×
UNCOV
665
      catch (std::exception& e) {
×
666
        SLOG(g_log << Logger::Error << "Error while starting outgoing protobuf logger: " << e.what() << endl,
×
667
             lci.d_slog->error(Logr::Error, "Exception while starting outgoing protobuf logger", "exception", Logging::Loggable("std::exception")));
×
668
      }
×
UNCOV
669
      catch (PDNSException& e) {
×
670
        SLOG(g_log << Logger::Error << "Error while starting outgoing protobuf logger: " << e.reason << endl,
×
671
             lci.d_slog->error(Logr::Error, "Exception while starting outgoing protobuf logger", "exception", Logging::Loggable("PDNSException")));
×
672
      }
×
UNCOV
673
    }
×
674
    else {
×
675
      SLOG(g_log << Logger::Error << "Only one outgoingProtobufServer() directive can be configured, we already have " << lci.outgoingProtobufExportConfig.servers.at(0).toString() << endl,
×
676
           lci.d_slog->info(Logr::Error, "Only one outgoingProtobufServer() directive can be configured", "existing", Logging::Loggable(lci.outgoingProtobufExportConfig.servers.at(0).toString())));
×
677
    }
×
UNCOV
678
  });
×
679

UNCOV
680
#ifdef HAVE_FSTRM
×
UNCOV
681
  Lua->writeFunction("dnstapFrameStreamServer", [&lci](boost::variant<const std::string, const std::unordered_map<int, std::string>> servers, boost::optional<frameStreamOptions_t> vars) {
×
UNCOV
682
    if (!lci.frameStreamExportConfig.enabled) {
×
683

UNCOV
684
      lci.frameStreamExportConfig.enabled = true;
×
685

UNCOV
686
      try {
×
UNCOV
687
        if (servers.type() == typeid(std::string)) {
×
688
          auto server = boost::get<const std::string>(servers);
×
689
          if (!boost::starts_with(server, "/")) {
×
690
            ComboAddress parsecheck(server);
×
691
          }
×
692
          lci.frameStreamExportConfig.servers.emplace_back(server);
×
693
        }
×
UNCOV
694
        else {
×
UNCOV
695
          auto serversMap = boost::get<const std::unordered_map<int, std::string>>(servers);
×
UNCOV
696
          for (const auto& serverPair : serversMap) {
×
UNCOV
697
            lci.frameStreamExportConfig.servers.emplace_back(serverPair.second);
×
UNCOV
698
          }
×
UNCOV
699
        }
×
700

UNCOV
701
        parseFrameStreamOptions(vars, lci.frameStreamExportConfig);
×
UNCOV
702
      }
×
UNCOV
703
      catch (std::exception& e) {
×
704
        SLOG(g_log << Logger::Error << "Error reading config for dnstap framestream logger: " << e.what() << endl,
×
705
              lci.d_slog->error(Logr::Error, "Exception reading config for dnstap framestream logger", "exception", Logging::Loggable("std::exception")));
×
706
      }
×
UNCOV
707
      catch (PDNSException& e) {
×
708
        SLOG(g_log << Logger::Error << "Error reading config for dnstap framestream logger: " << e.reason << endl,
×
709
             lci.d_slog->error(Logr::Error, "Exception reading config for dnstap framestream logger", "exception", Logging::Loggable("PDNSException")));
×
710
      }
×
UNCOV
711
    }
×
712
    else {
×
713
      SLOG(g_log << Logger::Error << "Only one dnstapFrameStreamServer() directive can be configured, we already have " << lci.frameStreamExportConfig.servers.at(0) << endl,
×
714
           lci.d_slog->info(Logr::Error,  "Only one dnstapFrameStreamServer() directive can be configured",  "existing", Logging::Loggable(lci.frameStreamExportConfig.servers.at(0))));
×
715
    }
×
UNCOV
716
  });
×
UNCOV
717
  Lua->writeFunction("dnstapNODFrameStreamServer", [&lci](boost::variant<const std::string, const std::unordered_map<int, std::string>> servers, boost::optional<frameStreamOptions_t> vars) {
×
UNCOV
718
    if (!lci.nodFrameStreamExportConfig.enabled) {
×
UNCOV
719
      lci.nodFrameStreamExportConfig.enabled = true;
×
720

UNCOV
721
      try {
×
UNCOV
722
        if (servers.type() == typeid(std::string)) {
×
723
          auto server = boost::get<const std::string>(servers);
×
724
          if (!boost::starts_with(server, "/")) {
×
725
            ComboAddress parsecheck(server);
×
726
          }
×
727
          lci.nodFrameStreamExportConfig.servers.emplace_back(server);
×
728
        }
×
UNCOV
729
        else {
×
UNCOV
730
          auto serversMap = boost::get<const std::unordered_map<int, std::string>>(servers);
×
UNCOV
731
          for (const auto& serverPair : serversMap) {
×
UNCOV
732
            lci.nodFrameStreamExportConfig.servers.emplace_back(serverPair.second);
×
UNCOV
733
          }
×
UNCOV
734
        }
×
735

UNCOV
736
        parseFrameStreamOptions(vars, lci.nodFrameStreamExportConfig);
×
UNCOV
737
      }
×
UNCOV
738
      catch (std::exception& e) {
×
739
        SLOG(g_log << Logger::Error << "Error reading config for dnstap NOD framestream logger: " << e.what() << endl,
×
740
              lci.d_slog->error(Logr::Error, "Exception reading config for dnstap NOD framestream logger", "exception", Logging::Loggable("std::exception")));
×
741
      }
×
UNCOV
742
      catch (PDNSException& e) {
×
743
        SLOG(g_log << Logger::Error << "Error reading config for dnstap NOD framestream logger: " << e.reason << endl,
×
744
             lci.d_slog->error(Logr::Error, "Exception reading config for dnstap NOD framestream logger", "exception", Logging::Loggable("PDNSException")));
×
745
      }
×
UNCOV
746
    }
×
747
    else {
×
748
      SLOG(g_log << Logger::Error << "Only one dnstapNODFrameStreamServer() directive can be configured, we already have " << lci.nodFrameStreamExportConfig.servers.at(0) << endl,
×
749
           lci.d_slog->info(Logr::Error,  "Only one dnstapNODFrameStreamServer() directive can be configured",  "existing", Logging::Loggable(lci.nodFrameStreamExportConfig.servers.at(0))));
×
750
    }
×
UNCOV
751
  });
×
UNCOV
752
#endif /* HAVE_FSTRM */
×
753

UNCOV
754
  Lua->writeFunction("addAllowedAdditionalQType", [&lci](int qtype, std::unordered_map<int, int> targetqtypes, boost::optional<std::map<std::string, int>> options) {
×
UNCOV
755
    switch (qtype) {
×
UNCOV
756
    case QType::MX:
×
UNCOV
757
    case QType::SRV:
×
UNCOV
758
    case QType::SVCB:
×
UNCOV
759
    case QType::HTTPS:
×
UNCOV
760
    case QType::NAPTR:
×
UNCOV
761
      break;
×
762
    default:
×
763
      SLOG(g_log << Logger::Error << "addAllowedAdditionalQType does not support " << QType(qtype).toString() << endl,
×
764
           lci.d_slog->info(Logr::Error, "addAllowedAdditionalQType does not support this qtype", "qtype", Logging::Loggable(QType(qtype).toString())));
×
765
      return;
×
UNCOV
766
    }
×
767

UNCOV
768
    std::set<QType> targets;
×
UNCOV
769
    for (const auto& t : targetqtypes) {
×
UNCOV
770
      targets.emplace(QType(t.second));
×
UNCOV
771
    }
×
772

UNCOV
773
    AdditionalMode mode = AdditionalMode::CacheOnlyRequireAuth; // Always cheap and should be safe
×
774

UNCOV
775
    if (options) {
×
UNCOV
776
      if (const auto it = options->find("mode"); it != options->end()) {
×
UNCOV
777
        mode = static_cast<AdditionalMode>(it->second);
×
UNCOV
778
        if (mode > AdditionalMode::ResolveDeferred) {
×
779
          SLOG(g_log << Logger::Error << "addAllowedAdditionalQType: unknown mode " << it->second << endl,
×
780
               lci.d_slog->info(Logr::Error, "addAllowedAdditionalQType: unknown mode", "mode", Logging::Loggable( it->second)));
×
781
        }
×
UNCOV
782
      }
×
UNCOV
783
    }
×
UNCOV
784
    lci.allowAdditionalQTypes.insert_or_assign(qtype, pair(targets, mode));
×
UNCOV
785
  });
×
786

UNCOV
787
  Lua->writeFunction("addProxyMapping", [&proxyMapping,&lci](const string& netmaskArg, const string& addressArg, boost::optional<std::vector<pair<int,std::string>>> smnStrings) {
×
UNCOV
788
    try {
×
UNCOV
789
      Netmask netmask(netmaskArg);
×
UNCOV
790
      ComboAddress address(addressArg);
×
UNCOV
791
      boost::optional<SuffixMatchNode> smn;
×
UNCOV
792
      if (smnStrings) {
×
UNCOV
793
        smn = boost::make_optional(SuffixMatchNode{});
×
UNCOV
794
        for (const auto& el : *smnStrings) {
×
UNCOV
795
          smn->add(el.second);
×
UNCOV
796
        }
×
UNCOV
797
      }
×
UNCOV
798
      proxyMapping.insert_or_assign(netmask, {address, smn});
×
UNCOV
799
    }
×
UNCOV
800
    catch (std::exception& e) {
×
801
      SLOG(g_log << Logger::Error << "Error processing addProxyMapping: " << e.what() << endl,
×
802
           lci.d_slog->error(Logr::Error, e.what(), "Exception processing addProxyMapping", "exception", Logging::Loggable("std::exception")));
×
803
    }
×
UNCOV
804
    catch (PDNSException& e) {
×
805
      SLOG(g_log << Logger::Error << "Error processing addProxyMapping: " << e.reason << endl,
×
806
           lci.d_slog->error(Logr::Error, e.reason, "Exception processing addProxyMapping", "exception", Logging::Loggable("PDNSException")));
×
807
    }
×
UNCOV
808
  });
×
809

UNCOV
810
  try {
×
UNCOV
811
    Lua->executeCode(ifs);
×
UNCOV
812
    newLuaConfig = std::move(lci);
×
UNCOV
813
  }
×
UNCOV
814
  catch (const LuaContext::ExecutionErrorException& e) {
×
815
    SLOG(g_log << Logger::Error << "Unable to load Lua script from '" + fname + "': ",
×
816
         lci.d_slog->error(Logr::Error, e.what(),  "Unable to load Lua script", "file", Logging::Loggable(fname)));
×
817
    try {
×
818
      std::rethrow_if_nested(e);
×
819
    }
×
820
    catch (const std::exception& exp) {
×
821
      // exp is the exception that was thrown from inside the lambda
822
      SLOG(g_log << exp.what() << std::endl,
×
823
           lci.d_slog->error(Logr::Error, exp.what(), "Exception loading Lua", "exception", Logging::Loggable("std::exception")));
×
824
    }
×
825
    catch (const PDNSException& exp) {
×
826
      // exp is the exception that was thrown from inside the lambda
827
      SLOG(g_log << exp.reason << std::endl,
×
828
           lci.d_slog->error(Logr::Error, exp.reason, "Exception loading Lua", "exception", Logging::Loggable("PDNSException")));
×
829
    }
×
830
    throw;
×
831
  }
×
UNCOV
832
  catch (std::exception& err) {
×
833
    SLOG(g_log << Logger::Error << "Unable to load Lua script from '" + fname + "': " << err.what() << endl,
×
834
         lci.d_slog->error(Logr::Error, err.what(),  "Unable to load Lua script", "file", Logging::Loggable(fname), "exception", Logging::Loggable("std::exception")));
×
835
    throw;
×
836
  }
×
UNCOV
837
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc