BIND 10 trac1186, updated. de67e0176367761eea5dd40119cd575361b0d053 [1186] Option6_AddrLst implemented (useful for storing v6 addresses)

BIND 10 source code commits bind10-changes at lists.isc.org
Thu Sep 8 14:58:06 UTC 2011


The branch, trac1186 has been updated
       via  de67e0176367761eea5dd40119cd575361b0d053 (commit)
       via  71c2767e44129d0d4cb44c71404d977639bf975d (commit)
      from  82e8b607ce2ff71d46c275b744cc7233edec9872 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit de67e0176367761eea5dd40119cd575361b0d053
Author: Tomek Mrugalski <tomasz at isc.org>
Date:   Thu Sep 8 16:57:10 2011 +0200

    [1186] Option6_AddrLst implemented (useful for storing v6 addresses)

commit 71c2767e44129d0d4cb44c71404d977639bf975d
Author: Tomek Mrugalski <tomasz at isc.org>
Date:   Thu Sep 8 16:53:17 2011 +0200

    [1186] from_bytes() method implement in IOAddress
    - similar to from_string() used in underlying boost::asio::address

-----------------------------------------------------------------------

Summary of changes:
 src/bin/dhcp6/iface_mgr.cc                     |    2 +
 src/lib/asiolink/io_address.cc                 |   17 ++-
 src/lib/asiolink/io_address.h                  |   10 ++
 src/lib/asiolink/tests/io_address_unittest.cc  |   20 +++
 src/lib/dhcp/Makefile.am                       |    1 +
 src/lib/dhcp/option6_addrlst.cc                |  132 +++++++++++++++
 src/lib/dhcp/option6_addrlst.h                 |  127 +++++++++++++++
 src/lib/dhcp/tests/Makefile.am                 |    1 +
 src/lib/dhcp/tests/option6_addrlst_unittest.cc |  208 ++++++++++++++++++++++++
 9 files changed, 517 insertions(+), 1 deletions(-)
 create mode 100644 src/lib/dhcp/option6_addrlst.cc
 create mode 100644 src/lib/dhcp/option6_addrlst.h
 create mode 100644 src/lib/dhcp/tests/option6_addrlst_unittest.cc

-----------------------------------------------------------------------
diff --git a/src/bin/dhcp6/iface_mgr.cc b/src/bin/dhcp6/iface_mgr.cc
index c67ef7f..0142089 100644
--- a/src/bin/dhcp6/iface_mgr.cc
+++ b/src/bin/dhcp6/iface_mgr.cc
@@ -553,9 +553,11 @@ IfaceMgr::receive() {
 
     // That's ugly.
     // TODO add IOAddress constructor that will take struct in6_addr*
+    // TODO: there's from_bytes() method added in IOAddress. Use it!
     inet_ntop(AF_INET6, &to_addr, addr_str,INET6_ADDRSTRLEN);
     pkt->local_addr_ = IOAddress(string(addr_str));
 
+    // TODO: there's from_bytes() method added in IOAddress. Use it!
     inet_ntop(AF_INET6, &from.sin6_addr, addr_str, INET6_ADDRSTRLEN);
     pkt->remote_addr_ = IOAddress(string(addr_str));
 
diff --git a/src/lib/asiolink/io_address.cc b/src/lib/asiolink/io_address.cc
index 7e2f5d4..5b2c888 100644
--- a/src/lib/asiolink/io_address.cc
+++ b/src/lib/asiolink/io_address.cc
@@ -54,6 +54,21 @@ IOAddress::toText() const {
     return (asio_address_.to_string());
 }
 
+IOAddress
+IOAddress::from_bytes(short family, const char* data) {
+    static char addr_str[INET6_ADDRSTRLEN];
+    if (data == NULL) {
+        isc_throw(BadValue, "NULL pointer received.");
+    }
+    if ( (family != AF_INET) && (family != AF_INET6) ) {
+        isc_throw(BadValue, "Invalid family type. Only AF_INET and AF_INET6"
+                  << "are supported");
+    }
+
+    inet_ntop(family, data, addr_str,INET6_ADDRSTRLEN);
+    return IOAddress(string(addr_str));
+}
+
 short
 IOAddress::getFamily() const {
     if (asio_address_.is_v4()) {
@@ -63,7 +78,7 @@ IOAddress::getFamily() const {
     }
 }
 
-const asio::ip::address& 
+const asio::ip::address&
 IOAddress::getAddress() const {
     return asio_address_;
 }
diff --git a/src/lib/asiolink/io_address.h b/src/lib/asiolink/io_address.h
index 1b488fa..4d090a1 100644
--- a/src/lib/asiolink/io_address.h
+++ b/src/lib/asiolink/io_address.h
@@ -87,6 +87,16 @@ public:
     /// \return AF_INET for IPv4 or AF_INET6 for IPv6.
     short getFamily() const;
 
+
+    /// \brief Creates an address from over wire data.
+    ///
+    /// \param family AF_NET for IPv4 or AF_NET6 for IPv6.
+    /// \param data pointer to first char of data
+    ///
+    /// \return Created IOAddress object
+    static IOAddress
+    from_bytes(short family, const char* data);
+
     /// \brief Compare addresses for equality
     ///
     /// \param other Address to compare against.
diff --git a/src/lib/asiolink/tests/io_address_unittest.cc b/src/lib/asiolink/tests/io_address_unittest.cc
index 18b181e..3abd535 100644
--- a/src/lib/asiolink/tests/io_address_unittest.cc
+++ b/src/lib/asiolink/tests/io_address_unittest.cc
@@ -61,3 +61,23 @@ TEST(IOAddressTest, Family) {
     EXPECT_EQ(AF_INET, IOAddress("192.0.2.1").getFamily());
     EXPECT_EQ(AF_INET6, IOAddress("2001:0DB8:0:0::0012").getFamily());
 }
+
+TEST(IOAddressTest, from_bytes) {
+    // 2001:db8:1::dead:beef
+    char v6[] = {
+        0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0, 0,
+        0, 0, 0, 0, 0xde, 0xad, 0xbe, 0xef };
+
+    char v4[] = { 192, 0 , 2, 3 };
+
+    IOAddress addr("::");
+    EXPECT_NO_THROW({
+        addr = IOAddress::from_bytes(AF_INET6, v6);
+    });
+    EXPECT_EQ("2001:db8:1::dead:beef", addr.toText());
+
+    EXPECT_NO_THROW({
+        addr = IOAddress::from_bytes(AF_INET, v4);
+    });
+    EXPECT_EQ(addr, IOAddress("192.0.2.3"));
+}
diff --git a/src/lib/dhcp/Makefile.am b/src/lib/dhcp/Makefile.am
index 973453c..ce674ee 100644
--- a/src/lib/dhcp/Makefile.am
+++ b/src/lib/dhcp/Makefile.am
@@ -13,6 +13,7 @@ libdhcp_la_SOURCES += libdhcp.cc libdhcp.h
 libdhcp_la_SOURCES += option.cc option.h
 libdhcp_la_SOURCES += option6_ia.cc option6_ia.h
 libdhcp_la_SOURCES += option6_iaaddr.cc option6_iaaddr.h
+libdhcp_la_SOURCES += option6_addrlst.cc option6_addrlst.h
 libdhcp_la_SOURCES += dhcp6.h
 libdhcp_la_SOURCES += pkt6.cc pkt6.h
 
diff --git a/src/lib/dhcp/option6_addrlst.cc b/src/lib/dhcp/option6_addrlst.cc
new file mode 100644
index 0000000..218baaf
--- /dev/null
+++ b/src/lib/dhcp/option6_addrlst.cc
@@ -0,0 +1,132 @@
+// 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 <stdint.h>
+#include <arpa/inet.h>
+#include <sstream>
+#include "exceptions/exceptions.h"
+
+#include "libdhcp.h"
+#include "option6_addrlst.h"
+#include "dhcp6.h"
+#include "io_address.h"
+
+using namespace std;
+using namespace isc;
+using namespace isc::dhcp;
+using namespace isc::asiolink;
+
+
+Option6AddrLst::Option6AddrLst(unsigned short type,
+                               std::vector<isc::asiolink::IOAddress>& addrs)
+    :Option(V6, type) {
+    addrs_ = addrs;
+}
+
+Option6AddrLst::Option6AddrLst(unsigned short type,
+                               isc::asiolink::IOAddress addr)
+    :Option(V6, type) {
+    addrs_.push_back(addr);
+}
+
+Option6AddrLst::Option6AddrLst(unsigned short type,
+                               boost::shared_array<char> buf,
+                               unsigned int buf_len,
+                               unsigned int offset,
+                               unsigned int option_len)
+    :Option(V6, type) {
+    unpack(buf, buf_len, offset, option_len);
+}
+
+void
+Option6AddrLst::setAddress(isc::asiolink::IOAddress addr) {
+    addrs_.clear();
+    addrs_.push_back(addr);
+}
+
+void
+Option6AddrLst::setAddresses(std::vector<isc::asiolink::IOAddress>& addrs) {
+    addrs_ = addrs;
+}
+
+unsigned int
+Option6AddrLst::pack(boost::shared_array<char> buf,
+                    unsigned int buf_len,
+                    unsigned int offset) {
+    if (len() > buf_len) {
+        isc_throw(OutOfRange, "Failed to pack IA option: len=" << len()
+                  << ", buffer=" << buf_len << ": too small buffer.");
+    }
+
+    *(uint16_t*)&buf[offset] = htons(type_);
+    offset += 2;
+    *(uint16_t*)&buf[offset] = htons(len()-4); // len() returns complete option
+    // length. len field contains length without 4-byte option header
+    offset += 2;
+
+    for (std::vector<IOAddress>::const_iterator addr=addrs_.begin();
+         addr!=addrs_.end();
+         ++addr) {
+        memcpy(&buf[offset],
+               addr->getAddress().to_v6().to_bytes().data(),
+               16);
+        offset += 16;
+    }
+
+    return offset;
+}
+
+unsigned int
+Option6AddrLst::unpack(boost::shared_array<char> buf,
+                  unsigned int buf_len,
+                  unsigned int offset,
+                  unsigned int option_len) {
+    if (offset+option_len > buf_len) {
+        isc_throw(OutOfRange, "Option " << type_
+                  << " truncated.");
+    }
+
+    if (option_len%16) {
+        isc_throw(OutOfRange, "Option " << type_
+                  << " malformed: len=" << option_len
+                  << " is not divisible by 16.");
+    }
+    while (option_len > 0) {
+        addrs_.push_back(IOAddress::from_bytes(AF_INET6, &buf[offset]));
+        offset += 16;
+        option_len -= 16;
+    }
+
+    return offset;
+}
+
+std::string Option6AddrLst::toText(int indent /* =0 */) {
+    stringstream tmp;
+    for (int i=0; i<indent; i++)
+        tmp << " ";
+
+    tmp << "type=" << type_ << " " << addrs_.size() << "addr(s): ";
+
+    for (AddrsContainer::const_iterator addr=addrs_.begin();
+         addr!=addrs_.end();
+         ++addr) {
+        tmp << addr->toText() << " ";
+    }
+    return tmp.str();
+}
+
+unsigned short Option6AddrLst::len() {
+
+    return (4 /* DHCPv6 option header len */ + addrs_.size()*16);
+}
diff --git a/src/lib/dhcp/option6_addrlst.h b/src/lib/dhcp/option6_addrlst.h
new file mode 100644
index 0000000..2dc0f1d
--- /dev/null
+++ b/src/lib/dhcp/option6_addrlst.h
@@ -0,0 +1,127 @@
+// 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 OPTION6_ADDRLST_H_
+#define OPTION6_ADDRLST_H_
+
+#include <vector>
+#include "io_address.h"
+#include "option.h"
+
+namespace isc {
+namespace dhcp {
+
+/// @brief Option class for handling list of IPv6 addresses.
+///
+/// This class handles a list of IPv6 addresses. An example of such option
+/// is dns-servers option. It can also be used to handle single address.
+///
+class Option6AddrLst: public Option {
+
+
+public:
+    typedef std::vector<isc::asiolink::IOAddress> AddrsContainer;
+
+    /// @brief Constructor used during option generation.
+    ///
+    /// @param type option type
+    /// @param addrs vector of addresses to be stored
+    ///
+    Option6AddrLst(unsigned short type,
+                   AddrsContainer& addrs);
+
+    /// @brief Simplified constructor for a single address
+    ///
+    /// @param type option type
+    /// @param addr a single address to be stored
+    ///
+    Option6AddrLst(unsigned short type,
+                   isc::asiolink::IOAddress addr);
+
+    /// @brief Constructor used for parsing received option
+    ///
+    /// @param type option type
+    /// @param buf pointer to packet buffer
+    /// @param buf_len length of packet buffer
+    /// @param offset offset to beginning of option data
+    /// @param len length of option data
+    ///
+    Option6AddrLst(unsigned short type, boost::shared_array<char> buf,
+                   unsigned int buf_len,
+                   unsigned int offset,
+                   unsigned int len);
+
+    /// @brief Assembles on-wire form of this option
+    ///
+    /// @param buf pointer to packet buffer
+    /// @param buf_len length of packet buffer
+    /// @param offset offset to place, where option is to be stored
+    ///
+    /// @return offset to the next unused char (just after stored option)
+    ///
+    unsigned int
+    pack(boost::shared_array<char> buf, unsigned int buf_len,
+         unsigned int offset);
+
+    /// @brief Parses received data
+    ///
+    /// @param buf pointer to packet buffer
+    /// @param buf_len length of packet buffer
+    /// @param offset offset to option data
+    /// @param parse_len specified option data length
+    ///
+    /// @return offset to the next unparsed char (just after parsed option)
+    ///
+    virtual unsigned int
+    unpack(boost::shared_array<char> buf,
+           unsigned int buf_len,
+           unsigned int offset,
+           unsigned int parse_len);
+
+    virtual std::string toText(int indent = 0);
+
+    /// @brief Sets a single address.
+    ///
+    /// @param addr a single address to be added
+    ///
+    void setAddress(isc::asiolink::IOAddress addr);
+
+    /// @brief Sets list of addresses.
+    ///
+    /// @param addrs a vector of addresses to be added
+    ///
+    void setAddresses(std::vector<isc::asiolink::IOAddress>& addrs);
+
+    /// @brief Returns vector with addresses.
+    ///
+    /// As user may want to use/modify this list, it is better to return
+    /// a copy rather than const reference to the original. This is
+    /// usually one or two addresses long, so it is not a big deal.
+    ///
+    /// @return vector with addresses
+    ///
+    AddrsContainer
+    getAddresses() { return addrs_; };
+
+    // returns data length (data length + DHCPv4/DHCPv6 option header)
+    virtual unsigned short len();
+
+protected:
+    AddrsContainer addrs_;
+};
+
+} // isc::dhcp namespace
+} // isc namespace
+
+#endif /* OPTION_ADDRLST_H_ */
diff --git a/src/lib/dhcp/tests/Makefile.am b/src/lib/dhcp/tests/Makefile.am
index f2b88bf..c00bef5 100644
--- a/src/lib/dhcp/tests/Makefile.am
+++ b/src/lib/dhcp/tests/Makefile.am
@@ -19,6 +19,7 @@ libdhcp_unittests_SOURCES  = run_unittests.cc
 libdhcp_unittests_SOURCES += ../libdhcp.h ../libdhcp.cc libdhcp_unittest.cc
 libdhcp_unittests_SOURCES += ../option6_iaaddr.h ../option6_iaaddr.cc option6_iaaddr_unittest.cc
 libdhcp_unittests_SOURCES += ../option6_ia.h ../option6_ia.cc option6_ia_unittest.cc
+libdhcp_unittests_SOURCES += ../option6_addrlst.h ../option6_addrlst.cc option6_addrlst_unittest.cc
 libdhcp_unittests_SOURCES += ../option.h ../option.cc option_unittest.cc
 libdhcp_unittests_SOURCES += ../pkt6.h ../pkt6.cc pkt6_unittest.cc
 
diff --git a/src/lib/dhcp/tests/option6_addrlst_unittest.cc b/src/lib/dhcp/tests/option6_addrlst_unittest.cc
new file mode 100644
index 0000000..ce0bc22
--- /dev/null
+++ b/src/lib/dhcp/tests/option6_addrlst_unittest.cc
@@ -0,0 +1,208 @@
+// 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 <config.h>
+#include <iostream>
+#include <sstream>
+
+#include <arpa/inet.h>
+#include <gtest/gtest.h>
+
+#include "io_address.h"
+#include "dhcp/dhcp6.h"
+#include "dhcp/option.h"
+#include "dhcp/option6_addrlst.h"
+
+using namespace std;
+using namespace isc;
+using namespace isc::dhcp;
+using namespace isc::asiolink;
+
+namespace {
+class Option6AddrLstTest : public ::testing::Test {
+public:
+    Option6AddrLstTest() {
+    }
+};
+
+TEST_F(Option6AddrLstTest, basic) {
+
+    char sampledata[] = {
+        // 2001:db8:1::dead:beef
+        0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0, 0,
+        0, 0, 0, 0, 0xde, 0xad, 0xbe, 0xef,
+
+        // ff02::face:b00c
+        0xff, 02, 0, 0, 0, 0, 0 , 0,
+        0, 0, 0, 0, 0xfa, 0xce, 0xb0, 0x0c,
+
+        // ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+    };
+
+    char expected1[] = {
+        D6O_NAME_SERVERS/256, D6O_NAME_SERVERS%256,//type
+        0, 16, // len = 16 (1 address)
+        0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0, 0,
+        0, 0, 0, 0, 0xde, 0xad, 0xbe, 0xef,
+
+    };
+
+    char expected2[] = {
+        D6O_SIP_SERVERS_ADDR/256, D6O_SIP_SERVERS_ADDR%256,
+        0, 32, // len = 32 (2 addresses)
+        // 2001:db8:1::dead:beef
+        0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0, 0,
+        0, 0, 0, 0, 0xde, 0xad, 0xbe, 0xef,
+
+        // ff02::face:b00c
+        0xff, 02, 0, 0, 0, 0, 0 , 0,
+        0, 0, 0, 0, 0xfa, 0xce, 0xb0, 0x0c,
+
+        // ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+    };
+
+    char expected3[] = {
+        D6O_NIS_SERVERS/256, D6O_NIS_SERVERS%256,
+        0, 48,
+        // 2001:db8:1::dead:beef
+        0x20, 0x01, 0x0d, 0xb8, 0x00, 0x01, 0, 0,
+        0, 0, 0, 0, 0xde, 0xad, 0xbe, 0xef,
+
+        // ff02::face:b00c
+        0xff, 02, 0, 0, 0, 0, 0 , 0,
+        0, 0, 0, 0, 0xfa, 0xce, 0xb0, 0x0c,
+
+        // ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+    };
+
+    boost::shared_array<char> buf(new char[300]);
+    for (int i=0; i<300; i++)
+        buf[i] = 0;
+
+    memcpy(&buf[0], sampledata, 48);
+
+    // just a single address
+    Option6AddrLst* opt1 = new Option6AddrLst(D6O_NAME_SERVERS,
+                                              buf,
+                                              128,
+                                              0,
+                                              16);
+
+
+    EXPECT_EQ(D6O_NAME_SERVERS, opt1->getType());
+    EXPECT_EQ(20, opt1->len());
+    Option6AddrLst::AddrsContainer addrs = opt1->getAddresses();
+    ASSERT_EQ(1, addrs.size());
+    IOAddress addr = addrs[0];
+    EXPECT_EQ("2001:db8:1::dead:beef", addr.toText());
+
+    // pack this option again in the same buffer, but in
+    // different place
+    int offset = opt1->pack(buf,300, 100);
+
+    EXPECT_EQ(120, offset);
+    EXPECT_EQ( 0, memcmp(expected1, &buf[100], 20) );
+
+    // two addresses
+    Option6AddrLst* opt2 = new Option6AddrLst(D6O_SIP_SERVERS_ADDR,
+                                              buf,
+                                              128,
+                                              0,
+                                              32);
+    EXPECT_EQ(D6O_SIP_SERVERS_ADDR, opt2->getType());
+    EXPECT_EQ(36, opt2->len());
+    addrs = opt2->getAddresses();
+    ASSERT_EQ(2, addrs.size());
+    EXPECT_EQ("2001:db8:1::dead:beef", addrs[0].toText());
+    EXPECT_EQ("ff02::face:b00c", addrs[1].toText());
+
+    // pack this option again in the same buffer, but in
+    // different place
+    offset = opt2->pack(buf,300, 150);
+
+    EXPECT_EQ(150+36, offset);
+    EXPECT_EQ( 0, memcmp(expected2, &buf[150], 36));
+
+
+    // three addresses
+    Option6AddrLst* opt3 = new Option6AddrLst(D6O_NIS_SERVERS,
+                                              buf,
+                                              128,
+                                              0,
+                                              48);
+
+    EXPECT_EQ(D6O_NIS_SERVERS, opt3->getType());
+    EXPECT_EQ(52, opt3->len());
+    addrs = opt3->getAddresses();
+    ASSERT_EQ(3, addrs.size());
+    EXPECT_EQ("2001:db8:1::dead:beef", addrs[0].toText());
+    EXPECT_EQ("ff02::face:b00c", addrs[1].toText());
+    EXPECT_EQ("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", addrs[2].toText());
+
+    // pack this option again in the same buffer, but in
+    // different place
+    offset = opt3->pack(buf,300, 200);
+
+    EXPECT_EQ(252, offset);
+    EXPECT_EQ( 0, memcmp(expected3, &buf[200], 52) );
+
+    delete opt1;
+    delete opt2;
+    delete opt3;
+}
+
+TEST_F(Option6AddrLstTest, constructors) {
+     Option6AddrLst * opt1 = new Option6AddrLst(1234,
+                                                IOAddress("::1"));
+     EXPECT_EQ(1234, opt1->getType());
+
+     Option6AddrLst::AddrsContainer addrs = opt1->getAddresses();
+     ASSERT_EQ(1, addrs.size() );
+     EXPECT_EQ("::1", addrs[0].toText());
+
+     addrs.clear();
+     addrs.push_back(IOAddress(string("fe80::1234")));
+     addrs.push_back(IOAddress(string("2001:db8:1::baca")));
+
+     Option6AddrLst * opt2 = new Option6AddrLst(5678,
+                                                addrs);
+
+     Option6AddrLst::AddrsContainer check = opt2->getAddresses();
+     ASSERT_EQ(2, check.size() );
+     EXPECT_EQ("fe80::1234", check[0].toText());
+     EXPECT_EQ("2001:db8:1::baca", check[1].toText());
+
+     delete opt1;
+     delete opt2;
+}
+
+TEST_F(Option6AddrLstTest, setAddress) {
+    Option6AddrLst * opt1 = new Option6AddrLst(1234,
+                                                IOAddress("::1"));
+    opt1->setAddress(IOAddress("::2"));
+
+    Option6AddrLst::AddrsContainer addrs = opt1->getAddresses();
+    ASSERT_EQ(1, addrs.size() );
+    EXPECT_EQ("::2", addrs[0].toText());
+
+    delete opt1;
+}
+
+} // namespace




More information about the bind10-changes mailing list