Preferred IP version sorts getaddrionf() results
diff --git a/CHANGES b/CHANGES
index e69e89b..80ac1f2 100644
--- a/CHANGES
+++ b/CHANGES
@@ -75,14 +75,22 @@
 	Tests: TRY_ADDRS_4 TRY_ADDRS_4_6
 	Feature recommended by Anand Buddhdev.
 
-	configure option --with-default-ipv allows to specify at build time if
-	IPv4, IPv6, or none of these is the preferred default.
+	configure option --enable-default-ipv allows to specify at build time if
+	IPv4, IPv6, or none of these is the preferred default; this is related
+	to environment variables SOCAT_PREFERRED_RESOLVE_IP and
+	SOCAT_DEFAULT_LISTEN_IP, and to Socat option -4, -6.
+	Furthermore, mechanism of IPv4 vs.IPv6 selection has been reworked.
+	When no IP version is preferred by these mechanism, passive Socat
+	addresses (LISTEN, RECV, RECVFROM) default to IPv6 because it might
+	support both versions (but checkout option ipv6-v6only).
+	For client addresses, when one of these mechanisms applies and name
+	resolution gives addresses of both IP versions, the addresses of the
+	preferred versions are tried first.
 
-	Socat options -4 and -6 have been reworked.
-	Tests: TCP_ENV6 TCP_DASH6
-
-	New option ai-addrconfig disables name resolution to protocol families
-	that are not configured on the computer (e.g. IPv6)
+	New option ai-addrconfig sets or unsets the AI_ADDRCONFIG flag of the
+	resolver to prevent name resolution to address families that are not
+	available in the network configuration. Default value is 1 in case the
+	resolver does not get an address family hint.
 
 	Flag AI_PASSIVE is now automatically applied for LISTEN, RECV, and
 	RECVFROM type addresses, and with bind option. In addition to its
diff --git a/config.h.in b/config.h.in
index 6342635..44e8f19 100644
--- a/config.h.in
+++ b/config.h.in
@@ -723,7 +723,7 @@
 
 #undef WITH_MSGLEVEL
 
-#undef WITH_DEFAULT_IPV 		/* default IP version: undef, "4", "6" */
+#undef WITH_DEFAULT_IPV 	/* default IP version: "0", "4", "6" */
 
 #define BUILD_DATE __DATE__ " " __TIME__
 
diff --git a/configure.ac b/configure.ac
index f5fae83..1388d59 100644
--- a/configure.ac
+++ b/configure.ac
@@ -821,12 +821,12 @@
 	       [AC_DEFINE(WITH_MSGLEVEL,0) AC_MSG_RESULT(debug)])
 
 AC_MSG_CHECKING(default IP version)
-AC_ARG_ENABLE(ip-version, [  --enable-ip-version=N     set default IP version to undef, "4", "6"],
+AC_ARG_ENABLE(default-ipv, [  --enable-default-ipv=N     set default/preferred IP version to "0" (none), "4", "6"],
 	      [case "$enableval" in
-	       "") AC_DEFINE(WITH_DEFAULT_IPV, 0) AC_MSG_RESULT("0");;
+	       "") AC_DEFINE(WITH_DEFAULT_IPV, '0') AC_MSG_RESULT("0");;
 	       4) AC_DEFINE(WITH_DEFAULT_IPV, '4') AC_MSG_RESULT("4");;
 	       6) AC_DEFINE(WITH_DEFAULT_IPV, '6') AC_MSG_RESULT("6");;
-	       *) AC_DEFINE(WITH_DEFAULT_IPV, 0) AC_MSG_RESULT("0");;
+	       *) AC_DEFINE(WITH_DEFAULT_IPV, '0') AC_MSG_RESULT("0");;
 	       esac],
 	       [AC_DEFINE(WITH_DEFAULT_IPV, '0') AC_MSG_RESULT("0")])
 
diff --git a/doc/socat.yo b/doc/socat.yo
index 8da8ac7..909fd77 100644
--- a/doc/socat.yo
+++ b/doc/socat.yo
@@ -2244,7 +2244,7 @@
 dit(bf(tt(ai-addrconfig[=0|1]))), dit(bf(tt(addrconfig[=0|1])))
    Sets or unsets the AI_ADDRCONFIG flag to prevent name resolution to address
    families that are not configured (e.g. IPv6). Default value is 1 in case the
-   resolver does not get an address family hint.
+   resolver does not get an address family hint from Socat address or defaults.
 dit(bf(tt(ai-passive[=0|1]))), dit(bf(tt(passive[=0|1])))
    Sets of unsets the AI_ADDRCONFIG flag for code(getaddrinfo)) calls. Default
    is 1 for LISTEN, RECV, and RECVFROM type addresses, and with
diff --git a/test.sh b/test.sh
index dd80bc1..f459065 100755
--- a/test.sh
+++ b/test.sh
@@ -2483,20 +2483,29 @@
 echo "$da" |$CMD2 >>"$tf" 2>>"${te}2"
 if [ $? -ne 0 ]; then
    $PRINTF "$FAILED: $TRACE $SOCAT:\n"
-   echo "$CMD1 &"
+   echo "SOCAT_DEFAULT_LISTEN_IP=6 $CMD1 &"
+   cat "${te}1" >&2
    echo "$CMD2"
-   cat "${te}1" "${te}2"
+   cat "${te}2" >&2
    numFAIL=$((numFAIL+1))
    listFAIL="$listFAIL $N"
 elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
-   $PRINTF "$FAILED: diff:\n"
-   cat "$tdiff"
+   $PRINTF "$FAILED (diff):\n"
+   echo "SOCAT_DEFAULT_LISTEN_IP=6 $CMD1 &"
+   cat "${te}1" >&2
+   echo "$CMD2"
+   cat "${te}2" >&2
+   echo "// diff:" >&2
+   cat "$tdiff" >&2
    numFAIL=$((numFAIL+1))
    listFAIL="$listFAIL $N"
 else
-   $PRINTF "$OK\n"
-   if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi
-   numOK=$((numOK+1))
+    $PRINTF "$OK\n"
+    if [ "$VERBOSE" ]; then echo "$CMD1 &"; fi
+    if [ "$DEBUG" ];   then cat "${te}1" >&2; fi
+    if [ "$VERBOSE" ]; then echo "$CMD2"; fi
+    if [ "$DEBUG" ];   then cat "${te}2" >&2; fi
+    numOK=$((numOK+1))
 fi
 kill $pid 2>/dev/null; wait
 fi
@@ -3870,26 +3879,30 @@
 da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')"
 # we have a normal tcp echo listening - so the socks header must appear in answer
 newport tcp6 	# provide free port number in $PORT
-CMD2="$TRACE $SOCAT $opts TCP6-L:$PORT,$REUSEADDR exec:\"./socks4echo.sh\""
-CMD="$TRACE $SOCAT $opts - socks4:$LOCALHOST6:32.98.76.54:32109,socksport=$PORT",socksuser="nobody"
+CMD0="$TRACE $SOCAT $opts TCP6-L:$PORT,$REUSEADDR exec:\"./socks4echo.sh\""
+CMD1="$TRACE $SOCAT $opts - socks4:$LOCALHOST6:32.98.76.54:32109,socksport=$PORT",socksuser="nobody"
 printf "test $F_n $TEST... " $N
-eval "$CMD2 2>\"${te}1\" &"
+eval "$CMD0 2>\"${te}0\" &"
 pid=$!	# background process id
 waittcp6port $PORT 1
-echo "$da" |$CMD >$tf 2>"${te}2"
-if ! echo "$da" |diff - "$tf" >"$tdiff"; then
+echo "$da" |$CMD1 >${tf}1 2>"${te}1"
+if ! echo "$da" |diff - "${tf}1" >"$tdiff"; then
     $PRINTF "$FAILED: $TRACE $SOCAT:\n"
-    echo "$CMD2 &"
-    echo "$CMD"
-    cat "${te}1"
-    cat "${te}2"
-    cat "$tdiff"
+    echo "$CMD0 &"
+    cat "${te}0" >&2
+    echo "$CMD1"
+    cat "${te}1" >&2
+    echo "// diff:" >&2
+    cat "$tdiff" >&2
     numFAIL=$((numFAIL+1))
     listFAIL="$listFAIL $N"
 else
-   $PRINTF "$OK\n"
-   if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi
-   numOK=$((numOK+1))
+    $PRINTF "$OK\n"
+    if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
+    if [ "$DEBUG" ];   then cat "${te}0" >&2; fi
+    if [ "$VERBOSE" ]; then echo "$CMD1"; fi
+    if [ "$DEBUG" ];   then cat "${te}1" >&2; fi
+    numOK=$((numOK+1))
 fi
 kill $pid 2>/dev/null
 wait
@@ -7885,24 +7898,34 @@
 rc2=$?
 kill $pid0 2>/dev/null; wait
 if [ $rc1 != 0 -o $rc2 != 0 ]; then
-    $PRINTF "$FAILED\n"
+    $PRINTF "$FAILED (client(s) failed)\n"
     echo "$CMD0 &"
+    cat "${te}0" >&2
     echo "$CMD1"
-    cat "${te}0"
-    cat "${te}1"
-    cat "${te}2"
+    cat "${te}1" >&2
+    echo "$CMD1"
+    cat "${te}2" >&2
     numFAIL=$((numFAIL+1))
     listFAIL="$listFAIL $N"
 elif echo "$da" |diff - "${tf}" >"$tdiff"; then
     $PRINTF "$OK\n"
+    if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
+    if [ "$DEBUG" ];   then cat "${te}0" >&2; fi
+    if [ "$VERBOSE" ]; then echo "$CMD1"; fi
+    if [ "$DEBUG" ];   then cat "${te}1" >&2; fi
+    if [ "$VERBOSE" ]; then echo "$CMD2"; fi
+    if [ "$DEBUG" ];   then cat "${te}2" >&2; fi
     numOK=$((numOK+1))
 else
-    $PRINTF "$FAILED\n"
+    $PRINTF "$FAILED (diff)\n"
     echo "$CMD0 &"
+    cat "${te}0" >&2
     echo "$CMD1"
-    cat "${te}0"
-    cat "${te}1"
-    cat "${tdiff}"
+    cat "${te}1" >&2
+    echo "$CMD2"
+    cat "${te}2" >&2
+    echo "// diff:" >&2
+    cat "${tdiff}" >&2
     numFAIL=$((numFAIL+1))
     listFAIL="$listFAIL $N"
 fi
diff --git a/xio-ip.c b/xio-ip.c
index 71933e8..fb6c1bc 100644
--- a/xio-ip.c
+++ b/xio-ip.c
@@ -112,11 +112,11 @@
 
 
 int xioinit_ip(
-	struct single *sfd,
-	int *pf)
+	int *pf,
+	char ipv)
 {
 	if (*pf == PF_UNSPEC) {
-		switch (xioparms.preferred_ip) {
+		switch (ipv) {
 		case '0': *pf = PF_UNSPEC; break;
 #if WITH_IP4
 		case '4': *pf = PF_INET; break;
@@ -254,7 +254,7 @@
 	}
 	if (error_num == EAI_SERVICE && protocol != 0) {
 	   if (hints.ai_protocol == 0) {
-	      Error7("getaddrinfo\"%s\", \"%s\", {%d,%d,%d,%d}, {}): %s",
+	      Error7("getaddrinfo\"%s\", \"%s\", {0x%02x,%d,%d,%d}, {}): %s",
 		     node?node:"NULL", service?service:"NULL",
 		     hints.ai_flags, hints.ai_family,
 		     hints.ai_socktype, hints.ai_protocol,
@@ -290,7 +290,7 @@
       while (record) {
 	 char buff[256/*!*/];
 	 sockaddr_info(record->ai_addr, record->ai_addrlen, buff, sizeof(buff));
-	 Debug5("getaddrinfo() -> flags=%d family=%d socktype=%d protocol=%d addr=%s", record->ai_flags, record->ai_family, record->ai_socktype, record->ai_protocol, buff);
+	 Debug5("getaddrinfo() -> flags=0x%02x family=%d socktype=%d protocol=%d addr=%s", record->ai_flags, record->ai_family, record->ai_socktype, record->ai_protocol, buff);
 	 record = record->ai_next;
       }
 #endif /* WITH_MSGLEVEL <= E_DEBUG */
@@ -425,7 +425,7 @@
 
 /* A simple resolver interface that just returns one address,
    the first found by calling xiogetaddrinfo().
-   family may be AF_INET, AF_INET6, or AF_UNSPEC.
+   family may be AF_INET, AF_INET6, or AF_UNSPEC;
    Returns -1 when an error occurred or when no result found.
 */
 int xioresolve(const char *node, const char *service,
@@ -434,6 +434,7 @@
 	       const int ai_flags[2], const unsigned long res_opts[2])
 {
    struct addrinfo *res = NULL;
+   struct addrinfo *aip;
    int rc;
 
    rc = xiogetaddrinfo(node, service, family, socktype, protocol,
@@ -455,8 +456,23 @@
    if (res->ai_next != NULL) {
       Info4("xioresolve(node=\"%s\", service=%s%s%s, ...): More than one address found", node?node:"NULL", service?"\"":"", service?service:"NULL", service?"\"":"");
    }
-   memcpy(addr, res->ai_addr, res->ai_addrlen);
-   *addrlen = res->ai_addrlen;
+
+   aip = res;
+   if (ai_flags[0] & AI_PASSIVE && family == PF_UNSPEC) {
+      /* We select the first IPv6 address, if available,
+	 because this might accept IPv4 connections too */
+      struct addrinfo *aip = res;
+      while (aip != NULL) {
+	 if (aip->ai_family == PF_INET6)
+	    break;
+	 aip = aip->ai_next;
+      }
+      if (aip == NULL)
+	 aip = res;
+   }
+
+   memcpy(addr, aip->ai_addr, aip->ai_addrlen);
+   *addrlen = aip->ai_addrlen;
    xiofreeaddrinfo(res);
    return 0;
 }
diff --git a/xio-ip.h b/xio-ip.h
index b12d4d9..4c63f7a 100644
--- a/xio-ip.h
+++ b/xio-ip.h
@@ -42,7 +42,7 @@
 extern const struct optdesc opt_res_stayopen;
 extern const struct optdesc opt_res_dnsrch;
 
-extern int xioinit_ip(struct single *sfd, int *pf);
+extern int xioinit_ip(int *pf, char ipv);
 
 extern int xiogetaddrinfo(const char *node, const char *service, int family, int socktype, int protocol, struct addrinfo **res, const int ai_flags[2], const unsigned long res_opts[2]);
 extern void xiofreeaddrinfo(struct addrinfo *res);
diff --git a/xio-ipapp.c b/xio-ipapp.c
index 93f0e52..3c671da 100644
--- a/xio-ipapp.c
+++ b/xio-ipapp.c
@@ -38,11 +38,13 @@
    int level;
    int result;
 
+   struct addrinfo **ai_sorted;
+   int i;
+
    if (argc != 3) {
       Error2("%s: wrong number of parameters (%d instead of 2)", argv[0], argc-1);
    }
 
-   xioinit_ip(xfd, &pf);
    xfd->howtoend = END_SHUTDOWN;
 
    if (applyopts_single(xfd, opts, PH_INIT) < 0)  return -1;
@@ -69,18 +71,32 @@
       Info("starting connect loop");
    }
 
+   /* Count addrinfo entries */
+   themp = themlist;
+   i = 0;
+   while (themp != NULL) {
+      ++i;
+      themp = themp->ai_next;
+   }
+   ai_sorted = Calloc((i+1), sizeof(struct addrinfo *));
+   if (ai_sorted == NULL)
+      return STAT_RETRYLATER;
+   /* Generate a list of addresses sorted by preferred ip version */
+   _xio_sort_ip_addresses(themlist, ai_sorted);
+
    do {	/* loop over retries, and forks */
 
-      themp = themlist;
-      /* Loop over themlist */
+      /* Loop over themlist - no, over ai_sorted */
       result = STAT_RETRYLATER;
+      i = 0;
+      themp = ai_sorted[i++];
       while (themp != NULL) {
 	 Notice1("opening connection to %s",
 		 sockaddr_info(themp->ai_addr, themp->ai_addrlen,
 			       infobuff, sizeof(infobuff)));
 
 #if WITH_RETRY
-	 if (xfd->forever || xfd->retry || themp->ai_next != NULL) {
+	 if (xfd->forever || xfd->retry || ai_sorted[i] != NULL) {
 	    level = E_INFO;
          } else
 #endif /* WITH_RETRY */
@@ -94,7 +110,7 @@
 			  lowport, level);
        if (result == STAT_OK)
 	  break;
-       themp = themp->ai_next;
+       themp = ai_sorted[i++];
        if (themp == NULL) {
 	  result = STAT_RETRYLATER;
        }
@@ -114,7 +130,7 @@
 	 }
 #endif /* WITH_RETRY */
       default:
-	 xiofreeaddrinfo(themlist);
+	 free(ai_sorted);
 	 free(opts0);free(opts);
 	 return result;
       }
@@ -131,7 +147,7 @@
 	    if (xfd->forever || --xfd->retry) {
 	       Nanosleep(&xfd->intervall, NULL); continue;
 	    }
-	    xiofreeaddrinfo(themlist);
+	    free(ai_sorted);
 	    free(opts0);
 	    return STAT_RETRYLATER;
 	 }
@@ -154,13 +170,14 @@
       }
    } while (true);
    /* only "active" process breaks (master without fork, or child) */
+   free(ai_sorted);
    xiofreeaddrinfo(themlist);
 
    if ((result = _xio_openlate(xfd, opts)) < 0) {
 	   free(opts0);free(opts);
       return result;
    }
-   free(opts0);free(opts);
+   free(opts0); free(opts);
    return 0;
 }
 
@@ -191,12 +208,14 @@
 
    retropt_socket_pf(opts, pf);
 
-   if ((result =
+   if (hostname != NULL || portname != NULL) {
+    if ((result =
 	xiogetaddrinfo(hostname, portname,
 		       *pf, socktype, protocol,
 		       themlist, ai_flags, res_opts))
        != STAT_OK) {
       return STAT_NORETRY;	/*! STAT_RETRYLATER? */
+    }
    }
 
    applyopts(-1, opts, PH_EARLY);
@@ -299,7 +318,7 @@
       Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
    }
 
-   xioinit_ip(&xfd->stream, &pf);
+   xioinit_ip(&pf, xioparms.default_ip);
    if (pf == PF_UNSPEC) {
 #if WITH_IP4 && WITH_IP6
       switch (xioparms.default_ip) {
@@ -338,4 +357,60 @@
 }
 #endif /* WITH_IP4 && WITH_TCP && WITH_LISTEN */
 
+
+/* Sort the records of an addrinfo list themp (as returned by getaddrinfo),
+   return the sorted list in the array ai_sorted (takes at most n entries
+   including the terminating NULL)
+   Returns 0 on success. */
+int _xio_sort_ip_addresses(
+	struct addrinfo *themlist,
+	struct addrinfo **ai_sorted)
+{
+	struct addrinfo *themp;
+	int i;
+	int ipv[3];
+	int ipi = 0;
+
+	/* Make a simple array of IP version preferences */
+	switch (xioparms.preferred_ip) {
+	case '0':
+		ipv[0] = PF_UNSPEC;
+		ipv[1] = -1;
+		break;
+	case '4':
+		ipv[0] = PF_INET;
+		ipv[1] = PF_INET6;
+		ipv[2] = -1;
+		break;
+	case '6':
+		ipv[0] = PF_INET6;
+		ipv[1] = PF_INET;
+		ipv[2] = -1;
+		break;
+	default:
+		Error("INTERNAL: undefined preferred_ip value");
+		return -1;
+	}
+
+	/* Create the sorted list */
+	ipi = 0;
+	i = 0;
+	while (ipv[ipi] >= 0) {
+		themp = themlist;
+		while (themp != NULL) {
+			if (ipv[ipi] == PF_UNSPEC) {
+				ai_sorted[i] = themp;
+				++i;
+			} else if (ipv[ipi] == themp->ai_family) {
+				ai_sorted[i] = themp;
+				++i;
+			}
+			themp = themp->ai_next;
+		}
+		++ipi;
+	}
+	ai_sorted[i] = NULL;
+	return 0;
+}
+
 #endif /* WITH_TCP || WITH_UDP */
diff --git a/xio-ipapp.h b/xio-ipapp.h
index 1767fff..fa25c47 100644
--- a/xio-ipapp.h
+++ b/xio-ipapp.h
@@ -28,5 +28,6 @@
 			 groups_t groups, int socktype,
 				 int ipproto, int protname);
 extern int _xioopen_ipapp_listen_prepare(struct opt *opts, struct opt **opts0, const char *portname, int *pf, int ipproto, const int ai_flags[2], const unsigned long res_opts[2], union sockaddr_union *us, socklen_t *uslen, int socktype);
+extern int _xio_sort_ip_addresses(struct addrinfo *themlist, struct addrinfo **ai_sorted);
 
 #endif /* !defined(__xio_ipapp_h_included) */
diff --git a/xio-openssl.c b/xio-openssl.c
index 42197b7..bcf8c2e 100644
--- a/xio-openssl.c
+++ b/xio-openssl.c
@@ -252,7 +252,9 @@
    struct addrinfo *themlist, *themp;
    bool needbind = false;
    bool lowport = false;
-   int level;
+   int level = E_ERROR;
+   struct addrinfo **ai_sorted;
+   int i;
    SSL_CTX* ctx;
    bool opt_ver = true;	/* verify peer certificate */
    char *opt_cert = NULL;	/* file name of client certificate */
@@ -280,7 +282,6 @@
       return STAT_NORETRY;
    }
 
-   xioinit_ip(xfd, &pf);
    xfd->howtoend = END_SHUTDOWN;
    if (applyopts_single(xfd, opts, PH_INIT) < 0)  return -1;
    applyopts(-1, opts, PH_INIT);
@@ -340,19 +341,34 @@
       Info("starting connect loop");
    }
 
+   /* Count addrinfo entries */
+   themp = themlist;
+   i = 0;
+   while (themp != NULL) {
+      ++i;
+      themp = themp->ai_next;
+   }
+   ai_sorted = Calloc((i+1), sizeof(struct addrinfo *));
+   if (ai_sorted == NULL)
+      return STAT_RETRYLATER;
+   /* Generate a list of addresses sorted by preferred ip version */
+   _xio_sort_ip_addresses(themlist, ai_sorted);
+
    do {	/* loop over failed connect and SSL handshake attempts */
 
-#if WITH_RETRY
-      if (xfd->forever || xfd->retry) {
-	 level = E_INFO;
-      } else
-#endif /* WITH_RETRY */
-	 level = E_ERROR;
-
-      themp = themlist;
-      /* loop over themlist */
+      /* Loop over ai_sorted list */
+      i = 0;
+      themp = ai_sorted[i++];
       while (themp != NULL) {
-       /* This cannot fork because we retrieved fork option above */
+
+#if WITH_RETRY
+	 if (xfd->forever || xfd->retry || ai_sorted[i] != NULL) {
+	    level = E_INFO;
+	 } else
+#endif /* WITH_RETRY */
+	    level = E_ERROR;
+
+	 /* This cannot fork because we retrieved fork option above */
        result =
 	 _xioopen_connect(xfd,
 			  needbind?us:NULL, uslen,
@@ -360,7 +376,7 @@
 			  opts, pf?pf:themp->ai_addr->sa_family, socktype, ipproto, lowport, level);
        if (result == STAT_OK)
 	  break;
-       themp = themp->ai_next;
+       themp = ai_sorted[i++];
        if (themp == NULL) {
 	  result = STAT_RETRYLATER;
       }
@@ -378,16 +394,16 @@
 	    --xfd->retry;
 	    continue;
 	 }
-	 xiofreeaddrinfo(themlist);
+	 free(ai_sorted);
 	 return STAT_NORETRY;
 #endif /* WITH_RETRY */
       default:
-	 xiofreeaddrinfo(themlist);
+	 free(ai_sorted);
 	 return result;
       }
       /*! isn't this too early? */
       if ((result = _xio_openlate(xfd, opts)) < 0) {
-	 xiofreeaddrinfo(themlist);
+	 free(ai_sorted);
 	 return result;
       }
 
@@ -449,6 +465,7 @@
 #endif /* WITH_RETRY */
       break;
    } while (true);	/* drop out on success */
+   free(ai_sorted);
    xiofreeaddrinfo(themlist);
 
    openssl_conn_loginfo(xfd->para.openssl.ssl);
@@ -572,7 +589,6 @@
       return STAT_NORETRY;
    }
 
-   xioinit_ip(xfd, &pf);
 #if WITH_IP4 && WITH_IP6
    switch (xioparms.default_ip) {
    case '4': pf = PF_INET; break;
diff --git a/xio-proxy.c b/xio-proxy.c
index 2753d70..b6b4c64 100644
--- a/xio-proxy.c
+++ b/xio-proxy.c
@@ -93,6 +93,8 @@
    union sockaddr_union us_sa,   *us = &us_sa;
    socklen_t uslen = sizeof(us_sa);
    struct addrinfo *themlist, *themp;
+   struct addrinfo **ai_sorted;
+   int i;
    const char *proxyname; char *proxyport = NULL;
    const char *targetname, *targetport;
    int ipproto = IPPROTO_TCP;
@@ -110,7 +112,6 @@
    targetname = argv[2];
    targetport = argv[3];
 
-   xioinit_ip(xfd, &pf);
    xfd->howtoend = END_SHUTDOWN;
    if (applyopts_single(xfd, opts, PH_INIT) < 0)  return -1;
    applyopts(-1, opts, PH_INIT);
@@ -128,32 +129,53 @@
    result = _xioopen_proxy_prepare(proxyvars, opts, targetname, targetport,
 				   xfd->para.socket.ip.ai_flags,
 				   xfd->para.socket.ip.res_opts);
-   if (result != STAT_OK)  return result;
+   if (result != STAT_OK)
+      return result;
 
-   result =
+   Notice4("opening connection to %s:%u via proxy %s:%s",
+      proxyvars->targetaddr, proxyvars->targetport, proxyname, proxyport);
+
+   i = 0;
+   do {      /* loop over retries (failed connect and proxy-request attempts) */
+
+    level = E_INFO;
+
+    result =
       _xioopen_ipapp_prepare(opts, &opts0, proxyname, proxyport,
 			     &pf, ipproto,
 			     xfd->para.socket.ip.ai_flags,
 			     xfd->para.socket.ip.res_opts,
 			     &themlist, us, &uslen,
 			     &needbind, &lowport, socktype);
-   if (result != STAT_OK)  return result;
+   if (result != STAT_OK)
+      return result;
 
-   Notice4("opening connection to %s:%u via proxy %s:%s",
-	   proxyvars->targetaddr, proxyvars->targetport, proxyname, proxyport);
-
-   do {	/* loop over failed connect and proxy connect attempts */
-
-#if WITH_RETRY
-      if (xfd->forever || xfd->retry) {
-         level = E_INFO;
-      } else
-#endif /* WITH_RETRY */
-         level = E_ERROR;
-
+    /* Count addrinfo entries */
       themp = themlist;
-      /* Loop over themlist */
+      i = 0;
       while (themp != NULL) {
+	 ++i;
+	 themp = themp->ai_next;
+      }
+      ai_sorted = Calloc((i+1), sizeof(struct addrinfo *));
+      if (ai_sorted == NULL)
+	 return STAT_RETRYLATER;
+      /* Generate a list of addresses sorted by preferred ip version */
+      _xio_sort_ip_addresses(themlist, ai_sorted);
+
+      /* Loop over themlist */
+      i = 0;
+      themp = ai_sorted[i++];
+      while (themp != NULL) {
+	 Notice4("opening connection to %s:%u via proxy %s:%s",
+		 proxyvars->targetaddr, proxyvars->targetport, proxyname, proxyport);
+#if WITH_RETRY
+	 if (xfd->forever || xfd->retry || ai_sorted[i] != NULL) {
+	    level = E_INFO;
+	 } else
+#endif /* WITH_RETRY */
+	    level = E_ERROR;
+
    result =
       _xioopen_connect(xfd,
 		       needbind?us:NULL, sizeof(*us),
@@ -161,7 +183,7 @@
 		       opts, pf?pf:themp->ai_family, socktype, IPPROTO_TCP, lowport, level);
        if (result == STAT_OK)
 	  break;
-       themp = themp->ai_next;
+       themp = ai_sorted[i++];
        if (themp == NULL) {
 	  result = STAT_RETRYLATER;
       }
@@ -170,18 +192,19 @@
 #if WITH_RETRY
       case STAT_RETRYLATER:
       case STAT_RETRYNOW:
-	 if (xfd->forever || xfd->retry--) {
-	    if (result == STAT_RETRYLATER)  Nanosleep(&xfd->intervall, NULL);
+	 if (xfd->forever || xfd->retry) {
+	    --xfd->retry;
+	    if (result == STAT_RETRYLATER)
+	       Nanosleep(&xfd->intervall, NULL);
 	    continue;
 	 }
 #endif /* WITH_RETRY */
       default:
+	 free(ai_sorted);
 	 xiofreeaddrinfo(themlist);
 	 return result;
       }
       }
-      xiofreeaddrinfo(themlist);
-      applyopts(xfd->fd, opts, PH_ALL);
 
       if ((result = _xio_openlate(xfd, opts)) < 0)
 	 return result;
diff --git a/xio-rawip.c b/xio-rawip.c
index a314a75..2613bfa 100644
--- a/xio-rawip.c
+++ b/xio-rawip.c
@@ -74,7 +74,7 @@
       return STAT_NORETRY;
    }
 
-   xioinit_ip(&xxfd->stream, &pf);
+   xioinit_ip(&pf, xioparms.preferred_ip);
    if ((result = _xioopen_rawip_sendto(argv[1], argv[2], opts, xioflags, xxfd,
 				       groups, &pf)) != STAT_OK) {
       return result;
@@ -165,7 +165,7 @@
       return STAT_NORETRY;
    }
 
-   xioinit_ip(xfd, &pf);
+   xioinit_ip(&pf, xioparms.preferred_ip);
    if ((result =
 	_xioopen_rawip_sendto(argv[1], argv[2], opts, xioflags, xxfd,
 				groups, &pf)) != STAT_OK) {
@@ -220,7 +220,7 @@
       return STAT_NORETRY;
    }
 
-   xioinit_ip(&xfd->stream, &pf);
+   xioinit_ip(&pf, xioparms.default_ip);
    if ((ipproto = strtoul(protname, &garbage, 0)) >= 256) {
       Error2("xioopen_rawip_recvfrom(\"%s\",,): protocol number exceeds 255 (%u)",
 	     protname, ipproto);
@@ -284,7 +284,7 @@
       return STAT_NORETRY;
    }
 
-   xioinit_ip(&xfd->stream, &pf);
+   xioinit_ip(&pf, xioparms.default_ip);
    if ((ipproto = strtoul(protname, &garbage, 0)) >= 256) {
       Error2("xioopen_rawip_recv(\"%s\",,): protocol number exceeds 255 (%u)",
 	     protname, ipproto);
diff --git a/xio-socks.c b/xio-socks.c
index 77e5312..26d49ec 100644
--- a/xio-socks.c
+++ b/xio-socks.c
@@ -54,6 +54,8 @@
    union sockaddr_union us_sa,  *us = &us_sa;
    socklen_t uslen = sizeof(us_sa);
    struct addrinfo *themlist, *themp;
+   struct addrinfo **ai_sorted;
+   int i;
    bool needbind = false;
    bool lowport = false;
    char infobuff[256];
@@ -72,7 +74,6 @@
    targetname = argv[2];
    targetport = argv[3];
 
-   xioinit_ip(xfd, &pf);
    xfd->howtoend = END_SHUTDOWN;
    if (applyopts_single(xfd, opts, PH_INIT) < 0)  return -1;
    applyopts(-1, opts, PH_INIT);
@@ -82,28 +83,39 @@
    retropt_bool(opts, OPT_FORK, &dofork);
 
    result = _xioopen_socks4_prepare(targetport, opts, &socksport, sockhead, &buflen);
-   if (result != STAT_OK)  return result;
-   result =
-      _xioopen_ipapp_prepare(opts, &opts0, sockdname, socksport,
-			     &pf, ipproto,
-			     xfd->para.socket.ip.ai_flags,
-			     xfd->para.socket.ip.res_opts,
-			     &themlist, us, &uslen,
-			     &needbind, &lowport, socktype);
+   if (result != STAT_OK)
+      return result;
 
    Notice5("opening connection to %s:%u via socks4 server %s:%s as user \"%s\"",
 	   targetname,
 	   ntohs(sockhead->port),
 	   sockdname, socksport, sockhead->userid);
 
-   do {	/* loop over failed connect and socks-request attempts */
+   i = 0;
+   do {	/* loop over retries (failed connect and socks-request attempts) */
 
-#if WITH_RETRY
-      if (xfd->forever || xfd->retry) {
-	 level = E_INFO;
-      } else
-#endif /* WITH_RETRY */
-	 level = E_ERROR;
+      level = E_INFO;
+
+      result =
+	 _xioopen_ipapp_prepare(opts, &opts0, sockdname, socksport,
+				&pf, ipproto,
+				xfd->para.socket.ip.ai_flags,
+				xfd->para.socket.ip.res_opts,
+				&themlist, us, &uslen,
+				&needbind, &lowport, socktype);
+
+      /* Count addrinfo entries */
+      themp = themlist;
+      i = 0;
+      while (themp != NULL) {
+	 ++i;
+	 themp = themp->ai_next;
+      }
+      ai_sorted = Calloc((i+1), sizeof(struct addrinfo *));
+      if (ai_sorted == NULL)
+	 return STAT_RETRYLATER;
+      /* Generate a list of addresses sorted by preferred ip version */
+      _xio_sort_ip_addresses(themlist, ai_sorted);
 
       /* we try to resolve the target address _before_ connecting to the socks
 	 server: this avoids unnecessary socks connects and timeouts */
@@ -124,41 +136,51 @@
 	 return result;
       }
 
-      themp = themlist;
       /* loop over themlist */
+      i = 0;
+      themp = ai_sorted[i++];
       while (themp != NULL) {
 	 Notice1("opening connection to %s",
 		 sockaddr_info(themp->ai_addr, themp->ai_addrlen,
 			       infobuff, sizeof(infobuff)));
+#if WITH_RETRY
+	 if (xfd->forever || xfd->retry || ai_sorted[i] != NULL) {
+	    level = E_INFO;
+	 } else
+#endif /* WITH_RETRY */
+	    level = E_ERROR;
+
       /* this cannot fork because we retrieved fork option above */
-      result =
-	 _xioopen_connect(xfd,
-			  needbind?us:NULL, sizeof(*us),
-			  themp->ai_addr, themp->ai_addrlen,
-			  opts, pf?pf:themp->ai_family, socktype, IPPROTO_TCP, lowport, level);
-      if (result == STAT_OK)
-	 break;
-      themp = themp->ai_next;
-       if (themp == NULL) {
-	  result = STAT_RETRYLATER;
+	 result =
+	    _xioopen_connect(xfd,
+			     needbind?us:NULL, sizeof(*us),
+			     themp->ai_addr, themp->ai_addrlen,
+			     opts, pf?pf:themp->ai_family, socktype, IPPROTO_TCP,
+			     lowport, level);
+	 if (result == STAT_OK)
+	    break;
+	 themp = ai_sorted[i++];
+	 if (themp == NULL) {
+	    result = STAT_RETRYLATER;
+	 }
       }
       switch (result) {
       case STAT_OK: break;
 #if WITH_RETRY
       case STAT_RETRYLATER:
       case STAT_RETRYNOW:
-	 if (xfd->forever || xfd->retry--) {
-	    if (result == STAT_RETRYLATER)  Nanosleep(&xfd->intervall, NULL);
+	 if (xfd->forever || xfd->retry) {
+	    --xfd->retry;
+	    if (result == STAT_RETRYLATER)
+	       Nanosleep(&xfd->intervall, NULL);
 	    continue;
 	 }
 #endif /* WITH_RETRY */
       default:
+	 free(ai_sorted);
 	 xiofreeaddrinfo(themlist);
 	 return result;
       }
-      }
-      xiofreeaddrinfo(themlist);
-      applyopts(xfd->fd, opts, PH_ALL);
 
       if ((result = _xio_openlate(xfd, opts)) < 0)
 	 return result;
diff --git a/xio-udp.c b/xio-udp.c
index aaba4d3..a6e31b2 100644
--- a/xio-udp.c
+++ b/xio-udp.c
@@ -297,7 +297,7 @@
       Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
    }
 
-   xioinit_ip(&xfd->stream, &pf);
+   xioinit_ip(&pf, xioparms.default_ip);
    if (pf == PF_UNSPEC) {
 #if WITH_IP4 && WITH_IP6
       switch (xioparms.default_ip) {
@@ -354,7 +354,7 @@
       return STAT_NORETRY;
    }
 
-   xioinit_ip(&xfd->stream, &pf);
+   //xioinit_ip(&pf, xioparms.preferred_ip);
    retropt_socket_pf(opts, &pf);
    if ((result = _xioopen_udp_sendto(argv[1], argv[2], opts, xioflags, xfd,
 				     groups, pf, socktype, ipproto))
@@ -451,7 +451,7 @@
       return STAT_NORETRY;
    }
 
-   xioinit_ip(xfd, &pf);
+   //xioinit_ip(&pf, xioparms.preferred_ip);
    if ((hostname = strdup(argv[1])) == NULL) {
       Error1("strdup(\"%s\"): out of memory", argv[1]);
       return STAT_RETRYLATER;
@@ -516,7 +516,7 @@
       return STAT_NORETRY;
    }
 
-   xioinit_ip(&xfd->stream, &pf);
+   xioinit_ip(&pf, xioparms.default_ip);
    xfd->stream.howtoend = END_NONE;
    retropt_socket_pf(opts, &pf);
    if (pf == PF_UNSPEC) {
@@ -541,8 +541,7 @@
 
    if ((result =
 	xioresolve(NULL, argv[1], pf, socktype, ipproto, &us, &uslen,
-		   ai_flags2,
-		   xfd->stream.para.socket.ip.res_opts))
+		   ai_flags2, xfd->stream.para.socket.ip.res_opts))
        != STAT_OK) {
       return result;
    }
@@ -602,7 +601,7 @@
       return STAT_NORETRY;
    }
 
-   xioinit_ip(&xfd->stream, &pf);
+   //xioinit_ip(&pf, xioparms.default_ip);
    retropt_socket_pf(opts, &pf);
    if (pf == PF_UNSPEC) {
 #if WITH_IP4 && WITH_IP6
diff --git a/xioinitialize.c b/xioinitialize.c
index ec06c7b..6b7161a 100644
--- a/xioinitialize.c
+++ b/xioinitialize.c
@@ -95,9 +95,11 @@
 	 switch (preferred_ip[0]) {
 	 case '4':
 	 case '6':
-	    xioparms.preferred_ip = preferred_ip[0]; break;
+	    xioparms.preferred_ip = preferred_ip[0];
+	    break;
 	 default:
-	    xioparms.preferred_ip = '0'; break;
+	    xioparms.preferred_ip = '0';
+	    break;
 	 }
       }
    }
diff --git a/xioopen.c b/xioopen.c
index 680ad44..fa214af 100644
--- a/xioopen.c
+++ b/xioopen.c
@@ -386,9 +386,9 @@
 		   int xioflags) {
    xiofile_t *xfd;
 
-   if (xioinitialize() < 0) {
-      return NULL;
-   }
+   //if (xioinitialize() < 0) {
+   //   return NULL;
+   //}
 
    Debug1("xioopen(\"%s\")", addr);