iface_mgr.cc 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
  1. // Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <config.h>
  15. #include <sstream>
  16. #include <fstream>
  17. #include <string.h>
  18. #include <netinet/in.h>
  19. #include <arpa/inet.h>
  20. #include <dhcp/dhcp4.h>
  21. #include <dhcp/dhcp6.h>
  22. #include <dhcp/iface_mgr.h>
  23. #include <exceptions/exceptions.h>
  24. #include <util/io/pktinfo_utilities.h>
  25. using namespace std;
  26. using namespace isc::asiolink;
  27. using namespace isc::util::io::internal;
  28. namespace isc {
  29. namespace dhcp {
  30. /// IfaceMgr is a singleton implementation
  31. IfaceMgr* IfaceMgr::instance_ = 0;
  32. void
  33. IfaceMgr::instanceCreate() {
  34. if (instance_) {
  35. // no need to do anything. Instance is already created.
  36. // Who called it again anyway? Uh oh. Had to be us, as
  37. // this is private method.
  38. return;
  39. }
  40. instance_ = new IfaceMgr();
  41. }
  42. IfaceMgr&
  43. IfaceMgr::instance() {
  44. if (instance_ == 0) {
  45. instanceCreate();
  46. }
  47. return (*instance_);
  48. }
  49. IfaceMgr::Iface::Iface(const std::string& name, int ifindex)
  50. :name_(name), ifindex_(ifindex), mac_len_(0), hardware_type_(0),
  51. flag_loopback_(false), flag_up_(false), flag_running_(false),
  52. flag_multicast_(false), flag_broadcast_(false), flags_(0)
  53. {
  54. memset(mac_, 0, sizeof(mac_));
  55. }
  56. std::string
  57. IfaceMgr::Iface::getFullName() const {
  58. ostringstream tmp;
  59. tmp << name_ << "/" << ifindex_;
  60. return (tmp.str());
  61. }
  62. std::string
  63. IfaceMgr::Iface::getPlainMac() const {
  64. ostringstream tmp;
  65. tmp.fill('0');
  66. tmp << hex;
  67. for (int i = 0; i < mac_len_; i++) {
  68. tmp.width(2);
  69. tmp << static_cast<int>(mac_[i]);
  70. if (i < mac_len_-1) {
  71. tmp << ":";
  72. }
  73. }
  74. return (tmp.str());
  75. }
  76. void IfaceMgr::Iface::setMac(const uint8_t* mac, size_t len) {
  77. if (len > IfaceMgr::MAX_MAC_LEN) {
  78. isc_throw(OutOfRange, "Interface " << getFullName()
  79. << " was detected to have link address of length "
  80. << len << ", but maximum supported length is "
  81. << IfaceMgr::MAX_MAC_LEN);
  82. }
  83. mac_len_ = len;
  84. memcpy(mac_, mac, len);
  85. }
  86. bool IfaceMgr::Iface::delAddress(const isc::asiolink::IOAddress& addr) {
  87. for (AddressCollection::iterator a = addrs_.begin();
  88. a!=addrs_.end(); ++a) {
  89. if (*a==addr) {
  90. addrs_.erase(a);
  91. return (true);
  92. }
  93. }
  94. return (false);
  95. }
  96. bool IfaceMgr::Iface::delSocket(uint16_t sockfd) {
  97. list<SocketInfo>::iterator sock = sockets_.begin();
  98. while (sock!=sockets_.end()) {
  99. if (sock->sockfd_ == sockfd) {
  100. close(sockfd);
  101. sockets_.erase(sock);
  102. return (true); //socket found
  103. }
  104. ++sock;
  105. }
  106. return (false); // socket not found
  107. }
  108. IfaceMgr::IfaceMgr()
  109. :control_buf_len_(CMSG_SPACE(sizeof(struct in6_pktinfo))),
  110. control_buf_(new char[control_buf_len_])
  111. {
  112. cout << "IfaceMgr initialization." << endl;
  113. try {
  114. // required for sending/receiving packets
  115. // let's keep it in front, just in case someone
  116. // wants to send anything during initialization
  117. // control_buf_ = boost::scoped_array<char>();
  118. detectIfaces();
  119. } catch (const std::exception& ex) {
  120. cout << "IfaceMgr creation failed:" << ex.what() << endl;
  121. // TODO Uncomment this (or call LOG_FATAL) once
  122. // interface detection is implemented. Otherwise
  123. // it is not possible to run tests in a portable
  124. // way (see detectIfaces() method).
  125. throw;
  126. }
  127. }
  128. void IfaceMgr::closeSockets() {
  129. for (IfaceCollection::iterator iface = ifaces_.begin();
  130. iface != ifaces_.end(); ++iface) {
  131. for (SocketCollection::iterator sock = iface->sockets_.begin();
  132. sock != iface->sockets_.end(); ++sock) {
  133. cout << "Closing socket " << sock->sockfd_ << endl;
  134. close(sock->sockfd_);
  135. }
  136. iface->sockets_.clear();
  137. }
  138. }
  139. IfaceMgr::~IfaceMgr() {
  140. // control_buf_ is deleted automatically (scoped_ptr)
  141. control_buf_len_ = 0;
  142. closeSockets();
  143. }
  144. void IfaceMgr::stubDetectIfaces() {
  145. string ifaceName;
  146. const string v4addr("127.0.0.1"), v6addr("::1");
  147. // This is a stub implementation for interface detection. Actual detection
  148. // is faked by detecting loopback interface (lo or lo0). It will eventually
  149. // be removed once we have actual implementations for all supported systems.
  150. cout << "Interface detection is not implemented on this Operating System yet. "
  151. << endl;
  152. try {
  153. if (if_nametoindex("lo") > 0) {
  154. ifaceName = "lo";
  155. // this is Linux-like OS
  156. } else if (if_nametoindex("lo0") > 0) {
  157. ifaceName = "lo0";
  158. // this is BSD-like OS
  159. } else {
  160. // we give up. What OS is this, anyway? Solaris? Hurd?
  161. isc_throw(NotImplemented,
  162. "Interface detection on this OS is not supported.");
  163. }
  164. Iface iface(ifaceName, if_nametoindex(ifaceName.c_str()));
  165. iface.flag_up_ = true;
  166. iface.flag_running_ = true;
  167. // note that we claim that this is not a loopback. iface_mgr tries to open a
  168. // socket on all interaces that are up, running and not loopback. As this is
  169. // the only interface we were able to detect, let's pretend this is a normal
  170. // interface.
  171. iface.flag_loopback_ = false;
  172. iface.flag_multicast_ = true;
  173. iface.flag_broadcast_ = true;
  174. iface.setHWType(HWTYPE_ETHERNET);
  175. iface.addAddress(IOAddress(v4addr));
  176. iface.addAddress(IOAddress(v6addr));
  177. addInterface(iface);
  178. cout << "Detected interface " << ifaceName << "/" << v4addr << "/"
  179. << v6addr << endl;
  180. } catch (const std::exception& ex) {
  181. // TODO: deallocate whatever memory we used
  182. // not that important, since this function is going to be
  183. // thrown away as soon as we get proper interface detection
  184. // implemented
  185. // TODO Do LOG_FATAL here
  186. std::cerr << "Interface detection failed." << std::endl;
  187. throw;
  188. }
  189. }
  190. bool IfaceMgr::openSockets4(const uint16_t port) {
  191. int sock;
  192. int count = 0;
  193. for (IfaceCollection::iterator iface=ifaces_.begin();
  194. iface!=ifaces_.end();
  195. ++iface) {
  196. cout << "Trying interface " << iface->getFullName() << endl;
  197. if (iface->flag_loopback_ ||
  198. !iface->flag_up_ ||
  199. !iface->flag_running_) {
  200. continue;
  201. }
  202. AddressCollection addrs = iface->getAddresses();
  203. for (AddressCollection::iterator addr= addrs.begin();
  204. addr != addrs.end();
  205. ++addr) {
  206. // skip IPv6 addresses
  207. if (addr->getFamily() != AF_INET) {
  208. continue;
  209. }
  210. sock = openSocket(iface->getName(), *addr, port);
  211. if (sock<0) {
  212. cout << "Failed to open unicast socket." << endl;
  213. return (false);
  214. }
  215. count++;
  216. }
  217. }
  218. return (count > 0);
  219. }
  220. bool IfaceMgr::openSockets6(const uint16_t port) {
  221. int sock;
  222. int count = 0;
  223. for (IfaceCollection::iterator iface=ifaces_.begin();
  224. iface!=ifaces_.end();
  225. ++iface) {
  226. if (iface->flag_loopback_ ||
  227. !iface->flag_up_ ||
  228. !iface->flag_running_) {
  229. continue;
  230. }
  231. AddressCollection addrs = iface->getAddresses();
  232. for (AddressCollection::iterator addr= addrs.begin();
  233. addr != addrs.end();
  234. ++addr) {
  235. // skip IPv4 addresses
  236. if (addr->getFamily() != AF_INET6) {
  237. continue;
  238. }
  239. sock = openSocket(iface->getName(), *addr, port);
  240. if (sock<0) {
  241. cout << "Failed to open unicast socket." << endl;
  242. return (false);
  243. }
  244. // Binding socket to unicast address and then joining multicast group
  245. // works well on Mac OS (and possibly other BSDs), but does not work
  246. // on Linux.
  247. if ( !joinMulticast(sock, iface->getName(),
  248. string(ALL_DHCP_RELAY_AGENTS_AND_SERVERS) ) ) {
  249. close(sock);
  250. isc_throw(Unexpected, "Failed to join " << ALL_DHCP_RELAY_AGENTS_AND_SERVERS
  251. << " multicast group.");
  252. }
  253. count++;
  254. /// @todo: Remove this ifdef once we start supporting BSD systems.
  255. #if defined(OS_LINUX)
  256. // To receive multicast traffic, Linux requires binding socket to
  257. // a multicast group. That in turn doesn't work on NetBSD.
  258. int sock2 = openSocket(iface->getName(),
  259. IOAddress(ALL_DHCP_RELAY_AGENTS_AND_SERVERS),
  260. port);
  261. if (sock2<0) {
  262. isc_throw(Unexpected, "Failed to open multicast socket on "
  263. << " interface " << iface->getFullName());
  264. iface->delSocket(sock); // delete previously opened socket
  265. }
  266. #endif
  267. }
  268. }
  269. return (count > 0);
  270. }
  271. void
  272. IfaceMgr::printIfaces(std::ostream& out /*= std::cout*/) {
  273. for (IfaceCollection::const_iterator iface=ifaces_.begin();
  274. iface!=ifaces_.end();
  275. ++iface) {
  276. const AddressCollection& addrs = iface->getAddresses();
  277. out << "Detected interface " << iface->getFullName()
  278. << ", hwtype=" << iface->getHWType()
  279. << ", mac=" << iface->getPlainMac();
  280. out << ", flags=" << hex << iface->flags_ << dec << "("
  281. << (iface->flag_loopback_?"LOOPBACK ":"")
  282. << (iface->flag_up_?"UP ":"")
  283. << (iface->flag_running_?"RUNNING ":"")
  284. << (iface->flag_multicast_?"MULTICAST ":"")
  285. << (iface->flag_broadcast_?"BROADCAST ":"")
  286. << ")" << endl;
  287. out << " " << addrs.size() << " addr(s):";
  288. for (AddressCollection::const_iterator addr = addrs.begin();
  289. addr != addrs.end(); ++addr) {
  290. out << " " << addr->toText();
  291. }
  292. out << endl;
  293. }
  294. }
  295. IfaceMgr::Iface*
  296. IfaceMgr::getIface(int ifindex) {
  297. for (IfaceCollection::iterator iface=ifaces_.begin();
  298. iface!=ifaces_.end();
  299. ++iface) {
  300. if (iface->getIndex() == ifindex)
  301. return (&(*iface));
  302. }
  303. return (NULL); // not found
  304. }
  305. IfaceMgr::Iface*
  306. IfaceMgr::getIface(const std::string& ifname) {
  307. for (IfaceCollection::iterator iface=ifaces_.begin();
  308. iface!=ifaces_.end();
  309. ++iface) {
  310. if (iface->getName() == ifname)
  311. return (&(*iface));
  312. }
  313. return (NULL); // not found
  314. }
  315. int IfaceMgr::openSocket(const std::string& ifname, const IOAddress& addr,
  316. const uint16_t port) {
  317. Iface* iface = getIface(ifname);
  318. if (!iface) {
  319. isc_throw(BadValue, "There is no " << ifname << " interface present.");
  320. }
  321. switch (addr.getFamily()) {
  322. case AF_INET:
  323. return openSocket4(*iface, addr, port);
  324. case AF_INET6:
  325. return openSocket6(*iface, addr, port);
  326. default:
  327. isc_throw(BadValue, "Failed to detect family of address: "
  328. << addr.toText());
  329. }
  330. }
  331. int IfaceMgr::openSocket4(Iface& iface, const IOAddress& addr, uint16_t port) {
  332. cout << "Creating UDP4 socket on " << iface.getFullName()
  333. << " " << addr.toText() << "/port=" << port << endl;
  334. struct sockaddr_in addr4;
  335. memset(&addr4, 0, sizeof(sockaddr));
  336. addr4.sin_family = AF_INET;
  337. addr4.sin_port = htons(port);
  338. addr4.sin_addr.s_addr = htonl(addr);
  339. //addr4.sin_addr.s_addr = 0; // anyaddr: this will receive 0.0.0.0 => 255.255.255.255 traffic
  340. // addr4.sin_addr.s_addr = 0xffffffffu; // broadcast address. This will receive 0.0.0.0 => 255.255.255.255 as well
  341. int sock = socket(AF_INET, SOCK_DGRAM, 0);
  342. if (sock < 0) {
  343. isc_throw(Unexpected, "Failed to create UDP6 socket.");
  344. }
  345. if (bind(sock, (struct sockaddr *)&addr4, sizeof(addr4)) < 0) {
  346. close(sock);
  347. isc_throw(Unexpected, "Failed to bind socket " << sock << " to " << addr.toText()
  348. << "/port=" << port);
  349. }
  350. // if there is no support for IP_PKTINFO, we are really out of luck
  351. // it will be difficult to undersand, where this packet came from
  352. #if defined(IP_PKTINFO)
  353. int flag = 1;
  354. if (setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &flag, sizeof(flag)) != 0) {
  355. close(sock);
  356. isc_throw(Unexpected, "setsockopt: IP_PKTINFO: failed.");
  357. }
  358. #endif
  359. cout << "Created socket " << sock << " on " << iface.getName() << "/" <<
  360. addr.toText() << "/port=" << port << endl;
  361. SocketInfo info(sock, addr, port);
  362. iface.addSocket(info);
  363. return (sock);
  364. }
  365. int IfaceMgr::openSocket6(Iface& iface, const IOAddress& addr, uint16_t port) {
  366. cout << "Creating UDP6 socket on " << iface.getFullName()
  367. << " " << addr.toText() << "/port=" << port << endl;
  368. struct sockaddr_in6 addr6;
  369. memset(&addr6, 0, sizeof(addr6));
  370. addr6.sin6_family = AF_INET6;
  371. addr6.sin6_port = htons(port);
  372. if (addr.toText() != "::1")
  373. addr6.sin6_scope_id = if_nametoindex(iface.getName().c_str());
  374. memcpy(&addr6.sin6_addr,
  375. addr.getAddress().to_v6().to_bytes().data(),
  376. sizeof(addr6.sin6_addr));
  377. #ifdef HAVE_SA_LEN
  378. addr6.sin6_len = sizeof(addr6);
  379. #endif
  380. // TODO: use sockcreator once it becomes available
  381. // make a socket
  382. int sock = socket(AF_INET6, SOCK_DGRAM, 0);
  383. if (sock < 0) {
  384. isc_throw(Unexpected, "Failed to create UDP6 socket.");
  385. }
  386. // Set the REUSEADDR option so that we don't fail to start if
  387. // we're being restarted.
  388. int flag = 1;
  389. if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
  390. (char *)&flag, sizeof(flag)) < 0) {
  391. close(sock);
  392. isc_throw(Unexpected, "Can't set SO_REUSEADDR option on dhcpv6 socket.");
  393. }
  394. if (bind(sock, (struct sockaddr *)&addr6, sizeof(addr6)) < 0) {
  395. close(sock);
  396. isc_throw(Unexpected, "Failed to bind socket " << sock << " to " << addr.toText()
  397. << "/port=" << port);
  398. }
  399. #ifdef IPV6_RECVPKTINFO
  400. // RFC3542 - a new way
  401. if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO,
  402. &flag, sizeof(flag)) != 0) {
  403. close(sock);
  404. isc_throw(Unexpected, "setsockopt: IPV6_RECVPKTINFO failed.");
  405. }
  406. #else
  407. // RFC2292 - an old way
  408. if (setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO,
  409. &flag, sizeof(flag)) != 0) {
  410. close(sock);
  411. isc_throw(Unexpected, "setsockopt: IPV6_PKTINFO: failed.");
  412. }
  413. #endif
  414. // multicast stuff
  415. if (addr.getAddress().to_v6().is_multicast()) {
  416. // both mcast (ALL_DHCP_RELAY_AGENTS_AND_SERVERS and ALL_DHCP_SERVERS)
  417. // are link and site-scoped, so there is no sense to join those groups
  418. // with global addresses.
  419. if ( !joinMulticast( sock, iface.getName(),
  420. string(ALL_DHCP_RELAY_AGENTS_AND_SERVERS) ) ) {
  421. close(sock);
  422. isc_throw(Unexpected, "Failed to join " << ALL_DHCP_RELAY_AGENTS_AND_SERVERS
  423. << " multicast group.");
  424. }
  425. }
  426. cout << "Created socket " << sock << " on " << iface.getName() << "/" <<
  427. addr.toText() << "/port=" << port << endl;
  428. SocketInfo info(sock, addr, port);
  429. iface.addSocket(info);
  430. return (sock);
  431. }
  432. bool
  433. IfaceMgr::joinMulticast(int sock, const std::string& ifname,
  434. const std::string & mcast) {
  435. struct ipv6_mreq mreq;
  436. if (inet_pton(AF_INET6, mcast.c_str(),
  437. &mreq.ipv6mr_multiaddr) <= 0) {
  438. cout << "Failed to convert " << ifname
  439. << " to IPv6 multicast address." << endl;
  440. return (false);
  441. }
  442. mreq.ipv6mr_interface = if_nametoindex(ifname.c_str());
  443. if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
  444. &mreq, sizeof(mreq)) < 0) {
  445. cout << "Failed to join " << mcast << " multicast group." << endl;
  446. return (false);
  447. }
  448. cout << "Joined multicast " << mcast << " group." << endl;
  449. return (true);
  450. }
  451. bool
  452. IfaceMgr::send(const Pkt6Ptr& pkt) {
  453. int result;
  454. Iface* iface = getIface(pkt->getIface());
  455. if (!iface) {
  456. isc_throw(BadValue, "Unable to send Pkt6. Invalid interface ("
  457. << pkt->getIface() << ") specified.");
  458. }
  459. memset(&control_buf_[0], 0, control_buf_len_);
  460. // Set the target address we're sending to.
  461. sockaddr_in6 to;
  462. memset(&to, 0, sizeof(to));
  463. to.sin6_family = AF_INET6;
  464. to.sin6_port = htons(pkt->getRemotePort());
  465. memcpy(&to.sin6_addr,
  466. pkt->getRemoteAddr().getAddress().to_v6().to_bytes().data(),
  467. 16);
  468. to.sin6_scope_id = pkt->getIndex();
  469. // Initialize our message header structure.
  470. struct msghdr m;
  471. memset(&m, 0, sizeof(m));
  472. m.msg_name = &to;
  473. m.msg_namelen = sizeof(to);
  474. // Set the data buffer we're sending. (Using this wacky
  475. // "scatter-gather" stuff... we only have a single chunk
  476. // of data to send, so we declare a single vector entry.)
  477. // As v structure is a C-style is used for both sending and
  478. // receiving data, it is shared between sending and receiving
  479. // (sendmsg and recvmsg). It is also defined in system headers,
  480. // so we have no control over its definition. To set iov_base
  481. // (defined as void*) we must use const cast from void *.
  482. // Otherwise C++ compiler would complain that we are trying
  483. // to assign const void* to void*.
  484. struct iovec v;
  485. memset(&v, 0, sizeof(v));
  486. v.iov_base = const_cast<void *>(pkt->getBuffer().getData());
  487. v.iov_len = pkt->getBuffer().getLength();
  488. m.msg_iov = &v;
  489. m.msg_iovlen = 1;
  490. // Setting the interface is a bit more involved.
  491. //
  492. // We have to create a "control message", and set that to
  493. // define the IPv6 packet information. We could set the
  494. // source address if we wanted, but we can safely let the
  495. // kernel decide what that should be.
  496. m.msg_control = &control_buf_[0];
  497. m.msg_controllen = control_buf_len_;
  498. struct cmsghdr *cmsg = CMSG_FIRSTHDR(&m);
  499. cmsg->cmsg_level = IPPROTO_IPV6;
  500. cmsg->cmsg_type = IPV6_PKTINFO;
  501. cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
  502. struct in6_pktinfo *pktinfo = convertPktInfo6(CMSG_DATA(cmsg));
  503. memset(pktinfo, 0, sizeof(struct in6_pktinfo));
  504. pktinfo->ipi6_ifindex = pkt->getIndex();
  505. m.msg_controllen = cmsg->cmsg_len;
  506. pkt->updateTimestamp();
  507. result = sendmsg(getSocket(*pkt), &m, 0);
  508. if (result < 0) {
  509. isc_throw(Unexpected, "Pkt6 send failed: sendmsg() returned " << result);
  510. }
  511. cout << "Sent " << pkt->getBuffer().getLength() << " bytes over socket " << getSocket(*pkt)
  512. << " on " << iface->getFullName() << " interface: "
  513. << " dst=[" << pkt->getRemoteAddr().toText() << "]:" << pkt->getRemotePort()
  514. << ", src=" << pkt->getLocalAddr().toText() << "]:" << pkt->getLocalPort()
  515. << endl;
  516. return (result);
  517. }
  518. bool
  519. IfaceMgr::send(const Pkt4Ptr& pkt)
  520. {
  521. Iface* iface = getIface(pkt->getIface());
  522. if (!iface) {
  523. isc_throw(BadValue, "Unable to send Pkt4. Invalid interface ("
  524. << pkt->getIface() << ") specified.");
  525. }
  526. memset(&control_buf_[0], 0, control_buf_len_);
  527. // Set the target address we're sending to.
  528. sockaddr_in to;
  529. memset(&to, 0, sizeof(to));
  530. to.sin_family = AF_INET;
  531. to.sin_port = htons(pkt->getRemotePort());
  532. to.sin_addr.s_addr = htonl(pkt->getRemoteAddr());
  533. struct msghdr m;
  534. // Initialize our message header structure.
  535. memset(&m, 0, sizeof(m));
  536. m.msg_name = &to;
  537. m.msg_namelen = sizeof(to);
  538. // Set the data buffer we're sending. (Using this wacky
  539. // "scatter-gather" stuff... we only have a single chunk
  540. // of data to send, so we declare a single vector entry.)
  541. struct iovec v;
  542. memset(&v, 0, sizeof(v));
  543. // iov_base field is of void * type. We use it for packet
  544. // transmission, so this buffer will not be modified.
  545. v.iov_base = const_cast<void *>(pkt->getBuffer().getData());
  546. v.iov_len = pkt->getBuffer().getLength();
  547. m.msg_iov = &v;
  548. m.msg_iovlen = 1;
  549. // call OS-specific routines (like setting interface index)
  550. os_send4(m, control_buf_, control_buf_len_, pkt);
  551. cout << "Trying to send " << pkt->getBuffer().getLength() << " bytes to "
  552. << pkt->getRemoteAddr().toText() << ":" << pkt->getRemotePort()
  553. << " over socket " << getSocket(*pkt) << " on interface "
  554. << getIface(pkt->getIface())->getFullName() << endl;
  555. pkt->updateTimestamp();
  556. int result = sendmsg(getSocket(*pkt), &m, 0);
  557. if (result < 0) {
  558. isc_throw(Unexpected, "Pkt4 send failed.");
  559. }
  560. cout << "Sent " << pkt->getBuffer().getLength() << " bytes over socket " << getSocket(*pkt)
  561. << " on " << iface->getFullName() << " interface: "
  562. << " dst=" << pkt->getRemoteAddr().toText() << ":" << pkt->getRemotePort()
  563. << ", src=" << pkt->getLocalAddr().toText() << ":" << pkt->getLocalPort()
  564. << endl;
  565. return (result);
  566. }
  567. boost::shared_ptr<Pkt4>
  568. IfaceMgr::receive4() {
  569. const SocketInfo* candidate = 0;
  570. IfaceCollection::const_iterator iface;
  571. for (iface = ifaces_.begin(); iface != ifaces_.end(); ++iface) {
  572. /// @todo: rewrite this as part of #1555
  573. for (SocketCollection::const_iterator s = iface->sockets_.begin();
  574. s != iface->sockets_.end(); ++s) {
  575. // We don't want IPv6 addresses here.
  576. if (s->addr_.getFamily() != AF_INET) {
  577. continue;
  578. }
  579. // This address looks good.
  580. if (!candidate) {
  581. candidate = &(*s);
  582. break;
  583. }
  584. }
  585. if (candidate) {
  586. break;
  587. }
  588. }
  589. if (!candidate) {
  590. isc_throw(Unexpected, "Failed to find any suitable sockets on all interfaces.");
  591. }
  592. cout << "Trying to receive over UDP4 socket " << candidate->sockfd_ << " bound to "
  593. << candidate->addr_.toText() << "/port=" << candidate->port_ << " on "
  594. << iface->getFullName() << endl;
  595. // Now we have a socket, let's get some data from it!
  596. struct sockaddr_in from_addr;
  597. uint8_t buf[RCVBUFSIZE];
  598. memset(&control_buf_[0], 0, control_buf_len_);
  599. memset(&from_addr, 0, sizeof(from_addr));
  600. // Initialize our message header structure.
  601. struct msghdr m;
  602. memset(&m, 0, sizeof(m));
  603. // Point so we can get the from address.
  604. m.msg_name = &from_addr;
  605. m.msg_namelen = sizeof(from_addr);
  606. struct iovec v;
  607. v.iov_base = static_cast<void*>(buf);
  608. v.iov_len = RCVBUFSIZE;
  609. m.msg_iov = &v;
  610. m.msg_iovlen = 1;
  611. // Getting the interface is a bit more involved.
  612. //
  613. // We set up some space for a "control message". We have
  614. // previously asked the kernel to give us packet
  615. // information (when we initialized the interface), so we
  616. // should get the destination address from that.
  617. m.msg_control = &control_buf_[0];
  618. m.msg_controllen = control_buf_len_;
  619. int result = recvmsg(candidate->sockfd_, &m, 0);
  620. if (result < 0) {
  621. cout << "Failed to receive UDP4 data." << endl;
  622. return (Pkt4Ptr()); // NULL
  623. }
  624. // We have all data let's create Pkt4 object.
  625. Pkt4Ptr pkt = Pkt4Ptr(new Pkt4(buf, result));
  626. pkt->updateTimestamp();
  627. unsigned int ifindex = iface->getIndex();
  628. IOAddress from(htonl(from_addr.sin_addr.s_addr));
  629. uint16_t from_port = htons(from_addr.sin_port);
  630. // Set receiving interface based on information, which socket was used to
  631. // receive data. OS-specific info (see os_receive4()) may be more reliable,
  632. // so this value may be overwritten.
  633. pkt->setIndex(ifindex);
  634. pkt->setIface(iface->getName());
  635. pkt->setRemoteAddr(from);
  636. pkt->setRemotePort(from_port);
  637. pkt->setLocalPort(candidate->port_);
  638. if (!os_receive4(m, pkt)) {
  639. cout << "Unable to find pktinfo" << endl;
  640. return (boost::shared_ptr<Pkt4>()); // NULL
  641. }
  642. cout << "Received " << result << " bytes from " << from.toText()
  643. << "/port=" << from_port
  644. << " sent to " << pkt->getLocalAddr().toText() << " over interface "
  645. << iface->getFullName() << endl;
  646. return (pkt);
  647. }
  648. Pkt6Ptr IfaceMgr::receive6() {
  649. uint8_t buf[RCVBUFSIZE];
  650. memset(&control_buf_[0], 0, control_buf_len_);
  651. struct sockaddr_in6 from;
  652. memset(&from, 0, sizeof(from));
  653. // Initialize our message header structure.
  654. struct msghdr m;
  655. memset(&m, 0, sizeof(m));
  656. // Point so we can get the from address.
  657. m.msg_name = &from;
  658. m.msg_namelen = sizeof(from);
  659. // Set the data buffer we're receiving. (Using this wacky
  660. // "scatter-gather" stuff... but we that doesn't really make
  661. // sense for us, so we use a single vector entry.)
  662. struct iovec v;
  663. memset(&v, 0, sizeof(v));
  664. v.iov_base = static_cast<void*>(buf);
  665. v.iov_len = RCVBUFSIZE;
  666. m.msg_iov = &v;
  667. m.msg_iovlen = 1;
  668. // Getting the interface is a bit more involved.
  669. //
  670. // We set up some space for a "control message". We have
  671. // previously asked the kernel to give us packet
  672. // information (when we initialized the interface), so we
  673. // should get the destination address from that.
  674. m.msg_control = &control_buf_[0];
  675. m.msg_controllen = control_buf_len_;
  676. /// TODO: Need to move to select() and pool over
  677. /// all available sockets. For now, we just take the
  678. /// first interface and use first socket from it.
  679. IfaceCollection::const_iterator iface = ifaces_.begin();
  680. const SocketInfo* candidate = 0;
  681. while (iface != ifaces_.end()) {
  682. for (SocketCollection::const_iterator s = iface->sockets_.begin();
  683. s != iface->sockets_.end(); ++s) {
  684. if (s->addr_.getFamily() != AF_INET6) {
  685. continue;
  686. }
  687. if (s->addr_.getAddress().to_v6().is_multicast()) {
  688. candidate = &(*s);
  689. break;
  690. }
  691. if (!candidate) {
  692. candidate = &(*s); // it's not multicast, but it's better than nothing
  693. }
  694. }
  695. if (candidate) {
  696. break;
  697. }
  698. ++iface;
  699. }
  700. if (iface == ifaces_.end()) {
  701. isc_throw(Unexpected, "No suitable IPv6 interfaces detected. Can't receive anything.");
  702. }
  703. if (!candidate) {
  704. isc_throw(Unexpected, "Interface " << iface->getFullName()
  705. << " does not have any sockets open.");
  706. }
  707. cout << "Trying to receive over UDP6 socket " << candidate->sockfd_ << " bound to "
  708. << candidate->addr_.toText() << "/port=" << candidate->port_ << " on "
  709. << iface->getFullName() << endl;
  710. int result = recvmsg(candidate->sockfd_, &m, 0);
  711. struct in6_addr to_addr;
  712. memset(&to_addr, 0, sizeof(to_addr));
  713. int ifindex = -1;
  714. if (result >= 0) {
  715. struct in6_pktinfo* pktinfo = NULL;
  716. // If we did read successfully, then we need to loop
  717. // through the control messages we received and
  718. // find the one with our destination address.
  719. //
  720. // We also keep a flag to see if we found it. If we
  721. // didn't, then we consider this to be an error.
  722. bool found_pktinfo = false;
  723. struct cmsghdr* cmsg = CMSG_FIRSTHDR(&m);
  724. while (cmsg != NULL) {
  725. if ((cmsg->cmsg_level == IPPROTO_IPV6) &&
  726. (cmsg->cmsg_type == IPV6_PKTINFO)) {
  727. pktinfo = convertPktInfo6(CMSG_DATA(cmsg));
  728. to_addr = pktinfo->ipi6_addr;
  729. ifindex = pktinfo->ipi6_ifindex;
  730. found_pktinfo = true;
  731. break;
  732. }
  733. cmsg = CMSG_NXTHDR(&m, cmsg);
  734. }
  735. if (!found_pktinfo) {
  736. cout << "Unable to find pktinfo" << endl;
  737. return (Pkt6Ptr()); // NULL
  738. }
  739. } else {
  740. cout << "Failed to receive data." << endl;
  741. return (Pkt6Ptr()); // NULL
  742. }
  743. // Let's create a packet.
  744. Pkt6Ptr pkt;
  745. try {
  746. pkt = Pkt6Ptr(new Pkt6(buf, result));
  747. } catch (const std::exception& ex) {
  748. cout << "Failed to create new packet." << endl;
  749. return (Pkt6Ptr()); // NULL
  750. }
  751. pkt->updateTimestamp();
  752. pkt->setLocalAddr(IOAddress::from_bytes(AF_INET6,
  753. reinterpret_cast<const uint8_t*>(&to_addr)));
  754. pkt->setRemoteAddr(IOAddress::from_bytes(AF_INET6,
  755. reinterpret_cast<const uint8_t*>(&from.sin6_addr)));
  756. pkt->setRemotePort(ntohs(from.sin6_port));
  757. pkt->setIndex(ifindex);
  758. Iface* received = getIface(pkt->getIndex());
  759. if (received) {
  760. pkt->setIface(received->getName());
  761. } else {
  762. cout << "Received packet over unknown interface (ifindex="
  763. << pkt->getIndex() << ")." << endl;
  764. return (boost::shared_ptr<Pkt6>()); // NULL
  765. }
  766. /// @todo: Move this to LOG_DEBUG
  767. cout << "Received " << pkt->getBuffer().getLength() << " bytes over "
  768. << pkt->getIface() << "/" << pkt->getIndex() << " interface: "
  769. << " src=" << pkt->getRemoteAddr().toText()
  770. << ", dst=" << pkt->getLocalAddr().toText()
  771. << endl;
  772. return (pkt);
  773. }
  774. uint16_t IfaceMgr::getSocket(const isc::dhcp::Pkt6& pkt) {
  775. Iface* iface = getIface(pkt.getIface());
  776. if (iface == NULL) {
  777. isc_throw(BadValue, "Tried to find socket for non-existent interface "
  778. << pkt.getIface());
  779. }
  780. SocketCollection::const_iterator s;
  781. for (s = iface->sockets_.begin(); s != iface->sockets_.end(); ++s) {
  782. if ((s->family_ == AF_INET6) &&
  783. (!s->addr_.getAddress().to_v6().is_multicast())) {
  784. return (s->sockfd_);
  785. }
  786. /// @todo: Add more checks here later. If remote address is
  787. /// not link-local, we can't use link local bound socket
  788. /// to send data.
  789. }
  790. isc_throw(Unexpected, "Interface " << iface->getFullName()
  791. << " does not have any suitable IPv6 sockets open.");
  792. }
  793. uint16_t IfaceMgr::getSocket(isc::dhcp::Pkt4 const& pkt) {
  794. Iface* iface = getIface(pkt.getIface());
  795. if (iface == NULL) {
  796. isc_throw(BadValue, "Tried to find socket for non-existent interface "
  797. << pkt.getIface());
  798. }
  799. SocketCollection::const_iterator s;
  800. for (s = iface->sockets_.begin(); s != iface->sockets_.end(); ++s) {
  801. if (s->family_ == AF_INET) {
  802. return (s->sockfd_);
  803. }
  804. /// TODO: Add more checks here later. If remote address is
  805. /// not link-local, we can't use link local bound socket
  806. /// to send data.
  807. }
  808. isc_throw(Unexpected, "Interface " << iface->getFullName()
  809. << " does not have any suitable IPv4 sockets open.");
  810. }
  811. } // end of namespace isc::dhcp
  812. } // end of namespace isc