iface_mgr_unittest.cc 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290
  1. // Copyright (C) 2011-2013 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 <asiolink/io_address.h>
  16. #include <dhcp/dhcp4.h>
  17. #include <dhcp/iface_mgr.h>
  18. #include <dhcp/pkt6.h>
  19. #include <boost/scoped_ptr.hpp>
  20. #include <gtest/gtest.h>
  21. #include <fstream>
  22. #include <iostream>
  23. #include <sstream>
  24. #include <arpa/inet.h>
  25. #include <unistd.h>
  26. using namespace std;
  27. using namespace isc;
  28. using namespace isc::asiolink;
  29. using namespace isc::dhcp;
  30. namespace {
  31. // Name of loopback interface detection
  32. const size_t BUF_SIZE = 32;
  33. char LOOPBACK[BUF_SIZE] = "lo";
  34. // Ports used during testing
  35. const uint16_t PORT1 = 10547; // V6 socket
  36. const uint16_t PORT2 = 10548; // V4 socket
  37. // On some systems measured duration of receive6() and
  38. // receive4() appears to be shorter than select() timeout.
  39. // called by these functions. This may be the case
  40. // if different ime resolutions are used by these functions.
  41. // For such cases we set the tolerance of 0.01s.
  42. const uint32_t TIMEOUT_TOLERANCE = 10000;
  43. class NakedIfaceMgr: public IfaceMgr {
  44. // "naked" Interface Manager, exposes internal fields
  45. public:
  46. NakedIfaceMgr() { }
  47. IfaceCollection & getIfacesLst() { return ifaces_; }
  48. };
  49. // dummy class for now, but this will be expanded when needed
  50. class IfaceMgrTest : public ::testing::Test {
  51. public:
  52. // these are empty for now, but let's keep them around
  53. IfaceMgrTest() {
  54. }
  55. ~IfaceMgrTest() {
  56. }
  57. };
  58. // We need some known interface to work reliably. Loopback interface
  59. // is named lo on Linux and lo0 on BSD boxes. We need to find out
  60. // which is available. This is not a real test, but rather a workaround
  61. // that will go away when interface detection is implemented.
  62. // NOTE: At this stage of development, write access to current directory
  63. // during running tests is required.
  64. TEST_F(IfaceMgrTest, loDetect) {
  65. // poor man's interface detection
  66. // it will go away as soon as proper interface detection
  67. // is implemented
  68. if (if_nametoindex("lo") > 0) {
  69. snprintf(LOOPBACK, BUF_SIZE - 1, "lo");
  70. } else if (if_nametoindex("lo0") > 0) {
  71. snprintf(LOOPBACK, BUF_SIZE - 1, "lo0");
  72. } else {
  73. cout << "Failed to detect loopback interface. Neither "
  74. << "lo nor lo0 worked. I give up." << endl;
  75. FAIL();
  76. }
  77. }
  78. // Uncomment this test to create packet writer. It will
  79. // write incoming DHCPv6 packets as C arrays. That is useful
  80. // for generating test sequences based on actual traffic
  81. //
  82. // TODO: this potentially should be moved to a separate tool
  83. //
  84. #if 0
  85. TEST_F(IfaceMgrTest, dhcp6Sniffer) {
  86. // testing socket operation in a portable way is tricky
  87. // without interface detection implemented
  88. unlink("interfaces.txt");
  89. ofstream interfaces("interfaces.txt", ios::ate);
  90. interfaces << "eth0 fe80::21e:8cff:fe9b:7349";
  91. interfaces.close();
  92. NakedIfaceMgr* ifacemgr = new NakedIfaceMgr();
  93. Pkt6* pkt = NULL;
  94. int cnt = 0;
  95. cout << "---8X-----------------------------------------" << endl;
  96. while (true) {
  97. pkt = ifacemgr->receive();
  98. cout << "// this code is autogenerated. Do NOT edit." << endl;
  99. cout << "// Received " << pkt->data_len_ << " bytes packet:" << endl;
  100. cout << "Pkt6 *capture" << cnt++ << "() {" << endl;
  101. cout << " Pkt6* pkt;" << endl;
  102. cout << " pkt = new Pkt6(" << pkt->data_len_ << ");" << endl;
  103. cout << " pkt->remote_port_ = " << pkt-> remote_port_ << ";" << endl;
  104. cout << " pkt->remote_addr_ = IOAddress(\""
  105. << pkt->remote_addr_.toText() << "\");" << endl;
  106. cout << " pkt->local_port_ = " << pkt-> local_port_ << ";" << endl;
  107. cout << " pkt->local_addr_ = IOAddress(\""
  108. << pkt->local_addr_.toText() << "\");" << endl;
  109. cout << " pkt->ifindex_ = " << pkt->ifindex_ << ";" << endl;
  110. cout << " pkt->iface_ = \"" << pkt->iface_ << "\";" << endl;
  111. // TODO it is better to declare statically initialize the array
  112. // and then memcpy it to packet.
  113. for (int i=0; i< pkt->data_len_; i++) {
  114. cout << " pkt->data_[" << i << "]="
  115. << (int)(unsigned char)pkt->data_[i] << "; ";
  116. if (!(i%4))
  117. cout << endl;
  118. }
  119. cout << endl;
  120. cout << " return (pkt);" << endl;
  121. cout << "}" << endl << endl;
  122. delete pkt;
  123. }
  124. cout << "---8X-----------------------------------------" << endl;
  125. // never happens. Infinite loop is infinite
  126. delete pkt;
  127. delete ifacemgr;
  128. }
  129. #endif
  130. TEST_F(IfaceMgrTest, basic) {
  131. // checks that IfaceManager can be instantiated
  132. IfaceMgr & ifacemgr = IfaceMgr::instance();
  133. ASSERT_TRUE(&ifacemgr != 0);
  134. }
  135. TEST_F(IfaceMgrTest, ifaceClass) {
  136. // basic tests for Iface inner class
  137. IfaceMgr::Iface* iface = new IfaceMgr::Iface("eth5", 7);
  138. EXPECT_STREQ("eth5/7", iface->getFullName().c_str());
  139. delete iface;
  140. }
  141. // TODO: Implement getPlainMac() test as soon as interface detection
  142. // is implemented.
  143. TEST_F(IfaceMgrTest, getIface) {
  144. cout << "Interface checks. Please ignore socket binding errors." << endl;
  145. NakedIfaceMgr* ifacemgr = new NakedIfaceMgr();
  146. // interface name, ifindex
  147. IfaceMgr::Iface iface1("lo1", 100);
  148. IfaceMgr::Iface iface2("eth9", 101);
  149. IfaceMgr::Iface iface3("en3", 102);
  150. IfaceMgr::Iface iface4("e1000g4", 103);
  151. cout << "This test assumes that there are less than 100 network interfaces"
  152. << " in the tested system and there are no lo1, eth9, en3, e1000g4"
  153. << " or wifi15 interfaces present." << endl;
  154. // note: real interfaces may be detected as well
  155. ifacemgr->getIfacesLst().push_back(iface1);
  156. ifacemgr->getIfacesLst().push_back(iface2);
  157. ifacemgr->getIfacesLst().push_back(iface3);
  158. ifacemgr->getIfacesLst().push_back(iface4);
  159. cout << "There are " << ifacemgr->getIfacesLst().size()
  160. << " interfaces." << endl;
  161. for (IfaceMgr::IfaceCollection::iterator iface=ifacemgr->getIfacesLst().begin();
  162. iface != ifacemgr->getIfacesLst().end();
  163. ++iface) {
  164. cout << " " << iface->getFullName() << endl;
  165. }
  166. // check that interface can be retrieved by ifindex
  167. IfaceMgr::Iface* tmp = ifacemgr->getIface(102);
  168. ASSERT_TRUE(tmp != NULL);
  169. EXPECT_EQ("en3", tmp->getName());
  170. EXPECT_EQ(102, tmp->getIndex());
  171. // check that interface can be retrieved by name
  172. tmp = ifacemgr->getIface("lo1");
  173. ASSERT_TRUE(tmp != NULL);
  174. EXPECT_EQ("lo1", tmp->getName());
  175. EXPECT_EQ(100, tmp->getIndex());
  176. // check that non-existing interfaces are not returned
  177. EXPECT_EQ(static_cast<void*>(NULL), ifacemgr->getIface("wifi15") );
  178. delete ifacemgr;
  179. }
  180. TEST_F(IfaceMgrTest, receiveTimeout6) {
  181. using namespace boost::posix_time;
  182. std::cout << "Testing DHCPv6 packet reception timeouts."
  183. << " Test will block for a few seconds when waiting"
  184. << " for timeout to occur." << std::endl;
  185. boost::scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
  186. // Open socket on the lo interface.
  187. IOAddress loAddr("::1");
  188. int socket1 = 0;
  189. ASSERT_NO_THROW(
  190. socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, 10547)
  191. );
  192. // Socket is open if its descriptor is greater than zero.
  193. ASSERT_GT(socket1, 0);
  194. // Remember when we call receive6().
  195. ptime start_time = microsec_clock::universal_time();
  196. // Call receive with timeout of 1s + 400000us = 1.4s.
  197. Pkt6Ptr pkt;
  198. ASSERT_NO_THROW(pkt = ifacemgr->receive6(1, 400000));
  199. // Remember when call to receive6() ended.
  200. ptime stop_time = microsec_clock::universal_time();
  201. // We did not send a packet to lo interface so we expect that
  202. // nothing has been received and timeout has been reached.
  203. ASSERT_FALSE(pkt);
  204. // Calculate duration of call to receive6().
  205. time_duration duration = stop_time - start_time;
  206. // We stop the clock when the call completes so it does not
  207. // precisely reflect the receive timeout. However the
  208. // uncertainity should be low enough to expect that measured
  209. // value is in the range <1.4s; 1.7s>.
  210. EXPECT_GE(duration.total_microseconds(),
  211. 1400000 - TIMEOUT_TOLERANCE);
  212. EXPECT_LE(duration.total_microseconds(), 1700000);
  213. // Test timeout shorter than 1s.
  214. start_time = microsec_clock::universal_time();
  215. ASSERT_NO_THROW(pkt = ifacemgr->receive6(0, 500000));
  216. stop_time = microsec_clock::universal_time();
  217. ASSERT_FALSE(pkt);
  218. duration = stop_time - start_time;
  219. // Check if measured duration is within <0.5s; 0.8s>.
  220. EXPECT_GE(duration.total_microseconds(),
  221. 500000 - TIMEOUT_TOLERANCE);
  222. EXPECT_LE(duration.total_microseconds(), 800000);
  223. // Test with invalid fractional timeout values.
  224. EXPECT_THROW(ifacemgr->receive6(0, 1000000), isc::BadValue);
  225. EXPECT_THROW(ifacemgr->receive6(1, 1000010), isc::BadValue);
  226. }
  227. TEST_F(IfaceMgrTest, receiveTimeout4) {
  228. using namespace boost::posix_time;
  229. std::cout << "Testing DHCPv6 packet reception timeouts."
  230. << " Test will block for a few seconds when waiting"
  231. << " for timeout to occur." << std::endl;
  232. boost::scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
  233. // Open socket on the lo interface.
  234. IOAddress loAddr("127.0.0.1");
  235. int socket1 = 0;
  236. ASSERT_NO_THROW(
  237. socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, 10067)
  238. );
  239. // Socket is open if its descriptor is greater than zero.
  240. ASSERT_GT(socket1, 0);
  241. Pkt4Ptr pkt;
  242. // Remember when we call receive4().
  243. ptime start_time = microsec_clock::universal_time();
  244. // Call receive with timeout of 2s + 300000us = 2.3s.
  245. ASSERT_NO_THROW(pkt = ifacemgr->receive4(2, 300000));
  246. // Remember when call to receive4() ended.
  247. ptime stop_time = microsec_clock::universal_time();
  248. // We did not send a packet to lo interface so we expect that
  249. // nothing has been received and timeout has been reached.
  250. ASSERT_FALSE(pkt);
  251. // Calculate duration of call to receive4().
  252. time_duration duration = stop_time - start_time;
  253. // We stop the clock when the call completes so it does not
  254. // precisely reflect the receive timeout. However the
  255. // uncertainity should be low enough to expect that measured
  256. // value is in the range <2.3s; 2.6s>.
  257. EXPECT_GE(duration.total_microseconds(),
  258. 2300000 - TIMEOUT_TOLERANCE);
  259. EXPECT_LE(duration.total_microseconds(), 2600000);
  260. // Test timeout shorter than 1s.
  261. start_time = microsec_clock::universal_time();
  262. ASSERT_NO_THROW(pkt = ifacemgr->receive4(0, 400000));
  263. stop_time = microsec_clock::universal_time();
  264. ASSERT_FALSE(pkt);
  265. duration = stop_time - start_time;
  266. // Check if measured duration is within <0.4s; 0.7s>.
  267. EXPECT_GE(duration.total_microseconds(),
  268. 400000 - TIMEOUT_TOLERANCE);
  269. EXPECT_LE(duration.total_microseconds(), 700000);
  270. // Test with invalid fractional timeout values.
  271. EXPECT_THROW(ifacemgr->receive6(0, 1000000), isc::BadValue);
  272. EXPECT_THROW(ifacemgr->receive6(2, 1000005), isc::BadValue);
  273. }
  274. TEST_F(IfaceMgrTest, multipleSockets) {
  275. boost::scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
  276. // container for initialized socket descriptors
  277. std::list<uint16_t> init_sockets;
  278. // create socket #1
  279. int socket1 = 0;
  280. ASSERT_NO_THROW(
  281. socket1 = ifacemgr->openSocketFromIface(LOOPBACK, PORT1, AF_INET);
  282. );
  283. ASSERT_GT(socket1, 0);
  284. init_sockets.push_back(socket1);
  285. // create socket #2
  286. IOAddress loAddr("127.0.0.1");
  287. int socket2 = 0;
  288. ASSERT_NO_THROW(
  289. socket2 = ifacemgr->openSocketFromRemoteAddress(loAddr, PORT2);
  290. );
  291. ASSERT_GT(socket2, 0);
  292. init_sockets.push_back(socket2);
  293. // Get loopback interface. If we don't find one we are unable to run
  294. // this test but we don't want to fail.
  295. IfaceMgr::Iface* iface_ptr = ifacemgr->getIface(LOOPBACK);
  296. if (iface_ptr == NULL) {
  297. cout << "Local loopback interface not found. Skipping test. " << endl;
  298. return;
  299. }
  300. // Once sockets have been sucessfully opened, they are supposed to
  301. // be on the list. Here we start to test if all expected sockets
  302. // are on the list and no other (unexpected) socket is there.
  303. IfaceMgr::SocketCollection sockets = iface_ptr->getSockets();
  304. int matched_sockets = 0;
  305. for (std::list<uint16_t>::iterator init_sockets_it =
  306. init_sockets.begin();
  307. init_sockets_it != init_sockets.end(); ++init_sockets_it) {
  308. // Set socket descriptors non blocking in order to be able
  309. // to call recv() on them without hang.
  310. int flags = fcntl(*init_sockets_it, F_GETFL, 0);
  311. ASSERT_GE(flags, 0);
  312. ASSERT_GE(fcntl(*init_sockets_it, F_SETFL, flags | O_NONBLOCK), 0);
  313. // recv() is expected to result in EWOULDBLOCK error on non-blocking
  314. // socket in case socket is valid but simply no data are coming in.
  315. char buf;
  316. recv(*init_sockets_it, &buf, 1, MSG_PEEK);
  317. EXPECT_EQ(EWOULDBLOCK, errno);
  318. // Apart from the ability to use the socket we want to make
  319. // sure that socket on the list is the one that we created.
  320. for (IfaceMgr::SocketCollection::const_iterator socket_it =
  321. sockets.begin(); socket_it != sockets.end(); ++socket_it) {
  322. if (*init_sockets_it == socket_it->sockfd_) {
  323. // This socket is the one that we created.
  324. ++matched_sockets;
  325. break;
  326. }
  327. }
  328. }
  329. // all created sockets have been matched if this condition works.
  330. EXPECT_EQ(sockets.size(), matched_sockets);
  331. // closeSockets() is the other function that we want to test. It
  332. // is supposed to close all sockets so as we will not be able to use
  333. // them anymore communication.
  334. ifacemgr->closeSockets();
  335. // closed sockets are supposed to be removed from the list
  336. sockets = iface_ptr->getSockets();
  337. ASSERT_EQ(0, sockets.size());
  338. // We are still in posession of socket descriptors that we created
  339. // on the beginning of this test. We can use them to check whether
  340. // closeSockets() only removed them from the list or they have been
  341. // really closed.
  342. for (std::list<uint16_t>::const_iterator init_sockets_it =
  343. init_sockets.begin();
  344. init_sockets_it != init_sockets.end(); ++init_sockets_it) {
  345. // recv() must result in error when using invalid socket.
  346. char buf;
  347. recv(*init_sockets_it, &buf, 1, MSG_PEEK);
  348. // EWOULDBLOCK would mean that socket is valid/open but
  349. // simply no data is received so we have to check for
  350. // other errors.
  351. EXPECT_NE(EWOULDBLOCK, errno);
  352. }
  353. }
  354. TEST_F(IfaceMgrTest, sockets6) {
  355. // testing socket operation in a portable way is tricky
  356. // without interface detection implemented
  357. boost::scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
  358. IOAddress loAddr("::1");
  359. Pkt6 pkt6(DHCPV6_SOLICIT, 123);
  360. pkt6.setIface(LOOPBACK);
  361. // bind multicast socket to port 10547
  362. int socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, 10547);
  363. EXPECT_GT(socket1, 0); // socket > 0
  364. EXPECT_EQ(socket1, ifacemgr->getSocket(pkt6));
  365. // bind unicast socket to port 10548
  366. int socket2 = ifacemgr->openSocket(LOOPBACK, loAddr, 10548);
  367. EXPECT_GT(socket2, 0);
  368. // removed code for binding socket twice to the same address/port
  369. // as it caused problems on some platforms (e.g. Mac OS X)
  370. // Close sockets here because the following tests will want to
  371. // open sockets on the same ports.
  372. ifacemgr->closeSockets();
  373. // Use address that is not assigned to LOOPBACK iface.
  374. IOAddress invalidAddr("::2");
  375. EXPECT_THROW(
  376. ifacemgr->openSocket(LOOPBACK, invalidAddr, 10547),
  377. SocketConfigError
  378. );
  379. // Use non-existing interface name.
  380. EXPECT_THROW(
  381. ifacemgr->openSocket("non_existing_interface", loAddr, 10548),
  382. BadValue
  383. );
  384. // Do not call closeSockets() because it is called by IfaceMgr's
  385. // virtual destructor.
  386. }
  387. TEST_F(IfaceMgrTest, socketsFromIface) {
  388. boost::scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
  389. // Open v6 socket on loopback interface and bind to port
  390. int socket1 = 0;
  391. EXPECT_NO_THROW(
  392. socket1 = ifacemgr->openSocketFromIface(LOOPBACK, PORT1, AF_INET6);
  393. );
  394. // Socket descriptor must be positive integer
  395. EXPECT_GT(socket1, 0);
  396. close(socket1);
  397. // Open v4 socket on loopback interface and bind to different port
  398. int socket2 = 0;
  399. EXPECT_NO_THROW(
  400. socket2 = ifacemgr->openSocketFromIface(LOOPBACK, PORT2, AF_INET);
  401. );
  402. // socket descriptor must be positive integer
  403. EXPECT_GT(socket2, 0);
  404. close(socket2);
  405. // Close sockets here because the following tests will want to
  406. // open sockets on the same ports.
  407. ifacemgr->closeSockets();
  408. // Use invalid interface name.
  409. EXPECT_THROW(
  410. ifacemgr->openSocketFromIface("non_existing_interface", PORT1, AF_INET),
  411. BadValue
  412. );
  413. // Do not call closeSockets() because it is called by IfaceMgr's
  414. // virtual destructor.
  415. }
  416. TEST_F(IfaceMgrTest, socketsFromAddress) {
  417. boost::scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
  418. // Open v6 socket on loopback interface and bind to port
  419. int socket1 = 0;
  420. IOAddress loAddr6("::1");
  421. EXPECT_NO_THROW(
  422. socket1 = ifacemgr->openSocketFromAddress(loAddr6, PORT1);
  423. );
  424. // socket descriptor must be positive integer
  425. EXPECT_GT(socket1, 0);
  426. // Open v4 socket on loopback interface and bind to different port
  427. int socket2 = 0;
  428. IOAddress loAddr("127.0.0.1");
  429. EXPECT_NO_THROW(
  430. socket2 = ifacemgr->openSocketFromAddress(loAddr, PORT2);
  431. );
  432. // socket descriptor must be positive integer
  433. EXPECT_GT(socket2, 0);
  434. // Close sockets here because the following tests will want to
  435. // open sockets on the same ports.
  436. ifacemgr->closeSockets();
  437. // Use non-existing address.
  438. IOAddress invalidAddr("1.2.3.4");
  439. EXPECT_THROW(
  440. ifacemgr->openSocketFromAddress(invalidAddr, PORT1), BadValue
  441. );
  442. // Do not call closeSockets() because it is called by IfaceMgr's
  443. // virtual destructor.
  444. }
  445. TEST_F(IfaceMgrTest, socketsFromRemoteAddress) {
  446. boost::scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
  447. // Open v6 socket to connect to remote address.
  448. // Loopback address is the only one that we know
  449. // so let's treat it as remote address.
  450. int socket1 = 0;
  451. IOAddress loAddr6("::1");
  452. EXPECT_NO_THROW(
  453. socket1 = ifacemgr->openSocketFromRemoteAddress(loAddr6, PORT1);
  454. );
  455. EXPECT_GT(socket1, 0);
  456. // Open v4 socket to connect to remote address.
  457. int socket2 = 0;
  458. IOAddress loAddr("127.0.0.1");
  459. EXPECT_NO_THROW(
  460. socket2 = ifacemgr->openSocketFromRemoteAddress(loAddr, PORT2);
  461. );
  462. EXPECT_GT(socket2, 0);
  463. // Close sockets here because the following tests will want to
  464. // open sockets on the same ports.
  465. ifacemgr->closeSockets();
  466. // The following test is currently disabled for OSes other than
  467. // Linux because interface detection is not implemented on them.
  468. // @todo enable this test for all OSes once interface detection
  469. // is implemented.
  470. #if defined(OS_LINUX)
  471. // Open v4 socket to connect to broadcast address.
  472. int socket3 = 0;
  473. IOAddress bcastAddr("255.255.255.255");
  474. EXPECT_NO_THROW(
  475. socket3 = ifacemgr->openSocketFromRemoteAddress(bcastAddr, PORT2);
  476. );
  477. EXPECT_GT(socket3, 0);
  478. #endif
  479. // Do not call closeSockets() because it is called by IfaceMgr's
  480. // virtual destructor.
  481. }
  482. // TODO: disabled due to other naming on various systems
  483. // (lo in Linux, lo0 in BSD systems)
  484. TEST_F(IfaceMgrTest, DISABLED_sockets6Mcast) {
  485. // testing socket operation in a portable way is tricky
  486. // without interface detection implemented
  487. NakedIfaceMgr* ifacemgr = new NakedIfaceMgr();
  488. IOAddress loAddr("::1");
  489. IOAddress mcastAddr("ff02::1:2");
  490. // bind multicast socket to port 10547
  491. int socket1 = ifacemgr->openSocket(LOOPBACK, mcastAddr, 10547);
  492. EXPECT_GT(socket1, 0); // socket > 0
  493. // expect success. This address/port is already bound, but
  494. // we are using SO_REUSEADDR, so we can bind it twice
  495. int socket2 = ifacemgr->openSocket(LOOPBACK, mcastAddr, 10547);
  496. EXPECT_GT(socket2, 0);
  497. // there's no good way to test negative case here.
  498. // we would need non-multicast interface. We will be able
  499. // to iterate thru available interfaces and check if there
  500. // are interfaces without multicast-capable flag.
  501. close(socket1);
  502. close(socket2);
  503. delete ifacemgr;
  504. }
  505. TEST_F(IfaceMgrTest, sendReceive6) {
  506. // testing socket operation in a portable way is tricky
  507. // without interface detection implemented
  508. boost::scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
  509. // let's assume that every supported OS have lo interface
  510. IOAddress loAddr("::1");
  511. int socket1 = 0, socket2 = 0;
  512. EXPECT_NO_THROW(
  513. socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, 10547);
  514. socket2 = ifacemgr->openSocket(LOOPBACK, loAddr, 10546);
  515. );
  516. EXPECT_GT(socket1, 0);
  517. EXPECT_GT(socket2, 0);
  518. // prepare dummy payload
  519. uint8_t data[128];
  520. for (int i = 0; i < 128; i++) {
  521. data[i] = i;
  522. }
  523. Pkt6Ptr sendPkt = Pkt6Ptr(new Pkt6(data, 128));
  524. sendPkt->repack();
  525. sendPkt->setRemotePort(10547);
  526. sendPkt->setRemoteAddr(IOAddress("::1"));
  527. sendPkt->setIndex(1);
  528. sendPkt->setIface(LOOPBACK);
  529. Pkt6Ptr rcvPkt;
  530. EXPECT_EQ(true, ifacemgr->send(sendPkt));
  531. rcvPkt = ifacemgr->receive6(10);
  532. ASSERT_TRUE(rcvPkt); // received our own packet
  533. // let's check that we received what was sent
  534. ASSERT_EQ(sendPkt->getData().size(), rcvPkt->getData().size());
  535. EXPECT_EQ(0, memcmp(&sendPkt->getData()[0], &rcvPkt->getData()[0],
  536. rcvPkt->getData().size()));
  537. EXPECT_EQ(sendPkt->getRemoteAddr().toText(), rcvPkt->getRemoteAddr().toText());
  538. // since we opened 2 sockets on the same interface and none of them is multicast,
  539. // none is preferred over the other for sending data, so we really should not
  540. // assume the one or the other will always be chosen for sending data. Therefore
  541. // we should accept both values as source ports.
  542. EXPECT_TRUE((rcvPkt->getRemotePort() == 10546) || (rcvPkt->getRemotePort() == 10547));
  543. // try to send/receive data over the closed socket. Closed socket's descriptor is
  544. // still being hold by IfaceMgr which will try to use it to receive data.
  545. close(socket1);
  546. EXPECT_THROW(ifacemgr->receive6(10), SocketReadError);
  547. EXPECT_THROW(ifacemgr->send(sendPkt), SocketWriteError);
  548. }
  549. TEST_F(IfaceMgrTest, sendReceive4) {
  550. // testing socket operation in a portable way is tricky
  551. // without interface detection implemented
  552. boost::scoped_ptr<NakedIfaceMgr> ifacemgr(new NakedIfaceMgr());
  553. // let's assume that every supported OS have lo interface
  554. IOAddress loAddr("127.0.0.1");
  555. int socket1 = 0, socket2 = 0;
  556. EXPECT_NO_THROW(
  557. socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, DHCP4_SERVER_PORT + 10000);
  558. socket2 = ifacemgr->openSocket(LOOPBACK, loAddr, DHCP4_SERVER_PORT + 10000 + 1);
  559. );
  560. EXPECT_GE(socket1, 0);
  561. EXPECT_GE(socket2, 0);
  562. boost::shared_ptr<Pkt4> sendPkt(new Pkt4(DHCPDISCOVER, 1234) );
  563. sendPkt->setLocalAddr(IOAddress("127.0.0.1"));
  564. sendPkt->setLocalPort(DHCP4_SERVER_PORT + 10000 + 1);
  565. sendPkt->setRemotePort(DHCP4_SERVER_PORT + 10000);
  566. sendPkt->setRemoteAddr(IOAddress("127.0.0.1"));
  567. sendPkt->setIndex(1);
  568. sendPkt->setIface(string(LOOPBACK));
  569. sendPkt->setHops(6);
  570. sendPkt->setSecs(42);
  571. sendPkt->setCiaddr(IOAddress("192.0.2.1"));
  572. sendPkt->setSiaddr(IOAddress("192.0.2.2"));
  573. sendPkt->setYiaddr(IOAddress("192.0.2.3"));
  574. sendPkt->setGiaddr(IOAddress("192.0.2.4"));
  575. // Unpack() now checks if mandatory DHCP_MESSAGE_TYPE is present.
  576. // Workarounds (creating DHCP Message Type Option by hand) are no longer
  577. // needed as setDhcpType() is called in constructor.
  578. uint8_t sname[] = "That's just a string that will act as SNAME";
  579. sendPkt->setSname(sname, strlen((const char*)sname));
  580. uint8_t file[] = "/another/string/that/acts/as/a/file_name.txt";
  581. sendPkt->setFile(file, strlen((const char*)file));
  582. ASSERT_NO_THROW(
  583. sendPkt->pack();
  584. );
  585. boost::shared_ptr<Pkt4> rcvPkt;
  586. EXPECT_EQ(true, ifacemgr->send(sendPkt));
  587. ASSERT_NO_THROW(rcvPkt = ifacemgr->receive4(10));
  588. ASSERT_TRUE(rcvPkt); // received our own packet
  589. ASSERT_NO_THROW(
  590. rcvPkt->unpack();
  591. );
  592. // let's check that we received what was sent
  593. EXPECT_EQ(sendPkt->len(), rcvPkt->len());
  594. EXPECT_EQ("127.0.0.1", rcvPkt->getRemoteAddr().toText());
  595. EXPECT_EQ(sendPkt->getRemotePort(), rcvPkt->getLocalPort());
  596. // now let's check content
  597. EXPECT_EQ(sendPkt->getHops(), rcvPkt->getHops());
  598. EXPECT_EQ(sendPkt->getOp(), rcvPkt->getOp());
  599. EXPECT_EQ(sendPkt->getSecs(), rcvPkt->getSecs());
  600. EXPECT_EQ(sendPkt->getFlags(), rcvPkt->getFlags());
  601. EXPECT_EQ(sendPkt->getCiaddr(), rcvPkt->getCiaddr());
  602. EXPECT_EQ(sendPkt->getSiaddr(), rcvPkt->getSiaddr());
  603. EXPECT_EQ(sendPkt->getYiaddr(), rcvPkt->getYiaddr());
  604. EXPECT_EQ(sendPkt->getGiaddr(), rcvPkt->getGiaddr());
  605. EXPECT_EQ(sendPkt->getTransid(), rcvPkt->getTransid());
  606. EXPECT_TRUE(sendPkt->getSname() == rcvPkt->getSname());
  607. EXPECT_TRUE(sendPkt->getFile() == rcvPkt->getFile());
  608. EXPECT_EQ(sendPkt->getHtype(), rcvPkt->getHtype());
  609. EXPECT_EQ(sendPkt->getHlen(), rcvPkt->getHlen());
  610. // since we opened 2 sockets on the same interface and none of them is multicast,
  611. // none is preferred over the other for sending data, so we really should not
  612. // assume the one or the other will always be chosen for sending data. We should
  613. // skip checking source port of sent address.
  614. // try to receive data over the closed socket. Closed socket's descriptor is
  615. // still being hold by IfaceMgr which will try to use it to receive data.
  616. close(socket1);
  617. EXPECT_THROW(ifacemgr->receive4(10), SocketReadError);
  618. EXPECT_THROW(ifacemgr->send(sendPkt), SocketWriteError);
  619. }
  620. TEST_F(IfaceMgrTest, socket4) {
  621. NakedIfaceMgr* ifacemgr = new NakedIfaceMgr();
  622. // Let's assume that every supported OS have lo interface.
  623. IOAddress loAddr("127.0.0.1");
  624. // Use unprivileged port (it's convenient for running tests as non-root).
  625. int socket1 = 0;
  626. EXPECT_NO_THROW(
  627. socket1 = ifacemgr->openSocket(LOOPBACK, loAddr, DHCP4_SERVER_PORT + 10000);
  628. );
  629. EXPECT_GT(socket1, 0);
  630. Pkt4 pkt(DHCPDISCOVER, 1234);
  631. pkt.setIface(LOOPBACK);
  632. // Expect that we get the socket that we just opened.
  633. EXPECT_EQ(socket1, ifacemgr->getSocket(pkt));
  634. close(socket1);
  635. delete ifacemgr;
  636. }
  637. // Test the Iface structure itself
  638. TEST_F(IfaceMgrTest, iface) {
  639. IfaceMgr::Iface* iface = NULL;
  640. EXPECT_NO_THROW(
  641. iface = new IfaceMgr::Iface("eth0",1);
  642. );
  643. EXPECT_EQ("eth0", iface->getName());
  644. EXPECT_EQ(1, iface->getIndex());
  645. EXPECT_EQ("eth0/1", iface->getFullName());
  646. // Let's make a copy of this address collection.
  647. IfaceMgr::AddressCollection addrs = iface->getAddresses();
  648. EXPECT_EQ(0, addrs.size());
  649. IOAddress addr1("192.0.2.6");
  650. iface->addAddress(addr1);
  651. addrs = iface->getAddresses();
  652. ASSERT_EQ(1, addrs.size());
  653. EXPECT_EQ("192.0.2.6", addrs.at(0).toText());
  654. // No such address, should return false.
  655. EXPECT_FALSE(iface->delAddress(IOAddress("192.0.8.9")));
  656. // This address is present, delete it!
  657. EXPECT_TRUE(iface->delAddress(IOAddress("192.0.2.6")));
  658. // Not really necessary, previous reference still points to the same
  659. // collection. Let's do it anyway, as test code may serve as example
  660. // usage code as well.
  661. addrs = iface->getAddresses();
  662. EXPECT_EQ(0, addrs.size());
  663. EXPECT_NO_THROW(
  664. delete iface;
  665. );
  666. }
  667. TEST_F(IfaceMgrTest, iface_methods) {
  668. IfaceMgr::Iface iface("foo", 1234);
  669. iface.setHWType(42);
  670. EXPECT_EQ(42, iface.getHWType());
  671. uint8_t mac[IfaceMgr::MAX_MAC_LEN+10];
  672. for (int i = 0; i < IfaceMgr::MAX_MAC_LEN + 10; i++)
  673. mac[i] = 255 - i;
  674. EXPECT_EQ("foo", iface.getName());
  675. EXPECT_EQ(1234, iface.getIndex());
  676. // MAC is too long. Exception should be thrown and
  677. // MAC length should not be set.
  678. EXPECT_THROW(
  679. iface.setMac(mac, IfaceMgr::MAX_MAC_LEN + 1),
  680. OutOfRange
  681. );
  682. // MAC length should stay not set as excep
  683. EXPECT_EQ(0, iface.getMacLen());
  684. // Setting maximum length MAC should be ok.
  685. iface.setMac(mac, IfaceMgr::MAX_MAC_LEN);
  686. // For some reason constants cannot be used directly in EXPECT_EQ
  687. // as this produces linking error.
  688. size_t len = IfaceMgr::MAX_MAC_LEN;
  689. EXPECT_EQ(len, iface.getMacLen());
  690. EXPECT_EQ(0, memcmp(mac, iface.getMac(), iface.getMacLen()));
  691. }
  692. TEST_F(IfaceMgrTest, socketInfo) {
  693. // check that socketinfo for IPv4 socket is functional
  694. IfaceMgr::SocketInfo sock1(7, IOAddress("192.0.2.56"), DHCP4_SERVER_PORT + 7);
  695. EXPECT_EQ(7, sock1.sockfd_);
  696. EXPECT_EQ("192.0.2.56", sock1.addr_.toText());
  697. EXPECT_EQ(AF_INET, sock1.family_);
  698. EXPECT_EQ(DHCP4_SERVER_PORT + 7, sock1.port_);
  699. // check that socketinfo for IPv6 socket is functional
  700. IfaceMgr::SocketInfo sock2(9, IOAddress("2001:db8:1::56"), DHCP4_SERVER_PORT + 9);
  701. EXPECT_EQ(9, sock2.sockfd_);
  702. EXPECT_EQ("2001:db8:1::56", sock2.addr_.toText());
  703. EXPECT_EQ(AF_INET6, sock2.family_);
  704. EXPECT_EQ(DHCP4_SERVER_PORT + 9, sock2.port_);
  705. // now let's test if IfaceMgr handles socket info properly
  706. NakedIfaceMgr* ifacemgr = new NakedIfaceMgr();
  707. IfaceMgr::Iface* loopback = ifacemgr->getIface(LOOPBACK);
  708. ASSERT_TRUE(loopback);
  709. loopback->addSocket(sock1);
  710. loopback->addSocket(sock2);
  711. Pkt6 pkt6(DHCPV6_REPLY, 123456);
  712. // pkt6 dos not have interface set yet
  713. EXPECT_THROW(
  714. ifacemgr->getSocket(pkt6),
  715. BadValue
  716. );
  717. // try to send over non-existing interface
  718. pkt6.setIface("nosuchinterface45");
  719. EXPECT_THROW(
  720. ifacemgr->getSocket(pkt6),
  721. BadValue
  722. );
  723. // this will work
  724. pkt6.setIface(LOOPBACK);
  725. EXPECT_EQ(9, ifacemgr->getSocket(pkt6));
  726. bool deleted = false;
  727. EXPECT_NO_THROW(
  728. deleted = ifacemgr->getIface(LOOPBACK)->delSocket(9);
  729. );
  730. EXPECT_EQ(true, deleted);
  731. // it should throw again, there's no usable socket anymore
  732. EXPECT_THROW(
  733. ifacemgr->getSocket(pkt6),
  734. Unexpected
  735. );
  736. // repeat for pkt4
  737. Pkt4 pkt4(DHCPDISCOVER, 1);
  738. // pkt4 does not have interface set yet.
  739. EXPECT_THROW(
  740. ifacemgr->getSocket(pkt4),
  741. BadValue
  742. );
  743. // Try to send over non-existing interface.
  744. pkt4.setIface("nosuchinterface45");
  745. EXPECT_THROW(
  746. ifacemgr->getSocket(pkt4),
  747. BadValue
  748. );
  749. // Socket info is set, packet has well defined interface. It should work.
  750. pkt4.setIface(LOOPBACK);
  751. EXPECT_EQ(7, ifacemgr->getSocket(pkt4));
  752. EXPECT_NO_THROW(
  753. ifacemgr->getIface(LOOPBACK)->delSocket(7);
  754. );
  755. // It should throw again, there's no usable socket anymore.
  756. EXPECT_THROW(
  757. ifacemgr->getSocket(pkt4),
  758. Unexpected
  759. );
  760. delete ifacemgr;
  761. }
  762. #if defined(OS_LINUX)
  763. /// @brief parses text representation of MAC address
  764. ///
  765. /// This function parses text representation of a MAC address and stores
  766. /// it in binary format. Text format is expected to be separate with
  767. /// semicolons, e.g. f4:6d:04:96:58:f2
  768. ///
  769. /// TODO: IfaceMgr::Iface::mac_ uses uint8_t* type, should be vector<uint8_t>
  770. ///
  771. /// @param textMac string with MAC address to parse
  772. /// @param mac pointer to output buffer
  773. /// @param macLen length of output buffer
  774. ///
  775. /// @return number of bytes filled in output buffer
  776. size_t parse_mac(const std::string& textMac, uint8_t* mac, size_t macLen) {
  777. stringstream tmp(textMac);
  778. tmp.flags(ios::hex);
  779. int i = 0;
  780. uint8_t octet = 0; // output octet
  781. uint8_t byte; // parsed character from text representation
  782. while (!tmp.eof()) {
  783. tmp >> byte; // hex value
  784. if (byte == ':') {
  785. mac[i++] = octet;
  786. if (i == macLen) {
  787. // parsing aborted. We hit output buffer size
  788. return(i);
  789. }
  790. octet = 0;
  791. continue;
  792. }
  793. if (isalpha(byte)) {
  794. byte = toupper(byte) - 'A' + 10;
  795. } else if (isdigit(byte)) {
  796. byte -= '0';
  797. } else {
  798. // parse error. Let's return what we were able to parse so far
  799. break;
  800. }
  801. octet <<= 4;
  802. octet += byte;
  803. }
  804. mac[i++] = octet;
  805. return (i);
  806. }
  807. /// @brief Parses 'ifconfig -a' output and creates list of interfaces
  808. ///
  809. /// This method tries to parse ifconfig output. Note that there are some
  810. /// oddities in recent versions of ifconfig, like putting extra spaces
  811. /// after MAC address, inconsistent naming and spacing between inet and inet6.
  812. /// This is an attempt to find a balance between tight parsing of every piece
  813. /// of text that ifconfig prints and robustness to handle slight differences
  814. /// in ifconfig output.
  815. ///
  816. /// @todo: Consider using isc::util::str::tokens here.
  817. ///
  818. /// @param textFile name of a text file that holds output of ifconfig -a
  819. /// @param ifaces empty list of interfaces to be filled
  820. void parse_ifconfig(const std::string& textFile, IfaceMgr::IfaceCollection& ifaces) {
  821. fstream f(textFile.c_str());
  822. bool first_line = true;
  823. IfaceMgr::IfaceCollection::iterator iface;
  824. while (!f.eof()) {
  825. string line;
  826. getline(f, line);
  827. // interfaces are separated by empty line
  828. if (line.length() == 0) {
  829. first_line = true;
  830. continue;
  831. }
  832. // uncomment this for ifconfig output debug
  833. // cout << "line[" << line << "]" << endl;
  834. // this is first line of a new interface
  835. if (first_line) {
  836. first_line = false;
  837. size_t offset;
  838. offset = line.find_first_of(" ");
  839. if (offset == string::npos) {
  840. isc_throw(BadValue, "Malformed output of ifconfig");
  841. }
  842. // ifconfig in Gentoo prints out eth0: instead of eth0
  843. if (line[offset - 1] == ':') {
  844. offset--;
  845. }
  846. string name = line.substr(0, offset);
  847. // sadly, ifconfig does not return ifindex
  848. ifaces.push_back(IfaceMgr::Iface(name, 0));
  849. iface = ifaces.end();
  850. --iface; // points to the last element
  851. offset = line.find(string("HWaddr"));
  852. string mac = "";
  853. if (offset != string::npos) { // some interfaces don't have MAC (e.g. lo)
  854. offset += 7;
  855. mac = line.substr(offset, string::npos);
  856. mac = mac.substr(0, mac.find_first_of(" "));
  857. uint8_t buf[IfaceMgr::MAX_MAC_LEN];
  858. int mac_len = parse_mac(mac, buf, IfaceMgr::MAX_MAC_LEN);
  859. iface->setMac(buf, mac_len);
  860. }
  861. }
  862. if (line.find("inet6") != string::npos) {
  863. // IPv6 address
  864. string addr;
  865. if (line.find("addr:", line.find("inet6")) != string::npos) {
  866. // Ubuntu style format: inet6 addr: ::1/128 Scope:Host
  867. addr = line.substr(line.find("addr:") + 6, string::npos);
  868. } else {
  869. // Gentoo style format: inet6 fe80::6ef0:49ff:fe96:ba17 prefixlen 64 scopeid 0x20<link>
  870. addr = line.substr(line.find("inet6") + 6, string::npos);
  871. }
  872. // handle Ubuntu format: inet6 addr: fe80::f66d:4ff:fe96:58f2/64 Scope:Link
  873. addr = addr.substr(0, addr.find("/"));
  874. // handle inet6 fe80::ca3a:35ff:fed4:8f1d prefixlen 64 scopeid 0x20<link>
  875. addr = addr.substr(0, addr.find(" "));
  876. IOAddress a(addr);
  877. iface->addAddress(a);
  878. } else if(line.find("inet") != string::npos) {
  879. // IPv4 address
  880. string addr;
  881. if (line.find("addr:", line.find("inet")) != string::npos) {
  882. // Ubuntu style format: inet addr:127.0.0.1 Mask:255.0.0.0
  883. addr = line.substr(line.find("addr:") + 5, string::npos);
  884. } else {
  885. // Gentoo style format: inet 10.53.0.4 netmask 255.255.255.0
  886. addr = line.substr(line.find("inet") + 5, string::npos);
  887. }
  888. addr = addr.substr(0, addr.find_first_of(" "));
  889. IOAddress a(addr);
  890. iface->addAddress(a);
  891. } else if(line.find("Metric") != string::npos) {
  892. // flags
  893. if (line.find("UP") != string::npos) {
  894. iface->flag_up_ = true;
  895. }
  896. if (line.find("LOOPBACK") != string::npos) {
  897. iface->flag_loopback_ = true;
  898. }
  899. if (line.find("RUNNING") != string::npos) {
  900. iface->flag_running_ = true;
  901. }
  902. if (line.find("BROADCAST") != string::npos) {
  903. iface->flag_broadcast_ = true;
  904. }
  905. if (line.find("MULTICAST") != string::npos) {
  906. iface->flag_multicast_ = true;
  907. }
  908. }
  909. }
  910. }
  911. // This test compares implemented detection routines to output of "ifconfig -a" command.
  912. // It is far from perfect, but it is able to verify that interface names, flags,
  913. // MAC address, IPv4 and IPv6 addresses are detected properly. Interface list completeness
  914. // (check that each interface is reported, i.e. no missing or extra interfaces) and
  915. // address completeness is verified.
  916. //
  917. // Things that are not tested:
  918. // - ifindex (ifconfig does not print it out)
  919. // - address scopes and lifetimes (we don't need it, so it is not implemented in IfaceMgr)
  920. // TODO: temporarily disabled, see ticket #1529
  921. TEST_F(IfaceMgrTest, DISABLED_detectIfaces_linux) {
  922. NakedIfaceMgr* ifacemgr = new NakedIfaceMgr();
  923. IfaceMgr::IfaceCollection& detectedIfaces = ifacemgr->getIfacesLst();
  924. const std::string textFile = "ifconfig.txt";
  925. unlink(textFile.c_str());
  926. int result = system( ("/sbin/ifconfig -a > " + textFile).c_str());
  927. ASSERT_EQ(0, result);
  928. // list of interfaces parsed from ifconfig
  929. IfaceMgr::IfaceCollection parsedIfaces;
  930. ASSERT_NO_THROW(
  931. parse_ifconfig(textFile, parsedIfaces);
  932. );
  933. unlink(textFile.c_str());
  934. cout << "------Parsed interfaces---" << endl;
  935. for (IfaceMgr::IfaceCollection::iterator i = parsedIfaces.begin();
  936. i != parsedIfaces.end(); ++i) {
  937. cout << i->getName() << ": ifindex=" << i->getIndex() << ", mac=" << i->getPlainMac();
  938. cout << ", flags:";
  939. if (i->flag_up_) {
  940. cout << " UP";
  941. }
  942. if (i->flag_running_) {
  943. cout << " RUNNING";
  944. }
  945. if (i->flag_multicast_) {
  946. cout << " MULTICAST";
  947. }
  948. if (i->flag_broadcast_) {
  949. cout << " BROADCAST";
  950. }
  951. cout << ", addrs:";
  952. const IfaceMgr::AddressCollection& addrs = i->getAddresses();
  953. for (IfaceMgr::AddressCollection::const_iterator a= addrs.begin();
  954. a != addrs.end(); ++a) {
  955. cout << a->toText() << " ";
  956. }
  957. cout << endl;
  958. }
  959. // Ok, now we have 2 lists of interfaces. Need to compare them
  960. ASSERT_EQ(detectedIfaces.size(), parsedIfaces.size());
  961. // TODO: This could could probably be written simple with find()
  962. for (IfaceMgr::IfaceCollection::iterator detected = detectedIfaces.begin();
  963. detected != detectedIfaces.end(); ++detected) {
  964. // let's find out if this interface is
  965. bool found = false;
  966. for (IfaceMgr::IfaceCollection::iterator i = parsedIfaces.begin();
  967. i != parsedIfaces.end(); ++i) {
  968. if (detected->getName() != i->getName()) {
  969. continue;
  970. }
  971. found = true;
  972. cout << "Checking interface " << detected->getName() << endl;
  973. // start with checking flags
  974. EXPECT_EQ(detected->flag_loopback_, i->flag_loopback_);
  975. EXPECT_EQ(detected->flag_up_, i->flag_up_);
  976. EXPECT_EQ(detected->flag_running_, i->flag_running_);
  977. EXPECT_EQ(detected->flag_multicast_, i->flag_multicast_);
  978. EXPECT_EQ(detected->flag_broadcast_, i->flag_broadcast_);
  979. // skip MAC comparison for loopback as netlink returns MAC
  980. // 00:00:00:00:00:00 for lo
  981. if (!detected->flag_loopback_) {
  982. ASSERT_EQ(detected->getMacLen(), i->getMacLen());
  983. EXPECT_EQ(0, memcmp(detected->getMac(), i->getMac(), i->getMacLen()));
  984. }
  985. EXPECT_EQ(detected->getAddresses().size(), i->getAddresses().size());
  986. // now compare addresses
  987. const IfaceMgr::AddressCollection& addrs = detected->getAddresses();
  988. for (IfaceMgr::AddressCollection::const_iterator addr = addrs.begin();
  989. addr != addrs.end(); ++addr) {
  990. bool addr_found = false;
  991. const IfaceMgr::AddressCollection& addrs2 = detected->getAddresses();
  992. for (IfaceMgr::AddressCollection::const_iterator a = addrs2.begin();
  993. a != addrs2.end(); ++a) {
  994. if (*addr != *a) {
  995. continue;
  996. }
  997. addr_found = true;
  998. }
  999. if (!addr_found) {
  1000. cout << "ifconfig does not seem to report " << addr->toText()
  1001. << " address on " << detected->getFullName() << " interface." << endl;
  1002. FAIL();
  1003. }
  1004. cout << "Address " << addr->toText() << " on interface " << detected->getFullName()
  1005. << " matched with 'ifconfig -a' output." << endl;
  1006. }
  1007. }
  1008. if (!found) { // corresponding interface was not found
  1009. FAIL();
  1010. }
  1011. }
  1012. delete ifacemgr;
  1013. }
  1014. #endif
  1015. volatile bool callback_ok;
  1016. void my_callback(void) {
  1017. cout << "Callback triggered." << endl;
  1018. callback_ok = true;
  1019. }
  1020. TEST_F(IfaceMgrTest, controlSession) {
  1021. // tests if extra control socket and its callback can be passed and
  1022. // it is supported properly by receive4() method.
  1023. callback_ok = false;
  1024. NakedIfaceMgr* ifacemgr = new NakedIfaceMgr();
  1025. // create pipe and register it as extra socket
  1026. int pipefd[2];
  1027. EXPECT_TRUE(pipe(pipefd) == 0);
  1028. EXPECT_NO_THROW(ifacemgr->set_session_socket(pipefd[0], my_callback));
  1029. Pkt4Ptr pkt4;
  1030. ASSERT_NO_THROW(pkt4 = ifacemgr->receive4(1));
  1031. // Our callback should not be called this time (there was no data)
  1032. EXPECT_FALSE(callback_ok);
  1033. // IfaceMgr should not process control socket data as incoming packets
  1034. EXPECT_FALSE(pkt4);
  1035. // Now, send some data over pipe (38 bytes)
  1036. EXPECT_EQ(38, write(pipefd[1], "Hi, this is a message sent over a pipe", 38));
  1037. // ... and repeat
  1038. ASSERT_NO_THROW(pkt4 = ifacemgr->receive4(1));
  1039. // IfaceMgr should not process control socket data as incoming packets
  1040. EXPECT_FALSE(pkt4);
  1041. // There was some data, so this time callback should be called
  1042. EXPECT_TRUE(callback_ok);
  1043. delete ifacemgr;
  1044. // close both pipe ends
  1045. close(pipefd[1]);
  1046. close(pipefd[0]);
  1047. }
  1048. }