sockcreator.cc 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. // Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include "sockcreator.h"
  15. #include <util/io/fd.h>
  16. #include <util/io/sockaddr_util.h>
  17. #include <cerrno>
  18. #include <string.h>
  19. #include <unistd.h>
  20. #include <sys/types.h>
  21. #include <sys/socket.h>
  22. #include <netinet/in.h>
  23. using namespace isc::util::io;
  24. using namespace isc::util::io::internal;
  25. using namespace isc::socket_creator;
  26. namespace {
  27. // Simple wrappers for read_data/write_data that throw an exception on error.
  28. void
  29. readMessage(const int fd, void* where, const size_t length) {
  30. if (read_data(fd, where, length) < length) {
  31. isc_throw(ReadError, "Error reading from socket creator client");
  32. }
  33. }
  34. void
  35. writeMessage(const int fd, const void* what, const size_t length) {
  36. if (!write_data(fd, what, length)) {
  37. isc_throw(WriteError, "Error writing to socket creator client");
  38. }
  39. }
  40. // Exit on a protocol error after informing the client of the problem.
  41. void
  42. protocolError(const int fd, const char reason = 'I') {
  43. // Tell client we have a problem
  44. char message[2];
  45. message[0] = 'F';
  46. message[1] = reason;
  47. writeMessage(fd, message, sizeof(message));
  48. // ... and exit
  49. isc_throw(ProtocolError, "Fatal error, reason: " << reason);
  50. }
  51. // Return appropriate socket type constant for the socket type requested.
  52. // The output_fd argument is required to report a protocol error.
  53. int
  54. getSocketType(const char type_code, const int output_fd) {
  55. int socket_type = 0;
  56. switch (type_code) {
  57. case 'T':
  58. socket_type = SOCK_STREAM;
  59. break;
  60. case 'U':
  61. socket_type = SOCK_DGRAM;
  62. break;
  63. default:
  64. protocolError(output_fd); // Does not return
  65. }
  66. return (socket_type);
  67. }
  68. // Convert return status from getSock() to a character to be sent back to
  69. // the caller.
  70. char
  71. getErrorCode(const int status) {
  72. char error_code = ' ';
  73. switch (status) {
  74. case -1:
  75. error_code = 'S';
  76. break;
  77. case -2:
  78. error_code = 'B';
  79. break;
  80. default:
  81. isc_throw(InternalError, "Error creating socket");
  82. }
  83. return (error_code);
  84. }
  85. // Handle the request from the client.
  86. //
  87. // Reads the type and family of socket required, creates the socket and returns
  88. // it to the client.
  89. //
  90. // The arguments passed (and the exceptions thrown) are the same as those for
  91. // run().
  92. void
  93. handleRequest(const int input_fd, const int output_fd,
  94. const get_sock_t get_sock, const send_fd_t send_fd_fun,
  95. const close_t close_fun)
  96. {
  97. // Read the message from the client
  98. char type[2];
  99. readMessage(input_fd, type, sizeof(type));
  100. // Decide what type of socket is being asked for
  101. const int sock_type = getSocketType(type[0], output_fd);
  102. // Read the address they ask for depending on what address family was
  103. // specified.
  104. sockaddr* addr = NULL;
  105. size_t addr_len = 0;
  106. sockaddr_in addr_in;
  107. sockaddr_in6 addr_in6;
  108. switch (type[1]) { // The address family
  109. // The casting to apparently incompatible types is required by the
  110. // C low-level interface.
  111. case '4':
  112. addr = convertSockAddr(&addr_in);
  113. addr_len = sizeof(addr_in);
  114. memset(&addr_in, 0, sizeof(addr_in));
  115. addr_in.sin_family = AF_INET;
  116. readMessage(input_fd, &addr_in.sin_port, sizeof(addr_in.sin_port));
  117. readMessage(input_fd, &addr_in.sin_addr.s_addr,
  118. sizeof(addr_in.sin_addr.s_addr));
  119. break;
  120. case '6':
  121. addr = convertSockAddr(&addr_in6);
  122. addr_len = sizeof(addr_in6);
  123. memset(&addr_in6, 0, sizeof(addr_in6));
  124. addr_in6.sin6_family = AF_INET6;
  125. readMessage(input_fd, &addr_in6.sin6_port,
  126. sizeof(addr_in6.sin6_port));
  127. readMessage(input_fd, &addr_in6.sin6_addr.s6_addr,
  128. sizeof(addr_in6.sin6_addr.s6_addr));
  129. break;
  130. default:
  131. protocolError(output_fd);
  132. }
  133. // Obtain the socket
  134. const int result = get_sock(sock_type, addr, addr_len, close_fun);
  135. if (result >= 0) {
  136. // Got the socket, send it to the client.
  137. writeMessage(output_fd, "S", 1);
  138. if (send_fd_fun(output_fd, result) != 0) {
  139. // Error. Close the socket (ignore any error from that operation)
  140. // and abort.
  141. close_fun(result);
  142. isc_throw(InternalError, "Error sending descriptor");
  143. }
  144. // Successfully sent the socket, so free up resources we still hold
  145. // for it.
  146. if (close_fun(result) == -1) {
  147. isc_throw(InternalError, "Error closing socket");
  148. }
  149. } else {
  150. // Error. Tell the client.
  151. char error_message[2];
  152. error_message[0] = 'E';
  153. error_message[1] = getErrorCode(result);
  154. writeMessage(output_fd, error_message, sizeof(error_message));
  155. // ...and append the reason code to the error message
  156. const int error_number = errno;
  157. writeMessage(output_fd, &error_number, sizeof(error_number));
  158. }
  159. }
  160. // Sets the MTU related flags for IPv6 UDP sockets.
  161. // It is borrowed from bind-9 lib/isc/unix/socket.c and modified
  162. // to compile here.
  163. //
  164. // The function returns -2 if it fails or the socket file descriptor
  165. // on success (for convenience, so the result can be just returned).
  166. int
  167. mtu(int fd) {
  168. #ifdef IPV6_USE_MIN_MTU /* RFC 3542, not too common yet*/
  169. const int on(1);
  170. // use minimum MTU
  171. if (setsockopt(fd, IPPROTO_IPV6, IPV6_USE_MIN_MTU, &on, sizeof(on)) < 0) {
  172. return (-2);
  173. }
  174. #else // Try the following as fallback
  175. #ifdef IPV6_MTU
  176. // Use minimum MTU on systems that don't have the IPV6_USE_MIN_MTU
  177. const int mtu = 1280;
  178. if (setsockopt(fd, IPPROTO_IPV6, IPV6_MTU, &mtu, sizeof(mtu)) < 0) {
  179. return (-2);
  180. }
  181. #endif
  182. #if defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DONT)
  183. // Turn off Path MTU discovery on IPv6/UDP sockets.
  184. const int action = IPV6_PMTUDISC_DONT;
  185. if (setsockopt(fd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &action,
  186. sizeof(action)) < 0) {
  187. return (-2);
  188. }
  189. #endif
  190. #endif
  191. return (fd);
  192. }
  193. // This one closes the socket if result is negative. Used not to leak socket
  194. // on error.
  195. int maybeClose(const int result, const int socket, const close_t close_fun) {
  196. if (result < 0) {
  197. if (close_fun(socket) == -1) {
  198. isc_throw(InternalError, "Error closing socket");
  199. }
  200. }
  201. return (result);
  202. }
  203. } // Anonymous namespace
  204. namespace isc {
  205. namespace socket_creator {
  206. // Get the socket and bind to it.
  207. int
  208. getSock(const int type, struct sockaddr* bind_addr, const socklen_t addr_len,
  209. const close_t close_fun) {
  210. const int sock = socket(bind_addr->sa_family, type, 0);
  211. if (sock == -1) {
  212. return (-1);
  213. }
  214. const int on = 1;
  215. if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
  216. // This is part of the binding process, so it's a bind error
  217. return (maybeClose(-2, sock, close_fun));
  218. }
  219. if (bind_addr->sa_family == AF_INET6 &&
  220. setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) == -1) {
  221. // This is part of the binding process, so it's a bind error
  222. return (maybeClose(-2, sock, close_fun));
  223. }
  224. if (bind(sock, bind_addr, addr_len) == -1) {
  225. return (maybeClose(-2, sock, close_fun));
  226. }
  227. if (type == SOCK_DGRAM && bind_addr->sa_family == AF_INET6) {
  228. // Set some MTU flags on IPv6 UDP sockets.
  229. return (maybeClose(mtu(sock), sock, close_fun));
  230. }
  231. return (sock);
  232. }
  233. // Main run loop.
  234. void
  235. run(const int input_fd, const int output_fd, get_sock_t get_sock,
  236. send_fd_t send_fd_fun, close_t close_fun)
  237. {
  238. for (;;) {
  239. char command;
  240. readMessage(input_fd, &command, sizeof(command));
  241. switch (command) {
  242. case 'S': // The "get socket" command
  243. handleRequest(input_fd, output_fd, get_sock,
  244. send_fd_fun, close_fun);
  245. break;
  246. case 'T': // The "terminate" command
  247. return;
  248. default: // Don't recognise anything else
  249. protocolError(output_fd);
  250. }
  251. }
  252. }
  253. } // End of the namespaces
  254. }