mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 15:32:35 +00:00
SENDTO addresses now prefer IPv4 over IPv6 name resolution
This commit is contained in:
parent
868998eb60
commit
127280088c
4 changed files with 99 additions and 25 deletions
5
CHANGES
5
CHANGES
|
@ -11,6 +11,11 @@ Corrections:
|
||||||
Added Socat option -0 to allow version 1.8.0.0 behaviour (no preferred
|
Added Socat option -0 to allow version 1.8.0.0 behaviour (no preferred
|
||||||
IP version).
|
IP version).
|
||||||
|
|
||||||
|
UDP-SENDTO, UDPLITE-SENDTO, and IP-SENDTO addresses now select an IPv4
|
||||||
|
address in case the server name resolves to both IPv4 and IPv6
|
||||||
|
addresses.
|
||||||
|
Tests: V1800_*_SENDTO_RESOLV_6_4
|
||||||
|
|
||||||
Guard applyopts_termios_value() with WITH_TERMIOS.
|
Guard applyopts_termios_value() with WITH_TERMIOS.
|
||||||
Thanks to Kush Upadhyay from Amazon Bottlerocket team for providing the
|
Thanks to Kush Upadhyay from Amazon Bottlerocket team for providing the
|
||||||
patch.
|
patch.
|
||||||
|
|
86
test.sh
86
test.sh
|
@ -13543,7 +13543,7 @@ te="$td/test$N.stderr"
|
||||||
tdiff="$td/test$N.diff"
|
tdiff="$td/test$N.diff"
|
||||||
da="test$N $(date) $RANDOM"
|
da="test$N $(date) $RANDOM"
|
||||||
newport udp6
|
newport udp6
|
||||||
CMD0="$TRACE $SOCAT $opts UDP6-RECV:$PORT,ipv6-join-group=[ff02::2]:$MCINTERFACE /dev/null"
|
CMD0="$TRACE $SOCAT $opts -T 0.001 -u UDP6-RECV:$PORT,ipv6-join-group=[ff02::2]:$MCINTERFACE /dev/null"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
$CMD0 >/dev/null 2>"${te}0"
|
$CMD0 >/dev/null 2>"${te}0"
|
||||||
rc0=$?
|
rc0=$?
|
||||||
|
@ -17011,6 +17011,10 @@ elif ! A=$(testaddrs TCP-CONNECT GOPEN); then
|
||||||
$PRINTF "test $F_n $TEST... ${YELLOW}Address $A not available in $SOCAT${NORMAL}\n" $N
|
$PRINTF "test $F_n $TEST... ${YELLOW}Address $A not available in $SOCAT${NORMAL}\n" $N
|
||||||
numCANT=$((numCANT+1))
|
numCANT=$((numCANT+1))
|
||||||
listCANT="$listCANT $N"
|
listCANT="$listCANT $N"
|
||||||
|
elif ! o=$(testoptions ai-addrconfig) >/dev/null; then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}Option $o not available in $SOCAT${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
elif ! runsip4 >/dev/null; then
|
elif ! runsip4 >/dev/null; then
|
||||||
$PRINTF "test $F_n $TEST... ${YELLOW}IPv4 not available${NORMAL}\n" $N
|
$PRINTF "test $F_n $TEST... ${YELLOW}IPv4 not available${NORMAL}\n" $N
|
||||||
numCANT=$((numCANT+1))
|
numCANT=$((numCANT+1))
|
||||||
|
@ -17858,7 +17862,6 @@ TEST="$NAME: sigint option with SHELL"
|
||||||
# Send the parent a SIGINT; when the child gets SIGINT too (vs.SIGTERM)
|
# Send the parent a SIGINT; when the child gets SIGINT too (vs.SIGTERM)
|
||||||
# the test succeeded
|
# the test succeeded
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
# Remove unneeded checks, adapt lists of the remaining ones
|
|
||||||
elif ! F=$(testfeats STDIO SHELL PIPE); then
|
elif ! F=$(testfeats STDIO SHELL PIPE); then
|
||||||
$PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not configured in $SOCAT${NORMAL}\n" $N
|
$PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not configured in $SOCAT${NORMAL}\n" $N
|
||||||
numCANT=$((numCANT+1))
|
numCANT=$((numCANT+1))
|
||||||
|
@ -18028,7 +18031,6 @@ TEST="$NAME: sigint option with SYSTEM"
|
||||||
# the test succeeded
|
# the test succeeded
|
||||||
# setsid is required so the initial SIGINT is not delivered to the sub process.
|
# setsid is required so the initial SIGINT is not delivered to the sub process.
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
# Remove unneeded checks, adapt lists of the remaining ones
|
|
||||||
elif [ "$UNAME" = "NetBSD" ]; then
|
elif [ "$UNAME" = "NetBSD" ]; then
|
||||||
# On NetBSD-4.0 and NetBSD-9.3 this test hangs (signal has no effect)
|
# On NetBSD-4.0 and NetBSD-9.3 this test hangs (signal has no effect)
|
||||||
# (other versions not tried)
|
# (other versions not tried)
|
||||||
|
@ -18696,7 +18698,6 @@ TEST="$NAME: f-setpipe-sz on STDIN"
|
||||||
# Start Socat in a shell pipe and have it calling Filan via EXEC and nofork
|
# Start Socat in a shell pipe and have it calling Filan via EXEC and nofork
|
||||||
# Check Filan output if pipe size of its input pipe is modified.
|
# Check Filan output if pipe size of its input pipe is modified.
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
# Remove unneeded checks, adapt lists of the remaining ones
|
|
||||||
elif ! $(type true >/dev/null 2>&1); then
|
elif ! $(type true >/dev/null 2>&1); then
|
||||||
$PRINTF "test $F_n $TEST... ${YELLOW}true not available${NORMAL}\n" $N
|
$PRINTF "test $F_n $TEST... ${YELLOW}true not available${NORMAL}\n" $N
|
||||||
numCANT=$((numCANT+1))
|
numCANT=$((numCANT+1))
|
||||||
|
@ -18763,7 +18764,6 @@ TEST="$NAME: f-setpipe-sz on EXEC with pipes"
|
||||||
# Start Socat calling Filan via EXEC and pipes and f-setpipe-sz
|
# Start Socat calling Filan via EXEC and pipes and f-setpipe-sz
|
||||||
# Check Filan output if pipe size of both pipes is modified.
|
# Check Filan output if pipe size of both pipes is modified.
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
# Remove unneeded checks, adapt lists of the remaining ones
|
|
||||||
elif ! F=$(testfeats STDIO EXEC); then
|
elif ! F=$(testfeats STDIO EXEC); then
|
||||||
$PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not configured in $SOCAT${NORMAL}\n" $N
|
$PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not configured in $SOCAT${NORMAL}\n" $N
|
||||||
numCANT=$((numCANT+1))
|
numCANT=$((numCANT+1))
|
||||||
|
@ -18885,7 +18885,6 @@ case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%udplite%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%udplite%*|*%$NAME%*)
|
||||||
TEST="$NAME: echo via connection to UDP-Lite V4 socket"
|
TEST="$NAME: echo via connection to UDP-Lite V4 socket"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
# Remove unneeded checks, adapt lists of the remaining ones
|
|
||||||
elif ! cond=$(checkconds \
|
elif ! cond=$(checkconds \
|
||||||
"" \
|
"" \
|
||||||
"" \
|
"" \
|
||||||
|
@ -18953,7 +18952,6 @@ case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%udplite%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%udplite%*|*%$NAME%*)
|
||||||
TEST="$NAME: echo via connection to UDP-Lite V4 socket"
|
TEST="$NAME: echo via connection to UDP-Lite V4 socket"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
# Remove unneeded checks, adapt lists of the remaining ones
|
|
||||||
elif ! cond=$(checkconds \
|
elif ! cond=$(checkconds \
|
||||||
"" \
|
"" \
|
||||||
"" \
|
"" \
|
||||||
|
@ -19021,7 +19019,6 @@ case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%udplite%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%udplite%*|*%$NAME%*)
|
||||||
TEST="$NAME: echo via connection to UDP-Lite V4 socket"
|
TEST="$NAME: echo via connection to UDP-Lite V4 socket"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
# Remove unneeded checks, adapt lists of the remaining ones
|
|
||||||
elif ! cond=$(checkconds \
|
elif ! cond=$(checkconds \
|
||||||
"" \
|
"" \
|
||||||
"" \
|
"" \
|
||||||
|
@ -19338,7 +19335,6 @@ TEST="$NAME: test socat-chain.sh with SOCKS4 over UNIX-socket"
|
||||||
# Run a socks4 server on UNIX-listen
|
# Run a socks4 server on UNIX-listen
|
||||||
# Connect with socat-chain.sh; check if data transfer is correct
|
# Connect with socat-chain.sh; check if data transfer is correct
|
||||||
if ! eval $NUMCOND; then :
|
if ! eval $NUMCOND; then :
|
||||||
# Remove unneeded checks, adapt lists of the remaining ones
|
|
||||||
elif ! cond=$(checkconds \
|
elif ! cond=$(checkconds \
|
||||||
"" \
|
"" \
|
||||||
"" \
|
"" \
|
||||||
|
@ -19410,7 +19406,6 @@ TEST="$NAME: test socat-chain.sh with SSL over PTY"
|
||||||
# open the PTY with socat-chain.sh using SSL;
|
# open the PTY with socat-chain.sh using SSL;
|
||||||
# check if data transfer is correct
|
# check if data transfer is correct
|
||||||
if ! eval $NUMCOND; then :
|
if ! eval $NUMCOND; then :
|
||||||
# Remove unneeded checks, adapt lists of the remaining ones
|
|
||||||
elif ! cond=$(checkconds \
|
elif ! cond=$(checkconds \
|
||||||
"" \
|
"" \
|
||||||
"" \
|
"" \
|
||||||
|
@ -19492,7 +19487,6 @@ TEST="$NAME: test the socat-mux.sh script"
|
||||||
# Connect with two clients to mux, send different data records from both.
|
# Connect with two clients to mux, send different data records from both.
|
||||||
# Check if both clients received both records in order.
|
# Check if both clients received both records in order.
|
||||||
if ! eval $NUMCOND; then :
|
if ! eval $NUMCOND; then :
|
||||||
# Remove unneeded checks, adapt lists of the remaining ones
|
|
||||||
elif ! cond=$(checkconds \
|
elif ! cond=$(checkconds \
|
||||||
"" \
|
"" \
|
||||||
"" \
|
"" \
|
||||||
|
@ -19604,7 +19598,6 @@ TEST="$NAME: test the socat-broker.sh script"
|
||||||
# Connect with two clients, send different data records from both.
|
# Connect with two clients, send different data records from both.
|
||||||
# Check if both client received both records in order.
|
# Check if both client received both records in order.
|
||||||
if ! eval $NUMCOND; then :
|
if ! eval $NUMCOND; then :
|
||||||
# Remove unneeded checks, adapt lists of the remaining ones
|
|
||||||
elif ! cond=$(checkconds \
|
elif ! cond=$(checkconds \
|
||||||
"" \
|
"" \
|
||||||
"" \
|
"" \
|
||||||
|
@ -20195,6 +20188,75 @@ IP-DATAGRAM:1.2.3.4 ip4 PROTO . bind=127.0.0.1
|
||||||
"
|
"
|
||||||
|
|
||||||
|
|
||||||
|
# Test if datagram SENDTO to a server name that resolves to IPv6 first and IPv4
|
||||||
|
# as second address, binding to an IPv4 address, uses IPv4
|
||||||
|
# This failed in Socat 1.8.0.0
|
||||||
|
while read ADDR protov IPPORT _; do
|
||||||
|
if [ -z "$ADDR" ] || [[ "$ADDR" == \#* ]]; then continue; fi
|
||||||
|
FEATS=
|
||||||
|
ADDR_="$(echo $ADDR |tr - _)" # UDP_SENDTO
|
||||||
|
PROTO="${ADDR%%-*}" # UDP
|
||||||
|
proto=$(tolower $PROTO) # udp
|
||||||
|
FEATS="$FEATS $PROTO"
|
||||||
|
NAME="$(echo "V1800_${ADDR_}_RESOLV_6_4" |sed 's/:[.0-8]*//')"
|
||||||
|
case "$TESTS" in
|
||||||
|
*%$N%*|*%functions%*|*%bugs%*|*%ip4%*|*%$protov%*|*%$proto%*|*%socket%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: test regression of $ADDR with IPv6,4 and binding to IPv4"
|
||||||
|
# Start a SENDTO command to (internal) test name localhost-6-4.dest-unreach.net
|
||||||
|
# and bind to an IPv4 address, and terminate immediately.
|
||||||
|
# When no error occurs the test succeeded.
|
||||||
|
if ! eval $NUMCOND; then :
|
||||||
|
elif ! cond=$(checkconds \
|
||||||
|
"" \
|
||||||
|
"$([ $IPPORT = PROTO ] && echo root)" \
|
||||||
|
"" \
|
||||||
|
"$FEATS DEVTESTS IP4" \
|
||||||
|
"$ADDR GOPEN" \
|
||||||
|
"bind" \
|
||||||
|
"$protov" ); then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}$cond${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
namesCANT="$namesCANT $NAME"
|
||||||
|
else
|
||||||
|
tf="$td/test$N.stdout"
|
||||||
|
te="$td/test$N.stderr"
|
||||||
|
tdiff="$td/test$N.diff"
|
||||||
|
da="test$N $(date) $RANDOM"
|
||||||
|
case X$IPPORT in
|
||||||
|
XPORT) newport $(tolower $PROTO); _PORT=$PORT ;;
|
||||||
|
XPROTO) echo "IPPROTO=\"$IPPROTO\""
|
||||||
|
_PORT=$IPPROTO ;;
|
||||||
|
esac
|
||||||
|
CMD0="$TRACE $SOCAT $opts -u /dev/null $ADDR:localhost-6-4.dest-unreach.net:$_PORT,bind=127.0.0.1"
|
||||||
|
printf "test $F_n $TEST... " $N
|
||||||
|
$CMD0 2>"${te}0" </dev/null
|
||||||
|
rc0=$?
|
||||||
|
if [ "$rc0" -ne 0 ]; then
|
||||||
|
$PRINTF "$FAILED (rc0=$rc0)\n"
|
||||||
|
echo "$CMD0 &"
|
||||||
|
cat "${te}0" >&2
|
||||||
|
numFAIL=$((numFAIL+1))
|
||||||
|
listFAIL="$listFAIL $N"
|
||||||
|
namesFAIL="$namesFAIL $NAME"
|
||||||
|
else
|
||||||
|
$PRINTF "$OK\n"
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}0" >&2; fi
|
||||||
|
numOK=$((numOK+1))
|
||||||
|
listOK="$listOK $N"
|
||||||
|
fi
|
||||||
|
fi # NUMCOND
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
PORT=$((PORT+1))
|
||||||
|
N=$((N+1))
|
||||||
|
done <<<"
|
||||||
|
UDP-SENDTO udp4 PORT
|
||||||
|
UDPLITE-SENDTO udplite4 PORT
|
||||||
|
IP-SENDTO ip4 PROTO
|
||||||
|
"
|
||||||
|
|
||||||
# end of common tests
|
# end of common tests
|
||||||
|
|
||||||
##################################################################################
|
##################################################################################
|
||||||
|
|
11
xio-ip.c
11
xio-ip.c
|
@ -516,8 +516,11 @@ int xiogetaddrinfo(const char *node, const char *service,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((error_num = Getaddrinfo(node, service, &hints, res)) != 0) {
|
if ((error_num = Getaddrinfo(node, service, &hints, res)) != 0) {
|
||||||
if (*res != NULL)
|
Warn7("getaddrinfo(\"%s\", \"%s\", {0x%02x,%d,%d,%d}, {}): %d",
|
||||||
freeaddrinfo(*res);
|
node?node:"NULL", service?service:"NULL",
|
||||||
|
hints.ai_flags, hints.ai_family,
|
||||||
|
hints.ai_socktype, hints.ai_protocol,
|
||||||
|
error_num);
|
||||||
if (numnode)
|
if (numnode)
|
||||||
free(numnode);
|
free(numnode);
|
||||||
|
|
||||||
|
@ -664,7 +667,7 @@ void xiofreeaddrinfo(struct addrinfo *res) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A simple resolver interface that just returns one address,
|
/* A simple resolver interface that just returns one address,
|
||||||
the first found by calling xiogetaddrinfo().
|
the first found by calling xiogetaddrinfo(), but ev.respects preferred_ip;
|
||||||
pf may be AF_INET, AF_INET6, or AF_UNSPEC;
|
pf may be AF_INET, AF_INET6, or AF_UNSPEC;
|
||||||
on failure logs error message;
|
on failure logs error message;
|
||||||
returns STAT_OK, STAT_RETRYLATER, STAT_NORETRY
|
returns STAT_OK, STAT_RETRYLATER, STAT_NORETRY
|
||||||
|
@ -683,13 +686,11 @@ int xioresolve(const char *node, const char *service,
|
||||||
if (rc == EAI_AGAIN) {
|
if (rc == EAI_AGAIN) {
|
||||||
Warn3("xioresolve(node=\"%s\", pf=%d, ...): %s",
|
Warn3("xioresolve(node=\"%s\", pf=%d, ...): %s",
|
||||||
node?node:"NULL", pf, gai_strerror(rc));
|
node?node:"NULL", pf, gai_strerror(rc));
|
||||||
xiofreeaddrinfo(res);
|
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
} else if (rc != 0) {
|
} else if (rc != 0) {
|
||||||
Error3("xioresolve(node=\"%s\", pf=%d, ...): %s",
|
Error3("xioresolve(node=\"%s\", pf=%d, ...): %s",
|
||||||
node?node:"NULL", pf,
|
node?node:"NULL", pf,
|
||||||
(rc == EAI_SYSTEM)?strerror(errno):gai_strerror(rc));
|
(rc == EAI_SYSTEM)?strerror(errno):gai_strerror(rc));
|
||||||
xiofreeaddrinfo(res);
|
|
||||||
return STAT_NORETRY;
|
return STAT_NORETRY;
|
||||||
}
|
}
|
||||||
if (res == NULL) {
|
if (res == NULL) {
|
||||||
|
|
22
xio-ipapp.c
22
xio-ipapp.c
|
@ -230,18 +230,24 @@ int
|
||||||
bool *lowport,
|
bool *lowport,
|
||||||
int socktype) {
|
int socktype) {
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
int result;
|
int rc;
|
||||||
|
|
||||||
retropt_socket_pf(opts, pf);
|
retropt_socket_pf(opts, pf);
|
||||||
|
|
||||||
if (hostname != NULL || portname != NULL) {
|
if (hostname != NULL || portname != NULL) {
|
||||||
if ((result =
|
rc = xiogetaddrinfo(hostname, portname, *pf, socktype, protocol,
|
||||||
xiogetaddrinfo(hostname, portname,
|
themlist, ai_flags);
|
||||||
*pf, socktype, protocol,
|
if (rc == EAI_AGAIN) {
|
||||||
themlist, ai_flags))
|
Warn4("_xioopen_ipapp_prepare(node=\"%s\", service=\"%s\", pf=%d, ...): %s",
|
||||||
!= STAT_OK) {
|
hostname?hostname:"NULL", portname?portname:"NULL",
|
||||||
return STAT_NORETRY; /*! STAT_RETRYLATER? */
|
*pf, gai_strerror(rc));
|
||||||
}
|
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));
|
||||||
|
return STAT_NORETRY; /*! STAT_RETRYLATER? */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
applyopts(NULL, -1, opts, PH_EARLY);
|
applyopts(NULL, -1, opts, PH_EARLY);
|
||||||
|
|
Loading…
Reference in a new issue