Commit 8e00f359 authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

[master] Merge branch 'trac910'

parents f63ff922 f52ff519
......@@ -239,7 +239,28 @@ MessageImpl::toWire(AbstractMessageRenderer& renderer, TSIGContext* tsig_ctx) {
"Message rendering attempted without Opcode set");
}
// Reserve the space for TSIG (if needed) so that we can handle truncation
// case correctly later when that happens. orig_xxx variables remember
// some configured parameters of renderer in case they are needed in
// truncation processing below.
const size_t tsig_len = (tsig_ctx != NULL) ? tsig_ctx->getTSIGLength() : 0;
const size_t orig_msg_len_limit = renderer.getLengthLimit();
const AbstractMessageRenderer::CompressMode orig_compress_mode =
renderer.getCompressMode();
if (tsig_len > 0) {
if (tsig_len > orig_msg_len_limit) {
isc_throw(InvalidParameter, "Failed to render DNS message: "
"too small limit for a TSIG (" <<
orig_msg_len_limit << ")");
}
renderer.setLengthLimit(orig_msg_len_limit - tsig_len);
}
// reserve room for the header
if (renderer.getLengthLimit() < HEADERLEN) {
isc_throw(InvalidParameter, "Failed to render DNS message: "
"too small limit for a Header");
}
renderer.skip(HEADERLEN);
uint16_t qdcount =
......@@ -284,6 +305,22 @@ MessageImpl::toWire(AbstractMessageRenderer& renderer, TSIGContext* tsig_ctx) {
}
}
// If we're adding a TSIG to a truncated message, clear all RRsets
// from the message except for the question before adding the TSIG.
// If even (some of) the question doesn't fit, don't include it.
if (tsig_ctx != NULL && renderer.isTruncated()) {
renderer.clear();
renderer.setLengthLimit(orig_msg_len_limit - tsig_len);
renderer.setCompressMode(orig_compress_mode);
renderer.skip(HEADERLEN);
qdcount = for_each(questions_.begin(), questions_.end(),
RenderSection<QuestionPtr>(renderer,
false)).getTotalCount();
ancount = 0;
nscount = 0;
arcount = 0;
}
// Adjust the counter buffer.
// XXX: these may not be equal to the number of corresponding entries
// in rrsets_[] or questions_ if truncation occurred or an EDNS OPT RR
......@@ -315,10 +352,16 @@ MessageImpl::toWire(AbstractMessageRenderer& renderer, TSIGContext* tsig_ctx) {
renderer.writeUint16At(arcount, header_pos);
// Add TSIG, if necessary, at the end of the message.
// TODO: truncate case consideration
if (tsig_ctx != NULL) {
tsig_ctx->sign(qid_, renderer.getData(),
renderer.getLength())->toWire(renderer);
// Release the reserved space in the renderer.
renderer.setLengthLimit(orig_msg_len_limit);
const int tsig_count =
tsig_ctx->sign(qid_, renderer.getData(),
renderer.getLength())->toWire(renderer);
if (tsig_count != 1) {
isc_throw(Unexpected, "Failed to render a TSIG RR");
}
// update the ARCOUNT for the TSIG RR. Note that for a sane DNS
// message arcount should never overflow to 0.
......
......@@ -565,6 +565,17 @@ public:
/// \c tsig_ctx will be updated based on the fact it was used for signing
/// and with the latest MAC.
///
/// \exception InvalidMessageOperation The message is not in the Render
/// mode, or either Rcode or Opcode is not set.
/// \exception InvalidParameter The allowable limit of \c renderer is too
/// small for a TSIG or the Header section. Note that this shouldn't
/// happen with parameters as defined in the standard protocols,
/// so it's more likely a program bug.
/// \exception Unexpected Rendering the TSIG RR fails. The implementation
/// internally makes sure this doesn't happen, so if that ever occurs
/// it should mean a bug either in the TSIG context or in the renderer
/// implementation.
///
/// \param renderer See the other version
/// \param tsig_ctx A TSIG context that is to be used for signing the
/// message
......
......@@ -703,6 +703,15 @@ Message_toWire(s_Message* self, PyObject* args) {
// python program has a bug.
PyErr_SetString(po_TSIGContextError, ex.what());
return (NULL);
} catch (const std::exception& ex) {
// Other exceptions should be rare (most likely an implementation
// bug)
PyErr_SetString(po_TSIGContextError, ex.what());
return (NULL);
} catch (...) {
PyErr_SetString(PyExc_RuntimeError,
"Unexpected C++ exception in Message.to_wire");
return (NULL);
}
}
PyErr_Clear();
......
......@@ -21,6 +21,7 @@ import unittest
import os
from pydnspp import *
from testutil import *
from pyunittests_util import fix_current_time
# helper functions for tests taken from c++ unittests
if "TESTDATA_PATH" in os.environ:
......@@ -31,7 +32,7 @@ else:
def factoryFromFile(message, file):
data = read_wire_data(file)
message.from_wire(data)
pass
return data
# we don't have direct comparison for rrsets right now (should we?
# should go in the cpp version first then), so also no direct list
......@@ -44,6 +45,15 @@ def compare_rrset_list(list1, list2):
return False
return True
# These are used for TSIG + TC tests
LONG_TXT1 = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcde";
LONG_TXT2 = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456";
LONG_TXT3 = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef01";
LONG_TXT4 = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0";
# a complete message taken from cpp tests, for testing towire and totext
def create_message():
message_render = Message(Message.RENDER)
......@@ -62,16 +72,12 @@ def create_message():
message_render.add_rrset(Message.SECTION_ANSWER, rrset)
return message_render
def strip_mutable_tsig_data(data):
# Unfortunately we cannot easily compare TSIG RR because we can't tweak
# current time. As a work around this helper function strips off the time
# dependent part of TSIG RDATA, i.e., the MAC (assuming HMAC-MD5) and
# Time Signed.
return data[0:-32] + data[-26:-22] + data[-6:]
class MessageTest(unittest.TestCase):
def setUp(self):
# make sure we don't use faked time unless explicitly do so in tests
fix_current_time(None)
self.p = Message(Message.PARSE)
self.r = Message(Message.RENDER)
......@@ -90,6 +96,10 @@ class MessageTest(unittest.TestCase):
self.tsig_key = TSIGKey("www.example.com:SFuWd/q99SzF8Yzd1QbB9g==")
self.tsig_ctx = TSIGContext(self.tsig_key)
def tearDown(self):
# reset any faked current time setting (it would affect other tests)
fix_current_time(None)
def test_init(self):
self.assertRaises(TypeError, Message, -1)
self.assertRaises(TypeError, Message, 3)
......@@ -285,33 +295,112 @@ class MessageTest(unittest.TestCase):
self.assertRaises(InvalidMessageOperation, self.r.to_wire,
MessageRenderer())
def __common_tsigquery_setup(self):
def __common_tsigmessage_setup(self, flags=[Message.HEADERFLAG_RD],
rrtype=RRType("A"), answer_data=None):
self.r.set_opcode(Opcode.QUERY())
self.r.set_rcode(Rcode.NOERROR())
self.r.set_header_flag(Message.HEADERFLAG_RD)
for flag in flags:
self.r.set_header_flag(flag)
if answer_data is not None:
rrset = RRset(Name("www.example.com"), RRClass("IN"),
rrtype, RRTTL(86400))
for rdata in answer_data:
rrset.add_rdata(Rdata(rrtype, RRClass("IN"), rdata))
self.r.add_rrset(Message.SECTION_ANSWER, rrset)
self.r.add_question(Question(Name("www.example.com"),
RRClass("IN"), RRType("A")))
RRClass("IN"), rrtype))
def __common_tsig_checks(self, expected_file):
renderer = MessageRenderer()
self.r.to_wire(renderer, self.tsig_ctx)
actual_wire = strip_mutable_tsig_data(renderer.get_data())
expected_wire = strip_mutable_tsig_data(read_wire_data(expected_file))
self.assertEqual(expected_wire, actual_wire)
self.assertEqual(read_wire_data(expected_file), renderer.get_data())
def test_to_wire_with_tsig(self):
fix_current_time(0x4da8877a)
self.r.set_qid(0x2d65)
self.__common_tsigquery_setup()
self.__common_tsigmessage_setup()
self.__common_tsig_checks("message_toWire2.wire")
def test_to_wire_with_edns_tsig(self):
fix_current_time(0x4db60d1f)
self.r.set_qid(0x6cd)
self.__common_tsigquery_setup()
self.__common_tsigmessage_setup()
edns = EDNS()
edns.set_udp_size(4096)
self.r.set_edns(edns)
self.__common_tsig_checks("message_toWire3.wire")
def test_to_wire_tsig_truncation(self):
fix_current_time(0x4e179212)
data = factoryFromFile(self.p, "message_fromWire17.wire")
self.assertEqual(TSIGError.NOERROR,
self.tsig_ctx.verify(self.p.get_tsig_record(), data))
self.r.set_qid(0x22c2)
self.__common_tsigmessage_setup([Message.HEADERFLAG_QR,
Message.HEADERFLAG_AA,
Message.HEADERFLAG_RD],
RRType("TXT"),
[LONG_TXT1, LONG_TXT2])
self.__common_tsig_checks("message_toWire4.wire")
def test_to_wire_tsig_truncation2(self):
fix_current_time(0x4e179212)
data = factoryFromFile(self.p, "message_fromWire17.wire")
self.assertEqual(TSIGError.NOERROR,
self.tsig_ctx.verify(self.p.get_tsig_record(), data))
self.r.set_qid(0x22c2)
self.__common_tsigmessage_setup([Message.HEADERFLAG_QR,
Message.HEADERFLAG_AA,
Message.HEADERFLAG_RD],
RRType("TXT"),
[LONG_TXT1, LONG_TXT3])
self.__common_tsig_checks("message_toWire4.wire")
def test_to_wire_tsig_truncation3(self):
self.r.set_opcode(Opcode.QUERY())
self.r.set_rcode(Rcode.NOERROR())
for i in range(1, 68):
self.r.add_question(Question(Name("www.example.com"),
RRClass("IN"), RRType(i)))
renderer = MessageRenderer()
self.r.to_wire(renderer, self.tsig_ctx)
self.p.from_wire(renderer.get_data())
self.assertTrue(self.p.get_header_flag(Message.HEADERFLAG_TC))
self.assertEqual(66, self.p.get_rr_count(Message.SECTION_QUESTION))
self.assertNotEqual(None, self.p.get_tsig_record())
def test_to_wire_tsig_no_truncation(self):
fix_current_time(0x4e17b38d)
data = factoryFromFile(self.p, "message_fromWire18.wire")
self.assertEqual(TSIGError.NOERROR,
self.tsig_ctx.verify(self.p.get_tsig_record(), data))
self.r.set_qid(0xd6e2)
self.__common_tsigmessage_setup([Message.HEADERFLAG_QR,
Message.HEADERFLAG_AA,
Message.HEADERFLAG_RD],
RRType("TXT"),
[LONG_TXT1, LONG_TXT4])
self.__common_tsig_checks("message_toWire5.wire")
def test_to_wire_tsig_length_errors(self):
renderer = MessageRenderer()
renderer.set_length_limit(84) # 84 = expected TSIG length - 1
self.__common_tsigmessage_setup()
self.assertRaises(TSIGContextError,
self.r.to_wire, renderer, self.tsig_ctx)
renderer.clear()
self.r.clear(Message.RENDER)
renderer.set_length_limit(86) # 86 = expected TSIG length + 1
self.__common_tsigmessage_setup()
self.assertRaises(TSIGContextError,
self.r.to_wire, renderer, self.tsig_ctx)
# skip the last test of the corresponding C++ test: it requires
# subclassing MessageRenderer, which is (currently) not possible
# for python. In any case, it's very unlikely to happen in practice.
def test_to_text(self):
message_render = create_message()
......
......@@ -74,7 +74,6 @@ class QuestionTest(unittest.TestCase):
self.assertEqual("foo.example.com. IN NS\n", str(self.test_question1))
self.assertEqual("bar.example.com. CH A\n", self.test_question2.to_text())
def test_to_wire_buffer(self):
obuffer = bytes()
obuffer = self.test_question1.to_wire(obuffer)
......@@ -82,7 +81,6 @@ class QuestionTest(unittest.TestCase):
wiredata = read_wire_data("question_toWire1")
self.assertEqual(obuffer, wiredata)
def test_to_wire_renderer(self):
renderer = MessageRenderer()
self.test_question1.to_wire(renderer)
......@@ -91,5 +89,13 @@ class QuestionTest(unittest.TestCase):
self.assertEqual(renderer.get_data(), wiredata)
self.assertRaises(TypeError, self.test_question1.to_wire, 1)
def test_to_wire_truncated(self):
renderer = MessageRenderer()
renderer.set_length_limit(self.example_name1.get_length())
self.assertFalse(renderer.is_truncated())
self.test_question1.to_wire(renderer)
self.assertTrue(renderer.is_truncated())
self.assertEqual(0, renderer.get_length())
if __name__ == '__main__':
unittest.main()
......@@ -57,10 +57,19 @@ Question::toWire(OutputBuffer& buffer) const {
unsigned int
Question::toWire(AbstractMessageRenderer& renderer) const {
const size_t pos0 = renderer.getLength();
renderer.writeName(name_);
rrtype_.toWire(renderer);
rrclass_.toWire(renderer);
// Make sure the renderer has a room for the question
if (renderer.getLength() > renderer.getLengthLimit()) {
renderer.trim(renderer.getLength() - pos0);
renderer.setTruncated();
return (0);
}
return (1); // number of "entries"
}
......
......@@ -201,23 +201,23 @@ public:
/// class description).
///
/// The owner name will be compressed if possible, although it's an
/// unlikely event in practice because the %Question section a DNS
/// unlikely event in practice because the Question section a DNS
/// message normally doesn't contain multiple question entries and
/// it's located right after the Header section.
/// Nevertheless, \c renderer records the information of the owner name
/// so that it can be pointed by other RRs in other sections (which is
/// more likely to happen).
///
/// In theory, an attempt to render a Question may cause truncation
/// (when the Question section contains a large number of entries),
/// but this implementation doesn't catch that situation.
/// It would make the code unnecessarily complicated (though perhaps
/// slightly) for almost impossible case in practice.
/// An upper layer will handle the pathological case as a general error.
/// It could be possible, though very rare in practice, that
/// an attempt to render a Question may cause truncation
/// (when the Question section contains a large number of entries).
/// In such a case this method avoid the rendering and indicate the
/// truncation in the \c renderer. This method returns 0 in this case.
///
/// \param renderer DNS message rendering context that encapsulates the
/// output buffer and name compression information.
/// \return 1
///
/// \return 1 on success; 0 if it causes truncation
unsigned int toWire(AbstractMessageRenderer& renderer) const;
/// \brief Render the Question in the wire format without name compression.
......
......@@ -62,7 +62,6 @@ using namespace isc::dns::rdata;
//
const uint16_t Message::DEFAULT_MAX_UDPSIZE;
const Name test_name("test.example.com");
namespace isc {
namespace util {
......@@ -79,7 +78,8 @@ const uint16_t TSIGContext::DEFAULT_FUDGE;
namespace {
class MessageTest : public ::testing::Test {
protected:
MessageTest() : obuffer(0), renderer(obuffer),
MessageTest() : test_name("test.example.com"), obuffer(0),
renderer(obuffer),
message_parse(Message::PARSE),
message_render(Message::RENDER),
bogus_section(static_cast<Message::Section>(
......@@ -103,8 +103,9 @@ protected:
"FAKEFAKEFAKEFAKE"));
rrset_aaaa->addRRsig(rrset_rrsig);
}
static Question factoryFromFile(const char* datafile);
const Name test_name;
OutputBuffer obuffer;
MessageRenderer renderer;
Message message_parse;
......@@ -114,17 +115,18 @@ protected:
RRsetPtr rrset_aaaa; // AAAA RRset with one RDATA with RRSIG
RRsetPtr rrset_rrsig; // RRSIG for the AAAA RRset
TSIGContext tsig_ctx;
vector<unsigned char> received_data;
vector<unsigned char> expected_data;
static void factoryFromFile(Message& message, const char* datafile);
void factoryFromFile(Message& message, const char* datafile);
};
void
MessageTest::factoryFromFile(Message& message, const char* datafile) {
std::vector<unsigned char> data;
UnitTestUtil::readWireData(datafile, data);
received_data.clear();
UnitTestUtil::readWireData(datafile, received_data);
InputBuffer buffer(&data[0], data.size());
InputBuffer buffer(&received_data[0], received_data.size());
message.fromWire(buffer);
}
......@@ -618,15 +620,43 @@ testGetTime() {
return (NOW);
}
// bit-wise constant flags to configure DNS header flags for test
// messages.
const unsigned int QR_FLAG = 0x1;
const unsigned int AA_FLAG = 0x2;
const unsigned int RD_FLAG = 0x4;
void
commonTSIGToWireCheck(Message& message, MessageRenderer& renderer,
TSIGContext& tsig_ctx, const char* const expected_file)
TSIGContext& tsig_ctx, const char* const expected_file,
unsigned int message_flags = RD_FLAG,
RRType qtype = RRType::A(),
const vector<const char*>* answer_data = NULL)
{
message.setOpcode(Opcode::QUERY());
message.setRcode(Rcode::NOERROR());
message.setHeaderFlag(Message::HEADERFLAG_RD, true);
if ((message_flags & QR_FLAG) != 0) {
message.setHeaderFlag(Message::HEADERFLAG_QR);
}
if ((message_flags & AA_FLAG) != 0) {
message.setHeaderFlag(Message::HEADERFLAG_AA);
}
if ((message_flags & RD_FLAG) != 0) {
message.setHeaderFlag(Message::HEADERFLAG_RD);
}
message.addQuestion(Question(Name("www.example.com"), RRClass::IN(),
RRType::A()));
qtype));
if (answer_data != NULL) {
RRsetPtr ans_rrset(new RRset(Name("www.example.com"), RRClass::IN(),
qtype, RRTTL(86400)));
for (vector<const char*>::const_iterator it = answer_data->begin();
it != answer_data->end();
++it) {
ans_rrset->addRdata(createRdata(qtype, RRClass::IN(), *it));
}
message.addRRset(Message::SECTION_ANSWER, ans_rrset);
}
message.toWire(renderer, tsig_ctx);
vector<unsigned char> expected_data;
......@@ -670,6 +700,182 @@ TEST_F(MessageTest, toWireWithEDNSAndTSIG) {
}
}
// Some of the following tests involve truncation. We use the query name
// "www.example.com" and some TXT question/answers. The length of the
// header and question will be 33 bytes. If we also try to include a
// TSIG of the same key name (not compressed) with HMAC-MD5, the TSIG RR
// will be 85 bytes.
// A long TXT RDATA. With a fully compressed owner name, the corresponding
// RR will be 268 bytes.
const char* const long_txt1 = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcde";
// With a fully compressed owner name, the corresponding RR will be 212 bytes.
// It should result in truncation even without TSIG (33 + 268 + 212 = 513)
const char* const long_txt2 = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456";
// With a fully compressed owner name, the corresponding RR will be 127 bytes.
// So, it can fit in the standard 512 bytes with txt1 and without TSIG, but
// adding a TSIG would result in truncation (33 + 268 + 127 + 85 = 513)
const char* const long_txt3 = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef01";
// This is 1 byte shorter than txt3, which will result in a possible longest
// message containing answer RRs and TSIG.
const char* const long_txt4 = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0";
// Example output generated by
// "dig -y www.example.com:SFuWd/q99SzF8Yzd1QbB9g== www.example.com txt
// QID: 0x22c2
// Time Signed: 0x00004e179212
TEST_F(MessageTest, toWireTSIGTruncation) {
isc::util::detail::gettimeFunction = testGetTime<0x4e179212>;
// Verify a validly signed query so that we can use the TSIG context
factoryFromFile(message_parse, "message_fromWire17.wire");
EXPECT_EQ(TSIGError::NOERROR(),
tsig_ctx.verify(message_parse.getTSIGRecord(),
&received_data[0], received_data.size()));
message_render.setQid(0x22c2);
vector<const char*> answer_data;
answer_data.push_back(long_txt1);
answer_data.push_back(long_txt2);
{
SCOPED_TRACE("Message sign with TSIG and TC bit on");
commonTSIGToWireCheck(message_render, renderer, tsig_ctx,
"message_toWire4.wire",
QR_FLAG|AA_FLAG|RD_FLAG,
RRType::TXT(), &answer_data);
}
}
TEST_F(MessageTest, toWireTSIGTruncation2) {
// Similar to the previous test, but without TSIG it wouldn't cause
// truncation.
isc::util::detail::gettimeFunction = testGetTime<0x4e179212>;
factoryFromFile(message_parse, "message_fromWire17.wire");
EXPECT_EQ(TSIGError::NOERROR(),
tsig_ctx.verify(message_parse.getTSIGRecord(),
&received_data[0], received_data.size()));
message_render.setQid(0x22c2);
vector<const char*> answer_data;
answer_data.push_back(long_txt1);
answer_data.push_back(long_txt3);
{
SCOPED_TRACE("Message sign with TSIG and TC bit on (2)");
commonTSIGToWireCheck(message_render, renderer, tsig_ctx,
"message_toWire4.wire",
QR_FLAG|AA_FLAG|RD_FLAG,
RRType::TXT(), &answer_data);
}
}
TEST_F(MessageTest, toWireTSIGTruncation3) {
// Similar to previous ones, but truncation occurs due to too many
// Questions (very unusual, but not necessarily illegal).
// We are going to create a message starting with a standard
// header (12 bytes) and multiple questions in the Question
// section of the same owner name (changing the RRType, just so
// that it would be the form that would be accepted by the BIND 9
// parser). The first Question is 21 bytes in length, and the subsequent
// ones are 6 bytes. We'll also use a TSIG whose size is 85 bytes.
// Up to 66 questions can fit in the standard 512-byte buffer
// (12 + 21 + 6 * 65 + 85 = 508). If we try to add one more it would
// result in truncation.
message_render.setOpcode(Opcode::QUERY());
message_render.setRcode(Rcode::NOERROR());
for (int i = 1; i <= 67; ++i) {
message_render.addQuestion(Question(Name("www.example.com"),
RRClass::IN(), RRType(i)));
}
message_render.toWire(renderer, tsig_ctx);
// Check the rendered data by parsing it. We only check it has the
// TC bit on, has the correct number of questions, and has a TSIG RR.
// Checking the signature wouldn't be necessary for this rare case
// scenario.
InputBuffer buffer(renderer.getData(), renderer.getLength());
message_parse.fromWire(buffer);
EXPECT_TRUE(message_parse.getHeaderFlag(Message::HEADERFLAG_TC));
// Note that the number of questions are 66, not 67 as we tried to add.
EXPECT_EQ(66, message_parse.getRRCount(Message::SECTION_QUESTION));
EXPECT_TRUE(message_parse.getTSIGRecord() != NULL);
}
TEST_F(MessageTest, toWireTSIGNoTruncation) {
// A boundary case that shouldn't cause truncation: the resulting
// response message with a TSIG will be 512 bytes long.
isc::util::detail::gettimeFunction = testGetTime<0x4e17b38d>;
factoryFromFile(message_parse, "message_fromWire18.wire");
EXPECT_EQ(TSIGError::NOERROR(),
tsig_ctx.verify(message_parse.getTSIGRecord(),
&received_data[0], received_data.size()));
message_render.setQid(0xd6e2);
vector<const char*> answer_data;
answer_data.push_back(long_txt1);
answer_data.push_back(long_txt4);
{
SCOPED_TRACE("Message sign with TSIG, no truncation");
commonTSIGToWireCheck(message_render, renderer, tsig_ctx,
"message_toWire5.wire",
QR_FLAG|AA_FLAG|RD_FLAG,
RRType::TXT(), &answer_data);
}
}