PageRenderTime 45ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/crypto/external/bsd/heimdal/dist/lib/roken/mini_inetd.c

http://www.minix3.org/
C | 199 lines | 98 code | 27 blank | 74 comment | 23 complexity | f03fcf1e3dedce796bbe83c7d7764e1d MD5 | raw file
Possible License(s): MIT, WTFPL, AGPL-1.0, BSD-3-Clause, GPL-3.0, LGPL-2.0, JSON, 0BSD
  1. /* $NetBSD: mini_inetd.c,v 1.1.1.1 2011/04/13 18:15:42 elric Exp $ */
  2. /*
  3. * Copyright (c) 1995 - 2001 Kungliga Tekniska Hรถgskolan
  4. * (Royal Institute of Technology, Stockholm, Sweden).
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. *
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in the
  16. * documentation and/or other materials provided with the distribution.
  17. *
  18. * 3. Neither the name of the Institute nor the names of its contributors
  19. * may be used to endorse or promote products derived from this software
  20. * without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
  23. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25. * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
  26. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32. * SUCH DAMAGE.
  33. */
  34. #include <config.h>
  35. #include <err.h>
  36. #include <krb5/roken.h>
  37. /*
  38. * accept a connection on `s' and pretend it's served by inetd.
  39. */
  40. static void
  41. accept_it (rk_socket_t s, rk_socket_t *ret_socket)
  42. {
  43. rk_socket_t as;
  44. as = accept(s, NULL, NULL);
  45. if(rk_IS_BAD_SOCKET(as))
  46. err (1, "accept");
  47. if (ret_socket) {
  48. *ret_socket = as;
  49. } else {
  50. int fd = socket_to_fd(as, 0);
  51. /* We would use _O_RDONLY for the socket_to_fd() call for
  52. STDIN, but there are instances where we assume that STDIN
  53. is a r/w socket. */
  54. dup2(fd, STDIN_FILENO);
  55. dup2(fd, STDOUT_FILENO);
  56. rk_closesocket(as);
  57. }
  58. }
  59. /**
  60. * Listen on a specified addresses
  61. *
  62. * Listens on the specified addresses for incoming connections. If
  63. * the \a ret_socket parameter is \a NULL, on return STDIN and STDOUT
  64. * will be connected to an accepted socket. If the \a ret_socket
  65. * parameter is non-NULL, the accepted socket will be returned in
  66. * *ret_socket. In the latter case, STDIN and STDOUT will be left
  67. * unmodified.
  68. *
  69. * This function does not return if there is an error or if no
  70. * connection is established.
  71. *
  72. * @param[in] ai Addresses to listen on
  73. * @param[out] ret_socket If non-NULL receives the accepted socket.
  74. *
  75. * @see mini_inetd()
  76. */
  77. ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
  78. mini_inetd_addrinfo (struct addrinfo *ai, rk_socket_t *ret_socket)
  79. {
  80. int ret;
  81. struct addrinfo *a;
  82. int n, nalloc, i;
  83. rk_socket_t *fds;
  84. fd_set orig_read_set, read_set;
  85. rk_socket_t max_fd = (rk_socket_t)-1;
  86. for (nalloc = 0, a = ai; a != NULL; a = a->ai_next)
  87. ++nalloc;
  88. fds = malloc (nalloc * sizeof(*fds));
  89. if (fds == NULL) {
  90. errx (1, "mini_inetd: out of memory");
  91. UNREACHABLE(return);
  92. }
  93. FD_ZERO(&orig_read_set);
  94. for (i = 0, a = ai; a != NULL; a = a->ai_next) {
  95. fds[i] = socket (a->ai_family, a->ai_socktype, a->ai_protocol);
  96. if (rk_IS_BAD_SOCKET(fds[i]))
  97. continue;
  98. socket_set_reuseaddr (fds[i], 1);
  99. socket_set_ipv6only(fds[i], 1);
  100. if (rk_IS_SOCKET_ERROR(bind (fds[i], a->ai_addr, a->ai_addrlen))) {
  101. warn ("bind af = %d", a->ai_family);
  102. rk_closesocket(fds[i]);
  103. fds[i] = rk_INVALID_SOCKET;
  104. continue;
  105. }
  106. if (rk_IS_SOCKET_ERROR(listen (fds[i], SOMAXCONN))) {
  107. warn ("listen af = %d", a->ai_family);
  108. rk_closesocket(fds[i]);
  109. fds[i] = rk_INVALID_SOCKET;
  110. continue;
  111. }
  112. #ifndef NO_LIMIT_FD_SETSIZE
  113. if (fds[i] >= FD_SETSIZE)
  114. errx (1, "fd too large");
  115. #endif
  116. FD_SET(fds[i], &orig_read_set);
  117. max_fd = max(max_fd, fds[i]);
  118. ++i;
  119. }
  120. if (i == 0)
  121. errx (1, "no sockets");
  122. n = i;
  123. do {
  124. read_set = orig_read_set;
  125. ret = select (max_fd + 1, &read_set, NULL, NULL, NULL);
  126. if (rk_IS_SOCKET_ERROR(ret) && rk_SOCK_ERRNO != EINTR)
  127. err (1, "select");
  128. } while (ret <= 0);
  129. for (i = 0; i < n; ++i)
  130. if (FD_ISSET (fds[i], &read_set)) {
  131. accept_it (fds[i], ret_socket);
  132. for (i = 0; i < n; ++i)
  133. rk_closesocket(fds[i]);
  134. free(fds);
  135. return;
  136. }
  137. abort ();
  138. }
  139. /**
  140. * Listen on a specified port
  141. *
  142. * Listens on the specified port for incoming connections. If the \a
  143. * ret_socket parameter is \a NULL, on return STDIN and STDOUT will be
  144. * connected to an accepted socket. If the \a ret_socket parameter is
  145. * non-NULL, the accepted socket will be returned in *ret_socket. In
  146. * the latter case, STDIN and STDOUT will be left unmodified.
  147. *
  148. * This function does not return if there is an error or if no
  149. * connection is established.
  150. *
  151. * @param[in] port Port to listen on
  152. * @param[out] ret_socket If non-NULL receives the accepted socket.
  153. *
  154. * @see mini_inetd_addrinfo()
  155. */
  156. ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
  157. mini_inetd(int port, rk_socket_t * ret_socket)
  158. {
  159. int error;
  160. struct addrinfo *ai, hints;
  161. char portstr[NI_MAXSERV];
  162. memset (&hints, 0, sizeof(hints));
  163. hints.ai_flags = AI_PASSIVE;
  164. hints.ai_socktype = SOCK_STREAM;
  165. hints.ai_family = PF_UNSPEC;
  166. snprintf (portstr, sizeof(portstr), "%d", ntohs(port));
  167. error = getaddrinfo (NULL, portstr, &hints, &ai);
  168. if (error)
  169. errx (1, "getaddrinfo: %s", gai_strerror (error));
  170. mini_inetd_addrinfo(ai, ret_socket);
  171. freeaddrinfo(ai);
  172. }