diff options
Diffstat (limited to 'src/lib/dns/rrset.cc')
-rw-r--r-- | src/lib/dns/rrset.cc | 99 |
1 files changed, 75 insertions, 24 deletions
diff --git a/src/lib/dns/rrset.cc b/src/lib/dns/rrset.cc index 7ea01d0ee5..8dfe884dac 100644 --- a/src/lib/dns/rrset.cc +++ b/src/lib/dns/rrset.cc @@ -17,6 +17,7 @@ #include <vector> #include <boost/shared_ptr.hpp> +#include <boost/foreach.hpp> #include <util/buffer.h> #include <dns/messagerenderer.h> @@ -71,7 +72,10 @@ AbstractRRset::toText() const { return (s); } -namespace { +namespace { // unnamed namespace + +// FIXME: This method's code should somehow be unified with +// BasicRRsetImpl::toWire() below to avoid duplication. template <typename T> inline unsigned int rrsetToWire(const AbstractRRset& rrset, T& output, const size_t limit) { @@ -124,7 +128,8 @@ rrsetToWire(const AbstractRRset& rrset, T& output, const size_t limit) { return (n); } -} + +} // end of unnamed namespace unsigned int AbstractRRset::toWire(OutputBuffer& buffer) const { @@ -164,6 +169,9 @@ public: BasicRRsetImpl(const Name& name, const RRClass& rrclass, const RRType& rrtype, const RRTTL& ttl) : name_(name), rrclass_(rrclass), rrtype_(rrtype), ttl_(ttl) {} + + unsigned int toWire(AbstractMessageRenderer& renderer, size_t limit) const; + Name name_; RRClass rrclass_; RRType rrtype_; @@ -174,6 +182,58 @@ public: vector<ConstRdataPtr> rdatalist_; }; +// FIXME: This method's code should somehow be unified with +// rrsetToWire() above to avoid duplication. +unsigned int +BasicRRsetImpl::toWire(AbstractMessageRenderer& renderer, size_t limit) const { + if (rdatalist_.empty()) { + // empty rrsets are only allowed for classes ANY and NONE + if (rrclass_ != RRClass::ANY() && + rrclass_ != RRClass::NONE()) { + isc_throw(EmptyRRset, "toWire() is attempted for an empty RRset"); + } + + // For an empty RRset, write the name, type, class and TTL once, + // followed by empty rdata. + name_.toWire(renderer); + rrtype_.toWire(renderer); + rrclass_.toWire(renderer); + ttl_.toWire(renderer); + renderer.writeUint16(0); + // Still counts as 1 'rr'; it does show up in the message + return (1); + } + + unsigned int n = 0; + + // sort the set of Rdata based on rrset-order and sortlist, and possible + // other options. Details to be considered. + BOOST_FOREACH(const ConstRdataPtr& rdata, rdatalist_) { + const size_t pos0 = renderer.getLength(); + assert(pos0 < 65536); + + name_.toWire(renderer); + rrtype_.toWire(renderer); + rrclass_.toWire(renderer); + ttl_.toWire(renderer); + + const size_t pos = renderer.getLength(); + renderer.skip(sizeof(uint16_t)); // leave the space for RDLENGTH + rdata->toWire(renderer); + renderer.writeUint16At(renderer.getLength() - pos - sizeof(uint16_t), + pos); + + if (limit > 0 && renderer.getLength() > limit) { + // truncation is needed + renderer.trim(renderer.getLength() - pos0); + return (n); + } + ++n; + } + + return (n); +} + BasicRRset::BasicRRset(const Name& name, const RRClass& rrclass, const RRType& rrtype, const RRTTL& ttl) { @@ -220,11 +280,6 @@ BasicRRset::getTTL() const { } void -BasicRRset::setName(const Name& name) { - impl_->name_ = name; -} - -void BasicRRset::setTTL(const RRTTL& ttl) { impl_->ttl_ = ttl; } @@ -241,7 +296,12 @@ BasicRRset::toWire(OutputBuffer& buffer) const { unsigned int BasicRRset::toWire(AbstractMessageRenderer& renderer) const { - return (AbstractRRset::toWire(renderer)); + const unsigned int rrs_written = impl_->toWire(renderer, + renderer.getLengthLimit()); + if (impl_->rdatalist_.size() > rrs_written) { + renderer.setTruncated(); + } + return (rrs_written); } RRset::RRset(const Name& name, const RRClass& rrclass, @@ -264,15 +324,13 @@ RRset::getRRsigDataCount() const { unsigned int RRset::toWire(OutputBuffer& buffer) const { - unsigned int rrs_written; - - rrs_written = rrsetToWire<OutputBuffer>(*this, buffer, 0); + unsigned int rrs_written = BasicRRset::toWire(buffer); if (getRdataCount() > rrs_written) { return (rrs_written); } if (rrsig_) { - rrs_written += rrsetToWire<OutputBuffer>(*(rrsig_.get()), buffer, 0); + rrs_written += rrsig_->toWire(buffer); } return (rrs_written); @@ -280,24 +338,17 @@ RRset::toWire(OutputBuffer& buffer) const { unsigned int RRset::toWire(AbstractMessageRenderer& renderer) const { - unsigned int rrs_written; - - rrs_written = - rrsetToWire<AbstractMessageRenderer>(*this, renderer, - renderer.getLengthLimit()); + unsigned int rrs_written = BasicRRset::toWire(renderer); if (getRdataCount() > rrs_written) { - renderer.setTruncated(); return (rrs_written); } if (rrsig_) { - rrs_written += - rrsetToWire<AbstractMessageRenderer>(*(rrsig_.get()), renderer, - renderer.getLengthLimit()); - } + rrs_written += rrsig_->toWire(renderer); - if (getRdataCount() + getRRsigDataCount() > rrs_written) { - renderer.setTruncated(); + if (getRdataCount() + getRRsigDataCount() > rrs_written) { + renderer.setTruncated(); + } } return (rrs_written); |