[svn] commit: r1201 - in /branches/jinmei-asio: ./ doc/ src/bin/auth/ src/lib/dns/ src/lib/dns/rdata/generic/ src/lib/dns/tests/
BIND 10 source code commits
bind10-changes at lists.isc.org
Mon Mar 8 10:50:18 UTC 2010
Author: jinmei
Date: Mon Mar 8 10:50:18 2010
New Revision: 1201
Log:
sync with trunk, mainly for truncation support
Modified:
branches/jinmei-asio/ (props changed)
branches/jinmei-asio/doc/Doxyfile
branches/jinmei-asio/src/bin/auth/auth_srv.cc
branches/jinmei-asio/src/bin/auth/auth_srv.h
branches/jinmei-asio/src/bin/auth/main.cc
branches/jinmei-asio/src/lib/dns/ (props changed)
branches/jinmei-asio/src/lib/dns/buffer.h
branches/jinmei-asio/src/lib/dns/message.cc
branches/jinmei-asio/src/lib/dns/messagerenderer.cc
branches/jinmei-asio/src/lib/dns/messagerenderer.h
branches/jinmei-asio/src/lib/dns/rdata/generic/rrsig_46.cc (props changed)
branches/jinmei-asio/src/lib/dns/rrset.cc
branches/jinmei-asio/src/lib/dns/tests/buffer_unittest.cc
Modified: branches/jinmei-asio/doc/Doxyfile
==============================================================================
--- branches/jinmei-asio/doc/Doxyfile (original)
+++ branches/jinmei-asio/doc/Doxyfile Mon Mar 8 10:50:18 2010
@@ -568,7 +568,7 @@
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
-INPUT = ../src/lib/cc/cpp ../src/lib/config/cpp ../src/lib/dns/cpp
+INPUT = ../src/lib/cc ../src/lib/config ../src/lib/dns ../src/lib/exceptions
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
Modified: branches/jinmei-asio/src/bin/auth/auth_srv.cc
==============================================================================
--- branches/jinmei-asio/src/bin/auth/auth_srv.cc (original)
+++ branches/jinmei-asio/src/bin/auth/auth_srv.cc Mon Mar 8 10:50:18 2010
@@ -87,10 +87,11 @@
int
AuthSrv::processMessage(InputBuffer& request_buffer,
Message& message,
- MessageRenderer& response_renderer)
+ MessageRenderer& response_renderer,
+ const bool udp_buffer)
{
try {
- message.fromWire(request_buffer);
+ message.fromWire(request_buffer);
} catch (...) {
cerr << "[AuthSrv] parse failed" << endl;
return (-1);
@@ -115,8 +116,11 @@
Query query(message, dnssec_ok);
impl_->data_sources.doQuery(query);
+ response_renderer.setLengthLimit(udp_buffer ? remote_bufsize : 65535);
message.toWire(response_renderer);
- cout << "sending a response:\n" << message.toText() << endl;
+ cout << "sending a response (" <<
+ boost::lexical_cast<string>(response_renderer.getLength())
+ << " bytes):\n" << message.toText() << endl;
return (0);
}
Modified: branches/jinmei-asio/src/bin/auth/auth_srv.h
==============================================================================
--- branches/jinmei-asio/src/bin/auth/auth_srv.h (original)
+++ branches/jinmei-asio/src/bin/auth/auth_srv.h Mon Mar 8 10:50:18 2010
@@ -47,7 +47,8 @@
//@}
int processMessage(isc::dns::InputBuffer& request_buffer,
isc::dns::Message& message,
- isc::dns::MessageRenderer& response_renderer);
+ isc::dns::MessageRenderer& response_renderer,
+ bool udp_buffer);
void serve(std::string zone_name);
void setDbFile(const std::string& db_file);
isc::data::ElementPtr updateConfig(isc::data::ElementPtr config);
Modified: branches/jinmei-asio/src/bin/auth/main.cc
==============================================================================
--- branches/jinmei-asio/src/bin/auth/main.cc (original)
+++ branches/jinmei-asio/src/bin/auth/main.cc Mon Mar 8 10:50:18 2010
@@ -127,7 +127,7 @@
if (!error) {
InputBuffer dnsbuffer(data_, bytes_transferred);
if (auth_server->processMessage(dnsbuffer, dns_message_,
- response_renderer_) == 0) {
+ response_renderer_, false) == 0) {
responselen_buffer_.writeUint16(response_buffer_.getLength());
async_write(socket_,
boost::asio::buffer(
@@ -231,7 +231,7 @@
dns_message_.clear(Message::PARSE);
response_renderer_.clear();
if (auth_server->processMessage(request_buffer, dns_message_,
- response_renderer_) == 0) {
+ response_renderer_, true) == 0) {
socket_.async_send_to(
boost::asio::buffer(response_buffer_.getData(),
response_buffer_.getLength()),
Modified: branches/jinmei-asio/src/lib/dns/buffer.h
==============================================================================
--- branches/jinmei-asio/src/lib/dns/buffer.h (original)
+++ branches/jinmei-asio/src/lib/dns/buffer.h Mon Mar 8 10:50:18 2010
@@ -306,7 +306,7 @@
/// exception class of \c InvalidBufferPosition will be thrown.
///
/// \param pos The position in the buffer to be returned.
- uint8_t operator[](size_t pos) const
+ const uint8_t& operator[](size_t pos) const
{
if (pos >= data_.size()) {
isc_throw(InvalidBufferPosition, "read at invalid position");
@@ -326,6 +326,14 @@
/// that is to be filled in later, e.g, by \ref writeUint16At().
/// \param len The length of the gap to be inserted in bytes.
void skip(size_t len) { data_.insert(data_.end(), len, 0); }
+ /// \brief TBD
+ void trim(size_t len)
+ {
+ if (len > data_.size()) {
+ isc_throw(OutOfRange, "trimming too large from output buffer");
+ }
+ data_.resize(data_.size() - len);
+ }
/// \brief Clear buffer content.
///
/// This method can be used to re-initialize and reuse the buffer without
Modified: branches/jinmei-asio/src/lib/dns/message.cc
==============================================================================
--- branches/jinmei-asio/src/lib/dns/message.cc (original)
+++ branches/jinmei-asio/src/lib/dns/message.cc Mon Mar 8 10:50:18 2010
@@ -386,17 +386,31 @@
template <typename T>
struct RenderSection
{
- RenderSection(MessageRenderer& renderer) :
- counter_(0), renderer_(renderer) {}
+ RenderSection(MessageRenderer& renderer, const bool partial_ok) :
+ counter_(0), renderer_(renderer), partial_ok_(partial_ok),
+ truncated_(false)
+ {}
void operator()(const T& entry)
{
- // TBD: if truncation is necessary, do something special.
- // throw an exception, set an internal flag, etc.
+ // If it's already truncated, ignore the rest of the section.
+ if (truncated_) {
+ return;
+ }
+ size_t pos0 = renderer_.getLength();
counter_ += entry->toWire(renderer_);
+ if (renderer_.isTruncated()) {
+ truncated_ = true;
+ if (!partial_ok_) {
+ // roll back to the end of the previous RRset.
+ renderer_.trim(renderer_.getLength() - pos0);
+ }
+ }
}
unsigned int getTotalCount() { return (counter_); }
unsigned int counter_;
MessageRenderer& renderer_;
+ const bool partial_ok_;
+ bool truncated_;
};
}
@@ -421,6 +435,13 @@
return (false);
}
+ // If adding the OPT RR would exceed the size limit, don't do it.
+ // 11 = len(".") + type(2byte) + class(2byte) + TTL(4byte) + RDLEN(2byte)
+ // (RDATA is empty in this simple implementation)
+ if (renderer.getLength() + 11 > renderer.getLengthLimit()) {
+ return (false);
+ }
+
// Render EDNS OPT RR
uint32_t extrcode_flags = ((mimpl->rcode_.getCode() & 0xff0) << 24);
if (mimpl->dnssec_ok_) {
@@ -446,31 +467,41 @@
// reserve room for the header
renderer.skip(HEADERLEN);
+ uint16_t ancount = 0, nscount = 0, arcount = 0;
+
uint16_t qdcount =
for_each(impl_->questions_.begin(), impl_->questions_.end(),
- RenderSection<QuestionPtr>(renderer)).getTotalCount();
+ RenderSection<QuestionPtr>(renderer, false)).getTotalCount();
// TBD: sort RRsets in each section based on configuration policy.
- uint16_t ancount =
- for_each(impl_->rrsets_[sectionCodeToId(Section::ANSWER())].begin(),
- impl_->rrsets_[sectionCodeToId(Section::ANSWER())].end(),
- RenderSection<RRsetPtr>(renderer)).getTotalCount();
- uint16_t nscount =
- for_each(impl_->rrsets_[sectionCodeToId(Section::AUTHORITY())].begin(),
- impl_->rrsets_[sectionCodeToId(Section::AUTHORITY())].end(),
- RenderSection<RRsetPtr>(renderer)).getTotalCount();
- uint16_t arcount =
- for_each(impl_->rrsets_[sectionCodeToId(Section::ADDITIONAL())].begin(),
- impl_->rrsets_[sectionCodeToId(Section::ADDITIONAL())].end(),
- RenderSection<RRsetPtr>(renderer)).getTotalCount();
+ if (!renderer.isTruncated()) {
+ ancount =
+ for_each(impl_->rrsets_[sectionCodeToId(Section::ANSWER())].begin(),
+ impl_->rrsets_[sectionCodeToId(Section::ANSWER())].end(),
+ RenderSection<RRsetPtr>(renderer, true)).getTotalCount();
+ }
+ if (!renderer.isTruncated()) {
+ nscount =
+ for_each(impl_->rrsets_[sectionCodeToId(Section::AUTHORITY())].begin(),
+ impl_->rrsets_[sectionCodeToId(Section::AUTHORITY())].end(),
+ RenderSection<RRsetPtr>(renderer, true)).getTotalCount();
+ }
+ if (renderer.isTruncated()) {
+ setHeaderFlag(MessageFlag::TC());
+ } else {
+ arcount =
+ for_each(impl_->rrsets_[sectionCodeToId(Section::ADDITIONAL())].begin(),
+ impl_->rrsets_[sectionCodeToId(Section::ADDITIONAL())].end(),
+ RenderSection<RRsetPtr>(renderer, false)).getTotalCount();
+ }
// Added EDNS OPT RR if necessary (we want to avoid hardcoding specialized
// logic, see the parser case)
- if (addEDNS(this->impl_, renderer)) {
+ if (!renderer.isTruncated() && addEDNS(this->impl_, renderer)) {
++arcount;
}
- // TBD: EDNS, TSIG, etc.
+ // TBD: TSIG, SIG(0) etc.
// fill in the header
size_t header_pos = 0;
Modified: branches/jinmei-asio/src/lib/dns/messagerenderer.cc
==============================================================================
--- branches/jinmei-asio/src/lib/dns/messagerenderer.cc (original)
+++ branches/jinmei-asio/src/lib/dns/messagerenderer.cc Mon Mar 8 10:50:18 2010
@@ -135,7 +135,9 @@
/// \param buffer An \c OutputBuffer object to which wire format data is
/// written.
MessageRendererImpl(OutputBuffer& buffer) :
- buffer_(buffer), nbuffer_(Name::MAX_WIRE) {}
+ buffer_(buffer), nbuffer_(Name::MAX_WIRE), msglength_limit_(512),
+ truncated_(false)
+ {}
/// The buffer that holds the entire DNS message.
OutputBuffer& buffer_;
/// A local working buffer to convert each given name into wire format.
@@ -145,6 +147,10 @@
OutputBuffer nbuffer_;
/// A set of compression pointers.
std::set<NameCompressNode, NameCompare> nodeset_;
+
+ /// TBD
+ uint16_t msglength_limit_;
+ bool truncated_;
};
MessageRenderer::MessageRenderer(OutputBuffer& buffer) :
@@ -163,6 +169,12 @@
}
void
+MessageRenderer::trim(size_t len)
+{
+ impl_->buffer_.trim(len);
+}
+
+void
MessageRenderer::clear()
{
impl_->buffer_.clear();
@@ -210,6 +222,30 @@
MessageRenderer::getLength() const
{
return (impl_->buffer_.getLength());
+}
+
+size_t
+MessageRenderer::getLengthLimit() const
+{
+ return (impl_->msglength_limit_);
+}
+
+void
+MessageRenderer::setLengthLimit(size_t len)
+{
+ impl_->msglength_limit_ = len;
+}
+
+bool
+MessageRenderer::isTruncated() const
+{
+ return (impl_->truncated_);
+}
+
+void
+MessageRenderer::setTruncated()
+{
+ impl_->truncated_ = true;
}
void
Modified: branches/jinmei-asio/src/lib/dns/messagerenderer.h
==============================================================================
--- branches/jinmei-asio/src/lib/dns/messagerenderer.h (original)
+++ branches/jinmei-asio/src/lib/dns/messagerenderer.h Mon Mar 8 10:50:18 2010
@@ -99,6 +99,23 @@
const void* getData() const;
/// \brief Return the length of data written in the internal buffer.
size_t getLength() const;
+
+ /// \brief TBD
+ bool isTruncated() const;
+
+ /// \brief TBD
+ size_t getLengthLimit() const;
+ //@}
+
+ ///
+ /// \name Setter Methods
+ ///
+ //@{
+ /// \brief TBD
+ void setLengthLimit(size_t len);
+
+ /// \brief TBD
+ void setTruncated();
//@}
///
@@ -113,6 +130,9 @@
///
/// \param len The length of the gap to be inserted in bytes.
void skip(size_t len);
+
+ /// \brief TBD
+ void trim(size_t len);
/// \brief Clear the internal buffer and other internal resources.
///
/// This method can be used to re-initialize and reuse the renderer
Modified: branches/jinmei-asio/src/lib/dns/rrset.cc
==============================================================================
--- branches/jinmei-asio/src/lib/dns/rrset.cc (original)
+++ branches/jinmei-asio/src/lib/dns/rrset.cc Mon Mar 8 10:50:18 2010
@@ -64,7 +64,7 @@
namespace {
template <typename T>
inline unsigned int
-rrsetToWire(const AbstractRRset& rrset, T& output)
+rrsetToWire(const AbstractRRset& rrset, T& output, const size_t limit)
{
unsigned int n = 0;
RdataIteratorPtr it = rrset.getRdataIterator();
@@ -77,16 +77,25 @@
// sort the set of Rdata based on rrset-order and sortlist, and possible
// other options. Details to be considered.
do {
+ const size_t pos0 = output.getLength();
+ assert(pos0 < 65536);
+
rrset.getName().toWire(output);
rrset.getType().toWire(output);
rrset.getClass().toWire(output);
rrset.getTTL().toWire(output);
- size_t pos = output.getLength();
+ const size_t pos = output.getLength();
output.skip(sizeof(uint16_t)); // leave the space for RDLENGTH
it->getCurrent().toWire(output);
output.writeUint16At(output.getLength() - pos - sizeof(uint16_t), pos);
+ if (limit > 0 && output.getLength() > limit) {
+ // truncation is needed
+ output.trim(output.getLength() - pos0);
+ return (n);
+ }
+
it->next();
++n;
} while (!it->isLast());
@@ -98,13 +107,18 @@
unsigned int
AbstractRRset::toWire(OutputBuffer& buffer) const
{
- return (rrsetToWire<OutputBuffer>(*this, buffer));
+ return (rrsetToWire<OutputBuffer>(*this, buffer, 0));
}
unsigned int
AbstractRRset::toWire(MessageRenderer& renderer) const
{
- return (rrsetToWire<MessageRenderer>(*this, renderer));
+ const unsigned int rrs_written = rrsetToWire<MessageRenderer>(
+ *this, renderer, renderer.getLengthLimit());
+ if (getRdataCount() > rrs_written) {
+ renderer.setTruncated();
+ }
+ return (rrs_written);
}
ostream&
Modified: branches/jinmei-asio/src/lib/dns/tests/buffer_unittest.cc
==============================================================================
--- branches/jinmei-asio/src/lib/dns/tests/buffer_unittest.cc (original)
+++ branches/jinmei-asio/src/lib/dns/tests/buffer_unittest.cc Mon Mar 8 10:50:18 2010
@@ -14,9 +14,13 @@
// $Id$
+#include <exceptions/exceptions.h>
+
#include <dns/buffer.h>
#include <gtest/gtest.h>
+
+using namespace isc;
namespace {
@@ -158,6 +162,20 @@
EXPECT_EQ(6, obuffer.getLength());
}
+TEST_F(BufferTest, outputBufferTrim)
+{
+ obuffer.writeData(testdata, sizeof(testdata));
+ EXPECT_EQ(5, obuffer.getLength());
+
+ obuffer.trim(1);
+ EXPECT_EQ(4, obuffer.getLength());
+
+ obuffer.trim(2);
+ EXPECT_EQ(2, obuffer.getLength());
+
+ EXPECT_THROW(obuffer.trim(3), OutOfRange);
+}
+
TEST_F(BufferTest, outputBufferReadat)
{
obuffer.writeData(testdata, sizeof(testdata));
More information about the bind10-changes
mailing list