1
0
mirror of https://github.com/moparisthebest/socat synced 2024-12-22 06:58:47 -05:00

LISTEN based addresses applied some address options to the listening FD instead of the connected FD

This commit is contained in:
Gerhard Rieger 2012-09-26 09:13:31 +02:00
parent 4d013105ea
commit 91b00e8c44
6 changed files with 78 additions and 13 deletions

View File

@ -1,5 +1,10 @@
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
include. Thanks to Horacio Mijail for reporting this problem

View File

@ -131,13 +131,12 @@ PH_LATE FD is ready, before start of data loop
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_EARLY before any other processing
PH_PRESOCKET before socket call
PH_SOCKET for socket call
PH_PASTSOCKET after socket call
PH_PREBIND before socket bind()
PH_BIND during socket bind()
PH_PASTBIND past socket bind()
@ -147,7 +146,9 @@ PH_PASTLISTEN after listen()
PH_PREACCEPT before accept()
PH_ACCEPT during accept()
PH_PASTACCEPT after accept()
# and the following on the new FD:
PH_FD soon after FD creation or identification
PH_PASTSOCKET after socket call
PH_CONNECTED phase common with connect
PH_PREFORK before forking
PH_FORK during fork()

63
test.sh
View File

@ -2807,10 +2807,13 @@ esac
PORT=$((PORT+1))
N=$((N+1))
# TCP6-LISTEN may also listen for IPv4 connections. Test if option
# ipv6-v6only=0 shows this behaviour.
NAME=IPV6ONLY0
case "$TESTS" in
*%$N%*|*%functions%*|*%ip6%*|*%ipapp%*|*%tcp%*|*%$NAME%*)
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 :;
elif ! testaddrs tcp ip4 >/dev/null || ! runsip4 >/dev/null; then
$PRINTF "test $F_n $TEST... ${YELLOW}TCP4 not available${NORMAL}\n" $N
@ -2828,8 +2831,8 @@ tdiff="$td/test$N.diff"
tsl=$PORT
ts="127.0.0.1:$tsl"
da="test$N $(date) $RANDOM"
CMD1="$SOCAT $opts TCP6-listen:$tsl,ipv6-v6only=0,reuseaddr PIPE"
CMD2="$SOCAT $opts stdin!!stdout TCP4:$ts"
CMD1="$SOCAT $opts TCP6-LISTEN:$tsl,ipv6-v6only=0,reuseaddr PIPE"
CMD2="$SOCAT $opts STDIN!!STDOUT TCP4:$ts"
printf "test $F_n $TEST... " $N
$CMD1 >"$tf" 2>"${te}1" &
pid=$! # background process id
@ -2858,6 +2861,8 @@ esac
PORT=$((PORT+1))
N=$((N+1))
# TCP6-LISTEN may also listen for IPv4 connections. Test if option
# ipv6-v6only=1 turns off this behaviour.
NAME=IPV6ONLY1
case "$TESTS" in
*%$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)"
# 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
case "$TESTS" in
*%$N%*|*%functions%*|*%ip4%*|*%tcp%*|*%generic%*|*%$NAME%*)
@ -10434,6 +10441,8 @@ fi # NUMCOND, SO_REUSEADDR
esac
PORT=$((PORT+1))
N=$((N+1))
#
fi
NAME=SCTP4STREAM
@ -11139,6 +11148,56 @@ N=$((N+1))
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
# before this paragraph.

View File

@ -1,5 +1,5 @@
/* 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 */
/* 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
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
#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 };

View File

@ -147,8 +147,6 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
return STAT_RETRYLATER;
}
applyopts(xfd->fd, opts, PH_PASTSOCKET);
applyopts_cloexec(xfd->fd, opts);
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);
#endif /* WITH_TCP || WITH_UDP */
applyopts(xfd->fd, opts, PH_PRELISTEN);
retropt_int(opts, OPT_BACKLOG, &backlog);
if (Listen(xfd->fd, backlog) < 0) {
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,
infobuff, sizeof(infobuff)));
applyopts(xfd->fd, opts, PH_FD);
applyopts(xfd->fd, opts, PH_CONNECTED);
if (dofork) {
pid_t pid; /* mostly int; only used with fork */
sigset_t mask_sigchld;
@ -343,6 +339,10 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
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)
return result;

View File

@ -1,5 +1,5 @@
/* 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 */
/* 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};
#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_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};
#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 };