Browse Source

[878] Replaced Addr6 class with asiolink::IOAddress.

Tomek Mrugalski 13 years ago
parent
commit
f6463fa6e7

+ 2 - 2
src/bin/dhcp6/Makefile.am

@@ -31,8 +31,8 @@ spec_config.h: spec_config.h.pre
 
 BUILT_SOURCES = spec_config.h
 pkglibexec_PROGRAMS = b10-dhcp6
-b10_dhcp6_SOURCES = main.cc addr6.cc iface_mgr.cc pkt6.cc dhcp6_srv.cc 
-b10_dhcp6_SOURCES += addr6.h iface_mgr.h pkt6.h dhcp6_srv.h dhcp6.h
+b10_dhcp6_SOURCES = main.cc iface_mgr.cc pkt6.cc dhcp6_srv.cc
+b10_dhcp6_SOURCES += iface_mgr.h pkt6.h dhcp6_srv.h dhcp6.h
 b10_dhcp6_LDADD =  $(top_builddir)/src/lib/datasrc/libdatasrc.la
 b10_dhcp6_LDADD += $(top_builddir)/src/lib/dns/libdns++.la
 b10_dhcp6_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la

+ 0 - 91
src/bin/dhcp6/addr6.cc

@@ -1,91 +0,0 @@
-// 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.h>
-#include <arpa/inet.h>
-
-#include <ostream>
-
-#include "dhcp6/addr6.h"
-
-std::ostream&
-isc::operator << (std::ostream & out, const isc::Addr6& addr) {
-    out << addr.getPlain();
-    return out;
-}
-
-using namespace std;
-using namespace isc;
-
-Addr6::Addr6(const char* addr, bool plain /*=false*/) {
-    if (plain) {
-        inet_pton(AF_INET6, addr, addr_);
-    } else {
-        memcpy(addr_, addr, 16);
-    }
-}
-
-Addr6::Addr6() {
-    memset(addr_, 0, 16);
-}
-
-Addr6::Addr6(in6_addr* addr) {
-    memcpy(addr_, addr, 16);
-}
-
-Addr6::Addr6(sockaddr_in6* addr) {
-    memcpy(addr_, &addr->sin6_addr, 16);
-}
-
-bool
-Addr6::linkLocal() const {
-    if ( ( (unsigned char)addr_[0]==0xfe) &&
-         ( (unsigned char)addr_[1]==0x80) ) {
-	return (true);
-    } else {
-        return (false);
-    }
-}
-
-bool
-Addr6::multicast() const {
-    if ( (unsigned char)addr_[0]==0xff) {
-        return (true);
-    } else {
-        return (false);
-    }
-}
-
-std::string
-Addr6::getPlain() const {
-    char buf[MAX_ADDRESS_STRING_LEN];
-
-    inet_ntop(AF_INET6, addr_, buf, MAX_ADDRESS_STRING_LEN);
-    return (string(buf));
-}
-
-bool
-Addr6::equals(const Addr6& other) const {
-    if (!memcmp(addr_, other.addr_, 16)) {
-        return (true);
-    } else {
-        return (false);
-    }
-    // return !memcmp() would be shorter, but less readable
-}
-
-bool
-Addr6::operator==(const Addr6& other) const {
-    return (equals(other));
-}

+ 0 - 63
src/bin/dhcp6/addr6.h

@@ -1,63 +0,0 @@
-// 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 ADDR6_H
-#define ADDR6_H
-
-#include <ostream>
-#include <string>
-#include <list>
-
-namespace isc {
-
-    static const int MAX_ADDRESS_STRING_LEN =
-        sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255");
-
-
-    /// \brief The implementation class for IPv6 address.
-    ///
-    /// There are no virtual methods to avoid virtual funtions
-    /// table. There are no extra fields, other than the address
-    /// itself. As a result, instances of this class are memory
-    /// optimal (sizeof(Addr6) == 16).
-    ///
-    /// Extra care should be taken, when extending this class
-    /// to keep low memory footprint.
-    class Addr6 {
-    public:
-        Addr6(const char* addr, bool plain=false);
-        Addr6(struct in6_addr* addr);
-        Addr6(struct sockaddr_in6* addr);
-        Addr6();
-        inline const char * get() const { return addr_; }
-        std::string getPlain() const;
-        char* getAddr() { return addr_; }
-        bool equals(const Addr6& other) const;
-        bool operator==(const Addr6& other) const;
-
-        bool linkLocal() const;
-        bool multicast() const;
-
-        // no dtor necessary (no allocations done)
-    private:
-        char addr_[16];
-    };
-
-    std::ostream& operator << (std::ostream & out, const Addr6& addr);
-
-    // TODO may need to also define map for faster access
-    typedef std::list<Addr6> Addr6Lst;
-};
-
-#endif

+ 0 - 1
src/bin/dhcp6/dhcp6_srv.cc

@@ -12,7 +12,6 @@
 // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 // PERFORMANCE OF THIS SOFTWARE.
 
-#include "dhcp6/addr6.h"
 #include "dhcp6/pkt6.h"
 #include "dhcp6/iface_mgr.h"
 #include "dhcp6/dhcp6_srv.h"

+ 0 - 2
src/bin/dhcp6/dhcp6_srv.h

@@ -17,8 +17,6 @@
 
 #include <iostream>
 
-#include "dhcp6/addr6.h"
-
 namespace isc {
     class Dhcpv6Srv {
     private:

+ 34 - 20
src/bin/dhcp6/iface_mgr.cc

@@ -19,13 +19,13 @@
 #include <arpa/inet.h>
 #include <net/if.h>
 
-#include "addr6.h"
 #include "dhcp6/iface_mgr.h"
 #include "dhcp6/dhcp6.h"
 #include "exceptions/exceptions.h"
 
 using namespace std;
 using namespace isc;
+using namespace isc::asiolink;
 
 namespace isc {
 
@@ -135,7 +135,7 @@ IfaceMgr::detectIfaces() {
         cout << "Detected interface " << ifaceName << "/" << linkLocal << endl;
 
         Iface iface(ifaceName, if_nametoindex( ifaceName.c_str() ) );
-        Addr6 addr(linkLocal.c_str(), true);
+        IOAddress addr(linkLocal);
         iface.addrs_.push_back(addr);
         ifaces_.push_back(iface);
         interfaces.close();
@@ -167,7 +167,7 @@ IfaceMgr::openSockets() {
             sendsock_ = sock;
 
             sock = openSocket(iface->name_,
-                              Addr6(ALL_DHCP_RELAY_AGENTS_AND_SERVERS, true),
+                              IOAddress(ALL_DHCP_RELAY_AGENTS_AND_SERVERS),
                               DHCP6_SERVER_PORT, true);
             if (sock<0) {
                 cout << "Failed to open multicast socket." << endl;
@@ -190,7 +190,7 @@ IfaceMgr::printIfaces() {
         for (Addr6Lst::const_iterator addr=iface->addrs_.begin();
              addr != iface->addrs_.end();
              ++addr) {
-            cout << "  " << *addr << endl;
+            cout << "  " << addr->toText() << endl;
         }
         cout << "  mac: " << iface->getPlainMac() << endl;
     }
@@ -209,7 +209,7 @@ IfaceMgr::getIface(int ifindex) {
 }
 
 IfaceMgr::Iface*
-IfaceMgr::getIface(const std::string &ifname) {
+IfaceMgr::getIface(const std::string& ifname) {
     for (IfaceLst::iterator iface=ifaces_.begin();
          iface!=ifaces_.end();
          ++iface) {
@@ -221,25 +221,27 @@ IfaceMgr::getIface(const std::string &ifname) {
 }
 
 int
-IfaceMgr::openSocket(const std::string &ifname,
-                         const Addr6 &addr,
-                         int port,
-                         bool mcast) {
+IfaceMgr::openSocket(const std::string& ifname,
+                     const IOAddress & addr,
+                     int port,
+                     bool mcast) {
     struct sockaddr_storage name;
     int name_len;
     struct sockaddr_in6 *addr6;
 
-    cout << "Creating socket on " << ifname << "/" << addr << "/port="
-         << port << endl;
+    cout << "Creating socket on " << ifname << "/" << addr.toText()
+         << "/port=" << port << endl;
 
     memset(&name, 0, sizeof(name));
     addr6 = (struct sockaddr_in6 *)&name;
     addr6->sin6_family = AF_INET6;
     addr6->sin6_port = htons(port);
     addr6->sin6_scope_id = if_nametoindex(ifname.c_str());
+
     memcpy(&addr6->sin6_addr,
-           addr.get(),
+           addr.getAddress().to_v6().to_bytes().data(),
            sizeof(addr6->sin6_addr));
+
 #ifdef HAVE_SA_LEN
     addr6->sin6_len = sizeof(*addr6);
 #endif
@@ -264,7 +266,7 @@ IfaceMgr::openSocket(const std::string &ifname,
     }
 
     if (bind(sock, (struct sockaddr *)&name, name_len) < 0) {
-        cout << "Failed to bind socket " << sock << " to " << addr.getPlain()
+        cout << "Failed to bind socket " << sock << " to " << addr.toText()
              << "/port=" << port << endl;
         return (-1);
     }
@@ -299,8 +301,8 @@ IfaceMgr::openSocket(const std::string &ifname,
         }
     }
 
-    cout << "Created socket " << sock << " on " << ifname << "/" << addr
-         << "/port=" << port << endl;
+    cout << "Created socket " << sock << " on " << ifname << "/" <<
+        addr.toText() << "/port=" << port << endl;
 
     return (sock);
 }
@@ -351,7 +353,9 @@ IfaceMgr::send(Pkt6 &pkt) {
     memset(&to, 0, sizeof(to));
     to.sin6_family = AF_INET6;
     to.sin6_port = htons(pkt.remote_port_);
-    memcpy(&to.sin6_addr, pkt.remote_addr_.get(), 16);
+    memcpy(&to.sin6_addr,
+           pkt.remote_addr_.getAddress().to_v6().to_bytes().data(),
+           16);
     to.sin6_scope_id = pkt.ifindex_;
 
     m.msg_name = &to;
@@ -394,7 +398,8 @@ IfaceMgr::send(Pkt6 &pkt) {
 
     cout << "Sent " << pkt.data_len_ << " bytes over "
          << pkt.iface_ << "/" << pkt.ifindex_ << " interface: "
-         << " dst=" << pkt.remote_addr_ << ", src=" << pkt.local_addr_
+         << " dst=" << pkt.remote_addr_.toText()
+         << ", src=" << pkt.local_addr_.toText()
          << endl;
 
     return (result);
@@ -410,6 +415,7 @@ IfaceMgr::receive() {
     struct sockaddr_in6 from;
     struct in6_addr to_addr;
     Pkt6* pkt;
+    char addr_str[INET6_ADDRSTRLEN];
 
     try {
         pkt = new Pkt6(1500);
@@ -489,8 +495,15 @@ IfaceMgr::receive() {
         return (0);
     }
 
-    pkt->local_addr_ = Addr6(&to_addr);
-    pkt->remote_addr_ = Addr6(&from);
+
+    // That's ugly.
+    // TODO add IOAddress constructor that will take struct in6_addr* parameter
+    inet_ntop(AF_INET6, &to_addr, addr_str,INET6_ADDRSTRLEN);
+    pkt->local_addr_ = IOAddress(string(addr_str));
+
+    inet_ntop(AF_INET6, &from.sin6_addr, addr_str, INET6_ADDRSTRLEN);
+    pkt->remote_addr_ = IOAddress(string(addr_str));
+
     pkt->remote_port_ = ntohs(from.sin6_port);
 
     Iface* received = getIface(pkt->ifindex_);
@@ -507,7 +520,8 @@ IfaceMgr::receive() {
     // TODO Move this to LOG_DEBUG
     cout << "Received " << pkt->data_len_ << " bytes over "
          << pkt->iface_ << "/" << pkt->ifindex_ << " interface: "
-         << " src=" << pkt->remote_addr_ << ", dst=" << pkt->local_addr_
+         << " src=" << pkt->remote_addr_.toText()
+         << ", dst=" << pkt->local_addr_.toText()
          << endl;
 
     return (pkt);

+ 3 - 2
src/bin/dhcp6/iface_mgr.h

@@ -16,7 +16,7 @@
 #define IFACE_MGR_H
 
 #include <list>
-#include "dhcp6/addr6.h"
+#include "io_address.h"
 #include "dhcp6/pkt6.h"
 
 namespace isc {
@@ -29,6 +29,7 @@ namespace isc {
      */
     class IfaceMgr {
     public:
+        typedef std::list<isc::asiolink::IOAddress> Addr6Lst;
         struct Iface { // XXX: could be a class as well
             std::string name_;
             int ifindex_;
@@ -58,7 +59,7 @@ namespace isc {
         void printIfaces();
 
         int openSocket(const std::string& ifname,
-                       const Addr6& addr,
+                       const isc::asiolink::IOAddress& addr,
                        int port, bool multicast);
         bool joinMcast(int sock, const std::string& ifname,
                        const std::string& mcast);

+ 2 - 0
src/bin/dhcp6/main.cc

@@ -73,6 +73,8 @@ main(int argc, char* argv[]) {
         }
     }
 
+    cout << "My pid=" << getpid() << endl;
+
     if (argc - optind > 0) {
         usage();
     }

+ 7 - 2
src/bin/dhcp6/pkt6.cc

@@ -31,7 +31,10 @@ namespace isc {
 /// \param data
 /// \param dataLen
 ///
-Pkt6::Pkt6(char * data, int dataLen) {
+Pkt6::Pkt6(char * data, int dataLen)
+    :local_addr_("::"),
+     remote_addr_("::")
+{
     data_ = data;
     data_len_ = dataLen;
 }
@@ -47,7 +50,9 @@ Pkt6::Pkt6(char * data, int dataLen) {
 ///
 /// \param dataLen - length of the data to be allocated
 ///
-Pkt6::Pkt6(int dataLen) {
+Pkt6::Pkt6(int dataLen)
+    :local_addr_("::"),
+     remote_addr_("::") {
     try {
 	data_ = new char[dataLen];
 	data_len_ = dataLen;

+ 3 - 3
src/bin/dhcp6/pkt6.h

@@ -16,7 +16,7 @@
 #define PKT6_H
 
 #include <iostream>
-#include "dhcp6/addr6.h"
+#include "io_address.h"
 
 namespace isc {
 
@@ -31,8 +31,8 @@ namespace isc {
         char * data_;
         int data_len_;
 
-        Addr6 local_addr_;
-        Addr6 remote_addr_;
+        isc::asiolink::IOAddress local_addr_;
+        isc::asiolink::IOAddress remote_addr_;
 
         std::string iface_;
         int ifindex_;

+ 2 - 3
src/bin/dhcp6/tests/Makefile.am

@@ -26,6 +26,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
 AM_CPPFLAGS += -I$(top_builddir)/src/bin # for generated spec_config.h header
 AM_CPPFLAGS += -I$(top_srcdir)/src/bin
 AM_CPPFLAGS += -I$(top_builddir)/src/lib/cc
+AM_CPPFLAGS += -I$(top_srcdir)/src/lib/asiolink
 AM_CPPFLAGS += $(BOOST_INCLUDES)
 AM_CPPFLAGS += -DTEST_DATA_DIR=\"$(abs_top_srcdir)/src/lib/testutils/testdata\"
 AM_CPPFLAGS += -DTEST_DATA_BUILDDIR=\"$(abs_top_builddir)/src/lib/testutils/testdata\"
@@ -42,12 +43,10 @@ if HAVE_GTEST
 
 TESTS += dhcp6_unittests
 
-dhcp6_unittests_SOURCES  = ../addr6.h ../addr6.cc
-dhcp6_unittests_SOURCES += ../pkt6.h ../pkt6.cc
+dhcp6_unittests_SOURCES = ../pkt6.h ../pkt6.cc
 dhcp6_unittests_SOURCES += ../iface_mgr.h ../iface_mgr.cc
 dhcp6_unittests_SOURCES += ../dhcp6_srv.h ../dhcp6_srv.cc
 dhcp6_unittests_SOURCES += dhcp6_unittests.cc
-dhcp6_unittests_SOURCES += addr6_unittest.cc
 dhcp6_unittests_SOURCES += pkt6_unittest.cc
 dhcp6_unittests_SOURCES += iface_mgr_unittest.cc
 dhcp6_unittests_SOURCES += dhcp6_srv_unittest.cc

+ 0 - 91
src/bin/dhcp6/tests/addr6_unittest.cc

@@ -1,91 +0,0 @@
-// 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 "dhcp6/addr6.h"
-
-using namespace std;
-using namespace isc;
-
-namespace {
-// empty class for now, but may be extended once Addr6 becomes bigger
-class Addr6Test : public ::testing::Test {
-public:
-    Addr6Test() {
-    }
-};
-
-TEST_F(Addr6Test, constructor) {
-
-    char buf[16];
-
-    string addr1("2001:db8:1::abcd");
-    inet_pton(AF_INET6, addr1.c_str(), buf);
-
-    Addr6 test1(addr1.c_str(), true);
-
-    EXPECT_EQ(test1.getPlain(), addr1);
-    EXPECT_EQ(memcmp(test1.get(),buf, 16), 0);
-
-    Addr6 test2(buf, false);
-
-    EXPECT_EQ(test2.getPlain(), addr1);
-    EXPECT_EQ(memcmp(test2.get(),buf, 16), 0);
-}
-
-TEST_F(Addr6Test, mcast_linklocal) {
-
-    Addr6 mcast("ff00:2001:db8:1::abcd", true);
-    Addr6 global("2001:db8:1::dead:beef", true);
-    Addr6 local("fe80::face:b00c", true);
-
-    EXPECT_TRUE(mcast.multicast());
-    EXPECT_FALSE(mcast.linkLocal());
-
-    EXPECT_FALSE(global.multicast());
-    EXPECT_FALSE(global.linkLocal());
-
-    EXPECT_FALSE(local.multicast());
-    EXPECT_TRUE(local.linkLocal());
-}
-
-TEST_F(Addr6Test, equal) {
-
-    Addr6 one("2001:db8:1::abcd");
-    Addr6 two("2001:db8:1::abcd");
-    Addr6 three("2001:db8:1::4321");
-
-    EXPECT_TRUE( one==two );
-    EXPECT_FALSE( one==three );
-}
-
-TEST_F(Addr6Test, stream) {
-
-    string plain("2001:db8:1::abcd");
-    Addr6 addr(plain.c_str(), true);
-
-    stringstream tmp;
-    tmp << addr;
-
-    EXPECT_STREQ( tmp.str().c_str(), plain.c_str() );
-}
-
-}

+ 7 - 6
src/bin/dhcp6/tests/iface_mgr_unittest.cc

@@ -20,12 +20,13 @@
 #include <arpa/inet.h>
 #include <gtest/gtest.h>
 
-#include "dhcp6/addr6.h"
+#include "io_address.h"
 #include "dhcp6/pkt6.h"
 #include "dhcp6/iface_mgr.h"
 
 using namespace std;
 using namespace isc;
+using namespace isc::asiolink;
 
 namespace {
 class NakedIfaceMgr: public IfaceMgr {
@@ -121,10 +122,10 @@ TEST_F(IfaceMgrTest, detectIfaces) {
     // there should be one address
     EXPECT_EQ(1, eth0->addrs_.size());
     
-    Addr6 * addr = &(*eth0->addrs_.begin());
+    IOAddress * addr = &(*eth0->addrs_.begin());
     ASSERT_TRUE( addr != NULL );
     
-    EXPECT_STREQ( "fe80::1234", addr->getPlain().c_str() );
+    EXPECT_STREQ( "fe80::1234", addr->toText().c_str() );
 }
 
 TEST_F(IfaceMgrTest, sockets) {
@@ -133,7 +134,7 @@ TEST_F(IfaceMgrTest, sockets) {
 
     IfaceMgr & ifacemgr = IfaceMgr::instance();
 
-    Addr6 loAddr("::1", true);
+    IOAddress loAddr("::1");
 
     // bind multicast socket to port 10547
     int socket1 = ifacemgr.openSocket("lo", loAddr, 10547, true);
@@ -156,7 +157,7 @@ TEST_F(IfaceMgrTest, sendReceive) {
     NakedIfaceMgr * ifacemgr = new NakedIfaceMgr();
 
     // let's assume that every supported OS have lo interface
-    Addr6 loAddr("::1", true);
+    IOAddress loAddr("::1");
     int socket1 = ifacemgr->openSocket("lo", loAddr, 10547, true);
     int socket2 = ifacemgr->openSocket("lo", loAddr, 10546, false);
 
@@ -171,7 +172,7 @@ TEST_F(IfaceMgrTest, sendReceive) {
     }
 
     sendPkt.remote_port_ = 10547;
-    sendPkt.remote_addr_ = Addr6("::1", true);
+    sendPkt.remote_addr_ = IOAddress("::1");
     sendPkt.ifindex_ = 1;
     sendPkt.iface_ = "lo";
     

+ 5 - 0
src/lib/asiolink/io_address.cc

@@ -63,5 +63,10 @@ IOAddress::getFamily() const {
     }
 }
 
+const asio::ip::address& 
+IOAddress::getAddress() const {
+    return asio_address_;
+}
+
 } // namespace asiolink
 } // namespace isc

+ 8 - 0
src/lib/asiolink/io_address.h

@@ -74,6 +74,14 @@ public:
     /// \return A string representation of the address.
     std::string toText() const;
 
+    /// \brief Returns const reference to the underlying address object.
+    ///
+    /// This is useful, when access to interface offerted by
+    //  asio::ip::address_v4 and asio::ip::address_v6 is beneficial.
+    /// 
+    /// \return A const reference to asio::ip::address object
+    const asio::ip::address& getAddress() const;
+
     /// \brief Returns the address family
     ///
     /// \return AF_INET for IPv4 or AF_INET6 for IPv6.