iface_mgr_bsd.cc 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  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. #if defined(OS_BSD)
  16. #include <dhcp/iface_mgr.h>
  17. #include <exceptions/exceptions.h>
  18. using namespace std;
  19. using namespace isc;
  20. using namespace isc::asiolink;
  21. using namespace isc::dhcp;
  22. namespace isc {
  23. namespace dhcp {
  24. void
  25. IfaceMgr::detectIfaces() {
  26. /// @todo do the actual detection on BSDs. Currently just calling
  27. /// stub implementation.
  28. stubDetectIfaces();
  29. }
  30. bool
  31. IfaceMgr::isDirectResponseSupported() {
  32. return (false);
  33. }
  34. int IfaceMgr::openSocket4(Iface& iface, const IOAddress& addr, uint16_t port,
  35. bool receive_bcast, bool send_bcast) {
  36. struct sockaddr_in addr4;
  37. memset(&addr4, 0, sizeof(sockaddr));
  38. addr4.sin_family = AF_INET;
  39. addr4.sin_port = htons(port);
  40. // If we are to receive broadcast messages we have to bind
  41. // to "ANY" address.
  42. addr4.sin_addr.s_addr = receive_bcast ? INADDR_ANY : htonl(addr);
  43. int sock = socket_handler_->openSocket(AF_INET, SOCK_DGRAM, 0);
  44. if (sock < 0) {
  45. isc_throw(SocketConfigError, "Failed to create UDP6 socket.");
  46. }
  47. if (receive_bcast) {
  48. // Bind to device so as we receive traffic on a specific interface.
  49. if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, iface.getName().c_str(),
  50. iface.getName().length() + 1) < 0) {
  51. close(sock);
  52. isc_throw(SocketConfigError, "Failed to set SO_BINDTODEVICE option"
  53. << "on socket " << sock);
  54. }
  55. }
  56. if (send_bcast) {
  57. // Enable sending to broadcast address.
  58. int flag = 1;
  59. if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &flag, sizeof(flag)) < 0) {
  60. close(sock);
  61. isc_throw(SocketConfigError, "Failed to set SO_BINDTODEVICE option"
  62. << "on socket " << sock);
  63. }
  64. }
  65. if (bind(sock, (struct sockaddr *)&addr4, sizeof(addr4)) < 0) {
  66. close(sock);
  67. isc_throw(SocketConfigError, "Failed to bind socket " << sock << " to " << addr.toText()
  68. << "/port=" << port);
  69. }
  70. // if there is no support for IP_PKTINFO, we are really out of luck
  71. // it will be difficult to undersand, where this packet came from
  72. #if defined(IP_PKTINFO)
  73. int flag = 1;
  74. if (setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &flag, sizeof(flag)) != 0) {
  75. close(sock);
  76. isc_throw(SocketConfigError, "setsockopt: IP_PKTINFO: failed.");
  77. }
  78. #endif
  79. SocketInfo info(sock, addr, port);
  80. iface.addSocket(info);
  81. return (sock);
  82. }
  83. bool
  84. IfaceMgr::send(const Pkt4Ptr& pkt)
  85. {
  86. Iface* iface = getIface(pkt->getIface());
  87. if (!iface) {
  88. isc_throw(BadValue, "Unable to send Pkt4. Invalid interface ("
  89. << pkt->getIface() << ") specified.");
  90. }
  91. memset(&control_buf_[0], 0, control_buf_len_);
  92. // Set the target address we're sending to.
  93. sockaddr_in to;
  94. memset(&to, 0, sizeof(to));
  95. to.sin_family = AF_INET;
  96. to.sin_port = htons(pkt->getRemotePort());
  97. to.sin_addr.s_addr = htonl(pkt->getRemoteAddr());
  98. struct msghdr m;
  99. // Initialize our message header structure.
  100. memset(&m, 0, sizeof(m));
  101. m.msg_name = &to;
  102. m.msg_namelen = sizeof(to);
  103. // Set the data buffer we're sending. (Using this wacky
  104. // "scatter-gather" stuff... we only have a single chunk
  105. // of data to send, so we declare a single vector entry.)
  106. struct iovec v;
  107. memset(&v, 0, sizeof(v));
  108. // iov_base field is of void * type. We use it for packet
  109. // transmission, so this buffer will not be modified.
  110. v.iov_base = const_cast<void *>(pkt->getBuffer().getData());
  111. v.iov_len = pkt->getBuffer().getLength();
  112. m.msg_iov = &v;
  113. m.msg_iovlen = 1;
  114. // call OS-specific routines (like setting interface index)
  115. os_send4(m, control_buf_, control_buf_len_, pkt);
  116. pkt->updateTimestamp();
  117. int result = sendmsg(getSocket(*pkt), &m, 0);
  118. if (result < 0) {
  119. isc_throw(SocketWriteError, "pkt4 send failed");
  120. }
  121. return (result);
  122. }
  123. void IfaceMgr::os_send4(struct msghdr& /*m*/,
  124. boost::scoped_array<char>& /*control_buf*/,
  125. size_t /*control_buf_len*/,
  126. const Pkt4Ptr& /*pkt*/) {
  127. // @todo: Are there any specific actions required before sending IPv4 packet
  128. // on BSDs? See iface_mgr_linux.cc for working Linux implementation.
  129. }
  130. bool IfaceMgr::os_receive4(struct msghdr& /*m*/, Pkt4Ptr& /*pkt*/) {
  131. // @todo: Are there any specific actions required before receiving IPv4 packet
  132. // on BSDs? See iface_mgr_linux.cc for working Linux implementation.
  133. return (true); // pretend that we have everything set up for reception.
  134. }
  135. } // end of isc::dhcp namespace
  136. } // end of dhcp namespace
  137. #endif