diff --git a/CHANGES b/CHANGES index bc8c249..f68d1ab 100644 --- a/CHANGES +++ b/CHANGES @@ -139,6 +139,9 @@ New features: Tests: OPENSSL_SERVERALTAUTH OPENSSL_SERVERALTIP4AUTH OPENSSL_SERVERALTIP6AUTH Fixes Red Hat bug 1805132 + Added options -r and -R for raw dump of transferred data to files. + Test: OPTION_RAW_DUMP + ####################### V 1.7.3.4: Corrections: diff --git a/doc/socat.yo b/doc/socat.yo index 88508f4..98698ae 100644 --- a/doc/socat.yo +++ b/doc/socat.yo @@ -153,6 +153,12 @@ dit(bf(tt(-x))) Writes the transferred data not only to their target streams, but also to stderr. The output format is hexadecimal, prefixed with "> " or "< " indicating flow directions. Can be combined with code(-v). +dit(bf(tt(-r ))) + Dumps the raw (binary) data flowing from left to right address to the given + file. +dit(bf(tt(-R ))) + Dumps the raw (binary) data flowing from right to left address to the given + file. label(option_b)dit(bf(tt(-b))tt()) Sets the data transfer block [link(size_t)(TYPE_SIZE_T)]. At most bytes are transferred per step. Default is 8192 bytes. diff --git a/socat.c b/socat.c index 3e94c78..320d41c 100644 --- a/socat.c +++ b/socat.c @@ -36,6 +36,8 @@ struct { char logopt; /* y..syslog; s..stderr; f..file; m..mixed */ bool lefttoright; /* first addr ro, second addr wo */ bool righttoleft; /* first addr wo, second addr ro */ + int sniffleft; /* -1 or an FD for teeing data arriving on xfd1 */ + int sniffright; /* -1 or an FD for teeing data arriving on xfd2 */ xiolock_t lock; /* a lock file */ } socat_opts = { 8192, /* bufsiz */ @@ -49,6 +51,8 @@ struct { 's', /* logopt */ false, /* lefttoright */ false, /* righttoleft */ + -1, /* sniffleft */ + -1, /* sniffright */ { NULL, 0 }, /* lock */ }; @@ -174,6 +178,30 @@ int main(int argc, const char *argv[]) { socat_opts.verbose = true; break; case 'x': if (arg1[0][2]) { socat_opt_hint(stderr, arg1[0][1], arg1[0][2]); Exit(1); } socat_opts.verbhex = true; break; + case 'r': if (arg1[0][2]) { + a = *arg1+2; + } else { + ++arg1, --argc; + if ((a = *arg1) == NULL) { + Error("option -r requires an argument; use option \"-h\" for help"); + break; + } + } + if ((socat_opts.sniffleft = Open(a, O_CREAT|O_WRONLY|O_APPEND|O_LARGEFILE|O_NONBLOCK, 0664)) < 0) + Error2("option -r \"%s\": %s", a, strerror(errno)); + break; + case 'R': if (arg1[0][2]) { + a = *arg1+2; + } else { + ++arg1, --argc; + if ((a = *arg1) == NULL) { + Error("option -R requires an argument; use option \"-h\" for help"); + break; + } + } + if ((socat_opts.sniffright = Open(a, O_CREAT|O_WRONLY|O_APPEND|O_LARGEFILE|O_NONBLOCK, 0664)) < 0) + Error2("option -r \"%s\": %s", a, strerror(errno)); + break; case 'b': if (arg1[0][2]) { a = *arg1+2; } else { @@ -364,8 +392,10 @@ void socat_usage(FILE *fd) { fputs(" -lp set the program name used for logging\n", fd); fputs(" -lu use microseconds for logging timestamps\n", fd); fputs(" -lh add hostname to log messages\n", fd); - fputs(" -v verbose data traffic, text\n", fd); - fputs(" -x verbose data traffic, hexadecimal\n", fd); + fputs(" -v verbose text dump of data traffic\n", fd); + fputs(" -x verbose hexadecimal dump of data traffic\n", fd); + fputs(" -r raw dump of data flowing from left to right\n", fd); + fputs(" -R raw dump of data flowing from right to left\n", fd); fputs(" -b set data buffer size (8192)\n", fd); fputs(" -s sloppy (continue on error)\n", fd); fputs(" -t wait seconds before closing second channel\n", fd); @@ -1258,6 +1288,12 @@ int xiotransfer(xiofile_t *inpipe, xiofile_t *outpipe, errno = EAGAIN; return -1; } + if (!righttoleft && socat_opts.sniffleft >= 0) { + Write(socat_opts.sniffleft, buff, bytes); + } else if (socat_opts.sniffright >= 0) { + Write(socat_opts.sniffright, buff, bytes); + } + if (socat_opts.verbose && socat_opts.verbhex) { /* Hack-o-rama */ size_t i = 0; diff --git a/test.sh b/test.sh index e30b385..ebc7b81 100755 --- a/test.sh +++ b/test.sh @@ -14255,6 +14255,60 @@ 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)) + + ################################################################################## #================================================================================= # here come tests that might affect your systems integrity. Put normal tests @@ -14377,10 +14431,10 @@ if [ !!! ]; then numOK=$((numOK+1)) else $PRINTF "$FAILED\n" - echo "$CMD0 &" - echo "$CMD1" - cat "${te}0" - cat "${te}1" + echo "$CMD0 &" >&2 + cat "${te}0" >&2 + echo "$CMD1" >&2 + cat "${te}1" >&2 numFAIL=$((numFAIL+1)) listFAIL="$listFAIL $N" fi