BIND 10 trac878, updated. ee826c177bef06f22cdbbf82044085972bfd8737 [878] Fix in ifacemgr_unittest: separate instances are now used
BIND 10 source code commits
bind10-changes at lists.isc.org
Thu Aug 18 16:19:31 UTC 2011
The branch, trac878 has been updated
via ee826c177bef06f22cdbbf82044085972bfd8737 (commit)
via 4111989bb81641ee36fa94bf5cb181aa18f5477f (commit)
via 68653f1c822916ceade94511168f87adff74c235 (commit)
via f6463fa6e74a32e3fb28f150247e11d0fe073782 (commit)
from 51a7361aef92b8c6caad857ed09f0bea0f210db6 (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 ee826c177bef06f22cdbbf82044085972bfd8737
Author: Tomek Mrugalski <tomasz at isc.org>
Date: Thu Aug 18 18:17:47 2011 +0200
[878] Fix in ifacemgr_unittest: separate instances are now used
Tests used single instance of IfaceMgr (it is singleton after all).
Therefore first fake interface data was reused in later tests,
causing them to fail.
commit 4111989bb81641ee36fa94bf5cb181aa18f5477f
Author: Tomek Mrugalski <tomasz at isc.org>
Date: Thu Aug 18 17:59:12 2011 +0200
[878] Many improvements in IfaceMgr after review
commit 68653f1c822916ceade94511168f87adff74c235
Author: Tomek Mrugalski <tomasz at isc.org>
Date: Thu Aug 18 16:08:53 2011 +0200
[878] Pkt6 now uses boost::shared_array to manage its buffer.
commit f6463fa6e74a32e3fb28f150247e11d0fe073782
Author: Tomek Mrugalski <tomasz at isc.org>
Date: Thu Aug 18 15:20:26 2011 +0200
[878] Replaced Addr6 class with asiolink::IOAddress.
-----------------------------------------------------------------------
Summary of changes:
doc/Doxyfile | 2 +-
src/bin/dhcp6/Makefile.am | 4 +-
src/bin/dhcp6/addr6.cc | 91 ------------------
src/bin/dhcp6/addr6.h | 63 -------------
src/bin/dhcp6/dhcp6_srv.cc | 1 -
src/bin/dhcp6/dhcp6_srv.h | 2 -
src/bin/dhcp6/iface_mgr.cc | 145 +++++++++++++++++++++--------
src/bin/dhcp6/iface_mgr.h | 53 +++++++----
src/bin/dhcp6/main.cc | 2 +
src/bin/dhcp6/pkt6.cc | 35 +------
src/bin/dhcp6/pkt6.h | 26 ++++-
src/bin/dhcp6/tests/Makefile.am | 5 +-
src/bin/dhcp6/tests/addr6_unittest.cc | 91 ------------------
src/bin/dhcp6/tests/iface_mgr_unittest.cc | 67 ++++++++-----
src/bin/dhcp6/tests/pkt6_unittest.cc | 9 --
src/lib/asiolink/io_address.cc | 5 +
src/lib/asiolink/io_address.h | 8 ++
17 files changed, 228 insertions(+), 381 deletions(-)
delete mode 100644 src/bin/dhcp6/addr6.cc
delete mode 100644 src/bin/dhcp6/addr6.h
delete mode 100644 src/bin/dhcp6/tests/addr6_unittest.cc
-----------------------------------------------------------------------
diff --git a/doc/Doxyfile b/doc/Doxyfile
index b8a4656..8857c16 100644
--- a/doc/Doxyfile
+++ b/doc/Doxyfile
@@ -574,7 +574,7 @@ INPUT = ../src/lib/cc ../src/lib/config \
../src/lib/log ../src/lib/asiolink/ ../src/lib/nsas \
../src/lib/testutils ../src/lib/cache ../src/lib/server_common/ \
../src/bin/sockcreator/ ../src/lib/util/ \
- ../src/lib/resolve ../src/lib/acl
+ ../src/lib/resolve ../src/lib/acl ../src/bin/dhcp6
# 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
diff --git a/src/bin/dhcp6/Makefile.am b/src/bin/dhcp6/Makefile.am
index 57ac397..40b80df 100644
--- a/src/bin/dhcp6/Makefile.am
+++ b/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
diff --git a/src/bin/dhcp6/addr6.cc b/src/bin/dhcp6/addr6.cc
deleted file mode 100644
index c191b78..0000000
--- a/src/bin/dhcp6/addr6.cc
+++ /dev/null
@@ -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));
-}
diff --git a/src/bin/dhcp6/addr6.h b/src/bin/dhcp6/addr6.h
deleted file mode 100644
index 07bcd7b..0000000
--- a/src/bin/dhcp6/addr6.h
+++ /dev/null
@@ -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
diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc
index 4bbfd94..4d9244f 100644
--- a/src/bin/dhcp6/dhcp6_srv.cc
+++ b/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"
diff --git a/src/bin/dhcp6/dhcp6_srv.h b/src/bin/dhcp6/dhcp6_srv.h
index 16941ba..a02f5f6 100644
--- a/src/bin/dhcp6/dhcp6_srv.h
+++ b/src/bin/dhcp6/dhcp6_srv.h
@@ -17,8 +17,6 @@
#include <iostream>
-#include "dhcp6/addr6.h"
-
namespace isc {
class Dhcpv6Srv {
private:
diff --git a/src/bin/dhcp6/iface_mgr.cc b/src/bin/dhcp6/iface_mgr.cc
index 8ca2bc2..da50ba4 100644
--- a/src/bin/dhcp6/iface_mgr.cc
+++ b/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 {
@@ -48,11 +48,6 @@ IfaceMgr::instance() {
return (*instance_);
}
-IfaceMgr::Iface::Iface()
- : name_(""), ifindex_(0), mac_len_(0) {
- memset(mac_, 0, 20);
-}
-
IfaceMgr::Iface::Iface(const std::string& name, int ifindex)
:name_(name), ifindex_(ifindex), mac_len_(0) {
memset(mac_, 0, 20);
@@ -84,6 +79,9 @@ IfaceMgr::IfaceMgr() {
cout << "IfaceMgr initialization." << endl;
try {
+ // required for sending/receiving packets
+ // let's keep it in front, just in case someone
+ // wants to send anything during initialization
control_buf_len_ = CMSG_SPACE(sizeof(struct in6_pktinfo));
control_buf_ = new char[control_buf_len_];
@@ -135,11 +133,16 @@ 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();
} catch (std::exception& ex) {
+ // TODO: deallocate whatever memory we used
+ // not that important, since this function is going to be
+ // thrown away as soon as we get proper interface detection
+ // implemented
+
// TODO Do LOG_FATAL here
std::cerr << "Interface detection failed." << std::endl;
throw ex;
@@ -167,10 +170,11 @@ 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;
+ close(sendsock_);
return (false);
}
recvsock_ = sock;
@@ -181,18 +185,18 @@ IfaceMgr::openSockets() {
}
void
-IfaceMgr::printIfaces() {
+IfaceMgr::printIfaces(std::ostream& out /*= std::cout*/) {
for (IfaceLst::const_iterator iface=ifaces_.begin();
iface!=ifaces_.end();
++iface) {
- cout << "Detected interface " << iface->getFullName() << endl;
- cout << " " << iface->addrs_.size() << " addr(s):" << endl;
+ out << "Detected interface " << iface->getFullName() << endl;
+ out << " " << iface->addrs_.size() << " addr(s):" << endl;
for (Addr6Lst::const_iterator addr=iface->addrs_.begin();
addr != iface->addrs_.end();
++addr) {
- cout << " " << *addr << endl;
+ out << " " << addr->toText() << endl;
}
- cout << " mac: " << iface->getPlainMac() << endl;
+ out << " mac: " << iface->getPlainMac() << endl;
}
}
@@ -205,11 +209,11 @@ IfaceMgr::getIface(int ifindex) {
return (&(*iface));
}
- return 0; // not found
+ return (NULL); // not found
}
IfaceMgr::Iface*
-IfaceMgr::getIface(const std::string &ifname) {
+IfaceMgr::getIface(const std::string& ifname) {
for (IfaceLst::iterator iface=ifaces_.begin();
iface!=ifaces_.end();
++iface) {
@@ -217,35 +221,49 @@ IfaceMgr::getIface(const std::string &ifname) {
return (&(*iface));
}
- return (0); // not found
+ return (NULL); // not found
}
+
+/**
+ * Opens UDP/IPv6 socket and binds it to specific address, interface nad port.
+ *
+ * @param ifname name of the interface
+ * @param addr address to be bound.
+ * @param port UDP port.
+ * @param mcast Should multicast address also be bound?
+ *
+ * @return socket descriptor, if socket creation, binding and multicast
+ * group join were all successful. -1 otherwise.
+ */
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
name_len = sizeof(*addr6);
- // XXX: use sockcreator once it becomes available
+ // TODO: use sockcreator once it becomes available
// make a socket
int sock = socket(AF_INET6, SOCK_DGRAM, 0);
@@ -260,12 +278,14 @@ IfaceMgr::openSocket(const std::string &ifname,
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
(char *)&flag, sizeof(flag)) < 0) {
cout << "Can't set SO_REUSEADDR option on dhcpv6 socket." << endl;
+ close(sock);
return (-1);
}
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;
+ close(sock);
return (-1);
}
@@ -274,6 +294,7 @@ IfaceMgr::openSocket(const std::string &ifname,
if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO,
&flag, sizeof(flag)) != 0) {
cout << "setsockopt: IPV6_RECVPKTINFO failed." << endl;
+ close(sock);
return (-1);
}
#else
@@ -281,6 +302,7 @@ IfaceMgr::openSocket(const std::string &ifname,
if (setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO,
&flag, sizeof(flag)) != 0) {
cout << "setsockopt: IPV6_PKTINFO: failed." << endl;
+ close(sock);
return (-1);
}
#endif
@@ -299,12 +321,21 @@ 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);
}
+/**
+ * joins multicast group
+ *
+ * @param sock socket file descriptor
+ * @param ifname name of the interface (DHCPv6 uses link-scoped mc groups)
+ * @param mcast multicast address to join (string)
+ *
+ * @return true if joined successfully, false otherwise
+ */
bool
IfaceMgr::joinMcast(int sock, const std::string& ifname,
const std::string & mcast) {
@@ -330,6 +361,17 @@ const std::string & mcast) {
return (true);
}
+/**
+ * Sends UDP packet over IPv6.
+ *
+ * All parameters for actual transmission are specified in
+ * Pkt6 structure itself. That includes destination address,
+ * src/dst port and interface over which data will be sent.
+ *
+ * @param pkt A packet object that is going to be sent.
+ *
+ * @return True, if transmission was successful. False otherwise.
+ */
bool
IfaceMgr::send(Pkt6 &pkt) {
struct msghdr m;
@@ -351,7 +393,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;
@@ -362,7 +406,7 @@ IfaceMgr::send(Pkt6 &pkt) {
* "scatter-gather" stuff... we only have a single chunk
* of data to send, so we declare a single vector entry.)
*/
- v.iov_base = (char *) pkt.data_;
+ v.iov_base = (char *) &pkt.data_[0];
v.iov_len = pkt.data_len_;
m.msg_iov = &v;
m.msg_iovlen = 1;
@@ -394,12 +438,23 @@ 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);
}
+
+/**
+ * Attempts to receive UDP/IPv6 packet over open sockets.
+ *
+ * TODO Start using select() and add timeout to be able
+ * to not wait infinitely, but rather do something useful
+ * (e.g. remove expired leases)
+ *
+ * @return Object prepresenting received packet.
+ */
Pkt6*
IfaceMgr::receive() {
struct msghdr m;
@@ -410,9 +465,17 @@ IfaceMgr::receive() {
struct sockaddr_in6 from;
struct in6_addr to_addr;
Pkt6* pkt;
+ char addr_str[INET6_ADDRSTRLEN];
try {
- pkt = new Pkt6(1500);
+ // RFC3315 states that server responses may be
+ // fragmented if they are over MTU. There is no
+ // text whether client's packets may be larger
+ // than 1500. Nevertheless to be on the safe side
+ // we use larger buffer. This buffer limit is checked
+ // during reception (see iov_len below), so we are
+ // safe
+ pkt = new Pkt6(65536);
} catch (std::exception& ex) {
cout << "Failed to create new packet." << endl;
return (0);
@@ -439,7 +502,7 @@ IfaceMgr::receive() {
* "scatter-gather" stuff... but we that doesn't really make
* sense for us, so we use a single vector entry.)
*/
- v.iov_base = pkt->data_;
+ v.iov_base = (void*)&pkt->data_[0];
v.iov_len = pkt->data_len_;
m.msg_iov = &v;
m.msg_iovlen = 1;
@@ -489,8 +552,14 @@ 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*
+ 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_);
@@ -498,8 +567,9 @@ IfaceMgr::receive() {
pkt->iface_ = received->name_;
} else {
cout << "Received packet over unknown interface (ifindex="
- << pkt->ifindex_ << endl;
- pkt->iface_ = "[unknown]";
+ << pkt->ifindex_ << ")." << endl;
+ delete pkt;
+ return (0);
}
pkt->data_len_ = result;
@@ -507,7 +577,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);
diff --git a/src/bin/dhcp6/iface_mgr.h b/src/bin/dhcp6/iface_mgr.h
index c72a712..c251fdc 100644
--- a/src/bin/dhcp6/iface_mgr.h
+++ b/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,61 +29,74 @@ namespace isc {
*/
class IfaceMgr {
public:
- struct Iface { // XXX: could be a class as well
- std::string name_;
- int ifindex_;
+ typedef std::list<isc::asiolink::IOAddress> Addr6Lst;
+ struct Iface { // TODO: could be a class as well
+ std::string name_; // network interface name
+ int ifindex_; // interface index (a value that uniquely indentifies
+ // an interface
Addr6Lst addrs_;
- char mac_[20]; //
+ char mac_[20]; // Infiniband used 20 bytes indentifiers
int mac_len_;
- Iface();
Iface(const std::string& name, int ifindex);
std::string getFullName() const;
std::string getPlainMac() const;
+ int sendsock_; // socket used to sending data
+ int recvsock_; // socket used for receiving data
+
// next field is not needed, let's keep it in cointainers
};
- // TODO performance improvement: we may change this into
- // 2 maps (ifindex-indexed and name-indexed)
+ // TODO performance improvement: we may change this into
+ // 2 maps (ifindex-indexed and name-indexed) and
+ // also hide it (make it public make tests easier for now)
typedef std::list<Iface> IfaceLst;
static IfaceMgr& instance();
- static void instanceCreate();
Iface * getIface(int ifindex);
Iface * getIface(const std::string& ifname);
- bool openSockets();
- void printIfaces();
-
- int openSocket(const std::string& ifname,
- const Addr6& addr,
- int port, bool multicast);
- bool joinMcast(int sock, const std::string& ifname,
- const std::string& mcast);
+ void printIfaces(std::ostream& out = std::cout);
bool send(Pkt6& pkt);
Pkt6* receive();
- // don't use private, we need derived classes in tests
+ // don't use private, we need derived classes in tests
protected:
IfaceMgr(); // don't create IfaceMgr directly, use instance() method
~IfaceMgr();
void detectIfaces();
- // XXX: having 2 maps (ifindex->iface and ifname->iface would)
+ int openSocket(const std::string& ifname,
+ const isc::asiolink::IOAddress& addr,
+ int port, bool multicast);
+
+ // TODO: having 2 maps (ifindex->iface and ifname->iface would)
// probably be better for performance reasons
IfaceLst ifaces_;
static IfaceMgr * instance_;
- int recvsock_; // XXX: should be fd_set eventually, but we have only
+ // TODO: Also keep this interface on Iface once interface detection
+ // is implemented. We may need it e.g. to close all sockets on
+ // specific interface
+ int recvsock_; // TODO: should be fd_set eventually, but we have only
int sendsock_; // 2 sockets for now. Will do for until next release
+ // we can't use the same socket, as receiving socket
+ // is bound to multicast address. And we all know what happens
+ // to people who try to use multicast as source address.
char * control_buf_;
int control_buf_len_;
+
+ private:
+ bool openSockets();
+ static void instanceCreate();
+ bool joinMcast(int sock, const std::string& ifname,
+ const std::string& mcast);
};
};
diff --git a/src/bin/dhcp6/main.cc b/src/bin/dhcp6/main.cc
index e56c8e5..95d2261 100644
--- a/src/bin/dhcp6/main.cc
+++ b/src/bin/dhcp6/main.cc
@@ -73,6 +73,8 @@ main(int argc, char* argv[]) {
}
}
+ cout << "My pid=" << getpid() << endl;
+
if (argc - optind > 0) {
usage();
}
diff --git a/src/bin/dhcp6/pkt6.cc b/src/bin/dhcp6/pkt6.cc
index 33025c3..5dcab86 100644
--- a/src/bin/dhcp6/pkt6.cc
+++ b/src/bin/dhcp6/pkt6.cc
@@ -22,50 +22,25 @@ namespace isc {
///
/// constructor
///
-/// This constructor is used during packet reception.
-///
-/// Note: Pkt6 will take ownership of any data passed
-/// (due to performance reasons). Copying data on creation
-/// would be more elegant, but slower.
-///
-/// \param data
-/// \param dataLen
-///
-Pkt6::Pkt6(char * data, int dataLen) {
- data_ = data;
- data_len_ = dataLen;
-}
-
-///
-/// constructor
-///
-/// This constructor is used for generated packets.
-///
-/// Note: Pkt6 will take ownership of any data passed
-/// (due to performance reasons). Copying data on creation
-/// would be more elegant, but slower.
-///
/// \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_ = boost::shared_array<char>(new char[dataLen]);
data_len_ = dataLen;
} catch (const std::exception& ex) {
// TODO move to LOG_FATAL()
// let's continue with empty pkt for now
std::cout << "Failed to allocate " << dataLen << " bytes."
<< std::endl;
- data_ = 0;
data_len_ = 0;
}
}
Pkt6::~Pkt6() {
- if (data_) {
- delete [] data_;
- data_ = 0;
- }
+ // no need to delete anything shared_ptr will take care of data_
}
};
diff --git a/src/bin/dhcp6/pkt6.h b/src/bin/dhcp6/pkt6.h
index 5508fda..9a14d92 100644
--- a/src/bin/dhcp6/pkt6.h
+++ b/src/bin/dhcp6/pkt6.h
@@ -16,32 +16,46 @@
#define PKT6_H
#include <iostream>
-#include "dhcp6/addr6.h"
+#include <boost/shared_array.hpp>
+#include "io_address.h"
namespace isc {
class Pkt6 {
public:
- Pkt6(char * data, int dataLen);
Pkt6(int len);
~Pkt6();
// XXX: probably need getter/setter wrappers
// and hide fields as protected
- char * data_;
+ // buffer that holds memory. It is shared_array as options may
+ // share pointer to this buffer
+ boost::shared_array<char> data_;
+
+ // length of the data
int data_len_;
- Addr6 local_addr_;
- Addr6 remote_addr_;
+ // local address (destination if receiving packet, source if sending packet)
+ isc::asiolink::IOAddress local_addr_;
+
+ // remote address (source if receiving packet, destination if sending packet)
+ isc::asiolink::IOAddress remote_addr_;
+ // name of the network interface the packet was received/to be sent over
std::string iface_;
+
+ // interface index (each network interface has assigned unique ifindex
+ // it is functional equvalent of name, but sometimes more useful, e.g.
+ // when using crazy systems that allow spaces in interface names (Windows)
int ifindex_;
+ // local TDP or UDP port
int local_port_;
+
+ // remote TCP or UDP port
int remote_port_;
// XXX: add *a lot* here
-
};
}
diff --git a/src/bin/dhcp6/tests/Makefile.am b/src/bin/dhcp6/tests/Makefile.am
index b86fab1..91eabce 100644
--- a/src/bin/dhcp6/tests/Makefile.am
+++ b/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
diff --git a/src/bin/dhcp6/tests/addr6_unittest.cc b/src/bin/dhcp6/tests/addr6_unittest.cc
deleted file mode 100644
index dbbca08..0000000
--- a/src/bin/dhcp6/tests/addr6_unittest.cc
+++ /dev/null
@@ -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() );
-}
-
-}
diff --git a/src/bin/dhcp6/tests/iface_mgr_unittest.cc b/src/bin/dhcp6/tests/iface_mgr_unittest.cc
index 7f2b583..0f7f431 100644
--- a/src/bin/dhcp6/tests/iface_mgr_unittest.cc
+++ b/src/bin/dhcp6/tests/iface_mgr_unittest.cc
@@ -20,21 +20,29 @@
#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 {
- // "naked" Interface Manager, exposes internal fields
+ // "naked" Interface Manager, exposes internal fields
public:
NakedIfaceMgr() { }
IfaceLst & getIfacesLst() { return ifaces_; }
void setSendSock(int sock) { sendsock_ = sock; }
void setRecvSock(int sock) { recvsock_ = sock; }
+
+ int openSocket(const std::string& ifname,
+ const isc::asiolink::IOAddress& addr,
+ int port, bool multicast) {
+ return IfaceMgr::openSocket(ifname, addr, port, multicast);
+ }
+
};
// dummy class for now, but this will be expanded when needed
@@ -101,62 +109,70 @@ TEST_F(IfaceMgrTest, getIface) {
TEST_F(IfaceMgrTest, detectIfaces) {
- // test detects that interfaces can be detected
+ // test detects that interfaces can be detected
// there is no code for that now, but interfaces are
// read from file
- fstream fakeifaces("interfaces.txt", ios::out);
+ fstream fakeifaces("interfaces.txt", ios::out|ios::trunc);
fakeifaces << "eth0 fe80::1234";
fakeifaces.close();
-
+
// this is not usable on systems that don't have eth0
// interfaces. Nevertheless, this fake interface should
// be on list, but if_nametoindex() will fail.
-
- IfaceMgr & ifacemgr = IfaceMgr::instance();
-
- ASSERT_TRUE( ifacemgr.getIface("eth0") != NULL );
-
- IfaceMgr::Iface * eth0 = ifacemgr.getIface("eth0");
-
+
+ NakedIfaceMgr * ifacemgr = new NakedIfaceMgr();
+
+ ASSERT_TRUE( ifacemgr->getIface("eth0") != NULL );
+
+ IfaceMgr::Iface * eth0 = ifacemgr->getIface("eth0");
+
// 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() );
+
+ delete ifacemgr;
}
TEST_F(IfaceMgrTest, sockets) {
// testing socket operation in a portable way is tricky
// without interface detection implemented
- IfaceMgr & ifacemgr = IfaceMgr::instance();
+ NakedIfaceMgr * ifacemgr = new NakedIfaceMgr();
- Addr6 loAddr("::1", true);
+ IOAddress loAddr("::1");
// bind multicast socket to port 10547
- int socket1 = ifacemgr.openSocket("lo", loAddr, 10547, true);
+ int socket1 = ifacemgr->openSocket("lo", loAddr, 10547, true);
EXPECT_GT(socket1, 0); // socket > 0
// bind unicast socket to port 10548
- int socket2 = ifacemgr.openSocket("lo", loAddr, 10548, false);
+ int socket2 = ifacemgr->openSocket("lo", loAddr, 10548, false);
EXPECT_GT(socket2, 0);
// good to check that both sockets can be opened at once
close(socket1);
close(socket2);
+
+ delete ifacemgr;
}
TEST_F(IfaceMgrTest, sendReceive) {
// testing socket operation in a portable way is tricky
// without interface detection implemented
+ fstream fakeifaces("interfaces.txt", ios::out|ios::trunc);
+ fakeifaces << "lo ::1";
+ fakeifaces.close();
+
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);
@@ -167,14 +183,14 @@ TEST_F(IfaceMgrTest, sendReceive) {
// prepare dummy payload
for (int i=0;i<128; i++) {
- sendPkt.data_[i] = i;
+ sendPkt.data_[i] = i;
}
sendPkt.remote_port_ = 10547;
- sendPkt.remote_addr_ = Addr6("::1", true);
+ sendPkt.remote_addr_ = IOAddress("::1");
sendPkt.ifindex_ = 1;
sendPkt.iface_ = "lo";
-
+
Pkt6 * rcvPkt;
EXPECT_EQ(true, ifacemgr->send(sendPkt));
@@ -185,7 +201,8 @@ TEST_F(IfaceMgrTest, sendReceive) {
// let's check that we received what was sent
EXPECT_EQ(sendPkt.data_len_, rcvPkt->data_len_);
- EXPECT_EQ(0, memcmp(sendPkt.data_, rcvPkt->data_, rcvPkt->data_len_) );
+ EXPECT_EQ(0, memcmp(&sendPkt.data_[0], &rcvPkt->data_[0],
+ rcvPkt->data_len_) );
EXPECT_EQ(sendPkt.remote_addr_, rcvPkt->remote_addr_);
EXPECT_EQ(rcvPkt->remote_port_, 10546);
diff --git a/src/bin/dhcp6/tests/pkt6_unittest.cc b/src/bin/dhcp6/tests/pkt6_unittest.cc
index 0fa393b..5054c45 100644
--- a/src/bin/dhcp6/tests/pkt6_unittest.cc
+++ b/src/bin/dhcp6/tests/pkt6_unittest.cc
@@ -38,16 +38,7 @@ TEST_F(Pkt6Test, constructor) {
ASSERT_EQ(pkt1->data_len_, 17);
- char * buf = new char[23];
- // can't use char buf[23], as Pkt6 takes ownership of the data
-
- Pkt6 * pkt2 = new Pkt6(buf, 23);
-
- ASSERT_EQ(pkt2->data_len_, 23);
- ASSERT_EQ(pkt2->data_, buf);
-
delete pkt1;
- delete pkt2;
}
}
diff --git a/src/lib/asiolink/io_address.cc b/src/lib/asiolink/io_address.cc
index 7f7a6fc..7e2f5d4 100644
--- a/src/lib/asiolink/io_address.cc
+++ b/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
diff --git a/src/lib/asiolink/io_address.h b/src/lib/asiolink/io_address.h
index 655b727..1b488fa 100644
--- a/src/lib/asiolink/io_address.h
+++ b/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.
More information about the bind10-changes
mailing list