|  | @@ -128,14 +128,9 @@ SecureZeroMemory(PVOID ptr, SIZE_T cnt)
 | 
	
		
			
				|  |  |  #include "common/util.h"
 | 
	
		
			
				|  |  |  #include "lib/container/smartlist.h"
 | 
	
		
			
				|  |  |  #include "lib/wallclock/tm_cvt.h"
 | 
	
		
			
				|  |  | -#include "common/address.h"
 | 
	
		
			
				|  |  | +#include "lib/net/address.h"
 | 
	
		
			
				|  |  |  #include "common/sandbox.h"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/* When set_max_file_descriptors() is called, update this with the max file
 | 
	
		
			
				|  |  | - * descriptor value so we can use it to check the limit when opening a new
 | 
	
		
			
				|  |  | - * socket. Default value is what Debian sets as the default hard limit. */
 | 
	
		
			
				|  |  | -static int max_sockets = 1024;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  /** As open(path, flags, mode), but return an fd with the close-on-exec mode
 | 
	
		
			
				|  |  |   * set. */
 | 
	
		
			
				|  |  |  int
 | 
	
	
		
			
				|  | @@ -707,618 +702,6 @@ tor_lockfile_unlock(tor_lockfile_t *lockfile)
 | 
	
		
			
				|  |  |    tor_free(lockfile);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#undef DEBUG_SOCKET_COUNTING
 | 
	
		
			
				|  |  | -#ifdef DEBUG_SOCKET_COUNTING
 | 
	
		
			
				|  |  | -/** A bitarray of all fds that should be passed to tor_socket_close(). Only
 | 
	
		
			
				|  |  | - * used if DEBUG_SOCKET_COUNTING is defined. */
 | 
	
		
			
				|  |  | -static bitarray_t *open_sockets = NULL;
 | 
	
		
			
				|  |  | -/** The size of <b>open_sockets</b>, in bits. */
 | 
	
		
			
				|  |  | -static int max_socket = -1;
 | 
	
		
			
				|  |  | -#endif /* defined(DEBUG_SOCKET_COUNTING) */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** Count of number of sockets currently open.  (Undercounts sockets opened by
 | 
	
		
			
				|  |  | - * eventdns and libevent.) */
 | 
	
		
			
				|  |  | -static int n_sockets_open = 0;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** Mutex to protect open_sockets, max_socket, and n_sockets_open. */
 | 
	
		
			
				|  |  | -static tor_mutex_t *socket_accounting_mutex = NULL;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** Helper: acquire the socket accounting lock. */
 | 
	
		
			
				|  |  | -static inline void
 | 
	
		
			
				|  |  | -socket_accounting_lock(void)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -  if (PREDICT_UNLIKELY(!socket_accounting_mutex))
 | 
	
		
			
				|  |  | -    socket_accounting_mutex = tor_mutex_new();
 | 
	
		
			
				|  |  | -  tor_mutex_acquire(socket_accounting_mutex);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** Helper: release the socket accounting lock. */
 | 
	
		
			
				|  |  | -static inline void
 | 
	
		
			
				|  |  | -socket_accounting_unlock(void)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -  tor_mutex_release(socket_accounting_mutex);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** As close(), but guaranteed to work for sockets across platforms (including
 | 
	
		
			
				|  |  | - * Windows, where close()ing a socket doesn't work.  Returns 0 on success and
 | 
	
		
			
				|  |  | - * the socket error code on failure. */
 | 
	
		
			
				|  |  | -int
 | 
	
		
			
				|  |  | -tor_close_socket_simple(tor_socket_t s)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -  int r = 0;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  /* On Windows, you have to call close() on fds returned by open(),
 | 
	
		
			
				|  |  | -  * and closesocket() on fds returned by socket().  On Unix, everything
 | 
	
		
			
				|  |  | -  * gets close()'d.  We abstract this difference by always using
 | 
	
		
			
				|  |  | -  * tor_close_socket to close sockets, and always using close() on
 | 
	
		
			
				|  |  | -  * files.
 | 
	
		
			
				|  |  | -  */
 | 
	
		
			
				|  |  | -  #if defined(_WIN32)
 | 
	
		
			
				|  |  | -    r = closesocket(s);
 | 
	
		
			
				|  |  | -  #else
 | 
	
		
			
				|  |  | -    r = close(s);
 | 
	
		
			
				|  |  | -  #endif
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  if (r != 0) {
 | 
	
		
			
				|  |  | -    int err = tor_socket_errno(-1);
 | 
	
		
			
				|  |  | -    log_info(LD_NET, "Close returned an error: %s", tor_socket_strerror(err));
 | 
	
		
			
				|  |  | -    return err;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  return r;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** As tor_close_socket_simple(), but keeps track of the number
 | 
	
		
			
				|  |  | - * of open sockets. Returns 0 on success, -1 on failure. */
 | 
	
		
			
				|  |  | -MOCK_IMPL(int,
 | 
	
		
			
				|  |  | -tor_close_socket,(tor_socket_t s))
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -  int r = tor_close_socket_simple(s);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  socket_accounting_lock();
 | 
	
		
			
				|  |  | -#ifdef DEBUG_SOCKET_COUNTING
 | 
	
		
			
				|  |  | -  if (s > max_socket || ! bitarray_is_set(open_sockets, s)) {
 | 
	
		
			
				|  |  | -    log_warn(LD_BUG, "Closing a socket (%d) that wasn't returned by tor_open_"
 | 
	
		
			
				|  |  | -             "socket(), or that was already closed or something.", s);
 | 
	
		
			
				|  |  | -  } else {
 | 
	
		
			
				|  |  | -    tor_assert(open_sockets && s <= max_socket);
 | 
	
		
			
				|  |  | -    bitarray_clear(open_sockets, s);
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -#endif /* defined(DEBUG_SOCKET_COUNTING) */
 | 
	
		
			
				|  |  | -  if (r == 0) {
 | 
	
		
			
				|  |  | -    --n_sockets_open;
 | 
	
		
			
				|  |  | -  } else {
 | 
	
		
			
				|  |  | -#ifdef _WIN32
 | 
	
		
			
				|  |  | -    if (r != WSAENOTSOCK)
 | 
	
		
			
				|  |  | -      --n_sockets_open;
 | 
	
		
			
				|  |  | -#else
 | 
	
		
			
				|  |  | -    if (r != EBADF)
 | 
	
		
			
				|  |  | -      --n_sockets_open; // LCOV_EXCL_LINE -- EIO and EINTR too hard to force.
 | 
	
		
			
				|  |  | -#endif /* defined(_WIN32) */
 | 
	
		
			
				|  |  | -    r = -1;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  tor_assert_nonfatal(n_sockets_open >= 0);
 | 
	
		
			
				|  |  | -  socket_accounting_unlock();
 | 
	
		
			
				|  |  | -  return r;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** @{ */
 | 
	
		
			
				|  |  | -#ifdef DEBUG_SOCKET_COUNTING
 | 
	
		
			
				|  |  | -/** Helper: if DEBUG_SOCKET_COUNTING is enabled, remember that <b>s</b> is
 | 
	
		
			
				|  |  | - * now an open socket. */
 | 
	
		
			
				|  |  | -static inline void
 | 
	
		
			
				|  |  | -mark_socket_open(tor_socket_t s)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -  /* XXXX This bitarray business will NOT work on windows: sockets aren't
 | 
	
		
			
				|  |  | -     small ints there. */
 | 
	
		
			
				|  |  | -  if (s > max_socket) {
 | 
	
		
			
				|  |  | -    if (max_socket == -1) {
 | 
	
		
			
				|  |  | -      open_sockets = bitarray_init_zero(s+128);
 | 
	
		
			
				|  |  | -      max_socket = s+128;
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -      open_sockets = bitarray_expand(open_sockets, max_socket, s+128);
 | 
	
		
			
				|  |  | -      max_socket = s+128;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  if (bitarray_is_set(open_sockets, s)) {
 | 
	
		
			
				|  |  | -    log_warn(LD_BUG, "I thought that %d was already open, but socket() just "
 | 
	
		
			
				|  |  | -             "gave it to me!", s);
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  bitarray_set(open_sockets, s);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -#else /* !(defined(DEBUG_SOCKET_COUNTING)) */
 | 
	
		
			
				|  |  | -#define mark_socket_open(s) ((void) (s))
 | 
	
		
			
				|  |  | -#endif /* defined(DEBUG_SOCKET_COUNTING) */
 | 
	
		
			
				|  |  | -/** @} */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** As socket(), but counts the number of open sockets. */
 | 
	
		
			
				|  |  | -MOCK_IMPL(tor_socket_t,
 | 
	
		
			
				|  |  | -tor_open_socket,(int domain, int type, int protocol))
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -  return tor_open_socket_with_extensions(domain, type, protocol, 1, 0);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** Mockable wrapper for connect(). */
 | 
	
		
			
				|  |  | -MOCK_IMPL(tor_socket_t,
 | 
	
		
			
				|  |  | -tor_connect_socket,(tor_socket_t sock, const struct sockaddr *address,
 | 
	
		
			
				|  |  | -                     socklen_t address_len))
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -  return connect(sock,address,address_len);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** As socket(), but creates a nonblocking socket and
 | 
	
		
			
				|  |  | - * counts the number of open sockets. */
 | 
	
		
			
				|  |  | -tor_socket_t
 | 
	
		
			
				|  |  | -tor_open_socket_nonblocking(int domain, int type, int protocol)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -  return tor_open_socket_with_extensions(domain, type, protocol, 1, 1);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** As socket(), but counts the number of open sockets and handles
 | 
	
		
			
				|  |  | - * socket creation with either of SOCK_CLOEXEC and SOCK_NONBLOCK specified.
 | 
	
		
			
				|  |  | - * <b>cloexec</b> and <b>nonblock</b> should be either 0 or 1 to indicate
 | 
	
		
			
				|  |  | - * if the corresponding extension should be used.*/
 | 
	
		
			
				|  |  | -tor_socket_t
 | 
	
		
			
				|  |  | -tor_open_socket_with_extensions(int domain, int type, int protocol,
 | 
	
		
			
				|  |  | -                                int cloexec, int nonblock)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -  tor_socket_t s;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  /* We are about to create a new file descriptor so make sure we have
 | 
	
		
			
				|  |  | -   * enough of them. */
 | 
	
		
			
				|  |  | -  if (get_n_open_sockets() >= max_sockets - 1) {
 | 
	
		
			
				|  |  | -#ifdef _WIN32
 | 
	
		
			
				|  |  | -    WSASetLastError(WSAEMFILE);
 | 
	
		
			
				|  |  | -#else
 | 
	
		
			
				|  |  | -    errno = EMFILE;
 | 
	
		
			
				|  |  | -#endif
 | 
	
		
			
				|  |  | -    return TOR_INVALID_SOCKET;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -#if defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK)
 | 
	
		
			
				|  |  | -  int ext_flags = (cloexec ? SOCK_CLOEXEC : 0) |
 | 
	
		
			
				|  |  | -                  (nonblock ? SOCK_NONBLOCK : 0);
 | 
	
		
			
				|  |  | -  s = socket(domain, type|ext_flags, protocol);
 | 
	
		
			
				|  |  | -  if (SOCKET_OK(s))
 | 
	
		
			
				|  |  | -    goto socket_ok;
 | 
	
		
			
				|  |  | -  /* If we got an error, see if it is EINVAL. EINVAL might indicate that,
 | 
	
		
			
				|  |  | -   * even though we were built on a system with SOCK_CLOEXEC and SOCK_NONBLOCK
 | 
	
		
			
				|  |  | -   * support, we are running on one without. */
 | 
	
		
			
				|  |  | -  if (errno != EINVAL)
 | 
	
		
			
				|  |  | -    return s;
 | 
	
		
			
				|  |  | -#endif /* defined(SOCK_CLOEXEC) && defined(SOCK_NONBLOCK) */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  s = socket(domain, type, protocol);
 | 
	
		
			
				|  |  | -  if (! SOCKET_OK(s))
 | 
	
		
			
				|  |  | -    return s;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -#if defined(FD_CLOEXEC)
 | 
	
		
			
				|  |  | -  if (cloexec) {
 | 
	
		
			
				|  |  | -    if (fcntl(s, F_SETFD, FD_CLOEXEC) == -1) {
 | 
	
		
			
				|  |  | -      log_warn(LD_FS,"Couldn't set FD_CLOEXEC: %s", strerror(errno));
 | 
	
		
			
				|  |  | -      tor_close_socket_simple(s);
 | 
	
		
			
				|  |  | -      return TOR_INVALID_SOCKET;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -#else /* !(defined(FD_CLOEXEC)) */
 | 
	
		
			
				|  |  | -  (void)cloexec;
 | 
	
		
			
				|  |  | -#endif /* defined(FD_CLOEXEC) */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  if (nonblock) {
 | 
	
		
			
				|  |  | -    if (set_socket_nonblocking(s) == -1) {
 | 
	
		
			
				|  |  | -      tor_close_socket_simple(s);
 | 
	
		
			
				|  |  | -      return TOR_INVALID_SOCKET;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  goto socket_ok; /* So that socket_ok will not be unused. */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | - socket_ok:
 | 
	
		
			
				|  |  | -  tor_take_socket_ownership(s);
 | 
	
		
			
				|  |  | -  return s;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | - * For socket accounting: remember that we are the owner of the socket
 | 
	
		
			
				|  |  | - * <b>s</b>. This will prevent us from overallocating sockets, and prevent us
 | 
	
		
			
				|  |  | - * from asserting later when we close the socket <b>s</b>.
 | 
	
		
			
				|  |  | - */
 | 
	
		
			
				|  |  | -void
 | 
	
		
			
				|  |  | -tor_take_socket_ownership(tor_socket_t s)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -  socket_accounting_lock();
 | 
	
		
			
				|  |  | -  ++n_sockets_open;
 | 
	
		
			
				|  |  | -  mark_socket_open(s);
 | 
	
		
			
				|  |  | -  socket_accounting_unlock();
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** As accept(), but counts the number of open sockets. */
 | 
	
		
			
				|  |  | -tor_socket_t
 | 
	
		
			
				|  |  | -tor_accept_socket(tor_socket_t sockfd, struct sockaddr *addr, socklen_t *len)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -  return tor_accept_socket_with_extensions(sockfd, addr, len, 1, 0);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** As accept(), but returns a nonblocking socket and
 | 
	
		
			
				|  |  | - * counts the number of open sockets. */
 | 
	
		
			
				|  |  | -tor_socket_t
 | 
	
		
			
				|  |  | -tor_accept_socket_nonblocking(tor_socket_t sockfd, struct sockaddr *addr,
 | 
	
		
			
				|  |  | -                              socklen_t *len)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -  return tor_accept_socket_with_extensions(sockfd, addr, len, 1, 1);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** As accept(), but counts the number of open sockets and handles
 | 
	
		
			
				|  |  | - * socket creation with either of SOCK_CLOEXEC and SOCK_NONBLOCK specified.
 | 
	
		
			
				|  |  | - * <b>cloexec</b> and <b>nonblock</b> should be either 0 or 1 to indicate
 | 
	
		
			
				|  |  | - * if the corresponding extension should be used.*/
 | 
	
		
			
				|  |  | -tor_socket_t
 | 
	
		
			
				|  |  | -tor_accept_socket_with_extensions(tor_socket_t sockfd, struct sockaddr *addr,
 | 
	
		
			
				|  |  | -                                 socklen_t *len, int cloexec, int nonblock)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -  tor_socket_t s;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  /* We are about to create a new file descriptor so make sure we have
 | 
	
		
			
				|  |  | -   * enough of them. */
 | 
	
		
			
				|  |  | -  if (get_n_open_sockets() >= max_sockets - 1) {
 | 
	
		
			
				|  |  | -#ifdef _WIN32
 | 
	
		
			
				|  |  | -    WSASetLastError(WSAEMFILE);
 | 
	
		
			
				|  |  | -#else
 | 
	
		
			
				|  |  | -    errno = EMFILE;
 | 
	
		
			
				|  |  | -#endif
 | 
	
		
			
				|  |  | -    return TOR_INVALID_SOCKET;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -#if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) \
 | 
	
		
			
				|  |  | -  && defined(SOCK_NONBLOCK)
 | 
	
		
			
				|  |  | -  int ext_flags = (cloexec ? SOCK_CLOEXEC : 0) |
 | 
	
		
			
				|  |  | -                  (nonblock ? SOCK_NONBLOCK : 0);
 | 
	
		
			
				|  |  | -  s = accept4(sockfd, addr, len, ext_flags);
 | 
	
		
			
				|  |  | -  if (SOCKET_OK(s))
 | 
	
		
			
				|  |  | -    goto socket_ok;
 | 
	
		
			
				|  |  | -  /* If we got an error, see if it is ENOSYS. ENOSYS indicates that,
 | 
	
		
			
				|  |  | -   * even though we were built on a system with accept4 support, we
 | 
	
		
			
				|  |  | -   * are running on one without. Also, check for EINVAL, which indicates that
 | 
	
		
			
				|  |  | -   * we are missing SOCK_CLOEXEC/SOCK_NONBLOCK support. */
 | 
	
		
			
				|  |  | -  if (errno != EINVAL && errno != ENOSYS)
 | 
	
		
			
				|  |  | -    return s;
 | 
	
		
			
				|  |  | -#endif /* defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) ... */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  s = accept(sockfd, addr, len);
 | 
	
		
			
				|  |  | -  if (!SOCKET_OK(s))
 | 
	
		
			
				|  |  | -    return s;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -#if defined(FD_CLOEXEC)
 | 
	
		
			
				|  |  | -  if (cloexec) {
 | 
	
		
			
				|  |  | -    if (fcntl(s, F_SETFD, FD_CLOEXEC) == -1) {
 | 
	
		
			
				|  |  | -      log_warn(LD_NET, "Couldn't set FD_CLOEXEC: %s", strerror(errno));
 | 
	
		
			
				|  |  | -      tor_close_socket_simple(s);
 | 
	
		
			
				|  |  | -      return TOR_INVALID_SOCKET;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -#else /* !(defined(FD_CLOEXEC)) */
 | 
	
		
			
				|  |  | -  (void)cloexec;
 | 
	
		
			
				|  |  | -#endif /* defined(FD_CLOEXEC) */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  if (nonblock) {
 | 
	
		
			
				|  |  | -    if (set_socket_nonblocking(s) == -1) {
 | 
	
		
			
				|  |  | -      tor_close_socket_simple(s);
 | 
	
		
			
				|  |  | -      return TOR_INVALID_SOCKET;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  goto socket_ok; /* So that socket_ok will not be unused. */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | - socket_ok:
 | 
	
		
			
				|  |  | -  tor_take_socket_ownership(s);
 | 
	
		
			
				|  |  | -  return s;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** Return the number of sockets we currently have opened. */
 | 
	
		
			
				|  |  | -int
 | 
	
		
			
				|  |  | -get_n_open_sockets(void)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -  int n;
 | 
	
		
			
				|  |  | -  socket_accounting_lock();
 | 
	
		
			
				|  |  | -  n = n_sockets_open;
 | 
	
		
			
				|  |  | -  socket_accounting_unlock();
 | 
	
		
			
				|  |  | -  return n;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** Mockable wrapper for getsockname(). */
 | 
	
		
			
				|  |  | -MOCK_IMPL(int,
 | 
	
		
			
				|  |  | -tor_getsockname,(tor_socket_t sock, struct sockaddr *address,
 | 
	
		
			
				|  |  | -                 socklen_t *address_len))
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -   return getsockname(sock, address, address_len);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | - * Find the local address associated with the socket <b>sock</b>, and
 | 
	
		
			
				|  |  | - * place it in *<b>addr_out</b>.  Return 0 on success, -1 on failure.
 | 
	
		
			
				|  |  | - *
 | 
	
		
			
				|  |  | - * (As tor_getsockname, but instead places the result in a tor_addr_t.) */
 | 
	
		
			
				|  |  | -int
 | 
	
		
			
				|  |  | -tor_addr_from_getsockname(tor_addr_t *addr_out, tor_socket_t sock)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -  struct sockaddr_storage ss;
 | 
	
		
			
				|  |  | -  socklen_t ss_len = sizeof(ss);
 | 
	
		
			
				|  |  | -  memset(&ss, 0, sizeof(ss));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  if (tor_getsockname(sock, (struct sockaddr *) &ss, &ss_len) < 0)
 | 
	
		
			
				|  |  | -    return -1;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  return tor_addr_from_sockaddr(addr_out, (struct sockaddr *)&ss, NULL);
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** Turn <b>socket</b> into a nonblocking socket. Return 0 on success, -1
 | 
	
		
			
				|  |  | - * on failure.
 | 
	
		
			
				|  |  | - */
 | 
	
		
			
				|  |  | -int
 | 
	
		
			
				|  |  | -set_socket_nonblocking(tor_socket_t sock)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -#if defined(_WIN32)
 | 
	
		
			
				|  |  | -  unsigned long nonblocking = 1;
 | 
	
		
			
				|  |  | -  ioctlsocket(sock, FIONBIO, (unsigned long*) &nonblocking);
 | 
	
		
			
				|  |  | -#else
 | 
	
		
			
				|  |  | -  int flags;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  flags = fcntl(sock, F_GETFL, 0);
 | 
	
		
			
				|  |  | -  if (flags == -1) {
 | 
	
		
			
				|  |  | -    log_warn(LD_NET, "Couldn't get file status flags: %s", strerror(errno));
 | 
	
		
			
				|  |  | -    return -1;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  flags |= O_NONBLOCK;
 | 
	
		
			
				|  |  | -  if (fcntl(sock, F_SETFL, flags) == -1) {
 | 
	
		
			
				|  |  | -    log_warn(LD_NET, "Couldn't set file status flags: %s", strerror(errno));
 | 
	
		
			
				|  |  | -    return -1;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -#endif /* defined(_WIN32) */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  return 0;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | - * Allocate a pair of connected sockets.  (Like socketpair(family,
 | 
	
		
			
				|  |  | - * type,protocol,fd), but works on systems that don't have
 | 
	
		
			
				|  |  | - * socketpair.)
 | 
	
		
			
				|  |  | - *
 | 
	
		
			
				|  |  | - * Currently, only (AF_UNIX, SOCK_STREAM, 0) sockets are supported.
 | 
	
		
			
				|  |  | - *
 | 
	
		
			
				|  |  | - * Note that on systems without socketpair, this call will fail if
 | 
	
		
			
				|  |  | - * localhost is inaccessible (for example, if the networking
 | 
	
		
			
				|  |  | - * stack is down). And even if it succeeds, the socket pair will not
 | 
	
		
			
				|  |  | - * be able to read while localhost is down later (the socket pair may
 | 
	
		
			
				|  |  | - * even close, depending on OS-specific timeouts).
 | 
	
		
			
				|  |  | - *
 | 
	
		
			
				|  |  | - * Returns 0 on success and -errno on failure; do not rely on the value
 | 
	
		
			
				|  |  | - * of errno or WSAGetLastError().
 | 
	
		
			
				|  |  | - **/
 | 
	
		
			
				|  |  | -/* It would be nicer just to set errno, but that won't work for windows. */
 | 
	
		
			
				|  |  | -int
 | 
	
		
			
				|  |  | -tor_socketpair(int family, int type, int protocol, tor_socket_t fd[2])
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -//don't use win32 socketpairs (they are always bad)
 | 
	
		
			
				|  |  | -#if defined(HAVE_SOCKETPAIR) && !defined(_WIN32)
 | 
	
		
			
				|  |  | -  int r;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -#ifdef SOCK_CLOEXEC
 | 
	
		
			
				|  |  | -  r = socketpair(family, type|SOCK_CLOEXEC, protocol, fd);
 | 
	
		
			
				|  |  | -  if (r == 0)
 | 
	
		
			
				|  |  | -    goto sockets_ok;
 | 
	
		
			
				|  |  | -  /* If we got an error, see if it is EINVAL. EINVAL might indicate that,
 | 
	
		
			
				|  |  | -   * even though we were built on a system with SOCK_CLOEXEC support, we
 | 
	
		
			
				|  |  | -   * are running on one without. */
 | 
	
		
			
				|  |  | -  if (errno != EINVAL)
 | 
	
		
			
				|  |  | -    return -errno;
 | 
	
		
			
				|  |  | -#endif /* defined(SOCK_CLOEXEC) */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  r = socketpair(family, type, protocol, fd);
 | 
	
		
			
				|  |  | -  if (r < 0)
 | 
	
		
			
				|  |  | -    return -errno;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -#if defined(FD_CLOEXEC)
 | 
	
		
			
				|  |  | -  if (SOCKET_OK(fd[0])) {
 | 
	
		
			
				|  |  | -    r = fcntl(fd[0], F_SETFD, FD_CLOEXEC);
 | 
	
		
			
				|  |  | -    if (r == -1) {
 | 
	
		
			
				|  |  | -      close(fd[0]);
 | 
	
		
			
				|  |  | -      close(fd[1]);
 | 
	
		
			
				|  |  | -      return -errno;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  if (SOCKET_OK(fd[1])) {
 | 
	
		
			
				|  |  | -    r = fcntl(fd[1], F_SETFD, FD_CLOEXEC);
 | 
	
		
			
				|  |  | -    if (r == -1) {
 | 
	
		
			
				|  |  | -      close(fd[0]);
 | 
	
		
			
				|  |  | -      close(fd[1]);
 | 
	
		
			
				|  |  | -      return -errno;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -#endif /* defined(FD_CLOEXEC) */
 | 
	
		
			
				|  |  | -  goto sockets_ok; /* So that sockets_ok will not be unused. */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | - sockets_ok:
 | 
	
		
			
				|  |  | -  socket_accounting_lock();
 | 
	
		
			
				|  |  | -  if (SOCKET_OK(fd[0])) {
 | 
	
		
			
				|  |  | -    ++n_sockets_open;
 | 
	
		
			
				|  |  | -    mark_socket_open(fd[0]);
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  if (SOCKET_OK(fd[1])) {
 | 
	
		
			
				|  |  | -    ++n_sockets_open;
 | 
	
		
			
				|  |  | -    mark_socket_open(fd[1]);
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -  socket_accounting_unlock();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  return 0;
 | 
	
		
			
				|  |  | -#else /* !(defined(HAVE_SOCKETPAIR) && !defined(_WIN32)) */
 | 
	
		
			
				|  |  | -  return tor_ersatz_socketpair(family, type, protocol, fd);
 | 
	
		
			
				|  |  | -#endif /* defined(HAVE_SOCKETPAIR) && !defined(_WIN32) */
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -#ifdef NEED_ERSATZ_SOCKETPAIR
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -static inline socklen_t
 | 
	
		
			
				|  |  | -SIZEOF_SOCKADDR(int domain)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -  switch (domain) {
 | 
	
		
			
				|  |  | -    case AF_INET:
 | 
	
		
			
				|  |  | -      return sizeof(struct sockaddr_in);
 | 
	
		
			
				|  |  | -    case AF_INET6:
 | 
	
		
			
				|  |  | -      return sizeof(struct sockaddr_in6);
 | 
	
		
			
				|  |  | -    default:
 | 
	
		
			
				|  |  | -      return 0;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/**
 | 
	
		
			
				|  |  | - * Helper used to implement socketpair on systems that lack it, by
 | 
	
		
			
				|  |  | - * making a direct connection to localhost.
 | 
	
		
			
				|  |  | - */
 | 
	
		
			
				|  |  | -STATIC int
 | 
	
		
			
				|  |  | -tor_ersatz_socketpair(int family, int type, int protocol, tor_socket_t fd[2])
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -    /* This socketpair does not work when localhost is down. So
 | 
	
		
			
				|  |  | -     * it's really not the same thing at all. But it's close enough
 | 
	
		
			
				|  |  | -     * for now, and really, when localhost is down sometimes, we
 | 
	
		
			
				|  |  | -     * have other problems too.
 | 
	
		
			
				|  |  | -     */
 | 
	
		
			
				|  |  | -    tor_socket_t listener = TOR_INVALID_SOCKET;
 | 
	
		
			
				|  |  | -    tor_socket_t connector = TOR_INVALID_SOCKET;
 | 
	
		
			
				|  |  | -    tor_socket_t acceptor = TOR_INVALID_SOCKET;
 | 
	
		
			
				|  |  | -    tor_addr_t listen_tor_addr;
 | 
	
		
			
				|  |  | -    struct sockaddr_storage connect_addr_ss, listen_addr_ss;
 | 
	
		
			
				|  |  | -    struct sockaddr *listen_addr = (struct sockaddr *) &listen_addr_ss;
 | 
	
		
			
				|  |  | -    uint16_t listen_port = 0;
 | 
	
		
			
				|  |  | -    tor_addr_t connect_tor_addr;
 | 
	
		
			
				|  |  | -    uint16_t connect_port = 0;
 | 
	
		
			
				|  |  | -    struct sockaddr *connect_addr = (struct sockaddr *) &connect_addr_ss;
 | 
	
		
			
				|  |  | -    socklen_t size;
 | 
	
		
			
				|  |  | -    int saved_errno = -1;
 | 
	
		
			
				|  |  | -    int ersatz_domain = AF_INET;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    memset(&connect_tor_addr, 0, sizeof(connect_tor_addr));
 | 
	
		
			
				|  |  | -    memset(&connect_addr_ss, 0, sizeof(connect_addr_ss));
 | 
	
		
			
				|  |  | -    memset(&listen_tor_addr, 0, sizeof(listen_tor_addr));
 | 
	
		
			
				|  |  | -    memset(&listen_addr_ss, 0, sizeof(listen_addr_ss));
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    if (protocol
 | 
	
		
			
				|  |  | -#ifdef AF_UNIX
 | 
	
		
			
				|  |  | -        || family != AF_UNIX
 | 
	
		
			
				|  |  | -#endif
 | 
	
		
			
				|  |  | -        ) {
 | 
	
		
			
				|  |  | -#ifdef _WIN32
 | 
	
		
			
				|  |  | -      return -WSAEAFNOSUPPORT;
 | 
	
		
			
				|  |  | -#else
 | 
	
		
			
				|  |  | -      return -EAFNOSUPPORT;
 | 
	
		
			
				|  |  | -#endif
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    if (!fd) {
 | 
	
		
			
				|  |  | -      return -EINVAL;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    listener = tor_open_socket(ersatz_domain, type, 0);
 | 
	
		
			
				|  |  | -    if (!SOCKET_OK(listener)) {
 | 
	
		
			
				|  |  | -      int first_errno = tor_socket_errno(-1);
 | 
	
		
			
				|  |  | -      if (first_errno == SOCK_ERRNO(EPROTONOSUPPORT)
 | 
	
		
			
				|  |  | -          && ersatz_domain == AF_INET) {
 | 
	
		
			
				|  |  | -        /* Assume we're on an IPv6-only system */
 | 
	
		
			
				|  |  | -        ersatz_domain = AF_INET6;
 | 
	
		
			
				|  |  | -        listener = tor_open_socket(ersatz_domain, type, 0);
 | 
	
		
			
				|  |  | -        if (!SOCKET_OK(listener)) {
 | 
	
		
			
				|  |  | -          /* Keep the previous behaviour, which was to return the IPv4 error.
 | 
	
		
			
				|  |  | -           * (This may be less informative on IPv6-only systems.)
 | 
	
		
			
				|  |  | -           * XX/teor - is there a better way to decide which errno to return?
 | 
	
		
			
				|  |  | -           * (I doubt we care much either way, once there is an error.)
 | 
	
		
			
				|  |  | -           */
 | 
	
		
			
				|  |  | -          return -first_errno;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    /* If there is no 127.0.0.1 or ::1, this will and must fail. Otherwise, we
 | 
	
		
			
				|  |  | -     * risk exposing a socketpair on a routable IP address. (Some BSD jails
 | 
	
		
			
				|  |  | -     * use a routable address for localhost. Fortunately, they have the real
 | 
	
		
			
				|  |  | -     * AF_UNIX socketpair.) */
 | 
	
		
			
				|  |  | -    if (ersatz_domain == AF_INET) {
 | 
	
		
			
				|  |  | -      tor_addr_from_ipv4h(&listen_tor_addr, INADDR_LOOPBACK);
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -      tor_addr_parse(&listen_tor_addr, "[::1]");
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    tor_assert(tor_addr_is_loopback(&listen_tor_addr));
 | 
	
		
			
				|  |  | -    size = tor_addr_to_sockaddr(&listen_tor_addr,
 | 
	
		
			
				|  |  | -                         0 /* kernel chooses port.  */,
 | 
	
		
			
				|  |  | -                         listen_addr,
 | 
	
		
			
				|  |  | -                         sizeof(listen_addr_ss));
 | 
	
		
			
				|  |  | -    if (bind(listener, listen_addr, size) == -1)
 | 
	
		
			
				|  |  | -      goto tidy_up_and_fail;
 | 
	
		
			
				|  |  | -    if (listen(listener, 1) == -1)
 | 
	
		
			
				|  |  | -      goto tidy_up_and_fail;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    connector = tor_open_socket(ersatz_domain, type, 0);
 | 
	
		
			
				|  |  | -    if (!SOCKET_OK(connector))
 | 
	
		
			
				|  |  | -      goto tidy_up_and_fail;
 | 
	
		
			
				|  |  | -    /* We want to find out the port number to connect to.  */
 | 
	
		
			
				|  |  | -    size = sizeof(connect_addr_ss);
 | 
	
		
			
				|  |  | -    if (getsockname(listener, connect_addr, &size) == -1)
 | 
	
		
			
				|  |  | -      goto tidy_up_and_fail;
 | 
	
		
			
				|  |  | -    if (size != SIZEOF_SOCKADDR (connect_addr->sa_family))
 | 
	
		
			
				|  |  | -      goto abort_tidy_up_and_fail;
 | 
	
		
			
				|  |  | -    if (connect(connector, connect_addr, size) == -1)
 | 
	
		
			
				|  |  | -      goto tidy_up_and_fail;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    size = sizeof(listen_addr_ss);
 | 
	
		
			
				|  |  | -    acceptor = tor_accept_socket(listener, listen_addr, &size);
 | 
	
		
			
				|  |  | -    if (!SOCKET_OK(acceptor))
 | 
	
		
			
				|  |  | -      goto tidy_up_and_fail;
 | 
	
		
			
				|  |  | -    if (size != SIZEOF_SOCKADDR(listen_addr->sa_family))
 | 
	
		
			
				|  |  | -      goto abort_tidy_up_and_fail;
 | 
	
		
			
				|  |  | -    /* Now check we are talking to ourself by matching port and host on the
 | 
	
		
			
				|  |  | -       two sockets.  */
 | 
	
		
			
				|  |  | -    if (getsockname(connector, connect_addr, &size) == -1)
 | 
	
		
			
				|  |  | -      goto tidy_up_and_fail;
 | 
	
		
			
				|  |  | -    /* Set *_tor_addr and *_port to the address and port that was used */
 | 
	
		
			
				|  |  | -    tor_addr_from_sockaddr(&listen_tor_addr, listen_addr, &listen_port);
 | 
	
		
			
				|  |  | -    tor_addr_from_sockaddr(&connect_tor_addr, connect_addr, &connect_port);
 | 
	
		
			
				|  |  | -    if (size != SIZEOF_SOCKADDR (connect_addr->sa_family)
 | 
	
		
			
				|  |  | -        || tor_addr_compare(&listen_tor_addr, &connect_tor_addr, CMP_SEMANTIC)
 | 
	
		
			
				|  |  | -        || listen_port != connect_port) {
 | 
	
		
			
				|  |  | -      goto abort_tidy_up_and_fail;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    tor_close_socket(listener);
 | 
	
		
			
				|  |  | -    fd[0] = connector;
 | 
	
		
			
				|  |  | -    fd[1] = acceptor;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    return 0;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  abort_tidy_up_and_fail:
 | 
	
		
			
				|  |  | -#ifdef _WIN32
 | 
	
		
			
				|  |  | -    saved_errno = WSAECONNABORTED;
 | 
	
		
			
				|  |  | -#else
 | 
	
		
			
				|  |  | -    saved_errno = ECONNABORTED; /* I hope this is portable and appropriate.  */
 | 
	
		
			
				|  |  | -#endif
 | 
	
		
			
				|  |  | -  tidy_up_and_fail:
 | 
	
		
			
				|  |  | -    if (saved_errno < 0)
 | 
	
		
			
				|  |  | -      saved_errno = errno;
 | 
	
		
			
				|  |  | -    if (SOCKET_OK(listener))
 | 
	
		
			
				|  |  | -      tor_close_socket(listener);
 | 
	
		
			
				|  |  | -    if (SOCKET_OK(connector))
 | 
	
		
			
				|  |  | -      tor_close_socket(connector);
 | 
	
		
			
				|  |  | -    if (SOCKET_OK(acceptor))
 | 
	
		
			
				|  |  | -      tor_close_socket(acceptor);
 | 
	
		
			
				|  |  | -    return -saved_errno;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -#undef SIZEOF_SOCKADDR
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -#endif /* defined(NEED_ERSATZ_SOCKETPAIR) */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/* Return the maximum number of allowed sockets. */
 | 
	
		
			
				|  |  | -int
 | 
	
		
			
				|  |  | -get_max_sockets(void)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -  return max_sockets;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  /** Number of extra file descriptors to keep in reserve beyond those that we
 | 
	
		
			
				|  |  |   * tell Tor it's allowed to use. */
 | 
	
		
			
				|  |  |  #define ULIMIT_BUFFER 32 /* keep 32 extra fd's beyond ConnLimit_ */
 | 
	
	
		
			
				|  | @@ -1396,7 +779,8 @@ set_max_file_descriptors(rlim_t limit, int *max_out)
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    /* Set the current limit value so if the attempt to set the limit to the
 | 
	
		
			
				|  |  |     * max fails at least we'll have a valid value of maximum sockets. */
 | 
	
		
			
				|  |  | -  *max_out = max_sockets = (int)rlim.rlim_cur - ULIMIT_BUFFER;
 | 
	
		
			
				|  |  | +  *max_out = (int)rlim.rlim_cur - ULIMIT_BUFFER;
 | 
	
		
			
				|  |  | +  set_max_sockets(*max_out);
 | 
	
		
			
				|  |  |    rlim.rlim_cur = rlim.rlim_max;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    if (setrlimit(RLIMIT_NOFILE, &rlim) != 0) {
 | 
	
	
		
			
				|  | @@ -1438,7 +822,9 @@ set_max_file_descriptors(rlim_t limit, int *max_out)
 | 
	
		
			
				|  |  |    if (limit > INT_MAX)
 | 
	
		
			
				|  |  |      limit = INT_MAX;
 | 
	
		
			
				|  |  |    tor_assert(max_out);
 | 
	
		
			
				|  |  | -  *max_out = max_sockets = (int)limit - ULIMIT_BUFFER;
 | 
	
		
			
				|  |  | +  *max_out = (int)limit - ULIMIT_BUFFER;
 | 
	
		
			
				|  |  | +  set_max_sockets(*max_out);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    return 0;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -2124,251 +1510,6 @@ tor_gethostname,(char *name, size_t namelen))
 | 
	
		
			
				|  |  |     return gethostname(name,namelen);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/** Set *addr to the IP address (in dotted-quad notation) stored in *str.
 | 
	
		
			
				|  |  | - * Return 1 on success, 0 if *str is badly formatted.
 | 
	
		
			
				|  |  | - * (Like inet_aton(str,addr), but works on Windows and Solaris.)
 | 
	
		
			
				|  |  | - */
 | 
	
		
			
				|  |  | -int
 | 
	
		
			
				|  |  | -tor_inet_aton(const char *str, struct in_addr* addr)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -  unsigned a,b,c,d;
 | 
	
		
			
				|  |  | -  char more;
 | 
	
		
			
				|  |  | -  if (tor_sscanf(str, "%3u.%3u.%3u.%3u%c", &a,&b,&c,&d,&more) != 4)
 | 
	
		
			
				|  |  | -    return 0;
 | 
	
		
			
				|  |  | -  if (a > 255) return 0;
 | 
	
		
			
				|  |  | -  if (b > 255) return 0;
 | 
	
		
			
				|  |  | -  if (c > 255) return 0;
 | 
	
		
			
				|  |  | -  if (d > 255) return 0;
 | 
	
		
			
				|  |  | -  addr->s_addr = htonl((a<<24) | (b<<16) | (c<<8) | d);
 | 
	
		
			
				|  |  | -  return 1;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** Given <b>af</b>==AF_INET and <b>src</b> a struct in_addr, or
 | 
	
		
			
				|  |  | - * <b>af</b>==AF_INET6 and <b>src</b> a struct in6_addr, try to format the
 | 
	
		
			
				|  |  | - * address and store it in the <b>len</b>-byte buffer <b>dst</b>.  Returns
 | 
	
		
			
				|  |  | - * <b>dst</b> on success, NULL on failure.
 | 
	
		
			
				|  |  | - *
 | 
	
		
			
				|  |  | - * (Like inet_ntop(af,src,dst,len), but works on platforms that don't have it:
 | 
	
		
			
				|  |  | - * Tor sometimes needs to format ipv6 addresses even on platforms without ipv6
 | 
	
		
			
				|  |  | - * support.) */
 | 
	
		
			
				|  |  | -const char *
 | 
	
		
			
				|  |  | -tor_inet_ntop(int af, const void *src, char *dst, size_t len)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -  if (af == AF_INET) {
 | 
	
		
			
				|  |  | -    if (tor_inet_ntoa(src, dst, len) < 0)
 | 
	
		
			
				|  |  | -      return NULL;
 | 
	
		
			
				|  |  | -    else
 | 
	
		
			
				|  |  | -      return dst;
 | 
	
		
			
				|  |  | -  } else if (af == AF_INET6) {
 | 
	
		
			
				|  |  | -    const struct in6_addr *addr = src;
 | 
	
		
			
				|  |  | -    char buf[64], *cp;
 | 
	
		
			
				|  |  | -    int longestGapLen = 0, longestGapPos = -1, i,
 | 
	
		
			
				|  |  | -      curGapPos = -1, curGapLen = 0;
 | 
	
		
			
				|  |  | -    uint16_t words[8];
 | 
	
		
			
				|  |  | -    for (i = 0; i < 8; ++i) {
 | 
	
		
			
				|  |  | -      words[i] = (((uint16_t)addr->s6_addr[2*i])<<8) + addr->s6_addr[2*i+1];
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    if (words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0 &&
 | 
	
		
			
				|  |  | -        words[4] == 0 && ((words[5] == 0 && words[6] && words[7]) ||
 | 
	
		
			
				|  |  | -                          (words[5] == 0xffff))) {
 | 
	
		
			
				|  |  | -      /* This is an IPv4 address. */
 | 
	
		
			
				|  |  | -      if (words[5] == 0) {
 | 
	
		
			
				|  |  | -        tor_snprintf(buf, sizeof(buf), "::%d.%d.%d.%d",
 | 
	
		
			
				|  |  | -                     addr->s6_addr[12], addr->s6_addr[13],
 | 
	
		
			
				|  |  | -                     addr->s6_addr[14], addr->s6_addr[15]);
 | 
	
		
			
				|  |  | -      } else {
 | 
	
		
			
				|  |  | -        tor_snprintf(buf, sizeof(buf), "::%x:%d.%d.%d.%d", words[5],
 | 
	
		
			
				|  |  | -                     addr->s6_addr[12], addr->s6_addr[13],
 | 
	
		
			
				|  |  | -                     addr->s6_addr[14], addr->s6_addr[15]);
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -      if ((strlen(buf) + 1) > len) /* +1 for \0 */
 | 
	
		
			
				|  |  | -        return NULL;
 | 
	
		
			
				|  |  | -      strlcpy(dst, buf, len);
 | 
	
		
			
				|  |  | -      return dst;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    i = 0;
 | 
	
		
			
				|  |  | -    while (i < 8) {
 | 
	
		
			
				|  |  | -      if (words[i] == 0) {
 | 
	
		
			
				|  |  | -        curGapPos = i++;
 | 
	
		
			
				|  |  | -        curGapLen = 1;
 | 
	
		
			
				|  |  | -        while (i<8 && words[i] == 0) {
 | 
	
		
			
				|  |  | -          ++i; ++curGapLen;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        if (curGapLen > longestGapLen) {
 | 
	
		
			
				|  |  | -          longestGapPos = curGapPos;
 | 
	
		
			
				|  |  | -          longestGapLen = curGapLen;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -      } else {
 | 
	
		
			
				|  |  | -        ++i;
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    if (longestGapLen<=1)
 | 
	
		
			
				|  |  | -      longestGapPos = -1;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    cp = buf;
 | 
	
		
			
				|  |  | -    for (i = 0; i < 8; ++i) {
 | 
	
		
			
				|  |  | -      if (words[i] == 0 && longestGapPos == i) {
 | 
	
		
			
				|  |  | -        if (i == 0)
 | 
	
		
			
				|  |  | -          *cp++ = ':';
 | 
	
		
			
				|  |  | -        *cp++ = ':';
 | 
	
		
			
				|  |  | -        while (i < 8 && words[i] == 0)
 | 
	
		
			
				|  |  | -          ++i;
 | 
	
		
			
				|  |  | -        --i; /* to compensate for loop increment. */
 | 
	
		
			
				|  |  | -      } else {
 | 
	
		
			
				|  |  | -        tor_snprintf(cp, sizeof(buf)-(cp-buf), "%x", (unsigned)words[i]);
 | 
	
		
			
				|  |  | -        cp += strlen(cp);
 | 
	
		
			
				|  |  | -        if (i != 7)
 | 
	
		
			
				|  |  | -          *cp++ = ':';
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    *cp = '\0';
 | 
	
		
			
				|  |  | -    if ((strlen(buf) + 1) > len) /* +1 for \0 */
 | 
	
		
			
				|  |  | -      return NULL;
 | 
	
		
			
				|  |  | -    strlcpy(dst, buf, len);
 | 
	
		
			
				|  |  | -    return dst;
 | 
	
		
			
				|  |  | -  } else {
 | 
	
		
			
				|  |  | -    return NULL;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** Given <b>af</b>==AF_INET or <b>af</b>==AF_INET6, and a string <b>src</b>
 | 
	
		
			
				|  |  | - * encoding an IPv4 address or IPv6 address correspondingly, try to parse the
 | 
	
		
			
				|  |  | - * address and store the result in <b>dst</b> (which must have space for a
 | 
	
		
			
				|  |  | - * struct in_addr or a struct in6_addr, as appropriate).  Return 1 on success,
 | 
	
		
			
				|  |  | - * 0 on a bad parse, and -1 on a bad <b>af</b>.
 | 
	
		
			
				|  |  | - *
 | 
	
		
			
				|  |  | - * (Like inet_pton(af,src,dst) but works on platforms that don't have it: Tor
 | 
	
		
			
				|  |  | - * sometimes needs to format ipv6 addresses even on platforms without ipv6
 | 
	
		
			
				|  |  | - * support.) */
 | 
	
		
			
				|  |  | -int
 | 
	
		
			
				|  |  | -tor_inet_pton(int af, const char *src, void *dst)
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -  if (af == AF_INET) {
 | 
	
		
			
				|  |  | -    return tor_inet_aton(src, dst);
 | 
	
		
			
				|  |  | -  } else if (af == AF_INET6) {
 | 
	
		
			
				|  |  | -    struct in6_addr *out = dst;
 | 
	
		
			
				|  |  | -    uint16_t words[8];
 | 
	
		
			
				|  |  | -    int gapPos = -1, i, setWords=0;
 | 
	
		
			
				|  |  | -    const char *dot = strchr(src, '.');
 | 
	
		
			
				|  |  | -    const char *eow; /* end of words. */
 | 
	
		
			
				|  |  | -    memset(words, 0xf8, sizeof(words));
 | 
	
		
			
				|  |  | -    if (dot == src)
 | 
	
		
			
				|  |  | -      return 0;
 | 
	
		
			
				|  |  | -    else if (!dot)
 | 
	
		
			
				|  |  | -      eow = src+strlen(src);
 | 
	
		
			
				|  |  | -    else {
 | 
	
		
			
				|  |  | -      unsigned byte1,byte2,byte3,byte4;
 | 
	
		
			
				|  |  | -      char more;
 | 
	
		
			
				|  |  | -      for (eow = dot-1; eow > src && TOR_ISDIGIT(*eow); --eow)
 | 
	
		
			
				|  |  | -        ;
 | 
	
		
			
				|  |  | -      if (*eow != ':')
 | 
	
		
			
				|  |  | -        return 0;
 | 
	
		
			
				|  |  | -      ++eow;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      /* We use "scanf" because some platform inet_aton()s are too lax
 | 
	
		
			
				|  |  | -       * about IPv4 addresses of the form "1.2.3" */
 | 
	
		
			
				|  |  | -      if (tor_sscanf(eow, "%3u.%3u.%3u.%3u%c",
 | 
	
		
			
				|  |  | -                     &byte1,&byte2,&byte3,&byte4,&more) != 4)
 | 
	
		
			
				|  |  | -        return 0;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      if (byte1 > 255 || byte2 > 255 || byte3 > 255 || byte4 > 255)
 | 
	
		
			
				|  |  | -        return 0;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -      words[6] = (byte1<<8) | byte2;
 | 
	
		
			
				|  |  | -      words[7] = (byte3<<8) | byte4;
 | 
	
		
			
				|  |  | -      setWords += 2;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    i = 0;
 | 
	
		
			
				|  |  | -    while (src < eow) {
 | 
	
		
			
				|  |  | -      if (i > 7)
 | 
	
		
			
				|  |  | -        return 0;
 | 
	
		
			
				|  |  | -      if (TOR_ISXDIGIT(*src)) {
 | 
	
		
			
				|  |  | -        char *next;
 | 
	
		
			
				|  |  | -        ssize_t len;
 | 
	
		
			
				|  |  | -        long r = strtol(src, &next, 16);
 | 
	
		
			
				|  |  | -        if (next == NULL || next == src) {
 | 
	
		
			
				|  |  | -          /* The 'next == src' error case can happen on versions of openbsd
 | 
	
		
			
				|  |  | -           * which treat "0xfoo" as an error, rather than as "0" followed by
 | 
	
		
			
				|  |  | -           * "xfoo". */
 | 
	
		
			
				|  |  | -          return 0;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        len = *next == '\0' ? eow - src : next - src;
 | 
	
		
			
				|  |  | -        if (len > 4)
 | 
	
		
			
				|  |  | -          return 0;
 | 
	
		
			
				|  |  | -        if (len > 1 && !TOR_ISXDIGIT(src[1]))
 | 
	
		
			
				|  |  | -          return 0; /* 0x is not valid */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        tor_assert(r >= 0);
 | 
	
		
			
				|  |  | -        tor_assert(r < 65536);
 | 
	
		
			
				|  |  | -        words[i++] = (uint16_t)r;
 | 
	
		
			
				|  |  | -        setWords++;
 | 
	
		
			
				|  |  | -        src = next;
 | 
	
		
			
				|  |  | -        if (*src != ':' && src != eow)
 | 
	
		
			
				|  |  | -          return 0;
 | 
	
		
			
				|  |  | -        ++src;
 | 
	
		
			
				|  |  | -      } else if (*src == ':' && i > 0 && gapPos == -1) {
 | 
	
		
			
				|  |  | -        gapPos = i;
 | 
	
		
			
				|  |  | -        ++src;
 | 
	
		
			
				|  |  | -      } else if (*src == ':' && i == 0 && src+1 < eow && src[1] == ':' &&
 | 
	
		
			
				|  |  | -                 gapPos == -1) {
 | 
	
		
			
				|  |  | -        gapPos = i;
 | 
	
		
			
				|  |  | -        src += 2;
 | 
	
		
			
				|  |  | -      } else {
 | 
	
		
			
				|  |  | -        return 0;
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    if (setWords > 8 ||
 | 
	
		
			
				|  |  | -        (setWords == 8 && gapPos != -1) ||
 | 
	
		
			
				|  |  | -        (setWords < 8 && gapPos == -1))
 | 
	
		
			
				|  |  | -      return 0;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    if (gapPos >= 0) {
 | 
	
		
			
				|  |  | -      int nToMove = setWords - (dot ? 2 : 0) - gapPos;
 | 
	
		
			
				|  |  | -      int gapLen = 8 - setWords;
 | 
	
		
			
				|  |  | -      tor_assert(nToMove >= 0);
 | 
	
		
			
				|  |  | -      memmove(&words[gapPos+gapLen], &words[gapPos],
 | 
	
		
			
				|  |  | -              sizeof(uint16_t)*nToMove);
 | 
	
		
			
				|  |  | -      memset(&words[gapPos], 0, sizeof(uint16_t)*gapLen);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    for (i = 0; i < 8; ++i) {
 | 
	
		
			
				|  |  | -      out->s6_addr[2*i  ] = words[i] >> 8;
 | 
	
		
			
				|  |  | -      out->s6_addr[2*i+1] = words[i] & 0xff;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    return 1;
 | 
	
		
			
				|  |  | -  } else {
 | 
	
		
			
				|  |  | -    return -1;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -/** Similar behavior to Unix gethostbyname: resolve <b>name</b>, and set
 | 
	
		
			
				|  |  | - * *<b>addr</b> to the proper IP address, in host byte order.  Returns 0
 | 
	
		
			
				|  |  | - * on success, -1 on failure; 1 on transient failure.
 | 
	
		
			
				|  |  | - *
 | 
	
		
			
				|  |  | - * (This function exists because standard windows gethostbyname
 | 
	
		
			
				|  |  | - * doesn't treat raw IP addresses properly.)
 | 
	
		
			
				|  |  | - */
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -MOCK_IMPL(int,
 | 
	
		
			
				|  |  | -tor_lookup_hostname,(const char *name, uint32_t *addr))
 | 
	
		
			
				|  |  | -{
 | 
	
		
			
				|  |  | -  tor_addr_t myaddr;
 | 
	
		
			
				|  |  | -  int ret;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  if ((ret = tor_addr_lookup(name, AF_INET, &myaddr)))
 | 
	
		
			
				|  |  | -    return ret;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  if (tor_addr_family(&myaddr) == AF_INET) {
 | 
	
		
			
				|  |  | -    *addr = tor_addr_to_ipv4h(&myaddr);
 | 
	
		
			
				|  |  | -    return ret;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  return -1;
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  /** Hold the result of our call to <b>uname</b>. */
 | 
	
		
			
				|  |  |  static char uname_result[256];
 | 
	
		
			
				|  |  |  /** True iff uname_result is set. */
 |