TCP based clients try all results of name resolution until a connection succeeded

This commit is contained in:
Gerhard Rieger 2023-10-22 23:15:49 +02:00
parent 2a9623d61c
commit cb6e16b360
16 changed files with 456 additions and 262 deletions

View file

@ -70,6 +70,11 @@ Features:
addresses. reuseaddr= restores the old behaviour.
Tests: TCP4_REUSEADDR OPENSSL_6_REUSEADDR REUSEADDR_NULL
TCP based client addresses now try all results of name resolution until
a connection attempt succeeded.
Tests: TRY_ADDRS_4 TRY_ADDRS_4_6
Feature recommended by Anand Buddhdev.
Corrections:
When a sub process (EXEC, SYSTEM) terminated with exit code other than
0, its last sent data might have been lost depending on timing of read/

306
test.sh
View file

@ -154,7 +154,7 @@ fi
MCINTERFACE=$INTERFACE
[ -z "$MCINTERFACE" ] && MCINTERFACE=lo # !!! Linux only - and not always
#LOCALHOST=192.168.58.1
LOCALHOST=localhost
LOCALHOST=localhost # attention: on FreeBSD-10 localhost resolves primarily to IPv6
#LOCALHOST=127.0.0.1
LOCALHOST6="[::1]"
#PROTO=$(awk '{print($2);}' /etc/protocols |sort -n |tail -n 1)
@ -977,9 +977,21 @@ runssctp6 () {
return 0;
}
# check if UNIX domain sockets work
runsunix () {
# for now...
# check if UNIX domain sockets work - see above
#runsunix () {
# # for now...
# return 0;
#}
routesip6 () {
runsip6 >/dev/null || { echo route6; return 1; }
ping -c 1 -s 0 -6 2606:4700:4700::1111 >/dev/null 2>&1 || { echo route6; return 1; }
return 0;
}
routesip6 () {
runsip6 >/dev/null || { echo route6; return 1; }
ping -c 1 -s 0 -6 2606:4700:4700::1111 >/dev/null 2>&1 || { echo route6; return 1; }
return 0;
}
@ -3481,16 +3493,18 @@ case $RUNS in tcp4|tcp6) newport $RUNS;; esac
CMD2="$TRACE $SOCAT $opts \"$PEERADDR\" EXEC:'$OD_C'"
CMD="$TRACE $SOCAT -T1 $opts -t 1 - $TESTADDR"
printf "test $F_n $TEST... " $N
eval "$CMD2 2>\"${te}1\" &"
pid=$! # background process id
eval "$CMD2 2>\"${te}2\" &"
pid2=$! # background process id
$WAITCMD
echo "$da" |$CMD >$tf 2>"${te}2"
echo "$da" |$CMD >$tf 2>"${te}"
kill $pid2 2>/dev/null
wait
if ! echo "$da" |$OD_C |diff - "$tf" >"$tdiff"; then
$PRINTF "$FAILED: $TRACE $SOCAT:\n"
echo "$CMD2 &"
cat "${te}2"
echo "$CMD"
cat "${te}1"
cat "${te}"
cat "$tdiff"
numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N"
@ -3500,10 +3514,9 @@ else
echo " $CMD2 &"
echo " $CMD"
fi
if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi
if [ -n "$debug" ]; then cat "${te}2" "${te}"; fi
numOK=$((numOK+1))
fi
kill $pid 2>/dev/null
wait
fi ;; # NUMCOND, feats
esac
@ -3518,8 +3531,8 @@ TCP4CONNECT , tcp4 TCP4-CONNECT:\$LOCALHOST:\$PORT TCP4-LISTEN:\$PORT
TCP4LISTEN , tcp4 TCP4-LISTEN:\$PORT,$REUSEADDR TCP4-CONNECT:\$LOCALHOST:\$PORT,retry=3
TCP6CONNECT , tcp6 TCP6-CONNECT:\$LOCALHOST6:\$PORT TCP6-LISTEN:\$PORT,$REUSEADDR waittcp6port\040\$PORT
TCP6LISTEN , tcp6 TCP6-LISTEN:\$PORT,$REUSEADDR TCP6-CONNECT:\$LOCALHOST6:\$PORT,retry=3
OPENSSL4CLIENT OPENSSL tcp4 OPENSSL:\$LOCALHOST:\$PORT,verify=0 OPENSSL-LISTEN:\$PORT,$REUSEADDR,$SOCAT_EGD,cert=testsrv.crt,key=testsrv.key,verify=0 waittcp4port\040\$PORT
OPENSSL4SERVER OPENSSL tcp4 OPENSSL-LISTEN:\$PORT,$SOCAT_EGD,cert=testsrv.crt,key=testsrv.key,verify=0 OPENSSL:\$LOCALHOST:\$PORT,$REUSEADDR,verify=0,retry=3
OPENSSL4CLIENT OPENSSL tcp4 OPENSSL:\$LOCALHOST:\$PORT,pf=ip4,verify=0 OPENSSL-LISTEN:\$PORT,pf=ip4,$REUSEADDR,$SOCAT_EGD,cert=testsrv.crt,key=testsrv.key,verify=0 waittcp4port\040\$PORT
OPENSSL4SERVER OPENSSL tcp4 OPENSSL-LISTEN:\$PORT,pf=ip4,$SOCAT_EGD,cert=testsrv.crt,key=testsrv.key,verify=0 OPENSSL:\$LOCALHOST:\$PORT,pf=ip4,$REUSEADDR,verify=0,retry=3
OPENSSL6CLIENT OPENSSL tcp6 OPENSSL:\$LOCALHOST6:\$PORT,pf=ip6,verify=0 OPENSSL-LISTEN:\$PORT,pf=ip6,$REUSEADDR,$SOCAT_EGD,cert=testsrv.crt,key=testsrv.key,verify=0 waittcp6port\040\$PORT
OPENSSL6SERVER OPENSSL tcp6 OPENSSL-LISTEN:\$PORT,pf=ip6,$SOCAT_EGD,cert=testsrv.crt,key=testsrv.key,verify=0 OPENSSL:\$LOCALHOST6:\$PORT,pf=ip6,$REUSEADDR,verify=0,retry=3
"
@ -3546,8 +3559,8 @@ te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
da="test$N $(date) $RANDOM"
newport tcp4 # provide free port number in $PORT
CMD0="$TRACE $SOCAT $opts OPENSSL-LISTEN:$PORT,$REUSEADDR,$SOCAT_EGD,cert=testsrv.crt,key=testsrv.key,verify=0 pipe"
CMD1="$TRACE $SOCAT $opts - OPENSSL:$LOCALHOST:$PORT,verify=1,cafile=testsrv.crt,$SOCAT_EGD"
CMD0="$TRACE $SOCAT $opts OPENSSL-LISTEN:$PORT,pf=ip4,$REUSEADDR,$SOCAT_EGD,cert=testsrv.crt,key=testsrv.key,verify=0 pipe"
CMD1="$TRACE $SOCAT $opts - OPENSSL:$LOCALHOST:$PORT,pf=ip4,verify=1,cafile=testsrv.crt,$SOCAT_EGD"
printf "test $F_n $TEST... " $N
eval "$CMD0 2>\"${te}0\" &"
pid=$! # background process id
@ -3594,8 +3607,8 @@ te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
da="test$N $(date) $RANDOM"
newport tcp4 # provide free port number in $PORT
CMD2="$TRACE $SOCAT $opts OPENSSL-LISTEN:$PORT,$REUSEADDR,verify=1,cert=testsrv.crt,key=testsrv.key,cafile=testcli.crt,$SOCAT_EGD PIPE"
CMD="$TRACE $SOCAT $opts - OPENSSL:$LOCALHOST:$PORT,verify=0,cert=testcli.crt,key=testcli.key,$SOCAT_EGD"
CMD2="$TRACE $SOCAT $opts OPENSSL-LISTEN:$PORT,pf=ip4,$REUSEADDR,verify=1,cert=testsrv.crt,key=testsrv.key,cafile=testcli.crt,$SOCAT_EGD PIPE"
CMD="$TRACE $SOCAT $opts - OPENSSL:$LOCALHOST:$PORT,pf=ip4,verify=0,cert=testcli.crt,key=testcli.key,$SOCAT_EGD"
printf "test $F_n $TEST... " $N
eval "$CMD2 2>\"${te}1\" &"
pid=$! # background process id
@ -4684,6 +4697,7 @@ pid6_2=$!
echo "$da3" |$CMD6 >${tf}_3 2>"${te}6_3" &
pid6_3=$!
wait $pid6_1 $pid6_2 $pid6_3
kill $pid1 $pid2 $pid3 $pid4 $pid5 2>/dev/null
#
(echo "$da1"; sleep 2) |diff - "${tf}_1" >"${tdiff}1"
(echo "$da2"; sleep 2) |diff - "${tf}_2" >"${tdiff}2"
@ -5218,7 +5232,7 @@ elif ! testfeats openssl >/dev/null; then
else
gentestcert testsrv
newport tcp4 # provide free port number in $PORT
testserversec "$N" "$TEST" "$opts" "SSL-L:$PORT,pf=ip4,reuseaddr,fork,retry=1,$SOCAT_EGD,verify=0,cert=testsrv.crt,key=testsrv.key" "" "range=$SECONDADDR/32" "SSL:$LOCALHOST:$PORT,cafile=testsrv.crt,$SOCAT_EGD" 4 tcp $PORT -1
testserversec "$N" "$TEST" "$opts" "SSL-L:$PORT,pf=ip4,reuseaddr,fork,retry=1,$SOCAT_EGD,verify=0,cert=testsrv.crt,key=testsrv.key" "" "range=$SECONDADDR/32" "SSL:$LOCALHOST:$PORT,pf=ip4,cafile=testsrv.crt,$SOCAT_EGD" 4 tcp $PORT -1
fi ;; # NUMCOND, feats
esac
N=$((N+1))
@ -5235,7 +5249,7 @@ elif ! testfeats openssl >/dev/null; then
else
gentestcert testsrv
newport tcp4 # provide free port number in $PORT
testserversec "$N" "$TEST" "$opts" "SSL-L:$PORT,pf=ip4,reuseaddr,fork,retry=1,$SOCAT_EGD,verify=0,cert=testsrv.crt,key=testsrv.key" "" "sp=$PORT" "SSL:$LOCALHOST:$PORT,cafile=testsrv.crt,$SOCAT_EGD" 4 tcp $PORT -1
testserversec "$N" "$TEST" "$opts" "SSL-L:$PORT,pf=ip4,reuseaddr,fork,retry=1,$SOCAT_EGD,verify=0,cert=testsrv.crt,key=testsrv.key" "" "sp=$PORT" "SSL:$LOCALHOST:$PORT,pf=ip4,cafile=testsrv.crt,$SOCAT_EGD" 4 tcp $PORT -1
fi ;; # NUMCOND, feats
esac
N=$((N+1))
@ -5252,7 +5266,7 @@ elif ! testfeats openssl >/dev/null; then
else
gentestcert testsrv
newport tcp4 # provide free port number in $PORT
testserversec "$N" "$TEST" "$opts" "SSL-L:$PORT,pf=ip4,reuseaddr,fork,retry=1,$SOCAT_EGD,verify=0,cert=testsrv.crt,key=testsrv.key" "" "lowport" "SSL:$LOCALHOST:$PORT,cafile=testsrv.crt,$SOCAT_EGD" 4 tcp $PORT -1
testserversec "$N" "$TEST" "$opts" "SSL-L:$PORT,pf=ip4,reuseaddr,fork,retry=1,$SOCAT_EGD,verify=0,cert=testsrv.crt,key=testsrv.key" "" "lowport" "SSL:$LOCALHOST:$PORT,pf=ip4,cafile=testsrv.crt,$SOCAT_EGD" 4 tcp $PORT -1
fi ;; # NUMCOND, feats
esac
N=$((N+1))
@ -5273,7 +5287,7 @@ hd="$td/hosts.deny"
$ECHO "socat: $SECONDADDR" >"$ha"
$ECHO "ALL: ALL" >"$hd"
newport tcp4 # provide free port number in $PORT
testserversec "$N" "$TEST" "$opts" "SSL-L:$PORT,pf=ip4,reuseaddr,fork,retry=1,$SOCAT_EGD,verify=0,cert=testsrv.crt,key=testsrv.key" "" "tcpwrap-etc=$td" "SSL:$LOCALHOST:$PORT,cafile=testsrv.crt,$SOCAT_EGD" 4 tcp $PORT -1
testserversec "$N" "$TEST" "$opts" "SSL-L:$PORT,pf=ip4,reuseaddr,fork,retry=1,$SOCAT_EGD,verify=0,cert=testsrv.crt,key=testsrv.key" "" "tcpwrap-etc=$td" "SSL:$LOCALHOST:$PORT,pf=ip4,cafile=testsrv.crt,$SOCAT_EGD" 4 tcp $PORT -1
fi ;; # NUMCOND, feats
esac
N=$((N+1))
@ -5291,7 +5305,7 @@ else
gentestcert testsrv
gentestcert testcli
newport tcp4 # provide free port number in $PORT
testserversec "$N" "$TEST" "$opts -4" "SSL-L:$PORT,pf=ip4,reuseaddr,fork,retry=1,$SOCAT_EGD,verify,cert=testsrv.crt,key=testsrv.key" "cafile=testcli.crt" "cafile=testsrv.crt" "SSL:$LOCALHOST:$PORT,cafile=testsrv.crt,cert=testcli.pem,$SOCAT_EGD" 4 tcp $PORT '*'
testserversec "$N" "$TEST" "$opts -4" "SSL-L:$PORT,pf=ip4,reuseaddr,fork,retry=1,$SOCAT_EGD,verify,cert=testsrv.crt,key=testsrv.key" "cafile=testcli.crt" "cafile=testsrv.crt" "SSL:$LOCALHOST:$PORT,pf=ip4,cafile=testsrv.crt,cert=testcli.pem,$SOCAT_EGD" 4 tcp $PORT '*'
fi ;; # NUMCOND, feats
esac
N=$((N+1))
@ -5446,7 +5460,7 @@ else
gentestcert testsrv
gentestcert testcli
newport tcp4 # provide free port number in $PORT
testserversec "$N" "$TEST" "$opts -4" "SSL-L:$PORT,pf=ip4,reuseaddr,cert=testsrv.crt,key=testsrv.key,cafile=testcli.crt" "" "commonname=onlyyou" "SSL:$LOCALHOST:$PORT,$REUSEADDR,verify=0,cafile=testsrv.crt,cert=testcli.crt,key=testcli.key" 4 tcp "$PORT" '*'
testserversec "$N" "$TEST" "$opts -4" "SSL-L:$PORT,pf=ip4,reuseaddr,cert=testsrv.crt,key=testsrv.key,cafile=testcli.crt" "" "commonname=onlyyou" "SSL:$LOCALHOST:$PORT,pf=ip4,$REUSEADDR,verify=0,cafile=testsrv.crt,cert=testcli.crt,key=testcli.key" 4 tcp "$PORT" '*'
fi ;; # testfeats, NUMCOND
esac
N=$((N+1))
@ -7911,7 +7925,7 @@ ha="$td/hosts.allow"
$ECHO "test : ALL : allow" >"$ha"
newport tcp4 # provide free port number in $PORT
CMD1="$TRACE $SOCAT $opts TCP4-LISTEN:$PORT,$REUSEADDR,hosts-allow=$ha,tcpwrap=test pipe"
CMD2="$TRACE $SOCAT $opts - TCP:$LOCALHOST:$PORT"
CMD2="$TRACE $SOCAT $opts - TCP4:$LOCALHOST:$PORT"
printf "test $F_n $TEST... " $N
$CMD1 2>"${te}1" &
pid1=$!
@ -8824,8 +8838,8 @@ da="test$N $(date) $RANDOM"
SRVCERT=testsrv
gentestcert "$SRVCERT"
newport tcp4 # provide free port number in $PORT
CMD1="$TRACE $SOCAT $opts -u -T 1 -b $($ECHO "$da\c" |wc -c) OPENSSL-LISTEN:$PORT,$REUSEADDR,cert=$SRVCERT.pem,verify=0 -"
CMD2="$TRACE $SOCAT $opts -u - OPENSSL-CONNECT:$LOCALHOST:$PORT,verify=0"
CMD1="$TRACE $SOCAT $opts -u -T 1 -b $($ECHO "$da\c" |wc -c) OPENSSL-LISTEN:$PORT,pf=ip4,$REUSEADDR,cert=$SRVCERT.pem,verify=0 -"
CMD2="$TRACE $SOCAT $opts -u - OPENSSL-CONNECT:$LOCALHOST:$PORT,pf=ip4,verify=0"
printf "test $F_n $TEST... " $N
#
$CMD1 2>"${te}1" >"$tf" &
@ -10438,8 +10452,8 @@ tdiff="$td/test$N.diff"
da="test$N $(date) $RANDOM"
newport tcp4
CMD0="$TRACE $SOCAT $opts TCP4-L:$PORT,so-reuseaddr,fork PIPE"
CMD1="$TRACE $SOCAT $opts - TCP:$LOCALHOST:$PORT,setsockopt=6:$TCP_MAXSEG:512"
CMD2="$TRACE $SOCAT $opts - TCP:$LOCALHOST:$PORT,setsockopt=6:$TCP_MAXSEG:1"
CMD1="$TRACE $SOCAT $opts - TCP4:$LOCALHOST:$PORT,setsockopt=6:$TCP_MAXSEG:512"
CMD2="$TRACE $SOCAT $opts - TCP4:$LOCALHOST:$PORT,setsockopt=6:$TCP_MAXSEG:1"
printf "test $F_n $TEST... " $N
$CMD0 >/dev/null 2>"${te}0" &
pid0=$!
@ -10516,7 +10530,7 @@ tdiff="$td/test$N.diff"
da="test$N $(date) $RANDOM"
newport tcp4
CMD0="$TRACE $SOCAT $opts TCP4-L:$PORT,setsockopt-listen=$SOL_SOCKET:$SO_REUSEADDR:1 PIPE"
CMD1="$TRACE $SOCAT $opts - TCP:$LOCALHOST:$PORT"
CMD1="$TRACE $SOCAT $opts - TCP4:$LOCALHOST:$PORT"
CMD2="$CMD0"
CMD3="$CMD1"
printf "test $F_n $TEST... " $N
@ -11383,9 +11397,9 @@ if [ $RLIMIT_NOFILE -gt 1024 ]; then
RLIMIT_NOFILE="$(ulimit -n)"
fi
newport tcp4
CMD0="$TRACE $SOCAT $opt_d0 $opts TCP-LISTEN:$PORT,$REUSEADDR,range=$LOCALHOST:255.255.255.255 PIPE"
CMD1="$TRACE $SOCAT $opts -t 0 /dev/null TCP:$SECONDADDR:$PORT,bind=$SECONDADDR"
CMD2="$TRACE $SOCAT $opts - TCP:$LOCALHOST:$PORT,bind=$LOCALHOST"
CMD0="$TRACE $SOCAT $opt_d0 $opts TCP4-LISTEN:$PORT,$REUSEADDR,range=$LOCALHOST:255.255.255.255 PIPE"
CMD1="$TRACE $SOCAT $opts -t 0 /dev/null TCP4:$SECONDADDR:$PORT,bind=$SECONDADDR"
CMD2="$TRACE $SOCAT $opts - TCP4:$LOCALHOST:$PORT,bind=$LOCALHOST"
printf "test $F_n $TEST... " $N
$CMD0 >/dev/null 2>"${te}0" &
pid0=$!
@ -11399,9 +11413,9 @@ rc2=$?
kill $pid0 2>/dev/null; wait
echo -e "$da" |diff "${tf}2" - >$tdiff
if [ $rc2 -ne 0 ]; then
$PRINTF "$FAILED\n"
$PRINTF "$FAILED (rc2=$rc2)\n"
echo "$CMD2 &"
cat "${te}2"
cat "${te}2" >&2
numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N"
elif [ -f "$tdiff" -a ! -s "$tdiff" ]; then
@ -11416,11 +11430,11 @@ elif [ -f "$tdiff" -a ! -s "$tdiff" ]; then
else
$PRINTF "$FAILED\n"
echo "$CMD0 &"
cat "${te}0" >&2
echo "$CMD1"
cat "${te}1" >&2
echo "$CMD2"
cat "${te}0"
cat "${te}1"
cat "${te}2"
cat "${te}2" >&2
numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N"
fi
@ -11557,8 +11571,8 @@ te1="$td/test$N.1.stderr"
tdiff="$td/test$N.diff"
da="test$N $(date) $RANDOM"
newport tcp4
CMD0="$TRACE $SOCAT $opts OPENSSL-LISTEN:$PORT,$REUSEADDR,cert=testsrv.pem,verify=0 PIPE"
CMD1="$TRACE $SOCAT $opts - OPENSSL-CONNECT:$LOCALHOST:$PORT,bind=$LOCALHOST,verify=0"
CMD0="$TRACE $SOCAT $opts OPENSSL-LISTEN:$PORT,pf=ip4,$REUSEADDR,cert=testsrv.pem,verify=0 PIPE"
CMD1="$TRACE $SOCAT $opts - OPENSSL-CONNECT:$LOCALHOST:$PORT,pf=ip4,bind=$LOCALHOST,verify=0"
printf "test $F_n $TEST... " $N
$CMD0 >/dev/null 2>"$te0" &
pid0=$!
@ -11734,15 +11748,15 @@ esac
N=$((N+1))
#
done <<<"
openssl SERVER X509 ISSUER OPENSSL-LISTEN:$PORT,$REUSEADDR,bind=$LOCALHOST,cert=testsrv.pem,cafile=testcli.crt,verify=1 OPENSSL-CONNECT:$LOCALHOST:$PORT,cert=testcli.pem,cafile=testsrv.crt,verify=1 $TESTCERT_ISSUER
openssl SERVER X509 SUBJECT OPENSSL-LISTEN:$PORT,$REUSEADDR,bind=$LOCALHOST,cert=testsrv.pem,cafile=testcli.crt,verify=1 OPENSSL-CONNECT:$LOCALHOST:$PORT,cert=testcli.pem,cafile=testsrv.crt,verify=1 $TESTCERT_SUBJECT
openssl SERVER X509 COMMONNAME OPENSSL-LISTEN:$PORT,$REUSEADDR,bind=$LOCALHOST,cert=testsrv.pem,cafile=testcli.crt,verify=1 OPENSSL-CONNECT:$LOCALHOST:$PORT,cert=testcli.pem,cafile=testsrv.crt,verify=1 $TESTCERT_COMMONNAME
openssl SERVER X509 COUNTRYNAME OPENSSL-LISTEN:$PORT,$REUSEADDR,bind=$LOCALHOST,cert=testsrv.pem,cafile=testcli.crt,verify=1 OPENSSL-CONNECT:$LOCALHOST:$PORT,cert=testcli.pem,cafile=testsrv.crt,verify=1 $TESTCERT_COUNTRYNAME
openssl SERVER X509 LOCALITYNAME OPENSSL-LISTEN:$PORT,$REUSEADDR,bind=$LOCALHOST,cert=testsrv.pem,cafile=testcli.crt,verify=1 OPENSSL-CONNECT:$LOCALHOST:$PORT,cert=testcli.pem,cafile=testsrv.crt,verify=1 $TESTCERT_LOCALITYNAME
openssl SERVER X509 ORGANIZATIONALUNITNAME OPENSSL-LISTEN:$PORT,$REUSEADDR,bind=$LOCALHOST,cert=testsrv.pem,cafile=testcli.crt,verify=1 OPENSSL-CONNECT:$LOCALHOST:$PORT,cert=testcli.pem,cafile=testsrv.crt,verify=1 $TESTCERT_ORGANIZATIONALUNITNAME
openssl SERVER X509 ORGANIZATIONNAME OPENSSL-LISTEN:$PORT,$REUSEADDR,bind=$LOCALHOST,cert=testsrv.pem,cafile=testcli.crt,verify=1 OPENSSL-CONNECT:$LOCALHOST:$PORT,cert=testcli.pem,cafile=testsrv.crt,verify=1 $TESTCERT_ORGANIZATIONNAME
openssl CLIENT X509 SUBJECT OPENSSL-CONNECT:$LOCALHOST:$PORT,cert=testcli.pem,cafile=testsrv.crt,verify=1 OPENSSL-LISTEN:$PORT,$REUSEADDR,bind=$LOCALHOST,cert=testsrv.pem,cafile=testcli.crt,verify=1 $TESTCERT_SUBJECT
openssl CLIENT X509 ISSUER OPENSSL-CONNECT:$LOCALHOST:$PORT,cert=testcli.pem,cafile=testsrv.crt,verify=1 OPENSSL-LISTEN:$PORT,$REUSEADDR,bind=$LOCALHOST,cert=testsrv.pem,cafile=testcli.crt,verify=1 $TESTCERT_ISSUER
openssl SERVER X509 ISSUER OPENSSL-LISTEN:$PORT,pf=ip4,$REUSEADDR,bind=$LOCALHOST,cert=testsrv.pem,cafile=testcli.crt,verify=1 OPENSSL-CONNECT:$LOCALHOST:$PORT,pf=ip4,cert=testcli.pem,cafile=testsrv.crt,verify=1 $TESTCERT_ISSUER
openssl SERVER X509 SUBJECT OPENSSL-LISTEN:$PORT,pf=ip4,$REUSEADDR,bind=$LOCALHOST,cert=testsrv.pem,cafile=testcli.crt,verify=1 OPENSSL-CONNECT:$LOCALHOST:$PORT,pf=ip4,cert=testcli.pem,cafile=testsrv.crt,verify=1 $TESTCERT_SUBJECT
openssl SERVER X509 COMMONNAME OPENSSL-LISTEN:$PORT,pf=ip4,$REUSEADDR,bind=$LOCALHOST,cert=testsrv.pem,cafile=testcli.crt,verify=1 OPENSSL-CONNECT:$LOCALHOST:$PORT,pf=ip4,cert=testcli.pem,cafile=testsrv.crt,verify=1 $TESTCERT_COMMONNAME
openssl SERVER X509 COUNTRYNAME OPENSSL-LISTEN:$PORT,pf=ip4,$REUSEADDR,bind=$LOCALHOST,cert=testsrv.pem,cafile=testcli.crt,verify=1 OPENSSL-CONNECT:$LOCALHOST:$PORT,pf=ip4,cert=testcli.pem,cafile=testsrv.crt,verify=1 $TESTCERT_COUNTRYNAME
openssl SERVER X509 LOCALITYNAME OPENSSL-LISTEN:$PORT,pf=ip4,$REUSEADDR,bind=$LOCALHOST,cert=testsrv.pem,cafile=testcli.crt,verify=1 OPENSSL-CONNECT:$LOCALHOST:$PORT,pf=ip4,cert=testcli.pem,cafile=testsrv.crt,verify=1 $TESTCERT_LOCALITYNAME
openssl SERVER X509 ORGANIZATIONALUNITNAME OPENSSL-LISTEN:$PORT,pf=ip4,$REUSEADDR,bind=$LOCALHOST,cert=testsrv.pem,cafile=testcli.crt,verify=1 OPENSSL-CONNECT:$LOCALHOST:$PORT,pf=ip4,cert=testcli.pem,cafile=testsrv.crt,verify=1 $TESTCERT_ORGANIZATIONALUNITNAME
openssl SERVER X509 ORGANIZATIONNAME OPENSSL-LISTEN:$PORT,pf=ip4,$REUSEADDR,bind=$LOCALHOST,cert=testsrv.pem,cafile=testcli.crt,verify=1 OPENSSL-CONNECT:$LOCALHOST:$PORT,pf=ip4,cert=testcli.pem,cafile=testsrv.crt,verify=1 $TESTCERT_ORGANIZATIONNAME
openssl CLIENT X509 SUBJECT OPENSSL-CONNECT:$LOCALHOST:$PORT,pf=ip4,cert=testcli.pem,cafile=testsrv.crt,verify=1 OPENSSL-LISTEN:$PORT,pf=ip4,$REUSEADDR,bind=$LOCALHOST,cert=testsrv.pem,cafile=testcli.crt,verify=1 $TESTCERT_SUBJECT
openssl CLIENT X509 ISSUER OPENSSL-CONNECT:$LOCALHOST:$PORT,pf=ip4,cert=testcli.pem,cafile=testsrv.crt,verify=1 OPENSSL-LISTEN:$PORT,pf=ip4,$REUSEADDR,bind=$LOCALHOST,cert=testsrv.pem,cafile=testcli.crt,verify=1 $TESTCERT_ISSUER
"
@ -12120,8 +12134,8 @@ te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
da="test$N $(date) $RANDOM"
newport tcp4
CMD0="$SOCAT $opts OPENSSL-LISTEN:$PORT,$REUSEADDR,cert=testsrv.pem,verify=0 SYSTEM:cat"
CMD1="$SOCAT $opts - OPENSSL-CONNECT:$LOCALHOST:$PORT,verify=0"
CMD0="$SOCAT $opts OPENSSL-LISTEN:$PORT,pf=ip4,$REUSEADDR,cert=testsrv.pem,verify=0 SYSTEM:cat"
CMD1="$SOCAT $opts - OPENSSL-CONNECT:$LOCALHOST:$PORT,pf=ip4,verify=0"
printf "test $F_n $TEST... " $N
$CMD0 >/dev/null 2>"${te}0" &
pid0=$!
@ -12505,7 +12519,7 @@ te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
da="test$N $(date) $RANDOM"
CMD0="$TRACE $SOCAT $opts TCP4-L:$tp,$REUSEADDR PIPE"
CMD1="$TRACE $SOCAT $opts - TCP:localhost:$tp"
CMD1="$TRACE $SOCAT $opts - TCP4:localhost:$tp"
CMD2="$CMD0"
CMD3="$CMD1"
printf "test $F_n $TEST... " $N
@ -12580,7 +12594,7 @@ da2="test$N $(date) $RANDOM"
da3="test$N $(date) $RANDOM"
CMD0="$TRACE $SOCAT $opts TCP4-L:$tp,$REUSEADDR,so-reuseport PIPE"
CMD1="$CMD0"
CMD2="$TRACE $SOCAT $opts - TCP:localhost:$tp"
CMD2="$TRACE $SOCAT $opts - TCP4:localhost:$tp"
CMD3="$CMD2"
printf "test $F_n $TEST... " $N
$CMD0 >/dev/null 2>"${te}0" &
@ -12711,15 +12725,15 @@ da="test$N $(date) $RANDOM"
#TESTSRV=./testsrvec; gentesteccert $TESTSRV
TESTSRV=./testsrv; gentestcert $TESTSRV
newport tcp4
CMD0="$TRACE $SOCAT $opts OPENSSL-LISTEN:$PORT,$REUSEADDR,cert=$TESTSRV.crt,key=$TESTSRV.pem,verify=0 PIPE"
CMD1="$TRACE $SOCAT $opts - OPENSSL-CONNECT:$LOCALHOST:$PORT,cipher=ECDHE-ECDSA-AES256-GCM-SHA384,cafile=$TESTSRV.crt,verify=0"
CMD0="$TRACE $SOCAT $opts OPENSSL-LISTEN:$PORT,pf=ip4,$REUSEADDR,cert=$TESTSRV.crt,key=$TESTSRV.pem,verify=0 PIPE"
CMD1="$TRACE $SOCAT $opts - OPENSSL-CONNECT:$LOCALHOST:$PORT,pf=ip4,cipher=ECDHE-ECDSA-AES256-GCM-SHA384,cafile=$TESTSRV.crt,verify=0"
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
kill $pid0 2>/dev/null; wait
if [ $rc1 -ne 0 ]; then
$PRINTF "$FAILED\n"
echo "failure symptom: client error" >&2
@ -13237,11 +13251,11 @@ TEST="$NAME: OpenSSL DTLS client"
# Start a Socat DTLS client, send data to server and check if reply is received.
if ! eval $NUMCOND; then :;
elif ! a=$(testfeats ip4 udp openssl); then
$PRINTF "test $F_n $TEST... ${YELLOW}$a not available${NORMAL}\n" $N
$PRINTF "test $F_n $TEST... ${YELLOW}Feature $a not available${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
elif ! a=$(testaddrs openssl-dtls-client); then
$PRINTF "test $F_n $TEST... ${YELLOW}$a not available${NORMAL}\n" $N
$PRINTF "test $F_n $TEST... ${YELLOW}Address $a not available${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
elif ! runsip4 >/dev/null; then
@ -13371,8 +13385,8 @@ te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
da="test$N $(date) $RANDOM"
newport tcp4
CMD0="$TRACE $SOCAT $opts OPENSSL-LISTEN:$PORT,$REUSEADDR,$SOCAT_EGD,cert=testalt.crt,key=testalt.key,verify=0 pipe"
CMD1="$TRACE $SOCAT $opts - OPENSSL:$LOCALHOST:$PORT,verify=1,cafile=testalt.crt,$SOCAT_EGD"
CMD0="$TRACE $SOCAT $opts OPENSSL-LISTEN:$PORT,pf=ip4,$REUSEADDR,$SOCAT_EGD,cert=testalt.crt,key=testalt.key,verify=0 pipe"
CMD1="$TRACE $SOCAT $opts - OPENSSL:$LOCALHOST:$PORT,pf=ip4,verify=1,cafile=testalt.crt,$SOCAT_EGD"
printf "test $F_n $TEST... " $N
eval "$CMD0 2>\"${te}0\" &"
pid=$! # background process id
@ -13915,8 +13929,8 @@ te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
da="test$N $(date) $RANDOM"
newport tcp4
CMD0="$TRACE $SOCAT $opts -u OPENSSL-LISTEN:$PORT,$REUSEADDR,cert=testsrv.pem,verify=0 CREAT:$to"
CMD1="$TRACE $SOCAT $opts -u OPEN:$ti OPENSSL-CONNECT:$LOCALHOST:$PORT,cafile=testsrv.crt"
CMD0="$TRACE $SOCAT $opts -u OPENSSL-LISTEN:$PORT,pf=ip4,$REUSEADDR,cert=testsrv.pem,verify=0 CREAT:$to"
CMD1="$TRACE $SOCAT $opts -u OPEN:$ti OPENSSL-CONNECT:$LOCALHOST:$PORT,pf=ip4,cafile=testsrv.crt"
printf "test $F_n $TEST... " $N
i=0; while [ $i -lt 100000 ]; do printf "%9u %9u %9u %9u %9u %9u %9u %9u %9u %9u\n" $i $i $i $i $i $i $i $i $i $i; let i+=100; done >$ti
$CMD0 >/dev/null 2>"${te}0" &
@ -13986,8 +14000,8 @@ te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
da="test$N $(date) $RANDOM"
newport tcp4
CMD0="$TRACE $SOCAT $opts -U OPENSSL-LISTEN:$PORT,$REUSEADDR,cert=testsrv.pem,verify=0 OPEN:$ti"
CMD1="$TRACE $SOCAT $opts -u OPENSSL-CONNECT:$LOCALHOST:$PORT,cafile=testsrv.crt CREAT:$to"
CMD0="$TRACE $SOCAT $opts -U OPENSSL-LISTEN:$PORT,pf=ip4,$REUSEADDR,cert=testsrv.pem,verify=0 OPEN:$ti"
CMD1="$TRACE $SOCAT $opts -u OPENSSL-CONNECT:$LOCALHOST:$PORT,pf=ip4,cafile=testsrv.crt CREAT:$to"
printf "test $F_n $TEST... " $N
i=0; while [ $i -lt 100000 ]; do printf "%9u %9u %9u %9u %9u %9u %9u %9u %9u %9u\n" $i $i $i $i $i $i $i $i $i $i; let i+=100; done >$ti
$CMD0 >/dev/null 2>"${te}0" &
@ -14060,8 +14074,8 @@ te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
da="test$N $(date) $RANDOM"
newport udp4
CMD0="$TRACE $SOCAT $opts -u OPENSSL-DTLS-LISTEN:$PORT,cert=testsrv.pem,verify=0 CREAT:$to"
CMD1="$TRACE $SOCAT $opts -u OPEN:$ti OPENSSL-DTLS-CONNECT:$LOCALHOST:$PORT,cafile=testsrv.crt"
CMD0="$TRACE $SOCAT $opts -u OPENSSL-DTLS-LISTEN:$PORT,pf=ip4,cert=testsrv.pem,verify=0 CREAT:$to"
CMD1="$TRACE $SOCAT $opts -u OPEN:$ti OPENSSL-DTLS-CONNECT:$LOCALHOST:$PORT,pf=ip4,cafile=testsrv.crt"
printf "test $F_n $TEST... " $N
i=0; while [ $i -lt $((2*8192)) ]; do printf "%9u %9u %9u %9u %9u %9u %9u %9u %9u %9u\n" $i $i $i $i $i $i $i $i $i $i; let i+=100; done >$ti
$CMD0 >/dev/null 2>"${te}0" &
@ -14134,8 +14148,8 @@ te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
da="test$N $(date) $RANDOM"
newport udp4
CMD0="$TRACE $SOCAT $opts -U OPENSSL-DTLS-LISTEN:$PORT,cert=testsrv.pem,verify=0 OPEN:$ti"
CMD1="$TRACE $SOCAT $opts -u OPENSSL-DTLS-CONNECT:$LOCALHOST:$PORT,cafile=testsrv.crt CREAT:$to"
CMD0="$TRACE $SOCAT $opts -U OPENSSL-DTLS-LISTEN:$PORT,pf=ip4,cert=testsrv.pem,verify=0 OPEN:$ti"
CMD1="$TRACE $SOCAT $opts -u OPENSSL-DTLS-CONNECT:$LOCALHOST:$PORT,pf=ip4,cafile=testsrv.crt CREAT:$to"
printf "test $F_n $TEST... " $N
i=0; while [ $i -lt $((2*8192)) ]; do printf "%9u %9u %9u %9u %9u %9u %9u %9u %9u %9u\n" $i $i $i $i $i $i $i $i $i $i; let i+=100; done >$ti
$CMD0 >/dev/null 2>"${te}0" &
@ -14259,8 +14273,8 @@ te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
da="test$N $(date) $RANDOM"
newport tcp4
CMD0="$TRACE $SOCAT $opts -u OPENSSL-LISTEN:$PORT,reuseaddr,cert=./testsrv.pem,cafile=./testalt.crt -"
CMD1="$TRACE $SOCAT $opts -u - OPENSSL-CONNECT:localhost:$PORT,cafile=testsrv.crt,cert=testalt.pem,verify=0"
CMD0="$TRACE $SOCAT $opts -u OPENSSL-LISTEN:$PORT,pf=ip4,reuseaddr,cert=./testsrv.pem,cafile=./testalt.crt -"
CMD1="$TRACE $SOCAT $opts -u - OPENSSL-CONNECT:localhost:$PORT,pf=ip4,cafile=testsrv.crt,cert=testalt.pem,verify=0"
printf "test $F_n $TEST... " $N
$CMD0 >/dev/null >"${tf}0" 2>"${te}0" &
pid0=$!
@ -14553,8 +14567,8 @@ tf="$td/test$N.stdout"
te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
da="test$N $(date) $RANDOM"
CMD0="sleep 1 && $TRACE $SOCAT $opts TCP-L:$PORT,reuseaddr PIPE"
CMD1="$TRACE $SOCAT $opts - TCP:$LOCALHOST:$PORT,connect-timeout=2,retry=1,interval=2"
CMD0="sleep 1 && $TRACE $SOCAT $opts TCP4-L:$PORT,reuseaddr PIPE"
CMD1="$TRACE $SOCAT $opts - TCP4:$LOCALHOST:$PORT,connect-timeout=2,retry=1,interval=2"
printf "test $F_n $TEST... " $N
eval "$CMD0" >/dev/null 2>"${te}0" &
pid0=$!
@ -15260,6 +15274,7 @@ fi # NUMCOND
esac
N=$((N+1))
# Test if option -S turns on logging of signal 31
NAME=SIG31_LOG
case "$TESTS" in
@ -16016,6 +16031,7 @@ if [ $rc0b -eq 1 ] && grep -q -e "Address already in use" -e "Address in use" "$
if [ "$VERBOSE" ]; then echo "$CMD0b"; fi
if [ "$DEBUG" ]; then cat "${te}0b" >&2; fi
numOK=$((numOK+1))
#elif grep -q "accept: \(Connection\|Operation\) timed out" "${te}0b"; then
elif grep -q "accept: .* timed out" "${te}0b"; then
# FreeBSD, Solaris do not seem to need SO_REUSEADDR with TCP at all
$PRINTF "$CANT\n"
@ -16045,6 +16061,156 @@ esac
N=$((N+1))
# Test if Socats TCP4-client tries all addresses if necessary
NAME=TRY_ADDRS_4
case "$TESTS" in
*%$N%*|*%functions%*|*%tcp%*|*%tcp4%*|*%socket%*|*%foreign%*|*%$NAME%*)
TEST="$NAME: try all available TCP4 addresses"
# Connect to a TCP4 port of a hostname that resolves to two addresses where at
# least on the first one the port is closed.
# server-4.dest-unreach.net has been configured for this purpose, it
# resolves to its public address and to 127.0.0.1; unfortunately
# forwarding nameservers need not keep order of A entries, so we need a port
# that is closed on both addresses.
# The test succeeded when the log shows that Socat tried to connect two times.
if ! eval $NUMCOND; then :;
elif [ -z "$FOREIGN" ]; then
$PRINTF "test $F_n $TEST... ${YELLOW}use test.sh option -foreign${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
elif ! F=$(testfeats IP4 TCP GOPEN); then
$PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not available${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
elif ! A=$(testaddrs TCP4-CONNECT GOPEN); then
$PRINTF "test $F_n $TEST... ${YELLOW}Address $A not available in $SOCAT${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
elif ! runsip4 >/dev/null; then
$PRINTF "test $F_n $TEST... ${YELLOW}IPv4 not available${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
else
tf="$td/test$N.stdout"
te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
da="test$N $(date) $RANDOM"
ADDRS=$(nslookup server-4.dest-unreach.net. |sed -n '/^$/,$ p' |grep ^Address |awk '{print($2);}')
while true; do
newport tcp4
OPEN=
for addr in $ADDRS; do
if $SOCAT /dev/null TCP4:$addr:$PORT 2>/dev/null; then
# port is open :-(
OPEN=1
break
fi
done
if [ -z "$OPEN" ]; then
break;
fi
newport tcp4
done
CMD="$TRACE $SOCAT $opts -d -d /dev/null TCP4:server-4.dest-unreach.net:$PORT"
printf "test $F_n $TEST... " $N
$CMD >/dev/null 2>"${te}"
rc=$?
if [ $(grep " N opening connection to AF=2 " ${te} |wc -l) -eq 2 ]; then
$PRINTF "$OK\n"
if [ "$VERBOSE" ]; then echo "$CMD"; fi
if [ "$DEBUG" ]; then cat "${te}" >&2; fi
numOK=$((numOK+1))
else
$PRINTF "$FAILED\n"
echo "$CMD"
cat "${te}" >&2
numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N"
namesFAIL="$namesFAIL $NAME"
fi
fi # NUMCOND
;;
esac
N=$((N+1))
# Test if Socats TCP-client tries all addresses (IPv4+IPv6) if necessary
NAME=TRY_ADDRS_4_6
case "$TESTS" in
*%$N%*|*%functions%*|*%tcp%*|*%tcp4%*|*%tcp6%*|*%socket%*|*%foreign%*|*%$NAME%*)
TEST="$NAME: for TCP try all available IPv4 and IPv6 addresses"
# Connect to a TCP port that is not open on localhost-4-6.dest-unreach.net,
# neither IPv4 nor IPv6
# Check the log if Socat tried both addresses
if ! eval $NUMCOND; then :;
#elif [ -z "$FOREIGN" ]; then # only needs Internet DNS
# $PRINTF "test $F_n $TEST... ${YELLOW}use test.sh option -foreign${NORMAL}\n" $N
# numCANT=$((numCANT+1))
# listCANT="$listCANT $N"
elif ! F=$(testfeats ip4 ip6 tcp); then
$PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not available${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
elif ! A=$(testaddrs TCP-CONNECT GOPEN); then
$PRINTF "test $F_n $TEST... ${YELLOW}Address $A not available in $SOCAT${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
elif ! runsip4 >/dev/null; then
$PRINTF "test $F_n $TEST... ${YELLOW}IPv4 not available${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
elif ! runsip6 >/dev/null; then
$PRINTF "test $F_n $TEST... ${YELLOW}IPv6 not available or not routable${NORMAL}\n" $N
numCANT=$((numCANT+1))
listCANT="$listCANT $N"
else
tf="$td/test$N.stdout"
te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
da="test$N $(date) $RANDOM"
LOCALHOST_4_6=localhost-4-6.dest-unreach.net
ADDRS=$(nslookup . |sed -n '/^$/,$ p' |grep ^Address |awk '{print($2);}')
while true; do
OPEN=
for addr in $ADDRS; do
case $addr in
*.*) ;;
*:*) addr="[$addr]" ;
esac
if $SOCAT /dev/null TCP:$addr:$PORT 2>/dev/null; then
# port is open :-(
OPEN=1
break
fi
done
if [ -z "$OPEN" ]; then
break;
fi
newport tcp4
done
CMD="$TRACE $SOCAT $opts -d -d /dev/null TCP:localhost-4-6.dest-unreach.net:$PORT"
printf "test $F_n $TEST... " $N
$CMD >/dev/null 2>"${te}"
rc=$?
if [ $(grep " N opening connection to AF=\(2\|10\) " ${te} |wc -l) -eq 2 ]; then
$PRINTF "$OK\n"
if [ "$VERBOSE" ]; then echo "$CMD"; fi
if [ "$DEBUG" ]; then cat "${te}" >&2; fi
numOK=$((numOK+1))
else
$PRINTF "$FAILED\n"
echo "$CMD"
cat "${te}" >&2
numFAIL=$((numFAIL+1))
listFAIL="$listFAIL $N"
namesFAIL="$namesFAIL $NAME"
fi
fi # NUMCOND
;;
esac
N=$((N+1))
# end of common tests
##################################################################################

184
xio-ip.c
View file

@ -135,15 +135,13 @@ unsigned long res_opts() {
*/
int xiogetaddrinfo(const char *node, const char *service,
int family, int socktype, int protocol,
union sockaddr_union *sau, socklen_t *socklen,
struct addrinfo **res,
unsigned long res_opts0, unsigned long res_opts1) {
int port = -1; /* port number in network byte order */
char *numnode = NULL;
size_t nodelen;
unsigned long save_res_opts = 0;
#if HAVE_GETADDRINFO
struct addrinfo hints = {0};
struct addrinfo *res = NULL;
#else /* HAVE_PROTOTYPE_LIB_getipnodebyname || nothing */
struct hostent *host;
#endif
@ -161,13 +159,12 @@ int xiogetaddrinfo(const char *node, const char *service,
save_res_opts, _res.options);
}
#endif /* HAVE_RESOLV_H */
memset(sau, 0, *socklen);
sau->soa.sa_family = family;
if (service && service[0]=='\0') {
Error("empty port/service");
}
#if LATER
#ifdef WITH_VSOCK
if (family == AF_VSOCK) {
error_num = sockaddr_vm_parse(&sau->vm, node, service);
@ -177,18 +174,7 @@ int xiogetaddrinfo(const char *node, const char *service,
return STAT_OK;
}
#endif /* WITH_VSOCK */
/* if service is numeric we don't want to have a lookup (might take long
with NIS), so we handle this specially */
if (service && isdigit(service[0]&0xff)) {
char *extra;
port = htons(strtoul(service, &extra, 0));
if (*extra != '\0') {
Warn2("xiogetaddrinfo(, \"%s\", ...): extra trailing data \"%s\"",
service, extra);
}
service = NULL;
}
#endif /* LATER */
/* the resolver functions might handle numeric forms of node names by
reverse lookup, that's not what we want.
@ -220,7 +206,7 @@ int xiogetaddrinfo(const char *node, const char *service,
if (node != NULL || service != NULL) {
struct addrinfo *record;
hints.ai_flags |= AI_PASSIVE;
hints.ai_flags |= AI_PASSIVE; /* important for IPv4+IPv6 listen */
hints.ai_family = family;
hints.ai_socktype = socktype;
hints.ai_protocol = protocol;
@ -230,7 +216,7 @@ int xiogetaddrinfo(const char *node, const char *service,
hints.ai_next = NULL;
do {
error_num = Getaddrinfo(node, service, &hints, &res);
error_num = Getaddrinfo(node, service, &hints, res);
if (error_num == 0) break;
if (error_num == EAI_SOCKTYPE && socktype != 0) {
/* there are systems where kernel goes SCTP but not getaddrinfo() */
@ -244,21 +230,20 @@ int xiogetaddrinfo(const char *node, const char *service,
hints.ai_flags, hints.ai_family,
hints.ai_socktype, hints.ai_protocol,
gai_strerror(error_num));
if (res != NULL) freeaddrinfo(res);
if (res != NULL) freeaddrinfo(*res);
if (numnode) free(numnode);
return STAT_NORETRY;
}
hints.ai_protocol = 0;
continue;
}
if (error_num != 0) {
if ((error_num = Getaddrinfo(node, service, &hints, res)) != 0) {
Error7("getaddrinfo(\"%s\", \"%s\", {%d,%d,%d,%d}, {}): %s",
node?node:"NULL", service?service:"NULL",
hints.ai_flags, hints.ai_family,
hints.ai_socktype, hints.ai_protocol,
(error_num == EAI_SYSTEM)?
strerror(errno):gai_strerror(error_num));
if (res != NULL) freeaddrinfo(res);
if (numnode) free(numnode);
#if HAVE_RESOLV_H
@ -272,65 +257,15 @@ int xiogetaddrinfo(const char *node, const char *service,
} while (1);
service = NULL; /* do not resolve later again */
record = res;
if (family == PF_UNSPEC && xioparms.preferred_ip == '0') {
/* we just take the first result */
family = res[0].ai_addr->sa_family;
}
if (family == PF_UNSPEC) {
int trypf;
trypf = (xioparms.preferred_ip=='6'?PF_INET6:PF_INET);
/* we must look for a matching entry */
while (record != NULL) {
if (record->ai_family == trypf) {
family = trypf;
break; /* family and record set accordingly */
}
record = record->ai_next;
}
if (record == NULL) {
/* we did not find a "preferred" entry, take the first */
record = res;
family = res[0].ai_addr->sa_family;
}
}
switch (family) {
#if WITH_IP4
case PF_INET:
if (*socklen > record->ai_addrlen) {
*socklen = record->ai_addrlen;
}
memcpy(&sau->ip4, record->ai_addr, *socklen);
break;
#endif /* WITH_IP4 */
#if WITH_IP6
case PF_INET6:
#if _AIX
/* older AIX versions pass wrong length, so we correct it */
record->ai_addr->sa_len = sizeof(struct sockaddr_in6);
#endif
if (*socklen > record->ai_addrlen) {
*socklen = record->ai_addrlen;
}
memcpy(&sau->ip6, record->ai_addr, *socklen);
break;
#endif /* WITH_IP6 */
default:
Error1("address resolved to unknown protocol family %d",
record->ai_addr->sa_family);
break;
}
freeaddrinfo(res);
} else {
switch (family) {
#if WITH_IP4
case PF_INET: *socklen = sizeof(sau->ip4); break;
#endif /* WITH_IP4 */
#if WITH_IP6
case PF_INET6: *socklen = sizeof(sau->ip6); break;
#endif /* WITH_IP6 */
#if WITH_MSGLEVEL <= E_DEBUG
record = *res;
while (record) {
char buff[256/*!*/];
sockaddr_info(record->ai_addr, record->ai_addrlen, buff, sizeof(buff));
Debug5("getaddrinfo() -> flags=%d family=%d socktype=%d protocol=%d addr=%s", record->ai_flags, record->ai_family, record->ai_socktype, record->ai_protocol, buff);
record = record->ai_next;
}
#endif /* WITH_MSGLEVEL <= E_DEBUG */
}
#elif HAVE_PROTOTYPE_LIB_getipnodebyname /* !HAVE_GETADDRINFO */
@ -381,7 +316,7 @@ int xiogetaddrinfo(const char *node, const char *service,
freehostent(host);
}
#else /* !HAVE_PROTOTYPE_LIB_getipnodebyname */
#elsif 0 /* !HAVE_PROTOTYPE_LIB_getipnodebyname */
if (node != NULL) {
/* this is not a typical IP6 resolver function - but Linux
@ -411,7 +346,7 @@ int xiogetaddrinfo(const char *node, const char *service,
return STAT_RETRYLATER;
}
if (host->h_addrtype != family) {
Error2("xioaddrinfo(): \"%s\" does not resolve to %s",
Error2("xiogetaddrinfo(): \"%s\" does not resolve to %s",
node, family==PF_INET?"IP4":"IP6");
} else {
switch (family) {
@ -435,22 +370,6 @@ int xiogetaddrinfo(const char *node, const char *service,
#endif
#if WITH_TCP || WITH_UDP
if (service) {
port = parseport(service, protocol);
}
if (port >= 0) {
switch (family) {
#if WITH_IP4
case PF_INET: sau->ip4.sin_port = port; break;
#endif /* WITH_IP4 */
#if WITH_IP6
case PF_INET6: sau->ip6.sin6_port = port; break;
#endif /* WITH_IP6 */
}
}
#endif /* WITH_TCP || WITH_UDP */
if (numnode) free(numnode);
#if HAVE_RESOLV_H
@ -462,6 +381,50 @@ int xiogetaddrinfo(const char *node, const char *service,
return STAT_OK;
}
void xiofreeaddrinfo(struct addrinfo *res) {
#if HAVE_GETADDRINFO
freeaddrinfo(res);
#else
;
#endif
}
/* A simple resolver interface that just returns one address,
the first found by calling xiogetaddrinfo().
family may be AF_INET, AF_INET6, or AF_UNSPEC.
Returns -1 when an error occurred or when no result found.
*/
int xioresolve(const char *node, const char *service,
int family, int socktype, int protocol,
union sockaddr_union *addr, socklen_t *addrlen,
unsigned long res_opts0, unsigned long res_opts1) {
struct addrinfo *res = NULL;
int rc;
rc = xiogetaddrinfo(node, service, family, socktype, protocol,
&res, res_opts0, res_opts1);
if (rc != 0) {
xiofreeaddrinfo(res);
return -1;
}
if (res == NULL) {
Warn1("xioresolve(node=\"%s\", ...): No result", node);
xiofreeaddrinfo(res);
return -1;
}
if (res->ai_addrlen > *addrlen) {
Warn3("xioresolve(node=\"%s\", addrlen="F_socklen", ...): "F_socklen" bytes required", node, *addrlen, res->ai_addrlen);
xiofreeaddrinfo(res);
return -1;
}
if (res->ai_next != NULL) {
Info4("xioresolve(node=\"%s\", service=%s%s%s, ...): More than one address found", node?node:"NULL", service?"\"":"", service?service:"NULL", service?"\"":"");
}
memcpy(addr, res->ai_addr, res->ai_addrlen);
*addrlen = res->ai_addrlen;
xiofreeaddrinfo(res);
return 0;
}
#if defined(HAVE_STRUCT_CMSGHDR) && defined(CMSG_DATA)
/* Converts the ancillary message in *cmsg into a form useable for further
@ -773,10 +736,10 @@ mc:addr
/* first parameter is alway multicast address */
/*! result */
xiogetaddrinfo(opt->value.u_string/*multiaddr*/, NULL,
xioresolve(opt->value.u_string/*multiaddr*/, NULL,
xfd->para.socket.la.soa.sa_family,
SOCK_DGRAM, IPPROTO_IP,
&sockaddr1, &socklen1, 0, 0);
&sockaddr1, &socklen1, 0, 0);
ip4_mreqn.mreq.imr_multiaddr = sockaddr1.ip4.sin_addr;
if (0) {
; /* for canonical reasons */
@ -784,7 +747,7 @@ mc:addr
} else if (opt->value3.u_string/*ifindex*/ != NULL) {
/* three parameters */
/* second parameter is interface address */
xiogetaddrinfo(opt->value2.u_string/*param2*/, NULL,
xioresolve(opt->value2.u_string/*param2*/, NULL,
xfd->para.socket.la.soa.sa_family,
SOCK_DGRAM, IPPROTO_IP,
&sockaddr2, &socklen2, 0, 0);
@ -812,7 +775,7 @@ mc:addr
#endif /* HAVE_STRUCT_IP_MREQN */
} else {
/*! result */
xiogetaddrinfo(opt->value2.u_string/*param2*/, NULL,
xioresolve(opt->value2.u_string/*param2*/, NULL,
xfd->para.socket.la.soa.sa_family,
SOCK_DGRAM, IPPROTO_IP,
&sockaddr2, &socklen2, 0, 0);
@ -960,25 +923,34 @@ int xioapply_ip_add_source_membership(struct single *xfd, struct opt *opt) {
socklen_t socklen2 = sizeof(sockaddr2.ip4);
union sockaddr_union sockaddr3;
socklen_t socklen3 = sizeof(sockaddr3.ip4);
int rc;
/* first parameter is always multicast address */
/*! result */
xiogetaddrinfo(opt->value.u_string/*mcaddr*/, NULL,
rc = xioresolve(opt->value.u_string/*mcaddr*/, NULL,
xfd->para.socket.la.soa.sa_family,
SOCK_DGRAM, IPPROTO_IP,
&sockaddr1, &socklen1, 0, 0);
if (rc < 0) {
return -1;
}
ip4_mreq_src.imr_multiaddr = sockaddr1.ip4.sin_addr;
/* second parameter is interface address */
xiogetaddrinfo(opt->value2.u_string/*ifaddr*/, NULL,
rc = xioresolve(opt->value.u_string/*ifaddr*/, NULL,
xfd->para.socket.la.soa.sa_family,
SOCK_DGRAM, IPPROTO_IP,
&sockaddr2, &socklen2, 0, 0);
if (rc < 0) {
return -1;
}
ip4_mreq_src.imr_interface = sockaddr2.ip4.sin_addr;
/* third parameter is source address */
xiogetaddrinfo(opt->value3.u_string/*srcaddr*/, NULL,
rc = xioresolve(opt->value.u_string/*srcaddr*/, NULL,
xfd->para.socket.la.soa.sa_family,
SOCK_DGRAM, IPPROTO_IP,
&sockaddr3, &socklen3, 0, 0);
if (rc < 0) {
return -1;
}
ip4_mreq_src.imr_sourceaddr = sockaddr3.ip4.sin_addr;
if (Setsockopt(xfd->fd, opt->desc->major, opt->desc->minor,
&ip4_mreq_src, sizeof(ip4_mreq_src)) < 0) {

View file

@ -39,10 +39,9 @@ extern const struct optdesc opt_res_defnames;
extern const struct optdesc opt_res_stayopen;
extern const struct optdesc opt_res_dnsrch;
extern int xiogetaddrinfo(const char *node, const char *service,
int family, int socktype, int protocol,
union sockaddr_union *sa, socklen_t *socklen,
unsigned long res_opts0, unsigned long res_opts1);
extern int xiogetaddrinfo(const char *node, const char *service, int family, int socktype, int protocol, struct addrinfo **res, unsigned long res_opts0, unsigned long res_opts1);
extern void xiofreeaddrinfo(struct addrinfo *res);
extern int xioresolve(const char *node, const char *service, int family, int socktype, int protocol, union sockaddr_union *addr, socklen_t *addrlen, unsigned long res_opts0, unsigned long res_opts1);
extern int xiolog_ancillary_ip(struct single *sfd, struct cmsghdr *cmsg, int *num, char *typbuff, int typlen, char *nambuff, int namlen, char *envbuff, int envlen, char *valbuff, int vallen);
extern int xiotype_ip_add_membership(char *token, const struct optname *ent, struct opt *opt);
extern int xioapply_ip_add_membership(xiosingle_t *xfd, struct opt *opt);

View file

@ -45,7 +45,7 @@ int xioparsenetwork_ip4(const char *rangename, struct xiorange *range) {
netmask_in->s_addr = htonl((0xffffffff << (32-bits)));
}
} else if (delimpos = strchr(rangename1, ':')) {
if ((rc = xiogetaddrinfo(delimpos+1, NULL, PF_UNSPEC, 0, 0,
if ((rc = xioresolve(delimpos+1, NULL, PF_INET, 0, 0,
&sau, &socklen, 0, 0))
!= STAT_OK) {
return rc;
@ -58,7 +58,7 @@ int xioparsenetwork_ip4(const char *rangename, struct xiorange *range) {
}
{
*delimpos = 0;
if ((rc = xiogetaddrinfo(rangename1, NULL, PF_UNSPEC, 0, 0,
if ((rc = xioresolve(rangename1, NULL, PF_INET, 0, 0,
&sau, &socklen, 0, 0))
!= STAT_OK) {
return rc;

View file

@ -11,7 +11,7 @@
#include "xioopen.h"
#include "xio-ascii.h"
#include "xio-socket.h"
#include "xio-ip.h" /* xiogetaddrinfo() */
#include "xio-ip.h" /* xioresolve() */
#include "xio-ip6.h"
#include "nestlex.h"
@ -85,7 +85,6 @@ const struct optdesc opt_ipv6_recvpathmtu = { "ipv6-recvpathmtu", "recvpathmtu",
int xioip6_pton(const char *src, struct in6_addr *dst) {
union sockaddr_union sockaddr;
socklen_t sockaddrlen = sizeof(sockaddr);
int res;
if (src[0] == '[') {
char plainaddr[INET6_ADDRSTRLEN];
@ -97,9 +96,8 @@ int xioip6_pton(const char *src, struct in6_addr *dst) {
*clos = '\0';
return xioip6_pton(plainaddr, dst);
}
if ((res =
xiogetaddrinfo(src, NULL, PF_INET6, 0, 0, &sockaddr, &sockaddrlen,
0, 0))
if (xioresolve(src, NULL, PF_INET6, 0, 0, &sockaddr, &sockaddrlen,
0, 0)
!= STAT_OK) {
return STAT_NORETRY;
}
@ -136,7 +134,7 @@ int xioparsenetwork_ip6(const char *rangename, struct xiorange *range) {
return STAT_NORETRY;
}
baseaddr[delimind-2] = '\0';
if (xiogetaddrinfo(baseaddr, NULL, PF_INET6, 0, 0, &sockaddr, &sockaddrlen,
if (xioresolve(baseaddr, NULL, PF_INET6, 0, 0, &sockaddr, &sockaddrlen,
0, 0)
!= STAT_OK) {
return STAT_NORETRY;
@ -481,7 +479,7 @@ int xioapply_ipv6_join_group(
/* Always two parameters */
/* First parameter is multicast address */
if ((res =
xiogetaddrinfo(opt->value.u_string/*multiaddr*/, NULL,
xioresolve(opt->value.u_string/*multiaddr*/, NULL,
xfd->para.socket.la.soa.sa_family,
SOCK_DGRAM, IPPROTO_IP,
&sockaddr1, &socklen1, 0, 0)) != STAT_OK) {
@ -620,7 +618,7 @@ int xioapply_ip6_join_source_group(struct single *xfd, struct opt *opt) {
/* First parameter is always multicast address */
if ((res =
xiogetaddrinfo(opt->value.u_string/*mcaddr*/, NULL,
xioresolve(opt->value.u_string/*mcaddr*/, NULL,
xfd->para.socket.la.soa.sa_family,
SOCK_DGRAM, IPPROTO_IP,
&sockaddr1, &socklen1, 0, 0)) != STAT_OK) {
@ -637,7 +635,7 @@ int xioapply_ip6_join_source_group(struct single *xfd, struct opt *opt) {
}
/* Third parameter is source address */
if ((res =
xiogetaddrinfo(opt->value3.u_string/*srcaddr*/, NULL,
xioresolve(opt->value3.u_string/*srcaddr*/, NULL,
xfd->para.socket.la.soa.sa_family,
SOCK_DGRAM, IPPROTO_IP,
&sockaddr2, &socklen2, 0, 0)) != STAT_OK) {

View file

@ -30,9 +30,9 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
const char *hostname = argv[1], *portname = argv[2];
bool dofork = false;
union sockaddr_union us_sa, *us = &us_sa;
union sockaddr_union them_sa, *them = &them_sa;
socklen_t uslen = sizeof(us_sa);
socklen_t themlen = sizeof(them_sa);
struct addrinfo *themlist, *themp;
char infobuff[256];
bool needbind = false;
bool lowport = false;
int level;
@ -52,7 +52,7 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
if (_xioopen_ipapp_prepare(opts, &opts0, hostname, portname, &pf, ipproto,
xfd->para.socket.ip.res_opts[1],
xfd->para.socket.ip.res_opts[0],
them, &themlen, us, &uslen, &needbind, &lowport,
&themlist, us, &uslen, &needbind, &lowport,
socktype) != STAT_OK) {
return STAT_NORETRY;
}
@ -68,20 +68,36 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
Info("starting connect loop");
}
do { /* loop over retries and forks */
do { /* loop over retries, and forks */
themp = themlist;
/* Loop over themlist */
result = STAT_RETRYLATER;
while (themp != NULL) {
Notice1("opening connection to %s",
sockaddr_info(themp->ai_addr, themp->ai_addrlen,
infobuff, sizeof(infobuff)));
#if WITH_RETRY
if (xfd->forever || xfd->retry) {
level = E_INFO;
} else
if (xfd->forever || xfd->retry || themp->ai_next != NULL) {
level = E_INFO;
} else
#endif /* WITH_RETRY */
level = E_ERROR;
level = E_ERROR;
result =
result =
_xioopen_connect(xfd,
needbind?us:NULL, uslen,
(struct sockaddr *)them, themlen,
opts, pf, socktype, ipproto, lowport, level);
themp->ai_addr, themp->ai_addrlen,
opts, pf?pf:themp->ai_family, socktype, ipproto,
lowport, level);
if (result == STAT_OK)
break;
themp = themp->ai_next;
if (themp == NULL) {
result = STAT_RETRYLATER;
}
}
switch (result) {
case STAT_OK: break;
#if WITH_RETRY
@ -95,10 +111,10 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
dropopts(opts, PH_ALL); free(opts); opts = copyopts(opts0, GROUP_ALL);
continue;
}
return STAT_NORETRY;
#endif /* WITH_RETRY */
default:
free(opts0);free(opts);
xiofreeaddrinfo(themlist);
free(opts0);free(opts);
return result;
}
@ -114,7 +130,8 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
if (xfd->forever || --xfd->retry) {
Nanosleep(&xfd->intervall, NULL); continue;
}
free(opts0);
xiofreeaddrinfo(themlist);
free(opts0);
return STAT_RETRYLATER;
}
@ -136,6 +153,7 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
}
} while (true);
/* only "active" process breaks (master without fork, or child) */
xiofreeaddrinfo(themlist);
if ((result = _xio_openlate(xfd, opts)) < 0) {
free(opts0);free(opts);
@ -158,12 +176,11 @@ int
int *pf,
int protocol,
unsigned long res_opts0, unsigned long res_opts1,
union sockaddr_union *them, socklen_t *themlen,
struct addrinfo **themlist,
union sockaddr_union *us, socklen_t *uslen,
bool *needbind, bool *lowport,
int socktype) {
uint16_t port;
char infobuff[256];
int result;
retropt_socket_pf(opts, pf);
@ -171,36 +188,35 @@ int
if ((result =
xiogetaddrinfo(hostname, portname,
*pf, socktype, protocol,
(union sockaddr_union *)them, themlen,
themlist,
res_opts0, res_opts1
))
!= STAT_OK) {
return STAT_NORETRY; /*! STAT_RETRYLATER? */
}
if (*pf == PF_UNSPEC) {
*pf = them->soa.sa_family;
}
applyopts(-1, opts, PH_EARLY);
/* 3 means: IP address AND port accepted */
if (retropt_bind(opts, *pf, socktype, protocol, (struct sockaddr *)us, uslen, 3,
if (retropt_bind(opts, (*pf!=PF_UNSPEC)?*pf:(*themlist)->ai_family,
socktype, protocol, (struct sockaddr *)us, uslen, 3,
res_opts0, res_opts1)
!= STAT_NOACTION) {
*needbind = true;
} else {
switch (*pf) {
switch ((*pf!=PF_UNSPEC)?*pf:(*themlist)->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) {
switch ((*pf!=PF_UNSPEC)?*pf:(*themlist)->ai_family) {
#if WITH_IP4
case PF_INET: us->ip4.sin_port = htons(port); break;
#endif /* WITH_IP4 */
@ -216,8 +232,6 @@ int
*opts0 = copyopts(opts, GROUP_ALL);
Notice1("opening connection to %s",
sockaddr_info((struct sockaddr *)them, *themlen, infobuff, sizeof(infobuff)));
return STAT_OK;
}
#endif /* WITH_IP4 */
@ -240,15 +254,14 @@ int _xioopen_ipapp_listen_prepare(struct opt *opts, struct opt **opts0,
retropt_socket_pf(opts, pf);
retropt_string(opts, OPT_BIND, &bindname);
if ((result =
xiogetaddrinfo(bindname, portname, *pf, socktype, ipproto,
(union sockaddr_union *)us, uslen,
res_opts0, res_opts1))
!= STAT_OK) {
result =
xioresolve(bindname, portname, *pf, socktype, ipproto,
us, uslen,
res_opts0, res_opts1);
if (result != STAT_OK) {
/*! STAT_RETRY? */
return result;
}
*opts0 = copyopts(opts, GROUP_ALL);
return STAT_OK;
}

View file

@ -22,7 +22,7 @@ extern int
const char *hostname,
const char *portname, int *pf, int protocol,
unsigned long res_opts0, unsigned long res_opts1,
union sockaddr_union *them, socklen_t *themlen,
struct addrinfo **res,
union sockaddr_union *us, socklen_t *uslen,
bool *needbind, bool *lowport,
int socktype);

View file

@ -145,7 +145,7 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
xiosetchilddied(); /* set SIGCHLD handler */
}
if ((xfd->fd = xiosocket(opts, us->sa_family, socktype, proto, level)) < 0) {
if ((xfd->fd = xiosocket(opts, pf?pf:us->sa_family, socktype, proto, level)) < 0) {
return STAT_RETRYLATER;
}
applyopts(xfd->fd, opts, PH_PASTSOCKET);
@ -199,8 +199,7 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
#if WITH_IP4 /*|| WITH_IP6*/
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
if (xioparserange(rangename, pf, &xfd->para.socket.range)
< 0) {
if (xioparserange(rangename, pf, &xfd->para.socket.range) < 0) {
free(rangename);
return STAT_NORETRY;
}

View file

@ -12,6 +12,7 @@
#include "xioopen.h"
#include "xio-fd.h"
#include "xio-ip.h"
#include "xio-socket.h" /* _xioopen_connect() */
#include "xio-listen.h"
#include "xio-udp.h"
@ -247,9 +248,8 @@ static int
int ipproto = IPPROTO_TCP;
bool dofork = false;
union sockaddr_union us_sa, *us = &us_sa;
union sockaddr_union them_sa, *them = &them_sa;
socklen_t uslen = sizeof(us_sa);
socklen_t themlen = sizeof(them_sa);
struct addrinfo *themlist, *themp;
bool needbind = false;
bool lowport = false;
int level;
@ -328,7 +328,7 @@ static int
_xioopen_ipapp_prepare(opts, &opts0, hostname, portname, &pf, ipproto,
xfd->para.socket.ip.res_opts[1],
xfd->para.socket.ip.res_opts[0],
them, &themlen, us, &uslen,
&themlist, us, &uslen,
&needbind, &lowport, socktype);
if (result != STAT_OK) return STAT_NORETRY;
@ -348,12 +348,22 @@ static int
#endif /* WITH_RETRY */
level = E_ERROR;
/* this cannot fork because we retrieved fork option above */
result =
themp = themlist;
/* loop over themlist */
while (themp != NULL) {
/* This cannot fork because we retrieved fork option above */
result =
_xioopen_connect(xfd,
needbind?us:NULL, uslen,
(struct sockaddr *)them, themlen,
opts, pf, socktype, ipproto, lowport, level);
themp->ai_addr, themp->ai_addrlen,
opts, pf?pf:themp->ai_addr->sa_family, socktype, ipproto, lowport, level);
if (result == STAT_OK)
break;
themp = themp->ai_next;
if (themp == NULL) {
result = STAT_RETRYLATER;
}
}
switch (result) {
case STAT_OK: break;
#if WITH_RETRY
@ -367,14 +377,16 @@ static int
--xfd->retry;
continue;
}
xiofreeaddrinfo(themlist);
return STAT_NORETRY;
#endif /* WITH_RETRY */
default:
xiofreeaddrinfo(themlist);
return result;
}
/*! isn't this too early? */
if ((result = _xio_openlate(xfd, opts)) < 0) {
xiofreeaddrinfo(themlist);
return result;
}
@ -395,7 +407,9 @@ static int
continue;
}
#endif /* WITH_RETRY */
default: return STAT_NORETRY;
default:
xiofreeaddrinfo(themlist);
return STAT_NORETRY;
}
if (dofork) {
@ -413,6 +427,7 @@ static int
if (xfd->forever || --xfd->retry) {
Nanosleep(&xfd->intervall, NULL); continue;
}
xiofreeaddrinfo(themlist);
return STAT_RETRYLATER;
}
@ -433,6 +448,7 @@ static int
#endif /* WITH_RETRY */
break;
} while (true); /* drop out on success */
xiofreeaddrinfo(themlist);
openssl_conn_loginfo(xfd->para.openssl.ssl);

View file

@ -91,9 +91,8 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
/* */
int pf = PF_UNSPEC;
union sockaddr_union us_sa, *us = &us_sa;
union sockaddr_union them_sa, *them = &them_sa;
socklen_t uslen = sizeof(us_sa);
socklen_t themlen = sizeof(them_sa);
struct addrinfo *themlist, *themp;
const char *proxyname; char *proxyport = NULL;
const char *targetname, *targetport;
int ipproto = IPPROTO_TCP;
@ -133,7 +132,7 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
&pf, ipproto,
xfd->para.socket.ip.res_opts[1],
xfd->para.socket.ip.res_opts[0],
them, &themlen, us, &uslen,
&themlist, us, &uslen,
&needbind, &lowport, socktype);
if (result != STAT_OK) return result;
@ -149,11 +148,20 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
#endif /* WITH_RETRY */
level = E_ERROR;
themp = themlist;
/* Loop over themlist */
while (themp != NULL) {
result =
_xioopen_connect(xfd,
needbind?us:NULL, sizeof(*us),
(struct sockaddr *)them, themlen,
opts, pf, socktype, IPPROTO_TCP, lowport, level);
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;
}
switch (result) {
case STAT_OK: break;
#if WITH_RETRY
@ -165,9 +173,11 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
}
#endif /* WITH_RETRY */
default:
xiofreeaddrinfo(themlist);
return result;
}
}
xiofreeaddrinfo(themlist);
applyopts(xfd->fd, opts, PH_ALL);
if ((result = _xio_openlate(xfd, opts)) < 0)
@ -291,7 +301,7 @@ int _xioopen_proxy_prepare(struct proxyvars *proxyvars, struct opt *opts,
/* currently we only resolve to IPv4 addresses. This is in accordance to
RFC 2396; however once it becomes clear how IPv6 addresses should be
represented in CONNECT commands this code might be extended */
rc = xiogetaddrinfo(targetname, targetport, PF_UNSPEC,
rc = xioresolve(targetname, targetport, PF_INET/*!?*/,
SOCK_STREAM, IPPROTO_TCP,
&host, &socklen, 0, 0);
if (rc != STAT_OK) {

View file

@ -121,7 +121,7 @@ int _xioopen_rawip_sendto(const char *hostname, const char *protname,
xfd->salen = sizeof(xfd->peersa);
if ((result =
xiogetaddrinfo(hostname, NULL, *pf, socktype, ipproto,
xioresolve(hostname, NULL, *pf, socktype, ipproto,
&xfd->peersa, &xfd->salen,
xfd->para.socket.ip.res_opts[0],
xfd->para.socket.ip.res_opts[1]))

View file

@ -541,6 +541,7 @@ int xioopen_socket_recvfrom(int argc, const char *argv[], struct opt *opts,
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
if (xioparserange(rangename, 0, &xfd->para.socket.range) < 0) {
free(rangename);
return STAT_NORETRY;
}
xfd->para.socket.dorange = true;
@ -619,6 +620,7 @@ int xioopen_socket_recv(int argc, const char *argv[], struct opt *opts,
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
if (xioparserange(rangename, 0, &xfd->para.socket.range) < 0) {
free(rangename);
return STAT_NORETRY;
}
xfd->para.socket.dorange = true;
@ -1167,8 +1169,7 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
/* for generic sockets, this has already been retrieved */
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
if (xioparserange(rangename, pf, &xfd->para.socket.range)
< 0) {
if (xioparserange(rangename, pf, &xfd->para.socket.range) < 0) {
free(rangename);
return STAT_NORETRY;
}
@ -1370,8 +1371,7 @@ int _xioopen_dgram_recv(struct single *xfd, int xioflags,
#if WITH_IP4 /*|| WITH_IP6*/
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
if (xioparserange(rangename, pf, &xfd->para.socket.range)
< 0) {
if (xioparserange(rangename, pf, &xfd->para.socket.range) < 0) {
free(rangename);
return STAT_NORETRY;
}
@ -1890,6 +1890,7 @@ int xioparsenetwork(const char *rangename, int pf, struct xiorange *range) {
int xioparserange(const char *rangename, int pf, struct xiorange *range) {
int i;
if (xioparsenetwork(rangename, pf, range) < 0) {
Error2("failed to parse or resolve range \"%s\" (pf=%d)", rangename, pf);
return -1;
}
/* we have parsed the address and mask; now we make sure that the stored

View file

@ -52,11 +52,11 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
int ipproto = IPPROTO_TCP;
bool dofork = false;
union sockaddr_union us_sa, *us = &us_sa;
union sockaddr_union them_sa, *them = &them_sa;
socklen_t uslen = sizeof(us_sa);
socklen_t themlen = sizeof(them_sa);
struct addrinfo *themlist, *themp;
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);
@ -87,7 +87,7 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
&pf, ipproto,
xfd->para.socket.ip.res_opts[1],
xfd->para.socket.ip.res_opts[0],
them, &themlen, us, &uslen,
&themlist, us, &uslen,
&needbind, &lowport, socktype);
Notice5("opening connection to %s:%u via socks4 server %s:%s as user \"%s\"",
@ -123,12 +123,24 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
return result;
}
themp = themlist;
/* loop over themlist */
while (themp != NULL) {
Notice1("opening connection to %s",
sockaddr_info(themp->ai_addr, themp->ai_addrlen,
infobuff, sizeof(infobuff)));
/* this cannot fork because we retrieved fork option above */
result =
_xioopen_connect (xfd,
needbind?us:NULL, sizeof(*us),
(struct sockaddr *)them, themlen,
opts, pf, socktype, IPPROTO_TCP, lowport, level);
_xioopen_connect(xfd,
needbind?us:NULL, sizeof(*us),
themp->ai_addr, themp->ai_addrlen,
opts, pf?pf:themp->ai_family, socktype, IPPROTO_TCP, lowport, level);
if (result == STAT_OK)
break;
themp = themp->ai_next;
if (themp == NULL) {
result = STAT_RETRYLATER;
}
switch (result) {
case STAT_OK: break;
#if WITH_RETRY
@ -140,9 +152,11 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
}
#endif /* WITH_RETRY */
default:
xiofreeaddrinfo(themlist);
return result;
}
}
xiofreeaddrinfo(themlist);
applyopts(xfd->fd, opts, PH_ALL);
if ((result = _xio_openlate(xfd, opts)) < 0)
@ -257,7 +271,7 @@ int
union sockaddr_union sau;
socklen_t saulen = sizeof(sau);
if ((result = xiogetaddrinfo(hostname, NULL,
if ((result = xioresolve(hostname, NULL,
PF_INET, SOCK_STREAM, IPPROTO_TCP,
&sau, &saulen,
xfd->para.socket.ip.res_opts[1],

View file

@ -382,7 +382,7 @@ int _xioopen_udp_sendto(const char *hostname, const char *servname,
xfd->salen = sizeof(xfd->peersa);
if ((result =
xiogetaddrinfo(hostname, servname, pf, socktype, ipproto,
xioresolve(hostname, servname, pf, socktype, ipproto,
&xfd->peersa, &xfd->salen,
xfd->para.socket.ip.res_opts[0],
xfd->para.socket.ip.res_opts[1]))
@ -515,7 +515,7 @@ int xioopen_udp_recvfrom(int argc, const char *argv[], struct opt *opts,
}
if ((result =
xiogetaddrinfo(NULL, argv[1], pf, socktype, ipproto,
xioresolve(NULL, argv[1], pf, socktype, ipproto,
&us, &uslen, xfd->stream.para.socket.ip.res_opts[0],
xfd->stream.para.socket.ip.res_opts[1]))
!= STAT_OK) {
@ -588,7 +588,7 @@ int xioopen_udp_recv(int argc, const char *argv[], struct opt *opts,
}
if ((result =
xiogetaddrinfo(NULL, argv[1], pf, socktype, ipproto,
xioresolve(NULL, argv[1], pf, socktype, ipproto,
&us, &uslen, xfd->stream.para.socket.ip.res_opts[0],
xfd->stream.para.socket.ip.res_opts[1]))
!= STAT_OK) {
@ -627,6 +627,7 @@ int xioopen_udp_recv(int argc, const char *argv[], struct opt *opts,
#if WITH_IP4 /*|| WITH_IP6*/
if (retropt_string(opts, OPT_RANGE, &rangename) >= 0) {
if (xioparserange(rangename, pf, &xfd->stream.para.socket.range) < 0) {
free(rangename);
return STAT_NORETRY;
}
xfd->stream.para.socket.dorange = true;

View file

@ -2596,8 +2596,8 @@ int parseopts_table(const char **a, groups_t groups, struct opt **opts,
Error1("trailing data in option \"%s\"", token);
}
*buffp = '\0';
if (xiogetaddrinfo(buff, NULL, AF_INET, SOCK_DGRAM, IPPROTO_IP,
(union sockaddr_union *)&sa, &salen,
if (xioresolve(buff, NULL, AF_INET, SOCK_DGRAM, IPPROTO_IP,
(union sockaddr_union *)&sa, &salen,
0, 0/*!!!*/) != STAT_OK) {
opt->desc = ODESC_ERROR; continue;
}
@ -3174,7 +3174,7 @@ int retropt_bind(struct opt *opts,
}
}
if ((result =
xiogetaddrinfo(hostname[0]!='\0'?hostname:NULL, portp,
xioresolve(hostname[0]!='\0'?hostname:NULL, portp,
af, socktype, ipproto,
(union sockaddr_union *)sa, salen,
res_opts0, res_opts1))