iface_mgr.cc 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963
  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, linkLocal;
  146. // This is a stub implementation for interface detection. Actual detection
  147. // is faked by reading a text file. It will eventually be removed once
  148. // we have actual implementations for all supported systems.
  149. cout << "Interface detection is not implemented yet. "
  150. << "Reading interfaces.txt file instead." << endl;
  151. cout << "Please use format: interface-name link-local-address" << endl;
  152. try {
  153. ifstream interfaces("interfaces.txt");
  154. if (!interfaces.good()) {
  155. cout << "interfaces.txt file is not available. Stub interface detection skipped." << endl;
  156. return;
  157. }
  158. interfaces >> ifaceName;
  159. interfaces >> linkLocal;
  160. cout << "Detected interface " << ifaceName << "/" << linkLocal << endl;
  161. Iface iface(ifaceName, if_nametoindex(ifaceName.c_str()));
  162. iface.flag_up_ = true;
  163. iface.flag_running_ = true;
  164. iface.flag_loopback_ = false;
  165. iface.flag_multicast_ = true;
  166. iface.flag_broadcast_ = true;
  167. iface.setHWType(HWTYPE_ETHERNET);
  168. IOAddress addr(linkLocal);
  169. iface.addAddress(addr);
  170. addInterface(iface);
  171. interfaces.close();
  172. } catch (const std::exception& ex) {
  173. // TODO: deallocate whatever memory we used
  174. // not that important, since this function is going to be
  175. // thrown away as soon as we get proper interface detection
  176. // implemented
  177. // TODO Do LOG_FATAL here
  178. std::cerr << "Interface detection failed." << std::endl;
  179. throw;
  180. }
  181. }
  182. bool IfaceMgr::openSockets4(const uint16_t port) {
  183. int sock;
  184. int count = 0;
  185. for (IfaceCollection::iterator iface=ifaces_.begin();
  186. iface!=ifaces_.end();
  187. ++iface) {
  188. cout << "Trying interface " << iface->getFullName() << endl;
  189. if (iface->flag_loopback_ ||
  190. !iface->flag_up_ ||
  191. !iface->flag_running_) {
  192. continue;
  193. }
  194. AddressCollection addrs = iface->getAddresses();
  195. for (AddressCollection::iterator addr= addrs.begin();
  196. addr != addrs.end();
  197. ++addr) {
  198. // skip IPv6 addresses
  199. if (addr->getFamily() != AF_INET) {
  200. continue;
  201. }
  202. sock = openSocket(iface->getName(), *addr, port);
  203. if (sock<0) {
  204. cout << "Failed to open unicast socket." << endl;
  205. return (false);
  206. }
  207. count++;
  208. }
  209. }
  210. return (count > 0);
  211. }
  212. bool IfaceMgr::openSockets6(const uint16_t port) {
  213. int sock;
  214. int count = 0;
  215. for (IfaceCollection::iterator iface=ifaces_.begin();
  216. iface!=ifaces_.end();
  217. ++iface) {
  218. if (iface->flag_loopback_ ||
  219. !iface->flag_up_ ||
  220. !iface->flag_running_) {
  221. continue;
  222. }
  223. AddressCollection addrs = iface->getAddresses();
  224. for (AddressCollection::iterator addr= addrs.begin();
  225. addr != addrs.end();
  226. ++addr) {
  227. // skip IPv4 addresses
  228. if (addr->getFamily() != AF_INET6) {
  229. continue;
  230. }
  231. sock = openSocket(iface->getName(), *addr, port);
  232. if (sock<0) {
  233. cout << "Failed to open unicast socket." << endl;
  234. return (false);
  235. }
  236. // Binding socket to unicast address and then joining multicast group
  237. // works well on Mac OS (and possibly other BSDs), but does not work
  238. // on Linux.
  239. if ( !joinMulticast(sock, iface->getName(),
  240. string(ALL_DHCP_RELAY_AGENTS_AND_SERVERS) ) ) {
  241. close(sock);
  242. isc_throw(Unexpected, "Failed to join " << ALL_DHCP_RELAY_AGENTS_AND_SERVERS
  243. << " multicast group.");
  244. }
  245. count++;
  246. /// @todo: Remove this ifdef once we start supporting BSD systems.
  247. #if defined(OS_LINUX)
  248. // To receive multicast traffic, Linux requires binding socket to
  249. // a multicast group. That in turn doesn't work on NetBSD.
  250. int sock2 = openSocket(iface->getName(),
  251. IOAddress(ALL_DHCP_RELAY_AGENTS_AND_SERVERS),
  252. port);
  253. if (sock2<0) {
  254. isc_throw(Unexpected, "Failed to open multicast socket on "
  255. << " interface " << iface->getFullName());
  256. iface->delSocket(sock); // delete previously opened socket
  257. }
  258. #endif
  259. }
  260. }
  261. return (count > 0);
  262. }
  263. void
  264. IfaceMgr::printIfaces(std::ostream& out /*= std::cout*/) {
  265. for (IfaceCollection::const_iterator iface=ifaces_.begin();
  266. iface!=ifaces_.end();
  267. ++iface) {
  268. const AddressCollection& addrs = iface->getAddresses();
  269. out << "Detected interface " << iface->getFullName()
  270. << ", hwtype=" << iface->getHWType()
  271. << ", mac=" << iface->getPlainMac();
  272. out << ", flags=" << hex << iface->flags_ << dec << "("
  273. << (iface->flag_loopback_?"LOOPBACK ":"")
  274. << (iface->flag_up_?"UP ":"")
  275. << (iface->flag_running_?"RUNNING ":"")
  276. << (iface->flag_multicast_?"MULTICAST ":"")
  277. << (iface->flag_broadcast_?"BROADCAST ":"")
  278. << ")" << endl;
  279. out << " " << addrs.size() << " addr(s):";
  280. for (AddressCollection::const_iterator addr = addrs.begin();
  281. addr != addrs.end(); ++addr) {
  282. out << " " << addr->toText();
  283. }
  284. out << endl;
  285. }
  286. }
  287. IfaceMgr::Iface*
  288. IfaceMgr::getIface(int ifindex) {
  289. for (IfaceCollection::iterator iface=ifaces_.begin();
  290. iface!=ifaces_.end();
  291. ++iface) {
  292. if (iface->getIndex() == ifindex)
  293. return (&(*iface));
  294. }
  295. return (NULL); // not found
  296. }
  297. IfaceMgr::Iface*
  298. IfaceMgr::getIface(const std::string& ifname) {
  299. for (IfaceCollection::iterator iface=ifaces_.begin();
  300. iface!=ifaces_.end();
  301. ++iface) {
  302. if (iface->getName() == ifname)
  303. return (&(*iface));
  304. }
  305. return (NULL); // not found
  306. }
  307. int IfaceMgr::openSocket(const std::string& ifname, const IOAddress& addr,
  308. const uint16_t port) {
  309. Iface* iface = getIface(ifname);
  310. if (!iface) {
  311. isc_throw(BadValue, "There is no " << ifname << " interface present.");
  312. }
  313. switch (addr.getFamily()) {
  314. case AF_INET:
  315. return openSocket4(*iface, addr, port);
  316. case AF_INET6:
  317. return openSocket6(*iface, addr, port);
  318. default:
  319. isc_throw(BadValue, "Failed to detect family of address: "
  320. << addr.toText());
  321. }
  322. }
  323. int IfaceMgr::openSocket4(Iface& iface, const IOAddress& addr, uint16_t port) {
  324. cout << "Creating UDP4 socket on " << iface.getFullName()
  325. << " " << addr.toText() << "/port=" << port << endl;
  326. struct sockaddr_in addr4;
  327. memset(&addr4, 0, sizeof(sockaddr));
  328. addr4.sin_family = AF_INET;
  329. addr4.sin_port = htons(port);
  330. addr4.sin_addr.s_addr = htonl(addr);
  331. //addr4.sin_addr.s_addr = 0; // anyaddr: this will receive 0.0.0.0 => 255.255.255.255 traffic
  332. // addr4.sin_addr.s_addr = 0xffffffffu; // broadcast address. This will receive 0.0.0.0 => 255.255.255.255 as well
  333. int sock = socket(AF_INET, SOCK_DGRAM, 0);
  334. if (sock < 0) {
  335. isc_throw(Unexpected, "Failed to create UDP6 socket.");
  336. }
  337. if (bind(sock, (struct sockaddr *)&addr4, sizeof(addr4)) < 0) {
  338. close(sock);
  339. isc_throw(Unexpected, "Failed to bind socket " << sock << " to " << addr.toText()
  340. << "/port=" << port);
  341. }
  342. // if there is no support for IP_PKTINFO, we are really out of luck
  343. // it will be difficult to undersand, where this packet came from
  344. #if defined(IP_PKTINFO)
  345. int flag = 1;
  346. if (setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &flag, sizeof(flag)) != 0) {
  347. close(sock);
  348. isc_throw(Unexpected, "setsockopt: IP_PKTINFO: failed.");
  349. }
  350. #endif
  351. cout << "Created socket " << sock << " on " << iface.getName() << "/" <<
  352. addr.toText() << "/port=" << port << endl;
  353. SocketInfo info(sock, addr, port);
  354. iface.addSocket(info);
  355. return (sock);
  356. }
  357. int IfaceMgr::openSocket6(Iface& iface, const IOAddress& addr, uint16_t port) {
  358. cout << "Creating UDP6 socket on " << iface.getFullName()
  359. << " " << addr.toText() << "/port=" << port << endl;
  360. struct sockaddr_in6 addr6;
  361. memset(&addr6, 0, sizeof(addr6));
  362. addr6.sin6_family = AF_INET6;
  363. addr6.sin6_port = htons(port);
  364. if (addr.toText() != "::1")
  365. addr6.sin6_scope_id = if_nametoindex(iface.getName().c_str());
  366. memcpy(&addr6.sin6_addr,
  367. addr.getAddress().to_v6().to_bytes().data(),
  368. sizeof(addr6.sin6_addr));
  369. #ifdef HAVE_SA_LEN
  370. addr6.sin6_len = sizeof(addr6);
  371. #endif
  372. // TODO: use sockcreator once it becomes available
  373. // make a socket
  374. int sock = socket(AF_INET6, SOCK_DGRAM, 0);
  375. if (sock < 0) {
  376. isc_throw(Unexpected, "Failed to create UDP6 socket.");
  377. }
  378. // Set the REUSEADDR option so that we don't fail to start if
  379. // we're being restarted.
  380. int flag = 1;
  381. if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
  382. (char *)&flag, sizeof(flag)) < 0) {
  383. close(sock);
  384. isc_throw(Unexpected, "Can't set SO_REUSEADDR option on dhcpv6 socket.");
  385. }
  386. if (bind(sock, (struct sockaddr *)&addr6, sizeof(addr6)) < 0) {
  387. close(sock);
  388. isc_throw(Unexpected, "Failed to bind socket " << sock << " to " << addr.toText()
  389. << "/port=" << port);
  390. }
  391. #ifdef IPV6_RECVPKTINFO
  392. // RFC3542 - a new way
  393. if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO,
  394. &flag, sizeof(flag)) != 0) {
  395. close(sock);
  396. isc_throw(Unexpected, "setsockopt: IPV6_RECVPKTINFO failed.");
  397. }
  398. #else
  399. // RFC2292 - an old way
  400. if (setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO,
  401. &flag, sizeof(flag)) != 0) {
  402. close(sock);
  403. isc_throw(Unexpected, "setsockopt: IPV6_PKTINFO: failed.");
  404. }
  405. #endif
  406. // multicast stuff
  407. if (addr.getAddress().to_v6().is_multicast()) {
  408. // both mcast (ALL_DHCP_RELAY_AGENTS_AND_SERVERS and ALL_DHCP_SERVERS)
  409. // are link and site-scoped, so there is no sense to join those groups
  410. // with global addresses.
  411. if ( !joinMulticast( sock, iface.getName(),
  412. string(ALL_DHCP_RELAY_AGENTS_AND_SERVERS) ) ) {
  413. close(sock);
  414. isc_throw(Unexpected, "Failed to join " << ALL_DHCP_RELAY_AGENTS_AND_SERVERS
  415. << " multicast group.");
  416. }
  417. }
  418. cout << "Created socket " << sock << " on " << iface.getName() << "/" <<
  419. addr.toText() << "/port=" << port << endl;
  420. SocketInfo info(sock, addr, port);
  421. iface.addSocket(info);
  422. return (sock);
  423. }
  424. bool
  425. IfaceMgr::joinMulticast(int sock, const std::string& ifname,
  426. const std::string & mcast) {
  427. struct ipv6_mreq mreq;
  428. if (inet_pton(AF_INET6, mcast.c_str(),
  429. &mreq.ipv6mr_multiaddr) <= 0) {
  430. cout << "Failed to convert " << ifname
  431. << " to IPv6 multicast address." << endl;
  432. return (false);
  433. }
  434. mreq.ipv6mr_interface = if_nametoindex(ifname.c_str());
  435. if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
  436. &mreq, sizeof(mreq)) < 0) {
  437. cout << "Failed to join " << mcast << " multicast group." << endl;
  438. return (false);
  439. }
  440. cout << "Joined multicast " << mcast << " group." << endl;
  441. return (true);
  442. }
  443. bool
  444. IfaceMgr::send(const Pkt6Ptr& pkt) {
  445. int result;
  446. Iface* iface = getIface(pkt->getIface());
  447. if (!iface) {
  448. isc_throw(BadValue, "Unable to send Pkt6. Invalid interface ("
  449. << pkt->getIface() << ") specified.");
  450. }
  451. memset(&control_buf_[0], 0, control_buf_len_);
  452. // Set the target address we're sending to.
  453. sockaddr_in6 to;
  454. memset(&to, 0, sizeof(to));
  455. to.sin6_family = AF_INET6;
  456. to.sin6_port = htons(pkt->getRemotePort());
  457. memcpy(&to.sin6_addr,
  458. pkt->getRemoteAddr().getAddress().to_v6().to_bytes().data(),
  459. 16);
  460. to.sin6_scope_id = pkt->getIndex();
  461. // Initialize our message header structure.
  462. struct msghdr m;
  463. memset(&m, 0, sizeof(m));
  464. m.msg_name = &to;
  465. m.msg_namelen = sizeof(to);
  466. // Set the data buffer we're sending. (Using this wacky
  467. // "scatter-gather" stuff... we only have a single chunk
  468. // of data to send, so we declare a single vector entry.)
  469. // As v structure is a C-style is used for both sending and
  470. // receiving data, it is shared between sending and receiving
  471. // (sendmsg and recvmsg). It is also defined in system headers,
  472. // so we have no control over its definition. To set iov_base
  473. // (defined as void*) we must use const cast from void *.
  474. // Otherwise C++ compiler would complain that we are trying
  475. // to assign const void* to void*.
  476. struct iovec v;
  477. memset(&v, 0, sizeof(v));
  478. v.iov_base = const_cast<void *>(pkt->getBuffer().getData());
  479. v.iov_len = pkt->getBuffer().getLength();
  480. m.msg_iov = &v;
  481. m.msg_iovlen = 1;
  482. // Setting the interface is a bit more involved.
  483. //
  484. // We have to create a "control message", and set that to
  485. // define the IPv6 packet information. We could set the
  486. // source address if we wanted, but we can safely let the
  487. // kernel decide what that should be.
  488. m.msg_control = &control_buf_[0];
  489. m.msg_controllen = control_buf_len_;
  490. struct cmsghdr *cmsg = CMSG_FIRSTHDR(&m);
  491. cmsg->cmsg_level = IPPROTO_IPV6;
  492. cmsg->cmsg_type = IPV6_PKTINFO;
  493. cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
  494. struct in6_pktinfo *pktinfo = convertPktInfo6(CMSG_DATA(cmsg));
  495. memset(pktinfo, 0, sizeof(struct in6_pktinfo));
  496. pktinfo->ipi6_ifindex = pkt->getIndex();
  497. m.msg_controllen = cmsg->cmsg_len;
  498. result = sendmsg(getSocket(*pkt), &m, 0);
  499. if (result < 0) {
  500. isc_throw(Unexpected, "Pkt6 send failed: sendmsg() returned " << result);
  501. }
  502. cout << "Sent " << pkt->getBuffer().getLength() << " bytes over socket " << getSocket(*pkt)
  503. << " on " << iface->getFullName() << " interface: "
  504. << " dst=[" << pkt->getRemoteAddr().toText() << "]:" << pkt->getRemotePort()
  505. << ", src=" << pkt->getLocalAddr().toText() << "]:" << pkt->getLocalPort()
  506. << endl;
  507. return (result);
  508. }
  509. bool
  510. IfaceMgr::send(const Pkt4Ptr& pkt)
  511. {
  512. Iface* iface = getIface(pkt->getIface());
  513. if (!iface) {
  514. isc_throw(BadValue, "Unable to send Pkt4. Invalid interface ("
  515. << pkt->getIface() << ") specified.");
  516. }
  517. memset(&control_buf_[0], 0, control_buf_len_);
  518. // Set the target address we're sending to.
  519. sockaddr_in to;
  520. memset(&to, 0, sizeof(to));
  521. to.sin_family = AF_INET;
  522. to.sin_port = htons(pkt->getRemotePort());
  523. to.sin_addr.s_addr = htonl(pkt->getRemoteAddr());
  524. struct msghdr m;
  525. // Initialize our message header structure.
  526. memset(&m, 0, sizeof(m));
  527. m.msg_name = &to;
  528. m.msg_namelen = sizeof(to);
  529. // Set the data buffer we're sending. (Using this wacky
  530. // "scatter-gather" stuff... we only have a single chunk
  531. // of data to send, so we declare a single vector entry.)
  532. struct iovec v;
  533. memset(&v, 0, sizeof(v));
  534. // iov_base field is of void * type. We use it for packet
  535. // transmission, so this buffer will not be modified.
  536. v.iov_base = const_cast<void *>(pkt->getBuffer().getData());
  537. v.iov_len = pkt->getBuffer().getLength();
  538. m.msg_iov = &v;
  539. m.msg_iovlen = 1;
  540. // call OS-specific routines (like setting interface index)
  541. os_send4(m, control_buf_, control_buf_len_, pkt);
  542. cout << "Trying to send " << pkt->getBuffer().getLength() << " bytes to "
  543. << pkt->getRemoteAddr().toText() << ":" << pkt->getRemotePort()
  544. << " over socket " << getSocket(*pkt) << " on interface "
  545. << getIface(pkt->getIface())->getFullName() << endl;
  546. int result = sendmsg(getSocket(*pkt), &m, 0);
  547. if (result < 0) {
  548. isc_throw(Unexpected, "Pkt4 send failed.");
  549. }
  550. cout << "Sent " << pkt->getBuffer().getLength() << " bytes over socket " << getSocket(*pkt)
  551. << " on " << iface->getFullName() << " interface: "
  552. << " dst=" << pkt->getRemoteAddr().toText() << ":" << pkt->getRemotePort()
  553. << ", src=" << pkt->getLocalAddr().toText() << ":" << pkt->getLocalPort()
  554. << endl;
  555. return (result);
  556. }
  557. boost::shared_ptr<Pkt4>
  558. IfaceMgr::receive4() {
  559. const SocketInfo* candidate = 0;
  560. IfaceCollection::const_iterator iface;
  561. for (iface = ifaces_.begin(); iface != ifaces_.end(); ++iface) {
  562. /// @todo: rewrite this as part of #1555
  563. for (SocketCollection::const_iterator s = iface->sockets_.begin();
  564. s != iface->sockets_.end(); ++s) {
  565. // We don't want IPv6 addresses here.
  566. if (s->addr_.getFamily() != AF_INET) {
  567. continue;
  568. }
  569. // This address looks good.
  570. if (!candidate) {
  571. candidate = &(*s);
  572. break;
  573. }
  574. }
  575. if (candidate) {
  576. break;
  577. }
  578. }
  579. if (!candidate) {
  580. isc_throw(Unexpected, "Failed to find any suitable sockets on all interfaces.");
  581. }
  582. cout << "Trying to receive over UDP4 socket " << candidate->sockfd_ << " bound to "
  583. << candidate->addr_.toText() << "/port=" << candidate->port_ << " on "
  584. << iface->getFullName() << endl;
  585. // Now we have a socket, let's get some data from it!
  586. struct sockaddr_in from_addr;
  587. uint8_t buf[RCVBUFSIZE];
  588. memset(&control_buf_[0], 0, control_buf_len_);
  589. memset(&from_addr, 0, sizeof(from_addr));
  590. // Initialize our message header structure.
  591. struct msghdr m;
  592. memset(&m, 0, sizeof(m));
  593. // Point so we can get the from address.
  594. m.msg_name = &from_addr;
  595. m.msg_namelen = sizeof(from_addr);
  596. struct iovec v;
  597. v.iov_base = static_cast<void*>(buf);
  598. v.iov_len = RCVBUFSIZE;
  599. m.msg_iov = &v;
  600. m.msg_iovlen = 1;
  601. // Getting the interface is a bit more involved.
  602. //
  603. // We set up some space for a "control message". We have
  604. // previously asked the kernel to give us packet
  605. // information (when we initialized the interface), so we
  606. // should get the destination address from that.
  607. m.msg_control = &control_buf_[0];
  608. m.msg_controllen = control_buf_len_;
  609. int result = recvmsg(candidate->sockfd_, &m, 0);
  610. if (result < 0) {
  611. cout << "Failed to receive UDP4 data." << endl;
  612. return (Pkt4Ptr()); // NULL
  613. }
  614. // We have all data let's create Pkt4 object.
  615. Pkt4Ptr pkt = Pkt4Ptr(new Pkt4(buf, result));
  616. unsigned int ifindex = iface->getIndex();
  617. IOAddress from(htonl(from_addr.sin_addr.s_addr));
  618. uint16_t from_port = htons(from_addr.sin_port);
  619. // Set receiving interface based on information, which socket was used to
  620. // receive data. OS-specific info (see os_receive4()) may be more reliable,
  621. // so this value may be overwritten.
  622. pkt->setIndex(ifindex);
  623. pkt->setIface(iface->getName());
  624. pkt->setRemoteAddr(from);
  625. pkt->setRemotePort(from_port);
  626. pkt->setLocalPort(candidate->port_);
  627. if (!os_receive4(m, pkt)) {
  628. cout << "Unable to find pktinfo" << endl;
  629. return (boost::shared_ptr<Pkt4>()); // NULL
  630. }
  631. cout << "Received " << result << " bytes from " << from.toText()
  632. << "/port=" << from_port
  633. << " sent to " << pkt->getLocalAddr().toText() << " over interface "
  634. << iface->getFullName() << endl;
  635. return (pkt);
  636. }
  637. Pkt6Ptr IfaceMgr::receive6() {
  638. uint8_t buf[RCVBUFSIZE];
  639. memset(&control_buf_[0], 0, control_buf_len_);
  640. struct sockaddr_in6 from;
  641. memset(&from, 0, sizeof(from));
  642. // Initialize our message header structure.
  643. struct msghdr m;
  644. memset(&m, 0, sizeof(m));
  645. // Point so we can get the from address.
  646. m.msg_name = &from;
  647. m.msg_namelen = sizeof(from);
  648. // Set the data buffer we're receiving. (Using this wacky
  649. // "scatter-gather" stuff... but we that doesn't really make
  650. // sense for us, so we use a single vector entry.)
  651. struct iovec v;
  652. memset(&v, 0, sizeof(v));
  653. v.iov_base = static_cast<void*>(buf);
  654. v.iov_len = RCVBUFSIZE;
  655. m.msg_iov = &v;
  656. m.msg_iovlen = 1;
  657. // Getting the interface is a bit more involved.
  658. //
  659. // We set up some space for a "control message". We have
  660. // previously asked the kernel to give us packet
  661. // information (when we initialized the interface), so we
  662. // should get the destination address from that.
  663. m.msg_control = &control_buf_[0];
  664. m.msg_controllen = control_buf_len_;
  665. /// TODO: Need to move to select() and pool over
  666. /// all available sockets. For now, we just take the
  667. /// first interface and use first socket from it.
  668. IfaceCollection::const_iterator iface = ifaces_.begin();
  669. const SocketInfo* candidate = 0;
  670. while (iface != ifaces_.end()) {
  671. for (SocketCollection::const_iterator s = iface->sockets_.begin();
  672. s != iface->sockets_.end(); ++s) {
  673. if (s->addr_.getFamily() != AF_INET6) {
  674. continue;
  675. }
  676. if (s->addr_.getAddress().to_v6().is_multicast()) {
  677. candidate = &(*s);
  678. break;
  679. }
  680. if (!candidate) {
  681. candidate = &(*s); // it's not multicast, but it's better than nothing
  682. }
  683. }
  684. if (candidate) {
  685. break;
  686. }
  687. ++iface;
  688. }
  689. if (iface == ifaces_.end()) {
  690. isc_throw(Unexpected, "No suitable IPv6 interfaces detected. Can't receive anything.");
  691. }
  692. if (!candidate) {
  693. isc_throw(Unexpected, "Interface " << iface->getFullName()
  694. << " does not have any sockets open.");
  695. }
  696. cout << "Trying to receive over UDP6 socket " << candidate->sockfd_ << " bound to "
  697. << candidate->addr_.toText() << "/port=" << candidate->port_ << " on "
  698. << iface->getFullName() << endl;
  699. int result = recvmsg(candidate->sockfd_, &m, 0);
  700. struct in6_addr to_addr;
  701. memset(&to_addr, 0, sizeof(to_addr));
  702. int ifindex = -1;
  703. if (result >= 0) {
  704. struct in6_pktinfo* pktinfo = NULL;
  705. // If we did read successfully, then we need to loop
  706. // through the control messages we received and
  707. // find the one with our destination address.
  708. //
  709. // We also keep a flag to see if we found it. If we
  710. // didn't, then we consider this to be an error.
  711. bool found_pktinfo = false;
  712. struct cmsghdr* cmsg = CMSG_FIRSTHDR(&m);
  713. while (cmsg != NULL) {
  714. if ((cmsg->cmsg_level == IPPROTO_IPV6) &&
  715. (cmsg->cmsg_type == IPV6_PKTINFO)) {
  716. pktinfo = convertPktInfo6(CMSG_DATA(cmsg));
  717. to_addr = pktinfo->ipi6_addr;
  718. ifindex = pktinfo->ipi6_ifindex;
  719. found_pktinfo = true;
  720. break;
  721. }
  722. cmsg = CMSG_NXTHDR(&m, cmsg);
  723. }
  724. if (!found_pktinfo) {
  725. cout << "Unable to find pktinfo" << endl;
  726. return (Pkt6Ptr()); // NULL
  727. }
  728. } else {
  729. cout << "Failed to receive data." << endl;
  730. return (Pkt6Ptr()); // NULL
  731. }
  732. // Let's create a packet.
  733. Pkt6Ptr pkt;
  734. try {
  735. pkt = Pkt6Ptr(new Pkt6(buf, result));
  736. } catch (const std::exception& ex) {
  737. cout << "Failed to create new packet." << endl;
  738. return (Pkt6Ptr()); // NULL
  739. }
  740. pkt->setLocalAddr(IOAddress::from_bytes(AF_INET6,
  741. reinterpret_cast<const uint8_t*>(&to_addr)));
  742. pkt->setRemoteAddr(IOAddress::from_bytes(AF_INET6,
  743. reinterpret_cast<const uint8_t*>(&from.sin6_addr)));
  744. pkt->setRemotePort(ntohs(from.sin6_port));
  745. pkt->setIndex(ifindex);
  746. Iface* received = getIface(pkt->getIndex());
  747. if (received) {
  748. pkt->setIface(received->getName());
  749. } else {
  750. cout << "Received packet over unknown interface (ifindex="
  751. << pkt->getIndex() << ")." << endl;
  752. return (boost::shared_ptr<Pkt6>()); // NULL
  753. }
  754. /// @todo: Move this to LOG_DEBUG
  755. cout << "Received " << pkt->getBuffer().getLength() << " bytes over "
  756. << pkt->getIface() << "/" << pkt->getIndex() << " interface: "
  757. << " src=" << pkt->getRemoteAddr().toText()
  758. << ", dst=" << pkt->getLocalAddr().toText()
  759. << endl;
  760. return (pkt);
  761. }
  762. uint16_t IfaceMgr::getSocket(const isc::dhcp::Pkt6& pkt) {
  763. Iface* iface = getIface(pkt.getIface());
  764. if (iface == NULL) {
  765. isc_throw(BadValue, "Tried to find socket for non-existent interface "
  766. << pkt.getIface());
  767. }
  768. SocketCollection::const_iterator s;
  769. for (s = iface->sockets_.begin(); s != iface->sockets_.end(); ++s) {
  770. if ((s->family_ == AF_INET6) &&
  771. (!s->addr_.getAddress().to_v6().is_multicast())) {
  772. return (s->sockfd_);
  773. }
  774. /// @todo: Add more checks here later. If remote address is
  775. /// not link-local, we can't use link local bound socket
  776. /// to send data.
  777. }
  778. isc_throw(Unexpected, "Interface " << iface->getFullName()
  779. << " does not have any suitable IPv6 sockets open.");
  780. }
  781. uint16_t IfaceMgr::getSocket(isc::dhcp::Pkt4 const& pkt) {
  782. Iface* iface = getIface(pkt.getIface());
  783. if (iface == NULL) {
  784. isc_throw(BadValue, "Tried to find socket for non-existent interface "
  785. << pkt.getIface());
  786. }
  787. SocketCollection::const_iterator s;
  788. for (s = iface->sockets_.begin(); s != iface->sockets_.end(); ++s) {
  789. if (s->family_ == AF_INET) {
  790. return (s->sockfd_);
  791. }
  792. /// TODO: Add more checks here later. If remote address is
  793. /// not link-local, we can't use link local bound socket
  794. /// to send data.
  795. }
  796. isc_throw(Unexpected, "Interface " << iface->getFullName()
  797. << " does not have any suitable IPv4 sockets open.");
  798. }
  799. } // end of namespace isc::dhcp
  800. } // end of namespace isc