2011-06-30 14:06:07 +02:00
|
|
|
// 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 <fstream>
|
|
|
|
#include <sstream>
|
|
|
|
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
|
2011-11-30 15:32:40 +01:00
|
|
|
#include <asiolink/io_address.h>
|
|
|
|
#include <dhcp/pkt6.h>
|
|
|
|
#include <dhcp/iface_mgr.h>
|
2011-11-09 14:41:25 +01:00
|
|
|
#include <dhcp/dhcp4.h>
|
2011-06-30 14:06:07 +02:00
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
using namespace isc;
|
2011-08-18 15:20:26 +02:00
|
|
|
using namespace isc::asiolink;
|
2011-10-11 16:43:30 +02:00
|
|
|
using namespace isc::dhcp;
|
2011-06-30 14:06:07 +02:00
|
|
|
|
2011-09-05 20:45:39 +02:00
|
|
|
// name of loopback interface detection
|
|
|
|
char LOOPBACK[32] = "lo";
|
2011-08-31 19:12:55 +02:00
|
|
|
|
2011-08-04 22:11:10 +02:00
|
|
|
namespace {
|
2011-10-06 15:56:56 -07:00
|
|
|
const char* const INTERFACE_FILE = TEST_DATA_BUILDDIR "/interfaces.txt";
|
|
|
|
|
2011-06-30 14:06:07 +02:00
|
|
|
class NakedIfaceMgr: public IfaceMgr {
|
2011-08-18 17:59:12 +02:00
|
|
|
// "naked" Interface Manager, exposes internal fields
|
2011-06-30 14:06:07 +02:00
|
|
|
public:
|
|
|
|
NakedIfaceMgr() { }
|
2011-11-08 18:32:18 +01:00
|
|
|
IfaceCollection & getIfacesLst() { return ifaces_; }
|
2011-06-30 14:06:07 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
// dummy class for now, but this will be expanded when needed
|
|
|
|
class IfaceMgrTest : public ::testing::Test {
|
|
|
|
public:
|
|
|
|
IfaceMgrTest() {
|
|
|
|
}
|
2011-11-08 18:51:51 +01:00
|
|
|
|
|
|
|
void createLoInterfacesTxt() {
|
|
|
|
unlink(INTERFACE_FILE);
|
|
|
|
fstream fakeifaces(INTERFACE_FILE, ios::out|ios::trunc);
|
|
|
|
fakeifaces << LOOPBACK << " ::1";
|
|
|
|
fakeifaces.close();
|
|
|
|
}
|
2011-06-30 14:06:07 +02:00
|
|
|
};
|
|
|
|
|
2011-09-05 20:45:39 +02:00
|
|
|
// We need some known interface to work reliably. Loopback interface
|
|
|
|
// is named lo on Linux and lo0 on BSD boxes. We need to find out
|
|
|
|
// which is available. This is not a real test, but rather a workaround
|
|
|
|
// that will go away when interface detection is implemented.
|
2011-10-11 16:43:30 +02:00
|
|
|
|
|
|
|
// NOTE: At this stage of development, write access to current directory
|
|
|
|
// during running tests is required.
|
2011-09-05 20:45:39 +02:00
|
|
|
TEST_F(IfaceMgrTest, loDetect) {
|
|
|
|
|
2011-10-28 12:13:53 +02:00
|
|
|
// poor man's interface detection
|
2011-09-05 20:45:39 +02:00
|
|
|
// it will go away as soon as proper interface detection
|
|
|
|
// is implemented
|
2011-10-28 12:13:53 +02:00
|
|
|
if (if_nametoindex("lo")>0) {
|
2011-09-05 20:45:39 +02:00
|
|
|
cout << "This is Linux, using lo as loopback." << endl;
|
2011-10-28 12:13:53 +02:00
|
|
|
sprintf(LOOPBACK, "lo");
|
|
|
|
} else if (if_nametoindex("lo0")>0) {
|
|
|
|
cout << "This is BSD, using lo0 as loopback." << endl;
|
|
|
|
sprintf(LOOPBACK, "lo0");
|
2011-09-05 20:45:39 +02:00
|
|
|
} else {
|
2011-10-28 12:13:53 +02:00
|
|
|
cout << "Failed to detect loopback interface. Neither "
|
|
|
|
<< "lo or lo0 worked. I give up." << endl;
|
|
|
|
ASSERT_TRUE(false);
|
2011-09-05 20:45:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-08-23 21:21:11 +02:00
|
|
|
// uncomment this test to create packet writer. It will
|
|
|
|
// write incoming DHCPv6 packets as C arrays. That is useful
|
|
|
|
// for generating test sequences based on actual traffic
|
|
|
|
//
|
|
|
|
// TODO: this potentially should be moved to a separate tool
|
|
|
|
//
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
TEST_F(IfaceMgrTest, dhcp6Sniffer) {
|
|
|
|
// testing socket operation in a portable way is tricky
|
|
|
|
// without interface detection implemented
|
|
|
|
|
|
|
|
unlink("interfaces.txt");
|
|
|
|
|
|
|
|
ofstream interfaces("interfaces.txt", ios::ate);
|
|
|
|
interfaces << "eth0 fe80::21e:8cff:fe9b:7349";
|
|
|
|
interfaces.close();
|
|
|
|
|
2011-12-14 18:32:41 +01:00
|
|
|
NakedIfaceMgr* ifacemgr = new NakedIfaceMgr();
|
2011-08-23 21:21:11 +02:00
|
|
|
|
2011-12-14 18:32:41 +01:00
|
|
|
Pkt6* pkt = NULL;
|
2011-08-23 21:21:11 +02:00
|
|
|
int cnt = 0;
|
|
|
|
cout << "---8X-----------------------------------------" << endl;
|
|
|
|
while (true) {
|
|
|
|
pkt = ifacemgr->receive();
|
2011-08-31 19:12:55 +02:00
|
|
|
|
2011-11-08 18:32:18 +01:00
|
|
|
cout << "// this code is autogenerated. Do NOT edit." << endl;
|
2011-08-23 21:21:11 +02:00
|
|
|
cout << "// Received " << pkt->data_len_ << " bytes packet:" << endl;
|
|
|
|
cout << "Pkt6 *capture" << cnt++ << "() {" << endl;
|
|
|
|
cout << " Pkt6* pkt;" << endl;
|
|
|
|
cout << " pkt = new Pkt6(" << pkt->data_len_ << ");" << endl;
|
|
|
|
cout << " pkt->remote_port_ = " << pkt-> remote_port_ << ";" << endl;
|
2011-08-31 19:12:55 +02:00
|
|
|
cout << " pkt->remote_addr_ = IOAddress(\""
|
|
|
|
<< pkt->remote_addr_.toText() << "\");" << endl;
|
2011-08-23 21:21:11 +02:00
|
|
|
cout << " pkt->local_port_ = " << pkt-> local_port_ << ";" << endl;
|
2011-08-31 19:12:55 +02:00
|
|
|
cout << " pkt->local_addr_ = IOAddress(\""
|
|
|
|
<< pkt->local_addr_.toText() << "\");" << endl;
|
2011-08-23 21:21:11 +02:00
|
|
|
cout << " pkt->ifindex_ = " << pkt->ifindex_ << ";" << endl;
|
|
|
|
cout << " pkt->iface_ = \"" << pkt->iface_ << "\";" << endl;
|
2011-10-12 17:03:23 +02:00
|
|
|
|
|
|
|
// TODO it is better to declare an array and then memcpy it to
|
|
|
|
// packet.
|
2011-08-23 21:21:11 +02:00
|
|
|
for (int i=0; i< pkt->data_len_; i++) {
|
2011-08-31 19:12:55 +02:00
|
|
|
cout << " pkt->data_[" << i << "]="
|
|
|
|
<< (int)(unsigned char)pkt->data_[i] << "; ";
|
2011-08-23 21:21:11 +02:00
|
|
|
if (!(i%4))
|
|
|
|
cout << endl;
|
|
|
|
}
|
|
|
|
cout << endl;
|
|
|
|
cout << " return (pkt);" << endl;
|
|
|
|
cout << "}" << endl << endl;
|
|
|
|
|
|
|
|
delete pkt;
|
|
|
|
}
|
|
|
|
cout << "---8X-----------------------------------------" << endl;
|
2011-08-31 19:12:55 +02:00
|
|
|
|
2011-08-23 21:21:11 +02:00
|
|
|
// never happens. Infinite loop is infinite
|
|
|
|
delete pkt;
|
|
|
|
delete ifacemgr;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2011-06-30 14:06:07 +02:00
|
|
|
TEST_F(IfaceMgrTest, basic) {
|
|
|
|
// checks that IfaceManager can be instantiated
|
|
|
|
|
|
|
|
IfaceMgr & ifacemgr = IfaceMgr::instance();
|
|
|
|
ASSERT_TRUE(&ifacemgr != 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(IfaceMgrTest, ifaceClass) {
|
|
|
|
// basic tests for Iface inner class
|
|
|
|
|
2011-12-14 18:32:41 +01:00
|
|
|
IfaceMgr::Iface* iface = new IfaceMgr::Iface("eth5", 7);
|
2011-06-30 14:06:07 +02:00
|
|
|
|
|
|
|
EXPECT_STREQ("eth5/7", iface->getFullName().c_str());
|
|
|
|
|
|
|
|
delete iface;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2011-08-31 19:12:55 +02:00
|
|
|
// TODO: Implement getPlainMac() test as soon as interface detection
|
|
|
|
// is implemented.
|
2011-06-30 14:06:07 +02:00
|
|
|
TEST_F(IfaceMgrTest, getIface) {
|
|
|
|
|
|
|
|
cout << "Interface checks. Please ignore socket binding errors." << endl;
|
2011-12-14 18:32:41 +01:00
|
|
|
NakedIfaceMgr* ifacemgr = new NakedIfaceMgr();
|
2011-06-30 14:06:07 +02:00
|
|
|
|
|
|
|
// interface name, ifindex
|
2011-08-31 19:12:55 +02:00
|
|
|
IfaceMgr::Iface iface1("lo1", 1);
|
2011-06-30 14:06:07 +02:00
|
|
|
IfaceMgr::Iface iface2("eth5", 2);
|
|
|
|
IfaceMgr::Iface iface3("en3", 5);
|
|
|
|
IfaceMgr::Iface iface4("e1000g0", 3);
|
|
|
|
|
2011-08-31 19:12:55 +02:00
|
|
|
// note: real interfaces may be detected as well
|
2011-06-30 14:06:07 +02:00
|
|
|
ifacemgr->getIfacesLst().push_back(iface1);
|
|
|
|
ifacemgr->getIfacesLst().push_back(iface2);
|
|
|
|
ifacemgr->getIfacesLst().push_back(iface3);
|
|
|
|
ifacemgr->getIfacesLst().push_back(iface4);
|
|
|
|
|
2011-08-31 19:12:55 +02:00
|
|
|
cout << "There are " << ifacemgr->getIfacesLst().size()
|
|
|
|
<< " interfaces." << endl;
|
2011-11-08 18:32:18 +01:00
|
|
|
for (IfaceMgr::IfaceCollection::iterator iface=ifacemgr->getIfacesLst().begin();
|
2011-08-31 19:12:55 +02:00
|
|
|
iface != ifacemgr->getIfacesLst().end();
|
|
|
|
++iface) {
|
2011-11-08 18:32:18 +01:00
|
|
|
cout << " " << iface->getFullName() << endl;
|
2011-08-31 19:12:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-06-30 14:06:07 +02:00
|
|
|
// check that interface can be retrieved by ifindex
|
2011-12-14 18:32:41 +01:00
|
|
|
IfaceMgr::Iface* tmp = ifacemgr->getIface(5);
|
2011-06-30 14:06:07 +02:00
|
|
|
// ASSERT_NE(NULL, tmp); is not supported. hmmmm.
|
|
|
|
ASSERT_TRUE( tmp != NULL );
|
|
|
|
|
2011-11-08 18:32:18 +01:00
|
|
|
EXPECT_EQ( "en3", tmp->getName() );
|
|
|
|
EXPECT_EQ(5, tmp->getIndex());
|
2011-06-30 14:06:07 +02:00
|
|
|
|
|
|
|
// check that interface can be retrieved by name
|
2011-08-31 19:12:55 +02:00
|
|
|
tmp = ifacemgr->getIface("lo1");
|
2011-06-30 14:06:07 +02:00
|
|
|
ASSERT_TRUE( tmp != NULL );
|
|
|
|
|
2011-11-08 18:32:18 +01:00
|
|
|
EXPECT_EQ( "lo1", tmp->getName() );
|
|
|
|
EXPECT_EQ(1, tmp->getIndex());
|
2011-06-30 14:06:07 +02:00
|
|
|
|
|
|
|
// check that non-existing interfaces are not returned
|
2011-10-07 19:42:25 +02:00
|
|
|
EXPECT_EQ(static_cast<void*>(NULL), ifacemgr->getIface("wifi0") );
|
2011-06-30 14:06:07 +02:00
|
|
|
|
|
|
|
delete ifacemgr;
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(IfaceMgrTest, detectIfaces) {
|
|
|
|
|
2011-08-18 17:59:12 +02:00
|
|
|
// test detects that interfaces can be detected
|
2011-06-30 14:06:07 +02:00
|
|
|
// there is no code for that now, but interfaces are
|
|
|
|
// read from file
|
2011-10-06 15:56:56 -07:00
|
|
|
fstream fakeifaces(INTERFACE_FILE, ios::out|ios::trunc);
|
2011-06-30 14:06:07 +02:00
|
|
|
fakeifaces << "eth0 fe80::1234";
|
|
|
|
fakeifaces.close();
|
2011-08-18 17:59:12 +02:00
|
|
|
|
2011-06-30 14:06:07 +02:00
|
|
|
// 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.
|
2011-08-18 17:59:12 +02:00
|
|
|
|
2011-12-14 18:32:41 +01:00
|
|
|
NakedIfaceMgr* ifacemgr = new NakedIfaceMgr();
|
2011-08-18 17:59:12 +02:00
|
|
|
|
2011-08-18 18:17:47 +02:00
|
|
|
ASSERT_TRUE( ifacemgr->getIface("eth0") != NULL );
|
2011-08-18 17:59:12 +02:00
|
|
|
|
2011-12-14 18:32:41 +01:00
|
|
|
IfaceMgr::Iface* eth0 = ifacemgr->getIface("eth0");
|
2011-08-18 17:59:12 +02:00
|
|
|
|
2011-06-30 14:06:07 +02:00
|
|
|
// there should be one address
|
2011-11-08 18:32:18 +01:00
|
|
|
IfaceMgr::AddressCollection addrs = eth0->getAddresses();
|
|
|
|
ASSERT_EQ(1, addrs.size());
|
2011-08-18 17:59:12 +02:00
|
|
|
|
2011-11-08 18:32:18 +01:00
|
|
|
IOAddress addr = *addrs.begin();
|
2011-08-18 17:59:12 +02:00
|
|
|
|
2011-11-08 18:32:18 +01:00
|
|
|
EXPECT_STREQ( "fe80::1234", addr.toText().c_str() );
|
2011-08-18 18:17:47 +02:00
|
|
|
|
|
|
|
delete ifacemgr;
|
2011-12-14 18:32:41 +01:00
|
|
|
unlink(INTERFACE_FILE);
|
2011-06-30 14:06:07 +02:00
|
|
|
}
|
|
|
|
|
2011-11-08 18:51:51 +01:00
|
|
|
TEST_F(IfaceMgrTest, sockets6) {
|
2011-06-30 14:06:07 +02:00
|
|
|
// testing socket operation in a portable way is tricky
|
|
|
|
// without interface detection implemented
|
|
|
|
|
2011-11-08 18:51:51 +01:00
|
|
|
createLoInterfacesTxt();
|
|
|
|
|
2011-12-14 18:32:41 +01:00
|
|
|
NakedIfaceMgr* ifacemgr = new NakedIfaceMgr();
|
2011-06-30 14:06:07 +02:00
|
|
|
|
2011-08-18 15:20:26 +02:00
|
|
|
IOAddress loAddr("::1");
|
2011-06-30 14:06:07 +02:00
|
|
|
|
2011-11-09 19:57:51 +01:00
|
|
|
Pkt6 pkt6(128);
|
|
|
|
pkt6.iface_ = LOOPBACK;
|
|
|
|
|
2011-06-30 14:06:07 +02:00
|
|
|
// bind multicast socket to port 10547
|
2011-08-31 19:12:55 +02:00
|
|
|
int socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, 10547);
|
2011-06-30 14:06:07 +02:00
|
|
|
EXPECT_GT(socket1, 0); // socket > 0
|
|
|
|
|
2011-11-09 19:57:51 +01:00
|
|
|
EXPECT_EQ(socket1, ifacemgr->getSocket(pkt6));
|
|
|
|
|
2011-06-30 14:06:07 +02:00
|
|
|
// bind unicast socket to port 10548
|
2011-08-31 19:12:55 +02:00
|
|
|
int socket2 = ifacemgr->openSocket(LOOPBACK, loAddr, 10548);
|
2011-08-18 19:36:31 +02:00
|
|
|
EXPECT_GT(socket2, 0);
|
|
|
|
|
2011-11-30 19:37:22 +01:00
|
|
|
// removed code for binding socket twice to the same address/port
|
|
|
|
// as it caused problems on some platforms (e.g. Mac OS X)
|
2011-08-18 19:36:31 +02:00
|
|
|
|
|
|
|
close(socket1);
|
|
|
|
close(socket2);
|
|
|
|
|
|
|
|
delete ifacemgr;
|
2011-12-14 18:32:41 +01:00
|
|
|
unlink(INTERFACE_FILE);
|
2011-08-18 19:36:31 +02:00
|
|
|
}
|
|
|
|
|
2011-10-07 21:35:10 +00:00
|
|
|
// TODO: disabled due to other naming on various systems
|
|
|
|
// (lo in Linux, lo0 in BSD systems)
|
2011-11-09 14:41:25 +01:00
|
|
|
TEST_F(IfaceMgrTest, DISABLED_sockets6Mcast) {
|
2011-08-18 19:36:31 +02:00
|
|
|
// testing socket operation in a portable way is tricky
|
|
|
|
// without interface detection implemented
|
|
|
|
|
2011-12-14 18:32:41 +01:00
|
|
|
NakedIfaceMgr* ifacemgr = new NakedIfaceMgr();
|
2011-08-18 19:36:31 +02:00
|
|
|
|
|
|
|
IOAddress loAddr("::1");
|
|
|
|
IOAddress mcastAddr("ff02::1:2");
|
|
|
|
|
|
|
|
// bind multicast socket to port 10547
|
2011-08-31 19:12:55 +02:00
|
|
|
int socket1 = ifacemgr->openSocket(LOOPBACK, mcastAddr, 10547);
|
2011-08-18 19:36:31 +02:00
|
|
|
EXPECT_GT(socket1, 0); // socket > 0
|
|
|
|
|
|
|
|
// expect success. This address/port is already bound, but
|
|
|
|
// we are using SO_REUSEADDR, so we can bind it twice
|
2011-08-31 19:12:55 +02:00
|
|
|
int socket2 = ifacemgr->openSocket(LOOPBACK, mcastAddr, 10547);
|
2011-06-30 14:06:07 +02:00
|
|
|
EXPECT_GT(socket2, 0);
|
|
|
|
|
2011-08-18 19:36:31 +02:00
|
|
|
// there's no good way to test negative case here.
|
|
|
|
// we would need non-multicast interface. We will be able
|
|
|
|
// to iterate thru available interfaces and check if there
|
|
|
|
// are interfaces without multicast-capable flag.
|
2011-06-30 14:06:07 +02:00
|
|
|
|
|
|
|
close(socket1);
|
|
|
|
close(socket2);
|
2011-08-18 17:59:12 +02:00
|
|
|
|
|
|
|
delete ifacemgr;
|
2011-06-30 14:06:07 +02:00
|
|
|
}
|
|
|
|
|
2011-11-08 18:51:51 +01:00
|
|
|
TEST_F(IfaceMgrTest, sendReceive6) {
|
2011-11-09 19:57:51 +01:00
|
|
|
|
2011-06-30 14:06:07 +02:00
|
|
|
// testing socket operation in a portable way is tricky
|
|
|
|
// without interface detection implemented
|
2011-11-09 19:57:51 +01:00
|
|
|
createLoInterfacesTxt();
|
2011-06-30 14:06:07 +02:00
|
|
|
|
2011-11-09 14:41:25 +01:00
|
|
|
NakedIfaceMgr* ifacemgr = new NakedIfaceMgr();
|
2011-06-30 14:06:07 +02:00
|
|
|
|
|
|
|
// let's assume that every supported OS have lo interface
|
2011-08-18 15:20:26 +02:00
|
|
|
IOAddress loAddr("::1");
|
2011-11-09 14:41:25 +01:00
|
|
|
int socket1 = 0, socket2 = 0;
|
|
|
|
EXPECT_NO_THROW(
|
|
|
|
socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, 10547);
|
|
|
|
socket2 = ifacemgr->openSocket(LOOPBACK, loAddr, 10546);
|
|
|
|
);
|
2011-06-30 14:06:07 +02:00
|
|
|
|
2011-08-24 20:36:35 +02:00
|
|
|
boost::shared_ptr<Pkt6> sendPkt(new Pkt6(128) );
|
2011-06-30 14:06:07 +02:00
|
|
|
|
|
|
|
// prepare dummy payload
|
|
|
|
for (int i=0;i<128; i++) {
|
2011-08-24 20:36:35 +02:00
|
|
|
sendPkt->data_[i] = i;
|
2011-06-30 14:06:07 +02:00
|
|
|
}
|
|
|
|
|
2011-08-24 20:36:35 +02:00
|
|
|
sendPkt->remote_port_ = 10547;
|
|
|
|
sendPkt->remote_addr_ = IOAddress("::1");
|
|
|
|
sendPkt->ifindex_ = 1;
|
2011-08-31 19:12:55 +02:00
|
|
|
sendPkt->iface_ = LOOPBACK;
|
2011-08-18 17:59:12 +02:00
|
|
|
|
2011-08-24 20:36:35 +02:00
|
|
|
boost::shared_ptr<Pkt6> rcvPkt;
|
2011-06-30 14:06:07 +02:00
|
|
|
|
|
|
|
EXPECT_EQ(true, ifacemgr->send(sendPkt));
|
|
|
|
|
2011-11-08 18:32:18 +01:00
|
|
|
rcvPkt = ifacemgr->receive6();
|
2011-06-30 14:06:07 +02:00
|
|
|
|
2011-10-11 16:43:30 +02:00
|
|
|
ASSERT_TRUE( rcvPkt ); // received our own packet
|
2011-06-30 14:06:07 +02:00
|
|
|
|
|
|
|
// let's check that we received what was sent
|
2011-08-24 20:36:35 +02:00
|
|
|
EXPECT_EQ(sendPkt->data_len_, rcvPkt->data_len_);
|
|
|
|
EXPECT_EQ(0, memcmp(&sendPkt->data_[0], &rcvPkt->data_[0],
|
2011-08-18 17:59:12 +02:00
|
|
|
rcvPkt->data_len_) );
|
2011-06-30 14:06:07 +02:00
|
|
|
|
2011-08-24 20:36:35 +02:00
|
|
|
EXPECT_EQ(sendPkt->remote_addr_.toText(), rcvPkt->remote_addr_.toText());
|
2011-11-09 19:57:51 +01:00
|
|
|
|
|
|
|
// since we opened 2 sockets on the same interface and none of them is multicast,
|
|
|
|
// none is preferred over the other for sending data, so we really should not
|
|
|
|
// assume the one or the other will always be choosen for sending data. Therefore
|
|
|
|
// we should accept both values as source ports.
|
|
|
|
EXPECT_TRUE( (rcvPkt->remote_port_ == 10546) || (rcvPkt->remote_port_ == 10547) );
|
2011-06-30 14:06:07 +02:00
|
|
|
|
|
|
|
delete ifacemgr;
|
2011-12-14 18:32:41 +01:00
|
|
|
unlink(INTERFACE_FILE);
|
2011-06-30 14:06:07 +02:00
|
|
|
}
|
|
|
|
|
2011-12-07 17:15:33 +01:00
|
|
|
TEST_F(IfaceMgrTest, sendReceive4) {
|
|
|
|
|
|
|
|
// testing socket operation in a portable way is tricky
|
|
|
|
// without interface detection implemented
|
|
|
|
createLoInterfacesTxt();
|
|
|
|
|
|
|
|
NakedIfaceMgr* ifacemgr = new NakedIfaceMgr();
|
|
|
|
|
|
|
|
// let's assume that every supported OS have lo interface
|
|
|
|
IOAddress loAddr("127.0.0.1");
|
|
|
|
int socket1 = 0, socket2 = 0;
|
|
|
|
EXPECT_NO_THROW(
|
|
|
|
socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, DHCP4_SERVER_PORT + 10000);
|
|
|
|
socket2 = ifacemgr->openSocket(LOOPBACK, loAddr, DHCP4_SERVER_PORT + 10000 + 1);
|
|
|
|
);
|
|
|
|
|
|
|
|
boost::shared_ptr<Pkt4> sendPkt(new Pkt4(DHCPDISCOVER, 1234) );
|
|
|
|
|
|
|
|
sendPkt->setLocalAddr(IOAddress("127.0.0.1"));
|
|
|
|
|
|
|
|
sendPkt->setLocalPort(DHCP4_SERVER_PORT + 10000 + 1);
|
|
|
|
sendPkt->setRemotePort(DHCP4_SERVER_PORT + 10000);
|
|
|
|
sendPkt->setRemoteAddr(IOAddress("127.0.0.1"));
|
|
|
|
sendPkt->setIndex(1);
|
|
|
|
sendPkt->setIface(string(LOOPBACK));
|
|
|
|
sendPkt->setHops(6);
|
|
|
|
sendPkt->setSecs(42);
|
|
|
|
sendPkt->setCiaddr(IOAddress("192.0.2.1"));
|
|
|
|
sendPkt->setSiaddr(IOAddress("192.0.2.2"));
|
|
|
|
sendPkt->setYiaddr(IOAddress("192.0.2.3"));
|
|
|
|
sendPkt->setGiaddr(IOAddress("192.0.2.4"));
|
|
|
|
|
|
|
|
uint8_t sname[] = "That's just a string that will act as SNAME";
|
|
|
|
sendPkt->setSname(sname, strlen((const char*)sname));
|
|
|
|
uint8_t file[] = "/another/string/that/acts/as/a/file_name.txt";
|
|
|
|
sendPkt->setFile(file, strlen((const char*)file));
|
|
|
|
|
|
|
|
ASSERT_NO_THROW(
|
|
|
|
sendPkt->pack();
|
|
|
|
);
|
|
|
|
|
|
|
|
boost::shared_ptr<Pkt4> rcvPkt;
|
|
|
|
|
|
|
|
EXPECT_EQ(true, ifacemgr->send(sendPkt));
|
|
|
|
|
|
|
|
rcvPkt = ifacemgr->receive4();
|
|
|
|
|
|
|
|
ASSERT_TRUE( rcvPkt ); // received our own packet
|
|
|
|
|
|
|
|
ASSERT_NO_THROW(
|
|
|
|
rcvPkt->unpack();
|
|
|
|
);
|
|
|
|
|
|
|
|
// let's check that we received what was sent
|
|
|
|
EXPECT_EQ(sendPkt->len(), rcvPkt->len());
|
|
|
|
|
2011-12-07 17:45:57 +01:00
|
|
|
EXPECT_EQ("127.0.0.1", rcvPkt->getRemoteAddr().toText());
|
2011-12-07 17:15:33 +01:00
|
|
|
EXPECT_EQ(sendPkt->getRemotePort(), rcvPkt->getLocalPort());
|
|
|
|
|
|
|
|
// now let's check content
|
|
|
|
EXPECT_EQ(sendPkt->getHops(), rcvPkt->getHops());
|
|
|
|
EXPECT_EQ(sendPkt->getOp(), rcvPkt->getOp());
|
|
|
|
EXPECT_EQ(sendPkt->getSecs(), rcvPkt->getSecs());
|
|
|
|
EXPECT_EQ(sendPkt->getFlags(), rcvPkt->getFlags());
|
|
|
|
EXPECT_EQ(sendPkt->getCiaddr(), rcvPkt->getCiaddr());
|
|
|
|
EXPECT_EQ(sendPkt->getSiaddr(), rcvPkt->getSiaddr());
|
|
|
|
EXPECT_EQ(sendPkt->getYiaddr(), rcvPkt->getYiaddr());
|
|
|
|
EXPECT_EQ(sendPkt->getGiaddr(), rcvPkt->getGiaddr());
|
|
|
|
EXPECT_EQ(sendPkt->getTransid(), rcvPkt->getTransid());
|
|
|
|
EXPECT_EQ(sendPkt->getType(), rcvPkt->getType());
|
|
|
|
EXPECT_TRUE(sendPkt->getSname() == rcvPkt->getSname());
|
|
|
|
EXPECT_TRUE(sendPkt->getFile() == rcvPkt->getFile());
|
|
|
|
EXPECT_EQ(sendPkt->getHtype(), rcvPkt->getHtype());
|
|
|
|
EXPECT_EQ(sendPkt->getHlen(), rcvPkt->getHlen());
|
|
|
|
|
|
|
|
// since we opened 2 sockets on the same interface and none of them is multicast,
|
|
|
|
// none is preferred over the other for sending data, so we really should not
|
|
|
|
// assume the one or the other will always be choosen for sending data. We should
|
|
|
|
// skip checking source port of sent address.
|
|
|
|
|
|
|
|
delete ifacemgr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-09 14:41:25 +01:00
|
|
|
TEST_F(IfaceMgrTest, socket4) {
|
|
|
|
|
|
|
|
createLoInterfacesTxt();
|
|
|
|
NakedIfaceMgr* ifacemgr = new NakedIfaceMgr();
|
|
|
|
|
2011-11-30 18:12:05 +01:00
|
|
|
// Let's assume that every supported OS have lo interface.
|
2011-11-09 14:41:25 +01:00
|
|
|
IOAddress loAddr("127.0.0.1");
|
2011-11-30 18:12:05 +01:00
|
|
|
// Use unprivileged port (it's convenient for running tests as non-root).
|
2011-11-09 14:41:25 +01:00
|
|
|
int socket1 = 0;
|
|
|
|
|
|
|
|
EXPECT_NO_THROW(
|
|
|
|
socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, DHCP4_SERVER_PORT + 10000);
|
|
|
|
);
|
|
|
|
|
|
|
|
EXPECT_GT(socket1, 0);
|
|
|
|
|
2011-11-09 19:57:51 +01:00
|
|
|
Pkt4 pkt(DHCPDISCOVER, 1234);
|
|
|
|
pkt.setIface(LOOPBACK);
|
|
|
|
|
2011-11-30 18:12:05 +01:00
|
|
|
// Expect that we get the socket that we just opened.
|
2011-11-09 19:57:51 +01:00
|
|
|
EXPECT_EQ(socket1, ifacemgr->getSocket(pkt));
|
|
|
|
|
2011-11-09 14:41:25 +01:00
|
|
|
close(socket1);
|
|
|
|
|
|
|
|
delete ifacemgr;
|
2011-12-14 18:32:41 +01:00
|
|
|
unlink(INTERFACE_FILE);
|
2011-11-09 14:41:25 +01:00
|
|
|
}
|
|
|
|
|
2011-11-10 17:30:53 +01:00
|
|
|
// Test the Iface structure itself
|
|
|
|
TEST_F(IfaceMgrTest, iface) {
|
2011-12-14 18:32:41 +01:00
|
|
|
IfaceMgr::Iface* iface = NULL;
|
2011-11-10 17:30:53 +01:00
|
|
|
EXPECT_NO_THROW(
|
|
|
|
iface = new IfaceMgr::Iface("eth0",1);
|
|
|
|
);
|
|
|
|
|
|
|
|
EXPECT_EQ("eth0", iface->getName());
|
|
|
|
EXPECT_EQ(1, iface->getIndex());
|
|
|
|
EXPECT_EQ("eth0/1", iface->getFullName());
|
|
|
|
|
|
|
|
// Let's make a copy of this address collection.
|
|
|
|
IfaceMgr::AddressCollection addrs = iface->getAddresses();
|
|
|
|
|
|
|
|
EXPECT_EQ(0, addrs.size());
|
|
|
|
|
|
|
|
IOAddress addr1("192.0.2.6");
|
|
|
|
iface->addAddress(addr1);
|
|
|
|
|
|
|
|
addrs = iface->getAddresses();
|
|
|
|
ASSERT_EQ(1, addrs.size());
|
|
|
|
EXPECT_EQ("192.0.2.6", addrs.at(0).toText());
|
|
|
|
|
|
|
|
// No such address, should return false.
|
|
|
|
EXPECT_FALSE(iface->delAddress(IOAddress("192.0.8.9")));
|
|
|
|
|
|
|
|
// This address is present, delete it!
|
|
|
|
EXPECT_TRUE(iface->delAddress(IOAddress("192.0.2.6")));
|
|
|
|
|
|
|
|
// Not really necessary, previous reference still points to the same
|
|
|
|
// collection. Let's do it anyway, as test code may serve as example
|
|
|
|
// usage code as well.
|
|
|
|
addrs = iface->getAddresses();
|
|
|
|
|
|
|
|
EXPECT_EQ(0, addrs.size());
|
|
|
|
|
|
|
|
EXPECT_NO_THROW(
|
|
|
|
delete iface;
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(IfaceMgrTest, socketInfo) {
|
|
|
|
|
|
|
|
// check that socketinfo for IPv4 socket is functional
|
|
|
|
IfaceMgr::SocketInfo sock1(7, IOAddress("192.0.2.56"), DHCP4_SERVER_PORT + 7);
|
|
|
|
EXPECT_EQ(7, sock1.sockfd_);
|
|
|
|
EXPECT_EQ("192.0.2.56", sock1.addr_.toText());
|
|
|
|
EXPECT_EQ(AF_INET, sock1.family_);
|
|
|
|
EXPECT_EQ(DHCP4_SERVER_PORT + 7, sock1.port_);
|
|
|
|
|
|
|
|
// check that socketinfo for IPv6 socket is functional
|
|
|
|
IfaceMgr::SocketInfo sock2(9, IOAddress("2001:db8:1::56"), DHCP4_SERVER_PORT + 9);
|
|
|
|
EXPECT_EQ(9, sock2.sockfd_);
|
|
|
|
EXPECT_EQ("2001:db8:1::56", sock2.addr_.toText());
|
|
|
|
EXPECT_EQ(AF_INET6, sock2.family_);
|
|
|
|
EXPECT_EQ(DHCP4_SERVER_PORT + 9, sock2.port_);
|
|
|
|
|
|
|
|
// now let's test if IfaceMgr handles socket info properly
|
|
|
|
createLoInterfacesTxt();
|
2011-12-14 18:32:41 +01:00
|
|
|
NakedIfaceMgr* ifacemgr = new NakedIfaceMgr();
|
2011-11-10 17:30:53 +01:00
|
|
|
IfaceMgr::Iface* loopback = ifacemgr->getIface(LOOPBACK);
|
|
|
|
ASSERT_TRUE(loopback);
|
|
|
|
loopback->addSocket(sock1);
|
|
|
|
loopback->addSocket(sock2);
|
|
|
|
|
|
|
|
Pkt6 pkt6(100);
|
|
|
|
|
|
|
|
// pkt6 dos not have interface set yet
|
|
|
|
EXPECT_THROW(
|
|
|
|
ifacemgr->getSocket(pkt6),
|
|
|
|
BadValue
|
|
|
|
);
|
|
|
|
|
|
|
|
// try to send over non-existing interface
|
|
|
|
pkt6.iface_ = "nosuchinterface45";
|
|
|
|
EXPECT_THROW(
|
|
|
|
ifacemgr->getSocket(pkt6),
|
|
|
|
BadValue
|
|
|
|
);
|
|
|
|
|
|
|
|
// this will work
|
|
|
|
pkt6.iface_ = LOOPBACK;
|
|
|
|
EXPECT_EQ(9, ifacemgr->getSocket(pkt6));
|
|
|
|
|
|
|
|
bool deleted = false;
|
|
|
|
EXPECT_NO_THROW(
|
|
|
|
deleted = ifacemgr->getIface(LOOPBACK)->delSocket(9);
|
|
|
|
);
|
|
|
|
EXPECT_EQ(true, deleted);
|
|
|
|
|
|
|
|
// it should throw again, there's no usable socket anymore
|
|
|
|
EXPECT_THROW(
|
|
|
|
ifacemgr->getSocket(pkt6),
|
|
|
|
Unexpected
|
|
|
|
);
|
|
|
|
|
|
|
|
// repeat for pkt4
|
|
|
|
Pkt4 pkt4(DHCPDISCOVER, 1);
|
|
|
|
|
|
|
|
// pkt4 does not have interface set yet.
|
|
|
|
EXPECT_THROW(
|
|
|
|
ifacemgr->getSocket(pkt4),
|
|
|
|
BadValue
|
|
|
|
);
|
|
|
|
|
|
|
|
// Try to send over non-existing interface.
|
|
|
|
pkt4.setIface("nosuchinterface45");
|
|
|
|
EXPECT_THROW(
|
|
|
|
ifacemgr->getSocket(pkt4),
|
|
|
|
BadValue
|
|
|
|
);
|
|
|
|
|
|
|
|
// Socket info is set, packet has well defined interface. It should work.
|
|
|
|
pkt4.setIface(LOOPBACK);
|
|
|
|
EXPECT_EQ(7, ifacemgr->getSocket(pkt4));
|
|
|
|
|
|
|
|
EXPECT_NO_THROW(
|
|
|
|
ifacemgr->getIface(LOOPBACK)->delSocket(7);
|
|
|
|
);
|
|
|
|
|
|
|
|
// It should throw again, there's no usable socket anymore.
|
|
|
|
EXPECT_THROW(
|
|
|
|
ifacemgr->getSocket(pkt4),
|
|
|
|
Unexpected
|
|
|
|
);
|
2011-06-30 14:06:07 +02:00
|
|
|
|
|
|
|
delete ifacemgr;
|
2011-12-14 18:32:41 +01:00
|
|
|
unlink(INTERFACE_FILE);
|
2011-06-30 14:06:07 +02:00
|
|
|
}
|
|
|
|
|
2011-08-04 22:11:10 +02:00
|
|
|
}
|