iface_mgr_sun.cc 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. // Copyright (C) 2011-2015 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. #if defined(OS_SUN)
  8. #include <dhcp/iface_mgr.h>
  9. #include <dhcp/iface_mgr_error_handler.h>
  10. #include <dhcp/pkt_filter_inet.h>
  11. #include <exceptions/exceptions.h>
  12. #include <sys/types.h>
  13. #include <sys/socket.h>
  14. #include <net/if_dl.h>
  15. #include <net/if.h>
  16. #include <ifaddrs.h>
  17. using namespace std;
  18. using namespace isc;
  19. using namespace isc::asiolink;
  20. using namespace isc::dhcp;
  21. namespace isc {
  22. namespace dhcp {
  23. /// This is a Solaris specific interface detection code. It works on Solaris 11
  24. /// only, as earlier versions did not support getifaddrs() API.
  25. void
  26. IfaceMgr::detectIfaces() {
  27. struct ifaddrs* iflist = 0;// The whole interface list
  28. struct ifaddrs* ifptr = 0; // The interface we're processing now
  29. // Gets list of ifaddrs struct
  30. if(getifaddrs(&iflist) != 0) {
  31. isc_throw(Unexpected, "Network interfaces detection failed.");
  32. }
  33. typedef map<string, IfacePtr> IfaceLst;
  34. IfaceLst::iterator iface_iter;
  35. IfaceLst ifaces;
  36. // First lookup for getting interfaces ...
  37. for (ifptr = iflist; ifptr != 0; ifptr = ifptr->ifa_next) {
  38. const char * ifname = ifptr->ifa_name;
  39. uint ifindex = 0;
  40. if (!(ifindex = if_nametoindex(ifname))) {
  41. // Interface name does not have corresponding index ...
  42. freeifaddrs(iflist);
  43. isc_throw(Unexpected, "Interface " << ifname << " has no index");
  44. }
  45. iface_iter = ifaces.find(ifname);
  46. if (iface_iter != ifaces.end()) {
  47. continue;
  48. }
  49. IfacePtr iface(new Iface(ifname, ifindex));
  50. iface->setFlags(ifptr->ifa_flags);
  51. ifaces.insert(pair<string, IfacePtr>(ifname, iface));
  52. }
  53. // Second lookup to get MAC and IP addresses
  54. for (ifptr = iflist; ifptr != 0; ifptr = ifptr->ifa_next) {
  55. iface_iter = ifaces.find(ifptr->ifa_name);
  56. if (iface_iter == ifaces.end()) {
  57. continue;
  58. }
  59. // Common byte pointer for following data
  60. const uint8_t * ptr = 0;
  61. if(ifptr->ifa_addr->sa_family == AF_LINK) {
  62. // HWAddr
  63. struct sockaddr_dl * ldata =
  64. reinterpret_cast<struct sockaddr_dl *>(ifptr->ifa_addr);
  65. ptr = reinterpret_cast<uint8_t *>(LLADDR(ldata));
  66. iface_iter->second->setHWType(ldata->sdl_type);
  67. iface_iter->second->setMac(ptr, ldata->sdl_alen);
  68. } else if(ifptr->ifa_addr->sa_family == AF_INET6) {
  69. // IPv6 Addr
  70. struct sockaddr_in6 * adata =
  71. reinterpret_cast<struct sockaddr_in6 *>(ifptr->ifa_addr);
  72. ptr = reinterpret_cast<uint8_t *>(&adata->sin6_addr);
  73. IOAddress a = IOAddress::fromBytes(AF_INET6, ptr);
  74. iface_iter->second->addAddress(a);
  75. } else {
  76. // IPv4 Addr
  77. struct sockaddr_in * adata =
  78. reinterpret_cast<struct sockaddr_in *>(ifptr->ifa_addr);
  79. ptr = reinterpret_cast<uint8_t *>(&adata->sin_addr);
  80. IOAddress a = IOAddress::fromBytes(AF_INET, ptr);
  81. iface_iter->second->addAddress(a);
  82. }
  83. }
  84. freeifaddrs(iflist);
  85. // Interfaces registering
  86. for(IfaceLst::const_iterator iface_iter = ifaces.begin();
  87. iface_iter != ifaces.end(); ++iface_iter) {
  88. addInterface(iface_iter->second);
  89. }
  90. }
  91. /// @brief sets flag_*_ fields
  92. ///
  93. /// Like Linux version, os specific flags
  94. ///
  95. /// @params flags
  96. void Iface::setFlags(uint64_t flags) {
  97. flags_ = flags;
  98. flag_loopback_ = flags & IFF_LOOPBACK;
  99. flag_up_ = flags & IFF_UP;
  100. flag_running_ = flags & IFF_RUNNING;
  101. flag_multicast_ = flags & IFF_MULTICAST;
  102. flag_broadcast_ = flags & IFF_BROADCAST;
  103. }
  104. void
  105. IfaceMgr::setMatchingPacketFilter(const bool /* direct_response_desired */) {
  106. // @todo Currently we ignore the preference to use direct traffic
  107. // because it hasn't been implemented for Solaris.
  108. setPacketFilter(PktFilterPtr(new PktFilterInet()));
  109. }
  110. bool
  111. IfaceMgr::openMulticastSocket(Iface& iface,
  112. const isc::asiolink::IOAddress& addr,
  113. const uint16_t port,
  114. IfaceMgrErrorMsgCallback error_handler) {
  115. try {
  116. // This should open a socket, bound it to link-local address
  117. // and join multicast group.
  118. openSocket(iface.getName(), addr, port,
  119. iface.flag_multicast_);
  120. } catch (const Exception& ex) {
  121. IFACEMGR_ERROR(SocketConfigError, error_handler,
  122. "Failed to open link-local socket on "
  123. " interface " << iface.getName() << ": "
  124. << ex.what());
  125. return (false);
  126. }
  127. return (true);
  128. }
  129. int
  130. IfaceMgr::openSocket6(Iface& iface, const IOAddress& addr, uint16_t port,
  131. const bool join_multicast) {
  132. IOAddress actual_address = join_multicast ? IOAddress("::") : addr;
  133. SocketInfo info = packet_filter6_->openSocket(iface, actual_address, port,
  134. join_multicast);
  135. iface.addSocket(info);
  136. return (info.sockfd_);
  137. }
  138. } // end of isc::dhcp namespace
  139. } // end of dhcp namespace
  140. #endif