2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
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.
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.
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.
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.
24 #include <sys/types.h>
28 #include "dnsdist-lua.hh"
29 #include "dnsdist-protobuf.hh"
33 #include "fstrm_logger.hh"
34 #include "remote_logger.hh"
37 #include "ipcipher.hh"
38 #endif /* HAVE_LIBCRYPTO */
40 void setupLuaBindings(bool client
)
42 g_lua
.writeFunction("infolog", [](const string
& arg
) {
45 g_lua
.writeFunction("errlog", [](const string
& arg
) {
48 g_lua
.writeFunction("warnlog", [](const string
& arg
) {
51 g_lua
.writeFunction("show", [](const string
& arg
) {
57 g_lua
.registerFunction
<string(std::exception_ptr::*)()>("__tostring", [](const std::exception_ptr
& eptr
) {
60 std::rethrow_exception(eptr
);
62 } catch(const std::exception
& e
) {
63 return string(e
.what());
64 } catch(const PDNSException
& e
) {
67 return string("Unknown exception");
69 return string("No exception");
72 g_lua
.writeFunction("newServerPolicy", [](string name
, policyfunc_t policy
) { return ServerPolicy
{name
, policy
, true};});
73 g_lua
.registerMember("name", &ServerPolicy::name
);
74 g_lua
.registerMember("policy", &ServerPolicy::policy
);
75 g_lua
.registerMember("isLua", &ServerPolicy::isLua
);
76 g_lua
.registerFunction("toString", &ServerPolicy::toString
);
78 g_lua
.writeVariable("firstAvailable", ServerPolicy
{"firstAvailable", firstAvailable
, false});
79 g_lua
.writeVariable("roundrobin", ServerPolicy
{"roundrobin", roundrobin
, false});
80 g_lua
.writeVariable("wrandom", ServerPolicy
{"wrandom", wrandom
, false});
81 g_lua
.writeVariable("whashed", ServerPolicy
{"whashed", whashed
, false});
82 g_lua
.writeVariable("chashed", ServerPolicy
{"chashed", chashed
, false});
83 g_lua
.writeVariable("leastOutstanding", ServerPolicy
{"leastOutstanding", leastOutstanding
, false});
86 g_lua
.registerFunction
<void(std::shared_ptr
<ServerPool
>::*)(std::shared_ptr
<DNSDistPacketCache
>)>("setCache", [](std::shared_ptr
<ServerPool
> pool
, std::shared_ptr
<DNSDistPacketCache
> cache
) {
88 pool
->packetCache
= cache
;
91 g_lua
.registerFunction("getCache", &ServerPool::getCache
);
92 g_lua
.registerFunction
<void(std::shared_ptr
<ServerPool
>::*)()>("unsetCache", [](std::shared_ptr
<ServerPool
> pool
) {
94 pool
->packetCache
= nullptr;
97 g_lua
.registerFunction("getECS", &ServerPool::getECS
);
98 g_lua
.registerFunction("setECS", &ServerPool::setECS
);
100 /* DownstreamState */
101 g_lua
.registerFunction
<void(DownstreamState::*)(int)>("setQPS", [](DownstreamState
& s
, int lim
) { s
.qps
= lim
? QPSLimiter(lim
, lim
) : QPSLimiter(); });
102 g_lua
.registerFunction
<void(std::shared_ptr
<DownstreamState
>::*)(string
)>("addPool", [](std::shared_ptr
<DownstreamState
> s
, string pool
) {
103 auto localPools
= g_pools
.getCopy();
104 addServerToPool(localPools
, pool
, s
);
105 g_pools
.setState(localPools
);
106 s
->pools
.insert(pool
);
108 g_lua
.registerFunction
<void(std::shared_ptr
<DownstreamState
>::*)(string
)>("rmPool", [](std::shared_ptr
<DownstreamState
> s
, string pool
) {
109 auto localPools
= g_pools
.getCopy();
110 removeServerFromPool(localPools
, pool
, s
);
111 g_pools
.setState(localPools
);
112 s
->pools
.erase(pool
);
114 g_lua
.registerFunction
<uint64_t(DownstreamState::*)()>("getOutstanding", [](const DownstreamState
& s
) { return s
.outstanding
.load(); });
115 g_lua
.registerFunction("isUp", &DownstreamState::isUp
);
116 g_lua
.registerFunction("setDown", &DownstreamState::setDown
);
117 g_lua
.registerFunction("setUp", &DownstreamState::setUp
);
118 g_lua
.registerFunction
<void(DownstreamState::*)(boost::optional
<bool> newStatus
)>("setAuto", [](DownstreamState
& s
, boost::optional
<bool> newStatus
) {
120 s
.upStatus
= *newStatus
;
124 g_lua
.registerFunction("getName", &DownstreamState::getName
);
125 g_lua
.registerFunction("getNameWithAddr", &DownstreamState::getNameWithAddr
);
126 g_lua
.registerMember("upStatus", &DownstreamState::upStatus
);
127 g_lua
.registerMember
<int (DownstreamState::*)>("weight",
128 [](const DownstreamState
& s
) -> int {return s
.weight
;},
129 [](DownstreamState
& s
, int newWeight
) {s
.setWeight(newWeight
);}
131 g_lua
.registerMember("order", &DownstreamState::order
);
132 g_lua
.registerMember("name", &DownstreamState::name
);
135 g_lua
.registerFunction
<void(dnsheader::*)(bool)>("setRD", [](dnsheader
& dh
, bool v
) {
139 g_lua
.registerFunction
<bool(dnsheader::*)()>("getRD", [](dnsheader
& dh
) {
143 g_lua
.registerFunction
<void(dnsheader::*)(bool)>("setCD", [](dnsheader
& dh
, bool v
) {
147 g_lua
.registerFunction
<bool(dnsheader::*)()>("getCD", [](dnsheader
& dh
) {
151 g_lua
.registerFunction
<void(dnsheader::*)(bool)>("setTC", [](dnsheader
& dh
, bool v
) {
153 if(v
) dh
.ra
= dh
.rd
; // you'll always need this, otherwise TC=1 gets ignored
156 g_lua
.registerFunction
<void(dnsheader::*)(bool)>("setQR", [](dnsheader
& dh
, bool v
) {
161 g_lua
.writeFunction("newCA", [](const std::string
& name
) { return ComboAddress(name
); });
162 g_lua
.registerFunction
<string(ComboAddress::*)()>("tostring", [](const ComboAddress
& ca
) { return ca
.toString(); });
163 g_lua
.registerFunction
<string(ComboAddress::*)()>("tostringWithPort", [](const ComboAddress
& ca
) { return ca
.toStringWithPort(); });
164 g_lua
.registerFunction
<string(ComboAddress::*)()>("toString", [](const ComboAddress
& ca
) { return ca
.toString(); });
165 g_lua
.registerFunction
<string(ComboAddress::*)()>("toStringWithPort", [](const ComboAddress
& ca
) { return ca
.toStringWithPort(); });
166 g_lua
.registerFunction
<uint16_t(ComboAddress::*)()>("getPort", [](const ComboAddress
& ca
) { return ntohs(ca
.sin4
.sin_port
); } );
167 g_lua
.registerFunction
<void(ComboAddress::*)(unsigned int)>("truncate", [](ComboAddress
& ca
, unsigned int bits
) { ca
.truncate(bits
); });
168 g_lua
.registerFunction
<bool(ComboAddress::*)()>("isIPv4", [](const ComboAddress
& ca
) { return ca
.sin4
.sin_family
== AF_INET
; });
169 g_lua
.registerFunction
<bool(ComboAddress::*)()>("isIPv6", [](const ComboAddress
& ca
) { return ca
.sin4
.sin_family
== AF_INET6
; });
170 g_lua
.registerFunction
<bool(ComboAddress::*)()>("isMappedIPv4", [](const ComboAddress
& ca
) { return ca
.isMappedIPv4(); });
171 g_lua
.registerFunction
<ComboAddress(ComboAddress::*)()>("mapToIPv4", [](const ComboAddress
& ca
) { return ca
.mapToIPv4(); });
172 g_lua
.registerFunction
<bool(nmts_t::*)(const ComboAddress
&)>("match", [](nmts_t
& s
, const ComboAddress
& ca
) { return s
.match(ca
); });
174 #ifdef HAVE_LIBCRYPTO
175 g_lua
.registerFunction
<ComboAddress(ComboAddress::*)(const std::string
& key
)>("ipencrypt", [](const ComboAddress
& ca
, const std::string
& key
) {
176 return encryptCA(ca
, key
);
178 g_lua
.registerFunction
<ComboAddress(ComboAddress::*)(const std::string
& key
)>("ipdecrypt", [](const ComboAddress
& ca
, const std::string
& key
) {
179 return decryptCA(ca
, key
);
182 g_lua
.writeFunction("makeIPCipherKey", [](const std::string
& password
) {
183 return makeIPCipherKey(password
);
185 #endif /* HAVE_LIBCRYPTO */
188 g_lua
.registerFunction("isPartOf", &DNSName::isPartOf
);
189 g_lua
.registerFunction
<bool(DNSName::*)()>("chopOff", [](DNSName
&dn
) { return dn
.chopOff(); });
190 g_lua
.registerFunction
<unsigned int(DNSName::*)()>("countLabels", [](const DNSName
& name
) { return name
.countLabels(); });
191 g_lua
.registerFunction
<size_t(DNSName::*)()>("wirelength", [](const DNSName
& name
) { return name
.wirelength(); });
192 g_lua
.registerFunction
<string(DNSName::*)()>("tostring", [](const DNSName
&dn
) { return dn
.toString(); });
193 g_lua
.registerFunction
<string(DNSName::*)()>("toString", [](const DNSName
&dn
) { return dn
.toString(); });
194 g_lua
.writeFunction("newDNSName", [](const std::string
& name
) { return DNSName(name
); });
195 g_lua
.writeFunction("newSuffixMatchNode", []() { return SuffixMatchNode(); });
196 g_lua
.writeFunction("newDNSNameSet", []() { return DNSNameSet(); });
199 g_lua
.registerFunction
<string(DNSNameSet::*)()>("toString", [](const DNSNameSet
&dns
) { return dns
.toString(); });
200 g_lua
.registerFunction
<void(DNSNameSet::*)(DNSName
&)>("add", [](DNSNameSet
& dns
, DNSName
& dn
) { dns
.insert(dn
); });
201 g_lua
.registerFunction
<bool(DNSNameSet::*)(DNSName
&)>("check", [](DNSNameSet
& dns
, DNSName
& dn
) { return dns
.find(dn
) != dns
.end(); });
202 g_lua
.registerFunction("delete",(size_t (DNSNameSet::*)(const DNSName
&)) &DNSNameSet::erase
);
203 g_lua
.registerFunction("size",(size_t (DNSNameSet::*)() const) &DNSNameSet::size
);
204 g_lua
.registerFunction("clear",(void (DNSNameSet::*)()) &DNSNameSet::clear
);
205 g_lua
.registerFunction("empty",(bool (DNSNameSet::*)()) &DNSNameSet::empty
);
207 /* SuffixMatchNode */
208 g_lua
.registerFunction
<void (SuffixMatchNode::*)(const boost::variant
<DNSName
, string
, vector
<pair
<int, DNSName
>>, vector
<pair
<int, string
>>> &name
)>("add", [](SuffixMatchNode
&smn
, const boost::variant
<DNSName
, string
, vector
<pair
<int, DNSName
>>, vector
<pair
<int, string
>>> &name
) {
209 if (name
.type() == typeid(DNSName
)) {
210 auto n
= boost::get
<DNSName
>(name
);
214 if (name
.type() == typeid(string
)) {
215 auto n
= boost::get
<string
>(name
);
219 if (name
.type() == typeid(vector
<pair
<int, DNSName
>>)) {
220 auto names
= boost::get
<vector
<pair
<int, DNSName
>>>(name
);
221 for (auto const n
: names
) {
226 if (name
.type() == typeid(vector
<pair
<int, string
>>)) {
227 auto names
= boost::get
<vector
<pair
<int, string
>>>(name
);
228 for (auto const n
: names
) {
234 g_lua
.registerFunction("check",(bool (SuffixMatchNode::*)(const DNSName
&) const) &SuffixMatchNode::check
);
237 g_lua
.writeFunction("newNMG", []() { return NetmaskGroup(); });
238 g_lua
.registerFunction
<void(NetmaskGroup::*)(const std::string
&mask
)>("addMask", [](NetmaskGroup
&nmg
, const std::string
& mask
)
242 g_lua
.registerFunction
<void(NetmaskGroup::*)(const std::map
<ComboAddress
,int>& map
)>("addMasks", [](NetmaskGroup
&nmg
, const std::map
<ComboAddress
,int>& map
)
244 for (const auto& entry
: map
) {
245 nmg
.addMask(Netmask(entry
.first
));
249 g_lua
.registerFunction("match", (bool (NetmaskGroup::*)(const ComboAddress
&) const)&NetmaskGroup::match
);
250 g_lua
.registerFunction("size", &NetmaskGroup::size
);
251 g_lua
.registerFunction("clear", &NetmaskGroup::clear
);
252 g_lua
.registerFunction
<string(NetmaskGroup::*)()>("toString", [](const NetmaskGroup
& nmg
) { return "NetmaskGroup " + nmg
.toString(); });
255 g_lua
.writeFunction("newQPSLimiter", [](int rate
, int burst
) { return QPSLimiter(rate
, burst
); });
256 g_lua
.registerFunction("check", &QPSLimiter::check
);
259 g_lua
.registerFunction
<std::string(ClientState::*)()>("toString", [](const ClientState
& fe
) {
260 setLuaNoSideEffect();
261 return fe
.local
.toStringWithPort();
263 g_lua
.registerMember("muted", &ClientState::muted
);
265 g_lua
.registerFunction
<void(ClientState::*)(std::shared_ptr
<BPFFilter
>)>("attachFilter", [](ClientState
& frontend
, std::shared_ptr
<BPFFilter
> bpf
) {
267 frontend
.attachFilter(bpf
);
270 g_lua
.registerFunction
<void(ClientState::*)()>("detachFilter", [](ClientState
& frontend
) {
271 frontend
.detachFilter();
273 #endif /* HAVE_EBPF */
276 g_lua
.writeFunction("newPacketCache", [](size_t maxEntries
, boost::optional
<std::unordered_map
<std::string
, boost::variant
<bool, size_t>>> vars
) {
278 bool keepStaleData
= false;
279 size_t maxTTL
= 86400;
281 size_t tempFailTTL
= 60;
282 size_t maxNegativeTTL
= 3600;
283 size_t staleTTL
= 60;
284 size_t numberOfShards
= 1;
285 bool dontAge
= false;
286 bool deferrableInsertLock
= true;
287 bool ecsParsing
= false;
291 if (vars
->count("deferrableInsertLock")) {
292 deferrableInsertLock
= boost::get
<bool>((*vars
)["deferrableInsertLock"]);
295 if (vars
->count("dontAge")) {
296 dontAge
= boost::get
<bool>((*vars
)["dontAge"]);
299 if (vars
->count("keepStaleData")) {
300 keepStaleData
= boost::get
<bool>((*vars
)["keepStaleData"]);
303 if (vars
->count("maxNegativeTTL")) {
304 maxNegativeTTL
= boost::get
<size_t>((*vars
)["maxNegativeTTL"]);
307 if (vars
->count("maxTTL")) {
308 maxTTL
= boost::get
<size_t>((*vars
)["maxTTL"]);
311 if (vars
->count("minTTL")) {
312 minTTL
= boost::get
<size_t>((*vars
)["minTTL"]);
315 if (vars
->count("numberOfShards")) {
316 numberOfShards
= boost::get
<size_t>((*vars
)["numberOfShards"]);
319 if (vars
->count("parseECS")) {
320 ecsParsing
= boost::get
<bool>((*vars
)["parseECS"]);
323 if (vars
->count("staleTTL")) {
324 staleTTL
= boost::get
<size_t>((*vars
)["staleTTL"]);
327 if (vars
->count("temporaryFailureTTL")) {
328 tempFailTTL
= boost::get
<size_t>((*vars
)["temporaryFailureTTL"]);
332 auto res
= std::make_shared
<DNSDistPacketCache
>(maxEntries
, maxTTL
, minTTL
, tempFailTTL
, maxNegativeTTL
, staleTTL
, dontAge
, numberOfShards
, deferrableInsertLock
, ecsParsing
);
334 res
->setKeepStaleData(keepStaleData
);
338 g_lua
.registerFunction("toString", &DNSDistPacketCache::toString
);
339 g_lua
.registerFunction("isFull", &DNSDistPacketCache::isFull
);
340 g_lua
.registerFunction("purgeExpired", &DNSDistPacketCache::purgeExpired
);
341 g_lua
.registerFunction("expunge", &DNSDistPacketCache::expunge
);
342 g_lua
.registerFunction
<void(std::shared_ptr
<DNSDistPacketCache
>::*)(const DNSName
& dname
, boost::optional
<uint16_t> qtype
, boost::optional
<bool> suffixMatch
)>("expungeByName", [](
343 std::shared_ptr
<DNSDistPacketCache
> cache
,
344 const DNSName
& dname
,
345 boost::optional
<uint16_t> qtype
,
346 boost::optional
<bool> suffixMatch
) {
348 g_outputBuffer
="Expunged " + std::to_string(cache
->expungeByName(dname
, qtype
? *qtype
: QType(QType::ANY
).getCode(), suffixMatch
? *suffixMatch
: false)) + " records\n";
351 g_lua
.registerFunction
<void(std::shared_ptr
<DNSDistPacketCache
>::*)()>("printStats", [](const std::shared_ptr
<DNSDistPacketCache
> cache
) {
353 g_outputBuffer
="Entries: " + std::to_string(cache
->getEntriesCount()) + "/" + std::to_string(cache
->getMaxEntries()) + "\n";
354 g_outputBuffer
+="Hits: " + std::to_string(cache
->getHits()) + "\n";
355 g_outputBuffer
+="Misses: " + std::to_string(cache
->getMisses()) + "\n";
356 g_outputBuffer
+="Deferred inserts: " + std::to_string(cache
->getDeferredInserts()) + "\n";
357 g_outputBuffer
+="Deferred lookups: " + std::to_string(cache
->getDeferredLookups()) + "\n";
358 g_outputBuffer
+="Lookup Collisions: " + std::to_string(cache
->getLookupCollisions()) + "\n";
359 g_outputBuffer
+="Insert Collisions: " + std::to_string(cache
->getInsertCollisions()) + "\n";
360 g_outputBuffer
+="TTL Too Shorts: " + std::to_string(cache
->getTTLTooShorts()) + "\n";
363 g_lua
.registerFunction
<std::unordered_map
<std::string
, uint64_t>(std::shared_ptr
<DNSDistPacketCache
>::*)()>("getStats", [](const std::shared_ptr
<DNSDistPacketCache
> cache
) {
364 std::unordered_map
<std::string
, uint64_t> stats
;
366 stats
["entries"] = cache
->getEntriesCount();
367 stats
["maxEntries"] = cache
->getMaxEntries();
368 stats
["hits"] = cache
->getHits();
369 stats
["misses"] = cache
->getMisses();
370 stats
["deferredInserts"] = cache
->getDeferredInserts();
371 stats
["deferredLookups"] = cache
->getDeferredLookups();
372 stats
["lookupCollisions"] = cache
->getLookupCollisions();
373 stats
["insertCollisions"] = cache
->getInsertCollisions();
374 stats
["ttlTooShorts"] = cache
->getTTLTooShorts();
378 g_lua
.registerFunction
<void(std::shared_ptr
<DNSDistPacketCache
>::*)(const std::string
& fname
)>("dump", [](const std::shared_ptr
<DNSDistPacketCache
> cache
, const std::string
& fname
) {
381 int fd
= open(fname
.c_str(), O_CREAT
| O_EXCL
| O_WRONLY
, 0660);
383 g_outputBuffer
= "Error opening dump file for writing: " + string(strerror(errno
)) + "\n";
387 uint64_t records
= 0;
389 records
= cache
->dump(fd
);
391 catch (const std::exception
& e
) {
398 g_outputBuffer
+= "Dumped " + std::to_string(records
) + " records\n";
402 /* ProtobufMessage */
403 g_lua
.registerFunction
<void(DNSDistProtoBufMessage::*)(std::string
)>("setTag", [](DNSDistProtoBufMessage
& message
, const std::string
& strValue
) {
404 message
.addTag(strValue
);
406 g_lua
.registerFunction
<void(DNSDistProtoBufMessage::*)(vector
<pair
<int, string
>>)>("setTagArray", [](DNSDistProtoBufMessage
& message
, const vector
<pair
<int, string
>>&tags
) {
407 for (const auto& tag
: tags
) {
408 message
.addTag(tag
.second
);
411 g_lua
.registerFunction
<void(DNSDistProtoBufMessage::*)(boost::optional
<time_t> sec
, boost::optional
<uint32_t> uSec
)>("setProtobufResponseType",
412 [](DNSDistProtoBufMessage
& message
, boost::optional
<time_t> sec
, boost::optional
<uint32_t> uSec
) {
413 message
.setType(DNSProtoBufMessage::Response
);
414 message
.setQueryTime(sec
?*sec
:0, uSec
?*uSec
:0);
416 g_lua
.registerFunction
<void(DNSDistProtoBufMessage::*)(const std::string
& strQueryName
, uint16_t uType
, uint16_t uClass
, uint32_t uTTL
, const std::string
& strBlob
)>("addResponseRR", [](DNSDistProtoBufMessage
& message
,
417 const std::string
& strQueryName
, uint16_t uType
, uint16_t uClass
, uint32_t uTTL
, const std::string
& strBlob
) {
418 message
.addRR(DNSName(strQueryName
), uType
, uClass
, uTTL
, strBlob
);
420 g_lua
.registerFunction
<void(DNSDistProtoBufMessage::*)(const Netmask
&)>("setEDNSSubnet", [](DNSDistProtoBufMessage
& message
, const Netmask
& subnet
) { message
.setEDNSSubnet(subnet
); });
421 g_lua
.registerFunction
<void(DNSDistProtoBufMessage::*)(const DNSName
&, uint16_t, uint16_t)>("setQuestion", [](DNSDistProtoBufMessage
& message
, const DNSName
& qname
, uint16_t qtype
, uint16_t qclass
) { message
.setQuestion(qname
, qtype
, qclass
); });
422 g_lua
.registerFunction
<void(DNSDistProtoBufMessage::*)(size_t)>("setBytes", [](DNSDistProtoBufMessage
& message
, size_t bytes
) { message
.setBytes(bytes
); });
423 g_lua
.registerFunction
<void(DNSDistProtoBufMessage::*)(time_t, uint32_t)>("setTime", [](DNSDistProtoBufMessage
& message
, time_t sec
, uint32_t usec
) { message
.setTime(sec
, usec
); });
424 g_lua
.registerFunction
<void(DNSDistProtoBufMessage::*)(time_t, uint32_t)>("setQueryTime", [](DNSDistProtoBufMessage
& message
, time_t sec
, uint32_t usec
) { message
.setQueryTime(sec
, usec
); });
425 g_lua
.registerFunction
<void(DNSDistProtoBufMessage::*)(uint8_t)>("setResponseCode", [](DNSDistProtoBufMessage
& message
, uint8_t rcode
) { message
.setResponseCode(rcode
); });
426 g_lua
.registerFunction
<std::string(DNSDistProtoBufMessage::*)()>("toDebugString", [](const DNSDistProtoBufMessage
& message
) { return message
.toDebugString(); });
427 g_lua
.registerFunction
<void(DNSDistProtoBufMessage::*)(const ComboAddress
&)>("setRequestor", [](DNSDistProtoBufMessage
& message
, const ComboAddress
& addr
) {
428 message
.setRequestor(addr
);
430 g_lua
.registerFunction
<void(DNSDistProtoBufMessage::*)(const std::string
&)>("setRequestorFromString", [](DNSDistProtoBufMessage
& message
, const std::string
& str
) {
431 message
.setRequestor(str
);
433 g_lua
.registerFunction
<void(DNSDistProtoBufMessage::*)(const ComboAddress
&)>("setResponder", [](DNSDistProtoBufMessage
& message
, const ComboAddress
& addr
) {
434 message
.setResponder(addr
);
436 g_lua
.registerFunction
<void(DNSDistProtoBufMessage::*)(const std::string
&)>("setResponderFromString", [](DNSDistProtoBufMessage
& message
, const std::string
& str
) {
437 message
.setResponder(str
);
439 g_lua
.registerFunction
<void(DNSDistProtoBufMessage::*)(const std::string
&)>("setServerIdentity", [](DNSDistProtoBufMessage
& message
, const std::string
& str
) {
440 message
.setServerIdentity(str
);
443 g_lua
.registerFunction
<std::string(DnstapMessage::*)()>("toDebugString", [](const DnstapMessage
& message
) { return message
.toDebugString(); });
444 g_lua
.registerFunction
<void(DnstapMessage::*)(const std::string
&)>("setExtra", [](DnstapMessage
& message
, const std::string
& str
) {
445 message
.setExtra(str
);
449 g_lua
.writeFunction("newRemoteLogger", [client
](const std::string
& remote
, boost::optional
<uint16_t> timeout
, boost::optional
<uint64_t> maxQueuedEntries
, boost::optional
<uint8_t> reconnectWaitTime
) {
450 return std::shared_ptr
<RemoteLoggerInterface
>(new RemoteLogger(ComboAddress(remote
), timeout
? *timeout
: 2, maxQueuedEntries
? (*maxQueuedEntries
*100) : 10000, reconnectWaitTime
? *reconnectWaitTime
: 1, client
));
453 g_lua
.writeFunction("newFrameStreamUnixLogger", [client
](const std::string
& address
) {
455 return std::shared_ptr
<RemoteLoggerInterface
>(new FrameStreamLogger(AF_UNIX
, address
, !client
));
457 throw std::runtime_error("fstrm support is required to build an AF_UNIX FrameStreamLogger");
458 #endif /* HAVE_FSTRM */
461 g_lua
.writeFunction("newFrameStreamTcpLogger", [client
](const std::string
& address
) {
462 #if defined(HAVE_FSTRM) && defined(HAVE_FSTRM_TCP_WRITER_INIT)
463 return std::shared_ptr
<RemoteLoggerInterface
>(new FrameStreamLogger(AF_INET
, address
, !client
));
465 throw std::runtime_error("fstrm with TCP support is required to build an AF_INET FrameStreamLogger");
466 #endif /* HAVE_FSTRM */
469 g_lua
.registerFunction("toString", &RemoteLoggerInterface::toString
);
472 /* DNSCryptContext bindings */
473 g_lua
.registerFunction
<std::string(DNSCryptContext::*)()>("getProviderName", [](const DNSCryptContext
& ctx
) { return ctx
.getProviderName().toStringNoDot(); });
474 g_lua
.registerFunction("markActive", &DNSCryptContext::markActive
);
475 g_lua
.registerFunction("markInactive", &DNSCryptContext::markInactive
);
476 g_lua
.registerFunction("removeInactiveCertificate", &DNSCryptContext::removeInactiveCertificate
);
477 g_lua
.registerFunction
<void(std::shared_ptr
<DNSCryptContext
>::*)(const std::string
& certFile
, const std::string
& keyFile
, boost::optional
<bool> active
)>("loadNewCertificate", [](std::shared_ptr
<DNSCryptContext
> ctx
, const std::string
& certFile
, const std::string
& keyFile
, boost::optional
<bool> active
) {
479 if (ctx
== nullptr) {
480 throw std::runtime_error("DNSCryptContext::loadNewCertificate() called on a nil value");
483 ctx
->loadNewCertificate(certFile
, keyFile
, active
? *active
: true);
485 g_lua
.registerFunction
<void(std::shared_ptr
<DNSCryptContext
>::*)(const DNSCryptCert
& newCert
, const DNSCryptPrivateKey
& newKey
, boost::optional
<bool> active
)>("addNewCertificate", [](std::shared_ptr
<DNSCryptContext
> ctx
, const DNSCryptCert
& newCert
, const DNSCryptPrivateKey
& newKey
, boost::optional
<bool> active
) {
487 if (ctx
== nullptr) {
488 throw std::runtime_error("DNSCryptContext::addNewCertificate() called on a nil value");
491 ctx
->addNewCertificate(newCert
, newKey
, active
? *active
: true);
493 g_lua
.registerFunction
<std::map
<int, std::shared_ptr
<DNSCryptCertificatePair
>>(std::shared_ptr
<DNSCryptContext
>::*)()>("getCertificatePairs", [](std::shared_ptr
<DNSCryptContext
> ctx
) {
494 std::map
<int, std::shared_ptr
<DNSCryptCertificatePair
>> result
;
496 if (ctx
!= nullptr) {
498 for (auto pair
: ctx
->getCertificates()) {
499 result
[idx
++] = pair
;
506 g_lua
.registerFunction
<std::shared_ptr
<DNSCryptCertificatePair
>(std::shared_ptr
<DNSCryptContext
>::*)(size_t idx
)>("getCertificatePair", [](std::shared_ptr
<DNSCryptContext
> ctx
, size_t idx
) {
508 if (ctx
== nullptr) {
509 throw std::runtime_error("DNSCryptContext::getCertificatePair() called on a nil value");
512 std::shared_ptr
<DNSCryptCertificatePair
> result
= nullptr;
513 auto pairs
= ctx
->getCertificates();
514 if (idx
< pairs
.size()) {
515 result
= pairs
.at(idx
);
521 g_lua
.registerFunction
<const DNSCryptCert(std::shared_ptr
<DNSCryptContext
>::*)(size_t idx
)>("getCertificate", [](std::shared_ptr
<DNSCryptContext
> ctx
, size_t idx
) {
523 if (ctx
== nullptr) {
524 throw std::runtime_error("DNSCryptContext::getCertificate() called on a nil value");
527 auto pairs
= ctx
->getCertificates();
528 if (idx
< pairs
.size()) {
529 return pairs
.at(idx
)->cert
;
532 throw std::runtime_error("This DNSCrypt context has no certificate at index " + std::to_string(idx
));
535 g_lua
.registerFunction
<std::string(std::shared_ptr
<DNSCryptContext
>::*)()>("printCertificates", [](const std::shared_ptr
<DNSCryptContext
> ctx
) {
538 if (ctx
!= nullptr) {
540 boost::format
fmt("%1$-3d %|5t|%2$-8d %|10t|%3$-7d %|20t|%4$-21.21s %|41t|%5$-21.21s");
541 ret
<< (fmt
% "#" % "Serial" % "Version" % "From" % "To" ) << endl
;
543 for (auto pair
: ctx
->getCertificates()) {
544 const auto cert
= pair
->cert
;
545 const DNSCryptExchangeVersion version
= DNSCryptContext::getExchangeVersion(cert
);
547 ret
<< (fmt
% idx
% cert
.getSerial() % (version
== DNSCryptExchangeVersion::VERSION1
? 1 : 2) % DNSCryptContext::certificateDateToStr(cert
.getTSStart()) % DNSCryptContext::certificateDateToStr(cert
.getTSEnd())) << endl
;
554 g_lua
.registerFunction
<void(DNSCryptContext::*)(const std::string
& providerPrivateKeyFile
, uint32_t serial
, time_t begin
, time_t end
, boost::optional
<DNSCryptExchangeVersion
> version
)>("generateAndLoadInMemoryCertificate", [](DNSCryptContext
& ctx
, const std::string
& providerPrivateKeyFile
, uint32_t serial
, time_t begin
, time_t end
, boost::optional
<DNSCryptExchangeVersion
> version
) {
555 DNSCryptPrivateKey privateKey
;
559 if (generateDNSCryptCertificate(providerPrivateKeyFile
, serial
, begin
, end
, version
? *version
: DNSCryptExchangeVersion::VERSION1
, cert
, privateKey
)) {
560 ctx
.addNewCertificate(cert
, privateKey
);
563 catch(const std::exception
& e
) {
565 g_outputBuffer
="Error: "+string(e
.what())+"\n";
569 /* DNSCryptCertificatePair */
570 g_lua
.registerFunction
<const DNSCryptCert(std::shared_ptr
<DNSCryptCertificatePair
>::*)()>("getCertificate", [](const std::shared_ptr
<DNSCryptCertificatePair
> pair
) {
571 if (pair
== nullptr) {
572 throw std::runtime_error("DNSCryptCertificatePair::getCertificate() called on a nil value");
576 g_lua
.registerFunction
<bool(std::shared_ptr
<DNSCryptCertificatePair
>::*)()>("isActive", [](const std::shared_ptr
<DNSCryptCertificatePair
> pair
) {
577 if (pair
== nullptr) {
578 throw std::runtime_error("DNSCryptCertificatePair::isActive() called on a nil value");
584 g_lua
.registerFunction
<std::string(DNSCryptCert::*)()>("getMagic", [](const DNSCryptCert
& cert
) { return std::string(reinterpret_cast<const char*>(cert
.magic
), sizeof(cert
.magic
)); });
585 g_lua
.registerFunction
<std::string(DNSCryptCert::*)()>("getEsVersion", [](const DNSCryptCert
& cert
) { return std::string(reinterpret_cast<const char*>(cert
.esVersion
), sizeof(cert
.esVersion
)); });
586 g_lua
.registerFunction
<std::string(DNSCryptCert::*)()>("getProtocolMinorVersion", [](const DNSCryptCert
& cert
) { return std::string(reinterpret_cast<const char*>(cert
.protocolMinorVersion
), sizeof(cert
.protocolMinorVersion
)); });
587 g_lua
.registerFunction
<std::string(DNSCryptCert::*)()>("getSignature", [](const DNSCryptCert
& cert
) { return std::string(reinterpret_cast<const char*>(cert
.signature
), sizeof(cert
.signature
)); });
588 g_lua
.registerFunction
<std::string(DNSCryptCert::*)()>("getResolverPublicKey", [](const DNSCryptCert
& cert
) { return std::string(reinterpret_cast<const char*>(cert
.signedData
.resolverPK
), sizeof(cert
.signedData
.resolverPK
)); });
589 g_lua
.registerFunction
<std::string(DNSCryptCert::*)()>("getClientMagic", [](const DNSCryptCert
& cert
) { return std::string(reinterpret_cast<const char*>(cert
.signedData
.clientMagic
), sizeof(cert
.signedData
.clientMagic
)); });
590 g_lua
.registerFunction
<uint32_t(DNSCryptCert::*)()>("getSerial", [](const DNSCryptCert
& cert
) { return cert
.getSerial(); });
591 g_lua
.registerFunction
<uint32_t(DNSCryptCert::*)()>("getTSStart", [](const DNSCryptCert
& cert
) { return ntohl(cert
.getTSStart()); });
592 g_lua
.registerFunction
<uint32_t(DNSCryptCert::*)()>("getTSEnd", [](const DNSCryptCert
& cert
) { return ntohl(cert
.getTSEnd()); });
597 g_lua
.writeFunction("newBPFFilter", [client
](uint32_t maxV4
, uint32_t maxV6
, uint32_t maxQNames
) {
599 return std::shared_ptr
<BPFFilter
>(nullptr);
601 return std::make_shared
<BPFFilter
>(maxV4
, maxV6
, maxQNames
);
604 g_lua
.registerFunction
<void(std::shared_ptr
<BPFFilter
>::*)(const ComboAddress
& ca
)>("block", [](std::shared_ptr
<BPFFilter
> bpf
, const ComboAddress
& ca
) {
606 return bpf
->block(ca
);
610 g_lua
.registerFunction
<void(std::shared_ptr
<BPFFilter
>::*)(const DNSName
& qname
, boost::optional
<uint16_t> qtype
)>("blockQName", [](std::shared_ptr
<BPFFilter
> bpf
, const DNSName
& qname
, boost::optional
<uint16_t> qtype
) {
612 return bpf
->block(qname
, qtype
? *qtype
: 255);
616 g_lua
.registerFunction
<void(std::shared_ptr
<BPFFilter
>::*)(const ComboAddress
& ca
)>("unblock", [](std::shared_ptr
<BPFFilter
> bpf
, const ComboAddress
& ca
) {
618 return bpf
->unblock(ca
);
622 g_lua
.registerFunction
<void(std::shared_ptr
<BPFFilter
>::*)(const DNSName
& qname
, boost::optional
<uint16_t> qtype
)>("unblockQName", [](std::shared_ptr
<BPFFilter
> bpf
, const DNSName
& qname
, boost::optional
<uint16_t> qtype
) {
624 return bpf
->unblock(qname
, qtype
? *qtype
: 255);
628 g_lua
.registerFunction
<std::string(std::shared_ptr
<BPFFilter
>::*)()>("getStats", [](const std::shared_ptr
<BPFFilter
> bpf
) {
629 setLuaNoSideEffect();
632 std::vector
<std::pair
<ComboAddress
, uint64_t> > stats
= bpf
->getAddrStats();
633 for (const auto& value
: stats
) {
634 if (value
.first
.sin4
.sin_family
== AF_INET
) {
635 res
+= value
.first
.toString() + ": " + std::to_string(value
.second
) + "\n";
637 else if (value
.first
.sin4
.sin_family
== AF_INET6
) {
638 res
+= "[" + value
.first
.toString() + "]: " + std::to_string(value
.second
) + "\n";
641 std::vector
<std::tuple
<DNSName
, uint16_t, uint64_t> > qstats
= bpf
->getQNameStats();
642 for (const auto& value
: qstats
) {
643 res
+= std::get
<0>(value
).toString() + " " + std::to_string(std::get
<1>(value
)) + ": " + std::to_string(std::get
<2>(value
)) + "\n";
649 g_lua
.registerFunction
<void(std::shared_ptr
<BPFFilter
>::*)()>("attachToAllBinds", [](std::shared_ptr
<BPFFilter
> bpf
) {
652 for (const auto& frontend
: g_frontends
) {
653 frontend
->attachFilter(bpf
);
658 g_lua
.writeFunction("newDynBPFFilter", [client
](std::shared_ptr
<BPFFilter
> bpf
) {
660 return std::shared_ptr
<DynBPFFilter
>(nullptr);
662 return std::make_shared
<DynBPFFilter
>(bpf
);
665 g_lua
.registerFunction
<void(std::shared_ptr
<DynBPFFilter
>::*)(const ComboAddress
& addr
, boost::optional
<int> seconds
)>("block", [](std::shared_ptr
<DynBPFFilter
> dbpf
, const ComboAddress
& addr
, boost::optional
<int> seconds
) {
667 struct timespec until
;
668 clock_gettime(CLOCK_MONOTONIC
, &until
);
669 until
.tv_sec
+= seconds
? *seconds
: 10;
670 dbpf
->block(addr
, until
);
674 g_lua
.registerFunction
<void(std::shared_ptr
<DynBPFFilter
>::*)()>("purgeExpired", [](std::shared_ptr
<DynBPFFilter
> dbpf
) {
677 clock_gettime(CLOCK_MONOTONIC
, &now
);
678 dbpf
->purgeExpired(now
);
682 g_lua
.registerFunction
<void(std::shared_ptr
<DynBPFFilter
>::*)(boost::variant
<std::string
, std::vector
<std::pair
<int, std::string
>>>)>("excludeRange", [](std::shared_ptr
<DynBPFFilter
> dbpf
, boost::variant
<std::string
, std::vector
<std::pair
<int, std::string
>>> ranges
) {
683 if (ranges
.type() == typeid(std::vector
<std::pair
<int, std::string
>>)) {
684 for (const auto& range
: *boost::get
<std::vector
<std::pair
<int, std::string
>>>(&ranges
)) {
685 dbpf
->excludeRange(Netmask(range
.second
));
689 dbpf
->excludeRange(Netmask(*boost::get
<std::string
>(&ranges
)));
693 g_lua
.registerFunction
<void(std::shared_ptr
<DynBPFFilter
>::*)(boost::variant
<std::string
, std::vector
<std::pair
<int, std::string
>>>)>("includeRange", [](std::shared_ptr
<DynBPFFilter
> dbpf
, boost::variant
<std::string
, std::vector
<std::pair
<int, std::string
>>> ranges
) {
694 if (ranges
.type() == typeid(std::vector
<std::pair
<int, std::string
>>)) {
695 for (const auto& range
: *boost::get
<std::vector
<std::pair
<int, std::string
>>>(&ranges
)) {
696 dbpf
->includeRange(Netmask(range
.second
));
700 dbpf
->includeRange(Netmask(*boost::get
<std::string
>(&ranges
)));
703 #endif /* HAVE_EBPF */
706 g_lua
.registerFunction
<size_t(EDNSOptionView::*)()>("count", [](const EDNSOptionView
& option
) {
707 return option
.values
.size();
709 g_lua
.registerFunction
<std::vector
<string
>(EDNSOptionView::*)()>("getValues", [] (const EDNSOptionView
& option
) {
710 std::vector
<string
> values
;
711 for (const auto& value
: option
.values
) {
712 values
.push_back(std::string(value
.content
, value
.size
));