From: Thomas Markwalder Date: Fri, 20 Jul 2018 15:21:23 +0000 (-0400) Subject: [5680] Add ability to fetch unescaped string from dns::Name X-Git-Tag: ha_phase2~30 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9b39ff33438048d53185adf299d8a98cd1f6a5a6;p=thirdparty%2Fkea.git [5680] Add ability to fetch unescaped string from dns::Name src/lib/dns/labelsequence.cc src/lib/dns/labelsequence.h Added LabelSequence::toRawText() src/lib/dns/name.cc src/lib/dns/name.h Added Name::toRawText() and LabelSequence::toRawText() src/lib/dns/tests/labelsequence_unittest.cc src/lib/dns/tests/name_unittest.cc Added unit tests --- diff --git a/src/lib/dns/labelsequence.cc b/src/lib/dns/labelsequence.cc index 686efa65bf..1c63717de2 100644 --- a/src/lib/dns/labelsequence.cc +++ b/src/lib/dns/labelsequence.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2012-2015,2017 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2012-2018 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -279,6 +279,60 @@ LabelSequence::getHash(bool case_sensitive) const { return (hash_val); } +std::string +LabelSequence::toRawText(bool omit_final_dot) const { + const uint8_t* np = &data_[offsets_[first_label_]]; + const uint8_t* np_end = np + getDataLength(); + + // use for integrity check + unsigned int labels = getLabelCount(); + // init with an impossible value to catch error cases in the end: + unsigned int count = Name::MAX_LABELLEN + 1; + + // result string: it will roughly have the same length as the wire format + // label sequence data. reserve that length to minimize reallocation. + std::string result; + result.reserve(getDataLength()); + + while (np != np_end) { + labels--; + count = *np++; + + if (count == 0) { + // We've reached the "final dot". If we've not dumped any + // character, the entire label sequence is the root name. + // In that case we don't omit the final dot. + if (!omit_final_dot || result.empty()) { + result.push_back('.'); + } + break; + } + + if (count <= Name::MAX_LABELLEN) { + assert(np_end - np >= count); + + if (!result.empty()) { + // just after a non-empty label. add a separating dot. + result.push_back('.'); + } + + while (count-- > 0) { + const uint8_t c = *np++; + result.push_back(c); + } + } else { + isc_throw(BadLabelType, "unknown label type in name data"); + } + } + + // We should be at the end of the data and have consumed all labels. + assert(np == np_end); + assert(labels == 0); + + return (result); +} + + std::string LabelSequence::toText(bool omit_final_dot) const { const uint8_t* np = &data_[offsets_[first_label_]]; diff --git a/src/lib/dns/labelsequence.h b/src/lib/dns/labelsequence.h index be5a1efeb8..0b0b2bc4e8 100644 --- a/src/lib/dns/labelsequence.h +++ b/src/lib/dns/labelsequence.h @@ -1,4 +1,4 @@ -// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2012-2018 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -305,6 +305,16 @@ public: /// \return a string representation of the LabelSequence. std::string toText() const; + /// \brief Convert the LabelSequence to a string without escape sequences. + /// + /// The string returned will contain a single character value for any + /// escape sequences in the label(s). + /// + /// \param omit_final_dot whether to omit the trailing dot in the output. + /// \return a string representation of the LabelSequence + /// that does not contain escape sequences. + std::string toRawText(bool omit_final_dot) const; + /// \brief Extend this LabelSequence with the given labelsequence /// /// The given labels are appended to the name data, and internal @@ -351,7 +361,6 @@ private: /// \param omit_final_dot whether to omit the trailing dot in the output. /// \return a string representation of the LabelSequence. std::string toText(bool omit_final_dot) const; - public: /// \brief Calculate a simple hash for the label sequence. /// diff --git a/src/lib/dns/name.cc b/src/lib/dns/name.cc index 94dd25e9b2..e734fb9556 100644 --- a/src/lib/dns/name.cc +++ b/src/lib/dns/name.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2009-2015 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2009-2018 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -509,6 +509,12 @@ Name::toText(bool omit_final_dot) const { return (ls.toText(omit_final_dot)); } +std::string +Name::toRawText(bool omit_final_dot) const { + LabelSequence ls(*this); + return (ls.toRawText(omit_final_dot)); +} + NameComparisonResult Name::compare(const Name& other) const { const LabelSequence ls1(*this); diff --git a/src/lib/dns/name.h b/src/lib/dns/name.h index 27a088e287..92d25cbb23 100644 --- a/src/lib/dns/name.h +++ b/src/lib/dns/name.h @@ -1,4 +1,4 @@ -// Copyright (C) 2009-2015 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2009-2018 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -392,6 +392,16 @@ public: /// \return a string representation of the Name. std::string toText(bool omit_final_dot = false) const; + /// \brief Convert the LabelSequence to a string without escape sequences. + /// + /// The string returned will contain a single character value for any + /// escape sequences in the label(s). + /// + /// \param omit_final_dot whether to omit the trailing dot in the output. + /// \return a string representation of the LabelSequence + /// that does not contain escape sequences. Default value is false. + std::string toRawText(bool omit_final_dot = false) const; + /// \brief Render the Name in the wire format with compression. /// /// This method dumps the Name in wire format with help of \c renderer, diff --git a/src/lib/dns/tests/labelsequence_unittest.cc b/src/lib/dns/tests/labelsequence_unittest.cc index 69e2cb8e4e..3cd1330e09 100644 --- a/src/lib/dns/tests/labelsequence_unittest.cc +++ b/src/lib/dns/tests/labelsequence_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2012-2018 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -629,6 +629,17 @@ TEST_F(LabelSequenceTest, toText) { EXPECT_EQ("0.1", ls_long2.toText()); } +// The following verifies that toRawText() returns a string +// actual characters in place of escape sequences. We do not +// bother with an exhaustive set of tests here as this is +// not a primary use case. +TEST_F(LabelSequenceTest, toRawText) { + Name n("a bc.$exa(m)ple.@org"); + LabelSequence l(n); + EXPECT_EQ("a bc.$exa(m)ple.@org", l.toRawText(true)); + EXPECT_EQ("a bc.$exa(m)ple.@org.", l.toRawText(false)); +} + // The following are test data used in the getHash test below. Normally // we use example/documentation domain names for testing, but in this case // we'd specifically like to use more realistic data, and are intentionally diff --git a/src/lib/dns/tests/name_unittest.cc b/src/lib/dns/tests/name_unittest.cc index d6ef1b2782..0380e59e3e 100644 --- a/src/lib/dns/tests/name_unittest.cc +++ b/src/lib/dns/tests/name_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2009-2017 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2009-2018 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -752,4 +752,17 @@ TEST_F(NameTest, LeftShiftOperator) { oss << example_name; EXPECT_EQ(example_name.toText(), oss.str()); } + +// The following verifies that toRawText() returns a string +// actual characters in place of escape sequences. We do not +// bother with an exhaustive set of tests here as this is +// not a primary use case. +TEST_F(NameTest, toRawText) { + Name n("a bc.$exa(m)ple.@org"); + EXPECT_EQ("a bc.$exa(m)ple.@org", n.toRawText(true)); + EXPECT_EQ("a bc.$exa(m)ple.@org.", n.toRawText(false)); + // Verify default value of omit parameter is false. + EXPECT_EQ("a bc.$exa(m)ple.@org.", n.toRawText()); +} + }