iface_mgr_unittest.cc 37 KB

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