}
DNSAction::Action operator()(DNSQuestion* dq, std::string* ruleresult) const override
{
- if (!dq->qTag) {
- dq->qTag = std::make_shared<QTag>();
- }
-
- dq->qTag->insert({d_tag, d_value});
+ dq->setTag(d_tag, d_value);
return Action::None;
}
}
DNSResponseAction::Action operator()(DNSResponse* dr, std::string* ruleresult) const override
{
- if (!dr->qTag) {
- dr->qTag = std::make_shared<QTag>();
- }
-
- dr->qTag->insert({d_tag, d_value});
+ dr->setTag(d_tag, d_value);
return Action::None;
}
}
}
- if (!dq->qTag) {
- dq->qTag = std::make_shared<QTag>();
- }
-
- dq->qTag->insert({d_tag, std::move(result)});
+ dq->setTag(d_tag, std::move(result));
return Action::None;
}
}
}
- if (!dq->qTag) {
- dq->qTag = std::make_shared<QTag>();
- }
-
- dq->qTag->insert({d_tag, std::move(result)});
+ dq->setTag(d_tag, std::move(result));
return Action::None;
}
});
luaCtx.registerFunction<void(DNSQuestion::*)(std::string, std::string)>("setTag", [](DNSQuestion& dq, const std::string& strLabel, const std::string& strValue) {
- if(dq.qTag == nullptr) {
- dq.qTag = std::make_shared<QTag>();
- }
- dq.qTag->insert({strLabel, strValue});
+ dq.setTag(strLabel, strValue);
});
luaCtx.registerFunction<void(DNSQuestion::*)(vector<pair<string, string>>)>("setTagArray", [](DNSQuestion& dq, const vector<pair<string, string>>&tags) {
- if (!dq.qTag) {
- dq.qTag = std::make_shared<QTag>();
- }
-
for (const auto& tag : tags) {
- dq.qTag->insert({tag.first, tag.second});
+ dq.setTag(tag.first, tag.second);
}
});
luaCtx.registerFunction<string(DNSQuestion::*)(std::string)const>("getTag", [](const DNSQuestion& dq, const std::string& strLabel) {
});
luaCtx.registerFunction<void(DNSResponse::*)(std::string, std::string)>("setTag", [](DNSResponse& dr, const std::string& strLabel, const std::string& strValue) {
- if(dr.qTag == nullptr) {
- dr.qTag = std::make_shared<QTag>();
- }
- dr.qTag->insert({strLabel, strValue});
+ dr.setTag(strLabel, strValue);
});
luaCtx.registerFunction<void(DNSResponse::*)(vector<pair<string, string>>)>("setTagArray", [](DNSResponse& dr, const vector<pair<string, string>>&tags) {
- if (!dr.qTag) {
- dr.qTag = std::make_shared<QTag>();
- }
-
for (const auto& tag : tags) {
- dr.qTag->insert({tag.first, tag.second});
+ dr.setTag(tag.first, tag.second);
}
});
luaCtx.registerFunction<string(DNSResponse::*)(std::string)const>("getTag", [](const DNSResponse& dr, const std::string& strLabel) {
return !(protocol == dnsdist::Protocol::DoUDP || protocol == dnsdist::Protocol::DNSCryptUDP);
}
+ void setTag(const std::string& key, std::string&& value) {
+ if (!qTag) {
+ qTag = std::make_shared<QTag>();
+ }
+ qTag->insert_or_assign(key, std::move(value));
+ }
+
+ void setTag(const std::string& key, const std::string& value) {
+ if (!qTag) {
+ qTag = std::make_shared<QTag>();
+ }
+ qTag->insert_or_assign(key, value);
+ }
+
protected:
PacketBuffer& data;
void dnsdist_ffi_dnsquestion_set_tag(dnsdist_ffi_dnsquestion_t* dq, const char* label, const char* value)
{
- if (!dq->dq->qTag) {
- dq->dq->qTag = std::make_shared<QTag>();
- }
-
- dq->dq->qTag->insert({label, value});
+ dq->dq->setTag(label, value);
}
size_t dnsdist_ffi_dnsquestion_get_trailing_data(dnsdist_ffi_dnsquestion_t* dq, const char** out)
.. method:: DNSQuestion:setTag(key, value)
- Set a tag into the DNSQuestion object.
- This function will not overwrite an existing tag. If the tag already exists it will keep its original value.
+ .. versionchanged:: 1.7.0
+ 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
.. method:: DNSQuestion:setTagArray(tags)
- Set an array of tags into the DNSQuestion object.
- This function will not overwrite an existing tag. If the tag already exists it will keep its original value.
+ .. versionchanged:: 1.7.0
+ 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
.. versionadded:: 1.6.0
+ .. versionchanged:: 1.7.0
+ Prior to 1.7.0 :func:`SetTagAction` would not overwrite an existing tag value if already set.
+
Associate a tag named ``name`` with a value of ``value`` to this query, that will be passed on to the response.
- This function will not overwrite an existing tag. If the tag already exists it will keep its original value.
+ This function will overwrite any existing tag value.
Subsequent rules are processed after this action.
Note that this function was called :func:`TagAction` before 1.6.0.
.. versionadded:: 1.6.0
+ .. versionchanged:: 1.7.0
+ Prior to 1.7.0 :func:`SetTagResponseAction` would not overwrite an existing tag value if already set.
+
Associate a tag named ``name`` with a value of ``value`` to this response.
- This function will not overwrite an existing tag. If the tag already exists it will keep its original value.
+ This function will overwrite any existing tag value.
Subsequent rules are processed after this action.
Note that this function was called :func:`TagResponseAction` before 1.6.0.
receivedQuery.id = query.id
self.assertEqual(query, receivedQuery)
self.assertEqual(expectedResponse, receivedResponse)
+
+class TestSetTagAction(DNSDistTest):
+
+ _config_template = """
+ newServer{address="127.0.0.1:%s"}
+
+ addAction(AllRule(), SetTagAction("dns", "value1"))
+ addAction("tag-me-dns-2.tags.tests.powerdns.com.", SetTagAction("dns", "value2"))
+
+ addAction(TagRule("dns", "value1"), SpoofAction("1.2.3.50"))
+ addAction(TagRule("dns", "value2"), SpoofAction("1.2.3.4"))
+
+ """
+
+ def testSetTagDefault(self):
+
+ """
+ Tag: Test setTag overwrites existing value
+ """
+ name = 'tag-me-dns-1.tags.tests.powerdns.com.'
+ query = dns.message.make_query(name, 'A', 'IN')
+ # dnsdist set RA = RD for spoofed responses
+ query.flags &= ~dns.flags.RD
+ expectedResponse = dns.message.make_response(query)
+ rrset = dns.rrset.from_text(name,
+ 60,
+ dns.rdataclass.IN,
+ dns.rdatatype.A,
+ '1.2.3.50')
+ expectedResponse.answer.append(rrset)
+
+ for method in ("sendUDPQuery", "sendTCPQuery"):
+ sender = getattr(self, method)
+ (_, receivedResponse) = sender(query, response=None, useQueue=False)
+ self.assertTrue(receivedResponse)
+ self.assertEqual(expectedResponse, receivedResponse)
+
+ def testSetTagOverwritten(self):
+
+ """
+ Tag: Test setTag overwrites existing value
+ """
+ name = 'tag-me-dns-2.tags.tests.powerdns.com.'
+ query = dns.message.make_query(name, 'A', 'IN')
+ # dnsdist set RA = RD for spoofed responses
+ query.flags &= ~dns.flags.RD
+ expectedResponse = dns.message.make_response(query)
+ rrset = dns.rrset.from_text(name,
+ 60,
+ dns.rdataclass.IN,
+ dns.rdatatype.A,
+ '1.2.3.4')
+ expectedResponse.answer.append(rrset)
+
+ for method in ("sendUDPQuery", "sendTCPQuery"):
+ sender = getattr(self, method)
+ (_, receivedResponse) = sender(query, response=None, useQueue=False)
+ self.assertTrue(receivedResponse)
+ self.assertEqual(expectedResponse, receivedResponse)
+
+class TestSetTag(DNSDistTest):
+
+ _config_template = """
+ newServer{address="127.0.0.1:%s"}
+
+ function dqset(dq)
+ dq:setTag("dns", "value1")
+ if tostring(dq.qname) == 'tag-me-dns-2.tags.tests.powerdns.com.' then
+ dq:setTag("dns", "value2")
+ end
+ return DNSAction.None, ""
+ end
+
+ addAction(AllRule(), LuaAction(dqset))
+
+ addAction(TagRule("dns", "value1"), SpoofAction("1.2.3.50"))
+ addAction(TagRule("dns", "value2"), SpoofAction("1.2.3.4"))
+
+ """
+
+ def testSetTagDefault(self):
+
+ """
+ Tag: Test setTag overwrites existing value
+ """
+ name = 'tag-me-dns-1.tags.tests.powerdns.com.'
+ query = dns.message.make_query(name, 'A', 'IN')
+ # dnsdist set RA = RD for spoofed responses
+ query.flags &= ~dns.flags.RD
+ expectedResponse = dns.message.make_response(query)
+ rrset = dns.rrset.from_text(name,
+ 60,
+ dns.rdataclass.IN,
+ dns.rdatatype.A,
+ '1.2.3.50')
+ expectedResponse.answer.append(rrset)
+
+ for method in ("sendUDPQuery", "sendTCPQuery"):
+ sender = getattr(self, method)
+ (_, receivedResponse) = sender(query, response=None, useQueue=False)
+ self.assertTrue(receivedResponse)
+ self.assertEqual(expectedResponse, receivedResponse)
+
+ def testSetTagOverwritten(self):
+
+ """
+ Tag: Test setTag overwrites existing value
+ """
+ name = 'tag-me-dns-2.tags.tests.powerdns.com.'
+ query = dns.message.make_query(name, 'A', 'IN')
+ # dnsdist set RA = RD for spoofed responses
+ query.flags &= ~dns.flags.RD
+ expectedResponse = dns.message.make_response(query)
+ rrset = dns.rrset.from_text(name,
+ 60,
+ dns.rdataclass.IN,
+ dns.rdatatype.A,
+ '1.2.3.4')
+ expectedResponse.answer.append(rrset)
+
+ for method in ("sendUDPQuery", "sendTCPQuery"):
+ sender = getattr(self, method)
+ (_, receivedResponse) = sender(query, response=None, useQueue=False)
+ self.assertTrue(receivedResponse)
+ self.assertEqual(expectedResponse, receivedResponse)