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("add",(void (SuffixMatchNode::*)(const DNSName
&)) &SuffixMatchNode::add
);
209 g_lua
.registerFunction("check",(bool (SuffixMatchNode::*)(const DNSName
&) const) &SuffixMatchNode::check
);
212 g_lua
.writeFunction("newNMG", []() { return NetmaskGroup(); });
213 g_lua
.registerFunction
<void(NetmaskGroup::*)(const std::string
&mask
)>("addMask", [](NetmaskGroup
&nmg
, const std::string
& mask
)
217 g_lua
.registerFunction
<void(NetmaskGroup::*)(const std::map
<ComboAddress
,int>& map
)>("addMasks", [](NetmaskGroup
&nmg
, const std::map
<ComboAddress
,int>& map
)
219 for (const auto& entry
: map
) {
220 nmg
.addMask(Netmask(entry
.first
));
224 g_lua
.registerFunction("match", (bool (NetmaskGroup::*)(const ComboAddress
&) const)&NetmaskGroup::match
);
225 g_lua
.registerFunction("size", &NetmaskGroup::size
);
226 g_lua
.registerFunction("clear", &NetmaskGroup::clear
);
227 g_lua
.registerFunction
<string(NetmaskGroup::*)()>("toString", [](const NetmaskGroup
& nmg
) { return "NetmaskGroup " + nmg
.toString(); });
230 g_lua
.writeFunction("newQPSLimiter", [](int rate
, int burst
) { return QPSLimiter(rate
, burst
); });
231 g_lua
.registerFunction("check", &QPSLimiter::check
);
234 g_lua
.registerFunction
<std::string(ClientState::*)()>("toString", [](const ClientState
& fe
) {
235 setLuaNoSideEffect();
236 return fe
.local
.toStringWithPort();
238 g_lua
.registerMember("muted", &ClientState::muted
);
240 g_lua
.registerFunction
<void(ClientState::*)(std::shared_ptr
<BPFFilter
>)>("attachFilter", [](ClientState
& frontend
, std::shared_ptr
<BPFFilter
> bpf
) {
242 frontend
.attachFilter(bpf
);
245 g_lua
.registerFunction
<void(ClientState::*)()>("detachFilter", [](ClientState
& frontend
) {
246 frontend
.detachFilter();
248 #endif /* HAVE_EBPF */
251 g_lua
.writeFunction("newPacketCache", [](size_t maxEntries
, boost::optional
<uint32_t> maxTTL
, boost::optional
<uint32_t> minTTL
, boost::optional
<uint32_t> tempFailTTL
, boost::optional
<uint32_t> staleTTL
, boost::optional
<bool> dontAge
, boost::optional
<size_t> numberOfShards
, boost::optional
<bool> deferrableInsertLock
, boost::optional
<uint32_t> maxNegativeTTL
, boost::optional
<bool> ecsParsing
, boost::optional
<std::unordered_map
<std::string
, boost::variant
<bool, size_t>>> vars
) {
253 bool keepStaleData
= false;
257 if (vars
->count("deferrableInsertLock")) {
258 deferrableInsertLock
= boost::get
<bool>((*vars
)["deferrableInsertLock"]);
261 if (vars
->count("dontAge")) {
262 dontAge
= boost::get
<bool>((*vars
)["dontAge"]);
265 if (vars
->count("keepStaleData")) {
266 keepStaleData
= boost::get
<bool>((*vars
)["keepStaleData"]);
269 if (vars
->count("maxEntries")) {
270 maxEntries
= boost::get
<size_t>((*vars
)["maxEntries"]);
273 if (vars
->count("maxNegativeTTL")) {
274 maxNegativeTTL
= boost::get
<size_t>((*vars
)["maxNegativeTTL"]);
277 if (vars
->count("maxTTL")) {
278 maxTTL
= boost::get
<size_t>((*vars
)["maxTTL"]);
281 if (vars
->count("minTTL")) {
282 minTTL
= boost::get
<size_t>((*vars
)["minTTL"]);
285 if (vars
->count("numberOfShards")) {
286 numberOfShards
= boost::get
<size_t>((*vars
)["numberOfShards"]);
289 if (vars
->count("parseECS")) {
290 ecsParsing
= boost::get
<bool>((*vars
)["parseECS"]);
293 if (vars
->count("staleTTL")) {
294 staleTTL
= boost::get
<size_t>((*vars
)["staleTTL"]);
297 if (vars
->count("temporaryFailureTTL")) {
298 tempFailTTL
= boost::get
<size_t>((*vars
)["temporaryFailureTTL"]);
303 auto res
= std::make_shared
<DNSDistPacketCache
>(maxEntries
, maxTTL
? *maxTTL
: 86400, minTTL
? *minTTL
: 0, tempFailTTL
? *tempFailTTL
: 60, maxNegativeTTL
? *maxNegativeTTL
: 3600, staleTTL
? *staleTTL
: 60, dontAge
? *dontAge
: false, numberOfShards
? *numberOfShards
: 1, deferrableInsertLock
? *deferrableInsertLock
: true, ecsParsing
? *ecsParsing
: false);
305 res
->setKeepStaleData(keepStaleData
);
309 g_lua
.registerFunction("toString", &DNSDistPacketCache::toString
);
310 g_lua
.registerFunction("isFull", &DNSDistPacketCache::isFull
);
311 g_lua
.registerFunction("purgeExpired", &DNSDistPacketCache::purgeExpired
);
312 g_lua
.registerFunction("expunge", &DNSDistPacketCache::expunge
);
313 g_lua
.registerFunction
<void(std::shared_ptr
<DNSDistPacketCache
>::*)(const DNSName
& dname
, boost::optional
<uint16_t> qtype
, boost::optional
<bool> suffixMatch
)>("expungeByName", [](
314 std::shared_ptr
<DNSDistPacketCache
> cache
,
315 const DNSName
& dname
,
316 boost::optional
<uint16_t> qtype
,
317 boost::optional
<bool> suffixMatch
) {
319 cache
->expungeByName(dname
, qtype
? *qtype
: QType(QType::ANY
).getCode(), suffixMatch
? *suffixMatch
: false);
322 g_lua
.registerFunction
<void(std::shared_ptr
<DNSDistPacketCache
>::*)()>("printStats", [](const std::shared_ptr
<DNSDistPacketCache
> cache
) {
324 g_outputBuffer
="Entries: " + std::to_string(cache
->getEntriesCount()) + "/" + std::to_string(cache
->getMaxEntries()) + "\n";
325 g_outputBuffer
+="Hits: " + std::to_string(cache
->getHits()) + "\n";
326 g_outputBuffer
+="Misses: " + std::to_string(cache
->getMisses()) + "\n";
327 g_outputBuffer
+="Deferred inserts: " + std::to_string(cache
->getDeferredInserts()) + "\n";
328 g_outputBuffer
+="Deferred lookups: " + std::to_string(cache
->getDeferredLookups()) + "\n";
329 g_outputBuffer
+="Lookup Collisions: " + std::to_string(cache
->getLookupCollisions()) + "\n";
330 g_outputBuffer
+="Insert Collisions: " + std::to_string(cache
->getInsertCollisions()) + "\n";
331 g_outputBuffer
+="TTL Too Shorts: " + std::to_string(cache
->getTTLTooShorts()) + "\n";
334 g_lua
.registerFunction
<std::unordered_map
<std::string
, uint64_t>(std::shared_ptr
<DNSDistPacketCache
>::*)()>("getStats", [](const std::shared_ptr
<DNSDistPacketCache
> cache
) {
335 std::unordered_map
<std::string
, uint64_t> stats
;
337 stats
["entries"] = cache
->getEntriesCount();
338 stats
["maxEntries"] = cache
->getMaxEntries();
339 stats
["hits"] = cache
->getHits();
340 stats
["misses"] = cache
->getMisses();
341 stats
["deferredInserts"] = cache
->getDeferredInserts();
342 stats
["deferredLookups"] = cache
->getDeferredLookups();
343 stats
["lookupCollisions"] = cache
->getLookupCollisions();
344 stats
["insertCollisions"] = cache
->getInsertCollisions();
345 stats
["ttlTooShorts"] = cache
->getTTLTooShorts();
349 g_lua
.registerFunction
<void(std::shared_ptr
<DNSDistPacketCache
>::*)(const std::string
& fname
)>("dump", [](const std::shared_ptr
<DNSDistPacketCache
> cache
, const std::string
& fname
) {
352 int fd
= open(fname
.c_str(), O_CREAT
| O_EXCL
| O_WRONLY
, 0660);
354 g_outputBuffer
= "Error opening dump file for writing: " + string(strerror(errno
)) + "\n";
358 uint64_t records
= 0;
360 records
= cache
->dump(fd
);
362 catch (const std::exception
& e
) {
369 g_outputBuffer
+= "Dumped " + std::to_string(records
) + " records\n";
373 /* ProtobufMessage */
374 g_lua
.registerFunction
<void(DNSDistProtoBufMessage::*)(std::string
)>("setTag", [](DNSDistProtoBufMessage
& message
, const std::string
& strValue
) {
375 message
.addTag(strValue
);
377 g_lua
.registerFunction
<void(DNSDistProtoBufMessage::*)(vector
<pair
<int, string
>>)>("setTagArray", [](DNSDistProtoBufMessage
& message
, const vector
<pair
<int, string
>>&tags
) {
378 for (const auto& tag
: tags
) {
379 message
.addTag(tag
.second
);
382 g_lua
.registerFunction
<void(DNSDistProtoBufMessage::*)(boost::optional
<time_t> sec
, boost::optional
<uint32_t> uSec
)>("setProtobufResponseType",
383 [](DNSDistProtoBufMessage
& message
, boost::optional
<time_t> sec
, boost::optional
<uint32_t> uSec
) {
384 message
.setType(DNSProtoBufMessage::Response
);
385 message
.setQueryTime(sec
?*sec
:0, uSec
?*uSec
:0);
387 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
,
388 const std::string
& strQueryName
, uint16_t uType
, uint16_t uClass
, uint32_t uTTL
, const std::string
& strBlob
) {
389 message
.addRR(DNSName(strQueryName
), uType
, uClass
, uTTL
, strBlob
);
391 g_lua
.registerFunction
<void(DNSDistProtoBufMessage::*)(const Netmask
&)>("setEDNSSubnet", [](DNSDistProtoBufMessage
& message
, const Netmask
& subnet
) { message
.setEDNSSubnet(subnet
); });
392 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
); });
393 g_lua
.registerFunction
<void(DNSDistProtoBufMessage::*)(size_t)>("setBytes", [](DNSDistProtoBufMessage
& message
, size_t bytes
) { message
.setBytes(bytes
); });
394 g_lua
.registerFunction
<void(DNSDistProtoBufMessage::*)(time_t, uint32_t)>("setTime", [](DNSDistProtoBufMessage
& message
, time_t sec
, uint32_t usec
) { message
.setTime(sec
, usec
); });
395 g_lua
.registerFunction
<void(DNSDistProtoBufMessage::*)(time_t, uint32_t)>("setQueryTime", [](DNSDistProtoBufMessage
& message
, time_t sec
, uint32_t usec
) { message
.setQueryTime(sec
, usec
); });
396 g_lua
.registerFunction
<void(DNSDistProtoBufMessage::*)(uint8_t)>("setResponseCode", [](DNSDistProtoBufMessage
& message
, uint8_t rcode
) { message
.setResponseCode(rcode
); });
397 g_lua
.registerFunction
<std::string(DNSDistProtoBufMessage::*)()>("toDebugString", [](const DNSDistProtoBufMessage
& message
) { return message
.toDebugString(); });
398 g_lua
.registerFunction
<void(DNSDistProtoBufMessage::*)(const ComboAddress
&)>("setRequestor", [](DNSDistProtoBufMessage
& message
, const ComboAddress
& addr
) {
399 message
.setRequestor(addr
);
401 g_lua
.registerFunction
<void(DNSDistProtoBufMessage::*)(const std::string
&)>("setRequestorFromString", [](DNSDistProtoBufMessage
& message
, const std::string
& str
) {
402 message
.setRequestor(str
);
404 g_lua
.registerFunction
<void(DNSDistProtoBufMessage::*)(const ComboAddress
&)>("setResponder", [](DNSDistProtoBufMessage
& message
, const ComboAddress
& addr
) {
405 message
.setResponder(addr
);
407 g_lua
.registerFunction
<void(DNSDistProtoBufMessage::*)(const std::string
&)>("setResponderFromString", [](DNSDistProtoBufMessage
& message
, const std::string
& str
) {
408 message
.setResponder(str
);
410 g_lua
.registerFunction
<void(DNSDistProtoBufMessage::*)(const std::string
&)>("setServerIdentity", [](DNSDistProtoBufMessage
& message
, const std::string
& str
) {
411 message
.setServerIdentity(str
);
414 g_lua
.registerFunction
<std::string(DnstapMessage::*)()>("toDebugString", [](const DnstapMessage
& message
) { return message
.toDebugString(); });
415 g_lua
.registerFunction
<void(DnstapMessage::*)(const std::string
&)>("setExtra", [](DnstapMessage
& message
, const std::string
& str
) {
416 message
.setExtra(str
);
420 g_lua
.writeFunction("newRemoteLogger", [client
](const std::string
& remote
, boost::optional
<uint16_t> timeout
, boost::optional
<uint64_t> maxQueuedEntries
, boost::optional
<uint8_t> reconnectWaitTime
) {
421 return std::shared_ptr
<RemoteLoggerInterface
>(new RemoteLogger(ComboAddress(remote
), timeout
? *timeout
: 2, maxQueuedEntries
? (*maxQueuedEntries
*100) : 10000, reconnectWaitTime
? *reconnectWaitTime
: 1, client
));
424 g_lua
.writeFunction("newFrameStreamUnixLogger", [client
](const std::string
& address
) {
426 return std::shared_ptr
<RemoteLoggerInterface
>(new FrameStreamLogger(AF_UNIX
, address
, !client
));
428 throw std::runtime_error("fstrm support is required to build an AF_UNIX FrameStreamLogger");
429 #endif /* HAVE_FSTRM */
432 g_lua
.writeFunction("newFrameStreamTcpLogger", [client
](const std::string
& address
) {
433 #if defined(HAVE_FSTRM) && defined(HAVE_FSTRM_TCP_WRITER_INIT)
434 return std::shared_ptr
<RemoteLoggerInterface
>(new FrameStreamLogger(AF_INET
, address
, !client
));
436 throw std::runtime_error("fstrm with TCP support is required to build an AF_INET FrameStreamLogger");
437 #endif /* HAVE_FSTRM */
440 g_lua
.registerFunction("toString", &RemoteLoggerInterface::toString
);
443 /* DNSCryptContext bindings */
444 g_lua
.registerFunction
<std::string(DNSCryptContext::*)()>("getProviderName", [](const DNSCryptContext
& ctx
) { return ctx
.getProviderName().toStringNoDot(); });
445 g_lua
.registerFunction("markActive", &DNSCryptContext::markActive
);
446 g_lua
.registerFunction("markInactive", &DNSCryptContext::markInactive
);
447 g_lua
.registerFunction("removeInactiveCertificate", &DNSCryptContext::removeInactiveCertificate
);
448 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
) {
450 if (ctx
== nullptr) {
451 throw std::runtime_error("DNSCryptContext::loadNewCertificate() called on a nil value");
454 ctx
->loadNewCertificate(certFile
, keyFile
, active
? *active
: true);
456 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
) {
458 if (ctx
== nullptr) {
459 throw std::runtime_error("DNSCryptContext::addNewCertificate() called on a nil value");
462 ctx
->addNewCertificate(newCert
, newKey
, active
? *active
: true);
464 g_lua
.registerFunction
<std::map
<int, std::shared_ptr
<DNSCryptCertificatePair
>>(std::shared_ptr
<DNSCryptContext
>::*)()>("getCertificatePairs", [](std::shared_ptr
<DNSCryptContext
> ctx
) {
465 std::map
<int, std::shared_ptr
<DNSCryptCertificatePair
>> result
;
467 if (ctx
!= nullptr) {
469 for (auto pair
: ctx
->getCertificates()) {
470 result
[idx
++] = pair
;
477 g_lua
.registerFunction
<std::shared_ptr
<DNSCryptCertificatePair
>(std::shared_ptr
<DNSCryptContext
>::*)(size_t idx
)>("getCertificatePair", [](std::shared_ptr
<DNSCryptContext
> ctx
, size_t idx
) {
479 if (ctx
== nullptr) {
480 throw std::runtime_error("DNSCryptContext::getCertificatePair() called on a nil value");
483 std::shared_ptr
<DNSCryptCertificatePair
> result
= nullptr;
484 auto pairs
= ctx
->getCertificates();
485 if (idx
< pairs
.size()) {
486 result
= pairs
.at(idx
);
492 g_lua
.registerFunction
<const DNSCryptCert(std::shared_ptr
<DNSCryptContext
>::*)(size_t idx
)>("getCertificate", [](std::shared_ptr
<DNSCryptContext
> ctx
, size_t idx
) {
494 if (ctx
== nullptr) {
495 throw std::runtime_error("DNSCryptContext::getCertificate() called on a nil value");
498 auto pairs
= ctx
->getCertificates();
499 if (idx
< pairs
.size()) {
500 return pairs
.at(idx
)->cert
;
503 throw std::runtime_error("This DNSCrypt context has no certificate at index " + std::to_string(idx
));
506 g_lua
.registerFunction
<std::string(std::shared_ptr
<DNSCryptContext
>::*)()>("printCertificates", [](const std::shared_ptr
<DNSCryptContext
> ctx
) {
509 if (ctx
!= nullptr) {
511 boost::format
fmt("%1$-3d %|5t|%2$-8d %|10t|%3$-2d %|20t|%4$-21.21s %|41t|%5$-21.21s");
512 ret
<< (fmt
% "#" % "Serial" % "Version" % "From" % "To" ) << endl
;
514 for (auto pair
: ctx
->getCertificates()) {
515 const auto cert
= pair
->cert
;
516 const DNSCryptExchangeVersion version
= DNSCryptContext::getExchangeVersion(cert
);
518 ret
<< (fmt
% idx
% cert
.getSerial() % (version
== DNSCryptExchangeVersion::VERSION1
? 1 : 2) % DNSCryptContext::certificateDateToStr(cert
.getTSStart()) % DNSCryptContext::certificateDateToStr(cert
.getTSEnd())) << endl
;
525 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
) {
526 DNSCryptPrivateKey privateKey
;
530 if (generateDNSCryptCertificate(providerPrivateKeyFile
, serial
, begin
, end
, version
? *version
: DNSCryptExchangeVersion::VERSION1
, cert
, privateKey
)) {
531 ctx
.addNewCertificate(cert
, privateKey
);
534 catch(const std::exception
& e
) {
536 g_outputBuffer
="Error: "+string(e
.what())+"\n";
540 /* DNSCryptCertificatePair */
541 g_lua
.registerFunction
<const DNSCryptCert(std::shared_ptr
<DNSCryptCertificatePair
>::*)()>("getCertificate", [](const std::shared_ptr
<DNSCryptCertificatePair
> pair
) {
542 if (pair
== nullptr) {
543 throw std::runtime_error("DNSCryptCertificatePair::getCertificate() called on a nil value");
547 g_lua
.registerFunction
<bool(std::shared_ptr
<DNSCryptCertificatePair
>::*)()>("isActive", [](const std::shared_ptr
<DNSCryptCertificatePair
> pair
) {
548 if (pair
== nullptr) {
549 throw std::runtime_error("DNSCryptCertificatePair::isActive() called on a nil value");
555 g_lua
.registerFunction
<std::string(DNSCryptCert::*)()>("getMagic", [](const DNSCryptCert
& cert
) { return std::string(reinterpret_cast<const char*>(cert
.magic
), sizeof(cert
.magic
)); });
556 g_lua
.registerFunction
<std::string(DNSCryptCert::*)()>("getEsVersion", [](const DNSCryptCert
& cert
) { return std::string(reinterpret_cast<const char*>(cert
.esVersion
), sizeof(cert
.esVersion
)); });
557 g_lua
.registerFunction
<std::string(DNSCryptCert::*)()>("getProtocolMinorVersion", [](const DNSCryptCert
& cert
) { return std::string(reinterpret_cast<const char*>(cert
.protocolMinorVersion
), sizeof(cert
.protocolMinorVersion
)); });
558 g_lua
.registerFunction
<std::string(DNSCryptCert::*)()>("getSignature", [](const DNSCryptCert
& cert
) { return std::string(reinterpret_cast<const char*>(cert
.signature
), sizeof(cert
.signature
)); });
559 g_lua
.registerFunction
<std::string(DNSCryptCert::*)()>("getResolverPublicKey", [](const DNSCryptCert
& cert
) { return std::string(reinterpret_cast<const char*>(cert
.signedData
.resolverPK
), sizeof(cert
.signedData
.resolverPK
)); });
560 g_lua
.registerFunction
<std::string(DNSCryptCert::*)()>("getClientMagic", [](const DNSCryptCert
& cert
) { return std::string(reinterpret_cast<const char*>(cert
.signedData
.clientMagic
), sizeof(cert
.signedData
.clientMagic
)); });
561 g_lua
.registerFunction
<uint32_t(DNSCryptCert::*)()>("getSerial", [](const DNSCryptCert
& cert
) { return cert
.getSerial(); });
562 g_lua
.registerFunction
<uint32_t(DNSCryptCert::*)()>("getTSStart", [](const DNSCryptCert
& cert
) { return ntohl(cert
.getTSStart()); });
563 g_lua
.registerFunction
<uint32_t(DNSCryptCert::*)()>("getTSEnd", [](const DNSCryptCert
& cert
) { return ntohl(cert
.getTSEnd()); });
568 g_lua
.writeFunction("newBPFFilter", [client
](uint32_t maxV4
, uint32_t maxV6
, uint32_t maxQNames
) {
570 return std::shared_ptr
<BPFFilter
>(nullptr);
572 return std::make_shared
<BPFFilter
>(maxV4
, maxV6
, maxQNames
);
575 g_lua
.registerFunction
<void(std::shared_ptr
<BPFFilter
>::*)(const ComboAddress
& ca
)>("block", [](std::shared_ptr
<BPFFilter
> bpf
, const ComboAddress
& ca
) {
577 return bpf
->block(ca
);
581 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
) {
583 return bpf
->block(qname
, qtype
? *qtype
: 255);
587 g_lua
.registerFunction
<void(std::shared_ptr
<BPFFilter
>::*)(const ComboAddress
& ca
)>("unblock", [](std::shared_ptr
<BPFFilter
> bpf
, const ComboAddress
& ca
) {
589 return bpf
->unblock(ca
);
593 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
) {
595 return bpf
->unblock(qname
, qtype
? *qtype
: 255);
599 g_lua
.registerFunction
<std::string(std::shared_ptr
<BPFFilter
>::*)()>("getStats", [](const std::shared_ptr
<BPFFilter
> bpf
) {
600 setLuaNoSideEffect();
603 std::vector
<std::pair
<ComboAddress
, uint64_t> > stats
= bpf
->getAddrStats();
604 for (const auto& value
: stats
) {
605 if (value
.first
.sin4
.sin_family
== AF_INET
) {
606 res
+= value
.first
.toString() + ": " + std::to_string(value
.second
) + "\n";
608 else if (value
.first
.sin4
.sin_family
== AF_INET6
) {
609 res
+= "[" + value
.first
.toString() + "]: " + std::to_string(value
.second
) + "\n";
612 std::vector
<std::tuple
<DNSName
, uint16_t, uint64_t> > qstats
= bpf
->getQNameStats();
613 for (const auto& value
: qstats
) {
614 res
+= std::get
<0>(value
).toString() + " " + std::to_string(std::get
<1>(value
)) + ": " + std::to_string(std::get
<2>(value
)) + "\n";
620 g_lua
.registerFunction
<void(std::shared_ptr
<BPFFilter
>::*)()>("attachToAllBinds", [](std::shared_ptr
<BPFFilter
> bpf
) {
623 for (const auto& frontend
: g_frontends
) {
624 frontend
->attachFilter(bpf
);
629 g_lua
.writeFunction("newDynBPFFilter", [client
](std::shared_ptr
<BPFFilter
> bpf
) {
631 return std::shared_ptr
<DynBPFFilter
>(nullptr);
633 return std::make_shared
<DynBPFFilter
>(bpf
);
636 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
) {
638 struct timespec until
;
639 clock_gettime(CLOCK_MONOTONIC
, &until
);
640 until
.tv_sec
+= seconds
? *seconds
: 10;
641 dbpf
->block(addr
, until
);
645 g_lua
.registerFunction
<void(std::shared_ptr
<DynBPFFilter
>::*)()>("purgeExpired", [](std::shared_ptr
<DynBPFFilter
> dbpf
) {
648 clock_gettime(CLOCK_MONOTONIC
, &now
);
649 dbpf
->purgeExpired(now
);
653 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
) {
654 if (ranges
.type() == typeid(std::vector
<std::pair
<int, std::string
>>)) {
655 for (const auto& range
: *boost::get
<std::vector
<std::pair
<int, std::string
>>>(&ranges
)) {
656 dbpf
->excludeRange(Netmask(range
.second
));
660 dbpf
->excludeRange(Netmask(*boost::get
<std::string
>(&ranges
)));
664 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
) {
665 if (ranges
.type() == typeid(std::vector
<std::pair
<int, std::string
>>)) {
666 for (const auto& range
: *boost::get
<std::vector
<std::pair
<int, std::string
>>>(&ranges
)) {
667 dbpf
->includeRange(Netmask(range
.second
));
671 dbpf
->includeRange(Netmask(*boost::get
<std::string
>(&ranges
)));
674 #endif /* HAVE_EBPF */
677 g_lua
.registerFunction
<size_t(EDNSOptionView::*)()>("count", [](const EDNSOptionView
& option
) {
678 return option
.values
.size();
680 g_lua
.registerFunction
<std::vector
<string
>(EDNSOptionView::*)()>("getValues", [] (const EDNSOptionView
& option
) {
681 std::vector
<string
> values
;
682 for (const auto& value
: option
.values
) {
683 values
.push_back(std::string(value
.content
, value
.size
));