]> git.ipfire.org Git - thirdparty/pdns.git/blame - pdns/dnsdistdist/dnsdist-lua-bindings-dnsquestion.cc
dnsdist: Fix formatting issues
[thirdparty/pdns.git] / pdns / dnsdistdist / dnsdist-lua-bindings-dnsquestion.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 */
22#include "dnsdist.hh"
27f38b46 23#include "dnsdist-async.hh"
20790191 24#include "dnsdist-dnsparser.hh"
e7c732b8 25#include "dnsdist-ecs.hh"
b37671bc 26#include "dnsdist-internal-queries.hh"
6bb38cd6
RG
27#include "dnsdist-lua.hh"
28#include "dnsparser.hh"
29
0e781539 30// NOLINTNEXTLINE(readability-function-cognitive-complexity): this function declares Lua bindings, even with a good refactoring it will likely blow up the threshold
fd51c832 31void setupLuaBindingsDNSQuestion(LuaContext& luaCtx)
6bb38cd6 32{
393ed488 33#ifndef DISABLE_NON_FFI_DQ_BINDINGS
6bb38cd6
RG
34 /* DNSQuestion */
35 /* PowerDNS DNSQuestion compat */
086114d5 36 luaCtx.registerMember<const ComboAddress(DNSQuestion::*)>(
40d01eff 37 "localaddr", [](const DNSQuestion& dnsQuestion) -> ComboAddress { return dnsQuestion.ids.origDest; }, [](DNSQuestion& dnsQuestion, const ComboAddress newLocal) { (void)newLocal; });
086114d5 38 luaCtx.registerMember<const DNSName(DNSQuestion::*)>(
40d01eff 39 "qname", [](const DNSQuestion& dnsQuestion) -> DNSName { return dnsQuestion.ids.qname; }, [](DNSQuestion& dnsQuestion, const DNSName& newName) { (void)newName; });
086114d5 40 luaCtx.registerMember<uint16_t(DNSQuestion::*)>(
40d01eff 41 "qtype", [](const DNSQuestion& dnsQuestion) -> uint16_t { return dnsQuestion.ids.qtype; }, [](DNSQuestion& dnsQuestion, uint16_t newType) { (void)newType; });
086114d5 42 luaCtx.registerMember<uint16_t(DNSQuestion::*)>(
40d01eff 43 "qclass", [](const DNSQuestion& dnsQuestion) -> uint16_t { return dnsQuestion.ids.qclass; }, [](DNSQuestion& dnsQuestion, uint16_t newClass) { (void)newClass; });
086114d5 44 luaCtx.registerMember<int(DNSQuestion::*)>(
34b2ed52
RG
45 "rcode",
46 [](const DNSQuestion& dnsQuestion) -> int {
47 return static_cast<int>(dnsQuestion.getHeader()->rcode);
48 },
49 [](DNSQuestion& dnsQuestion, int newRCode) {
69534a09
RG
50 dnsdist::PacketMangling::editDNSHeaderFromPacket(dnsQuestion.getMutableData(), [newRCode](dnsheader& header) {
51 header.rcode = static_cast<decltype(header.rcode)>(newRCode);
52 return true;
53 });
54 });
086114d5 55 luaCtx.registerMember<const ComboAddress(DNSQuestion::*)>(
40d01eff 56 "remoteaddr", [](const DNSQuestion& dnsQuestion) -> ComboAddress { return dnsQuestion.ids.origRemote; }, [](DNSQuestion& dnsQuestion, const ComboAddress newRemote) { (void)newRemote; });
6bb38cd6 57 /* DNSDist DNSQuestion */
086114d5 58 luaCtx.registerMember<dnsheader*(DNSQuestion::*)>(
34b2ed52
RG
59 "dh",
60 [](const DNSQuestion& dnsQuestion) -> dnsheader* {
61 return dnsQuestion.getMutableHeader();
62 },
63 [](DNSQuestion& dnsQuestion, const dnsheader* dnsHeader) {
69534a09
RG
64 dnsdist::PacketMangling::editDNSHeaderFromPacket(dnsQuestion.getMutableData(), [&dnsHeader](dnsheader& header) {
65 header = *dnsHeader;
66 return true;
67 });
68 });
086114d5 69 luaCtx.registerMember<uint16_t(DNSQuestion::*)>(
40d01eff 70 "len", [](const DNSQuestion& dnsQuestion) -> uint16_t { return dnsQuestion.getData().size(); }, [](DNSQuestion& dnsQuestion, uint16_t newlen) { dnsQuestion.getMutableData().resize(newlen); });
086114d5 71 luaCtx.registerMember<uint8_t(DNSQuestion::*)>(
40d01eff 72 "opcode", [](const DNSQuestion& dnsQuestion) -> uint8_t { return dnsQuestion.getHeader()->opcode; }, [](DNSQuestion& dnsQuestion, uint8_t newOpcode) { (void)newOpcode; });
086114d5 73 luaCtx.registerMember<bool(DNSQuestion::*)>(
40d01eff 74 "tcp", [](const DNSQuestion& dnsQuestion) -> bool { return dnsQuestion.overTCP(); }, [](DNSQuestion& dnsQuestion, bool newTcp) { (void)newTcp; });
086114d5 75 luaCtx.registerMember<bool(DNSQuestion::*)>(
40d01eff 76 "skipCache", [](const DNSQuestion& dnsQuestion) -> bool { return dnsQuestion.ids.skipCache; }, [](DNSQuestion& dnsQuestion, bool newSkipCache) { dnsQuestion.ids.skipCache = newSkipCache; });
086114d5 77 luaCtx.registerMember<std::string(DNSQuestion::*)>(
40d01eff 78 "pool", [](const DNSQuestion& dnsQuestion) -> std::string { return dnsQuestion.ids.poolName; }, [](DNSQuestion& dnsQuestion, const std::string& newPoolName) { dnsQuestion.ids.poolName = newPoolName; });
086114d5 79 luaCtx.registerMember<bool(DNSQuestion::*)>(
40d01eff 80 "useECS", [](const DNSQuestion& dnsQuestion) -> bool { return dnsQuestion.useECS; }, [](DNSQuestion& dnsQuestion, bool useECS) { dnsQuestion.useECS = useECS; });
086114d5 81 luaCtx.registerMember<bool(DNSQuestion::*)>(
40d01eff 82 "ecsOverride", [](const DNSQuestion& dnsQuestion) -> bool { return dnsQuestion.ecsOverride; }, [](DNSQuestion& dnsQuestion, bool ecsOverride) { dnsQuestion.ecsOverride = ecsOverride; });
086114d5 83 luaCtx.registerMember<uint16_t(DNSQuestion::*)>(
40d01eff 84 "ecsPrefixLength", [](const DNSQuestion& dnsQuestion) -> uint16_t { return dnsQuestion.ecsPrefixLength; }, [](DNSQuestion& dnsQuestion, uint16_t newPrefixLength) { dnsQuestion.ecsPrefixLength = newPrefixLength; });
086114d5
RG
85 luaCtx.registerMember<boost::optional<uint32_t>(DNSQuestion::*)>(
86 "tempFailureTTL",
40d01eff
RG
87 [](const DNSQuestion& dnsQuestion) -> boost::optional<uint32_t> {
88 return dnsQuestion.ids.tempFailureTTL;
086114d5 89 },
40d01eff
RG
90 [](DNSQuestion& dnsQuestion, boost::optional<uint32_t> newValue) {
91 dnsQuestion.ids.tempFailureTTL = newValue;
086114d5
RG
92 });
93 luaCtx.registerMember<std::string(DNSQuestion::*)>(
40d01eff
RG
94 "deviceID", [](const DNSQuestion& dnsQuestion) -> std::string {
95 if (dnsQuestion.ids.d_protoBufData) {
96 return dnsQuestion.ids.d_protoBufData->d_deviceID;
e79f2196 97 }
40d01eff
RG
98 return {}; }, [](DNSQuestion& dnsQuestion, const std::string& newValue) {
99 if (!dnsQuestion.ids.d_protoBufData) {
100 dnsQuestion.ids.d_protoBufData = std::make_unique<InternalQueryState::ProtoBufData>();
e79f2196 101 }
40d01eff 102 dnsQuestion.ids.d_protoBufData->d_deviceID = newValue; });
086114d5 103 luaCtx.registerMember<std::string(DNSQuestion::*)>(
40d01eff
RG
104 "deviceName", [](const DNSQuestion& dnsQuestion) -> std::string {
105 if (dnsQuestion.ids.d_protoBufData) {
106 return dnsQuestion.ids.d_protoBufData->d_deviceName;
e79f2196 107 }
40d01eff
RG
108 return {}; }, [](DNSQuestion& dnsQuestion, const std::string& newValue) {
109 if (!dnsQuestion.ids.d_protoBufData) {
110 dnsQuestion.ids.d_protoBufData = std::make_unique<InternalQueryState::ProtoBufData>();
e79f2196 111 }
40d01eff 112 dnsQuestion.ids.d_protoBufData->d_deviceName = newValue; });
086114d5 113 luaCtx.registerMember<std::string(DNSQuestion::*)>(
40d01eff
RG
114 "requestorID", [](const DNSQuestion& dnsQuestion) -> std::string {
115 if (dnsQuestion.ids.d_protoBufData) {
116 return dnsQuestion.ids.d_protoBufData->d_requestorID;
e79f2196 117 }
40d01eff
RG
118 return {}; }, [](DNSQuestion& dnsQuestion, const std::string& newValue) {
119 if (!dnsQuestion.ids.d_protoBufData) {
120 dnsQuestion.ids.d_protoBufData = std::make_unique<InternalQueryState::ProtoBufData>();
e79f2196 121 }
40d01eff
RG
122 dnsQuestion.ids.d_protoBufData->d_requestorID = newValue; });
123 luaCtx.registerFunction<bool (DNSQuestion::*)() const>("getDO", [](const DNSQuestion& dnsQuestion) {
124 return getEDNSZ(dnsQuestion) & EDNS_HEADER_FLAG_DO;
086114d5 125 });
40d01eff
RG
126 luaCtx.registerFunction<std::string (DNSQuestion::*)() const>("getContent", [](const DNSQuestion& dnsQuestion) {
127 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
128 return std::string(reinterpret_cast<const char*>(dnsQuestion.getData().data()), dnsQuestion.getData().size());
1bf2f3b2 129 });
40d01eff
RG
130 luaCtx.registerFunction<void (DNSQuestion::*)(const std::string&)>("setContent", [](DNSQuestion& dnsQuestion, const std::string& raw) {
131 uint16_t oldID = dnsQuestion.getHeader()->id;
132 auto& buffer = dnsQuestion.getMutableData();
27f38b46
RG
133 buffer.clear();
134 buffer.insert(buffer.begin(), raw.begin(), raw.end());
90686725 135
90686725
RG
136 dnsdist::PacketMangling::editDNSHeaderFromPacket(buffer, [oldID](dnsheader& header) {
137 header.id = oldID;
138 return true;
139 });
27f38b46 140 });
40d01eff
RG
141 luaCtx.registerFunction<std::map<uint16_t, EDNSOptionView> (DNSQuestion::*)() const>("getEDNSOptions", [](const DNSQuestion& dnsQuestion) {
142 if (dnsQuestion.ednsOptions == nullptr) {
143 parseEDNSOptions(dnsQuestion);
144 if (dnsQuestion.ednsOptions == nullptr) {
086114d5 145 throw std::runtime_error("parseEDNSOptions should have populated the EDNS options");
cbf4e13a 146 }
086114d5 147 }
cbf4e13a 148
40d01eff 149 return *dnsQuestion.ednsOptions;
086114d5 150 });
40d01eff
RG
151 luaCtx.registerFunction<std::string (DNSQuestion::*)(void) const>("getTrailingData", [](const DNSQuestion& dnsQuestion) {
152 return dnsQuestion.getTrailingData();
086114d5 153 });
40d01eff
RG
154 luaCtx.registerFunction<bool (DNSQuestion::*)(std::string)>("setTrailingData", [](DNSQuestion& dnsQuestion, const std::string& tail) {
155 return dnsQuestion.setTrailingData(tail);
086114d5 156 });
cbf4e13a 157
40d01eff
RG
158 luaCtx.registerFunction<std::string (DNSQuestion::*)() const>("getServerNameIndication", [](const DNSQuestion& dnsQuestion) {
159 return dnsQuestion.sni;
086114d5 160 });
15e21d84 161
40d01eff
RG
162 luaCtx.registerFunction<std::string (DNSQuestion::*)() const>("getProtocol", [](const DNSQuestion& dnsQuestion) {
163 return dnsQuestion.getProtocol().toPrettyString();
a58258f9
RG
164 });
165
40d01eff
RG
166 luaCtx.registerFunction<timespec (DNSQuestion::*)() const>("getQueryTime", [](const DNSQuestion& dnsQuestion) {
167 return dnsQuestion.ids.queryRealTime.getStartTime();
21e30815
RG
168 });
169
40d01eff 170 luaCtx.registerFunction<void (DNSQuestion::*)(std::string)>("sendTrap", [](const DNSQuestion& dnsQuestion, boost::optional<std::string> reason) {
6bb38cd6 171#ifdef HAVE_NET_SNMP
40d01eff
RG
172 if (g_snmpAgent != nullptr && g_snmpTrapsEnabled) {
173 g_snmpAgent->sendDNSTrap(dnsQuestion, reason ? *reason : "");
086114d5 174 }
6bb38cd6 175#endif /* HAVE_NET_SNMP */
086114d5 176 });
acf86c7a 177
40d01eff
RG
178 luaCtx.registerFunction<void (DNSQuestion::*)(std::string, std::string)>("setTag", [](DNSQuestion& dnsQuestion, const std::string& strLabel, const std::string& strValue) {
179 dnsQuestion.setTag(strLabel, strValue);
086114d5 180 });
40d01eff 181 luaCtx.registerFunction<void (DNSQuestion::*)(LuaAssociativeTable<std::string>)>("setTagArray", [](DNSQuestion& dnsQuestion, const LuaAssociativeTable<std::string>& tags) {
086114d5 182 for (const auto& tag : tags) {
40d01eff 183 dnsQuestion.setTag(tag.first, tag.second);
086114d5
RG
184 }
185 });
40d01eff
RG
186 luaCtx.registerFunction<string (DNSQuestion::*)(std::string) const>("getTag", [](const DNSQuestion& dnsQuestion, const std::string& strLabel) {
187 if (!dnsQuestion.ids.qTag) {
086114d5
RG
188 return string();
189 }
6bb38cd6 190
086114d5 191 std::string strValue;
40d01eff
RG
192 const auto tagIt = dnsQuestion.ids.qTag->find(strLabel);
193 if (tagIt == dnsQuestion.ids.qTag->cend()) {
086114d5
RG
194 return string();
195 }
40d01eff 196 return tagIt->second;
086114d5 197 });
40d01eff
RG
198 luaCtx.registerFunction<QTag (DNSQuestion::*)(void) const>("getTagArray", [](const DNSQuestion& dnsQuestion) {
199 if (!dnsQuestion.ids.qTag) {
086114d5
RG
200 QTag empty;
201 return empty;
202 }
15fac047 203
40d01eff 204 return *dnsQuestion.ids.qTag;
086114d5 205 });
6bb38cd6 206
40d01eff
RG
207 luaCtx.registerFunction<void (DNSQuestion::*)(LuaArray<std::string>)>("setProxyProtocolValues", [](DNSQuestion& dnsQuestion, const LuaArray<std::string>& values) {
208 if (!dnsQuestion.proxyProtocolValues) {
209 dnsQuestion.proxyProtocolValues = make_unique<std::vector<ProxyProtocolValue>>();
448d66d4 210 }
8a79a6c4 211
40d01eff
RG
212 dnsQuestion.proxyProtocolValues->clear();
213 dnsQuestion.proxyProtocolValues->reserve(values.size());
448d66d4 214 for (const auto& value : values) {
23a3bc71 215 checkParameterBound("setProxyProtocolValues", value.first, std::numeric_limits<uint8_t>::max());
40d01eff 216 dnsQuestion.proxyProtocolValues->push_back({value.second, static_cast<uint8_t>(value.first)});
448d66d4
RG
217 }
218 });
219
40d01eff 220 luaCtx.registerFunction<void (DNSQuestion::*)(uint64_t, std::string)>("addProxyProtocolValue", [](DNSQuestion& dnsQuestion, uint64_t type, std::string value) {
23a3bc71 221 checkParameterBound("addProxyProtocolValue", type, std::numeric_limits<uint8_t>::max());
40d01eff
RG
222 if (!dnsQuestion.proxyProtocolValues) {
223 dnsQuestion.proxyProtocolValues = make_unique<std::vector<ProxyProtocolValue>>();
448d66d4
RG
224 }
225
40d01eff 226 dnsQuestion.proxyProtocolValues->push_back({std::move(value), static_cast<uint8_t>(type)});
448d66d4
RG
227 });
228
40d01eff 229 luaCtx.registerFunction<LuaArray<std::string> (DNSQuestion::*)()>("getProxyProtocolValues", [](const DNSQuestion& dnsQuestion) {
bfb79abc 230 LuaArray<std::string> result;
40d01eff 231 if (!dnsQuestion.proxyProtocolValues) {
bfb79abc 232 return result;
448d66d4
RG
233 }
234
40d01eff
RG
235 result.resize(dnsQuestion.proxyProtocolValues->size());
236 for (const auto& value : *dnsQuestion.proxyProtocolValues) {
237 result.emplace_back(value.type, value.content);
448d66d4
RG
238 }
239
240 return result;
241 });
8a79a6c4 242
40d01eff
RG
243 luaCtx.registerFunction<bool (DNSQuestion::*)(const DNSName& newName)>("changeName", [](DNSQuestion& dnsQuestion, const DNSName& newName) -> bool {
244 if (!dnsdist::changeNameInDNSPacket(dnsQuestion.getMutableData(), dnsQuestion.ids.qname, newName)) {
20790191
RG
245 return false;
246 }
40d01eff 247 dnsQuestion.ids.qname = newName;
20790191
RG
248 return true;
249 });
250
086114d5
RG
251 luaCtx.registerFunction<void (DNSQuestion::*)(const boost::variant<LuaArray<ComboAddress>, LuaArray<std::string>>&, boost::optional<uint16_t>)>("spoof", [](DNSQuestion& dnsQuestion, const boost::variant<LuaArray<ComboAddress>, LuaArray<std::string>>& response, boost::optional<uint16_t> typeForAny) {
252 if (response.type() == typeid(LuaArray<ComboAddress>)) {
253 std::vector<ComboAddress> data;
254 auto responses = boost::get<LuaArray<ComboAddress>>(response);
255 data.reserve(responses.size());
256 for (const auto& resp : responses) {
257 data.push_back(resp.second);
4efa18f1 258 }
086114d5
RG
259 std::string result;
260 SpoofAction tempSpoofAction(data);
261 tempSpoofAction(&dnsQuestion, &result);
262 return;
263 }
264 if (response.type() == typeid(LuaArray<std::string>)) {
265 std::vector<std::string> data;
266 auto responses = boost::get<LuaArray<std::string>>(response);
267 data.reserve(responses.size());
268 for (const auto& resp : responses) {
269 data.push_back(resp.second);
4efa18f1 270 }
086114d5
RG
271 std::string result;
272 SpoofAction tempSpoofAction(data, typeForAny ? *typeForAny : std::optional<uint16_t>());
273 tempSpoofAction(&dnsQuestion, &result);
274 return;
275 }
2be05607
RG
276 });
277
40d01eff
RG
278 luaCtx.registerFunction<void (DNSQuestion::*)(uint16_t code, const std::string&)>("setEDNSOption", [](DNSQuestion& dnsQuestion, uint16_t code, const std::string& data) {
279 setEDNSOption(dnsQuestion, code, data);
21ebaa6e
RG
280 });
281
086114d5 282 luaCtx.registerFunction<void (DNSQuestion::*)(uint16_t infoCode, const boost::optional<std::string>& extraText)>("setExtendedDNSError", [](DNSQuestion& dnsQuestion, uint16_t infoCode, const boost::optional<std::string>& extraText) {
f18d8af3
RG
283 EDNSExtendedError ede;
284 ede.infoCode = infoCode;
285 if (extraText) {
286 ede.extraText = *extraText;
287 }
a3e16785 288 dnsQuestion.ids.d_extendedError = std::make_unique<EDNSExtendedError>(ede);
f18d8af3
RG
289 });
290
40d01eff
RG
291 luaCtx.registerFunction<bool (DNSQuestion::*)(uint16_t asyncID, uint16_t queryID, uint32_t timeoutMs)>("suspend", [](DNSQuestion& dnsQuestion, uint16_t asyncID, uint16_t queryID, uint32_t timeoutMs) {
292 dnsQuestion.asynchronous = true;
293 return dnsdist::suspendQuery(dnsQuestion, asyncID, queryID, timeoutMs);
27f38b46
RG
294 });
295
40d01eff
RG
296 luaCtx.registerFunction<bool (DNSQuestion::*)()>("setRestartable", [](DNSQuestion& dnsQuestion) {
297 dnsQuestion.ids.d_packet = std::make_unique<PacketBuffer>(dnsQuestion.getData());
b37671bc
RG
298 return true;
299 });
300
086114d5 301 class AsynchronousObject
27f38b46 302 {
086114d5
RG
303 public:
304 AsynchronousObject(std::unique_ptr<CrossProtocolQuery>&& obj_) :
305 object(std::move(obj_))
306 {
307 }
27f38b46 308
40d01eff 309 [[nodiscard]] DNSQuestion getDQ() const
086114d5
RG
310 {
311 return object->getDQ();
312 }
27f38b46 313
40d01eff 314 [[nodiscard]] DNSResponse getDR() const
086114d5
RG
315 {
316 return object->getDR();
317 }
27f38b46 318
086114d5
RG
319 bool resume()
320 {
321 return dnsdist::queueQueryResumptionEvent(std::move(object));
27f38b46
RG
322 }
323
086114d5
RG
324 bool drop()
325 {
326 auto sender = object->getTCPQuerySender();
327 if (!sender) {
328 return false;
329 }
27f38b46 330
40d01eff 331 timeval now{};
086114d5
RG
332 gettimeofday(&now, nullptr);
333 sender->notifyIOError(now, TCPResponse(std::move(object->query)));
334 return true;
335 }
27f38b46 336
086114d5
RG
337 bool setRCode(uint8_t rcode, bool clearAnswers)
338 {
339 return dnsdist::setInternalQueryRCode(object->query.d_idstate, object->query.d_buffer, rcode, clearAnswers);
340 }
27f38b46 341
086114d5
RG
342 private:
343 std::unique_ptr<CrossProtocolQuery> object;
344 };
27f38b46 345
086114d5
RG
346 luaCtx.registerFunction<DNSQuestion (AsynchronousObject::*)(void) const>("getDQ", [](const AsynchronousObject& obj) {
347 return obj.getDQ();
348 });
27f38b46 349
086114d5
RG
350 luaCtx.registerFunction<DNSQuestion (AsynchronousObject::*)(void) const>("getDR", [](const AsynchronousObject& obj) {
351 return obj.getDR();
352 });
27f38b46 353
086114d5
RG
354 luaCtx.registerFunction<bool (AsynchronousObject::*)(void)>("resume", [](AsynchronousObject& obj) {
355 return obj.resume();
356 });
357
358 luaCtx.registerFunction<bool (AsynchronousObject::*)(void)>("drop", [](AsynchronousObject& obj) {
359 return obj.drop();
360 });
27f38b46 361
086114d5 362 luaCtx.registerFunction<bool (AsynchronousObject::*)(uint8_t, bool)>("setRCode", [](AsynchronousObject& obj, uint8_t rcode, bool clearAnswers) {
27f38b46
RG
363 return obj.setRCode(rcode, clearAnswers);
364 });
365
366 luaCtx.writeFunction("getAsynchronousObject", [](uint16_t asyncID, uint16_t queryID) -> AsynchronousObject {
367 if (!dnsdist::g_asyncHolder) {
368 throw std::runtime_error("Unable to resume, no asynchronous holder");
369 }
370 auto query = dnsdist::g_asyncHolder->get(asyncID, queryID);
371 if (!query) {
372 throw std::runtime_error("Unable to find asynchronous object");
373 }
40d01eff 374 return {std::move(query)};
27f38b46
RG
375 });
376
6bb38cd6 377 /* LuaWrapper doesn't support inheritance */
086114d5 378 luaCtx.registerMember<const ComboAddress(DNSResponse::*)>(
40d01eff 379 "localaddr", [](const DNSResponse& dnsQuestion) -> ComboAddress { return dnsQuestion.ids.origDest; }, [](DNSResponse& dnsQuestion, const ComboAddress newLocal) { (void)newLocal; });
086114d5 380 luaCtx.registerMember<const DNSName(DNSResponse::*)>(
40d01eff 381 "qname", [](const DNSResponse& dnsQuestion) -> DNSName { return dnsQuestion.ids.qname; }, [](DNSResponse& dnsQuestion, const DNSName& newName) { (void)newName; });
086114d5 382 luaCtx.registerMember<uint16_t(DNSResponse::*)>(
40d01eff 383 "qtype", [](const DNSResponse& dnsQuestion) -> uint16_t { return dnsQuestion.ids.qtype; }, [](DNSResponse& dnsQuestion, uint16_t newType) { (void)newType; });
086114d5 384 luaCtx.registerMember<uint16_t(DNSResponse::*)>(
40d01eff 385 "qclass", [](const DNSResponse& dnsQuestion) -> uint16_t { return dnsQuestion.ids.qclass; }, [](DNSResponse& dnsQuestion, uint16_t newClass) { (void)newClass; });
086114d5 386 luaCtx.registerMember<int(DNSResponse::*)>(
34b2ed52
RG
387 "rcode",
388 [](const DNSResponse& dnsQuestion) -> int {
389 return static_cast<int>(dnsQuestion.getHeader()->rcode);
390 },
391 [](DNSResponse& dnsQuestion, int newRCode) {
69534a09
RG
392 dnsdist::PacketMangling::editDNSHeaderFromPacket(dnsQuestion.getMutableData(), [newRCode](dnsheader& header) {
393 header.rcode = static_cast<decltype(header.rcode)>(newRCode);
394 return true;
395 });
396 });
40d01eff
RG
397 luaCtx.registerMember<ComboAddress(DNSResponse::*)>(
398 "remoteaddr", [](const DNSResponse& dnsQuestion) -> ComboAddress { return dnsQuestion.ids.origRemote; }, [](DNSResponse& dnsQuestion, const ComboAddress newRemote) { (void)newRemote; });
086114d5 399 luaCtx.registerMember<dnsheader*(DNSResponse::*)>(
34b2ed52
RG
400 "dh",
401 [](const DNSResponse& dnsResponse) -> dnsheader* {
402 return dnsResponse.getMutableHeader();
403 },
404 [](DNSResponse& dnsResponse, const dnsheader* dnsHeader) {
69534a09
RG
405 dnsdist::PacketMangling::editDNSHeaderFromPacket(dnsResponse.getMutableData(), [&dnsHeader](dnsheader& header) {
406 header = *dnsHeader;
407 return true;
408 });
409 });
086114d5 410 luaCtx.registerMember<uint16_t(DNSResponse::*)>(
40d01eff 411 "len", [](const DNSResponse& dnsQuestion) -> uint16_t { return dnsQuestion.getData().size(); }, [](DNSResponse& dnsQuestion, uint16_t newlen) { dnsQuestion.getMutableData().resize(newlen); });
086114d5 412 luaCtx.registerMember<uint8_t(DNSResponse::*)>(
40d01eff 413 "opcode", [](const DNSResponse& dnsQuestion) -> uint8_t { return dnsQuestion.getHeader()->opcode; }, [](DNSResponse& dnsQuestion, uint8_t newOpcode) { (void)newOpcode; });
086114d5 414 luaCtx.registerMember<bool(DNSResponse::*)>(
40d01eff 415 "tcp", [](const DNSResponse& dnsQuestion) -> bool { return dnsQuestion.overTCP(); }, [](DNSResponse& dnsQuestion, bool newTcp) { (void)newTcp; });
086114d5 416 luaCtx.registerMember<bool(DNSResponse::*)>(
40d01eff 417 "skipCache", [](const DNSResponse& dnsQuestion) -> bool { return dnsQuestion.ids.skipCache; }, [](DNSResponse& dnsQuestion, bool newSkipCache) { dnsQuestion.ids.skipCache = newSkipCache; });
086114d5 418 luaCtx.registerMember<std::string(DNSResponse::*)>(
40d01eff
RG
419 "pool", [](const DNSResponse& dnsQuestion) -> std::string { return dnsQuestion.ids.poolName; }, [](DNSResponse& dnsQuestion, const std::string& newPoolName) { dnsQuestion.ids.poolName = newPoolName; });
420 luaCtx.registerFunction<void (DNSResponse::*)(std::function<uint32_t(uint8_t section, uint16_t qclass, uint16_t qtype, uint32_t ttl)> editFunc)>("editTTLs", [](DNSResponse& dnsResponse, const std::function<uint32_t(uint8_t section, uint16_t qclass, uint16_t qtype, uint32_t ttl)>& editFunc) {
421 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
422 editDNSPacketTTL(reinterpret_cast<char*>(dnsResponse.getMutableData().data()), dnsResponse.getData().size(), editFunc);
90686725 423 });
40d01eff
RG
424 luaCtx.registerFunction<bool (DNSResponse::*)() const>("getDO", [](const DNSResponse& dnsQuestion) {
425 return getEDNSZ(dnsQuestion) & EDNS_HEADER_FLAG_DO;
90686725 426 });
40d01eff
RG
427 luaCtx.registerFunction<std::string (DNSResponse::*)() const>("getContent", [](const DNSResponse& dnsQuestion) {
428 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
429 return std::string(reinterpret_cast<const char*>(dnsQuestion.getData().data()), dnsQuestion.getData().size());
1bf2f3b2 430 });
40d01eff
RG
431 luaCtx.registerFunction<void (DNSResponse::*)(const std::string&)>("setContent", [](DNSResponse& dnsResponse, const std::string& raw) {
432 uint16_t oldID = dnsResponse.getHeader()->id;
433 auto& buffer = dnsResponse.getMutableData();
27f38b46
RG
434 buffer.clear();
435 buffer.insert(buffer.begin(), raw.begin(), raw.end());
90686725
RG
436 dnsdist::PacketMangling::editDNSHeaderFromPacket(buffer, [oldID](dnsheader& header) {
437 header.id = oldID;
438 return true;
439 });
27f38b46
RG
440 });
441
40d01eff
RG
442 luaCtx.registerFunction<std::map<uint16_t, EDNSOptionView> (DNSResponse::*)() const>("getEDNSOptions", [](const DNSResponse& dnsQuestion) {
443 if (dnsQuestion.ednsOptions == nullptr) {
444 parseEDNSOptions(dnsQuestion);
445 if (dnsQuestion.ednsOptions == nullptr) {
086114d5 446 throw std::runtime_error("parseEDNSOptions should have populated the EDNS options");
e292b91b 447 }
086114d5 448 }
e292b91b 449
40d01eff 450 return *dnsQuestion.ednsOptions;
086114d5 451 });
40d01eff
RG
452 luaCtx.registerFunction<std::string (DNSResponse::*)(void) const>("getTrailingData", [](const DNSResponse& dnsQuestion) {
453 return dnsQuestion.getTrailingData();
086114d5 454 });
40d01eff
RG
455 luaCtx.registerFunction<bool (DNSResponse::*)(std::string)>("setTrailingData", [](DNSResponse& dnsQuestion, const std::string& tail) {
456 return dnsQuestion.setTrailingData(tail);
086114d5 457 });
acf86c7a 458
40d01eff
RG
459 luaCtx.registerFunction<void (DNSResponse::*)(std::string, std::string)>("setTag", [](DNSResponse& dnsResponse, const std::string& strLabel, const std::string& strValue) {
460 dnsResponse.setTag(strLabel, strValue);
086114d5 461 });
acf86c7a 462
40d01eff 463 luaCtx.registerFunction<void (DNSResponse::*)(LuaAssociativeTable<std::string>)>("setTagArray", [](DNSResponse& dnsResponse, const LuaAssociativeTable<string>& tags) {
086114d5 464 for (const auto& tag : tags) {
40d01eff 465 dnsResponse.setTag(tag.first, tag.second);
086114d5
RG
466 }
467 });
40d01eff
RG
468 luaCtx.registerFunction<string (DNSResponse::*)(std::string) const>("getTag", [](const DNSResponse& dnsResponse, const std::string& strLabel) {
469 if (!dnsResponse.ids.qTag) {
086114d5
RG
470 return string();
471 }
acf86c7a 472
086114d5 473 std::string strValue;
40d01eff
RG
474 const auto tagIt = dnsResponse.ids.qTag->find(strLabel);
475 if (tagIt == dnsResponse.ids.qTag->cend()) {
086114d5
RG
476 return string();
477 }
40d01eff 478 return tagIt->second;
086114d5 479 });
40d01eff
RG
480 luaCtx.registerFunction<QTag (DNSResponse::*)(void) const>("getTagArray", [](const DNSResponse& dnsResponse) {
481 if (!dnsResponse.ids.qTag) {
086114d5
RG
482 QTag empty;
483 return empty;
484 }
acf86c7a 485
40d01eff 486 return *dnsResponse.ids.qTag;
086114d5 487 });
acf86c7a 488
40d01eff
RG
489 luaCtx.registerFunction<std::string (DNSResponse::*)() const>("getProtocol", [](const DNSResponse& dnsResponse) {
490 return dnsResponse.getProtocol().toPrettyString();
a58258f9
RG
491 });
492
40d01eff
RG
493 luaCtx.registerFunction<timespec (DNSResponse::*)() const>("getQueryTime", [](const DNSResponse& dnsResponse) {
494 return dnsResponse.ids.queryRealTime.getStartTime();
21e30815
RG
495 });
496
40d01eff 497 luaCtx.registerFunction<void (DNSResponse::*)(std::string)>("sendTrap", [](const DNSResponse& dnsResponse, boost::optional<std::string> reason) {
6bb38cd6 498#ifdef HAVE_NET_SNMP
40d01eff
RG
499 if (g_snmpAgent != nullptr && g_snmpTrapsEnabled) {
500 g_snmpAgent->sendDNSTrap(dnsResponse, reason ? *reason : "");
086114d5 501 }
6bb38cd6 502#endif /* HAVE_NET_SNMP */
086114d5 503 });
255abac6
RG
504
505#ifdef HAVE_DNS_OVER_HTTPS
40d01eff
RG
506 luaCtx.registerFunction<std::string (DNSQuestion::*)(void) const>("getHTTPPath", [](const DNSQuestion& dnsQuestion) {
507 if (dnsQuestion.ids.du == nullptr) {
086114d5
RG
508 return std::string();
509 }
40d01eff 510 return dnsQuestion.ids.du->getHTTPPath();
086114d5 511 });
255abac6 512
40d01eff
RG
513 luaCtx.registerFunction<std::string (DNSQuestion::*)(void) const>("getHTTPQueryString", [](const DNSQuestion& dnsQuestion) {
514 if (dnsQuestion.ids.du == nullptr) {
086114d5
RG
515 return std::string();
516 }
40d01eff 517 return dnsQuestion.ids.du->getHTTPQueryString();
086114d5 518 });
255abac6 519
40d01eff
RG
520 luaCtx.registerFunction<std::string (DNSQuestion::*)(void) const>("getHTTPHost", [](const DNSQuestion& dnsQuestion) {
521 if (dnsQuestion.ids.du == nullptr) {
086114d5
RG
522 return std::string();
523 }
40d01eff 524 return dnsQuestion.ids.du->getHTTPHost();
086114d5 525 });
255abac6 526
40d01eff
RG
527 luaCtx.registerFunction<std::string (DNSQuestion::*)(void) const>("getHTTPScheme", [](const DNSQuestion& dnsQuestion) {
528 if (dnsQuestion.ids.du == nullptr) {
086114d5
RG
529 return std::string();
530 }
40d01eff 531 return dnsQuestion.ids.du->getHTTPScheme();
086114d5 532 });
255abac6 533
40d01eff
RG
534 luaCtx.registerFunction<LuaAssociativeTable<std::string> (DNSQuestion::*)(void) const>("getHTTPHeaders", [](const DNSQuestion& dnsQuestion) {
535 if (dnsQuestion.ids.du == nullptr) {
086114d5
RG
536 return LuaAssociativeTable<std::string>();
537 }
40d01eff 538 return dnsQuestion.ids.du->getHTTPHeaders();
086114d5 539 });
255abac6 540
40d01eff
RG
541 luaCtx.registerFunction<void (DNSQuestion::*)(uint64_t statusCode, const std::string& body, const boost::optional<std::string> contentType)>("setHTTPResponse", [](DNSQuestion& dnsQuestion, uint64_t statusCode, const std::string& body, const boost::optional<std::string>& contentType) {
542 if (dnsQuestion.ids.du == nullptr) {
086114d5
RG
543 return;
544 }
545 checkParameterBound("DNSQuestion::setHTTPResponse", statusCode, std::numeric_limits<uint16_t>::max());
546 PacketBuffer vect(body.begin(), body.end());
40d01eff 547 dnsQuestion.ids.du->setHTTPResponse(statusCode, std::move(vect), contentType ? *contentType : "");
086114d5 548 });
255abac6 549#endif /* HAVE_DNS_OVER_HTTPS */
af9f750c 550
40d01eff 551 luaCtx.registerFunction<bool (DNSQuestion::*)(bool nxd, const std::string& zone, uint64_t ttl, const std::string& mname, const std::string& rname, uint64_t serial, uint64_t refresh, uint64_t retry, uint64_t expire, uint64_t minimum)>("setNegativeAndAdditionalSOA", [](DNSQuestion& dnsQuestion, bool nxd, const std::string& zone, uint64_t ttl, const std::string& mname, const std::string& rname, uint64_t serial, uint64_t refresh, uint64_t retry, uint64_t expire, uint64_t minimum) {
086114d5
RG
552 checkParameterBound("setNegativeAndAdditionalSOA", ttl, std::numeric_limits<uint32_t>::max());
553 checkParameterBound("setNegativeAndAdditionalSOA", serial, std::numeric_limits<uint32_t>::max());
554 checkParameterBound("setNegativeAndAdditionalSOA", refresh, std::numeric_limits<uint32_t>::max());
555 checkParameterBound("setNegativeAndAdditionalSOA", retry, std::numeric_limits<uint32_t>::max());
556 checkParameterBound("setNegativeAndAdditionalSOA", expire, std::numeric_limits<uint32_t>::max());
557 checkParameterBound("setNegativeAndAdditionalSOA", minimum, std::numeric_limits<uint32_t>::max());
61643ae0 558
40d01eff 559 return setNegativeAndAdditionalSOA(dnsQuestion, nxd, DNSName(zone), ttl, DNSName(mname), DNSName(rname), serial, refresh, retry, expire, minimum, false);
086114d5 560 });
27f38b46 561
086114d5 562 luaCtx.registerFunction<void (DNSResponse::*)(uint16_t infoCode, const boost::optional<std::string>& extraText)>("setExtendedDNSError", [](DNSResponse& dnsResponse, uint16_t infoCode, const boost::optional<std::string>& extraText) {
f18d8af3
RG
563 EDNSExtendedError ede;
564 ede.infoCode = infoCode;
565 if (extraText) {
566 ede.extraText = *extraText;
567 }
a3e16785 568 dnsResponse.ids.d_extendedError = std::make_unique<EDNSExtendedError>(ede);
f18d8af3
RG
569 });
570
40d01eff
RG
571 luaCtx.registerFunction<bool (DNSResponse::*)(uint16_t asyncID, uint16_t queryID, uint32_t timeoutMs)>("suspend", [](DNSResponse& dnsResponse, uint16_t asyncID, uint16_t queryID, uint32_t timeoutMs) {
572 dnsResponse.asynchronous = true;
573 return dnsdist::suspendResponse(dnsResponse, asyncID, queryID, timeoutMs);
27f38b46 574 });
b37671bc 575
40d01eff
RG
576 luaCtx.registerFunction<bool (DNSResponse::*)(const DNSName& newName)>("changeName", [](DNSResponse& dnsResponse, const DNSName& newName) -> bool {
577 if (!dnsdist::changeNameInDNSPacket(dnsResponse.getMutableData(), dnsResponse.ids.qname, newName)) {
20790191
RG
578 return false;
579 }
40d01eff 580 dnsResponse.ids.qname = newName;
20790191
RG
581 return true;
582 });
583
40d01eff
RG
584 luaCtx.registerFunction<bool (DNSResponse::*)()>("restart", [](DNSResponse& dnsResponse) {
585 if (!dnsResponse.ids.d_packet) {
b37671bc
RG
586 return false;
587 }
40d01eff
RG
588 dnsResponse.asynchronous = true;
589 dnsResponse.getMutableData() = *dnsResponse.ids.d_packet;
590 auto query = dnsdist::getInternalQueryFromDQ(dnsResponse, false);
b37671bc
RG
591 return dnsdist::queueQueryResumptionEvent(std::move(query));
592 });
0cfda149 593
40d01eff
RG
594 luaCtx.registerFunction<std::shared_ptr<DownstreamState> (DNSResponse::*)(void) const>("getSelectedBackend", [](const DNSResponse& dnsResponse) {
595 return dnsResponse.d_downstream;
ab86fe94 596 });
393ed488 597#endif /* DISABLE_NON_FFI_DQ_BINDINGS */
6bb38cd6 598}