]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/dnsdist-lua-bindings.cc
Reduce systemcall usage in protobuf logging
[thirdparty/pdns.git] / pdns / dnsdist-lua-bindings.cc
CommitLineData
6bb38cd6
RG
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 */
f037144c
RG
22#include <fcntl.h>
23#include <sys/stat.h>
24#include <sys/types.h>
25
6bb38cd6
RG
26#include "dnsdist.hh"
27#include "dnsdist-lua.hh"
28#include "dnsdist-protobuf.hh"
29
82a91ddf 30#include "dnstap.hh"
6bb38cd6 31#include "dolog.hh"
82a91ddf 32#include "fstrm_logger.hh"
6bb38cd6
RG
33#include "remote_logger.hh"
34
35void setupLuaBindings(bool client)
36{
37 g_lua.writeFunction("infolog", [](const string& arg) {
38 infolog("%s", arg);
39 });
40 g_lua.writeFunction("errlog", [](const string& arg) {
41 errlog("%s", arg);
42 });
43 g_lua.writeFunction("warnlog", [](const string& arg) {
44 warnlog("%s", arg);
45 });
46 g_lua.writeFunction("show", [](const string& arg) {
47 g_outputBuffer+=arg;
48 g_outputBuffer+="\n";
49 });
50
f5aff975
CHB
51 /* Exceptions */
52 g_lua.registerFunction<string(std::exception_ptr::*)()>("__tostring", [](const std::exception_ptr& eptr) {
53 try {
54 if (eptr) {
55 std::rethrow_exception(eptr);
56 }
57 } catch(const std::exception& e) {
58 return string(e.what());
59 } catch(const PDNSException& e) {
60 return e.reason;
61 } catch(...) {
62 return string("Unknown exception");
63 }
64 return string("No exception");
65 });
6bb38cd6 66 /* ServerPolicy */
a1b1a29d 67 g_lua.writeFunction("newServerPolicy", [](string name, policyfunc_t policy) { return ServerPolicy{name, policy, true};});
6bb38cd6
RG
68 g_lua.registerMember("name", &ServerPolicy::name);
69 g_lua.registerMember("policy", &ServerPolicy::policy);
a1b1a29d 70 g_lua.registerMember("isLua", &ServerPolicy::isLua);
a4fd2d2f 71 g_lua.registerFunction("toString", &ServerPolicy::toString);
6bb38cd6 72
a1b1a29d
RG
73 g_lua.writeVariable("firstAvailable", ServerPolicy{"firstAvailable", firstAvailable, false});
74 g_lua.writeVariable("roundrobin", ServerPolicy{"roundrobin", roundrobin, false});
75 g_lua.writeVariable("wrandom", ServerPolicy{"wrandom", wrandom, false});
76 g_lua.writeVariable("whashed", ServerPolicy{"whashed", whashed, false});
1720247e 77 g_lua.writeVariable("chashed", ServerPolicy{"chashed", chashed, false});
a1b1a29d 78 g_lua.writeVariable("leastOutstanding", ServerPolicy{"leastOutstanding", leastOutstanding, false});
6bb38cd6
RG
79
80 /* ServerPool */
81 g_lua.registerFunction<void(std::shared_ptr<ServerPool>::*)(std::shared_ptr<DNSDistPacketCache>)>("setCache", [](std::shared_ptr<ServerPool> pool, std::shared_ptr<DNSDistPacketCache> cache) {
82 if (pool) {
83 pool->packetCache = cache;
84 }
85 });
86 g_lua.registerFunction("getCache", &ServerPool::getCache);
87 g_lua.registerFunction<void(std::shared_ptr<ServerPool>::*)()>("unsetCache", [](std::shared_ptr<ServerPool> pool) {
88 if (pool) {
89 pool->packetCache = nullptr;
90 }
91 });
7e687744
RG
92 g_lua.registerFunction("getECS", &ServerPool::getECS);
93 g_lua.registerFunction("setECS", &ServerPool::setECS);
6bb38cd6
RG
94
95 /* DownstreamState */
96 g_lua.registerFunction<void(DownstreamState::*)(int)>("setQPS", [](DownstreamState& s, int lim) { s.qps = lim ? QPSLimiter(lim, lim) : QPSLimiter(); });
97 g_lua.registerFunction<void(std::shared_ptr<DownstreamState>::*)(string)>("addPool", [](std::shared_ptr<DownstreamState> s, string pool) {
98 auto localPools = g_pools.getCopy();
99 addServerToPool(localPools, pool, s);
100 g_pools.setState(localPools);
101 s->pools.insert(pool);
102 });
103 g_lua.registerFunction<void(std::shared_ptr<DownstreamState>::*)(string)>("rmPool", [](std::shared_ptr<DownstreamState> s, string pool) {
104 auto localPools = g_pools.getCopy();
105 removeServerFromPool(localPools, pool, s);
106 g_pools.setState(localPools);
107 s->pools.erase(pool);
108 });
2831298d 109 g_lua.registerFunction<uint64_t(DownstreamState::*)()>("getOutstanding", [](const DownstreamState& s) { return s.outstanding.load(); });
6bb38cd6
RG
110 g_lua.registerFunction("isUp", &DownstreamState::isUp);
111 g_lua.registerFunction("setDown", &DownstreamState::setDown);
112 g_lua.registerFunction("setUp", &DownstreamState::setUp);
113 g_lua.registerFunction<void(DownstreamState::*)(boost::optional<bool> newStatus)>("setAuto", [](DownstreamState& s, boost::optional<bool> newStatus) {
114 if (newStatus) {
115 s.upStatus = *newStatus;
116 }
117 s.setAuto();
118 });
119 g_lua.registerFunction("getName", &DownstreamState::getName);
120 g_lua.registerFunction("getNameWithAddr", &DownstreamState::getNameWithAddr);
121 g_lua.registerMember("upStatus", &DownstreamState::upStatus);
5a2bbe8c
CHB
122 g_lua.registerMember<int (DownstreamState::*)>("weight",
123 [](const DownstreamState& s) -> int {return s.weight;},
124 [](DownstreamState& s, int newWeight) {s.setWeight(newWeight);}
125 );
6bb38cd6
RG
126 g_lua.registerMember("order", &DownstreamState::order);
127 g_lua.registerMember("name", &DownstreamState::name);
128
129 /* dnsheader */
130 g_lua.registerFunction<void(dnsheader::*)(bool)>("setRD", [](dnsheader& dh, bool v) {
131 dh.rd=v;
132 });
133
134 g_lua.registerFunction<bool(dnsheader::*)()>("getRD", [](dnsheader& dh) {
135 return (bool)dh.rd;
136 });
137
138 g_lua.registerFunction<void(dnsheader::*)(bool)>("setCD", [](dnsheader& dh, bool v) {
139 dh.cd=v;
140 });
141
142 g_lua.registerFunction<bool(dnsheader::*)()>("getCD", [](dnsheader& dh) {
143 return (bool)dh.cd;
144 });
145
146 g_lua.registerFunction<void(dnsheader::*)(bool)>("setTC", [](dnsheader& dh, bool v) {
147 dh.tc=v;
148 if(v) dh.ra = dh.rd; // you'll always need this, otherwise TC=1 gets ignored
149 });
150
151 g_lua.registerFunction<void(dnsheader::*)(bool)>("setQR", [](dnsheader& dh, bool v) {
152 dh.qr=v;
153 });
154
155 /* ComboAddress */
156 g_lua.writeFunction("newCA", [](const std::string& name) { return ComboAddress(name); });
157 g_lua.registerFunction<string(ComboAddress::*)()>("tostring", [](const ComboAddress& ca) { return ca.toString(); });
158 g_lua.registerFunction<string(ComboAddress::*)()>("tostringWithPort", [](const ComboAddress& ca) { return ca.toStringWithPort(); });
159 g_lua.registerFunction<string(ComboAddress::*)()>("toString", [](const ComboAddress& ca) { return ca.toString(); });
160 g_lua.registerFunction<string(ComboAddress::*)()>("toStringWithPort", [](const ComboAddress& ca) { return ca.toStringWithPort(); });
161 g_lua.registerFunction<uint16_t(ComboAddress::*)()>("getPort", [](const ComboAddress& ca) { return ntohs(ca.sin4.sin_port); } );
162 g_lua.registerFunction<void(ComboAddress::*)(unsigned int)>("truncate", [](ComboAddress& ca, unsigned int bits) { ca.truncate(bits); });
163 g_lua.registerFunction<bool(ComboAddress::*)()>("isIPv4", [](const ComboAddress& ca) { return ca.sin4.sin_family == AF_INET; });
164 g_lua.registerFunction<bool(ComboAddress::*)()>("isIPv6", [](const ComboAddress& ca) { return ca.sin4.sin_family == AF_INET6; });
165 g_lua.registerFunction<bool(ComboAddress::*)()>("isMappedIPv4", [](const ComboAddress& ca) { return ca.isMappedIPv4(); });
166 g_lua.registerFunction<ComboAddress(ComboAddress::*)()>("mapToIPv4", [](const ComboAddress& ca) { return ca.mapToIPv4(); });
167 g_lua.registerFunction<bool(nmts_t::*)(const ComboAddress&)>("match", [](nmts_t& s, const ComboAddress& ca) { return s.match(ca); });
168
169 /* DNSName */
170 g_lua.registerFunction("isPartOf", &DNSName::isPartOf);
171 g_lua.registerFunction<bool(DNSName::*)()>("chopOff", [](DNSName&dn ) { return dn.chopOff(); });
172 g_lua.registerFunction<unsigned int(DNSName::*)()>("countLabels", [](const DNSName& name) { return name.countLabels(); });
173 g_lua.registerFunction<size_t(DNSName::*)()>("wirelength", [](const DNSName& name) { return name.wirelength(); });
174 g_lua.registerFunction<string(DNSName::*)()>("tostring", [](const DNSName&dn ) { return dn.toString(); });
175 g_lua.registerFunction<string(DNSName::*)()>("toString", [](const DNSName&dn ) { return dn.toString(); });
176 g_lua.writeFunction("newDNSName", [](const std::string& name) { return DNSName(name); });
177 g_lua.writeFunction("newSuffixMatchNode", []() { return SuffixMatchNode(); });
178
179 /* SuffixMatchNode */
180 g_lua.registerFunction("add",(void (SuffixMatchNode::*)(const DNSName&)) &SuffixMatchNode::add);
181 g_lua.registerFunction("check",(bool (SuffixMatchNode::*)(const DNSName&) const) &SuffixMatchNode::check);
182
183 /* NetmaskGroup */
184 g_lua.writeFunction("newNMG", []() { return NetmaskGroup(); });
185 g_lua.registerFunction<void(NetmaskGroup::*)(const std::string&mask)>("addMask", [](NetmaskGroup&nmg, const std::string& mask)
186 {
187 nmg.addMask(mask);
188 });
189 g_lua.registerFunction<void(NetmaskGroup::*)(const std::map<ComboAddress,int>& map)>("addMasks", [](NetmaskGroup&nmg, const std::map<ComboAddress,int>& map)
190 {
191 for (const auto& entry : map) {
192 nmg.addMask(Netmask(entry.first));
193 }
194 });
195
196 g_lua.registerFunction("match", (bool (NetmaskGroup::*)(const ComboAddress&) const)&NetmaskGroup::match);
197 g_lua.registerFunction("size", &NetmaskGroup::size);
198 g_lua.registerFunction("clear", &NetmaskGroup::clear);
a4fd2d2f 199 g_lua.registerFunction<string(NetmaskGroup::*)()>("toString", [](const NetmaskGroup& nmg ) { return "NetmaskGroup " + nmg.toString(); });
6bb38cd6
RG
200
201 /* QPSLimiter */
202 g_lua.writeFunction("newQPSLimiter", [](int rate, int burst) { return QPSLimiter(rate, burst); });
203 g_lua.registerFunction("check", &QPSLimiter::check);
204
205 /* ClientState */
206 g_lua.registerFunction<std::string(ClientState::*)()>("toString", [](const ClientState& fe) {
207 setLuaNoSideEffect();
208 return fe.local.toStringWithPort();
209 });
210 g_lua.registerMember("muted", &ClientState::muted);
211#ifdef HAVE_EBPF
212 g_lua.registerFunction<void(ClientState::*)(std::shared_ptr<BPFFilter>)>("attachFilter", [](ClientState& frontend, std::shared_ptr<BPFFilter> bpf) {
213 if (bpf) {
214 frontend.attachFilter(bpf);
215 }
216 });
217 g_lua.registerFunction<void(ClientState::*)()>("detachFilter", [](ClientState& frontend) {
218 frontend.detachFilter();
219 });
220#endif /* HAVE_EBPF */
221
222 /* PacketCache */
c1b81381
RG
223 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) {
224
225 bool keepStaleData = false;
226
227 if (vars) {
228
229 if (vars->count("deferrableInsertLock")) {
230 deferrableInsertLock = boost::get<bool>((*vars)["deferrableInsertLock"]);
231 }
232
233 if (vars->count("dontAge")) {
234 dontAge = boost::get<bool>((*vars)["dontAge"]);
235 }
236
237 if (vars->count("keepStaleData")) {
238 keepStaleData = boost::get<bool>((*vars)["keepStaleData"]);
239 }
240
241 if (vars->count("maxEntries")) {
242 maxEntries = boost::get<size_t>((*vars)["maxEntries"]);
243 }
244
245 if (vars->count("maxNegativeTTL")) {
246 maxNegativeTTL = boost::get<size_t>((*vars)["maxNegativeTTL"]);
247 }
248
249 if (vars->count("maxTTL")) {
250 maxTTL = boost::get<size_t>((*vars)["maxTTL"]);
251 }
252
253 if (vars->count("minTTL")) {
254 minTTL = boost::get<size_t>((*vars)["minTTL"]);
255 }
256
257 if (vars->count("numberOfShards")) {
258 numberOfShards = boost::get<size_t>((*vars)["numberOfShards"]);
259 }
260
261 if (vars->count("parseECS")) {
262 ecsParsing = boost::get<bool>((*vars)["parseECS"]);
263 }
264
265 if (vars->count("staleTTL")) {
266 staleTTL = boost::get<size_t>((*vars)["staleTTL"]);
267 }
268
269 if (vars->count("temporaryFailureTTL")) {
270 tempFailTTL = boost::get<size_t>((*vars)["temporaryFailureTTL"]);
271 }
272
273 }
274
275 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);
276
277 res->setKeepStaleData(keepStaleData);
278
279 return res;
6bb38cd6
RG
280 });
281 g_lua.registerFunction("toString", &DNSDistPacketCache::toString);
282 g_lua.registerFunction("isFull", &DNSDistPacketCache::isFull);
283 g_lua.registerFunction("purgeExpired", &DNSDistPacketCache::purgeExpired);
284 g_lua.registerFunction("expunge", &DNSDistPacketCache::expunge);
285 g_lua.registerFunction<void(std::shared_ptr<DNSDistPacketCache>::*)(const DNSName& dname, boost::optional<uint16_t> qtype, boost::optional<bool> suffixMatch)>("expungeByName", [](
286 std::shared_ptr<DNSDistPacketCache> cache,
287 const DNSName& dname,
288 boost::optional<uint16_t> qtype,
289 boost::optional<bool> suffixMatch) {
290 if (cache) {
eace2c24 291 cache->expungeByName(dname, qtype ? *qtype : QType(QType::ANY).getCode(), suffixMatch ? *suffixMatch : false);
6bb38cd6
RG
292 }
293 });
294 g_lua.registerFunction<void(std::shared_ptr<DNSDistPacketCache>::*)()>("printStats", [](const std::shared_ptr<DNSDistPacketCache> cache) {
295 if (cache) {
296 g_outputBuffer="Entries: " + std::to_string(cache->getEntriesCount()) + "/" + std::to_string(cache->getMaxEntries()) + "\n";
297 g_outputBuffer+="Hits: " + std::to_string(cache->getHits()) + "\n";
298 g_outputBuffer+="Misses: " + std::to_string(cache->getMisses()) + "\n";
299 g_outputBuffer+="Deferred inserts: " + std::to_string(cache->getDeferredInserts()) + "\n";
300 g_outputBuffer+="Deferred lookups: " + std::to_string(cache->getDeferredLookups()) + "\n";
301 g_outputBuffer+="Lookup Collisions: " + std::to_string(cache->getLookupCollisions()) + "\n";
302 g_outputBuffer+="Insert Collisions: " + std::to_string(cache->getInsertCollisions()) + "\n";
303 g_outputBuffer+="TTL Too Shorts: " + std::to_string(cache->getTTLTooShorts()) + "\n";
304 }
305 });
c1b81381
RG
306 g_lua.registerFunction<std::unordered_map<std::string, uint64_t>(std::shared_ptr<DNSDistPacketCache>::*)()>("getStats", [](const std::shared_ptr<DNSDistPacketCache> cache) {
307 std::unordered_map<std::string, uint64_t> stats;
308 if (cache) {
309 stats["entries"] = cache->getEntriesCount();
310 stats["maxEntries"] = cache->getMaxEntries();
311 stats["hits"] = cache->getHits();
312 stats["misses"] = cache->getMisses();
313 stats["deferredInserts"] = cache->getDeferredInserts();
314 stats["deferredLookups"] = cache->getDeferredLookups();
315 stats["lookupCollisions"] = cache->getLookupCollisions();
316 stats["insertCollisions"] = cache->getInsertCollisions();
317 stats["ttlTooShorts"] = cache->getTTLTooShorts();
318 }
319 return stats;
320 });
f037144c
RG
321 g_lua.registerFunction<void(std::shared_ptr<DNSDistPacketCache>::*)(const std::string& fname)>("dump", [](const std::shared_ptr<DNSDistPacketCache> cache, const std::string& fname) {
322 if (cache) {
323
324 int fd = open(fname.c_str(), O_CREAT | O_EXCL | O_WRONLY, 0660);
325 if (fd < 0) {
326 g_outputBuffer = "Error opening dump file for writing: " + string(strerror(errno)) + "\n";
327 return;
328 }
329
330 uint64_t records = 0;
331 try {
332 records = cache->dump(fd);
333 }
334 catch (const std::exception& e) {
335 close(fd);
336 throw;
337 }
338
339 close(fd);
340
341 g_outputBuffer += "Dumped " + std::to_string(records) + " records\n";
342 }
343 });
6bb38cd6
RG
344
345 /* ProtobufMessage */
346 g_lua.registerFunction<void(DNSDistProtoBufMessage::*)(std::string)>("setTag", [](DNSDistProtoBufMessage& message, const std::string& strValue) {
347 message.addTag(strValue);
348 });
349 g_lua.registerFunction<void(DNSDistProtoBufMessage::*)(vector<pair<int, string>>)>("setTagArray", [](DNSDistProtoBufMessage& message, const vector<pair<int, string>>&tags) {
350 for (const auto& tag : tags) {
351 message.addTag(tag.second);
352 }
353 });
354 g_lua.registerFunction<void(DNSDistProtoBufMessage::*)(boost::optional <time_t> sec, boost::optional <uint32_t> uSec)>("setProtobufResponseType",
355 [](DNSDistProtoBufMessage& message, boost::optional <time_t> sec, boost::optional <uint32_t> uSec) {
356 message.setType(DNSProtoBufMessage::Response);
357 message.setQueryTime(sec?*sec:0, uSec?*uSec:0);
358 });
359 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,
360 const std::string& strQueryName, uint16_t uType, uint16_t uClass, uint32_t uTTL, const std::string& strBlob) {
361 message.addRR(DNSName(strQueryName), uType, uClass, uTTL, strBlob);
362 });
363 g_lua.registerFunction<void(DNSDistProtoBufMessage::*)(const Netmask&)>("setEDNSSubnet", [](DNSDistProtoBufMessage& message, const Netmask& subnet) { message.setEDNSSubnet(subnet); });
364 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); });
365 g_lua.registerFunction<void(DNSDistProtoBufMessage::*)(size_t)>("setBytes", [](DNSDistProtoBufMessage& message, size_t bytes) { message.setBytes(bytes); });
366 g_lua.registerFunction<void(DNSDistProtoBufMessage::*)(time_t, uint32_t)>("setTime", [](DNSDistProtoBufMessage& message, time_t sec, uint32_t usec) { message.setTime(sec, usec); });
367 g_lua.registerFunction<void(DNSDistProtoBufMessage::*)(time_t, uint32_t)>("setQueryTime", [](DNSDistProtoBufMessage& message, time_t sec, uint32_t usec) { message.setQueryTime(sec, usec); });
368 g_lua.registerFunction<void(DNSDistProtoBufMessage::*)(uint8_t)>("setResponseCode", [](DNSDistProtoBufMessage& message, uint8_t rcode) { message.setResponseCode(rcode); });
369 g_lua.registerFunction<std::string(DNSDistProtoBufMessage::*)()>("toDebugString", [](const DNSDistProtoBufMessage& message) { return message.toDebugString(); });
370 g_lua.registerFunction<void(DNSDistProtoBufMessage::*)(const ComboAddress&)>("setRequestor", [](DNSDistProtoBufMessage& message, const ComboAddress& addr) {
371 message.setRequestor(addr);
372 });
373 g_lua.registerFunction<void(DNSDistProtoBufMessage::*)(const std::string&)>("setRequestorFromString", [](DNSDistProtoBufMessage& message, const std::string& str) {
374 message.setRequestor(str);
375 });
376 g_lua.registerFunction<void(DNSDistProtoBufMessage::*)(const ComboAddress&)>("setResponder", [](DNSDistProtoBufMessage& message, const ComboAddress& addr) {
377 message.setResponder(addr);
378 });
379 g_lua.registerFunction<void(DNSDistProtoBufMessage::*)(const std::string&)>("setResponderFromString", [](DNSDistProtoBufMessage& message, const std::string& str) {
380 message.setResponder(str);
381 });
312a09a6
RG
382 g_lua.registerFunction<void(DNSDistProtoBufMessage::*)(const std::string&)>("setServerIdentity", [](DNSDistProtoBufMessage& message, const std::string& str) {
383 message.setServerIdentity(str);
384 });
6bb38cd6 385
82a91ddf
CH
386 g_lua.registerFunction<std::string(DnstapMessage::*)()>("toDebugString", [](const DnstapMessage& message) { return message.toDebugString(); });
387 g_lua.registerFunction<void(DnstapMessage::*)(const std::string&)>("setExtra", [](DnstapMessage& message, const std::string& str) {
388 message.setExtra(str);
389 });
390
6bb38cd6
RG
391 /* RemoteLogger */
392 g_lua.writeFunction("newRemoteLogger", [client](const std::string& remote, boost::optional<uint16_t> timeout, boost::optional<uint64_t> maxQueuedEntries, boost::optional<uint8_t> reconnectWaitTime) {
da71b63b 393 return std::shared_ptr<RemoteLoggerInterface>(new RemoteLogger(ComboAddress(remote), timeout ? *timeout : 2, maxQueuedEntries ? (*maxQueuedEntries*100) : 10000, reconnectWaitTime ? *reconnectWaitTime : 1, client));
82a91ddf
CH
394 });
395
396 g_lua.writeFunction("newFrameStreamUnixLogger", [client](const std::string& address) {
82a91ddf 397#ifdef HAVE_FSTRM
6b44773a 398 return std::shared_ptr<RemoteLoggerInterface>(new FrameStreamLogger(AF_UNIX, address, !client));
82a91ddf
CH
399#else
400 throw std::runtime_error("fstrm support is required to build an AF_UNIX FrameStreamLogger");
401#endif /* HAVE_FSTRM */
402 });
403
404 g_lua.writeFunction("newFrameStreamTcpLogger", [client](const std::string& address) {
82a91ddf 405#if defined(HAVE_FSTRM) && defined(HAVE_FSTRM_TCP_WRITER_INIT)
6b44773a 406 return std::shared_ptr<RemoteLoggerInterface>(new FrameStreamLogger(AF_INET, address, !client));
82a91ddf
CH
407#else
408 throw std::runtime_error("fstrm with TCP support is required to build an AF_INET FrameStreamLogger");
409#endif /* HAVE_FSTRM */
410 });
6bb38cd6 411
a4fd2d2f
CH
412 g_lua.registerFunction("toString", &RemoteLoggerInterface::toString);
413
6bb38cd6 414#ifdef HAVE_DNSCRYPT
43234e76
RG
415 /* DNSCryptContext bindings */
416 g_lua.registerFunction<std::string(DNSCryptContext::*)()>("getProviderName", [](const DNSCryptContext& ctx) { return ctx.getProviderName().toStringNoDot(); });
43234e76
RG
417 g_lua.registerFunction("markActive", &DNSCryptContext::markActive);
418 g_lua.registerFunction("markInactive", &DNSCryptContext::markInactive);
419 g_lua.registerFunction("removeInactiveCertificate", &DNSCryptContext::removeInactiveCertificate);
420 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) {
421
422 if (ctx == nullptr) {
423 throw std::runtime_error("DNSCryptContext::loadNewCertificate() called on a nil value");
424 }
425
426 ctx->loadNewCertificate(certFile, keyFile, active ? *active : true);
427 });
428 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) {
429
430 if (ctx == nullptr) {
431 throw std::runtime_error("DNSCryptContext::addNewCertificate() called on a nil value");
432 }
433
434 ctx->addNewCertificate(newCert, newKey, active ? *active : true);
435 });
436 g_lua.registerFunction<std::map<int, std::shared_ptr<DNSCryptCertificatePair>>(std::shared_ptr<DNSCryptContext>::*)()>("getCertificatePairs", [](std::shared_ptr<DNSCryptContext> ctx) {
437 std::map<int, std::shared_ptr<DNSCryptCertificatePair>> result;
438
439 if (ctx != nullptr) {
440 size_t idx = 1;
441 for (auto pair : ctx->getCertificates()) {
442 result[idx++] = pair;
6bb38cd6
RG
443 }
444 }
43234e76
RG
445
446 return result;
447 });
c2baf928 448
43234e76
RG
449 g_lua.registerFunction<std::shared_ptr<DNSCryptCertificatePair>(std::shared_ptr<DNSCryptContext>::*)(size_t idx)>("getCertificatePair", [](std::shared_ptr<DNSCryptContext> ctx, size_t idx) {
450
451 if (ctx == nullptr) {
452 throw std::runtime_error("DNSCryptContext::getCertificatePair() called on a nil value");
453 }
454
455 std::shared_ptr<DNSCryptCertificatePair> result = nullptr;
55710b0f
RG
456 auto pairs = ctx->getCertificates();
457 if (idx < pairs.size()) {
458 result = pairs.at(idx);
43234e76
RG
459 }
460
461 return result;
462 });
463
c2baf928 464 g_lua.registerFunction<const DNSCryptCert(std::shared_ptr<DNSCryptContext>::*)(size_t idx)>("getCertificate", [](std::shared_ptr<DNSCryptContext> ctx, size_t idx) {
55710b0f
RG
465
466 if (ctx == nullptr) {
c2baf928 467 throw std::runtime_error("DNSCryptContext::getCertificate() called on a nil value");
55710b0f
RG
468 }
469
470 auto pairs = ctx->getCertificates();
c2baf928
RG
471 if (idx < pairs.size()) {
472 return pairs.at(idx)->cert;
55710b0f
RG
473 }
474
c2baf928 475 throw std::runtime_error("This DNSCrypt context has no certificate at index " + std::to_string(idx));
55710b0f
RG
476 });
477
43234e76
RG
478 g_lua.registerFunction<std::string(std::shared_ptr<DNSCryptContext>::*)()>("printCertificates", [](const std::shared_ptr<DNSCryptContext> ctx) {
479 ostringstream ret;
480
481 if (ctx != nullptr) {
482 size_t idx = 1;
483 boost::format fmt("%1$-3d %|5t|%2$-8d %|10t|%3$-2d %|20t|%4$-21.21s %|41t|%5$-21.21s");
484 ret << (fmt % "#" % "Serial" % "Version" % "From" % "To" ) << endl;
485
486 for (auto pair : ctx->getCertificates()) {
487 const auto cert = pair->cert;
488 const DNSCryptExchangeVersion version = DNSCryptContext::getExchangeVersion(cert);
489
490 ret << (fmt % idx % cert.getSerial() % (version == DNSCryptExchangeVersion::VERSION1 ? 1 : 2) % DNSCryptContext::certificateDateToStr(cert.getTSStart()) % DNSCryptContext::certificateDateToStr(cert.getTSEnd())) << endl;
491 }
492 }
493
494 return ret.str();
495 });
496
497 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) {
498 DNSCryptPrivateKey privateKey;
499 DNSCryptCert cert;
500
501 try {
502 if (generateDNSCryptCertificate(providerPrivateKeyFile, serial, begin, end, version ? *version : DNSCryptExchangeVersion::VERSION1, cert, privateKey)) {
503 ctx.addNewCertificate(cert, privateKey);
504 }
505 }
506 catch(const std::exception& e) {
507 errlog(e.what());
508 g_outputBuffer="Error: "+string(e.what())+"\n";
509 }
510 });
511
512 /* DNSCryptCertificatePair */
513 g_lua.registerFunction<const DNSCryptCert(std::shared_ptr<DNSCryptCertificatePair>::*)()>("getCertificate", [](const std::shared_ptr<DNSCryptCertificatePair> pair) {
514 if (pair == nullptr) {
515 throw std::runtime_error("DNSCryptCertificatePair::getCertificate() called on a nil value");
516 }
517 return pair->cert;
518 });
519 g_lua.registerFunction<bool(std::shared_ptr<DNSCryptCertificatePair>::*)()>("isActive", [](const std::shared_ptr<DNSCryptCertificatePair> pair) {
520 if (pair == nullptr) {
521 throw std::runtime_error("DNSCryptCertificatePair::isActive() called on a nil value");
6bb38cd6 522 }
43234e76 523 return pair->active;
6bb38cd6
RG
524 });
525
43234e76
RG
526 /* DNSCryptCert */
527 g_lua.registerFunction<std::string(DNSCryptCert::*)()>("getMagic", [](const DNSCryptCert& cert) { return std::string(reinterpret_cast<const char*>(cert.magic), sizeof(cert.magic)); });
528 g_lua.registerFunction<std::string(DNSCryptCert::*)()>("getEsVersion", [](const DNSCryptCert& cert) { return std::string(reinterpret_cast<const char*>(cert.esVersion), sizeof(cert.esVersion)); });
529 g_lua.registerFunction<std::string(DNSCryptCert::*)()>("getProtocolMinorVersion", [](const DNSCryptCert& cert) { return std::string(reinterpret_cast<const char*>(cert.protocolMinorVersion), sizeof(cert.protocolMinorVersion)); });
530 g_lua.registerFunction<std::string(DNSCryptCert::*)()>("getSignature", [](const DNSCryptCert& cert) { return std::string(reinterpret_cast<const char*>(cert.signature), sizeof(cert.signature)); });
531 g_lua.registerFunction<std::string(DNSCryptCert::*)()>("getResolverPublicKey", [](const DNSCryptCert& cert) { return std::string(reinterpret_cast<const char*>(cert.signedData.resolverPK), sizeof(cert.signedData.resolverPK)); });
532 g_lua.registerFunction<std::string(DNSCryptCert::*)()>("getClientMagic", [](const DNSCryptCert& cert) { return std::string(reinterpret_cast<const char*>(cert.signedData.clientMagic), sizeof(cert.signedData.clientMagic)); });
533 g_lua.registerFunction<uint32_t(DNSCryptCert::*)()>("getSerial", [](const DNSCryptCert& cert) { return cert.getSerial(); });
534 g_lua.registerFunction<uint32_t(DNSCryptCert::*)()>("getTSStart", [](const DNSCryptCert& cert) { return ntohl(cert.getTSStart()); });
535 g_lua.registerFunction<uint32_t(DNSCryptCert::*)()>("getTSEnd", [](const DNSCryptCert& cert) { return ntohl(cert.getTSEnd()); });
6bb38cd6
RG
536#endif
537
538 /* BPF Filter */
539#ifdef HAVE_EBPF
540 g_lua.writeFunction("newBPFFilter", [client](uint32_t maxV4, uint32_t maxV6, uint32_t maxQNames) {
541 if (client) {
542 return std::shared_ptr<BPFFilter>(nullptr);
543 }
544 return std::make_shared<BPFFilter>(maxV4, maxV6, maxQNames);
545 });
546
547 g_lua.registerFunction<void(std::shared_ptr<BPFFilter>::*)(const ComboAddress& ca)>("block", [](std::shared_ptr<BPFFilter> bpf, const ComboAddress& ca) {
548 if (bpf) {
549 return bpf->block(ca);
550 }
551 });
552
553 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) {
554 if (bpf) {
555 return bpf->block(qname, qtype ? *qtype : 255);
556 }
557 });
558
559 g_lua.registerFunction<void(std::shared_ptr<BPFFilter>::*)(const ComboAddress& ca)>("unblock", [](std::shared_ptr<BPFFilter> bpf, const ComboAddress& ca) {
560 if (bpf) {
561 return bpf->unblock(ca);
562 }
563 });
564
565 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) {
566 if (bpf) {
567 return bpf->unblock(qname, qtype ? *qtype : 255);
568 }
569 });
570
571 g_lua.registerFunction<std::string(std::shared_ptr<BPFFilter>::*)()>("getStats", [](const std::shared_ptr<BPFFilter> bpf) {
572 setLuaNoSideEffect();
573 std::string res;
574 if (bpf) {
575 std::vector<std::pair<ComboAddress, uint64_t> > stats = bpf->getAddrStats();
576 for (const auto& value : stats) {
577 if (value.first.sin4.sin_family == AF_INET) {
578 res += value.first.toString() + ": " + std::to_string(value.second) + "\n";
579 }
580 else if (value.first.sin4.sin_family == AF_INET6) {
581 res += "[" + value.first.toString() + "]: " + std::to_string(value.second) + "\n";
582 }
583 }
584 std::vector<std::tuple<DNSName, uint16_t, uint64_t> > qstats = bpf->getQNameStats();
585 for (const auto& value : qstats) {
586 res += std::get<0>(value).toString() + " " + std::to_string(std::get<1>(value)) + ": " + std::to_string(std::get<2>(value)) + "\n";
587 }
588 }
589 return res;
590 });
591
592 g_lua.registerFunction<void(std::shared_ptr<BPFFilter>::*)()>("attachToAllBinds", [](std::shared_ptr<BPFFilter> bpf) {
593 std::string res;
594 if (bpf) {
595 for (const auto& frontend : g_frontends) {
596 frontend->attachFilter(bpf);
597 }
598 }
599 });
600
601 g_lua.writeFunction("newDynBPFFilter", [client](std::shared_ptr<BPFFilter> bpf) {
602 if (client) {
603 return std::shared_ptr<DynBPFFilter>(nullptr);
604 }
605 return std::make_shared<DynBPFFilter>(bpf);
606 });
607
608 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) {
609 if (dbpf) {
610 struct timespec until;
611 clock_gettime(CLOCK_MONOTONIC, &until);
612 until.tv_sec += seconds ? *seconds : 10;
613 dbpf->block(addr, until);
614 }
615 });
616
617 g_lua.registerFunction<void(std::shared_ptr<DynBPFFilter>::*)()>("purgeExpired", [](std::shared_ptr<DynBPFFilter> dbpf) {
618 if (dbpf) {
619 struct timespec now;
620 clock_gettime(CLOCK_MONOTONIC, &now);
621 dbpf->purgeExpired(now);
622 }
623 });
ee38369c
RS
624
625 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) {
626 if (ranges.type() == typeid(std::vector<std::pair<int, std::string>>)) {
627 for (const auto& range : *boost::get<std::vector<std::pair<int, std::string>>>(&ranges)) {
628 dbpf->excludeRange(Netmask(range.second));
629 }
630 }
631 else {
632 dbpf->excludeRange(Netmask(*boost::get<std::string>(&ranges)));
633 }
634 });
635
636 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) {
637 if (ranges.type() == typeid(std::vector<std::pair<int, std::string>>)) {
638 for (const auto& range : *boost::get<std::vector<std::pair<int, std::string>>>(&ranges)) {
639 dbpf->includeRange(Netmask(range.second));
640 }
641 }
642 else {
643 dbpf->includeRange(Netmask(*boost::get<std::string>(&ranges)));
644 }
645 });
6bb38cd6 646#endif /* HAVE_EBPF */
cbf4e13a
RG
647
648 /* EDNSOptionView */
649 g_lua.registerFunction<size_t(EDNSOptionView::*)()>("count", [](const EDNSOptionView& option) {
650 return option.values.size();
651 });
652 g_lua.registerFunction<std::vector<std::pair<int, string>>(EDNSOptionView::*)()>("getValues", [] (const EDNSOptionView& option) {
653 std::vector<std::pair<int, string> > values;
654 for (const auto& value : option.values) {
655 values.push_back(std::make_pair(values.size(), std::string(value.content, value.size)));
656 }
657 return values;
658 });
6bb38cd6 659}