[svn] commit: r41 - in /experiments/jinmei-messageapi: Makefile dnsexceptions.hh dnsmessage-test.cc dnsmessage.cc dnsmessage.hh dnsname.cc dnsname.hh rrset-test.cc rrset.cc rrset.hh
BIND 10 source code commits
bind10-changes at lists.isc.org
Wed Sep 30 08:29:11 UTC 2009
Author: jinmei
Date: Wed Sep 30 08:29:10 2009
New Revision: 41
Log:
an initial prototyping of the DNS message API.
the test program can send a simple DNS query using the API.
Added:
experiments/jinmei-messageapi/dnsmessage-test.cc
experiments/jinmei-messageapi/dnsmessage.cc
experiments/jinmei-messageapi/dnsmessage.hh
Modified:
experiments/jinmei-messageapi/Makefile
experiments/jinmei-messageapi/dnsexceptions.hh
experiments/jinmei-messageapi/dnsname.cc
experiments/jinmei-messageapi/dnsname.hh
experiments/jinmei-messageapi/rrset-test.cc
experiments/jinmei-messageapi/rrset.cc
experiments/jinmei-messageapi/rrset.hh
Modified: experiments/jinmei-messageapi/Makefile
==============================================================================
--- experiments/jinmei-messageapi/Makefile (original)
+++ experiments/jinmei-messageapi/Makefile Wed Sep 30 08:29:10 2009
@@ -1,7 +1,7 @@
CC = g++
CFLAGS = -g -Wall
BOOSTINCFLAG = -I. -I/usr/pkg/include -I/usr/local/include #define this appropriately
-TARGET = dnsname-test rrset-test
+TARGET = dnsname-test rrset-test dnsmessage-test
.cc.o:
$(CC) $(CFLAGS) $(BOOSTINCFLAG) -c $<
@@ -14,6 +14,9 @@
rrset-test: rrset.o dnsname.o rrset-test.o
$(CC) rrset.o dnsname.o rrset-test.o -o $@
+dnsmessage-test: rrset.o dnsname.o dnsmessage.o dnsmessage-test.o
+ $(CC) dnsmessage.o rrset.o dnsname.o dnsmessage-test.o -o $@
+
##
clean:
/bin/rm -f $(TARGET) *.o *.~
Modified: experiments/jinmei-messageapi/dnsexceptions.hh
==============================================================================
--- experiments/jinmei-messageapi/dnsexceptions.hh (original)
+++ experiments/jinmei-messageapi/dnsexceptions.hh Wed Sep 30 08:29:10 2009
@@ -29,6 +29,10 @@
class DNSInvalidRdataType : public DNSException {};
class DNSRdtypeMismatch : public DNSException {};
class DNSInvalidWireRdata : public DNSException {};
+ class DNSNoMessageRenderer : public DNSException {};
+ class DNSNoNameCompressor : public DNSException {};
+ class DNSInvalidMessageSection : public DNSException {};
+ class DNSInvalidRendererPosition : public DNSException {};
}
}
#endif // __DNSEXCEPTIONS_HH
Modified: experiments/jinmei-messageapi/dnsname.cc
==============================================================================
--- experiments/jinmei-messageapi/dnsname.cc (original)
+++ experiments/jinmei-messageapi/dnsname.cc Wed Sep 30 08:29:10 2009
@@ -17,6 +17,7 @@
#include <stdexcept>
#include "dnsname.hh"
+#include "dnsmessage.hh"
#include "dnsexceptions.hh"
using namespace std;
@@ -282,7 +283,7 @@
}
string
-Name::to_string(bool omit_final_dot) const
+Name::to_text(bool omit_final_dot) const
{
string tdata;
unsigned int nlen;
@@ -398,6 +399,14 @@
return (tdata);
}
+void
+Name::to_wire(MessageRenderer& r, NameCompressor& c) const
+{
+ // TBD: very simple version for prototyping; e.g. it omits compression.
+ r.write_data(_ndata.c_str(), _ndata.size());
+ r.write_uint8(0); // XXX: explicitly need trailing null char
+}
+
bool
Name::operator==(const Name &other) const
{
@@ -453,6 +462,6 @@
ostream &
operator<<(ostream &os, const Name &name)
{
- os << name.to_string(false);
+ os << name.to_text(false);
return (os);
}
Modified: experiments/jinmei-messageapi/dnsname.hh
==============================================================================
--- experiments/jinmei-messageapi/dnsname.hh (original)
+++ experiments/jinmei-messageapi/dnsname.hh Wed Sep 30 08:29:10 2009
@@ -26,67 +26,73 @@
using namespace std;
namespace ISC {
- namespace DNS {
- typedef enum {
- namereln_none = 0,
- namereln_contains = 1,
- namereln_subdomain = 2,
- namereln_equal = 3,
- namereln_commonancestor = 4
- } NameRelation;
- class NameComparisonResult {
- public:
- explicit NameComparisonResult(int order, int nlabels,
- NameRelation reln) :
- _order(order), _nlabels(nlabels), _reln(reln)
- {}
- int order() const { return (_order); }
- int nlabels() const { return (_nlabels); }
- NameRelation reln() const { return (_reln); }
- private:
- int _order;
- int _nlabels;
- NameRelation _reln;
- };
- class Name {
- public:
- // constructors
- Name();
- explicit Name(const string &namestr);
- // need a ctor for "from-wire"? how can we
- // differentiate it with "from-string" (above)?
- // copy constructor (default cp-ctor should work fine)
- //Name(const Name &orig);
- // destructor (default dtor should work fine)
- //~Name();
+namespace DNS {
+class MessageRenderer;
+class NameCompressor;
- // public methods
- string to_string(bool omit_final_dot) const;
- unsigned int countlabels() const { return (_labels); }
- NameComparisonResult fullcompare(const Name &other) const;
- Name split(unsigned int first, unsigned int n) const;
- Name concatenate(const Name &suffix) const;
- bool is_wildcard() const;
- bool is_absolute() const;
- bool operator==(const Name &other) const;
- bool operator!=(const Name &other) const
- {
- return (!(*this == other));
- }
- bool operator<=(const Name &other) const;
- bool operator>=(const Name &other) const;
- bool operator<(const Name &other) const;
- bool operator>(const Name &other) const;
- private:
- string _ndata; // or vector<unsigned char>?
- vector<char> _offsets;
- unsigned int _length;
- unsigned int _labels;
- bool _is_absolute;
+typedef enum {
+ namereln_none = 0,
+ namereln_contains = 1,
+ namereln_subdomain = 2,
+ namereln_equal = 3,
+ namereln_commonancestor = 4
+} NameRelation;
+class NameComparisonResult {
+public:
+ explicit NameComparisonResult(int order, int nlabels,
+ NameRelation reln) :
+ _order(order), _nlabels(nlabels), _reln(reln)
+ {}
+ int order() const { return (_order); }
+ int nlabels() const { return (_nlabels); }
+ NameRelation reln() const { return (_reln); }
+private:
+ int _order;
+ int _nlabels;
+ NameRelation _reln;
+};
+class Name {
+public:
+ // constructors
+ Name();
+ explicit Name(const string &namestr);
+ // need a ctor for "from-wire"? how can we differentiate it with
+ // "from-string" (above)?
- void from_string(const string &namestr);
- };
+ // copy constructor (default cp-ctor should work fine)
+ //Name(const Name &orig);
+
+ // destructor (default dtor should work fine)
+ //~Name();
+
+ // public methods
+ string to_text(bool omit_final_dot) const;
+ void to_wire(MessageRenderer& r, NameCompressor& c) const;
+ unsigned int countlabels() const { return (_labels); }
+ NameComparisonResult fullcompare(const Name &other) const;
+ Name split(unsigned int first, unsigned int n) const;
+ Name concatenate(const Name &suffix) const;
+ bool is_wildcard() const;
+ bool is_absolute() const;
+ bool operator==(const Name &other) const;
+ bool operator!=(const Name &other) const
+ {
+ return (!(*this == other));
}
+ bool operator<=(const Name &other) const;
+ bool operator>=(const Name &other) const;
+ bool operator<(const Name &other) const;
+ bool operator>(const Name &other) const;
+private:
+ string _ndata; // or vector<unsigned char>?
+ vector<char> _offsets;
+ unsigned int _length;
+ unsigned int _labels;
+ bool _is_absolute;
+
+ void from_string(const string &namestr);
+};
+}
}
ostream &operator<<(ostream &os, const ISC::DNS::Name &name);
Modified: experiments/jinmei-messageapi/rrset-test.cc
==============================================================================
--- experiments/jinmei-messageapi/rrset-test.cc (original)
+++ experiments/jinmei-messageapi/rrset-test.cc Wed Sep 30 08:29:10 2009
@@ -40,33 +40,27 @@
cout << (numericRdtype == RdataType::AAAA) << endl; // should be 1
AAAARdata aaaa("2001:0db8:0000:0000:0000:0000:0000:1234");
- cout << aaaa.toText() << endl; // should be (e.g.) "2001:db8::1234"
+ cout << aaaa.to_text() << endl; // should be (e.g.) "2001:db8::1234"
- // Construct a AAAA rdataset and print it.
- RdataSet rdataset(RdataClass::IN, RdataType::AAAA, 3600);
- rdataset.addRdata(rdataptr_t(new AAAARdata("2001:db8::1234")));
- rdataset.addRdata(rdataptr_t(new AAAARdata("2001:db8::abcd")));
- cout << rdataset.toText() << endl; // "<TTL> IN AAAA <addr>"
- cout << rdataset.countRdata() << endl; // should be 2
+ // Construct a AAAA RRset and print it.
+ RRSet rrset(Name("www.example.com."), RdataClass::IN, RdataType::AAAA,
+ 3600);
+ rrset.add_rdata(rdataptr_t(new AAAARdata("2001:db8::1234")));
+ rrset.add_rdata(rdataptr_t(new AAAARdata("2001:db8::abcd")));
+ cout << rrset.to_text() << endl; // "<name> <TTL> IN AAAA <addr>"
+ cout << rrset.count_rdata() << endl; // should be 2
- // Construct a AAAA RRset, using the rdataset just created above and a
- // name, and print it.
- RRSet rrset(Name("www.example.com."), rdataset);
- rrset.addRdata(rdataptr_t(new AAAARdata("2001:db8::beef")));
- cout << rrset.toText() << endl; // "<name> <TTL> IN AAAA <addr>"
- cout << rrset.countRdata() << endl; // should be 3
-
- // An example use case of examining each rdata in an RRset (or rdataset)
- vector<AAAARdata> datalist = rrset.getRdatalist<AAAARdata>();
+ // An example use case of examining each rdata in an RRset
+ vector<AAAARdata> datalist;
+ rrset.get_rdatalist(datalist);
for (vector<AAAARdata>::const_iterator it = datalist.begin();
it != datalist.end();
++it)
{
- char addrbuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:"
- "255.255.255.255")];
- inet_ntop(AF_INET6, &(*it).getAddress(), addrbuf,
- sizeof(addrbuf)); // omit error check for brevity
- cout << addrbuf << endl;
+ char addrbuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
+ // omit error check for brevity:
+ inet_ntop(AF_INET6, &(*it).getAddress(), addrbuf, sizeof(addrbuf));
+ cout << addrbuf << endl; // 2001:db8::{1234, abcd}
}
return (0);
Modified: experiments/jinmei-messageapi/rrset.cc
==============================================================================
--- experiments/jinmei-messageapi/rrset.cc (original)
+++ experiments/jinmei-messageapi/rrset.cc Wed Sep 30 08:29:10 2009
@@ -23,6 +23,7 @@
#include <cstring>
#include "rrset.hh"
+#include "dnsmessage.hh"
using namespace std;
using namespace ISC::DNS;
@@ -40,7 +41,7 @@
}
const string
-RdataClass::toText() const
+RdataClass::to_text() const
{
// XXX: quick hack
if (_classval == 1)
@@ -48,6 +49,12 @@
else if (_classval == 3)
return ("CHAOS");
throw runtime_error("unexpected case");
+}
+
+void
+RdataClass::to_wire(MessageRenderer& r) const
+{
+ r.write_uint16(_classval);
}
const RdataClass RdataClass::IN("IN");
@@ -66,7 +73,7 @@
}
const string
-RdataType::toText() const
+RdataType::to_text() const
{
if (_typeval == 1)
return ("A");
@@ -75,10 +82,22 @@
throw runtime_error("unexpected case");
}
+void
+RdataType::to_wire(MessageRenderer& r) const
+{
+ r.write_uint16(_typeval);
+}
+
const RdataType RdataType::A("A");
const RdataType RdataType::AAAA("AAAA");
// ...more to follow
+void
+TTL::to_wire(MessageRenderer& r) const
+{
+ r.write_uint16(_ttlval);
+}
+
ARdata::ARdata(const string& addrstr)
{
if (inet_pton(AF_INET, addrstr.c_str(), &_addr) != 1)
@@ -86,21 +105,21 @@
}
void
-ARdata::fromWire(const string& wireData)
+ARdata::from_wire(const string& wireData)
{
if (wireData.size() != sizeof(_addr))
throw DNSInvalidWireRdata();
memcpy(&_addr, wireData.data(), sizeof(_addr));
}
-string
-ARdata::toWire() const
-{
- return (string((const char *)&_addr, sizeof(_addr))); // XXX ugly
-}
-
-string
-ARdata::toText() const
+void
+ARdata::to_wire(MessageRenderer& renderer, NameCompressor& compressor) const
+{
+ //TBD: copy (const char *)&_addr, sizeof(_addr)
+}
+
+string
+ARdata::to_text() const
{
char addrbuf[sizeof("255.255.255.255")];
@@ -117,21 +136,21 @@
}
void
-AAAARdata::fromWire(const string& wireData)
+AAAARdata::from_wire(const string& wireData)
{
if (wireData.size() != sizeof(_addr))
throw DNSInvalidWireRdata();
memcpy(&_addr, wireData.data(), sizeof(_addr));
}
-string
-AAAARdata::toWire() const
-{
- return (string((const char *)&_addr, sizeof(_addr))); // XXX
-}
-
-string
-AAAARdata::toText() const
+void
+AAAARdata::to_wire(MessageRenderer& renderer, NameCompressor& compressor) const
+{
+ //TBD: copy (const char *)&_addr, sizeof(_addr)
+}
+
+string
+AAAARdata::to_text() const
{
char addrbuf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
@@ -142,15 +161,15 @@
}
void
-RdataSet::addRdata(rdataptr_t rdata)
-{
- if (rdata->getType() != _rdtype)
+RdataSet::add_rdata(rdataptr_t rdata)
+{
+ if (rdata->get_type() != _rdtype)
throw DNSRdtypeMismatch();
_rdatalist.push_back(rdata);
}
string
-RdataSet::toTextInternal(const string &prefix) const
+RdataSet::to_text() const
{
string s;
@@ -160,11 +179,98 @@
{
if (!s.empty())
s.push_back('\n');
- if (!prefix.empty())
- s += prefix + " ";
- s += _ttl.toText() + " " + _rdclass.toText() + " " +
- _rdtype.toText() + " " + (**it).toText();
+ s += _ttl.to_text() + " " + _rdclass.to_text() + " " +
+ _rdtype.to_text() + " " + (**it).to_text();
}
return (s);
}
+
+string
+RRSet::to_text() const
+{
+ string s;
+
+ for (vector<rdataptr_t>::const_iterator it = _rdatalist.begin();
+ it != _rdatalist.end();
+ ++it)
+ {
+ if (!s.empty())
+ s.push_back('\n');
+ s += _name.to_text(false) + " ";
+ s += _ttl.to_text() + " " + _rdclass.to_text() + " " +
+ _rdtype.to_text() + " " + (**it).to_text();
+ }
+
+ return (s);
+}
+
+void
+RRSet::add_rdata(rdataptr_t rdata)
+{
+ if (rdata->get_type() != _rdtype)
+ throw DNSRdtypeMismatch();
+ _rdatalist.push_back(rdata);
+}
+
+int
+RRSet::to_wire(Message& message, section_t section)
+{
+ int num_rrs = 0;
+
+ // sort Rdata list based on rrset-order and sortlist, and possible
+ // other options. Details to be considered.
+
+ MessageRenderer& r = message.get_renderer();
+ NameCompressor& c = message.get_compressor();
+ for (vector<rdataptr_t>::iterator it = _rdatalist.begin();
+ it != _rdatalist.end();
+ ++it, ++num_rrs)
+ {
+ _name.to_wire(r, c);
+ _rdtype.to_wire(r);
+ _rdclass.to_wire(r);
+ _ttl.to_wire(r);
+ (**it).to_wire(r, c);
+
+ // TBD: handle truncation case
+ }
+
+ return (num_rrs);
+}
+
+string
+Question::to_text() const
+{
+ // return in dig-style format. note that in the wire format class follows
+ // type.
+ return (_name.to_text(false) + " " + _rdclass.to_text() + " " +
+ _rdtype.to_text());
+}
+
+int
+Question::to_wire(Message& message, section_t section)
+{
+ MessageRenderer& r = message.get_renderer();
+ NameCompressor& c = message.get_compressor();
+
+ _name.to_wire(r, c);
+ _rdtype.to_wire(r);
+ _rdclass.to_wire(r);
+
+ return (1);
+}
+
+#ifdef notyet
+void
+SpecialRRSet::to_wire(Message& message)
+{
+ // sort Rdata list based on rrset-order and sortlist, and possible
+ // other options with no or fewer copies. Details to be considered.
+
+ MessageRenderer& r = message.get_renderer();
+
+ // directly copy or link to wire-formatted data in the renderer for
+ // faster rendering. details to be considered.
+}
+#endif
Modified: experiments/jinmei-messageapi/rrset.hh
==============================================================================
--- experiments/jinmei-messageapi/rrset.hh (original)
+++ experiments/jinmei-messageapi/rrset.hh Wed Sep 30 08:29:10 2009
@@ -33,273 +33,310 @@
using namespace std;
namespace ISC {
- namespace DNS {
- // if we worry about data copy, we may have to use
- // shared pointers at the cost of depending on boost.
- class Rdata;
- typedef boost::shared_ptr<Rdata> rdataptr_t;
- // if we want to avoid the dependency, use this; but we'll have
- // to care much more about resource leak.
- //typedef Rdata * rdataptr_t;
-
- class RdataClass {
- public:
- RdataClass() {}
- explicit RdataClass(uint16_t classval) :
- _classval(classval) {}
- explicit RdataClass(const string& classstr);
- const string toText() const;
- uint16_t toValue() const { return (_classval); }
- bool operator==(const RdataClass& other) const
- { return (_classval == other._classval); }
- bool operator!=(const RdataClass& other) const
- { return (_classval != other._classval); }
-
- // (Some) well-known Rdclass constants
- static const RdataClass IN;
- static const RdataClass CHAOS;
- private:
- uint16_t _classval;
- };
-
- class RdataType {
- public:
- RdataType() {}
- explicit RdataType(uint16_t typeval) :
- _typeval(typeval) {}
- explicit RdataType(const string& typestr);
- const string toText() const;
- uint16_t toValue() const { return (_typeval); }
- bool operator==(const RdataType& other) const
- { return (_typeval == other._typeval); }
- bool operator!=(const RdataType& other) const
- { return (_typeval != other._typeval); }
-
- // (Some) Well-known Rdtype constants
- static const RdataType A;
- static const RdataType AAAA;
- // more to follow...
-
- private:
- uint16_t _typeval;
- };
-
- class TTL {
- public:
- TTL() {}
- // we probably want to pass an integer as an argument
- // of type TTL (e.g., make_rrset(..., 3600), so don't
- // make the constructor explicit here.
- TTL(uint32_t ttlval) : _ttlval(ttlval) {}
- string toText() const
- { return (boost::lexical_cast<string>(_ttlval)); }
- uint32_t toValue() { return (_ttlval); }
- bool operator==(const TTL& other) const
- { return (_ttlval == other._ttlval); }
- bool operator!=(const TTL& other) const
- { return (_ttlval != other._ttlval); }
- // define the following using serial number arithmetic:
- bool operator<=(const TTL &other) const;
- bool operator>=(const TTL &other) const;
- bool operator<(const TTL &other) const;
- bool operator>(const TTL &other) const;
- private:
- uint32_t _ttlval;
- };
-
- // Abstract RDATA class
- class Rdata {
- public:
- virtual ~Rdata() {};
- virtual unsigned int count() const = 0;
- virtual const RdataType& getType() const = 0;
- virtual string toText() const = 0;
- virtual void fromWire(const string& wireData) = 0;
- virtual string toWire() const = 0;
- // need generic method for getting n-th field? c.f. ldns
- // e.g. string getField(int n);
- };
-
- // WireFormat Rdata.
- // Whether to have this as a separate concrete class is an
- // open issue.
- class WireRdata : public Rdata {
- public:
- WireRdata() {}
- explicit WireRdata(const RdataClass& rdclass,
- const RdataType& rdtype,
- const string& wireData) :
- _rdclass(rdclass), _rdtype(rdtype),
- _wireData(wireData) {}
- // disallow fromWire() for this class by not defining
- // it. (should we allow that?)
- string toWire() const { return (_wireData); }
- const RdataType& getType() const { return (_rdtype); }
- private:
- RdataClass _rdclass;
- RdataType _rdtype;
- string _wireData;
- };
-
- // Standard DNS Rdata Subclasses
- class ARdata : public Rdata {
- public:
- ARdata() {}
- // constructor from a textual IPv4 address
- explicit ARdata(const string& addrstr);
- unsigned int count() const { return (1); }
- const RdataType& getType() const
- { return (RdataType::A); }
- string toText() const;
- void fromWire(const string& wireData);
- string toWire() const;
- const struct in_addr& getAddress() const
- { return (_addr); }
- bool operator==(const ARdata &other) const
- { return (_addr.s_addr == other._addr.s_addr); }
- virtual bool operator!=(const ARdata &other) const
- { return !(*this == other); }
- private:
- // XXX: should probably define an "address class"
- // and use it.
- struct in_addr _addr;
- };
-
- class AAAARdata : public Rdata {
- public:
- AAAARdata() {}
- // constructor from a textual IPv6 address
- AAAARdata(const string& addrstr);
- unsigned int count() const { return (1); }
- string toText() const;
- const RdataType& getType() const
- { return (RdataType::AAAA); }
- void fromWire(const string& wireData);
- string toWire() const;
- const struct in6_addr& getAddress() const
- { return (_addr); }
- bool operator==(const AAAARdata &other) const
- {
- return (IN6_ARE_ADDR_EQUAL(&_addr,
- &other._addr));
- }
- virtual bool operator!=(const AAAARdata &other) const
- { return !(*this == other); }
- private:
- // XXX: should probably define an "address class"
- // and use it.
- struct in6_addr _addr;
- };
-
- // add NSRdata, MXRdata, etc...
-
- // A set of RDATAs. This is a primary class internally used
- // in our major software such as name servers.
- // Open Issues:
- // - add more set-like operations, e.g, merge?
- // - add a "sort" method? "search(find)" method?
- // - BIND9 libdns has some special DNSSEC-related methods
- // such as addnoqname(), addclosest(). do we need these?
- // - need to check duplicate rdata in addrdata()?
- // - need a comparison method? if so, should it compare
- // rdata's as a set or as a list (compare each rdata one
- // by one)? ldns has ldns_rr_list_compare(), which takes
- // the latter approach (assuming the caller sorts the lists
- // beforehand?).
- class RdataSet {
- public:
- RdataSet() {}
- explicit RdataSet(const RdataClass& rdclass,
- const RdataType& rdtype,
- const TTL& ttl) :
- _rdclass(rdclass), _rdtype(rdtype), _ttl(ttl) {}
- void addRdata(rdataptr_t rdata);
- void removeRdata(const Rdata& rdata);
- string toText() const
- { return (toTextInternal("")); }
- string toWire() const;
- unsigned int countRdata() const
- { return (_rdatalist.size()); }
- const RdataClass& getClass() const
- { return (_rdclass); }
- const RdataType& getType() const { return (_rdtype); }
- const TTL& getTTL() const { return (_ttl); }
- template <typename T> vector<T> getRdatalist() const;
- protected:
- string toTextInternal(const string& prefix) const;
- private:
- RdataClass _rdclass;
- RdataType _rdtype;
- TTL _ttl;
- vector<rdataptr_t> _rdatalist;
- };
-
- template <typename T> vector<T>
- RdataSet::getRdatalist() const
- {
- vector<T> ret;
- vector<rdataptr_t>::const_iterator it;
- for (it = _rdatalist.begin();
- it != _rdatalist.end();
- ++it) {
- T concreateRdata;
-
- if (concreateRdata.getType() !=
- (**it).getType()) {
- throw DNSRdtypeMismatch();
- }
- concreateRdata.fromWire((**it).toWire());
- ret.push_back(concreateRdata);
- }
- return (ret);
+namespace DNS {
+// if we worry about data copy, we may have to use
+// shared pointers at the cost of depending on boost.
+class Rdata;
+typedef boost::shared_ptr<Rdata> rdataptr_t;
+// if we want to avoid the dependency, use this; but we'll have
+// to care much more about resource leak.
+//typedef Rdata * rdataptr_t;
+class Message;
+class MessageRenderer;
+class NameCompressor;
+
+// XXX: this should be defined somewhere else.
+typedef enum { SECTION_QUESTION = 0,
+ SECTION_ANSWER = 1,
+ SECTION_AUTHORITY = 2,
+ SECTION_ADDITIONAL = 3,
+ SECTION_MAX = 4 } section_t;
+
+class RdataClass {
+public:
+ RdataClass() {}
+ explicit RdataClass(uint16_t classval) :
+ _classval(classval) {}
+ explicit RdataClass(const string& classstr);
+ const string to_text() const;
+ void to_wire(MessageRenderer& r) const;
+ uint16_t get_value() const { return (_classval); }
+ bool operator==(const RdataClass& other) const
+ { return (_classval == other._classval); }
+ bool operator!=(const RdataClass& other) const
+ { return (_classval != other._classval); }
+
+ // (Some) well-known Rdclass constants
+ static const RdataClass IN;
+ static const RdataClass CHAOS;
+private:
+ uint16_t _classval;
+};
+
+class RdataType {
+public:
+ RdataType() {}
+ explicit RdataType(uint16_t typeval) :
+ _typeval(typeval) {}
+ explicit RdataType(const string& typestr);
+ const string to_text() const;
+ void to_wire(MessageRenderer& r) const;
+ uint16_t get_value() const { return (_typeval); }
+ bool operator==(const RdataType& other) const
+ { return (_typeval == other._typeval); }
+ bool operator!=(const RdataType& other) const
+ { return (_typeval != other._typeval); }
+
+ // (Some) Well-known Rdtype constants
+ static const RdataType A;
+ static const RdataType AAAA;
+ // more to follow...
+
+private:
+ uint16_t _typeval;
+};
+
+class TTL {
+public:
+ TTL() {}
+ // we probably want to pass an integer as an argument
+ // of type TTL (e.g., make_rrset(..., 3600), so don't
+ // make the constructor explicit here.
+ TTL(uint32_t ttlval) : _ttlval(ttlval) {}
+ string to_text() const
+ { return (boost::lexical_cast<string>(_ttlval)); }
+ void to_wire(MessageRenderer& r) const;
+ uint32_t get_value() { return (_ttlval); }
+ bool operator==(const TTL& other) const
+ { return (_ttlval == other._ttlval); }
+ bool operator!=(const TTL& other) const
+ { return (_ttlval != other._ttlval); }
+ // define the following using serial number arithmetic:
+ bool operator<=(const TTL &other) const;
+ bool operator>=(const TTL &other) const;
+ bool operator<(const TTL &other) const;
+ bool operator>(const TTL &other) const;
+private:
+ uint32_t _ttlval;
+};
+
+// Abstract RDATA class
+class Rdata {
+public:
+ virtual ~Rdata() {};
+ virtual unsigned int count() const = 0;
+ virtual const RdataType& get_type() const = 0;
+ virtual string to_text() const = 0;
+ virtual void from_wire(const string& wireData) = 0;
+ virtual void to_wire(MessageRenderer& r,
+ NameCompressor& c) const = 0;
+ // need generic method for getting n-th field? c.f. ldns
+ // e.g. string getField(int n);
+};
+
+// WireFormat Rdata.
+// Whether to have this as a separate concrete class is an
+// open issue.
+class WireRdata : public Rdata {
+public:
+ WireRdata() {}
+ explicit WireRdata(const RdataClass& rdclass,
+ const RdataType& rdtype,
+ const string& wireData) :
+ _rdclass(rdclass), _rdtype(rdtype),
+ _wireData(wireData) {}
+ // disallow to/from_wire() for this class by not defining
+ // it. (should we allow that?)
+ const RdataType& get_type() const { return (_rdtype); }
+private:
+ RdataClass _rdclass;
+ RdataType _rdtype;
+ string _wireData;
+};
+
+// Standard DNS Rdata Subclasses
+class ARdata : public Rdata {
+public:
+ ARdata() {}
+ // constructor from a textual IPv4 address
+ explicit ARdata(const string& addrstr);
+ unsigned int count() const { return (1); }
+ const RdataType& get_type() const { return (RdataType::A); }
+ static const RdataType& get_type_static() { return (RdataType::A); }
+ string to_text() const;
+ void from_wire(const string& wireData);
+ void to_wire(MessageRenderer& r, NameCompressor& c) const;
+ const struct in_addr& getAddress() const
+ { return (_addr); }
+ bool operator==(const ARdata &other) const
+ { return (_addr.s_addr == other._addr.s_addr); }
+ virtual bool operator!=(const ARdata &other) const
+ { return !(*this == other); }
+private:
+ // XXX: should probably define an "address class"
+ // and use it.
+ struct in_addr _addr;
+};
+
+class AAAARdata : public Rdata {
+public:
+ AAAARdata() {}
+ // constructor from a textual IPv6 address
+ AAAARdata(const string& addrstr);
+ unsigned int count() const { return (1); }
+ string to_text() const;
+ const RdataType& get_type() const { return (RdataType::AAAA); }
+ static const RdataType& get_type_static()
+ { return (RdataType::AAAA); }
+ void from_wire(const string& wireData);
+ void to_wire(MessageRenderer& r, NameCompressor& c) const;
+ const struct in6_addr& getAddress() const
+ { return (_addr); }
+ bool operator==(const AAAARdata &other) const
+ { return (IN6_ARE_ADDR_EQUAL(&_addr, &other._addr)); }
+ virtual bool operator!=(const AAAARdata &other) const
+ { return !(*this == other); }
+private:
+ // XXX: should probably define an "address class"
+ // and use it.
+ struct in6_addr _addr;
+};
+
+// add NSRdata, MXRdata, etc...
+
+// A set of RDATAs. This is a primary class internally used
+// in our major software such as name servers.
+// Open Issues:
+// - add more set-like operations, e.g, merge?
+// - add a "sort" method? "search(find)" method?
+// - BIND9 libdns has some special DNSSEC-related methods
+// such as addnoqname(), addclosest(). do we need these?
+// - need to check duplicate rdata in addrdata()?
+// - need a comparison method? if so, should it compare
+// rdata's as a set or as a list (compare each rdata one
+// by one)? ldns has ldns_rr_list_compare(), which takes
+// the latter approach (assuming the caller sorts the lists
+// beforehand?).
+class RdataSet {
+public:
+ RdataSet() {}
+ explicit RdataSet(const RdataClass& rdclass,
+ const RdataType& rdtype,
+ const TTL& ttl) :
+ _rdclass(rdclass), _rdtype(rdtype), _ttl(ttl) {}
+ void add_rdata(rdataptr_t rdata);
+ void remove_rdata(const Rdata& rdata);
+ string to_text() const;
+ string to_wire() const;
+ unsigned int count_rdata() const { return (_rdatalist.size()); }
+ const RdataClass& get_class() const { return (_rdclass); }
+ const RdataType& get_type() const { return (_rdtype); }
+ const TTL& getTTL() const { return (_ttl); }
+private:
+ RdataClass _rdclass;
+ RdataType _rdtype;
+ TTL _ttl;
+ vector<rdataptr_t> _rdatalist;
+};
+
+// An RRSet. Conceptually it's a named RdataSet. A (section
+// of) DNS message would consist of a list of RRSets.
+class AbstractRRSet {
+public:
+ virtual ~AbstractRRSet() {}
+ virtual string to_text() const = 0;
+ virtual int to_wire(Message& message, section_t section) = 0;
+ virtual unsigned int count_rdata() const = 0;
+ virtual const Name& get_name() const = 0;
+ virtual const RdataClass& get_class() const = 0;
+ virtual const RdataType& get_type() const = 0;
+};
+
+class RRSet : public AbstractRRSet {
+public:
+ RRSet() {}
+ explicit RRSet(const Name &name,
+ const RdataClass &rdclass,
+ const RdataType &rdtype,
+ const TTL &ttl) :
+ _name(name), _rdclass(rdclass), _rdtype(rdtype), _ttl(ttl) {}
+ unsigned int count_rdata() const { return (_rdatalist.size()); }
+ void add_rdata(rdataptr_t rdata);
+ void remove_rdata(const Rdata& rdata);
+ string to_text() const;
+ int to_wire(Message& message, section_t section);
+ const Name& get_name() const { return (_name); }
+ const RdataClass& get_class() const { return (_rdclass); }
+ const RdataType& get_type() const { return (_rdtype); }
+ const TTL& get_ttl() const { return (_ttl); }
+ template <typename T> void get_rdatalist(vector<T>&) const;
+private:
+ Name _name;
+ RdataClass _rdclass;
+ RdataType _rdtype;
+ TTL _ttl;
+ vector<rdataptr_t> _rdatalist;
+};
+
+class Question : public AbstractRRSet { // generic Question section entry
+public:
+ explicit Question(const Name& name, const RdataClass& rdclass,
+ const RdataType& rdtype) :
+ _name(name), _rdclass(rdclass), _rdtype(rdtype) {}
+ string to_text() const;
+ int to_wire(Message& message, section_t section);
+ unsigned int count_rdata() const { return (0); }
+ const Name& get_name() const { return (_name); }
+ const RdataClass& get_class() const { return (_rdclass); }
+ const RdataType& get_type() const { return (_rdtype); }
+
+private:
+ Name _name;
+ RdataClass _rdclass;
+ RdataType _rdtype;
+};
+
+// TBD: this interface should be revisited.
+template <typename T>
+void
+RRSet::get_rdatalist(vector<T>& v) const
+{
+ vector<rdataptr_t>::const_iterator it;
+ for (it = _rdatalist.begin(); it != _rdatalist.end(); ++it) {
+ const T& concreteRdata = static_cast<const T&>(**it); // XXX
+ if (T::get_type_static() != (**it).get_type()) {
+ throw DNSRdtypeMismatch();
}
-
- // An RRSet. Conceptually it's a named RdataSet. A (section
- // of) DNS message would consist of a list of RRSets.
- class RRSet : public RdataSet {
- public:
- RRSet() {}
- explicit RRSet(const Name &name,
- const RdataClass &rdclass,
- const RdataType &rdtype,
- const TTL &ttl) :
- RdataSet(rdclass, rdtype, ttl), _name(name) {}
- explicit RRSet(const Name &name,
- const RdataSet &rdataset) :
- RdataSet(rdataset), _name(name) {}
- string toText() const
- { return (toTextInternal(_name.to_string(false))); }
- const Name& getName() const { return (_name); }
- private:
- Name _name;
- };
-
- // A single RR. Architecturally this is redundant, but it
- // would often be convenient if we can handle each RR
- // separately.
- // Note: an RR *is-not-a* set, so conceptually it cannot be a
- // derived class of RdataSet.
- class RR {
- public:
- RR() {}
- explicit RR(const string& rrstr);
- explicit RR(const Name &name, const RdataClass &rdclass,
- const RdataType &rdtype, const TTL &ttl,
- const Rdata &rdata) {}
- string toText() const
- { return (_rrset.toText()); }
- const Name& getName() const
- { return (_rrset.getName()); }
- const RdataClass& getClass() const
- { return (_rrset.getClass()); }
- const RdataType& getType() const
- { return (_rrset.getType()); }
- const TTL& getTTL() const { return (_rrset.getTTL()); }
- private:
- // An RR is (could be) actually implemented as an RRSet
- // containing at most one RR.
- RRSet _rrset;
- };
+ v.push_back(concreteRdata);
}
}
+
+// A single RR. Architecturally this is redundant, but it
+// would often be convenient if we can handle each RR
+// separately.
+// Note: an RR *is-not-a* set, so conceptually it cannot be a
+// derived class of RdataSet.
+class RR {
+public:
+ RR() {}
+ explicit RR(const string& rrstr);
+ explicit RR(const Name &name, const RdataClass &rdclass,
+ const RdataType &rdtype, const TTL &ttl,
+ const Rdata &rdata) {}
+ string to_text() const
+ { return (_rrset.to_text()); }
+ const Name& get_name() const
+ { return (_rrset.get_name()); }
+ const RdataClass& get_class() const
+ { return (_rrset.get_class()); }
+ const RdataType& get_type() const
+ { return (_rrset.get_type()); }
+ const TTL& get_ttl() const { return (_rrset.get_ttl()); }
+private:
+ // An RR is (could be) actually implemented as an RRSet
+ // containing at most one RR.
+ RRSet _rrset;
+};
+}
+}
#endif // __RRSET_HH
More information about the bind10-changes
mailing list