mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 23:42:34 +00:00
version 2.0.0-b1
This commit is contained in:
parent
b819572f5e
commit
db717446a4
96 changed files with 6419 additions and 2363 deletions
28
CHANGES
28
CHANGES
|
@ -1,4 +1,32 @@
|
||||||
|
|
||||||
|
####################### V 2.0.0-b1:
|
||||||
|
|
||||||
|
new features:
|
||||||
|
address chains consisting of inter and endpoint addresses, linked with
|
||||||
|
'|' (pipe character)
|
||||||
|
|
||||||
|
reverting inter addresses
|
||||||
|
|
||||||
|
dual type inter addresses
|
||||||
|
|
||||||
|
changed form of dual addresses from in!!out to out%in
|
||||||
|
|
||||||
|
address overloading per parameter number, inter/endpoint type, and
|
||||||
|
supported transfer directions
|
||||||
|
|
||||||
|
derived new inter addresses OPENSSL-CLIENT, OPENSSL-SERVER,
|
||||||
|
PROXY-CLIENT, SOCKS4-CLIENT, SOCKS4A-CLIENT from related old addresses
|
||||||
|
|
||||||
|
new inter address SOCKS5-CLIENT
|
||||||
|
|
||||||
|
new inter address NOP
|
||||||
|
|
||||||
|
new inter address TEST, TESTUNI, TESTREV
|
||||||
|
|
||||||
|
new form of PTY address with symlink paramater
|
||||||
|
|
||||||
|
new form of FD address with output/input fd numbers
|
||||||
|
|
||||||
####################### V 1.6.0.0:
|
####################### V 1.6.0.0:
|
||||||
|
|
||||||
new features:
|
new features:
|
||||||
|
|
20
EXAMPLES
20
EXAMPLES
|
@ -87,7 +87,7 @@ $ socat -u -,cr -
|
||||||
|
|
||||||
// save piped data similar to 'tee':
|
// save piped data similar to 'tee':
|
||||||
// copies stdin to stdout, but writes everything to the file too
|
// copies stdin to stdout, but writes everything to the file too
|
||||||
$ socat -,echo=0 open:/tmp/myfile,create,trunc,ignoreeof!!/tmp/myfile
|
$ socat - OPEN:/tmp/myfile,create,trunc%open:/tmp/myfile,ignoreeof
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// intrusion testing
|
// intrusion testing
|
||||||
|
@ -113,23 +113,23 @@ $ socat -,echo=0 open:/tmp/myfile,create,trunc,ignoreeof!!/tmp/myfile
|
||||||
// forms of stdin with stdout, all equivalent
|
// forms of stdin with stdout, all equivalent
|
||||||
$ socat echo -
|
$ socat echo -
|
||||||
$ socat echo STDIO
|
$ socat echo STDIO
|
||||||
$ socat echo STDIN!!STDOUT
|
$ socat echo STDOUT%STDIN
|
||||||
$ socat echo STDIO!!STDIO
|
$ socat echo STDIO%STDIO
|
||||||
$ socat echo -!!-
|
$ socat echo -%-
|
||||||
$ socat echo FD:0!!FD:1
|
$ socat echo FD:1%FD:0
|
||||||
$ socat echo 0!!1
|
$ socat echo 1%0
|
||||||
$ socat echo /dev/stdin!!/dev/stdout // if your OS provides these
|
$ socat echo /dev/stdout%/dev/stdin // if your OS provides these
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// some echo address examples
|
// some echo address examples
|
||||||
$ socat - PIPE
|
$ socat - PIPE
|
||||||
$ socat - PIPE:/tmp/pipi // other version of echo
|
$ socat - PIPE:/tmp/pipi // other version of echo
|
||||||
$ socat - PIPE:/tmp/pipi,nonblock!!/tmp/pipi // other version of echo
|
$ socat - PIPE:/tmp/pipi%/tmp/pipi // other version of echo
|
||||||
$ socat - EXEC:/bin/cat // another echo
|
$ socat - EXEC:/bin/cat // another echo
|
||||||
$ socat - SYSTEM:/bin/cat // another echo
|
$ socat - SYSTEM:/bin/cat // another echo
|
||||||
$ socat - TCP:loopback:7 // if inetd echo/TCP service activated
|
$ socat - TCP:loopback:7 // if inetd echo/TCP service activated
|
||||||
$ socat - UDP:loopback:7 // if inetd echo/UDP service activated
|
$ socat - UDP:loopback:7 // if inetd echo/UDP service activated
|
||||||
$ socat - /tmp/hugo,trunc,ignoreeof!!/tmp/hugo // with delay
|
$ socat - /tmp/hugo,trunc%/tmp/hugo,ignoreeof // with delay
|
||||||
$ socat - UDP:loopback:2000,bind=:2000 // self "connection"
|
$ socat - UDP:loopback:2000,bind=:2000 // self "connection"
|
||||||
$ socat - TCP:loopback:2000,bind=:2000 // Linux bug?
|
$ socat - TCP:loopback:2000,bind=:2000 // Linux bug?
|
||||||
# socat - IP:loopback:222 // raw protocol, self "connected" (attention,
|
# socat - IP:loopback:222 // raw protocol, self "connected" (attention,
|
||||||
|
@ -151,7 +151,7 @@ $ socat -u - CREATE:/tmp/outfile1,group=floppy,perm=0640
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// file handling
|
// file handling
|
||||||
$ socat - FILE:/tmp/outfile1,ignoreeof!!FILE:/tmp/outfile1,append // prints outfile1, then echoes input and protocols into file (appends to old data)
|
$ socat - FILE:/tmp/outfile1,append%FILE:/tmp/outfile1,ignoreeof // prints outfile1, then echoes input and protocols into file (appends to old data)
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// unix socket handling
|
// unix socket handling
|
||||||
|
|
8
FAQ
8
FAQ
|
@ -57,14 +57,6 @@ But the following OS differences result in errors on non Linux systems:
|
||||||
$PATH, and "openssl s_server ..." needs enough entropy to generate a key.
|
$PATH, and "openssl s_server ..." needs enough entropy to generate a key.
|
||||||
|
|
||||||
|
|
||||||
Q: When I specify a dual address (two partial addresses linked with "!!") on
|
|
||||||
the command line, I get some message "event not found", and my shell history
|
|
||||||
has the line truncated. Not even protecting the '!'s with '\' helps.
|
|
||||||
|
|
||||||
A: '!' is appearently used by your shell as history expansion character. Say
|
|
||||||
"set +H" and add this line to your (bash) profile.
|
|
||||||
|
|
||||||
|
|
||||||
Q: On Solaris, socat was built successfully, but when started, it gets killed
|
Q: On Solaris, socat was built successfully, but when started, it gets killed
|
||||||
with something like "ld.so.1: ./socat: fatal: libreadline.so.4: open failed: no
|
with something like "ld.so.1: ./socat: fatal: libreadline.so.4: open failed: no
|
||||||
such file or directory"
|
such file or directory"
|
||||||
|
|
37
Makefile.in
37
Makefile.in
|
@ -37,18 +37,19 @@ INSTALL = @INSTALL@
|
||||||
|
|
||||||
#0 CFLAGS = @CFLAGS@ $(CCOPTS) $(DEFS) $(INCLS)
|
#0 CFLAGS = @CFLAGS@ $(CCOPTS) $(DEFS) $(INCLS)
|
||||||
CFLAGS = @CFLAGS@ $(CCOPTS) $(DEFS) $(CPPFLAGS)
|
CFLAGS = @CFLAGS@ $(CCOPTS) $(DEFS) $(CPPFLAGS)
|
||||||
CLIBS = $(LIBS)
|
CLIBS = $(LIBS) -lpthread
|
||||||
#CLIBS = $(LIBS) -lm -lefence
|
#CLIBS = $(LIBS) -lm -lefence
|
||||||
XIOSRCS = xioinitialize.c xiohelp.c xioparam.c xiodiag.c xioopen.c xioopts.c \
|
XIOSRCS = xioinitialize.c xiohelp.c xioparam.c xiodiag.c xioopen.c xioopts.c \
|
||||||
xiosignal.c xiosigchld.c xioread.c xiowrite.c \
|
xiosignal.c xiosigchld.c xioread.c xiowrite.c xiotransfer.c xioengine.c \
|
||||||
xiolayer.c xioshutdown.c xioclose.c xioexit.c \
|
xiolayer.c xioshutdown.c xioclose.c xioexit.c xiosocketpair.c \
|
||||||
xio-process.c xio-fd.c xio-fdnum.c xio-stdio.c xio-pipe.c \
|
xio-process.c xio-fd.c xio-fdnum.c xio-stdio.c xio-pipe.c \
|
||||||
xio-gopen.c xio-creat.c xio-file.c xio-named.c \
|
xio-gopen.c xio-creat.c xio-file.c xio-named.c \
|
||||||
xio-socket.c xio-listen.c xio-unix.c xio-ip.c xio-ip4.c xio-ip6.c xio-ipapp.c xio-tcp.c xio-socks.c xio-proxy.c xio-udp.c \
|
xio-socket.c xio-listen.c xio-unix.c xio-ip.c xio-ip4.c xio-ip6.c xio-ipapp.c xio-tcp.c xio-socks.c xio-socks5.c xio-proxy.c xio-udp.c \
|
||||||
xio-rawip.c \
|
xio-rawip.c \
|
||||||
xio-progcall.c xio-exec.c xio-system.c xio-termios.c xio-readline.c \
|
xio-progcall.c xio-exec.c xio-system.c xio-termios.c xio-readline.c \
|
||||||
xio-pty.c xio-openssl.c \
|
xio-pty.c xio-openssl.c \
|
||||||
xio-ascii.c xiolockfile.c xio-tcpwrap.c xio-ext2.c xio-tun.c
|
xio-ascii.c xiolockfile.c xio-tcpwrap.c xio-ext2.c xio-tun.c \
|
||||||
|
xio-nop.c xio-test.c
|
||||||
XIOOBJS = $(XIOSRCS:.c=.o)
|
XIOOBJS = $(XIOSRCS:.c=.o)
|
||||||
UTLSRCS = error.c dalan.c procan.c hostan.c fdname.c sysutils.c utils.c nestlex.c @FILAN@ @SYCLS@ @SSLCLS@
|
UTLSRCS = error.c dalan.c procan.c hostan.c fdname.c sysutils.c utils.c nestlex.c @FILAN@ @SYCLS@ @SSLCLS@
|
||||||
UTLOBJS = $(UTLSRCS:.c=.o)
|
UTLOBJS = $(UTLSRCS:.c=.o)
|
||||||
|
@ -61,24 +62,24 @@ HFILES = sycls.h sslcls.h error.h dalan.h procan.h filan.h hostan.h sysincludes.
|
||||||
xiomodes.h xiolayer.h xio-process.h xio-fd.h xio-fdnum.h xio-stdio.h \
|
xiomodes.h xiolayer.h xio-process.h xio-fd.h xio-fdnum.h xio-stdio.h \
|
||||||
xio-named.h xio-file.h xio-creat.h xio-gopen.h xio-pipe.h xio-socket.h \
|
xio-named.h xio-file.h xio-creat.h xio-gopen.h xio-pipe.h xio-socket.h \
|
||||||
xio-listen.h xio-unix.h xio-rawip.h xio-ip.h xio-ip4.h xio-ip6.h \
|
xio-listen.h xio-unix.h xio-rawip.h xio-ip.h xio-ip4.h xio-ip6.h \
|
||||||
xio-ipapp.h xio-tcp.h xio-udp.h xio-socks.h xio-proxy.h xio-progcall.h xio-exec.h \
|
xio-ipapp.h xio-tcp.h xio-udp.h xio-socks.h xio-socks5.h xio-proxy.h xio-progcall.h xio-exec.h \
|
||||||
xio-system.h xio-termios.h xio-readline.h \
|
xio-system.h xio-termios.h xio-readline.h \
|
||||||
xio-pty.h xio-openssl.h \
|
xio-pty.h xio-openssl.h \
|
||||||
xio-ascii.h xiolockfile.h xio-tcpwrap.h xio-ext2.h xio-tun.h
|
xio-ascii.h xiolockfile.h xio-tcpwrap.h xio-ext2.h xio-tun.h \
|
||||||
|
xiosigchld.h xiostatic.h xio-nop.h xio-test.h
|
||||||
|
|
||||||
|
DOCFILES = README README.FIPS CHANGES FILES EXAMPLES PORTING SECURITY DEVELOPMENT doc/socat.1 doc/socat.html FAQ BUGREPORTS COPYING COPYING.OpenSSL doc/dest-unreach.css doc/socat-openssltunnel.html doc/socat-multicast.html doc/socat-tun.html
|
||||||
DOCFILES = README README.FIPS CHANGES FILES EXAMPLES PORTING SECURITY DEVELOPMENT doc/socat.1 doc/socat.html doc/xio.help FAQ BUGREPORTS COPYING COPYING.OpenSSL doc/dest-unreach.css doc/socat-openssltunnel.html doc/socat-multicast.html doc/socat-tun.html
|
|
||||||
SHFILES = daemon.sh mail.sh ftp.sh readline.sh
|
SHFILES = daemon.sh mail.sh ftp.sh readline.sh
|
||||||
TESTFILES = test.sh socks4echo.sh proxyecho.sh gatherinfo.sh readline-test.sh \
|
TESTFILES = test.sh socks4echo.sh proxyecho.sh gatherinfo.sh readline-test.sh \
|
||||||
proxy.sh socks4a-echo.sh testcert.conf
|
proxy.sh socks4a-echo.sh testcert.conf
|
||||||
OSFILES = Config/Makefile.Linux-2-6-16 Config/config.Linux-2-6-16.h \
|
#OSFILES = Config/Makefile.Linux-2-6-16 Config/config.Linux-2-6-16.h \
|
||||||
Config/Makefile.AIX-5-1 Config/config.AIX-5-1.h \
|
# Config/Makefile.AIX-5-1 Config/config.AIX-5-1.h \
|
||||||
Config/Makefile.SunOS-5-8 Config/config.SunOS-5-8.h \
|
# Config/Makefile.SunOS-5-8 Config/config.SunOS-5-8.h \
|
||||||
Config/Makefile.HP-UX-B-11-11 Config/config.HP-UX-B-11-11.h \
|
# Config/Makefile.HP-UX-B-11-11 Config/config.HP-UX-B-11-11.h \
|
||||||
Config/Makefile.FreeBSD-6-1 Config/config.FreeBSD-6-1.h \
|
# Config/Makefile.FreeBSD-6-1 Config/config.FreeBSD-6-1.h \
|
||||||
Config/Makefile.NetBSD-2-0-2 Config/config.NetBSD-2-0-2.h \
|
# Config/Makefile.NetBSD-2-0-2 Config/config.NetBSD-2-0-2.h \
|
||||||
Config/Makefile.OpenBSD-3-8 Config/config.OpenBSD-3-8.h \
|
# Config/Makefile.OpenBSD-3-8 Config/config.OpenBSD-3-8.h \
|
||||||
Config/Makefile.Tru64-5-1B Config/config.Tru64-5-1B.h
|
# Config/Makefile.Tru64-5-1B Config/config.Tru64-5-1B.h
|
||||||
|
|
||||||
|
|
||||||
all: progs
|
all: progs
|
||||||
|
@ -133,7 +134,7 @@ socat.tar.bz2: socat.tar
|
||||||
|
|
||||||
VERSION = `sed 's/"//g' VERSION`
|
VERSION = `sed 's/"//g' VERSION`
|
||||||
TARDIR = socat-$(VERSION)
|
TARDIR = socat-$(VERSION)
|
||||||
socat.tar: configure.in configure Makefile.in config.h.in install-sh VERSION $(CFILES) $(HFILES) $(DOCFILES) $(SHFILES) $(OSFILES) $(TESTFILES) socat.spec
|
socat.tar: configure.in configure Makefile.in config.h.in install-sh VERSION $(CFILES) $(HFILES) $(DOCFILES) $(SHFILES) $(OSFILES) $(TESTFILES)
|
||||||
if [ ! -d $(TARDIR) ]; then mkdir $(TARDIR); fi
|
if [ ! -d $(TARDIR) ]; then mkdir $(TARDIR); fi
|
||||||
tar cf - $+ |(cd $(TARDIR); tar xf -)
|
tar cf - $+ |(cd $(TARDIR); tar xf -)
|
||||||
tar cvf socat.tar $(TARDIR)
|
tar cvf socat.tar $(TARDIR)
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
"1.6.0.0"
|
"2.0.0-b1"
|
||||||
|
|
4
compat.h
4
compat.h
|
@ -1,5 +1,5 @@
|
||||||
/* $Id: compat.h,v 1.32 2006/06/19 20:28:52 gerhard Exp $ */
|
/* $Id: compat.h,v 1.32 2006/06/19 20:28:52 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2001-2006 */
|
/* Copyright Gerhard Rieger 2001-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
#ifndef __compat_h_included
|
#ifndef __compat_h_included
|
||||||
|
@ -587,6 +587,8 @@
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define F_thread "%lu"
|
||||||
|
|
||||||
/* Cygwin 1.3.22 has the prototypes, but not the type... */
|
/* Cygwin 1.3.22 has the prototypes, but not the type... */
|
||||||
#ifndef HAVE_TYPE_STAT64
|
#ifndef HAVE_TYPE_STAT64
|
||||||
# undef HAVE_STAT64
|
# undef HAVE_STAT64
|
||||||
|
|
|
@ -444,6 +444,8 @@
|
||||||
#undef HAVE_PROC_DIR_FD
|
#undef HAVE_PROC_DIR_FD
|
||||||
|
|
||||||
#undef WITH_HELP
|
#undef WITH_HELP
|
||||||
|
#undef WITH_NOP
|
||||||
|
#undef WITH_TEST
|
||||||
#undef WITH_STDIO
|
#undef WITH_STDIO
|
||||||
#undef WITH_FDNUM
|
#undef WITH_FDNUM
|
||||||
#undef WITH_FILE
|
#undef WITH_FILE
|
||||||
|
@ -461,6 +463,8 @@
|
||||||
#undef WITH_LISTEN
|
#undef WITH_LISTEN
|
||||||
#undef WITH_SOCKS4
|
#undef WITH_SOCKS4
|
||||||
#undef WITH_SOCKS4A
|
#undef WITH_SOCKS4A
|
||||||
|
#define WITH_SOCKS5 1
|
||||||
|
#define WITH_SOCKS4_SERVER 1
|
||||||
#undef WITH_PROXY
|
#undef WITH_PROXY
|
||||||
#undef WITH_EXEC
|
#undef WITH_EXEC
|
||||||
#undef WITH_SYSTEM
|
#undef WITH_SYSTEM
|
||||||
|
|
16
configure.in
16
configure.in
|
@ -90,6 +90,22 @@ AC_ARG_ENABLE(help, [ --disable-help disable help],
|
||||||
esac],
|
esac],
|
||||||
[AC_DEFINE(WITH_HELP) AC_MSG_RESULT(yes)])
|
[AC_DEFINE(WITH_HELP) AC_MSG_RESULT(yes)])
|
||||||
|
|
||||||
|
AC_MSG_CHECKING(whether to include nop address support)
|
||||||
|
AC_ARG_ENABLE(nop, [ --disable-nop disable nop support],
|
||||||
|
[case "$enableval" in
|
||||||
|
no) AC_MSG_RESULT(no);;
|
||||||
|
*) AC_DEFINE(WITH_NOP) AC_MSG_RESULT(yes);;
|
||||||
|
esac],
|
||||||
|
[AC_DEFINE(WITH_NOP) AC_MSG_RESULT(yes)])
|
||||||
|
|
||||||
|
AC_MSG_CHECKING(whether to include test address support)
|
||||||
|
AC_ARG_ENABLE(test, [ --disable-test disable test support],
|
||||||
|
[case "$enableval" in
|
||||||
|
no) AC_MSG_RESULT(no);;
|
||||||
|
*) AC_DEFINE(WITH_TEST) AC_MSG_RESULT(yes);;
|
||||||
|
esac],
|
||||||
|
[AC_DEFINE(WITH_TEST) AC_MSG_RESULT(yes)])
|
||||||
|
|
||||||
AC_MSG_CHECKING(whether to include STDIO support)
|
AC_MSG_CHECKING(whether to include STDIO support)
|
||||||
AC_ARG_ENABLE(stdio, [ --disable-stdio disable STDIO support],
|
AC_ARG_ENABLE(stdio, [ --disable-stdio disable STDIO support],
|
||||||
[case "$enableval" in
|
[case "$enableval" in
|
||||||
|
|
489
doc/socat.1
489
doc/socat.1
|
@ -1,11 +1,17 @@
|
||||||
.TH "socat" "1" "March 2007" "socat" ""
|
.TH "socat" "1" "July 2006" "socat" ""
|
||||||
.PP
|
.PP
|
||||||
.PP
|
.PP
|
||||||
.SH "NAME"
|
.SH "NAME"
|
||||||
socat \- Multipurpose relay (SOcket CAT)
|
socat \- Multipurpose relay (SOcket CAT)
|
||||||
.PP
|
.PP
|
||||||
.SH "SYNOPSIS"
|
.SH "SYNOPSIS"
|
||||||
\f(CWsocat [options] <address> <address>\fP
|
\f(CWsocat [options] <right-address>\fP
|
||||||
|
.br
|
||||||
|
\f(CWsocat [options] <left-address> <right-address>\fP
|
||||||
|
.br
|
||||||
|
\f(CWsocat [options] <left-address> <right-address> \&.\&.\fP
|
||||||
|
.br
|
||||||
|
\f(CWsocat [options] <left-addresses> \&.\&. -- <right-address> \&.\&.\fP
|
||||||
.br
|
.br
|
||||||
\f(CWsocat -V\fP
|
\f(CWsocat -V\fP
|
||||||
.br
|
.br
|
||||||
|
@ -142,7 +148,7 @@ nothing has happened for <timeout> [timeval] seconds
|
||||||
Useful with protocols like UDP that cannot transfer EOF\&.
|
Useful with protocols like UDP that cannot transfer EOF\&.
|
||||||
.IP "\fB\f(CW-u\fP\fP"
|
.IP "\fB\f(CW-u\fP\fP"
|
||||||
Uses unidirectional mode\&. The first address is only used for reading, and the
|
Uses unidirectional mode\&. The first address is only used for reading, and the
|
||||||
second address is only used for writing (example)\&.
|
second address is only used for writing\&.
|
||||||
.IP "\fB\f(CW-U\fP\fP"
|
.IP "\fB\f(CW-U\fP\fP"
|
||||||
Uses unidirectional mode in reverse direction\&. The first address is only
|
Uses unidirectional mode in reverse direction\&. The first address is only
|
||||||
used for writing, and the second address is only used for reading\&.
|
used for writing, and the second address is only used for reading\&.
|
||||||
|
@ -252,7 +258,7 @@ path, the \f(CWexecvp()\fP semantics for finding the program via
|
||||||
\f(CW$PATH\fP
|
\f(CW$PATH\fP
|
||||||
apply\&. After successful program start, \fBsocat\fP writes data to stdin of the
|
apply\&. After successful program start, \fBsocat\fP writes data to stdin of the
|
||||||
process and reads from its stdout using a UNIX domain socket generated by
|
process and reads from its stdout using a UNIX domain socket generated by
|
||||||
\f(CWsocketpair()\fP per default\&. (example)
|
\f(CWsocketpair()\fP per default\&.
|
||||||
.br
|
.br
|
||||||
Option groups: FD,SOCKET,EXEC,FORK,TERMIOS
|
Option groups: FD,SOCKET,EXEC,FORK,TERMIOS
|
||||||
.br
|
.br
|
||||||
|
@ -294,7 +300,7 @@ In case of a UNIX domain socket, \fBsocat\fP connects; if connecting fails,
|
||||||
If the entry is not a socket, \fBsocat\fP opens it applying the \f(CWO_APPEND\fP
|
If the entry is not a socket, \fBsocat\fP opens it applying the \f(CWO_APPEND\fP
|
||||||
flag\&.
|
flag\&.
|
||||||
If it does not exist, it is opened with flag
|
If it does not exist, it is opened with flag
|
||||||
\f(CWO_CREAT\fP as a regular file (example)\&.
|
\f(CWO_CREAT\fP as a regular file\&.
|
||||||
.br
|
.br
|
||||||
Option groups: FD,REG,SOCKET,NAMED,OPEN
|
Option groups: FD,REG,SOCKET,NAMED,OPEN
|
||||||
.br
|
.br
|
||||||
|
@ -315,7 +321,9 @@ Option groups: FD,SOCKET,IP4,IP6
|
||||||
.br
|
.br
|
||||||
Useful options:
|
Useful options:
|
||||||
pf,
|
pf,
|
||||||
ttl
|
ttl,
|
||||||
|
broadcast
|
||||||
|
.br
|
||||||
See also:
|
See also:
|
||||||
IP4-SENDTO,
|
IP4-SENDTO,
|
||||||
IP6-SENDTO,
|
IP6-SENDTO,
|
||||||
|
@ -334,52 +342,6 @@ Like IP-SENDTO, but always uses IPv6\&.
|
||||||
Option groups: FD,SOCKET,IP6
|
Option groups: FD,SOCKET,IP6
|
||||||
.br
|
.br
|
||||||
.IP
|
.IP
|
||||||
.IP "\fB\f(CWIP-DATAGRAM:<address>:<protocol>\fP\fP"
|
|
||||||
Sends outgoing data to the specified address which may in particular be a
|
|
||||||
broadcast or multicast address\&. Packets arriving on the local socket are
|
|
||||||
checked if their source addresses match
|
|
||||||
eventual RANGE or TCPWRAP
|
|
||||||
options\&. This address type can for example be used for implementing
|
|
||||||
symmetric or asymmetric broadcast or multicast communications\&.
|
|
||||||
.br
|
|
||||||
Option groups: FD, SOCKET,
|
|
||||||
IP4, IP6, RANGE
|
|
||||||
.br
|
|
||||||
Useful options:
|
|
||||||
range,
|
|
||||||
tcpwrap,
|
|
||||||
broadcast,
|
|
||||||
ip-multicast-loop,
|
|
||||||
ip-multicast-ttl,
|
|
||||||
ip-multicast-if,
|
|
||||||
ip-add-membership,
|
|
||||||
ttl,
|
|
||||||
tos,
|
|
||||||
bind,
|
|
||||||
pf
|
|
||||||
.br
|
|
||||||
See also:
|
|
||||||
IP4-DATAGRAM,
|
|
||||||
IP6-DATAGRAM,
|
|
||||||
IP-SENDTO,
|
|
||||||
IP-RECVFROM,
|
|
||||||
IP-RECV,
|
|
||||||
UDP-DATAGRAM
|
|
||||||
.IP "\fB\f(CWIP4-DATAGRAM:<host>:<protocol>\fP\fP"
|
|
||||||
Like IP-DATAGRAM, but always uses IPv4\&.
|
|
||||||
(example)
|
|
||||||
.br
|
|
||||||
Option groups: FD, SOCKET,
|
|
||||||
IP4, RANGE
|
|
||||||
.br
|
|
||||||
.IP "\fB\f(CWIP6-DATAGRAM:<host>:<protocol>\fP\fP"
|
|
||||||
Like IP-DATAGRAM, but always uses IPv6\&. Please
|
|
||||||
note that IPv6 does not know broadcasts\&.
|
|
||||||
.br
|
|
||||||
Option groups: FD, SOCKET,
|
|
||||||
IP6, RANGE
|
|
||||||
.br
|
|
||||||
.IP
|
|
||||||
.IP "\fB\f(CWIP-RECVFROM:<protocol>\fP\fP"
|
.IP "\fB\f(CWIP-RECVFROM:<protocol>\fP\fP"
|
||||||
Opens a raw IP socket of <protocol>\&. Depending on option pf, IP procotol version
|
Opens a raw IP socket of <protocol>\&. Depending on option pf, IP procotol version
|
||||||
4 or 6 is used\&. It receives one packet from an unspecified peer and may send one or more answer packets to that peer\&.
|
4 or 6 is used\&. It receives one packet from an unspecified peer and may send one or more answer packets to that peer\&.
|
||||||
|
@ -449,8 +411,7 @@ Option groups: FD,SOCKET,IP6,RANGE
|
||||||
.br
|
.br
|
||||||
.IP
|
.IP
|
||||||
.IP "\fB\f(CWOPEN:<filename>\fP\fP"
|
.IP "\fB\f(CWOPEN:<filename>\fP\fP"
|
||||||
Opens <filename> using the \f(CWopen()\fP system call
|
Opens <filename> using the \f(CWopen()\fP system call\&.
|
||||||
(example)\&.
|
|
||||||
This operation fails on UNIX domain sockets\&.
|
This operation fails on UNIX domain sockets\&.
|
||||||
.br
|
.br
|
||||||
Note: This address type is rarly useful in bidirectional mode\&.
|
Note: This address type is rarly useful in bidirectional mode\&.
|
||||||
|
@ -510,9 +471,11 @@ connection is accepted, this address behaves as SSL server\&.
|
||||||
.br
|
.br
|
||||||
Note: You probably want to use the certificate option with this address\&.
|
Note: You probably want to use the certificate option with this address\&.
|
||||||
.br
|
.br
|
||||||
NOTE: The client certificate is only checked for validity against
|
NOTE: Without verify option, the client certificate is
|
||||||
cafile or capath,
|
not checked\&. Even with verify option, the client
|
||||||
but not for match with the client\'s name or its IP address!
|
certificate is only checked for validity against cafile
|
||||||
|
or capath, but not for match with the client\'s name or
|
||||||
|
its IP address!
|
||||||
.br
|
.br
|
||||||
Option groups: FD,SOCKET,IP4,IP6,TCP,LISTEN,OPENSSL,CHILD,RANGE,RETRY
|
Option groups: FD,SOCKET,IP4,IP6,TCP,LISTEN,OPENSSL,CHILD,RANGE,RETRY
|
||||||
.br
|
.br
|
||||||
|
@ -596,11 +559,12 @@ retry
|
||||||
.br
|
.br
|
||||||
See also: SOCKS, TCP
|
See also: SOCKS, TCP
|
||||||
.IP "\fB\f(CWPTY\fP\fP"
|
.IP "\fB\f(CWPTY\fP\fP"
|
||||||
|
.IP "\fB\f(CWPTY:<symlink>\fP\fP"
|
||||||
Generates a pseudo terminal (pty) and uses its master side\&. Another process
|
Generates a pseudo terminal (pty) and uses its master side\&. Another process
|
||||||
may open the pty\'s slave side using it like a serial line or terminal\&.
|
may open the pty\'s slave side using it like a serial line or terminal\&. If
|
||||||
(example)\&. If
|
|
||||||
both the ptmx and the openpty mechanisms are available, ptmx is used
|
both the ptmx and the openpty mechanisms are available, ptmx is used
|
||||||
(POSIX)\&.
|
(POSIX)\&. In the second form, the link option is
|
||||||
|
already integrated as a parameter\&.
|
||||||
.br
|
.br
|
||||||
Option groups: FD,NAMED,PTY,TERMIOS
|
Option groups: FD,NAMED,PTY,TERMIOS
|
||||||
.br
|
.br
|
||||||
|
@ -618,7 +582,7 @@ PIPE,
|
||||||
EXEC, SYSTEM
|
EXEC, SYSTEM
|
||||||
.IP "\fB\f(CWREADLINE\fP\fP"
|
.IP "\fB\f(CWREADLINE\fP\fP"
|
||||||
Uses GNU readline and history on stdio to allow editing and reusing input
|
Uses GNU readline and history on stdio to allow editing and reusing input
|
||||||
lines (example)\&. This requires the GNU readline and
|
lines\&. This requires the GNU readline and
|
||||||
history libraries\&. Note that stdio should be a (pseudo) terminal device,
|
history libraries\&. Note that stdio should be a (pseudo) terminal device,
|
||||||
otherwise readline does not seem to work\&.
|
otherwise readline does not seem to work\&.
|
||||||
.br
|
.br
|
||||||
|
@ -635,7 +599,7 @@ Connects via <socks-server> [IP address]
|
||||||
to <host> [IPv4 address]
|
to <host> [IPv4 address]
|
||||||
on <port> [TCP service],
|
on <port> [TCP service],
|
||||||
using socks version 4 protocol over IP version 4 or 6 depending on address specification, name resolution, or option
|
using socks version 4 protocol over IP version 4 or 6 depending on address specification, name resolution, or option
|
||||||
pf (example)\&.
|
pf\&.
|
||||||
.br
|
.br
|
||||||
Option groups: FD,SOCKET,IP4,IP6,TCP,SOCKS4,RETRY
|
Option groups: FD,SOCKET,IP4,IP6,TCP,SOCKS4,RETRY
|
||||||
.br
|
.br
|
||||||
|
@ -743,7 +707,7 @@ TCP-LISTEN,
|
||||||
UDP,
|
UDP,
|
||||||
UNIX-CONNECT
|
UNIX-CONNECT
|
||||||
.IP "\fB\f(CWTCP4:<host>:<port>\fP\fP"
|
.IP "\fB\f(CWTCP4:<host>:<port>\fP\fP"
|
||||||
Like TCP, but only supports IPv4 protocol (example)\&.
|
Like TCP, but only supports IPv4 protocol\&.
|
||||||
.br
|
.br
|
||||||
Option groups: FD,SOCKET,IP4,TCP,RETRY
|
Option groups: FD,SOCKET,IP4,TCP,RETRY
|
||||||
.br
|
.br
|
||||||
|
@ -783,7 +747,7 @@ UNIX-LISTEN,
|
||||||
OPENSSL-LISTEN
|
OPENSSL-LISTEN
|
||||||
.IP "\fB\f(CWTCP4-LISTEN:<port>\fP\fP"
|
.IP "\fB\f(CWTCP4-LISTEN:<port>\fP\fP"
|
||||||
Like TCP-LISTEN, but only supports IPv4
|
Like TCP-LISTEN, but only supports IPv4
|
||||||
protocol (example)\&.
|
protocol\&.
|
||||||
.br
|
.br
|
||||||
Option groups: FD,SOCKET,LISTEN,CHILD,RANGE,IP4,TCP,RETRY
|
Option groups: FD,SOCKET,LISTEN,CHILD,RANGE,IP4,TCP,RETRY
|
||||||
.br
|
.br
|
||||||
|
@ -796,23 +760,7 @@ ipv6only
|
||||||
.br
|
.br
|
||||||
Option groups: FD,SOCKET,LISTEN,CHILD,RANGE,IP6,TCP,RETRY
|
Option groups: FD,SOCKET,LISTEN,CHILD,RANGE,IP6,TCP,RETRY
|
||||||
.br
|
.br
|
||||||
.IP "\fB\f(CWTUN:<if-addr>/<bits>\fP\fP"
|
.IP
|
||||||
Creates a Linux TUN/TAP device and assignes to it the address and netmask
|
|
||||||
defined by the parameters\&. The resulting network interface is ready for use
|
|
||||||
by other processes; socat serves its "wire side"\&. This address requires read
|
|
||||||
and write access to the tunnel cloning device, usually \f(CW/dev/net/tun\fP\&.
|
|
||||||
.br
|
|
||||||
Option groups: FD,NAMED,OPEN,TUN
|
|
||||||
.br
|
|
||||||
Useful options:
|
|
||||||
iff-up,
|
|
||||||
tun-device,
|
|
||||||
tun-name,
|
|
||||||
tun-type,
|
|
||||||
iff-no-pi
|
|
||||||
.br
|
|
||||||
See also:
|
|
||||||
ip-recv
|
|
||||||
.IP "\fB\f(CWUDP:<host>:<port>\fP\fP"
|
.IP "\fB\f(CWUDP:<host>:<port>\fP\fP"
|
||||||
Connects to <port> [UDP service] on
|
Connects to <port> [UDP service] on
|
||||||
<host> [IP address] using UDP/IP version 4 or 6
|
<host> [IP address] using UDP/IP version 4 or 6
|
||||||
|
@ -849,60 +797,14 @@ Like UDP, but only supports IPv6 protocol\&.
|
||||||
.br
|
.br
|
||||||
Option groups: FD,SOCKET,IP6
|
Option groups: FD,SOCKET,IP6
|
||||||
.br
|
.br
|
||||||
.IP "\fB\f(CWUDP-DATAGRAM:<address>:<port>\fP\fP"
|
.IP
|
||||||
Sends outgoing data to the specified address which may in particular be a
|
|
||||||
broadcast or multicast address\&. Packets arriving on the local socket are
|
|
||||||
checked for the correct remote port and if their source addresses match
|
|
||||||
eventual RANGE or TCPWRAP
|
|
||||||
options\&. This address type can for example be used for implementing
|
|
||||||
symmetric or asymmetric broadcast or multicast communications\&.
|
|
||||||
.br
|
|
||||||
Option groups: FD,SOCKET,IP4,IP6,RANGE
|
|
||||||
.br
|
|
||||||
Useful options:
|
|
||||||
range,
|
|
||||||
tcpwrap,
|
|
||||||
broadcast,
|
|
||||||
ip-multicast-loop,
|
|
||||||
ip-multicast-ttl,
|
|
||||||
ip-multicast-if,
|
|
||||||
ip-add-membership,
|
|
||||||
ttl,
|
|
||||||
tos,
|
|
||||||
bind,
|
|
||||||
sourceport,
|
|
||||||
pf
|
|
||||||
.br
|
|
||||||
See also:
|
|
||||||
UDP4-DATAGRAM,
|
|
||||||
UDP6-DATAGRAM,
|
|
||||||
UDP-SENDTO,
|
|
||||||
UDP-RECVFROM,
|
|
||||||
UDP-RECV,
|
|
||||||
UDP-CONNECT,
|
|
||||||
UDP-LISTEN,
|
|
||||||
IP-DATAGRAM
|
|
||||||
.IP "\fB\f(CWUDP4-DATAGRAM:<address>:<port>\fP\fP"
|
|
||||||
Like UDP-DATAGRAM, but only supports IPv4
|
|
||||||
protocol (example1,
|
|
||||||
example2)\&.
|
|
||||||
.br
|
|
||||||
Option groups: FD, SOCKET,
|
|
||||||
IP4, RANGE
|
|
||||||
.IP "\fB\f(CWUDP6-DATAGRAM:<address>:<port>\fP\fP"
|
|
||||||
Like UDP-DATAGRAM, but only supports IPv6
|
|
||||||
protocol\&.
|
|
||||||
.br
|
|
||||||
Option groups: FD,SOCKET,
|
|
||||||
IP6,RANGE
|
|
||||||
.IP "\fB\f(CWUDP-LISTEN:<port>\fP\fP"
|
.IP "\fB\f(CWUDP-LISTEN:<port>\fP\fP"
|
||||||
Waits for a UDP/IP packet arriving on <port>
|
Waits for a UDP/IP packet arriving on <port>
|
||||||
[UDP service] and `connects\' back to sender\&.
|
[UDP service] and `connects\' back to sender\&.
|
||||||
The accepted IP version is 4 or the one specified with option
|
The accepted IP version is 4 or the one specified with option
|
||||||
pf\&.
|
pf\&.
|
||||||
Please note that,
|
Please note that,
|
||||||
due to UDP protocol properties, no real connection is established; data has
|
due to UDP protocol properties, no real connection is established; data has to arrive from the peer first, and no end-of-file condition can be
|
||||||
to arrive from the peer first, and no end-of-file condition can be
|
|
||||||
transported\&. Note that opening
|
transported\&. Note that opening
|
||||||
this address usually blocks until a client connects\&.
|
this address usually blocks until a client connects\&.
|
||||||
.br
|
.br
|
||||||
|
@ -931,14 +833,13 @@ protocol\&.
|
||||||
.br
|
.br
|
||||||
Option groups: FD,SOCKET,LISTEN,CHILD,RANGE,IP6
|
Option groups: FD,SOCKET,LISTEN,CHILD,RANGE,IP6
|
||||||
.br
|
.br
|
||||||
|
.IP
|
||||||
.IP "\fB\f(CWUDP-SENDTO:<host>:<port>\fP\fP"
|
.IP "\fB\f(CWUDP-SENDTO:<host>:<port>\fP\fP"
|
||||||
Communicates with the specified peer socket, defined by <port> [UDP
|
Communicates with the specified peer socket, defined by <port> [UDP service] on
|
||||||
service] on
|
|
||||||
<host> [IP address], using UDP/IP version 4 or 6
|
<host> [IP address], using UDP/IP version 4 or 6
|
||||||
depending on address specification, name resolution, or option
|
depending on address specification, name resolution, or option
|
||||||
pf\&. It sends packets to and receives packets
|
pf\&. It sends packets to and receives packets from that peer socket only\&.
|
||||||
from that peer socket only\&.
|
This is effectively a datagram client\&.
|
||||||
This address effectively implements a datagram client\&.
|
|
||||||
It works well with socat UDP-RECVFROM and UDP-RECV address peers\&.
|
It works well with socat UDP-RECVFROM and UDP-RECV address peers\&.
|
||||||
.br
|
.br
|
||||||
Option groups: FD,SOCKET,IP4,IP6
|
Option groups: FD,SOCKET,IP4,IP6
|
||||||
|
@ -959,23 +860,19 @@ UDP-CONNECT,
|
||||||
UDP-LISTEN,
|
UDP-LISTEN,
|
||||||
IP-SENDTO
|
IP-SENDTO
|
||||||
.IP "\fB\f(CWUDP4-SENDTO:<host>:<port>\fP\fP"
|
.IP "\fB\f(CWUDP4-SENDTO:<host>:<port>\fP\fP"
|
||||||
Like UDP-SENDTO, but only supports IPv4
|
Like UDP-SENDTO, but only supports IPv4 protocol\&.
|
||||||
protocol\&.
|
|
||||||
.br
|
.br
|
||||||
Option groups: FD,SOCKET,IP4
|
Option groups: FD,SOCKET,IP4
|
||||||
.IP "\fB\f(CWUDP6-SENDTO:<host>:<port>\fP\fP"
|
.IP "\fB\f(CWUDP6-SENDTO:<host>:<port>\fP\fP"
|
||||||
Like UDP-SENDTO, but only supports IPv6
|
Like UDP-SENDTO, but only supports IPv6 protocol\&.
|
||||||
protocol\&.
|
|
||||||
.br
|
.br
|
||||||
Option groups: FD,SOCKET,IP6
|
Option groups: FD,SOCKET,IP6
|
||||||
.IP
|
.IP
|
||||||
.IP "\fB\f(CWUDP-RECVFROM:<port>\fP\fP"
|
.IP "\fB\f(CWUDP-RECVFROM:<port>\fP\fP"
|
||||||
Creates a UDP socket on <port> [UDP service] using
|
Creates a UDP socket on <port> [UDP service] using UDP/IP version 4 or 6
|
||||||
UDP/IP version 4 or 6
|
|
||||||
depending on option pf\&.
|
depending on option pf\&.
|
||||||
It receives one packet from an unspecified peer and may send one or more
|
It receives one packet from an unspecified peer and may send one or more
|
||||||
answer packets to that peer\&. This mode is particularly useful with fork
|
answer packets to that peer\&. This mode is particularly useful with fork option
|
||||||
option
|
|
||||||
where each arriving packet - from arbitrary peers - is handled by its own sub
|
where each arriving packet - from arbitrary peers - is handled by its own sub
|
||||||
process\&. This allows a behaviour similar to typical UDP based servers like ntpd
|
process\&. This allows a behaviour similar to typical UDP based servers like ntpd
|
||||||
or named\&. This address works well with socat SENDTO address peers\&.
|
or named\&. This address works well with socat SENDTO address peers\&.
|
||||||
|
@ -1012,7 +909,8 @@ Option groups: FD,SOCKET,IP6,CHILD,RANGE
|
||||||
Creates a UDP socket on <port> [UDP service] using UDP/IP version 4 or 6
|
Creates a UDP socket on <port> [UDP service] using UDP/IP version 4 or 6
|
||||||
depending on option pf\&.
|
depending on option pf\&.
|
||||||
It receives packets from multiple unspecified peers and merges the data\&.
|
It receives packets from multiple unspecified peers and merges the data\&.
|
||||||
No replies are possible\&. It works well with, e\&.g\&., socat UDP-SENDTO address peers; it behaves similar to a syslog server\&.
|
No replies are possible\&. It can be, e\&.g\&., addressed by socat UDP-SENDTO address peers\&.
|
||||||
|
This address works well with socat SENDTO address peers; it behaves similar to a syslog server\&.
|
||||||
.br
|
.br
|
||||||
Option groups: FD,SOCKET,IP4,IP6,RANGE
|
Option groups: FD,SOCKET,IP4,IP6,RANGE
|
||||||
.br
|
.br
|
||||||
|
@ -1050,9 +948,7 @@ if <filename> is not a UNIX domain socket, this is an error;
|
||||||
if <filename> is a UNIX domain socket, but no process is listening, this is
|
if <filename> is a UNIX domain socket, but no process is listening, this is
|
||||||
an error\&.
|
an error\&.
|
||||||
.br
|
.br
|
||||||
Option groups: FD,SOCKET,
|
Option groups: FD,SOCKET,NAMED,RETRY
|
||||||
NAMED,RETRY,
|
|
||||||
UNIX
|
|
||||||
.br
|
.br
|
||||||
)
|
)
|
||||||
Useful options:
|
Useful options:
|
||||||
|
@ -1071,12 +967,9 @@ If <filename> exists and is a UNIX domain socket, binding to the address
|
||||||
fails (use option unlink-early!)\&.
|
fails (use option unlink-early!)\&.
|
||||||
Note that opening this address usually blocks until a client connects\&.
|
Note that opening this address usually blocks until a client connects\&.
|
||||||
Beginning with socat version 1\&.4\&.3, the file system entry is removed when
|
Beginning with socat version 1\&.4\&.3, the file system entry is removed when
|
||||||
this address is closed (but see option unlink-close) (example)\&.
|
this address is closed (but see option unlink-close)\&.
|
||||||
.br
|
.br
|
||||||
Option groups: FD,SOCKET,
|
Option groups: FD,SOCKET,NAMED,LISTEN,CHILD,RETRY
|
||||||
NAMED,LISTEN,
|
|
||||||
CHILD,RETRY,
|
|
||||||
UNIX
|
|
||||||
.br
|
.br
|
||||||
Useful options:
|
Useful options:
|
||||||
fork,
|
fork,
|
||||||
|
@ -1097,8 +990,7 @@ Communicates with the specified peer socket, defined by [<filename>] assuming it
|
||||||
It sends packets to and receives packets from that peer socket only\&.
|
It sends packets to and receives packets from that peer socket only\&.
|
||||||
It works well with socat UNIX-RECVFROM and UNIX-RECV address peers\&.
|
It works well with socat UNIX-RECVFROM and UNIX-RECV address peers\&.
|
||||||
.br
|
.br
|
||||||
Option groups: FD,SOCKET,
|
Option groups: FD,SOCKET,NAMED
|
||||||
NAMED,UNIX
|
|
||||||
.br
|
.br
|
||||||
Useful options:
|
Useful options:
|
||||||
bind
|
bind
|
||||||
|
@ -1116,9 +1008,7 @@ Receives one packet and may send one or more answer packets to that peer\&.
|
||||||
This mode is particularly useful with fork option where each arriving packet - from arbitrary peers - is handled by its own sub process\&.
|
This mode is particularly useful with fork option where each arriving packet - from arbitrary peers - is handled by its own sub process\&.
|
||||||
This address works well with socat UNIX-SENDTO address peers\&.
|
This address works well with socat UNIX-SENDTO address peers\&.
|
||||||
.br
|
.br
|
||||||
Option groups: FD,SOCKET,
|
Option groups: FD,SOCKET,NAMED,CHILD
|
||||||
NAMED,CHILD,
|
|
||||||
UNIX
|
|
||||||
.br
|
.br
|
||||||
Useful options:
|
Useful options:
|
||||||
fork
|
fork
|
||||||
|
@ -1135,8 +1025,7 @@ Creates a UNIX domain datagram socket [<filename>]\&.
|
||||||
Receives packets from multiple unspecified peers and merges the data\&.
|
Receives packets from multiple unspecified peers and merges the data\&.
|
||||||
No replies are possible\&. It can be, e\&.g\&., addressed by socat UNIX-SENDTO address peers\&.
|
No replies are possible\&. It can be, e\&.g\&., addressed by socat UNIX-SENDTO address peers\&.
|
||||||
It behaves similar to a syslog server\&.
|
It behaves similar to a syslog server\&.
|
||||||
Option groups: FD,SOCKET,
|
Option groups: FD,SOCKET,NAMED
|
||||||
NAMED,UNIX
|
|
||||||
.br
|
.br
|
||||||
See also:
|
See also:
|
||||||
UNIX-SENDTO,
|
UNIX-SENDTO,
|
||||||
|
@ -1145,14 +1034,13 @@ UNIX-LISTEN,
|
||||||
UDP-RECV,
|
UDP-RECV,
|
||||||
IP-RECV
|
IP-RECV
|
||||||
.IP
|
.IP
|
||||||
.IP "\fB\f(CWUNIX-CLIENT:<filename>\fP\fP"
|
.IP "\fB\f(CWUNIX:<filename>\fP\fP"
|
||||||
Communicates with the specified peer socket, defined by
|
Communicates with the specified peer socket, defined by
|
||||||
[<filename>] assuming it is a UNIX domain socket\&.
|
[<filename>] assuming it is a UNIX domain socket\&.
|
||||||
It first tries to connect and, if that fails, assumes it is a datagram
|
It first tries to connect and, if that fails, assumes it is a datagram
|
||||||
socket, thus supporting both types\&.
|
socket, thus supporting both types\&.
|
||||||
.br
|
.br
|
||||||
Option groups: FD,SOCKET,
|
Option groups: FD,SOCKET,NAMED
|
||||||
NAMED,UNIX
|
|
||||||
.br
|
.br
|
||||||
Useful options:
|
Useful options:
|
||||||
bind
|
bind
|
||||||
|
@ -1161,19 +1049,6 @@ See also:
|
||||||
UNIX-CONNECT,
|
UNIX-CONNECT,
|
||||||
UNIX-SENDTO,
|
UNIX-SENDTO,
|
||||||
GOPEN
|
GOPEN
|
||||||
.IP
|
|
||||||
.IP "\fB\f(CWABSTRACT-CONNECT:<string>\fP\fP"
|
|
||||||
.IP "\fB\f(CWABSTRACT-LISTEN:<string>\fP\fP"
|
|
||||||
.IP "\fB\f(CWABSTRACT-SENDTO:<string>\fP\fP"
|
|
||||||
.IP "\fB\f(CWABSTRACT-RECVFROM:<string>\fP\fP"
|
|
||||||
.IP "\fB\f(CWABSTRACT-RECV:<string>\fP\fP"
|
|
||||||
.IP "\fB\f(CWABSTRACT-CLIENT:<string>\fP\fP"
|
|
||||||
The ABSTRACT addresses are almost identical to the related UNIX addresses
|
|
||||||
except that they do not address file system based sockets but an alternate
|
|
||||||
UNIX domain address space\&. To archieve this the socket address strings are
|
|
||||||
prefixed with "\e0" internally\&. This feature is available (only?) on Linux\&.
|
|
||||||
Option groups are the same as with the related UNIX addresses, except that
|
|
||||||
the ABSTRACT addresses are not member of the NAMED group\&.
|
|
||||||
.PP
|
.PP
|
||||||
.SH "ADDRESS OPTIONS"
|
.SH "ADDRESS OPTIONS"
|
||||||
.PP
|
.PP
|
||||||
|
@ -1248,37 +1123,20 @@ internally handles
|
||||||
this flag for the fds it controls, so in most cases there will be no need to
|
this flag for the fds it controls, so in most cases there will be no need to
|
||||||
apply this option\&.
|
apply this option\&.
|
||||||
.IP "\fB\f(CWsetlk\fP\fP"
|
.IP "\fB\f(CWsetlk\fP\fP"
|
||||||
Tries to set a discretionary write lock to the whole file using the \f(CWfcntl(fd,
|
Tries to set a discretionary lock to the whole file using the \f(CWfcntl(fd,
|
||||||
F_SETLK, \&.\&.\&.)\fP system call\&. If the file is already locked, this call results
|
F_SETLK, \&.\&.\&.)\fP system call\&. If the file is already locked, this call results
|
||||||
in an error\&.
|
in an error\&.
|
||||||
On Linux, when the file permissions for group are "S" (g-x,g+s), and the
|
|
||||||
file system is locally mounted with the "mand" option, the lock is
|
|
||||||
mandatory, i\&.e\&. prevents other processes from opening the file\&.
|
|
||||||
.IP "\fB\f(CWsetlkw\fP\fP"
|
.IP "\fB\f(CWsetlkw\fP\fP"
|
||||||
Tries to set a discretionary waiting write lock to the whole file using the
|
Tries to set a discretionary waiting lock to the whole file using the
|
||||||
\f(CWfcntl(fd, F_SETLKW, \&.\&.\&.)\fP system call\&. If the file is already locked,
|
\f(CWfcntl(fd, F_SETLKW, \&.\&.\&.)\fP system call\&. If the file is already locked,
|
||||||
this call blocks\&.
|
this call blocks\&.
|
||||||
See option setlk for information about making this
|
|
||||||
lock mandatory\&.
|
|
||||||
.IP "\fB\f(CWsetlk-rd\fP\fP"
|
|
||||||
Tries to set a discretionary read lock to the whole file using the \f(CWfcntl(fd,
|
|
||||||
F_SETLK, \&.\&.\&.)\fP system call\&. If the file is already write locked, this call
|
|
||||||
results in an error\&.
|
|
||||||
See option setlk for information about making this
|
|
||||||
lock mandatory\&.
|
|
||||||
.IP "\fB\f(CWsetlkw-rd\fP\fP"
|
|
||||||
Tries to set a discretionary waiting read lock to the whole file using the
|
|
||||||
\f(CWfcntl(fd, F_SETLKW, \&.\&.\&.)\fP system call\&. If the file is already write
|
|
||||||
locked, this call blocks\&.
|
|
||||||
See option setlk for information about making this
|
|
||||||
lock mandatory\&.
|
|
||||||
.IP "\fB\f(CWflock-ex\fP\fP"
|
.IP "\fB\f(CWflock-ex\fP\fP"
|
||||||
Tries to set a blocking exclusive advisory lock to the file using the
|
Tries to set a blocking exclusive advisory lock to the file using the
|
||||||
\f(CWflock(fd, LOCK_EX)\fP system call\&. \fBSocat\fP hangs in this call if the file
|
\f(CWflock(fd, LOCK_EX)\fP system call\&. \fBSocat\fP hangs in this call if the file
|
||||||
is locked by another process\&.
|
is locked by another process\&.
|
||||||
.IP "\fB\f(CWflock-ex-nb\fP\fP"
|
.IP "\fB\f(CWflock-ex-nb\fP\fP"
|
||||||
Tries to set a nonblocking exclusive advisory lock to the file using the
|
Tries to set a nonblocking exclusive advisory lock to the file using the
|
||||||
\f(CWflock(fd, LOCK_EX|LOCK_NB)\fP system call\&. If the file is already locked,
|
\f(CWflock(fd, LOCK_EX)\fP system call\&. If the file is already locked,
|
||||||
this option results in an error\&.
|
this option results in an error\&.
|
||||||
.IP "\fB\f(CWflock-sh\fP\fP"
|
.IP "\fB\f(CWflock-sh\fP\fP"
|
||||||
Tries to set a blocking shared advisory lock to the file using the
|
Tries to set a blocking shared advisory lock to the file using the
|
||||||
|
@ -1291,7 +1149,7 @@ this option results in an error\&.
|
||||||
.IP "\fB\f(CWlock\fP\fP"
|
.IP "\fB\f(CWlock\fP\fP"
|
||||||
Sets a blocking lock on the file\&. Uses the setlk or flock mechanism
|
Sets a blocking lock on the file\&. Uses the setlk or flock mechanism
|
||||||
depending on availability on the particular platform\&. If both are available,
|
depending on availability on the particular platform\&. If both are available,
|
||||||
the POSIX variant (setlkw) is used\&.
|
the POSIX variant (setlkw) is selected\&.
|
||||||
.IP "\fB\f(CWuser=<user>\fP\fP"
|
.IP "\fB\f(CWuser=<user>\fP\fP"
|
||||||
Sets the <user> (owner) of the stream\&.
|
Sets the <user> (owner) of the stream\&.
|
||||||
If the address is member of the NAMED option group,
|
If the address is member of the NAMED option group,
|
||||||
|
@ -1336,8 +1194,7 @@ This is useful only on file system entries\&.
|
||||||
.IP "\fB\f(CWappend=<bool>\fP\fP"
|
.IP "\fB\f(CWappend=<bool>\fP\fP"
|
||||||
Always writes data to the actual end of file\&.
|
Always writes data to the actual end of file\&.
|
||||||
If the address is member of the OPEN option group,
|
If the address is member of the OPEN option group,
|
||||||
\fBsocat\fP uses the \f(CWO_APPEND\fP flag with the \f(CWopen()\fP system call
|
\fBsocat\fP uses the \f(CWO_APPEND\fP flag with the \f(CWopen()\fP system call\&.
|
||||||
(example)\&.
|
|
||||||
Otherwise, \fBsocat\fP applies the \f(CWfcntl(fd, F_SETFL, O_APPEND)\fP call\&.
|
Otherwise, \fBsocat\fP applies the \f(CWfcntl(fd, F_SETFL, O_APPEND)\fP call\&.
|
||||||
.IP "\fB\f(CWnonblock=<bool>\fP\fP"
|
.IP "\fB\f(CWnonblock=<bool>\fP\fP"
|
||||||
Tries to open or use file in nonblocking mode\&. Its only effects are that the
|
Tries to open or use file in nonblocking mode\&. Its only effects are that the
|
||||||
|
@ -1362,19 +1219,6 @@ when socat is used as a high volume server or proxy where clients often
|
||||||
abort the connection\&.
|
abort the connection\&.
|
||||||
.br
|
.br
|
||||||
This option is experimental\&.
|
This option is experimental\&.
|
||||||
.IP "\fB\f(CWend-close\fP\fP"
|
|
||||||
Changes the (address dependent) method of ending a connection to just close
|
|
||||||
the file descriptors\&. This is useful when the connection is to be reused by
|
|
||||||
or shared with other processes (example)\&.
|
|
||||||
.br
|
|
||||||
Normally, socket connections will be ended with \f(CWshutdown(2)\fP which
|
|
||||||
terminates the socket even if it is shared by multiple processes\&.
|
|
||||||
\f(CWclose(2)\fP "unlinks" the socket from the process but keeps it active as
|
|
||||||
long as there are still links from other processes\&.
|
|
||||||
.br
|
|
||||||
Similarly, when an address of type EXEC or SYSTEM is ended, socat usually
|
|
||||||
will explicitely kill the sub process\&. With this option, it will just close
|
|
||||||
the file descriptors\&.
|
|
||||||
.PP
|
.PP
|
||||||
.br
|
.br
|
||||||
.PP
|
.PP
|
||||||
|
@ -1432,7 +1276,7 @@ E\&.g\&., option `creat\' sets the \f(CWO_CREAT\fP flag\&.
|
||||||
See also options append and
|
See also options append and
|
||||||
nonblock\&.
|
nonblock\&.
|
||||||
.IP "\fB\f(CWcreat=<bool>\fP\fP"
|
.IP "\fB\f(CWcreat=<bool>\fP\fP"
|
||||||
Creates the file if it does not exist (example)\&.
|
Creates the file if it does not exist\&.
|
||||||
.IP "\fB\f(CWdsync=<bool>\fP\fP"
|
.IP "\fB\f(CWdsync=<bool>\fP\fP"
|
||||||
Blocks \f(CWwrite()\fP calls until metainfo is physically written to media\&.
|
Blocks \f(CWwrite()\fP calls until metainfo is physically written to media\&.
|
||||||
.IP "\fB\f(CWexcl=<bool>\fP\fP"
|
.IP "\fB\f(CWexcl=<bool>\fP\fP"
|
||||||
|
@ -1513,7 +1357,7 @@ option FORK,
|
||||||
these options apply to the child processes instead of the main socat process\&.
|
these options apply to the child processes instead of the main socat process\&.
|
||||||
.IP "\fB\f(CWchroot=<directory>\fP\fP"
|
.IP "\fB\f(CWchroot=<directory>\fP\fP"
|
||||||
Performs a \f(CWchroot()\fP operation to <directory>
|
Performs a \f(CWchroot()\fP operation to <directory>
|
||||||
after processing the address (example)\&. This call might require root privilege\&.
|
after processing the address\&. This call might require root privilege\&.
|
||||||
.IP "\fB\f(CWchroot-early=<directory>\fP\fP"
|
.IP "\fB\f(CWchroot-early=<directory>\fP\fP"
|
||||||
Performs a \f(CWchroot()\fP operation to <directory>
|
Performs a \f(CWchroot()\fP operation to <directory>
|
||||||
before opening the address\&. This call might require root privilege\&.
|
before opening the address\&. This call might require root privilege\&.
|
||||||
|
@ -1531,11 +1375,11 @@ Changes the <user> (owner) of the process before opening
|
||||||
the address\&. This call might require root privilege\&.
|
the address\&. This call might require root privilege\&.
|
||||||
.IP "\fB\f(CWsu=<user>\fP\fP"
|
.IP "\fB\f(CWsu=<user>\fP\fP"
|
||||||
Changes the <user> (owner) and groups of the process after
|
Changes the <user> (owner) and groups of the process after
|
||||||
processing the address (example)\&. This call might require root privilege\&.
|
processing the address\&. This call might require root privilege\&.
|
||||||
.IP "\fB\f(CWsu-d=<user>\fP\fP"
|
.IP "\fB\f(CWsu-d=<user>\fP\fP"
|
||||||
Short name for \fB\f(CWsubstuser-delayed\fP\fP\&.
|
Short name for \fB\f(CWsubstuser-delayed\fP\fP\&.
|
||||||
Changes the <user>
|
Changes the <user>
|
||||||
(owner) and groups of the process after processing the address (example)\&.
|
(owner) and groups of the process after processing the address\&.
|
||||||
The user and his groups are retrieved \fIbefore\fP a possible
|
The user and his groups are retrieved \fIbefore\fP a possible
|
||||||
\f(CWchroot()\fP\&. This call might require root privilege\&.
|
\f(CWchroot()\fP\&. This call might require root privilege\&.
|
||||||
.IP "\fB\f(CWsetpgid=<pid_t>\fP\fP"
|
.IP "\fB\f(CWsetpgid=<pid_t>\fP\fP"
|
||||||
|
@ -1544,7 +1388,7 @@ Makes the process a member of the specified process group
|
||||||
is given, or if the value is 0 or 1, the process becomes leader of a new
|
is given, or if the value is 0 or 1, the process becomes leader of a new
|
||||||
process group\&.
|
process group\&.
|
||||||
.IP "\fB\f(CWsetsid\fP\fP"
|
.IP "\fB\f(CWsetsid\fP\fP"
|
||||||
Makes the process the leader of a new session (example)\&.
|
Makes the process the leader of a new session\&.
|
||||||
.PP
|
.PP
|
||||||
.br
|
.br
|
||||||
.PP
|
.PP
|
||||||
|
@ -1552,7 +1396,7 @@ Makes the process the leader of a new session (example)\&.
|
||||||
.PP
|
.PP
|
||||||
These options apply to the readline address type\&.
|
These options apply to the readline address type\&.
|
||||||
.IP "\fB\f(CWhistory=<filename>\fP\fP"
|
.IP "\fB\f(CWhistory=<filename>\fP\fP"
|
||||||
Reads and writes history from/to <filename> (example)\&.
|
Reads and writes history from/to <filename>\&.
|
||||||
.IP "\fB\f(CWnoprompt\fP\fP"
|
.IP "\fB\f(CWnoprompt\fP\fP"
|
||||||
Since version 1\&.4\&.0, socat per default tries to determine a prompt -
|
Since version 1\&.4\&.0, socat per default tries to determine a prompt -
|
||||||
that is then passed to the readline call - by remembering the last
|
that is then passed to the readline call - by remembering the last
|
||||||
|
@ -1566,7 +1410,6 @@ The prompt is defined as the text that was output to the readline address
|
||||||
after the lastest newline character and before an input character was
|
after the lastest newline character and before an input character was
|
||||||
typed\&. The pattern is a regular expression, e\&.g\&.
|
typed\&. The pattern is a regular expression, e\&.g\&.
|
||||||
"^[Pp]assword:\&.*$" or "([Uu]ser:|[Pp]assword:)"\&. See regex(7) for details\&.
|
"^[Pp]assword:\&.*$" or "([Uu]ser:|[Pp]assword:)"\&. See regex(7) for details\&.
|
||||||
(example)
|
|
||||||
.IP "\fB\f(CWprompt=<string>\fP\fP"
|
.IP "\fB\f(CWprompt=<string>\fP\fP"
|
||||||
Passes the string as prompt to the readline function\&. readline prints this
|
Passes the string as prompt to the readline function\&. readline prints this
|
||||||
prompt when stepping through the history\&. If this string matches a constant
|
prompt when stepping through the history\&. If this string matches a constant
|
||||||
|
@ -1586,11 +1429,11 @@ Converts the default line termination character NL (\'\en\', 0x0a) to/from CR
|
||||||
(\'\er\', 0x0d) when writing/reading on this channel\&.
|
(\'\er\', 0x0d) when writing/reading on this channel\&.
|
||||||
.IP "\fB\f(CWcrnl\fP\fP"
|
.IP "\fB\f(CWcrnl\fP\fP"
|
||||||
Converts the default line termination character NL (\'\en\', 0x0a) to/from CRNL
|
Converts the default line termination character NL (\'\en\', 0x0a) to/from CRNL
|
||||||
("\er\en", 0x0d0a) when writing/reading on this channel (example)\&.
|
("\er\en", 0x0d0a) when writing/reading on this channel\&.
|
||||||
Note: socat simply strips all CR characters\&.
|
Note: socat simply strips all CR characters\&.
|
||||||
.IP "\fB\f(CWignoreeof\fP\fP"
|
.IP "\fB\f(CWignoreeof\fP\fP"
|
||||||
When EOF occurs on this channel, \fBsocat\fP ignores it and tries to read more
|
When EOF occurs on this channel, \fBsocat\fP ignores it and tries to read more
|
||||||
data (like "tail -f") (example)\&.
|
data (like "tail -f")\&.
|
||||||
.IP "\fB\f(CWreadbytes=<bytes>\fP\fP"
|
.IP "\fB\f(CWreadbytes=<bytes>\fP\fP"
|
||||||
\fBsocat\fP reads only so many bytes from this address (the address provides
|
\fBsocat\fP reads only so many bytes from this address (the address provides
|
||||||
only so many bytes for transfer and pretends to be at EOF afterwards)\&.
|
only so many bytes for transfer and pretends to be at EOF afterwards)\&.
|
||||||
|
@ -1610,7 +1453,7 @@ These options are intended for all kinds of sockets, e\&.g\&. IP or UNIX domain\
|
||||||
.IP "\fB\f(CWbind=<sockname>\fP\fP"
|
.IP "\fB\f(CWbind=<sockname>\fP\fP"
|
||||||
Binds the socket to the given socket address using the \f(CWbind()\fP system
|
Binds the socket to the given socket address using the \f(CWbind()\fP system
|
||||||
call\&. The form of <sockname> is socket domain dependent:
|
call\&. The form of <sockname> is socket domain dependent:
|
||||||
IP4 and IP6 allow the form [hostname|hostaddress][:(service|port)] (example),
|
IP4 and IP6 allow the form [hostname|hostaddress][:(service|port)],
|
||||||
UNIX domain sockets require <filename>\&.
|
UNIX domain sockets require <filename>\&.
|
||||||
.IP "\fB\f(CWconnect-timeout=<seconds>\fP\fP"
|
.IP "\fB\f(CWconnect-timeout=<seconds>\fP\fP"
|
||||||
Abort the connection attempt after <seconds> [timeval]
|
Abort the connection attempt after <seconds> [timeval]
|
||||||
|
@ -1653,7 +1496,7 @@ the socket layer will pass the buffered data to \fBsocat\fP\&.
|
||||||
Sets the receive timeout [timeval]\&.
|
Sets the receive timeout [timeval]\&.
|
||||||
.IP "\fB\f(CWreuseaddr\fP\fP"
|
.IP "\fB\f(CWreuseaddr\fP\fP"
|
||||||
Allows other sockets to bind to an address even if parts of it (e\&.g\&. the
|
Allows other sockets to bind to an address even if parts of it (e\&.g\&. the
|
||||||
local port) are already in use by \fBsocat\fP (example)\&.
|
local port) are already in use by \fBsocat\fP\&.
|
||||||
.IP "\fB\f(CWsndbuf=<bytes>\fP\fP"
|
.IP "\fB\f(CWsndbuf=<bytes>\fP\fP"
|
||||||
Sets the size of the send buffer after the \f(CWsocket()\fP call to
|
Sets the size of the send buffer after the \f(CWsocket()\fP call to
|
||||||
<bytes> [int]\&.
|
<bytes> [int]\&.
|
||||||
|
@ -1676,14 +1519,6 @@ something like "ip4" or "ip6"\&.
|
||||||
.PP
|
.PP
|
||||||
.br
|
.br
|
||||||
.PP
|
.PP
|
||||||
\fI\fBUNIX option group\fP\fP
|
|
||||||
.PP
|
|
||||||
These options apply to UNIX domain based addresses\&.
|
|
||||||
.IP "\fB\f(CWunix-tightsocklen=[0|1]\fP\fP"
|
|
||||||
On socket operations, pass a socket address length that does not include the
|
|
||||||
whole \f(CWstruct sockaddr_un\fP record but (besides other components) only
|
|
||||||
the relevant part of the filename or abstract string\&. Default is 1\&.
|
|
||||||
.PP
|
|
||||||
\fI\fBIP4 and IP6 option groups\fP\fP
|
\fI\fBIP4 and IP6 option groups\fP\fP
|
||||||
.PP
|
.PP
|
||||||
These options can be used with IPv4 and IPv6 based sockets\&.
|
These options can be used with IPv4 and IPv6 based sockets\&.
|
||||||
|
@ -1706,26 +1541,6 @@ IP options are defined in RFC 791\&.
|
||||||
.IP "\fB\f(CWmtudiscover=<0|1|2>\fP\fP"
|
.IP "\fB\f(CWmtudiscover=<0|1|2>\fP\fP"
|
||||||
Takes 0, 1, 2 to never, want, or always use path MTU discover on this
|
Takes 0, 1, 2 to never, want, or always use path MTU discover on this
|
||||||
socket\&.
|
socket\&.
|
||||||
.IP "\fB\f(CWip-add-membership=<multicast-address:interface-address>\fP\fP"
|
|
||||||
.IP "\fB\f(CWip-add-membership=<multicast-address:interface-name>\fP\fP"
|
|
||||||
.IP "\fB\f(CWip-add-membership=<multicast-address:interface-index>\fP\fP"
|
|
||||||
.IP "\fB\f(CWip-add-membership=<multicast-address:interface-address:interface-name>\fP\fP"
|
|
||||||
.IP "\fB\f(CWip-add-membership=<multicast-address:interface-address:interface-index>\fP\fP"
|
|
||||||
Makes the socket member of the specified multicast group\&. This is currently
|
|
||||||
only implemented for IPv4\&. The option takes the IP address of the multicast
|
|
||||||
group and info about the desired network interface\&. The most common syntax
|
|
||||||
is the first one, while the others are only available on systems that
|
|
||||||
provide \f(CWstruct mreqn\fP (Linux)\&.
|
|
||||||
.br
|
|
||||||
The indices of active network interfaces can be shown using the utility
|
|
||||||
\fBprocan\fP\&.
|
|
||||||
dif(\fB\f(CWip-multicast-if=<hostname>\fP\fP)
|
|
||||||
Specifies hostname or address of the network interface to be used for
|
|
||||||
multicast traffic\&.
|
|
||||||
dif(\fB\f(CWip-multicast-loop=<bool>\fP\fP)
|
|
||||||
Specifies if outgoing multicast traffic should loop back to the interface\&.
|
|
||||||
dif(\fB\f(CWip-multicast-ttl=<byte>\fP\fP)
|
|
||||||
Sets the TTL used for outgoing multicast traffic\&. Default is 1\&.
|
|
||||||
.IP "\fB\f(CWres-debug\fP\fP"
|
.IP "\fB\f(CWres-debug\fP\fP"
|
||||||
.IP "\fB\f(CWres-aaonly\fP\fP"
|
.IP "\fB\f(CWres-aaonly\fP\fP"
|
||||||
.IP "\fB\f(CWres-usevc\fP\fP"
|
.IP "\fB\f(CWres-usevc\fP\fP"
|
||||||
|
@ -1777,8 +1592,7 @@ Sets the time to keep the socket in FIN-WAIT-2 state to <seconds>
|
||||||
.IP "\fB\f(CWmss=<bytes>\fP\fP"
|
.IP "\fB\f(CWmss=<bytes>\fP\fP"
|
||||||
Sets the MSS (maximum segment size) after the \f(CWsocket()\fP call to <bytes>
|
Sets the MSS (maximum segment size) after the \f(CWsocket()\fP call to <bytes>
|
||||||
[int]\&. This
|
[int]\&. This
|
||||||
value is then proposed to the peer with the SYN or SYN/ACK packet
|
value is then proposed to the peer with the SYN or SYN/ACK packet\&.
|
||||||
(example)\&.
|
|
||||||
.IP "\fB\f(CWmss-late=<bytes>\fP\fP"
|
.IP "\fB\f(CWmss-late=<bytes>\fP\fP"
|
||||||
Sets the MSS of the socket after connection has been established to <bytes>
|
Sets the MSS of the socket after connection has been established to <bytes>
|
||||||
[int]\&.
|
[int]\&.
|
||||||
|
@ -1829,7 +1643,7 @@ thus can be used with UDP and TCP, client and server addresses\&.
|
||||||
For outgoing (client) TCP and UDP connections, it sets the source
|
For outgoing (client) TCP and UDP connections, it sets the source
|
||||||
<port> using an extra \f(CWbind()\fP call\&.
|
<port> using an extra \f(CWbind()\fP call\&.
|
||||||
With TCP or UDP listen addresses, socat immediately shuts down the
|
With TCP or UDP listen addresses, socat immediately shuts down the
|
||||||
connection if the client does not use this sourceport (example)\&.
|
connection if the client does not use this sourceport\&.
|
||||||
.IP "\fB\f(CWlowport\fP\fP"
|
.IP "\fB\f(CWlowport\fP\fP"
|
||||||
Outgoing (client) TCP and UDP connections with this option use
|
Outgoing (client) TCP and UDP connections with this option use
|
||||||
an unused random source port between 640 and 1023 incl\&. On UNIX class operating
|
an unused random source port between 640 and 1023 incl\&. On UNIX class operating
|
||||||
|
@ -1849,7 +1663,7 @@ Overrides the default "socks" service or port 1080 for the socks server
|
||||||
port with <TCP service>\&.
|
port with <TCP service>\&.
|
||||||
.IP "\fB\f(CWsocksuser=<user>\fP\fP"
|
.IP "\fB\f(CWsocksuser=<user>\fP\fP"
|
||||||
Sends the <user> [string] in the username field to the
|
Sends the <user> [string] in the username field to the
|
||||||
socks server\&. Default is the actual user name ($LOGNAME or $USER) (example)\&.
|
socks server\&. Default is the actual user name ($LOGNAME or $USER)\&.
|
||||||
.PP
|
.PP
|
||||||
.br
|
.br
|
||||||
.PP
|
.PP
|
||||||
|
@ -1877,20 +1691,19 @@ server unencrypted (base64 encoded) and might be sniffed\&.
|
||||||
.IP "\fB\f(CWresolve\fP\fP"
|
.IP "\fB\f(CWresolve\fP\fP"
|
||||||
Per default, socat sends to the proxy a CONNECT request containing the
|
Per default, socat sends to the proxy a CONNECT request containing the
|
||||||
target hostname\&. With this option, socat resolves the hostname locally and
|
target hostname\&. With this option, socat resolves the hostname locally and
|
||||||
sends the IP address\&. Please note that, according to RFC 2396, only name
|
sends the IP address\&.
|
||||||
resolution to IPv4 addresses is implemented\&.
|
|
||||||
.PP
|
.PP
|
||||||
.br
|
.br
|
||||||
.PP
|
.PP
|
||||||
\fI\fBRANGE option group\fP\fP
|
\fI\fBRANGE option group\fP\fP
|
||||||
.PP
|
.PP
|
||||||
These options check if a connecting client should be granted access\&. They can
|
These options check if a connecting client is granted access\&. They can be
|
||||||
be applied to listening and receiving network sockets\&. tcp-wrappers options
|
applied to listening and receiving network sockets\&. tcp-wrappers options fall
|
||||||
fall into this group\&.
|
into this group\&.
|
||||||
.IP "\fB\f(CWrange=<address-range>\fP\fP"
|
.IP "\fB\f(CWrange=<address-range>\fP\fP"
|
||||||
After accepting a connection, tests if the peer is within \fIrange\fP\&. For
|
After accepting a connection, tests if the peer is within \fIrange\fP\&. For
|
||||||
IPv4 addresses, address-range takes the form address/bits, e\&.g\&.
|
IPv4 addresses, address-range takes the form ww\&.xx\&.yy\&.zz/bits, e\&.g\&.
|
||||||
10\&.0\&.0\&.0/8, or address:mask, e\&.g\&. 10\&.0\&.0\&.0:255\&.0\&.0\&.0 (example); for IPv6, it is [ip6-address/bits], e\&.g\&. [::1/128]\&.
|
10\&.0\&.0\&.0/8; for IPv6, it is [ip6-address/bits], e\&.g\&. [::1/128]\&.
|
||||||
If the client address does not match, \fBsocat\fP issues a warning and keeps
|
If the client address does not match, \fBsocat\fP issues a warning and keeps
|
||||||
listening/receiving\&.
|
listening/receiving\&.
|
||||||
.IP "\fB\f(CWtcpwrap[=<name>]\fP\fP"
|
.IP "\fB\f(CWtcpwrap[=<name>]\fP\fP"
|
||||||
|
@ -1898,7 +1711,7 @@ Uses Wietse Venema\'s libwrap (tcpd) library to determine
|
||||||
if the client is allowed to connect\&. The configuration files are
|
if the client is allowed to connect\&. The configuration files are
|
||||||
/etc/hosts\&.allow and /etc/hosts\&.deny per default, see "man 5 hosts_access"
|
/etc/hosts\&.allow and /etc/hosts\&.deny per default, see "man 5 hosts_access"
|
||||||
for more information\&. The optional <name> (type string)
|
for more information\&. The optional <name> (type string)
|
||||||
is passed to the wrapper functions as daemon process name (example)\&.
|
is passed to the wrapper functions as daemon process name\&.
|
||||||
If omitted, the basename of socats invocation (argv[0]) is passed\&.
|
If omitted, the basename of socats invocation (argv[0]) is passed\&.
|
||||||
If both tcpwrap and range options are applied to an address, both
|
If both tcpwrap and range options are applied to an address, both
|
||||||
conditions must be fulfilled to allow the connection\&.
|
conditions must be fulfilled to allow the connection\&.
|
||||||
|
@ -1927,7 +1740,7 @@ Options for addresses with multiple connections via child processes\&.
|
||||||
.IP "\fB\f(CWfork\fP\fP"
|
.IP "\fB\f(CWfork\fP\fP"
|
||||||
After establishing a connection, handles its channel in a child process and
|
After establishing a connection, handles its channel in a child process and
|
||||||
keeps the parent process attempting to produce more connections, either by
|
keeps the parent process attempting to produce more connections, either by
|
||||||
listening or by connecting in a loop (example)\&.
|
listening or by connecting in a loop\&.
|
||||||
.br
|
.br
|
||||||
SSL-CONNECT and SSL-LISTEN differ in when they actually fork off the child:
|
SSL-CONNECT and SSL-LISTEN differ in when they actually fork off the child:
|
||||||
SSL-LISTEN forks \fIbefore\fP the SSL handshake, while SSL-CONNECT forks
|
SSL-LISTEN forks \fIbefore\fP the SSL handshake, while SSL-CONNECT forks
|
||||||
|
@ -1991,22 +1804,22 @@ created by opening \fB/dev/ptmx\fP or \fB/dev/ptc\fP instead of the default
|
||||||
Establishes communication with the sub process using a pseudo terminal
|
Establishes communication with the sub process using a pseudo terminal
|
||||||
instead of a socket pair\&. Creates the pty with an available mechanism\&. If
|
instead of a socket pair\&. Creates the pty with an available mechanism\&. If
|
||||||
openpty and ptmx are both available, it uses ptmx because this is POSIX
|
openpty and ptmx are both available, it uses ptmx because this is POSIX
|
||||||
compliant (example)\&.
|
compliant\&.
|
||||||
.IP "\fB\f(CWctty\fP\fP"
|
.IP "\fB\f(CWctty\fP\fP"
|
||||||
Makes the pty the controlling tty of the sub process (example)\&.
|
Makes the pty the controlling tty of the sub process\&.
|
||||||
.IP "\fB\f(CWstderr\fP\fP"
|
.IP "\fB\f(CWstderr\fP\fP"
|
||||||
Directs stderr of the sub process to its output channel by making stderr a
|
Directs stderr of the sub process to its output channel by making stderr a
|
||||||
\f(CWdup()\fP of stdout (example)\&.
|
\f(CWdup()\fP of stdout\&.
|
||||||
.IP "\fB\f(CWfdin=<fdnum>\fP\fP"
|
.IP "\fB\f(CWfdin=<fdnum>\fP\fP"
|
||||||
Assigns the sub processes input channel to its file descriptor
|
Assigns the sub processes input channel to its file descriptor
|
||||||
<fdnum>
|
<fdnum>
|
||||||
instead of stdin (0)\&. The program started from the subprocess has to use
|
instead of stdin (0)\&. The program started from the subprocess has to use
|
||||||
this fd for reading data from \fBsocat\fP (example)\&.
|
this fd for reading data from \fBsocat\fP\&.
|
||||||
.IP "\fB\f(CWfdout=<fdnum>\fP\fP"
|
.IP "\fB\f(CWfdout=<fdnum>\fP\fP"
|
||||||
Assigns the sub processes output channel to its file descriptor
|
Assigns the sub processes output channel to its file descriptor
|
||||||
<fdnum>
|
<fdnum>
|
||||||
instead of stdout (1)\&. The program started from the subprocess has to use
|
instead of stdout (1)\&. The program started from the subprocess has to use
|
||||||
this fd for writing data to \fBsocat\fP (example)\&.
|
this fd for writing data to \fBsocat\fP\&.
|
||||||
.IP "\fB\f(CWsighup\fP\fP, \fB\f(CWsigint\fP\fP, \fB\f(CWsigquit\fP\fP"
|
.IP "\fB\f(CWsighup\fP\fP, \fB\f(CWsigint\fP\fP, \fB\f(CWsigquit\fP\fP"
|
||||||
Has \fBsocat\fP pass an eventual signal of this type to the sub process\&.
|
Has \fBsocat\fP pass an eventual signal of this type to the sub process\&.
|
||||||
If no address has this option, socat terminates on these signals\&.
|
If no address has this option, socat terminates on these signals\&.
|
||||||
|
@ -2033,12 +1846,12 @@ Note: On some operating systems, these options may not be
|
||||||
available\&. Use ispeed or ospeed
|
available\&. Use ispeed or ospeed
|
||||||
instead\&.
|
instead\&.
|
||||||
.IP "\fB\f(CWecho=<bool>\fP\fP"
|
.IP "\fB\f(CWecho=<bool>\fP\fP"
|
||||||
Enables or disables local echo (example)\&.
|
Enables or disables local echo\&.
|
||||||
.IP "\fB\f(CWicanon=<bool>\fP\fP"
|
.IP "\fB\f(CWicanon=<bool>\fP\fP"
|
||||||
Sets or clears canonical mode, enabling line buffering and some special
|
Sets or clears canonical mode, enabling line buffering and some special
|
||||||
characters\&.
|
characters\&.
|
||||||
.IP "\fB\f(CWraw\fP\fP"
|
.IP "\fB\f(CWraw\fP\fP"
|
||||||
Sets raw mode, thus passing input and output almost unprocessed (example)\&.
|
Sets raw mode, thus passing input and output almost unprocessed\&.
|
||||||
.IP "\fB\f(CWignbrk=<bool>\fP\fP"
|
.IP "\fB\f(CWignbrk=<bool>\fP\fP"
|
||||||
Ignores or interpretes the BREAK character (e\&.g\&., ^C)
|
Ignores or interpretes the BREAK character (e\&.g\&., ^C)
|
||||||
.IP "\fB\f(CWbrkint=<bool>\fP\fP"
|
.IP "\fB\f(CWbrkint=<bool>\fP\fP"
|
||||||
|
@ -2174,8 +1987,7 @@ Generates a symbolic link that points to the actual pseudo terminal
|
||||||
to solve the problem that ptys are generated with more or less
|
to solve the problem that ptys are generated with more or less
|
||||||
unpredictable names, making it difficult to directly access the socat
|
unpredictable names, making it difficult to directly access the socat
|
||||||
generated pty automatically\&. With this option, the user can specify a "fix"
|
generated pty automatically\&. With this option, the user can specify a "fix"
|
||||||
point in the file hierarchy that helps him to access the actual pty
|
point in the file hierarchy that helps him to access the actual pty\&.
|
||||||
(example)\&.
|
|
||||||
Beginning with \fBsocat\fP version 1\&.4\&.3, the symbolic link is removed when
|
Beginning with \fBsocat\fP version 1\&.4\&.3, the symbolic link is removed when
|
||||||
the address is closed (but see option unlink-close)\&.
|
the address is closed (but see option unlink-close)\&.
|
||||||
.IP "\fB\f(CWwait-slave\fP\fP"
|
.IP "\fB\f(CWwait-slave\fP\fP"
|
||||||
|
@ -2233,8 +2045,9 @@ this option is not provided\&.
|
||||||
.IP "\f(CWTLSv1\fP"
|
.IP "\f(CWTLSv1\fP"
|
||||||
Select TLS protocol version 1\&.
|
Select TLS protocol version 1\&.
|
||||||
.IP "\fB\f(CWverify=<bool>\fP\fP"
|
.IP "\fB\f(CWverify=<bool>\fP\fP"
|
||||||
Controls check of the peer\'s certificate\&. Default is 1 (true)\&. Disabling
|
Controls check of the peer\'s certificate\&. Default is 1 (true) for client and
|
||||||
verify might open your socket for everyone, making the encryption useless!
|
0 (false) for server addresses\&. Disabling verify might open your socket for
|
||||||
|
everyone!
|
||||||
.IP "\fB\f(CWcert=<filename>\fP\fP"
|
.IP "\fB\f(CWcert=<filename>\fP\fP"
|
||||||
Specifies the file with the certificate and private key for authentication\&.
|
Specifies the file with the certificate and private key for authentication\&.
|
||||||
The certificate must be in OpenSSL format (*\&.pem)\&.
|
The certificate must be in OpenSSL format (*\&.pem)\&.
|
||||||
|
@ -2295,61 +2108,6 @@ Performs an unlimited number of retry attempts\&.
|
||||||
.PP
|
.PP
|
||||||
.br
|
.br
|
||||||
.PP
|
.PP
|
||||||
\fI\fBTUN option group\fP\fP
|
|
||||||
.PP
|
|
||||||
Options that control Linux TUN/TAP interface device addresses\&.
|
|
||||||
.PP
|
|
||||||
.IP "\fB\f(CWtun-device=<device-file>\fP\fP"
|
|
||||||
Instructs socat to take another path for the TUN clone device\&. Default is
|
|
||||||
\f(CW/dev/net/tun\fP\&.
|
|
||||||
.IP "\fB\f(CWtun-name=<if-name>\fP\fP"
|
|
||||||
Gives the resulting network interface a specific name instead of the system
|
|
||||||
generated (tun0, tun1, etc\&.)
|
|
||||||
.IP "\fB\f(CWtun-type=[tun|tap]\fP\fP"
|
|
||||||
Sets the type of the TUN device; use this option to generate a TAP
|
|
||||||
device\&. See the Linux docu for the difference between these types\&.
|
|
||||||
When you try to establish a tunnel between two TUN devices, their types
|
|
||||||
should be the same\&.
|
|
||||||
.IP "\fB\f(CWiff-no-pi\fP\fP"
|
|
||||||
Sets the IFF_NO_PI flag which controls if the device includes additional
|
|
||||||
packet information in the tunnel\&.
|
|
||||||
When you try to establish a tunnel between two TUN devices, these flags
|
|
||||||
should have the same values\&.
|
|
||||||
.IP "\fB\f(CWiff-up\fP\fP"
|
|
||||||
Sets the TUN network interface status UP\&. Strongly recommended\&.
|
|
||||||
.IP "\fB\f(CWiff-broadcast\fP\fP"
|
|
||||||
Sets the BROADCAST flag of the TUN network interface\&.
|
|
||||||
.IP "\fB\f(CWiff-debug\fP\fP"
|
|
||||||
Sets the DEBUG flag of the TUN network interface\&.
|
|
||||||
.IP "\fB\f(CWiff-loopback\fP\fP"
|
|
||||||
Sets the LOOPBACK flag of the TUN network interface\&.
|
|
||||||
.IP "\fB\f(CWiff-pointopoint\fP\fP"
|
|
||||||
Sets the POINTOPOINT flag of the TUN device\&.
|
|
||||||
.IP "\fB\f(CWiff-notrailers\fP\fP"
|
|
||||||
Sets the NOTRAILERS flag of the TUN device\&.
|
|
||||||
.IP "\fB\f(CWiff-running\fP\fP"
|
|
||||||
Sets the RUNNING flag of the TUN device\&.
|
|
||||||
.IP "\fB\f(CWiff-noarp\fP\fP"
|
|
||||||
Sets the NOARP flag of the TUN device\&.
|
|
||||||
.IP "\fB\f(CWiff-promisc\fP\fP"
|
|
||||||
Sets the PROMISC flag of the TUN device\&.
|
|
||||||
.IP "\fB\f(CWiff-allmulti\fP\fP"
|
|
||||||
Sets the ALLMULTI flag of the TUN device\&.
|
|
||||||
.IP "\fB\f(CWiff-master\fP\fP"
|
|
||||||
Sets the MASTER flag of the TUN device\&.
|
|
||||||
.IP "\fB\f(CWiff-slave\fP\fP"
|
|
||||||
Sets the SLAVE flag of the TUN device\&.
|
|
||||||
.IP "\fB\f(CWiff-multicast\fP\fP"
|
|
||||||
Sets the MULTICAST flag of the TUN device\&.
|
|
||||||
.IP "\fB\f(CWiff-portsel\fP\fP"
|
|
||||||
Sets the PORTSEL flag of the TUN device\&.
|
|
||||||
.IP "\fB\f(CWiff-automedia\fP\fP"
|
|
||||||
Sets the AUTOMEDIA flag of the TUN device\&.
|
|
||||||
.IP "\fB\f(CWiff-dynamic\fP\fP"
|
|
||||||
Sets the DYNAMIC flag of the TUN device\&.
|
|
||||||
.PP
|
|
||||||
.br
|
|
||||||
.PP
|
|
||||||
.SH "DATA VALUES"
|
.SH "DATA VALUES"
|
||||||
.PP
|
.PP
|
||||||
This section explains the different data types that address parameters and
|
This section explains the different data types that address parameters and
|
||||||
|
@ -2491,7 +2249,7 @@ second connection\&.
|
||||||
\.LP
|
\.LP
|
||||||
\.nf
|
\.nf
|
||||||
\fBsocat -d -d -lmlocal2 \\
|
\fBsocat -d -d -lmlocal2 \\
|
||||||
TCP4-LISTEN:80,bind=myaddr1,reuseaddr,fork,su=nobody,range=10.0.0.0/8 \\
|
TCP4-LISTEN:80,bind=myaddr1,su=nobody,fork,range=10.0.0.0/8,reuseaddr \\
|
||||||
TCP4:www.domain.org:80,bind=myaddr2\fP
|
TCP4:www.domain.org:80,bind=myaddr2\fP
|
||||||
\.fi
|
\.fi
|
||||||
.IP
|
.IP
|
||||||
|
@ -2626,7 +2384,7 @@ pty is required to have ftp issue a prompt\&.
|
||||||
Nevertheless, there may occur some confusion with the password and FTP
|
Nevertheless, there may occur some confusion with the password and FTP
|
||||||
prompts\&.
|
prompts\&.
|
||||||
.IP
|
.IP
|
||||||
(\fB\f(CWsocat PTY,link=$HOME/dev/vmodem0,raw,echo=0,waitslave EXEC:\'"ssh modemserver\&.us\&.org socat - /dev/ttyS0,nonblock,raw,echo=0"\'\fP\fP)
|
.IP "\fB\f(CWsocat PTY,link=$HOME/dev/vmodem0,raw,echo=0,waitslave exec:\'"ssh modemserver\&.us\&.org socat - /dev/ttyS0,nonblock,raw,echo=0"\'\fP\fP"
|
||||||
.IP
|
.IP
|
||||||
Generates a pseudo terminal
|
Generates a pseudo terminal
|
||||||
device (PTY) on the client that can be reached under the
|
device (PTY) on the client that can be reached under the
|
||||||
|
@ -2649,31 +2407,6 @@ through the proxy daemon listening on port 3128
|
||||||
CONNECT method, where they are authenticated as "user" with "pass" (proxyauth)\&. The proxy
|
CONNECT method, where they are authenticated as "user" with "pass" (proxyauth)\&. The proxy
|
||||||
should establish connections to host www\&.domain\&.org on port 22 then\&.
|
should establish connections to host www\&.domain\&.org on port 22 then\&.
|
||||||
.IP
|
.IP
|
||||||
.IP "\fB\f(CWsocat - SSL:server:4443,cafile=server\&.crt,cert=client\&.pem\fP\fP"
|
|
||||||
.IP
|
|
||||||
is an OpenSSL client that tries to establish a secure connection to an SSL
|
|
||||||
server\&. Option cafile specifies a file that
|
|
||||||
contains trust certificates: we trust the server only when it presents one of
|
|
||||||
these certificates and proofs that it owns the related private key\&.
|
|
||||||
Otherwise the connection is terminated\&.
|
|
||||||
With cert a file containing the client certificate
|
|
||||||
and the associated private key is specified\&. This is required in case the
|
|
||||||
server wishes a client authentication; many Internet servers do not\&.
|
|
||||||
.br
|
|
||||||
The first address (\'-\') can be replaced by almost any other socat address\&.
|
|
||||||
.IP
|
|
||||||
.IP "\fB\f(CWsocat SSL-LISTEN:4443,reuseaddr,pf=ip4,fork,cert=server\&.pem,cafile=client\&.crt PIPE\fP\fP"
|
|
||||||
.IP
|
|
||||||
is an OpenSSL server that accepts TCP connections, presents the certificate
|
|
||||||
from the file server\&.pem and forces the client to present a certificate that is
|
|
||||||
verified against cafile\&.crt\&.
|
|
||||||
.br
|
|
||||||
The second address (\'PIPE\') can be replaced by almost any other socat
|
|
||||||
address\&.
|
|
||||||
.br
|
|
||||||
For instructions on generating and distributing OpenSSL keys and certificates
|
|
||||||
see the additional socat docu \f(CWsocat-openssl\&.txt\fP\&.
|
|
||||||
.IP
|
|
||||||
.IP "\fB\f(CWecho |socat -u - file:/tmp/bigfile,create,largefile,seek=100000000000\fP\fP"
|
.IP "\fB\f(CWecho |socat -u - file:/tmp/bigfile,create,largefile,seek=100000000000\fP\fP"
|
||||||
.IP
|
.IP
|
||||||
creates a 100GB sparse file; this requires a file system type that
|
creates a 100GB sparse file; this requires a file system type that
|
||||||
|
@ -2697,46 +2430,7 @@ to make the squid executable from Cygwin run under Windows, actual per May 2004)
|
||||||
.IP
|
.IP
|
||||||
.IP "\fB\f(CWsocat - tcp:www\&.blackhat\&.org:31337,readbytes=1000\fP\fP"
|
.IP "\fB\f(CWsocat - tcp:www\&.blackhat\&.org:31337,readbytes=1000\fP\fP"
|
||||||
.IP
|
.IP
|
||||||
connects to an unknown service and prevents being flooded\&.
|
connect to an unknown service and prevent being flooded\&.
|
||||||
.IP
|
|
||||||
.IP "\fB\f(CWsocat -U TCP:target:9999,end-close TCP-L:8888,reuseaddr,fork\fP\fP"
|
|
||||||
.IP
|
|
||||||
merges data arriving from different TCP streams on port 8888 to just one stream
|
|
||||||
to target:9999\&. The end-close option prevents the child
|
|
||||||
processes forked off by the second address from terminating the shared
|
|
||||||
connection to 9999 (close(2) just unlinks the inode which stays active as long
|
|
||||||
as the parent process lives; shutdown(2) would actively terminate the
|
|
||||||
connection)\&.
|
|
||||||
.IP
|
|
||||||
.IP "\fB\f(CWsocat - UDP4-DATAGRAM:192\&.168\&.1\&.0:123,sp=123,broadcast,range=192\&.168\&.1\&.0/24\fP\fP"
|
|
||||||
.IP
|
|
||||||
sends a broadcast to the network 192\&.168\&.1\&.0/24 and receives the replies of the
|
|
||||||
timeservers there\&. Ignores NTP packets from hosts outside this network\&.
|
|
||||||
.IP
|
|
||||||
.IP "\fB\f(CWsocat - IP4-DATAGRAM:255\&.255\&.255\&.255:44,broadcast,range=10\&.0\&.0\&.0/8\fP\fP"
|
|
||||||
.IP
|
|
||||||
sends a broadcast to the local network(s) using protocol 44\&. Accepts replies
|
|
||||||
from the private address range only\&.
|
|
||||||
.IP
|
|
||||||
.IP "\fB\f(CWsocat - UDP4-DATAGRAM:224\&.255\&.0\&.1:6666,bind=:6666,ip-add-membership=224\&.255\&.0\&.1:eth0\fP\fP"
|
|
||||||
.IP
|
|
||||||
transfers data from stdin to the specified multicast address using UDP\&. Both
|
|
||||||
local and remote ports are 6666\&. Tells the interface eth0 to also accept
|
|
||||||
multicast packets of the given group\&. Multiple hosts on the local network can
|
|
||||||
run this command, so all data sent by any of the hosts will be received
|
|
||||||
by all the other ones\&. Note that there are many possible reasons for failure,
|
|
||||||
including IP-filters, routing issues, wrong interface selection by the
|
|
||||||
operating system, bridges, or a badly configured switch\&.
|
|
||||||
.IP
|
|
||||||
.IP "\fB\f(CWsocat TCP:host2:4443 TUN:192\&.168\&.255\&.1/24,up\fP\fP"
|
|
||||||
.IP
|
|
||||||
establishes one side of a virtual (but not private!) network with host2 where a
|
|
||||||
similar process might run, with TCP-L and tun address 192\&.168\&.255\&.2\&. They
|
|
||||||
can reach each other using the addresses 192\&.168\&.255\&.1 and
|
|
||||||
192\&.168\&.255\&.2\&. Substitute the TCP link with an SSL connection protected by
|
|
||||||
client and server authentication (see OpenSSL
|
|
||||||
client and
|
|
||||||
server)\&.
|
|
||||||
.IP
|
.IP
|
||||||
.PP
|
.PP
|
||||||
.SH "DIAGNOSTICS"
|
.SH "DIAGNOSTICS"
|
||||||
|
@ -2843,12 +2537,15 @@ lots of other useful tools and libraries\&.
|
||||||
The \fILinux developers community\fP (http://www\&.linux\&.org/) for providing a free, open source operating
|
The \fILinux developers community\fP (http://www\&.linux\&.org/) for providing a free, open source operating
|
||||||
system\&.
|
system\&.
|
||||||
.PP
|
.PP
|
||||||
|
\fISourceforge\fP (http://www\&.sourceforge\&.net/) for providing a compile
|
||||||
|
farm with Solaris, FreeBSD, and MacOS X machines, making these ports possible\&.
|
||||||
|
.PP
|
||||||
The \fIOpen Group\fP (http://www\&.unix-systems\&.org/) for making their
|
The \fIOpen Group\fP (http://www\&.unix-systems\&.org/) for making their
|
||||||
standard specifications available on the Internet for free\&.
|
standard specifications available on the Internet for free\&.
|
||||||
.PP
|
.PP
|
||||||
.SH "VERSION"
|
.SH "VERSION"
|
||||||
.PP
|
.PP
|
||||||
This man page describes version 1\&.6\&.0 of \fBsocat\fP\&.
|
This man page describes version 1\&.5\&.0 of \fBsocat\fP\&.
|
||||||
.PP
|
.PP
|
||||||
.SH "BUGS"
|
.SH "BUGS"
|
||||||
.PP
|
.PP
|
||||||
|
|
528
doc/socat.html
528
doc/socat.html
File diff suppressed because it is too large
Load diff
7
error.c
7
error.c
|
@ -176,8 +176,8 @@ void msg(int level, const char *format, ...) {
|
||||||
result = gettimeofday(&now, NULL);
|
result = gettimeofday(&now, NULL);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
/* invoking msg() might create endless recursion; by hand instead */
|
/* invoking msg() might create endless recursion; by hand instead */
|
||||||
sprintf(buff, "cannot read time: %s["F_pid"] E %s",
|
sprintf(buff, "cannot read time: %s["F_pid".%lu] E %s",
|
||||||
diagopts.progname, getpid(), strerror(errno));
|
diagopts.progname, getpid(), (unsigned long)pthread_self(), strerror(errno));
|
||||||
_msg(LOG_ERR, buff, strstr(buff, " E "+1));
|
_msg(LOG_ERR, buff, strstr(buff, " E "+1));
|
||||||
strcpy(buff, "unknown time "); bytes = 20;
|
strcpy(buff, "unknown time "); bytes = 20;
|
||||||
} else {
|
} else {
|
||||||
|
@ -215,7 +215,8 @@ void msg(int level, const char *format, ...) {
|
||||||
if (diagopts.withhostname) {
|
if (diagopts.withhostname) {
|
||||||
bytes = sprintf(bufp, "%s ", diagopts.hostname), bufp+=bytes;
|
bytes = sprintf(bufp, "%s ", diagopts.hostname), bufp+=bytes;
|
||||||
}
|
}
|
||||||
bytes = sprintf(bufp, "%s["F_pid"] ", diagopts.progname, getpid());
|
bytes = sprintf(bufp, "%s["F_pid".%lu] ",
|
||||||
|
diagopts.progname, getpid(), (unsigned long)pthread_self());
|
||||||
bufp += bytes;
|
bufp += bytes;
|
||||||
syslp = bufp;
|
syslp = bufp;
|
||||||
*bufp++ = "DINWEF"[level];
|
*bufp++ = "DINWEF"[level];
|
||||||
|
|
2
ftp.sh
2
ftp.sh
|
@ -80,7 +80,7 @@ TMPDIR=$(if [ -x /bin/mktemp ]; then
|
||||||
(umask 077; d=/tmp/$USER/FTPSH.$$; mkdir $d; echo $d)
|
(umask 077; d=/tmp/$USER/FTPSH.$$; mkdir $d; echo $d)
|
||||||
fi)
|
fi)
|
||||||
TO="$TMPDIR/to"; FROM="$TMPDIR/from"
|
TO="$TMPDIR/to"; FROM="$TMPDIR/from"
|
||||||
socat $SO1 fifo:$TO,nonblock,ignoreeof!!fifo:$FROM $method:$server:21,$addropts &
|
socat $SO1 fifo:$FROM $method:$server:21,$addropts%fifo:$TO,nonblock,ignoreeof &
|
||||||
S1=$!
|
S1=$!
|
||||||
while ! [ -p "$TO" -a -p "$FROM" ]; do sleep 1; done
|
while ! [ -p "$TO" -a -p "$FROM" ]; do sleep 1; done
|
||||||
exec 4>$TMPDIR/to 3<$TMPDIR/from
|
exec 4>$TMPDIR/to 3<$TMPDIR/from
|
||||||
|
|
31
nestlex.c
31
nestlex.c
|
@ -1,5 +1,5 @@
|
||||||
/* $Id: nestlex.c,v 1.4 2006/06/23 17:04:36 gerhard Exp $ */
|
/* $Id: nestlex.c,v 1.4 2006/06/23 17:04:36 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2006 */
|
/* Copyright Gerhard Rieger 2006-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
/* a function for lexical scanning of nested character patterns */
|
/* a function for lexical scanning of nested character patterns */
|
||||||
|
@ -29,6 +29,7 @@ int nestlex(const char **addr, /* input string; aft points to end token */
|
||||||
const char *squotes[],/* list of strings that quote softly */
|
const char *squotes[],/* list of strings that quote softly */
|
||||||
const char *nests[],/* list of strings that start nesting;
|
const char *nests[],/* list of strings that start nesting;
|
||||||
every second one is matching end */
|
every second one is matching end */
|
||||||
|
bool dropspace, /* drop trailing space before end token */
|
||||||
bool dropquotes, /* drop the outermost quotes */
|
bool dropquotes, /* drop the outermost quotes */
|
||||||
bool c_esc, /* solve C char escapes: \n \t \0 etc */
|
bool c_esc, /* solve C char escapes: \n \t \0 etc */
|
||||||
bool html_esc /* solve HTML char escapes: %0d %08 etc */
|
bool html_esc /* solve HTML char escapes: %0d %08 etc */
|
||||||
|
@ -38,6 +39,7 @@ int nestlex(const char **addr, /* input string; aft points to end token */
|
||||||
const char **quotx; /* loops over quote patterns */
|
const char **quotx; /* loops over quote patterns */
|
||||||
const char **nestx; /* loops over nest patterns */
|
const char **nestx; /* loops over nest patterns */
|
||||||
char *out = *token; /* pointer into output token */
|
char *out = *token; /* pointer into output token */
|
||||||
|
char *lastnonspace = out;
|
||||||
char c;
|
char c;
|
||||||
int i;
|
int i;
|
||||||
int result;
|
int result;
|
||||||
|
@ -46,7 +48,9 @@ int nestlex(const char **addr, /* input string; aft points to end token */
|
||||||
|
|
||||||
/* is this end of input string? */
|
/* is this end of input string? */
|
||||||
if (*in == 0) {
|
if (*in == 0) {
|
||||||
|
if (dropspace) {
|
||||||
|
out = lastnonspace;
|
||||||
|
}
|
||||||
break; /* end of string */
|
break; /* end of string */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +59,9 @@ int nestlex(const char **addr, /* input string; aft points to end token */
|
||||||
while (*endx) {
|
while (*endx) {
|
||||||
if (!strncmp(in, *endx, strlen(*endx))) {
|
if (!strncmp(in, *endx, strlen(*endx))) {
|
||||||
/* this end pattern matches */
|
/* this end pattern matches */
|
||||||
|
if (dropspace) {
|
||||||
|
out = lastnonspace;
|
||||||
|
}
|
||||||
*addr = in;
|
*addr = in;
|
||||||
*token = out;
|
*token = out;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -83,7 +90,7 @@ int nestlex(const char **addr, /* input string; aft points to end token */
|
||||||
result =
|
result =
|
||||||
nestlex(&in, &out, len, endnest, NULL/*hquotes*/,
|
nestlex(&in, &out, len, endnest, NULL/*hquotes*/,
|
||||||
NULL/*squotes*/, NULL/*nests*/,
|
NULL/*squotes*/, NULL/*nests*/,
|
||||||
false, c_esc, html_esc);
|
false, false, c_esc, html_esc);
|
||||||
if (result == 0 && dropquotes) {
|
if (result == 0 && dropquotes) {
|
||||||
/* we strip this quote */
|
/* we strip this quote */
|
||||||
in += strlen(*quotx);
|
in += strlen(*quotx);
|
||||||
|
@ -101,6 +108,7 @@ int nestlex(const char **addr, /* input string; aft points to end token */
|
||||||
}
|
}
|
||||||
if (hquotes && *quotx != NULL) {
|
if (hquotes && *quotx != NULL) {
|
||||||
/* there was a quote; string might continue with hard quote */
|
/* there was a quote; string might continue with hard quote */
|
||||||
|
lastnonspace = out;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +134,7 @@ int nestlex(const char **addr, /* input string; aft points to end token */
|
||||||
result =
|
result =
|
||||||
nestlex(&in, &out, len, endnest, hquotes,
|
nestlex(&in, &out, len, endnest, hquotes,
|
||||||
squotes, nests,
|
squotes, nests,
|
||||||
false, c_esc, html_esc);
|
false, false, c_esc, html_esc);
|
||||||
|
|
||||||
if (result == 0 && dropquotes) {
|
if (result == 0 && dropquotes) {
|
||||||
/* we strip the trailing quote */
|
/* we strip the trailing quote */
|
||||||
|
@ -144,6 +152,7 @@ int nestlex(const char **addr, /* input string; aft points to end token */
|
||||||
}
|
}
|
||||||
if (squotes && *quotx != NULL) {
|
if (squotes && *quotx != NULL) {
|
||||||
/* there was a soft quote; string might continue with any quote */
|
/* there was a soft quote; string might continue with any quote */
|
||||||
|
lastnonspace = out;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +172,7 @@ int nestlex(const char **addr, /* input string; aft points to end token */
|
||||||
|
|
||||||
result =
|
result =
|
||||||
nestlex(&in, &out, len, endnest, hquotes, squotes, nests,
|
nestlex(&in, &out, len, endnest, hquotes, squotes, nests,
|
||||||
false, c_esc, html_esc);
|
false, false, c_esc, html_esc);
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
/* copy endnest */
|
/* copy endnest */
|
||||||
i = strlen(nestx[1]); while (i > 0) {
|
i = strlen(nestx[1]); while (i > 0) {
|
||||||
|
@ -182,6 +191,7 @@ int nestlex(const char **addr, /* input string; aft points to end token */
|
||||||
}
|
}
|
||||||
if (nests && *nestx) {
|
if (nests && *nestx) {
|
||||||
/* we handled a nested expression, continue loop */
|
/* we handled a nested expression, continue loop */
|
||||||
|
lastnonspace = out;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,6 +226,7 @@ int nestlex(const char **addr, /* input string; aft points to end token */
|
||||||
*token = out;
|
*token = out;
|
||||||
return -1; /* output overflow */
|
return -1; /* output overflow */
|
||||||
}
|
}
|
||||||
|
lastnonspace = out;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -227,6 +238,9 @@ int nestlex(const char **addr, /* input string; aft points to end token */
|
||||||
*token = out;
|
*token = out;
|
||||||
return -1; /* output overflow */
|
return -1; /* output overflow */
|
||||||
}
|
}
|
||||||
|
if (!isspace(c)) {
|
||||||
|
lastnonspace = out;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
/* never come here? */
|
/* never come here? */
|
||||||
|
@ -235,3 +249,10 @@ int nestlex(const char **addr, /* input string; aft points to end token */
|
||||||
*token = out;
|
*token = out;
|
||||||
return 0; /* OK */
|
return 0; /* OK */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int skipsp(const char **text) {
|
||||||
|
while (isspace(**text)) {
|
||||||
|
++(*text);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* $Id: nestlex.h,v 1.3 2006/06/23 17:04:39 gerhard Exp $ */
|
/* $Id: nestlex.h,v 1.3 2006/06/23 17:04:39 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2006 */
|
/* Copyright Gerhard Rieger 2006-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
#ifndef __nestlex_h_included
|
#ifndef __nestlex_h_included
|
||||||
|
@ -15,9 +15,13 @@ int nestlex(const char **addr, /* input string; aft points to end token */
|
||||||
const char *squotes[],/* list of strings that quote softly */
|
const char *squotes[],/* list of strings that quote softly */
|
||||||
const char *nests[],/* list of strings that start nesting;
|
const char *nests[],/* list of strings that start nesting;
|
||||||
every second one is matching end */
|
every second one is matching end */
|
||||||
|
bool dropspace, /* drop trailing space before end token */
|
||||||
bool dropquotes, /* drop the outermost quotes */
|
bool dropquotes, /* drop the outermost quotes */
|
||||||
bool c_esc, /* solve C char escapes: \n \t \0 etc */
|
bool c_esc, /* solve C char escapes: \n \t \0 etc */
|
||||||
bool html_esc /* solve HTML char escapes: %0d %08 etc */
|
bool html_esc /* solve HTML char escapes: %0d %08 etc */
|
||||||
);
|
);
|
||||||
|
|
||||||
|
extern
|
||||||
|
int skipsp(const char **text);
|
||||||
|
|
||||||
#endif /* !defined(__nestlex_h_included) */
|
#endif /* !defined(__nestlex_h_included) */
|
||||||
|
|
2
procan.c
2
procan.c
|
@ -1,5 +1,5 @@
|
||||||
/* $Id: procan.c,v 1.17 2006/12/28 07:25:01 gerhard Exp $ */
|
/* $Id: procan.c,v 1.17 2006/12/28 07:25:01 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2001-2006 */
|
/* Copyright Gerhard Rieger 2001-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
/* the subroutine procan makes a "PROCess ANalysis". It gathers information
|
/* the subroutine procan makes a "PROCess ANalysis". It gathers information
|
||||||
|
|
276
socat.c
276
socat.c
|
@ -20,45 +20,25 @@
|
||||||
#include "filan.h"
|
#include "filan.h"
|
||||||
#include "xio.h"
|
#include "xio.h"
|
||||||
#include "xioopts.h"
|
#include "xioopts.h"
|
||||||
|
#include "xiosigchld.h"
|
||||||
#include "xiolockfile.h"
|
#include "xiolockfile.h"
|
||||||
|
|
||||||
|
#include "xioopen.h"
|
||||||
|
|
||||||
/* command line options */
|
/* command line options */
|
||||||
struct {
|
struct {
|
||||||
size_t bufsiz;
|
|
||||||
bool verbose;
|
|
||||||
bool verbhex;
|
|
||||||
struct timeval pollintv; /* with ignoreeof, reread after seconds */
|
|
||||||
struct timeval closwait; /* after close of x, die after seconds */
|
|
||||||
struct timeval total_timeout;/* when nothing happens, die after seconds */
|
|
||||||
bool debug;
|
|
||||||
bool strictopts; /* stop on errors in address options */
|
bool strictopts; /* stop on errors in address options */
|
||||||
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 */
|
|
||||||
xiolock_t lock; /* a lock file */
|
xiolock_t lock; /* a lock file */
|
||||||
} socat_opts = {
|
} socat_opts = {
|
||||||
8192, /* bufsiz */
|
|
||||||
false, /* verbose */
|
|
||||||
false, /* verbhex */
|
|
||||||
{1,0}, /* pollintv */
|
|
||||||
{0,500000}, /* closwait */
|
|
||||||
{0,0}, /* total_timeout */
|
|
||||||
0, /* debug */
|
|
||||||
0, /* strictopts */
|
0, /* strictopts */
|
||||||
's', /* logopt */
|
|
||||||
false, /* lefttoright */
|
|
||||||
false, /* righttoleft */
|
|
||||||
{ NULL, 0 }, /* lock */
|
{ NULL, 0 }, /* lock */
|
||||||
};
|
};
|
||||||
|
|
||||||
void socat_usage(FILE *fd);
|
void socat_usage(FILE *fd);
|
||||||
void socat_version(FILE *fd);
|
void socat_version(FILE *fd);
|
||||||
int socat(const char *address1, const char *address2);
|
int socat(int argc, const char *address1, const char *address2);
|
||||||
int _socat(void);
|
int _socat(xiofile_t *xfd1, xiofile_t *xfd2);
|
||||||
int cv_newline(unsigned char **buff, ssize_t *bytes, int lineterm1, int lineterm2);
|
|
||||||
void socat_signal(int sig);
|
void socat_signal(int sig);
|
||||||
static int socat_sigchild(struct single *file);
|
|
||||||
|
|
||||||
void lftocrlf(char **in, ssize_t *len, size_t bufsiz);
|
void lftocrlf(char **in, ssize_t *len, size_t bufsiz);
|
||||||
void crlftolf(char **in, ssize_t *len, size_t bufsiz);
|
void crlftolf(char **in, ssize_t *len, size_t bufsiz);
|
||||||
|
@ -93,11 +73,11 @@ int main(int argc, const char *argv[]) {
|
||||||
|
|
||||||
/* we must init before applying options because env settings have lower
|
/* we must init before applying options because env settings have lower
|
||||||
priority and are to be overridden by options */
|
priority and are to be overridden by options */
|
||||||
if (xioinitialize() != 0) {
|
if (xioinitialize(XIO_MAYALL) != 0) {
|
||||||
Exit(1);
|
Exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
xiosetopt('p', "!!");
|
xiosetopt('p', "%");
|
||||||
xiosetopt('o', ":");
|
xiosetopt('o', ":");
|
||||||
|
|
||||||
argc0 = argc; /* save for later use */
|
argc0 = argc; /* save for later use */
|
||||||
|
@ -114,14 +94,14 @@ int main(int argc, const char *argv[]) {
|
||||||
#endif /* WITH_HELP */
|
#endif /* WITH_HELP */
|
||||||
case 'd': diag_set('d', NULL); break;
|
case 'd': diag_set('d', NULL); break;
|
||||||
#if WITH_FILAN
|
#if WITH_FILAN
|
||||||
case 'D': socat_opts.debug = true; break;
|
case 'D': xioparams->debug = true; break;
|
||||||
#endif
|
#endif
|
||||||
case 'l':
|
case 'l':
|
||||||
switch (arg1[0][2]) {
|
switch (arg1[0][2]) {
|
||||||
case 'm': /* mixed mode: stderr, then switch to syslog; + facility */
|
case 'm': /* mixed mode: stderr, then switch to syslog; + facility */
|
||||||
diag_set('s', NULL);
|
diag_set('s', NULL);
|
||||||
xiosetopt('l', "m");
|
xiosetopt('l', "m");
|
||||||
socat_opts.logopt = arg1[0][2];
|
xioparams->logopt = arg1[0][2];
|
||||||
xiosetopt('y', &arg1[0][3]);
|
xiosetopt('y', &arg1[0][3]);
|
||||||
break;
|
break;
|
||||||
case 'y': /* syslog + facility */
|
case 'y': /* syslog + facility */
|
||||||
|
@ -152,8 +132,8 @@ int main(int argc, const char *argv[]) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'v': socat_opts.verbose = true; break;
|
case 'v': xioparams->verbose = true; break;
|
||||||
case 'x': socat_opts.verbhex = true; break;
|
case 'x': xioparams->verbhex = true; break;
|
||||||
case 'b': if (arg1[0][2]) {
|
case 'b': if (arg1[0][2]) {
|
||||||
a = *arg1+2;
|
a = *arg1+2;
|
||||||
} else {
|
} else {
|
||||||
|
@ -163,7 +143,7 @@ int main(int argc, const char *argv[]) {
|
||||||
Exit(1);
|
Exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
socat_opts.bufsiz = strtoul(a, (char **)&a, 0);
|
xioparams->bufsiz = strtoul(a, (char **)&a, 0);
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
diag_set_int('e', E_FATAL); break;
|
diag_set_int('e', E_FATAL); break;
|
||||||
|
@ -177,9 +157,9 @@ int main(int argc, const char *argv[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rto = strtod(a, (char **)&a);
|
rto = strtod(a, (char **)&a);
|
||||||
socat_opts.closwait.tv_sec = rto;
|
xioparams->closwait.tv_sec = rto;
|
||||||
socat_opts.closwait.tv_usec =
|
xioparams->closwait.tv_usec =
|
||||||
(rto-socat_opts.closwait.tv_sec) * 1000000;
|
(rto-xioparams->closwait.tv_sec) * 1000000;
|
||||||
break;
|
break;
|
||||||
case 'T': if (arg1[0][2]) {
|
case 'T': if (arg1[0][2]) {
|
||||||
a = *arg1+2;
|
a = *arg1+2;
|
||||||
|
@ -191,12 +171,12 @@ int main(int argc, const char *argv[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rto = strtod(a, (char **)&a);
|
rto = strtod(a, (char **)&a);
|
||||||
socat_opts.total_timeout.tv_sec = rto;
|
xioparams->total_timeout.tv_sec = rto;
|
||||||
socat_opts.total_timeout.tv_usec =
|
xioparams->total_timeout.tv_usec =
|
||||||
(rto-socat_opts.total_timeout.tv_sec) * 1000000;
|
(rto-xioparams->total_timeout.tv_sec) * 1000000;
|
||||||
break;
|
break;
|
||||||
case 'u': socat_opts.lefttoright = true; break;
|
case 'u': xioparams->lefttoright = true; break;
|
||||||
case 'U': socat_opts.righttoleft = true; break;
|
case 'U': xioparams->righttoleft = true; break;
|
||||||
case 'g': xioopts_ignoregroups = true; break;
|
case 'g': xioopts_ignoregroups = true; break;
|
||||||
case 'L': if (socat_opts.lock.lockfile)
|
case 'L': if (socat_opts.lock.lockfile)
|
||||||
Error("only one -L and -W option allowed");
|
Error("only one -L and -W option allowed");
|
||||||
|
@ -237,8 +217,9 @@ int main(int argc, const char *argv[]) {
|
||||||
break;
|
break;
|
||||||
#endif /* WITH_IP4 || WITH_IP6 */
|
#endif /* WITH_IP4 || WITH_IP6 */
|
||||||
case '\0':
|
case '\0':
|
||||||
|
case '-': /*! this is hardcoded "--" */
|
||||||
case ',':
|
case ',':
|
||||||
case ':': break; /* this "-" is a variation of STDIO */
|
case ':': break; /* this "-" is a variation of STDIO or -- */
|
||||||
default:
|
default:
|
||||||
xioinqopt('p', buff, sizeof(buff));
|
xioinqopt('p', buff, sizeof(buff));
|
||||||
if (arg1[0][1] == buff[0]) {
|
if (arg1[0][1] == buff[0]) {
|
||||||
|
@ -251,15 +232,20 @@ int main(int argc, const char *argv[]) {
|
||||||
xioinqopt('p', buff, sizeof(buff));
|
xioinqopt('p', buff, sizeof(buff));
|
||||||
if (arg1[0][0] == '-' &&
|
if (arg1[0][0] == '-' &&
|
||||||
(arg1[0][1] == '\0' || arg1[0][1] == ':' ||
|
(arg1[0][1] == '\0' || arg1[0][1] == ':' ||
|
||||||
arg1[0][1] == ',' || arg1[0][1] == buff[0]))
|
arg1[0][1] == ',' || arg1[0][1] == '-'/*!*/ ||
|
||||||
|
arg1[0][1] == buff[0]))
|
||||||
break;
|
break;
|
||||||
++arg1; --argc;
|
++arg1; --argc;
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
|
Info1("%d address arguments", argc);
|
||||||
|
#else
|
||||||
if (argc != 2) {
|
if (argc != 2) {
|
||||||
Error1("exactly 2 addresses required (there are %d); use option \"-h\" for help", argc);
|
Error1("exactly 2 addresses required (there are %d); use option \"-h\" for help", argc);
|
||||||
Exit(1);
|
Exit(1);
|
||||||
}
|
}
|
||||||
if (socat_opts.lefttoright && socat_opts.righttoleft) {
|
#endif
|
||||||
|
if (xioparams->lefttoright && xioparams->righttoleft) {
|
||||||
Error("-U and -u must not be combined");
|
Error("-U and -u must not be combined");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,6 +277,26 @@ int main(int argc, const char *argv[]) {
|
||||||
Signal(SIGFPE, socat_signal);
|
Signal(SIGFPE, socat_signal);
|
||||||
Signal(SIGSEGV, socat_signal);
|
Signal(SIGSEGV, socat_signal);
|
||||||
Signal(SIGTERM, socat_signal);
|
Signal(SIGTERM, socat_signal);
|
||||||
|
#if HAVE_SIGACTION
|
||||||
|
{
|
||||||
|
struct sigaction act;
|
||||||
|
memset(&act, 0, sizeof(struct sigaction));
|
||||||
|
act.sa_flags = SA_NOCLDSTOP|SA_RESTART|SA_SIGINFO
|
||||||
|
#ifdef SA_NOMASK
|
||||||
|
|SA_NOMASK
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
act.sa_sigaction = xiosigaction_subaddr_ok;
|
||||||
|
if (Sigaction(SIGUSR1, &act, NULL) < 0) {
|
||||||
|
/*! Linux man does not explicitely say that errno is defined */
|
||||||
|
Warn1("sigaction(SIGUSR1, {&xiosigaction_subaddr_ok}, NULL): %s", strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else /* !HAVE_SIGACTION */
|
||||||
|
if (Signal(SIGUSR1, xiosigaction_subaddr_ok) == SIG_ERR) {
|
||||||
|
Warn1("signal(SIGCHLD, xiosigaction_subaddr_ok): %s", strerror(errno));
|
||||||
|
}
|
||||||
|
#endif /* !HAVE_SIGACTION */
|
||||||
|
|
||||||
/* set xio hooks */
|
/* set xio hooks */
|
||||||
xiohook_newchild = &socat_newchild;
|
xiohook_newchild = &socat_newchild;
|
||||||
|
@ -304,7 +310,7 @@ int main(int argc, const char *argv[]) {
|
||||||
|
|
||||||
Atexit(socat_unlock);
|
Atexit(socat_unlock);
|
||||||
|
|
||||||
result = socat(arg1[0], arg1[1]);
|
result = socat(argc, arg1[0], arg1[1]);
|
||||||
Notice1("exiting with status %d", result);
|
Notice1("exiting with status %d", result);
|
||||||
Exit(result);
|
Exit(result);
|
||||||
return 0; /* not reached, just for gcc -Wall */
|
return 0; /* not reached, just for gcc -Wall */
|
||||||
|
@ -516,125 +522,75 @@ void socat_version(FILE *fd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
xiofile_t *sock1, *sock2;
|
|
||||||
int closing = 0; /* 0..no eof yet, 1..first eof just occurred,
|
|
||||||
2..counting down closing timeout */
|
|
||||||
|
|
||||||
/* call this function when the common command line options are parsed, and the
|
/* call this function when the common command line options are parsed, and the
|
||||||
addresses are extracted (but not resolved). */
|
addresses are extracted (but not resolved). */
|
||||||
int socat(const char *address1, const char *address2) {
|
int socat(int argc, const char *address1, const char *address2) {
|
||||||
int mayexec;
|
xiofile_t *xfd1, *xfd2;
|
||||||
|
|
||||||
|
xioinitialize(XIO_MAYALL);
|
||||||
#if 1
|
#if 1
|
||||||
if (Signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
|
if (Signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
|
||||||
Warn1("signal(SIGPIPE, SIG_IGN): %s", strerror(errno));
|
Warn1("signal(SIGPIPE, SIG_IGN): %s", strerror(errno));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (socat_opts.lefttoright) {
|
/* open the first (left most) address */
|
||||||
if ((sock1 = xioopen(address1, XIO_RDONLY|XIO_MAYFORK|XIO_MAYCHILD|XIO_MAYCONVERT)) == NULL) {
|
if (xioparams->lefttoright) {
|
||||||
|
if ((xfd1 = socat_open(address1, XIO_RDONLY, XIO_MAYFORK|XIO_MAYCHILD|XIO_MAYCONVERT)) == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
xiosetsigchild(sock1, socat_sigchild);
|
} else if (xioparams->righttoleft) {
|
||||||
} else if (socat_opts.righttoleft) {
|
if ((xfd1 = socat_open(address1, XIO_WRONLY, XIO_MAYFORK|XIO_MAYCHILD|XIO_MAYCONVERT)) == NULL) {
|
||||||
if ((sock1 = xioopen(address1, XIO_WRONLY|XIO_MAYFORK|XIO_MAYCHILD|XIO_MAYCONVERT)) == NULL) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
xiosetsigchild(sock1, socat_sigchild);
|
|
||||||
} else {
|
} else {
|
||||||
if ((sock1 = xioopen(address1, XIO_RDWR|XIO_MAYFORK|XIO_MAYCHILD|XIO_MAYCONVERT)) == NULL) {
|
if ((xfd1 = socat_open(address1, XIO_RDWR, XIO_MAYFORK|XIO_MAYCHILD|XIO_MAYCONVERT)) == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
xiosetsigchild(sock1, socat_sigchild);
|
|
||||||
}
|
}
|
||||||
|
xiosetsigchild(xfd1, socat_sigchild);
|
||||||
#if 1 /*! */
|
#if 1 /*! */
|
||||||
if (XIO_READABLE(sock1) &&
|
if (XIO_RDSTREAM(xfd1)->subaddrstat < 0) {
|
||||||
(XIO_RDSTREAM(sock1)->howtoend == END_KILL ||
|
Info1("child "F_pid" has already died",
|
||||||
XIO_RDSTREAM(sock1)->howtoend == END_CLOSE_KILL ||
|
XIO_RDSTREAM(xfd1)->child.pid);
|
||||||
XIO_RDSTREAM(sock1)->howtoend == END_SHUTDOWN_KILL)) {
|
XIO_RDSTREAM(xfd1)->child.pid = 0;
|
||||||
if (XIO_RDSTREAM(sock1)->para.exec.pid == diedunknown1) {
|
|
||||||
/* child has alread died... but it might have put regular data into
|
|
||||||
the communication channel, so continue */
|
|
||||||
Info1("child "F_pid" has already died (diedunknown1)",
|
|
||||||
XIO_RDSTREAM(sock1)->para.exec.pid);
|
|
||||||
diedunknown1 = 0;
|
|
||||||
XIO_RDSTREAM(sock1)->para.exec.pid = 0;
|
|
||||||
/* return STAT_RETRYLATER; */
|
/* return STAT_RETRYLATER; */
|
||||||
} else if (XIO_RDSTREAM(sock1)->para.exec.pid == diedunknown2) {
|
|
||||||
Info1("child "F_pid" has already died (diedunknown2)",
|
|
||||||
XIO_RDSTREAM(sock1)->para.exec.pid);
|
|
||||||
diedunknown2 = 0;
|
|
||||||
XIO_RDSTREAM(sock1)->para.exec.pid = 0;
|
|
||||||
} else if (XIO_RDSTREAM(sock1)->para.exec.pid == diedunknown3) {
|
|
||||||
Info1("child "F_pid" has already died (diedunknown3)",
|
|
||||||
XIO_RDSTREAM(sock1)->para.exec.pid);
|
|
||||||
diedunknown3 = 0;
|
|
||||||
XIO_RDSTREAM(sock1)->para.exec.pid = 0;
|
|
||||||
} else if (XIO_RDSTREAM(sock1)->para.exec.pid == diedunknown4) {
|
|
||||||
Info1("child "F_pid" has already died (diedunknown4)",
|
|
||||||
XIO_RDSTREAM(sock1)->para.exec.pid);
|
|
||||||
diedunknown4 = 0;
|
|
||||||
XIO_RDSTREAM(sock1)->para.exec.pid = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mayexec = (sock1->common.flags&XIO_DOESCONVERT ? 0 : XIO_MAYEXEC);
|
/* second (right) addresses chain */
|
||||||
if (XIO_WRITABLE(sock1)) {
|
if (XIO_WRITABLE(xfd1)) {
|
||||||
if (XIO_READABLE(sock1)) {
|
if (XIO_READABLE(xfd1)) {
|
||||||
if ((sock2 = xioopen(address2, XIO_RDWR|XIO_MAYFORK|XIO_MAYCHILD|mayexec|XIO_MAYCONVERT)) == NULL) {
|
if ((xfd2 = socat_open(address2, XIO_RDWR, XIO_MAYFORK|XIO_MAYCHILD|XIO_MAYEXEC|XIO_MAYCONVERT)) == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
xiosetsigchild(sock2, socat_sigchild);
|
|
||||||
} else {
|
} else {
|
||||||
if ((sock2 = xioopen(address2, XIO_RDONLY|XIO_MAYFORK|XIO_MAYCHILD|mayexec|XIO_MAYCONVERT)) == NULL) {
|
if ((xfd2 = socat_open(address2, XIO_RDONLY, XIO_MAYFORK|XIO_MAYCHILD|XIO_MAYEXEC|XIO_MAYCONVERT)) == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
xiosetsigchild(sock2, socat_sigchild);
|
|
||||||
}
|
}
|
||||||
} else { /* assuming sock1 is readable */
|
} else { /* assuming sock1 is readable */
|
||||||
if ((sock2 = xioopen(address2, XIO_WRONLY|XIO_MAYFORK|XIO_MAYCHILD|mayexec|XIO_MAYCONVERT)) == NULL) {
|
if ((xfd2 = socat_open(address2, XIO_WRONLY, XIO_MAYFORK|XIO_MAYCHILD|XIO_MAYEXEC|XIO_MAYCONVERT)) == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
xiosetsigchild(sock2, socat_sigchild);
|
|
||||||
}
|
}
|
||||||
|
xiosetsigchild(xfd2, socat_sigchild);
|
||||||
#if 1 /*! */
|
#if 1 /*! */
|
||||||
if (XIO_READABLE(sock2) &&
|
if (XIO_RDSTREAM(xfd2)->subaddrstat < 0) {
|
||||||
(XIO_RDSTREAM(sock2)->howtoend == END_KILL ||
|
Info1("child "F_pid" has already died",
|
||||||
XIO_RDSTREAM(sock2)->howtoend == END_CLOSE_KILL ||
|
XIO_RDSTREAM(xfd2)->child.pid);
|
||||||
XIO_RDSTREAM(sock2)->howtoend == END_SHUTDOWN_KILL)) {
|
XIO_RDSTREAM(xfd2)->child.pid = 0;
|
||||||
if (XIO_RDSTREAM(sock2)->para.exec.pid == diedunknown1) {
|
|
||||||
/* child has alread died... but it might have put regular data into
|
|
||||||
the communication channel, so continue */
|
|
||||||
Info1("child "F_pid" has already died (diedunknown1)",
|
|
||||||
XIO_RDSTREAM(sock2)->para.exec.pid);
|
|
||||||
diedunknown1 = 0;
|
|
||||||
XIO_RDSTREAM(sock2)->para.exec.pid = 0;
|
|
||||||
/* return STAT_RETRYLATER; */
|
/* return STAT_RETRYLATER; */
|
||||||
} else if (XIO_RDSTREAM(sock2)->para.exec.pid == diedunknown2) {
|
|
||||||
Info1("child "F_pid" has already died (diedunknown2)",
|
|
||||||
XIO_RDSTREAM(sock2)->para.exec.pid);
|
|
||||||
diedunknown2 = 0;
|
|
||||||
XIO_RDSTREAM(sock2)->para.exec.pid = 0;
|
|
||||||
} else if (XIO_RDSTREAM(sock2)->para.exec.pid == diedunknown3) {
|
|
||||||
Info1("child "F_pid" has already died (diedunknown3)",
|
|
||||||
XIO_RDSTREAM(sock2)->para.exec.pid);
|
|
||||||
diedunknown3 = 0;
|
|
||||||
XIO_RDSTREAM(sock2)->para.exec.pid = 0;
|
|
||||||
} else if (XIO_RDSTREAM(sock2)->para.exec.pid == diedunknown4) {
|
|
||||||
Info1("child "F_pid" has already died (diedunknown4)",
|
|
||||||
XIO_RDSTREAM(sock2)->para.exec.pid);
|
|
||||||
diedunknown4 = 0;
|
|
||||||
XIO_RDSTREAM(sock2)->para.exec.pid = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Info("resolved and opened all sock addresses");
|
Info("resolved and opened all sock addresses");
|
||||||
return
|
return
|
||||||
_socat(); /* nsocks, sockets are visible outside function */
|
_socat(xfd1, xfd2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* checks if this is a connection to a child process, and if so, sees if the
|
/* checks if this is a connection to a child process, and if so, sees if the
|
||||||
child already died, leaving some data for us.
|
child already died, leaving some data for us.
|
||||||
returns <0 if an error occurred;
|
returns <0 if an error occurred;
|
||||||
|
@ -646,10 +602,10 @@ int childleftdata(xiofile_t *xfd) {
|
||||||
int retval;
|
int retval;
|
||||||
/* have to check if a child process died before, but left read data */
|
/* have to check if a child process died before, but left read data */
|
||||||
if (XIO_READABLE(xfd) &&
|
if (XIO_READABLE(xfd) &&
|
||||||
(XIO_RDSTREAM(xfd)->howtoend == END_KILL ||
|
(/*0 XIO_RDSTREAM(xfd)->howtoclose == END_KILL ||*/
|
||||||
XIO_RDSTREAM(xfd)->howtoend == END_CLOSE_KILL ||
|
XIO_RDSTREAM(xfd)->howtoclose == END_CLOSE_KILL ||
|
||||||
XIO_RDSTREAM(xfd)->howtoend == END_SHUTDOWN_KILL) &&
|
XIO_RDSTREAM(xfd)->howtoclose == END_SHUTDOWN_KILL) &&
|
||||||
XIO_RDSTREAM(xfd)->para.exec.pid == 0) {
|
XIO_RDSTREAM(xfd)->child.pid == 0) {
|
||||||
struct timeval time0 = { 0,0 };
|
struct timeval time0 = { 0,0 };
|
||||||
|
|
||||||
FD_ZERO(&in); FD_ZERO(&out); FD_ZERO(&expt);
|
FD_ZERO(&in); FD_ZERO(&out); FD_ZERO(&expt);
|
||||||
|
@ -658,17 +614,17 @@ int childleftdata(xiofile_t *xfd) {
|
||||||
/*0 FD_SET(XIO_GETRDFD(xfd), &expt);*/
|
/*0 FD_SET(XIO_GETRDFD(xfd), &expt);*/
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
retval = Select(FOPEN_MAX, &in, &out, &expt, &time0);
|
retval = Select(FD_SETSIZE, &in, &out, &expt, &time0);
|
||||||
} while (retval < 0 && errno == EINTR);
|
} while (retval < 0 && errno == EINTR);
|
||||||
|
|
||||||
if (retval < 0) {
|
if (retval < 0) {
|
||||||
#if HAVE_FDS_BITS
|
#if HAVE_FDS_BITS
|
||||||
Error5("select(%d, &0x%lx, &0x%lx, &0x%lx, {0}): %s",
|
Error5("select(%d, &0x%lx, &0x%lx, &0x%lx, {0}): %s",
|
||||||
FOPEN_MAX, in.fds_bits[0], out.fds_bits[0],
|
FD_SETSIZE, in.fds_bits[0], out.fds_bits[0],
|
||||||
expt.fds_bits[0], strerror(errno));
|
expt.fds_bits[0], strerror(errno));
|
||||||
#else
|
#else
|
||||||
Error5("select(%d, &0x%lx, &0x%lx, &0x%lx, {0}): %s",
|
Error5("select(%d, &0x%lx, &0x%lx, &0x%lx, {0}): %s",
|
||||||
FOPEN_MAX, in.__fds_bits[0], out.__fds_bits[0],
|
FD_SETSIZE, in.__fds_bits[0], out.__fds_bits[0],
|
||||||
expt.__fds_bits[0], strerror(errno));
|
expt.__fds_bits[0], strerror(errno));
|
||||||
#endif
|
#endif
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -681,9 +637,9 @@ int childleftdata(xiofile_t *xfd) {
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif /* 0 */
|
||||||
|
|
||||||
int xiotransfer(xiofile_t *inpipe, xiofile_t *outpipe,
|
#if 0
|
||||||
unsigned char **buff, size_t bufsiz, bool righttoleft);
|
|
||||||
|
|
||||||
bool mayrd1; /* sock1 has read data or eof, according to select() */
|
bool mayrd1; /* sock1 has read data or eof, according to select() */
|
||||||
bool mayrd2; /* sock2 has read data or eof, according to select() */
|
bool mayrd2; /* sock2 has read data or eof, according to select() */
|
||||||
|
@ -693,7 +649,7 @@ bool maywr2; /* sock2 can be written to, according to select() */
|
||||||
/* here we come when the sockets are opened (in the meaning of C language),
|
/* here we come when the sockets are opened (in the meaning of C language),
|
||||||
and their options are set/applied
|
and their options are set/applied
|
||||||
returns -1 on error or 0 on success */
|
returns -1 on error or 0 on success */
|
||||||
int _socat(void) {
|
int _socat(xiofile_t *xfd1, xiofile_t *xfd2) {
|
||||||
fd_set in, out, expt;
|
fd_set in, out, expt;
|
||||||
int retval;
|
int retval;
|
||||||
unsigned char *buff;
|
unsigned char *buff;
|
||||||
|
@ -702,6 +658,9 @@ int _socat(void) {
|
||||||
int wasaction = 1; /* last select was active, do NOT sleep before next */
|
int wasaction = 1; /* last select was active, do NOT sleep before next */
|
||||||
struct timeval total_timeout; /* the actual total timeout timer */
|
struct timeval total_timeout; /* the actual total timeout timer */
|
||||||
|
|
||||||
|
sock1 = xfd1;
|
||||||
|
sock2 = xfd2;
|
||||||
|
|
||||||
#if WITH_FILAN
|
#if WITH_FILAN
|
||||||
if (socat_opts.debug) {
|
if (socat_opts.debug) {
|
||||||
int fdi, fdo;
|
int fdi, fdo;
|
||||||
|
@ -732,7 +691,7 @@ int _socat(void) {
|
||||||
#endif /* WITH_FILAN */
|
#endif /* WITH_FILAN */
|
||||||
|
|
||||||
/* when converting nl to crnl, size might double */
|
/* when converting nl to crnl, size might double */
|
||||||
buff = Malloc(2*socat_opts.bufsiz+1);
|
buff = Malloc(2*xioparams->bufsiz+1);
|
||||||
if (buff == NULL) return -1;
|
if (buff == NULL) return -1;
|
||||||
|
|
||||||
if (socat_opts.logopt == 'm' && xioinqopt('l', NULL, 0) == 'm') {
|
if (socat_opts.logopt == 'm' && xioinqopt('l', NULL, 0) == 'm') {
|
||||||
|
@ -818,6 +777,7 @@ int _socat(void) {
|
||||||
if (XIO_READABLE(sock1) &&
|
if (XIO_READABLE(sock1) &&
|
||||||
!(XIO_RDSTREAM(sock1)->eof > 1 && !XIO_RDSTREAM(sock1)->ignoreeof) &&
|
!(XIO_RDSTREAM(sock1)->eof > 1 && !XIO_RDSTREAM(sock1)->ignoreeof) &&
|
||||||
!socat_opts.righttoleft) {
|
!socat_opts.righttoleft) {
|
||||||
|
Debug3("*** sock1: %p [%d,%d]", sock1, XIO_GETRDFD(sock1), XIO_GETWRFD(sock1));
|
||||||
if (!mayrd1) {
|
if (!mayrd1) {
|
||||||
FD_SET(XIO_GETRDFD(sock1), &in);
|
FD_SET(XIO_GETRDFD(sock1), &in);
|
||||||
}
|
}
|
||||||
|
@ -828,6 +788,7 @@ int _socat(void) {
|
||||||
if (XIO_READABLE(sock2) &&
|
if (XIO_READABLE(sock2) &&
|
||||||
!(XIO_RDSTREAM(sock2)->eof > 1 && !XIO_RDSTREAM(sock2)->ignoreeof) &&
|
!(XIO_RDSTREAM(sock2)->eof > 1 && !XIO_RDSTREAM(sock2)->ignoreeof) &&
|
||||||
!socat_opts.lefttoright) {
|
!socat_opts.lefttoright) {
|
||||||
|
Debug3("*** sock2: %p [%d,%d]", sock2, XIO_GETRDFD(sock2), XIO_GETWRFD(sock2));
|
||||||
if (!mayrd2) {
|
if (!mayrd2) {
|
||||||
FD_SET(XIO_GETRDFD(sock2), &in);
|
FD_SET(XIO_GETRDFD(sock2), &in);
|
||||||
}
|
}
|
||||||
|
@ -835,7 +796,7 @@ int _socat(void) {
|
||||||
FD_SET(XIO_GETWRFD(sock1), &out);
|
FD_SET(XIO_GETWRFD(sock1), &out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
retval = Select(FOPEN_MAX, &in, &out, &expt, to);
|
retval = Select(FD_SETSIZE, &in, &out, &expt, to);
|
||||||
_errno = errno;
|
_errno = errno;
|
||||||
if (retval < 0 && errno == EINTR) {
|
if (retval < 0 && errno == EINTR) {
|
||||||
Info1("select(): %s", strerror(errno));
|
Info1("select(): %s", strerror(errno));
|
||||||
|
@ -851,12 +812,12 @@ int _socat(void) {
|
||||||
if (retval < 0) {
|
if (retval < 0) {
|
||||||
#if HAVE_FDS_BITS
|
#if HAVE_FDS_BITS
|
||||||
Error7("select(%d, &0x%lx, &0x%lx, &0x%lx, %s%lu): %s",
|
Error7("select(%d, &0x%lx, &0x%lx, &0x%lx, %s%lu): %s",
|
||||||
FOPEN_MAX, in.fds_bits[0], out.fds_bits[0],
|
FD_SETSIZE, in.fds_bits[0], out.fds_bits[0],
|
||||||
expt.fds_bits[0], to?"&":"NULL/", to?to->tv_sec:0,
|
expt.fds_bits[0], to?"&":"NULL/", to?to->tv_sec:0,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
#else
|
#else
|
||||||
Error7("select(%d, &0x%lx, &0x%lx, &0x%lx, %s%lu): %s",
|
Error7("select(%d, &0x%lx, &0x%lx, &0x%lx, %s%lu): %s",
|
||||||
FOPEN_MAX, in.__fds_bits[0], out.__fds_bits[0],
|
FD_SETSIZE, in.__fds_bits[0], out.__fds_bits[0],
|
||||||
expt.__fds_bits[0], to?"&":"NULL/", to?to->tv_sec:0,
|
expt.__fds_bits[0], to?"&":"NULL/", to?to->tv_sec:0,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
#endif
|
#endif
|
||||||
|
@ -900,7 +861,7 @@ int _socat(void) {
|
||||||
|
|
||||||
if (mayrd1 && maywr2) {
|
if (mayrd1 && maywr2) {
|
||||||
mayrd1 = false;
|
mayrd1 = false;
|
||||||
if ((bytes1 = xiotransfer(sock1, sock2, &buff, socat_opts.bufsiz, false))
|
if ((bytes1 = xiotransfer(sock1, sock2, &buff, xioparams->bufsiz, false))
|
||||||
< 0) {
|
< 0) {
|
||||||
if (errno != EAGAIN) {
|
if (errno != EAGAIN) {
|
||||||
closing = MAX(closing, 1);
|
closing = MAX(closing, 1);
|
||||||
|
@ -920,15 +881,22 @@ int _socat(void) {
|
||||||
/* avoid idle when all readbytes already there */
|
/* avoid idle when all readbytes already there */
|
||||||
mayrd1 = true;
|
mayrd1 = true;
|
||||||
}
|
}
|
||||||
|
} else { /* bytes2 == 0 */
|
||||||
|
if (XIO_RDSTREAM(sock1)->ignoreeof && !closing) {
|
||||||
|
;
|
||||||
|
} else {
|
||||||
|
XIO_RDSTREAM(sock1)->eof = 2;
|
||||||
|
closing = MAX(closing, 1);
|
||||||
}
|
}
|
||||||
/* (bytes1 == 0) handled later */
|
/* (bytes1 == 0) handled later */
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
bytes1 = -1;
|
bytes1 = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mayrd2 && maywr1) {
|
if (mayrd2 && maywr1) {
|
||||||
mayrd2 = false;
|
mayrd2 = false;
|
||||||
if ((bytes2 = xiotransfer(sock2, sock1, &buff, socat_opts.bufsiz, true))
|
if ((bytes2 = xiotransfer(sock2, sock1, &buff, xioparams->bufsiz, true))
|
||||||
< 0) {
|
< 0) {
|
||||||
if (errno != EAGAIN) {
|
if (errno != EAGAIN) {
|
||||||
closing = MAX(closing, 1);
|
closing = MAX(closing, 1);
|
||||||
|
@ -948,8 +916,15 @@ int _socat(void) {
|
||||||
/* avoid idle when all readbytes already there */
|
/* avoid idle when all readbytes already there */
|
||||||
mayrd2 = true;
|
mayrd2 = true;
|
||||||
}
|
}
|
||||||
|
} else { /* bytes == 0 */
|
||||||
|
if (XIO_RDSTREAM(sock2)->ignoreeof && !closing) {
|
||||||
|
;
|
||||||
|
} else {
|
||||||
|
XIO_RDSTREAM(sock2)->eof = 2;
|
||||||
|
closing = MAX(closing, 1);
|
||||||
}
|
}
|
||||||
/* (bytes2 == 0) handled later */
|
/* (bytes2 == 0) handled later */
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
bytes2 = -1;
|
bytes2 = -1;
|
||||||
}
|
}
|
||||||
|
@ -959,7 +934,7 @@ int _socat(void) {
|
||||||
if (bytes1 == 0 || XIO_RDSTREAM(sock1)->eof >= 2) {
|
if (bytes1 == 0 || XIO_RDSTREAM(sock1)->eof >= 2) {
|
||||||
if (XIO_RDSTREAM(sock1)->ignoreeof && !closing) {
|
if (XIO_RDSTREAM(sock1)->ignoreeof && !closing) {
|
||||||
Debug1("socket 1 (fd %d) is at EOF, ignoring",
|
Debug1("socket 1 (fd %d) is at EOF, ignoring",
|
||||||
XIO_RDSTREAM(sock1)->fd); /*! */
|
XIO_RDSTREAM(sock1)->fd1); /*! */
|
||||||
polling = 1;
|
polling = 1;
|
||||||
} else {
|
} else {
|
||||||
Notice1("socket 1 (fd %d) is at EOF", XIO_GETRDFD(sock1));
|
Notice1("socket 1 (fd %d) is at EOF", XIO_GETRDFD(sock1));
|
||||||
|
@ -973,7 +948,7 @@ int _socat(void) {
|
||||||
if (bytes2 == 0 || XIO_RDSTREAM(sock2)->eof >= 2) {
|
if (bytes2 == 0 || XIO_RDSTREAM(sock2)->eof >= 2) {
|
||||||
if (XIO_RDSTREAM(sock2)->ignoreeof && !closing) {
|
if (XIO_RDSTREAM(sock2)->ignoreeof && !closing) {
|
||||||
Debug1("socket 2 (fd %d) is at EOF, ignoring",
|
Debug1("socket 2 (fd %d) is at EOF, ignoring",
|
||||||
XIO_RDSTREAM(sock2)->fd);
|
XIO_RDSTREAM(sock2)->fd1);
|
||||||
polling = 1;
|
polling = 1;
|
||||||
} else {
|
} else {
|
||||||
Notice1("socket 2 (fd %d) is at EOF", XIO_GETRDFD(sock2));
|
Notice1("socket 2 (fd %d) is at EOF", XIO_GETRDFD(sock2));
|
||||||
|
@ -991,8 +966,9 @@ int _socat(void) {
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif /* 0 */
|
||||||
|
|
||||||
|
#if 0
|
||||||
#define MAXTIMESTAMPLEN 128
|
#define MAXTIMESTAMPLEN 128
|
||||||
/* prints the timestamp to the buffer and terminates it with '\0'. This buffer
|
/* prints the timestamp to the buffer and terminates it with '\0'. This buffer
|
||||||
should be at least MAXTIMESTAMPLEN bytes long.
|
should be at least MAXTIMESTAMPLEN bytes long.
|
||||||
|
@ -1035,7 +1011,9 @@ int gettimestamp(char *timestamp) {
|
||||||
#endif /* !HAVE_GETTIMEOFDAY */
|
#endif /* !HAVE_GETTIMEOFDAY */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
static const char *prefixltor = "> ";
|
static const char *prefixltor = "> ";
|
||||||
static const char *prefixrtol = "< ";
|
static const char *prefixrtol = "< ";
|
||||||
static unsigned long numltor;
|
static unsigned long numltor;
|
||||||
|
@ -1061,8 +1039,9 @@ static int
|
||||||
fputs(buff, file);
|
fputs(buff, file);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif /* 0 */
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* inpipe is suspected to have read data available; read at most bufsiz bytes
|
/* inpipe is suspected to have read data available; read at most bufsiz bytes
|
||||||
and transfer them to outpipe. Perform required data conversions.
|
and transfer them to outpipe. Perform required data conversions.
|
||||||
buff should be at least twice as large as bufsiz, to allow all standard
|
buff should be at least twice as large as bufsiz, to allow all standard
|
||||||
|
@ -1078,7 +1057,7 @@ int xiotransfer(xiofile_t *inpipe, xiofile_t *outpipe,
|
||||||
unsigned char **buff, size_t bufsiz, bool righttoleft) {
|
unsigned char **buff, size_t bufsiz, bool righttoleft) {
|
||||||
ssize_t bytes, writt;
|
ssize_t bytes, writt;
|
||||||
|
|
||||||
bytes = xioread(inpipe, *buff, socat_opts.bufsiz);
|
bytes = xioread(inpipe, *buff, xioparams->bufsiz);
|
||||||
if (bytes < 0) {
|
if (bytes < 0) {
|
||||||
if (errno != EAGAIN)
|
if (errno != EAGAIN)
|
||||||
XIO_RDSTREAM(inpipe)->eof = 2;
|
XIO_RDSTREAM(inpipe)->eof = 2;
|
||||||
|
@ -1105,7 +1084,7 @@ int xiotransfer(xiofile_t *inpipe, xiofile_t *outpipe,
|
||||||
errno = EAGAIN; return -1;
|
errno = EAGAIN; return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (socat_opts.verbose && socat_opts.verbhex) {
|
if (xioparams->verbose && xioparams->verbhex) {
|
||||||
/* Hack-o-rama */
|
/* Hack-o-rama */
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
size_t j;
|
size_t j;
|
||||||
|
@ -1178,7 +1157,7 @@ int xiotransfer(xiofile_t *inpipe, xiofile_t *outpipe,
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
} else if (socat_opts.verbhex) {
|
} else if (xioparams->verbhex) {
|
||||||
int i;
|
int i;
|
||||||
/*! prefix? */
|
/*! prefix? */
|
||||||
for (i = 0; i < bytes; ++i) {
|
for (i = 0; i < bytes; ++i) {
|
||||||
|
@ -1206,11 +1185,13 @@ int xiotransfer(xiofile_t *inpipe, xiofile_t *outpipe,
|
||||||
}
|
}
|
||||||
return writt;
|
return writt;
|
||||||
}
|
}
|
||||||
|
#endif /* 0 */
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
|
||||||
#define CR '\r'
|
#define CR '\r'
|
||||||
#define LF '\n'
|
#define LF '\n'
|
||||||
|
|
||||||
|
|
||||||
int cv_newline(unsigned char **buff, ssize_t *bytes,
|
int cv_newline(unsigned char **buff, ssize_t *bytes,
|
||||||
int lineterm1, int lineterm2) {
|
int lineterm1, int lineterm2) {
|
||||||
/* must perform newline changes */
|
/* must perform newline changes */
|
||||||
|
@ -1260,7 +1241,7 @@ int cv_newline(unsigned char **buff, ssize_t *bytes,
|
||||||
} else {
|
} else {
|
||||||
from = '\r';
|
from = '\r';
|
||||||
}
|
}
|
||||||
if ((buf2 = Malloc(2*socat_opts.bufsiz+1)) == NULL) {
|
if ((buf2 = Malloc(2*xioparams->bufsiz+1)) == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
s = *buff; t = buf2; z = *buff + *bytes;
|
s = *buff; t = buf2; z = *buff + *bytes;
|
||||||
|
@ -1279,6 +1260,7 @@ int cv_newline(unsigned char **buff, ssize_t *bytes,
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif /* 0 */
|
||||||
|
|
||||||
void socat_signal(int signum) {
|
void socat_signal(int signum) {
|
||||||
switch (signum) {
|
switch (signum) {
|
||||||
|
@ -1302,6 +1284,7 @@ void socat_signal(int signum) {
|
||||||
Exit(128+signum);
|
Exit(128+signum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* this is the callback when the child of an address died */
|
/* this is the callback when the child of an address died */
|
||||||
static int socat_sigchild(struct single *file) {
|
static int socat_sigchild(struct single *file) {
|
||||||
if (file->ignoreeof && !closing) {
|
if (file->ignoreeof && !closing) {
|
||||||
|
@ -1312,6 +1295,7 @@ static int socat_sigchild(struct single *file) {
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int socat_lock(void) {
|
static int socat_lock(void) {
|
||||||
int lockrc;
|
int lockrc;
|
||||||
|
|
16
sslcls.c
16
sslcls.c
|
@ -197,6 +197,22 @@ int sycSSL_set_fd(SSL *ssl, int fd) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sycSSL_set_rfd(SSL *ssl, int fd) {
|
||||||
|
int result;
|
||||||
|
Debug2("SSL_set_rfd(%p, %d)", ssl, fd);
|
||||||
|
result = SSL_set_rfd(ssl, fd);
|
||||||
|
Debug1("SSL_set_rfd() -> %d", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sycSSL_set_wfd(SSL *ssl, int fd) {
|
||||||
|
int result;
|
||||||
|
Debug2("SSL_set_wfd(%p, %d)", ssl, fd);
|
||||||
|
result = SSL_set_wfd(ssl, fd);
|
||||||
|
Debug1("SSL_set_wfd() -> %d", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
int sycSSL_connect(SSL *ssl) {
|
int sycSSL_connect(SSL *ssl) {
|
||||||
int result;
|
int result;
|
||||||
Debug1("SSL_connect(%p)", ssl);
|
Debug1("SSL_connect(%p)", ssl);
|
||||||
|
|
4
sslcls.h
4
sslcls.h
|
@ -32,6 +32,8 @@ int sycSSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str);
|
||||||
int sycSSL_set_cipher_list(SSL *ssl, const char *str);
|
int sycSSL_set_cipher_list(SSL *ssl, const char *str);
|
||||||
long sycSSL_get_verify_result(SSL *ssl);
|
long sycSSL_get_verify_result(SSL *ssl);
|
||||||
int sycSSL_set_fd(SSL *ssl, int fd);
|
int sycSSL_set_fd(SSL *ssl, int fd);
|
||||||
|
int sycSSL_set_rfd(SSL *ssl, int fd);
|
||||||
|
int sycSSL_set_wfd(SSL *ssl, int fd);
|
||||||
int sycSSL_connect(SSL *ssl);
|
int sycSSL_connect(SSL *ssl);
|
||||||
int sycSSL_accept(SSL *ssl);
|
int sycSSL_accept(SSL *ssl);
|
||||||
int sycSSL_read(SSL *ssl, void *buf, int num);
|
int sycSSL_read(SSL *ssl, void *buf, int num);
|
||||||
|
@ -77,6 +79,8 @@ int sycFIPS_mode_set(int onoff);
|
||||||
#define sycSSL_set_cipher_list(s,t) SSL_set_cipher_list(s,t)
|
#define sycSSL_set_cipher_list(s,t) SSL_set_cipher_list(s,t)
|
||||||
#define sycSSL_get_verify_result(s) SSL_get_verify_result(s)
|
#define sycSSL_get_verify_result(s) SSL_get_verify_result(s)
|
||||||
#define sycSSL_set_fd(s,f) SSL_set_fd(s,f)
|
#define sycSSL_set_fd(s,f) SSL_set_fd(s,f)
|
||||||
|
#define sycSSL_set_rfd(s,f) SSL_set_rfd(s,f)
|
||||||
|
#define sycSSL_set_wfd(s,f) SSL_set_wfd(s,f)
|
||||||
#define sycSSL_connect(s) SSL_connect(s)
|
#define sycSSL_connect(s) SSL_connect(s)
|
||||||
#define sycSSL_accept(s) SSL_accept(s)
|
#define sycSSL_accept(s) SSL_accept(s)
|
||||||
#define sycSSL_read(s,b,n) SSL_read(s,b,n)
|
#define sycSSL_read(s,b,n) SSL_read(s,b,n)
|
||||||
|
|
111
sycls.c
111
sycls.c
|
@ -720,6 +720,41 @@ int Select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* we only show the first word of the fd_set's; hope this is enough for most
|
||||||
|
cases. */
|
||||||
|
int Pselect(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
||||||
|
struct timespec *timeout, const sigset_t *sigmask) {
|
||||||
|
int result, _errno;
|
||||||
|
#if HAVE_FDS_BITS
|
||||||
|
Debug8("pselect(%d, &0x%lx, &0x%lx, &0x%lx, %s%lu.%06u, {0x%lx})",
|
||||||
|
n, readfds->fds_bits[0], writefds->fds_bits[0],
|
||||||
|
exceptfds->fds_bits[0],
|
||||||
|
timeout?"&":"NULL/", timeout?timeout->tv_sec:0,
|
||||||
|
timeout?timeout->tv_nsec:0, /*sigmask->__val[0]*/
|
||||||
|
*(unsigned long *)sigmask);
|
||||||
|
#else
|
||||||
|
Debug8("pselect(%d, &0x%lx, &0x%lx, &0x%lx, %s%lu.%06u, {0x%lx})",
|
||||||
|
n, readfds->__fds_bits[0], writefds->__fds_bits[0],
|
||||||
|
exceptfds->__fds_bits[0],
|
||||||
|
timeout?"&":"NULL/", timeout?timeout->tv_sec:0,
|
||||||
|
timeout?timeout->tv_nsec:0, *(unsigned long *)sigmask);
|
||||||
|
#endif
|
||||||
|
result = pselect(n, readfds, writefds, exceptfds, timeout, sigmask);
|
||||||
|
_errno = errno;
|
||||||
|
#if HAVE_FDS_BITS
|
||||||
|
Debug4("pselect -> (, 0x%lx, 0x%lx, 0x%lx, , ), %d",
|
||||||
|
readfds->fds_bits[0], writefds->fds_bits[0], exceptfds->fds_bits[0],
|
||||||
|
result);
|
||||||
|
#else
|
||||||
|
Debug4("pselect -> (, 0x%lx, 0x%lx, 0x%lx, , ), %d",
|
||||||
|
readfds->__fds_bits[0], writefds->__fds_bits[0],
|
||||||
|
exceptfds->__fds_bits[0],
|
||||||
|
result);
|
||||||
|
#endif
|
||||||
|
errno = _errno;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
pid_t Fork(void) {
|
pid_t Fork(void) {
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int _errno;
|
int _errno;
|
||||||
|
@ -764,12 +799,15 @@ int Sigaction(int signum, const struct sigaction *act,
|
||||||
}
|
}
|
||||||
#endif /* HAVE_SIGACTION */
|
#endif /* HAVE_SIGACTION */
|
||||||
|
|
||||||
int Sigprocmask(int how, const sigset_t *set, sigset_t *oset) {
|
int Sigprocmask(int how, const sigset_t *set, sigset_t *oldset) {
|
||||||
int retval;
|
int _errno, result;
|
||||||
Debug3("sigprocmask(%d, %p, %p)", how, set, oset);
|
Debug3("sigprocmask(%d, {0x%lx}, %p)", how, *(unsigned long *)set, oldset);
|
||||||
retval = sigprocmask(how, set, oset);
|
result = sigprocmask(how, set, oldset);
|
||||||
Debug1("sigprocmask() -> %d", retval);
|
_errno = errno;
|
||||||
return retval;
|
Debug4("sigprocmask(,,%s%lu%s) -> %d",
|
||||||
|
oldset?" {0x":"", oldset?*(unsigned long *)oldset:0, oldset?"}":"", result);
|
||||||
|
errno = _errno;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int Alarm(unsigned int seconds) {
|
unsigned int Alarm(unsigned int seconds) {
|
||||||
|
@ -1138,7 +1176,7 @@ int Pause(void) {
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if WITH_IP4 || WITH_IP6
|
#if _WITH_IP4 || _WITH_IP6
|
||||||
struct hostent *Gethostbyname(const char *name) {
|
struct hostent *Gethostbyname(const char *name) {
|
||||||
struct hostent *hent;
|
struct hostent *hent;
|
||||||
Debug1("gethostbyname(\"%s\")", name);
|
Debug1("gethostbyname(\"%s\")", name);
|
||||||
|
@ -1154,7 +1192,7 @@ struct hostent *Gethostbyname(const char *name) {
|
||||||
}
|
}
|
||||||
return hent;
|
return hent;
|
||||||
}
|
}
|
||||||
#endif /* WITH_IP4 || WITH_IP6 */
|
#endif /* _WITH_IP4 || _WITH_IP6 */
|
||||||
|
|
||||||
#if (_WITH_IP4 || _WITH_IP6) && HAVE_GETADDRINFO
|
#if (_WITH_IP4 || _WITH_IP6) && HAVE_GETADDRINFO
|
||||||
int Getaddrinfo(const char *node, const char *service,
|
int Getaddrinfo(const char *node, const char *service,
|
||||||
|
@ -1397,6 +1435,27 @@ void Abort(void) {
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Pthread_create(pthread_t *thread, const pthread_attr_t *attr,
|
||||||
|
void *(*start_routine)(void *), void *arg) {
|
||||||
|
int result, _errno;
|
||||||
|
Debug4("pthread_create(%p, %p, %p, %p)", thread, attr, start_routine, arg);
|
||||||
|
result = pthread_create(thread, attr, start_routine, arg);
|
||||||
|
_errno = errno;
|
||||||
|
Debug1("pthread_create() -> %d", errno);
|
||||||
|
errno = _errno;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Pthread_join(pthread_t thread, void **value_ptr) {
|
||||||
|
int result, _errno;
|
||||||
|
Debug2("pthread_join(%p, %p)", thread, value_ptr);
|
||||||
|
result = pthread_join(thread, value_ptr);
|
||||||
|
_errno = errno;
|
||||||
|
Debug1("pthread_join() -> %d", errno);
|
||||||
|
errno = _errno;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
int Mkstemp(char *template) {
|
int Mkstemp(char *template) {
|
||||||
int result, _errno;
|
int result, _errno;
|
||||||
Debug1("mkstemp(\"%s\")", template);
|
Debug1("mkstemp(\"%s\")", template);
|
||||||
|
@ -1500,4 +1559,40 @@ void Add_history(const char *string) {
|
||||||
|
|
||||||
#endif /* WITH_READLINE */
|
#endif /* WITH_READLINE */
|
||||||
|
|
||||||
|
#if WITH_GZIP
|
||||||
|
|
||||||
|
gzFile Gzdopen(int fd, const char *mode) {
|
||||||
|
gzFile result;
|
||||||
|
Debug2("gzdopen(%d, \"%s\")", fd, mode);
|
||||||
|
result = gzdopen(fd, mode);
|
||||||
|
Debug1("gzdopen() -> %p", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Gzread(gzFile file, voidp buf, unsigned len) {
|
||||||
|
int result;
|
||||||
|
Debug3("gzread(%p, %p, %u)", file, buf, len);
|
||||||
|
result = gzread(file, buf, len);
|
||||||
|
Debug1("gzread() -> %d", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Gzwrite(gzFile file, const voidp buf, unsigned len) {
|
||||||
|
int result;
|
||||||
|
Debug3("gzwrite(%p, %p, %u)", file, buf, len);
|
||||||
|
result = gzwrite(file, buf, len);
|
||||||
|
Debug1("gzwrite() -> %d", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Gzclose(gzFile file) {
|
||||||
|
int result;
|
||||||
|
Debug1("gzclose(%p)", file);
|
||||||
|
result = gzclose(file);
|
||||||
|
Debug1("gzclose() -> %d", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* WITH_GZIP */
|
||||||
|
|
||||||
#endif /* WITH_SYCLS */
|
#endif /* WITH_SYCLS */
|
||||||
|
|
21
sycls.h
21
sycls.h
|
@ -75,6 +75,8 @@ int Chmod(const char *path, mode_t mode);
|
||||||
int Poll(struct pollfd *ufds, unsigned int nfds, int timeout);
|
int Poll(struct pollfd *ufds, unsigned int nfds, int timeout);
|
||||||
int Select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
int Select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
||||||
struct timeval *timeout);
|
struct timeval *timeout);
|
||||||
|
int Pselect(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
|
||||||
|
struct timespec *timeout, const sigset_t *sigmask);
|
||||||
pid_t Fork(void);
|
pid_t Fork(void);
|
||||||
pid_t Waitpid(pid_t pid, int *status, int options);
|
pid_t Waitpid(pid_t pid, int *status, int options);
|
||||||
#ifndef HAVE_TYPE_SIGHANDLER
|
#ifndef HAVE_TYPE_SIGHANDLER
|
||||||
|
@ -133,9 +135,13 @@ int Grantpt(int fd);
|
||||||
int Unlockpt(int fd);
|
int Unlockpt(int fd);
|
||||||
int Gethostname(char *name, size_t len);
|
int Gethostname(char *name, size_t len);
|
||||||
int Uname(struct utsname *buf);
|
int Uname(struct utsname *buf);
|
||||||
|
int Sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
|
||||||
int Atexit(void (*func)(void));
|
int Atexit(void (*func)(void));
|
||||||
void Exit(int status);
|
void Exit(int status);
|
||||||
void Abort(void);
|
void Abort(void);
|
||||||
|
int Pthread_create(pthread_t *thread, const pthread_attr_t *attr,
|
||||||
|
void *(*start_routine)(void *), void *arg);
|
||||||
|
int Pthread_join(pthread_t thread, void **value_ptr);
|
||||||
int Mkstemp(char *template);
|
int Mkstemp(char *template);
|
||||||
|
|
||||||
char *Readline(const char *prompt);
|
char *Readline(const char *prompt);
|
||||||
|
@ -145,6 +151,12 @@ int Write_history(const char *filename);
|
||||||
int Append_history(int nelements, const char *filename);
|
int Append_history(int nelements, const char *filename);
|
||||||
int Read_history(const char *filename);
|
int Read_history(const char *filename);
|
||||||
void Add_history(const char *string);
|
void Add_history(const char *string);
|
||||||
|
#if WITH_GZIP
|
||||||
|
gzFile Gzdopen(int fd, const char *mode) {
|
||||||
|
int Gzread(gzFile file, voidp buf, unsigned len) {
|
||||||
|
int Gzwrite(gzFile file, const voidp buf, unsigned len) {
|
||||||
|
int Gzclose(gzFile file) {
|
||||||
|
#endif /* WITH_GZIP */
|
||||||
|
|
||||||
#else /* !WITH_SYCLS */
|
#else /* !WITH_SYCLS */
|
||||||
|
|
||||||
|
@ -205,6 +217,7 @@ void Add_history(const char *string);
|
||||||
#define Chmod(p,m) chmod(p,m)
|
#define Chmod(p,m) chmod(p,m)
|
||||||
#define Poll(u, n, t) poll(u, n, t)
|
#define Poll(u, n, t) poll(u, n, t)
|
||||||
#define Select(n,r,w,e,t) select(n,r,w,e,t)
|
#define Select(n,r,w,e,t) select(n,r,w,e,t)
|
||||||
|
#define Pselect(n,r,w,e,t,s) select(n,r,w,e,t,s)
|
||||||
#define Fork() fork()
|
#define Fork() fork()
|
||||||
#define Waitpid(p,s,o) waitpid(p,s,o)
|
#define Waitpid(p,s,o) waitpid(p,s,o)
|
||||||
#define Signal(s,h) signal(s,h)
|
#define Signal(s,h) signal(s,h)
|
||||||
|
@ -252,9 +265,12 @@ void Add_history(const char *string);
|
||||||
#define Getpgid(p) getpgid(p)
|
#define Getpgid(p) getpgid(p)
|
||||||
#define Gethostname(n,l) gethostname(n,l)
|
#define Gethostname(n,l) gethostname(n,l)
|
||||||
#define Uname(b) uname(b)
|
#define Uname(b) uname(b)
|
||||||
|
#define Sigprocmask(h,s,o) sigprocmask(h,s,o)
|
||||||
#define Atexit(f) atexit(f)
|
#define Atexit(f) atexit(f)
|
||||||
#define Exit(s) exit(s)
|
#define Exit(s) exit(s)
|
||||||
#define Abort() abort()
|
#define Abort() abort()
|
||||||
|
#define Pthread_create(t,attr,s,arg) pthread_create(t,attr,s,arg)
|
||||||
|
#define Pthread_join(t,ptr) pthread_join(t,ptr)
|
||||||
#define Mkstemp(t) mkstemp(t)
|
#define Mkstemp(t) mkstemp(t)
|
||||||
|
|
||||||
#define Readline(p) readline(p)
|
#define Readline(p) readline(p)
|
||||||
|
@ -265,6 +281,11 @@ void Add_history(const char *string);
|
||||||
#define Read_history(f) read_history(f)
|
#define Read_history(f) read_history(f)
|
||||||
#define Add_history(s) add_history(s)
|
#define Add_history(s) add_history(s)
|
||||||
|
|
||||||
|
#define Gzdopen(f,m) gzdopen(f,m)
|
||||||
|
#define Gzread(f,b,l) gzread(f,b,l)
|
||||||
|
#define Gzwrite(f,b,l) gzwrite(f,b,l)
|
||||||
|
#define Gzclose(f) gzclose(f)
|
||||||
|
|
||||||
#endif /* !WITH_SYCLS */
|
#endif /* !WITH_SYCLS */
|
||||||
|
|
||||||
#endif /* !defined(__sycls_h_included) */
|
#endif /* !defined(__sycls_h_included) */
|
||||||
|
|
|
@ -67,10 +67,11 @@
|
||||||
#if HAVE_FCNTL_H
|
#if HAVE_FCNTL_H
|
||||||
#include <fcntl.h> /* open(), O_RDWR */
|
#include <fcntl.h> /* open(), O_RDWR */
|
||||||
#endif
|
#endif
|
||||||
|
#include <pthread.h>
|
||||||
#if HAVE_NETDB_H && (_WITH_IP4 || _WITH_IP6)
|
#if HAVE_NETDB_H && (_WITH_IP4 || _WITH_IP6)
|
||||||
#include <netdb.h> /* struct hostent, gethostbyname() */
|
#include <netdb.h> /* struct hostent, gethostbyname() */
|
||||||
#endif
|
#endif
|
||||||
#if HAVE_SYS_UN_H && WITH_UNIX
|
#if HAVE_SYS_UN_H && _WITH_UNIX
|
||||||
#include <sys/un.h> /* struct sockaddr_un, unix domain sockets */
|
#include <sys/un.h> /* struct sockaddr_un, unix domain sockets */
|
||||||
#endif
|
#endif
|
||||||
#if HAVE_SYS_IOCTL_H
|
#if HAVE_SYS_IOCTL_H
|
||||||
|
|
|
@ -402,7 +402,7 @@ const char *hstrerror(int err) {
|
||||||
#endif /* !HAVE_HSTRERROR */
|
#endif /* !HAVE_HSTRERROR */
|
||||||
|
|
||||||
|
|
||||||
#if WITH_TCP || WITH_UDP
|
#if _WITH_TCP || _WITH_UDP
|
||||||
/* returns port in network byte order */
|
/* returns port in network byte order */
|
||||||
int parseport(const char *portname, int ipproto) {
|
int parseport(const char *portname, int ipproto) {
|
||||||
struct servent *se;
|
struct servent *se;
|
||||||
|
@ -425,7 +425,7 @@ int parseport(const char *portname, int ipproto) {
|
||||||
|
|
||||||
return se->s_port;
|
return se->s_port;
|
||||||
}
|
}
|
||||||
#endif /* WITH_TCP || WITH_UDP */
|
#endif /* _WITH_TCP || _WITH_UDP */
|
||||||
|
|
||||||
#if WITH_IP4 || WITH_IP6
|
#if WITH_IP4 || WITH_IP6
|
||||||
/* check the systems interfaces for ifname and return its index
|
/* check the systems interfaces for ifname and return its index
|
||||||
|
|
12
sysutils.h
12
sysutils.h
|
@ -17,15 +17,15 @@ union xioin6_u {
|
||||||
|
|
||||||
union sockaddr_union {
|
union sockaddr_union {
|
||||||
struct sockaddr soa;
|
struct sockaddr soa;
|
||||||
#if WITH_UNIX
|
#if _WITH_UNIX
|
||||||
struct sockaddr_un un;
|
struct sockaddr_un un;
|
||||||
#endif /* WITH_UNIX */
|
#endif /* _WITH_UNIX */
|
||||||
#if WITH_IP4
|
#if _WITH_IP4
|
||||||
struct sockaddr_in ip4;
|
struct sockaddr_in ip4;
|
||||||
#endif /* WITH_IP4 */
|
#endif /* _WITH_IP4 */
|
||||||
#if WITH_IP6
|
#if _WITH_IP6
|
||||||
struct sockaddr_in6 ip6;
|
struct sockaddr_in6 ip6;
|
||||||
#endif /* WITH_IP6 */
|
#endif /* _WITH_IP6 */
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
#if _WITH_IP4
|
#if _WITH_IP4
|
||||||
|
|
429
test.sh
429
test.sh
|
@ -25,7 +25,7 @@ export SOCAT_OPTS="$opts"
|
||||||
#debug="1"
|
#debug="1"
|
||||||
debug=
|
debug=
|
||||||
TESTS="$@"
|
TESTS="$@"
|
||||||
INTERFACE=eth0; # not used for function tests
|
INTERFACE=eth1; # not used for function tests
|
||||||
MCINTERFACE=lo # !!! Linux only
|
MCINTERFACE=lo # !!! Linux only
|
||||||
#LOCALHOST=192.168.58.1
|
#LOCALHOST=192.168.58.1
|
||||||
#LOCALHOST=localhost
|
#LOCALHOST=localhost
|
||||||
|
@ -45,6 +45,16 @@ if ! type usleep >/dev/null 2>&1; then
|
||||||
sleep $(((n+999999)/1000000))
|
sleep $(((n+999999)/1000000))
|
||||||
}
|
}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# a "real value" sleep
|
||||||
|
rsleep () {
|
||||||
|
local n="$1"
|
||||||
|
local s="${n%.*}"
|
||||||
|
local u="${n#*.}"
|
||||||
|
sleep "$s"
|
||||||
|
usleep "$((u*10**(6-${#u})))"
|
||||||
|
}
|
||||||
|
|
||||||
#USLEEP=usleep
|
#USLEEP=usleep
|
||||||
F_n="%3d" # format string for test numbers
|
F_n="%3d" # format string for test numbers
|
||||||
LANG=C
|
LANG=C
|
||||||
|
@ -89,7 +99,7 @@ esac
|
||||||
# for some tests we need a second local IPv4 address
|
# for some tests we need a second local IPv4 address
|
||||||
case "$UNAME" in
|
case "$UNAME" in
|
||||||
Linux)
|
Linux)
|
||||||
BROADCASTIF=eth0
|
BROADCASTIF=eth1
|
||||||
SECONDADDR=127.0.0.2
|
SECONDADDR=127.0.0.2
|
||||||
BCADDR=127.255.255.255
|
BCADDR=127.255.255.255
|
||||||
BCIFADDR=$($IFCONFIG $BROADCASTIF |grep 'inet ' |awk '{print($2);}' |cut -d: -f2) ;;
|
BCIFADDR=$($IFCONFIG $BROADCASTIF |grep 'inet ' |awk '{print($2);}' |cut -d: -f2) ;;
|
||||||
|
@ -124,7 +134,7 @@ case "$UNAME" in
|
||||||
esac
|
esac
|
||||||
if [ -z "$SECONDIP6ADDR" ]; then
|
if [ -z "$SECONDIP6ADDR" ]; then
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%root2%*) $IFCONFIG eth0 ::2/128
|
*%root2%*) $IFCONFIG eth1 ::2/128
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -468,7 +478,7 @@ N=1
|
||||||
#for o in $(filloptionvalues $OPTS|tr ',' ' '); do
|
#for o in $(filloptionvalues $OPTS|tr ',' ' '); do
|
||||||
# echo testing if $METHOD accepts option $o
|
# echo testing if $METHOD accepts option $o
|
||||||
# touch $TF
|
# touch $TF
|
||||||
# $SOCAT $opts -!!$method:$TF,$o /dev/null,ignoreof </dev/null
|
# $SOCAT $opts $method:$TF,$o%- /dev/null,ignoreof </dev/null
|
||||||
# rm -f $TF
|
# rm -f $TF
|
||||||
#done
|
#done
|
||||||
|
|
||||||
|
@ -971,7 +981,7 @@ for addr in create; do
|
||||||
for o in $(filloptionvalues $OPTS|tr ',' ' '); do
|
for o in $(filloptionvalues $OPTS|tr ',' ' '); do
|
||||||
echo testing if $ADDR accepts option $o
|
echo testing if $ADDR accepts option $o
|
||||||
rm -f $TF
|
rm -f $TF
|
||||||
$SOCAT $opts -!!$addr:$TF,$o /dev/null,ignoreof </dev/null
|
$SOCAT $opts $addr:$TF,$o%- /dev/null,ignoreof </dev/null
|
||||||
rm -f $TF
|
rm -f $TF
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
@ -1099,7 +1109,7 @@ for addr in open; do
|
||||||
for o in $(filloptionvalues $OPTS|tr ',' ' '); do
|
for o in $(filloptionvalues $OPTS|tr ',' ' '); do
|
||||||
echo testing if $ADDR on file accepts option $o
|
echo testing if $ADDR on file accepts option $o
|
||||||
touch $TF
|
touch $TF
|
||||||
$SOCAT $opts -!!$addr:$TF,$o /dev/null,ignoreof </dev/null
|
$SOCAT $opts $addr:$TF,$o%- /dev/null,ignoreof </dev/null
|
||||||
rm -f $TF
|
rm -f $TF
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
@ -1129,7 +1139,7 @@ for addr in gopen; do
|
||||||
for o in $(filloptionvalues $OPTS|tr ',' ' '); do
|
for o in $(filloptionvalues $OPTS|tr ',' ' '); do
|
||||||
echo testing if $ADDR on new file accepts option $o
|
echo testing if $ADDR on new file accepts option $o
|
||||||
rm -f $TF
|
rm -f $TF
|
||||||
$SOCAT $opts -!!$addr:$TF,$o /dev/null,ignoreof </dev/null
|
$SOCAT $opts $addr:$TF,$o%- /dev/null,ignoreof </dev/null
|
||||||
rm -f $TF
|
rm -f $TF
|
||||||
done
|
done
|
||||||
|
|
||||||
|
@ -1147,7 +1157,7 @@ for addr in gopen; do
|
||||||
for o in $(filloptionvalues $OPTS|tr ',' ' '); do
|
for o in $(filloptionvalues $OPTS|tr ',' ' '); do
|
||||||
echo testing if $ADDR on existing file accepts option $o
|
echo testing if $ADDR on existing file accepts option $o
|
||||||
rm -f $TF; touch $TF
|
rm -f $TF; touch $TF
|
||||||
$SOCAT $opts -!!$addr:$TF,$o /dev/null,ignoreof </dev/null
|
$SOCAT $opts $addr:$TF,$o%- /dev/null,ignoreof </dev/null
|
||||||
rm -f $TF
|
rm -f $TF
|
||||||
done
|
done
|
||||||
|
|
||||||
|
@ -1183,7 +1193,7 @@ for addr in gopen; do
|
||||||
for o in $(filloptionvalues $OPTS|tr ',' ' '); do
|
for o in $(filloptionvalues $OPTS|tr ',' ' '); do
|
||||||
echo testing if $ADDR on socket accepts option $o
|
echo testing if $ADDR on socket accepts option $o
|
||||||
rm -f $TF; $SOCAT - UNIX-L:$TF & pid=$!
|
rm -f $TF; $SOCAT - UNIX-L:$TF & pid=$!
|
||||||
$SOCAT $opts -!!$addr:$TF,$o /dev/null,ignoreof </dev/null
|
$SOCAT $opts $addr:$TF,$o%- /dev/null,ignoreof </dev/null
|
||||||
kill $pid 2>/dev/null
|
kill $pid 2>/dev/null
|
||||||
rm -f $TF
|
rm -f $TF
|
||||||
done
|
done
|
||||||
|
@ -1203,7 +1213,7 @@ for addr in gopen; do
|
||||||
for o in $(filloptionvalues $OPTS|tr ',' ' '); do
|
for o in $(filloptionvalues $OPTS|tr ',' ' '); do
|
||||||
echo testing if $ADDR on existing device accepts option $o
|
echo testing if $ADDR on existing device accepts option $o
|
||||||
rm -f $TF; mknod $TF c 1 3
|
rm -f $TF; mknod $TF c 1 3
|
||||||
$SOCAT $opts -!!$addr:$TF,$o /dev/null,ignoreof </dev/null
|
$SOCAT $opts $addr:$TF,$o%- /dev/null,ignoreof </dev/null
|
||||||
done
|
done
|
||||||
else
|
else
|
||||||
TEST="$ADDR on existing device accepts all its options"
|
TEST="$ADDR on existing device accepts all its options"
|
||||||
|
@ -1219,7 +1229,7 @@ for addr in gopen; do
|
||||||
#echo $OPTS
|
#echo $OPTS
|
||||||
for o in $(filloptionvalues $OPTS|tr ',' ' '); do
|
for o in $(filloptionvalues $OPTS|tr ',' ' '); do
|
||||||
echo testing if $ADDR on existing device accepts option $o
|
echo testing if $ADDR on existing device accepts option $o
|
||||||
$SOCAT $opts -!!$addr:$TF,$o /dev/null,ignoreof </dev/null
|
$SOCAT $opts $addr:$TF,$o%- /dev/null,ignoreof </dev/null
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -1425,7 +1435,7 @@ testecho () {
|
||||||
local arg1="$3"; [ -z "$arg1" ] && arg1="-"
|
local arg1="$3"; [ -z "$arg1" ] && arg1="-"
|
||||||
local arg2="$4"; [ -z "$arg2" ] && arg2="echo"
|
local arg2="$4"; [ -z "$arg2" ] && arg2="echo"
|
||||||
local opts="$5"
|
local opts="$5"
|
||||||
local T="$6"; [ -z "$T" ] && T=0
|
local T="$6"; [ -z "$T" ] && T=0; export T
|
||||||
local tf="$td/test$N.stdout"
|
local tf="$td/test$N.stdout"
|
||||||
local te="$td/test$N.stderr"
|
local te="$td/test$N.stderr"
|
||||||
local tdiff="$td/test$N.diff"
|
local tdiff="$td/test$N.diff"
|
||||||
|
@ -1435,7 +1445,7 @@ testecho () {
|
||||||
$PRINTF "test $F_n %s... " $num "$title"
|
$PRINTF "test $F_n %s... " $num "$title"
|
||||||
#echo "$da" |$cmd >"$tf" 2>"$te"
|
#echo "$da" |$cmd >"$tf" 2>"$te"
|
||||||
#set -vx
|
#set -vx
|
||||||
(echo "$da"; sleep $T) |$SOCAT $opts "$arg1" "$arg2" >"$tf" 2>"$te" &
|
(echo "$da"; rsleep $T) |$SOCAT $opts "$arg1" "$arg2" >"$tf" 2>"$te" &
|
||||||
export rc1=$!
|
export rc1=$!
|
||||||
#sleep 5 && kill $rc1 2>/dev/null &
|
#sleep 5 && kill $rc1 2>/dev/null &
|
||||||
# rc2=$!
|
# rc2=$!
|
||||||
|
@ -1461,6 +1471,44 @@ testecho () {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# special function for use with the test address of socat V2 chains
|
||||||
|
testchain () {
|
||||||
|
local num="$1"
|
||||||
|
local title="$2"
|
||||||
|
local arg1="$3"; [ -z "$arg1" ] && arg1="-"
|
||||||
|
local arg2="$4"; [ -z "$arg2" ] && arg2="echo"
|
||||||
|
local opts="$5"
|
||||||
|
local suffix="$6" # what is to be appended by tests
|
||||||
|
local T="$7"; [ -z "$T" ] && T=0; export T
|
||||||
|
local tf="$td/test$N.stdout"
|
||||||
|
local te="$td/test$N.stderr"
|
||||||
|
local tdiff="$td/test$N.diff"
|
||||||
|
local da="$(date)"
|
||||||
|
$PRINTF "test $F_n %s... " $num "$title"
|
||||||
|
(echo "$da"; rsleep $T) |$SOCAT $opts "$arg1" "$arg2" >"$tf" 2>"$te" &
|
||||||
|
export rc1=$!
|
||||||
|
wait $rc1
|
||||||
|
if [ "$?" != 0 ]; then
|
||||||
|
$PRINTF "$FAILED: $SOCAT:\n"
|
||||||
|
echo "$SOCAT $opts $arg1 $arg2"
|
||||||
|
cat "$te"
|
||||||
|
numFAIL=$((numFAIL+1))
|
||||||
|
elif echo -e "$da\n$suffix\c" |diff - "$tf" >"$tdiff" 2>&1; then
|
||||||
|
$PRINTF "$OK\n"
|
||||||
|
if [ -n "$debug" ]; then cat $te; fi
|
||||||
|
numOK=$((numOK+1))
|
||||||
|
else
|
||||||
|
$PRINTF "$FAILED:\n"
|
||||||
|
echo "$SOCAT $opts $arg1 $arg2"
|
||||||
|
cat "$te"
|
||||||
|
echo diff:
|
||||||
|
cat "$tdiff"
|
||||||
|
numFAIL=$((numFAIL+1))
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
# test if call to od and throughput of data works - with graceful shutdown and
|
# test if call to od and throughput of data works - with graceful shutdown and
|
||||||
# flush of od buffers
|
# flush of od buffers
|
||||||
testod () {
|
testod () {
|
||||||
|
@ -1469,14 +1517,14 @@ testod () {
|
||||||
local arg1="$3"; [ -z "$arg1" ] && arg1="-"
|
local arg1="$3"; [ -z "$arg1" ] && arg1="-"
|
||||||
local arg2="$4"; [ -z "$arg2" ] && arg2="echo"
|
local arg2="$4"; [ -z "$arg2" ] && arg2="echo"
|
||||||
local opts="$5"
|
local opts="$5"
|
||||||
local T="$6"; [ -z "$T" ] && T=0
|
local T="$6"; [ -z "$T" ] && T=0; export T
|
||||||
local tf="$td/test$N.stdout"
|
local tf="$td/test$N.stdout"
|
||||||
local te="$td/test$N.stderr"
|
local te="$td/test$N.stderr"
|
||||||
local tdiff="$td/test$N.diff"
|
local tdiff="$td/test$N.diff"
|
||||||
local dain="$(date)"
|
local dain="$(date)"
|
||||||
local daout="$(echo "$dain" |od -c)"
|
local daout="$(echo "$dain" |od -c)"
|
||||||
$PRINTF "test $F_n %s... " $num "$title"
|
$PRINTF "test $F_n %s... " $num "$title"
|
||||||
(echo "$dain"; sleep $T) |$SOCAT $opts "$arg1" "$arg2" >"$tf" 2>"$te"
|
(echo "$dain"; rsleep $T) |$SOCAT $opts "$arg1" "$arg2" >"$tf" 2>"$te"
|
||||||
if [ "$?" != 0 ]; then
|
if [ "$?" != 0 ]; then
|
||||||
$PRINTF "$FAILED: $SOCAT:\n"
|
$PRINTF "$FAILED: $SOCAT:\n"
|
||||||
echo "$SOCAT $opts $arg1 $arg2"
|
echo "$SOCAT $opts $arg1 $arg2"
|
||||||
|
@ -1816,17 +1864,20 @@ gentestcert () {
|
||||||
local name="$1"
|
local name="$1"
|
||||||
if [ -f $name.key -a -f $name.crt -a -f $name.pem ]; then return; fi
|
if [ -f $name.key -a -f $name.crt -a -f $name.pem ]; then return; fi
|
||||||
openssl genrsa $OPENSSL_RAND -out $name.key 768 >/dev/null 2>&1
|
openssl genrsa $OPENSSL_RAND -out $name.key 768 >/dev/null 2>&1
|
||||||
openssl req -new -config testcert.conf -key $name.key -x509 -out $name.crt >/dev/null 2>&1
|
openssl req -new -config testcert.conf -key $name.key -x509 -days 3653 -out $name.crt >/dev/null 2>&1
|
||||||
cat $name.key $name.crt >$name.pem
|
cat $name.key $name.crt >$name.pem
|
||||||
}
|
}
|
||||||
|
|
||||||
# generate a test DSA key and certificate
|
# generate a test DSA key and certificate
|
||||||
gentestdsacert () {
|
gentestdsacert () {
|
||||||
|
#set -vx
|
||||||
local name="$1"
|
local name="$1"
|
||||||
if [ -f $name.key -a -f $name.crt -a -f $name.pem ]; then return; fi
|
if [ -f $name.key -a -f $name.crt -a -f $name.pem ]; then
|
||||||
|
return;
|
||||||
|
fi
|
||||||
openssl dsaparam -out $name-dsa.pem 512 >/dev/null 2>&1
|
openssl dsaparam -out $name-dsa.pem 512 >/dev/null 2>&1
|
||||||
openssl dhparam -dsaparam -out $name-dh.pem 512 >/dev/null 2>&1
|
openssl dhparam -dsaparam -out $name-dh.pem 512 >/dev/null 2>&1
|
||||||
openssl req -newkey dsa:$name-dsa.pem -keyout $name.key -nodes -x509 -config testcert.conf -out $name.crt >/dev/null 2>&1
|
openssl req -newkey dsa:$name-dsa.pem -keyout $name.key -nodes -x509 -days 3653 -config testcert.conf -out $name.crt >/dev/null 2>&1
|
||||||
cat $name-dsa.pem $name-dh.pem $name.key $name.crt >$name.pem
|
cat $name-dsa.pem $name-dh.pem $name.key $name.crt >$name.pem
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1861,8 +1912,8 @@ N=$((N+1))
|
||||||
NAME=DUALSTDIO
|
NAME=DUALSTDIO
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%functions%*|*%stdio%*|*%$NAME%*)
|
*%functions%*|*%stdio%*|*%$NAME%*)
|
||||||
TEST="$NAME: splitted form of stdio ('stdin!!stdout') with simple echo via internal pipe"
|
TEST="$NAME: splitted form of stdio ('stdout%stdin') with simple echo via internal pipe"
|
||||||
testecho "$N" "$TEST" "stdin!!stdout" "pipe" "$opts"
|
testecho "$N" "$TEST" "stdout%stdin" "pipe" "$opts"
|
||||||
esac
|
esac
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
@ -1870,8 +1921,8 @@ N=$((N+1))
|
||||||
NAME=DUALSHORTSTDIO
|
NAME=DUALSHORTSTDIO
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%functions%*|*%stdio%*|*%$NAME%*)
|
*%functions%*|*%stdio%*|*%$NAME%*)
|
||||||
TEST="$NAME: short splitted form of stdio ('-!!-') with simple echo via internal pipe"
|
TEST="$NAME: short splitted form of stdio ('-%-') with simple echo via internal pipe"
|
||||||
testecho "$N" "$TEST" "-!!-" "pipe" "$opts"
|
testecho "$N" "$TEST" "-%-" "pipe" "$opts"
|
||||||
esac
|
esac
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
@ -1880,7 +1931,7 @@ NAME=DUALFDS
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%functions%*|*%fd%*|*%$NAME%*)
|
*%functions%*|*%fd%*|*%$NAME%*)
|
||||||
TEST="$NAME: file descriptors with simple echo via internal pipe"
|
TEST="$NAME: file descriptors with simple echo via internal pipe"
|
||||||
testecho "$N" "$TEST" "0!!1" "pipe" "$opts"
|
testecho "$N" "$TEST" "1%0" "pipe" "$opts"
|
||||||
esac
|
esac
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
@ -1897,14 +1948,15 @@ esac
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
|
||||||
NAME=DUALPIPE
|
# does not work with <write>%<read>
|
||||||
case "$TESTS" in
|
#NAME=DUALPIPE
|
||||||
*%functions%*|*%pipe%*|*%$NAME%*)
|
#case "$TESTS" in
|
||||||
TEST="$NAME: simple echo via named pipe, specified twice"
|
#*%functions%*|*%pipe%*|*%$NAME%*)
|
||||||
tp="$td/pipe$N"
|
#TEST="$NAME: simple echo via named pipe, specified twice"
|
||||||
testecho "$N" "$TEST" "" "pipe:$tp,nonblock!!pipe:$tp" "$opts"
|
#tp="$td/pipe$N"
|
||||||
esac
|
#testecho "$N" "$TEST" "" "pipe:$tp%pipe:$tp,nonblock" "$opts"
|
||||||
N=$((N+1))
|
#esac
|
||||||
|
#N=$((N+1))
|
||||||
|
|
||||||
|
|
||||||
NAME=FILE
|
NAME=FILE
|
||||||
|
@ -1912,7 +1964,7 @@ case "$TESTS" in
|
||||||
*%functions%*|*%file%*|*%ignoreeof%*|*%$NAME%*)
|
*%functions%*|*%file%*|*%ignoreeof%*|*%$NAME%*)
|
||||||
TEST="$NAME: simple echo via file"
|
TEST="$NAME: simple echo via file"
|
||||||
tf="$td/file$N"
|
tf="$td/file$N"
|
||||||
testecho "$N" "$TEST" "" "$tf,ignoreeof!!$tf" "$opts"
|
testecho "$N" "$TEST" "" "$tf%$tf,ignoreeof" "$opts"
|
||||||
esac
|
esac
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
@ -1994,7 +2046,8 @@ NAME=DUALSYSTEMFDS
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%functions%*|*%system%*|*%$NAME%*)
|
*%functions%*|*%system%*|*%$NAME%*)
|
||||||
TEST="$NAME: echo via dual system() of cat"
|
TEST="$NAME: echo via dual system() of cat"
|
||||||
testecho "$N" "$TEST" "system:$CAT>&6,fdout=6!!system:$CAT<&7,fdin=7" "" "$opts"
|
#testecho "$N" "$TEST" "system:'strace -tt -o /tmp/cat.out cat'>&6,fdout=6!!system:$CAT<&7,fdin=7" "" "$opts" "$T"
|
||||||
|
testecho "$N" "$TEST" "system:$CAT<&7,fdin=7%system:'cat'>&6,fdout=6" "" "$opts" "0.1"
|
||||||
esac
|
esac
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
@ -2003,7 +2056,7 @@ NAME=EXECSOCKETFLUSH
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%functions%*|*%exec%*|*%$NAME%*)
|
*%functions%*|*%exec%*|*%$NAME%*)
|
||||||
TEST="$NAME: call to od via exec with socketpair"
|
TEST="$NAME: call to od via exec with socketpair"
|
||||||
testod "$N" "$TEST" "" "exec:$OD_C" "$opts"
|
testod "$N" "$TEST" "" "exec:$OD_C" "$opts" "0.1"
|
||||||
esac
|
esac
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
@ -2012,7 +2065,7 @@ NAME=SYSTEMSOCKETFLUSH
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%functions%*|*%system%*|*%$NAME%*)
|
*%functions%*|*%system%*|*%$NAME%*)
|
||||||
TEST="$NAME: call to od via system() with socketpair"
|
TEST="$NAME: call to od via system() with socketpair"
|
||||||
testod "$N" "$TEST" "" "system:$OD_C" "$opts"
|
testod "$N" "$TEST" "" "system:$OD_C" "$opts" "0.1"
|
||||||
esac
|
esac
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
@ -2081,7 +2134,7 @@ N=$((N+1))
|
||||||
#case "$TESTS" in
|
#case "$TESTS" in
|
||||||
#*%functions%*|*%system%*|*%$NAME%*)
|
#*%functions%*|*%system%*|*%$NAME%*)
|
||||||
#TEST="$NAME: call to od via dual system()"
|
#TEST="$NAME: call to od via dual system()"
|
||||||
#testecho "$N" "$TEST" "system:$OD_C>&6,fdout=6!!system:$CAT<&7,fdin=7" "" "$opts"
|
#testecho "$N" "$TEST" "system:$CAT<&7,fdin=7%system:$OD_C>&6,fdout=6" "" "$opts"
|
||||||
#esac
|
#esac
|
||||||
#N=$((N+1))
|
#N=$((N+1))
|
||||||
|
|
||||||
|
@ -2227,7 +2280,7 @@ TEST="$NAME: echo via two unidirectional UDP IPv4 sockets"
|
||||||
tf="$td/file$N"
|
tf="$td/file$N"
|
||||||
p1=$PORT
|
p1=$PORT
|
||||||
p2=$((PORT+1))
|
p2=$((PORT+1))
|
||||||
testecho "$N" "$TEST" "" "udp:127.0.0.1:$p2,sp=$p1!!udp:127.0.0.1:$p1,sp=$p2" "$opts"
|
testecho "$N" "$TEST" "" "udp:127.0.0.1:$p1,sp=$p2%udp:127.0.0.1:$p2,sp=$p1" "$opts"
|
||||||
esac
|
esac
|
||||||
PORT=$((PORT+2))
|
PORT=$((PORT+2))
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
@ -2248,7 +2301,7 @@ ts="$td/test$N.socket"
|
||||||
tdiff="$td/test$N.diff"
|
tdiff="$td/test$N.diff"
|
||||||
da=$(date)
|
da=$(date)
|
||||||
CMD1="$SOCAT $opts UNIX-LISTEN:$ts PIPE"
|
CMD1="$SOCAT $opts UNIX-LISTEN:$ts PIPE"
|
||||||
CMD2="$SOCAT $opts -!!- UNIX:$ts"
|
CMD2="$SOCAT $opts -%- UNIX:$ts"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
$CMD1 </dev/null >$tf 2>"${te}1" &
|
$CMD1 </dev/null >$tf 2>"${te}1" &
|
||||||
bg=$! # background process id
|
bg=$! # background process id
|
||||||
|
@ -2285,7 +2338,7 @@ tsl=$PORT
|
||||||
ts="127.0.0.1:$tsl"
|
ts="127.0.0.1:$tsl"
|
||||||
da=$(date)
|
da=$(date)
|
||||||
CMD1="$SOCAT $opts TCP4-LISTEN:$tsl,reuseaddr PIPE"
|
CMD1="$SOCAT $opts TCP4-LISTEN:$tsl,reuseaddr PIPE"
|
||||||
CMD2="$SOCAT $opts stdin!!stdout TCP4:$ts"
|
CMD2="$SOCAT $opts stdout%stdin TCP4:$ts"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
$CMD1 >"$tf" 2>"${te}1" &
|
$CMD1 >"$tf" 2>"${te}1" &
|
||||||
waittcp4port $tsl 1
|
waittcp4port $tsl 1
|
||||||
|
@ -2325,7 +2378,7 @@ tsl=$PORT
|
||||||
ts="[::1]:$tsl"
|
ts="[::1]:$tsl"
|
||||||
da=$(date)
|
da=$(date)
|
||||||
CMD1="$SOCAT $opts TCP6-listen:$tsl,reuseaddr PIPE"
|
CMD1="$SOCAT $opts TCP6-listen:$tsl,reuseaddr PIPE"
|
||||||
CMD2="$SOCAT $opts stdin!!stdout TCP6:$ts"
|
CMD2="$SOCAT $opts stdout%stdin TCP6:$ts"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
$CMD1 >"$tf" 2>"${te}1" &
|
$CMD1 >"$tf" 2>"${te}1" &
|
||||||
pid=$! # background process id
|
pid=$! # background process id
|
||||||
|
@ -2371,7 +2424,7 @@ tsl=$PORT
|
||||||
ts="127.0.0.1:$tsl"
|
ts="127.0.0.1:$tsl"
|
||||||
da=$(date)
|
da=$(date)
|
||||||
CMD1="$SOCAT $opts TCP-listen:$tsl,pf=ip4,reuseaddr PIPE"
|
CMD1="$SOCAT $opts TCP-listen:$tsl,pf=ip4,reuseaddr PIPE"
|
||||||
CMD2="$SOCAT $opts stdin!!stdout TCP:$ts"
|
CMD2="$SOCAT $opts stdout%stdin TCP:$ts"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
$CMD1 >"$tf" 2>"${te}1" &
|
$CMD1 >"$tf" 2>"${te}1" &
|
||||||
pid=$! # background process id
|
pid=$! # background process id
|
||||||
|
@ -2417,7 +2470,7 @@ tsl=$PORT
|
||||||
ts="[::1]:$tsl"
|
ts="[::1]:$tsl"
|
||||||
da=$(date)
|
da=$(date)
|
||||||
CMD1="$SOCAT $opts TCP-listen:$tsl,pf=ip6,reuseaddr PIPE"
|
CMD1="$SOCAT $opts TCP-listen:$tsl,pf=ip6,reuseaddr PIPE"
|
||||||
CMD2="$SOCAT $opts stdin!!stdout TCP:$ts"
|
CMD2="$SOCAT $opts stdout%stdin TCP:$ts"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
$CMD1 >"$tf" 2>"${te}1" &
|
$CMD1 >"$tf" 2>"${te}1" &
|
||||||
pid=$! # background process id
|
pid=$! # background process id
|
||||||
|
@ -2465,7 +2518,7 @@ tsl=$PORT
|
||||||
ts="127.0.0.1:$tsl"
|
ts="127.0.0.1:$tsl"
|
||||||
da=$(date)
|
da=$(date)
|
||||||
CMD1="$SOCAT $opts TCP6-listen:$tsl,ipv6-v6only=0,reuseaddr PIPE"
|
CMD1="$SOCAT $opts TCP6-listen:$tsl,ipv6-v6only=0,reuseaddr PIPE"
|
||||||
CMD2="$SOCAT $opts stdin!!stdout TCP4:$ts"
|
CMD2="$SOCAT $opts stdout%stdin TCP4:$ts"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
$CMD1 >"$tf" 2>"${te}1" &
|
$CMD1 >"$tf" 2>"${te}1" &
|
||||||
pid=$! # background process id
|
pid=$! # background process id
|
||||||
|
@ -2513,7 +2566,7 @@ tsl=$PORT
|
||||||
ts="127.0.0.1:$tsl"
|
ts="127.0.0.1:$tsl"
|
||||||
da=$(date)
|
da=$(date)
|
||||||
CMD1="$SOCAT $opts TCP6-listen:$tsl,ipv6-v6only=1,reuseaddr PIPE"
|
CMD1="$SOCAT $opts TCP6-listen:$tsl,ipv6-v6only=1,reuseaddr PIPE"
|
||||||
CMD2="$SOCAT $opts stdin!!stdout TCP4:$ts"
|
CMD2="$SOCAT $opts stdout%stdin TCP4:$ts"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
$CMD1 >"$tf" 2>"${te}1" &
|
$CMD1 >"$tf" 2>"${te}1" &
|
||||||
pid=$! # background process id
|
pid=$! # background process id
|
||||||
|
@ -2558,7 +2611,7 @@ tsl=$PORT
|
||||||
ts="127.0.0.1:$tsl"
|
ts="127.0.0.1:$tsl"
|
||||||
da=$(date)
|
da=$(date)
|
||||||
CMD1="$SOCAT $opts TCP-listen:$tsl,reuseaddr PIPE"
|
CMD1="$SOCAT $opts TCP-listen:$tsl,reuseaddr PIPE"
|
||||||
CMD2="$SOCAT $opts stdin!!stdout TCP4:$ts"
|
CMD2="$SOCAT $opts stdout%stdin TCP4:$ts"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
SOCAT_DEFAULT_LISTEN_IP=4 $CMD1 >"$tf" 2>"${te}1" &
|
SOCAT_DEFAULT_LISTEN_IP=4 $CMD1 >"$tf" 2>"${te}1" &
|
||||||
pid=$! # background process id
|
pid=$! # background process id
|
||||||
|
@ -2603,7 +2656,7 @@ tsl=$PORT
|
||||||
ts="[::1]:$tsl"
|
ts="[::1]:$tsl"
|
||||||
da=$(date)
|
da=$(date)
|
||||||
CMD1="$SOCAT $opts TCP-listen:$tsl,reuseaddr PIPE"
|
CMD1="$SOCAT $opts TCP-listen:$tsl,reuseaddr PIPE"
|
||||||
CMD2="$SOCAT $opts stdin!!stdout TCP6:$ts"
|
CMD2="$SOCAT $opts stdout%stdin TCP6:$ts"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
SOCAT_DEFAULT_LISTEN_IP=6 $CMD1 >"$tf" 2>"${te}1" &
|
SOCAT_DEFAULT_LISTEN_IP=6 $CMD1 >"$tf" 2>"${te}1" &
|
||||||
pid=$! # background process id
|
pid=$! # background process id
|
||||||
|
@ -2651,7 +2704,7 @@ tsl=$PORT
|
||||||
ts="127.0.0.1:$tsl"
|
ts="127.0.0.1:$tsl"
|
||||||
da=$(date)
|
da=$(date)
|
||||||
CMD1="$SOCAT $opts -4 TCP-listen:$tsl,reuseaddr PIPE"
|
CMD1="$SOCAT $opts -4 TCP-listen:$tsl,reuseaddr PIPE"
|
||||||
CMD2="$SOCAT $opts stdin!!stdout TCP4:$ts"
|
CMD2="$SOCAT $opts stdout%stdin TCP4:$ts"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
SOCAT_DEFAULT_LISTEN_IP=6 $CMD1 >"$tf" 2>"${te}1" &
|
SOCAT_DEFAULT_LISTEN_IP=6 $CMD1 >"$tf" 2>"${te}1" &
|
||||||
pid=$! # background process id
|
pid=$! # background process id
|
||||||
|
@ -2696,7 +2749,7 @@ tsl=$PORT
|
||||||
ts="[::1]:$tsl"
|
ts="[::1]:$tsl"
|
||||||
da=$(date)
|
da=$(date)
|
||||||
CMD1="$SOCAT $opts -6 TCP-listen:$tsl,reuseaddr PIPE"
|
CMD1="$SOCAT $opts -6 TCP-listen:$tsl,reuseaddr PIPE"
|
||||||
CMD2="$SOCAT $opts stdin!!stdout TCP6:$ts"
|
CMD2="$SOCAT $opts stdout%stdin TCP6:$ts"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
SOCAT_DEFAULT_LISTEN_IP=4 $CMD1 >"$tf" 2>"${te}1" &
|
SOCAT_DEFAULT_LISTEN_IP=4 $CMD1 >"$tf" 2>"${te}1" &
|
||||||
pid=$! # background process id
|
pid=$! # background process id
|
||||||
|
@ -2745,7 +2798,7 @@ tsl=$PORT
|
||||||
ts="127.0.0.1:$tsl"
|
ts="127.0.0.1:$tsl"
|
||||||
da=$(date)
|
da=$(date)
|
||||||
CMD1="$SOCAT $opts -6 TCP-listen:$tsl,pf=ip4,reuseaddr PIPE"
|
CMD1="$SOCAT $opts -6 TCP-listen:$tsl,pf=ip4,reuseaddr PIPE"
|
||||||
CMD2="$SOCAT $opts stdin!!stdout TCP4:$ts"
|
CMD2="$SOCAT $opts stdout%stdin TCP4:$ts"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
SOCAT_DEFAULT_LISTEN_IP=6 $CMD1 >"$tf" 2>"${te}1" &
|
SOCAT_DEFAULT_LISTEN_IP=6 $CMD1 >"$tf" 2>"${te}1" &
|
||||||
pid=$! # background process id
|
pid=$! # background process id
|
||||||
|
@ -2790,7 +2843,7 @@ tsl=$PORT
|
||||||
ts="[::1]:$tsl"
|
ts="[::1]:$tsl"
|
||||||
da=$(date)
|
da=$(date)
|
||||||
CMD1="$SOCAT $opts -4 TCP-listen:$tsl,pf=ip6,reuseaddr PIPE"
|
CMD1="$SOCAT $opts -4 TCP-listen:$tsl,pf=ip6,reuseaddr PIPE"
|
||||||
CMD2="$SOCAT $opts stdin!!stdout TCP6:$ts"
|
CMD2="$SOCAT $opts stdout%stdin TCP6:$ts"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
SOCAT_DEFAULT_LISTEN_IP=4 $CMD1 >"$tf" 2>"${te}1" &
|
SOCAT_DEFAULT_LISTEN_IP=4 $CMD1 >"$tf" 2>"${te}1" &
|
||||||
pid=$! # background process id
|
pid=$! # background process id
|
||||||
|
@ -2915,7 +2968,7 @@ te="$td/test$N.stderr"
|
||||||
tdiff="$td/test$N.diff"
|
tdiff="$td/test$N.diff"
|
||||||
da=$(date)
|
da=$(date)
|
||||||
echo "$da" >$tf1
|
echo "$da" >$tf1
|
||||||
CMD="$SOCAT $opts $tf1!!/dev/null /dev/null,ignoreeof!!-"
|
CMD="$SOCAT $opts /dev/null%$tf1 -%/dev/null,ignoreeof"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
$CMD >"$tf2" 2>"$te"
|
$CMD >"$tf2" 2>"$te"
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
|
@ -2945,7 +2998,7 @@ tf="$td/test$N.stdout"
|
||||||
te="$td/test$N.stderr"
|
te="$td/test$N.stderr"
|
||||||
tdiff="$td/test$N.diff"
|
tdiff="$td/test$N.diff"
|
||||||
da=$(date)
|
da=$(date)
|
||||||
CMD="$SOCAT $opts $tp!!/dev/null /dev/null,ignoreeof!!$tf"
|
CMD="$SOCAT $opts /dev/null%$tp $tf%/dev/null,ignoreeof"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
#mknod $tp p # no mknod p on FreeBSD
|
#mknod $tp p # no mknod p on FreeBSD
|
||||||
mkfifo $tp
|
mkfifo $tp
|
||||||
|
@ -3121,9 +3174,9 @@ case "$TESTS" in
|
||||||
TEST="$NAME: exec against address with ignoreeof"
|
TEST="$NAME: exec against address with ignoreeof"
|
||||||
tf="$td/test$N.stdout"
|
tf="$td/test$N.stdout"
|
||||||
te="$td/test$N.stderr"
|
te="$td/test$N.stderr"
|
||||||
CMD="$SOCAT $opts -lf /dev/null EXEC:$TRUE /dev/null,ignoreeof"
|
CMD="$SOCAT $opts -lf "$te" EXEC:$TRUE /dev/null,ignoreeof"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
$CMD >"$tf" 2>"$te"
|
$CMD >"$tf"
|
||||||
if [ -s "$te" ]; then
|
if [ -s "$te" ]; then
|
||||||
$PRINTF "$FAILED: $SOCAT:\n"
|
$PRINTF "$FAILED: $SOCAT:\n"
|
||||||
echo "$CMD"
|
echo "$CMD"
|
||||||
|
@ -3337,6 +3390,119 @@ esac
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
|
||||||
|
NAME=CHAIN
|
||||||
|
case "$TESTS" in
|
||||||
|
*%functions%*|*%chain%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: stdio to test+pipe"
|
||||||
|
testchain "$N" "$TEST" "stdio" "test|pipe" "$opts" "><"
|
||||||
|
esac
|
||||||
|
N=$((N+1))
|
||||||
|
|
||||||
|
NAME=REVCHAIN
|
||||||
|
case "$TESTS" in
|
||||||
|
*%functions%*|*%chain%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: stdio to rev.test+pipe"
|
||||||
|
testchain "$N" "$TEST" "stdio" "^test|pipe" "$opts" "<>"
|
||||||
|
esac
|
||||||
|
N=$((N+1))
|
||||||
|
|
||||||
|
NAME=TWOCHAINS
|
||||||
|
case "$TESTS" in
|
||||||
|
*%functions%*|*%chain%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: test+stdio vs. test+pipe"
|
||||||
|
testchain "$N" "$TEST" "test|stdio" "test|pipe" "$opts" "<><>"
|
||||||
|
esac
|
||||||
|
N=$((N+1))
|
||||||
|
|
||||||
|
NAME=TWOREVCHAINS
|
||||||
|
case "$TESTS" in
|
||||||
|
*%functions%*|*%chain%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: rev.test+stdio vs. rev.test+pipe"
|
||||||
|
testchain "$N" "$TEST" "^test|stdio" "^test|pipe" "$opts" "><><"
|
||||||
|
esac
|
||||||
|
N=$((N+1))
|
||||||
|
|
||||||
|
NAME=LONGCHAIN
|
||||||
|
case "$TESTS" in
|
||||||
|
*%functions%*|*%chain%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: stdio vs. four-tests+pipe"
|
||||||
|
testchain "$N" "$TEST" "stdio" "test|^test|test|^test|pipe" "$opts" "><><><><"
|
||||||
|
esac
|
||||||
|
N=$((N+1))
|
||||||
|
|
||||||
|
NAME=TOWLONGCHAINS
|
||||||
|
case "$TESTS" in
|
||||||
|
*%functions%*|*%chain%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: four-tests+stdio vs. four-tests+pipe"
|
||||||
|
testchain "$N" "$TEST" "^test|test|^test|test|stdio" "test|^test|test|^test|pipe" "$opts" "<><>><><><><<><>"
|
||||||
|
esac
|
||||||
|
N=$((N+1))
|
||||||
|
|
||||||
|
NAME=CHAINSPACES
|
||||||
|
case "$TESTS" in
|
||||||
|
*%functions%*|*%chain%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: lot of test with spaces"
|
||||||
|
testchain "$N" "$TEST" " ^ test | test | ^ test | test | stdio " " test | ^ test | test | ^ test | pipe " "$opts" "<><>><><><><<><>"
|
||||||
|
esac
|
||||||
|
N=$((N+1))
|
||||||
|
|
||||||
|
NAME=CHAINUNIDIR
|
||||||
|
case "$TESTS" in
|
||||||
|
*%functions%*|*%chain%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: two unidirectional chains"
|
||||||
|
testchain "$N" "$TEST" "test|stdin" "test|stdout" "-u $opts" "<>"
|
||||||
|
esac
|
||||||
|
N=$((N+1))
|
||||||
|
|
||||||
|
NAME=CHAINREVDIR
|
||||||
|
case "$TESTS" in
|
||||||
|
*%functions%*|*%chain%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: two unidirectional chains, right to left"
|
||||||
|
testchain "$N" "$TEST" "^test|stdout" "^test|stdin" "-U $opts" "><"
|
||||||
|
esac
|
||||||
|
N=$((N+1))
|
||||||
|
|
||||||
|
NAME=CHAINDUAL
|
||||||
|
case "$TESTS" in
|
||||||
|
*%functions%*|*%chain%*|*%dual%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: bidirectional dual chain (uni/rev)"
|
||||||
|
testchain "$N" "$TEST" "stdio" "testuni%testrev|pipe" "$opts" "><"
|
||||||
|
esac
|
||||||
|
N=$((N+1))
|
||||||
|
|
||||||
|
NAME=CHAINDUAL2
|
||||||
|
case "$TESTS" in
|
||||||
|
*%functions%*|*%chain%*|*%dual%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: bidirectional dual chain (bi/rev)"
|
||||||
|
testchain "$N" "$TEST" "stdio" "test%testrev|pipe" "$opts" "><"
|
||||||
|
esac
|
||||||
|
N=$((N+1))
|
||||||
|
|
||||||
|
NAME=CHAINDUAL3
|
||||||
|
case "$TESTS" in
|
||||||
|
*%functions%*|*%chain%*|*%dual%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: bidirectional dual chain (uni/bi)"
|
||||||
|
testchain "$N" "$TEST" "stdio" "testuni%^test|pipe" "$opts" "><"
|
||||||
|
esac
|
||||||
|
N=$((N+1))
|
||||||
|
|
||||||
|
NAME=CHAINDUAL4
|
||||||
|
case "$TESTS" in
|
||||||
|
*%functions%*|*%chain%*|*%dual%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: bidirectional dual chain (bi/bi)"
|
||||||
|
testchain "$N" "$TEST" "stdio" "test%^test|pipe" "$opts" "><"
|
||||||
|
esac
|
||||||
|
N=$((N+1))
|
||||||
|
|
||||||
|
NAME=CHAINDUAL5
|
||||||
|
case "$TESTS" in
|
||||||
|
*%functions%*|*%chain%*|*%dual%*|*%$NAME%*)
|
||||||
|
TEST="$NAME: bidirectional mixed normal and dual chains"
|
||||||
|
testchain "$N" "$TEST" "test|test%^test|^test|stdio" "^test|testuni%testrev|test|pipe" "$opts" "><<<>><<>>><"
|
||||||
|
esac
|
||||||
|
N=$((N+1))
|
||||||
|
|
||||||
|
|
||||||
NAME=OPENSSL_TCP4
|
NAME=OPENSSL_TCP4
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%functions%*|*%openssl%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*)
|
*%functions%*|*%openssl%*|*%tcp%*|*%tcp4%*|*%ip4%*|*%$NAME%*)
|
||||||
|
@ -3358,12 +3524,15 @@ tdiff="$td/test$N.diff"
|
||||||
da=$(date)
|
da=$(date)
|
||||||
CMD2="$SOCAT $opts exec:'openssl s_server -accept "$PORT" -quiet -cert testsrv.pem' pipe"
|
CMD2="$SOCAT $opts exec:'openssl s_server -accept "$PORT" -quiet -cert testsrv.pem' pipe"
|
||||||
#! CMD="$SOCAT $opts - openssl:$LOCALHOST:$PORT"
|
#! CMD="$SOCAT $opts - openssl:$LOCALHOST:$PORT"
|
||||||
CMD="$SOCAT $opts - openssl:$LOCALHOST:$PORT,pf=ip4,verify=0,$SOCAT_EGD"
|
#CMD="$SOCAT $opts - openssl:$LOCALHOST:$PORT,pf=ip4,verify=0,$SOCAT_EGD"
|
||||||
|
CMD="$SOCAT $opts - openssl,verify=0,$SOCAT_EGD|tcp4:$LOCALHOST:$PORT"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
eval "$CMD2 2>\"${te}1\" &"
|
eval "$CMD2 2>\"${te}1\" &"
|
||||||
pid=$! # background process id
|
pid=$! # background process id
|
||||||
waittcp4port $PORT
|
waittcp4port $PORT
|
||||||
echo "$da" |$CMD >$tf 2>"${te}2"
|
# the openssl s_server program appears to not support half closed connections,
|
||||||
|
# so we must delay EOF
|
||||||
|
(echo "$da"; sleep 1) |$CMD >$tf 2>"${te}2"
|
||||||
if ! echo "$da" |diff - "$tf" >"$tdiff"; then
|
if ! echo "$da" |diff - "$tf" >"$tdiff"; then
|
||||||
$PRINTF "$FAILED: $SOCAT:\n"
|
$PRINTF "$FAILED: $SOCAT:\n"
|
||||||
echo "$CMD2 &"
|
echo "$CMD2 &"
|
||||||
|
@ -3401,8 +3570,10 @@ tf="$td/test$N.stdout"
|
||||||
te="$td/test$N.stderr"
|
te="$td/test$N.stderr"
|
||||||
tdiff="$td/test$N.diff"
|
tdiff="$td/test$N.diff"
|
||||||
da=$(date)
|
da=$(date)
|
||||||
CMD2="$SOCAT $opts OPENSSL-LISTEN:$PORT,pf=ip4,reuseaddr,$SOCAT_EGD,cert=testsrv.crt,key=testsrv.key,verify=0 pipe"
|
#CMD2="$SOCAT $opts OPENSSL-LISTEN:$PORT,pf=ip4,reuseaddr,$SOCAT_EGD,cert=testsrv.crt,key=testsrv.key,verify=0 pipe"
|
||||||
CMD="$SOCAT $opts - openssl:$LOCALHOST:$PORT,pf=ip4,verify=0,$SOCAT_EGD"
|
CMD2="$SOCAT $opts TCP4-LISTEN:$PORT,reuseaddr ^OPENSSL-LISTEN,$SOCAT_EGD',cert=testsrv.crt,key=testsrv.key,verify=0|pipe'"
|
||||||
|
#CMD="$SOCAT $opts - openssl:$LOCALHOST:$PORT,pf=ip4,,verify=0,$SOCAT_EGD"
|
||||||
|
CMD="$SOCAT $opts - openssl,verify=0,$SOCAT_EGD|tcp4:$LOCALHOST:$PORT"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
eval "$CMD2 2>\"${te}1\" &"
|
eval "$CMD2 2>\"${te}1\" &"
|
||||||
pid=$! # background process id
|
pid=$! # background process id
|
||||||
|
@ -3625,7 +3796,8 @@ tdiff="$td/test$N.diff"
|
||||||
da="$(date)" da="$da$($ECHO '\r')"
|
da="$(date)" da="$da$($ECHO '\r')"
|
||||||
# we have a normal tcp echo listening - so the socks header must appear in answer
|
# we have a normal tcp echo listening - so the socks header must appear in answer
|
||||||
CMD2="$SOCAT tcp4-l:$PORT,reuseaddr exec:\"./socks4echo.sh\""
|
CMD2="$SOCAT tcp4-l:$PORT,reuseaddr exec:\"./socks4echo.sh\""
|
||||||
CMD="$SOCAT $opts - socks4:$LOCALHOST:32.98.76.54:32109,pf=ip4,socksport=$PORT",socksuser="nobody"
|
#CMD="$SOCAT $opts - socks4:$LOCALHOST:32.98.76.54:32109,pf=ip4,socksport=$PORT",socksuser="nobody"
|
||||||
|
CMD="$SOCAT $opts - socks4:32.98.76.54:32109,socksuser=nobody|tcp4:$LOCALHOST:$PORT"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
eval "$CMD2 2>\"${te}1\" &"
|
eval "$CMD2 2>\"${te}1\" &"
|
||||||
pid=$! # background process id
|
pid=$! # background process id
|
||||||
|
@ -3712,7 +3884,8 @@ tdiff="$td/test$N.diff"
|
||||||
da="$(date)" da="$da$($ECHO '\r')"
|
da="$(date)" da="$da$($ECHO '\r')"
|
||||||
# we have a normal tcp echo listening - so the socks header must appear in answer
|
# we have a normal tcp echo listening - so the socks header must appear in answer
|
||||||
CMD2="$SOCAT tcp4-l:$PORT,reuseaddr exec:\"./socks4a-echo.sh\""
|
CMD2="$SOCAT tcp4-l:$PORT,reuseaddr exec:\"./socks4a-echo.sh\""
|
||||||
CMD="$SOCAT $opts - socks4a:$LOCALHOST:localhost:32109,pf=ip4,socksport=$PORT",socksuser="nobody"
|
#CMD="$SOCAT $opts - socks4a:$LOCALHOST:localhost:32109,pf=ip4,socksport=$PORT",socksuser="nobody"
|
||||||
|
CMD="$SOCAT $opts - socks4a:localhost:32109,socksuser=nobody|tcp4:$LOCALHOST:$PORT"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
eval "$CMD2 2>\"${te}1\" &"
|
eval "$CMD2 2>\"${te}1\" &"
|
||||||
pid=$! # background process id
|
pid=$! # background process id
|
||||||
|
@ -3800,7 +3973,8 @@ tdiff="$td/test$N.diff"
|
||||||
da="$(date)" da="$da$($ECHO '\r')"
|
da="$(date)" da="$da$($ECHO '\r')"
|
||||||
#CMD2="$SOCAT tcp4-l:$PORT,crlf system:\"read; read; $ECHO \\\"HTTP/1.0 200 OK\n\\\"; cat\""
|
#CMD2="$SOCAT tcp4-l:$PORT,crlf system:\"read; read; $ECHO \\\"HTTP/1.0 200 OK\n\\\"; cat\""
|
||||||
CMD2="$SOCAT tcp4-l:$PORT,reuseaddr,crlf exec:\"/bin/bash proxyecho.sh\""
|
CMD2="$SOCAT tcp4-l:$PORT,reuseaddr,crlf exec:\"/bin/bash proxyecho.sh\""
|
||||||
CMD="$SOCAT $opts - proxy:$LOCALHOST:127.0.0.1:1000,pf=ip4,proxyport=$PORT"
|
#CMD="$SOCAT $opts - proxy:$LOCALHOST:127.0.0.1:1000,pf=ip4,proxyport=$PORT"
|
||||||
|
CMD="$SOCAT $opts - proxy:127.0.0.1:1000|tcp4:$LOCALHOST:$PORT"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
eval "$CMD2 2>\"${te}2\" &"
|
eval "$CMD2 2>\"${te}2\" &"
|
||||||
pid=$! # background process id
|
pid=$! # background process id
|
||||||
|
@ -3882,7 +4056,7 @@ tsl=$PORT
|
||||||
ts="127.0.0.1:$tsl"
|
ts="127.0.0.1:$tsl"
|
||||||
da=$(date)
|
da=$(date)
|
||||||
CMD1="$SOCAT $opts TCP4-LISTEN:$tsl,reuseaddr exec:$CAT,nofork"
|
CMD1="$SOCAT $opts TCP4-LISTEN:$tsl,reuseaddr exec:$CAT,nofork"
|
||||||
CMD2="$SOCAT $opts stdin!!stdout TCP4:$ts"
|
CMD2="$SOCAT $opts stdout%stdin TCP4:$ts"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
#$CMD1 >"$tf" 2>"${te}1" &
|
#$CMD1 >"$tf" 2>"${te}1" &
|
||||||
$CMD1 >/dev/null 2>"${te}1" &
|
$CMD1 >/dev/null 2>"${te}1" &
|
||||||
|
@ -3944,7 +4118,7 @@ N=$((N+1))
|
||||||
#da=$(date)
|
#da=$(date)
|
||||||
#$SOCAT UDP-listen:$tsl PIPE &
|
#$SOCAT UDP-listen:$tsl PIPE &
|
||||||
#sleep 2
|
#sleep 2
|
||||||
#echo "$da" |$SOCAT stdin!!stdout UDP:$ts >"$tf"
|
#echo "$da" |$SOCAT stdout%stdin UDP:$ts >"$tf"
|
||||||
#if [ $? -eq 0 ] && echo "$da" |diff "$tf" -; then
|
#if [ $? -eq 0 ] && echo "$da" |diff "$tf" -; then
|
||||||
# $ECHO "... test $N succeeded"
|
# $ECHO "... test $N succeeded"
|
||||||
# numOK=$((numOK+1))
|
# numOK=$((numOK+1))
|
||||||
|
@ -4068,7 +4242,8 @@ tdiff="$td/test$N.diff"
|
||||||
da="$(date)" da="$da$($ECHO '\r')"
|
da="$(date)" da="$da$($ECHO '\r')"
|
||||||
#CMD2="$SOCAT tcp-l:$PORT,crlf system:\"read; read; $ECHO \\\"HTTP/1.0 200 OK\n\\\"; cat\""
|
#CMD2="$SOCAT tcp-l:$PORT,crlf system:\"read; read; $ECHO \\\"HTTP/1.0 200 OK\n\\\"; cat\""
|
||||||
CMD2="$SOCAT tcp4-l:$PORT,reuseaddr,crlf exec:\"/bin/bash proxyecho.sh -w 2\""
|
CMD2="$SOCAT tcp4-l:$PORT,reuseaddr,crlf exec:\"/bin/bash proxyecho.sh -w 2\""
|
||||||
CMD="$SOCAT $opts - proxy:$LOCALHOST:127.0.0.1:1000,pf=ip4,proxyport=$PORT"
|
#CMD="$SOCAT $opts - proxy:$LOCALHOST:127.0.0.1:1000,pf=ip4,proxyport=$PORT"
|
||||||
|
CMD="$SOCAT $opts - proxy:127.0.0.1:1000|tcp4:$LOCALHOST:$PORT"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
eval "$CMD2 2>\"${te}1\" &"
|
eval "$CMD2 2>\"${te}1\" &"
|
||||||
pid=$! # background process id
|
pid=$! # background process id
|
||||||
|
@ -4129,7 +4304,7 @@ NAME=SINGLEEXECOUTSOCKETPAIR
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%functions%*|*%$NAME%*)
|
*%functions%*|*%$NAME%*)
|
||||||
TEST="$NAME: inheritance of stdout to single exec with socketpair"
|
TEST="$NAME: inheritance of stdout to single exec with socketpair"
|
||||||
testecho "$N" "$TEST" "-!!exec:cat" "" "$opts" 1
|
testecho "$N" "$TEST" "exec:cat%-" "" "$opts" 1
|
||||||
esac
|
esac
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
@ -4137,7 +4312,7 @@ NAME=SINGLEEXECOUTPIPE
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%functions%*|*%$NAME%*)
|
*%functions%*|*%$NAME%*)
|
||||||
TEST="$NAME: inheritance of stdout to single exec with pipe"
|
TEST="$NAME: inheritance of stdout to single exec with pipe"
|
||||||
testecho "$N" "$TEST" "-!!exec:cat,pipes" "" "$opts" 1
|
testecho "$N" "$TEST" "exec:cat,pipes%-" "" "$opts" 1
|
||||||
esac
|
esac
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
@ -4149,7 +4324,7 @@ if ! testaddrs pty >/dev/null; then
|
||||||
$PRINTF "test $F_n $TEST... ${YELLOW}PTY not available${NORMAL}\n" $N
|
$PRINTF "test $F_n $TEST... ${YELLOW}PTY not available${NORMAL}\n" $N
|
||||||
numCANT=$((numCANT+1))
|
numCANT=$((numCANT+1))
|
||||||
else
|
else
|
||||||
testecho "$N" "$TEST" "-!!exec:cat,pty,raw" "" "$opts" 1
|
testecho "$N" "$TEST" "exec:cat,pty,raw%-" "" "$opts" 1
|
||||||
fi
|
fi
|
||||||
esac
|
esac
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
@ -4158,7 +4333,7 @@ NAME=SINGLEEXECINSOCKETPAIR
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%functions%*|*%$NAME%*)
|
*%functions%*|*%$NAME%*)
|
||||||
TEST="$NAME: inheritance of stdin to single exec with socketpair"
|
TEST="$NAME: inheritance of stdin to single exec with socketpair"
|
||||||
testecho "$N" "$TEST" "exec:cat!!-" "" "$opts"
|
testecho "$N" "$TEST" "-%exec:cat" "" "$opts"
|
||||||
esac
|
esac
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
@ -4166,7 +4341,7 @@ NAME=SINGLEEXECINPIPE
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%functions%*|*%$NAME%*)
|
*%functions%*|*%$NAME%*)
|
||||||
TEST="$NAME: inheritance of stdin to single exec with pipe"
|
TEST="$NAME: inheritance of stdin to single exec with pipe"
|
||||||
testecho "$N" "$TEST" "exec:cat,pipes!!-" "" "$opts"
|
testecho "$N" "$TEST" "-%exec:cat,pipes" "" "$opts"
|
||||||
esac
|
esac
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
@ -4178,7 +4353,7 @@ if ! testaddrs pty >/dev/null; then
|
||||||
$PRINTF "test $F_n $TEST... ${YELLOW}PTY not available${NORMAL}\n" $N
|
$PRINTF "test $F_n $TEST... ${YELLOW}PTY not available${NORMAL}\n" $N
|
||||||
numCANT=$((numCANT+1))
|
numCANT=$((numCANT+1))
|
||||||
else
|
else
|
||||||
testecho "$N" "$TEST" "exec:cat,pty,raw!!-" "" "$opts" $MISCDELAY
|
testecho "$N" "$TEST" "-%exec:cat,pty,raw" "" "$opts" $MISCDELAY
|
||||||
fi
|
fi
|
||||||
esac
|
esac
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
@ -4191,7 +4366,7 @@ if ! testaddrs pty >/dev/null; then
|
||||||
$PRINTF "test $F_n $TEST... ${YELLOW}PTY not available${NORMAL}\n" $N
|
$PRINTF "test $F_n $TEST... ${YELLOW}PTY not available${NORMAL}\n" $N
|
||||||
numCANT=$((numCANT+1))
|
numCANT=$((numCANT+1))
|
||||||
else
|
else
|
||||||
testecho "$N" "$TEST" "exec:cat,pty,raw!!-" "" "$opts"
|
testecho "$N" "$TEST" "-%exec:cat,pty,raw" "" "$opts"
|
||||||
fi
|
fi
|
||||||
esac
|
esac
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
@ -4217,7 +4392,7 @@ tr="$td/test$N.ref"
|
||||||
tdiff="$td/test$N.diff"
|
tdiff="$td/test$N.diff"
|
||||||
da="$(date)" da="$da$($ECHO '\r')"
|
da="$(date)" da="$da$($ECHO '\r')"
|
||||||
# the feature that we really want to test is in the readline.sh script:
|
# the feature that we really want to test is in the readline.sh script:
|
||||||
CMD="$SOCAT $opts open:$tpi,nonblock!!open:$tpo exec:\"./readline.sh -nh ./readline-test.sh\",pty,ctty,setsid,raw,echo=0,isig"
|
CMD="$SOCAT $opts open:$tpo%open:$tpi,nonblock exec:\"./readline.sh -nh ./readline-test.sh\",pty,ctty,setsid,raw,echo=0,isig"
|
||||||
#echo "$CMD" >"$ts"
|
#echo "$CMD" >"$ts"
|
||||||
#chmod a+x "$ts"
|
#chmod a+x "$ts"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
|
@ -4366,10 +4541,12 @@ CMD1="$SOCAT $opts -lpserver tcp4-l:$PORT,reuseaddr,bind=$LOCALHOST echo"
|
||||||
# this is the proxy in the protected network that provides a way out
|
# this is the proxy in the protected network that provides a way out
|
||||||
CMD2="$SOCAT $opts -lpproxy tcp4-l:$((PORT+1)),reuseaddr,bind=$LOCALHOST,fork exec:./proxy.sh"
|
CMD2="$SOCAT $opts -lpproxy tcp4-l:$((PORT+1)),reuseaddr,bind=$LOCALHOST,fork exec:./proxy.sh"
|
||||||
# this is our proxy connect wrapper in the protected network
|
# this is our proxy connect wrapper in the protected network
|
||||||
CMD3="$SOCAT $opts -lpwrapper tcp4-l:$((PORT+2)),reuseaddr,bind=$LOCALHOST,fork proxy:$LOCALHOST:$LOCALHOST:$((PORT+3)),pf=ip4,proxyport=$((PORT+1)),resolve"
|
#CMD3="$SOCAT $opts -lpwrapper tcp4-l:$((PORT+2)),reuseaddr,bind=$LOCALHOST,fork proxy:$LOCALHOST:$LOCALHOST:$((PORT+3)),pf=ip4,proxyport=$((PORT+1)),resolve"
|
||||||
|
CMD3="$SOCAT $opts -lpwrapper tcp4-l:$((PORT+2)),reuseaddr,bind=$LOCALHOST,fork proxy:$LOCALHOST:$((PORT+3)),resolve\\|tcp4:$LOCALHOST:$((PORT+1))"
|
||||||
# this is our double client in the protected network using SSL
|
# this is our double client in the protected network using SSL
|
||||||
#CMD4="$SOCAT $opts -lp2client ssl:$LOCALHOST:$((PORT+2)),pf=ip4,retry=10,intervall=1,cert=testcli.pem,cafile=testsrv.crt,$SOCAT_EGD tcp4:$LOCALHOST:$PORT"
|
#CMD4="$SOCAT $opts -lp2client ssl:$LOCALHOST:$((PORT+2)),pf=ip4,retry=10,intervall=1,cert=testcli.pem,cafile=testsrv.crt,$SOCAT_EGD tcp4:$LOCALHOST:$PORT"
|
||||||
CMD4="$SOCAT $opts -lp2client ssl:$LOCALHOST:$((PORT+2)),pf=ip4,cert=testcli.pem,cafile=testsrv.crt,$SOCAT_EGD tcp4:$LOCALHOST:$PORT"
|
#CMD4="$SOCAT $opts -lp2client ssl:$LOCALHOST:$((PORT+2)),pf=ip4,cert=testcli.pem,cafile=testsrv.crt,$SOCAT_EGD tcp4:$LOCALHOST:$PORT"
|
||||||
|
CMD4="$SOCAT $opts -lp2client ssl,cert=testcli.pem,cafile=testsrv.crt,$SOCAT_EGD\|tcp4:$LOCALHOST:$((PORT+2)) tcp4:$LOCALHOST:$PORT"
|
||||||
# this is the double server in the outside network
|
# this is the double server in the outside network
|
||||||
CMD5="$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"
|
CMD5="$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
|
# this is the outside client that wants to use the protected server
|
||||||
|
@ -4446,11 +4623,16 @@ CMD1="$SOCAT $opts -lpserver -t1 tcp4-l:$PORT,reuseaddr,bind=$LOCALHOST,fork ech
|
||||||
# this is the proxy in the protected network that provides a way out
|
# this is the proxy in the protected network that provides a way out
|
||||||
CMD2="$SOCAT $opts -lpproxy -t1 tcp4-l:$((PORT+1)),reuseaddr,bind=$LOCALHOST,fork exec:./proxy.sh"
|
CMD2="$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
|
# this is our proxy connect wrapper in the protected network
|
||||||
CMD3="$SOCAT $opts -lpwrapper -t3 tcp4-l:$((PORT+2)),reuseaddr,bind=$LOCALHOST,fork proxy:$LOCALHOST:$LOCALHOST:$((PORT+3)),pf=ip4,proxyport=$((PORT+1)),resolve"
|
#CMD3="$SOCAT $opts -lpwrapper -t3 tcp4-l:$((PORT+2)),reuseaddr,bind=$LOCALHOST,fork proxy:$LOCALHOST:$LOCALHOST:$((PORT+3)),pf=ip4,proxyport=$((PORT+1)),resolve"
|
||||||
|
CMD3="$SOCAT $opts -lu -lpwrapper -t3 tcp4-l:$((PORT+2)),reuseaddr,bind=$LOCALHOST,fork proxy:$LOCALHOST:$((PORT+3)),resolve\\|tcp4:$LOCALHOST:$((PORT+1))"
|
||||||
# this is our double client in the protected network using SSL
|
# this is our double client in the protected network using SSL
|
||||||
CMD4="$SOCAT $opts -lp2client -t3 ssl:$LOCALHOST:$((PORT+2)),retry=10,intervall=1,cert=testcli.pem,cafile=testsrv.crt,verify,fork,$SOCAT_EGD tcp4:$LOCALHOST:$PORT"
|
#CMD4="$SOCAT $opts -lp2client -t3 ssl:$LOCALHOST:$((PORT+2)),retry=10,intervall=1,cert=testcli.pem,cafile=testsrv.crt,verify,fork,$SOCAT_EGD tcp4:$LOCALHOST:$PORT"
|
||||||
|
#CMD4="$SOCAT $opts -lu -lp2client -t3 ssl,cert=testcli.pem,cafile=testsrv.crt,fork,$SOCAT_EGD,retry=10,intervall=1\\|tcp4:$LOCALHOST:$((PORT+2)) tcp4:$LOCALHOST:$PORT"
|
||||||
|
CMD4="$SOCAT $opts -lu -lp2client -t3 tcp4:$LOCALHOST:$((PORT+2)),fork ^ssl,cert=testcli.pem,cafile=testsrv.crt,$SOCAT_EGD,retry=10,intervall=1\\|tcp4:$LOCALHOST:$PORT"
|
||||||
# this is the double server in the outside network
|
# this is the double server in the outside network
|
||||||
CMD5="$SOCAT $opts -lp2server -t4 tcp4-l:$((PORT+4)),reuseaddr,bind=$LOCALHOST,fork ssl-l:$((PORT+3)),pf=ip4,reuseaddr,bind=$LOCALHOST,$SOCAT_EGD,cert=testsrv.pem,cafile=testcli.crt,retry=10"
|
#CMD5="$SOCAT $opts -lp2server -t4 tcp4-l:$((PORT+4)),reuseaddr,bind=$LOCALHOST,fork ssl-l:$((PORT+3)),pf=ip4,reuseaddr,bind=$LOCALHOST,$SOCAT_EGD,cert=testsrv.pem,cafile=testcli.crt,retry=10"
|
||||||
|
#CMD5="$SOCAT $opts -lp2server -t4 tcp4-l:$((PORT+4)),reuseaddr,bind=$LOCALHOST,fork tcp4-l:$((PORT+3)),reuseaddr,bind=$LOCALHOST,retry=10\\|ssl-l,$SOCAT_EGD,cert=testsrv.pem,cafile=testcli.crt"
|
||||||
|
CMD5="$SOCAT $opts -lp2server -t4 tcp4-l:$((PORT+4)),reuseaddr,bind=$LOCALHOST,fork ssl-l,$SOCAT_EGD,cert=testsrv.pem,cafile=testcli.crt\\|tcp4-l:$((PORT+3)),reuseaddr,bind=$LOCALHOST,retry=10"
|
||||||
# this is the outside client that wants to use the protected server
|
# this is the outside client that wants to use the protected server
|
||||||
CMD6="$SOCAT $opts -lpclient -t5 - tcp4:$LOCALHOST:$((PORT+4)),retry=3"
|
CMD6="$SOCAT $opts -lpclient -t5 - tcp4:$LOCALHOST:$((PORT+4)),retry=3"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
|
@ -4594,7 +4776,9 @@ testserversec () {
|
||||||
#set -vx
|
#set -vx
|
||||||
# assemble address w/ security option; on dual, take read part:
|
# assemble address w/ security option; on dual, take read part:
|
||||||
case "$arg1" in
|
case "$arg1" in
|
||||||
*!!*) arg="${arg1%!!*},$secopt1!!${arg1#*!!}" ;;
|
#*!!*) arg="${arg1%!!*},$secopt1!!${arg1#*!!}" ;;
|
||||||
|
#*%*) arg="${arg1%\%*}%${arg1#*%},$secopt1" ;;
|
||||||
|
*%*) arg="$arg1,$secopt1" ;;
|
||||||
*) arg="$arg1,$secopt1" ;;
|
*) arg="$arg1,$secopt1" ;;
|
||||||
esac
|
esac
|
||||||
# start server
|
# start server
|
||||||
|
@ -5323,8 +5507,10 @@ tf="$td/test$N.stdout"
|
||||||
te="$td/test$N.stderr"
|
te="$td/test$N.stderr"
|
||||||
tdiff="$td/test$N.diff"
|
tdiff="$td/test$N.diff"
|
||||||
da=$(date)
|
da=$(date)
|
||||||
CMD2="$SOCAT $opts OPENSSL-LISTEN:$PORT,pf=ip4,reuseaddr,$SOCAT_EGD,cert=$SRVCERT.pem,key=$SRVCERT.key,verify=0 pipe"
|
#CMD2="$SOCAT $opts OPENSSL-LISTEN:$PORT,pf=ip4,reuseaddr,$SOCAT_EGD,cert=$SRVCERT.pem,key=$SRVCERT.key,verify=0 pipe"
|
||||||
CMD="$SOCAT $opts - openssl:$LOCALHOST:$PORT,pf=ip4,verify=0,$SOCAT_EGD"
|
CMD2="$SOCAT $opts TCP4-LISTEN:$PORT,reuseaddr ^OPENSSL-LISTEN,$SOCAT_EGD,cert=$SRVCERT.pem,key=$SRVCERT.key,verify=0\|pipe"
|
||||||
|
#CMD="$SOCAT $opts - openssl:$LOCALHOST:$PORT,pf=ip4,verify=0,$SOCAT_EGD"
|
||||||
|
CMD="$SOCAT $opts - openssl,verify=0,$SOCAT_EGD|tcp4:$LOCALHOST:$PORT"
|
||||||
$PRINTF "test $F_n $TEST... " $N
|
$PRINTF "test $F_n $TEST... " $N
|
||||||
eval "$CMD2 2>\"${te}1\" &"
|
eval "$CMD2 2>\"${te}1\" &"
|
||||||
pid=$! # background process id
|
pid=$! # background process id
|
||||||
|
@ -5690,7 +5876,7 @@ tsl=$PORT
|
||||||
ts="127.0.0.1:$tsl"
|
ts="127.0.0.1:$tsl"
|
||||||
da=$(date)
|
da=$(date)
|
||||||
CMD1="$SOCAT $opts TCP6-listen:$tsl,reuseaddr PIPE"
|
CMD1="$SOCAT $opts TCP6-listen:$tsl,reuseaddr PIPE"
|
||||||
CMD2="$SOCAT $opts stdin!!stdout TCP6:$ts"
|
CMD2="$SOCAT $opts stdout%stdin TCP6:$ts"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
$CMD1 >"$tf" 2>"${te}1" &
|
$CMD1 >"$tf" 2>"${te}1" &
|
||||||
pid=$! # background process id
|
pid=$! # background process id
|
||||||
|
@ -6250,7 +6436,7 @@ PORT2=$PORT; PORT=$((PORT+1))
|
||||||
PORT3=$PORT
|
PORT3=$PORT
|
||||||
# we use the forward channel (PORT1) for testing, and have a backward channel
|
# 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
|
# (PORT2) to get the data back, so we get the classical echo behaviour
|
||||||
testserversec "$N" "$TEST" "$opts -s" "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
|
testserversec "$N" "$TEST" "$opts -s" "udp4-sendto:127.0.0.1:$PORT2%udp4-recv:$PORT1,reuseaddr" "" "sp=$PORT3" "udp4-sendto:127.0.0.1:$PORT1%udp4-recv:$PORT2" 4 udp $PORT1 0
|
||||||
fi
|
fi
|
||||||
esac
|
esac
|
||||||
PORT=$((PORT+1))
|
PORT=$((PORT+1))
|
||||||
|
@ -6268,7 +6454,7 @@ PORT1=$PORT; PORT=$((PORT+1))
|
||||||
PORT2=$PORT
|
PORT2=$PORT
|
||||||
# we use the forward channel (PORT1) for testing, and have a backward channel
|
# 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
|
# (PORT2) to get the data back, so we get the classical echo behaviour
|
||||||
testserversec "$N" "$TEST" "$opts -s" "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
|
testserversec "$N" "$TEST" "$opts -s" "udp4-sendto:127.0.0.1:$PORT2%udp4-recv:$PORT1,reuseaddr" "" "lowport" "udp4-sendto:127.0.0.1:$PORT1%udp4-recv:$PORT2" 4 udp $PORT1 0
|
||||||
fi
|
fi
|
||||||
esac
|
esac
|
||||||
PORT=$((PORT+1))
|
PORT=$((PORT+1))
|
||||||
|
@ -6286,7 +6472,7 @@ PORT1=$PORT; PORT=$((PORT+1))
|
||||||
PORT2=$PORT
|
PORT2=$PORT
|
||||||
# we use the forward channel (PORT1) for testing, and have a backward channel
|
# 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
|
# (PORT2) to get the data back, so we get the classical echo behaviour
|
||||||
testserversec "$N" "$TEST" "$opts -s" "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
|
testserversec "$N" "$TEST" "$opts -s" "udp4-sendto:127.0.0.1:$PORT2%udp4-recv:$PORT1,reuseaddr" "" "range=$SECONDADDR/32" "udp4-sendto:127.0.0.1:$PORT1%udp4-recv:$PORT2" 4 udp $PORT1 0
|
||||||
fi
|
fi
|
||||||
esac
|
esac
|
||||||
PORT=$((PORT+1))
|
PORT=$((PORT+1))
|
||||||
|
@ -6308,7 +6494,7 @@ $ECHO "socat: $SECONDADDR" >"$ha"
|
||||||
$ECHO "ALL: ALL" >"$hd"
|
$ECHO "ALL: ALL" >"$hd"
|
||||||
# we use the forward channel (PORT1) for testing, and have a backward channel
|
# 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
|
# (PORT2) to get the data back, so we get the classical echo behaviour
|
||||||
testserversec "$N" "$TEST" "$opts -s" "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
|
testserversec "$N" "$TEST" "$opts -s" "udp4-sendto:127.0.0.1:$PORT2%udp4-recv:$PORT1,reuseaddr" "" "tcpwrap-etc=$td" "udp4-sendto:127.0.0.1:$PORT1%udp4-recv:$PORT2" 4 udp $PORT1 0
|
||||||
fi ;; # feat
|
fi ;; # feat
|
||||||
esac
|
esac
|
||||||
PORT=$((PORT+1))
|
PORT=$((PORT+1))
|
||||||
|
@ -6390,7 +6576,7 @@ PORT2=$PORT; PORT=$((PORT+1))
|
||||||
PORT3=$PORT
|
PORT3=$PORT
|
||||||
# we use the forward channel (PORT1) for testing, and have a backward channel
|
# 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
|
# (PORT2) to get the data back, so we get the classical echo behaviour
|
||||||
testserversec "$N" "$TEST" "$opts -s" "udp6-recv:$PORT1,reuseaddr!!udp6-sendto:[::1]:$PORT2" "" "sp=$PORT3" "udp6-recv:$PORT2!!udp6-sendto:[::1]:$PORT1" 6 udp $PORT1 0
|
testserversec "$N" "$TEST" "$opts -s" "udp6-sendto:[::1]:$PORT2%udp6-recv:$PORT1,reuseaddr" "" "sp=$PORT3" "udp6-sendto:[::1]:$PORT1%udp6-recv:$PORT2" 6 udp $PORT1 0
|
||||||
fi
|
fi
|
||||||
esac
|
esac
|
||||||
PORT=$((PORT+1))
|
PORT=$((PORT+1))
|
||||||
|
@ -6408,7 +6594,7 @@ PORT1=$PORT; PORT=$((PORT+1))
|
||||||
PORT2=$PORT
|
PORT2=$PORT
|
||||||
# we use the forward channel (PORT1) for testing, and have a backward channel
|
# 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
|
# (PORT2) to get the data back, so we get the classical echo behaviour
|
||||||
testserversec "$N" "$TEST" "$opts -s" "udp6-recv:$PORT1,reuseaddr!!udp6-sendto:[::1]:$PORT2" "" "lowport" "udp6-recv:$PORT2!!udp6-sendto:[::1]:$PORT1" 6 udp $PORT1 0
|
testserversec "$N" "$TEST" "$opts -s" "udp6-sendto:[::1]:$PORT2%udp6-recv:$PORT1,reuseaddr" "" "lowport" "udp6-sendto:[::1]:$PORT1%udp6-recv:$PORT2" 6 udp $PORT1 0
|
||||||
fi
|
fi
|
||||||
esac
|
esac
|
||||||
PORT=$((PORT+1))
|
PORT=$((PORT+1))
|
||||||
|
@ -6426,7 +6612,7 @@ PORT1=$PORT; PORT=$((PORT+1))
|
||||||
PORT2=$PORT
|
PORT2=$PORT
|
||||||
# we use the forward channel (PORT1) for testing, and have a backward channel
|
# 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
|
# (PORT2) to get the data back, so we get the classical echo behaviour
|
||||||
testserversec "$N" "$TEST" "$opts -s" "udp6-recv:$PORT1,reuseaddr!!udp6-sendto:[::1]:$PORT2" "" "range=[::2/128]" "udp6-recv:$PORT2!!udp6-sendto:[::1]:$PORT1" 6 udp $PORT1 0
|
testserversec "$N" "$TEST" "$opts -s" "udp6-sendto:[::1]:$PORT2%udp6-recv:$PORT1,reuseaddr" "" "range=[::2/128]" "udp6-sendto:[::1]:$PORT1%udp6-recv:$PORT2" 6 udp $PORT1 0
|
||||||
fi
|
fi
|
||||||
esac
|
esac
|
||||||
PORT=$((PORT+1))
|
PORT=$((PORT+1))
|
||||||
|
@ -6448,7 +6634,7 @@ PORT1=$PORT; PORT=$((PORT+1))
|
||||||
PORT2=$PORT
|
PORT2=$PORT
|
||||||
# we use the forward channel (PORT1) for testing, and have a backward channel
|
# 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
|
# (PORT2) to get the data back, so we get the classical echo behaviour
|
||||||
testserversec "$N" "$TEST" "$opts -s" "udp6-recv:$PORT1,reuseaddr!!udp6-sendto:[::1]:$PORT2" "" "tcpwrap-etc=$td" "udp6-recv:$PORT2!!udp6-sendto:[::1]:$PORT1" 6 udp $PORT1 0
|
testserversec "$N" "$TEST" "$opts -s" "udp6-sendto:[::1]:$PORT2%udp6-recv:$PORT1,reuseaddr" "" "tcpwrap-etc=$td" "udp6-sendto:[::1]:$PORT1%udp6-recv:$PORT2" 6 udp $PORT1 0
|
||||||
fi ;; # feat
|
fi ;; # feat
|
||||||
esac
|
esac
|
||||||
PORT=$((PORT+1))
|
PORT=$((PORT+1))
|
||||||
|
@ -6467,7 +6653,7 @@ elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then
|
||||||
numCANT=$((numCANT+1))
|
numCANT=$((numCANT+1))
|
||||||
else
|
else
|
||||||
#testserversec "$N" "$TEST" "$opts -s" "ip4-recvfrom:$PROTO,reuseaddr,fork" "" "range=$SECONDADDR/32" "ip4-sendto:127.0.0.1:$PROTO" 4 ip $PROTO 0
|
#testserversec "$N" "$TEST" "$opts -s" "ip4-recvfrom:$PROTO,reuseaddr,fork" "" "range=$SECONDADDR/32" "ip4-sendto:127.0.0.1:$PROTO" 4 ip $PROTO 0
|
||||||
testserversec "$N" "$TEST" "$opts -s" "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
|
testserversec "$N" "$TEST" "$opts -s" "udp4-sendto:127.0.0.1:$PORT%ip4-recvfrom:$PROTO,reuseaddr" "" "range=$SECONDADDR/32" "ip4-sendto:127.0.0.1:$PROTO%udp4-recv:$PORT" 4 ip $PROTO 0
|
||||||
fi # not feats, not root
|
fi # not feats, not root
|
||||||
esac
|
esac
|
||||||
PROTO=$((PROTO+1))
|
PROTO=$((PROTO+1))
|
||||||
|
@ -6490,7 +6676,7 @@ hd="$td/hosts.deny"
|
||||||
$ECHO "socat: $SECONDADDR" >"$ha"
|
$ECHO "socat: $SECONDADDR" >"$ha"
|
||||||
$ECHO "ALL: ALL" >"$hd"
|
$ECHO "ALL: ALL" >"$hd"
|
||||||
#testserversec "$N" "$TEST" "$opts -s" "ip4-recvfrom:$PROTO,reuseaddr,fork" "" "tcpwrap-etc=$td" "ip4-sendto:127.0.0.1:$PROTO" 4 ip $PROTO 0
|
#testserversec "$N" "$TEST" "$opts -s" "ip4-recvfrom:$PROTO,reuseaddr,fork" "" "tcpwrap-etc=$td" "ip4-sendto:127.0.0.1:$PROTO" 4 ip $PROTO 0
|
||||||
testserversec "$N" "$TEST" "$opts -s" "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
|
testserversec "$N" "$TEST" "$opts -s" "udp4-sendto:127.0.0.1:$PORT%ip4-recvfrom:$PROTO,reuseaddr" "" "tcpwrap-etc=$td" "ip4-sendto:127.0.0.1:$PROTO%udp4-recv:$PORT" 4 ip $PROTO 0
|
||||||
fi # not feats, not root
|
fi # not feats, not root
|
||||||
esac
|
esac
|
||||||
PROTO=$((PROTO+1))
|
PROTO=$((PROTO+1))
|
||||||
|
@ -6513,7 +6699,7 @@ PROTO1=$PROTO; PROTO=$((PROTO+1))
|
||||||
PROTO2=$PROTO
|
PROTO2=$PROTO
|
||||||
# we use the forward channel (PROTO1) for testing, and have a backward channel
|
# 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
|
# (PROTO2) to get the data back, so we get the classical echo behaviour
|
||||||
testserversec "$N" "$TEST" "$opts -s" "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
|
testserversec "$N" "$TEST" "$opts -s" "ip4-sendto:127.0.0.1:$PROTO2%ip4-recv:$PROTO1,reuseaddr" "" "range=$SECONDADDR/32" "ip4-sendto:127.0.0.1:$PROTO1%ip4-recv:$PROTO2" 4 ip $PROTO1 0
|
||||||
fi # not feats, not root
|
fi # not feats, not root
|
||||||
esac
|
esac
|
||||||
PROTO=$((PROTO+1))
|
PROTO=$((PROTO+1))
|
||||||
|
@ -6540,7 +6726,7 @@ $ECHO "socat: $SECONDADDR" >"$ha"
|
||||||
$ECHO "ALL: ALL" >"$hd"
|
$ECHO "ALL: ALL" >"$hd"
|
||||||
# we use the forward channel (PROTO1) for testing, and have a backward channel
|
# 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
|
# (PROTO2) to get the data back, so we get the classical echo behaviour
|
||||||
testserversec "$N" "$TEST" "$opts -s" "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
|
testserversec "$N" "$TEST" "$opts -s" "ip4-sendto:127.0.0.1:$PROTO2%ip4-recv:$PROTO1,reuseaddr" "" "tcpwrap-etc=$td" "ip4-sendto:127.0.0.1:$PROTO1%ip4-recv:$PROTO2" 4 ip $PROTO1 0
|
||||||
fi # not feats, not root
|
fi # not feats, not root
|
||||||
esac
|
esac
|
||||||
PROTO=$((PROTO+1))
|
PROTO=$((PROTO+1))
|
||||||
|
@ -6559,7 +6745,7 @@ elif [ $(id -u) -ne 0 -a "$withroot" -eq 0 ]; then
|
||||||
numCANT=$((numCANT+1))
|
numCANT=$((numCANT+1))
|
||||||
else
|
else
|
||||||
#testserversec "$N" "$TEST" "$opts -s" "ip6-recvfrom:$PROTO,reuseaddr,fork" "" "range=[::2/128]" "ip6-sendto:[::1]:$PROTO" 6 ip $PROTO 0
|
#testserversec "$N" "$TEST" "$opts -s" "ip6-recvfrom:$PROTO,reuseaddr,fork" "" "range=[::2/128]" "ip6-sendto:[::1]:$PROTO" 6 ip $PROTO 0
|
||||||
testserversec "$N" "$TEST" "$opts -s" "ip6-recvfrom:$PROTO,reuseaddr!!udp6-sendto:[::1]:$PORT" "" "range=[::2/128]" "udp6-recv:$PORT!!ip6-sendto:[::1]:$PROTO" 6 ip $PROTO 0
|
testserversec "$N" "$TEST" "$opts -s" "udp6-sendto:[::1]:$PORT%ip6-recvfrom:$PROTO,reuseaddr" "" "range=[::2/128]" "ip6-sendto:[::1]:$PROTO%udp6-recv:$PORT" 6 ip $PROTO 0
|
||||||
fi # not feats, not root
|
fi # not feats, not root
|
||||||
esac
|
esac
|
||||||
PROTO=$((PROTO+1))
|
PROTO=$((PROTO+1))
|
||||||
|
@ -6582,7 +6768,7 @@ hd="$td/hosts.deny"
|
||||||
$ECHO "socat: [::2]" >"$ha"
|
$ECHO "socat: [::2]" >"$ha"
|
||||||
$ECHO "ALL: ALL" >"$hd"
|
$ECHO "ALL: ALL" >"$hd"
|
||||||
#testserversec "$N" "$TEST" "$opts -s" "ip6-recvfrom:$PROTO,reuseaddr,fork" "" "tcpwrap-etc=$td" "ip6-sendto:[::1]:$PROTO" 6 ip $PROTO 0
|
#testserversec "$N" "$TEST" "$opts -s" "ip6-recvfrom:$PROTO,reuseaddr,fork" "" "tcpwrap-etc=$td" "ip6-sendto:[::1]:$PROTO" 6 ip $PROTO 0
|
||||||
testserversec "$N" "$TEST" "$opts -s" "ip6-recvfrom:$PROTO,reuseaddr!!udp6-sendto:[::1]:$PORT" "" "tcpwrap-etc=$td" "udp6-recv:$PORT!!ip6-sendto:[::1]:$PROTO" 6 ip $PROTO 0
|
testserversec "$N" "$TEST" "$opts -s" "udp6-sendto:[::1]:$PORT%ip6-recvfrom:$PROTO,reuseaddr" "" "tcpwrap-etc=$td" "ip6-sendto:[::1]:$PROTO%udp6-recv:$PORT" 6 ip $PROTO 0
|
||||||
fi # not feats, not root
|
fi # not feats, not root
|
||||||
esac
|
esac
|
||||||
PROTO=$((PROTO+1))
|
PROTO=$((PROTO+1))
|
||||||
|
@ -6605,7 +6791,7 @@ PROTO1=$PROTO; PROTO=$((PROTO+1))
|
||||||
PROTO2=$PROTO
|
PROTO2=$PROTO
|
||||||
# we use the forward channel (PROTO1) for testing, and have a backward channel
|
# 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
|
# (PROTO2) to get the data back, so we get the classical echo behaviour
|
||||||
testserversec "$N" "$TEST" "$opts -s" "ip6-recv:$PROTO1,reuseaddr!!ip6-sendto:[::1]:$PROTO2" "" "range=[::2/128]" "ip6-recv:$PROTO2!!ip6-sendto:[::1]:$PROTO1" 6 ip $PROTO1 0
|
testserversec "$N" "$TEST" "$opts -s" "ip6-sendto:[::1]:$PROTO2%ip6-recv:$PROTO1,reuseaddr" "" "range=[::2/128]" "ip6-sendto:[::1]:$PROTO1%ip6-recv:$PROTO2" 6 ip $PROTO1 0
|
||||||
fi # not feats, not root
|
fi # not feats, not root
|
||||||
esac
|
esac
|
||||||
PROTO=$((PROTO+1))
|
PROTO=$((PROTO+1))
|
||||||
|
@ -6630,7 +6816,7 @@ $ECHO "socat: [::2]" >"$ha"
|
||||||
$ECHO "ALL: ALL" >"$hd"
|
$ECHO "ALL: ALL" >"$hd"
|
||||||
# we use the forward channel (PROTO1) for testing, and have a backward channel
|
# 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
|
# (PROTO2) to get the data back, so we get the classical echo behaviour
|
||||||
testserversec "$N" "$TEST" "$opts -s" "ip6-recv:$PROTO1,reuseaddr!!ip6-sendto:[::1]:$PROTO2" "" "tcpwrap-etc=$td" "ip6-recv:$PROTO2!!ip6-sendto:[::1]:$PROTO1" 6 ip $PROTO1 0
|
testserversec "$N" "$TEST" "$opts -s" "ip6-sendto:[::1]:$PROTO2%ip6-recv:$PROTO1,reuseaddr" "" "tcpwrap-etc=$td" "ip6-sendto:[::1]:$PROTO1%ip6-recv:$PROTO2" 6 ip $PROTO1 0
|
||||||
fi # not feats, not root
|
fi # not feats, not root
|
||||||
esac
|
esac
|
||||||
PROTO=$((PROTO+1))
|
PROTO=$((PROTO+1))
|
||||||
|
@ -6836,10 +7022,27 @@ esac
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
|
||||||
|
# purpose of the shut-none option is to keep a shared socket
|
||||||
|
# open. with shared we mean that two or more processes use it. usually, when a
|
||||||
|
# process closes a socket, it performs a shutdown procedure with half close.
|
||||||
|
# on a shared socket, this would shutdown the socket as a whole, disabling it
|
||||||
|
# for all processes. the shut-none option does not shutdown but close the
|
||||||
|
# socket; this just removes the processes reference to the socket but keeps it
|
||||||
|
# open for the other processes.
|
||||||
NAME=TCP4ENDCLOSE
|
NAME=TCP4ENDCLOSE
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%functions%*|*%ip4%*|*%ipapp%*|*%tcp%*|*%$NAME%*)
|
*%functions%*|*%ip4%*|*%ipapp%*|*%tcp%*|*%$NAME%*)
|
||||||
TEST="$NAME: end-close keeps TCP V4 socket open"
|
TEST="$NAME: shut-none keeps TCP V4 socket open"
|
||||||
|
# this is how we test the shut-none option:
|
||||||
|
# we have some tcp service (CMD3) that accepts one connection and only receives
|
||||||
|
# date.
|
||||||
|
# a multiplexer process (CMD) opens a connection to that service; it accepts
|
||||||
|
# multiple connections from client processes and merges and forwards their
|
||||||
|
# data; each client is handled in a sub process with a clone of the forwarder
|
||||||
|
# socket.
|
||||||
|
# two client processes connect and send data. normally, the "common" connection
|
||||||
|
# would terminate when the first client disconnects; with the shut-none option,
|
||||||
|
# the data of the second process also has to arrive at the target service.
|
||||||
tf="$td/test$N.stdout"
|
tf="$td/test$N.stdout"
|
||||||
te="$td/test$N.stderr"
|
te="$td/test$N.stderr"
|
||||||
tdiff="$td/test$N.diff"
|
tdiff="$td/test$N.diff"
|
||||||
|
@ -6848,7 +7051,7 @@ p2=$PORT
|
||||||
da1a="$(date) $RANDOM"
|
da1a="$(date) $RANDOM"
|
||||||
da1b="$(date) $RANDOM"
|
da1b="$(date) $RANDOM"
|
||||||
CMD1="$SOCAT $opts -u - TCP4-CONNECT:$LOCALHOST:$p1"
|
CMD1="$SOCAT $opts -u - TCP4-CONNECT:$LOCALHOST:$p1"
|
||||||
CMD="$SOCAT $opts -U TCP4:$LOCALHOST:$p2,end-close TCP4-LISTEN:$p1,bind=$LOCALHOST,reuseaddr,fork"
|
CMD="$SOCAT $opts -U TCP4:$LOCALHOST:$p2,shut-none TCP4-LISTEN:$p1,bind=$LOCALHOST,reuseaddr,fork"
|
||||||
CMD3="$SOCAT $opts -u TCP4-LISTEN:$p2,reuseaddr,bind=$LOCALHOST -"
|
CMD3="$SOCAT $opts -u TCP4-LISTEN:$p2,reuseaddr,bind=$LOCALHOST -"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
$CMD3 >"$tf" 2>"${te}3" &
|
$CMD3 >"$tf" 2>"${te}3" &
|
||||||
|
@ -6882,11 +7085,21 @@ esac
|
||||||
PORT=$((PORT+1))
|
PORT=$((PORT+1))
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
|
||||||
|
# purpose: see above; here we do not test against a TCP socket but an exec'd
|
||||||
|
# sub process (socketpair)
|
||||||
NAME=EXECENDCLOSE
|
NAME=EXECENDCLOSE
|
||||||
case "$TESTS" in
|
case "$TESTS" in
|
||||||
*%functions%*|*%exec%*|*%$NAME%*)
|
*%functions%*|*%exec%*|*%$NAME%*)
|
||||||
TEST="$NAME: end-close keeps EXEC child running"
|
TEST="$NAME: shut-none keeps EXEC child running"
|
||||||
|
# this is how we test the shut-none option:
|
||||||
|
# we have a server process (CMD) that runs a program (cat); the process accepts
|
||||||
|
# multiple connections from client processes and merges and forwards their
|
||||||
|
# data; each client is handled in a sub process with a clone of the forwarder
|
||||||
|
# socket.
|
||||||
|
# two client processes connect and send data. normally, the "common" connection
|
||||||
|
# the the cat sub process would terminate when the first client disconnects;
|
||||||
|
# with the shut-none option, the data of the second process also has to arrive
|
||||||
|
# at the target service.
|
||||||
tf="$td/test$N.stdout"
|
tf="$td/test$N.stdout"
|
||||||
te="$td/test$N.stderr"
|
te="$td/test$N.stderr"
|
||||||
ts="$td/test$N.sock"
|
ts="$td/test$N.sock"
|
||||||
|
@ -6894,7 +7107,7 @@ tdiff="$td/test$N.diff"
|
||||||
da1a="$(date) $RANDOM"
|
da1a="$(date) $RANDOM"
|
||||||
da1b="$(date) $RANDOM"
|
da1b="$(date) $RANDOM"
|
||||||
CMD1="$SOCAT $opts - UNIX-CONNECT:$ts"
|
CMD1="$SOCAT $opts - UNIX-CONNECT:$ts"
|
||||||
CMD="$SOCAT -t0.1 $opts EXEC:"$CAT",end-close UNIX-LISTEN:$ts,fork"
|
CMD="$SOCAT -t0.1 $opts EXEC:"$CAT",shut-none,end-close UNIX-LISTEN:$ts,fork"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
$CMD 2>"${te}2" &
|
$CMD 2>"${te}2" &
|
||||||
pid2=$!
|
pid2=$!
|
||||||
|
@ -6906,16 +7119,18 @@ usleep 100000
|
||||||
kill "$pid2" 2>/dev/null
|
kill "$pid2" 2>/dev/null
|
||||||
wait
|
wait
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
$PRINTF "$FAILED: $SOCAT:\n"
|
$PRINTF "$FAILED\n"
|
||||||
echo "$CMD1 &"
|
echo "$CMD1 &"
|
||||||
echo "$CMD2"
|
echo "$CMD"
|
||||||
cat "${te}1a" "${te}1b" "${te}2"
|
cat "${te}1a" "${te}1b" "${te}2"
|
||||||
$PRINTF "$FAILED: $SOCAT:\n"
|
numFAIL=$((numFAIL+1))
|
||||||
elif ! echo -e "$da1a\n$da1b" |diff - "$tf" >"$tdiff"; then
|
elif ! echo -e "$da1a\n$da1b" |diff - "$tf" >"$tdiff"; then
|
||||||
$PRINTF "$FAILED\n"
|
$PRINTF "$FAILED\n"
|
||||||
|
echo "$CMD1 &"
|
||||||
|
echo "$CMD"
|
||||||
cat "$tdiff"
|
cat "$tdiff"
|
||||||
cat "${te}1a" "${te}1b" "${te}2"
|
cat "${te}1a" "${te}1b" "${te}2"
|
||||||
$PRINTF "$FAILED: $SOCAT:\n"
|
numFAIL=$((numFAIL+1))
|
||||||
else
|
else
|
||||||
$PRINTF "$OK\n"
|
$PRINTF "$OK\n"
|
||||||
if [ -n "$debug" ]; then cat "${te}1a" "${te}1b" "${te}2"; fi
|
if [ -n "$debug" ]; then cat "${te}1a" "${te}1b" "${te}2"; fi
|
||||||
|
@ -7721,7 +7936,7 @@ to="$td/test$N.out"
|
||||||
te="$td/test$N.err"
|
te="$td/test$N.err"
|
||||||
tdiff="$td/test$N.diff"
|
tdiff="$td/test$N.diff"
|
||||||
da="$(date)" da="$da$($ECHO '\r')"
|
da="$(date)" da="$da$($ECHO '\r')"
|
||||||
CMD="$SOCAT $opts system:\"echo A; sleep 2\",readbytes=2!!- -!!/dev/null"
|
CMD="$SOCAT $opts -%system:\"echo A; sleep 2\",readbytes=2 /dev/null%-"
|
||||||
printf "test $F_n $TEST... " $N
|
printf "test $F_n $TEST... " $N
|
||||||
(sleep 1; echo) |eval "$CMD" >"$to" 2>"$te"
|
(sleep 1; echo) |eval "$CMD" >"$to" 2>"$te"
|
||||||
if test -s "$to"; then
|
if test -s "$to"; then
|
||||||
|
|
20
xio-creat.c
20
xio-creat.c
|
@ -1,5 +1,5 @@
|
||||||
/* $Id: xio-creat.c,v 1.16 2006/07/13 06:39:01 gerhard Exp $ */
|
/* $Id: xio-creat.c,v 1.16.2.1 2006/07/24 19:17:32 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2001-2006 */
|
/* Copyright Gerhard Rieger 2001-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
/* this file contains the source for opening addresses of create type */
|
/* this file contains the source for opening addresses of create type */
|
||||||
|
@ -17,8 +17,11 @@ static int xioopen_creat(int arg, const char *argv[], struct opt *opts, int rw,
|
||||||
|
|
||||||
|
|
||||||
/*! within stream model, this is a write-only address - use 2 instead of 3 */
|
/*! within stream model, this is a write-only address - use 2 instead of 3 */
|
||||||
const struct addrdesc addr_creat = { "create", 3, xioopen_creat, GROUP_FD|GROUP_NAMED|GROUP_FILE, 0, 0, 0 HELP(":<filename>") };
|
static const struct xioaddr_endpoint_desc xioaddr_creat1 = { XIOADDR_SYS, "create", 1, XIOBIT_ALL/*?*/, GROUP_FD|GROUP_NAMED|GROUP_FILE, XIOSHUT_NONE, XIOCLOSE_CLOSE, xioopen_creat, 0, 0, 0 HELP(":<filename>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_creat[] = {
|
||||||
|
(union xioaddr_desc *)&xioaddr_creat1,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
/* retrieve the mode option and perform the creat() call.
|
/* retrieve the mode option and perform the creat() call.
|
||||||
returns the file descriptor or a negative value. */
|
returns the file descriptor or a negative value. */
|
||||||
|
@ -60,15 +63,16 @@ static int xioopen_creat(int argc, const char *argv[], struct opt *opts, int xio
|
||||||
Notice2("creating regular file \"%s\" for %s", filename, ddirection[rw]);
|
Notice2("creating regular file \"%s\" for %s", filename, ddirection[rw]);
|
||||||
if ((result = _xioopen_creat(filename, rw, opts)) < 0)
|
if ((result = _xioopen_creat(filename, rw, opts)) < 0)
|
||||||
return result;
|
return result;
|
||||||
fd->stream.fd = result;
|
fd->stream.fd1 = fd->stream.fd2 = result;
|
||||||
|
fd->stream.fdtype = FDTYPE_SINGLE;
|
||||||
|
|
||||||
applyopts_named(filename, opts, PH_PASTOPEN);
|
applyopts_named(filename, opts, PH_PASTOPEN);
|
||||||
if ((result = applyopts2(fd->stream.fd, opts, PH_PASTOPEN, PH_LATE2)) < 0)
|
if ((result = applyopts2(fd->stream.fd1, opts, PH_PASTOPEN, PH_LATE2)) < 0)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
applyopts_cloexec(fd->stream.fd, opts);
|
applyopts_cloexec(fd->stream.fd1, opts);
|
||||||
|
|
||||||
applyopts_fchown(fd->stream.fd, opts);
|
applyopts_fchown(fd->stream.fd1, opts);
|
||||||
|
|
||||||
if ((result = _xio_openlate(&fd->stream, opts)) < 0)
|
if ((result = _xio_openlate(&fd->stream, opts)) < 0)
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
/* $Id: xio-creat.h,v 1.4 2001/11/04 17:19:20 gerhard Exp $ */
|
/* $Id: xio-creat.h,v 1.4.2.1 2006/07/24 19:17:34 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2001 */
|
/* Copyright Gerhard Rieger 2001-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
#ifndef __xio_creat_h_included
|
#ifndef __xio_creat_h_included
|
||||||
#define __xio_creat_h_included 1
|
#define __xio_creat_h_included 1
|
||||||
|
|
||||||
extern const struct addrdesc addr_creat;
|
extern const union xioaddr_desc *xioaddrs_creat[];
|
||||||
|
|
||||||
#endif /* !defined(__xio_creat_h_included) */
|
#endif /* !defined(__xio_creat_h_included) */
|
||||||
|
|
27
xio-exec.c
27
xio-exec.c
|
@ -1,8 +1,11 @@
|
||||||
/* $Id: xio-exec.c,v 1.19 2006/07/12 21:59:28 gerhard Exp $ */
|
/* $Id: xio-exec.c,v 1.19.2.1 2006/07/24 19:17:35 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2001-2006 */
|
/* Copyright Gerhard Rieger 2001-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
/* this file contains the source for opening addresses of exec type */
|
/* this file contains the source for opening addresses of exec type */
|
||||||
|
/* this file contains the source for an inter address that just invokes a
|
||||||
|
program. The program should provide its data side on FDs 0 and 1, and its
|
||||||
|
protocol side on FDs 3 and 4. */
|
||||||
|
|
||||||
#include "xiosysincludes.h"
|
#include "xiosysincludes.h"
|
||||||
#include "xioopen.h"
|
#include "xioopen.h"
|
||||||
|
@ -13,18 +16,25 @@
|
||||||
|
|
||||||
#if WITH_EXEC
|
#if WITH_EXEC
|
||||||
|
|
||||||
static int xioopen_exec(int argc, const char *argv[], struct opt *opts,
|
static int xioopen_exec1end(int argc, const char *argv[], struct opt *opts,
|
||||||
int xioflags, /* XIO_RDONLY etc. */
|
int xioflags, /* XIO_RDONLY etc. */
|
||||||
xiofile_t *fd,
|
xiofile_t *fd,
|
||||||
unsigned groups,
|
unsigned groups,
|
||||||
int dummy1, int dummy2, int dummy3
|
int dummy1, int dummy2, int dummy3
|
||||||
);
|
);
|
||||||
|
|
||||||
const struct addrdesc addr_exec = { "exec", 3, xioopen_exec, GROUP_FD|GROUP_FORK|GROUP_EXEC|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_TERMIOS|GROUP_FIFO|GROUP_PTY|GROUP_PARENT, 0, 0, 0 HELP(":<command-line>") };
|
|
||||||
|
static const struct xioaddr_endpoint_desc xioaddr_exec1end = { XIOADDR_ENDPOINT, "exec", 1, XIOBIT_ALL, GROUP_FD|GROUP_FORK|GROUP_EXEC|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_TERMIOS|GROUP_FIFO|GROUP_PTY|GROUP_PARENT, XIOSHUT_UNSPEC, XIOCLOSE_UNSPEC, xioopen_exec1end, 0, 0, 0 HELP(":<command-line>") };
|
||||||
|
|
||||||
|
const union xioaddr_desc *xioaddrs_exec[] = {
|
||||||
|
(union xioaddr_desc *)&xioaddr_exec1end,
|
||||||
|
NULL };
|
||||||
|
|
||||||
|
|
||||||
const struct optdesc opt_dash = { "dash", "login", OPT_DASH, GROUP_EXEC, PH_PREEXEC, TYPE_BOOL, OFUNC_SPEC };
|
const struct optdesc opt_dash = { "dash", "login", OPT_DASH, GROUP_EXEC, PH_PREEXEC, TYPE_BOOL, OFUNC_SPEC };
|
||||||
|
|
||||||
static int xioopen_exec(int argc, const char *argv[], struct opt *opts,
|
|
||||||
|
static int xioopen_exec1end(int argc, const char *argv[], struct opt *opts,
|
||||||
int xioflags, /* XIO_RDONLY, XIO_MAYCHILD etc. */
|
int xioflags, /* XIO_RDONLY, XIO_MAYCHILD etc. */
|
||||||
xiofile_t *fd,
|
xiofile_t *fd,
|
||||||
unsigned groups,
|
unsigned groups,
|
||||||
|
@ -39,7 +49,7 @@ static int xioopen_exec(int argc, const char *argv[], struct opt *opts,
|
||||||
|
|
||||||
retropt_bool(opts, OPT_DASH, &dash);
|
retropt_bool(opts, OPT_DASH, &dash);
|
||||||
|
|
||||||
status = _xioopen_foxec(xioflags, &fd->stream, groups, &opts);
|
status = _xioopen_foxec_end(xioflags, &fd->stream, groups, &opts);
|
||||||
if (status < 0) return status;
|
if (status < 0) return status;
|
||||||
if (status == 0) { /* child */
|
if (status == 0) { /* child */
|
||||||
const char *ends[] = { " ", NULL };
|
const char *ends[] = { " ", NULL };
|
||||||
|
@ -74,7 +84,7 @@ static int xioopen_exec(int argc, const char *argv[], struct opt *opts,
|
||||||
token = Malloc(len); /*! */
|
token = Malloc(len); /*! */
|
||||||
tokp = token;
|
tokp = token;
|
||||||
if (nestlex(&strp, &tokp, &len, ends, hquotes, squotes, nests,
|
if (nestlex(&strp, &tokp, &len, ends, hquotes, squotes, nests,
|
||||||
true, true, false) < 0) {
|
false, true, true, false) < 0) {
|
||||||
Error("internal: miscalculated string lengths");
|
Error("internal: miscalculated string lengths");
|
||||||
}
|
}
|
||||||
*tokp++ = '\0';
|
*tokp++ = '\0';
|
||||||
|
@ -89,7 +99,7 @@ static int xioopen_exec(int argc, const char *argv[], struct opt *opts,
|
||||||
++strp;
|
++strp;
|
||||||
pargv[pargc++] = tokp;
|
pargv[pargc++] = tokp;
|
||||||
if (nestlex(&strp, &tokp, &len, ends, hquotes, squotes, nests,
|
if (nestlex(&strp, &tokp, &len, ends, hquotes, squotes, nests,
|
||||||
true, true, false) < 0) {
|
false, true, true, false) < 0) {
|
||||||
Error("internal: miscalculated string lengths");
|
Error("internal: miscalculated string lengths");
|
||||||
}
|
}
|
||||||
*tokp++ = '\0';
|
*tokp++ = '\0';
|
||||||
|
@ -134,4 +144,5 @@ static int xioopen_exec(int argc, const char *argv[], struct opt *opts,
|
||||||
/* parent */
|
/* parent */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* WITH_EXEC */
|
#endif /* WITH_EXEC */
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
/* $Id: xio-exec.h,v 1.6 2002/05/19 08:05:36 gerhard Exp $ */
|
/* $Id: xio-exec.h,v 1.6.2.1 2006/07/24 19:17:37 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2001, 2002 */
|
/* Copyright Gerhard Rieger 2001-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
#ifndef __xio_exec_h_included
|
#ifndef __xio_exec_h_included
|
||||||
#define __xio_exec_h_included 1
|
#define __xio_exec_h_included 1
|
||||||
|
|
||||||
extern const struct addrdesc addr_exec;
|
extern const union xioaddr_desc *xioaddrs_exec[];
|
||||||
|
|
||||||
extern const struct optdesc opt_dash;
|
extern const struct optdesc opt_dash;
|
||||||
|
|
||||||
|
|
5
xio-fd.c
5
xio-fd.c
|
@ -1,5 +1,5 @@
|
||||||
/* $Id: xio-fd.c,v 1.26 2006/12/28 07:35:50 gerhard Exp $ */
|
/* $Id: xio-fd.c,v 1.26 2006/12/28 07:35:50 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2001-2006 */
|
/* Copyright Gerhard Rieger 2001-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
/* this file contains common file descriptor related option definitions */
|
/* this file contains common file descriptor related option definitions */
|
||||||
|
@ -74,4 +74,5 @@ const struct optdesc opt_flock_ex_nb = { "flock-ex-nb", "flock-nb", OPT_FLOCK_E
|
||||||
const struct optdesc opt_cool_write = { "cool-write", "coolwrite", OPT_COOL_WRITE, GROUP_FD, PH_INIT, TYPE_BOOL, OFUNC_OFFSET, (bool)&((xiofile_t *)0)->stream.cool_write };
|
const struct optdesc opt_cool_write = { "cool-write", "coolwrite", OPT_COOL_WRITE, GROUP_FD, PH_INIT, TYPE_BOOL, OFUNC_OFFSET, (bool)&((xiofile_t *)0)->stream.cool_write };
|
||||||
|
|
||||||
/* control closing of connections */
|
/* control closing of connections */
|
||||||
const struct optdesc opt_end_close = { "end-close", "close", OPT_END_CLOSE, GROUP_FD, PH_INIT, TYPE_CONST, OFUNC_OFFSET, (bool)&((xiofile_t *)0)->stream.howtoend, END_CLOSE };
|
const struct optdesc opt_end_close = { "end-close", NULL, OPT_END_CLOSE, GROUP_FD, PH_INIT, TYPE_CONST, OFUNC_OFFSET, (bool)&((xiofile_t *)0)->stream.howtoclose, XIOCLOSE_CLOSE };
|
||||||
|
const struct optdesc opt_shut_none = { "shut-none", NULL, OPT_SHUT_NONE, GROUP_FD, PH_INIT, TYPE_CONST, OFUNC_OFFSET, (bool)&((xiofile_t *)0)->stream.howtoshut, XIOSHUT_NONE };
|
||||||
|
|
3
xio-fd.h
3
xio-fd.h
|
@ -1,5 +1,5 @@
|
||||||
/* $Id: xio-fd.h,v 1.12 2006/12/28 07:35:50 gerhard Exp $ */
|
/* $Id: xio-fd.h,v 1.12 2006/12/28 07:35:50 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2001-2006 */
|
/* Copyright Gerhard Rieger 2001-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
#ifndef __xio_fd_h_included
|
#ifndef __xio_fd_h_included
|
||||||
|
@ -37,5 +37,6 @@ extern const struct optdesc opt_f_setlk_wr;
|
||||||
extern const struct optdesc opt_f_setlkw_wr;
|
extern const struct optdesc opt_f_setlkw_wr;
|
||||||
extern const struct optdesc opt_cool_write;
|
extern const struct optdesc opt_cool_write;
|
||||||
extern const struct optdesc opt_end_close;
|
extern const struct optdesc opt_end_close;
|
||||||
|
extern const struct optdesc opt_shut_none;
|
||||||
|
|
||||||
#endif /* !defined(__xio_fd_h_included) */
|
#endif /* !defined(__xio_fd_h_included) */
|
||||||
|
|
72
xio-fdnum.c
72
xio-fdnum.c
|
@ -1,5 +1,5 @@
|
||||||
/* $Id: xio-fdnum.c,v 1.13 2006/07/08 10:03:14 gerhard Exp $ */
|
/* $Id: xio-fdnum.c,v 1.13.2.1 2006/07/24 19:17:38 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2001-2006 */
|
/* Copyright Gerhard Rieger 2001-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
/* this file contains the source for opening addresses of fdnum type */
|
/* this file contains the source for opening addresses of fdnum type */
|
||||||
|
@ -15,8 +15,13 @@
|
||||||
static int xioopen_fdnum(int argc, const char *argv[], struct opt *opts, int rw, xiofile_t *xfd, unsigned groups, int dummy1, int dummy2, int dummy3);
|
static int xioopen_fdnum(int argc, const char *argv[], struct opt *opts, int rw, xiofile_t *xfd, unsigned groups, int dummy1, int dummy2, int dummy3);
|
||||||
|
|
||||||
|
|
||||||
const struct addrdesc addr_fd = { "fd", 3, xioopen_fdnum, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, 0, 0, 0 HELP(":<num>") };
|
const struct xioaddr_endpoint_desc xioaddr_fdnum1 = { XIOADDR_ENDPOINT, "fd", 1, XIOBIT_ALL, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, XIOSHUT_NONE, XIOCLOSE_NONE, xioopen_fdnum, 0, 0, 0 HELP(":<num>") };
|
||||||
|
const struct xioaddr_endpoint_desc xioaddr_fdnum2 = { XIOADDR_ENDPOINT, "fd", 2, XIOBIT_RDWR, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, XIOSHUT_NONE, XIOCLOSE_NONE, xioopen_fdnum, 0, 0, 0 HELP(":<numout>:<numin>") };
|
||||||
|
|
||||||
|
const union xioaddr_desc *xioaddrs_fdnum[] = {
|
||||||
|
(union xioaddr_desc *)&xioaddr_fdnum1,
|
||||||
|
(union xioaddr_desc *)&xioaddr_fdnum2,
|
||||||
|
NULL };
|
||||||
|
|
||||||
/* use some file descriptor and apply the options. Set the FD_CLOEXEC flag. */
|
/* use some file descriptor and apply the options. Set the FD_CLOEXEC flag. */
|
||||||
static int xioopen_fdnum(int argc, const char *argv[], struct opt *opts,
|
static int xioopen_fdnum(int argc, const char *argv[], struct opt *opts,
|
||||||
|
@ -24,23 +29,43 @@ static int xioopen_fdnum(int argc, const char *argv[], struct opt *opts,
|
||||||
int dummy1, int dummy2, int dummy3) {
|
int dummy1, int dummy2, int dummy3) {
|
||||||
char *a1;
|
char *a1;
|
||||||
int rw = (xioflags&XIO_ACCMODE);
|
int rw = (xioflags&XIO_ACCMODE);
|
||||||
int numfd;
|
int numfd1, numfd2 = -1;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if (argc != 2) {
|
if (argc < 2 || argc > 3) {
|
||||||
Error3("%s:%s: wrong number of parameters (%d instead of 1)", argv[0], argv[1], argc-1);
|
Error3("%s:%s: wrong number of parameters (%d instead of 1 or 2)", argv[0], argv[1], argc-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
numfd = strtoul(argv[1], &a1, 0);
|
numfd1 = strtoul(argv[1], &a1, 0);
|
||||||
if (*a1 != '\0') {
|
if (*a1 != '\0') {
|
||||||
Error1("error in FD number \"%s\"", argv[1]);
|
Error1("error in FD number \"%s\"", argv[1]);
|
||||||
}
|
}
|
||||||
/* we dont want to see these fds in child processes */
|
/* we dont want to see these fds in child processes */
|
||||||
if (Fcntl_l(numfd, F_SETFD, FD_CLOEXEC) < 0) {
|
if (Fcntl_l(numfd1, F_SETFD, FD_CLOEXEC) < 0) {
|
||||||
Warn2("fcntl(%d, F_SETFD, FD_CLOEXEC): %s", numfd, strerror(errno));
|
Warn2("fcntl(%d, F_SETFD, FD_CLOEXEC): %s", numfd1, strerror(errno));
|
||||||
}
|
}
|
||||||
Notice2("using file descriptor %d for %s", numfd, ddirection[rw]);
|
|
||||||
if ((result = xioopen_fd(opts, rw, &xfd->stream, numfd, dummy2, dummy3)) < 0) {
|
if (argv[2]) {
|
||||||
|
if (rw != XIO_RDWR) {
|
||||||
|
Warn("two file descriptors given for unidirectional transfer");
|
||||||
|
}
|
||||||
|
numfd2 = numfd1;
|
||||||
|
numfd1 = strtoul(argv[2], &a1, 0);
|
||||||
|
if (*a1 != '\0') {
|
||||||
|
Error1("error in FD number \"%s\"", argv[2]);
|
||||||
|
}
|
||||||
|
/* we dont want to see these fds in child processes */
|
||||||
|
if (Fcntl_l(numfd2, F_SETFD, FD_CLOEXEC) < 0) {
|
||||||
|
Warn2("fcntl(%d, F_SETFD, FD_CLOEXEC): %s", numfd2, strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argv[2] == NULL) {
|
||||||
|
Notice2("using file descriptor %d for %s", numfd1, ddirection[rw]);
|
||||||
|
} else {
|
||||||
|
Notice4("using file descriptors %d for %s and %d for %s", numfd1, ddirection[((rw+1)&1)-1], numfd2, ddirection[((rw+1)&2)-1]);
|
||||||
|
}
|
||||||
|
if ((result = xioopen_fd(opts, rw, xfd, numfd1, numfd2, dummy2, dummy3)) < 0) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -52,27 +77,32 @@ static int xioopen_fdnum(int argc, const char *argv[], struct opt *opts,
|
||||||
|
|
||||||
/* retrieve and apply options to a standard file descriptor.
|
/* retrieve and apply options to a standard file descriptor.
|
||||||
Do not set FD_CLOEXEC flag. */
|
Do not set FD_CLOEXEC flag. */
|
||||||
int xioopen_fd(struct opt *opts, int rw, xiosingle_t *xfd, int numfd, int dummy2, int dummy3) {
|
int xioopen_fd(struct opt *opts, int rw, xiofile_t *xfd, int numfd1, int numfd2, int dummy2, int dummy3) {
|
||||||
|
|
||||||
xfd->fd = numfd;
|
xfd->stream.fd1 = numfd1;
|
||||||
xfd->howtoend = END_NONE;
|
xfd->stream.fd2 = numfd2;
|
||||||
|
if (numfd2 >= 0) {
|
||||||
|
xfd->stream.fdtype = FDTYPE_DOUBLE;
|
||||||
|
} else {
|
||||||
|
xfd->stream.fdtype = FDTYPE_SINGLE;
|
||||||
|
}
|
||||||
|
|
||||||
#if WITH_TERMIOS
|
#if WITH_TERMIOS
|
||||||
if (Isatty(xfd->fd)) {
|
if (Isatty(xfd->stream.fd1)) {
|
||||||
if (Tcgetattr(xfd->fd, &xfd->savetty) < 0) {
|
if (Tcgetattr(xfd->stream.fd1, &xfd->stream.savetty) < 0) {
|
||||||
Warn2("cannot query current terminal settings on fd %d: %s",
|
Warn2("cannot query current terminal settings on fd %d: %s",
|
||||||
xfd->fd, strerror(errno));
|
xfd->stream.fd1, strerror(errno));
|
||||||
} else {
|
} else {
|
||||||
xfd->ttyvalid = true;
|
xfd->stream.ttyvalid = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WITH_TERMIOS */
|
#endif /* WITH_TERMIOS */
|
||||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1;
|
||||||
applyopts(-1, opts, PH_INIT);
|
applyopts(-1, opts, PH_INIT);
|
||||||
|
|
||||||
applyopts2(xfd->fd, opts, PH_INIT, PH_FD);
|
applyopts2(xfd->stream.fd1, opts, PH_INIT, PH_FD);
|
||||||
|
|
||||||
return _xio_openlate(xfd, opts);
|
return _xio_openlate(&xfd->stream, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* WITH_FD */
|
#endif /* WITH_FD */
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
/* $Id: xio-fdnum.h,v 1.6 2006/03/21 20:48:31 gerhard Exp $ */
|
/* $Id: xio-fdnum.h,v 1.6.2.1 2006/07/24 19:17:40 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2001-2006 */
|
/* Copyright Gerhard Rieger 2001-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
#ifndef __xio_fdnum_h_included
|
#ifndef __xio_fdnum_h_included
|
||||||
#define __xio_fdnum_h_included 1
|
#define __xio_fdnum_h_included 1
|
||||||
|
|
||||||
extern const struct addrdesc addr_fd;
|
extern const struct xioaddr_endpoint_desc xioaddr_fdnum1;
|
||||||
|
extern const union xioaddr_desc *xioaddrs_fdnum[];
|
||||||
|
|
||||||
extern int xioopen_fd(struct opt *opts, int rw, xiosingle_t *xfd, int numfd, int dummy2, int dummy3);
|
extern int xioopen_fd(struct opt *opts, int rw, xiofile_t *xfd, int numfd1, int numfd2, int dummy2, int dummy3);
|
||||||
|
|
||||||
#endif /* !defined(__xio_fdnum_h_included) */
|
#endif /* !defined(__xio_fdnum_h_included) */
|
||||||
|
|
25
xio-file.c
25
xio-file.c
|
@ -11,7 +11,7 @@
|
||||||
#include "xio-file.h"
|
#include "xio-file.h"
|
||||||
|
|
||||||
|
|
||||||
static int xioopen_open(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3);
|
static int xioopen_open1(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3);
|
||||||
|
|
||||||
|
|
||||||
#if WITH_OPEN
|
#if WITH_OPEN
|
||||||
|
@ -66,13 +66,17 @@ const struct optdesc opt_o_trunc = { "o-trunc", "trunc", OPT_O_TRUNC,
|
||||||
|
|
||||||
#if _WITH_FILE /*! inconsistent name FILE vs. OPEN */
|
#if _WITH_FILE /*! inconsistent name FILE vs. OPEN */
|
||||||
|
|
||||||
const struct addrdesc addr_open = { "open", 3, xioopen_open, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_REG|GROUP_NAMED|GROUP_OPEN|GROUP_FILE|GROUP_TERMIOS, 0, 0, 0 HELP(":<filename>") };
|
static const struct xioaddr_endpoint_desc xioaddr_open1 = { XIOADDR_SYS, "open", 1, XIOBIT_ALL, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_REG|GROUP_NAMED|GROUP_OPEN|GROUP_FILE|GROUP_TERMIOS, XIOSHUT_CLOSE, XIOCLOSE_CLOSE, xioopen_open1, 0, 0, 0 HELP(":<filename>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_open[] = {
|
||||||
|
(union xioaddr_desc *)&xioaddr_open1,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
/* open for writing:
|
/* open for writing:
|
||||||
if the filesystem entry already exists, the data is appended
|
if the filesystem entry already exists, the data is appended
|
||||||
if it does not exist, a file is created and the data is appended
|
if it does not exist, a file is created and the data is appended
|
||||||
*/
|
*/
|
||||||
static int xioopen_open(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3) {
|
static int xioopen_open1(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3) {
|
||||||
const char *filename = argv[1];
|
const char *filename = argv[1];
|
||||||
int rw = (xioflags & XIO_ACCMODE);
|
int rw = (xioflags & XIO_ACCMODE);
|
||||||
bool exists;
|
bool exists;
|
||||||
|
@ -96,13 +100,14 @@ static int xioopen_open(int argc, const char *argv[], struct opt *opts, int xiof
|
||||||
filetypenames[(result&S_IFMT)>>12], filename, ddirection[rw]);
|
filetypenames[(result&S_IFMT)>>12], filename, ddirection[rw]);
|
||||||
if ((result = _xioopen_open(filename, rw, opts)) < 0)
|
if ((result = _xioopen_open(filename, rw, opts)) < 0)
|
||||||
return result;
|
return result;
|
||||||
fd->stream.fd = result;
|
fd->stream.fd1 = result;
|
||||||
|
fd->stream.fdtype = FDTYPE_SINGLE;
|
||||||
|
|
||||||
#if WITH_TERMIOS
|
#if WITH_TERMIOS
|
||||||
if (Isatty(fd->stream.fd)) {
|
if (Isatty(fd->stream.fd1)) {
|
||||||
if (Tcgetattr(fd->stream.fd, &fd->stream.savetty) < 0) {
|
if (Tcgetattr(fd->stream.fd1, &fd->stream.savetty) < 0) {
|
||||||
Warn2("cannot query current terminal settings on fd %d: %s",
|
Warn2("cannot query current terminal settings on fd %d: %s",
|
||||||
fd->stream.fd, strerror(errno));
|
fd->stream.fd1, strerror(errno));
|
||||||
} else {
|
} else {
|
||||||
fd->stream.ttyvalid = true;
|
fd->stream.ttyvalid = true;
|
||||||
}
|
}
|
||||||
|
@ -110,10 +115,10 @@ static int xioopen_open(int argc, const char *argv[], struct opt *opts, int xiof
|
||||||
#endif /* WITH_TERMIOS */
|
#endif /* WITH_TERMIOS */
|
||||||
|
|
||||||
applyopts_named(filename, opts, PH_FD);
|
applyopts_named(filename, opts, PH_FD);
|
||||||
applyopts(fd->stream.fd, opts, PH_FD);
|
applyopts(fd->stream.fd1, opts, PH_FD);
|
||||||
applyopts_cloexec(fd->stream.fd, opts);
|
applyopts_cloexec(fd->stream.fd1, opts);
|
||||||
|
|
||||||
applyopts_fchown(fd->stream.fd, opts);
|
applyopts_fchown(fd->stream.fd1, opts);
|
||||||
|
|
||||||
if ((result = _xio_openlate(&fd->stream, opts)) < 0)
|
if ((result = _xio_openlate(&fd->stream, opts)) < 0)
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* $Id: xio-file.h,v 1.8 2006/07/13 21:19:15 gerhard Exp $ */
|
/* $Id: xio-file.h,v 1.8.2.1 2006/07/24 19:17:44 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2001-2006 */
|
/* Copyright Gerhard Rieger 2001-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
#ifndef __xio_file_h_included
|
#ifndef __xio_file_h_included
|
||||||
|
@ -26,6 +26,6 @@ extern const struct optdesc opt_o_priv;
|
||||||
extern const struct optdesc opt_o_trunc;
|
extern const struct optdesc opt_o_trunc;
|
||||||
extern const struct optdesc opt_o_noatime;
|
extern const struct optdesc opt_o_noatime;
|
||||||
|
|
||||||
extern const struct addrdesc addr_open;
|
extern const union xioaddr_desc *xioaddrs_open[];
|
||||||
|
|
||||||
#endif /* !defined(__xio_file_h_included) */
|
#endif /* !defined(__xio_file_h_included) */
|
||||||
|
|
92
xio-gopen.c
92
xio-gopen.c
|
@ -14,12 +14,17 @@
|
||||||
|
|
||||||
#if WITH_GOPEN
|
#if WITH_GOPEN
|
||||||
|
|
||||||
static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3);
|
static int xioopen_gopen1(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3);
|
||||||
|
|
||||||
|
|
||||||
const struct addrdesc addr_gopen = { "gopen", 3, xioopen_gopen, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_REG|GROUP_NAMED|GROUP_OPEN|GROUP_FILE|GROUP_TERMIOS|GROUP_SOCKET|GROUP_SOCK_UNIX, 0, 0, 0 HELP(":<filename>") };
|
const struct xioaddr_endpoint_desc xioaddr_gopen1 = { XIOADDR_SYS, "gopen", 1, XIOBIT_ALL, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_REG|GROUP_NAMED|GROUP_OPEN|GROUP_FILE|GROUP_TERMIOS|GROUP_SOCKET|GROUP_SOCK_UNIX, XIOSHUT_UNSPEC, XIOCLOSE_UNSPEC, xioopen_gopen1, 0, 0, 0 HELP(":<filename>") };
|
||||||
|
|
||||||
static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3) {
|
const union xioaddr_desc *xioaddrs_gopen[] = {
|
||||||
|
(union xioaddr_desc *)&xioaddr_gopen1,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static int xioopen_gopen1(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3) {
|
||||||
const char *filename = argv[1];
|
const char *filename = argv[1];
|
||||||
flags_t openflags = (xioflags & XIO_ACCMODE);
|
flags_t openflags = (xioflags & XIO_ACCMODE);
|
||||||
mode_t st_mode;
|
mode_t st_mode;
|
||||||
|
@ -76,24 +81,30 @@ static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xio
|
||||||
/* save options, because we might have to start again with Socket() */
|
/* save options, because we might have to start again with Socket() */
|
||||||
opts2 = copyopts(opts, GROUP_ALL);
|
opts2 = copyopts(opts, GROUP_ALL);
|
||||||
|
|
||||||
if ((fd->stream.fd = Socket(PF_UNIX, socktype, 0)) < 0) {
|
if ((fd->stream.fd1 = Socket(PF_UNIX, socktype, 0)) < 0) {
|
||||||
Error2("socket(PF_UNIX, %d, 0): %s", socktype, strerror(errno));
|
Error2("socket(PF_UNIX, %d, 0): %s", socktype, strerror(errno));
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
/*0 Info2("socket(PF_UNIX, %d, 0) -> %d", socktype, fd->stream.fd);*/
|
fd->stream.fd2 = fd->stream.fd1;
|
||||||
applyopts(fd->stream.fd, opts, PH_PASTSOCKET);
|
fd->stream.fdtype = FDTYPE_SINGLE;
|
||||||
applyopts(fd->stream.fd, opts, PH_FD);
|
if (fd->stream.howtoshut == XIOSHUT_UNSPEC)
|
||||||
|
fd->stream.howtoshut = XIOSHUT_DOWN;
|
||||||
|
if (fd->stream.howtoclose == XIOCLOSE_UNSPEC)
|
||||||
|
fd->stream.howtoclose = XIOCLOSE_CLOSE;
|
||||||
|
/*0 Info2("socket(PF_UNIX, %d, 0) -> %d", socktype, fd->stream.fd1);*/
|
||||||
|
applyopts(fd->stream.fd1, opts, PH_PASTSOCKET);
|
||||||
|
applyopts(fd->stream.fd1, opts, PH_FD);
|
||||||
|
|
||||||
applyopts_cloexec(fd->stream.fd, opts);
|
applyopts_cloexec(fd->stream.fd1, opts);
|
||||||
|
|
||||||
sa.sun_family = AF_UNIX;
|
sa.sun_family = AF_UNIX;
|
||||||
salen = xiosetunix(&sa, filename, false, false);
|
salen = xiosetunix(&sa, filename, false, false);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
applyopts(fd->stream.fd, opts, PH_PREBIND);
|
applyopts(fd->stream.fd1, opts, PH_PREBIND);
|
||||||
applyopts(fd->stream.fd, opts, PH_BIND);
|
applyopts(fd->stream.fd1, opts, PH_BIND);
|
||||||
if (us) {
|
if (us) {
|
||||||
if (Bind(fd->stream.fd, us, uslen) < 0) {
|
if (Bind(fd->stream.fd1, us, uslen) < 0) {
|
||||||
Error4("bind(%d, {%s}, "F_Zd"): %s",
|
Error4("bind(%d, {%s}, "F_Zd"): %s",
|
||||||
fd->fd, sockaddr_info(us, infobuff, sizeof(infobuff)),
|
fd->fd, sockaddr_info(us, infobuff, sizeof(infobuff)),
|
||||||
uslen, strerror(errno));
|
uslen, strerror(errno));
|
||||||
|
@ -104,33 +115,33 @@ static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xio
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
applyopts(fd->stream.fd, opts, PH_PASTBIND);
|
applyopts(fd->stream.fd1, opts, PH_PASTBIND);
|
||||||
#endif /* 0 */
|
#endif /* 0 */
|
||||||
|
|
||||||
applyopts(fd->stream.fd, opts, PH_CONNECT);
|
applyopts(fd->stream.fd1, opts, PH_CONNECT);
|
||||||
if ((result = Connect(fd->stream.fd, (struct sockaddr *)&sa, salen)) < 0) {
|
if ((result = Connect(fd->stream.fd1, (struct sockaddr *)&sa, salen)) < 0) {
|
||||||
if (errno == EINPROGRESS) {
|
if (errno == EINPROGRESS) {
|
||||||
Warn4("connect(%d, %s, "F_Zd"): %s",
|
Warn4("connect(%d, %s, "F_Zd"): %s",
|
||||||
fd->stream.fd, sockaddr_unix_info(&sa, salen, infobuff, sizeof(infobuff)),
|
fd->stream.fd1, sockaddr_unix_info(&sa, salen, infobuff, sizeof(infobuff)),
|
||||||
sizeof(sa), strerror(errno));
|
sizeof(sa), strerror(errno));
|
||||||
} else if (errno == EPROTOTYPE && optsotype != SOCK_STREAM) {
|
} else if (errno == EPROTOTYPE && optsotype != SOCK_STREAM) {
|
||||||
Warn4("connect(%d, %s, "F_Zd"): %s",
|
Warn4("connect(%d, %s, "F_Zd"): %s",
|
||||||
fd->stream.fd, sockaddr_unix_info(&sa, salen, infobuff, sizeof(infobuff)),
|
fd->stream.fd1, sockaddr_unix_info(&sa, salen, infobuff, sizeof(infobuff)),
|
||||||
sizeof(sa), strerror(errno));
|
sizeof(sa), strerror(errno));
|
||||||
Info("assuming datagram socket");
|
Info("assuming datagram socket");
|
||||||
Close(fd->stream.fd);
|
Close(fd->stream.fd1);
|
||||||
|
|
||||||
opts = opts2;
|
opts = opts2;
|
||||||
if ((fd->stream.fd = Socket(PF_UNIX, SOCK_DGRAM, 0)) < 0) {
|
if ((fd->stream.fd1 = Socket(PF_UNIX, SOCK_DGRAM, 0)) < 0) {
|
||||||
Error1("socket(PF_UNIX, SOCK_DGRAM, 0): %s", strerror(errno));
|
Error1("socket(PF_UNIX, SOCK_DGRAM, 0): %s", strerror(errno));
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
/*0 Info1("socket(PF_UNIX, SOCK_DGRAM, 0) -> %d", fd->stream.fd);*/
|
/*0 Info1("socket(PF_UNIX, SOCK_DGRAM, 0) -> %d", fd->stream.fd1);*/
|
||||||
|
|
||||||
applyopts(fd->stream.fd, opts, PH_PASTSOCKET);
|
applyopts(fd->stream.fd1, opts, PH_PASTSOCKET);
|
||||||
applyopts(fd->stream.fd, opts, PH_FD);
|
applyopts(fd->stream.fd1, opts, PH_FD);
|
||||||
|
|
||||||
applyopts_cloexec(fd->stream.fd, opts);
|
applyopts_cloexec(fd->stream.fd1, opts);
|
||||||
|
|
||||||
sa.sun_family = AF_UNIX;
|
sa.sun_family = AF_UNIX;
|
||||||
strncpy(sa.sun_path, filename, sizeof(sa.sun_path));
|
strncpy(sa.sun_path, filename, sizeof(sa.sun_path));
|
||||||
|
@ -140,23 +151,24 @@ static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xio
|
||||||
memcpy(&fd->stream.peersa.soa, &sa, fd->stream.salen);
|
memcpy(&fd->stream.peersa.soa, &sa, fd->stream.salen);
|
||||||
} else {
|
} else {
|
||||||
Error4("connect(%d, %s, "F_Zd"): %s",
|
Error4("connect(%d, %s, "F_Zd"): %s",
|
||||||
fd->stream.fd, sockaddr_unix_info(&sa, fd->stream.salen, infobuff, sizeof(infobuff)),
|
fd->stream.fd1, sockaddr_unix_info(&sa, fd->stream.salen, infobuff, sizeof(infobuff)),
|
||||||
sizeof(sa), strerror(errno));
|
sizeof(sa), strerror(errno));
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fd->stream.howtoend == END_UNSPEC) {
|
if (fd->stream.howtoshut == XIOSHUT_UNSPEC)
|
||||||
fd->stream.howtoend = END_SHUTDOWN;
|
fd->stream.howtoshut = XIOSHUT_CLOSE;
|
||||||
}
|
if (fd->stream.howtoclose == XIOCLOSE_UNSPEC)
|
||||||
|
fd->stream.howtoclose = XIOCLOSE_CLOSE;
|
||||||
|
|
||||||
applyopts_fchown(fd->stream.fd, opts);
|
applyopts_fchown(fd->stream.fd1, opts);
|
||||||
applyopts(fd->stream.fd, opts, PH_CONNECTED);
|
applyopts(fd->stream.fd1, opts, PH_CONNECTED);
|
||||||
applyopts(fd->stream.fd, opts, PH_LATE);
|
applyopts(fd->stream.fd1, opts, PH_LATE);
|
||||||
applyopts_named(filename, opts, PH_PASTOPEN); /* unlink-late */
|
applyopts_named(filename, opts, PH_PASTOPEN); /* unlink-late */
|
||||||
|
|
||||||
if (Getsockname(fd->stream.fd, (struct sockaddr *)&us, &uslen) < 0) {
|
if (Getsockname(fd->stream.fd1, (struct sockaddr *)&us, &uslen) < 0) {
|
||||||
Warn4("getsockname(%d, %p, {%d}): %s",
|
Warn4("getsockname(%d, %p, {%d}): %s",
|
||||||
fd->stream.fd, &us, uslen, strerror(errno));
|
fd->stream.fd1, &us, uslen, strerror(errno));
|
||||||
} else {
|
} else {
|
||||||
Notice1("successfully connected via %s",
|
Notice1("successfully connected via %s",
|
||||||
sockaddr_unix_info(&us, uslen, infobuff, sizeof(infobuff)));
|
sockaddr_unix_info(&us, uslen, infobuff, sizeof(infobuff)));
|
||||||
|
@ -190,24 +202,28 @@ static int xioopen_gopen(int argc, const char *argv[], struct opt *opts, int xio
|
||||||
Ioctl(result, I_PUSH, "ttcompat");
|
Ioctl(result, I_PUSH, "ttcompat");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
fd->stream.fd = result;
|
if (fd->stream.howtoshut == XIOSHUT_UNSPEC)
|
||||||
|
fd->stream.howtoshut = XIOSHUT_NONE;
|
||||||
|
if (fd->stream.howtoclose == XIOCLOSE_UNSPEC)
|
||||||
|
fd->stream.howtoclose = XIOCLOSE_CLOSE;
|
||||||
|
fd->stream.fd1 = result;
|
||||||
|
|
||||||
#if WITH_TERMIOS
|
#if WITH_TERMIOS
|
||||||
if (Isatty(fd->stream.fd)) {
|
if (Isatty(fd->stream.fd1)) {
|
||||||
if (Tcgetattr(fd->stream.fd, &fd->stream.savetty) < 0) {
|
if (Tcgetattr(fd->stream.fd1, &fd->stream.savetty) < 0) {
|
||||||
Warn2("cannot query current terminal settings on fd %d: %s",
|
Warn2("cannot query current terminal settings on fd %d: %s",
|
||||||
fd->stream.fd, strerror(errno));
|
fd->stream.fd1, strerror(errno));
|
||||||
} else {
|
} else {
|
||||||
fd->stream.ttyvalid = true;
|
fd->stream.ttyvalid = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WITH_TERMIOS */
|
#endif /* WITH_TERMIOS */
|
||||||
applyopts_named(filename, opts, PH_FD);
|
applyopts_named(filename, opts, PH_FD);
|
||||||
applyopts(fd->stream.fd, opts, PH_FD);
|
applyopts(fd->stream.fd1, opts, PH_FD);
|
||||||
applyopts_cloexec(fd->stream.fd, opts);
|
applyopts_cloexec(fd->stream.fd1, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((result = applyopts2(fd->stream.fd, opts, PH_PASTSOCKET, PH_CONNECTED)) < 0)
|
if ((result = applyopts2(fd->stream.fd1, opts, PH_PASTSOCKET, PH_CONNECTED)) < 0)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
if ((result = _xio_openlate(&fd->stream, opts)) < 0)
|
if ((result = _xio_openlate(&fd->stream, opts)) < 0)
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
/* $Id: xio-gopen.h,v 1.4 2001/11/04 17:19:20 gerhard Exp $ */
|
/* $Id: xio-gopen.h,v 1.4.2.1 2006/07/24 19:17:49 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2001 */
|
/* Copyright Gerhard Rieger 2001-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
#ifndef __xio_gopen_h_included
|
#ifndef __xio_gopen_h_included
|
||||||
#define __xio_gopen_h_included 1
|
#define __xio_gopen_h_included 1
|
||||||
|
|
||||||
extern const struct addrdesc addr_gopen;
|
extern const struct xioaddr_endpoint_desc xioaddr_gopen1;
|
||||||
|
extern const union xioaddr_desc *xioaddrs_gopen[];
|
||||||
|
|
||||||
#endif /* !defined(__xio_gopen_h_included) */
|
#endif /* !defined(__xio_gopen_h_included) */
|
||||||
|
|
19
xio-ipapp.c
19
xio-ipapp.c
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#include "xiosysincludes.h"
|
#include "xiosysincludes.h"
|
||||||
|
|
||||||
#if WITH_TCP || WITH_UDP
|
#if _WITH_TCP || _WITH_UDP
|
||||||
|
|
||||||
#include "xioopen.h"
|
#include "xioopen.h"
|
||||||
#include "xio-socket.h"
|
#include "xio-socket.h"
|
||||||
|
@ -19,7 +19,7 @@ const struct optdesc opt_sourceport = { "sourceport", "sp", OPT_SOURCEPORT
|
||||||
/*const struct optdesc opt_port = { "port", NULL, OPT_PORT, GROUP_IPAPP, PH_BIND, TYPE_USHORT, OFUNC_SPEC };*/
|
/*const struct optdesc opt_port = { "port", NULL, OPT_PORT, GROUP_IPAPP, PH_BIND, TYPE_USHORT, OFUNC_SPEC };*/
|
||||||
const struct optdesc opt_lowport = { "lowport", NULL, OPT_LOWPORT, GROUP_IPAPP, PH_LATE, TYPE_BOOL, OFUNC_SPEC };
|
const struct optdesc opt_lowport = { "lowport", NULL, OPT_LOWPORT, GROUP_IPAPP, PH_LATE, TYPE_BOOL, OFUNC_SPEC };
|
||||||
|
|
||||||
#if WITH_IP4
|
#if _WITH_IP4
|
||||||
/* we expect the form "host:port" */
|
/* we expect the form "host:port" */
|
||||||
int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
|
int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
|
||||||
int xioflags, xiofile_t *xxfd,
|
int xioflags, xiofile_t *xxfd,
|
||||||
|
@ -42,8 +42,6 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
|
||||||
Error2("%s: wrong number of parameters (%d instead of 2)", argv[0], argc-1);
|
Error2("%s: wrong number of parameters (%d instead of 2)", argv[0], argc-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
xfd->howtoend = END_SHUTDOWN;
|
|
||||||
|
|
||||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||||
applyopts(-1, opts, PH_INIT);
|
applyopts(-1, opts, PH_INIT);
|
||||||
|
|
||||||
|
@ -124,7 +122,7 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
|
||||||
}
|
}
|
||||||
/* parent process */
|
/* parent process */
|
||||||
Notice1("forked off child process "F_pid, pid);
|
Notice1("forked off child process "F_pid, pid);
|
||||||
Close(xfd->fd);
|
Close(xfd->fd1);
|
||||||
/* with and without retry */
|
/* with and without retry */
|
||||||
Nanosleep(&xfd->intervall, NULL);
|
Nanosleep(&xfd->intervall, NULL);
|
||||||
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
|
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
|
||||||
|
@ -214,10 +212,10 @@ int
|
||||||
sockaddr_info((struct sockaddr *)them, *themlen, infobuff, sizeof(infobuff)));
|
sockaddr_info((struct sockaddr *)them, *themlen, infobuff, sizeof(infobuff)));
|
||||||
return STAT_OK;
|
return STAT_OK;
|
||||||
}
|
}
|
||||||
#endif /* WITH_IP4 */
|
#endif /* _WITH_IP4 */
|
||||||
|
|
||||||
|
|
||||||
#if WITH_TCP && WITH_LISTEN
|
#if _WITH_TCP && WITH_LISTEN
|
||||||
int _xioopen_ipapp_listen_prepare(struct opt *opts, struct opt **opts0,
|
int _xioopen_ipapp_listen_prepare(struct opt *opts, struct opt **opts0,
|
||||||
const char *portname, int *pf, int ipproto,
|
const char *portname, int *pf, int ipproto,
|
||||||
unsigned long res_opts0,
|
unsigned long res_opts0,
|
||||||
|
@ -271,7 +269,8 @@ int xioopen_ipapp_listen(int argc, const char *argv[], struct opt *opts,
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
fd->stream.howtoend = END_SHUTDOWN;
|
fd->stream.howtoshut = XIOSHUT_DOWN;
|
||||||
|
fd->stream.howtoclose = XIOCLOSE_CLOSE;
|
||||||
|
|
||||||
if (applyopts_single(&fd->stream, opts, PH_INIT) < 0) return -1;
|
if (applyopts_single(&fd->stream, opts, PH_INIT) < 0) return -1;
|
||||||
applyopts(-1, opts, PH_INIT);
|
applyopts(-1, opts, PH_INIT);
|
||||||
|
@ -293,6 +292,6 @@ int xioopen_ipapp_listen(int argc, const char *argv[], struct opt *opts,
|
||||||
return result;
|
return result;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* WITH_IP4 && WITH_TCP && WITH_LISTEN */
|
#endif /* _WITH_IP4 && _WITH_TCP && WITH_LISTEN */
|
||||||
|
|
||||||
#endif /* WITH_TCP || WITH_UDP */
|
#endif /* _WITH_TCP || _WITH_UDP */
|
||||||
|
|
78
xio-listen.c
78
xio-listen.c
|
@ -115,46 +115,24 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
|
||||||
|
|
||||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||||
|
|
||||||
#if 1
|
if ((xfd->fd1 = Socket(pf, socktype, proto)) < 0) {
|
||||||
if (dofork) {
|
|
||||||
#if HAVE_SIGACTION
|
|
||||||
struct sigaction act;
|
|
||||||
memset(&act, 0, sizeof(struct sigaction));
|
|
||||||
act.sa_flags = SA_NOCLDSTOP|SA_RESTART
|
|
||||||
#ifdef SA_NOMASK
|
|
||||||
|SA_NOMASK
|
|
||||||
#endif
|
|
||||||
;
|
|
||||||
act.sa_handler = childdied;
|
|
||||||
if (Sigaction(SIGCHLD, &act, NULL) < 0) {
|
|
||||||
/*! man does not say that errno is defined */
|
|
||||||
Warn2("sigaction(SIGCHLD, %p, NULL): %s", childdied, strerror(errno));
|
|
||||||
}
|
|
||||||
#else /* HAVE_SIGACTION */
|
|
||||||
if (Signal(SIGCHLD, childdied) == SIG_ERR) {
|
|
||||||
Warn2("signal(SIGCHLD, %p): %s", childdied, strerror(errno));
|
|
||||||
}
|
|
||||||
#endif /* !HAVE_SIGACTION */
|
|
||||||
}
|
|
||||||
#endif /* 1 */
|
|
||||||
|
|
||||||
if ((xfd->fd = Socket(pf, socktype, proto)) < 0) {
|
|
||||||
Msg4(level,
|
Msg4(level,
|
||||||
"socket(%d, %d, %d): %s", pf, socktype, proto, strerror(errno));
|
"socket(%d, %d, %d): %s", pf, socktype, proto, strerror(errno));
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
xfd->fdtype = FDTYPE_SINGLE;
|
||||||
|
|
||||||
applyopts(xfd->fd, opts, PH_PASTSOCKET);
|
applyopts(xfd->fd1, opts, PH_PASTSOCKET);
|
||||||
|
|
||||||
applyopts_cloexec(xfd->fd, opts);
|
applyopts_cloexec(xfd->fd1, opts);
|
||||||
|
|
||||||
applyopts(xfd->fd, opts, PH_PREBIND);
|
applyopts(xfd->fd1, opts, PH_PREBIND);
|
||||||
applyopts(xfd->fd, opts, PH_BIND);
|
applyopts(xfd->fd1, opts, PH_BIND);
|
||||||
if (Bind(xfd->fd, (struct sockaddr *)us, uslen) < 0) {
|
if (Bind(xfd->fd1, (struct sockaddr *)us, uslen) < 0) {
|
||||||
Msg4(level, "bind(%d, {%s}, "F_Zd"): %s", xfd->fd,
|
Msg4(level, "bind(%d, {%s}, "F_Zd"): %s", xfd->fd1,
|
||||||
sockaddr_info(us, uslen, infobuff, sizeof(infobuff)), uslen,
|
sockaddr_info(us, uslen, infobuff, sizeof(infobuff)), uslen,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
Close(xfd->fd);
|
Close(xfd->fd1);
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,12 +144,12 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
|
||||||
/* under some circumstances (e.g., TCP listen on port 0) bind() fills empty
|
/* under some circumstances (e.g., TCP listen on port 0) bind() fills empty
|
||||||
fields that we want to know. */
|
fields that we want to know. */
|
||||||
salen = sizeof(sa);
|
salen = sizeof(sa);
|
||||||
if (Getsockname(xfd->fd, us, &uslen) < 0) {
|
if (Getsockname(xfd->fd1, us, &uslen) < 0) {
|
||||||
Warn4("getsockname(%d, %p, {%d}): %s",
|
Warn4("getsockname(%d, %p, {%d}): %s",
|
||||||
xfd->fd, &us, uslen, strerror(errno));
|
xfd->fd1, &us, uslen, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
applyopts(xfd->fd, opts, PH_PASTBIND);
|
applyopts(xfd->fd1, opts, PH_PASTBIND);
|
||||||
#if WITH_UNIX
|
#if WITH_UNIX
|
||||||
if (us->sa_family == AF_UNIX) {
|
if (us->sa_family == AF_UNIX) {
|
||||||
/*applyopts_early(((struct sockaddr_un *)us)->sun_path, opts);*/
|
/*applyopts_early(((struct sockaddr_un *)us)->sun_path, opts);*/
|
||||||
|
@ -181,8 +159,8 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
|
||||||
#endif /* WITH_UNIX */
|
#endif /* WITH_UNIX */
|
||||||
|
|
||||||
retropt_int(opts, OPT_BACKLOG, &backlog);
|
retropt_int(opts, OPT_BACKLOG, &backlog);
|
||||||
if (Listen(xfd->fd, backlog) < 0) {
|
if (Listen(xfd->fd1, backlog) < 0) {
|
||||||
Error3("listen(%d, %d): %s", xfd->fd, backlog, strerror(errno));
|
Error3("listen(%d, %d): %s", xfd->fd1, backlog, strerror(errno));
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,9 +207,9 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
|
||||||
do {
|
do {
|
||||||
/*? int level = E_ERROR;*/
|
/*? int level = E_ERROR;*/
|
||||||
Notice1("listening on %s", sockaddr_info(us, uslen, lisname, sizeof(lisname)));
|
Notice1("listening on %s", sockaddr_info(us, uslen, lisname, sizeof(lisname)));
|
||||||
ps = Accept(xfd->fd, (struct sockaddr *)&sa, &salen);
|
ps = Accept(xfd->fd1, (struct sockaddr *)&sa, &salen);
|
||||||
if (ps >= 0) {
|
if (ps >= 0) {
|
||||||
/*0 Info4("accept(%d, %p, {"F_Zu"}) -> %d", xfd->fd, &sa, salen, ps);*/
|
/*0 Info4("accept(%d, %p, {"F_Zu"}) -> %d", xfd->fd1, &sa, salen, ps);*/
|
||||||
break; /* success, break out of loop */
|
break; /* success, break out of loop */
|
||||||
}
|
}
|
||||||
if (errno == EINTR) {
|
if (errno == EINTR) {
|
||||||
|
@ -239,12 +217,12 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
|
||||||
}
|
}
|
||||||
if (errno == ECONNABORTED) {
|
if (errno == ECONNABORTED) {
|
||||||
Notice4("accept(%d, %p, {"F_Zu"}): %s",
|
Notice4("accept(%d, %p, {"F_Zu"}): %s",
|
||||||
xfd->fd, &sa, salen, strerror(errno));
|
xfd->fd1, &sa, salen, strerror(errno));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Msg4(level, "accept(%d, %p, {"F_Zu"}): %s",
|
Msg4(level, "accept(%d, %p, {"F_Zu"}): %s",
|
||||||
xfd->fd, &sa, salen, strerror(errno));
|
xfd->fd1, &sa, salen, strerror(errno));
|
||||||
Close(xfd->fd);
|
Close(xfd->fd1);
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
} while (true);
|
} while (true);
|
||||||
applyopts_cloexec(ps, opts);
|
applyopts_cloexec(ps, opts);
|
||||||
|
@ -271,21 +249,21 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
|
||||||
sockaddr_info((struct sockaddr *)pa, pas,
|
sockaddr_info((struct sockaddr *)pa, pas,
|
||||||
infobuff, sizeof(infobuff)));
|
infobuff, sizeof(infobuff)));
|
||||||
|
|
||||||
applyopts(xfd->fd, opts, PH_FD);
|
applyopts(xfd->fd1, opts, PH_FD);
|
||||||
|
|
||||||
applyopts(xfd->fd, opts, PH_CONNECTED);
|
applyopts(xfd->fd1, opts, PH_CONNECTED);
|
||||||
|
|
||||||
if (dofork) {
|
if (dofork) {
|
||||||
if ((pid = Fork()) < 0) {
|
if ((pid = Fork()) < 0) {
|
||||||
Msg1(level, "fork(): %s", strerror(errno));
|
Msg1(level, "fork(): %s", strerror(errno));
|
||||||
Close(xfd->fd);
|
Close(xfd->fd1);
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
if (pid == 0) { /* child */
|
if (pid == 0) { /* child */
|
||||||
if (Close(xfd->fd) < 0) {
|
if (Close(xfd->fd1) < 0) {
|
||||||
Info2("close(%d): %s", xfd->fd, strerror(errno));
|
Info2("close(%d): %s", xfd->fd1, strerror(errno));
|
||||||
}
|
}
|
||||||
xfd->fd = ps;
|
xfd->fd1 = ps;
|
||||||
|
|
||||||
#if WITH_RETRY
|
#if WITH_RETRY
|
||||||
/* !? */
|
/* !? */
|
||||||
|
@ -317,10 +295,10 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
|
||||||
Notice1("forked off child process "F_pid, pid);
|
Notice1("forked off child process "F_pid, pid);
|
||||||
Info("still listening");
|
Info("still listening");
|
||||||
} else {
|
} else {
|
||||||
if (Close(xfd->fd) < 0) {
|
if (Close(xfd->fd1) < 0) {
|
||||||
Info2("close(%d): %s", xfd->fd, strerror(errno));
|
Info2("close(%d): %s", xfd->fd1, strerror(errno));
|
||||||
}
|
}
|
||||||
xfd->fd = ps;
|
xfd->fd1 = ps;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
64
xio-nop.c
Normal file
64
xio-nop.c
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
/* $Id: xio-socks.c,v 1.25 2006/02/08 19:46:59 gerhard Exp $ */
|
||||||
|
/* Copyright Gerhard Rieger 2006-2007 */
|
||||||
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
|
/* this file contains the source for a degenerated address that just transfers
|
||||||
|
data */
|
||||||
|
|
||||||
|
#include "xiosysincludes.h"
|
||||||
|
#include "xioopen.h"
|
||||||
|
|
||||||
|
#include "xio-nop.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if WITH_NOP
|
||||||
|
|
||||||
|
static int xioopen_nop(int argc, const char *argv[], struct opt *opts,
|
||||||
|
int xioflags, xiofile_t *xxfd,
|
||||||
|
unsigned groups, int dummy1, int dummy2,
|
||||||
|
int dummy3);
|
||||||
|
|
||||||
|
static const struct xioaddr_inter_desc xiointer_nop0ro = { XIOADDR_PROT, "nop", 0, XIOBIT_RDONLY, 0/*groups*/, XIOSHUT_CLOSE, XIOCLOSE_NONE, xioopen_nop, 0, 0, 0, XIOBIT_WRONLY HELP("") };
|
||||||
|
static const struct xioaddr_inter_desc xiointer_nop0wo = { XIOADDR_PROT, "nop", 0, XIOBIT_WRONLY, 0/*groups*/, XIOSHUT_CLOSE, XIOCLOSE_NONE, xioopen_nop, 0, 0, 0, XIOBIT_RDONLY HELP("") };
|
||||||
|
static const struct xioaddr_inter_desc xiointer_nop0rw = { XIOADDR_PROT, "nop", 0, XIOBIT_RDWR, 0/*groups*/, XIOSHUT_CLOSE, XIOCLOSE_NONE, xioopen_nop, 0, 0, 0, XIOBIT_RDWR HELP("") };
|
||||||
|
|
||||||
|
const union xioaddr_desc *xioaddrs_nop[] = {
|
||||||
|
(union xioaddr_desc *)&xiointer_nop0ro,
|
||||||
|
(union xioaddr_desc *)&xiointer_nop0wo,
|
||||||
|
(union xioaddr_desc *)&xiointer_nop0rw,
|
||||||
|
NULL };
|
||||||
|
|
||||||
|
static int xioopen_nop(int argc, const char *argv[], struct opt *opts,
|
||||||
|
int xioflags, xiofile_t *xxfd,
|
||||||
|
unsigned groups, int dummy, int dummy2,
|
||||||
|
int dummy3) {
|
||||||
|
struct single *xfd = &xxfd->stream;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (argc != 1) {
|
||||||
|
Error("address NOP takes no arguments");
|
||||||
|
return STAT_NORETRY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xfd->fd1 < 0 && xfd->fd2 < 0) {
|
||||||
|
Error("NOP cannot be endpoint");
|
||||||
|
return STAT_NORETRY;
|
||||||
|
}
|
||||||
|
|
||||||
|
applyopts(-1, opts, PH_INIT);
|
||||||
|
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||||
|
|
||||||
|
Notice("opening NOP");
|
||||||
|
|
||||||
|
xfd->dtype = XIODATA_STREAM;
|
||||||
|
/*xfd->fdtype = FDTYPE_DOUBLE;*/
|
||||||
|
|
||||||
|
applyopts(xfd->fd1, opts, PH_ALL);
|
||||||
|
|
||||||
|
if ((result = _xio_openlate(xfd, opts)) < 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* WITH_NOP */
|
||||||
|
|
10
xio-nop.h
Normal file
10
xio-nop.h
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
/* $Id: xio-socks.h,v 1.6 2004/06/06 19:03:28 gerhard Exp $ */
|
||||||
|
/* Copyright Gerhard Rieger 2006-2007 */
|
||||||
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
|
#ifndef __xio_nop_h_included
|
||||||
|
#define __xio_nop_h_included 1
|
||||||
|
|
||||||
|
extern const union xioaddr_desc *xioaddrs_nop[];
|
||||||
|
|
||||||
|
#endif /* !defined(__xio_nop_h_included) */
|
251
xio-openssl.c
251
xio-openssl.c
|
@ -51,15 +51,44 @@ static int xioSSL_set_fd(struct single *xfd, int level);
|
||||||
static int xioSSL_connect(struct single *xfd, bool opt_ver, int level);
|
static int xioSSL_connect(struct single *xfd, bool opt_ver, int level);
|
||||||
|
|
||||||
|
|
||||||
/* description record for ssl connect */
|
/* description record for inter-address ssl connect with 0 parameters */
|
||||||
const struct addrdesc addr_openssl = {
|
static const struct xioaddr_inter_desc xiointer_openssl_connect0 = {
|
||||||
"openssl", /* keyword for selecting this address type in xioopen calls
|
XIOADDR_INTER, /* this is an embedded address (inter module) */
|
||||||
|
"openssl-client", /* keyword for selecting this address type in xioopen calls
|
||||||
(canonical or main name) */
|
(canonical or main name) */
|
||||||
3, /* data flow directions this address supports on API layer:
|
0, /* number of required parameters */
|
||||||
1..read, 2..write, 3..both */
|
XIOBIT_ALL, /* data flow directions this address supports on API layer:
|
||||||
|
XIOBIT_RDONLY|XIOBIT_WRONLY|XIOBIT_RDWR */
|
||||||
|
GROUP_CHILD|GROUP_OPENSSL|GROUP_RETRY, /* bitwise OR of address groups this address belongs to.
|
||||||
|
You might have to specify a new group in xioopts.h */
|
||||||
|
XIOSHUT_OPENSSL,
|
||||||
|
XIOCLOSE_CLOSE,
|
||||||
xioopen_openssl_connect, /* a function pointer used to "open" these addresses.*/
|
xioopen_openssl_connect, /* a function pointer used to "open" these addresses.*/
|
||||||
|
0, /* an integer passed to xioopen_openssl; makes it possible to
|
||||||
|
use the same xioopen_openssl function for slightly different
|
||||||
|
address types. */
|
||||||
|
0, /* like previous argument */
|
||||||
|
0, /* like previous arguments, but pointer type.
|
||||||
|
No trailing comma or semicolon! */
|
||||||
|
XIOBIT_RDWR /* SSL is a bidirectional protocol */
|
||||||
|
HELP("") /* a text displayed from xio help function.
|
||||||
|
No trailing comma or semicolon!
|
||||||
|
only generates this text if WITH_HELP is != 0 */
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* description record for endpoint-address ssl connect with 2 parameters */
|
||||||
|
static const struct xioaddr_endpoint_desc xioendpoint_openssl_connect2 = {
|
||||||
|
XIOADDR_ENDPOINT, /* this is not an embedded address but a sys address */
|
||||||
|
"openssl-client", /* keyword for selecting this address type in xioopen calls
|
||||||
|
(canonical or main name) */
|
||||||
|
2, /* number of required parameters */
|
||||||
|
XIOBIT_ALL, /* data flow directions this address supports on API layer:
|
||||||
|
XIOBIT_RDONLY|XIOBIT_WRONLY|XIOBIT_RDWR */
|
||||||
GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_CHILD|GROUP_OPENSSL|GROUP_RETRY, /* bitwise OR of address groups this address belongs to.
|
GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_CHILD|GROUP_OPENSSL|GROUP_RETRY, /* bitwise OR of address groups this address belongs to.
|
||||||
You might have to specify a new group in xioopts.h */
|
You might have to specify a new group in xioopts.h */
|
||||||
|
XIOSHUT_OPENSSL,
|
||||||
|
XIOCLOSE_CLOSE,
|
||||||
|
xioopen_openssl_connect, /* a function pointer used to "open" these addresses.*/
|
||||||
0, /* an integer passed to xioopen_openssl; makes it possible to
|
0, /* an integer passed to xioopen_openssl; makes it possible to
|
||||||
use the same xioopen_openssl function for slightly different
|
use the same xioopen_openssl function for slightly different
|
||||||
address types. */
|
address types. */
|
||||||
|
@ -71,16 +100,53 @@ const struct addrdesc addr_openssl = {
|
||||||
only generates this text if WITH_HELP is != 0 */
|
only generates this text if WITH_HELP is != 0 */
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
/* array containing ssl connect description records */
|
||||||
|
const union xioaddr_desc *xioaddrs_openssl_connect[] = {
|
||||||
|
(union xioaddr_desc *)&xiointer_openssl_connect0,
|
||||||
|
(union xioaddr_desc *)&xioendpoint_openssl_connect2,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#if WITH_LISTEN
|
#if WITH_LISTEN
|
||||||
/* description record for ssl listen */
|
/* description record for inter-address ssl listen */
|
||||||
const struct addrdesc addr_openssl_listen = {
|
static const struct xioaddr_inter_desc xiointer_openssl_listen0 = {
|
||||||
"openssl-listen", /* keyword for selecting this address type in xioopen calls
|
XIOADDR_INTER, /* this is an embedded address (inter module) */
|
||||||
|
"openssl-server", /* keyword for selecting this address type in xioopen calls
|
||||||
(canonical or main name) */
|
(canonical or main name) */
|
||||||
3, /* data flow directions this address supports on API layer:
|
0, /* number of required parameters */
|
||||||
1..read, 2..write, 3..both */
|
XIOBIT_ALL, /* data flow directions this address supports on API layer:
|
||||||
|
XIOBIT_RDONLY|XIOBIT_WRONLY|XIOBIT_RDWR */
|
||||||
|
GROUP_CHILD|GROUP_OPENSSL|GROUP_RETRY, /* bitwise OR of address groups this address belongs to.
|
||||||
|
You might have to specify a new group in xioopts.h */
|
||||||
|
XIOSHUT_OPENSSL,
|
||||||
|
XIOCLOSE_CLOSE,
|
||||||
xioopen_openssl_listen, /* a function pointer used to "open" these addresses.*/
|
xioopen_openssl_listen, /* a function pointer used to "open" these addresses.*/
|
||||||
|
0, /* an integer passed to xioopen_openssl_listen; makes it possible to
|
||||||
|
use the same xioopen_openssl_listen function for slightly different
|
||||||
|
address types. */
|
||||||
|
0, /* like previous argument */
|
||||||
|
0, /* like previous arguments, but pointer type.
|
||||||
|
No trailing comma or semicolon! */
|
||||||
|
XIOBIT_RDWR /* SSL is a bidirectional protocol */
|
||||||
|
HELP("") /* a text displayed from xio help function.
|
||||||
|
No trailing comma or semicolon!
|
||||||
|
only generates this text if WITH_HELP is != 0 */
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* description record for enpoint-address ssl listen */
|
||||||
|
static const struct xioaddr_endpoint_desc xioendpoint_openssl_listen1 = {
|
||||||
|
XIOADDR_ENDPOINT, /* this is not an embedded module but a sys module */
|
||||||
|
"openssl-server", /* keyword for selecting this address type in xioopen calls
|
||||||
|
(canonical or main name) */
|
||||||
|
1, /* number of required parameters */
|
||||||
|
XIOBIT_ALL, /* data flow directions this address supports on API layer:
|
||||||
|
XIOBIT_RDONLY|XIOBIT_WRONLY|XIOBIT_RDWR */
|
||||||
GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE|GROUP_OPENSSL|GROUP_RETRY, /* bitwise OR of address groups this address belongs to.
|
GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE|GROUP_OPENSSL|GROUP_RETRY, /* bitwise OR of address groups this address belongs to.
|
||||||
You might have to specify a new group in xioopts.h */
|
You might have to specify a new group in xioopts.h */
|
||||||
|
XIOSHUT_OPENSSL,
|
||||||
|
XIOCLOSE_CLOSE,
|
||||||
|
xioopen_openssl_listen, /* a function pointer used to "open" these addresses.*/
|
||||||
0, /* an integer passed to xioopen_openssl_listen; makes it possible to
|
0, /* an integer passed to xioopen_openssl_listen; makes it possible to
|
||||||
use the same xioopen_openssl_listen function for slightly different
|
use the same xioopen_openssl_listen function for slightly different
|
||||||
address types. */
|
address types. */
|
||||||
|
@ -91,6 +157,13 @@ const struct addrdesc addr_openssl_listen = {
|
||||||
No trailing comma or semicolon!
|
No trailing comma or semicolon!
|
||||||
only generates this text if WITH_HELP is != 0 */
|
only generates this text if WITH_HELP is != 0 */
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
/* array containing ssl listen description records */
|
||||||
|
const union xioaddr_desc *xioaddrs_openssl_listen[] = {
|
||||||
|
(union xioaddr_desc *)&xiointer_openssl_listen0,
|
||||||
|
(union xioaddr_desc *)&xioendpoint_openssl_listen1,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
#endif /* WITH_LISTEN */
|
#endif /* WITH_LISTEN */
|
||||||
|
|
||||||
/* both client and server */
|
/* both client and server */
|
||||||
|
@ -153,7 +226,7 @@ static int
|
||||||
{
|
{
|
||||||
struct single *xfd = &xxfd->stream;
|
struct single *xfd = &xxfd->stream;
|
||||||
struct opt *opts0 = NULL;
|
struct opt *opts0 = NULL;
|
||||||
const char *hostname, *portname;
|
const char *hostname, *portname = NULL;
|
||||||
int pf = PF_UNSPEC;
|
int pf = PF_UNSPEC;
|
||||||
int ipproto = IPPROTO_TCP;
|
int ipproto = IPPROTO_TCP;
|
||||||
int socktype = SOCK_STREAM;
|
int socktype = SOCK_STREAM;
|
||||||
|
@ -165,7 +238,7 @@ static int
|
||||||
bool needbind = false;
|
bool needbind = false;
|
||||||
bool lowport = false;
|
bool lowport = false;
|
||||||
int level;
|
int level;
|
||||||
SSL_CTX* ctx;
|
/*0 SSL_CTX* ctx;*/
|
||||||
bool opt_ver = true; /* verify peer certificate */
|
bool opt_ver = true; /* verify peer certificate */
|
||||||
char *opt_cert = NULL; /* file name of client certificate */
|
char *opt_cert = NULL; /* file name of client certificate */
|
||||||
int result;
|
int result;
|
||||||
|
@ -176,15 +249,18 @@ static int
|
||||||
}
|
}
|
||||||
xfd->flags |= XIO_DOESCONVERT;
|
xfd->flags |= XIO_DOESCONVERT;
|
||||||
|
|
||||||
if (argc != 3) {
|
xfd->howtoshut = XIOSHUT_OPENSSL;
|
||||||
Error1("%s: 2 parameters required", argv[0]);
|
xfd->howtoclose = XIOCLOSE_CLOSE;
|
||||||
return STAT_NORETRY;
|
|
||||||
}
|
/* we support two forms of openssl-connect */
|
||||||
|
if (argc == 3) {
|
||||||
hostname = argv[1];
|
hostname = argv[1];
|
||||||
portname = argv[2];
|
portname = argv[2];
|
||||||
|
|
||||||
xfd->howtoend = END_SHUTDOWN;
|
/* a "terminal" form where we build a tcp connection to given host and
|
||||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
port */
|
||||||
|
|
||||||
|
applyopts_single(xfd, opts, PH_INIT);
|
||||||
applyopts(-1, opts, PH_INIT);
|
applyopts(-1, opts, PH_INIT);
|
||||||
|
|
||||||
retropt_bool(opts, OPT_FORK, &dofork);
|
retropt_bool(opts, OPT_FORK, &dofork);
|
||||||
|
@ -192,7 +268,8 @@ static int
|
||||||
retropt_string(opts, OPT_OPENSSL_CERTIFICATE, &opt_cert);
|
retropt_string(opts, OPT_OPENSSL_CERTIFICATE, &opt_cert);
|
||||||
|
|
||||||
result =
|
result =
|
||||||
_xioopen_openssl_prepare(opts, xfd, false, &opt_ver, opt_cert, &ctx);
|
_xioopen_openssl_prepare(opts, xfd, false, &opt_ver, opt_cert,
|
||||||
|
&xfd->para.openssl.ctx);
|
||||||
if (result != STAT_OK) return STAT_NORETRY;
|
if (result != STAT_OK) return STAT_NORETRY;
|
||||||
|
|
||||||
result =
|
result =
|
||||||
|
@ -202,6 +279,32 @@ static int
|
||||||
them, &themlen, us, &uslen,
|
them, &themlen, us, &uslen,
|
||||||
&needbind, &lowport, &socktype);
|
&needbind, &lowport, &socktype);
|
||||||
if (result != STAT_OK) return STAT_NORETRY;
|
if (result != STAT_OK) return STAT_NORETRY;
|
||||||
|
} else if (argc = 1) {
|
||||||
|
|
||||||
|
/* or a "non terminal" address without required parameters */
|
||||||
|
if (xfd->fd2 < 0) {
|
||||||
|
Error("openssl-connect without hostname and port must be an embedded address");
|
||||||
|
return STAT_NORETRY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||||
|
applyopts(-1, opts, PH_INIT);
|
||||||
|
|
||||||
|
retropt_bool(opts, OPT_FORK, &dofork);
|
||||||
|
|
||||||
|
retropt_string(opts, OPT_OPENSSL_CERTIFICATE, &opt_cert);
|
||||||
|
|
||||||
|
result =
|
||||||
|
_xioopen_openssl_prepare(opts, xfd, false, &opt_ver, opt_cert,
|
||||||
|
&xfd->para.openssl.ctx);
|
||||||
|
if (result != STAT_OK) return STAT_NORETRY;
|
||||||
|
|
||||||
|
retropt_bool(opts, OPT_FORK, &dofork);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Error1("%s: 0 or 2 parameters required", argv[0]);
|
||||||
|
return STAT_NORETRY;
|
||||||
|
}
|
||||||
|
|
||||||
if (xioopts.logopt == 'm') {
|
if (xioopts.logopt == 'm') {
|
||||||
Info("starting connect loop, switching to syslog");
|
Info("starting connect loop, switching to syslog");
|
||||||
|
@ -219,6 +322,8 @@ static int
|
||||||
#endif /* WITH_RETRY */
|
#endif /* WITH_RETRY */
|
||||||
level = E_ERROR;
|
level = E_ERROR;
|
||||||
|
|
||||||
|
/*!!! this belongs only to "old" openssl-connect form */
|
||||||
|
if (portname) {
|
||||||
/* this cannot fork because we retrieved fork option above */
|
/* this cannot fork because we retrieved fork option above */
|
||||||
result =
|
result =
|
||||||
_xioopen_connect(xfd,
|
_xioopen_connect(xfd,
|
||||||
|
@ -243,20 +348,24 @@ static int
|
||||||
default:
|
default:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*! isn't this too early? */
|
/*! isn't this too early? */
|
||||||
if ((result = _xio_openlate(xfd, opts)) < 0) {
|
if ((result = _xio_openlate(xfd, opts)) < 0) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = _xioopen_openssl_connect(xfd, opt_ver, ctx, level);
|
result =
|
||||||
|
_xioopen_openssl_connect(xfd, opt_ver, xfd->para.openssl.ctx, level);
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case STAT_OK: break;
|
case STAT_OK: break;
|
||||||
#if WITH_RETRY
|
#if WITH_RETRY
|
||||||
case STAT_RETRYLATER:
|
case STAT_RETRYLATER:
|
||||||
case STAT_RETRYNOW:
|
case STAT_RETRYNOW:
|
||||||
if (xfd->forever || xfd->retry) {
|
if (xfd->forever || xfd->retry) {
|
||||||
Close(xfd->fd);
|
Close(xfd->fd1);
|
||||||
|
if (xfd->fdtype == FDTYPE_DOUBLE)
|
||||||
|
Close(xfd->fd2);
|
||||||
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
|
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
|
||||||
if (result == STAT_RETRYLATER) {
|
if (result == STAT_RETRYLATER) {
|
||||||
Nanosleep(&xfd->intervall, NULL);
|
Nanosleep(&xfd->intervall, NULL);
|
||||||
|
@ -297,7 +406,9 @@ static int
|
||||||
}
|
}
|
||||||
/* parent process */
|
/* parent process */
|
||||||
Notice1("forked off child process "F_pid, pid);
|
Notice1("forked off child process "F_pid, pid);
|
||||||
Close(xfd->fd);
|
Close(xfd->fd1);
|
||||||
|
if (xfd->fdtype == FDTYPE_DOUBLE)
|
||||||
|
Close(xfd->fd2);
|
||||||
sycSSL_free(xfd->para.openssl.ssl);
|
sycSSL_free(xfd->para.openssl.ssl);
|
||||||
xfd->para.openssl.ssl = NULL;
|
xfd->para.openssl.ssl = NULL;
|
||||||
/* with and without retry */
|
/* with and without retry */
|
||||||
|
@ -383,7 +494,7 @@ static int
|
||||||
addr_openssl */
|
addr_openssl */
|
||||||
{
|
{
|
||||||
struct single *xfd = &xxfd->stream;
|
struct single *xfd = &xxfd->stream;
|
||||||
const char *portname;
|
const char *portname = NULL;
|
||||||
struct opt *opts0 = NULL;
|
struct opt *opts0 = NULL;
|
||||||
union sockaddr_union us_sa, *us = &us_sa;
|
union sockaddr_union us_sa, *us = &us_sa;
|
||||||
socklen_t uslen = sizeof(us_sa);
|
socklen_t uslen = sizeof(us_sa);
|
||||||
|
@ -392,7 +503,7 @@ static int
|
||||||
int ipproto = IPPROTO_TCP;
|
int ipproto = IPPROTO_TCP;
|
||||||
/*! lowport? */
|
/*! lowport? */
|
||||||
int level;
|
int level;
|
||||||
SSL_CTX* ctx;
|
/*0 SSL_CTX* ctx;*/
|
||||||
bool opt_ver = true; /* verify peer certificate - changed with 1.6.0 */
|
bool opt_ver = true; /* verify peer certificate - changed with 1.6.0 */
|
||||||
char *opt_cert = NULL; /* file name of server certificate */
|
char *opt_cert = NULL; /* file name of server certificate */
|
||||||
int result;
|
int result;
|
||||||
|
@ -403,11 +514,6 @@ static int
|
||||||
}
|
}
|
||||||
xfd->flags |= XIO_DOESCONVERT;
|
xfd->flags |= XIO_DOESCONVERT;
|
||||||
|
|
||||||
if (argc != 2) {
|
|
||||||
Error1("%s: 1 parameter required", argv[0]);
|
|
||||||
return STAT_NORETRY;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if WITH_IP4 && WITH_IP6
|
#if WITH_IP4 && WITH_IP6
|
||||||
pf = xioopts.default_ip=='6'?PF_INET6:PF_INET;
|
pf = xioopts.default_ip=='6'?PF_INET6:PF_INET;
|
||||||
#elif WITH_IP6
|
#elif WITH_IP6
|
||||||
|
@ -416,9 +522,36 @@ static int
|
||||||
pf = PF_INET;
|
pf = PF_INET;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
portname = argv[1];
|
if (argc == 2) {
|
||||||
|
|
||||||
|
portname = argv[1];
|
||||||
|
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||||
|
applyopts(-1, opts, PH_INIT);
|
||||||
|
|
||||||
|
retropt_string(opts, OPT_OPENSSL_CERTIFICATE, &opt_cert);
|
||||||
|
if (opt_cert == NULL) {
|
||||||
|
Warn("no certificate given; consider option \"cert\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
result =
|
||||||
|
_xioopen_openssl_prepare(opts, xfd, true, &opt_ver, opt_cert,
|
||||||
|
&xfd->para.openssl.ctx);
|
||||||
|
if (result != STAT_OK) return STAT_NORETRY;
|
||||||
|
|
||||||
|
if (_xioopen_ipapp_listen_prepare(opts, &opts0, portname, &pf, ipproto,
|
||||||
|
xfd->para.socket.ip.res_opts[1],
|
||||||
|
xfd->para.socket.ip.res_opts[0],
|
||||||
|
us, &uslen, &socktype)
|
||||||
|
!= STAT_OK) {
|
||||||
|
return STAT_NORETRY;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (argc == 1) {
|
||||||
|
if (xfd->fd1 < 0) {
|
||||||
|
Error("openssl-listen without port must be an embedded address");
|
||||||
|
return STAT_NORETRY;
|
||||||
|
}
|
||||||
|
|
||||||
xfd->howtoend = END_SHUTDOWN;
|
|
||||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||||
applyopts(-1, opts, PH_INIT);
|
applyopts(-1, opts, PH_INIT);
|
||||||
|
|
||||||
|
@ -430,18 +563,15 @@ static int
|
||||||
applyopts(-1, opts, PH_EARLY);
|
applyopts(-1, opts, PH_EARLY);
|
||||||
|
|
||||||
result =
|
result =
|
||||||
_xioopen_openssl_prepare(opts, xfd, true, &opt_ver, opt_cert, &ctx);
|
_xioopen_openssl_prepare(opts, xfd, true, &opt_ver, opt_cert,
|
||||||
|
&xfd->para.openssl.ctx);
|
||||||
if (result != STAT_OK) return STAT_NORETRY;
|
if (result != STAT_OK) return STAT_NORETRY;
|
||||||
|
|
||||||
if (_xioopen_ipapp_listen_prepare(opts, &opts0, portname, &pf, ipproto,
|
} else {
|
||||||
xfd->para.socket.ip.res_opts[1],
|
Error1("%s: 1 parameter required", argv[0]);
|
||||||
xfd->para.socket.ip.res_opts[0],
|
return -1;
|
||||||
us, &uslen, &socktype)
|
|
||||||
!= STAT_OK) {
|
|
||||||
return STAT_NORETRY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
xfd->addr = &addr_openssl_listen;
|
|
||||||
xfd->dtype = XIODATA_OPENSSL;
|
xfd->dtype = XIODATA_OPENSSL;
|
||||||
|
|
||||||
while (true) { /* loop over failed attempts */
|
while (true) { /* loop over failed attempts */
|
||||||
|
@ -453,6 +583,7 @@ static int
|
||||||
#endif /* WITH_RETRY */
|
#endif /* WITH_RETRY */
|
||||||
level = E_ERROR;
|
level = E_ERROR;
|
||||||
|
|
||||||
|
if (portname) {
|
||||||
/* tcp listen; this can fork() for us; it only returns on error or on
|
/* tcp listen; this can fork() for us; it only returns on error or on
|
||||||
successful establishment of tcp connection */
|
successful establishment of tcp connection */
|
||||||
result = _xioopen_listen(xfd, xioflags,
|
result = _xioopen_listen(xfd, xioflags,
|
||||||
|
@ -464,6 +595,7 @@ static int
|
||||||
E_ERROR
|
E_ERROR
|
||||||
#endif /* WITH_RETRY */
|
#endif /* WITH_RETRY */
|
||||||
);
|
);
|
||||||
|
}
|
||||||
/*! not sure if we should try again on retry/forever */
|
/*! not sure if we should try again on retry/forever */
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case STAT_OK: break;
|
case STAT_OK: break;
|
||||||
|
@ -484,8 +616,8 @@ static int
|
||||||
default:
|
default:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
result =
|
||||||
result = _xioopen_openssl_listen(xfd, opt_ver, ctx, level);
|
_xioopen_openssl_listen(xfd, opt_ver, xfd->para.openssl.ctx, level);
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case STAT_OK: break;
|
case STAT_OK: break;
|
||||||
#if WITH_RETRY
|
#if WITH_RETRY
|
||||||
|
@ -537,12 +669,11 @@ int _xioopen_openssl_listen(struct single *xfd,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* assign the network connection to the SSL object */
|
/* assign the network connection to the SSL object */
|
||||||
if (sycSSL_set_fd(xfd->para.openssl.ssl, xfd->fd) <= 0) {
|
ret = xioSSL_set_fd(xfd, level);
|
||||||
if (ERR_peek_error() == 0) Msg(level, "SSL_set_fd() failed");
|
if (ret != STAT_OK) {
|
||||||
while (err = ERR_get_error()) {
|
sycSSL_free(xfd->para.openssl.ssl);
|
||||||
Msg2(level, "SSL_set_fd(, %d): %s",
|
xfd->para.openssl.ssl = NULL;
|
||||||
xfd->fd, ERR_error_string(err, NULL));
|
return ret;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if WITH_DEBUG
|
#if WITH_DEBUG
|
||||||
|
@ -634,7 +765,6 @@ int
|
||||||
unsigned long err;
|
unsigned long err;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
xfd->addr = &addr_openssl;
|
|
||||||
xfd->dtype = XIODATA_OPENSSL;
|
xfd->dtype = XIODATA_OPENSSL;
|
||||||
|
|
||||||
retropt_bool(opts, OPT_OPENSSL_FIPS, &opt_fips);
|
retropt_bool(opts, OPT_OPENSSL_FIPS, &opt_fips);
|
||||||
|
@ -751,7 +881,7 @@ int
|
||||||
if ((result =
|
if ((result =
|
||||||
openssl_SSL_ERROR_SSL(E_ERROR, "SSL_CTX_load_verify_locations"))
|
openssl_SSL_ERROR_SSL(E_ERROR, "SSL_CTX_load_verify_locations"))
|
||||||
!= STAT_OK) {
|
!= STAT_OK) {
|
||||||
/*! free ctx */
|
SSL_CTX_free(*ctx); *ctx = NULL;
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -963,14 +1093,33 @@ static int xioSSL_set_fd(struct single *xfd, int level) {
|
||||||
unsigned long err;
|
unsigned long err;
|
||||||
|
|
||||||
/* assign a network connection to the SSL object */
|
/* assign a network connection to the SSL object */
|
||||||
if (sycSSL_set_fd(xfd->para.openssl.ssl, xfd->fd) <= 0) {
|
if (xfd->fd2 < 0) {
|
||||||
|
if (sycSSL_set_fd(xfd->para.openssl.ssl, xfd->fd1) <= 0) {
|
||||||
Msg(level, "SSL_set_fd() failed");
|
Msg(level, "SSL_set_fd() failed");
|
||||||
while (err = ERR_get_error()) {
|
while (err = ERR_get_error()) {
|
||||||
Msg2(level, "SSL_set_fd(, %d): %s",
|
Msg2(level, "SSL_set_fd(, %d): %s",
|
||||||
xfd->fd, ERR_error_string(err, NULL));
|
xfd->fd2, ERR_error_string(err, NULL));
|
||||||
}
|
}
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (sycSSL_set_rfd(xfd->para.openssl.ssl, xfd->fd1) <= 0) {
|
||||||
|
Msg(level, "SSL_set_rfd() failed");
|
||||||
|
while (err = ERR_get_error()) {
|
||||||
|
Msg2(level, "SSL_set_rfd(, %d): %s",
|
||||||
|
xfd->fd1, ERR_error_string(err, NULL));
|
||||||
|
}
|
||||||
|
return STAT_RETRYLATER;
|
||||||
|
}
|
||||||
|
if (sycSSL_set_wfd(xfd->para.openssl.ssl, xfd->fd2) <= 0) {
|
||||||
|
Msg(level, "SSL_set_wfd() failed");
|
||||||
|
while (err = ERR_get_error()) {
|
||||||
|
Msg2(level, "SSL_set_wfd(, %d): %s",
|
||||||
|
xfd->fd2, ERR_error_string(err, NULL));
|
||||||
|
}
|
||||||
|
return STAT_RETRYLATER;
|
||||||
|
}
|
||||||
|
}
|
||||||
return STAT_OK;
|
return STAT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,8 @@
|
||||||
#define SSLIO_BASE 0x53530000 /* "SSxx" */
|
#define SSLIO_BASE 0x53530000 /* "SSxx" */
|
||||||
#define SSLIO_MASK 0xffff0000
|
#define SSLIO_MASK 0xffff0000
|
||||||
|
|
||||||
extern const struct addrdesc addr_openssl;
|
extern const union xioaddr_desc *xioaddrs_openssl_connect[];
|
||||||
extern const struct addrdesc addr_openssl_listen;
|
extern const union xioaddr_desc *xioaddrs_openssl_listen[];
|
||||||
|
|
||||||
extern const struct optdesc opt_openssl_cipherlist;
|
extern const struct optdesc opt_openssl_cipherlist;
|
||||||
extern const struct optdesc opt_openssl_method;
|
extern const struct optdesc opt_openssl_method;
|
||||||
|
|
48
xio-pipe.c
48
xio-pipe.c
|
@ -12,16 +12,20 @@
|
||||||
|
|
||||||
#if WITH_PIPE
|
#if WITH_PIPE
|
||||||
|
|
||||||
static int xioopen_fifo(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3);
|
static int xioopen_fifo0(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3);
|
||||||
static int xioopen_fifo_unnamed(xiofile_t *sock, struct opt *opts);
|
static int xioopen_fifo1(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3);
|
||||||
|
|
||||||
|
static const struct xioaddr_endpoint_desc xioaddr_pipe0 = { XIOADDR_SYS, "pipe", 0, XIOBIT_RDWR, GROUP_FD|GROUP_NAMED|GROUP_OPEN|GROUP_FIFO, XIOSHUT_CLOSE, XIOCLOSE_CLOSE, xioopen_fifo0, 0, 0, 0 HELP("") };
|
||||||
|
static const struct xioaddr_endpoint_desc xioaddr_pipe1 = { XIOADDR_SYS, "pipe", 1, XIOBIT_ALL, GROUP_FD|GROUP_NAMED|GROUP_OPEN|GROUP_FIFO, XIOSHUT_CLOSE, XIOCLOSE_CLOSE, xioopen_fifo1, 0, 0, 0 HELP(":<filename>") };
|
||||||
|
|
||||||
const struct addrdesc addr_pipe = { "pipe", 3, xioopen_fifo, GROUP_FD|GROUP_NAMED|GROUP_OPEN|GROUP_FIFO, 0, 0, 0 HELP(":<filename>") };
|
const union xioaddr_desc *xioaddrs_pipe[] = {
|
||||||
|
(union xioaddr_desc *)&xioaddr_pipe0,
|
||||||
|
(union xioaddr_desc *)&xioaddr_pipe1,
|
||||||
|
NULL };
|
||||||
|
|
||||||
/* process an unnamed bidirectional "pipe" or "fifo" or "echo" argument with
|
/* process an unnamed bidirectional "pipe" or "fifo" or "echo" argument with
|
||||||
options */
|
options */
|
||||||
static int xioopen_fifo_unnamed(xiofile_t *sock, struct opt *opts) {
|
static int xioopen_fifo0(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *sock, unsigned groups, int dummy1, int dummy2, int dummy3) {
|
||||||
struct opt *opts2;
|
struct opt *opts2;
|
||||||
int filedes[2];
|
int filedes[2];
|
||||||
int numleft;
|
int numleft;
|
||||||
|
@ -37,11 +41,12 @@ static int xioopen_fifo_unnamed(xiofile_t *sock, struct opt *opts) {
|
||||||
/*0 Info2("pipe({%d,%d})", filedes[0], filedes[1]);*/
|
/*0 Info2("pipe({%d,%d})", filedes[0], filedes[1]);*/
|
||||||
|
|
||||||
sock->common.tag = XIO_TAG_RDWR;
|
sock->common.tag = XIO_TAG_RDWR;
|
||||||
sock->stream.dtype = XIODATA_PIPE;
|
sock->stream.dtype = XIODATA_2PIPE;
|
||||||
sock->stream.fd = filedes[0];
|
sock->stream.fd1 = filedes[0];
|
||||||
sock->stream.para.bipipe.fdout = filedes[1];
|
sock->stream.fd2 = filedes[1];
|
||||||
applyopts_cloexec(sock->stream.fd, opts);
|
sock->stream.fdtype = FDTYPE_DOUBLE;
|
||||||
applyopts_cloexec(sock->stream.para.bipipe.fdout, opts);
|
applyopts_cloexec(sock->stream.fd1, opts);
|
||||||
|
applyopts_cloexec(sock->stream.fd2, opts);
|
||||||
|
|
||||||
/* one-time and input-direction options, no second application */
|
/* one-time and input-direction options, no second application */
|
||||||
retropt_bool(opts, OPT_IGNOREEOF, &sock->stream.ignoreeof);
|
retropt_bool(opts, OPT_IGNOREEOF, &sock->stream.ignoreeof);
|
||||||
|
@ -52,7 +57,7 @@ static int xioopen_fifo_unnamed(xiofile_t *sock, struct opt *opts) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* apply options to first FD */
|
/* apply options to first FD */
|
||||||
if ((result = applyopts(sock->stream.fd, opts, PH_ALL)) < 0) {
|
if ((result = applyopts(sock->stream.fd1, opts, PH_ALL)) < 0) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if ((result = applyopts_single(&sock->stream, opts, PH_ALL)) < 0) {
|
if ((result = applyopts_single(&sock->stream, opts, PH_ALL)) < 0) {
|
||||||
|
@ -60,7 +65,7 @@ static int xioopen_fifo_unnamed(xiofile_t *sock, struct opt *opts) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* apply options to second FD */
|
/* apply options to second FD */
|
||||||
if ((result = applyopts(sock->stream.para.bipipe.fdout, opts2, PH_ALL)) < 0)
|
if ((result = applyopts(sock->stream.fd2, opts2, PH_ALL)) < 0)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -75,7 +80,7 @@ static int xioopen_fifo_unnamed(xiofile_t *sock, struct opt *opts) {
|
||||||
|
|
||||||
|
|
||||||
/* open a named pipe/fifo */
|
/* open a named pipe/fifo */
|
||||||
static int xioopen_fifo(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3) {
|
static int xioopen_fifo1(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3) {
|
||||||
const char *pipename = argv[1];
|
const char *pipename = argv[1];
|
||||||
int rw = (xioflags & XIO_ACCMODE);
|
int rw = (xioflags & XIO_ACCMODE);
|
||||||
#if HAVE_STAT64
|
#if HAVE_STAT64
|
||||||
|
@ -88,14 +93,6 @@ static int xioopen_fifo(int argc, const char *argv[], struct opt *opts, int xiof
|
||||||
mode_t mode = 0666;
|
mode_t mode = 0666;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if (argc == 1) {
|
|
||||||
return xioopen_fifo_unnamed(fd, fd->stream.opts);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argc != 2) {
|
|
||||||
Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (applyopts_single(&fd->stream, opts, PH_INIT) < 0) return -1;
|
if (applyopts_single(&fd->stream, opts, PH_INIT) < 0) return -1;
|
||||||
applyopts(-1, opts, PH_INIT);
|
applyopts(-1, opts, PH_INIT);
|
||||||
|
|
||||||
|
@ -166,11 +163,14 @@ static int xioopen_fifo(int argc, const char *argv[], struct opt *opts, int xiof
|
||||||
if ((result = _xioopen_open(pipename, rw, opts)) < 0) {
|
if ((result = _xioopen_open(pipename, rw, opts)) < 0) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
fd->stream.fd = result;
|
fd->stream.fd1 = result;
|
||||||
|
fd->stream.fdtype = FDTYPE_SINGLE;
|
||||||
|
fd->stream.howtoshut = XIOSHUTWR_NONE|XIOSHUTRD_CLOSE;
|
||||||
|
fd->stream.howtoclose = XIOCLOSE_CLOSE;
|
||||||
|
|
||||||
applyopts_named(pipename, opts, PH_FD);
|
applyopts_named(pipename, opts, PH_FD);
|
||||||
applyopts(fd->stream.fd, opts, PH_FD);
|
applyopts(fd->stream.fd1, opts, PH_FD);
|
||||||
applyopts_cloexec(fd->stream.fd, opts);
|
applyopts_cloexec(fd->stream.fd1, opts);
|
||||||
return _xio_openlate(&fd->stream, opts);
|
return _xio_openlate(&fd->stream, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
/* $Id: xio-pipe.h,v 1.4 2001/11/04 17:19:20 gerhard Exp $ */
|
/* $Id: xio-pipe.h,v 1.4.2.1 2006/07/24 19:18:02 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2001 */
|
/* Copyright Gerhard Rieger 2001-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
#ifndef __xio_pipe_h_included
|
#ifndef __xio_pipe_h_included
|
||||||
#define __xio_pipe_h_included 1
|
#define __xio_pipe_h_included 1
|
||||||
|
|
||||||
const extern struct addrdesc addr_pipe;
|
extern const union xioaddr_desc *xioaddrs_pipe[];
|
||||||
|
|
||||||
extern int xioopen_fifo_unnamed(char *arg, xiofile_t *sock);
|
extern int xioopen_fifo_unnamed(char *arg, xiofile_t *sock);
|
||||||
|
|
||||||
|
|
760
xio-progcall.c
760
xio-progcall.c
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "xiosysincludes.h"
|
#include "xiosysincludes.h"
|
||||||
#include "xioopen.h"
|
#include "xioopen.h"
|
||||||
|
#include "xiosigchld.h"
|
||||||
|
|
||||||
#include "xio-process.h"
|
#include "xio-process.h"
|
||||||
#include "xio-progcall.h"
|
#include "xio-progcall.h"
|
||||||
|
@ -41,7 +42,7 @@ const struct optdesc opt_sigquit = { "sigquit", NULL, OPT_SIGQUIT, GROUP_P
|
||||||
return>0: is parent process
|
return>0: is parent process
|
||||||
return<0: error occurred, assume parent process and no child exists !!!
|
return<0: error occurred, assume parent process and no child exists !!!
|
||||||
*/
|
*/
|
||||||
int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
int _xioopen_foxec_int(int xioflags, /* XIO_RDONLY etc. */
|
||||||
struct single *fd,
|
struct single *fd,
|
||||||
unsigned groups,
|
unsigned groups,
|
||||||
struct opt **copts /* in: opts; out: opts for child */
|
struct opt **copts /* in: opts; out: opts for child */
|
||||||
|
@ -102,6 +103,11 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
||||||
retropt_ushort(popts, OPT_FDIN, (unsigned short *)&fdi);
|
retropt_ushort(popts, OPT_FDIN, (unsigned short *)&fdi);
|
||||||
retropt_ushort(popts, OPT_FDOUT, (unsigned short *)&fdo);
|
retropt_ushort(popts, OPT_FDOUT, (unsigned short *)&fdo);
|
||||||
|
|
||||||
|
if (rw == XIO_WRONLY) {
|
||||||
|
if (fd->howtoclose == XIOCLOSE_UNSPEC) {
|
||||||
|
fd->howtoclose = XIOCLOSE_SLEEP_SIGTERM;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (withfork) {
|
if (withfork) {
|
||||||
if (!(xioflags&XIO_MAYCHILD)) {
|
if (!(xioflags&XIO_MAYCHILD)) {
|
||||||
Error("cannot fork off child process here");
|
Error("cannot fork off child process here");
|
||||||
|
@ -125,15 +131,24 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
||||||
if (!withfork) {
|
if (!withfork) {
|
||||||
/*0 struct single *stream1, *stream2;*/
|
/*0 struct single *stream1, *stream2;*/
|
||||||
|
|
||||||
|
free(*copts);
|
||||||
|
*copts = moveopts(popts, GROUP_ALL);
|
||||||
|
/* what if WE are sock1 ? */
|
||||||
|
#if 1
|
||||||
if (!(xioflags & XIO_MAYEXEC /* means exec+nofork */)) {
|
if (!(xioflags & XIO_MAYEXEC /* means exec+nofork */)) {
|
||||||
Error("option nofork is not allowed here");
|
Error("nofork option is not allowed here");
|
||||||
/*!! free something */
|
/*!! free something */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
fd->flags |= XIO_DOESEXEC;
|
fd->flags |= XIO_DOESEXEC;
|
||||||
|
#else /*!! */
|
||||||
free(*copts);
|
if (sock1 == NULL) {
|
||||||
*copts = moveopts(popts, GROUP_ALL);
|
Fatal("nofork option must no be applied to first socat address");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (fd->howtoclose == XIOCLOSE_UNSPEC) {
|
||||||
|
fd->howtoclose = XIOCLOSE_CLOSE;
|
||||||
|
}
|
||||||
|
|
||||||
#if 0 /*!! */
|
#if 0 /*!! */
|
||||||
if (sock1->tag == XIO_TAG_DUAL) {
|
if (sock1->tag == XIO_TAG_DUAL) {
|
||||||
|
@ -202,6 +217,13 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
||||||
# define PTMX "/dev/ptc" /* AIX 4.3.3 */
|
# define PTMX "/dev/ptc" /* AIX 4.3.3 */
|
||||||
#endif
|
#endif
|
||||||
fd->dtype = XIODATA_PTY;
|
fd->dtype = XIODATA_PTY;
|
||||||
|
if (fd->howtoshut == XIOSHUT_UNSPEC) {
|
||||||
|
fd->howtoshut = XIOSHUTRD_SIGTERM|XIOSHUTWR_SIGHUP;
|
||||||
|
}
|
||||||
|
if (fd->howtoclose == XIOCLOSE_UNSPEC) {
|
||||||
|
fd->howtoclose = XIOCLOSE_CLOSE_SIGTERM;
|
||||||
|
}
|
||||||
|
|
||||||
#if HAVE_DEV_PTMX || HAVE_DEV_PTC
|
#if HAVE_DEV_PTMX || HAVE_DEV_PTC
|
||||||
if (usebestpty || useptmx) {
|
if (usebestpty || useptmx) {
|
||||||
if ((ptyfd = Open(PTMX, O_RDWR|O_NOCTTY, 0620)) < 0) {
|
if ((ptyfd = Open(PTMX, O_RDWR|O_NOCTTY, 0620)) < 0) {
|
||||||
|
@ -235,7 +257,7 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
||||||
Warn2("ttyname(%d): %s", ptyfd, strerror(errno));
|
Warn2("ttyname(%d): %s", ptyfd, strerror(errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
strncpy(ptyname, tn, MAXPTYNAMELEN);
|
strncpy(ptyname, tn, MAXPTYNAMELEN); /*! ttyname_r() */
|
||||||
if ((ttyfd = Open(tn, O_RDWR|O_NOCTTY, 0620)) < 0) {
|
if ((ttyfd = Open(tn, O_RDWR|O_NOCTTY, 0620)) < 0) {
|
||||||
Warn2("open(\"%s\", O_RDWR|O_NOCTTY, 0620): %s", tn, strerror(errno));
|
Warn2("open(\"%s\", O_RDWR|O_NOCTTY, 0620): %s", tn, strerror(errno));
|
||||||
} else {
|
} else {
|
||||||
|
@ -283,8 +305,11 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
applyopts_cloexec(ptyfd, popts);/*!*/
|
applyopts_cloexec(ptyfd, popts);/*!*/
|
||||||
if (fd->howtoend = END_UNSPEC) {
|
if (fd->howtoshut == XIOSHUT_UNSPEC) {
|
||||||
fd->howtoend = END_CLOSE_KILL;
|
fd->howtoshut = XIOSHUTRD_SIGTERM|XIOSHUTWR_SIGHUP;
|
||||||
|
}
|
||||||
|
if (fd->howtoclose == XIOCLOSE_UNSPEC) {
|
||||||
|
fd->howtoclose = XIOCLOSE_CLOSE_SIGTERM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* this for parent, was after fork */
|
/* this for parent, was after fork */
|
||||||
|
@ -292,7 +317,8 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
||||||
applyopts(ptyfd, popts, PH_LATE);
|
applyopts(ptyfd, popts, PH_LATE);
|
||||||
if (applyopts_single(fd, popts, PH_LATE) < 0) return -1;
|
if (applyopts_single(fd, popts, PH_LATE) < 0) return -1;
|
||||||
|
|
||||||
fd->fd = ptyfd;
|
fd->fd1 = ptyfd;
|
||||||
|
fd->fdtype = FDTYPE_SINGLE;
|
||||||
|
|
||||||
/* this for child, was after fork */
|
/* this for child, was after fork */
|
||||||
applyopts(ttyfd, *copts, PH_FD);
|
applyopts(ttyfd, *copts, PH_FD);
|
||||||
|
@ -301,13 +327,23 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
||||||
if (usepipes) {
|
if (usepipes) {
|
||||||
struct opt *popts2, *copts2;
|
struct opt *popts2, *copts2;
|
||||||
|
|
||||||
if (rw == XIO_RDWR)
|
if (rw == XIO_RDWR) {
|
||||||
fd->dtype = XIODATA_2PIPE;
|
fd->dtype = XIODATA_2PIPE;
|
||||||
|
}
|
||||||
|
if (fd->howtoshut == XIOSHUT_UNSPEC) {
|
||||||
|
fd->howtoshut = XIOSHUT_CLOSE;
|
||||||
|
}
|
||||||
|
if (fd->howtoclose == XIOCLOSE_UNSPEC) {
|
||||||
|
fd->howtoclose = XIOCLOSE_CLOSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (rw != XIO_WRONLY) {
|
if (rw != XIO_WRONLY) {
|
||||||
if (Pipe(rdpip) < 0) {
|
if (Pipe(rdpip) < 0) {
|
||||||
Error2("pipe(%p): %s", rdpip, strerror(errno));
|
Error2("pipe(%p): %s", rdpip, strerror(errno));
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
rdpip[0] = rdpip[1] = -1;
|
||||||
}
|
}
|
||||||
/*0 Info2("pipe({%d,%d})", rdpip[0], rdpip[1]);*/
|
/*0 Info2("pipe({%d,%d})", rdpip[0], rdpip[1]);*/
|
||||||
/* rdpip[0]: read by socat; rdpip[1]: write by child */
|
/* rdpip[0]: read by socat; rdpip[1]: write by child */
|
||||||
|
@ -331,6 +367,8 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
||||||
Error2("pipe(%p): %s", wrpip, strerror(errno));
|
Error2("pipe(%p): %s", wrpip, strerror(errno));
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
wrpip[0] = wrpip[1] = -1;
|
||||||
}
|
}
|
||||||
/*0 Info2("pipe({%d,%d})", wrpip[0], wrpip[1]);*/
|
/*0 Info2("pipe({%d,%d})", wrpip[0], wrpip[1]);*/
|
||||||
|
|
||||||
|
@ -340,20 +378,25 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
||||||
applyopts(wrpip[1], popts2, PH_FD);
|
applyopts(wrpip[1], popts2, PH_FD);
|
||||||
applyopts(wrpip[0], copts2, PH_FD);
|
applyopts(wrpip[0], copts2, PH_FD);
|
||||||
}
|
}
|
||||||
if (fd->howtoend == END_UNSPEC) {
|
|
||||||
fd->howtoend = END_CLOSE_KILL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* this for parent, was after fork */
|
/* this for parent, was after fork */
|
||||||
switch (rw) {
|
switch (rw) {
|
||||||
case XIO_RDONLY: fd->fd = rdpip[0]; break;
|
case XIO_RDONLY:
|
||||||
case XIO_WRONLY: fd->fd = wrpip[1]; break;
|
fd->fd1 = rdpip[0];
|
||||||
case XIO_RDWR: fd->fd = rdpip[0];
|
fd->fdtype = FDTYPE_SINGLE;
|
||||||
fd->para.exec.fdout = wrpip[1];
|
break;
|
||||||
|
case XIO_WRONLY:
|
||||||
|
fd->fd1 = wrpip[1];
|
||||||
|
fd->fdtype = FDTYPE_SINGLE;
|
||||||
|
break;
|
||||||
|
case XIO_RDWR:
|
||||||
|
fd->fd1 = rdpip[0];
|
||||||
|
fd->fd2 = wrpip[1];
|
||||||
|
fd->fdtype = FDTYPE_DOUBLE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
applyopts(fd->fd, popts, PH_FD);
|
applyopts(fd->fd1, popts, PH_FD);
|
||||||
applyopts(fd->fd, popts, PH_LATE);
|
applyopts(fd->fd1, popts, PH_LATE);
|
||||||
if (applyopts_single(fd, popts, PH_LATE) < 0) return -1;
|
if (applyopts_single(fd, popts, PH_LATE) < 0) return -1;
|
||||||
} else {
|
} else {
|
||||||
d = AF_UNIX; type = SOCK_STREAM;
|
d = AF_UNIX; type = SOCK_STREAM;
|
||||||
|
@ -385,29 +428,42 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
||||||
applyopts(sv[1], popts, PH_BIND);
|
applyopts(sv[1], popts, PH_BIND);
|
||||||
applyopts(sv[1], popts, PH_PASTBIND);
|
applyopts(sv[1], popts, PH_PASTBIND);
|
||||||
|
|
||||||
if (fd->howtoend == END_UNSPEC) {
|
if (fd->howtoshut == XIOSHUT_UNSPEC) {
|
||||||
fd->howtoend = END_SHUTDOWN_KILL;
|
fd->howtoshut = XIOSHUT_DOWN;
|
||||||
|
}
|
||||||
|
if (fd->howtoclose == XIOCLOSE_UNSPEC) {
|
||||||
|
fd->howtoclose = XIOCLOSE_SIGTERM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* this for parent, was after fork */
|
/* this for parent, was after fork */
|
||||||
fd->fd = sv[0];
|
fd->fd1 = sv[0];
|
||||||
applyopts(fd->fd, popts, PH_FD);
|
fd->fdtype = FDTYPE_SINGLE;
|
||||||
applyopts(fd->fd, popts, PH_LATE);
|
applyopts(fd->fd1, popts, PH_FD);
|
||||||
|
applyopts(fd->fd1, popts, PH_LATE);
|
||||||
if (applyopts_single(fd, popts, PH_LATE) < 0) return -1;
|
if (applyopts_single(fd, popts, PH_LATE) < 0) return -1;
|
||||||
}
|
}
|
||||||
/*0 if ((optpr = copyopts(*copts, GROUP_PROCESS)) == NULL)
|
/*0 if ((optpr = copyopts(*copts, GROUP_PROCESS)) == NULL)
|
||||||
return STAT_RETRYLATER;*/
|
return STAT_RETRYLATER;*/
|
||||||
retropt_bool(*copts, OPT_STDERR, &withstderr);
|
retropt_bool(*copts, OPT_STDERR, &withstderr);
|
||||||
|
#if 0
|
||||||
if (Signal(SIGCHLD, childdied) == SIG_ERR) {
|
if (Signal(SIGCHLD, childdied) == SIG_ERR) {
|
||||||
Warn2("signal(SIGCHLD, %p): %s", childdied, strerror(errno));
|
Warn2("signal(SIGCHLD, %p): %s", childdied, strerror(errno));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (withfork) {
|
if (withfork) {
|
||||||
const char *forkwaitstring;
|
const char *forkwaitstring;
|
||||||
int forkwaitsecs = 0;
|
int forkwaitsecs = 0;
|
||||||
|
sigset_t set, oldset;
|
||||||
|
|
||||||
|
sigemptyset(&set);
|
||||||
|
sigaddset(&set, SIGCHLD);
|
||||||
|
|
||||||
|
Sigprocmask(SIG_BLOCK, &set, &oldset); /* disable SIGCHLD */
|
||||||
|
|
||||||
pid = Fork();
|
pid = Fork();
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
|
Sigprocmask(SIG_SETMASK, &oldset, NULL);
|
||||||
Error1("fork(): %s", strerror(errno));
|
Error1("fork(): %s", strerror(errno));
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
@ -417,11 +473,18 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
||||||
Sleep(forkwaitsecs);
|
Sleep(forkwaitsecs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pid > 0) {
|
||||||
|
/* for parent (this is our socat process) */
|
||||||
|
xiosigchld_register(pid, xiosigaction_child, fd);
|
||||||
|
Sigprocmask(SIG_SETMASK, &oldset, NULL); /* disable SIGCHLD */
|
||||||
|
}
|
||||||
|
|
||||||
if (pid == 0) { /* child */
|
if (pid == 0) { /* child */
|
||||||
/* drop parents locks, reset FIPS... */
|
/* drop parents locks, reset FIPS... */
|
||||||
if (xio_forked_inchild() != 0) {
|
if (xio_forked_inchild() != 0) {
|
||||||
Exit(1);
|
Exit(1);
|
||||||
}
|
}
|
||||||
|
Sigprocmask(SIG_SETMASK, &oldset, NULL); /* disable SIGCHLD */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!withfork || pid == 0) { /* child */
|
if (!withfork || pid == 0) { /* child */
|
||||||
|
@ -580,19 +643,23 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (0) {
|
||||||
|
; /* for canonical reasons */
|
||||||
#if HAVE_PTY
|
#if HAVE_PTY
|
||||||
if (usepty) {
|
} else if (usepty) {
|
||||||
if (Close(ttyfd) < 0) {
|
if (Close(ttyfd) < 0) {
|
||||||
Info2("close(%d): %s", ttyfd, strerror(errno));
|
Info2("close(%d): %s", ttyfd, strerror(errno));
|
||||||
}
|
}
|
||||||
} /*0 else*/
|
|
||||||
#endif /* HAVE_PTY */
|
#endif /* HAVE_PTY */
|
||||||
#if 0
|
#if 1
|
||||||
if (usepipes) {
|
} else if (usepipes) {
|
||||||
} else {
|
if (wrpip[0] >= 0) Close(wrpip[0]);
|
||||||
|
if (rdpip[1] >= 0) Close(rdpip[1]);
|
||||||
|
} else { /* socketpair() */
|
||||||
|
Close(sv[1]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
fd->para.exec.pid = pid;
|
fd->child.pid = pid;
|
||||||
|
|
||||||
if (applyopts_single(fd, popts, PH_LATE) < 0) return -1;
|
if (applyopts_single(fd, popts, PH_LATE) < 0) return -1;
|
||||||
applyopts_signal(fd, popts);
|
applyopts_signal(fd, popts);
|
||||||
|
@ -604,6 +671,639 @@ int _xioopen_foxec(int xioflags, /* XIO_RDONLY etc. */
|
||||||
|
|
||||||
return pid; /* indicate parent (main) process */
|
return pid; /* indicate parent (main) process */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* fork for exec/system, but return before exec'ing.
|
||||||
|
return=0: is child process
|
||||||
|
return>0: is parent process
|
||||||
|
return<0: error occurred, assume parent process and no child exists !!!
|
||||||
|
*/
|
||||||
|
int _xioopen_foxec_end(int xioflags, /* XIO_RDONLY etc. */
|
||||||
|
struct single *fd,
|
||||||
|
unsigned groups,
|
||||||
|
struct opt **copts /* in: opts; out: opts for child */
|
||||||
|
) {
|
||||||
|
struct opt *popts; /* parent process options */
|
||||||
|
int numleft;
|
||||||
|
int d, type, protocol, sv[2], rdpip[2], wrpip[2];
|
||||||
|
int rw = (xioflags & XIO_ACCMODE);
|
||||||
|
bool usepipes = false;
|
||||||
|
#if HAVE_PTY
|
||||||
|
int ptyfd = -1, ttyfd = -1;
|
||||||
|
bool usebestpty = false; /* use the best available way to open pty */
|
||||||
|
#if defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC)
|
||||||
|
bool useptmx = false; /* use /dev/ptmx or equivalent */
|
||||||
|
#endif
|
||||||
|
#if HAVE_OPENPTY
|
||||||
|
bool useopenpty = false; /* try only openpty */
|
||||||
|
#endif /* HAVE_OPENPTY */
|
||||||
|
bool usepty = false; /* any of the pty options is selected */
|
||||||
|
char ptyname[MAXPTYNAMELEN];
|
||||||
|
#endif /* HAVE_PTY */
|
||||||
|
pid_t pid = 0; /* mostly int */
|
||||||
|
short fdi = 0, fdo = 1;
|
||||||
|
short result;
|
||||||
|
bool withstderr = false;
|
||||||
|
bool nofork = false;
|
||||||
|
bool withfork;
|
||||||
|
|
||||||
|
popts = moveopts(*copts, GROUP_ALL);
|
||||||
|
if (applyopts_single(fd, popts, PH_INIT) < 0) return -1;
|
||||||
|
applyopts2(-1, popts, PH_INIT, PH_EARLY);
|
||||||
|
|
||||||
|
retropt_bool(popts, OPT_NOFORK, &nofork);
|
||||||
|
withfork = !nofork;
|
||||||
|
|
||||||
|
retropt_bool(popts, OPT_PIPES, &usepipes);
|
||||||
|
#if HAVE_PTY
|
||||||
|
retropt_bool(popts, OPT_PTY, &usebestpty);
|
||||||
|
#if HAVE_OPENPTY
|
||||||
|
retropt_bool(popts, OPT_OPENPTY, &useopenpty);
|
||||||
|
#endif
|
||||||
|
#if defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC)
|
||||||
|
retropt_bool(popts, OPT_PTMX, &useptmx);
|
||||||
|
#endif
|
||||||
|
usepty = (usebestpty
|
||||||
|
#if HAVE_OPENPTY
|
||||||
|
|| useopenpty
|
||||||
|
#endif
|
||||||
|
#if defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC)
|
||||||
|
|| useptmx
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
if (usepipes && usepty) {
|
||||||
|
Warn("_xioopen_foxec(): options \"pipes\" and \"pty\" must not be specified together; ignoring \"pipes\"");
|
||||||
|
usepipes = false;
|
||||||
|
}
|
||||||
|
#endif /* HAVE_PTY */
|
||||||
|
retropt_ushort(popts, OPT_FDIN, (unsigned short *)&fdi);
|
||||||
|
retropt_ushort(popts, OPT_FDOUT, (unsigned short *)&fdo);
|
||||||
|
|
||||||
|
if (rw == XIO_WRONLY) {
|
||||||
|
if (fd->howtoclose == XIOCLOSE_UNSPEC) {
|
||||||
|
fd->howtoclose = XIOCLOSE_SLEEP_SIGTERM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (withfork) {
|
||||||
|
if (!(xioflags&XIO_MAYCHILD)) {
|
||||||
|
Error("cannot fork off child process here");
|
||||||
|
/*!! free something */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fd->flags |= XIO_DOESCHILD;
|
||||||
|
|
||||||
|
#if HAVE_PTY
|
||||||
|
Notice2("forking off child, using %s for %s",
|
||||||
|
&("socket\0\0pipes\0\0\0pty\0\0\0\0\0"[(usepipes<<3)|(usepty<<4)]),
|
||||||
|
ddirection[rw]);
|
||||||
|
#else
|
||||||
|
Notice2("forking off child, using %s for %s",
|
||||||
|
&("socket\0\0pipes\0\0\0"[(usepipes<<3)]),
|
||||||
|
ddirection[rw]);
|
||||||
|
#endif /* HAVE_PTY */
|
||||||
|
}
|
||||||
|
applyopts(-1, popts, PH_PREBIGEN);
|
||||||
|
|
||||||
|
if (!withfork) {
|
||||||
|
/*0 struct single *stream1, *stream2;*/
|
||||||
|
|
||||||
|
free(*copts);
|
||||||
|
*copts = moveopts(popts, GROUP_ALL);
|
||||||
|
/* what if WE are sock1 ? */
|
||||||
|
#if 1
|
||||||
|
if (!(xioflags & XIO_MAYEXEC /* means exec+nofork */)) {
|
||||||
|
Error("nofork option is not allowed here");
|
||||||
|
/*!! free something */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
fd->flags |= XIO_DOESEXEC;
|
||||||
|
#else /*!! */
|
||||||
|
if (sock1 == NULL) {
|
||||||
|
Fatal("nofork option must no be applied to first socat address");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (fd->howtoclose == XIOCLOSE_UNSPEC) {
|
||||||
|
fd->howtoclose = XIOCLOSE_CLOSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0 /*!! */
|
||||||
|
if (sock1->tag == XIO_TAG_DUAL) {
|
||||||
|
stream1 = &sock1->dual.stream[0]->stream;
|
||||||
|
stream2 = &sock1->dual.stream[1]->stream;
|
||||||
|
} else {
|
||||||
|
stream1 = &sock1->stream;
|
||||||
|
stream2 = &sock1->stream;
|
||||||
|
}
|
||||||
|
if (stream1->dtype == DATA_READLINE || stream2->dtype == DATA_READLINE ||
|
||||||
|
stream1->dtype == DATA_OPENSSL || stream2->dtype == DATA_OPENSSL
|
||||||
|
) {
|
||||||
|
Error("with option nofork, openssl and readline in address1 do not work");
|
||||||
|
}
|
||||||
|
if (stream1->lineterm != LINETERM_RAW ||
|
||||||
|
stream2->lineterm != LINETERM_RAW ||
|
||||||
|
stream1->ignoreeof || stream2->ignoreeof) {
|
||||||
|
Warn("due to option nofork, address1 options for lineterm and igoreeof do not apply");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*! problem: when fdi==WRFD(sock[0]) or fdo==RDFD(sock[0]) */
|
||||||
|
if (rw != XIO_WRONLY) {
|
||||||
|
if (XIO_GETRDFD(sock[0]/*!!*/) == fdi) {
|
||||||
|
if (Fcntl_l(fdi, F_SETFD, 0) < 0) {
|
||||||
|
Warn2("fcntl(%d, F_SETFD, 0): %s", fdi, strerror(errno));
|
||||||
|
}
|
||||||
|
if (Dup2(XIO_GETRDFD(sock[0]), fdi) < 0) {
|
||||||
|
Error3("dup2(%d, %d): %s",
|
||||||
|
XIO_GETRDFD(sock[0]), fdi, strerror(errno));
|
||||||
|
}
|
||||||
|
/*0 Info2("dup2(%d, %d)", XIO_GETRDFD(sock[0]), fdi);*/
|
||||||
|
} else {
|
||||||
|
if (Dup2(XIO_GETRDFD(sock[0]), fdi) < 0) {
|
||||||
|
Error3("dup2(%d, %d): %s",
|
||||||
|
XIO_GETRDFD(sock[0]), fdi, strerror(errno));
|
||||||
|
}
|
||||||
|
/*0 Info2("dup2(%d, %d)", XIO_GETRDFD(sock[0]), fdi);*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rw != XIO_RDONLY) {
|
||||||
|
if (XIO_GETWRFD(sock[0]) == fdo) {
|
||||||
|
if (Fcntl_l(fdo, F_SETFD, 0) < 0) {
|
||||||
|
Warn2("fcntl(%d, F_SETFD, 0): %s", fdo, strerror(errno));
|
||||||
|
}
|
||||||
|
if (Dup2(XIO_GETWRFD(sock[0]), fdo) < 0) {
|
||||||
|
Error3("dup2(%d, %d): %s)",
|
||||||
|
XIO_GETWRFD(sock[0]), fdo, strerror(errno));
|
||||||
|
}
|
||||||
|
/*0 Info2("dup2(%d, %d)", XIO_GETWRFD(sock[0]), fdo);*/
|
||||||
|
} else {
|
||||||
|
if (Dup2(XIO_GETWRFD(sock[0]), fdo) < 0) {
|
||||||
|
Error3("dup2(%d, %d): %s)",
|
||||||
|
XIO_GETWRFD(sock[0]), fdo, strerror(errno));
|
||||||
|
}
|
||||||
|
/*0 Info2("dup2(%d, %d)", XIO_GETWRFD(sock[0]), fdo);*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
#if HAVE_PTY
|
||||||
|
if (usepty) {
|
||||||
|
|
||||||
|
#if defined(HAVE_DEV_PTMX)
|
||||||
|
# define PTMX "/dev/ptmx" /* Linux */
|
||||||
|
#elif HAVE_DEV_PTC
|
||||||
|
# define PTMX "/dev/ptc" /* AIX 4.3.3 */
|
||||||
|
#endif
|
||||||
|
fd->dtype = XIODATA_PTY;
|
||||||
|
if (fd->howtoshut == XIOSHUT_UNSPEC) {
|
||||||
|
fd->howtoshut = XIOSHUTRD_SIGTERM|XIOSHUTWR_SIGHUP;
|
||||||
|
}
|
||||||
|
if (fd->howtoclose == XIOCLOSE_UNSPEC) {
|
||||||
|
fd->howtoclose = XIOCLOSE_CLOSE_SIGTERM;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if HAVE_DEV_PTMX || HAVE_DEV_PTC
|
||||||
|
if (usebestpty || useptmx) {
|
||||||
|
if ((ptyfd = Open(PTMX, O_RDWR|O_NOCTTY, 0620)) < 0) {
|
||||||
|
Warn1("open(\""PTMX"\", O_RDWR|O_NOCTTY, 0620): %s",
|
||||||
|
strerror(errno));
|
||||||
|
/*!*/
|
||||||
|
} else {
|
||||||
|
/*0 Info2("open(\"%s\", O_RDWR|O_NOCTTY, 0620) -> %d", PTMX, ptyfd);*/
|
||||||
|
}
|
||||||
|
if (ptyfd >= 0 && ttyfd < 0) {
|
||||||
|
char *tn = NULL;
|
||||||
|
/* we used PTMX before forking */
|
||||||
|
extern char *ptsname(int);
|
||||||
|
#if HAVE_GRANTPT /* AIX, not Linux */
|
||||||
|
if (Grantpt(ptyfd)/*!*/ < 0) {
|
||||||
|
Warn2("grantpt(%d): %s", ptyfd, strerror(errno));
|
||||||
|
}
|
||||||
|
#endif /* HAVE_GRANTPT */
|
||||||
|
#if HAVE_UNLOCKPT
|
||||||
|
if (Unlockpt(ptyfd)/*!*/ < 0) {
|
||||||
|
Warn2("unlockpt(%d): %s", ptyfd, strerror(errno));
|
||||||
|
}
|
||||||
|
#endif /* HAVE_UNLOCKPT */
|
||||||
|
#if HAVE_PTSNAME /* AIX, not Linux */
|
||||||
|
if ((tn = Ptsname(ptyfd)) == NULL) {
|
||||||
|
Warn2("ptsname(%d): %s", ptyfd, strerror(errno));
|
||||||
|
}
|
||||||
|
#endif /* HAVE_PTSNAME */
|
||||||
|
if (tn == NULL) {
|
||||||
|
if ((tn = Ttyname(ptyfd)) == NULL) {
|
||||||
|
Warn2("ttyname(%d): %s", ptyfd, strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
strncpy(ptyname, tn, MAXPTYNAMELEN); /*! ttyname_r() */
|
||||||
|
if ((ttyfd = Open(tn, O_RDWR|O_NOCTTY, 0620)) < 0) {
|
||||||
|
Warn2("open(\"%s\", O_RDWR|O_NOCTTY, 0620): %s", tn, strerror(errno));
|
||||||
|
} else {
|
||||||
|
/*0 Info2("open(\"%s\", O_RDWR|O_NOCTTY, 0620) -> %d", tn, ttyfd);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef I_PUSH
|
||||||
|
/* Linux: I_PUSH def'd; pty: ioctl(, I_FIND, ...) -> -1 EINVAL */
|
||||||
|
/* AIX: I_PUSH def'd; pty: ioctl(, I_FIND, ...) -> 1 */
|
||||||
|
/* SunOS: I_PUSH def'd; pty: ioctl(, I_FIND, ...) -> 0 */
|
||||||
|
/* HP-UX: I_PUSH def'd; pty: ioctl(, I_FIND, ...) -> 0 */
|
||||||
|
if (Ioctl(ttyfd, I_FIND, "ldterm") == 0) {
|
||||||
|
Ioctl(ttyfd, I_PUSH, "ptem"); /* 0 */
|
||||||
|
Ioctl(ttyfd, I_PUSH, "ldterm"); /* 0 */
|
||||||
|
Ioctl(ttyfd, I_PUSH, "ttcompat"); /* HP-UX: -1 */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0 /* the following block need not work */
|
||||||
|
|
||||||
|
if (ttyfd >= 0 && ((tn = Ttyname(ttyfd)) == NULL)) {
|
||||||
|
Warn2("ttyname(%d): %s", ttyfd, strerror(errno));
|
||||||
|
}
|
||||||
|
if (tn == NULL) {
|
||||||
|
Error("could not open pty");
|
||||||
|
return STAT_NORETRY;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
Info1("opened pseudo terminal %s", tn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* HAVE_DEV_PTMX || HAVE_DEV_PTC */
|
||||||
|
#if HAVE_OPENPTY
|
||||||
|
if (ptyfd < 0) {
|
||||||
|
int result;
|
||||||
|
if ((result = Openpty(&ptyfd, &ttyfd, ptyname, NULL, NULL)) < 0) {
|
||||||
|
Error4("openpty(%p, %p, %p, NULL, NULL): %s",
|
||||||
|
&ptyfd, &ttyfd, ptyname, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* HAVE_OPENPTY */
|
||||||
|
free(*copts);
|
||||||
|
if ((*copts = moveopts(popts, GROUP_TERMIOS|GROUP_FORK|GROUP_EXEC|GROUP_PROCESS)) == NULL) {
|
||||||
|
return STAT_RETRYLATER;
|
||||||
|
}
|
||||||
|
applyopts_cloexec(ptyfd, popts);/*!*/
|
||||||
|
if (fd->howtoshut == XIOSHUT_UNSPEC) {
|
||||||
|
fd->howtoshut = XIOSHUTRD_SIGTERM|XIOSHUTWR_SIGHUP;
|
||||||
|
}
|
||||||
|
if (fd->howtoclose == XIOCLOSE_UNSPEC) {
|
||||||
|
fd->howtoclose = XIOCLOSE_CLOSE_SIGTERM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this for parent, was after fork */
|
||||||
|
applyopts(ptyfd, popts, PH_FD);
|
||||||
|
applyopts(ptyfd, popts, PH_LATE);
|
||||||
|
if (applyopts_single(fd, popts, PH_LATE) < 0) return -1;
|
||||||
|
|
||||||
|
fd->fd1 = ptyfd;
|
||||||
|
fd->fdtype = FDTYPE_SINGLE;
|
||||||
|
|
||||||
|
/* this for child, was after fork */
|
||||||
|
applyopts(ttyfd, *copts, PH_FD);
|
||||||
|
} else
|
||||||
|
#endif /* HAVE_PTY */
|
||||||
|
if (usepipes) {
|
||||||
|
struct opt *popts2, *copts2;
|
||||||
|
|
||||||
|
if (rw == XIO_RDWR) {
|
||||||
|
fd->dtype = XIODATA_2PIPE;
|
||||||
|
}
|
||||||
|
if (fd->howtoshut == XIOSHUT_UNSPEC) {
|
||||||
|
fd->howtoshut = XIOSHUT_CLOSE;
|
||||||
|
}
|
||||||
|
if (fd->howtoclose == XIOCLOSE_UNSPEC) {
|
||||||
|
fd->howtoclose = XIOCLOSE_CLOSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rw != XIO_WRONLY) {
|
||||||
|
if (Pipe(rdpip) < 0) {
|
||||||
|
Error2("pipe(%p): %s", rdpip, strerror(errno));
|
||||||
|
return STAT_RETRYLATER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*0 Info2("pipe({%d,%d})", rdpip[0], rdpip[1]);*/
|
||||||
|
/* rdpip[0]: read by socat; rdpip[1]: write by child */
|
||||||
|
free(*copts);
|
||||||
|
if ((*copts = moveopts(popts, GROUP_FORK|GROUP_EXEC|GROUP_PROCESS))
|
||||||
|
== NULL) {
|
||||||
|
return STAT_RETRYLATER;
|
||||||
|
}
|
||||||
|
|
||||||
|
popts2 = copyopts(popts, GROUP_ALL);
|
||||||
|
copts2 = copyopts(*copts, GROUP_ALL);
|
||||||
|
|
||||||
|
if (rw != XIO_WRONLY) {
|
||||||
|
applyopts_cloexec(rdpip[0], popts);
|
||||||
|
applyopts(rdpip[0], popts, PH_FD);
|
||||||
|
applyopts(rdpip[1], *copts, PH_FD);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rw != XIO_RDONLY) {
|
||||||
|
if (Pipe(wrpip) < 0) {
|
||||||
|
Error2("pipe(%p): %s", wrpip, strerror(errno));
|
||||||
|
return STAT_RETRYLATER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*0 Info2("pipe({%d,%d})", wrpip[0], wrpip[1]);*/
|
||||||
|
|
||||||
|
/* wrpip[1]: write by socat; wrpip[0]: read by child */
|
||||||
|
if (rw != XIO_RDONLY) {
|
||||||
|
applyopts_cloexec(wrpip[1], popts2);
|
||||||
|
applyopts(wrpip[1], popts2, PH_FD);
|
||||||
|
applyopts(wrpip[0], copts2, PH_FD);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this for parent, was after fork */
|
||||||
|
switch (rw) {
|
||||||
|
case XIO_RDONLY:
|
||||||
|
fd->fd1 = rdpip[0];
|
||||||
|
fd->fdtype = FDTYPE_SINGLE;
|
||||||
|
break;
|
||||||
|
case XIO_WRONLY:
|
||||||
|
fd->fd1 = wrpip[1];
|
||||||
|
fd->fdtype = FDTYPE_SINGLE;
|
||||||
|
break;
|
||||||
|
case XIO_RDWR:
|
||||||
|
fd->fd1 = rdpip[0];
|
||||||
|
fd->fd2 = wrpip[1];
|
||||||
|
fd->fdtype = FDTYPE_DOUBLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
applyopts(fd->fd1, popts, PH_FD);
|
||||||
|
applyopts(fd->fd1, popts, PH_LATE);
|
||||||
|
if (applyopts_single(fd, popts, PH_LATE) < 0) return -1;
|
||||||
|
} else {
|
||||||
|
d = AF_UNIX; type = SOCK_STREAM;
|
||||||
|
protocol = 0; /* PF_UNIX does not work on AIX */
|
||||||
|
retropt_int(popts, OPT_SO_TYPE, &type);
|
||||||
|
result = Socketpair(d, type, protocol, sv);
|
||||||
|
if (result < 0) {
|
||||||
|
Error5("socketpair(%d, %d, %d, %p): %s",
|
||||||
|
d, type, protocol, sv, strerror(errno));
|
||||||
|
return STAT_RETRYLATER;
|
||||||
|
}
|
||||||
|
/*0 Info5("socketpair(%d, %d, %d, {%d,%d})",
|
||||||
|
d, type, protocol, sv[0], sv[1]);*/
|
||||||
|
free(*copts);
|
||||||
|
if ((*copts = moveopts(popts, GROUP_FORK|GROUP_EXEC|GROUP_PROCESS)) == NULL) {
|
||||||
|
return STAT_RETRYLATER;
|
||||||
|
}
|
||||||
|
applyopts(sv[0], *copts, PH_PASTSOCKET);
|
||||||
|
applyopts(sv[1], popts, PH_PASTSOCKET);
|
||||||
|
|
||||||
|
applyopts_cloexec(sv[0], *copts);
|
||||||
|
applyopts(sv[0], *copts, PH_FD);
|
||||||
|
applyopts(sv[1], popts, PH_FD);
|
||||||
|
|
||||||
|
applyopts(sv[0], *copts, PH_PREBIND);
|
||||||
|
applyopts(sv[0], *copts, PH_BIND);
|
||||||
|
applyopts(sv[0], *copts, PH_PASTBIND);
|
||||||
|
applyopts(sv[1], popts, PH_PREBIND);
|
||||||
|
applyopts(sv[1], popts, PH_BIND);
|
||||||
|
applyopts(sv[1], popts, PH_PASTBIND);
|
||||||
|
|
||||||
|
if (fd->howtoshut == XIOSHUT_UNSPEC) {
|
||||||
|
fd->howtoshut = XIOSHUT_DOWN;
|
||||||
|
}
|
||||||
|
if (fd->howtoclose == XIOCLOSE_UNSPEC) {
|
||||||
|
fd->howtoclose = XIOCLOSE_SIGTERM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this for parent, was after fork */
|
||||||
|
fd->fd1 = sv[0];
|
||||||
|
fd->fdtype = FDTYPE_SINGLE;
|
||||||
|
applyopts(fd->fd1, popts, PH_FD);
|
||||||
|
applyopts(fd->fd1, popts, PH_LATE);
|
||||||
|
if (applyopts_single(fd, popts, PH_LATE) < 0) return -1;
|
||||||
|
}
|
||||||
|
/*0 if ((optpr = copyopts(*copts, GROUP_PROCESS)) == NULL)
|
||||||
|
return STAT_RETRYLATER;*/
|
||||||
|
retropt_bool(*copts, OPT_STDERR, &withstderr);
|
||||||
|
#if 0
|
||||||
|
if (Signal(SIGCHLD, childdied) == SIG_ERR) {
|
||||||
|
Warn2("signal(SIGCHLD, %p): %s", childdied, strerror(errno));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (withfork) {
|
||||||
|
const char *forkwaitstring;
|
||||||
|
int forkwaitsecs = 0;
|
||||||
|
sigset_t set, oldset;
|
||||||
|
|
||||||
|
sigemptyset(&set);
|
||||||
|
sigaddset(&set, SIGCHLD);
|
||||||
|
|
||||||
|
Sigprocmask(SIG_BLOCK, &set, &oldset); /* disable SIGCHLD */
|
||||||
|
|
||||||
|
pid = Fork();
|
||||||
|
if (pid < 0) {
|
||||||
|
Sigprocmask(SIG_SETMASK, &oldset, NULL);
|
||||||
|
Error1("fork(): %s", strerror(errno));
|
||||||
|
return STAT_RETRYLATER;
|
||||||
|
}
|
||||||
|
/* gdb recommends to have env controlled sleep after fork */
|
||||||
|
if (forkwaitstring = getenv("SOCAT_FORK_WAIT")) {
|
||||||
|
forkwaitsecs = atoi(forkwaitstring);
|
||||||
|
Sleep(forkwaitsecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pid > 0) {
|
||||||
|
/* for parent (this is our socat process) */
|
||||||
|
xiosigchld_register(pid, xiosigaction_child, fd);
|
||||||
|
Sigprocmask(SIG_SETMASK, &oldset, NULL); /* disable SIGCHLD */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pid == 0) { /* child */
|
||||||
|
/* drop parents locks, reset FIPS... */
|
||||||
|
if (xio_forked_inchild() != 0) {
|
||||||
|
Exit(1);
|
||||||
|
}
|
||||||
|
Sigprocmask(SIG_SETMASK, &oldset, NULL); /* disable SIGCHLD */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!withfork || pid == 0) { /* child */
|
||||||
|
uid_t user;
|
||||||
|
gid_t group;
|
||||||
|
|
||||||
|
if (withfork) {
|
||||||
|
if (Signal(SIGCHLD, SIG_IGN) == SIG_ERR) {
|
||||||
|
Warn1("signal(SIGCHLD, SIG_IGN): %s", strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if HAVE_PTY
|
||||||
|
if (usepty) {
|
||||||
|
if (rw != XIO_RDONLY && fdi != ttyfd) {
|
||||||
|
if (Dup2(ttyfd, fdi) < 0) {
|
||||||
|
Error3("dup2(%d, %d): %s", ttyfd, fdi, strerror(errno));
|
||||||
|
return STAT_RETRYLATER; }
|
||||||
|
/*0 Info2("dup2(%d, %d)", ttyfd, fdi);*/
|
||||||
|
}
|
||||||
|
if (rw != XIO_WRONLY && fdo != ttyfd) {
|
||||||
|
if (Dup2(ttyfd, fdo) < 0) {
|
||||||
|
Error3("dup2(%d, %d): %s", ttyfd, fdo, strerror(errno));
|
||||||
|
return STAT_RETRYLATER; }
|
||||||
|
/*0 Info2("dup2(%d, %d)", ttyfd, fdo);*/
|
||||||
|
}
|
||||||
|
if ((rw == XIO_RDONLY || fdi != ttyfd) &&
|
||||||
|
(rw == XIO_WRONLY || fdo != ttyfd)) {
|
||||||
|
applyopts_cloexec(ttyfd, *copts);
|
||||||
|
}
|
||||||
|
|
||||||
|
applyopts(ttyfd, *copts, PH_LATE);
|
||||||
|
|
||||||
|
applyopts(ttyfd, *copts, PH_LATE2);
|
||||||
|
} else
|
||||||
|
#endif /* HAVE_PTY */
|
||||||
|
if (usepipes) {
|
||||||
|
/* we might have a temporary conflict between what FDs are
|
||||||
|
currently allocated, and which are to be used. We try to find
|
||||||
|
a graceful solution via temporary descriptors */
|
||||||
|
int tmpi, tmpo;
|
||||||
|
|
||||||
|
if (fdi == rdpip[1]) { /* a conflict here */
|
||||||
|
if ((tmpi = Dup(wrpip[0])) < 0) {
|
||||||
|
Error2("dup(%d): %s", wrpip[0], strerror(errno));
|
||||||
|
return STAT_RETRYLATER;
|
||||||
|
}
|
||||||
|
/*0 Info2("dup(%d) -> %d", wrpip[0], tmpi);*/
|
||||||
|
rdpip[1] = tmpi;
|
||||||
|
}
|
||||||
|
if (fdo == wrpip[0]) { /* a conflict here */
|
||||||
|
if ((tmpo = Dup(rdpip[1])) < 0) {
|
||||||
|
Error2("dup(%d): %s", rdpip[1], strerror(errno));
|
||||||
|
return STAT_RETRYLATER;
|
||||||
|
}
|
||||||
|
/*0 Info2("dup(%d) -> %d", rdpip[1], tmpo);*/
|
||||||
|
wrpip[0] = tmpo;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rw != XIO_WRONLY && rdpip[1] != fdo) {
|
||||||
|
if (Dup2(rdpip[1], fdo) < 0) {
|
||||||
|
Error3("dup2(%d, %d): %s", rdpip[1], fdo, strerror(errno));
|
||||||
|
return STAT_RETRYLATER;
|
||||||
|
}
|
||||||
|
Close(rdpip[1]);
|
||||||
|
/*0 Info2("dup2(%d, %d)", rdpip[1], fdo);*/
|
||||||
|
/*0 applyopts_cloexec(fdo, *copts);*/
|
||||||
|
}
|
||||||
|
if (rw != XIO_RDONLY && wrpip[0] != fdi) {
|
||||||
|
if (Dup2(wrpip[0], fdi) < 0) {
|
||||||
|
Error3("dup2(%d, %d): %s", wrpip[0], fdi, strerror(errno));
|
||||||
|
return STAT_RETRYLATER;
|
||||||
|
}
|
||||||
|
Close(wrpip[0]);
|
||||||
|
/*0 Info2("dup2(%d, %d)", wrpip[0], fdi);*/
|
||||||
|
/*0 applyopts_cloexec(wrpip[0], *copts);*/ /* option is already consumed! */
|
||||||
|
/* applyopts_cloexec(fdi, *copts);*/ /* option is already consumed! */
|
||||||
|
}
|
||||||
|
|
||||||
|
applyopts(fdi, *copts, PH_LATE);
|
||||||
|
applyopts(fdo, *copts, PH_LATE);
|
||||||
|
applyopts(fdi, *copts, PH_LATE2);
|
||||||
|
applyopts(fdo, *copts, PH_LATE2);
|
||||||
|
|
||||||
|
} else { /* socketpair */
|
||||||
|
if (rw != XIO_RDONLY && fdi != sv[1]) {
|
||||||
|
if (Dup2(sv[1], fdi) < 0) {
|
||||||
|
Error3("dup2(%d, %d): %s", sv[1], fdi, strerror(errno));
|
||||||
|
return STAT_RETRYLATER; }
|
||||||
|
/*0 Info2("dup2(%d, %d)", sv[1], fdi);*/
|
||||||
|
}
|
||||||
|
if (rw != XIO_WRONLY && fdo != sv[1]) {
|
||||||
|
if (Dup2(sv[1], fdo) < 0) {
|
||||||
|
Error3("dup2(%d, %d): %s", sv[1], fdo, strerror(errno));
|
||||||
|
return STAT_RETRYLATER; }
|
||||||
|
/*0 Info2("dup2(%d, %d)", sv[1], fdo);*/
|
||||||
|
}
|
||||||
|
if (fdi != sv[1] && fdo != sv[1]) {
|
||||||
|
applyopts_cloexec(sv[1], *copts);
|
||||||
|
}
|
||||||
|
|
||||||
|
applyopts(fdi, *copts, PH_LATE);
|
||||||
|
applyopts(fdi, *copts, PH_LATE2);
|
||||||
|
}
|
||||||
|
} /* withfork */
|
||||||
|
else {
|
||||||
|
applyopts(-1, *copts, PH_LATE);
|
||||||
|
applyopts(-1, *copts, PH_LATE2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* what to do with stderr? */
|
||||||
|
if (withstderr) {
|
||||||
|
/* handle it just like ordinary process output, i.e. copy output fd */
|
||||||
|
if (!withfork) {
|
||||||
|
if (Dup2(fdo, 2) < 0) {
|
||||||
|
Error2("dup2(%d, 2): %s", fdo, strerror(errno));
|
||||||
|
}
|
||||||
|
/*0 Info1("dup2(%d, 2)", fdo);*/
|
||||||
|
} else
|
||||||
|
#if HAVE_PTY
|
||||||
|
if (usepty) {
|
||||||
|
if (Dup2(ttyfd, 2) < 0) {
|
||||||
|
Error2("dup2(%d, 2): %s", ttyfd, strerror(errno));
|
||||||
|
}
|
||||||
|
/*0 Info1("dup2(%d, 2)", ttyfd);*/
|
||||||
|
} else
|
||||||
|
#endif /* HAVE_PTY */
|
||||||
|
if (usepipes) {
|
||||||
|
if (Dup2(/*rdpip[1]*/ fdo, 2) < 0) {
|
||||||
|
Error2("dup2(%d, 2): %s", /*rdpip[1]*/ fdo, strerror(errno));
|
||||||
|
}
|
||||||
|
/*0 Info1("dup2(%d, 2)", rdpip[1]);*/
|
||||||
|
} else {
|
||||||
|
if (Dup2(sv[1], 2) < 0) {
|
||||||
|
Error2("dup2(%d, 2): %s", sv[1], strerror(errno));
|
||||||
|
}
|
||||||
|
/*0 Info1("dup2(%d, 2)", sv[1]);*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_xioopen_setdelayeduser();
|
||||||
|
/* set group before user - maybe you are not permitted afterwards */
|
||||||
|
if (retropt_gidt(*copts, OPT_SETGID, &group) >= 0) {
|
||||||
|
Setgid(group);
|
||||||
|
}
|
||||||
|
if (retropt_uidt(*copts, OPT_SETUID, &user) >= 0) {
|
||||||
|
Setuid(user);
|
||||||
|
}
|
||||||
|
return 0; /* indicate child process */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* for parent (this is our socat process) */
|
||||||
|
Notice1("forked off child process "F_pid, pid);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if ((popts = copyopts(*copts,
|
||||||
|
GROUP_FD|GROUP_TERMIOS|GROUP_FORK|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_FIFO)) == NULL)
|
||||||
|
return STAT_RETRYLATER;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (0) {
|
||||||
|
; /* for canonical reasons */
|
||||||
|
#if HAVE_PTY
|
||||||
|
} else if (usepty) {
|
||||||
|
if (Close(ttyfd) < 0) {
|
||||||
|
Info2("close(%d): %s", ttyfd, strerror(errno));
|
||||||
|
}
|
||||||
|
#endif /* HAVE_PTY */
|
||||||
|
#if 1
|
||||||
|
} else if (usepipes) {
|
||||||
|
Close(wrpip[0]);
|
||||||
|
Close(rdpip[1]);
|
||||||
|
} else { /* socketpair() */
|
||||||
|
Close(sv[1]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
fd->child.pid = pid;
|
||||||
|
|
||||||
|
if (applyopts_single(fd, popts, PH_LATE) < 0) return -1;
|
||||||
|
applyopts_signal(fd, popts);
|
||||||
|
if ((numleft = leftopts(popts)) > 0) {
|
||||||
|
Error1("%d option(s) could not be used", numleft);
|
||||||
|
showleft(popts);
|
||||||
|
return STAT_NORETRY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pid; /* indicate parent (main) process */
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* WITH_EXEC || WITH_SYSTEM */
|
#endif /* WITH_EXEC || WITH_SYSTEM */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* $Id: xio-progcall.h,v 1.13 2006/02/08 19:37:15 gerhard Exp $ */
|
/* $Id: xio-progcall.h,v 1.13 2006/02/08 19:37:15 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2001-2006 */
|
/* Copyright Gerhard Rieger 2001-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
#ifndef __xio_progcall_h_included
|
#ifndef __xio_progcall_h_included
|
||||||
|
@ -18,7 +18,12 @@ extern const struct optdesc opt_sighup;
|
||||||
extern const struct optdesc opt_sigint;
|
extern const struct optdesc opt_sigint;
|
||||||
extern const struct optdesc opt_sigquit;
|
extern const struct optdesc opt_sigquit;
|
||||||
|
|
||||||
extern int _xioopen_foxec(int rw, /* O_RDONLY etc. */
|
extern int _xioopen_foxec_int(int rw, /* O_RDONLY etc. */
|
||||||
|
struct single *fd,
|
||||||
|
unsigned groups,
|
||||||
|
struct opt **opts
|
||||||
|
);
|
||||||
|
extern int _xioopen_foxec_end(int rw, /* O_RDONLY etc. */
|
||||||
struct single *fd,
|
struct single *fd,
|
||||||
unsigned groups,
|
unsigned groups,
|
||||||
struct opt **opts
|
struct opt **opts
|
||||||
|
|
135
xio-proxy.c
135
xio-proxy.c
|
@ -1,5 +1,5 @@
|
||||||
/* $Id: xio-proxy.c,v 1.28 2006/12/28 14:02:54 gerhard Exp $ */
|
/* $Id: xio-proxy.c,v 1.28 2006/12/28 14:02:54 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2002-2006 */
|
/* Copyright Gerhard Rieger 2002-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
/* this file contains the source for opening addresses of HTTP proxy CONNECT
|
/* this file contains the source for opening addresses of HTTP proxy CONNECT
|
||||||
|
@ -19,8 +19,12 @@
|
||||||
|
|
||||||
#define PROXYPORT "8080"
|
#define PROXYPORT "8080"
|
||||||
|
|
||||||
static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
|
static int xioopen_proxy_connect2(int argc, const char *argv[], struct opt *opts,
|
||||||
int xioflags, xiofile_t *fd,
|
int xioflags, xiofile_t *xxfd,
|
||||||
|
unsigned groups, int dummy1, int dummy2,
|
||||||
|
int dummy3);
|
||||||
|
static int xioopen_proxy_connect3(int argc, const char *argv[], struct opt *opts,
|
||||||
|
int xioflags, xiofile_t *xxfd,
|
||||||
unsigned groups, int dummy1, int dummy2,
|
unsigned groups, int dummy1, int dummy2,
|
||||||
int dummy3);
|
int dummy3);
|
||||||
|
|
||||||
|
@ -29,8 +33,15 @@ const struct optdesc opt_ignorecr = { "ignorecr", NULL, OPT_IGNORECR, GROUP_H
|
||||||
const struct optdesc opt_proxy_resolve = { "proxy-resolve", "resolve", OPT_PROXY_RESOLVE, GROUP_HTTP, PH_LATE, TYPE_BOOL, OFUNC_SPEC };
|
const struct optdesc opt_proxy_resolve = { "proxy-resolve", "resolve", OPT_PROXY_RESOLVE, GROUP_HTTP, PH_LATE, TYPE_BOOL, OFUNC_SPEC };
|
||||||
const struct optdesc opt_proxy_authorization = { "proxy-authorization", "proxyauth", OPT_PROXY_AUTHORIZATION, GROUP_HTTP, PH_LATE, TYPE_STRING, OFUNC_SPEC };
|
const struct optdesc opt_proxy_authorization = { "proxy-authorization", "proxyauth", OPT_PROXY_AUTHORIZATION, GROUP_HTTP, PH_LATE, TYPE_STRING, OFUNC_SPEC };
|
||||||
|
|
||||||
const struct addrdesc addr_proxy_connect = { "proxy", 3, xioopen_proxy_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_HTTP|GROUP_CHILD|GROUP_RETRY, 0, 0, 0 HELP(":<proxy-server>:<host>:<port>") };
|
static const struct xioaddr_inter_desc xioaddr_proxy_connect2 = { XIOADDR_INTER, "proxy", 2, XIOBIT_ALL, GROUP_HTTP|GROUP_CHILD|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_proxy_connect2, 0, 0, 0, XIOBIT_RDWR HELP(":<host>:<port>") };
|
||||||
|
|
||||||
|
static const struct xioaddr_endpoint_desc xioaddr_proxy_connect3 = { XIOADDR_ENDPOINT, "proxy", 3, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_HTTP|GROUP_CHILD|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_proxy_connect3, 0, 0, 0 HELP(":<proxy-server>:<host>:<port>") };
|
||||||
|
|
||||||
|
const union xioaddr_desc *xioaddrs_proxy_connect[] = {
|
||||||
|
(union xioaddr_desc *)&xioaddr_proxy_connect2,
|
||||||
|
(union xioaddr_desc *)&xioaddr_proxy_connect3,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
/*0#define CONNLEN 40*/ /* "CONNECT 123.156.189.123:65432 HTTP/1.0\r\n\0" */
|
/*0#define CONNLEN 40*/ /* "CONNECT 123.156.189.123:65432 HTTP/1.0\r\n\0" */
|
||||||
#define CONNLEN 281 /* "CONNECT <255bytes>:65432 HTTP/1.0\r\n\0" */
|
#define CONNLEN 281 /* "CONNECT <255bytes>:65432 HTTP/1.0\r\n\0" */
|
||||||
|
@ -57,12 +68,12 @@ static ssize_t
|
||||||
xioproxy_recvbytes(struct single *xfd, char *buff, size_t buflen, int level) {
|
xioproxy_recvbytes(struct single *xfd, char *buff, size_t buflen, int level) {
|
||||||
ssize_t result;
|
ssize_t result;
|
||||||
do {
|
do {
|
||||||
/* we need at least buflen bytes... */
|
/* we need at least 16 bytes... */
|
||||||
result = Read(xfd->fd, buff, buflen);
|
result = Read(xfd->fd1, buff, buflen);
|
||||||
} while (result < 0 && errno == EINTR); /*! EAGAIN? */
|
} while (result < 0 && errno == EINTR); /*! EAGAIN? */
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
Msg4(level, "read(%d, %p, "F_Zu"): %s",
|
Msg4(level, "read(%d, %p, "F_Zu"): %s",
|
||||||
xfd->fd, buff, buflen, strerror(errno));
|
xfd->fd1, buff, buflen, strerror(errno));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
|
@ -75,46 +86,105 @@ static ssize_t
|
||||||
#define BUFLEN 2048
|
#define BUFLEN 2048
|
||||||
|
|
||||||
|
|
||||||
static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
|
static int xioopen_proxy_connect2(int argc, const char *argv[], struct opt *opts,
|
||||||
|
int xioflags, xiofile_t *xxfd,
|
||||||
|
unsigned groups, int dummy1, int dummy2,
|
||||||
|
int dummy3) {
|
||||||
|
struct single *xfd = &xxfd->stream;
|
||||||
|
struct proxyvars struct_proxyvars = { 0 }, *proxyvars = &struct_proxyvars;
|
||||||
|
const char *targetname, *targetport;
|
||||||
|
/* variables to be filled with address option values */
|
||||||
|
bool dofork = false;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (xfd->fd1 < 0) {
|
||||||
|
Error("xioopen_proxy_connect(): proxyname missing");
|
||||||
|
return STAT_NORETRY;
|
||||||
|
}
|
||||||
|
targetname = argv[1];
|
||||||
|
targetport = argv[2];
|
||||||
|
|
||||||
|
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||||
|
applyopts(-1, opts, PH_INIT);
|
||||||
|
|
||||||
|
retropt_bool(opts, OPT_FORK, &dofork);
|
||||||
|
if (dofork && !(xioflags & XIO_MAYFORK)) {
|
||||||
|
Error("fork option not allowed by application");
|
||||||
|
}
|
||||||
|
|
||||||
|
result = _xioopen_proxy_prepare(proxyvars, opts, targetname, targetport);
|
||||||
|
if (result != STAT_OK) return result;
|
||||||
|
|
||||||
|
Notice2("opening connection to %s:%u using proxy CONNECT",
|
||||||
|
proxyvars->targetaddr, proxyvars->targetport);
|
||||||
|
|
||||||
|
xfd->dtype = XIODATA_STREAM;
|
||||||
|
xfd->fdtype = FDTYPE_DOUBLE;
|
||||||
|
|
||||||
|
applyopts(xfd->fd1, opts, PH_ALL);
|
||||||
|
/*!*/
|
||||||
|
|
||||||
|
if ((result = _xio_openlate(xfd, opts)) < 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
result = _xioopen_proxy_connect(xfd, proxyvars, E_ERROR);
|
||||||
|
switch (result) {
|
||||||
|
case STAT_OK: break;
|
||||||
|
default:
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Notice2("successfully connected to %s:%u via proxy",
|
||||||
|
proxyvars->targetaddr, proxyvars->targetport);
|
||||||
|
return STAT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int xioopen_proxy_connect3(int argc, const char *argv[], struct opt *opts,
|
||||||
int xioflags, xiofile_t *xxfd,
|
int xioflags, xiofile_t *xxfd,
|
||||||
unsigned groups, int dummy1, int dummy2,
|
unsigned groups, int dummy1, int dummy2,
|
||||||
int dummy3) {
|
int dummy3) {
|
||||||
/* we expect the form: host:host:port */
|
/* we expect the form: host:host:port */
|
||||||
struct single *xfd = &xxfd->stream;
|
struct single *xfd = &xxfd->stream;
|
||||||
struct opt *opts0 = NULL;
|
|
||||||
struct proxyvars struct_proxyvars = { 0 }, *proxyvars = &struct_proxyvars;
|
struct proxyvars struct_proxyvars = { 0 }, *proxyvars = &struct_proxyvars;
|
||||||
|
const char *proxyname;
|
||||||
|
char *proxyport = NULL;
|
||||||
|
const char *targetname, *targetport;
|
||||||
/* variables to be filled with address option values */
|
/* variables to be filled with address option values */
|
||||||
bool dofork = false;
|
bool dofork = false;
|
||||||
|
int socktype = SOCK_STREAM;
|
||||||
|
struct opt *opts0 = NULL;
|
||||||
/* */
|
/* */
|
||||||
int pf = PF_UNSPEC;
|
int pf = PF_UNSPEC;
|
||||||
union sockaddr_union us_sa, *us = &us_sa;
|
union sockaddr_union us_sa, *us = &us_sa;
|
||||||
union sockaddr_union them_sa, *them = &them_sa;
|
union sockaddr_union them_sa, *them = &them_sa;
|
||||||
socklen_t uslen = sizeof(us_sa);
|
socklen_t uslen = sizeof(us_sa);
|
||||||
socklen_t themlen = sizeof(them_sa);
|
socklen_t themlen = sizeof(them_sa);
|
||||||
const char *proxyname; char *proxyport = NULL;
|
|
||||||
const char *targetname, *targetport;
|
|
||||||
int ipproto = IPPROTO_TCP;
|
int ipproto = IPPROTO_TCP;
|
||||||
bool needbind = false;
|
bool needbind = false;
|
||||||
bool lowport = false;
|
bool lowport = false;
|
||||||
int socktype = SOCK_STREAM;
|
|
||||||
int level;
|
int level;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if (argc != 4) {
|
if (xfd->fd1 >= 0) {
|
||||||
Error1("%s: 3 parameters required", argv[0]);
|
Error("xioopen_proxy_connect(): proxyname not allowed here");
|
||||||
return STAT_NORETRY;
|
return STAT_NORETRY;
|
||||||
}
|
}
|
||||||
proxyname = argv[1];
|
proxyname = argv[1];
|
||||||
targetname = argv[2];
|
targetname = argv[2];
|
||||||
targetport = argv[3];
|
targetport = argv[3];
|
||||||
|
|
||||||
xfd->howtoend = END_SHUTDOWN;
|
xfd->howtoshut = XIOSHUT_DOWN;
|
||||||
|
xfd->howtoclose = XIOCLOSE_CLOSE;
|
||||||
|
|
||||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||||
applyopts(-1, opts, PH_INIT);
|
applyopts(-1, opts, PH_INIT);
|
||||||
|
|
||||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||||
|
|
||||||
retropt_bool(opts, OPT_FORK, &dofork);
|
retropt_bool(opts, OPT_FORK, &dofork);
|
||||||
|
if (dofork && !(xioflags & XIO_MAYFORK)) {
|
||||||
|
Error("fork option not allowed by application");
|
||||||
|
}
|
||||||
|
|
||||||
if (retropt_string(opts, OPT_PROXYPORT, &proxyport) < 0) {
|
if (retropt_string(opts, OPT_PROXYPORT, &proxyport) < 0) {
|
||||||
if ((proxyport = strdup(PROXYPORT)) == NULL) {
|
if ((proxyport = strdup(PROXYPORT)) == NULL) {
|
||||||
|
@ -133,7 +203,6 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
|
||||||
them, &themlen, us, &uslen,
|
them, &themlen, us, &uslen,
|
||||||
&needbind, &lowport, &socktype);
|
&needbind, &lowport, &socktype);
|
||||||
if (result != STAT_OK) return result;
|
if (result != STAT_OK) return result;
|
||||||
|
|
||||||
Notice4("opening connection to %s:%u via proxy %s:%s",
|
Notice4("opening connection to %s:%u via proxy %s:%s",
|
||||||
proxyvars->targetaddr, proxyvars->targetport, proxyname, proxyport);
|
proxyvars->targetaddr, proxyvars->targetport, proxyname, proxyport);
|
||||||
|
|
||||||
|
@ -164,8 +233,9 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
|
||||||
default:
|
default:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
xfd->fdtype = FDTYPE_SINGLE;
|
||||||
applyopts(xfd->fd, opts, PH_ALL);
|
applyopts(xfd->fd1, opts, PH_ALL);
|
||||||
|
/*!*/
|
||||||
|
|
||||||
if ((result = _xio_openlate(xfd, opts)) < 0)
|
if ((result = _xio_openlate(xfd, opts)) < 0)
|
||||||
return result;
|
return result;
|
||||||
|
@ -212,7 +282,8 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
|
||||||
}
|
}
|
||||||
/* parent process */
|
/* parent process */
|
||||||
Notice1("forked off child process "F_pid, pid);
|
Notice1("forked off child process "F_pid, pid);
|
||||||
Close(xfd->fd);
|
Close(xfd->fd1);
|
||||||
|
Close(xfd->fd2);
|
||||||
Nanosleep(&xfd->intervall, NULL);
|
Nanosleep(&xfd->intervall, NULL);
|
||||||
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
|
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
|
||||||
continue;
|
continue;
|
||||||
|
@ -224,9 +295,8 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
|
||||||
|
|
||||||
} while (true); /* end of complete open loop - drop out on success */
|
} while (true); /* end of complete open loop - drop out on success */
|
||||||
|
|
||||||
Notice4("successfully connected to %s:%u via proxy %s:%s",
|
Notice2("successfully connected to %s:%u via proxy",
|
||||||
proxyvars->targetaddr, proxyvars->targetport,
|
proxyvars->targetaddr, proxyvars->targetport);
|
||||||
proxyname, proxyport);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -275,6 +345,7 @@ int _xioopen_proxy_prepare(struct proxyvars *proxyvars, struct opt *opts,
|
||||||
int _xioopen_proxy_connect(struct single *xfd,
|
int _xioopen_proxy_connect(struct single *xfd,
|
||||||
struct proxyvars *proxyvars,
|
struct proxyvars *proxyvars,
|
||||||
int level) {
|
int level) {
|
||||||
|
int wfd;
|
||||||
size_t offset;
|
size_t offset;
|
||||||
char request[CONNLEN];
|
char request[CONNLEN];
|
||||||
char buff[BUFLEN+1];
|
char buff[BUFLEN+1];
|
||||||
|
@ -286,6 +357,8 @@ int _xioopen_proxy_connect(struct single *xfd,
|
||||||
int state;
|
int state;
|
||||||
ssize_t sresult;
|
ssize_t sresult;
|
||||||
|
|
||||||
|
wfd = (xfd->fdtype == FDTYPE_SINGLE ? xfd->fd1 : xfd->fd2);
|
||||||
|
|
||||||
/* generate proxy request header - points to final target */
|
/* generate proxy request header - points to final target */
|
||||||
sprintf(request, "CONNECT %s:%u HTTP/1.0\r\n",
|
sprintf(request, "CONNECT %s:%u HTTP/1.0\r\n",
|
||||||
proxyvars->targetaddr, proxyvars->targetport);
|
proxyvars->targetaddr, proxyvars->targetport);
|
||||||
|
@ -295,13 +368,13 @@ int _xioopen_proxy_connect(struct single *xfd,
|
||||||
Info1("sending \"%s\"", textbuff);
|
Info1("sending \"%s\"", textbuff);
|
||||||
/* write errors are assumed to always be hard errors, no retry */
|
/* write errors are assumed to always be hard errors, no retry */
|
||||||
do {
|
do {
|
||||||
sresult = Write(xfd->fd, request, strlen(request));
|
sresult = Write(wfd, request, strlen(request));
|
||||||
} while (sresult < 0 && errno == EINTR);
|
} while (sresult < 0 && errno == EINTR);
|
||||||
if (sresult < 0) {
|
if (sresult < 0) {
|
||||||
Msg4(level, "write(%d, %p, "F_Zu"): %s",
|
Msg4(level, "write(%d, %p, "F_Zu"): %s",
|
||||||
xfd->fd, request, strlen(request), strerror(errno));
|
wfd, request, strlen(request), strerror(errno));
|
||||||
if (Close(xfd->fd) < 0) {
|
if (Close(wfd) < 0) {
|
||||||
Info2("close(%d): %s", xfd->fd, strerror(errno));
|
Info2("close(%d): %s", xfd->fd2, strerror(errno));
|
||||||
}
|
}
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
@ -328,13 +401,13 @@ int _xioopen_proxy_connect(struct single *xfd,
|
||||||
Info1("sending \"%s\\r\\n\"", header);
|
Info1("sending \"%s\\r\\n\"", header);
|
||||||
*next++ = '\r'; *next++ = '\n'; *next++ = '\0';
|
*next++ = '\r'; *next++ = '\n'; *next++ = '\0';
|
||||||
do {
|
do {
|
||||||
sresult = Write(xfd->fd, header, strlen(header));
|
sresult = Write(wfd, header, strlen(header));
|
||||||
} while (sresult < 0 && errno == EINTR);
|
} while (sresult < 0 && errno == EINTR);
|
||||||
if (sresult < 0) {
|
if (sresult < 0) {
|
||||||
Msg4(level, "write(%d, %p, "F_Zu"): %s",
|
Msg4(level, "write(%d, %p, "F_Zu"): %s",
|
||||||
xfd->fd, header, strlen(header), strerror(errno));
|
xfd->fd2, header, strlen(header), strerror(errno));
|
||||||
if (Close(xfd->fd) < 0) {
|
if (Close(wfd/*!*/) < 0) {
|
||||||
Info2("close(%d): %s", xfd->fd, strerror(errno));
|
Info2("close(%d): %s", xfd->fd2, strerror(errno));
|
||||||
}
|
}
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
@ -344,7 +417,7 @@ int _xioopen_proxy_connect(struct single *xfd,
|
||||||
|
|
||||||
Info("sending \"\\r\\n\"");
|
Info("sending \"\\r\\n\"");
|
||||||
do {
|
do {
|
||||||
sresult = Write(xfd->fd, "\r\n", 2);
|
sresult = Write(wfd, "\r\n", 2);
|
||||||
} while (sresult < 0 && errno == EINTR);
|
} while (sresult < 0 && errno == EINTR);
|
||||||
/*! */
|
/*! */
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* $Id: xio-proxy.h,v 1.6 2006/05/31 19:17:57 gerhard Exp $ */
|
/* $Id: xio-proxy.h,v 1.6.2.1 2006/07/24 19:18:10 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2002-2006 */
|
/* Copyright Gerhard Rieger 2002-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
#ifndef __xio_proxy_h_included
|
#ifndef __xio_proxy_h_included
|
||||||
|
@ -19,7 +19,7 @@ extern const struct optdesc opt_ignorecr;
|
||||||
extern const struct optdesc opt_proxy_resolve;
|
extern const struct optdesc opt_proxy_resolve;
|
||||||
extern const struct optdesc opt_proxy_authorization;
|
extern const struct optdesc opt_proxy_authorization;
|
||||||
|
|
||||||
extern const struct addrdesc addr_proxy_connect;
|
extern const union xioaddr_desc *xioaddrs_proxy_connect[];
|
||||||
|
|
||||||
int _xioopen_proxy_prepare(struct proxyvars *proxyvars, struct opt *opts,
|
int _xioopen_proxy_prepare(struct proxyvars *proxyvars, struct opt *opts,
|
||||||
const char *targetname, const char *targetport);
|
const char *targetname, const char *targetport);
|
||||||
|
|
33
xio-pty.c
33
xio-pty.c
|
@ -18,9 +18,18 @@
|
||||||
|
|
||||||
#define MAXPTYNAMELEN 64
|
#define MAXPTYNAMELEN 64
|
||||||
|
|
||||||
static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3);
|
static int xioopen_pty(const char *linkname, struct opt *opts, int xioflags, xiofile_t *xfd, unsigned groups);
|
||||||
|
static int xioopen_pty0(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3);
|
||||||
|
static int xioopen_pty1(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3);
|
||||||
|
|
||||||
const struct addrdesc addr_pty = { "pty", 3, xioopen_pty, GROUP_NAMED|GROUP_FD|GROUP_TERMIOS|GROUP_PTY, 0, 0, 0 HELP("") };
|
static const struct xioaddr_endpoint_desc xioendpoint_pty0 = { XIOADDR_SYS, "pty", 0, XIOBIT_ALL, GROUP_NAMED|GROUP_FD|GROUP_TERMIOS|GROUP_PTY, XIOSHUT_NONE, XIOCLOSE_CLOSE, xioopen_pty0, 0, 0, 0 HELP("") };
|
||||||
|
static const struct xioaddr_endpoint_desc xioendpoint_pty1 = { XIOADDR_SYS, "pty", 1, XIOBIT_ALL, GROUP_NAMED|GROUP_FD|GROUP_TERMIOS|GROUP_PTY, XIOSHUT_NONE, XIOCLOSE_CLOSE, xioopen_pty1, 0, 0, 0 HELP(":<symlink>") };
|
||||||
|
|
||||||
|
const union xioaddr_desc* xioaddrs_pty[] = {
|
||||||
|
(union xioaddr_desc *)&xioendpoint_pty0,
|
||||||
|
(union xioaddr_desc *)&xioendpoint_pty1,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
const struct optdesc opt_symbolic_link = { "symbolic-link", "link", OPT_SYMBOLIC_LINK, GROUP_PTY, PH_LATE, TYPE_FILENAME, OFUNC_SPEC, 0, 0 };
|
const struct optdesc opt_symbolic_link = { "symbolic-link", "link", OPT_SYMBOLIC_LINK, GROUP_PTY, PH_LATE, TYPE_FILENAME, OFUNC_SPEC, 0, 0 };
|
||||||
#if HAVE_POLL
|
#if HAVE_POLL
|
||||||
|
@ -28,7 +37,17 @@ const struct optdesc opt_pty_wait_slave = { "pty-wait-slave", "wait-slave", OPT_
|
||||||
const struct optdesc opt_pty_intervall = { "pty-intervall", NULL, OPT_PTY_INTERVALL, GROUP_PTY, PH_EARLY, TYPE_TIMESPEC, OFUNC_SPEC, 0, 0 };
|
const struct optdesc opt_pty_intervall = { "pty-intervall", NULL, OPT_PTY_INTERVALL, GROUP_PTY, PH_EARLY, TYPE_TIMESPEC, OFUNC_SPEC, 0, 0 };
|
||||||
#endif /* HAVE_POLL */
|
#endif /* HAVE_POLL */
|
||||||
|
|
||||||
static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, unsigned groups, int dummy1, int dummy2, int dummy3) {
|
static int xioopen_pty0(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, unsigned groups, int dummy1, int dummy2, int dummy3) {
|
||||||
|
char *linkname = NULL;
|
||||||
|
retropt_string(opts, OPT_SYMBOLIC_LINK, &linkname);
|
||||||
|
return xioopen_pty(linkname, opts, xioflags, xfd, groups);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int xioopen_pty1(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, unsigned groups, int dummy1, int dummy2, int dummy3) {
|
||||||
|
return xioopen_pty(argv[1], opts, xioflags, xfd, groups);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int xioopen_pty(const char *linkname, struct opt *opts, int xioflags, xiofile_t *xfd, unsigned groups) {
|
||||||
/* we expect the form: filename */
|
/* we expect the form: filename */
|
||||||
int ptyfd = -1, ttyfd = -1;
|
int ptyfd = -1, ttyfd = -1;
|
||||||
#if defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC)
|
#if defined(HAVE_DEV_PTMX) || defined(HAVE_DEV_PTC)
|
||||||
|
@ -39,7 +58,6 @@ static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xiofl
|
||||||
#endif /* HAVE_OPENPTY */
|
#endif /* HAVE_OPENPTY */
|
||||||
char ptyname[MAXPTYNAMELEN];
|
char ptyname[MAXPTYNAMELEN];
|
||||||
char *tn = NULL;
|
char *tn = NULL;
|
||||||
char *linkname = NULL;
|
|
||||||
bool opt_unlink_close = true; /* remove symlink afterwards */
|
bool opt_unlink_close = true; /* remove symlink afterwards */
|
||||||
bool wait_slave = false; /* true would be better for many platforms, but
|
bool wait_slave = false; /* true would be better for many platforms, but
|
||||||
some OSes cannot handle this, and for common
|
some OSes cannot handle this, and for common
|
||||||
|
@ -47,8 +65,6 @@ static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xiofl
|
||||||
compatibility we choose "no" as default */
|
compatibility we choose "no" as default */
|
||||||
struct timespec pollintv = { PTY_INTERVALL };
|
struct timespec pollintv = { PTY_INTERVALL };
|
||||||
|
|
||||||
xfd->stream.howtoend = END_CLOSE;
|
|
||||||
|
|
||||||
applyopts(-1, opts, PH_INIT);
|
applyopts(-1, opts, PH_INIT);
|
||||||
if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1;
|
if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1;
|
||||||
|
|
||||||
|
@ -142,7 +158,7 @@ static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xiofl
|
||||||
}
|
}
|
||||||
#endif /* HAVE_OPENPTY */
|
#endif /* HAVE_OPENPTY */
|
||||||
|
|
||||||
if (!retropt_string(opts, OPT_SYMBOLIC_LINK, &linkname)) {
|
if (linkname) {
|
||||||
if (Unlink(linkname) < 0 && errno != ENOENT) {
|
if (Unlink(linkname) < 0 && errno != ENOENT) {
|
||||||
Error2("unlink(\"%s\"): %s", linkname, strerror(errno));
|
Error2("unlink(\"%s\"): %s", linkname, strerror(errno));
|
||||||
}
|
}
|
||||||
|
@ -163,10 +179,11 @@ static int xioopen_pty(int argc, const char *argv[], struct opt *opts, int xiofl
|
||||||
|
|
||||||
applyopts_cloexec(ptyfd, opts);/*!*/
|
applyopts_cloexec(ptyfd, opts);/*!*/
|
||||||
xfd->stream.dtype = XIODATA_PTY;
|
xfd->stream.dtype = XIODATA_PTY;
|
||||||
|
xfd->stream.fdtype = FDTYPE_SINGLE;
|
||||||
|
|
||||||
applyopts(ptyfd, opts, PH_FD);
|
applyopts(ptyfd, opts, PH_FD);
|
||||||
|
|
||||||
xfd->stream.fd = ptyfd;
|
xfd->stream.fd1 = ptyfd;
|
||||||
applyopts(ptyfd, opts, PH_LATE);
|
applyopts(ptyfd, opts, PH_LATE);
|
||||||
if (applyopts_single(&xfd->stream, opts, PH_LATE) < 0) return -1;
|
if (applyopts_single(&xfd->stream, opts, PH_LATE) < 0) return -1;
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
/* $Id: xio-pty.h,v 1.2 2004/10/24 13:49:53 gerhard Exp $ */
|
/* $Id: xio-pty.h,v 1.2.2.1 2006/07/24 19:18:15 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2002-2004 */
|
/* Copyright Gerhard Rieger 2002-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
#ifndef __xio_pty_h_included
|
#ifndef __xio_pty_h_included
|
||||||
#define __xio_pty_h_included 1
|
#define __xio_pty_h_included 1
|
||||||
|
|
||||||
extern const struct addrdesc addr_pty;
|
extern const union xioaddr_desc* xioaddrs_pty[];
|
||||||
|
|
||||||
extern const struct optdesc opt_symbolic_link;
|
extern const struct optdesc opt_symbolic_link;
|
||||||
#if HAVE_POLL
|
#if HAVE_POLL
|
||||||
|
|
49
xio-rawip.c
49
xio-rawip.c
|
@ -34,31 +34,41 @@ static
|
||||||
int xioopen_rawip_recv(int argc, const char *argv[], struct opt *opts,
|
int xioopen_rawip_recv(int argc, const char *argv[], struct opt *opts,
|
||||||
int xioflags, xiofile_t *xfd, unsigned groups,
|
int xioflags, xiofile_t *xfd, unsigned groups,
|
||||||
int pf, int socktype, int ipproto);
|
int pf, int socktype, int ipproto);
|
||||||
|
|
||||||
static
|
static
|
||||||
int _xioopen_rawip_sendto(const char *hostname, const char *protname,
|
int _xioopen_rawip_sendto(const char *hostname, const char *protname,
|
||||||
struct opt *opts, int xioflags,
|
struct opt *opts, int xioflags,
|
||||||
xiofile_t *xxfd, unsigned groups, int pf);
|
xiofile_t *xxfd, unsigned groups, int pf);
|
||||||
|
|
||||||
const struct addrdesc addr_rawip_sendto = { "ip-sendto", 3, xioopen_rawip_sendto, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6, PF_UNSPEC, 0, 0 HELP(":<host>:<protocol>") };
|
static const struct xioaddr_endpoint_desc xioaddr_rawip_sendto2 = { XIOADDR_SYS, "ip-sendto", 2, XIOBIT_WRONLY|XIOBIT_RDWR, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6, XIOSHUT_DOWN, XIOCLOSE_NONE, xioopen_rawip_sendto, PF_UNSPEC, 0, 0 HELP(":<host>:<protocol>") };
|
||||||
const struct addrdesc addr_rawip_datagram= { "ip-datagram", 3, xioopen_rawip_datagram, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_RANGE, PF_UNSPEC, 0, 0 HELP(":<host>:<protocol>") };
|
const union xioaddr_desc *xioaddrs_rawip_sendto[] = { (union xioaddr_desc *)&xioaddr_rawip_sendto2, NULL };
|
||||||
const struct addrdesc addr_rawip_recvfrom= { "ip-recvfrom", 3, xioopen_rawip_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_CHILD|GROUP_RANGE, PF_UNSPEC, SOCK_RAW, 0 HELP(":<protocol>") };
|
static const struct xioaddr_endpoint_desc xioaddr_rawip_datagram2= { XIOADDR_SYS, "ip-datagram", 2, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_RANGE, XIOSHUT_DOWN, XIOCLOSE_NONE, xioopen_rawip_datagram, PF_UNSPEC, 0, 0 HELP(":<host>:<protocol>") };
|
||||||
const struct addrdesc addr_rawip_recv = { "ip-recv", 1, xioopen_rawip_recv, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_RANGE, PF_UNSPEC, SOCK_RAW, 0 HELP(":<protocol>") };
|
const union xioaddr_desc *xioaddrs_rawip_datagram[] = { (union xioaddr_desc *)&xioaddr_rawip_datagram2, NULL };
|
||||||
|
static const struct xioaddr_endpoint_desc xioaddr_rawip_recvfrom1= { XIOADDR_SYS, "ip-recvfrom", 1, XIOBIT_RDONLY|XIOBIT_RDWR, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_CHILD|GROUP_RANGE, XIOSHUT_DOWN, XIOCLOSE_NONE, xioopen_rawip_recvfrom, PF_UNSPEC, SOCK_RAW, 0 HELP(":<protocol>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_rawip_recvfrom[] = { (union xioaddr_desc *)&xioaddr_rawip_recvfrom1, NULL };
|
||||||
|
static const struct xioaddr_endpoint_desc xioaddr_rawip_recv1 = { XIOADDR_SYS, "ip-recv", 1, XIOBIT_RDONLY, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_RANGE, XIOSHUT_DOWN, XIOCLOSE_NONE, xioopen_rawip_recv, PF_UNSPEC, SOCK_RAW, 0 HELP(":<protocol>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_rawip_recv[] = { (union xioaddr_desc *)&xioaddr_rawip_recv1, NULL };
|
||||||
|
|
||||||
#if WITH_IP4
|
#if WITH_IP4
|
||||||
const struct addrdesc addr_rawip4_sendto = { "ip4-sendto", 3, xioopen_rawip_sendto, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4, PF_INET, 0, 0 HELP(":<host>:<protocol>") };
|
static const struct xioaddr_endpoint_desc xioaddr_rawip4_sendto2 = { XIOADDR_SYS, "ip4-sendto", 2, XIOBIT_WRONLY|XIOBIT_RDWR, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4, XIOSHUT_DOWN, XIOCLOSE_NONE, xioopen_rawip_sendto, PF_INET, 0, 0 HELP(":<host>:<protocol>") };
|
||||||
const struct addrdesc addr_rawip4_datagram= { "ip4-datagram", 3, xioopen_rawip_datagram, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_RANGE, PF_INET, 0, 0 HELP(":<host>:<protocol>") };
|
const union xioaddr_desc *xioaddrs_rawip4_sendto[] = { (union xioaddr_desc *)&xioaddr_rawip4_sendto2, NULL };
|
||||||
const struct addrdesc addr_rawip4_recvfrom= { "ip4-recvfrom", 3, xioopen_rawip_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_CHILD|GROUP_RANGE, PF_INET, SOCK_RAW, 0 HELP(":<protocol>") };
|
static const struct xioaddr_endpoint_desc xioaddr_rawip4_datagram2= { XIOADDR_SYS, "ip4-datagram", 2, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_RANGE, XIOSHUT_DOWN, XIOCLOSE_NONE, xioopen_rawip_datagram, PF_INET, 0, 0 HELP(":<host>:<protocol>") };
|
||||||
const struct addrdesc addr_rawip4_recv = { "ip4-recv", 1, xioopen_rawip_recv, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_RANGE, PF_INET, SOCK_RAW, 0 HELP(":<protocol>") };
|
const union xioaddr_desc *xioaddrs_rawip4_datagram[] = { (union xioaddr_desc *)&xioaddr_rawip4_datagram2, NULL };
|
||||||
#endif
|
static const struct xioaddr_endpoint_desc xioaddr_rawip4_recvfrom1= { XIOADDR_SYS, "ip4-recvfrom", 1, XIOBIT_RDONLY|XIOBIT_RDWR, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_CHILD|GROUP_RANGE, XIOSHUT_DOWN, XIOCLOSE_NONE, xioopen_rawip_recvfrom, PF_INET, SOCK_RAW, 0 HELP(":<protocol>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_rawip4_recvfrom[] = { (union xioaddr_desc *)&xioaddr_rawip4_recvfrom1, NULL };
|
||||||
|
static const struct xioaddr_endpoint_desc xioaddr_rawip4_recv1 = { XIOADDR_SYS, "ip4-recv", 1, XIOBIT_RDONLY, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_RANGE, XIOSHUT_DOWN, XIOCLOSE_NONE, xioopen_rawip_recv, PF_INET, SOCK_RAW, 0 HELP(":<protocol>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_rawip4_recv[] = { (union xioaddr_desc *)&xioaddr_rawip4_recv1, NULL };
|
||||||
|
#endif /* IWITH_IP4 */
|
||||||
|
|
||||||
#if WITH_IP6
|
#if WITH_IP6
|
||||||
const struct addrdesc addr_rawip6_sendto = { "ip6-sendto", 3, xioopen_rawip_sendto, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6, PF_INET6, 0, 0 HELP(":<host>:<protocol>") };
|
static const struct xioaddr_endpoint_desc xioaddr_rawip6_sendto2 = { XIOADDR_SYS, "ip6-sendto", 2, XIOBIT_WRONLY|XIOBIT_RDWR, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6, XIOSHUT_DOWN, XIOCLOSE_NONE, xioopen_rawip_sendto, PF_INET6, 0, 0 HELP(":<host>:<protocol>") };
|
||||||
const struct addrdesc addr_rawip6_datagram= { "ip6-datagram", 3, xioopen_rawip_datagram, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_RANGE, PF_INET6, 0, 0 HELP(":<host>:<protocol>") };
|
const union xioaddr_desc *xioaddrs_rawip6_sendto[] = { (union xioaddr_desc *)&xioaddr_rawip6_sendto2, NULL };
|
||||||
const struct addrdesc addr_rawip6_recvfrom= { "ip6-recvfrom", 3, xioopen_rawip_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_CHILD|GROUP_RANGE, PF_INET6, SOCK_RAW, 0 HELP(":<protocol>") };
|
static const struct xioaddr_endpoint_desc xioaddr_rawip6_datagram2= { XIOADDR_SYS, "ip6-datagram", 2, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_RANGE, XIOSHUT_DOWN, XIOCLOSE_NONE, xioopen_rawip_datagram, PF_INET6, 0, 0 HELP(":<host>:<protocol>") };
|
||||||
const struct addrdesc addr_rawip6_recv = { "ip6-recv", 1, xioopen_rawip_recv, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_RANGE, PF_INET6, SOCK_RAW, 0 HELP(":<protocol>") };
|
const union xioaddr_desc *xioaddrs_rawip6_datagram[] = { (union xioaddr_desc *)&xioaddr_rawip6_datagram2, NULL };
|
||||||
#endif
|
static const struct xioaddr_endpoint_desc xioaddr_rawip6_recvfrom1= { XIOADDR_SYS, "ip6-recvfrom", 1, XIOBIT_RDONLY|XIOBIT_RDWR, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_CHILD|GROUP_RANGE, XIOSHUT_DOWN, XIOCLOSE_NONE, xioopen_rawip_recvfrom, PF_INET6, SOCK_RAW, 0 HELP(":<protocol>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_rawip6_recvfrom[] = { (union xioaddr_desc *)&xioaddr_rawip6_recvfrom1, NULL };
|
||||||
|
static const struct xioaddr_endpoint_desc xioaddr_rawip6_recv1 = { XIOADDR_SYS, "ip6-recv", 1, XIOBIT_RDONLY, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_RANGE, XIOSHUT_DOWN, XIOCLOSE_NONE, xioopen_rawip_recv, PF_INET6, SOCK_RAW, 0 HELP(":<protocol>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_rawip6_recv[] = { (union xioaddr_desc *)&xioaddr_rawip6_recv1, NULL };
|
||||||
|
#endif /* WITH_IP6 */
|
||||||
|
|
||||||
/* we expect the form: host:protocol */
|
/* we expect the form: host:protocol */
|
||||||
/* struct sockaddr_in sa;*/
|
/* struct sockaddr_in sa;*/
|
||||||
|
@ -106,7 +116,6 @@ int _xioopen_rawip_sendto(const char *hostname, const char *protname,
|
||||||
/*return STAT_NORETRY;*/
|
/*return STAT_NORETRY;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
xfd->howtoend = END_SHUTDOWN;
|
|
||||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||||
|
|
||||||
/* ...res_opts[] */
|
/* ...res_opts[] */
|
||||||
|
@ -128,6 +137,7 @@ int _xioopen_rawip_sendto(const char *hostname, const char *protname,
|
||||||
|
|
||||||
uslen = socket_init(pf, &us);
|
uslen = socket_init(pf, &us);
|
||||||
|
|
||||||
|
xfd->fdtype = FDTYPE_SINGLE;
|
||||||
xfd->dtype = XIODATA_RECVFROM_SKIPIP;
|
xfd->dtype = XIODATA_RECVFROM_SKIPIP;
|
||||||
|
|
||||||
if (retropt_bind(opts, pf, socktype, ipproto, &us.soa, &uslen, feats,
|
if (retropt_bind(opts, pf, socktype, ipproto, &us.soa, &uslen, feats,
|
||||||
|
@ -215,7 +225,8 @@ int xioopen_rawip_recvfrom(int argc, const char *argv[], struct opt *opts,
|
||||||
protname);
|
protname);
|
||||||
/*return STAT_NORETRY;*/
|
/*return STAT_NORETRY;*/
|
||||||
}
|
}
|
||||||
xfd->stream.howtoend = END_NONE;
|
xfd->stream.howtoshut = XIOSHUT_NONE;
|
||||||
|
xfd->stream.howtoclose = XIOCLOSE_CLOSE;
|
||||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||||
|
|
||||||
retropt_socket_pf(opts, &pf);
|
retropt_socket_pf(opts, &pf);
|
||||||
|
@ -235,6 +246,7 @@ int xioopen_rawip_recvfrom(int argc, const char *argv[], struct opt *opts,
|
||||||
needbind = true;
|
needbind = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xfd->stream.fdtype = FDTYPE_SINGLE;
|
||||||
xfd->stream.dtype = XIODATA_RECVFROM_SKIPIP_ONE;
|
xfd->stream.dtype = XIODATA_RECVFROM_SKIPIP_ONE;
|
||||||
if ((result =
|
if ((result =
|
||||||
_xioopen_dgram_recvfrom(&xfd->stream, xioflags, needbind?&us.soa:NULL,
|
_xioopen_dgram_recvfrom(&xfd->stream, xioflags, needbind?&us.soa:NULL,
|
||||||
|
@ -293,6 +305,7 @@ int xioopen_rawip_recv(int argc, const char *argv[], struct opt *opts,
|
||||||
xfd->stream.para.socket.la.soa.sa_family = pf;
|
xfd->stream.para.socket.la.soa.sa_family = pf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xfd->stream.fdtype = FDTYPE_SINGLE;
|
||||||
xfd->stream.dtype = XIODATA_RECV_SKIPIP;
|
xfd->stream.dtype = XIODATA_RECV_SKIPIP;
|
||||||
result = _xioopen_dgram_recv(&xfd->stream, xioflags, NULL/*&us.soa*/, uslen,
|
result = _xioopen_dgram_recv(&xfd->stream, xioflags, NULL/*&us.soa*/, uslen,
|
||||||
opts, pf, socktype, ipproto, E_ERROR);
|
opts, pf, socktype, ipproto, E_ERROR);
|
||||||
|
|
24
xio-rawip.h
24
xio-rawip.h
|
@ -5,17 +5,17 @@
|
||||||
#ifndef __xio_rawip_h_included
|
#ifndef __xio_rawip_h_included
|
||||||
#define __xio_rawip_h_included 1
|
#define __xio_rawip_h_included 1
|
||||||
|
|
||||||
extern const struct addrdesc addr_rawip_sendto;
|
extern const union xioaddr_desc *xioaddrs_rawip_sendto[];
|
||||||
extern const struct addrdesc addr_rawip_datagram;
|
extern const union xioaddr_desc *xioaddrs_rawip_datagram[];
|
||||||
extern const struct addrdesc addr_rawip_recvfrom;
|
extern const union xioaddr_desc *xioaddrs_rawip_recvfrom[];
|
||||||
extern const struct addrdesc addr_rawip_recv;
|
extern const union xioaddr_desc *xioaddrs_rawip_recv[];
|
||||||
extern const struct addrdesc addr_rawip4_sendto;
|
extern const union xioaddr_desc *xioaddrs_rawip4_sendto[];
|
||||||
extern const struct addrdesc addr_rawip4_datagram;
|
extern const union xioaddr_desc *xioaddrs_rawip4_datagram[];
|
||||||
extern const struct addrdesc addr_rawip4_recvfrom;
|
extern const union xioaddr_desc *xioaddrs_rawip4_recvfrom[];
|
||||||
extern const struct addrdesc addr_rawip4_recv;
|
extern const union xioaddr_desc *xioaddrs_rawip4_recv[];
|
||||||
extern const struct addrdesc addr_rawip6_sendto;
|
extern const union xioaddr_desc *xioaddrs_rawip6_sendto[];
|
||||||
extern const struct addrdesc addr_rawip6_datagram;
|
extern const union xioaddr_desc *xioaddrs_rawip6_datagram[];
|
||||||
extern const struct addrdesc addr_rawip6_recvfrom;
|
extern const union xioaddr_desc *xioaddrs_rawip6_recvfrom[];
|
||||||
extern const struct addrdesc addr_rawip6_recv;
|
extern const union xioaddr_desc *xioaddrs_rawip6_recv[];
|
||||||
|
|
||||||
#endif /* !defined(__xio_rawip_h_included) */
|
#endif /* !defined(__xio_rawip_h_included) */
|
||||||
|
|
|
@ -30,8 +30,13 @@ static int xioopen_readline(int argc, const char *argv[], struct opt *opts,
|
||||||
int dummy1, int dummy2, int dummy3);
|
int dummy1, int dummy2, int dummy3);
|
||||||
|
|
||||||
|
|
||||||
const struct addrdesc addr_readline = {
|
static const struct xioaddr_endpoint_desc xioendpoint_readline0 = {
|
||||||
"readline", 3, xioopen_readline, GROUP_FD|GROUP_TERMIOS|GROUP_READLINE, 0, 0, 0 HELP(NULL) };
|
XIOADDR_SYS, "readline", 0, XIOBIT_WRONLY|XIOBIT_RDWR, GROUP_FD|GROUP_TERMIOS|GROUP_READLINE, XIOSHUT_CLOSE, XIOCLOSE_NONE, xioopen_readline, 0, 0, 0 HELP(NULL) };
|
||||||
|
|
||||||
|
const union xioaddr_desc *xioaddrs_readline[] = {
|
||||||
|
(union xioaddr_desc *)&xioendpoint_readline0,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
const struct optdesc opt_history_file = { "history-file", "history", OPT_HISTORY_FILE, GROUP_READLINE, PH_LATE, TYPE_STRING, OFUNC_OFFSET, (int)&((xiofile_t *)0)->stream.para.readline.history_file };
|
const struct optdesc opt_history_file = { "history-file", "history", OPT_HISTORY_FILE, GROUP_READLINE, PH_LATE, TYPE_STRING, OFUNC_OFFSET, (int)&((xiofile_t *)0)->stream.para.readline.history_file };
|
||||||
const struct optdesc opt_prompt = { "prompt", NULL, OPT_PROMPT, GROUP_READLINE, PH_LATE, TYPE_STRING, OFUNC_OFFSET, (int)&((xiofile_t *)0)->stream.para.readline.prompt };
|
const struct optdesc opt_prompt = { "prompt", NULL, OPT_PROMPT, GROUP_READLINE, PH_LATE, TYPE_STRING, OFUNC_OFFSET, (int)&((xiofile_t *)0)->stream.para.readline.prompt };
|
||||||
|
@ -69,15 +74,16 @@ static int xioopen_readline(int argc, const char *argv[], struct opt *opts,
|
||||||
}
|
}
|
||||||
Notice(msgbuf);
|
Notice(msgbuf);
|
||||||
|
|
||||||
xfd->stream.fd = 0; /* stdin */
|
xfd->stream.fd1 = 0; /* stdin */
|
||||||
xfd->stream.howtoend = END_NONE;
|
xfd->stream.howtoclose = XIOCLOSE_READLINE;
|
||||||
xfd->stream.dtype = XIODATA_READLINE;
|
xfd->stream.dtype = XIODATA_READLINE;
|
||||||
|
xfd->stream.fdtype = FDTYPE_SINGLE;
|
||||||
|
|
||||||
#if WITH_TERMIOS
|
#if WITH_TERMIOS
|
||||||
if (Isatty(xfd->stream.fd)) {
|
if (Isatty(xfd->stream.fd1)) {
|
||||||
if (Tcgetattr(xfd->stream.fd, &xfd->stream.savetty) < 0) {
|
if (Tcgetattr(xfd->stream.fd1, &xfd->stream.savetty) < 0) {
|
||||||
Warn2("cannot query current terminal settings on fd %d. %s",
|
Warn2("cannot query current terminal settings on fd %d. %s",
|
||||||
xfd->stream.fd, strerror(errno));
|
xfd->stream.fd1, strerror(errno));
|
||||||
} else {
|
} else {
|
||||||
xfd->stream.ttyvalid = true;
|
xfd->stream.ttyvalid = true;
|
||||||
}
|
}
|
||||||
|
@ -87,7 +93,7 @@ static int xioopen_readline(int argc, const char *argv[], struct opt *opts,
|
||||||
if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1;
|
if (applyopts_single(&xfd->stream, opts, PH_INIT) < 0) return -1;
|
||||||
applyopts(-1, opts, PH_INIT);
|
applyopts(-1, opts, PH_INIT);
|
||||||
|
|
||||||
applyopts2(xfd->stream.fd, opts, PH_INIT, PH_FD);
|
applyopts2(xfd->stream.fd1, opts, PH_INIT, PH_FD);
|
||||||
|
|
||||||
Using_history();
|
Using_history();
|
||||||
applyopts_offset(&xfd->stream, opts);
|
applyopts_offset(&xfd->stream, opts);
|
||||||
|
@ -120,8 +126,8 @@ static int xioopen_readline(int argc, const char *argv[], struct opt *opts,
|
||||||
if (xfd->stream.para.readline.history_file) {
|
if (xfd->stream.para.readline.history_file) {
|
||||||
Read_history(xfd->stream.para.readline.history_file);
|
Read_history(xfd->stream.para.readline.history_file);
|
||||||
}
|
}
|
||||||
xiotermios_clrflag(xfd->stream.fd, 3, ICANON);
|
xiotermios_clrflag(xfd->stream.fd1, 3, ICANON);
|
||||||
xiotermios_clrflag(xfd->stream.fd, 3, ECHO);
|
xiotermios_clrflag(xfd->stream.fd1, 3, ECHO);
|
||||||
return _xio_openlate(&xfd->stream, opts);
|
return _xio_openlate(&xfd->stream, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,40 +147,40 @@ ssize_t xioread_readline(struct single *pipe, void *buff, size_t bufsiz) {
|
||||||
readline */
|
readline */
|
||||||
struct termios saveterm, setterm;
|
struct termios saveterm, setterm;
|
||||||
*pipe->para.readline.dynend = '\0';
|
*pipe->para.readline.dynend = '\0';
|
||||||
Tcgetattr(pipe->fd, &saveterm); /*! error */
|
Tcgetattr(pipe->fd1, &saveterm); /*! error */
|
||||||
setterm = saveterm;
|
setterm = saveterm;
|
||||||
setterm.c_lflag |= ICANON;
|
setterm.c_lflag |= ICANON;
|
||||||
Tcsetattr(pipe->fd, TCSANOW, &setterm); /*!*/
|
Tcsetattr(pipe->fd1, TCSANOW, &setterm); /*!*/
|
||||||
do {
|
do {
|
||||||
bytes = Read(pipe->fd, buff, bufsiz);
|
bytes = Read(pipe->fd1, buff, bufsiz);
|
||||||
} while (bytes < 0 && errno == EINTR);
|
} while (bytes < 0 && errno == EINTR);
|
||||||
if (bytes < 0) {
|
if (bytes < 0) {
|
||||||
_errno = errno;
|
_errno = errno;
|
||||||
Error4("read(%d, %p, "F_Zu"): %s",
|
Error4("read(%d, %p, "F_Zu"): %s",
|
||||||
pipe->fd, buff, bufsiz, strerror(_errno));
|
pipe->fd1, buff, bufsiz, strerror(_errno));
|
||||||
errno = _errno;
|
errno = _errno;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
setterm.c_lflag &= ~ICANON;
|
setterm.c_lflag &= ~ICANON;
|
||||||
Tcgetattr(pipe->fd, &setterm); /*! error */
|
Tcgetattr(pipe->fd1, &setterm); /*! error */
|
||||||
Tcsetattr(pipe->fd, TCSANOW, &saveterm); /*!*/
|
Tcsetattr(pipe->fd1, TCSANOW, &saveterm); /*!*/
|
||||||
pipe->para.readline.dynend = pipe->para.readline.dynprompt;
|
pipe->para.readline.dynend = pipe->para.readline.dynprompt;
|
||||||
/*Write(pipe->fd, "\n", 1);*/ /*!*/
|
/*Write(pipe->fd1, "\n", 1);*/ /*!*/
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
#endif /* HAVE_REGEX_H */
|
#endif /* HAVE_REGEX_H */
|
||||||
|
|
||||||
xiotermios_setflag(pipe->fd, 3, ECHO);
|
xiotermios_setflag(pipe->fd1, 3, ECHO);
|
||||||
if (pipe->para.readline.prompt || pipe->para.readline.dynprompt) {
|
if (pipe->para.readline.prompt || pipe->para.readline.dynprompt) {
|
||||||
/* we must carriage return, because readline will first print the
|
/* we must carriage return, because readline will first print the
|
||||||
prompt */
|
prompt */
|
||||||
ssize_t writt;
|
ssize_t writt;
|
||||||
do {
|
do {
|
||||||
writt = Write(pipe->fd, "\r", 1);
|
writt = Write(pipe->fd1, "\r", 1);
|
||||||
} while (writt < 0 && errno == EINTR);
|
} while (writt < 0 && errno == EINTR);
|
||||||
if (writt < 0) {
|
if (writt < 0) {
|
||||||
Warn2("write(%d, \"\\r\", 1): %s",
|
Warn2("write(%d, \"\\r\", 1): %s",
|
||||||
pipe->fd, strerror(errno));
|
pipe->fd1, strerror(errno));
|
||||||
} else if (writt < 1) {
|
} else if (writt < 1) {
|
||||||
Warn1("write() only wrote "F_Zu" of 1 byte", writt);
|
Warn1("write() only wrote "F_Zu" of 1 byte", writt);
|
||||||
}
|
}
|
||||||
|
@ -191,7 +197,7 @@ ssize_t xioread_readline(struct single *pipe, void *buff, size_t bufsiz) {
|
||||||
if (line == NULL) {
|
if (line == NULL) {
|
||||||
return 0; /* EOF */
|
return 0; /* EOF */
|
||||||
}
|
}
|
||||||
xiotermios_clrflag(pipe->fd, 3, ECHO);
|
xiotermios_clrflag(pipe->fd1, 3, ECHO);
|
||||||
Add_history(line);
|
Add_history(line);
|
||||||
bytes = strlen(line);
|
bytes = strlen(line);
|
||||||
strncpy(buff, line, bufsiz);
|
strncpy(buff, line, bufsiz);
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
/* $Id: xio-readline.h,v 1.4 2003/12/23 21:38:59 gerhard Exp $ */
|
/* $Id: xio-readline.h,v 1.4.2.1 2006/07/24 19:18:24 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2002, 2003 */
|
/* Copyright Gerhard Rieger 2002-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
#ifndef __xio_readline_h_included
|
#ifndef __xio_readline_h_included
|
||||||
#define __xio_readline_h_included 1
|
#define __xio_readline_h_included 1
|
||||||
|
|
||||||
extern const struct addrdesc addr_readline;
|
extern const union xioaddr_desc *xioaddrs_readline[];
|
||||||
|
|
||||||
extern const struct optdesc opt_history_file;
|
extern const struct optdesc opt_history_file;
|
||||||
extern const struct optdesc opt_prompt;
|
extern const struct optdesc opt_prompt;
|
||||||
|
|
167
xio-socket.c
167
xio-socket.c
|
@ -9,6 +9,7 @@
|
||||||
#if _WITH_SOCKET
|
#if _WITH_SOCKET
|
||||||
|
|
||||||
#include "xioopen.h"
|
#include "xioopen.h"
|
||||||
|
#include "xiosigchld.h"
|
||||||
#include "xio-socket.h"
|
#include "xio-socket.h"
|
||||||
#include "xio-named.h"
|
#include "xio-named.h"
|
||||||
#if WITH_IP4
|
#if WITH_IP4
|
||||||
|
@ -144,20 +145,21 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
||||||
int _errno;
|
int _errno;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if ((xfd->fd = Socket(pf, stype, proto)) < 0) {
|
if ((xfd->fd1 = Socket(pf, stype, proto)) < 0) {
|
||||||
Msg4(level,
|
Msg4(level,
|
||||||
"socket(%d, %d, %d): %s", pf, stype, proto, strerror(errno));
|
"socket(%d, %d, %d): %s", pf, stype, proto, strerror(errno));
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
xfd->fdtype = FDTYPE_SINGLE;
|
||||||
|
|
||||||
applyopts_offset(xfd, opts);
|
applyopts_offset(xfd, opts);
|
||||||
applyopts(xfd->fd, opts, PH_PASTSOCKET);
|
applyopts(xfd->fd1, opts, PH_PASTSOCKET);
|
||||||
applyopts(xfd->fd, opts, PH_FD);
|
applyopts(xfd->fd1, opts, PH_FD);
|
||||||
|
|
||||||
applyopts_cloexec(xfd->fd, opts);
|
applyopts_cloexec(xfd->fd1, opts);
|
||||||
|
|
||||||
applyopts(xfd->fd, opts, PH_PREBIND);
|
applyopts(xfd->fd1, opts, PH_PREBIND);
|
||||||
applyopts(xfd->fd, opts, PH_BIND);
|
applyopts(xfd->fd1, opts, PH_BIND);
|
||||||
#if WITH_TCP || WITH_UDP
|
#if WITH_TCP || WITH_UDP
|
||||||
if (alt) {
|
if (alt) {
|
||||||
union sockaddr_union sin, *sinp;
|
union sockaddr_union sin, *sinp;
|
||||||
|
@ -214,13 +216,13 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
||||||
problem = false;
|
problem = false;
|
||||||
do { /* loop over lowport bind() attempts */
|
do { /* loop over lowport bind() attempts */
|
||||||
*port = htons(i);
|
*port = htons(i);
|
||||||
if (Bind(xfd->fd, (struct sockaddr *)sinp, sizeof(*sinp)) < 0) {
|
if (Bind(xfd->fd1, (struct sockaddr *)sinp, sizeof(*sinp)) < 0) {
|
||||||
Msg4(errno==EADDRINUSE?E_INFO:level,
|
Msg4(errno==EADDRINUSE?E_INFO:level,
|
||||||
"bind(%d, {%s}, "F_Zd"): %s", xfd->fd,
|
"bind(%d, {%s}, "F_Zd"): %s", xfd->fd1,
|
||||||
sockaddr_info(&sinp->soa, sizeof(*sinp), infobuff, sizeof(infobuff)),
|
sockaddr_info(&sinp->soa, sizeof(*sinp), infobuff, sizeof(infobuff)),
|
||||||
sizeof(*sinp), strerror(errno));
|
sizeof(*sinp), strerror(errno));
|
||||||
if (errno != EADDRINUSE) {
|
if (errno != EADDRINUSE) {
|
||||||
Close(xfd->fd);
|
Close(xfd->fd1);
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -230,7 +232,7 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
||||||
if (i == N) {
|
if (i == N) {
|
||||||
Msg(level, "no low port available");
|
Msg(level, "no low port available");
|
||||||
/*errno = EADDRINUSE; still assigned */
|
/*errno = EADDRINUSE; still assigned */
|
||||||
Close(xfd->fd);
|
Close(xfd->fd1);
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
} while (i != N);
|
} while (i != N);
|
||||||
|
@ -238,31 +240,31 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
||||||
#endif /* WITH_TCP || WITH_UDP */
|
#endif /* WITH_TCP || WITH_UDP */
|
||||||
|
|
||||||
if (us) {
|
if (us) {
|
||||||
if (Bind(xfd->fd, us, uslen) < 0) {
|
if (Bind(xfd->fd1, us, uslen) < 0) {
|
||||||
Msg4(level, "bind(%d, {%s}, "F_Zd"): %s",
|
Msg4(level, "bind(%d, {%s}, "F_Zd"): %s",
|
||||||
xfd->fd, sockaddr_info(us, uslen, infobuff, sizeof(infobuff)),
|
xfd->fd1, sockaddr_info(us, uslen, infobuff, sizeof(infobuff)),
|
||||||
uslen, strerror(errno));
|
uslen, strerror(errno));
|
||||||
Close(xfd->fd);
|
Close(xfd->fd1);
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
applyopts(xfd->fd, opts, PH_PASTBIND);
|
applyopts(xfd->fd1, opts, PH_PASTBIND);
|
||||||
|
|
||||||
applyopts(xfd->fd, opts, PH_CONNECT);
|
applyopts(xfd->fd1, opts, PH_CONNECT);
|
||||||
|
|
||||||
if (xfd->para.socket.connect_timeout.tv_sec != 0 ||
|
if (xfd->para.socket.connect_timeout.tv_sec != 0 ||
|
||||||
xfd->para.socket.connect_timeout.tv_usec != 0) {
|
xfd->para.socket.connect_timeout.tv_usec != 0) {
|
||||||
fcntl_flags = Fcntl(xfd->fd, F_GETFL);
|
fcntl_flags = Fcntl(xfd->fd1, F_GETFL);
|
||||||
Fcntl_l(xfd->fd, F_SETFL, fcntl_flags|O_NONBLOCK);
|
Fcntl_l(xfd->fd1, F_SETFL, fcntl_flags|O_NONBLOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
result = Connect(xfd->fd, (struct sockaddr *)them, themlen);
|
result = Connect(xfd->fd1, (struct sockaddr *)them, themlen);
|
||||||
_errno = errno;
|
_errno = errno;
|
||||||
la.soa.sa_family = them->sa_family; lalen = sizeof(la);
|
la.soa.sa_family = them->sa_family; lalen = sizeof(la);
|
||||||
if (Getsockname(xfd->fd, &la.soa, &lalen) < 0) {
|
if (Getsockname(xfd->fd1, &la.soa, &lalen) < 0) {
|
||||||
Msg4(level-1, "getsockname(%d, %p, {%d}): %s",
|
Msg4(level-1, "getsockname(%d, %p, {%d}): %s",
|
||||||
xfd->fd, &la.soa, lalen, strerror(errno));
|
xfd->fd1, &la.soa, lalen, strerror(errno));
|
||||||
}
|
}
|
||||||
errno = _errno;
|
errno = _errno;
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
|
@ -273,15 +275,15 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
||||||
fd_set readfds, writefds, exceptfds;
|
fd_set readfds, writefds, exceptfds;
|
||||||
int result;
|
int result;
|
||||||
Info4("connect(%d, %s, "F_Zd"): %s",
|
Info4("connect(%d, %s, "F_Zd"): %s",
|
||||||
xfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
|
xfd->fd1, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
|
||||||
themlen, strerror(errno));
|
themlen, strerror(errno));
|
||||||
timeout = xfd->para.socket.connect_timeout;
|
timeout = xfd->para.socket.connect_timeout;
|
||||||
FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&exceptfds);
|
FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&exceptfds);
|
||||||
FD_SET(xfd->fd, &readfds); FD_SET(xfd->fd, &writefds);
|
FD_SET(xfd->fd1, &readfds); FD_SET(xfd->fd1, &writefds);
|
||||||
result =
|
result =
|
||||||
Select(xfd->fd+1, &readfds, &writefds, &exceptfds, &timeout);
|
Select(xfd->fd1+1, &readfds, &writefds, &exceptfds, &timeout);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
Msg2(level, "select(%d,,,,): %s", xfd->fd+1, strerror(errno));
|
Msg2(level, "select(%d,,,,): %s", xfd->fd1+1, strerror(errno));
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
|
@ -290,26 +292,26 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
||||||
strerror(ETIMEDOUT));
|
strerror(ETIMEDOUT));
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
if (FD_ISSET(xfd->fd, &readfds)) {
|
if (FD_ISSET(xfd->fd1, &readfds)) {
|
||||||
#if 0
|
#if 0
|
||||||
unsigned char dummy[1];
|
unsigned char dummy[1];
|
||||||
Read(xfd->fd, &dummy, 1); /* get error message */
|
Read(xfd->fd1, &dummy, 1); /* get error message */
|
||||||
Msg2(level, "connecting to %s: %s",
|
Msg2(level, "connecting to %s: %s",
|
||||||
sockaddr_info(them, infobuff, sizeof(infobuff)),
|
sockaddr_info(them, infobuff, sizeof(infobuff)),
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
#else
|
#else
|
||||||
Connect(xfd->fd, them, themlen); /* get error message */
|
Connect(xfd->fd1, them, themlen); /* get error message */
|
||||||
Msg4(level, "connect(%d, %s, "F_Zd"): %s",
|
Msg4(level, "connect(%d, %s, "F_Zd"): %s",
|
||||||
xfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
|
xfd->fd1, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
|
||||||
themlen, strerror(errno));
|
themlen, strerror(errno));
|
||||||
#endif
|
#endif
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
/* otherwise OK */
|
/* otherwise OK */
|
||||||
Fcntl_l(xfd->fd, F_SETFL, fcntl_flags);
|
Fcntl_l(xfd->fd1, F_SETFL, fcntl_flags);
|
||||||
} else {
|
} else {
|
||||||
Warn4("connect(%d, %s, "F_Zd"): %s",
|
Warn4("connect(%d, %s, "F_Zd"): %s",
|
||||||
xfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
|
xfd->fd1, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
|
||||||
themlen, strerror(errno));
|
themlen, strerror(errno));
|
||||||
}
|
}
|
||||||
} else if (pf == PF_UNIX && errno == EPROTOTYPE) {
|
} else if (pf == PF_UNIX && errno == EPROTOTYPE) {
|
||||||
|
@ -317,7 +319,7 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
||||||
the only way to distinguish stream and datagram sockets */
|
the only way to distinguish stream and datagram sockets */
|
||||||
int _errno = errno;
|
int _errno = errno;
|
||||||
Info4("connect(%d, %s, "F_Zd"): %s",
|
Info4("connect(%d, %s, "F_Zd"): %s",
|
||||||
xfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
|
xfd->fd1, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
|
||||||
themlen, strerror(errno));
|
themlen, strerror(errno));
|
||||||
#if 0
|
#if 0
|
||||||
Info("assuming datagram socket");
|
Info("assuming datagram socket");
|
||||||
|
@ -326,22 +328,21 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
||||||
memcpy(&xfd->peersa.soa, them, xfd->salen);
|
memcpy(&xfd->peersa.soa, them, xfd->salen);
|
||||||
#endif
|
#endif
|
||||||
/*!!! and remove bind socket */
|
/*!!! and remove bind socket */
|
||||||
Close(xfd->fd); xfd->fd = -1;
|
Close(xfd->fd1); xfd->fd1 = -1;
|
||||||
errno = _errno;
|
errno = _errno;
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
Msg4(level, "connect(%d, %s, "F_Zd"): %s",
|
Msg4(level, "connect(%d, %s, "F_Zd"): %s",
|
||||||
xfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
|
xfd->fd1, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
|
||||||
themlen, strerror(errno));
|
themlen, strerror(errno));
|
||||||
Close(xfd->fd);
|
Close(xfd->fd1);
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
applyopts_fchown(xfd->fd, opts);
|
applyopts_fchown(xfd->fd1, opts);
|
||||||
applyopts(xfd->fd, opts, PH_CONNECTED);
|
applyopts(xfd->fd1, opts, PH_CONNECTED);
|
||||||
applyopts(xfd->fd, opts, PH_LATE);
|
applyopts(xfd->fd1, opts, PH_LATE);
|
||||||
|
|
||||||
Notice1("successfully connected from local address %s",
|
Notice1("successfully connected from local address %s",
|
||||||
sockaddr_info(&la.soa, themlen, infobuff, sizeof(infobuff)));
|
sockaddr_info(&la.soa, themlen, infobuff, sizeof(infobuff)));
|
||||||
|
|
||||||
|
@ -428,7 +429,7 @@ int xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
||||||
}
|
}
|
||||||
/* parent process */
|
/* parent process */
|
||||||
Notice1("forked off child process "F_pid, pid);
|
Notice1("forked off child process "F_pid, pid);
|
||||||
Close(xfd->fd);
|
Close(xfd->fd1);
|
||||||
/* with and without retry */
|
/* with and without retry */
|
||||||
Nanosleep(&xfd->intervall, NULL);
|
Nanosleep(&xfd->intervall, NULL);
|
||||||
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
|
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
|
||||||
|
@ -458,7 +459,7 @@ int _xioopen_dgram_sendto(/* them is already in xfd->peersa */
|
||||||
union sockaddr_union la; socklen_t lalen = sizeof(la);
|
union sockaddr_union la; socklen_t lalen = sizeof(la);
|
||||||
char infobuff[256];
|
char infobuff[256];
|
||||||
|
|
||||||
if ((xfd->fd = Socket(pf, socktype, ipproto)) < 0) {
|
if ((xfd->fd1 = Socket(pf, socktype, ipproto)) < 0) {
|
||||||
Msg4(level,
|
Msg4(level,
|
||||||
"socket(%d, %d, %d): %s", pf, socktype, ipproto, strerror(errno));
|
"socket(%d, %d, %d): %s", pf, socktype, ipproto, strerror(errno));
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
|
@ -466,36 +467,36 @@ int _xioopen_dgram_sendto(/* them is already in xfd->peersa */
|
||||||
|
|
||||||
applyopts_offset(xfd, opts);
|
applyopts_offset(xfd, opts);
|
||||||
applyopts_single(xfd, opts, PH_PASTSOCKET);
|
applyopts_single(xfd, opts, PH_PASTSOCKET);
|
||||||
applyopts(xfd->fd, opts, PH_PASTSOCKET);
|
applyopts(xfd->fd1, opts, PH_PASTSOCKET);
|
||||||
applyopts(xfd->fd, opts, PH_FD);
|
applyopts(xfd->fd1, opts, PH_FD);
|
||||||
|
|
||||||
applyopts_cloexec(xfd->fd, opts);
|
applyopts_cloexec(xfd->fd1, opts);
|
||||||
|
|
||||||
applyopts(xfd->fd, opts, PH_PREBIND);
|
applyopts(xfd->fd1, opts, PH_PREBIND);
|
||||||
applyopts(xfd->fd, opts, PH_BIND);
|
applyopts(xfd->fd1, opts, PH_BIND);
|
||||||
|
|
||||||
if (us) {
|
if (us) {
|
||||||
if (Bind(xfd->fd, (struct sockaddr *)us, uslen) < 0) {
|
if (Bind(xfd->fd1, (struct sockaddr *)us, uslen) < 0) {
|
||||||
Msg4(level, "bind(%d, {%s}, "F_Zd"): %s",
|
Msg4(level, "bind(%d, {%s}, "F_Zd"): %s",
|
||||||
xfd->fd, sockaddr_info((struct sockaddr *)us, uslen, infobuff, sizeof(infobuff)),
|
xfd->fd1, sockaddr_info((struct sockaddr *)us, uslen, infobuff, sizeof(infobuff)),
|
||||||
uslen, strerror(errno));
|
uslen, strerror(errno));
|
||||||
Close(xfd->fd);
|
Close(xfd->fd1);
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
applyopts(xfd->fd, opts, PH_PASTBIND);
|
applyopts(xfd->fd1, opts, PH_PASTBIND);
|
||||||
|
|
||||||
/*applyopts(xfd->fd, opts, PH_CONNECT);*/
|
/*applyopts(xfd->fd1, opts, PH_CONNECT);*/
|
||||||
|
|
||||||
if (Getsockname(xfd->fd, &la.soa, &lalen) < 0) {
|
if (Getsockname(xfd->fd1, &la.soa, &lalen) < 0) {
|
||||||
Warn4("getsockname(%d, %p, {%d}): %s",
|
Warn4("getsockname(%d, %p, {%d}): %s",
|
||||||
xfd->fd, &la.soa, lalen, strerror(errno));
|
xfd->fd1, &la.soa, lalen, strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
applyopts_fchown(xfd->fd, opts);
|
applyopts_fchown(xfd->fd1, opts);
|
||||||
applyopts(xfd->fd, opts, PH_CONNECTED);
|
applyopts(xfd->fd1, opts, PH_CONNECTED);
|
||||||
applyopts(xfd->fd, opts, PH_LATE);
|
applyopts(xfd->fd1, opts, PH_LATE);
|
||||||
|
|
||||||
/* xfd->dtype = DATA_RECVFROM; *//* no, the caller must set this (ev _SKIPIP) */
|
/* xfd->dtype = DATA_RECVFROM; *//* no, the caller must set this (ev _SKIPIP) */
|
||||||
Notice1("successfully prepared local socket %s",
|
Notice1("successfully prepared local socket %s",
|
||||||
|
@ -577,24 +578,24 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
||||||
}
|
}
|
||||||
#endif /* 1 */
|
#endif /* 1 */
|
||||||
|
|
||||||
if ((xfd->fd = Socket(pf, socktype, proto)) < 0) {
|
if ((xfd->fd1 = Socket(pf, socktype, proto)) < 0) {
|
||||||
Msg4(level,
|
Msg4(level,
|
||||||
"socket(%d, %d, %d): %s", pf, socktype, proto, strerror(errno));
|
"socket(%d, %d, %d): %s", pf, socktype, proto, strerror(errno));
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
|
||||||
applyopts_single(xfd, opts, PH_PASTSOCKET);
|
applyopts_single(xfd, opts, PH_PASTSOCKET);
|
||||||
applyopts(xfd->fd, opts, PH_PASTSOCKET);
|
applyopts(xfd->fd1, opts, PH_PASTSOCKET);
|
||||||
|
|
||||||
applyopts_cloexec(xfd->fd, opts);
|
applyopts_cloexec(xfd->fd1, opts);
|
||||||
|
|
||||||
applyopts(xfd->fd, opts, PH_PREBIND);
|
applyopts(xfd->fd1, opts, PH_PREBIND);
|
||||||
applyopts(xfd->fd, opts, PH_BIND);
|
applyopts(xfd->fd1, opts, PH_BIND);
|
||||||
if ((us != NULL) && Bind(xfd->fd, (struct sockaddr *)us, uslen) < 0) {
|
if ((us != NULL) && Bind(xfd->fd1, (struct sockaddr *)us, uslen) < 0) {
|
||||||
Msg4(level, "bind(%d, {%s}, "F_Zd"): %s", xfd->fd,
|
Msg4(level, "bind(%d, {%s}, "F_Zd"): %s", xfd->fd1,
|
||||||
sockaddr_info(us, uslen, infobuff, sizeof(infobuff)), uslen,
|
sockaddr_info(us, uslen, infobuff, sizeof(infobuff)), uslen,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
Close(xfd->fd);
|
Close(xfd->fd1);
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -604,7 +605,7 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
applyopts(xfd->fd, opts, PH_PASTBIND);
|
applyopts(xfd->fd1, opts, PH_PASTBIND);
|
||||||
#if WITH_UNIX
|
#if WITH_UNIX
|
||||||
if (pf == AF_UNIX && us != NULL) {
|
if (pf == AF_UNIX && us != NULL) {
|
||||||
/*applyopts_early(((struct sockaddr_un *)us)->sun_path, opts);*/
|
/*applyopts_early(((struct sockaddr_un *)us)->sun_path, opts);*/
|
||||||
|
@ -688,7 +689,7 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
||||||
if (drop) {
|
if (drop) {
|
||||||
char *dummy[2];
|
char *dummy[2];
|
||||||
|
|
||||||
Recv(xfd->fd, dummy, sizeof(dummy), 0);
|
Recv(xfd->fd1, dummy, sizeof(dummy), 0);
|
||||||
drop = true;
|
drop = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -702,8 +703,8 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
||||||
Notice1("receiving IP protocol %u", proto);
|
Notice1("receiving IP protocol %u", proto);
|
||||||
}
|
}
|
||||||
FD_ZERO(&in); FD_ZERO(&out); FD_ZERO(&expt);
|
FD_ZERO(&in); FD_ZERO(&out); FD_ZERO(&expt);
|
||||||
FD_SET(xfd->fd, &in);
|
FD_SET(xfd->fd1, &in);
|
||||||
if (Select(xfd->fd+1, &in, &out, &expt, NULL) > 0) {
|
if (Select(xfd->fd1+1, &in, &out, &expt, NULL) > 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -711,12 +712,12 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Msg2(level, "select(, {%d}): %s", xfd->fd, strerror(errno));
|
Msg2(level, "select(, {%d}): %s", xfd->fd1, strerror(errno));
|
||||||
Close(xfd->fd);
|
Close(xfd->fd1);
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
} while (true);
|
} while (true);
|
||||||
|
|
||||||
if (xiogetpacketsrc(xfd->fd, pa, &palen) < 0) {
|
if (xiogetpacketsrc(xfd->fd1, pa, &palen) < 0) {
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -727,16 +728,16 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
||||||
if (xiocheckpeer(xfd, pa, la) < 0) {
|
if (xiocheckpeer(xfd, pa, la) < 0) {
|
||||||
/* drop packet */
|
/* drop packet */
|
||||||
char buff[512];
|
char buff[512];
|
||||||
Recv(xfd->fd, buff, sizeof(buff), 0);
|
Recv(xfd->fd1, buff, sizeof(buff), 0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Info1("permitting packet from %s",
|
Info1("permitting packet from %s",
|
||||||
sockaddr_info((struct sockaddr *)pa, palen,
|
sockaddr_info((struct sockaddr *)pa, palen,
|
||||||
infobuff, sizeof(infobuff)));
|
infobuff, sizeof(infobuff)));
|
||||||
|
|
||||||
applyopts(xfd->fd, opts, PH_FD);
|
applyopts(xfd->fd1, opts, PH_FD);
|
||||||
|
|
||||||
applyopts(xfd->fd, opts, PH_CONNECTED);
|
applyopts(xfd->fd1, opts, PH_CONNECTED);
|
||||||
|
|
||||||
xfd->peersa = *(union sockaddr_union *)pa;
|
xfd->peersa = *(union sockaddr_union *)pa;
|
||||||
xfd->salen = palen;
|
xfd->salen = palen;
|
||||||
|
@ -758,7 +759,7 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
||||||
|
|
||||||
if ((pid = Fork()) < 0) {
|
if ((pid = Fork()) < 0) {
|
||||||
Msg1(level, "fork(): %s", strerror(errno));
|
Msg1(level, "fork(): %s", strerror(errno));
|
||||||
Close(xfd->fd);
|
Close(xfd->fd1);
|
||||||
Sigprocmask(SIG_UNBLOCK, &mask_sigchldusr1, NULL);
|
Sigprocmask(SIG_UNBLOCK, &mask_sigchldusr1, NULL);
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
@ -830,24 +831,24 @@ int _xioopen_dgram_recv(struct single *xfd, int xioflags,
|
||||||
|
|
||||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
|
if (applyopts_single(xfd, opts, PH_INIT) < 0) return STAT_NORETRY;
|
||||||
|
|
||||||
if ((xfd->fd = Socket(pf, socktype, proto)) < 0) {
|
if ((xfd->fd1 = Socket(pf, socktype, proto)) < 0) {
|
||||||
Msg4(level,
|
Msg4(level,
|
||||||
"socket(%d, %d, %d): %s", pf, socktype, proto, strerror(errno));
|
"socket(%d, %d, %d): %s", pf, socktype, proto, strerror(errno));
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
|
||||||
applyopts_single(xfd, opts, PH_PASTSOCKET);
|
applyopts_single(xfd, opts, PH_PASTSOCKET);
|
||||||
applyopts(xfd->fd, opts, PH_PASTSOCKET);
|
applyopts(xfd->fd1, opts, PH_PASTSOCKET);
|
||||||
|
|
||||||
applyopts_cloexec(xfd->fd, opts);
|
applyopts_cloexec(xfd->fd1, opts);
|
||||||
|
|
||||||
applyopts(xfd->fd, opts, PH_PREBIND);
|
applyopts(xfd->fd1, opts, PH_PREBIND);
|
||||||
applyopts(xfd->fd, opts, PH_BIND);
|
applyopts(xfd->fd1, opts, PH_BIND);
|
||||||
if ((us != NULL) && Bind(xfd->fd, (struct sockaddr *)us, uslen) < 0) {
|
if ((us != NULL) && Bind(xfd->fd1, (struct sockaddr *)us, uslen) < 0) {
|
||||||
Msg4(level, "bind(%d, {%s}, "F_Zd"): %s", xfd->fd,
|
Msg4(level, "bind(%d, {%s}, "F_Zd"): %s", xfd->fd1,
|
||||||
sockaddr_info(us, uslen, infobuff, sizeof(infobuff)), uslen,
|
sockaddr_info(us, uslen, infobuff, sizeof(infobuff)), uslen,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
Close(xfd->fd);
|
Close(xfd->fd1);
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -857,7 +858,7 @@ int _xioopen_dgram_recv(struct single *xfd, int xioflags,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
applyopts(xfd->fd, opts, PH_PASTBIND);
|
applyopts(xfd->fd1, opts, PH_PASTBIND);
|
||||||
#if WITH_UNIX
|
#if WITH_UNIX
|
||||||
if (pf == AF_UNIX && us != NULL) {
|
if (pf == AF_UNIX && us != NULL) {
|
||||||
/*applyopts_early(((struct sockaddr_un *)us)->sun_path, opts);*/
|
/*applyopts_early(((struct sockaddr_un *)us)->sun_path, opts);*/
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* $Id: xio-socket.h,v 1.16 2006/12/30 23:04:21 gerhard Exp $ */
|
/* $Id: xio-socket.h,v 1.16 2006/12/30 23:04:21 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2001-2006 */
|
/* Copyright Gerhard Rieger 2001-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
#ifndef __xio_socket_h_included
|
#ifndef __xio_socket_h_included
|
||||||
|
|
110
xio-socks.c
110
xio-socks.c
|
@ -1,5 +1,5 @@
|
||||||
/* $Id: xio-socks.c,v 1.33 2006/12/28 14:06:37 gerhard Exp $ */
|
/* $Id: xio-socks.c,v 1.33 2006/12/28 14:06:37 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2001-2006 */
|
/* Copyright Gerhard Rieger 2001-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
/* this file contains the source for opening addresses of socks4 type */
|
/* this file contains the source for opening addresses of socks4 type */
|
||||||
|
@ -35,10 +35,25 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
|
||||||
const struct optdesc opt_socksport = { "socksport", NULL, OPT_SOCKSPORT, GROUP_IP_SOCKS4, PH_LATE, TYPE_STRING, OFUNC_SPEC };
|
const struct optdesc opt_socksport = { "socksport", NULL, OPT_SOCKSPORT, GROUP_IP_SOCKS4, PH_LATE, TYPE_STRING, OFUNC_SPEC };
|
||||||
const struct optdesc opt_socksuser = { "socksuser", NULL, OPT_SOCKSUSER, GROUP_IP_SOCKS4, PH_LATE, TYPE_NAME, OFUNC_SPEC };
|
const struct optdesc opt_socksuser = { "socksuser", NULL, OPT_SOCKSUSER, GROUP_IP_SOCKS4, PH_LATE, TYPE_NAME, OFUNC_SPEC };
|
||||||
|
|
||||||
const struct addrdesc addr_socks4_connect = { "socks4", 3, xioopen_socks4_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_IP_SOCKS4|GROUP_CHILD|GROUP_RETRY, 0, 0, 0 HELP(":<socks-server>:<host>:<port>") };
|
static const struct xioaddr_inter_desc xiointer_socks4_connect2 = { XIOADDR_INTER, "socks4", 2, XIOBIT_ALL, GROUP_IP_SOCKS4|GROUP_CHILD|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_socks4_connect, 0, 0, 0, XIOBIT_RDWR HELP(":<host>:<port>") };
|
||||||
|
static const struct xioaddr_endpoint_desc xioendpoint_socks4_connect3 = { XIOADDR_ENDPOINT, "socks4", 3, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_IP_SOCKS4|GROUP_CHILD|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_socks4_connect, 0, 0, 0 HELP(":<socks-server>:<host>:<port>") };
|
||||||
|
|
||||||
const struct addrdesc addr_socks4a_connect = { "socks4a", 3, xioopen_socks4_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_IP_SOCKS4|GROUP_CHILD|GROUP_RETRY, 1, 0, 0 HELP(":<socks-server>:<host>:<port>") };
|
const union xioaddr_desc *xioaddrs_socks4_connect[] = {
|
||||||
|
(union xioaddr_desc *)&xiointer_socks4_connect2,
|
||||||
|
(union xioaddr_desc *)&xioendpoint_socks4_connect3,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct xioaddr_inter_desc xiointer_socks4a_connect2 = { XIOADDR_INTER, "socks4a", 2, XIOBIT_ALL, GROUP_IP_SOCKS4|GROUP_CHILD|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_socks4_connect, 1, 0, 0, XIOBIT_RDWR HELP(":<host>:<port>") };
|
||||||
|
static const struct xioaddr_endpoint_desc xioendpoint_socks4a_connect3 = { XIOADDR_ENDPOINT, "socks4a", 3, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_IP_SOCKS4|GROUP_CHILD|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_socks4_connect, 1, 0, 0 HELP(":<socks-server>:<host>:<port>") };
|
||||||
|
|
||||||
|
const union xioaddr_desc *xioaddrs_socks4a_connect[] = {
|
||||||
|
(union xioaddr_desc *)&xiointer_socks4a_connect2,
|
||||||
|
(union xioaddr_desc *)&xioendpoint_socks4a_connect3,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!!! should be two different functions */
|
||||||
static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts,
|
static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts,
|
||||||
int xioflags, xiofile_t *xxfd,
|
int xioflags, xiofile_t *xxfd,
|
||||||
unsigned groups, int socks4a, int dummy2,
|
unsigned groups, int socks4a, int dummy2,
|
||||||
|
@ -46,7 +61,7 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
|
||||||
/* we expect the form: host:host:port */
|
/* we expect the form: host:host:port */
|
||||||
struct single *xfd = &xxfd->stream;
|
struct single *xfd = &xxfd->stream;
|
||||||
struct opt *opts0 = NULL;
|
struct opt *opts0 = NULL;
|
||||||
const char *sockdname; char *socksport;
|
const char *sockdname; char *sockdport;
|
||||||
const char *targetname, *targetport;
|
const char *targetname, *targetport;
|
||||||
int pf = PF_UNSPEC;
|
int pf = PF_UNSPEC;
|
||||||
int ipproto = IPPROTO_TCP;
|
int ipproto = IPPROTO_TCP;
|
||||||
|
@ -58,21 +73,36 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
|
||||||
bool needbind = false;
|
bool needbind = false;
|
||||||
bool lowport = false;
|
bool lowport = false;
|
||||||
unsigned char buff[BUFF_LEN];
|
unsigned char buff[BUFF_LEN];
|
||||||
struct socks4 *sockhead = (struct socks4 *)buff;
|
struct socks4request *sockhead = (struct socks4request *)buff;
|
||||||
size_t buflen = sizeof(buff);
|
size_t buflen = sizeof(buff);
|
||||||
int socktype = SOCK_STREAM;
|
int socktype = SOCK_STREAM;
|
||||||
int level;
|
int level;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if (argc != 4) {
|
if (argc < 3 || argc > 4) {
|
||||||
Error1("%s: 3 parameters required", argv[0]);
|
Warn("syntax 1 (terminal): socks-connect:<socks-server>:<host>:<port>");
|
||||||
|
Error("syntax 2 (inter): socks-connect:<host>:<port>");
|
||||||
|
return STAT_NORETRY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc == 3) {
|
||||||
|
if (xfd->fd1 < 0) {
|
||||||
|
Error("xioopen_socks4_connect(): socksservername missing");
|
||||||
|
return STAT_NORETRY;
|
||||||
|
}
|
||||||
|
sockdname = NULL;
|
||||||
|
targetname = argv[1];
|
||||||
|
targetport = argv[2];
|
||||||
|
} else /* if (argc == 4) */ {
|
||||||
|
if (xfd->fd1 >= 0) {
|
||||||
|
Error("xioopen_socks4_connect(): socksservername not allowed here");
|
||||||
return STAT_NORETRY;
|
return STAT_NORETRY;
|
||||||
}
|
}
|
||||||
sockdname = argv[1];
|
sockdname = argv[1];
|
||||||
targetname = argv[2];
|
targetname = argv[2];
|
||||||
targetport = argv[3];
|
targetport = argv[3];
|
||||||
|
}
|
||||||
|
|
||||||
xfd->howtoend = END_SHUTDOWN;
|
|
||||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||||
applyopts(-1, opts, PH_INIT);
|
applyopts(-1, opts, PH_INIT);
|
||||||
|
|
||||||
|
@ -80,20 +110,26 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
|
||||||
|
|
||||||
retropt_bool(opts, OPT_FORK, &dofork);
|
retropt_bool(opts, OPT_FORK, &dofork);
|
||||||
|
|
||||||
result = _xioopen_socks4_prepare(targetport, opts, &socksport, sockhead, &buflen);
|
result = _xioopen_socks4_prepare(targetport, opts, &sockdport, sockhead, &buflen);
|
||||||
if (result != STAT_OK) return result;
|
if (result != STAT_OK) return result;
|
||||||
|
if (xfd->fd2 < 0) {
|
||||||
result =
|
result =
|
||||||
_xioopen_ipapp_prepare(opts, &opts0, sockdname, socksport,
|
_xioopen_ipapp_prepare(opts, &opts0, sockdname, sockdport,
|
||||||
&pf, ipproto,
|
&pf, ipproto,
|
||||||
xfd->para.socket.ip.res_opts[1],
|
xfd->para.socket.ip.res_opts[1],
|
||||||
xfd->para.socket.ip.res_opts[0],
|
xfd->para.socket.ip.res_opts[0],
|
||||||
them, &themlen, us, &uslen,
|
them, &themlen, us, &uslen,
|
||||||
&needbind, &lowport, &socktype);
|
&needbind, &lowport, &socktype);
|
||||||
|
if (result != STAT_OK) return result;
|
||||||
|
|
||||||
Notice5("opening connection to %s:%u via socks4 server %s:%s as user \"%s\"",
|
Notice5("opening connection to %s:%u via socks4 server %s:%s as user \"%s\"",
|
||||||
targetname,
|
targetname,
|
||||||
ntohs(sockhead->port),
|
ntohs(sockhead->port),
|
||||||
sockdname, socksport, sockhead->userid);
|
sockdname, sockdport, sockhead->userid);
|
||||||
|
} else {
|
||||||
|
Notice3("opening connection to %s:%u using socks4 connect as user \"%s\"",
|
||||||
|
targetname, ntohs(sockhead->port), sockhead->userid);
|
||||||
|
}
|
||||||
|
|
||||||
do { /* loop over failed connect and socks-request attempts */
|
do { /* loop over failed connect and socks-request attempts */
|
||||||
|
|
||||||
|
@ -123,6 +159,7 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (xfd->fd2 < 0) {
|
||||||
/* this cannot fork because we retrieved fork option above */
|
/* this cannot fork because we retrieved fork option above */
|
||||||
result =
|
result =
|
||||||
_xioopen_connect (xfd,
|
_xioopen_connect (xfd,
|
||||||
|
@ -142,8 +179,14 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
|
||||||
default:
|
default:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
xfd->fdtype = FDTYPE_SINGLE;
|
||||||
|
} else {
|
||||||
|
xfd->dtype = XIODATA_STREAM;
|
||||||
|
xfd->fdtype = FDTYPE_DOUBLE;
|
||||||
|
}
|
||||||
|
|
||||||
applyopts(xfd->fd, opts, PH_ALL);
|
/*!*/
|
||||||
|
applyopts(xfd->fd1, opts, PH_ALL);
|
||||||
|
|
||||||
if ((result = _xio_openlate(xfd, opts)) < 0)
|
if ((result = _xio_openlate(xfd, opts)) < 0)
|
||||||
return result;
|
return result;
|
||||||
|
@ -190,7 +233,8 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
|
||||||
}
|
}
|
||||||
/* parent process */
|
/* parent process */
|
||||||
Notice1("forked off child process "F_pid, pid);
|
Notice1("forked off child process "F_pid, pid);
|
||||||
Close(xfd->fd);
|
Close(xfd->fd1);
|
||||||
|
Close(xfd->fd2);
|
||||||
Nanosleep(&xfd->intervall, NULL);
|
Nanosleep(&xfd->intervall, NULL);
|
||||||
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
|
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
|
||||||
continue;
|
continue;
|
||||||
|
@ -205,7 +249,7 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int _xioopen_socks4_prepare(const char *targetport, struct opt *opts, char **socksport, struct socks4 *sockhead, size_t *headlen) {
|
int _xioopen_socks4_prepare(const char *targetport, struct opt *opts, char **socksport, struct socks4request *sockhead, size_t *headlen) {
|
||||||
struct servent *se;
|
struct servent *se;
|
||||||
char *userid;
|
char *userid;
|
||||||
|
|
||||||
|
@ -247,7 +291,7 @@ int
|
||||||
_xioopen_socks4_connect0(struct single *xfd,
|
_xioopen_socks4_connect0(struct single *xfd,
|
||||||
const char *hostname, /* socks target host */
|
const char *hostname, /* socks target host */
|
||||||
int socks4a,
|
int socks4a,
|
||||||
struct socks4 *sockhead,
|
struct socks4request *sockhead,
|
||||||
ssize_t *headlen, /* get available space,
|
ssize_t *headlen, /* get available space,
|
||||||
return used length*/
|
return used length*/
|
||||||
int level) {
|
int level) {
|
||||||
|
@ -294,15 +338,18 @@ int
|
||||||
/* perform socks4 client dialog on existing FD.
|
/* perform socks4 client dialog on existing FD.
|
||||||
Called within fork/retry loop, after connect() */
|
Called within fork/retry loop, after connect() */
|
||||||
int _xioopen_socks4_connect(struct single *xfd,
|
int _xioopen_socks4_connect(struct single *xfd,
|
||||||
struct socks4 *sockhead,
|
struct socks4request *sockhead,
|
||||||
size_t headlen,
|
size_t headlen,
|
||||||
int level) {
|
int level) {
|
||||||
ssize_t bytes;
|
ssize_t bytes;
|
||||||
|
int wfd;
|
||||||
int result;
|
int result;
|
||||||
unsigned char buff[SIZEOF_STRUCT_SOCKS4];
|
unsigned char buff[SIZEOF_STRUCT_SOCKS4];
|
||||||
struct socks4 *replyhead = (struct socks4 *)buff;
|
struct socks4head *replyhead = (struct socks4head *)buff;
|
||||||
char *destdomname = NULL;
|
char *destdomname = NULL;
|
||||||
|
|
||||||
|
wfd = (xfd->fdtype == FDTYPE_SINGLE ? xfd->fd1 : xfd->fd2);
|
||||||
|
|
||||||
/* send socks header (target addr+port, +auth) */
|
/* send socks header (target addr+port, +auth) */
|
||||||
#if WITH_MSGLEVEL <= E_INFO
|
#if WITH_MSGLEVEL <= E_INFO
|
||||||
if (ntohl(sockhead->dest) <= 0x000000ff) {
|
if (ntohl(sockhead->dest) <= 0x000000ff) {
|
||||||
|
@ -329,13 +376,16 @@ int _xioopen_socks4_connect(struct single *xfd,
|
||||||
}
|
}
|
||||||
#endif /* WITH_MSGLEVEL <= E_DEBUG */
|
#endif /* WITH_MSGLEVEL <= E_DEBUG */
|
||||||
do {
|
do {
|
||||||
result = Write(xfd->fd, sockhead, headlen);
|
result = Write(wfd, sockhead, headlen);
|
||||||
} while (result < 0 && errno == EINTR);
|
} while (result < 0 && errno == EINTR);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
Msg4(level, "write(%d, %p, "F_Zu"): %s",
|
Msg4(level, "write(%d, %p, "F_Zu"): %s",
|
||||||
xfd->fd, sockhead, headlen, strerror(errno));
|
wfd, sockhead, headlen, strerror(errno));
|
||||||
if (Close(xfd->fd) < 0) {
|
if (Close(wfd) < 0) {
|
||||||
Info2("close(%d): %s", xfd->fd, strerror(errno));
|
Info2("close(%d): %s", wfd, strerror(errno));
|
||||||
|
}
|
||||||
|
if (Close(xfd->fd1) < 0) {
|
||||||
|
Info2("close(%d): %s", xfd->fd1, strerror(errno));
|
||||||
}
|
}
|
||||||
return STAT_RETRYLATER; /* retry complete open cycle */
|
return STAT_RETRYLATER; /* retry complete open cycle */
|
||||||
}
|
}
|
||||||
|
@ -345,20 +395,26 @@ int _xioopen_socks4_connect(struct single *xfd,
|
||||||
while (bytes >= 0) { /* loop over answer chunks until complete or error */
|
while (bytes >= 0) { /* loop over answer chunks until complete or error */
|
||||||
/* receive socks answer */
|
/* receive socks answer */
|
||||||
do {
|
do {
|
||||||
result = Read(xfd->fd, buff+bytes, SIZEOF_STRUCT_SOCKS4-bytes);
|
result = Read(xfd->fd1, buff+bytes, SIZEOF_STRUCT_SOCKS4-bytes);
|
||||||
} while (result < 0 && errno == EINTR);
|
} while (result < 0 && errno == EINTR);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
Msg4(level, "read(%d, %p, "F_Zu"): %s",
|
Msg4(level, "read(%d, %p, "F_Zu"): %s",
|
||||||
xfd->fd, buff+bytes, SIZEOF_STRUCT_SOCKS4-bytes,
|
xfd->fd1, buff+bytes, SIZEOF_STRUCT_SOCKS4-bytes,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
if (Close(xfd->fd) < 0) {
|
if (Close(xfd->fd1) < 0) {
|
||||||
Info2("close(%d): %s", xfd->fd, strerror(errno));
|
Info2("close(%d): %s", xfd->fd1, strerror(errno));
|
||||||
|
}
|
||||||
|
if (Close(wfd) < 0) {
|
||||||
|
Info2("close(%d): %s", wfd, strerror(errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
Msg(level, "read(): EOF during read of socks reply, peer might not be a socks4 server");
|
Msg(level, "read(): EOF during read of socks reply, peer might not be a socks4 server");
|
||||||
if (Close(xfd->fd) < 0) {
|
if (Close(xfd->fd1) < 0) {
|
||||||
Info2("close(%d): %s", xfd->fd, strerror(errno));
|
Info2("close(%d): %s", xfd->fd1, strerror(errno));
|
||||||
|
}
|
||||||
|
if (Close(wfd) < 0) {
|
||||||
|
Info2("close(%d): %s", wfd, strerror(errno));
|
||||||
}
|
}
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
|
19
xio-socks.h
19
xio-socks.h
|
@ -1,36 +1,37 @@
|
||||||
/* $Id: xio-socks.h,v 1.6 2004/06/06 19:03:28 gerhard Exp $ */
|
/* $Id: xio-socks.h,v 1.6.2.1 2006/07/24 19:18:30 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2001-2004 */
|
/* Copyright Gerhard Rieger 2001-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
#ifndef __xio_socks_h_included
|
#ifndef __xio_socks_h_included
|
||||||
#define __xio_socks_h_included 1
|
#define __xio_socks_h_included 1
|
||||||
|
|
||||||
struct socks4 {
|
#define SIZEOF_STRUCT_SOCKS4 sizeof(struct socks4head)
|
||||||
|
|
||||||
|
struct socks4request {
|
||||||
uint8_t version;
|
uint8_t version;
|
||||||
uint8_t action;
|
uint8_t action;
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
uint32_t dest;
|
uint32_t dest;
|
||||||
char userid[1]; /* just to have access via this struct */
|
char userid[1]; /* just to have access via this struct */
|
||||||
} ;
|
} ;
|
||||||
#define SIZEOF_STRUCT_SOCKS4 8
|
|
||||||
|
|
||||||
extern const struct optdesc opt_socksport;
|
extern const struct optdesc opt_socksport;
|
||||||
extern const struct optdesc opt_socksuser;
|
extern const struct optdesc opt_socksuser;
|
||||||
|
|
||||||
extern const struct addrdesc addr_socks4_connect;
|
extern const union xioaddr_desc *xioaddrs_socks4_connect[];
|
||||||
extern const struct addrdesc addr_socks4a_connect;
|
extern const union xioaddr_desc *xioaddrs_socks4a_connect[];
|
||||||
|
|
||||||
extern int _xioopen_socks4_prepare(const char *targetport, struct opt *opts, char **socksport, struct socks4 *sockhead, size_t *headlen);
|
extern int _xioopen_socks4_prepare(const char *targetport, struct opt *opts, char **socksport, struct socks4request *sockhead, size_t *headlen);
|
||||||
extern int
|
extern int
|
||||||
_xioopen_socks4_connect0(struct single *xfd,
|
_xioopen_socks4_connect0(struct single *xfd,
|
||||||
const char *hostname, /* socks target host */
|
const char *hostname, /* socks target host */
|
||||||
int socks4a,
|
int socks4a,
|
||||||
struct socks4 *sockhead,
|
struct socks4request *sockhead,
|
||||||
ssize_t *headlen, /* get available space,
|
ssize_t *headlen, /* get available space,
|
||||||
return used length*/
|
return used length*/
|
||||||
int level);
|
int level);
|
||||||
extern int _xioopen_socks4_connect(struct single *xfd,
|
extern int _xioopen_socks4_connect(struct single *xfd,
|
||||||
struct socks4 *sockhead,
|
struct socks4request *sockhead,
|
||||||
size_t headlen,
|
size_t headlen,
|
||||||
int level);
|
int level);
|
||||||
|
|
||||||
|
|
505
xio-socks5.c
Normal file
505
xio-socks5.c
Normal file
|
@ -0,0 +1,505 @@
|
||||||
|
/* $Id$ */
|
||||||
|
/* Copyright Gerhard Rieger 2004-2007 */
|
||||||
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
|
/* this file contains the source for opening addresses of socks5 type */
|
||||||
|
|
||||||
|
#include "xiosysincludes.h"
|
||||||
|
#include "xioopen.h"
|
||||||
|
#include "xio-socket.h"
|
||||||
|
#include "xio-ipapp.h"
|
||||||
|
|
||||||
|
#include "xio-socks5.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if WITH_SOCKS5
|
||||||
|
|
||||||
|
#define SOCKSPORT "1080"
|
||||||
|
#define SOCKS5_MAXLEN 512
|
||||||
|
|
||||||
|
static int
|
||||||
|
xioopen_socks5_client(int argc, const char *argv[],
|
||||||
|
struct opt *opts, int xioflags, xiofile_t *xfd,
|
||||||
|
unsigned groups, int dummy1, int dummy2,
|
||||||
|
int dummy3);
|
||||||
|
|
||||||
|
const struct optdesc opt_socks5_username = { "socks5-username", "socks5user", OPT_SOCKS5_USERNAME, GROUP_SOCKS5, PH_LATE, TYPE_STRING, OFUNC_SPEC };
|
||||||
|
const struct optdesc opt_socks5_password = { "socks5-password", "socks5pass", OPT_SOCKS5_PASSWORD, GROUP_SOCKS5, PH_LATE, TYPE_STRING, OFUNC_SPEC };
|
||||||
|
|
||||||
|
static const struct xioaddr_inter_desc xiointer_socks5_client = { XIOADDR_PROT, "socks5", 2, XIOBIT_ALL, GROUP_SOCKS5, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_socks5_client, 0, 0, 0, XIOBIT_RDWR HELP(":<host>:<port>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_socks5_client[] = {
|
||||||
|
(union xioaddr_desc *)&xiointer_socks5_client, NULL };
|
||||||
|
|
||||||
|
/* read until buflen bytes received or EOF */
|
||||||
|
/* returns STAT_OK, STAT_RETRYLATER, or STAT_NOTRETRY */
|
||||||
|
static int xiosocks5_recvbytes(struct single *xfd,
|
||||||
|
uint8_t *buff, size_t buflen, int level) {
|
||||||
|
size_t bytes;
|
||||||
|
ssize_t result;
|
||||||
|
|
||||||
|
bytes = 0;
|
||||||
|
while (bytes >= 0) { /* loop over answer chunks until complete or error */
|
||||||
|
/* receive socks answer */
|
||||||
|
Debug("waiting for data from peer");
|
||||||
|
do {
|
||||||
|
result = Read(xfd->fd1, buff+bytes, buflen-bytes);
|
||||||
|
} while (result < 0 && errno == EINTR);
|
||||||
|
if (result < 0) {
|
||||||
|
Msg4(level, "read(%d, %p, "F_Zu"): %s",
|
||||||
|
xfd->fd1, buff+bytes, buflen-bytes,
|
||||||
|
strerror(errno));
|
||||||
|
if (Close(xfd->fd1) < 0) {
|
||||||
|
Warn2("close(%d): %s", xfd->fd1, strerror(errno));
|
||||||
|
}
|
||||||
|
if (Close(xfd->fd2) < 0) {
|
||||||
|
Warn2("close(%d): %s", xfd->fd2, strerror(errno));
|
||||||
|
}
|
||||||
|
return STAT_RETRYLATER;
|
||||||
|
}
|
||||||
|
if (result == 0) {
|
||||||
|
Msg(level, "read(): EOF during read of socks reply");
|
||||||
|
if (Close(xfd->fd1) < 0) {
|
||||||
|
Warn2("close(%d): %s", xfd->fd1, strerror(errno));
|
||||||
|
}
|
||||||
|
if (Close(xfd->fd2) < 0) {
|
||||||
|
Warn2("close(%d): %s", xfd->fd2, strerror(errno));
|
||||||
|
}
|
||||||
|
return STAT_RETRYLATER;
|
||||||
|
}
|
||||||
|
bytes += result;
|
||||||
|
if (bytes == buflen) {
|
||||||
|
Debug1("received all "F_Zd" bytes", bytes);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Debug2("received "F_Zd" bytes, waiting for "F_Zu" more bytes",
|
||||||
|
result, buflen-bytes);
|
||||||
|
}
|
||||||
|
if (result <= 0) { /* we had a problem while reading socks answer */
|
||||||
|
return STAT_RETRYLATER; /* retry complete open cycle */
|
||||||
|
}
|
||||||
|
return STAT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int xioopen_socks5_client(int argc, const char *argv[],
|
||||||
|
struct opt *opts, int xioflags,
|
||||||
|
xiofile_t *xxfd,
|
||||||
|
unsigned groups, int dummy1, int dummy2,
|
||||||
|
int dummy3) {
|
||||||
|
/* we expect the form: host:port */
|
||||||
|
xiosingle_t *xfd = &xxfd->stream;
|
||||||
|
const char *targetname, *targetservice;
|
||||||
|
int level;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (argc != 3) {
|
||||||
|
Error("SOCKS5 syntax: socks5-connect:<host>:<port>"); /*! UDP? */
|
||||||
|
return STAT_NORETRY;
|
||||||
|
}
|
||||||
|
|
||||||
|
targetname = argv[1];
|
||||||
|
targetservice = argv[2];
|
||||||
|
|
||||||
|
applyopts(-1, opts, PH_INIT);
|
||||||
|
applyopts_single(xfd, opts, PH_INIT);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
result = _xioopen_socks5_prepare(a3, opts, &socksport, sockhead, &buflen);
|
||||||
|
if (result != STAT_OK) return result;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (xfd->fd1 < 0) {
|
||||||
|
Error("socks5 must be used as embedded address");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Notice2("opening connection to %s:%s using socks5",
|
||||||
|
targetname, targetservice);
|
||||||
|
|
||||||
|
do { /* loop over failed connect and socks-request attempts */
|
||||||
|
|
||||||
|
#if WITH_RETRY
|
||||||
|
if (xfd->forever || xfd->retry) {
|
||||||
|
level = E_INFO;
|
||||||
|
} else
|
||||||
|
#endif /* WITH_RETRY */
|
||||||
|
level = E_ERROR;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* we try to resolve the target address _before_ connecting to the socks
|
||||||
|
server: this avoids unnecessary socks connects and timeouts */
|
||||||
|
result =
|
||||||
|
_xioopen_socks5_connect0(xfd, targetname, sockhead, opts,
|
||||||
|
(ssize_t *)&buflen, level);
|
||||||
|
switch (result) {
|
||||||
|
case STAT_OK: break;
|
||||||
|
#if WITH_RETRY
|
||||||
|
case STAT_RETRYLATER:
|
||||||
|
case STAT_RETRYNOW:
|
||||||
|
if (xfd->forever || xfd->retry--) {
|
||||||
|
if (result == STAT_RETRYLATER) Nanosleep(&xfd->intervall, NULL);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif /* WITH_RETRY */
|
||||||
|
default:
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (xfd->fd1 < 0) {
|
||||||
|
/* this cannot fork because we retrieved fork option above */
|
||||||
|
result =
|
||||||
|
_xioopen_connect (xfd,
|
||||||
|
needbind?(struct sockaddr *)us:NULL, sizeof(*us),
|
||||||
|
(struct sockaddr *)them, sizeof(struct sockaddr_in),
|
||||||
|
opts, PF_INET, socktype, IPPROTO_TCP, lowport, level);
|
||||||
|
switch (result) {
|
||||||
|
case STAT_OK: break;
|
||||||
|
#if WITH_RETRY
|
||||||
|
case STAT_RETRYLATER:
|
||||||
|
case STAT_RETRYNOW:
|
||||||
|
if (xfd->forever || xfd->retry--) {
|
||||||
|
if (result == STAT_RETRYLATER) Nanosleep(&xfd->intervall, NULL);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif /* WITH_RETRY */
|
||||||
|
default:
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
xfd->fd1 = xfd->fd2 = xfd->fd;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
xfd->dtype = XIODATA_STREAM;
|
||||||
|
|
||||||
|
result =
|
||||||
|
_xioopen_socks5_connect(xfd, targetname, targetservice, opts, level);
|
||||||
|
switch (result) {
|
||||||
|
case STAT_OK: break;
|
||||||
|
#if WITH_RETRY
|
||||||
|
case STAT_RETRYLATER:
|
||||||
|
case STAT_RETRYNOW:
|
||||||
|
if (xfd->forever || xfd->retry--) {
|
||||||
|
if (result == STAT_RETRYLATER) Nanosleep(&xfd->intervall, NULL);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif /* WITH_RETRY */
|
||||||
|
default:
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!*/
|
||||||
|
applyopts(xfd->fd1, opts, PH_ALL);
|
||||||
|
|
||||||
|
if ((result = _xio_openlate(xfd, opts)) < 0)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while (true); /* end of complete open loop - drop out on success */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* perform socks5 client dialog on existing FD.
|
||||||
|
Called within fork/retry loop, after connect() */
|
||||||
|
int _xioopen_socks5_connect(struct single *xfd,
|
||||||
|
const char *targetname, const char *targetservice,
|
||||||
|
struct opt *opts, int level) {
|
||||||
|
uint16_t targetport;
|
||||||
|
unsigned char sendbuff[SOCKS5_MAXLEN]; size_t sendlen;
|
||||||
|
unsigned char recvbuff[SOCKS5_MAXLEN];
|
||||||
|
struct socks5_method *sendmethod;
|
||||||
|
struct socks5_select *recvselect;
|
||||||
|
struct socks5_request *sendrequest;
|
||||||
|
struct socks5_reply *recvreply;
|
||||||
|
size_t namelen;
|
||||||
|
size_t addrlen;
|
||||||
|
size_t readpos;
|
||||||
|
char *emsg;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
/* prepare */
|
||||||
|
targetport = parseport(targetservice, IPPROTO_TCP/*!*/);
|
||||||
|
|
||||||
|
/* just the simplest authentications */
|
||||||
|
sendmethod = (struct socks5_method *)sendbuff;
|
||||||
|
sendmethod->version = 5; /* protocol version */
|
||||||
|
sendmethod->nmethods = 2; /* number of proposed authentication types */
|
||||||
|
sendmethod->methods[0] = SOCKS5_METHOD_NOAUTH; /* no auth at all */
|
||||||
|
sendmethod->methods[1] = SOCKS5_METHOD_USERPASS; /* username/password */
|
||||||
|
/*sendmethod->methods[2] = SOCKS5_METHOD_AVENTAIL;*/ /* Aventail Connect */
|
||||||
|
sendlen = 2+sendmethod->nmethods;
|
||||||
|
|
||||||
|
/* send socks header (target addr+port, +auth) */
|
||||||
|
Info("sending socks5 identifier/method selection message");
|
||||||
|
do {
|
||||||
|
result = Write(xfd->fd2, sendmethod, sendlen);
|
||||||
|
} while (result < 0 && errno == EINTR);
|
||||||
|
if (result < 0) {
|
||||||
|
Msg4(level, "write(%d, %p, "F_Zu"): %s",
|
||||||
|
xfd->fd2, sendmethod, sendlen, strerror(errno));
|
||||||
|
if (Close(xfd->fd2) < 0) {
|
||||||
|
Warn2("close(%d): %s", xfd->fd2, strerror(errno));
|
||||||
|
}
|
||||||
|
if (Close(xfd->fd1) < 0) {
|
||||||
|
Warn2("close(%d): %s", xfd->fd1, strerror(errno));
|
||||||
|
}
|
||||||
|
return STAT_RETRYLATER; /* retry complete open cycle */
|
||||||
|
}
|
||||||
|
|
||||||
|
Info1("waiting for socks5 select reply ("F_Zu" bytes)", SOCKS5_SELECT_LENGTH);
|
||||||
|
if ((result =
|
||||||
|
xiosocks5_recvbytes(xfd, recvbuff, SOCKS5_SELECT_LENGTH, level)) !=
|
||||||
|
STAT_OK) {
|
||||||
|
/* we had a problem while reading socks answer */
|
||||||
|
/*! Close(); */
|
||||||
|
return result; /* ev. retry complete open cycle */
|
||||||
|
}
|
||||||
|
recvselect = (struct socks5_select *)recvbuff;
|
||||||
|
Info2("socks5 select: {%u, %u}", recvselect->version, recvselect->method);
|
||||||
|
if (recvselect->version != 5) {
|
||||||
|
Error1("socks5: server protocol version is %u",
|
||||||
|
recvbuff[0]);
|
||||||
|
}
|
||||||
|
if (recvselect->method == SOCKS5_METHOD_NONE) {
|
||||||
|
Error("socks5: server did not accept our authentication methods");
|
||||||
|
}
|
||||||
|
/*! check if selected methods is one of our proposals */
|
||||||
|
|
||||||
|
switch (recvselect->method) {
|
||||||
|
case SOCKS5_METHOD_NOAUTH:
|
||||||
|
break;
|
||||||
|
case SOCKS5_METHOD_USERPASS:
|
||||||
|
if (xio_socks5_username_password(level, opts, xfd) < 0) {
|
||||||
|
Error("username/password not accepted");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Error("socks5 select: unimplemented authentication method selected");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendrequest = (struct socks5_request *)sendbuff;
|
||||||
|
sendrequest->version = SOCKS5_VERSION;
|
||||||
|
sendrequest->command = SOCKS5_COMMAND_CONNECT;
|
||||||
|
sendrequest->reserved = 0;
|
||||||
|
sendrequest->addrtype = SOCKS5_ADDRTYPE_NAME;
|
||||||
|
switch (sendrequest->addrtype) {
|
||||||
|
case SOCKS5_ADDRTYPE_IPV4:
|
||||||
|
break;
|
||||||
|
case SOCKS5_ADDRTYPE_NAME:
|
||||||
|
if ((namelen = strlen(targetname)) > 255) {
|
||||||
|
Error1("socks5: target name is longer than 255 bytes: \"%s\"",
|
||||||
|
targetname);
|
||||||
|
}
|
||||||
|
sendrequest->destaddr[0] = strlen(targetname);
|
||||||
|
strncpy(sendrequest->destaddr+1, targetname, sizeof(sendbuff)-5);
|
||||||
|
break;
|
||||||
|
case SOCKS5_ADDRTYPE_IPV6:
|
||||||
|
break;
|
||||||
|
default: Fatal("socks5: undefined address type in socks request");
|
||||||
|
}
|
||||||
|
*((uint16_t *)&sendrequest->destaddr[strlen(targetname)+1]) = targetport;
|
||||||
|
sendlen = sizeof(struct socks5_request) + namelen + 2;
|
||||||
|
|
||||||
|
/* send socks request (target addr+port, +auth) */
|
||||||
|
Info("sending socks5 request selection");
|
||||||
|
do {
|
||||||
|
result = Write(xfd->fd2, sendrequest, sendlen);
|
||||||
|
} while (result < 0 && errno == EINTR);
|
||||||
|
if (result < 0) {
|
||||||
|
Msg4(level, "write(%d, %p, "F_Zu"): %s",
|
||||||
|
xfd->fd2, sendmethod, sendlen, strerror(errno));
|
||||||
|
if (Close(xfd->fd2) < 0) {
|
||||||
|
Warn2("close(%d): %s", xfd->fd2, strerror(errno));
|
||||||
|
}
|
||||||
|
if (Close(xfd->fd1) < 0) {
|
||||||
|
Warn2("close(%d): %s", xfd->fd1, strerror(errno));
|
||||||
|
}
|
||||||
|
return STAT_RETRYLATER; /* retry complete open cycle */
|
||||||
|
}
|
||||||
|
|
||||||
|
Info("waiting for socks5 reply");
|
||||||
|
recvreply = (struct socks5_reply *)recvbuff;
|
||||||
|
if ((result =
|
||||||
|
xiosocks5_recvbytes(xfd, recvbuff, SOCKS5_REPLY_LENGTH1, level))
|
||||||
|
!= STAT_OK) {
|
||||||
|
/*! close... */
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if (recvreply->version != SOCKS5_VERSION) {
|
||||||
|
Error1("socks5: version of reply is %d", recvreply->version);
|
||||||
|
}
|
||||||
|
switch (recvreply->reply) {
|
||||||
|
case SOCKS5_REPLY_SUCCESS: emsg = NULL; break;
|
||||||
|
case SOCKS5_REPLY_FAILURE: emsg = "general socks server failure"; break;
|
||||||
|
case SOCKS5_REPLY_DENIED: emsg = "connection not allowed by ruleset"; break;
|
||||||
|
case SOCKS5_REPLY_NETUNREACH: emsg = "network unreachable"; break;
|
||||||
|
case SOCKS5_REPLY_HOSTUNREACH: emsg = "host unreachable"; break;
|
||||||
|
case SOCKS5_REPLY_REFUSED: emsg = "connection refused"; break;
|
||||||
|
case SOCKS5_REPLY_TTLEXPIRED: emsg = "TTL expired"; break;
|
||||||
|
case SOCKS5_REPLY_CMDUNSUPP: emsg = "command not supported"; break;
|
||||||
|
case SOCKS5_REPLY_ADDRUNSUPP: emsg = "address type not supported"; break;
|
||||||
|
default: emsg = "undefined error code"; break;
|
||||||
|
}
|
||||||
|
if (recvreply->reply != SOCKS5_REPLY_SUCCESS) {
|
||||||
|
Error1("socks5 reply: %s", emsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (recvreply->addrtype) {
|
||||||
|
case SOCKS5_ADDRTYPE_IPV4:
|
||||||
|
addrlen = 4; /*!*/
|
||||||
|
if ((result =
|
||||||
|
xiosocks5_recvbytes(xfd, recvbuff+SOCKS5_REPLY_LENGTH1, addrlen,
|
||||||
|
level))
|
||||||
|
!= STAT_OK) {
|
||||||
|
/*! close... */
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
readpos = sizeof(recvreply)-1+4;
|
||||||
|
break;
|
||||||
|
case SOCKS5_ADDRTYPE_NAME:
|
||||||
|
/* read 1 byte containing domain name length */
|
||||||
|
if ((result =
|
||||||
|
xiosocks5_recvbytes(xfd, recvbuff+SOCKS5_REPLY_LENGTH1, 1, level))
|
||||||
|
!= STAT_OK) {
|
||||||
|
/*! close... */
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/* read domain name */
|
||||||
|
if ((result =
|
||||||
|
xiosocks5_recvbytes(xfd, recvbuff+SOCKS5_REPLY_LENGTH1+1,
|
||||||
|
recvreply->destaddr[0], level))
|
||||||
|
!= STAT_OK) {
|
||||||
|
/*! close... */
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
readpos = sizeof(recvreply)+recvreply->destaddr[0];
|
||||||
|
addrlen = recvreply->destaddr[0]+1;
|
||||||
|
break;
|
||||||
|
case SOCKS5_ADDRTYPE_IPV6:
|
||||||
|
addrlen = 16; /*!*/
|
||||||
|
if ((result =
|
||||||
|
xiosocks5_recvbytes(xfd, recvbuff+SOCKS5_REPLY_LENGTH1, addrlen,
|
||||||
|
level))
|
||||||
|
== EOF) {
|
||||||
|
/*! close... */
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
readpos = sizeof(recvreply)-1+4;
|
||||||
|
break;
|
||||||
|
default: Error("socks5: undefined address type in answer");
|
||||||
|
addrlen = 0;
|
||||||
|
readpos = sizeof(recvreply)-1;
|
||||||
|
}
|
||||||
|
if ((result =
|
||||||
|
xiosocks5_recvbytes(xfd, recvbuff+readpos, 2, level))
|
||||||
|
!= STAT_OK) {
|
||||||
|
/*! close... */
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Infos(...); */
|
||||||
|
return STAT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int xio_socks5_username_password(int level, struct opt *opts,
|
||||||
|
struct single *xfd) {
|
||||||
|
/*!!! */
|
||||||
|
unsigned char sendbuff[513];
|
||||||
|
unsigned char *pos;
|
||||||
|
char *username = NULL;
|
||||||
|
char *password = NULL;
|
||||||
|
unsigned char recvbuff[2];
|
||||||
|
struct socks5_userpass_reply *reply;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
retropt_string(opts, OPT_SOCKS5_USERNAME, (char **)&username);
|
||||||
|
if (username == NULL) {
|
||||||
|
Error("socks5: username required");
|
||||||
|
return STAT_NORETRY;
|
||||||
|
}
|
||||||
|
retropt_string(opts, OPT_SOCKS5_PASSWORD, (char **)&password);
|
||||||
|
if (password == NULL) {
|
||||||
|
Error("socks5: password required");
|
||||||
|
return STAT_NORETRY;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos = sendbuff;
|
||||||
|
*pos++ = SOCKS5_USERPASS_VERSION;
|
||||||
|
*pos++ = strlen(username);
|
||||||
|
strncpy(pos, username, 255);
|
||||||
|
pos += strlen(username);
|
||||||
|
*pos++ = strlen(password);
|
||||||
|
strncpy(pos, password, 255);
|
||||||
|
pos += strlen(password);
|
||||||
|
|
||||||
|
result =
|
||||||
|
xio_socks5_dialog(level, xfd, sendbuff, pos-sendbuff,
|
||||||
|
recvbuff, 2,
|
||||||
|
"username/password authentication");
|
||||||
|
if (result != STAT_OK) {
|
||||||
|
Msg(level, "socks5 username/password dialog failed");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
Info("socks5 username/password authentication succeeded");
|
||||||
|
reply = (struct socks5_userpass_reply *)recvbuff;
|
||||||
|
if (reply->version != SOCKS5_USERPASS_VERSION) {
|
||||||
|
Msg(level, "socks5 username/password authentication version mismatch");
|
||||||
|
return STAT_NORETRY;
|
||||||
|
}
|
||||||
|
if (reply->status != SOCKS5_REPLY_SUCCESS) {
|
||||||
|
Msg(level, "socks5 username/password authentication failure");
|
||||||
|
return STAT_RETRYLATER;
|
||||||
|
}
|
||||||
|
return STAT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int xio_socks5_dialog(int level, struct single *xfd,
|
||||||
|
unsigned char *sendbuff, size_t sendlen,
|
||||||
|
unsigned char *recvbuff, size_t recvlen,
|
||||||
|
const char *descr /* identifier/method selection */) {
|
||||||
|
int result;
|
||||||
|
|
||||||
|
/* send socks header (target addr+port, +auth) */
|
||||||
|
Info1("sending socks5 %s message", descr);
|
||||||
|
do {
|
||||||
|
result = Write(xfd->fd2, sendbuff, sendlen);
|
||||||
|
} while (result < 0 && errno == EINTR);
|
||||||
|
if (result < 0) {
|
||||||
|
Msg4(level, "write(%d, %p, "F_Zu"): %s",
|
||||||
|
xfd->fd2, sendbuff, sendlen, strerror(errno));
|
||||||
|
if (Close(xfd->fd2) < 0) {
|
||||||
|
Warn2("close(%d): %s", xfd->fd2, strerror(errno));
|
||||||
|
}
|
||||||
|
if (Close(xfd->fd1) < 0) {
|
||||||
|
Warn2("close(%d): %s", xfd->fd1, strerror(errno));
|
||||||
|
}
|
||||||
|
return STAT_RETRYLATER; /* retry complete open cycle */
|
||||||
|
}
|
||||||
|
|
||||||
|
Info2("waiting for socks5 %s reply ("F_Zu" bytes)",
|
||||||
|
descr, recvlen);
|
||||||
|
if ((result =
|
||||||
|
xiosocks5_recvbytes(xfd, recvbuff, recvlen, level))
|
||||||
|
== EOF) {
|
||||||
|
/* we had a problem while reading socks answer */
|
||||||
|
/*! Close(); */
|
||||||
|
return result; /* retry complete open cycle */
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
replyversion = ((struct socks5_version *)recvbuff)->version;
|
||||||
|
Info1("socks5 server reply version: {%u}", replyversion);
|
||||||
|
if (replyversion != SOCKS5_VERSION) {
|
||||||
|
Error1("socks5: server protocol version is %u",
|
||||||
|
replyversion);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* WITH_SOCKS5 */
|
||||||
|
|
107
xio-socks5.h
Normal file
107
xio-socks5.h
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
/* $Id$ */
|
||||||
|
/* Copyright Gerhard Rieger 2004-2007 */
|
||||||
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
|
#ifndef __xio_socks5_h_included
|
||||||
|
#define __xio_socks5_h_included 1
|
||||||
|
|
||||||
|
#define SOCKS5_VERSION 5
|
||||||
|
|
||||||
|
#define SOCKS5_METHOD_NOAUTH 0x00
|
||||||
|
#define SOCKS5_METHOD_GSSAPI 0x01
|
||||||
|
#define SOCKS5_METHOD_USERPASS 0x02
|
||||||
|
#define SOCKS5_METHOD_AVENTAIL 0x86 /*!*/
|
||||||
|
#define SOCKS5_METHOD_NONE 0xff
|
||||||
|
|
||||||
|
#define SOCKS5_COMMAND_CONNECT 0x01
|
||||||
|
#define SOCKS5_COMMAND_BIND 0x02
|
||||||
|
#define SOCKS5_COMMAND_UDPASSOC 0x03
|
||||||
|
|
||||||
|
#define SOCKS5_ADDRTYPE_IPV4 0x01
|
||||||
|
#define SOCKS5_ADDRTYPE_NAME 0x03
|
||||||
|
#define SOCKS5_ADDRTYPE_IPV6 0x04
|
||||||
|
|
||||||
|
#define SOCKS5_REPLY_SUCCESS 0x00
|
||||||
|
#define SOCKS5_REPLY_FAILURE 0x01
|
||||||
|
#define SOCKS5_REPLY_DENIED 0x02
|
||||||
|
#define SOCKS5_REPLY_NETUNREACH 0x03
|
||||||
|
#define SOCKS5_REPLY_HOSTUNREACH 0x04
|
||||||
|
#define SOCKS5_REPLY_REFUSED 0x05
|
||||||
|
#define SOCKS5_REPLY_TTLEXPIRED 0x06
|
||||||
|
#define SOCKS5_REPLY_CMDUNSUPP 0x07
|
||||||
|
#define SOCKS5_REPLY_ADDRUNSUPP 0x08
|
||||||
|
|
||||||
|
#define SOCKS5_USERPASS_VERSION 0x01
|
||||||
|
|
||||||
|
/* just the first byte of server replies */
|
||||||
|
struct socks5_version {
|
||||||
|
uint8_t version;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* the version/method selection message of the client */
|
||||||
|
struct socks5_method {
|
||||||
|
uint8_t version;
|
||||||
|
uint8_t nmethods;
|
||||||
|
uint8_t methods[1]; /* has variable length, see nmethods */
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* the selection message of the server */
|
||||||
|
struct socks5_select {
|
||||||
|
uint8_t version;
|
||||||
|
uint8_t method;
|
||||||
|
} ;
|
||||||
|
#define SOCKS5_SELECT_LENGTH sizeof(struct socks5_select)
|
||||||
|
|
||||||
|
/* the request message */
|
||||||
|
struct socks5_request {
|
||||||
|
uint8_t version;
|
||||||
|
uint8_t command;
|
||||||
|
uint8_t reserved;
|
||||||
|
uint8_t addrtype;
|
||||||
|
uint8_t destaddr[1]; /* has variable length */
|
||||||
|
/*uint16_t destport;*/ /* position depends on length of destaddr */
|
||||||
|
} ;
|
||||||
|
|
||||||
|
/* the request message */
|
||||||
|
struct socks5_reply {
|
||||||
|
uint8_t version;
|
||||||
|
uint8_t reply;
|
||||||
|
uint8_t reserved;
|
||||||
|
uint8_t addrtype;
|
||||||
|
uint8_t destaddr[1]; /* has variable length */
|
||||||
|
/*uint16_t destport;*/ /* position depends on length of destaddr */
|
||||||
|
} ;
|
||||||
|
#define SOCKS5_REPLY_LENGTH1 4 /*!*/ /* the fixed size fields */
|
||||||
|
|
||||||
|
/* the username/password authentication reply */
|
||||||
|
struct socks5_userpass_reply {
|
||||||
|
uint8_t version; /* authentication version, not socks version */
|
||||||
|
uint8_t status;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
extern const struct optdesc opt_socksport;
|
||||||
|
extern const struct optdesc opt_socksuser;
|
||||||
|
#endif
|
||||||
|
extern const struct optdesc opt_socks5_username;
|
||||||
|
extern const struct optdesc opt_socks5_password;
|
||||||
|
|
||||||
|
extern const union xioaddr_desc *xioaddrs_socks5_client[];
|
||||||
|
|
||||||
|
extern int
|
||||||
|
_xioopen_socks5_connect0(struct single *xfd,
|
||||||
|
const char *targetname, const char *targetservice,
|
||||||
|
int level);
|
||||||
|
extern int _xioopen_socks5_connect(struct single *xfd,
|
||||||
|
const char *targetname,
|
||||||
|
const char *targetservice,
|
||||||
|
struct opt *opts,
|
||||||
|
int level);
|
||||||
|
extern int xio_socks5_dialog(int level, struct single *xfd,
|
||||||
|
unsigned char *sendbuff, size_t sendlen,
|
||||||
|
unsigned char *recvbuff, size_t recvlen,
|
||||||
|
const char *descr);
|
||||||
|
extern int xio_socks5_username_password(int level, struct opt *opts,
|
||||||
|
struct single *xfd);
|
||||||
|
|
||||||
|
#endif /* !defined(__xio_socks5_h_included) */
|
70
xio-stdio.c
70
xio-stdio.c
|
@ -1,5 +1,5 @@
|
||||||
/* $Id: xio-stdio.c,v 1.18 2006/12/28 14:07:01 gerhard Exp $ */
|
/* $Id: xio-stdio.c,v 1.18 2006/12/28 14:07:01 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2001-2006 */
|
/* Copyright Gerhard Rieger 2001-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
/* this file contains the source for opening addresses stdio type */
|
/* this file contains the source for opening addresses stdio type */
|
||||||
|
@ -20,49 +20,51 @@ static int xioopen_stdfd(int argc, const char *argv[], struct opt *opts, int xio
|
||||||
/* we specify all option groups that we can imagine for a FD, becasue the
|
/* we specify all option groups that we can imagine for a FD, becasue the
|
||||||
changed parsing mechanism does not allow us to check the type of FD before
|
changed parsing mechanism does not allow us to check the type of FD before
|
||||||
applying the options */
|
applying the options */
|
||||||
const struct addrdesc addr_stdio = { "stdio", 3, xioopen_stdio, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, 0, 0, 0 HELP(NULL) };
|
static const struct xioaddr_endpoint_desc xioaddr_stdio0 = { XIOADDR_SYS, "stdio", 0, XIOBIT_ALL, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, XIOSHUT_NONE, XIOCLOSE_NONE, xioopen_stdio, 0, 0, 0 HELP(NULL) };
|
||||||
const struct addrdesc addr_stdin = { "stdin", 1, xioopen_stdfd, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, 0, 0, 0 HELP(NULL) };
|
static const struct xioaddr_endpoint_desc xioaddr_stdin0 = { XIOADDR_SYS, "stdin", 0, XIOBIT_RDONLY, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, XIOSHUT_NONE, XIOCLOSE_NONE, xioopen_stdfd, 0, 0, 0 HELP(NULL) };
|
||||||
const struct addrdesc addr_stdout = { "stdout", 2, xioopen_stdfd, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, 1, 0, 0 HELP(NULL) };
|
static const struct xioaddr_endpoint_desc xioaddr_stdout0 = { XIOADDR_SYS, "stdout", 0, XIOBIT_WRONLY, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, XIOSHUT_NONE, XIOCLOSE_NONE, xioopen_stdfd, 1, 0, 0 HELP(NULL) };
|
||||||
const struct addrdesc addr_stderr = { "stderr", 2, xioopen_stdfd, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, 2, 0, 0 HELP(NULL) };
|
static const struct xioaddr_endpoint_desc xioaddr_stderr0 = { XIOADDR_SYS, "stderr", 0, XIOBIT_WRONLY, GROUP_FD|GROUP_FIFO|GROUP_CHR|GROUP_BLK|GROUP_FILE|GROUP_SOCKET|GROUP_TERMIOS|GROUP_SOCK_UNIX|GROUP_SOCK_IP|GROUP_IPAPP, XIOSHUT_NONE, XIOCLOSE_NONE, xioopen_stdfd, 2, 0, 0 HELP(NULL) };
|
||||||
|
|
||||||
|
const union xioaddr_desc *xioaddrs_stdio[] = {
|
||||||
|
(union xioaddr_desc *)&xioaddr_stdio0, NULL };
|
||||||
|
const union xioaddr_desc *xioaddrs_stdin[] = {
|
||||||
|
(union xioaddr_desc *)&xioaddr_stdin0, NULL };
|
||||||
|
const union xioaddr_desc *xioaddrs_stdout[] = {
|
||||||
|
(union xioaddr_desc *)&xioaddr_stdout0, NULL };
|
||||||
|
const union xioaddr_desc *xioaddrs_stderr[] = {
|
||||||
|
(union xioaddr_desc *)&xioaddr_stderr0, NULL };
|
||||||
|
|
||||||
/* process a bidirectional "stdio" or "-" argument with options.
|
/* process a bidirectional "stdio" or "-" argument with options.
|
||||||
generate a dual address. */
|
generate a dual address. */
|
||||||
int xioopen_stdio_bi(xiofile_t *sock) {
|
int xioopen_stdio_bi(xiofile_t *sock) {
|
||||||
struct opt *opts1, *opts2, *optspr;
|
struct opt *opts1, *opts2, *optspr;
|
||||||
unsigned int groups1 = addr_stdio.groups, groups2 = addr_stdio.groups;
|
unsigned int groups1 = xioaddr_stdio0.groups, groups2 = xioaddr_stdio0.groups;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if (xioopen_makedual(sock) < 0) {
|
sock->stream.fd1 = 0 /*stdin*/;
|
||||||
return -1;
|
sock->stream.fd2 = 1 /*stdout*/;
|
||||||
}
|
sock->stream.fdtype = FDTYPE_DOUBLE;
|
||||||
|
|
||||||
sock->dual.stream[0]->tag = XIO_TAG_RDONLY;
|
|
||||||
sock->dual.stream[0]->fd = 0 /*stdin*/;
|
|
||||||
sock->dual.stream[1]->tag = XIO_TAG_WRONLY;
|
|
||||||
sock->dual.stream[1]->fd = 1 /*stdout*/;
|
|
||||||
sock->dual.stream[0]->howtoend =
|
|
||||||
sock->dual.stream[1]->howtoend = END_NONE;
|
|
||||||
|
|
||||||
#if WITH_TERMIOS
|
#if WITH_TERMIOS
|
||||||
if (Isatty(sock->dual.stream[0]->fd)) {
|
if (Isatty(sock->stream.fd1)) {
|
||||||
if (Tcgetattr(sock->dual.stream[0]->fd,
|
if (Tcgetattr(sock->stream.fd1,
|
||||||
&sock->dual.stream[0]->savetty)
|
&sock->stream.savetty)
|
||||||
< 0) {
|
< 0) {
|
||||||
Warn2("cannot query current terminal settings on fd %d: %s",
|
Warn2("cannot query current terminal settings on fd %d: %s",
|
||||||
sock->dual.stream[0]->fd, strerror(errno));
|
sock->stream.fd1, strerror(errno));
|
||||||
} else {
|
} else {
|
||||||
sock->dual.stream[0]->ttyvalid = true;
|
sock->stream.ttyvalid = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Isatty(sock->dual.stream[1]->fd)) {
|
if (Isatty(sock->stream.fd2)) {
|
||||||
if (Tcgetattr(sock->dual.stream[1]->fd,
|
if (Tcgetattr(sock->stream.fd2,
|
||||||
&sock->dual.stream[1]->savetty)
|
&sock->stream.savetty)
|
||||||
< 0) {
|
< 0) {
|
||||||
Warn2("cannot query current terminal settings on fd %d: %s",
|
Warn2("cannot query current terminal settings on fd %d: %s",
|
||||||
sock->dual.stream[1]->fd, strerror(errno));
|
|
||||||
|
sock->stream.fd2, strerror(errno));
|
||||||
} else {
|
} else {
|
||||||
sock->dual.stream[1]->ttyvalid = true;
|
sock->stream.ttyvalid = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WITH_TERMIOS */
|
#endif /* WITH_TERMIOS */
|
||||||
|
@ -71,7 +73,7 @@ int xioopen_stdio_bi(xiofile_t *sock) {
|
||||||
applyopts(-1, sock->stream.opts, PH_INIT);
|
applyopts(-1, sock->stream.opts, PH_INIT);
|
||||||
|
|
||||||
/* options here are one-time and one-direction, no second use */
|
/* options here are one-time and one-direction, no second use */
|
||||||
retropt_bool(sock->stream.opts, OPT_IGNOREEOF, &sock->dual.stream[0]->ignoreeof);
|
retropt_bool(sock->stream.opts, OPT_IGNOREEOF, &sock->stream.ignoreeof);
|
||||||
|
|
||||||
/* extract opts that should be applied only once */
|
/* extract opts that should be applied only once */
|
||||||
if ((optspr = copyopts(sock->stream.opts, GROUP_PROCESS)) == NULL) {
|
if ((optspr = copyopts(sock->stream.opts, GROUP_PROCESS)) == NULL) {
|
||||||
|
@ -88,10 +90,10 @@ int xioopen_stdio_bi(xiofile_t *sock) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* apply options to first FD */
|
/* apply options to first FD */
|
||||||
if ((result = applyopts(sock->dual.stream[0]->fd, opts1, PH_ALL)) < 0) {
|
if ((result = applyopts(sock->stream.fd1, opts1, PH_ALL)) < 0) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if ((result = _xio_openlate(sock->dual.stream[0], opts1)) < 0) {
|
if ((result = _xio_openlate(&sock->stream, opts1)) < 0) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,14 +101,14 @@ int xioopen_stdio_bi(xiofile_t *sock) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
/* apply options to second FD */
|
/* apply options to second FD */
|
||||||
if ((result = applyopts(sock->dual.stream[1]->fd, opts2, PH_ALL)) < 0) {
|
if ((result = applyopts(sock->stream.fd2, opts2, PH_ALL)) < 0) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if ((result = _xio_openlate(sock->dual.stream[1], opts2)) < 0) {
|
if ((result = _xio_openlate(&sock->stream, opts2)) < 0) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((result = _xio_openlate(sock->dual.stream[1], optspr)) < 0) {
|
if ((result = _xio_openlate(&sock->stream, optspr)) < 0) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,7 +133,7 @@ static int xioopen_stdio(int argc, const char *argv[], struct opt *opts, int xio
|
||||||
Notice2("using %s for %s",
|
Notice2("using %s for %s",
|
||||||
&("stdin\0\0\0stdout"[rw<<3]),
|
&("stdin\0\0\0stdout"[rw<<3]),
|
||||||
ddirection[rw]);
|
ddirection[rw]);
|
||||||
return xioopen_fd(opts, rw, &fd->stream, rw, dummy2, dummy3);
|
return xioopen_fd(opts, rw, fd, rw, -1, dummy2, dummy3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* wrap around unidirectional xioopensingle and xioopen_fd to automatically determine stdin or stdout fd depending on rw.
|
/* wrap around unidirectional xioopensingle and xioopen_fd to automatically determine stdin or stdout fd depending on rw.
|
||||||
|
@ -145,6 +147,6 @@ static int xioopen_stdfd(int argc, const char *argv[], struct opt *opts, int xio
|
||||||
Notice2("using %s for %s",
|
Notice2("using %s for %s",
|
||||||
&("stdin\0\0\0stdout\0\0stderr"[fd<<3]),
|
&("stdin\0\0\0stdout\0\0stderr"[fd<<3]),
|
||||||
ddirection[rw]);
|
ddirection[rw]);
|
||||||
return xioopen_fd(opts, rw, &xfd->stream, fd, dummy2, dummy3);
|
return xioopen_fd(opts, rw, xfd, fd, -1, dummy2, dummy3);
|
||||||
}
|
}
|
||||||
#endif /* WITH_STDIO */
|
#endif /* WITH_STDIO */
|
||||||
|
|
13
xio-stdio.h
13
xio-stdio.h
|
@ -1,17 +1,16 @@
|
||||||
/* $Id: xio-stdio.h,v 1.5 2006/02/08 19:47:03 gerhard Exp $ */
|
/* $Id: xio-stdio.h,v 1.5.2.1 2006/07/24 19:18:35 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2001-2006 */
|
/* Copyright Gerhard Rieger 2001-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
#ifndef __xio_stdio_h_included
|
#ifndef __xio_stdio_h_included
|
||||||
#define __xio_stdio_h_included 1
|
#define __xio_stdio_h_included 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
extern int xioopen_stdio_bi(xiofile_t *sock);
|
extern int xioopen_stdio_bi(xiofile_t *sock);
|
||||||
|
|
||||||
extern const struct addrdesc addr_stdio;
|
extern const union xioaddr_desc *xioaddrs_stdio[];
|
||||||
extern const struct addrdesc addr_stdin;
|
extern const union xioaddr_desc *xioaddrs_stdin[];
|
||||||
extern const struct addrdesc addr_stdout;
|
extern const union xioaddr_desc *xioaddrs_stdout[];
|
||||||
extern const struct addrdesc addr_stderr;
|
extern const union xioaddr_desc *xioaddrs_stderr[];
|
||||||
|
|
||||||
#endif /* !defined(__xio_stdio_h_included) */
|
#endif /* !defined(__xio_stdio_h_included) */
|
||||||
|
|
12
xio-system.c
12
xio-system.c
|
@ -1,5 +1,5 @@
|
||||||
/* $Id: xio-system.c,v 1.13 2006/03/21 20:53:38 gerhard Exp $ */
|
/* $Id: xio-system.c,v 1.13.2.1 2006/07/24 19:18:36 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2001-2006 */
|
/* Copyright Gerhard Rieger 2001-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
/* this file contains the source for opening addresses of system type */
|
/* this file contains the source for opening addresses of system type */
|
||||||
|
@ -20,8 +20,12 @@ static int xioopen_system(int arg, const char *argv[], struct opt *opts,
|
||||||
int dummy1, int dummy2, int dummy3
|
int dummy1, int dummy2, int dummy3
|
||||||
);
|
);
|
||||||
|
|
||||||
const struct addrdesc addr_system = { "system", 3, xioopen_system, GROUP_FD|GROUP_FORK|GROUP_EXEC|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_TERMIOS|GROUP_FIFO|GROUP_PTY|GROUP_PARENT, 1, 0, 0 HELP(":<shell-command>") };
|
static const struct xioaddr_endpoint_desc xioendpoint_system1 = { XIOADDR_SYS, "system", 1, XIOBIT_ALL, GROUP_FD|GROUP_FORK|GROUP_EXEC|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_TERMIOS|GROUP_FIFO|GROUP_PTY|GROUP_PARENT, XIOSHUT_UNSPEC, XIOCLOSE_UNSPEC, xioopen_system, 1, 0, 0 HELP(":<shell-command>") };
|
||||||
|
|
||||||
|
const union xioaddr_desc *xioaddrs_system[] = {
|
||||||
|
(union xioaddr_desc *)&xioendpoint_system1,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
static int xioopen_system(int argc, const char *argv[], struct opt *opts,
|
static int xioopen_system(int argc, const char *argv[], struct opt *opts,
|
||||||
int xioflags, /* XIO_RDONLY etc. */
|
int xioflags, /* XIO_RDONLY etc. */
|
||||||
|
@ -34,7 +38,7 @@ static int xioopen_system(int argc, const char *argv[], struct opt *opts,
|
||||||
int result;
|
int result;
|
||||||
const char *string = argv[1];
|
const char *string = argv[1];
|
||||||
|
|
||||||
status = _xioopen_foxec(xioflags, &fd->stream, groups, &opts);
|
status = _xioopen_foxec_end(xioflags, &fd->stream, groups, &opts);
|
||||||
if (status < 0) return status;
|
if (status < 0) return status;
|
||||||
if (status == 0) { /* child */
|
if (status == 0) { /* child */
|
||||||
int numleft;
|
int numleft;
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
/* $Id: xio-system.h,v 1.4 2001/11/04 17:19:20 gerhard Exp $ */
|
/* $Id: xio-system.h,v 1.4.2.1 2006/07/24 19:18:38 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2001 */
|
/* Copyright Gerhard Rieger 2001-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
#ifndef __xio_system_h_included
|
#ifndef __xio_system_h_included
|
||||||
#define __xio_system_h_included 1
|
#define __xio_system_h_included 1
|
||||||
|
|
||||||
extern const struct addrdesc addr_system;
|
extern const union xioaddr_desc *xioaddrs_system[];
|
||||||
|
|
||||||
#endif /* !defined(__xio_system_h_included) */
|
#endif /* !defined(__xio_system_h_included) */
|
||||||
|
|
22
xio-tcp.c
22
xio-tcp.c
|
@ -1,5 +1,5 @@
|
||||||
/* $Id: xio-tcp.c,v 1.24 2006/07/13 06:48:47 gerhard Exp $ */
|
/* $Id: xio-tcp.c,v 1.24.2.1 2006/07/24 19:18:39 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2001-2006 */
|
/* Copyright Gerhard Rieger 2001-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
/* this file contains the source for TCP related functions and options */
|
/* this file contains the source for TCP related functions and options */
|
||||||
|
@ -17,23 +17,29 @@
|
||||||
/****** TCP addresses ******/
|
/****** TCP addresses ******/
|
||||||
|
|
||||||
#if WITH_IP4 || WITH_IP6
|
#if WITH_IP4 || WITH_IP6
|
||||||
const struct addrdesc addr_tcp_connect = { "tcp-connect", 1+XIO_RDWR, xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_CHILD|GROUP_RETRY, SOCK_STREAM, IPPROTO_TCP, PF_UNSPEC HELP(":<host>:<port>") };
|
static const struct xioaddr_endpoint_desc xioendpoint_tcp_connect2 = { XIOADDR_SYS, "tcp-connect", 2, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_CHILD|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_ipapp_connect, SOCK_STREAM, IPPROTO_TCP, PF_UNSPEC HELP(":<host>:<port>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_tcp_connect[] = { (union xioaddr_desc *)&xioendpoint_tcp_connect2, NULL };
|
||||||
#if WITH_LISTEN
|
#if WITH_LISTEN
|
||||||
const struct addrdesc addr_tcp_listen = { "tcp-listen", 1+XIO_RDWR, xioopen_ipapp_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE|GROUP_RETRY, SOCK_STREAM, IPPROTO_TCP, PF_UNSPEC HELP(":<port>") };
|
static const struct xioaddr_endpoint_desc xioendpoint_tcp_listen1 = { XIOADDR_SYS, "tcp-listen", 1, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_ipapp_listen, SOCK_STREAM, IPPROTO_TCP, PF_UNSPEC HELP(":<port>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_tcp_listen[] = { (union xioaddr_desc *)&xioendpoint_tcp_listen1, NULL };
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if WITH_IP4
|
#if WITH_IP4
|
||||||
const struct addrdesc addr_tcp4_connect = { "tcp4-connect", 1+XIO_RDWR, xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_TCP|GROUP_CHILD|GROUP_RETRY, SOCK_STREAM, IPPROTO_TCP, PF_INET HELP(":<host>:<port>") };
|
static const struct xioaddr_endpoint_desc xioendpoint_tcp4_connect2 = { XIOADDR_SYS, "tcp4-connect", 2, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_TCP|GROUP_CHILD|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_ipapp_connect, SOCK_STREAM, IPPROTO_TCP, PF_INET HELP(":<host>:<port>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_tcp4_connect[] = { (union xioaddr_desc *)&xioendpoint_tcp4_connect2, NULL };
|
||||||
#if WITH_LISTEN
|
#if WITH_LISTEN
|
||||||
const struct addrdesc addr_tcp4_listen = { "tcp4-listen", 1+XIO_RDWR, xioopen_ipapp_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_TCP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE|GROUP_RETRY, SOCK_STREAM, IPPROTO_TCP, PF_INET HELP(":<port>") };
|
static const struct xioaddr_endpoint_desc xioendpoint_tcp4_listen1 = { XIOADDR_SYS, "tcp4-listen", 1, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_TCP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_ipapp_listen, SOCK_STREAM, IPPROTO_TCP, PF_INET HELP(":<port>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_tcp4_listen[] = { (union xioaddr_desc *)&xioendpoint_tcp4_listen1, NULL };
|
||||||
#endif
|
#endif
|
||||||
#endif /* WITH_IP4 */
|
#endif /* WITH_IP4 */
|
||||||
|
|
||||||
#if WITH_IP6
|
#if WITH_IP6
|
||||||
const struct addrdesc addr_tcp6_connect = { "tcp6-connect", 1+XIO_RDWR, xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_CHILD|GROUP_RETRY, SOCK_STREAM, IPPROTO_TCP, PF_INET6 HELP(":<host>:<port>") };
|
static const struct xioaddr_endpoint_desc xioendpoint_tcp6_connect2 = { XIOADDR_SYS, "tcp6-connect", 2, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_CHILD|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_ipapp_connect, SOCK_STREAM, IPPROTO_TCP, PF_INET6 HELP(":<host>:<port>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_tcp6_connect[] = {(union xioaddr_desc *) &xioendpoint_tcp6_connect2, NULL };
|
||||||
#if WITH_LISTEN
|
#if WITH_LISTEN
|
||||||
const struct addrdesc addr_tcp6_listen = { "tcp6-listen", 1+XIO_RDWR, xioopen_ipapp_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE|GROUP_RETRY, SOCK_STREAM, IPPROTO_TCP, PF_INET6 HELP(":<port>") };
|
static const struct xioaddr_endpoint_desc xioendpoint_tcp6_listen1 = { XIOADDR_SYS, "tcp6-listen", 1, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_TCP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_ipapp_listen, SOCK_STREAM, IPPROTO_TCP, PF_INET6 HELP(":<port>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_tcp6_listen[] = { (union xioaddr_desc *)&xioendpoint_tcp6_listen1, NULL };
|
||||||
#endif
|
#endif
|
||||||
#endif /* WITH_IP6 */
|
#endif /* WITH_IP6 */
|
||||||
|
|
||||||
|
|
16
xio-tcp.h
16
xio-tcp.h
|
@ -1,16 +1,16 @@
|
||||||
/* $Id: xio-tcp.h,v 1.12 2006/03/21 20:59:34 gerhard Exp $ */
|
/* $Id: xio-tcp.h,v 1.12.2.1 2006/07/24 19:18:42 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2001-2006 */
|
/* Copyright Gerhard Rieger 2001-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
#ifndef __xio_tcp_h_included
|
#ifndef __xio_tcp_h_included
|
||||||
#define __xio_tcp_h_included 1
|
#define __xio_tcp_h_included 1
|
||||||
|
|
||||||
extern const struct addrdesc addr_tcp_connect;
|
extern const union xioaddr_desc *xioaddrs_tcp_connect[];
|
||||||
extern const struct addrdesc addr_tcp_listen;
|
extern const union xioaddr_desc *xioaddrs_tcp_listen[];
|
||||||
extern const struct addrdesc addr_tcp4_connect;
|
extern const union xioaddr_desc *xioaddrs_tcp4_connect[];
|
||||||
extern const struct addrdesc addr_tcp4_listen;
|
extern const union xioaddr_desc *xioaddrs_tcp4_listen[];
|
||||||
extern const struct addrdesc addr_tcp6_connect;
|
extern const union xioaddr_desc *xioaddrs_tcp6_connect[];
|
||||||
extern const struct addrdesc addr_tcp6_listen;
|
extern const union xioaddr_desc *xioaddrs_tcp6_listen[];
|
||||||
|
|
||||||
extern const struct optdesc opt_tcp_nodelay;
|
extern const struct optdesc opt_tcp_nodelay;
|
||||||
extern const struct optdesc opt_tcp_maxseg;
|
extern const struct optdesc opt_tcp_maxseg;
|
||||||
|
|
|
@ -131,11 +131,11 @@ int xio_tcpwrap_check(xiosingle_t *xfd, union sockaddr_union *us,
|
||||||
Warn1("inet_ntop(): %s", strerror(errno));
|
Warn1("inet_ntop(): %s", strerror(errno));
|
||||||
}
|
}
|
||||||
Debug7("request_init(%p, RQ_FILE, %d, RQ_CLIENT_SIN, {%s:%u}, RQ_SERVER_SIN, {%s:%u}, RQ_DAEMON, \"%s\", 0",
|
Debug7("request_init(%p, RQ_FILE, %d, RQ_CLIENT_SIN, {%s:%u}, RQ_SERVER_SIN, {%s:%u}, RQ_DAEMON, \"%s\", 0",
|
||||||
&ri, xfd->fd, clientaddr,
|
&ri, xfd->fd1, clientaddr,
|
||||||
ntohs(((struct sockaddr_in *)them)->sin_port),
|
ntohs(((struct sockaddr_in *)them)->sin_port),
|
||||||
serveraddr, ntohs(us->ip4.sin_port),
|
serveraddr, ntohs(us->ip4.sin_port),
|
||||||
xfd->para.socket.ip.libwrapname?xfd->para.socket.ip.libwrapname:(char *)diag_get_string('p'));
|
xfd->para.socket.ip.libwrapname?xfd->para.socket.ip.libwrapname:(char *)diag_get_string('p'));
|
||||||
request_init(&ri, RQ_FILE, xfd->fd,
|
request_init(&ri, RQ_FILE, xfd->fd1,
|
||||||
RQ_CLIENT_SIN, them,
|
RQ_CLIENT_SIN, them,
|
||||||
RQ_SERVER_SIN, &us->soa,
|
RQ_SERVER_SIN, &us->soa,
|
||||||
RQ_DAEMON, xfd->para.socket.ip.libwrapname?xfd->para.socket.ip.libwrapname:(char *)diag_get_string('p'), 0);
|
RQ_DAEMON, xfd->para.socket.ip.libwrapname?xfd->para.socket.ip.libwrapname:(char *)diag_get_string('p'), 0);
|
||||||
|
|
228
xio-test.c
Normal file
228
xio-test.c
Normal file
|
@ -0,0 +1,228 @@
|
||||||
|
/* $Id$ */
|
||||||
|
/* Copyright Gerhard Rieger 2007 */
|
||||||
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
|
/* this file contains the source for an intermediate test address that appends
|
||||||
|
'>' to every block transferred from right to left, and '<' in the other
|
||||||
|
direction */
|
||||||
|
|
||||||
|
#include "xiosysincludes.h"
|
||||||
|
#include "xioopen.h"
|
||||||
|
|
||||||
|
#include "xio-test.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if WITH_TEST
|
||||||
|
|
||||||
|
static int xioopen_test(int argc, const char *argv[], struct opt *opts,
|
||||||
|
int xioflags, xiofile_t *xxfd,
|
||||||
|
unsigned groups, int dummy1, int dummy2,
|
||||||
|
int dummy3);
|
||||||
|
static int xioopen_testuni(int argc, const char *argv[], struct opt *opts,
|
||||||
|
int xioflags, xiofile_t *xxfd,
|
||||||
|
unsigned groups, int dummy1, int dummy2,
|
||||||
|
int dummy3);
|
||||||
|
static int xioopen_testrev(int argc, const char *argv[], struct opt *opts,
|
||||||
|
int xioflags, xiofile_t *xxfd,
|
||||||
|
unsigned groups, int dummy1, int dummy2,
|
||||||
|
int dummy3);
|
||||||
|
|
||||||
|
static const struct xioaddr_inter_desc xiointer_test0ro = { XIOADDR_PROT, "test", 0, XIOBIT_RDONLY, 0/*groups*/, XIOSHUT_CLOSE, XIOCLOSE_NONE, xioopen_test, 0, 0, 0, XIOBIT_WRONLY HELP("") };
|
||||||
|
static const struct xioaddr_inter_desc xiointer_test0wo = { XIOADDR_PROT, "test", 0, XIOBIT_WRONLY, 0/*groups*/, XIOSHUT_CLOSE, XIOCLOSE_NONE, xioopen_test, 0, 0, 0, XIOBIT_RDONLY HELP("") };
|
||||||
|
static const struct xioaddr_inter_desc xiointer_test0rw = { XIOADDR_PROT, "test", 0, XIOBIT_RDWR, 0/*groups*/, XIOSHUT_CLOSE, XIOCLOSE_NONE, xioopen_test, 0, 0, 0, XIOBIT_RDWR HELP("") };
|
||||||
|
|
||||||
|
const union xioaddr_desc *xioaddrs_test[] = {
|
||||||
|
(union xioaddr_desc *)&xiointer_test0ro,
|
||||||
|
(union xioaddr_desc *)&xiointer_test0wo,
|
||||||
|
(union xioaddr_desc *)&xiointer_test0rw,
|
||||||
|
NULL };
|
||||||
|
|
||||||
|
|
||||||
|
static const struct xioaddr_inter_desc xiointer_testuni = { XIOADDR_PROT, "testuni", 0, XIOBIT_WRONLY, 0/*groups*/, XIOSHUT_CLOSE, XIOCLOSE_NONE, xioopen_testuni, 0, 0, 0, XIOBIT_RDONLY HELP("") };
|
||||||
|
|
||||||
|
const union xioaddr_desc *xioaddrs_testuni[] = {
|
||||||
|
(union xioaddr_desc *)&xiointer_testuni,
|
||||||
|
NULL };
|
||||||
|
|
||||||
|
|
||||||
|
static const struct xioaddr_inter_desc xiointer_testrev = { XIOADDR_PROT, "testrev", 0, XIOBIT_WRONLY, 0/*groups*/, XIOSHUT_CLOSE, XIOCLOSE_NONE, xioopen_testrev, 0, 0, 0, XIOBIT_RDONLY HELP("") };
|
||||||
|
|
||||||
|
const union xioaddr_desc *xioaddrs_testrev[] = {
|
||||||
|
(union xioaddr_desc *)&xiointer_testrev,
|
||||||
|
NULL };
|
||||||
|
|
||||||
|
static int xioopen_test(int argc, const char *argv[], struct opt *opts,
|
||||||
|
int xioflags, xiofile_t *xxfd,
|
||||||
|
unsigned groups, int dummy, int dummy2,
|
||||||
|
int dummy3) {
|
||||||
|
struct single *xfd = &xxfd->stream;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
assert(argc == 1);
|
||||||
|
assert(!(xfd->fd1 < 0 && xfd->fd2 < 0));
|
||||||
|
|
||||||
|
applyopts(-1, opts, PH_INIT);
|
||||||
|
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||||
|
|
||||||
|
Notice("opening TEST");
|
||||||
|
xfd->dtype = XIODATA_TEST;
|
||||||
|
applyopts(xfd->fd1, opts, PH_ALL);
|
||||||
|
if ((result = _xio_openlate(xfd, opts)) < 0)
|
||||||
|
return result;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int xioopen_testuni(int argc, const char *argv[], struct opt *opts,
|
||||||
|
int xioflags, xiofile_t *xxfd,
|
||||||
|
unsigned groups, int dummy, int dummy2,
|
||||||
|
int dummy3) {
|
||||||
|
struct single *xfd = &xxfd->stream;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
assert(argc == 1);
|
||||||
|
assert(!(xfd->fd1 < 0 && xfd->fd2 < 0));
|
||||||
|
|
||||||
|
applyopts(-1, opts, PH_INIT);
|
||||||
|
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||||
|
|
||||||
|
Notice("opening TESTUNI");
|
||||||
|
xfd->dtype = XIODATA_TESTUNI;
|
||||||
|
applyopts(xfd->fd1, opts, PH_ALL);
|
||||||
|
if ((result = _xio_openlate(xfd, opts)) < 0)
|
||||||
|
return result;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int xioopen_testrev(int argc, const char *argv[], struct opt *opts,
|
||||||
|
int xioflags, xiofile_t *xxfd,
|
||||||
|
unsigned groups, int dummy, int dummy2,
|
||||||
|
int dummy3) {
|
||||||
|
struct single *xfd = &xxfd->stream;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
assert(argc == 1);
|
||||||
|
assert(!(xfd->fd1 < 0 && xfd->fd2 < 0));
|
||||||
|
|
||||||
|
applyopts(-1, opts, PH_INIT);
|
||||||
|
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||||
|
|
||||||
|
Notice("opening TESTREV");
|
||||||
|
xfd->dtype = XIODATA_TESTREV;
|
||||||
|
applyopts(xfd->fd1, opts, PH_ALL);
|
||||||
|
if ((result = _xio_openlate(xfd, opts)) < 0)
|
||||||
|
return result;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t xioread_test(struct single *sfd, void *buff, size_t bufsiz) {
|
||||||
|
int fd = sfd->fd1;
|
||||||
|
ssize_t bytes;
|
||||||
|
int _errno;
|
||||||
|
|
||||||
|
do {
|
||||||
|
bytes = Read(fd, buff, bufsiz-1);
|
||||||
|
} while (bytes < 0 && errno == EINTR);
|
||||||
|
if (bytes < 0) {
|
||||||
|
_errno = errno;
|
||||||
|
switch (_errno) {
|
||||||
|
case EPIPE: case ECONNRESET:
|
||||||
|
Warn4("read(%d, %p, "F_Zu"): %s",
|
||||||
|
fd, buff, bufsiz-1, strerror(_errno));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Error4("read(%d, %p, "F_Zu"): %s",
|
||||||
|
fd, buff, bufsiz-1, strerror(_errno));
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (bytes == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
((char *)buff)[bytes] = '<';
|
||||||
|
return bytes+1;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t xiowrite_test(struct single *sfd, const void *buff, size_t bytes) {
|
||||||
|
int fd = ((sfd->fdtype==FDTYPE_DOUBLE)?sfd->fd2:sfd->fd1);
|
||||||
|
void *buff1;
|
||||||
|
ssize_t writt;
|
||||||
|
int _errno;
|
||||||
|
|
||||||
|
if ((buff1 = Malloc(bytes+1)) == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(buff1, buff, bytes);
|
||||||
|
((char *)buff1)[bytes] = '>';
|
||||||
|
do {
|
||||||
|
writt = Write(fd, buff1, bytes+1);
|
||||||
|
} while (writt < 0 && errno == EINTR);
|
||||||
|
if (writt < 0) {
|
||||||
|
_errno = errno;
|
||||||
|
switch (_errno) {
|
||||||
|
case EPIPE:
|
||||||
|
case ECONNRESET:
|
||||||
|
if (sfd->cool_write) {
|
||||||
|
Notice4("write(%d, %p, "F_Zu"): %s",
|
||||||
|
fd, buff1, bytes+1, strerror(_errno));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*PASSTHROUGH*/
|
||||||
|
default:
|
||||||
|
Error4("write(%d, %p, "F_Zu"): %s",
|
||||||
|
fd, buff1, bytes+1, strerror(_errno));
|
||||||
|
}
|
||||||
|
errno = _errno;
|
||||||
|
free(buff1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((size_t)writt < bytes) {
|
||||||
|
Warn2("write() only wrote "F_Zu" of "F_Zu" bytes",
|
||||||
|
writt, bytes+1);
|
||||||
|
}
|
||||||
|
free(buff1);
|
||||||
|
return writt;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t xiowrite_testrev(struct single *sfd, const void *buff, size_t bytes) {
|
||||||
|
int fd = ((sfd->fdtype==FDTYPE_DOUBLE)?sfd->fd2:sfd->fd1);
|
||||||
|
void *buff1;
|
||||||
|
ssize_t writt;
|
||||||
|
int _errno;
|
||||||
|
|
||||||
|
if ((buff1 = Malloc(bytes+1)) == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(buff1, buff, bytes);
|
||||||
|
((char *)buff1)[bytes] = '<';
|
||||||
|
do {
|
||||||
|
writt = Write(fd, buff1, bytes+1);
|
||||||
|
} while (writt < 0 && errno == EINTR);
|
||||||
|
if (writt < 0) {
|
||||||
|
_errno = errno;
|
||||||
|
switch (_errno) {
|
||||||
|
case EPIPE:
|
||||||
|
case ECONNRESET:
|
||||||
|
if (sfd->cool_write) {
|
||||||
|
Notice4("write(%d, %p, "F_Zu"): %s",
|
||||||
|
fd, buff1, bytes+1, strerror(_errno));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*PASSTHROUGH*/
|
||||||
|
default:
|
||||||
|
Error4("write(%d, %p, "F_Zu"): %s",
|
||||||
|
fd, buff1, bytes+1, strerror(_errno));
|
||||||
|
}
|
||||||
|
errno = _errno;
|
||||||
|
free(buff1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((size_t)writt < bytes) {
|
||||||
|
Warn2("write() only wrote "F_Zu" of "F_Zu" bytes",
|
||||||
|
writt, bytes+1);
|
||||||
|
}
|
||||||
|
free(buff1);
|
||||||
|
return writt;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* WITH_TEST */
|
||||||
|
|
16
xio-test.h
Normal file
16
xio-test.h
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
/* $Id$ */
|
||||||
|
/* Copyright Gerhard Rieger 2007 */
|
||||||
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
|
#ifndef __xio_test_h_included
|
||||||
|
#define __xio_test_h_included 1
|
||||||
|
|
||||||
|
extern const union xioaddr_desc *xioaddrs_test[];
|
||||||
|
extern const union xioaddr_desc *xioaddrs_testuni[];
|
||||||
|
extern const union xioaddr_desc *xioaddrs_testrev[];
|
||||||
|
|
||||||
|
extern size_t xioread_test(struct single *sfd, void *buff, size_t bufsiz);
|
||||||
|
extern size_t xiowrite_test(struct single *sfd, const void *buff, size_t bytes);
|
||||||
|
extern size_t xiowrite_testrev(struct single *sfd, const void *buff, size_t bytes);
|
||||||
|
|
||||||
|
#endif /* !defined(__xio_test_h_included) */
|
24
xio-tun.c
24
xio-tun.c
|
@ -46,7 +46,13 @@ const struct optdesc opt_iff_automedia = { "iff-automedia", "automedia", O
|
||||||
const struct optdesc opt_route = { "route", NULL, OPT_ROUTE, GROUP_INTERFACE, PH_INIT, TYPE_STRING, OFUNC_SPEC };
|
const struct optdesc opt_route = { "route", NULL, OPT_ROUTE, GROUP_INTERFACE, PH_INIT, TYPE_STRING, OFUNC_SPEC };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const struct addrdesc xioaddr_tun = { "tun", 3, xioopen_tun, GROUP_FD|GROUP_CHR|GROUP_NAMED|GROUP_OPEN|GROUP_TUN, 0, 0, 0 HELP(":<ip-addr>/<bits>") };
|
static const struct xioaddr_endpoint_desc xioendpoint_tun1 = { XIOADDR_SYS, "tun", 1, XIOBIT_ALL, GROUP_FD|GROUP_CHR|GROUP_NAMED|GROUP_OPEN|GROUP_TUN, XIOSHUT_CLOSE, XIOCLOSE_NONE, xioopen_tun, 0, 0, 0 HELP(":<ip-addr>/<bits>") };
|
||||||
|
|
||||||
|
const union xioaddr_desc *xioaddrs_tun[] = {
|
||||||
|
(union xioaddr_desc *)&xioendpoint_tun1,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
// "if-name"=tun3
|
// "if-name"=tun3
|
||||||
// "route"=address/netmask
|
// "route"=address/netmask
|
||||||
// "ip6-route"=address/netmask
|
// "ip6-route"=address/netmask
|
||||||
|
@ -101,7 +107,7 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl
|
||||||
Notice("creating tunnel network interface");
|
Notice("creating tunnel network interface");
|
||||||
if ((result = _xioopen_open(tundevice, rw, opts)) < 0)
|
if ((result = _xioopen_open(tundevice, rw, opts)) < 0)
|
||||||
return result;
|
return result;
|
||||||
xfd->stream.fd = result;
|
xfd->stream.fd1 = result;
|
||||||
|
|
||||||
/* prepare configuration of the new network interface */
|
/* prepare configuration of the new network interface */
|
||||||
memset(&ifr, 0,sizeof(ifr));
|
memset(&ifr, 0,sizeof(ifr));
|
||||||
|
@ -132,10 +138,10 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Ioctl(xfd->stream.fd, TUNSETIFF, &ifr) < 0) {
|
if (Ioctl(xfd->stream.fd1, TUNSETIFF, &ifr) < 0) {
|
||||||
Error3("ioctl(%d, TUNSETIFF, {\"%s\"}: %s",
|
Error3("ioctl(%d, TUNSETIFF, {\"%s\"}: %s",
|
||||||
xfd->stream.fd, ifr.ifr_name, strerror(errno));
|
xfd->stream.fd1, ifr.ifr_name, strerror(errno));
|
||||||
Close(xfd->stream.fd);
|
Close(xfd->stream.fd1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===================== setting interface properties =====================*/
|
/*===================== setting interface properties =====================*/
|
||||||
|
@ -143,7 +149,7 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl
|
||||||
/* we seem to need a socket for manipulating the interface */
|
/* we seem to need a socket for manipulating the interface */
|
||||||
if ((sockfd = Socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
|
if ((sockfd = Socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
|
||||||
Error1("socket(PF_INET, SOCK_DGRAM, 0): %s", strerror(errno));
|
Error1("socket(PF_INET, SOCK_DGRAM, 0): %s", strerror(errno));
|
||||||
sockfd = xfd->stream.fd; /* desparate fallback attempt */
|
sockfd = xfd->stream.fd1; /* desparate fallback attempt */
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------- setting interface address and netmask ------------*/
|
/*--------------------- setting interface address and netmask ------------*/
|
||||||
|
@ -195,10 +201,10 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl
|
||||||
#if LATER
|
#if LATER
|
||||||
applyopts_named(tundevice, opts, PH_FD);
|
applyopts_named(tundevice, opts, PH_FD);
|
||||||
#endif
|
#endif
|
||||||
applyopts(xfd->stream.fd, opts, PH_FD);
|
applyopts(xfd->stream.fd1, opts, PH_FD);
|
||||||
applyopts_cloexec(xfd->stream.fd, opts);
|
applyopts_cloexec(xfd->stream.fd1, opts);
|
||||||
|
|
||||||
applyopts_fchown(xfd->stream.fd, opts);
|
applyopts_fchown(xfd->stream.fd1, opts);
|
||||||
|
|
||||||
if ((result = _xio_openlate(&xfd->stream, opts)) < 0)
|
if ((result = _xio_openlate(&xfd->stream, opts)) < 0)
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -28,6 +28,6 @@ extern const struct optdesc opt_iff_portsel;
|
||||||
extern const struct optdesc opt_iff_automedia;
|
extern const struct optdesc opt_iff_automedia;
|
||||||
/*extern const struct optdesc opt_iff_dynamic;*/
|
/*extern const struct optdesc opt_iff_dynamic;*/
|
||||||
|
|
||||||
extern const struct addrdesc xioaddr_tun;
|
extern const union xioaddr_desc *xioaddrs_tun[];
|
||||||
|
|
||||||
#endif /* !defined(__xio_tun_h_included) */
|
#endif /* !defined(__xio_tun_h_included) */
|
||||||
|
|
110
xio-udp.c
110
xio-udp.c
|
@ -35,42 +35,59 @@ static
|
||||||
int xioopen_udp_recv(int argc, const char *argv[], struct opt *opts,
|
int xioopen_udp_recv(int argc, const char *argv[], struct opt *opts,
|
||||||
int xioflags, xiofile_t *xfd, unsigned groups,
|
int xioflags, xiofile_t *xfd, unsigned groups,
|
||||||
int pf, int socktype, int ipproto);
|
int pf, int socktype, int ipproto);
|
||||||
|
|
||||||
static
|
static
|
||||||
int _xioopen_udp_sendto(const char *hostname, const char *servname,
|
int _xioopen_udp_sendto(const char *hostname, const char *servname,
|
||||||
struct opt *opts,
|
struct opt *opts,
|
||||||
int xioflags, xiofile_t *xxfd, unsigned groups,
|
int xioflags, xiofile_t *xxfd, unsigned groups,
|
||||||
int pf, int socktype, int ipproto);
|
int pf, int socktype, int ipproto);
|
||||||
|
|
||||||
const struct addrdesc addr_udp_connect = { "udp-connect", 3, xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP, SOCK_DGRAM, IPPROTO_UDP, PF_UNSPEC HELP(":<host>:<port>") };
|
static const struct xioaddr_endpoint_desc xioaddr_udp_connect2 = { XIOADDR_SYS, "udp-connect", 2, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_ipapp_connect, SOCK_DGRAM, IPPROTO_UDP, PF_UNSPEC HELP(":<host>:<port>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_udp_connect[] = { (union xioaddr_desc *)&xioaddr_udp_connect2, NULL };
|
||||||
#if WITH_LISTEN
|
#if WITH_LISTEN
|
||||||
const struct addrdesc addr_udp_listen = { "udp-listen", 3, xioopen_ipdgram_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE, PF_UNSPEC, IPPROTO_UDP, PF_UNSPEC HELP(":<port>") };
|
static const struct xioaddr_endpoint_desc xioaddr_udp_listen1 = { XIOADDR_SYS, "udp-listen", 1, XIOBIT_RDONLY|XIO_RDWR, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_ipdgram_listen, PF_UNSPEC, IPPROTO_UDP, PF_UNSPEC HELP(":<port>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_udp_listen[] = { (union xioaddr_desc *)&xioaddr_udp_listen1, NULL };
|
||||||
#endif /* WITH_LISTEN */
|
#endif /* WITH_LISTEN */
|
||||||
const struct addrdesc addr_udp_sendto = { "udp-sendto", 3, xioopen_udp_sendto, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP, PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP HELP(":<host>:<port>") };
|
static const struct xioaddr_endpoint_desc xioaddr_udp_sendto2 = { XIOADDR_SYS, "udp-sendto", 2, XIOBIT_WRONLY|XIOBIT_RDWR, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_udp_sendto, PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP HELP(":<host>:<port>") };
|
||||||
const struct addrdesc addr_udp_recvfrom = { "udp-recvfrom", 3, xioopen_udp_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_CHILD|GROUP_RANGE, PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP HELP(":<port>") };
|
const union xioaddr_desc *xioaddrs_udp_sendto[] = { (union xioaddr_desc *)&xioaddr_udp_sendto2, NULL };
|
||||||
const struct addrdesc addr_udp_recv = { "udp-recv", 1, xioopen_udp_recv, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_RANGE, PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP HELP(":<port>") };
|
static const struct xioaddr_endpoint_desc xioaddr_udp_recvfrom1 = { XIOADDR_SYS, "udp-recvfrom", 1, XIOBIT_RDONLY|XIOBIT_RDWR, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_CHILD|GROUP_RANGE, XIOSHUT_NONE, XIOCLOSE_NONE, xioopen_udp_recvfrom, PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP HELP(":<port>") };
|
||||||
const struct addrdesc addr_udp_datagram = { "udp-datagram", 3, xioopen_udp_datagram, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_RANGE, PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP HELP(":<host>:<port>") };
|
const union xioaddr_desc *xioaddrs_udp_recvfrom[] = { (union xioaddr_desc *)&xioaddr_udp_recvfrom1, NULL };
|
||||||
|
static const struct xioaddr_endpoint_desc xioaddr_udp_recv1 = { XIOADDR_SYS, "udp-recv", 1, XIOBIT_RDONLY, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_RANGE, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_udp_recv, PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP HELP(":<port>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_udp_recv[] = { (union xioaddr_desc *)&xioaddr_udp_recv1, NULL };
|
||||||
|
static const struct xioaddr_endpoint_desc xioaddr_udp_datagram2 = { XIOADDR_SYS, "udp-datagram", 2, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_RANGE, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_udp_datagram, PF_UNSPEC, SOCK_DGRAM, IPPROTO_UDP HELP(":<host>:<port>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_udp_datagram[] = { (union xioaddr_desc *)&xioaddr_udp_datagram2, NULL };
|
||||||
|
|
||||||
#if WITH_IP4
|
#if WITH_IP4
|
||||||
const struct addrdesc addr_udp4_connect = { "udp4-connect", 3, xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP, SOCK_DGRAM, IPPROTO_UDP, PF_INET HELP(":<host>:<port>") };
|
static const struct xioaddr_endpoint_desc xioaddr_udp4_connect2 = { XIOADDR_SYS, "udp4-connect", 2, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_ipapp_connect, SOCK_DGRAM, IPPROTO_UDP, PF_INET HELP(":<host>:<port>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_udp4_connect[] = { (union xioaddr_desc *)&xioaddr_udp4_connect2, NULL };
|
||||||
#if WITH_LISTEN
|
#if WITH_LISTEN
|
||||||
const struct addrdesc addr_udp4_listen = { "udp4-listen", 3, xioopen_ipdgram_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE, PF_INET, IPPROTO_UDP, PF_INET HELP(":<port>") };
|
static const struct xioaddr_endpoint_desc xioaddr_udp4_listen1 = { XIOADDR_SYS, "udp4-listen", 1, XIOBIT_RDONLY|XIOBIT_RDWR, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_ipdgram_listen, PF_INET, IPPROTO_UDP, PF_INET HELP(":<port>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_udp4_listen[] = { (union xioaddr_desc *)&xioaddr_udp4_listen1, NULL };
|
||||||
#endif /* WITH_LISTEN */
|
#endif /* WITH_LISTEN */
|
||||||
const struct addrdesc addr_udp4_sendto = { "udp4-sendto", 3, xioopen_udp_sendto, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP, PF_INET, SOCK_DGRAM, IPPROTO_UDP HELP(":<host>:<port>") };
|
static const struct xioaddr_endpoint_desc xioaddr_udp4_sendto2 = { XIOADDR_SYS, "udp4-sendto", 2, XIOBIT_WRONLY|XIOBIT_RDWR, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_udp_sendto, PF_INET, SOCK_DGRAM, IPPROTO_UDP HELP(":<host>:<port>") };
|
||||||
const struct addrdesc addr_udp4_datagram = { "udp4-datagram",3, xioopen_udp_datagram, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP|GROUP_RANGE, PF_INET, SOCK_DGRAM, IPPROTO_UDP HELP(":<remote-address>:<port>") };
|
const union xioaddr_desc *xioaddrs_udp4_sendto[] = { (union xioaddr_desc *)&xioaddr_udp4_sendto2, NULL };
|
||||||
const struct addrdesc addr_udp4_recvfrom= { "udp4-recvfrom", 3, xioopen_udp_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP|GROUP_CHILD|GROUP_RANGE, PF_INET, SOCK_DGRAM, IPPROTO_UDP HELP(":<host>:<port>") };
|
static const struct xioaddr_endpoint_desc xioaddr_udp4_datagram2= { XIOADDR_SYS, "udp4-datagram",2, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_udp_datagram, PF_INET, SOCK_DGRAM, IPPROTO_UDP HELP(":<host>:<port>") };
|
||||||
const struct addrdesc addr_udp4_recv = { "udp4-recv", 1, xioopen_udp_recv, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP|GROUP_RANGE, PF_INET, SOCK_DGRAM, IPPROTO_UDP HELP(":<port>") };
|
const union xioaddr_desc *xioaddrs_udp4_datagram[] = { (union xioaddr_desc *)&xioaddr_udp4_datagram2, NULL };
|
||||||
|
static const struct xioaddr_endpoint_desc xioaddr_udp4_recvfrom1= { XIOADDR_SYS, "udp4-recvfrom",1, XIOBIT_RDONLY|XIOBIT_RDWR, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP|GROUP_CHILD|GROUP_RANGE, XIOSHUT_NONE, XIOCLOSE_NONE, xioopen_udp_recvfrom, PF_INET, SOCK_DGRAM, IPPROTO_UDP HELP(":<host>:<port>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_udp4_recvfrom[] = { (union xioaddr_desc *)&xioaddr_udp4_recvfrom1, NULL };
|
||||||
|
static const struct xioaddr_endpoint_desc xioaddr_udp4_recv1 = { XIOADDR_SYS, "udp4-recv", 1, XIOBIT_RDONLY, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP4|GROUP_IP_UDP|GROUP_RANGE, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_udp_recv, PF_INET, SOCK_DGRAM, IPPROTO_UDP HELP(":<port>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_udp4_recv[] = { (union xioaddr_desc *)&xioaddr_udp4_recv1, NULL };
|
||||||
#endif /* WITH_IP4 */
|
#endif /* WITH_IP4 */
|
||||||
|
|
||||||
#if WITH_IP6
|
#if WITH_IP6
|
||||||
const struct addrdesc addr_udp6_connect = { "udp6-connect", 3, xioopen_ipapp_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP, SOCK_DGRAM, IPPROTO_UDP, PF_INET6 HELP(":<host>:<port>") };
|
static const struct xioaddr_endpoint_desc xioaddr_udp6_connect2 = { XIOADDR_SYS, "udp6-connect", 2, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_ipapp_connect, SOCK_DGRAM, IPPROTO_UDP, PF_INET6 HELP(":<host>:<port>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_udp6_connect[] = { (union xioaddr_desc *)&xioaddr_udp6_connect2, NULL };
|
||||||
#if WITH_LISTEN
|
#if WITH_LISTEN
|
||||||
const struct addrdesc addr_udp6_listen = { "udp6-listen", 3, xioopen_ipdgram_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE, PF_INET6, IPPROTO_UDP, 0 HELP(":<port>") };
|
static const struct xioaddr_endpoint_desc xioaddr_udp6_listen1 = { XIOADDR_SYS, "udp6-listen", 1, XIOBIT_RDONLY|XIOBIT_RDWR, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_LISTEN|GROUP_CHILD|GROUP_RANGE, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_ipdgram_listen, PF_INET6, IPPROTO_UDP, 0 HELP(":<port>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_udp6_listen[] = { (union xioaddr_desc *)&xioaddr_udp6_listen1, NULL };
|
||||||
#endif /* WITH_LISTEN */
|
#endif /* WITH_LISTEN */
|
||||||
const struct addrdesc addr_udp6_sendto = { "udp6-sendto", 3, xioopen_udp_sendto, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP, PF_INET6, SOCK_DGRAM, IPPROTO_UDP HELP(":<host>:<port>") };
|
static const struct xioaddr_endpoint_desc xioaddr_udp6_sendto2 = { XIOADDR_SYS, "udp6-sendto", 2, XIOBIT_WRONLY|XIOBIT_RDWR, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_udp_sendto, PF_INET6, SOCK_DGRAM, IPPROTO_UDP HELP(":<host>:<port>") };
|
||||||
const struct addrdesc addr_udp6_datagram= { "udp6-datagram", 3, xioopen_udp_datagram,GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_RANGE, PF_INET6, SOCK_DGRAM, IPPROTO_UDP HELP(":<host>:<port>") };
|
const union xioaddr_desc *xioaddrs_udp6_sendto[] = { (union xioaddr_desc *)&xioaddr_udp6_sendto2, NULL };
|
||||||
const struct addrdesc addr_udp6_recvfrom= { "udp6-recvfrom", 3, xioopen_udp_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_CHILD|GROUP_RANGE, PF_INET6, SOCK_DGRAM, IPPROTO_UDP HELP(":<port>") };
|
static const struct xioaddr_endpoint_desc xioaddr_udp6_datagram2= { XIOADDR_SYS, "udp6-datagram",2, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_udp_datagram, PF_INET6, SOCK_DGRAM, IPPROTO_UDP HELP(":<host>:<port>") };
|
||||||
const struct addrdesc addr_udp6_recv = { "udp6-recv", 1, xioopen_udp_recv, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_RANGE, PF_INET6, SOCK_DGRAM, IPPROTO_UDP HELP(":<port>") };
|
const union xioaddr_desc *xioaddrs_udp6_datagram[] = { (union xioaddr_desc *)&xioaddr_udp6_datagram2, NULL };
|
||||||
|
static const struct xioaddr_endpoint_desc xioaddr_udp6_recvfrom1= { XIOADDR_SYS, "udp6-recvfrom",1, XIOBIT_RDONLY|XIOBIT_RDWR, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_CHILD|GROUP_RANGE, XIOSHUT_NONE, XIOCLOSE_NONE, xioopen_udp_recvfrom, PF_INET6, SOCK_DGRAM, IPPROTO_UDP HELP(":<port>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_udp6_recvfrom[] = { (union xioaddr_desc *)&xioaddr_udp6_recvfrom1, NULL };
|
||||||
|
static const struct xioaddr_endpoint_desc xioaddr_udp6_recv1 = { XIOADDR_SYS, "udp6-recv", 1, XIOBIT_RDONLY, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_IP6|GROUP_IP_UDP|GROUP_RANGE, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_udp_recv, PF_INET6, SOCK_DGRAM, IPPROTO_UDP HELP(":<port>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_udp6_recv[] = { (union xioaddr_desc *)&xioaddr_udp6_recv1, NULL };
|
||||||
#endif /* WITH_IP6 */
|
#endif /* WITH_IP6 */
|
||||||
|
|
||||||
|
|
||||||
|
@ -113,6 +130,8 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
|
||||||
if (applyopts_single(&fd->stream, opts, PH_INIT) < 0) return -1;
|
if (applyopts_single(&fd->stream, opts, PH_INIT) < 0) return -1;
|
||||||
applyopts(-1, opts, PH_INIT);
|
applyopts(-1, opts, PH_INIT);
|
||||||
|
|
||||||
|
fd->stream.fdtype = FDTYPE_SINGLE;
|
||||||
|
|
||||||
uslen = socket_init(pf, &us);
|
uslen = socket_init(pf, &us);
|
||||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||||
retropt_bind(opts, pf, socktype, IPPROTO_UDP,
|
retropt_bind(opts, pf, socktype, IPPROTO_UDP,
|
||||||
|
@ -172,61 +191,61 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
|
||||||
union sockaddr_union _sockname;
|
union sockaddr_union _sockname;
|
||||||
union sockaddr_union *la = &_sockname; /* local address */
|
union sockaddr_union *la = &_sockname; /* local address */
|
||||||
|
|
||||||
if ((fd->stream.fd = Socket(pf, socktype, ipproto)) < 0) {
|
if ((fd->stream.fd1 = Socket(pf, socktype, ipproto)) < 0) {
|
||||||
Error4("socket(%d, %d, %d): %s", pf, socktype, ipproto, strerror(errno));
|
Error4("socket(%d, %d, %d): %s", pf, socktype, ipproto, strerror(errno));
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
applyopts(fd->stream.fd, opts, PH_PASTSOCKET);
|
/*0 Info4("socket(%d, %d, %d) -> %d", pf, socktype, ipproto, fd->stream.fd);*/
|
||||||
if (Setsockopt(fd->stream.fd, opt_so_reuseaddr.major,
|
applyopts(fd->stream.fd1, opts, PH_PASTSOCKET);
|
||||||
|
if (Setsockopt(fd->stream.fd1, opt_so_reuseaddr.major,
|
||||||
opt_so_reuseaddr.minor, &one, sizeof(one)) < 0) {
|
opt_so_reuseaddr.minor, &one, sizeof(one)) < 0) {
|
||||||
Warn6("setsockopt(%d, %d, %d, {%d}, "F_Zd"): %s",
|
Warn6("setsockopt(%d, %d, %d, {%d}, "F_Zd"): %s",
|
||||||
fd->stream.fd, opt_so_reuseaddr.major,
|
fd->stream.fd1, opt_so_reuseaddr.major,
|
||||||
opt_so_reuseaddr.minor, one, sizeof(one), strerror(errno));
|
opt_so_reuseaddr.minor, one, sizeof(one), strerror(errno));
|
||||||
}
|
}
|
||||||
applyopts_cloexec(fd->stream.fd, opts);
|
applyopts_cloexec(fd->stream.fd1, opts);
|
||||||
applyopts(fd->stream.fd, opts, PH_PREBIND);
|
applyopts(fd->stream.fd1, opts, PH_PREBIND);
|
||||||
applyopts(fd->stream.fd, opts, PH_BIND);
|
applyopts(fd->stream.fd1, opts, PH_BIND);
|
||||||
if (Bind(fd->stream.fd, &us.soa, uslen) < 0) {
|
if (Bind(fd->stream.fd1, &us.soa, uslen) < 0) {
|
||||||
Error4("bind(%d, {%s}, "F_Zd"): %s", fd->stream.fd,
|
Error4("bind(%d, {%s}, "F_Zd"): %s", fd->stream.fd1,
|
||||||
sockaddr_info(&us.soa, uslen, infobuff, sizeof(infobuff)),
|
sockaddr_info(&us.soa, uslen, infobuff, sizeof(infobuff)),
|
||||||
uslen, strerror(errno));
|
uslen, strerror(errno));
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
/* under some circumstances bind() fills sockaddr with interesting info. */
|
/* under some circumstances bind() fills sockaddr with interesting info. */
|
||||||
if (Getsockname(fd->stream.fd, &us.soa, &uslen) < 0) {
|
if (Getsockname(fd->stream.fd1, &us.soa, &uslen) < 0) {
|
||||||
Error4("getsockname(%d, %p, {%d}): %s",
|
Error4("getsockname(%d, %p, {%d}): %s",
|
||||||
fd->stream.fd, &us.soa, uslen, strerror(errno));
|
fd->stream.fd1, &us.soa, uslen, strerror(errno));
|
||||||
}
|
}
|
||||||
applyopts(fd->stream.fd, opts, PH_PASTBIND);
|
applyopts(fd->stream.fd1, opts, PH_PASTBIND);
|
||||||
|
|
||||||
Notice1("listening on UDP %s",
|
Notice1("listening on UDP %s",
|
||||||
sockaddr_info(&us.soa, uslen, infobuff, sizeof(infobuff)));
|
sockaddr_info(&us.soa, uslen, infobuff, sizeof(infobuff)));
|
||||||
FD_ZERO(&in); FD_ZERO(&out); FD_ZERO(&expt);
|
FD_ZERO(&in); FD_ZERO(&out); FD_ZERO(&expt);
|
||||||
FD_SET(fd->stream.fd, &in);
|
FD_SET(fd->stream.fd1, &in);
|
||||||
while (Select(fd->stream.fd+1, &in, &out, &expt, NULL) < 0) {
|
while (Select(fd->stream.fd1+1, &in, &out, &expt, NULL) < 0) {
|
||||||
if (errno != EINTR) break;
|
if (errno != EINTR) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
themlen = socket_init(pf, them);
|
themlen = socket_init(pf, them);
|
||||||
do {
|
do {
|
||||||
result = Recvfrom(fd->stream.fd, buff1, 1, MSG_PEEK,
|
result = Recvfrom(fd->stream.fd1, buff1, 1, MSG_PEEK,
|
||||||
&them->soa, &themlen);
|
&them->soa, &themlen);
|
||||||
} while (result < 0 && errno == EINTR);
|
} while (result < 0 && errno == EINTR);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
Error5("recvfrom(%d, %p, 1, MSG_PEEK, {%s}, {"F_Zu"}): %s",
|
Error5("recvfrom(%d, %p, 1, MSG_PEEK, {%s}, {"F_Zu"}): %s",
|
||||||
fd->stream.fd, buff1,
|
fd->stream.fd1, buff1,
|
||||||
sockaddr_info(&them->soa, themlen, infobuff, sizeof(infobuff)),
|
sockaddr_info(&them->soa, themlen, infobuff, sizeof(infobuff)),
|
||||||
themlen, strerror(errno));
|
themlen, strerror(errno));
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
|
||||||
Notice1("accepting UDP connection from %s",
|
Notice1("accepting UDP connection from %s",
|
||||||
sockaddr_info(&them->soa, themlen, infobuff, sizeof(infobuff)));
|
sockaddr_info(&them->soa, themlen, infobuff, sizeof(infobuff)));
|
||||||
|
|
||||||
if (xiocheckpeer(&fd->stream, them, la) < 0) {
|
if (xiocheckpeer(&fd->stream, them, la) < 0) {
|
||||||
/* drop packet */
|
/* drop packet */
|
||||||
char buff[512];
|
char buff[512];
|
||||||
Recv(fd->stream.fd, buff, sizeof(buff), 0);
|
Recv(fd->stream.fd1, buff, sizeof(buff), 0);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Info1("permitting UDP connection from %s",
|
Info1("permitting UDP connection from %s",
|
||||||
|
@ -249,8 +268,8 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
|
||||||
/* server: continue loop with select */
|
/* server: continue loop with select */
|
||||||
/* when we dont close this we get awkward behaviour on Linux 2.4:
|
/* when we dont close this we get awkward behaviour on Linux 2.4:
|
||||||
recvfrom gives 0 bytes with invalid socket address */
|
recvfrom gives 0 bytes with invalid socket address */
|
||||||
if (Close(fd->stream.fd) < 0) {
|
if (Close(fd->stream.fd1) < 0) {
|
||||||
Info2("close(%d): %s", fd->stream.fd, strerror(errno));
|
Info2("close(%d): %s", fd->stream.fd1, strerror(errno));
|
||||||
}
|
}
|
||||||
Notice1("forked off child process "F_pid, pid);
|
Notice1("forked off child process "F_pid, pid);
|
||||||
Sleep(1); /*! give child a chance to consume the old packet */
|
Sleep(1); /*! give child a chance to consume the old packet */
|
||||||
|
@ -260,18 +279,17 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
applyopts(fd->stream.fd, opts, PH_CONNECT);
|
applyopts(fd->stream.fd1, opts, PH_CONNECT);
|
||||||
if ((result = Connect(fd->stream.fd, &them->soa, themlen)) < 0) {
|
if ((result = Connect(fd->stream.fd1, &them->soa, themlen)) < 0) {
|
||||||
Error4("connect(%d, {%s}, "F_Zd"): %s",
|
Error4("connect(%d, {%s}, "F_Zd"): %s",
|
||||||
fd->stream.fd,
|
fd->stream.fd1,
|
||||||
sockaddr_info(&them->soa, themlen, infobuff, sizeof(infobuff)),
|
sockaddr_info(&them->soa, themlen, infobuff, sizeof(infobuff)),
|
||||||
themlen, strerror(errno));
|
themlen, strerror(errno));
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
}
|
}
|
||||||
|
|
||||||
fd->stream.howtoend = END_SHUTDOWN;
|
applyopts_fchown(fd->stream.fd1, opts);
|
||||||
applyopts_fchown(fd->stream.fd, opts);
|
applyopts(fd->stream.fd1, opts, PH_LATE);
|
||||||
applyopts(fd->stream.fd, opts, PH_LATE);
|
|
||||||
|
|
||||||
if ((result = _xio_openlate(&fd->stream, opts)) < 0)
|
if ((result = _xio_openlate(&fd->stream, opts)) < 0)
|
||||||
return result;
|
return result;
|
||||||
|
@ -312,7 +330,6 @@ int _xioopen_udp_sendto(const char *hostname, const char *servname,
|
||||||
bool needbind = false;
|
bool needbind = false;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
xfd->howtoend = END_SHUTDOWN;
|
|
||||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||||
|
|
||||||
/* ...res_opts[] */
|
/* ...res_opts[] */
|
||||||
|
@ -452,7 +469,6 @@ int xioopen_udp_recvfrom(int argc, const char *argv[], struct opt *opts,
|
||||||
return STAT_NORETRY;
|
return STAT_NORETRY;
|
||||||
}
|
}
|
||||||
|
|
||||||
xfd->stream.howtoend = END_NONE;
|
|
||||||
retropt_socket_pf(opts, &pf);
|
retropt_socket_pf(opts, &pf);
|
||||||
if (pf == PF_UNSPEC) {
|
if (pf == PF_UNSPEC) {
|
||||||
#if WITH_IP4 && WITH_IP6
|
#if WITH_IP4 && WITH_IP6
|
||||||
|
|
36
xio-udp.h
36
xio-udp.h
|
@ -5,24 +5,24 @@
|
||||||
#ifndef __xio_udp_h_included
|
#ifndef __xio_udp_h_included
|
||||||
#define __xio_udp_h_included 1
|
#define __xio_udp_h_included 1
|
||||||
|
|
||||||
extern const struct addrdesc addr_udp_connect;
|
extern const union xioaddr_desc *xioaddrs_udp_connect[];
|
||||||
extern const struct addrdesc addr_udp_listen;
|
extern const union xioaddr_desc *xioaddrs_udp_listen[];
|
||||||
extern const struct addrdesc addr_udp_sendto;
|
extern const union xioaddr_desc *xioaddrs_udp_sendto[];
|
||||||
extern const struct addrdesc addr_udp_datagram;
|
extern const union xioaddr_desc *xioaddrs_udp_datagram[];
|
||||||
extern const struct addrdesc addr_udp_recvfrom;
|
extern const union xioaddr_desc *xioaddrs_udp_recvfrom[];
|
||||||
extern const struct addrdesc addr_udp_recv;
|
extern const union xioaddr_desc *xioaddrs_udp_recv[];
|
||||||
extern const struct addrdesc addr_udp4_connect;
|
extern const union xioaddr_desc *xioaddrs_udp4_connect[];
|
||||||
extern const struct addrdesc addr_udp4_listen;
|
extern const union xioaddr_desc *xioaddrs_udp4_listen[];
|
||||||
extern const struct addrdesc addr_udp4_sendto;
|
extern const union xioaddr_desc *xioaddrs_udp4_sendto[];
|
||||||
extern const struct addrdesc addr_udp4_datagram;
|
extern const union xioaddr_desc *xioaddrs_udp4_datagram[];
|
||||||
extern const struct addrdesc addr_udp4_recvfrom;
|
extern const union xioaddr_desc *xioaddrs_udp4_recvfrom[];
|
||||||
extern const struct addrdesc addr_udp4_recv;
|
extern const union xioaddr_desc *xioaddrs_udp4_recv[];
|
||||||
extern const struct addrdesc addr_udp6_connect;
|
extern const union xioaddr_desc *xioaddrs_udp6_connect[];
|
||||||
extern const struct addrdesc addr_udp6_listen;
|
extern const union xioaddr_desc *xioaddrs_udp6_listen[];
|
||||||
extern const struct addrdesc addr_udp6_sendto;
|
extern const union xioaddr_desc *xioaddrs_udp6_sendto[];
|
||||||
extern const struct addrdesc addr_udp6_datagram;
|
extern const union xioaddr_desc *xioaddrs_udp6_datagram[];
|
||||||
extern const struct addrdesc addr_udp6_recvfrom;
|
extern const union xioaddr_desc *xioaddrs_udp6_recvfrom[];
|
||||||
extern const struct addrdesc addr_udp6_recv;
|
extern const union xioaddr_desc *xioaddrs_udp6_recv[];
|
||||||
|
|
||||||
extern int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
|
extern int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
|
||||||
int rw, xiofile_t *fd,
|
int rw, xiofile_t *fd,
|
||||||
|
|
50
xio-unix.c
50
xio-unix.c
|
@ -25,7 +25,6 @@ int xioopen_unix_recv(int argc, const char *argv[], struct opt *opts,
|
||||||
int pf, int socktype, int ipproto);
|
int pf, int socktype, int ipproto);
|
||||||
static
|
static
|
||||||
int xioopen_unix_client(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, unsigned groups, int dummy1, int dummy2, int dummy3);
|
int xioopen_unix_client(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, unsigned groups, int dummy1, int dummy2, int dummy3);
|
||||||
|
|
||||||
#if WITH_ABSTRACT_UNIXSOCKET
|
#if WITH_ABSTRACT_UNIXSOCKET
|
||||||
static int xioopen_abstract_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3);
|
static int xioopen_abstract_connect(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3);
|
||||||
static int xioopen_abstract_listen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3);
|
static int xioopen_abstract_listen(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *fd, unsigned groups, int dummy1, int dummy2, int dummy3);
|
||||||
|
@ -39,23 +38,36 @@ static
|
||||||
int xioopen_abstract_client(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, unsigned groups, int dummy1, int dummy2, int dummy3);
|
int xioopen_abstract_client(int argc, const char *argv[], struct opt *opts, int xioflags, xiofile_t *xfd, unsigned groups, int dummy1, int dummy2, int dummy3);
|
||||||
#endif /* WITH_ABSTRACT_UNIXSOCKET */
|
#endif /* WITH_ABSTRACT_UNIXSOCKET */
|
||||||
|
|
||||||
const struct addrdesc addr_unix_connect = { "unix-connect", 3, xioopen_unix_connect, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, 0, SOCK_STREAM, 0 HELP(":<filename>") };
|
static const struct xioaddr_endpoint_desc xioendpoint_unix_connect1 = { XIOADDR_SYS, "unix-connect", 1, XIOBIT_ALL, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_unix_connect, 0, SOCK_STREAM, 0 HELP(":<filename>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_unix_connect[] = { (union xioaddr_desc *)&xioendpoint_unix_connect1, NULL };
|
||||||
#if WITH_LISTEN
|
#if WITH_LISTEN
|
||||||
const struct addrdesc addr_unix_listen = { "unix-listen", 3, xioopen_unix_listen, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_LISTEN|GROUP_CHILD|GROUP_RETRY, 0, SOCK_STREAM, 0 HELP(":<filename>") };
|
static const struct xioaddr_endpoint_desc xioendpoint_unix_listen1 = { XIOADDR_SYS, "unix-listen", 1, XIOBIT_ALL, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_LISTEN|GROUP_CHILD|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_unix_listen, 0, SOCK_STREAM, 0 HELP(":<filename>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_unix_listen[] = { (union xioaddr_desc *)&xioendpoint_unix_listen1, NULL };
|
||||||
#endif /* WITH_LISTEN */
|
#endif /* WITH_LISTEN */
|
||||||
const struct addrdesc addr_unix_sendto = { "unix-sendto", 3, xioopen_unix_sendto, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, 0, SOCK_DGRAM, 0 HELP(":<filename>") };
|
static const struct xioaddr_endpoint_desc xioendpoint_unix_sendto1 = { XIOADDR_SYS, "unix-sendto", 1, XIOBIT_WRONLY|XIOBIT_RDWR, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_unix_sendto, 0, SOCK_DGRAM, 0 HELP(":<filename>") };
|
||||||
const struct addrdesc addr_unix_recvfrom= { "unix-recvfrom", 3, xioopen_unix_recvfrom, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY|GROUP_CHILD, PF_UNIX, SOCK_DGRAM, 0 HELP(":<filename>") };
|
const union xioaddr_desc *xioaddrs_unix_sendto[] = { (union xioaddr_desc *)&xioendpoint_unix_sendto1, NULL };
|
||||||
const struct addrdesc addr_unix_recv = { "unix-recv", 1, xioopen_unix_recv, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, PF_UNIX, SOCK_DGRAM, 0 HELP(":<filename>") };
|
static const struct xioaddr_endpoint_desc xioendpoint_unix_recvfrom1= { XIOADDR_SYS, "unix-recvfrom",1, XIOBIT_RDONLY|XIOBIT_RDWR, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY|GROUP_CHILD, XIOSHUT_DOWN, XIOCLOSE_NONE, xioopen_unix_recvfrom, PF_UNIX, SOCK_DGRAM, 0 HELP(":<filename>") };
|
||||||
const struct addrdesc addr_unix_client = { "unix-client", 3, xioopen_unix_client, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, PF_UNIX, 0, 0 HELP(":<filename>") };
|
const union xioaddr_desc *xioaddrs_unix_recvfrom[]= { (union xioaddr_desc *)&xioendpoint_unix_recvfrom1, NULL };
|
||||||
|
static const struct xioaddr_endpoint_desc xioendpoint_unix_recv1 = { XIOADDR_SYS, "unix-recv", 1, XIOBIT_RDONLY, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_NONE, xioopen_unix_recv, PF_UNIX, SOCK_DGRAM, 0 HELP(":<filename>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_unix_recv[] = { (union xioaddr_desc *)&xioendpoint_unix_recv1, NULL };
|
||||||
|
static const struct xioaddr_endpoint_desc xioendpoint_unix_client1 = { XIOADDR_SYS, "unix-client", 1, XIOBIT_ALL, GROUP_FD|GROUP_NAMED|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_unix_client, PF_UNIX, 0, 0 HELP(":<filename>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_unix_client[] = { (union xioaddr_desc *)&xioendpoint_unix_client1, NULL };
|
||||||
|
|
||||||
#if WITH_ABSTRACT_UNIXSOCKET
|
#if WITH_ABSTRACT_UNIXSOCKET
|
||||||
const struct addrdesc xioaddr_abstract_connect = { "abstract-connect", 3, xioopen_abstract_connect, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, 0, SOCK_STREAM, 0 HELP(":<filename>") };
|
static const struct xioaddr_endpoint_desc xioendpoint_abstract_connect1 = { XIOADDR_SYS, "abstract-connect", 1, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_abstract_connect, 0, SOCK_STREAM, 0 HELP(":<filename>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_abstract_connect[] = { (union xioaddr_desc *)&xioendpoint_abstract_connect1, NULL };
|
||||||
#if WITH_LISTEN
|
#if WITH_LISTEN
|
||||||
const struct addrdesc xioaddr_abstract_listen = { "abstract-listen", 3, xioopen_abstract_listen, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_LISTEN|GROUP_CHILD|GROUP_RETRY, 0, SOCK_STREAM, 0 HELP(":<filename>") };
|
static const struct xioaddr_endpoint_desc xioendpoint_abstract_listen1 = { XIOADDR_SYS, "abstract-listen", 1, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_LISTEN|GROUP_CHILD|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_abstract_listen, 0, SOCK_STREAM, 0 HELP(":<filename>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_abstract_listen[] = { (union xioaddr_desc *)&xioendpoint_abstract_listen1, NULL };
|
||||||
#endif /* WITH_LISTEN */
|
#endif /* WITH_LISTEN */
|
||||||
const struct addrdesc xioaddr_abstract_sendto = { "abstract-sendto", 3, xioopen_abstract_sendto, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, 0, SOCK_DGRAM, 0 HELP(":<filename>") };
|
static const struct xioaddr_endpoint_desc xioendpoint_abstract_sendto1 = { XIOADDR_SYS, "abstract-sendto", 1, XIOBIT_WRONLY|XIOBIT_RDWR, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_abstract_sendto, 0, SOCK_DGRAM, 0 HELP(":<filename>") };
|
||||||
const struct addrdesc xioaddr_abstract_recvfrom= { "abstract-recvfrom", 3, xioopen_abstract_recvfrom, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY|GROUP_CHILD, PF_UNIX, SOCK_DGRAM, 0 HELP(":<filename>") };
|
const union xioaddr_desc *xioaddrs_abstract_sendto[] = { (union xioaddr_desc *)&xioendpoint_abstract_sendto1, NULL };
|
||||||
const struct addrdesc xioaddr_abstract_recv = { "abstract-recv", 1, xioopen_abstract_recv, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, PF_UNIX, SOCK_DGRAM, 0 HELP(":<filename>") };
|
static const struct xioaddr_endpoint_desc xioendpoint_abstract_recvfrom1= { XIOADDR_SYS, "abstract-recvfrom", 1, XIOBIT_RDONLY|XIOBIT_RDWR, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY|GROUP_CHILD, XIOSHUT_DOWN, XIOCLOSE_NONE, xioopen_abstract_recvfrom, PF_UNIX, SOCK_DGRAM, 0 HELP(":<filename>") };
|
||||||
const struct addrdesc xioaddr_abstract_client = { "abstract-client", 3, xioopen_abstract_client, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, PF_UNIX, 0, 0 HELP(":<filename>") };
|
const union xioaddr_desc *xioaddrs_abstract_recvfrom[] = { (union xioaddr_desc *)&xioendpoint_abstract_recvfrom1, NULL };
|
||||||
|
static const struct xioaddr_endpoint_desc xioendpoint_abstract_recv1 = { XIOADDR_SYS, "abstract-recv", 1, XIOBIT_RDONLY, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_NONE, xioopen_abstract_recv, PF_UNIX, SOCK_DGRAM, 0 HELP(":<filename>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_abstract_recv[] = { (union xioaddr_desc *)&xioendpoint_abstract_recv1, NULL };
|
||||||
|
static const struct xioaddr_endpoint_desc xioendpoint_abstract_client1 = { XIOADDR_SYS, "abstract-client", 1, XIOBIT_ALL, GROUP_FD|GROUP_SOCKET|GROUP_SOCK_UNIX|GROUP_RETRY, XIOSHUT_DOWN, XIOCLOSE_CLOSE, xioopen_abstract_client, PF_UNIX, 0, 0 HELP(":<filename>") };
|
||||||
|
const union xioaddr_desc *xioaddrs_abstract_client[] = { (union xioaddr_desc *)&xioendpoint_abstract_client1, NULL };
|
||||||
#endif /* WITH_ABSTRACT_UNIXSOCKET */
|
#endif /* WITH_ABSTRACT_UNIXSOCKET */
|
||||||
|
|
||||||
const struct optdesc opt_unix_tightsocklen = { "unix-tightsocklen", "tightsocklen", OPT_UNIX_TIGHTSOCKLEN, GROUP_SOCK_UNIX, PH_INIT, TYPE_BOOL, OFUNC_SPEC, 0, 0 };
|
const struct optdesc opt_unix_tightsocklen = { "unix-tightsocklen", "tightsocklen", OPT_UNIX_TIGHTSOCKLEN, GROUP_SOCK_UNIX, PH_INIT, TYPE_BOOL, OFUNC_SPEC, 0, 0 };
|
||||||
|
@ -133,8 +145,6 @@ static int xioopen_unix_listen(int argc, const char *argv[], struct opt *opts, i
|
||||||
xfd->opt_unlink_close = true;
|
xfd->opt_unlink_close = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
xfd->howtoend = END_SHUTDOWN;
|
|
||||||
|
|
||||||
applyopts(-1, opts, PH_INIT);
|
applyopts(-1, opts, PH_INIT);
|
||||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||||
applyopts(-1, opts, PH_EARLY);
|
applyopts(-1, opts, PH_EARLY);
|
||||||
|
@ -242,8 +252,6 @@ static int xioopen_unix_sendto(int argc, const char *argv[], struct opt *opts, i
|
||||||
uslen = socket_init(pf, &us);
|
uslen = socket_init(pf, &us);
|
||||||
xfd->salen = socket_init(pf, &xfd->peersa);
|
xfd->salen = socket_init(pf, &xfd->peersa);
|
||||||
|
|
||||||
xfd->howtoend = END_SHUTDOWN;
|
|
||||||
|
|
||||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||||
|
|
||||||
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
||||||
|
@ -299,7 +307,6 @@ int xioopen_unix_recvfrom(int argc, const char *argv[], struct opt *opts,
|
||||||
name = argv[1];
|
name = argv[1];
|
||||||
uslen = xiosetunix(&us, name, false, tight);
|
uslen = xiosetunix(&us, name, false, tight);
|
||||||
|
|
||||||
xfd->stream.howtoend = END_NONE;
|
|
||||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||||
retropt_bind(opts, pf, socktype, 0, (struct sockaddr *)&us, &uslen, 1, 0, 0);
|
retropt_bind(opts, pf, socktype, 0, (struct sockaddr *)&us, &uslen, 1, 0, 0);
|
||||||
retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early);
|
retropt_bool(opts, OPT_UNLINK_EARLY, &opt_unlink_early);
|
||||||
|
@ -406,7 +413,6 @@ static int xioopen_unix_client(int argc, const char *argv[], struct opt *opts, i
|
||||||
Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
|
Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
xfd->howtoend = END_SHUTDOWN;
|
|
||||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||||
|
|
||||||
uslen = socket_init(pf, &us);
|
uslen = socket_init(pf, &us);
|
||||||
|
@ -487,8 +493,6 @@ static int xioopen_abstract_listen(int argc, const char *argv[], struct opt *opt
|
||||||
name = argv[1];
|
name = argv[1];
|
||||||
uslen = xiosetunix(&us, name, true, tight);
|
uslen = xiosetunix(&us, name, true, tight);
|
||||||
|
|
||||||
xfd->howtoend = END_SHUTDOWN;
|
|
||||||
|
|
||||||
applyopts(-1, opts, PH_INIT);
|
applyopts(-1, opts, PH_INIT);
|
||||||
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
|
||||||
applyopts(-1, opts, PH_EARLY);
|
applyopts(-1, opts, PH_EARLY);
|
||||||
|
@ -574,8 +578,6 @@ static int xioopen_abstract_sendto(int argc, const char *argv[], struct opt *opt
|
||||||
uslen = socket_init(pf, &us);
|
uslen = socket_init(pf, &us);
|
||||||
xfd->salen = socket_init(pf, &xfd->peersa);
|
xfd->salen = socket_init(pf, &xfd->peersa);
|
||||||
|
|
||||||
xfd->howtoend = END_SHUTDOWN;
|
|
||||||
|
|
||||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||||
|
|
||||||
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
retropt_bool(opts, OPT_UNIX_TIGHTSOCKLEN, &tight);
|
||||||
|
@ -620,7 +622,6 @@ int xioopen_abstract_recvfrom(int argc, const char *argv[], struct opt *opts,
|
||||||
name = argv[1];
|
name = argv[1];
|
||||||
uslen = xiosetunix(&us, name, true, tight);
|
uslen = xiosetunix(&us, name, true, tight);
|
||||||
|
|
||||||
xfd->stream.howtoend = END_NONE;
|
|
||||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||||
retropt_bind(opts, pf, socktype, 0, (struct sockaddr *)&us, &uslen, 1, 0, 0);
|
retropt_bind(opts, pf, socktype, 0, (struct sockaddr *)&us, &uslen, 1, 0, 0);
|
||||||
|
|
||||||
|
@ -685,7 +686,6 @@ static int xioopen_abstract_client(int argc, const char *argv[], struct opt *opt
|
||||||
Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
|
Error2("%s: wrong number of parameters (%d instead of 1)", argv[0], argc-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
xfd->howtoend = END_SHUTDOWN;
|
|
||||||
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
retropt_int(opts, OPT_SO_TYPE, &socktype);
|
||||||
|
|
||||||
uslen = socket_init(pf, &us);
|
uslen = socket_init(pf, &us);
|
||||||
|
|
24
xio-unix.h
24
xio-unix.h
|
@ -5,18 +5,18 @@
|
||||||
#ifndef __xio_unix_h_included
|
#ifndef __xio_unix_h_included
|
||||||
#define __xio_unix_h_included 1
|
#define __xio_unix_h_included 1
|
||||||
|
|
||||||
extern const struct addrdesc addr_unix_connect;
|
extern const union xioaddr_desc *xioaddrs_unix_connect[];
|
||||||
extern const struct addrdesc addr_unix_listen;
|
extern const union xioaddr_desc *xioaddrs_unix_listen[];
|
||||||
extern const struct addrdesc addr_unix_sendto;
|
extern const union xioaddr_desc *xioaddrs_unix_sendto[];
|
||||||
extern const struct addrdesc addr_unix_recvfrom;
|
extern const union xioaddr_desc *xioaddrs_unix_recvfrom[];
|
||||||
extern const struct addrdesc addr_unix_recv;
|
extern const union xioaddr_desc *xioaddrs_unix_recv[];
|
||||||
extern const struct addrdesc addr_unix_client;
|
extern const union xioaddr_desc *xioaddrs_unix_client[];
|
||||||
extern const struct addrdesc xioaddr_abstract_connect;
|
extern const union xioaddr_desc *xioaddrs_abstract_connect[];
|
||||||
extern const struct addrdesc xioaddr_abstract_listen;
|
extern const union xioaddr_desc *xioaddrs_abstract_listen[];
|
||||||
extern const struct addrdesc xioaddr_abstract_sendto;
|
extern const union xioaddr_desc *xioaddrs_abstract_sendto[];
|
||||||
extern const struct addrdesc xioaddr_abstract_recvfrom;
|
extern const union xioaddr_desc *xioaddrs_abstract_recvfrom[];
|
||||||
extern const struct addrdesc xioaddr_abstract_recv;
|
extern const union xioaddr_desc *xioaddrs_abstract_recv[];
|
||||||
extern const struct addrdesc xioaddr_abstract_client;
|
extern const union xioaddr_desc *xioaddrs_abstract_client[];
|
||||||
|
|
||||||
extern const struct optdesc opt_unix_tightsocklen;
|
extern const struct optdesc opt_unix_tightsocklen;
|
||||||
|
|
||||||
|
|
309
xio.h
309
xio.h
|
@ -19,7 +19,7 @@
|
||||||
#define LINETERM_CR 1
|
#define LINETERM_CR 1
|
||||||
#define LINETERM_CRNL 2
|
#define LINETERM_CRNL 2
|
||||||
|
|
||||||
struct addrdesc;
|
union xioaddr_desc;
|
||||||
struct opt;
|
struct opt;
|
||||||
|
|
||||||
/* the flags argument of xioopen */
|
/* the flags argument of xioopen */
|
||||||
|
@ -27,18 +27,37 @@ struct opt;
|
||||||
#define XIO_WRONLY O_WRONLY /* asserted to be 1 */
|
#define XIO_WRONLY O_WRONLY /* asserted to be 1 */
|
||||||
#define XIO_RDWR O_RDWR /* asserted to be 2 */
|
#define XIO_RDWR O_RDWR /* asserted to be 2 */
|
||||||
#define XIO_ACCMODE O_ACCMODE /* must be 3 */
|
#define XIO_ACCMODE O_ACCMODE /* must be 3 */
|
||||||
#define XIO_MAYFORK 4 /* address is allowed to fork the program (fork) */
|
/* 3 is undefined */
|
||||||
#define XIO_MAYCHILD 8 /* address is allowed to fork off a child (exec)*/
|
#define XIO_MAYFORK 4 /* address is allowed to fork the program (fork),
|
||||||
|
especially with listen and connect addresses */
|
||||||
|
#define XIO_MAYCHILD 8 /* address is allowed to fork off a child that
|
||||||
|
exec's another program or calls system() */
|
||||||
#define XIO_MAYEXEC 16 /* address is allowed to exec a prog (exec+nofork) */
|
#define XIO_MAYEXEC 16 /* address is allowed to exec a prog (exec+nofork) */
|
||||||
#define XIO_MAYCONVERT 32 /* address is allowed to perform modifications on the
|
#define XIO_MAYCONVERT 32 /* address is allowed to perform modifications on the
|
||||||
stream data, e.g. SSL, REALDINE; CRLF */
|
stream data, e.g. SSL, READLINE; CRLF */
|
||||||
|
#define XIO_MAYCHAIN 64 /* address is allowed to consist of a chain of
|
||||||
|
subaddresses that are handled by socat
|
||||||
|
subprocesses */
|
||||||
|
#define XIO_EMBEDDED 256 /* address is nonterminal */
|
||||||
|
#define XIO_MAYALL INT_MAX /* all features enabled */
|
||||||
|
|
||||||
/* the status flags of xiofile_t */
|
/* the status flags of xiofile_t */
|
||||||
#define XIO_DOESFORK XIO_MAYFORK
|
#define XIO_DOESFORK XIO_MAYFORK
|
||||||
#define XIO_DOESCHILD XIO_MAYCHILD
|
#define XIO_DOESCHILD XIO_MAYCHILD
|
||||||
#define XIO_DOESEXEC XIO_MAYEXEC
|
#define XIO_DOESEXEC XIO_MAYEXEC
|
||||||
#define XIO_DOESCONVERT XIO_MAYCONVERT
|
#define XIO_DOESCONVERT XIO_MAYCONVERT
|
||||||
|
#define XIO_DOESCHAIN XIO_MAYCHAIN
|
||||||
|
|
||||||
|
/* sometimes we use a set of allowed direction(s), a bit pattern */
|
||||||
|
#define XIOBIT_RDONLY (1<<XIO_RDONLY)
|
||||||
|
#define XIOBIT_WRONLY (1<<XIO_WRONLY)
|
||||||
|
#define XIOBIT_RDWR (1<<XIO_RDWR)
|
||||||
|
#define XIOBIT_ALL (XIOBIT_RDONLY|XIOBIT_WRONLY|XIOBIT_RDWR)
|
||||||
|
#define XIOBIT_ALLRD (XIOBIT_RDONLY|XIOBIT_RDWR)
|
||||||
|
#define XIOBIT_ALLWR (XIOBIT_WRONLY|XIOBIT_RDWR)
|
||||||
|
#define XIOBIT_ONE (XIOBIT_RDONLY|XIOBIT_WRONLY)
|
||||||
|
/* reverse the direction pattern */
|
||||||
|
#define XIOBIT_REVERSE(x) (((x)&XIOBIT_RDWR)|(((x)&XIOBIT_RDONLY)?XIOBIT_WRONLY:0)|(((x)&XIOBIT_WRONLY)?XIOBIT_RDONLY:0))
|
||||||
|
|
||||||
/* methods for reading and writing, and for related checks */
|
/* methods for reading and writing, and for related checks */
|
||||||
#define XIODATA_READMASK 0xf000 /* mask for basic r/w method */
|
#define XIODATA_READMASK 0xf000 /* mask for basic r/w method */
|
||||||
|
@ -47,6 +66,7 @@ struct opt;
|
||||||
#define XIOREAD_PTY 0x4000 /* handle EIO */
|
#define XIOREAD_PTY 0x4000 /* handle EIO */
|
||||||
#define XIOREAD_READLINE 0x5000 /* ... */
|
#define XIOREAD_READLINE 0x5000 /* ... */
|
||||||
#define XIOREAD_OPENSSL 0x6000 /* SSL_read() */
|
#define XIOREAD_OPENSSL 0x6000 /* SSL_read() */
|
||||||
|
#define XIOREAD_TEST 0x7000 /* xioread_test() */
|
||||||
#define XIODATA_WRITEMASK 0x0f00 /* mask for basic r/w method */
|
#define XIODATA_WRITEMASK 0x0f00 /* mask for basic r/w method */
|
||||||
#define XIOWRITE_STREAM 0x0100 /* write() (default) */
|
#define XIOWRITE_STREAM 0x0100 /* write() (default) */
|
||||||
#define XIOWRITE_SENDTO 0x0200 /* sendto() */
|
#define XIOWRITE_SENDTO 0x0200 /* sendto() */
|
||||||
|
@ -54,6 +74,8 @@ struct opt;
|
||||||
#define XIOWRITE_2PIPE 0x0400 /* write() to alternate (2pipe) Fd */
|
#define XIOWRITE_2PIPE 0x0400 /* write() to alternate (2pipe) Fd */
|
||||||
#define XIOWRITE_READLINE 0x0500 /* check for prompt */
|
#define XIOWRITE_READLINE 0x0500 /* check for prompt */
|
||||||
#define XIOWRITE_OPENSSL 0x0600 /* SSL_write() */
|
#define XIOWRITE_OPENSSL 0x0600 /* SSL_write() */
|
||||||
|
#define XIOWRITE_TEST 0x0700 /* xiowrite_test() */
|
||||||
|
#define XIOWRITE_TESTREV 0x0800 /* xiowrite_testrev() */
|
||||||
/* modifiers to XIODATA_READ_RECV */
|
/* modifiers to XIODATA_READ_RECV */
|
||||||
#define XIOREAD_RECV_CHECKPORT 0x0001 /* recv, check peer port */
|
#define XIOREAD_RECV_CHECKPORT 0x0001 /* recv, check peer port */
|
||||||
#define XIOREAD_RECV_CHECKADDR 0x0002 /* recv, check peer address */
|
#define XIOREAD_RECV_CHECKADDR 0x0002 /* recv, check peer address */
|
||||||
|
@ -76,7 +98,46 @@ struct opt;
|
||||||
#define XIODATA_PTY (XIOREAD_PTY|XIOWRITE_STREAM)
|
#define XIODATA_PTY (XIOREAD_PTY|XIOWRITE_STREAM)
|
||||||
#define XIODATA_READLINE (XIOREAD_READLINE|XIOWRITE_STREAM)
|
#define XIODATA_READLINE (XIOREAD_READLINE|XIOWRITE_STREAM)
|
||||||
#define XIODATA_OPENSSL (XIOREAD_OPENSSL|XIOWRITE_OPENSSL)
|
#define XIODATA_OPENSSL (XIOREAD_OPENSSL|XIOWRITE_OPENSSL)
|
||||||
|
#define XIODATA_TEST (XIOREAD_TEST|XIOWRITE_TEST)
|
||||||
|
#define XIODATA_TESTUNI XIOWRITE_TEST
|
||||||
|
#define XIODATA_TESTREV XIOWRITE_TESTREV
|
||||||
|
|
||||||
|
/* XIOSHUT_* define the actions on shutdown of the address */
|
||||||
|
/* */
|
||||||
|
#define XIOSHUTRD_MASK 0x00f0
|
||||||
|
#define XIOSHUTWR_MASK 0x000f
|
||||||
|
#define XIOSHUTSPEC_MASK 0xff00 /* specific action */
|
||||||
|
#define XIOSHUTRD_UNSPEC 0x0000
|
||||||
|
#define XIOSHUTWR_UNSPEC 0x0000
|
||||||
|
#define XIOSHUTRD_NONE 0x0010 /* no action - e.g. stdin */
|
||||||
|
#define XIOSHUTWR_NONE 0x0001 /* no action - e.g. stdout */
|
||||||
|
#define XIOSHUTRD_CLOSE 0x0020 /* close() */
|
||||||
|
#define XIOSHUTWR_CLOSE 0x0002 /* close() */
|
||||||
|
#define XIOSHUTRD_DOWN 0x0030 /* shutdown(, SHUT_RD) */
|
||||||
|
#define XIOSHUTWR_DOWN 0x0003 /* shutdown(, SHUT_WR) */
|
||||||
|
#define XIOSHUTRD_SIGHUP 0x0040 /* kill sub process */
|
||||||
|
#define XIOSHUTWR_SIGHUP 0x0004 /* flush sub process with SIGHPUP */
|
||||||
|
#define XIOSHUTRD_SIGTERM 0x0050 /* kill sub process with SIGTERM */
|
||||||
|
#define XIOSHUTWR_SIGTERM 0x0005 /* kill sub process with SIGTERM */
|
||||||
|
#define XIOSHUTWR_SIGKILL 0x0006 /* kill sub process with SIGKILL */
|
||||||
|
#define XIOSHUT_UNSPEC (XIOSHUTRD_UNSPEC|XIOSHUTWR_UNSPEC)
|
||||||
|
#define XIOSHUT_NONE (XIOSHUTRD_NONE|XIOSHUTWR_NONE)
|
||||||
|
#define XIOSHUT_CLOSE (XIOSHUTRD_CLOSE|XIOSHUTWR_CLOSE)
|
||||||
|
#define XIOSHUT_DOWN (XIOSHUTRD_DOWN|XIOSHUTWR_DOWN)
|
||||||
|
#define XIOSHUT_KILL (XIOSHUTRD_KILL|XIOSHUTWR_KILL)
|
||||||
|
#define XIOSHUT_OPENSSL 0x0100 /* specific action on openssl */
|
||||||
|
/*!!!*/
|
||||||
|
|
||||||
|
#define XIOCLOSE_UNSPEC 0x0000 /* after init, when no end-close... option */
|
||||||
|
#define XIOCLOSE_NONE 0x0001 /* no action */
|
||||||
|
#define XIOCLOSE_CLOSE 0x0002 /* close() */
|
||||||
|
#define XIOCLOSE_SIGTERM 0x0003 /* send SIGTERM to sub process */
|
||||||
|
#define XIOCLOSE_SIGKILL 0x0004 /* send SIGKILL to sub process */
|
||||||
|
#define XIOCLOSE_CLOSE_SIGTERM 0x0005 /* close fd, then send SIGTERM */
|
||||||
|
#define XIOCLOSE_CLOSE_SIGKILL 0x0006 /* close fd, then send SIGKILL */
|
||||||
|
#define XIOCLOSE_SLEEP_SIGTERM 0x0007 /* short sleep, then SIGTERM */
|
||||||
|
#define XIOCLOSE_OPENSSL 0x0100
|
||||||
|
#define XIOCLOSE_READLINE 0x0101
|
||||||
|
|
||||||
/* these are the values allowed for the "enum xiotag tag" flag of the "struct
|
/* these are the values allowed for the "enum xiotag tag" flag of the "struct
|
||||||
single" and "union bipipe" (xiofile_t) structures. */
|
single" and "union bipipe" (xiofile_t) structures. */
|
||||||
|
@ -89,6 +150,88 @@ enum xiotag {
|
||||||
streams */
|
streams */
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
union bipipe;
|
||||||
|
|
||||||
|
|
||||||
|
#define XIOADDR_ENDPOINT 0 /* endpoint address */
|
||||||
|
#define XIOADDR_INTER 1 /* inter address */
|
||||||
|
#define XIOADDR_SYS XIOADDR_ENDPOINT
|
||||||
|
#define XIOADDR_PROT XIOADDR_INTER
|
||||||
|
|
||||||
|
struct xioaddr_inter_desc {
|
||||||
|
int tag; /* 0: endpoint addr; 1: inter addr */
|
||||||
|
const char *defname; /* main (canonical) name of address */
|
||||||
|
int numparams; /* number of required parameters */
|
||||||
|
int leftdirs; /* set of data directions supported on left side:
|
||||||
|
e.g. XIOBIT_RDONLY|XIOBIT_WRONLY|XIOBIT_RDWR */
|
||||||
|
unsigned groups;
|
||||||
|
int howtoshut;
|
||||||
|
int howtoclose;
|
||||||
|
int (*func)(int argc, const char *argv[], struct opt *opts, int rw, union bipipe *fd, unsigned groups,
|
||||||
|
int arg1, int arg2, int arg3);
|
||||||
|
int arg1;
|
||||||
|
int arg2;
|
||||||
|
int arg3;
|
||||||
|
int rightdirs;
|
||||||
|
#if WITH_HELP
|
||||||
|
const char *syntax;
|
||||||
|
#endif
|
||||||
|
} ;
|
||||||
|
|
||||||
|
struct xioaddr_endpoint_desc {
|
||||||
|
int tag; /* 0: endpoint addr; 1: inter addr */
|
||||||
|
const char *defname; /* main (canonical) name of address */
|
||||||
|
int numparams; /* number of required parameters */
|
||||||
|
int leftdirs;
|
||||||
|
unsigned groups;
|
||||||
|
int howtoshut;
|
||||||
|
int howtoclose;
|
||||||
|
int (*func)(int argc, const char *argv[], struct opt *opts, int rw, union bipipe *fd, unsigned groups,
|
||||||
|
int arg1, int arg2, int arg3);
|
||||||
|
int arg1;
|
||||||
|
int arg2;
|
||||||
|
int arg3;
|
||||||
|
#if WITH_HELP
|
||||||
|
const char *syntax;
|
||||||
|
#endif
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
struct xioaddr_common_desc {
|
||||||
|
int tag; /* 0: endpoint addr; 1: inter addr */
|
||||||
|
const char *defname; /* main (canonical) name of address */
|
||||||
|
int numparams; /* number of required parameters */
|
||||||
|
int leftdirs;
|
||||||
|
unsigned groups;
|
||||||
|
int howtoshut;
|
||||||
|
int howtoclose;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
union xioaddr_desc {
|
||||||
|
int tag; /* 0: endpoint addr; 1: inter addr */
|
||||||
|
struct xioaddr_common_desc common_desc;
|
||||||
|
struct xioaddr_inter_desc inter_desc;
|
||||||
|
struct xioaddr_endpoint_desc endpoint_desc;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
union xioaddr_descp {
|
||||||
|
struct xioaddr_common_desc *common_desc;
|
||||||
|
int *tag; /* 0: endpoint addr; 1: inter addr */
|
||||||
|
struct xioaddr_inter_desc *inter_desc;
|
||||||
|
struct xioaddr_endpoint_desc *endpoint_desc;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
/*!!! this to xio-sockd4.h */
|
||||||
|
struct socks4head {
|
||||||
|
uint8_t version;
|
||||||
|
uint8_t action;
|
||||||
|
uint16_t port;
|
||||||
|
uint32_t dest;
|
||||||
|
} ;
|
||||||
|
|
||||||
/* global XIO options/parameters */
|
/* global XIO options/parameters */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool strictopts;
|
bool strictopts;
|
||||||
|
@ -97,11 +240,22 @@ typedef struct {
|
||||||
const char *optionsep;
|
const char *optionsep;
|
||||||
char ip4portsep;
|
char ip4portsep;
|
||||||
char ip6portsep; /* do not change, might be hardcoded somewhere! */
|
char ip6portsep; /* do not change, might be hardcoded somewhere! */
|
||||||
char logopt; /* 'm' means "switch to syslog when entering daemon mode" */
|
|
||||||
const char *syslogfac; /* syslog facility (only with mixed mode) */
|
const char *syslogfac; /* syslog facility (only with mixed mode) */
|
||||||
char default_ip; /* default prot.fam for IP based listen ('4' or '6') */
|
char default_ip; /* default prot.fam for IP based listen ('4' or '6') */
|
||||||
char preferred_ip; /* preferred prot.fam. for name resolution ('0' for
|
char preferred_ip; /* preferred prot.fam. for name resolution ('0' for
|
||||||
unspecified, '4', or '6') */
|
unspecified, '4', or '6') */
|
||||||
|
char *reversechar;
|
||||||
|
char *chainsep;
|
||||||
|
size_t bufsiz;
|
||||||
|
bool verbose;
|
||||||
|
bool verbhex;
|
||||||
|
bool debug;
|
||||||
|
char logopt; /* y..syslog; s..stderr; f..file; m..mixed */
|
||||||
|
struct timeval total_timeout;/* when nothing happens, die after seconds */
|
||||||
|
struct timeval pollintv; /* with ignoreeof, reread after seconds */
|
||||||
|
struct timeval closwait; /* after close of x, die after seconds */
|
||||||
|
bool lefttoright; /* first addr ro, second addr wo */
|
||||||
|
bool righttoleft; /* first addr wo, second addr ro */
|
||||||
} xioopts_t;
|
} xioopts_t;
|
||||||
|
|
||||||
/* pack the description of a lock file */
|
/* pack the description of a lock file */
|
||||||
|
@ -111,14 +265,12 @@ typedef struct {
|
||||||
struct timespec intervall; /* polling intervall */
|
struct timespec intervall; /* polling intervall */
|
||||||
} xiolock_t;
|
} xiolock_t;
|
||||||
|
|
||||||
extern xioopts_t xioopts;
|
|
||||||
|
|
||||||
#define MAXARGV 8
|
#define MAXARGV 8
|
||||||
|
|
||||||
/* a non-dual file descriptor */
|
/* a non-dual file descriptor */
|
||||||
typedef struct single {
|
typedef struct single {
|
||||||
enum xiotag tag; /* see enum xiotag */
|
enum xiotag tag; /* see enum xiotag */
|
||||||
const struct addrdesc *addr;
|
const union xioaddr_desc *addrdesc;
|
||||||
int flags;
|
int flags;
|
||||||
/* until here, keep consistent with bipipe.common !!! */
|
/* until here, keep consistent with bipipe.common !!! */
|
||||||
#if WITH_RETRY
|
#if WITH_RETRY
|
||||||
|
@ -136,26 +288,41 @@ typedef struct single {
|
||||||
size_t actbytes; /* so many bytes still to be read (when readbytes!=0)*/
|
size_t actbytes; /* so many bytes still to be read (when readbytes!=0)*/
|
||||||
xiolock_t lock; /* parameters of lockfile */
|
xiolock_t lock; /* parameters of lockfile */
|
||||||
bool havelock; /* we are happy owner of the above lock */
|
bool havelock; /* we are happy owner of the above lock */
|
||||||
bool cool_write; /* downlevel EPIPE, ECONNRESET to notice */
|
|
||||||
/* until here, keep consistent with bipipe.dual ! */
|
/* until here, keep consistent with bipipe.dual ! */
|
||||||
|
int reverse; /* valid during parse and overload, before open:
|
||||||
|
will this (inter) address be integrated forward or
|
||||||
|
reverse? */
|
||||||
|
const union xioaddr_desc **addrdescs;
|
||||||
|
/* valid after parse, before overload:
|
||||||
|
the list of possible address descriptors derived
|
||||||
|
from addr keyword, one of which will be selected by
|
||||||
|
context and num of parameters */
|
||||||
|
int closing; /* 0..write channel is up, 1..just shutdown write ch.,
|
||||||
|
2..counting down closing timeout, 3..no more write
|
||||||
|
possible */
|
||||||
|
bool cool_write; /* downlevel EPIPE, ECONNRESET to notice */
|
||||||
int argc; /* number of fields in argv */
|
int argc; /* number of fields in argv */
|
||||||
const char *argv[MAXARGV]; /* address keyword, required args */
|
const char *argv[MAXARGV]; /* address keyword, required args */
|
||||||
struct opt *opts; /* the options of this address */
|
struct opt *opts; /* the options of this address */
|
||||||
int lineterm; /* 0..dont touch; 1..CR; 2..CRNL on extern data */
|
int lineterm; /* 0..dont touch; 1..CR; 2..CRNL on extern data */
|
||||||
int fd;
|
int fd1;
|
||||||
|
int fd2;
|
||||||
|
enum {
|
||||||
|
FDTYPE_SINGLE, /* only fd1 is in use, for reading and/or writing */
|
||||||
|
FDTYPE_DOUBLE /* fd2 is in use too - for writing */
|
||||||
|
} fdtype;
|
||||||
|
pid_t subaddrpid; /* pid of subaddress (process handling next addr in
|
||||||
|
chain) */
|
||||||
|
int subaddrstat; /* state of subaddress process
|
||||||
|
0...no sub address process
|
||||||
|
1...running
|
||||||
|
-1...ended (aborted?) */
|
||||||
|
int subaddrexit; /* if subaddstat==-1: exit code of sub process */
|
||||||
bool opt_unlink_close; /* option unlink_close */
|
bool opt_unlink_close; /* option unlink_close */
|
||||||
char *unlink_close; /* name of a symlink or unix socket to be removed */
|
char *unlink_close; /* name of a symlink or unix socket to be removed */
|
||||||
int dtype;
|
int dtype;
|
||||||
enum {
|
int howtoshut; /* method for shutting down xfds */
|
||||||
END_UNSPEC, /* after init, when no end-close... option */
|
int howtoclose; /* method for closing xfds */
|
||||||
END_NONE, /* no action */
|
|
||||||
END_CLOSE, /* close() */
|
|
||||||
END_SHUTDOWN, /* shutdown() */
|
|
||||||
END_UNLINK, /* unlink() */
|
|
||||||
END_KILL, /* has subprocess */
|
|
||||||
END_CLOSE_KILL, /* first close fd, then kill subprocess */
|
|
||||||
END_SHUTDOWN_KILL /* first shutdown fd, then kill subprocess */
|
|
||||||
} howtoend;
|
|
||||||
#if _WITH_SOCKET
|
#if _WITH_SOCKET
|
||||||
union sockaddr_union peersa;
|
union sockaddr_union peersa;
|
||||||
socklen_t salen;
|
socklen_t salen;
|
||||||
|
@ -164,13 +331,19 @@ typedef struct single {
|
||||||
bool ttyvalid; /* the following struct is valid */
|
bool ttyvalid; /* the following struct is valid */
|
||||||
struct termios savetty; /* save orig tty settings for later restore */
|
struct termios savetty; /* save orig tty settings for later restore */
|
||||||
#endif /* WITH_TERMIOS */
|
#endif /* WITH_TERMIOS */
|
||||||
const char *name; /* only with END_UNLINK */
|
/*0 const char *name;*/ /* only with END_UNLINK */
|
||||||
|
struct { /* this was for exec only, now for embedded */
|
||||||
|
pid_t pid; /* child PID, with EXEC: */
|
||||||
int (*sigchild)(struct single *); /* callback after sigchild */
|
int (*sigchild)(struct single *); /* callback after sigchild */
|
||||||
|
} child;
|
||||||
pid_t ppid; /* parent pid, only if we send it signals */
|
pid_t ppid; /* parent pid, only if we send it signals */
|
||||||
|
pthread_t subthread; /* thread handling next inter-addr in chain */
|
||||||
union {
|
union {
|
||||||
|
#if 0
|
||||||
struct {
|
struct {
|
||||||
int fdout; /* use fd for output */
|
int fdout; /* use fd for output */
|
||||||
} bipipe;
|
} bipipe;
|
||||||
|
#endif
|
||||||
#if _WITH_SOCKET
|
#if _WITH_SOCKET
|
||||||
struct {
|
struct {
|
||||||
struct timeval connect_timeout; /* how long to hang in connect() */
|
struct timeval connect_timeout; /* how long to hang in connect() */
|
||||||
|
@ -213,6 +386,37 @@ typedef struct single {
|
||||||
#endif
|
#endif
|
||||||
} readline;
|
} readline;
|
||||||
#endif /* WITH_READLINE */
|
#endif /* WITH_READLINE */
|
||||||
|
#if WITH_SOCKS4_SERVER
|
||||||
|
struct {
|
||||||
|
int state; /* state of socks4 protocol negotiation */
|
||||||
|
/* we cannot rely on all request data arriving at once */
|
||||||
|
struct socks4head head;
|
||||||
|
char *userid;
|
||||||
|
char *hostname; /* socks4a only */
|
||||||
|
/* the following structs are an experiment for future synchronization
|
||||||
|
mechanisms */
|
||||||
|
struct {
|
||||||
|
size_t canrecv;
|
||||||
|
size_t wantwrite;
|
||||||
|
void *inbuff;
|
||||||
|
size_t inbuflen; /* length of buffer */
|
||||||
|
size_t bytes; /* current bytes in buffer */
|
||||||
|
} proto;
|
||||||
|
struct {
|
||||||
|
size_t canrecv;
|
||||||
|
size_t wantwrite;
|
||||||
|
} peer_proto;
|
||||||
|
struct {
|
||||||
|
size_t canrecv;
|
||||||
|
size_t wantwrite;
|
||||||
|
int _errno;
|
||||||
|
} data;
|
||||||
|
struct {
|
||||||
|
size_t canrecv;
|
||||||
|
size_t wantwrite;
|
||||||
|
} peer_data;
|
||||||
|
} socks4d;
|
||||||
|
#endif /* WITH_SOCKS4_SERVER */
|
||||||
#if WITH_OPENSSL
|
#if WITH_OPENSSL
|
||||||
struct {
|
struct {
|
||||||
struct timeval connect_timeout; /* how long to hang in connect() */
|
struct timeval connect_timeout; /* how long to hang in connect() */
|
||||||
|
@ -225,6 +429,13 @@ typedef struct single {
|
||||||
short iff_opts[2]; /* ifr flags, using OFUNC_OFFSET_MASKS */
|
short iff_opts[2]; /* ifr flags, using OFUNC_OFFSET_MASKS */
|
||||||
} tun;
|
} tun;
|
||||||
#endif /* WITH_TUN */
|
#endif /* WITH_TUN */
|
||||||
|
#if _WITH_GZIP
|
||||||
|
struct {
|
||||||
|
gzFile in; /* for reading (uncompressing from stream to API) */
|
||||||
|
gzFile out; /* for writing (compressing from API to stream) */
|
||||||
|
int level;
|
||||||
|
} gzip;
|
||||||
|
#endif /* _WITH_GZIP */
|
||||||
} para;
|
} para;
|
||||||
} xiosingle_t;
|
} xiosingle_t;
|
||||||
|
|
||||||
|
@ -242,13 +453,13 @@ typedef union bipipe {
|
||||||
enum xiotag tag;
|
enum xiotag tag;
|
||||||
struct {
|
struct {
|
||||||
enum xiotag tag;
|
enum xiotag tag;
|
||||||
const struct addrdesc *addr;
|
const union xioaddr_desc *addrdesc;
|
||||||
int flags;
|
int flags;
|
||||||
} common;
|
} common;
|
||||||
struct single stream;
|
struct single stream;
|
||||||
struct {
|
struct {
|
||||||
enum xiotag tag;
|
enum xiotag tag;
|
||||||
const struct addrdesc *addr;
|
const union xioaddr_desc *addrdesc;
|
||||||
int flags; /* compatible to fcntl(.., F_GETFL, ..) */
|
int flags; /* compatible to fcntl(.., F_GETFL, ..) */
|
||||||
#if WITH_RETRY
|
#if WITH_RETRY
|
||||||
unsigned retry; /* retry opening this many times */
|
unsigned retry; /* retry opening this many times */
|
||||||
|
@ -262,31 +473,19 @@ typedef union bipipe {
|
||||||
size_t actbytes; /* so many bytes still to be read */
|
size_t actbytes; /* so many bytes still to be read */
|
||||||
xiolock_t lock; /* parameters of lockfile */
|
xiolock_t lock; /* parameters of lockfile */
|
||||||
bool havelock; /* we are happy owner of the above lock */
|
bool havelock; /* we are happy owner of the above lock */
|
||||||
|
/* until here, keep consistent with struct single ! */
|
||||||
xiosingle_t *stream[2]; /* input stream, output stream */
|
xiosingle_t *stream[2]; /* input stream, output stream */
|
||||||
} dual;
|
} dual;
|
||||||
} xiofile_t;
|
} xiofile_t;
|
||||||
|
|
||||||
|
|
||||||
struct addrdesc {
|
|
||||||
const char *defname; /* main (canonical) name of address */
|
|
||||||
int directions; /* 1..read, 2..write, 3..both */
|
|
||||||
int (*func)(int argc, const char *argv[], struct opt *opts, int rw, xiofile_t *fd, unsigned groups,
|
|
||||||
int arg1, int arg2, int arg3);
|
|
||||||
unsigned groups;
|
|
||||||
int arg1;
|
|
||||||
int arg2;
|
|
||||||
int arg3;
|
|
||||||
#if WITH_HELP
|
|
||||||
const char *syntax;
|
|
||||||
#endif
|
|
||||||
} ;
|
|
||||||
|
|
||||||
#define XIO_WRITABLE(s) (((s)->common.flags+1)&2)
|
#define XIO_WRITABLE(s) (((s)->common.flags+1)&2)
|
||||||
#define XIO_READABLE(s) (((s)->common.flags+1)&1)
|
#define XIO_READABLE(s) (((s)->common.flags+1)&1)
|
||||||
#define XIO_RDSTREAM(s) (((s)->tag==XIO_TAG_DUAL)?(s)->dual.stream[0]:&(s)->stream)
|
#define XIO_RDSTREAM(s) (((s)->tag==XIO_TAG_DUAL)?(s)->dual.stream[0]:&(s)->stream)
|
||||||
#define XIO_WRSTREAM(s) (((s)->tag==XIO_TAG_DUAL)?(s)->dual.stream[1]:&(s)->stream)
|
#define XIO_WRSTREAM(s) (((s)->tag==XIO_TAG_DUAL)?(s)->dual.stream[1]:&(s)->stream)
|
||||||
#define XIO_GETRDFD(s) (((s)->tag==XIO_TAG_DUAL)?(s)->dual.stream[0]->fd:(s)->stream.fd)
|
#define XIO_GETRDFD(s) (((s)->tag==XIO_TAG_DUAL)?(s)->dual.stream[0]->fd1:(s)->stream.fd1)
|
||||||
#define XIO_GETWRFD(s) (((s)->tag==XIO_TAG_DUAL)?(s)->dual.stream[1]->fd:(((s)->stream.dtype&XIODATA_WRITEMASK)==XIOWRITE_2PIPE)?(s)->stream.para.exec.fdout:(((s)->stream.dtype&XIODATA_WRITEMASK)==XIOWRITE_PIPE)?(s)->stream.para.bipipe.fdout:(s)->stream.fd)
|
#define _XIO_GETWRFD(s) (((s)->fdtype==FDTYPE_DOUBLE)?(s)->fd2:(s)->fd1)
|
||||||
|
#define XIO_GETWRFD(s) (((s)->tag==XIO_TAG_DUAL)?_XIO_GETWRFD((s)->dual.stream[1]):_XIO_GETWRFD(&(s)->stream))
|
||||||
#define XIO_EOF(s) (XIO_RDSTREAM(s)->eof && !XIO_RDSTREAM(s)->ignoreeof)
|
#define XIO_EOF(s) (XIO_RDSTREAM(s)->eof && !XIO_RDSTREAM(s)->ignoreeof)
|
||||||
|
|
||||||
typedef unsigned long flags_t;
|
typedef unsigned long flags_t;
|
||||||
|
@ -357,6 +556,12 @@ struct opt {
|
||||||
union integral value;
|
union integral value;
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
/* with threading, the arguments indirectly passed to xioengine() */
|
||||||
|
struct threadarg_struct {
|
||||||
|
xiofile_t *xfd1;
|
||||||
|
xiofile_t *xfd2;
|
||||||
|
} ;
|
||||||
|
|
||||||
extern const char *PIPESEP;
|
extern const char *PIPESEP;
|
||||||
extern xiofile_t *sock[XIO_MAXSOCK];
|
extern xiofile_t *sock[XIO_MAXSOCK];
|
||||||
|
|
||||||
|
@ -372,33 +577,39 @@ extern xiofile_t *sock[XIO_MAXSOCK];
|
||||||
#define STAT_NORETRY -3 /* address syntax error, not implemented etc;
|
#define STAT_NORETRY -3 /* address syntax error, not implemented etc;
|
||||||
not even by external changes correctable */
|
not even by external changes correctable */
|
||||||
|
|
||||||
extern int xioinitialize(void);
|
extern int xioinitialize(int xioflags);
|
||||||
extern int xio_forked_inchild(void);
|
extern int xio_forked_inchild(void);
|
||||||
extern int xiosetopt(char what, const char *arg);
|
extern int xiosetopt(char what, const char *arg);
|
||||||
extern int xioinqopt(char what, char *arg, size_t n);
|
extern int xioinqopt(char what, char *arg, size_t n);
|
||||||
extern xiofile_t *xioopen(const char *args, int flags);
|
extern xiofile_t *xioopen(const char *args, int xioflags);
|
||||||
extern int xioopensingle(char *addr, struct single *xfd, int xioflags);
|
extern xiofile_t *xioopenx(const char *addr, int xioflags, int infd, int outfd);extern int xiosocketpair(xiofile_t **xfd1p, xiofile_t **xfd2p, int how, ...);
|
||||||
|
|
||||||
|
extern int xioopensingle(char *addr, xiosingle_t *fd, int xioflags);
|
||||||
extern int xioopenhelp(FILE *of, int level);
|
extern int xioopenhelp(FILE *of, int level);
|
||||||
|
|
||||||
/* must be outside function for use by childdied handler */
|
/* must be outside function for use by childdied handler */
|
||||||
extern xiofile_t *sock1, *sock2;
|
extern xiofile_t *xioallocfd(void);
|
||||||
extern pid_t diedunknown1; /* child died before it is registered */
|
extern void xiofreefd(xiofile_t *xfd);
|
||||||
extern pid_t diedunknown2;
|
|
||||||
extern pid_t diedunknown3;
|
|
||||||
extern pid_t diedunknown4;
|
|
||||||
|
|
||||||
extern int xiosetsigchild(xiofile_t *xfd, int (*callback)(struct single *));
|
|
||||||
extern int xio_opt_signal(pid_t pid, int signum);
|
extern int xio_opt_signal(pid_t pid, int signum);
|
||||||
extern void childdied(int signum);
|
|
||||||
|
|
||||||
|
extern void *xioengine(void *thread_arg);
|
||||||
|
extern int _socat(xiofile_t *xfd1, xiofile_t *xfd2);
|
||||||
extern ssize_t xioread(xiofile_t *sock1, void *buff, size_t bufsiz);
|
extern ssize_t xioread(xiofile_t *sock1, void *buff, size_t bufsiz);
|
||||||
extern ssize_t xiopending(xiofile_t *sock1);
|
extern ssize_t xiopending(xiofile_t *sock1);
|
||||||
extern ssize_t xiowrite(xiofile_t *sock1, const void *buff, size_t bufsiz);
|
extern ssize_t xiowrite(xiofile_t *sock1, const void *buff, size_t bufsiz);
|
||||||
|
extern int xiotransfer(xiofile_t *inpipe, xiofile_t *outpipe,
|
||||||
|
unsigned char **buff, size_t bufsiz, bool righttoleft);
|
||||||
extern int xioshutdown(xiofile_t *sock, int how);
|
extern int xioshutdown(xiofile_t *sock, int how);
|
||||||
|
|
||||||
extern int xioclose(xiofile_t *sock);
|
extern int xioclose(xiofile_t *sock);
|
||||||
extern void xioexit(void);
|
extern void xioexit(void);
|
||||||
|
|
||||||
extern int (*xiohook_newchild)(void); /* xio calls this function from a new child process */
|
extern int (*xiohook_newchild)(void); /* xio calls this function from a new child process */
|
||||||
|
extern int socat_sigchild(struct single *file);
|
||||||
|
|
||||||
|
|
||||||
|
extern xioopts_t xioopts, *xioparams;
|
||||||
|
|
||||||
|
|
||||||
#endif /* !defined(__xio_h_included) */
|
#endif /* !defined(__xio_h_included) */
|
||||||
|
|
81
xioclose.c
81
xioclose.c
|
@ -21,63 +21,82 @@ int xioclose1(struct single *pipe) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (pipe->howtoclose) {
|
||||||
|
|
||||||
#if WITH_READLINE
|
#if WITH_READLINE
|
||||||
if ((pipe->dtype & XIODATA_MASK) == XIODATA_READLINE) {
|
case XIOCLOSE_READLINE:
|
||||||
Write_history(pipe->para.readline.history_file);
|
Write_history(pipe->para.readline.history_file);
|
||||||
/*xiotermios_setflag(pipe->fd, 3, ECHO|ICANON);*/ /* error when pty closed */
|
/*xiotermios_setflag(pipe->fd, 3, ECHO|ICANON);*/ /* error when pty closed */
|
||||||
}
|
break;
|
||||||
#endif /* WITH_READLINE */
|
#endif /* WITH_READLINE */
|
||||||
|
|
||||||
#if WITH_OPENSSL
|
#if WITH_OPENSSL
|
||||||
if ((pipe->dtype & XIODATA_MASK) == XIODATA_OPENSSL) {
|
case XIOCLOSE_OPENSSL:
|
||||||
if (pipe->para.openssl.ssl) {
|
if (pipe->para.openssl.ssl) {
|
||||||
/* e.g. on TCP connection refused, we do not yet have this set */
|
/* e.g. on TCP connection refused, we do not yet have this set */
|
||||||
sycSSL_shutdown(pipe->para.openssl.ssl);
|
sycSSL_shutdown(pipe->para.openssl.ssl);
|
||||||
sycSSL_free(pipe->para.openssl.ssl);
|
sycSSL_free(pipe->para.openssl.ssl);
|
||||||
pipe->para.openssl.ssl = NULL;
|
pipe->para.openssl.ssl = NULL;
|
||||||
}
|
}
|
||||||
Close(pipe->fd); pipe->fd = -1;
|
Close(pipe->fd1); pipe->fd1 = -1;
|
||||||
|
Close(pipe->fd2); pipe->fd2 = -1;
|
||||||
if (pipe->para.openssl.ctx) {
|
if (pipe->para.openssl.ctx) {
|
||||||
sycSSL_CTX_free(pipe->para.openssl.ctx);
|
sycSSL_CTX_free(pipe->para.openssl.ctx);
|
||||||
pipe->para.openssl.ctx = NULL;
|
pipe->para.openssl.ctx = NULL;
|
||||||
}
|
}
|
||||||
} else
|
break;
|
||||||
#endif /* WITH_OPENSSL */
|
#endif /* WITH_OPENSSL */
|
||||||
|
|
||||||
#if WITH_TERMIOS
|
#if WITH_TERMIOS
|
||||||
if (pipe->ttyvalid) {
|
if (pipe->ttyvalid) {
|
||||||
if (Tcsetattr(pipe->fd, 0, &pipe->savetty) < 0) {
|
if (Tcsetattr(pipe->fd1, 0, &pipe->savetty) < 0) {
|
||||||
Warn2("cannot restore terminal settings on fd %d: %s",
|
Warn2("cannot restore terminal settings on fd %d: %s",
|
||||||
pipe->fd, strerror(errno));
|
pipe->fd1, strerror(errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WITH_TERMIOS */
|
#endif /* WITH_TERMIOS */
|
||||||
if (pipe->fd >= 0) {
|
|
||||||
switch (pipe->howtoend) {
|
case XIOCLOSE_SIGTERM:
|
||||||
case END_KILL: case END_SHUTDOWN_KILL: case END_CLOSE_KILL:
|
if (pipe->child.pid > 0) {
|
||||||
if (pipe->para.exec.pid > 0) {
|
if (Kill(pipe->child.pid, SIGTERM) < 0) {
|
||||||
if (Kill(pipe->para.exec.pid, SIGTERM) < 0) {
|
|
||||||
Msg2(errno==ESRCH?E_INFO:E_WARN, "kill(%d, SIGTERM): %s",
|
Msg2(errno==ESRCH?E_INFO:E_WARN, "kill(%d, SIGTERM): %s",
|
||||||
pipe->para.exec.pid, strerror(errno));
|
pipe->child.pid, strerror(errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case XIOCLOSE_CLOSE_SIGTERM:
|
||||||
|
if (pipe->child.pid > 0) {
|
||||||
|
if (Kill(pipe->child.pid, SIGTERM) < 0) {
|
||||||
|
Msg2(errno==ESRCH?E_INFO:E_WARN, "kill(%d, SIGTERM): %s",
|
||||||
|
pipe->child.pid, strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*PASSTHROUGH*/
|
||||||
|
case XIOCLOSE_CLOSE:
|
||||||
|
if (pipe->fd1 >= 0) {
|
||||||
|
if (Close(pipe->fd1) < 0) {
|
||||||
|
Info2("close(%d): %s", pipe->fd1, strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XIOCLOSE_SLEEP_SIGTERM:
|
||||||
|
Sleep(1);
|
||||||
|
if (pipe->child.pid > 0) {
|
||||||
|
if (Kill(pipe->child.pid, SIGTERM) < 0) {
|
||||||
|
Msg2(errno==ESRCH?E_INFO:E_WARN, "kill(%d, SIGTERM): %s",
|
||||||
|
pipe->child.pid, strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XIOCLOSE_NONE:
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
Error2("xioclose(): bad end action 0x%x on 0x%x", pipe->howtoclose, pipe);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
switch (pipe->howtoend) {
|
|
||||||
case END_CLOSE: case END_CLOSE_KILL:
|
|
||||||
if (Close(pipe->fd) < 0) {
|
|
||||||
Info2("close(%d): %s", pipe->fd, strerror(errno)); } break;
|
|
||||||
#if WITH_SOCKET
|
|
||||||
case END_SHUTDOWN: case END_SHUTDOWN_KILL:
|
|
||||||
if (Shutdown(pipe->fd, 2) < 0) {
|
|
||||||
Info3("shutdown(%d, %d): %s", pipe->fd, 2, strerror(errno)); }
|
|
||||||
break;
|
|
||||||
#endif /* WITH_SOCKET */
|
|
||||||
case END_UNLINK: if (Unlink((const char *)pipe->name) < 0) {
|
|
||||||
Warn2("unlink(\"%s\"): %s", pipe->name, strerror(errno)); }
|
|
||||||
break;
|
|
||||||
case END_NONE: default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* unlock */
|
/* unlock */
|
||||||
if (pipe->havelock) {
|
if (pipe->havelock) {
|
||||||
|
@ -98,6 +117,7 @@ int xioclose1(struct single *pipe) {
|
||||||
|
|
||||||
/* close the xio fd */
|
/* close the xio fd */
|
||||||
int xioclose(xiofile_t *file) {
|
int xioclose(xiofile_t *file) {
|
||||||
|
xiofile_t *xfd = file;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
if (file->tag == XIO_TAG_INVALID) {
|
if (file->tag == XIO_TAG_INVALID) {
|
||||||
|
@ -113,6 +133,9 @@ int xioclose(xiofile_t *file) {
|
||||||
} else {
|
} else {
|
||||||
result = xioclose1(&file->stream);
|
result = xioclose1(&file->stream);
|
||||||
}
|
}
|
||||||
|
if (xfd->stream.subthread != 0) {
|
||||||
|
Pthread_join(xfd->stream.subthread, NULL);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
37
xioconfig.h
37
xioconfig.h
|
@ -21,23 +21,26 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if WITH_SOCKS4A
|
#if WITH_SOCKS4A
|
||||||
# define WITH_SOCKS4 1
|
# define _WITH_SOCKS4 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if WITH_SOCKS4 || WITH_PROXY
|
#if WITH_SOCKS4 || WITH_SOCKS5 || WITH_PROXY
|
||||||
# define WITH_TCP 1
|
# define _WITH_TCP 1
|
||||||
# define WITH_IP4 1 /* currently this socks implementation does not work
|
# define _WITH_IP4 1 /* currently this socks implementation does not work
|
||||||
with IP6 */
|
with IP6 */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if WITH_OPENSSL
|
#if 0
|
||||||
# define WITH_TCP 1
|
#if !defined(HAVE_NETINET_IP6_H)
|
||||||
# define WITH_IP4 1
|
# undef WITH_IP6
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if WITH_IP6
|
#if WITH_OPENSSL
|
||||||
# if !defined(HAVE_NETINET_IP6_H)
|
# define _WITH_TCP 1
|
||||||
# undef WITH_IP6
|
# define _WITH_IP4 1
|
||||||
|
# if WITH_IP6
|
||||||
|
# define _WITH_IP6 1
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -47,7 +50,11 @@
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if WITH_UNIX || WITH_IP4 || WITH_IP6 || WITH_SOCKS4 || WITH_RAWIP
|
#if WITH_UNIX || HAVE_SYS_UN_H
|
||||||
|
# define _WITH_UNIX 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if WITH_IP4 || WITH_IP6 || WITH_SOCKS4 || WITH_RAWIP || _WITH_UNIX
|
||||||
# define WITH_SOCKET 1
|
# define WITH_SOCKET 1
|
||||||
#else
|
#else
|
||||||
# undef WITH_SOCKET
|
# undef WITH_SOCKET
|
||||||
|
@ -65,6 +72,14 @@
|
||||||
# define _WITH_SOCKET 1
|
# define _WITH_SOCKET 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if WITH_TCP
|
||||||
|
# define _WITH_TCP 1
|
||||||
|
# define _WITH_IP4 1
|
||||||
|
# if WITH_IP6
|
||||||
|
# define _WITH_IP6 1
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#if WITH_IP4 || WITH_TUN
|
#if WITH_IP4 || WITH_TUN
|
||||||
# define _WITH_IP4 1
|
# define _WITH_IP4 1
|
||||||
#endif
|
#endif
|
||||||
|
|
434
xioengine.c
Normal file
434
xioengine.c
Normal file
|
@ -0,0 +1,434 @@
|
||||||
|
/* $Id$ */
|
||||||
|
/* Copyright Gerhard Rieger 2007 */
|
||||||
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
|
/* this is the source file of the socat transfer loop/engine */
|
||||||
|
|
||||||
|
#include "xiosysincludes.h"
|
||||||
|
|
||||||
|
#include "xioopen.h"
|
||||||
|
#include "xiosigchld.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* checks if this is a connection to a child process, and if so, sees if the
|
||||||
|
child already died, leaving some data for us.
|
||||||
|
returns <0 if an error occurred;
|
||||||
|
returns 0 if no child or not yet died or died without data (sets eof);
|
||||||
|
returns >0 if child died and left data
|
||||||
|
*/
|
||||||
|
int childleftdata(xiofile_t *xfd) {
|
||||||
|
fd_set in, out, expt;
|
||||||
|
int retval;
|
||||||
|
/* have to check if a child process died before, but left read data */
|
||||||
|
if (XIO_READABLE(xfd) &&
|
||||||
|
(XIO_RDSTREAM(xfd)->howtoclose == XIOCLOSE_SIGTERM ||
|
||||||
|
XIO_RDSTREAM(xfd)->howtoclose == XIOCLOSE_SIGKILL ||
|
||||||
|
XIO_RDSTREAM(xfd)->howtoclose == XIOCLOSE_CLOSE_SIGTERM ||
|
||||||
|
XIO_RDSTREAM(xfd)->howtoclose == XIOCLOSE_CLOSE_SIGKILL) &&
|
||||||
|
XIO_RDSTREAM(xfd)->child.pid == 0) {
|
||||||
|
struct timeval time0 = { 0,0 };
|
||||||
|
|
||||||
|
FD_ZERO(&in); FD_ZERO(&out); FD_ZERO(&expt);
|
||||||
|
if (XIO_READABLE(xfd) && !(XIO_RDSTREAM(xfd)->eof >= 2 && !XIO_RDSTREAM(xfd)->ignoreeof)) {
|
||||||
|
FD_SET(XIO_GETRDFD(xfd), &in);
|
||||||
|
/*0 FD_SET(XIO_GETRDFD(xfd), &expt);*/
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
retval = Select(FD_SETSIZE, &in, &out, &expt, &time0);
|
||||||
|
} while (retval < 0 && errno == EINTR);
|
||||||
|
|
||||||
|
if (retval < 0) {
|
||||||
|
#if HAVE_FDS_BITS
|
||||||
|
Error5("select(%d, &0x%lx, &0x%lx, &0x%lx, {0}): %s",
|
||||||
|
FD_SETSIZE, in.fds_bits[0], out.fds_bits[0],
|
||||||
|
expt.fds_bits[0], strerror(errno));
|
||||||
|
#else
|
||||||
|
Error5("select(%d, &0x%lx, &0x%lx, &0x%lx, {0}): %s",
|
||||||
|
FD_SETSIZE, in.__fds_bits[0], out.__fds_bits[0],
|
||||||
|
expt.__fds_bits[0], strerror(errno));
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
} else if (retval == 0) {
|
||||||
|
Info("terminated child did not leave data for us");
|
||||||
|
XIO_RDSTREAM(xfd)->eof = 2;
|
||||||
|
xfd->stream.eof = 2;
|
||||||
|
/*0 closing = MAX(closing, 1);*/
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *xioengine(void *thread_arg) {
|
||||||
|
struct threadarg_struct *engine_arg = thread_arg;
|
||||||
|
|
||||||
|
_socat(engine_arg->xfd1, engine_arg->xfd2);
|
||||||
|
free(engine_arg);
|
||||||
|
return NULL/*!*/;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* here we come when the sockets are opened (in the meaning of C language),
|
||||||
|
and their options are set/applied
|
||||||
|
returns -1 on error or 0 on success */
|
||||||
|
int _socat(xiofile_t *xfd1, xiofile_t *xfd2) {
|
||||||
|
xiofile_t *sock1, *sock2;
|
||||||
|
fd_set in, out, expt;
|
||||||
|
int retval;
|
||||||
|
unsigned char *buff;
|
||||||
|
ssize_t bytes1, bytes2;
|
||||||
|
int polling = 0; /* handling ignoreeof */
|
||||||
|
int wasaction = 1; /* last select was active, do NOT sleep before next */
|
||||||
|
struct timeval total_timeout; /* the actual total timeout timer */
|
||||||
|
bool mayrd1 = false; /* sock1 has read data or eof, according to select() */
|
||||||
|
bool mayrd2 = false; /* sock2 has read data or eof, according to select() */
|
||||||
|
bool maywr1 = false; /* sock1 can be written to, according to select() */
|
||||||
|
bool maywr2 = false; /* sock2 can be written to, according to select() */
|
||||||
|
|
||||||
|
sock1 = xfd1;
|
||||||
|
sock2 = xfd2;
|
||||||
|
|
||||||
|
#if WITH_FILAN
|
||||||
|
if (xioparams->debug) {
|
||||||
|
int fdi, fdo;
|
||||||
|
int msglevel, exitlevel;
|
||||||
|
|
||||||
|
msglevel = diag_get_int('D'); /* save current message level */
|
||||||
|
diag_set_int('D', E_ERROR); /* only print errors and fatals in filan */
|
||||||
|
exitlevel = diag_get_int('e'); /* save current exit level */
|
||||||
|
diag_set_int('e', E_FATAL); /* only exit on fatals */
|
||||||
|
|
||||||
|
fdi = XIO_GETRDFD(sock1);
|
||||||
|
fdo = XIO_GETWRFD(sock1);
|
||||||
|
filan_fd(fdi, stderr);
|
||||||
|
if (fdo != fdi) {
|
||||||
|
filan_fd(fdo, stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
fdi = XIO_GETRDFD(sock2);
|
||||||
|
fdo = XIO_GETWRFD(sock2);
|
||||||
|
filan_fd(fdi, stderr);
|
||||||
|
if (fdo != fdi) {
|
||||||
|
filan_fd(fdo, stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
diag_set_int('e', exitlevel); /* restore old exit level */
|
||||||
|
diag_set_int('D', msglevel); /* restore old message level */
|
||||||
|
}
|
||||||
|
#endif /* WITH_FILAN */
|
||||||
|
|
||||||
|
/* when converting nl to crnl, size might double */
|
||||||
|
buff = Malloc(2*xioparams->bufsiz+1);
|
||||||
|
if (buff == NULL) return -1;
|
||||||
|
|
||||||
|
if (xioparams->logopt == 'm' && xioinqopt('l', NULL, 0) == 'm') {
|
||||||
|
Info("switching to syslog");
|
||||||
|
diag_set('y', xioopts.syslogfac);
|
||||||
|
xiosetopt('l', "\0");
|
||||||
|
}
|
||||||
|
total_timeout = xioparams->total_timeout;
|
||||||
|
|
||||||
|
Notice4("starting data transfer loop with FDs [%d,%d] and [%d,%d]",
|
||||||
|
XIO_GETRDFD(sock1), XIO_GETWRFD(sock1),
|
||||||
|
XIO_GETRDFD(sock2), XIO_GETWRFD(sock2));
|
||||||
|
while (XIO_RDSTREAM(sock1)->eof <= 1 ||
|
||||||
|
XIO_RDSTREAM(sock2)->eof <= 1) {
|
||||||
|
struct timeval timeout, *to = NULL;
|
||||||
|
|
||||||
|
Debug4("data loop: sock1->eof=%d, sock2->eof=%d, 1->closing=%d, 2->closing=%d",
|
||||||
|
XIO_RDSTREAM(sock1)->eof, XIO_RDSTREAM(sock2)->eof,
|
||||||
|
sock1->stream.closing, sock2->stream.closing);
|
||||||
|
Debug3("wasaction=%d, total_to={"F_tv_sec"."F_tv_usec"}",
|
||||||
|
wasaction, total_timeout.tv_sec, total_timeout.tv_usec);
|
||||||
|
|
||||||
|
/* for ignoreeof */
|
||||||
|
if (polling) {
|
||||||
|
if (!wasaction) {
|
||||||
|
/* yes we could do it with select but I like readable trace output */
|
||||||
|
if (xioparams->pollintv.tv_sec) Sleep(xioparams->pollintv.tv_sec);
|
||||||
|
if (xioparams->pollintv.tv_usec) Usleep(xioparams->pollintv.tv_usec);
|
||||||
|
|
||||||
|
if (xioparams->total_timeout.tv_sec != 0 ||
|
||||||
|
xioparams->total_timeout.tv_usec != 0) {
|
||||||
|
if (total_timeout.tv_usec < xioparams->pollintv.tv_usec) {
|
||||||
|
total_timeout.tv_usec += 1000000;
|
||||||
|
total_timeout.tv_sec -= 1;
|
||||||
|
}
|
||||||
|
total_timeout.tv_sec -= xioparams->pollintv.tv_sec;
|
||||||
|
total_timeout.tv_usec -= xioparams->pollintv.tv_usec;
|
||||||
|
if (total_timeout.tv_sec < 0 ||
|
||||||
|
total_timeout.tv_sec == 0 && total_timeout.tv_usec < 0) {
|
||||||
|
Notice("inactivity timeout triggered");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
wasaction = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (polling) {
|
||||||
|
/* there is a ignoreeof poll timeout, use it */
|
||||||
|
timeout = xioparams->pollintv;
|
||||||
|
to = &timeout;
|
||||||
|
} else if (xioparams->total_timeout.tv_sec != 0 ||
|
||||||
|
xioparams->total_timeout.tv_usec != 0) {
|
||||||
|
/* there might occur a total inactivity timeout */
|
||||||
|
timeout = xioparams->total_timeout;
|
||||||
|
to = &timeout;
|
||||||
|
} else {
|
||||||
|
to = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
if (sock1->stream.closing>=1 || sock2->stream.closing>=1) {
|
||||||
|
/* first eof already occurred, start end timer */
|
||||||
|
timeout = xioparams->closwait;
|
||||||
|
to = &timeout;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
do {
|
||||||
|
int _errno;
|
||||||
|
FD_ZERO(&in); FD_ZERO(&out); FD_ZERO(&expt);
|
||||||
|
|
||||||
|
childleftdata(sock1);
|
||||||
|
childleftdata(sock2);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (closing>=1) {
|
||||||
|
/* first eof already occurred, start end timer */
|
||||||
|
timeout = xioparams->closwait;
|
||||||
|
to = &timeout;
|
||||||
|
closing = 2;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (sock1->stream.closing>=1 || sock2->stream.closing>=1) {
|
||||||
|
/* first eof already occurred, start end timer */
|
||||||
|
timeout = xioparams->closwait;
|
||||||
|
to = &timeout;
|
||||||
|
if (sock1->stream.closing==1) {
|
||||||
|
sock1->stream.closing = 2;
|
||||||
|
}
|
||||||
|
if (sock2->stream.closing==1) {
|
||||||
|
sock2->stream.closing = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (XIO_READABLE(sock1) &&
|
||||||
|
!(XIO_RDSTREAM(sock1)->eof > 1 && !XIO_RDSTREAM(sock1)->ignoreeof)
|
||||||
|
/*0 && !xioparams->righttoleft*/) {
|
||||||
|
Debug3("*** sock1: %p [%d,%d]", sock1, XIO_GETRDFD(sock1), XIO_GETWRFD(sock1));
|
||||||
|
if (!mayrd1) {
|
||||||
|
FD_SET(XIO_GETRDFD(sock1), &in);
|
||||||
|
}
|
||||||
|
if (!maywr2) {
|
||||||
|
FD_SET(XIO_GETWRFD(sock2), &out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (XIO_READABLE(sock2) &&
|
||||||
|
!(XIO_RDSTREAM(sock2)->eof > 1 && !XIO_RDSTREAM(sock2)->ignoreeof)
|
||||||
|
/*0 && !xioparams->lefttoright*/) {
|
||||||
|
Debug3("*** sock2: %p [%d,%d]", sock2, XIO_GETRDFD(sock2), XIO_GETWRFD(sock2));
|
||||||
|
if (!mayrd2) {
|
||||||
|
FD_SET(XIO_GETRDFD(sock2), &in);
|
||||||
|
}
|
||||||
|
if (!maywr1) {
|
||||||
|
FD_SET(XIO_GETWRFD(sock1), &out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
retval = Select(FD_SETSIZE, &in, &out, &expt, to);
|
||||||
|
_errno = errno;
|
||||||
|
if (retval < 0 && errno == EINTR) {
|
||||||
|
Info1("select(): %s", strerror(errno));
|
||||||
|
}
|
||||||
|
errno = _errno;
|
||||||
|
} while (retval < 0 && errno == EINTR);
|
||||||
|
|
||||||
|
/* attention:
|
||||||
|
when an exec'd process sends data and terminates, it is unpredictable
|
||||||
|
whether the data or the sigchild arrives first.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (retval < 0) {
|
||||||
|
#if HAVE_FDS_BITS
|
||||||
|
Error7("select(%d, &0x%lx, &0x%lx, &0x%lx, %s%lu): %s",
|
||||||
|
FD_SETSIZE, in.fds_bits[0], out.fds_bits[0],
|
||||||
|
expt.fds_bits[0], to?"&":"NULL/", to?to->tv_sec:0,
|
||||||
|
strerror(errno));
|
||||||
|
#else
|
||||||
|
Error7("select(%d, &0x%lx, &0x%lx, &0x%lx, %s%lu): %s",
|
||||||
|
FD_SETSIZE, in.__fds_bits[0], out.__fds_bits[0],
|
||||||
|
expt.__fds_bits[0], to?"&":"NULL/", to?to->tv_sec:0,
|
||||||
|
strerror(errno));
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
} else if (retval == 0) {
|
||||||
|
Info2("select timed out (no data within %ld.%06ld seconds)",
|
||||||
|
(sock1->stream.closing>=1||sock2->stream.closing>=1)?
|
||||||
|
xioparams->closwait.tv_sec:xioparams->total_timeout.tv_sec,
|
||||||
|
(sock1->stream.closing>=1||sock2->stream.closing>=1)?
|
||||||
|
xioparams->closwait.tv_usec:xioparams->total_timeout.tv_usec);
|
||||||
|
if (polling && !wasaction) {
|
||||||
|
/* there was a ignoreeof poll timeout, use it */
|
||||||
|
;
|
||||||
|
} else if (xioparams->total_timeout.tv_sec != 0 ||
|
||||||
|
xioparams->total_timeout.tv_usec != 0) {
|
||||||
|
/* there was a total inactivity timeout */
|
||||||
|
Notice("inactivity timeout triggered");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sock1->stream.closing || sock2->stream.closing) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* one possibility to come here is ignoreeof on some fd, but no EOF
|
||||||
|
and no data on any descriptor - this is no indication for end! */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*0 Debug1("XIO_READABLE(sock1) = %d", XIO_READABLE(sock1));*/
|
||||||
|
/*0 Debug1("XIO_GETRDFD(sock1) = %d", XIO_GETRDFD(sock1));*/
|
||||||
|
if (XIO_READABLE(sock1) && XIO_GETRDFD(sock1) >= 0 &&
|
||||||
|
FD_ISSET(XIO_GETRDFD(sock1), &in)) {
|
||||||
|
mayrd1 = true;
|
||||||
|
}
|
||||||
|
/*0 Debug1("XIO_READABLE(sock2) = %d", XIO_READABLE(sock2));*/
|
||||||
|
/*0 Debug1("XIO_GETRDFD(sock2) = %d", XIO_GETRDFD(sock2));*/
|
||||||
|
/*0 Debug1("FD_ISSET(XIO_GETRDFD(sock2), &in) = %d", FD_ISSET(XIO_GETRDFD(sock2), &in));*/
|
||||||
|
if (XIO_READABLE(sock2) && XIO_GETRDFD(sock2) >= 0 &&
|
||||||
|
FD_ISSET(XIO_GETRDFD(sock2), &in)) {
|
||||||
|
mayrd2 = true;
|
||||||
|
}
|
||||||
|
/*0 Debug2("mayrd2 = %d, maywr1 = %d", mayrd2, maywr1);*/
|
||||||
|
if (XIO_GETWRFD(sock1) >= 0 && FD_ISSET(XIO_GETWRFD(sock1), &out)) {
|
||||||
|
maywr1 = true;
|
||||||
|
}
|
||||||
|
if (XIO_GETWRFD(sock2) >= 0 && FD_ISSET(XIO_GETWRFD(sock2), &out)) {
|
||||||
|
maywr2 = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mayrd1 && maywr2) {
|
||||||
|
mayrd1 = false;
|
||||||
|
if ((bytes1 = xiotransfer(sock1, sock2, &buff, xioparams->bufsiz, false))
|
||||||
|
< 0) {
|
||||||
|
if (errno != EAGAIN) {
|
||||||
|
/*sock2->closing = MAX(socks2->closing, 1);*/
|
||||||
|
Notice("socket 1 to socket 2 is in error");
|
||||||
|
if (/*0 xioparams->lefttoright*/ !XIO_READABLE(sock2)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (bytes1 > 0) {
|
||||||
|
maywr2 = false;
|
||||||
|
total_timeout = xioparams->total_timeout;
|
||||||
|
wasaction = 1;
|
||||||
|
/* is more data available that has already passed select()? */
|
||||||
|
mayrd1 = (xiopending(sock1) > 0);
|
||||||
|
if (XIO_RDSTREAM(sock1)->readbytes != 0 &&
|
||||||
|
XIO_RDSTREAM(sock1)->actbytes == 0) {
|
||||||
|
/* avoid idle when all readbytes already there */
|
||||||
|
mayrd1 = true;
|
||||||
|
}
|
||||||
|
} else { /* bytes1 == 0 */
|
||||||
|
if (XIO_RDSTREAM(sock1)->ignoreeof && !sock1->stream.closing) {
|
||||||
|
;
|
||||||
|
} else {
|
||||||
|
XIO_RDSTREAM(sock1)->eof = 2;
|
||||||
|
}
|
||||||
|
/* (bytes1 == 0) handled later */
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bytes1 = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mayrd2 && maywr1) {
|
||||||
|
mayrd2 = false;
|
||||||
|
if ((bytes2 = xiotransfer(sock2, sock1, &buff, xioparams->bufsiz, true))
|
||||||
|
< 0) {
|
||||||
|
if (errno != EAGAIN) {
|
||||||
|
/*sock1->closing = MAX(sock1->closing, 1);*/
|
||||||
|
Notice("socket 2 to socket 1 is in error");
|
||||||
|
if (/*0 xioparams->righttoleft*/ !XIO_READABLE(sock1)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (bytes2 > 0) {
|
||||||
|
maywr1 = false;
|
||||||
|
total_timeout = xioparams->total_timeout;
|
||||||
|
wasaction = 1;
|
||||||
|
/* is more data available that has already passed select()? */
|
||||||
|
mayrd2 = (xiopending(sock2) > 0);
|
||||||
|
if (XIO_RDSTREAM(sock2)->readbytes != 0 &&
|
||||||
|
XIO_RDSTREAM(sock2)->actbytes == 0) {
|
||||||
|
/* avoid idle when all readbytes already there */
|
||||||
|
mayrd2 = true;
|
||||||
|
}
|
||||||
|
} else { /* bytes == 0 */
|
||||||
|
if (XIO_RDSTREAM(sock2)->ignoreeof && !sock2->stream.closing) {
|
||||||
|
;
|
||||||
|
} else {
|
||||||
|
XIO_RDSTREAM(sock2)->eof = 2;
|
||||||
|
}
|
||||||
|
/* (bytes2 == 0) handled later */
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bytes2 = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NOW handle EOFs */
|
||||||
|
|
||||||
|
if (bytes1 == 0 || XIO_RDSTREAM(sock1)->eof >= 2) {
|
||||||
|
if (XIO_RDSTREAM(sock1)->ignoreeof && !sock1->stream.closing) {
|
||||||
|
Debug1("socket 1 (fd %d) is at EOF, ignoring",
|
||||||
|
XIO_RDSTREAM(sock1)->fd1); /*! */
|
||||||
|
polling = 1;
|
||||||
|
} else {
|
||||||
|
Notice1("socket 1 (fd %d) is at EOF", XIO_GETRDFD(sock1));
|
||||||
|
xioshutdown(sock2, SHUT_WR);
|
||||||
|
sock2->stream.closing = MAX(sock2->stream.closing, 1);
|
||||||
|
if (/*0 xioparams->lefttoright*/ !XIO_READABLE(sock2)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bytes2 == 0 || XIO_RDSTREAM(sock2)->eof >= 2) {
|
||||||
|
if (XIO_RDSTREAM(sock2)->ignoreeof && !sock2->stream.closing) {
|
||||||
|
Debug1("socket 2 (fd %d) is at EOF, ignoring",
|
||||||
|
XIO_RDSTREAM(sock2)->fd1);
|
||||||
|
polling = 1;
|
||||||
|
} else {
|
||||||
|
Notice1("socket 2 (fd %d) is at EOF", XIO_GETRDFD(sock2));
|
||||||
|
xioshutdown(sock1, SHUT_WR);
|
||||||
|
sock1->stream.closing = MAX(sock1->stream.closing, 1);
|
||||||
|
if (/*0 xioparams->righttoleft*/ !XIO_READABLE(sock1)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* close everything that's still open */
|
||||||
|
xioclose(sock1);
|
||||||
|
xioclose(sock2);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* this is the callback when the child of an address died */
|
||||||
|
int socat_sigchild(struct single *file) {
|
||||||
|
Debug3("socat_sigchild().1: file->ignoreeof=%d, file->closing=%d, file->eof=%d",
|
||||||
|
file->ignoreeof, file->closing, file->eof);
|
||||||
|
if (file->ignoreeof && !file->closing) {
|
||||||
|
;
|
||||||
|
} else {
|
||||||
|
file->eof = MAX(file->eof, 1);
|
||||||
|
file->closing = 3;
|
||||||
|
}
|
||||||
|
Debug3("socat_sigchild().9: file->ignoreeof=%d, file->closing=%d, file->eof=%d",
|
||||||
|
file->ignoreeof, file->closing, file->eof);
|
||||||
|
return 0;
|
||||||
|
}
|
60
xiohelp.c
60
xiohelp.c
|
@ -41,7 +41,7 @@ static const char *addressgroupnames[] = {
|
||||||
"TERMIOS", "RANGE", "PTY", "PARENT",
|
"TERMIOS", "RANGE", "PTY", "PARENT",
|
||||||
"UNIX", "IP4", "IP6", "INTERFACE",
|
"UNIX", "IP4", "IP6", "INTERFACE",
|
||||||
"UDP", "TCP", "SOCKS4", "OPENSSL",
|
"UDP", "TCP", "SOCKS4", "OPENSSL",
|
||||||
"PROCESS", "APPL", "HTTP", "undef"
|
"PROCESS", "APPL", "HTTP", "SOCKS5"
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ static int xiohelp_option(FILE *of, const struct optname *on, const char *name)
|
||||||
int xioopenhelp(FILE *of,
|
int xioopenhelp(FILE *of,
|
||||||
int level /* 0..only addresses, 1..and options */
|
int level /* 0..only addresses, 1..and options */
|
||||||
) {
|
) {
|
||||||
const struct addrname *an;
|
const struct xioaddrname *an;
|
||||||
const struct optname *on;
|
const struct optname *on;
|
||||||
int i, j;
|
int i, j;
|
||||||
unsigned int groups;
|
unsigned int groups;
|
||||||
|
@ -101,32 +101,68 @@ int xioopenhelp(FILE *of,
|
||||||
fputs(" echo is an alias for pipe\n", of);
|
fputs(" echo is an alias for pipe\n", of);
|
||||||
fputs(" fifo is an alias for pipe\n", of);
|
fputs(" fifo is an alias for pipe\n", of);
|
||||||
}
|
}
|
||||||
fputs(" <single-address>!!<single-address>\n", of);
|
fputs(" <single-address>%<single-address>\n", of);
|
||||||
fputs(" <single-address>\n", of);
|
fputs(" <single-address>\n", of);
|
||||||
fputs(" single-address:\n", of);
|
fputs(" single-address:\n", of);
|
||||||
fputs(" <address-head>[,<opts>]\n", of);
|
fputs(" <address-head>[,<opts>]\n", of);
|
||||||
fputs(" address-head:\n", of);
|
fputs(" address-head:\n", of);
|
||||||
an = &addressnames[0];
|
an = &address_names[0];
|
||||||
i = 0;
|
i = 0;
|
||||||
while (addressnames[i].name) {
|
while (address_names[i].name) {
|
||||||
if (!strcmp(an->name, an->desc->defname)) {
|
if (!strcmp(an->name, (an->desc)[0]->common_desc.defname)) {
|
||||||
/* it is a canonical address name */
|
/* it is a canonical address name */
|
||||||
fprintf(of, " %s", an->name);
|
const union xioaddr_desc **ad;
|
||||||
if (an->desc->syntax) {
|
ad = an->desc;
|
||||||
fputs(an->desc->syntax, of); }
|
while (*ad != NULL) {
|
||||||
fputs("\tgroups=", of);
|
const char *syntax;
|
||||||
groups = an->desc->groups; occurred = false;
|
int pos = 0;
|
||||||
|
fprintf(of, " %s", an->name); pos += strlen(an->name);
|
||||||
|
if ((*ad)->tag == XIOADDR_ENDPOINT) {
|
||||||
|
syntax = (*ad)->endpoint_desc.syntax;
|
||||||
|
} else if ((*ad)->tag == XIOADDR_INTER) {
|
||||||
|
syntax = (*ad)->inter_desc.syntax;
|
||||||
|
} else {
|
||||||
|
syntax = NULL;
|
||||||
|
}
|
||||||
|
if (syntax) {
|
||||||
|
fputs(syntax, of); pos += strlen(syntax); }
|
||||||
|
while (pos < 36) { putc(' ', of); ++pos; }
|
||||||
|
if ((*ad)->common_desc.leftdirs & XIOBIT_RDONLY) {
|
||||||
|
putc('r', of); } else { putc(' ', of); }
|
||||||
|
if ((*ad)->common_desc.leftdirs & XIOBIT_WRONLY) {
|
||||||
|
putc('w', of); } else { putc(' ', of); }
|
||||||
|
if ((*ad)->common_desc.leftdirs & XIOBIT_RDWR) {
|
||||||
|
putc('b', of); } else { putc(' ', of); }
|
||||||
|
putc(' ', of);
|
||||||
|
if ((*ad)->tag == 1) {
|
||||||
|
while (pos < 36) { putc(' ', of); ++pos; }
|
||||||
|
if ((*ad)->inter_desc.rightdirs & XIOBIT_RDONLY) {
|
||||||
|
putc('r', of); } else { putc(' ', of); }
|
||||||
|
if ((*ad)->inter_desc.rightdirs & XIOBIT_WRONLY) {
|
||||||
|
putc('w', of); } else { putc(' ', of); }
|
||||||
|
if ((*ad)->inter_desc.rightdirs & XIOBIT_RDWR) {
|
||||||
|
putc('b', of); } else { putc(' ', of); }
|
||||||
|
} else {
|
||||||
|
fputs(" ", of);
|
||||||
|
}
|
||||||
|
|
||||||
|
pos += 7;
|
||||||
|
fputs(" groups=", of);
|
||||||
|
groups = (*ad)->common_desc.groups; occurred = false;
|
||||||
for (j = 0; j < 32; ++j) {
|
for (j = 0; j < 32; ++j) {
|
||||||
if (groups & 1) {
|
if (groups & 1) {
|
||||||
if (occurred) { fputc(',', of); }
|
if (occurred) { fputc(',', of); }
|
||||||
fprintf(of, "%s", addressgroupnames[j]);
|
fprintf(of, "%s", addressgroupnames[j]);
|
||||||
|
pos += strlen(addressgroupnames[j]);
|
||||||
occurred = true;
|
occurred = true;
|
||||||
}
|
}
|
||||||
groups >>= 1;
|
groups >>= 1;
|
||||||
}
|
}
|
||||||
fputc('\n', of);
|
fputc('\n', of);
|
||||||
|
++ad;
|
||||||
|
}
|
||||||
} else if (level == 2) {
|
} else if (level == 2) {
|
||||||
fprintf(of, " %s is an alias name for %s\n", an->name, an->desc->defname);
|
fprintf(of, " %s is an alias name for %s\n", an->name, (an->desc)[0]->common_desc.defname);
|
||||||
}
|
}
|
||||||
++an; ++i;
|
++an; ++i;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,30 @@
|
||||||
/* $Id: xioinitialize.c,v 1.17 2006/12/28 14:21:41 gerhard Exp $ */
|
/* $Id: xioinitialize.c,v 1.17 2006/12/28 14:21:41 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2001-2006 */
|
/* Copyright Gerhard Rieger 2001-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
/* this file contains the source for the initialize function */
|
/* this file contains the source for the initialize function */
|
||||||
|
|
||||||
#include "xiosysincludes.h"
|
#include "xiosysincludes.h"
|
||||||
|
|
||||||
|
#include "xiostatic.h"
|
||||||
#include "xioopen.h"
|
#include "xioopen.h"
|
||||||
#include "xiolockfile.h"
|
#include "xiolockfile.h"
|
||||||
|
#include "xiosigchld.h"
|
||||||
|
|
||||||
#include "xio-openssl.h" /* xio_reset_fips_mode() */
|
#include "xio-openssl.h" /* xio_reset_fips_mode() */
|
||||||
|
|
||||||
static int xioinitialized;
|
static int xioinitialized;
|
||||||
xiofile_t *sock[XIO_MAXSOCK];
|
xiofile_t *sock[XIO_MAXSOCK];
|
||||||
int (*xiohook_newchild)(void); /* xio calls this function from a new child
|
int (*xiohook_newchild)(void); /* xio calls this function in every new child
|
||||||
process */
|
process */
|
||||||
|
|
||||||
|
|
||||||
|
/* call this function before calling any other xio function.
|
||||||
|
With xioflags, you have to set the features that xio can make use of.
|
||||||
|
Use XIO_MAYALL for unrestricted use. */
|
||||||
/* returns 0 on success or != if an error occurred */
|
/* returns 0 on success or != if an error occurred */
|
||||||
int xioinitialize(void) {
|
int xioinitialize(int xioflags) {
|
||||||
|
int xio_flags;
|
||||||
if (xioinitialized) return 0;
|
if (xioinitialized) return 0;
|
||||||
|
|
||||||
/* configure and .h's cannot guarantee this */
|
/* configure and .h's cannot guarantee this */
|
||||||
|
@ -67,7 +73,7 @@ int xioinitialize(void) {
|
||||||
assert(tdata.termarg.c_ospeed == tdata.speeds[OSPEED_OFFSET]);
|
assert(tdata.termarg.c_ospeed == tdata.speeds[OSPEED_OFFSET]);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif /* WITH_TERMIOS */
|
||||||
|
|
||||||
/* these dependencies required in applyopts() for OFUNC_FCNTL */
|
/* these dependencies required in applyopts() for OFUNC_FCNTL */
|
||||||
assert(F_GETFD == F_SETFD-1);
|
assert(F_GETFD == F_SETFD-1);
|
||||||
|
@ -103,15 +109,41 @@ int xioinitialize(void) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
xio_flags = xioflags;
|
||||||
|
|
||||||
|
if ((xio_flags|XIO_MAYFORK) || (xio_flags|XIO_MAYCHILD) ||
|
||||||
|
(xio_flags|XIO_MAYCHAIN)) {
|
||||||
|
|
||||||
|
#if HAVE_SIGACTION
|
||||||
|
struct sigaction act;
|
||||||
|
memset(&act, 0, sizeof(struct sigaction));
|
||||||
|
act.sa_flags = SA_NOCLDSTOP|SA_RESTART|SA_SIGINFO
|
||||||
|
#ifdef SA_NOMASK
|
||||||
|
|SA_NOMASK
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
act.sa_sigaction = childdied;
|
||||||
|
if (Sigaction(SIGCHLD, &act, NULL) < 0) {
|
||||||
|
/*! Linux man does not explicitely say that errno is defined */
|
||||||
|
Warn2("sigaction(SIGCHLD, %p, NULL): %s", childdied, strerror(errno));
|
||||||
|
}
|
||||||
|
#else /* !HAVE_SIGACTION */
|
||||||
|
act.sa_handler = childdied;
|
||||||
|
if (Signal(SIGCHLD, childdied) == SIG_ERR) {
|
||||||
|
Warn2("signal(SIGCHLD, %p): %s", childdied, strerror(errno));
|
||||||
|
}
|
||||||
|
#endif /* !HAVE_SIGACTION */
|
||||||
|
}
|
||||||
|
|
||||||
xioinitialized = 1;
|
xioinitialized = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* well, this function is not for initialization, but I could not find a better
|
/* well, this function is not for initialization, but I could not find a better
|
||||||
place for it
|
source file for it
|
||||||
it is called in the child process after fork
|
it is called in the child process after fork
|
||||||
it drops the locks of the xiofile's so only the parent owns them
|
it drops the lock references of the xiofile's so only the parent owns them
|
||||||
*/
|
*/
|
||||||
void xiodroplocks(void) {
|
void xiodroplocks(void) {
|
||||||
int i;
|
int i;
|
||||||
|
@ -124,6 +156,7 @@ void xiodroplocks(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* consider an invokation like this:
|
/* consider an invokation like this:
|
||||||
socat -u exec:'some program that accepts data' tcp-l:...,fork
|
socat -u exec:'some program that accepts data' tcp-l:...,fork
|
||||||
we do not want the program to be killed by the first tcp-l sub process, it's
|
we do not want the program to be killed by the first tcp-l sub process, it's
|
||||||
|
@ -146,16 +179,17 @@ static int xio_nokill(xiofile_t *sock) {
|
||||||
case XIO_TAG_WRONLY:
|
case XIO_TAG_WRONLY:
|
||||||
case XIO_TAG_RDWR:
|
case XIO_TAG_RDWR:
|
||||||
/* here is the core of this function */
|
/* here is the core of this function */
|
||||||
switch (sock->stream.howtoend) {
|
switch (sock->stream.howtoclose) {
|
||||||
case END_SHUTDOWN_KILL: sock->stream.howtoend = END_CLOSE; break;
|
case END_SHUTDOWN_KILL: sock->stream.howtoclose = END_CLOSE; break;
|
||||||
case END_CLOSE_KILL: sock->stream.howtoend = END_CLOSE; break;
|
case END_CLOSE_KILL: sock->stream.howtoclose = END_CLOSE; break;
|
||||||
case END_SHUTDOWN: sock->stream.howtoend = END_CLOSE; break;
|
case END_SHUTDOWN: sock->stream.howtoclose = END_CLOSE; break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
#endif /* 0 */
|
||||||
|
|
||||||
/* call this function immediately after fork() in child process */
|
/* call this function immediately after fork() in child process */
|
||||||
/* it performs some neccessary actions
|
/* it performs some neccessary actions
|
||||||
|
@ -175,6 +209,7 @@ int xio_forked_inchild(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* change XIO_SHUTDOWN_KILL to XIO_SHUTDOWN */
|
/* change XIO_SHUTDOWN_KILL to XIO_SHUTDOWN */
|
||||||
if (sock1 != NULL) {
|
if (sock1 != NULL) {
|
||||||
int result2;
|
int result2;
|
||||||
|
@ -182,6 +217,7 @@ int xio_forked_inchild(void) {
|
||||||
if (result2 < 0) Exit(1);
|
if (result2 < 0) Exit(1);
|
||||||
result |= result2;
|
result |= result2;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* $Id: xiolayer.c,v 1.7 2005/08/18 19:56:05 gerhard Exp $ */
|
/* $Id: xiolayer.c,v 1.7 2005/08/18 19:56:05 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2001-2005 */
|
/* Copyright Gerhard Rieger 2001-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
/* this file contains the source for common options */
|
/* this file contains the source for common options */
|
||||||
|
@ -18,8 +18,8 @@ const struct optdesc opt_lockfile = { "lockfile", NULL, OPT_LOCKFILE, GROUP_A
|
||||||
const struct optdesc opt_waitlock = { "waitlock", NULL, OPT_WAITLOCK, GROUP_APPL, PH_INIT, TYPE_FILENAME, OFUNC_EXT, 0, 0 };
|
const struct optdesc opt_waitlock = { "waitlock", NULL, OPT_WAITLOCK, GROUP_APPL, PH_INIT, TYPE_FILENAME, OFUNC_EXT, 0, 0 };
|
||||||
/****** APPL addresses ******/
|
/****** APPL addresses ******/
|
||||||
#if WITH_RETRY
|
#if WITH_RETRY
|
||||||
const struct optdesc opt_forever = { "forever", NULL, OPT_FOREVER, GROUP_RETRY, PH_INIT, TYPE_BOOL, OFUNC_EXT, (int)(&((struct single *)0)->forever), sizeof(((struct single *)0)->forever) };
|
const struct optdesc opt_forever = { "forever", NULL, OPT_FOREVER, GROUP_RETRY, PH_INIT, TYPE_BOOL, OFUNC_OFFSET, (int)(&((struct single *)0)->forever), sizeof(((struct single *)0)->forever) };
|
||||||
const struct optdesc opt_intervall = { "intervall", NULL, OPT_INTERVALL, GROUP_RETRY, PH_INIT, TYPE_TIMESPEC, OFUNC_EXT, (int)(&((struct single *)0)->intervall), sizeof(((struct single *)0)->intervall) };
|
const struct optdesc opt_intervall = { "intervall", NULL, OPT_INTERVALL, GROUP_RETRY, PH_INIT, TYPE_TIMESPEC, OFUNC_OFFSET, (int)(&((struct single *)0)->intervall), sizeof(((struct single *)0)->intervall) };
|
||||||
const struct optdesc opt_retry = { "retry", NULL, OPT_RETRY, GROUP_RETRY, PH_INIT, TYPE_UINT, OFUNC_EXT, (int)(&((struct single *)0)->retry), sizeof(((struct single *)0)->retry) };
|
const struct optdesc opt_retry = { "retry", NULL, OPT_RETRY, GROUP_RETRY, PH_INIT, TYPE_UINT, OFUNC_OFFSET, (int)(&((struct single *)0)->retry), sizeof(((struct single *)0)->retry) };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "xio-tcp.h"
|
#include "xio-tcp.h"
|
||||||
#include "xio-udp.h"
|
#include "xio-udp.h"
|
||||||
#include "xio-socks.h"
|
#include "xio-socks.h"
|
||||||
|
#include "xio-socks5.h"
|
||||||
#include "xio-proxy.h"
|
#include "xio-proxy.h"
|
||||||
#endif /* WITH_SOCKET */
|
#endif /* WITH_SOCKET */
|
||||||
#include "xio-progcall.h"
|
#include "xio-progcall.h"
|
||||||
|
@ -41,5 +42,7 @@
|
||||||
#include "xio-tcpwrap.h"
|
#include "xio-tcpwrap.h"
|
||||||
#include "xio-ext2.h"
|
#include "xio-ext2.h"
|
||||||
#include "xio-tun.h"
|
#include "xio-tun.h"
|
||||||
|
#include "xio-nop.h"
|
||||||
|
#include "xio-test.h"
|
||||||
|
|
||||||
#endif /* !defined(__xiomodes_h_included) */
|
#endif /* !defined(__xiomodes_h_included) */
|
||||||
|
|
19
xioopen.h
19
xioopen.h
|
@ -1,5 +1,5 @@
|
||||||
/* $Id: xioopen.h,v 1.22 2006/05/12 20:14:05 gerhard Exp $ */
|
/* $Id: xioopen.h,v 1.22.2.1 2006/07/24 19:26:29 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2001-2006 */
|
/* Copyright Gerhard Rieger 2001-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
#ifndef __xioopen_h_included
|
#ifndef __xioopen_h_included
|
||||||
|
@ -33,16 +33,25 @@ extern const struct optdesc opt_tabdly;
|
||||||
extern const struct optdesc opt_csize;
|
extern const struct optdesc opt_csize;
|
||||||
|
|
||||||
|
|
||||||
struct addrname {
|
struct xioaddrname {
|
||||||
const char *name;
|
const char *name;
|
||||||
const struct addrdesc *desc;
|
const union xioaddr_desc **desc;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
struct xioaddr_endpoint_name {
|
||||||
|
const char *name;
|
||||||
|
const struct xioaddr_endpoint_desc **desc;
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
extern const char *ddirection[];
|
extern const char *ddirection[];
|
||||||
extern const char *filetypenames[];
|
extern const char *filetypenames[];
|
||||||
extern const struct addrname addressnames[];
|
extern const struct xioaddrname address_names[];
|
||||||
extern const struct optname optionnames[];
|
extern const struct optname optionnames[];
|
||||||
|
|
||||||
|
extern xiofile_t *socat_open(const char *addrs0, int dirs, int flags);
|
||||||
|
extern xiofile_t *xioparse_dual(const char **addr);
|
||||||
|
extern int xioopen_inter_dual(xiofile_t *xfd, int xioflags);
|
||||||
|
extern int xioopen_endpoint_dual(xiofile_t *xfd, int xioflags);
|
||||||
extern int xioopen_makedual(xiofile_t *file);
|
extern int xioopen_makedual(xiofile_t *file);
|
||||||
|
|
||||||
#define retropt_2bytes(o,c,r) retropt_ushort(o,c,r)
|
#define retropt_2bytes(o,c,r) retropt_ushort(o,c,r)
|
||||||
|
|
96
xioopts.c
96
xioopts.c
|
@ -88,6 +88,12 @@ bool xioopts_ignoregroups;
|
||||||
# define IF_SOCKS4(a,b)
|
# define IF_SOCKS4(a,b)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if WITH_SOCKS5
|
||||||
|
# define IF_SOCKS5(a,b) {a,b},
|
||||||
|
#else
|
||||||
|
# define IF_SOCKS5(a,b)
|
||||||
|
#endif
|
||||||
|
|
||||||
#if WITH_PROXY
|
#if WITH_PROXY
|
||||||
# define IF_PROXY(a,b) {a,b},
|
# define IF_PROXY(a,b) {a,b},
|
||||||
#else
|
#else
|
||||||
|
@ -1190,6 +1196,7 @@ const struct optname optionnames[] = {
|
||||||
#endif
|
#endif
|
||||||
IF_ANY ("setuid", &opt_setuid)
|
IF_ANY ("setuid", &opt_setuid)
|
||||||
IF_ANY ("setuid-early", &opt_setuid_early)
|
IF_ANY ("setuid-early", &opt_setuid_early)
|
||||||
|
IF_ANY ("shut-none", &opt_shut_none)
|
||||||
#if WITH_EXEC || WITH_SYSTEM
|
#if WITH_EXEC || WITH_SYSTEM
|
||||||
IF_ANY ("sid", &opt_setsid)
|
IF_ANY ("sid", &opt_setsid)
|
||||||
#endif
|
#endif
|
||||||
|
@ -1302,6 +1309,8 @@ const struct optname optionnames[] = {
|
||||||
#ifdef SO_USELOOPBACK /* AIX433, Solaris */
|
#ifdef SO_USELOOPBACK /* AIX433, Solaris */
|
||||||
IF_SOCKET ("so-useloopback", &opt_so_useloopback)
|
IF_SOCKET ("so-useloopback", &opt_so_useloopback)
|
||||||
#endif /* SO_USELOOPBACK */
|
#endif /* SO_USELOOPBACK */
|
||||||
|
IF_SOCKS5 ("socks5-password", &opt_socks5_password)
|
||||||
|
IF_SOCKS5 ("socks5-username", &opt_socks5_username)
|
||||||
IF_SOCKS4 ("socksport", &opt_socksport)
|
IF_SOCKS4 ("socksport", &opt_socksport)
|
||||||
IF_SOCKS4 ("socksuser", &opt_socksuser)
|
IF_SOCKS4 ("socksuser", &opt_socksuser)
|
||||||
IF_IPAPP ("sourceport", &opt_sourceport)
|
IF_IPAPP ("sourceport", &opt_sourceport)
|
||||||
|
@ -1560,9 +1569,9 @@ const struct optname optionnames[] = {
|
||||||
to the array opts. Uses the option table 'optionnames'.
|
to the array opts. Uses the option table 'optionnames'.
|
||||||
returns 0 on success, -1 on error, 1 on unknown/wrong option
|
returns 0 on success, -1 on error, 1 on unknown/wrong option
|
||||||
*/
|
*/
|
||||||
int parseopts(const char **a, unsigned int groups, struct opt **opts) {
|
int parseopts(const char **a, struct opt **opts) {
|
||||||
|
|
||||||
return parseopts_table(a, groups, opts, optionnames,
|
return parseopts_table(a, opts, optionnames,
|
||||||
sizeof(optionnames)/sizeof(struct optname)-1);
|
sizeof(optionnames)/sizeof(struct optname)-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1571,7 +1580,7 @@ int parseopts(const char **a, unsigned int groups, struct opt **opts) {
|
||||||
to the array opts. Uses the specified option table.
|
to the array opts. Uses the specified option table.
|
||||||
returns 0 on success, -1 on error, 1 on unknown/wrong option
|
returns 0 on success, -1 on error, 1 on unknown/wrong option
|
||||||
*/
|
*/
|
||||||
int parseopts_table(const char **a, unsigned int groups, struct opt **opts,
|
int parseopts_table(const char **a, struct opt **opts,
|
||||||
const struct optname optionnames[], size_t optionnum) {
|
const struct optname optionnames[], size_t optionnum) {
|
||||||
int i=0;
|
int i=0;
|
||||||
struct opt *opt;
|
struct opt *opt;
|
||||||
|
@ -1603,15 +1612,15 @@ int parseopts_table(const char **a, unsigned int groups, struct opt **opts,
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
/*endkey[i++] = xioopts.chainsep;*/ /* default: "|" */
|
endkey[i++] = xioopts.chainsep; /* default: "|" */
|
||||||
endkey[i++] = xioopts.pipesep; /* default: "!!" */
|
endkey[i++] = xioopts.pipesep; /* default: "%" */
|
||||||
endkey[i++] = ","/*xioopts.comma*/; /* default: "," */
|
endkey[i++] = ","/*xioopts.comma*/; /* default: "," */
|
||||||
endkey[i++] = "=";
|
endkey[i++] = "=";
|
||||||
endkey[i++] = NULL;
|
endkey[i++] = NULL;
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
/*endval[i++] = xioopts.chainsep;*/ /* default: "|" */
|
endval[i++] = xioopts.chainsep; /* default: "|" */
|
||||||
endval[i++] = xioopts.pipesep; /* default: "!!" */
|
endval[i++] = xioopts.pipesep; /* default: "%" */
|
||||||
endval[i++] = ","/*xioopts.comma*/; /* default: "," */
|
endval[i++] = ","/*xioopts.comma*/; /* default: "," */
|
||||||
endval[i++] = NULL;
|
endval[i++] = NULL;
|
||||||
|
|
||||||
|
@ -1637,7 +1646,7 @@ int parseopts_table(const char **a, unsigned int groups, struct opt **opts,
|
||||||
len = sizeof(token); tokp = token;
|
len = sizeof(token); tokp = token;
|
||||||
parsres =
|
parsres =
|
||||||
nestlex(a, &tokp, &len, endkey, hquotes, squotes, nests,
|
nestlex(a, &tokp, &len, endkey, hquotes, squotes, nests,
|
||||||
true, true, false);
|
true, true, true, false);
|
||||||
if (parsres != 0) {
|
if (parsres != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1654,6 +1663,7 @@ int parseopts_table(const char **a, unsigned int groups, struct opt **opts,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
if (!(ent->desc->group & groups) && !(ent->desc->group & GROUP_ANY) &&
|
if (!(ent->desc->group & groups) && !(ent->desc->group & GROUP_ANY) &&
|
||||||
!xioopts_ignoregroups) {
|
!xioopts_ignoregroups) {
|
||||||
Error1("parseopts(): option \"%s\" not supported with this address type",
|
Error1("parseopts(): option \"%s\" not supported with this address type",
|
||||||
|
@ -1664,6 +1674,7 @@ int parseopts_table(const char **a, unsigned int groups, struct opt **opts,
|
||||||
continue;
|
continue;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
(*opts)[i].desc = ent->desc;
|
(*opts)[i].desc = ent->desc;
|
||||||
|
|
||||||
if (!strncmp(*a, assign_str, strlen(assign_str))) {
|
if (!strncmp(*a, assign_str, strlen(assign_str))) {
|
||||||
|
@ -1672,7 +1683,7 @@ int parseopts_table(const char **a, unsigned int groups, struct opt **opts,
|
||||||
len = sizeof(token); tokp = token;
|
len = sizeof(token); tokp = token;
|
||||||
parsres =
|
parsres =
|
||||||
nestlex(a, &tokp, &len, endval, hquotes, squotes, nests,
|
nestlex(a, &tokp, &len, endval, hquotes, squotes, nests,
|
||||||
true, true, false);
|
true, true, true, false);
|
||||||
if (parsres != 0) {
|
if (parsres != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1981,7 +1992,7 @@ int parseopts_table(const char **a, unsigned int groups, struct opt **opts,
|
||||||
/*! result= */
|
/*! result= */
|
||||||
nestlex((const char **)&tokp, &buffp, &bufspc,
|
nestlex((const char **)&tokp, &buffp, &bufspc,
|
||||||
ends, NULL, NULL, nests,
|
ends, NULL, NULL, nests,
|
||||||
true, false, false);
|
true, true, false, false);
|
||||||
if (*tokp != ':') {
|
if (*tokp != ':') {
|
||||||
Error1("syntax in option %s: missing ':'", token);
|
Error1("syntax in option %s: missing ':'", token);
|
||||||
}
|
}
|
||||||
|
@ -1994,7 +2005,7 @@ int parseopts_table(const char **a, unsigned int groups, struct opt **opts,
|
||||||
/*! result= */
|
/*! result= */
|
||||||
nestlex((const char **)&tokp, &buffp, &bufspc,
|
nestlex((const char **)&tokp, &buffp, &bufspc,
|
||||||
ends, NULL, NULL, nests,
|
ends, NULL, NULL, nests,
|
||||||
true, false, false);
|
true, true, false, false);
|
||||||
*buffp++ = '\0';
|
*buffp++ = '\0';
|
||||||
(*opts)[i].value.u_ip_mreq.param2 = strdup(buff); /*!!! NULL */
|
(*opts)[i].value.u_ip_mreq.param2 = strdup(buff); /*!!! NULL */
|
||||||
|
|
||||||
|
@ -2034,7 +2045,7 @@ int parseopts_table(const char **a, unsigned int groups, struct opt **opts,
|
||||||
tokp = token;
|
tokp = token;
|
||||||
nestlex((const char **)&tokp, &buffp, &bufspc,
|
nestlex((const char **)&tokp, &buffp, &bufspc,
|
||||||
ends, NULL, NULL, nests,
|
ends, NULL, NULL, nests,
|
||||||
true, false, false);
|
true, true, false, false);
|
||||||
if (*tokp != '\0') {
|
if (*tokp != '\0') {
|
||||||
Error1("trailing data in option \"%s\"", token);
|
Error1("trailing data in option \"%s\"", token);
|
||||||
}
|
}
|
||||||
|
@ -2069,6 +2080,32 @@ int parseopts_table(const char **a, unsigned int groups, struct opt **opts,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* checks if the options conform to the group set.
|
||||||
|
returns 0 if all options conform to the group set,
|
||||||
|
or -1 otherwise. */
|
||||||
|
int xiocheckopts(struct opt *opts, unsigned int groups) {
|
||||||
|
const struct opt *opt = opts;
|
||||||
|
|
||||||
|
if (opts == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
while (opt->desc != ODESC_END) {
|
||||||
|
|
||||||
|
if (!(opt->desc->group & groups) &&
|
||||||
|
!(opt->desc->group & GROUP_ANY) &&
|
||||||
|
!xioopts_ignoregroups) {
|
||||||
|
Error1("option \"%s\" not supported with this address type",
|
||||||
|
opt->desc->defname);
|
||||||
|
Info2("parseopts() groups=%08x, opt->group=%08x",
|
||||||
|
groups, opt->desc->group);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* copy the already parsed options for repeated application, but only those
|
/* copy the already parsed options for repeated application, but only those
|
||||||
matching groups ANY and <groups> */
|
matching groups ANY and <groups> */
|
||||||
struct opt *copyopts(const struct opt *opts, unsigned int groups) {
|
struct opt *copyopts(const struct opt *opts, unsigned int groups) {
|
||||||
|
@ -2479,7 +2516,7 @@ int retropt_bind(struct opt *opts,
|
||||||
portallowed = (feats>=2);
|
portallowed = (feats>=2);
|
||||||
bindp = bindname;
|
bindp = bindname;
|
||||||
nestlex((const char **)&bindp, &hostp, &hostlen, ends, NULL, NULL, nests,
|
nestlex((const char **)&bindp, &hostp, &hostlen, ends, NULL, NULL, nests,
|
||||||
true, false, false);
|
true, true, false, false);
|
||||||
*hostp++ = '\0';
|
*hostp++ = '\0';
|
||||||
if (!strncmp(bindp, portsep, strlen(portsep))) {
|
if (!strncmp(bindp, portsep, strlen(portsep))) {
|
||||||
if (!portallowed) {
|
if (!portallowed) {
|
||||||
|
@ -2591,7 +2628,8 @@ int applyopts(int fd, struct opt *opts, unsigned int phase) {
|
||||||
long mask = opt->desc->arg3;
|
long mask = opt->desc->arg3;
|
||||||
|
|
||||||
if (Ioctl(fd, getreq, (void *)&val) < 0) {
|
if (Ioctl(fd, getreq, (void *)&val) < 0) {
|
||||||
Error4("ioctl(%d, 0x%x, %p): %s",
|
Error5("option \"%s\": ioctl(%d, 0x%x, %p): %s",
|
||||||
|
opt->desc->defname,
|
||||||
fd, opt->desc->major, (void *)&val, strerror(errno));
|
fd, opt->desc->major, (void *)&val, strerror(errno));
|
||||||
opt->desc = ODESC_ERROR; ++opt; continue;
|
opt->desc = ODESC_ERROR; ++opt; continue;
|
||||||
}
|
}
|
||||||
|
@ -3339,6 +3377,8 @@ static int applyopt_offset(struct single *xfd, struct opt *opt) {
|
||||||
switch (opt->desc->type) {
|
switch (opt->desc->type) {
|
||||||
case TYPE_BOOL:
|
case TYPE_BOOL:
|
||||||
*(bool *)ptr = opt->value.u_bool; break;
|
*(bool *)ptr = opt->value.u_bool; break;
|
||||||
|
case TYPE_UINT:
|
||||||
|
*(unsigned int *)ptr = opt->value.u_uint; break;
|
||||||
case TYPE_DOUBLE:
|
case TYPE_DOUBLE:
|
||||||
*(double *)ptr = opt->value.u_double; break;
|
*(double *)ptr = opt->value.u_double; break;
|
||||||
case TYPE_TIMEVAL:
|
case TYPE_TIMEVAL:
|
||||||
|
@ -3358,6 +3398,8 @@ static int applyopt_offset(struct single *xfd, struct opt *opt) {
|
||||||
case TYPE_CONST:
|
case TYPE_CONST:
|
||||||
*(int *)ptr = opt->desc->minor;
|
*(int *)ptr = opt->desc->minor;
|
||||||
break;
|
break;
|
||||||
|
case TYPE_TIMESPEC:
|
||||||
|
*(struct timespec *)ptr = opt->value.u_timespec; break;
|
||||||
default:
|
default:
|
||||||
Error1("applyopt_offset(): type %d not implemented",
|
Error1("applyopt_offset(): type %d not implemented",
|
||||||
opt->desc->type);
|
opt->desc->type);
|
||||||
|
@ -3574,10 +3616,10 @@ mc:addr
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HAVE_STRUCT_IP_MREQN
|
#if HAVE_STRUCT_IP_MREQN
|
||||||
if (Setsockopt(xfd->fd, opt->desc->major, opt->desc->minor,
|
if (Setsockopt(xfd->fd1, opt->desc->major, opt->desc->minor,
|
||||||
&ip4_mreqn.mreqn, sizeof(ip4_mreqn.mreqn)) < 0) {
|
&ip4_mreqn.mreqn, sizeof(ip4_mreqn.mreqn)) < 0) {
|
||||||
Error8("setsockopt(%d, %d, %d, {0x%08x,0x%08x,%d}, "F_Zu"): %s",
|
Error8("setsockopt(%d, %d, %d, {0x%08x,0x%08x,%d}, "F_Zu"): %s",
|
||||||
xfd->fd, opt->desc->major, opt->desc->minor,
|
xfd->fd1, opt->desc->major, opt->desc->minor,
|
||||||
ip4_mreqn.mreqn.imr_multiaddr.s_addr,
|
ip4_mreqn.mreqn.imr_multiaddr.s_addr,
|
||||||
ip4_mreqn.mreqn.imr_address.s_addr,
|
ip4_mreqn.mreqn.imr_address.s_addr,
|
||||||
ip4_mreqn.mreqn.imr_ifindex,
|
ip4_mreqn.mreqn.imr_ifindex,
|
||||||
|
@ -3586,10 +3628,10 @@ mc:addr
|
||||||
opt->desc = ODESC_ERROR; continue;
|
opt->desc = ODESC_ERROR; continue;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (Setsockopt(xfd->fd, opt->desc->major, opt->desc->minor,
|
if (Setsockopt(xfd->fd1, opt->desc->major, opt->desc->minor,
|
||||||
&ip4_mreqn.mreq, sizeof(ip4_mreqn.mreq)) < 0) {
|
&ip4_mreqn.mreq, sizeof(ip4_mreqn.mreq)) < 0) {
|
||||||
Error7("setsockopt(%d, %d, %d, {0x%08x,0x%08x}, "F_Zu"): %s",
|
Error7("setsockopt(%d, %d, %d, {0x%08x,0x%08x}, "F_Zu"): %s",
|
||||||
xfd->fd, opt->desc->major, opt->desc->minor,
|
xfd->fd1, opt->desc->major, opt->desc->minor,
|
||||||
ip4_mreqn.mreq.imr_multiaddr,
|
ip4_mreqn.mreq.imr_multiaddr,
|
||||||
ip4_mreqn.mreq.imr_interface,
|
ip4_mreqn.mreq.imr_interface,
|
||||||
sizeof(ip4_mreqn.mreq),
|
sizeof(ip4_mreqn.mreq),
|
||||||
|
@ -3626,10 +3668,10 @@ mc:addr
|
||||||
ip6_mreq.ipv6mr_interface = htonl(0);
|
ip6_mreq.ipv6mr_interface = htonl(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Setsockopt(xfd->fd, opt->desc->major, opt->desc->minor,
|
if (Setsockopt(xfd->fd1, opt->desc->major, opt->desc->minor,
|
||||||
&ip6_mreq, sizeof(ip6_mreq)) < 0) {
|
&ip6_mreq, sizeof(ip6_mreq)) < 0) {
|
||||||
Error6("setsockopt(%d, %d, %d, {...,0x%08x}, "F_Zu"): %s",
|
Error6("setsockopt(%d, %d, %d, {...,0x%08x}, "F_Zu"): %s",
|
||||||
xfd->fd, opt->desc->major, opt->desc->minor,
|
xfd->fd1, opt->desc->major, opt->desc->minor,
|
||||||
ip6_mreq.ipv6mr_interface,
|
ip6_mreq.ipv6mr_interface,
|
||||||
sizeof(ip6_mreq),
|
sizeof(ip6_mreq),
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
|
@ -3668,7 +3710,7 @@ int applyopts_signal(struct single *xfd, struct opt *opts) {
|
||||||
++opt; continue;
|
++opt; continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xio_opt_signal(xfd->para.exec.pid, opt->desc->major) < 0) {
|
if (xio_opt_signal(xfd->child.pid, opt->desc->major) < 0) {
|
||||||
opt->desc = ODESC_ERROR; continue;
|
opt->desc = ODESC_ERROR; continue;
|
||||||
}
|
}
|
||||||
opt->desc = ODESC_DONE;
|
opt->desc = ODESC_DONE;
|
||||||
|
@ -3685,15 +3727,23 @@ int _xio_openlate(struct single *fd, struct opt *opts) {
|
||||||
|
|
||||||
_xioopen_setdelayeduser();
|
_xioopen_setdelayeduser();
|
||||||
|
|
||||||
if ((result = applyopts(fd->fd, opts, PH_LATE)) < 0) {
|
if ((result = applyopts(fd->fd1, opts, PH_LATE)) < 0) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
#if 0 /*! need to copy opts before previous statement! */
|
||||||
|
if (fd->fdtype == FDTYPE_DOUBLE) {
|
||||||
|
if ((result = applyopts(fd->fd2, opts, PH_LATE)) < 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if ((result = applyopts_single(fd, opts, PH_LATE)) < 0) {
|
if ((result = applyopts_single(fd, opts, PH_LATE)) < 0) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
if ((result = applyopts(fd->fd, opts, PH_LATE2)) < 0) {
|
if ((result = applyopts(fd->fd1, opts, PH_LATE2)) < 0) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
/*! need to apply to fd2 too! */
|
||||||
|
|
||||||
if ((numleft = leftopts(opts)) > 0) {
|
if ((numleft = leftopts(opts)) > 0) {
|
||||||
showleft(opts);
|
showleft(opts);
|
||||||
|
|
10
xioopts.h
10
xioopts.h
|
@ -145,6 +145,7 @@ enum e_func {
|
||||||
#define GROUP_PROCESS 0x10000000 /* a process related option */
|
#define GROUP_PROCESS 0x10000000 /* a process related option */
|
||||||
#define GROUP_APPL 0x20000000 /* option handled by data loop */
|
#define GROUP_APPL 0x20000000 /* option handled by data loop */
|
||||||
#define GROUP_HTTP 0x40000000 /* any HTTP client */
|
#define GROUP_HTTP 0x40000000 /* any HTTP client */
|
||||||
|
#define GROUP_SOCKS5 0x80000000
|
||||||
|
|
||||||
#define GROUP_ANY (GROUP_PROCESS|GROUP_APPL)
|
#define GROUP_ANY (GROUP_PROCESS|GROUP_APPL)
|
||||||
#define GROUP_ALL 0xffffffff
|
#define GROUP_ALL 0xffffffff
|
||||||
|
@ -533,6 +534,7 @@ enum e_optcode {
|
||||||
OPT_SETSID,
|
OPT_SETSID,
|
||||||
OPT_SETUID,
|
OPT_SETUID,
|
||||||
OPT_SETUID_EARLY,
|
OPT_SETUID_EARLY,
|
||||||
|
OPT_SHUT_NONE,
|
||||||
OPT_SIGHUP,
|
OPT_SIGHUP,
|
||||||
OPT_SIGINT,
|
OPT_SIGINT,
|
||||||
OPT_SIGQUIT,
|
OPT_SIGQUIT,
|
||||||
|
@ -630,6 +632,8 @@ enum e_optcode {
|
||||||
#ifdef SO_USE_IFBUFS
|
#ifdef SO_USE_IFBUFS
|
||||||
OPT_SO_USE_IFBUFS,
|
OPT_SO_USE_IFBUFS,
|
||||||
#endif /* SO_USE_IFBUFS */
|
#endif /* SO_USE_IFBUFS */
|
||||||
|
OPT_SOCKS5_PASSWORD,
|
||||||
|
OPT_SOCKS5_USERNAME,
|
||||||
#if 1 || defined(WITH_SOCKS4)
|
#if 1 || defined(WITH_SOCKS4)
|
||||||
OPT_SOCKSPORT,
|
OPT_SOCKSPORT,
|
||||||
OPT_SOCKSUSER,
|
OPT_SOCKSUSER,
|
||||||
|
@ -856,10 +860,10 @@ extern int applyopts_single(struct single *fd, struct opt *opts, enum e_phase ph
|
||||||
extern int applyopts_offset(struct single *xfd, struct opt *opts);
|
extern int applyopts_offset(struct single *xfd, struct opt *opts);
|
||||||
extern int applyopts_signal(struct single *xfd, struct opt *opts);
|
extern int applyopts_signal(struct single *xfd, struct opt *opts);
|
||||||
extern int _xio_openlate(struct single *fd, struct opt *opts);
|
extern int _xio_openlate(struct single *fd, struct opt *opts);
|
||||||
extern int parseopts(const char **a, unsigned int groups, struct opt **opts);
|
extern int parseopts(const char **a, struct opt **opts);
|
||||||
extern int parseopts_table(const char **a, unsigned int groups,
|
extern int parseopts_table(const char **a, struct opt **opts,
|
||||||
struct opt **opts,
|
|
||||||
const struct optname optionnames[], size_t optionnum);
|
const struct optname optionnames[], size_t optionnum);
|
||||||
|
extern int xiocheckopts(struct opt *opts, unsigned int groups);
|
||||||
extern struct opt *copyopts(const struct opt *opts, unsigned int groups);
|
extern struct opt *copyopts(const struct opt *opts, unsigned int groups);
|
||||||
extern struct opt *moveopts(struct opt *opts, unsigned int groups);
|
extern struct opt *moveopts(struct opt *opts, unsigned int groups);
|
||||||
extern int leftopts(const struct opt *opts);
|
extern int leftopts(const struct opt *opts);
|
||||||
|
|
20
xioparam.c
20
xioparam.c
|
@ -1,5 +1,5 @@
|
||||||
/* $Id: xioparam.c,v 1.10 2006/06/19 20:30:24 gerhard Exp $ */
|
/* $Id: xioparam.c,v 1.10 2006/06/19 20:30:24 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2001-2006 */
|
/* Copyright Gerhard Rieger 2001-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
/* this file contains the source for xio options handling */
|
/* this file contains the source for xio options handling */
|
||||||
|
@ -12,16 +12,28 @@
|
||||||
/* options that can be applied to this module */
|
/* options that can be applied to this module */
|
||||||
xioopts_t xioopts = {
|
xioopts_t xioopts = {
|
||||||
false, /* strictopts */
|
false, /* strictopts */
|
||||||
"!!", /* pipesep */
|
"%", /* pipesep */
|
||||||
":", /* paramsep */
|
":", /* paramsep */
|
||||||
",", /* optionsep */
|
",", /* optionsep */
|
||||||
':', /* ip4portsep */
|
':', /* ip4portsep */
|
||||||
':', /* ip6portsep */
|
':', /* ip6portsep */
|
||||||
'\0', /* logopt */
|
|
||||||
NULL, /* syslogfac */
|
NULL, /* syslogfac */
|
||||||
'4', /* default_ip */
|
'4', /* default_ip */
|
||||||
'4' /* preferred_ip */
|
'4', /* preferred_ip */
|
||||||
|
"^", /* reversechar */
|
||||||
|
"|", /* chainsep */
|
||||||
|
8192, /* bufsiz */
|
||||||
|
false, /* verbose */
|
||||||
|
false, /* verbhex */
|
||||||
|
0, /* debug */
|
||||||
|
's', /* logopt */
|
||||||
|
{0,0}, /* total_timeout */
|
||||||
|
{1,0}, /* pollintv */
|
||||||
|
{0,500000}, /* closwait */
|
||||||
|
false, /* lefttoright */
|
||||||
|
false, /* righttoleft */
|
||||||
} ;
|
} ;
|
||||||
|
xioopts_t *xioparams = &xioopts;
|
||||||
|
|
||||||
|
|
||||||
/* allow application to set xioopen options */
|
/* allow application to set xioopen options */
|
||||||
|
|
60
xioread.c
60
xioread.c
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include "xio-termios.h"
|
#include "xio-termios.h"
|
||||||
#include "xio-socket.h"
|
#include "xio-socket.h"
|
||||||
|
#include "xio-test.h"
|
||||||
#include "xio-readline.h"
|
#include "xio-readline.h"
|
||||||
#include "xio-openssl.h"
|
#include "xio-openssl.h"
|
||||||
|
|
||||||
|
@ -21,6 +22,7 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
|
||||||
int nexthead;
|
int nexthead;
|
||||||
#endif
|
#endif
|
||||||
struct single *pipe;
|
struct single *pipe;
|
||||||
|
int fd;
|
||||||
int _errno;
|
int _errno;
|
||||||
|
|
||||||
if (file->tag == XIO_TAG_INVALID) {
|
if (file->tag == XIO_TAG_INVALID) {
|
||||||
|
@ -50,10 +52,12 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fd = XIO_GETRDFD(file);
|
||||||
|
|
||||||
switch (pipe->dtype & XIODATA_READMASK) {
|
switch (pipe->dtype & XIODATA_READMASK) {
|
||||||
case XIOREAD_STREAM:
|
case XIOREAD_STREAM:
|
||||||
do {
|
do {
|
||||||
bytes = Read(pipe->fd, buff, bufsiz);
|
bytes = Read(fd, buff, bufsiz);
|
||||||
} while (bytes < 0 && errno == EINTR);
|
} while (bytes < 0 && errno == EINTR);
|
||||||
if (bytes < 0) {
|
if (bytes < 0) {
|
||||||
_errno = errno;
|
_errno = errno;
|
||||||
|
@ -61,12 +65,30 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
|
||||||
#if 1
|
#if 1
|
||||||
case EPIPE: case ECONNRESET:
|
case EPIPE: case ECONNRESET:
|
||||||
Warn4("read(%d, %p, "F_Zu"): %s",
|
Warn4("read(%d, %p, "F_Zu"): %s",
|
||||||
pipe->fd, buff, bufsiz, strerror(_errno));
|
fd, buff, bufsiz, strerror(_errno));
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
Error4("read(%d, %p, "F_Zu"): %s",
|
Error4("read(%d, %p, "F_Zu"): %s",
|
||||||
pipe->fd, buff, bufsiz, strerror(_errno));
|
fd, buff, bufsiz, strerror(_errno));
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case XIODATA_PTY:
|
||||||
|
do {
|
||||||
|
bytes = Read(fd, buff, bufsiz);
|
||||||
|
} while (bytes < 0 && errno == EINTR);
|
||||||
|
if (bytes < 0) {
|
||||||
|
_errno = errno;
|
||||||
|
if (_errno == EIO) {
|
||||||
|
Notice4("read(%d, %p, "F_Zu"): %s (probably PTY closed)",
|
||||||
|
fd, buff, bufsiz, strerror(_errno));
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
Error4("read(%d, %p, "F_Zu"): %s",
|
||||||
|
fd, buff, bufsiz, strerror(_errno));
|
||||||
}
|
}
|
||||||
errno = _errno;
|
errno = _errno;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -75,17 +97,17 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
|
||||||
|
|
||||||
case XIOREAD_PTY:
|
case XIOREAD_PTY:
|
||||||
do {
|
do {
|
||||||
bytes = Read(pipe->fd, buff, bufsiz);
|
bytes = Read(fd, buff, bufsiz);
|
||||||
} while (bytes < 0 && errno == EINTR);
|
} while (bytes < 0 && errno == EINTR);
|
||||||
if (bytes < 0) {
|
if (bytes < 0) {
|
||||||
_errno = errno;
|
_errno = errno;
|
||||||
if (_errno == EIO) {
|
if (_errno == EIO) {
|
||||||
Notice4("read(%d, %p, "F_Zu"): %s (probably PTY closed)",
|
Notice4("read(%d, %p, "F_Zu"): %s (probably PTY closed)",
|
||||||
pipe->fd, buff, bufsiz, strerror(_errno));
|
fd, buff, bufsiz, strerror(_errno));
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
Error4("read(%d, %p, "F_Zu"): %s",
|
Error4("read(%d, %p, "F_Zu"): %s",
|
||||||
pipe->fd, buff, bufsiz, strerror(_errno));
|
fd, buff, bufsiz, strerror(_errno));
|
||||||
}
|
}
|
||||||
errno = _errno;
|
errno = _errno;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -100,6 +122,15 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
|
||||||
break;
|
break;
|
||||||
#endif /* WITH_READLINE */
|
#endif /* WITH_READLINE */
|
||||||
|
|
||||||
|
#if WITH_TEST
|
||||||
|
case XIOREAD_TEST:
|
||||||
|
/* this function prints its error messages */
|
||||||
|
if ((bytes = xioread_test(pipe, buff, bufsiz)) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif /* WITH_TEST */
|
||||||
|
|
||||||
#if WITH_OPENSSL
|
#if WITH_OPENSSL
|
||||||
case XIOREAD_OPENSSL:
|
case XIOREAD_OPENSSL:
|
||||||
/* this function prints its error messages */
|
/* this function prints its error messages */
|
||||||
|
@ -118,14 +149,13 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
|
||||||
char infobuff[256];
|
char infobuff[256];
|
||||||
|
|
||||||
do {
|
do {
|
||||||
bytes =
|
bytes = Recvfrom(fd, buff, bufsiz, 0, &from.soa, &fromlen);
|
||||||
Recvfrom(pipe->fd, buff, bufsiz, 0, &from.soa, &fromlen);
|
|
||||||
} while (bytes < 0 && errno == EINTR);
|
} while (bytes < 0 && errno == EINTR);
|
||||||
if (bytes < 0) {
|
if (bytes < 0) {
|
||||||
char infobuff[256];
|
char infobuff[256];
|
||||||
_errno = errno;
|
_errno = errno;
|
||||||
Error6("recvfrom(%d, %p, "F_Zu", 0, %s, {"F_socklen"}): %s",
|
Error6("recvfrom(%d, %p, "F_Zu", 0, %s, {"F_socklen"}): %s",
|
||||||
pipe->fd, buff, bufsiz,
|
fd, buff, bufsiz,
|
||||||
sockaddr_info(&from.soa, fromlen, infobuff, sizeof(infobuff)),
|
sockaddr_info(&from.soa, fromlen, infobuff, sizeof(infobuff)),
|
||||||
fromlen, strerror(errno));
|
fromlen, strerror(errno));
|
||||||
errno = _errno;
|
errno = _errno;
|
||||||
|
@ -209,7 +239,7 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
|
||||||
headlen = 4*((struct ip *)buff)->ip_vhl;
|
headlen = 4*((struct ip *)buff)->ip_vhl;
|
||||||
#endif
|
#endif
|
||||||
if (headlen > bytes) {
|
if (headlen > bytes) {
|
||||||
Warn1("xioread(%d, ...)/IP4: short packet", pipe->fd);
|
Warn1("xioread(%d, ...)/IP4: short packet", fd);
|
||||||
bytes = 0;
|
bytes = 0;
|
||||||
} else {
|
} else {
|
||||||
memmove(buff, ((char *)buff)+headlen, bytes-headlen);
|
memmove(buff, ((char *)buff)+headlen, bytes-headlen);
|
||||||
|
@ -286,11 +316,11 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
|
||||||
|
|
||||||
socket_init(pipe->para.socket.la.soa.sa_family, &from);
|
socket_init(pipe->para.socket.la.soa.sa_family, &from);
|
||||||
/* get source address */
|
/* get source address */
|
||||||
if (xiogetpacketsrc(pipe->fd, &from, &fromlen) < 0) {
|
if (xiogetpacketsrc(fd, &from, &fromlen) < 0) {
|
||||||
return STAT_RETRYNOW;
|
return STAT_RETRYNOW;
|
||||||
}
|
}
|
||||||
if (xiocheckpeer(pipe, &from, &pipe->para.socket.la) < 0) {
|
if (xiocheckpeer(pipe, &from, &pipe->para.socket.la) < 0) {
|
||||||
Recvfrom(pipe->fd, buff, bufsiz, 0, &from.soa, &fromlen); /* drop */
|
Recvfrom(fd, buff, bufsiz, 0, &from.soa, &fromlen); /* drop */
|
||||||
errno = EAGAIN; return -1;
|
errno = EAGAIN; return -1;
|
||||||
}
|
}
|
||||||
Info1("permitting packet from %s",
|
Info1("permitting packet from %s",
|
||||||
|
@ -299,13 +329,13 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
|
||||||
|
|
||||||
do {
|
do {
|
||||||
bytes =
|
bytes =
|
||||||
Recvfrom(pipe->fd, buff, bufsiz, 0, &from.soa, &fromlen);
|
Recvfrom(fd, buff, bufsiz, 0, &from.soa, &fromlen);
|
||||||
} while (bytes < 0 && errno == EINTR);
|
} while (bytes < 0 && errno == EINTR);
|
||||||
if (bytes < 0) {
|
if (bytes < 0) {
|
||||||
char infobuff[256];
|
char infobuff[256];
|
||||||
_errno = errno;
|
_errno = errno;
|
||||||
Error6("recvfrom(%d, %p, "F_Zu", 0, %s, "F_socklen"): %s",
|
Error6("recvfrom(%d, %p, "F_Zu", 0, %s, "F_socklen"): %s",
|
||||||
pipe->fd, buff, bufsiz,
|
fd, buff, bufsiz,
|
||||||
sockaddr_info(&from.soa, fromlen, infobuff, sizeof(infobuff)),
|
sockaddr_info(&from.soa, fromlen, infobuff, sizeof(infobuff)),
|
||||||
fromlen, strerror(errno));
|
fromlen, strerror(errno));
|
||||||
errno = _errno;
|
errno = _errno;
|
||||||
|
@ -334,7 +364,7 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
|
||||||
headlen = 4*((struct ip *)buff)->ip_vhl;
|
headlen = 4*((struct ip *)buff)->ip_vhl;
|
||||||
#endif
|
#endif
|
||||||
if (headlen > bytes) {
|
if (headlen > bytes) {
|
||||||
Warn1("xioread(%d, ...)/IP4: short packet", pipe->fd);
|
Warn1("xioread(%d, ...)/IP4: short packet", fd);
|
||||||
bytes = 0;
|
bytes = 0;
|
||||||
} else {
|
} else {
|
||||||
memmove(buff, ((char *)buff)+headlen, bytes-headlen);
|
memmove(buff, ((char *)buff)+headlen, bytes-headlen);
|
||||||
|
|
265
xioshutdown.c
265
xioshutdown.c
|
@ -8,6 +8,9 @@
|
||||||
#include "xiosysincludes.h"
|
#include "xiosysincludes.h"
|
||||||
#include "xioopen.h"
|
#include "xioopen.h"
|
||||||
|
|
||||||
|
|
||||||
|
static int xioshut_sleep_kill(pid_t sub, unsigned long usec, int sig);
|
||||||
|
|
||||||
static pid_t socat_kill_pid; /* here we pass the pid to be killed in sighandler */
|
static pid_t socat_kill_pid; /* here we pass the pid to be killed in sighandler */
|
||||||
|
|
||||||
static void signal_kill_pid(int dummy) {
|
static void signal_kill_pid(int dummy) {
|
||||||
|
@ -15,15 +18,21 @@ static void signal_kill_pid(int dummy) {
|
||||||
Kill(socat_kill_pid, SIGTERM);
|
Kill(socat_kill_pid, SIGTERM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* how: SHUT_RD, SHUT_WR, or SHUT_RDWR */
|
||||||
int xioshutdown(xiofile_t *sock, int how) {
|
int xioshutdown(xiofile_t *sock, int how) {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
|
Debug2("xioshutdown(%p, %d)", sock, how);
|
||||||
|
Debug2("xioshutdown(): dtype=0x%x, howtoshut=0x%04x",
|
||||||
|
sock->stream.dtype, sock->stream.howtoshut);
|
||||||
|
|
||||||
if (sock->tag == XIO_TAG_INVALID) {
|
if (sock->tag == XIO_TAG_INVALID) {
|
||||||
Error("xioshutdown(): invalid file descriptor");
|
Error("xioshutdown(): invalid file descriptor");
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*Debug3("xioshutdown: flags=%d, dtype=%d, howtoclose=%d", sock->stream.flags, sock->stream.dtype, sock->stream.howtoclose);*/
|
||||||
if (sock->tag == XIO_TAG_DUAL) {
|
if (sock->tag == XIO_TAG_DUAL) {
|
||||||
if ((how+1)&1) {
|
if ((how+1)&1) {
|
||||||
result = xioshutdown((xiofile_t *)sock->dual.stream[0], 0);
|
result = xioshutdown((xiofile_t *)sock->dual.stream[0], 0);
|
||||||
|
@ -31,104 +40,182 @@ int xioshutdown(xiofile_t *sock, int how) {
|
||||||
if ((how+1)&2) {
|
if ((how+1)&2) {
|
||||||
result |= xioshutdown((xiofile_t *)sock->dual.stream[1], 1);
|
result |= xioshutdown((xiofile_t *)sock->dual.stream[1], 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if WITH_OPENSSL
|
|
||||||
} else if ((sock->stream.dtype & XIODATA_MASK) == XIODATA_OPENSSL) {
|
|
||||||
sycSSL_shutdown (sock->stream.para.openssl.ssl);
|
|
||||||
/*! what about half/full close? */
|
|
||||||
#endif /* WITH_OPENSSL */
|
|
||||||
|
|
||||||
} else if ((sock->stream.dtype & XIODATA_MASK) == XIODATA_PIPE) {
|
|
||||||
if ((how+1)&1) {
|
|
||||||
if (Close(sock->stream.fd) < 0) {
|
|
||||||
Info2("close(%d): %s",
|
|
||||||
sock->stream.fd, strerror(errno));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((how+1)&2) {
|
|
||||||
if (Close(sock->stream.para.bipipe.fdout) < 0) {
|
|
||||||
Info2("close(%d): %s",
|
|
||||||
sock->stream.para.bipipe.fdout, strerror(errno));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if ((sock->stream.dtype & XIODATA_MASK) == XIODATA_2PIPE) {
|
|
||||||
if ((how+1)&1) {
|
|
||||||
if (Close(sock->stream.fd) < 0) {
|
|
||||||
Info2("close(%d): %s",
|
|
||||||
sock->stream.fd, strerror(errno));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((how+1)&2) {
|
|
||||||
if (Close(sock->stream.para.exec.fdout) < 0) {
|
|
||||||
Info2("close(%d): %s",
|
|
||||||
sock->stream.para.exec.fdout, strerror(errno));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#if WITH_SOCKET
|
|
||||||
} else if (sock->stream.howtoend == END_SHUTDOWN) {
|
|
||||||
if ((result = Shutdown(sock->stream.fd, how)) < 0) {
|
|
||||||
Info3("shutdown(%d, %d): %s",
|
|
||||||
sock->stream.fd, how, strerror(errno));
|
|
||||||
}
|
|
||||||
} else if (sock->stream.howtoend == END_SHUTDOWN_KILL) {
|
|
||||||
if ((result = Shutdown(sock->stream.fd, how)) < 0) {
|
|
||||||
Info3("shutdown(%d, %d): %s",
|
|
||||||
sock->stream.fd, how, strerror(errno));
|
|
||||||
}
|
|
||||||
if ((sock->stream.flags&XIO_ACCMODE) == XIO_WRONLY) {
|
|
||||||
/* the child process might want to flush some data before terminating
|
|
||||||
*/
|
|
||||||
int status = 0;
|
|
||||||
|
|
||||||
/* we wait for the child process to die, but to prevent timeout
|
|
||||||
we raise an alarm after some time.
|
|
||||||
NOTE: the alarm does not terminate waitpid() on Linux/glibc (BUG?),
|
|
||||||
therefore we have to do the kill in the signal handler */
|
|
||||||
Signal(SIGALRM, signal_kill_pid);
|
|
||||||
socat_kill_pid = sock->stream.para.exec.pid;
|
|
||||||
#if HAVE_SETITIMER
|
|
||||||
/*! with next feature release, we get usec resolution and an option */
|
|
||||||
#else
|
|
||||||
Alarm(1 /*! sock->stream.para.exec.waitdie */);
|
|
||||||
#endif /* !HAVE_SETITIMER */
|
|
||||||
if (Waitpid(sock->stream.para.exec.pid, &status, 0) < 0) {
|
|
||||||
Warn3("waitpid("F_pid", %p, 0): %s",
|
|
||||||
sock->stream.para.exec.pid, &status, strerror(errno));
|
|
||||||
}
|
|
||||||
Alarm(0);
|
|
||||||
}
|
|
||||||
} else if ((sock->stream.dtype & XIODATA_MASK) == XIODATA_RECVFROM) {
|
|
||||||
if (how >= 1) {
|
|
||||||
if (Close(sock->stream.fd) < 0) {
|
|
||||||
Info2("close(%d): %s",
|
|
||||||
sock->stream.fd, strerror(errno));
|
|
||||||
}
|
|
||||||
sock->stream.eof = 2;
|
|
||||||
sock->stream.fd = -1;
|
|
||||||
}
|
|
||||||
#endif /* WITH_SOCKET */
|
|
||||||
#if 0
|
|
||||||
} else {
|
|
||||||
Error1("xioshutdown(): bad data type specification %d", sock->stream.dtype);
|
|
||||||
return -1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
else if (sock->stream.howtoend == END_CLOSE &&
|
|
||||||
sock->stream.dtype == DATA_STREAM) {
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* let us bring how nearer to the resulting action */
|
||||||
|
if ((sock->stream.flags&XIO_ACCMODE) == XIO_WRONLY) {
|
||||||
|
how = ((how+1) & ~(SHUT_RD+1)) - 1;
|
||||||
|
} else if ((sock->stream.flags&XIO_ACCMODE) == XIO_RDONLY) {
|
||||||
|
how = ((how+1) & ~(SHUT_WR+1)) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* here handle special shutdown functions */
|
||||||
|
switch (sock->stream.howtoshut) {
|
||||||
|
#if WITH_OPENSSL
|
||||||
|
case XIOSHUT_OPENSSL:
|
||||||
|
sycSSL_shutdown(sock->stream.para.openssl.ssl);
|
||||||
|
/*! what about half/full close? */
|
||||||
|
return 0;
|
||||||
|
#endif /* WITH_OPENSSL */
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (how == SHUT_RDWR) {
|
||||||
|
/* in this branch we handle only shutdown actions where read and write
|
||||||
|
shutdown are not independent */
|
||||||
|
|
||||||
|
switch (sock->stream.howtoshut) {
|
||||||
|
#if 0
|
||||||
|
case XIODATA_STREAM:
|
||||||
|
switch (sock->stream.howtoclose) {
|
||||||
|
#if WITH_SOCKET
|
||||||
|
case END_SHUTDOWN:
|
||||||
|
if ((result = Shutdown(sock->stream.fd1, how)) < 0) {
|
||||||
|
Info3("shutdown(%d, %d): %s",
|
||||||
|
sock->stream.fd1, how, strerror(errno));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case END_SHUTDOWN_KILL:
|
||||||
|
if ((result = Shutdown(sock->stream.fd1, how)) < 0) {
|
||||||
|
Info3("shutdown(%d, %d): %s",
|
||||||
|
sock->stream.fd1, how, strerror(errno));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif /* WITH_SOCKET */
|
||||||
|
case END_CLOSE:
|
||||||
|
Close(sock->stream.fd1);
|
||||||
#if WITH_TERMIOS
|
#if WITH_TERMIOS
|
||||||
if (sock->stream.ttyvalid) {
|
if (sock->stream.ttyvalid) {
|
||||||
if (Tcsetattr(sock->stream.fd, 0, &sock->stream.savetty) < 0) {
|
if (Tcsetattr(sock->stream.fd1, 0, &sock->stream.savetty) < 0) {
|
||||||
Warn2("cannot restore terminal settings on fd %d: %s",
|
Warn2("cannot restore terminal settings on fd %d: %s",
|
||||||
sock->stream.fd, strerror(errno));
|
sock->stream.fd1, strerror(errno));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WITH_TERMIOS */
|
#endif /* WITH_TERMIOS */
|
||||||
|
/*PASSTHROUGH*/
|
||||||
|
case END_NONE:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Error1("xioshutdown(): bad end action 0x%x", sock->stream.howtoclose);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#if WITH_SOCKET
|
||||||
|
case XIODATA_RECVFROM:
|
||||||
|
if (how >= 1) {
|
||||||
|
if (Close(sock->stream.fd1) < 0) {
|
||||||
|
Info2("close(%d): %s",
|
||||||
|
sock->stream.fd1, strerror(errno));
|
||||||
|
}
|
||||||
|
sock->stream.eof = 2;
|
||||||
|
sock->stream.fd1 = -1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif /* WITH_SOCKET */
|
||||||
|
#endif /* 0 */
|
||||||
|
default:
|
||||||
|
Error1("xioshutdown(): bad data type specification 0x%x", sock->stream.dtype);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((how+1) & 1) { /* contains SHUT_RD */
|
||||||
|
switch (sock->stream.dtype & XIODATA_READMASK) {
|
||||||
|
/* shutdown read channel */
|
||||||
|
|
||||||
|
case XIOREAD_STREAM:
|
||||||
|
case XIODATA_2PIPE:
|
||||||
|
if (Close(sock->stream.fd1) < 0) {
|
||||||
|
Info2("close(%d): %s",
|
||||||
|
sock->stream.fd1, strerror(errno));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((how+1) & 2) { /* contains SHUT_WR */
|
||||||
|
/* shutdown write channel */
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
if (sock->stream.fdtype == FDTYPE_DOUBLE) {
|
||||||
|
fd = sock->stream.fd2;
|
||||||
|
} else {
|
||||||
|
fd = sock->stream.fd1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (sock->stream.howtoshut & XIOSHUTWR_MASK) {
|
||||||
|
|
||||||
|
case XIOSHUTWR_CLOSE:
|
||||||
|
if (Close(fd) < 0) {
|
||||||
|
Info2("close(%d): %s", fd, strerror(errno));
|
||||||
|
}
|
||||||
|
/*PASSTHROUGH*/
|
||||||
|
case XIOSHUTWR_NONE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if WITH_SOCKET
|
||||||
|
case XIOSHUTWR_DOWN:
|
||||||
|
if (Shutdown(fd, SHUT_WR) < 0) {
|
||||||
|
Info2("shutdown(%d, SHUT_WR): %s", fd, strerror(errno));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif /* WITH_SOCKET */
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
case XIOSHUTWR_DOWN_KILL:
|
||||||
|
if (Shutdown(fd, SHUT_WR) < 0) {
|
||||||
|
Info2("shutdown(%d, SHUT_WR): %s", fd, strerror(errno));
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
case XIOSHUTWR_SIGHUP:
|
||||||
|
/* the child process might want to flush some data before
|
||||||
|
terminating */
|
||||||
|
xioshut_sleep_kill(sock->stream.child.pid, 0, SIGHUP);
|
||||||
|
break;
|
||||||
|
case XIOSHUTWR_SIGTERM:
|
||||||
|
/* the child process might want to flush some data before
|
||||||
|
terminating */
|
||||||
|
xioshut_sleep_kill(sock->stream.child.pid, 1000000, SIGTERM);
|
||||||
|
break;
|
||||||
|
case XIOSHUTWR_SIGKILL:
|
||||||
|
/* the child process might want to flush some data before
|
||||||
|
terminating */
|
||||||
|
xioshut_sleep_kill(sock->stream.child.pid, 1000000, SIGKILL);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Error1("xioshutdown(): unhandled howtoshut=0x%x during SHUT_WR",
|
||||||
|
sock->stream.howtoshut);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* wait some time and then send signal to sub process. This is useful after
|
||||||
|
shutting down the connection to give process some time to flush its output
|
||||||
|
data */
|
||||||
|
static int xioshut_sleep_kill(pid_t sub, unsigned long usec, int sig) {
|
||||||
|
struct sigaction act;
|
||||||
|
int status = 0;
|
||||||
|
|
||||||
|
/* we wait for the child process to die, but to prevent timeout
|
||||||
|
we raise an alarm after some time. */
|
||||||
|
/* NOTE: the alarm does not terminate waitpid() on Linux/glibc
|
||||||
|
(BUG?),
|
||||||
|
therefore we have to do the kill in the signal handler */
|
||||||
|
Signal(SIGALRM, signal_kill_pid);
|
||||||
|
socat_kill_pid = sub;
|
||||||
|
#if HAVE_SETITIMER
|
||||||
|
/*! with next feature release, we get usec resolution and an option
|
||||||
|
*/
|
||||||
|
#else
|
||||||
|
Alarm(1 /*! sock->stream.child.waitdie */);
|
||||||
|
#endif /* !HAVE_SETITIMER */
|
||||||
|
if (Waitpid(sub, &status, 0) < 0) {
|
||||||
|
Warn3("waitpid("F_pid", %p, 0): %s",
|
||||||
|
sub, &status, strerror(errno));
|
||||||
|
}
|
||||||
|
Alarm(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
167
xiosigchld.c
167
xiosigchld.c
|
@ -1,5 +1,5 @@
|
||||||
/* $Id: xiosigchld.c,v 1.21 2006/12/28 14:38:38 gerhard Exp $ */
|
/* $Id: xiosigchld.c,v 1.21 2006/12/28 14:38:38 gerhard Exp $ */
|
||||||
/* Copyright Gerhard Rieger 2001-2006 */
|
/* Copyright Gerhard Rieger 2001-2007 */
|
||||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
/* this is the source of the extended child signal handler */
|
/* this is the source of the extended child signal handler */
|
||||||
|
@ -7,23 +7,42 @@
|
||||||
|
|
||||||
#include "xiosysincludes.h"
|
#include "xiosysincludes.h"
|
||||||
#include "xioopen.h"
|
#include "xioopen.h"
|
||||||
|
#include "xiosigchld.h"
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* we maintain a table of all known child processes */
|
||||||
|
/* for now, we use a very primitive data structure - just an unsorted, size
|
||||||
|
limited array */
|
||||||
|
|
||||||
/*!! with socat, at most 4 exec children exist */
|
#define XIO_MAXCHILDPIDS 16
|
||||||
|
|
||||||
|
struct _xiosigchld_child {
|
||||||
|
pid_t pid;
|
||||||
|
void (*sigaction)(int, siginfo_t *, void *);
|
||||||
|
void *context;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
static struct _xiosigchld_child * _xiosigchld_find(pid_t pid);
|
||||||
|
|
||||||
|
static struct _xiosigchld_child xio_childpids[XIO_MAXCHILDPIDS];
|
||||||
|
|
||||||
|
#if 1 /*!!!*/
|
||||||
|
/*!! with socat, at most 4 managed children exist */
|
||||||
pid_t diedunknown1; /* child died before it is registered */
|
pid_t diedunknown1; /* child died before it is registered */
|
||||||
pid_t diedunknown2;
|
pid_t diedunknown2;
|
||||||
pid_t diedunknown3;
|
pid_t diedunknown3;
|
||||||
pid_t diedunknown4;
|
pid_t diedunknown4;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* register for a xio filedescriptor a callback (handler).
|
/* register for a xio filedescriptor a callback (handler).
|
||||||
when a SIGCHLD occurs, the signal handler will ??? */
|
when a SIGCHLD occurs, the signal handler will ??? */
|
||||||
int xiosetsigchild(xiofile_t *xfd, int (*callback)(struct single *)) {
|
int xiosetsigchild(xiofile_t *xfd, int (*callback)(struct single *)) {
|
||||||
if (xfd->tag != XIO_TAG_DUAL) {
|
if (xfd->tag != XIO_TAG_DUAL) {
|
||||||
xfd->stream.sigchild = callback;
|
xfd->stream.child.sigchild = callback;
|
||||||
} else {
|
} else {
|
||||||
xfd->dual.stream[0]->sigchild = callback;
|
xfd->dual.stream[0]->child.sigchild = callback;
|
||||||
xfd->dual.stream[1]->sigchild = callback;
|
xfd->dual.stream[1]->child.sigchild = callback;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -31,9 +50,9 @@ int xiosetsigchild(xiofile_t *xfd, int (*callback)(struct single *)) {
|
||||||
/* exec'd child has died, perform appropriate changes to descriptor */
|
/* exec'd child has died, perform appropriate changes to descriptor */
|
||||||
static int sigchld_stream(struct single *file) {
|
static int sigchld_stream(struct single *file) {
|
||||||
/*!! call back to application */
|
/*!! call back to application */
|
||||||
file->para.exec.pid = 0;
|
file->child.pid = 0;
|
||||||
if (file->sigchild) {
|
if (file->child.sigchild) {
|
||||||
return (*file->sigchild)(file);
|
return (*file->child.sigchild)(file);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -43,12 +62,9 @@ static int xio_checkchild(xiofile_t *socket, int socknum, pid_t deadchild) {
|
||||||
int retval;
|
int retval;
|
||||||
if (socket != NULL) {
|
if (socket != NULL) {
|
||||||
if (socket->tag != XIO_TAG_DUAL) {
|
if (socket->tag != XIO_TAG_DUAL) {
|
||||||
if ((socket->stream.howtoend == END_KILL ||
|
if (socket->stream.child.pid == deadchild) {
|
||||||
socket->stream.howtoend == END_CLOSE_KILL ||
|
|
||||||
socket->stream.howtoend == END_SHUTDOWN_KILL) &&
|
|
||||||
socket->stream.para.exec.pid == deadchild) {
|
|
||||||
Info2("exec'd process %d on socket %d terminated",
|
Info2("exec'd process %d on socket %d terminated",
|
||||||
socket->stream.para.exec.pid, socknum);
|
socket->stream.child.pid, socknum);
|
||||||
sigchld_stream(&socket->stream);
|
sigchld_stream(&socket->stream);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -64,17 +80,22 @@ static int xio_checkchild(xiofile_t *socket, int socknum, pid_t deadchild) {
|
||||||
|
|
||||||
/* this is the "physical" signal handler for SIGCHLD */
|
/* this is the "physical" signal handler for SIGCHLD */
|
||||||
/* the current socat/xio implementation knows two kinds of children:
|
/* the current socat/xio implementation knows two kinds of children:
|
||||||
exec/system addresses perform a fork: these children are registered and
|
exec/system addresses perform a fork: their children are registered and
|
||||||
there death influences the parents flow;
|
their death's influence the parents' flow;
|
||||||
listen-socket with fork children: these children are "anonymous" and their
|
listen-socket with fork children: these children are "anonymous" and their
|
||||||
death does not affect the parent process (now; maybe we have a child
|
death does not affect the parent process (now; maybe we have a child
|
||||||
process counter later) */
|
process counter later) */
|
||||||
void childdied(int signum) {
|
void childdied(int signum
|
||||||
|
#if HAVE_SIGACTION
|
||||||
|
, siginfo_t *siginfo, void *context
|
||||||
|
#endif /* HAVE_SIGACTION */
|
||||||
|
) {
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int _errno;
|
int _errno;
|
||||||
int status = 0;
|
int status = 0;
|
||||||
bool wassig = false;
|
bool wassig = false;
|
||||||
int i;
|
int i;
|
||||||
|
struct _xiosigchld_child *entry;
|
||||||
|
|
||||||
_errno = errno; /* save current value; e.g., select() on Cygwin seems
|
_errno = errno; /* save current value; e.g., select() on Cygwin seems
|
||||||
to set it to EINTR _before_ handling the signal, and
|
to set it to EINTR _before_ handling the signal, and
|
||||||
|
@ -105,6 +126,7 @@ void childdied(int signum) {
|
||||||
errno = _errno;
|
errno = _errno;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
/*! indent */
|
/*! indent */
|
||||||
/* check if it was a registered child process */
|
/* check if it was a registered child process */
|
||||||
i = 0;
|
i = 0;
|
||||||
|
@ -128,6 +150,15 @@ void childdied(int signum) {
|
||||||
Debug("saving pid in diedunknown4");
|
Debug("saving pid in diedunknown4");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
entry = _xiosigchld_find(pid);
|
||||||
|
if (entry == NULL) {
|
||||||
|
Info("dead child "F_pid" died unknown");
|
||||||
|
} else {
|
||||||
|
(*entry->sigaction)(signum, siginfo, entry->context);
|
||||||
|
xiosigchld_unregister(pid);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (WIFEXITED(status)) {
|
if (WIFEXITED(status)) {
|
||||||
if (WEXITSTATUS(status) == 0) {
|
if (WEXITSTATUS(status) == 0) {
|
||||||
|
@ -157,3 +188,107 @@ void childdied(int signum) {
|
||||||
Info("childdied() finished");
|
Info("childdied() finished");
|
||||||
errno = _errno;
|
errno = _errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* search for given pid in child process table. returns matching entry on
|
||||||
|
success, or NULL if not found. Can be used with pid==0 to look for an empty
|
||||||
|
entry. */
|
||||||
|
static struct _xiosigchld_child *
|
||||||
|
_xiosigchld_find(pid_t pid) {
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* is it already registered? */
|
||||||
|
for (i = 0; i < XIO_MAXCHILDPIDS; ++i) {
|
||||||
|
if (pid == xio_childpids[i].pid) {
|
||||||
|
return &xio_childpids[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add a child process to the table
|
||||||
|
returns 0 on success (registered or reregistered child)
|
||||||
|
returns -1 on table overflow
|
||||||
|
*/
|
||||||
|
int xiosigchld_register(pid_t pid,
|
||||||
|
void (*sigaction)(int, siginfo_t *, void *),
|
||||||
|
void *context) {
|
||||||
|
struct _xiosigchld_child *entry;
|
||||||
|
|
||||||
|
/* is it already registered? */
|
||||||
|
if (entry = _xiosigchld_find(pid)) {
|
||||||
|
/* was already registered, override */
|
||||||
|
entry->sigaction = sigaction;
|
||||||
|
entry->context = context;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* try to register it */
|
||||||
|
if (entry = _xiosigchld_find(0)) {
|
||||||
|
entry->pid = pid;
|
||||||
|
entry->sigaction = sigaction;
|
||||||
|
entry->context = context;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Warn("xiosigchld_register(): table overflow");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* remove a child process to the table
|
||||||
|
returns 0 on success
|
||||||
|
returns 1 if pid was not found in table
|
||||||
|
*/
|
||||||
|
int xiosigchld_unregister(pid_t pid) {
|
||||||
|
struct _xiosigchld_child *entry;
|
||||||
|
|
||||||
|
/* is it already registered? */
|
||||||
|
if (entry = _xiosigchld_find(pid)) {
|
||||||
|
/* found, remove it from table */
|
||||||
|
entry->pid = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clear the child process table */
|
||||||
|
/* especially interesting after fork() in child process
|
||||||
|
returns 0
|
||||||
|
*/
|
||||||
|
int xiosigchld_clearall(void) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < XIO_MAXCHILDPIDS; ++i) {
|
||||||
|
xio_childpids[i].pid = 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xiosigaction_subaddr_ok(int signum, siginfo_t *siginfo, void *ucontext) {
|
||||||
|
pid_t subpid = siginfo->si_pid;
|
||||||
|
struct _xiosigchld_child *entry;
|
||||||
|
xiosingle_t *xfd;
|
||||||
|
|
||||||
|
entry = _xiosigchld_find(subpid);
|
||||||
|
if (entry == NULL) {
|
||||||
|
Warn1("SIGUSR1 from unregistered process "F_pid, subpid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
xfd = entry->context;
|
||||||
|
xfd->subaddrstat = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void xiosigaction_child(int signum, siginfo_t *siginfo, void *ucontext) {
|
||||||
|
pid_t subpid = siginfo->si_pid;
|
||||||
|
xiosingle_t *xfd = ucontext;
|
||||||
|
|
||||||
|
/* the sub process that is connected to this xio address has terminated */
|
||||||
|
Notice2("sub process "F_pid" died, setting in xfd %p", subpid, xfd);
|
||||||
|
xfd->subaddrstat = -1;
|
||||||
|
xfd->subaddrexit = siginfo->si_status;
|
||||||
|
if (xfd->child.sigchild) {
|
||||||
|
(*xfd->child.sigchild)(xfd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
30
xiosigchld.h
Normal file
30
xiosigchld.h
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/* $Id$ */
|
||||||
|
/* Copyright Gerhard Rieger 2006 */
|
||||||
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
|
#ifndef __xiosigchld_h
|
||||||
|
#define __xiosigchld_h 1
|
||||||
|
|
||||||
|
extern pid_t diedunknown1; /* child died before it is registered */
|
||||||
|
extern pid_t diedunknown2;
|
||||||
|
extern pid_t diedunknown3;
|
||||||
|
extern pid_t diedunknown4;
|
||||||
|
|
||||||
|
extern int xiosetsigchild(xiofile_t *xfd, int (*callback)(struct single *));
|
||||||
|
extern void childdied(int signum
|
||||||
|
#if HAVE_SIGACTION
|
||||||
|
, siginfo_t *siginfo, void *context
|
||||||
|
#endif /* HAVE_SIGACTION */
|
||||||
|
);
|
||||||
|
|
||||||
|
extern int
|
||||||
|
xiosigchld_register(pid_t pid,
|
||||||
|
void (*sigaction)(int, siginfo_t *, void *),
|
||||||
|
void *context);
|
||||||
|
extern int xiosigchld_unregister(pid_t pid);
|
||||||
|
extern int xiosigchld_clearall(void);
|
||||||
|
|
||||||
|
extern void xiosigaction_subaddr_ok(int signum, siginfo_t *siginfo, void *ucontext);
|
||||||
|
extern void xiosigaction_child(int signum, siginfo_t *siginfo, void *ucontext);
|
||||||
|
|
||||||
|
#endif /* !defined(__xiosigchld_h) */
|
186
xiosocketpair.c
Normal file
186
xiosocketpair.c
Normal file
|
@ -0,0 +1,186 @@
|
||||||
|
/* $Id$ */
|
||||||
|
/* Copyright Gerhard Rieger 2007 */
|
||||||
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
|
/* this is the source of the internal xiosocketpair function */
|
||||||
|
|
||||||
|
#include "xiosysincludes.h"
|
||||||
|
#include "sycls.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "xio.h"
|
||||||
|
|
||||||
|
#if defined(HAVE_DEV_PTMX)
|
||||||
|
# define PTMX "/dev/ptmx" /* Linux */
|
||||||
|
#elif HAVE_DEV_PTC
|
||||||
|
# define PTMX "/dev/ptc" /* AIX */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MAXPTYNAMELEN 64
|
||||||
|
|
||||||
|
/* how: 0...socketpair; 1...pipes pair; 2...pty (master, slave)
|
||||||
|
how==0: var args (int)domain, (int)type, (int)protocol
|
||||||
|
how==1: no var args
|
||||||
|
how==2: var args (int)useptmx
|
||||||
|
returns -1 on error or 0 on success */
|
||||||
|
|
||||||
|
int xiosocketpair(xiofile_t **xfd1p, xiofile_t **xfd2p, int how, ...) {
|
||||||
|
va_list ap;
|
||||||
|
xiofile_t *xfd1, *xfd2;
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
if ((xfd1 = xioallocfd()) == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ((xfd2 = xioallocfd()) == NULL) {
|
||||||
|
xiofreefd(xfd1);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (how) {
|
||||||
|
case 0: /* socketpair */
|
||||||
|
{
|
||||||
|
int sv[2];
|
||||||
|
int domain, type, protocol;
|
||||||
|
|
||||||
|
va_start(ap, how);
|
||||||
|
domain = va_arg(ap, int);
|
||||||
|
type = va_arg(ap, int);
|
||||||
|
protocol = va_arg(ap, int);
|
||||||
|
va_end(ap);
|
||||||
|
if (Socketpair(domain, type, protocol, sv) < 0) {
|
||||||
|
Error5("socketpair(%d, %d, %d, %p): %s",
|
||||||
|
domain, type, protocol, sv, strerror(errno));
|
||||||
|
xiofreefd(xfd1); xiofreefd(xfd2);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
assert(xfd1->stream.fdtype == FDTYPE_SINGLE);
|
||||||
|
xfd1->stream.fd1 = sv[0];
|
||||||
|
assert(xfd2->stream.fdtype == FDTYPE_SINGLE);
|
||||||
|
xfd2->stream.fd1 = sv[1];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
int filedes1[2], filedes2[2];
|
||||||
|
if (Pipe(filedes1) < 0) {
|
||||||
|
Error2("pipe(%p): %s", filedes1, strerror(errno));
|
||||||
|
xiofreefd(xfd1); xiofreefd(xfd2);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (Pipe(filedes2) < 0) {
|
||||||
|
Error2("pipe(%p): %s", filedes2, strerror(errno));
|
||||||
|
xiofreefd(xfd1); xiofreefd(xfd2);
|
||||||
|
Close(filedes1[0]); Close(filedes1[1]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
xfd1->stream.fd1 = filedes1[0];
|
||||||
|
xfd1->stream.fd2 = filedes2[1];
|
||||||
|
xfd1->stream.fdtype = FDTYPE_DOUBLE;
|
||||||
|
xfd1->stream.dtype = XIODATA_2PIPE;
|
||||||
|
xfd2->stream.fd1 = filedes2[0];
|
||||||
|
xfd2->stream.fd2 = filedes1[1];
|
||||||
|
xfd2->stream.fdtype = FDTYPE_DOUBLE;
|
||||||
|
xfd2->stream.dtype = XIODATA_2PIPE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
#if HAVE_DEV_PTMX || HAVE_DEV_PTC
|
||||||
|
case 2: /* pty (master, slave) */
|
||||||
|
{
|
||||||
|
int useptmx;
|
||||||
|
char ptyname[MAXPTYNAMELEN];
|
||||||
|
int ptyfd = -1, ttyfd;
|
||||||
|
|
||||||
|
va_start(ap, how);
|
||||||
|
useptmx = va_arg(ap, int);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
if (useptmx) {
|
||||||
|
if ((ptyfd = Open(PTMX, O_RDWR|O_NOCTTY, 0620)) < 0) {
|
||||||
|
Warn1("open(\""PTMX"\", O_RDWR|O_NOCTTY, 0620): %s",
|
||||||
|
strerror(errno));
|
||||||
|
/*!*/
|
||||||
|
} else {
|
||||||
|
;/*0 Info1("open(\""PTMX"\", O_RDWR|O_NOCTTY, 0620) -> %d", ptyfd);*/
|
||||||
|
}
|
||||||
|
if (ptyfd >= 0) {
|
||||||
|
char *tn = NULL;
|
||||||
|
|
||||||
|
/* we used PTMX before forking */
|
||||||
|
/*0 extern char *ptsname(int);*/
|
||||||
|
#if HAVE_GRANTPT /* AIX, not Linux */
|
||||||
|
if (Grantpt(ptyfd)/*!*/ < 0) {
|
||||||
|
Warn2("grantpt(%d): %s", ptyfd, strerror(errno));
|
||||||
|
}
|
||||||
|
#endif /* HAVE_GRANTPT */
|
||||||
|
#if HAVE_UNLOCKPT
|
||||||
|
if (Unlockpt(ptyfd)/*!*/ < 0) {
|
||||||
|
Warn2("unlockpt(%d): %s", ptyfd, strerror(errno));
|
||||||
|
}
|
||||||
|
#endif /* HAVE_UNLOCKPT */
|
||||||
|
#if HAVE_PTSNAME /* AIX, not Linux */
|
||||||
|
if ((tn = Ptsname(ptyfd)) == NULL) {
|
||||||
|
Warn2("ptsname(%d): %s", ptyfd, strerror(errno));
|
||||||
|
} else {
|
||||||
|
Notice1("PTY is %s", tn);
|
||||||
|
}
|
||||||
|
#endif /* HAVE_PTSNAME */
|
||||||
|
#if 0
|
||||||
|
if (tn == NULL) {
|
||||||
|
/*! ttyname_r() */
|
||||||
|
if ((tn = Ttyname(ptyfd)) == NULL) {
|
||||||
|
Warn2("ttyname(%d): %s", ptyfd, strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
strncpy(ptyname, tn, MAXPTYNAMELEN);
|
||||||
|
#endif
|
||||||
|
if ((ttyfd = Open(tn, O_RDWR|O_NOCTTY, 0620)) < 0) {
|
||||||
|
Warn2("open(\"%s\", O_RDWR|O_NOCTTY, 0620): %s", tn, strerror(errno));
|
||||||
|
} else {
|
||||||
|
/*0 Info2("open(\"%s\", O_RDWR|O_NOCTTY, 0620) -> %d", tn, ttyfd);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef I_PUSH
|
||||||
|
/* Linux: I_PUSH def'd; pty: ioctl(, I_FIND, ...) -> -1 EINVAL */
|
||||||
|
/* AIX: I_PUSH def'd; pty: ioctl(, I_FIND, ...) -> 1 */
|
||||||
|
/* SunOS: I_PUSH def'd; pty: ioctl(, I_FIND, ...) -> 0 */
|
||||||
|
/* HP-UX: I_PUSH def'd; pty: ioctl(, I_FIND, ...) -> 0 */
|
||||||
|
if (Ioctl(ttyfd, I_FIND, "ldterm") == 0) {
|
||||||
|
Ioctl(ttyfd, I_PUSH, "ptem"); /* 0 */
|
||||||
|
Ioctl(ttyfd, I_PUSH, "ldterm"); /* 0 */
|
||||||
|
Ioctl(ttyfd, I_PUSH, "ttcompat"); /* HP-UX: -1 */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if HAVE_OPENPTY
|
||||||
|
if (ptyfd < 0) {
|
||||||
|
int result;
|
||||||
|
if ((result = Openpty(&ptyfd, &ttyfd, ptyname, NULL, NULL)) < 0) {
|
||||||
|
Error4("openpty(%p, %p, %p, NULL, NULL): %s",
|
||||||
|
&ptyfd, &ttyfd, ptyname, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
Notice1("PTY is %s", ptyname);
|
||||||
|
}
|
||||||
|
#endif /* HAVE_OPENPTY */
|
||||||
|
assert(xfd1->stream.fdtype == FDTYPE_SINGLE);
|
||||||
|
xfd1->stream.fd1 = ttyfd;
|
||||||
|
assert(xfd2->stream.fdtype == FDTYPE_SINGLE);
|
||||||
|
xfd2->stream.fd1 = ptyfd;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#endif /* HAVE_DEV_PTMX || HAVE_DEV_PTC */
|
||||||
|
|
||||||
|
default:
|
||||||
|
Error1("undefined socketpair mechanism %d", how);
|
||||||
|
xiofreefd(xfd1); xiofreefd(xfd2);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
*xfd1p = xfd1;
|
||||||
|
*xfd2p = xfd2;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
11
xiostatic.h
Normal file
11
xiostatic.h
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
/* $Id$ */
|
||||||
|
/* Copyright Gerhard Rieger 2006 */
|
||||||
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
|
/* libxio internal global variables */
|
||||||
|
#ifndef __xiostatic_h
|
||||||
|
#define __xiostatic_h 1
|
||||||
|
|
||||||
|
extern int xio_flags;
|
||||||
|
|
||||||
|
#endif /* !defined(__xiostatic_h) */
|
302
xiotransfer.c
Normal file
302
xiotransfer.c
Normal file
|
@ -0,0 +1,302 @@
|
||||||
|
/* $Id$ */
|
||||||
|
/* Copyright Gerhard Rieger 2007 */
|
||||||
|
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||||
|
|
||||||
|
/* this is the source file of the data transfer function */
|
||||||
|
|
||||||
|
#include "xiosysincludes.h"
|
||||||
|
|
||||||
|
#include "mytypes.h"
|
||||||
|
#include "compat.h"
|
||||||
|
#include "error.h"
|
||||||
|
|
||||||
|
#include "sycls.h"
|
||||||
|
#include "xio.h"
|
||||||
|
|
||||||
|
static
|
||||||
|
int cv_newline(unsigned char **buff, ssize_t *bytes, int lineterm1, int lineterm2);
|
||||||
|
|
||||||
|
|
||||||
|
#define MAXTIMESTAMPLEN 128
|
||||||
|
/* prints the timestamp to the buffer and terminates it with '\0'. This buffer
|
||||||
|
should be at least MAXTIMESTAMPLEN bytes long.
|
||||||
|
returns 0 on success or -1 if an error occurred */
|
||||||
|
int gettimestamp(char *timestamp) {
|
||||||
|
size_t bytes;
|
||||||
|
#if HAVE_GETTIMEOFDAY || 1
|
||||||
|
struct timeval now;
|
||||||
|
int result;
|
||||||
|
time_t nowt;
|
||||||
|
#else /* !HAVE_GETTIMEOFDAY */
|
||||||
|
time_t now;
|
||||||
|
#endif /* !HAVE_GETTIMEOFDAY */
|
||||||
|
|
||||||
|
#if HAVE_GETTIMEOFDAY || 1
|
||||||
|
result = gettimeofday(&now, NULL);
|
||||||
|
if (result < 0) {
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
nowt = now.tv_sec;
|
||||||
|
#if HAVE_STRFTIME
|
||||||
|
bytes = strftime(timestamp, 20, "%Y/%m/%d %H:%M:%S", localtime(&nowt));
|
||||||
|
bytes += sprintf(timestamp+19, "."F_tv_usec" ", now.tv_usec);
|
||||||
|
#else
|
||||||
|
strcpy(timestamp, ctime(&nowt));
|
||||||
|
bytes = strlen(timestamp);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#else /* !HAVE_GETTIMEOFDAY */
|
||||||
|
now = time(NULL); if (now == (time_t)-1) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
#if HAVE_STRFTIME
|
||||||
|
bytes = strftime(timestamp, 21, "%Y/%m/%d %H:%M:%S ", localtime(&now));
|
||||||
|
#else
|
||||||
|
strcpy(timestamp, ctime(&now));
|
||||||
|
bytes = strlen(timestamp);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif /* !HAVE_GETTIMEOFDAY */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const char *prefixltor = "> ";
|
||||||
|
static const char *prefixrtol = "< ";
|
||||||
|
static unsigned long numltor;
|
||||||
|
static unsigned long numrtol;
|
||||||
|
/* print block header (during verbose or hex dump)
|
||||||
|
returns 0 on success or -1 if an error occurred */
|
||||||
|
static int
|
||||||
|
xioprintblockheader(FILE *file, size_t bytes, bool righttoleft) {
|
||||||
|
char timestamp[MAXTIMESTAMPLEN];
|
||||||
|
char buff[128+MAXTIMESTAMPLEN];
|
||||||
|
if (gettimestamp(timestamp) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (righttoleft) {
|
||||||
|
sprintf(buff, "%s%s length="F_Zu" from=%lu to=%lu\n",
|
||||||
|
prefixrtol, timestamp, bytes, numrtol, numrtol+bytes-1);
|
||||||
|
numrtol+=bytes;
|
||||||
|
} else {
|
||||||
|
sprintf(buff, "%s%s length="F_Zu" from=%lu to=%lu\n",
|
||||||
|
prefixltor, timestamp, bytes, numltor, numltor+bytes-1);
|
||||||
|
numltor+=bytes;
|
||||||
|
}
|
||||||
|
fputs(buff, file);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* inpipe is suspected to have read data available; read at most bufsiz bytes
|
||||||
|
and transfer them to outpipe. Perform required data conversions.
|
||||||
|
buff should be at least twice as large as bufsiz, to allow all standard
|
||||||
|
conversions. Returns the number of bytes written, or 0 on EOF or <0 if an
|
||||||
|
error occurred or when data was read but none written due to conversions
|
||||||
|
(with EAGAIN). EAGAIN also occurs when reading from a nonblocking FD where
|
||||||
|
the file has a mandatory lock.
|
||||||
|
If 0 bytes were read (EOF), it does NOT shutdown or close a channel, and it
|
||||||
|
does NOT write a zero bytes block.
|
||||||
|
*/
|
||||||
|
/* inpipe, outpipe must be single descriptors (not dual!) */
|
||||||
|
int xiotransfer(xiofile_t *inpipe, xiofile_t *outpipe,
|
||||||
|
unsigned char **buff, size_t bufsiz, bool righttoleft) {
|
||||||
|
ssize_t bytes, writt;
|
||||||
|
|
||||||
|
bytes = xioread(inpipe, *buff, bufsiz);
|
||||||
|
if (bytes < 0) {
|
||||||
|
if (errno != EAGAIN)
|
||||||
|
XIO_RDSTREAM(inpipe)->eof = 2;
|
||||||
|
/*xioshutdown(inpipe, SHUT_RD);*/
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (bytes == 0) {
|
||||||
|
writt = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
else /* if (bytes > 0)*/ {
|
||||||
|
|
||||||
|
if (XIO_RDSTREAM(inpipe)->lineterm !=
|
||||||
|
XIO_WRSTREAM(outpipe)->lineterm) {
|
||||||
|
cv_newline(buff, &bytes,
|
||||||
|
XIO_RDSTREAM(inpipe)->lineterm,
|
||||||
|
XIO_WRSTREAM(outpipe)->lineterm);
|
||||||
|
}
|
||||||
|
if (bytes == 0) {
|
||||||
|
errno = EAGAIN; return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xioparams->verbose && xioparams->verbhex) {
|
||||||
|
/* Hack-o-rama */
|
||||||
|
size_t i = 0;
|
||||||
|
size_t j;
|
||||||
|
size_t N = 16;
|
||||||
|
const unsigned char *end, *s, *t;
|
||||||
|
s = *buff;
|
||||||
|
end = (*buff)+bytes;
|
||||||
|
xioprintblockheader(stderr, bytes, righttoleft);
|
||||||
|
while (s < end) {
|
||||||
|
/*! prefix? */
|
||||||
|
j = Min(N, (size_t)(end-s));
|
||||||
|
|
||||||
|
/* print hex */
|
||||||
|
t = s;
|
||||||
|
i = 0;
|
||||||
|
while (i < j) {
|
||||||
|
int c = *t++;
|
||||||
|
fprintf(stderr, " %02x", c);
|
||||||
|
++i;
|
||||||
|
if (c == '\n') break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fill hex column */
|
||||||
|
while (i < N) {
|
||||||
|
fputs(" ", stderr);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
fputs(" ", stderr);
|
||||||
|
|
||||||
|
/* print acsii */
|
||||||
|
t = s;
|
||||||
|
i = 0;
|
||||||
|
while (i < j) {
|
||||||
|
int c = *t++;
|
||||||
|
if (c == '\n') {
|
||||||
|
fputc('.', stderr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!isprint(c))
|
||||||
|
c = '.';
|
||||||
|
fputc(c, stderr);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
fputc('\n', stderr);
|
||||||
|
s = t;
|
||||||
|
}
|
||||||
|
fputs("--\n", stderr);
|
||||||
|
} else if (xioparams->verbose) {
|
||||||
|
size_t i = 0;
|
||||||
|
xioprintblockheader(stderr, bytes, righttoleft);
|
||||||
|
while (i < (size_t)bytes) {
|
||||||
|
int c = (*buff)[i];
|
||||||
|
if (i > 0 && (*buff)[i-1] == '\n')
|
||||||
|
/*! prefix? */;
|
||||||
|
switch (c) {
|
||||||
|
case '\a' : fputs("\\a", stderr); break;
|
||||||
|
case '\b' : fputs("\\b", stderr); break;
|
||||||
|
case '\t' : fputs("\t", stderr); break;
|
||||||
|
case '\n' : fputs("\n", stderr); break;
|
||||||
|
case '\v' : fputs("\\v", stderr); break;
|
||||||
|
case '\f' : fputs("\\f", stderr); break;
|
||||||
|
case '\r' : fputs("\\r", stderr); break;
|
||||||
|
case '\\' : fputs("\\\\", stderr); break;
|
||||||
|
default:
|
||||||
|
if (!isprint(c))
|
||||||
|
c = '.';
|
||||||
|
fputc(c, stderr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
} else if (xioparams->verbhex) {
|
||||||
|
int i;
|
||||||
|
/*! prefix? */
|
||||||
|
for (i = 0; i < bytes; ++i) {
|
||||||
|
fprintf(stderr, " %02x", (*buff)[i]);
|
||||||
|
}
|
||||||
|
fputc('\n', stderr);
|
||||||
|
}
|
||||||
|
|
||||||
|
writt = xiowrite(outpipe, *buff, bytes);
|
||||||
|
if (writt < 0) {
|
||||||
|
/* EAGAIN when nonblocking but a mandatory lock is on file.
|
||||||
|
the problem with EAGAIN is that the read cannot be repeated,
|
||||||
|
so we need to buffer the data and try to write it later
|
||||||
|
again. not yet implemented, sorry. */
|
||||||
|
#if 0
|
||||||
|
if (errno == EPIPE) {
|
||||||
|
return 0; /* can no longer write; handle like EOF */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
Info3("transferred "F_Zu" bytes from %d to %d",
|
||||||
|
writt, XIO_GETRDFD(inpipe), XIO_GETWRFD(outpipe));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return writt;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CR '\r'
|
||||||
|
#define LF '\n'
|
||||||
|
|
||||||
|
|
||||||
|
static int cv_newline(unsigned char **buff, ssize_t *bytes,
|
||||||
|
int lineterm1, int lineterm2) {
|
||||||
|
/* must perform newline changes */
|
||||||
|
if (lineterm1 <= LINETERM_CR && lineterm2 <= LINETERM_CR) {
|
||||||
|
/* no change in data length */
|
||||||
|
unsigned char from, to, *p, *z;
|
||||||
|
if (lineterm1 == LINETERM_RAW) {
|
||||||
|
from = '\n'; to = '\r';
|
||||||
|
} else {
|
||||||
|
from = '\r'; to = '\n';
|
||||||
|
}
|
||||||
|
z = *buff + *bytes;
|
||||||
|
p = *buff;
|
||||||
|
while (p < z) {
|
||||||
|
if (*p == from) *p = to;
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (lineterm1 == LINETERM_CRNL) {
|
||||||
|
/* buffer becomes shorter */
|
||||||
|
unsigned char to, *s, *t, *z;
|
||||||
|
if (lineterm2 == LINETERM_RAW) {
|
||||||
|
to = '\n';
|
||||||
|
} else {
|
||||||
|
to = '\r';
|
||||||
|
}
|
||||||
|
z = *buff + *bytes;
|
||||||
|
s = t = *buff;
|
||||||
|
while (s < z) {
|
||||||
|
if (*s == '\r') {
|
||||||
|
++s;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (*s == '\n') {
|
||||||
|
*t++ = to; ++s;
|
||||||
|
} else {
|
||||||
|
*t++ = *s++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*bytes = t - *buff;
|
||||||
|
} else {
|
||||||
|
/* buffer becomes longer, must alloc another space */
|
||||||
|
unsigned char *buf2;
|
||||||
|
unsigned char from; unsigned char *s, *t, *z;
|
||||||
|
if (lineterm1 == LINETERM_RAW) {
|
||||||
|
from = '\n';
|
||||||
|
} else {
|
||||||
|
from = '\r';
|
||||||
|
}
|
||||||
|
if ((buf2 = Malloc(2*xioparams->bufsiz + 1)) == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
s = *buff; t = buf2; z = *buff + *bytes;
|
||||||
|
while (s < z) {
|
||||||
|
if (*s == from) {
|
||||||
|
*t++ = '\r'; *t++ = '\n';
|
||||||
|
++s;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
*t++ = *s++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
free(*buff);
|
||||||
|
*buff = buf2;
|
||||||
|
*bytes = t - buf2;;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
47
xiowrite.c
47
xiowrite.c
|
@ -8,6 +8,7 @@
|
||||||
#include "xiosysincludes.h"
|
#include "xiosysincludes.h"
|
||||||
#include "xioopen.h"
|
#include "xioopen.h"
|
||||||
|
|
||||||
|
#include "xio-test.h"
|
||||||
#include "xio-readline.h"
|
#include "xio-readline.h"
|
||||||
#include "xio-openssl.h"
|
#include "xio-openssl.h"
|
||||||
|
|
||||||
|
@ -20,6 +21,7 @@
|
||||||
ssize_t xiowrite(xiofile_t *file, const void *buff, size_t bytes) {
|
ssize_t xiowrite(xiofile_t *file, const void *buff, size_t bytes) {
|
||||||
ssize_t writt;
|
ssize_t writt;
|
||||||
struct single *pipe;
|
struct single *pipe;
|
||||||
|
int fd;
|
||||||
int _errno;
|
int _errno;
|
||||||
|
|
||||||
if (file->tag == XIO_TAG_INVALID) {
|
if (file->tag == XIO_TAG_INVALID) {
|
||||||
|
@ -46,11 +48,13 @@ ssize_t xiowrite(xiofile_t *file, const void *buff, size_t bytes) {
|
||||||
}
|
}
|
||||||
#endif /* WITH_READLINE */
|
#endif /* WITH_READLINE */
|
||||||
|
|
||||||
|
fd = XIO_GETWRFD(file);
|
||||||
|
|
||||||
switch (pipe->dtype & XIODATA_WRITEMASK) {
|
switch (pipe->dtype & XIODATA_WRITEMASK) {
|
||||||
|
|
||||||
case XIOWRITE_STREAM:
|
case XIOWRITE_STREAM:
|
||||||
do {
|
do {
|
||||||
writt = Write(pipe->fd, buff, bytes);
|
writt = Write(fd, buff, bytes);
|
||||||
} while (writt < 0 && errno == EINTR);
|
} while (writt < 0 && errno == EINTR);
|
||||||
if (writt < 0) {
|
if (writt < 0) {
|
||||||
_errno = errno;
|
_errno = errno;
|
||||||
|
@ -59,13 +63,13 @@ ssize_t xiowrite(xiofile_t *file, const void *buff, size_t bytes) {
|
||||||
case ECONNRESET:
|
case ECONNRESET:
|
||||||
if (pipe->cool_write) {
|
if (pipe->cool_write) {
|
||||||
Notice4("write(%d, %p, "F_Zu"): %s",
|
Notice4("write(%d, %p, "F_Zu"): %s",
|
||||||
pipe->fd, buff, bytes, strerror(_errno));
|
fd, buff, bytes, strerror(_errno));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/*PASSTRHOUGH*/
|
/*PASSTRHOUGH*/
|
||||||
default:
|
default:
|
||||||
Error4("write(%d, %p, "F_Zu"): %s",
|
Error4("write(%d, %p, "F_Zu"): %s",
|
||||||
pipe->fd, buff, bytes, strerror(_errno));
|
fd, buff, bytes, strerror(_errno));
|
||||||
}
|
}
|
||||||
errno = _errno;
|
errno = _errno;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -85,14 +89,14 @@ ssize_t xiowrite(xiofile_t *file, const void *buff, size_t bytes) {
|
||||||
/*socklen_t fromlen;*/
|
/*socklen_t fromlen;*/
|
||||||
|
|
||||||
do {
|
do {
|
||||||
writt = Sendto(pipe->fd, buff, bytes, 0,
|
writt = Sendto(fd, buff, bytes, 0,
|
||||||
&pipe->peersa.soa, pipe->salen);
|
&pipe->peersa.soa, pipe->salen);
|
||||||
} while (writt < 0 && errno == EINTR);
|
} while (writt < 0 && errno == EINTR);
|
||||||
if (writt < 0) {
|
if (writt < 0) {
|
||||||
char infobuff[256];
|
char infobuff[256];
|
||||||
_errno = errno;
|
_errno = errno;
|
||||||
Error6("sendto(%d, %p, "F_Zu", 0, %s, "F_socklen"): %s",
|
Error6("sendto(%d, %p, "F_Zu", 0, %s, "F_socklen"): %s",
|
||||||
pipe->fd, buff, bytes,
|
fd, buff, bytes,
|
||||||
sockaddr_info(&pipe->peersa.soa, pipe->salen,
|
sockaddr_info(&pipe->peersa.soa, pipe->salen,
|
||||||
infobuff, sizeof(infobuff)),
|
infobuff, sizeof(infobuff)),
|
||||||
pipe->salen, strerror(_errno));
|
pipe->salen, strerror(_errno));
|
||||||
|
@ -102,7 +106,7 @@ ssize_t xiowrite(xiofile_t *file, const void *buff, size_t bytes) {
|
||||||
if ((size_t)writt < bytes) {
|
if ((size_t)writt < bytes) {
|
||||||
char infobuff[256];
|
char infobuff[256];
|
||||||
Warn7("sendto(%d, %p, "F_Zu", 0, %s, "F_socklen") only wrote "F_Zu" of "F_Zu" bytes",
|
Warn7("sendto(%d, %p, "F_Zu", 0, %s, "F_socklen") only wrote "F_Zu" of "F_Zu" bytes",
|
||||||
pipe->fd, buff, bytes,
|
fd, buff, bytes,
|
||||||
sockaddr_info(&pipe->peersa.soa, pipe->salen,
|
sockaddr_info(&pipe->peersa.soa, pipe->salen,
|
||||||
infobuff, sizeof(infobuff)),
|
infobuff, sizeof(infobuff)),
|
||||||
pipe->salen, writt, bytes);
|
pipe->salen, writt, bytes);
|
||||||
|
@ -112,7 +116,7 @@ ssize_t xiowrite(xiofile_t *file, const void *buff, size_t bytes) {
|
||||||
char infobuff[256];
|
char infobuff[256];
|
||||||
union sockaddr_union us;
|
union sockaddr_union us;
|
||||||
socklen_t uslen = sizeof(us);
|
socklen_t uslen = sizeof(us);
|
||||||
Getsockname(pipe->fd, &us.soa, &uslen);
|
Getsockname(fd, &us.soa, &uslen);
|
||||||
Notice1("local address: %s",
|
Notice1("local address: %s",
|
||||||
sockaddr_info(&us.soa, uslen, infobuff, sizeof(infobuff)));
|
sockaddr_info(&us.soa, uslen, infobuff, sizeof(infobuff)));
|
||||||
}
|
}
|
||||||
|
@ -120,13 +124,14 @@ ssize_t xiowrite(xiofile_t *file, const void *buff, size_t bytes) {
|
||||||
#endif /* WITH_SOCKET */
|
#endif /* WITH_SOCKET */
|
||||||
|
|
||||||
case XIOWRITE_PIPE:
|
case XIOWRITE_PIPE:
|
||||||
|
case XIOWRITE_2PIPE:
|
||||||
do {
|
do {
|
||||||
writt = Write(pipe->para.bipipe.fdout, buff, bytes);
|
writt = Write(fd, buff, bytes);
|
||||||
} while (writt < 0 && errno == EINTR);
|
} while (writt < 0 && errno == EINTR);
|
||||||
_errno = errno;
|
_errno = errno;
|
||||||
if (writt < 0) {
|
if (writt < 0) {
|
||||||
Error4("write(%d, %p, "F_Zu"): %s",
|
Error4("write(%d, %p, "F_Zu"): %s",
|
||||||
pipe->para.bipipe.fdout, buff, bytes, strerror(_errno));
|
fd, buff, bytes, strerror(_errno));
|
||||||
errno = _errno;
|
errno = _errno;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -136,22 +141,14 @@ ssize_t xiowrite(xiofile_t *file, const void *buff, size_t bytes) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XIOWRITE_2PIPE:
|
#if WITH_TEST
|
||||||
do {
|
case XIOWRITE_TEST:
|
||||||
writt = Write(pipe->para.exec.fdout, buff, bytes);
|
/* this function prints its own error messages */
|
||||||
} while (writt < 0 && errno == EINTR);
|
return xiowrite_test(pipe, buff, bytes);
|
||||||
_errno = errno;
|
case XIOWRITE_TESTREV:
|
||||||
if (writt < 0) {
|
/* this function prints its own error messages */
|
||||||
Error4("write(%d, %p, "F_Zu"): %s",
|
return xiowrite_testrev(pipe, buff, bytes);
|
||||||
pipe->para.exec.fdout, buff, bytes, strerror(_errno));
|
#endif /* WITH_TEST */
|
||||||
errno = _errno;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if ((size_t)writt < bytes) {
|
|
||||||
Warn2("write() only processed "F_Zu" of "F_Zu" bytes",
|
|
||||||
writt, bytes);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
#if WITH_OPENSSL
|
#if WITH_OPENSSL
|
||||||
case XIOWRITE_OPENSSL:
|
case XIOWRITE_OPENSSL:
|
||||||
|
|
Loading…
Reference in a new issue