iface_mgr.cc 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191
  1. // Copyright (C) 2011-2016 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this
  5. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6. #include <config.h>
  7. #include <asiolink/asio_wrapper.h>
  8. #include <asiolink/io_error.h>
  9. #include <asiolink/udp_endpoint.h>
  10. #include <dhcp/dhcp4.h>
  11. #include <dhcp/dhcp6.h>
  12. #include <dhcp/iface_mgr.h>
  13. #include <dhcp/iface_mgr_error_handler.h>
  14. #include <dhcp/pkt_filter_inet.h>
  15. #include <dhcp/pkt_filter_inet6.h>
  16. #include <exceptions/exceptions.h>
  17. #include <util/io/pktinfo_utilities.h>
  18. #include <boost/foreach.hpp>
  19. #include <boost/scoped_ptr.hpp>
  20. #include <cstring>
  21. #include <errno.h>
  22. #include <fstream>
  23. #include <sstream>
  24. #include <arpa/inet.h>
  25. #include <netinet/in.h>
  26. #include <string.h>
  27. #include <sys/select.h>
  28. using namespace std;
  29. using namespace isc::asiolink;
  30. using namespace isc::util;
  31. using namespace isc::util::io::internal;
  32. namespace isc {
  33. namespace dhcp {
  34. IfaceMgr&
  35. IfaceMgr::instance() {
  36. return (*instancePtr());
  37. }
  38. const IfaceMgrPtr&
  39. IfaceMgr::instancePtr() {
  40. static IfaceMgrPtr iface_mgr(new IfaceMgr());
  41. return (iface_mgr);
  42. }
  43. Iface::Iface(const std::string& name, int ifindex)
  44. :name_(name), ifindex_(ifindex), mac_len_(0), hardware_type_(0),
  45. flag_loopback_(false), flag_up_(false), flag_running_(false),
  46. flag_multicast_(false), flag_broadcast_(false), flags_(0),
  47. inactive4_(false), inactive6_(false)
  48. {
  49. memset(mac_, 0, sizeof(mac_));
  50. }
  51. void
  52. Iface::closeSockets() {
  53. // Close IPv4 sockets.
  54. closeSockets(AF_INET);
  55. // Close IPv6 sockets.
  56. closeSockets(AF_INET6);
  57. }
  58. void
  59. Iface::closeSockets(const uint16_t family) {
  60. // Check that the correect 'family' value has been specified.
  61. // The possible values are AF_INET or AF_INET6. Note that, in
  62. // the current code they are used to differentiate that the
  63. // socket is used to transmit IPv4 or IPv6 traffic. However,
  64. // the actual family types of the sockets may be different,
  65. // e.g. for LPF we are using raw sockets of AF_PACKET family.
  66. //
  67. // @todo Consider replacing the AF_INET and AF_INET6 with some
  68. // enum which will not be confused with the actual socket type.
  69. if ((family != AF_INET) && (family != AF_INET6)) {
  70. isc_throw(BadValue, "Invalid socket family " << family
  71. << " specified when requested to close all sockets"
  72. << " which belong to this family");
  73. }
  74. // Search for the socket of the specific type.
  75. SocketCollection::iterator sock = sockets_.begin();
  76. while (sock != sockets_.end()) {
  77. if (sock->family_ == family) {
  78. // Close and delete the socket and move to the
  79. // next one.
  80. close(sock->sockfd_);
  81. // Close fallback socket if open.
  82. if (sock->fallbackfd_ >= 0) {
  83. close(sock->fallbackfd_);
  84. }
  85. sockets_.erase(sock++);
  86. } else {
  87. // Different type of socket. Let's move
  88. // to the next one.
  89. ++sock;
  90. }
  91. }
  92. }
  93. std::string
  94. Iface::getFullName() const {
  95. ostringstream tmp;
  96. tmp << name_ << "/" << ifindex_;
  97. return (tmp.str());
  98. }
  99. std::string
  100. Iface::getPlainMac() const {
  101. ostringstream tmp;
  102. tmp.fill('0');
  103. tmp << hex;
  104. for (int i = 0; i < mac_len_; i++) {
  105. tmp.width(2);
  106. tmp << static_cast<int>(mac_[i]);
  107. if (i < mac_len_-1) {
  108. tmp << ":";
  109. }
  110. }
  111. return (tmp.str());
  112. }
  113. void Iface::setMac(const uint8_t* mac, size_t len) {
  114. if (len > MAX_MAC_LEN) {
  115. isc_throw(OutOfRange, "Interface " << getFullName()
  116. << " was detected to have link address of length "
  117. << len << ", but maximum supported length is "
  118. << MAX_MAC_LEN);
  119. }
  120. mac_len_ = len;
  121. memcpy(mac_, mac, len);
  122. }
  123. bool Iface::delAddress(const isc::asiolink::IOAddress& addr) {
  124. for (AddressCollection::iterator a = addrs_.begin();
  125. a!=addrs_.end(); ++a) {
  126. if (a->get() == addr) {
  127. addrs_.erase(a);
  128. return (true);
  129. }
  130. }
  131. return (false);
  132. }
  133. bool Iface::delSocket(const uint16_t sockfd) {
  134. list<SocketInfo>::iterator sock = sockets_.begin();
  135. while (sock!=sockets_.end()) {
  136. if (sock->sockfd_ == sockfd) {
  137. close(sockfd);
  138. // Close fallback socket if open.
  139. if (sock->fallbackfd_ >= 0) {
  140. close(sock->fallbackfd_);
  141. }
  142. sockets_.erase(sock);
  143. return (true); //socket found
  144. }
  145. ++sock;
  146. }
  147. return (false); // socket not found
  148. }
  149. IfaceMgr::IfaceMgr()
  150. :control_buf_len_(CMSG_SPACE(sizeof(struct in6_pktinfo))),
  151. control_buf_(new char[control_buf_len_]),
  152. packet_filter_(new PktFilterInet()),
  153. packet_filter6_(new PktFilterInet6()),
  154. test_mode_(false)
  155. {
  156. try {
  157. // required for sending/receiving packets
  158. // let's keep it in front, just in case someone
  159. // wants to send anything during initialization
  160. // control_buf_ = boost::scoped_array<char>();
  161. detectIfaces();
  162. } catch (const std::exception& ex) {
  163. isc_throw(IfaceDetectError, ex.what());
  164. }
  165. }
  166. void Iface::addUnicast(const isc::asiolink::IOAddress& addr) {
  167. BOOST_FOREACH(Address a, unicasts_) {
  168. if (a.get() == addr) {
  169. isc_throw(BadValue, "Address " << addr
  170. << " already defined on the " << name_ << " interface.");
  171. }
  172. }
  173. unicasts_.push_back(OptionalValue<IOAddress>(addr, true));
  174. }
  175. bool
  176. Iface::getAddress4(isc::asiolink::IOAddress& address) const {
  177. // Iterate over existing addresses assigned to the interface.
  178. // Try to find the one that is IPv4.
  179. BOOST_FOREACH(Address addr, getAddresses()) {
  180. // If address is IPv4, we assign it to the function argument
  181. // and return true.
  182. if (addr.get().isV4()) {
  183. address = addr.get();
  184. return (true);
  185. }
  186. }
  187. // There is no IPv4 address assigned to this interface.
  188. return (false);
  189. }
  190. bool
  191. Iface::hasAddress(const isc::asiolink::IOAddress& address) const {
  192. BOOST_FOREACH(Address addr, getAddresses()) {
  193. if (address == addr.get()) {
  194. return (true);
  195. }
  196. }
  197. return (false);
  198. }
  199. void
  200. Iface::addAddress(const isc::asiolink::IOAddress& addr) {
  201. addrs_.push_back(Address(addr, OptionalValueState(true)));
  202. }
  203. void
  204. Iface::setActive(const IOAddress& address, const bool active) {
  205. for (AddressCollection::iterator addr_it = addrs_.begin();
  206. addr_it != addrs_.end(); ++addr_it) {
  207. if (address == addr_it->get()) {
  208. addr_it->specify(OptionalValueState(active));
  209. return;
  210. }
  211. }
  212. isc_throw(BadValue, "specified address " << address << " was not"
  213. " found on the interface " << getName());
  214. }
  215. void
  216. Iface::setActive(const bool active) {
  217. for (AddressCollection::iterator addr_it = addrs_.begin();
  218. addr_it != addrs_.end(); ++addr_it) {
  219. addr_it->specify(OptionalValueState(active));
  220. }
  221. }
  222. unsigned int
  223. Iface::countActive4() const {
  224. uint16_t count = 0;
  225. BOOST_FOREACH(Address addr, addrs_) {
  226. if (addr.get().isV4() && addr.isSpecified()) {
  227. ++count;
  228. }
  229. }
  230. return (count);
  231. }
  232. void IfaceMgr::closeSockets() {
  233. BOOST_FOREACH(IfacePtr iface, ifaces_) {
  234. iface->closeSockets();
  235. }
  236. }
  237. void
  238. IfaceMgr::closeSockets(const uint16_t family) {
  239. BOOST_FOREACH(IfacePtr iface, ifaces_) {
  240. iface->closeSockets(family);
  241. }
  242. }
  243. IfaceMgr::~IfaceMgr() {
  244. // control_buf_ is deleted automatically (scoped_ptr)
  245. control_buf_len_ = 0;
  246. closeSockets();
  247. }
  248. bool
  249. IfaceMgr::isDirectResponseSupported() const {
  250. return (packet_filter_->isDirectResponseSupported());
  251. }
  252. void
  253. IfaceMgr::addExternalSocket(int socketfd, SocketCallback callback) {
  254. if (socketfd < 0) {
  255. isc_throw(BadValue, "Attempted to install callback for invalid socket "
  256. << socketfd);
  257. }
  258. BOOST_FOREACH(SocketCallbackInfo s, callbacks_) {
  259. // There's such a socket description there already.
  260. // Update the callback and we're done
  261. if (s.socket_ == socketfd) {
  262. s.callback_ = callback;
  263. return;
  264. }
  265. }
  266. // Add a new entry to the callbacks vector
  267. SocketCallbackInfo x;
  268. x.socket_ = socketfd;
  269. x.callback_ = callback;
  270. callbacks_.push_back(x);
  271. }
  272. void
  273. IfaceMgr::deleteExternalSocket(int socketfd) {
  274. for (SocketCallbackInfoContainer::iterator s = callbacks_.begin();
  275. s != callbacks_.end(); ++s) {
  276. if (s->socket_ == socketfd) {
  277. callbacks_.erase(s);
  278. return;
  279. }
  280. }
  281. }
  282. void
  283. IfaceMgr::deleteAllExternalSockets() {
  284. callbacks_.clear();
  285. }
  286. void
  287. IfaceMgr::setPacketFilter(const PktFilterPtr& packet_filter) {
  288. // Do not allow NULL pointer.
  289. if (!packet_filter) {
  290. isc_throw(InvalidPacketFilter, "NULL packet filter object specified for"
  291. " DHCPv4");
  292. }
  293. // Different packet filters use different socket types. It does not make
  294. // sense to allow the change of packet filter when there are IPv4 sockets
  295. // open because they can't be used by the receive/send functions of the
  296. // new packet filter. Below, we check that there are no open IPv4 sockets.
  297. // If we find at least one, we have to fail. However, caller still has a
  298. // chance to replace the packet filter if he closes sockets explicitly.
  299. if (hasOpenSocket(AF_INET)) {
  300. // There is at least one socket open, so we have to fail.
  301. isc_throw(PacketFilterChangeDenied,
  302. "it is not allowed to set new packet"
  303. << " filter when there are open IPv4 sockets - need"
  304. << " to close them first");
  305. }
  306. // Everything is fine, so replace packet filter.
  307. packet_filter_ = packet_filter;
  308. }
  309. void
  310. IfaceMgr::setPacketFilter(const PktFilter6Ptr& packet_filter) {
  311. if (!packet_filter) {
  312. isc_throw(InvalidPacketFilter, "NULL packet filter object specified for"
  313. " DHCPv6");
  314. }
  315. if (hasOpenSocket(AF_INET6)) {
  316. // There is at least one socket open, so we have to fail.
  317. isc_throw(PacketFilterChangeDenied,
  318. "it is not allowed to set new packet"
  319. << " filter when there are open IPv6 sockets - need"
  320. << " to close them first");
  321. }
  322. packet_filter6_ = packet_filter;
  323. }
  324. bool
  325. IfaceMgr::hasOpenSocket(const uint16_t family) const {
  326. // Iterate over all interfaces and search for open sockets.
  327. BOOST_FOREACH(IfacePtr iface, ifaces_) {
  328. BOOST_FOREACH(SocketInfo sock, iface->getSockets()) {
  329. // Check if the socket matches specified family.
  330. if (sock.family_ == family) {
  331. // There is at least one socket open, so return.
  332. return (true);
  333. }
  334. }
  335. }
  336. // There are no open sockets found for the specified family.
  337. return (false);
  338. }
  339. bool
  340. IfaceMgr::hasOpenSocket(const IOAddress& addr) const {
  341. // Iterate over all interfaces and search for open sockets.
  342. BOOST_FOREACH(IfacePtr iface, ifaces_) {
  343. BOOST_FOREACH(SocketInfo sock, iface->getSockets()) {
  344. // Check if the socket address matches the specified address or
  345. // if address is unspecified (in6addr_any).
  346. if (sock.addr_ == addr) {
  347. return (true);
  348. } else if (sock.addr_ == IOAddress("::")) {
  349. // Handle the case that the address is unspecified (any).
  350. // In this case, we should check if the specified address
  351. // belongs to any of the interfaces.
  352. BOOST_FOREACH(Iface::Address a, iface->getAddresses()) {
  353. if (addr == a.get()) {
  354. return (true);
  355. }
  356. }
  357. }
  358. }
  359. }
  360. // There are no open sockets found for the specified family.
  361. return (false);
  362. }
  363. void IfaceMgr::stubDetectIfaces() {
  364. string ifaceName;
  365. const string v4addr("127.0.0.1"), v6addr("::1");
  366. // This is a stub implementation for interface detection. Actual detection
  367. // is faked by detecting loopback interface (lo or lo0). It will eventually
  368. // be removed once we have actual implementations for all supported systems.
  369. if (if_nametoindex("lo") > 0) {
  370. ifaceName = "lo";
  371. // this is Linux-like OS
  372. } else if (if_nametoindex("lo0") > 0) {
  373. ifaceName = "lo0";
  374. // this is BSD-like OS
  375. } else {
  376. // we give up. What OS is this, anyway? Solaris? Hurd?
  377. isc_throw(NotImplemented,
  378. "Interface detection on this OS is not supported.");
  379. }
  380. IfacePtr iface(new Iface(ifaceName, if_nametoindex(ifaceName.c_str())));
  381. iface->flag_up_ = true;
  382. iface->flag_running_ = true;
  383. // Note that we claim that this is not a loopback. iface_mgr tries to open a
  384. // socket on all interaces that are up, running and not loopback. As this is
  385. // the only interface we were able to detect, let's pretend this is a normal
  386. // interface.
  387. iface->flag_loopback_ = false;
  388. iface->flag_multicast_ = true;
  389. iface->flag_broadcast_ = true;
  390. iface->setHWType(HWTYPE_ETHERNET);
  391. iface->addAddress(IOAddress(v4addr));
  392. iface->addAddress(IOAddress(v6addr));
  393. addInterface(iface);
  394. }
  395. bool
  396. IfaceMgr::openSockets4(const uint16_t port, const bool use_bcast,
  397. IfaceMgrErrorMsgCallback error_handler) {
  398. int count = 0;
  399. int bcast_num = 0;
  400. BOOST_FOREACH(IfacePtr iface, ifaces_) {
  401. // If the interface is inactive, there is nothing to do. Simply
  402. // proceed to the next detected interface.
  403. if (iface->inactive4_) {
  404. continue;
  405. } else {
  406. // If the interface has been specified in the configuration that
  407. // it should be used to listen the DHCP traffic we have to check
  408. // that the interface configuration is valid and that the interface
  409. // is not a loopback interface. In both cases, we want to report
  410. // that the socket will not be opened.
  411. if (iface->flag_loopback_) {
  412. IFACEMGR_ERROR(SocketConfigError, error_handler,
  413. "must not open socket on the loopback"
  414. " interface " << iface->getName());
  415. continue;
  416. }
  417. IOAddress out_address("0.0.0.0");
  418. if (!iface->flag_up_ || !iface->flag_running_ ||
  419. !iface->getAddress4(out_address)) {
  420. IFACEMGR_ERROR(SocketConfigError, error_handler,
  421. "the interface " << iface->getName()
  422. << " is down or has no usable IPv4"
  423. " addresses configured");
  424. continue;
  425. }
  426. }
  427. BOOST_FOREACH(Iface::Address addr, iface->getAddresses()) {
  428. // Skip non-IPv4 addresses and those that weren't selected..
  429. if (!addr.get().isV4() || !addr.isSpecified()) {
  430. continue;
  431. }
  432. // If selected interface is broadcast capable set appropriate
  433. // options on the socket so as it can receive and send broadcast
  434. // messages.
  435. if (iface->flag_broadcast_ && use_bcast) {
  436. // The DHCP server must have means to determine which interface
  437. // the broadcast packets are coming from. This is achieved by
  438. // binding a socket to the device (interface) and specialized
  439. // packet filters (e.g. BPF and LPF) implement this mechanism.
  440. // If the PktFilterInet (generic one) is used, the socket is
  441. // bound to INADDR_ANY which effectively binds the socket to
  442. // all addresses on all interfaces. So, only one of those can
  443. // be opened. Currently, the direct response support is
  444. // provided by the PktFilterLPF and PktFilterBPF, so by checking
  445. // the support for direct response we actually determine that
  446. // one of those objects is in use. For all other objects we
  447. // assume that binding to the device is not supported and we
  448. // cease opening sockets and display the appropriate message.
  449. if (!isDirectResponseSupported() && bcast_num > 0) {
  450. IFACEMGR_ERROR(SocketConfigError, error_handler,
  451. "Binding socket to an interface is not"
  452. " supported on this OS; therefore only"
  453. " one socket listening to broadcast traffic"
  454. " can be opened. Sockets will not be opened"
  455. " on remaining interfaces");
  456. continue;
  457. } else {
  458. try {
  459. // We haven't open any broadcast sockets yet, so we can
  460. // open at least one more.
  461. openSocket(iface->getName(), addr.get(), port, true, true);
  462. } catch (const Exception& ex) {
  463. IFACEMGR_ERROR(SocketConfigError, error_handler,
  464. "failed to open socket on interface "
  465. << iface->getName() << ", reason: "
  466. << ex.what());
  467. continue;
  468. }
  469. // Binding socket to an interface is not supported so we
  470. // can't open any more broadcast sockets. Increase the
  471. // number of open broadcast sockets.
  472. ++bcast_num;
  473. }
  474. } else {
  475. try {
  476. // Not broadcast capable, do not set broadcast flags.
  477. openSocket(iface->getName(), addr.get(), port, false, false);
  478. } catch (const Exception& ex) {
  479. IFACEMGR_ERROR(SocketConfigError, error_handler,
  480. "failed to open socket on interface "
  481. << iface->getName() << ", reason: "
  482. << ex.what());
  483. continue;
  484. }
  485. }
  486. ++count;
  487. }
  488. }
  489. return (count > 0);
  490. }
  491. bool
  492. IfaceMgr::openSockets6(const uint16_t port,
  493. IfaceMgrErrorMsgCallback error_handler) {
  494. int count = 0;
  495. BOOST_FOREACH(IfacePtr iface, ifaces_) {
  496. if (iface->inactive6_) {
  497. continue;
  498. } else {
  499. // If the interface has been specified in the configuration that
  500. // it should be used to listen the DHCP traffic we have to check
  501. // that the interface configuration is valid and that the interface
  502. // is not a loopback interface. In both cases, we want to report
  503. // that the socket will not be opened.
  504. if (iface->flag_loopback_) {
  505. IFACEMGR_ERROR(SocketConfigError, error_handler,
  506. "must not open socket on the loopback"
  507. " interface " << iface->getName());
  508. continue;
  509. } else if (!iface->flag_up_ || !iface->flag_running_) {
  510. IFACEMGR_ERROR(SocketConfigError, error_handler,
  511. "the interface " << iface->getName()
  512. << " is down or has no usable IPv6"
  513. " addresses configured");
  514. continue;
  515. }
  516. }
  517. // Open unicast sockets if there are any unicast addresses defined
  518. BOOST_FOREACH(Iface::Address addr, iface->getUnicasts()) {
  519. try {
  520. openSocket(iface->getName(), addr, port);
  521. } catch (const Exception& ex) {
  522. IFACEMGR_ERROR(SocketConfigError, error_handler,
  523. "Failed to open unicast socket on interface "
  524. << iface->getName() << ", reason: "
  525. << ex.what());
  526. continue;
  527. }
  528. count++;
  529. }
  530. BOOST_FOREACH(Iface::Address addr, iface->getAddresses()) {
  531. // Skip all but V6 addresses.
  532. if (!addr.get().isV6()) {
  533. continue;
  534. }
  535. // Bind link-local addresses only. Otherwise we bind several sockets
  536. // on interfaces that have several global addresses. For examples
  537. // with interface with 2 global addresses, we would bind 3 sockets
  538. // (one for link-local and two for global). That would result in
  539. // getting each message 3 times.
  540. if (!addr.get().isV6LinkLocal()){
  541. continue;
  542. }
  543. // Run OS-specific function to open a socket capable of receiving
  544. // packets sent to All_DHCP_Relay_Agents_and_Servers multicast
  545. // address.
  546. if (openMulticastSocket(*iface, addr, port, error_handler)) {
  547. ++count;
  548. }
  549. }
  550. }
  551. return (count > 0);
  552. }
  553. void
  554. IfaceMgr::printIfaces(std::ostream& out /*= std::cout*/) {
  555. BOOST_FOREACH(IfacePtr iface, ifaces_) {
  556. const Iface::AddressCollection& addrs = iface->getAddresses();
  557. out << "Detected interface " << iface->getFullName()
  558. << ", hwtype=" << iface->getHWType()
  559. << ", mac=" << iface->getPlainMac();
  560. out << ", flags=" << hex << iface->flags_ << dec << "("
  561. << (iface->flag_loopback_?"LOOPBACK ":"")
  562. << (iface->flag_up_?"UP ":"")
  563. << (iface->flag_running_?"RUNNING ":"")
  564. << (iface->flag_multicast_?"MULTICAST ":"")
  565. << (iface->flag_broadcast_?"BROADCAST ":"")
  566. << ")" << endl;
  567. out << " " << addrs.size() << " addr(s):";
  568. BOOST_FOREACH(Iface::Address addr, addrs) {
  569. out << " " << addr.get().toText();
  570. }
  571. out << endl;
  572. }
  573. }
  574. IfacePtr
  575. IfaceMgr::getIface(int ifindex) {
  576. BOOST_FOREACH(IfacePtr iface, ifaces_) {
  577. if (iface->getIndex() == ifindex)
  578. return (iface);
  579. }
  580. return (IfacePtr()); // not found
  581. }
  582. IfacePtr
  583. IfaceMgr::getIface(const std::string& ifname) {
  584. BOOST_FOREACH(IfacePtr iface, ifaces_) {
  585. if (iface->getName() == ifname)
  586. return (iface);
  587. }
  588. return (IfacePtr()); // not found
  589. }
  590. void
  591. IfaceMgr::clearIfaces() {
  592. ifaces_.clear();
  593. }
  594. void
  595. IfaceMgr::clearUnicasts() {
  596. BOOST_FOREACH(IfacePtr iface, ifaces_) {
  597. iface->clearUnicasts();
  598. }
  599. }
  600. int IfaceMgr::openSocket(const std::string& ifname, const IOAddress& addr,
  601. const uint16_t port, const bool receive_bcast,
  602. const bool send_bcast) {
  603. IfacePtr iface = getIface(ifname);
  604. if (!iface) {
  605. isc_throw(BadValue, "There is no " << ifname << " interface present.");
  606. }
  607. if (addr.isV4()) {
  608. return openSocket4(*iface, addr, port, receive_bcast, send_bcast);
  609. } else if (addr.isV6()) {
  610. return openSocket6(*iface, addr, port, receive_bcast);
  611. } else {
  612. isc_throw(BadValue, "Failed to detect family of address: "
  613. << addr);
  614. }
  615. }
  616. int IfaceMgr::openSocketFromIface(const std::string& ifname,
  617. const uint16_t port,
  618. const uint8_t family) {
  619. // Search for specified interface among detected interfaces.
  620. BOOST_FOREACH(IfacePtr iface, ifaces_) {
  621. if ((iface->getFullName() != ifname) &&
  622. (iface->getName() != ifname)) {
  623. continue;
  624. }
  625. // Interface is now detected. Search for address on interface
  626. // that matches address family (v6 or v4).
  627. Iface::AddressCollection addrs = iface->getAddresses();
  628. Iface::AddressCollection::iterator addr_it = addrs.begin();
  629. while (addr_it != addrs.end()) {
  630. if (addr_it->get().getFamily() == family) {
  631. // We have interface and address so let's open socket.
  632. // This may cause isc::Unexpected exception.
  633. return (openSocket(iface->getName(), *addr_it, port, false));
  634. }
  635. ++addr_it;
  636. }
  637. // If we are at the end of address collection it means that we found
  638. // interface but there is no address for family specified.
  639. if (addr_it == addrs.end()) {
  640. // Stringify the family value to append it to exception string.
  641. std::string family_name("AF_INET");
  642. if (family == AF_INET6) {
  643. family_name = "AF_INET6";
  644. }
  645. // We did not find address on the interface.
  646. isc_throw(SocketConfigError, "There is no address for interface: "
  647. << ifname << ", port: " << port << ", address "
  648. " family: " << family_name);
  649. }
  650. }
  651. // If we got here it means that we had not found the specified interface.
  652. // Otherwise we would have returned from previous exist points.
  653. isc_throw(BadValue, "There is no " << ifname << " interface present.");
  654. }
  655. int IfaceMgr::openSocketFromAddress(const IOAddress& addr,
  656. const uint16_t port) {
  657. // Search through detected interfaces and addresses to match
  658. // local address we got.
  659. BOOST_FOREACH(IfacePtr iface, ifaces_) {
  660. BOOST_FOREACH(Iface::Address a, iface->getAddresses()) {
  661. // Local address must match one of the addresses
  662. // on detected interfaces. If it does, we have
  663. // address and interface detected so we can open
  664. // socket.
  665. if (a.get() == addr) {
  666. // Open socket using local interface, address and port.
  667. // This may cause isc::Unexpected exception.
  668. return (openSocket(iface->getName(), a, port, false));
  669. }
  670. }
  671. }
  672. // If we got here it means that we did not find specified address
  673. // on any available interface.
  674. isc_throw(BadValue, "There is no such address " << addr);
  675. }
  676. int IfaceMgr::openSocketFromRemoteAddress(const IOAddress& remote_addr,
  677. const uint16_t port) {
  678. try {
  679. // Get local address to be used to connect to remote location.
  680. IOAddress local_address(getLocalAddress(remote_addr, port));
  681. return openSocketFromAddress(local_address, port);
  682. } catch (const Exception& e) {
  683. isc_throw(SocketConfigError, e.what());
  684. }
  685. }
  686. isc::asiolink::IOAddress
  687. IfaceMgr::getLocalAddress(const IOAddress& remote_addr, const uint16_t port) {
  688. // Create remote endpoint, we will be connecting to it.
  689. boost::scoped_ptr<const UDPEndpoint>
  690. remote_endpoint(static_cast<const UDPEndpoint*>
  691. (UDPEndpoint::create(IPPROTO_UDP, remote_addr, port)));
  692. if (!remote_endpoint) {
  693. isc_throw(Unexpected, "Unable to create remote endpoint");
  694. }
  695. // Create socket that will be used to connect to remote endpoint.
  696. boost::asio::io_service io_service;
  697. boost::asio::ip::udp::socket sock(io_service);
  698. boost::system::error_code err_code;
  699. // If remote address is broadcast address we have to
  700. // allow this on the socket.
  701. if (remote_addr.isV4() &&
  702. (remote_addr == IOAddress(DHCP_IPV4_BROADCAST_ADDRESS))) {
  703. // Socket has to be open prior to setting the broadcast
  704. // option. Otherwise set_option will complain about
  705. // bad file descriptor.
  706. // @todo: We don't specify interface in any way here. 255.255.255.255
  707. // We can very easily end up with a socket working on a different
  708. // interface.
  709. // zero out the errno to be safe
  710. errno = 0;
  711. sock.open(boost::asio::ip::udp::v4(), err_code);
  712. if (err_code) {
  713. const char* errstr = strerror(errno);
  714. isc_throw(Unexpected, "failed to open UDPv4 socket, reason:"
  715. << errstr);
  716. }
  717. sock.set_option(boost::asio::socket_base::broadcast(true), err_code);
  718. if (err_code) {
  719. sock.close();
  720. isc_throw(Unexpected, "failed to enable broadcast on the socket");
  721. }
  722. }
  723. // Try to connect to remote endpoint and check if attempt is successful.
  724. sock.connect(remote_endpoint->getASIOEndpoint(), err_code);
  725. if (err_code) {
  726. sock.close();
  727. isc_throw(Unexpected, "failed to connect to remote endpoint.");
  728. }
  729. // Once we are connected socket object holds local endpoint.
  730. boost::asio::ip::udp::socket::endpoint_type local_endpoint =
  731. sock.local_endpoint();
  732. boost::asio::ip::address local_address(local_endpoint.address());
  733. // Close the socket.
  734. sock.close();
  735. // Return address of local endpoint.
  736. return IOAddress(local_address);
  737. }
  738. int
  739. IfaceMgr::openSocket4(Iface& iface, const IOAddress& addr,
  740. const uint16_t port, const bool receive_bcast,
  741. const bool send_bcast) {
  742. // Assuming that packet filter is not NULL, because its modifier checks it.
  743. SocketInfo info = packet_filter_->openSocket(iface, addr, port,
  744. receive_bcast, send_bcast);
  745. iface.addSocket(info);
  746. return (info.sockfd_);
  747. }
  748. bool
  749. IfaceMgr::send(const Pkt6Ptr& pkt) {
  750. IfacePtr iface = getIface(pkt->getIface());
  751. if (!iface) {
  752. isc_throw(BadValue, "Unable to send DHCPv6 message. Invalid interface ("
  753. << pkt->getIface() << ") specified.");
  754. }
  755. // Assuming that packet filter is not NULL, because its modifier checks it.
  756. return (packet_filter6_->send(*iface, getSocket(*pkt), pkt));
  757. }
  758. bool
  759. IfaceMgr::send(const Pkt4Ptr& pkt) {
  760. IfacePtr iface = getIface(pkt->getIface());
  761. if (!iface) {
  762. isc_throw(BadValue, "Unable to send DHCPv4 message. Invalid interface ("
  763. << pkt->getIface() << ") specified.");
  764. }
  765. // Assuming that packet filter is not NULL, because its modifier checks it.
  766. return (packet_filter_->send(*iface, getSocket(*pkt).sockfd_, pkt));
  767. }
  768. boost::shared_ptr<Pkt4>
  769. IfaceMgr::receive4(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */) {
  770. // Sanity check for microsecond timeout.
  771. if (timeout_usec >= 1000000) {
  772. isc_throw(BadValue, "fractional timeout must be shorter than"
  773. " one million microseconds");
  774. }
  775. const SocketInfo* candidate = 0;
  776. IfacePtr iface;
  777. fd_set sockets;
  778. int maxfd = 0;
  779. FD_ZERO(&sockets);
  780. /// @todo: marginal performance optimization. We could create the set once
  781. /// and then use its copy for select(). Please note that select() modifies
  782. /// provided set to indicated which sockets have something to read.
  783. BOOST_FOREACH(iface, ifaces_) {
  784. BOOST_FOREACH(SocketInfo s, iface->getSockets()) {
  785. // Only deal with IPv4 addresses.
  786. if (s.addr_.isV4()) {
  787. // Add this socket to listening set
  788. FD_SET(s.sockfd_, &sockets);
  789. if (maxfd < s.sockfd_) {
  790. maxfd = s.sockfd_;
  791. }
  792. }
  793. }
  794. }
  795. // if there are any callbacks for external sockets registered...
  796. if (!callbacks_.empty()) {
  797. BOOST_FOREACH(SocketCallbackInfo s, callbacks_) {
  798. FD_SET(s.socket_, &sockets);
  799. if (maxfd < s.socket_) {
  800. maxfd = s.socket_;
  801. }
  802. }
  803. }
  804. struct timeval select_timeout;
  805. select_timeout.tv_sec = timeout_sec;
  806. select_timeout.tv_usec = timeout_usec;
  807. // zero out the errno to be safe
  808. errno = 0;
  809. int result = select(maxfd + 1, &sockets, NULL, NULL, &select_timeout);
  810. if (result == 0) {
  811. // nothing received and timeout has been reached
  812. return (Pkt4Ptr()); // NULL
  813. } else if (result < 0) {
  814. // In most cases we would like to know whether select() returned
  815. // an error because of a signal being received or for some other
  816. // reasaon. This is because DHCP servers use signals to trigger
  817. // certain actions, like reconfiguration or graceful shutdown.
  818. // By catching a dedicated exception the caller will know if the
  819. // error returned by the function is due to the reception of the
  820. // signal or for some other reason.
  821. if (errno == EINTR) {
  822. isc_throw(SignalInterruptOnSelect, strerror(errno));
  823. } else {
  824. isc_throw(SocketReadError, strerror(errno));
  825. }
  826. }
  827. // Let's find out which socket has the data
  828. BOOST_FOREACH(SocketCallbackInfo s, callbacks_) {
  829. if (!FD_ISSET(s.socket_, &sockets)) {
  830. continue;
  831. }
  832. // something received over external socket
  833. // Calling the external socket's callback provides its service
  834. // layer access without integrating any specific features
  835. // in IfaceMgr
  836. if (s.callback_) {
  837. s.callback_();
  838. }
  839. return (Pkt4Ptr());
  840. }
  841. // Let's find out which interface/socket has the data
  842. BOOST_FOREACH(iface, ifaces_) {
  843. BOOST_FOREACH(SocketInfo s, iface->getSockets()) {
  844. if (FD_ISSET(s.sockfd_, &sockets)) {
  845. candidate = &(s);
  846. break;
  847. }
  848. }
  849. if (candidate) {
  850. break;
  851. }
  852. }
  853. if (!candidate) {
  854. isc_throw(SocketReadError, "received data over unknown socket");
  855. }
  856. // Now we have a socket, let's get some data from it!
  857. // Assuming that packet filter is not NULL, because its modifier checks it.
  858. return (packet_filter_->receive(*iface, *candidate));
  859. }
  860. Pkt6Ptr IfaceMgr::receive6(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */ ) {
  861. // Sanity check for microsecond timeout.
  862. if (timeout_usec >= 1000000) {
  863. isc_throw(BadValue, "fractional timeout must be shorter than"
  864. " one million microseconds");
  865. }
  866. const SocketInfo* candidate = 0;
  867. fd_set sockets;
  868. int maxfd = 0;
  869. FD_ZERO(&sockets);
  870. /// @todo: marginal performance optimization. We could create the set once
  871. /// and then use its copy for select(). Please note that select() modifies
  872. /// provided set to indicated which sockets have something to read.
  873. BOOST_FOREACH(IfacePtr iface, ifaces_) {
  874. BOOST_FOREACH(SocketInfo s, iface->getSockets()) {
  875. // Only deal with IPv6 addresses.
  876. if (s.addr_.isV6()) {
  877. // Add this socket to listening set
  878. FD_SET(s.sockfd_, &sockets);
  879. if (maxfd < s.sockfd_) {
  880. maxfd = s.sockfd_;
  881. }
  882. }
  883. }
  884. }
  885. // if there are any callbacks for external sockets registered...
  886. if (!callbacks_.empty()) {
  887. BOOST_FOREACH(SocketCallbackInfo s, callbacks_) {
  888. // Add it to the set as well
  889. FD_SET(s.socket_, &sockets);
  890. if (maxfd < s.socket_) {
  891. maxfd = s.socket_;
  892. }
  893. }
  894. }
  895. struct timeval select_timeout;
  896. select_timeout.tv_sec = timeout_sec;
  897. select_timeout.tv_usec = timeout_usec;
  898. // zero out the errno to be safe
  899. errno = 0;
  900. int result = select(maxfd + 1, &sockets, NULL, NULL, &select_timeout);
  901. if (result == 0) {
  902. // nothing received and timeout has been reached
  903. return (Pkt6Ptr()); // NULL
  904. } else if (result < 0) {
  905. // In most cases we would like to know whether select() returned
  906. // an error because of a signal being received or for some other
  907. // reasaon. This is because DHCP servers use signals to trigger
  908. // certain actions, like reconfiguration or graceful shutdown.
  909. // By catching a dedicated exception the caller will know if the
  910. // error returned by the function is due to the reception of the
  911. // signal or for some other reason.
  912. if (errno == EINTR) {
  913. isc_throw(SignalInterruptOnSelect, strerror(errno));
  914. } else {
  915. isc_throw(SocketReadError, strerror(errno));
  916. }
  917. }
  918. // Let's find out which socket has the data
  919. BOOST_FOREACH(SocketCallbackInfo s, callbacks_) {
  920. if (!FD_ISSET(s.socket_, &sockets)) {
  921. continue;
  922. }
  923. // something received over external socket
  924. // Calling the external socket's callback provides its service
  925. // layer access without integrating any specific features
  926. // in IfaceMgr
  927. if (s.callback_) {
  928. s.callback_();
  929. }
  930. return (Pkt6Ptr());
  931. }
  932. // Let's find out which interface/socket has the data
  933. BOOST_FOREACH(IfacePtr iface, ifaces_) {
  934. BOOST_FOREACH(SocketInfo s, iface->getSockets()) {
  935. if (FD_ISSET(s.sockfd_, &sockets)) {
  936. candidate = &(s);
  937. break;
  938. }
  939. }
  940. if (candidate) {
  941. break;
  942. }
  943. }
  944. if (!candidate) {
  945. isc_throw(SocketReadError, "received data over unknown socket");
  946. }
  947. // Assuming that packet filter is not NULL, because its modifier checks it.
  948. return (packet_filter6_->receive(*candidate));
  949. }
  950. uint16_t IfaceMgr::getSocket(const isc::dhcp::Pkt6& pkt) {
  951. IfacePtr iface = getIface(pkt.getIface());
  952. if (!iface) {
  953. isc_throw(IfaceNotFound, "Tried to find socket for non-existent interface");
  954. }
  955. const Iface::SocketCollection& socket_collection = iface->getSockets();
  956. Iface::SocketCollection::const_iterator candidate = socket_collection.end();
  957. Iface::SocketCollection::const_iterator s;
  958. for (s = socket_collection.begin(); s != socket_collection.end(); ++s) {
  959. // We should not merge those conditions for debugging reasons.
  960. // V4 sockets are useless for sending v6 packets.
  961. if (s->family_ != AF_INET6) {
  962. continue;
  963. }
  964. // Sockets bound to multicast address are useless for sending anything.
  965. if (s->addr_.isV6Multicast()) {
  966. continue;
  967. }
  968. if (s->addr_ == pkt.getLocalAddr()) {
  969. // This socket is bound to the source address. This is perfect
  970. // match, no need to look any further.
  971. return (s->sockfd_);
  972. }
  973. // If we don't have any other candidate, this one will do
  974. if (candidate == socket_collection.end()) {
  975. candidate = s;
  976. } else {
  977. // If we want to send something to link-local and the socket is
  978. // bound to link-local or we want to send to global and the socket
  979. // is bound to global, then use it as candidate
  980. if ( (pkt.getRemoteAddr().isV6LinkLocal() &&
  981. s->addr_.isV6LinkLocal()) ||
  982. (!pkt.getRemoteAddr().isV6LinkLocal() &&
  983. !s->addr_.isV6LinkLocal()) ) {
  984. candidate = s;
  985. }
  986. }
  987. }
  988. if (candidate != socket_collection.end()) {
  989. return (candidate->sockfd_);
  990. }
  991. isc_throw(SocketNotFound, "Interface " << iface->getFullName()
  992. << " does not have any suitable IPv6 sockets open.");
  993. }
  994. SocketInfo
  995. IfaceMgr::getSocket(isc::dhcp::Pkt4 const& pkt) {
  996. IfacePtr iface = getIface(pkt.getIface());
  997. if (iface == NULL) {
  998. isc_throw(IfaceNotFound, "Tried to find socket for non-existent interface");
  999. }
  1000. const Iface::SocketCollection& socket_collection = iface->getSockets();
  1001. // A candidate being an end of the iterator marks that it is a begining of
  1002. // the socket search and that the candidate needs to be set to the first
  1003. // socket found.
  1004. Iface::SocketCollection::const_iterator candidate = socket_collection.end();
  1005. Iface::SocketCollection::const_iterator s;
  1006. for (s = socket_collection.begin(); s != socket_collection.end(); ++s) {
  1007. if (s->family_ == AF_INET) {
  1008. if (s->addr_ == pkt.getLocalAddr()) {
  1009. return (*s);
  1010. }
  1011. if (candidate == socket_collection.end()) {
  1012. candidate = s;
  1013. }
  1014. }
  1015. }
  1016. if (candidate == socket_collection.end()) {
  1017. isc_throw(SocketNotFound, "Interface " << iface->getFullName()
  1018. << " does not have any suitable IPv4 sockets open.");
  1019. }
  1020. return (*candidate);
  1021. }
  1022. } // end of namespace isc::dhcp
  1023. } // end of namespace isc