+/**
+ * Try to set the local address for a newly-created socket. Return -1
+ * if this fails.
+ **/
+int try_bind_local(int s, int ai_family, int ai_socktype,
+ const char *bind_addr)
+{
+ int error;
+ struct addrinfo bhints, *bres_all, *r;
+
+ memset(&bhints, 0, sizeof bhints);
+ bhints.ai_family = ai_family;
+ bhints.ai_socktype = ai_socktype;
+ bhints.ai_flags = AI_PASSIVE;
+ if ((error = getaddrinfo(bind_addr, NULL, &bhints, &bres_all))) {
+ rprintf(FERROR, RSYNC_NAME ": getaddrinfo %s: %s\n",
+ bind_addr, gai_strerror(error));
+ return -1;
+ }
+
+ for (r = bres_all; r; r = r->ai_next) {
+ if (bind(s, r->ai_addr, r->ai_addrlen) == -1)
+ continue;
+ freeaddrinfo(bres_all);
+ return s;
+ }
+
+ /* no error message; there might be some problem that allows
+ * creation of the socket but not binding, perhaps if the
+ * machine has no ipv6 address of this name. */
+ freeaddrinfo(bres_all);
+ return -1;
+}
+
+/* connect() timeout handler based on alarm() */
+static RETSIGTYPE contimeout_handler(UNUSED(int val))
+{
+ connect_timeout = -1;
+}
+
+/**
+ * Open a socket to a tcp remote host with the specified port .
+ *
+ * Based on code from Warren. Proxy support by Stephen Rothwell.
+ * getaddrinfo() rewrite contributed by KAME.net.
+ *
+ * Now that we support IPv6 we need to look up the remote machine's
+ * address first, using @p af_hint to set a preference for the type
+ * of address. Then depending on whether it has v4 or v6 addresses we
+ * try to open a connection.
+ *
+ * The loop allows for machines with some addresses which may not be
+ * reachable, perhaps because we can't e.g. route ipv6 to that network
+ * but we can get ip4 packets through.
+ *
+ * @param bind_addr Local address to use. Normally NULL to bind
+ * the wildcard address.
+ *
+ * @param af_hint Address family, e.g. AF_INET or AF_INET6.
+ **/
+int open_socket_out(char *host, int port, const char *bind_addr,
+ int af_hint)