iface_mgr_unittest.cc 42 KB

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