mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 23:42:34 +00:00
Replaced SIGUSR1 with socketpair for synchronization between parent and child processes on RECVFROM type addresses
This commit is contained in:
parent
a0e17a813a
commit
02483ff39e
12 changed files with 269 additions and 257 deletions
7
CHANGES
7
CHANGES
|
@ -28,6 +28,13 @@ Coding:
|
||||||
|
|
||||||
Make gcc happy, replace strncat with "manual" copying
|
Make gcc happy, replace strncat with "manual" copying
|
||||||
|
|
||||||
|
On addresses like UDP-RECVFROM with fork option every packet causes a
|
||||||
|
new child process which then reads the packet. The parent process must
|
||||||
|
wait until the packet has been read before checking again. The former
|
||||||
|
synchronization mechanism using SIGUSR1 is now replaced by a
|
||||||
|
socketpair. SIGUSR1 is no longer used for internal synchronization.
|
||||||
|
Tests: UDP4_FORK UDP6_FORK UNIX_FORK
|
||||||
|
|
||||||
####################### V 1.7.4.5 (not released):
|
####################### V 1.7.4.5 (not released):
|
||||||
|
|
||||||
Corrections:
|
Corrections:
|
||||||
|
|
1
socat.c
1
socat.c
|
@ -720,6 +720,7 @@ int socat(const char *address1, const char *address2) {
|
||||||
the communication channel, so continue */
|
the communication channel, so continue */
|
||||||
Info2("child "F_pid" has already died with status %d",
|
Info2("child "F_pid" has already died with status %d",
|
||||||
XIO_RDSTREAM(sock1)->para.exec.pid, statunknown[i]);
|
XIO_RDSTREAM(sock1)->para.exec.pid, statunknown[i]);
|
||||||
|
++num_child; /* it was counted as anonymous child, undo */
|
||||||
if (statunknown[i] != 0) {
|
if (statunknown[i] != 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
278
test.sh
278
test.sh
|
@ -1935,7 +1935,7 @@ testaddrs () {
|
||||||
local a A;
|
local a A;
|
||||||
for a in $@; do
|
for a in $@; do
|
||||||
A=$(echo "$a" |tr 'a-z' 'A-Z')
|
A=$(echo "$a" |tr 'a-z' 'A-Z')
|
||||||
if ! $SOCAT $A /dev/null 2>&1 |grep -q "E unknown device/address"; then
|
if ! $SOCAT $A /dev/null 2>&1 </dev/null |grep -q "E unknown device/address"; then
|
||||||
shift
|
shift
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
@ -1991,7 +1991,8 @@ childpids () {
|
||||||
AIX) l="$(ps -fade |grep "^........ ...... $(printf %6u $1)" |awk '{print($2);}')" ;;
|
AIX) l="$(ps -fade |grep "^........ ...... $(printf %6u $1)" |awk '{print($2);}')" ;;
|
||||||
FreeBSD) l="$(ps -fl |grep "^[^ ][^ ]*[ ][ ]*[0-9][0-9]*[ ][ ]*$(printf %5u $1)" |awk '{print($2);}')" ;;
|
FreeBSD) l="$(ps -fl |grep "^[^ ][^ ]*[ ][ ]*[0-9][0-9]*[ ][ ]*$(printf %5u $1)" |awk '{print($2);}')" ;;
|
||||||
HP-UX) l="$(ps -fade |grep "^........ ..... $(printf %5u $1)" |awk '{print($2);}')" ;;
|
HP-UX) l="$(ps -fade |grep "^........ ..... $(printf %5u $1)" |awk '{print($2);}')" ;;
|
||||||
Linux) l="$(ps -fade |grep "^........ ..... $(printf %5u $1)" |awk '{print($2);}')" ;;
|
# Linux) l="$(ps -fade |grep "^........ ..... $(printf %5u $1)" |awk '{print($2);}')" ;;
|
||||||
|
Linux) l="$(ps -fade |grep "^[^[:space:]][^[:space:]]*[[:space:]][[:space:]]*[^[:space:]][^[:space:]]*[[:space:]][[:space:]]*$1 " |awk '{print($2);}')" ;;
|
||||||
# NetBSD) l="$(ps -aj |grep "^........ ..... $(printf %4u $1)" |awk '{print($2);}')" ;;
|
# NetBSD) l="$(ps -aj |grep "^........ ..... $(printf %4u $1)" |awk '{print($2);}')" ;;
|
||||||
NetBSD) l="$(ps -aj |grep "^[^ ][^ ]*[ ][ ]*..... $(printf %5u $1)" |awk '{print($2);}')" ;;
|
NetBSD) l="$(ps -aj |grep "^[^ ][^ ]*[ ][ ]*..... $(printf %5u $1)" |awk '{print($2);}')" ;;
|
||||||
OpenBSD) l="$(ps -aj |grep "^........ ..... $(printf %5u $1)" |awk '{print($2);}')" ;;
|
OpenBSD) l="$(ps -aj |grep "^........ ..... $(printf %5u $1)" |awk '{print($2);}')" ;;
|
||||||
|
@ -5593,7 +5594,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=OUTBOUNDIN
|
NAME=OUTBOUNDIN
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%openssl%*|*%proxy%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%openssl%*|*%proxy%*|*%fork%*|*%$NAME%*)
|
||||||
TEST="$NAME: gender changer via SSL through HTTP proxy, oneshot"
|
TEST="$NAME: gender changer via SSL through HTTP proxy, oneshot"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif ! feat=$(testfeats openssl proxy); then
|
elif ! feat=$(testfeats openssl proxy); then
|
||||||
|
@ -5684,7 +5685,7 @@ N=$((N+1))
|
||||||
#!
|
#!
|
||||||
NAME=INTRANETRIPPER
|
NAME=INTRANETRIPPER
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%openssl%*|*%proxy%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%openssl%*|*%proxy%*|*%fork%*|*%$NAME%*)
|
||||||
TEST="$NAME: gender changer via SSL through HTTP proxy, daemons"
|
TEST="$NAME: gender changer via SSL through HTTP proxy, daemons"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif ! feat=$(testfeats openssl proxy); then
|
elif ! feat=$(testfeats openssl proxy); then
|
||||||
|
@ -5966,7 +5967,7 @@ testserversec () {
|
||||||
|
|
||||||
NAME=TCP4RANGEBITS
|
NAME=TCP4RANGEBITS
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%fork%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of TCP4-L with RANGE option"
|
TEST="$NAME: security of TCP4-L with RANGE option"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif [ -z "$SECONDADDR" ]; then
|
elif [ -z "$SECONDADDR" ]; then
|
||||||
|
@ -5983,7 +5984,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=TCP4RANGEMASK
|
NAME=TCP4RANGEMASK
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%fork%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of TCP4-L with RANGE option"
|
TEST="$NAME: security of TCP4-L with RANGE option"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif [ -z "$SECONDADDR" ]; then
|
elif [ -z "$SECONDADDR" ]; then
|
||||||
|
@ -6001,7 +6002,7 @@ N=$((N+1))
|
||||||
# like TCP4RANGEMASK, but the "bad" address is within the same class A network
|
# like TCP4RANGEMASK, but the "bad" address is within the same class A network
|
||||||
NAME=TCP4RANGEMASKHAIRY
|
NAME=TCP4RANGEMASKHAIRY
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%fork%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of TCP4-L with RANGE option"
|
TEST="$NAME: security of TCP4-L with RANGE option"
|
||||||
if ! eval $NUMCOND; then :; else
|
if ! eval $NUMCOND; then :; else
|
||||||
newport tcp4 # provide free port number in $PORT
|
newport tcp4 # provide free port number in $PORT
|
||||||
|
@ -6013,7 +6014,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=TCP4SOURCEPORT
|
NAME=TCP4SOURCEPORT
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%sourceport%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%fork%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%sourceport%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of TCP4-L with SOURCEPORT option"
|
TEST="$NAME: security of TCP4-L with SOURCEPORT option"
|
||||||
if ! eval $NUMCOND; then :; else
|
if ! eval $NUMCOND; then :; else
|
||||||
newport tcp4 # provide free port number in $PORT
|
newport tcp4 # provide free port number in $PORT
|
||||||
|
@ -6024,7 +6025,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=TCP4LOWPORT
|
NAME=TCP4LOWPORT
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%lowport%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%fork%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%lowport%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of TCP4-L with LOWPORT option"
|
TEST="$NAME: security of TCP4-L with LOWPORT option"
|
||||||
if ! eval $NUMCOND; then :; else
|
if ! eval $NUMCOND; then :; else
|
||||||
newport tcp4 # provide free port number in $PORT
|
newport tcp4 # provide free port number in $PORT
|
||||||
|
@ -6035,7 +6036,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=TCP4WRAPPERS_ADDR
|
NAME=TCP4WRAPPERS_ADDR
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%tcpwrap%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%fork%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%tcpwrap%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of TCP4-L with TCPWRAP option"
|
TEST="$NAME: security of TCP4-L with TCPWRAP option"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif ! feat=$(testfeats tcp ip4 libwrap) || ! runsip4 >/dev/null; then
|
elif ! feat=$(testfeats tcp ip4 libwrap) || ! runsip4 >/dev/null; then
|
||||||
|
@ -6055,7 +6056,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=TCP4WRAPPERS_NAME
|
NAME=TCP4WRAPPERS_NAME
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%tcpwrap%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%fork%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%tcpwrap%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of TCP4-L with TCPWRAP option"
|
TEST="$NAME: security of TCP4-L with TCPWRAP option"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif ! feat=$(testfeats tcp ip4 libwrap) || ! runsip4 >/dev/null; then
|
elif ! feat=$(testfeats tcp ip4 libwrap) || ! runsip4 >/dev/null; then
|
||||||
|
@ -6076,7 +6077,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=TCP6RANGE
|
NAME=TCP6RANGE
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%range%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%fork%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%range%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of TCP6-L with RANGE option"
|
TEST="$NAME: security of TCP6-L with RANGE option"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then
|
elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then
|
||||||
|
@ -6092,7 +6093,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=TCP6SOURCEPORT
|
NAME=TCP6SOURCEPORT
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%sourceport%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%fork%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%sourceport%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of TCP6-L with SOURCEPORT option"
|
TEST="$NAME: security of TCP6-L with SOURCEPORT option"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then
|
elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then
|
||||||
|
@ -6108,7 +6109,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=TCP6LOWPORT
|
NAME=TCP6LOWPORT
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%lowport%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%fork%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%lowport%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of TCP6-L with LOWPORT option"
|
TEST="$NAME: security of TCP6-L with LOWPORT option"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then
|
elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then
|
||||||
|
@ -6124,7 +6125,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=TCP6TCPWRAP
|
NAME=TCP6TCPWRAP
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%tcpwrap%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%fork%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%tcpwrap%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of TCP6-L with TCPWRAP option"
|
TEST="$NAME: security of TCP6-L with TCPWRAP option"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif ! feat=$(testfeats tcp ip6 libwrap && runstcp6); then
|
elif ! feat=$(testfeats tcp ip6 libwrap && runstcp6); then
|
||||||
|
@ -6145,7 +6146,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=UDP4RANGE
|
NAME=UDP4RANGE
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%range%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%security%*|*%fork%*|*%udp%*|*%udp4%*|*%ip4%*|*%range%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of UDP4-L with RANGE option"
|
TEST="$NAME: security of UDP4-L with RANGE option"
|
||||||
if ! eval $NUMCOND; then :; else
|
if ! eval $NUMCOND; then :; else
|
||||||
newport udp4 # provide free port number in $PORT
|
newport udp4 # provide free port number in $PORT
|
||||||
|
@ -6200,7 +6201,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=UDP6RANGE
|
NAME=UDP6RANGE
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp6%*|*%ip6%*|*%range%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%security%*|*%fork%*|*%udp%*|*%udp6%*|*%ip6%*|*%range%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of UDP6-L with RANGE option"
|
TEST="$NAME: security of UDP6-L with RANGE option"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then
|
elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then
|
||||||
|
@ -6269,7 +6270,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=OPENSSLTCP4_RANGE
|
NAME=OPENSSLTCP4_RANGE
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%range%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%security%*|*%fork%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%range%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of SSL-L over TCP/IPv4 with RANGE option"
|
TEST="$NAME: security of SSL-L over TCP/IPv4 with RANGE option"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif ! testfeats openssl >/dev/null; then
|
elif ! testfeats openssl >/dev/null; then
|
||||||
|
@ -6286,7 +6287,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=OPENSSLTCP4_SOURCEPORT
|
NAME=OPENSSLTCP4_SOURCEPORT
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%sourceport%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%security%*|*%fork%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%sourceport%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of SSL-L with SOURCEPORT option"
|
TEST="$NAME: security of SSL-L with SOURCEPORT option"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif ! testfeats openssl >/dev/null; then
|
elif ! testfeats openssl >/dev/null; then
|
||||||
|
@ -6303,7 +6304,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=OPENSSLTCP4_LOWPORT
|
NAME=OPENSSLTCP4_LOWPORT
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%lowport%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%security%*|*%fork%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%lowport%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of SSL-L with LOWPORT option"
|
TEST="$NAME: security of SSL-L with LOWPORT option"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif ! testfeats openssl >/dev/null; then
|
elif ! testfeats openssl >/dev/null; then
|
||||||
|
@ -6320,7 +6321,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=OPENSSLTCP4_TCPWRAP
|
NAME=OPENSSLTCP4_TCPWRAP
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%tcpwrap%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%security%*|*%fork%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%tcpwrap%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of SSL-L with TCPWRAP option"
|
TEST="$NAME: security of SSL-L with TCPWRAP option"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif ! feat=$(testfeats ip4 tcp libwrap openssl); then
|
elif ! feat=$(testfeats ip4 tcp libwrap openssl); then
|
||||||
|
@ -6341,7 +6342,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=OPENSSLCERTSERVER
|
NAME=OPENSSLCERTSERVER
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%security%*|*%fork%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of SSL-L with client certificate"
|
TEST="$NAME: security of SSL-L with client certificate"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif ! testfeats openssl >/dev/null; then
|
elif ! testfeats openssl >/dev/null; then
|
||||||
|
@ -6359,7 +6360,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=OPENSSLCERTCLIENT
|
NAME=OPENSSLCERTCLIENT
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%security%*|*%fork%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of SSL with server certificate"
|
TEST="$NAME: security of SSL with server certificate"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif ! testfeats openssl >/dev/null; then
|
elif ! testfeats openssl >/dev/null; then
|
||||||
|
@ -6378,7 +6379,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=OPENSSLTCP6_RANGE
|
NAME=OPENSSLTCP6_RANGE
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%range%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%security%*|*%fork%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%range%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of SSL-L over TCP/IPv6 with RANGE option"
|
TEST="$NAME: security of SSL-L over TCP/IPv6 with RANGE option"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif ! testfeats openssl >/dev/null; then
|
elif ! testfeats openssl >/dev/null; then
|
||||||
|
@ -6399,7 +6400,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=OPENSSLTCP6_SOURCEPORT
|
NAME=OPENSSLTCP6_SOURCEPORT
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%sourceport%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%security%*|*%fork%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%sourceport%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of SSL-L over TCP/IPv6 with SOURCEPORT option"
|
TEST="$NAME: security of SSL-L over TCP/IPv6 with SOURCEPORT option"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif ! testfeats openssl >/dev/null; then
|
elif ! testfeats openssl >/dev/null; then
|
||||||
|
@ -6420,7 +6421,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=OPENSSLTCP6_LOWPORT
|
NAME=OPENSSLTCP6_LOWPORT
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%lowport%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%security%*|*%fork%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%lowport%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of SSL-L over TCP/IPv6 with LOWPORT option"
|
TEST="$NAME: security of SSL-L over TCP/IPv6 with LOWPORT option"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif ! testfeats openssl >/dev/null; then
|
elif ! testfeats openssl >/dev/null; then
|
||||||
|
@ -6441,7 +6442,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=OPENSSLTCP6_TCPWRAP
|
NAME=OPENSSLTCP6_TCPWRAP
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%tcpwrap%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%security%*|*%fork%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%tcpwrap%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of SSL-L over TCP/IPv6 with TCPWRAP option"
|
TEST="$NAME: security of SSL-L over TCP/IPv6 with TCPWRAP option"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif ! feat=$(testfeats ip6 tcp libwrap openssl && runsip6); then
|
elif ! feat=$(testfeats ip6 tcp libwrap openssl && runsip6); then
|
||||||
|
@ -6464,7 +6465,7 @@ N=$((N+1))
|
||||||
# test security with the openssl-commonname option on client side
|
# test security with the openssl-commonname option on client side
|
||||||
NAME=OPENSSL_CN_CLIENT_SECURITY
|
NAME=OPENSSL_CN_CLIENT_SECURITY
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%openssl%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%security%*|*%fork%*|*%openssl%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of client openssl-commonname option"
|
TEST="$NAME: security of client openssl-commonname option"
|
||||||
# connect using non matching server name/address with commonname
|
# connect using non matching server name/address with commonname
|
||||||
# options, this should succeed. Then without this option, should fail
|
# options, this should succeed. Then without this option, should fail
|
||||||
|
@ -6515,7 +6516,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=OPENSSL_FIPS_SECURITY
|
NAME=OPENSSL_FIPS_SECURITY
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%openssl%*|*%fips%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%security%*|*%fork%*|*%openssl%*|*%fips%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*)
|
||||||
TEST="$NAME: OpenSSL restrictions by FIPS"
|
TEST="$NAME: OpenSSL restrictions by FIPS"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif ! testfeats openssl >/dev/null; then
|
elif ! testfeats openssl >/dev/null; then
|
||||||
|
@ -7108,7 +7109,12 @@ kill $pid0 2>/dev/null
|
||||||
wait
|
wait
|
||||||
if ! diff "$tref" "$tf" >"$tdiff"; then
|
if ! diff "$tref" "$tf" >"$tdiff"; then
|
||||||
$PRINTF "$FAILED\n"
|
$PRINTF "$FAILED\n"
|
||||||
cat "${te}0" "${te}1" "${te}2"
|
echo "$CMD0 &"
|
||||||
|
cat "${te}0" >&2
|
||||||
|
echo "$CMD1"
|
||||||
|
cat "${te}1" >&2
|
||||||
|
echo "$CMD2"
|
||||||
|
cat "${te}2" >&2
|
||||||
cat "$tdiff"
|
cat "$tdiff"
|
||||||
numFAIL=$((numFAIL+1))
|
numFAIL=$((numFAIL+1))
|
||||||
listFAIL="$listFAIL $N"
|
listFAIL="$listFAIL $N"
|
||||||
|
@ -7908,7 +7914,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=UDP4RECVFROM_RANGE
|
NAME=UDP4RECVFROM_RANGE
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%range%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%security%*|*%fork%*|*%udp%*|*%udp4%*|*%ip4%*|*%range%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of UDP4-RECVFROM with RANGE option"
|
TEST="$NAME: security of UDP4-RECVFROM with RANGE option"
|
||||||
newport udp4 # provide free port number in $PORT
|
newport udp4 # provide free port number in $PORT
|
||||||
#testserversec "$N" "$TEST" "$opts" "UDP4-RECVFROM:$PORT,reuseaddr,fork" "" "range=$SECONDADDR/32" "UDP4-SENDTO:127.0.0.1:$PORT" 4 udp $PORT 0
|
#testserversec "$N" "$TEST" "$opts" "UDP4-RECVFROM:$PORT,reuseaddr,fork" "" "range=$SECONDADDR/32" "UDP4-SENDTO:127.0.0.1:$PORT" 4 udp $PORT 0
|
||||||
|
@ -7920,7 +7926,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=UDP4RECVFROM_TCPWRAP
|
NAME=UDP4RECVFROM_TCPWRAP
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%tcpwrap%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%security%*|*%fork%*|*%udp%*|*%udp4%*|*%ip4%*|*%tcpwrap%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of UDP4-RECVFROM with TCPWRAP option"
|
TEST="$NAME: security of UDP4-RECVFROM with TCPWRAP option"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif ! feat=$(testfeats ip4 udp libwrap) || ! runsip4 >/dev/null; then
|
elif ! feat=$(testfeats ip4 udp libwrap) || ! runsip4 >/dev/null; then
|
||||||
|
@ -8056,7 +8062,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=UDP6RECVFROM_RANGE
|
NAME=UDP6RECVFROM_RANGE
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp6%*|*%ip6%*|*%range%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%security%*|*%fork%*|*%udp%*|*%udp6%*|*%ip6%*|*%range%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of UDP6-RECVFROM with RANGE option"
|
TEST="$NAME: security of UDP6-RECVFROM with RANGE option"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then
|
elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then
|
||||||
|
@ -8176,7 +8182,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=IP4RECVFROM_RANGE
|
NAME=IP4RECVFROM_RANGE
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%ip%*|*%ip4%*|*%range%*|*%root%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%security%*|*%fork%*|*%ip%*|*%ip4%*|*%range%*|*%root%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of IP4-RECVFROM with RANGE option"
|
TEST="$NAME: security of IP4-RECVFROM with RANGE option"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif ! feat=$(testfeats ip4 rawip) || ! runsip4 >/dev/null; then
|
elif ! feat=$(testfeats ip4 rawip) || ! runsip4 >/dev/null; then
|
||||||
|
@ -8198,7 +8204,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=IP4RECVFROM_TCPWRAP
|
NAME=IP4RECVFROM_TCPWRAP
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%ip%*|*%ip4%*|*%tcpwrap%*|*%root%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%security%*|*%fork%*|*%ip%*|*%ip4%*|*%tcpwrap%*|*%root%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of IP4-RECVFROM with TCPWRAP option"
|
TEST="$NAME: security of IP4-RECVFROM with TCPWRAP option"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif ! feat=$(testfeats ip4 rawip libwrap) || ! runsip4 >/dev/null; then
|
elif ! feat=$(testfeats ip4 rawip libwrap) || ! runsip4 >/dev/null; then
|
||||||
|
@ -8281,7 +8287,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=IP6RECVFROM_RANGE
|
NAME=IP6RECVFROM_RANGE
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%ip%*|*%ip6%*|*%range%*|*%root%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%security%*|*%fork%*|*%ip%*|*%ip6%*|*%range%*|*%root%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of IP6-RECVFROM with RANGE option"
|
TEST="$NAME: security of IP6-RECVFROM with RANGE option"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif ! feat=$(testfeats ip6 rawip && runsip6); then
|
elif ! feat=$(testfeats ip6 rawip && runsip6); then
|
||||||
|
@ -8303,7 +8309,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=IP6RECVFROM_TCPWRAP
|
NAME=IP6RECVFROM_TCPWRAP
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%ip%*|*%ip6%*|*%tcpwrap%*|*%root%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%security%*|*%fork%*|*%ip%*|*%ip6%*|*%tcpwrap%*|*%root%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of IP6-RECVFROM with TCPWRAP option"
|
TEST="$NAME: security of IP6-RECVFROM with TCPWRAP option"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif ! feat=$(testfeats ip6 rawip libwrap && runsip6); then
|
elif ! feat=$(testfeats ip6 rawip libwrap && runsip6); then
|
||||||
|
@ -8650,48 +8656,69 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=TCP4ENDCLOSE
|
NAME=TCP4ENDCLOSE
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%tcp%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%fork%*|*%ip4%*|*%ipapp%*|*%tcp%*|*%$NAME%*)
|
||||||
TEST="$NAME: end-close keeps TCP V4 socket open"
|
TEST="$NAME: end-close keeps TCP V4 socket open"
|
||||||
if ! eval $NUMCOND; then :; else
|
if ! eval $NUMCOND; then :; else
|
||||||
tf="$td/test$N.stdout"
|
tf="$td/test$N.stdout"
|
||||||
te="$td/test$N.stderr"
|
te="$td/test$N.stderr"
|
||||||
tdiff="$td/test$N.diff"
|
tdiff="$td/test$N.diff"
|
||||||
|
newport tcp4; p0=$PORT
|
||||||
newport tcp4; p1=$PORT
|
newport tcp4; p1=$PORT
|
||||||
newport tcp4; p2=$PORT
|
da2a="$(date) $RANDOM"
|
||||||
da1a="$(date) $RANDOM"
|
da2b="$(date) $RANDOM"
|
||||||
da1b="$(date) $RANDOM"
|
CMD0="$TRACE $SOCAT -lp collector $opts -u TCP4-LISTEN:$p0,$REUSEADDR,bind=$LOCALHOST -"
|
||||||
CMD1="$TRACE $SOCAT $opts -u - TCP4-CONNECT:$LOCALHOST:$p1"
|
CMD1="$TRACE $SOCAT -lp forker $opts -U TCP4:$LOCALHOST:$p0,end-close TCP4-LISTEN:$p1,bind=$LOCALHOST,$REUSEADDR,fork"
|
||||||
CMD="$TRACE $SOCAT $opts -U TCP4:$LOCALHOST:$p2,end-close TCP4-LISTEN:$p1,bind=$LOCALHOST,$REUSEADDR,fork"
|
CMD2="$TRACE $SOCAT -lp client $opts -u - TCP4-CONNECT:$LOCALHOST:$p1"
|
||||||
CMD3="$TRACE $SOCAT $opts -u TCP4-LISTEN:$p2,$REUSEADDR,bind=$LOCALHOST -"
|
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
$CMD3 >"$tf" 2>"${te}3" &
|
$CMD0 >"${tf}0" 2>"${te}0" &
|
||||||
pid3=$!
|
pid0=$!
|
||||||
waittcp4port $p2 1
|
waittcp4port $p0 1
|
||||||
$CMD 2>"${te}2" &
|
$CMD1 2>"${te}1" &
|
||||||
pid2=$!
|
pid1=$!
|
||||||
usleep $MICROS
|
usleep $MICROS
|
||||||
waittcp4port $p1 1
|
waittcp4port $p1 1
|
||||||
echo "$da1a" |$CMD1 2>>"${te}1a"
|
echo "$da2a" |$CMD2 2>>"${te}2a"
|
||||||
echo "$da1b" |$CMD1 2>>"${te}1b"
|
rc2a=$?
|
||||||
|
echo "$da2b" |$CMD2 2>>"${te}2b"
|
||||||
|
rc2b=$?
|
||||||
sleep 1
|
sleep 1
|
||||||
kill "$pid3" "$pid2" 2>/dev/null
|
kill "$pid0" "$pid1" 2>/dev/null
|
||||||
wait
|
wait
|
||||||
if [ $? -ne 0 ]; then
|
if [ $rc2a -ne 0 -o $rc2b -ne 0 ]; then
|
||||||
$PRINTF "$FAILED: $TRACE $SOCAT:\n"
|
$PRINTF "$FAILED: $TRACE $SOCAT:\n"
|
||||||
echo "$CMD1 &"
|
echo "$CMD0 &"
|
||||||
|
cat "${te}0" >&2
|
||||||
|
echo "$CMD1"
|
||||||
|
cat "${te}1" >&2
|
||||||
echo "$CMD2"
|
echo "$CMD2"
|
||||||
cat "${te}1a" "${te}1b" "${te}2" "${te}3"
|
cat "${te}2a" >&2
|
||||||
|
echo "$CMD2"
|
||||||
|
cat "${te}2b" >&2
|
||||||
numFAIL=$((numFAIL+1))
|
numFAIL=$((numFAIL+1))
|
||||||
listFAIL="$listFAIL $N"
|
listFAIL="$listFAIL $N"
|
||||||
elif ! $ECHO "$da1a\n$da1b" |diff - "$tf" >"$tdiff"; then
|
elif ! $ECHO "$da2a\n$da2b" |diff - "${tf}0" >"$tdiff"; then
|
||||||
$PRINTF "$FAILED\n"
|
$PRINTF "$FAILED (diff)\n"
|
||||||
|
echo "$CMD0 &"
|
||||||
|
cat "${te}0" >&2
|
||||||
|
echo "$CMD1"
|
||||||
|
cat "${te}1" >&2
|
||||||
|
echo "$CMD2"
|
||||||
|
cat "${te}2a" >&2
|
||||||
|
echo "$CMD2"
|
||||||
|
cat "${te}2b" >&2
|
||||||
cat "$tdiff"
|
cat "$tdiff"
|
||||||
cat "${te}1a" "${te}1b" "${te}2" "${te}3"
|
|
||||||
numFAIL=$((numFAIL+1))
|
numFAIL=$((numFAIL+1))
|
||||||
listFAIL="$listFAIL $N"
|
listFAIL="$listFAIL $N"
|
||||||
else
|
else
|
||||||
$PRINTF "$OK\n"
|
$PRINTF "$OK\n"
|
||||||
if [ -n "$debug" ]; then cat "${te}1a" "${te}1b" "${te}2" "${te}3"; fi
|
if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}0" >&2; fi
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD1 &"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}1" >&2; fi
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD2"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}2a" >&2; fi
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD2"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}2b" >&2; fi
|
||||||
numOK=$((numOK+1))
|
numOK=$((numOK+1))
|
||||||
fi
|
fi
|
||||||
fi ;; # NUMCOND
|
fi ;; # NUMCOND
|
||||||
|
@ -8701,7 +8728,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=EXECENDCLOSE
|
NAME=EXECENDCLOSE
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%exec%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%fork%*|*%exec%*|*%$NAME%*)
|
||||||
TEST="$NAME: end-close keeps EXEC child running"
|
TEST="$NAME: end-close keeps EXEC child running"
|
||||||
if ! eval $NUMCOND; then :; else
|
if ! eval $NUMCOND; then :; else
|
||||||
tf="$td/test$N.stdout"
|
tf="$td/test$N.stdout"
|
||||||
|
@ -9875,7 +9902,7 @@ N=$((N+1))
|
||||||
# process under some circumstances.
|
# process under some circumstances.
|
||||||
NAME=EXECPTYKILL
|
NAME=EXECPTYKILL
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%bugs%*|*%exec%*|*%pty%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%bugs%*|*%fork%*|*%exec%*|*%pty%*|*%$NAME%*)
|
||||||
TEST="$NAME: exec:...,pty explicitely kills sub process"
|
TEST="$NAME: exec:...,pty explicitely kills sub process"
|
||||||
# we want to check if the exec'd sub process is killed in time
|
# we want to check if the exec'd sub process is killed in time
|
||||||
# for this we have a shell script that generates a file after two seconds;
|
# for this we have a shell script that generates a file after two seconds;
|
||||||
|
@ -10037,7 +10064,7 @@ N=$((N+1))
|
||||||
# zombies because the master process did not catch SIGCHLD
|
# zombies because the master process did not catch SIGCHLD
|
||||||
NAME=UDP4LISTEN_SIGCHLD
|
NAME=UDP4LISTEN_SIGCHLD
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%udp%*|*%zombie%*|*%signal%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%fork%*|*%ip4%*|*%ipapp%*|*%udp%*|*%zombie%*|*%signal%*|*%$NAME%*)
|
||||||
TEST="$NAME: test if UDP4-LISTEN child becomes zombie"
|
TEST="$NAME: test if UDP4-LISTEN child becomes zombie"
|
||||||
# idea: run a udp-listen process with fork and -T. Connect once, so a sub
|
# idea: run a udp-listen process with fork and -T. Connect once, so a sub
|
||||||
# process is forked off. Make some transfer and wait until the -T timeout is
|
# process is forked off. Make some transfer and wait until the -T timeout is
|
||||||
|
@ -10091,7 +10118,7 @@ N=$((N+1))
|
||||||
# zombies because the master process caught SIGCHLD but did not wait()
|
# zombies because the master process caught SIGCHLD but did not wait()
|
||||||
NAME=UDP4RECVFROM_SIGCHLD
|
NAME=UDP4RECVFROM_SIGCHLD
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%ip4%*|*%udp%*|*%dgram%*|*%zombie%*|*%signal%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%bugs%*|*%fork%*|*%ip4%*|*%udp%*|*%dgram%*|*%zombie%*|*%signal%*|*%$NAME%*)
|
||||||
TEST="$NAME: test if UDP4-RECVFROM child becomes zombie"
|
TEST="$NAME: test if UDP4-RECVFROM child becomes zombie"
|
||||||
# idea: run a udp-recvfrom process with fork and -T. Send it one packet, so a
|
# idea: run a udp-recvfrom process with fork and -T. Send it one packet, so a
|
||||||
# sub process is forked off. Make some transfer and wait until the -T timeout
|
# sub process is forked off. Make some transfer and wait until the -T timeout
|
||||||
|
@ -10115,25 +10142,39 @@ rc2=$?
|
||||||
sleep 1
|
sleep 1
|
||||||
#read -p ">"
|
#read -p ">"
|
||||||
l="$(childprocess $pid1)"
|
l="$(childprocess $pid1)"
|
||||||
|
#echo "l=\"$l\""
|
||||||
kill $pid1 2>/dev/null; wait
|
kill $pid1 2>/dev/null; wait
|
||||||
if [ $rc2 -ne 0 ]; then
|
if [ $rc2 -ne 0 ]; then
|
||||||
$PRINTF "$NO_RESULT\n" # already handled in test UDP4DGRAM
|
$PRINTF "$NO_RESULT\n" # already handled in test UDP4DGRAM
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD1 &"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}1" >&2; fi
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD2"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}2" >&2; fi
|
||||||
numCANT=$((numCANT+1))
|
numCANT=$((numCANT+1))
|
||||||
listCANT="$listCANT $N"
|
listCANT="$listCANT $N"
|
||||||
elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
|
elif ! echo "$da" |diff - "$tf" >"$tdiff"; then
|
||||||
$PRINTF "$NO_RESULT\n" # already handled in test UDP4DGRAM
|
$PRINTF "$NO_RESULT\n" # already handled in test UDP4DGRAM
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD1 &"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}1" >&2; fi
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD2"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}2" >&2; fi
|
||||||
numCANT=$((numCANT+1))
|
numCANT=$((numCANT+1))
|
||||||
listCANT="$listCANT $N"
|
listCANT="$listCANT $N"
|
||||||
elif $(isdefunct "$l"); then
|
elif $(isdefunct "$l"); then
|
||||||
$PRINTF "$FAILED: $TRACE $SOCAT:\n"
|
$PRINTF "$FAILED: $TRACE $SOCAT:\n"
|
||||||
echo "$CMD1 &"
|
echo "$CMD1 &"
|
||||||
|
cat "${te}1" >&2
|
||||||
echo "$CMD2"
|
echo "$CMD2"
|
||||||
|
cat "${te}2" >&2
|
||||||
cat "${te}1" "${te}2"
|
cat "${te}1" "${te}2"
|
||||||
numFAIL=$((numFAIL+1))
|
numFAIL=$((numFAIL+1))
|
||||||
listFAIL="$listFAIL $N"
|
listFAIL="$listFAIL $N"
|
||||||
else
|
else
|
||||||
$PRINTF "$OK\n"
|
$PRINTF "$OK\n"
|
||||||
if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi
|
if [ "$VERBOSE" ]; then echo "$CMD1 &"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}1" >&2; fi
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD2"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}2" >&2; fi
|
||||||
numOK=$((numOK+1))
|
numOK=$((numOK+1))
|
||||||
fi
|
fi
|
||||||
fi ;; # NUMCOND
|
fi ;; # NUMCOND
|
||||||
|
@ -10204,7 +10245,7 @@ N=$((N+1))
|
||||||
# child process.
|
# child process.
|
||||||
NAME=UDP4RECVFROM_FORK
|
NAME=UDP4RECVFROM_FORK
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%ip4%*|*%udp%*|*%dgram%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%fork%*|*%ip4%*|*%udp%*|*%dgram%*|*%$NAME%*)
|
||||||
TEST="$NAME: test if UDP4-RECVFROM handles more than one packet"
|
TEST="$NAME: test if UDP4-RECVFROM handles more than one packet"
|
||||||
# idea: run a UDP4-RECVFROM process with fork and -T. Send it one packet;
|
# idea: run a UDP4-RECVFROM process with fork and -T. Send it one packet;
|
||||||
# send it a second packet and check if this is processed properly. If yes, the
|
# send it a second packet and check if this is processed properly. If yes, the
|
||||||
|
@ -11293,7 +11334,7 @@ N=$((N+1))
|
||||||
|
|
||||||
NAME=SOCKETRANGEMASK
|
NAME=SOCKETRANGEMASK
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%security%*|*%generic%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%socket%*|*%range%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%security%*|*%fork%*|*%generic%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%socket%*|*%range%*|*%$NAME%*)
|
||||||
TEST="$NAME: security of generic socket-listen with RANGE option"
|
TEST="$NAME: security of generic socket-listen with RANGE option"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif [ -z "$SECONDADDR" ]; then
|
elif [ -z "$SECONDADDR" ]; then
|
||||||
|
@ -11374,7 +11415,7 @@ N=$((N+1))
|
||||||
# Test the generic setsockopt option
|
# Test the generic setsockopt option
|
||||||
NAME=SETSOCKOPT
|
NAME=SETSOCKOPT
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%ip4%*|*%tcp%*|*%generic%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%fork%*|*%ip4%*|*%tcp%*|*%generic%*|*%$NAME%*)
|
||||||
TEST="$NAME: test the setsockopt option"
|
TEST="$NAME: test the setsockopt option"
|
||||||
# Set the TCP_MAXSEG (MSS) option with a reasonable value, this should succeed.
|
# Set the TCP_MAXSEG (MSS) option with a reasonable value, this should succeed.
|
||||||
# The try again with TCP_MAXSEG=1, this fails at least on Linux.
|
# The try again with TCP_MAXSEG=1, this fails at least on Linux.
|
||||||
|
@ -12104,7 +12145,7 @@ feat="$(tolower "$FEAT")"
|
||||||
# test the max-children option on really connection oriented sockets
|
# test the max-children option on really connection oriented sockets
|
||||||
NAME=${KEYW}MAXCHILDREN
|
NAME=${KEYW}MAXCHILDREN
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%maxchildren%*|*%$feat%*|*%$proto%*|*%socket%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%fork%*|*%maxchildren%*|*%$feat%*|*%$proto%*|*%socket%*|*%$NAME%*)
|
||||||
TEST="$NAME: max-children option"
|
TEST="$NAME: max-children option"
|
||||||
# start a listen process with max-children=1; connect with a client, let it
|
# start a listen process with max-children=1; connect with a client, let it
|
||||||
# sleep some time before sending data; connect with second client that sends
|
# sleep some time before sending data; connect with second client that sends
|
||||||
|
@ -12189,7 +12230,7 @@ proto="$(echo "$PROTO" |tr A-Z a-z)"
|
||||||
# test the max-children option on pseudo connected sockets
|
# test the max-children option on pseudo connected sockets
|
||||||
NAME=${KEYW}MAXCHILDREN
|
NAME=${KEYW}MAXCHILDREN
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%maxchildren%*|*%socket%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%fork%*|*%maxchildren%*|*%socket%*|*%$NAME%*)
|
||||||
TEST="$NAME: max-children option"
|
TEST="$NAME: max-children option"
|
||||||
# start a listen process with max-children=1; connect with a client, let it
|
# start a listen process with max-children=1; connect with a client, let it
|
||||||
# send data and then sleep; connect with second client that wants to send
|
# send data and then sleep; connect with second client that wants to send
|
||||||
|
@ -12550,7 +12591,7 @@ N=$((N+1))
|
||||||
# had a bug that converted a bit mask of 0 internally to 0xffffffff
|
# had a bug that converted a bit mask of 0 internally to 0xffffffff
|
||||||
NAME=TCP4RANGE_0BITS
|
NAME=TCP4RANGE_0BITS
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%fork%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%$NAME%*)
|
||||||
TEST="$NAME: correct evaluation of range mask 0"
|
TEST="$NAME: correct evaluation of range mask 0"
|
||||||
if ! eval $NUMCOND; then :;
|
if ! eval $NUMCOND; then :;
|
||||||
elif [ -z "$SECONDADDR" ]; then
|
elif [ -z "$SECONDADDR" ]; then
|
||||||
|
@ -12999,7 +13040,7 @@ if [ "$addropts" = "." ]; then addropts=; fi
|
||||||
# $ADDR with fork removes the file system entry when the process is terminated
|
# $ADDR with fork removes the file system entry when the process is terminated
|
||||||
NAME=${ADDR_}_REMOVE_FORK
|
NAME=${ADDR_}_REMOVE_FORK
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%$N%*|*%functions%*|*%bugs%*|*%unix%*|*%socket%*|*%$NAME%*)
|
*%$N%*|*%functions%*|*%bugs%*|*%fork%*|*%unix%*|*%socket%*|*%$NAME%*)
|
||||||
TEST="$NAME: $ADDR with fork removes socket entry when terminated during accept"
|
TEST="$NAME: $ADDR with fork removes socket entry when terminated during accept"
|
||||||
# start a socat process with listening unix domain socket etc and option fork.
|
# start a socat process with listening unix domain socket etc and option fork.
|
||||||
# Terminate the process and check if the file system socket entry still exists.
|
# Terminate the process and check if the file system socket entry still exists.
|
||||||
|
@ -16069,6 +16110,101 @@ PORT=$((PORT+1))
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
|
||||||
|
while read KEYW FEAT RUNS ADDR IPPORT; do
|
||||||
|
if [ -z "$KEYW" ] || [[ "$KEYW" == \#* ]]; then continue; fi
|
||||||
|
RUNS=$(tolower $KEYW)
|
||||||
|
PROTO=$KEYW
|
||||||
|
proto="$(echo "$PROTO" |tr A-Z a-z)"
|
||||||
|
feat="$(tolower "$FEAT")"
|
||||||
|
# test the fork option on really RECVFROM oriented sockets
|
||||||
|
NAME=${KEYW}_FORK
|
||||||
|
case "$TESTS" in
|
||||||
|
*%$N%*|*%functions%*|*%fork%*|*%$feat%*|*%$proto%*|*%socket%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: ${KEYW}-RECVFROM with fork option"
|
||||||
|
# Start a RECVFROM process with fork option and SYSTEM address where clients
|
||||||
|
# data determines the sleep time; send a record with sleep before storing the
|
||||||
|
# data, then send a record with 0 sleep before storing data.
|
||||||
|
# When the second record is stored before the first one the test succeeded.
|
||||||
|
if ! eval $NUMCOND; then :;
|
||||||
|
elif ! F=$(testfeats $FEAT STDIO SYSTEM); then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}Feature $F not available${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
elif ! A=$(testaddrs - STDIO SYSTEM $PROTO-RECVFROM $PROTO-SENDTO); then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}Address $A not available${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
elif ! o=$(testoptions fork ) >/dev/null; then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}Option $o not available${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
elif ! runs$RUNS >/dev/null; then
|
||||||
|
$PRINTF "test $F_n $TEST... ${YELLOW}$(toupper $RUNS) not available${NORMAL}\n" $N
|
||||||
|
numCANT=$((numCANT+1))
|
||||||
|
listCANT="$listCANT $N"
|
||||||
|
else
|
||||||
|
case "X$IPPORT" in
|
||||||
|
"XPORT")
|
||||||
|
newport $proto
|
||||||
|
tsl=$PORT # test socket listen address
|
||||||
|
tsc="$ADDR:$PORT" # test socket connect address
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
tsl="$(eval echo "$ADDR")" # resolve $N
|
||||||
|
tsc=$tsl
|
||||||
|
esac
|
||||||
|
#ts="$td/test$N.sock"
|
||||||
|
tf="$td/test$N.stdout"
|
||||||
|
te="$td/test$N.stderr"
|
||||||
|
tdiff="$td/test$N.diff"
|
||||||
|
da="test$N $(date) $RANDOM"
|
||||||
|
CMD0="$TRACE $SOCAT $opts -t 3 $PROTO-RECVFROM:$tsl,fork SYSTEM:'read t x; sleep \$t; echo \$x >>'\"$tf\""
|
||||||
|
CMD1="$TRACE $SOCAT $opts -t 3 - $PROTO-SENDTO:$tsc"
|
||||||
|
printf "test $F_n $TEST... " $N
|
||||||
|
eval $CMD0 </dev/null 2>"${te}0" &
|
||||||
|
pid0=$!
|
||||||
|
wait${proto}port $tsl 1
|
||||||
|
echo "2 $da 1" |$CMD1 >"${tf}1" 2>"${te}1" &
|
||||||
|
pid1=$!
|
||||||
|
sleep 1
|
||||||
|
echo "0 $da 2" |$CMD1 >"${tf}2" 2>"${te}2" &
|
||||||
|
pid2=$!
|
||||||
|
sleep 2
|
||||||
|
cpids="$(childpids $pid0 </dev/null)"
|
||||||
|
kill $pid1 $pid2 $cpids $pid0 2>/dev/null; wait
|
||||||
|
if echo -e "$da 2\n$da 1" |diff - $tf >$tdiff; then
|
||||||
|
$PRINTF "$OK\n"
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD0 &"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}0" >&2; fi
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD1"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}1" >&2; fi
|
||||||
|
if [ "$VERBOSE" ]; then echo "$CMD2"; fi
|
||||||
|
if [ "$DEBUG" ]; then cat "${te}2" >&2; fi
|
||||||
|
numOK=$((numOK+1))
|
||||||
|
else
|
||||||
|
$PRINTF "$FAILED\n"
|
||||||
|
echo "$CMD0 &"
|
||||||
|
cat "${te}0" >&2
|
||||||
|
echo "$CMD1"
|
||||||
|
cat "${te}1" >&2
|
||||||
|
echo "$CMD2"
|
||||||
|
cat "${te}2" >&2
|
||||||
|
echo "diff:" >&2
|
||||||
|
cat "$tdiff" >&2
|
||||||
|
numFAIL=$((numFAIL+1))
|
||||||
|
listFAIL="$listFAIL $N"
|
||||||
|
namesFAIL="$namesFAIL $NAME"
|
||||||
|
fi
|
||||||
|
fi # NUMCOND
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
N=$((N+1))
|
||||||
|
done <<<"
|
||||||
|
UDP4 UDP udp4 127.0.0.1 PORT
|
||||||
|
UDP6 UDP udp4 [::1] PORT
|
||||||
|
UNIX unix unix $td/test\$N.server -
|
||||||
|
"
|
||||||
|
|
||||||
# end of common tests
|
# end of common tests
|
||||||
|
|
||||||
##################################################################################
|
##################################################################################
|
||||||
|
|
|
@ -338,11 +338,7 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
|
||||||
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;
|
||||||
|
|
||||||
/* we must prevent that the current packet triggers another fork;
|
/* Block SIGCHLD until parent is ready to react */
|
||||||
therefore we wait for a signal from the recent child: USR1
|
|
||||||
indicates that is has consumed the last packet; CHLD means it has
|
|
||||||
terminated */
|
|
||||||
/* block SIGCHLD and SIGUSR1 until parent is ready to react */
|
|
||||||
sigemptyset(&mask_sigchld);
|
sigemptyset(&mask_sigchld);
|
||||||
sigaddset(&mask_sigchld, SIGCHLD);
|
sigaddset(&mask_sigchld, SIGCHLD);
|
||||||
Sigprocmask(SIG_BLOCK, &mask_sigchld, NULL);
|
Sigprocmask(SIG_BLOCK, &mask_sigchld, NULL);
|
||||||
|
@ -383,6 +379,7 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
|
||||||
/* now we are ready to handle signals */
|
/* now we are ready to handle signals */
|
||||||
Sigprocmask(SIG_UNBLOCK, &mask_sigchld, NULL);
|
Sigprocmask(SIG_UNBLOCK, &mask_sigchld, NULL);
|
||||||
|
|
||||||
|
|
||||||
while (maxchildren) {
|
while (maxchildren) {
|
||||||
if (num_child < maxchildren) break;
|
if (num_child < maxchildren) break;
|
||||||
Notice("maxchildren are active, waiting");
|
Notice("maxchildren are active, waiting");
|
||||||
|
|
|
@ -545,7 +545,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
||||||
applyopts(fdi, *copts, PH_LATE2);
|
applyopts(fdi, *copts, PH_LATE2);
|
||||||
}
|
}
|
||||||
if (withfork) {
|
if (withfork) {
|
||||||
Info("Signalling parent ready");
|
Info("notifying parent that child process is ready");
|
||||||
Close(trigger[1]); /* in child, notify parent that ready */
|
Close(trigger[1]); /* in child, notify parent that ready */
|
||||||
}
|
}
|
||||||
} /* withfork */
|
} /* withfork */
|
||||||
|
@ -603,7 +603,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
||||||
fds[0].fd = trigger[0];
|
fds[0].fd = trigger[0];
|
||||||
fds[0].events = POLLIN|POLLHUP;
|
fds[0].events = POLLIN|POLLHUP;
|
||||||
Poll(fds, 1, -1);
|
Poll(fds, 1, -1);
|
||||||
Info("Child process signalled ready");
|
Info("child process notified parent that it is ready");
|
||||||
}
|
}
|
||||||
|
|
||||||
return pid; /* indicate parent (main) process */
|
return pid; /* indicate parent (main) process */
|
||||||
|
|
182
xio-socket.c
182
xio-socket.c
|
@ -1084,101 +1084,13 @@ int _xioopen_dgram_sendto(/* them is already in xfd->peersa */
|
||||||
packet in the IP stacks input queue and forks a sub process. The sub process
|
packet in the IP stacks input queue and forks a sub process. The sub process
|
||||||
then reads this packet for processing its data.
|
then reads this packet for processing its data.
|
||||||
There is a problem because the parent process would find the same packet
|
There is a problem because the parent process would find the same packet
|
||||||
again if it calls select()/poll() before the child process reads the
|
again if it calls select()/poll() before the child process has read the
|
||||||
packet.
|
packet.
|
||||||
To solve this problem we implement the following mechanism:
|
To solve this problem we implement the following mechanism:
|
||||||
The sub process sends a SIGUSR1 when it has read the packet (or a SIGCHLD if
|
Before forking an unnamed pipe (fifo) is created. The sub process closes the
|
||||||
it dies before). The parent process waits until it receives that signal and
|
write side when it has read the packet. The parent process waits until the
|
||||||
only then continues to listen.
|
read side of the pipe gives EOF and only then continues to listen.
|
||||||
To prevent a signal from another process to trigger our loop, we pass the
|
|
||||||
pid of the sub process to the signal handler in xio_waitingfor. The signal
|
|
||||||
handler sets xio_hashappened if the pid matched.
|
|
||||||
*/
|
*/
|
||||||
static pid_t xio_waitingfor; /* info from recv loop to signal handler:
|
|
||||||
indicates the pid of the child process
|
|
||||||
that should send us the USR1 signal */
|
|
||||||
static bool xio_hashappened; /* info from signal handler to loop: child
|
|
||||||
process has read ("consumed") the packet */
|
|
||||||
static int xio_childstatus;
|
|
||||||
|
|
||||||
/* this is the signal handler for USR1 and CHLD */
|
|
||||||
void xiosigaction_hasread(int signum
|
|
||||||
#if HAVE_STRUCT_SIGACTION_SA_SIGACTION && defined(SA_SIGINFO)
|
|
||||||
, siginfo_t *siginfo, void *ucontext
|
|
||||||
#endif
|
|
||||||
) {
|
|
||||||
pid_t pid;
|
|
||||||
int _errno;
|
|
||||||
int status = 0;
|
|
||||||
bool wassig = false;
|
|
||||||
|
|
||||||
_errno = errno;
|
|
||||||
diag_in_handler = 1;
|
|
||||||
#if HAVE_STRUCT_SIGACTION_SA_SIGACTION && defined(SA_SIGINFO)
|
|
||||||
Debug5("xiosigaction_hasread(%d, {%d,%d,%d,"F_pid"}, )",
|
|
||||||
signum, siginfo->si_signo, siginfo->si_errno, siginfo->si_code,
|
|
||||||
siginfo->si_pid);
|
|
||||||
#else
|
|
||||||
Debug1("xiosigaction_hasread(%d)", signum);
|
|
||||||
#endif
|
|
||||||
if (signum == SIGCHLD) {
|
|
||||||
do {
|
|
||||||
pid = Waitpid(-1, &status, WNOHANG);
|
|
||||||
if (pid == 0) {
|
|
||||||
Msg(wassig?E_INFO:E_WARN,
|
|
||||||
"waitpid(-1, {}, WNOHANG): no child has exited");
|
|
||||||
Info("xiosigaction_hasread() finished");
|
|
||||||
Debug("xiosigaction_hasread() ->");
|
|
||||||
diag_in_handler = 0;
|
|
||||||
errno = _errno;
|
|
||||||
return;
|
|
||||||
} else if (pid < 0 && errno == EINTR) {
|
|
||||||
Info1("xiosigaction_hasread(): %s", strerror(errno));
|
|
||||||
} else if (pid < 0 && errno == ECHILD) {
|
|
||||||
Msg(wassig?E_INFO:E_NOTICE,
|
|
||||||
"waitpid(-1, {}, WNOHANG): "F_strerror);
|
|
||||||
Info("xiosigaction_hasread() finished");
|
|
||||||
Debug("xiosigaction_hasread() ->");
|
|
||||||
diag_in_handler = 0;
|
|
||||||
errno = _errno;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
wassig = true;
|
|
||||||
if (pid < 0) {
|
|
||||||
Warn1("waitpid(-1, {%d}, WNOHANG): "F_strerror, status);
|
|
||||||
Info("xiosigaction_hasread() finished");
|
|
||||||
Debug("xiosigaction_hasread() ->");
|
|
||||||
diag_in_handler = 0;
|
|
||||||
errno = _errno;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (pid == xio_waitingfor) {
|
|
||||||
xio_waitingfor = 0; /* so this child will not set hashappened again */
|
|
||||||
xio_hashappened = true;
|
|
||||||
xio_childstatus = WEXITSTATUS(status);
|
|
||||||
Debug("xiosigaction_hasread() ->");
|
|
||||||
diag_in_handler = 0;
|
|
||||||
errno = _errno;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} while (1);
|
|
||||||
}
|
|
||||||
#if HAVE_STRUCT_SIGACTION_SA_SIGACTION && defined(SA_SIGINFO)
|
|
||||||
if (xio_waitingfor == siginfo->si_pid) {
|
|
||||||
xio_hashappened = true;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
xio_hashappened = true;
|
|
||||||
#endif
|
|
||||||
#if !HAVE_SIGACTION
|
|
||||||
Signal(sig, xiosigaction_hasread);
|
|
||||||
#endif /* !HAVE_SIGACTION */
|
|
||||||
Debug("xiosigaction_hasread() ->");
|
|
||||||
diag_in_handler = 0;
|
|
||||||
errno = _errno;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* waits for incoming packet, checks its source address and port. Depending
|
/* waits for incoming packet, checks its source address and port. Depending
|
||||||
on fork option, it may fork a subprocess.
|
on fork option, it may fork a subprocess.
|
||||||
|
@ -1267,42 +1179,7 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dofork) {
|
if (dofork) {
|
||||||
#if HAVE_SIGACTION
|
xiosetchilddied();
|
||||||
{
|
|
||||||
struct sigaction act;
|
|
||||||
memset(&act, 0, sizeof(struct sigaction));
|
|
||||||
act.sa_flags = SA_NOCLDSTOP/*|SA_RESTART*/
|
|
||||||
#ifdef SA_SIGINFO /* not on Linux 2.0(.33) */
|
|
||||||
|SA_SIGINFO
|
|
||||||
#endif
|
|
||||||
#ifdef SA_NOMASK
|
|
||||||
|SA_NOMASK
|
|
||||||
#endif
|
|
||||||
;
|
|
||||||
#if HAVE_STRUCT_SIGACTION_SA_SIGACTION && defined(SA_SIGINFO)
|
|
||||||
act.sa_sigaction = xiosigaction_hasread;
|
|
||||||
#else /* Linux 2.0(.33) does not have sigaction.sa_sigaction */
|
|
||||||
act.sa_handler = xiosigaction_hasread;
|
|
||||||
#endif
|
|
||||||
sigfillset(&act.sa_mask);
|
|
||||||
if (Sigaction(SIGUSR1, &act, NULL) < 0) {
|
|
||||||
/*! Linux man does not explicitely say that errno is defined */
|
|
||||||
Warn1("sigaction(SIGUSR1, {&xiosigaction_subaddr_ok}, NULL): %s", strerror(errno));
|
|
||||||
}
|
|
||||||
if (Sigaction(SIGCHLD, &act, NULL) < 0) {
|
|
||||||
/*! Linux man does not explicitely say that errno is defined */
|
|
||||||
Warn1("sigaction(SIGCHLD, {&xiosigaction_subaddr_ok}, NULL): %s", strerror(errno));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else /* !HAVE_SIGACTION */
|
|
||||||
/*!!!*/
|
|
||||||
if (Signal(SIGUSR1, xiosigaction_hasread) == SIG_ERR) {
|
|
||||||
Warn1("signal(SIGUSR1, xiosigaction_hasread): %s", strerror(errno));
|
|
||||||
}
|
|
||||||
if (Signal(SIGCHLD, xiosigaction_hasread) == SIG_ERR) {
|
|
||||||
Warn1("signal(SIGCHLD, xiosigaction_hasread): %s", strerror(errno));
|
|
||||||
}
|
|
||||||
#endif /* !HAVE_SIGACTION */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true) { /* but we only loop if fork option is set */
|
while (true) { /* but we only loop if fork option is set */
|
||||||
|
@ -1314,6 +1191,7 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
||||||
socklen_t palen = sizeof(_peername); /* peer address size */
|
socklen_t palen = sizeof(_peername); /* peer address size */
|
||||||
char ctrlbuff[1024]; /* ancillary messages */
|
char ctrlbuff[1024]; /* ancillary messages */
|
||||||
struct msghdr msgh = {0};
|
struct msghdr msgh = {0};
|
||||||
|
int trigger[2]; /* for socketpair that indicates consumption of packet */
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
socket_init(pf, pa);
|
socket_init(pf, pa);
|
||||||
|
@ -1397,29 +1275,22 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
||||||
xfd->salen = palen;
|
xfd->salen = palen;
|
||||||
|
|
||||||
if (dofork) {
|
if (dofork) {
|
||||||
sigset_t oldset, mask_sigchldusr1;
|
Info("Generating socketpair that triggers parent when packet has been consumed");
|
||||||
|
if (Socketpair(PF_UNIX, SOCK_STREAM, 0, trigger) < 0) {
|
||||||
/* we must prevent that the current packet triggers another fork;
|
Error1("socketpair(PF_UNIX, SOCK_STREAM, 0, ...): %s", strerror(errno));
|
||||||
therefore we wait for a signal from the recent child: USR1
|
}
|
||||||
indicates that is has consumed the last packet; CHLD means it has
|
|
||||||
terminated */
|
|
||||||
/* block SIGCHLD and SIGUSR1 until parent is ready to react */
|
|
||||||
Sigprocmask(SIG_BLOCK, NULL, &mask_sigchldusr1);
|
|
||||||
sigaddset(&mask_sigchldusr1, SIGCHLD);
|
|
||||||
sigaddset(&mask_sigchldusr1, SIGUSR1);
|
|
||||||
Sigprocmask(SIG_SETMASK, &mask_sigchldusr1, &oldset);
|
|
||||||
|
|
||||||
if ((pid = xio_fork(false, level)) < 0) {
|
if ((pid = xio_fork(false, level)) < 0) {
|
||||||
|
Close(trigger[0]);
|
||||||
|
Close(trigger[1]);
|
||||||
Close(xfd->fd);
|
Close(xfd->fd);
|
||||||
Sigprocmask(SIG_SETMASK, &oldset, NULL);
|
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pid == 0) { /* child */
|
if (pid == 0) { /* child */
|
||||||
/* no reason to block SIGCHLD in child process */
|
Close(trigger[0]);
|
||||||
Sigprocmask(SIG_SETMASK, &oldset, NULL);
|
xfd->triggerfd = trigger[1];
|
||||||
xfd->ppid = Getppid(); /* send parent a signal when packet has
|
Fcntl_l(xfd->triggerfd, F_SETFD, FD_CLOEXEC);
|
||||||
been consumed */
|
|
||||||
|
|
||||||
#if WITH_RETRY
|
#if WITH_RETRY
|
||||||
/* !? */
|
/* !? */
|
||||||
|
@ -1437,29 +1308,14 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
xio_waitingfor = pid;
|
/* Parent */
|
||||||
|
Close(trigger[1]);
|
||||||
|
|
||||||
do {
|
|
||||||
#if HAVE_PSELECT
|
|
||||||
{
|
{
|
||||||
struct timespec timeout = { LONG_MAX, 0 };
|
char buf[1];
|
||||||
Pselect(0, NULL, NULL, NULL, &timeout, &oldset);
|
while (Read(trigger[0], buf, 1) < 0 && errno == EINTR) ;
|
||||||
Sigprocmask(SIG_SETMASK, &oldset, NULL);
|
|
||||||
}
|
}
|
||||||
#else /* ! HAVE_PSELECT */
|
|
||||||
/* now we are ready to handle signals */
|
|
||||||
Sigprocmask(SIG_SETMASK, &oldset, NULL);
|
|
||||||
Sleep(1); /* any signal speeds up return */
|
|
||||||
#endif /* ! HAVE_PSELECT */
|
|
||||||
} while (!xio_hashappened) ;
|
|
||||||
xio_hashappened = false;
|
|
||||||
|
|
||||||
if (xio_childstatus != 0) {
|
|
||||||
char buff[512];
|
|
||||||
Recv(xfd->fd, buff, sizeof(buff), 0);
|
|
||||||
xio_childstatus = 0;
|
|
||||||
Info("drop data because of child exit failed");
|
|
||||||
}
|
|
||||||
Info("continue listening");
|
Info("continue listening");
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -226,7 +226,9 @@ int _xioopen_ipdgram_listen(struct single *sfd,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* server: continue loop with socket()+recvfrom() */
|
/* server: continue loop with socket()+recvfrom() */
|
||||||
/* when we dont close this we get awkward behaviour on Linux 2.4:
|
/* This avoids the requirement of a sync (trigger) mechanism as with
|
||||||
|
RECVFROM addresses */
|
||||||
|
/* And when we dont close this we got awkward behaviour on Linux 2.4:
|
||||||
recvfrom gives 0 bytes with invalid socket address */
|
recvfrom gives 0 bytes with invalid socket address */
|
||||||
if (Close(sfd->fd) < 0) {
|
if (Close(sfd->fd) < 0) {
|
||||||
Info2("close(%d): %s", sfd->fd, strerror(errno));
|
Info2("close(%d): %s", sfd->fd, strerror(errno));
|
||||||
|
|
6
xio.h
6
xio.h
|
@ -164,6 +164,7 @@ typedef struct single {
|
||||||
size_t actbytes; /* so many bytes still to be read (when readbytes!=0)*/
|
size_t actbytes; /* so many bytes still to be read (when readbytes!=0)*/
|
||||||
xiolock_t lock; /* parameters of lockfile */
|
xiolock_t lock; /* parameters of lockfile */
|
||||||
bool havelock; /* we are happy owner of the above lock */
|
bool havelock; /* we are happy owner of the above lock */
|
||||||
|
int triggerfd; /* close this FD in child process to signal parent */
|
||||||
bool cool_write; /* downlevel EPIPE, ECONNRESET to notice */
|
bool cool_write; /* downlevel EPIPE, ECONNRESET to notice */
|
||||||
/* until here, keep consistent with bipipe.dual ! */
|
/* until here, keep consistent with bipipe.dual ! */
|
||||||
int argc; /* number of fields in argv */
|
int argc; /* number of fields in argv */
|
||||||
|
@ -199,7 +200,6 @@ typedef struct single {
|
||||||
struct termios savetty; /* save orig tty settings for later restore */
|
struct termios savetty; /* save orig tty settings for later restore */
|
||||||
#endif /* WITH_TERMIOS */
|
#endif /* WITH_TERMIOS */
|
||||||
int (*sigchild)(struct single *); /* callback after sigchild */
|
int (*sigchild)(struct single *); /* callback after sigchild */
|
||||||
pid_t ppid; /* parent pid, only if we send it signals */
|
|
||||||
int escape; /* escape character; -1 for no escape */
|
int escape; /* escape character; -1 for no escape */
|
||||||
bool actescape; /* escape character found in input data */
|
bool actescape; /* escape character found in input data */
|
||||||
union {
|
union {
|
||||||
|
@ -312,7 +312,9 @@ typedef union bipipe {
|
||||||
size_t actbytes; /* so many bytes still to be read */
|
size_t actbytes; /* so many bytes still to be read */
|
||||||
xiolock_t lock; /* parameters of lockfile */
|
xiolock_t lock; /* parameters of lockfile */
|
||||||
bool havelock; /* we are happy owner of the above lock */
|
bool havelock; /* we are happy owner of the above lock */
|
||||||
xiosingle_t *stream[2]; /* input stream, output stream */
|
int triggerfd; /* close this FD in child process to notify parent */
|
||||||
|
bool cool_write; /* downlevel EPIPE, ECONNRESET to notice */
|
||||||
|
struct single *stream[2]; /* input stream, output stream */
|
||||||
} dual;
|
} dual;
|
||||||
} xiofile_t;
|
} xiofile_t;
|
||||||
|
|
||||||
|
|
|
@ -217,6 +217,15 @@ pid_t xio_fork(bool subchild, int level) {
|
||||||
if (!subchild) {
|
if (!subchild) {
|
||||||
/* set SOCAT_PID to new value */
|
/* set SOCAT_PID to new value */
|
||||||
xiosetenvulong("PID", pid, 1);
|
xiosetenvulong("PID", pid, 1);
|
||||||
|
} else {
|
||||||
|
/* Make sure the sub process does not hold the trigger pipe open */
|
||||||
|
if (sock1 != NULL) {
|
||||||
|
struct single *sfd;
|
||||||
|
sfd = XIO_RDSTREAM(sock1);
|
||||||
|
if (sfd->triggerfd >= 0) Close(sfd->triggerfd);
|
||||||
|
sfd = XIO_WRSTREAM(sock1);
|
||||||
|
if (sfd->triggerfd >= 0) Close(sfd->triggerfd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* gdb recommends to have env controlled sleep after fork */
|
/* gdb recommends to have env controlled sleep after fork */
|
||||||
if (forkwaitstring = getenv("SOCAT_FORK_WAIT")) {
|
if (forkwaitstring = getenv("SOCAT_FORK_WAIT")) {
|
||||||
|
|
|
@ -363,7 +363,7 @@ static xiofile_t *xioallocfd(void) {
|
||||||
#endif /* WITH_RETRY */
|
#endif /* WITH_RETRY */
|
||||||
/* fd->common.ignoreeof = false; */
|
/* fd->common.ignoreeof = false; */
|
||||||
/* fd->common.eof = 0; */
|
/* fd->common.eof = 0; */
|
||||||
|
fd->stream.triggerfd = -1;
|
||||||
fd->stream.fd = -1;
|
fd->stream.fd = -1;
|
||||||
fd->stream.dtype = XIODATA_STREAM;
|
fd->stream.dtype = XIODATA_STREAM;
|
||||||
#if _WITH_SOCKET
|
#if _WITH_SOCKET
|
||||||
|
|
|
@ -271,8 +271,10 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
|
||||||
#else
|
#else
|
||||||
Shutdown(pipe->fd, SHUT_RD);
|
Shutdown(pipe->fd, SHUT_RD);
|
||||||
#endif
|
#endif
|
||||||
if (pipe->ppid > 0) {
|
if (pipe->triggerfd >= 0) {
|
||||||
Kill(pipe->ppid, SIGUSR1);
|
Info("notifying parent that socket is ready again");
|
||||||
|
Close(pipe->triggerfd);
|
||||||
|
pipe->triggerfd = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -112,7 +112,6 @@ void childdied(int signum) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/*! indent */
|
/*! indent */
|
||||||
if (num_child) num_child--;
|
|
||||||
/* check if it was a registered child process */
|
/* check if it was a registered child process */
|
||||||
i = 0;
|
i = 0;
|
||||||
while (i < XIO_MAXSOCK) {
|
while (i < XIO_MAXSOCK) {
|
||||||
|
@ -121,6 +120,7 @@ void childdied(int signum) {
|
||||||
}
|
}
|
||||||
if (i == XIO_MAXSOCK) {
|
if (i == XIO_MAXSOCK) {
|
||||||
Info2("childdied(%d): cannot identify child %d", signum, pid);
|
Info2("childdied(%d): cannot identify child %d", signum, pid);
|
||||||
|
if (num_child) num_child--;
|
||||||
if (nextunknown == NUMUNKNOWN) {
|
if (nextunknown == NUMUNKNOWN) {
|
||||||
nextunknown = 0;
|
nextunknown = 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue