sockcreator.cc 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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 <unistd.h>
  17. #include <cerrno>
  18. #include <string.h>
  19. #include <sys/types.h>
  20. #include <sys/socket.h>
  21. #include <netinet/in.h>
  22. using namespace isc::util::io;
  23. namespace isc {
  24. namespace socket_creator {
  25. int
  26. get_sock(const int type, struct sockaddr *bind_addr, const socklen_t addr_len)
  27. {
  28. int sock(socket(bind_addr->sa_family, type, 0));
  29. if (sock == -1) {
  30. return -1;
  31. }
  32. const int on(1);
  33. if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
  34. return -2; // This is part of the binding process, so it's a bind error
  35. }
  36. if (bind_addr->sa_family == AF_INET6 &&
  37. setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) == -1) {
  38. return -2; // This is part of the binding process, so it's a bind error
  39. }
  40. if (bind(sock, bind_addr, addr_len) == -1) {
  41. return -2;
  42. }
  43. return sock;
  44. }
  45. // These are macros so they can exit the function
  46. #define READ(WHERE, HOW_MANY) do { \
  47. size_t how_many = (HOW_MANY); \
  48. if (read_data(input_fd, (WHERE), how_many) < how_many) { \
  49. return 1; \
  50. } \
  51. } while (0)
  52. #define WRITE(WHAT, HOW_MANY) do { \
  53. if (!write_data(output_fd, (WHAT), (HOW_MANY))) { \
  54. return 2; \
  55. } \
  56. } while (0)
  57. #define DEFAULT \
  58. default: /* Unrecognized part of protocol */ \
  59. WRITE("FI", 2); \
  60. return 3;
  61. int
  62. run(const int input_fd, const int output_fd, const get_sock_t get_sock,
  63. const send_fd_t send_fd)
  64. {
  65. for (;;) {
  66. // Read the command
  67. char command;
  68. READ(&command, 1);
  69. switch (command) {
  70. case 'T': // The "terminate" command
  71. return 0;
  72. case 'S': { // Create a socket
  73. // Read what type of socket they want
  74. char type[2];
  75. READ(type, 2);
  76. // Read the address they ask for
  77. struct sockaddr *addr(NULL);
  78. size_t addr_len(0);
  79. struct sockaddr_in addr_in;
  80. struct sockaddr_in6 addr_in6;
  81. switch (type[1]) { // The address family
  82. /*
  83. * Here are some casts. They are required by C++ and
  84. * the low-level interface (they are implicit in C).
  85. */
  86. case '4':
  87. addr = static_cast<struct sockaddr *>(
  88. static_cast<void *>(&addr_in));
  89. addr_len = sizeof addr_in;
  90. memset(&addr_in, 0, sizeof addr_in);
  91. addr_in.sin_family = AF_INET;
  92. READ(static_cast<char *>(static_cast<void *>(
  93. &addr_in.sin_port)), 2);
  94. READ(static_cast<char *>(static_cast<void *>(
  95. &addr_in.sin_addr.s_addr)), 4);
  96. break;
  97. case '6':
  98. addr = static_cast<struct sockaddr *>(
  99. static_cast<void *>(&addr_in6));
  100. addr_len = sizeof addr_in6;
  101. memset(&addr_in6, 0, sizeof addr_in6);
  102. addr_in6.sin6_family = AF_INET6;
  103. READ(static_cast<char *>(static_cast<void *>(
  104. &addr_in6.sin6_port)), 2);
  105. READ(static_cast<char *>(static_cast<void *>(
  106. &addr_in6.sin6_addr.s6_addr)), 16);
  107. break;
  108. DEFAULT
  109. }
  110. int sock_type;
  111. switch (type[0]) { // Translate the type
  112. case 'T':
  113. sock_type = SOCK_STREAM;
  114. break;
  115. case 'U':
  116. sock_type = SOCK_DGRAM;
  117. break;
  118. DEFAULT
  119. }
  120. int result(get_sock(sock_type, addr, addr_len));
  121. if (result >= 0) { // We got the socket
  122. WRITE("S", 1);
  123. // FIXME: Check the output and write a test for it
  124. send_fd(output_fd, result);
  125. // Don't leak the socket
  126. close(result);
  127. } else {
  128. WRITE("E", 1);
  129. switch (result) {
  130. case -1:
  131. WRITE("S", 1);
  132. break;
  133. case -2:
  134. WRITE("B", 1);
  135. break;
  136. default:
  137. return 4;
  138. }
  139. int error(errno);
  140. WRITE(static_cast<char *>(static_cast<void *>(&error)),
  141. sizeof error);
  142. }
  143. break;
  144. }
  145. DEFAULT
  146. }
  147. }
  148. }
  149. } // End of the namespaces
  150. }