iface_mgr.cc 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179
  1. // Copyright (C) 2011-2013 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. // This must be included before udp_endpoint.h
  16. #include <asio.hpp>
  17. #include <asiolink/io_error.h>
  18. #include <asiolink/udp_endpoint.h>
  19. #include <dhcp/dhcp4.h>
  20. #include <dhcp/dhcp6.h>
  21. #include <dhcp/iface_mgr.h>
  22. #include <dhcp/pkt_filter_inet.h>
  23. #include <exceptions/exceptions.h>
  24. #include <util/io/pktinfo_utilities.h>
  25. #include <fstream>
  26. #include <sstream>
  27. #include <arpa/inet.h>
  28. #include <netinet/in.h>
  29. #include <string.h>
  30. #include <sys/select.h>
  31. using namespace std;
  32. using namespace isc::asiolink;
  33. using namespace isc::util::io::internal;
  34. namespace isc {
  35. namespace dhcp {
  36. IfaceMgr&
  37. IfaceMgr::instance() {
  38. static IfaceMgr iface_mgr;
  39. return (iface_mgr);
  40. }
  41. Iface::Iface(const std::string& name, int ifindex)
  42. :name_(name), ifindex_(ifindex), mac_len_(0), hardware_type_(0),
  43. flag_loopback_(false), flag_up_(false), flag_running_(false),
  44. flag_multicast_(false), flag_broadcast_(false), flags_(0),
  45. inactive4_(false), inactive6_(false)
  46. {
  47. memset(mac_, 0, sizeof(mac_));
  48. }
  49. void
  50. Iface::closeSockets() {
  51. // Close IPv4 sockets.
  52. closeSockets(AF_INET);
  53. // Close IPv6 sockets.
  54. closeSockets(AF_INET6);
  55. }
  56. void
  57. Iface::closeSockets(const uint16_t family) {
  58. // Check that the correect 'family' value has been specified.
  59. // The possible values are AF_INET or AF_INET6. Note that, in
  60. // the current code they are used to differentiate that the
  61. // socket is used to transmit IPv4 or IPv6 traffic. However,
  62. // the actual family types of the sockets may be different,
  63. // e.g. for LPF we are using raw sockets of AF_PACKET family.
  64. //
  65. // @todo Consider replacing the AF_INET and AF_INET6 with some
  66. // enum which will not be confused with the actual socket type.
  67. if ((family != AF_INET) && (family != AF_INET6)) {
  68. isc_throw(BadValue, "Invalid socket family " << family
  69. << " specified when requested to close all sockets"
  70. << " which belong to this family");
  71. }
  72. // Search for the socket of the specific type.
  73. SocketCollection::iterator sock = sockets_.begin();
  74. while (sock != sockets_.end()) {
  75. if (sock->family_ == family) {
  76. // Close and delete the socket and move to the
  77. // next one.
  78. close(sock->sockfd_);
  79. sockets_.erase(sock++);
  80. } else {
  81. // Different type of socket. Let's move
  82. // to the next one.
  83. ++sock;
  84. }
  85. }
  86. }
  87. std::string
  88. Iface::getFullName() const {
  89. ostringstream tmp;
  90. tmp << name_ << "/" << ifindex_;
  91. return (tmp.str());
  92. }
  93. std::string
  94. Iface::getPlainMac() const {
  95. ostringstream tmp;
  96. tmp.fill('0');
  97. tmp << hex;
  98. for (int i = 0; i < mac_len_; i++) {
  99. tmp.width(2);
  100. tmp << static_cast<int>(mac_[i]);
  101. if (i < mac_len_-1) {
  102. tmp << ":";
  103. }
  104. }
  105. return (tmp.str());
  106. }
  107. void Iface::setMac(const uint8_t* mac, size_t len) {
  108. if (len > MAX_MAC_LEN) {
  109. isc_throw(OutOfRange, "Interface " << getFullName()
  110. << " was detected to have link address of length "
  111. << len << ", but maximum supported length is "
  112. << MAX_MAC_LEN);
  113. }
  114. mac_len_ = len;
  115. memcpy(mac_, mac, len);
  116. }
  117. bool Iface::delAddress(const isc::asiolink::IOAddress& addr) {
  118. for (AddressCollection::iterator a = addrs_.begin();
  119. a!=addrs_.end(); ++a) {
  120. if (*a==addr) {
  121. addrs_.erase(a);
  122. return (true);
  123. }
  124. }
  125. return (false);
  126. }
  127. bool Iface::delSocket(uint16_t sockfd) {
  128. list<SocketInfo>::iterator sock = sockets_.begin();
  129. while (sock!=sockets_.end()) {
  130. if (sock->sockfd_ == sockfd) {
  131. close(sockfd);
  132. sockets_.erase(sock);
  133. return (true); //socket found
  134. }
  135. ++sock;
  136. }
  137. return (false); // socket not found
  138. }
  139. IfaceMgr::IfaceMgr()
  140. :control_buf_len_(CMSG_SPACE(sizeof(struct in6_pktinfo))),
  141. control_buf_(new char[control_buf_len_]),
  142. session_socket_(INVALID_SOCKET), session_callback_(NULL),
  143. packet_filter_(new PktFilterInet())
  144. {
  145. try {
  146. // required for sending/receiving packets
  147. // let's keep it in front, just in case someone
  148. // wants to send anything during initialization
  149. // control_buf_ = boost::scoped_array<char>();
  150. detectIfaces();
  151. } catch (const std::exception& ex) {
  152. isc_throw(IfaceDetectError, ex.what());
  153. }
  154. }
  155. void IfaceMgr::closeSockets() {
  156. for (IfaceCollection::iterator iface = ifaces_.begin();
  157. iface != ifaces_.end(); ++iface) {
  158. iface->closeSockets();
  159. }
  160. }
  161. void
  162. IfaceMgr::closeSockets(const uint16_t family) {
  163. for (IfaceCollection::iterator iface = ifaces_.begin();
  164. iface != ifaces_.end(); ++iface) {
  165. iface->closeSockets(family);
  166. }
  167. }
  168. IfaceMgr::~IfaceMgr() {
  169. // control_buf_ is deleted automatically (scoped_ptr)
  170. control_buf_len_ = 0;
  171. closeSockets();
  172. }
  173. bool
  174. IfaceMgr::isDirectResponseSupported() const {
  175. return (packet_filter_->isDirectResponseSupported());
  176. }
  177. void
  178. IfaceMgr::setPacketFilter(const boost::shared_ptr<PktFilter>& packet_filter) {
  179. // Do not allow NULL pointer.
  180. if (!packet_filter) {
  181. isc_throw(InvalidPacketFilter, "NULL packet filter object specified");
  182. }
  183. // Different packet filters use different socket types. It does not make
  184. // sense to allow the change of packet filter when there are IPv4 sockets
  185. // open because they can't be used by the receive/send functions of the
  186. // new packet filter. Below, we check that there are no open IPv4 sockets.
  187. // If we find at least one, we have to fail. However, caller still has a
  188. // chance to replace the packet filter if he closes sockets explicitly.
  189. for (IfaceCollection::const_iterator iface = ifaces_.begin();
  190. iface != ifaces_.end(); ++iface) {
  191. const Iface::SocketCollection& sockets = iface->getSockets();
  192. for (Iface::SocketCollection::const_iterator sock = sockets.begin();
  193. sock != sockets.end(); ++sock) {
  194. if (sock->family_ == AF_INET) {
  195. // There is at least one socket open, so we have to fail.
  196. isc_throw(PacketFilterChangeDenied,
  197. "it is not allowed to set new packet"
  198. << " filter when there are open IPv4 sockets - need"
  199. << " to close them first");
  200. }
  201. }
  202. }
  203. // Everything is fine, so replace packet filter.
  204. packet_filter_ = packet_filter;
  205. }
  206. void IfaceMgr::stubDetectIfaces() {
  207. string ifaceName;
  208. const string v4addr("127.0.0.1"), v6addr("::1");
  209. // This is a stub implementation for interface detection. Actual detection
  210. // is faked by detecting loopback interface (lo or lo0). It will eventually
  211. // be removed once we have actual implementations for all supported systems.
  212. if (if_nametoindex("lo") > 0) {
  213. ifaceName = "lo";
  214. // this is Linux-like OS
  215. } else if (if_nametoindex("lo0") > 0) {
  216. ifaceName = "lo0";
  217. // this is BSD-like OS
  218. } else {
  219. // we give up. What OS is this, anyway? Solaris? Hurd?
  220. isc_throw(NotImplemented,
  221. "Interface detection on this OS is not supported.");
  222. }
  223. Iface iface(ifaceName, if_nametoindex(ifaceName.c_str()));
  224. iface.flag_up_ = true;
  225. iface.flag_running_ = true;
  226. // Note that we claim that this is not a loopback. iface_mgr tries to open a
  227. // socket on all interaces that are up, running and not loopback. As this is
  228. // the only interface we were able to detect, let's pretend this is a normal
  229. // interface.
  230. iface.flag_loopback_ = false;
  231. iface.flag_multicast_ = true;
  232. iface.flag_broadcast_ = true;
  233. iface.setHWType(HWTYPE_ETHERNET);
  234. iface.addAddress(IOAddress(v4addr));
  235. iface.addAddress(IOAddress(v6addr));
  236. addInterface(iface);
  237. }
  238. bool IfaceMgr::openSockets4(const uint16_t port, const bool use_bcast) {
  239. int sock;
  240. int count = 0;
  241. // This option is used to bind sockets to particular interfaces.
  242. // This is currently the only way to discover on which interface
  243. // the broadcast packet has been received. If this option is
  244. // not supported then only one interface should be confugured
  245. // to listen for broadcast traffic.
  246. #ifdef SO_BINDTODEVICE
  247. const bool bind_to_device = true;
  248. #else
  249. const bool bind_to_device = false;
  250. #endif
  251. int bcast_num = 0;
  252. for (IfaceCollection::iterator iface = ifaces_.begin();
  253. iface != ifaces_.end();
  254. ++iface) {
  255. if (iface->flag_loopback_ ||
  256. !iface->flag_up_ ||
  257. !iface->flag_running_ ||
  258. iface->inactive4_) {
  259. continue;
  260. }
  261. Iface::AddressCollection addrs = iface->getAddresses();
  262. for (Iface::AddressCollection::iterator addr = addrs.begin();
  263. addr != addrs.end();
  264. ++addr) {
  265. // Skip all but V4 addresses.
  266. if (!addr->isV4()) {
  267. continue;
  268. }
  269. // If selected interface is broadcast capable set appropriate
  270. // options on the socket so as it can receive and send broadcast
  271. // messages.
  272. if (iface->flag_broadcast_ && use_bcast) {
  273. // If our OS supports binding socket to a device we can listen
  274. // for broadcast messages on multiple interfaces. Otherwise we
  275. // bind to INADDR_ANY address but we can do it only once. Thus,
  276. // if one socket has been bound we can't do it any further.
  277. if (!bind_to_device && bcast_num > 0) {
  278. isc_throw(SocketConfigError, "SO_BINDTODEVICE socket option is"
  279. << " not supported on this OS; therefore, DHCP"
  280. << " server can only listen broadcast traffic on"
  281. << " a single interface");
  282. } else {
  283. // We haven't open any broadcast sockets yet, so we can
  284. // open at least one more.
  285. sock = openSocket(iface->getName(), *addr, port, true, true);
  286. // Binding socket to an interface is not supported so we can't
  287. // open any more broadcast sockets. Increase the number of
  288. // opened broadcast sockets.
  289. if (!bind_to_device) {
  290. ++bcast_num;
  291. }
  292. }
  293. } else {
  294. // Not broadcast capable, do not set broadcast flags.
  295. sock = openSocket(iface->getName(), *addr, port, false, false);
  296. }
  297. if (sock < 0) {
  298. isc_throw(SocketConfigError, "failed to open IPv4 socket"
  299. << " supporting broadcast traffic");
  300. }
  301. count++;
  302. }
  303. }
  304. return (count > 0);
  305. }
  306. bool IfaceMgr::openSockets6(const uint16_t port) {
  307. int sock;
  308. int count = 0;
  309. for (IfaceCollection::iterator iface = ifaces_.begin();
  310. iface != ifaces_.end();
  311. ++iface) {
  312. if (iface->flag_loopback_ ||
  313. !iface->flag_up_ ||
  314. !iface->flag_running_ ||
  315. iface->inactive6_) {
  316. continue;
  317. }
  318. Iface::AddressCollection addrs = iface->getAddresses();
  319. for (Iface::AddressCollection::iterator addr = addrs.begin();
  320. addr != addrs.end();
  321. ++addr) {
  322. // Skip all but V6 addresses.
  323. if (!addr->isV6()) {
  324. continue;
  325. }
  326. // Bind link-local addresses only. Otherwise we bind several sockets
  327. // on interfaces that have several global addresses. For examples
  328. // with interface with 2 global addresses, we would bind 3 sockets
  329. // (one for link-local and two for global). That would result in
  330. // getting each message 3 times.
  331. if (!addr->getAddress().to_v6().is_link_local()){
  332. continue;
  333. }
  334. sock = openSocket(iface->getName(), *addr, port);
  335. if (sock < 0) {
  336. isc_throw(SocketConfigError, "failed to open unicast socket");
  337. }
  338. // Binding socket to unicast address and then joining multicast group
  339. // works well on Mac OS (and possibly other BSDs), but does not work
  340. // on Linux.
  341. if ( !joinMulticast(sock, iface->getName(),
  342. string(ALL_DHCP_RELAY_AGENTS_AND_SERVERS))) {
  343. close(sock);
  344. isc_throw(SocketConfigError, "Failed to join "
  345. << ALL_DHCP_RELAY_AGENTS_AND_SERVERS
  346. << " multicast group.");
  347. }
  348. count++;
  349. /// @todo: Remove this ifdef once we start supporting BSD systems.
  350. #if defined(OS_LINUX)
  351. // To receive multicast traffic, Linux requires binding socket to
  352. // a multicast group. That in turn doesn't work on NetBSD.
  353. int sock2 = openSocket(iface->getName(),
  354. IOAddress(ALL_DHCP_RELAY_AGENTS_AND_SERVERS),
  355. port);
  356. if (sock2 < 0) {
  357. isc_throw(SocketConfigError, "Failed to open multicast socket on "
  358. << " interface " << iface->getFullName());
  359. iface->delSocket(sock); // delete previously opened socket
  360. }
  361. #endif
  362. }
  363. }
  364. return (count > 0);
  365. }
  366. void
  367. IfaceMgr::printIfaces(std::ostream& out /*= std::cout*/) {
  368. for (IfaceCollection::const_iterator iface=ifaces_.begin();
  369. iface!=ifaces_.end();
  370. ++iface) {
  371. const Iface::AddressCollection& addrs = iface->getAddresses();
  372. out << "Detected interface " << iface->getFullName()
  373. << ", hwtype=" << iface->getHWType()
  374. << ", mac=" << iface->getPlainMac();
  375. out << ", flags=" << hex << iface->flags_ << dec << "("
  376. << (iface->flag_loopback_?"LOOPBACK ":"")
  377. << (iface->flag_up_?"UP ":"")
  378. << (iface->flag_running_?"RUNNING ":"")
  379. << (iface->flag_multicast_?"MULTICAST ":"")
  380. << (iface->flag_broadcast_?"BROADCAST ":"")
  381. << ")" << endl;
  382. out << " " << addrs.size() << " addr(s):";
  383. for (Iface::AddressCollection::const_iterator addr = addrs.begin();
  384. addr != addrs.end(); ++addr) {
  385. out << " " << addr->toText();
  386. }
  387. out << endl;
  388. }
  389. }
  390. Iface*
  391. IfaceMgr::getIface(int ifindex) {
  392. for (IfaceCollection::iterator iface=ifaces_.begin();
  393. iface!=ifaces_.end();
  394. ++iface) {
  395. if (iface->getIndex() == ifindex)
  396. return (&(*iface));
  397. }
  398. return (NULL); // not found
  399. }
  400. Iface*
  401. IfaceMgr::getIface(const std::string& ifname) {
  402. for (IfaceCollection::iterator iface=ifaces_.begin();
  403. iface!=ifaces_.end();
  404. ++iface) {
  405. if (iface->getName() == ifname)
  406. return (&(*iface));
  407. }
  408. return (NULL); // not found
  409. }
  410. int IfaceMgr::openSocket(const std::string& ifname, const IOAddress& addr,
  411. const uint16_t port, const bool receive_bcast,
  412. const bool send_bcast) {
  413. Iface* iface = getIface(ifname);
  414. if (!iface) {
  415. isc_throw(BadValue, "There is no " << ifname << " interface present.");
  416. }
  417. if (addr.isV4()) {
  418. return openSocket4(*iface, addr, port, receive_bcast, send_bcast);
  419. } else if (addr.isV6()) {
  420. return openSocket6(*iface, addr, port);
  421. } else {
  422. isc_throw(BadValue, "Failed to detect family of address: "
  423. << addr.toText());
  424. }
  425. }
  426. int IfaceMgr::openSocketFromIface(const std::string& ifname,
  427. const uint16_t port,
  428. const uint8_t family) {
  429. // Search for specified interface among detected interfaces.
  430. for (IfaceCollection::iterator iface = ifaces_.begin();
  431. iface != ifaces_.end();
  432. ++iface) {
  433. if ((iface->getFullName() != ifname) &&
  434. (iface->getName() != ifname)) {
  435. continue;
  436. }
  437. // Interface is now detected. Search for address on interface
  438. // that matches address family (v6 or v4).
  439. Iface::AddressCollection addrs = iface->getAddresses();
  440. Iface::AddressCollection::iterator addr_it = addrs.begin();
  441. while (addr_it != addrs.end()) {
  442. if (addr_it->getFamily() == family) {
  443. // We have interface and address so let's open socket.
  444. // This may cause isc::Unexpected exception.
  445. return (openSocket(iface->getName(), *addr_it, port));
  446. }
  447. ++addr_it;
  448. }
  449. // If we are at the end of address collection it means that we found
  450. // interface but there is no address for family specified.
  451. if (addr_it == addrs.end()) {
  452. // Stringify the family value to append it to exception string.
  453. std::string family_name("AF_INET");
  454. if (family == AF_INET6) {
  455. family_name = "AF_INET6";
  456. }
  457. // We did not find address on the interface.
  458. isc_throw(SocketConfigError, "There is no address for interface: "
  459. << ifname << ", port: " << port << ", address "
  460. " family: " << family_name);
  461. }
  462. }
  463. // If we got here it means that we had not found the specified interface.
  464. // Otherwise we would have returned from previous exist points.
  465. isc_throw(BadValue, "There is no " << ifname << " interface present.");
  466. }
  467. int IfaceMgr::openSocketFromAddress(const IOAddress& addr,
  468. const uint16_t port) {
  469. // Search through detected interfaces and addresses to match
  470. // local address we got.
  471. for (IfaceCollection::iterator iface = ifaces_.begin();
  472. iface != ifaces_.end();
  473. ++iface) {
  474. Iface::AddressCollection addrs = iface->getAddresses();
  475. for (Iface::AddressCollection::iterator addr_it = addrs.begin();
  476. addr_it != addrs.end();
  477. ++addr_it) {
  478. // Local address must match one of the addresses
  479. // on detected interfaces. If it does, we have
  480. // address and interface detected so we can open
  481. // socket.
  482. if (*addr_it == addr) {
  483. // Open socket using local interface, address and port.
  484. // This may cause isc::Unexpected exception.
  485. return (openSocket(iface->getName(), *addr_it, port));
  486. }
  487. }
  488. }
  489. // If we got here it means that we did not find specified address
  490. // on any available interface.
  491. isc_throw(BadValue, "There is no such address " << addr.toText());
  492. }
  493. int IfaceMgr::openSocketFromRemoteAddress(const IOAddress& remote_addr,
  494. const uint16_t port) {
  495. try {
  496. // Get local address to be used to connect to remote location.
  497. IOAddress local_address(getLocalAddress(remote_addr, port).getAddress());
  498. return openSocketFromAddress(local_address, port);
  499. } catch (const Exception& e) {
  500. isc_throw(SocketConfigError, e.what());
  501. }
  502. }
  503. isc::asiolink::IOAddress
  504. IfaceMgr::getLocalAddress(const IOAddress& remote_addr, const uint16_t port) {
  505. // Create remote endpoint, we will be connecting to it.
  506. boost::scoped_ptr<const UDPEndpoint>
  507. remote_endpoint(static_cast<const UDPEndpoint*>
  508. (UDPEndpoint::create(IPPROTO_UDP, remote_addr, port)));
  509. if (!remote_endpoint) {
  510. isc_throw(Unexpected, "Unable to create remote endpoint");
  511. }
  512. // Create socket that will be used to connect to remote endpoint.
  513. asio::io_service io_service;
  514. asio::ip::udp::socket sock(io_service);
  515. asio::error_code err_code;
  516. // If remote address is broadcast address we have to
  517. // allow this on the socket.
  518. if (remote_addr.isV4() &&
  519. (remote_addr == IOAddress(DHCP_IPV4_BROADCAST_ADDRESS))) {
  520. // Socket has to be open prior to setting the broadcast
  521. // option. Otherwise set_option will complain about
  522. // bad file descriptor.
  523. // @todo: We don't specify interface in any way here. 255.255.255.255
  524. // We can very easily end up with a socket working on a different
  525. // interface.
  526. sock.open(asio::ip::udp::v4(), err_code);
  527. if (err_code) {
  528. isc_throw(Unexpected, "failed to open UDPv4 socket");
  529. }
  530. sock.set_option(asio::socket_base::broadcast(true), err_code);
  531. if (err_code) {
  532. sock.close();
  533. isc_throw(Unexpected, "failed to enable broadcast on the socket");
  534. }
  535. }
  536. // Try to connect to remote endpoint and check if attempt is successful.
  537. sock.connect(remote_endpoint->getASIOEndpoint(), err_code);
  538. if (err_code) {
  539. sock.close();
  540. isc_throw(Unexpected, "failed to connect to remote endpoint.");
  541. }
  542. // Once we are connected socket object holds local endpoint.
  543. asio::ip::udp::socket::endpoint_type local_endpoint =
  544. sock.local_endpoint();
  545. asio::ip::address local_address(local_endpoint.address());
  546. // Close the socket.
  547. sock.close();
  548. // Return address of local endpoint.
  549. return IOAddress(local_address);
  550. }
  551. int IfaceMgr::openSocket6(Iface& iface, const IOAddress& addr, uint16_t port) {
  552. struct sockaddr_in6 addr6;
  553. memset(&addr6, 0, sizeof(addr6));
  554. addr6.sin6_family = AF_INET6;
  555. addr6.sin6_port = htons(port);
  556. if (addr.toText() != "::1") {
  557. addr6.sin6_scope_id = if_nametoindex(iface.getName().c_str());
  558. }
  559. memcpy(&addr6.sin6_addr, &addr.toBytes()[0], sizeof(addr6.sin6_addr));
  560. #ifdef HAVE_SA_LEN
  561. addr6.sin6_len = sizeof(addr6);
  562. #endif
  563. // TODO: use sockcreator once it becomes available
  564. // make a socket
  565. int sock = socket(AF_INET6, SOCK_DGRAM, 0);
  566. if (sock < 0) {
  567. isc_throw(SocketConfigError, "Failed to create UDP6 socket.");
  568. }
  569. // Set the REUSEADDR option so that we don't fail to start if
  570. // we're being restarted.
  571. int flag = 1;
  572. if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
  573. (char *)&flag, sizeof(flag)) < 0) {
  574. close(sock);
  575. isc_throw(SocketConfigError, "Can't set SO_REUSEADDR option on dhcpv6 socket.");
  576. }
  577. if (bind(sock, (struct sockaddr *)&addr6, sizeof(addr6)) < 0) {
  578. close(sock);
  579. isc_throw(SocketConfigError, "Failed to bind socket " << sock << " to " << addr.toText()
  580. << "/port=" << port);
  581. }
  582. #ifdef IPV6_RECVPKTINFO
  583. // RFC3542 - a new way
  584. if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO,
  585. &flag, sizeof(flag)) != 0) {
  586. close(sock);
  587. isc_throw(SocketConfigError, "setsockopt: IPV6_RECVPKTINFO failed.");
  588. }
  589. #else
  590. // RFC2292 - an old way
  591. if (setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO,
  592. &flag, sizeof(flag)) != 0) {
  593. close(sock);
  594. isc_throw(SocketConfigError, "setsockopt: IPV6_PKTINFO: failed.");
  595. }
  596. #endif
  597. // multicast stuff
  598. if (addr.getAddress().to_v6().is_multicast()) {
  599. // both mcast (ALL_DHCP_RELAY_AGENTS_AND_SERVERS and ALL_DHCP_SERVERS)
  600. // are link and site-scoped, so there is no sense to join those groups
  601. // with global addresses.
  602. if ( !joinMulticast( sock, iface.getName(),
  603. string(ALL_DHCP_RELAY_AGENTS_AND_SERVERS) ) ) {
  604. close(sock);
  605. isc_throw(SocketConfigError, "Failed to join " << ALL_DHCP_RELAY_AGENTS_AND_SERVERS
  606. << " multicast group.");
  607. }
  608. }
  609. SocketInfo info(sock, addr, port);
  610. iface.addSocket(info);
  611. return (sock);
  612. }
  613. int IfaceMgr::openSocket4(Iface& iface, const IOAddress& addr,
  614. const uint16_t port, const bool receive_bcast,
  615. const bool send_bcast) {
  616. // Skip checking if the packet_filter_ is non-NULL because this check
  617. // has been already done when packet filter object was set.
  618. int sock = packet_filter_->openSocket(iface, addr, port,
  619. receive_bcast, send_bcast);
  620. SocketInfo info(sock, addr, port);
  621. iface.addSocket(info);
  622. return (sock);
  623. }
  624. bool
  625. IfaceMgr::joinMulticast(int sock, const std::string& ifname,
  626. const std::string & mcast) {
  627. struct ipv6_mreq mreq;
  628. if (inet_pton(AF_INET6, mcast.c_str(),
  629. &mreq.ipv6mr_multiaddr) <= 0) {
  630. return (false);
  631. }
  632. mreq.ipv6mr_interface = if_nametoindex(ifname.c_str());
  633. if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
  634. &mreq, sizeof(mreq)) < 0) {
  635. return (false);
  636. }
  637. return (true);
  638. }
  639. bool
  640. IfaceMgr::send(const Pkt6Ptr& pkt) {
  641. int result;
  642. Iface* iface = getIface(pkt->getIface());
  643. if (!iface) {
  644. isc_throw(BadValue, "Unable to send Pkt6. Invalid interface ("
  645. << pkt->getIface() << ") specified.");
  646. }
  647. memset(&control_buf_[0], 0, control_buf_len_);
  648. // Set the target address we're sending to.
  649. sockaddr_in6 to;
  650. memset(&to, 0, sizeof(to));
  651. to.sin6_family = AF_INET6;
  652. to.sin6_port = htons(pkt->getRemotePort());
  653. memcpy(&to.sin6_addr,
  654. &pkt->getRemoteAddr().toBytes()[0],
  655. 16);
  656. to.sin6_scope_id = pkt->getIndex();
  657. // Initialize our message header structure.
  658. struct msghdr m;
  659. memset(&m, 0, sizeof(m));
  660. m.msg_name = &to;
  661. m.msg_namelen = sizeof(to);
  662. // Set the data buffer we're sending. (Using this wacky
  663. // "scatter-gather" stuff... we only have a single chunk
  664. // of data to send, so we declare a single vector entry.)
  665. // As v structure is a C-style is used for both sending and
  666. // receiving data, it is shared between sending and receiving
  667. // (sendmsg and recvmsg). It is also defined in system headers,
  668. // so we have no control over its definition. To set iov_base
  669. // (defined as void*) we must use const cast from void *.
  670. // Otherwise C++ compiler would complain that we are trying
  671. // to assign const void* to void*.
  672. struct iovec v;
  673. memset(&v, 0, sizeof(v));
  674. v.iov_base = const_cast<void *>(pkt->getBuffer().getData());
  675. v.iov_len = pkt->getBuffer().getLength();
  676. m.msg_iov = &v;
  677. m.msg_iovlen = 1;
  678. // Setting the interface is a bit more involved.
  679. //
  680. // We have to create a "control message", and set that to
  681. // define the IPv6 packet information. We could set the
  682. // source address if we wanted, but we can safely let the
  683. // kernel decide what that should be.
  684. m.msg_control = &control_buf_[0];
  685. m.msg_controllen = control_buf_len_;
  686. struct cmsghdr *cmsg = CMSG_FIRSTHDR(&m);
  687. // FIXME: Code below assumes that cmsg is not NULL, but
  688. // CMSG_FIRSTHDR() is coded to return NULL as a possibility. The
  689. // following assertion should never fail, but if it did and you came
  690. // here, fix the code. :)
  691. assert(cmsg != NULL);
  692. cmsg->cmsg_level = IPPROTO_IPV6;
  693. cmsg->cmsg_type = IPV6_PKTINFO;
  694. cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
  695. struct in6_pktinfo *pktinfo = convertPktInfo6(CMSG_DATA(cmsg));
  696. memset(pktinfo, 0, sizeof(struct in6_pktinfo));
  697. pktinfo->ipi6_ifindex = pkt->getIndex();
  698. m.msg_controllen = cmsg->cmsg_len;
  699. pkt->updateTimestamp();
  700. result = sendmsg(getSocket(*pkt), &m, 0);
  701. if (result < 0) {
  702. isc_throw(SocketWriteError, "Pkt6 send failed: sendmsg() returned " << result);
  703. }
  704. return (result);
  705. }
  706. bool
  707. IfaceMgr::send(const Pkt4Ptr& pkt) {
  708. Iface* iface = getIface(pkt->getIface());
  709. if (!iface) {
  710. isc_throw(BadValue, "Unable to send Pkt4. Invalid interface ("
  711. << pkt->getIface() << ") specified.");
  712. }
  713. // Skip checking if packet filter is non-NULL because it has been
  714. // already checked when packet filter was set.
  715. return (packet_filter_->send(*iface, getSocket(*pkt), pkt));
  716. }
  717. boost::shared_ptr<Pkt4>
  718. IfaceMgr::receive4(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */) {
  719. // Sanity check for microsecond timeout.
  720. if (timeout_usec >= 1000000) {
  721. isc_throw(BadValue, "fractional timeout must be shorter than"
  722. " one million microseconds");
  723. }
  724. const SocketInfo* candidate = 0;
  725. IfaceCollection::const_iterator iface;
  726. fd_set sockets;
  727. int maxfd = 0;
  728. stringstream names;
  729. FD_ZERO(&sockets);
  730. /// @todo: marginal performance optimization. We could create the set once
  731. /// and then use its copy for select(). Please note that select() modifies
  732. /// provided set to indicated which sockets have something to read.
  733. for (iface = ifaces_.begin(); iface != ifaces_.end(); ++iface) {
  734. const Iface::SocketCollection& socket_collection = iface->getSockets();
  735. for (Iface::SocketCollection::const_iterator s = socket_collection.begin();
  736. s != socket_collection.end(); ++s) {
  737. // Only deal with IPv4 addresses.
  738. if (s->addr_.isV4()) {
  739. names << s->sockfd_ << "(" << iface->getName() << ") ";
  740. // Add this socket to listening set
  741. FD_SET(s->sockfd_, &sockets);
  742. if (maxfd < s->sockfd_) {
  743. maxfd = s->sockfd_;
  744. }
  745. }
  746. }
  747. }
  748. // if there is session socket registered...
  749. if (session_socket_ != INVALID_SOCKET) {
  750. // at it to the set as well
  751. FD_SET(session_socket_, &sockets);
  752. if (maxfd < session_socket_)
  753. maxfd = session_socket_;
  754. names << session_socket_ << "(session)";
  755. }
  756. struct timeval select_timeout;
  757. select_timeout.tv_sec = timeout_sec;
  758. select_timeout.tv_usec = timeout_usec;
  759. int result = select(maxfd + 1, &sockets, NULL, NULL, &select_timeout);
  760. if (result == 0) {
  761. // nothing received and timeout has been reached
  762. return (Pkt4Ptr()); // NULL
  763. } else if (result < 0) {
  764. isc_throw(SocketReadError, strerror(errno));
  765. }
  766. // Let's find out which socket has the data
  767. if ((session_socket_ != INVALID_SOCKET) && (FD_ISSET(session_socket_, &sockets))) {
  768. // something received over session socket
  769. if (session_callback_) {
  770. // in theory we could call io_service.run_one() here, instead of
  771. // implementing callback mechanism, but that would introduce
  772. // asiolink dependency to libdhcp++ and that is something we want
  773. // to avoid (see CPE market and out long term plans for minimalistic
  774. // implementations.
  775. session_callback_();
  776. }
  777. return (Pkt4Ptr()); // NULL
  778. }
  779. // Let's find out which interface/socket has the data
  780. for (iface = ifaces_.begin(); iface != ifaces_.end(); ++iface) {
  781. const Iface::SocketCollection& socket_collection = iface->getSockets();
  782. for (Iface::SocketCollection::const_iterator s = socket_collection.begin();
  783. s != socket_collection.end(); ++s) {
  784. if (FD_ISSET(s->sockfd_, &sockets)) {
  785. candidate = &(*s);
  786. break;
  787. }
  788. }
  789. if (candidate) {
  790. break;
  791. }
  792. }
  793. if (!candidate) {
  794. isc_throw(SocketReadError, "received data over unknown socket");
  795. }
  796. // Now we have a socket, let's get some data from it!
  797. // Skip checking if packet filter is non-NULL because it has been
  798. // already checked when packet filter was set.
  799. return (packet_filter_->receive(*iface, *candidate));
  800. }
  801. Pkt6Ptr IfaceMgr::receive6(uint32_t timeout_sec, uint32_t timeout_usec /* = 0 */ ) {
  802. // Sanity check for microsecond timeout.
  803. if (timeout_usec >= 1000000) {
  804. isc_throw(BadValue, "fractional timeout must be shorter than"
  805. " one million microseconds");
  806. }
  807. const SocketInfo* candidate = 0;
  808. fd_set sockets;
  809. int maxfd = 0;
  810. stringstream names;
  811. FD_ZERO(&sockets);
  812. /// @todo: marginal performance optimization. We could create the set once
  813. /// and then use its copy for select(). Please note that select() modifies
  814. /// provided set to indicated which sockets have something to read.
  815. IfaceCollection::const_iterator iface;
  816. for (iface = ifaces_.begin(); iface != ifaces_.end(); ++iface) {
  817. const Iface::SocketCollection& socket_collection = iface->getSockets();
  818. for (Iface::SocketCollection::const_iterator s = socket_collection.begin();
  819. s != socket_collection.end(); ++s) {
  820. // Only deal with IPv6 addresses.
  821. if (s->addr_.isV6()) {
  822. names << s->sockfd_ << "(" << iface->getName() << ") ";
  823. // Add this socket to listening set
  824. FD_SET(s->sockfd_, &sockets);
  825. if (maxfd < s->sockfd_) {
  826. maxfd = s->sockfd_;
  827. }
  828. }
  829. }
  830. }
  831. // if there is session socket registered...
  832. if (session_socket_ != INVALID_SOCKET) {
  833. // at it to the set as well
  834. FD_SET(session_socket_, &sockets);
  835. if (maxfd < session_socket_)
  836. maxfd = session_socket_;
  837. names << session_socket_ << "(session)";
  838. }
  839. struct timeval select_timeout;
  840. select_timeout.tv_sec = timeout_sec;
  841. select_timeout.tv_usec = timeout_usec;
  842. int result = select(maxfd + 1, &sockets, NULL, NULL, &select_timeout);
  843. if (result == 0) {
  844. // nothing received and timeout has been reached
  845. return (Pkt6Ptr()); // NULL
  846. } else if (result < 0) {
  847. isc_throw(SocketReadError, strerror(errno));
  848. }
  849. // Let's find out which socket has the data
  850. if ((session_socket_ != INVALID_SOCKET) && (FD_ISSET(session_socket_, &sockets))) {
  851. // something received over session socket
  852. if (session_callback_) {
  853. // in theory we could call io_service.run_one() here, instead of
  854. // implementing callback mechanism, but that would introduce
  855. // asiolink dependency to libdhcp++ and that is something we want
  856. // to avoid (see CPE market and out long term plans for minimalistic
  857. // implementations.
  858. session_callback_();
  859. }
  860. return (Pkt6Ptr()); // NULL
  861. }
  862. // Let's find out which interface/socket has the data
  863. for (iface = ifaces_.begin(); iface != ifaces_.end(); ++iface) {
  864. const Iface::SocketCollection& socket_collection = iface->getSockets();
  865. for (Iface::SocketCollection::const_iterator s = socket_collection.begin();
  866. s != socket_collection.end(); ++s) {
  867. if (FD_ISSET(s->sockfd_, &sockets)) {
  868. candidate = &(*s);
  869. break;
  870. }
  871. }
  872. if (candidate) {
  873. break;
  874. }
  875. }
  876. if (!candidate) {
  877. isc_throw(SocketReadError, "received data over unknown socket");
  878. }
  879. // Now we have a socket, let's get some data from it!
  880. uint8_t buf[RCVBUFSIZE];
  881. memset(&control_buf_[0], 0, control_buf_len_);
  882. struct sockaddr_in6 from;
  883. memset(&from, 0, sizeof(from));
  884. // Initialize our message header structure.
  885. struct msghdr m;
  886. memset(&m, 0, sizeof(m));
  887. // Point so we can get the from address.
  888. m.msg_name = &from;
  889. m.msg_namelen = sizeof(from);
  890. // Set the data buffer we're receiving. (Using this wacky
  891. // "scatter-gather" stuff... but we that doesn't really make
  892. // sense for us, so we use a single vector entry.)
  893. struct iovec v;
  894. memset(&v, 0, sizeof(v));
  895. v.iov_base = static_cast<void*>(buf);
  896. v.iov_len = RCVBUFSIZE;
  897. m.msg_iov = &v;
  898. m.msg_iovlen = 1;
  899. // Getting the interface is a bit more involved.
  900. //
  901. // We set up some space for a "control message". We have
  902. // previously asked the kernel to give us packet
  903. // information (when we initialized the interface), so we
  904. // should get the destination address from that.
  905. m.msg_control = &control_buf_[0];
  906. m.msg_controllen = control_buf_len_;
  907. result = recvmsg(candidate->sockfd_, &m, 0);
  908. struct in6_addr to_addr;
  909. memset(&to_addr, 0, sizeof(to_addr));
  910. int ifindex = -1;
  911. if (result >= 0) {
  912. struct in6_pktinfo* pktinfo = NULL;
  913. // If we did read successfully, then we need to loop
  914. // through the control messages we received and
  915. // find the one with our destination address.
  916. //
  917. // We also keep a flag to see if we found it. If we
  918. // didn't, then we consider this to be an error.
  919. bool found_pktinfo = false;
  920. struct cmsghdr* cmsg = CMSG_FIRSTHDR(&m);
  921. while (cmsg != NULL) {
  922. if ((cmsg->cmsg_level == IPPROTO_IPV6) &&
  923. (cmsg->cmsg_type == IPV6_PKTINFO)) {
  924. pktinfo = convertPktInfo6(CMSG_DATA(cmsg));
  925. to_addr = pktinfo->ipi6_addr;
  926. ifindex = pktinfo->ipi6_ifindex;
  927. found_pktinfo = true;
  928. break;
  929. }
  930. cmsg = CMSG_NXTHDR(&m, cmsg);
  931. }
  932. if (!found_pktinfo) {
  933. isc_throw(SocketReadError, "unable to find pktinfo");
  934. }
  935. } else {
  936. isc_throw(SocketReadError, "failed to receive data");
  937. }
  938. // Let's create a packet.
  939. Pkt6Ptr pkt;
  940. try {
  941. pkt = Pkt6Ptr(new Pkt6(buf, result));
  942. } catch (const std::exception& ex) {
  943. isc_throw(SocketReadError, "failed to create new packet");
  944. }
  945. pkt->updateTimestamp();
  946. pkt->setLocalAddr(IOAddress::fromBytes(AF_INET6,
  947. reinterpret_cast<const uint8_t*>(&to_addr)));
  948. pkt->setRemoteAddr(IOAddress::fromBytes(AF_INET6,
  949. reinterpret_cast<const uint8_t*>(&from.sin6_addr)));
  950. pkt->setRemotePort(ntohs(from.sin6_port));
  951. pkt->setIndex(ifindex);
  952. Iface* received = getIface(pkt->getIndex());
  953. if (received) {
  954. pkt->setIface(received->getName());
  955. } else {
  956. isc_throw(SocketReadError, "received packet over unknown interface"
  957. << "(ifindex=" << pkt->getIndex() << ")");
  958. }
  959. return (pkt);
  960. }
  961. uint16_t IfaceMgr::getSocket(const isc::dhcp::Pkt6& pkt) {
  962. Iface* iface = getIface(pkt.getIface());
  963. if (iface == NULL) {
  964. isc_throw(BadValue, "Tried to find socket for non-existent interface "
  965. << pkt.getIface());
  966. }
  967. const Iface::SocketCollection& socket_collection = iface->getSockets();
  968. Iface::SocketCollection::const_iterator s;
  969. for (s = socket_collection.begin(); s != socket_collection.end(); ++s) {
  970. if ((s->family_ == AF_INET6) &&
  971. (!s->addr_.getAddress().to_v6().is_multicast())) {
  972. return (s->sockfd_);
  973. }
  974. /// @todo: Add more checks here later. If remote address is
  975. /// not link-local, we can't use link local bound socket
  976. /// to send data.
  977. }
  978. isc_throw(Unexpected, "Interface " << iface->getFullName()
  979. << " does not have any suitable IPv6 sockets open.");
  980. }
  981. uint16_t IfaceMgr::getSocket(isc::dhcp::Pkt4 const& pkt) {
  982. Iface* iface = getIface(pkt.getIface());
  983. if (iface == NULL) {
  984. isc_throw(BadValue, "Tried to find socket for non-existent interface "
  985. << pkt.getIface());
  986. }
  987. const Iface::SocketCollection& socket_collection = iface->getSockets();
  988. Iface::SocketCollection::const_iterator s;
  989. for (s = socket_collection.begin(); s != socket_collection.end(); ++s) {
  990. if (s->family_ == AF_INET) {
  991. return (s->sockfd_);
  992. }
  993. /// TODO: Add more checks here later. If remote address is
  994. /// not link-local, we can't use link local bound socket
  995. /// to send data.
  996. }
  997. isc_throw(Unexpected, "Interface " << iface->getFullName()
  998. << " does not have any suitable IPv4 sockets open.");
  999. }
  1000. } // end of namespace isc::dhcp
  1001. } // end of namespace isc