mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 15:32:35 +00:00
new address options shut-null, null-eof
This commit is contained in:
parent
793763677a
commit
806bccbf94
13 changed files with 96 additions and 10 deletions
10
CHANGES
10
CHANGES
|
@ -1,7 +1,13 @@
|
|||
|
||||
new features:
|
||||
new address options shut-none, shut-down, and shut-close allow to
|
||||
control socat's half close behaviour
|
||||
address options shut-none, shut-down, and shut-close allow to control
|
||||
socat's half close behaviour
|
||||
|
||||
with address option shut-null socat sends an empty packet to the peer
|
||||
to indicate EOF
|
||||
|
||||
option null-eof changes the behaviour of sockets that receive an empty
|
||||
packet to see EOF instead of ignoring it
|
||||
|
||||
####################### V 1.7.0.1:
|
||||
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
"1.7.0.1"
|
||||
"1.7.0.1+shutnull"
|
||||
|
|
10
doc/socat.yo
10
doc/socat.yo
|
@ -1490,6 +1490,16 @@ label(OPTION_SHUT_DOWN)dit(bf(tt(shut-down)))
|
|||
label(OPTION_SHUT_CLOSE)dit(bf(tt(shut-close)))
|
||||
Changes the (address dependent) method of shutting down the write part of a
|
||||
connection to tt(close\(fd)).
|
||||
label(OPTION_SHUT_NULL)dit(bf(tt(shut-null)))
|
||||
When one address indicates EOF, socat() will send a zero sized packet to the
|
||||
write channel of the other address to transfer the EOF condition. This is
|
||||
useful with UDP and other datagram protocols. Has been tested against
|
||||
netcat and socat with option link(null-eof)(OPTION_NULL_EOF).
|
||||
label(OPTION_NULL_EOF)dit(bf(tt(null-eof)))
|
||||
Normally socat() will ignore empty (zero size payload) packets arriving on
|
||||
datagram sockets, so it survives port scans. With this option socat()
|
||||
interprets empty datagram packets as EOF indicator (see
|
||||
link(shut-null)(OPTION_SHUT_NULL).
|
||||
label(OPTION_IOCTL_VOID)dit(bf(tt(ioctl-void=<request>)))
|
||||
Calls tt(ioctl()) with the request value as second argument and NULL as
|
||||
third argument. This option allows to utilize ioctls that are not
|
||||
|
|
52
test.sh
52
test.sh
|
@ -7558,6 +7558,58 @@ esac
|
|||
N=$((N+1))
|
||||
|
||||
|
||||
# test the shut-null and null-eof options
|
||||
NAME=SHUTNULLEOF
|
||||
case "$TESTS" in
|
||||
*%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.
|
||||
# whe the receiving process just got 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="$SOCAT $opts -u UDP-RECV:$PORT,null-eof CREAT:$tf"
|
||||
CMD1="$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" |$CMD1 >"${tf}1" 2>"${te}1"
|
||||
rc1=$?
|
||||
echo "xyz" |$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))
|
||||
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))
|
||||
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
|
||||
|
|
1
xio-fd.c
1
xio-fd.c
|
@ -78,6 +78,7 @@ const struct optdesc opt_end_close = { "end-close", "close", OPT_END_CLOSE, GROU
|
|||
const struct optdesc opt_shut_none = { "shut-none", NULL, OPT_SHUT_NONE, GROUP_FD, PH_INIT, TYPE_BOOL, OFUNC_OFFSET, (bool)&((xiofile_t *)0)->stream.howtoshut, XIOSHUT_NONE };
|
||||
const struct optdesc opt_shut_down = { "shut-down", NULL, OPT_SHUT_DOWN, GROUP_FD, PH_INIT, TYPE_BOOL, OFUNC_OFFSET, (bool)&((xiofile_t *)0)->stream.howtoshut, XIOSHUT_DOWN };
|
||||
const struct optdesc opt_shut_close= { "shut-close", NULL, OPT_SHUT_CLOSE, GROUP_FD, PH_INIT, TYPE_BOOL, OFUNC_OFFSET, (bool)&((xiofile_t *)0)->stream.howtoshut, XIOSHUT_CLOSE };
|
||||
const struct optdesc opt_shut_null = { "shut-null", NULL, OPT_SHUT_NULL, GROUP_FD, PH_INIT, TYPE_CONST, OFUNC_OFFSET, (bool)&((xiofile_t *)0)->stream.howtoshut, XIOSHUT_NULL };
|
||||
|
||||
/****** generic ioctl() options ******/
|
||||
const struct optdesc opt_ioctl_void = { "ioctl-void", "ioctl", OPT_IOCTL_VOID, GROUP_FD, PH_FD, TYPE_INT, OFUNC_IOCTL_GENERIC, 0, 0, 0 };
|
||||
|
|
1
xio-fd.h
1
xio-fd.h
|
@ -45,6 +45,7 @@ extern const struct optdesc opt_end_close;
|
|||
extern const struct optdesc opt_shut_none;
|
||||
extern const struct optdesc opt_shut_down;
|
||||
extern const struct optdesc opt_shut_close;
|
||||
extern const struct optdesc opt_shut_null;
|
||||
extern const struct optdesc opt_streams_i_push;
|
||||
|
||||
#endif /* !defined(__xio_fd_h_included) */
|
||||
|
|
|
@ -196,6 +196,8 @@ const struct optdesc opt_setsockopt_int = { "setsockopt-int", "sockopt-int
|
|||
const struct optdesc opt_setsockopt_bin = { "setsockopt-bin", "sockopt-bin", OPT_SETSOCKOPT_BIN, GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT_INT_BIN, OFUNC_SOCKOPT_GENERIC, 0, 0 };
|
||||
const struct optdesc opt_setsockopt_string = { "setsockopt-string", "sockopt-string", OPT_SETSOCKOPT_STRING, GROUP_SOCKET,PH_PASTSOCKET,TYPE_INT_INT_STRING, OFUNC_SOCKOPT_GENERIC, 0, 0 };
|
||||
|
||||
const struct optdesc opt_null_eof = { "null-eof", NULL, OPT_NULL_EOF, GROUP_SOCKET, PH_INIT, TYPE_BOOL, OFUNC_OFFSET, (bool)&((xiofile_t *)0)->stream.para.socket.null_eof };
|
||||
|
||||
|
||||
#if WITH_GENERICSOCKET
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* source: xio-socket.h */
|
||||
/* Copyright Gerhard Rieger 2001-2008 */
|
||||
/* Copyright Gerhard Rieger 2001-2009 */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
#ifndef __xio_socket_h_included
|
||||
|
@ -67,6 +67,7 @@ extern const struct optdesc opt_protocol_family;
|
|||
extern const struct optdesc opt_setsockopt_int;
|
||||
extern const struct optdesc opt_setsockopt_bin;
|
||||
extern const struct optdesc opt_setsockopt_string;
|
||||
extern const struct optdesc opt_null_eof;
|
||||
|
||||
|
||||
extern
|
||||
|
|
7
xio.h
7
xio.h
|
@ -147,10 +147,11 @@ typedef struct single {
|
|||
char *unlink_close; /* name of a symlink or unix socket to be removed */
|
||||
int dtype;
|
||||
enum {
|
||||
XIOSHUT_UNSPEC, /* fall back to old (up to 1.7.0.0) behaviour */
|
||||
XIOSHUT_UNSPEC, /* standard (address dependent) behaviour */
|
||||
XIOSHUT_NONE, /* do nothing on shutdown */
|
||||
XIOSHUT_CLOSE, /* close the FD */
|
||||
XIOSHUT_DOWN /* shutdown() */
|
||||
XIOSHUT_DOWN, /* shutdown() */
|
||||
XIOSHUT_NULL /* send an empty packet (dgram socket) */
|
||||
} howtoshut;
|
||||
enum {
|
||||
END_UNSPEC, /* after init, when no end-close... option */
|
||||
|
@ -183,7 +184,7 @@ typedef struct single {
|
|||
struct {
|
||||
struct timeval connect_timeout; /* how long to hang in connect() */
|
||||
union sockaddr_union la; /* local socket address */
|
||||
bool emptyiseof; /* with dgram: empty packet means EOF */
|
||||
bool null_eof; /* with dgram: empty packet means EOF */
|
||||
bool dorange;
|
||||
struct xiorange range; /* restrictions for peer address */
|
||||
#if _WITH_IP4 || _WITH_IP6
|
||||
|
|
|
@ -926,6 +926,7 @@ const struct optname optionnames[] = {
|
|||
#ifdef O_NSHARE
|
||||
IF_OPEN ("nshare", &opt_o_nshare)
|
||||
#endif
|
||||
IF_SOCKET ("null-eof", &opt_null_eof)
|
||||
#ifdef O_ASYNC
|
||||
IF_ANY ("o-async", &opt_async)
|
||||
#endif
|
||||
|
@ -1316,6 +1317,7 @@ const struct optname optionnames[] = {
|
|||
IF_ANY ("shut-close", &opt_shut_close)
|
||||
IF_ANY ("shut-down", &opt_shut_down)
|
||||
IF_ANY ("shut-none", &opt_shut_none)
|
||||
IF_ANY ("shut-null", &opt_shut_null)
|
||||
#if WITH_EXEC || WITH_SYSTEM
|
||||
IF_ANY ("sid", &opt_setsid)
|
||||
#endif
|
||||
|
|
|
@ -444,6 +444,7 @@ enum e_optcode {
|
|||
OPT_NOFLSH, /* termios.c_lflag */
|
||||
OPT_NOFORK, /* exec, system */
|
||||
OPT_NOPROMPT, /* readline */
|
||||
OPT_NULL_EOF, /* receiving empty packet triggers EOF */
|
||||
#ifdef OCRNL
|
||||
OPT_OCRNL, /* termios.c_oflag */
|
||||
#endif
|
||||
|
@ -593,6 +594,7 @@ enum e_optcode {
|
|||
OPT_SHUT_CLOSE,
|
||||
OPT_SHUT_DOWN,
|
||||
OPT_SHUT_NONE,
|
||||
OPT_SHUT_NULL, /* send 0 bytes on shutdown */
|
||||
OPT_SIGHUP,
|
||||
OPT_SIGINT,
|
||||
OPT_SIGQUIT,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* source: xioread.c */
|
||||
/* Copyright Gerhard Rieger 2001-2008 */
|
||||
/* Copyright Gerhard Rieger 2001-2009 */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* this is the source of the extended read function */
|
||||
|
@ -159,7 +159,7 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
|
|||
bytes,
|
||||
sockaddr_info(&from.soa, fromlen, infobuff, sizeof(infobuff)));
|
||||
if (bytes == 0) {
|
||||
if (!pipe->para.socket.emptyiseof) {
|
||||
if (!pipe->para.socket.null_eof) {
|
||||
errno = EAGAIN; return -1;
|
||||
}
|
||||
return bytes;
|
||||
|
@ -350,7 +350,7 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
|
|||
bytes,
|
||||
sockaddr_info(&from.soa, fromlen, infobuff, sizeof(infobuff)));
|
||||
if (bytes == 0) {
|
||||
if (!pipe->para.socket.emptyiseof) {
|
||||
if (!pipe->para.socket.null_eof) {
|
||||
errno = EAGAIN; return -1;
|
||||
}
|
||||
return bytes;
|
||||
|
|
|
@ -35,6 +35,7 @@ int xioshutdown(xiofile_t *sock, int how) {
|
|||
}
|
||||
|
||||
switch (sock->stream.howtoshut) {
|
||||
char writenull;
|
||||
case XIOSHUT_NONE:
|
||||
return 0;
|
||||
case XIOSHUT_CLOSE:
|
||||
|
@ -49,9 +50,16 @@ int xioshutdown(xiofile_t *sock, int how) {
|
|||
sock->stream.fd, how, strerror(errno));
|
||||
}
|
||||
return 0;
|
||||
#if _WITH_SOCKET
|
||||
case XIOSHUT_NULL:
|
||||
/* send an empty packet; only useful on datagram sockets? */
|
||||
xiowrite(sock, &writenull, 0);
|
||||
return 0;
|
||||
#endif /* _WITH_SOCKET */
|
||||
default: ;
|
||||
}
|
||||
|
||||
|
||||
#if WITH_OPENSSL
|
||||
if ((sock->stream.dtype & XIODATA_MASK) == XIODATA_OPENSSL) {
|
||||
sycSSL_shutdown (sock->stream.para.openssl.ssl);
|
||||
|
|
Loading…
Reference in a new issue