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

PowerDNS / pdns / 12595591960

03 Jan 2025 09:27AM UTC coverage: 62.774% (+2.5%) from 60.245%
12595591960

Pull #15008

github

web-flow
Merge c2a2749d3 into 788f396a7
Pull Request #15008: Do not follow CNAME records for ANY or CNAME queries

30393 of 78644 branches covered (38.65%)

Branch coverage included in aggregate %.

105822 of 138350 relevant lines covered (76.49%)

4613078.44 hits per line

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

61.54
/pdns/dnsdistdist/dnsdist-lua-bindings.cc
1
/*
2
 * This file is part of PowerDNS or dnsdist.
3
 * Copyright -- PowerDNS.COM B.V. and its contributors
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of version 2 of the GNU General Public License as
7
 * published by the Free Software Foundation.
8
 *
9
 * In addition, for the avoidance of any doubt, permission is granted to
10
 * link this program with OpenSSL and to (re)distribute the binaries
11
 * produced as the result of such linking.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
 */
22
#include "bpf-filter.hh"
23
#include "config.h"
24
#include "dnsdist.hh"
25
#include "dnsdist-async.hh"
26
#include "dnsdist-dynblocks.hh"
27
#include "dnsdist-dynbpf.hh"
28
#include "dnsdist-frontend.hh"
29
#include "dnsdist-lua.hh"
30
#include "dnsdist-resolver.hh"
31
#include "dnsdist-svc.hh"
32
#include "dnsdist-xsk.hh"
33

34
#include "dolog.hh"
35
#include "xsk.hh"
36

37
void setupLuaBindingsLogging(LuaContext& luaCtx)
38
{
662✔
39
  luaCtx.writeFunction("vinfolog", [](const string& arg) {
662✔
40
    vinfolog("%s", arg);
×
41
  });
×
42
  luaCtx.writeFunction("infolog", [](const string& arg) {
662✔
43
    infolog("%s", arg);
×
44
  });
×
45
  luaCtx.writeFunction("errlog", [](const string& arg) {
662✔
46
    errlog("%s", arg);
×
47
  });
×
48
  luaCtx.writeFunction("warnlog", [](const string& arg) {
662✔
49
    warnlog("%s", arg);
×
50
  });
×
51
  luaCtx.writeFunction("show", [](const string& arg) {
662✔
52
    g_outputBuffer += arg;
×
53
    g_outputBuffer += "\n";
×
54
  });
×
55
}
662✔
56

57
// NOLINTNEXTLINE(readability-function-cognitive-complexity): this function declares Lua bindings, even with a good refactoring it will likely blow up the threshold
58
void setupLuaBindings(LuaContext& luaCtx, bool client, bool configCheck)
59
{
653✔
60
  /* Exceptions */
61
  luaCtx.registerFunction<string (std::exception_ptr::*)() const>("__tostring", [](const std::exception_ptr& eptr) -> std::string {
653✔
62
    try {
×
63
      if (eptr) {
×
64
        std::rethrow_exception(eptr);
×
65
      }
×
66
    }
×
67
    catch (const std::exception& e) {
×
68
      return {e.what()};
×
69
    }
×
70
    catch (const PDNSException& e) {
×
71
      return e.reason;
×
72
    }
×
73
    catch (...) {
×
74
      return {"Unknown exception"};
×
75
    }
×
76
    return {"No exception"};
×
77
  });
×
78
#ifndef DISABLE_POLICIES_BINDINGS
653✔
79
  /* ServerPolicy */
80
  luaCtx.writeFunction("newServerPolicy", [](const string& name, const ServerPolicy::policyfunc_t& policy) { return std::make_shared<ServerPolicy>(name, policy, true); });
653✔
81
  luaCtx.registerMember("name", &ServerPolicy::d_name);
653✔
82
  luaCtx.registerMember("policy", &ServerPolicy::d_policy);
653✔
83
  luaCtx.registerMember("ffipolicy", &ServerPolicy::d_ffipolicy);
653✔
84
  luaCtx.registerMember("isLua", &ServerPolicy::d_isLua);
653✔
85
  luaCtx.registerMember("isFFI", &ServerPolicy::d_isFFI);
653✔
86
  luaCtx.registerMember("isPerThread", &ServerPolicy::d_isPerThread);
653✔
87
  luaCtx.registerFunction("toString", &ServerPolicy::toString);
653✔
88
  luaCtx.registerFunction("__tostring", &ServerPolicy::toString);
653✔
89

90
  const std::array<std::shared_ptr<ServerPolicy>, 6> policies = {
653✔
91
    std::make_shared<ServerPolicy>("firstAvailable", firstAvailable, false),
653✔
92
    std::make_shared<ServerPolicy>("roundrobin", roundrobin, false),
653✔
93
    std::make_shared<ServerPolicy>("wrandom", wrandom, false),
653✔
94
    std::make_shared<ServerPolicy>("whashed", whashed, false),
653✔
95
    std::make_shared<ServerPolicy>("chashed", chashed, false),
653✔
96
    std::make_shared<ServerPolicy>("leastOutstanding", leastOutstanding, false)};
653✔
97
  for (const auto& policy : policies) {
3,918✔
98
    luaCtx.writeVariable(policy->d_name, policy);
3,918✔
99
  }
3,918✔
100

101
#endif /* DISABLE_POLICIES_BINDINGS */
653✔
102

103
  /* ServerPool */
104
  luaCtx.registerFunction<void (std::shared_ptr<ServerPool>::*)(std::shared_ptr<DNSDistPacketCache>)>("setCache", [](const std::shared_ptr<ServerPool>& pool, std::shared_ptr<DNSDistPacketCache> cache) {
653✔
105
    if (pool) {
106!
106
      pool->packetCache = std::move(cache);
106✔
107
    }
106✔
108
  });
106✔
109
  luaCtx.registerFunction("getCache", &ServerPool::getCache);
653✔
110
  luaCtx.registerFunction<void (std::shared_ptr<ServerPool>::*)()>("unsetCache", [](const std::shared_ptr<ServerPool>& pool) {
653✔
111
    if (pool) {
×
112
      pool->packetCache = nullptr;
×
113
    }
×
114
  });
×
115
  luaCtx.registerFunction("getECS", &ServerPool::getECS);
653✔
116
  luaCtx.registerFunction("setECS", &ServerPool::setECS);
653✔
117

118
#ifndef DISABLE_DOWNSTREAM_BINDINGS
653✔
119
  /* DownstreamState */
120
  luaCtx.registerFunction<void (DownstreamState::*)(int)>("setQPS", [](DownstreamState& state, int lim) { state.qps = lim > 0 ? QPSLimiter(lim, lim) : QPSLimiter(); });
653!
121
  luaCtx.registerFunction<void (std::shared_ptr<DownstreamState>::*)(string)>("addPool", [](const std::shared_ptr<DownstreamState>& state, const string& pool) {
653✔
122
    addServerToPool(pool, state);
123
    state->d_config.pools.insert(pool);
124
  });
125
  luaCtx.registerFunction<void (std::shared_ptr<DownstreamState>::*)(string)>("rmPool", [](const std::shared_ptr<DownstreamState>& state, const string& pool) {
653✔
126
    removeServerFromPool(pool, state);
127
    state->d_config.pools.erase(pool);
128
  });
129
  luaCtx.registerFunction<uint64_t (DownstreamState::*)() const>("getOutstanding", [](const DownstreamState& state) { return state.outstanding.load(); });
653✔
130
  luaCtx.registerFunction<uint64_t (DownstreamState::*)() const>("getDrops", [](const DownstreamState& state) { return state.reuseds.load(); });
653✔
131
  luaCtx.registerFunction<double (DownstreamState::*)() const>("getLatency", [](const DownstreamState& state) { return state.getRelevantLatencyUsec(); });
653✔
132
  luaCtx.registerFunction("isUp", &DownstreamState::isUp);
653✔
133
  luaCtx.registerFunction("setDown", &DownstreamState::setDown);
653✔
134
  luaCtx.registerFunction("setUp", &DownstreamState::setUp);
653✔
135
  luaCtx.registerFunction<void (DownstreamState::*)(boost::optional<bool> newStatus)>("setAuto", [](DownstreamState& state, boost::optional<bool> newStatus) {
653✔
136
    if (newStatus) {
6✔
137
      state.setUpStatus(*newStatus);
1✔
138
    }
1✔
139
    state.setAuto();
6✔
140
  });
6✔
141
  luaCtx.registerFunction<void (DownstreamState::*)(boost::optional<bool> newStatus)>("setLazyAuto", [](DownstreamState& state, boost::optional<bool> newStatus) {
653✔
142
    if (newStatus) {
×
143
      state.setUpStatus(*newStatus);
144
    }
145
    state.setLazyAuto();
146
  });
147
  luaCtx.registerFunction<std::string (DownstreamState::*)() const>("getName", [](const DownstreamState& state) -> const std::string& { return state.getName(); });
653✔
148
  luaCtx.registerFunction<std::string (DownstreamState::*)() const>("getNameWithAddr", [](const DownstreamState& state) -> const std::string& { return state.getNameWithAddr(); });
653✔
149
  luaCtx.registerMember<bool(DownstreamState::*)>(
653✔
150
    "upStatus",
653✔
151
    [](const DownstreamState& state) -> bool { return state.upStatus.load(std::memory_order_relaxed); },
653✔
152
    [](DownstreamState& state, bool newStatus) { state.upStatus.store(newStatus); });
653✔
153
  luaCtx.registerMember<int(DownstreamState::*)>(
653✔
154
    "weight",
653✔
155
    [](const DownstreamState& state) -> int { return state.d_config.d_weight; },
653✔
156
    [](DownstreamState& state, int newWeight) { state.setWeight(newWeight); });
653✔
157
  luaCtx.registerMember<int(DownstreamState::*)>(
653✔
158
    "order",
653✔
159
    [](const DownstreamState& state) -> int { return state.d_config.order; },
653✔
160
    [](DownstreamState& state, int newOrder) { state.d_config.order = newOrder; });
653✔
161
  luaCtx.registerMember<const std::string(DownstreamState::*)>(
653✔
162
    "name", [](const DownstreamState& backend) -> std::string { return backend.getName(); }, [](DownstreamState& backend, const std::string& newName) { backend.setName(newName); });
653✔
163
  luaCtx.registerFunction<std::string (DownstreamState::*)() const>("getID", [](const DownstreamState& state) { return boost::uuids::to_string(*state.d_config.id); });
653✔
164
#endif /* DISABLE_DOWNSTREAM_BINDINGS */
653✔
165

166
#ifndef DISABLE_DNSHEADER_BINDINGS
653✔
167
  /* dnsheader */
168
  luaCtx.registerFunction<void (dnsheader::*)(bool)>("setRD", [](dnsheader& dnsHeader, bool value) {
653✔
169
    dnsHeader.rd = value;
170
  });
171

172
  luaCtx.registerFunction<bool (dnsheader::*)() const>("getRD", [](const dnsheader& dnsHeader) {
653✔
173
    return (bool)dnsHeader.rd;
174
  });
175

176
  luaCtx.registerFunction<void (dnsheader::*)(bool)>("setRA", [](dnsheader& dnsHeader, bool value) {
653✔
177
    dnsHeader.ra = value;
178
  });
179

180
  luaCtx.registerFunction<bool (dnsheader::*)() const>("getRA", [](const dnsheader& dnsHeader) {
653✔
181
    return (bool)dnsHeader.ra;
182
  });
183

184
  luaCtx.registerFunction<void (dnsheader::*)(bool)>("setAD", [](dnsheader& dnsHeader, bool value) {
653✔
185
    dnsHeader.ad = value;
186
  });
187

188
  luaCtx.registerFunction<bool (dnsheader::*)() const>("getAD", [](const dnsheader& dnsHeader) {
653✔
189
    return (bool)dnsHeader.ad;
190
  });
191

192
  luaCtx.registerFunction<void (dnsheader::*)(bool)>("setAA", [](dnsheader& dnsHeader, bool value) {
653✔
193
    dnsHeader.aa = value;
4✔
194
  });
4✔
195

196
  luaCtx.registerFunction<bool (dnsheader::*)() const>("getAA", [](const dnsheader& dnsHeader) {
653✔
197
    return (bool)dnsHeader.aa;
198
  });
199

200
  luaCtx.registerFunction<void (dnsheader::*)(bool)>("setCD", [](dnsheader& dnsHeader, bool value) {
653✔
201
    dnsHeader.cd = value;
3✔
202
  });
3✔
203

204
  luaCtx.registerFunction<bool (dnsheader::*)() const>("getCD", [](const dnsheader& dnsHeader) {
653✔
205
    return (bool)dnsHeader.cd;
206
  });
207

208
  luaCtx.registerFunction<uint16_t (dnsheader::*)() const>("getID", [](const dnsheader& dnsHeader) {
653✔
209
    return ntohs(dnsHeader.id);
184✔
210
  });
184✔
211

212
  luaCtx.registerFunction<bool (dnsheader::*)() const>("getTC", [](const dnsheader& dnsHeader) {
653✔
213
    return (bool)dnsHeader.tc;
4✔
214
  });
4✔
215

216
  luaCtx.registerFunction<void (dnsheader::*)(bool)>("setTC", [](dnsheader& dnsHeader, bool value) {
653✔
217
    dnsHeader.tc = value;
2✔
218
    if (value) {
2!
219
      dnsHeader.ra = dnsHeader.rd; // you'll always need this, otherwise TC=1 gets ignored
2✔
220
    }
2✔
221
  });
2✔
222

223
  luaCtx.registerFunction<void (dnsheader::*)(bool)>("setQR", [](dnsheader& dnsHeader, bool value) {
653✔
224
    dnsHeader.qr = value;
4✔
225
  });
4✔
226
#endif /* DISABLE_DNSHEADER_BINDINGS */
653✔
227

228
#ifndef DISABLE_COMBO_ADDR_BINDINGS
653✔
229
  /* ComboAddress */
230
  luaCtx.writeFunction("newCA", [](const std::string& name) { return ComboAddress(name); });
653✔
231
  luaCtx.writeFunction("newCAFromRaw", [](const std::string& raw, boost::optional<uint16_t> port) {
653✔
232
    if (raw.size() == 4) {
×
233
      sockaddr_in sin4{};
234
      memset(&sin4, 0, sizeof(sin4));
235
      sin4.sin_family = AF_INET;
236
      memcpy(&sin4.sin_addr.s_addr, raw.c_str(), raw.size());
237
      if (port) {
×
238
        sin4.sin_port = htons(*port);
239
      }
240
      return ComboAddress(&sin4);
241
    }
242
    if (raw.size() == 16) {
×
243
      sockaddr_in6 sin6{};
244
      memset(&sin6, 0, sizeof(sin6));
245
      sin6.sin6_family = AF_INET6;
246
      memcpy(&sin6.sin6_addr.s6_addr, raw.c_str(), raw.size());
247
      if (port) {
×
248
        sin6.sin6_port = htons(*port);
249
      }
250
      return ComboAddress(&sin6);
251
    }
252
    return ComboAddress();
253
  });
254
  luaCtx.registerFunction<string (ComboAddress::*)() const>("tostring", [](const ComboAddress& addr) { return addr.toString(); });
653✔
255
  luaCtx.registerFunction<string (ComboAddress::*)() const>("tostringWithPort", [](const ComboAddress& addr) { return addr.toStringWithPort(); });
653✔
256
  luaCtx.registerFunction<string (ComboAddress::*)() const>("__tostring", [](const ComboAddress& addr) { return addr.toString(); });
653✔
257
  luaCtx.registerFunction<string (ComboAddress::*)() const>("toString", [](const ComboAddress& addr) { return addr.toString(); });
653✔
258
  luaCtx.registerFunction<string (ComboAddress::*)() const>("toStringWithPort", [](const ComboAddress& addr) { return addr.toStringWithPort(); });
653✔
259
  luaCtx.registerFunction<uint16_t (ComboAddress::*)() const>("getPort", [](const ComboAddress& addr) { return ntohs(addr.sin4.sin_port); });
653✔
260
  luaCtx.registerFunction<void (ComboAddress::*)(unsigned int)>("truncate", [](ComboAddress& addr, unsigned int bits) { addr.truncate(bits); });
653✔
261
  luaCtx.registerFunction<bool (ComboAddress::*)() const>("isIPv4", [](const ComboAddress& addr) { return addr.sin4.sin_family == AF_INET; });
653✔
262
  luaCtx.registerFunction<bool (ComboAddress::*)() const>("isIPv6", [](const ComboAddress& addr) { return addr.sin4.sin_family == AF_INET6; });
653✔
263
  luaCtx.registerFunction<bool (ComboAddress::*)() const>("isMappedIPv4", [](const ComboAddress& addr) { return addr.isMappedIPv4(); });
653✔
264
  luaCtx.registerFunction<ComboAddress (ComboAddress::*)() const>("mapToIPv4", [](const ComboAddress& addr) { return addr.mapToIPv4(); });
653✔
265
#ifndef DISABLE_DYNBLOCKS
653✔
266
  luaCtx.registerFunction<bool (ClientAddressDynamicRules::*)(const ComboAddress&) const>("match", [](const ClientAddressDynamicRules& set, const ComboAddress& addr) { return set.match(addr); });
653✔
267
#endif /* DISABLE_DYNBLOCKS */
653✔
268
#endif /* DISABLE_COMBO_ADDR_BINDINGS */
653✔
269

270
#ifndef DISABLE_DNSNAME_BINDINGS
653✔
271
  /* DNSName */
272
  luaCtx.registerFunction("isPartOf", &DNSName::isPartOf);
653✔
273
  luaCtx.registerFunction<bool (DNSName::*)()>("chopOff", [](DNSName& name) { return name.chopOff(); });
653✔
274
  luaCtx.registerFunction<unsigned int (DNSName::*)() const>("countLabels", [](const DNSName& name) { return name.countLabels(); });
653✔
275
  luaCtx.registerFunction<size_t (DNSName::*)() const>("hash", [](const DNSName& name) { return name.hash(); });
653✔
276
  luaCtx.registerFunction<size_t (DNSName::*)() const>("wirelength", [](const DNSName& name) { return name.wirelength(); });
653✔
277
  luaCtx.registerFunction<string (DNSName::*)() const>("tostring", [](const DNSName& name) { return name.toString(); });
653✔
278
  luaCtx.registerFunction<string (DNSName::*)() const>("toString", [](const DNSName& name) { return name.toString(); });
653✔
279
  luaCtx.registerFunction<string (DNSName::*)() const>("toStringNoDot", [](const DNSName& name) { return name.toStringNoDot(); });
653✔
280
  luaCtx.registerFunction<string (DNSName::*)() const>("__tostring", [](const DNSName& name) { return name.toString(); });
653✔
281
  luaCtx.registerFunction<string (DNSName::*)() const>("toDNSString", [](const DNSName& name) { return name.toDNSString(); });
653✔
282
  luaCtx.registerFunction<DNSName (DNSName::*)(const DNSName&) const>("makeRelative", [](const DNSName& name, const DNSName& relTo) { return name.makeRelative(relTo); });
653✔
283
  luaCtx.writeFunction("newDNSName", [](const std::string& name) { return DNSName(name); });
653✔
284
  luaCtx.writeFunction("newDNSNameFromRaw", [](const std::string& name) { return DNSName(name.c_str(), name.size(), 0, false); });
653✔
285
  luaCtx.writeFunction("newSuffixMatchNode", []() { return SuffixMatchNode(); });
653✔
286
  luaCtx.writeFunction("newDNSNameSet", []() { return DNSNameSet(); });
653✔
287

288
  /* DNSNameSet */
289
  luaCtx.registerFunction<string (DNSNameSet::*)() const>("toString", [](const DNSNameSet& dns) { return dns.toString(); });
653✔
290
  luaCtx.registerFunction<string (DNSNameSet::*)() const>("__tostring", [](const DNSNameSet& dns) { return dns.toString(); });
653✔
291
  luaCtx.registerFunction<void (DNSNameSet::*)(DNSName&)>("add", [](DNSNameSet& dns, DNSName& name) { dns.insert(name); });
653✔
292
  luaCtx.registerFunction<bool (DNSNameSet::*)(DNSName&)>("check", [](DNSNameSet& dns, DNSName& name) { return dns.find(name) != dns.end(); });
653✔
293
  // clang-format off
294
  luaCtx.registerFunction("delete", (size_t (DNSNameSet::*)(const DNSName&)) &DNSNameSet::erase);
653✔
295
  luaCtx.registerFunction("size", (size_t (DNSNameSet::*)() const) &DNSNameSet::size);
653✔
296
  luaCtx.registerFunction("clear", (void (DNSNameSet::*)()) &DNSNameSet::clear);
653✔
297
  luaCtx.registerFunction("empty", (bool (DNSNameSet::*)() const) &DNSNameSet::empty);
653✔
298
  // clang-format on
299
#endif /* DISABLE_DNSNAME_BINDINGS */
653✔
300

301
#ifndef DISABLE_SUFFIX_MATCH_BINDINGS
653✔
302
  /* SuffixMatchNode */
303
  luaCtx.registerFunction<void (SuffixMatchNode::*)(const boost::variant<DNSName, std::string, LuaArray<DNSName>, LuaArray<std::string>>& name)>("add", [](SuffixMatchNode& smn, const boost::variant<DNSName, std::string, LuaArray<DNSName>, LuaArray<std::string>>& name) {
653✔
304
    if (name.type() == typeid(DNSName)) {
21✔
305
      const auto& actualName = boost::get<DNSName>(name);
7✔
306
      smn.add(actualName);
7✔
307
      return;
7✔
308
    }
7✔
309
    if (name.type() == typeid(std::string)) {
14✔
310
      const auto& actualName = boost::get<std::string>(name);
12✔
311
      smn.add(actualName);
12✔
312
      return;
12✔
313
    }
12✔
314
    if (name.type() == typeid(LuaArray<DNSName>)) {
2✔
315
      const auto& names = boost::get<LuaArray<DNSName>>(name);
1✔
316
      for (const auto& actualName : names) {
2✔
317
        smn.add(actualName.second);
2✔
318
      }
2✔
319
      return;
1✔
320
    }
1✔
321
    if (name.type() == typeid(LuaArray<std::string>)) {
1!
322
      const auto& names = boost::get<LuaArray<string>>(name);
1✔
323
      for (const auto& actualName : names) {
2✔
324
        smn.add(actualName.second);
2✔
325
      }
2✔
326
      return;
1✔
327
    }
1✔
328
  });
1✔
329
  luaCtx.registerFunction<void (SuffixMatchNode::*)(const boost::variant<DNSName, string, LuaArray<DNSName>, LuaArray<std::string>>& name)>("remove", [](SuffixMatchNode& smn, const boost::variant<DNSName, string, LuaArray<DNSName>, LuaArray<std::string>>& name) {
653✔
330
    if (name.type() == typeid(DNSName)) {
×
331
      const auto& actualName = boost::get<DNSName>(name);
332
      smn.remove(actualName);
333
      return;
334
    }
335
    if (name.type() == typeid(string)) {
×
336
      const auto& actualName = boost::get<string>(name);
337
      DNSName dnsName(actualName);
338
      smn.remove(dnsName);
339
      return;
340
    }
341
    if (name.type() == typeid(LuaArray<DNSName>)) {
×
342
      const auto& names = boost::get<LuaArray<DNSName>>(name);
343
      for (const auto& actualName : names) {
×
344
        smn.remove(actualName.second);
345
      }
346
      return;
347
    }
348
    if (name.type() == typeid(LuaArray<std::string>)) {
×
349
      const auto& names = boost::get<LuaArray<std::string>>(name);
350
      for (const auto& actualName : names) {
×
351
        DNSName dnsName(actualName.second);
352
        smn.remove(dnsName);
353
      }
354
      return;
355
    }
356
  });
357

358
  // clang-format off
359
  luaCtx.registerFunction("check", (bool (SuffixMatchNode::*)(const DNSName&) const) &SuffixMatchNode::check);
653✔
360
  // clang-format on
361
  luaCtx.registerFunction<boost::optional<DNSName> (SuffixMatchNode::*)(const DNSName&) const>("getBestMatch", [](const SuffixMatchNode& smn, const DNSName& needle) {
653✔
362
    boost::optional<DNSName> result{boost::none};
363
    auto res = smn.getBestMatch(needle);
364
    if (res) {
×
365
      result = *res;
366
    }
367
    return result;
368
  });
369
#endif /* DISABLE_SUFFIX_MATCH_BINDINGS */
653✔
370

371
#ifndef DISABLE_NETMASK_BINDINGS
653✔
372
  /* Netmask */
373
  luaCtx.writeFunction("newNetmask", [](boost::variant<std::string, ComboAddress> addrOrStr, boost::optional<uint8_t> bits) {
653✔
374
    if (addrOrStr.type() == typeid(ComboAddress)) {
×
375
      const auto& comboAddr = boost::get<ComboAddress>(addrOrStr);
376
      if (bits) {
×
377
        return Netmask(comboAddr, *bits);
378
      }
379
      return Netmask(comboAddr);
380
    }
381
    if (addrOrStr.type() == typeid(std::string)) {
×
382
      const auto& str = boost::get<std::string>(addrOrStr);
383
      return Netmask(str);
384
    }
385
    throw std::runtime_error("Invalid parameter passed to 'newNetmask()'");
386
  });
387
  luaCtx.registerFunction("empty", &Netmask::empty);
653✔
388
  luaCtx.registerFunction("getBits", &Netmask::getBits);
653✔
389
  luaCtx.registerFunction<ComboAddress (Netmask::*)() const>("getNetwork", [](const Netmask& netmask) { return netmask.getNetwork(); }); // const reference makes this necessary
653✔
390
  luaCtx.registerFunction<ComboAddress (Netmask::*)() const>("getMaskedNetwork", [](const Netmask& netmask) { return netmask.getMaskedNetwork(); });
653✔
391
  luaCtx.registerFunction("isIpv4", &Netmask::isIPv4);
653✔
392
  luaCtx.registerFunction("isIPv4", &Netmask::isIPv4);
653✔
393
  luaCtx.registerFunction("isIpv6", &Netmask::isIPv6);
653✔
394
  luaCtx.registerFunction("isIPv6", &Netmask::isIPv6);
653✔
395
  // clang-format off
396
  luaCtx.registerFunction("match", (bool (Netmask::*)(const string&) const) &Netmask::match);
653✔
397
  // clang-format on
398
  luaCtx.registerFunction("toString", &Netmask::toString);
653✔
399
  luaCtx.registerFunction("__tostring", &Netmask::toString);
653✔
400
  luaCtx.registerEqFunction(&Netmask::operator==);
653✔
401
  luaCtx.registerToStringFunction(&Netmask::toString);
653✔
402

403
  /* NetmaskGroup */
404
  luaCtx.writeFunction("newNMG", []() { return NetmaskGroup(); });
653✔
405
  luaCtx.registerFunction<void (NetmaskGroup::*)(const std::string& mask)>("addMask", [](NetmaskGroup& nmg, const std::string& mask) {
653✔
406
    nmg.addMask(mask);
6✔
407
  });
6✔
408
  luaCtx.registerFunction<void (NetmaskGroup::*)(const NetmaskGroup& otherNMG)>("addNMG", [](NetmaskGroup& nmg, const NetmaskGroup& otherNMG) {
653✔
409
    /* this is not going to be very efficient, sorry */
410
    auto entries = otherNMG.toStringVector();
2✔
411
    for (const auto& entry : entries) {
2✔
412
      nmg.addMask(entry);
2✔
413
    }
2✔
414
  });
2✔
415
  luaCtx.registerFunction<void (NetmaskGroup::*)(const std::map<ComboAddress, int>& map)>("addMasks", [](NetmaskGroup& nmg, const std::map<ComboAddress, int>& map) {
653✔
416
    for (const auto& entry : map) {
×
417
      nmg.addMask(Netmask(entry.first));
418
    }
419
  });
420

421
  // clang-format off
422
  luaCtx.registerFunction("match", (bool (NetmaskGroup::*)(const ComboAddress&) const) &NetmaskGroup::match);
653✔
423
  // clang-format on
424
  luaCtx.registerFunction("size", &NetmaskGroup::size);
653✔
425
  luaCtx.registerFunction("clear", &NetmaskGroup::clear);
653✔
426
  luaCtx.registerFunction<string (NetmaskGroup::*)() const>("toString", [](const NetmaskGroup& nmg) { return "NetmaskGroup " + nmg.toString(); });
653✔
427
  luaCtx.registerFunction<string (NetmaskGroup::*)() const>("__tostring", [](const NetmaskGroup& nmg) { return "NetmaskGroup " + nmg.toString(); });
653✔
428
#endif /* DISABLE_NETMASK_BINDINGS */
653✔
429

430
#ifndef DISABLE_QPS_LIMITER_BINDINGS
653✔
431
  /* QPSLimiter */
432
  luaCtx.writeFunction("newQPSLimiter", [](int rate, int burst) { return QPSLimiter(rate, burst); });
653✔
433
  luaCtx.registerFunction("check", &QPSLimiter::check);
653✔
434
#endif /* DISABLE_QPS_LIMITER_BINDINGS */
653✔
435

436
#ifndef DISABLE_CLIENT_STATE_BINDINGS
653✔
437
  /* ClientState */
438
  luaCtx.registerFunction<std::string (ClientState::*)() const>("toString", [](const ClientState& frontend) {
653✔
439
    setLuaNoSideEffect();
440
    return frontend.local.toStringWithPort();
441
  });
442
  luaCtx.registerFunction<std::string (ClientState::*)() const>("__tostring", [](const ClientState& frontend) {
653✔
443
    setLuaNoSideEffect();
444
    return frontend.local.toStringWithPort();
445
  });
446
  luaCtx.registerFunction<std::string (ClientState::*)() const>("getType", [](const ClientState& frontend) {
653✔
447
    setLuaNoSideEffect();
448
    return frontend.getType();
449
  });
450
  luaCtx.registerFunction<std::string (ClientState::*)() const>("getConfiguredTLSProvider", [](const ClientState& frontend) {
653✔
451
    setLuaNoSideEffect();
452
    if (frontend.doqFrontend != nullptr || frontend.doh3Frontend != nullptr) {
×
453
      return std::string("BoringSSL");
454
    }
455
    if (frontend.tlsFrontend != nullptr) {
×
456
      return frontend.tlsFrontend->getRequestedProvider();
457
    }
458
    if (frontend.dohFrontend != nullptr) {
×
459
      return std::string("openssl");
460
    }
461
    return std::string();
462
  });
463
  luaCtx.registerFunction<std::string (ClientState::*)() const>("getEffectiveTLSProvider", [](const ClientState& frontend) {
653✔
464
    setLuaNoSideEffect();
6✔
465
    if (frontend.doqFrontend != nullptr || frontend.doh3Frontend != nullptr) {
6!
466
      return std::string("BoringSSL");
467
    }
468
    if (frontend.tlsFrontend != nullptr) {
6!
469
      return frontend.tlsFrontend->getEffectiveProvider();
6✔
470
    }
6✔
471
    if (frontend.dohFrontend != nullptr) {
×
472
      return std::string("openssl");
473
    }
474
    return std::string();
475
  });
476
  luaCtx.registerMember("muted", &ClientState::muted);
653✔
477
#ifdef HAVE_EBPF
653✔
478
  luaCtx.registerFunction<void (ClientState::*)(std::shared_ptr<BPFFilter>)>("attachFilter", [](ClientState& frontend, std::shared_ptr<BPFFilter> bpf) {
653✔
479
    if (bpf) {
×
480
      frontend.attachFilter(bpf, frontend.getSocket());
481
    }
482
  });
483
  luaCtx.registerFunction<void (ClientState::*)()>("detachFilter", [](ClientState& frontend) {
653✔
484
    frontend.detachFilter(frontend.getSocket());
485
  });
486
#endif /* HAVE_EBPF */
653✔
487
#endif /* DISABLE_CLIENT_STATE_BINDINGS */
653✔
488

489
  /* BPF Filter */
490
#ifdef HAVE_EBPF
653✔
491
  using bpfopts_t = LuaAssociativeTable<boost::variant<bool, uint32_t, std::string>>;
653✔
492
  luaCtx.writeFunction("newBPFFilter", [client](bpfopts_t opts) {
653✔
493
    if (client) {
4!
494
      return std::shared_ptr<BPFFilter>(nullptr);
495
    }
496
    std::unordered_map<std::string, BPFFilter::MapConfiguration> mapsConfig;
4✔
497

498
    const auto convertParamsToConfig = [&](const std::string& name, BPFFilter::MapType type) {
20✔
499
      BPFFilter::MapConfiguration config;
20✔
500
      config.d_type = type;
20✔
501
      if (const string key = name + "MaxItems"; opts.count(key)) {
20✔
502
        const auto& tmp = opts.at(key);
12✔
503
        if (tmp.type() != typeid(uint32_t)) {
12!
504
          throw std::runtime_error("params is invalid");
505
        }
506
        const auto& params = boost::get<uint32_t>(tmp);
12✔
507
        config.d_maxItems = params;
12✔
508
      }
12✔
509

510
      if (const string key = name + "PinnedPath"; opts.count(key)) {
20!
511
        auto& tmp = opts.at(key);
512
        if (tmp.type() != typeid(string)) {
×
513
          throw std::runtime_error("params is invalid");
514
        }
515
        auto& params = boost::get<string>(tmp);
516
        config.d_pinnedPath = std::move(params);
517
      }
518
      mapsConfig[name] = std::move(config);
20✔
519
    };
20✔
520

521
    convertParamsToConfig("ipv4", BPFFilter::MapType::IPv4);
4✔
522
    convertParamsToConfig("ipv6", BPFFilter::MapType::IPv6);
4✔
523
    convertParamsToConfig("qnames", BPFFilter::MapType::QNames);
4✔
524
    convertParamsToConfig("cidr4", BPFFilter::MapType::CIDR4);
4✔
525
    convertParamsToConfig("cidr6", BPFFilter::MapType::CIDR6);
4✔
526

527
    BPFFilter::MapFormat format = BPFFilter::MapFormat::Legacy;
4✔
528
    bool external = false;
4✔
529
    if (opts.count("external") != 0) {
4!
530
      const auto& tmp = opts.at("external");
531
      if (tmp.type() != typeid(bool)) {
×
532
        throw std::runtime_error("params is invalid");
533
      }
534
      external = boost::get<bool>(tmp);
535
      if (external) {
×
536
        format = BPFFilter::MapFormat::WithActions;
537
      }
538
    }
539

540
    return std::make_shared<BPFFilter>(mapsConfig, format, external);
4✔
541
  });
4✔
542

543
  luaCtx.registerFunction<void (std::shared_ptr<BPFFilter>::*)(const ComboAddress& addr, boost::optional<uint32_t> action)>("block", [](const std::shared_ptr<BPFFilter>& bpf, const ComboAddress& addr, boost::optional<uint32_t> action) {
653✔
544
    if (bpf) {
3!
545
      if (!action) {
3!
546
        return bpf->block(addr, BPFFilter::MatchAction::Drop);
3✔
547
      }
3✔
548
      BPFFilter::MatchAction match{};
549

550
      switch (*action) {
551
      case 0:
×
552
        match = BPFFilter::MatchAction::Pass;
553
        break;
554
      case 1:
×
555
        match = BPFFilter::MatchAction::Drop;
556
        break;
557
      case 2:
×
558
        match = BPFFilter::MatchAction::Truncate;
559
        break;
560
      default:
×
561
        throw std::runtime_error("Unsupported action for BPFFilter::block");
562
      }
563
      return bpf->block(addr, match);
564
    }
565
  });
3✔
566
  luaCtx.registerFunction<void (std::shared_ptr<BPFFilter>::*)(const string& range, uint32_t action, boost::optional<bool> force)>("addRangeRule", [](const std::shared_ptr<BPFFilter>& bpf, const string& range, uint32_t action, boost::optional<bool> force) {
653✔
567
    if (!bpf) {
×
568
      return;
569
    }
570
    BPFFilter::MatchAction match{};
571
    switch (action) {
572
    case 0:
×
573
      match = BPFFilter::MatchAction::Pass;
574
      break;
575
    case 1:
×
576
      match = BPFFilter::MatchAction::Drop;
577
      break;
578
    case 2:
×
579
      match = BPFFilter::MatchAction::Truncate;
580
      break;
581
    default:
×
582
      throw std::runtime_error("Unsupported action for BPFFilter::block");
583
    }
584
    return bpf->addRangeRule(Netmask(range), force ? *force : false, match);
×
585
  });
586
  luaCtx.registerFunction<void (std::shared_ptr<BPFFilter>::*)(const DNSName& qname, boost::optional<uint16_t> qtype, boost::optional<uint32_t> action)>("blockQName", [](const std::shared_ptr<BPFFilter>& bpf, const DNSName& qname, boost::optional<uint16_t> qtype, boost::optional<uint32_t> action) {
653✔
587
    if (bpf) {
4!
588
      if (!action) {
4!
589
        return bpf->block(qname, BPFFilter::MatchAction::Drop, qtype ? *qtype : 255);
4!
590
      }
4✔
591
      BPFFilter::MatchAction match{};
592

593
      switch (*action) {
594
      case 0:
×
595
        match = BPFFilter::MatchAction::Pass;
596
        break;
597
      case 1:
×
598
        match = BPFFilter::MatchAction::Drop;
599
        break;
600
      case 2:
×
601
        match = BPFFilter::MatchAction::Truncate;
602
        break;
603
      default:
×
604
        throw std::runtime_error("Unsupported action for BPFFilter::blockQName");
605
      }
606
      return bpf->block(qname, match, qtype ? *qtype : 255);
×
607
    }
608
  });
4✔
609

610
  luaCtx.registerFunction<void (std::shared_ptr<BPFFilter>::*)(const ComboAddress& addr)>("unblock", [](const std::shared_ptr<BPFFilter>& bpf, const ComboAddress& addr) {
653✔
611
    if (bpf) {
5!
612
      return bpf->unblock(addr);
5✔
613
    }
5✔
614
  });
5✔
615
  luaCtx.registerFunction<void (std::shared_ptr<BPFFilter>::*)(const string& range)>("rmRangeRule", [](const std::shared_ptr<BPFFilter>& bpf, const string& range) {
653✔
616
    if (!bpf) {
×
617
      return;
618
    }
619
    bpf->rmRangeRule(Netmask(range));
620
  });
621
  luaCtx.registerFunction<std::string (std::shared_ptr<BPFFilter>::*)() const>("lsRangeRule", [](const std::shared_ptr<BPFFilter>& bpf) {
653✔
622
    setLuaNoSideEffect();
623
    std::string res;
624
    if (!bpf) {
×
625
      return res;
626
    }
627
    const auto rangeStat = bpf->getRangeRule();
628
    for (const auto& value : rangeStat) {
×
629
      if (value.first.isIPv4()) {
×
630
        res += BPFFilter::toString(value.second.action) + "\t " + value.first.toString() + "\n";
631
      }
632
      else if (value.first.isIPv6()) {
×
633
        res += BPFFilter::toString(value.second.action) + "\t[" + value.first.toString() + "]\n";
634
      }
635
    }
636
    return res;
637
  });
638
  luaCtx.registerFunction<void (std::shared_ptr<BPFFilter>::*)(const DNSName& qname, boost::optional<uint16_t> qtype)>("unblockQName", [](const std::shared_ptr<BPFFilter>& bpf, const DNSName& qname, boost::optional<uint16_t> qtype) {
653✔
639
    if (bpf) {
2!
640
      return bpf->unblock(qname, qtype ? *qtype : 255);
2!
641
    }
2✔
642
  });
2✔
643

644
  luaCtx.registerFunction<std::string (std::shared_ptr<BPFFilter>::*)() const>("getStats", [](const std::shared_ptr<BPFFilter>& bpf) {
653✔
645
    setLuaNoSideEffect();
2✔
646
    std::string res;
2✔
647
    if (bpf) {
2!
648
      auto stats = bpf->getAddrStats();
2✔
649
      for (const auto& value : stats) {
2✔
650
        if (value.first.sin4.sin_family == AF_INET) {
2!
651
          res += value.first.toString() + ": " + std::to_string(value.second) + "\n";
652
        }
653
        else if (value.first.sin4.sin_family == AF_INET6) {
2!
654
          res += "[" + value.first.toString() + "]: " + std::to_string(value.second) + "\n";
2✔
655
        }
2✔
656
      }
2✔
657
      const auto rangeStat = bpf->getRangeRule();
2✔
658
      for (const auto& value : rangeStat) {
2!
659
        if (value.first.isIPv4()) {
×
660
          res += BPFFilter::toString(value.second.action) + "\t " + value.first.toString() + ": " + std::to_string(value.second.counter) + "\n";
661
        }
662
        else if (value.first.isIPv6()) {
×
663
          res += BPFFilter::toString(value.second.action) + "\t[" + value.first.toString() + "]: " + std::to_string(value.second.counter) + "\n";
664
        }
665
      }
666
      auto qstats = bpf->getQNameStats();
2✔
667
      for (const auto& value : qstats) {
2✔
668
        res += std::get<0>(value).toString() + " " + std::to_string(std::get<1>(value)) + ": " + std::to_string(std::get<2>(value)) + "\n";
2✔
669
      }
2✔
670
    }
2✔
671
    return res;
2✔
672
  });
2✔
673

674
  luaCtx.registerFunction<void (std::shared_ptr<BPFFilter>::*)()>("attachToAllBinds", [](std::shared_ptr<BPFFilter>& bpf) {
653✔
675
    std::string res;
676
    if (!dnsdist::configuration::isImmutableConfigurationDone()) {
×
677
      throw std::runtime_error("attachToAllBinds() cannot be used at configuration time!");
678
      return;
679
    }
680
    if (bpf) {
×
681
      for (const auto& frontend : dnsdist::getFrontends()) {
×
682
        frontend->attachFilter(bpf, frontend->getSocket());
683
      }
684
    }
685
  });
686

687
  luaCtx.writeFunction("newDynBPFFilter", [client](std::shared_ptr<BPFFilter>& bpf) {
653✔
688
    if (client) {
×
689
      return std::shared_ptr<DynBPFFilter>(nullptr);
690
    }
691
    return std::make_shared<DynBPFFilter>(bpf);
692
  });
693

694
  luaCtx.registerFunction<void (std::shared_ptr<DynBPFFilter>::*)(const ComboAddress& addr, boost::optional<int> seconds)>("block", [](const std::shared_ptr<DynBPFFilter>& dbpf, const ComboAddress& addr, boost::optional<int> seconds) {
653✔
695
    if (dbpf) {
×
696
      timespec until{};
697
      clock_gettime(CLOCK_MONOTONIC, &until);
698
      until.tv_sec += seconds ? *seconds : 10;
×
699
      dbpf->block(addr, until);
700
    }
701
  });
702

703
  luaCtx.registerFunction<void (std::shared_ptr<DynBPFFilter>::*)()>("purgeExpired", [](const std::shared_ptr<DynBPFFilter>& dbpf) {
653✔
704
    if (dbpf) {
×
705
      timespec now{};
706
      clock_gettime(CLOCK_MONOTONIC, &now);
707
      dbpf->purgeExpired(now);
708
    }
709
  });
710

711
  luaCtx.registerFunction<void (std::shared_ptr<DynBPFFilter>::*)(LuaTypeOrArrayOf<std::string>)>("excludeRange", [](const std::shared_ptr<DynBPFFilter>& dbpf, LuaTypeOrArrayOf<std::string> ranges) {
653✔
712
    if (!dbpf) {
×
713
      return;
714
    }
715

716
    if (ranges.type() == typeid(LuaArray<std::string>)) {
×
717
      for (const auto& range : *boost::get<LuaArray<std::string>>(&ranges)) {
×
718
        dbpf->excludeRange(Netmask(range.second));
719
      }
720
    }
721
    else {
722
      dbpf->excludeRange(Netmask(*boost::get<std::string>(&ranges)));
723
    }
724
  });
725

726
  luaCtx.registerFunction<void (std::shared_ptr<DynBPFFilter>::*)(LuaTypeOrArrayOf<std::string>)>("includeRange", [](const std::shared_ptr<DynBPFFilter>& dbpf, LuaTypeOrArrayOf<std::string> ranges) {
653✔
727
    if (!dbpf) {
×
728
      return;
729
    }
730

731
    if (ranges.type() == typeid(LuaArray<std::string>)) {
×
732
      for (const auto& range : *boost::get<LuaArray<std::string>>(&ranges)) {
×
733
        dbpf->includeRange(Netmask(range.second));
734
      }
735
    }
736
    else {
737
      dbpf->includeRange(Netmask(*boost::get<std::string>(&ranges)));
738
    }
739
  });
740
#endif /* HAVE_EBPF */
653✔
741
#ifdef HAVE_XSK
653✔
742
  using xskopt_t = LuaAssociativeTable<boost::variant<uint32_t, std::string>>;
653✔
743
  luaCtx.writeFunction("newXsk", [client](xskopt_t opts) {
653✔
744
    if (dnsdist::configuration::isImmutableConfigurationDone()) {
×
745
      throw std::runtime_error("newXsk() only can be used at configuration time!");
×
746
    }
×
747
    if (client) {
×
748
      return std::shared_ptr<XskSocket>(nullptr);
×
749
    }
×
750
    uint32_t queue_id{};
×
751
    uint32_t frameNums{65536};
×
752
    std::string ifName;
×
753
    std::string path("/sys/fs/bpf/dnsdist/xskmap");
×
754
    if (opts.count("ifName") == 1) {
×
755
      ifName = boost::get<std::string>(opts.at("ifName"));
×
756
    }
×
757
    else {
×
758
      throw std::runtime_error("ifName field is required!");
×
759
    }
×
760
    if (opts.count("NIC_queue_id") == 1) {
×
761
      queue_id = boost::get<uint32_t>(opts.at("NIC_queue_id"));
×
762
    }
×
763
    else {
×
764
      throw std::runtime_error("NIC_queue_id field is required!");
×
765
    }
×
766
    if (opts.count("frameNums") == 1) {
×
767
      frameNums = boost::get<uint32_t>(opts.at("frameNums"));
×
768
    }
×
769
    if (opts.count("xskMapPath") == 1) {
×
770
      path = boost::get<std::string>(opts.at("xskMapPath"));
×
771
    }
×
772
    auto socket = std::make_shared<XskSocket>(frameNums, ifName, queue_id, path);
×
773
    dnsdist::xsk::g_xsk.push_back(socket);
×
774
    return socket;
×
775
  });
×
776
  luaCtx.registerFunction<std::string (std::shared_ptr<XskSocket>::*)() const>("getMetrics", [](const std::shared_ptr<XskSocket>& xsk) -> std::string {
653✔
777
    if (!xsk) {
×
778
      return {};
×
779
    }
×
780
    return xsk->getMetrics();
×
781
  });
×
782
#endif /* HAVE_XSK */
653✔
783
  /* EDNSOptionView */
784
  luaCtx.registerFunction<size_t (EDNSOptionView::*)() const>("count", [](const EDNSOptionView& option) {
653✔
785
    return option.values.size();
32✔
786
  });
32✔
787
  luaCtx.registerFunction<std::vector<string> (EDNSOptionView::*)() const>("getValues", [](const EDNSOptionView& option) {
653✔
788
    std::vector<string> values;
36✔
789
    values.reserve(values.size());
36✔
790
    for (const auto& value : option.values) {
44✔
791
      values.emplace_back(value.content, value.size);
44✔
792
    }
44✔
793
    return values;
36✔
794
  });
36✔
795

796
  luaCtx.writeFunction("newDOHResponseMapEntry", [](const std::string& regex, uint64_t status, const std::string& content, boost::optional<LuaAssociativeTable<std::string>> customHeaders) {
653✔
797
    checkParameterBound("newDOHResponseMapEntry", status, std::numeric_limits<uint16_t>::max());
4✔
798
    boost::optional<LuaAssociativeTable<std::string>> headers{boost::none};
4✔
799
    if (customHeaders) {
4!
800
      headers = LuaAssociativeTable<std::string>();
4✔
801
      for (const auto& header : *customHeaders) {
4✔
802
        (*headers)[boost::to_lower_copy(header.first)] = header.second;
4✔
803
      }
4✔
804
    }
4✔
805
    return std::make_shared<DOHResponseMapEntry>(regex, status, PacketBuffer(content.begin(), content.end()), headers);
4✔
806
  });
4✔
807

808
  luaCtx.writeFunction("newSVCRecordParameters", [](uint64_t priority, const std::string& target, boost::optional<svcParamsLua_t> additionalParameters) {
653✔
809
    checkParameterBound("newSVCRecordParameters", priority, std::numeric_limits<uint16_t>::max());
14✔
810
    SVCRecordParameters parameters;
14✔
811
    if (additionalParameters) {
14!
812
      parameters = parseSVCParameters(*additionalParameters);
14✔
813
    }
14✔
814
    parameters.priority = priority;
14✔
815
    parameters.target = DNSName(target);
14✔
816

817
    return parameters;
14✔
818
  });
14✔
819

820
  luaCtx.writeFunction("getListOfNetworkInterfaces", []() {
653✔
821
    LuaArray<std::string> result;
×
822
    auto itfs = getListOfNetworkInterfaces();
×
823
    int counter = 1;
×
824
    for (const auto& itf : itfs) {
×
825
      result.emplace_back(counter++, itf);
×
826
    }
×
827
    return result;
×
828
  });
×
829

830
  luaCtx.writeFunction("getListOfAddressesOfNetworkInterface", [](const std::string& itf) {
653✔
831
    LuaArray<std::string> result;
×
832
    auto addrs = getListOfAddressesOfNetworkInterface(itf);
×
833
    int counter = 1;
×
834
    for (const auto& addr : addrs) {
×
835
      result.emplace_back(counter++, addr.toString());
×
836
    }
×
837
    return result;
×
838
  });
×
839

840
  luaCtx.writeFunction("getListOfRangesOfNetworkInterface", [](const std::string& itf) {
653✔
841
    LuaArray<std::string> result;
×
842
    auto addrs = getListOfRangesOfNetworkInterface(itf);
×
843
    int counter = 1;
×
844
    for (const auto& addr : addrs) {
×
845
      result.emplace_back(counter++, addr.toString());
×
846
    }
×
847
    return result;
×
848
  });
×
849

850
  luaCtx.writeFunction("getMACAddress", [](const std::string& addr) {
653✔
851
    return getMACAddress(ComboAddress(addr));
×
852
  });
×
853

854
  luaCtx.writeFunction("getCurrentTime", []() -> timespec {
653✔
855
    timespec now{};
4✔
856
    if (gettime(&now, true) < 0) {
4!
857
      unixDie("Getting timestamp");
×
858
    }
×
859
    return now;
4✔
860
  });
4✔
861

862
  luaCtx.writeFunction("getAddressInfo", [client, configCheck](std::string hostname, std::function<void(const std::string& hostname, const LuaArray<ComboAddress>& ips)> callback) {
653✔
863
    if (client || configCheck) {
2!
864
      return;
1✔
865
    }
1✔
866
    std::thread newThread(dnsdist::resolver::asynchronousResolver, std::move(hostname), [callback = std::move(callback)](const std::string& resolvedHostname, std::vector<ComboAddress>& ips) {
1✔
867
      LuaArray<ComboAddress> result;
1✔
868
      result.reserve(ips.size());
1✔
869
      for (const auto& entry : ips) {
4✔
870
        result.emplace_back(result.size() + 1, entry);
4✔
871
      }
4✔
872
      {
1✔
873
        auto lua = g_lua.lock();
1✔
874
        callback(resolvedHostname, result);
1✔
875
        dnsdist::handleQueuedAsynchronousEvents();
1✔
876
      }
1✔
877
    });
1✔
878
    newThread.detach();
1✔
879
  });
1✔
880
}
653✔
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