sockopt.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. /* Licensed to the Apache Software Foundation (ASF) under one or more
  2. * contributor license agreements. See the NOTICE file distributed with
  3. * this work for additional information regarding copyright ownership.
  4. * The ASF licenses this file to You under the Apache License, Version 2.0
  5. * (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "apr_arch_networkio.h"
  17. #include "apr_network_io.h"
  18. #include "apr_general.h"
  19. #include "apr_strings.h"
  20. #include <string.h>
  21. apr_status_t soblock(SOCKET sd)
  22. {
  23. u_long zero = 0;
  24. if (ioctlsocket(sd, FIONBIO, &zero) == SOCKET_ERROR) {
  25. return apr_get_netos_error();
  26. }
  27. return APR_SUCCESS;
  28. }
  29. apr_status_t sononblock(SOCKET sd)
  30. {
  31. u_long one = 1;
  32. if (ioctlsocket(sd, FIONBIO, &one) == SOCKET_ERROR) {
  33. return apr_get_netos_error();
  34. }
  35. return APR_SUCCESS;
  36. }
  37. APR_DECLARE(apr_status_t) apr_socket_timeout_set(apr_socket_t *sock, apr_interval_time_t t)
  38. {
  39. apr_status_t stat;
  40. if (t == 0) {
  41. /* Set the socket non-blocking if it was previously blocking */
  42. if (sock->timeout != 0) {
  43. if ((stat = sononblock(sock->socketdes)) != APR_SUCCESS)
  44. return stat;
  45. }
  46. }
  47. else if (t > 0) {
  48. /* Set the socket to blocking if it was previously non-blocking */
  49. if (sock->timeout == 0) {
  50. if ((stat = soblock(sock->socketdes)) != APR_SUCCESS)
  51. return stat;
  52. }
  53. /* Reset socket timeouts if the new timeout differs from the old timeout */
  54. if (sock->timeout != t)
  55. {
  56. /* Win32 timeouts are in msec, represented as int */
  57. sock->timeout_ms = (int)apr_time_as_msec(t);
  58. setsockopt(sock->socketdes, SOL_SOCKET, SO_RCVTIMEO,
  59. (char *) &sock->timeout_ms,
  60. sizeof(sock->timeout_ms));
  61. setsockopt(sock->socketdes, SOL_SOCKET, SO_SNDTIMEO,
  62. (char *) &sock->timeout_ms,
  63. sizeof(sock->timeout_ms));
  64. }
  65. }
  66. else if (t < 0) {
  67. int zero = 0;
  68. /* Set the socket to blocking with infinite timeouts */
  69. if ((stat = soblock(sock->socketdes)) != APR_SUCCESS)
  70. return stat;
  71. setsockopt(sock->socketdes, SOL_SOCKET, SO_RCVTIMEO,
  72. (char *) &zero, sizeof(zero));
  73. setsockopt(sock->socketdes, SOL_SOCKET, SO_SNDTIMEO,
  74. (char *) &zero, sizeof(zero));
  75. }
  76. sock->timeout = t;
  77. return APR_SUCCESS;
  78. }
  79. APR_DECLARE(apr_status_t) apr_socket_opt_set(apr_socket_t *sock,
  80. apr_int32_t opt, apr_int32_t on)
  81. {
  82. int one;
  83. apr_status_t stat;
  84. one = on ? 1 : 0;
  85. switch (opt) {
  86. case APR_SO_KEEPALIVE:
  87. if (on != apr_is_option_set(sock, APR_SO_KEEPALIVE)) {
  88. if (setsockopt(sock->socketdes, SOL_SOCKET, SO_KEEPALIVE,
  89. (void *)&one, sizeof(int)) == -1) {
  90. return apr_get_netos_error();
  91. }
  92. apr_set_option(sock, APR_SO_KEEPALIVE, on);
  93. }
  94. break;
  95. case APR_SO_DEBUG:
  96. if (on != apr_is_option_set(sock, APR_SO_DEBUG)) {
  97. if (setsockopt(sock->socketdes, SOL_SOCKET, SO_DEBUG,
  98. (void *)&one, sizeof(int)) == -1) {
  99. return apr_get_netos_error();
  100. }
  101. apr_set_option(sock, APR_SO_DEBUG, on);
  102. }
  103. break;
  104. case APR_SO_SNDBUF:
  105. if (setsockopt(sock->socketdes, SOL_SOCKET, SO_SNDBUF,
  106. (void *)&on, sizeof(int)) == -1) {
  107. return apr_get_netos_error();
  108. }
  109. break;
  110. case APR_SO_RCVBUF:
  111. if (setsockopt(sock->socketdes, SOL_SOCKET, SO_RCVBUF,
  112. (void *)&on, sizeof(int)) == -1) {
  113. return apr_get_netos_error();
  114. }
  115. break;
  116. case APR_SO_REUSEADDR:
  117. if (on != apr_is_option_set(sock, APR_SO_REUSEADDR)) {
  118. if (setsockopt(sock->socketdes, SOL_SOCKET, SO_REUSEADDR,
  119. (void *)&one, sizeof(int)) == -1) {
  120. return apr_get_netos_error();
  121. }
  122. apr_set_option(sock, APR_SO_REUSEADDR, on);
  123. }
  124. break;
  125. case APR_SO_NONBLOCK:
  126. if (apr_is_option_set(sock, APR_SO_NONBLOCK) != on) {
  127. if (on) {
  128. if ((stat = sononblock(sock->socketdes)) != APR_SUCCESS)
  129. return stat;
  130. }
  131. else {
  132. if ((stat = soblock(sock->socketdes)) != APR_SUCCESS)
  133. return stat;
  134. }
  135. apr_set_option(sock, APR_SO_NONBLOCK, on);
  136. }
  137. break;
  138. case APR_SO_LINGER:
  139. {
  140. if (apr_is_option_set(sock, APR_SO_LINGER) != on) {
  141. struct linger li;
  142. li.l_onoff = on;
  143. li.l_linger = APR_MAX_SECS_TO_LINGER;
  144. if (setsockopt(sock->socketdes, SOL_SOCKET, SO_LINGER,
  145. (char *) &li, sizeof(struct linger)) == -1) {
  146. return apr_get_netos_error();
  147. }
  148. apr_set_option(sock, APR_SO_LINGER, on);
  149. }
  150. break;
  151. }
  152. case APR_TCP_DEFER_ACCEPT:
  153. #if defined(TCP_DEFER_ACCEPT)
  154. if (apr_is_option_set(sock, APR_TCP_DEFER_ACCEPT) != on) {
  155. int optlevel = IPPROTO_TCP;
  156. int optname = TCP_DEFER_ACCEPT;
  157. if (setsockopt(sock->socketdes, optlevel, optname,
  158. (void *)&on, sizeof(int)) == -1) {
  159. return errno;
  160. }
  161. apr_set_option(sock, APR_TCP_DEFER_ACCEPT, on);
  162. }
  163. #else
  164. return APR_ENOTIMPL;
  165. #endif
  166. case APR_TCP_NODELAY:
  167. if (apr_is_option_set(sock, APR_TCP_NODELAY) != on) {
  168. int optlevel = IPPROTO_TCP;
  169. int optname = TCP_NODELAY;
  170. #if APR_HAVE_SCTP
  171. if (sock->protocol == IPPROTO_SCTP) {
  172. optlevel = IPPROTO_SCTP;
  173. optname = SCTP_NODELAY;
  174. }
  175. #endif
  176. if (setsockopt(sock->socketdes, optlevel, optname,
  177. (void *)&on, sizeof(int)) == -1) {
  178. return apr_get_netos_error();
  179. }
  180. apr_set_option(sock, APR_TCP_NODELAY, on);
  181. }
  182. break;
  183. case APR_IPV6_V6ONLY:
  184. #if APR_HAVE_IPV6 && defined(IPV6_V6ONLY)
  185. /* we don't know the initial setting of this option,
  186. * so don't check sock->options since that optimization
  187. * won't work
  188. */
  189. if (setsockopt(sock->socketdes, IPPROTO_IPV6, IPV6_V6ONLY,
  190. (void *)&on, sizeof(int)) == -1) {
  191. return apr_get_netos_error();
  192. }
  193. apr_set_option(sock, APR_IPV6_V6ONLY, on);
  194. #else
  195. return APR_ENOTIMPL;
  196. #endif
  197. break;
  198. default:
  199. return APR_EINVAL;
  200. break;
  201. }
  202. return APR_SUCCESS;
  203. }
  204. APR_DECLARE(apr_status_t) apr_socket_timeout_get(apr_socket_t *sock, apr_interval_time_t *t)
  205. {
  206. *t = sock->timeout;
  207. return APR_SUCCESS;
  208. }
  209. APR_DECLARE(apr_status_t) apr_socket_opt_get(apr_socket_t *sock,
  210. apr_int32_t opt, apr_int32_t *on)
  211. {
  212. switch (opt) {
  213. case APR_SO_DISCONNECTED:
  214. *on = sock->disconnected;
  215. break;
  216. case APR_SO_KEEPALIVE:
  217. case APR_SO_DEBUG:
  218. case APR_SO_REUSEADDR:
  219. case APR_SO_NONBLOCK:
  220. case APR_SO_LINGER:
  221. default:
  222. *on = apr_is_option_set(sock, opt);
  223. break;
  224. }
  225. return APR_SUCCESS;
  226. }
  227. APR_DECLARE(int) apr_socket_fd_get(apr_socket_t *sock)
  228. {
  229. if (sock) {
  230. return sock->socketdes;
  231. } else {
  232. return 0;
  233. }
  234. }
  235. APR_DECLARE(apr_status_t) apr_socket_atmark(apr_socket_t *sock, int *atmark)
  236. {
  237. u_long oobmark;
  238. if (ioctlsocket(sock->socketdes, SIOCATMARK, (void*) &oobmark) < 0)
  239. return apr_get_netos_error();
  240. *atmark = (oobmark != 0);
  241. return APR_SUCCESS;
  242. }
  243. APR_DECLARE(apr_status_t) apr_gethostname(char *buf, int len,
  244. apr_pool_t *cont)
  245. {
  246. if (gethostname(buf, len) == -1) {
  247. buf[0] = '\0';
  248. return apr_get_netos_error();
  249. }
  250. else if (!memchr(buf, '\0', len)) { /* buffer too small */
  251. buf[0] = '\0';
  252. return APR_ENAMETOOLONG;
  253. }
  254. return APR_SUCCESS;
  255. }