Browse Source

[1144] Merge branch 'trac1144'

Dima Volodin 13 years ago
parent
commit
d267c0511a

+ 4 - 0
ChangeLog

@@ -1,3 +1,7 @@
+292.	[func]		dvv
+	Implement the DLV rrtype according to RFC4431.
+	(Trac #1144, git TBD)
+
 291.    [func]          naokikambe
 291.    [func]          naokikambe
 	Statistics items are specified by each module's spec file.
 	Statistics items are specified by each module's spec file.
 	Stats module can read these through the config manager. Stats
 	Stats module can read these through the config manager. Stats

+ 4 - 0
src/lib/dns/Makefile.am

@@ -24,6 +24,9 @@ EXTRA_DIST += rdata/generic/cname_5.h
 EXTRA_DIST += rdata/generic/detail/nsec_bitmap.cc
 EXTRA_DIST += rdata/generic/detail/nsec_bitmap.cc
 EXTRA_DIST += rdata/generic/detail/nsec_bitmap.h
 EXTRA_DIST += rdata/generic/detail/nsec_bitmap.h
 EXTRA_DIST += rdata/generic/detail/txt_like.h
 EXTRA_DIST += rdata/generic/detail/txt_like.h
+EXTRA_DIST += rdata/generic/detail/ds_like.h
+EXTRA_DIST += rdata/generic/dlv_32769.cc
+EXTRA_DIST += rdata/generic/dlv_32769.h
 EXTRA_DIST += rdata/generic/dname_39.cc
 EXTRA_DIST += rdata/generic/dname_39.cc
 EXTRA_DIST += rdata/generic/dname_39.h
 EXTRA_DIST += rdata/generic/dname_39.h
 EXTRA_DIST += rdata/generic/dnskey_48.cc
 EXTRA_DIST += rdata/generic/dnskey_48.cc
@@ -107,6 +110,7 @@ libdns___la_SOURCES += character_string.h character_string.cc
 libdns___la_SOURCES += rdata/generic/detail/nsec_bitmap.h
 libdns___la_SOURCES += rdata/generic/detail/nsec_bitmap.h
 libdns___la_SOURCES += rdata/generic/detail/nsec_bitmap.cc
 libdns___la_SOURCES += rdata/generic/detail/nsec_bitmap.cc
 libdns___la_SOURCES += rdata/generic/detail/txt_like.h
 libdns___la_SOURCES += rdata/generic/detail/txt_like.h
+libdns___la_SOURCES += rdata/generic/detail/ds_like.h
 
 
 libdns___la_CPPFLAGS = $(AM_CPPFLAGS)
 libdns___la_CPPFLAGS = $(AM_CPPFLAGS)
 # Most applications of libdns++ will only implicitly rely on libcryptolink,
 # Most applications of libdns++ will only implicitly rely on libcryptolink,

+ 225 - 0
src/lib/dns/rdata/generic/detail/ds_like.h

@@ -0,0 +1,225 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#ifndef __DS_LIKE_H
+#define __DS_LIKE_H 1
+
+#include <stdint.h>
+
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <boost/lexical_cast.hpp>
+
+#include <exceptions/exceptions.h>
+
+#include <dns/messagerenderer.h>
+#include <dns/name.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+namespace isc {
+namespace dns {
+namespace rdata {
+namespace generic {
+namespace detail {
+
+/// \brief \c rdata::DSLikeImpl class represents the DS-like RDATA for DS
+/// and DLV types.
+///
+/// This class implements the basic interfaces inherited by the DS and DLV
+/// classes from the abstract \c rdata::Rdata class, and provides trivial
+/// accessors to DS-like RDATA.
+template <class Type, uint16_t typeCode> class DSLikeImpl {
+    // Common sequence of toWire() operations used for the two versions of
+    // toWire().
+    template <typename Output>
+    void
+    toWireCommon(Output& output) const {
+        output.writeUint16(tag_);
+        output.writeUint8(algorithm_);
+        output.writeUint8(digest_type_);
+        output.writeData(&digest_[0], digest_.size());
+    }
+
+public:
+    /// \brief Constructor from string.
+    ///
+    /// <b>Exceptions</b>
+    ///
+    /// \c InvalidRdataText is thrown if the method cannot process the
+    /// parameter data for any of the number of reasons.
+    DSLikeImpl(const std::string& ds_str) {
+        std::istringstream iss(ds_str);
+        // peekc should be of iss's char_type for isspace to work
+        std::istringstream::char_type peekc;
+        std::stringbuf digestbuf;
+        uint32_t tag, algorithm, digest_type;
+
+        iss >> tag >> algorithm >> digest_type;
+        if (iss.bad() || iss.fail()) {
+            isc_throw(InvalidRdataText,
+                      "Invalid " << RRType(typeCode) << " text");
+        }
+        if (tag > 0xffff) {
+            isc_throw(InvalidRdataText,
+                      RRType(typeCode) << " tag out of range");
+        }
+        if (algorithm > 0xff) {
+            isc_throw(InvalidRdataText,
+                      RRType(typeCode) << " algorithm out of range");
+        }
+        if (digest_type > 0xff) {
+            isc_throw(InvalidRdataText,
+                      RRType(typeCode) << " digest type out of range");
+        }
+
+        iss.read(&peekc, 1);
+        if (!iss.good() || !isspace(peekc, iss.getloc())) {
+            isc_throw(InvalidRdataText,
+                      RRType(typeCode) << " presentation format error");
+        }
+
+        iss >> &digestbuf;
+
+        tag_ = tag;
+        algorithm_ = algorithm;
+        digest_type_ = digest_type;
+        decodeHex(digestbuf.str(), digest_);
+    }
+
+    /// \brief Constructor from wire-format data.
+    ///
+    /// \param buffer A buffer storing the wire format data.
+    /// \param rdata_len The length of the RDATA in bytes, normally expected
+    /// to be the value of the RDLENGTH field of the corresponding RR.
+    ///
+    /// <b>Exceptions</b>
+    ///
+    /// \c InvalidRdataLength is thrown if the input data is too short for the
+    /// type.
+    DSLikeImpl(InputBuffer& buffer, size_t rdata_len) {
+        if (rdata_len < 4) {
+            isc_throw(InvalidRdataLength, RRType(typeCode) << " too short");
+        }
+
+        tag_ = buffer.readUint16();
+        algorithm_ = buffer.readUint8();
+        digest_type_ = buffer.readUint8();
+
+        rdata_len -= 4;
+        digest_.resize(rdata_len);
+        buffer.readData(&digest_[0], rdata_len);
+    }
+
+    /// \brief The copy constructor.
+    ///
+    /// Trivial for now, we could've used the default one.
+    DSLikeImpl(const DSLikeImpl& source) {
+        digest_ = source.digest_;
+        tag_ = source.tag_;
+        algorithm_ = source.algorithm_;
+        digest_type_ = source.digest_type_;
+    }
+
+    /// \brief Convert the DS-like data to a string.
+    ///
+    /// \return A \c string object that represents the DS-like data.
+    std::string
+    toText() const {
+        using namespace boost;
+        return (lexical_cast<string>(static_cast<int>(tag_)) +
+            " " + lexical_cast<string>(static_cast<int>(algorithm_)) +
+            " " + lexical_cast<string>(static_cast<int>(digest_type_)) +
+            " " + encodeHex(digest_));
+    }
+
+    /// \brief Render the DS-like data in the wire format to an OutputBuffer
+    /// object.
+    ///
+    /// \param buffer An output buffer to store the wire data.
+    void
+    toWire(OutputBuffer& buffer) const {
+        toWireCommon(buffer);
+    }
+
+    /// \brief Render the DS-like data in the wire format to an
+    /// AbstractMessageRenderer object.
+    ///
+    /// \param renderer A renderer object to send the wire data to.
+    void
+    toWire(AbstractMessageRenderer& renderer) const {
+        toWireCommon(renderer);
+    }
+
+    /// \brief Compare two instances of DS-like RDATA.
+    ///
+    /// It is up to the caller to make sure that \c other is an object of the
+    /// same \c DSLikeImpl class.
+    ///
+    /// \param other the right-hand operand to compare against.
+    /// \return < 0 if \c this would be sorted before \c other.
+    /// \return 0 if \c this is identical to \c other in terms of sorting
+    /// order.
+    /// \return > 0 if \c this would be sorted after \c other.
+    int
+    compare(const DSLikeImpl& other_ds) const {
+        if (tag_ != other_ds.tag_) {
+            return (tag_ < other_ds.tag_ ? -1 : 1);
+        }
+        if (algorithm_ != other_ds.algorithm_) {
+            return (algorithm_ < other_ds.algorithm_ ? -1 : 1);
+        }
+        if (digest_type_ != other_ds.digest_type_) {
+            return (digest_type_ < other_ds.digest_type_ ? -1 : 1);
+        }
+
+        size_t this_len = digest_.size();
+        size_t other_len = other_ds.digest_.size();
+        size_t cmplen = min(this_len, other_len);
+        int cmp = memcmp(&digest_[0], &other_ds.digest_[0], cmplen);
+        if (cmp != 0) {
+            return (cmp);
+        } else {
+            return ((this_len == other_len)
+                    ? 0 : (this_len < other_len) ? -1 : 1);
+        }
+    }
+
+    /// \brief Accessors
+    uint16_t
+    getTag() const {
+        return (tag_);
+    }
+
+private:
+    // straightforward representation of DS RDATA fields
+    uint16_t tag_;
+    uint8_t algorithm_;
+    uint8_t digest_type_;
+    std::vector<uint8_t> digest_;
+};
+
+}
+}
+}
+}
+}
+#endif //  __DS_LIKE_H
+
+// Local Variables: 
+// mode: c++
+// End: 

+ 121 - 0
src/lib/dns/rdata/generic/dlv_32769.cc

@@ -0,0 +1,121 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <string>
+
+#include <util/buffer.h>
+#include <util/encode/hex.h>
+
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+
+#include <dns/rdata/generic/detail/ds_like.h>
+
+using namespace std;
+using namespace isc::util;
+using namespace isc::util::encode;
+using namespace isc::dns::rdata::generic::detail;
+
+// BEGIN_ISC_NAMESPACE
+// BEGIN_RDATA_NAMESPACE
+
+/// \brief Constructor from string.
+///
+/// A copy of the implementation object is allocated and constructed.
+DLV::DLV(const string& ds_str) :
+    impl_(new DLVImpl(ds_str))
+{}
+
+/// \brief Constructor from wire-format data.
+///
+/// A copy of the implementation object is allocated and constructed.
+DLV::DLV(InputBuffer& buffer, size_t rdata_len) :
+    impl_(new DLVImpl(buffer, rdata_len))
+{}
+
+/// \brief Copy constructor
+///
+/// A copy of the implementation object is allocated and constructed.
+DLV::DLV(const DLV& source) :
+    Rdata(), impl_(new DLVImpl(*source.impl_))
+{}
+
+/// \brief Assignment operator
+///
+/// PIMPL-induced logic
+DLV&
+DLV::operator=(const DLV& source) {
+    if (impl_ == source.impl_) {
+        return (*this);
+    }
+
+    DLVImpl* newimpl = new DLVImpl(*source.impl_);
+    delete impl_;
+    impl_ = newimpl;
+
+    return (*this);
+}
+
+/// \brief Destructor
+///
+/// Deallocates an internal resource.
+DLV::~DLV() {
+    delete impl_;
+}
+
+/// \brief Convert the \c DLV to a string.
+///
+/// A pass-thru to the corresponding implementation method.
+string
+DLV::toText() const {
+    return (impl_->toText());
+}
+
+/// \brief Render the \c DLV in the wire format to a OutputBuffer object
+///
+/// A pass-thru to the corresponding implementation method.
+void
+DLV::toWire(OutputBuffer& buffer) const {
+    impl_->toWire(buffer);
+}
+
+/// \brief Render the \c DLV in the wire format to a AbstractMessageRenderer
+/// object
+///
+/// A pass-thru to the corresponding implementation method.
+void
+DLV::toWire(AbstractMessageRenderer& renderer) const {
+    impl_->toWire(renderer);
+}
+
+/// \brief Compare two instances of \c DLV RDATA.
+///
+/// The type check is performed here. Otherwise, a pass-thru to the
+/// corresponding implementation method.
+int
+DLV::compare(const Rdata& other) const {
+    const DLV& other_ds = dynamic_cast<const DLV&>(other);
+
+    return (impl_->compare(*other_ds.impl_));
+}
+
+/// \brief Tag accessor
+uint16_t
+DLV::getTag() const {
+    return (impl_->getTag());
+}
+
+// END_RDATA_NAMESPACE
+// END_ISC_NAMESPACE

+ 77 - 0
src/lib/dns/rdata/generic/dlv_32769.h

@@ -0,0 +1,77 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+// BEGIN_HEADER_GUARD
+
+#include <stdint.h>
+
+#include <string>
+
+#include <dns/name.h>
+#include <dns/rrtype.h>
+#include <dns/rrttl.h>
+#include <dns/rdata.h>
+
+// BEGIN_ISC_NAMESPACE
+
+// BEGIN_COMMON_DECLARATIONS
+// END_COMMON_DECLARATIONS
+
+// BEGIN_RDATA_NAMESPACE
+
+namespace detail {
+template <class Type, uint16_t typeCode> class DSLikeImpl;
+}
+
+/// \brief \c rdata::generic::DLV class represents the DLV RDATA as defined in
+/// RFC4431.
+///
+/// This class implements the basic interfaces inherited from the abstract
+/// \c rdata::Rdata class, and provides trivial accessors specific to the
+/// DLV RDATA.
+class DLV : public Rdata {
+public:
+    // BEGIN_COMMON_MEMBERS
+    // END_COMMON_MEMBERS
+
+    /// \brief Assignment operator.
+    ///
+    /// It internally allocates a resource, and if it fails a corresponding
+    /// standard exception will be thrown.
+    /// This operator never throws an exception otherwise.
+    ///
+    /// This operator provides the strong exception guarantee: When an
+    /// exception is thrown the content of the assignment target will be
+    /// intact.
+    DLV& operator=(const DLV& source);
+
+    /// \brief The destructor.
+    ~DLV();
+
+    /// \brief Return the value of the Tag field.
+    ///
+    /// This method never throws an exception.
+    uint16_t getTag() const;
+private:
+    typedef detail::DSLikeImpl<DLV, 32769> DLVImpl;
+    DLVImpl* impl_;
+};
+
+// END_RDATA_NAMESPACE
+// END_ISC_NAMESPACE
+// END_HEADER_GUARD
+
+// Local Variables: 
+// mode: c++
+// End: 

+ 13 - 96
src/lib/dns/rdata/generic/ds_43.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
 //
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
 // purpose with or without fee is hereby granted, provided that the above
@@ -12,87 +12,32 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 // PERFORMANCE OF THIS SOFTWARE.
 
 
-#include <iostream>
 #include <string>
 #include <string>
-#include <sstream>
-#include <vector>
-
-#include <boost/lexical_cast.hpp>
 
 
 #include <util/buffer.h>
 #include <util/buffer.h>
 #include <util/encode/hex.h>
 #include <util/encode/hex.h>
 
 
 #include <dns/messagerenderer.h>
 #include <dns/messagerenderer.h>
-#include <dns/name.h>
 #include <dns/rdata.h>
 #include <dns/rdata.h>
 #include <dns/rdataclass.h>
 #include <dns/rdataclass.h>
 
 
-#include <stdio.h>
+#include <dns/rdata/generic/detail/ds_like.h>
-#include <time.h>
 
 
 using namespace std;
 using namespace std;
 using namespace isc::util;
 using namespace isc::util;
 using namespace isc::util::encode;
 using namespace isc::util::encode;
+using namespace isc::dns::rdata::generic::detail;
 
 
 // BEGIN_ISC_NAMESPACE
 // BEGIN_ISC_NAMESPACE
 // BEGIN_RDATA_NAMESPACE
 // BEGIN_RDATA_NAMESPACE
 
 
-struct DSImpl {
-    // straightforward representation of DS RDATA fields
-    DSImpl(uint16_t tag, uint8_t algorithm, uint8_t digest_type,
-           const vector<uint8_t>& digest) :
-        tag_(tag), algorithm_(algorithm), digest_type_(digest_type),
-        digest_(digest)
-    {}
-
-    uint16_t tag_;
-    uint8_t algorithm_;
-    uint8_t digest_type_;
-    const vector<uint8_t> digest_;
-};
-
 DS::DS(const string& ds_str) :
 DS::DS(const string& ds_str) :
-    impl_(NULL)
+    impl_(new DSImpl(ds_str))
-{
+{}
-    istringstream iss(ds_str);
-    unsigned int tag, algorithm, digest_type;
-    stringbuf digestbuf;
-
-    iss >> tag >> algorithm >> digest_type >> &digestbuf;
-    if (iss.bad() || iss.fail()) {
-        isc_throw(InvalidRdataText, "Invalid DS text");
-    }
-    if (tag > 0xffff) {
-        isc_throw(InvalidRdataText, "DS tag out of range");
-    }
-    if (algorithm > 0xff) {
-        isc_throw(InvalidRdataText, "DS algorithm out of range");
-    }
-    if (digest_type > 0xff) {
-        isc_throw(InvalidRdataText, "DS digest type out of range");
-    }
-
-    vector<uint8_t> digest;
-    decodeHex(digestbuf.str(), digest);
-
-    impl_ = new DSImpl(tag, algorithm, digest_type, digest);
-}
-
-DS::DS(InputBuffer& buffer, size_t rdata_len) {
-    if (rdata_len < 4) {
-        isc_throw(InvalidRdataLength, "DS too short");
-    }
-
-    uint16_t tag = buffer.readUint16();
-    uint16_t algorithm = buffer.readUint8();
-    uint16_t digest_type = buffer.readUint8();
-
-    rdata_len -= 4;
-    vector<uint8_t> digest(rdata_len);
-    buffer.readData(&digest[0], rdata_len);
 
 
-    impl_ = new DSImpl(tag, algorithm, digest_type, digest);
+DS::DS(InputBuffer& buffer, size_t rdata_len) :
-}
+    impl_(new DSImpl(buffer, rdata_len))
+{}
 
 
 DS::DS(const DS& source) :
 DS::DS(const DS& source) :
     Rdata(), impl_(new DSImpl(*source.impl_))
     Rdata(), impl_(new DSImpl(*source.impl_))
@@ -117,57 +62,29 @@ DS::~DS() {
 
 
 string
 string
 DS::toText() const {
 DS::toText() const {
-    using namespace boost;
+    return (impl_->toText());
-    return (lexical_cast<string>(static_cast<int>(impl_->tag_)) +
-        " " + lexical_cast<string>(static_cast<int>(impl_->algorithm_)) +
-        " " + lexical_cast<string>(static_cast<int>(impl_->digest_type_)) +
-        " " + encodeHex(impl_->digest_));
 }
 }
 
 
 void
 void
 DS::toWire(OutputBuffer& buffer) const {
 DS::toWire(OutputBuffer& buffer) const {
-    buffer.writeUint16(impl_->tag_);
+    impl_->toWire(buffer);
-    buffer.writeUint8(impl_->algorithm_);
-    buffer.writeUint8(impl_->digest_type_);
-    buffer.writeData(&impl_->digest_[0], impl_->digest_.size());
 }
 }
 
 
 void
 void
 DS::toWire(AbstractMessageRenderer& renderer) const {
 DS::toWire(AbstractMessageRenderer& renderer) const {
-    renderer.writeUint16(impl_->tag_);
+    impl_->toWire(renderer);
-    renderer.writeUint8(impl_->algorithm_);
-    renderer.writeUint8(impl_->digest_type_);
-    renderer.writeData(&impl_->digest_[0], impl_->digest_.size());
 }
 }
 
 
 int
 int
 DS::compare(const Rdata& other) const {
 DS::compare(const Rdata& other) const {
     const DS& other_ds = dynamic_cast<const DS&>(other);
     const DS& other_ds = dynamic_cast<const DS&>(other);
 
 
-    if (impl_->tag_ != other_ds.impl_->tag_) {
+    return (impl_->compare(*other_ds.impl_));
-        return (impl_->tag_ < other_ds.impl_->tag_ ? -1 : 1);
-    }
-    if (impl_->algorithm_ != other_ds.impl_->algorithm_) {
-        return (impl_->algorithm_ < other_ds.impl_->algorithm_ ? -1 : 1);
-    }
-    if (impl_->digest_type_ != other_ds.impl_->digest_type_) {
-        return (impl_->digest_type_ < other_ds.impl_->digest_type_ ? -1 : 1);
-    }
-
-    size_t this_len = impl_->digest_.size();
-    size_t other_len = other_ds.impl_->digest_.size();
-    size_t cmplen = min(this_len, other_len);
-    int cmp = memcmp(&impl_->digest_[0], &other_ds.impl_->digest_[0], cmplen);
-    if (cmp != 0) {
-        return (cmp);
-    } else {
-        return ((this_len == other_len) ? 0 : (this_len < other_len) ? -1 : 1);
-    }
 }
 }
 
 
 uint16_t
 uint16_t
 DS::getTag() const {
 DS::getTag() const {
-    return (impl_->tag_);
+    return (impl_->getTag());
 }
 }
 
 
 // END_RDATA_NAMESPACE
 // END_RDATA_NAMESPACE

+ 27 - 6
src/lib/dns/rdata/generic/ds_43.h

@@ -1,4 +1,4 @@
-// Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
 //
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
 // purpose with or without fee is hereby granted, provided that the above
@@ -12,6 +12,8 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 // PERFORMANCE OF THIS SOFTWARE.
 
 
+// BEGIN_HEADER_GUARD
+
 #include <stdint.h>
 #include <stdint.h>
 
 
 #include <string>
 #include <string>
@@ -21,8 +23,6 @@
 #include <dns/rrttl.h>
 #include <dns/rrttl.h>
 #include <dns/rdata.h>
 #include <dns/rdata.h>
 
 
-// BEGIN_HEADER_GUARD
-
 // BEGIN_ISC_NAMESPACE
 // BEGIN_ISC_NAMESPACE
 
 
 // BEGIN_COMMON_DECLARATIONS
 // BEGIN_COMMON_DECLARATIONS
@@ -30,20 +30,41 @@
 
 
 // BEGIN_RDATA_NAMESPACE
 // BEGIN_RDATA_NAMESPACE
 
 
-struct DSImpl;
+namespace detail {
+template <class Type, uint16_t typeCode> class DSLikeImpl;
+}
 
 
+/// \brief \c rdata::generic::DS class represents the DS RDATA as defined in
+/// RFC3658.
+///
+/// This class implements the basic interfaces inherited from the abstract
+/// \c rdata::Rdata class, and provides trivial accessors specific to the
+/// DS RDATA.
 class DS : public Rdata {
 class DS : public Rdata {
 public:
 public:
     // BEGIN_COMMON_MEMBERS
     // BEGIN_COMMON_MEMBERS
     // END_COMMON_MEMBERS
     // END_COMMON_MEMBERS
+
+    /// \brief Assignment operator.
+    ///
+    /// It internally allocates a resource, and if it fails a corresponding
+    /// standard exception will be thrown.
+    /// This operator never throws an exception otherwise.
+    ///
+    /// This operator provides the strong exception guarantee: When an
+    /// exception is thrown the content of the assignment target will be
+    /// intact.
     DS& operator=(const DS& source);
     DS& operator=(const DS& source);
+
+    /// \brief The destructor.
     ~DS();
     ~DS();
 
 
+    /// \brief Return the value of the Tag field.
     ///
     ///
-    /// Specialized methods
+    /// This method never throws an exception.
-    ///
     uint16_t getTag() const;
     uint16_t getTag() const;
 private:
 private:
+    typedef detail::DSLikeImpl<DS, 43> DSImpl;
     DSImpl* impl_;
     DSImpl* impl_;
 };
 };
 
 

+ 1 - 1
src/lib/dns/tests/Makefile.am

@@ -35,7 +35,7 @@ run_unittests_SOURCES += rdata_dname_unittest.cc
 run_unittests_SOURCES += rdata_afsdb_unittest.cc
 run_unittests_SOURCES += rdata_afsdb_unittest.cc
 run_unittests_SOURCES += rdata_opt_unittest.cc
 run_unittests_SOURCES += rdata_opt_unittest.cc
 run_unittests_SOURCES += rdata_dnskey_unittest.cc
 run_unittests_SOURCES += rdata_dnskey_unittest.cc
-run_unittests_SOURCES += rdata_ds_unittest.cc
+run_unittests_SOURCES += rdata_ds_like_unittest.cc
 run_unittests_SOURCES += rdata_nsec_unittest.cc
 run_unittests_SOURCES += rdata_nsec_unittest.cc
 run_unittests_SOURCES += rdata_nsec3_unittest.cc
 run_unittests_SOURCES += rdata_nsec3_unittest.cc
 run_unittests_SOURCES += rdata_nsecbitmap_unittest.cc
 run_unittests_SOURCES += rdata_nsecbitmap_unittest.cc

+ 171 - 0
src/lib/dns/tests/rdata_ds_like_unittest.cc

@@ -0,0 +1,171 @@
+// Copyright (C) 2011  Internet Systems Consortium, Inc. ("ISC")
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+#include <algorithm>
+#include <string>
+
+#include <util/buffer.h>
+#include <dns/messagerenderer.h>
+#include <dns/rdata.h>
+#include <dns/rdataclass.h>
+#include <dns/rrclass.h>
+#include <dns/rrtype.h>
+
+#include <gtest/gtest.h>
+
+#include <dns/tests/unittest_util.h>
+#include <dns/tests/rdata_unittest.h>
+
+using isc::UnitTestUtil;
+using namespace std;
+using namespace isc::dns;
+using namespace isc::util;
+using namespace isc::dns::rdata;
+
+namespace {
+// hacks to make templates work
+template <class T>
+class RRTYPE : public RRType {
+public:
+    RRTYPE();
+};
+
+template<> RRTYPE<generic::DS>::RRTYPE() : RRType(RRType::DS()) {}
+template<> RRTYPE<generic::DLV>::RRTYPE() : RRType(RRType::DLV()) {}
+
+template <class DS_LIKE>
+class Rdata_DS_LIKE_Test : public RdataTest {
+protected:
+    static DS_LIKE const rdata_ds_like;
+};
+
+string ds_like_txt("12892 5 2 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D"
+                   "5F0EB5C777586DE18DA6B5");
+
+template <class DS_LIKE>
+DS_LIKE const Rdata_DS_LIKE_Test<DS_LIKE>::rdata_ds_like(ds_like_txt);
+
+// The list of types we want to test.
+typedef testing::Types<generic::DS, generic::DLV> Implementations;
+
+TYPED_TEST_CASE(Rdata_DS_LIKE_Test, Implementations);
+
+TYPED_TEST(Rdata_DS_LIKE_Test, toText_DS_LIKE) {
+    EXPECT_EQ(ds_like_txt, this->rdata_ds_like.toText());
+}
+
+TYPED_TEST(Rdata_DS_LIKE_Test, badText_DS_LIKE) {
+    EXPECT_THROW(const TypeParam ds_like2("99999 5 2 BEEF"), InvalidRdataText);
+    EXPECT_THROW(const TypeParam ds_like2("11111 555 2 BEEF"),
+                 InvalidRdataText);
+    EXPECT_THROW(const TypeParam ds_like2("11111 5 22222 BEEF"),
+                 InvalidRdataText);
+    EXPECT_THROW(const TypeParam ds_like2("11111 5 2"), InvalidRdataText);
+    EXPECT_THROW(const TypeParam ds_like2("GARBAGE IN"), InvalidRdataText);
+    // no space between the digest type and the digest.
+    EXPECT_THROW(const TypeParam ds_like2(
+                     "12892 5 2F1E184C0E1D615D20EB3C223ACED3B03C773DD952D"
+                     "5F0EB5C777586DE18DA6B5"), InvalidRdataText);
+}
+
+TYPED_TEST(Rdata_DS_LIKE_Test, createFromWire_DS_LIKE) {
+    EXPECT_EQ(0, this->rdata_ds_like.compare(
+              *this->rdataFactoryFromFile(RRTYPE<TypeParam>(), RRClass::IN(),
+                                          "rdata_ds_fromWire")));
+}
+
+TYPED_TEST(Rdata_DS_LIKE_Test, assignment_DS_LIKE) {
+    TypeParam copy((string(ds_like_txt)));
+    copy = this->rdata_ds_like;
+    EXPECT_EQ(0, copy.compare(this->rdata_ds_like));
+
+    // Check if the copied data is valid even after the original is deleted
+    TypeParam* copy2 = new TypeParam(this->rdata_ds_like);
+    TypeParam copy3((string(ds_like_txt)));
+    copy3 = *copy2;
+    delete copy2;
+    EXPECT_EQ(0, copy3.compare(this->rdata_ds_like));
+
+    // Self assignment
+    copy = copy;
+    EXPECT_EQ(0, copy.compare(this->rdata_ds_like));
+}
+
+TYPED_TEST(Rdata_DS_LIKE_Test, getTag_DS_LIKE) {
+    EXPECT_EQ(12892, this->rdata_ds_like.getTag());
+}
+
+TYPED_TEST(Rdata_DS_LIKE_Test, toWireRenderer) {
+    Rdata_DS_LIKE_Test<TypeParam>::renderer.skip(2);
+    TypeParam rdata_ds_like(ds_like_txt);
+    rdata_ds_like.toWire(this->renderer);
+
+    vector<unsigned char> data;
+    UnitTestUtil::readWireData("rdata_ds_fromWire", data);
+    EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
+                        static_cast<const uint8_t*>
+                        (this->obuffer.getData()) + 2,
+                        this->obuffer.getLength() - 2,
+                        &data[2], data.size() - 2);
+}
+
+TYPED_TEST(Rdata_DS_LIKE_Test, toWireBuffer) {
+    TypeParam rdata_ds_like(ds_like_txt);
+    rdata_ds_like.toWire(this->obuffer);
+}
+
+string ds_like_txt1("12892 5 2 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D"
+                   "5F0EB5C777586DE18DA6B5");
+// different tag
+string ds_like_txt2("12893 5 2 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D"
+                   "5F0EB5C777586DE18DA6B5");
+// different algorithm
+string ds_like_txt3("12892 6 2 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D"
+                   "5F0EB5C777586DE18DA6B5");
+// different digest type
+string ds_like_txt4("12892 5 3 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D"
+                   "5F0EB5C777586DE18DA6B5");
+// different digest
+string ds_like_txt5("12892 5 2 F2E184C0E1D615D20EB3C223ACED3B03C773DD952D"
+                   "5F0EB5C777586DE18DA6B5");
+// different digest length
+string ds_like_txt6("12892 5 2 F2E184C0E1D615D20EB3C223ACED3B03C773DD952D"
+                   "5F0EB5C777586DE18DA6B555");
+
+TYPED_TEST(Rdata_DS_LIKE_Test, compare) {
+    // trivial case: self equivalence
+    EXPECT_EQ(0, TypeParam(ds_like_txt).compare(TypeParam(ds_like_txt)));
+
+    // non-equivalence tests
+    EXPECT_LT(TypeParam(ds_like_txt1).compare(TypeParam(ds_like_txt2)), 0);
+    EXPECT_GT(TypeParam(ds_like_txt2).compare(TypeParam(ds_like_txt1)), 0);
+
+    EXPECT_LT(TypeParam(ds_like_txt1).compare(TypeParam(ds_like_txt3)), 0);
+    EXPECT_GT(TypeParam(ds_like_txt3).compare(TypeParam(ds_like_txt1)), 0);
+
+    EXPECT_LT(TypeParam(ds_like_txt1).compare(TypeParam(ds_like_txt4)), 0);
+    EXPECT_GT(TypeParam(ds_like_txt4).compare(TypeParam(ds_like_txt1)), 0);
+
+    EXPECT_LT(TypeParam(ds_like_txt1).compare(TypeParam(ds_like_txt5)), 0);
+    EXPECT_GT(TypeParam(ds_like_txt5).compare(TypeParam(ds_like_txt1)), 0);
+
+    EXPECT_LT(TypeParam(ds_like_txt1).compare(TypeParam(ds_like_txt6)), 0);
+    EXPECT_GT(TypeParam(ds_like_txt6).compare(TypeParam(ds_like_txt1)), 0);
+
+    // comparison attempt between incompatible RR types should be rejected
+    EXPECT_THROW(this->rdata_ds_like.compare(*RdataTest::rdata_nomatch),
+                 bad_cast);
+}
+
+}

+ 0 - 99
src/lib/dns/tests/rdata_ds_unittest.cc

@@ -1,99 +0,0 @@
-// Copyright (C) 2010  Internet Systems Consortium, Inc. ("ISC")
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
-// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
-// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-// PERFORMANCE OF THIS SOFTWARE.
-
-#include <string>
-
-#include <util/buffer.h>
-#include <dns/messagerenderer.h>
-#include <dns/rdata.h>
-#include <dns/rdataclass.h>
-#include <dns/rrclass.h>
-#include <dns/rrtype.h>
-
-#include <gtest/gtest.h>
-
-#include <dns/tests/unittest_util.h>
-#include <dns/tests/rdata_unittest.h>
-
-using isc::UnitTestUtil;
-using namespace std;
-using namespace isc::dns;
-using namespace isc::util;
-using namespace isc::dns::rdata;
-
-namespace {
-class Rdata_DS_Test : public RdataTest {
-    // there's nothing to specialize
-};
-
-string ds_txt("12892 5 2 F1E184C0E1D615D20EB3C223ACED3B03C773DD952D"
-              "5F0EB5C777586DE18DA6B5");
-const generic::DS rdata_ds(ds_txt);
-
-TEST_F(Rdata_DS_Test, toText_DS) {
-    EXPECT_EQ(ds_txt, rdata_ds.toText());
-}
-
-TEST_F(Rdata_DS_Test, badText_DS) {
-    EXPECT_THROW(const generic::DS ds2("99999 5 2 BEEF"), InvalidRdataText);
-    EXPECT_THROW(const generic::DS ds2("11111 555 2 BEEF"), InvalidRdataText);
-    EXPECT_THROW(const generic::DS ds2("11111 5 22222 BEEF"), InvalidRdataText);
-    EXPECT_THROW(const generic::DS ds2("11111 5 2"), InvalidRdataText);
-    EXPECT_THROW(const generic::DS ds2("GARBAGE IN"), InvalidRdataText);
-}
-
-// this test currently fails; we must fix it, and then migrate the test to
-// badText_DS
-TEST_F(Rdata_DS_Test, DISABLED_badText_DS) {
-    // no space between the digest type and the digest.
-    EXPECT_THROW(const generic::DS ds2(
-                     "12892 5 2F1E184C0E1D615D20EB3C223ACED3B03C773DD952D"
-                     "5F0EB5C777586DE18DA6B5"), InvalidRdataText);
-}
-
-TEST_F(Rdata_DS_Test, createFromWire_DS) {
-    EXPECT_EQ(0, rdata_ds.compare(
-                  *rdataFactoryFromFile(RRType::DS(), RRClass::IN(),
-                                        "rdata_ds_fromWire")));
-}
-
-TEST_F(Rdata_DS_Test, getTag_DS) {
-    EXPECT_EQ(12892, rdata_ds.getTag());
-}
-
-TEST_F(Rdata_DS_Test, toWireRenderer) {
-    renderer.skip(2);
-    generic::DS rdata_ds(ds_txt);
-    rdata_ds.toWire(renderer);
-
-    vector<unsigned char> data;
-    UnitTestUtil::readWireData("rdata_ds_fromWire", data);
-    EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
-                        static_cast<const uint8_t *>(obuffer.getData()) + 2,
-                        obuffer.getLength() - 2, &data[2], data.size() - 2);
-}
-
-TEST_F(Rdata_DS_Test, toWireBuffer) {
-    generic::DS rdata_ds(ds_txt);
-    rdata_ds.toWire(obuffer);
-}
-
-TEST_F(Rdata_DS_Test, compare) {
-    // trivial case: self equivalence
-    EXPECT_EQ(0, generic::DS(ds_txt).compare(generic::DS(ds_txt)));
-
-    // TODO: need more tests
-}
-
-}

+ 4 - 1
tests/system/cleanall.sh

@@ -27,7 +27,10 @@ find . -type f \( \
 
 
 status=0
 status=0
 
 
-for d in `find . -type d -maxdepth 1 -mindepth 1 -print`
+for d in ./.* ./*
 do
 do
+   case $d in ./.|./..) continue ;; esac
+   test -d $d || continue
+
    test ! -f $d/clean.sh || ( cd $d && sh clean.sh )
    test ! -f $d/clean.sh || ( cd $d && sh clean.sh )
 done
 done