mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 23:42:34 +00:00
LISTEN based addresses applied some address options to the listening FD instead of the connected FD
This commit is contained in:
parent
4d013105ea
commit
91b00e8c44
6 changed files with 78 additions and 13 deletions
5
CHANGES
5
CHANGES
|
@ -1,5 +1,10 @@
|
||||||
|
|
||||||
corrections:
|
corrections:
|
||||||
|
LISTEN based addresses applied some address options, e.g. so-keepalive,
|
||||||
|
to the listening file descriptor instead of the connected file
|
||||||
|
descriptor
|
||||||
|
Thanks to Ulises Alonso for reporting this bug
|
||||||
|
|
||||||
make failed after configure with non gcc compiler due to missing
|
make failed after configure with non gcc compiler due to missing
|
||||||
include. Thanks to Horacio Mijail for reporting this problem
|
include. Thanks to Horacio Mijail for reporting this problem
|
||||||
|
|
||||||
|
|
|
@ -131,13 +131,12 @@ PH_LATE FD is ready, before start of data loop
|
||||||
PH_LATE2 FD is ready, dropping privileges
|
PH_LATE2 FD is ready, dropping privileges
|
||||||
|
|
||||||
|
|
||||||
SOCKET with LISTEN and FORK:
|
SOCKET with LISTEN and ACCEPT:
|
||||||
|
|
||||||
PH_INIT retrieving info from original state
|
PH_INIT retrieving info from original state
|
||||||
PH_EARLY before any other processing
|
PH_EARLY before any other processing
|
||||||
PH_PRESOCKET before socket call
|
PH_PRESOCKET before socket call
|
||||||
PH_SOCKET for socket call
|
PH_SOCKET for socket call
|
||||||
PH_PASTSOCKET after socket call
|
|
||||||
PH_PREBIND before socket bind()
|
PH_PREBIND before socket bind()
|
||||||
PH_BIND during socket bind()
|
PH_BIND during socket bind()
|
||||||
PH_PASTBIND past socket bind()
|
PH_PASTBIND past socket bind()
|
||||||
|
@ -147,7 +146,9 @@ PH_PASTLISTEN after listen()
|
||||||
PH_PREACCEPT before accept()
|
PH_PREACCEPT before accept()
|
||||||
PH_ACCEPT during accept()
|
PH_ACCEPT during accept()
|
||||||
PH_PASTACCEPT after accept()
|
PH_PASTACCEPT after accept()
|
||||||
|
# and the following on the new FD:
|
||||||
PH_FD soon after FD creation or identification
|
PH_FD soon after FD creation or identification
|
||||||
|
PH_PASTSOCKET after socket call
|
||||||
PH_CONNECTED phase common with connect
|
PH_CONNECTED phase common with connect
|
||||||
PH_PREFORK before forking
|
PH_PREFORK before forking
|
||||||
PH_FORK during fork()
|
PH_FORK during fork()
|
||||||
|
|
63
test.sh
63
test.sh
|
@ -2807,10 +2807,13 @@ esac
|
||||||
PORT=$((PORT+1))
|
PORT=$((PORT+1))
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
# TCP6-LISTEN may also listen for IPv4 connections. Test if option
|
||||||
|
# ipv6-v6only=0 shows this behaviour.
|
||||||
NAME=IPV6ONLY0
|
NAME=IPV6ONLY0
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%ip6%*|*%ipapp%*|*%tcp%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%ip6%*|*%ipapp%*|*%tcp%*|*%$NAME%*)
|
||||||
TEST="$NAME: option ipv6-v6only=0 listens on IPv4"
|
TEST="$NAME: option ipv6-v6only=0 listens on IPv4"
|
||||||
|
# create a listening TCP6 socket and try to connect to the port using TCP4
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif ! testaddrs tcp ip4 >/dev/null || ! runsip4 >/dev/null; then
|
elif ! testaddrs tcp ip4 >/dev/null || ! runsip4 >/dev/null; then
|
||||||
$PRINTF "test $F_n $TEST... ${YELLOW}TCP4 not available${NORMAL}\n" $N
|
$PRINTF "test $F_n $TEST... ${YELLOW}TCP4 not available${NORMAL}\n" $N
|
||||||
|
@ -2828,8 +2831,8 @@ tdiff="$td/test$N.diff"
|
||||||
tsl=$PORT
|
tsl=$PORT
|
||||||
ts="127.0.0.1:$tsl"
|
ts="127.0.0.1:$tsl"
|
||||||
da="test$N $(date) $RANDOM"
|
da="test$N $(date) $RANDOM"
|
||||||
CMD1="$SOCAT $opts TCP6-listen:$tsl,ipv6-v6only=0,reuseaddr PIPE"
|
CMD1="$SOCAT $opts TCP6-LISTEN:$tsl,ipv6-v6only=0,reuseaddr PIPE"
|
||||||
CMD2="$SOCAT $opts stdin!!stdout TCP4:$ts"
|
CMD2="$SOCAT $opts STDIN!!STDOUT TCP4:$ts"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
$CMD1 >"$tf" 2>"${te}1" &
|
$CMD1 >"$tf" 2>"${te}1" &
|
||||||
pid=$! # background process id
|
pid=$! # background process id
|
||||||
|
@ -2858,6 +2861,8 @@ esac
|
||||||
PORT=$((PORT+1))
|
PORT=$((PORT+1))
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
# TCP6-LISTEN may also listen for IPv4 connections. Test if option
|
||||||
|
# ipv6-v6only=1 turns off this behaviour.
|
||||||
NAME=IPV6ONLY1
|
NAME=IPV6ONLY1
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%ip6%*|*%ipapp%*|*%tcp%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%ip6%*|*%ipapp%*|*%tcp%*|*%$NAME%*)
|
||||||
|
@ -10365,6 +10370,8 @@ SOL_SOCKET="$($PROCAN -c |grep "^#define[[:space:]]*SOL_SOCKET[[:space:]]" |cut
|
||||||
SO_REUSEADDR="$($PROCAN -c |grep "^#define[[:space:]]*SO_REUSEADDR[[:space:]]" |cut -d' ' -f3)"
|
SO_REUSEADDR="$($PROCAN -c |grep "^#define[[:space:]]*SO_REUSEADDR[[:space:]]" |cut -d' ' -f3)"
|
||||||
|
|
||||||
# test the generic setsockopt-int option
|
# test the generic setsockopt-int option
|
||||||
|
if false; then
|
||||||
|
# this test no longer works due to fix for options on listening sockets
|
||||||
NAME=SETSOCKOPT_INT
|
NAME=SETSOCKOPT_INT
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%ip4%*|*%tcp%*|*%generic%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%ip4%*|*%tcp%*|*%generic%*|*%$NAME%*)
|
||||||
|
@ -10434,6 +10441,8 @@ fi # NUMCOND, SO_REUSEADDR
|
||||||
esac
|
esac
|
||||||
PORT=$((PORT+1))
|
PORT=$((PORT+1))
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
#
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
NAME=SCTP4STREAM
|
NAME=SCTP4STREAM
|
||||||
|
@ -11139,6 +11148,56 @@ N=$((N+1))
|
||||||
fi # false
|
fi # false
|
||||||
|
|
||||||
|
|
||||||
|
# LISTEN addresses in socat up to 1.7.2.1 applied many file descriptor, socket,
|
||||||
|
# and TCP options only to the listening socket instead of the connection socket.
|
||||||
|
NAME=LISTEN_KEEPALIVE
|
||||||
|
case "$TESTS" in
|
||||||
|
*%functions%*|*%bugs%*|*%listen%*|*%keepalive%*|*%socket%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: keepalive option is applied to connection socket"
|
||||||
|
# instance 0 has TCP-LISTEN with option so-keepalive and invokes filan after
|
||||||
|
# accept(). filan writes its output to the socket. instance 1 connects to
|
||||||
|
# instance 0. The value of the sockets so-keepalive option is checked, it must
|
||||||
|
# be 1
|
||||||
|
if ! eval $NUMCOND; then :; else
|
||||||
|
tf="$td/test$N.stdout"
|
||||||
|
te="$td/test$N.stderr"
|
||||||
|
#tdiff="$td/test$N.diff"
|
||||||
|
#da="test$N $(date) $RANDOM"
|
||||||
|
CMD0="$SOCAT $opts TCP4-LISTEN:$PORT,reuseaddr,so-keepalive EXEC:\"$FILAN -i 1\",nofork"
|
||||||
|
CMD1="$SOCAT $opts - TCP4:$LOCALHOST:$PORT"
|
||||||
|
printf "test $F_n $TEST... " $N
|
||||||
|
eval $CMD0 >/dev/null 2>"${te}0" &
|
||||||
|
pid0=$!
|
||||||
|
waittcp4port $PORT 1
|
||||||
|
$CMD1 >"${tf}1" 2>"${te}1"
|
||||||
|
KEEPALIVE="$(cat "${tf}1" |tail -n +2 |sed -e "s/.*KEEPALIVE=//" -e "s/[[:space:]].*//")"
|
||||||
|
rc1=$?
|
||||||
|
kill $pid0 2>/dev/null; wait
|
||||||
|
if [ -z "$KEEPALIVE" ]; then
|
||||||
|
$PRINTF "$NO_RESULT\n"
|
||||||
|
echo "$CMD0 &"
|
||||||
|
echo "$CMD1"
|
||||||
|
cat "${te}0"
|
||||||
|
cat "${te}1"
|
||||||
|
numWARN=$((numWARN+1))
|
||||||
|
elif [ "$KEEPALIVE" = "1" ]; then
|
||||||
|
$PRINTF "$OK\n";
|
||||||
|
numOK=$((numOK+1))
|
||||||
|
else
|
||||||
|
$PRINTF "$FAILED\n"
|
||||||
|
echo "$CMD0 &"
|
||||||
|
echo "$CMD1"
|
||||||
|
cat "${te}0"
|
||||||
|
cat "${te}1"
|
||||||
|
numFAIL=$((numFAIL+1))
|
||||||
|
fi
|
||||||
|
fi # NUMCOND
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
PORT=$((PORT+1))
|
||||||
|
N=$((N+1))
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# here come tests that might affect your systems integrity. Put normal tests
|
# here come tests that might affect your systems integrity. Put normal tests
|
||||||
# before this paragraph.
|
# before this paragraph.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* source: xio-ip6.c */
|
/* source: xio-ip6.c */
|
||||||
/* Copyright Gerhard Rieger 2001-2011 */
|
/* Copyright Gerhard Rieger 2001-2012 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
/* this file contains the source for IP6 related functions */
|
/* this file contains the source for IP6 related functions */
|
||||||
|
@ -20,7 +20,7 @@ static char *inet6addr_info(const struct in6_addr *sa, char *buff, size_t blen);
|
||||||
|
|
||||||
|
|
||||||
#ifdef IPV6_V6ONLY
|
#ifdef IPV6_V6ONLY
|
||||||
const struct optdesc opt_ipv6_v6only = { "ipv6-v6only", "ipv6only", OPT_IPV6_V6ONLY, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_V6ONLY };
|
const struct optdesc opt_ipv6_v6only = { "ipv6-v6only", "ipv6only", OPT_IPV6_V6ONLY, GROUP_SOCK_IP6, PH_PREBIND, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_V6ONLY };
|
||||||
#endif
|
#endif
|
||||||
#ifdef IPV6_JOIN_GROUP
|
#ifdef IPV6_JOIN_GROUP
|
||||||
const struct optdesc opt_ipv6_join_group = { "ipv6-join-group", "join-group", OPT_IPV6_JOIN_GROUP, GROUP_SOCK_IP6, PH_PASTBIND, TYPE_IP_MREQN, OFUNC_SOCKOPT, SOL_IPV6, IPV6_JOIN_GROUP };
|
const struct optdesc opt_ipv6_join_group = { "ipv6-join-group", "join-group", OPT_IPV6_JOIN_GROUP, GROUP_SOCK_IP6, PH_PASTBIND, TYPE_IP_MREQN, OFUNC_SOCKOPT, SOL_IPV6, IPV6_JOIN_GROUP };
|
||||||
|
|
10
xio-listen.c
10
xio-listen.c
|
@ -147,8 +147,6 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
|
||||||
applyopts(xfd->fd, opts, PH_PASTSOCKET);
|
|
||||||
|
|
||||||
applyopts_cloexec(xfd->fd, opts);
|
applyopts_cloexec(xfd->fd, opts);
|
||||||
|
|
||||||
applyopts(xfd->fd, opts, PH_PREBIND);
|
applyopts(xfd->fd, opts, PH_PREBIND);
|
||||||
|
@ -206,6 +204,7 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
|
||||||
retropt_bool(opts, OPT_LOWPORT, &xfd->para.socket.ip.lowport);
|
retropt_bool(opts, OPT_LOWPORT, &xfd->para.socket.ip.lowport);
|
||||||
#endif /* WITH_TCP || WITH_UDP */
|
#endif /* WITH_TCP || WITH_UDP */
|
||||||
|
|
||||||
|
applyopts(xfd->fd, opts, PH_PRELISTEN);
|
||||||
retropt_int(opts, OPT_BACKLOG, &backlog);
|
retropt_int(opts, OPT_BACKLOG, &backlog);
|
||||||
if (Listen(xfd->fd, backlog) < 0) {
|
if (Listen(xfd->fd, backlog) < 0) {
|
||||||
Error3("listen(%d, %d): %s", xfd->fd, backlog, strerror(errno));
|
Error3("listen(%d, %d): %s", xfd->fd, backlog, strerror(errno));
|
||||||
|
@ -277,9 +276,6 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
|
||||||
sockaddr_info((struct sockaddr *)pa, pas,
|
sockaddr_info((struct sockaddr *)pa, pas,
|
||||||
infobuff, sizeof(infobuff)));
|
infobuff, sizeof(infobuff)));
|
||||||
|
|
||||||
applyopts(xfd->fd, opts, PH_FD);
|
|
||||||
applyopts(xfd->fd, opts, PH_CONNECTED);
|
|
||||||
|
|
||||||
if (dofork) {
|
if (dofork) {
|
||||||
pid_t pid; /* mostly int; only used with fork */
|
pid_t pid; /* mostly int; only used with fork */
|
||||||
sigset_t mask_sigchld;
|
sigset_t mask_sigchld;
|
||||||
|
@ -343,6 +339,10 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
applyopts(xfd->fd, opts, PH_FD);
|
||||||
|
applyopts(xfd->fd, opts, PH_PASTSOCKET);
|
||||||
|
applyopts(xfd->fd, opts, PH_CONNECTED);
|
||||||
if ((result = _xio_openlate(xfd, opts)) < 0)
|
if ((result = _xio_openlate(xfd, opts)) < 0)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* source: xio-socket.c */
|
/* source: xio-socket.c */
|
||||||
/* Copyright Gerhard Rieger 2001-2011 */
|
/* Copyright Gerhard Rieger 2001-2012 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
/* this file contains the source for socket related functions, and the
|
/* this file contains the source for socket related functions, and the
|
||||||
|
@ -85,7 +85,7 @@ const struct optdesc opt_so_debug = { "so-debug", "debug", OPT_SO_DEBUG,
|
||||||
const struct optdesc opt_so_acceptconn={ "so-acceptconn","acceptconn",OPT_SO_ACCEPTCONN,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_ACCEPTCONN};
|
const struct optdesc opt_so_acceptconn={ "so-acceptconn","acceptconn",OPT_SO_ACCEPTCONN,GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_ACCEPTCONN};
|
||||||
#endif /* SO_ACCEPTCONN */
|
#endif /* SO_ACCEPTCONN */
|
||||||
const struct optdesc opt_so_broadcast= { "so-broadcast", "broadcast", OPT_SO_BROADCAST,GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_BROADCAST};
|
const struct optdesc opt_so_broadcast= { "so-broadcast", "broadcast", OPT_SO_BROADCAST,GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_BROADCAST};
|
||||||
const struct optdesc opt_so_reuseaddr= { "so-reuseaddr", "reuseaddr", OPT_SO_REUSEADDR,GROUP_SOCKET, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_REUSEADDR};
|
const struct optdesc opt_so_reuseaddr= { "so-reuseaddr", "reuseaddr", OPT_SO_REUSEADDR,GROUP_SOCKET, PH_PREBIND, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_REUSEADDR};
|
||||||
const struct optdesc opt_so_keepalive= { "so-keepalive", "keepalive", OPT_SO_KEEPALIVE,GROUP_SOCKET, PH_FD, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_KEEPALIVE};
|
const struct optdesc opt_so_keepalive= { "so-keepalive", "keepalive", OPT_SO_KEEPALIVE,GROUP_SOCKET, PH_FD, TYPE_INT, OFUNC_SOCKOPT, SOL_SOCKET, SO_KEEPALIVE};
|
||||||
#if HAVE_STRUCT_LINGER
|
#if HAVE_STRUCT_LINGER
|
||||||
const struct optdesc opt_so_linger = { "so-linger", "linger", OPT_SO_LINGER, GROUP_SOCKET, PH_PASTSOCKET, TYPE_LINGER,OFUNC_SOCKOPT,SOL_SOCKET, SO_LINGER };
|
const struct optdesc opt_so_linger = { "so-linger", "linger", OPT_SO_LINGER, GROUP_SOCKET, PH_PASTSOCKET, TYPE_LINGER,OFUNC_SOCKOPT,SOL_SOCKET, SO_LINGER };
|
||||||
|
|
Loading…
Reference in a new issue