iface_mgr.cc 33 KB

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