struct InternalQueryState
{
+ struct ProtoBufData
+ {
+ std::optional<boost::uuids::uuid> uniqueId{std::nullopt}; // 17
+ std::string d_deviceName;
+ std::string d_deviceID;
+ std::string d_requestorID;
+ };
+
static void DeleterPlaceHolder(DOHUnit*)
{
}
ComboAddress hopLocal;
DNSName qname; // 24
std::string poolName; // 24
- StopWatch queryRealTime{true}; // 16
+ StopWatch queryRealTime{true}; // 24
std::shared_ptr<DNSDistPacketCache> packetCache{nullptr}; // 16
std::unique_ptr<DNSCryptQuery> dnsCryptQuery{nullptr}; // 8
std::unique_ptr<QTag> qTag{nullptr}; // 8
- std::unique_ptr<PacketBuffer> d_packet; // Initial packet, so we can restart the query from the response path if needed // 8
+ std::unique_ptr<PacketBuffer> d_packet{nullptr}; // Initial packet, so we can restart the query from the response path if needed // 8
+ std::unique_ptr<ProtoBufData> d_protoBufData{nullptr};
boost::optional<uint32_t> tempFailureTTL{boost::none}; // 8
ClientState* cs{nullptr}; // 8
std::unique_ptr<DOHUnit, void (*)(DOHUnit*)> du; // 8
uint16_t cacheFlags{0}; // DNS flags as sent to the backend // 2
uint16_t udpPayloadSize{0}; // Max UDP payload size from the query // 2
dnsdist::Protocol protocol; // 1
- boost::optional<boost::uuids::uuid> uniqueId{boost::none}; // 17 (placed here to reduce the space lost to padding)
bool ednsAdded{false};
bool ecsAdded{false};
bool skipCache{false};
DNSAction::Action operator()(DNSQuestion* dq, std::string* ruleresult) const override
{
- if (!dq->ids.uniqueId) {
- dq->ids.uniqueId = getUniqueID();
+ if (!dq->ids.d_protoBufData) {
+ dq->ids.d_protoBufData = std::make_unique<InternalQueryState::ProtoBufData>();
+ }
+ if (!dq->ids.d_protoBufData->uniqueId) {
+ dq->ids.d_protoBufData->uniqueId = getUniqueID();
}
DNSDistProtoBufMessage message(*dq);
}
DNSResponseAction::Action operator()(DNSResponse* dr, std::string* ruleresult) const override
{
- if (!dr->ids.uniqueId) {
- dr->ids.uniqueId = getUniqueID();
+ if (!dr->ids.d_protoBufData) {
+ dr->ids.d_protoBufData = std::make_unique<InternalQueryState::ProtoBufData>();
+ }
+ if (!dr->ids.d_protoBufData->uniqueId) {
+ dr->ids.d_protoBufData->uniqueId = getUniqueID();
}
DNSDistProtoBufMessage message(*dr, d_includeCNAME);
dq.ids.tempFailureTTL = newValue;
}
);
+ luaCtx.registerMember<std::string (DNSQuestion::*)>("deviceID", [](const DNSQuestion& dq) -> std::string {
+ if (dq.ids.d_protoBufData) {
+ return dq.ids.d_protoBufData->d_deviceID;
+ }
+ return std::string();
+ }, [](DNSQuestion& dq, const std::string& newValue) {
+ if (!dq.ids.d_protoBufData) {
+ dq.ids.d_protoBufData = std::make_unique<InternalQueryState::ProtoBufData>();
+ }
+ dq.ids.d_protoBufData->d_deviceID = newValue;
+ });
+ luaCtx.registerMember<std::string (DNSQuestion::*)>("deviceName", [](const DNSQuestion& dq) -> std::string {
+ if (dq.ids.d_protoBufData) {
+ return dq.ids.d_protoBufData->d_deviceName;
+ }
+ return std::string();
+ }, [](DNSQuestion& dq, const std::string& newValue) {
+ if (!dq.ids.d_protoBufData) {
+ dq.ids.d_protoBufData = std::make_unique<InternalQueryState::ProtoBufData>();
+ }
+ dq.ids.d_protoBufData->d_deviceName = newValue;
+ });
+ luaCtx.registerMember<std::string (DNSQuestion::*)>("requestorID", [](const DNSQuestion& dq) -> std::string {
+ if (dq.ids.d_protoBufData) {
+ return dq.ids.d_protoBufData->d_requestorID;
+ }
+ return std::string();
+ }, [](DNSQuestion& dq, const std::string& newValue) {
+ if (!dq.ids.d_protoBufData) {
+ dq.ids.d_protoBufData = std::make_unique<InternalQueryState::ProtoBufData>();
+ }
+ dq.ids.d_protoBufData->d_requestorID = newValue;
+ });
luaCtx.registerFunction<bool(DNSQuestion::*)()const>("getDO", [](const DNSQuestion& dq) {
return getEDNSZ(dq) & EDNS_HEADER_FLAG_DO;
});
protocol = pdns::ProtoZero::Message::TransportProtocol::DNSCryptTCP;
}
- m.setRequest(d_dq.ids.uniqueId ? *d_dq.ids.uniqueId : getUniqueID(), d_requestor ? *d_requestor : d_dq.ids.origRemote, d_responder ? *d_responder : d_dq.ids.origDest, d_question ? d_question->d_name : d_dq.ids.qname, d_question ? d_question->d_type : d_dq.ids.qtype, d_question ? d_question->d_class : d_dq.ids.qclass, d_dq.getHeader()->id, protocol, d_bytes ? *d_bytes : d_dq.getData().size());
+ m.setRequest(d_dq.ids.d_protoBufData && d_dq.ids.d_protoBufData->uniqueId ? *d_dq.ids.d_protoBufData->uniqueId : getUniqueID(), d_requestor ? *d_requestor : d_dq.ids.origRemote, d_responder ? *d_responder : d_dq.ids.origDest, d_question ? d_question->d_name : d_dq.ids.qname, d_question ? d_question->d_type : d_dq.ids.qtype, d_question ? d_question->d_class : d_dq.ids.qclass, d_dq.getHeader()->id, protocol, d_bytes ? *d_bytes : d_dq.getData().size());
if (d_serverIdentity) {
m.setServerIdentity(*d_serverIdentity);
m.commitResponse();
+ if (d_dq.ids.d_protoBufData) {
+ const auto& pbData = d_dq.ids.d_protoBufData;
+ if (!pbData->d_deviceName.empty()) {
+ m.setDeviceName(pbData->d_deviceName);
+ }
+ if (!pbData->d_deviceID.empty()) {
+ m.setDeviceId(pbData->d_deviceID);
+ }
+ if (!pbData->d_requestorID.empty()) {
+ m.setRequestorId(pbData->d_requestorID);
+ }
+ }
+
for (const auto& [key, values] : d_metaTags) {
if (!values.empty()) {
m.setMeta(key, values, {});
void dnsdist_ffi_dnsquestion_set_tag(dnsdist_ffi_dnsquestion_t* dq, const char* label, const char* value) __attribute__ ((visibility ("default")));
void dnsdist_ffi_dnsquestion_set_tag_raw(dnsdist_ffi_dnsquestion_t* dq, const char* label, const char* value, size_t valueSize) __attribute__ ((visibility ("default")));
+void dnsdist_ffi_dnsquestion_set_requestor_id(dnsdist_ffi_dnsquestion_t* dq, const char* value, size_t valueSize) __attribute__ ((visibility ("default")));
+void dnsdist_ffi_dnsquestion_set_device_id(dnsdist_ffi_dnsquestion_t* dq, const char* value, size_t valueSize) __attribute__ ((visibility ("default")));
+void dnsdist_ffi_dnsquestion_set_device_name(dnsdist_ffi_dnsquestion_t* dq, const char* value, size_t valueSize) __attribute__ ((visibility ("default")));
+
void dnsdist_ffi_dnsquestion_set_http_response(dnsdist_ffi_dnsquestion_t* dq, uint16_t statusCode, const char* body, size_t bodyLen, const char* contentType) __attribute__ ((visibility ("default")));
size_t dnsdist_ffi_dnsquestion_get_trailing_data(dnsdist_ffi_dnsquestion_t* dq, const char** out) __attribute__ ((visibility ("default")));
dq->dq->setTag(label, std::string(value, valueSize));
}
+void dnsdist_ffi_dnsquestion_set_requestor_id(dnsdist_ffi_dnsquestion_t* dq, const char* value, size_t valueSize)
+{
+ if (!dq || !dq->dq || !value) {
+ return;
+ }
+ if (!dq->dq->ids.d_protoBufData) {
+ dq->dq->ids.d_protoBufData = std::make_unique<InternalQueryState::ProtoBufData>();
+ }
+ dq->dq->ids.d_protoBufData->d_requestorID = std::string(value, valueSize);
+}
+
+void dnsdist_ffi_dnsquestion_set_device_id(dnsdist_ffi_dnsquestion_t* dq, const char* value, size_t valueSize)
+{
+ if (!dq || !dq->dq || !value) {
+ return;
+ }
+ if (!dq->dq->ids.d_protoBufData) {
+ dq->dq->ids.d_protoBufData = std::make_unique<InternalQueryState::ProtoBufData>();
+ }
+ dq->dq->ids.d_protoBufData->d_deviceID = std::string(value, valueSize);
+}
+
+void dnsdist_ffi_dnsquestion_set_device_name(dnsdist_ffi_dnsquestion_t* dq, const char* value, size_t valueSize)
+{
+ if (!dq || !dq->dq || !value) {
+ return;
+ }
+ if (!dq->dq->ids.d_protoBufData) {
+ dq->dq->ids.d_protoBufData = std::make_unique<InternalQueryState::ProtoBufData>();
+ }
+ dq->dq->ids.d_protoBufData->d_deviceName = std::string(value, valueSize);
+}
+
size_t dnsdist_ffi_dnsquestion_get_trailing_data(dnsdist_ffi_dnsquestion_t* dq, const char** out)
{
dq->trailingData = dq->dq->getTrailingData();
The DNSQuestion object has several attributes, many of them read-only:
+ .. attribute:: DNSQuestion.deviceID
+
+ .. versionadded:: 1.8.0
+
+ The identifier of the remote device, which will be exported via ProtoBuf if set.
+
+ .. attribute:: DNSQuestion.deviceName
+
+ .. versionadded:: 1.8.0
+
+ The name of the remote device, which will be exported via ProtoBuf if set.
+
.. attribute:: DNSQuestion.dh
The :ref:`DNSHeader` of this query.
:ref:`ComboAddress` of the remote client.
+ .. attribute:: DNSQuestion.requestorID
+
+ .. versionadded:: 1.8.0
+
+ The identifier of the requestor, which will be exported via ProtoBuf if set.
+
.. attribute:: DNSQuestion.rcode
RCode (as an unsigned integer) of this question.
Whether to skip cache lookup / storing the answer for this question, settable.
.. attribute:: DNSQuestion.tempFailureTTL
-
+
On a SERVFAIL or REFUSED from the backend, cache for this amount of seconds, settable.
.. attribute:: DNSQuestion.tcp
Prior to 1.7.0 calling :func:`DNSQuestion:setTag` would not overwrite an existing tag value if already set.
Set a tag into the DNSQuestion object. Overwrites the value if any already exists.
-
+
:param string key: The tag's key
:param string value: The tag's value
Prior to 1.7.0 calling :func:`DNSQuestion:setTagArray` would not overwrite existing tag values if already set.
Set an array of tags into the DNSQuestion object. Overwrites the values if any already exist.
-
+
:param table tags: A table of tags, using strings as keys and values
.. method:: DNSQuestion:setTrailingData(tail) -> bool
dnsdist_ffi_dnsquestion_set_http_response(&lightDQ, 0U, nullptr, 0U, nullptr);
}
}
+
+ const std::string deviceID{"my-device-id"};
+ const std::string deviceName{"my-device-name"};
+ const std::string requestorID{"my-requestor-ID"};
+ dnsdist_ffi_dnsquestion_set_device_id(nullptr, nullptr, 0);
+ dnsdist_ffi_dnsquestion_set_device_id(&lightDQ, nullptr, 0);
+ dnsdist_ffi_dnsquestion_set_device_id(&lightDQ, deviceID.c_str(), deviceID.size());
+ dnsdist_ffi_dnsquestion_set_device_name(nullptr, nullptr, 0);
+ dnsdist_ffi_dnsquestion_set_device_name(&lightDQ, nullptr, 0);
+ dnsdist_ffi_dnsquestion_set_device_name(&lightDQ, deviceName.c_str(), deviceName.size());
+ dnsdist_ffi_dnsquestion_set_requestor_id(nullptr, nullptr, 0);
+ dnsdist_ffi_dnsquestion_set_requestor_id(&lightDQ, nullptr, 0);
+ dnsdist_ffi_dnsquestion_set_requestor_id(&lightDQ, requestorID.c_str(), requestorID.size());
+ BOOST_REQUIRE(ids.d_protoBufData != nullptr);
+ BOOST_CHECK_EQUAL(ids.d_protoBufData->d_deviceID, deviceID);
+ BOOST_CHECK_EQUAL(ids.d_protoBufData->d_deviceName, deviceName);
+ BOOST_CHECK_EQUAL(ids.d_protoBufData->d_requestorID, requestorID);
}
BOOST_AUTO_TEST_CASE(test_Response)