diff --git a/CHANGES b/CHANGES
index 6c264e4..69f091b 100644
--- a/CHANGES
+++ b/CHANGES
@@ -60,10 +60,24 @@ Corrections:
 	now handled properly.
 	Test: UNIX_L_BIND
 
-	Removed unused bytes variable from gettimestamp(), corrected #elsif and
-	socks4 record length.
+	Removed unused bytes variable from gettimestamp(), corrected #elsif,
+	and socks4 record length.
 	Thanks to clang-18 and gcc-13.
 
+	Address TCP-CONNECT, when target address resolves to both IPv4 and
+	IPv6, now tries to take into account bind address for protocol
+	selection.
+
+	Reworked and harmonized ipapp client addresses.
+	Tests: TCP_CONNECT_RETRY SCTP_CONNECT_RETRY DCCP_CONNECT_RETRY
+	OPENSSL_CONNECT_RETRY SOCKS4_RETRY SOCKS5_CONNECT_RETRY
+	PROXY_CONNECT_RETRY
+
+	Socks and proxy clients now also support option max-children.
+	Tests: TCP_CONNECT_MAXCHILDREN SCTP_CONNECT_MAXCHILDREN
+	DCCP_CONNECT_MAXCHILDREN OPENSSL_CONNECT_MAXCHILDREN
+	SOCKS4_MAXCHILDREN SOCKS5_CONNECT_MAXCHILDREN PROXY_CONNECT_MAXCHILDREN
+
 Features:
 	POSIXMQ-RECV now takes option o-nonblock; this, in combination with -T,
 	makes it possible to terminate Socat in case the queue is empty.
diff --git a/socks4echo.sh b/socks4echo.sh
index a577b20..44c631a 100755
--- a/socks4echo.sh
+++ b/socks4echo.sh
@@ -9,6 +9,7 @@
 # it is required for test.sh
 # for TCP, use this script as:
 # socat tcp-l:1080,reuseaddr,crlf system:"socks4echo.sh"
+# Then connect with a socks4 request for 32.98.76.54:32109 and user nobody
 
 # older bash and ksh do not have -n option to read command; we try dd then
 #if echo a |read -n 1 null >/dev/null 2>&1; then
diff --git a/test.sh b/test.sh
index 0ed9584..5829e63 100755
--- a/test.sh
+++ b/test.sh
@@ -39,7 +39,7 @@ usage() {
     $ECHO "Usage: $0 <options> [<test-spec> ...]"
     $ECHO "options:"
     $ECHO "\t-h \t\tShow this help"
-    $ECHO "\t-t <sec> \tBase for timeouts in seconds, default: 0.1"
+    $ECHO "\t-t <sec> \tBase for timeouts in seconds, default is automatically determined"
     $ECHO "\t-v \t\tBe more verbose, show failed commands"
     $ECHO "\t-n <num> \tOnly perform test with given number"
     $ECHO "\t-N <num> \tOnly perform tests starting with given number"
@@ -123,6 +123,13 @@ divide_uint_by_1000000 () {
     fi
 }
 
+
+# output the value in seconds for n * val_t
+relsecs () {
+    local n="$1"
+    divide_uint_by_1000000 $((n*MICROS))
+}
+
 _MICROS=$((MICROS+999999)); SECONDs="${_MICROS%??????}"
 [ -z "$SECONDs" ] && SECONDs=0
 [ "$DEFS" ] && echo "SECONDs=\"$SECONDs\"" >&2
@@ -145,26 +152,20 @@ if [ -z "$FILAN" ]; then if test -x ./filan; then FILAN="./filan"; elif ! type f
 
 if ! sleep 0.1 2>/dev/null; then
     sleep () {
-	$SOCAT -T $0 PIPE PIPE
+	$SOCAT -T "$1" PIPE PIPE
     }
 fi
 
 if [ -z "$val_t" ]; then
-    # Determine the time Socat needs for an empty run
+    # Estimate the time Socat needs for an empty run
+    sleep 0.5 	# immediately after build the first runs are extremely fast
     $SOCAT /dev/null /dev/null 	# populate caches
-    MILLIs=$(bash -c 'time $SOCAT $opts /dev/null /dev/null' 2>&1 |grep ^real |sed 's/.*m\(.*\)s.*/\1/' |tr -d ,.)
+    MILLIs=$(bash -c "time for _ in {1..3}; do $SOCAT -d0 $opts /dev/null /dev/null; done" 2>&1 |grep ^real |sed 's/.*m\(.*\)s.*/\1/' |tr -d ,.)
     while [ "${MILLIs:0:1}" = '0' ]; do MILLIs=${MILLIs##0}; done 	# strip leading '0' to avoid octal
     [ -z "$MILLIs" ] && MILLIs=1
-    [ "$DEFS" ] && echo "MILLIs=\"$MILLIs\" (1)" >&2
-
-    # On my idle development computer this value flaps from 0.001 to 0.004
-    # 0.001 lets many tests fail, so we triple the result
-    #MILLIs=$((10*MILLIs))
-    MILLIs=$((3*MILLIs))
-    [ "$DEFS" ] && echo "MILLIs=\"$MILLIs\" (2)" >&2
+    [ "$DEFS" ] && echo "MILLIs=\"$MILLIs\"" >&2
     MICROS=${MILLIs}000
 
-    #set -vx
     case $MICROS in
 	???????*) val_t=${MICROS%??????}.${MICROS: -6} ;;
 	*)        x=000000$MICROS; val_t=0.${x: -6} ;;
@@ -212,7 +213,13 @@ PATH=.:$PATH 	# for relsleep
 MISCDELAY=1
 
 OPTS="$opt_t $OPTS"
-[ "$EXPERIMENTAL" ] && OPTS="--experimental $OPTS"
+
+if [ "$EXPERIMENTAL" ]; then
+    if $SOCAT -h |grep -e --experimental >/dev/null; then
+	OPTS="$OPTS --experimental"
+    fi
+fi
+
 opts="$OPTS"
 [ "$DEFS" ] && echo "opts=\"$opts\"" >&2
 
@@ -1009,7 +1016,7 @@ runsip4 () {
     CYGWIN*) l=$(ipconfig |grep IPv4);;
     *)     l=$($IFCONFIG -a |grep ' ::1[^:0-9A-Fa-f]') ;;
     esac
-    [ -z "$l" ] && return 1    
+    [ -z "$l" ] && return 1
     # existence of interface might not suffice, check for routeability:
     case "$UNAME" in
     Darwin) ping -c 1 127.0.0.1 >/dev/null 2>&1; l="$?" ;;
@@ -1043,7 +1050,7 @@ runsip6 () {
     CYGWIN*) l=$(ipconfig |grep IPv6);;
     *)     l=$($IFCONFIG -a |grep ' ::1[^:0-9A-Fa-f]') ;;
     esac
-    [ -z "$l" ] && return 1    
+    [ -z "$l" ] && return 1
     # existence of interface might not suffice, check for routeability:
     case "$UNAME" in
     Darwin) $PING6 -c 1 ::1 >/dev/null 2>&1; l="$?" ;;
@@ -1484,6 +1491,24 @@ checktcpport () {
     return 1
 }
 
+waittcpport () {
+    local port="$1"
+    local logic="$2" 	# 0..wait until free; 1..wait until listening (default)
+    local timeout="$3"
+    while true; do
+#echo "timeout=\"$timeout\"" >&2
+	if [ "$logic" = 0 ]; then
+	    if checktcpport $1; then break; fi
+	else
+	    if ! checktcpport $1; then break; fi
+	fi
+	if [ $timeout -le 0 ]; then return 1; fi
+	sleep 1
+	let --timeout;
+    done
+    return 0;
+}
+
 checktcp4port () {
     checktcpport $1
 }
@@ -2289,7 +2314,7 @@ esac
 N=$((N+1))
 
 
-# test: send EOF to exec'ed sub process, let it finish its operation, and 
+# test: send EOF to exec'ed sub process, let it finish its operation, and
 # check if the sub process returns its data before terminating.
 NAME=EXECSOCKETPAIRFLUSH
 # idea: have socat exec'ing od; send data and EOF, and check if the od'ed data
@@ -2455,8 +2480,9 @@ esac
 N=$((N+1))
 
 newport() {
-     _PORT=$((_PORT+1))
+    _PORT=$((_PORT+1))
      while eval wait${1}port $_PORT 1 0 2>/dev/null; do _PORT=$((_PORT+1)); done
+     #while ! eval check${1}port $_PORT 2>/dev/null; do sleep 1; _PORT=$((_PORT+1)); done
      #echo "PORT=$_PORT" >&2
      PORT=$_PORT
 }
@@ -3565,7 +3591,7 @@ printf "test $F_n $TEST... " $N
 touch "$ti"
 $CMD >"$tf" 2>"$te" &
 bg=$!
-# Up to 1.8.0.1 this sleep was 0.1 and thus the test said OK despite the bug 
+# Up to 1.8.0.1 this sleep was 0.1 and thus the test said OK despite the bug
 sleep 1.1
 echo "$da" >>"$ti"
 sleep 1
@@ -4028,8 +4054,6 @@ esac
 N=$((N+1))
 
 
-newport $RUNS 	# in case it has not yet been invoked
-
 while read NAMEKEYW FEAT RUNS TESTTMPL PEERTMPL WAITTMPL; do
 if [ -z "$NAMEKEYW" ] || [[ "$NAMEKEYW" == \#* ]]; then continue; fi
 
@@ -4514,35 +4538,47 @@ elif ! testfeats listen tcp ip4 >/dev/null || ! runsip4 >/dev/null; then
     $PRINTF "test $F_n $TEST... ${YELLOW}TCP/IPv4 not available${NORMAL}\n" $N
     cant
 else
-ts="$td/test$N.sh"
-tf="$td/test$N.stdout"
-te="$td/test$N.stderr"
-tdiff="$td/test$N.diff"
-da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')"
-newport tcp4 	# provide free port number in $PORT
-#CMD2="$TRACE $SOCAT tcp4-l:$PORT,crlf SYSTEM:\"read; read; $ECHO \\\"HTTP/1.0 200 OK\n\\\"; cat\""
-CMD2="$TRACE $SOCAT $opts TCP4-L:$PORT,$REUSEADDR,crlf EXEC:\"/usr/bin/env bash proxyecho.sh\""
-CMD="$TRACE $SOCAT $opts - PROXY:$LOCALHOST:127.0.0.1:1000,pf=ip4,proxyport=$PORT"
-printf "test $F_n $TEST... " $N
-eval "$CMD2 2>\"${te}2\" &"
-pid=$!	# background process id
-waittcp4port $PORT 1
-echo "$da" |$CMD >"$tf" 2>"${te}1"
-if ! echo "$da" |diff - "$tf" >"$tdiff"; then
-    $PRINTF "$FAILED: $TRACE $SOCAT:\n"
-    echo "$CMD2 &"
-    echo "$CMD"
-    cat "${te}1"
-    cat "${te}2"
-    cat "$tdiff"
-    failed
-else
-   $PRINTF "$OK\n"
-   if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi
-   ok
-fi
-kill $pid 2>/dev/null
-wait
+    ts="$td/test$N.sh"
+    tf="$td/test$N.stdout"
+    te="$td/test$N.stderr"
+    tdiff="$td/test$N.diff"
+    da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')"
+    newport tcp4 	# provide free port number in $PORT
+    #CMD0="$TRACE $SOCAT tcp4-l:$PORT,crlf SYSTEM:\"read; read; $ECHO \\\"HTTP/1.0 200 OK\n\\\"; cat\""
+    CMD0="$TRACE $SOCAT $opts TCP4-L:$PORT,$REUSEADDR,crlf EXEC:\"/usr/bin/env bash proxyecho.sh\""
+    CMD1="$TRACE $SOCAT $opts - PROXY:$LOCALHOST:127.0.0.1:1000,pf=ip4,proxyport=$PORT"
+    printf "test $F_n $TEST... " $N
+    eval "$CMD0 2>\"${te}0\" &"
+    pid=$!	# background process id
+    waittcp4port $PORT 1
+    echo "$da" |$CMD1 >"$tf" 2>"${te}1"
+    rc1=$?
+    if [ "$rc1" -ne 0 ]; then
+	$PRINTF "$FAILED (rc1=$rc1)\n"
+	echo "$CMD0 &"
+	cat "${te}0" >&2
+	echo "$CMD1"
+	cat "${te}1" >&2
+	fail
+    elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
+	$PRINTF "$FAILED (diff)\n"
+	echo "$CMD0 &"
+	cat "${te}0" >&2
+	echo "$CMD1"
+	cat "${te}1" >&2
+	echo "// diff:" >&2
+	cat "$tdiff" >&2
+	fail
+    else
+	$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
+	ok
+    fi
+    kill $pid 2>/dev/null
+    wait
 fi ;; # NUMCOND, feats
 esac
 N=$((N+1))
@@ -4559,35 +4595,47 @@ elif ! testfeats listen tcp ip6 >/dev/null || ! runsip6 >/dev/null; then
     $PRINTF "test $F_n $TEST... ${YELLOW}TCP/IPv6 not available${NORMAL}\n" $N
     cant
 else
-ts="$td/test$N.sh"
-tf="$td/test$N.stdout"
-te="$td/test$N.stderr"
-tdiff="$td/test$N.diff"
-da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')"
-newport tcp6 	# provide free port number in $PORT
-#CMD2="$TRACE $SOCAT $opts TCP6-L:$PORT,crlf SYSTEM:\"read; read; $ECHO \\\"HTTP/1.0 200 OK\n\\\"; cat\""
-CMD2="$TRACE $SOCAT $opts TCP6-L:$PORT,$REUSEADDR,crlf EXEC:\"/usr/bin/env bash proxyecho.sh\""
-CMD="$TRACE $SOCAT $opts - PROXY:$LOCALHOST6:127.0.0.1:1000,proxyport=$PORT"
-printf "test $F_n $TEST... " $N
-eval "$CMD2 2>\"${te}2\" &"
-pid=$!	# background process id
-waittcp6port $PORT 1
-echo "$da" |$CMD >"$tf" 2>"${te}1"
-if ! echo "$da" |diff - "$tf" >"$tdiff"; then
-    $PRINTF "$FAILED: $TRACE $SOCAT:\n"
-    echo "$CMD2 &"
-    echo "$CMD"
-    cat "${te}1"
-    cat "${te}2"
-    cat "$tdiff"
-    failed
-else
-   $PRINTF "$OK\n"
-   if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi
-   ok
-fi
-kill $pid 2>/dev/null
-wait
+    ts="$td/test$N.sh"
+    tf="$td/test$N.stdout"
+    te="$td/test$N.stderr"
+    tdiff="$td/test$N.diff"
+    da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')"
+    newport tcp6 	# provide free port number in $PORT
+    #CMD0="$TRACE $SOCAT $opts TCP6-L:$PORT,crlf SYSTEM:\"read; read; $ECHO \\\"HTTP/1.0 200 OK\n\\\"; cat\""
+    CMD0="$TRACE $SOCAT $opts TCP6-L:$PORT,$REUSEADDR,crlf EXEC:\"/usr/bin/env bash proxyecho.sh\""
+    CMD1="$TRACE $SOCAT $opts - PROXY:$LOCALHOST6:127.0.0.1:1000,proxyport=$PORT"
+    printf "test $F_n $TEST... " $N
+    eval "$CMD0 2>\"${te}0\" &"
+    pid=$!	# background process id
+    waittcp6port $PORT 1
+    echo "$da" |$CMD1 >"$tf" 2>"${te}1"
+    rc1=$?
+    if [ "$rc1" -ne 0 ]; then
+	$PRINTF "$FAILED (rc1=$rc1)\n"
+	echo "$CMD0 &"
+	cat "${te}0" >&2
+	echo "$CMD1"
+	cat "${te}1" >&2
+	failed
+    elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
+	$PRINTF "$FAILED (diff)\n"
+	echo "$CMD0 &"
+	cat "${te}0" >&2
+	echo "$CMD1"
+	cat "${te}1" >&2
+	echo "// diff: " >&2
+	cat "$tdiff" >&2
+	failed
+    else
+	$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
+	ok
+    fi
+    kill $pid 2>/dev/null
+    wait
 fi ;; # NUMCOND, feats
 esac
 N=$((N+1))
@@ -5033,7 +5081,7 @@ N=$((N+1))
 
 NAME=GENDERCHANGER
 case "$TESTS" in
-*%$N%*|*%functions%*|*%listen%*|*%$NAME%*)
+*%$N%*|*%functions%*|*%listen%*|*%retry%*|*%$NAME%*)
 TEST="$NAME: TCP4 \"gender changer\""
 if ! eval $NUMCOND; then :; else
 tf="$td/test$N.stdout"
@@ -5096,7 +5144,7 @@ N=$((N+1))
 
 NAME=OUTBOUNDIN
 case "$TESTS" in
-*%$N%*|*%functions%*|*%openssl%*|*%proxy%*|*%fork%*|*%listen%*|*%$NAME%*)
+*%$N%*|*%functions%*|*%openssl%*|*%proxy%*|*%fork%*|*%listen%*|*%retry%*|*%$NAME%*)
 TEST="$NAME: gender changer via SSL through HTTP proxy, oneshot"
 if ! eval $NUMCOND; then :;
 elif ! feat=$(testfeats openssl proxy); then
@@ -5185,7 +5233,7 @@ N=$((N+1))
 #!
 NAME=INTRANETRIPPER
 case "$TESTS" in
-*%$N%*|*%functions%*|*%openssl%*|*%proxy%*|*%listen%*|*%fork%*|*%$NAME%*)
+*%$N%*|*%functions%*|*%openssl%*|*%proxy%*|*%listen%*|*%fork%*|*%retry%*|*%$NAME%*)
 TEST="$NAME: gender changer via SSL through HTTP proxy, daemons"
 if ! eval $NUMCOND; then :;
 elif ! feat=$(testfeats openssl proxy); then
@@ -5460,7 +5508,7 @@ testserversec () {
 
 NAME=TCP4RANGEBITS
 case "$TESTS" in
-*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%listen%*|*%fork%*|*%$NAME%*)
+*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%listen%*|*%fork%*|*%retry%*|*%$NAME%*)
 TEST="$NAME: security of TCP4-L with RANGE option"
 if ! eval $NUMCOND; then :;
 elif [ -z "$SECONDADDR" ]; then
@@ -5476,7 +5524,7 @@ N=$((N+1))
 
 NAME=TCP4RANGEMASK
 case "$TESTS" in
-*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%listen%*|*%fork%*|*%$NAME%*)
+*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%listen%*|*%fork%*|*%retry%*|*%$NAME%*)
 TEST="$NAME: security of TCP4-L with RANGE option"
 if ! eval $NUMCOND; then :;
 elif [ -z "$SECONDADDR" ]; then
@@ -5493,7 +5541,7 @@ N=$((N+1))
 # like TCP4RANGEMASK, but the "bad" address is within the same class A network
 NAME=TCP4RANGEMASKHAIRY
 case "$TESTS" in
-*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%listen%*|*%fork%*|*%$NAME%*)
+*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%listen%*|*%fork%*|*%retry%*|*%$NAME%*)
 TEST="$NAME: security of TCP4-L with RANGE option"
 if ! eval $NUMCOND; then :; else
 newport tcp4 	# provide free port number in $PORT
@@ -5505,7 +5553,7 @@ N=$((N+1))
 
 NAME=TCP4SOURCEPORT
 case "$TESTS" in
-*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%sourceport%*|*%listen%*|*%fork%*|*%$NAME%*)
+*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%sourceport%*|*%listen%*|*%fork%*|*%retry%*|*%$NAME%*)
 TEST="$NAME: security of TCP4-L with SOURCEPORT option"
 if ! eval $NUMCOND; then :; else
 newport tcp4 	# provide free port number in $PORT
@@ -5516,7 +5564,7 @@ N=$((N+1))
 
 NAME=TCP4LOWPORT
 case "$TESTS" in
-*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%lowport%*|*%listen%*|*%fork%*|*%$NAME%*)
+*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%lowport%*|*%listen%*|*%fork%*|*%retry%*|*%$NAME%*)
 TEST="$NAME: security of TCP4-L with LOWPORT option"
 if ! eval $NUMCOND; then :; else
 newport tcp4 	# provide free port number in $PORT
@@ -5527,7 +5575,7 @@ N=$((N+1))
 
 NAME=TCP4WRAPPERS_ADDR
 case "$TESTS" in
-*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%tcpwrap%*|*%listen%*|*%fork%*|*%$NAME%*)
+*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%tcpwrap%*|*%listen%*|*%fork%*|*%retry%*|*%$NAME%*)
 TEST="$NAME: security of TCP4-L with TCPWRAP option"
 if ! eval $NUMCOND; then :;
 elif ! feat=$(testfeats tcp ip4 libwrap) || ! runsip4 >/dev/null; then
@@ -5546,7 +5594,7 @@ N=$((N+1))
 
 NAME=TCP4WRAPPERS_NAME
 case "$TESTS" in
-*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%tcpwrap%*|*%listen%*|*%fork%*|*%$NAME%*)
+*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%tcpwrap%*|*%listen%*|*%fork%*|*%retry%*|*%$NAME%*)
 TEST="$NAME: security of TCP4-L with TCPWRAP option"
 if ! eval $NUMCOND; then :;
 elif ! feat=$(testfeats tcp ip4 libwrap) || ! runsip4 >/dev/null; then
@@ -5566,7 +5614,7 @@ N=$((N+1))
 
 NAME=TCP6RANGE
 case "$TESTS" in
-*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%range%*|*%listen%*|*%fork%*|*%$NAME%*)
+*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%range%*|*%listen%*|*%fork%*|*%retry%*|*%$NAME%*)
 TEST="$NAME: security of TCP6-L with RANGE option"
 if ! eval $NUMCOND; then :;
 elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then
@@ -5581,7 +5629,7 @@ N=$((N+1))
 
 NAME=TCP6SOURCEPORT
 case "$TESTS" in
-*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%sourceport%*|*%listen%|*%fork%**|*%$NAME%*)
+*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%sourceport%*|*%listen%|*%fork%*|*%retry%*|*%$NAME%*)
 TEST="$NAME: security of TCP6-L with SOURCEPORT option"
 if ! eval $NUMCOND; then :;
 elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then
@@ -5596,7 +5644,7 @@ N=$((N+1))
 
 NAME=TCP6LOWPORT
 case "$TESTS" in
-*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%lowport%*|*%listen%*|*%fork%*|*%$NAME%*)
+*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%lowport%*|*%listen%*|*%fork%*|*%retry%*|*%$NAME%*)
 TEST="$NAME: security of TCP6-L with LOWPORT option"
 if ! eval $NUMCOND; then :;
 elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then
@@ -5611,7 +5659,7 @@ N=$((N+1))
 
 NAME=TCP6TCPWRAP
 case "$TESTS" in
-*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%tcpwrap%*|*%listen%*|*%fork%*|*%$NAME%*)
+*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%tcpwrap%*|*%listen%*|*%fork%*|*%retry%*|*%$NAME%*)
 TEST="$NAME: security of TCP6-L with TCPWRAP option"
 if ! eval $NUMCOND; then :;
 elif ! feat=$(testfeats tcp ip6 libwrap && runstcp6); then
@@ -5750,7 +5798,7 @@ N=$((N+1))
 
 NAME=OPENSSLTCP4_RANGE
 case "$TESTS" in
-*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%range%*|*%listen%*|*%fork%*|*%$NAME%*)
+*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%range%*|*%listen%*|*%fork%*|*%retry%*|*%$NAME%*)
 TEST="$NAME: security of SSL-L over TCP/IPv4 with RANGE option"
 if ! eval $NUMCOND; then :;
 elif ! testfeats openssl >/dev/null; then
@@ -5766,7 +5814,7 @@ N=$((N+1))
 
 NAME=OPENSSLTCP4_SOURCEPORT
 case "$TESTS" in
-*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%sourceport%*|*%listen%*|*%fork%*|*%$NAME%*)
+*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%sourceport%*|*%listen%*|*%fork%*|*%retry%*|*%$NAME%*)
 TEST="$NAME: security of SSL-L with SOURCEPORT option"
 if ! eval $NUMCOND; then :;
 elif ! testfeats openssl >/dev/null; then
@@ -5782,7 +5830,7 @@ N=$((N+1))
 
 NAME=OPENSSLTCP4_LOWPORT
 case "$TESTS" in
-*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%lowport%*|*%listen%*|*%fork%*|*%$NAME%*)
+*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%lowport%*|*%listen%*|*%fork%*|*%retry%*|*%$NAME%*)
 TEST="$NAME: security of SSL-L with LOWPORT option"
 if ! eval $NUMCOND; then :;
 elif ! testfeats openssl >/dev/null; then
@@ -5798,7 +5846,7 @@ N=$((N+1))
 
 NAME=OPENSSLTCP4_TCPWRAP
 case "$TESTS" in
-*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%tcpwrap%*|*%listen%*|*%fork%*|*%$NAME%*)
+*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%tcpwrap%*|*%listen%*|*%fork%*|*%retry%*|*%$NAME%*)
 TEST="$NAME: security of SSL-L with TCPWRAP option"
 if ! eval $NUMCOND; then :;
 elif ! feat=$(testfeats ip4 tcp libwrap openssl); then
@@ -5818,7 +5866,7 @@ N=$((N+1))
 
 NAME=OPENSSLCERTSERVER
 case "$TESTS" in
-*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%listen%*|*%fork%*|*%$NAME%*)
+*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%listen%*|*%fork%*|*%retry%*|*%$NAME%*)
 TEST="$NAME: security of SSL-L with client certificate"
 if ! eval $NUMCOND; then :;
 elif ! testfeats openssl >/dev/null; then
@@ -5835,7 +5883,7 @@ N=$((N+1))
 
 NAME=OPENSSLCERTCLIENT
 case "$TESTS" in
-*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%listen%*|*%fork%*|*%$NAME%*)
+*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%listen%*|*%fork%*|*%retry%*|*%$NAME%*)
 TEST="$NAME: security of SSL with server certificate"
 if ! eval $NUMCOND; then :;
 elif ! testfeats openssl >/dev/null; then
@@ -5853,7 +5901,7 @@ N=$((N+1))
 
 NAME=OPENSSLTCP6_RANGE
 case "$TESTS" in
-*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%range%*|*%listen%*|*%fork%*|*%$NAME%*)
+*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%range%*|*%listen%*|*%fork%*|*%retry%*|*%$NAME%*)
 TEST="$NAME: security of SSL-L over TCP/IPv6 with RANGE option"
 if ! eval $NUMCOND; then :;
 elif ! testfeats openssl >/dev/null; then
@@ -5872,7 +5920,7 @@ N=$((N+1))
 
 NAME=OPENSSLTCP6_SOURCEPORT
 case "$TESTS" in
-*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%sourceport%*|*%listen%*|*%fork%*|*%$NAME%*)
+*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%sourceport%*|*%listen%*|*%fork%*|*%retry%*|*%$NAME%*)
 TEST="$NAME: security of SSL-L over TCP/IPv6 with SOURCEPORT option"
 if ! eval $NUMCOND; then :;
 elif ! testfeats openssl >/dev/null; then
@@ -5891,7 +5939,7 @@ N=$((N+1))
 
 NAME=OPENSSLTCP6_LOWPORT
 case "$TESTS" in
-*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%lowport%*|*%listen%*|*%fork%*|*%$NAME%*)
+*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%lowport%*|*%listen%*|*%fork%*|*%retry%*|*%$NAME%*)
 TEST="$NAME: security of SSL-L over TCP/IPv6 with LOWPORT option"
 if ! eval $NUMCOND; then :;
 elif ! testfeats openssl >/dev/null; then
@@ -5910,7 +5958,7 @@ N=$((N+1))
 
 NAME=OPENSSLTCP6_TCPWRAP
 case "$TESTS" in
-*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%tcpwrap%*|*%listen%*|*%fork%*|*%$NAME%*)
+*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%tcpwrap%*|*%listen%*|*%fork%*|*%retry%*|*%$NAME%*)
 TEST="$NAME: security of SSL-L over TCP/IPv6 with TCPWRAP option"
 if ! eval $NUMCOND; then :;
 elif ! feat=$(testfeats ip6 tcp libwrap openssl && runsip6); then
@@ -5932,7 +5980,7 @@ N=$((N+1))
 # test security with the openssl-commonname option on client side
 NAME=OPENSSL_CN_CLIENT_SECURITY
 case "$TESTS" in
-*%$N%*|*%functions%*|*%security%*|*%openssl%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%listen%*|*%fork%*|*%$NAME%*)
+*%$N%*|*%functions%*|*%security%*|*%openssl%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%listen%*|*%fork%*|*%retry%*|*%$NAME%*)
 TEST="$NAME: security of client openssl-commonname option"
 # connect using non matching server name/address with commonname
 # options, this should succeed. Then without this option, should fail
@@ -5979,7 +6027,7 @@ N=$((N+1))
 
 NAME=OPENSSL_FIPS_SECURITY
 case "$TESTS" in
-*%$N%*|*%functions%*|*%security%*|*%openssl%*|*%fips%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%listen%*|*%fork%*|*%$NAME%*)
+*%$N%*|*%functions%*|*%security%*|*%openssl%*|*%fips%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%listen%*|*%fork%*|*%retry%*|*%$NAME%*)
 TEST="$NAME: OpenSSL restrictions by FIPS"
 if ! eval $NUMCOND; then :;
 elif ! testfeats openssl >/dev/null; then
@@ -6556,7 +6604,7 @@ case "$MAJADDR" in
 	tca="$ts"
 	waitproto="file"
 	waitfor="$ts" ;;
-esac	
+esac
 case "$MINADDR" in
     "PORT")
 	newport $protov 	# provide free port number in $PORT
@@ -6564,7 +6612,7 @@ case "$MINADDR" in
 	tca="$MAJADDR:$PORT"
 	waitproto="${protov}port"
 	waitfor="$PORT" ;;
-esac	
+esac
 #set -xv
 echo -e "$da1a\n$da2\n$da1b" >"$tref"
 # establish a listening and forking listen socket in background
@@ -10662,7 +10710,7 @@ N=$((N+1))
 
 NAME=SOCKETRANGEMASK
 case "$TESTS" in
-*%$N%*|*%functions%*|*%security%*|*%generic%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%socket%*|*%range%*|*%listen%*|*%fork%*|*%$NAME%*)
+*%$N%*|*%functions%*|*%security%*|*%generic%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%socket%*|*%range%*|*%listen%*|*%fork%*|*%retry%*|*%$NAME%*)
 TEST="$NAME: security of generic socket-listen with RANGE option"
 if ! eval $NUMCOND; then :;
 elif [ -z "$SECONDADDR" ]; then
@@ -11483,10 +11531,10 @@ PROTO=$KEYW
 proto="$(tolower "$PROTO")"
 feat="$(tolower "$FEAT")"
 # test the max-children option on really connection oriented sockets
-NAME=${KEYW}MAXCHILDREN
+NAME=${KEYW}_L_MAXCHILDREN
 case "$TESTS" in
 *%$N%*|*%functions%*|*%fork%*|*%maxchildren%*|*%$feat%*|*%$proto%*|*%socket%*|*%listen%*|*%$NAME%*)
-TEST="$NAME: max-children option"
+TEST="$NAME: max-children option with $PROTO-LISTEN"
 # start a listen process with max-children=1; connect with a client, let it
 # sleep some time before sending data; connect with second client that sends
 # data immediately. If max-children is working correctly the first data should
@@ -11566,10 +11614,10 @@ RUNS=$(tolower $KEYW)
 PROTO=$KEYW
 proto="$(tolower "$PROTO")"
 # test the max-children option on pseudo connected sockets
-NAME=${KEYW}MAXCHILDREN
+NAME=${KEYW}_L_MAXCHILDREN
 case "$TESTS" in
 *%$N%*|*%functions%*|*%fork%*|*%maxchildren%*|*%$SEL%*|*%socket%*|*%listen%*|*%$NAME%*)
-TEST="$NAME: max-children option"
+TEST="$NAME: max-children option with $PROTO-LISTEN"
 # start a listen process with max-children=1; connect with a client, let it
 # send data and then sleep; connect with second client that wants to send
 # data immediately, but keep first client active until server terminates.
@@ -11931,7 +11979,7 @@ N=$((N+1))
 # had a bug that converted a bit mask of 0 internally to 0xffffffff
 NAME=TCP4RANGE_0BITS
 case "$TESTS" in
-*%$N%*|*%functions%*|*%fork%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%listen%*|*%$NAME%*)
+*%$N%*|*%functions%*|*%fork%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%listen%*|*%retry%*|*%$NAME%*)
 TEST="$NAME: correct evaluation of range mask 0"
 if ! eval $NUMCOND; then :;
 elif [ -z "$SECONDADDR" ]; then
@@ -14617,7 +14665,6 @@ fi
 fi # NUMCOND
  ;;
 esac
-PORT=$((PORT+1))
 N=$((N+1))
 
 # Socats access to different types of file system entries using various kinds
@@ -14752,7 +14799,7 @@ orphaned    gopen
 # Up to 1.7.4.3 this terminated immediately on connection refused
 NAME=TCP_TIMEOUT_RETRY
 case "$TESTS" in
-*%$N%*|*%functions%*|*%bugs%*|*%tcp%*|*%socket%*|*%listen%*|*%$NAME%*)
+*%$N%*|*%functions%*|*%bugs%*|*%tcp%*|*%socket%*|*%listen%*|*%retry%*|*%$NAME%*)
 TEST="$NAME: TCP with options connect-timeout and retry"
 # In background run a delayed echo server
 # In foreground start TCP with connect-timeout and retry. On first attempt the
@@ -14831,7 +14878,6 @@ fi
 fi # NUMCOND
  ;;
 esac
-PORT=$((PORT+1))
 N=$((N+1))
 
 # Up to 1.7.4.3 there was a bug with the lowport option:
@@ -14880,7 +14926,6 @@ fi
 fi # NUMCOND
  ;;
 esac
-PORT=$((PORT+1))
 N=$((N+1))
 
 # Test if trailing garbage in integer type options gives error
@@ -15160,7 +15205,6 @@ fi
 fi # NUMCOND
  ;;
 esac
-PORT=$((PORT+1))
 N=$((N+1))
 
 
@@ -15215,7 +15259,6 @@ fi
 fi # NUMCOND
  ;;
 esac
-PORT=$((PORT+1))
 N=$((N+1))
 
 
@@ -15258,7 +15301,6 @@ fi
 fi # NUMCOND
  ;;
 esac
-PORT=$((PORT+1))
 N=$((N+1))
 
 # Test if Socat makes the sniffing file descriptos (-r, -R) CLOEXEC to not leak
@@ -15301,7 +15343,6 @@ fi
 fi # NUMCOND
  ;;
 esac
-PORT=$((PORT+1))
 N=$((N+1))
 
 
@@ -15544,7 +15585,6 @@ kill $pid 2>/dev/null
 wait
 fi ;; # NUMCOND, feats
 esac
-PORT=$((PORT+1))
 N=$((N+1))
 
 
@@ -15857,7 +15897,7 @@ waitunixport $ts 1
 rc1=$?
 kill $pid0 2>/dev/null; wait
 relsleep 1 	# child process might need more time
-if grep -q " W connect" ${te}0; then
+if ! grep -q " E " ${te}0; then
     $PRINTF "$OK\n"
     if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
     if [ "$DEBUG" ];   then cat "${te}0" >&2; fi
@@ -15960,7 +16000,6 @@ else
 fi
 fi ;; # NUMCOND, feats
 esac
-PORT=$((PORT+1))
 N=$((N+1))
 
 
@@ -16614,8 +16653,8 @@ else
 tf="$td/test$N.stdout"
 te="$td/test$N.stderr"
 tdiff="$td/test$N.diff"
-ts1p=$PORT; PORT=$((PORT+1))
-ts2p=$PORT; PORT=$((PORT+1))
+newport udp; ts1p=$PORT
+newport udp; ts2p=$PORT
 da="test$N $(date) $RANDOM"
 CMD1="$TRACE $SOCAT $opts -T 0.2 UDP4-DATAGRAM:$LOCALHOST:$ts2p,bind=$LOCALHOST:$ts1p SOCKETPAIR,socktype=$SOCK_DGRAM"
 CMD2="$TRACE $SOCAT $opts -b 24 -t 0.2 -T 0.3 - UDP4-DATAGRAM:$LOCALHOST:$ts1p,bind=$LOCALHOST:$ts2p"
@@ -16655,7 +16694,6 @@ fi
 fi # NUMCOND
  ;;
 esac
-PORT=$((PORT+1))
 N=$((N+1))
 
 
@@ -16856,13 +16894,14 @@ case "$TESTS" in
 *%$N%*|*%functions%*|*%fork%*|*%maxchildren%*|*%socket%*|*%posixmq%*|*%$NAME%*)
 TEST="$NAME: POSIX-MQ RECV with fork,max-children"
 # Start a POSIX-MQ receiver with fork that creates a POSIX-MQ and stores its
-# output via sub processes that sleeps after writing.
+# output via sub processes that sleep after writing.
 # Run a client/sender that sends message 1;
-# run a client/sender that sends message 3, has to wait;
-# write message 2 directly into output file;
+# run a client/sender that sends message 2;
+# run a client/sender that sends message 4, has to wait;
+# write message 3 directly into output file;
 # Check if the messages are stored in order of their numbers
 if ! eval $NUMCOND; then :;
-elif ! cond=$(checkconds "" "" "" "POSIXMQ STDIO SYSTEM" "POSIXMQ-SEND POSIXMQ-RECEIVE STDIO SYSTEM" "fork max-children unlink-early unlink-close"); then
+elif ! cond=$(checkconds "" "" "" "POSIXMQ STDIO SHELL" "POSIXMQ-SEND POSIXMQ-RECEIVE STDIO SHELL" "fork max-children unlink-early unlink-close"); then
     $PRINTF "test $F_n $TEST... ${YELLOW}$cond${NORMAL}\n" $N
     cant
 else
@@ -16871,7 +16910,7 @@ te="$td/test$N.stderr"
 tdiff="$td/test$N.diff"
 da="test$N $(date) $RANDOM"
 tq=/test$N
-CMD0="$TRACE $SOCAT $opts -u POSIXMQ-RECV:$tq,unlink-early,fork,max-children=1 SYSTEM:\"cat\ >>${tf}0;\ sleep\ 1\""
+CMD0="$TRACE $SOCAT $opts -u POSIXMQ-RECV:$tq,unlink-early,fork,max-children=2 SHELL:\"cat\ >>${tf}0;\ relsleep\ 5\""
 CMD1a="$TRACE $SOCAT $opts -u STDIO POSIXMQ-SEND:$tq"
 CMD1b="$TRACE $SOCAT $opts -u STDIO POSIXMQ-SEND:$tq,unlink-close"
 printf "test $F_n $TEST... " $N
@@ -16880,23 +16919,28 @@ pid0=$!
 relsleep 1
 echo "$da 1" |$CMD1a >/dev/null 2>"${te}1a"
 rc1a=$?
-echo "$da 3" |$CMD1b >/dev/null 2>"${te}1b"
+echo "$da 2" |$CMD1a >/dev/null 2>"${te}1b"
 rc1b=$?
-sleep 0.5
-echo "$da 2" >>"${tf}0"
-sleep 1 	# as in SYSTEM
+echo "$da 4" |$CMD1b >/dev/null 2>"${te}1c"
+rc1c=$?
+#sleep 0.5
+relsleep 2
+echo "$da 3" >>"${tf}0"
+relsleep 5 	# as in SHELL
 kill $(childpids $pid0) $pid0 2>/dev/null
 wait 2>/dev/null
 if [ $rc1a -ne 0 -o $rc1b -ne 0 ]; then
-    $PRINTF "$FAILED (rc1a=$rc1a, rc1b=$rc1b)\n"
+    $PRINTF "$FAILED (rc1a=$rc1a, rc1b=$rc1b, rc1c=$rc1c)\n"
     echo "$CMD0"
     cat "${te}0" >&2
     echo "$CMD1a"
     cat "${te}1a" >&2
     echo "$CMD1b"
     cat "${te}1b" >&2
+    echo "$CMD1c"
+    cat "${te}1c" >&2
     failed
-elif $ECHO "$da 1\n$da 2\n$da 3" |diff - ${tf}0 >${tdiff}0; then
+elif $ECHO "$da 1\n$da 2\n$da 3\n$da 4" |diff - ${tf}0 >${tdiff}0; then
     $PRINTF "$OK\n"
     if [ "$VERBOSE" ]; then echo "$CMD0"; fi
     if [ "$DEBUG" ];   then cat "${te}0" >&2; fi
@@ -16904,6 +16948,8 @@ elif $ECHO "$da 1\n$da 2\n$da 3" |diff - ${tf}0 >${tdiff}0; then
     if [ "$DEBUG" ];   then cat "${te}1a" >&2; fi
     if [ "$VERBOSE" ]; then echo "$CMD1b"; fi
     if [ "$DEBUG" ];   then cat "${te}1b" >&2; fi
+    if [ "$VERBOSE" ]; then echo "$CMD1c"; fi
+    if [ "$DEBUG" ];   then cat "${te}1c" >&2; fi
     ok
 else
     $PRINTF "$FAILED (diff)\n"
@@ -16913,7 +16959,9 @@ else
     cat "${te}1a" >&2
     echo "$CMD1b"
     cat "${te}1b" >&2
-    echo "difference:" >&2
+    echo "$CMD1c"
+    cat "${te}1c" >&2
+    echo "// diff:" >&2
     cat ${tdiff}0 >&2
     failed
 fi
@@ -16927,44 +16975,49 @@ NAME=POSIXMQ_SEND_MAXCHILDREN
 case "$TESTS" in
 *%$N%*|*%functions%*|*%fork%*|*%maxchildren%*|*%socket%*|*%posixmq%*|*%$NAME%*)
 TEST="$NAME: POSIX-MQ SEND with fork,max-children"
-# Start a POSIX-MQ receiver that creates a POSIX-MQ and transfers data from it
+# Start a POSIX-MQ receiver that creates the MQ and transfers data from it
 # to an output file
-# Run a POSIX-MQ sender that two times forks and invokes a data generator
-# for messages 1 and 3 in a shell process with some trailing sleep.
-# Afterwards write message 2 directly into output file; message 3 should be
+# Run a POSIX-MQ sender that forks two child shell processes that get data from
+# a file queue with messages 1, 2, and 4, transfer it to the receiver and sleep
+# afterwards to delay the third child by option max-children=2
+# Afterwards write message 3 directly into output file; message 4 should be
 # delayed due to max-children option
 # Check if the messages are stored in order of their numbers.
-# The data generator is implemented as a receiver from an MQ with "1", "3"
+# The data generator is implemented with just a directory containing files
+# "1", "2", "4"
 if ! eval $NUMCOND; then :;
-elif ! cond=$(checkconds "" "" "" "POSIXMQ STDIO SYSTEM" "POSIXMQ-SEND POSIXMQ-READ STDIO SYSTEM" "fork max-children mq-prio unlink-early unlink-close"); then
+elif ! cond=$(checkconds "" "" "" "POSIXMQ STDIO SHELL" "POSIXMQ-SEND POSIXMQ-READ STDIO SHELL" "fork max-children mq-prio unlink-early unlink-close"); then
     $PRINTF "test $F_n $TEST... ${YELLOW}$cond${NORMAL}\n" $N
     cant
 else
 tf="$td/test$N.stdout"
 te="$td/test$N.stderr"
 tdiff="$td/test$N.diff"
+tq="/test$N"
+tQ="$td/test$N.q"
 da="test$N $(date) $RANDOM"
-tq=/test$N
-CMD1="$TRACE $SOCAT $opts -u POSIXMQ-READ:$tq,unlink-early STDIO"
-CMD2="$TRACE $SOCAT $opts -U POSIXMQ-SEND:$tq,fork,max-children=1,interval=0.1 SYSTEM:\"./socat\ -u\ POSIXMQ-RECV\:$tq-data\ -;\ sleep\ 1\""
+CMD1="$TRACE $SOCAT $opts -lp reader -u POSIXMQ-READ:$tq,unlink-early STDIO"
+#CMD2="$TRACE $SOCAT $opts -lp worker -U POSIXMQ-SEND:$tq,fork,max-children=2,interval=$(relsecs 2) SHELL:'f=\$(ls -1 $tQ|head -n 1);\ test\ -f\ "$tQ/\$f"\ ||\ exit\ 1;\ {\ cat\ $tQ/\$f;\ rm\ $tQ/\$f;\ };\ sleep\ $(relsecs 5)'"
+CMD2="$TRACE $SOCAT $opts -lp worker -U POSIXMQ-SEND:$tq,fork,max-children=2,interval=$(relsecs 2) SHELL:'shopt\ -s\ nullglob;\ f=\$(ls -1 $tQ|head -n 1);\ test\ -z\ "\$f"\ &&\ exit;\ {\ cat\ $tQ/\$f;\ rm\ $tQ/\$f;\ };\ sleep\ $(relsecs 5)'"
 printf "test $F_n $TEST... " $N
 # create data for the generator
-echo "$da 1" |$SOCAT -u - POSIXMQ-SEND:$tq-data,unlink-early 2>"${te}0a"
-echo "$da 3" |$SOCAT -u - POSIXMQ-SEND:$tq-data 2>"${te}0b"
+mkdir -p $tQ
+echo "$da 1" >$tQ/01
+echo "$da 2" >$tQ/02
+echo "$da 4" >$tQ/04
 eval $CMD1 2>"${te}1" >>"${tf}1" &
 pid1=$!
 relsleep 1
 eval $CMD2 2>"${te}2" &
 pid2=$!
-sleep 0.5
-echo "$da 2" >>"${tf}1"
-sleep 1 	# as in SYSTEM
-kill $pid1 $(childpids $pid1) $pid2 $(childpids $pid2) 2>/dev/null
+relsleep 4
+echo "$da 3" >>"${tf}1"
+relsleep 10
+kill $(childpids -r $pid1) $pid1 $(childpids -r $pid2) $pid2 2>/dev/null
 wait 2>/dev/null
-# remove the queues
-$SOCAT -u /dev/null POSIXMQ-SEND:$tq-data,unlink-close 2>"${te}3a"
+# remove the MQ
 $SOCAT -u /dev/null POSIXMQ-SEND:$tq,unlink-close 2>"${te}3b"
-if $ECHO "$da 1\n$da 2\n$da 3" |diff - ${tf}1 >${tdiff}1; then
+if $ECHO "$da 1\n$da 2\n$da 3\n$da 4" |diff - ${tf}1 >${tdiff}1; then
     $PRINTF "$OK\n"
     if [ "$VERBOSE" ]; then echo "$CMD1"; fi
     if [ "$DEBUG" ];   then cat "${te}1" >&2; fi
@@ -16977,7 +17030,7 @@ else
     cat "${te}1" >&2
     echo "$CMD2"
     cat "${te}2" >&2
-    echo "difference:" >&2
+    echo "// diff:" >&2
     cat ${tdiff}1 >&2
     failed
 fi
@@ -16985,6 +17038,7 @@ fi # NUMCOND
  ;;
 esac
 N=$((N+1))
+date "+%Y/%m/%d %H:%M:%S.%N"
 
 
 # Test the sigint option with SHELL address
@@ -17184,7 +17238,7 @@ if grep -q " W waitpid..: child .* exited with status 130" "${te}0"; then
     if [ "$DEBUG" ];   then cat "${te}0" >&2; fi
     ok
 else
-    $PRINTF "${YELLOW}FAILED (shell does not propagate SIGINT?${NORMAL}\n"
+    $PRINTF "${YELLOW}FAILED (shell does not propagate SIGINT?)${NORMAL}\n"
     echo "$CMD0 &"
     cat "${te}0" >&2
     cant
@@ -17664,7 +17718,6 @@ fi
 fi # NUMCOND
  ;;
 esac
-PORT=$((PORT+1))
 N=$((N+1))
 
 done <<<"
@@ -17740,7 +17793,6 @@ fi
 fi # NUMCOND
  ;;
 esac
-PORT=$((PORT+1))
 N=$((N+1))
 
 
@@ -17769,7 +17821,7 @@ tf="$td/test$N.stdout"
 te="$td/test$N.stderr"
 tdiff="$td/test$N.diff"
 da="test$N $(date) $RANDOM"
-newport tcp4 	# or whatever proto, or drop this line
+newport tcp4
 # Find the default pipe size
 PIPESZ="$(echo |$FILAN -n 0 |grep "0:" |head -n 1 |sed 's/.*F_GETPIPE_SZ=\([0-9][0-9]*\).*/\1/')"
 PIPESZ2=$((2*PIPESZ))
@@ -17968,7 +18020,6 @@ else
     fi
 fi ;; # NUMCOND
 esac
-PORT=$((PORT+1))
 N=$((N+1))
 
 
@@ -18029,7 +18080,6 @@ else
     fi
 fi ;; # NUMCOND
 esac
-PORT=$((PORT+1))
 N=$((N+1))
 
 
@@ -18090,7 +18140,6 @@ else
     fi
 fi ;; # NUMCOND
 esac
-PORT=$((PORT+1))
 N=$((N+1))
 
 
@@ -18201,10 +18250,10 @@ RUNS=$(tolower $KEYW)
 PROTO=$KEYW
 proto="$(tolower "$PROTO")"
 # test the max-children option on pseudo connected sockets
-NAME=${KEYW}MAXCHILDREN
+NAME=${KEYW}_L_MAXCHILDREN
 case "$TESTS" in
 *%$N%*|*%functions%*|*%fork%*|*%maxchildren%*|*%$SEL%*|*%socket%*|*%listen%*|*%$NAME%*)
-TEST="$NAME: max-children option"
+TEST="$NAME: max-children option with $PROTO-LISTEN"
 # start a listen process with max-children=1; connect with a client, let it
 # send data and then sleep; connect with second client that wants to send
 # data immediately, but keep first client active until server terminates.
@@ -19005,7 +19054,6 @@ fi # NUMCOND
 esac
 N=$((N+1))
 
-
 BIN_TIMEOUT=
 if type timeout >/dev/null 2>&1; then
     BIN_TIMEOUT=timeout
@@ -19164,7 +19212,6 @@ else
 fi # NUMCOND
  ;;
 esac
-PORT=$((PORT+1))
 N=$((N+1))
 done <<<"
 UDP-SENDTO               udp4     PORT
@@ -19236,7 +19283,6 @@ else
 fi # NUMCOND
  ;;
 esac
-PORT=$((PORT+1))
 N=$((N+1))
 done <<<"
 TCP-CONNECT                tcp4      PORT
@@ -19249,7 +19295,9 @@ DCCP-CONNECT               dccp4     PORT
 #ROXY::127.0.0.1           tcp4      PORT
 "
 
+
 # Above tests introduced before or with 1.8.0.1
+#==============================================================================
 # Below test introduced with 1.8.0.2
 
 # Test the readline.sh file overwrite vulnerability
@@ -19310,10 +19358,9 @@ N=$((N+1))
 
 
 # Above test introduced with 1.8.0.2
+#==============================================================================
 # Below tests introduced with 1.8.0.3 (or later)
 
-
-
 # Test the SOCKS5-CONNECT and SOCKS5-LISTEN addresses with IPv4
 for SUFFIX in CONNECT LISTEN; do
 
@@ -19430,7 +19477,7 @@ else
 	cat "${te}0" >&2
 	echo "$CMD1"
 	cat "${te}1" >&2
-	fail
+	failed
     elif ! echo "$da" |diff - "${tf}1" >$tdiff; then
 	$PRINTF "$FAILED (diff)\n"
 	echo "$CMD0 &"
@@ -19439,7 +19486,7 @@ else
 	cat "${te}1" >&2
 	echo "// diff:" >&2
 	cat "$tdiff" >&2
-	fail
+	failed
     else
 	$PRINTF "$OK\n"
 	if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
@@ -19505,6 +19552,535 @@ esac
 N=$((N+1))
 
 
+while read ADDR proto CSUFF CPARMS COPTS SADDR SOPTS PIPE; do
+if [ -z "$ADDR" ] || [[ "$ADDR" == \#* ]]; then continue; fi
+
+if [ "X$CSUFF" != "X-" ]; then
+    CADDR=$ADDR-$CSUFF
+else
+    CADDR=$ADDR
+fi
+CNAME=$(echo $CADDR |tr - _)
+PROTO=$(toupper $proto)
+FEAT=$ADDR
+runs=$proto
+case "$CPARMS" in
+    PORT) newport $proto; CPARMS=$PORT ;;
+    *'$PORT'*) newport $proto; CPARMS=$(eval echo "$CPARMS") ;;
+esac
+#echo "PORT=$PORT CPARMS=$CPARMS" >&2
+case "X$COPTS" in
+    X-) COPTS= ;;
+    *'$PORT'*) newport $proto; COPTS=$(eval echo "$COPTS") ;;
+esac
+case "X$SOPTS" in
+    X-) SOPTS= ;;
+esac
+
+# Test if bind on *-CONNECT selects the matching IP version
+NAME=${CNAME}_BIND_6_4
+case "$TESTS" in
+*%$N%*|*%functions%*|*%$proto%*|*%${proto}4%*|*%${proto}6%*|*%ip4%*|*%ip6%*|*%listen%*|*%bind%*|*%socket%*|*%$NAME%*)
+TEST="$NAME: $ADDR bind chooses matching IPv"
+# Have an IPv4 listener
+# Host name localhost-4-6.dest-unreach.net resolves to both 127.0.0.1 and [::1],
+# consequently; with option -6 we have Socat try IPv6 first, and on failure try
+# IPv4
+# Start Socat TCP-CONNECT with -6 and binding and connecting to this host name;
+# Up to version 1.8.0.0 Socat only tries IPv6 and fails
+# With version 1.8.0.1 Socat first connects using IPv6, and due to ECONNREFUSED
+# tries to connect using IPv4 but still binds to IPv6 which fails with
+# EAFNOSUPPORT "Address family not supported by protocol";
+# With 1.8.0.3 the connection attempt with IPv4 correctly binds to IPv4 and
+# succeeds
+if ! eval $NUMCOND; then :
+elif ! cond=$(checkconds \
+		  "" \
+		  "" \
+		  "" \
+		  "$FEAT IP4 IP6 TCP LISTEN STDIO PIPE" \
+		  "$CADDR $SADDR STDIO PIPE" \
+		  "bind pf" \
+		  "${runs}4 ${runs}6" ); then
+    $PRINTF "test $F_n $TEST... ${YELLOW}$cond${NORMAL}\n" $N
+    cant
+elif ! SOCAT_MAIN_WAIT= $SOCAT -h |grep -e '[[:space:]]-6[[:space:]]' >/dev/null; then
+    $PRINTF "test $F_n $TEST... ${YELLOW}no option -0${NORMAL}\n" $N
+    cant
+else
+    tf="$td/test$N.stdout"
+    te="$td/test$N.stderr"
+    tdiff="$td/test$N.diff"
+    da="test$N $(date) $RANDOM"
+    CMD0="$TRACE $SOCAT $opts $SADDR:$PORT,$SOPTS,pf=2 $PIPE"
+    CMD1="$TRACE $SOCAT $opts -6 STDIO $CADDR:localhost-4-6.dest-unreach.net:$CPARMS,bind=localhost-4-6.dest-unreach.net,$COPTS"
+    printf "test $F_n $TEST... " $N
+    $CMD0 >/dev/null 2>"${te}0" &
+    pid0=$!
+    wait${proto}4port $PORT 1
+    { echo "$da"; relsleep 10; } |$CMD1 >"${tf}1" 2>"${te}1"
+    rc1=$?
+    kill $pid0 2>/dev/null; wait
+    if echo "$da" |diff - "${tf}1" >$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
+	ok
+    elif [ "$rc1" -ne 0 ] && grep "Address family not supported by protocol" "${te}1" >/dev/null; then
+	$PRINTF "$FAILED (EAFNOSUPPORT)\n"
+	echo "$CMD0 &"
+	cat "${te}0" >&2
+	echo "$CMD1"
+	cat "${te}1" >&2
+	failed
+    elif [ "$rc1" -ne 0 ]; then
+	$PRINTF "$CANT (unexpected error)\n"
+	echo "$CMD0 &"
+	cat "${te}0" >&2
+	echo "$CMD1"
+	cat "${te}1" >&2
+	cant
+    elif ! echo "$da" |diff - "${tf}1" >$tdiff; then
+	$PRINTF "$FAILED (diff)\n"
+	echo "$CMD0 &"
+	cat "${te}0" >&2
+	echo "$CMD1"
+	cat "${te}1" >&2
+	echo "// diff:" >&2
+	cat "$tdiff" >&2
+	failed
+    else
+	$PRINTF "$CANT (unexpected problem)\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
+	cant
+    fi
+fi # NUMCOND
+ ;;
+esac
+N=$((N+1))
+
+done <<<"
+TCP     tcp  CONNECT PORT        -                           TCP-L  -                                         PIPE
+SCTP    sctp CONNECT PORT        -                           SCTP-L -                                         PIPE
+DCCP    dccp CONNECT PORT        -                           DCCP-L -                                         PIPE
+OPENSSL tcp  CONNECT PORT        cafile=testsrv.pem,verify=0 SSL-L  cert=testsrv.pem,key=testsrv.key,verify=0 PIPE
+SOCKS4  tcp  -       32.98.76.54:32109 socksport=\$PORT,socksuser=nobody  TCP-L  -             EXEC:./socks4echo.sh
+SOCKS5  tcp  CONNECT \$PORT:127.0.0.1:80  -                               TCP-L  -      EXEC:./socks5server-echo.sh
+PROXY   tcp  CONNECT 127.0.0.1:80        proxyport=\$PORT,crlf            TCP-L  crlf          EXEC:./proxyecho.sh
+"
+
+
+# Test if TCP-CONNECT with host name resolving to IPv6 first and IPv4 second
+# (due to option -6) chooses IPv4 when bind option is specific.
+# This works only since version 1.8.0.3
+NAME=TCP_BIND_4
+case "$TESTS" in
+*%$N%*|*%functions%*|*%internet%*|*%tcp4%*|*%tcp6%*|*%ip4%*|*%ip6%*|*%listen%*|*%socket%*|*%$NAME%*)
+TEST="$NAME: TCP-CONNECT chooses IPv4 from bind"
+# Start a TCP4 listener with echo function
+# Start Socat TCP-CONNECT with host name resolving to IPv6 first and IPv4
+# second, and bind to IPv4 explicitly.
+# When connection and data transfer work the test succeeded.
+if ! eval $NUMCOND; then :
+elif ! cond=$(checkconds \
+		  "" \
+		  "" \
+		  "" \
+		  "IP4 IP6 TCP LISTEN STDIO PIPE" \
+		  "TCP-CONNECT TCP4-LISTEN STDIO PIPE" \
+		  "" \
+		  "tcp4 tcp6" ); then
+    $PRINTF "test $F_n $TEST... ${YELLOW}$cond${NORMAL}\n" $N
+    cant
+elif ! SOCAT_MAIN_WAIT= $SOCAT -h |grep -e '[[:space:]]-6[[:space:]]' >/dev/null; then
+    $PRINTF "test $F_n $TEST... ${YELLOW}no option -0${NORMAL}\n" $N
+    cant
+else
+    tf="$td/test$N.stdout"
+    te="$td/test$N.stderr"
+    tdiff="$td/test$N.diff"
+    da="test$N $(date) $RANDOM"
+    newport tcp4
+    CMD0="$TRACE $SOCAT $opts TCP4-LISTEN:$PORT PIPE"
+    CMD1="$TRACE $SOCAT $opts -6 - TCP-CONNECT:localhost-4-6.dest-unreach.net:$PORT,bind=127.0.0.1"
+    printf "test $F_n $TEST... " $N
+    $CMD0 >/dev/null 2>"${te}0" &
+    pid0=$!
+    waittcp4port $PORT 1
+    echo "$da" |$CMD1 >"${tf}1" 2>"${te}1"
+    rc1=$?
+    kill $pid0 2>/dev/null; wait
+    if echo "$da" |diff - "${tf}1" >$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
+	ok
+    elif [ "$rc1" -ne 0 ] && grep "Address family for hostname not supported" "${te}1" >/dev/null; then
+	$PRINTF "$FAILED (EAFNOSUPPORT)\n"
+	echo "$CMD0 &"
+	cat "${te}0" >&2
+	echo "$CMD1"
+	cat "${te}1" >&2
+	failed
+    elif [ "$rc1" -ne 0 ]; then
+	$PRINTF "$CANT (unexpected error)\n"
+	echo "$CMD0 &"
+	cat "${te}0" >&2
+	echo "$CMD1"
+	cat "${te}1" >&2
+	cant
+    elif ! echo "$da" |diff - "${tf}1" >$tdiff; then
+	$PRINTF "$FAILED (diff)\n"
+	echo "$CMD0 &"
+	cat "${te}0" >&2
+	echo "$CMD1"
+	cat "${te}1" >&2
+	echo "// diff:" >&2
+	cat "$tdiff" >&2
+	failed
+    else
+	$PRINTF "$CANT (unexpected problem)\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
+	cant
+    fi
+fi # NUMCOND
+ ;;
+esac
+N=$((N+1))
+
+# Test if TCP-CONNECT with host name resolving to IPv4 first and IPv6 second
+# (due to option -4) chooses IPv6 when bind option is specific.
+# This works only since version 1.8.0.3
+NAME=TCP_BIND_6
+case "$TESTS" in
+*%$N%*|*%functions%*|*%internet%*|*%tcp4%*|*%tcp6%*|*%ip4%*|*%ip6%*|*%listen%*|*%socket%*|*%$NAME%*)
+TEST="$NAME: TCP-CONNECT chooses IPv6 from bind"
+# Start a TCP6 listener with echo function
+# Start Socat TCP-CONNECT with host name resolving to IPv4 first and IPv6
+# second, and bind to IPv6 explicitly.
+# When connection and data transfer work the test succeeded.
+if ! eval $NUMCOND; then :
+elif ! cond=$(checkconds \
+		  "" \
+		  "" \
+		  "" \
+		  "IP4 IP6 TCP LISTEN STDIO PIPE" \
+		  "TCP-CONNECT TCP4-LISTEN STDIO PIPE" \
+		  "" \
+		  "tcp4 tcp6" ); then
+    $PRINTF "test $F_n $TEST... ${YELLOW}$cond${NORMAL}\n" $N
+    cant
+elif ! SOCAT_MAIN_WAIT= $SOCAT -h |grep -e '[[:space:]]-4[[:space:]]' >/dev/null; then
+    $PRINTF "test $F_n $TEST... ${YELLOW}no option -0${NORMAL}\n" $N
+    cant
+else
+    tf="$td/test$N.stdout"
+    te="$td/test$N.stderr"
+    tdiff="$td/test$N.diff"
+    da="test$N $(date) $RANDOM"
+    newport tcp4
+    CMD0="$TRACE $SOCAT $opts TCP6-LISTEN:$PORT PIPE"
+    CMD1="$TRACE $SOCAT $opt -4 - TCP-CONNECT:localhost-4-6.dest-unreach.net:$PORT,bind=[::1]"
+    printf "test $F_n $TEST... " $N
+    $CMD0 >/dev/null 2>"${te}0" &
+    pid0=$!
+    waittcp4port $PORT 1
+    echo "$da" |$CMD1 >"${tf}1" 2>"${te}1"
+    rc1=$?
+    kill $pid0 2>/dev/null; wait
+    if echo "$da" |diff - "${tf}1" >$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
+	ok
+    elif [ "$rc1" -ne 0 ] && grep "Address family for hostname not supported" "${te}1" >/dev/null; then
+	$PRINTF "$FAILED (EAFNOSUPPORT)\n"
+	echo "$CMD0 &"
+	cat "${te}0" >&2
+	echo "$CMD1"
+	cat "${te}1" >&2
+	failed
+    elif [ "$rc1" -ne 0 ]; then
+	$PRINTF "$CANT (unexpected error)\n"
+	echo "$CMD0 &"
+	cat "${te}0" >&2
+	echo "$CMD1"
+	cat "${te}1" >&2
+	cant
+    elif ! echo "$da" |diff - "${tf}1" >$tdiff; then
+	$PRINTF "$FAILED (diff)\n"
+	echo "$CMD0 &"
+	cat "${te}0" >&2
+	echo "$CMD1"
+	cat "${te}1" >&2
+	echo "// diff:" >&2
+	cat "$tdiff" >&2
+	failed
+    else
+	$PRINTF "$CANT (unexpected problem)\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
+	cant
+    fi
+fi # NUMCOND
+ ;;
+esac
+N=$((N+1))
+
+
+while read ADDR proto CSUFF CPARMS COPTS SADDR SOPTS PIPE; do
+if [ -z "$ADDR" ] || [[ "$ADDR" == \#* ]]; then continue; fi
+
+if [ "X$CSUFF" != "X-" ]; then
+    CADDR=$ADDR-$CSUFF
+else
+    CADDR=$ADDR
+fi
+CNAME=$(echo $CADDR |tr - _)
+PROTO=$(toupper $proto)
+FEAT=$ADDR
+runs=$proto
+case "$CPARMS" in
+    PORT) newport $proto; CPARMS=$PORT ;;
+    *'$PORT'*) newport $proto; CPARMS=$(eval echo "$CPARMS") ;;
+esac
+#echo "PORT=$PORT CPARMS=$CPARMS" >&2
+case "X$COPTS" in
+    X-) COPTS= ;;
+    *'$PORT'*) newport $proto; COPTS=$(eval echo "$COPTS") ;;
+esac
+case "X$SOPTS" in
+    X-) SOPTS= ;;
+esac
+
+# Test the retry option with *-CONNECT addresses
+NAME=${CNAME}_RETRY
+case "$TESTS" in
+*%$N%*|*%functions%*|*%$proto%*|*%${proto}4%*|*%ip4%*|*%listen%*|*%socket%*|*%retry%*|*%$NAME%*)
+TEST="$NAME: $ADDR can retry"
+# Have an IPv4 listener with delay
+# Start a connector whose first attempt must fail; check if the second attempt
+# succeeds.
+if ! eval $NUMCOND; then :
+elif ! cond=$(checkconds \
+		  "" \
+		  "" \
+		  "" \
+		  "$FEAT IP4 TCP LISTEN STDIO" \
+		  "$CADDR $SADDR STDIO PIPE" \
+		  "pf retry interval" \
+		  "${runs}4 ${runs}6" ); then
+    $PRINTF "test $F_n $TEST... ${YELLOW}$cond${NORMAL}\n" $N
+    cant
+elif ! SOCAT_MAIN_WAIT= $SOCAT -h |grep -e '[[:space:]]-6[[:space:]]' >/dev/null; then
+    $PRINTF "test $F_n $TEST... ${YELLOW}no option -0${NORMAL}\n" $N
+    cant
+else
+#    newport $proto
+#echo "PORT=$PORT CPARMS=$CPARMS" >&2
+    tf="$td/test$N.stdout"
+    te="$td/test$N.stderr"
+    tdiff="$td/test$N.diff"
+    da="test$N $(date) $RANDOM"
+    CMD0="relsleep 5; $TRACE $SOCAT $opts $SADDR:$PORT,$SOPTS,pf=2 $PIPE"
+    CMD1="$TRACE $SOCAT $opts -4 STDIO $CADDR:$LOCALHOST:$CPARMS,retry=1,interval=$(relsecs 10),$COPTS"
+    printf "test $F_n $TEST... " $N
+#date +%Y/%m/%d" "%H:%M:%S.%N
+    eval "$CMD0" >/dev/null 2>"${te}0" &
+    pid0=$!
+    { echo "$da"; relsleep 15; } |$CMD1 >"${tf}1" 2>"${te}1"
+    rc1=$?
+    kill $pid0 2>/dev/null; wait
+    if echo "$da" |diff - "${tf}1" >$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
+	ok
+    elif [ "$rc1" -ne 0 ] && grep "Address family not supported by protocol" "${te}1" >/dev/null; then
+	$PRINTF "$FAILED (EAFNOSUPPORT)\n"
+	echo "$CMD0 &"
+	cat "${te}0" >&2
+	echo "$CMD1"
+	cat "${te}1" >&2
+	failed
+    elif [ "$rc1" -ne 0 ]; then
+	$PRINTF "$CANT (unexpected error)\n"
+	echo "$CMD0 &"
+	cat "${te}0" >&2
+	echo "$CMD1"
+	cat "${te}1" >&2
+	cant
+    elif ! echo "$da" |diff - "${tf}1" >$tdiff; then
+	$PRINTF "$FAILED (diff)\n"
+	echo "$CMD0 &"
+	cat "${te}0" >&2
+	echo "$CMD1"
+	cat "${te}1" >&2
+	echo "// diff:" >&2
+	cat "$tdiff" >&2
+	failed
+    else
+	$PRINTF "$CANT (unexpected problem)\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
+	cant
+    fi
+fi # NUMCOND
+ ;;
+esac
+N=$((N+1))
+
+done <<<"
+TCP     tcp  CONNECT PORT        -                           TCP-L  -                                         PIPE
+SCTP    sctp CONNECT PORT        -                           SCTP-L -                                         PIPE
+DCCP    dccp CONNECT PORT        -                           DCCP-L -                                         PIPE
+OPENSSL tcp  CONNECT PORT        cafile=testsrv.pem,verify=0 SSL-L  cert=testsrv.pem,key=testsrv.key,verify=0 PIPE
+SOCKS4  tcp  -       32.98.76.54:32109 socksport=\$PORT,socksuser=nobody  TCP-L  -             EXEC:./socks4echo.sh
+SOCKS5  tcp  CONNECT \$PORT:127.0.0.1:80  -                               TCP-L  -      EXEC:./socks5server-echo.sh
+PROXY   tcp  CONNECT 127.0.0.1:80        proxyport=\$PORT,crlf            TCP-L  crlf          EXEC:./proxyecho.sh
+"
+
+#------------------------------------------------------------------------------
+
+while read ADDR proto CSUFF CPARMS COPTS SADDR SOPTS PIPE SLOW; do
+if [ -z "$ADDR" ] || [[ "$ADDR" == \#* ]]; then continue; fi
+
+if [ "X$CSUFF" != "X-" ]; then
+    CADDR=$ADDR-$CSUFF
+else
+    CADDR=$ADDR
+fi
+CNAME=$(echo $CADDR |tr - _)
+PROTO=$(toupper $proto)
+FEAT=$ADDR
+runs=$proto
+case "$CPARMS" in
+    PORT) newport $proto; CPARMS=$PORT ;;
+    *'$PORT'*) newport $proto; CPARMS=$(eval echo "$CPARMS") ;;
+esac
+#echo "PORT=$PORT CPARMS=$CPARMS" >&2
+case "X$COPTS" in
+    X-) COPTS= ;;
+    *'$PORT'*) newport $proto; COPTS=$(eval echo "$COPTS") ;;
+esac
+case "X$SOPTS" in
+    X-) SOPTS= ;;
+esac
+
+# Test the fork and max-children options with CONNECT addresses
+NAME=${CNAME}_MAXCHILDREN
+case "$TESTS" in
+*%$N%*|*%functions%*|*%$proto%*|*%${proto}4%*|*%ip4%*|*%listen%*|*%socket%*|*%fork%*|*%maxchildren%*|*%$NAME%*)
+TEST="$NAME: $ADDR with fork,max-children"
+# Start a reader process that transfers received data to an output file;
+# run a sending client that forks at most 2 parallel child processes that
+# transfer data from a simple directory queue to the reader but afterwards
+# hang some time to prevent more child process.
+# After the first two transfers write the third record directly to the file;
+# a little later the Socat mechanism puts a 4th record.
+# When the 4 records in the output file have the expected order the test
+# succeeded.
+if ! eval $NUMCOND; then :
+elif ! cond=$(checkconds \
+		  "" \
+		  "" \
+		  "" \
+		  "$FEAT IP4 TCP LISTEN STDIO PIPE" \
+		  "$CADDR $SADDR STDIO PIPE" \
+		  "pf" \
+		  "${runs}4" ); then
+    $PRINTF "test $F_n $TEST... ${YELLOW}$cond${NORMAL}\n" $N
+    cant
+else
+#    newport $proto
+#echo "PORT=$PORT CPARMS=$CPARMS" >&2
+    tf="$td/test$N.stdout"
+    te="$td/test$N.stderr"
+    tdiff="$td/test$N.diff"
+    tQ="$td/test$N.q"
+    ext=q.y.f. 	# some unusual extension to prevent from deleting wrong file
+    da="test$N $(date) $RANDOM"
+    CMD0="$TRACE $SOCAT $opts -lp reader $SADDR:$PORT,$SOPTS,pf=2,reuseaddr,fork $PIPE"
+    CMD1="$TRACE $SOCAT $opts -4 $CADDR:$LOCALHOST:$CPARMS,fork,max-children=2,interval=$(relsecs $((2*SLOW))),$COPTS SHELL:'shopt\ -s\ nullglob;\ F=\$(ls -1 $tQ|grep .$ext\\\$|head -n 1);\ test\ \"\$F\"\ ||\ exit;\ cat\ $tQ/\$F;\ mv\ -i\ $tQ/\$F\ $tQ/.\$F;\ sleep\ $(relsecs $((5*SLOW)) )'!!-"
+    printf "test $F_n $TEST... " $N
+    # create data for the generator
+    mkdir -p $tQ
+    echo "$da 1" >$tQ/01.$ext
+    echo "$da 2" >$tQ/02.$ext
+    echo "$da 4" >$tQ/04.$ext
+    eval "$CMD0" 2>"${te}0" &
+    pid0=$!
+    relsleep $((1*SLOW))
+    eval $CMD1 2>"${te}1" >>"${tf}0" &
+    pid1=$!
+    relsleep $((4*SLOW))
+#date +%Y/%m/%d" "%H:%M:%S.%N
+    echo "$da 3" >>"${tf}0"
+    relsleep $((4*SLOW))
+    kill $(childpids -r $pid0) $pid0 $(childpids -r $pid1) $pid1 2>/dev/null
+    wait 2>/dev/null
+    if ! test -e "${tf}0" || ! test -s "${tf}0"; then
+	$PRINTF "$FAILED\n"
+	echo "$CMD0 &"
+	cat "${te}0" >&2
+	echo "$CMD1"
+	cat "${te}1" >&2
+	failed
+    elif $ECHO "$da 1\n$da 2\n$da 3\n$da 4" |diff - ${tf}0 >$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
+	ok
+    else
+	$PRINTF "$FAILED (diff)\n"
+	echo "$CMD0 &"
+	cat "${te}0" >&2
+	echo "$CMD1"
+	cat "${te}1" >&2
+	echo "// diff:" >&2
+	cat "$tdiff" >&2
+	failed
+    fi
+fi # NUMCOND
+ ;;
+esac
+N=$((N+1))
+
+done <<<"
+TCP     tcp  CONNECT PORT         -                                TCP-L  -                           PIPE 1
+SCTP    sctp CONNECT PORT         -                                SCTP-L -                           PIPE 1
+DCCP    dccp CONNECT PORT         -                                DCCP-L -                           PIPE 1
+OPENSSL tcp  CONNECT PORT cafile=testsrv.pem,verify=0 SSL-L cert=testsrv.pem,key=testsrv.key,verify=0 PIPE 6
+SOCKS4  tcp  - 32.98.76.54:32109 socksport=\$PORT,socksuser=nobody TCP-L  -           EXEC:./socks4echo.sh 6
+SOCKS5  tcp  CONNECT \$PORT:127.0.0.1:80  -                        TCP-L  -    EXEC:./socks5server-echo.sh 5
+PROXY   tcp  CONNECT 127.0.0.1:80 proxyport=\$PORT,crlf            TCP-L  crlf         EXEC:./proxyecho.sh 4
+"
+# detto IP6
+
+
+# test combined 4_6/6_4 with retry and fork
+
+
 # end of common tests
 
 ##################################################################################
@@ -19519,7 +20095,7 @@ case "$TESTS" in
 TEST="$NAME: pty with group-late works on pty"
 # up to socat 1.7.1.1 address pty changed the ownership of /dev/ptmx instead of
 # the pty with options user-late, group-late, or perm-late.
-# here we check for correct behaviour. 
+# here we check for correct behaviour.
 # ATTENTION: in case of failure of this test the
 # group of /dev/ptmx might be changed!
 if ! eval $NUMCOND; then :; else
@@ -19626,7 +20202,7 @@ rm -f testsrv.* testcli.* testsrvdsa* testsrvfips* testclifips*
 # end
 
 # too dangerous - run as root and having a shell problem, it might purge your
-# file systems 
+# file systems
 #rm -r "$td"
 
 # sometimes subprocesses hang; we want to see this
diff --git a/xio-ip.c b/xio-ip.c
index a0c12c9..7b1c56e 100644
--- a/xio-ip.c
+++ b/xio-ip.c
@@ -161,6 +161,79 @@ int Res_init(void) {
 #endif /* HAVE_RESOLV_H */
 
 
+/* Looks for a bind option and, if found, passes it to resolver;
+   for IP (v4, v6) and raw (PF_UNSPEC);
+   returns list of addrinfo results;
+   returns STAT_OK if option exists and could be resolved,
+   STAT_NORETRY if option exists but had error,
+   or STAT_NOACTION if it does not exist */
+int retropt_bind_ip(
+	struct opt *opts,
+	int af,
+	int socktype,
+	int ipproto,
+	struct addrinfo ***bindlist,
+	int feats,	/* TCP etc: 1..address allowed,
+			   3..address and port allowed
+			*/
+	const int ai_flags[2])
+{
+   const char portsep[] = ":";
+   const char *ends[] = { portsep, NULL };
+   const char *nests[] = { "[", "]", NULL };
+   bool portallowed;
+   char *bindname, *bindp;
+   char hostname[512], *hostp = hostname, *portp = NULL;
+   size_t hostlen = sizeof(hostname)-1;
+   int parsres;
+   int ai_flags2[2];
+   int result;
+
+   if (retropt_string(opts, OPT_BIND, &bindname) < 0) {
+      return STAT_NOACTION;
+   }
+   bindp = bindname;
+
+      portallowed = (feats>=2);
+      parsres =
+	 nestlex((const char **)&bindp, &hostp, &hostlen, ends, NULL, NULL, nests,
+		 true, false, false);
+      if (parsres < 0) {
+	 Error1("option too long:  \"%s\"", bindp);
+	 return STAT_NORETRY;
+      } else if (parsres > 0) {
+	 Error1("syntax error in \"%s\"", bindp);
+	 return STAT_NORETRY;
+      }
+      *hostp++ = '\0';
+      if (!strncmp(bindp, portsep, strlen(portsep))) {
+	 if (!portallowed) {
+	    Error("port specification not allowed in this bind option");
+	    return STAT_NORETRY;
+	 } else {
+	    portp = bindp + strlen(portsep);
+	 }
+      }
+
+      /* Set AI_PASSIVE, except when it is explicitely disabled */
+      ai_flags2[0] = ai_flags[0];
+      ai_flags2[1] = ai_flags[1];
+      if (!(ai_flags2[1] & AI_PASSIVE))
+      ai_flags2[0] |= AI_PASSIVE;
+
+      if ((result =
+	   xiogetaddrinfo(hostname[0]!='\0'?hostname:NULL, portp,
+		      af, socktype, ipproto,
+		      bindlist, ai_flags2))
+	  != STAT_OK) {
+	 Error2("error resolving bind option \"%s\" with af=%d", bindname, af);
+	 return STAT_NORETRY;
+      }
+
+      return STAT_OK;
+}
+
+
 #if WITH_DEVTESTS
 
 /* Have a couple of hard coded sockaddr records, to be copied and adapted when
@@ -516,11 +589,11 @@ int _xiogetaddrinfo(const char *node, const char *service,
 	   continue;
 	}
       if ((error_num = Getaddrinfo(node, service, &hints, res)) != 0) {
-	 Warn7("getaddrinfo(\"%s\", \"%s\", {0x%02x,%d,%d,%d}, {}): %d",
+	 Warn7("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,
-		error_num);
+		gai_strerror(error_num));
 	 if (numnode)
 	    free(numnode);
 
@@ -760,6 +833,9 @@ void xiofreeaddrinfo(struct addrinfo **ai_sorted) {
    int ain;
    struct addrinfo *res;
 
+   if (ai_sorted == NULL)
+      return;
+
    /* Find the original *res from getaddrinfo past NULL */
    ain = 0;
    while (ai_sorted[ain] != NULL)
diff --git a/xio-ip.h b/xio-ip.h
index ec94e16..c6c0355 100644
--- a/xio-ip.h
+++ b/xio-ip.h
@@ -49,6 +49,7 @@ extern const struct optdesc opt_res_nsaddr;
 
 extern int xioinit_ip(int *pf, char ipv);
 
+extern int retropt_bind_ip(struct opt *opts, int af, int socktype, int ipproto, struct addrinfo ***bindlist, int feats, const int ai_flags[2]);
 extern int xiogetaddrinfo(const char *node, const char *service, int family, int socktype, int protocol, struct addrinfo ***ai_sorted, const int ai_flags[2]);
 extern void xiofreeaddrinfo(struct addrinfo **ai_sorted);
 extern int _xio_sort_ip_addresses(struct addrinfo *themlist, struct addrinfo **ai_sorted);
diff --git a/xio-ipapp.c b/xio-ipapp.c
index fcc0d33..53c505d 100644
--- a/xio-ipapp.c
+++ b/xio-ipapp.c
@@ -19,6 +19,7 @@ const struct optdesc opt_sourceport = { "sourceport", "sp",       OPT_SOURCEPORT
 /*const struct optdesc opt_port = { "port",  NULL,    OPT_PORT,        GROUP_IPAPP, PH_BIND,    TYPE_USHORT,	OFUNC_SPEC };*/
 const struct optdesc opt_lowport = { "lowport", NULL, OPT_LOWPORT, GROUP_IPAPP, PH_LATE, TYPE_BOOL, OFUNC_SPEC };
 
+
 #if _WITH_IP4 || _WITH_IP6
 /* we expect the form "host:port" */
 int xioopen_ipapp_connect(
@@ -31,20 +32,18 @@ int xioopen_ipapp_connect(
 {
    struct single *sfd = &xxfd->stream;
    struct opt *opts0 = NULL;
+   const char *hostname = argv[1], *portname = argv[2];
+   int pf = addrdesc->arg3;
    int socktype = addrdesc->arg1;
    int ipproto = addrdesc->arg2;
-   int pf = addrdesc->arg3;
-   const char *hostname = argv[1], *portname = argv[2];
    bool dofork = false;
    int maxchildren = 0;
-   union sockaddr_union us_sa,  *us = &us_sa;
-   socklen_t uslen = sizeof(us_sa);
-   struct addrinfo **themarr, *themp;
-   char infobuff[256];
+   struct addrinfo **bindarr = NULL;
+   struct addrinfo **themarr = NULL;
+   uint16_t bindport = 0;
    bool needbind = false;
    bool lowport = false;
-   int level;
-   int i;
+   int level = E_ERROR;
    int result;
 
    if (argc != 3) {
@@ -52,97 +51,84 @@ int xioopen_ipapp_connect(
       return STAT_NORETRY;
    }
 
-   if (sfd->howtoend == END_UNSPEC)
-      sfd->howtoend = END_SHUTDOWN;
+   /* Apply and retrieve some options */
+   result = _xioopen_ipapp_init(sfd, xioflags, opts,
+				&dofork, &maxchildren,
+				&pf, &socktype, &ipproto);
+   if (result != STAT_OK)
+      return result;
 
-   if (applyopts_single(sfd, opts, PH_INIT) < 0)
-      return -1;
-   applyopts(sfd, -1, opts, PH_INIT);
+   opts0 = opts; 	/* save remaining options for each loop */
+   opts = NULL;
 
-   retropt_bool(opts, OPT_FORK, &dofork);
-   if (dofork) {
-      if (!(xioflags & XIO_MAYFORK)) {
-	 Error("option fork not allowed here");
-	 return STAT_NORETRY;
-      }
-      sfd->flags |= XIO_DOESFORK;
-   }
+   Notice2("opening connection to %s:%s", hostname, portname);
 
-   retropt_int(opts, OPT_MAX_CHILDREN, &maxchildren);
-
-   if (! dofork && maxchildren) {
-       Error("option max-children not allowed without option fork");
-       return STAT_NORETRY;
-   }
-
-   if (_xioopen_ipapp_prepare(opts, &opts0, hostname, portname, &pf, ipproto,
-			      sfd->para.socket.ip.ai_flags,
-			      &themarr, us, &uslen, &needbind, &lowport,
-			      socktype) != STAT_OK) {
-      return STAT_NORETRY;
-   }
-
-   if (dofork) {
-      xiosetchilddied();	/* set SIGCHLD handler */
-   }
-
-   if (xioparms.logopt == 'm') {
-      Info("starting connect loop, switching to syslog");
-      diag_set('y', xioparms.syslogfac);  xioparms.logopt = 'y';
-   } else {
-      Info("starting connect loop");
-   }
-
-   do {	/* loop over retries, and forks */
-
-      /* Loop over themarr (which had been "ai_sorted") */
-      result = STAT_RETRYLATER;
-      i = 0;
-      themp = themarr[i++];
-      while (themp != NULL) {
-	 Notice1("opening connection to %s",
-		 sockaddr_info(themp->ai_addr, themp->ai_addrlen,
-			       infobuff, sizeof(infobuff)));
+   do {	/* loop over retries and/or forks */
+      int _errno;
 
 #if WITH_RETRY
-	 if (sfd->forever || sfd->retry) {
-	    level = E_INFO;
-	 } else if (themarr[i] != NULL) {
-	    level = E_WARN;
-         } else
+      if (sfd->forever || sfd->retry) {
+	 level = E_NOTICE;
+      } else
 #endif /* WITH_RETRY */
-	    level = E_ERROR;
+	 level = E_WARN;
 
-       result =
-	 _xioopen_connect(sfd,
-			  needbind?us:NULL, uslen,
-			  themp->ai_addr, themp->ai_addrlen,
-			  opts, pf?pf:themp->ai_family, socktype, ipproto,
-			  lowport, level);
-       if (result == STAT_OK)
-	  break;
-       themp = themarr[i++];
-       if (themp == NULL) {
-	  result = STAT_RETRYLATER;
-       }
-      }
+      opts = copyopts(opts0, GROUP_ALL);
+
+      result =
+	 _xioopen_ipapp_prepare(&opts, opts0, hostname, portname,
+				pf, socktype, ipproto,
+				sfd->para.socket.ip.ai_flags,
+				&themarr, &bindarr, &bindport, &needbind, &lowport);
       switch (result) {
       case STAT_OK: break;
 #if WITH_RETRY
       case STAT_RETRYLATER:
       case STAT_RETRYNOW:
-	 if (sfd->forever || sfd->retry) {
-	    --sfd->retry;
-	    if (result == STAT_RETRYLATER) {
+	 if (sfd->forever || sfd->retry--) {
+	    if (result == STAT_RETRYLATER)
 	       Nanosleep(&sfd->intervall, NULL);
-	    }
-	    dropopts(opts, PH_ALL); free(opts); opts = copyopts(opts0, GROUP_ALL);
+	    if (bindarr != NULL)  xiofreeaddrinfo(bindarr);
+	    xiofreeaddrinfo(themarr);
+	    freeopts(opts);
 	    continue;
 	 }
 #endif /* WITH_RETRY */
-      default:
+	 /* FALLTHROUGH */
+      case STAT_NORETRY:
+	 if (bindarr != NULL)  xiofreeaddrinfo(bindarr);
 	 xiofreeaddrinfo(themarr);
-	 free(opts0);free(opts);
+	 freeopts(opts);
+	 freeopts(opts0);
+	 return result;
+      }
+
+      result =
+	 _xioopen_ipapp_connect(sfd, hostname, opts, themarr,
+				needbind, bindarr, bindport, lowport, level);
+      _errno = errno;
+      if (bindarr != NULL)
+	 xiofreeaddrinfo(bindarr);
+      xiofreeaddrinfo(themarr);
+      switch (result) {
+      case STAT_OK: break;
+#if WITH_RETRY
+      case STAT_RETRYLATER:
+      case STAT_RETRYNOW:
+	 if (sfd->forever || sfd->retry--) {
+	    if (result == STAT_RETRYLATER) {
+	       Nanosleep(&sfd->intervall, NULL);
+	    }
+	    freeopts(opts);
+	    continue;
+	 }
+#endif /* WITH_RETRY */
+	 /* FALLTHROUGH */
+      default:
+	 Error4("%s:%s:%s: %s", argv[0], argv[1], argv[2],
+		_errno?strerror(_errno):"(See above)");
+	 freeopts(opts);
+	 freeopts(opts0);
 	 return result;
       }
 
@@ -155,16 +141,18 @@ int xioopen_ipapp_connect(
 				   so Notice is too weak */
 	 }
 	 while ((pid = xio_fork(false, level, sfd->shutup)) < 0) {
-	    if (sfd->forever || --sfd->retry) {
-	       Nanosleep(&sfd->intervall, NULL); continue;
+	    if (sfd->forever || sfd->retry--) {
+	       Nanosleep(&sfd->intervall, NULL);
+	       continue;
 	    }
-	    xiofreeaddrinfo(themarr);
-	    free(opts0);
+	    freeopts(opts);
+	    freeopts(opts0);
 	    return STAT_RETRYLATER;
 	 }
 
 	 if (pid == 0) {	/* child process */
-	    sfd->forever = false;  sfd->retry = 0;
+	    sfd->forever = false;
+	    sfd->retry = 0;
 	    break;
 	 }
 
@@ -176,109 +164,266 @@ int xioopen_ipapp_connect(
 	    Info1("all %d allowed children are active, waiting", maxchildren);
 	    Nanosleep(&sfd->intervall, NULL);
 	 }
-	 dropopts(opts, PH_ALL); free(opts); opts = copyopts(opts0, GROUP_ALL);
+	 freeopts(opts);
 	 continue;	/* with next socket() bind() connect() */
       } else
 #endif /* WITH_RETRY */
       {
 	 break;
       }
-   } while (true);
+   } while (true); 	/* end of loop over retries and/or forks */
    /* only "active" process breaks (master without fork, or child) */
-   xiofreeaddrinfo(themarr);
 
-   if ((result = _xio_openlate(sfd, opts)) < 0) {
-	   free(opts0);free(opts);
-      return result;
-   }
-   free(opts0); free(opts);
-   return 0;
+   Notice2("successfully connected to %s:%s", hostname, portname);
+
+   result = _xio_openlate(sfd, opts);
+   freeopts(opts);
+   freeopts(opts0);
+   return result;
 }
 
 
-/* returns STAT_OK on success or some other value on failure
+/* This function performs static initializations for addresses like TCP-CONNECT
+   before start of the outer loop:
+   it retrieves some options
+   returns STAT_OK on success or some other value on failure;
+   applies and consumes the following options:
+   PH_INIT, OPT_FORK, OPT_MAX_CHILDREN, OPT_PROTOCOL_FAMILY, OPT_SO_TYPE,
+   OPT_SO_PROTOTYPE
+*/
+int _xioopen_ipapp_init(
+	struct single *sfd,
+	int xioflags,
+	struct opt *opts,
+	bool *dofork,
+	int *maxchildren,
+	int *pf,
+	int *socktype,
+	int *ipproto)
+{
+   if (sfd->howtoend == END_UNSPEC)
+      sfd->howtoend = END_SHUTDOWN;
+
+   if (applyopts_single(sfd, opts, PH_INIT) < 0)
+      return -1;
+   if (applyopts(sfd, -1, opts, PH_INIT) < 0)
+      return -1;
+
+   retropt_bool(opts, OPT_FORK, dofork);
+   if (dofork) {
+      if (!(xioflags & XIO_MAYFORK)) {
+	 Error1("%s: option fork not allowed here", sfd->addr->defname);
+	 return STAT_NORETRY;
+      }
+      sfd->flags |= XIO_DOESFORK;
+   }
+
+   retropt_int(opts, OPT_MAX_CHILDREN, maxchildren);
+   if (! dofork && maxchildren) {
+      Error1("%s: option max-children not allowed without option fork", sfd->addr->defname);
+      return STAT_NORETRY;
+   }
+
+   retropt_socket_pf(opts, pf);
+   retropt_int(opts, OPT_SO_TYPE, socktype);
+   retropt_int(opts, OPT_SO_PROTOTYPE, ipproto);
+
+   if (dofork) {
+      xiosetchilddied();	/* set SIGCHLD handler */
+   }
+
+   if (xioparms.logopt == 'm') {
+      Info("starting connect loop, switching to syslog");
+      diag_set('y', xioparms.syslogfac);
+      xioparms.logopt = 'y';
+   } else {
+      Info("starting connect loop");
+   }
+
+   return STAT_OK;
+}
+
+
+/* This function performs preparations for addresses like TCP-CONNECT
+   at the beginning of the outer (retry/fork) loop:
+   it evaluates some options and performs name resolution of both server
+   (target, "them") address and bind ("us") address.
+   It is intended to be invoked before the connect loop starts;
+   returns STAT_OK on success or some other value on failure;
    applies and consumes the following options:
    PH_EARLY
-   OPT_PROTOCOL_FAMILY, OPT_BIND, OPT_SOURCEPORT, OPT_LOWPORT
- */
-int
-   _xioopen_ipapp_prepare(
-	   struct opt *opts,
-	   struct opt **opts0,
-	   const char *hostname,
-	   const char *portname,
-	   int *pf,
-	   int protocol,
-	   const int ai_flags[2],
-	   struct addrinfo ***themarr,
-	   union sockaddr_union *us,
-	   socklen_t *uslen,
-	   bool *needbind,
-	   bool *lowport,
-	   int socktype) {
+   OPT_BIND, OPT_SOURCEPORT, OPT_LOWPORT
+   returns STAT_OK, STAT_RETRYLATER, or STAT_NORETRY (+errno)
+*/
+int _xioopen_ipapp_prepare(
+	struct opt **opts,
+	struct opt *opts0,
+	const char *hostname,
+	const char *portname,
+	int pf,
+	int socktype,
+	int protocol,
+	const int ai_flags[2],
+	struct addrinfo ***themarr, 	/* always from getaddrinfo(); xiofreeaddrinfo()! */
+	struct addrinfo ***bindarr, 	/* on bind from getaddrinfo(); xiofreeaddrinfo()! */
+	uint16_t *bindport, 		/* for bind without address */
+	bool *needbind,
+	bool *lowport)
+{
    uint16_t port;
    int rc;
 
-   retropt_socket_pf(opts, pf);
+   *opts = copyopts(opts0, GROUP_ALL);
 
    if (hostname != NULL || portname != NULL) {
-      rc = xiogetaddrinfo(hostname, portname, *pf, socktype, protocol,
+      rc = xiogetaddrinfo(hostname, portname, pf, socktype, protocol,
 			  themarr, ai_flags);
       if (rc == EAI_AGAIN) {
 	 Warn4("_xioopen_ipapp_prepare(node=\"%s\", service=\"%s\", pf=%d, ...): %s",
 	       hostname?hostname:"NULL", portname?portname:"NULL",
-	       *pf, gai_strerror(rc));
+	       pf, gai_strerror(rc));
+	 errno = EAGAIN;
 	 return STAT_RETRYLATER;
       } else if (rc != 0) {
 	 Error4("_xioopen_ipapp_prepare(node=\"%s\", service=\"%s\", pf=%d, ...): %s",
 		hostname?hostname:"NULL", portname?portname:"NULL",
-		*pf, (rc == EAI_SYSTEM)?strerror(errno):gai_strerror(rc));
+		pf, (rc == EAI_SYSTEM)?strerror(errno):gai_strerror(rc));
+	 errno = 0; 	/* unspecified */
 	 return STAT_NORETRY;	/*! STAT_RETRYLATER? */
       }
    }
 
-   applyopts(NULL, -1, opts, PH_EARLY);
+   applyopts(NULL, -1, *opts, PH_EARLY);
 
    /* 3 means: IP address AND port accepted */
-   if (retropt_bind(opts, (*pf!=PF_UNSPEC)?*pf:(**themarr)->ai_family,
-		    socktype, protocol, (struct sockaddr *)us, uslen, 3,
-		    ai_flags)
+   if (retropt_bind_ip(*opts, pf, socktype, protocol, bindarr, 3, ai_flags)
        != STAT_NOACTION) {
       *needbind = true;
-   } else {
-      switch ((*pf!=PF_UNSPEC)?*pf:(**themarr)->ai_family) {
-#if WITH_IP4
-      case PF_INET:  socket_in_init(&us->ip4);  *uslen = sizeof(us->ip4); break;
-#endif /* WITH_IP4 */
-#if WITH_IP6
-      case PF_INET6: socket_in6_init(&us->ip6); *uslen = sizeof(us->ip6); break;
-#endif /* WITH_IP6 */
-      default: Error("unsupported protocol family");
-      }
    }
-
-   if (retropt_2bytes(opts, OPT_SOURCEPORT, &port) >= 0) {
-      switch ((*pf!=PF_UNSPEC)?*pf:(**themarr)->ai_family) {
+   if (retropt_2bytes(*opts, OPT_SOURCEPORT, &port) >= 0) {
+      if (*bindarr) {
+	 struct addrinfo **bindp;
+	 bindp = *bindarr;
+	 switch ((*bindp)->ai_family) {
 #if WITH_IP4
-      case PF_INET:  us->ip4.sin_port = htons(port); break;
+	 case PF_INET:  ((struct sockaddr_in *)(*bindp)->ai_addr)->sin_port = htons(port); break;
 #endif /* WITH_IP4 */
 #if WITH_IP6
-      case PF_INET6: us->ip6.sin6_port = htons(port); break;
+	 case PF_INET6: ((struct sockaddr_in6 *)(*bindp)->ai_addr)->sin6_port = htons(port); break;
 #endif /* WITH_IP6 */
-      default: Error("unsupported protocol family");
+	 default:
+	    Error("unsupported protocol family");
+	    errno = EPROTONOSUPPORT;
+	    return STAT_NORETRY;
+	 }
+      } else {
+	 *bindport = port;
       }
       *needbind = true;
    }
 
-   retropt_bool(opts, OPT_LOWPORT, lowport);
-
-   *opts0 = copyopts(opts, GROUP_ALL);
+   retropt_bool(*opts, OPT_LOWPORT, lowport);
 
    return STAT_OK;
 }
 #endif /* _WITH_IP4 || _WITH_IP6 */
 
 
+/* Tries to connect to the addresses in themarr, for each one it tries to bind
+   to the addresses in bindarr.
+   Ends on success or when all attempts failed.
+   Returns STAT_OK on success, or STAT_RETRYLATER (+errno) on failure. */
+int _xioopen_ipapp_connect(struct single *sfd,
+			   const char *hostname,
+			   struct opt *opts,
+			   struct addrinfo **themarr,
+			   bool needbind,
+			   struct addrinfo **bindarr,
+			   uint16_t bindport,
+			   bool lowport,
+			   int level)
+{
+   struct addrinfo **themp;
+   struct addrinfo **bindp;
+   union sockaddr_union bindaddr = {0};
+   union sockaddr_union *bindaddrp = NULL;
+   socklen_t bindlen = 0;
+   char infobuff[256];
+   int _errno;
+   int result = STAT_OK;
+
+   --level;
+
+   /* Loop over server addresses (themarr) */
+   themp = themarr;
+   while (*themp != NULL) {
+      Notice1("opening connection to %s",
+	      sockaddr_info((*themp)->ai_addr, (*themp)->ai_addrlen,
+			    infobuff, sizeof(infobuff)));
+
+      if (*(themp+1) == NULL) {
+	 ++level; 	/* last attempt */
+      }
+
+      /* Loop over array (list) of bind addresses */
+      if (needbind && bindarr != NULL) {
+	 /* Bind by hostname, use resolvers results list */
+	 bindp = bindarr;
+	 while (*bindp != NULL) {
+	    if ((*bindp)->ai_family == (*themp)->ai_family)
+	       break;
+	    ++bindp;
+	 }
+	 if (*bindp == NULL) {
+	    Warn3("%s: No bind address with matching address family (%d) of %s available",
+		  sfd->addr->defname, (*themp)->ai_family, hostname);
+	    ++themp;
+	    if ((*themp) == NULL) {
+	       result = STAT_RETRYLATER;
+	    }
+	    _errno = ENOPROTOOPT;
+	    continue;
+	 }
+	 bindaddrp = (union sockaddr_union *)(*bindp)->ai_addr;
+	 bindlen  = (*bindp)->ai_addrlen;
+      } else if (needbind && bindport) {
+	 /* Bind by sourceport option */
+	 switch ((*themp)->ai_family) {
+	 case PF_INET:
+	    bindaddr.ip4.sin_family = (*themp)->ai_family;
+	    bindaddr.ip4.sin_port = htons(bindport);
+	    bindaddrp = &bindaddr;
+	    bindlen = sizeof(bindaddr.ip4);
+	    break;
+	 case PF_INET6:
+	    bindaddr.ip6.sin6_family = (*themp)->ai_family;
+	    bindaddr.ip6.sin6_port = htons(bindport);
+	    bindaddrp = &bindaddr;
+	    bindlen = sizeof(bindaddr.ip6);
+	    break;
+	 }
+      }
+
+      result =
+	 _xioopen_connect(sfd,
+			  bindaddrp, bindlen,
+			  (*themp)->ai_addr, (*themp)->ai_addrlen,
+			  opts, /*pf?pf:*/(*themp)->ai_family, (*themp)->ai_socktype, (*themp)->ai_protocol,
+			  lowport, level);
+      if (result == STAT_OK)
+	 break;
+      _errno = errno;
+      ++themp;
+      if (*themp == NULL)
+	 result = STAT_RETRYLATER;
+   } 	/* end of loop over target addresses */
+
+   if (result != STAT_OK)
+      errno = _errno;
+   return result;
+}
+
+
 #if WITH_TCP && WITH_LISTEN
 /*
    applies and consumes the following options:
diff --git a/xio-ipapp.h b/xio-ipapp.h
index af9e7b4..e190e36 100644
--- a/xio-ipapp.h
+++ b/xio-ipapp.h
@@ -15,11 +15,9 @@ extern const struct optdesc opt_sourceport;
 extern const struct optdesc opt_lowport;
 
 extern int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, const struct addrdesc *addrdesc);
-extern int _xioopen_ipapp_prepare(struct opt *opts, struct opt **opts0, const char *hostname, const char *portname, int *pf, int protocol, const int ai_flags[2], struct addrinfo ***themlist, union sockaddr_union *us,  socklen_t *uslen, bool *needbind, bool *lowport, int socktype);
-extern int _xioopen_ip4app_connect(const char *hostname, const char *portname,
-				   struct single *xfd,
-				   int socktype, int ipproto, void *protname,
-				   struct opt *opts);
+extern int _xioopen_ipapp_init(struct single *sfd, int xioflags, struct opt *opts, bool *dofork, int *maxchildren, int *pf, int *socktype, int *protocol);
+extern int _xioopen_ipapp_prepare(struct opt **opts, struct opt *opts0, const char *hostname, const char *portname, int pf, int socktype, int protocol, const int ai_flags[2], struct addrinfo ***themarr, struct addrinfo ***bindarr, uint16_t *bindport, bool *needbind, bool *lowport);
+extern int _xioopen_ipapp_connect(struct single *sfd, const char *hostname, struct opt *opts, struct addrinfo **themarr, bool needbind, struct addrinfo **bindarr, uint16_t bindport, bool lowport, int level);
 extern int xioopen_ipapp_listen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, const struct addrdesc *addrdesc);
 extern int _xioopen_ipapp_listen_prepare(struct opt *opts, struct opt **opts0, const char *portname, int *pf, int ipproto, const int ai_flags[2], union sockaddr_union *us, socklen_t *uslen, int socktype);
 
diff --git a/xio-openssl.c b/xio-openssl.c
index c333ca3..21a571a 100644
--- a/xio-openssl.c
+++ b/xio-openssl.c
@@ -238,13 +238,13 @@ static int xioopen_openssl_connect(
    int socktype = SOCK_STREAM;
    int ipproto = IPPROTO_TCP;
    bool dofork = false;
-   union sockaddr_union us_sa,  *us = &us_sa;
-   socklen_t uslen = sizeof(us_sa);
-   struct addrinfo **themarr, *themp;
+   int maxchildren = 0;
+   struct addrinfo **bindarr = NULL;
+   struct addrinfo **themarr = NULL;
+   uint16_t bindport = 0;
    bool needbind = false;
    bool lowport = false;
    int level = E_ERROR;
-   int i;
    SSL_CTX* ctx;
    bool opt_ver = true;	/* verify peer certificate */
    char *opt_cert = NULL;	/* file name of client certificate */
@@ -254,7 +254,7 @@ static int xioopen_openssl_connect(
    int result;
 
    if (!(xioflags & XIO_MAYCONVERT)) {
-      Error("address with data processing not allowed here");
+      Error1("%s: address with data processing not allowed here", argv[0]);
       return STAT_NORETRY;
    }
    sfd->flags |= XIO_DOESCONVERT;
@@ -272,14 +272,6 @@ static int xioopen_openssl_connect(
       return STAT_NORETRY;
    }
 
-   if (sfd->howtoend == END_UNSPEC)
-      sfd->howtoend = END_SHUTDOWN;
-   if (applyopts_single(sfd, opts, PH_INIT) < 0)
-      return -1;
-   applyopts(sfd, -1, opts, PH_INIT);
-
-   retropt_bool(opts, OPT_FORK, &dofork);
-
    retropt_string(opts, OPT_OPENSSL_CERTIFICATE, &opt_cert);
    retropt_string(opts, OPT_OPENSSL_COMMONNAME, (char **)&opt_commonname);
 #if defined(HAVE_SSL_set_tlsext_host_name) || defined(SSL_set_tlsext_host_name)
@@ -315,73 +307,83 @@ static int xioopen_openssl_connect(
       socktype = SOCK_DGRAM;
       ipproto = IPPROTO_UDP;
    }
-   retropt_int(opts, OPT_SO_TYPE,      &socktype);
-   retropt_int(opts, OPT_SO_PROTOTYPE, &ipproto);
 
-   result =
-      _xioopen_ipapp_prepare(opts, &opts0, hostname, portname, &pf, ipproto,
-			     sfd->para.socket.ip.ai_flags,
-			     &themarr, us, &uslen,
-			     &needbind, &lowport, socktype);
-   if (result != STAT_OK)  return STAT_NORETRY;
+   /* Apply and retrieve some options */
+   result = _xioopen_ipapp_init(sfd, xioflags, opts,
+				&dofork, &maxchildren,
+				&pf, &socktype, &ipproto);
+   if (result != STAT_OK)
+      return result;
 
-   if (xioparms.logopt == 'm') {
-      Info("starting connect loop, switching to syslog");
-      diag_set('y', xioparms.syslogfac);  xioparms.logopt = 'y';
-   } else {
-      Info("starting connect loop");
-   }
+   opts0 = opts; 	/* save remaining options for each loop */
+   opts = NULL;
 
-   do {	/* loop over failed connect and SSL handshake attempts */
+   Notice2("opening OpenSSL connection to %s:%s", hostname, portname);
 
-      /* Loop over themarr (which had been "ai_sorted") */
-      i = 0;
-      themp = themarr[i++];
-      while (themp != NULL) {
+   do {	/* loop over retries (failed connect and SSL handshake attempts) and/or forks */
+      int _errno;
 
 #if WITH_RETRY
-	 if (sfd->forever || sfd->retry || themarr[i] != NULL) {
-	    level = E_INFO;
-	 } else
+      if (sfd->forever || sfd->retry) {
+	 level = E_NOTICE;
+      } else
 #endif /* WITH_RETRY */
-	    level = E_ERROR;
+	 level = E_WARN;
 
-	 /* This cannot fork because we retrieved fork option above */
-       result =
-	 _xioopen_connect(sfd,
-			  needbind?us:NULL, uslen,
-			  themp->ai_addr, themp->ai_addrlen,
-			  opts, pf?pf:themp->ai_addr->sa_family, socktype, ipproto, lowport, level);
-       if (result == STAT_OK)
-	  break;
-       themp = themarr[i++];
-       if (themp == NULL) {
-	  result = STAT_RETRYLATER;
-      }
-      }
+      opts = copyopts(opts0, GROUP_ALL);
+
+      result =
+	 _xioopen_ipapp_prepare(&opts, opts0, hostname, portname,
+				pf, socktype, ipproto,
+				sfd->para.socket.ip.ai_flags,
+				&themarr, &bindarr, &bindport, &needbind, &lowport);
       switch (result) {
       case STAT_OK: break;
 #if WITH_RETRY
       case STAT_RETRYLATER:
       case STAT_RETRYNOW:
-	 if (sfd->forever || sfd->retry) {
-	    dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
+	 if (sfd->forever || sfd->retry--) {
+	    if (result == STAT_RETRYLATER)
+	       Nanosleep(&sfd->intervall, NULL);
+	    if (bindarr != NULL)  xiofreeaddrinfo(bindarr);
+	    xiofreeaddrinfo(themarr);
+	    freeopts(opts);
+	    continue;
+	 }
+#endif /* WITH_RETRY */
+      case STAT_NORETRY:
+	 if (bindarr != NULL)  xiofreeaddrinfo(bindarr);
+	 xiofreeaddrinfo(themarr);
+	 freeopts(opts);
+	 freeopts(opts0);
+	 return result;
+      }
+
+      Notice2("opening connection to server %s:%s", hostname, portname);
+      result =
+	 _xioopen_ipapp_connect(sfd, hostname, opts, themarr,
+				needbind, bindarr, bindport, lowport, level);
+      _errno = errno;
+      if (bindarr != NULL)  xiofreeaddrinfo(bindarr);
+      xiofreeaddrinfo(themarr);
+      switch (result) {
+      case STAT_OK: break;
+#if WITH_RETRY
+      case STAT_RETRYLATER:
+      case STAT_RETRYNOW:
+	 if (sfd->forever || sfd->retry--) {
 	    if (result == STAT_RETRYLATER) {
 	       Nanosleep(&sfd->intervall, NULL);
 	    }
-	    --sfd->retry;
+	    freeopts(opts);
 	    continue;
 	 }
-	 xiofreeaddrinfo(themarr);
-	 return STAT_NORETRY;
 #endif /* WITH_RETRY */
       default:
-	 xiofreeaddrinfo(themarr);
-	 return result;
-      }
-      /*! isn't this too early? */
-      if ((result = _xio_openlate(sfd, opts)) < 0) {
-	 xiofreeaddrinfo(themarr);
+	 Error4("%s:%s:%s: %s", argv[0], hostname, portname,
+		_errno?strerror(_errno):"(See above)");
+	 freeopts(opts0);
+	 freeopts(opts);
 	 return result;
       }
 
@@ -392,19 +394,19 @@ static int xioopen_openssl_connect(
 #if WITH_RETRY
       case STAT_RETRYLATER:
       case STAT_RETRYNOW:
-	 if (sfd->forever || sfd->retry) {
-	    Close(sfd->fd);
-	    dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
+	 if (sfd->forever || sfd->retry--) {
 	    if (result == STAT_RETRYLATER) {
 	       Nanosleep(&sfd->intervall, NULL);
 	    }
-	    --sfd->retry;
+	    freeopts(opts);
+	    Close(sfd->fd);
 	    continue;
 	 }
 #endif /* WITH_RETRY */
       default:
-	 xiofreeaddrinfo(themarr);
-	 return STAT_NORETRY;
+	 freeopts(opts);
+	 freeopts(opts0);
+	 return result;
       }
 
       if (dofork) {
@@ -419,15 +421,19 @@ static int xioopen_openssl_connect(
 	    level = E_WARN;
 	 }
 	 while ((pid = xio_fork(false, level, sfd->shutup)) < 0) {
-	    if (sfd->forever || --sfd->retry) {
-	       Nanosleep(&sfd->intervall, NULL); continue;
+	    if (sfd->forever || sfd->retry--) {
+	       Nanosleep(&sfd->intervall, NULL);
+	       freeopts(opts);
+	       continue;
 	    }
-	    xiofreeaddrinfo(themarr);
+	    freeopts(opts);
+	    freeopts(opts0);
 	    return STAT_RETRYLATER;
 	 }
 
 	 if (pid == 0) {	/* child process */
-	    sfd->forever = false;  sfd->retry = 0;
+	    sfd->forever = false;
+	    sfd->retry = 0;
 	    break;
 	 }
 
@@ -437,21 +443,29 @@ static int xioopen_openssl_connect(
 	 sfd->para.openssl.ssl = NULL;
 	 /* with and without retry */
 	 Nanosleep(&sfd->intervall, NULL);
-	 dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
+	 while (maxchildren > 0 && num_child >= maxchildren) {
+	    Info1("all %d allowed children are active, waiting", maxchildren);
+	    Nanosleep(&sfd->intervall, NULL);
+	 }
+	 freeopts(opts);
 	 continue;	/* with next socket() bind() connect() */
       }
 #endif /* WITH_RETRY */
       break;
+
    } while (true);	/* drop out on success */
-   xiofreeaddrinfo(themarr);
 
    openssl_conn_loginfo(sfd->para.openssl.ssl);
 
    free((void *)opt_commonname);
    free((void *)opt_snihost);
 
-   /* fill in the fd structure */
-   return STAT_OK;
+   Notice2("successfully connected to SSL server %s:%s", hostname, portname);
+
+   result = _xio_openlate(sfd, opts);
+   freeopts(opts);
+   freeopts(opts0);
+   return result;
 }
 
 
diff --git a/xio-proxy.c b/xio-proxy.c
index 0a8d4e6..ba82d5d 100644
--- a/xio-proxy.c
+++ b/xio-proxy.c
@@ -83,18 +83,18 @@ static int xioopen_proxy_connect(
 	xiofile_t *xxfd,
 	const struct addrdesc *addrdesc)
 {
-      /* we expect the form: host:host:port */
+   /* we expect the form: host:host:port */
    struct single *sfd = &xxfd->stream;
    struct opt *opts0 = NULL;
    struct proxyvars struct_proxyvars = { 0 }, *proxyvars = &struct_proxyvars;
    /* variables to be filled with address option values */
    bool dofork = false;
+   int maxchildren = 0;
    /* */
    int pf = PF_UNSPEC;
-   union sockaddr_union us_sa,   *us = &us_sa;
-   socklen_t uslen = sizeof(us_sa);
-   struct addrinfo **themarr, *themp;
-   int i;
+   struct addrinfo **bindarr = NULL;
+   struct addrinfo **themarr = NULL;
+   uint16_t bindport = 0;
    const char *proxyname; char *proxyport = NULL;
    const char *targetname, *targetport;
    int ipproto = IPPROTO_TCP;
@@ -112,90 +112,123 @@ static int xioopen_proxy_connect(
    targetname = argv[2];
    targetport = argv[3];
 
-   if (sfd->howtoend == END_UNSPEC)
-      sfd->howtoend = END_SHUTDOWN;
-   if (applyopts_single(sfd, opts, PH_INIT) < 0)
-      return -1;
-   applyopts(sfd, 1, opts, PH_INIT);
-
-   retropt_int(opts, OPT_SO_TYPE, &socktype);
-
-   retropt_bool(opts, OPT_FORK, &dofork);
-
    if (retropt_string(opts, OPT_PROXYPORT, &proxyport) < 0) {
       if ((proxyport = strdup(PROXYPORT)) == NULL) {
 	 errno = ENOMEM;  return -1;
       }
    }
 
-   result = _xioopen_proxy_prepare(proxyvars, opts, targetname, targetport,
-				   sfd->para.socket.ip.ai_flags);
-   if (result != STAT_OK)
-      return 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,
-			     sfd->para.socket.ip.ai_flags,
-			     &themarr, us, &uslen,
-			     &needbind, &lowport, socktype);
+   result =
+      _xioopen_ipapp_init(sfd, xioflags, opts,
+			  &dofork, &maxchildren,
+			  &pf, &socktype, &ipproto);
    if (result != STAT_OK)
        return result;
 
-      /* Loop over themlist */
-      i = 0;
-      themp = themarr[i++];
-      while (themp != NULL) {
-	 Notice4("opening connection to %s:%u via proxy %s:%s",
-		 proxyvars->targetaddr, proxyvars->targetport, proxyname, proxyport);
-#if WITH_RETRY
-	 if (sfd->forever || sfd->retry || themarr[i] != NULL) {
-	    level = E_INFO;
-	 } else
-#endif /* WITH_RETRY */
-	    level = E_ERROR;
+   result = _xioopen_proxy_init(proxyvars, opts, targetname, targetport);
+   if (result != STAT_OK)
+      return result;
 
-   result =
-      _xioopen_connect(sfd,
-		       needbind?us:NULL, uslen,
-		       themp->ai_addr, themp->ai_addrlen,
-		       opts, pf?pf:themp->ai_family, socktype, IPPROTO_TCP, lowport, level);
-       if (result == STAT_OK)
-	  break;
-       themp = themarr[i++];
-       if (themp == NULL) {
-	  result = STAT_RETRYLATER;
-      }
+   opts0 = opts; 	/* save remaining options for each loop */
+   opts = NULL;
+
+   Notice4("opening connection to %s:%s via proxy %s:%s",
+      targetname, targetport, proxyname, proxyport);
+
+   do {      /* loop over retries (failed connect and proxy-request attempts)
+	        and/or forks */
+      int _errno;
+
+#if WITH_RETRY
+      if (sfd->forever || sfd->retry) {
+	 level = E_NOTICE;
+      } else
+#endif /* WITH_RETRY */
+	 level = E_WARN;
+
+      opts = copyopts(opts0, GROUP_ALL);
+
+      result =
+	 _xioopen_ipapp_prepare(&opts, opts0, proxyname, proxyport,
+				pf, socktype, ipproto,
+				sfd->para.socket.ip.ai_flags,
+				&themarr, &bindarr, &bindport, &needbind, &lowport);
       switch (result) {
       case STAT_OK: break;
 #if WITH_RETRY
       case STAT_RETRYLATER:
       case STAT_RETRYNOW:
-	 if (sfd->forever || sfd->retry) {
-	    --sfd->retry;
+	 if (sfd->forever || sfd->retry--) {
 	    if (result == STAT_RETRYLATER)
 	       Nanosleep(&sfd->intervall, NULL);
+	    if (bindarr != NULL)  xiofreeaddrinfo(bindarr);
+	    xiofreeaddrinfo(themarr);
+	    freeopts(opts);
 	    continue;
 	 }
 #endif /* WITH_RETRY */
-      default:
+	 /* FALLTHROUGH */
+      case STAT_NORETRY:
+	 if (bindarr != NULL)  xiofreeaddrinfo(bindarr);
 	 xiofreeaddrinfo(themarr);
+	 freeopts(opts);
+	 freeopts(opts0);
 	 return result;
       }
-      }
-      xiofreeaddrinfo(themarr);
-      applyopts(sfd, -1, opts, PH_ALL);
 
-      if ((result = _xio_openlate(sfd, opts)) < 0)
+      result =
+	 _xioopen_proxy_prepare(proxyvars, opts, targetname, targetport,
+				sfd->para.socket.ip.ai_flags);
+      switch (result) {
+      case STAT_OK: break;
+#if WITH_RETRY
+      case STAT_RETRYLATER:
+      case STAT_RETRYNOW:
+	 if (sfd->forever || sfd->retry--) {
+	    if (result == STAT_RETRYLATER)
+	       Nanosleep(&sfd->intervall, NULL);
+	 if (bindarr != NULL)  xiofreeaddrinfo(bindarr);
+	 xiofreeaddrinfo(themarr);
+	    freeopts(opts);
+	    continue;
+	 }
+#endif /* WITH_RETRY */
+	 /* FALLTHROUGH */
+      default:
+	 if (bindarr != NULL)  xiofreeaddrinfo(bindarr);
+	 xiofreeaddrinfo(themarr);
+	 freeopts(opts);
+	 freeopts(opts0);
 	 return result;
+      }
+
+      Notice2("opening connection to proxy %s:%s", proxyname, proxyport);
+      result =
+	 _xioopen_ipapp_connect(sfd, proxyname, opts, themarr,
+				needbind, bindarr, bindport, lowport, level);
+      _errno = errno;
+      if (bindarr != NULL)  xiofreeaddrinfo(bindarr);
+      xiofreeaddrinfo(themarr);
+      switch (result) {
+      case STAT_OK: break;
+#if WITH_RETRY
+      case STAT_RETRYLATER:
+      case STAT_RETRYNOW:
+	 if (sfd->forever || sfd->retry--) {
+	    if (result == STAT_RETRYLATER)
+	       Nanosleep(&sfd->intervall, NULL);
+	    freeopts(opts);
+	    continue;
+	 }
+#endif /* WITH_RETRY */
+	 /* FALLTHROUGH */
+      default:
+	 Error4("%s:%s:...,proxyport=%s: %s", argv[0], proxyname, proxyport,
+		_errno?strerror(_errno):"(See above)");
+	 freeopts(opts0);
+	 freeopts(opts);
+	 return result;
+      }
 
       result = _xioopen_proxy_connect(sfd, proxyvars, level);
       switch (result) {
@@ -204,11 +237,16 @@ static int xioopen_proxy_connect(
       case STAT_RETRYLATER:
       case STAT_RETRYNOW:
 	 if (sfd->forever || sfd->retry--) {
-	    if (result == STAT_RETRYLATER)  Nanosleep(&sfd->intervall, NULL);
+	    if (result == STAT_RETRYLATER)
+	       Nanosleep(&sfd->intervall, NULL);
+	    freeopts(opts);
 	    continue;
 	 }
 #endif /* WITH_RETRY */
+	 /* FALLTHROUGH */
       default:
+	 freeopts(opts);
+	 freeopts(opts0);
 	 return result;
       }
 
@@ -225,21 +263,32 @@ static int xioopen_proxy_connect(
 	 }
 	 while ((pid = xio_fork(false, level, sfd->shutup)) < 0) {
 	    if (sfd->forever || --sfd->retry) {
-	       Nanosleep(&sfd->intervall, NULL); continue;
+	       if (sfd->retry > 0)
+		  --sfd->retry;
+	       Nanosleep(&sfd->intervall, NULL);
+	       freeopts(opts);
+	       continue;
 	    }
+	    freeopts(opts);
+	    freeopts(opts0);
 	    return STAT_RETRYLATER;
 	 }
 
 	 if (pid == 0) {	/* child process */
-	    sfd->forever = false;  sfd->retry = 0;
+	    sfd->forever = false;
+	    sfd->retry = 0;
 	    break;
 	 }
 
 	 /* parent process */
 	 Close(sfd->fd);
+	 /* With and without retry */
 	 Nanosleep(&sfd->intervall, NULL);
-	 dropopts(opts, PH_ALL);
-	 opts = copyopts(opts0, GROUP_ALL);
+	 while (maxchildren > 0 && num_child >= maxchildren) {
+	    Info1("all %d allowed children are active, waiting", maxchildren);
+	    Nanosleep(&sfd->intervall, NULL);
+	 }
+	 freeopts(opts);
 	 continue;
       } else
 #endif /* WITH_RETRY */
@@ -248,25 +297,25 @@ static int xioopen_proxy_connect(
       }
 
    } while (true);	/* end of complete open loop - drop out on success */
+   /* Only "active" process breaks (master without fork, or child) */
 
    Notice4("successfully connected to %s:%u via proxy %s:%s",
 	   proxyvars->targetaddr, proxyvars->targetport,
 	   proxyname, proxyport);
 
-   return 0;
+   result = _xio_openlate(sfd, opts);
+   freeopts(opts);
+   freeopts(opts0);
+   return result;
 }
 
 
-int _xioopen_proxy_prepare(
+int _xioopen_proxy_init(
 	struct proxyvars *proxyvars,
 	struct opt *opts,
 	const char *targetname,
-	const char *targetport,
-	const int ai_flags[2]) {
-   union sockaddr_union host;
-   socklen_t socklen = sizeof(host);
-   int rc;
-
+	const char *targetport)
+{
    retropt_bool(opts, OPT_IGNORECR, &proxyvars->ignorecr);
    retropt_bool(opts, OPT_PROXY_RESOLVE, &proxyvars->doresolve);
    retropt_string(opts, OPT_HTTP_VERSION,             &proxyvars->version);
@@ -316,6 +365,28 @@ int _xioopen_proxy_prepare(
       Close(authfd);
    }
 
+   if (!proxyvars->doresolve) {
+      proxyvars->targetaddr = strdup(targetname);
+      if (proxyvars->targetaddr == NULL) {
+	 Error1("strdup(\"%s\"): out of memory", targetname);
+	 return STAT_RETRYLATER;
+      }
+   }
+
+   return STAT_OK;
+}
+
+int _xioopen_proxy_prepare(
+	struct proxyvars *proxyvars,
+	struct opt *opts,
+	const char *targetname,
+	const char *targetport,
+	const int ai_flags[2])
+{
+   union sockaddr_union host;
+   socklen_t socklen = sizeof(host);
+   int rc;
+
    if (proxyvars->doresolve) {
       /* currently we only resolve to IPv4 addresses. This is in accordance to
 	 RFC 2396; however once it becomes clear how IPv6 addresses should be
@@ -325,6 +396,10 @@ int _xioopen_proxy_prepare(
 		      &host, &socklen, ai_flags);
       if (rc != STAT_OK) {
 	 proxyvars->targetaddr = strdup(targetname);
+	 if (proxyvars->targetaddr == NULL) {
+	    Error1("strdup(\"%s\"): out of memory", targetname);
+	    return STAT_RETRYLATER;
+	 }
       } else {
 #define LEN 16	/* www.xxx.yyy.zzz\0 */
 	 if ((proxyvars->targetaddr = Malloc(LEN)) == NULL) {
@@ -337,8 +412,6 @@ int _xioopen_proxy_prepare(
 		  ((unsigned char *)&host.ip4.sin_addr.s_addr)[3]);
 #undef LEN
       }
-   } else {
-      proxyvars->targetaddr = strdup(targetname);
    }
 
    proxyvars->targetport = htons(parseport(targetport, IPPROTO_TCP));
diff --git a/xio-proxy.h b/xio-proxy.h
index fee18b7..f7fb2b8 100644
--- a/xio-proxy.h
+++ b/xio-proxy.h
@@ -25,9 +25,8 @@ extern const struct optdesc opt_proxy_authorization_file;
 
 extern const struct addrdesc xioaddr_proxy_connect;
 
+extern int _xioopen_proxy_init(struct proxyvars *proxyvars, struct opt *opts, const char *targetname, const char *targetport);
 extern int _xioopen_proxy_prepare(struct proxyvars *proxyvars, struct opt *opts, const char *targetname, const char *targetport, const int ai_flags[2]);
-int _xioopen_proxy_connect(struct single *xfd,
-			   struct proxyvars *proxyvars,
-			   int level);
+extern int _xioopen_proxy_connect(struct single *xfd, struct proxyvars *proxyvars, int level);
 
 #endif /* !defined(__xio_proxy_h_included) */
diff --git a/xio-socket.c b/xio-socket.c
index c798598..96e9893 100644
--- a/xio-socket.c
+++ b/xio-socket.c
@@ -805,7 +805,7 @@ int xiogetpacketinfo(struct single *sfd, int fd)
       with IP sockets: lowport (selects randomly a free port from 640 to 1023)
       with UNIX and abstract sockets: uses tmpname() to find a free file system
       entry.
-   returns 0 on success.
+   Returns STAT_OK on success, or STAT_RETRYLATER (+errno) on failure.
 */
 int _xioopen_connect(struct single *sfd, union sockaddr_union *us, size_t uslen,
 		     struct sockaddr *them, size_t themlen,
@@ -835,7 +835,7 @@ int _xioopen_connect(struct single *sfd, union sockaddr_union *us, size_t uslen,
    applyopts_cloexec(sfd->fd, opts);
 
    if (xiobind(sfd, us, uslen, opts, pf, alt, level) < 0) {
-      return -1;
+      return STAT_RETRYLATER;
    }
 
    applyopts(sfd, -1, opts, PH_CONNECT);
@@ -875,6 +875,7 @@ int _xioopen_connect(struct single *sfd, union sockaddr_union *us, size_t uslen,
 	       Msg4(level, "xiopoll({%d,POLLOUT|POLLERR},,{"F_tv_sec"."F_tv_usec"): %s",
 		    sfd->fd, timeout.tv_sec, timeout.tv_usec, strerror(errno));
 	       Close(sfd->fd);
+	       errno = _errno;
 	       return STAT_RETRYLATER;
 	    }
 	    if (result == 0) {
@@ -882,6 +883,7 @@ int _xioopen_connect(struct single *sfd, union sockaddr_union *us, size_t uslen,
 		    sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
 		    strerror(ETIMEDOUT));
 	       Close(sfd->fd);
+	       errno = _errno;
 	       return STAT_RETRYLATER;
 	    }
 	    if (writefd.revents & POLLERR) {
@@ -897,15 +899,19 @@ int _xioopen_connect(struct single *sfd, union sockaddr_union *us, size_t uslen,
 		     sfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
 		     themlen, strerror(errno));
 #endif
+	       _errno = errno;
 	       Close(sfd->fd);
+	       errno = _errno;
 	       return STAT_RETRYLATER;
 	    }
 	    /* otherwise OK or network error */
 	    result = Getsockopt(sfd->fd, SOL_SOCKET, SO_ERROR, &err, &errlen);
 	    if (result != 0) {
+	       _errno = errno;
 	       Msg2(level, "getsockopt(%d, SOL_SOCKET, SO_ERROR, ...): %s",
 		    sfd->fd, strerror(err));
 	       Close(sfd->fd);
+	       errno = _errno;
 	       return STAT_RETRYLATER;
 	    }
 	    Debug2("getsockopt(%d, SOL_SOCKET, SO_ERROR, { %d }) -> 0",
@@ -915,6 +921,7 @@ int _xioopen_connect(struct single *sfd, union sockaddr_union *us, size_t uslen,
 		     sfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
 		     themlen, strerror(err));
 	       Close(sfd->fd);
+	       errno = err;
 	       return STAT_RETRYLATER;
 	    }
 	    Fcntl_l(sfd->fd, F_SETFL, fcntl_flags);
@@ -945,6 +952,7 @@ int _xioopen_connect(struct single *sfd, union sockaddr_union *us, size_t uslen,
 	      sfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
 	      themlen, strerror(errno));
 	 Close(sfd->fd);
+	 errno = _errno;
 	 return STAT_RETRYLATER;
       }
    } else {	/* result >= 0 */
@@ -1679,9 +1687,7 @@ int xiocheckrange(union sockaddr_union *sa, struct xiorange *range) {
 int xiocheckpeer(xiosingle_t *sfd,
 		 union sockaddr_union *pa, union sockaddr_union *la) {
    char infobuff[256];
-#if (WITH_TCP || WITH_UDP) && WITH_LIBWRAP
    int result;
-#endif
 
 #if WITH_IP4 || WITH_IP6
    if (sfd->para.socket.dorange) {
@@ -2091,9 +2097,8 @@ int xiosetsockaddrenv(const char *lr,
 
 /* retrieves options so-type and so-prototype from opts, calls socket, and
    ev. generates an appropriate error message.
-   returns 0 on success or -1 if an error occurred. */
-int
-xiosocket(struct opt *opts, int pf, int socktype, int proto, int msglevel) {
+   returns 0 on success or -1 (and errno) if an error occurred. */
+int xiosocket(struct opt *opts, int pf, int socktype, int proto, int msglevel) {
    int result;
 
    retropt_int(opts, OPT_SO_TYPE, &socktype);
@@ -2118,6 +2123,7 @@ xiosocket(struct opt *opts, int pf, int socktype, int proto, int msglevel) {
       with IP sockets: lowport (selects randomly a free port from 640 to 1023)
       with UNIX and abstract sockets: uses a method similar to tmpname() to
       find a free file system entry.
+   On success returns STAT_OK, otherwise errno is set.
 */
 int xiobind(
 	struct single *sfd,
@@ -2154,18 +2160,20 @@ int xiobind(
 	       usrname = strndup(us->un.sun_path, sizeof(us->un.sun_path));
 	    if (usrname	== NULL) {
 	       int _errno = errno;
-	       Error2("strndup(\"%s\", "F_Zu"): out of memory",
+	       Msg2(level, "strndup(\"%s\", "F_Zu"): out of memory",
 		      us->un.sun_path, sizeof(us->un.sun_path));
 	       errno = _errno;
-	       return -1;
+	       return STAT_RETRYLATER;
 	    }
 	 }
 
 	 do {	/* loop over tempnam bind() attempts */
 	    sockname = xio_tempnam(usrname, abstract);
 	    if (sockname == NULL) {
+	       int _errno = errno;
 	       Error2("tempnam(\"%s\"): %s", usrname, strerror(errno));
 	       free(usrname);
+	       errno = _errno;
 	       return -1;
 	    }
 	    strncpy(us->un.sun_path+(abstract?1:0), sockname, sizeof(us->un.sun_path));
@@ -2179,8 +2187,10 @@ int xiobind(
 					   infobuff, sizeof(infobuff)),
 		    uslen, strerror(errno));
 	       if (errno != EADDRINUSE) {
+		  int _errno = errno;
 		  free(usrname);
 		  Close(sfd->fd);
+		  errno = _errno;
 		  return STAT_RETRYLATER;
 	       }
 	    } else {
@@ -2193,10 +2203,12 @@ int xiobind(
 
       if (us != NULL) {
 	 if (Bind(sfd->fd, &us->soa, uslen) < 0) {
+	    int _errno = errno;
 	    Msg4(level, "bind(%d, {%s}, "F_Zd"): %s",
 		 sfd->fd, sockaddr_info(&us->soa, uslen, infobuff, sizeof(infobuff)),
 		 uslen, strerror(errno));
 	    Close(sfd->fd);
+	    errno = _errno;
 	    return STAT_RETRYLATER;
 	 }
 	 applyopts_named(us->un.sun_path, opts, PH_PREOPEN);
@@ -2268,12 +2280,14 @@ int xiobind(
       do {	/* loop over lowport bind() attempts */
 	 *port = htons(i);
 	 if (Bind(sfd->fd, &sinp->soa, sizeof(*sinp)) < 0) {
+	    int _errno = errno;
 	    Msg4(errno==EADDRINUSE?E_INFO:level,
 		 "bind(%d, {%s}, "F_Zd"): %s", sfd->fd,
 		 sockaddr_info(&sinp->soa, sizeof(*sinp), infobuff, sizeof(infobuff)),
 		 sizeof(*sinp), strerror(errno));
-	    if (errno != EADDRINUSE) {
+	    if (_errno != EADDRINUSE) {
 	       Close(sfd->fd);
+	       errno = _errno;
 	       return STAT_RETRYLATER;
 	    }
 	 } else {
@@ -2282,8 +2296,8 @@ int xiobind(
 	 --i;  if (i < XIO_IPPORT_LOWER)  i = IPPORT_RESERVED-1;
 	 if (i == N) {
 	    Msg(level, "no low port available");
-	    /*errno = EADDRINUSE; still assigned */
 	    Close(sfd->fd);
+	    errno = EADDRINUSE;
 	    return STAT_RETRYLATER;
 	 }
       } while (i != N);
@@ -2294,17 +2308,19 @@ int xiobind(
       if (us) {
 	 applyopts(sfd, sfd->fd, opts, PH_BIND);
 	 if (Bind(sfd->fd, &us->soa, uslen) < 0) {
+	    int _errno = errno;
 	    Msg4(level, "bind(%d, {%s}, "F_Zd"): %s",
 		 sfd->fd, sockaddr_info(&us->soa, uslen, infobuff, sizeof(infobuff)),
 		 uslen, strerror(errno));
 	    Close(sfd->fd);
+	    errno = _errno;
 	    return STAT_RETRYLATER;
 	 }
       }
    }
 
    applyopts(sfd, -1, opts, PH_PASTBIND);
-   return 0;
+   return STAT_OK;
 }
 
 /* Handles the SO_REUSEADDR socket option for TCP LISTEN addresses depending on
diff --git a/xio-socks.c b/xio-socks.c
index fd064dd..ea0805c 100644
--- a/xio-socks.c
+++ b/xio-socks.c
@@ -54,13 +54,12 @@ static int xioopen_socks4_connect(
    int pf = PF_UNSPEC;
    int ipproto = IPPROTO_TCP;
    bool dofork = false;
-   union sockaddr_union us_sa,  *us = &us_sa;
-   socklen_t uslen = sizeof(us_sa);
-   struct addrinfo **themarr, *themp;
-   int i;
+   int maxchildren = 0;
+   struct addrinfo **bindarr = NULL;
+   struct addrinfo **themarr = NULL;
+   uint16_t bindport = 0;
    bool needbind = false;
    bool lowport = false;
-   char infobuff[256];
    unsigned char buff[BUFF_LEN];
    struct socks4 *sockhead = (struct socks4 *)buff;
    size_t buflen = sizeof(buff);
@@ -76,41 +75,43 @@ static int xioopen_socks4_connect(
    targetname = argv[2];
    targetport = argv[3];
 
-   if (sfd->howtoend == END_UNSPEC)
-      sfd->howtoend = END_SHUTDOWN;
-   if (applyopts_single(sfd, opts, PH_INIT) < 0)  return -1;
-   applyopts(sfd, 1, opts, PH_INIT);
-
-   retropt_int(opts, OPT_SO_TYPE, &socktype);
-
-   retropt_bool(opts, OPT_FORK, &dofork);
-
-   result = _xioopen_socks4_prepare(targetport, opts, &socksport, sockhead, &buflen);
+   /* Apply and retrieve some options */
+   result = _xioopen_ipapp_init(sfd, xioflags, opts,
+			        &dofork, &maxchildren,
+			        &pf, &socktype, &ipproto);
    if (result != STAT_OK)
       return result;
 
+   result = _xioopen_socks4_init(targetport, opts, &socksport, sockhead,
+				 &buflen);
+   if (result != STAT_OK)
+      return result;
+
+   opts0 = opts; 	/* save remaining options for each loop */
+   opts = NULL;
+
    Notice5("opening connection to %s:%u via socks4 server %s:%s as user \"%s\"",
-	   targetname,
-	   ntohs(sockhead->port),
+	   targetname, ntohs(sockhead->port),
 	   sockdname, socksport, sockhead->userid);
 
-   i = 0;
-   do {	/* loop over retries (failed connect and socks-request attempts) */
+   do {	/* loop over retries (failed connect and socks-request attempts)
+	   and/or forks */
+      int _errno;
 
-      level = E_INFO;
+#if WITH_RETRY
+      if (sfd->forever || sfd->retry) {
+	 level = E_NOTICE;
+      } else
+#endif /* WITH_RETRY */
+	 level = E_WARN;
+
+      opts = copyopts(opts0, GROUP_ALL);
 
       result =
-	 _xioopen_ipapp_prepare(opts, &opts0, sockdname, socksport,
-				&pf, ipproto,
+	 _xioopen_ipapp_prepare(&opts, opts0, sockdname, socksport,
+				pf, socktype, ipproto,
 				sfd->para.socket.ip.ai_flags,
-				&themarr, us, &uslen,
-				&needbind, &lowport, socktype);
-
-      /* we try to resolve the target address _before_ connecting to the socks
-	 server: this avoids unnecessary socks connects and timeouts */
-      result =
-	 _xioopen_socks4_connect0(sfd, targetname, socks4a, sockhead,
-				  (ssize_t *)&buflen, level);
+				&themarr, &bindarr, &bindport, &needbind, &lowport);
       switch (result) {
       case STAT_OK: break;
 #if WITH_RETRY
@@ -119,60 +120,78 @@ static int xioopen_socks4_connect(
 	 if (sfd->forever || sfd->retry--) {
 	    if (result == STAT_RETRYLATER)
 	       Nanosleep(&sfd->intervall, NULL);
+	    if (bindarr != NULL)  xiofreeaddrinfo(bindarr);
+	    xiofreeaddrinfo(themarr);
+	    freeopts(opts);
 	    continue;
 	 }
 #endif /* WITH_RETRY */
-      default:
+	 /* FALLTHROUGH */
+      case STAT_NORETRY:
+	 if (bindarr != NULL)  xiofreeaddrinfo(bindarr);
+	 xiofreeaddrinfo(themarr);
+	 freeopts(opts);
+	 freeopts(opts0);
 	 return result;
       }
 
-      /* loop over themarr */
-      i = 0;
-      themp = themarr[i++];
-      while (themp != NULL) {
-	 Notice1("opening connection to %s",
-		 sockaddr_info(themp->ai_addr, themp->ai_addrlen,
-			       infobuff, sizeof(infobuff)));
-#if WITH_RETRY
-	 if (sfd->forever || sfd->retry || themarr[i] != NULL) {
-	    level = E_INFO;
-	 } else
-#endif /* WITH_RETRY */
-	    level = E_ERROR;
-
-      /* this cannot fork because we retrieved fork option above */
-	 result =
-	    _xioopen_connect(sfd,
-			     needbind?us:NULL, uslen,
-			     themp->ai_addr, themp->ai_addrlen,
-			     opts, pf?pf:themp->ai_family, socktype, IPPROTO_TCP, lowport, level);
-	 if (result == STAT_OK)
-	    break;
-	   themp = themarr[i++];
-	 if (themp == NULL)
-	    result = STAT_RETRYLATER;
-      }
+      /* we try to resolve the target address _before_ connecting to the socks
+	 server: this may avoid unnecessary connects and timeouts */
+      result =
+	 _xioopen_socks4_prepare(sfd, targetname, socks4a, sockhead,
+				 (ssize_t *)&buflen, level);
       switch (result) {
       case STAT_OK: break;
 #if WITH_RETRY
       case STAT_RETRYLATER:
       case STAT_RETRYNOW:
-	 if (sfd->forever || sfd->retry) {
-	    --sfd->retry;
+	 if (sfd->forever || sfd->retry--) {
 	    if (result == STAT_RETRYLATER)
 	       Nanosleep(&sfd->intervall, NULL);
+	 if (bindarr != NULL)  xiofreeaddrinfo(bindarr);
+	 xiofreeaddrinfo(themarr);
+	    freeopts(opts);
 	    continue;
 	 }
 #endif /* WITH_RETRY */
+	 /* FALLTHROUGH */
       default:
+	 if (bindarr != NULL)  xiofreeaddrinfo(bindarr);
 	 xiofreeaddrinfo(themarr);
+	 freeopts(opts);
+	 freeopts(opts0);
 	 return result;
       }
-      xiofreeaddrinfo(themarr);
-      applyopts(sfd, -1, opts, PH_ALL);
 
-      if ((result = _xio_openlate(sfd, opts)) < 0)
+      Notice2("opening connection to sockd %s:%s", sockdname, socksport);
+      result =
+	 _xioopen_ipapp_connect(sfd, sockdname, opts, themarr,
+				needbind, bindarr, bindport, lowport, level);
+      _errno = errno;
+      if (bindarr != NULL)  xiofreeaddrinfo(bindarr);
+      xiofreeaddrinfo(themarr);
+      switch (result) {
+      case STAT_OK: break;
+#if WITH_RETRY
+      case STAT_RETRYLATER:
+      case STAT_RETRYNOW:
+	 if (sfd->forever || sfd->retry--) {
+	    if (result == STAT_RETRYLATER) {
+	       Nanosleep(&sfd->intervall, NULL);
+	    }
+	    freeopts(opts);
+	    continue;
+	 }
+#endif /* WITH_RETRY */
+	 /* FALLTHROUGH */
+      default:
+	 errno = _errno;
+	 Error4("%s:%s:...,socksport=%s: %s", argv[0], sockdname, socksport,
+		_errno?strerror(_errno):"(See above)");
+	 freeopts(opts0);
+	 freeopts(opts);
 	 return result;
+      }
 
       result = _xioopen_socks4_connect(sfd, sockhead, buflen, level);
       switch (result) {
@@ -181,11 +200,16 @@ static int xioopen_socks4_connect(
       case STAT_RETRYLATER:
       case STAT_RETRYNOW:
 	 if (sfd->forever || sfd->retry--) {
-	    if (result == STAT_RETRYLATER)  Nanosleep(&sfd->intervall, NULL);
+	    if (result == STAT_RETRYLATER)
+	       Nanosleep(&sfd->intervall, NULL);
+	    freeopts(opts);
 	    continue;
 	 }
 #endif /* WITH_RETRY */
+	 /* FALLTHROUGH */
       default:
+	 freeopts(opts);
+	 freeopts(opts0);
 	 return result;
       }
 
@@ -202,10 +226,13 @@ static int xioopen_socks4_connect(
 				   so Notice is too weak */
 	 }
 	 while ((pid = xio_fork(false, level, sfd->shutup)) < 0) {
-	    if (sfd->forever || --sfd->retry) {
+	    if (sfd->forever || sfd->retry--) {
 	       Nanosleep(&sfd->intervall, NULL);
+	       freeopts(opts);
 	       continue;
 	    }
+	    freeopts(opts);
+	    freeopts(opts0);
 	    return STAT_RETRYLATER;
 	 }
 
@@ -217,8 +244,13 @@ static int xioopen_socks4_connect(
 
 	 /* parent process */
 	 Close(sfd->fd);
+	 /* with and without retry */
 	 Nanosleep(&sfd->intervall, NULL);
-	 dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
+	 while (maxchildren > 0 && num_child >= maxchildren) {
+	    Info1("all %d allowed children are active, waiting", maxchildren);
+	    Nanosleep(&sfd->intervall, NULL);
+	 }
+	 freeopts(opts);
 	 continue;
       } else
 #endif /* WITH_RETRY */
@@ -227,7 +259,15 @@ static int xioopen_socks4_connect(
       }
 
    } while (true);	/* end of complete open loop - drop out on success */
-   return 0;
+   /* only "active" process breaks (master without fork, or child) */
+
+   Notice4("successfully connected to %s:%s via sockd %s:%s",
+	   targetname, targetport, sockdname, socksport);
+
+   result = _xio_openlate(sfd, opts);
+   freeopts(opts);
+   freeopts(opts0);
+   return result;
 }
 
 #endif /* WITH_SOCKS4 || WITH_SOCKS4A */
@@ -260,7 +300,13 @@ int _xioopen_opt_socksport(
 #endif /* WITH_SOCKS4 || WITH_SOCKS4A || WITH_SOCKS5 */
 #if WITH_SOCKS4 || WITH_SOCKS4A
 
-int _xioopen_socks4_prepare(const char *targetport, struct opt *opts, char **socksport, struct socks4 *sockhead, size_t *headlen) {
+int _xioopen_socks4_init(
+	const char *targetport,
+	struct opt *opts,
+	char **socksport,
+	struct socks4 *sockhead,
+	size_t *headlen)
+{
    char *userid;
 
    /* generate socks header - points to final target */
@@ -286,14 +332,14 @@ int _xioopen_socks4_prepare(const char *targetport, struct opt *opts, char **soc
 
 
 /* called within retry/fork loop, before connect() */
-int
-   _xioopen_socks4_connect0(struct single *sfd,
-			    const char *hostname,	/* socks target host */
-			    int socks4a,
-			    struct socks4 *sockhead,
-			    ssize_t *headlen,		/* get available space,
-							   return used length*/
-			    int level) {
+int _xioopen_socks4_prepare(
+	struct single *sfd,
+	const char *hostname,	/* socks target host */
+	int socks4a,
+	struct socks4 *sockhead,
+	ssize_t *headlen,	/* get available space, return used length*/
+	int level)
+{
    int result;
 
    if (!socks4a) {
@@ -435,16 +481,7 @@ int _xioopen_socks4_connect(struct single *sfd,
    switch (replyhead->action) {
    case SOCKS_CD_GRANTED:
       /* Notice("socks: connect request succeeded"); */
-#if 0
-      if (Getsockname(sfd->fd, (struct sockaddr *)&us, &uslen) < 0) {
-	 Warn4("getsockname(%d, %p, {%d}): %s",
-		sfd->fd, &us, uslen, strerror(errno));
-      }
-      Notice1("successfully connected from %s via socks4",
-	      sockaddr_info((struct sockaddr *)&us, infobuff, sizeof(infobuff)));
-#else
       Notice("successfully connected via socks4");
-#endif
       break;
 
    case SOCKS_CD_FAILED:
diff --git a/xio-socks.h b/xio-socks.h
index f9a1131..f5abfb9 100644
--- a/xio-socks.h
+++ b/xio-socks.h
@@ -21,15 +21,8 @@ extern const struct addrdesc xioaddr_socks4_connect;
 extern const struct addrdesc xioaddr_socks4a_connect;
 
 extern int _xioopen_opt_socksport(struct opt *opts, char **socksport);
-extern int _xioopen_socks4_prepare(const char *targetport, struct opt *opts, char **socksport, struct socks4 *sockhead, size_t *headlen);
-extern int
-   _xioopen_socks4_connect0(struct single *xfd,
-			    const char *hostname,	/* socks target host */
-			    int socks4a,
-			    struct socks4 *sockhead,
-			    ssize_t *headlen,		/* get available space,
-							   return used length*/
-			    int level);
+extern int _xioopen_socks4_init(const char *targetport, struct opt *opts, char **socksport, struct socks4 *sockhead, size_t *headlen);
+extern int _xioopen_socks4_prepare(struct single *xfd, const char *hostname, int socks4a, struct socks4 *sockhead, ssize_t *headlen, int level);
 extern int _xioopen_socks4_connect(struct single *xfd,
 				   struct socks4 *sockhead,
 				   size_t headlen,
diff --git a/xio-socks5.c b/xio-socks5.c
index 31aa1ca..27ae1b1 100644
--- a/xio-socks5.c
+++ b/xio-socks5.c
@@ -512,6 +512,7 @@ static int xioopen_socks5(
 {
 	int socks_command = addrdesc->arg1;
 	bool dofork = false;
+	int maxchildren = 0;
 	int socktype = SOCK_STREAM;
 	int pf = PF_UNSPEC;
 	int ipproto = IPPROTO_TCP;
@@ -519,12 +520,11 @@ static int xioopen_socks5(
 	struct opt *opts0 = NULL;
 	struct single *sfd = &xxfd->stream;
 	const char *socks_server, *target_name, *target_port, *socks_port;
-	union sockaddr_union us_sa, *us = &us_sa;
-	socklen_t uslen = sizeof(us_sa);
-	struct addrinfo **themarr, *themp;
+	struct addrinfo **bindarr = NULL;
+	struct addrinfo **themarr = NULL;
+	uint16_t bindport = 0;
 	bool needbind = false;
 	bool lowport = false;
-	char infobuff[256];
 
 	if (argc < 4 || argc > 5) {
 		xio_syntax(argv[0], 4, argc-1, addrdesc->syntax);
@@ -542,75 +542,115 @@ static int xioopen_socks5(
 		target_port = argv[3];
 	}
 
-	if (sfd->howtoend == END_UNSPEC)
-		sfd->howtoend = END_SHUTDOWN;
-	if (applyopts_single(sfd, opts, PH_INIT) < 0)	return -1;
-	applyopts(sfd, -1, opts, PH_INIT);
-
-	retropt_int(opts, OPT_SO_TYPE, &socktype);
-	retropt_bool(opts, OPT_FORK, &dofork);
+	/* Apply and retrieve some options */
+	result = _xioopen_ipapp_init(sfd, xioflags, opts,
+			        &dofork, &maxchildren,
+			        &pf, &socktype, &ipproto);
+	if (result != STAT_OK)
+		return result;
 
 	if (_xioopen_opt_socksport(opts, (char **)&socks_port) < 0) {
 		return STAT_NORETRY;
 	}
 	/*! possible memory leak */
 
-	result = _xioopen_ipapp_prepare(opts, &opts0, socks_server, socks_port,
-					&pf, ipproto,
-					sfd->para.socket.ip.ai_flags,
-					&themarr, us, &uslen,
-					&needbind, &lowport, socktype);
+	opts0 = opts;
+	opts = NULL;
 
-	Notice2("connecting to socks5 server %s:%s",
-		socks_server, socks_port);
+	Notice4("opening connection to %s:%s vis socks5 server %s:%s",
+		target_name, target_port, socks_server, socks_port);
 
-	do {
+	do {	/* loop over retries (failed connect and socks-request attempts)
+		   and/or forks */
+		int _errno;
 #if WITH_RETRY
 		if (sfd->forever || sfd->retry) {
-			level = E_INFO;
-		} else {
-			level = E_ERROR;
-		}
+			level = E_NOTICE;
+		} else
 #endif
+			level = E_WARN;
 
-		/* loop over themarr */
-		themp = themarr[0];
-		while (themp != NULL) {
-			Notice1("opening connection to %s",
-				sockaddr_info(themp->ai_addr, themp->ai_addrlen,
-					      infobuff, sizeof(infobuff)));
-			result = _xioopen_connect(sfd, 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;
+		opts = copyopts(opts0, GROUP_ALL);
 
-			switch(result){
-				break;
+		result =
+			_xioopen_ipapp_prepare(&opts, opts0, socks_server, socks_port,
+					       pf, socktype, ipproto,
+					       sfd->para.socket.ip.ai_flags,
+					       &themarr, &bindarr, &bindport, &needbind,
+					       &lowport);
+		switch (result) {
+		case STAT_OK: break;
 #if WITH_RETRY
-			case STAT_RETRYLATER:
-			case STAT_RETRYNOW:
-				if (sfd->forever || sfd->retry-- ) {
-					if (result == STAT_RETRYLATER)	Nanosleep(&sfd->intervall, NULL);
-					continue;
-				}
-#endif
-			default:
+		case STAT_RETRYLATER:
+		case STAT_RETRYNOW:
+			if (sfd->forever || sfd->retry--) {
+				if (result == STAT_RETRYLATER)
+					Nanosleep(&sfd->intervall, NULL);
+				if (bindarr != NULL)  xiofreeaddrinfo(bindarr);
 				xiofreeaddrinfo(themarr);
-				return result;
+				freeopts(opts);
+				continue;
 			}
-		}
-		xiofreeaddrinfo(themarr);
-		applyopts(sfd, -1, opts, PH_ALL);
-
-		if ((result = _xio_openlate(sfd, opts)) < 0)
+#endif /* WITH_RETRY */
+			/* FALLTHROUGH */
+		case STAT_NORETRY:
+			if (bindarr != NULL)  xiofreeaddrinfo(bindarr);
+			xiofreeaddrinfo(themarr);
+			freeopts(opts);
+			freeopts(opts0);
 			return result;
+		}
 
-		if ((result = _xioopen_socks5_handshake(sfd, level)) != STAT_OK) {
+		Notice2("opening connection to socks5 server %s:%s",
+			socks_server, socks_port);
+		result =
+			_xioopen_ipapp_connect(sfd, socks_server, opts, themarr,
+					       needbind, bindarr, bindport, lowport, level);
+		_errno = errno;
+		if (bindarr != NULL)  xiofreeaddrinfo(bindarr);
+		xiofreeaddrinfo(themarr);
+		switch (result) {
+		case STAT_OK: break;
+#if WITH_RETRY
+		case STAT_RETRYLATER:
+		case STAT_RETRYNOW:
+			if (sfd->forever || sfd->retry--) {
+				if (result == STAT_RETRYLATER) {
+					Nanosleep(&sfd->intervall, NULL);
+				}
+				freeopts(opts);
+				continue;
+			}
+#endif /* WITH_RETRY */
+			/* FALLTHROUGH */
+		default:
+			Error4("%s:%s:%s:...: %s",
+			       argv[0], socks_server, socks_port,
+			       _errno?strerror(_errno):"(See above)");
+			freeopts(opts0);
+			freeopts(opts);
+			return result;
+		}
+
+		result = _xioopen_socks5_handshake(sfd, level);
+		switch (result) {
+		case STAT_OK: break;
+#if WITH_RETRY
+		case STAT_RETRYLATER:
+		case STAT_RETRYNOW:
+			if (sfd->forever || sfd->retry--) {
+				if (result == STAT_RETRYLATER) {
+					Nanosleep(&sfd->intervall, NULL);
+				}
+				freeopts(opts);
+				continue;
+			}
+#endif /* WITH_RETRY */
+			/* FALLTHROUGH */
+		default:
+			Error3("%s:%s:%s: Connection failed", argv[0], socks_server, socks_port);
+			freeopts(opts0);
+			freeopts(opts);
 			return result;
 		}
 
@@ -622,11 +662,16 @@ static int xioopen_socks5(
 		case STAT_RETRYLATER:
 		case STAT_RETRYNOW:
 			if ( sfd->forever || sfd->retry-- ) {
-				if (result == STAT_RETRYLATER)	Nanosleep(&sfd->intervall, NULL);
+				if (result == STAT_RETRYLATER)
+					Nanosleep(&sfd->intervall, NULL);
+				freeopts(opts);
 				continue;
 			}
-#endif
+#endif /* WITH_RETRY */
+			/* FALLTHROUGH */
 		default:
+			freeopts(opts);
+			freeopts(opts0);
 			return result;
 		}
 
@@ -642,12 +687,18 @@ static int xioopen_socks5(
 				level = E_WARN;
 			}
 			while ((pid = xio_fork(false, level, sfd->shutup)) < 0) {
-				if (sfd->forever || --sfd->retry) {
+				if (sfd->forever || sfd->retry) {
+					if (sfd->retry > 0)
+						--sfd->retry;
 					Nanosleep(&sfd->intervall, NULL);
+					freeopts(opts);
 					continue;
 				}
+				freeopts(opts);
+				freeopts(opts0);
 				return STAT_RETRYLATER;
 			}
+
 			if ( pid == 0 ) {
 				sfd->forever = false;
 				sfd->retry = 0;
@@ -656,17 +707,26 @@ static int xioopen_socks5(
 
 			Close(sfd->fd);
 			Nanosleep(&sfd->intervall, NULL);
-			dropopts(opts, PH_ALL);
-			opts = copyopts(opts0, GROUP_ALL);
+			while (maxchildren > 0 && num_child >= maxchildren) {
+				Info1("all %d allowed children are active, waiting", maxchildren);
+				Nanosleep(&sfd->intervall, NULL);
+			}
+			freeopts(opts);
 			continue;
 		} else
-#endif
+#endif /* WITH_RETRY */
 		{
 			break;
 		}
 	} while (true);
 
-	return 0;
+	Notice4("successfully connected to %s:%s via socks5 server %s:%s",
+		target_name, target_port, socks_server, socks_port);
+
+	result = _xio_openlate(sfd, opts);
+	freeopts(opts);
+	freeopts(opts0);
+	return STAT_OK;
 }
 
 #endif /* WITH_SOCKS5 */
diff --git a/xioopts.c b/xioopts.c
index d36179c..71d5cf4 100644
--- a/xioopts.c
+++ b/xioopts.c
@@ -2912,7 +2912,6 @@ int showleft(const struct opt *opts) {
    return 0;
 }
 
-
 /* determines the address group from mode_t */
 /* does not set GROUP_FD; cannot determine GROUP_TERMIOS ! */
 groups_t _groupbits(mode_t mode) {
@@ -4690,3 +4689,11 @@ int dumpopts(struct opt *opts)
 	}
 	return 0;
 }
+
+/* Better with type specific free function */
+void freeopts(
+	struct opt *opts)
+{
+   free(opts);
+   return;
+}
diff --git a/xioopts.h b/xioopts.h
index 5071cc4..d40e34d 100644
--- a/xioopts.h
+++ b/xioopts.h
@@ -1031,6 +1031,7 @@ extern groups_t _groupbits(mode_t mode);
 extern int dropopts(struct opt *opts, unsigned int phase);
 extern int dropopts2(struct opt *opts, unsigned int from, unsigned int to);
 extern int dumpopts(struct opt *opts);
+extern void freeopts(struct opt *opts);
 
 #if HAVE_BASIC_UID_T==1
 #  define retropt_uid(o,c,r) retropt_short(o,c,r)