* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "dnsdist.hh"
+#include "dnsdist-async.hh"
#include "dnsdist-ecs.hh"
#include "dnsdist-lua.hh"
#include "dnsparser.hh"
luaCtx.registerFunction<std::string(DNSQuestion::*)()const>("getContent", [](const DNSQuestion& dq) {
return std::string(reinterpret_cast<const char*>(dq.getData().data()), dq.getData().size());
});
+ luaCtx.registerFunction<void(DNSQuestion::*)(const std::string&)>("setContent", [](DNSQuestion& dq, const std::string& raw) {
+ uint16_t oldID = dq.getHeader()->id;
+ auto& buffer = dq.getMutableData();
+ buffer.clear();
+ buffer.insert(buffer.begin(), raw.begin(), raw.end());
+ reinterpret_cast<dnsheader*>(buffer.data())->id = oldID;
+ });
luaCtx.registerFunction<std::map<uint16_t, EDNSOptionView>(DNSQuestion::*)()const>("getEDNSOptions", [](const DNSQuestion& dq) {
if (dq.ednsOptions == nullptr) {
parseEDNSOptions(dq);
setEDNSOption(dq, code, data);
});
+ luaCtx.registerFunction<bool(DNSQuestion::*)(uint16_t asyncID, uint16_t queryID, uint32_t timeoutMs)>("suspend", [](DNSQuestion& dq, uint16_t asyncID, uint16_t queryID, uint32_t timeoutMs) {
+ dq.asynchronous = true;
+ return dnsdist::suspendQuery(dq, asyncID, queryID, timeoutMs);
+ });
+
+class AsynchronousObject
+{
+public:
+ AsynchronousObject(std::unique_ptr<CrossProtocolQuery>&& obj_): object(std::move(obj_))
+ {
+ }
+
+ DNSQuestion getDQ() const
+ {
+ return object->getDQ();
+ }
+
+ DNSResponse getDR() const
+ {
+ return object->getDR();
+ }
+
+ bool resume()
+ {
+ return dnsdist::queueQueryResumptionEvent(std::move(object));
+ }
+
+ bool drop()
+ {
+ auto sender = object->getTCPQuerySender();
+ if (!sender) {
+ return false;
+ }
+
+ struct timeval now;
+ gettimeofday(&now, nullptr);
+ sender->notifyIOError(std::move(object->query.d_idstate), now);
+ return true;
+ }
+
+ bool setRCode(uint8_t rcode, bool clearAnswers)
+ {
+ return dnsdist::setInternalQueryRCode(object->query.d_idstate, object->query.d_buffer, rcode, clearAnswers);
+ }
+
+private:
+ std::unique_ptr<CrossProtocolQuery> object;
+};
+
+ luaCtx.registerFunction<DNSQuestion(AsynchronousObject::*)(void) const>("getDQ", [](const AsynchronousObject& obj) {
+ return obj.getDQ();
+ });
+
+ luaCtx.registerFunction<DNSQuestion(AsynchronousObject::*)(void) const>("getDR", [](const AsynchronousObject& obj) {
+ return obj.getDR();
+ });
+
+ luaCtx.registerFunction<bool(AsynchronousObject::*)(void)>("resume", [](AsynchronousObject& obj) {
+ return obj.resume();
+ });
+
+ luaCtx.registerFunction<bool(AsynchronousObject::*)(void)>("drop", [](AsynchronousObject& obj) {
+ return obj.drop();
+ });
+
+ luaCtx.registerFunction<bool(AsynchronousObject::*)(uint8_t, bool)>("setRCode", [](AsynchronousObject& obj, uint8_t rcode, bool clearAnswers) {
+ return obj.setRCode(rcode, clearAnswers);
+ });
+
+ luaCtx.writeFunction("getAsynchronousObject", [](uint16_t asyncID, uint16_t queryID) -> AsynchronousObject {
+ if (!dnsdist::g_asyncHolder) {
+ throw std::runtime_error("Unable to resume, no asynchronous holder");
+ }
+ auto query = dnsdist::g_asyncHolder->get(asyncID, queryID);
+ if (!query) {
+ throw std::runtime_error("Unable to find asynchronous object");
+ }
+ return AsynchronousObject(std::move(query));
+ });
+
/* LuaWrapper doesn't support inheritance */
luaCtx.registerMember<const ComboAddress (DNSResponse::*)>("localaddr", [](const DNSResponse& dq) -> const ComboAddress { return dq.ids.origDest; }, [](DNSResponse& dq, const ComboAddress newLocal) { (void) newLocal; });
luaCtx.registerMember<const DNSName (DNSResponse::*)>("qname", [](const DNSResponse& dq) -> const DNSName { return dq.ids.qname; }, [](DNSResponse& dq, const DNSName newName) { (void) newName; });
luaCtx.registerFunction<std::string(DNSResponse::*)()const>("getContent", [](const DNSResponse& dq) {
return std::string(reinterpret_cast<const char*>(dq.getData().data()), dq.getData().size());
});
+ luaCtx.registerFunction<void(DNSResponse::*)(const std::string&)>("setContent", [](DNSResponse& dr, const std::string& raw) {
+ uint16_t oldID = dr.getHeader()->id;
+ auto& buffer = dr.getMutableData();
+ buffer.clear();
+ buffer.insert(buffer.begin(), raw.begin(), raw.end());
+ reinterpret_cast<dnsheader*>(buffer.data())->id = oldID;
+ });
+
luaCtx.registerFunction<std::map<uint16_t, EDNSOptionView>(DNSResponse::*)()const>("getEDNSOptions", [](const DNSResponse& dq) {
if (dq.ednsOptions == nullptr) {
parseEDNSOptions(dq);
return setNegativeAndAdditionalSOA(dq, nxd, DNSName(zone), ttl, DNSName(mname), DNSName(rname), serial, refresh, retry, expire, minimum, false);
});
+
+ luaCtx.registerFunction<bool(DNSResponse::*)(uint16_t asyncID, uint16_t queryID, uint32_t timeoutMs)>("suspend", [](DNSResponse& dr, uint16_t asyncID, uint16_t queryID, uint32_t timeoutMs) {
+ dr.asynchronous = true;
+ return dnsdist::suspendResponse(dr, asyncID, queryID, timeoutMs);
+ });
#endif /* DISABLE_NON_FFI_DQ_BINDINGS */
}
dh.rd=v;
});
- luaCtx.registerFunction<bool(dnsheader::*)()>("getRD", [](dnsheader& dh) {
+ luaCtx.registerFunction<bool(dnsheader::*)()const>("getRD", [](const dnsheader& dh) {
return (bool)dh.rd;
});
dh.ra=v;
});
- luaCtx.registerFunction<bool(dnsheader::*)()>("getRA", [](dnsheader& dh) {
+ luaCtx.registerFunction<bool(dnsheader::*)()const>("getRA", [](const dnsheader& dh) {
return (bool)dh.ra;
});
dh.ad=v;
});
- luaCtx.registerFunction<bool(dnsheader::*)()>("getAD", [](dnsheader& dh) {
+ luaCtx.registerFunction<bool(dnsheader::*)()const>("getAD", [](const dnsheader& dh) {
return (bool)dh.ad;
});
dh.aa=v;
});
- luaCtx.registerFunction<bool(dnsheader::*)()>("getAA", [](dnsheader& dh) {
+ luaCtx.registerFunction<bool(dnsheader::*)()const>("getAA", [](const dnsheader& dh) {
return (bool)dh.aa;
});
dh.cd=v;
});
- luaCtx.registerFunction<bool(dnsheader::*)()>("getCD", [](dnsheader& dh) {
+ luaCtx.registerFunction<bool(dnsheader::*)()const >("getCD", [](const dnsheader& dh) {
return (bool)dh.cd;
});
+ luaCtx.registerFunction<uint16_t(dnsheader::*)()const>("getID", [](const dnsheader& dh) {
+ return ntohs(dh.id);
+ });
+
luaCtx.registerFunction<void(dnsheader::*)(bool)>("setTC", [](dnsheader& dh, bool v) {
dh.tc=v;
if(v) dh.ra = dh.rd; // you'll always need this, otherwise TC=1 gets ignored
#include "dnsdist-async.hh"
#include "dnsdist-dnsparser.hh"
+#include "dnsdist-ecs.hh"
#include "dnsdist-lua-ffi.hh"
#include "dnsdist-mac-address.hh"
#include "dnsdist-lua-network.hh"
{
try {
dq->dq->asynchronous = true;
- dnsdist::suspendQuery(*dq->dq, asyncID, queryID, timeoutMs);
- return true;
+ return dnsdist::suspendQuery(*dq->dq, asyncID, queryID, timeoutMs);
}
catch (const std::exception& e) {
vinfolog("Error in dnsdist_ffi_dnsquestion_set_async: %s", e.what());
return false;
}
- dnsdist::suspendResponse(*dr, asyncID, queryID, timeoutMs);
- return true;
+ return dnsdist::suspendResponse(*dr, asyncID, queryID, timeoutMs);
}
catch (const std::exception& e) {
vinfolog("Error in dnsdist_ffi_dnsresponse_set_async: %s", e.what());
return false;
}
- const auto qnameLength = query->query.d_idstate.qname.wirelength();
- auto& buffer = query->query.d_buffer;
- if (buffer.size() < sizeof(dnsheader) + qnameLength + sizeof(uint16_t) + sizeof(uint16_t)) {
+ if (!dnsdist::setInternalQueryRCode(query->query.d_idstate, query->query.d_buffer, rcode, clearAnswers)) {
return false;
}
- EDNS0Record edns0;
- bool hadEDNS = false;
- if (clearAnswers) {
- hadEDNS = getEDNS0Record(buffer, edns0);
- }
-
- auto dh = reinterpret_cast<dnsheader*>(buffer.data());
- dh->rcode = rcode;
- dh->ad = false;
- dh->aa = false;
- dh->ra = dh->rd;
- dh->qr = true;
-
- if (clearAnswers) {
- dh->ancount = 0;
- dh->nscount = 0;
- dh->arcount = 0;
- buffer.resize(sizeof(dnsheader) + qnameLength + sizeof(uint16_t) + sizeof(uint16_t));
- if (hadEDNS) {
- if (!addEDNS(buffer, query->query.d_idstate.protocol.isUDP() ? 4096 : std::numeric_limits<uint16_t>::max(), edns0.extFlags & htons(EDNS_HEADER_FLAG_DO), g_PayloadSizeSelfGenAnswers, 0)) {
- return false;
- }
- }
- }
-
query->query.d_idstate.skipCache = true;
return dnsdist::queueQueryResumptionEvent(std::move(query));