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