+
+/**
+ * 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)
+{
+ int type = SOCK_STREAM;
+ int error, s;
+ struct addrinfo hints, *res0, *res;
+ char portbuf[10];
+ char *h, *cp;
+ int proxied = 0;
+ char buffer[1024];
+ char *proxy_user = NULL, *proxy_pass = NULL;
+
+ /* if we have a RSYNC_PROXY env variable then redirect our
+ * connetcion via a web proxy at the given address. */
+ h = getenv("RSYNC_PROXY");
+ proxied = h != NULL && *h != '\0';
+
+ if (proxied) {
+ strlcpy(buffer, h, sizeof buffer);
+
+ /* Is the USER:PASS@ prefix present? */
+ if ((cp = strrchr(buffer, '@')) != NULL) {
+ *cp++ = '\0';
+ /* The remainder is the HOST:PORT part. */
+ h = cp;
+
+ if ((cp = strchr(buffer, ':')) == NULL) {
+ rprintf(FERROR,
+ "invalid proxy specification: should be USER:PASS@HOST:PORT\n");
+ return -1;
+ }
+ *cp++ = '\0';
+
+ proxy_user = buffer;
+ proxy_pass = cp;
+ } else {
+ /* The whole buffer is the HOST:PORT part. */
+ h = buffer;
+ }
+
+ if ((cp = strchr(h, ':')) == NULL) {
+ rprintf(FERROR,
+ "invalid proxy specification: should be HOST:PORT\n");
+ return -1;
+ }
+ *cp++ = '\0';
+ strlcpy(portbuf, cp, sizeof portbuf);
+ if (verbose >= 2) {
+ rprintf(FINFO, "connection via http proxy %s port %s\n",
+ h, portbuf);
+ }
+ } else {
+ snprintf(portbuf, sizeof portbuf, "%d", port);
+ h = host;
+ }
+
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = af_hint;
+ hints.ai_socktype = type;
+ error = getaddrinfo(h, portbuf, &hints, &res0);
+ if (error) {
+ rprintf(FERROR, RSYNC_NAME ": getaddrinfo: %s %s: %s\n",
+ h, portbuf, gai_strerror(error));