iface_mgr_unittest.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. // Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <config.h>
  15. #include <iostream>
  16. #include <fstream>
  17. #include <sstream>
  18. #include <arpa/inet.h>
  19. #include <gtest/gtest.h>
  20. #include "io_address.h"
  21. #include "dhcp/pkt6.h"
  22. #include "dhcp6/iface_mgr.h"
  23. using namespace std;
  24. using namespace isc;
  25. using namespace isc::asiolink;
  26. // name of loopback interface detection
  27. char LOOPBACK[32] = "lo";
  28. namespace {
  29. const char* const INTERFACE_FILE = TEST_DATA_BUILDDIR "/interfaces.txt";
  30. class NakedIfaceMgr: public IfaceMgr {
  31. // "naked" Interface Manager, exposes internal fields
  32. public:
  33. NakedIfaceMgr() { }
  34. IfaceLst & getIfacesLst() { return ifaces_; }
  35. void setSendSock(int sock) { sendsock_ = sock; }
  36. void setRecvSock(int sock) { recvsock_ = sock; }
  37. int openSocket(const std::string& ifname,
  38. const isc::asiolink::IOAddress& addr,
  39. int port) {
  40. return IfaceMgr::openSocket(ifname, addr, port);
  41. }
  42. };
  43. // dummy class for now, but this will be expanded when needed
  44. class IfaceMgrTest : public ::testing::Test {
  45. public:
  46. IfaceMgrTest() {
  47. }
  48. };
  49. // We need some known interface to work reliably. Loopback interface
  50. // is named lo on Linux and lo0 on BSD boxes. We need to find out
  51. // which is available. This is not a real test, but rather a workaround
  52. // that will go away when interface detection is implemented.
  53. TEST_F(IfaceMgrTest, loDetect) {
  54. unlink("interfaces.txt");
  55. ofstream interfaces("interfaces.txt", ios::ate);
  56. interfaces << "lo ::1";
  57. interfaces.close();
  58. NakedIfaceMgr * ifacemgr = new NakedIfaceMgr();
  59. IOAddress loAddr("::1");
  60. IOAddress mcastAddr("ff02::1:2");
  61. // bind multicast socket to port 10547
  62. int socket1 = ifacemgr->openSocket("lo", mcastAddr, 10547);
  63. // this fails on BSD (there's no lo interface there)
  64. // poor man's interface dection
  65. // it will go away as soon as proper interface detection
  66. // is implemented
  67. if (socket1>0) {
  68. cout << "This is Linux, using lo as loopback." << endl;
  69. close(socket1);
  70. } else {
  71. // this fails on Linux and succeeds on BSD
  72. socket1 = ifacemgr->openSocket("lo0", mcastAddr, 10547);
  73. if (socket1>0) {
  74. sprintf(LOOPBACK, "lo0");
  75. cout << "This is BSD, using lo0 as loopback." << endl;
  76. close(socket1);
  77. } else {
  78. cout << "Failed to detect loopback interface. Neither "
  79. << "lo or lo0 worked. I give up." << endl;
  80. ASSERT_TRUE(false);
  81. }
  82. }
  83. delete ifacemgr;
  84. }
  85. // uncomment this test to create packet writer. It will
  86. // write incoming DHCPv6 packets as C arrays. That is useful
  87. // for generating test sequences based on actual traffic
  88. //
  89. // TODO: this potentially should be moved to a separate tool
  90. //
  91. #if 0
  92. TEST_F(IfaceMgrTest, dhcp6Sniffer) {
  93. // testing socket operation in a portable way is tricky
  94. // without interface detection implemented
  95. unlink("interfaces.txt");
  96. ofstream interfaces("interfaces.txt", ios::ate);
  97. interfaces << "eth0 fe80::21e:8cff:fe9b:7349";
  98. interfaces.close();
  99. NakedIfaceMgr * ifacemgr = new NakedIfaceMgr();
  100. Pkt6 * pkt = 0;
  101. int cnt = 0;
  102. cout << "---8X-----------------------------------------" << endl;
  103. while (true) {
  104. pkt = ifacemgr->receive();
  105. cout << "// Received " << pkt->data_len_ << " bytes packet:" << endl;
  106. cout << "Pkt6 *capture" << cnt++ << "() {" << endl;
  107. cout << " Pkt6* pkt;" << endl;
  108. cout << " pkt = new Pkt6(" << pkt->data_len_ << ");" << endl;
  109. cout << " pkt->remote_port_ = " << pkt-> remote_port_ << ";" << endl;
  110. cout << " pkt->remote_addr_ = IOAddress(\""
  111. << pkt->remote_addr_.toText() << "\");" << endl;
  112. cout << " pkt->local_port_ = " << pkt-> local_port_ << ";" << endl;
  113. cout << " pkt->local_addr_ = IOAddress(\""
  114. << pkt->local_addr_.toText() << "\");" << endl;
  115. cout << " pkt->ifindex_ = " << pkt->ifindex_ << ";" << endl;
  116. cout << " pkt->iface_ = \"" << pkt->iface_ << "\";" << endl;
  117. for (int i=0; i< pkt->data_len_; i++) {
  118. cout << " pkt->data_[" << i << "]="
  119. << (int)(unsigned char)pkt->data_[i] << "; ";
  120. if (!(i%4))
  121. cout << endl;
  122. }
  123. cout << endl;
  124. cout << " return (pkt);" << endl;
  125. cout << "}" << endl << endl;
  126. delete pkt;
  127. }
  128. cout << "---8X-----------------------------------------" << endl;
  129. // never happens. Infinite loop is infinite
  130. delete pkt;
  131. delete ifacemgr;
  132. }
  133. #endif
  134. TEST_F(IfaceMgrTest, basic) {
  135. // checks that IfaceManager can be instantiated
  136. IfaceMgr & ifacemgr = IfaceMgr::instance();
  137. ASSERT_TRUE(&ifacemgr != 0);
  138. }
  139. TEST_F(IfaceMgrTest, ifaceClass) {
  140. // basic tests for Iface inner class
  141. IfaceMgr::Iface * iface = new IfaceMgr::Iface("eth5", 7);
  142. EXPECT_STREQ("eth5/7", iface->getFullName().c_str());
  143. delete iface;
  144. }
  145. // TODO: Implement getPlainMac() test as soon as interface detection
  146. // is implemented.
  147. TEST_F(IfaceMgrTest, getIface) {
  148. cout << "Interface checks. Please ignore socket binding errors." << endl;
  149. NakedIfaceMgr * ifacemgr = new NakedIfaceMgr();
  150. // interface name, ifindex
  151. IfaceMgr::Iface iface1("lo1", 1);
  152. IfaceMgr::Iface iface2("eth5", 2);
  153. IfaceMgr::Iface iface3("en3", 5);
  154. IfaceMgr::Iface iface4("e1000g0", 3);
  155. // note: real interfaces may be detected as well
  156. ifacemgr->getIfacesLst().push_back(iface1);
  157. ifacemgr->getIfacesLst().push_back(iface2);
  158. ifacemgr->getIfacesLst().push_back(iface3);
  159. ifacemgr->getIfacesLst().push_back(iface4);
  160. cout << "There are " << ifacemgr->getIfacesLst().size()
  161. << " interfaces." << endl;
  162. for (IfaceMgr::IfaceLst::iterator iface=ifacemgr->getIfacesLst().begin();
  163. iface != ifacemgr->getIfacesLst().end();
  164. ++iface) {
  165. cout << " " << iface->name_ << "/" << iface->ifindex_ << endl;
  166. }
  167. // check that interface can be retrieved by ifindex
  168. IfaceMgr::Iface * tmp = ifacemgr->getIface(5);
  169. // ASSERT_NE(NULL, tmp); is not supported. hmmmm.
  170. ASSERT_TRUE( tmp != NULL );
  171. EXPECT_STREQ( "en3", tmp->name_.c_str() );
  172. EXPECT_EQ(5, tmp->ifindex_);
  173. // check that interface can be retrieved by name
  174. tmp = ifacemgr->getIface("lo1");
  175. ASSERT_TRUE( tmp != NULL );
  176. EXPECT_STREQ( "lo1", tmp->name_.c_str() );
  177. EXPECT_EQ(1, tmp->ifindex_);
  178. // check that non-existing interfaces are not returned
  179. EXPECT_EQ(static_cast<void*>(NULL), ifacemgr->getIface("wifi0") );
  180. delete ifacemgr;
  181. }
  182. TEST_F(IfaceMgrTest, detectIfaces) {
  183. // test detects that interfaces can be detected
  184. // there is no code for that now, but interfaces are
  185. // read from file
  186. fstream fakeifaces(INTERFACE_FILE, ios::out|ios::trunc);
  187. fakeifaces << "eth0 fe80::1234";
  188. fakeifaces.close();
  189. // this is not usable on systems that don't have eth0
  190. // interfaces. Nevertheless, this fake interface should
  191. // be on list, but if_nametoindex() will fail.
  192. NakedIfaceMgr * ifacemgr = new NakedIfaceMgr();
  193. ASSERT_TRUE( ifacemgr->getIface("eth0") != NULL );
  194. IfaceMgr::Iface * eth0 = ifacemgr->getIface("eth0");
  195. // there should be one address
  196. EXPECT_EQ(1, eth0->addrs_.size());
  197. IOAddress * addr = &(*eth0->addrs_.begin());
  198. ASSERT_TRUE( addr != NULL );
  199. EXPECT_STREQ( "fe80::1234", addr->toText().c_str() );
  200. delete ifacemgr;
  201. }
  202. // TODO: disabled due to other naming on various systems
  203. // (lo in Linux, lo0 in BSD systems)
  204. // Fix for this is available on 1186 branch, will reenable
  205. // this test once 1186 is merged
  206. TEST_F(IfaceMgrTest, DISABLED_sockets) {
  207. // testing socket operation in a portable way is tricky
  208. // without interface detection implemented
  209. NakedIfaceMgr * ifacemgr = new NakedIfaceMgr();
  210. IOAddress loAddr("::1");
  211. // bind multicast socket to port 10547
  212. int socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, 10547);
  213. EXPECT_GT(socket1, 0); // socket > 0
  214. // bind unicast socket to port 10548
  215. int socket2 = ifacemgr->openSocket(LOOPBACK, loAddr, 10548);
  216. EXPECT_GT(socket2, 0);
  217. // expect success. This address/port is already bound, but
  218. // we are using SO_REUSEADDR, so we can bind it twice
  219. int socket3 = ifacemgr->openSocket(LOOPBACK, loAddr, 10547);
  220. // rebinding succeeds on Linux, fails on BSD
  221. // TODO: add OS-specific defines here (or modify code to
  222. // behave the same way on all OSes, but that may not be
  223. // possible
  224. // EXPECT_GT(socket3, 0); // socket > 0
  225. // we now have 3 sockets open at the same time. Looks good.
  226. close(socket1);
  227. close(socket2);
  228. close(socket3);
  229. delete ifacemgr;
  230. }
  231. // TODO: disabled due to other naming on various systems
  232. // (lo in Linux, lo0 in BSD systems)
  233. TEST_F(IfaceMgrTest, DISABLED_socketsMcast) {
  234. // testing socket operation in a portable way is tricky
  235. // without interface detection implemented
  236. NakedIfaceMgr * ifacemgr = new NakedIfaceMgr();
  237. IOAddress loAddr("::1");
  238. IOAddress mcastAddr("ff02::1:2");
  239. // bind multicast socket to port 10547
  240. int socket1 = ifacemgr->openSocket(LOOPBACK, mcastAddr, 10547);
  241. EXPECT_GT(socket1, 0); // socket > 0
  242. // expect success. This address/port is already bound, but
  243. // we are using SO_REUSEADDR, so we can bind it twice
  244. int socket2 = ifacemgr->openSocket(LOOPBACK, mcastAddr, 10547);
  245. EXPECT_GT(socket2, 0);
  246. // there's no good way to test negative case here.
  247. // we would need non-multicast interface. We will be able
  248. // to iterate thru available interfaces and check if there
  249. // are interfaces without multicast-capable flag.
  250. close(socket1);
  251. close(socket2);
  252. delete ifacemgr;
  253. }
  254. // TODO: disabled due to other naming on various systems
  255. // (lo in Linux, lo0 in BSD systems)
  256. // Fix for this is available on 1186 branch, will reenable
  257. // this test once 1186 is merged
  258. TEST_F(IfaceMgrTest, DISABLED_sendReceive) {
  259. // testing socket operation in a portable way is tricky
  260. // without interface detection implemented
  261. fstream fakeifaces(INTERFACE_FILE, ios::out|ios::trunc);
  262. fakeifaces << LOOPBACK << " ::1";
  263. fakeifaces.close();
  264. NakedIfaceMgr * ifacemgr = new NakedIfaceMgr();
  265. // let's assume that every supported OS have lo interface
  266. IOAddress loAddr("::1");
  267. int socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, 10547);
  268. int socket2 = ifacemgr->openSocket(LOOPBACK, loAddr, 10546);
  269. ifacemgr->setSendSock(socket2);
  270. ifacemgr->setRecvSock(socket1);
  271. boost::shared_ptr<Pkt6> sendPkt(new Pkt6(128) );
  272. // prepare dummy payload
  273. for (int i=0;i<128; i++) {
  274. sendPkt->data_[i] = i;
  275. }
  276. sendPkt->remote_port_ = 10547;
  277. sendPkt->remote_addr_ = IOAddress("::1");
  278. sendPkt->ifindex_ = 1;
  279. sendPkt->iface_ = LOOPBACK;
  280. boost::shared_ptr<Pkt6> rcvPkt;
  281. EXPECT_EQ(true, ifacemgr->send(sendPkt));
  282. rcvPkt = ifacemgr->receive();
  283. ASSERT_TRUE( rcvPkt != NULL ); // received our own packet
  284. // let's check that we received what was sent
  285. EXPECT_EQ(sendPkt->data_len_, rcvPkt->data_len_);
  286. EXPECT_EQ(0, memcmp(&sendPkt->data_[0], &rcvPkt->data_[0],
  287. rcvPkt->data_len_) );
  288. EXPECT_EQ(sendPkt->remote_addr_.toText(), rcvPkt->remote_addr_.toText());
  289. EXPECT_EQ(rcvPkt->remote_port_, 10546);
  290. delete ifacemgr;
  291. }
  292. }