Commit 0373b72a authored by chenzhengzhang's avatar chenzhengzhang
Browse files

[trac1128] implement SRV rr type

parent 58996536
......@@ -51,6 +51,8 @@ EXTRA_DIST += rdata/generic/soa_6.cc
EXTRA_DIST += rdata/generic/soa_6.h
EXTRA_DIST += rdata/generic/txt_16.cc
EXTRA_DIST += rdata/generic/txt_16.h
EXTRA_DIST += rdata/generic/srv_33.cc
EXTRA_DIST += rdata/generic/srv_33.h
EXTRA_DIST += rdata/hs_4/a_1.cc
EXTRA_DIST += rdata/hs_4/a_1.h
EXTRA_DIST += rdata/in_1/a_1.cc
......
// 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 <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <boost/lexical_cast.hpp>
#include <util/buffer.h>
#include <dns/messagerenderer.h>
#include <dns/name.h>
#include <dns/rdata.h>
#include <dns/rdataclass.h>
using namespace std;
using namespace isc::util;
// BEGIN_ISC_NAMESPACE
// BEGIN_RDATA_NAMESPACE
struct SRVImpl {
// straightforward representation of SRV RDATA fields
SRVImpl(uint16_t priority, uint16_t weight, uint16_t port,
const Name& target) :
priority_(priority), weight_(weight), port_(port),
target_(target)
{}
uint16_t priority_;
uint16_t weight_;
uint16_t port_;
Name target_;
};
SRV::SRV(const string& srv_str) :
impl_(NULL)
{
istringstream iss(srv_str);
string targetname;
unsigned int priority, weight, port;
iss >> priority >> weight >> port >> targetname;
if (iss.bad() || iss.fail()) {
isc_throw(InvalidRdataText, "Invalid SRV text");
}
if (priority > 0xffff) {
isc_throw(InvalidRdataText, "SRV priority out of range");
}
if (weight > 0xffff) {
isc_throw(InvalidRdataText, "SRV weight out of range");
}
if (port > 0xffff) {
isc_throw(InvalidRdataText, "SRV port out of range");
}
impl_ = new SRVImpl(priority, weight, port, Name(targetname));
}
SRV::SRV(InputBuffer& buffer, size_t rdata_len) {
if (rdata_len < 6) {
isc_throw(InvalidRdataLength, "SRV too short");
}
uint16_t priority = buffer.readUint16();
uint16_t weight = buffer.readUint16();
uint16_t port = buffer.readUint16();
const Name targetname(buffer);
impl_ = new SRVImpl(priority, weight, port, targetname);
}
SRV::SRV(const SRV& source) :
Rdata(), impl_(new SRVImpl(*source.impl_))
{}
SRV&
SRV::operator=(const SRV& source) {
if (impl_ == source.impl_) {
return (*this);
}
SRVImpl* newimpl = new SRVImpl(*source.impl_);
delete impl_;
impl_ = newimpl;
return (*this);
}
SRV::~SRV() {
delete impl_;
}
string
SRV::toText() const {
using namespace boost;
return (lexical_cast<string>(static_cast<int>(impl_->priority_)) +
" " + lexical_cast<string>(static_cast<int>(impl_->weight_)) +
" " + lexical_cast<string>(static_cast<int>(impl_->port_)) +
" " + impl_->target_.toText());
}
void
SRV::toWire(OutputBuffer& buffer) const {
buffer.writeUint16(impl_->priority_);
buffer.writeUint16(impl_->weight_);
buffer.writeUint16(impl_->port_);
impl_->target_.toWire(buffer);
}
void
SRV::toWire(AbstractMessageRenderer& renderer) const {
renderer.writeUint16(impl_->priority_);
renderer.writeUint16(impl_->weight_);
renderer.writeUint16(impl_->port_);
renderer.writeName(impl_->target_, false);
}
int
SRV::compare(const Rdata& other) const {
const SRV& other_srv = dynamic_cast<const SRV&>(other);
if (impl_->priority_ != other_srv.impl_->priority_) {
return (impl_->priority_ < other_srv.impl_->priority_ ? -1 : 1);
}
if (impl_->weight_ != other_srv.impl_->weight_) {
return (impl_->weight_ < other_srv.impl_->weight_ ? -1 : 1);
}
if (impl_->port_ != other_srv.impl_->port_) {
return (impl_->port_ < other_srv.impl_->port_ ? -1 : 1);
}
return (compareNames(impl_->target_, other_srv.impl_->target_));
}
uint16_t
SRV::getPriority() const {
return (impl_->priority_);
}
uint16_t
SRV::getWeight() const {
return (impl_->weight_);
}
uint16_t
SRV::getPort() const {
return (impl_->port_);
}
const Name&
SRV::getTarget() const {
return (impl_->target_);
}
// END_RDATA_NAMESPACE
// END_ISC_NAMESPACE
// 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 <stdint.h>
#include <string>
#include <dns/name.h>
#include <dns/rrtype.h>
#include <dns/rrttl.h>
#include <dns/rdata.h>
// BEGIN_HEADER_GUARD
// BEGIN_ISC_NAMESPACE
// BEGIN_COMMON_DECLARATIONS
// END_COMMON_DECLARATIONS
// BEGIN_RDATA_NAMESPACE
struct SRVImpl;
class SRV : public Rdata {
public:
// BEGIN_COMMON_MEMBERS
// END_COMMON_MEMBERS
SRV& operator=(const SRV& source);
~SRV();
///
/// Specialized methods
///
uint16_t getPriority() const;
uint16_t getWeight() const;
uint16_t getPort() const;
const Name& getTarget() const;
private:
SRVImpl* impl_;
};
// END_RDATA_NAMESPACE
// END_ISC_NAMESPACE
// END_HEADER_GUARD
// Local Variables:
// mode: c++
// End:
......@@ -41,6 +41,7 @@ run_unittests_SOURCES += rdata_nsecbitmap_unittest.cc
run_unittests_SOURCES += rdata_nsec3param_unittest.cc
run_unittests_SOURCES += rdata_rrsig_unittest.cc
run_unittests_SOURCES += rdata_rp_unittest.cc
run_unittests_SOURCES += rdata_srv_unittest.cc
run_unittests_SOURCES += rdata_tsig_unittest.cc
run_unittests_SOURCES += rrset_unittest.cc rrsetlist_unittest.cc
run_unittests_SOURCES += question_unittest.cc
......
// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for generic
// 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 <util/buffer.h>
#include <dns/exceptions.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_SRV_Test : public RdataTest {
// there's nothing to specialize
};
string srv_txt("1 5 1500 a.example.com.");
string srv_txt2("1 5 1400 example.com.");
string too_long_label("012345678901234567890123456789"
"0123456789012345678901234567890123");
// 1 5 1500 a.example.com.
const uint8_t wiredata_srv[] = {
0x00, 0x01, 0x00, 0x05, 0x05, 0xdc, 0x01, 0x61, 0x07, 0x65, 0x78,
0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00};
// 1 5 1400 example.com.
const uint8_t wiredata_srv2[] = {
0x00, 0x01, 0x00, 0x05, 0x05, 0x78, 0x07, 0x65, 0x78, 0x61, 0x6d,
0x70, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00};
const generic::SRV rdata_srv(srv_txt);
const generic::SRV rdata_srv2(srv_txt2);
TEST_F(Rdata_SRV_Test, createFromText) {
EXPECT_EQ(1, rdata_srv.getPriority());
EXPECT_EQ(5, rdata_srv.getWeight());
EXPECT_EQ(1500, rdata_srv.getPort());
EXPECT_EQ(Name("a.example.com."), rdata_srv.getTarget());
}
TEST_F(Rdata_SRV_Test, badText) {
// priority is too large (2814...6 is 2^48)
EXPECT_THROW(generic::SRV("281474976710656 5 1500 a.example.com."),
InvalidRdataText);
// weight is too large
EXPECT_THROW(generic::SRV("1 281474976710656 1500 a.example.com."),
InvalidRdataText);
// port is too large
EXPECT_THROW(generic::SRV("1 5 281474976710656 a.example.com."),
InvalidRdataText);
// incomplete text
EXPECT_THROW(generic::SRV("1 5 a.example.com."),
InvalidRdataText);
// bad name
EXPECT_THROW(generic::SRV("1 5 1500 a.example.com." + too_long_label),
TooLongLabel);
}
TEST_F(Rdata_SRV_Test, assignment) {
generic::SRV copy((string(srv_txt2)));
copy = rdata_srv;
EXPECT_EQ(0, copy.compare(rdata_srv));
// Check if the copied data is valid even after the original is deleted
generic::SRV* copy2 = new generic::SRV(rdata_srv);
generic::SRV copy3((string(srv_txt2)));
copy3 = *copy2;
delete copy2;
EXPECT_EQ(0, copy3.compare(rdata_srv));
// Self assignment
copy = copy;
EXPECT_EQ(0, copy.compare(rdata_srv));
}
TEST_F(Rdata_SRV_Test, createFromWire) {
EXPECT_EQ(0, rdata_srv.compare(
*rdataFactoryFromFile(RRType("SRV"), RRClass("IN"),
"rdata_srv_fromWire")));
// RDLENGTH is too short
EXPECT_THROW(rdataFactoryFromFile(RRType("SRV"), RRClass("IN"),
"rdata_srv_fromWire", 23),
InvalidRdataLength);
// RDLENGTH is too long
EXPECT_THROW(rdataFactoryFromFile(RRType("SRV"), RRClass("IN"),
"rdata_srv_fromWire", 46),
InvalidRdataLength);
// incomplete name. the error should be detected in the name constructor
EXPECT_THROW(rdataFactoryFromFile(RRType("SRV"), RRClass("IN"),
"rdata_cname_fromWire", 69),
DNSMessageFORMERR);
}
TEST_F(Rdata_SRV_Test, toWireBuffer) {
rdata_srv.toWire(obuffer);
EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
obuffer.getData(), obuffer.getLength(),
wiredata_srv, sizeof(wiredata_srv));
obuffer.clear();
rdata_srv2.toWire(obuffer);
EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
obuffer.getData(), obuffer.getLength(),
wiredata_srv2, sizeof(wiredata_srv2));
}
TEST_F(Rdata_SRV_Test, toWireRenderer) {
rdata_srv.toWire(renderer);
EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
obuffer.getData(), obuffer.getLength(),
wiredata_srv, sizeof(wiredata_srv));
renderer.clear();
rdata_srv2.toWire(renderer);
EXPECT_PRED_FORMAT4(UnitTestUtil::matchWireData,
obuffer.getData(), obuffer.getLength(),
wiredata_srv2, sizeof(wiredata_srv2));
}
TEST_F(Rdata_SRV_Test, toText) {
EXPECT_EQ(srv_txt, rdata_srv.toText());
EXPECT_EQ(srv_txt2, rdata_srv2.toText());
}
TEST_F(Rdata_SRV_Test, compare) {
// test RDATAs, sorted in the ascendent order.
vector<generic::SRV> compare_set;
compare_set.push_back(generic::SRV("1 5 1500 a.example.com."));
compare_set.push_back(generic::SRV("2 5 1500 a.example.com."));
compare_set.push_back(generic::SRV("2 6 1500 a.example.com."));
compare_set.push_back(generic::SRV("2 6 1600 a.example.com."));
compare_set.push_back(generic::SRV("2 6 1600 example.com."));
EXPECT_EQ(0, compare_set[0].compare(
generic::SRV("1 5 1500 a.example.com.")));
vector<generic::SRV>::const_iterator it;
vector<generic::SRV>::const_iterator it_end = compare_set.end();
for (it = compare_set.begin(); it != it_end - 1; ++it) {
EXPECT_GT(0, (*it).compare(*(it + 1)));
EXPECT_LT(0, (*(it + 1)).compare(*it));
}
// comparison attempt between incompatible RR types should be rejected
EXPECT_THROW(rdata_srv.compare(*RdataTest::rdata_nomatch), bad_cast);
}
}
#
# various kinds of SRV RDATA stored in an input buffer
#
# RDLENGHT=21 bytes
# 0 1
00 15
# 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 20 1 2(bytes)
00 01 00 05 05 dc 01 61 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
#
# short length
# 3 4
00 12
# 5 6 7 8 9 30 1 2 3 4 5 6 7 8 9 40 1 2 3 4 5
00 01 00 05 05 dc 01 61 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
#
# length too long
# 6 7
00 19
#
# 8 9 50 1 2 3 4 5 6 7 8 9 60 1 2 3 4 5 6 7 8
00 01 00 05 05 dc 01 61 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00
#
# incomplete target name
# 9 70
00 06
# 1 2 3 4 5 6 7 8 9 70 1 2 3 4 5 6 7 8
00 01 00 05 05 dc 01 61 07 65 78 61 6d 70 6c 65 03 63
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment