s2n_socket.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. /*
  2. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License").
  5. * You may not use this file except in compliance with the License.
  6. * A copy of the License is located at
  7. *
  8. * http://aws.amazon.com/apache2.0
  9. *
  10. * or in the "license" file accompanying this file. This file is distributed
  11. * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  12. * express or implied. See the License for the specific language governing
  13. * permissions and limitations under the License.
  14. */
  15. #include "utils/s2n_socket.h"
  16. #include <netinet/in.h>
  17. #include <netinet/tcp.h>
  18. #include <sys/socket.h>
  19. #include <unistd.h>
  20. #include "tls/s2n_connection.h"
  21. #include "utils/s2n_safety.h"
  22. #if TCP_CORK
  23. #define S2N_CORK TCP_CORK
  24. #define S2N_CORK_ON 1
  25. #define S2N_CORK_OFF 0
  26. #elif TCP_NOPUSH
  27. #define S2N_CORK TCP_NOPUSH
  28. #define S2N_CORK_ON 1
  29. #define S2N_CORK_OFF 0
  30. #elif TCP_NODELAY
  31. #define S2N_CORK TCP_NODELAY
  32. #define S2N_CORK_ON 0
  33. #define S2N_CORK_OFF 1
  34. #endif
  35. int s2n_socket_quickack(struct s2n_connection *conn)
  36. {
  37. #ifdef TCP_QUICKACK
  38. POSIX_ENSURE_REF(conn);
  39. if (!conn->managed_recv_io) {
  40. return 0;
  41. }
  42. struct s2n_socket_read_io_context *r_io_ctx = (struct s2n_socket_read_io_context *) conn->recv_io_context;
  43. POSIX_ENSURE_REF(r_io_ctx);
  44. if (r_io_ctx->tcp_quickack_set) {
  45. return 0;
  46. }
  47. /* Ignore the return value, if it fails it fails */
  48. int optval = 1;
  49. if (setsockopt(r_io_ctx->fd, IPPROTO_TCP, TCP_QUICKACK, &optval, sizeof(optval)) == 0) {
  50. r_io_ctx->tcp_quickack_set = 1;
  51. }
  52. #endif
  53. return 0;
  54. }
  55. int s2n_socket_write_snapshot(struct s2n_connection *conn)
  56. {
  57. #ifdef S2N_CORK
  58. socklen_t corklen = sizeof(int);
  59. POSIX_ENSURE_REF(conn);
  60. struct s2n_socket_write_io_context *w_io_ctx = (struct s2n_socket_write_io_context *) conn->send_io_context;
  61. POSIX_ENSURE_REF(w_io_ctx);
  62. getsockopt(w_io_ctx->fd, IPPROTO_TCP, S2N_CORK, &w_io_ctx->original_cork_val, &corklen);
  63. POSIX_ENSURE_EQ(corklen, sizeof(int));
  64. w_io_ctx->original_cork_is_set = 1;
  65. #endif
  66. return 0;
  67. }
  68. int s2n_socket_read_snapshot(struct s2n_connection *conn)
  69. {
  70. #ifdef SO_RCVLOWAT
  71. socklen_t watlen = sizeof(int);
  72. POSIX_ENSURE_REF(conn);
  73. struct s2n_socket_read_io_context *r_io_ctx = (struct s2n_socket_read_io_context *) conn->recv_io_context;
  74. POSIX_ENSURE_REF(r_io_ctx);
  75. getsockopt(r_io_ctx->fd, SOL_SOCKET, SO_RCVLOWAT, &r_io_ctx->original_rcvlowat_val, &watlen);
  76. POSIX_ENSURE_EQ(watlen, sizeof(int));
  77. r_io_ctx->original_rcvlowat_is_set = 1;
  78. #endif
  79. return 0;
  80. }
  81. int s2n_socket_write_restore(struct s2n_connection *conn)
  82. {
  83. #ifdef S2N_CORK
  84. POSIX_ENSURE_REF(conn);
  85. struct s2n_socket_write_io_context *w_io_ctx = (struct s2n_socket_write_io_context *) conn->send_io_context;
  86. POSIX_ENSURE_REF(w_io_ctx);
  87. if (!w_io_ctx->original_cork_is_set) {
  88. return 0;
  89. }
  90. setsockopt(w_io_ctx->fd, IPPROTO_TCP, S2N_CORK, &w_io_ctx->original_cork_val, sizeof(w_io_ctx->original_cork_val));
  91. w_io_ctx->original_cork_is_set = 0;
  92. #endif
  93. return 0;
  94. }
  95. int s2n_socket_read_restore(struct s2n_connection *conn)
  96. {
  97. #ifdef SO_RCVLOWAT
  98. POSIX_ENSURE_REF(conn);
  99. struct s2n_socket_read_io_context *r_io_ctx = (struct s2n_socket_read_io_context *) conn->recv_io_context;
  100. POSIX_ENSURE_REF(r_io_ctx);
  101. if (!r_io_ctx->original_rcvlowat_is_set) {
  102. return 0;
  103. }
  104. setsockopt(r_io_ctx->fd, SOL_SOCKET, SO_RCVLOWAT, &r_io_ctx->original_rcvlowat_val, sizeof(r_io_ctx->original_rcvlowat_val));
  105. r_io_ctx->original_rcvlowat_is_set = 0;
  106. #endif
  107. return 0;
  108. }
  109. int s2n_socket_was_corked(struct s2n_connection *conn)
  110. {
  111. POSIX_ENSURE_REF(conn);
  112. /* If we're not using custom I/O and a send fd has not been set yet, return false*/
  113. if (!conn->managed_send_io || !conn->send) {
  114. return 0;
  115. }
  116. struct s2n_socket_write_io_context *io_ctx = (struct s2n_socket_write_io_context *) conn->send_io_context;
  117. POSIX_ENSURE_REF(io_ctx);
  118. return io_ctx->original_cork_val;
  119. }
  120. int s2n_socket_write_cork(struct s2n_connection *conn)
  121. {
  122. #ifdef S2N_CORK
  123. POSIX_ENSURE_REF(conn);
  124. int optval = S2N_CORK_ON;
  125. struct s2n_socket_write_io_context *w_io_ctx = (struct s2n_socket_write_io_context *) conn->send_io_context;
  126. POSIX_ENSURE_REF(w_io_ctx);
  127. /* Ignore the return value, if it fails it fails */
  128. setsockopt(w_io_ctx->fd, IPPROTO_TCP, S2N_CORK, &optval, sizeof(optval));
  129. #endif
  130. return 0;
  131. }
  132. int s2n_socket_write_uncork(struct s2n_connection *conn)
  133. {
  134. #ifdef S2N_CORK
  135. POSIX_ENSURE_REF(conn);
  136. int optval = S2N_CORK_OFF;
  137. struct s2n_socket_write_io_context *w_io_ctx = (struct s2n_socket_write_io_context *) conn->send_io_context;
  138. POSIX_ENSURE_REF(w_io_ctx);
  139. /* Ignore the return value, if it fails it fails */
  140. setsockopt(w_io_ctx->fd, IPPROTO_TCP, S2N_CORK, &optval, sizeof(optval));
  141. #endif
  142. return 0;
  143. }
  144. int s2n_socket_set_read_size(struct s2n_connection *conn, int size)
  145. {
  146. #ifdef SO_RCVLOWAT
  147. POSIX_ENSURE_REF(conn);
  148. struct s2n_socket_read_io_context *r_io_ctx = (struct s2n_socket_read_io_context *) conn->recv_io_context;
  149. POSIX_ENSURE_REF(r_io_ctx);
  150. setsockopt(r_io_ctx->fd, SOL_SOCKET, SO_RCVLOWAT, &size, sizeof(size));
  151. #endif
  152. return 0;
  153. }
  154. int s2n_socket_read(void *io_context, uint8_t *buf, uint32_t len)
  155. {
  156. POSIX_ENSURE_REF(io_context);
  157. POSIX_ENSURE_REF(buf);
  158. int rfd = ((struct s2n_socket_read_io_context *) io_context)->fd;
  159. if (rfd < 0) {
  160. errno = EBADF;
  161. POSIX_BAIL(S2N_ERR_BAD_FD);
  162. }
  163. /* Clear the quickack flag so we know to reset it */
  164. ((struct s2n_socket_read_io_context *) io_context)->tcp_quickack_set = 0;
  165. /* On success, the number of bytes read is returned. On failure, -1 is
  166. * returned and errno is set appropriately. */
  167. ssize_t result = read(rfd, buf, len);
  168. POSIX_ENSURE_INCLUSIVE_RANGE(INT_MIN, result, INT_MAX);
  169. return result;
  170. }
  171. int s2n_socket_write(void *io_context, const uint8_t *buf, uint32_t len)
  172. {
  173. POSIX_ENSURE_REF(io_context);
  174. POSIX_ENSURE_REF(buf);
  175. int wfd = ((struct s2n_socket_write_io_context *) io_context)->fd;
  176. if (wfd < 0) {
  177. errno = EBADF;
  178. POSIX_BAIL(S2N_ERR_BAD_FD);
  179. }
  180. /* On success, the number of bytes written is returned. On failure, -1 is
  181. * returned and errno is set appropriately. */
  182. ssize_t result = write(wfd, buf, len);
  183. POSIX_ENSURE_INCLUSIVE_RANGE(INT_MIN, result, INT_MAX);
  184. return result;
  185. }
  186. int s2n_socket_is_ipv6(int fd, uint8_t *ipv6)
  187. {
  188. POSIX_ENSURE_REF(ipv6);
  189. socklen_t len;
  190. struct sockaddr_storage addr;
  191. len = sizeof(addr);
  192. POSIX_GUARD(getpeername(fd, (struct sockaddr *) &addr, &len));
  193. *ipv6 = 0;
  194. if (AF_INET6 == addr.ss_family) {
  195. *ipv6 = 1;
  196. }
  197. return 0;
  198. }