UDP-LISTEN would alway set SO_REUSEADDR even without fork option and when user set it to 0

This commit is contained in:
Gerhard Rieger 2010-10-03 16:38:04 +02:00
parent cb913fbc0c
commit 2e385902c0
3 changed files with 73 additions and 7 deletions

View file

@ -8,6 +8,9 @@ corrections:
socket using address GOPEN. Thanks to Martin Forssen for bug report and
patch.
UDP-LISTEN would alway set SO_REUSEADDR even without fork option and
when user set it to 0. Thanks to Michal Svoboda for reporting this bug.
####################### V 1.7.1.3:
security:

57
test.sh
View file

@ -5945,6 +5945,63 @@ esac
N=$((N+1))
NAME=UDPLISTENFORK
case "$TESTS" in
*%functions%*|*%ip4%*|*%udp%*|*%listen%*|*%fork%*|*%$NAME%*)
TEST="$NAME: UDP socket rebinds after first connection"
if ! eval $NUMCOND; then :; else
tf="$td/test$N.stdout"
te="$td/test$N.stderr"
tdiff="$td/test$N.diff"
da1="test$N $(date) $RANDOM"
da2="test$N $(date) $RANDOM"
#establish a listening and forking udp socket in background
SRV="$SOCAT $opts -lpserver UDP4-LISTEN:$PORT,bind=$LOCALHOST,fork PIPE"
#make a first and a second connection
CLI="$SOCAT $opts -lpclient - UDP4-CONNECT:$LOCALHOST:$PORT"
$PRINTF "test $F_n $TEST... " $N
eval "$SRV 2>${te}s &"
pids=$!
waitudp4port "$PORT"
echo "$da1" |eval "$CLI" >"${tf}1" 2>"${te}1"
if [ $? -ne 0 ]; then
kill "$pids" 2>/dev/null
$PRINTF "$NO_RESULT (first conn failed):\n"
echo "$SRV &"
echo "$CLI"
cat "${te}s" "${te}1"
numCANT=$((numCANT+1))
elif ! echo "$da1" |diff - "${tf}1" >"$tdiff"; then
kill "$pids" 2>/dev/null
$PRINTF "$NO_RESULT (first conn failed); diff:\n"
cat "$tdiff"
numCANT=$((numCANT+1))
else
sleep 2 # UDP-LISTEN sleeps 1s
echo "$da2" |eval "$CLI" >"${tf}2" 2>"${te}2"
rc="$?"; kill "$pids" 2>/dev/null
if [ $rc -ne 0 ]; then
$PRINTF "$FAILED:\n"
echo "$SRV &"
echo "$CLI"
cat "${te}s" "${te}2"
numFAIL=$((numFAIL+1))
elif ! echo "$da2" |diff - "${tf}2" >"$tdiff"; then
$PRINTF "$FAILED: diff\n"
cat "$tdiff"
numFAIL=$((numFAIL+1))
else
$PRINTF "$OK\n"
numOK=$((numOK+1))
fi # !( $? -ne 0)
fi # !(rc -ne 0)
wait
fi ;; # NUMCOND, feats
esac
PORT=$((PORT+1))
N=$((N+1))
NAME=UNIXLISTENFORK
case "$TESTS" in
*%functions%*|*%unix%*|*%listen%*|*%fork%*|*%$NAME%*)

View file

@ -1,5 +1,5 @@
/* source: xio-udp.c */
/* Copyright Gerhard Rieger 2001-2008 */
/* Copyright Gerhard Rieger 2001-2010 */
/* Published under the GNU General Public License V.2, see file COPYING */
/* this file contains the source for handling UDP addresses */
@ -170,7 +170,8 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
while (true) { /* we loop with fork or prohibited packets */
/* now wait for some packet on this datagram socket, get its sender
address, connect there, and return */
int one = 1;
int reuseaddr = dofork;
int doreuseaddr = (dofork != 0);
char infobuff[256];
union sockaddr_union _sockname;
union sockaddr_union *la = &_sockname; /* local address */
@ -178,12 +179,17 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
if ((fd->stream.fd = xiosocket(opts, pf, socktype, ipproto, E_ERROR)) < 0) {
return STAT_RETRYLATER;
}
doreuseaddr |= (retropt_int(opts, OPT_SO_REUSEADDR, &reuseaddr) >= 0);
applyopts(fd->stream.fd, opts, PH_PASTSOCKET);
if (Setsockopt(fd->stream.fd, opt_so_reuseaddr.major,
opt_so_reuseaddr.minor, &one, sizeof(one)) < 0) {
Warn6("setsockopt(%d, %d, %d, {%d}, "F_Zd"): %s",
fd->stream.fd, opt_so_reuseaddr.major,
opt_so_reuseaddr.minor, one, sizeof(one), strerror(errno));
if (doreuseaddr) {
if (Setsockopt(fd->stream.fd, opt_so_reuseaddr.major,
opt_so_reuseaddr.minor, &reuseaddr, sizeof(reuseaddr))
< 0) {
Warn6("setsockopt(%d, %d, %d, {%d}, "F_Zd"): %s",
fd->stream.fd, opt_so_reuseaddr.major,
opt_so_reuseaddr.minor, reuseaddr, sizeof(reuseaddr),
strerror(errno));
}
}
applyopts_cloexec(fd->stream.fd, opts);
applyopts(fd->stream.fd, opts, PH_PREBIND);