mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-31 05:55:28 +00:00
supported TXT RR (partially) so that we can implement authors.bind:-)
git-svn-id: svn://bind10.isc.org/svn/bind10/branches/f2f200910@172 e5f2f494-b856-4b98-b285-d166d9295462
This commit is contained in:
@@ -46,6 +46,7 @@ class DNSNoMessageParser : public DNSException {};
|
||||
class DNSInvalidMessageSection : public DNSException {};
|
||||
class DNSInvalidRendererPosition : public DNSException {};
|
||||
class DNSMessageTooShort : public DNSException {};
|
||||
class DNSCharStringTooLong : public DNSException {};
|
||||
}
|
||||
}
|
||||
#endif // __EXCEPTIONS_HH
|
||||
|
@@ -307,11 +307,11 @@ Message::addRR(section_t section, const RR& rr)
|
||||
std::bind2nd(MatchRR(), rr));
|
||||
if (it != sections_[section].end()) {
|
||||
(*it)->setTtl(std::min((*it)->getTtl(), rr.getTtl()));
|
||||
(*it)->addRdata(Rdata::RDATAPTR(rr.getRdata()->copy()));
|
||||
(*it)->addRdata(Rdata::RdataPtr(rr.getRdata()->copy()));
|
||||
} else {
|
||||
RRset *rrset = new RRset(rr.getName(), rr.getClass(), rr.getType(),
|
||||
rr.getTtl());
|
||||
rrset->addRdata(Rdata::RDATAPTR(rr.getRdata()->copy()));
|
||||
rrset->addRdata(Rdata::RdataPtr(rr.getRdata()->copy()));
|
||||
sections_[section].push_back(RRsetPtr(rrset));
|
||||
}
|
||||
}
|
||||
|
@@ -36,6 +36,7 @@ using isc::dns::TTL;
|
||||
using isc::dns::Rdata::IN::A;
|
||||
using isc::dns::Rdata::IN::AAAA;
|
||||
using isc::dns::Rdata::Generic::NS;
|
||||
using isc::dns::Rdata::Generic::TXT;
|
||||
using isc::dns::RRset;
|
||||
using isc::dns::Rdata::Rdata;
|
||||
using isc::dns::Question;
|
||||
@@ -81,6 +82,8 @@ RRType::RRType(const std::string& typestr)
|
||||
typeval_ = 1;
|
||||
else if (typestr == "NS")
|
||||
typeval_ = 2;
|
||||
else if (typestr == "TXT")
|
||||
typeval_ = 16;
|
||||
else if (typestr == "AAAA")
|
||||
typeval_ = 28;
|
||||
else
|
||||
@@ -94,6 +97,8 @@ RRType::toText() const
|
||||
return ("A");
|
||||
else if (typeval_ == 2)
|
||||
return ("NS");
|
||||
else if (typeval_ == 16)
|
||||
return ("TXT");
|
||||
else if (typeval_ == 28)
|
||||
return ("AAAA");
|
||||
throw std::runtime_error("unexpected type");
|
||||
@@ -107,6 +112,7 @@ RRType::toWire(Buffer& buffer) const
|
||||
|
||||
const RRType RRType::A("A");
|
||||
const RRType RRType::NS("NS");
|
||||
const RRType RRType::TXT("TXT");
|
||||
const RRType RRType::AAAA("AAAA");
|
||||
// ...more to follow
|
||||
|
||||
@@ -147,6 +153,12 @@ createNSDataFromText(const std::string& text_rdata)
|
||||
return (new NS(text_rdata));
|
||||
}
|
||||
|
||||
Rdata *
|
||||
createTXTDataFromText(const std::string& text_rdata)
|
||||
{
|
||||
return (new TXT(text_rdata));
|
||||
}
|
||||
|
||||
RdataFactoryRegister::RdataFactoryRegister()
|
||||
{
|
||||
rdata_factory_repository.insert(pair<RRClassTypePair, RdataFactory>
|
||||
@@ -155,11 +167,17 @@ RdataFactoryRegister::RdataFactoryRegister()
|
||||
rdata_factory_repository.insert(pair<RRClassTypePair, RdataFactory>
|
||||
(RRClassTypePair(RRClass::IN, RRType::AAAA),
|
||||
createAAAADataFromText));
|
||||
//XXX: NS belongs to the 'generic' class. should revisit it.
|
||||
//XXX: NS/TXT belongs to the 'generic' class. should revisit it.
|
||||
rdata_factory_repository.insert(pair<RRClassTypePair, RdataFactory>
|
||||
(RRClassTypePair(RRClass::IN, RRType::NS),
|
||||
createNSDataFromText));
|
||||
}
|
||||
rdata_factory_repository.insert(pair<RRClassTypePair, RdataFactory>
|
||||
(RRClassTypePair(RRClass::IN, RRType::TXT),
|
||||
createTXTDataFromText));
|
||||
// XXX: we should treat class-agnostic type accordingly.
|
||||
rdata_factory_repository.insert(pair<RRClassTypePair, RdataFactory>
|
||||
(RRClassTypePair(RRClass::CH, RRType::TXT),
|
||||
createTXTDataFromText));}
|
||||
|
||||
Rdata *
|
||||
Rdata::fromText(const RRClass& rrclass, const RRType& rrtype,
|
||||
@@ -273,6 +291,90 @@ NS::copy() const
|
||||
return (new NS(toText()));
|
||||
}
|
||||
|
||||
TXT::TXT(const std::string& text_data)
|
||||
{
|
||||
size_t length = text_data.size();
|
||||
size_t pos_begin = 0;
|
||||
|
||||
if (length > 1 && text_data[0] == '"' && text_data[length - 1] == '"') {
|
||||
pos_begin = 1;
|
||||
length -= 2;
|
||||
}
|
||||
if (text_data.size() > MAX_CHARACTER_STRING)
|
||||
throw DNSCharStringTooLong();
|
||||
string_list.push_back(text_data.substr(pos_begin, length));
|
||||
}
|
||||
|
||||
bool
|
||||
TXT::operator==(const TXT& other) const
|
||||
{
|
||||
std::vector<std::string>::const_iterator lit, rit;
|
||||
|
||||
if (count() != other.count())
|
||||
return (false);
|
||||
|
||||
lit = string_list.begin();
|
||||
rit = other.string_list.begin();
|
||||
while (lit != string_list.end()) {
|
||||
if (*lit != *rit)
|
||||
return (false);
|
||||
++lit;
|
||||
++rit;
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
void
|
||||
TXT::fromWire(Buffer& buffer, NameDecompressor& decompressor)
|
||||
{
|
||||
//TBD
|
||||
}
|
||||
|
||||
void
|
||||
TXT::toWire(Buffer& buffer, NameCompressor& compressor) const
|
||||
{
|
||||
std::vector<std::string>::const_iterator it;
|
||||
size_t total_length = 0;
|
||||
size_t length_pos;
|
||||
|
||||
length_pos = buffer.getSize();
|
||||
buffer.writeUint16(0); // dummy data. filled in later
|
||||
|
||||
for (it = string_list.begin(); it != string_list.end(); ++it) {
|
||||
buffer.writeUint8((*it).size());
|
||||
buffer.writeData((*it).c_str(), (*it).size());
|
||||
total_length += (*it).size() + 1;
|
||||
}
|
||||
|
||||
buffer.writeUint16At(total_length, length_pos);
|
||||
}
|
||||
|
||||
std::string
|
||||
TXT::toText() const
|
||||
{
|
||||
std::vector<std::string>::const_iterator it;
|
||||
std::string s;
|
||||
|
||||
// XXX: this implementation is not entirely correct. for example, it
|
||||
// should escape double-quotes if they appear in the character string.
|
||||
for (it = string_list.begin(); it != string_list.end(); ++it) {
|
||||
if (!s.empty())
|
||||
s.push_back(' ');
|
||||
s.push_back('"');
|
||||
s += *it;
|
||||
s.push_back('"');
|
||||
}
|
||||
|
||||
return (s);
|
||||
}
|
||||
|
||||
Rdata*
|
||||
TXT::copy() const
|
||||
{
|
||||
return (new TXT(toText()));
|
||||
}
|
||||
|
||||
std::string
|
||||
RRset::toText() const
|
||||
{
|
||||
|
@@ -81,6 +81,7 @@ public:
|
||||
// (Some) Well-known RRtype constants
|
||||
static const RRType A;
|
||||
static const RRType NS;
|
||||
static const RRType TXT;
|
||||
static const RRType AAAA;
|
||||
// more to follow...
|
||||
|
||||
@@ -163,6 +164,27 @@ public:
|
||||
private:
|
||||
Name nsname_;
|
||||
};
|
||||
|
||||
// A quick hack implementation of TXT RR. It currently supports only one
|
||||
// "character-string".
|
||||
class TXT : public Rdata::Rdata {
|
||||
public:
|
||||
TXT() {}
|
||||
explicit TXT(const std::string& text_data);
|
||||
unsigned int count() const { return (string_list.size()); }
|
||||
const RRType& getType() const { return (RRType::TXT); }
|
||||
static const RRType& getTypeStatic() { return (RRType::TXT); }
|
||||
std::string toText() const;
|
||||
void fromWire(Buffer& b, NameDecompressor& c);
|
||||
void toWire(Buffer& b, NameCompressor& c) const;
|
||||
bool operator==(const TXT &other) const;
|
||||
virtual bool operator!=(const TXT &other) const
|
||||
{ return !(*this == other); }
|
||||
virtual Rdata* copy() const;
|
||||
private:
|
||||
static const unsigned int MAX_CHARACTER_STRING = 255;
|
||||
std::vector<std::string> string_list;
|
||||
};
|
||||
// add MXRdata, etc...
|
||||
}
|
||||
|
||||
|
@@ -30,6 +30,7 @@ using isc::dns::Rdata::Rdata;
|
||||
using isc::dns::Rdata::IN::A;
|
||||
using isc::dns::Rdata::IN::AAAA;
|
||||
using isc::dns::Rdata::Generic::NS;
|
||||
using isc::dns::Rdata::Generic::TXT;
|
||||
using isc::dns::RRset;
|
||||
using isc::dns::RR;
|
||||
using isc::dns::Question;
|
||||
@@ -52,10 +53,12 @@ TEST_F(RRClassTest, fromToText)
|
||||
class RRTypeTest : public ::testing::Test {
|
||||
protected:
|
||||
RRTypeTest() :
|
||||
rrtype_a("A"), rrtype_aaaa("AAAA"), rrtype_ns("NS") {}
|
||||
rrtype_a("A"), rrtype_aaaa("AAAA"), rrtype_ns("NS"), rrtype_txt("TXT")
|
||||
{}
|
||||
RRType rrtype_a;
|
||||
RRType rrtype_aaaa;
|
||||
RRType rrtype_ns;
|
||||
RRType rrtype_txt;
|
||||
};
|
||||
|
||||
TEST_F(RRTypeTest, fromToText)
|
||||
@@ -63,6 +66,7 @@ TEST_F(RRTypeTest, fromToText)
|
||||
EXPECT_EQ("A", rrtype_a.toText());
|
||||
EXPECT_EQ("AAAA", rrtype_aaaa.toText());
|
||||
EXPECT_EQ("NS", rrtype_ns.toText());
|
||||
EXPECT_EQ("TXT", rrtype_txt.toText());
|
||||
}
|
||||
|
||||
// The fixture for testing class TTL.
|
||||
@@ -135,6 +139,29 @@ TEST_F(Rdata_Generic_NS_Test, fromToText)
|
||||
EXPECT_EQ("ns.example.com.", rdata.toText());
|
||||
}
|
||||
|
||||
// The fixture for testing Generic/TXT Rdata class
|
||||
class Rdata_Generic_TXT_Test : public ::testing::Test {
|
||||
protected:
|
||||
Rdata_Generic_TXT_Test() : rdata("this is a test string") {}
|
||||
TXT rdata;
|
||||
};
|
||||
|
||||
TEST_F(Rdata_Generic_TXT_Test, longCharString)
|
||||
{
|
||||
EXPECT_THROW(TXT("0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
"0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
"0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
"0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
"0123456789abcdef0123456789abcdef0123456789abcdef"
|
||||
"0123456789abcdef"),
|
||||
isc::dns::DNSCharStringTooLong);
|
||||
}
|
||||
|
||||
TEST_F(Rdata_Generic_TXT_Test, fromToText)
|
||||
{
|
||||
EXPECT_EQ("\"this is a test string\"", rdata.toText());
|
||||
}
|
||||
|
||||
// The fixture for testing class RRset
|
||||
class RRsetTest : public ::testing::Test {
|
||||
protected:
|
||||
|
Reference in New Issue
Block a user