#! /usr/bin/env bash # source: test.sh # Copyright Gerhard Rieger and contributors (see file CHANGES) # Published under the GNU General Public License V.2, see file COPYING # perform lots of tests on socat # this script uses functions; you need a shell that supports them # you can pass general options to socat: export OPTS="-d -d -d -d -lu" # you can eg strace socat with: export TRACE="strace -v -tt -ff -D -x -s 1024 -o /tmp/$USER/socat.strace" #set -vx val_t=0.1 NUMCOND=true #NUMCOND="test \$N -gt 70" VERBOSE= FOREIGN= while [ "$1" ]; do case "X$1" in X-t?*) val_t="${1#-t}" ;; X-t) shift; val_t="$1" ;; X-v) VERBOSE=1 ;; # show commands X-n?*) NUMCOND="test \$N -eq ${1#-n}" ;; X-n) shift; NUMCOND="test \$N -eq $1" ;; X-N?*) NUMCOND="test \$N -gt ${1#-N}" ;; X-N) shift; NUMCOND="test \$N -ge $1" ;; X-C) rm -f testcert*.conf testcert.dh testcli*.* testsrv*.* ;; X-foreign) FOREIGN=1 ;; # allow access to 3rd party Internet hosts *) break; esac shift done opt_t="-t $val_t" UNAME=`uname` UNAME_R=`uname -r` #MICROS=100000 case "X$val_t" in X*.???????*) S="${val_t%.*}"; uS="${val_t#*.}"; uS="${uS:0:6}" ;; X*.*) S="${val_t%.*}"; uS="${val_t#*.}"; uS="${uS}000000"; uS="${uS:0:6}" ;; X*) S="${val_t}"; uS="000000" ;; esac MICROS=${S}${uS} MICROS=${MICROS##0000}; MICROS=${MICROS##00}; MICROS=${MICROS##0} #echo MICROS=$MICROS >&2 # _MICROS=$((MICROS+999999)); SECONDs="${_MICROS%??????}" [ -z "$SECONDs" ] && SECONDs=0 withroot=0 # perform privileged tests even if not run by root [ -z "$SOCAT" ] && SOCAT="./socat" if ! [ -x "$SOCAT" ] && ! type $SOCAT >/dev/null 2>&1; then echo "$SOCAT does not exist" >&2; exit 1; fi if [ "$SOCAT" = socat ]; then SOCAT=$(type -p socat) || SOCAT=$(which socat) fi #echo $SOCAT if [ -z "$PROCAN" ]; then if test -x ./procan; then PROCAN="./procan"; elif type procan >/dev/null 2>&1; then PROCAN=procan; elif test -x ${SOCAT%/*}/procan; then PROCAN=${SOCAT%/*}/procan; else PROCAN=false; fi; fi if [ -z "$FILAN" ]; then if test -x ./filan; then FILAN="./filan"; elif ! type filan >/dev/null 2>&1; then FILAN=filan; elif test -x ${SOCAT%/*}/filan; then FILAN=${SOCAT%/*}/filan; else FILAN=false; fi; fi #PATH=$PATH:/opt/freeware/bin #PATH=$PATH:/usr/local/ssl/bin PATH=$PATH:/sbin # RHEL6:ip case "$0" in */*) PATH="${0%/*}:$PATH" esac #OPENSSL_RAND="-rand /dev/egd-pool" #SOCAT_EGD="egd=/dev/egd-pool" MISCDELAY=1 opts="$opt_t $OPTS" export SOCAT_OPTS="$opts" #debug="1" debug= TESTS="$*"; export TESTS if ! SOCAT_MAIN_WAIT= $SOCAT -V >/dev/null 2>&1; then echo "Failed to execute $SOCAT, exiting" >&2 exit 1 fi SOCAT_VERSION=$(SOCAT_MAIN_WAIT= $SOCAT -V |head -n 2 |tail -n 1 |sed 's/.* \([0-9][1-9]*\.[0-9][0-9]*\.[0-9][^[:space:]]*\).*/\1/') if [ -z "$SOCAT_VERSION" ]; then echo "Warning: failed to retrieve Socat version" >&2 fi # for some tests we need a network interface if type ip >/dev/null 2>&1; then INTERFACE=$(ip r get 8.8.8.8 |grep ' dev ' |head -n 1 |sed "s/.*dev[[:space:]][[:space:]]*\([^[:space:]][^[:space:]]*\).*/\1/") else case "$UNAME" in Linux) if [ "$IP" ]; then INTERFACE="$($IP route get 8.8.8.8 |grep ' dev ' |sed -e 's/.* dev //' -e 's/ .*//')" else INTERFACE="$(netstat -rn |grep -e "^default" -e "^0\.0\.0\.0" |awk '{print($8);}')" fi ;; FreeBSD) INTERFACE="$(netstat -rn |grep -e "^default" -e "^0\.0\.0\.0" |awk '{print($4);}')" ;; *) INTERFACE="$(netstat -rn |grep -e "^default" -e "^0\.0\.0\.0" |awk '{print($4);}')" ;; esac fi MCINTERFACE=$INTERFACE [ -z "$MCINTERFACE" ] && MCINTERFACE=lo # !!! Linux only - and not always #LOCALHOST=192.168.58.1 LOCALHOST=localhost #LOCALHOST=127.0.0.1 LOCALHOST6="[::1]" #PROTO=$(awk '{print($2);}' /etc/protocols |sort -n |tail -n 1) #PROTO=$(($PROTO+1)) PROTO=$((144+RANDOM/2048)) PORT=12002 SOURCEPORT=2002 REUSEADDR=reuseaddr # use this with LISTEN addresses and bind options # SSL certificate contents TESTCERT_CONF=testcert.conf TESTCERT6_CONF=testcert6.conf TESTALT_CONF=testalt.conf # TESTCERT_COMMONNAME="$LOCALHOST" TESTCERT_COMMONNAME6="$LOCALHOST6" TESTCERT_COUNTRYNAME="XY" TESTCERT_LOCALITYNAME="Lunar Base" TESTCERT_ORGANIZATIONALUNITNAME="socat" TESTCERT_ORGANIZATIONNAME="dest-unreach" TESTCERT_SUBJECT="C = $TESTCERT_COUNTRYNAME, CN = $TESTCERT_COMMONNAME, O = $TESTCERT_ORGANIZATIONNAME, OU = $TESTCERT_ORGANIZATIONALUNITNAME, L = $TESTCERT_LOCALITYNAME" TESTCERT_ISSUER="C = $TESTCERT_COUNTRYNAME, CN = $TESTCERT_COMMONNAME, O = $TESTCERT_ORGANIZATIONNAME, OU = $TESTCERT_ORGANIZATIONALUNITNAME, L = $TESTCERT_LOCALITYNAME" RSABITS=2048 # Ubuntu-20.04 with OpenSSL-1.1.1f does not work with 1024 nor 1536 DSABITS=2048 cat >$TESTCERT_CONF <$TESTCERT6_CONF <$TESTALT_CONF </dev/null 2>&1 || usleep 0 2>&1 |grep -q deprecated; then usleep () { local n="$1" case "$n" in *???????) S="${n%??????}"; uS="${n:${#n}-6}" ;; *) S=0; uS="00000$n"; uS="${uS:${#uS}-6}" ;; esac $SOCAT -T "$S.$uS" pipe pipe } fi #USLEEP=usleep if type ping6 >/dev/null 2>&1; then PING6=ping6 else PING6="ping -6" fi F_n="%3d" # format string for test numbers export LC_ALL=C # for timestamps format... export LANG=C export LANGUAGE=C # knoppix case "$UNAME" in HP-UX|OSF1) echo "$SOCAT -u stdin stdout" >cat.sh chmod a+x cat.sh CAT=./cat.sh ;; SunOS) # /usr/bin/tr doesn't handle the a-z range syntax (needs [a-z]), use # /usr/xpg4/bin/tr instead alias tr=/usr/xpg4/bin/tr ;; *) CAT="cat" ;; esac # some OSes need special options case "$UNAME" in #HP-UX) # # on HP-UX, the default options (below) hang some tests (former 14, 15) # PTYOPTS= # PTYOPTS2= # ;; SunOS) PTYOPTS="echo=0,opost=0,perm=600" PTYOPTS2="cfmakeraw" ;; *) PTYOPTS="echo=0,opost=0" #PTYOPTS2="raw,echo=0" PTYOPTS2="cfmakeraw" #PTYOPTS2="rawer" ;; esac # for some tests we need an unprivileged user id to su to if [ "$SUDO_USER" ]; then SUBSTUSER="$SUDO_USER" else SUBSTUSER="$(grep -v '^[^:]*:^[^:]*:0:' /etc/passwd |tail -n 1 |cut -d: -f1)" fi if type ip >/dev/null 2>&1; then if ip -V |grep -q "^ip utility, iproute2-"; then IP=$(type -p ip) else unset IP fi fi if type ss >/dev/null 2>&1; then if ss -V |grep -q "^ss utility, iproute2-"; then SS=$(type -p ss) else unset SS fi fi if [ -z "$SS" ]; then # non-root users might miss ifconfig in their path case "$UNAME" in AIX) IFCONFIG=/usr/sbin/ifconfig ;; FreeBSD) IFCONFIG=/sbin/ifconfig ;; HP-UX) IFCONFIG=/usr/sbin/ifconfig ;; Linux) IFCONFIG=/sbin/ifconfig ;; NetBSD)IFCONFIG=/sbin/ifconfig ;; OpenBSD)IFCONFIG=/sbin/ifconfig ;; OSF1) IFCONFIG=/sbin/ifconfig ;; SunOS) IFCONFIG=/sbin/ifconfig ;; Darwin)IFCONFIG=/sbin/ifconfig ;; DragonFly) IFCONFIG=/sbin/ifconfig ;; *) IFCONFIG=/sbin/ifconfig ;; esac fi # need output like "644" case "$UNAME" in Linux) fileperms() { stat -L --print "%a\n" "$1" 2>/dev/null; } ;; FreeBSD) fileperms() { stat -L -x "$1" |grep ' Mode:' |sed 's/.* Mode:[[:space:]]*([0-9]\([0-7][0-7][0-7]\).*/\1/'; } ;; *) fileperms() { local p s=0 c p="$(ls -l -L "$1" |awk '{print($1);}')" p="${p:1:9}" while [ "$p" ]; do c=${p:0:1}; p=${p:1}; [ "x$c" == x- ]; let "s=2*s+$?"; done printf "%03o\n" $s; } ;; esac # need user (owner) of filesystem entry case "$UNAME" in Linux) fileuser() { stat -L --print "%U\n" "$1" 2>/dev/null; } ;; FreeBSD) fileuser() { ls -l "$1" |awk '{print($3);}'; } ;; *) fileuser() { ls -l "$1" |awk '{print($3);}'; } ;; esac if2addr4() { local IF="$1" if [ "$IP" ]; then $IP address show dev "$IF" |grep "inet " |sed -e "s/.*inet //" -e "s/ .*//" else $IFCONFIG "$BROADCASTIF" |grep 'inet ' |awk '{print($2);}' |cut -d: -f2 fi } if2bc4() { local IF="$1" if [ "$IP" ]; then $IP address show dev "$IF" |grep ' inet .* brd ' |awk '{print($4);}' else $IFCONFIG "$IF" |grep 'broadcast ' |sed 's/.*broadcast/broadcast/' |awk '{print($2);}' fi } # for some tests we need a second local IPv4 address case "$UNAME" in Linux) if [ "$IP" ]; then BROADCASTIF=$($IP r get 8.8.8.8 |grep ' dev ' |sed 's/.*\&2 exit 1 fi ECHO="echo $E" PRINTF="printf" case "$TERM" in vt100|vt320|linux|xterm|cons25|dtterm|aixterm|sun-color|xterm-color|xterm-256color|screen) # there are different behaviours of printf (and echo) # on some systems, echo behaves different than printf... if [ "$($PRINTF "\0101")" = "A" ]; then RED="\0033[31m" GREEN="\0033[32m" YELLOW="\0033[33m" # if [ "$UNAME" = SunOS ]; then # NORMAL="\0033[30m" # else NORMAL="\0033[39m" # fi else RED="\033[31m" GREEN="\033[32m" YELLOW="\033[33m" # if [ "$UNAME" = SunOS ]; then # NORMAL="\033[30m" # else NORMAL="\033[39m" # fi fi OK="${GREEN}OK${NORMAL}" FAILED="${RED}FAILED${NORMAL}" NO_RESULT="${YELLOW}NO RESULT${NORMAL}" ;; *) OK="OK" FAILED="FAILED" NO_RESULT="NO RESULT" ;; esac if [ -x /usr/xpg4/bin/id ]; then # SunOS has rather useless tools in its default path PATH="/usr/xpg4/bin:$PATH" fi OPENSSL_S_CLIENT_4= OPENSSL_S_CLIENT_DTLS= init_openssl_s_client () { if openssl s_client -help 2>&1 |grep -q ' -4 '; then OPENSSL_S_CLIENT_4="-4" else OPENSSL_S_CLIENT_4=" " fi if openssl s_client -help 2>&1 | grep -q ' -dtls '; then OPENSSL_S_CLIENT_DTLS=-dtls else OPENSSL_S_CLIENT_DTLS=-dtls1 fi } OPENSSL_S_SERVER_4= OPENSSL_S_SERVER_DTLS= OPENSSL_S_SERVER_NO_IGN_EOF= init_openssl_s_server () { if openssl s_server -help 2>&1 |grep -q ' -4 '; then OPENSSL_S_SERVER_4="-4" else OPENSSL_S_SERVER_4=" " fi if openssl s_server -help 2>&1 | grep -q ' -dtls '; then OPENSSL_S_SERVER_DTLS="-dtls" else OPENSSL_S_SERVER_DTLS="-dtls1" fi if openssl s_server -help 2>&1 | grep -q ' -no-ign_eof '; then OPENSSL_S_SERVER_NO_IGN_EOF="-no-ign_eof" else OPENSSL_S_SERVER_NO_IGN_EOF=" " fi } [ -z "$TESTS" ] && TESTS="consistency functions filan" # use '%' as separation char TESTS="%$(echo "$TESTS" |tr ' ' '%')%" [ -z "$USER" ] && USER="$LOGNAME" # HP-UX if [ -z "$TMPDIR" ]; then if [ -z "$TMP" ]; then TMP=/tmp fi TMPDIR="$TMP" fi TD="$TMPDIR/$USER/$$"; td="$TD" rm -rf "$TD" || (echo "cannot rm $TD" >&2; exit 1) mkdir -p "$TD" #trap "rm -r $TD" 0 3 echo "Using temp directory $TD" case "$TESTS" in *%consistency%*) # test if addresses are sorted alphabetically: $ECHO "testing if address array is sorted...\c" TF="$TD/socat-q" IFS="$($ECHO ' \n\t')" $SOCAT -? |sed '1,/address-head:/ d' |egrep 'groups=' |while IFS="$IFS:" read x y; do echo "$x"; done >"$TF" $SOCAT -? |sed '1,/address-head:/ d' |egrep 'groups=' |while IFS="$IFS:" read x y; do echo "$x"; done |LC_ALL=C sort |diff "$TF" - >"$TF-diff" if [ -s "$TF-diff" ]; then $ECHO "\n*** address array is not sorted. Wrong entries:" >&2 cat "$TD/socat-q-diff" >&2 exit 1 else echo " ok" fi #/bin/rm "$TF" #/bin/rm "$TF-diff" esac case "$TESTS" in *%consistency%*) # test if address options array ("optionnames") is sorted alphabetically: $ECHO "testing if address options are sorted...\c" TF="$TD/socat-qq" $SOCAT -??? |sed '1,/opt:/ d' |awk '{print($1);}' >"$TF" LC_ALL=C sort "$TF" |diff "$TF" - >"$TF-diff" if [ -s "$TF-diff" ]; then $ECHO "\n*** option array is not sorted. Wrong entries:" >&2 cat "$TD/socat-qq-diff" >&2 exit 1 else echo " ok" fi /bin/rm "$TF" /bin/rm "$TF-diff" esac #============================================================================== case "$TESTS" in *%options%*) # inquire which options are available OPTS_ANY=$($SOCAT -?? |sed '1,/opt:/ d' |egrep 'groups=([A-Z]+,)*ANY' |awk '{print($1);}' |xargs echo |tr ' ' ',') OPTS_BLK=$($SOCAT -?? |sed '1,/opt:/ d' |egrep 'groups=([A-Z]+,)*BLK' |awk '{print($1);}' |xargs echo |tr ' ' ',') OPTS_CHILD=$($SOCAT -?? |sed '1,/opt:/ d' |egrep 'groups=([A-Z]+,)*CHILD' |awk '{print($1);}' |xargs echo |tr ' ' ',') OPTS_CHR=$($SOCAT -?? |sed '1,/opt:/ d' |egrep 'groups=([A-Z]+,)*CHR' |awk '{print($1);}' |xargs echo |tr ' ' ',') OPTS_DEVICE=$($SOCAT -?? |sed '1,/opt:/ d' |egrep 'groups=([A-Z]+,)*DEVICE' |awk '{print($1);}' |xargs echo |tr ' ' ',') OPTS_EXEC=$($SOCAT -?? |sed '1,/opt:/ d' |egrep 'groups=([A-Z]+,)*EXEC' |awk '{print($1);}' |xargs echo |tr ' ' ',') OPTS_FD=$($SOCAT -?? |sed '1,/opt:/ d' |egrep 'groups=([A-Z]+,)*FD' |awk '{print($1);}' |xargs echo |tr ' ' ',') OPTS_FIFO=$($SOCAT -?? |sed '1,/opt:/ d' |egrep 'groups=([A-Z]+,)*FIFO' |awk '{print($1);}' |xargs echo |tr ' ' ',') OPTS_FORK=$($SOCAT -?? |sed '1,/opt:/ d' |egrep 'groups=([A-Z]+,)*FORK' |awk '{print($1);}' |xargs echo |tr ' ' ',') OPTS_LISTEN=$($SOCAT -?? |sed '1,/opt:/ d' |egrep 'groups=([A-Z]+,)*LISTEN' |awk '{print($1);}' |xargs echo |tr ' ' ',') OPTS_NAMED=$($SOCAT -?? |sed '1,/opt:/ d' |egrep 'groups=([A-Z]+,)*NAMED' |awk '{print($1);}' |xargs echo |tr ' ' ',') OPTS_OPEN=$($SOCAT -?? |sed '1,/opt:/ d' |egrep 'groups=([A-Z]+,)*OPEN[^S]' |awk '{print($1);}' |xargs echo |tr ' ' ',') OPTS_PARENT=$($SOCAT -?? |sed '1,/opt:/ d' |egrep 'groups=([A-Z]+,)*PARENT' |awk '{print($1);}' |xargs echo |tr ' ' ',') OPTS_READLINE=$($SOCAT -?? |sed '1,/opt:/ d' |egrep 'groups=([A-Z]+,)*READLINE' |awk '{print($1);}' |xargs echo |tr ' ' ',') OPTS_RETRY=$($SOCAT -?? |sed '1,/opt:/ d' |egrep 'groups=([A-Z]+,)*RETRY' |awk '{print($1);}' |grep -v forever|xargs echo |tr ' ' ',') OPTS_RANGE=$($SOCAT -?? |sed '1,/opt:/ d' |egrep 'groups=([A-Z]+,)*RANGE' |awk '{print($1);}' |xargs echo |tr ' ' ',') OPTS_FILE=$($SOCAT -?? |sed '1,/opt:/ d' |egrep 'groups=([A-Z]+,)*REG' |awk '{print($1);}' |xargs echo |tr ' ' ',') OPTS_UNIX=$($SOCAT -?? |sed '1,/opt:/ d' |egrep 'groups=([A-Z]+,)*UNIX' |awk '{print($1);}' |xargs echo |tr ' ' ',') OPTS_SOCKET=$($SOCAT -?? |sed '1,/opt:/ d' |egrep 'groups=([A-Z]+,)*SOCKET' |awk '{print($1);}' |xargs echo |tr ' ' ',') OPTS_TERMIOS=$($SOCAT -?? |sed '1,/opt:/ d' |egrep 'groups=([A-Z]+,)*TERMIOS' |awk '{print($1);}' |xargs echo |tr ' ' ',') OPTS_IP4=$($SOCAT -?? |sed '1,/opt:/ d' |egrep 'groups=([A-Z]+,)*IP4' |awk '{print($1);}' |xargs echo |tr ' ' ',') OPTS_IP6=$($SOCAT -?? |sed '1,/opt:/ d' |egrep 'groups=([A-Z]+,)*IP6' |awk '{print($1);}' |xargs echo |tr ' ' ',') OPTS_TCP=$($SOCAT -?? |sed '1,/opt:/ d' |egrep 'groups=([A-Z]+,)*TCP' |awk '{print($1);}' |xargs echo |tr ' ' ',') OPTS_UDP=$($SOCAT -?? |sed '1,/opt:/ d' |egrep 'groups=([A-Z]+,)*UDP' |awk '{print($1);}' |xargs echo |tr ' ' ',') OPTS_SOCKS4=$($SOCAT -?? |sed '1,/opt:/ d' |egrep 'groups=([A-Z]+,)*SOCKS4' |awk '{print($1);}' |xargs echo |tr ' ' ',') OPTS_PROCESS=$($SOCAT -?? |sed '1,/opt:/ d' |egrep 'groups=([A-Z]+,)*PROCESS' |awk '{print($1);}' |xargs echo |tr ' ' ',') OPTS_OPENSSL=$($SOCAT -?? |sed '1,/opt:/ d' |egrep 'groups=([A-Z]+,)*OPENSSL' |awk '{print($1);}' |xargs echo |tr ' ' ',') OPTS_PTY=$($SOCAT -?? |sed '1,/opt:/ d' |egrep 'groups=([A-Z]+,)*PTY' |awk '{print($1);}' |xargs echo |tr ' ' ',') OPTS_HTTP=$($SOCAT -?? |sed '1,/opt:/ d' |egrep 'groups=([A-Z]+,)*HTTP' |awk '{print($1);}' |xargs echo |tr ' ' ',') OPTS_APPL=$($SOCAT -?? |sed '1,/opt:/ d' |egrep 'groups=([A-Z]+,)*APPL' |awk '{print($1);}' |xargs echo |tr ' ' ',') # find user ids to setown to; non-root only can setown to itself if [ $(id -u) = 0 ]; then # up to now, it is not a big problem when these do not exist _UID=nobody _GID=staff else _UID=$(id -u) _GID=$(id -g) fi # some options require values; here we try to replace these bare options with # valid forms. filloptionvalues() { local OPTS=",$1," # case "$OPTS" in *,umask,*) OPTS=$(echo "$OPTS" |sed "s/,umask,/,umask=0026,/g");; esac case "$OPTS" in *,user,*) OPTS=$(echo "$OPTS" |sed "s/,user,/,user=$_UID,/g");; esac case "$OPTS" in *,user-early,*) OPTS=$(echo "$OPTS" |sed "s/,user-early,/,user-early=$_UID,/g");; esac case "$OPTS" in *,user-late,*) OPTS=$(echo "$OPTS" |sed "s/,user-late,/,user-late=$_UID,/g");; esac case "$OPTS" in *,owner,*) OPTS=$(echo "$OPTS" |sed "s/,owner,/,owner=$_UID,/g");; esac case "$OPTS" in *,uid,*) OPTS=$(echo "$OPTS" |sed "s/,uid,/,uid=$_UID,/g");; esac case "$OPTS" in *,uid-l,*) OPTS=$(echo "$OPTS" |sed "s/,uid-l,/,uid-l=$_UID,/g");; esac case "$OPTS" in *,setuid,*) OPTS=$(echo "$OPTS" |sed "s/,setuid,/,setuid=$_UID,/g");; esac case "$OPTS" in *,group,*) OPTS=$(echo "$OPTS" |sed "s/,group,/,group=$_GID,/g");; esac case "$OPTS" in *,group-early,*) OPTS=$(echo "$OPTS" |sed "s/,group-early,/,group-early=$_GID,/g");; esac case "$OPTS" in *,group-late,*) OPTS=$(echo "$OPTS" |sed "s/,group-late,/,group-late=$_GID,/g");; esac case "$OPTS" in *,gid,*) OPTS=$(echo "$OPTS" |sed "s/,gid,/,gid=$_GID,/g");; esac case "$OPTS" in *,gid-l,*) OPTS=$(echo "$OPTS" |sed "s/,gid-l,/,gid-l=$_GID,/g");; esac case "$OPTS" in *,setgid,*) OPTS=$(echo "$OPTS" |sed "s/,setgid,/,setgid=$_GID,/g");; esac case "$OPTS" in *,mode,*) OPTS=$(echo "$OPTS" |sed "s/,mode,/,mode=0700,/g");; esac case "$OPTS" in *,perm,*) OPTS=$(echo "$OPTS" |sed "s/,perm,/,perm=0700,/g");; esac case "$OPTS" in *,perm-early,*) OPTS=$(echo "$OPTS" |sed "s/,perm-early,/,perm-early=0700,/g");; esac case "$OPTS" in *,perm-late,*) OPTS=$(echo "$OPTS" |sed "s/,perm-late,/,perm-late=0700,/g");; esac case "$OPTS" in *,path,*) OPTS=$(echo "$OPTS" |sed "s/,path,/,path=.,/g");; esac # SOCKET case "$OPTS" in *,bind,*) OPTS=$(echo "$OPTS" |sed "s/,bind,/,bind=:,/g");; esac case "$OPTS" in *,linger,*) OPTS=$(echo "$OPTS" |sed "s/,linger,/,linger=2,/g");; esac case "$OPTS" in *,connect-timeout,*) OPTS=$(echo "$OPTS" |sed "s/,connect-timeout,/,connect-timeout=1,/g");; esac # IP case "$OPTS" in *,ipoptions,*) OPTS=$(echo "$OPTS" |sed "s|,ipoptions,|,ipoptions=x01,|g");; esac case "$OPTS" in *,pf,*) OPTS=$(echo "$OPTS" |sed "s|,pf,|,pf=ip4,|g");; esac case "$OPTS" in *,range,*) OPTS=$(echo "$OPTS" |sed "s|,range,|,range=127.0.0.1/32,|g");; esac case "$OPTS" in *,if,*) OPTS=$(echo "$OPTS" |sed "s/,if,/,if=$INTERFACE,/g");; esac # PTY case "$OPTS" in *,pty-interval,*) OPTS=$(echo "$OPTS" |sed "s/,pty-interval,/,pty-interval=$INTERFACE,/g");; esac # RETRY case "$OPTS" in *,interval,*) OPTS=$(echo "$OPTS" |sed "s/,interval,/,interval=1,/g");; esac # READLINE case "$OPTS" in *,history,*) OPTS=$(echo "$OPTS" |sed "s/,history,/,history=.history,/g");; esac case "$OPTS" in *,noecho,*) OPTS=$(echo "$OPTS" |sed "s/,noecho,/,noecho=password,/g");; esac case "$OPTS" in *,prompt,*) OPTS=$(echo "$OPTS" |sed "s/,prompt,/,prompt=CMD,/g");; esac # IPAPP case "$OPTS" in *,sp,*) OPTS=$(echo "$OPTS" |sed "s/,sp,/,sp=$SOURCEPORT,/g");; esac # OPENSSL case "$OPTS" in *,ciphers,*) OPTS=$(echo "$OPTS" |sed "s/,ciphers,/,ciphers=NULL,/g");; esac case "$OPTS" in *,method,*) OPTS=$(echo "$OPTS" |sed "s/,method,/,method=SSLv3,/g");; esac case "$OPTS" in *,cafile,*) OPTS=$(echo "$OPTS" |sed "s/,cafile,/,cafile=/tmp/hugo,/g");; esac case "$OPTS" in *,capath,*) OPTS=$(echo "$OPTS" |sed "s/,capath,/,capath=/tmp/hugo,/g");; esac case "$OPTS" in *,cert,*) OPTS=$(echo "$OPTS" |sed "s/,cert,/,cert=/tmp/hugo,/g");; esac case "$OPTS" in *,key,*) OPTS=$(echo "$OPTS" |sed "s/,key,/,key=/tmp/hugo,/g");; esac case "$OPTS" in *,dh,*) OPTS=$(echo "$OPTS" |sed "s/,dh,/,dh=/tmp/hugo,/g");; esac case "$OPTS" in *,egd,*) OPTS=$(echo "$OPTS" |sed "s/,egd,/,egd=/tmp/hugo,/g");; esac case "$OPTS" in *,compress,*) OPTS=$(echo "$OPTS" |sed "s/,compress,/,compress=none,/g");; esac # PROXY case "$OPTS" in *,proxyauth,*) OPTS=$(echo "$OPTS" |sed "s/,proxyauth,/,proxyauth=user:pass,/g");; esac case "$OPTS" in *,proxyport,*) OPTS=$(echo "$OPTS" |sed "s/,proxyport,/,proxyport=3128,/g");; esac case "$OPTS" in *,link,*) OPTS=$(echo "$OPTS" |sed "s/,link,/,link=testlink,/g");; esac # TCP-WRAPPERS case "$OPTS" in *,allow-table,*) OPTS=$(echo "$OPTS" |sed "s|,allow-table,|,allow-table=/tmp/hugo,|g");; esac case "$OPTS" in *,deny-table,*) OPTS=$(echo "$OPTS" |sed "s|,deny-table,|,deny-table=/tmp/hugo,|g");; esac case "$OPTS" in *,tcpwrap-dir,*) OPTS=$(echo "$OPTS" |sed "s|,tcpwrap-dir,|,tcpwrap-dir=/tmp,|g");; esac echo $OPTS >&2 expr "$OPTS" : ',\(.*\),' } # OPTS_FIFO: nothing yet # OPTS_CHR: nothing yet # OPTS_BLK: nothing yet # OPTS_REG: nothing yet OPTS_SOCKET=",$OPTS_SOCKET," OPTS_SOCKET=$(expr "$OPTS_SOCKET" : ',\(.*\),') N=1 #------------------------------------------------------------------------------ #method=open #METHOD=$(echo "$method" |tr a-z A-Z) #TEST="$METHOD on file accepts all its options" # echo "### $TEST" #TF=$TD/file$N #DA="test$N $(date) $RANDOM" #OPTGROUPS=$($SOCAT -? |fgrep " $method:" |sed 's/.*=//') #for g in $(echo $OPTGROUPS |tr ',' ' '); do # eval "OPTG=\$OPTS_$(echo $g |tr a-z- A-Z_)"; # OPTS="$OPTS,$OPTG"; #done ##echo $OPTS # #for o in $(filloptionvalues $OPTS|tr ',' ' '); do # echo testing if $METHOD accepts option $o # touch $TF # $SOCAT $opts -!!$method:$TF,$o /dev/null,ignoreof &2 & pid=$! sleep 1 #waittcp4port $PORT for o in $(filloptionvalues $OPTS|tr ',' ' '); do echo "testing if $ADDR accepts option $o" # echo $SOCAT $opts /dev/null $addr:$LOCALHOST:$PORT,$o $SOCAT $opts /dev/null $addr:$LOCALHOST:$PORT,$o done kill $pid done kill $pid 2>/dev/null opts= PORT=$((PORT+1)) fi #------------------------------------------------------------------------------ # test proxy connect #set -vx if true; then #if false; then #opts="-s -d -d -d -d" pid=$! for addr in proxy; do ADDR=$(echo "$addr" |tr a-z A-Z) TEST="$ADDR accepts all its options" echo "### $TEST" OPTGROUPS=$($SOCAT -? |fgrep " $addr:" |sed 's/.*=//') # echo OPTGROUPS=$OPTGROUPS OPTS= for g in $(echo $OPTGROUPS |tr ',' ' '); do eval "OPTG=\$OPTS_$(echo $g |tr a-z A-Z)"; OPTS="$OPTS,$OPTG"; done echo $OPTS # prepare dummy server $SOCAT tcp-l:$PORT,reuseaddr,crlf exec:"/usr/bin/env bash proxyecho.sh" || echo "cannot start proxyecho.sh" >&2 & pid=$! sleep 1 for o in $(filloptionvalues $OPTS|tr ',' ' '); do echo "testing if $ADDR accepts option $o" # echo $SOCAT $opts /dev/null $addr:$LOCALHOST:127.0.0.1:$PORT,$o $SOCAT $opts /dev/null $addr:$LOCALHOST:127.0.0.1:$((PORT+1)),proxyport=$PORT,$o done kill $pid 2>/dev/null done kill $pid 2>/dev/null opts= PORT=$((PORT+2)) fi #------------------------------------------------------------------------------ # test tcp4 #set -vx if true; then #if false; then #opts="-s -d -d -d -d" $SOCAT $opts tcp4-listen:$PORT,reuseaddr,fork,$o echo /dev/null opts= PORT=$((PORT+1)) fi #------------------------------------------------------------------------------ # test udp4-connect #set -vx if true; then #if false; then #opts="-s -d -d -d -d" $SOCAT $opts udp4-listen:$PORT,fork,$o echo /dev/null opts= PORT=$((PORT+1)) fi #------------------------------------------------------------------------------ # test tcp4-listen #set -vx if true; then #if false; then #opts="-s -d -d -d -d" for addr in tcp4-listen; do ADDR=$(echo "$addr" |tr a-z A-Z) TEST="$ADDR accepts all its options" echo "### $TEST" OPTGROUPS=$($SOCAT -? |fgrep " $addr:" |sed 's/.*=//') OPTS= for g in $(echo $OPTGROUPS |tr ',' ' '); do eval "OPTG=\$OPTS_$(echo $g |tr a-z A-Z)"; OPTS="$OPTS,$OPTG"; done echo $OPTS for o in $(filloptionvalues $OPTS|tr ',' ' '); do echo "testing if $ADDR accepts option $o" $SOCAT $opts $ADDR:$PORT,reuseaddr,$o echo /dev/null kill $pid 2>/dev/null done done opts= PORT=$((PORT+1)) fi #------------------------------------------------------------------------------ # test udp4-listen #set -vx if true; then #if false; then #opts="-s -d -d -d -d" for addr in udp4-listen; do ADDR=$(echo "$addr" |tr a-z A-Z) TEST="$ADDR accepts all its options" echo "### $TEST" OPTGROUPS=$($SOCAT -? |fgrep " $addr:" |sed 's/.*=//') OPTS= for g in $(echo $OPTGROUPS |tr ',' ' '); do eval "OPTG=\$OPTS_$(echo $g |tr a-z A-Z)"; OPTS="$OPTS,$OPTG"; done echo $OPTS for o in $(filloptionvalues $OPTS|tr ',' ' '); do echo "testing if $ADDR accepts option $o" $SOCAT $opts $ADDR:$PORT,reuseaddr,$o echo /dev/null kill $pid 2>/dev/null done done opts= PORT=$((PORT+1)) fi #------------------------------------------------------------------------------ # test udp4-sendto #set -vx if true; then #if false; then #opts="-s -d -d -d -d" $SOCAT $opts udp4-recv:$PORT,fork,$o echo /dev/null opts= PORT=$((PORT+1)) fi #------------------------------------------------------------------------------ # test udp4-datagram #set -vx if true; then #if false; then #opts="-s -d -d -d -d" #$SOCAT $opts udp4-recvfrom:$PORT,fork,$o echo /dev/null opts= PORT=$((PORT+1)) fi #------------------------------------------------------------------------------ # test udp4-recv #set -vx if true; then #if false; then #opts="-s -d -d -d -d" for addr in udp4-recv; do ADDR=$(echo "$addr" |tr a-z A-Z) TEST="$ADDR accepts all its options" echo "### $TEST" OPTGROUPS=$($SOCAT -? |fgrep " $addr:" |sed 's/.*=//') OPTS= for g in $(echo $OPTGROUPS |tr ',' ' '); do eval "OPTG=\$OPTS_$(echo $g |tr a-z A-Z)"; OPTS="$OPTS,$OPTG"; done echo $OPTS for o in $(filloptionvalues $OPTS|tr ',' ' '); do echo "testing if $ADDR accepts option $o" $SOCAT $opts $ADDR:$PORT,reuseaddr,$o echo /dev/null kill $pid 2>/dev/null done done opts= PORT=$((PORT+1)) fi #------------------------------------------------------------------------------ # test udp4-recvfrom #set -vx if true; then #if false; then #opts="-s -d -d -d -d" for addr in udp4-recvfrom; do ADDR=$(echo "$addr" |tr a-z A-Z) TEST="$ADDR accepts all its options" echo "### $TEST" OPTGROUPS=$($SOCAT -? |fgrep " $addr:" |sed 's/.*=//') OPTS= for g in $(echo $OPTGROUPS |tr ',' ' '); do eval "OPTG=\$OPTS_$(echo $g |tr a-z A-Z)"; OPTS="$OPTS,$OPTG"; done echo $OPTS for o in $(filloptionvalues $OPTS|tr ',' ' '); do echo "testing if $ADDR accepts option $o" $SOCAT $opts $ADDR:$PORT,reuseaddr,$o echo /dev/null kill $pid 2>/dev/null done done opts= PORT=$((PORT+1)) fi #------------------------------------------------------------------------------ # test ip4-sendto #set -vx if true; then #if false; then #opts="-s -d -d -d -d" $SOCAT $opts ip4-recv:$PORT,fork,$o echo /dev/null opts= PORT=$((PORT+1)) fi #------------------------------------------------------------------------------ # test ip4-recv #set -vx if true; then #if false; then #opts="-s -d -d -d -d" for addr in ip4-recv; do ADDR=$(echo "$addr" |tr a-z A-Z) TEST="$ADDR accepts all its options" echo "### $TEST" OPTGROUPS=$($SOCAT -? |fgrep " $addr:" |sed 's/.*=//') OPTS= for g in $(echo $OPTGROUPS |tr ',' ' '); do eval "OPTG=\$OPTS_$(echo $g |tr a-z A-Z)"; OPTS="$OPTS,$OPTG"; done echo $OPTS for o in $(filloptionvalues $OPTS|tr ',' ' '); do echo "testing if $ADDR accepts option $o" $SOCAT $opts $ADDR:$PORT,reuseaddr,$o echo /dev/null kill $pid 2>/dev/null done done opts= PORT=$((PORT+1)) fi #------------------------------------------------------------------------------ # test ip4-recvfrom #set -vx if true; then #if false; then #opts="-s -d -d -d -d" for addr in ip4-recvfrom; do ADDR=$(echo "$addr" |tr a-z A-Z) TEST="$ADDR accepts all its options" echo "### $TEST" OPTGROUPS=$($SOCAT -? |fgrep " $addr:" |sed 's/.*=//') OPTS= for g in $(echo $OPTGROUPS |tr ',' ' '); do eval "OPTG=\$OPTS_$(echo $g |tr a-z A-Z)"; OPTS="$OPTS,$OPTG"; done echo $OPTS for o in $(filloptionvalues $OPTS|tr ',' ' '); do echo "testing if $ADDR accepts option $o" $SOCAT $opts $ADDR:$PORT,reuseaddr,$o echo /dev/null kill $pid 2>/dev/null done done opts= PORT=$((PORT+1)) fi #------------------------------------------------------------------------------ # test READLINE if true; then #if false; then #opts="-s -d -d -d -d" for addr in readline; do ADDR=$(echo "$addr" |tr a-z A-Z) TEST="$ADDR accepts all its options" echo "### $TEST" TS=$TD/script$N OPTGROUPS=$($SOCAT -? |fgrep " $addr " |sed 's/.*=//') OPTS= for g in $(echo $OPTGROUPS |tr ',' ' '); do eval "OPTG=\$OPTS_$(echo $g |tr a-z A-Z)"; OPTS="$OPTS,$OPTG"; done #echo $OPTS for o in $(filloptionvalues $OPTS|tr ',' ' '); do # for o in bs0; do echo "testing if $ADDR accepts option $o" echo "$SOCAT $opts readline,$o /dev/null" >$TS chmod u+x $TS $SOCAT /dev/null,ignoreeof exec:$TS,pty #stty sane done #reset 1>&0 2>&0 done opts= fi #------------------------------------------------------------------------------ # unnamed pipe #if false; then if true; then for addr in pipe; do ADDR=$(echo "$addr" |tr a-z A-Z) TEST="unnamed $ADDR accepts all its options" echo "### $TEST" OPTGROUPS=$($SOCAT -? |egrep " $addr[^:]" |sed 's/.*=//') OPTS= for g in $(echo $OPTGROUPS |tr ',' ' '); do eval "OPTG=\$OPTS_$(echo $g |tr a-z A-Z)"; OPTS="$OPTS,$OPTG"; done #echo $OPTS for o in $(filloptionvalues $OPTS|tr ',' ' '); do echo testing if unnamed $ADDR accepts option $o $SOCAT $opts $addr,$o /dev/null $TF done done fi #------------------------------------------------------------------------------ # test OPEN address #! test it on pipe, device, new file N=1 #if false; then if true; then for addr in open; do ADDR=$(echo "$addr" |tr a-z A-Z) TEST="$ADDR on file accepts all its options" echo "### $TEST" TF=$TD/file$N OPTGROUPS=$($SOCAT -? |fgrep " $addr:" |sed 's/.*=//') OPTS= for g in $(echo $OPTGROUPS |tr ',' ' '); do eval "OPTG=\$OPTS_$(echo $g |tr a-z A-Z)"; OPTS="$OPTS,$OPTG"; done #echo $OPTS for o in $(filloptionvalues $OPTS|tr ',' ' '); do echo testing if $ADDR on file accepts option $o touch $TF $SOCAT $opts -!!$addr:$TF,$o /dev/null,ignoreof /dev/null rm -f $TF done if [ $(id -u) -eq 0 ]; then TEST="$ADDR on existing device accepts all its options" echo "### $TEST" TF=$TD/null OPTGROUPS=$($SOCAT -? |fgrep " $addr:" |sed 's/.*=//') OPTGROUPS=$(echo $OPTGROUPS |sed -e 's/,REG,/,/g' -e 's/,OPEN,/,/g') OPTS= for g in $(echo $OPTGROUPS |tr ',' ' '); do eval "OPTG=\$OPTS_$(echo $g |tr a-z A-Z)"; OPTS="$OPTS,$OPTG"; done #echo $OPTS for o in $(filloptionvalues $OPTS|tr ',' ' '); do echo testing if $ADDR on existing device accepts option $o rm -f $TF; mknod $TF c 1 3 $SOCAT $opts -!!$addr:$TF,$o /dev/null,ignoreof "$tf" 2>"$te" (psleep $T; echo "$da"; psleep $T) |($TRACE $SOCAT $opts "$arg1" "$arg2" >"$tf" 2>"$te"; echo $? >"$td/test$N.rc") & export rc1=$! #sleep 5 && kill $rc1 2>/dev/null & # rc2=$! wait $rc1 # kill $rc2 2>/dev/null if [ "$(cat "$td/test$N.rc")" != 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$TRACE $SOCAT $opts $arg1 $arg2" >&2 cat "$te" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif echo "$da" |diff - "$tf" >"$tdiff" 2>&1; then $PRINTF "$OK\n" if [ "$VERBOSE" ]; then echo "$SOCAT $opts $arg1 $arg2" >&2; fi if [ -n "$debug" ]; then cat $te >&2; fi numOK=$((numOK+1)) else $PRINTF "$FAILED:\n" echo "$TRACE $SOCAT $opts $arg1 $arg2" >&2 cat "$te" >&2 echo diff: >&2 cat "$tdiff" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND } # test if call to od and throughput of data works - with graceful shutdown and # flush of od buffers testod () { local num="$1" local title="$2" local arg1="$3"; [ -z "$arg1" ] && arg1="-" local arg2="$4"; [ -z "$arg2" ] && arg2="echo" local opts="$5" local T="$6"; [ -z "$T" ] && T=0 local tf="$td/test$N.stdout" local te="$td/test$N.stderr" local tr="$td/test$N.ref" local tdiff="$td/test$N.diff" local dain="$(date) $RANDOM" if ! eval $NUMCOND; then :; else echo "$dain" |$OD_C >"$tr" # local daout="$(echo "$dain" |$OD_C)" $PRINTF "test $F_n %s... " $num "$title" (psleep $T; echo "$dain"; psleep $T) |$TRACE $SOCAT $opts "$arg1" "$arg2" >"$tf" 2>"$te" if [ "$?" != 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$TRACE $SOCAT $opts $arg1 $arg2" cat "$te" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $num" # elif echo "$daout" |diff - "$tf" >"$tdiff" 2>&1; then elif diff "$tr" "$tf" >"$tdiff" 2>&1; then $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) else $PRINTF "$FAILED: diff:\n" echo "$TRACE $SOCAT $opts $arg1 $arg2" cat "$te" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $num" fi fi # NUMCOND } # test if the socat executable has these features compiled in # print the first missing address type testfeats () { local a A; for a in $@; do A=$(echo "$a" |tr 'a-z-' 'A-Z_') if SOCAT_MAIN_WAIT= $SOCAT -V |grep "#define WITH_$A 1\$" >/dev/null; then if [[ "$A" =~ OPENSSL.* ]]; then gentestcert testsrv gentestcert testcli fi shift continue fi echo "$a" return 1 done return 0 } # test if the socat executable has these address types compiled in # print the first missing address type testaddrs () { local a A; for a in $@; do A=$(echo "$a" |tr 'a-z' 'A-Z') if ! $SOCAT $A /dev/null 2>&1 |grep -q "E unknown device/address"; then shift continue fi echo "$a" return 1 done return 0 } # test if the socat executable has these options compiled in # print the first missing option testoptions () { local a A; for a in $@; do A=$(echo "$a" |tr 'a-z' 'A-Z') if $SOCAT -??? |grep "[^a-z0-9-]$a[^a-z0-9-]" >/dev/null; then shift continue fi echo "$a" return 1 done return 0 } # check if the given pid exists and has child processes # if yes: prints child process lines to stdout, returns 0 # if not: prints ev.message to stderr, returns 1 childprocess () { local l case "$UNAME" in AIX) l="$(ps -fade |grep "^........ ...... $(printf %6u $1)")" ;; FreeBSD) l="$(ps -faje |grep "^........ ..... $(printf %5u $1)")" ;; HP-UX) l="$(ps -fade |grep "^........ ..... $(printf %5u $1)")" ;; Linux) l="$(ps -fade |grep "^........ ..... $(printf %5u $1)")" ;; # NetBSD) l="$(ps -aj |grep "^........ ..... $(printf %4u $1)")" ;; NetBSD) l="$(ps -aj |grep "^[^ ][^ ]*[ ][ ]*..... $(printf %5u $1)")" ;; OpenBSD) l="$(ps -aj |grep "^........ ..... $(printf %5u $1)")" ;; SunOS) l="$(ps -fade |grep "^........ ..... $(printf %5u $1)")" ;; DragonFly)l="$(ps -faje |grep "^[^ ][^ ]*[ ][ ]*..... $(printf %5u $1)")" ;; CYGWIN*) l="$(ps -pafe |grep "^[^ ]*[ ][ ]*[^ ][^ ]*[ ][ ]*$1[ ]")" ;; *) l="$(ps -fade |grep "^[^ ][^ ]*[ ][ ]*[0-9][0-9]**[ ][ ]*$(printf %5u $1) ")" ;; esac if [ -z "$l" ]; then return 1; fi echo "$l" return 0 } # return a list of child process pids childpids () { case "$UNAME" in 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);}')" ;; HP-UX) l="$(ps -fade |grep "^........ ..... $(printf %5u $1)" |awk '{print($2);}')" ;; Linux) l="$(ps -fade |grep "^........ ..... $(printf %5u $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);}')" ;; OpenBSD) l="$(ps -aj |grep "^........ ..... $(printf %5u $1)" |awk '{print($2);}')" ;; SunOS) l="$(ps -fade |grep "^........ ..... $(printf %5u $1)" |awk '{print($2);}')" ;; DragonFly)l="$(ps -faje |grep "^[^ ][^ ]*[ ][ ]*..... $(printf %5u $1)" |awk '{print($2);}')" ;; CYGWIN*) l="$(ps -pafe |grep "^[^ ]*[ ][ ]*[^ ][^ ]*[ ][ ]*$1[ ]" |awk '{print($2);}')" ;; *) l="$(ps -fade |grep "^[^ ][^ ]*[ ][ ]*[0-9][0-9]*[ ][ ]*$(printf %5u $1) " |awk '{print($2);}')" ;; esac if [ -z "$l" ]; then return 1; fi echo "$l" return 0 } # check if the given process line refers to a defunct (zombie) process # yes: returns 0 # no: returns 1 isdefunct () { local l case "$UNAME" in AIX) l="$(echo "$1" |grep ' $')" ;; FreeBSD) l="$(echo "$1" |grep ' $')" ;; HP-UX) l="$(echo "$1" |grep ' $')" ;; Linux) l="$(echo "$1" |grep ' $')" ;; SunOS) l="$(echo "$1" |grep ' $')" ;; DragonFly)l="$(echo "$1" |grep ' $')" ;; *) l="$(echo "$1" |grep ' $')" ;; esac [ -n "$l" ]; } # check if UNIX socket protocol is available on host runsunix () { return 0; $TRACE $SOCAT /dev/null UNIX-LISTEN:"$td/unix.socket" 2>"$td/unix.stderr" & pid=$! usleep $MICROS kill "$pid" 2>/dev/null test ! -s "$td/unix.stderr" } unset HAVENOT_IP4 # check if an IP4 loopback interface exists runsip4 () { [ -n "$HAVENOT_IP4" ] && return $HAVENOT_IP4 local l case "$UNAME" in AIX) l=$($IFCONFIG lo0 |fgrep 'inet 127.0.0.1 ') ;; FreeBSD) l=$($IFCONFIG lo0 |fgrep 'inet 127.0.0.1 ') ;; HP-UX) l=$($IFCONFIG lo0 |fgrep 'inet 127.0.0.1 ') ;; Linux) if [ "$IP" ]; then l=$($IP address |egrep ' inet 127.0.0.1/') else l=$($IFCONFIG |egrep 'inet (addr:)?127\.0\.0\.1 ') fi ;; NetBSD)l=$($IFCONFIG -a |fgrep 'inet 127.0.0.1 ');; OpenBSD)l=$($IFCONFIG -a |fgrep 'inet 127.0.0.1 ');; OSF1) l=$($IFCONFIG -a |grep ' inet ') ;; SunOS) l=$($IFCONFIG -a |grep 'inet ') ;; Darwin)l=$($IFCONFIG lo0 |fgrep 'inet 127.0.0.1 ') ;; DragonFly)l=$($IFCONFIG -a |fgrep 'inet 127.0.0.1 ');; CYGWIN*) l=$(ipconfig |grep IPv4);; *) l=$($IFCONFIG -a |grep ' ::1[^:0-9A-Fa-f]') ;; esac [ -z "$l" ] && return 1 # existence of interface might not suffice, check for routeability: case "$UNAME" in Darwin) ping -c 1 127.0.0.1 >/dev/null 2>&1; l="$?" ;; Linux) ping -c 1 127.0.0.1 >/dev/null 2>&1; l="$?" ;; *) if [ -n "$l" ]; then l=0; else l=1; fi ;; esac HAVENOT_IP4=$l if [ "$HAVENOT_IP4" -ne 0 ]; then echo IP4 fi return $l; } unset HAVENOT_IP6 # check if an IP6 loopback interface exists runsip6 () { [ -n "$HAVENOT_IP6" ] && return $HAVENOT_IP6 local l case "$UNAME" in AIX) l=$($IFCONFIG lo0 |grep 'inet6 ::1[/%]') ;; HP-UX) l=$($IFCONFIG lo0 |grep ' inet6 ') ;; Linux) if [ "$IP" ]; then l=$($IP address |egrep 'inet6 ::1/128') else l=$($IFCONFIG |egrep 'inet6 (addr: )?::1/?') fi ;; NetBSD)l=$($IFCONFIG -a |grep 'inet6 ::1 ');; OSF1) l=$($IFCONFIG -a |grep ' inet6 ') ;; SunOS) l=$($IFCONFIG -a |grep 'inet6 ') ;; Darwin)l=$($IFCONFIG lo0 |grep 'inet6 ::1 ') ;; CYGWIN*) l=$(ipconfig |grep IPv6);; *) l=$($IFCONFIG -a |grep ' ::1[^:0-9A-Fa-f]') ;; esac [ -z "$l" ] && return 1 # existence of interface might not suffice, check for routeability: case "$UNAME" in Darwin) $PING6 -c 1 ::1 >/dev/null 2>&1; l="$?" ;; Linux) $PING6 -c 1 ::1 >/dev/null 2>&1; l="$?" ;; *) if [ -n "$l" ]; then l=0; else l=1; fi ;; esac HAVENOT_IP6=$l if [ "$HAVENOT_IP6" -ne 0 ]; then echo IP6 fi return "$HAVENOT_IP6" } # check if TCP on IPv4 is available on host runstcp4 () { runsip4 >/dev/null || { echo TCP4; return 1; } $SOCAT -h |grep ' tcp4-' >/dev/null || return 1 return 0; } # check if TCP on IPv6 is available on host runstcp6 () { runsip6 >/dev/null || { echo TCP6; return 1; } $SOCAT -h |grep ' tcp6-' >/dev/null || return 1 return 0; } # check if UDP on IPv4 is available on host runsudp4 () { runsip4 >/dev/null || { echo UDP4; return 1; } $SOCAT -h |grep ' udp4-' >/dev/null || return 1 return 0; } # check if UDP on IPv6 is available on host runsudp6 () { runsip6 >/dev/null || { echo UDP6; return 1; } $SOCAT -h |grep ' udp6-' >/dev/null || return 1 return 0; } # check if SCTP on IPv4 is available on host runssctp4 () { runsip4 >/dev/null || { echo SCTP4; return 1; } $SOCAT -h |grep ' sctp4-' >/dev/null || return 1 $SOCAT /dev/null SCTP4-L:0,accept-timeout=0.001 2>/dev/null || return 1; return 0; } # check if SCTP on IPv6 is available on host runssctp6 () { runsip6 >/dev/null || { echo SCTP6; return 1; } $SOCAT -h |grep ' sctp6-' >/dev/null || return 1 $SOCAT /dev/null SCTP6-L:0,accept-timeout=0.001 2>/dev/null || return 1; return 0; } # wait until an IP4 protocol is ready waitip4proto () { local proto="$1" local logic="$2" # 0..wait until free; 1..wait until listening local timeout="$3" local l [ "$logic" ] || logic=1 [ "$timeout" ] || timeout=5 while [ $timeout -gt 0 ]; do case "$UNAME" in Linux) if [ "$SS" ]; then l=$($SS -n -w -l |grep '^\(raw\|UNCONN\) .* .*[0-9*]:'$proto' [ ]*0\.0\.0\.0:\*') else l=$(netstat -n -w -l |grep '^raw .* .*[0-9*]:'$proto' [ ]*0\.0\.0\.0:\*') fi ;; # FreeBSD) l=$(netstat -an |egrep '^raw46? .*[0-9*]\.'$proto' .* \*\.\*') ;; # NetBSD) l=$(netstat -an |grep '^raw .*[0-9*]\.'$proto' [ ]* \*\.\*') ;; # OpenBSD) l=$(netstat -an |grep '^raw .*[0-9*]\.'$proto' [ ]* \*\.\*') ;; # Darwin) case "$(uname -r)" in # [1-5]*) l=$(netstat -an |grep '^raw.* .*[0-9*]\.'$proto' .* \*\.\*') ;; # *) l=$(netstat -an |grep '^raw4.* .*[0-9*]\.'$proto' .* \*\.\* .*') ;; # esac ;; AIX) # does not seem to show raw sockets in netstat sleep 1; return 0 ;; # SunOS) l=$(netstat -an -f inet -P raw |grep '.*[1-9*]\.'$proto' [ ]*Idle') ;; # HP-UX) l=$(netstat -an |grep '^raw 0 0 .*[0-9*]\.'$proto' .* \*\.\* ') ;; # OSF1) l=$(/usr/sbin/netstat -an |grep '^raw 0 0 .*[0-9*]\.'$proto' [ ]*\*\.\*') ;; *) #l=$(netstat -an |grep -i 'raw .*[0-9*][:.]'$proto' ') ;; sleep 1; return 0 ;; esac [ \( \( $logic -ne 0 \) -a -n "$l" \) -o \ \( \( $logic -eq 0 \) -a -z "$l" \) ] && return 0 sleep 1 timeout=$((timeout-1)) done $ECHO "!protocol $proto timed out! \c" >&2 return 1 } # we need this misleading function name for canonical reasons waitip4port () { waitip4proto "$1" "$2" "$3" } # wait until an IP6 protocol is ready waitip6proto () { local proto="$1" local logic="$2" # 0..wait until free; 1..wait until listening local timeout="$3" local l [ "$logic" ] || logic=1 [ "$timeout" ] || timeout=5 while [ $timeout -gt 0 ]; do case "$UNAME" in Linux) if [ "$SS" ]; then l=$($SS -n -w -l |grep '^\(raw\|UNCONN\) .* \*:'$proto' [ ]*\*:\*') else l=$(netstat -n -w -l |grep '^raw[6 ] .* .*:[0-9*]*:'$proto' [ ]*:::\*') fi ;; # FreeBSD) l=$(netstat -an |egrep '^raw46? .*[0-9*]\.'$proto' .* \*\.\*') ;; # NetBSD) l=$(netstat -an |grep '^raw .*[0-9*]\.'$proto' [ ]* \*\.\*') ;; # OpenBSD) l=$(netstat -an |grep '^raw .*[0-9*]\.'$proto' [ ]* \*\.\*') ;; # Darwin) case "$(uname -r)" in # [1-5]*) l=$(netstat -an |grep '^raw.* .*[0-9*]\.'$proto' .* \*\.\*') ;; # *) l=$(netstat -an |grep '^raw4.* .*[0-9*]\.'$proto' .* \*\.\* .*') ;; # esac ;; AIX) # does not seem to show raw sockets in netstat sleep 1; return 0 ;; # SunOS) l=$(netstat -an -f inet -P raw |grep '.*[1-9*]\.'$proto' [ ]*Idle') ;; # HP-UX) l=$(netstat -an |grep '^raw 0 0 .*[0-9*]\.'$proto' .* \*\.\* ') ;; # OSF1) l=$(/usr/sbin/netstat -an |grep '^raw 0 0 .*[0-9*]\.'$proto' [ ]*\*\.\*') ;; *) #l=$(netstat -an |egrep -i 'raw6? .*[0-9*][:.]'$proto' ') ;; sleep 1; return 0 ;; esac [ \( \( $logic -ne 0 \) -a -n "$l" \) -o \ \( \( $logic -eq 0 \) -a -z "$l" \) ] && return 0 sleep 1 timeout=$((timeout-1)) done $ECHO "!protocol $proto timed out! \c" >&2 return 1 } # we need this misleading function name for canonical reasons waitip6port () { waitip6proto "$1" "$2" "$3" } # check if a TCP4 port is in use # exits with 0 when it is not used checktcp4port () { local port="$1" local l case "$UNAME" in Linux) if [ "$SS" ]; then l=$($SS -4 -l -n -t |grep "^LISTEN .*:$port\>") else l=$(netstat -a -n -t |grep '^tcp .* .*[0-9*]:'$port' .* LISTEN') fi ;; FreeBSD) l=$(netstat -an |grep '^tcp4.* .*[0-9*]\.'$port' .* \*\.\* .* LISTEN') ;; NetBSD) l=$(netstat -an |grep '^tcp .* .*[0-9*]\.'$port' [ ]* \*\.\* [ ]* LISTEN.*') ;; Darwin) case "$(uname -r)" in [1-5]*) l=$(netstat -an |grep '^tcp.* .*[0-9*]\.'$port' .* \*\.\* .* LISTEN') ;; *) l=$(netstat -an |grep '^tcp4.* .*[0-9*]\.'$port' .* \*\.\* .* LISTEN') ;; esac ;; AIX) l=$(netstat -an |grep '^tcp[^6] 0 0 .*[*0-9]\.'$port' .* LISTEN$') ;; SunOS) l=$(netstat -an -f inet -P tcp |grep '.*[1-9*]\.'$port' .*\* 0 .* LISTEN') ;; HP-UX) l=$(netstat -an |grep '^tcp 0 0 .*[0-9*]\.'$port' .* LISTEN$') ;; OSF1) l=$(/usr/sbin/netstat -an |grep '^tcp 0 0 .*[0-9*]\.'$port' [ ]*\*\.\* [ ]*LISTEN') ;; CYGWIN*) l=$(netstat -an -p TCP |grep '^ TCP [0-9.]*:'$port' .* LISTENING') ;; DragonFly)l=$(netstat -ant |grep '^tcp4 .* .*[0-9*]\.'$port' [ ]* \*\.\* [ ]* LISTEN.*') ;; *) l=$(netstat -an |grep -i 'tcp .*[0-9*][:.]'$port' .* listen') ;; esac [ -z "$l" ] && return 0 return 1 } # wait until a TCP4 listen port is ready waittcp4port () { local port="$1" local logic="$2" # 0..wait until free; 1..wait until listening (default) local timeout="$3" local l local vx=+; case $- in *vx*) set +vx; vx=-; esac # no tracing here [ "$logic" ] || logic=1 [ "$timeout" ] || timeout=5 while [ $timeout -gt 0 ]; do case "$UNAME" in Linux) if [ "$SS" ]; then l=$($SS -l -n -t |grep "^LISTEN .*:$port\>") else l=$(netstat -a -n -t |grep '^tcp .* .*[0-9*]:'$port' .* LISTEN') fi ;; FreeBSD) l=$(netstat -an |grep '^tcp4.* .*[0-9*]\.'$port' .* \*\.\* .* LISTEN') ;; NetBSD) l=$(netstat -an |grep '^tcp .* .*[0-9*]\.'$port' [ ]* \*\.\* [ ]* LISTEN.*') ;; Darwin) case "$(uname -r)" in [1-5]*) l=$(netstat -an |grep '^tcp.* .*[0-9*]\.'$port' .* \*\.\* .* LISTEN') ;; *) l=$(netstat -an |grep '^tcp4.* .*[0-9*]\.'$port' .* \*\.\* .* LISTEN') ;; esac ;; AIX) l=$(netstat -an |grep '^tcp[^6] 0 0 .*[*0-9]\.'$port' .* LISTEN$') ;; SunOS) l=$(netstat -an -f inet -P tcp |grep '.*[1-9*]\.'$port' .*\* .* 0 .* LISTEN') ;; HP-UX) l=$(netstat -an |grep '^tcp 0 0 .*[0-9*]\.'$port' .* LISTEN$') ;; OSF1) l=$(/usr/sbin/netstat -an |grep '^tcp 0 0 .*[0-9*]\.'$port' [ ]*\*\.\* [ ]*LISTEN') ;; CYGWIN*) l=$(netstat -an -p TCP |grep '^ TCP [0-9.]*:'$port' .* LISTENING') ;; DragonFly) l=$(netstat -ant |grep '^tcp4 .* .*[0-9*]\.'$port' [ ]* \*\.\* [ ]* LISTEN.*') ;; *) l=$(netstat -an |grep -i 'tcp .*[0-9*][:.]'$port' .* listen') ;; esac if [ \( \( $logic -ne 0 \) -a -n "$l" \) -o \ \( \( $logic -eq 0 \) -a -z "$l" \) ]; then set ${vx}vx return 0 fi sleep 1 timeout=$((timeout-1)) done $ECHO "!port $port timed out! \c" >&2 set ${vx}vx return 1 } # wait until a UDP4 port is ready waitudp4port () { local port="$1" local logic="$2" # 0..wait until free; 1..wait until listening local timeout="$3" local l local vx=+; case $- in *vx*) set +vx; vx=-; esac # no tracing here [ "$logic" ] || logic=1 [ "$timeout" ] || timeout=5 while [ $timeout -gt 0 ]; do case "$UNAME" in Linux) if [ "$SS" ]; then l=$($SS -4 -l -n -u |grep "^UNCONN .*:$port\>") else l=$(netstat -a -n -u -l |grep '^udp .* .*[0-9*]:'$port' [ ]*0\.0\.0\.0:\*') fi ;; FreeBSD) l=$(netstat -an |egrep '^udp46? .*[0-9*]\.'$port' .* \*\.\*') ;; NetBSD) l=$(netstat -an |grep '^udp .*[0-9*]\.'$port' [ ]* \*\.\*') ;; OpenBSD) l=$(netstat -an |grep '^udp .*[0-9*]\.'$port' [ ]* \*\.\*') ;; Darwin) case "$(uname -r)" in [1-5]*) l=$(netstat -an |grep '^udp.* .*[0-9*]\.'$port' .* \*\.\*') ;; *) l=$(netstat -an |grep '^udp4.* .*[0-9*]\.'$port' .* \*\.\* .*') ;; esac ;; AIX) l=$(netstat -an |grep '^udp[4 ] 0 0 .*[*0-9]\.'$port' .* \*\.\*[ ]*$') ;; SunOS) l=$(netstat -an -f inet -P udp |grep '.*[1-9*]\.'$port' [ ]*Idle') ;; HP-UX) l=$(netstat -an |grep '^udp 0 0 .*[0-9*]\.'$port' .* \*\.\* ') ;; OSF1) l=$(/usr/sbin/netstat -an |grep '^udp 0 0 .*[0-9*]\.'$port' [ ]*\*\.\*') ;; DragonFly) l=$(netstat -an |grep '^udp4 .* .*[0-9*]\.'$port' [ ]* \*\.\* [ ]*') ;; *) l=$(netstat -an |grep -i 'udp .*[0-9*][:.]'$port' ') ;; esac if [ \( \( $logic -ne 0 \) -a -n "$l" \) -o \ \( \( $logic -eq 0 \) -a -z "$l" \) ]; then set ${vx}vx return 0 fi sleep 1 timeout=$((timeout-1)) done $ECHO "!port $port timed out! \c" >&2 set ${vx}vx return 1 } # wait until an SCTP4 listen port is ready waitsctp4port () { local port="$1" local logic="$2" # 0..wait until free; 1..wait until listening local timeout="$3" local l local vx=+; case $- in *vx*) set +vx; vx=-; esac # no tracing here [ "$logic" ] || logic=1 [ "$timeout" ] || timeout=5 while [ $timeout -gt 0 ]; do case "$UNAME" in Linux) if [ "$SS" ]; then l=$($SS -4 -n -A sctp 2>/dev/null |grep "^LISTEN .*:$port\>") else l=$(netstat -n -a |grep '^sctp .* .*[0-9*]:'$port' .* LISTEN') fi ;; # FreeBSD) l=$(netstat -an |grep '^tcp4.* .*[0-9*]\.'$port' .* \*\.\* .* LISTEN') ;; # NetBSD) l=$(netstat -an |grep '^tcp .* .*[0-9*]\.'$port' [ ]* \*\.\* [ ]* LISTEN.*') ;; # Darwin) case "$(uname -r)" in # [1-5]*) l=$(netstat -an |grep '^tcp.* .*[0-9*]\.'$port' .* \*\.\* .* LISTEN') ;; # *) l=$(netstat -an |grep '^tcp4.* .*[0-9*]\.'$port' .* \*\.\* .* LISTEN') ;; # esac ;; # AIX) l=$(netstat -an |grep '^tcp[^6] 0 0 .*[*0-9]\.'$port' .* LISTEN$') ;; SunOS) l=$(netstat -an -f inet -P sctp |grep '.*[1-9*]\.'$port' .*\* 0 .* LISTEN') ;; # HP-UX) l=$(netstat -an |grep '^tcp 0 0 .*[0-9*]\.'$port' .* LISTEN$') ;; # OSF1) l=$(/usr/sbin/netstat -an |grep '^tcp 0 0 .*[0-9*]\.'$port' [ ]*\*\.\* [ ]*LISTEN') ;; # CYGWIN*) l=$(netstat -an -p TCP |grep '^ TCP [0-9.]*:'$port' .* LISTENING') ;; *) l=$(netstat -an |grep -i 'sctp .*[0-9*][:.]'$port' .* listen') ;; esac if [ \( \( $logic -ne 0 \) -a -n "$l" \) -o \ \( \( $logic -eq 0 \) -a -z "$l" \) ]; then set ${vx}vx return 0 fi sleep 1 timeout=$((timeout-1)) done $ECHO "!port $port timed out! \c" >&2 set ${vx}vx return 1 } # wait until a tcp6 listen port is ready waittcp6port () { local port="$1" local logic="$2" # 0..wait until free; 1..wait until listening local timeout="$3" local l local vx=+; case $- in *vx*) set +vx; vx=-; esac # no tracing here [ "$logic" ] || logic=1 [ "$timeout" ] || timeout=5 while [ $timeout -gt 0 ]; do case "$UNAME" in Linux) if [ "$SS" ]; then l=$($SS -6 -n -t -l |grep "^LISTEN .*:$port\>") else l=$(netstat -an |grep -E '^tcp6? .* [0-9a-f:%]*:'$port' .* LISTEN') fi ;; FreeBSD) l=$(netstat -an |egrep -i 'tcp(6|46) .*[0-9*][:.]'$port' .* listen') ;; NetBSD) l=$(netstat -an |grep '^tcp6 .*[0-9*]\.'$port' [ ]* \*\.\*') ;; OpenBSD) l=$(netstat -an |grep -i 'tcp6 .*[0-9*][:.]'$port' .* listen') ;; Darwin) l=$(netstat -an |egrep '^tcp4?6 +[0-9]+ +[0-9]+ +[0-9a-z:%*]+\.'$port' +[0-9a-z:%*.]+ +LISTEN') ;; AIX) l=$(netstat -an |grep '^tcp[6 ] 0 0 .*[*0-9]\.'$port' .* LISTEN$') ;; SunOS) l=$(netstat -an -f inet6 -P tcp |grep '.*[1-9*]\.'$port' .*\* [ ]* 0 .* LISTEN') ;; #OSF1) l=$(/usr/sbin/netstat -an |grep '^tcp6 0 0 .*[0-9*]\.'$port' [ ]*\*\.\* [ ]*LISTEN') /*?*/;; DragonFly) l=$(netstat -ant |grep '^tcp6 .* .*[0-9*]\.'$port' [ ]* \*\.\* [ ]* LISTEN.*') ;; *) l=$(netstat -an |grep -i 'tcp6 .*:'$port' .* listen') ;; esac if [ \( \( $logic -ne 0 \) -a -n "$l" \) -o \ \( \( $logic -eq 0 \) -a -z "$l" \) ]; then set ${vx}vx return 0 fi sleep 1 timeout=$((timeout-1)) done $ECHO "!port $port timed out! \c" >&2 #echo set ${vx}vx >&2 set ${vx}vx return 1 } # wait until a UDP6 port is ready waitudp6port () { local port="$1" local logic="$2" # 0..wait until free; 1..wait until listening local timeout="$3" local l local vx=+; case $- in *vx*) set +vx; vx=-; esac # no tracing here [ "$logic" ] || logic=1 [ "$timeout" ] || timeout=5 while [ $timeout -gt 0 ]; do case "$UNAME" in Linux) if [ "$SS" ]; then # CAUTION!!! ss from iproute2 4.15.0-2ubuntu on 18-04 changes # the output format when writing to pipe l=$($SS -6 -u -l -n |grep "^UNCONN.*:$port\>") else l=$(netstat -an |grep -E '^udp6? .* .*[0-9*:%]:'$port' [ ]*:::\*') fi ;; FreeBSD) l=$(netstat -an |egrep '^udp(6|46) .*[0-9*]\.'$port' .* \*\.\*') ;; NetBSD) l=$(netstat -an |grep '^udp6 .* \*\.'$port' [ ]* \*\.\*') ;; OpenBSD) l=$(netstat -an |grep '^udp6 .*[0-9*]\.'$port' [ ]* \*\.\*') ;; Darwin) l=$(netstat -an |egrep '^udp4?6 +[0-9]+ +[0-9]+ +[0-9a-z:%*]+\.'$port' +[0-9a-z:%*.]+') ;; AIX) l=$(netstat -an |grep '^udp[6 ] 0 0 .*[*0-9]\.'$port' .* \*\.\*[ ]*$') ;; SunOS) l=$(netstat -an -f inet6 -P udp |grep '.*[1-9*]\.'$port' [ ]*Idle') ;; #HP-UX) l=$(netstat -an |grep '^udp 0 0 .*[0-9*]\.'$port' ') ;; #OSF1) l=$(/usr/sbin/netstat -an |grep '^udp6 0 0 .*[0-9*]\.'$port' [ ]*\*\.\*') ;; DragonFly) l=$(netstat -ant |grep '^udp6 .* .*[0-9*]\.'$port' [ ]* \*\.\* [ ]*') ;; *) l=$(netstat -an |grep -i 'udp .*[0-9*][:.]'$port' ') ;; esac if [ \( \( $logic -ne 0 \) -a -n "$l" \) -o \ \( \( $logic -eq 0 \) -a -z "$l" \) ]; then set ${vx}vx return 0 fi sleep 1 timeout=$((timeout-1)) done $ECHO "!port $port timed out! \c" >&2 set ${vx}vx return 1 } # wait until a sctp6 listen port is ready # not all (Linux) variants show this in netstat waitsctp6port () { local port="$1" local logic="$2" # 0..wait until free; 1..wait until listening local timeout="$3" local l local vx=+; case $- in *vx*) set +vx; vx=-; esac # no tracing here [ "$logic" ] || logic=1 [ "$timeout" ] || timeout=5 while [ $timeout -gt 0 ]; do case "$UNAME" in Linux) if [ "$SS" ]; then l=$($SS -6 -n -A sctp 2>/dev/null |grep "^LISTEN .*:$port\>") else l=$(netstat -an |grep '^sctp[6 ] .* [0-9a-f:]*:'$port' .* LISTEN') fi ;; # FreeBSD) l=$(netstat -an |grep -i 'tcp[46][6 ] .*[0-9*][:.]'$port' .* listen') ;; # NetBSD) l=$(netstat -an |grep '^tcp6 .*[0-9*]\.'$port' [ ]* \*\.\*') ;; # OpenBSD) l=$(netstat -an |grep -i 'tcp6 .*[0-9*][:.]'$port' .* listen') ;; # AIX) l=$(netstat -an |grep '^tcp[6 ] 0 0 .*[*0-9]\.'$port' .* LISTEN$') ;; SunOS) l=$(netstat -an -f inet6 -P sctp |grep '.*[1-9*]\.'$port' .*\* [ ]* 0 .* LISTEN') ;; # #OSF1) l=$(/usr/sbin/netstat -an |grep '^tcp6 0 0 .*[0-9*]\.'$port' [ ]*\*\.\* [ ]*LISTEN') /*?*/;; *) l=$(netstat -an |grep -i 'stcp6 .*:'$port' .* listen') ;; esac if [ \( \( $logic -ne 0 \) -a -n "$l" \) -o \ \( \( $logic -eq 0 \) -a -z "$l" \) ]; then set ${vx}vx return 0 fi sleep 1 timeout=$((timeout-1)) done $ECHO "!port $port timed out! \c" >&2 set ${vx}vx return 1 } # we need this misleading function name for canonical reasons waitunixport () { waitfile "$1" "$2" "$3" } # wait until a filesystem entry exists waitfile () { local crit=-e case "X$1" in X-*) crit="$1"; shift ;; esac local file="$1" local logic="$2" # 0..wait until gone; 1..wait until exists (default); # 2..wait until not empty local timeout="$3" local vx=+; case $- in *vx*) set +vx; vx=-; esac # no tracing here [ "$logic" ] || logic=1 [ "$logic" -eq 2 ] && crit=-s [ "$timeout" ] || timeout=5 while [ $timeout -gt 0 ]; do if [ \( $logic -ne 0 -a $crit "$file" \) -o \ \( $logic -eq 0 -a ! $crit "$file" \) ]; then set ${vx}vx return 0 fi sleep 1 timeout=$((timeout-1)) done echo "file $file timed out" >&2 set ${vx}vx return 1 } # system dependent values case "$UNAME" in SunOS) SOCK_SEQPACKET=6 ;; *) SOCK_SEQPACKET=5 ;; esac # generate a test certificate and key gentestcert () { local name="$1" if ! [ -f testcert.dh ]; then openssl dhparam -out testcert.dh $RSABITS fi if [ -s $name.key -a -s $name.crt -a -s $name.pem ]; then return; fi openssl genrsa $OPENSSL_RAND -out $name.key $RSABITS >/dev/null 2>&1 #openssl req -new -config $TESTCERT_CONF -key $name.key -x509 -out $name.crt -days 3653 -extensions v3_ca >/dev/null 2>&1 openssl req -new -config $TESTCERT_CONF -key $name.key -x509 -out $name.crt -days 3653 >/dev/null 2>&1 cat $name.key $name.crt testcert.dh >$name.pem } # generate a test DSA key and certificate gentestdsacert () { local name="$1" if [ -s $name.key -a -s $name.crt -a -s $name.pem ]; then return; fi openssl dsaparam -out $name-dsa.pem $DSABITS >/dev/null 2>&1 openssl dhparam -dsaparam -out $name-dh.pem $DSABITS >/dev/null 2>&1 openssl req -newkey dsa:$name-dsa.pem -keyout $name.key -nodes -x509 -config $TESTCERT_CONF -out $name.crt -days 3653 >/dev/null 2>&1 cat $name-dsa.pem $name-dh.pem $name.key $name.crt >$name.pem } # generate a test EC key and certificate gentesteccert () { local name="$1" if [ -s $name.key -a -s $name.crt -a -s $name.pem ]; then return; fi openssl ecparam -name secp521r1 -out $name-ec.pem >/dev/null 2>&1 chmod 0400 $name-ec.pem openssl req -newkey ec:$name-ec.pem -keyout $name.key -nodes -x509 -config $TESTCERT_CONF -out $name.crt -days 3653 >/dev/null 2>&1 cat $name-ec.pem $name.key $name.crt >$name.pem } gentestcert6 () { local name="$1" if [ -s $name.key -a -s $name.crt -a -s $name.pem ]; then return; fi cat $TESTCERT_CONF | { echo "# automatically generated by $0"; cat; } | sed 's/\(commonName\s*=\s*\).*/\1[::1]/' >$TESTCERT6_CONF openssl genrsa $OPENSSL_RAND -out $name.key $RSABITS >/dev/null 2>&1 openssl req -new -config $TESTCERT6_CONF -key $name.key -x509 -out $name.crt -days 3653 >/dev/null 2>&1 cat $name.key $name.crt >$name.pem } # generate a server certificate and key with SubjectAltName gentestaltcert () { local name="$1" if ! [ -f testcert.dh ]; then openssl dhparam -out testcert.dh $RSABITS fi if [ -s $name.key -a -s $name.crt -a -s $name.pem ]; then return; fi openssl genrsa $OPENSSL_RAND -out $name.key $RSABITS >/dev/null 2>&1 openssl req -new -config $TESTALT_CONF -key $name.key -x509 -out $name.crt -days 3653 >/dev/null 2>&1 cat $name.key $name.crt testcert.dh >$name.pem } #------------------------------------------------------------------------------ # Begin of functional tests NAME=UNISTDIO case "$TESTS " in *%$N%*|*%functions%*|*%stdio%*|*%$NAME%*) TEST="$NAME: unidirectional throughput from stdin to stdout" testecho "$N" "$TEST" "stdin" "stdout" "$opts -u" esac N=$((N+1)) NAME=UNPIPESTDIO case "$TESTS" in *%$N%*|*%functions%*|*%stdio%*|*%$NAME%*) TEST="$NAME: stdio with simple echo via internal pipe" testecho "$N" "$TEST" "stdio" "pipe" "$opts" esac N=$((N+1)) NAME=UNPIPESHORT case "$TESTS" in *%$N%*|*%functions%*|*%stdio%*|*%$NAME%*) TEST="$NAME: short form of stdio ('-') with simple echo via internal pipe" testecho "$N" "$TEST" "-" "pipe" "$opts" esac N=$((N+1)) NAME=DUALSTDIO case "$TESTS" in *%$N%*|*%functions%*|*%stdio%*|*%$NAME%*) TEST="$NAME: splitted form of stdio ('stdin!!stdout') with simple echo via internal pipe" testecho "$N" "$TEST" "stdin!!stdout" "pipe" "$opts" esac N=$((N+1)) NAME=DUALSHORTSTDIO case "$TESTS" in *%$N%*|*%functions%*|*%stdio%*|*%$NAME%*) TEST="$NAME: short splitted form of stdio ('-!!-') with simple echo via internal pipe" testecho "$N" "$TEST" "-!!-" "pipe" "$opts" esac N=$((N+1)) NAME=DUALFDS case "$TESTS" in *%$N%*|*%functions%*|*%fd%*|*%$NAME%*) TEST="$NAME: file descriptors with simple echo via internal pipe" testecho "$N" "$TEST" "0!!1" "pipe" "$opts" esac N=$((N+1)) NAME=NAMEDPIPE case "$TESTS" in *%$N%*|*%functions%*|*%pipe%*|*%$NAME%*) TEST="$NAME: simple echo via named pipe" # with MacOS, this test hangs if nonblock is not used. Is an OS bug. tp="$td/pipe$N" # note: the nonblock is required by MacOS 10.1(?), otherwise it hangs (OS bug?) testecho "$N" "$TEST" "" "pipe:$tp,nonblock" "$opts" esac N=$((N+1)) NAME=DUALPIPE case "$TESTS" in *%$N%*|*%functions%*|*%pipe%*|*%$NAME%*) TEST="$NAME: simple echo via named pipe, specified twice" tp="$td/pipe$N" testecho "$N" "$TEST" "" "pipe:$tp,nonblock!!pipe:$tp" "$opts" esac N=$((N+1)) NAME=FILE case "$TESTS" in *%$N%*|*%functions%*|*%engine%*|*%file%*|*%ignoreeof%*|*%$NAME%*) TEST="$NAME: simple echo via file" tf="$td/file$N" testecho "$N" "$TEST" "" "$tf,ignoreeof!!$tf" "$opts" esac N=$((N+1)) NAME=EXECSOCKET case "$TESTS" in *%$N%*|*%functions%*|*%exec%*|*%$NAME%*) TEST="$NAME: simple echo via exec of cat with socketpair" testecho "$N" "$TEST" "" "exec:$CAT" "$opts" esac N=$((N+1)) NAME=SYSTEMSOCKET case "$TESTS" in *%$N%*|*%functions%*|*%system%*|*%$NAME%*) TEST="$NAME: simple echo via system() of cat with socketpair" testecho "$N" "$TEST" "" "system:$CAT" "$opts" "$val_t" esac N=$((N+1)) NAME=EXECPIPES case "$TESTS" in *%$N%*|*%functions%*|*%pipe%*|*%$NAME%*) TEST="$NAME: simple echo via exec of cat with pipes" testecho "$N" "$TEST" "" "exec:$CAT,pipes" "$opts" esac N=$((N+1)) NAME=SYSTEMPIPES case "$TESTS" in *%$N%*|*%functions%*|*%pipes%*|*%$NAME%*) TEST="$NAME: simple echo via system() of cat with pipes" testecho "$N" "$TEST" "" "system:$CAT,pipes" "$opts" esac N=$((N+1)) NAME=EXECPTY case "$TESTS" in *%$N%*|*%functions%*|*%exec%*|*%pty%*|*%$NAME%*) TEST="$NAME: simple echo via exec of cat with pseudo terminal" if ! eval $NUMCOND; then :; elif ! testfeats pty >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}PTY not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else testecho "$N" "$TEST" "" "exec:$CAT,pty,$PTYOPTS" "$opts" fi esac N=$((N+1)) NAME=SYSTEMPTY case "$TESTS" in *%$N%*|*%functions%*|*%system%*|*%pty%*|*%$NAME%*) TEST="$NAME: simple echo via system() of cat with pseudo terminal" if ! eval $NUMCOND; then :; elif ! testfeats pty >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}PTY not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else testecho "$N" "$TEST" "" "system:$CAT,pty,$PTYOPTS" "$opts" fi esac N=$((N+1)) NAME=SYSTEMPIPESFDS case "$TESTS" in *%$N%*|*%functions%*|*%system%*|*%$NAME%*) TEST="$NAME: simple echo via system() of cat with pipes, non stdio" testecho "$N" "$TEST" "" "system:$CAT>&9 <&8,pipes,fdin=8,fdout=9" "$opts" esac N=$((N+1)) NAME=DUALSYSTEMFDS case "$TESTS" in *%$N%*|*%functions%*|*%system%*|*%$NAME%*) TEST="$NAME: echo via dual system() of cat" testecho "$N" "$TEST" "system:$CAT>&6,fdout=6!!system:$CAT<&7,fdin=7" "" "$opts" "$val_t" esac N=$((N+1)) # test: send EOF to exec'ed sub process, let it finish its operation, and # check if the sub process returns its data before terminating. NAME=EXECSOCKETFLUSH # idea: have socat exec'ing od; send data and EOF, and check if the od'ed data # arrives. case "$TESTS" in *%$N%*|*%functions%*|*%exec%*|*%$NAME%*) TEST="$NAME: call to od via exec with socketpair" testod "$N" "$TEST" "" "exec:$OD_C" "$opts" esac N=$((N+1)) NAME=SYSTEMSOCKETFLUSH case "$TESTS" in *%$N%*|*%functions%*|*%system%*|*%$NAME%*) TEST="$NAME: call to od via system() with socketpair" testod "$N" "$TEST" "" "system:$OD_C" "$opts" $val_t esac N=$((N+1)) NAME=EXECPIPESFLUSH case "$TESTS" in *%$N%*|*%functions%*|*%exec%*|*%$NAME%*) TEST="$NAME: call to od via exec with pipes" testod "$N" "$TEST" "" "exec:$OD_C,pipes" "$opts" esac N=$((N+1)) NAME=SYSTEMPIPESFLUSH case "$TESTS" in *%$N%*|*%functions%*|*%system%*|*%$NAME%*) TEST="$NAME: call to od via system() with pipes" testod "$N" "$TEST" "" "system:$OD_C,pipes" "$opts" "$val_t" esac N=$((N+1)) ## LATER: #NAME=EXECPTYFLUSH #case "$TESTS" in #*%$N%*|*%functions%*|*%exec%*|*%pty%*|*%$NAME%*) #TEST="$NAME: call to od via exec with pseudo terminal" #if ! testfeats pty >/dev/null; then # $PRINTF "test $F_n $TEST... ${YELLOW}PTY not available${NORMAL}\n" $N # numCANT=$((numCANT+1)) # listCANT="$listCANT $N" #else #testod "$N" "$TEST" "" "exec:$OD_C,pty,$PTYOPTS" "$opts" #fi #esac #N=$((N+1)) ## LATER: #NAME=SYSTEMPTYFLUSH #case "$TESTS" in #*%$N%*|*%functions%*|*%system%*|*%pty%*|*%$NAME%*) #TEST="$NAME: call to od via system() with pseudo terminal" #if ! testfeats pty >/dev/null; then # $PRINTF "test $F_n $TEST... ${YELLOW}PTY not available${NORMAL}\n" $N # numCANT=$((numCANT+1)) # listCANT="$listCANT $N" #else #testod "$N" "$TEST" "" "system:$OD_C,pty,$PTYOPTS" "$opts" #fi #esac #N=$((N+1)) NAME=SYSTEMPIPESFDSFLUSH case "$TESTS" in *%$N%*|*%functions%*|*%system%*|*%$NAME%*) TEST="$NAME: call to od via system() with pipes, non stdio" testod "$N" "$TEST" "" "system:$OD_C>&9 <&8,pipes,fdin=8,fdout=9" "$opts" "$val_t" esac N=$((N+1)) NAME=DUALSYSTEMFDSFLUSH case "$TESTS" in *%$N%*|*%functions%*|*%system%*|*%$NAME%*) TEST="$NAME: call to od via dual system()" testod "$N" "$TEST" "system:$OD_C>&6,fdout=6!!system:$CAT<&7,fdin=7" "pipe" "$opts" "$val_t" esac N=$((N+1)) case "$UNAME" in Linux) IPPROTO=254 ;; Darwin) IPPROTO=255 ;; *) IPPROTO=254 ;; # just a guess esac NAME=RAWIP4SELF case "$TESTS" in *%$N%*|*%functions%*|*%ip4%*|*%rawip%*|*%root%*|*%$NAME%*) TEST="$NAME: simple echo via self receiving raw IPv4 protocol" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats ip4) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}IP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! feat=$(testfeats rawip) >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}RAWIP not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else testecho "$N" "$TEST" "" "ip4:127.0.0.1:$IPPROTO" "$opts" fi esac N=$((N+1)) NAME=RAWIPX4SELF case "$TESTS" in *%$N%*|*%functions%*|*%ip4%*|*%rawip%*|*%root%*|*%$NAME%*) TEST="$NAME: simple echo via self receiving raw IP protocol, v4 by target" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats ip4) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}IP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! feat=$(testfeats rawip) >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}RAWIP not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else testecho "$N" "$TEST" "" "ip:127.0.0.1:$IPPROTO" "$opts" fi ;; # NUMCOND, feats esac N=$((N+1)) NAME=RAWIP6SELF case "$TESTS" in *%$N%*|*%functions%*|*%ip6%*|*%rawip%*|*%root%*|*%$NAME%*) TEST="$NAME: simple echo via self receiving raw IPv6 protocol" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}IP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! feat=$(testfeats rawip) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}RAWIP not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else testecho "$N" "$TEST" "" "ip6:[::1]:$IPPROTO" "$opts" fi ;; # NUMCOND, feats esac N=$((N+1)) NAME=RAWIPX6SELF case "$TESTS" in *%$N%*|*%functions%*|*%ip%*|*%ip6%*|*%rawip%*|*%rawip6%*|*%root%*|*%$NAME%*) TEST="$NAME: simple echo via self receiving raw IP protocol, v6 by target" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}IP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! feat=$(testfeats rawip) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}RAWIP not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else testecho "$N" "$TEST" "" "ip:[::1]:$IPPROTO" "$opts" fi esac N=$((N+1)) NAME=TCPSELF case "$TESTS" in *%$N%*|*%functions%*|*%$NAME%*) TEST="$NAME: echo via self connection of TCP IPv4 socket" if ! eval $NUMCOND; then :; elif [ "$UNAME" != Linux ]; then $PRINTF "test $F_n $TEST... ${YELLOW}only on Linux$NORMAL\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else #ts="127.0.0.1:$tsl" testecho "$N" "$TEST" "" "tcp:$SECONDADDR:$PORT,sp=$PORT,bind=$SECONDADDR,reuseaddr" "$opts" fi esac PORT=$((PORT+1)) N=$((N+1)) NAME=UDPSELF if ! eval $NUMCOND; then :; else case "$TESTS" in *%$N%*|*%functions%*|*%$NAME%*) TEST="$NAME: echo via self connection of UDP IPv4 socket" if [ "$UNAME" != Linux ]; then $PRINTF "test $F_n $TEST... ${YELLOW}only on Linux$NORMAL\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else testecho "$N" "$TEST" "" "udp:$SECONDADDR:$PORT,sp=$PORT,bind=$SECONDADDR" "$opts" fi esac fi # NUMCOND PORT=$((PORT+1)) N=$((N+1)) NAME=UDP6SELF case "$TESTS" in *%$N%*|*%functions%*|*%udp%*|*%udp6%*|*%ip6%*|*%$NAME%*) TEST="$NAME: echo via self connection of UDP IPv6 socket" if ! eval $NUMCOND; then :; elif [ "$UNAME" != Linux ]; then $PRINTF "test $F_n $TEST... ${YELLOW}only on Linux${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats udp ip6 >/dev/null || ! runsudp6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}UDP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/file$N" testecho "$N" "$TEST" "" "udp6:[::1]:$PORT,sp=$PORT,bind=[::1]" "$opts" fi esac PORT=$((PORT+1)) N=$((N+1)) NAME=DUALUDPSELF if ! eval $NUMCOND; then :; else case "$TESTS" in *%$N%*|*%functions%*|*%$NAME%*) TEST="$NAME: echo via two unidirectional UDP IPv4 sockets" tf="$td/file$N" p1=$PORT p2=$((PORT+1)) testecho "$N" "$TEST" "" "udp:127.0.0.1:$p2,sp=$p1!!udp:127.0.0.1:$p1,sp=$p2" "$opts" esac fi # NUMCOND PORT=$((PORT+2)) N=$((N+1)) #function testdual { # local #} NAME=UNIXSTREAM if ! eval $NUMCOND; then :; else case "$TESTS" in *%$N%*|*%functions%*|*%unix%*|*%$NAME%*) TEST="$NAME: echo via connection to UNIX domain socket" tf="$td/test$N.stdout" te="$td/test$N.stderr" ts="$td/test$N.socket" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts UNIX-LISTEN:$ts PIPE" CMD2="$TRACE $SOCAT $opts -!!- UNIX-CONNECT:$ts" printf "test $F_n $TEST... " $N $CMD1 $tf 2>"${te}1" & bg=$! # background process id waitfile "$ts" echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" rc2=$? if [ "$rc2" -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" cat "${te}1" echo "$CMD2" echo "rc=$rc2" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: diff:\n" cat "$tdiff" echo "$CMD1 &" cat "${te}1" echo "$CMD2" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $bg 2>/dev/null esac fi # NUMCOND N=$((N+1)) NAME=TCP4 if ! eval $NUMCOND; then :; else case "$TESTS" in *%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%tcp%*|*%$NAME%*) TEST="$NAME: echo via connection to TCP V4 socket" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="127.0.0.1:$tsl" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts TCP4-LISTEN:$tsl,$REUSEADDR PIPE" CMD2="$TRACE $SOCAT $opts stdin!!stdout TCP4:$ts" printf "test $F_n $TEST... " $N $CMD1 >"$tf" 2>"${te}1" & pid1=$! waittcp4port $tsl 1 echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" if [ $? -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" cat "${te}1" echo "$CMD2" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid1 2>/dev/null wait ;; esac PORT=$((PORT+1)) fi # NUMCOND N=$((N+1)) #et -xv NAME=TCP6 case "$TESTS" in *%$N%*|*%functions%*|*%ip6%*|*%ipapp%*|*%tcp%*|*%$NAME%*) TEST="$NAME: echo via connection to TCP V6 socket" if ! eval $NUMCOND; then :; elif ! testfeats tcp ip6 >/dev/null || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="[::1]:$tsl" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts TCP6-listen:$tsl,$REUSEADDR PIPE" CMD2="$TRACE $SOCAT $opts stdin!!stdout TCP6:$ts" printf "test $F_n $TEST... " $N $CMD1 >"$tf" 2>"${te}1" & pid=$! # background process id waittcp6port $tsl 1 echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" if [ $? -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "$te" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: diff:\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null fi esac PORT=$((PORT+1)) N=$((N+1)) #set +vx NAME=TCPX4 case "$TESTS" in *%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%tcp%*|*%$NAME%*) TEST="$NAME: echo via connection to TCP socket, v4 by target" if ! eval $NUMCOND; then :; elif ! testfeats tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats ip6 >/dev/null || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}IP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="127.0.0.1:$tsl" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts TCP-listen:$tsl,pf=ip4,$REUSEADDR PIPE" CMD2="$TRACE $SOCAT $opts stdin!!stdout TCP:$ts" printf "test $F_n $TEST... " $N $CMD1 >"$tf" 2>"${te}1" & pid=$! # background process id waittcp4port $tsl 1 echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" if [ $? -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "$te" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: diff:\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null fi esac PORT=$((PORT+1)) N=$((N+1)) NAME=TCPX6 case "$TESTS" in *%$N%*|*%functions%*|*%ip6%*|*%ipapp%*|*%tcp%*|*%$NAME%*) TEST="$NAME: echo via connection to TCP socket, v6 by target" if ! eval $NUMCOND; then :; elif ! testfeats tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats ip6 >/dev/null || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}IP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="[::1]:$tsl" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts TCP-listen:$tsl,pf=ip6,$REUSEADDR PIPE" CMD2="$TRACE $SOCAT $opts stdin!!stdout TCP:$ts" printf "test $F_n $TEST... " $N $CMD1 >"$tf" 2>"${te}1" & pid=$! # background process id waittcp6port $tsl 1 echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" if [ $? -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "$te" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: diff:\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null fi 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 ! testfeats tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats ip6 >/dev/null || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! feat=$(testoptions ipv6-v6only); then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="127.0.0.1:$tsl" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts TCP6-LISTEN:$tsl,ipv6-v6only=0,$REUSEADDR PIPE" CMD2="$TRACE $SOCAT $opts STDIN!!STDOUT TCP4:$ts" printf "test $F_n $TEST... " $N $CMD1 >"$tf" 2>"${te}1" & pid=$! # background process id waittcp6port $tsl 1 echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" if [ $? -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: diff:\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null fi esac PORT=$((PORT+1)) N=$((N+1)) #set -vx # 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%*) TEST="$NAME: option ipv6-v6only=1 does not listen on IPv4" if ! eval $NUMCOND; then :; elif ! testfeats tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats ip6 >/dev/null || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}IP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! feat=$(testoptions ipv6-v6only); then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="127.0.0.1:$tsl" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts TCP6-listen:$tsl,ipv6-v6only=1,$REUSEADDR PIPE" CMD2="$TRACE $SOCAT $opts stdin!!stdout TCP4:$ts" printf "test $F_n $TEST... " $N $CMD1 >"$tf" 2>"${te}1" & pid=$! # background process id waittcp6port $tsl 1 echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" if [ $? -eq 0 ]; then $PRINTF "$FAILED:\n" cat "${te}1" "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED:\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" numOK=$((numOK+1)) fi kill $pid; wait wait fi esac PORT=$((PORT+1)) N=$((N+1)) #set +vx NAME=ENV_LISTEN_4 case "$TESTS" in *%$N%*|*%functions%*|*%ip6%*|*%ipapp%*|*%tcp%*|*%$NAME%*) TEST="$NAME: env SOCAT_DEFAULT_LISTEN_IP for IPv4 preference on listen" if ! eval $NUMCOND; then :; elif ! testfeats tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats ip6 >/dev/null || ! runstcp6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! feat=$(testoptions ipv6-v6only); then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="127.0.0.1:$tsl" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts TCP-LISTEN:$tsl,$REUSEADDR PIPE" CMD2="$TRACE $SOCAT $opts stdin!!stdout TCP4:$ts" printf "test $F_n $TEST... " $N SOCAT_DEFAULT_LISTEN_IP=4 $CMD1 >"$tf" 2>"${te}1" & pid=$! # background process id waittcp4port $tsl 1 echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" if [ $? -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: diff:\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null; wait fi esac PORT=$((PORT+1)) N=$((N+1)) NAME=ENV_LISTEN_6 case "$TESTS" in *%$N%*|*%functions%*|*%ip6%*|*%ipapp%*|*%tcp%*|*%$NAME%*) TEST="$NAME: env SOCAT_DEFAULT_LISTEN_IP for IPv6 preference on listen" if ! eval $NUMCOND; then :; elif ! testfeats tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats ip6 >/dev/null || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}IP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="[::1]:$tsl" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts TCP-LISTEN:$tsl,$REUSEADDR PIPE" CMD2="$TRACE $SOCAT $opts stdin!!stdout TCP6:$ts" printf "test $F_n $TEST... " $N SOCAT_DEFAULT_LISTEN_IP=6 $CMD1 >"$tf" 2>"${te}1" & pid=$! # background process id waittcp6port $tsl 1 echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" if [ $? -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: diff:\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null; wait fi esac PORT=$((PORT+1)) N=$((N+1)) NAME=LISTEN_OPTION_4 case "$TESTS" in *%$N%*|*%functions%*|*%ip6%*|*%ipapp%*|*%tcp%*|*%$NAME%*) TEST="$NAME: option -4 for IPv4 preference on listen" if ! eval $NUMCOND; then :; elif ! testfeats tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats ip6 >/dev/null || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}IP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! feat=$(testoptions ipv6-v6only); then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="127.0.0.1:$tsl" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts -4 TCP-LISTEN:$tsl,$REUSEADDR PIPE" CMD2="$TRACE $SOCAT $opts stdin!!stdout TCP4:$ts" printf "test $F_n $TEST... " $N SOCAT_DEFAULT_LISTEN_IP=6 $CMD1 >"$tf" 2>"${te}1" & pid=$! # background process id waittcp4port $tsl 1 echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" if [ $? -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: diff:\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null; wait fi esac PORT=$((PORT+1)) N=$((N+1)) NAME=LISTEN_OPTION_6 case "$TESTS" in *%$N%*|*%functions%*|*%ip6%*|*%ipapp%*|*%tcp%*|*%$NAME%*) TEST="$NAME: option -6 for IPv6 preference on listen" if ! eval $NUMCOND; then :; elif ! testfeats tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats ip6 >/dev/null || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}IP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="[::1]:$tsl" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts -6 TCP-listen:$tsl,$REUSEADDR PIPE" CMD2="$TRACE $SOCAT $opts stdin!!stdout TCP6:$ts" printf "test $F_n $TEST... " $N SOCAT_DEFAULT_LISTEN_IP=4 $CMD1 >"$tf" 2>"${te}1" & pid=$! # background process id waittcp6port $tsl 1 echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" if [ $? -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: diff:\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null; wait wait fi # feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=LISTEN_PF_IP4 case "$TESTS" in *%$N%*|*%functions%*|*%ip6%*|*%ipapp%*|*%tcp%*|*%$NAME%*) TEST="$NAME: pf=4 overrides option -6 on listen" if ! eval $NUMCOND; then :; elif ! testfeats tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats ip6 >/dev/null || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}IP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! feat=$(testoptions ipv6-v6only); then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="127.0.0.1:$tsl" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts -6 TCP-LISTEN:$tsl,pf=ip4,$REUSEADDR PIPE" CMD2="$TRACE $SOCAT $opts stdin!!stdout TCP4:$ts" printf "test $F_n $TEST... " $N SOCAT_DEFAULT_LISTEN_IP=6 $CMD1 >"$tf" 2>"${te}1" & pid=$! # background process id waittcp4port $tsl 1 echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" if [ $? -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: diff:\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null; wait fi esac PORT=$((PORT+1)) N=$((N+1)) NAME=LISTEN_PF_IP6 case "$TESTS" in *%$N%*|*%functions%*|*%ip6%*|*%ipapp%*|*%tcp%*|*%$NAME%*) TEST="$NAME: pf=6 overrides option -4 on listen" if ! eval $NUMCOND; then :; elif ! testfeats tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats ip6 >/dev/null || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}IP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="[::1]:$tsl" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts -4 TCP-LISTEN:$tsl,pf=ip6,$REUSEADDR PIPE" CMD2="$TRACE $SOCAT $opts stdin!!stdout TCP6:$ts" printf "test $F_n $TEST... " $N SOCAT_DEFAULT_LISTEN_IP=4 $CMD1 >"$tf" 2>"${te}1" & pid=$! # background process id waittcp6port $tsl 1 echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" if [ $? -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: diff:\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null; wait fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=UDP4STREAM case "$TESTS" in *%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%udp%*|*%$NAME%*) TEST="$NAME: echo via connection to UDP V4 socket" if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="$LOCALHOST:$tsl" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts UDP4-LISTEN:$tsl,$REUSEADDR PIPE" CMD2="$TRACE $SOCAT $opts - UDP4:$ts" printf "test $F_n $TEST... " $N $CMD1 >"$tf" 2>"${te}1" & pid1=$! waitudp4port $tsl 1 echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" rc2=$? kill $pid1 2>/dev/null; wait if [ $rc2 -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" echo "$CMD1 &" cat "${te}1" echo "$CMD2" cat "${te}2" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) NAME=UDP6STREAM case "$TESTS" in *%$N%*|*%functions%*|*%ip6%*|*%ipapp%*|*%udp%*|*%$NAME%*) TEST="$NAME: echo via connection to UDP V6 socket" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats udp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}UDP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="$LOCALHOST6:$tsl" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts UDP6-LISTEN:$tsl,$REUSEADDR PIPE" CMD2="$TRACE $SOCAT $opts - UDP6:$ts" printf "test $F_n $TEST... " $N $CMD1 >"$tf" 2>"${te}1" & pid1=$! waitudp6port $tsl 1 echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" rc2=$? kill $pid1 2>/dev/null; wait if [ $rc2 -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi fi ;; # ! testfeats esac PORT=$((PORT+1)) N=$((N+1)) NAME=GOPENFILE case "$TESTS" in *%$N%*|*%functions%*|*%engine%*|*%gopen%*|*%file%*|*%ignoreeof%*|*%$NAME%*) TEST="$NAME: file opening with gopen" if ! eval $NUMCOND; then :; else tf1="$td/test$N.1.stdout" tf2="$td/test$N.2.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" echo "$da" >$tf1 CMD="$TRACE $SOCAT $opts $tf1!!/dev/null /dev/null,ignoreeof!!-" printf "test $F_n $TEST... " $N $CMD >"$tf2" 2>"$te" if [ $? -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD" cat "$te" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! diff "$tf1" "$tf2" >"$tdiff"; then $PRINTF "$FAILED: diff:\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi # NUMCOND esac N=$((N+1)) NAME=GOPENPIPE case "$TESTS" in *%$N%*|*%functions%*|*%gopen%*|*%pipe%*|*%ignoreeof%*|*%$NAME%*) TEST="$NAME: pipe opening with gopen for reading" if ! eval $NUMCOND; then :; else tp="$td/pipe$N" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD="$TRACE $SOCAT $opts $tp!!/dev/null /dev/null,ignoreeof!!$tf" printf "test $F_n $TEST... " $N #mknod $tp p # no mknod p on FreeBSD mkfifo $tp $CMD >$tf 2>"$te" & #($CMD >$tf 2>"$te" || rm -f "$tp") 2>/dev/null & bg=$! # background process id usleep $MICROS if [ ! -p "$tp" ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD" cat "$te" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else #echo "$da" >"$tp" # might hang forever echo "$da" >"$tp" & export pid=$!; (sleep 1; kill $pid 2>/dev/null) & # Solaris needs more time: sleep 1 kill "$bg" 2>/dev/null; wait if ! echo "$da" |diff - "$tf" >"$tdiff"; then if [ -s "$te" ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD" cat "$te" else $PRINTF "$FAILED: diff:\n" cat "$tdiff" fi numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi wait fi # NUMCOND esac N=$((N+1)) NAME=GOPENUNIXSTREAM case "$TESTS" in *%$N%*|*%functions%*|*%gopen%*|*%unix%*|*%listen%*|*%$NAME%*) TEST="$NAME: GOPEN on UNIX stream socket" if ! eval $NUMCOND; then :; else ts="$td/test$N.socket" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da1="test$N $(date) $RANDOM" #establish a listening unix socket in background SRV="$TRACE $SOCAT $opts -lpserver UNIX-LISTEN:\"$ts\" PIPE" #make a connection CMD="$TRACE $SOCAT $opts - $ts" $PRINTF "test $F_n $TEST... " $N eval "$SRV 2>${te}s &" pids=$! waitfile "$ts" echo "$da1" |eval "$CMD" >"${tf}1" 2>"${te}1" if [ $? -ne 0 ]; then kill "$pids" 2>/dev/null $PRINTF "$FAILED:\n" echo "$SRV &" cat "${te}s" echo "$CMD" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da1" |diff - "${tf}1" >"$tdiff"; then kill "$pids" 2>/dev/null $PRINTF "$FAILED:\n" echo "$SRV &" cat "${te}s" echo "$CMD" cat "${te}1" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi # !(rc -ne 0) wait fi # NUMCOND esac N=$((N+1)) NAME=GOPENUNIXSEQPACKET case "$TESTS" in *%$N%*|*%functions%*|*%gopen%*|*%unix%*|*%listen%*|*%seqpacket%*|*%$NAME%*) TEST="$NAME: GOPEN on UNIX seqpacket socket" if ! eval $NUMCOND; then :; else ts="$td/test$N.socket" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da1="test$N $(date) $RANDOM" #establish a listening unix socket in background SRV="$TRACE $SOCAT $opts -lpserver UNIX-LISTEN:\"$ts\",so-type=$SOCK_SEQPACKET PIPE" #make a connection CMD="$TRACE $SOCAT $opts - $ts" $PRINTF "test $F_n $TEST... " $N eval "$SRV 2>${te}s &" pids=$! waitfile "$ts" echo "$da1" |eval "$CMD" >"${tf}1" 2>"${te}1" if [ $? -ne 0 ]; then kill "$pids" 2>/dev/null $PRINTF "$FAILED:\n" echo "$SRV &" cat "${te}s" echo "$CMD" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da1" |diff - "${tf}1" >"$tdiff"; then kill "$pids" 2>/dev/null $PRINTF "$FAILED:\n" echo "$SRV &" cat "${te}s" echo "$CMD" cat "${te}1" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi # !(rc -ne 0) wait fi # NUMCOND esac N=$((N+1)) NAME=GOPENUNIXDGRAM case "$TESTS" in *%$N%*|*%functions%*|*%gopen%*|*%unix%*|*%dgram%*|*%$NAME%*) TEST="$NAME: GOPEN on UNIX datagram socket" if ! eval $NUMCOND; then :; else ts="$td/test$N.socket" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da1="test$N $(date) $RANDOM" #establish a receiving unix socket in background SRV="$TRACE $SOCAT $opts -u -lpserver UNIX-RECV:\"$ts\" file:\"$tf\",create" #make a connection CMD="$TRACE $SOCAT $opts -u - $ts" $PRINTF "test $F_n $TEST... " $N eval "$SRV 2>${te}s &" pids=$! waitfile "$ts" echo "$da1" |eval "$CMD" 2>"${te}1" waitfile -s "$tf" if [ $? -ne 0 ]; then $PRINTF "$FAILED:\n" echo "$SRV &" cat "${te}s" echo "$CMD" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da1" |diff - "${tf}" >"$tdiff"; then $PRINTF "$FAILED:\n" echo "$SRV &" cat "${te}s" echo "$CMD" cat "${te}1" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi # !(rc -ne 0) kill "$pids" 2>/dev/null; wait fi ;; # NUMCOND esac N=$((N+1)) NAME=IGNOREEOF case "$TESTS" in *%$N%*|*%functions%*|*%engine%*|*%ignoreeof%*|*%$NAME%*) TEST="$NAME: ignoreeof on file" if ! eval $NUMCOND; then :; else ti="$td/test$N.file" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD="$TRACE $SOCAT $opts -u file:\"$ti\",ignoreeof -" printf "test $F_n $TEST... " $N touch "$ti" $CMD >"$tf" 2>"$te" & bg=$! usleep 500000 echo "$da" >>"$ti" sleep 1 kill $bg 2>/dev/null; wait if ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: diff:\n" cat "$tdiff" listFAIL="$listFAIL $N" numFAIL=$((numFAIL+1)) else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND esac N=$((N+1)) NAME=IGNOREEOF_REV case "$TESTS" in *%$N%*|*%functions%*|*%engine%*|*%ignoreeof%*|*%$NAME%*) TEST="$NAME: ignoreeof on file right-to-left" if ! eval $NUMCOND; then :; else ti="$td/test$N.file" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD="$SOCAT $opts -U - file:\"$ti\",ignoreeof" printf "test $F_n $TEST... " $N touch "$ti" $CMD >"$tf" 2>"$te" & bg=$! usleep 500000 echo "$da" >>"$ti" sleep 1 kill $bg 2>/dev/null if ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: diff:\n" cat "$tdiff" listFAIL="$listFAIL $N" numFAIL=$((numFAIL+1)) else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi wait fi ;; # NUMCOND esac N=$((N+1)) NAME=EXECIGNOREEOF case "$TESTS" in *%$N%*|*%functions%*|*%engine%*|*%ignoreeof%*|*%$NAME%*) TEST="$NAME: exec against address with ignoreeof" if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" # remark: diagnostics to null, no good style CMD="$TRACE $SOCAT $opts -lf /dev/null EXEC:$TRUE /dev/null,ignoreeof" printf "test $F_n $TEST... " $N $CMD >"$tf" 2>"$te" if [ -s "$te" ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD" cat "$te" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND esac N=$((N+1)) NAME=FAKEPTY case "$TESTS" in *%$N%*|*%functions%*|*%pty%*|*%$NAME%*) TEST="$NAME: generation of pty for other processes" if ! eval $NUMCOND; then :; elif ! testfeats pty >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}PTY not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tt="$td/pty$N" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts PTY,$PTYOPTS,link=$tt PIPE" CMD2="$TRACE $SOCAT $opts - $tt,$PTYOPTS2" printf "test $F_n $TEST... " $N $CMD1 2>"${te}1" & pid=$! # background process id waitfile "$tt" # this hangs on HP-UX, so we use a timeout (echo "$da"; sleep 1) |$CMD2 >$tf 2>"${te}2" & pid2=$! #sleep 5 && kill $rc2 2>/dev/null & wait $pid2 if ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" sleep 1 echo "$CMD2" cat "${te}1" cat "${te}2" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null; wait fi ;; # NUMCOND, feats esac N=$((N+1)) NAME=O_TRUNC case "$TESTS" in *%$N%*|*%functions%*|*%$NAME%*) TEST="$NAME: option o-trunc" if ! eval $NUMCOND; then :; else ff="$td/test$N.file" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD="$TRACE $SOCAT -u $opts - open:$ff,append,o-trunc" printf "test $F_n $TEST... " $N rm -f $ff; $ECHO "prefix-\c" >$ff echo "$da" |$CMD >$tf 2>"$te" rc0=$? if ! [ $rc0 = 0 ] || ! echo "$da" |diff - $ff >"$tdiff"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD" cat "$te" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND esac N=$((N+1)) NAME=FTRUNCATE case "$TESTS" in *%$N%*|*%functions%*|*%$NAME%*) TEST="$NAME: option ftruncate" if ! eval $NUMCOND; then :; else ff="$td/test$N.file" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD="$TRACE $SOCAT -u $opts - open:$ff,append,ftruncate=0" printf "test $F_n $TEST... " $N rm -f $ff; $ECHO "prefix-\c" >$ff if ! echo "$da" |$CMD >$tf 2>"$te" || ! echo "$da" |diff - $ff >"$tdiff"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD" cat "$te" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND esac N=$((N+1)) NAME=RIGHTTOLEFT case "$TESTS" in *%$N%*|*%functions%*|*%$NAME%*) TEST="$NAME: unidirectional throughput from stdin to stdout, right to left" testecho "$N" "$TEST" "stdout" "stdin" "$opts -U" esac N=$((N+1)) NAME=CHILDDEFAULT case "$TESTS" in *%$N%*|*%functions%*|*%$NAME%*) if ! eval $NUMCOND; then :; else TEST="$NAME: child process default properties" tf="$td/test$N.stdout" te="$td/test$N.stderr" CMD="$TRACE $SOCAT $opts -u exec:$PROCAN -" printf "test $F_n $TEST... " $N $CMD >$tf 2>$te MYPID=`expr "\`grep "process id =" $tf\`" : '[^0-9]*\([0-9]*\).*'` MYPPID=`expr "\`grep "process parent id =" $tf\`" : '[^0-9]*\([0-9]*\).*'` MYPGID=`expr "\`grep "process group id =" $tf\`" : '[^0-9]*\([0-9]*\).*'` MYSID=`expr "\`grep "process session id =" $tf\`" : '[^0-9]*\([0-9]*\).*'` #echo "PID=$MYPID, PPID=$MYPPID, PGID=$MYPGID, SID=$MYSID" if [ "$MYPID" = "$MYPPID" -o "$MYPID" = "$MYPGID" -o "$MYPID" = "$MYSID" -o \ "$MYPPID" = "$MYPGID" -o "$MYPPID" = "$MYSID" -o "$MYPGID" = "$MYSID" ]; then $PRINTF "$FAILED:\n" echo "$CMD" cat "$te" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" numOK=$((numOK+1)) fi fi ;; # NUMCOND esac N=$((N+1)) NAME=CHILDSETSID case "$TESTS" in *%$N%*|*%functions%*|*%$NAME%*) TEST="$NAME: child process with setsid" if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" CMD="$TRACE $SOCAT $opts -u exec:$PROCAN,setsid -" printf "test $F_n $TEST... " $N $CMD >$tf 2>$te MYPID=`grep "process id =" $tf |(expr "\`cat\`" : '[^0-9]*\([0-9]*\).*')` MYPPID=`grep "process parent id =" $tf |(expr "\`cat\`" : '[^0-9]*\([0-9]*\).*')` MYPGID=`grep "process group id =" $tf |(expr "\`cat\`" : '[^0-9]*\([0-9]*\).*')` MYSID=`grep "process session id =" $tf |(expr "\`cat\`" : '[^0-9]*\([0-9]*\).*')` #$ECHO "\nPID=$MYPID, PPID=$MYPPID, PGID=$MYPGID, SID=$MYSID" # PID, PGID, and SID must be the same if [ "$MYPID" = "$MYPPID" -o \ "$MYPID" != "$MYPGID" -o "$MYPID" != "$MYSID" ]; then $PRINTF "$FAILED\n" echo "$CMD" cat "$te" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" numOK=$((numOK+1)) fi fi ;; # NUMCOND esac N=$((N+1)) NAME=MAINSETSID case "$TESTS" in *%$N%*|*%functions%*|*%$NAME%*) TEST="$NAME: main process with setsid" if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" CMD="$TRACE $SOCAT $opts -U -,setsid exec:$PROCAN" printf "test $F_n $TEST... " $N $CMD >$tf 2>$te MYPID=`grep "process id =" $tf |(expr "\`cat\`" : '[^0-9]*\([0-9]*\).*')` MYPPID=`grep "process parent id =" $tf |(expr "\`cat\`" : '[^0-9]*\([0-9]*\).*')` MYPGID=`grep "process group id =" $tf |(expr "\`cat\`" : '[^0-9]*\([0-9]*\).*')` MYSID=`grep "process session id =" $tf |(expr "\`cat\`" : '[^0-9]*\([0-9]*\).*')` #$ECHO "\nPID=$MYPID, PPID=$MYPPID, PGID=$MYPGID, SID=$MYSID" # PPID, PGID, and SID must be the same if [ "$MYPID" = "$MYPPID" -o \ "$MYPPID" != "$MYPGID" -o "$MYPPID" != "$MYSID" ]; then $PRINTF "$FAILED\n" echo "$CMD" cat "$te" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" numOK=$((numOK+1)) fi fi ;; # NUMCOND esac N=$((N+1)) NAME=OPENSSL_TCP4 case "$TESTS" in *%$N%*|*%functions%*|*%openssl%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*) TEST="$NAME: openssl connect" if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! type openssl >/dev/null 2>&1; then $PRINTF "test $F_n $TEST... ${YELLOW}openssl executable not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP/IPv4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" init_openssl_s_server CMD2="$TRACE $SOCAT $opts exec:'openssl s_server $OPENSSL_S_SERVER_4 -accept "$PORT" -quiet -cert testsrv.pem' pipe" CMD="$TRACE $SOCAT $opts - openssl:$LOCALHOST:$PORT,pf=ip4,verify=0,$SOCAT_EGD" printf "test $F_n $TEST... " $N eval "$CMD2 2>\"${te}1\" &" pid=$! # background process id # this might timeout when openssl opens tcp46 port like " :::$PORT" waittcp4port $PORT #echo "$da" |$CMD >$tf 2>"${te}2" #note: with about OpenSSL 1.1 s_server lost the half close feature, thus: (echo "$da"; psleep 0.1) |$CMD >$tf 2>"${te}2" if ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD2 &" echo "$CMD" cat "${te}1" cat "${te}2" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null; wait fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=OPENSSLLISTEN_TCP4 case "$TESTS" in *%$N%*|*%functions%*|*%openssl%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*) TEST="$NAME: openssl listen" if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats listen tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP/IPv4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD2="$TRACE $SOCAT $opts OPENSSL-LISTEN:$PORT,pf=ip4,$REUSEADDR,$SOCAT_EGD,cert=testsrv.crt,key=testsrv.key,verify=0 pipe" CMD="$TRACE $SOCAT $opts - openssl:$LOCALHOST:$PORT,pf=ip4,verify=0,$SOCAT_EGD" printf "test $F_n $TEST... " $N eval "$CMD2 2>\"${te}1\" &" pid=$! # background process id waittcp4port $PORT echo "$da" |$CMD >$tf 2>"${te}2" if ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD2 &" echo "$CMD" cat "${te}1" cat "${te}2" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null wait fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=OPENSSLLISTEN_TCP6 case "$TESTS" in *%$N%*|*%functions%*|*%openssl%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%$NAME%*) TEST="$NAME: openssl listen" if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats listen tcp ip6 >/dev/null || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP/IPv6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD2="$TRACE $SOCAT $opts OPENSSL-LISTEN:$PORT,pf=ip6,$REUSEADDR,$SOCAT_EGD,cert=testsrv.crt,key=testsrv.key,verify=0 pipe" CMD="$TRACE $SOCAT $opts - openssl:$LOCALHOST6:$PORT,verify=0,$SOCAT_EGD" printf "test $F_n $TEST... " $N eval "$CMD2 2>\"${te}1\" &" pid=$! # background process id waittcp6port $PORT echo "$da" |$CMD >$tf 2>"${te}2" if ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD2 &" echo "$CMD" cat "${te}1" cat "${te}2" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null wait fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) while read NAMEKEYW FEAT RUNS TESTTMPL PEERTMPL WAITTMPL; do if [ -z "$NAMEKEYW" ] || [[ "$NAMEKEYW" == \#* ]]; then continue; fi export ts="$td/test$N.socket" WAITTMPL="$(echo "$WAITTMPL" |sed -e 's/\040/ /g')" TESTADDR=$(eval echo $TESTTMPL) PEERADDR=$(eval echo $PEERTMPL) WAITCMD=$(eval echo $WAITTMPL) TESTKEYW=${TESTADDR%%:*} feat=$(tolower $FEAT) # does our address implementation support halfclose? NAME=${NAMEKEYW}_HALFCLOSE case "$TESTS" in *%$N%*|*%functions%*|*%$feat%*|*%socket%*|*%halfclose%*|*%$NAME%*) TEST="$NAME: $TESTKEYW half close" # have a "peer" socat "peer" that executes "$OD_C" and see if EOF on the # connecting socat brings the result of od if ! eval $NUMCOND; then :; elif [ "$FEAT" != ',' ] && ! testfeats "$FEAT" >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$FEAT not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! runs$RUNS >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$RUNS not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD2="$TRACE $SOCAT $opts \"$PEERADDR\" EXEC:'$OD_C'" CMD="$TRACE $SOCAT -T1 $opts -t 1 - $TESTADDR" printf "test $F_n $TEST... " $N eval "$CMD2 2>\"${te}1\" &" pid=$! # background process id $WAITCMD echo "$da" |$CMD >$tf 2>"${te}2" if ! echo "$da" |$OD_C |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD2 &" echo "$CMD" cat "${te}1" cat "${te}2" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null wait fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) done <<<" UNIXCONNECT , unix UNIX-CONNECT:\$ts UNIX-LISTEN:\$ts waitfile\040\$ts UNIXCLIENT , unix UNIX-CLIENT:\$ts UNIX-LISTEN:\$ts waitfile\040\$ts GOPEN_UNIXSTREAM , unix GOPEN:\$ts UNIX-LISTEN:\$ts waitfile\040\$ts UNIXLISTEN , unix UNIX-LISTEN:\$ts UNIX-CONNECT:\$ts,retry=3 sleep\040\1 TCP4CONNECT , tcp4 TCP4-CONNECT:\$LOCALHOST:\$PORT TCP4-LISTEN:\$PORT,$REUSEADDR waittcp4port\040\$PORT TCP4LISTEN , tcp4 TCP4-LISTEN:\$PORT,$REUSEADDR TCP4-CONNECT:\$LOCALHOST:\$PORT,retry=3 TCP6CONNECT , tcp6 TCP6-CONNECT:\$LOCALHOST6:\$PORT TCP6-LISTEN:\$PORT,$REUSEADDR waittcp6port\040\$PORT TCP6LISTEN , tcp6 TCP6-LISTEN:\$PORT,$REUSEADDR TCP6-CONNECT:\$LOCALHOST6:\$PORT,retry=3 OPENSSL4CLIENT OPENSSL tcp4 OPENSSL:\$LOCALHOST:\$PORT,verify=0 OPENSSL-LISTEN:\$PORT,$REUSEADDR,$SOCAT_EGD,cert=testsrv.crt,key=testsrv.key,verify=0 waittcp4port\040\$PORT OPENSSL4SERVER OPENSSL tcp4 OPENSSL-LISTEN:\$PORT,$SOCAT_EGD,cert=testsrv.crt,key=testsrv.key,verify=0 OPENSSL:\$LOCALHOST:\$PORT,$REUSEADDR,verify=0,retry=3 OPENSSL6CLIENT OPENSSL tcp6 OPENSSL:\$LOCALHOST6:\$PORT,pf=ip6,verify=0 OPENSSL-LISTEN:\$PORT,pf=ip6,$REUSEADDR,$SOCAT_EGD,cert=testsrv.crt,key=testsrv.key,verify=0 waittcp6port\040\$PORT OPENSSL6SERVER OPENSSL tcp6 OPENSSL-LISTEN:\$PORT,pf=ip6,$SOCAT_EGD,cert=testsrv.crt,key=testsrv.key,verify=0 OPENSSL:\$LOCALHOST6:\$PORT,pf=ip6,$REUSEADDR,verify=0,retry=3 " NAME=OPENSSL_SERVERAUTH case "$TESTS" in *%$N%*|*%functions%*|*%openssl%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*) TEST="$NAME: OpenSSL server authentication (hostname)" if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats listen tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP/IPv4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv gentestcert testcli tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts OPENSSL-LISTEN:$PORT,$REUSEADDR,$SOCAT_EGD,cert=testsrv.crt,key=testsrv.key,verify=0 pipe" CMD1="$TRACE $SOCAT $opts - OPENSSL:$LOCALHOST:$PORT,verify=1,cafile=testsrv.crt,$SOCAT_EGD" printf "test $F_n $TEST... " $N eval "$CMD0 2>\"${te}0\" &" pid=$! # background process id waittcp4port $PORT echo "$da" |$CMD1 >$tf 2>"${te}1" if ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD0 &" cat "${te}0" echo "$CMD1" cat "${te}1" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null wait fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=OPENSSL_CLIENTAUTH case "$TESTS" in *%$N%*|*%functions%*|*%openssl%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*) TEST="$NAME: openssl client authentication" if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats listen tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP/IPv4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv gentestcert testcli tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD2="$TRACE $SOCAT $opts OPENSSL-LISTEN:$PORT,$REUSEADDR,verify=1,cert=testsrv.crt,key=testsrv.key,cafile=testcli.crt,$SOCAT_EGD pipe" CMD="$TRACE $SOCAT $opts - openssl:$LOCALHOST:$PORT,verify=0,cert=testcli.crt,key=testcli.key,$SOCAT_EGD" printf "test $F_n $TEST... " $N eval "$CMD2 2>\"${te}1\" &" pid=$! # background process id waittcp4port $PORT echo "$da" |$CMD >$tf 2>"${te}2" if ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD2 &" echo "$CMD" cat "${te}1" cat "${te}2" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null wait fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=OPENSSL_FIPS_BOTHAUTH case "$TESTS" in *%$N%*|*%functions%*|*%openssl%*|*%fips%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*) TEST="$NAME: OpenSSL+FIPS client and server authentication" if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats listen tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP/IPv4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testoptions fips >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL/FIPS not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else OPENSSL_FIPS=1 gentestcert testsrvfips OPENSSL_FIPS=1 gentestcert testclifips tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD2="$TRACE $SOCAT $opts OPENSSL-LISTEN:$PORT,$REUSEADDR,fips,$SOCAT_EGD,cert=testsrvfips.crt,key=testsrvfips.key,cafile=testclifips.crt pipe" CMD="$TRACE $SOCAT $opts - openssl:$LOCALHOST:$PORT,fips,verify=1,cert=testclifips.crt,key=testclifips.key,cafile=testsrvfips.crt,$SOCAT_EGD" printf "test $F_n $TEST... " $N eval "$CMD2 2>\"${te}1\" &" pid=$! # background process id waittcp4port $PORT echo "$da" |$CMD >$tf 2>"${te}2" if ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD2 &" echo "$CMD" cat "${te}1" cat "${te}2" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null wait fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=OPENSSL_COMPRESS case "$TESTS" in *%$N%*|*%functions%*|*%openssl%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*) TEST="$NAME: OpenSSL compression" if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats listen tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP/IPv4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testoptions openssl-compress >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL compression option not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv printf "test $F_n $TEST... " $N tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" success=yes for srccompr in '' compress=auto compress=none; do for dstcompr in '' compress=auto compress=none; do CMD2="$TRACE $SOCAT $opts OPENSSL-LISTEN:$PORT,pf=ip4,$REUSEADDR,$SOCAT_EGD,cert=testsrv.crt,key=testsrv.key,verify=0,$dstcompr pipe" CMD="$TRACE $SOCAT $opts - openssl:$LOCALHOST:$PORT,pf=ip4,verify=0,$SOCAT_EGD,$srccompr" eval "$CMD2 2>\"${te}1\" &" pid=$! # background process id waittcp4port $PORT echo "$da" | $CMD >$tf 2>"${te}2" kill $pid 2>/dev/null if ! echo "$da" |diff - "$tf" >"$tdiff"; then success= break fi done done if test -z "$success"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD2 &" echo "$CMD" cat "${te}1" cat "${te}2" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=SOCKS4CONNECT_TCP4 case "$TESTS" in *%$N%*|*%functions%*|*%socks%*|*%socks4%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*) TEST="$NAME: socks4 connect over TCP/IPv4" if ! eval $NUMCOND; then :; elif ! testfeats socks4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}SOCKS4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats listen tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP/IPv4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')" # we have a normal tcp echo listening - so the socks header must appear in answer CMD2="$TRACE $SOCAT $opts TCP4-L:$PORT,$REUSEADDR exec:\"./socks4echo.sh\"" CMD="$TRACE $SOCAT $opts - socks4:$LOCALHOST:32.98.76.54:32109,pf=ip4,socksport=$PORT",socksuser="nobody" printf "test $F_n $TEST... " $N eval "$CMD2 2>\"${te}1\" &" pid=$! # background process id waittcp4port $PORT 1 echo "$da" |$CMD >$tf 2>"${te}2" if ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD2 &" echo "$CMD" cat "${te}1" cat "${te}2" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null wait fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=SOCKS4CONNECT_TCP6 case "$TESTS" in *%$N%*|*%functions%*|*%socks%*|*%socks4%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%$NAME%*) TEST="$NAME: socks4 connect over TCP/IPv6" if ! eval $NUMCOND; then :; elif ! testfeats socks4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}SOCKS4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats listen tcp ip6 >/dev/null || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP/IPv6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')" # we have a normal tcp echo listening - so the socks header must appear in answer CMD2="$TRACE $SOCAT $opts TCP6-L:$PORT,$REUSEADDR exec:\"./socks4echo.sh\"" CMD="$TRACE $SOCAT $opts - socks4:$LOCALHOST6:32.98.76.54:32109,socksport=$PORT",socksuser="nobody" printf "test $F_n $TEST... " $N eval "$CMD2 2>\"${te}1\" &" pid=$! # background process id waittcp6port $PORT 1 echo "$da" |$CMD >$tf 2>"${te}2" if ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD2 &" echo "$CMD" cat "${te}1" cat "${te}2" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null wait fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=SOCKS4ACONNECT_TCP4 case "$TESTS" in *%$N%*|*%functions%*|*%socks%*|*%socks4a%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*) TEST="$NAME: socks4a connect over TCP/IPv4" if ! eval $NUMCOND; then :; elif ! testfeats socks4a >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}SOCKS4A not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats listen tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP/IPv4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')" # we have a normal tcp echo listening - so the socks header must appear in answer CMD2="$TRACE $SOCAT $opts TCP4-L:$PORT,$REUSEADDR exec:\"./socks4a-echo.sh\"" CMD="$TRACE $SOCAT $opts - socks4a:$LOCALHOST:localhost:32109,pf=ip4,socksport=$PORT",socksuser="nobody" printf "test $F_n $TEST... " $N eval "$CMD2 2>\"${te}1\" &" pid=$! # background process id waittcp4port $PORT 1 echo "$da" |$CMD >$tf 2>"${te}2" if ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD2 &" echo "$CMD" cat "${te}1" cat "${te}2" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null wait fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=SOCKS4ACONNECT_TCP6 case "$TESTS" in *%$N%*|*%functions%*|*%socks%*|*%socks4a%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%$NAME%*) TEST="$NAME: socks4a connect over TCP/IPv6" if ! eval $NUMCOND; then :; elif ! testfeats socks4a >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}SOCKS4A not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats listen tcp ip6 >/dev/null || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP/IPv6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')" # we have a normal tcp echo listening - so the socks header must appear in answer CMD2="$TRACE $SOCAT $opts TCP6-L:$PORT,$REUSEADDR exec:\"./socks4a-echo.sh\"" CMD="$TRACE $SOCAT $opts - socks4a:$LOCALHOST6:localhost:32109,socksport=$PORT",socksuser="nobody" printf "test $F_n $TEST... " $N eval "$CMD2 2>\"${te}1\" &" pid=$! # background process id waittcp6port $PORT 1 echo "$da" |$CMD >$tf 2>"${te}2" if ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD2 &" echo "$CMD" cat "${te}1" cat "${te}2" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null wait fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=PROXYCONNECT_TCP4 case "$TESTS" in *%$N%*|*%functions%*|*%proxyconnect%*|*%proxy%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*) TEST="$NAME: proxy connect over TCP/IPv4" if ! eval $NUMCOND; then :; elif ! testfeats proxy >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}PROXY not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats listen tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP/IPv4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else ts="$td/test$N.sh" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')" #CMD2="$TRACE $SOCAT tcp4-l:$PORT,crlf SYSTEM:\"read; read; $ECHO \\\"HTTP/1.0 200 OK\n\\\"; cat\"" CMD2="$TRACE $SOCAT $opts TCP4-L:$PORT,$REUSEADDR,crlf exec:\"/usr/bin/env bash proxyecho.sh\"" CMD="$TRACE $SOCAT $opts - proxy:$LOCALHOST:127.0.0.1:1000,pf=ip4,proxyport=$PORT" printf "test $F_n $TEST... " $N eval "$CMD2 2>\"${te}2\" &" pid=$! # background process id waittcp4port $PORT 1 echo "$da" |$CMD >"$tf" 2>"${te}1" if ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD2 &" echo "$CMD" cat "${te}1" cat "${te}2" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null wait fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=PROXYCONNECT_TCP6 case "$TESTS" in *%$N%*|*%functions%*|*%proxyconnect%*|*%proxy%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%$NAME%*) TEST="$NAME: proxy connect over TCP/IPv6" if ! eval $NUMCOND; then :; elif ! testfeats proxy >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}PROXY not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats listen tcp ip6 >/dev/null || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP/IPv6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else ts="$td/test$N.sh" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')" #CMD2="$TRACE $SOCAT $opts tcp6-l:$PORT,crlf SYSTEM:\"read; read; $ECHO \\\"HTTP/1.0 200 OK\n\\\"; cat\"" CMD2="$TRACE $SOCAT $opts TCP6-L:$PORT,$REUSEADDR,crlf exec:\"/usr/bin/env bash proxyecho.sh\"" CMD="$TRACE $SOCAT $opts - proxy:$LOCALHOST6:127.0.0.1:1000,proxyport=$PORT" printf "test $F_n $TEST... " $N eval "$CMD2 2>\"${te}2\" &" pid=$! # background process id waittcp6port $PORT 1 echo "$da" |$CMD >"$tf" 2>"${te}1" if ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD2 &" echo "$CMD" cat "${te}1" cat "${te}2" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null wait fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=TCP4NOFORK case "$TESTS" in *%$N%*|*%functions%*|*%$NAME%*) TEST="$NAME: echo via connection to TCP V4 socket with nofork'ed exec" if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="127.0.0.1:$tsl" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts TCP4-LISTEN:$tsl,$REUSEADDR exec:$CAT,nofork" CMD2="$TRACE $SOCAT $opts stdin!!stdout TCP4:$ts" printf "test $F_n $TEST... " $N #$CMD1 >"$tf" 2>"${te}1" & $CMD1 >/dev/null 2>"${te}1" & waittcp4port $tsl #usleep $MICROS echo "$da" |$CMD2 >"$tf" 2>>"${te}2" if [ $? -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) NAME=EXECCATNOFORK case "$TESTS" in *%$N%*|*%functions%*|*%$NAME%*) TEST="$NAME: simple echo via exec of cat with nofork" testecho "$N" "$TEST" "" "exec:$CAT,nofork" "$opts" esac N=$((N+1)) NAME=SYSTEMCATNOFORK case "$TESTS" in *%$N%*|*%functions%*|*%$NAME%*) TEST="$NAME: simple echo via system() of cat with nofork" testecho "$N" "$TEST" "" "system:$CAT,nofork" "$opts" esac N=$((N+1)) NAME=NOFORKSETSID case "$TESTS" in *%$N%*|*%functions%*|*%$NAME%*) TEST="$NAME: simple echo via exec() of cat with nofork and setsid" testecho "$N" "$TEST" "" "system:$CAT,nofork,setsid" "$opts" esac N=$((N+1)) #============================================================================== #TEST="$NAME: echo via 'connection' to UDP V4 socket" #if ! eval $NUMCOND; then :; else #tf="$td/file$N" #tsl=65534 #ts="127.0.0.1:$tsl" #da="test$N $(date) $RANDOM" #$TRACE $SOCAT UDP-listen:$tsl,$REUSEADDR PIPE & #sleep 2 #echo "$da" |$TRACE $SOCAT stdin!!stdout UDP:$ts >"$tf" #if [ $? -eq 0 ] && echo "$da" |diff "$tf" -; then # $ECHO "... test $N succeeded" # numOK=$((numOK+1)) #else # $ECHO "*** test $N $FAILED" # numFAIL=$((numFAIL+1)) # listFAIL="$listFAIL $N" #fi #fi ;; # NUMCOND #N=$((N+1)) #============================================================================== # TEST 4 - simple echo via new file #if ! eval $NUMCOND; then :; else #N=4 #tf="$td/file$N" #tp="$td/pipe$N" #da="test$N $(date) $RANDOM" #rm -f "$tf.tmp" #echo "$da" |$TRACE $SOCAT - FILE:$tf.tmp,ignoreeof >"$tf" #if [ $? -eq 0 ] && echo "$da" |diff "$tf" -; then # $ECHO "... test $N succeeded" # numOK=$((numOK+1)) #else # $ECHO "*** test $N $FAILED" # numFAIL=$((numFAIL+1)) # listFAIL="$listFAIL $N" #fi #fi ;; # NUMCOND #============================================================================== NAME=TOTALTIMEOUT case "$TESTS" in *%$N%*|*%functions%*|*%engine%*|*%timeout%*|*%$NAME%*) TEST="$NAME: socat inactivity timeout" if ! eval $NUMCOND; then :; else #set -vx tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')" CMD2="$TRACE $SOCAT $opts -T 1 TCP4-LISTEN:$PORT,$REUSEADDR pipe" CMD="$TRACE $SOCAT $opts - tcp4-connect:$LOCALHOST:$PORT" printf "test $F_n $TEST... " $N eval "$CMD2 2>${te}1 &" pid=$! # background process id waittcp4port $PORT 1 (echo "$da"; sleep 2; echo X) |$CMD >"$tf" 2>"${te}2" if ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD2 &" echo "$CMD" cat "${te}1" cat "${te}2" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null wait #set +vx fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) NAME=IGNOREEOF+TOTALTIMEOUT case "$TESTS" in *%$N%*|*%functions%*|*%engine%*|*%timeout%*|*%ignoreeof%*|*%$NAME%*) TEST="$NAME: ignoreeof and inactivity timeout" if ! eval $NUMCOND; then :; else #set -vx ti="$td/test$N.file" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD="$TRACE $SOCAT $opts -T 2 -u file:\"$ti\",ignoreeof -" printf "test $F_n $TEST... " $N touch "$ti" $CMD >"$tf" 2>"$te" & bg=$! # background process id psleep 0.5 echo "$da" >>"$ti" sleep 4 echo X >>"$ti" sleep 1 kill $bg 2>/dev/null if ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD &" cat "$te" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "$te"; fi numOK=$((numOK+1)) fi wait fi ;; # NUMCOND, feats esac N=$((N+1)) NAME=PROXY2SPACES case "$TESTS" in *%$N%*|*%functions%*|*%proxy%*|*%$NAME%*) TEST="$NAME: proxy connect accepts status with multiple spaces" if ! eval $NUMCOND; then :; elif ! testfeats proxy >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}PROXY not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else ts="$td/test$N.sh" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')" #CMD2="$TRACE $SOCAT $opts tcp-l:$PORT,crlf SYSTEM:\"read; read; $ECHO \\\"HTTP/1.0 200 OK\n\\\"; cat\"" CMD2="$TRACE $SOCAT $opts tcp4-l:$PORT,reuseaddr,crlf exec:\"/usr/bin/env bash proxyecho.sh -w 2\"" CMD="$TRACE $SOCAT $opts - proxy:$LOCALHOST:127.0.0.1:1000,pf=ip4,proxyport=$PORT" printf "test $F_n $TEST... " $N eval "$CMD2 2>\"${te}1\" &" pid=$! # background process id waittcp4port $PORT 1 echo "$da" |$CMD >"$tf" 2>"${te}2" if ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD2 &" echo "$CMD" cat "${te}1" cat "${te}2" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null wait fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=BUG-UNISTDIO case "$TESTS" in *%$N%*|*%functions%*|*%$NAME%*) TEST="$NAME: for bug with address options on both stdin/out in unidirectional mode" if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" ff="$td/test$N.file" printf "test $F_n $TEST... " $N >"$ff" #$TRACE $SOCAT $opts -u /dev/null -,setlk <"$ff" 2>"$te" CMD="$TRACE $SOCAT $opts -u /dev/null -,setlk" $CMD <"$ff" 2>"$te" if [ "$?" -eq 0 ]; then $PRINTF "$OK\n" numOK=$((numOK+1)) else if [ "$UNAME" = "Linux" ]; then $PRINTF "$FAILED\n" echo "$CMD" cat "$te" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "${YELLOW}failed (don't care)${NORMAL}\n" numCANT=$((numCANT+1)) listCANT="$listCANT $N" fi fi fi ;; # NUMCOND esac N=$((N+1)) NAME=SINGLEEXECOUTSOCKETPAIR case "$TESTS" in *%$N%*|*%functions%*|*%$NAME%*) TEST="$NAME: inheritance of stdout to single exec with socketpair" testecho "$N" "$TEST" "-!!exec:cat" "" "$opts" 1 esac N=$((N+1)) NAME=SINGLEEXECOUTPIPE case "$TESTS" in *%$N%*|*%functions%*|*%$NAME%*) TEST="$NAME: inheritance of stdout to single exec with pipe" testecho "$N" "$TEST" "-!!exec:cat,pipes" "" "$opts" 1 esac N=$((N+1)) NAME=SINGLEEXECOUTPTY case "$TESTS" in *%$N%*|*%functions%*|*%pty%*|*%$NAME%*) TEST="$NAME: inheritance of stdout to single exec with pty" if ! eval $NUMCOND; then :; elif ! testfeats pty >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}PTY not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else testecho "$N" "$TEST" "-!!exec:cat,pty,raw" "" "$opts" 1 fi ;; # NUMCOND, feats esac N=$((N+1)) NAME=SINGLEEXECINSOCKETPAIR case "$TESTS" in *%$N%*|*%functions%*|*%$NAME%*) TEST="$NAME: inheritance of stdin to single exec with socketpair" testecho "$N" "$TEST" "exec:cat!!-" "" "$opts" esac N=$((N+1)) NAME=SINGLEEXECINPIPE case "$TESTS" in *%$N%*|*%functions%*|*%$NAME%*) TEST="$NAME: inheritance of stdin to single exec with pipe" testecho "$N" "$TEST" "exec:cat,pipes!!-" "" "$opts" esac N=$((N+1)) NAME=SINGLEEXECINPTYDELAY case "$TESTS" in *%$N%*|*%functions%*|*%pty%*|*%$NAME%*) TEST="$NAME: inheritance of stdin to single exec with pty, with delay" if ! eval $NUMCOND; then :; elif ! testfeats pty >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}PTY not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else testecho "$N" "$TEST" "exec:cat,pty,raw!!-" "" "$opts" $MISCDELAY fi ;; # NUMCOND, feats esac N=$((N+1)) NAME=SINGLEEXECINPTY case "$TESTS" in *%$N%*|*%functions%*|*%pty%*|*%$NAME%*) TEST="$NAME: inheritance of stdin to single exec with pty" if ! eval $NUMCOND; then :; elif ! testfeats pty >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}PTY not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else # T value needed (only) by AIX testecho "$N" "$TEST" "exec:cat,pty,raw!!-" "" "$opts" 0.1 fi ;; # NUMCOND, feats esac N=$((N+1)) NAME=READLINE #set -vx case "$TESTS" in *%$N%*|*%functions%*|*%pty%*|*%readline%*|*%$NAME%*) TEST="$NAME: readline with password and sigint" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats readline pty); then $PRINTF "test $F_n $TEST... ${YELLOW}$(echo "$feat"| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else SAVETERM="$TERM"; TERM= # 'cause konsole might print controls even in raw SAVEMICS=$MICROS #MICROS=2000000 ts="$td/test$N.sh" to="$td/test$N.stdout" tpi="$td/test$N.inpipe" tpo="$td/test$N.outpipe" te="$td/test$N.stderr" tr="$td/test$N.ref" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')" # the feature that we really want to test is in the readline.sh script: CMD="$TRACE $SOCAT $opts -t1 open:$tpi,nonblock!!open:$tpo exec:\"./readline.sh -nh ./readline-test.sh\",pty,ctty,setsid,raw,echo=0,isig" #echo "$CMD" >"$ts" #chmod a+x "$ts" printf "test $F_n $TEST... " $N rm -f "$tpi" "$tpo" mkfifo "$tpi" touch "$tpo" # # during development of this test, the following command line succeeded: # (sleep 1; $ECHO "user\n\c"; sleep 1; $ECHO "password\c"; sleep 1; $ECHO "\n\c"; sleep 1; $ECHO "test 1\n\c"; sleep 1; $ECHO "\003\c"; sleep 1; $ECHO "test 2\n\c"; sleep 1; $ECHO "exit\n\c"; sleep 1) |$TRACE $SOCAT -d -d -d -d -lf/tmp/$USER/debug1 -v -x - exec:'./readline.sh ./readline-test.sh',pty,ctty,setsid,raw,echo=0,isig # # the following cat, in case of socat failure, reads the pipe to prevent below writer from hanging PATH=${SOCAT%socat}:$PATH eval "$CMD 2>$te || cat $tpi >/dev/null &" pid=$! # background process id usleep $MICROS ( usleep $((3*MICROS)) $ECHO "user\n\c" usleep $MICROS $ECHO "password\c" usleep $MICROS $ECHO "\n\c" usleep $MICROS $ECHO "test 1\n\c" usleep $MICROS $ECHO "\003\c" usleep $MICROS $ECHO "test 2\n\c" usleep $MICROS $ECHO "exit\n\c" usleep $MICROS ) >"$tpi" cat >$tr < test 1 executing test 1 prog> ./readline-test.sh got SIGINT test 2 executing test 2 prog> exit EOF #0 if ! sed 's/.*\r//g' "$tpo" |diff -q "$tr" - >/dev/null 2>&1; then #0 if ! sed 's/.*'"$($ECHO '\r\c')"'//dev/null 2>&1; then wait if ! tr "$($ECHO '\r \c')" "% " <$tpo |sed 's/%$//g' |sed 's/.*%//g' |diff "$tr" - >"$tdiff" 2>&1; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD" cat "$te" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null # necc on OpenBSD wait MICROS=$SAVEMICS TERM="$SAVETERM" fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=GENDERCHANGER case "$TESTS" in *%$N%*|*%functions%*|*%$NAME%*) TEST="$NAME: TCP4 \"gender changer\"" 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" # this is the server in the protected network that we want to reach CMD1="$TRACE $SOCAT -lpserver $opts tcp4-l:$PORT,reuseaddr,bind=$LOCALHOST echo" # this is the double client in the protected network CMD2="$TRACE $SOCAT -lp2client $opts tcp4:$LOCALHOST:$((PORT+1)),retry=10,interval=1 tcp4:$LOCALHOST:$PORT" # this is the double server in the outside network CMD3="$TRACE $SOCAT -lp2server $opts tcp4-l:$((PORT+2)),reuseaddr,bind=$LOCALHOST tcp4-l:$((PORT+1)),reuseaddr,bind=$LOCALHOST" # this is the outside client that wants to use the protected server CMD4="$TRACE $SOCAT -lpclient $opts -t1 - tcp4:$LOCALHOST:$((PORT+2))" printf "test $F_n $TEST... " $N eval "$CMD1 2>${te}1 &" pid1=$! eval "$CMD2 2>${te}2 &" pid2=$! eval "$CMD3 2>${te}3 &" pid3=$! waittcp4port $PORT 1 && waittcp4port $((PORT+2)) 1 sleep 1 echo "$da" |$CMD4 >$tf 2>"${te}4" if ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2 &" echo "$CMD3 &" echo "$CMD4" cat "${te}1" "${te}2" "${te}3" "${te}4" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2" "${te}3" "${te}4"; fi numOK=$((numOK+1)) fi kill $pid1 $pid2 $pid3 $pid4 2>/dev/null wait fi ;; # NUMCOND esac PORT=$((PORT+3)) N=$((N+1)) #! #PORT=10000 #! NAME=OUTBOUNDIN case "$TESTS" in *%$N%*|*%functions%*|*%openssl%*|*%proxy%*|*%$NAME%*) TEST="$NAME: gender changer via SSL through HTTP proxy, oneshot" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats openssl proxy); then $PRINTF "test $F_n $TEST... ${YELLOW}$(echo "$feat" |tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv gentestcert testcli tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" # this is the server in the protected network that we want to reach CMD1="$TRACE $SOCAT $opts -lpserver tcp4-l:$PORT,reuseaddr,bind=$LOCALHOST echo" # this is the proxy in the protected network that provides a way out CMD2="$TRACE $SOCAT $opts -lpproxy tcp4-l:$((PORT+1)),reuseaddr,bind=$LOCALHOST,fork exec:./proxy.sh" # this is our proxy connect wrapper in the protected network CMD3="$TRACE $SOCAT $opts -lpwrapper tcp4-l:$((PORT+2)),reuseaddr,bind=$LOCALHOST,fork proxy:$LOCALHOST:$LOCALHOST:$((PORT+3)),pf=ip4,proxyport=$((PORT+1)),resolve" # this is our double client in the protected network using SSL #CMD4="$TRACE $SOCAT $opts -lp2client ssl:$LOCALHOST:$((PORT+2)),pf=ip4,retry=10,interval=1,cert=testcli.pem,cafile=testsrv.crt,$SOCAT_EGD tcp4:$LOCALHOST:$PORT" CMD4="$TRACE $SOCAT $opts -lp2client ssl:$LOCALHOST:$((PORT+2)),pf=ip4,cert=testcli.pem,cafile=testsrv.crt,$SOCAT_EGD tcp4:$LOCALHOST:$PORT" # this is the double server in the outside network CMD5="$TRACE $SOCAT $opts -lp2server -t1 tcp4-l:$((PORT+4)),reuseaddr,bind=$LOCALHOST ssl-l:$((PORT+3)),pf=ip4,reuseaddr,bind=$LOCALHOST,$SOCAT_EGD,cert=testsrv.pem,cafile=testcli.crt" # this is the outside client that wants to use the protected server CMD6="$TRACE $SOCAT $opts -lpclient -t5 - tcp4:$LOCALHOST:$((PORT+4))" printf "test $F_n $TEST... " $N eval "$CMD1 2>${te}1 &" pid1=$! eval "$CMD2 2>${te}2 &" pid2=$! eval "$CMD3 2>${te}3 &" pid3=$! waittcp4port $PORT 1 || $PRINTF "$FAILED: port $PORT\n" >&2 &2 &2 ${te}5 &" pid5=$! waittcp4port $((PORT+4)) 1 || $PRINTF "$FAILED: port $((PORT+4))\n" >&2 $tf 2>"${te}6" & pid6=$! waittcp4port $((PORT+3)) 1 || $PRINTF "$FAILED: port $((PORT+3))\n" >&2 ${te}4 &" pid4=$! wait $pid6 if ! (echo "$da"; sleep 2) |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" cat "${te}1" echo "$CMD2 &" cat "${te}2" echo "$CMD3 &" cat "${te}3" echo "$CMD5 &" cat "${te}5" echo "$CMD6" cat "${te}6" echo "$CMD4 &" cat "${te}4" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2" "${te}3" "${te}4" "${te}5" "${te}6"; fi numOK=$((numOK+1)) fi kill $pid1 $pid2 $pid3 $pid4 $pid5 2>/dev/null wait fi ;; # NUMCOND, feats esac PORT=$((PORT+5)) N=$((N+1)) # test the TCP gender changer with almost production requirements: a double # client repeatedly tries to connect to a double server via SSL through an HTTP # proxy. the double servers SSL port becomes active for one connection only # after a (real) client has connected to its TCP port. when the double client # succeeded to establish an SSL connection, it connects with its second client # side to the specified (protected) server. all three consecutive connections # must function for full success of this test. PORT=$((RANDOM+16184)) #! NAME=INTRANETRIPPER case "$TESTS" in *%$N%*|*%functions%*|*%openssl%*|*%proxy%*|*%$NAME%*) TEST="$NAME: gender changer via SSL through HTTP proxy, daemons" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats openssl proxy); then $PRINTF "test $F_n $TEST... ${YELLOW}$(echo "$feat"| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv gentestcert testcli tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da1="test$N.1 $(date) $RANDOM" da2="test$N.2 $(date) $RANDOM" da3="test$N.3 $(date) $RANDOM" # this is the server in the protected network that we want to reach CMD1="$TRACE $SOCAT $opts -lpserver -t1 tcp4-l:$PORT,reuseaddr,bind=$LOCALHOST,fork echo" # this is the proxy in the protected network that provides a way out # note: the proxy.sh script starts one or two more socat processes without # setting the program name CMD2="$TRACE $SOCAT $opts -lpproxy -t1 tcp4-l:$((PORT+1)),reuseaddr,bind=$LOCALHOST,fork exec:./proxy.sh" # this is our proxy connect wrapper in the protected network CMD3="$TRACE $SOCAT $opts -lpwrapper -t3 tcp4-l:$((PORT+2)),reuseaddr,bind=$LOCALHOST,fork proxy:$LOCALHOST:$LOCALHOST:$((PORT+3)),pf=ip4,proxyport=$((PORT+1)),resolve" # this is our double client in the protected network using SSL CMD4="$TRACE $SOCAT $opts -lp2client -t3 ssl:$LOCALHOST:$((PORT+2)),retry=10,interval=1,cert=testcli.pem,cafile=testsrv.crt,verify,fork,$SOCAT_EGD tcp4:$LOCALHOST:$PORT,forever,interval=0.1" # this is the double server in the outside network CMD5="$TRACE $SOCAT $opts -lp2server -t4 tcp4-l:$((PORT+4)),reuseaddr,bind=$LOCALHOST,backlog=3,fork ssl-l:$((PORT+3)),pf=ip4,reuseaddr,bind=$LOCALHOST,$SOCAT_EGD,cert=testsrv.pem,cafile=testcli.crt,retry=20,interval=0.5" # this is the outside client that wants to use the protected server CMD6="$TRACE $SOCAT $opts -lpclient -t6 - tcp4:$LOCALHOST:$((PORT+4)),retry=3" printf "test $F_n $TEST... " $N # start the intranet infrastructure eval "$CMD1 2>\"${te}1\" &" pid1=$! eval "$CMD2 2>\"${te}2\" &" pid2=$! waittcp4port $PORT 1 || $PRINTF "$FAILED: port $PORT\n" >&2 &2 \"${te}3\" &" pid3=$! eval "$CMD4 2>\"${te}4\" &" pid4=$! waittcp4port $((PORT+2)) 1 || $PRINTF "$FAILED: port $((PORT+2))\n" >&2 \"${te}5\" &" pid5=$! waittcp4port $((PORT+4)) 1 || $PRINTF "$FAILED: port $((PORT+4))\n" >&2 ${tf}_1 2>"${te}6_1" & pid6_1=$! echo "$da2" |$CMD6 >${tf}_2 2>"${te}6_2" & pid6_2=$! echo "$da3" |$CMD6 >${tf}_3 2>"${te}6_3" & pid6_3=$! wait $pid6_1 $pid6_2 $pid6_3 # (echo "$da1"; sleep 2) |diff - "${tf}_1" >"${tdiff}1" (echo "$da2"; sleep 2) |diff - "${tf}_2" >"${tdiff}2" (echo "$da3"; sleep 2) |diff - "${tf}_3" >"${tdiff}3" if test -s "${tdiff}1" -o -s "${tdiff}2" -o -s "${tdiff}3"; then # FAILED only when none of the three transfers succeeded if test -s "${tdiff}1" -a -s "${tdiff}2" -a -s "${tdiff}3"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" cat "${te}1" echo "$CMD2 &" cat "${te}2" echo "$CMD3 &" cat "${te}3" echo "$CMD4 &" cat "${te}4" echo "$CMD5 &" cat "${te}5" echo "$CMD6 &" cat "${te}6_1" cat "${tdiff}1" echo "$CMD6 &" cat "${te}6_2" cat "${tdiff}2" echo "$CMD6 &" cat "${te}6_3" cat "${tdiff}3" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK ${YELLOW}(partial failure)${NORMAL}\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2" "${te}3" "${te}4" "${te}5" ${te}6*; fi numOK=$((numOK+1)) fi else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2" "${te}3" "${te}4" "${te}5" ${te}6*; fi numOK=$((numOK+1)) fi kill $pid1 $pid2 $pid3 $pid4 $pid5 2>/dev/null wait fi ;; # NUMCOND, feats esac PORT=$((PORT+5)) N=$((N+1)) # let us test the security features with -s, retry, and fork # method: first test without security feature if it works # then try with security feature, must fail # test the security features of a server address testserversec () { local N="$1" local title="$2" local opts="$3" local arg1="$4" # the server address local secopt0="$5" # option without security for server, mostly empty local secopt1="$6" # the security option for server, to be tested local arg2="$7" # the client address local ipvers="$8" # IP version, for check of listen port local proto="$9" # protocol, for check of listen port local port="${10}" # start client when this port is listening local expect="${11}" # expected behaviour of client: 0..empty output; -1..error; *: any of these local T="${12}"; [ -z "$T" ] && T=0 local tf="$td/test$N.stdout" local te="$td/test$N.stderr" local tdiff1="$td/test$N.diff1" local tdiff2="$td/test$N.diff2" local da="test$N.1 $(date) $RANDOM" local stat result $PRINTF "test $F_n %s... " $N "$title" # first: without security # start server $TRACE $SOCAT $opts "$arg1,$secopt0" echo 2>"${te}1" & spid=$! if [ "$port" ] && ! wait${proto}${ipvers}port $port 1; then kill $spid 2>/dev/null $PRINTF "$NO_RESULT (ph.1 server not working):\n" echo "$TRACE $SOCAT $opts \"$arg1,$secopt0\" echo &" cat "${te}1" numCANT=$((numCANT+1)) listCANT="$listCANT $N" wait; return fi # now use client (echo "$da"; sleep $T) |$TRACE $SOCAT $opts - "$arg2" >"$tf" 2>"${te}2" stat="$?" kill $spid 2>/dev/null #killall $TRACE $SOCAT 2>/dev/null if [ "$stat" != 0 ]; then $PRINTF "$NO_RESULT (ph.1 function fails): $TRACE $SOCAT:\n" echo "$TRACE $SOCAT $opts \"$arg1,$secopt0\" echo &" cat "${te}1" echo "$TRACE $SOCAT $opts - \"$arg2\"" cat "${te}2" numCANT=$((numCANT+1)) listCANT="$listCANT $N" wait; return elif echo "$da" |diff - "$tf" >"$tdiff1" 2>&1; then : # function without security is ok, go on else $PRINTF "$NO_RESULT (ph.1 function fails): diff:\n" echo "$TRACE $SOCAT $opts $arg1,$secopt0 echo &" cat "${te}1" echo "$TRACE $SOCAT $opts - $arg2" cat "${te}2" cat "$tdiff1" numCANT=$((numCANT+1)) listCANT="$listCANT $N" wait; return fi # then: with security if [ "$port" ] && ! wait${proto}${ipvers}port $port 0; then $PRINTF "$NO_RESULT (ph.1 port remains in use)\n" numCANT=$((numCANT+1)) listCANT="$listCANT $N" wait; return fi wait #set -vx # assemble address w/ security option; on dual, take read part: case "$arg1" in *!!*) arg="${arg1%!!*},$secopt1!!${arg1#*!!}" ;; *) arg="$arg1,$secopt1" ;; esac # start server # use -s to make sure that it fails due to a sec violation, not some other failure CMD3="$TRACE $SOCAT $opts -s $arg echo" $CMD3 2>"${te}3" & spid=$! if [ "$port" ] && ! wait${proto}${ipvers}port $port 1; then kill $spid 2>/dev/null $PRINTF "$NO_RESULT (ph.2 server not working)\n" wait echo "$CMD3" cat "${te}3" numCANT=$((numCANT+1)) listCANT="$listCANT $N" return fi # now use client da="test$N.2 $(date) $RANDOM" (echo "$da"; sleep $T) |$TRACE $SOCAT $opts - "$arg2" >"$tf" 2>"${te}4" stat=$? kill $spid 2>/dev/null #set +vx #killall $TRACE $SOCAT 2>/dev/null if [ "$stat" != 0 ]; then result=-1; # socat had error elif [ ! -s "$tf" ]; then result=0; # empty output elif echo "$da" |diff - "$tf" >"$tdiff2" 2>&1; then result=1; # output is copy of input else result=2; # output differs from input fi if [ "$expect" != '1' -a "$result" -eq 1 ]; then $PRINTF "$FAILED: SECURITY BROKEN\n" echo "$TRACE $SOCAT $opts $arg echo" cat "${te}3" echo "$TRACE $SOCAT $opts - $arg2" cat "${te}4" cat "$tdiff2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif [ "X$expect" != 'X*' -a X$result != X$expect ]; then case X$result in X-1) $PRINTF "$NO_RESULT (ph.2 client error): $TRACE $SOCAT:\n" echo "$TRACE $SOCAT $opts $arg echo" cat "${te}3" echo "$TRACE $SOCAT $opts - $arg2" cat "${te}4" numCANT=$((numCANT+1)) listCANT="$listCANT $N" ;; X0) $PRINTF "$NO_RESULT (ph.2 diff failed): diff:\n" echo "$TRACE $SOCAT $opts $arg echo" cat "${te}3" echo "$TRACE $SOCAT $opts - $arg2" cat "${te}4" cat "$tdiff2" numCANT=$((numCANT+1)) listCANT="$listCANT $N" ;; X1) $PRINTF "$FAILED: SECURITY BROKEN\n" echo "$TRACE $SOCAT $opts $arg echo" cat "${te}3" echo "$TRACE $SOCAT $opts - $arg2" cat "${te}4" cat "$tdiff2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" ;; X2) $PRINTF "$FAILED: diff:\n" echo "$TRACE $SOCAT $opts $arg echo" cat "${te}3" echo "$TRACE $SOCAT $opts - $arg2" cat "${te}4" cat "$tdiff2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" ;; esac else $PRINTF "$OK\n" [ "$VERBOSE" ] && echo " $TRACE $SOCAT $opts $arg echo" [ "$debug" ] && cat ${te}3 [ "$VERBOSE" ] && echo " $TRACE $SOCAT $opts - $arg2" [ "$debug" ] && cat ${te}4 numOK=$((numOK+1)) fi wait #set +vx } NAME=TCP4RANGEBITS case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%$NAME%*) TEST="$NAME: security of TCP4-L with RANGE option" if ! eval $NUMCOND; then :; elif [ -z "$SECONDADDR" ]; then # we need access to a second addresses $PRINTF "test $F_n $TEST... ${YELLOW}need a second IPv4 address${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else testserversec "$N" "$TEST" "$opts" "tcp4-l:$PORT,reuseaddr,fork,retry=1" "" "range=$SECONDADDR/32" "tcp4:127.0.0.1:$PORT" 4 tcp $PORT 0 fi ;; # $SECONDADDR, NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) NAME=TCP4RANGEMASK case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%$NAME%*) TEST="$NAME: security of TCP4-L with RANGE option" if ! eval $NUMCOND; then :; elif [ -z "$SECONDADDR" ]; then # we need access to a second addresses $PRINTF "test $F_n $TEST... ${YELLOW}need a second IPv4 address${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else testserversec "$N" "$TEST" "$opts" "tcp4-l:$PORT,reuseaddr,fork,retry=1" "" "range=$SECONDADDR:255.255.255.255" "tcp4:127.0.0.1:$PORT" 4 tcp $PORT 0 fi ;; # $SECONDADDR, NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) # like TCP4RANGEMASK, but the "bad" address is within the same class A network NAME=TCP4RANGEMASKHAIRY case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%$NAME%*) TEST="$NAME: security of TCP4-L with RANGE option" if ! eval $NUMCOND; then :; else testserversec "$N" "$TEST" "$opts" "tcp4-l:$PORT,reuseaddr,fork,retry=1" "" "range=127.0.0.0:255.255.0.0" "tcp4:$SECONDADDR:$PORT,bind=$SECONDADDR" 4 tcp $PORT 0 fi ;; # Linux, NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) NAME=TCP4SOURCEPORT case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%sourceport%*|*%$NAME%*) TEST="$NAME: security of TCP4-L with SOURCEPORT option" if ! eval $NUMCOND; then :; else testserversec "$N" "$TEST" "$opts" "tcp4-l:$PORT,reuseaddr,fork,retry=1" "" "sp=$PORT" "tcp4:127.0.0.1:$PORT" 4 tcp $PORT 0 fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) NAME=TCP4LOWPORT case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%lowport%*|*%$NAME%*) TEST="$NAME: security of TCP4-L with LOWPORT option" if ! eval $NUMCOND; then :; else testserversec "$N" "$TEST" "$opts" "tcp4-l:$PORT,reuseaddr,fork,retry=1" "" "lowport" "tcp4:127.0.0.1:$PORT" 4 tcp $PORT 0 fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) NAME=TCP4WRAPPERS_ADDR case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%tcpwrap%*|*%$NAME%*) TEST="$NAME: security of TCP4-L with TCPWRAP option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats tcp ip4 libwrap) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else ha="$td/hosts.allow" hd="$td/hosts.deny" $ECHO "socat: $SECONDADDR" >"$ha" $ECHO "ALL: ALL" >"$hd" testserversec "$N" "$TEST" "$opts" "tcp4-l:$PORT,reuseaddr,fork,retry=1" "" "hosts-allow=$ha,hosts-deny=$hd" "tcp4:127.0.0.1:$PORT" 4 tcp $PORT 0 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=TCP4WRAPPERS_NAME case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%tcpwrap%*|*%$NAME%*) TEST="$NAME: security of TCP4-L with TCPWRAP option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats tcp ip4 libwrap) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else ha="$td/hosts.allow" hd="$td/hosts.deny" $ECHO "socat: $LOCALHOST" >"$ha" $ECHO "ALL: ALL" >"$hd" testserversec "$N" "$TEST" "$opts" "tcp4-l:$PORT,reuseaddr,fork,retry=1" "" "hosts-allow=$ha,hosts-deny=$hd" "tcp4:$SECONDADDR:$PORT,bind=$SECONDADDR" 4 tcp $PORT 0 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=TCP6RANGE case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%range%*|*%$NAME%*) TEST="$NAME: security of TCP6-L with RANGE option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else testserversec "$N" "$TEST" "$opts" "tcp6-l:$PORT,reuseaddr,fork,retry=1" "" "range=[::2]/128" "tcp6:[::1]:$PORT" 6 tcp $PORT 0 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=TCP6SOURCEPORT case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%sourceport%*|*%$NAME%*) TEST="$NAME: security of TCP6-L with SOURCEPORT option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else testserversec "$N" "$TEST" "$opts" "tcp6-l:$PORT,reuseaddr,fork,retry=1" "" "sp=$PORT" "tcp6:[::1]:$PORT" 6 tcp $PORT 0 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=TCP6LOWPORT case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%lowport%*|*%$NAME%*) TEST="$NAME: security of TCP6-L with LOWPORT option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else testserversec "$N" "$TEST" "$opts" "tcp6-l:$PORT,reuseaddr,fork,retry=1" "" "lowport" "tcp6:[::1]:$PORT" 6 tcp $PORT 0 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=TCP6TCPWRAP case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%tcpwrap%*|*%$NAME%*) TEST="$NAME: security of TCP6-L with TCPWRAP option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats tcp ip6 libwrap && runstcp6); then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else ha="$td/hosts.allow" hd="$td/hosts.deny" $ECHO "socat: [::2]" >"$ha" $ECHO "ALL: ALL" >"$hd" testserversec "$N" "$TEST" "$opts" "tcp6-l:$PORT,reuseaddr,fork,retry=1" "" "hosts-allow=$ha,hosts-deny=$hd" "tcp6:[::1]:$PORT" 6 tcp $PORT 0 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=UDP4RANGE case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%range%*|*%$NAME%*) TEST="$NAME: security of UDP4-L with RANGE option" if ! eval $NUMCOND; then :; else #testserversec "$N" "$TEST" "$opts" "udp4-l:$PORT,reuseaddr,fork" "" "range=$SECONDADDR/32" "udp4:127.0.0.1:$PORT" 4 udp $PORT 0 testserversec "$N" "$TEST" "$opts" "udp4-l:$PORT,reuseaddr" "" "range=$SECONDADDR/32" "udp4:127.0.0.1:$PORT" 4 udp $PORT 0 fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) NAME=UDP4SOURCEPORT case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%sourceport%*|*%$NAME%*) TEST="$NAME: security of UDP4-L with SOURCEPORT option" if ! eval $NUMCOND; then :; else testserversec "$N" "$TEST" "$opts" "udp4-l:$PORT,reuseaddr" "" "sp=$PORT" "udp4:127.0.0.1:$PORT" 4 udp $PORT 0 fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) NAME=UDP4LOWPORT case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%lowport%*|*%$NAME%*) TEST="$NAME: security of UDP4-L with LOWPORT option" if ! eval $NUMCOND; then :; else testserversec "$N" "$TEST" "$opts" "udp4-l:$PORT,reuseaddr" "" "lowport" "udp4:127.0.0.1:$PORT" 4 udp $PORT 0 fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) NAME=UDP4TCPWRAP case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%tcpwrap%*|*%$NAME%*) TEST="$NAME: security of UDP4-L with TCPWRAP option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats udp ip4 libwrap) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else ha="$td/hosts.allow" hd="$td/hosts.deny" $ECHO "socat: $SECONDADDR" >"$ha" $ECHO "ALL: ALL" >"$hd" testserversec "$N" "$TEST" "$opts" "udp4-l:$PORT,reuseaddr" "" "tcpwrap-etc=$td" "udp4:127.0.0.1:$PORT" 4 udp $PORT 0 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=UDP6RANGE case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp6%*|*%ip6%*|*%range%*|*%$NAME%*) TEST="$NAME: security of UDP6-L with RANGE option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else #testserversec "$N" "$TEST" "$opts" "udp6-l:$PORT,reuseaddr,fork" "" "range=[::2]/128" "udp6:[::1]:$PORT" 6 udp $PORT 0 testserversec "$N" "$TEST" "$opts" "udp6-l:$PORT,reuseaddr" "" "range=[::2]/128" "udp6:[::1]:$PORT" 6 udp $PORT 0 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=UDP6SOURCEPORT case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp6%*|*%ip6%*|*%sourceport%*|*%$NAME%*) TEST="$NAME: security of UDP6-L with SOURCEPORT option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats udp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}UDP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else testserversec "$N" "$TEST" "$opts" "udp6-l:$PORT,reuseaddr" "" "sp=$PORT" "udp6:[::1]:$PORT" 6 udp $PORT 0 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=UDP6LOWPORT case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp6%*|*%ip6%*|*%lowport%*|*%$NAME%*) TEST="$NAME: security of UDP6-L with LOWPORT option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats udp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}UDP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else testserversec "$N" "$TEST" "$opts" "udp6-l:$PORT,reuseaddr" "" "lowport" "udp6:[::1]:$PORT" 6 udp $PORT 0 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=UDP6TCPWRAP case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp6%*|*%ip6%*|*%tcpwrap%*|*%$NAME%*) TEST="$NAME: security of UDP6-L with TCPWRAP option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats tcp ip6 libwrap && runsip6); then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else ha="$td/hosts.allow" hd="$td/hosts.deny" $ECHO "socat: [::2]" >"$ha" $ECHO "ALL: ALL" >"$hd" testserversec "$N" "$TEST" "$opts" "udp6-l:$PORT,reuseaddr" "" "lowport" "udp6:[::1]:$PORT" 6 udp $PORT 0 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=OPENSSLTCP4_RANGE case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%range%*|*%$NAME%*) TEST="$NAME: security of SSL-L over TCP/IPv4 with RANGE option" if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv testserversec "$N" "$TEST" "$opts" "SSL-L:$PORT,pf=ip4,reuseaddr,fork,retry=1,$SOCAT_EGD,verify=0,cert=testsrv.crt,key=testsrv.key" "" "range=$SECONDADDR/32" "SSL:$LOCALHOST:$PORT,cafile=testsrv.crt,$SOCAT_EGD" 4 tcp $PORT -1 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=OPENSSLTCP4_SOURCEPORT case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%sourceport%*|*%$NAME%*) TEST="$NAME: security of SSL-L with SOURCEPORT option" if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv testserversec "$N" "$TEST" "$opts" "SSL-L:$PORT,pf=ip4,reuseaddr,fork,retry=1,$SOCAT_EGD,verify=0,cert=testsrv.crt,key=testsrv.key" "" "sp=$PORT" "SSL:$LOCALHOST:$PORT,cafile=testsrv.crt,$SOCAT_EGD" 4 tcp $PORT -1 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=OPENSSLTCP4_LOWPORT case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%lowport%*|*%$NAME%*) TEST="$NAME: security of SSL-L with LOWPORT option" if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv testserversec "$N" "$TEST" "$opts" "SSL-L:$PORT,pf=ip4,reuseaddr,fork,retry=1,$SOCAT_EGD,verify=0,cert=testsrv.crt,key=testsrv.key" "" "lowport" "SSL:$LOCALHOST:$PORT,cafile=testsrv.crt,$SOCAT_EGD" 4 tcp $PORT -1 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=OPENSSLTCP4_TCPWRAP case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%tcpwrap%*|*%$NAME%*) TEST="$NAME: security of SSL-L with TCPWRAP option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats ip4 tcp libwrap openssl); then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv ha="$td/hosts.allow" hd="$td/hosts.deny" $ECHO "socat: $SECONDADDR" >"$ha" $ECHO "ALL: ALL" >"$hd" testserversec "$N" "$TEST" "$opts" "SSL-L:$PORT,pf=ip4,reuseaddr,fork,retry=1,$SOCAT_EGD,verify=0,cert=testsrv.crt,key=testsrv.key" "" "tcpwrap-etc=$td" "SSL:$LOCALHOST:$PORT,cafile=testsrv.crt,$SOCAT_EGD" 4 tcp $PORT -1 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=OPENSSLCERTSERVER case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%$NAME%*) TEST="$NAME: security of SSL-L with client certificate" if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv gentestcert testcli testserversec "$N" "$TEST" "$opts -4" "SSL-L:$PORT,pf=ip4,reuseaddr,fork,retry=1,$SOCAT_EGD,verify,cert=testsrv.crt,key=testsrv.key" "cafile=testcli.crt" "cafile=testsrv.crt" "SSL:$LOCALHOST:$PORT,cafile=testsrv.crt,cert=testcli.pem,$SOCAT_EGD" 4 tcp $PORT '*' fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=OPENSSLCERTCLIENT case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%$NAME%*) TEST="$NAME: security of SSL with server certificate" if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv gentestcert testcli testserversec "$N" "$TEST" "$opts -t 0.5 -lu -d" "ssl:$LOCALHOST:$PORT,pf=ip4,fork,retry=2,verify,cert=testcli.pem,$SOCAT_EGD" "cafile=testsrv.crt" "cafile=testcli.crt" "ssl-l:$PORT,pf=ip4,reuseaddr,$SOCAT_EGD,cafile=testcli.crt,cert=testsrv.crt,key=testsrv.key" 4 tcp "" -1 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=OPENSSLTCP6_RANGE case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%range%*|*%$NAME%*) TEST="$NAME: security of SSL-L over TCP/IPv6 with RANGE option" if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert6 testsrv6 testserversec "$N" "$TEST" "$opts" "ssl-l:$PORT,pf=ip6,reuseaddr,fork,retry=1,$SOCAT_EGD,verify=0,cert=testsrv6.crt,key=testsrv6.key" "" "range=[::2]/128" "ssl:[::1]:$PORT,cafile=testsrv6.crt,$SOCAT_EGD" 6 tcp $PORT -1 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=OPENSSLTCP6_SOURCEPORT case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%sourceport%*|*%$NAME%*) TEST="$NAME: security of SSL-L over TCP/IPv6 with SOURCEPORT option" if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert6 testsrv6 testserversec "$N" "$TEST" "$opts" "ssl-l:$PORT,pf=ip6,reuseaddr,fork,retry=1,$SOCAT_EGD,verify=0,cert=testsrv6.crt,key=testsrv6.key" "" "sp=$PORT" "ssl:[::1]:$PORT,cafile=testsrv6.crt,$SOCAT_EGD" 6 tcp $PORT -1 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=OPENSSLTCP6_LOWPORT case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%lowport%*|*%$NAME%*) TEST="$NAME: security of SSL-L over TCP/IPv6 with LOWPORT option" if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert6 testsrv6 testserversec "$N" "$TEST" "$opts" "ssl-l:$PORT,pf=ip6,reuseaddr,fork,retry=1,$SOCAT_EGD,verify=0,cert=testsrv6.crt,key=testsrv6.key" "" "lowport" "ssl:[::1]:$PORT,cafile=testsrv6.crt,$SOCAT_EGD" 6 tcp $PORT -1 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=OPENSSLTCP6_TCPWRAP case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%openssl%*|*%tcpwrap%*|*%$NAME%*) TEST="$NAME: security of SSL-L over TCP/IPv6 with TCPWRAP option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats ip6 tcp libwrap openssl && runsip6); then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert6 testsrv6 ha="$td/hosts.allow" hd="$td/hosts.deny" $ECHO "socat: [::2]" >"$ha" $ECHO "ALL: ALL" >"$hd" testserversec "$N" "$TEST" "$opts" "ssl-l:$PORT,pf=ip6,reuseaddr,fork,retry=1,$SOCAT_EGD,verify=0,cert=testsrv6.crt,key=testsrv6.key" "" "tcpwrap-etc=$td" "ssl:[::1]:$PORT,cafile=testsrv6.crt,$SOCAT_EGD" 6 tcp $PORT -1 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) # test security with the openssl-commonname option on client side NAME=OPENSSL_CN_CLIENT_SECURITY case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%openssl%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*) TEST="$NAME: security of client openssl-commonname option" # connect using non matching server name/address with commonname # options, this should succeed. Then without this option, should fail if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats listen tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP/IPv4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv gentestcert testcli testserversec "$N" "$TEST" "$opts -t 0.5 -4" "SSL:127.0.0.1:$PORT,fork,retry=2,verify,cafile=testsrv.crt" "commonname=$LOCALHOST" "" "SSL-L:$PORT,pf=ip4,$REUSEADDR,cert=testsrv.crt,key=testsrv.key,verify=0" 4 tcp "" '*' fi ;; # testfeats, NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) # test security with the openssl-commonname option on server side NAME=OPENSSL_CN_SERVER_SECURITY case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%openssl%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*) TEST="$NAME: security of server openssl-commonname option" # connect using with client certificate to server, this should succeed. # Then use the server with a non matching openssl-commonname option, # this must fail if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats listen tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP/IPv4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv gentestcert testcli testserversec "$N" "$TEST" "$opts -4" "SSL-L:$PORT,pf=ip4,reuseaddr,cert=testsrv.crt,key=testsrv.key,cafile=testcli.crt" "" "commonname=onlyyou" "SSL:$LOCALHOST:$PORT,$REUSEADDR,verify=0,cafile=testsrv.crt,cert=testcli.crt,key=testcli.key" 4 tcp "$PORT" '*' fi ;; # testfeats, NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) NAME=OPENSSL_FIPS_SECURITY case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%openssl%*|*%fips%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*) TEST="$NAME: OpenSSL restrictions by FIPS" if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats listen tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP/IPv4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testoptions fips >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL/FIPS not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv gentestcert testcli # openssl client accepts a "normal" certificate only when not in fips mode testserversec "$N" "$TEST" "$opts" "ssl:$LOCALHOST:$PORT,fork,retry=2,verify,cafile=testsrv.crt" "" "fips" "SSL-L:$PORT,pf=ip4,$REUSEADDR,cert=testsrv.crt,key=testsrv.key" 4 tcp "" -1 fi ;; # testfeats, NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) NAME=UNIEXECEOF case "$TESTS" in *%$N%*|*%functions%*|*%$NAME%*) TEST="$NAME: give exec'd write-only process a chance to flush (-u)" testod "$N" "$TEST" "" exec:"$OD_C" "$opts -u" esac N=$((N+1)) NAME=REVEXECEOF case "$TESTS" in *%$N%*|*%functions%*|*%$NAME%*) TEST="$NAME: give exec'd write-only process a chance to flush (-U)" testod "$N" "$TEST" exec:"$OD_C" "-" "$opts -U" esac N=$((N+1)) NAME=FILANDIR case "$TESTS" in *%$N%*|*%filan%*|*%$NAME%*) TEST="$NAME: check type printed for directories" if ! eval $NUMCOND; then :; else te="$td/test$N.stderr" printf "test $F_n $TEST... " $N type=$($FILAN -f . 2>$te |tail -n 1 |awk '{print($2);}') if [ "$type" = "dir" ]; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" cat "$te" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi ;; # NUMCOND esac N=$((N+1)) NAME=FILANSOCKET case "$TESTS" in *%$N%*|*%filan%*|*%$NAME%*) TEST="$NAME: capability to analyze named unix socket" if ! eval $NUMCOND; then :; else ts="$td/test$N.socket" te1="$td/test$N.stderr1" # socat te2="$td/test$N.stderr2" # filan printf "test $F_n $TEST... " $N $TRACE $SOCAT $opts UNIX-LISTEN:"$ts" /dev/null "$te1" & spid=$! waitfile "$ts" 1 type=$($FILAN -f "$ts" 2>$te2 |tail -n 1 |awk '{print($2);}') if [ "$type" = "socket" ]; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" cat "$te1" cat "$te2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi kill $spid 2>/dev/null wait fi ;; # NUMCOND esac N=$((N+1)) testptywaitslave () { local N="$1" local TEST="$2" local PTYTYPE="$3" # ptmx or openpty local opts="$4" local tp="$td/test$N.pty" local ts="$td/test$N.socket" local tf="$td/test$N.file" local tdiff="$td/test$N.diff" local te1="$td/test$N.stderr1" local te2="$td/test$N.stderr2" local te3="$td/test$N.stderr3" local te4="$td/test$N.stderr4" local da="test$N $(date) $RANDOM" printf "test $F_n $TEST... " $N # first generate a pty, then a socket ($TRACE $SOCAT $opts -lpsocat1 pty,$PTYTYPE,pty-wait-slave,link="$tp" unix-listen:"$ts" 2>"$te1"; rm -f "$tp") 2>/dev/null & pid=$! waitfile "$tp" # if pty was non-blocking, the socket is active, and socat1 will term $TRACE $SOCAT $opts -T 10 -lpsocat2 file:/dev/null unix-connect:"$ts" 2>"$te2" # if pty is blocking, first socat is still active and we get a connection now #((echo "$da"; sleep 2) |$TRACE $SOCAT -lpsocat3 $opts - file:"$tp",$PTYOPTS2 >"$tf" 2>"$te3") & ( (waitfile "$ts"; echo "$da"; sleep 1) |$TRACE $SOCAT -lpsocat3 $opts - file:"$tp",$PTYOPTS2 >"$tf" 2>"$te3") & waitfile "$ts" # but we need an echoer on the socket $TRACE $SOCAT $opts -lpsocat4 unix:"$ts" echo 2>"$te4" # now $tf file should contain $da #kill $pid 2>/dev/null wait # if echo "$da" |diff - "$tf"> "$tdiff"; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "${YELLOW}FAILED${NORMAL}\n" cat "$te1" #cat "$te2" # not of interest cat "$te3" cat "$te4" cat "$tdiff" numCANT=$((numCANT+1)) listCANT="$listCANT $N" fi } NAME=PTMXWAITSLAVE PTYTYPE=ptmx case "$TESTS" in *%$N%*|*%functions%*|*%pty%*|*%$NAME%*) TEST="$NAME: test if master pty ($PTYTYPE) waits for slave connection" if ! eval $NUMCOND; then :; else if ! feat=$(testfeats pty); then $PRINTF "test $F_n $TEST... ${YELLOW}$(echo "$feat"| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! feat=$(testoptions "$PTYTYPE" pty-wait-slave); then $PRINTF "test $F_n $TEST... ${YELLOW}option $(echo "$feat"| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else testptywaitslave "$N" "$TEST" "$PTYTYPE" "$opts" fi fi ;; # NUMCOND esac N=$((N+1)) NAME=OPENPTYWAITSLAVE PTYTYPE=openpty case "$TESTS" in *%$N%*|*%functions%*|*%pty%*|*%$NAME%*) TEST="$NAME: test if master pty ($PTYTYPE) waits for slave connection" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats pty); then $PRINTF "test $F_n $TEST... ${YELLOW}$(echo "$feat"| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! feat=$(testoptions "$PTYTYPE" pty-wait-slave); then $PRINTF "test $F_n $TEST... ${YELLOW}option $(echo "$feat"| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else testptywaitslave "$N" "$TEST" "$PTYTYPE" "$opts" fi ;; # NUMCOND, feats esac N=$((N+1)) # Test the connect-timeout address option NAME=CONNECTTIMEOUT case "$TESTS" in *%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%tcp%*|*%timeout%*|*%$NAME%*) TEST="$NAME: test the connect-timeout option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats tcp); then $PRINTF "test $F_n $TEST... ${YELLOW}$(echo "$feat"| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! feat=$(testoptions connect-timeout); then $PRINTF "test $F_n $TEST... ${YELLOW}$(echo "$feat"| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else # we need a hanging connection attempt, guess an address for this case "$UNAME" in Linux) HANGIP=1.0.0.1 ;; *) HANGIP=255.255.255.254 ;; esac te1="$td/test$N.stderr1" tk1="$td/test$N.kill1" te2="$td/test$N.stderr2" tk2="$td/test$N.kill2" $PRINTF "test $F_n $TEST... " $N # first, try to make socat hang and see if it can be killed #$TRACE $SOCAT $opts - tcp:$HANGIP:1 >"$te1" 2>&1 "$te1" 2>&1 "$tk1"; then $PRINTF "${YELLOW}does not hang${NORMAL}\n" numCANT=$((numCANT+1)) listCANT="$listCANT $N" else # second, set connect-timeout and see if socat exits before kill $TRACE $SOCAT $opts - tcp:$HANGIP:1,connect-timeout=1.0 >"$te2" 2>&1 "$tk2"; then $PRINTF "$FAILED\n" echo "$CMD" cat "$te1" cat "$te2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" numOK=$((numOK+1)) fi fi wait fi ;; # testfeats, NUMCOND esac N=$((N+1)) # version 1.7.0.0 had a bug with the connect-timeout option: while it correctly # terminated a hanging connect attempt, it prevented a successful connection # establishment from being recognized by socat, instead the timeout occurred NAME=CONNECTTIMEOUT_CONN if ! eval $NUMCOND; then :; else case "$TESTS" in *%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%tcp%*|*%timeout%*|*%$NAME%*) TEST="$NAME: TCP4 connect-timeout option when server replies" # just try a connection that is expected to succeed with the usual data # transfer; with the bug it will fail tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="127.0.0.1:$tsl" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts TCP4-LISTEN:$tsl,$REUSEADDR PIPE" CMD2="$TRACE $SOCAT $opts STDIO TCP4:$ts,connect-timeout=1" printf "test $F_n $TEST... " $N $CMD1 >"$tf" 2>"${te}1" & pid1=$! waittcp4port $tsl 1 echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" if [ $? -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" cat "${te}1" echo "$CMD2" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid1 2>/dev/null wait ;; esac PORT=$((PORT+1)) fi # NUMCOND N=$((N+1)) NAME=OPENSSLLISTENDSA case "$TESTS" in *%$N%*|*%functions%*|*%openssl%*|*%$NAME%*) TEST="$NAME: openssl listen with DSA certificate" if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else SRVCERT=testsrvdsa gentestdsacert $SRVCERT tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD2="$TRACE $SOCAT $opts OPENSSL-LISTEN:$PORT,pf=ip4,$REUSEADDR,$SOCAT_EGD,cert=$SRVCERT.pem,key=$SRVCERT.key,verify=0 pipe" CMD="$TRACE $SOCAT $opts - openssl:$LOCALHOST:$PORT,pf=ip4,verify=0,$SOCAT_EGD" $PRINTF "test $F_n $TEST... " $N eval "$CMD2 2>\"${te}1\" &" pid=$! # background process id waittcp4port $PORT echo "$da" |$CMD >$tf 2>"${te}2" if ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" echo "$CMD2 &" echo "$CMD" cat "${te}1" cat "${te}2" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat ${te}1 ${te}2; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null wait fi ;; # testfeats, NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) # derive signal number from signal name # kill -l should provide the info signum () { if [ ! "$BASH_VERSION" -o -o posix ]; then # we expect: for i in $(POSIXLY_CORRECT=1 kill -l); do echo "$i"; done |grep -n -i "^$1$" |cut -d: -f1 else # expect: # " 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL" signam="$1" kill -l $tpp"'; echo \$$ '">$tp; read x\"",nofork 2>"$te"; stat=$? tsh="$td/test$N.sh" cat <"$tsh" #! /usr/bin/env bash echo \$PPID >"$tpp" echo \$\$ >"$tp" read x EOF chmod a+x "$tsh" #$TRACE $SOCAT $opts echo SYSTEM:"exec \"$tsh\"",pty,setsid,nofork 2>"$te"; stat=$? CMD="$TRACE $SOCAT $opts ECHO SYSTEM:\"exec\\\ \\\"$tsh\\\"\",pty,setsid,nofork" $TRACE $SOCAT $opts ECHO SYSTEM:"exec \"$tsh\"",pty,setsid,nofork 2>"$te" stat=$? sleep 1; kill -INT $(cat $tp) wait if [ "$stat" -eq $((128+$SIG)) ]; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD" cat "$te" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi wait fi ;; # NUMCOND, feats esac N=$((N+1)) done NAME=READBYTES #set -vx case "$TESTS" in *%$N%*|*%functions%*|*%$NAME%*) TEST="$NAME: restrict reading from file with bytes option" if ! eval $NUMCOND; then :; elif false; then $PRINTF "test $F_n $TEST... ${YELLOW}$(echo "$feat"| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tr="$td/test$N.ref" ti="$td/test$N.in" to="$td/test$N.out" te="$td/test$N.err" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')" # the feature that we really want to test is in the readline.sh script: CMD="$TRACE $SOCAT $opts -u open:$ti,readbytes=100 -" printf "test $F_n $TEST... " $N rm -f "$tf" "$ti" "$to" # echo "AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAA" >"$tr" # 100 bytes cat "$tr" "$tr" >"$ti" # 200 bytes $CMD >"$to" 2>"$te" if ! diff "$tr" "$to" >"$tdiff" 2>&1; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD" cat "$te" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND, feats esac N=$((N+1)) NAME=UDPLISTENFORK case "$TESTS" in *%$N%*|*%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 #processes hang forever without -T SRV="$TRACE $SOCAT -T 5 $opts -lpserver UDP4-LISTEN:$PORT,bind=$LOCALHOST,$REUSEADDR,fork PIPE" #make a first and a second connection CLI="$TRACE $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)) listCANT="$listCANT $N" 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)) listCANT="$listCANT $N" 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 &" cat "${te}s" echo "$CLI" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da2" |diff - "${tf}2" >"$tdiff"; then $PRINTF "$FAILED: diff\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" 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)) # Is a listen address capable of forking two child processes and have both # active? while read PROTOV MAJADDR MINADDR; do if [ -z "$PROTOV" ] || [[ "$PROTOV" == \#* ]]; then continue; fi protov="$(echo "$PROTOV" |tr A-Z a-z)" proto="${protov%%[0-9]}" NAME=${PROTOV}LISTENFORK case "$TESTS" in *%$N%*|*%functions%*|*%$protov%*|*%$proto%*|*%listen%*|*%fork%*|*%$NAME%*) TEST="$NAME: $PROTOV listen handles 2 concurrent connections" # Have a listening address with fork option. connect with client1, send a piece # of data, wait 1s, connect with client2, send another piece of data, wait 1s, # and send another piece of data with client1. The server processes append all # data to the same file. Check all data are written to the file in correct # order. if ! eval $NUMCOND; then :; #elif ! feat=$(testfeats $PROTOV); then # $PRINTF "test $F_n $TEST... ${YELLOW}$(echo "$PROTOV" |tr a-z A-Z) not available${NORMAL}\n" $N # numCANT=$((numCANT+1)) elif ! runs$protov >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$PROTOV not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else ts="$td/test$N.sock" tref="$td/test$N.ref" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da1a="test$N $(date) 1a $RANDOM" da1b="test$N $(date) 1b $RANDOM" da2="test$N $(date) 2 $RANDOM" case "$MAJADDR" in "FILE") tla="$ts" tca="$ts" waitproto="file" waitfor="$ts" ;; esac case "$MINADDR" in "PORT") tla="$PORT,bind=$MAJADDR" tca="$MAJADDR:$PORT" waitproto="${protov}port" waitfor="$PORT" ;; esac #set -xv echo -e "$da1a\n$da2\n$da1b" >"$tref" # establish a listening and forking listen socket in background # UDP processes hang forever without -T CMD0="$TRACE $SOCAT -T 5 $opts -lpserver $PROTOV-LISTEN:$tla,$REUSEADDR,fork PIPE" # make a first and a second connection CMD1="$TRACE $SOCAT $opts -lpclient - $PROTOV-CONNECT:$tca" $PRINTF "test $F_n $TEST... " $N eval "$CMD0 2>${te}0 &" pid0=$! wait$waitproto "$waitfor" 1 2 (echo "$da1a"; sleep 2; echo "$da1b") |eval "$CMD1" >>"${tf}" 2>"${te}1" & sleep 1 # trailing sleep req for sctp because no half close (echo "$da2"; sleep 1) |eval "$CMD1" >>"${tf}" 2>"${te}2" & sleep 2 kill $pid0 2>/dev/null wait if ! diff "$tref" "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "${te}0" "${te}1" "${te}2" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" numOK=$((numOK+1)) fi # !(rc -ne 0) wait fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) done <<<" TCP4 $LOCALHOST PORT TCP6 $LOCALHOST6 PORT UDP4 $LOCALHOST PORT UDP6 $LOCALHOST6 PORT SCTP4 $LOCALHOST PORT SCTP6 $LOCALHOST6 PORT UNIX FILE , " NAME=UNIXTOSTREAM case "$TESTS" in *%$N%*|*%functions%*|*%unix%*|*%listen%*|*%$NAME%*) TEST="$NAME: generic UNIX client connects to stream socket" if ! eval $NUMCOND; then :; else ts="$td/test$N.socket" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da1="test$N $(date) $RANDOM" #establish a listening unix socket in background SRV="$TRACE $SOCAT $opts -lpserver UNIX-LISTEN:\"$ts\" PIPE" #make a connection CLI="$TRACE $SOCAT $opts -lpclient - UNIX:\"$ts\"" $PRINTF "test $F_n $TEST... " $N eval "$SRV 2>${te}s &" pids=$! waitfile "$ts" echo "$da1" |eval "$CLI" >"${tf}1" 2>"${te}1" if [ $? -ne 0 ]; then kill "$pids" 2>/dev/null $PRINTF "$FAILED:\n" echo "$SRV &" echo "$CLI" cat "${te}s" "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da1" |diff - "${tf}1" >"$tdiff"; then kill "$pids" 2>/dev/null $PRINTF "$FAILED; diff:\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" numOK=$((numOK+1)) fi # !(rc -ne 0) wait fi ;; # NUMCOND esac N=$((N+1)) NAME=UNIXTODGRAM case "$TESTS" in *%$N%*|*%functions%*|*%engine%*|*%unix%*|*%recv%*|*%$NAME%*) TEST="$NAME: generic UNIX client connects to datagram socket" if ! eval $NUMCOND; then :; else ts1="$td/test$N.socket1" ts2="$td/test$N.socket2" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da1="test$N $(date) $RANDOM" #establish a receiving unix datagram socket in background SRV="$TRACE $SOCAT $opts -lpserver UNIX-RECVFROM:\"$ts1\" PIPE" #make a connection CLI="$TRACE $SOCAT $opts -lpclient - UNIX:\"$ts1\",bind=\"$ts2\"" #CLI="$TRACE $SOCAT $opts -lpclient - UNIX:\"$ts1\"" $PRINTF "test $F_n $TEST... " $N eval "$SRV 2>${te}s &" pids=$! waitfile "$ts1" echo "$da1" |eval "$CLI" >"${tf}1" 2>"${te}1" rc=$? kill $pids 2>/dev/null wait if [ $rc -ne 0 ]; then kill "$pids" 2>/dev/null $PRINTF "$FAILED:\n" echo "$SRV &" cat "${te}s" echo "$CLI" cat "${te}1" "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da1" |diff - "${tf}1" >"$tdiff"; then kill "$pids" 2>/dev/null $PRINTF "$FAILED:\n" echo "$SRV &" cat "${te}s" echo "$CLI" cat "${te}1" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" numOK=$((numOK+1)) fi # !(rc -ne 0) fi ;; # NUMCOND esac N=$((N+1)) # there was an error in address EXEC with options pipes,stderr NAME=EXECPIPESSTDERR case "$TESTS" in *%$N%*|*%functions%*|*%$NAME%*) TEST="$NAME: simple echo via exec of cat with pipes,stderr" # this test is known to fail when logging is enabled with OPTS/opts env var. SAVE_opts="$opts" opts="$(echo "$opts" |sed 's/-dd*//g')" testecho "$N" "$TEST" "" "EXEC:$CAT,pipes,stderr" "$opts" opts="$SAVE_opts" esac N=$((N+1)) # EXEC and SYSTEM with stderr injected socat messages into the data stream. NAME=EXECSTDERRLOG case "$TESTS" in *%$N%*|*%functions%*|*%$NAME%*) TEST="$NAME: simple echo via exec of cat with pipes,stderr" SAVE_opts="$opts" # make sure at least two -d are there case "$opts" in *-d*-d*) ;; *-d*) opts="$opts -d" ;; *) opts="-d -d" ;; esac testecho "$N" "$TEST" "" "exec:$CAT,pipes,stderr" "$opts" opts="$SAVE_opts" esac N=$((N+1)) NAME=SIMPLEPARSE case "$TESTS" in *%$N%*|*%functions%*|*%PARSE%*|*%$NAME%*) TEST="$NAME: invoke socat from socat" testecho "$N" "$TEST" "" exec:"$SOCAT - exec\:$CAT,pipes" "$opts" esac N=$((N+1)) NAME=FULLPARSE case "$TESTS" in *%$N%*|*%functions%*|*%parse%*|*%$NAME%*) TEST="$NAME: correctly parse special chars" if ! eval $NUMCOND; then :; else $PRINTF "test $F_n $TEST... " $N tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" # a string where commas are hidden in nesting lexical constructs # if they are scanned incorrectly, socat will see an "unknown option" dain='(,)[,]{,}","([),])hugo' daout='(,)[,]{,},([),])hugo' $TRACE "$SOCAT" $opts -u "exec:echo $dain" - >"$tf" 2>"$te" rc=$? echo "$daout" |diff "$tf" - >"$tdiff" if [ "$rc" -ne 0 ]; then $PRINTF "$FAILED:\n" echo "$TRACE $SOCAT" -u "exec:echo $da" - cat "$te" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif [ -s "$tdiff" ]; then $PRINTF "$FAILED:\n" echo diff: cat "$tdiff" if [ -n "$debug" ]; then cat $te; fi numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND esac N=$((N+1)) NAME=NESTEDSOCATEXEC case "$TESTS" in *%parse%*|*%$N%*|*%functions%*|*%$NAME%*) TEST="$NAME: does lexical analysis work sensibly (exec)" testecho "$N" "$TEST" "" "exec:'$SOCAT - exec:$CAT,pipes'" "$opts" 1 esac N=$((N+1)) NAME=NESTEDSOCATSYSTEM case "$TESTS" in *%parse%*|*%$N%*|*%functions%*|*%$NAME%*) TEST="$NAME: does lexical analysis work sensibly (system)" testecho "$N" "$TEST" "" "system:\"$SOCAT - exec:$CAT,pipes\"" "$opts" 1 esac N=$((N+1)) NAME=TCP6BYTCP4 case "$TESTS" in *%$N%*|*%functions%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%$NAME%*) TEST="$NAME: TCP4 mapped into TCP6 address space" if ! eval $NUMCOND; then :; elif true; then $PRINTF "test $F_n $TEST... ${YELLOW}Feature removed${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats tcp ip6 >/dev/null || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="127.0.0.1:$tsl" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts TCP6-listen:$tsl,$REUSEADDR PIPE" CMD2="$TRACE $SOCAT $opts stdin!!stdout TCP6:$ts" printf "test $F_n $TEST... " $N $CMD1 >"$tf" 2>"${te}1" & pid=$! # background process id waittcp6port $tsl 1 echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" if [ $? -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: diff:\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null; wait fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) # test the UDP4-SENDTO and UDP4-RECVFROM addresses together NAME=UDP4DGRAM case "$TESTS" in *%$N%*|*%functions%*|*%udp%*|*%udp4%*|*%ip4%*|*%dgram%*|*%$NAME%*) TEST="$NAME: UDP/IPv4 sendto and recvfrom" # start a UDP4-RECVFROM process that echoes data, and send test data using # UDP4-SENDTO. The sent data should be returned. if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1p=$PORT; PORT=$((PORT+1)) ts1a="127.0.0.1" ts1="$ts1a:$ts1p" ts2p=$PORT; PORT=$((PORT+1)) ts2="127.0.0.1:$ts2p" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts UDP4-RECVFROM:$ts1p,reuseaddr,bind=$ts1a PIPE" CMD2="$TRACE $SOCAT $opts - UDP4-SENDTO:$ts1,bind=$ts2" printf "test $F_n $TEST... " $N $CMD1 2>"${te}1" & pid1="$!" waitudp4port $ts1p 1 echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" rc2="$?" kill "$pid1" 2>/dev/null; wait; if [ "$rc2" -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" cat "${te}1" echo "$CMD2" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" echo "$CMD1 &" cat "${te}1" echo "$CMD2" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) NAME=UDP6DGRAM case "$TESTS" in *%$N%*|*%functions%*|*%udp%*|*%udp6%*|*%ip6%*|*%dgram%*|*%$NAME%*) TEST="$NAME: UDP/IPv6 datagram" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1p=$PORT; PORT=$((PORT+1)) tsa="[::1]" ts1="$tsa:$ts1p" ts2p=$PORT; PORT=$((PORT+1)) ts2="$tsa:$ts2p" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts UDP6-RECVFROM:$ts1p,reuseaddr,bind=$tsa PIPE" CMD2="$TRACE $SOCAT $opts - UDP6-SENDTO:$ts1,bind=$ts2" printf "test $F_n $TEST... " $N $CMD1 2>"${te}1" & waitudp6port $ts1p 1 echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" if [ $? -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat ${te}1 ${te}2; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=RAWIP4RECVFROM case "$TESTS" in *%$N%*|*%functions%*|*%ip%*|*%ip4%*|*%rawip%*|*%rawip4%*|*%dgram%*|*%root%*|*%$NAME%*) TEST="$NAME: raw IPv4 datagram" if ! eval $NUMCOND; then :; elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1p=$PROTO; PROTO=$((PROTO+1)) ts1a="127.0.0.1" ts1="$ts1a:$ts1p" ts2a="$SECONDADDR" ts2="$ts2a:$ts2p" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts IP4-RECVFROM:$ts1p,reuseaddr,bind=$ts1a PIPE" CMD2="$TRACE $SOCAT $opts - IP4-SENDTO:$ts1,bind=$ts2a" printf "test $F_n $TEST... " $N $CMD1 2>"${te}1" & pid1=$! waitip4proto $ts1p 1 echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" rc2=$? kill $pid1 2>/dev/null; wait if [ $rc2 -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # root, NUMCOND esac N=$((N+1)) if false; then NAME=RAWIP6RECVFROM case "$TESTS" in *%$N%*|*%functions%*|*%ip%*|*%ip6%*|*%rawip%*|*%rawip6%*|*%dgram%*|*%root%*|*%$NAME%*) TEST="$NAME: raw IPv6 datagram by self addressing" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats ip6 rawip && runsip6); then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1p=$PROTO; PROTO=$((PROTO+1)) tsa="[::1]" ts1="$tsa:$ts1p" ts2="$tsa" da="test$N $(date) $RANDOM" #CMD1="$TRACE $SOCAT $opts IP6-RECVFROM:$ts1p,reuseaddr,bind=$tsa PIPE" CMD2="$TRACE $SOCAT $opts - IP6-SENDTO:$ts1,bind=$ts2" printf "test $F_n $TEST... " $N #$CMD1 2>"${te}1" & waitip6proto $ts1p 1 echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" if [ $? -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" # echo "$CMD1 &" # cat "${te}1" echo "$CMD2" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "$te"; fi numOK=$((numOK+1)) fi fi ;; # root, NUMCOND esac N=$((N+1)) fi #false NAME=UNIXDGRAM case "$TESTS" in *%$N%*|*%functions%*|*%engine%*|*%unix%*|*%dgram%*|*%$NAME%*) TEST="$NAME: UNIX datagram" if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1="$td/test$N.socket1" ts2="$td/test$N.socket2" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts UNIX-RECVFROM:$ts1,reuseaddr PIPE" CMD2="$TRACE $SOCAT $opts - UNIX-SENDTO:$ts1,bind=$ts2" printf "test $F_n $TEST... " $N $CMD1 2>"${te}1" & pid1="$!" waitfile $ts1 1 echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" rc2=$? kill "$pid1" 2>/dev/null; wait if [ $rc2 -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" cat "${te}1" echo "$CMD2" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi # NUMCOND ;; esac N=$((N+1)) NAME=UDP4RECV case "$TESTS" in *%$N%*|*%functions%*|*%engine%*|*%ip4%*|*%dgram%*|*%udp%*|*%udp4%*|*%recv%*|*%$NAME%*) TEST="$NAME: UDP/IPv4 receive" if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1p=$PORT; PORT=$((PORT+1)) ts1a="127.0.0.1" ts1="$ts1a:$ts1p" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts -u UDP4-RECV:$ts1p,reuseaddr -" CMD2="$TRACE $SOCAT $opts -u - UDP4-SENDTO:$ts1" printf "test $F_n $TEST... " $N $CMD1 >"$tf" 2>"${te}1" & pid1="$!" waitudp4port $ts1p 1 echo "$da" |$CMD2 2>>"${te}2" rc2="$?" #ls -l $tf i=0; while [ ! -s "$tf" -a "$i" -lt 10 ]; do usleep 100000; i=$((i+1)); done kill "$pid1" 2>/dev/null; wait if [ "$rc2" -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" echo "$CMD1 &" echo "$CMD2" cat "${te}1" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi # NUMCOND ;; esac N=$((N+1)) NAME=UDP6RECV case "$TESTS" in *%$N%*|*%functions%*|*%ip6%*|*%dgram%*|*%udp%*|*%udp6%*|*%recv%*|*%$NAME%*) TEST="$NAME: UDP/IPv6 receive" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1p=$PORT; PORT=$((PORT+1)) ts1a="[::1]" ts1="$ts1a:$ts1p" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts -u UDP6-RECV:$ts1p,reuseaddr -" CMD2="$TRACE $SOCAT $opts -u - UDP6-SENDTO:$ts1" printf "test $F_n $TEST... " $N $CMD1 >"$tf" 2>"${te}1" & pid1="$!" waitudp6port $ts1p 1 echo "$da" |$CMD2 2>>"${te}2" rc2="$?" #ls -l $tf i=0; while [ ! -s "$tf" -a "$i" -lt 10 ]; do usleep 100000; i=$((i+1)); done kill "$pid1" 2>/dev/null; wait if [ "$rc2" -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND, feats esac N=$((N+1)) NAME=RAWIP4RECV case "$TESTS" in *%$N%*|*%functions%*|*%ip4%*|*%dgram%*|*%rawip%*|*%rawip4%*|*%recv%*|*%root%*|*%$NAME%*) TEST="$NAME: raw IPv4 receive" if ! eval $NUMCOND; then :; elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1p=$PROTO; PROTO=$((PROTO+1)) ts1a="127.0.0.1" ts1="$ts1a:$ts1p" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts -u IP4-RECV:$ts1p,reuseaddr -" CMD2="$TRACE $SOCAT $opts -u - IP4-SENDTO:$ts1" printf "test $F_n $TEST... " $N $CMD1 >"$tf" 2>"${te}1" & pid1="$!" waitip4proto $ts1p 1 echo "$da" |$CMD2 2>>"${te}2" rc2="$?" #ls -l $tf i=0; while [ ! -s "$tf" -a "$i" -lt 10 ]; do usleep 100000; i=$((i+1)); done kill "$pid1" 2>/dev/null; wait if [ "$rc2" -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND, root esac N=$((N+1)) NAME=RAWIP6RECV case "$TESTS" in *%$N%*|*%functions%*|*%ip6%*|*%dgram%*|*%rawip%*|*%rawip6%*|*%recv%*|*%root%*|*%$NAME%*) TEST="$NAME: raw IPv6 receive" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats ip6 rawip && runsip6); then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1p=$PROTO; PROTO=$((PROTO+1)) ts1a="[::1]" ts1="$ts1a:$ts1p" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts -u IP6-RECV:$ts1p,reuseaddr -" CMD2="$TRACE $SOCAT $opts -u - IP6-SENDTO:$ts1" printf "test $F_n $TEST... " $N $CMD1 >"$tf" 2>"${te}1" & pid1="$!" waitip6proto $ts1p 1 echo "$da" |$CMD2 2>>"${te}2" rc2="$?" i=0; while [ ! -s "$tf" -a "$i" -lt 10 ]; do usleep 100000; i=$((i+1)); done kill "$pid1" 2>/dev/null; wait if [ "$rc2" -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND, root esac N=$((N+1)) NAME=UNIXRECV case "$TESTS" in *%$N%*|*%functions%*|*%unix%*|*%dgram%*|*%recv%*|*%$NAME%*) TEST="$NAME: UNIX receive" if ! eval $NUMCOND; then :; else ts="$td/test$N.socket" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1="$ts" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts -u UNIX-RECV:$ts1,reuseaddr -" CMD2="$TRACE $SOCAT $opts -u - UNIX-SENDTO:$ts1" printf "test $F_n $TEST... " $N $CMD1 >"$tf" 2>"${te}1" & pid1="$!" waitfile $ts1 1 echo "$da" |$CMD2 2>>"${te}2" rc2="$?" i=0; while [ ! -s "$tf" -a "$i" -lt 10 ]; do usleep 100000; i=$((i+1)); done kill "$pid1" 2>/dev/null; wait if [ "$rc2" -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi # NUMCOND ;; esac N=$((N+1)) NAME=UDP4RECVFROM_SOURCEPORT case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%sourceport%*|*%$NAME%*) TEST="$NAME: security of UDP4-RECVFROM with SOURCEPORT option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats udp ip4) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}UDP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else testserversec "$N" "$TEST" "$opts" "udp4-recvfrom:$PORT,reuseaddr" "" "sp=$PORT" "udp4-sendto:127.0.0.1:$PORT" 4 udp $PORT 0 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=UDP4RECVFROM_LOWPORT case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%lowport%*|*%$NAME%*) TEST="$NAME: security of UDP4-RECVFROM with LOWPORT option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats udp ip4) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}UDP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else testserversec "$N" "$TEST" "$opts" "udp4-recvfrom:$PORT,reuseaddr" "" "lowport" "udp4-sendto:127.0.0.1:$PORT" 4 udp $PORT 0 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=UDP4RECVFROM_RANGE case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%range%*|*%$NAME%*) TEST="$NAME: security of UDP4-RECVFROM with RANGE option" #testserversec "$N" "$TEST" "$opts" "udp4-recvfrom:$PORT,reuseaddr,fork" "" "range=$SECONDADDR/32" "udp4-sendto:127.0.0.1:$PORT" 4 udp $PORT 0 if ! eval $NUMCOND; then :; else testserversec "$N" "$TEST" "$opts" "udp4-recvfrom:$PORT,reuseaddr" "" "range=$SECONDADDR/32" "udp4-sendto:127.0.0.1:$PORT" 4 udp $PORT 0 fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) NAME=UDP4RECVFROM_TCPWRAP case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%tcpwrap%*|*%$NAME%*) TEST="$NAME: security of UDP4-RECVFROM with TCPWRAP option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats ip4 udp libwrap) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else ha="$td/hosts.allow" hd="$td/hosts.deny" $ECHO "socat: $SECONDADDR" >"$ha" $ECHO "ALL: ALL" >"$hd" #testserversec "$N" "$TEST" "$opts" "udp4-recvfrom:$PORT,reuseaddr,fork" "" "tcpwrap=$d" "udp4-sendto:127.0.0.1:$PORT" 4 udp $PORT 0 testserversec "$N" "$TEST" "$opts" "udp4-recvfrom:$PORT,reuseaddr" "" "tcpwrap-etc=$td" "udp4-sendto:127.0.0.1:$PORT" 4 udp $PORT 0 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=UDP4RECV_SOURCEPORT case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%sourceport%*|*%$NAME%*) TEST="$NAME: security of UDP4-RECV with SOURCEPORT option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats udp ip4) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}UDP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else PORT1=$PORT; PORT=$((PORT+1)) PORT2=$PORT; PORT=$((PORT+1)) PORT3=$PORT # we use the forward channel (PORT1) for testing, and have a backward channel # (PORT2) to get the data back, so we get the classical echo behaviour testserversec "$N" "$TEST" "$opts" "udp4-recv:$PORT1,reuseaddr!!udp4-sendto:127.0.0.1:$PORT2" "" "sp=$PORT3" "udp4-recv:$PORT2!!udp4-sendto:127.0.0.1:$PORT1" 4 udp $PORT1 0 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=UDP4RECV_LOWPORT case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%lowport%*|*%$NAME%*) TEST="$NAME: security of UDP4-RECV with LOWPORT option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats udp ip4) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}UDP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else PORT1=$PORT; PORT=$((PORT+1)) PORT2=$PORT # we use the forward channel (PORT1) for testing, and have a backward channel # (PORT2) to get the data back, so we get the classical echo behaviour testserversec "$N" "$TEST" "$opts" "udp4-recv:$PORT1,reuseaddr!!udp4-sendto:127.0.0.1:$PORT2" "" "lowport" "udp4-recv:$PORT2!!udp4-sendto:127.0.0.1:$PORT1" 4 udp $PORT1 0 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=UDP4RECV_RANGE case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%range%*|*%$NAME%*) TEST="$NAME: security of UDP4-RECV with RANGE option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats udp ip4) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}UDP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else PORT1=$PORT; PORT=$((PORT+1)) PORT2=$PORT # we use the forward channel (PORT1) for testing, and have a backward channel # (PORT2) to get the data back, so we get the classical echo behaviour testserversec "$N" "$TEST" "$opts" "udp4-recv:$PORT1,reuseaddr!!udp4-sendto:127.0.0.1:$PORT2" "" "range=$SECONDADDR/32" "udp4-recv:$PORT2!!udp4-sendto:127.0.0.1:$PORT1" 4 udp $PORT1 0 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=UDP4RECV_TCPWRAP case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%tcpwrap%*|*%$NAME%*) TEST="$NAME: security of UDP4-RECV with TCPWRAP option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats udp ip4 libwrap) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else PORT1=$PORT; PORT=$((PORT+1)) PORT2=$PORT ha="$td/hosts.allow" hd="$td/hosts.deny" $ECHO "socat: $SECONDADDR" >"$ha" $ECHO "ALL: ALL" >"$hd" # we use the forward channel (PORT1) for testing, and have a backward channel # (PORT2) to get the data back, so we get the classical echo behaviour testserversec "$N" "$TEST" "$opts" "udp4-recv:$PORT1,reuseaddr!!udp4-sendto:127.0.0.1:$PORT2" "" "tcpwrap-etc=$td" "udp4-recv:$PORT2!!udp4-sendto:127.0.0.1:$PORT1" 4 udp $PORT1 0 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=UDP6RECVFROM_SOURCEPORT case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp6%*|*%ip6%*|*%sourceport%*|*%$NAME%*) TEST="$NAME: security of UDP6-RECVFROM with SOURCEPORT option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats udp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}UDP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else testserversec "$N" "$TEST" "$opts" "udp6-recvfrom:$PORT,reuseaddr" "" "sp=$PORT" "udp6-sendto:[::1]:$PORT" 6 udp $PORT 0 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=UDP6RECVFROM_LOWPORT case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp6%*|*%ip6%*|*%lowport%*|*%$NAME%*) TEST="$NAME: security of UDP6-RECVFROM with LOWPORT option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats udp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}UDP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else testserversec "$N" "$TEST" "$opts" "udp6-recvfrom:$PORT,reuseaddr" "" "lowport" "udp6-sendto:[::1]:$PORT" 6 udp $PORT 0 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=UDP6RECVFROM_RANGE case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp6%*|*%ip6%*|*%range%*|*%$NAME%*) TEST="$NAME: security of UDP6-RECVFROM with RANGE option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats tcp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else #testserversec "$N" "$TEST" "$opts" "udp6-recvfrom:$PORT,reuseaddr,fork" "" "range=[::2]/128" "udp6-sendto:[::1]:$PORT" 6 udp $PORT 0 testserversec "$N" "$TEST" "$opts" "udp6-recvfrom:$PORT,reuseaddr" "" "range=[::2]/128" "udp6-sendto:[::1]:$PORT" 6 udp $PORT 0 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=UDP6RECVFROM_TCPWRAP case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp6%*|*%ip6%*|*%tcpwrap%*|*%$NAME%*) TEST="$NAME: security of UDP6-RECVFROM with TCPWRAP option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats udp ip6 libwrap && runsip6); then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else ha="$td/hosts.allow" hd="$td/hosts.deny" $ECHO "socat: [::2]" >"$ha" $ECHO "ALL: ALL" >"$hd" testserversec "$N" "$TEST" "$opts" "udp6-recvfrom:$PORT,reuseaddr" "" "tcpwrap-etc=$td" "udp6-sendto:[::1]:$PORT" 6 udp $PORT 0 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=UDP6RECV_SOURCEPORT case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp6%*|*%ip6%*|*%sourceport%*|*%$NAME%*) TEST="$NAME: security of UDP6-RECV with SOURCEPORT option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats udp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}UDP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else PORT1=$PORT; PORT=$((PORT+1)) PORT2=$PORT; PORT=$((PORT+1)) PORT3=$PORT # we use the forward channel (PORT1) for testing, and have a backward channel # (PORT2) to get the data back, so we get the classical echo behaviour testserversec "$N" "$TEST" "$opts" "udp6-recv:$PORT1,reuseaddr!!udp6-sendto:[::1]:$PORT2" "" "sp=$PORT3" "udp6-recv:$PORT2!!udp6-sendto:[::1]:$PORT1" 6 udp $PORT1 0 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=UDP6RECV_LOWPORT case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp6%*|*%ip6%*|*%lowport%*|*%$NAME%*) TEST="$NAME: security of UDP6-RECV with LOWPORT option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats udp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}UDP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else PORT1=$PORT; PORT=$((PORT+1)) PORT2=$PORT # we use the forward channel (PORT1) for testing, and have a backward channel # (PORT2) to get the data back, so we get the classical echo behaviour testserversec "$N" "$TEST" "$opts" "udp6-recv:$PORT1,reuseaddr!!udp6-sendto:[::1]:$PORT2" "" "lowport" "udp6-recv:$PORT2!!udp6-sendto:[::1]:$PORT1" 6 udp $PORT1 0 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=UDP6RECV_RANGE case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp6%*|*%ip6%*|*%range%*|*%$NAME%*) TEST="$NAME: security of UDP6-RECV with RANGE option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats udp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}UDP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else PORT1=$PORT; PORT=$((PORT+1)) PORT2=$PORT # we use the forward channel (PORT1) for testing, and have a backward channel # (PORT2) to get the data back, so we get the classical echo behaviour testserversec "$N" "$TEST" "$opts" "udp6-recv:$PORT1,reuseaddr!!udp6-sendto:[::1]:$PORT2" "" "range=[::2]/128" "udp6-recv:$PORT2!!udp6-sendto:[::1]:$PORT1" 6 udp $PORT1 0 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=UDP6RECV_TCPWRAP case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp6%*|*%ip6%*|*%tcpwrap%*|*%$NAME%*) TEST="$NAME: security of UDP6-RECV with TCPWRAP option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats udp ip6 libwrap && runsip6); then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else ha="$td/hosts.allow" hd="$td/hosts.deny" $ECHO "socat: [::2]" >"$ha" $ECHO "ALL: ALL" >"$hd" PORT1=$PORT; PORT=$((PORT+1)) PORT2=$PORT # we use the forward channel (PORT1) for testing, and have a backward channel # (PORT2) to get the data back, so we get the classical echo behaviour testserversec "$N" "$TEST" "$opts" "udp6-recv:$PORT1,reuseaddr!!udp6-sendto:[::1]:$PORT2" "" "tcpwrap-etc=$td" "udp6-recv:$PORT2!!udp6-sendto:[::1]:$PORT1" 6 udp $PORT1 0 fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=IP4RECVFROM_RANGE case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%ip%*|*%ip4%*|*%range%*|*%root%*|*%$NAME%*) TEST="$NAME: security of IP4-RECVFROM with RANGE option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats ip4 rawip) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else #testserversec "$N" "$TEST" "$opts" "ip4-recvfrom:$PROTO,reuseaddr,fork" "" "range=$SECONDADDR/32" "ip4-sendto:127.0.0.1:$PROTO" 4 ip $PROTO 0 testserversec "$N" "$TEST" "$opts" "ip4-recvfrom:$PROTO,reuseaddr!!udp4-sendto:127.0.0.1:$PORT" "" "range=$SECONDADDR/32" "udp4-recv:$PORT!!ip4-sendto:127.0.0.1:$PROTO" 4 ip $PROTO 0 fi ;; # NUMCOND, feats, root esac PROTO=$((PROTO+1)) PORT=$((PORT+1)) N=$((N+1)) NAME=IP4RECVFROM_TCPWRAP case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%ip%*|*%ip4%*|*%tcpwrap%*|*%root%*|*%$NAME%*) TEST="$NAME: security of IP4-RECVFROM with TCPWRAP option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats ip4 rawip libwrap) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else ha="$td/hosts.allow" hd="$td/hosts.deny" $ECHO "socat: $SECONDADDR" >"$ha" $ECHO "ALL: ALL" >"$hd" #testserversec "$N" "$TEST" "$opts" "ip4-recvfrom:$PROTO,reuseaddr,fork" "" "tcpwrap-etc=$td" "ip4-sendto:127.0.0.1:$PROTO" 4 ip $PROTO 0 testserversec "$N" "$TEST" "$opts" "ip4-recvfrom:$PROTO,reuseaddr!!udp4-sendto:127.0.0.1:$PORT" "" "tcpwrap-etc=$td" "udp4-recv:$PORT!!ip4-sendto:127.0.0.1:$PROTO" 4 ip $PROTO 0 fi # NUMCOND, feats, root ;; esac PROTO=$((PROTO+1)) PORT=$((PORT+1)) N=$((N+1)) NAME=IP4RECV_RANGE case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%ip%*|*%ip4%*|*%range%*|*%root%*|*%$NAME%*) TEST="$NAME: security of IP4-RECV with RANGE option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats ip4 rawip) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}IP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else PROTO1=$PROTO; PROTO=$((PROTO+1)) PROTO2=$PROTO # we use the forward channel (PROTO1) for testing, and have a backward channel # (PROTO2) to get the data back, so we get the classical echo behaviour testserversec "$N" "$TEST" "$opts" "ip4-recv:$PROTO1,reuseaddr!!ip4-sendto:127.0.0.1:$PROTO2" "" "range=$SECONDADDR/32" "ip4-recv:$PROTO2!!ip4-sendto:127.0.0.1:$PROTO1" 4 ip $PROTO1 0 fi ;; # NUMCOND, feats, root esac PROTO=$((PROTO+1)) N=$((N+1)) NAME=IP4RECV_TCPWRAP case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%ip%*|*%ip4%*|*%tcpwrap%*|*%root%*|*%$NAME%*) TEST="$NAME: security of IP4-RECV with TCPWRAP option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats ip4 rawip libwrap) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else PROTO1=$PROTO; PROTO=$((PROTO+1)) PROTO2=$PROTO ha="$td/hosts.allow" hd="$td/hosts.deny" $ECHO "socat: $SECONDADDR" >"$ha" $ECHO "ALL: ALL" >"$hd" # we use the forward channel (PROTO1) for testing, and have a backward channel # (PROTO2) to get the data back, so we get the classical echo behaviour testserversec "$N" "$TEST" "$opts" "ip4-recv:$PROTO1,reuseaddr!!ip4-sendto:127.0.0.1:$PROTO2" "" "tcpwrap-etc=$td" "ip4-recv:$PROTO2!!ip4-sendto:127.0.0.1:$PROTO1" 4 ip $PROTO1 0 fi ;; # NUMCOND, feats, root esac PROTO=$((PROTO+1)) N=$((N+1)) NAME=IP6RECVFROM_RANGE case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%ip%*|*%ip6%*|*%range%*|*%root%*|*%$NAME%*) TEST="$NAME: security of IP6-RECVFROM with RANGE option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats ip6 rawip && runsip6); then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else #testserversec "$N" "$TEST" "$opts" "ip6-recvfrom:$PROTO,reuseaddr,fork" "" "range=[::2]/128" "ip6-sendto:[::1]:$PROTO" 6 ip $PROTO 0 testserversec "$N" "$TEST" "$opts" "ip6-recvfrom:$PROTO,reuseaddr!!udp6-sendto:[::1]:$PORT" "" "range=[::2]/128" "udp6-recv:$PORT!!ip6-sendto:[::1]:$PROTO" 6 ip $PROTO 0 fi ;; # NUMCOND, feats esac PROTO=$((PROTO+1)) PORT=$((PORT+1)) N=$((N+1)) NAME=IP6RECVFROM_TCPWRAP case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%ip%*|*%ip6%*|*%tcpwrap%*|*%root%*|*%$NAME%*) TEST="$NAME: security of IP6-RECVFROM with TCPWRAP option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats ip6 rawip libwrap && runsip6); then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else ha="$td/hosts.allow" hd="$td/hosts.deny" $ECHO "socat: [::2]" >"$ha" $ECHO "ALL: ALL" >"$hd" #testserversec "$N" "$TEST" "$opts" "ip6-recvfrom:$PROTO,reuseaddr,fork" "" "tcpwrap-etc=$td" "ip6-sendto:[::1]:$PROTO" 6 ip $PROTO 0 testserversec "$N" "$TEST" "$opts" "ip6-recvfrom:$PROTO,reuseaddr!!udp6-sendto:[::1]:$PORT" "" "tcpwrap-etc=$td" "udp6-recv:$PORT!!ip6-sendto:[::1]:$PROTO" 6 ip $PROTO 0 fi ;; # NUMCOND, feats esac PROTO=$((PROTO+1)) PORT=$((PORT+1)) N=$((N+1)) NAME=IP6RECV_RANGE case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%ip%*|*%ip6%*|*%range%*|*%root%*|*%$NAME%*) TEST="$NAME: security of IP6-RECV with RANGE option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats ip6 rawip) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}raw IP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else PROTO1=$PROTO; PROTO=$((PROTO+1)) PROTO2=$PROTO # we use the forward channel (PROTO1) for testing, and have a backward channel # (PROTO2) to get the data back, so we get the classical echo behaviour testserversec "$N" "$TEST" "$opts" "ip6-recv:$PROTO1,reuseaddr!!ip6-sendto:[::1]:$PROTO2" "" "range=[::2]/128" "ip6-recv:$PROTO2!!ip6-sendto:[::1]:$PROTO1" 6 ip $PROTO1 0 fi ;; # NUMCOND, feats esac PROTO=$((PROTO+1)) N=$((N+1)) NAME=IP6RECV_TCPWRAP case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%ip%*|*%ip6%*|*%tcpwrap%*|*%root%*|*%$NAME%*) TEST="$NAME: security of IP6-RECV with TCPWRAP option" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats ip6 rawip libwrap && runsip6); then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else PROTO1=$PROTO; PROTO=$((PROTO+1)) PROTO2=$PROTO ha="$td/hosts.allow" hd="$td/hosts.deny" $ECHO "socat: [::2]" >"$ha" $ECHO "ALL: ALL" >"$hd" # we use the forward channel (PROTO1) for testing, and have a backward channel # (PROTO2) to get the data back, so we get the classical echo behaviour testserversec "$N" "$TEST" "$opts" "ip6-recv:$PROTO1,reuseaddr!!ip6-sendto:[::1]:$PROTO2" "" "tcpwrap-etc=$td" "ip6-recv:$PROTO2!!ip6-sendto:[::1]:$PROTO1" 6 ip $PROTO1 0 fi ;; # NUMCOND, feats esac PROTO=$((PROTO+1)) N=$((N+1)) NAME=O_NOATIME_FILE case "$TESTS" in *%$N%*|*%functions%*|*%open%*|*%noatime%*|*%$NAME%*) TEST="$NAME: option O_NOATIME on file" # idea: create a file with o-noatime option; one second later create a file # without this option (using touch); one second later read from the first file. # Then we check which file has the later ATIME stamp. For this check we use # "ls -ltu" because it is more portable than "test ... -nt ..." if ! eval $NUMCOND; then :; elif ! testoptions o-noatime >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}o-noatime not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.file" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" $PRINTF "test $F_n $TEST... " $N CMD="$TRACE $SOCAT $opts -u open:\"${tf}1\",o-noatime /dev/null" # generate a file touch "${tf}1" sleep 1 # generate a reference file touch "${tf}2" sleep 1 # read from the first file $CMD 2>"$te" if [ $? -ne 0 ]; then # command failed $PRINTF "${FAILED}:\n" echo "$CMD" cat "$te" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else # check which file has a later atime stamp if [ $(ls -ltu "${tf}1" "${tf}2" |head -1 |sed 's/.* //') != "${tf}2" ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD" cat "$te" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "$te"; fi numOK=$((numOK+1)) fi # wrong time stamps fi # command ok fi ;; # NUMCOND, feats esac N=$((N+1)) NAME=O_NOATIME_FD case "$TESTS" in *%$N%*|*%functions%*|*%noatime%*|*%$NAME%*) TEST="$NAME: option O_NOATIME on file descriptor" # idea: use a fd of a file with o-noatime option; one second later create a file # without this option (using touch); one second later read from the first file. # Then we check which file has the later ATIME stamp. For this check we use # "ls -ltu" because it is more portable than "test ... -nt ..." if ! eval $NUMCOND; then :; elif ! testoptions o-noatime >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}o-noatime not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.file" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" $PRINTF "test $F_n $TEST... " $N touch ${tf}1 CMD="$TRACE $SOCAT $opts -u -,o-noatime /dev/null <${tf}1" # generate a file, len >= 1 touch "${tf}1" sleep 1 # generate a reference file touch "${tf}2" sleep 1 # read from the first file sh -c "$CMD" 2>"$te" if [ $? -ne 0 ]; then # command failed $PRINTF "${FAILED}:\n" echo "$CMD" cat "$te" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else # check which file has a later atime stamp if [ $(ls -ltu "${tf}1" "${tf}2" |head -1 |sed 's/.* //') != "${tf}2" ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD" cat "$te" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "$te"; fi numOK=$((numOK+1)) fi # wrong time stamps fi # command ok fi ;; # NUMCOND, feats esac N=$((N+1)) NAME=FS_NOATIME case "$TESTS" in *%$N%*|*%functions%*|*%fs%*|*%noatime%*|*%$NAME%*) TEST="$NAME: extended file system options using fs noatime option" # idea: create a file with fs-noatime option; one second later create a file # without this option (using touch); one second later read from the first file. # Then we check which file has the later ATIME stamp. For this check we use # "ls -ltu" because it is more portable than "test ... -nt ..." if ! eval $NUMCOND; then :; elif ! testoptions fs-noatime >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}fs-noatime not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else ts="$td/test$N.socket" tf="$td/test$N.file" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1="$ts" da="test$N $(date) $RANDOM" $PRINTF "test $F_n $TEST... " $N CMD0="$TRACE $SOCAT $opts -u /dev/null create:\"${tf}1\"" CMD="$TRACE $SOCAT $opts -u /dev/null create:\"${tf}1\",fs-noatime" # check if this is a capable FS; lsattr does other things on AIX, thus socat $CMD0 2>"${te}0" if [ $? -ne 0 ]; then $PRINTF "${YELLOW} cannot test${NORMAL}\n" numCANT=$((numCANT+1)) listCANT="$listCANT $N" else # generate a file with noatime, len >= 1 $CMD 2>"$te" if [ $? -ne 0 ]; then # command failed $PRINTF "${YELLOW}impotent file system?${NORMAL}\n" echo "$CMD" cat "$te" numCANT=$((numCANT+1)) listCANT="$listCANT $N" else sleep 1 # generate a reference file touch "${tf}2" sleep 1 # read from the first file cat "${tf}1" >/dev/null # check which file has a later atime stamp #if [ $(ls -ltu "${tf}1" "${tf}2" |head -n 1 |awk '{print($8);}') != "${tf}2" ]; if [ $(ls -ltu "${tf}1" "${tf}2" |head -n 1 |sed "s|.*\\($td.*\\)|\1|g") != "${tf}2" ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD" cat "$te" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "$te"; fi numOK=$((numOK+1)) fi fi # not impotent fi # can test fi ;; # NUMCOND, feats esac N=$((N+1)) NAME=COOLWRITE case "$TESTS" in *%$N%*|*%functions%*|*%engine%*|*%timeout%*|*%coolwrite%*|*%$NAME%*) TEST="$NAME: option cool-write" if ! eval $NUMCOND; then :; elif ! testoptions cool-write >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}option cool-write not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else #set -vx ti="$td/test$N.pipe" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" # a reader that will terminate after 1 byte CMD1="$TRACE $SOCAT $opts -u pipe:\"$ti\",readbytes=1 /dev/null" CMD="$TRACE $SOCAT $opts -u - file:\"$ti\",cool-write" printf "test $F_n $TEST... " $N $CMD1 2>"${te}1" & bg=$! # background process id sleep 1 (echo .; sleep 1; echo) |$CMD 2>"$te" rc=$? kill $bg 2>/dev/null; wait if [ $rc -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD &" cat "$te" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "$te"; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND, feats esac N=$((N+1)) # test if option coolwrite can be applied to bidirectional address stdio # this failed up to socat 1.6.0.0 NAME=COOLSTDIO case "$TESTS" in *%$N%*|*%functions%*|*%engine%*|*%timeout%*|*%coolwrite%*|*%$NAME%*) TEST="$NAME: option cool-write on bidirectional stdio" # this test starts a socat reader that terminates after receiving one+ # bytes (option readbytes); and a test process that sends two bytes via # named pipe to the receiving process and, a second later, sends another # byte. The last write will fail with "broken pipe"; if option coolwrite # has been applied successfully, socat will terminate with 0 (OK), # otherwise with error. if ! eval $NUMCOND; then :; elif ! testoptions cool-write >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}option cool-write not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else #set -vx ti="$td/test$N.pipe" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" # a reader that will terminate after 1 byte CMD1="$TRACE $SOCAT $opts -u pipe:\"$ti\",readbytes=1 /dev/null" CMD="$TRACE $SOCAT $opts -,cool-write pipe >\"$ti\"" printf "test $F_n $TEST... " $N $CMD1 2>"${te}1" & bg=$! # background process id sleep 1 (echo .; sleep 1; echo) |eval "$CMD" 2>"$te" rc=$? kill $bg 2>/dev/null; wait if [ $rc -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" cat "${te}1" echo "$CMD" cat "$te" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "$te"; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND, feats esac N=$((N+1)) NAME=TCP4ENDCLOSE case "$TESTS" in *%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%tcp%*|*%$NAME%*) TEST="$NAME: end-close keeps TCP V4 socket open" if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" p1=$PORT; PORT=$((PORT+1)) p2=$PORT da1a="$(date) $RANDOM" da1b="$(date) $RANDOM" CMD1="$TRACE $SOCAT $opts -u - TCP4-CONNECT:$LOCALHOST:$p1" CMD="$TRACE $SOCAT $opts -U TCP4:$LOCALHOST:$p2,end-close TCP4-LISTEN:$p1,bind=$LOCALHOST,$REUSEADDR,fork" CMD3="$TRACE $SOCAT $opts -u TCP4-LISTEN:$p2,$REUSEADDR,bind=$LOCALHOST -" printf "test $F_n $TEST... " $N $CMD3 >"$tf" 2>"${te}3" & pid3=$! waittcp4port $p2 1 $CMD 2>"${te}2" & pid2=$! usleep $MICROS waittcp4port $p1 1 echo "$da1a" |$CMD1 2>>"${te}1a" echo "$da1b" |$CMD1 2>>"${te}1b" sleep 1 kill "$pid3" "$pid2" 2>/dev/null wait if [ $? -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1a" "${te}1b" "${te}2" "${te}3" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! $ECHO "$da1a\n$da1b" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" cat "${te}1a" "${te}1b" "${te}2" "${te}3" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1a" "${te}1b" "${te}2" "${te}3"; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) NAME=EXECENDCLOSE case "$TESTS" in *%$N%*|*%functions%*|*%exec%*|*%$NAME%*) TEST="$NAME: end-close keeps EXEC child running" if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" ts="$td/test$N.sock" tdiff="$td/test$N.diff" da1a="$(date) $RANDOM" da1b="$(date) $RANDOM" CMD1="$TRACE $SOCAT $opts - UNIX-CONNECT:$ts" CMD="$TRACE $SOCAT $opts EXEC:"$CAT",end-close UNIX-LISTEN:$ts,fork" printf "test $F_n $TEST... " $N $CMD 2>"${te}2" & pid2=$! waitfile $ts 1 echo "$da1a" |$CMD1 2>>"${te}1a" >"$tf" usleep $MICROS echo "$da1b" |$CMD1 2>>"${te}1b" >>"$tf" #usleep $MICROS kill "$pid2" 2>/dev/null wait if [ $? -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1a" "${te}1b" "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! $ECHO "$da1a\n$da1b" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" cat "${te}1a" "${te}1b" "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1a" "${te}1b" "${te}2"; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND esac N=$((N+1)) # up to 1.7.0.0 option end-close led to an error with some address types due to # bad internal handling. here we check it for address PTY NAME=PTYENDCLOSE case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%pty%*|*%$NAME%*) TEST="$NAME: PTY handles option end-close" # with the bug, socat exits with error. we invoke socat in a no-op mode and # check its return status. if ! eval $NUMCOND; then :; else tf="$td/test$N.stout" te="$td/test$N.stderr" CMD="$TRACE $SOCAT $opts -d -d /dev/null pty,end-close" printf "test $F_n $TEST... " $N # AIX reports the pty writeable for select() only when its slave side has been # opened, therefore we run this process in background and check its NOTICE # output for the PTY name { $CMD 2>"${te}"; echo $? >"$td/test$N.rc0"; } & waitfile "${te}" psleep 0.1 PTY=$(grep "N PTY is " $te |sed 's/.*N PTY is //') [ -e "$PTY" ] && cat $PTY >/dev/null rc=$(cat "$td/test$N.rc0") if [ "$rc" = 0 ]; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD" cat "${te}" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac N=$((N+1)) # Test the shut-null and null-eof options NAME=SHUTNULLEOF case "$TESTS" in *%$N%*|*%functions%*|*%socket%*|*%$NAME%*) TEST="$NAME: options shut-null and null-eof" # Run a receiving background process with option null-eof. # Start a sending process with option shut-null that sends a test record to the # receiving process and then terminates. # Send another test record. # When the receiving process only received and stored the first test record the # test succeeded if ! eval $NUMCOND; then :; else tf="$td/test$N.stout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts -u UDP-RECV:$PORT,null-eof CREAT:$tf" CMD1="$TRACE $SOCAT $opts -u - UDP-SENDTO:127.0.0.1:$PORT,shut-null" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" & pid0=$! waitudp4port $PORT 1 { echo "$da"; psleep 0.1; } |$CMD1 >"${tf}1" 2>"${te}1" rc1=$? { echo "xyz"; psleep 0.1; } |$CMD1 >"${tf}2" 2>"${te}2" rc2=$? kill $pid0 2>/dev/null; wait if [ $rc1 != 0 -o $rc2 != 0 ]; then $PRINTF "$FAILED\n" echo "$CMD0 &" echo "$CMD1" cat "${te}0" cat "${te}1" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif echo "$da" |diff - "${tf}" >"$tdiff"; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0 &" echo "$CMD1" cat "${te}0" cat "${te}1" cat "${tdiff}" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac N=$((N+1)) NAME=UDP6LISTENBIND # this tests for a bug in (up to) 1.5.0.0: # with udp*-listen, the bind option supported only IPv4 case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%ip6%*|*%ipapp%*|*%udp%*|*%udp6%*|*%$NAME%*) TEST="$NAME: UDP6-LISTEN with bind" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats udp ip6) || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}UDP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="$LOCALHOST6:$tsl" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts UDP6-LISTEN:$tsl,$REUSEADDR,bind=$LOCALHOST6 PIPE" CMD2="$TRACE $SOCAT $opts - UDP6:$ts" printf "test $F_n $TEST... " $N $CMD1 >"$tf" 2>"${te}1" & pid1=$! waitudp6port $tsl 1 echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" rc2=$? kill $pid1 2>/dev/null; wait if [ $rc2 -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=TCPWRAPPERS_MULTIOPTS # this tests for a bug in 1.5.0.0 that let socat fail when more than one # tcp-wrappers related option was specified in one address case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%tcpwrap%*|*%$NAME%*) TEST="$NAME: use of multiple tcpwrapper enabling options" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats tcp ip4 libwrap) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" ha="$td/hosts.allow" $ECHO "test : ALL : allow" >"$ha" CMD1="$TRACE $SOCAT $opts TCP4-LISTEN:$PORT,$REUSEADDR,hosts-allow=$ha,tcpwrap=test pipe" CMD2="$TRACE $SOCAT $opts - TCP:$LOCALHOST:$PORT" printf "test $F_n $TEST... " $N $CMD1 2>"${te}1" & pid1=$! waittcp4port $PORT echo "$da" |$CMD2 >"$tf" 2>"${te}2" rc2=$? kill $pid1 2>/dev/null; wait if [ $rc2 -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=TCPWRAPPERS_TCP6ADDR # this tests for a bug in 1.5.0.0 that brought false results with tcp-wrappers # and IPv6 when case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%tcpwrap%*|*%$NAME%*) TEST="$NAME: specification of TCP6 address in hosts.allow" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats tcp ip6 libwrap && runsip6); then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" ha="$td/hosts.allow" hd="$td/hosts.deny" $ECHO "socat : [::1] : allow" >"$ha" $ECHO "ALL : ALL : deny" >"$hd" CMD1="$TRACE $SOCAT $opts TCP6-LISTEN:$PORT,$REUSEADDR,tcpwrap-etc=$td,tcpwrappers=socat pipe" CMD2="$TRACE $SOCAT $opts - TCP6:[::1]:$PORT" printf "test $F_n $TEST... " $N $CMD1 2>"${te}1" & pid1=$! waittcp6port $PORT echo "$da" |$CMD2 >"$tf" 2>"${te}2" rc2=$? kill $pid1 2>/dev/null; wait if [ $rc2 -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=UDP4BROADCAST case "$TESTS" in *%$N%*|*%functions%*|*%udp%*|*%udp4%*|*%ip4%*|*%dgram%*|*%broadcast%*|*%$NAME%*) TEST="$NAME: UDP/IPv4 broadcast" if ! eval $NUMCOND; then :; elif [ -z "$BCADDR" ]; then $PRINTF "test $F_n $TEST... ${YELLOW}dont know a broadcast address${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1p=$PORT; PORT=$((PORT+1)) #ts1="$BCADDR/8:$ts1p" ts1="$BCADDR:$ts1p" ts2p=$PORT; PORT=$((PORT+1)) ts2="$BCIFADDR:$ts2p" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts UDP4-RECVFROM:$ts1p,reuseaddr,broadcast PIPE" #CMD2="$TRACE $SOCAT $opts - UDP4-BROADCAST:$ts1" CMD2="$TRACE $SOCAT $opts - UDP4-DATAGRAM:$ts1,broadcast" printf "test $F_n $TEST... " $N $CMD1 2>"${te}1" & pid1="$!" waitudp4port $ts1p 1 echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" rc2="$?" kill "$pid1" 2>/dev/null; wait; if [ "$rc2" -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$tut" ]; then echo "$CMD1 &" echo "$CMD2" fi if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND, feats esac N=$((N+1)) NAME=IP4BROADCAST # test a local broadcast of a raw IPv4 protocol. # because we receive - in addition to the regular reply - our own broadcast, # we use a token XXXX that is changed to YYYY in the regular reply packet. case "$TESTS" in *%$N%*|*%functions%*|*%engine%*|*%rawip%*|*%rawip4%*|*%ip4%*|*%dgram%*|*%broadcast%*|*%root%*|*%$NAME%*) TEST="$NAME: raw IPv4 broadcast" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats ip4 rawip) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}raw IP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ -z "$BCADDR" ]; then $PRINTF "test $F_n $TEST... ${YELLOW}dont know a broadcast address${NORMAL}\n" $N else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1p=$PROTO #ts1="$BCADDR/8:$ts1p" ts1="$BCADDR:$ts1p" ts2p=$ts1p ts2="$BCIFADDR" da="test$N $(date) $RANDOM XXXX" sh="$td/test$N-sed.sh" echo 'sed s/XXXX/YYYY/' >"$sh" chmod a+x "$sh" # EXEC need not work with script (musl libc), so use SYSTEM CMD1="$TRACE $SOCAT $opts IP4-RECVFROM:$ts1p,reuseaddr,broadcast SYSTEM:$sh" #CMD2="$TRACE $SOCAT $opts - IP4-BROADCAST:$ts1" CMD2="$TRACE $SOCAT $opts - IP4-DATAGRAM:$ts1,broadcast" printf "test $F_n $TEST... " $N $CMD1 2>"${te}1" & pid1="$!" waitip4port $ts1p 1 echo "$da" |$CMD2 2>>"${te}2" |grep -v XXXX >>"$tf" rc2="$?" kill "$pid1" 2>/dev/null; wait; if [ "$rc2" -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" | sed 's/XXXX/YYYY/'|diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND, feats esac PROTO=$((PROTO+1)) N=$((N+1)) #NAME=UDP4BROADCAST_RANGE #case "$TESTS" in #*%$N%*|*%functions%*|*%security%*|*%udp%*|*%udp4%*|*%ip4%*|*%dgram%*|*%broadcast%*|*%range%*|*%$NAME%*) #TEST="$NAME: security of UDP4-BROADCAST with RANGE option" #if ! eval $NUMCOND; then :; #elif [ -z "$BCADDR" ]; then # $PRINTF "test $F_n $TEST... ${YELLOW}dont know a broadcast address${NORMAL}\n" $N #else #testserversec "$N" "$TEST" "$opts" "UDP4-BROADCAST:$BCADDR/8:$PORT" "" "range=127.1.0.0:255.255.0.0" "udp4:127.1.0.0:$PORT" 4 udp $PORT 0 #fi ;; # NUMCOND, feats #esac #PORT=$((PORT+1)) #N=$((N+1)) NAME=UDP4MULTICAST_UNIDIR case "$TESTS" in *%$N%*|*%functions%*|*%udp%*|*%udp4%*|*%ip4%*|*%dgram%*|*%multicast%*|*%$NAME%*) TEST="$NAME: UDP/IPv4 multicast, send only" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats ip4 udp) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1p=$PORT; PORT=$((PORT+1)) ts1a="$SECONDADDR" ts1="$ts1a:$ts1p" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT -u $opts UDP4-RECV:$ts1p,reuseaddr,ip-add-membership=224.255.255.254:$ts1a -" CMD2="$TRACE $SOCAT -u $opts - UDP4-SENDTO:224.255.255.254:$ts1p,bind=$ts1a" printf "test $F_n $TEST... " $N $CMD1 2>"${te}1" >"${tf}" & pid1="$!" waitudp4port $ts1p 1 echo "$da" |$CMD2 2>>"${te}2" rc2="$?" usleep $MICROS kill "$pid1" 2>/dev/null; wait; if [ "$rc2" -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND, feats esac N=$((N+1)) NAME=IP4MULTICAST_UNIDIR case "$TESTS" in *%$N%*|*%functions%*|*%rawip%*|*%ip4%*|*%dgram%*|*%multicast%*|*%root%*|*%$NAME%*) TEST="$NAME: IPv4 multicast" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats ip4 rawip) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1p=$PROTO ts1a="$SECONDADDR" ts1="$ts1a:$ts1p" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT -u $opts IP4-RECV:$ts1p,reuseaddr,ip-add-membership=224.255.255.254:$ts1a -" CMD2="$TRACE $SOCAT -u $opts - IP4-SENDTO:224.255.255.254:$ts1p,bind=$ts1a" printf "test $F_n $TEST... " $N $CMD1 2>"${te}1" >"${tf}" & pid1="$!" waitip4proto $ts1p 1 usleep $MICROS echo "$da" |$CMD2 2>>"${te}2" rc2="$?" #usleep $MICROS sleep 1 kill "$pid1" 2>/dev/null; wait; if [ "$rc2" -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND, feats esac PROTO=$((PROTO+1)) N=$((N+1)) if true; then # This test succeeds, e.g., on CentOS-7 with kernel 3.10.0, Ubuntu-16.04 with 4.4.0 # but fails, e.g., on Ubuntu-18.04 with kernel 4.15.0, CentOS-8 with 4.10.0 NAME=UDP6MULTICAST_UNIDIR case "$TESTS" in *%$N%*|*%functions%*|*%udp%*|*%udp6%*|*%ip6%*|*%dgram%*|*%multicast%*|*%$NAME%*) TEST="$NAME: UDP/IPv6 multicast" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats ip6 udp && runsip6); then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1p=$PORT; PORT=$((PORT+1)) if1="$MCINTERFACE" ts1a="[::1]" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT -u $opts UDP6-RECV:$ts1p,reuseaddr,ipv6-join-group=[ff02::2]:$if1 -" CMD2="$TRACE $SOCAT -u $opts - UDP6-SENDTO:[ff02::2]:$ts1p,bind=$ts1a" #CMD2="$TRACE $SOCAT -u $opts - UDP6-SENDTO:[ff02::2]:$ts1p" printf "test $F_n $TEST... " $N $CMD1 2>"${te}1" >"${tf}" & pid1="$!" waitudp6port $ts1p 1 echo "$da" |$CMD2 2>>"${te}2" rc2="$?" usleep $MICROS kill "$pid1" 2>/dev/null; wait; if [ "$rc2" -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo -e "$CMD1 &\n$CMD2" cat "${te}1" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then if ! [ "$UNAME" = Linux ] || ! [[ $(uname -r) =~ ^2\.* ]] || ! [[ ^3\.* ]] || ! [[ ^4\.[0-4]\.* ]]; then $PRINTF "${YELLOW}works only on Linux up to about 4.4${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else $PRINTF "$FAILED\n" echo "$CMD1 &" echo "$CMD2" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi else $PRINTF "$OK\n" if [ "$VERBOSE" ]; then echo -e "$CMD1 &\n$CMD2"; fi if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND, feats esac N=$((N+1)) fi # false NAME=UDP4MULTICAST_BIDIR case "$TESTS" in *%$N%*|*%functions%*|*%udp%*|*%udp4%*|*%ip4%*|*%dgram%*|*%multicast%*|*%$NAME%*) TEST="$NAME: UDP/IPv4 multicast, with reply" if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1p=$PORT; PORT=$((PORT+1)) ts1a="$SECONDADDR" ts1="$ts1a:$ts1p" ts2p=$PORT; PORT=$((PORT+1)) ts2="$BCIFADDR:$ts2p" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts UDP4-RECVFROM:$ts1p,reuseaddr,ip-add-membership=224.255.255.254:$ts1a PIPE" #CMD2="$TRACE $SOCAT $opts - UDP4-MULTICAST:224.255.255.254:$ts1p,bind=$ts1a" CMD2="$TRACE $SOCAT $opts - UDP4-DATAGRAM:224.255.255.254:$ts1p,bind=$ts1a" printf "test $F_n $TEST... " $N $CMD1 2>"${te}1" & pid1="$!" waitudp4port $ts1p 1 echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" rc2="$?" kill "$pid1" 2>/dev/null; wait; if [ "$rc2" -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$VERBOSE" ]; then echo "$CMD1 &" echo "$CMD2" fi if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND esac N=$((N+1)) NAME=IP4MULTICAST_BIDIR case "$TESTS" in *%$N%*|*%functions%*|*%rawip%*|*%ip4%*|*%dgram%*|*%multicast%*|*%root%*|*%$NAME%*) TEST="$NAME: IPv4 multicast, with reply" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats ip4 rawip) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1p=$PROTO ts1a="$SECONDADDR" ts1="$ts1a:$ts1p" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts IP4-RECVFROM:$ts1p,reuseaddr,ip-add-membership=224.255.255.254:$ts1a PIPE" #CMD2="$TRACE $SOCAT $opts - IP4-MULTICAST:224.255.255.254:$ts1p,bind=$ts1a" CMD2="$TRACE $SOCAT $opts - IP4-DATAGRAM:224.255.255.254:$ts1p,bind=$ts1a" printf "test $F_n $TEST... " $N $CMD1 2>"${te}1" & pid1="$!" waitip4port $ts1p 1 usleep 100000 # give process a chance to add multicast membership echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" rc2="$?" kill "$pid1" 2>/dev/null; wait; if [ "$rc2" -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$tut" ]; then echo "$CMD1 &" echo "$CMD2" fi if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND, feats esac PROTO=$((PROTO+1)) N=$((N+1)) NAME=TUNREAD case "$TESTS" in *%$N%*|*%functions%*|*%tun%*|*%root%*|*%$NAME%*) TEST="$NAME: reading data sent through tun interface" #idea: create a TUN interface and send a datagram to one of the addresses of # its virtual network. On the tunnel side, read the packet and compare its last # bytes with the datagram payload if ! eval $NUMCOND; then :; elif ! feat=$(testfeats ip4 tun) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" tl="$td/test$N.lock" da="test$N $(date) $RANDOM" dalen=$((${#da}+1)) TUNNET=10.255.255 CMD1="$TRACE $SOCAT $opts -u - UDP4-SENDTO:$TUNNET.2:$PORT" #CMD="$TRACE $SOCAT $opts -u -L $tl TUN,ifaddr=$TUNNET.1,netmask=255.255.255.0,iff-up=1 -" CMD="$TRACE $SOCAT $opts -u -L $tl TUN:$TUNNET.1/24,iff-up=1 -" printf "test $F_n $TEST... " $N $CMD 2>"${te}" |tail -c $dalen >"${tf}" & sleep 1 echo "$da" |$CMD1 2>"${te}1" sleep 1 kill "$(cat $tl 2>/dev/null)" 2>/dev/null wait if [ $? -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD &" echo "$CMD1" cat "${te}" "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" echo "$CMD &" echo "$CMD1" cat "$tdiff" cat "${te}" "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}" "${te}1"; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) # use the INTERFACE address on a tun/tap device and transfer data fully # transparent NAME=TUNINTERFACE case "$TESTS" in *%$N%*|*%functions%*|*%tun%*|*%interface%*|*%root%*|*%$NAME%*) TEST="$NAME: pass data through tun interface using INTERFACE" #idea: create a TUN interface and send a raw packet on the interface side. # It should arrive unmodified on the tunnel side. if ! eval $NUMCOND; then :; elif ! feat=$(testfeats ip4 tun interface) || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" tl="$td/test$N.lock" da="$(date) $RANDOM" TUNNET=10.255.255 TUNNAME=tun9 CMD1="$TRACE $SOCAT $opts -L $tl TUN:$TUNNET.1/24,iff-up=1,tun-type=tun,tun-name=$TUNNAME echo" CMD="$TRACE $SOCAT $opts - INTERFACE:$TUNNAME" printf "test $F_n $TEST... " $N $CMD1 2>"${te}1" & pid1="$!" #waitinterface "$TUNNAME" sleep 1 echo "$da" |$CMD >"$tf" 2>"${te}" kill $pid1 2>/dev/null wait if [ $? -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD &" echo "$CMD1" cat "${te}" "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" echo "$CMD &" echo "$CMD1" cat "$tdiff" cat "${te}" "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}" "${te}1"; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=ABSTRACTSTREAM case "$TESTS" in *%$N%*|*%functions%*|*%unix%*|*%abstract%*|*%connect%*|*%listen%*|*%$NAME%*) TEST="$NAME: abstract UNIX stream socket, listen and connect" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats abstract-unixsocket); then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else ts="$td/test$N.socket" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da1="test$N $(date) $RANDOM" #establish a listening abstract unix socket SRV="$TRACE $SOCAT $opts -lpserver ABSTRACT-LISTEN:\"$ts\",$REUSEADDR PIPE" #make a connection CMD="$TRACE $SOCAT $opts - ABSTRACT-CONNECT:$ts" $PRINTF "test $F_n $TEST... " $N touch "$ts" # make a file with same name, so non-abstract fails eval "$SRV 2>${te}s &" pids=$! #waitfile "$ts" sleep 1 echo "$da1" |eval "$CMD" >"${tf}1" 2>"${te}1" if [ $? -ne 0 ]; then kill "$pids" 2>/dev/null $PRINTF "$FAILED:\n" echo "$SRV &" cat "${te}s" echo "$CMD" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da1" |diff - "${tf}1" >"$tdiff"; then kill "$pids" 2>/dev/null $PRINTF "$FAILED:\n" echo "$SRV &" cat "${te}s" echo "$CMD" cat "${te}1" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi # !(rc -ne 0) wait fi ;; # NUMCOND, feats esac N=$((N+1)) NAME=ABSTRACTDGRAM case "$TESTS" in *%$N%*|*%functions%*|*%unix%*|*%abstract%*|*%dgram%*|*%$NAME%*) TEST="$NAME: abstract UNIX datagram" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats abstract-unixsocket); then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1="$td/test$N.socket1" ts2="$td/test$N.socket2" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts ABSTRACT-RECVFROM:$ts1,reuseaddr PIPE" #CMD2="$TRACE $SOCAT $opts - ABSTRACT-SENDTO:$ts1,bind=$ts2" CMD2="$TRACE $SOCAT $opts - ABSTRACT-SENDTO:$ts1,bind=$ts2" printf "test $F_n $TEST... " $N touch "$ts1" # make a file with same name, so non-abstract fails $CMD1 2>"${te}1" & pid1="$!" sleep 1 echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" rc2=$? kill "$pid1" 2>/dev/null; wait if [ $rc2 -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" cat "${te}1" echo "$CMD2" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND, feats esac N=$((N+1)) NAME=ABSTRACTRECV case "$TESTS" in *%$N%*|*%functions%*|*%unix%*|*%abstract%*|*%dgram%*|*%recv%*|*%$NAME%*) TEST="$NAME: abstract UNIX datagram receive" if ! eval $NUMCOND; then :; elif ! feat=$(testfeats abstract-unixsocket); then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else ts="$td/test$N.socket" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1="$ts" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts -u ABSTRACT-RECV:$ts1,reuseaddr -" CMD2="$TRACE $SOCAT $opts -u - ABSTRACT-SENDTO:$ts1" printf "test $F_n $TEST... " $N touch "$ts1" # make a file with same name, so non-abstract fails $CMD1 >"$tf" 2>"${te}1" & pid1="$!" #waitfile $ts1 1 sleep 1 echo "$da" |$CMD2 2>>"${te}2" rc2="$?" i=0; while [ ! -s "$tf" -a "$i" -lt 10 ]; do usleep 100000; i=$((i+1)); done kill "$pid1" 2>/dev/null; wait if [ "$rc2" -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND, feats esac N=$((N+1)) # bind with Linux abstract UNIX domain addresses bound to filesystem socket # instead of abstract namespace NAME=ABSTRACT_BIND case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%socket%*|*%unix%*|*%abstract%*|*%$NAME%*) TEST="$NAME: abstract bind" # open an abstract client address with bind option, bind to the target socket. # send a datagram. # when socat outputs the datagram it got the test succeeded if ! eval $NUMCOND; then :; elif [ "$UNAME" != Linux ]; then $PRINTF "test $F_n $TEST... ${YELLOW}only on Linux${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1="$td/test$N.sock1" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts - ABSTRACT-SENDTO:$ts1,bind=$ts1" printf "test $F_n $TEST... " $N echo "$da" |$CMD1 >$tf 2>"${te}1" rc1=$? if [ $rc1 -ne 0 ]; then $PRINTF "$FAILED\n" echo "$CMD1" >&2 echo "rc=$rc1" >&2 cat "${te}1" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif echo "$da" |diff -q - $tf; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD1" >&2 cat "${te}1" >&2 echo "$da" |diff - "$tf" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) NAME=OPENSSLREAD # socat determined availability of data using select(). With openssl, the # following situation might occur: # a SSL data block with more than 8192 bytes (socats default blocksize) # arrives; socat calls SSL_read, and the SSL routine reads the complete block. # socat then reads 8192 bytes from the SSL layer, the rest remains buffered. # If the TCP connection stays idle for some time, the data in the SSL layer # keeps there and is not transferred by socat until the socket indicates more # data or EOF. case "$TESTS" in *%$N%*|*%functions%*|*%openssl%*|*%$NAME%*) TEST="$NAME: socat handles data buffered by openssl" #idea: have a socat process (server) that gets an SSL block that is larger than # socat transfer block size; keep the socket connection open and kill the # server process after a short time; if not the whole data block has been # transferred, the test has failed. if ! eval $NUMCOND; then :; elif ! feat=$(testfeats openssl) >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$(echo "$feat"| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.out" te="$td/test$N.err" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" SRVCERT=testsrv gentestcert "$SRVCERT" CMD1="$TRACE $SOCAT $opts -u -T 1 -b $($ECHO "$da\c" |wc -c) OPENSSL-LISTEN:$PORT,$REUSEADDR,cert=$SRVCERT.pem,verify=0 -" CMD2="$TRACE $SOCAT $opts -u - OPENSSL-CONNECT:$LOCALHOST:$PORT,verify=0" printf "test $F_n $TEST... " $N # $CMD1 2>"${te}1" >"$tf" & pid=$! # background process id waittcp4port $PORT (echo "$da"; sleep 2) |$CMD2 2>"${te}2" kill "$pid" 2>/dev/null; wait if ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1" cat "${te}1" echo "$CMD2" cat "${te}2" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi wait fi # NUMCOND, featsesac ;; esac N=$((N+1)) # test: there is a bug with the readbytes option: when the socket delivered # exacly that many bytes as specified with readbytes and the stays idle (no # more data, no EOF), socat waits for more data instead of generating EOF on # this in put stream. NAME=READBYTES_EOF #set -vx case "$TESTS" in *%$N%*|*%functions%*|*%$NAME%*) TEST="$NAME: trigger EOF after that many bytes, even when socket idle" #idea: we deliver that many bytes to socat; the process should terminate then. # we try to transfer data in the other direction then; if transfer succeeds, # the process did not terminate and the bug is still there. if ! eval $NUMCOND; then :; elif false; then $PRINTF "test $F_n $TEST... ${YELLOW}$(echo "$feat"| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tr="$td/test$N.ref" ti="$td/test$N.in" to="$td/test$N.out" te="$td/test$N.err" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')" CMD="$TRACE $SOCAT $opts SYSTEM:\"echo A; sleep $((2*SECONDs))\",readbytes=2!!- -!!/dev/null" printf "test $F_n $TEST... " $N (usleep $((2*MICROS)); echo) |eval "$CMD" >"$to" 2>"$te" if test -s "$to"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND, feats esac N=$((N+1)) # test: there was a bug with exec:...,pty that did not kill the exec'd sub # process under some circumstances. NAME=EXECPTYKILL case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%exec%*|*%pty%*|*%$NAME%*) TEST="$NAME: exec:...,pty explicitely kills sub process" # 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; # it should be killed after one second, so if the file was generated the test # has failed if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" ts="$td/test$N.sock" tda="$td/test$N.data" tsh="$td/test$N.sh" tdiff="$td/test$N.diff" cat >"$tsh" <"${te}2" & pid1=$! sleep $SECONDs waitfile $ts $SECONDs $CMD 2>>"${te}1" >>"$tf" sleep $((2*SECONDs)) kill "$pid1" 2>/dev/null wait if [ $? -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif [ -f "$tda" ]; then $PRINTF "$FAILED\n" cat "${te}1" "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) # test if service name resolution works; this was buggy in 1.5 and 1.6.0.0 NAME=TCP4SERVICE case "$TESTS" in *%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%tcp%*|*%$NAME%*) TEST="$NAME: echo via connection to TCP V4 socket" # select a tcp entry from /etc/services, have a server listen on the port # number and connect using the service name; with the bug, connection will to a # wrong port if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" # find a service entry we do not need root for (>=1024; here >=1100 for ease) SERVENT="$(grep '^[a-z][a-z]*[^!-~][^!-~]*[1-9][1-9][0-9][0-9]/tcp' /etc/services |head -n 1)" SERVICE="$(echo $SERVENT |cut -d' ' -f1)" _PORT="$PORT" PORT="$(echo $SERVENT |sed 's/.* \([1-9][0-9]*\).*/\1/')" tsl="$PORT" ts="127.0.0.1:$SERVICE" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts TCP4-LISTEN:$tsl,$REUSEADDR PIPE" CMD2="$TRACE $SOCAT $opts stdin!!stdout TCP4:$ts" printf "test $F_n $TEST... " $N $CMD1 >"$tf" 2>"${te}1" & pid1=$! waittcp4port $tsl 1 echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" if [ $? -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" cat "${te}1" echo "$CMD2" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid1 2>/dev/null wait PORT="$_PORT" fi ;; # NUMCOND esac N=$((N+1)) # test: up to socat 1.6.0.0, the highest file descriptor supported in socats # transfer engine was FOPEN_MAX-1; this usually worked fine but would fail when # socat was invoked with many file descriptors already opened. socat would # just hang in the select() call. Thanks to Daniel Lucq for reporting this # problem. # FOPEN_MAX on different OS's: # OS FOPEN_ ulimit ulimit FD_ # MAX -H -n -S -n SETSIZE # Linux 2.6: 16 1024 1024 1024 # HP-UX 11.11: 60 2048 2048 2048 # FreeBSD: 20 11095 11095 1024 # Cygwin: 20 unlimit 256 64 # AIX: 32767 65534 65534 # SunOS 8: 20 1024 # musl libc: 1024 NAME=EXCEED_FOPEN_MAX case "$TESTS" in *%$N%*|*%functions%*|*%maxfds%*|*%$NAME%*) TEST="$NAME: more than FOPEN_MAX FDs in use" # this test opens a number of FDs before socat is invoked. socat will have to # allocate higher FD numbers and thus hang if it cannot handle them. if ! eval $NUMCOND; then :; elif [ "$UNAME" != Linux ]; then $PRINTF "test $F_n $TEST... ${YELLOW}only on Linux${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else REDIR= #set -vx FOPEN_MAX=$($PROCAN -c 2>/dev/null |grep '^#define[ ][ ]*FOPEN_MAX' |awk '{print($3);}') if [ -z "$FOPEN_MAX" ]; then $PRINTF "test $F_n $TEST... ${YELLOW}could not determine FOPEN_MAX${NORMAL}\n" "$N" numCANT=$((numCANT+1)) listCANT="$listCANT $N" else if [ $FOPEN_MAX -lt 270 ]; then OPEN_FILES=$FOPEN_MAX # more than the highest FOPEN_MAX else OPEN_FILES=269 # bash tends to SIGSEGV on higher value # btw, the test is obsolete anyway fi i=3; while [ "$i" -lt "$OPEN_FILES" ]; do REDIR="$REDIR $i>&2" i=$((i+1)) done #echo "$REDIR" #testecho "$N" "$TEST" "" "pipe" "$opts -T 3" "" 1 #set -vx eval testecho "\"$N\"" "\"$TEST\"" "\"\"" "pipe" "\"$opts -T $((2*SECONDs))\"" 1 $REDIR #set +vx fi # could determine FOPEN_MAX fi ;; # NUMCOND esac N=$((N+1)) # there was a bug with udp-listen and fork: terminating sub processes became # zombies because the master process did not catch SIGCHLD NAME=UDP4LISTEN_SIGCHLD case "$TESTS" in *%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%udp%*|*%zombie%*|*%signal%*|*%$NAME%*) TEST="$NAME: test if UDP4-LISTEN child becomes zombie" # 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 # over. Now check for the child process: if it is zombie the test failed. # Correct is that child process terminated if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="$LOCALHOST:$tsl" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts -T 0.5 UDP4-LISTEN:$tsl,$REUSEADDR,fork PIPE" CMD2="$TRACE $SOCAT $opts - UDP4:$ts" printf "test $F_n $TEST... " $N $CMD1 >"$tf" 2>"${te}1" & pid1=$! waitudp4port $tsl 1 echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" rc2=$? sleep 1 #read -p ">" l="$(childprocess $pid1)" kill $pid1 2>/dev/null; wait if [ $rc2 -ne 0 ]; then $PRINTF "$NO_RESULT (client failed)\n" # already handled in test UDP4STREAM numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$NO_RESULT (diff failed)\n" # already handled in test UDP4STREAM numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif $(isdefunct "$l"); then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) #set +vx # there was a bug with udp-recvfrom and fork: terminating sub processes became # zombies because the master process caught SIGCHLD but did not wait() NAME=UDP4RECVFROM_SIGCHLD case "$TESTS" in *%$N%*|*%functions%*|*%ip4%*|*%udp%*|*%dgram%*|*%zombie%*|*%signal%*|*%$NAME%*) 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 # sub process is forked off. Make some transfer and wait until the -T timeout # is over. Now check for the child process: if it is zombie the test failed. # Correct is that child process terminated if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="$LOCALHOST:$tsl" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts -T 0.5 UDP4-RECVFROM:$tsl,reuseaddr,fork PIPE" CMD2="$TRACE $SOCAT $opts - UDP4-SENDTO:$ts" printf "test $F_n $TEST... " $N $CMD1 >"$tf" 2>"${te}1" & pid1=$! waitudp4port $tsl 1 echo "$da" |$CMD2 >>"$tf" 2>>"${te}2" rc2=$? sleep 1 #read -p ">" l="$(childprocess $pid1)" kill $pid1 2>/dev/null; wait if [ $rc2 -ne 0 ]; then $PRINTF "$NO_RESULT\n" # already handled in test UDP4DGRAM numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$NO_RESULT\n" # already handled in test UDP4DGRAM numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif $(isdefunct "$l"); then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) # test: there was a bug with ip*-recv and bind option: it would not bind, and # with the first received packet an error: # socket_init(): unknown address family 0 # occurred NAME=RAWIP4RECVBIND case "$TESTS" in *%$N%*|*%functions%*|*%ip4%*|*%dgram%*|*%rawip%*|*%rawip4%*|*%recv%*|*%root%*|*%$NAME%*) TEST="$NAME: raw IPv4 receive with bind" # idea: start a socat process with ip4-recv:...,bind=... and send it a packet # if the packet passes the test succeeded if ! eval $NUMCOND; then :; elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1p=$PROTO; PROTO=$((PROTO+1)) ts1a="127.0.0.1" ts1="$ts1a:$ts1p" da="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts -u IP4-RECV:$ts1p,bind=$ts1a,reuseaddr -" CMD2="$TRACE $SOCAT $opts -u - IP4-SENDTO:$ts1" printf "test $F_n $TEST... " $N $CMD1 >"$tf" 2>"${te}1" & pid1="$!" waitip4proto $ts1p 1 echo "$da" |$CMD2 2>>"${te}2" rc2="$?" #ls -l $tf i=0; while [ ! -s "$tf" -a "$i" -lt 10 ]; do usleep 100000; i=$((i+1)); done kill "$pid1" 2>/dev/null; wait if [ "$rc2" -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" echo "$CMD2" cat "${te}1" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND, root esac PROTO=$((PROTO+1)) N=$((N+1)) # there was a bug in *-recvfrom with fork: due to an error in the appropriate # signal handler the master process would hang after forking off the first # child process. NAME=UDP4RECVFROM_FORK case "$TESTS" in *%$N%*|*%functions%*|*%ip4%*|*%udp%*|*%dgram%*|*%$NAME%*) 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; # send it a second packet and check if this is processed properly. If yes, the # test succeeded. if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsp=$PORT ts="$LOCALHOST:$tsp" da2a="test$N $(date) $RANDOM" da2b="test$N $(date) $RANDOM" CMD1="$TRACE $SOCAT $opts -T 2 UDP4-RECVFROM:$tsp,reuseaddr,fork PIPE" CMD2="$TRACE $SOCAT $opts -T 1 - UDP4-SENDTO:$ts" printf "test $F_n $TEST... " $N $CMD1 >/dev/null 2>"${te}1" & pid1=$! waitudp4port $tsp 1 echo "$da2a" |$CMD2 >/dev/null 2>>"${te}2a" # this should always work rc2a=$? echo "$da2b" |$CMD2 >"$tf" 2>>"${te}2b" # this would fail when bug rc2b=$? kill $pid1 2>/dev/null; wait if [ $rc2b -ne 0 ]; then $PRINTF "$NO_RESULT\n" numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! echo "$da2b" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" >&2 cat "${te}1" >&2 echo "$CMD2" >&2 cat "${te}2b" >&2 cat "$tdiff" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2" "${te}3"; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) # there was a bug in parsing the arguments of exec: consecutive spaces resulted # in additional empty arguments NAME=EXECSPACES case "$TESTS" in *%$N%*|*%functions%*|*%exec%*|*%parse%*|*%$NAME%*) TEST="$NAME: correctly parse exec with consecutive spaces" if ! eval $NUMCOND; then :; else $PRINTF "test $F_n $TEST... " $N tf="$td/test$N.stdout" te="$td/test$N.stderr" da="test$N $(date) $RANDOM" # with a double space tdiff="$td/test$N.diff" # put the test data as first argument after two spaces. expect the data in the # first argument of the exec'd command. $TRACE $SOCAT $opts -u "exec:\"bash -c \\\"echo \\\\\\\"\$1\\\\\\\"\\\" \\\"\\\" \\\"$da\\\"\"" - >"$tf" 2>"$te" rc=$? echo "$da" |diff - "$tf" >"$tdiff" if [ "$rc" -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" cat "$te" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif [ -s "$tdiff" ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo diff: cat "$tdiff" if [ -n "$debug" ]; then cat $te; fi numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND esac N=$((N+1)) # a bug was found in the way UDP-LISTEN handles the listening socket: # when UDP-LISTEN continued to listen after a packet had been dropped by, e.g., # range option, the old listen socket would not be closed but a new one created. NAME=UDP4LISTENCONT case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%ip4%*|*%udp%*|*%$NAME%*) TEST="$NAME: let range drop a packet and see if old socket is closed" # idea: run a UDP4-LISTEN process with range option. Send it one packet from an # address outside range and check if two listening sockets are open then if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" if [ "$SS" ]; then while [ "$($SS -anu |grep "127\.0\.0\.1:$PORT\>" |wc -l)" -ne 0 ]; do PORT=$((PORT+1)) done else while [ "$(netstat -an |grep "^udp.*127\.0\.0\.1:$PORT\>" |wc -l)" -ne 0 ]; do PORT=$((PORT+1)) done fi tp=$PORT da1="test$N $(date) $RANDOM" a1="$LOCALHOST" a2="$SECONDADDR" #CMD0="$TRACE $SOCAT $opts UDP4-LISTEN:$tp,bind=$a1,range=$a2/32 PIPE" CMD0="$TRACE $SOCAT $opts UDP4-LISTEN:$tp,$REUSEADDR,range=$a2/32 PIPE" CMD1="$TRACE $SOCAT $opts - UDP-CONNECT:$a1:$tp" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" & pid1=$! waitudp4port $tp 1 echo "$da1" |$CMD1 >"${tf}1" 2>"${te}1" # this should fail rc1=$? waitudp4port $tp 1 if [ "$SS" ]; then nsocks="$($SS -anu |grep ":$PORT\>" |wc -l)" else nsocks="$(netstat -an |grep "^udp.*[:.]$PORT\>" |wc -l)" fi kill $pid1 2>/dev/null; wait if [ $rc1 -ne 0 ]; then $PRINTF "$NO_RESULT\n" numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ $nsocks -eq 0 ]; then $PRINTF "$NO_RESULT\n" numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ $nsocks -ne 1 ]; then $PRINTF "$FAILED ($nsocks listening sockets)\n" echo "$CMD0 &" echo "$CMD1" cat "${te}0" "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}0" "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) # during wait for next poll time option ignoreeof blocked the data transfer in # the reverse direction NAME=IGNOREEOFNOBLOCK case "$TESTS" in *%$N%*|*%functions%*|*%engine%*|*%socket%*|*%ignoreeof%*|*%$NAME%*) TEST="$NAME: ignoreeof does not block other direction" # have socat poll in ignoreeof mode. while it waits one second for next check, # we send data in the reverse direction and then the total timeout fires. # it the data has passed, the test succeeded. if ! eval $NUMCOND; then :; else tf="$td/test$N.stout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts /dev/null,ignoreeof!!- -!!/dev/null" printf "test $F_n $TEST... " $N (usleep 333333; echo "$da") |$CMD0 >"$tf" 2>"${te}0" rc0=$? if [ $rc0 != 0 ]; then $PRINTF "$FAILED\n" echo "$CMD0 &" echo "$CMD1" cat "${te}0" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif echo "$da" |diff - "$tf" >/dev/null; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0 &" echo "$CMD1" cat "${te}0" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi ;; # NUMCOND esac N=$((N+1)) # test the escape option NAME=ESCAPE case "$TESTS" in *%$N%*|*%functions%*|*%engine%*|*%escape%*|*%$NAME%*) TEST="$NAME: escape character triggers EOF" # idea: start socat just echoing input, but apply escape option. send a string # containing the escape character and check if the output is truncated 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" CMD="$TRACE $SOCAT $opts -,escape=27 pipe" printf "test $F_n $TEST... " $N $ECHO "$da\n\x1bXYZ" |$CMD >"$tf" 2>"$te" if [ $? -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD" cat "$te" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: diff:\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND esac N=$((N+1)) # test the escape option combined with ignoreeof NAME=ESCAPE_IGNOREEOF case "$TESTS" in *%$N%*|*%functions%*|*%engine%*|*%ignoreeof%*|*%escape%*|*%$NAME%*) TEST="$NAME: escape character triggers EOF" # idea: start socat just echoing input, but apply escape option. send a string # containing the escape character and check if the output is truncated if ! eval $NUMCOND; then :; else ti="$td/test$N.file" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD="$TRACE $SOCAT -T 5 $opts file:$ti,ignoreeof,escape=27!!- pipe" printf "test $F_n $TEST... " $N >"$ti" $CMD >"$tf" 2>"$te" & $ECHO "$da\n\x1bXYZ" >>"$ti" sleep 1 if ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: diff:\n" cat "$tdiff" cat "$te" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND esac N=$((N+1)) # test: logging of ancillary message while read PF KEYW ADDR IPPORT SCM_ENABLE SCM_RECV SCM_TYPE SCM_NAME ROOT SCM_VALUE do if [ -z "$PF" ] || [[ "$PF" == \#* ]]; then continue; fi # pf="$(echo "$PF" |tr A-Z a-z)" proto="$(echo "$KEYW" |tr A-Z a-z)" NAME=${KEYW}SCM_$SCM_TYPE case "$TESTS" in *%$N%*|*%functions%*|*%socket%*|*%$pf%*|*%dgram%*|*%udp%*|*%$proto%*|*%recv%*|*%ancillary%*|*%$ROOT%*|*%$NAME%*) TEST="$NAME: $KEYW log ancillary message $SCM_TYPE $SCM_NAME" # idea: start a socat process with *-RECV:..,... , ev. with ancillary message # enabling option and send it a packet, ev. with some option. check the info log # for the appropriate output. if ! eval $NUMCOND; then :; #elif [[ "$PF" == "#*" ]]; then : elif [ "$ROOT" = root -a $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ "$PF" = "IP6" ] && ( ! feat=$(testfeats ip6) || ! runsip6 >/dev/null ); then $PRINTF "test $F_n $TEST... ${YELLOW}IP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testoptions $SCM_RECV >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}option $SCM_RECV not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" case "X$IPPORT" in "XPORT") tra="$PORT" # test recv address tsa="$ADDR:$PORT" # test sendto address PORT=$((PORT+1)) ;; "XPROTO") tra="$PROTO" # test recv address tsa="$ADDR:$PROTO" # test sendto address PROTO=$((PROTO+1)) ;; *) tra="$(eval echo "$ADDR")" # resolve $N tsa="$tra" esac CMD0="$TRACE $SOCAT $opts -d -d -d -u $KEYW-RECV:$tra,reuseaddr,$SCM_RECV -" CMD1="$TRACE $SOCAT $opts -u - $KEYW-SENDTO:$tsa,$SCM_ENABLE" printf "test $F_n $TEST... " $N # is this option supported? if $SOCAT -hhh |grep "[[:space:]]$SCM_RECV[[:space:]]" >/dev/null; then if [ "$SCM_VALUE" = "timestamp" ]; then secs="$(date '+%S')" if [ "$secs" -ge 58 -a "$secs" -le 59 ]; then dsecs=$((60-secs)) #echo "Sleeping $dsecs seconds to avoid minute change in timestamp" >/dev/tty sleep $dsecs fi fi $CMD0 >"$tf" 2>"${te}0" & pid0="$!" wait${proto}port $tra 1 echo "XYZ" |$CMD1 2>"${te}1" rc1="$?" sleep 1 i=0; while [ ! -s "${te}0" -a "$i" -lt 10 ]; do usleep 100000; i=$((i+1)); done kill "$pid0" 2>/dev/null; wait # do not show more messages than requested case "$opts" in *-d*-d*-d*-d*) LEVELS="[EWNID]" ;; *-d*-d*-d*) LEVELS="[EWNI]" ;; *-d*-d*) LEVELS="[EWN]" ;; *-d*) LEVELS="[EW]" ;; *) LEVELS="[E]" ;; esac if [ "$SCM_VALUE" = "timestamp" ]; then SCM_VALUE="$(date '+%a %b %e %H:%M:.. %Y'), ...... usecs" fi if [ "$rc1" -ne 0 ]; then $PRINTF "$NO_RESULT: $TRACE $SOCAT:\n" echo "$CMD0 &" echo "$CMD1" grep " $LEVELS " "${te}0" grep " $LEVELS " "${te}1" numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! grep "ancillary message: $SCM_TYPE: $SCM_NAME=" ${te}0 >/dev/null; then $PRINTF "$FAILED\n" echo "variable $SCM_TYPE: $SCM_NAME not set" echo "$CMD0 &" echo "$CMD1" grep " $LEVELS " "${te}0" grep " $LEVELS " "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! grep "ancillary message: $SCM_TYPE: $SCM_NAME=$SCM_VALUE\$" ${te}0 >/dev/null; then $PRINTF "$FAILED\n" badval="$(grep "ancillary message: $SCM_TYPE: $SCM_NAME" ${te}0 |sed 's/.*=//g')" echo "variable $SCM_TYPE: $SCM_NAME has value \"$badval\" instead of pattern \"$SCM_VALUE\"" >&2 echo "$CMD0 &" echo "$CMD1" grep " $LEVELS " "${te}0" grep " $LEVELS " "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then grep " $LEVELS " "${te}0"; echo; grep " $LEVELS " "${te}1"; fi numOK=$((numOK+1)) fi else # option is not supported $PRINTF "${YELLOW}$SCM_RECV not available${NORMAL}\n" numCANT=$((numCANT+1)) listCANT="$listCANT $N" fi # option is not supported fi # NUMCOND, root, feats ;; esac N=$((N+1)) # done <<<" IP4 UDP4 127.0.0.1 PORT ip-options=x01000000 ip-recvopts IP_OPTIONS options user x01000000 IP4 UDP4 127.0.0.1 PORT , so-timestamp SCM_TIMESTAMP timestamp user timestamp IP4 UDP4 127.0.0.1 PORT ip-ttl=53 ip-recvttl IP_TTL ttl user 53 IP4 UDP4 127.0.0.1 PORT ip-tos=7 ip-recvtos IP_TOS tos user 7 IP4 UDP4 127.0.0.1 PORT , ip-pktinfo IP_PKTINFO locaddr user 127.0.0.1 IP4 UDP4 127.0.0.1 PORT , ip-pktinfo IP_PKTINFO dstaddr user 127.0.0.1 IP4 UDP4 127.0.0.1 PORT , ip-pktinfo IP_PKTINFO if user lo IP4 UDP4 127.0.0.1 PORT , ip-recvif IP_RECVIF if user lo0 IP4 UDP4 127.0.0.1 PORT , ip-recvdstaddr IP_RECVDSTADDR dstaddr user 127.0.0.1 IP4 IP4 127.0.0.1 PROTO ip-options=x01000000 ip-recvopts IP_OPTIONS options root x01000000 IP4 IP4 127.0.0.1 PROTO , so-timestamp SCM_TIMESTAMP timestamp root timestamp IP4 IP4 127.0.0.1 PROTO ip-ttl=53 ip-recvttl IP_TTL ttl root 53 IP4 IP4 127.0.0.1 PROTO ip-tos=7 ip-recvtos IP_TOS tos root 7 IP4 IP4 127.0.0.1 PROTO , ip-pktinfo IP_PKTINFO locaddr root 127.0.0.1 IP4 IP4 127.0.0.1 PROTO , ip-pktinfo IP_PKTINFO dstaddr root 127.0.0.1 IP4 IP4 127.0.0.1 PROTO , ip-pktinfo IP_PKTINFO if root lo IP4 IP4 127.0.0.1 PROTO , ip-recvif IP_RECVIF if root lo0 IP4 IP4 127.0.0.1 PROTO , ip-recvdstaddr IP_RECVDSTADDR dstaddr root 127.0.0.1 IP6 UDP6 [::1] PORT , so-timestamp SCM_TIMESTAMP timestamp user timestamp IP6 UDP6 [::1] PORT , ipv6-recvpktinfo IPV6_PKTINFO dstaddr user [[]0000:0000:0000:0000:0000:0000:0000:0001[]] IP6 UDP6 [::1] PORT ipv6-unicast-hops=35 ipv6-recvhoplimit IPV6_HOPLIMIT hoplimit user 35 IP6 UDP6 [::1] PORT ipv6-tclass=0xaa ipv6-recvtclass IPV6_TCLASS tclass user x000000aa IP6 IP6 [::1] PROTO , so-timestamp SCM_TIMESTAMP timestamp root timestamp IP6 IP6 [::1] PROTO , ipv6-recvpktinfo IPV6_PKTINFO dstaddr root [[]0000:0000:0000:0000:0000:0000:0000:0001[]] IP6 IP6 [::1] PROTO ipv6-unicast-hops=35 ipv6-recvhoplimit IPV6_HOPLIMIT hoplimit root 35 IP6 IP6 [::1] PROTO ipv6-tclass=0xaa ipv6-recvtclass IPV6_TCLASS tclass root x000000aa #UNIX UNIX $td/test\$N.server - , so-timestamp SCM_TIMESTAMP timestamp user timestamp " # this one fails, appearently due to a Linux weakness: # UNIX so-timestamp # test: setting of environment variables that describe a stream socket # connection: SOCAT_SOCKADDR, SOCAT_PEERADDR; and SOCAT_SOCKPORT, # SOCAT_PEERPORT when applicable while read KEYW FEAT TEST_SOCKADDR TEST_PEERADDR TEST_SOCKPORT TEST_PEERPORT; do if [ -z "$KEYW" ] || [[ "$KEYW" == \#* ]]; then continue; fi # protov="$(echo "$KEYW" |tr A-Z a-z)" proto="${protov%%[0-9]}" NAME=${KEYW}LISTENENV case "$TESTS" in *%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%tcp%*|*%$proto%*|*%$protov%*|*%envvar%*|*%$NAME%*) TEST="$NAME: $KEYW-LISTEN sets environment variables with socket addresses" # have a server accepting a connection and invoking some shell code. The shell # code extracts and prints the SOCAT related environment vars. # outside code then checks if the environment contains the variables correctly # describing the peer and local sockets. if ! eval $NUMCOND; then :; elif ! feat=$(testfeats $FEAT); then $PRINTF "test $F_n $TEST... ${YELLOW}$(echo "$feat" |tr a-z A-Z) not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ "$KEYW" = "TCP6" -o "$KEYW" = "UDP6" -o "$KEYW" = "SCTP6" ] && \ ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}IP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ "$KEYW" = "SCTP4" ] && ! runssctp4 "$((PORT))" >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$KEYW not available${NORMAL}\n" $N elif [ "$KEYW" = "SCTP6" ] && ! runssctp6 "$((PORT))" >/dev/null; then #!!! branch not reached - caught above! $PRINTF "test $F_n $TEST... ${YELLOW}$KEYW not available${NORMAL}\n" $N else tf="$td/test$N.stdout" te="$td/test$N.stderr" TEST_SOCKADDR="$(echo "$TEST_SOCKADDR" |sed "s/\$N/$N/g")" # actual vars tsa="$TEST_SOCKADDR" # test server address tsp="$TEST_SOCKPORT" # test server port if [ "$tsp" != ',' ]; then tsa1="$tsp"; tsa2="$tsa"; tsa="$tsa:$tsp" # tsa2 used for server bind= else tsa1="$tsa"; tsa2= # tsa1 used for addr parameter fi TEST_PEERADDR="$(echo "$TEST_PEERADDR" |sed "s/\$N/$N/g")" # actual vars tca="$TEST_PEERADDR" # test client address tcp="$TEST_PEERPORT" # test client port if [ "$tcp" != ',' ]; then tca="$tca:$tcp" fi #CMD0="$TRACE $SOCAT $opts -u $KEYW-LISTEN:$tsa1 SYSTEM:\"export -p\"" CMD0="$TRACE $SOCAT $opts -u -lpsocat $KEYW-LISTEN:$tsa1,$REUSEADDR SYSTEM:\"echo SOCAT_SOCKADDR=\\\$SOCAT_SOCKADDR; echo SOCAT_PEERADDR=\\\$SOCAT_PEERADDR; echo SOCAT_SOCKPORT=\\\$SOCAT_SOCKPORT; echo SOCAT_PEERPORT=\\\$SOCAT_PEERPORT; sleep 1\"" CMD1="$TRACE $SOCAT $opts -u - $KEYW-CONNECT:$tsa,bind=$tca" printf "test $F_n $TEST... " $N eval "$CMD0 2>\"${te}0\" >\"$tf\" &" pid0=$! wait${protov}port $tsa1 1 echo |$CMD1 2>"${te}1" rc1=$? waitfile "$tf" 2 kill $pid0 2>/dev/null; wait #set -vx if [ $rc1 != 0 ]; then $PRINTF "$NO_RESULT (client failed):\n" echo "$CMD0 &" cat "${te}0" echo "$CMD1" cat "${te}1" numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ "$(grep SOCAT_SOCKADDR "${tf}" |sed -e 's/^[^=]*=//' |sed -e "s/[\"']//g")" = "$TEST_SOCKADDR" -a \ "$(grep SOCAT_PEERADDR "${tf}" |sed -e 's/^[^=]*=//' -e "s/[\"']//g")" = "$TEST_PEERADDR" -a \ \( "$TEST_SOCKPORT" = ',' -o "$(grep SOCAT_SOCKPORT "${tf}" |sed -e 's/^[^=]*=//' |sed -e 's/"//g')" = "$tsp" \) -a \ \( "$TEST_PEERPORT" = ',' -o "$(grep SOCAT_PEERPORT "${tf}" |sed -e 's/^[^=]*=//' |sed -e 's/"//g')" = "$tcp" \) \ ]; then $PRINTF "$OK\n" if [ "$debug" ]; then echo "$CMD0 &" cat "${te}0" echo "$CMD1" cat "${te}1" fi numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0 &" cat "${te}0" echo "$CMD1" cat "${te}1" echo -e "SOCAT_SOCKADDR=$TEST_SOCKADDR\nSOCAT_PEERADDR=$TEST_PEERADDR\nSOCAT_SOCKPORT=$TEST_SOCKPORT\nSOCAT_PEERPORT=$TEST_PEERPORT" | diff - "${tf}" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND, feats ;; esac N=$((N+1)) #set +xv # done <<<" TCP4 TCP 127.0.0.1 $SECONDADDR $PORT $((PORT+1)) TCP6 IP6 [0000:0000:0000:0000:0000:0000:0000:0001] [0000:0000:0000:0000:0000:0000:0000:0001] $((PORT+2)) $((PORT+3)) UDP6 IP6 [0000:0000:0000:0000:0000:0000:0000:0001] [0000:0000:0000:0000:0000:0000:0000:0001] $((PORT+6)) $((PORT+7)) SCTP4 SCTP 127.0.0.1 $SECONDADDR $((PORT+8)) $((PORT+9)) SCTP6 SCTP [0000:0000:0000:0000:0000:0000:0000:0001] [0000:0000:0000:0000:0000:0000:0000:0001] $((PORT+10)) $((PORT+11)) UNIX UNIX $td/test\$N.server $td/test\$N.client , , " # this one fails due to weakness in socats UDP4-LISTEN implementation: #UDP4 $LOCALHOST $SECONDADDR $((PORT+4)) $((PORT+5)) # test: environment variables from ancillary message while read PF KEYW ADDR IPPORT SCM_ENABLE SCM_RECV SCM_ENVNAME ROOT SCM_VALUE do if [ -z "$PF" ] || [[ "$PF" == \#* ]]; then continue; fi # pf="$(echo "$PF" |tr A-Z a-z)" proto="$(echo "$KEYW" |tr A-Z a-z)" NAME=${KEYW}ENV_$SCM_ENVNAME case "$TESTS" in *%$N%*|*%functions%*|*%socket%*|*%$pf%*|*%dgram%*|*%udp%*|*%$proto%*|*%recv%*|*%ancillary%*|*%envvar%*|*%$ROOT%*|*%$NAME%*) #set -vx TEST="$NAME: $KEYW ancillary message sets env SOCAT_$SCM_ENVNAME" # idea: start a socat process with *-RECVFROM:..,... , ev. with ancillary # message enabling option and send it a packet, ev. with some option. write # the resulting environment to a file and check its contents for the # appropriate variable. if ! eval $NUMCOND; then :; elif [ "$ROOT" = root -a $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ "$PF" = "IP6" ] && ( ! feat=$(testfeats ip6) || ! runsip6 ) >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}IP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" case "X$IPPORT" in "XPORT") tra="$PORT" # test recv address tsa="$ADDR:$PORT" # test sendto address PORT=$((PORT+1)) ;; "XPROTO") tra="$PROTO" # test recv address tsa="$ADDR:$PROTO" # test sendto address PROTO=$((PROTO+1)) ;; *) tra="$(eval echo "$ADDR")" # resolve $N tsa="$tra" esac #CMD0="$TRACE $SOCAT $opts -u $KEYW-RECVFROM:$tra,reuseaddr,$SCM_RECV SYSTEM:\"export -p\"" # without that ultra escaped quote the test failed for IPv6 when there was file ./1 CMD0="$TRACE $SOCAT $opts -u -lpsocat $KEYW-RECVFROM:$tra,reuseaddr,$SCM_RECV SYSTEM:\"echo \\\\\\\"\\\$SOCAT_$SCM_ENVNAME\\\\\\\"\"" CMD1="$TRACE $SOCAT $opts -u - $KEYW-SENDTO:$tsa,$SCM_ENABLE" printf "test $F_n $TEST... " $N # is this option supported? if $SOCAT -hhh |grep "[[:space:]]$SCM_RECV[[:space:]]" >/dev/null; then if [ "$SCM_VALUE" = "timestamp" ]; then secs="$(date '+%S')" if [ "$secs" -ge 58 -a "$secs" -le 59 ]; then dsecs=$((60-secs)) #echo "Sleeping $dsecs seconds to avoid minute change in timestamp" >/dev/tty sleep $dsecs fi fi eval "$CMD0 >\"$tf\" 2>\"${te}0\" &" pid0="$!" wait${proto}port $tra 1 echo "XYZ" |$CMD1 2>"${te}1" rc1="$?" waitfile "$tf" 2 #i=0; while [ ! -s "${te}0" -a "$i" -lt 10 ]; do usleep 100000; i=$((i+1)); done kill "$pid0" 2>/dev/null; wait # do not show more messages than requested if [ "$SCM_VALUE" = "timestamp" ]; then SCM_VALUE="$(date '+%a %b %e %H:%M:.. %Y'), ...... usecs" #echo "\"$SCM_VALUE\"" >&2 # debugging fi if [ "$rc1" -ne 0 ]; then $PRINTF "$NO_RESULT: $SOCAT:\n" echo "$CMD0 &" echo "$CMD1" cat "${te}0" cat "${te}1" numCANT=$((numCANT+1)) listCANT="$listCANT $N" #elif ! egrep "^export SOCAT_$SCM_ENVNAME=[\"']?$SCM_VALUE[\"']?\$" ${tf} >/dev/null; then #elif ! eval echo "$TRACE $SOCAT_\$SCM_VALUE" |diff - "${tf}" >/dev/null; then elif ! expr "$(cat "$tf")" : "$SCM_VALUE\$" >/dev/null; then $PRINTF "$FAILED\n" echo "logged value \"$(cat "$tf")\" instead of $SCM_VALUE" echo "$CMD0 &" echo "$CMD1" cat "${te}0" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}0"; echo; cat "${te}1"; fi numOK=$((numOK+1)) fi else # option is not supported $PRINTF "${YELLOW}$SCM_RECV not available${NORMAL}\n" numCANT=$((numCANT+1)) listCANT="$listCANT $N" fi # option is not supported fi ;; # NUMCOND, feats esac N=$((N+1)) # done <<<" IP4 UDP4 127.0.0.1 PORT ip-options=x01000000 ip-recvopts IP_OPTIONS user x01000000 IP4 UDP4 127.0.0.1 PORT , so-timestamp TIMESTAMP user timestamp IP4 UDP4 127.0.0.1 PORT ip-ttl=53 ip-recvttl IP_TTL user 53 IP4 UDP4 127.0.0.1 PORT ip-tos=7 ip-recvtos IP_TOS user 7 IP4 UDP4 127.0.0.1 PORT , ip-pktinfo IP_LOCADDR user 127.0.0.1 IP4 UDP4 127.0.0.1 PORT , ip-pktinfo IP_DSTADDR user 127.0.0.1 IP4 UDP4 127.0.0.1 PORT , ip-pktinfo IP_IF user lo IP4 UDP4 127.0.0.1 PORT , ip-recvif IP_IF user lo0 IP4 UDP4 127.0.0.1 PORT , ip-recvdstaddr IP_DSTADDR user 127.0.0.1 IP4 IP4 127.0.0.1 PROTO ip-options=x01000000 ip-recvopts IP_OPTIONS root x01000000 IP4 IP4 127.0.0.1 PROTO , so-timestamp TIMESTAMP root timestamp IP4 IP4 127.0.0.1 PROTO ip-ttl=53 ip-recvttl IP_TTL root 53 IP4 IP4 127.0.0.1 PROTO ip-tos=7 ip-recvtos IP_TOS root 7 IP4 IP4 127.0.0.1 PROTO , ip-pktinfo IP_LOCADDR root 127.0.0.1 IP4 IP4 127.0.0.1 PROTO , ip-pktinfo IP_DSTADDR root 127.0.0.1 IP4 IP4 127.0.0.1 PROTO , ip-pktinfo IP_IF root lo IP4 IP4 127.0.0.1 PROTO , ip-recvif IP_IF root lo0 IP4 IP4 127.0.0.1 PROTO , ip-recvdstaddr IP_DSTADDR root 127.0.0.1 IP6 UDP6 [::1] PORT , ipv6-recvpktinfo IPV6_DSTADDR user [[]0000:0000:0000:0000:0000:0000:0000:0001[]] IP6 UDP6 [::1] PORT ipv6-unicast-hops=35 ipv6-recvhoplimit IPV6_HOPLIMIT user 35 IP6 UDP6 [::1] PORT ipv6-tclass=0xaa ipv6-recvtclass IPV6_TCLASS user x000000aa IP6 IP6 [::1] PROTO , ipv6-recvpktinfo IPV6_DSTADDR root [[]0000:0000:0000:0000:0000:0000:0000:0001[]] IP6 IP6 [::1] PROTO ipv6-unicast-hops=35 ipv6-recvhoplimit IPV6_HOPLIMIT root 35 IP6 IP6 [::1] PROTO ipv6-tclass=0xaa ipv6-recvtclass IPV6_TCLASS root x000000aa #UNIX UNIX $td/test\$N.server - , so-timestamp TIMESTAMP user timestamp " # test the SOCKET-CONNECT address (against TCP4-LISTEN) NAME=SOCKET_CONNECT_TCP4 case "$TESTS" in *%$N%*|*%functions%*|*%generic%*|*%socket%*|*%$NAME%*) TEST="$NAME: socket connect with TCP/IPv4" # start a TCP4-LISTEN process that echoes data, and send test data using # SOCKET-CONNECT, selecting TCP/IPv4. The sent data should be returned. if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts0p=$PORT; PORT=$((PORT+1)) ts0a="127.0.0.1" ts1p=$(printf "%04x" $ts0p); ts1a="7f000001" # "127.0.0.1" ts1="x${ts1p}${ts1a}x0000000000000000" ts1b=$(printf "%04x" $PORT); PORT=$((PORT+1)) da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts TCP4-LISTEN:$ts0p,$REUSEADDR,bind=$ts0a PIPE" CMD1="$TRACE $SOCAT $opts - SOCKET-CONNECT:2:6:$ts1,bind=x${ts1b}00000000x0000000000000000" printf "test $F_n $TEST... " $N $CMD0 2>"${te}0" & pid0="$!" waittcp4port $ts0p 1 echo "$da" |$CMD1 >>"$tf" 2>>"${te}1" rc1="$?" kill "$pid0" 2>/dev/null; wait; if [ "$rc1" -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD0 &" cat "${te}0" echo "$CMD1" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" echo "$CMD0 &" cat "${te}0" echo "$CMD1" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) PF_INET6="$($PROCAN -c |grep "^#define[[:space:]]*PF_INET6[[:space:]]" |cut -d' ' -f3)" # test the SOCKET-CONNECT address (against TCP6-LISTEN) NAME=SOCKET_CONNECT_TCP6 case "$TESTS" in *%$N%*|*%functions%*|*%generic%*|*%tcp6%*|*%socket%*|*%$NAME%*) TEST="$NAME: socket connect with TCP/IPv6" if ! eval $NUMCOND; then :; elif ! testfeats tcp ip6 >/dev/null || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else # start a TCP6-LISTEN process that echoes data, and send test data using # SOCKET-CONNECT, selecting TCP/IPv6. The sent data should be returned. tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts0p=$PORT; PORT=$((PORT+1)) ts0a="[::1]" ts1p=$(printf "%04x" $ts0p); ts1a="00000000000000000000000000000001" # "[::1]" ts1="x${ts1p}x00000000x${ts1a}x00000000" ts1b=$(printf "%04x" $PORT); PORT=$((PORT+1)) da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts TCP6-LISTEN:$ts0p,$REUSEADDR,bind=$ts0a PIPE" CMD1="$TRACE $SOCAT $opts - SOCKET-CONNECT:$PF_INET6:6:$ts1,bind=x${ts1b}x00000000x00000000000000000000000000000000x00000000" printf "test $F_n $TEST... " $N $CMD0 2>"${te}0" & pid0="$!" waittcp6port $ts0p 1 echo "$da" |$CMD1 >>"$tf" 2>>"${te}1" rc1="$?" kill "$pid0" 2>/dev/null; wait; if [ "$rc1" -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD0 &" cat "${te}0" echo "$CMD1" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" echo "$CMD0 &" cat "${te}0" echo "$CMD1" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) # test the SOCKET-CONNECT address (against UNIX-LISTEN) NAME=SOCKET_CONNECT_UNIX case "$TESTS" in *%$N%*|*%functions%*|*%generic%*|*%unix%*|*%socket%*|*%$NAME%*) TEST="$NAME: socket connect with UNIX domain" # start a UNIX-LISTEN process that echoes data, and send test data using # SOCKET-CONNECT, selecting UNIX socket. The sent data should be returned. if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts0="$td/test$N.server" ts1="$td/test$N.client" da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts UNIX-LISTEN:$ts0,$REUSEADDR PIPE" CMD1="$TRACE $SOCAT $opts - SOCKET-CONNECT:1:0:\\\"$ts0\\\0\\\",bind=\\\"$ts1\\\0\\\"" printf "test $F_n $TEST... " $N $CMD0 2>"${te}0" & pid0="$!" waitfile $ts0 1 echo "$da" |$CMD1 >>"$tf" 2>>"${te}1" rc1="$?" kill "$pid0" 2>/dev/null; wait; if [ "$rc1" -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD0 &" cat "${te}0" echo "$CMD1" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" echo "$CMD0 &" cat "${te}0" echo "$CMD1" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND esac N=$((N+1)) # test the SOCKET-LISTEN address (with TCP4-CONNECT) NAME=SOCKET_LISTEN case "$TESTS" in *%$N%*|*%functions%*|*%generic%*|*%socket%*|*%$NAME%*) TEST="$NAME: socket recvfrom with TCP/IPv4" # start a SOCKET-LISTEN process that uses TCP/IPv4 and echoes data, and # send test data using TCP4-CONNECT. The sent data should be returned. if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1p=$PORT; PORT=$((PORT+1)) ts1a="127.0.0.1" ts0p=$(printf "%04x" $ts1p); ts0a="7f000001" # "127.0.0.1" ts0="x${ts0p}${ts0a}x0000000000000000" ts1b=$PORT; PORT=$((PORT+1)) ts1="$ts1a:$ts1p" da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts SOCKET-LISTEN:2:6:$ts0,$REUSEADDR PIPE" CMD1="$TRACE $SOCAT $opts - TCP4-CONNECT:$ts1,bind=:$ts1b" printf "test $F_n $TEST... " $N $CMD0 2>"${te}0" & pid0="$!" #sleep 1 waittcp4port $ts1p 1 echo "$da" |$CMD1 >>"$tf" 2>>"${te}1" rc1="$?" kill "$pid0" 2>/dev/null; wait; if [ "$rc1" -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD0 &" cat "${te}0" echo "$CMD1" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" echo "$CMD0 &" cat "${te}0" echo "$CMD1" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) SOCK_DGRAM="$($PROCAN -c |grep "^#define[[:space:]]*SOCK_DGRAM[[:space:]]" |cut -d' ' -f3)" # test the SOCKET-SENDTO address (against UDP4-RECVFROM) NAME=SOCKET_SENDTO case "$TESTS" in *%$N%*|*%functions%*|*%generic%*|*%socket%*|*%ip4%*|*%udp%*|*%dgram%*|*%$NAME%*) TEST="$NAME: socket sendto with UDP/IPv4" # start a UDP4-RECVFROM process that echoes data, and send test data using # SOCKET-SENDTO, selecting UDP/IPv4. The sent data should be returned. if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts0p=$PORT; PORT=$((PORT+1)) ts0a="127.0.0.1" ts1p=$(printf "%04x" $ts0p); ts1a="7f000001" # "127.0.0.1" ts1="x${ts1p}${ts1a}x0000000000000000" ts1b=$(printf "%04x" $PORT); PORT=$((PORT+1)) da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts UDP4-RECVFROM:$ts0p,reuseaddr,bind=$ts0a PIPE" CMD1="$TRACE $SOCAT $opts - SOCKET-SENDTO:2:$SOCK_DGRAM:17:$ts1,bind=x${ts1b}x00000000x0000000000000000" printf "test $F_n $TEST... " $N $CMD0 2>"${te}0" & pid0="$!" waitudp4port $ts0p 1 echo "$da" |$CMD1 >>"$tf" 2>>"${te}1" rc1="$?" kill "$pid0" 2>/dev/null; wait; if [ "$rc1" -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD0 &" cat "${te}0" echo "$CMD1" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" echo "$CMD0 &" cat "${te}0" echo "$CMD1" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) # test the SOCKET-RECVFROM address (with UDP4-SENDTO) NAME=SOCKET_RECVFROM case "$TESTS" in *%$N%*|*%functions%*|*%generic%*|*%socket%*|*%ip4%*|*%udp%*|*%dgram%*|*%$NAME%*) TEST="$NAME: socket recvfrom with UDP/IPv4" # start a SOCKET-RECVFROM process that uses UDP/IPv4 and echoes data, and # send test data using UDP4-SENDTO. The sent data should be returned. if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1p=$PORT; PORT=$((PORT+1)) ts1a="127.0.0.1" ts0p=$(printf "%04x" $ts1p); ts0a="7f000001" # "127.0.0.1" ts0="x${ts0p}${ts0a}x0000000000000000" ts1b=$PORT; PORT=$((PORT+1)) ts1="$ts1a:$ts1p" da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts SOCKET-RECVFROM:2:$SOCK_DGRAM:17:$ts0,reuseaddr PIPE" CMD1="$TRACE $SOCAT $opts - UDP4-SENDTO:$ts1,bind=:$ts1b" printf "test $F_n $TEST... " $N $CMD0 2>"${te}0" & pid0="$!" sleep 1 # waitudp4port $ts1p 1 echo "$da" |$CMD1 >>"$tf" 2>>"${te}1" rc1="$?" kill "$pid0" 2>/dev/null; wait; if [ "$rc1" -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD0 &" cat "${te}0" echo "$CMD1" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" echo "$CMD0 &" cat "${te}0" echo "$CMD1" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) # test the SOCKET-RECV address (with UDP4-SENDTO) NAME=SOCKET_RECV case "$TESTS" in *%$N%*|*%functions%*|*%generic%*|*%socket%*|*%ip4%*|*%udp%*|*%dgram%*|*%$NAME%*) TEST="$NAME: socket recv with UDP/IPv4" # start a SOCKET-RECV process that uses UPD/IPv4 and writes received data to file, and # send test data using UDP4-SENDTO. if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts1p=$PORT; PORT=$((PORT+1)) ts1a="127.0.0.1" ts0p=$(printf "%04x" $ts1p); ts0a="7f000001" # "127.0.0.1" ts0="x${ts0p}${ts0a}x0000000000000000" ts1b=$PORT; PORT=$((PORT+1)) ts1="$ts1a:$ts1p" da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts -u SOCKET-RECV:2:$SOCK_DGRAM:17:$ts0,reuseaddr -" CMD1="$TRACE $SOCAT $opts -u - UDP4-SENDTO:$ts1,bind=:$ts1b" printf "test $F_n $TEST... " $N $CMD0 2>"${te}0" >"$tf" & pid0="$!" sleep 1 # waitudp4port $ts1p 1 echo "$da" |$CMD1 2>>"${te}1" rc1="$?" sleep 1 kill "$pid0" 2>/dev/null; wait; if [ "$rc1" -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD0 &" cat "${te}0" echo "$CMD1" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" echo "$CMD0 &" cat "${te}0" echo "$CMD1" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) # test SOCKET-DATAGRAM (with UDP4-DATAGRAM) NAME=SOCKET_DATAGRAM case "$TESTS" in *%$N%*|*%functions%*|*%generic%*|*%socket%*|*%ip4%*|*%udp%*|*%dgram%*|*%$NAME%*) TEST="$NAME: socket datagram via UDP/IPv4" # start a UDP4-DATAGRAM process that echoes data, and send test data using # SOCKET-DATAGRAM, selecting UDP/IPv4. The sent data should be returned. if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" ts0p=$PORT; PORT=$((PORT+1)) ts1p=$PORT; PORT=$((PORT+1)) ts0a="127.0.0.1" ts1b=$(printf "%04x" $ts0p); ts1a="7f000001" # "127.0.0.1" ts0b=$(printf "%04x" $ts0p) ts1b=$(printf "%04x" $ts1p) ts1="x${ts0b}${ts1a}x0000000000000000" da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts UDP4-DATAGRAM:$ts0a:$ts1p,bind=:$ts0p,reuseaddr PIPE" CMD1="$TRACE $SOCAT $opts - SOCKET-DATAGRAM:2:$SOCK_DGRAM:17:$ts1,bind=x${ts1b}x00000000x0000000000000000" printf "test $F_n $TEST... " $N $CMD0 2>"${te}0" & pid0="$!" waitudp4port $ts0p 1 echo "$da" |$CMD1 2>>"${te}1" >"$tf" rc1="$?" kill "$pid0" 2>/dev/null; wait; if [ "$rc1" -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD0 &" cat "${te}0" echo "$CMD1" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" echo "$CMD0 &" cat "${te}0" echo "$CMD1" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat $te; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) NAME=SOCKETRANGEMASK case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%generic%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%socket%*|*%range%*|*%$NAME%*) TEST="$NAME: security of generic socket-listen with RANGE option" if ! eval $NUMCOND; then :; elif [ -z "$SECONDADDR" ]; then # we need access to more loopback addresses $PRINTF "test $F_n $TEST... ${YELLOW}need a second IPv4 address${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else ts1p=$(printf "%04x" $PORT); testserversec "$N" "$TEST" "$opts" "SOCKET-LISTEN:2:6:x${ts1p}x00000000x0000000000000000,$REUSEADDR,fork,retry=1" "" "range=x0000x7f000000:x0000xffffffff" "SOCKET-CONNECT:2:6:x${ts1p}x${SECONDADDRHEX}x0000000000000000" 4 tcp $PORT 0 fi ;; # NUMCOND, $SECONDADDR esac PORT=$((PORT+1)) N=$((N+1)) TIOCEXCL="$($PROCAN -c |grep "^#define[[:space:]]*TIOCEXCL[[:space:]]" |cut -d' ' -f3)" # test the generic ioctl-void option NAME=IOCTL_VOID case "$TESTS" in *%$N%*|*%functions%*|*%pty%*|*%generic%*|*%$NAME%*) TEST="$NAME: test the ioctl-void option" # there are not many ioctls that apply to non global resources and do not # require root. TIOCEXCL seems to fit: # process 0 provides a pty; # process 1 opens it with the TIOCEXCL ioctl; # process 2 opens it too and fails with "device or resource busy" only when the # previous ioctl was successful if ! eval $NUMCOND; then :; elif [ -z "$TIOCEXCL" ]; then # we use the numeric value of TIOCEXL which is system dependent $PRINTF "test $F_n $TEST... ${YELLOW}no value of TIOCEXCL${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tp="$td/test$N.pty" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts PTY,LINK=$tp pipe" CMD1="$TRACE $SOCAT $opts - file:$tp,ioctl-void=$TIOCEXCL,raw,echo=0" CMD2="$TRACE $SOCAT $opts - file:$tp,raw,echo=0" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" & pid0=$! waitfile $tp 1 (echo "$da"; sleep 2) |$CMD1 >"$tf" 2>"${te}1" & # this should always work pid1=$! usleep 1000000 $CMD2 >/dev/null 2>"${te}2" /dev/null; wait if ! echo "$da" |diff - "$tf" >/dev/null; then $PRINTF "${YELLOW}phase 1 failed${NORMAL}\n" echo "$CMD0 &" echo "$CMD1" echo "$da" |diff - "$tf" numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ $rc2 -eq 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD0 &" echo "$CMD1" echo "$CMD2" cat "${te}0" "${te}1" "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}0" "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi fi # NUMCOND, TIOCEXCL ;; esac N=$((N+1)) SOL_SOCKET="$($PROCAN -c |grep "^#define[[:space:]]*SOL_SOCKET[[:space:]]" |cut -d' ' -f3)" SO_REUSEADDR="$($PROCAN -c |grep "^#define[[:space:]]*SO_REUSEADDR[[:space:]]" |cut -d' ' -f3)" TCP_MAXSEG="$($PROCAN -c |grep "^#define[[:space:]]*TCP_MAXSEG[[:space:]]" |cut -d' ' -f3)" # Test the generic setsockopt option NAME=SETSOCKOPT case "$TESTS" in *%$N%*|*%functions%*|*%ip4%*|*%tcp%*|*%generic%*|*%$NAME%*) TEST="$NAME: test the setsockopt option" # 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. # Thus: # process 0 provides a tcp listening,forking socket # process 1 connects to this port using reasonably MSS, data transfer should # succeed. # Then, # process 2 connects to this port using a very small MSS, this should fail if ! eval $NUMCOND; then :; elif [ -z "$TCP_MAXSEG" ]; then # we use the numeric value of TCP_MAXSEG which might be system dependent $PRINTF "test $F_n $TEST... ${YELLOW}value of TCPMAXSEG not known${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts TCP4-L:$PORT,so-reuseaddr,fork PIPE" CMD1="$TRACE $SOCAT $opts - TCP:$LOCALHOST:$PORT,setsockopt=6:$TCP_MAXSEG:512" CMD2="$TRACE $SOCAT $opts - TCP:$LOCALHOST:$PORT,setsockopt=6:$TCP_MAXSEG:1" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" & pid0=$! waittcp4port $PORT 1 (echo "$da"; sleep 1) |$CMD1 >"${tf}1" 2>"${te}1" # this should always work rc1=$? usleep 1000000 (echo "$da"; sleep 1) |$CMD2 >"${tf}2" 2>"${te}2" # this should fail rc2=$? kill $pid0 $pid1 $pid2 2>/dev/null; wait if ! echo "$da" |diff - "${tf}1" >"$tdiff"; then $PRINTF "${YELLOW}phase 1 failed${NORMAL}\n" echo "$CMD0 &" cat ${te}0 echo "$CMD1" cat ${te}1 cat "$tdiff" numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ $rc1 -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD0 &" cat ${te}0 echo "$CMD1" cat ${te}1 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif [ $rc2 -eq 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD0 &" cat ${te}0 echo "$CMD2" cat ${te}2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}0" "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi fi # NUMCOND, SO_REUSEADDR ;; esac PORT=$((PORT+1)) N=$((N+1)) # Test the generic setsockopt-listen option # This test, with setsockopt-int, no longer worked due to fix for options on # listening sockets # Now it got a chance again using new option setsockopt-listen #NAME=SETSOCKOPT_INT NAME=SETSOCKOPT_LISTEN case "$TESTS" in *%$N%*|*%functions%*|*%ip4%*|*%tcp%*|*%generic%*|*%$NAME%*) TEST="$NAME: test the setsockopt-listen option" # there are not many socket options that apply to non global resources, do not # require root, do not require a network connection, and can easily be # tested. SO_REUSEADDR seems to fit: # process 0 provides a tcp listening socket with reuseaddr; # process 1 connects to this port; thus the port is connected but no longer # listening # process 2 tries to listen on this port with SO_REUSEADDR, will fail if the # (generically specified) SO_REUSEADDR socket options did not work # process 3 connects to this port; only if it is successful the test is ok if ! eval $NUMCOND; then :; elif [ -z "$SO_REUSEADDR" ]; then # we use the numeric value of SO_REUSEADDR which might be system dependent $PRINTF "test $F_n $TEST... ${YELLOW}value of SO_REUSEADDR not known${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts TCP4-L:$PORT,setsockopt-listen=$SOL_SOCKET:$SO_REUSEADDR:1 PIPE" CMD1="$TRACE $SOCAT $opts - TCP:$LOCALHOST:$PORT" CMD2="$CMD0" CMD3="$CMD1" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" & pid0=$! waittcp4port $PORT 1 echo "$da" |$CMD1 >"${tf}1" 2>"${te}1" # this should always work rc1=$? kill $pid0 2>/dev/null; wait $CMD2 >/dev/null 2>"${te}2" & pid2=$! waittcp4port $PORT 1 echo "$da" |$CMD3 >"${tf}3" 2>"${te}3" rc3=$? kill $pid2 2>/dev/null; wait if ! echo "$da" |diff - "${tf}1" >"${tdiff}1"; then $PRINTF "${YELLOW}phase 1 failed${NORMAL}\n" echo "$CMD0 &" cat ${te}0 echo "$CMD1" cat ${te}1 cat "${tdiff}1" numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ $rc3 -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD0 &" cat ${te}0 echo "$CMD1" cat ${te}1 echo "$CMD2 &" cat ${te}2 echo "$CMD3" cat ${te}3 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "${tf}3" >"${tdiff}3"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD0 &" cat ${te}0 echo "$CMD1" cat ${te}1 echo "$CMD2 &" cat ${te}2 echo "$CMD3" cat ${te}3 cat "${tdiff}3" numCANT=$((numCANT+1)) listCANT="$listCANT $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}0" "${te}1" "${te}2" "${te}3"; fi numOK=$((numOK+1)) fi fi # NUMCOND, SO_REUSEADDR ;; esac PORT=$((PORT+1)) N=$((N+1)) NAME=SCTP4STREAM case "$TESTS" in *%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%sctp%*|*%$NAME%*) TEST="$NAME: echo via connection to SCTP V4 socket" PORT="$((PORT+1))" if ! eval $NUMCOND; then :; elif ! testfeats sctp ip4 >/dev/null || ! runsip4 >/dev/null || ! runssctp4 "$((PORT-1))" >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}SCTP4 not available${NORMAL}\n" $N listCANT="$listCANT $N" numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ "$UNAME" = Linux ] && ! grep ^sctp /proc/modules >/dev/null; then # RHEL5 based systems became unusable when an sctp socket was created but # module sctp not loaded $PRINTF "test $F_n $TEST...${YELLOW}load sctp module!${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="127.0.0.1:$tsl" da=$(date) CMD1="$TRACE $SOCAT $opts SCTP4-LISTEN:$tsl,$REUSEADDR PIPE" CMD2="$TRACE $SOCAT $opts stdin!!stdout SCTP4:$ts" printf "test $F_n $TEST... " $N $CMD1 >"$tf" 2>"${te}1" & pid1=$! waitsctp4port $tsl 1 # SCTP does not seem to support half close, so we give it 1s to finish (echo "$da"; sleep 1) |$CMD2 >>"$tf" 2>>"${te}2" if [ $? -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" cat "${te}1" echo "$CMD2" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid1 2>/dev/null wait fi # NUMCOND, feats ;; esac PORT=$((PORT+1)) N=$((N+1)) NAME=SCTP6STREAM case "$TESTS" in *%$N%*|*%functions%*|*%ip6%*|*%ipapp%*|*%sctp%*|*%$NAME%*) TEST="$NAME: echo via connection to SCTP V6 socket" PORT="$((PORT+1))" if ! eval $NUMCOND; then :; elif ! testfeats sctp ip6 >/dev/null || ! runsip6 >/dev/null || ! runssctp6 "$((PORT-1))" >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}SCTP6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ "$UNAME" = Linux ] && ! grep ^sctp /proc/modules >/dev/null; then $PRINTF "test $F_n $TEST...${YELLOW}load sctp module!${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" tsl=$PORT ts="[::1]:$tsl" da=$(date) CMD1="$TRACE $SOCAT $opts SCTP6-listen:$tsl,$REUSEADDR PIPE" CMD2="$TRACE $SOCAT $opts stdin!!stdout SCTP6:$ts" printf "test $F_n $TEST... " $N $CMD1 >"$tf" 2>"${te}1" & pid=$! # background process id waitsctp6port $tsl 1 # SCTP does not seem to support half close, so we let it 1s to finish (echo "$da"; sleep 1) |$CMD2 >>"$tf" 2>>"${te}2" if [ $? -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" cat "${te}1" echo "$CMD2" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: diff:\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null fi # NUMCOND, feats ;; esac PORT=$((PORT+1)) N=$((N+1)) if type openssl >/dev/null 2>&1; then OPENSSL_METHOD=$(openssl s_client -help 2>&1 |egrep -e '-tls1_[012]' |sed -e 's/.*\(-tls1_[012]\).*/\1/' |sort |tail -n 1) #OPENSSL_METHOD=$(openssl s_client -help 2>&1 |egrep -o -e '-tls1(_[012])?' |sort |tail -n 1) [ -z "$OPENSSL_METHOD" ] && OPENSSL_METHOD="-tls1" # just so fi # socat up to 1.7.1.1 (and 2.0.0-b3) terminated with error when an openssl peer # performed a renegotiation. Test if this is fixed. # Note: the renegotiation feature in OpenSSL exists only up to TLSv1.2 NAME=OPENSSLRENEG1 case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%openssl%*|*%socket%*|*%$NAME%*) TEST="$NAME: OpenSSL connections survive renogotiation" # connect with s_client to socat ssl-l; force a renog, then transfer data. When # data is passed the test succeeded if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! type openssl >/dev/null 2>&1; then $PRINTF "test $F_n $TEST... ${YELLOW}openssl executable not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP/IPv4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" init_openssl_s_client CMD0="$TRACE $SOCAT $opts OPENSSL-LISTEN:$PORT,$REUSEADDR,cert=testsrv.crt,key=testsrv.key,verify=0 PIPE" #CMD1="openssl s_client -port $PORT -verify 0" # not with openssl 1.1.0g CMD1="openssl s_client $OPENSSL_S_CLIENT_4 $OPENSSL_METHOD -port $PORT" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" & pid0=$! waittcp4port $PORT 1 (echo "R"; sleep 1; echo "$da"; sleep 1) |$CMD1 2>"${te}1" |fgrep "$da" >"${tf}1" rc1=$? kill $pid0 2>/dev/null; wait if echo "$da" |diff - ${tf}1 >"$tdiff"; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0 &" echo "$CMD1" cat "${te}0" # cat "${te}1" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # socat up to 1.7.1.1 (and 2.0.0-b3) terminated with error when an openssl peer # performed a renegotiation. The first temporary fix to this problem might # leave socat in a blocking ssl-read state. Test if this has been fixed. # Note: the renegotiation feature in OpenSSL exists only up to TLSv1.2 NAME=OPENSSLRENEG2 case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%openssl%*|*%socket%*|*%$NAME%*) TEST="$NAME: OpenSSL connections do not block after renogotiation" # connect with s_client to socat ssl-l; force a renog, then transfer data from # socat to the peer. When data is passed this means that the former ssl read no # longer blocks and the test succeeds if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! type openssl >/dev/null 2>&1; then $PRINTF "test $F_n $TEST... ${YELLOW}openssl executable not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP/IPv4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" init_openssl_s_client CMD0="$TRACE $SOCAT $opts OPENSSL-LISTEN:$PORT,$REUSEADDR,cert=testsrv.crt,key=testsrv.key,verify=0 SYSTEM:\"sleep 1; echo \\\\\\\"\\\"$da\\\"\\\\\\\"; sleep 1\"!!STDIO" #CMD1="openssl s_client -port $PORT -verify 0" # not with openssl 1.1.0g CMD1="openssl s_client $OPENSSL_S_CLIENT_4 $OPENSSL_METHOD -port $PORT" printf "test $F_n $TEST... " $N eval "$CMD0 >/dev/null 2>\"${te}0\" &" pid0=$! waittcp4port $PORT 1 (echo "R"; sleep 2) |$CMD1 2>"${te}1" |fgrep "$da" >"${tf}1" rc1=$? kill $pid0 2>/dev/null; wait if echo "$da" |diff - ${tf}1 >"$tdiff"; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0 &" echo "$CMD1" cat "${te}0" # cat "${te}1" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # socat up to 1.7.1.2 had a stack overflow vulnerability that occurred when # command line arguments (whole addresses, host names, file names) were longer # than 512 bytes. NAME=HOSTNAMEOVFL case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%security%*|*%socket%*|*%$NAME%*) TEST="$NAME: stack overflow on overly long host name" # provide a long host name to TCP-CONNECT and check socats exit code 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" # prepare long data - perl might not be installed rm -f "$td/test$N.dat" i=0; while [ $i -lt 64 ]; do echo -n "AAAAAAAAAAAAAAAA" >>"$td/test$N.dat"; i=$((i+1)); done CMD0="$TRACE $SOCAT $opts TCP-CONNECT:$(cat "$td/test$N.dat"):$PORT STDIO" printf "test $F_n $TEST... " $N $CMD0 &0 2>"${te}0" rc0=$? if [ $rc0 -lt 128 ] || [ $rc0 -eq 255 ]; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0" cat "${te}0" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # socat up to 1.7.1.2 had a stack overflow vulnerability that occurred when # command line arguments (whole addresses, host names, file names) were longer # than 512 bytes. NAME=FILENAMEOVFL case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%security%*|*%openssl%*|*%$NAME%*) TEST="$NAME: stack overflow on overly long file name" # provide a 600 bytes long key file option to OPENSSL-CONNECT and check socats exit code 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" i=0; while [ $i -lt 64 ]; do echo -n "AAAAAAAAAAAAAAAA" >>"$td/test$N.dat"; i=$((i+1)); done CMD0="$TRACE $SOCAT $opts OPENSSL:localhost:$PORT,key=$(cat "$td/test$N.dat") STDIO" printf "test $F_n $TEST... " $N $CMD0 &0 2>"${te}0" rc0=$? if [ $rc0 -lt 128 ] || [ $rc0 -eq 255 ]; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0" cat "${te}0" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # socat up to 1.7.3.0 had a stack overflow vulnerability that occurred when # command line arguments (whole addresses, host names, file names) were longer # than 512 bytes and specially crafted. NAME=NESTEDOVFL case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%security%*|*%exec%*|*%$NAME%*) TEST="$NAME: stack overflow on overly long nested arg" # provide a long host name to TCP-CONNECT and check socats exit code 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" # prepare long data - perl might not be installed rm -f "$td/test$N.dat" i=0; while [ $i -lt 64 ]; do echo -n "AAAAAAAAAAAAAAAA" >>"$td/test$N.dat"; i=$((i+1)); done CMD0="$TRACE $SOCAT $opts EXEC:[$(cat "$td/test$N.dat")] STDIO" printf "test $F_n $TEST... " $N $CMD0 &0 2>"${te}0" rc0=$? if [ $rc0 -lt 128 ] || [ $rc0 -eq 255 ]; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0" cat "${te}0" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # test for a bug in gopen that lead to crash or warning when opening a unix # domain socket with GOPEN NAME=GOPEN_UNIX_CRASH case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%gopen%*|*%unix%*|*%socket%*|*%$NAME%*) TEST="$NAME: check crash when connecting to a unix domain socket using address GOPEN" # a unix domain server is started in background. the check process connects to # its socket. when this process crashes or issues a warning the bug is present. # please note that a clean behaviour does not proof anything; behaviour of bug # depends on the value of an uninitialized var #set -vx if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" ts="$td/test$N.sock" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts UNIX-LISTEN:$ts PIPE" CMD1="$TRACE $SOCAT $opts -d - GOPEN:$ts" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" "${tf}1" 2>"${te}1" rc1=$? kill $pid0 2>/dev/null; wait if [ $rc1 -ne 0 ]; then $PRINTF "$FAILED\n" echo "$CMD0 &" echo "$CMD1" cat "${te}0" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif grep -q ' W ' "${te}1"; then $PRINTF "$FAILED\n" echo "$CMD0 &" echo "$CMD1" cat "${te}0" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - ${tf}1 >"$tdiff"; then $PRINTF "$FAILED\n" echo "$CMD0 &" echo "$CMD1" cat "${te}0" cat "${te}1" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" numOK=$((numOK+1)) fi fi # NUMCOND ;; esac N=$((N+1)) # test if socat keeps an existing file where it wanted to create a UNIX socket NAME=UNIXLISTEN_KEEPFILE case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%unix%*|*%socket%*|*%$NAME%*) TEST="$NAME: socat keeps an existing file where it wanted to create a UNIX socket" # we create a file and start socat with UNIX-LISTEN on this file. expected # behaviour: socat exits immediately with error, but keeps the file # up to 1.7.1.3, it removed the file if ! eval $NUMCOND; then :; else tf="$td/test$N.file" te="$td/test$N.stderr" CMD0="$TRACE $SOCAT $opts -u UNIX-LISTEN:$tf /dev/null" printf "test $F_n $TEST... " $N rm -f "$tf"; touch "$tf" $CMD0 >/dev/null 2>"${te}0" rc0=$? if [ $rc0 -ne 0 -a -f "$tf" ]; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0" cat "${te}0" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac N=$((N+1)) # PTY address allowed to sepcify address parameters but ignored them NAME=PTY_VOIDARG case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%pty%*|*%$NAME%*) TEST="$NAME: check if address params of PTY produce error" # invoke socat with address PTY and some param; expect an error 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="$TRACE $SOCAT $opts /dev/null PTY:/tmp/xyz" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" rc0=$? if [ $rc0 -ne 0 ]; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0" cat "${te}0" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac N=$((N+1)) # incomplete writes were reported but led to data loss NAME=INCOMPLETE_WRITE case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%$NAME%*) TEST="$NAME: check if incomplete writes are handled properly" # write to a nonblocking fd a block that is too large for atomic write # and check if all data arrives if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tp="$td/test$N.pipe" tw="$td/test$N.wc-c" # this is the size we write() in one call; data is never stored on disk, so # make it large enough to exceed any atomic write size; but higher number might # take much time bytes=100000 # for Linux 2.6.? this must be >65536 CMD0="$TRACE $SOCAT $opts -u PIPE:$tp STDOUT" CMD1="$TRACE $SOCAT $opts -u -b $bytes OPEN:/dev/zero,readbytes=$bytes FILE:$tp,o-nonblock" printf "test $F_n $TEST... " $N $CMD0 2>"${te}0" |wc -c >"$tw" & pid=$! waitfile "$tp" $CMD1 2>"${te}1" >"${tf}1" rc1=$? wait if [ $rc1 -ne 0 ]; then $PRINTF "$NO_RESULT\n" numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ ! -e "$tw" ]; then $PRINTF "$NO_RESULT\n" numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ "$bytes" -eq $(cat "$tw") ]; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "transferred only $(cat $tw) of $bytes bytes" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac N=$((N+1)) NAME=OPENSSL_ANULL case "$TESTS" in *%$N%*|*%functions%*|*%openssl%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*) TEST="$NAME: OpenSSL server with cipher aNULL " if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats listen tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP/IPv4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD2="$TRACE $SOCAT $opts OPENSSL-LISTEN:$PORT,$REUSEADDR,$SOCAT_EGD,ciphers=aNULL,verify=0 pipe" CMD="$TRACE $SOCAT $opts - openssl:$LOCALHOST:$PORT,ciphers=aNULL,verify=0,$SOCAT_EGD" printf "test $F_n $TEST... " $N eval "$CMD2 2>\"${te}1\" &" pid=$! # background process id waittcp4port $PORT echo "$da" |$CMD >$tf 2>"${te}2" if ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "${YELLOW}FAILED${NORMAL}\n" #echo "$CMD2 &" #echo "$CMD" #cat "${te}1" #cat "${te}2" #cat "$tdiff" numOK=$((numOK+1)) else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null wait fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) while read KEYW FEAT 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 max-children option on really connection oriented sockets NAME=${KEYW}MAXCHILDREN case "$TESTS" in *%$N%*|*%functions%*|*%maxchildren%*|*%$feat%*|*%$proto%*|*%socket%*|*%$NAME%*) TEST="$NAME: max-children option" # 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 # data immediately. If max-children is working correctly the first data should # arrive first because the second process has to wait. if ! eval $NUMCOND; then :; elif ! testfeats "$FEAT" >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$FEAT 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") tsl=$PORT # test socket listen address tsc="$ADDR:$PORT" # test socket connect address PORT=$((PORT+1)) ;; *) 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 -U FILE:$tf,o-trunc,o-creat,o-append $PROTO-LISTEN:$tsl,$REUSEADDR,fork,max-children=1" CMD1="$TRACE $SOCAT $opts -u - $PROTO-CONNECT:$tsc,shut-null" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" & pid0=$! wait${proto}port $tsl 1 (echo "$da 1"; sleep 2) |$CMD1 >"${tf}1" 2>"${te}1" & pid1=$! sleep 1 echo "$da 2" |$CMD1 >"${tf}2" 2>"${te}2" & pid2=$! sleep 2 kill $pid1 $pid2 $pid0 2>/dev/null; wait if echo -e "$da 1\n$da 2" |diff - $tf >$tdiff; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0 &" echo "(echo \"$da 1\"; sleep 2) |$CMD1" echo "echo \"$da 2\" |$CMD1" cat "${te}0" cat "${te}1" cat "${te}2" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac N=$((N+1)) done <<<" TCP4 TCP 127.0.0.1 PORT TCP6 TCP [::1] PORT SCTP4 SCTP 127.0.0.1 PORT SCTP6 SCTP [::1] PORT UNIX unix $td/test\$N.server - " # debugging this hanging test was difficult - following lessons learned: # kill had no effect when child process existed # strace -f (on Fedora-23) sometimes writes/pads? blocks with \0, overwriting client traces # using the TRACE feature lets above kill command kill strace, not socat # care for timing, understand what you want :-) while read KEYW FEAT ADDR IPPORT SHUT; do if [ -z "$KEYW" ]|| [[ "$KEYW" == \#* ]]; then continue; fi RUNS=$(tolower $KEYW) PROTO=$KEYW proto="$(echo "$PROTO" |tr A-Z a-z)" # test the max-children option on pseudo connected sockets NAME=${KEYW}MAXCHILDREN case "$TESTS" in *%$N%*|*%functions%*|*%maxchildren%*|*%socket%*|*%$NAME%*) TEST="$NAME: max-children option" # 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 # data immediately, but keep first client active until server terminates. #If max-children is working correctly only the first data should # arrive. if ! eval $NUMCOND; then :; elif ! testfeats "$FEAT" >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$FEAT 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") tsl=$PORT # test socket listen address tsc="$ADDR:$PORT" # test socket connect address PORT=$((PORT+1)) ;; *) 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" # on some Linux distributions it hangs, thus -T option here CMD0="$TRACE $SOCAT $opts -U -T 4 FILE:$tf,o-trunc,o-creat,o-append $PROTO-LISTEN:$tsl,$REUSEADDR,fork,max-children=1" CMD1="$TRACE $SOCAT $opts -u - $PROTO-CONNECT:$tsc,$SHUT" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" & pid0=$! wait${proto}port $tsl 1 (echo "$da 1"; sleep 3) |$CMD1 >"${tf}1" 2>"${te}1" & pid1=$! sleep 1 echo "$da 2" |$CMD1 >"${tf}2" 2>"${te}2" & pid2=$! sleep 1 cpids="$(childpids $pid0)" kill $pid1 $pid2 $pid0 $cpids 2>/dev/null; wait if echo -e "$da 1" |diff - $tf >$tdiff; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0 &" echo "(echo \"$da 1\"; sleep 2) |$CMD1" echo "echo \"$da 2\" |$CMD1" cat "${te}0" cat "${te}1" cat "${te}2" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac N=$((N+1)) done <<<" UDP4 UDP 127.0.0.1 PORT shut-null UDP6 UDP [::1] PORT shut-null " # debugging this hanging test was difficult - following lessons learned: # kill had no effect when child process existed # strace -f (on Fedora-23) sometimes writes/pads? blocks with \0, overwriting client traces # using the TRACE feature lets above kill command kill strace, not socat # care for timing, understand what you want :-) # socat up to 1.7.2.0 had a bug in xioscan_readline() that could be exploited # to overflow a heap based buffer (socat security advisory 3) # problem reported by Johan Thillemann NAME=READLINE_OVFL case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%security%*|*%readline%*|*%pty%*|*%$NAME%*) TEST="$NAME: test for buffer overflow in readline prompt handling" # address 1 is the readline where write data was handled erroneous # address 2 provides data to trigger the buffer overflow # when no SIGSEGV or so occurs the test succeeded (bug fixed) if ! eval $NUMCOND; then :; elif ! feat=$(testfeats readline pty); then $PRINTF "test $F_n $TEST... ${YELLOW}$(echo "$feat"| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" ti="$td/test$N.data" CMD0="$SOCAT $opts READLINE $ti" printf "test $F_n $TEST... " $N # prepare long data - perl might not be installed #perl -e 'print "\r","Z"x513' >"$ti" echo $E -n "\rA" >"$ti" i=0; while [ $i -lt 32 ]; do echo -n "AAAAAAAAAAAAAAAA" >>"$ti"; let i=i+1; done $TRACE $SOCAT - SYSTEM:"$CMD0; echo rc=\$? >&2",pty >/dev/null 2>"${te}0" rc=$? rc0="$(grep ^rc= "${te}0" |sed 's/.*=//')" if [ $rc -ne 0 ]; then $PRINTF "${YELLOW}framework failed${NORMAL}\n" elif [ $rc0 -eq 0 ]; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0" grep -v ^rc= "${te}0" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # socat up to 1.7.2.1 did only shutdown() but not close() an accept() socket # that was rejected due to range, tcpwrap, lowport, or sourceport option. # This file descriptor leak could be used for a denial of service attack. NAME=FDLEAK case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%security%*|*%socket%*|*%$NAME%*) TEST="$NAME: file descriptor leak with range option" # have a TCP-LISTEN with range option; connect with wrong source address until # "open files" limit would exceed. When server continues operation the bug is # not present. 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" RLIMIT_NOFILE="$(ulimit -n)" if ! [[ "$RLIMIT_NOFILE" =~ ^[0-9][0-9]*$ ]]; then $PRINTF "${YELLOW}cannot determine ulimit -n${NORMAL}" else if [ $RLIMIT_NOFILE -gt 1024 ]; then ulimit -n 1024 # 65536 takes too long RLIMIT_NOFILE="$(ulimit -n)" fi CMD0="$TRACE $SOCAT $opts TCP-LISTEN:$PORT,$REUSEADDR,range=$LOCALHOST:255.255.255.255 PIPE" CMD1="$TRACE $SOCAT $opts -t 0 /dev/null TCP:$SECONDADDR:$PORT,bind=$SECONDADDR" CMD2="$TRACE $SOCAT $opts - TCP:$LOCALHOST:$PORT,bind=$LOCALHOST" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" & pid0=$! waittcp4port $PORT 1 while [ $RLIMIT_NOFILE -gt 0 ]; do $CMD1 >/dev/null 2>>"${te}1" let RLIMIT_NOFILE=RLIMIT_NOFILE-1 done echo "$da" |$CMD2 >"${tf}2" 2>"${te}2" rc2=$? kill $pid0 2>/dev/null; wait echo -e "$da" |diff "${tf}2" - >$tdiff if [ $rc2 -ne 0 ]; then $PRINTF "$FAILED\n" echo "$CMD2 &" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif [ -f "$tdiff" -a ! -s "$tdiff" ]; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0 &" echo "$CMD1" echo "$CMD2" cat "${te}0" cat "${te}1" cat "${te}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # ulimit -n fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) if false; then # this overflow is not reliably reproducable # socat up to 2.0.0-b6 did not check the length of the PROXY-CONNECT command line paramters when copying them into the HTTP request buffer. This could lead to a buffer overflow. NAME=PROXY_ADDR_OVFL case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%security%*|*%socket%*|*%$NAME%*) TEST="$NAME: proxy address parameters overflow" # invoke socat PROXY-CONNECT with long proxy server and target server names. If it terminates with exit code >= 128 it is vulnerable # However, even if vulnerable it often does not crash. Therefore we try to use a boundary check program like ElectricFence; only with its help we can tell that clean run proofs absence of vulnerability 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" EF=; for p in ef; do if type ef >/dev/null 2>&1; then EF="ef "; break fi done CMD0="$TRACE $SOCAT $opts TCP-LISTEN:$PORT,$REUSEADDR FILE:/dev/null" #CMD1="$EF $TRACE $SOCAT $opts FILE:/dev/null PROXY-CONNECT:$(perl -e "print 'A' x 256"):$(perl -e "print 'A' x 256"):80" CMD1="$EF $TRACE $SOCAT $opts FILE:/dev/null PROXY-CONNECT:localhost:$(perl -e "print 'A' x 384"):80,proxyport=$PORT" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" & pid0=$! waittcp4port $PORT 1 $CMD1 >/dev/null 2>"${te}1" rc1=$? if [ $rc1 -lt 128 ]; then if [ "$EF" ]; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$UNKNOWN $RED(install ElectricFEnce!)$NORMAL\n" numCANT=$((num+1)) listCANT="$listCANT $N" fi else $PRINTF "$FAILED\n" echo "$CMD1" cat "${te}" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) 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 *%$N%*|*%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="$TRACE $SOCAT $opts TCP4-LISTEN:$PORT,$REUSEADDR,so-keepalive EXEC:\"$FILAN -i 1\",nofork" CMD1="$TRACE $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" numCANT=$((numCANT+1)) listCANT="$listCANT $N" 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)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # OPENSSL-CONNECT with bind option failed on some systems (eg.FreeBSD, but not # Linux) with "Invalid argument". NAME=OPENSSL_CONNECT_BIND case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%socket%*|*%openssl%*|*%$NAME%*) TEST="$NAME: test OPENSSL-CONNECT with bind option" # have a simple SSL server that just echoes data. # connect with socat using OPENSSL-CONNECT with bind, send data and check if the # reply is identical. if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv tf0="$td/test$N.0.stdout" te0="$td/test$N.0.stderr" tf1="$td/test$N.1.stdout" te1="$td/test$N.1.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts OPENSSL-LISTEN:$PORT,$REUSEADDR,cert=testsrv.pem,verify=0 PIPE" CMD1="$TRACE $SOCAT $opts - OPENSSL-CONNECT:$LOCALHOST:$PORT,bind=$LOCALHOST,verify=0" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"$te0" & pid0=$! waittcp4port $PORT 1 echo "$da" |$CMD1 >"$tf1" 2>"$te1" rc1=$? kill $pid0 2>/dev/null; wait if [ "$rc1" -ne 0 ]; then $PRINTF "$FAILED\n" echo "$CMD0 &" echo "$CMD1" cat "$te0" cat "$te1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - $tf1 >"$tdiff"; then $PRINTF "$FAILED\n" echo "$CMD0 &" echo "$CMD1" cat "${te}0" cat "${te}1" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" numOK=$((numOK+1)) fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # socat up to version 1.7.2.3 # had a bug that converted a bit mask of 0 internally to 0xffffffff NAME=TCP4RANGE_0BITS case "$TESTS" in *%$N%*|*%functions%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%range%*|*%$NAME%*) TEST="$NAME: correct evaluation of range mask 0" if ! eval $NUMCOND; then :; elif [ -z "$SECONDADDR" ]; then # we need access to a second address $PRINTF "test $F_n $TEST... ${YELLOW}need a second IPv4 address${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" #testserversec "$N" "$TEST" "$opts" "tcp4-l:$PORT,reuseaddr,fork,retry=1" "" "range=$SECONDADDR/32" "tcp4:127.0.0.1:$PORT" 4 tcp $PORT 0 CMD0="$TRACE $SOCAT $opts -u TCP4-LISTEN:$PORT,$REUSEADDR,range=127.0.0.1/0 CREATE:$tf" CMD1="$TRACE $SOCAT $opts -u - TCP4-CONNECT:$SECONDADDR:$PORT,bind=$SECONDADDR" printf "test $F_n $TEST... " $N $CMD0 2>"${te}0" & pid0=$! waittcp4port $PORT 1 echo "$da" |$CMD1 >"${tf}1" 2>"${te}1" rc1=$? sleep 1 kill $pid0 2>/dev/null; wait if [ $rc1 != 0 ]; then $PRINTF "${YELLOW}invocation failed${NORMAL}\n" numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! [ -f "$tf" ]; then $PRINTF "$FAILED\n" echo "$CMD0 &" echo "$CMD1" cat "${te}0" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "${YELLOW}diff failed${NORMAL}\n" numCANT=$((numCANT+1)) listCANT="$listCANT $N" else $PRINTF "$OK\n" numOK=$((numOK+1)) fi fi ;; # $SECONDADDR, NUMCOND esac PORT=$((PORT+1)) N=$((N+1)) # test: OPENSSL sets of environment variables with important values of peer certificate while read ssldist MODE MODULE FIELD TESTADDRESS PEERADDRESS VALUE; do if [ -z "$ssldist" ] || [[ "$ssldist" == \#* ]]; then continue; fi # SSLDIST=$(toupper $ssldist) NAME="ENV_${SSLDIST}_${MODE}_${MODULE}_${FIELD}" case "$TESTS" in *%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%tcp%*|*%$ssldist%*|*%envvar%*|*%$NAME%*) TEST="$NAME: $SSLDIST sets env SOCAT_${SSLDIST}_${MODULE}_${FIELD}" # have a server accepting a connection and invoking some shell code. The shell # code extracts and prints the SOCAT related environment vars. # outside code then checks if the environment contains the variables correctly # describing the desired field. FEAT=$(echo "$ssldist" |tr a-z A-Z) if ! eval $NUMCOND; then :; elif ! testfeats $FEAT >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$FEAT not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" gentestcert testsrv gentestcert testcli test_proto=tcp4 case "$MODE" in SERVER) CMD0="$SOCAT $opts -u $TESTADDRESS system:\"echo SOCAT_${SSLDIST}_${MODULE}_${FIELD}=\\\$SOCAT_${SSLDIST}_${MODULE}_${FIELD}; sleep 1\"" CMD1="$SOCAT $opts -u /dev/null $PEERADDRESS" printf "test $F_n $TEST... " $N eval "$CMD0 2>\"${te}0\" >\"$tf\" &" pid0=$! wait${test_proto}port $PORT 1 $CMD1 2>"${te}1" rc1=$? waitfile "$tf" 2 kill $pid0 2>/dev/null; wait ;; CLIENT) CMD0="$SOCAT $opts -u /dev/null $PEERADDRESS" CMD1="$SOCAT $opts -u $TESTADDRESS system:\"echo SOCAT_${SSLDIST}_${MODULE}_${FIELD}=\\\$SOCAT_${SSLDIST}_${MODULE}_${FIELD}; sleep 1\"" printf "test $F_n $TEST... " $N $CMD0 2>"${te}0" & pid0=$! wait${test_proto}port $PORT 1 eval "$CMD1 2>\"${te}1\" >\"$tf\"" rc1=$? waitfile "$tf" 2 kill $pid0 2>/dev/null; wait ;; esac if [ $rc1 != 0 ]; then $PRINTF "$NO_RESULT (client failed):\n" echo "$CMD0 &" cat "${te}0" echo "$CMD1" cat "${te}1" numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif effval="$(grep SOCAT_${SSLDIST}_${MODULE}_${FIELD} "${tf}" |sed -e 's/^[^=]*=//' |sed -e "s/[\"']//g")"; [ "$effval" = "$VALUE" ]; then $PRINTF "$OK\n" if [ "$debug" ]; then echo "$CMD0 &" cat "${te}0" echo "$CMD1" cat "${te}1" fi numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "expected \"$VALUE\", got \"$effval\"" >&2 echo "$CMD0 &" cat "${te}0" echo "$CMD1" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND, feats ;; esac N=$((N+1)) # done <<<" openssl SERVER X509 ISSUER OPENSSL-LISTEN:$PORT,$REUSEADDR,bind=$LOCALHOST,cert=testsrv.pem,cafile=testcli.crt,verify=1 OPENSSL-CONNECT:$LOCALHOST:$PORT,cert=testcli.pem,cafile=testsrv.crt,verify=1 $TESTCERT_ISSUER openssl SERVER X509 SUBJECT OPENSSL-LISTEN:$PORT,$REUSEADDR,bind=$LOCALHOST,cert=testsrv.pem,cafile=testcli.crt,verify=1 OPENSSL-CONNECT:$LOCALHOST:$PORT,cert=testcli.pem,cafile=testsrv.crt,verify=1 $TESTCERT_SUBJECT openssl SERVER X509 COMMONNAME OPENSSL-LISTEN:$PORT,$REUSEADDR,bind=$LOCALHOST,cert=testsrv.pem,cafile=testcli.crt,verify=1 OPENSSL-CONNECT:$LOCALHOST:$PORT,cert=testcli.pem,cafile=testsrv.crt,verify=1 $TESTCERT_COMMONNAME openssl SERVER X509 COUNTRYNAME OPENSSL-LISTEN:$PORT,$REUSEADDR,bind=$LOCALHOST,cert=testsrv.pem,cafile=testcli.crt,verify=1 OPENSSL-CONNECT:$LOCALHOST:$PORT,cert=testcli.pem,cafile=testsrv.crt,verify=1 $TESTCERT_COUNTRYNAME openssl SERVER X509 LOCALITYNAME OPENSSL-LISTEN:$PORT,$REUSEADDR,bind=$LOCALHOST,cert=testsrv.pem,cafile=testcli.crt,verify=1 OPENSSL-CONNECT:$LOCALHOST:$PORT,cert=testcli.pem,cafile=testsrv.crt,verify=1 $TESTCERT_LOCALITYNAME openssl SERVER X509 ORGANIZATIONALUNITNAME OPENSSL-LISTEN:$PORT,$REUSEADDR,bind=$LOCALHOST,cert=testsrv.pem,cafile=testcli.crt,verify=1 OPENSSL-CONNECT:$LOCALHOST:$PORT,cert=testcli.pem,cafile=testsrv.crt,verify=1 $TESTCERT_ORGANIZATIONALUNITNAME openssl SERVER X509 ORGANIZATIONNAME OPENSSL-LISTEN:$PORT,$REUSEADDR,bind=$LOCALHOST,cert=testsrv.pem,cafile=testcli.crt,verify=1 OPENSSL-CONNECT:$LOCALHOST:$PORT,cert=testcli.pem,cafile=testsrv.crt,verify=1 $TESTCERT_ORGANIZATIONNAME openssl CLIENT X509 SUBJECT OPENSSL-CONNECT:$LOCALHOST:$PORT,cert=testcli.pem,cafile=testsrv.crt,verify=1 OPENSSL-LISTEN:$PORT,$REUSEADDR,bind=$LOCALHOST,cert=testsrv.pem,cafile=testcli.crt,verify=1 $TESTCERT_SUBJECT openssl CLIENT X509 ISSUER OPENSSL-CONNECT:$LOCALHOST:$PORT,cert=testcli.pem,cafile=testsrv.crt,verify=1 OPENSSL-LISTEN:$PORT,$REUSEADDR,bind=$LOCALHOST,cert=testsrv.pem,cafile=testcli.crt,verify=1 $TESTCERT_ISSUER " ############################################################################### # tests: option umask with "passive" NAMED group addresses while read addr fileopt addropts proto diropt ADDR2; do if [ -z "$addr" ] || [[ "$addr" == \#* ]]; then continue; fi # some passive (listening...) filesystem based addresses did not implement the # umask option ADDR=$(toupper $addr) ADDR_=${ADDR/-/_} PROTO=$(toupper $proto) if [ "$diropt" = "." ]; then diropt=; fi if [ "$fileopt" = "." ]; then fileopt=; fi if [ "$addropts" = "." ]; then addropts=; fi NAME=${ADDR_}_UMASK case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%proto%*|*%socket%*|*%$proto%*|*%umask%*|*%$NAME%*) TEST="$NAME: $ADDR applies option umask" # start a socat process with passive/listening file system entry. Check the # permissions of the FS entry, then terminate the process. # Test succeeds when FS entry exists and has expected permissions. if ! eval $NUMCOND; then :; else if [ $ADDR = PTY ]; then set -xv; fi tlog="$td/test$N.log" te0="$td/test$N.0.stderr" tsock="$td/test$N.sock" if [ -z "$fileopt" ]; then CMD0="$TRACE $SOCAT $opts $diropt $ADDR:$tsock,$addropts,unlink-close=0,umask=177 $ADDR2" else CMD0="$TRACE $SOCAT $opts $diropt $ADDR,$fileopt=$tsock,$addropts,unlink-close=0,umask=177 $ADDR2" fi printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"$te0" & pid0=$! wait${proto} $tsock 1 2>"$tlog" ERRNOENT=; if ! [ -e "$tsock" ]; then ERRNOENT=1; fi perms=$(fileperms "$tsock") kill $pid0 2>>"$tlog" wait if [ "$ERRNOENT" ]; then $PRINTF "${RED}no entry${NORMAL}\n" echo "$CMD0 &" cat "$te0" cat "$tlog" let numFAIL=numFAIL+1 listFAIL="$listFAIL $N" elif [ "$perms" != "600" ]; then $PRINTF "${RED}perms \"$perms\", expected \"600\" ${NORMAL}\n" echo "$CMD0 &" cat "$te0" let numFAIL=numFAIL+1 listFAIL="$listFAIL $N" else $PRINTF "$OK\n" let numOK=numOK+1 fi set +xv fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # done <<<" # address fileopt addropts waitfor direction ADDR2 create . . file -U FILE:/dev/null open . creat file . FILE:/dev/null gopen . creat file . FILE:/dev/null unix-listen . . unixport . FILE:/dev/null unix-recvfrom . . unixport . FILE:/dev/null unix-recv . . unixport -u FILE:/dev/null pipe . . file -u FILE:/dev/null # pty does not seem to honor umask: #pty link . file . PIPE " # tests: option perm with "passive" NAMED group addresses while read addr fileopt addropts feat waitfor diropt; do if [ -z "$addr" ] || [[ "$addr" == \#* ]]; then continue; fi # test if passive (listening...) filesystem based addresses implement option perm ADDR=$(toupper $addr) ADDR_=${ADDR/-/_} if [ "$diropt" = "." ]; then diropt=; fi if [ "$fileopt" = "." ]; then fileopt=; fi if [ "$addropts" = "." ]; then addropts=; fi NAME=${ADDR_}_PERM case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%socket%*|*%$feat%*|*%ignoreeof%*|*%perm%*|*%$NAME%*) TEST="$NAME: $ADDR applies option perm" # start a socat process with passive/listening file system entry. Check the # permissions of the FS entry, then terminate the process. # Test succeeds when FS entry exists and has expected permissions. if ! eval $NUMCOND; then :; else tlog="$td/test$N.log" te0="$td/test$N.0.stderr" tsock="$td/test$N.sock" # set -vx if [ -z "$fileopt" ]; then CMD0="$TRACE $SOCAT $opts $diropt $ADDR:$tsock,$addropts,perm=511 FILE:/dev/null,ignoreeof" else CMD0="$TRACE $SOCAT $opts $diropt $ADDR,$fileopt=$tsock,$addropts,perm=511 FILE:/dev/null,ignoreeof" fi printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"$te0" & pid0=$! wait${waitfor} $tsock 1 2>"$tlog" ERRNOENT=; if ! [ -e "$tsock" ]; then ERRNOENT=1; fi perms=$(fileperms "$tsock") kill $pid0 2>>"$tlog" wait if [ "$ERRNOENT" ]; then $PRINTF "${RED}no entry${NORMAL}\n" echo "$CMD0 &" cat "$te0" cat "$tlog" let numFAIL=numFAIL+1 listFAIL="$listFAIL $N" elif [ "$perms" != "511" ]; then $PRINTF "${RED}perms \"$perms\", expected \"511\" ${NORMAL}\n" echo "$CMD0 &" cat "$te0" let numFAIL=numFAIL+1 listFAIL="$listFAIL $N" else $PRINTF "$OK\n" let numOK=numOK+1 fi set +vx fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # done <<<" # address fileopt addropts feat waitfor direction create . . file file -U open . creat file file . gopen . creat file file . unix-listen . . unix unixport . unix-recvfrom . . unix unixport . unix-recv . . unix unixport -u pipe . . pipe file -u pty link . pty file . " # tests: option user with "passive" NAMED group addresses while read addr fileopt addropts feat waitfor diropt; do if [ -z "$addr" ] || [[ "$addr" == \#* ]]; then continue; fi # test if passive (listening...) filesystem based addresses implement option user ADDR=$(toupper $addr) ADDR_=${ADDR/-/_} if [ "$diropt" = "." ]; then diropt=; fi if [ "$fileopt" = "." ]; then fileopt=; fi if [ "$addropts" = "." ]; then addropts=; fi NAME=${ADDR_}_USER case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%socket%*|*%$feat%*|*%root%*|*%ignoreeof%*|*%$NAME%*) TEST="$NAME: $ADDR applies option user" # start a socat process with passive/listening file system entry with user option. # Check the owner of the FS entry, then terminate the process. # Test succeeds when FS entry exists and has expected owner. if ! eval $NUMCOND; then :; elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then $PRINTF "test $F_n $TEST... ${YELLOW}must be root${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tlog="$td/test$N.log" te0="$td/test$N.0.stderr" tsock="$td/test$N.sock" # set -vx if [ -z "$fileopt" ]; then CMD0="$TRACE $SOCAT $opts $diropt $ADDR:$tsock,$addropts,user=$SUBSTUSER FILE:/dev/null,ignoreeof" else CMD0="$TRACE $SOCAT $opts $diropt $ADDR,$fileopt=$tsock,$addropts,user=$SUBSTUSER FILE:/dev/null,ignoreeof" fi printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"$te0" & pid0=$! wait${waitfor} $tsock 1 2>"$tlog" ERRNOENT=; if ! [ -e "$tsock" ]; then ERRNOENT=1; fi user=$(fileuser "$tsock") kill $pid0 2>>"$tlog" wait if [ "$ERRNOENT" ]; then $PRINTF "${RED}no entry${NORMAL}\n" echo "$CMD0 &" cat "$te0" cat "$tlog" let numFAIL=numFAIL+1 listFAIL="$listFAIL $N" elif [ "$user" != "$SUBSTUSER" ]; then $PRINTF "${RED}user \"$user\", expected \"$SUBSTUSER\" ${NORMAL}\n" echo "$CMD0 &" cat "$te0" let numFAIL=numFAIL+1 listFAIL="$listFAIL $N" else $PRINTF "$OK\n" let numOK=numOK+1 fi set +vx fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # done <<<" # address fileopt addropts feat waitfor direction create . . file file -U open . creat file file . gopen . creat file file . unix-listen . . unix unixport . unix-recvfrom . . unix unixport . unix-recv . . unix unixport -u pipe . . pipe file -u pty link . pty file . " # tests: is "passive" filesystem entry removed at the end? (without fork) while read addr fileopt addropts feat waitfor diropt crit ADDR2; do if [ -z "$addr" ] || [[ "$addr" == \#* ]]; then continue; fi # some passive (listening...) filesystem based addresses did not remove the file # system entry at the end ADDR=$(toupper $addr) ADDR_=${ADDR/-/_} if [ "$diropt" = "." ]; then diropt=; fi if [ "$fileopt" = "." ]; then fileopt=; fi if [ "$addropts" = "." ]; then addropts=; fi # $ADDR removes the file system entry when the process is terminated NAME=${ADDR_}_REMOVE case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%feat%*|*%socket%*|*%$NAME%*) TEST="$NAME: $ADDR removes socket entry when terminated while waiting for connection" # start a socat process with listening unix domain socket etc. Terminate the # process and check if the file system socket entry still exists. # Test succeeds when entry does not exist. if ! eval $NUMCOND; then :; else tlog="$td/test$N.log" te0="$td/test$N.0.stderr" tsock="$td/test$N.sock" if [ -z "$fileopt" ]; then CMD0="$TRACE $SOCAT $opts $diropt $ADDR:$tsock,$addropts $ADDR2" else CMD0="$TRACE $SOCAT $opts $diropt $ADDR,$fileopt=$tsock,$addropts $ADDR2" fi printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"$te0" & pid0=$! wait${waitfor} "$crit" $tsock 1 2>"$tlog" kill $pid0 2>>"$tlog" rc1=$? wait >>"$tlog" if [ $rc1 != 0 ]; then $PRINTF "${YELLOW}setup failed${NORMAL}\n" echo "$CMD0 &" cat "$te0" cat "$tlog" numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! [ $crit $tsock ]; then $PRINTF "$OK\n" let numOK=numOK+1 else $PRINTF "$FAILED\n" echo "$CMD0 &" cat "$te0" cat "$tlog" let numFAIL=numFAIL+1 listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # done <<<" # address fileopt addropts feat waitfor direction crit ADDR2 unix-listen . . unix unixport . -e FILE:/dev/null unix-recvfrom . . unix unixport . -e FILE:/dev/null unix-recv . . unix unixport -u -e FILE:/dev/null pipe . . pipe file -u -e FILE:/dev/null pty link . pty file . -L PIPE " # tests: is "passive" filesystem entry removed at the end? (with fork) while read addr fileopt addropts proto diropt crit ADDR2; do if [ -z "$addr" ] || [[ "$addr" == \#* ]]; then continue; fi # some passive (listening...) filesystem based addresses with fork did not remove # the file system entry at the end ADDR=$(toupper $addr) ADDR_=${ADDR/-/_} PROTO=$(toupper $proto) if [ "$diropt" = "." ]; then diropt=; fi if [ "$fileopt" = "." ]; then fileopt=; fi if [ "$addropts" = "." ]; then addropts=; fi # $ADDR with fork removes the file system entry when the process is terminated NAME=${ADDR_}_REMOVE_FORK case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%unix%*|*%socket%*|*%$NAME%*) 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. # Terminate the process and check if the file system socket entry still exists. # Test succeeds when entry does not exist. if ! eval $NUMCOND; then :; else tlog="$td/test$N.log" te0="$td/test$N.0.stderr" tsock="$td/test$N.sock" if [ -z "$fileopt" ]; then CMD0="$TRACE $SOCAT $opts $diropt $ADDR:$tsock,fork,$addropts $ADDR2" else CMD0="$TRACE $SOCAT $opts $diropt $ADDR,fork,$fileopt=$tsock,$addropts $ADDR2" fi printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"$te0" & pid0=$! wait${proto} "$crit" $tsock 1 2>"$tlog" kill $pid0 2>>"$tlog" rc1=$? wait if [ $rc1 != 0 ]; then $PRINTF "${YELLOW}setup failed${NORMAL}\n" echo "$CMD0 &" cat "$te0" cat "$tlog" numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! [ $crit $tsock ]; then $PRINTF "$OK\n" let numOK=numOK+1 else $PRINTF "$FAILED\n" echo "$CMD0 &" cat "$te0" cat "$tlog" let numFAIL=numFAIL+1 listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # done <<<" # address fileopt addropts waitfor direction crit ADDR2 unix-listen . . unixport . -e FILE:/dev/null unix-recvfrom . . unixport . -e FILE:/dev/null " # bug fix: SYSTEM address child process shut down parents sockets including # SSL connection under some circumstances. NAME=SYSTEM_SHUTDOWN case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%system%*|*%openssl%*|*%socket%*|*%$NAME%*) TEST="$NAME: SYSTEM address does not shutdown its parents addresses" # start an OpenSSL echo server using SYSTEM:cat # start an OpenSSL client that sends data # when the client recieves its data and terminates without error the test succeeded # in case of the bug the client issues an error like: # SSL_connect(): error:1408F119:SSL routines:SSL3_GET_RECORD:decryption failed or bad record mac if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD0="$SOCAT $opts OPENSSL-LISTEN:$PORT,$REUSEADDR,cert=testsrv.pem,verify=0 SYSTEM:cat" CMD1="$SOCAT $opts - OPENSSL-CONNECT:$LOCALHOST:$PORT,verify=0" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" & pid0=$! waittcp4port $PORT 1 echo "$da" |$CMD1 >"${tf}1" 2>"${te}1" rc1=$? kill $pid0 2>/dev/null; wait if [ $rc1 -ne 0 ]; then $PRINTF "$FAILED\n" echo "rc1=$rc1" echo "$CMD0 &" echo "$CMD1" cat "${te}0" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "${tf}1" >"$tdiff" 2>&1; then $PRINTF "$FAILED\n" echo "diff:" cat "$tdiff" echo "$CMD0 &" echo "$CMD1" cat "${te}0" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" numOK=$((numOK+1)) fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # test if TCP4-LISTEN with empty port arg terminates with error NAME=TCP4_NOPORT case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%socket%*|*%tcp%*|*%tcp4%*|*%$NAME%*) TEST="$NAME: test if TCP4-LISTEN with empty port arg bails out" # run socat with TCP4-LISTEN with empty port arg. Check if it terminates # immediately with return code 1 if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" t0rc="$td/test$N.rc" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD0="$SOCAT $opts TCP4-LISTEN: /dev/null" printf "test $F_n $TEST... " $N { $CMD0 >/dev/null 2>"${te}0"; echo $? >"$t0rc"; } & 2>/dev/null pid0=$! sleep 1 kill $pid0 2>/dev/null; wait if [ ! -f "$t0rc" ]; then $PRINTF "$FAILED\n" echo "no return code of CMD0 stored" >&2 echo "$CMD0 &" cat "${te}0" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo 1 |diff - "$t0rc" >"$tdiff"; then $PRINTF "$FAILED\n" echo "CMD0 exited with $(cat $t0rc), expected 1" echo "$CMD0 &" cat "${te}0" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" numOK=$((numOK+1)) fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # tests of various SSL methods; from TLS1.3 this method is not avail in OpenSSL: OPENSSL_METHODS_OBSOLETE="SSL3 SSL23" OPENSSL_METHODS_EXPECTED="TLS1 TLS1.1 TLS1.2 DTLS1 DTLS1.2" # the OPENSSL_METHOD_DTLS1 test hangs sometimes, probably depending on the openssl version. OPENSSL_VERSION="$(openssl version)" OPENSSL_VERSION="${OPENSSL_VERSION#* }" OPENSSL_VERSION="${OPENSSL_VERSION%%-*}" OPENSSL_VERSION_GOOD=1.0.2 # this is just a guess. # known bad: 1.0.1e # known good: 1.0.2j # test if the obsolete SSL methods can be used with OpenSSL for method in $OPENSSL_METHODS_OBSOLETE; do NAME=OPENSSL_METHOD_$method case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%socket%*|*%openssl%*|*%$NAME%*) TEST="$NAME: test OpenSSL method $method" # Start a socat process with obsoelete OpenSSL method, it should fail if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! socat -hhh |grep -q "^[[:space:]]*openssl-method[[:space:]]"; then $PRINTF "test $F_n $TEST... ${YELLOW}Option openssl-method not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD0="$SOCAT $opts OPENSSL-LISTEN:$PORT,$REUSEADDR,openssl-method=$method,cert=testsrv.pem,verify=0 PIPE" CMD1="$SOCAT $opts - OPENSSL-CONNECT:$LOCALHOST:$PORT,opensslmethod=$method,verify=0" printf "test $F_n $TEST... " $N if [ "$method" = DTLS1 -a "$(echo -e "$OPENSSL_VERSION\n1.0.2" |sort |tail -n 1)" = "$OPENSSL_VERSION_GOOD" ]; then $PRINTF "${YELLOW}might hang, skipping${NORMAL}\n" numCANT=$((numCANT+1)) listCANT="$listCANT $N" else $CMD0 >/dev/null 2>"${te}0" & pid0=$! waittcp4port $PORT 1 1 2>/dev/null; w0=$? # result of waiting for process 0 if [ $w0 -eq 0 ]; then echo "$da" |$CMD1 >"${tf}1" 2>"${te}1" rc1=$? kill $pid0 2>/dev/null; wait fi echo "$da" |diff - "${tf}1" >"$tdiff" 2>/dev/null if [ $w0 -eq 0 ] && [ -f "${tf}1" ] && ! [ -s "$tdiff" ]; then $PRINTF "${YELLOW}WARN${NORMAL} (obsolete method succeeds)\n" numOK=$((numOK+1)) else $PRINTF "$OK (obsolete method fails)\n" cat "$tdiff" numOK=$((numOK+1)) fi if [ "$VERBOSE" ]; then echo " $CMD0" echo " echo \"$da\" |$CMD1" fi fi # !DTLS1 hang fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) done # test if the various SSL methods can be used with OpenSSL for method in $OPENSSL_METHODS_EXPECTED; do NAME=OPENSSL_METHOD_$method METHFAM=$(tolower "${method%%[0-9]*}") case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%socket%*|*%openssl%*|*%$METHFAM%*|*%$NAME%*) TEST="$NAME: test OpenSSL method $method" # Start a socat process listening with OpenSSL and echoing data, # using the selected method # Start a second socat process connecting to the listener using # the same method, send some data and catch the reply. # If the reply is identical to the sent data the test succeeded. if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! socat -hhh |grep -q "^[[:space:]]*openssl-method[[:space:]]"; then $PRINTF "test $F_n $TEST... ${YELLOW}Option openssl-method not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD0="$SOCAT $opts OPENSSL-LISTEN:$PORT,$REUSEADDR,openssl-method=$method,cert=testsrv.pem,verify=0 PIPE" CMD1="$SOCAT $opts - OPENSSL-CONNECT:$LOCALHOST:$PORT,openssl-method=$method,verify=0" printf "test $F_n $TEST... " $N if [ "$method" = DTLS1 -a "$(echo -e "$OPENSSL_VERSION\n1.0.2" |sort |tail -n 1)" = "$OPENSSL_VERSION_GOOD" ]; then $PRINTF "${YELLOW}might hang, skipping${NORMAL}\n" numCANT=$((numCANT+1)) listCANT="$listCANT $N" else $CMD0 >/dev/null 2>"${te}0" & pid0=$! if [[ "$method" =~ DTLS* ]]; then waitudp4port $PORT 1 else waittcp4port $PORT 1 fi echo "$da" |$CMD1 >"${tf}1" 2>"${te}1" rc1=$? kill $pid0 2>/dev/null; wait if echo "$da" |diff - "${tf}1" >"$tdiff"; then $PRINTF "$OK\n" numOK=$((numOK+1)) if [ "$VERBOSE" ]; then echo " $CMD0" echo " echo \"$da\" |$CMD1" fi else $PRINTF "$FAILED\n" echo "$CMD0 &" cat "${te}0" echo "$CMD1" cat "${te}1" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" #esac fi fi # !DTLS1 hang fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) done # test security of option openssl-set-min-proto-version OPENSSL_LATEST_PROTO_VERSION=$(openssl s_server --help 2>&1 |grep -e -ssl[1-9] -e -tls[1-9] |awk '{print($1);}' |cut -c 2- |tr '[a-z_]' '[A-Z.]' |sort |tail -n 1) OPENSSL_BEFORELAST_PROTO_VERSION=$(openssl s_server --help 2>&1 |grep -e -ssl[1-9] -e -tls[1-9] |awk '{print($1);}' |cut -c 2- |tr '[a-z_]' '[A-Z.]' |sort |tail -n 2 |head -n 1) NAME=OPENSSL_MIN_VERSION case "$TESTS" in *%$N%*|*%functions%*|*%security%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%openssl%*|*%$NAME%*) TEST="$NAME: security of OpenSSL server with openssl-min-proto-version" if ! eval $NUMCOND; then :; elif ! testaddrs openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! feat=$(testoptions openssl-min-proto-version); then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! [ "$OPENSSL_LATEST_PROTO_VERSION" -a "$OPENSSL_BEFORELAST_PROTO_VERSION" -a \ "$OPENSSL_LATEST_PROTO_VERSION" != "$OPENSSL_BEFORELAST_PROTO_VERSION" ]; then $PRINTF "test $F_n $TEST... ${YELLOW}cannot determine two available SSL/TLS versions${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv testserversec "$N" "$TEST" "$opts -4" "SSL-L:$PORT,pf=ip4,reuseaddr,$SOCAT_EGD,verify=0,cert=testsrv.crt,key=testsrv.key" "" "openssl-min-proto-version=$OPENSSL_LATEST_PROTO_VERSION" "SSL:$LOCALHOST:$PORT,cafile=testsrv.crt,$SOCAT_EGD,openssl-max-proto-version=$OPENSSL_BEFORELAST_PROTO_VERSION" 4 tcp $PORT -1 fi ;; # NUMCOND, $fets esac PORT=$((PORT+1)) N=$((N+1)) # Address options fdin and fdout were silently ignored when not applicable # due to -u or -U option. Now these combinations are caught as errors. NAME=FDOUT_ERROR case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%socket%*|*%$NAME%*) TEST="$NAME: fdout bails out in write-only context" # use EXEC in write-only context with option fdout. Expected behaviour: error 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" CMD="$SOCAT $opts -u /dev/null EXEC:cat,fdout=1" printf "test $F_n $TEST... " $N $CMD >/dev/null 2>"${te}" rc=$? if [ $rc -eq 1 ]; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD" cat "${te}" echo "command did not terminate with error!" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # test if failure exit code of SYSTEM invocation causes socat to also exit # with !=0 NAME=SYSTEM_RC case "$TESTS" in *%$N%*|*%functions%*|*%system%*|*%$NAME%*) TEST="$NAME: promote failure of SYSTEM" # run socat with SYSTEM:false and check if socat exits with !=0 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" # shut-none makes sure that the child is not killed by parent CMD0="$TRACE $SOCAT $opts - SYSTEM:false,shut-none" printf "test $F_n $TEST... " $N sleep 1 |$CMD0 >/dev/null 2>"${te}0" rc0=$? if [ $rc0 -eq 0 ]; then $PRINTF "$FAILED\n" echo "$CMD0" cat "${te}0" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" numOK=$((numOK+1)) fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # test if failure exit code of EXEC invocation causes socat to also exit # with !=0 NAME=EXEC_RC case "$TESTS" in *%$N%*|*%functions%*|*%exec%*|*%$NAME%*) TEST="$NAME: promote failure of EXEC" # run socat with EXEC:false and check if socat exits with !=0 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" # shut-none makes sure that the child is not killed by parent CMD0="$TRACE $SOCAT $opts - EXEC:false,shut-none" printf "test $F_n $TEST... " $N sleep 1 |$CMD0 >/dev/null 2>"${te}0" rc0=$? if [ $rc0 -eq 0 ]; then $PRINTF "$FAILED\n" echo "$CMD0" cat "${te}0" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" numOK=$((numOK+1)) fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # test the so-reuseaddr option NAME=SO_REUSEADDR case "$TESTS" in *%$N%*|*%functions%*|*%ip4%*|*%tcp%*|*%socket%*|*%$NAME%*) TEST="$NAME: test the so-reuseaddr option" # process 0 provides a tcp listening socket with so-reuseaddr; # process 1 connects to this port; thus the port is connected but no longer # listening # process 2 tries to listen on this port with SO_REUSEADDR, will fail if the # SO_REUSEADDR socket options did not work # process 3 connects to this port; only if it is successful the test is ok if ! eval $NUMCOND; then :; elif ! feat=$(testoptions so-reuseaddr); then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tp="$PORT" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts TCP4-L:$tp,$REUSEADDR PIPE" CMD1="$TRACE $SOCAT $opts - TCP:localhost:$tp" CMD2="$CMD0" CMD3="$CMD1" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" & pid0=$! waittcp4port $tp 1 (echo "$da"; sleep 3) |$CMD1 >"$tf" 2>"${te}1" & # this should always work pid1=$! usleep 1000000 $CMD2 >/dev/null 2>"${te}2" & pid2=$! waittcp4port $tp 1 (echo "$da") |$CMD3 >"${tf}3" 2>"${te}3" rc3=$? kill $pid0 $pid1 $pid2 2>/dev/null; wait if ! echo "$da" |diff - "$tf"; then $PRINTF "${YELLOW}phase 1 failed${NORMAL}\n" echo "$CMD0 &" echo "$CMD1" numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ $rc3 -ne 0 ]; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD0 &" echo "$CMD1" echo "$CMD2 &" echo "$CMD3" cat "${te}2" "${te}3" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "${tf}3"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD0 &" echo "$CMD1" echo "$CMD2 &" echo "$CMD3" echo "$da" |diff - "${tf}3" numCANT=$((numCANT+1)) listCANT="$listCANT $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}0" "${te}1" "${te}2" "${te}3"; fi numOK=$((numOK+1)) fi fi # NUMCOND, SO_REUSEADDR ;; esac PORT=$((PORT+1)) N=$((N+1)) # test the so-reuseport option NAME=SO_REUSEPORT case "$TESTS" in *%$N%*|*%functions%*|*%ip4%*|*%tcp%*|*%socket%*|*%$NAME%*) TEST="$NAME: test the so-reuseport option" # process 0 provides a tcp listening socket with so-reuseport; # process 1 provides an equivalent tcp listening socket with so-reuseport; # process 2 connects to this port and transfers data # process 3 connects to this port and transfers data # test succeeds when both data transfers work if ! eval $NUMCOND; then :; elif ! feat=$(testoptions so-reuseport); then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tp="$PORT" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da2="test$N $(date) $RANDOM" da3="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts TCP4-L:$tp,$REUSEADDR,so-reuseport PIPE" CMD1="$CMD0" CMD2="$TRACE $SOCAT $opts - TCP:localhost:$tp" CMD3="$CMD2" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" & pid0=$! $CMD1 >/dev/null 2>"${te}1" & pid1=$! waittcp4port $tp 1 (echo "$da2") |$CMD2 >"${tf}2" 2>"${te}2" # this should always work rc2=$? (echo "$da3") |$CMD3 >"${tf}3" 2>"${te}3" rc3=$? kill $pid0 $pid1 $pid2 2>/dev/null; wait if ! echo "$da2" |diff - "${tf}2"; then $PRINTF "${YELLOW}phase 1 failed${NORMAL}\n" echo "$CMD0 &" cat "${te}0" echo "$CMD1 &" cat "${te}1" echo "$CMD2" cat "${te}2" numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ $rc3 -ne 0 ]; then $PRINTF "$FAILED:\n" echo "$CMD0 &" cat "${te}0" echo "$CMD1 &" cat "${te}1" echo "$CMD2" cat "${te}2" echo "$CMD3" cat "${te}3" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da2" |diff - "${tf}2"; then $PRINTF "$FAILED:\n" echo "$CMD0 &" cat "${te}0" echo "$CMD1 &" cat "${te}1" echo "$CMD2" cat "${te}2" echo "$CMD3" cat "${te}3" echo "$da2" |diff - "${tf}2" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da3" |diff - "${tf}3"; then $PRINTF "$FAILED:\n" echo "$CMD0 &" cat "${te}0" echo "$CMD1 &" cat "${te}1" echo "$CMD2" cat "${te}2" echo "$CMD3" cat "${te}3" echo "$da3" |diff - "${tf}3" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}0" "${te}1" "${te}2" "${te}3"; fi numOK=$((numOK+1)) fi fi # NUMCOND, SO_REUSEPORT ;; esac PORT=$((PORT+1)) N=$((N+1)) # Programs invoked with EXEC, nofork, and -u or -U had stdin and stdout assignment swapped. NAME=EXEC_NOFORK_UNIDIR case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%exec%*|*%$NAME%*) TEST="$NAME: Programs invoked with EXEC, nofork, and -u or -U had stdin and stdout assignment swapped" # invoke a simple echo command with EXEC, nofork, and -u # expected behaviour: output appears on stdout 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="$TRACE $SOCAT $opts -u /dev/null EXEC:\"echo \\\\\\\"\\\"$da\\\"\\\\\\\"\",nofork" printf "test $F_n $TEST... " $N eval "$CMD0" >"${tf}0" 2>"${te}0" rc1=$? if echo "$da" |diff - "${tf}0" >"$tdiff"; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0" cat "${te}0" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac #PORT=$((PORT+1)) N=$((N+1)) # OpenSSL ECDHE ciphers were introduced in socat 1.7.3.0 but in the same release # they were broken by a porting effort. This test checks if OpenSSL ECDHE works # 2019-02: this does no longer work (Ubuntu-18.04) NAME=OPENSSL_ECDHE case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%openssl%*|*%socket%*|*%$NAME%*) TEST="$NAME: test OpenSSL ECDHE" # generate a ECDHE key, start an OpenSSL server, connect with a client and try to # pass data if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! openssl ciphers |grep -q '\'; then $PRINTF "test $F_n $TEST... ${YELLOW}openssl: cipher ECDHE not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" #TESTSRV=./testsrvec; gentesteccert $TESTSRV TESTSRV=./testsrv; gentestcert $TESTSRV CMD0="$TRACE $SOCAT $opts OPENSSL-LISTEN:$PORT,$REUSEADDR,cert=$TESTSRV.crt,key=$TESTSRV.pem,verify=0 PIPE" CMD1="$TRACE $SOCAT $opts - OPENSSL-CONNECT:$LOCALHOST:$PORT,cipher=ECDHE-ECDSA-AES256-GCM-SHA384,cafile=$TESTSRV.crt,verify=0" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" & pid0=$! waittcp4port $PORT 1 echo "$da" |$CMD1 >"${tf}1" 2>"${te}1" rc1=$? kill $pid0 2>/dev/null; wait if [ $rc1 -ne 0 ]; then $PRINTF "$FAILED\n" echo "failure symptom: client error" >&2 echo "server and stderr:" >&2 echo "$CMD0 &" cat "${te}0" echo "client and stderr:" >&2 echo "$CMD1" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif echo "$da" |diff - "${tf}1" >"$tdiff"; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "server and stderr:" >&2 echo "$CMD1" cat "${te}1" echo "client and stderr:" >&2 echo "$CMD0 &" cat "${te}0" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # option ipv6-join-group "could not be used" # fixed in 1.7.3.2 NAME=USE_IPV6_JOIN_GROUP case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%socket%*|*%ip6%*|*%udp%*|*%udp6%*|*%dgram%*|*%$NAME%*) TEST="$NAME: is option ipv6-join-group used" # Invoke socat with option ipv6-join-group on UDP6 address. # Terminate immediately, do not transfer data. # If socat exits with 0 the test succeeds. # Up to 1.7.3.1 it failed with "1 option(s) could not be used" 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="$TRACE $SOCAT $opts UDP6-RECV:$PORT,ipv6-join-group=[ff02::2]:$MCINTERFACE /dev/null" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" rc0=$? if [ $rc0 -eq 0 ]; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0" cat "${te}0" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # The fix to "Make code async-signal-safe" used internally FD 3 and FD 4. # Using option fdin=3 did not pass data to executed program. NAME=DIAG_FDIN case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%exec%*|*%$NAME%*) TEST="$NAME: test use of fdin=3" # Use FD 3 explicitely with fdin and test if Socat passes data to executed # program 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="$TRACE $SOCAT $opts - SYSTEM:\"cat >&3 <&4\",fdin=4,fdout=3" printf "test $F_n $TEST... " $N echo "$da" |$TRACE $SOCAT $opts - SYSTEM:"cat <&3 >&4",fdin=3,fdout=4 >${tf}0 2>"${te}0" rc0=$? if [ $rc0 -ne 0 ]; then $PRINTF "$FAILED\n" echo "$CMD0" cat "${te}0" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif echo "$da" |diff - ${tf}0 >$tdiff; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0" cat "${te}0" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) NAME=SOCAT_OPT_HINT case "$TESTS" in *%$N%*|*%functions%*|*%$NAME%*) TEST="$NAME: check if merging single character options is rejected" if ! eval $NUMCOND; then :; else te="$td/test$N.stderr" CMD0="$TRACE $SOCAT $opts -vx FILE:/dev/null ECHO" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" rc0=$? if [ "$rc0" = "1" ]; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi ;; # NUMCOND esac N=$((N+1)) # test for a bug in Socat version 1.7.3.3 where # termios options of the first address were applied to the second address. NAME=TERMIOS_PH_ALL case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%pty%*|*%termios%*|*%$NAME%*) TEST="$NAME: are termios options applied to the correct address" # add a termios option to the first address, a tty, and have a second address # with pipe. If no error occurs the termios option was not applied to the pipe, # thus the test succeeded. 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="$TRACE $SOCAT $opts -T 1 STDIO,echo=0 EXEC:cat" echo "$CMD0" >$td/test$N.sh chmod a+x $td/test$N.sh printf "test $F_n $TEST... " $N # EXEC need not work with script (musl libc), so use SYSTEM $SOCAT /dev/null SYSTEM:$td/test$N.sh,pty 2>"${te}0" rc0=$? if [ $rc0 -eq 0 ]; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0" cat "${te}0" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # Due to a fallback logic before calling getaddrinfo(), intended to allow use # of service (port) names with SCTP, raw socket addresses where resolved with # socket type stream, which fails for protocol 6 (TCP) # Fixed after 1.7.3.3 NAME=IP_SENDTO_6 case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%socket%*|*%rawip%*|*%rawip4%*|*%$NAME%*) TEST="$NAME: IP-SENDTO::6 passes getaddrinfo()" # invoke socat with address IP-SENDTO:*:6; when this does not fail with # "ai_socktype not supported", the test succeeded if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" CMD0="$TRACE $SOCAT $opts -u /dev/null IP-SENDTO:127.0.0.1:6" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" if ! grep -q "ai_socktype not supported" ${te}0; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0" cat "${te}0" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac N=$((N+1)) # test if the multiple EOF messages are fixed NAME=MULTIPLE_EOF case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%unix%*|*%socket%*|*%$NAME%*) TEST="$NAME: multiple EOF messages" # start two processes, connected via UNIX socket. The listener gets EOF from local address immediately; the second process then sends data. If the listener reports "socket 1 (fd .*) is at EOF" only once, the test succeeded if ! eval $NUMCOND; then :; else 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 -d -d UNIX-LISTEN:$ts /dev/null" CMD1="$TRACE $SOCAT $opts -d -d - UNIX-CONNECT:$ts" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" & pid0=$! waitunixport $ts 1 echo "$da" |$CMD1 >"${tf}1" 2>"${te}1" rc1=$? kill $pid0 2>/dev/null; wait if [ $(grep "socket 2 (fd .*) is at EOF" ${te}0 |wc -l) -eq 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)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac N=$((N+1)) # Test for integer overflow with data transfer block size parameter NAME=BLKSIZE_INT_OVERFL case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%security%*|*%$NAME%*) TEST="$NAME: integer overflow with buffer size parameter" # Use a buffer size that would lead to integer overflow # Test succeeds when Socat terminates with correct error message if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" dat="$td/test$N.dat" # calculate the minimal length with integer overflow BYTES=$($PROCAN |grep size_t |awk '{print($3);}') case $BYTES in 2) CHKSIZE=32768 ;; 4) CHKSIZE=2147483648 ;; 8) CHKSIZE=9223372036854775808 ;; 16) CHKSIZE=170141183460469231731687303715884105728 ;; esac CMD0="$TRACE $SOCAT $opts -T 1 -b $CHKSIZE /dev/null PIPE" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" rc0=$? if [ $rc0 -eq 0 ]; then $PRINTF "$FAILED (rc=$rc0)\n" echo "$CMD0" cat "${te}0" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif [ $rc0 -eq 1 ]; then if grep -q "buffer size option (-b) to big" "${te}0"; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED (rc=$rc0)\n" echo "$CMD0" cat "${te}0" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # Test if unbalanced quoting in Socat addresses is detected NAME=UNBALANCED_QUOTE case "$TESTS" in *%$N%*|*%functions%*|*%syntax%*|*%bugs%*|*%$NAME%*) TEST="$NAME: Test fix of unbalanced quoting" # Invoke Socat with an address containing unbalanced quoting. If Socat prints # a "syntax error" message, the test succeeds 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="$TRACE $SOCAT $opts -u FILE:$td/ab\"cd FILE:/dev/null" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" if grep -q "syntax error" "${te}0"; then $PRINTF "$OK\n" if [ "$VERBOSE" ]; then echo "$CMD0" >&2; fi if [ "$debug" ]; then cat ${te} >&2; fi numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0" cat "${te}0" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac N=$((N+1)) # Currently (2020) SCTP has not found its way into main distributions # /etc/services file. A fallback mechanism has been implemented in Socat # that allows use of TCP service names when service resolution for SCTP failed. # Furthermore, older getaddrinfo() implementations to not handle SCTP as SOCK_STREAM # at all, fall back to unspecified socktype then. NAME=SCTP_SERVICENAME case "$TESTS" in *%$N%*|*%functions%*|*%socket%*|*%sctp%*|*%$NAME%*) TEST="$NAME: Service name resolution works with SCTP" # invoke socat with address SCTP4-CONNECT:$LOCALHOST:http; when this fails with # "Connection refused", or does not fail at all, the test succeeded if ! eval $NUMCOND; then :; elif ! runssctp4 "$((PORT))" >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}SCTP4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" CMD0="$TRACE $SOCAT $opts -u /dev/null SCTP4-CONNECT:$LOCALHOST:http" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" if [ $? -eq 0 ]; then $PRINTF "$OK\n" numOK=$((numOK+1)) elif grep -q "Connection refused" ${te}0; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0" cat "${te}0" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac N=$((N+1)) # Test the o-direct option on reading NAME=O_DIRECT case "$TESTS" in *%$N%*|*%functions%*|*%engine%*|*%file%*|*%$NAME%*) TEST="$NAME: echo via file with o-direct" # Write data to a file and read it with options o-direct (and ignoreeof) # When the data read is the same as the data written the test succeeded. if ! eval $NUMCOND; then :; elif ! testoptions o-direct >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}o-direct not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.file" to="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" $PRINTF "test $F_n $TEST... " $N CMD="$TRACE $SOCAT $opts - $tf,o-direct,ignoreeof!!$tf" echo "$da" |$CMD >"$to" 2>"$te" rc=$? if [ $rc -ne 0 ] && grep -q "Invalid argument" "$te" && [ $UNAME = Linux ]; then case $(stat -f $tf |grep "Type: [^[:space:]]*" |sed -e 's/.*\(Type: [^[:space:]]*\).*/\1/' |cut -c 7-) in #case $(stat -f $tf |grep -o "Type: [^[:space:]]*" |cut -c 7-) in ext2/ext3|xfs|reiserfs) $PRINTF "${FAILED}\n" echo "$CMD" >&2 cat "$te" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" ;; *) $PRINTF "${YELLOW}inable file system${NORMAL}\n" numCANT=$((numCANT+1)) listCANT="$listCANT $N" ;; esac elif [ $rc -ne 0 ]; then $PRINTF "${FAILED}:\n" echo "$CMD" >&2 cat "$te" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! echo "$da" |diff - "$to" >$tdiff; then $PRINTF "${FAILED}\n" echo "$CMD" >&2 cat "$te" >&2 cat "$tdiff" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" numOK=$((numOK+1)) fi # command ok fi ;; # NUMCOND, feats esac N=$((N+1)) # test if option unlink-close removes the bind socket file NAME=UNIX_SENDTO_UNLINK case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%socket%*|*%unix%*|*%$NAME%*) TEST="$NAME: Option unlink-close with UNIX sendto socket" # Have a recv socket with option unlink-close=0 # and a sendto socket with option unlink-close=1 # Expected beavior: the recv socket is kept, the # sendto/bind socket is removed if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" uns="$td/test$N.server" unc="$td/test$N.client" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts -u UNIX-RECV:$uns,unlink-close=0 GOPEN:$tf" CMD1="$TRACE $SOCAT $opts - UNIX-SENDTO:$uns,bind=$unc,unlink-close=1" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" & pid0=$! waitunixport $uns 1 echo "$da" |$CMD1 >"${tf}1" 2>"${te}1" rc1=$? kill $pid0 2>/dev/null; wait if test -S $uns && ! test -S $unc; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0 &" echo "$CMD1" ls -ld $uns $unc cat "${te}0" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac N=$((N+1)) # test if option unlink-close removes the bind socket file NAME=UNIX_CONNECT_UNLINK case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%socket%*|*%unix%*|*%$NAME%*) TEST="$NAME: Option unlink-close with UNIX connect socket" # Have a listen socket with option unlink-close=0 # and a connect socket with option unlink-close=1 # Expected beavior: the listen socket entry is kept, the # connect/bind socket is removed if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" uns="$td/test$N.server" unc="$td/test$N.client" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts -u UNIX-LISTEN:$uns,unlink-close=0 GOPEN:$tf" CMD1="$TRACE $SOCAT $opts - UNIX-CONNECT:$uns,bind=$unc,unlink-close=1" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" & pid0=$! waitunixport $uns 1 echo "$da" |$CMD1 >"${tf}1" 2>"${te}1" rc1=$? kill $pid0 2>/dev/null; wait if test -S $uns && ! test -S $unc; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0 &" echo "$CMD1" ls -ld $uns $unc cat "${te}0" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac N=$((N+1)) # test the DTLS client feature NAME=OPENSSL_DTLS_CLIENT case "$TESTS" in *%$N%*|*%functions%*|*%openssl%*|*%dtls%*|*%udp%*|*%udp4%*|*%ip4%*|*%$NAME%*) TEST="$NAME: OpenSSL DTLS client" # Run openssl s_server in DTLS mode, wrapped into a simple Socat echoing command. # Start a Socat DTLS client, send data to server and check if reply is received. if ! eval $NUMCOND; then :; elif ! a=$(testfeats ip4 udp openssl); then $PRINTF "test $F_n $TEST... ${YELLOW}$a not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! a=$(testaddrs openssl-dtls-client); then $PRINTF "test $F_n $TEST... ${YELLOW}$a not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}IPv4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! type openssl >/dev/null 2>&1; then $PRINTF "test $F_n $TEST... ${YELLOW}openssl executable not found${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" #set -vx da="test$N $(date) $RANDOM" init_openssl_s_server CMD1="$TRACE openssl s_server $OPENSSL_S_SERVER_4 $OPENSSL_S_SERVER_DTLS -accept $PORT -quiet $OPENSSL_S_SERVER_NO_IGN_EOF -cert testsrv.pem" CMD="$TRACE $SOCAT $opts -T 3 - OPENSSL-DTLS-CLIENT:$LOCALHOST:$PORT,pf=ip4,verify=0,$SOCAT_EGD" printf "test $F_n $TEST... " $N ( sleep 2; echo "$da"; sleep 1 ) |$CMD1 2>"${te}1" & pid1=$! # background process id waitudp4port $PORT $CMD >$tf 2>"$te" kill $pid1 2>/dev/null; wait 2>/dev/null if ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD1 &" cat "${te}1" echo "$CMD" cat "$te" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "$te"; fi numOK=$((numOK+1)) fi fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) set +vx # test the DTLS server feature NAME=OPENSSL_DTLS_SERVER case "$TESTS" in *%$N%*|*%functions%*|*%openssl%*|*%dtls%*|*%udp%*|*%udp4%*|*%ip4%*|*%socket%*|*%$NAME%*) TEST="$NAME: OpenSSL DTLS server" # Run a socat OpenSSL DTLS server with echo function # Start an OpenSSL s_client, send data and check if repley is received. if ! eval $NUMCOND; then :; elif ! a=$(testfeats ip4 udp openssl) >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}$a not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! a=$(testaddrs openssl-dtls-server); then $PRINTF "test $F_n $TEST... ${YELLOW}$a not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}IPv4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! type openssl >/dev/null 2>&1; then $PRINTF "test $F_n $TEST... ${YELLOW}openssl executable not found${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [[ $(openssl version |awk '{print($2);}') =~ 0.9.8[a-c] ]]; then $PRINTF "test $F_n $TEST... ${YELLOW}openssl s_client might hang${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" init_openssl_s_client CMD1="$TRACE $SOCAT $opts OPENSSL-DTLS-SERVER:$PORT,$REUSEADDR,cert=testsrv.crt,key=testsrv.key,verify=0 PIPE" CMD="openssl s_client $OPENSSL_S_CLIENT_4 -host $LOCALHOST -port $PORT $OPENSSL_S_CLIENT_DTLS" printf "test $F_n $TEST... " $N $CMD1 >/dev/null 2>"${te}1" & pid1=$! waitudp4port $PORT 1 ( echo "$da"; psleep 0.1 ) |$CMD 2>"$te" |grep "$da" >"$tf" rc=$? kill $pid1 2>/dev/null; wait if echo "$da" |diff - $tf >"$tdiff"; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD1 &" cat "${te}1" echo "$CMD" cat "$te" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) NAME=OPENSSL_SERVERALTAUTH case "$TESTS" in *%$N%*|*%functions%*|*%openssl%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*) TEST="$NAME: OpenSSL server authentication with SubjectAltName (hostname)" if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats listen tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP/IPv4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestaltcert testalt tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts OPENSSL-LISTEN:$PORT,$REUSEADDR,$SOCAT_EGD,cert=testalt.crt,key=testalt.key,verify=0 pipe" CMD1="$TRACE $SOCAT $opts - OPENSSL:$LOCALHOST:$PORT,verify=1,cafile=testalt.crt,$SOCAT_EGD" printf "test $F_n $TEST... " $N eval "$CMD0 2>\"${te}0\" &" pid=$! # background process id waittcp4port $PORT echo "$da" |$CMD1 >$tf 2>"${te}1" if ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD0 &" >&2 cat "${te}0" >&2 echo "$CMD1" >&2 cat "${te}1" >&2 cat "$tdiff" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null wait fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=OPENSSL_SERVERALTIP4AUTH case "$TESTS" in *%$N%*|*%functions%*|*%openssl%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*) TEST="$NAME: OpenSSL server authentication with SubjectAltName (IPv4 address)" if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats listen tcp ip4 openssl >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP/IPv4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestaltcert testalt tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts OPENSSL-LISTEN:$PORT,$REUSEADDR,$SOCAT_EGD,cert=testalt.crt,key=testalt.key,verify=0 pipe" CMD1="$TRACE $SOCAT $opts - OPENSSL:127.0.0.1:$PORT,verify=1,cafile=testalt.crt,$SOCAT_EGD" printf "test $F_n $TEST... " $N eval "$CMD0 2>\"${te}0\" &" pid=$! # background process id waittcp4port $PORT echo "$da" |$CMD1 >$tf 2>"${te}1" if ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD0 &" >&2 cat "${te}0" >&2 echo "$CMD1" >&2 cat "${te}1" >&2 cat "$tdiff" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null wait fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) NAME=OPENSSL_SERVERALTIP6AUTH case "$TESTS" in *%$N%*|*%functions%*|*%openssl%*|*%tcp%*|*%tcp6%*|*%ip6%*|*%$NAME%*) TEST="$NAME: OpenSSL server authentication with SubjectAltName (IPv6 address)" if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats listen tcp ip6 openssl >/dev/null || ! runsip6 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP/IPv6 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestaltcert testalt tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts OPENSSL-LISTEN:$PORT,pf=ip6,$REUSEADDR,$SOCAT_EGD,cert=testalt.crt,key=testalt.key,verify=0 pipe" CMD1="$TRACE $SOCAT $opts - OPENSSL:[::1]:$PORT,verify=1,cafile=testalt.crt,$SOCAT_EGD" printf "test $F_n $TEST... " $N eval "$CMD0 2>\"${te}0\" &" pid=$! # background process id waittcp6port $PORT echo "$da" |$CMD1 >$tf 2>"${te}1" if ! echo "$da" |diff - "$tf" >"$tdiff"; then $PRINTF "$FAILED: $TRACE $SOCAT:\n" echo "$CMD0 &" >&2 cat "${te}0" >&2 echo "$CMD1" >&2 cat "${te}1" >&2 cat "$tdiff" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null wait fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) # Test the -r and -R options NAME=OPTION_RAW_DUMP case "$TESTS" in *%$N%*|*%functions%*|*%option%*|*%$NAME%*) TEST="$NAME: raw dump of transferred data" # Start Socat transferring data from left named pipe to right and from right # pipe to left, use options -r and -R, and check if dump files contain correct # data if ! eval $NUMCOND; then :; elif [ $($SOCAT -h |grep -e ' -[rR] ' |wc -l) -lt 2 ]; then $PRINTF "test $F_n $TEST... ${YELLOW}Options -r, -R not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tp1="$td/test$N.pipe1" tp2="$td/test$N.pipe2" tr1="$td/test$N.raw1" tr2="$td/test$N.raw2" tdiff1="$td/test$N.diff1" tdiff2="$td/test$N.diff2" da1="test$N $(date) $RANDOM" da2="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts -r $tr1 -R $tr2 PIPE:$tp1!!/dev/null PIPE:$tp2!!/dev/null" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" & pid0=$! waitfile $tp1 1 echo "$da1" >$tp1 waitfile $tp2 1 echo "$da2" >$tp2 sleep 1 kill $pid0 2>/dev/null; wait if ! echo "$da1" |diff - $tr1 >$tdiff1 || ! echo "$da2" |diff - $tr2 >$tdiff2; then $PRINTF "$FAILED\n" echo "$CMD0 &" >&2 cat "${te}0" >&2 echo "Left-to-right:" >&2 cat $tdiff1 >&2 echo "Right-to-left:" >&2 cat $tdiff2 >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" numOK=$((numOK+1)) fi fi # NUMCOND ;; esac N=$((N+1)) # Test the OpenSSL SNI feature NAME=OPENSSL_SNI case "$TESTS" in *%$N%*|*%functions%*|*%socket%*|*%openssl%*|*%$NAME%*) TEST="$NAME: Test the OpenSSL SNI feature" # Connect to a server that is known to use SNI. Use an SNI name, not the # certifications default name. When the TLS connection is established # the test succeeded. SNISERVER=badssl.com if ! eval $NUMCOND; then :; elif ! testaddrs openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! feat=$(testoptions openssl-snihost); then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ -z "$FOREIGN" ]; then $PRINTF "test $F_n $TEST... ${YELLOW}use test.sh option -foreign${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts FILE:/dev/null OPENSSL-CONNECT:$SNISERVER:443" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" rc0=$? if [ $rc0 -eq 0 ]; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0" >&2 cat "${te}0" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac N=$((N+1)) # Test the openssl-no-sni option NAME=OPENSSL_NO_SNI case "$TESTS" in *%$N%*|*%functions%*|*%socket%*|*%openssl%*|*%$NAME%*) TEST="$NAME: Test the openssl-no-sni option" # Connect to a server that is known to use SNI. Use an SNI name, not the # certifications default name, and use option openssl-no-sni. # When the TLS connection failed the test succeeded. # Please note that this test is only relevant when test OPENSSL_SNI succeeded. SNISERVER=badssl.com if ! eval $NUMCOND; then :; elif ! testaddrs openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! feat=$(testoptions openssl-no-sni); then $PRINTF "test $F_n $TEST... ${YELLOW}$feat not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ -z "$FOREIGN" ]; then $PRINTF "test $F_n $TEST... ${YELLOW}use test.sh option -foreign${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts FILE:/dev/null OPENSSL-CONNECT:$SNISERVER:443,openssl-no-sni" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" rc0=$? if [ $rc0 -ne 0 ]; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0" >&2 cat "${te}0" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac N=$((N+1)) # Test the accept-timeout (listen-timeout) address option NAME=ACCEPTTIMEOUT case "$TESTS" in *%$N%*|*%functions%*|*%ip4%*|*%ipapp%*|*%tcp%*|*%listen%*|*%timeout%*|*%$NAME%*) TEST="$NAME: test the accept-timeout option" if ! eval $NUMCOND; then :; elif ! feat=$(testaddrs tcp); then $PRINTF "test $F_n $TEST... ${YELLOW}$(echo "$feat"| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! feat=$(testoptions accept-timeout); then $PRINTF "test $F_n $TEST... ${YELLOW}$(echo "$feat"| tr 'a-z' 'A-Z') not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else # Just start a process with accept-timeout 1s and check if it still runs 2s later # but before this, we test if the process waits at all te1="$td/test$N.stderr1" tk1="$td/test$N.kill1" te2="$td/test$N.stderr2" tk2="$td/test$N.kill2" $PRINTF "test $F_n $TEST... " $N # First, try to make socat hang and see if it can be killed CMD1="$TRACE $SOCAT $opts TCP-LISTEN:$PORT,reuseaddr PIPE" $CMD1 >"$te1" 2>&1 "$tk1"; then $PRINTF "${YELLOW}does not hang${NORMAL}\n" echo $CMD1 >&2 cat "$te1" >&2 cat "$tk1" >&2 numCANT=$((numCANT+1)) listCANT="$listCANT $N" else # Second, set accept-timeout and see if socat exits before kill CMD2="$TRACE $SOCAT $opts TCP-LISTEN:$PORT,reuseaddr,accept-timeout=1 PIPE" >"$te1" & $CMD2 >"$te1" 2>&1 "$tk2"; then $PRINTF "$FAILED\n" echo "$CMD2" >&2 cat "$te2" >&2 cat "$tk2" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" numOK=$((numOK+1)) fi fi wait fi ;; # testaddrs, NUMCOND esac N=$((N+1)) # Test the modified UDP-DATAGRAM address: Now it ignores peerport by default NAME=UDP_DATAGRAM_PEERPORT case "$TESTS" in *%$N%*|*%functions%*|*%udp%*|*%socket%*|*%$NAME%*) TEST="$NAME: test UDP-DATAGRAM ignoring peerport" # A UDP-DATAGRAM address bound to PORT has defined peer on PORT+1 # From another Socat instance we send a packet to PORT but with source port # PORT+2. The first instance should accept the packet if ! eval $NUMCOND; then : elif [ $(echo $E "$SOCAT_VERSION\n1.7.3.4" |sort -n |tail -n 1) = 1.7.3.4 ]; then $PRINTF "test $F_n $TEST... ${YELLOW}Only with Socat 1.7.4.0 or higher${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts -u UDP-DATAGRAM:$LOCALHOST:$((PORT+1)),bind=:$((PORT)) -" CMD1="$TRACE $SOCAT $opts -u - UDP-DATAGRAM:$LOCALHOST:$((PORT)),bind=:$((PORT+2))" printf "test $F_n $TEST... " $N $CMD0 >${tf}0 2>"${te}0" & pid0=$! waitudp4port $PORT 1 echo "$da" |$CMD1 >"${tf}1" 2>"${te}1" rc1=$? psleep 0.1 kill $pid0 2>/dev/null; wait if [ -f ${tf}0 ] && echo "$da" |diff - ${tf}0 >$tdiff; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0 &" >&2 cat "${te}0" >&2 echo "$CMD1" >&2 cat "${te}1" >&2 cat "${tdiff}" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # Test the proxy-authorization-file option NAME=PROXYAUTHFILE case "$TESTS" in *%$N%*|*%functions%*|*%proxyconnect%*|*%proxy%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*) TEST="$NAME: proxy-authorization-file option" if ! eval $NUMCOND; then :; elif ! testfeats proxy >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}PROXY not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats listen tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP/IPv4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testoptions proxy-authorization-file >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}Option proxy-authorization-file not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else ta="$td/test$N.auth" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM"; da="$da$($ECHO '\r')" CMD0="{ echo -e \"HTTP/1.0 200 OK\\n\"; sleep 2; } |$TRACE $SOCAT $opts - TCP4-L:$PORT,$REUSEADDR,crlf" CMD1="$TRACE $SOCAT $opts FILE:/dev/null PROXY-CONNECT:$LOCALHOST:127.0.0.1:1000,pf=ip4,proxyport=$PORT,proxy-authorization-file=$ta" printf "test $F_n $TEST... " $N echo "user:s3cr3t" >$ta eval "$CMD0 >${tf}0 2>${te}0 &" pid0=$! # background process id waittcp4port $PORT 1 $CMD1 >"${tf}1" 2>"${te}1" rc1=$? kill $pid0 2>/dev/null wait $pid0 if [ $rc1 -ne 0 ]; then $PRINTF "$FAILED\n" echo "$CMD0 &" >&2 cat "${te}0" >&2 echo "$CMD1" >&2 cat "${te}1" >&2 cat "${tf}0" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif ! grep -q '^Proxy-authorization: Basic dXNlcjpzM2NyM3QK$' ${tf}0; then $PRINTF "$FAILED:\n" echo "$CMD0 &" >&2 cat "${te}0" >&2 echo "$CMD1" >&2 cat "${te}1" >&2 cat "${tf}0" >&2 echo "Authorization string not in client request" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ -n "$debug" ]; then cat "${te}1" "${te}2"; fi numOK=$((numOK+1)) fi kill $pid 2>/dev/null wait fi ;; # NUMCOND, feats esac PORT=$((PORT+1)) N=$((N+1)) # Test communication via vsock loopback socket NAME=VSOCK_ECHO case "$TESTS" in *%$N%*|*%functions%*|*%vsock%*|*%socket%*|*%$NAME%*) TEST="$NAME: test communication via VSOCK loopback socket" # Start a listening echo server # Connect with a client, send data and compare reply with original data if ! eval $NUMCOND; then :; elif ! fea=$(testfeats VSOCK); then $PRINTF "test $F_n $TEST... ${YELLOW}$fea not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts VSOCK-LISTEN:$PORT PIPE" CMD1="$TRACE $SOCAT $opts - VSOCK-CONNECT:1:$PORT" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" & pid0=$! sleep 1 echo "$da" |$CMD1 >"${tf}1" 2>"${te}1" rc1=$? kill $pid0 2>/dev/null; wait if [ $rc1 -ne 0 ] && [ "$UNAME" != Linux ]; then $PRINTF "${YELLOW}works only on Linux?${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ $rc1 -ne 0 ] && [ "$UNAME" = Linux ] && ! [[ $UNAME_R =~ ^[6-9]\.* ]] && ! [[ $UNAME_R =~ ^5\.[6-]\.* ]] && ! [[ $UNAME_R =~ ^5\.[1-9][0-9].* ]]; then $PRINTF "${YELLOW}works only on Linux from 5.6${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ $rc1 -ne 0 ]; then $PRINTF "$FAILED\n" echo "$CMD0 &" >&2 cat "${te}0" >&2 echo "$CMD1" >&2 cat "${te}1" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif echo "$da" |diff - ${tf}1 >${tfdiff}$N; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0 &" >&2 cat "${te}0" >&2 echo "$CMD1" >&2 cat "${te}1" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # File transfer with OpenSSL stream connection was incomplete # Test file transfer from client to server NAME=OPENSSL_STREAM_TO_SERVER case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%openssl%*|*%tcp%*|*%socket%*|*%$NAME%*) TEST="$NAME: OpenSSL stream from client to server" # Start a unidirectional OpenSSL server and stream receiver # Start a unidirectional OpenSSL client that connects to the server and sends # data # Test succeeded when the data received and stored by server is the same as # sent by the client if ! eval $NUMCOND; then :; elif ! a=$(testfeats ip4 tcp openssl); then $PRINTF "test $F_n $TEST... ${YELLOW}$a not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! a=$(testaddrs openssl-listen openssl-connect); then $PRINTF "test $F_n $TEST... ${YELLOW}$a not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}IPv4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv ti="$td/test$N.datain" to="$td/test$N.dataout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts -u OPENSSL-LISTEN:$PORT,$REUSEADDR,cert=testsrv.pem,verify=0 CREAT:$to" CMD1="$TRACE $SOCAT $opts -u OPEN:$ti OPENSSL-CONNECT:$LOCALHOST:$PORT,cafile=testsrv.crt" printf "test $F_n $TEST... " $N i=0; while [ $i -lt 100000 ]; do printf "%9u %9u %9u %9u %9u %9u %9u %9u %9u %9u\n" $i $i $i $i $i $i $i $i $i $i; let i+=100; done >$ti $CMD0 >/dev/null 2>"${te}0" & pid0=$! waittcp4port $PORT 1 $CMD1 >"${tf}1" 2>"${te}1" rc1=$? usleep $MICROS kill $pid0 2>/dev/null; wait if [ $rc1 -ne 0 ]; then $PRINTF "$FAILED\n" echo "$CMD0 &" >&2 cat "${te}0" >&2 echo "$CMD1" >&2 cat "${te}1" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif diff $ti $to >$tdiff; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0 &" >&2 cat "${te}0" >&2 echo "$CMD1" >&2 cat "${te}1" >&2 echo "diff:" >&2 head -n 2 $tdiff >&2 echo ... >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # File transfer with OpenSSL stream connection was incomplete # Test file transfer from server to client NAME=OPENSSL_STREAM_TO_CLIENT case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%openssl%*|*%tcp%*|*%socket%*|*%$NAME%*) TEST="$NAME: OpenSSL stream from server to client" # Start a unidirectional OpenSSL server and stream sender # Start a unidirectional OpenSSL client that connects to the server and receives # data # Test succeeded when the data received and stored by client is the same as # sent by the server if ! eval $NUMCOND; then :; elif ! a=$(testfeats ip4 tcp openssl); then $PRINTF "test $F_n $TEST... ${YELLOW}$a not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! a=$(testaddrs openssl-listen openssl-connect); then $PRINTF "test $F_n $TEST... ${YELLOW}$a not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}IPv4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv ti="$td/test$N.datain" to="$td/test$N.dataout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts -U OPENSSL-LISTEN:$PORT,$REUSEADDR,cert=testsrv.pem,verify=0 OPEN:$ti" CMD1="$TRACE $SOCAT $opts -u OPENSSL-CONNECT:$LOCALHOST:$PORT,cafile=testsrv.crt CREAT:$to" printf "test $F_n $TEST... " $N i=0; while [ $i -lt 100000 ]; do printf "%9u %9u %9u %9u %9u %9u %9u %9u %9u %9u\n" $i $i $i $i $i $i $i $i $i $i; let i+=100; done >$ti $CMD0 >/dev/null 2>"${te}0" & pid0=$! waittcp4port $PORT 1 $CMD1 >"${tf}1" 2>"${te}1" rc1=$? usleep $MICROS kill $pid0 2>/dev/null; wait if [ $rc1 -ne 0 ]; then $PRINTF "$FAILED\n" echo "$CMD0 &" >&2 cat "${te}0" >&2 echo "$CMD1" >&2 cat "${te}1" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif diff $ti $to >$tdiff; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0 &" >&2 cat "${te}0" >&2 echo "$CMD1" >&2 cat "${te}1" >&2 echo "diff:" >&2 head -n 2 $tdiff >&2 echo ... >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # Test file transfer from client to server using DTLS NAME=OPENSSL_DTLS_TO_SERVER case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%openssl%*|*%dtls%*|*%udp%*|*%socket%*|*%$NAME%*) TEST="$NAME: OpenSSL DTLS transfer from client to server" # Start a unidirectional OpenSSL DTLS server/receiver # Start a unidirectional OpenSSL DTLS client that connects to the server and # sends data # Test succeeded when the data received and stored by server is the same as # sent by the client if ! eval $NUMCOND; then :; elif ! a=$(testfeats ip4 udp openssl); then $PRINTF "test $F_n $TEST... ${YELLOW}$a not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! a=$(testaddrs openssl-dtls-listen openssl-dtls-connect); then $PRINTF "test $F_n $TEST... ${YELLOW}$a not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}IPv4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [[ $(openssl version |awk '{print($2);}') =~ 0.9.8[a-c] ]]; then $PRINTF "test $F_n $TEST... ${YELLOW}openssl s_client might hang${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv ti="$td/test$N.datain" to="$td/test$N.dataout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts -u OPENSSL-DTLS-LISTEN:$PORT,cert=testsrv.pem,verify=0 CREAT:$to" CMD1="$TRACE $SOCAT $opts -u OPEN:$ti OPENSSL-DTLS-CONNECT:$LOCALHOST:$PORT,cafile=testsrv.crt" printf "test $F_n $TEST... " $N i=0; while [ $i -lt $((2*8192)) ]; do printf "%9u %9u %9u %9u %9u %9u %9u %9u %9u %9u\n" $i $i $i $i $i $i $i $i $i $i; let i+=100; done >$ti $CMD0 >/dev/null 2>"${te}0" & pid0=$! waitudp4port $PORT 1 $CMD1 >"${tf}1" 2>"${te}1" rc1=$? usleep $MICROS kill $pid0 2>/dev/null; wait if [ $rc1 -ne 0 ]; then $PRINTF "$FAILED\n" echo "$CMD0 &" >&2 cat "${te}0" >&2 echo "$CMD1" >&2 cat "${te}1" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif diff $ti $to >$tdiff; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0 &" >&2 cat "${te}0" >&2 echo "$CMD1" >&2 cat "${te}1" >&2 echo "diff:" >&2 head -n 2 $tdiff >&2 echo ... >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # Test file transfer from server to client using DTLS NAME=OPENSSL_DTLS_TO_CLIENT case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%openssl%*|*%dtls%*|*%udp%*|*%socket%*|*%$NAME%*) TEST="$NAME: OpenSSL DTLS transfer from server to client" # Start a unidirectional OpenSSL DTLS server/sender # Start a unidirectional OpenSSL DTLS client that connects to the server and # receives data # Test succeeded when the data received and stored by client is the same as # sent by the server if ! eval $NUMCOND; then :; elif ! a=$(testfeats ip4 udp openssl); then $PRINTF "test $F_n $TEST... ${YELLOW}$a not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! a=$(testaddrs openssl-dtls-listen openssl-dtls-connect); then $PRINTF "test $F_n $TEST... ${YELLOW}$a not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}IPv4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [[ $(openssl version |awk '{print($2);}') =~ 0.9.8[a-c] ]]; then $PRINTF "test $F_n $TEST... ${YELLOW}openssl s_client might hang${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv ti="$td/test$N.datain" to="$td/test$N.dataout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts -U OPENSSL-DTLS-LISTEN:$PORT,cert=testsrv.pem,verify=0 OPEN:$ti" CMD1="$TRACE $SOCAT $opts -u OPENSSL-DTLS-CONNECT:$LOCALHOST:$PORT,cafile=testsrv.crt CREAT:$to" printf "test $F_n $TEST... " $N i=0; while [ $i -lt $((2*8192)) ]; do printf "%9u %9u %9u %9u %9u %9u %9u %9u %9u %9u\n" $i $i $i $i $i $i $i $i $i $i; let i+=100; done >$ti $CMD0 >/dev/null 2>"${te}0" & pid0=$! waitudp4port $PORT 1 $CMD1 >"${tf}1" 2>"${te}1" rc1=$? usleep $MICROS kill $pid0 2>/dev/null; wait if [ $rc1 -ne 0 ]; then $PRINTF "$FAILED\n" echo "$CMD0 &" >&2 cat "${te}0" >&2 echo "$CMD1" >&2 cat "${te}1" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif diff $ti $to >$tdiff; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0 &" >&2 cat "${te}0" >&2 echo "$CMD1" >&2 cat "${te}1" >&2 echo "diff:" >&2 head -n 2 $tdiff >&2 echo ... >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # Test if the problem with overlapping internal parameters of sockets and # openssl are fixed NAME=OPENSSL_PARA_OVERLAP case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%socket%*|*%ip4%*|*%tcp%*|*%tcp4%*|*%openssl%*|*%$NAME%*) TEST="$NAME: test diverse of socket,openssl params" # That bug had not many effects; the simplest to use is possible SIGSEGV on # close when option accept-timeout with fractional seconds was applied if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! type openssl >/dev/null 2>&1; then $PRINTF "test $F_n $TEST... ${YELLOW}openssl executable not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP/IPv4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" trc0="$td/test$N.rc0" da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts OPENSSL-LISTEN:$PORT,pf=ip4,$REUSEADDR,accept-timeout=4.5,$SOCAT_EGD,cert=testsrv.crt,key=testsrv.key,verify=0 PIPE" CMD1="$TRACE $SOCAT $opts /dev/null OPENSSL-CONNECT:$LOCALHOST:$PORT,pf=ip4,verify=0,$SOCAT_EGD" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" || echo $? >$trc0 & pid0=$! waittcp4port $PORT 1 $CMD1 >"${tf}1" 2>"${te}1" rc1=$? psleep 0.5 kill $pid0 2>/dev/null; wait if [ $rc1 -ne 0 ]; then $PRINTF "$CANT\n" numCANT=$((numCANT+1)) elif [ ! -e $trc0 ]; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0 &" >&2 cat "${te}0" >&2 echo "$CMD1" >&2 cat "${te}1" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # Bug fix, OpenSSL server could be crashed by client cert with IPv6 address in SubjectAltname NAME=OPENSSL_CLIENT_IP6_CN case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%openssl%*|*%ip6%*|*%socket%*|*%$NAME%*) TEST="$NAME: Test if OpenSSL server may be crashed by client cert with IPv6 address" # Socat 1.7.4.1 had a bug that caused OpenSSL server to crash with SIGSEGV when # it checked a client certificate containing IPv6 address in SubjectAltName and # no openssl-commonname option was given if ! eval $NUMCOND; then :; elif ! testfeats openssl >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}OPENSSL not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif ! testfeats tcp ip4 >/dev/null || ! runsip4 >/dev/null; then $PRINTF "test $F_n $TEST... ${YELLOW}TCP/IPv4 not available${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else gentestcert testsrv gentestaltcert testalt tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts -u OPENSSL-LISTEN:$PORT,reuseaddr,cert=./testsrv.pem,cafile=./testalt.crt -" CMD1="$TRACE $SOCAT $opts -u - OPENSSL-CONNECT:localhost:$PORT,cafile=testsrv.crt,cert=testalt.pem,verify=0" printf "test $F_n $TEST... " $N $CMD0 >/dev/null >"${tf}0" 2>"${te}0" & pid0=$! waittcp4port $PORT 1 echo "$da" |$CMD1 2>"${te}1" rc1=$? kill $pid0 2>/dev/null; wait if [ $rc1 -eq 0 ] && echo "$da" |diff - "${tf}0" >$tdiff; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0 &" >&2 cat "${te}0" >&2 echo "$CMD1" >&2 cat "${te}1" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # Test if unknown service specs are handled properly NAME=BAD_SERVICE case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%tcp%*|*%socket%*|*%$NAME%*) TEST="$NAME: test if unknown service specs are handled properly" # Try to resolve an unspecified TCP service " 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" CMD="$TRACE $SOCAT $opts - TCP:$LOCALHOST:zyxw" printf "test $F_n $TEST... " $N $CMD >/dev/null 2>"${te}" & pid=$! sleep 1 kill -9 $pid 2>/dev/null; rc=$? # did process still exist? if [ $rc -ne 0 ]; then $PRINTF "$OK\n" if [ "$VERBOSE" ]; then echo "$CMD &" >&2 fi numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD &" >&2 cat "${te}" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # Test if the user option with abstract UNIX domain socket is not applied to # file "" (empty name) NAME=ABSTRACT_USER case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%socket%*|*%unix%*|*%abstract%*|*%$NAME%*) TEST="$NAME: Is the fs related user option on ABSTRACT socket applied to FD" # Apply the user option to an abstract socket; check if this produces an error. # No error should occur if ! eval $NUMCOND; then :; elif [ "$UNAME" != Linux ]; then $PRINTF "test $F_n $TEST... ${YELLOW}only on Linux${NORMAL}\n" $N numCANT=$((numCANT+1)) listCANT="$listCANT $N" else tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD="$TRACE $SOCAT ABSTRACT-LISTEN:temp,accept-timeout=0.1,user=$USER FILE:/dev/null" printf "test $F_n $TEST... " $N $CMD >/dev/null 2>"${te}" echo "$da" |$CMD >"${tf}1" 2>"${te}1" rc=$? if [ $rc -eq 0 ]; then $PRINTF "$OK\n" if [ "$VERBOSE" ]; then echo "$CMD" >&2 fi numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD" >&2 cat "${te}" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # Test if option -R does not "sniff" left-to-right traffic NAME=SNIFF_RIGHT_TO_LEFT case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%$NAME%*) TEST="$NAME: test if option -R does not "sniff" left-to-right traffic" # Use option -R, check if left-to-right traffic is not in output file if ! eval $NUMCOND; then :; else tf="$td/test$N.stdout" te="$td/test$N.stderr" ts="$td/test$N.sniffed" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD="$TRACE $SOCAT $opts -R $ts - /dev/null" printf "test $F_n $TEST... " $N echo "$da" |$CMD >"${tf}" 2>"${te}" rc=$? if [ ! -f "$ts" ]; then $PRINTF "$CANT\n" if [ "$VERBOSE" ]; then echo "$CMD" >&2 cat "${te}" >&2 fi numCANT=$((numCANT+1)) listCANT="$listCANT $N" elif [ ! -s "$ts" ]; then $PRINTF "$OK\n" if [ "$VERBOSE" ]; then echo "$CMD" >&2 fi numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD &" >&2 cat "${te}" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # Socats access to different types of file system entries using various kinds # of addresses fails in a couple of useless combinations. These failures have # to print an error message and exit with return code 1. # Up to version 1.7.4.2 this desired behaviour was found for most combinations, # however some fix in 1.7.4.3 degraded the overall result. # This group of tests checks all known compinations. while read entry method; do if [ -z "$entry" ] || [[ "$entry" == \#* ]]; then continue; fi NAME=$(toupper $method)_TO_$(toupper $entry) case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%socket%*|*%unix%*|*%$NAME%*) #set -vx TEST="$NAME: Failure handling on $method access to $entry" # Create some kind of system entry and try to access it with some improper # address. Check if Socat returns with rc 1 and prints an error message if ! eval $NUMCOND; then :; else ts="$td/test$N.socket" tf="$td/test$N.stdout" te="$td/test$N.stderr" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" printf "test $F_n $TEST... " $N # create an invalid or non-matching UNIX socket case "$entry" in missing) pid0=; rm -f $ts ;; denied) pid0=; rm -f $ts; touch $ts; chmod 000 $ts ;; directory) pid0=; mkdir -p $ts ;; orphaned) pid0= # the remainder of a UNIX socket in FS $SOCAT $opts UNIX-LISTEN:$ts,unlink-close=0 /dev/null >${tf}0 2>${te}0 & waitunixport $ts 1 $SOCAT $opts /dev/null UNIX-CONNECT:$ts ;; file) pid0=; rm -f $ts; touch $ts ;; stream) CMD0="$SOCAT $opts UNIX-LISTEN:$ts /dev/null" $CMD0 >${tf}0 2>${te}0 & pid0=$! ;; dgram) CMD0="$SOCAT $opts -u UNIX-RECV:$ts /dev/null" $CMD0 >${tf}0 2>${te}0 & pid0=$! ;; seqpacket) CMD0="$SOCAT $opts UNIX-LISTEN:$ts,socktype=$SOCK_SEQPACKET= /dev/null" $CMD0 >${tf}0 2>${te}0 & pid0=$! ;; esac [ "$pid0" ] && waitunixport $ts 1 # try to access this socket case "$method" in connect) CMD1="$TRACE $SOCAT $opts -u - UNIX-CONNECT:$ts" ;; send) CMD1="$TRACE $SOCAT $opts -u - UNIX-SEND:$ts" ;; sendto) CMD1="$TRACE $SOCAT $opts -u - UNIX-SENDTO:$ts" ;; seqpacket) CMD1="$TRACE $SOCAT $opts -u - UNIX-CONNECT:$ts,socktype=$SOCK_SEQPACKET" ;; unix) CMD1="$TRACE $SOCAT $opts -u - UNIX-CLIENT:$ts" ;; gopen) CMD1="$TRACE $SOCAT $opts -u - GOPEN:$ts" ;; esac echo "$da" |$CMD1 >"${tf}1" 2>"${te}1" rc1=$? [ "$pid0" ] && { kill $pid0 2>/dev/null; wait; } if [ $rc1 != 1 ]; then $PRINTF "$FAILED (bad return code $rc1)\n" if [ "$pid0" ]; then echo "$CMD0 &" >&2 cat "${te}0" >&2 fi echo "$CMD1" >&2 cat "${te}1" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif nerr=$(grep ' E ' "${te}1" |wc -l); test "$nerr" -ne 1; then $PRINTF "$FAILED ($nerr error message(s) instead of 1)\n" if [ "$pid0" ]; then echo "$CMD0 &" >&2 cat "${te}0" >&2 fi echo "$CMD1" >&2 cat "${te}1" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" else $PRINTF "$OK\n" if [ "$VERBOSE" ]; then if [ "$pid0" ]; then echo "$CMD0 &" >&2; fi echo "$CMD1" >&2 fi numOK=$((numOK+1)) fi set +vx fi # NUMCOND ;; esac N=$((N+1)) done <<<" missing connect denied connect directory connect orphaned connect file connect dgram connect seqpacket connect missing send denied send directory send orphaned send file send stream send seqpacket send missing sendto denied sendto directory sendto orphaned sendto file sendto stream sendto seqpacket sendto missing seqpacket denied seqpacket directory seqpacket orphaned seqpacket file seqpacket stream seqpacket dgram seqpacket missing unix denied unix directory unix file unix orphaned unix denied gopen directory gopen orphaned gopen " # Test TCP with options connect-timeout and retry. # Up to 1.7.4.3 this terminated immediately on connection refused NAME=TCP_TIMEOUT_RETRY case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%tcp%*|*%socket%*|*%$NAME%*) TEST="$NAME: TCP with options connect-timeout and retry" # In background run a delayed echo server # In foreground start TCP with connect-timeout and retry. On first attempt the # server is not listening; when socat makes a second attempt that succeeds, the # bug is absent and the test succeeded. 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="sleep 1 && $TRACE $SOCAT $opts TCP-L:$PORT,reuseaddr PIPE" CMD1="$TRACE $SOCAT $opts - TCP:$LOCALHOST:$PORT,connect-timeout=2,retry=1,interval=2" printf "test $F_n $TEST... " $N eval "$CMD0" >/dev/null 2>"${te}0" & pid0=$! echo "$da" |$CMD1 >"${tf}1" 2>"${te}1" rc1=$? kill $pid0 2>/dev/null; wait if [ $rc1 -ne 0 ]; then $PRINTF "$FAILED\n" echo "$CMD0 &" >&2 cat "${te}0" >&2 echo "$CMD1" >&2 cat "${te}1" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif echo "$da" |diff - "${tf}1" >$tdiff; then $PRINTF "$OK\n" if [ "$VERBOSE" ]; then echo "$CMD0 &" >&2 echo "$CMD1" >&2 fi numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0 &" >&2 cat "${te}0" >&2 echo "$CMD1" >&2 cat "${te}1" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # Test if the rawer option works. Up to Socat 1.7.4.3, it failed because it # cleared the CREAD flag. NAME=RAWER case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%pty%*|*%$NAME%*) TEST="$NAME: Test if the rawer option fails" # Invoke Socat with a terminal address with option rawer. When it has no error # the test succeeded. 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 -lp outer /dev/null EXEC:\"$SOCAT\\ -lp\\ inner\\ -\\,rawer\\ PIPE\",pty" printf "test $F_n $TEST... " $N eval "$CMD0" >/dev/null 2>"${te}0" rc0=$? if [ $rc0 -eq 0 ]; then $PRINTF "$OK\n" if [ "$VERBOSE" ]; then echo "$CMD0" >&2 fi numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0" >&2 cat "${te}0" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # Up to 1.7.4.3 there was a bug with the lowport option: # Active addresses UDP-SEND, UDP-SENDTO always bound to port 1 instead of # 640..1023 NAME=UDP_LOWPORT case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%socket%*|*%$NAME%*) TEST="$NAME: UDP4-SEND with lowport" # Run Socat with UDP4-SEND:...,lowport and full logging and check the # parameters of bind() call. It port is in the range 640..1023 the test # succeeded. 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" CMD="$TRACE $SOCAT $opts -d -d -d -d /dev/null UDP4-SENDTO:$LOCALHOST:$PORT,lowport" printf "test $F_n $TEST... " $N $CMD >/dev/null 2>"${te}" rc1=$? LOWPORT=$(grep 'D bind(.*:' $te |sed 's/.*:\([0-9][0-9]*\),.*/\1/') #echo "LOWPORT=\"$LOWPORT\"" >&2 #type socat >&2 if [[ $LOWPORT =~ [0-9][0-9]* ]] && [ "$LOWPORT" -ge 640 -a "$LOWPORT" -le 1023 ]; then $PRINTF "$OK\n" if [ "$VERBOSE" ]; then echo "$CMD" >&2 fi numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD" >&2 cat "${te}" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1)) # Test if trailing garbage in integer type options gives error NAME=MISSING_INTEGER case "$TESTS" in *%$N%*|*%functions%*|*%syntax%*|*%bugs%*|*%$NAME%*) TEST="$NAME: Error on option that's missing integer value" # Invoke Socat with pty and option ispeed=b19200. # When socat terminates with error the test succeeded 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="$TRACE $SOCAT $opts - PTY,ispeed=b19200" printf "test $F_n $TEST... " $N $CMD0 /dev/null 2>"${te}0" if grep -q "missing numerical value" "${te}0"; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0" cat "${te}0" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac N=$((N+1)) # Test if trailing garbage in integer type options gives error NAME=INTEGER_GARBAGE case "$TESTS" in *%$N%*|*%functions%*|*%syntax%*|*%bugs%*|*%$NAME%*) TEST="$NAME: Error on trailing garbabe" # Invoke Socat with pty and option ispeed=b19200. # When socat terminates with error the test succeeded 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="$TRACE $SOCAT $opts - PTY,ispeed=19200B" printf "test $F_n $TEST... " $N $CMD0 /dev/null 2>"${te}0" if grep -q "trailing garbage" "${te}0"; then $PRINTF "$OK\n" if [ "$VERBOSE" ]; then echo "$CMD0" >&2; fi if [ "$debug" ]; then cat ${te} >&2; fi numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0" cat "${te}0" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac N=$((N+1)) # end of common tests ################################################################################## #================================================================================= # here come tests that might affect your systems integrity. Put normal tests # before this paragraph. # tests must be explicitely selected by roottough or name (not number) NAME=PTYGROUPLATE case "$TESTS" in *%roottough%*|*%$NAME%*) TEST="$NAME: pty with group-late works on pty" # up to socat 1.7.1.1 address pty changed the ownership of /dev/ptmx instead of # the pty with options user-late, group-late, or perm-late. # here we check for correct behaviour. # ATTENTION: in case of failure of this test the # group of /dev/ptmx might be changed! if ! eval $NUMCOND; then :; else # save current /dev/ptmx properties F= for f in /dev/ptmx /dev/ptc; do if [ -e $f ]; then F=$(echo "$f" |tr / ..) ls -l $f >"$td/test$N.$F.ls-l" break fi done printf "test $F_n $TEST... " $N if [ -z "$F" ]; then echo -e "${YELLOW}no /dev/ptmx or /dev/ptc${NORMAL}" else GROUP=daemon tf="$td/test$N.stdout" te="$td/test$N.stderr" tl="$td/test$N.pty" tdiff="$td/test$N.diff" da="test$N $(date) $RANDOM" CMD0="$TRACE $SOCAT $opts pty,link=$tl,group-late=$GROUP,escape=0x1a PIPE" CMD1="$TRACE $SOCAT $opts - $tl,raw,echo=0" $CMD0 >/dev/null 2>"${te}0" & pid0=$! (echo "$da"; usleep $MICROS; echo -e "\x1a") |$CMD1 >"${tf}1" 2>"${te}1" >"$tf" rc1=$? kill $pid0 2>/dev/null; wait if [ $rc1 -ne 0 ]; then $PRINTF "$FAILED\n" echo "$CMD0 &" echo "$CMD1" cat "${te}0" cat "${te}1" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" elif echo "$da" |diff - "$tf" >$tdiff; then $PRINTF "$OK\n" numOK=$((numOK+1)) else $PRINTF "$FAILED\n" cat "$tdiff" numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi if ! ls -l $f |diff "$td/test$N.$F.ls-l" -; then $PRINTF "${RED}this test changed properties of $f!${NORMAL}\n" fi fi # no /dev/ptmx fi # NUMCOND ;; esac N=$((N+1)) echo "Used temp directory $TD - you might want to remove it after analysis" echo "Summary: $((N-1)) tests, $((numOK+numFAIL+numCANT)) selected; $numOK ok, $numFAIL failed, $numCANT could not be performed" if [ "$numCANT" -gt 0 ]; then echo "CANT: $listCANT" fi if [ "$numFAIL" -gt 0 ]; then echo "FAILED: $listFAIL" exit 1 fi exit 0 #============================================================================== rm -f testsrv.* testcli.* testsrvdsa* testsrvfips* testclifips* # end # too dangerous - run as root and having a shell problem, it might purge your # file systems #rm -r "$td" # sometimes subprocesses hang; we want to see this wait exit #============================================================================== # test template # Give a description of what is tested (a bugfix, a new feature...) NAME=SHORT_UNIQUE_TESTNAME case "$TESTS" in *%$N%*|*%functions%*|*%bugs%*|*%socket%*|*%$NAME%*) TEST="$NAME: give a one line description of test" # Describe how the test is performed, and what's the success criteria 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="$TRACE $SOCAT $opts server-address PIPE" CMD1="$TRACE $SOCAT $opts - client-address" printf "test $F_n $TEST... " $N $CMD0 >/dev/null 2>"${te}0" & pid0=$! waitport $PORT 1 echo "$da" |$CMD1 >"${tf}1" 2>"${te}1" rc1=$? kill $pid0 2>/dev/null; wait if [ !!! ]; then $PRINTF "$OK\n" if [ "$VERBOSE" ]; then echo "$CMD0 &" >&2 echo "$CMD1" >&2 fi numOK=$((numOK+1)) else $PRINTF "$FAILED\n" echo "$CMD0 &" >&2 cat "${te}0" >&2 echo "$CMD1" >&2 cat "${te}1" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi fi # NUMCOND ;; esac PORT=$((PORT+1)) N=$((N+1))